Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177391135
D57016.1794276938.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
D57016.1794276938.diff
View Options
diff --git a/tests/sys/net/routing/Makefile b/tests/sys/net/routing/Makefile
--- a/tests/sys/net/routing/Makefile
+++ b/tests/sys/net/routing/Makefile
@@ -8,6 +8,7 @@
ATF_TESTS_C += test_rtsock_ops
ATF_TESTS_PYTEST += test_routing_l3.py
ATF_TESTS_PYTEST += test_rtsock_multipath.py
+ATF_TESTS_SH+= test_routing
${PACKAGE}FILES+= generic_cleanup.sh
${PACKAGE}FILESMODE_generic_cleanup.sh=0555
diff --git a/tests/sys/net/routing/test_routing.sh b/tests/sys/net/routing/test_routing.sh
new file mode 100755
--- /dev/null
+++ b/tests/sys/net/routing/test_routing.sh
@@ -0,0 +1,233 @@
+#!/usr/bin/env atf-sh
+#
+# Copyright (c) 2026 Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+. $(atf_get_srcdir)/../../common/vnet.subr
+
+jq_rtentry()
+{
+ local route="$1"
+
+ jq -r '.statistics."route-information"."route-table"."rt-family".[]."rt-entry".[] |
+ select(.destination == "'${route}'")'
+}
+
+jq_nhop_filter()
+{
+ local nhop="$1"
+ local weight="$2"
+ local metric="$3"
+
+ jq -r 'select(.gateway == "'${nhop}'") |
+ select(.weight == '${weight}') |
+ select(.metric == '${metric}') |
+ .gateway'
+}
+
+
+atf_test_case "add_lowest_metric" "cleanup"
+add_lowest_metric_head()
+{
+ atf_set descr 'Create 4 routes to same dst and verify the lowest metric wins'
+ atf_set require.user root
+ atf_set require.progs jq
+}
+
+add_lowest_metric_body()
+{
+ local epair prefix route nhop1 nhop2 nhop3
+
+ prefix="3fff::"
+ route="3fff:a::"
+ nhop1="3fff::1"
+ nhop2="3fff::2"
+ nhop3="3fff::3"
+
+ vnet_init
+ epair=$(vnet_mkepair)
+ vnet_mkjail metric1 ${epair}a
+
+ atf_check -o ignore \
+ ifconfig -j metric1 ${epair}a inet6 ${prefix}1/64 up
+
+ # Create an ECMP route with metric 2
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop2} -weight 10 -metric 2
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop3} -weight 10 -metric 2
+
+ # Validate routes
+ atf_check -o save:netstat \
+ netstat -rn6j metric1 --libxo json
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop2} 10 2)
+ atf_check_equal "$output" "$nhop2"
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop3} 10 2)
+ atf_check_equal "$output" "$nhop3"
+
+ # Create a route with metric 3
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop1} -metric 3
+ # Verify that nhop1 is not the best route
+ atf_check -o not-match:".*gateway: ${nhop1}.*" \
+ route -n6j metric1 get -net ${route}/64
+
+ # Create a route to the same nhop with same metric 3 and verify it fails
+ atf_check -s exit:1 -o ignore -e ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop1} -metric 3
+
+ # Create a route to an existing nhop with lower metric
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop1} -metric 1
+ # Verify that nhop1 is now the best route
+ atf_check -o match:".*gateway: ${nhop1}.*" \
+ route -n6j metric1 get -net ${route}/64
+}
+
+add_lowest_metric_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "add_default_metric" "cleanup"
+add_default_metric_head()
+{
+ atf_set descr 'Create a route and verify the default metric is set'
+ atf_set require.user root
+}
+
+add_default_metric_body()
+{
+ local epair prefix route nhop1
+
+ prefix="3fff::"
+ route="3fff:a::"
+ nhop1="3fff::1"
+
+ vnet_init
+ epair=$(vnet_mkepair)
+ vnet_mkjail metric1 ${epair}a
+
+ atf_check -o ignore \
+ ifconfig -j metric1 ${epair}a inet6 ${prefix}1/64 up
+
+ # Create a route without specifying its metric
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop1}
+
+ # Verify the route has the default metric
+ atf_check -o save:netstat \
+ netstat -rn6j metric1 --libxo json
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop1} 1 1)
+ atf_check_equal "$output" "$nhop1"
+}
+
+add_default_metric_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "delete_route_with_metric" "cleanup"
+delete_route_with_metric_head()
+{
+ atf_set descr 'Create four routes to same dst and delete routes with specific metric'
+ atf_set require.user root
+}
+
+delete_route_with_metric_body()
+{
+ local epair prefix route nhop1 nhop2
+
+ prefix="3fff::"
+ route="3fff:a::"
+ nhop1="3fff::1"
+ nhop2="3fff::2"
+
+ vnet_init
+ epair=$(vnet_mkepair)
+ vnet_mkjail metric1 ${epair}a
+
+ atf_check -o ignore \
+ ifconfig -j metric1 ${epair}a inet6 ${prefix}1/64 up
+
+ # Create two groups of ECMP routes with metric 2 and 3, and
+ # another route with metric 4.
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop1} -metric 3
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop1} -weight 10 -metric 2
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop2} -weight 10 -metric 2
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop2} -metric 3
+ atf_check -o ignore \
+ route -6j metric1 add -net ${route}/64 -gateway ${nhop2} -metric 4
+
+ # Validate we have 5 routes
+ atf_check -o save:netstat \
+ netstat -rn6j metric1 --libxo json
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop1} 1 3)
+ atf_check_equal "$output" "$nhop1"
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop1} 10 2)
+ atf_check_equal "$output" "$nhop1"
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop2} 10 2)
+ atf_check_equal "$output" "$nhop2"
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop2} 1 3)
+ atf_check_equal "$output" "$nhop2"
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop2} 1 4)
+ atf_check_equal "$output" "$nhop2"
+
+ # Delete one of the nexthops of them best ECMP route
+ # Test that deleting a route by specifying gateway + metric works.
+ atf_check -o ignore \
+ route -n6j metric1 delete -net ${route}/64 -gateway ${nhop2} -metric 2
+
+ # Verify that nhop1 is the best route now
+ atf_check -o match:".*gateway: ${nhop1}.*" \
+ route -n6j metric1 get -net ${route}/64
+
+ # But other route with nhops2 should exists.
+ atf_check -o save:netstat \
+ netstat -rn6j metric1 --libxo json
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop2} 1 3)
+ atf_check_equal "$output" "$nhop2"
+ output=$(cat netstat | jq_rtentry ${route}/64 | jq_nhop_filter ${nhop2} 1 4)
+ atf_check_equal "$output" "$nhop2"
+
+ # Delete routes with nhop1 as nexthop without specifying metric.
+ # Test that deleting a route by gateway removes all routes with
+ # that gateway, regardless of metric value.
+ atf_check -o ignore \
+ route -n6j metric1 delete -net ${route}/64 -gateway ${nhop1}
+
+ # Verify that nhop2 is the best route now
+ atf_check -o match:".*gateway: ${nhop2}.*" \
+ route -n6j metric1 get -net ${route}/64
+
+ # Delete routes with metric 3 without specifying their gateway.
+ # Test that deleting a route by metric removes all routes with
+ # that metric, regardless of gateway value.
+ atf_check -o ignore \
+ route -n6j metric1 delete -net ${route}/64 -metric 3
+
+ # Verify that nhop2 is still the best route with metric of 4
+ atf_check -o match:".*gateway: ${nhop2}.*" \
+ route -n6j metric1 get -net ${route}/64
+ 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_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"
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Nov 10, 2:15 AM (3 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41609524
Default Alt Text
D57016.1794276938.diff (7 KB)
Attached To
Mode
D57016: routing: Add tests for metric
Attached
Detach File
Event Timeline