1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Simple tests for ipvtap 5 6 7# 8# The testing environment looks this way: 9# 10# |------HNS-------| |------PHY-------| 11# | veth<----------------->veth | 12# |------|--|------| |----------------| 13# | | 14# | | |-----TST0-------| 15# | |------------|----ipvlan | 16# | |----------------| 17# | 18# | |-----TST1-------| 19# |---------------|----ipvlan | 20# |----------------| 21# 22 23ALL_TESTS=" 24 test_ip_set 25" 26 27source lib.sh 28 29DEBUG=0 30 31VETH_HOST=vethtst.h 32VETH_PHY=vethtst.p 33 34NS_COUNT=32 35IP_ITERATIONS=1024 36IPSET_TIMEOUT="60s" 37 38ns_run() { 39 ns=$1 40 shift 41 if [[ "$ns" == "global" ]]; then 42 "$@" >/dev/null 43 else 44 ip netns exec "$ns" "$@" >/dev/null 45 fi 46} 47 48test_ip_setup_env() { 49 setup_ns NS_PHY 50 setup_ns HST_NS 51 52 # setup simulated other-host (phy) and host itself 53 ns_run "$HST_NS" ip link add $VETH_HOST type veth peer name $VETH_PHY \ 54 netns "$NS_PHY" >/dev/null 55 ns_run "$HST_NS" ip link set $VETH_HOST up 56 ns_run "$NS_PHY" ip link set $VETH_PHY up 57 58 for ((i=0; i<NS_COUNT; i++)); do 59 setup_ns ipvlan_ns_$i 60 ns="ipvlan_ns_$i" 61 if [ "$DEBUG" = "1" ]; then 62 echo "created NS ${!ns}" 63 fi 64 if ! ns_run "$HST_NS" ip link add netns ${!ns} ipvlan0 \ 65 link $VETH_HOST \ 66 type ipvtap mode l2 bridge; then 67 exit_error "FAIL: Failed to configure ipvlan link." 68 fi 69 done 70} 71 72test_ip_cleanup_env() { 73 ns_run "$HST_NS" ip link del $VETH_HOST 74 cleanup_all_ns 75} 76 77exit_error() { 78 echo "$1" 79 exit $ksft_fail 80} 81 82rnd() { 83 echo $(( RANDOM % 32 + 16 )) 84} 85 86test_ip_set_thread() { 87 # Here we are trying to create some IP conflicts between namespaces. 88 # If just add/remove IP, nothing interesting will happen. 89 # But if add random IP and then remove random IP, 90 # eventually conflicts start to apear. 91 ip link set ipvlan0 up 92 for ((i=0; i<IP_ITERATIONS; i++)); do 93 v=$(rnd) 94 ip a a "172.25.0.$v/24" dev ipvlan0 2>/dev/null 95 ip a a "fc00::$v/64" dev ipvlan0 2>/dev/null 96 v=$(rnd) 97 ip a d "172.25.0.$v/24" dev ipvlan0 2>/dev/null 98 ip a d "fc00::$v/64" dev ipvlan0 2>/dev/null 99 done 100} 101 102test_ip_set() { 103 RET=0 104 105 trap test_ip_cleanup_env EXIT 106 107 test_ip_setup_env 108 109 declare -A ns_pids 110 for ((i=0; i<NS_COUNT; i++)); do 111 ns="ipvlan_ns_$i" 112 ns_run ${!ns} timeout "$IPSET_TIMEOUT" \ 113 bash -c "$0 test_ip_set_thread"& 114 ns_pids[$i]=$! 115 done 116 117 for ((i=0; i<NS_COUNT; i++)); do 118 wait "${ns_pids[$i]}" 119 done 120 121 declare -A all_ips 122 for ((i=0; i<NS_COUNT; i++)); do 123 ns="ipvlan_ns_$i" 124 ip_output=$(ip netns exec ${!ns} ip a l dev ipvlan0 | grep inet) 125 while IFS= read -r nsip_out; do 126 if [[ -z $nsip_out ]]; then 127 continue; 128 fi 129 nsip=$(awk '{print $2}' <<< "$nsip_out") 130 if [[ -v all_ips[$nsip] ]]; then 131 RET=$ksft_fail 132 log_test "conflict for $nsip" 133 return "$RET" 134 else 135 all_ips[$nsip]=$i 136 fi 137 done <<< "$ip_output" 138 done 139 140 if [ "$DEBUG" = "1" ]; then 141 for key in "${!all_ips[@]}"; do 142 echo "$key: ${all_ips[$key]}" 143 done 144 fi 145 146 trap - EXIT 147 test_ip_cleanup_env 148 149 log_test "test multithreaded ip set" 150} 151 152if [[ "$1" == "-d" ]]; then 153 DEBUG=1 154 shift 155fi 156 157if [[ "$1" == "-t" ]]; then 158 shift 159 TESTS="$*" 160fi 161 162if [[ "$1" == "test_ip_set_thread" ]]; then 163 test_ip_set_thread 164else 165 require_command ip 166 167 tests_run 168fi 169