mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
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>
175 lines
4.4 KiB
Bash
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
|
|
}
|