git: 4d37c2ea3c86 - main - routing: Add test for nexthop subscription

From: Pouria Mousavizadeh Tehrani <pouria_at_FreeBSD.org>
Date: Sat, 11 Jul 2026 19:26:24 UTC
The branch main has been updated by pouria:

URL: https://cgit.FreeBSD.org/src/commit/?id=4d37c2ea3c863e802a0d58a70331f4da9e41486c

commit 4d37c2ea3c863e802a0d58a70331f4da9e41486c
Author:     Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
AuthorDate: 2026-06-12 20:22:47 +0000
Commit:     Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
CommitDate: 2026-07-11 18:23:09 +0000

    routing: Add test for nexthop subscription
    
    Make sure we have reachability when one of our nexthops
    gets down without deleting the route.
    
    Differential Revision: https://reviews.freebsd.org/D57552
---
 tests/sys/net/routing/test_routing.sh | 90 ++++++++++++++++++++++++++++++++---
 1 file changed, 84 insertions(+), 6 deletions(-)

diff --git a/tests/sys/net/routing/test_routing.sh b/tests/sys/net/routing/test_routing.sh
index 296bd7ebaffd..644b0381bca5 100755
--- a/tests/sys/net/routing/test_routing.sh
+++ b/tests/sys/net/routing/test_routing.sh
@@ -34,7 +34,6 @@ add_lowest_metric_head()
 	atf_set require.user root
 	atf_set require.progs jq
 }
-
 add_lowest_metric_body()
 {
 	local epair laddr route nhop1 nhop2 nhop3
@@ -83,7 +82,6 @@ add_lowest_metric_body()
 	atf_check -o match:".*gateway: ${nhop1}.*" \
 	    route -n6 get -net ${route}/64
 }
-
 add_lowest_metric_cleanup()
 {
 	vnet_cleanup
@@ -96,7 +94,6 @@ add_default_metric_head()
 	atf_set require.user root
 	atf_set require.progs jq
 }
-
 add_default_metric_body()
 {
 	local epair laddr route nhop1
@@ -121,7 +118,6 @@ add_default_metric_body()
 	output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop1} 1 1)
 	atf_check_equal "$output" "$nhop1"
 }
-
 add_default_metric_cleanup()
 {
 	vnet_cleanup
@@ -134,7 +130,6 @@ delete_route_with_metric_head()
 	atf_set require.user root
 	atf_set require.progs jq
 }
-
 delete_route_with_metric_body()
 {
 	local epair laddr route nhop1 nhop2
@@ -216,16 +211,99 @@ delete_route_with_metric_body()
 	output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop2} 1 4)
 	atf_check_equal "$output" "$nhop2"
 }
-
 delete_route_with_metric_cleanup()
 {
 	vnet_cleanup
 }
 
+atf_test_case "test_ecmp_routes_by_event" "cleanup"
+test_ecmp_routes_by_event_head()
+{
+	atf_set descr 'Test reachability of ECMP routes when an ifp gets down'
+	atf_set require.user root
+}
+test_ecmp_routes_by_event_body()
+{
+	local jname epair0 epair1 lo0_addr lo1_addr ep0_prefix ep1_prefix
+
+	jname="ecmp_route_by_event"
+	lo0_addr="3fff:a::1"
+	lo1_addr="3fff:b::1"
+	ep0_prefix="3fff:1::"
+	ep1_prefix="3fff:2::"
+
+	vnet_init
+	epair0=$(vnet_mkepair)
+	epair1=$(vnet_mkepair)
+
+	vnet_mkjail ${jname} ${epair0}b
+	atf_check -o ignore \
+	    ifconfig ${epair1}b vnet ${jname}
+
+	atf_check -o ignore \
+	    ifconfig ${epair0}a inet6 ${ep0_prefix}a/127 up
+	atf_check -o ignore \
+	    ifconfig ${epair1}a inet6 ${ep1_prefix}a/127 up
+	atf_check -o ignore \
+	    ifconfig -j ${jname} ${epair0}b inet6 ${ep0_prefix}b/127 up
+	atf_check -o ignore \
+	    ifconfig -j ${jname} ${epair1}b inet6 ${ep1_prefix}b/127 up
+	atf_check -o ignore \
+	    ifconfig lo0 inet6 ${lo0_addr}/128 up
+	atf_check -o ignore \
+	    ifconfig -j ${jname} lo0 inet6 ${lo1_addr}/128 up
+
+	# Create ECMP routes with via epair0 and epair1 to loopback
+	atf_check -o ignore \
+	    route -6 add -net ${lo1_addr}/128 -gateway ${ep0_prefix}b
+	atf_check -o ignore \
+	    route -6 add -net ${lo1_addr}/128 -gateway ${ep1_prefix}b
+	atf_check -o ignore \
+	    route -6j ${jname} add -net ${lo0_addr}/128 -gateway ${ep0_prefix}a
+	atf_check -o ignore \
+	    route -6j ${jname} add -net ${lo0_addr}/128 -gateway ${ep1_prefix}a
+
+	# Check the connection
+	atf_check -o ignore ping -c1 -t1 ${ep0_prefix}b
+	atf_check -o ignore ping -c1 -t1 ${ep1_prefix}b
+	atf_check -o ignore ping -c1 -t1 -S ${lo0_addr} ${lo1_addr}
+
+	# Down one of the nexthop interfaces
+	atf_check -o ignore \
+	    ifconfig ${epair0}a down
+	# Since epair doesn't support linkstate and we need to receive
+	# the icmp reply, shutdown the other side of epair too
+	atf_check -o ignore \
+	    ifconfig -j${jname} ${epair0}b down
+
+	# Test if our destination is still reachable
+	sleep 0.01
+	atf_check -o ignore ping -c1 -t1 -S ${lo0_addr} ${lo1_addr}
+
+	# Do the same thing for other interface
+	atf_check -o ignore \
+	    ifconfig ${epair0}a up
+	atf_check -o ignore \
+	    ifconfig -j${jname} ${epair0}b up
+	atf_check -o ignore \
+	    ifconfig ${epair1}a down
+	atf_check -o ignore \
+	    ifconfig -j${jname} ${epair1}b down
+
+	# Test if our destination is still reachable
+	sleep 0.01
+	atf_check -o ignore ping -c1 -t1 -S ${lo0_addr} ${lo1_addr}
+}
+test_ecmp_routes_by_event_cleanup()
+{
+	vnet_cleanup
+}
+
 
 atf_init_test_cases()
 {
 	atf_add_test_case "add_lowest_metric"
 	atf_add_test_case "add_default_metric"
 	atf_add_test_case "delete_route_with_metric"
+	atf_add_test_case "test_ecmp_routes_by_event"
 }