Skip to content

Commit

Permalink
Merge branch 'bonding-802-3ad-fix-no-transmission-of-lacpdus'
Browse files Browse the repository at this point in the history
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.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
kuba-moo committed Aug 23, 2022
2 parents 0ee7828 + f2e44df commit 5003e52
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 28 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3679,6 +3679,7 @@ F: Documentation/networking/bonding.rst
F: drivers/net/bonding/
F: include/net/bond*
F: include/uapi/linux/if_bonding.h
F: tools/testing/selftests/net/bonding/

BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER
M: Dan Robertson <dan@dlrobertson.com>
Expand Down
41 changes: 15 additions & 26 deletions drivers/net/bonding/bond_3ad.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ enum ad_link_speed_type {
static const u8 null_mac_addr[ETH_ALEN + 2] __long_aligned = {
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 u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned =
Expand Down Expand Up @@ -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: bonding struct to work on
* @tick_resolution: tick duration (millisecond resolution)
*
* 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 */
if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
bond->dev->dev_addr)) {

BOND_AD_INFO(bond).aggregator_identifier = 0;

BOND_AD_INFO(bond).system.sys_priority =
bond->params.ad_actor_sys_prio;
if (is_zero_ether_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_AD_INFO(bond).aggregator_identifier = 0;
BOND_AD_INFO(bond).system.sys_priority =
bond->params.ad_actor_sys_prio;
if (is_zero_ether_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);

bond_3ad_initiate_agg_selection(bond,
AD_AGGREGATOR_SELECTION_TIMER *
ad_ticks_per_sec);
}
bond_3ad_initiate_agg_selection(bond,
AD_AGGREGATOR_SELECTION_TIMER *
ad_ticks_per_sec);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
* 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 {
SLAVE_AD_INFO(new_slave)->id =
SLAVE_AD_INFO(prev_slave)->id + 1;
Expand Down
2 changes: 1 addition & 1 deletion include/net/bond_3ad.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ static inline const char *bond_3ad_churn_desc(churn_state_t state)
}

/* ========== 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_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
Expand Down
1 change: 1 addition & 0 deletions tools/testing/selftests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ TARGETS += cpu-hotplug
TARGETS += damon
TARGETS += drivers/dma-buf
TARGETS += drivers/s390x/uvdevice
TARGETS += drivers/net/bonding
TARGETS += efivarfs
TARGETS += exec
TARGETS += filesystems
Expand Down
6 changes: 6 additions & 0 deletions tools/testing/selftests/drivers/net/bonding/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for net selftests

TEST_PROGS := bond-break-lacpdu-tx.sh

include ../../../lib.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/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
1 change: 1 addition & 0 deletions tools/testing/selftests/drivers/net/bonding/config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CONFIG_BONDING=y
1 change: 1 addition & 0 deletions tools/testing/selftests/drivers/net/bonding/settings
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
timeout=60

0 comments on commit 5003e52

Please sign in to comment.