diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e4a47149735..08879d552ae 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -175,6 +175,7 @@ struct bond_parm_tbl bond_mode_tbl[] = { struct bond_parm_tbl xmit_hashtype_tbl[] = { { "layer2", BOND_XMIT_POLICY_LAYER2}, { "layer3+4", BOND_XMIT_POLICY_LAYER34}, +{ "layer2+3", BOND_XMIT_POLICY_LAYER23}, { NULL, -1}, }; @@ -3605,6 +3606,24 @@ void bond_unregister_arp(struct bonding *bond) /*---------------------------- Hashing Policies -----------------------------*/ /* + * Hash for the output device based upon layer 2 and layer 3 data. If + * the packet is not IP mimic bond_xmit_hash_policy_l2() + */ +static int bond_xmit_hash_policy_l23(struct sk_buff *skb, + struct net_device *bond_dev, int count) +{ + struct ethhdr *data = (struct ethhdr *)skb->data; + struct iphdr *iph = ip_hdr(skb); + + if (skb->protocol == __constant_htons(ETH_P_IP)) { + return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^ + (data->h_dest[5] ^ bond_dev->dev_addr[5])) % count; + } + + return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; +} + +/* * Hash for the output device based upon layer 3 and layer 4 data. If * the packet is a frag or not TCP or UDP, just use layer 3 data. If it is * altogether not IP, mimic bond_xmit_hash_policy_l2() @@ -4306,6 +4325,22 @@ out: /*------------------------- Device initialization ---------------------------*/ +static void bond_set_xmit_hash_policy(struct bonding *bond) +{ + switch (bond->params.xmit_policy) { + case BOND_XMIT_POLICY_LAYER23: + bond->xmit_hash_policy = bond_xmit_hash_policy_l23; + break; + case BOND_XMIT_POLICY_LAYER34: + bond->xmit_hash_policy = bond_xmit_hash_policy_l34; + break; + case BOND_XMIT_POLICY_LAYER2: + default: + bond->xmit_hash_policy = bond_xmit_hash_policy_l2; + break; + } +} + /* * set bond mode specific net device operations */ @@ -4322,10 +4357,7 @@ void bond_set_mode_ops(struct bonding *bond, int mode) break; case BOND_MODE_XOR: bond_dev->hard_start_xmit = bond_xmit_xor; - if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) - bond->xmit_hash_policy = bond_xmit_hash_policy_l34; - else - bond->xmit_hash_policy = bond_xmit_hash_policy_l2; + bond_set_xmit_hash_policy(bond); break; case BOND_MODE_BROADCAST: bond_dev->hard_start_xmit = bond_xmit_broadcast; @@ -4333,10 +4365,7 @@ void bond_set_mode_ops(struct bonding *bond, int mode) case BOND_MODE_8023AD: bond_set_master_3ad_flags(bond); bond_dev->hard_start_xmit = bond_3ad_xmit_xor; - if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) - bond->xmit_hash_policy = bond_xmit_hash_policy_l34; - else - bond->xmit_hash_policy = bond_xmit_hash_policy_l2; + bond_set_xmit_hash_policy(bond); break; case BOND_MODE_ALB: bond_set_master_alb_flags(bond); @@ -4498,8 +4527,7 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) for (i = 0; tbl[i].modename; i++) { if ((isdigit(*mode_arg) && tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) || - (strncmp(mode_arg, tbl[i].modename, - strlen(tbl[i].modename)) == 0)) { + (strcmp(mode_arg, tbl[i].modename) == 0)) { return tbl[i].mode; } } |