1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3 4test_dir="$(dirname "$0")" 5export REQUIRE_MZ=no 6export NUM_NETIFS=0 7# shellcheck disable=SC1091 8source "${test_dir}/../../../net/forwarding/lib.sh" 9 10TCP_PORT="43434" 11 12# Create a team interface inside of a given network namespace with a given 13# mode, members, and IP address. 14# Arguments: 15# namespace - Network namespace to put the team interface into. 16# team - The name of the team interface to setup. 17# mode - The team mode of the interface. 18# ip_address - The IP address to assign to the team interface. 19# prefix_length - The prefix length for the IP address subnet. 20# $@ - members - The member interfaces of the aggregation. 21setup_team() 22{ 23 local namespace=$1 24 local team=$2 25 local mode=$3 26 local ip_address=$4 27 local prefix_length=$5 28 shift 5 29 local members=("$@") 30 31 # Prerequisite: team must have no members 32 for member in "${members[@]}"; do 33 ip -n "${namespace}" link set "${member}" nomaster 34 done 35 36 # Prerequisite: team must have no address in order to set it 37 # shellcheck disable=SC2086 38 ip -n "${namespace}" addr del "${ip_address}/${prefix_length}" \ 39 ${NODAD} dev "${team}" 40 41 echo "Setting team in ${namespace} to mode ${mode}" 42 43 if ! ip -n "${namespace}" link set "${team}" down; then 44 echo "Failed to bring team device down" 45 return 1 46 fi 47 if ! ip netns exec "${namespace}" teamnl "${team}" setoption mode \ 48 "${mode}"; then 49 echo "Failed to set ${team} mode to '${mode}'" 50 return 1 51 fi 52 53 # Aggregate the members into teams. 54 for member in "${members[@]}"; do 55 ip -n "${namespace}" link set "${member}" master "${team}" 56 done 57 58 # Bring team devices up and give them addresses. 59 if ! ip -n "${namespace}" link set "${team}" up; then 60 echo "Failed to set ${team} up" 61 return 1 62 fi 63 64 # shellcheck disable=SC2086 65 if ! ip -n "${namespace}" addr add "${ip_address}/${prefix_length}" \ 66 ${NODAD} dev "${team}"; then 67 echo "Failed to give ${team} IP address in ${namespace}" 68 return 1 69 fi 70} 71 72# This is global used to keep track of the sender's iperf3 process, so that it 73# can be terminated. 74declare sender_pid 75 76# Start sending and receiving TCP traffic with iperf3. 77# Globals: 78# sender_pid - The process ID of the iperf3 sender process. Used to kill it 79# later. 80start_listening_and_sending() 81{ 82 ip netns exec "${NS2}" iperf3 -s -p "${TCP_PORT}" --logfile /dev/null & 83 # Wait for server to become reachable before starting client. 84 slowwait 5 ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p \ 85 "${TCP_PORT}" -t 1 --logfile /dev/null 86 ip netns exec "${NS1}" iperf3 -c "${NS2_IP}" -p "${TCP_PORT}" -b 1M -l \ 87 1K -t 0 --logfile /dev/null & 88 sender_pid=$! 89} 90 91# Stop sending TCP traffic with iperf3. 92# Globals: 93# sender_pid - The process ID of the iperf3 sender process. 94stop_sending_and_listening() 95{ 96 kill "${sender_pid}" && wait "${sender_pid}" 2>/dev/null || true 97} 98 99# Monitor for TCP traffic with Tcpdump, save results to temp files. 100# Arguments: 101# namespace - The network namespace to run tcpdump inside of. 102# $@ - interfaces - The interfaces to listen to. 103save_tcpdump_outputs() 104{ 105 local namespace=$1 106 shift 1 107 local interfaces=("$@") 108 109 for interface in "${interfaces[@]}"; do 110 tcpdump_start "${interface}" "${namespace}" 111 done 112 113 sleep 1 114 115 for interface in "${interfaces[@]}"; do 116 tcpdump_stop_nosleep "${interface}" 117 done 118} 119 120clear_tcpdump_outputs() 121{ 122 local interfaces=("$@") 123 124 for interface in "${interfaces[@]}"; do 125 tcpdump_cleanup "${interface}" 126 done 127} 128 129# Read Tcpdump output, determine packet counts. 130# Arguments: 131# interface - The name of the interface to count packets for. 132# ip_address - The destination IP address. 133did_interface_receive() 134{ 135 local interface="$1" 136 local ip_address="$2" 137 local packet_count 138 139 packet_count=$(tcpdump_show "$interface" | grep -c \ 140 "> ${ip_address}.${TCP_PORT}") 141 echo "Packet count for ${interface} was ${packet_count}" 142 143 if [[ "${packet_count}" -gt 0 ]]; then 144 true 145 else 146 false 147 fi 148} 149 150# Return true if the given interface in the given namespace does NOT receive 151# traffic over a 1 second period. 152# Arguments: 153# interface - The name of the interface. 154# ip_address - The destination IP address. 155# namespace - The name of the namespace that the interface is in. 156check_no_traffic() 157{ 158 local interface="$1" 159 local ip_address="$2" 160 local namespace="$3" 161 local rc 162 163 save_tcpdump_outputs "${namespace}" "${interface}" 164 did_interface_receive "${interface}" "${ip_address}" 165 rc=$? 166 167 clear_tcpdump_outputs "${interface}" 168 169 if [[ "${rc}" -eq 0 ]]; then 170 return 1 171 else 172 return 0 173 fi 174} 175