diff -Nurp linux-2.6.22.19-vs2.3.0.34/drivers/net/bonding/bond_main.c linux-2.6.22.19-vs2.3.0.34.bond1/drivers/net/bonding/bond_main.c --- linux-2.6.22.19-vs2.3.0.34/drivers/net/bonding/bond_main.c 2007-09-05 07:07:59.000000000 +0200 +++ linux-2.6.22.19-vs2.3.0.34.bond1/drivers/net/bonding/bond_main.c 2009-06-23 00:51:24.000000000 +0200 @@ -123,7 +123,7 @@ MODULE_PARM_DESC(lacp_rate, "LACPDU tx r "(slow/fast)"); module_param(xmit_hash_policy, charp, 0); MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)" - ", 1 for layer 3+4"); + ", 1 for layer 3+4, 2 for layer2+3"); module_param(arp_interval, int, 0); MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); module_param_array(arp_ip_target, charp, NULL, 0); @@ -170,6 +170,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}, }; @@ -3447,6 +3448,24 @@ void bond_unregister_arp(struct bonding } /*---------------------------- 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 @@ -4183,6 +4202,8 @@ void bond_set_mode_ops(struct bonding *b 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 if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER23) + bond->xmit_hash_policy = bond_xmit_hash_policy_l23; else bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; @@ -4194,6 +4215,8 @@ void bond_set_mode_ops(struct bonding *b 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 if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER23) + bond->xmit_hash_policy = bond_xmit_hash_policy_l23; else bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; diff -Nurp linux-2.6.22.19-vs2.3.0.34/include/linux/if_bonding.h linux-2.6.22.19-vs2.3.0.34.bond1/include/linux/if_bonding.h --- linux-2.6.22.19-vs2.3.0.34/include/linux/if_bonding.h 2006-06-18 03:49:35.000000000 +0200 +++ linux-2.6.22.19-vs2.3.0.34.bond1/include/linux/if_bonding.h 2009-06-23 00:49:47.000000000 +0200 @@ -86,6 +86,7 @@ /* hashing types */ #define BOND_XMIT_POLICY_LAYER2 0 /* layer 2 (MAC only), default */ #define BOND_XMIT_POLICY_LAYER34 1 /* layer 3+4 (IP ^ MAC) */ +#define BOND_XMIT_POLICY_LAYER23 2 /* layer 2+3 (IP ^ MAC) */ typedef struct ifbond { __s32 bond_mode;