xref: /linux/tools/testing/selftests/drivers/net/team/team_lib.sh (revision 91a4855d6c03e770e42f17c798a36a3c46e63de2)
105e35244SMarc Harvey#!/bin/bash
205e35244SMarc Harvey# SPDX-License-Identifier: GPL-2.0
305e35244SMarc Harvey
405e35244SMarc Harveytest_dir="$(dirname "$0")"
505e35244SMarc Harveyexport REQUIRE_MZ=no
605e35244SMarc Harveyexport NUM_NETIFS=0
705e35244SMarc Harvey# shellcheck disable=SC1091
805e35244SMarc Harveysource "${test_dir}/../../../net/forwarding/lib.sh"
905e35244SMarc Harvey
1005e35244SMarc HarveyTCP_PORT="43434"
1105e35244SMarc Harvey
1205e35244SMarc Harvey# Create a team interface inside of a given network namespace with a given
1305e35244SMarc Harvey# mode, members, and IP address.
1405e35244SMarc Harvey# Arguments:
1505e35244SMarc Harvey#  namespace - Network namespace to put the team interface into.
1605e35244SMarc Harvey#  team - The name of the team interface to setup.
1705e35244SMarc Harvey#  mode - The team mode of the interface.
1805e35244SMarc Harvey#  ip_address - The IP address to assign to the team interface.
1905e35244SMarc Harvey#  prefix_length - The prefix length for the IP address subnet.
2005e35244SMarc Harvey#  $@ - members - The member interfaces of the aggregation.
2105e35244SMarc Harveysetup_team()
2205e35244SMarc Harvey{
2305e35244SMarc Harvey	local namespace=$1
2405e35244SMarc Harvey	local team=$2
2505e35244SMarc Harvey	local mode=$3
2605e35244SMarc Harvey	local ip_address=$4
2705e35244SMarc Harvey	local prefix_length=$5
2805e35244SMarc Harvey	shift 5
2905e35244SMarc Harvey	local members=("$@")
3005e35244SMarc Harvey
3105e35244SMarc Harvey	# Prerequisite: team must have no members
3205e35244SMarc Harvey	for member in "${members[@]}"; do
3305e35244SMarc Harvey		ip -n "${namespace}" link set "${member}" nomaster
3405e35244SMarc Harvey	done
3505e35244SMarc Harvey
3605e35244SMarc Harvey	# Prerequisite: team must have no address in order to set it
3705e35244SMarc Harvey	# shellcheck disable=SC2086
3805e35244SMarc Harvey	ip -n "${namespace}" addr del "${ip_address}/${prefix_length}" \
3905e35244SMarc Harvey			${NODAD} dev "${team}"
4005e35244SMarc Harvey
4105e35244SMarc Harvey	echo "Setting team in ${namespace} to mode ${mode}"
4205e35244SMarc Harvey
4305e35244SMarc Harvey	if ! ip -n "${namespace}" link set "${team}" down; then
4405e35244SMarc Harvey		echo "Failed to bring team device down"
4505e35244SMarc Harvey		return 1
4605e35244SMarc Harvey	fi
4705e35244SMarc Harvey	if ! ip netns exec "${namespace}" teamnl "${team}" setoption mode \
4805e35244SMarc Harvey			"${mode}"; then
4905e35244SMarc Harvey		echo "Failed to set ${team} mode to '${mode}'"
5005e35244SMarc Harvey		return 1
5105e35244SMarc Harvey	fi
5205e35244SMarc Harvey
5305e35244SMarc Harvey	# Aggregate the members into teams.
5405e35244SMarc Harvey	for member in "${members[@]}"; do
5505e35244SMarc Harvey		ip -n "${namespace}" link set "${member}" master "${team}"
5605e35244SMarc Harvey	done
5705e35244SMarc Harvey
5805e35244SMarc Harvey	# Bring team devices up and give them addresses.
5905e35244SMarc Harvey	if ! ip -n "${namespace}" link set "${team}" up; then
6005e35244SMarc Harvey		echo "Failed to set ${team} up"
6105e35244SMarc Harvey		return 1
6205e35244SMarc Harvey	fi
6305e35244SMarc Harvey
6405e35244SMarc Harvey	# shellcheck disable=SC2086
6505e35244SMarc Harvey	if ! ip -n "${namespace}" addr add "${ip_address}/${prefix_length}" \
6605e35244SMarc Harvey			${NODAD} dev "${team}"; then
6705e35244SMarc Harvey		echo "Failed to give ${team} IP address in ${namespace}"
6805e35244SMarc Harvey		return 1
6905e35244SMarc Harvey	fi
7005e35244SMarc Harvey}
7105e35244SMarc Harvey
7205e35244SMarc Harvey# This is global used to keep track of the sender's iperf3 process, so that it
7305e35244SMarc Harvey# can be terminated.
7405e35244SMarc Harveydeclare sender_pid
7505e35244SMarc Harvey
7605e35244SMarc Harvey# Start sending and receiving TCP traffic with iperf3.
7705e35244SMarc Harvey# Globals:
7805e35244SMarc Harvey#  sender_pid - The process ID of the iperf3 sender process. Used to kill it
7905e35244SMarc Harvey#  later.
8005e35244SMarc Harveystart_listening_and_sending()
8105e35244SMarc Harvey{
8205e35244SMarc Harvey	ip netns exec "${NS2}" iperf3 -s -p "${TCP_PORT}" --logfile /dev/null &
8305e35244SMarc Harvey	# Wait for server to become reachable before starting client.
8405e35244SMarc Harvey	slowwait 5 ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p \
8505e35244SMarc Harvey			"${TCP_PORT}" -t 1 --logfile /dev/null
8605e35244SMarc Harvey	ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p "${TCP_PORT}" -b 1M -l \
8705e35244SMarc Harvey			1K -t 0 --logfile /dev/null &
8805e35244SMarc Harvey	sender_pid=$!
8905e35244SMarc Harvey}
9005e35244SMarc Harvey
9105e35244SMarc Harvey# Stop sending TCP traffic with iperf3.
9205e35244SMarc Harvey# Globals:
9305e35244SMarc Harvey#   sender_pid - The process ID of the iperf3 sender process.
9405e35244SMarc Harveystop_sending_and_listening()
9505e35244SMarc Harvey{
9605e35244SMarc Harvey	kill "${sender_pid}" && wait "${sender_pid}" 2>/dev/null || true
9705e35244SMarc Harvey}
9805e35244SMarc Harvey
9905e35244SMarc Harvey# Monitor for TCP traffic with Tcpdump, save results to temp files.
10005e35244SMarc Harvey# Arguments:
10105e35244SMarc Harvey#   namespace - The network namespace to run tcpdump inside of.
10205e35244SMarc Harvey#   $@ - interfaces - The interfaces to listen to.
10305e35244SMarc Harveysave_tcpdump_outputs()
10405e35244SMarc Harvey{
10505e35244SMarc Harvey	local namespace=$1
10605e35244SMarc Harvey	shift 1
10705e35244SMarc Harvey	local interfaces=("$@")
10805e35244SMarc Harvey
10905e35244SMarc Harvey	for interface in "${interfaces[@]}"; do
11005e35244SMarc Harvey		tcpdump_start "${interface}" "${namespace}"
11105e35244SMarc Harvey	done
11205e35244SMarc Harvey
11305e35244SMarc Harvey	sleep 1
11405e35244SMarc Harvey
11505e35244SMarc Harvey	for interface in "${interfaces[@]}"; do
11605e35244SMarc Harvey		tcpdump_stop_nosleep "${interface}"
11705e35244SMarc Harvey	done
11805e35244SMarc Harvey}
11905e35244SMarc Harvey
12005e35244SMarc Harveyclear_tcpdump_outputs()
12105e35244SMarc Harvey{
12205e35244SMarc Harvey	local interfaces=("$@")
12305e35244SMarc Harvey
12405e35244SMarc Harvey	for interface in "${interfaces[@]}"; do
12505e35244SMarc Harvey		tcpdump_cleanup "${interface}"
12605e35244SMarc Harvey	done
12705e35244SMarc Harvey}
12805e35244SMarc Harvey
12905e35244SMarc Harvey# Read Tcpdump output, determine packet counts.
13005e35244SMarc Harvey# Arguments:
13105e35244SMarc Harvey#   interface - The name of the interface to count packets for.
13205e35244SMarc Harvey#   ip_address - The destination IP address.
13305e35244SMarc Harveydid_interface_receive()
13405e35244SMarc Harvey{
13505e35244SMarc Harvey	local interface="$1"
13605e35244SMarc Harvey	local ip_address="$2"
13705e35244SMarc Harvey	local packet_count
13805e35244SMarc Harvey
13905e35244SMarc Harvey	packet_count=$(tcpdump_show "$interface" | grep -c \
14005e35244SMarc Harvey			"> ${ip_address}.${TCP_PORT}")
14105e35244SMarc Harvey	echo "Packet count for ${interface} was ${packet_count}"
14205e35244SMarc Harvey
14305e35244SMarc Harvey	if [[ "${packet_count}" -gt 0 ]]; then
14405e35244SMarc Harvey		true
14505e35244SMarc Harvey	else
14605e35244SMarc Harvey		false
14705e35244SMarc Harvey	fi
14805e35244SMarc Harvey}
149*10407eebSMarc Harvey
150*10407eebSMarc Harvey# Return true if the given interface in the given namespace does NOT receive
151*10407eebSMarc Harvey# traffic over a 1 second period.
152*10407eebSMarc Harvey# Arguments:
153*10407eebSMarc Harvey#   interface - The name of the interface.
154*10407eebSMarc Harvey#   ip_address - The destination IP address.
155*10407eebSMarc Harvey#   namespace - The name of the namespace that the interface is in.
156*10407eebSMarc Harveycheck_no_traffic()
157*10407eebSMarc Harvey{
158*10407eebSMarc Harvey	local interface="$1"
159*10407eebSMarc Harvey	local ip_address="$2"
160*10407eebSMarc Harvey	local namespace="$3"
161*10407eebSMarc Harvey	local rc
162*10407eebSMarc Harvey
163*10407eebSMarc Harvey	save_tcpdump_outputs "${namespace}" "${interface}"
164*10407eebSMarc Harvey	did_interface_receive "${interface}" "${ip_address}"
165*10407eebSMarc Harvey	rc=$?
166*10407eebSMarc Harvey
167*10407eebSMarc Harvey	clear_tcpdump_outputs "${interface}"
168*10407eebSMarc Harvey
169*10407eebSMarc Harvey	if [[ "${rc}" -eq 0 ]]; then
170*10407eebSMarc Harvey		return 1
171*10407eebSMarc Harvey	else
172*10407eebSMarc Harvey		return 0
173*10407eebSMarc Harvey	fi
174*10407eebSMarc Harvey}
175