udpgro_fwd.sh 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. BPF_FILE="../bpf/xdp_dummy.bpf.o"
  4. readonly BASE="ns-$(mktemp -u XXXXXX)"
  5. readonly SRC=2
  6. readonly DST=1
  7. readonly DST_NAT=100
  8. readonly NS_SRC=$BASE$SRC
  9. readonly NS_DST=$BASE$DST
  10. # "baremetal" network used for raw UDP traffic
  11. readonly BM_NET_V4=192.168.1.
  12. readonly BM_NET_V6=2001:db8::
  13. # "overlay" network used for UDP over UDP tunnel traffic
  14. readonly OL_NET_V4=172.16.1.
  15. readonly OL_NET_V6=2001:db8:1::
  16. readonly NPROCS=`nproc`
  17. cleanup() {
  18. local ns
  19. local -r jobs="$(jobs -p)"
  20. [ -n "${jobs}" ] && kill -1 ${jobs} 2>/dev/null
  21. for ns in $NS_SRC $NS_DST; do
  22. ip netns del $ns 2>/dev/null
  23. done
  24. }
  25. trap cleanup EXIT
  26. create_ns() {
  27. local net
  28. local ns
  29. for ns in $NS_SRC $NS_DST; do
  30. ip netns add $ns
  31. ip -n $ns link set dev lo up
  32. done
  33. ip link add name veth$SRC type veth peer name veth$DST
  34. for ns in $SRC $DST; do
  35. ip link set dev veth$ns netns $BASE$ns
  36. ip -n $BASE$ns link set dev veth$ns up
  37. ip -n $BASE$ns addr add dev veth$ns $BM_NET_V4$ns/24
  38. ip -n $BASE$ns addr add dev veth$ns $BM_NET_V6$ns/64 nodad
  39. done
  40. ip -n $NS_DST link set veth$DST xdp object ${BPF_FILE} section xdp 2>/dev/null
  41. }
  42. create_vxlan_endpoint() {
  43. local -r netns=$1
  44. local -r bm_dev=$2
  45. local -r bm_rem_addr=$3
  46. local -r vxlan_dev=$4
  47. local -r vxlan_id=$5
  48. local -r vxlan_port=4789
  49. ip -n $netns link set dev $bm_dev up
  50. ip -n $netns link add dev $vxlan_dev type vxlan id $vxlan_id \
  51. dstport $vxlan_port remote $bm_rem_addr
  52. ip -n $netns link set dev $vxlan_dev up
  53. }
  54. create_vxlan_pair() {
  55. local ns
  56. create_ns
  57. for ns in $SRC $DST; do
  58. # note that 3 - $SRC == $DST and 3 - $DST == $SRC
  59. create_vxlan_endpoint $BASE$ns veth$ns $BM_NET_V4$((3 - $ns)) vxlan$ns 4
  60. ip -n $BASE$ns addr add dev vxlan$ns $OL_NET_V4$ns/24
  61. done
  62. for ns in $SRC $DST; do
  63. create_vxlan_endpoint $BASE$ns veth$ns $BM_NET_V6$((3 - $ns)) vxlan6$ns 6
  64. ip -n $BASE$ns addr add dev vxlan6$ns $OL_NET_V6$ns/24 nodad
  65. done
  66. }
  67. is_ipv6() {
  68. if [[ $1 =~ .*:.* ]]; then
  69. return 0
  70. fi
  71. return 1
  72. }
  73. run_test() {
  74. local -r msg=$1
  75. local -r dst=$2
  76. local -r pkts=$3
  77. local -r vxpkts=$4
  78. local bind=$5
  79. local rx_args=""
  80. local rx_family="-4"
  81. local family=-4
  82. local filter=IpInReceives
  83. local ipt=iptables
  84. printf "%-40s" "$msg"
  85. if is_ipv6 $dst; then
  86. # rx program does not support '-6' and implies ipv6 usage by default
  87. rx_family=""
  88. family=-6
  89. filter=Ip6InReceives
  90. ipt=ip6tables
  91. fi
  92. rx_args="$rx_family"
  93. [ -n "$bind" ] && rx_args="$rx_args -b $bind"
  94. # send a single GSO packet, segmented in 10 UDP frames.
  95. # Always expect 10 UDP frames on RX side as rx socket does
  96. # not enable GRO
  97. ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 4789
  98. ip netns exec $NS_DST $ipt -A INPUT -p udp --dport 8000
  99. ip netns exec $NS_DST ./udpgso_bench_rx -C 1000 -R 10 -n 10 -l 1300 $rx_args &
  100. local spid=$!
  101. sleep 0.1
  102. ip netns exec $NS_SRC ./udpgso_bench_tx $family -M 1 -s 13000 -S 1300 -D $dst
  103. local retc=$?
  104. wait $spid
  105. local rets=$?
  106. if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then
  107. echo " fail client exit code $retc, server $rets"
  108. ret=1
  109. return
  110. fi
  111. local rcv=`ip netns exec $NS_DST $ipt"-save" -c | grep 'dport 8000' | \
  112. sed -e 's/\[//' -e 's/:.*//'`
  113. if [ $rcv != $pkts ]; then
  114. echo " fail - received $rcv packets, expected $pkts"
  115. ret=1
  116. return
  117. fi
  118. local vxrcv=`ip netns exec $NS_DST $ipt"-save" -c | grep 'dport 4789' | \
  119. sed -e 's/\[//' -e 's/:.*//'`
  120. # upper net can generate a little noise, allow some tolerance
  121. if [ $vxrcv -lt $vxpkts -o $vxrcv -gt $((vxpkts + 3)) ]; then
  122. echo " fail - received $vxrcv vxlan packets, expected $vxpkts"
  123. ret=1
  124. return
  125. fi
  126. echo " ok"
  127. }
  128. run_bench() {
  129. local -r msg=$1
  130. local -r dst=$2
  131. local family=-4
  132. printf "%-40s" "$msg"
  133. if [ $NPROCS -lt 2 ]; then
  134. echo " skip - needed 2 CPUs found $NPROCS"
  135. return
  136. fi
  137. is_ipv6 $dst && family=-6
  138. # bind the sender and the receiver to different CPUs to try
  139. # get reproducible results
  140. ip netns exec $NS_DST bash -c "echo 2 > /sys/class/net/veth$DST/queues/rx-0/rps_cpus"
  141. ip netns exec $NS_DST taskset 0x2 ./udpgso_bench_rx -C 1000 -R 10 &
  142. local spid=$!
  143. sleep 0.1
  144. ip netns exec $NS_SRC taskset 0x1 ./udpgso_bench_tx $family -l 3 -S 1300 -D $dst
  145. local retc=$?
  146. wait $spid
  147. local rets=$?
  148. if [ ${rets} -ne 0 ] || [ ${retc} -ne 0 ]; then
  149. echo " fail client exit code $retc, server $rets"
  150. ret=1
  151. return
  152. fi
  153. }
  154. for family in 4 6; do
  155. BM_NET=$BM_NET_V4
  156. OL_NET=$OL_NET_V4
  157. IPT=iptables
  158. SUFFIX=24
  159. VXDEV=vxlan
  160. PING=ping
  161. if [ $family = 6 ]; then
  162. BM_NET=$BM_NET_V6
  163. OL_NET=$OL_NET_V6
  164. SUFFIX="64 nodad"
  165. VXDEV=vxlan6
  166. IPT=ip6tables
  167. # Use ping6 on systems where ping doesn't handle IPv6
  168. ping -w 1 -c 1 ::1 > /dev/null 2>&1 || PING="ping6"
  169. fi
  170. echo "IPv$family"
  171. create_ns
  172. run_test "No GRO" $BM_NET$DST 10 0
  173. cleanup
  174. create_ns
  175. ip netns exec $NS_DST ethtool -K veth$DST rx-gro-list on
  176. run_test "GRO frag list" $BM_NET$DST 1 0
  177. cleanup
  178. # UDP GRO fwd skips aggregation when find an udp socket with the GRO option
  179. # if there is an UDP tunnel in the running system, such lookup happen
  180. # take place.
  181. # use NAT to circumvent GRO FWD check
  182. create_ns
  183. ip -n $NS_DST addr add dev veth$DST $BM_NET$DST_NAT/$SUFFIX
  184. ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
  185. ip netns exec $NS_DST $IPT -t nat -I PREROUTING -d $BM_NET$DST_NAT \
  186. -j DNAT --to-destination $BM_NET$DST
  187. run_test "GRO fwd" $BM_NET$DST_NAT 1 0 $BM_NET$DST
  188. cleanup
  189. create_ns
  190. run_bench "UDP fwd perf" $BM_NET$DST
  191. ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
  192. run_bench "UDP GRO fwd perf" $BM_NET$DST
  193. cleanup
  194. create_vxlan_pair
  195. ip netns exec $NS_DST ethtool -K veth$DST rx-gro-list on
  196. run_test "GRO frag list over UDP tunnel" $OL_NET$DST 1 1
  197. cleanup
  198. # use NAT to circumvent GRO FWD check
  199. create_vxlan_pair
  200. ip -n $NS_DST addr add dev $VXDEV$DST $OL_NET$DST_NAT/$SUFFIX
  201. ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
  202. ip netns exec $NS_DST $IPT -t nat -I PREROUTING -d $OL_NET$DST_NAT \
  203. -j DNAT --to-destination $OL_NET$DST
  204. # load arp cache before running the test to reduce the amount of
  205. # stray traffic on top of the UDP tunnel
  206. ip netns exec $NS_SRC $PING -q -c 1 $OL_NET$DST_NAT >/dev/null
  207. run_test "GRO fwd over UDP tunnel" $OL_NET$DST_NAT 1 1 $OL_NET$DST
  208. cleanup
  209. create_vxlan_pair
  210. run_bench "UDP tunnel fwd perf" $OL_NET$DST
  211. ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
  212. run_bench "UDP tunnel GRO fwd perf" $OL_NET$DST
  213. cleanup
  214. done
  215. exit $ret