mirror of
https://github.com/espressif/openthread.git
synced 2026-09-01 14:59:54 +00:00
[border-router] detect DHCPv6-PD prefix conflict with route prefixes (#12361)
This commit enhances the DHCPv6 PD prefix conflict detection logic to check against Route Information Options (RIOs) present in received Router Advertisements, in addition to the existing check against on-link prefixes (PIOs). The conflict detection behavior is event-driven to correctly handle network propagation delays and valid advertisements: 1. On new prefix assignment (`kPdPrefixChanged`): A strict check is performed. If the prefix matches any existing RIO from another router, it is flagged as a conflict. 2. On RA table updates (`kRxRaPrefixTableChanged`): The check focuses on conflict resolution. Crucially, it ignores new RIO matches appearing after the prefix has been adopted. This is necessary because once the BR publishes the PD prefix in Thread Network Data as the OMR prefix, other BRs will naturally start advertising it as a RIO to announce reachability. The unit test `TestDhcp6PdConflict` is updated to verify both the detection of conflict, its resolution, and that the subsequent RIO advertisements do not cause a conflict after PD prefix is published as OMR.
This commit is contained in:
@@ -5209,6 +5209,119 @@ void TestDhcp6PdConflict(void)
|
||||
|
||||
VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ true);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Wait for the PIO from Router A to expire. We renew the PD
|
||||
// prefix during this time to ensure it stays valid.
|
||||
|
||||
Log("Wait for Router A PIO to expire");
|
||||
|
||||
AdvanceTime(200 * 1000);
|
||||
ReportPdPrefixesAsRa({Pio(pdPrefix, kValidLitime, kPreferredLifetime)});
|
||||
AdvanceTime(200 * 1000);
|
||||
|
||||
// Router A entry should be expired and removed. The PD prefix is still
|
||||
// valid (renewed). The conflict should be resolved. Validate that PD
|
||||
// prefix is again being use as OMR prefix.
|
||||
|
||||
AdvanceTime(100 * 1000);
|
||||
|
||||
VerifyPdOmrPrefix(pdPrefix);
|
||||
VerifyOmrPrefixInNetData(pdPrefix, /* aDefaultRoute */ false);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Remove the PD prefix
|
||||
|
||||
ReportPdPrefixesAsRa({Pio(pdPrefix, 0, 0)});
|
||||
|
||||
AdvanceTime(1 * 1000);
|
||||
VerifyNoPdOmrPrefix();
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Now Advertise the PD prefix as RIO from a router first.
|
||||
|
||||
Log("Router A advertises PD prefix as RIO before delegating the prefix");
|
||||
SendRouterAdvert(routerAddressA, {Rio(pdPrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
// Check that local OMR is used.
|
||||
|
||||
sExpectedRios.Clear();
|
||||
sExpectedRios.Add(localOmr);
|
||||
|
||||
AdvanceTime(10 * 1000);
|
||||
VerifyOrQuit(sExpectedRios.SawAll());
|
||||
|
||||
VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Report the same PD prefix. Validate that local OMR prefix is
|
||||
// still being used (due to RIO conflict).
|
||||
|
||||
Log("Delegate PD prefix which conflicts with already advertised RIO prefix from router A");
|
||||
ReportPdPrefixesAsRa({Pio(pdPrefix, kValidLitime, kPreferredLifetime)});
|
||||
|
||||
sExpectedRios.Clear();
|
||||
sExpectedRios.Add(localOmr);
|
||||
|
||||
AdvanceTime(30 * 1000);
|
||||
VerifyOrQuit(sExpectedRios.SawAll());
|
||||
|
||||
VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Remove the RIO from Router A. Validate that the PD prefix is
|
||||
// now accepted and used as OMR.
|
||||
|
||||
Log("Router A removes RIO, conflict should be resolved");
|
||||
SendRouterAdvert(routerAddressA, {Rio(pdPrefix, 0, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
sExpectedRios.Clear();
|
||||
sExpectedRios.Add(pdPrefix);
|
||||
|
||||
AdvanceTime(10 * 1000);
|
||||
VerifyOrQuit(sExpectedRios.SawAll());
|
||||
|
||||
VerifyOmrPrefixInNetData(pdPrefix, /* aDefaultRoute */ false);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Remove the PD prefix
|
||||
|
||||
ReportPdPrefixesAsRa({Pio(pdPrefix, 0, 0)});
|
||||
|
||||
AdvanceTime(1 * 1000);
|
||||
VerifyNoPdOmrPrefix();
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Report the PD prefix again. Validate that it is used as OMR prefix.
|
||||
|
||||
Log("Delegate PD prefix");
|
||||
ReportPdPrefixesAsRa({Pio(pdPrefix, kValidLitime, kPreferredLifetime)});
|
||||
|
||||
sExpectedRios.Clear();
|
||||
sExpectedRios.Add(pdPrefix);
|
||||
|
||||
AdvanceTime(10 * 1000);
|
||||
VerifyOrQuit(sExpectedRios.SawAll());
|
||||
|
||||
VerifyOmrPrefixInNetData(pdPrefix, /* aDefaultRoute */ false);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Advertise the same prefix as RIO from a router. This should NOT
|
||||
// be treated as a conflict since the PD prefix is already adopted
|
||||
// and used.
|
||||
|
||||
Log("Router A advertises PD prefix as RIO after it is delegated");
|
||||
SendRouterAdvert(routerAddressA, {Rio(pdPrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)});
|
||||
|
||||
AdvanceTime(1 * 1000);
|
||||
|
||||
sExpectedRios.Clear();
|
||||
sExpectedRios.Add(pdPrefix);
|
||||
|
||||
AdvanceTime(300 * 1000);
|
||||
VerifyOrQuit(sExpectedRios.SawAll());
|
||||
|
||||
VerifyOmrPrefixInNetData(pdPrefix, /* aDefaultRoute */ false);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
|
||||
|
||||
Reference in New Issue
Block a user