]>
Commit | Line | Data |
---|---|---|
82094b55 AF |
1 | From: Jiri Pirko <jpirko@redhat.com> |
2 | Date: Thu, 28 May 2009 01:05:00 +0000 (+0000) | |
3 | Subject: bonding: allow bond in mode balance-alb to work properly in bridge -try4.3 | |
4 | Patch-mainline: v2.6.31-rc1 | |
5 | Git-commit: 5d4e039b2cb1ca4de9774344ea7b61ad7fa1b0a1 | |
6 | References: bnc#532443 | |
7 | ||
8 | bonding: 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) | |
13 | changes 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 | ||
19 | changes 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 | ||
23 | The problem is described in following bugzilla: | |
24 | https://bugzilla.redhat.com/show_bug.cgi?id=487763 | |
25 | ||
26 | Basically here's what's going on. In every mode, bonding interface uses the same | |
27 | mac address for all enslaved devices (except fail_over_mac). Only balance-alb | |
28 | will simultaneously use multiple MAC addresses across different slaves. When you | |
29 | put this kind of bond device into a bridge it will only add one of mac adresses | |
30 | into a hash list of mac addresses, say X. This mac address is marked as local. | |
31 | But this bonding interface also has mac address Y. Now then packet arrives with | |
32 | destination address Y, this address is not marked as local and the packed looks | |
33 | like it needs to be forwarded. This packet is then lost which is wrong. | |
34 | ||
35 | Notice that interfaces can be added and removed from bond while it is in bridge. | |
36 | ||
37 | ||
38 | When the multiple addresses for bridge port approach failed to solve this issue | |
39 | due to STP I started to think other way to solve this. I returned to previous | |
40 | solution but tweaked one. | |
41 | ||
42 | This patch solves the situation in the bonding without touching bridge code. | |
43 | For every incoming frame to bonding the destination address is compared to | |
44 | current address of the slave device from which tha packet came. If these two | |
45 | match destination address is replaced by mac address of the master. This address | |
46 | is known by bridge so it is delivered properly. Note that the comparsion is not | |
47 | made directly, it's used skb->pkt_type == PACKET_HOST instead. This is "set" | |
48 | previously in eth_type_trans(). | |
49 | ||
50 | I experimentally tried that this works as good as searching through the slave | |
51 | list (v4 of this patch). | |
52 | ||
53 | Jirka | |
54 | ||
55 | Signed-off-by: Jiri Pirko <jpirko@redhat.com> | |
56 | Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> | |
57 | Signed-off-by: Andy Gospodarek <andy@greyhouse.net> | |
58 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
59 | Acked-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)) |