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