xref: /linux/tools/testing/selftests/drivers/net/team/team_lib.sh (revision 91a4855d6c03e770e42f17c798a36a3c46e63de2)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4test_dir="$(dirname "$0")"
5export REQUIRE_MZ=no
6export NUM_NETIFS=0
7# shellcheck disable=SC1091
8source "${test_dir}/../../../net/forwarding/lib.sh"
9
10TCP_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.
21setup_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.
74declare 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.
80start_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.
94stop_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.
103save_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
120clear_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.
133did_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}
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.
156check_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}
175