aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-01-06 18:04:02 -0800
committerJakub Kicinski <kuba@kernel.org>2026-01-06 18:04:03 -0800
commit653267321f05316f159e05b3ef562aa700632db6 (patch)
treec583be60cb6a191f2c8363139064db4572fdfc07
parent353cfc0ef3f34ef7fe313ae38dac37f2454a7cf5 (diff)
parent75df712cddfd6c76e0e255584766385648ad9529 (diff)
downloadipvs-main.tar.gz
Merge branch 'net-netdevsim-fix-inconsistent-carrier-state-after-link-unlink'HEADmain
Yohei Kojima says: ==================== net: netdevsim: fix inconsistent carrier state after link/unlink This series fixes netdevsim's inconsistent behavior between carrier and link/unlink state. More specifically, this fixes a bug that the carrier goes DOWN although two netdevsim were peered, depending on the order of peering and ifup. Especially in a NetworkManager-enabled environment, netdevsim test fails because of this. The first patch fixes the bug itself in netdevsim/bus.c by adding netif_carrier_on() into a proper function. The second patch adds a regression test for this bug. ==================== Link: https://patch.msgid.link/cover.1767624906.git.yk@y-koj.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/netdevsim/bus.c8
-rwxr-xr-xtools/testing/selftests/drivers/net/netdevsim/peer.sh59
2 files changed, 67 insertions, 0 deletions
diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c
index 70e8c38ddad6b6..d16b95304aa7e3 100644
--- a/drivers/net/netdevsim/bus.c
+++ b/drivers/net/netdevsim/bus.c
@@ -332,6 +332,11 @@ static ssize_t link_device_store(const struct bus_type *bus, const char *buf, si
rcu_assign_pointer(nsim_a->peer, nsim_b);
rcu_assign_pointer(nsim_b->peer, nsim_a);
+ if (netif_running(dev_a) && netif_running(dev_b)) {
+ netif_carrier_on(dev_a);
+ netif_carrier_on(dev_b);
+ }
+
out_err:
put_net(ns_b);
put_net(ns_a);
@@ -381,6 +386,9 @@ static ssize_t unlink_device_store(const struct bus_type *bus, const char *buf,
if (!peer)
goto out_put_netns;
+ netif_carrier_off(dev);
+ netif_carrier_off(peer->netdev);
+
err = 0;
RCU_INIT_POINTER(nsim->peer, NULL);
RCU_INIT_POINTER(peer->peer, NULL);
diff --git a/tools/testing/selftests/drivers/net/netdevsim/peer.sh b/tools/testing/selftests/drivers/net/netdevsim/peer.sh
index 7f32b560092576..f4721f7636dd6a 100755
--- a/tools/testing/selftests/drivers/net/netdevsim/peer.sh
+++ b/tools/testing/selftests/drivers/net/netdevsim/peer.sh
@@ -52,6 +52,39 @@ cleanup_ns()
ip netns del nssv
}
+is_carrier_up()
+{
+ local netns="$1"
+ local nsim_dev="$2"
+
+ test "$(ip netns exec "$netns" \
+ cat /sys/class/net/"$nsim_dev"/carrier 2>/dev/null)" -eq 1
+}
+
+assert_carrier_up()
+{
+ local netns="$1"
+ local nsim_dev="$2"
+
+ if ! is_carrier_up "$netns" "$nsim_dev"; then
+ echo "$nsim_dev's carrier should be UP, but it isn't"
+ cleanup_ns
+ exit 1
+ fi
+}
+
+assert_carrier_down()
+{
+ local netns="$1"
+ local nsim_dev="$2"
+
+ if is_carrier_up "$netns" "$nsim_dev"; then
+ echo "$nsim_dev's carrier should be DOWN, but it isn't"
+ cleanup_ns
+ exit 1
+ fi
+}
+
###
### Code start
###
@@ -113,6 +146,32 @@ if [ $? -eq 0 ]; then
exit 1
fi
+# netdevsim carrier state consistency checking
+assert_carrier_up nssv "$NSIM_DEV_1_NAME"
+assert_carrier_up nscl "$NSIM_DEV_2_NAME"
+
+echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX" > "$NSIM_DEV_SYS_UNLINK"
+
+assert_carrier_down nssv "$NSIM_DEV_1_NAME"
+assert_carrier_down nscl "$NSIM_DEV_2_NAME"
+
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" down
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" up
+
+assert_carrier_down nssv "$NSIM_DEV_1_NAME"
+assert_carrier_down nscl "$NSIM_DEV_2_NAME"
+
+echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX $NSIM_DEV_2_FD:$NSIM_DEV_2_IFIDX" > $NSIM_DEV_SYS_LINK
+
+assert_carrier_up nssv "$NSIM_DEV_1_NAME"
+assert_carrier_up nscl "$NSIM_DEV_2_NAME"
+
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" down
+ip netns exec nssv ip link set dev "$NSIM_DEV_1_NAME" up
+
+assert_carrier_up nssv "$NSIM_DEV_1_NAME"
+assert_carrier_up nscl "$NSIM_DEV_2_NAME"
+
# send/recv packets
tmp_file=$(mktemp)