Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 #
0004 # Test unicast FIB offload indication.
0005 
0006 lib_dir=$(dirname $0)/../../../net/forwarding
0007 
0008 ALL_TESTS="
0009         ipv6_route_add
0010         ipv6_route_replace
0011         ipv6_route_nexthop_group_share
0012         ipv6_route_rate
0013 "
0014 NUM_NETIFS=4
0015 source $lib_dir/lib.sh
0016 source $lib_dir/devlink_lib.sh
0017 
0018 tor1_create()
0019 {
0020         simple_if_init $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
0021 }
0022 
0023 tor1_destroy()
0024 {
0025         simple_if_fini $tor1_p1 2001:db8:1::2/128 2001:db8:1::3/128
0026 }
0027 
0028 tor2_create()
0029 {
0030         simple_if_init $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
0031 }
0032 
0033 tor2_destroy()
0034 {
0035         simple_if_fini $tor2_p1 2001:db8:2::2/128 2001:db8:2::3/128
0036 }
0037 
0038 spine_create()
0039 {
0040         ip link set dev $spine_p1 up
0041         ip link set dev $spine_p2 up
0042 
0043         __addr_add_del $spine_p1 add 2001:db8:1::1/64
0044         __addr_add_del $spine_p2 add 2001:db8:2::1/64
0045 }
0046 
0047 spine_destroy()
0048 {
0049         __addr_add_del $spine_p2 del 2001:db8:2::1/64
0050         __addr_add_del $spine_p1 del 2001:db8:1::1/64
0051 
0052         ip link set dev $spine_p2 down
0053         ip link set dev $spine_p1 down
0054 }
0055 
0056 ipv6_offload_check()
0057 {
0058         local pfx="$1"; shift
0059         local expected_num=$1; shift
0060         local num
0061 
0062         # Try to avoid races with route offload
0063         sleep .1
0064 
0065         num=$(ip -6 route show match ${pfx} | grep "offload" | wc -l)
0066 
0067         if [ $num -eq $expected_num ]; then
0068                 return 0
0069         fi
0070 
0071         return 1
0072 }
0073 
0074 ipv6_route_add_prefix()
0075 {
0076         RET=0
0077 
0078         # Add a prefix route and check that it is offloaded.
0079         ip -6 route add 2001:db8:3::/64 dev $spine_p1 metric 100
0080         ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
0081         check_err $? "prefix route not offloaded"
0082 
0083         # Append an identical prefix route with an higher metric and check that
0084         # offload indication did not change.
0085         ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 200
0086         ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 1
0087         check_err $? "lowest metric not offloaded after append"
0088         ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
0089         check_err $? "highest metric offloaded when should not"
0090 
0091         # Prepend an identical prefix route with lower metric and check that
0092         # it is offloaded and the others are not.
0093         ip -6 route append 2001:db8:3::/64 dev $spine_p1 metric 10
0094         ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 10" 1
0095         check_err $? "lowest metric not offloaded after prepend"
0096         ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 100" 0
0097         check_err $? "mid metric offloaded when should not"
0098         ipv6_offload_check "2001:db8:3::/64 dev $spine_p1 metric 200" 0
0099         check_err $? "highest metric offloaded when should not"
0100 
0101         # Delete the routes and add the same route with a different nexthop
0102         # device. Check that it is offloaded.
0103         ip -6 route flush 2001:db8:3::/64 dev $spine_p1
0104         ip -6 route add 2001:db8:3::/64 dev $spine_p2
0105         ipv6_offload_check "2001:db8:3::/64 dev $spine_p2" 1
0106 
0107         log_test "IPv6 prefix route add"
0108 
0109         ip -6 route flush 2001:db8:3::/64
0110 }
0111 
0112 ipv6_route_add_mpath()
0113 {
0114         RET=0
0115 
0116         # Add a multipath route and check that it is offloaded.
0117         ip -6 route add 2001:db8:3::/64 metric 100 \
0118                 nexthop via 2001:db8:1::2 dev $spine_p1 \
0119                 nexthop via 2001:db8:2::2 dev $spine_p2
0120         ipv6_offload_check "2001:db8:3::/64 metric 100" 2
0121         check_err $? "multipath route not offloaded when should"
0122 
0123         # Append another nexthop and check that it is offloaded as well.
0124         ip -6 route append 2001:db8:3::/64 metric 100 \
0125                 nexthop via 2001:db8:1::3 dev $spine_p1
0126         ipv6_offload_check "2001:db8:3::/64 metric 100" 3
0127         check_err $? "appended nexthop not offloaded when should"
0128 
0129         # Mimic route replace by removing the route and adding it back with
0130         # only two nexthops.
0131         ip -6 route del 2001:db8:3::/64
0132         ip -6 route add 2001:db8:3::/64 metric 100 \
0133                 nexthop via 2001:db8:1::2 dev $spine_p1 \
0134                 nexthop via 2001:db8:2::2 dev $spine_p2
0135         ipv6_offload_check "2001:db8:3::/64 metric 100" 2
0136         check_err $? "multipath route not offloaded after delete & add"
0137 
0138         # Append a nexthop with an higher metric and check that the offload
0139         # indication did not change.
0140         ip -6 route append 2001:db8:3::/64 metric 200 \
0141                 nexthop via 2001:db8:1::3 dev $spine_p1
0142         ipv6_offload_check "2001:db8:3::/64 metric 100" 2
0143         check_err $? "lowest metric not offloaded after append"
0144         ipv6_offload_check "2001:db8:3::/64 metric 200" 0
0145         check_err $? "highest metric offloaded when should not"
0146 
0147         # Prepend a nexthop with a lower metric and check that it is offloaded
0148         # and the others are not.
0149         ip -6 route append 2001:db8:3::/64 metric 10 \
0150                 nexthop via 2001:db8:1::3 dev $spine_p1
0151         ipv6_offload_check "2001:db8:3::/64 metric 10" 1
0152         check_err $? "lowest metric not offloaded after prepend"
0153         ipv6_offload_check "2001:db8:3::/64 metric 100" 0
0154         check_err $? "mid metric offloaded when should not"
0155         ipv6_offload_check "2001:db8:3::/64 metric 200" 0
0156         check_err $? "highest metric offloaded when should not"
0157 
0158         log_test "IPv6 multipath route add"
0159 
0160         ip -6 route flush 2001:db8:3::/64
0161 }
0162 
0163 ipv6_route_add()
0164 {
0165         ipv6_route_add_prefix
0166         ipv6_route_add_mpath
0167 }
0168 
0169 ipv6_route_replace()
0170 {
0171         RET=0
0172 
0173         # Replace prefix route with prefix route.
0174         ip -6 route add 2001:db8:3::/64 metric 100 dev $spine_p1
0175         ipv6_offload_check "2001:db8:3::/64 metric 100" 1
0176         check_err $? "prefix route not offloaded when should"
0177         ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p2
0178         ipv6_offload_check "2001:db8:3::/64 metric 100" 1
0179         check_err $? "prefix route not offloaded after replace"
0180 
0181         # Replace prefix route with multipath route.
0182         ip -6 route replace 2001:db8:3::/64 metric 100 \
0183                 nexthop via 2001:db8:1::2 dev $spine_p1 \
0184                 nexthop via 2001:db8:2::2 dev $spine_p2
0185         ipv6_offload_check "2001:db8:3::/64 metric 100" 2
0186         check_err $? "multipath route not offloaded after replace"
0187 
0188         # Replace multipath route with prefix route. A prefix route cannot
0189         # replace a multipath route, so it is appended.
0190         ip -6 route replace 2001:db8:3::/64 metric 100 dev $spine_p1
0191         ipv6_offload_check "2001:db8:3::/64 metric 100 dev $spine_p1" 0
0192         check_err $? "prefix route offloaded after 'replacing' multipath route"
0193         ipv6_offload_check "2001:db8:3::/64 metric 100" 2
0194         check_err $? "multipath route not offloaded after being 'replaced' by prefix route"
0195 
0196         # Replace multipath route with multipath route.
0197         ip -6 route replace 2001:db8:3::/64 metric 100 \
0198                 nexthop via 2001:db8:1::3 dev $spine_p1 \
0199                 nexthop via 2001:db8:2::3 dev $spine_p2
0200         ipv6_offload_check "2001:db8:3::/64 metric 100" 2
0201         check_err $? "multipath route not offloaded after replacing multipath route"
0202 
0203         # Replace a non-existing multipath route with a multipath route and
0204         # check that it is appended and not offloaded.
0205         ip -6 route replace 2001:db8:3::/64 metric 200 \
0206                 nexthop via 2001:db8:1::3 dev $spine_p1 \
0207                 nexthop via 2001:db8:2::3 dev $spine_p2
0208         ipv6_offload_check "2001:db8:3::/64 metric 100" 2
0209         check_err $? "multipath route not offloaded after non-existing route was 'replaced'"
0210         ipv6_offload_check "2001:db8:3::/64 metric 200" 0
0211         check_err $? "multipath route offloaded after 'replacing' non-existing route"
0212 
0213         log_test "IPv6 route replace"
0214 
0215         ip -6 route flush 2001:db8:3::/64
0216 }
0217 
0218 ipv6_route_nexthop_group_share()
0219 {
0220         RET=0
0221 
0222         # The driver consolidates identical nexthop groups in order to reduce
0223         # the resource usage in its adjacency table. Check that the deletion
0224         # of one multipath route using the group does not affect the other.
0225         ip -6 route add 2001:db8:3::/64 \
0226                 nexthop via 2001:db8:1::2 dev $spine_p1 \
0227                 nexthop via 2001:db8:2::2 dev $spine_p2
0228         ip -6 route add 2001:db8:4::/64 \
0229                 nexthop via 2001:db8:1::2 dev $spine_p1 \
0230                 nexthop via 2001:db8:2::2 dev $spine_p2
0231         ipv6_offload_check "2001:db8:3::/64" 2
0232         check_err $? "multipath route not offloaded when should"
0233         ipv6_offload_check "2001:db8:4::/64" 2
0234         check_err $? "multipath route not offloaded when should"
0235         ip -6 route del 2001:db8:3::/64
0236         ipv6_offload_check "2001:db8:4::/64" 2
0237         check_err $? "multipath route not offloaded after deletion of route sharing the nexthop group"
0238 
0239         # Check that after unsharing a nexthop group the routes are still
0240         # marked as offloaded.
0241         ip -6 route add 2001:db8:3::/64 \
0242                 nexthop via 2001:db8:1::2 dev $spine_p1 \
0243                 nexthop via 2001:db8:2::2 dev $spine_p2
0244         ip -6 route del 2001:db8:4::/64 \
0245                 nexthop via 2001:db8:1::2 dev $spine_p1
0246         ipv6_offload_check "2001:db8:4::/64" 1
0247         check_err $? "singlepath route not offloaded after unsharing the nexthop group"
0248         ipv6_offload_check "2001:db8:3::/64" 2
0249         check_err $? "multipath route not offloaded after unsharing the nexthop group"
0250 
0251         log_test "IPv6 nexthop group sharing"
0252 
0253         ip -6 route flush 2001:db8:3::/64
0254         ip -6 route flush 2001:db8:4::/64
0255 }
0256 
0257 ipv6_route_rate()
0258 {
0259         local batch_dir=$(mktemp -d)
0260         local num_rts=$((40 * 1024))
0261         local num_nhs=16
0262         local total
0263         local start
0264         local diff
0265         local end
0266         local nhs
0267         local i
0268 
0269         RET=0
0270 
0271         # Prepare 40K /64 multipath routes with 16 nexthops each and check how
0272         # long it takes to add them. A limit of 60 seconds is set. It is much
0273         # higher than insertion should take and meant to flag a serious
0274         # regression.
0275         total=$((nums_nhs * num_rts))
0276 
0277         for i in $(seq 1 $num_nhs); do
0278                 ip -6 address add 2001:db8:1::10:$i/128 dev $tor1_p1
0279                 nexthops+=" nexthop via 2001:db8:1::10:$i dev $spine_p1"
0280         done
0281 
0282         for i in $(seq 1 $num_rts); do
0283                 echo "route add 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
0284                         >> $batch_dir/add.batch
0285                 echo "route del 2001:db8:8:$(printf "%x" $i)::/64$nexthops" \
0286                         >> $batch_dir/del.batch
0287         done
0288 
0289         start=$(date +%s.%N)
0290 
0291         ip -batch $batch_dir/add.batch
0292         count=$(ip -6 route show | grep offload | wc -l)
0293         while [ $count -lt $total ]; do
0294                 sleep .01
0295                 count=$(ip -6 route show | grep offload | wc -l)
0296         done
0297 
0298         end=$(date +%s.%N)
0299 
0300         diff=$(echo "$end - $start" | bc -l)
0301         test "$(echo "$diff > 60" | bc -l)" -eq 0
0302         check_err $? "route insertion took too long"
0303         log_info "inserted $num_rts routes in $diff seconds"
0304 
0305         log_test "IPv6 routes insertion rate"
0306 
0307         ip -batch $batch_dir/del.batch
0308         for i in $(seq 1 $num_nhs); do
0309                 ip -6 address del 2001:db8:1::10:$i/128 dev $tor1_p1
0310         done
0311         rm -rf $batch_dir
0312 }
0313 
0314 setup_prepare()
0315 {
0316         spine_p1=${NETIFS[p1]}
0317         tor1_p1=${NETIFS[p2]}
0318 
0319         spine_p2=${NETIFS[p3]}
0320         tor2_p1=${NETIFS[p4]}
0321 
0322         vrf_prepare
0323         forwarding_enable
0324 
0325         tor1_create
0326         tor2_create
0327         spine_create
0328 }
0329 
0330 cleanup()
0331 {
0332         pre_cleanup
0333 
0334         spine_destroy
0335         tor2_destroy
0336         tor1_destroy
0337 
0338         forwarding_restore
0339         vrf_cleanup
0340 }
0341 
0342 trap cleanup EXIT
0343 
0344 setup_prepare
0345 setup_wait
0346 
0347 tests_run
0348 
0349 exit $EXIT_STATUS