]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bonding: do not set usable_slaves for broadcast mode
authorHangbin Liu <liuhangbin@gmail.com>
Wed, 4 Mar 2026 07:13:53 +0000 (15:13 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sat, 7 Mar 2026 00:25:16 +0000 (16:25 -0800)
After commit e0caeb24f538 ("net: bonding: update the slave array for broadcast mode"),
broadcast mode will also set all_slaves and usable_slaves during
bond_enslave(). But if we also set updelay, during enslave, the
slave init state will be BOND_LINK_BACK. And later
bond_update_slave_arr() will alloc usable_slaves but add nothing.
This will cause bond_miimon_inspect() to have ignore_updelay
always true. So the updelay will be always ignored. e.g.

[    6.498368] bond0: (slave veth2): link status definitely down, disabling slave
[    7.536371] bond0: (slave veth2): link status up, enabling it in 0 ms
[    7.536402] bond0: (slave veth2): link status definitely up, 10000 Mbps full duplex

To fix it, we can either always call bond_update_slave_arr() on every
place when link changes. Or, let's just not set usable_slaves for
broadcast mode.

Fixes: e0caeb24f538 ("net: bonding: update the slave array for broadcast mode")
Reported-by: Liang Li <liali@redhat.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Link: https://patch.msgid.link/20260304-b4-bond_updelay-v1-1-f72eb2e454d0@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/bonding/bond_main.c

index 14ed91391fcc5c9984be5e8cec65eede631fea97..93a32a368d31b373a03595593610f5c817450cbe 100644 (file)
@@ -5069,13 +5069,18 @@ static void bond_set_slave_arr(struct bonding *bond,
 {
        struct bond_up_slave *usable, *all;
 
-       usable = rtnl_dereference(bond->usable_slaves);
-       rcu_assign_pointer(bond->usable_slaves, usable_slaves);
-       kfree_rcu(usable, rcu);
-
        all = rtnl_dereference(bond->all_slaves);
        rcu_assign_pointer(bond->all_slaves, all_slaves);
        kfree_rcu(all, rcu);
+
+       if (BOND_MODE(bond) == BOND_MODE_BROADCAST) {
+               kfree_rcu(usable_slaves, rcu);
+               return;
+       }
+
+       usable = rtnl_dereference(bond->usable_slaves);
+       rcu_assign_pointer(bond->usable_slaves, usable_slaves);
+       kfree_rcu(usable, rcu);
 }
 
 static void bond_reset_slave_arr(struct bonding *bond)