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