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