test_lwt_bpf.sh 8.9 KB

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