net: bonding: send peer notify when failure recovery

In LACP mode with broadcast_neighbor enabled, after LACP protocol
recovery, the port can transmit packets. However, if the bond port
doesn't send gratuitous ARP/ND packets to the switch, the switch
won't return packets through the current interface. This causes
traffic imbalance. To resolve this issue, when LACP protocol recovers,
send ARP/ND packets if broadcast_neighbor is enabled.

Cc: Jay Vosburgh <jv@jvosburgh.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: Tonghao Zhang <tonghao@bamaicloud.com>
Signed-off-by: Zengbing Tu <tuzengbing@didiglobal.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/3993652dc093fffa9504ce1c2448fb9dea31d2d2.1751031306.git.tonghao@bamaicloud.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Tonghao Zhang 2025-06-27 21:49:30 +08:00 committed by Paolo Abeni
parent 3d98ee5265
commit 2f9afffc39
3 changed files with 36 additions and 7 deletions

View File

@ -773,8 +773,9 @@ num_unsol_na
greater than 1.
The valid range is 0 - 255; the default value is 1. These options
affect only the active-backup mode. These options were added for
bonding versions 3.3.0 and 3.4.0 respectively.
affect the active-backup or 802.3ad (broadcast_neighbor enabled) mode.
These options were added for bonding versions 3.3.0 and 3.4.0
respectively.
From Linux 3.0 and bonding version 3.7.1, these notifications
are generated by the ipv4 and ipv6 code and the numbers of

View File

@ -982,6 +982,17 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
return 0;
}
static void ad_cond_set_peer_notif(struct port *port)
{
struct bonding *bond = port->slave->bond;
if (bond->params.broadcast_neighbor && rtnl_trylock()) {
bond->send_peer_notif = bond->params.num_peer_notif *
max(1, bond->params.peer_notif_delay);
rtnl_unlock();
}
}
/**
* ad_mux_machine - handle a port's mux state machine
* @port: the port we're looking at
@ -2062,6 +2073,8 @@ static void ad_enable_collecting_distributing(struct port *port,
__enable_port(port);
/* Slave array needs update */
*update_slave_arr = true;
/* Should notify peers if possible */
ad_cond_set_peer_notif(port);
}
}

View File

@ -1237,17 +1237,32 @@ static struct slave *bond_find_best_slave(struct bonding *bond)
/* must be called in RCU critical section or with RTNL held */
static bool bond_should_notify_peers(struct bonding *bond)
{
struct slave *slave = rcu_dereference_rtnl(bond->curr_active_slave);
struct bond_up_slave *usable;
struct slave *slave = NULL;
if (!slave || !bond->send_peer_notif ||
if (!bond->send_peer_notif ||
bond->send_peer_notif %
max(1, bond->params.peer_notif_delay) != 0 ||
!netif_carrier_ok(bond->dev) ||
test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
!netif_carrier_ok(bond->dev))
return false;
/* The send_peer_notif is set by active-backup or 8023ad
* mode, and cleared in bond_close() when changing mode.
* It is safe to only check bond mode here.
*/
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
usable = rcu_dereference_rtnl(bond->usable_slaves);
if (!usable || !READ_ONCE(usable->count))
return false;
} else {
slave = rcu_dereference_rtnl(bond->curr_active_slave);
if (!slave || test_bit(__LINK_STATE_LINKWATCH_PENDING,
&slave->dev->state))
return false;
}
netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n",
slave ? slave->dev->name : "NULL");
slave ? slave->dev->name : "all");
return true;
}