From nobody Fri Apr 3 16:01:25 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5DEDB376BFB for ; Fri, 3 Apr 2026 07:14:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775200479; cv=none; b=h0FpI9FTfttHBx2eKFb6KOMs53RMgVykrnh09huUJZOwM5Vsy4MCqNAmW0pZUjuNQwN6mOu4+9ai/BQDKTZQKOWQC6cjcVyVxUnrCIedOyMIFbwChaj5euMCgWaH+Y5nujrIg06VyozboKtn4QqDfY4NFhf5uRyOEQOPnxjp7nU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775200479; c=relaxed/simple; bh=B1CUHr6cyj7dXHUCHEQXJx2KVZ46yecg3Gc0EUFXTkI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=uN24JJXqE3SpD+yukT3v1MLhEt0+ycKRYwZqPl80xTZnHdq4r7eHEgzv2Tdp3Yy/emKddjRmPgjRwrrZaMqeRZoOoUhT/Ct9i42CUbukujCeCDARfXt2V70AgtZQnC9xqhWFw244J/Mp194SHieMXavJlpJTae7HxUDkJL1LpzA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=tqzRKvC1; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--marcharvey.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="tqzRKvC1" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-1279caef718so2790893c88.1 for ; Fri, 03 Apr 2026 00:14:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775200477; x=1775805277; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=dHW/Kj+WoZEi+6uAOeMCAmInrznHjYR3guz1LxHCc1k=; b=tqzRKvC1KIhIFCvatxs4ZroZFiqLpXMBqDnEr6EuQPVKG3DWKZpKw0rguFfFE1M8zk lh3cWL4ARsb6HGrtXUbY0GWKIsQiHkx68O3HoSInaf0tSyj6THOS4T2Q661XdKSZ6Dv/ MLnGzYZc8inQuLdPoSRurOrpe5/GxcJf/myr5xCH4s66cQQ7erc8Yc7mVxEO/rROABii Jch14tvfSx5zdvIEy4VQ4yFRVooJR+lIbcoKQJF39VlFcHJ8H6oQwZ/Jf5+KWnXgmDGj bhC8dwKSMclmX+BzxSVEc9kbD5Pug/YVJpG8Ufqy24eANhe2xbQ/NLVgnLuGMvBfhfLD 0w8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775200477; x=1775805277; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=dHW/Kj+WoZEi+6uAOeMCAmInrznHjYR3guz1LxHCc1k=; b=RSRDJF8dPhx3L/wygiFuBhaNLkexutjEq7UX8nntDycV9LkIEDAlNLxPz0hvsJSYBo hAsMrernVgpePiI6N6oBtx+/wvGIABVbyVfeybakQHbs7rY+VTGcHh/VHXMVkWAF7GCw ATF8LcRbNN4b9mLebC0LAmQGirxV97RTS1KTWBQL7qlsy+oROzTkuNldEQrrzaMtzh6E Itb3QqmSvsJy2AdmfOrSTNlJvf/5Y3+PicEhgiLwiPpp4VF7X4RmQglpbh71sR9flK/u rH6yeHrjQY4+W/QTmcN3JkA9HD3jdk5NtpUpUcaDO36sR+5AtiBbbr36sfI2gex52GGX efRg== X-Forwarded-Encrypted: i=1; AJvYcCXohhIXp24rjYAJlKBwYmHLp3muSDLCyNT6r8b3hjhwm1HvpPtTMwd5gFPcyov/YwQz+hR39/FRcl+pWUo=@vger.kernel.org X-Gm-Message-State: AOJu0YxSd79j+GQvY9TIAg6hd5+EYVrrkdrPHbaVRrRaFKcNDsfPE4Sw zWuWijpX2n446wE2BsWF2iKu1OrpFkoxkUTF7SDNAG3wEh2DhnBHOnQwBCT1BlJ/GPX/YO6I3Q1 fmOM3BGZcEvBCcDqIzj6CdA== X-Received: from dlak22.prod.google.com ([2002:a05:701b:2916:b0:12a:6d14:dfd9]) (user=marcharvey job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:929:b0:127:380e:ff5a with SMTP id a92af1059eb24-12bfb73e31emr956624c88.17.1775200477366; Fri, 03 Apr 2026 00:14:37 -0700 (PDT) Date: Fri, 03 Apr 2026 07:14:26 +0000 In-Reply-To: <20260403-teaming-driver-internal-v4-0-d3032f33ca25@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260403-teaming-driver-internal-v4-0-d3032f33ca25@google.com> X-Developer-Key: i=marcharvey@google.com; a=ed25519; pk=OzOeciadbfF5Bug/4/hyEAwfrruSY4tn0Q0LocyYUL0= X-Developer-Signature: v=1; a=ed25519-sha256; t=1775200467; l=8380; i=marcharvey@google.com; s=20260401; h=from:subject:message-id; bh=B1CUHr6cyj7dXHUCHEQXJx2KVZ46yecg3Gc0EUFXTkI=; b=ozbwprojtwD9UJ4SvW3+EeQNlfHACJyBaWnDTI1Bp4UBwSkOTk+KL+z4Ki3uJB40h9XI36TUQ BhBuSjCOeJHDZbVJ0cYT4xQcRHDySEAKLq7LslClR8uvKsWTph8UVx/ X-Mailer: b4 0.14.3 Message-ID: <20260403-teaming-driver-internal-v4-5-d3032f33ca25@google.com> Subject: [PATCH net-next v4 05/10] selftests: net: Add test for enablement of ports with teamd From: Marc Harvey To: Jiri Pirko , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Shuah Khan , Simon Horman Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Marc Harvey Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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. Signed-off-by: Marc Harvey --- Changes in v4: - None Changed in v3: - Make test cleanup kill teamd instead of terminate. - Link to v2: https://lore.kernel.org/netdev/20260401-teaming-driver-intern= al-v2-5-f80c1291727b@google.com/ 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/20260331053353.2504254-6-marcharv= ey@google.com/ --- tools/testing/selftests/drivers/net/team/Makefile | 1 + .../drivers/net/team/teamd_activebackup.sh | 217 +++++++++++++++++= ++++ tools/testing/selftests/net/lib.sh | 13 ++ 3 files changed, 231 insertions(+) diff --git a/tools/testing/selftests/drivers/net/team/Makefile b/tools/test= ing/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 :=3D \ options.sh \ propagation.sh \ refleak.sh \ + teamd_activebackup.sh \ transmit_failover.sh \ # end of TEST_PROGS =20 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..aa882e1ee3d8 --- /dev/null +++ b/tools/testing/selftests/drivers/net/team/teamd_activebackup.sh @@ -0,0 +1,217 @@ +#!/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=3D"teamd_test_active_backup" + +test_dir=3D"$(dirname "$0")" +# shellcheck disable=3DSC1091 +source "${test_dir}/../../../net/lib.sh" +# shellcheck disable=3DSC1091 +source "${test_dir}/team_lib.sh" + +NS1=3D"" +NS2=3D"" +export NODAD=3D"nodad" +PREFIX_LENGTH=3D"64" +NS1_IP=3D"fd00::1" +NS2_IP=3D"fd00::2" +NS1_IP4=3D"192.168.0.1" +NS2_IP4=3D"192.168.0.2" +NS1_TEAMD_CONF=3D"" +NS2_TEAMD_CONF=3D"" +NS1_TEAMD_PID=3D"" +NS2_TEAMD_PID=3D"" + +while getopts "4" opt; do + case $opt in + 4) + echo "IPv4 mode selected." + export NODAD=3D + PREFIX_LENGTH=3D"24" + NS1_IP=3D"${NS1_IP4}" + NS2_IP=3D"${NS2_IP4}" + ;; + \?) + echo "Invalid option: -${OPTARG}" >&2 + exit 1 + ;; + esac +done + +teamd_config_create() +{ + local runner=3D$1 + local dev=3D$2 + local conf + + conf=3D$(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 specif= ied +# 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=3D$1 + + echo "Setting up two-link aggregation for runner ${runner}" + trap environment_destroy EXIT + + setup_ns ns1 ns2 + NS1=3D"${NS_LIST[0]}" + NS2=3D"${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=3D$(teamd_config_create "${runner}" "test_team1") + NS2_TEAMD_CONF=3D$(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=3D$(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=3D$(pgrep -f "teamd -d -f ${NS2_TEAMD_CONF}") + + echo "Created team devices" + + rm "${NS1_TEAMD_CONF}" + rm "${NS2_TEAMD_CONF}" + NS1_TEAMD_CONF=3D"" + NS2_TEAMD_CONF=3D"" + + for link in $(seq 0 1); do + in_all_ns "ip link set eth${link} up" + check_err $? "Failed to set eth${link} up" + done + + 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 + check_err $? "Failed to add address to team device in ${NS1}" + ip -n "${NS2}" addr add "${NS2_IP}/${PREFIX_LENGTH}" "${NODAD}" dev \ + test_team2 + check_err $? "Failed to add address to team device in ${NS2}" + + slowwait 2 timeout 0.5 ip netns exec "${NS1}" ping -W 1 -c 1 "${NS2_IP}" +} + +# Tear down the environment: kill teamd and delete network namespaces. +environment_destroy() +{ + echo "Tearing down two-link aggregation" + if [ -n "${NS1_TEAMD_PID}" ]; then + kill -9 "${NS1_TEAMD_PID}" 2>/dev/null + fi + if [ -n "${NS2_TEAMD_PID}" ]; then + kill -9 "${NS2_TEAMD_PID}" 2>/dev/null + fi + cleanup_all_ns +} + +# Change the active port for an active-backup mode team. +# Arguments: +# namespace - The network namespace that the team is in. +# team - The name of the team. +# active_port - The port to make active. +set_active_port() +{ + local namespace=3D$1 + local team=3D$2 + local active_port=3D$3 + + ip netns exec "${namespace}" teamdctl "${team}" state item set \ + runner.active_port "${active_port}" + slowwait 2 bash -c "ip netns exec ${namespace} teamdctl ${team} state \ + item get runner.active_port | grep -q ${active_port}" +} + +# Test that active backup runner can change active ports. +# Globals: +# RET - Used by test infra, set by `check_err` functions. +teamd_test_active_backup() +{ + export RET=3D0 + + start_listening_and_sending + + ### Scenario 1: Don't manually set active port, just make sure team + # works. + did_interface_receive test_team2 "${NS2}" + check_err $? "Traffic did not reach team interface in NS2." + + ### Scenario 2: Choose active port. + set_active_port "${NS1}" test_team1 eth1 + set_active_port "${NS2}" test_team2 eth1 + + did_interface_receive eth0 "${NS2}" + check_fail $? "eth0 IS transmitting when disabled" + did_interface_receive eth1 "${NS2}" + check_err $? "eth1 not transmitting when enabled" + + ### Scenario 3: Change active port. + set_active_port "${NS1}" test_team1 eth0 + set_active_port "${NS2}" test_team2 eth0 + + did_interface_receive eth0 "${NS2}" + check_err $? "eth0 not transmitting when enabled" + did_interface_receive eth1 "${NS2}" + check_fail $? "eth1 IS transmitting when disabled" + + log_test "teamd active backup runner test" + + stop_sending_and_listening +} + +require_command teamd +require_command teamdctl +require_command iperf3 +environment_create activebackup +tests_run +exit "${EXIT_STATUS}" diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/n= et/lib.sh index e915386daf1b..8efa782dd4fd 100644 --- a/tools/testing/selftests/net/lib.sh +++ b/tools/testing/selftests/net/lib.sh @@ -224,6 +224,19 @@ setup_ns() NS_LIST+=3D("${ns_list[@]}") } =20 +in_all_ns() +{ + local ret=3D0 + local ns_list=3D("${NS_LIST[@]}") + + for ns in "${ns_list[@]}"; do + ip netns exec "${ns}" bash -c "$@" + (( ret =3D ret || $? )) + done + + return "${ret}" +} + # Create netdevsim with given id and net namespace. create_netdevsim() { local id=3D"$1" --=20 2.53.0.1185.g05d4b7b318-goog