Commit b9881d9a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bonding-ns-validation-fixes'



Hangbin Liu says:

====================
bonding: fix ns validation on backup slaves

The first patch fixed a ns validation issue on backup slaves. The second
patch re-format the bond option test and add a test lib file. The third
patch add the arp validate regression test for the kernel patch.

Here is the new bonding option test without the kernel fix:

]# ./bond_options.sh
TEST: prio (active-backup miimon primary_reselect 0)           [ OK ]
TEST: prio (active-backup miimon primary_reselect 1)           [ OK ]
TEST: prio (active-backup miimon primary_reselect 2)           [ OK ]
TEST: prio (active-backup arp_ip_target primary_reselect 0)    [ OK ]
TEST: prio (active-backup arp_ip_target primary_reselect 1)    [ OK ]
TEST: prio (active-backup arp_ip_target primary_reselect 2)    [ OK ]
TEST: prio (active-backup ns_ip6_target primary_reselect 0)    [ OK ]
TEST: prio (active-backup ns_ip6_target primary_reselect 1)    [ OK ]
TEST: prio (active-backup ns_ip6_target primary_reselect 2)    [ OK ]
TEST: prio (balance-tlb miimon primary_reselect 0)             [ OK ]
TEST: prio (balance-tlb miimon primary_reselect 1)             [ OK ]
TEST: prio (balance-tlb miimon primary_reselect 2)             [ OK ]
TEST: prio (balance-tlb arp_ip_target primary_reselect 0)      [ OK ]
TEST: prio (balance-tlb arp_ip_target primary_reselect 1)      [ OK ]
TEST: prio (balance-tlb arp_ip_target primary_reselect 2)      [ OK ]
TEST: prio (balance-tlb ns_ip6_target primary_reselect 0)      [ OK ]
TEST: prio (balance-tlb ns_ip6_target primary_reselect 1)      [ OK ]
TEST: prio (balance-tlb ns_ip6_target primary_reselect 2)      [ OK ]
TEST: prio (balance-alb miimon primary_reselect 0)             [ OK ]
TEST: prio (balance-alb miimon primary_reselect 1)             [ OK ]
TEST: prio (balance-alb miimon primary_reselect 2)             [ OK ]
TEST: prio (balance-alb arp_ip_target primary_reselect 0)      [ OK ]
TEST: prio (balance-alb arp_ip_target primary_reselect 1)      [ OK ]
TEST: prio (balance-alb arp_ip_target primary_reselect 2)      [ OK ]
TEST: prio (balance-alb ns_ip6_target primary_reselect 0)      [ OK ]
TEST: prio (balance-alb ns_ip6_target primary_reselect 1)      [ OK ]
TEST: prio (balance-alb ns_ip6_target primary_reselect 2)      [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 0)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 1)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 2)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 3)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 4)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 5)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 6)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 0)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 1)  [ OK ]
TEST: arp_validate (interface eth1 mii_status DOWN)                 [FAIL]
TEST: arp_validate (interface eth2 mii_status DOWN)                 [FAIL]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 2)  [FAIL]
TEST: arp_validate (interface eth1 mii_status DOWN)                 [FAIL]
TEST: arp_validate (interface eth2 mii_status DOWN)                 [FAIL]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 3)  [FAIL]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 4)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 5)  [ OK ]
TEST: arp_validate (interface eth1 mii_status DOWN)                 [FAIL]
TEST: arp_validate (interface eth2 mii_status DOWN)                 [FAIL]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 6)  [FAIL]

Here is the test result after the kernel fix:
TEST: arp_validate (active-backup arp_ip_target arp_validate 0)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 1)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 2)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 3)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 4)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 5)  [ OK ]
TEST: arp_validate (active-backup arp_ip_target arp_validate 6)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 0)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 1)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 2)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 3)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 4)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 5)  [ OK ]
TEST: arp_validate (active-backup ns_ip6_target arp_validate 6)  [ OK ]
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dc5110c2 2e825f8a
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -3269,7 +3269,8 @@ static int bond_na_rcv(const struct sk_buff *skb, struct bonding *bond,

	combined = skb_header_pointer(skb, 0, sizeof(_combined), &_combined);
	if (!combined || combined->ip6.nexthdr != NEXTHDR_ICMP ||
	    combined->icmp6.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT)
	    (combined->icmp6.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION &&
	     combined->icmp6.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT))
		goto out;

	saddr = &combined->ip6.saddr;
@@ -3291,7 +3292,7 @@ static int bond_na_rcv(const struct sk_buff *skb, struct bonding *bond,
	else if (curr_active_slave &&
		 time_after(slave_last_rx(bond, curr_active_slave),
			    curr_active_slave->last_link_up))
		bond_validate_na(bond, slave, saddr, daddr);
		bond_validate_na(bond, slave, daddr, saddr);
	else if (curr_arp_slave &&
		 bond_time_in_interval(bond, slave_last_tx(curr_arp_slave), 1))
		bond_validate_na(bond, slave, saddr, daddr);
+6 −2
Original line number Diff line number Diff line
@@ -761,13 +761,17 @@ static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
#if IS_ENABLED(CONFIG_IPV6)
static inline int bond_get_targets_ip6(struct in6_addr *targets, struct in6_addr *ip)
{
	struct in6_addr mcaddr;
	int i;

	for (i = 0; i < BOND_MAX_NS_TARGETS; i++)
		if (ipv6_addr_equal(&targets[i], ip))
	for (i = 0; i < BOND_MAX_NS_TARGETS; i++) {
		addrconf_addr_solict_mult(&targets[i], &mcaddr);
		if ((ipv6_addr_equal(&targets[i], ip)) ||
		    (ipv6_addr_equal(&mcaddr, ip)))
			return i;
		else if (ipv6_addr_any(&targets[i]))
			break;
	}

	return -1;
}
+2 −1
Original line number Diff line number Diff line
@@ -8,11 +8,12 @@ TEST_PROGS := \
	dev_addr_lists.sh \
	mode-1-recovery-updelay.sh \
	mode-2-recovery-updelay.sh \
	option_prio.sh \
	bond_options.sh \
	bond-eth-type-change.sh

TEST_FILES := \
	lag_lib.sh \
	bond_topo_3d1c.sh \
	net_forwarding_lib.sh

include ../../../lib.mk
+264 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Test bonding options with mode 1,5,6

ALL_TESTS="
	prio
	arp_validate
"

REQUIRE_MZ=no
NUM_NETIFS=0
lib_dir=$(dirname "$0")
source ${lib_dir}/net_forwarding_lib.sh
source ${lib_dir}/bond_topo_3d1c.sh

skip_prio()
{
	local skip=1

	# check if iproute support prio option
	ip -n ${s_ns} link set eth0 type bond_slave prio 10
	[[ $? -ne 0 ]] && skip=0

	# check if kernel support prio option
	ip -n ${s_ns} -d link show eth0 | grep -q "prio 10"
	[[ $? -ne 0 ]] && skip=0

	return $skip
}

skip_ns()
{
	local skip=1

	# check if iproute support ns_ip6_target option
	ip -n ${s_ns} link add bond1 type bond ns_ip6_target ${g_ip6}
	[[ $? -ne 0 ]] && skip=0

	# check if kernel support ns_ip6_target option
	ip -n ${s_ns} -d link show bond1 | grep -q "ns_ip6_target ${g_ip6}"
	[[ $? -ne 0 ]] && skip=0

	ip -n ${s_ns} link del bond1

	return $skip
}

active_slave=""
check_active_slave()
{
	local target_active_slave=$1
	active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave")
	test "$active_slave" = "$target_active_slave"
	check_err $? "Current active slave is $active_slave but not $target_active_slave"
}


# Test bonding prio option
prio_test()
{
	local param="$1"
	RET=0

	# create bond
	bond_reset "${param}"

	# check bonding member prio value
	ip -n ${s_ns} link set eth0 type bond_slave prio 0
	ip -n ${s_ns} link set eth1 type bond_slave prio 10
	ip -n ${s_ns} link set eth2 type bond_slave prio 11
	cmd_jq "ip -n ${s_ns} -d -j link show eth0" \
		".[].linkinfo.info_slave_data | select (.prio == 0)" "-e" &> /dev/null
	check_err $? "eth0 prio is not 0"
	cmd_jq "ip -n ${s_ns} -d -j link show eth1" \
		".[].linkinfo.info_slave_data | select (.prio == 10)" "-e" &> /dev/null
	check_err $? "eth1 prio is not 10"
	cmd_jq "ip -n ${s_ns} -d -j link show eth2" \
		".[].linkinfo.info_slave_data | select (.prio == 11)" "-e" &> /dev/null
	check_err $? "eth2 prio is not 11"

	bond_check_connection "setup"

	# active slave should be the primary slave
	check_active_slave eth1

	# active slave should be the higher prio slave
	ip -n ${s_ns} link set $active_slave down
	bond_check_connection "fail over"
	check_active_slave eth2

	# when only 1 slave is up
	ip -n ${s_ns} link set $active_slave down
	bond_check_connection "only 1 slave up"
	check_active_slave eth0

	# when a higher prio slave change to up
	ip -n ${s_ns} link set eth2 up
	bond_check_connection "higher prio slave up"
	case $primary_reselect in
		"0")
			check_active_slave "eth2"
			;;
		"1")
			check_active_slave "eth0"
			;;
		"2")
			check_active_slave "eth0"
			;;
	esac
	local pre_active_slave=$active_slave

	# when the primary slave change to up
	ip -n ${s_ns} link set eth1 up
	bond_check_connection "primary slave up"
	case $primary_reselect in
		"0")
			check_active_slave "eth1"
			;;
		"1")
			check_active_slave "$pre_active_slave"
			;;
		"2")
			check_active_slave "$pre_active_slave"
			ip -n ${s_ns} link set $active_slave down
			bond_check_connection "pre_active slave down"
			check_active_slave "eth1"
			;;
	esac

	# Test changing bond slave prio
	if [[ "$primary_reselect" == "0" ]];then
		ip -n ${s_ns} link set eth0 type bond_slave prio 1000000
		ip -n ${s_ns} link set eth1 type bond_slave prio 0
		ip -n ${s_ns} link set eth2 type bond_slave prio -50
		ip -n ${s_ns} -d link show eth0 | grep -q 'prio 1000000'
		check_err $? "eth0 prio is not 1000000"
		ip -n ${s_ns} -d link show eth1 | grep -q 'prio 0'
		check_err $? "eth1 prio is not 0"
		ip -n ${s_ns} -d link show eth2 | grep -q 'prio -50'
		check_err $? "eth3 prio is not -50"
		check_active_slave "eth1"

		ip -n ${s_ns} link set $active_slave down
		bond_check_connection "change slave prio"
		check_active_slave "eth0"
	fi
}

prio_miimon()
{
	local primary_reselect
	local mode=$1

	for primary_reselect in 0 1 2; do
		prio_test "mode $mode miimon 100 primary eth1 primary_reselect $primary_reselect"
		log_test "prio" "$mode miimon primary_reselect $primary_reselect"
	done
}

prio_arp()
{
	local primary_reselect
	local mode=$1

	for primary_reselect in 0 1 2; do
		prio_test "mode active-backup arp_interval 100 arp_ip_target ${g_ip4} primary eth1 primary_reselect $primary_reselect"
		log_test "prio" "$mode arp_ip_target primary_reselect $primary_reselect"
	done
}

prio_ns()
{
	local primary_reselect
	local mode=$1

	if skip_ns; then
		log_test_skip "prio ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
		return 0
	fi

	for primary_reselect in 0 1 2; do
		prio_test "mode active-backup arp_interval 100 ns_ip6_target ${g_ip6} primary eth1 primary_reselect $primary_reselect"
		log_test "prio" "$mode ns_ip6_target primary_reselect $primary_reselect"
	done
}

prio()
{
	local mode modes="active-backup balance-tlb balance-alb"

	if skip_prio; then
		log_test_skip "prio" "Current iproute or kernel doesn't support bond option 'prio'."
		return 0
	fi

	for mode in $modes; do
		prio_miimon $mode
		prio_arp $mode
		prio_ns $mode
	done
}

arp_validate_test()
{
	local param="$1"
	RET=0

	# create bond
	bond_reset "${param}"

	bond_check_connection
	[ $RET -ne 0 ] && log_test "arp_validate" "$retmsg"

	# wait for a while to make sure the mii status stable
	sleep 5
	for i in $(seq 0 2); do
		mii_status=$(cmd_jq "ip -n ${s_ns} -j -d link show eth$i" ".[].linkinfo.info_slave_data.mii_status")
		if [ ${mii_status} != "UP" ]; then
			RET=1
			log_test "arp_validate" "interface eth$i mii_status $mii_status"
		fi
	done
}

arp_validate_arp()
{
	local mode=$1
	local val
	for val in $(seq 0 6); do
		arp_validate_test "mode $mode arp_interval 100 arp_ip_target ${g_ip4} arp_validate $val"
		log_test "arp_validate" "$mode arp_ip_target arp_validate $val"
	done
}

arp_validate_ns()
{
	local mode=$1
	local val

	if skip_ns; then
		log_test_skip "arp_validate ns" "Current iproute or kernel doesn't support bond option 'ns_ip6_target'."
		return 0
	fi

	for val in $(seq 0 6); do
		arp_validate_test "mode $mode arp_interval 100 ns_ip6_target ${g_ip6} arp_validate $val"
		log_test "arp_validate" "$mode ns_ip6_target arp_validate $val"
	done
}

arp_validate()
{
	arp_validate_arp "active-backup"
	arp_validate_ns "active-backup"
}

trap cleanup EXIT

setup_prepare
setup_wait
tests_run

exit $EXIT_STATUS
+143 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
#
# Topology for Bond mode 1,5,6 testing
#
#  +-------------------------------------+
#  |                bond0                |
#  |                  +                  |  Server
#  |      eth0        | eth1   eth2      |  192.0.2.1/24
#  |        +-------------------+        |  2001:db8::1/24
#  |        |         |         |        |
#  +-------------------------------------+
#           |         |         |
#  +-------------------------------------+
#  |        |         |         |        |
#  |    +---+---------+---------+---+    |  Gateway
#  |    |            br0            |    |  192.0.2.254/24
#  |    +-------------+-------------+    |  2001:db8::254/24
#  |                  |                  |
#  +-------------------------------------+
#                     |
#  +-------------------------------------+
#  |                  |                  |  Client
#  |                  +                  |  192.0.2.10/24
#  |                eth0                 |  2001:db8::10/24
#  +-------------------------------------+

s_ns="s-$(mktemp -u XXXXXX)"
c_ns="c-$(mktemp -u XXXXXX)"
g_ns="g-$(mktemp -u XXXXXX)"
s_ip4="192.0.2.1"
c_ip4="192.0.2.10"
g_ip4="192.0.2.254"
s_ip6="2001:db8::1"
c_ip6="2001:db8::10"
g_ip6="2001:db8::254"

gateway_create()
{
	ip netns add ${g_ns}
	ip -n ${g_ns} link add br0 type bridge
	ip -n ${g_ns} link set br0 up
	ip -n ${g_ns} addr add ${g_ip4}/24 dev br0
	ip -n ${g_ns} addr add ${g_ip6}/24 dev br0
}

gateway_destroy()
{
	ip -n ${g_ns} link del br0
	ip netns del ${g_ns}
}

server_create()
{
	ip netns add ${s_ns}
	ip -n ${s_ns} link add bond0 type bond mode active-backup miimon 100

	for i in $(seq 0 2); do
		ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns}

		ip -n ${g_ns} link set s${i} up
		ip -n ${g_ns} link set s${i} master br0
		ip -n ${s_ns} link set eth${i} master bond0
	done

	ip -n ${s_ns} link set bond0 up
	ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0
	ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0
	sleep 2
}

# Reset bond with new mode and options
bond_reset()
{
	local param="$1"

	ip -n ${s_ns} link set bond0 down
	ip -n ${s_ns} link del bond0

	ip -n ${s_ns} link add bond0 type bond $param
	for i in $(seq 0 2); do
		ip -n ${s_ns} link set eth$i master bond0
	done

	ip -n ${s_ns} link set bond0 up
	ip -n ${s_ns} addr add ${s_ip4}/24 dev bond0
	ip -n ${s_ns} addr add ${s_ip6}/24 dev bond0
	sleep 2
}

server_destroy()
{
	for i in $(seq 0 2); do
		ip -n ${s_ns} link del eth${i}
	done
	ip netns del ${s_ns}
}

client_create()
{
	ip netns add ${c_ns}
	ip -n ${c_ns} link add eth0 type veth peer name c0 netns ${g_ns}

	ip -n ${g_ns} link set c0 up
	ip -n ${g_ns} link set c0 master br0

	ip -n ${c_ns} link set eth0 up
	ip -n ${c_ns} addr add ${c_ip4}/24 dev eth0
	ip -n ${c_ns} addr add ${c_ip6}/24 dev eth0
}

client_destroy()
{
	ip -n ${c_ns} link del eth0
	ip netns del ${c_ns}
}

setup_prepare()
{
	gateway_create
	server_create
	client_create
}

cleanup()
{
	pre_cleanup

	client_destroy
	server_destroy
	gateway_destroy
}

bond_check_connection()
{
	local msg=${1:-"check connection"}

	sleep 2
	ip netns exec ${s_ns} ping ${c_ip4} -c5 -i 0.1 &>/dev/null
	check_err $? "${msg}: ping failed"
	ip netns exec ${s_ns} ping6 ${c_ip6} -c5 -i 0.1 &>/dev/null
	check_err $? "${msg}: ping6 failed"
}
Loading