Skip to content

Commit fdee88a

Browse files
author
CKI KWF Bot
committed
Merge: bonding: update LACP activity flag after setting lacp_active
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1410 JIRA: https://issues.redhat.com/browse/RHEL-100461 Resolve the bonding LACP negotiation failure when the lacp_active parameter is set to off. Signed-off-by: Hangbin Liu <haliu@redhat.com> Approved-by: Xin Long <lxin@redhat.com> Approved-by: Paolo Abeni <pabeni@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents b7a4df5 + 2f15cac commit fdee88a

File tree

6 files changed

+159
-19
lines changed

6 files changed

+159
-19
lines changed

drivers/net/bonding/bond_3ad.c

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,13 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker);
9595
static void ad_mux_machine(struct port *port, bool *update_slave_arr);
9696
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
9797
static void ad_tx_machine(struct port *port);
98-
static void ad_periodic_machine(struct port *port, struct bond_params *bond_params);
98+
static void ad_periodic_machine(struct port *port);
9999
static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
100100
static void ad_agg_selection_logic(struct aggregator *aggregator,
101101
bool *update_slave_arr);
102102
static void ad_clear_agg(struct aggregator *aggregator);
103103
static void ad_initialize_agg(struct aggregator *aggregator);
104-
static void ad_initialize_port(struct port *port, int lacp_fast);
104+
static void ad_initialize_port(struct port *port, const struct bond_params *bond_params);
105105
static void ad_enable_collecting(struct port *port);
106106
static void ad_disable_distributing(struct port *port,
107107
bool *update_slave_arr);
@@ -1296,10 +1296,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
12961296
* case of EXPIRED even if LINK_DOWN didn't arrive for
12971297
* the port.
12981298
*/
1299-
port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
13001299
port->sm_vars &= ~AD_PORT_MATCHED;
1300+
/* Based on IEEE 8021AX-2014, Figure 6-18 - Receive
1301+
* machine state diagram, the statue should be
1302+
* Partner_Oper_Port_State.Synchronization = FALSE;
1303+
* Partner_Oper_Port_State.LACP_Timeout = Short Timeout;
1304+
* start current_while_timer(Short Timeout);
1305+
* Actor_Oper_Port_State.Expired = TRUE;
1306+
*/
1307+
port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION;
13011308
port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT;
1302-
port->partner_oper.port_state |= LACP_STATE_LACP_ACTIVITY;
13031309
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
13041310
port->actor_oper_port_state |= LACP_STATE_EXPIRED;
13051311
port->sm_vars |= AD_PORT_CHURNED;
@@ -1405,11 +1411,10 @@ static void ad_tx_machine(struct port *port)
14051411
/**
14061412
* ad_periodic_machine - handle a port's periodic state machine
14071413
* @port: the port we're looking at
1408-
* @bond_params: bond parameters we will use
14091414
*
14101415
* Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
14111416
*/
1412-
static void ad_periodic_machine(struct port *port, struct bond_params *bond_params)
1417+
static void ad_periodic_machine(struct port *port)
14131418
{
14141419
periodic_states_t last_state;
14151420

@@ -1418,8 +1423,7 @@ static void ad_periodic_machine(struct port *port, struct bond_params *bond_para
14181423

14191424
/* check if port was reinitialized */
14201425
if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
1421-
(!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) ||
1422-
!bond_params->lacp_active) {
1426+
(!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY))) {
14231427
port->sm_periodic_state = AD_NO_PERIODIC;
14241428
}
14251429
/* check if state machine should change state */
@@ -1943,16 +1947,16 @@ static void ad_initialize_agg(struct aggregator *aggregator)
19431947
/**
19441948
* ad_initialize_port - initialize a given port's parameters
19451949
* @port: the port we're looking at
1946-
* @lacp_fast: boolean. whether fast periodic should be used
1950+
* @bond_params: bond parameters we will use
19471951
*/
1948-
static void ad_initialize_port(struct port *port, int lacp_fast)
1952+
static void ad_initialize_port(struct port *port, const struct bond_params *bond_params)
19491953
{
19501954
static const struct port_params tmpl = {
19511955
.system_priority = 0xffff,
19521956
.key = 1,
19531957
.port_number = 1,
19541958
.port_priority = 0xff,
1955-
.port_state = 1,
1959+
.port_state = 0,
19561960
};
19571961
static const struct lacpdu lacpdu = {
19581962
.subtype = 0x01,
@@ -1970,12 +1974,14 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
19701974
port->actor_port_priority = 0xff;
19711975
port->actor_port_aggregator_identifier = 0;
19721976
port->ntt = false;
1973-
port->actor_admin_port_state = LACP_STATE_AGGREGATION |
1974-
LACP_STATE_LACP_ACTIVITY;
1975-
port->actor_oper_port_state = LACP_STATE_AGGREGATION |
1976-
LACP_STATE_LACP_ACTIVITY;
1977+
port->actor_admin_port_state = LACP_STATE_AGGREGATION;
1978+
port->actor_oper_port_state = LACP_STATE_AGGREGATION;
1979+
if (bond_params->lacp_active) {
1980+
port->actor_admin_port_state |= LACP_STATE_LACP_ACTIVITY;
1981+
port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY;
1982+
}
19771983

1978-
if (lacp_fast)
1984+
if (bond_params->lacp_fast)
19791985
port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT;
19801986

19811987
memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
@@ -2187,7 +2193,7 @@ void bond_3ad_bind_slave(struct slave *slave)
21872193
/* port initialization */
21882194
port = &(SLAVE_AD_INFO(slave)->port);
21892195

2190-
ad_initialize_port(port, bond->params.lacp_fast);
2196+
ad_initialize_port(port, &bond->params);
21912197

21922198
port->slave = slave;
21932199
port->actor_port_number = SLAVE_AD_INFO(slave)->id;
@@ -2499,7 +2505,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
24992505
}
25002506

25012507
ad_rx_machine(NULL, port);
2502-
ad_periodic_machine(port, &bond->params);
2508+
ad_periodic_machine(port);
25032509
ad_port_selection_logic(port, &update_slave_arr);
25042510
ad_mux_machine(port, &update_slave_arr);
25052511
ad_tx_machine(port);
@@ -2869,6 +2875,31 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
28692875
spin_unlock_bh(&bond->mode_lock);
28702876
}
28712877

2878+
/**
2879+
* bond_3ad_update_lacp_active - change the lacp active
2880+
* @bond: bonding struct
2881+
*
2882+
* Update actor_oper_port_state when lacp_active is modified.
2883+
*/
2884+
void bond_3ad_update_lacp_active(struct bonding *bond)
2885+
{
2886+
struct port *port = NULL;
2887+
struct list_head *iter;
2888+
struct slave *slave;
2889+
int lacp_active;
2890+
2891+
lacp_active = bond->params.lacp_active;
2892+
spin_lock_bh(&bond->mode_lock);
2893+
bond_for_each_slave(bond, slave, iter) {
2894+
port = &(SLAVE_AD_INFO(slave)->port);
2895+
if (lacp_active)
2896+
port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY;
2897+
else
2898+
port->actor_oper_port_state &= ~LACP_STATE_LACP_ACTIVITY;
2899+
}
2900+
spin_unlock_bh(&bond->mode_lock);
2901+
}
2902+
28722903
size_t bond_3ad_stats_size(void)
28732904
{
28742905
return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */

drivers/net/bonding/bond_options.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,7 @@ static int bond_option_lacp_active_set(struct bonding *bond,
16371637
netdev_dbg(bond->dev, "Setting LACP active to %s (%llu)\n",
16381638
newval->string, newval->value);
16391639
bond->params.lacp_active = newval->value;
1640+
bond_3ad_update_lacp_active(bond);
16401641

16411642
return 0;
16421643
}

include/net/bond_3ad.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
307307
struct slave *slave);
308308
int bond_3ad_set_carrier(struct bonding *bond);
309309
void bond_3ad_update_lacp_rate(struct bonding *bond);
310+
void bond_3ad_update_lacp_active(struct bonding *bond);
310311
void bond_3ad_update_ad_actor_settings(struct bonding *bond);
311312
int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats);
312313
size_t bond_3ad_stats_size(void);

tools/testing/selftests/drivers/net/bonding/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ TEST_PROGS := \
1010
mode-2-recovery-updelay.sh \
1111
bond_options.sh \
1212
bond-eth-type-change.sh \
13-
bond_macvlan_ipvlan.sh
13+
bond_macvlan_ipvlan.sh \
14+
bond_passive_lacp.sh
1415

1516
TEST_FILES := \
1617
lag_lib.sh \
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0
3+
#
4+
# Test if a bond interface works with lacp_active=off.
5+
6+
# shellcheck disable=SC2034
7+
REQUIRE_MZ=no
8+
NUM_NETIFS=0
9+
lib_dir=$(dirname "$0")
10+
# shellcheck disable=SC1091
11+
source "$lib_dir"/../../../net/forwarding/lib.sh
12+
13+
# shellcheck disable=SC2317
14+
check_port_state()
15+
{
16+
local netns=$1
17+
local port=$2
18+
local state=$3
19+
20+
ip -n "${netns}" -d -j link show "$port" | \
21+
jq -e ".[].linkinfo.info_slave_data.ad_actor_oper_port_state_str | index(\"${state}\") != null" > /dev/null
22+
}
23+
24+
check_pkt_count()
25+
{
26+
RET=0
27+
local ns="$1"
28+
local iface="$2"
29+
30+
# wait 65s, one per 30s
31+
slowwait_for_counter 65 2 tc_rule_handle_stats_get \
32+
"dev ${iface} egress" 101 ".packets" "-n ${ns}" &> /dev/null
33+
}
34+
35+
setup() {
36+
setup_ns c_ns s_ns
37+
38+
# shellcheck disable=SC2154
39+
ip -n "${c_ns}" link add eth0 type veth peer name eth0 netns "${s_ns}"
40+
ip -n "${c_ns}" link add eth1 type veth peer name eth1 netns "${s_ns}"
41+
42+
# Add tc filter to count the pkts
43+
tc -n "${c_ns}" qdisc add dev eth0 clsact
44+
tc -n "${c_ns}" filter add dev eth0 egress handle 101 protocol 0x8809 matchall action pass
45+
tc -n "${s_ns}" qdisc add dev eth1 clsact
46+
tc -n "${s_ns}" filter add dev eth1 egress handle 101 protocol 0x8809 matchall action pass
47+
48+
ip -n "${s_ns}" link add bond0 type bond mode 802.3ad lacp_active on lacp_rate fast
49+
ip -n "${s_ns}" link set eth0 master bond0
50+
ip -n "${s_ns}" link set eth1 master bond0
51+
52+
ip -n "${c_ns}" link add bond0 type bond mode 802.3ad lacp_active off lacp_rate fast
53+
ip -n "${c_ns}" link set eth0 master bond0
54+
ip -n "${c_ns}" link set eth1 master bond0
55+
56+
}
57+
58+
trap cleanup_all_ns EXIT
59+
setup
60+
61+
# The bond will send 2 lacpdu pkts during init time, let's wait at least 2s
62+
# after interface up
63+
ip -n "${c_ns}" link set bond0 up
64+
sleep 2
65+
66+
# 1. The passive side shouldn't send LACPDU.
67+
check_pkt_count "${c_ns}" "eth0" && RET=1
68+
log_test "802.3ad lacp_active off" "init port"
69+
70+
ip -n "${s_ns}" link set bond0 up
71+
# 2. The passive side should not have the 'active' flag.
72+
RET=0
73+
slowwait 2 check_port_state "${c_ns}" "eth0" "active" && RET=1
74+
log_test "802.3ad lacp_active off" "port state active"
75+
76+
# 3. The active side should have the 'active' flag.
77+
RET=0
78+
slowwait 2 check_port_state "${s_ns}" "eth0" "active" || RET=1
79+
log_test "802.3ad lacp_active on" "port state active"
80+
81+
# 4. Make sure the connection is not expired.
82+
RET=0
83+
slowwait 5 check_port_state "${s_ns}" "eth0" "distributing"
84+
slowwait 10 check_port_state "${s_ns}" "eth0" "expired" && RET=1
85+
log_test "bond 802.3ad lacp_active off" "port connection"
86+
87+
# After testing, disconnect one port on each side to check the state.
88+
ip -n "${s_ns}" link set eth0 nomaster
89+
ip -n "${s_ns}" link set eth0 up
90+
ip -n "${c_ns}" link set eth1 nomaster
91+
ip -n "${c_ns}" link set eth1 up
92+
# Due to Periodic Machine and Rx Machine state change, the bond will still
93+
# send lacpdu pkts in a few seconds. sleep at lease 5s to make sure
94+
# negotiation finished
95+
sleep 5
96+
97+
# 5. The active side should keep sending LACPDU.
98+
check_pkt_count "${s_ns}" "eth1" || RET=1
99+
log_test "bond 802.3ad lacp_active on" "port pkt after disconnect"
100+
101+
# 6. The passive side shouldn't send LACPDU anymore.
102+
check_pkt_count "${c_ns}" "eth0" && RET=1
103+
log_test "bond 802.3ad lacp_active off" "port pkt after disconnect"
104+
105+
exit "$EXIT_STATUS"

tools/testing/selftests/drivers/net/bonding/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CONFIG_MACVLAN=y
66
CONFIG_IPVLAN=y
77
CONFIG_NET_ACT_GACT=y
88
CONFIG_NET_CLS_FLOWER=y
9+
CONFIG_NET_CLS_MATCHALL=m
910
CONFIG_NET_SCH_INGRESS=y
1011
CONFIG_NLMON=y
1112
CONFIG_VETH=y

0 commit comments

Comments
 (0)