aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/netdevice.h
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2009-05-27 21:05:00 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-29 04:51:23 -0400
commit5d4e039b2cb1ca4de9774344ea7b61ad7fa1b0a1 (patch)
tree8db8402dab8a3cffbf67fb846e35c45beb3d31a0 /include/linux/netdevice.h
parent4d5ef9f0f588045d5e53e51816bd619d82385676 (diff)
bonding: allow bond in mode balance-alb to work properly in bridge -try4.3
[PATCH net-next] bonding: allow bond in mode balance-alb to work properly in bridge -try4.3 (updated) changes v4.2 -> v4.3 - memcpy the address always, not just in case it differs from master->dev_addr - compare_ether_addr_64bits() is not used so there is no direct need to make new header file (I think it would be good to have bond stuff in separate file anyway). changes v4.1 -> v4.2 - use skb->pkt_type == PACKET_HOST compare rather then comparing skb dest addr against skb->dev->dev_addr The problem is described in following bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=487763 Basically here's what's going on. In every mode, bonding interface uses the same mac address for all enslaved devices (except fail_over_mac). Only balance-alb will simultaneously use multiple MAC addresses across different slaves. When you put this kind of bond device into a bridge it will only add one of mac adresses into a hash list of mac addresses, say X. This mac address is marked as local. But this bonding interface also has mac address Y. Now then packet arrives with destination address Y, this address is not marked as local and the packed looks like it needs to be forwarded. This packet is then lost which is wrong. Notice that interfaces can be added and removed from bond while it is in bridge. *** When the multiple addresses for bridge port approach failed to solve this issue due to STP I started to think other way to solve this. I returned to previous solution but tweaked one. This patch solves the situation in the bonding without touching bridge code. For every incoming frame to bonding the destination address is compared to current address of the slave device from which tha packet came. If these two match destination address is replaced by mac address of the master. This address is known by bridge so it is delivered properly. Note that the comparsion is not made directly, it's used skb->pkt_type == PACKET_HOST instead. This is "set" previously in eth_type_trans(). I experimentally tried that this works as good as searching through the slave list (v4 of this patch). Jirka Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/netdevice.h')
-rw-r--r--include/linux/netdevice.h18
1 files changed, 18 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 8e03b06e638e..1eaf5ae14fea 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1917,6 +1917,16 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
1917 dev->gso_max_size = size; 1917 dev->gso_max_size = size;
1918} 1918}
1919 1919
1920static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
1921 struct net_device *master)
1922{
1923 if (skb->pkt_type == PACKET_HOST) {
1924 u16 *dest = (u16 *) eth_hdr(skb)->h_dest;
1925
1926 memcpy(dest, master->dev_addr, ETH_ALEN);
1927 }
1928}
1929
1920/* On bonding slaves other than the currently active slave, suppress 1930/* On bonding slaves other than the currently active slave, suppress
1921 * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and 1931 * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
1922 * ARP on active-backup slaves with arp_validate enabled. 1932 * ARP on active-backup slaves with arp_validate enabled.
@@ -1930,6 +1940,14 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)
1930 if (master->priv_flags & IFF_MASTER_ARPMON) 1940 if (master->priv_flags & IFF_MASTER_ARPMON)
1931 dev->last_rx = jiffies; 1941 dev->last_rx = jiffies;
1932 1942
1943 if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
1944 /* Do address unmangle. The local destination address
1945 * will be always the one master has. Provides the right
1946 * functionality in a bridge.
1947 */
1948 skb_bond_set_mac_by_master(skb, master);
1949 }
1950
1933 if (dev->priv_flags & IFF_SLAVE_INACTIVE) { 1951 if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
1934 if ((dev->priv_flags & IFF_SLAVE_NEEDARP) && 1952 if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
1935 skb->protocol == __cpu_to_be16(ETH_P_ARP)) 1953 skb->protocol == __cpu_to_be16(ETH_P_ARP))