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 25export ALL_TESTS="teamd_test_active_backup" 26 27test_dir="$(dirname "$0")" 28# shellcheck disable=SC1091 29source "${test_dir}/../../../net/lib.sh" 30# shellcheck disable=SC1091 31source "${test_dir}/team_lib.sh" 32 33NS1="" 34NS2="" 35export NODAD="nodad" 36PREFIX_LENGTH="64" 37NS1_IP="fd00::1" 38NS2_IP="fd00::2" 39NS1_IP4="192.168.0.1" 40NS2_IP4="192.168.0.2" 41NS1_TEAMD_CONF="" 42NS2_TEAMD_CONF="" 43NS1_TEAMD_PID="" 44NS2_TEAMD_PID="" 45 46while 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 60done 61 62teamd_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. 89environment_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. 138environment_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. 168set_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. 185wait_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. 198teamd_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 240require_command teamd 241require_command teamdctl 242require_command iperf3 243require_command tcpdump 244environment_create activebackup 245tests_run 246exit "${EXIT_STATUS}" 247