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