#!/bin/bash # SPDX-License-Identifier: GPL-2.0 # These tests verify the decoupled RX and TX enablement of team driver member # interfaces. # # Topology # # +---------------------+ NS1 # | test_team1 | # | | | # | eth0 | # | | | # | | | # +---------------------+ # | # +---------------------+ NS2 # | | | # | | | # | eth0 | # | | | # | test_team2 | # +---------------------+ export ALL_TESTS=" team_test_tx_enablement team_test_rx_enablement " test_dir="$(dirname "$0")" # shellcheck disable=SC1091 source "${test_dir}/../../../net/lib.sh" # shellcheck disable=SC1091 source "${test_dir}/team_lib.sh" NS1="" NS2="" export NODAD="nodad" PREFIX_LENGTH="64" NS1_IP="fd00::1" NS2_IP="fd00::2" NS1_IP4="192.168.0.1" NS2_IP4="192.168.0.2" MEMBERS=("eth0") PING_COUNT=5 PING_TIMEOUT_S=1 PING_INTERVAL=0.1 while getopts "4" opt; do case $opt in 4) echo "IPv4 mode selected." export NODAD= PREFIX_LENGTH="24" NS1_IP="${NS1_IP4}" NS2_IP="${NS2_IP4}" ;; \?) echo "Invalid option: -$OPTARG" >&2 exit 1 ;; esac done # This has to be sourced after opts are gathered... export REQUIRE_MZ=no export NUM_NETIFS=0 # shellcheck disable=SC1091 source "${test_dir}/../../../net/forwarding/lib.sh" # Create the network namespaces, veth pair, and team devices in the specified # mode. # Globals: # RET - Used by test infra, set by `check_err` functions. # Arguments: # mode - The team driver mode to use for the team devices. environment_create() { trap cleanup_all_ns EXIT setup_ns ns1 ns2 NS1="${NS_LIST[0]}" NS2="${NS_LIST[1]}" # Create the interfaces. ip -n "${NS1}" link add eth0 type veth peer name eth0 netns "${NS2}" ip -n "${NS1}" link add test_team1 type team ip -n "${NS2}" link add test_team2 type team # Set up the receiving network namespace's team interface. setup_team "${NS2}" test_team2 roundrobin "${NS2_IP}" \ "${PREFIX_LENGTH}" "${MEMBERS[@]}" } # Set a particular option value for team or team port. # Arguments: # namespace - The namespace name that has the team. # option_name - The option name to set. # option_value - The value to set the option to. # team_name - The name of team to set the option for. # member_name - The (optional) optional name of the member port. set_option_value() { local namespace="$1" local option_name="$2" local option_value="$3" local team_name="$4" local member_name="$5" local port_flag="--port=${member_name}" ip netns exec "${namespace}" teamnl "${team_name}" setoption \ "${option_name}" "${option_value}" "${port_flag}" return $? } # Send some pings and return the ping command return value. try_ping() { ip netns exec "${NS1}" ping -i "${PING_INTERVAL}" -c "${PING_COUNT}" \ "${NS2_IP}" -W "${PING_TIMEOUT_S}" } # Checks tcpdump output from net/forwarding lib, and checks if there are any # ICMP(4 or 6) packets. # Arguments: # interface - The interface name to search for. # ip_address - The destination IP address (4 or 6) to search for. did_interface_receive_icmp() { local interface="$1" local ip_address="$2" local packet_count packet_count=$(tcpdump_show "$interface" | grep -c \ "> ${ip_address}: ICMP") echo "Packet count for ${interface} was ${packet_count}" if [[ "$packet_count" -gt 0 ]]; then true else false fi } # Test JUST tx enablement with a given mode. # Globals: # RET - Used by test infra, set by `check_err` functions. # Arguments: # mode - The mode to set the team interfaces to. team_test_mode_tx_enablement() { local mode="$1" export RET=0 # Set up the sender team with the correct mode. setup_team "${NS1}" test_team1 "${mode}" "${NS1_IP}" \ "${PREFIX_LENGTH}" "${MEMBERS[@]}" check_err $? "Failed to set up sender team" ### Scenario 1: Member interface initially enabled. # Expect ping to pass try_ping check_err $? "Ping failed when TX enabled" ### Scenario 2: One tx-side interface disabled. # Expect ping to fail. set_option_value "${NS1}" tx_enabled false test_team1 eth0 check_err $? "Failed to disable TX" tcpdump_start eth0 "${NS2}" try_ping check_fail $? "Ping succeeded when TX disabled" tcpdump_stop eth0 # Expect no packets to be transmitted, since TX is disabled. did_interface_receive_icmp eth0 "${NS2_IP}" check_fail $? "eth0 IS transmitting when TX disabled" tcpdump_cleanup eth0 ### Scenario 3: The interface has tx re-enabled. # Expect ping to pass. set_option_value "${NS1}" tx_enabled true test_team1 eth0 check_err $? "Failed to reenable TX" try_ping check_err $? "Ping failed when TX reenabled" log_test "TX failover of '${mode}' test" } # Test JUST rx enablement with a given mode. # Globals: # RET - Used by test infra, set by `check_err` functions. # Arguments: # mode - The mode to set the team interfaces to. team_test_mode_rx_enablement() { local mode="$1" export RET=0 # Set up the sender team with the correct mode. setup_team "${NS1}" test_team1 "${mode}" "${NS1_IP}" \ "${PREFIX_LENGTH}" "${MEMBERS[@]}" check_err $? "Failed to set up sender team" ### Scenario 1: Member interface initially enabled. # Expect ping to pass try_ping check_err $? "Ping failed when RX enabled" ### Scenario 2: One rx-side interface disabled. # Expect ping to fail. set_option_value "${NS1}" rx_enabled false test_team1 eth0 check_err $? "Failed to disable RX" tcpdump_start eth0 "${NS2}" try_ping check_fail $? "Ping succeeded when RX disabled" tcpdump_stop eth0 # Expect packets to be transmitted, since only RX is disabled. did_interface_receive_icmp eth0 "${NS2_IP}" check_err $? "eth0 not transmitting when RX disabled" tcpdump_cleanup eth0 ### Scenario 3: The interface has rx re-enabled. # Expect ping to pass. set_option_value "${NS1}" rx_enabled true test_team1 eth0 check_err $? "Failed to reenable RX" try_ping check_err $? "Ping failed when RX reenabled" log_test "RX failover of '${mode}' test" } team_test_tx_enablement() { team_test_mode_tx_enablement broadcast team_test_mode_tx_enablement roundrobin team_test_mode_tx_enablement random } team_test_rx_enablement() { team_test_mode_rx_enablement broadcast team_test_mode_rx_enablement roundrobin team_test_mode_rx_enablement random } require_command teamnl require_command tcpdump require_command ping environment_create tests_run exit "${EXIT_STATUS}"