]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.fixes/fix-balance-alb-bonding-receive
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / fix-balance-alb-bonding-receive
CommitLineData
82094b55
AF
1From: Jiri Pirko <jpirko@redhat.com>
2Date: Thu, 28 May 2009 01:05:00 +0000 (+0000)
3Subject: bonding: allow bond in mode balance-alb to work properly in bridge -try4.3
4Patch-mainline: v2.6.31-rc1
5Git-commit: 5d4e039b2cb1ca4de9774344ea7b61ad7fa1b0a1
6References: bnc#532443
7
8bonding: allow bond in mode balance-alb to work properly in bridge -try4.3
9
10[PATCH net-next] bonding: allow bond in mode balance-alb to work properly in bridge -try4.3
11
12(updated)
13changes v4.2 -> v4.3
14- memcpy the address always, not just in case it differs from master->dev_addr
15- compare_ether_addr_64bits() is not used so there is no direct need to make new
16 header file (I think it would be good to have bond stuff in separate file
17 anyway).
18
19changes v4.1 -> v4.2
20- use skb->pkt_type == PACKET_HOST compare rather then comparing skb dest addr
21 against skb->dev->dev_addr
22
23The problem is described in following bugzilla:
24https://bugzilla.redhat.com/show_bug.cgi?id=487763
25
26Basically here's what's going on. In every mode, bonding interface uses the same
27mac address for all enslaved devices (except fail_over_mac). Only balance-alb
28will simultaneously use multiple MAC addresses across different slaves. When you
29put this kind of bond device into a bridge it will only add one of mac adresses
30into a hash list of mac addresses, say X. This mac address is marked as local.
31But this bonding interface also has mac address Y. Now then packet arrives with
32destination address Y, this address is not marked as local and the packed looks
33like it needs to be forwarded. This packet is then lost which is wrong.
34
35Notice that interfaces can be added and removed from bond while it is in bridge.
36
37
38When the multiple addresses for bridge port approach failed to solve this issue
39due to STP I started to think other way to solve this. I returned to previous
40solution but tweaked one.
41
42This patch solves the situation in the bonding without touching bridge code.
43For every incoming frame to bonding the destination address is compared to
44current address of the slave device from which tha packet came. If these two
45match destination address is replaced by mac address of the master. This address
46is known by bridge so it is delivered properly. Note that the comparsion is not
47made directly, it's used skb->pkt_type == PACKET_HOST instead. This is "set"
48previously in eth_type_trans().
49
50I experimentally tried that this works as good as searching through the slave
51list (v4 of this patch).
52
53Jirka
54
55Signed-off-by: Jiri Pirko <jpirko@redhat.com>
56Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
57Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
58Signed-off-by: David S. Miller <davem@davemloft.net>
59Acked-by: Jeff Mahoney <jeffm@suse.com>
60---
61 include/linux/netdevice.h | 18 ++++++++++++++++++
62 1 file changed, 18 insertions(+)
63
64--- a/include/linux/netdevice.h
65+++ b/include/linux/netdevice.h
66@@ -1705,6 +1705,16 @@ static inline void netif_set_gso_max_siz
67 dev->gso_max_size = size;
68 }
69
70+static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
71+ struct net_device *master)
72+{
73+ if (skb->pkt_type == PACKET_HOST) {
74+ u16 *dest = (u16 *) eth_hdr(skb)->h_dest;
75+
76+ memcpy(dest, master->dev_addr, ETH_ALEN);
77+ }
78+}
79+
80 /* On bonding slaves other than the currently active slave, suppress
81 * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
82 * ARP on active-backup slaves with arp_validate enabled.
83@@ -1718,6 +1728,14 @@ static inline int skb_bond_should_drop(s
84 if (master->priv_flags & IFF_MASTER_ARPMON)
85 dev->last_rx = jiffies;
86
87+ if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
88+ /* Do address unmangle. The local destination address
89+ * will be always the one master has. Provides the right
90+ * functionality in a bridge.
91+ */
92+ skb_bond_set_mac_by_master(skb, master);
93+ }
94+
95 if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
96 if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
97 skb->protocol == __constant_htons(ETH_P_ARP))