1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# Run a series of udpgro functional tests. 5 6readonly PEER_NS="ns-peer-$(mktemp -u XXXXXX)" 7 8# set global exit status, but never reset nonzero one. 9check_err() 10{ 11 if [ $ret -eq 0 ]; then 12 ret=$1 13 fi 14} 15 16cleanup() { 17 local -r jobs="$(jobs -p)" 18 local -r ns="$(ip netns list|grep $PEER_NS)" 19 20 [ -n "${jobs}" ] && kill -1 ${jobs} 2>/dev/null 21 [ -n "$ns" ] && ip netns del $ns 2>/dev/null 22} 23trap cleanup EXIT 24 25cfg_veth() { 26 ip netns add "${PEER_NS}" 27 ip -netns "${PEER_NS}" link set lo up 28 ip link add type veth 29 ip link set dev veth0 up 30 ip addr add dev veth0 192.168.1.2/24 31 ip addr add dev veth0 2001:db8::2/64 nodad 32 33 ip link set dev veth1 netns "${PEER_NS}" 34 ip -netns "${PEER_NS}" addr add dev veth1 192.168.1.1/24 35 ip -netns "${PEER_NS}" addr add dev veth1 2001:db8::1/64 nodad 36 ip -netns "${PEER_NS}" link set dev veth1 up 37 ip -n "${PEER_NS}" link set veth1 xdp object ../bpf/xdp_dummy.o section xdp 38} 39 40run_one() { 41 # use 'rx' as separator between sender args and receiver args 42 local -r all="$@" 43 local -r tx_args=${all%rx*} 44 local -r rx_args=${all#*rx} 45 46 cfg_veth 47 48 ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} && \ 49 echo "ok" || \ 50 echo "failed" & 51 52 # Hack: let bg programs complete the startup 53 sleep 0.1 54 ./udpgso_bench_tx ${tx_args} 55 ret=$? 56 wait $(jobs -p) 57 return $ret 58} 59 60run_test() { 61 local -r args=$@ 62 63 printf " %-40s" "$1" 64 ./in_netns.sh $0 __subprocess $2 rx -G -r $3 65} 66 67run_one_nat() { 68 # use 'rx' as separator between sender args and receiver args 69 local addr1 addr2 pid family="" ipt_cmd=ip6tables 70 local -r all="$@" 71 local -r tx_args=${all%rx*} 72 local -r rx_args=${all#*rx} 73 74 if [[ ${tx_args} = *-4* ]]; then 75 ipt_cmd=iptables 76 family=-4 77 addr1=192.168.1.1 78 addr2=192.168.1.3/24 79 else 80 addr1=2001:db8::1 81 addr2="2001:db8::3/64 nodad" 82 fi 83 84 cfg_veth 85 ip -netns "${PEER_NS}" addr add dev veth1 ${addr2} 86 87 # fool the GRO engine changing the destination address ... 88 ip netns exec "${PEER_NS}" $ipt_cmd -t nat -I PREROUTING -d ${addr1} -j DNAT --to-destination ${addr2%/*} 89 90 # ... so that GRO will match the UDP_GRO enabled socket, but packets 91 # will land on the 'plain' one 92 ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 & 93 pid=$! 94 ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} && \ 95 echo "ok" || \ 96 echo "failed"& 97 98 sleep 0.1 99 ./udpgso_bench_tx ${tx_args} 100 ret=$? 101 kill -INT $pid 102 wait $(jobs -p) 103 return $ret 104} 105 106run_one_2sock() { 107 # use 'rx' as separator between sender args and receiver args 108 local -r all="$@" 109 local -r tx_args=${all%rx*} 110 local -r rx_args=${all#*rx} 111 112 cfg_veth 113 114 ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 & 115 ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} && \ 116 echo "ok" || \ 117 echo "failed" & 118 119 # Hack: let bg programs complete the startup 120 sleep 0.1 121 ./udpgso_bench_tx ${tx_args} -p 12345 122 sleep 0.1 123 # first UDP GSO socket should be closed at this point 124 ./udpgso_bench_tx ${tx_args} 125 ret=$? 126 wait $(jobs -p) 127 return $ret 128} 129 130run_nat_test() { 131 local -r args=$@ 132 133 printf " %-40s" "$1" 134 ./in_netns.sh $0 __subprocess_nat $2 rx -r $3 135} 136 137run_2sock_test() { 138 local -r args=$@ 139 140 printf " %-40s" "$1" 141 ./in_netns.sh $0 __subprocess_2sock $2 rx -G -r $3 142} 143 144run_all() { 145 local -r core_args="-l 4" 146 local -r ipv4_args="${core_args} -4 -D 192.168.1.1" 147 local -r ipv6_args="${core_args} -6 -D 2001:db8::1" 148 ret=0 149 150 echo "ipv4" 151 run_test "no GRO" "${ipv4_args} -M 10 -s 1400" "-4 -n 10 -l 1400" 152 check_err $? 153 154 # explicitly check we are not receiving UDP_SEGMENT cmsg (-S -1) 155 # when GRO does not take place 156 run_test "no GRO chk cmsg" "${ipv4_args} -M 10 -s 1400" "-4 -n 10 -l 1400 -S -1" 157 check_err $? 158 159 # the GSO packets are aggregated because: 160 # * veth schedule napi after each xmit 161 # * segmentation happens in BH context, veth napi poll is delayed after 162 # the transmission of the last segment 163 run_test "GRO" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720" 164 check_err $? 165 run_test "GRO chk cmsg" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720 -S 1472" 166 check_err $? 167 run_test "GRO with custom segment size" "${ipv4_args} -M 1 -s 14720 -S 500 " "-4 -n 1 -l 14720" 168 check_err $? 169 run_test "GRO with custom segment size cmsg" "${ipv4_args} -M 1 -s 14720 -S 500 " "-4 -n 1 -l 14720 -S 500" 170 check_err $? 171 172 run_nat_test "bad GRO lookup" "${ipv4_args} -M 1 -s 14720 -S 0" "-n 10 -l 1472" 173 check_err $? 174 run_2sock_test "multiple GRO socks" "${ipv4_args} -M 1 -s 14720 -S 0 " "-4 -n 1 -l 14720 -S 1472" 175 check_err $? 176 177 echo "ipv6" 178 run_test "no GRO" "${ipv6_args} -M 10 -s 1400" "-n 10 -l 1400" 179 check_err $? 180 run_test "no GRO chk cmsg" "${ipv6_args} -M 10 -s 1400" "-n 10 -l 1400 -S -1" 181 check_err $? 182 run_test "GRO" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 1 -l 14520" 183 check_err $? 184 run_test "GRO chk cmsg" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 1 -l 14520 -S 1452" 185 check_err $? 186 run_test "GRO with custom segment size" "${ipv6_args} -M 1 -s 14520 -S 500" "-n 1 -l 14520" 187 check_err $? 188 run_test "GRO with custom segment size cmsg" "${ipv6_args} -M 1 -s 14520 -S 500" "-n 1 -l 14520 -S 500" 189 check_err $? 190 191 run_nat_test "bad GRO lookup" "${ipv6_args} -M 1 -s 14520 -S 0" "-n 10 -l 1452" 192 check_err $? 193 run_2sock_test "multiple GRO socks" "${ipv6_args} -M 1 -s 14520 -S 0 " "-n 1 -l 14520 -S 1452" 194 check_err $? 195 return $ret 196} 197 198if [ ! -f ../bpf/xdp_dummy.o ]; then 199 echo "Missing xdp_dummy helper. Build bpf selftest first" 200 exit -1 201fi 202 203if [[ $# -eq 0 ]]; then 204 run_all 205elif [[ $1 == "__subprocess" ]]; then 206 shift 207 run_one $@ 208elif [[ $1 == "__subprocess_nat" ]]; then 209 shift 210 run_one_nat $@ 211elif [[ $1 == "__subprocess_2sock" ]]; then 212 shift 213 run_one_2sock $@ 214fi 215 216exit $? 217