0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 : ${VXPORT:=4789}
0065 export VXPORT
0066
0067 : ${ALL_TESTS:="
0068 ping_ipv4
0069 test_flood
0070 test_unicast
0071 test_ttl
0072 test_tos
0073 test_ecn_encap
0074 test_ecn_decap
0075 reapply_config
0076 ping_ipv4
0077 test_flood
0078 test_unicast
0079 test_learning
0080 "}
0081
0082 NUM_NETIFS=6
0083 source lib.sh
0084
0085 h1_create()
0086 {
0087 simple_if_init $h1 192.0.2.1/28
0088 tc qdisc add dev $h1 clsact
0089 }
0090
0091 h1_destroy()
0092 {
0093 tc qdisc del dev $h1 clsact
0094 simple_if_fini $h1 192.0.2.1/28
0095 }
0096
0097 h2_create()
0098 {
0099 simple_if_init $h2 192.0.2.2/28
0100 tc qdisc add dev $h2 clsact
0101 }
0102
0103 h2_destroy()
0104 {
0105 tc qdisc del dev $h2 clsact
0106 simple_if_fini $h2 192.0.2.2/28
0107 }
0108
0109 rp1_set_addr()
0110 {
0111 ip address add dev $rp1 192.0.2.17/28
0112
0113 ip route add 192.0.2.32/28 nexthop via 192.0.2.18
0114 ip route add 192.0.2.48/28 nexthop via 192.0.2.18
0115 }
0116
0117 rp1_unset_addr()
0118 {
0119 ip route del 192.0.2.48/28 nexthop via 192.0.2.18
0120 ip route del 192.0.2.32/28 nexthop via 192.0.2.18
0121
0122 ip address del dev $rp1 192.0.2.17/28
0123 }
0124
0125 switch_create()
0126 {
0127 ip link add name br1 type bridge vlan_filtering 0 mcast_snooping 0
0128
0129
0130 ip link set dev br1 address $(mac_get $swp1)
0131 ip link set dev br1 up
0132
0133 ip link set dev $rp1 up
0134 rp1_set_addr
0135
0136 ip link add name vx1 type vxlan id 1000 \
0137 local 192.0.2.17 dstport "$VXPORT" \
0138 nolearning noudpcsum tos inherit ttl 100
0139 ip link set dev vx1 up
0140
0141 ip link set dev vx1 master br1
0142 ip link set dev $swp1 master br1
0143 ip link set dev $swp1 up
0144
0145 ip link set dev $swp2 master br1
0146 ip link set dev $swp2 up
0147
0148 bridge fdb append dev vx1 00:00:00:00:00:00 dst 192.0.2.34 self
0149 bridge fdb append dev vx1 00:00:00:00:00:00 dst 192.0.2.50 self
0150 }
0151
0152 switch_destroy()
0153 {
0154 rp1_unset_addr
0155 ip link set dev $rp1 down
0156
0157 bridge fdb del dev vx1 00:00:00:00:00:00 dst 192.0.2.50 self
0158 bridge fdb del dev vx1 00:00:00:00:00:00 dst 192.0.2.34 self
0159
0160 ip link set dev vx1 nomaster
0161 ip link set dev vx1 down
0162 ip link del dev vx1
0163
0164 ip link set dev $swp2 down
0165 ip link set dev $swp2 nomaster
0166
0167 ip link set dev $swp1 down
0168 ip link set dev $swp1 nomaster
0169
0170 ip link set dev br1 down
0171 ip link del dev br1
0172 }
0173
0174 vrp2_create()
0175 {
0176 simple_if_init $rp2 192.0.2.18/28
0177 __simple_if_init v1 v$rp2 192.0.2.33/28
0178 __simple_if_init v3 v$rp2 192.0.2.49/28
0179 tc qdisc add dev v1 clsact
0180 }
0181
0182 vrp2_destroy()
0183 {
0184 tc qdisc del dev v1 clsact
0185 __simple_if_fini v3 192.0.2.49/28
0186 __simple_if_fini v1 192.0.2.33/28
0187 simple_if_fini $rp2 192.0.2.18/28
0188 }
0189
0190 ns_init_common()
0191 {
0192 local in_if=$1; shift
0193 local in_addr=$1; shift
0194 local other_in_addr=$1; shift
0195 local nh_addr=$1; shift
0196 local host_addr=$1; shift
0197
0198 ip link set dev $in_if up
0199 ip address add dev $in_if $in_addr/28
0200 tc qdisc add dev $in_if clsact
0201
0202 ip link add name br2 type bridge vlan_filtering 0
0203 ip link set dev br2 up
0204
0205 ip link add name w1 type veth peer name w2
0206
0207 ip link set dev w1 master br2
0208 ip link set dev w1 up
0209
0210 ip link add name vx2 type vxlan id 1000 local $in_addr dstport "$VXPORT"
0211 ip link set dev vx2 up
0212 bridge fdb append dev vx2 00:00:00:00:00:00 dst 192.0.2.17 self
0213 bridge fdb append dev vx2 00:00:00:00:00:00 dst $other_in_addr self
0214
0215 ip link set dev vx2 master br2
0216 tc qdisc add dev vx2 clsact
0217
0218 simple_if_init w2 $host_addr/28
0219
0220 ip route add 192.0.2.16/28 nexthop via $nh_addr
0221 ip route add $other_in_addr/32 nexthop via $nh_addr
0222 }
0223 export -f ns_init_common
0224
0225 ns1_create()
0226 {
0227 ip netns add ns1
0228 ip link set dev v2 netns ns1
0229 in_ns ns1 \
0230 ns_init_common v2 192.0.2.34 192.0.2.50 192.0.2.33 192.0.2.3
0231 }
0232
0233 ns1_destroy()
0234 {
0235 ip netns exec ns1 ip link set dev v2 netns 1
0236 ip netns del ns1
0237 }
0238
0239 ns2_create()
0240 {
0241 ip netns add ns2
0242 ip link set dev v4 netns ns2
0243 in_ns ns2 \
0244 ns_init_common v4 192.0.2.50 192.0.2.34 192.0.2.49 192.0.2.4
0245 }
0246
0247 ns2_destroy()
0248 {
0249 ip netns exec ns2 ip link set dev v4 netns 1
0250 ip netns del ns2
0251 }
0252
0253 setup_prepare()
0254 {
0255 h1=${NETIFS[p1]}
0256 swp1=${NETIFS[p2]}
0257
0258 swp2=${NETIFS[p3]}
0259 h2=${NETIFS[p4]}
0260
0261 rp1=${NETIFS[p5]}
0262 rp2=${NETIFS[p6]}
0263
0264 vrf_prepare
0265 forwarding_enable
0266
0267 h1_create
0268 h2_create
0269 switch_create
0270
0271 ip link add name v1 type veth peer name v2
0272 ip link add name v3 type veth peer name v4
0273 vrp2_create
0274 ns1_create
0275 ns2_create
0276
0277 r1_mac=$(in_ns ns1 mac_get w2)
0278 r2_mac=$(in_ns ns2 mac_get w2)
0279 h2_mac=$(mac_get $h2)
0280 }
0281
0282 cleanup()
0283 {
0284 pre_cleanup
0285
0286 ns2_destroy
0287 ns1_destroy
0288 vrp2_destroy
0289 ip link del dev v3
0290 ip link del dev v1
0291
0292 switch_destroy
0293 h2_destroy
0294 h1_destroy
0295
0296 forwarding_restore
0297 vrf_cleanup
0298 }
0299
0300
0301
0302
0303
0304 reapply_config()
0305 {
0306 echo "Reapplying configuration"
0307
0308 bridge fdb del dev vx1 00:00:00:00:00:00 dst 192.0.2.50 self
0309 bridge fdb del dev vx1 00:00:00:00:00:00 dst 192.0.2.34 self
0310 rp1_unset_addr
0311 ip link set dev vx1 nomaster
0312 sleep 5
0313
0314 ip link set dev vx1 master br1
0315 bridge fdb append dev vx1 00:00:00:00:00:00 dst 192.0.2.34 self
0316 bridge fdb append dev vx1 00:00:00:00:00:00 dst 192.0.2.50 self
0317 sleep 1
0318 rp1_set_addr
0319 sleep 5
0320 }
0321
0322 ping_ipv4()
0323 {
0324 ping_test $h1 192.0.2.2 ": local->local"
0325 ping_test $h1 192.0.2.3 ": local->remote 1"
0326 ping_test $h1 192.0.2.4 ": local->remote 2"
0327 }
0328
0329 maybe_in_ns()
0330 {
0331 echo ${1:+in_ns} $1
0332 }
0333
0334 __flood_counter_add_del()
0335 {
0336 local add_del=$1; shift
0337 local dev=$1; shift
0338 local ns=$1; shift
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349 $(maybe_in_ns $ns) __icmp_capture_add_del \
0350 $add_del 100 "" $dev skip_sw 2>/dev/null || \
0351 $(maybe_in_ns $ns) __icmp_capture_add_del \
0352 $add_del 100 "" $dev skip_hw
0353 }
0354
0355 flood_counter_install()
0356 {
0357 __flood_counter_add_del add "$@"
0358 }
0359
0360 flood_counter_uninstall()
0361 {
0362 __flood_counter_add_del del "$@"
0363 }
0364
0365 flood_fetch_stat()
0366 {
0367 local dev=$1; shift
0368 local ns=$1; shift
0369
0370 $(maybe_in_ns $ns) tc_rule_stats_get $dev 100 ingress
0371 }
0372
0373 flood_fetch_stats()
0374 {
0375 local counters=("${@}")
0376 local counter
0377
0378 for counter in "${counters[@]}"; do
0379 flood_fetch_stat $counter
0380 done
0381 }
0382
0383 vxlan_flood_test()
0384 {
0385 local mac=$1; shift
0386 local dst=$1; shift
0387 local -a expects=("${@}")
0388
0389 local -a counters=($h2 "vx2 ns1" "vx2 ns2")
0390 local counter
0391 local key
0392
0393 for counter in "${counters[@]}"; do
0394 flood_counter_install $counter
0395 done
0396
0397 local -a t0s=($(flood_fetch_stats "${counters[@]}"))
0398 $MZ $h1 -c 10 -d 100msec -p 64 -b $mac -B $dst -t icmp -q
0399 sleep 1
0400 local -a t1s=($(flood_fetch_stats "${counters[@]}"))
0401
0402 for key in ${!t0s[@]}; do
0403 local delta=$((t1s[$key] - t0s[$key]))
0404 local expect=${expects[$key]}
0405
0406 ((expect == delta))
0407 check_err $? "${counters[$key]}: Expected to capture $expect packets, got $delta."
0408 done
0409
0410 for counter in "${counters[@]}"; do
0411 flood_counter_uninstall $counter
0412 done
0413 }
0414
0415 __test_flood()
0416 {
0417 local mac=$1; shift
0418 local dst=$1; shift
0419 local what=$1; shift
0420
0421 RET=0
0422
0423 vxlan_flood_test $mac $dst 10 10 10
0424
0425 log_test "VXLAN: $what"
0426 }
0427
0428 test_flood()
0429 {
0430 __test_flood de:ad:be:ef:13:37 192.0.2.100 "flood"
0431 }
0432
0433 vxlan_fdb_add_del()
0434 {
0435 local add_del=$1; shift
0436 local mac=$1; shift
0437 local dev=$1; shift
0438 local dst=$1; shift
0439
0440 bridge fdb $add_del dev $dev $mac self static permanent \
0441 ${dst:+dst} $dst 2>/dev/null
0442 bridge fdb $add_del dev $dev $mac master static 2>/dev/null
0443 }
0444
0445 __test_unicast()
0446 {
0447 local mac=$1; shift
0448 local dst=$1; shift
0449 local hit_idx=$1; shift
0450 local what=$1; shift
0451
0452 RET=0
0453
0454 local -a expects=(0 0 0)
0455 expects[$hit_idx]=10
0456
0457 vxlan_flood_test $mac $dst "${expects[@]}"
0458
0459 log_test "VXLAN: $what"
0460 }
0461
0462 test_unicast()
0463 {
0464 local -a targets=("$h2_mac $h2"
0465 "$r1_mac vx1 192.0.2.34"
0466 "$r2_mac vx1 192.0.2.50")
0467 local target
0468
0469 for target in "${targets[@]}"; do
0470 vxlan_fdb_add_del add $target
0471 done
0472
0473 __test_unicast $h2_mac 192.0.2.2 0 "local MAC unicast"
0474 __test_unicast $r1_mac 192.0.2.3 1 "remote MAC 1 unicast"
0475 __test_unicast $r2_mac 192.0.2.4 2 "remote MAC 2 unicast"
0476
0477 for target in "${targets[@]}"; do
0478 vxlan_fdb_add_del del $target
0479 done
0480 }
0481
0482 vxlan_ping_test()
0483 {
0484 local ping_dev=$1; shift
0485 local ping_dip=$1; shift
0486 local ping_args=$1; shift
0487 local capture_dev=$1; shift
0488 local capture_dir=$1; shift
0489 local capture_pref=$1; shift
0490 local expect=$1; shift
0491
0492 local t0=$(tc_rule_stats_get $capture_dev $capture_pref $capture_dir)
0493 ping_do $ping_dev $ping_dip "$ping_args"
0494 local t1=$(tc_rule_stats_get $capture_dev $capture_pref $capture_dir)
0495 local delta=$((t1 - t0))
0496
0497
0498 ((expect <= delta && delta <= expect + 2))
0499 check_err $? "$capture_dev: Expected to capture $expect packets, got $delta."
0500 }
0501
0502 test_ttl()
0503 {
0504 RET=0
0505
0506 tc filter add dev v1 egress pref 77 prot ip \
0507 flower ip_ttl 99 action pass
0508 vxlan_ping_test $h1 192.0.2.3 "" v1 egress 77 10
0509 tc filter del dev v1 egress pref 77 prot ip
0510
0511 log_test "VXLAN: envelope TTL"
0512 }
0513
0514 test_tos()
0515 {
0516 RET=0
0517
0518 tc filter add dev v1 egress pref 77 prot ip \
0519 flower ip_tos 0x14 action pass
0520 vxlan_ping_test $h1 192.0.2.3 "-Q 0x14" v1 egress 77 10
0521 vxlan_ping_test $h1 192.0.2.3 "-Q 0x18" v1 egress 77 0
0522 tc filter del dev v1 egress pref 77 prot ip
0523
0524 log_test "VXLAN: envelope TOS inheritance"
0525 }
0526
0527 __test_ecn_encap()
0528 {
0529 local q=$1; shift
0530 local tos=$1; shift
0531
0532 RET=0
0533
0534 tc filter add dev v1 egress pref 77 prot ip \
0535 flower ip_tos $tos action pass
0536 sleep 1
0537 vxlan_ping_test $h1 192.0.2.3 "-Q $q" v1 egress 77 10
0538 tc filter del dev v1 egress pref 77 prot ip
0539
0540 log_test "VXLAN: ECN encap: $q->$tos"
0541 }
0542
0543 test_ecn_encap()
0544 {
0545
0546 __test_ecn_encap 0x00 0x00
0547 __test_ecn_encap 0x01 0x01
0548 __test_ecn_encap 0x02 0x02
0549 __test_ecn_encap 0x03 0x02
0550 }
0551
0552 vxlan_encapped_ping_do()
0553 {
0554 local count=$1; shift
0555 local dev=$1; shift
0556 local next_hop_mac=$1; shift
0557 local dest_ip=$1; shift
0558 local dest_mac=$1; shift
0559 local inner_tos=$1; shift
0560 local outer_tos=$1; shift
0561
0562 $MZ $dev -c $count -d 100msec -q \
0563 -b $next_hop_mac -B $dest_ip \
0564 -t udp tos=$outer_tos,sp=23456,dp=$VXPORT,p=$(:
0565 )"08:"$( : VXLAN flags
0566 )"00:00:00:"$( : VXLAN reserved
0567 )"00:03:e8:"$( : VXLAN VNI
0568 )"00:"$( : VXLAN reserved
0569 )"$dest_mac:"$( : ETH daddr
0570 )"$(mac_get w2):"$( : ETH saddr
0571 )"08:00:"$( : ETH type
0572 )"45:"$( : IP version + IHL
0573 )"$inner_tos:"$( : IP TOS
0574 )"00:54:"$( : IP total length
0575 )"99:83:"$( : IP identification
0576 )"40:00:"$( : IP flags + frag off
0577 )"40:"$( : IP TTL
0578 )"01:"$( : IP proto
0579 )"00:00:"$( : IP header csum
0580 )"c0:00:02:03:"$( : IP saddr: 192.0.2.3
0581 )"c0:00:02:01:"$( : IP daddr: 192.0.2.1
0582 )"08:"$( : ICMP type
0583 )"00:"$( : ICMP code
0584 )"8b:f2:"$( : ICMP csum
0585 )"1f:6a:"$( : ICMP request identifier
0586 )"00:01:"$( : ICMP request sequence number
0587 )"4f:ff:c5:5b:00:00:00:00:"$( : ICMP payload
0588 )"6d:74:0b:00:00:00:00:00:"$( :
0589 )"10:11:12:13:14:15:16:17:"$( :
0590 )"18:19:1a:1b:1c:1d:1e:1f:"$( :
0591 )"20:21:22:23:24:25:26:27:"$( :
0592 )"28:29:2a:2b:2c:2d:2e:2f:"$( :
0593 )"30:31:32:33:34:35:36:37"
0594 }
0595 export -f vxlan_encapped_ping_do
0596
0597 vxlan_encapped_ping_test()
0598 {
0599 local ping_dev=$1; shift
0600 local nh_dev=$1; shift
0601 local ping_dip=$1; shift
0602 local inner_tos=$1; shift
0603 local outer_tos=$1; shift
0604 local stat_get=$1; shift
0605 local expect=$1; shift
0606
0607 local t0=$($stat_get)
0608
0609 in_ns ns1 \
0610 vxlan_encapped_ping_do 10 $ping_dev $(mac_get $nh_dev) \
0611 $ping_dip $(mac_get $h1) \
0612 $inner_tos $outer_tos
0613
0614 local t1=$($stat_get)
0615 local delta=$((t1 - t0))
0616
0617
0618 ((expect <= delta && delta <= expect + 2))
0619 check_err $? "Expected to capture $expect packets, got $delta."
0620 }
0621 export -f vxlan_encapped_ping_test
0622
0623 __test_ecn_decap()
0624 {
0625 local orig_inner_tos=$1; shift
0626 local orig_outer_tos=$1; shift
0627 local decapped_tos=$1; shift
0628
0629 RET=0
0630
0631 tc filter add dev $h1 ingress pref 77 prot ip \
0632 flower ip_tos $decapped_tos action drop
0633 sleep 1
0634 vxlan_encapped_ping_test v2 v1 192.0.2.17 \
0635 $orig_inner_tos $orig_outer_tos \
0636 "tc_rule_stats_get $h1 77 ingress" 10
0637 tc filter del dev $h1 ingress pref 77
0638
0639 log_test "VXLAN: ECN decap: $orig_outer_tos/$orig_inner_tos->$decapped_tos"
0640 }
0641
0642 test_ecn_decap_error()
0643 {
0644 local orig_inner_tos=00
0645 local orig_outer_tos=03
0646
0647 RET=0
0648
0649 vxlan_encapped_ping_test v2 v1 192.0.2.17 \
0650 $orig_inner_tos $orig_outer_tos \
0651 "link_stats_rx_errors_get vx1" 10
0652
0653 log_test "VXLAN: ECN decap: $orig_outer_tos/$orig_inner_tos->error"
0654 }
0655
0656 test_ecn_decap()
0657 {
0658
0659 __test_ecn_decap 00 00 0x00
0660 __test_ecn_decap 00 01 0x00
0661 __test_ecn_decap 00 02 0x00
0662
0663 __test_ecn_decap 01 00 0x01
0664 __test_ecn_decap 01 01 0x01
0665 __test_ecn_decap 01 02 0x01
0666 __test_ecn_decap 01 03 0x03
0667 __test_ecn_decap 02 00 0x02
0668 __test_ecn_decap 02 01 0x01
0669 __test_ecn_decap 02 02 0x02
0670 __test_ecn_decap 02 03 0x03
0671 __test_ecn_decap 03 00 0x03
0672 __test_ecn_decap 03 01 0x03
0673 __test_ecn_decap 03 02 0x03
0674 __test_ecn_decap 03 03 0x03
0675 test_ecn_decap_error
0676 }
0677
0678 test_learning()
0679 {
0680 local mac=de:ad:be:ef:13:37
0681 local dst=192.0.2.100
0682
0683
0684 ip link set dev br1 type bridge ageing_time 1000
0685 ip link set dev vx1 type vxlan ageing 10
0686 ip link set dev vx1 type vxlan learning
0687 reapply_config
0688
0689
0690 RET=0
0691
0692 vxlan_flood_test $mac $dst 10 10 10
0693
0694 log_test "VXLAN: flood before learning"
0695
0696
0697
0698 RET=0
0699
0700 in_ns ns1 $MZ w2 -c 1 -p 64 -a $mac -b ff:ff:ff:ff:ff:ff -B $dst \
0701 -t icmp -q
0702 sleep 1
0703
0704 bridge fdb show brport vx1 | grep $mac | grep -q self
0705 check_err $?
0706 bridge fdb show brport vx1 | grep $mac | grep -q -v self
0707 check_err $?
0708
0709 log_test "VXLAN: show learned FDB entry"
0710
0711
0712 RET=0
0713
0714 vxlan_flood_test $mac $dst 0 10 0
0715
0716 log_test "VXLAN: learned FDB entry"
0717
0718
0719
0720 RET=0
0721
0722 bridge fdb del dev vx1 $mac master self
0723 sleep 1
0724
0725 vxlan_flood_test $mac $dst 10 10 10
0726
0727 log_test "VXLAN: deletion of learned FDB entry"
0728
0729
0730 RET=0
0731
0732 in_ns ns1 $MZ w2 -c 1 -p 64 -a $mac -b ff:ff:ff:ff:ff:ff -B $dst \
0733 -t icmp -q
0734 sleep 1
0735
0736 bridge fdb show brport vx1 | grep $mac | grep -q self
0737 check_err $?
0738 bridge fdb show brport vx1 | grep $mac | grep -q -v self
0739 check_err $?
0740
0741 vxlan_flood_test $mac $dst 0 10 0
0742
0743 sleep 20
0744
0745 bridge fdb show brport vx1 | grep $mac | grep -q self
0746 check_fail $?
0747 bridge fdb show brport vx1 | grep $mac | grep -q -v self
0748 check_fail $?
0749
0750 vxlan_flood_test $mac $dst 10 10 10
0751
0752 log_test "VXLAN: Ageing of learned FDB entry"
0753
0754
0755
0756 RET=0
0757
0758 ip link set dev vx1 type bridge_slave learning off
0759
0760 in_ns ns1 $MZ w2 -c 1 -p 64 -a $mac -b ff:ff:ff:ff:ff:ff -B $dst \
0761 -t icmp -q
0762 sleep 1
0763
0764 bridge fdb show brport vx1 | grep $mac | grep -q -v self
0765 check_fail $?
0766
0767 ip link set dev vx1 type bridge_slave learning on
0768
0769 in_ns ns1 $MZ w2 -c 1 -p 64 -a $mac -b ff:ff:ff:ff:ff:ff -B $dst \
0770 -t icmp -q
0771 sleep 1
0772
0773 bridge fdb show brport vx1 | grep $mac | grep -q -v self
0774 check_err $?
0775
0776 log_test "VXLAN: learning toggling on bridge port"
0777
0778
0779 ip link set dev vx1 type vxlan nolearning
0780 ip link set dev vx1 type vxlan ageing 300
0781 ip link set dev br1 type bridge ageing_time 30000
0782 reapply_config
0783 }
0784
0785 test_all()
0786 {
0787 echo "Running tests with UDP port $VXPORT"
0788 tests_run
0789 }
0790
0791 trap cleanup EXIT
0792
0793 setup_prepare
0794 setup_wait
0795 test_all
0796
0797 exit $EXIT_STATUS