bonding: send learning packets for vlans on slave
authorDebabrata Banerjee <dbanerje@akamai.com>
Wed, 9 May 2018 23:32:11 +0000 (19:32 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 19 May 2018 08:26:59 +0000 (10:26 +0200)
[ Upstream commit 21706ee8a47d3ede7fdae0be6d7c0a0e31a83229 ]

There was a regression at some point from the intended functionality of
commit f60c3704e87d ("bonding: Fix alb mode to only use first level
vlans.")

Given the return value vlan_get_encap_level() we need to store the nest
level of the bond device, and then compare the vlan's encap level to
this. Without this, this check always fails and learning packets are
never sent.

In addition, this same commit caused a regression in the behavior of
balance_alb, which requires learning packets be sent for all interfaces
using the slave's mac in order to load balance properly. For vlan's
that have not set a user mac, we can send after checking one bit.
Otherwise we need send the set mac, albeit defeating rx load balancing
for that vlan.

Signed-off-by: Debabrata Banerjee <dbanerje@akamai.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
include/net/bonding.h

index 7b85c508c2736d6e2200857fe50e69aec220aa74..91d8a48e53c368dded18dd01b0a5cf8a9fd2f0b9 100644 (file)
@@ -944,6 +944,10 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
        skb->priority = TC_PRIO_CONTROL;
        skb->dev = slave->dev;
 
+       netdev_dbg(slave->bond->dev,
+                  "Send learning packet: dev %s mac %pM vlan %d\n",
+                  slave->dev->name, mac_addr, vid);
+
        if (vid)
                __vlan_hwaccel_put_tag(skb, vlan_proto, vid);
 
@@ -966,14 +970,13 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
         */
        rcu_read_lock();
        netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
-               if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
-                       if (strict_match &&
-                           ether_addr_equal_64bits(mac_addr,
-                                                   upper->dev_addr)) {
+               if (is_vlan_dev(upper) &&
+                   bond->nest_level == vlan_get_encap_level(upper) - 1) {
+                       if (upper->addr_assign_type == NET_ADDR_STOLEN) {
                                alb_send_lp_vid(slave, mac_addr,
                                                vlan_dev_vlan_proto(upper),
                                                vlan_dev_vlan_id(upper));
-                       } else if (!strict_match) {
+                       } else {
                                alb_send_lp_vid(slave, upper->dev_addr,
                                                vlan_dev_vlan_proto(upper),
                                                vlan_dev_vlan_id(upper));
index 13a015b8052b4b1b7fd541cf8a488f36504f4e71..1a139d0f22328c709e33eb4f6af393fd435f52d7 100644 (file)
@@ -1732,6 +1732,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        if (bond_mode_uses_xmit_hash(bond))
                bond_update_slave_arr(bond, NULL);
 
+       bond->nest_level = dev_get_nest_level(bond_dev);
+
        netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n",
                    slave_dev->name,
                    bond_is_active_slave(new_slave) ? "an active" : "a backup",
index f32f7ef8a23a25a06f8e095f6982b57c78b0dd7f..7734cc9c7d29eb7b3d8a7f709e59c87938fbb8d4 100644 (file)
@@ -197,6 +197,7 @@ struct bonding {
        struct   slave __rcu *primary_slave;
        struct   bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
        bool     force_primary;
+       u32      nest_level;
        s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
        int     (*recv_probe)(const struct sk_buff *, struct bonding *,
                              struct slave *);