| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- #!/bin/bash
- # SPDX-License-Identifier: GPL-2.0
- #
- # Test unicast FIB offload indication.
- lib_dir=$(dirname $0)/../../../net/forwarding
- ALL_TESTS="
- ipv6_route_add
- ipv6_route_replace
- ipv6_route_nexthop_group_share
- ipv6_route_rate
- "
- NUM_NETIFS=4
- source $lib_dir/lib.sh
- source $lib_dir/devlink_lib.sh
- tor1_create()
- {
- simple_if_init $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
- }
- tor1_destroy()
- {
- simple_if_fini $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
- }
- tor2_create()
- {
- simple_if_init $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
- }
- tor2_destroy()
- {
- simple_if_fini $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
- }
- spine_create()
- {
- ip link set dev $spine_p1 up
- ip link set dev $spine_p2 up
- __addr_add_del $spine_p1 add 2001:db8:1::1/64
- __addr_add_del $spine_p2 add 2001:db8:2::1/64
- }
- spine_destroy()
- {
- __addr_add_del $spine_p2 del 2001:db8:2::1/64
- __addr_add_del $spine_p1 del 2001:db8:1::1/64
- ip link set dev $spine_p2 down
- ip link set dev $spine_p1 down
- }
- ipv6_offload_check()
- {
- local pfx="$1"; shift
- local expected_num=$1; shift
- local num
- # Try to avoid races with route offload
- sleep .1
- num=$(ip -6 route show match ${pfx} | grep "offload" | wc -l)
- if [ $num -eq $expected_num ]; then
- return 0
- fi
- return 1
- }
- ipv6_route_add_prefix()
- {
- RET=0
- # Add a prefix route and check that it is offloaded.
- ip -6 route add 2001:db8:3::/64 dev $spine_p1 metric 100
- ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
- check_err $? "prefix route not offloaded"
- # Append an identical prefix route with an higher metric and check that
- # offload indication did not change.
- ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 200
- ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
- check_err $? "lowest metric not offloaded after append"
- ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
- check_err $? "highest metric offloaded when should not"
- # Prepend an identical prefix route with lower metric and check that
- # it is offloaded and the others are not.
- ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 10
- ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 10" 1
- check_err $? "lowest metric not offloaded after prepend"
- ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 0
- check_err $? "mid metric offloaded when should not"
- ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
- check_err $? "highest metric offloaded when should not"
- # Delete the routes and add the same route with a different nexthop
- # device. Check that it is offloaded.
- ip -6 route flush 2001:db8:3::/64 dev $spine_p1
- ip -6 route add 2001:db8:3::/64 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64 dev $spine_p2" 1
- log_test "IPv6 prefix route add"
- ip -6 route flush 2001:db8:3::/64
- }
- ipv6_route_add_mpath()
- {
- RET=0
- # Add a multipath route and check that it is offloaded.
- ip -6 route add 2001:db8:3::/64 metric 100 \
- nexthop via 2001:db8:1::2 dev $spine_p1 \
- nexthop via 2001:db8:2::2 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64 metric 100" 2
- check_err $? "multipath route not offloaded when should"
- # Append another nexthop and check that it is offloaded as well.
- ip -6 route append 2001:db8:3::/64 metric 100 \
- nexthop via 2001:db8:1::3 dev $spine_p1
- ipv6_offload_check "2001:db8:3::/64 metric 100" 3
- check_err $? "appended nexthop not offloaded when should"
- # Mimic route replace by removing the route and adding it back with
- # only two nexthops.
- ip -6 route del 2001:db8:3::/64
- ip -6 route add 2001:db8:3::/64 metric 100 \
- nexthop via 2001:db8:1::2 dev $spine_p1 \
- nexthop via 2001:db8:2::2 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64 metric 100" 2
- check_err $? "multipath route not offloaded after delete & add"
- # Append a nexthop with an higher metric and check that the offload
- # indication did not change.
- ip -6 route append 2001:db8:3::/64 metric 200 \
- nexthop via 2001:db8:1::3 dev $spine_p1
- ipv6_offload_check "2001:db8:3::/64 metric 100" 2
- check_err $? "lowest metric not offloaded after append"
- ipv6_offload_check "2001:db8:3::/64 metric 200" 0
- check_err $? "highest metric offloaded when should not"
- # Prepend a nexthop with a lower metric and check that it is offloaded
- # and the others are not.
- ip -6 route append 2001:db8:3::/64 metric 10 \
- nexthop via 2001:db8:1::3 dev $spine_p1
- ipv6_offload_check "2001:db8:3::/64 metric 10" 1
- check_err $? "lowest metric not offloaded after prepend"
- ipv6_offload_check "2001:db8:3::/64 metric 100" 0
- check_err $? "mid metric offloaded when should not"
- ipv6_offload_check "2001:db8:3::/64 metric 200" 0
- check_err $? "highest metric offloaded when should not"
- log_test "IPv6 multipath route add"
- ip -6 route flush 2001:db8:3::/64
- }
- ipv6_route_add()
- {
- ipv6_route_add_prefix
- ipv6_route_add_mpath
- }
- ipv6_route_replace()
- {
- RET=0
- # Replace prefix route with prefix route.
- ip -6 route add 2001:db8:3::/64 metric 100 dev $spine_p1
- ipv6_offload_check "2001:db8:3::/64 metric 100" 1
- check_err $? "prefix route not offloaded when should"
- ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64 metric 100" 1
- check_err $? "prefix route not offloaded after replace"
- # Replace prefix route with multipath route.
- ip -6 route replace 2001:db8:3::/64 metric 100 \
- nexthop via 2001:db8:1::2 dev $spine_p1 \
- nexthop via 2001:db8:2::2 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64 metric 100" 2
- check_err $? "multipath route not offloaded after replace"
- # Replace multipath route with prefix route. A prefix route cannot
- # replace a multipath route, so it is appended.
- ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p1
- ipv6_offload_check "2001:db8:3::/64 metric 100 dev $spine_p1" 0
- check_err $? "prefix route offloaded after 'replacing' multipath route"
- ipv6_offload_check "2001:db8:3::/64 metric 100" 2
- check_err $? "multipath route not offloaded after being 'replaced' by prefix route"
- # Replace multipath route with multipath route.
- ip -6 route replace 2001:db8:3::/64 metric 100 \
- nexthop via 2001:db8:1::3 dev $spine_p1 \
- nexthop via 2001:db8:2::3 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64 metric 100" 2
- check_err $? "multipath route not offloaded after replacing multipath route"
- # Replace a non-existing multipath route with a multipath route and
- # check that it is appended and not offloaded.
- ip -6 route replace 2001:db8:3::/64 metric 200 \
- nexthop via 2001:db8:1::3 dev $spine_p1 \
- nexthop via 2001:db8:2::3 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64 metric 100" 2
- check_err $? "multipath route not offloaded after non-existing route was 'replaced'"
- ipv6_offload_check "2001:db8:3::/64 metric 200" 0
- check_err $? "multipath route offloaded after 'replacing' non-existing route"
- log_test "IPv6 route replace"
- ip -6 route flush 2001:db8:3::/64
- }
- ipv6_route_nexthop_group_share()
- {
- RET=0
- # The driver consolidates identical nexthop groups in order to reduce
- # the resource usage in its adjacency table. Check that the deletion
- # of one multipath route using the group does not affect the other.
- ip -6 route add 2001:db8:3::/64 \
- nexthop via 2001:db8:1::2 dev $spine_p1 \
- nexthop via 2001:db8:2::2 dev $spine_p2
- ip -6 route add 2001:db8:4::/64 \
- nexthop via 2001:db8:1::2 dev $spine_p1 \
- nexthop via 2001:db8:2::2 dev $spine_p2
- ipv6_offload_check "2001:db8:3::/64" 2
- check_err $? "multipath route not offloaded when should"
- ipv6_offload_check "2001:db8:4::/64" 2
- check_err $? "multipath route not offloaded when should"
- ip -6 route del 2001:db8:3::/64
- ipv6_offload_check "2001:db8:4::/64" 2
- check_err $? "multipath route not offloaded after deletion of route sharing the nexthop group"
- # Check that after unsharing a nexthop group the routes are still
- # marked as offloaded.
- ip -6 route add 2001:db8:3::/64 \
- nexthop via 2001:db8:1::2 dev $spine_p1 \
- nexthop via 2001:db8:2::2 dev $spine_p2
- ip -6 route del 2001:db8:4::/64 \
- nexthop via 2001:db8:1::2 dev $spine_p1
- ipv6_offload_check "2001:db8:4::/64" 1
- check_err $? "singlepath route not offloaded after unsharing the nexthop group"
- ipv6_offload_check "2001:db8:3::/64" 2
- check_err $? "multipath route not offloaded after unsharing the nexthop group"
- log_test "IPv6 nexthop group sharing"
- ip -6 route flush 2001:db8:3::/64
- ip -6 route flush 2001:db8:4::/64
- }
- ipv6_route_rate()
- {
- local batch_dir=$(mktemp -d)
- local num_rts=$((40 * 1024))
- local num_nhs=16
- local total
- local start
- local diff
- local end
- local nhs
- local i
- RET=0
- # Prepare 40K /64 multipath routes with 16 nexthops each and check how
- # long it takes to add them. A limit of 60 seconds is set. It is much
- # higher than insertion should take and meant to flag a serious
- # regression.
- total=$((nums_nhs * num_rts))
- for i in $(seq 1 $num_nhs); do
- ip -6 address add 2001:db8:1::10:$i/128 dev $tor1_p1
- nexthops+=" nexthop via 2001:db8:1::10:$i dev $spine_p1"
- done
- for i in $(seq 1 $num_rts); do
- echo "route add 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
- >> $batch_dir/add.batch
- echo "route del 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
- >> $batch_dir/del.batch
- done
- start=$(date +%s.%N)
- ip -batch $batch_dir/add.batch
- count=$(ip -6 route show | grep offload | wc -l)
- while [ $count -lt $total ]; do
- sleep .01
- count=$(ip -6 route show | grep offload | wc -l)
- done
- end=$(date +%s.%N)
- diff=$(echo "$end - $start" | bc -l)
- test "$(echo "$diff > 60" | bc -l)" -eq 0
- check_err $? "route insertion took too long"
- log_info "inserted $num_rts routes in $diff seconds"
- log_test "IPv6 routes insertion rate"
- ip -batch $batch_dir/del.batch
- for i in $(seq 1 $num_nhs); do
- ip -6 address del 2001:db8:1::10:$i/128 dev $tor1_p1
- done
- rm -rf $batch_dir
- }
- setup_prepare()
- {
- spine_p1=${NETIFS[p1]}
- tor1_p1=${NETIFS[p2]}
- spine_p2=${NETIFS[p3]}
- tor2_p1=${NETIFS[p4]}
- vrf_prepare
- forwarding_enable
- tor1_create
- tor2_create
- spine_create
- }
- cleanup()
- {
- pre_cleanup
- spine_destroy
- tor2_destroy
- tor1_destroy
- forwarding_restore
- vrf_cleanup
- }
- trap cleanup EXIT
- setup_prepare
- setup_wait
- tests_run
- exit $EXIT_STATUS
|