linux/tools/testing/selftests/drivers/net/netdevsim/peer.sh
Yohei Kojima 75df712cdd selftests: netdevsim: add carrier state consistency test
This commit adds a test case for netdevsim carrier state consistency.
Specifically, the added test verifies the carrier state during the
following operations:

1. Unlink two netdevsims
2. ifdown one netdevsim, then ifup again
3. Link the netdevsims again
4. ifdown one netdevsim, then ifup again

These steps verifies that the carrier is UP iff two netdevsims are
linked and ifuped.

Signed-off-by: Yohei Kojima <yk@y-koj.net>
Link: https://patch.msgid.link/481e2729e53b6074ebfc0ad85764d8feb244de8c.1767624906.git.yk@y-koj.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-01-06 18:04:01 -08:00

203 lines
4.7 KiB
Bash
Executable file

#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-only
lib_dir=$(dirname $0)/../../../net
source $lib_dir/lib.sh
NSIM_DEV_1_ID=$((256 + RANDOM % 256))
NSIM_DEV_1_SYS=/sys/bus/netdevsim/devices/netdevsim$NSIM_DEV_1_ID
NSIM_DEV_2_ID=$((512 + RANDOM % 256))
NSIM_DEV_2_SYS=/sys/bus/netdevsim/devices/netdevsim$NSIM_DEV_2_ID
NSIM_DEV_SYS_NEW=/sys/bus/netdevsim/new_device
NSIM_DEV_SYS_DEL=/sys/bus/netdevsim/del_device
NSIM_DEV_SYS_LINK=/sys/bus/netdevsim/link_device
NSIM_DEV_SYS_UNLINK=/sys/bus/netdevsim/unlink_device
socat_check()
{
if [ ! -x "$(command -v socat)" ]; then
echo "socat command not found. Skipping test"
return 1
fi
return 0
}
setup_ns()
{
set -e
ip netns add nssv
ip netns add nscl
NSIM_DEV_1_NAME=$(find $NSIM_DEV_1_SYS/net -maxdepth 1 -type d ! \
-path $NSIM_DEV_1_SYS/net -exec basename {} \;)
NSIM_DEV_2_NAME=$(find $NSIM_DEV_2_SYS/net -maxdepth 1 -type d ! \
-path $NSIM_DEV_2_SYS/net -exec basename {} \;)
ip link set $NSIM_DEV_1_NAME netns nssv
ip link set $NSIM_DEV_2_NAME netns nscl
ip netns exec nssv ip addr add '192.168.1.1/24' dev $NSIM_DEV_1_NAME
ip netns exec nscl ip addr add '192.168.1.2/24' dev $NSIM_DEV_2_NAME
ip netns exec nssv ip link set dev $NSIM_DEV_1_NAME up
ip netns exec nscl ip link set dev $NSIM_DEV_2_NAME up
set +e
}
cleanup_ns()
{
ip netns del nscl
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
###
socat_check || exit 4
modprobe netdevsim
# linking
echo $NSIM_DEV_1_ID > $NSIM_DEV_SYS_NEW
echo $NSIM_DEV_2_ID > $NSIM_DEV_SYS_NEW
udevadm settle
setup_ns
NSIM_DEV_1_FD=$((256 + RANDOM % 256))
exec {NSIM_DEV_1_FD}</var/run/netns/nssv
NSIM_DEV_1_IFIDX=$(ip netns exec nssv cat /sys/class/net/$NSIM_DEV_1_NAME/ifindex)
NSIM_DEV_2_FD=$((256 + RANDOM % 256))
exec {NSIM_DEV_2_FD}</var/run/netns/nscl
NSIM_DEV_2_IFIDX=$(ip netns exec nscl cat /sys/class/net/$NSIM_DEV_2_NAME/ifindex)
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX $NSIM_DEV_2_FD:2000" > $NSIM_DEV_SYS_LINK 2>/dev/null
if [ $? -eq 0 ]; then
echo "linking with non-existent netdevsim should fail"
cleanup_ns
exit 1
fi
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX 2000:$NSIM_DEV_2_IFIDX" > $NSIM_DEV_SYS_LINK 2>/dev/null
if [ $? -eq 0 ]; then
echo "linking with non-existent netnsid should fail"
cleanup_ns
exit 1
fi
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX $NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX" > $NSIM_DEV_SYS_LINK 2>/dev/null
if [ $? -eq 0 ]; then
echo "linking with self should fail"
cleanup_ns
exit 1
fi
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX $NSIM_DEV_2_FD:$NSIM_DEV_2_IFIDX" > $NSIM_DEV_SYS_LINK
if [ $? -ne 0 ]; then
echo "linking netdevsim1 with netdevsim2 should succeed"
cleanup_ns
exit 1
fi
# argument error checking
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX $NSIM_DEV_2_FD:a" > $NSIM_DEV_SYS_LINK 2>/dev/null
if [ $? -eq 0 ]; then
echo "invalid arg should fail"
cleanup_ns
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)
ip netns exec nssv socat TCP-LISTEN:1234,fork $tmp_file &
pid=$!
res=0
wait_local_port_listen nssv 1234 tcp
echo "HI" | ip netns exec nscl socat STDIN TCP:192.168.1.1:1234
count=$(cat $tmp_file | wc -c)
if [[ $count -ne 3 ]]; then
echo "expected 3 bytes, got $count"
res=1
fi
echo "$NSIM_DEV_1_FD:$NSIM_DEV_1_IFIDX" > $NSIM_DEV_SYS_UNLINK
echo $NSIM_DEV_2_ID > $NSIM_DEV_SYS_DEL
kill $pid
echo $NSIM_DEV_1_ID > $NSIM_DEV_SYS_DEL
cleanup_ns
modprobe -r netdevsim
exit $res