Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

selftests: net: Add tests for failover of team-aggregated ports

There are currently no kernel tests that verify the effect of setting
the enabled team driver option. In a followup patch, there will be
changes to this option, so it will be important to make sure it still
behaves as it does now.

The test verifies that tcp continues to work across two different team
devices in separate network namespaces, even when member links are
manually disabled.

Signed-off-by: Marc Harvey <marcharvey@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260409-teaming-driver-internal-v7-4-f47e7589685d@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Marc Harvey and committed by
Paolo Abeni
05e35244 cfa477df

+319 -2
+2
tools/testing/selftests/drivers/net/team/Makefile
··· 7 7 options.sh \ 8 8 propagation.sh \ 9 9 refleak.sh \ 10 + transmit_failover.sh \ 10 11 # end of TEST_PROGS 11 12 12 13 TEST_INCLUDES := \ 14 + team_lib.sh \ 13 15 ../bonding/lag_lib.sh \ 14 16 ../../../net/forwarding/lib.sh \ 15 17 ../../../net/in_netns.sh \
+4
tools/testing/selftests/drivers/net/team/config
··· 6 6 CONFIG_NET_IPGRE=y 7 7 CONFIG_NET_TEAM=y 8 8 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=y 9 + CONFIG_NET_TEAM_MODE_BROADCAST=y 9 10 CONFIG_NET_TEAM_MODE_LOADBALANCE=y 11 + CONFIG_NET_TEAM_MODE_RANDOM=y 12 + CONFIG_NET_TEAM_MODE_ROUNDROBIN=y 13 + CONFIG_VETH=y
+148
tools/testing/selftests/drivers/net/team/team_lib.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + test_dir="$(dirname "$0")" 5 + export REQUIRE_MZ=no 6 + export NUM_NETIFS=0 7 + # shellcheck disable=SC1091 8 + source "${test_dir}/../../../net/forwarding/lib.sh" 9 + 10 + TCP_PORT="43434" 11 + 12 + # Create a team interface inside of a given network namespace with a given 13 + # mode, members, and IP address. 14 + # Arguments: 15 + # namespace - Network namespace to put the team interface into. 16 + # team - The name of the team interface to setup. 17 + # mode - The team mode of the interface. 18 + # ip_address - The IP address to assign to the team interface. 19 + # prefix_length - The prefix length for the IP address subnet. 20 + # $@ - members - The member interfaces of the aggregation. 21 + setup_team() 22 + { 23 + local namespace=$1 24 + local team=$2 25 + local mode=$3 26 + local ip_address=$4 27 + local prefix_length=$5 28 + shift 5 29 + local members=("$@") 30 + 31 + # Prerequisite: team must have no members 32 + for member in "${members[@]}"; do 33 + ip -n "${namespace}" link set "${member}" nomaster 34 + done 35 + 36 + # Prerequisite: team must have no address in order to set it 37 + # shellcheck disable=SC2086 38 + ip -n "${namespace}" addr del "${ip_address}/${prefix_length}" \ 39 + ${NODAD} dev "${team}" 40 + 41 + echo "Setting team in ${namespace} to mode ${mode}" 42 + 43 + if ! ip -n "${namespace}" link set "${team}" down; then 44 + echo "Failed to bring team device down" 45 + return 1 46 + fi 47 + if ! ip netns exec "${namespace}" teamnl "${team}" setoption mode \ 48 + "${mode}"; then 49 + echo "Failed to set ${team} mode to '${mode}'" 50 + return 1 51 + fi 52 + 53 + # Aggregate the members into teams. 54 + for member in "${members[@]}"; do 55 + ip -n "${namespace}" link set "${member}" master "${team}" 56 + done 57 + 58 + # Bring team devices up and give them addresses. 59 + if ! ip -n "${namespace}" link set "${team}" up; then 60 + echo "Failed to set ${team} up" 61 + return 1 62 + fi 63 + 64 + # shellcheck disable=SC2086 65 + if ! ip -n "${namespace}" addr add "${ip_address}/${prefix_length}" \ 66 + ${NODAD} dev "${team}"; then 67 + echo "Failed to give ${team} IP address in ${namespace}" 68 + return 1 69 + fi 70 + } 71 + 72 + # This is global used to keep track of the sender's iperf3 process, so that it 73 + # can be terminated. 74 + declare sender_pid 75 + 76 + # Start sending and receiving TCP traffic with iperf3. 77 + # Globals: 78 + # sender_pid - The process ID of the iperf3 sender process. Used to kill it 79 + # later. 80 + start_listening_and_sending() 81 + { 82 + ip netns exec "${NS2}" iperf3 -s -p "${TCP_PORT}" --logfile /dev/null & 83 + # Wait for server to become reachable before starting client. 84 + slowwait 5 ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p \ 85 + "${TCP_PORT}" -t 1 --logfile /dev/null 86 + ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p "${TCP_PORT}" -b 1M -l \ 87 + 1K -t 0 --logfile /dev/null & 88 + sender_pid=$! 89 + } 90 + 91 + # Stop sending TCP traffic with iperf3. 92 + # Globals: 93 + # sender_pid - The process ID of the iperf3 sender process. 94 + stop_sending_and_listening() 95 + { 96 + kill "${sender_pid}" && wait "${sender_pid}" 2>/dev/null || true 97 + } 98 + 99 + # Monitor for TCP traffic with Tcpdump, save results to temp files. 100 + # Arguments: 101 + # namespace - The network namespace to run tcpdump inside of. 102 + # $@ - interfaces - The interfaces to listen to. 103 + save_tcpdump_outputs() 104 + { 105 + local namespace=$1 106 + shift 1 107 + local interfaces=("$@") 108 + 109 + for interface in "${interfaces[@]}"; do 110 + tcpdump_start "${interface}" "${namespace}" 111 + done 112 + 113 + sleep 1 114 + 115 + for interface in "${interfaces[@]}"; do 116 + tcpdump_stop_nosleep "${interface}" 117 + done 118 + } 119 + 120 + clear_tcpdump_outputs() 121 + { 122 + local interfaces=("$@") 123 + 124 + for interface in "${interfaces[@]}"; do 125 + tcpdump_cleanup "${interface}" 126 + done 127 + } 128 + 129 + # Read Tcpdump output, determine packet counts. 130 + # Arguments: 131 + # interface - The name of the interface to count packets for. 132 + # ip_address - The destination IP address. 133 + did_interface_receive() 134 + { 135 + local interface="$1" 136 + local ip_address="$2" 137 + local packet_count 138 + 139 + packet_count=$(tcpdump_show "$interface" | grep -c \ 140 + "> ${ip_address}.${TCP_PORT}") 141 + echo "Packet count for ${interface} was ${packet_count}" 142 + 143 + if [[ "${packet_count}" -gt 0 ]]; then 144 + true 145 + else 146 + false 147 + fi 148 + }
+158
tools/testing/selftests/drivers/net/team/transmit_failover.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + # These tests verify the basic failover capability of the team driver via the 5 + # `enabled` team driver option across different team driver modes. This does not 6 + # rely on teamd, and instead just uses teamnl to set the `enabled` option 7 + # directly. 8 + # 9 + # Topology: 10 + # 11 + # +-------------------------+ NS1 12 + # | test_team1 | 13 + # | + | 14 + # | eth0 | eth1 | 15 + # | +---+---+ | 16 + # | | | | 17 + # +-------------------------+ 18 + # | | 19 + # +-------------------------+ NS2 20 + # | | | | 21 + # | +-------+ | 22 + # | eth0 | eth1 | 23 + # | + | 24 + # | test_team2 | 25 + # +-------------------------+ 26 + 27 + export ALL_TESTS="team_test_failover" 28 + 29 + test_dir="$(dirname "$0")" 30 + # shellcheck disable=SC1091 31 + source "${test_dir}/../../../net/lib.sh" 32 + # shellcheck disable=SC1091 33 + source "${test_dir}/team_lib.sh" 34 + 35 + NS1="" 36 + NS2="" 37 + export NODAD="nodad" 38 + PREFIX_LENGTH="64" 39 + NS1_IP="fd00::1" 40 + NS2_IP="fd00::2" 41 + NS1_IP4="192.168.0.1" 42 + NS2_IP4="192.168.0.2" 43 + MEMBERS=("eth0" "eth1") 44 + 45 + while getopts "4" opt; do 46 + case $opt in 47 + 4) 48 + echo "IPv4 mode selected." 49 + export NODAD= 50 + PREFIX_LENGTH="24" 51 + NS1_IP="${NS1_IP4}" 52 + NS2_IP="${NS2_IP4}" 53 + ;; 54 + \?) 55 + echo "Invalid option: -$OPTARG" >&2 56 + exit 1 57 + ;; 58 + esac 59 + done 60 + 61 + # Create the network namespaces, veth pair, and team devices in the specified 62 + # mode. 63 + # Globals: 64 + # RET - Used by test infra, set by `check_err` functions. 65 + # Arguments: 66 + # mode - The team driver mode to use for the team devices. 67 + environment_create() 68 + { 69 + trap cleanup_all_ns EXIT 70 + setup_ns ns1 ns2 71 + NS1="${NS_LIST[0]}" 72 + NS2="${NS_LIST[1]}" 73 + 74 + # Create the interfaces. 75 + ip -n "${NS1}" link add eth0 type veth peer name eth0 netns "${NS2}" 76 + ip -n "${NS1}" link add eth1 type veth peer name eth1 netns "${NS2}" 77 + ip -n "${NS1}" link add test_team1 type team 78 + ip -n "${NS2}" link add test_team2 type team 79 + 80 + # Set up the receiving network namespace's team interface. 81 + setup_team "${NS2}" test_team2 roundrobin "${NS2_IP}" \ 82 + "${PREFIX_LENGTH}" "${MEMBERS[@]}" 83 + } 84 + 85 + 86 + # Check that failover works for a specific team driver mode. 87 + # Globals: 88 + # RET - Used by test infra, set by `check_err` functions. 89 + # Arguments: 90 + # mode - The mode to set the team interfaces to. 91 + team_test_mode_failover() 92 + { 93 + local mode="$1" 94 + export RET=0 95 + 96 + # Set up the sender team with the correct mode. 97 + setup_team "${NS1}" test_team1 "${mode}" "${NS1_IP}" \ 98 + "${PREFIX_LENGTH}" "${MEMBERS[@]}" 99 + check_err $? "Failed to set up sender team" 100 + 101 + start_listening_and_sending 102 + 103 + ### Scenario 1: All interfaces initially enabled. 104 + save_tcpdump_outputs "${NS2}" "${MEMBERS[@]}" 105 + did_interface_receive eth0 "${NS2_IP}" 106 + check_err $? "eth0 not transmitting when both links enabled" 107 + did_interface_receive eth1 "${NS2_IP}" 108 + check_err $? "eth1 not transmitting when both links enabled" 109 + clear_tcpdump_outputs "${MEMBERS[@]}" 110 + 111 + ### Scenario 2: One tx-side interface disabled. 112 + ip netns exec "${NS1}" teamnl test_team1 setoption enabled false \ 113 + --port=eth1 114 + slowwait 2 bash -c "ip netns exec ${NS1} teamnl test_team1 getoption \ 115 + enabled --port=eth1 | grep -q false" 116 + 117 + save_tcpdump_outputs "${NS2}" "${MEMBERS[@]}" 118 + did_interface_receive eth0 "${NS2_IP}" 119 + check_err $? "eth0 not transmitting when enabled" 120 + did_interface_receive eth1 "${NS2_IP}" 121 + check_fail $? "eth1 IS transmitting when disabled" 122 + clear_tcpdump_outputs "${MEMBERS[@]}" 123 + 124 + ### Scenario 3: The interface is re-enabled. 125 + ip netns exec "${NS1}" teamnl test_team1 setoption enabled true \ 126 + --port=eth1 127 + slowwait 2 bash -c "ip netns exec ${NS1} teamnl test_team1 getoption \ 128 + enabled --port=eth1 | grep -q true" 129 + 130 + save_tcpdump_outputs "${NS2}" "${MEMBERS[@]}" 131 + did_interface_receive eth0 "${NS2_IP}" 132 + check_err $? "eth0 not transmitting when both links enabled" 133 + did_interface_receive eth1 "${NS2_IP}" 134 + check_err $? "eth1 not transmitting when both links enabled" 135 + clear_tcpdump_outputs "${MEMBERS[@]}" 136 + 137 + log_test "Failover of '${mode}' test" 138 + 139 + # Clean up 140 + stop_sending_and_listening 141 + } 142 + 143 + team_test_failover() 144 + { 145 + team_test_mode_failover broadcast 146 + team_test_mode_failover roundrobin 147 + team_test_mode_failover random 148 + # Don't test `activebackup` or `loadbalance` modes, since they are too 149 + # complicated for just setting `enabled` to work. They use more than 150 + # the `enabled` option for transmit. 151 + } 152 + 153 + require_command teamnl 154 + require_command iperf3 155 + require_command tcpdump 156 + environment_create 157 + tests_run 158 + exit "${EXIT_STATUS}"
+7 -2
tools/testing/selftests/net/forwarding/lib.sh
··· 1750 1750 sleep 1 1751 1751 } 1752 1752 1753 - tcpdump_stop() 1753 + tcpdump_stop_nosleep() 1754 1754 { 1755 1755 local if_name=$1 1756 1756 local pid=${cappid[$if_name]} 1757 1757 1758 1758 $ns_cmd kill "$pid" && wait "$pid" 1759 + } 1760 + 1761 + tcpdump_stop() 1762 + { 1763 + tcpdump_stop_nosleep "$1" 1759 1764 sleep 1 1760 1765 } 1761 1766 ··· 1775 1770 { 1776 1771 local if_name=$1 1777 1772 1778 - tcpdump -e -n -r ${capfile[$if_name]} 2>&1 1773 + tcpdump -e -nn -r ${capfile[$if_name]} 2>&1 1779 1774 } 1780 1775 1781 1776 # return 0 if the packet wasn't seen on host2_if or 1 if it was