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