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 test for enablement of ports with teamd

There are no tests that verify enablement and disablement of team driver
ports with teamd. This should work even with changes to the enablement
option, so it is important to test.

This test sets up an active-backup network configuration across two
network namespaces, and tries to send traffic while changing which
link is the active one.

Also increase the team test timeout to 300 seconds, because gracefully
killing teamd can take 30 seconds for each instance.

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-5-f47e7589685d@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Marc Harvey and committed by
Paolo Abeni
10407eeb 05e35244

+287
+1
tools/testing/selftests/drivers/net/team/Makefile
··· 7 7 options.sh \ 8 8 propagation.sh \ 9 9 refleak.sh \ 10 + teamd_activebackup.sh \ 10 11 transmit_failover.sh \ 11 12 # end of TEST_PROGS 12 13
+1
tools/testing/selftests/drivers/net/team/settings
··· 1 + timeout=300
+26
tools/testing/selftests/drivers/net/team/team_lib.sh
··· 146 146 false 147 147 fi 148 148 } 149 + 150 + # Return true if the given interface in the given namespace does NOT receive 151 + # traffic over a 1 second period. 152 + # Arguments: 153 + # interface - The name of the interface. 154 + # ip_address - The destination IP address. 155 + # namespace - The name of the namespace that the interface is in. 156 + check_no_traffic() 157 + { 158 + local interface="$1" 159 + local ip_address="$2" 160 + local namespace="$3" 161 + local rc 162 + 163 + save_tcpdump_outputs "${namespace}" "${interface}" 164 + did_interface_receive "${interface}" "${ip_address}" 165 + rc=$? 166 + 167 + clear_tcpdump_outputs "${interface}" 168 + 169 + if [[ "${rc}" -eq 0 ]]; then 170 + return 1 171 + else 172 + return 0 173 + fi 174 + }
+246
tools/testing/selftests/drivers/net/team/teamd_activebackup.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + # These tests verify that teamd is able to enable and disable ports via the 5 + # active backup runner. 6 + # 7 + # Topology: 8 + # 9 + # +-------------------------+ NS1 10 + # | test_team1 | 11 + # | + | 12 + # | eth0 | eth1 | 13 + # | +---+---+ | 14 + # | | | | 15 + # +-------------------------+ 16 + # | | 17 + # +-------------------------+ NS2 18 + # | | | | 19 + # | +-------+ | 20 + # | eth0 | eth1 | 21 + # | + | 22 + # | test_team2 | 23 + # +-------------------------+ 24 + 25 + export ALL_TESTS="teamd_test_active_backup" 26 + 27 + test_dir="$(dirname "$0")" 28 + # shellcheck disable=SC1091 29 + source "${test_dir}/../../../net/lib.sh" 30 + # shellcheck disable=SC1091 31 + source "${test_dir}/team_lib.sh" 32 + 33 + NS1="" 34 + NS2="" 35 + export NODAD="nodad" 36 + PREFIX_LENGTH="64" 37 + NS1_IP="fd00::1" 38 + NS2_IP="fd00::2" 39 + NS1_IP4="192.168.0.1" 40 + NS2_IP4="192.168.0.2" 41 + NS1_TEAMD_CONF="" 42 + NS2_TEAMD_CONF="" 43 + NS1_TEAMD_PID="" 44 + NS2_TEAMD_PID="" 45 + 46 + while getopts "4" opt; do 47 + case $opt in 48 + 4) 49 + echo "IPv4 mode selected." 50 + export NODAD= 51 + PREFIX_LENGTH="24" 52 + NS1_IP="${NS1_IP4}" 53 + NS2_IP="${NS2_IP4}" 54 + ;; 55 + \?) 56 + echo "Invalid option: -${OPTARG}" >&2 57 + exit 1 58 + ;; 59 + esac 60 + done 61 + 62 + teamd_config_create() 63 + { 64 + local runner=$1 65 + local dev=$2 66 + local conf 67 + 68 + conf=$(mktemp) 69 + 70 + cat > "${conf}" <<-EOF 71 + { 72 + "device": "${dev}", 73 + "runner": {"name": "${runner}"}, 74 + "ports": { 75 + "eth0": {}, 76 + "eth1": {} 77 + } 78 + } 79 + EOF 80 + echo "${conf}" 81 + } 82 + 83 + # Create the network namespaces, veth pair, and team devices in the specified 84 + # runner. 85 + # Globals: 86 + # RET - Used by test infra, set by `check_err` functions. 87 + # Arguments: 88 + # runner - The Teamd runner to use for the Team devices. 89 + environment_create() 90 + { 91 + local runner=$1 92 + 93 + echo "Setting up two-link aggregation for runner ${runner}" 94 + echo "Teamd version is: $(teamd --version)" 95 + trap environment_destroy EXIT 96 + 97 + setup_ns ns1 ns2 98 + NS1="${NS_LIST[0]}" 99 + NS2="${NS_LIST[1]}" 100 + 101 + for link in $(seq 0 1); do 102 + ip -n "${NS1}" link add "eth${link}" type veth peer name \ 103 + "eth${link}" netns "${NS2}" 104 + check_err $? "Failed to create veth pair" 105 + done 106 + 107 + NS1_TEAMD_CONF=$(teamd_config_create "${runner}" "test_team1") 108 + NS2_TEAMD_CONF=$(teamd_config_create "${runner}" "test_team2") 109 + echo "Conf files are ${NS1_TEAMD_CONF} and ${NS2_TEAMD_CONF}" 110 + 111 + ip netns exec "${NS1}" teamd -d -f "${NS1_TEAMD_CONF}" 112 + check_err $? "Failed to create team device in ${NS1}" 113 + NS1_TEAMD_PID=$(pgrep -f "teamd -d -f ${NS1_TEAMD_CONF}") 114 + 115 + ip netns exec "${NS2}" teamd -d -f "${NS2_TEAMD_CONF}" 116 + check_err $? "Failed to create team device in ${NS2}" 117 + NS2_TEAMD_PID=$(pgrep -f "teamd -d -f ${NS2_TEAMD_CONF}") 118 + 119 + echo "Created team devices" 120 + echo "Teamd PIDs are ${NS1_TEAMD_PID} and ${NS2_TEAMD_PID}" 121 + 122 + ip -n "${NS1}" link set test_team1 up 123 + check_err $? "Failed to set test_team1 up in ${NS1}" 124 + ip -n "${NS2}" link set test_team2 up 125 + check_err $? "Failed to set test_team2 up in ${NS2}" 126 + 127 + ip -n "${NS1}" addr add "${NS1_IP}/${PREFIX_LENGTH}" "${NODAD}" dev \ 128 + test_team1 129 + check_err $? "Failed to add address to team device in ${NS1}" 130 + ip -n "${NS2}" addr add "${NS2_IP}/${PREFIX_LENGTH}" "${NODAD}" dev \ 131 + test_team2 132 + check_err $? "Failed to add address to team device in ${NS2}" 133 + 134 + slowwait 2 timeout 0.5 ip netns exec "${NS1}" ping -W 1 -c 1 "${NS2_IP}" 135 + } 136 + 137 + # Tear down the environment: kill teamd and delete network namespaces. 138 + environment_destroy() 139 + { 140 + echo "Tearing down two-link aggregation" 141 + 142 + rm "${NS1_TEAMD_CONF}" 143 + rm "${NS2_TEAMD_CONF}" 144 + 145 + # First, try graceful teamd teardown. 146 + ip netns exec "${NS1}" teamd -k -t test_team1 147 + ip netns exec "${NS2}" teamd -k -t test_team2 148 + 149 + # If teamd can't be killed gracefully, then sigkill. 150 + if kill -0 "${NS1_TEAMD_PID}" 2>/dev/null; then 151 + echo "Sending sigkill to teamd for test_team1" 152 + kill -9 "${NS1_TEAMD_PID}" 153 + rm -f /var/run/teamd/test_team1.{pid,sock} 154 + fi 155 + if kill -0 "${NS2_TEAMD_PID}" 2>/dev/null; then 156 + echo "Sending sigkill to teamd for test_team2" 157 + kill -9 "${NS2_TEAMD_PID}" 158 + rm -f /var/run/teamd/test_team2.{pid,sock} 159 + fi 160 + cleanup_all_ns 161 + } 162 + 163 + # Change the active port for an active-backup mode team. 164 + # Arguments: 165 + # namespace - The network namespace that the team is in. 166 + # team - The name of the team. 167 + # active_port - The port to make active. 168 + set_active_port() 169 + { 170 + local namespace=$1 171 + local team=$2 172 + local active_port=$3 173 + 174 + ip netns exec "${namespace}" teamdctl "${team}" state item set \ 175 + runner.active_port "${active_port}" 176 + slowwait 2 bash -c "ip netns exec ${namespace} teamdctl ${team} state \ 177 + item get runner.active_port | grep -q ${active_port}" 178 + } 179 + 180 + # Wait for an interface to stop receiving traffic. If it keeps receiving traffic 181 + # for the duration of the timeout, then return an error. 182 + # Arguments: 183 + # - namespace - The network namespace that the interface is in. 184 + # - interface - The name of the interface. 185 + wait_to_stop_receiving() 186 + { 187 + local namespace=$1 188 + local interface=$2 189 + 190 + echo "Waiting for ${interface} in ${namespace} to stop receiving" 191 + slowwait 10 check_no_traffic "${interface}" "${NS2_IP}" \ 192 + "${namespace}" 193 + } 194 + 195 + # Test that active backup runner can change active ports. 196 + # Globals: 197 + # RET - Used by test infra, set by `check_err` functions. 198 + teamd_test_active_backup() 199 + { 200 + export RET=0 201 + 202 + start_listening_and_sending 203 + 204 + ### Scenario 1: Don't manually set active port, just make sure team 205 + # works. 206 + save_tcpdump_outputs "${NS2}" test_team2 207 + did_interface_receive test_team2 "${NS2_IP}" 208 + check_err $? "Traffic did not reach team interface in NS2." 209 + clear_tcpdump_outputs test_team2 210 + 211 + ### Scenario 2: Choose active port. 212 + set_active_port "${NS1}" test_team1 eth1 213 + set_active_port "${NS2}" test_team2 eth1 214 + 215 + wait_to_stop_receiving "${NS2}" eth0 216 + save_tcpdump_outputs "${NS2}" eth0 eth1 217 + did_interface_receive eth0 "${NS2_IP}" 218 + check_fail $? "eth0 IS transmitting when inactive" 219 + did_interface_receive eth1 "${NS2_IP}" 220 + check_err $? "eth1 not transmitting when active" 221 + clear_tcpdump_outputs eth0 eth1 222 + 223 + ### Scenario 3: Change active port. 224 + set_active_port "${NS1}" test_team1 eth0 225 + set_active_port "${NS2}" test_team2 eth0 226 + 227 + wait_to_stop_receiving "${NS2}" eth1 228 + save_tcpdump_outputs "${NS2}" eth0 eth1 229 + did_interface_receive eth0 "${NS2_IP}" 230 + check_err $? "eth0 not transmitting when active" 231 + did_interface_receive eth1 "${NS2_IP}" 232 + check_fail $? "eth1 IS transmitting when inactive" 233 + clear_tcpdump_outputs eth0 eth1 234 + 235 + log_test "teamd active backup runner test" 236 + 237 + stop_sending_and_listening 238 + } 239 + 240 + require_command teamd 241 + require_command teamdctl 242 + require_command iperf3 243 + require_command tcpdump 244 + environment_create activebackup 245 + tests_run 246 + exit "${EXIT_STATUS}"
+13
tools/testing/selftests/net/lib.sh
··· 224 224 NS_LIST+=("${ns_list[@]}") 225 225 } 226 226 227 + in_all_ns() 228 + { 229 + local ret=0 230 + local ns_list=("${NS_LIST[@]}") 231 + 232 + for ns in "${ns_list[@]}"; do 233 + ip netns exec "${ns}" "$@" 234 + (( ret = ret || $? )) 235 + done 236 + 237 + return "${ret}" 238 + } 239 + 227 240 # Create netdevsim with given id and net namespace. 228 241 create_netdevsim() { 229 242 local id="$1"