This is a simple ipvtap test to do simple test
on handling IP-address assigning to ipvlan interface.

It creates a veth-interface and then creates several
network-namespace with ipvlan0 interface in it linked to veth.

Then it starts to add/remove addresses on ipvlan0 interfaces
in several threads.

At finish, it checks that there is no duplicated addresses.

Signed-off-by: Dmitry Skorodumov <[email protected]>
---
 tools/testing/selftests/net/Makefile       |   1 +
 tools/testing/selftests/net/config         |   2 +
 tools/testing/selftests/net/ipvtap_test.sh | 167 +++++++++++++++++++++
 3 files changed, 170 insertions(+)
 create mode 100755 tools/testing/selftests/net/ipvtap_test.sh

diff --git a/tools/testing/selftests/net/Makefile 
b/tools/testing/selftests/net/Makefile
index b66ba04f19d9..45c4ea381bc3 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -48,6 +48,7 @@ TEST_PROGS := \
        ipv6_flowlabel.sh \
        ipv6_force_forwarding.sh \
        ipv6_route_update_soft_lockup.sh \
+       ipvtap_test.sh \
        l2_tos_ttl_inherit.sh \
        l2tp.sh \
        link_netns.py \
diff --git a/tools/testing/selftests/net/config 
b/tools/testing/selftests/net/config
index 1e1f253118f5..5702ab8fa5ad 100644
--- a/tools/testing/selftests/net/config
+++ b/tools/testing/selftests/net/config
@@ -48,6 +48,7 @@ CONFIG_IPV6_SEG6_LWTUNNEL=y
 CONFIG_IPV6_SIT=y
 CONFIG_IPV6_VTI=y
 CONFIG_IPVLAN=m
+CONFIG_IPVTAP=m
 CONFIG_KALLSYMS=y
 CONFIG_L2TP=m
 CONFIG_L2TP_ETH=m
@@ -122,6 +123,7 @@ CONFIG_TEST_BPF=m
 CONFIG_TLS=m
 CONFIG_TRACEPOINTS=y
 CONFIG_TUN=y
+CONFIG_TAP=m
 CONFIG_USER_NS=y
 CONFIG_VETH=y
 CONFIG_VLAN_8021Q=y
diff --git a/tools/testing/selftests/net/ipvtap_test.sh 
b/tools/testing/selftests/net/ipvtap_test.sh
new file mode 100755
index 000000000000..751793f26fed
--- /dev/null
+++ b/tools/testing/selftests/net/ipvtap_test.sh
@@ -0,0 +1,168 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Simple tests for ipvtap
+
+
+#
+# The testing environment looks this way:
+#
+# |------HOST------|     |------PHY-------|
+# |      veth<----------------->veth      |
+# |------|--|------|     |----------------|
+#        |  |
+#        |  |            |-----TST0-------|
+#        |  |------------|----ipvlan      |
+#        |               |----------------|
+#        |
+#        |               |-----TST1-------|
+#        |---------------|----ipvlan      |
+#                        |----------------|
+#
+
+ALL_TESTS="
+       test_ip_set
+"
+
+source lib.sh
+
+DEBUG=0
+
+VETH_HOST=vethtst.h
+VETH_PHY=vethtst.p
+
+NS_COUNT=32
+IP_ITERATIONS=1024
+
+ns_run() {
+       ns=$1
+       shift
+       if [[ "$ns" == "global" ]]; then
+               "$@" >/dev/null
+       else
+               ip netns exec "$ns" "$@" >/dev/null
+       fi
+}
+
+test_ip_setup_env() {
+       modprobe -q tap
+       modprobe -q ipvlan
+       modprobe -q ipvtap
+
+       setup_ns NS_PHY
+
+       # setup simulated other-host (phy) and host itself
+       ip link add $VETH_HOST type veth peer name $VETH_PHY \
+               netns "$NS_PHY" >/dev/null
+       ip link set $VETH_HOST up
+       ns_run "$NS_PHY" ip link set $VETH_PHY up
+
+       for ((i=0; i<NS_COUNT; i++)); do
+               setup_ns ipvlan_ns_$i
+               ns="ipvlan_ns_$i"
+               if [ "$DEBUG" = "1" ]; then
+                       echo "created NS ${!ns}"
+               fi
+               if ! ip link add netns ${!ns} ipvlan0 link $VETH_HOST \
+                   type ipvtap mode l2 bridge; then
+                       exit_error "FAIL: Failed to configure ipvlan link."
+               fi
+       done
+}
+
+test_ip_cleanup_env() {
+       ip link del $VETH_HOST
+       cleanup_all_ns
+}
+
+exit_error() {
+       echo "$1"
+       exit $ksft_fail
+}
+
+rnd() {
+       echo $(( RANDOM % 32 + 16 ))
+}
+
+test_ip_set_thread() {
+       ip link set ipvlan0 up
+       for ((i=0; i<IP_ITERATIONS; i++)); do
+               v=$(rnd)
+               ip a a "172.25.0.$v/24" dev ipvlan0 2>/dev/null
+               ip a a "fc00::$v/64" dev ipvlan0 2>/dev/null
+               v=$(rnd)
+               ip a d "172.25.0.$v/24" dev ipvlan0 2>/dev/null
+               ip a d "fc00::$v/64" dev ipvlan0 2>/dev/null
+       done
+}
+
+test_ip_set() {
+       RET=0
+
+       modprobe -q tap
+       modprobe -q ipvlan
+       modprobe -q ipvtap
+
+       trap test_ip_cleanup_env EXIT
+
+       test_ip_setup_env
+
+       declare -A ns_pids
+       for ((i=0; i<NS_COUNT; i++)); do
+               ns="ipvlan_ns_$i"
+               ns_run ${!ns} bash -c "$0 test_ip_set_thread"&
+               ns_pids[$i]=$!
+       done
+
+       for ((i=0; i<NS_COUNT; i++)); do
+               wait "${ns_pids[$i]}"
+       done
+
+       declare -A all_ips
+       for ((i=0; i<NS_COUNT; i++)); do
+               ns="ipvlan_ns_$i"
+               ip_output=$(ip netns exec ${!ns} ip a l dev ipvlan0 | grep inet)
+               while IFS= read -r nsip_out; do
+                       if [[ -z $nsip_out ]]; then
+                               continue;
+                       fi
+                       nsip=$(awk '{print $2}' <<< "$nsip_out")
+                       if [[ -v all_ips[$nsip] ]]; then
+                               RET=$ksft_fail
+                               log_test "conflict for $nsip"
+                               return "$RET"
+                       else
+                               all_ips[$nsip]=$i
+                       fi
+               done <<< "$ip_output"
+       done
+
+       if [ "$DEBUG" = "1" ]; then
+               for key in "${!all_ips[@]}"; do
+                       echo "$key: ${all_ips[$key]}"
+               done
+       fi
+
+       trap - EXIT
+       test_ip_cleanup_env
+
+       log_test "test multithreaded ip set"
+}
+
+if [[ "$1" == "-d" ]]; then
+       DEBUG=1
+       shift
+fi
+
+if [[ "$1" == "-t" ]]; then
+       shift
+       TESTS="$*"
+fi
+
+if [[ "$1" == "test_ip_set_thread" ]]; then
+       test_ip_set_thread
+else
+       require_command ip
+
+       tests_run
+fi
-- 
2.43.0


Reply via email to