linux/tools/testing/selftests/drivers/net/team/team_lib.sh
Marc Harvey 10407eebe8 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>
2026-04-13 15:09:49 +02:00

175 lines
4.4 KiB
Bash

#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
test_dir="$(dirname "$0")"
export REQUIRE_MZ=no
export NUM_NETIFS=0
# shellcheck disable=SC1091
source "${test_dir}/../../../net/forwarding/lib.sh"
TCP_PORT="43434"
# Create a team interface inside of a given network namespace with a given
# mode, members, and IP address.
# Arguments:
# namespace - Network namespace to put the team interface into.
# team - The name of the team interface to setup.
# mode - The team mode of the interface.
# ip_address - The IP address to assign to the team interface.
# prefix_length - The prefix length for the IP address subnet.
# $@ - members - The member interfaces of the aggregation.
setup_team()
{
local namespace=$1
local team=$2
local mode=$3
local ip_address=$4
local prefix_length=$5
shift 5
local members=("$@")
# Prerequisite: team must have no members
for member in "${members[@]}"; do
ip -n "${namespace}" link set "${member}" nomaster
done
# Prerequisite: team must have no address in order to set it
# shellcheck disable=SC2086
ip -n "${namespace}" addr del "${ip_address}/${prefix_length}" \
${NODAD} dev "${team}"
echo "Setting team in ${namespace} to mode ${mode}"
if ! ip -n "${namespace}" link set "${team}" down; then
echo "Failed to bring team device down"
return 1
fi
if ! ip netns exec "${namespace}" teamnl "${team}" setoption mode \
"${mode}"; then
echo "Failed to set ${team} mode to '${mode}'"
return 1
fi
# Aggregate the members into teams.
for member in "${members[@]}"; do
ip -n "${namespace}" link set "${member}" master "${team}"
done
# Bring team devices up and give them addresses.
if ! ip -n "${namespace}" link set "${team}" up; then
echo "Failed to set ${team} up"
return 1
fi
# shellcheck disable=SC2086
if ! ip -n "${namespace}" addr add "${ip_address}/${prefix_length}" \
${NODAD} dev "${team}"; then
echo "Failed to give ${team} IP address in ${namespace}"
return 1
fi
}
# This is global used to keep track of the sender's iperf3 process, so that it
# can be terminated.
declare sender_pid
# Start sending and receiving TCP traffic with iperf3.
# Globals:
# sender_pid - The process ID of the iperf3 sender process. Used to kill it
# later.
start_listening_and_sending()
{
ip netns exec "${NS2}" iperf3 -s -p "${TCP_PORT}" --logfile /dev/null &
# Wait for server to become reachable before starting client.
slowwait 5 ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p \
"${TCP_PORT}" -t 1 --logfile /dev/null
ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p "${TCP_PORT}" -b 1M -l \
1K -t 0 --logfile /dev/null &
sender_pid=$!
}
# Stop sending TCP traffic with iperf3.
# Globals:
# sender_pid - The process ID of the iperf3 sender process.
stop_sending_and_listening()
{
kill "${sender_pid}" && wait "${sender_pid}" 2>/dev/null || true
}
# Monitor for TCP traffic with Tcpdump, save results to temp files.
# Arguments:
# namespace - The network namespace to run tcpdump inside of.
# $@ - interfaces - The interfaces to listen to.
save_tcpdump_outputs()
{
local namespace=$1
shift 1
local interfaces=("$@")
for interface in "${interfaces[@]}"; do
tcpdump_start "${interface}" "${namespace}"
done
sleep 1
for interface in "${interfaces[@]}"; do
tcpdump_stop_nosleep "${interface}"
done
}
clear_tcpdump_outputs()
{
local interfaces=("$@")
for interface in "${interfaces[@]}"; do
tcpdump_cleanup "${interface}"
done
}
# Read Tcpdump output, determine packet counts.
# Arguments:
# interface - The name of the interface to count packets for.
# ip_address - The destination IP address.
did_interface_receive()
{
local interface="$1"
local ip_address="$2"
local packet_count
packet_count=$(tcpdump_show "$interface" | grep -c \
"> ${ip_address}.${TCP_PORT}")
echo "Packet count for ${interface} was ${packet_count}"
if [[ "${packet_count}" -gt 0 ]]; then
true
else
false
fi
}
# Return true if the given interface in the given namespace does NOT receive
# traffic over a 1 second period.
# Arguments:
# interface - The name of the interface.
# ip_address - The destination IP address.
# namespace - The name of the namespace that the interface is in.
check_no_traffic()
{
local interface="$1"
local ip_address="$2"
local namespace="$3"
local rc
save_tcpdump_outputs "${namespace}" "${interface}"
did_interface_receive "${interface}" "${ip_address}"
rc=$?
clear_tcpdump_outputs "${interface}"
if [[ "${rc}" -eq 0 ]]; then
return 1
else
return 0
fi
}