udpgro.sh 5.7 KB

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