test_lwt_bpf.sh 9.2 KB

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