summaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r--drivers/net/bonding/bond_main.c48
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index e4a4714..08879d5 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;
}
}
OpenPOWER on IntegriCloud