Add a regression test for veth_set_channels() incorrectly reporting
LOWER_UP on a running interface whose peer is administratively down.

Test the up/up and both mixed up/down combinations with GRO enabled and
disabled. Resize the RX and TX channel counts in both directions on
each end and check LOWER_UP on each running interface. Also verify that
rejecting an out-of-range channel count leaves that state unchanged.

IFF_LOWER_UP is masked on administratively down interfaces, so do not
use it to assert their raw carrier state. Omit the down/down combination,
where neither endpoint can report LOWER_UP.

On an unpatched UML kernel the four mixed up/down cases fail. All six
cases pass with the carrier restoration fix.

Assisted-by: LLM
Signed-off-by: Xia Yan <[email protected]>
---

Notes:
    Changes in v2:
    - Limit carrier assertions to running endpoints and omit down/down, since
      IFF_LOWER_UP does not expose a down endpoint's raw carrier state.
    - Use log_test_skip() on veth creation failure to avoid a stale retmsg.
    - Include the discovery and reproduction details in the driver commit.
    - Driver code is unchanged.
    
    v1: https://lore.kernel.org/netdev/[email protected]/
    Review: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/8081
    
    Validation for the revised selftest on the original net baseline:
    - bash -n passed.
    - Unpatched UML kernel: 2 pass, 4 fail (the mixed up/down cases).
    - Patched UML kernel: 6 pass.
    - Injected veth creation failure after an earlier failed case: SKIP no
      longer repeats the earlier error; the aggregate failure is preserved.
    
    Reused the existing UML kernels; no kernel rebuild was performed for
    this revision. Prior build results and their limits remain archived.

 tools/testing/selftests/net/Makefile          |  1 +
 .../selftests/net/veth_channels_carrier.sh    | 93 +++++++++++++++++++
 2 files changed, 94 insertions(+)
 create mode 100755 tools/testing/selftests/net/veth_channels_carrier.sh

diff --git a/tools/testing/selftests/net/Makefile 
b/tools/testing/selftests/net/Makefile
index 590b33e..4004014 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -128,6 +128,7 @@ TEST_PROGS := \
        udpgso_bench.sh \
        unicast_extensions.sh \
        veth.sh \
+       veth_channels_carrier.sh \
        vlan_bridge_binding.sh \
        vlan_hw_filter.sh \
        vrf-xfrm-tests.sh \
diff --git a/tools/testing/selftests/net/veth_channels_carrier.sh 
b/tools/testing/selftests/net/veth_channels_carrier.sh
new file mode 100755
index 0000000..03c2995
--- /dev/null
+++ b/tools/testing/selftests/net/veth_channels_carrier.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
+
+require_command ip
+require_command ethtool
+
+if [ "$EUID" -ne 0 ]; then
+       echo "SKIP: root privileges are required"
+       exit "$ksft_skip"
+fi
+
+trap cleanup_all_ns EXIT
+setup_ns ns || exit $?
+
+check_carrier()
+{
+       local dev=$1
+       local state=$2
+       local expected=$3
+       local carrier=0
+       local link
+
+       # IFF_LOWER_UP is reported only for running interfaces.
+       [ "$state" = up ] || return 0
+
+       link=$(ip -n "$ns" -o link show dev "$dev")
+       check_err $? "Failed to read $dev link state"
+       [[ $link == *LOWER_UP* ]] && carrier=1
+       [ "$carrier" -eq "$expected" ]
+       check_err $? "$dev carrier is $carrier, expected $expected"
+}
+
+check_state()
+{
+       local left=$1
+       local right=$2
+       local gro=$3
+       local expected=0
+       local count dev
+
+       RET=0
+       if ! ip -n "$ns" link add vca numtxqueues 2 numrxqueues 2 \
+               type veth peer name vcb numtxqueues 2 numrxqueues 2; then
+               log_test_skip "veth carrier: $left/$right, GRO $gro"
+               return
+       fi
+
+       ip -n "$ns" link set vca "$left"
+       check_err $? "Failed to configure vca"
+       ip -n "$ns" link set vcb "$right"
+       check_err $? "Failed to configure vcb"
+       ip netns exec "$ns" ethtool -K vca gro "$gro" >/dev/null
+       check_err $? "Failed to configure GRO"
+       ip netns exec "$ns" ethtool -K vcb gro "$gro" >/dev/null
+       check_err $? "Failed to configure peer GRO"
+
+       [ "$left" = up ] && [ "$right" = up ] && expected=1
+       check_carrier vca "$left" "$expected"
+       check_carrier vcb "$right" "$expected"
+
+       for dev in vca vcb; do
+               for count in 1 2; do
+                       ip netns exec "$ns" ethtool -L "$dev" \
+                               rx "$count" tx "$count"
+                       check_err $? "Failed to resize $dev channels"
+                       check_carrier vca "$left" "$expected"
+                       check_carrier vcb "$right" "$expected"
+               done
+
+               ip netns exec "$ns" ethtool -L "$dev" rx 3 tx 3 \
+                       >/dev/null 2>&1
+               check_fail $? "Out-of-range channel counts were accepted"
+               check_carrier vca "$left" "$expected"
+               check_carrier vcb "$right" "$expected"
+       done
+
+       ip -n "$ns" link del vca
+       check_err $? "Failed to delete the veth pair"
+       log_test "veth carrier: $left/$right, GRO $gro"
+}
+
+for gro in off on; do
+       for left in down up; do
+               for right in down up; do
+                       [ "$left" = down ] && [ "$right" = down ] && continue
+                       check_state "$left" "$right" "$gro"
+               done
+       done
+done
+
+exit "$EXIT_STATUS"
-- 
2.43.0


Reply via email to