Jiri Pirko a écrit : > (resend) > > Hi all. > > 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 for mode balance-alb. 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. > > This patch solves the situation in the bonding without touching bridge code, > as Patrick suggested. For every incoming frame to bonding it searches the > destination address in slaves list and if any of slave addresses matches, it > rewrites the address in frame by the adress of bonding master. This ensures that > all frames comming thru the bonding in alb mode have the same address. > > Jirka > > > Signed-off-by: Jiri Pirko <jpirko@xxxxxxxxxx> > > diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c > index 27fb7f5..2838be0 100644 > --- a/drivers/net/bonding/bond_alb.c > +++ b/drivers/net/bonding/bond_alb.c > @@ -1762,6 +1762,26 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr) > return 0; > } > > +void bond_alb_change_dest(struct sk_buff *skb) > +{ > + struct net_device *bond_dev = skb->dev; > + struct bonding *bond = netdev_priv(bond_dev); > + unsigned char *dest = eth_hdr(skb)->h_dest; > + struct slave *slave; > + int i; > + > + if (!memcmp(dest, bond_dev->dev_addr, ETH_ALEN)) > + return; > + read_lock(&bond->lock); Its a pity bonding doesnt use RCU and needs this read_lock(&bond->lock) > + bond_for_each_slave(bond, slave, i) { > + if (!memcmp(slave->dev->dev_addr, dest, ETH_ALEN)) { compare_ether_addr() (or even better compare_ether_addr_64bits()) instead of memcmp() ? > + memcpy(dest, bond_dev->dev_addr, ETH_ALEN); > + break; > + } > + } > + read_unlock(&bond->lock); > +} > + _______________________________________________ Bridge mailing list Bridge@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/bridge