#!/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 }