test_lwt_bpf.sh 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # Uncomment to see generated bytecode
  4. #VERBOSE=verbose
  5. NS1=lwt_ns1
  6. NS2=lwt_ns2
  7. VETH0=tst_lwt1a
  8. VETH1=tst_lwt1b
  9. VETH2=tst_lwt2a
  10. VETH3=tst_lwt2b
  11. IPVETH0="192.168.254.1"
  12. IPVETH1="192.168.254.2"
  13. IPVETH1b="192.168.254.3"
  14. IPVETH2="192.168.111.1"
  15. IPVETH3="192.168.111.2"
  16. IP_LOCAL="192.168.99.1"
  17. TRACE_ROOT=/sys/kernel/debug/tracing
  18. function lookup_mac()
  19. {
  20. set +x
  21. if [ ! -z "$2" ]; then
  22. MAC=$(ip netns exec $2 ip link show $1 | grep ether | awk '{print $2}')
  23. else
  24. MAC=$(ip link show $1 | grep ether | awk '{print $2}')
  25. fi
  26. MAC="${MAC//:/}"
  27. echo "0x${MAC:10:2}${MAC:8:2}${MAC:6:2}${MAC:4:2}${MAC:2:2}${MAC:0:2}"
  28. set -x
  29. }
  30. function cleanup {
  31. set +ex
  32. rm test_lwt_bpf.o 2> /dev/null
  33. ip link del $VETH0 2> /dev/null
  34. ip link del $VETH1 2> /dev/null
  35. ip link del $VETH2 2> /dev/null
  36. ip link del $VETH3 2> /dev/null
  37. ip netns exec $NS1 killall netserver
  38. ip netns delete $NS1 2> /dev/null
  39. ip netns delete $NS2 2> /dev/null
  40. set -ex
  41. }
  42. function setup_one_veth {
  43. ip netns add $1
  44. ip link add $2 type veth peer name $3
  45. ip link set dev $2 up
  46. ip addr add $4/24 dev $2
  47. ip link set $3 netns $1
  48. ip netns exec $1 ip link set dev $3 up
  49. ip netns exec $1 ip addr add $5/24 dev $3
  50. if [ "$6" ]; then
  51. ip netns exec $1 ip addr add $6/32 dev $3
  52. fi
  53. }
  54. function get_trace {
  55. set +x
  56. cat ${TRACE_ROOT}/trace | grep -v '^#'
  57. set -x
  58. }
  59. function cleanup_routes {
  60. ip route del ${IPVETH1}/32 dev $VETH0 2> /dev/null || true
  61. ip route del table local local ${IP_LOCAL}/32 dev lo 2> /dev/null || true
  62. }
  63. function install_test {
  64. cleanup_routes
  65. cp /dev/null ${TRACE_ROOT}/trace
  66. OPTS="encap bpf headroom 14 $1 obj test_lwt_bpf.o section $2 $VERBOSE"
  67. if [ "$1" == "in" ]; then
  68. ip route add table local local ${IP_LOCAL}/32 $OPTS dev lo
  69. else
  70. ip route add ${IPVETH1}/32 $OPTS dev $VETH0
  71. fi
  72. }
  73. function remove_prog {
  74. if [ "$1" == "in" ]; then
  75. ip route del table local local ${IP_LOCAL}/32 dev lo
  76. else
  77. ip route del ${IPVETH1}/32 dev $VETH0
  78. fi
  79. }
  80. function filter_trace {
  81. # Add newline to allow starting EXPECT= variables on newline
  82. NL=$'\n'
  83. echo "${NL}$*" | sed -e 's/^.*: : //g'
  84. }
  85. function expect_fail {
  86. set +x
  87. echo "FAIL:"
  88. echo "Expected: $1"
  89. echo "Got: $2"
  90. set -x
  91. exit 1
  92. }
  93. function match_trace {
  94. set +x
  95. RET=0
  96. TRACE=$1
  97. EXPECT=$2
  98. GOT="$(filter_trace "$TRACE")"
  99. [ "$GOT" != "$EXPECT" ] && {
  100. expect_fail "$EXPECT" "$GOT"
  101. RET=1
  102. }
  103. set -x
  104. return $RET
  105. }
  106. function test_start {
  107. set +x
  108. echo "----------------------------------------------------------------"
  109. echo "Starting test: $*"
  110. echo "----------------------------------------------------------------"
  111. set -x
  112. }
  113. function failure {
  114. get_trace
  115. echo "FAIL: $*"
  116. exit 1
  117. }
  118. function test_ctx_xmit {
  119. test_start "test_ctx on lwt xmit"
  120. install_test xmit test_ctx
  121. ping -c 3 $IPVETH1 || {
  122. failure "test_ctx xmit: packets are dropped"
  123. }
  124. match_trace "$(get_trace)" "
  125. len 84 hash 0 protocol 8
  126. cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX
  127. len 84 hash 0 protocol 8
  128. cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX
  129. len 84 hash 0 protocol 8
  130. cb 1234 ingress_ifindex 0 ifindex $DST_IFINDEX" || exit 1
  131. remove_prog xmit
  132. }
  133. function test_ctx_out {
  134. test_start "test_ctx on lwt out"
  135. install_test out test_ctx
  136. ping -c 3 $IPVETH1 || {
  137. failure "test_ctx out: packets are dropped"
  138. }
  139. match_trace "$(get_trace)" "
  140. len 84 hash 0 protocol 0
  141. cb 1234 ingress_ifindex 0 ifindex 0
  142. len 84 hash 0 protocol 0
  143. cb 1234 ingress_ifindex 0 ifindex 0
  144. len 84 hash 0 protocol 0
  145. cb 1234 ingress_ifindex 0 ifindex 0" || exit 1
  146. remove_prog out
  147. }
  148. function test_ctx_in {
  149. test_start "test_ctx on lwt in"
  150. install_test in test_ctx
  151. ping -c 3 $IP_LOCAL || {
  152. failure "test_ctx out: packets are dropped"
  153. }
  154. # We will both request & reply packets as the packets will
  155. # be from $IP_LOCAL => $IP_LOCAL
  156. match_trace "$(get_trace)" "
  157. len 84 hash 0 protocol 8
  158. cb 1234 ingress_ifindex 1 ifindex 1
  159. len 84 hash 0 protocol 8
  160. cb 1234 ingress_ifindex 1 ifindex 1
  161. len 84 hash 0 protocol 8
  162. cb 1234 ingress_ifindex 1 ifindex 1
  163. len 84 hash 0 protocol 8
  164. cb 1234 ingress_ifindex 1 ifindex 1
  165. len 84 hash 0 protocol 8
  166. cb 1234 ingress_ifindex 1 ifindex 1
  167. len 84 hash 0 protocol 8
  168. cb 1234 ingress_ifindex 1 ifindex 1" || exit 1
  169. remove_prog in
  170. }
  171. function test_data {
  172. test_start "test_data on lwt $1"
  173. install_test $1 test_data
  174. ping -c 3 $IPVETH1 || {
  175. failure "test_data ${1}: packets are dropped"
  176. }
  177. match_trace "$(get_trace)" "
  178. src: 1fea8c0 dst: 2fea8c0
  179. src: 1fea8c0 dst: 2fea8c0
  180. src: 1fea8c0 dst: 2fea8c0" || exit 1
  181. remove_prog $1
  182. }
  183. function test_data_in {
  184. test_start "test_data on lwt in"
  185. install_test in test_data
  186. ping -c 3 $IP_LOCAL || {
  187. failure "test_data in: packets are dropped"
  188. }
  189. # We will both request & reply packets as the packets will
  190. # be from $IP_LOCAL => $IP_LOCAL
  191. match_trace "$(get_trace)" "
  192. src: 163a8c0 dst: 163a8c0
  193. src: 163a8c0 dst: 163a8c0
  194. src: 163a8c0 dst: 163a8c0
  195. src: 163a8c0 dst: 163a8c0
  196. src: 163a8c0 dst: 163a8c0
  197. src: 163a8c0 dst: 163a8c0" || exit 1
  198. remove_prog in
  199. }
  200. function test_cb {
  201. test_start "test_cb on lwt $1"
  202. install_test $1 test_cb
  203. ping -c 3 $IPVETH1 || {
  204. failure "test_cb ${1}: packets are dropped"
  205. }
  206. match_trace "$(get_trace)" "
  207. cb0: 0 cb1: 0 cb2: 0
  208. cb3: 0 cb4: 0
  209. cb0: 0 cb1: 0 cb2: 0
  210. cb3: 0 cb4: 0
  211. cb0: 0 cb1: 0 cb2: 0
  212. cb3: 0 cb4: 0" || exit 1
  213. remove_prog $1
  214. }
  215. function test_cb_in {
  216. test_start "test_cb on lwt in"
  217. install_test in test_cb
  218. ping -c 3 $IP_LOCAL || {
  219. failure "test_cb in: packets are dropped"
  220. }
  221. # We will both request & reply packets as the packets will
  222. # be from $IP_LOCAL => $IP_LOCAL
  223. match_trace "$(get_trace)" "
  224. cb0: 0 cb1: 0 cb2: 0
  225. cb3: 0 cb4: 0
  226. cb0: 0 cb1: 0 cb2: 0
  227. cb3: 0 cb4: 0
  228. cb0: 0 cb1: 0 cb2: 0
  229. cb3: 0 cb4: 0
  230. cb0: 0 cb1: 0 cb2: 0
  231. cb3: 0 cb4: 0
  232. cb0: 0 cb1: 0 cb2: 0
  233. cb3: 0 cb4: 0
  234. cb0: 0 cb1: 0 cb2: 0
  235. cb3: 0 cb4: 0" || exit 1
  236. remove_prog in
  237. }
  238. function test_drop_all {
  239. test_start "test_drop_all on lwt $1"
  240. install_test $1 drop_all
  241. ping -c 3 $IPVETH1 && {
  242. failure "test_drop_all ${1}: Unexpected success of ping"
  243. }
  244. match_trace "$(get_trace)" "
  245. dropping with: 2
  246. dropping with: 2
  247. dropping with: 2" || exit 1
  248. remove_prog $1
  249. }
  250. function test_drop_all_in {
  251. test_start "test_drop_all on lwt in"
  252. install_test in drop_all
  253. ping -c 3 $IP_LOCAL && {
  254. failure "test_drop_all in: Unexpected success of ping"
  255. }
  256. match_trace "$(get_trace)" "
  257. dropping with: 2
  258. dropping with: 2
  259. dropping with: 2" || exit 1
  260. remove_prog in
  261. }
  262. function test_push_ll_and_redirect {
  263. test_start "test_push_ll_and_redirect on lwt xmit"
  264. install_test xmit push_ll_and_redirect
  265. ping -c 3 $IPVETH1 || {
  266. failure "Redirected packets appear to be dropped"
  267. }
  268. match_trace "$(get_trace)" "
  269. redirected to $DST_IFINDEX
  270. redirected to $DST_IFINDEX
  271. redirected to $DST_IFINDEX" || exit 1
  272. remove_prog xmit
  273. }
  274. function test_no_l2_and_redirect {
  275. test_start "test_no_l2_and_redirect on lwt xmit"
  276. install_test xmit fill_garbage_and_redirect
  277. ping -c 3 $IPVETH1 && {
  278. failure "Unexpected success despite lack of L2 header"
  279. }
  280. match_trace "$(get_trace)" "
  281. redirected to $DST_IFINDEX
  282. redirected to $DST_IFINDEX
  283. redirected to $DST_IFINDEX" || exit 1
  284. remove_prog xmit
  285. }
  286. function test_rewrite {
  287. test_start "test_rewrite on lwt xmit"
  288. install_test xmit test_rewrite
  289. ping -c 3 $IPVETH1 || {
  290. failure "Rewritten packets appear to be dropped"
  291. }
  292. match_trace "$(get_trace)" "
  293. out: rewriting from 2fea8c0 to 3fea8c0
  294. out: rewriting from 2fea8c0 to 3fea8c0
  295. out: rewriting from 2fea8c0 to 3fea8c0" || exit 1
  296. remove_prog out
  297. }
  298. function test_fill_garbage {
  299. test_start "test_fill_garbage on lwt xmit"
  300. install_test xmit fill_garbage
  301. ping -c 3 $IPVETH1 && {
  302. failure "test_drop_all ${1}: Unexpected success of ping"
  303. }
  304. match_trace "$(get_trace)" "
  305. Set initial 96 bytes of header to FF
  306. Set initial 96 bytes of header to FF
  307. Set initial 96 bytes of header to FF" || exit 1
  308. remove_prog xmit
  309. }
  310. function test_netperf_nop {
  311. test_start "test_netperf_nop on lwt xmit"
  312. install_test xmit nop
  313. netperf -H $IPVETH1 -t TCP_STREAM || {
  314. failure "packets appear to be dropped"
  315. }
  316. match_trace "$(get_trace)" ""|| exit 1
  317. remove_prog xmit
  318. }
  319. function test_netperf_redirect {
  320. test_start "test_netperf_redirect on lwt xmit"
  321. install_test xmit push_ll_and_redirect_silent
  322. netperf -H $IPVETH1 -t TCP_STREAM || {
  323. failure "Rewritten packets appear to be dropped"
  324. }
  325. match_trace "$(get_trace)" ""|| exit 1
  326. remove_prog xmit
  327. }
  328. cleanup
  329. setup_one_veth $NS1 $VETH0 $VETH1 $IPVETH0 $IPVETH1 $IPVETH1b
  330. setup_one_veth $NS2 $VETH2 $VETH3 $IPVETH2 $IPVETH3
  331. ip netns exec $NS1 netserver
  332. echo 1 > ${TRACE_ROOT}/tracing_on
  333. DST_MAC=$(lookup_mac $VETH1 $NS1)
  334. SRC_MAC=$(lookup_mac $VETH0)
  335. DST_IFINDEX=$(cat /sys/class/net/$VETH0/ifindex)
  336. CLANG_OPTS="-O2 -target bpf -I ../include/"
  337. CLANG_OPTS+=" -DSRC_MAC=$SRC_MAC -DDST_MAC=$DST_MAC -DDST_IFINDEX=$DST_IFINDEX"
  338. clang $CLANG_OPTS -c test_lwt_bpf.c -o test_lwt_bpf.o
  339. test_ctx_xmit
  340. test_ctx_out
  341. test_ctx_in
  342. test_data "xmit"
  343. test_data "out"
  344. test_data_in
  345. test_cb "xmit"
  346. test_cb "out"
  347. test_cb_in
  348. test_drop_all "xmit"
  349. test_drop_all "out"
  350. test_drop_all_in
  351. test_rewrite
  352. test_push_ll_and_redirect
  353. test_no_l2_and_redirect
  354. test_fill_garbage
  355. test_netperf_nop
  356. test_netperf_redirect
  357. cleanup
  358. echo 0 > ${TRACE_ROOT}/tracing_on
  359. exit 0