selftests: forwarding: Add a test for NH group stats

Add to lib.sh support for fetching NH stats, and a new library,
router_mpath_nh_lib.sh, with the common code for testing NH stats.
Use the latter from router_mpath_nh.sh and router_mpath_nh_res.sh.

The test works by sending traffic through a NH group, and checking that the
reported values correspond to what the link that ultimately receives the
traffic reports having seen.

Signed-off-by: Petr Machata <petrm@nvidia.com>
Link: https://lore.kernel.org/r/2a424c54062a5f1efd13b9ec5b2b0e29c6af2574.1709901020.git.petrm@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Petr Machata 2024-03-08 13:59:55 +01:00 committed by Jakub Kicinski
parent 44c2fbebe1
commit a22b042660
5 changed files with 190 additions and 0 deletions

View File

@ -123,6 +123,7 @@ TEST_FILES := devlink_lib.sh \
mirror_gre_topo_lib.sh \
mirror_lib.sh \
mirror_topo_lib.sh \
router_mpath_nh_lib.sh \
sch_ets_core.sh \
sch_ets_tests.sh \
sch_tbf_core.sh \

View File

@ -900,6 +900,33 @@ hw_stats_get()
jq ".[0].stats64.$dir.$stat"
}
__nh_stats_get()
{
local key=$1; shift
local group_id=$1; shift
local member_id=$1; shift
ip -j -s -s nexthop show id $group_id |
jq --argjson member_id "$member_id" --arg key "$key" \
'.[].group_stats[] | select(.id == $member_id) | .[$key]'
}
nh_stats_get()
{
local group_id=$1; shift
local member_id=$1; shift
__nh_stats_get packets "$group_id" "$member_id"
}
nh_stats_get_hw()
{
local group_id=$1; shift
local member_id=$1; shift
__nh_stats_get packets_hw "$group_id" "$member_id"
}
humanize()
{
local speed=$1; shift
@ -2010,3 +2037,10 @@ bail_on_lldpad()
fi
fi
}
absval()
{
local v=$1; shift
echo $((v > 0 ? v : -v))
}

View File

@ -7,9 +7,12 @@ ALL_TESTS="
multipath_test
ping_ipv4_blackhole
ping_ipv6_blackhole
nh_stats_test_v4
nh_stats_test_v6
"
NUM_NETIFS=8
source lib.sh
source router_mpath_nh_lib.sh
h1_create()
{
@ -325,6 +328,16 @@ ping_ipv6_blackhole()
ip -6 nexthop del id 1001
}
nh_stats_test_v4()
{
__nh_stats_test_v4 mpath
}
nh_stats_test_v6()
{
__nh_stats_test_v6 mpath
}
setup_prepare()
{
h1=${NETIFS[p1]}

View File

@ -0,0 +1,129 @@
# SPDX-License-Identifier: GPL-2.0
nh_stats_do_test()
{
local what=$1; shift
local nh1_id=$1; shift
local nh2_id=$1; shift
local group_id=$1; shift
local stats_get=$1; shift
local mz="$@"
local dp
RET=0
sleep 2
for ((dp=0; dp < 60000; dp += 10000)); do
local dd
local t0_rp12=$(link_stats_tx_packets_get $rp12)
local t0_rp13=$(link_stats_tx_packets_get $rp13)
local t0_nh1=$($stats_get $group_id $nh1_id)
local t0_nh2=$($stats_get $group_id $nh2_id)
ip vrf exec vrf-h1 \
$mz -q -p 64 -d 0 -t udp \
"sp=1024,dp=$((dp))-$((dp + 10000))"
sleep 2
local t1_rp12=$(link_stats_tx_packets_get $rp12)
local t1_rp13=$(link_stats_tx_packets_get $rp13)
local t1_nh1=$($stats_get $group_id $nh1_id)
local t1_nh2=$($stats_get $group_id $nh2_id)
local d_rp12=$((t1_rp12 - t0_rp12))
local d_rp13=$((t1_rp13 - t0_rp13))
local d_nh1=$((t1_nh1 - t0_nh1))
local d_nh2=$((t1_nh2 - t0_nh2))
dd=$(absval $((d_rp12 - d_nh1)))
((dd < 10))
check_err $? "Discrepancy between link and $stats_get: d_rp12=$d_rp12 d_nh1=$d_nh1"
dd=$(absval $((d_rp13 - d_nh2)))
((dd < 10))
check_err $? "Discrepancy between link and $stats_get: d_rp13=$d_rp13 d_nh2=$d_nh2"
done
log_test "NH stats test $what"
}
nh_stats_test_dispatch_swhw()
{
local what=$1; shift
local nh1_id=$1; shift
local nh2_id=$1; shift
local group_id=$1; shift
local mz="$@"
local used
nh_stats_do_test "$what" "$nh1_id" "$nh2_id" "$group_id" \
nh_stats_get "${mz[@]}"
used=$(ip -s -j -d nexthop show id $group_id |
jq '.[].hw_stats.used')
kind=$(ip -j -d link show dev $rp11 |
jq -r '.[].linkinfo.info_kind')
if [[ $used == true ]]; then
nh_stats_do_test "HW $what" "$nh1_id" "$nh2_id" "$group_id" \
nh_stats_get_hw "${mz[@]}"
elif [[ $kind == veth ]]; then
log_test_skip "HW stats not offloaded on veth topology"
fi
}
nh_stats_test_dispatch()
{
local nhgtype=$1; shift
local what=$1; shift
local nh1_id=$1; shift
local nh2_id=$1; shift
local group_id=$1; shift
local mz="$@"
local enabled
local kind
if ! ip nexthop help 2>&1 | grep -q hw_stats; then
log_test_skip "NH stats test: ip doesn't support HW stats"
return
fi
ip nexthop replace id $group_id group $nh1_id/$nh2_id \
hw_stats on type $nhgtype
enabled=$(ip -s -j -d nexthop show id $group_id |
jq '.[].hw_stats.enabled')
if [[ $enabled == true ]]; then
nh_stats_test_dispatch_swhw "$what" "$nh1_id" "$nh2_id" \
"$group_id" "${mz[@]}"
elif [[ $enabled == false ]]; then
check_err 1 "HW stats still disabled after enabling"
log_test "NH stats test"
else
log_test_skip "NH stats test: ip doesn't report hw_stats info"
fi
ip nexthop replace id $group_id group $nh1_id/$nh2_id \
hw_stats off type $nhgtype
}
__nh_stats_test_v4()
{
local nhgtype=$1; shift
sysctl_set net.ipv4.fib_multipath_hash_policy 1
nh_stats_test_dispatch $nhgtype "IPv4" 101 102 103 \
$MZ $h1 -A 192.0.2.2 -B 198.51.100.2
sysctl_restore net.ipv4.fib_multipath_hash_policy
}
__nh_stats_test_v6()
{
local nhgtype=$1; shift
sysctl_set net.ipv6.fib_multipath_hash_policy 1
nh_stats_test_dispatch $nhgtype "IPv6" 104 105 106 \
$MZ -6 $h1 -A 2001:db8:1::2 -B 2001:db8:2::2
sysctl_restore net.ipv6.fib_multipath_hash_policy
}

View File

@ -5,9 +5,12 @@ ALL_TESTS="
ping_ipv4
ping_ipv6
multipath_test
nh_stats_test_v4
nh_stats_test_v6
"
NUM_NETIFS=8
source lib.sh
source router_mpath_nh_lib.sh
h1_create()
{
@ -333,6 +336,16 @@ multipath_test()
ip nexthop replace id 106 group 104,1/105,1 type resilient
}
nh_stats_test_v4()
{
__nh_stats_test_v4 resilient
}
nh_stats_test_v6()
{
__nh_stats_test_v6 resilient
}
setup_prepare()
{
h1=${NETIFS[p1]}