Commit 5003e52c authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch 'bonding-802-3ad-fix-no-transmission-of-lacpdus'

Jonathan Toppins says:

====================
bonding: 802.3ad: fix no transmission of LACPDUs

Configuring a bond in a specific order can leave the bond in a state
where it never transmits LACPDUs.

The first patch adds some kselftest infrastructure and the reproducer
that demonstrates the problem. The second patch fixes the issue. The
new third patch makes ad_ticks_per_sec a static const and removes the
passing of this variable via the stack.
====================

Link: https://lore.kernel.org/r/cover.1660919940.git.jtoppins@redhat.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0ee7828d f2e44dff
...@@ -3679,6 +3679,7 @@ F: Documentation/networking/bonding.rst ...@@ -3679,6 +3679,7 @@ F: Documentation/networking/bonding.rst
F: drivers/net/bonding/ F: drivers/net/bonding/
F: include/net/bond* F: include/net/bond*
F: include/uapi/linux/if_bonding.h F: include/uapi/linux/if_bonding.h
F: tools/testing/selftests/net/bonding/
BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER
M: Dan Robertson <dan@dlrobertson.com> M: Dan Robertson <dan@dlrobertson.com>
......
...@@ -84,7 +84,8 @@ enum ad_link_speed_type { ...@@ -84,7 +84,8 @@ enum ad_link_speed_type {
static const u8 null_mac_addr[ETH_ALEN + 2] __long_aligned = { static const u8 null_mac_addr[ETH_ALEN + 2] __long_aligned = {
0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0
}; };
static u16 ad_ticks_per_sec;
static const u16 ad_ticks_per_sec = 1000 / AD_TIMER_INTERVAL;
static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000; static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
static const u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned = static const u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned =
...@@ -2001,36 +2002,24 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) ...@@ -2001,36 +2002,24 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
/** /**
* bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
* @bond: bonding struct to work on * @bond: bonding struct to work on
* @tick_resolution: tick duration (millisecond resolution)
* *
* Can be called only after the mac address of the bond is set. * Can be called only after the mac address of the bond is set.
*/ */
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution) void bond_3ad_initialize(struct bonding *bond)
{ {
/* check that the bond is not initialized yet */ BOND_AD_INFO(bond).aggregator_identifier = 0;
if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr), BOND_AD_INFO(bond).system.sys_priority =
bond->dev->dev_addr)) { bond->params.ad_actor_sys_prio;
if (is_zero_ether_addr(bond->params.ad_actor_system))
BOND_AD_INFO(bond).aggregator_identifier = 0; BOND_AD_INFO(bond).system.sys_mac_addr =
*((struct mac_addr *)bond->dev->dev_addr);
BOND_AD_INFO(bond).system.sys_priority = else
bond->params.ad_actor_sys_prio; BOND_AD_INFO(bond).system.sys_mac_addr =
if (is_zero_ether_addr(bond->params.ad_actor_system)) *((struct mac_addr *)bond->params.ad_actor_system);
BOND_AD_INFO(bond).system.sys_mac_addr =
*((struct mac_addr *)bond->dev->dev_addr);
else
BOND_AD_INFO(bond).system.sys_mac_addr =
*((struct mac_addr *)bond->params.ad_actor_system);
/* initialize how many times this module is called in one
* second (should be about every 100ms)
*/
ad_ticks_per_sec = tick_resolution;
bond_3ad_initiate_agg_selection(bond, bond_3ad_initiate_agg_selection(bond,
AD_AGGREGATOR_SELECTION_TIMER * AD_AGGREGATOR_SELECTION_TIMER *
ad_ticks_per_sec); ad_ticks_per_sec);
}
} }
/** /**
......
...@@ -2081,7 +2081,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, ...@@ -2081,7 +2081,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
/* Initialize AD with the number of times that the AD timer is called in 1 second /* Initialize AD with the number of times that the AD timer is called in 1 second
* can be called only after the mac address of the bond is set * can be called only after the mac address of the bond is set
*/ */
bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL); bond_3ad_initialize(bond);
} else { } else {
SLAVE_AD_INFO(new_slave)->id = SLAVE_AD_INFO(new_slave)->id =
SLAVE_AD_INFO(prev_slave)->id + 1; SLAVE_AD_INFO(prev_slave)->id + 1;
......
...@@ -290,7 +290,7 @@ static inline const char *bond_3ad_churn_desc(churn_state_t state) ...@@ -290,7 +290,7 @@ static inline const char *bond_3ad_churn_desc(churn_state_t state)
} }
/* ========== AD Exported functions to the main bonding code ========== */ /* ========== AD Exported functions to the main bonding code ========== */
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution); void bond_3ad_initialize(struct bonding *bond);
void bond_3ad_bind_slave(struct slave *slave); void bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave); void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *); void bond_3ad_state_machine_handler(struct work_struct *);
......
...@@ -12,6 +12,7 @@ TARGETS += cpu-hotplug ...@@ -12,6 +12,7 @@ TARGETS += cpu-hotplug
TARGETS += damon TARGETS += damon
TARGETS += drivers/dma-buf TARGETS += drivers/dma-buf
TARGETS += drivers/s390x/uvdevice TARGETS += drivers/s390x/uvdevice
TARGETS += drivers/net/bonding
TARGETS += efivarfs TARGETS += efivarfs
TARGETS += exec TARGETS += exec
TARGETS += filesystems TARGETS += filesystems
......
# SPDX-License-Identifier: GPL-2.0
# Makefile for net selftests
TEST_PROGS := bond-break-lacpdu-tx.sh
include ../../../lib.mk
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Regression Test:
# Verify LACPDUs get transmitted after setting the MAC address of
# the bond.
#
# https://bugzilla.redhat.com/show_bug.cgi?id=2020773
#
# +---------+
# | fab-br0 |
# +---------+
# |
# +---------+
# | fbond |
# +---------+
# | |
# +------+ +------+
# |veth1 | |veth2 |
# +------+ +------+
#
# We use veths instead of physical interfaces
set -e
tmp=$(mktemp -q dump.XXXXXX)
cleanup() {
ip link del fab-br0 >/dev/null 2>&1 || :
ip link del fbond >/dev/null 2>&1 || :
ip link del veth1-bond >/dev/null 2>&1 || :
ip link del veth2-bond >/dev/null 2>&1 || :
modprobe -r bonding >/dev/null 2>&1 || :
rm -f -- ${tmp}
}
trap cleanup 0 1 2
cleanup
sleep 1
# create the bridge
ip link add fab-br0 address 52:54:00:3B:7C:A6 mtu 1500 type bridge \
forward_delay 15
# create the bond
ip link add fbond type bond mode 4 miimon 200 xmit_hash_policy 1 \
ad_actor_sys_prio 65535 lacp_rate fast
# set bond address
ip link set fbond address 52:54:00:3B:7C:A6
ip link set fbond up
# set again bond sysfs parameters
ip link set fbond type bond ad_actor_sys_prio 65535
# create veths
ip link add name veth1-bond type veth peer name veth1-end
ip link add name veth2-bond type veth peer name veth2-end
# add ports
ip link set fbond master fab-br0
ip link set veth1-bond down master fbond
ip link set veth2-bond down master fbond
# bring up
ip link set veth1-end up
ip link set veth2-end up
ip link set fab-br0 up
ip link set fbond up
ip addr add dev fab-br0 10.0.0.3
tcpdump -n -i veth1-end -e ether proto 0x8809 >${tmp} 2>&1 &
sleep 15
pkill tcpdump >/dev/null 2>&1
rc=0
num=$(grep "packets captured" ${tmp} | awk '{print $1}')
if test "$num" -gt 0; then
echo "PASS, captured ${num}"
else
echo "FAIL"
rc=1
fi
exit $rc
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment