On 4/9/26 4:59 AM, Marc Harvey wrote:
> 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 <[email protected]>
> ---
> Changes in v7:
> - Increase test timeout to 300 seconds, since terminating teamd can
>   take 30 seconds during test cleanup.
> - Link to v6: 
> https://lore.kernel.org/netdev/[email protected]/
> 
> Changes in v6:
> - Remove manual changing of member port states to UP, not needed.
> - Link to v5: 
> https://lore.kernel.org/netdev/[email protected]/
> 
> Changes in v5:
> - Make test wait for inactive link to stop receiving traffic after
>   setting it to inactive, since there was a race condition.
> - Change test teardown to try graceful shutdown first, then use
>   sigkill if needed.
> - Manually delete leftover teamd files during teardown.
> - Use tcpdump instead of checking rx counters.
> - Link to v4: 
> https://lore.kernel.org/netdev/[email protected]/
> 
> Changed in v3:
> - Make test cleanup kill teamd instead of terminate.
> - Link to v2: 
> https://lore.kernel.org/netdev/[email protected]/
> 
> Changes in v2:
> - Fix shellcheck failures.
> - Remove dependency on net forwarding lib and pipe viewer tools.
> - Use iperf3 for tcp instead of netcat.
> - Link to v1: 
> https://lore.kernel.org/all/[email protected]/
> ---
>  tools/testing/selftests/drivers/net/team/Makefile  |   1 +
>  tools/testing/selftests/drivers/net/team/settings  |   1 +
>  .../testing/selftests/drivers/net/team/team_lib.sh |  26 +++
>  .../drivers/net/team/teamd_activebackup.sh         | 246 
> +++++++++++++++++++++
>  tools/testing/selftests/net/lib.sh                 |  13 ++
>  5 files changed, 287 insertions(+)
> 
> diff --git a/tools/testing/selftests/drivers/net/team/Makefile 
> b/tools/testing/selftests/drivers/net/team/Makefile
> index 777da2e0429e..dab922d7f83d 100644
> --- a/tools/testing/selftests/drivers/net/team/Makefile
> +++ b/tools/testing/selftests/drivers/net/team/Makefile
> @@ -7,6 +7,7 @@ TEST_PROGS := \
>       options.sh \
>       propagation.sh \
>       refleak.sh \
> +     teamd_activebackup.sh \
>       transmit_failover.sh \
>  # end of TEST_PROGS
>  
> diff --git a/tools/testing/selftests/drivers/net/team/settings 
> b/tools/testing/selftests/drivers/net/team/settings
> new file mode 100644
> index 000000000000..694d70710ff0
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/team/settings
> @@ -0,0 +1 @@
> +timeout=300
> diff --git a/tools/testing/selftests/drivers/net/team/team_lib.sh 
> b/tools/testing/selftests/drivers/net/team/team_lib.sh
> index 2057f5edee79..02ef0ee02d6a 100644
> --- a/tools/testing/selftests/drivers/net/team/team_lib.sh
> +++ b/tools/testing/selftests/drivers/net/team/team_lib.sh
> @@ -146,3 +146,29 @@ did_interface_receive()
>               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
> +}
> diff --git a/tools/testing/selftests/drivers/net/team/teamd_activebackup.sh 
> b/tools/testing/selftests/drivers/net/team/teamd_activebackup.sh
> new file mode 100755
> index 000000000000..2b26a697e179
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/net/team/teamd_activebackup.sh
> @@ -0,0 +1,246 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +
> +# These tests verify that teamd is able to enable and disable ports via the
> +# active backup runner.
> +#
> +# Topology:
> +#
> +#  +-------------------------+  NS1
> +#  |        test_team1       |
> +#  |            +            |
> +#  |      eth0  |  eth1      |
> +#  |        +---+---+        |
> +#  |        |       |        |
> +#  +-------------------------+
> +#           |       |
> +#  +-------------------------+  NS2
> +#  |        |       |        |
> +#  |        +-------+        |
> +#  |      eth0  |  eth1      |
> +#  |            +            |
> +#  |        test_team2       |
> +#  +-------------------------+
> +
> +export ALL_TESTS="teamd_test_active_backup"
> +
> +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"
> +NS1_TEAMD_CONF=""
> +NS2_TEAMD_CONF=""
> +NS1_TEAMD_PID=""
> +NS2_TEAMD_PID=""
> +
> +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
> +
> +teamd_config_create()
> +{
> +     local runner=$1
> +     local dev=$2
> +     local conf
> +
> +     conf=$(mktemp)
> +
> +     cat > "${conf}" <<-EOF
> +     {
> +             "device": "${dev}",
> +             "runner": {"name": "${runner}"},
> +             "ports": {
> +                     "eth0": {},
> +                     "eth1": {}
> +             }
> +     }
> +     EOF
> +     echo "${conf}"
> +}
> +
> +# Create the network namespaces, veth pair, and team devices in the specified
> +# runner.
> +# Globals:
> +#   RET - Used by test infra, set by `check_err` functions.
> +# Arguments:
> +#   runner - The Teamd runner to use for the Team devices.
> +environment_create()
> +{
> +     local runner=$1
> +
> +     echo "Setting up two-link aggregation for runner ${runner}"
> +     echo "Teamd version is: $(teamd --version)"
> +     trap environment_destroy EXIT
> +
> +     setup_ns ns1 ns2
> +     NS1="${NS_LIST[0]}"
> +     NS2="${NS_LIST[1]}"
> +
> +     for link in $(seq 0 1); do
> +             ip -n "${NS1}" link add "eth${link}" type veth peer name \
> +                             "eth${link}" netns "${NS2}"
> +             check_err $? "Failed to create veth pair"
> +     done
> +
> +     NS1_TEAMD_CONF=$(teamd_config_create "${runner}" "test_team1")
> +     NS2_TEAMD_CONF=$(teamd_config_create "${runner}" "test_team2")
> +     echo "Conf files are ${NS1_TEAMD_CONF} and ${NS2_TEAMD_CONF}"
> +
> +     ip netns exec "${NS1}" teamd -d -f "${NS1_TEAMD_CONF}"
> +     check_err $? "Failed to create team device in ${NS1}"
> +     NS1_TEAMD_PID=$(pgrep -f "teamd -d -f ${NS1_TEAMD_CONF}")
> +
> +     ip netns exec "${NS2}" teamd -d -f "${NS2_TEAMD_CONF}"
> +     check_err $? "Failed to create team device in ${NS2}"
> +     NS2_TEAMD_PID=$(pgrep -f "teamd -d -f ${NS2_TEAMD_CONF}")
> +
> +     echo "Created team devices"
> +     echo "Teamd PIDs are ${NS1_TEAMD_PID} and ${NS2_TEAMD_PID}"
> +
> +     ip -n "${NS1}" link set test_team1 up
> +     check_err $? "Failed to set test_team1 up in ${NS1}"
> +     ip -n "${NS2}" link set test_team2 up
> +     check_err $? "Failed to set test_team2 up in ${NS2}"
> +
> +     ip -n "${NS1}" addr add "${NS1_IP}/${PREFIX_LENGTH}" "${NODAD}" dev \
> +                     test_team1

Note for a possible follow-up: it looks like that the above will fail with:

Error: either "local" is duplicate, or "" is garbage.

when running in ipv4 mode (not invoked by the CI/self-test infra), due
to the quotes around ${NODAD}.

/P


Reply via email to