From e3b7329c02763155a1b6617cc75c664b26a09cd7 Mon Sep 17 00:00:00 2001
From: Daniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Date: Mon, 15 Jun 2009 19:41:07 +0000
Subject: [PATCH] Add more hashes to the bonding driver.

---
 kernel-2.6.spec                    |  2 +
 linux-2.6-720-bonding-hashes.patch | 96 ++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+)
 create mode 100644 linux-2.6-720-bonding-hashes.patch

diff --git a/kernel-2.6.spec b/kernel-2.6.spec
index cf0754417..64f04b1d1 100644
--- a/kernel-2.6.spec
+++ b/kernel-2.6.spec
@@ -191,6 +191,7 @@ Patch680: linux-2.6-680-htb-hysteresis-tso.patch
 Patch690: linux-2.6-690-web100.patch
 Patch700: linux-2.6-700-fperm.patch
 Patch710: linux-2.6-710-avoid-64bits-addr-pcmcia.patch
+Patch720: linux-2.6-720-bonding-hashes.patch
 
 # See also the file named 'sources' here for the related checksums
 # NOTE. iwlwifi should be in-kernel starting from 2.6.24
@@ -411,6 +412,7 @@ KERNEL_PREVIOUS=vanilla
 %ApplyPatch 690
 %ApplyPatch 700
 %ApplyPatch 710
+%ApplyPatch 720
 
 
 # NetNS conflict-resolving patch for VINI. Will work with patch vini_pl_patch-1 but may
diff --git a/linux-2.6-720-bonding-hashes.patch b/linux-2.6-720-bonding-hashes.patch
new file mode 100644
index 000000000..5a0be1d75
--- /dev/null
+++ b/linux-2.6-720-bonding-hashes.patch
@@ -0,0 +1,96 @@
+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.bonding/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.bonding/drivers/net/bonding/bond_main.c	2009-06-15 19:26:31.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, 3 for layer3");
+ 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,8 @@ 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},
++{	"layer3",		BOND_XMIT_POLICY_LAYER3},
+ {	NULL,			-1},
+ };
+ 
+@@ -3447,6 +3449,40 @@ void bond_unregister_arp(struct bonding 
+ }
+ 
+ /*---------------------------- Hashing Policies -----------------------------*/
++ 
++/*
++ * Hash for the output device based upon layer 3 data. If the packet
++ * is not IP mimic bond_xmit_hash_policy_l2()
++ */
++static int bond_xmit_hash_policy_l3(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) % count;
++	else
++		return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
++}
++
++/*
++ * 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 +4219,10 @@ 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_policty_l23;
++		else if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER3)
++			bond->xmit_hash_policy = bond_xmit_hash_policy_l3;
+ 		else
+ 			bond->xmit_hash_policy = bond_xmit_hash_policy_l2;
+ 		break;
+@@ -4194,6 +4234,10 @@ 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_policty_l23;
++		else if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER3)
++			bond->xmit_hash_policy = bond_xmit_hash_policy_l3;
+ 		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.bonding/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.bonding/include/linux/if_bonding.h	2009-06-15 19:29:16.000000000 +0200
+@@ -86,6 +86,8 @@
+ /* 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) */
++#define BOND_XMIT_POLICY_LAYER3		3 /* layer3 (IP only) */
+ 
+ typedef struct ifbond {
+ 	__s32 bond_mode;
-- 
2.47.0