Commit 65326732 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-netdevsim-fix-inconsistent-carrier-state-after-link-unlink'

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: default avatarJakub Kicinski <kuba@kernel.org>
parents 353cfc0e 75df712c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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);
+59 −0
Original line number Diff line number Diff line
@@ -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)