vxlan_reserved.sh 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #!/bin/bash
  2. # SPDX-License-Identifier: GPL-2.0
  3. # +--------------------+
  4. # | H1 (vrf) |
  5. # | + $h1 |
  6. # | | 192.0.2.1/28 |
  7. # +----|---------------+
  8. # |
  9. # +----|--------------------------------+
  10. # | SW | |
  11. # | +--|------------------------------+ |
  12. # | | + $swp1 BR1 (802.1d) | |
  13. # | | | |
  14. # | | + vx1 (vxlan) | |
  15. # | | local 192.0.2.17 | |
  16. # | | id 1000 dstport $VXPORT | |
  17. # | +---------------------------------+ |
  18. # | |
  19. # | 192.0.2.32/28 via 192.0.2.18 |
  20. # | |
  21. # | + $rp1 |
  22. # | | 192.0.2.17/28 |
  23. # +--|----------------------------------+
  24. # |
  25. # +--|----------------------------------+
  26. # | | |
  27. # | + $rp2 |
  28. # | 192.0.2.18/28 |
  29. # | |
  30. # | VRP2 (vrf) |
  31. # +-------------------------------------+
  32. : ${VXPORT:=4789}
  33. : ${ALL_TESTS:="
  34. default_test
  35. plain_test
  36. reserved_0_test
  37. reserved_10_test
  38. reserved_31_test
  39. reserved_56_test
  40. reserved_63_test
  41. "}
  42. NUM_NETIFS=4
  43. source lib.sh
  44. h1_create()
  45. {
  46. adf_simple_if_init $h1 192.0.2.1/28
  47. tc qdisc add dev $h1 clsact
  48. defer tc qdisc del dev $h1 clsact
  49. tc filter add dev $h1 ingress pref 77 \
  50. prot ip flower skip_hw ip_proto icmp action drop
  51. defer tc filter del dev $h1 ingress pref 77
  52. }
  53. switch_create()
  54. {
  55. adf_ip_link_add br1 type bridge vlan_filtering 0 mcast_snooping 0
  56. # Make sure the bridge uses the MAC address of the local port and not
  57. # that of the VxLAN's device.
  58. adf_ip_link_set_addr br1 $(mac_get $swp1)
  59. adf_ip_link_set_up br1
  60. adf_ip_link_set_up $rp1
  61. adf_ip_addr_add $rp1 192.0.2.17/28
  62. adf_ip_route_add 192.0.2.32/28 nexthop via 192.0.2.18
  63. adf_ip_link_set_master $swp1 br1
  64. adf_ip_link_set_up $swp1
  65. }
  66. vrp2_create()
  67. {
  68. adf_simple_if_init $rp2 192.0.2.18/28
  69. }
  70. setup_prepare()
  71. {
  72. h1=${NETIFS[p1]}
  73. swp1=${NETIFS[p2]}
  74. rp1=${NETIFS[p3]}
  75. rp2=${NETIFS[p4]}
  76. adf_vrf_prepare
  77. adf_forwarding_enable
  78. h1_create
  79. switch_create
  80. vrp2_create
  81. }
  82. vxlan_header_bytes()
  83. {
  84. local vni=$1; shift
  85. local -a extra_bits=("$@")
  86. local -a bits
  87. local i
  88. for ((i=0; i < 64; i++)); do
  89. bits[i]=0
  90. done
  91. # Bit 4 is the I flag and is always on.
  92. bits[4]=1
  93. for i in ${extra_bits[@]}; do
  94. bits[i]=1
  95. done
  96. # Bits 32..55 carry the VNI
  97. local mask=0x800000
  98. for ((i=0; i < 24; i++)); do
  99. bits[$((i + 32))]=$(((vni & mask) != 0))
  100. ((mask >>= 1))
  101. done
  102. local bytes
  103. for ((i=0; i < 8; i++)); do
  104. local byte=0
  105. local j
  106. for ((j=0; j < 8; j++)); do
  107. local bit=${bits[8 * i + j]}
  108. ((byte += bit << (7 - j)))
  109. done
  110. bytes+=$(printf %02x $byte):
  111. done
  112. echo ${bytes%:}
  113. }
  114. neg_bytes()
  115. {
  116. local bytes=$1; shift
  117. local -A neg=([0]=f [1]=e [2]=d [3]=c [4]=b [5]=a [6]=9 [7]=8
  118. [8]=7 [9]=6 [a]=5 [b]=4 [c]=3 [d]=2 [e]=1 [f]=0 [:]=:)
  119. local out
  120. local i
  121. for ((i=0; i < ${#bytes}; i++)); do
  122. local c=${bytes:$i:1}
  123. out+=${neg[$c]}
  124. done
  125. echo $out
  126. }
  127. vxlan_ping_do()
  128. {
  129. local count=$1; shift
  130. local dev=$1; shift
  131. local next_hop_mac=$1; shift
  132. local dest_ip=$1; shift
  133. local dest_mac=$1; shift
  134. local vni=$1; shift
  135. local reserved_bits=$1; shift
  136. local vxlan_header=$(vxlan_header_bytes $vni $reserved_bits)
  137. $MZ $dev -c $count -d 100msec -q \
  138. -b $next_hop_mac -B $dest_ip \
  139. -t udp sp=23456,dp=$VXPORT,p=$(:
  140. )"$vxlan_header:"$( : VXLAN
  141. )"$dest_mac:"$( : ETH daddr
  142. )"00:11:22:33:44:55:"$( : ETH saddr
  143. )"08:00:"$( : ETH type
  144. )"45:"$( : IP version + IHL
  145. )"00:"$( : IP TOS
  146. )"00:54:"$( : IP total length
  147. )"99:83:"$( : IP identification
  148. )"40:00:"$( : IP flags + frag off
  149. )"40:"$( : IP TTL
  150. )"01:"$( : IP proto
  151. )"00:00:"$( : IP header csum
  152. )"$(ipv4_to_bytes 192.0.2.3):"$( : IP saddr
  153. )"$(ipv4_to_bytes 192.0.2.1):"$( : IP daddr
  154. )"08:"$( : ICMP type
  155. )"00:"$( : ICMP code
  156. )"8b:f2:"$( : ICMP csum
  157. )"1f:6a:"$( : ICMP request identifier
  158. )"00:01:"$( : ICMP request seq. number
  159. )"4f:ff:c5:5b:00:00:00:00:"$( : ICMP payload
  160. )"6d:74:0b:00:00:00:00:00:"$( :
  161. )"10:11:12:13:14:15:16:17:"$( :
  162. )"18:19:1a:1b:1c:1d:1e:1f:"$( :
  163. )"20:21:22:23:24:25:26:27:"$( :
  164. )"28:29:2a:2b:2c:2d:2e:2f:"$( :
  165. )"30:31:32:33:34:35:36:37"
  166. }
  167. vxlan_device_add()
  168. {
  169. adf_ip_link_add vx1 up type vxlan id 1000 \
  170. local 192.0.2.17 dstport "$VXPORT" \
  171. nolearning noudpcsum tos inherit ttl 100 "$@"
  172. adf_ip_link_set_master vx1 br1
  173. }
  174. vxlan_all_reserved_bits()
  175. {
  176. local i
  177. for ((i=0; i < 64; i++)); do
  178. if ((i == 4 || i >= 32 && i < 56)); then
  179. continue
  180. fi
  181. echo $i
  182. done
  183. }
  184. vxlan_ping_vanilla()
  185. {
  186. vxlan_ping_do 10 $rp2 $(mac_get $rp1) 192.0.2.17 $(mac_get $h1) 1000
  187. }
  188. vxlan_ping_reserved()
  189. {
  190. for bit in $(vxlan_all_reserved_bits); do
  191. vxlan_ping_do 1 $rp2 $(mac_get $rp1) \
  192. 192.0.2.17 $(mac_get $h1) 1000 "$bit"
  193. ((n++))
  194. done
  195. }
  196. vxlan_ping_test()
  197. {
  198. local what=$1; shift
  199. local get_stat=$1; shift
  200. local expect=$1; shift
  201. RET=0
  202. local t0=$($get_stat)
  203. "$@"
  204. check_err $? "Failure when running $@"
  205. local t1=$($get_stat)
  206. local delta=$((t1 - t0))
  207. ((expect == delta))
  208. check_err $? "Expected to capture $expect packets, got $delta."
  209. log_test "$what"
  210. }
  211. __default_test_do()
  212. {
  213. local n_allowed_bits=$1; shift
  214. local what=$1; shift
  215. vxlan_ping_test "$what: clean packets" \
  216. "tc_rule_stats_get $h1 77 ingress" \
  217. 10 vxlan_ping_vanilla
  218. local t0=$(link_stats_get vx1 rx errors)
  219. vxlan_ping_test "$what: mangled packets" \
  220. "tc_rule_stats_get $h1 77 ingress" \
  221. $n_allowed_bits vxlan_ping_reserved
  222. local t1=$(link_stats_get vx1 rx errors)
  223. RET=0
  224. local expect=$((39 - n_allowed_bits))
  225. local delta=$((t1 - t0))
  226. ((expect == delta))
  227. check_err $? "Expected $expect error packets, got $delta."
  228. log_test "$what: drops reported"
  229. }
  230. default_test_do()
  231. {
  232. vxlan_device_add
  233. __default_test_do 0 "Default"
  234. }
  235. default_test()
  236. {
  237. in_defer_scope \
  238. default_test_do
  239. }
  240. plain_test_do()
  241. {
  242. vxlan_device_add reserved_bits 0xf7ffffff000000ff
  243. __default_test_do 0 "reserved_bits 0xf7ffffff000000ff"
  244. }
  245. plain_test()
  246. {
  247. in_defer_scope \
  248. plain_test_do
  249. }
  250. reserved_test()
  251. {
  252. local bit=$1; shift
  253. local allowed_bytes=$(vxlan_header_bytes 0xffffff $bit)
  254. local reserved_bytes=$(neg_bytes $allowed_bytes)
  255. local reserved_bits=${reserved_bytes//:/}
  256. vxlan_device_add reserved_bits 0x$reserved_bits
  257. __default_test_do 1 "reserved_bits 0x$reserved_bits"
  258. }
  259. reserved_0_test()
  260. {
  261. in_defer_scope \
  262. reserved_test 0
  263. }
  264. reserved_10_test()
  265. {
  266. in_defer_scope \
  267. reserved_test 10
  268. }
  269. reserved_31_test()
  270. {
  271. in_defer_scope \
  272. reserved_test 31
  273. }
  274. reserved_56_test()
  275. {
  276. in_defer_scope \
  277. reserved_test 56
  278. }
  279. reserved_63_test()
  280. {
  281. in_defer_scope \
  282. reserved_test 63
  283. }
  284. trap cleanup EXIT
  285. setup_prepare
  286. setup_wait
  287. tests_run
  288. exit $EXIT_STATUS