[routing-manager] RoutePublisher and new route publishing model (#8986)

This commit updates the `RoutingManager` module to implement a new
model for publishing routes. The new model replaces the previous
model, which explicitly published all discovered routes and on-link
prefixes (from processing Router Advertisements on AIL) as external
routes in the Network Data.

The new model simplifies this logic by publishing either a `fc00::/7`
(ULA) route or a `::/0` (default) route in the Network Data,
depending on the set of discovered routes and on-link prefixes, and
the currently favored OMR prefix.

This commit adds the `RoutePublisher` class, a nested sub-component of
the `RoutingManager` class. The `RoutePublisher` class is responsible
for determining the route prefix to publish and its preference. The
preference of the published route is determined based on the current
role of the Border Router (BR): low preference if the BR is a child,
and medium preference if the BR is acting as a router.

This commit also updates `test_routing_manager` unit test validating
the new behavior.
This commit is contained in:
Abtin Keshavarzian
2023-05-01 18:30:14 -07:00
committed by GitHub
parent 2dcecb7ac0
commit d6221f4d32
10 changed files with 753 additions and 557 deletions
@@ -108,8 +108,7 @@ class ManualMulticastAddressConfig(thread_cert.TestCase):
# packet back to Host.
# TD receives the MPL packet containing an encapsulated ping packet to
# MA1, sent by Host, and unicasts a ping response packet back to Host.
pkts.filter_eth_src(vars['TD_ETH']) \
.filter_ipv6_dst(_pkt.ipv6.src) \
pkts.filter_ipv6_dst(_pkt.ipv6.src) \
.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \
.must_next()
@@ -147,8 +147,6 @@ class MultiBorderRouters(thread_cert.TestCase):
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2)
br1_on_link_prefix = br1.get_br_on_link_prefix()
self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0])
self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0])
self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
self.assertEqual(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -200,8 +198,6 @@ class MultiBorderRouters(thread_cert.TestCase):
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 1)
br2_on_link_prefix = br2.get_br_on_link_prefix()
self.assertEqual(set(map(IPv6Network, br2.get_netdata_non_nat64_prefixes())),
set(map(IPv6Network, [br1_on_link_prefix, br2_on_link_prefix])))
self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
self.assertEqual(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -130,10 +130,10 @@ class MultiThreadNetworks(thread_cert.TestCase):
# Each BR should independently register an external route for the on-link prefix
# and OMR prefix in another Thread Network.
self.assertTrue(len(br1.get_netdata_non_nat64_prefixes()) == 2)
self.assertTrue(len(router1.get_netdata_non_nat64_prefixes()) == 2)
self.assertTrue(len(br2.get_netdata_non_nat64_prefixes()) == 2)
self.assertTrue(len(router2.get_netdata_non_nat64_prefixes()) == 2)
self.assertTrue(len(br1.get_netdata_non_nat64_prefixes()) == 1)
self.assertTrue(len(router1.get_netdata_non_nat64_prefixes()) == 1)
self.assertTrue(len(br2.get_netdata_non_nat64_prefixes()) == 1)
self.assertTrue(len(router2.get_netdata_non_nat64_prefixes()) == 1)
br1_external_routes = br1.get_routes()
br2_external_routes = br2.get_routes()
@@ -127,10 +127,8 @@ class MultiThreadNetworks(thread_cert.TestCase):
logging.info("HOST addrs: %r", host.get_addrs())
self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1)
on_link_prefix = br1.get_netdata_non_nat64_prefixes()[0]
self.assertEqual(IPv6Network(on_link_prefix), IPv6Network(ON_LINK_PREFIX))
host_on_link_addr = host.get_matched_ula_addresses(on_link_prefix)[0]
host_on_link_addr = host.get_matched_ula_addresses(ON_LINK_PREFIX)[0]
self.assertTrue(router1.ping(host_on_link_addr))
self.assertTrue(
host.ping(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True, interface=host_on_link_addr))
@@ -164,18 +162,16 @@ class MultiThreadNetworks(thread_cert.TestCase):
br2_omr_prefix = br2.get_br_omr_prefix()
self.assertNotEqual(br1_omr_prefix, br2_omr_prefix)
# Verify that the Border Routers starts advertsing new on-link prefix
# Verify that the Border Routers starts advertising new on-link prefix
# but don't remove the external routes for the radvd on-link prefix
# immediately, because the SLAAC addresses are still valid.
self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 3)
self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 3)
self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 2)
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2)
on_link_prefixes = list(
set(br1.get_netdata_non_nat64_prefixes()).intersection(br2.get_netdata_non_nat64_prefixes()))
self.assertEqual(len(on_link_prefixes), 1)
self.assertEqual(IPv6Network(on_link_prefixes[0]), IPv6Network(br2.get_br_on_link_prefix()))
self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1)
self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 1)
self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 1)
self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 1)
br2_on_link_prefix = br2.get_br_on_link_prefix()
router1_omr_addr = router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
router2_omr_addr = router2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]
@@ -184,7 +180,7 @@ class MultiThreadNetworks(thread_cert.TestCase):
# and preferred Border Router on-link prefix can be reached by Thread
# devices in network of Border Router 1.
for host_on_link_addr in [
host.get_matched_ula_addresses(on_link_prefixes[0])[0],
host.get_matched_ula_addresses(br2_on_link_prefix)[0],
host.get_matched_ula_addresses(ON_LINK_PREFIX)[0]
]:
self.assertTrue(router1.ping(host_on_link_addr))
@@ -192,11 +188,6 @@ class MultiThreadNetworks(thread_cert.TestCase):
host_on_link_addr = host.get_matched_ula_addresses(ON_LINK_PREFIX)[0]
# Make sure that addresses of the deprecated radvd `ON_LINK_PREFIX`
# can't be reached by Thread devices in network of Border Router 2.
self.assertFalse(router2.ping(host_on_link_addr))
self.assertFalse(host.ping(router2_omr_addr, backbone=True, interface=host_on_link_addr))
# Wait 30 seconds for the radvd `ON_LINK_PREFIX` to be invalidated
# and make sure that Thread devices in both networks can't reach
# the on-link address.
@@ -177,8 +177,6 @@ class SingleBorderRouter(thread_cert.TestCase):
# The same local OMR and on-link prefix should be re-register.
self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -231,8 +229,6 @@ class SingleBorderRouter(thread_cert.TestCase):
# The same local OMR and on-link prefix should be re-registered.
self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -285,8 +281,6 @@ class SingleBorderRouter(thread_cert.TestCase):
# The same local OMR and on-link prefix should be re-registered.
self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix])
self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix])
self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix])
self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix])
self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1)
@@ -320,8 +314,8 @@ class SingleBorderRouter(thread_cert.TestCase):
br.start_radvd_service(prefix=config.ONLINK_GUA_PREFIX, slaac=True)
self.simulator.go(5)
self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 2)
self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 2)
self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1)
self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1)
self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_GUA)[0]))
self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0]))