• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2022, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <openthread/config.h>
30 
31 #include "test_platform.h"
32 #include "test_util.hpp"
33 
34 #include <openthread/dataset_ftd.h>
35 #include <openthread/thread.h>
36 #include <openthread/platform/border_routing.h>
37 
38 #include "border_router/routing_manager.hpp"
39 #include "common/arg_macros.hpp"
40 #include "common/array.hpp"
41 #include "common/numeric_limits.hpp"
42 #include "common/time.hpp"
43 #include "instance/instance.hpp"
44 #include "net/icmp6.hpp"
45 #include "net/nd6.hpp"
46 
47 namespace ot {
48 
49 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
50 
51 // Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>"
52 #define Log(...)                                                                                         \
53     printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 3600000), (sNow / 60000) % 60, \
54            (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__))
55 
56 static constexpr uint32_t kInfraIfIndex     = 1;
57 static const char         kInfraIfAddress[] = "fe80::1";
58 
59 static constexpr uint32_t kValidLitime       = 2000;
60 static constexpr uint32_t kPreferredLifetime = 1800;
61 static constexpr uint32_t kInfiniteLifetime  = NumericLimits<uint32_t>::kMax;
62 
63 static constexpr uint32_t kRioValidLifetime       = 1800;
64 static constexpr uint32_t kRioDeprecatingLifetime = 300;
65 
66 static constexpr uint16_t kMaxRaSize              = 800;
67 static constexpr uint16_t kMaxDeprecatingPrefixes = 16;
68 
69 static constexpr otOperationalDataset kDataset = {
70     .mActiveTimestamp =
71         {
72             .mSeconds       = 1,
73             .mTicks         = 0,
74             .mAuthoritative = false,
75         },
76     .mNetworkKey =
77         {
78             .m8 = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
79         },
80     .mNetworkName = {"OpenThread"},
81     .mExtendedPanId =
82         {
83             .m8 = {0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xfe},
84         },
85     .mMeshLocalPrefix =
86         {
87             .m8 = {0xfd, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
88         },
89     .mPanId   = 0x1234,
90     .mChannel = 11,
91     .mPskc =
92         {
93             .m8 = {0xc2, 0x3a, 0x76, 0xe9, 0x8f, 0x1a, 0x64, 0x83, 0x63, 0x9b, 0x1a, 0xc1, 0x27, 0x1e, 0x2e, 0x27},
94         },
95     .mSecurityPolicy =
96         {
97             .mRotationTime                 = 672,
98             .mObtainNetworkKeyEnabled      = true,
99             .mNativeCommissioningEnabled   = true,
100             .mRoutersEnabled               = true,
101             .mExternalCommissioningEnabled = true,
102         },
103     .mChannelMask = 0x07fff800,
104     .mComponents =
105         {
106             .mIsActiveTimestampPresent = true,
107             .mIsNetworkKeyPresent      = true,
108             .mIsNetworkNamePresent     = true,
109             .mIsExtendedPanIdPresent   = true,
110             .mIsMeshLocalPrefixPresent = true,
111             .mIsPanIdPresent           = true,
112             .mIsChannelPresent         = true,
113             .mIsPskcPresent            = true,
114             .mIsSecurityPolicyPresent  = true,
115             .mIsChannelMaskPresent     = true,
116         },
117 };
118 
119 static Instance *sInstance;
120 
121 static uint32_t sNow = 0;
122 static uint32_t sAlarmTime;
123 static bool     sAlarmOn = false;
124 
125 static otRadioFrame sRadioTxFrame;
126 static uint8_t      sRadioTxFramePsdu[OT_RADIO_FRAME_MAX_SIZE];
127 static bool         sRadioTxOngoing = false;
128 
129 using Icmp6Packet = Ip6::Nd::RouterAdvert::Icmp6Packet;
130 
131 enum ExpectedPio
132 {
133     kNoPio,                     // Expect to see no PIO in RA.
134     kPioAdvertisingLocalOnLink, // Expect to see local on-link prefix advertised (non-zero preferred lifetime).
135     kPioDeprecatingLocalOnLink, // Expect to see local on-link prefix deprecated (zero preferred lifetime).
136 };
137 
138 struct DeprecatingPrefix
139 {
140     DeprecatingPrefix(void) = default;
141 
DeprecatingPrefixot::DeprecatingPrefix142     DeprecatingPrefix(const Ip6::Prefix &aPrefix, uint32_t aLifetime)
143         : mPrefix(aPrefix)
144         , mLifetime(aLifetime)
145     {
146     }
147 
Matchesot::DeprecatingPrefix148     bool Matches(const Ip6::Prefix &aPrefix) const { return mPrefix == aPrefix; }
149 
150     Ip6::Prefix mPrefix;   // Old on-link prefix being deprecated.
151     uint32_t    mLifetime; // Valid lifetime of prefix from PIO.
152 };
153 
154 static Ip6::Address sInfraIfAddress;
155 
156 bool        sRsEmitted;      // Indicates if an RS message was emitted by BR.
157 bool        sRaValidated;    // Indicates if an RA was emitted by BR and successfully validated.
158 bool        sNsEmitted;      // Indicates if an NS message was emitted by BR.
159 bool        sRespondToNs;    // Indicates whether or not to respond to NS.
160 ExpectedPio sExpectedPio;    // Expected PIO in the emitted RA by BR (MUST be seen in RA to set `sRaValidated`).
161 uint32_t    sOnLinkLifetime; // Valid lifetime for local on-link prefix from the last processed RA.
162 
163 // Indicate whether or not to check the emitted RA header (default route) lifetime
164 bool sCheckRaHeaderLifetime;
165 
166 // Expected default route lifetime in emitted RA header by BR.
167 uint32_t sExpectedRaHeaderLifetime;
168 
169 enum ExpectedRaHeaderFlags
170 {
171     kRaHeaderFlagsSkipChecking, // Skip checking the RA header flags.
172     kRaHeaderFlagsNone,         // Expect no flag (neither M or O).
173     kRaHeaderFlagsOnlyM,        // Expect M flag only.
174     kRaHeaderFlagsOnlyO,        // Expect O flag only.
175     kRaHeaderFlagsBothMAndO,    // Expect both M and O flags.
176 };
177 
178 // The expected RA header flags when validating emitted RA message.
179 ExpectedRaHeaderFlags sExpectedRaHeaderFlags;
180 
181 // Array containing deprecating prefixes from PIOs in the last processed RA.
182 Array<DeprecatingPrefix, kMaxDeprecatingPrefixes> sDeprecatingPrefixes;
183 
184 static constexpr uint16_t kMaxRioPrefixes = 10;
185 
186 struct RioPrefix
187 {
188     RioPrefix(void) = default;
189 
RioPrefixot::RioPrefix190     explicit RioPrefix(const Ip6::Prefix &aPrefix)
191         : mSawInRa(false)
192         , mPrefix(aPrefix)
193         , mLifetime(0)
194     {
195     }
196 
197     bool        mSawInRa;  // Indicate whether or not this prefix was seen in the emitted RA (as RIO).
198     Ip6::Prefix mPrefix;   // The RIO prefix.
199     uint32_t    mLifetime; // The RIO prefix lifetime - only valid when `mSawInRa`
200 };
201 
202 class ExpectedRios : public Array<RioPrefix, kMaxRioPrefixes>
203 {
204 public:
Add(const Ip6::Prefix & aPrefix)205     void Add(const Ip6::Prefix &aPrefix) { SuccessOrQuit(PushBack(RioPrefix(aPrefix))); }
206 
SawAll(void) const207     bool SawAll(void) const
208     {
209         bool sawAll = true;
210 
211         for (const RioPrefix &rioPrefix : *this)
212         {
213             if (!rioPrefix.mSawInRa)
214             {
215                 sawAll = false;
216                 break;
217             }
218         }
219 
220         return sawAll;
221     }
222 };
223 
224 ExpectedRios sExpectedRios; // Expected RIO prefixes in emitted RAs.
225 
226 //----------------------------------------------------------------------------------------------------------------------
227 // Function prototypes
228 
229 void        ProcessRadioTxAndTasklets(void);
230 void        AdvanceTime(uint32_t aDuration);
231 void        LogRouterAdvert(const Icmp6Packet &aPacket);
232 void        ValidateRouterAdvert(const Icmp6Packet &aPacket);
233 const char *PreferenceToString(int8_t aPreference);
234 void        SendRouterAdvert(const Ip6::Address &aAddress, const Icmp6Packet &aPacket);
235 void        SendNeighborAdvert(const Ip6::Address &aAddress, const Ip6::Nd::NeighborAdvertMessage &aNaMessage);
236 void        DiscoverNat64Prefix(const Ip6::Prefix &aPrefix);
237 
238 extern "C" {
239 
240 #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED
otPlatLog(otLogLevel aLogLevel,otLogRegion aLogRegion,const char * aFormat,...)241 void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
242 {
243     OT_UNUSED_VARIABLE(aLogLevel);
244     OT_UNUSED_VARIABLE(aLogRegion);
245 
246     va_list args;
247 
248     printf("   ");
249     va_start(args, aFormat);
250     vprintf(aFormat, args);
251     va_end(args);
252     printf("\n");
253 }
254 #endif
255 
256 //----------------------------------------------------------------------------------------------------------------------
257 // `otPlatRadio
258 
otPlatRadioGetCaps(otInstance *)259 otRadioCaps otPlatRadioGetCaps(otInstance *) { return OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF; }
260 
otPlatRadioTransmit(otInstance *,otRadioFrame *)261 otError otPlatRadioTransmit(otInstance *, otRadioFrame *)
262 {
263     sRadioTxOngoing = true;
264 
265     return OT_ERROR_NONE;
266 }
267 
otPlatRadioGetTransmitBuffer(otInstance *)268 otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *) { return &sRadioTxFrame; }
269 
270 //----------------------------------------------------------------------------------------------------------------------
271 // `otPlatAlaram
272 
otPlatAlarmMilliStop(otInstance *)273 void otPlatAlarmMilliStop(otInstance *) { sAlarmOn = false; }
274 
otPlatAlarmMilliStartAt(otInstance *,uint32_t aT0,uint32_t aDt)275 void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt)
276 {
277     sAlarmOn   = true;
278     sAlarmTime = aT0 + aDt;
279 }
280 
otPlatAlarmMilliGetNow(void)281 uint32_t otPlatAlarmMilliGetNow(void) { return sNow; }
282 
283 //---------------------------------------------------------------------------------------------------------------------
284 // otPlatInfraIf
285 
otPlatInfraIfHasAddress(uint32_t aInfraIfIndex,const otIp6Address * aAddress)286 bool otPlatInfraIfHasAddress(uint32_t aInfraIfIndex, const otIp6Address *aAddress)
287 {
288     VerifyOrQuit(aInfraIfIndex == kInfraIfIndex);
289 
290     return AsCoreType(aAddress) == sInfraIfAddress;
291 }
292 
otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,const otIp6Address * aDestAddress,const uint8_t * aBuffer,uint16_t aBufferLength)293 otError otPlatInfraIfSendIcmp6Nd(uint32_t            aInfraIfIndex,
294                                  const otIp6Address *aDestAddress,
295                                  const uint8_t      *aBuffer,
296                                  uint16_t            aBufferLength)
297 {
298     Icmp6Packet packet;
299 
300     Log("otPlatInfraIfSendIcmp6Nd(aDestAddr: %s, aBufferLength:%u)", AsCoreType(aDestAddress).ToString().AsCString(),
301         aBufferLength);
302 
303     VerifyOrQuit(aInfraIfIndex == kInfraIfIndex);
304 
305     packet.Init(aBuffer, aBufferLength);
306 
307     VerifyOrQuit(aBufferLength >= sizeof(Ip6::Icmp::Header));
308 
309     switch (reinterpret_cast<const Ip6::Icmp::Header *>(aBuffer)->GetType())
310     {
311     case Ip6::Icmp::Header::kTypeRouterSolicit:
312         Log("  Router Solicit message");
313         sRsEmitted = true;
314         break;
315 
316     case Ip6::Icmp::Header::kTypeRouterAdvert:
317         Log("  Router Advertisement message");
318         LogRouterAdvert(packet);
319         ValidateRouterAdvert(packet);
320         break;
321 
322     case Ip6::Icmp::Header::kTypeNeighborSolicit:
323     {
324         const Ip6::Nd::NeighborSolicitMessage *nsMsg =
325             reinterpret_cast<const Ip6::Nd::NeighborSolicitMessage *>(packet.GetBytes());
326 
327         Log("  Neighbor Solicit message");
328 
329         VerifyOrQuit(packet.GetLength() >= sizeof(Ip6::Nd::NeighborSolicitMessage));
330         VerifyOrQuit(nsMsg->IsValid());
331         sNsEmitted = true;
332 
333         if (sRespondToNs)
334         {
335             Ip6::Nd::NeighborAdvertMessage naMsg;
336 
337             naMsg.SetTargetAddress(nsMsg->GetTargetAddress());
338             naMsg.SetRouterFlag();
339             naMsg.SetSolicitedFlag();
340             SendNeighborAdvert(AsCoreType(aDestAddress), naMsg);
341         }
342 
343         break;
344     }
345 
346     default:
347         VerifyOrQuit(false, "Bad ICMP6 type");
348     }
349 
350     return OT_ERROR_NONE;
351 }
352 
353 //----------------------------------------------------------------------------------------------------------------------
354 
355 Array<void *, 500> sHeapAllocatedPtrs;
356 
357 #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
358 
otPlatCAlloc(size_t aNum,size_t aSize)359 void *otPlatCAlloc(size_t aNum, size_t aSize)
360 {
361     void *ptr = calloc(aNum, aSize);
362 
363     SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr));
364 
365     return ptr;
366 }
367 
otPlatFree(void * aPtr)368 void otPlatFree(void *aPtr)
369 {
370     if (aPtr != nullptr)
371     {
372         void **entry = sHeapAllocatedPtrs.Find(aPtr);
373 
374         VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice");
375         sHeapAllocatedPtrs.Remove(*entry);
376     }
377 
378     free(aPtr);
379 }
380 
381 #endif
382 
383 } // extern "C"
384 
385 //---------------------------------------------------------------------------------------------------------------------
386 
ProcessRadioTxAndTasklets(void)387 void ProcessRadioTxAndTasklets(void)
388 {
389     do
390     {
391         if (sRadioTxOngoing)
392         {
393             sRadioTxOngoing = false;
394             otPlatRadioTxStarted(sInstance, &sRadioTxFrame);
395             otPlatRadioTxDone(sInstance, &sRadioTxFrame, nullptr, OT_ERROR_NONE);
396         }
397 
398         otTaskletsProcess(sInstance);
399     } while (otTaskletsArePending(sInstance));
400 }
401 
AdvanceTime(uint32_t aDuration)402 void AdvanceTime(uint32_t aDuration)
403 {
404     uint32_t time = sNow + aDuration;
405 
406     Log("AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000);
407 
408     while (TimeMilli(sAlarmTime) <= TimeMilli(time))
409     {
410         ProcessRadioTxAndTasklets();
411         sNow = sAlarmTime;
412         otPlatAlarmMilliFired(sInstance);
413     }
414 
415     ProcessRadioTxAndTasklets();
416     sNow = time;
417 }
418 
ValidateRouterAdvert(const Icmp6Packet & aPacket)419 void ValidateRouterAdvert(const Icmp6Packet &aPacket)
420 {
421     constexpr uint8_t kMaxPrefixes = 16;
422 
423     Ip6::Nd::RouterAdvert::RxMessage raMsg(aPacket);
424     bool                             sawExpectedPio = false;
425     Array<Ip6::Prefix, kMaxPrefixes> pioPrefixes;
426     Array<Ip6::Prefix, kMaxPrefixes> rioPrefixes;
427 #if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
428     bool sawStubRouterFlag = false;
429 #endif
430 
431     VerifyOrQuit(raMsg.IsValid());
432 
433     if (sCheckRaHeaderLifetime)
434     {
435         VerifyOrQuit(raMsg.GetHeader().GetRouterLifetime() == sExpectedRaHeaderLifetime);
436     }
437 
438     switch (sExpectedRaHeaderFlags)
439     {
440     case kRaHeaderFlagsSkipChecking:
441         break;
442     case kRaHeaderFlagsNone:
443         VerifyOrQuit(!raMsg.GetHeader().IsManagedAddressConfigFlagSet());
444         VerifyOrQuit(!raMsg.GetHeader().IsOtherConfigFlagSet());
445         break;
446     case kRaHeaderFlagsOnlyM:
447         VerifyOrQuit(raMsg.GetHeader().IsManagedAddressConfigFlagSet());
448         VerifyOrQuit(!raMsg.GetHeader().IsOtherConfigFlagSet());
449         break;
450     case kRaHeaderFlagsOnlyO:
451         VerifyOrQuit(!raMsg.GetHeader().IsManagedAddressConfigFlagSet());
452         VerifyOrQuit(raMsg.GetHeader().IsOtherConfigFlagSet());
453         break;
454     case kRaHeaderFlagsBothMAndO:
455         VerifyOrQuit(raMsg.GetHeader().IsManagedAddressConfigFlagSet());
456         VerifyOrQuit(raMsg.GetHeader().IsOtherConfigFlagSet());
457         break;
458     }
459 
460     sDeprecatingPrefixes.Clear();
461 
462     for (const Ip6::Nd::Option &option : raMsg)
463     {
464         switch (option.GetType())
465         {
466         case Ip6::Nd::Option::kTypePrefixInfo:
467         {
468             const Ip6::Nd::PrefixInfoOption &pio = static_cast<const Ip6::Nd::PrefixInfoOption &>(option);
469             Ip6::Prefix                      prefix;
470             Ip6::Prefix                      localOnLink;
471 
472             VerifyOrQuit(pio.IsValid());
473             pio.GetPrefix(prefix);
474 
475             VerifyOrQuit(!pioPrefixes.Contains(prefix), "Duplicate PIO prefix in RA");
476             SuccessOrQuit(pioPrefixes.PushBack(prefix));
477 
478             SuccessOrQuit(otBorderRoutingGetOnLinkPrefix(sInstance, &localOnLink));
479 
480             if (prefix == localOnLink)
481             {
482                 switch (sExpectedPio)
483                 {
484                 case kNoPio:
485                     break;
486 
487                 case kPioAdvertisingLocalOnLink:
488                     if (pio.GetPreferredLifetime() > 0)
489                     {
490                         sOnLinkLifetime = pio.GetValidLifetime();
491                         sawExpectedPio  = true;
492                     }
493                     break;
494 
495                 case kPioDeprecatingLocalOnLink:
496                     if (pio.GetPreferredLifetime() == 0)
497                     {
498                         sOnLinkLifetime = pio.GetValidLifetime();
499                         sawExpectedPio  = true;
500                     }
501                     break;
502                 }
503             }
504             else
505             {
506                 VerifyOrQuit(pio.GetPreferredLifetime() == 0, "Old on link prefix is not deprecated");
507                 SuccessOrQuit(sDeprecatingPrefixes.PushBack(DeprecatingPrefix(prefix, pio.GetValidLifetime())));
508             }
509             break;
510         }
511 
512         case Ip6::Nd::Option::kTypeRouteInfo:
513         {
514             const Ip6::Nd::RouteInfoOption &rio = static_cast<const Ip6::Nd::RouteInfoOption &>(option);
515             Ip6::Prefix                     prefix;
516 
517             VerifyOrQuit(rio.IsValid());
518             rio.GetPrefix(prefix);
519 
520             VerifyOrQuit(!rioPrefixes.Contains(prefix), "Duplicate RIO prefix in RA");
521             SuccessOrQuit(rioPrefixes.PushBack(prefix));
522 
523             for (RioPrefix &rioPrefix : sExpectedRios)
524             {
525                 if (prefix == rioPrefix.mPrefix)
526                 {
527                     rioPrefix.mSawInRa  = true;
528                     rioPrefix.mLifetime = rio.GetRouteLifetime();
529                 }
530             }
531 
532             break;
533         }
534 
535 #if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
536         case Ip6::Nd::Option::kTypeRaFlagsExtension:
537         {
538             const Ip6::Nd::RaFlagsExtOption &flagsOption = static_cast<const Ip6::Nd::RaFlagsExtOption &>(option);
539 
540             VerifyOrQuit(flagsOption.IsValid());
541             VerifyOrQuit(flagsOption.IsStubRouterFlagSet());
542             sawStubRouterFlag = true;
543             break;
544         }
545 #endif
546 
547         default:
548             VerifyOrQuit(false, "Unexpected option type in RA msg");
549         }
550     }
551 
552 #if OPENTHREAD_CONFIG_BORDER_ROUTING_STUB_ROUTER_FLAG_IN_EMITTED_RA_ENABLE
553     VerifyOrQuit(sawStubRouterFlag);
554 #endif
555 
556     if (!sRaValidated)
557     {
558         switch (sExpectedPio)
559         {
560         case kNoPio:
561             break;
562         case kPioAdvertisingLocalOnLink:
563         case kPioDeprecatingLocalOnLink:
564             // First emitted RAs may not yet have the expected PIO
565             // so we exit and not set `sRaValidated` to allow it
566             // to be checked for next received RA.
567             VerifyOrExit(sawExpectedPio);
568             break;
569         }
570 
571         sRaValidated = true;
572     }
573 
574 exit:
575     return;
576 }
577 
578 //----------------------------------------------------------------------------------------------------------------------
579 
LogRouterAdvert(const Icmp6Packet & aPacket)580 void LogRouterAdvert(const Icmp6Packet &aPacket)
581 {
582     Ip6::Nd::RouterAdvert::RxMessage raMsg(aPacket);
583 
584     VerifyOrQuit(raMsg.IsValid());
585 
586     Log("     RA header - M:%u, O:%u", raMsg.GetHeader().IsManagedAddressConfigFlagSet(),
587         raMsg.GetHeader().IsOtherConfigFlagSet());
588     Log("     RA header - lifetime %u, prf:%s", raMsg.GetHeader().GetRouterLifetime(),
589         PreferenceToString(raMsg.GetHeader().GetDefaultRouterPreference()));
590 
591     for (const Ip6::Nd::Option &option : raMsg)
592     {
593         switch (option.GetType())
594         {
595         case Ip6::Nd::Option::kTypePrefixInfo:
596         {
597             const Ip6::Nd::PrefixInfoOption &pio = static_cast<const Ip6::Nd::PrefixInfoOption &>(option);
598             Ip6::Prefix                      prefix;
599 
600             VerifyOrQuit(pio.IsValid());
601             pio.GetPrefix(prefix);
602             Log("     PIO - %s, flags:%s%s, valid:%u, preferred:%u", prefix.ToString().AsCString(),
603                 pio.IsOnLinkFlagSet() ? "L" : "", pio.IsAutoAddrConfigFlagSet() ? "A" : "", pio.GetValidLifetime(),
604                 pio.GetPreferredLifetime());
605             break;
606         }
607 
608         case Ip6::Nd::Option::kTypeRouteInfo:
609         {
610             const Ip6::Nd::RouteInfoOption &rio = static_cast<const Ip6::Nd::RouteInfoOption &>(option);
611             Ip6::Prefix                     prefix;
612 
613             VerifyOrQuit(rio.IsValid());
614             rio.GetPrefix(prefix);
615             Log("     RIO - %s, prf:%s, lifetime:%u", prefix.ToString().AsCString(),
616                 PreferenceToString(rio.GetPreference()), rio.GetRouteLifetime());
617             break;
618         }
619 
620         case Ip6::Nd::Option::kTypeRaFlagsExtension:
621         {
622             const Ip6::Nd::RaFlagsExtOption &flagsOption = static_cast<const Ip6::Nd::RaFlagsExtOption &>(option);
623 
624             VerifyOrQuit(flagsOption.IsValid());
625             Log("     FlagsExt - StubRouter:%u", flagsOption.IsStubRouterFlagSet());
626             break;
627         }
628 
629         default:
630             VerifyOrQuit(false, "Bad option type in RA msg");
631         }
632     }
633 }
634 
LogRouterAdvert(const uint8_t * aBuffer,size_t aLength)635 void LogRouterAdvert(const uint8_t *aBuffer, size_t aLength)
636 {
637     Icmp6Packet packet;
638     packet.Init(aBuffer, aLength);
639     LogRouterAdvert(packet);
640 }
641 
PreferenceToString(int8_t aPreference)642 const char *PreferenceToString(int8_t aPreference)
643 {
644     const char *str = "";
645 
646     switch (aPreference)
647     {
648     case NetworkData::kRoutePreferenceLow:
649         str = "low";
650         break;
651 
652     case NetworkData::kRoutePreferenceMedium:
653         str = "med";
654         break;
655 
656     case NetworkData::kRoutePreferenceHigh:
657         str = "high";
658         break;
659 
660     default:
661         break;
662     }
663 
664     return str;
665 }
666 
SendRouterAdvert(const Ip6::Address & aAddress,const uint8_t * aBuffer,uint16_t aLength)667 void SendRouterAdvert(const Ip6::Address &aAddress, const uint8_t *aBuffer, uint16_t aLength)
668 {
669     otPlatInfraIfRecvIcmp6Nd(sInstance, kInfraIfIndex, &aAddress, aBuffer, aLength);
670 }
671 
SendRouterAdvert(const Ip6::Address & aAddress,const Icmp6Packet & aPacket)672 void SendRouterAdvert(const Ip6::Address &aAddress, const Icmp6Packet &aPacket)
673 {
674     SendRouterAdvert(aAddress, aPacket.GetBytes(), aPacket.GetLength());
675 }
676 
SendNeighborAdvert(const Ip6::Address & aAddress,const Ip6::Nd::NeighborAdvertMessage & aNaMessage)677 void SendNeighborAdvert(const Ip6::Address &aAddress, const Ip6::Nd::NeighborAdvertMessage &aNaMessage)
678 {
679     Log("Sending NA from %s", aAddress.ToString().AsCString());
680     otPlatInfraIfRecvIcmp6Nd(sInstance, kInfraIfIndex, &aAddress, reinterpret_cast<const uint8_t *>(&aNaMessage),
681                              sizeof(aNaMessage));
682 }
683 
DiscoverNat64Prefix(const Ip6::Prefix & aPrefix)684 void DiscoverNat64Prefix(const Ip6::Prefix &aPrefix)
685 {
686     Log("Discovered NAT64 prefix %s", aPrefix.ToString().AsCString());
687 
688     otPlatInfraIfDiscoverNat64PrefixDone(sInstance, kInfraIfIndex, &aPrefix);
689 }
690 
PrefixFromString(const char * aString,uint8_t aPrefixLength)691 Ip6::Prefix PrefixFromString(const char *aString, uint8_t aPrefixLength)
692 {
693     Ip6::Prefix prefix;
694 
695     SuccessOrQuit(AsCoreType(&prefix.mPrefix).FromString(aString));
696     prefix.mLength = aPrefixLength;
697 
698     return prefix;
699 }
700 
AddressFromString(const char * aString)701 Ip6::Address AddressFromString(const char *aString)
702 {
703     Ip6::Address address;
704 
705     SuccessOrQuit(address.FromString(aString));
706 
707     return address;
708 }
709 
VerifyOmrPrefixInNetData(const Ip6::Prefix & aOmrPrefix,bool aDefaultRoute)710 void VerifyOmrPrefixInNetData(const Ip6::Prefix &aOmrPrefix, bool aDefaultRoute)
711 {
712     otNetworkDataIterator           iterator = OT_NETWORK_DATA_ITERATOR_INIT;
713     NetworkData::OnMeshPrefixConfig prefixConfig;
714 
715     Log("VerifyOmrPrefixInNetData(%s, def-route:%s)", aOmrPrefix.ToString().AsCString(), aDefaultRoute ? "yes" : "no");
716 
717     SuccessOrQuit(otNetDataGetNextOnMeshPrefix(sInstance, &iterator, &prefixConfig));
718     VerifyOrQuit(prefixConfig.GetPrefix() == aOmrPrefix);
719     VerifyOrQuit(prefixConfig.mStable == true);
720     VerifyOrQuit(prefixConfig.mSlaac == true);
721     VerifyOrQuit(prefixConfig.mPreferred == true);
722     VerifyOrQuit(prefixConfig.mOnMesh == true);
723     VerifyOrQuit(prefixConfig.mDefaultRoute == aDefaultRoute);
724 
725     VerifyOrQuit(otNetDataGetNextOnMeshPrefix(sInstance, &iterator, &prefixConfig) == kErrorNotFound);
726 }
727 
VerifyNoOmrPrefixInNetData(void)728 void VerifyNoOmrPrefixInNetData(void)
729 {
730     otNetworkDataIterator           iterator = OT_NETWORK_DATA_ITERATOR_INIT;
731     NetworkData::OnMeshPrefixConfig prefixConfig;
732 
733     Log("VerifyNoOmrPrefixInNetData()");
734     VerifyOrQuit(otNetDataGetNextOnMeshPrefix(sInstance, &iterator, &prefixConfig) != kErrorNone);
735 }
736 
737 using NetworkData::RoutePreference;
738 
739 enum ExternalRouteMode : uint8_t
740 {
741     kNoRoute,
742     kDefaultRoute,
743     kUlaRoute,
744 };
745 
746 enum AdvPioMode : uint8_t
747 {
748     kSkipAdvPioCheck,
749     kWithAdvPioFlagSet,
750     kWithAdvPioCleared,
751 };
752 
VerifyExternalRouteInNetData(ExternalRouteMode aExternalRouteMode,AdvPioMode aAdvPioMode=kSkipAdvPioCheck)753 void VerifyExternalRouteInNetData(ExternalRouteMode aExternalRouteMode, AdvPioMode aAdvPioMode = kSkipAdvPioCheck)
754 {
755     Error                 error;
756     otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
757     otExternalRouteConfig routeConfig;
758 
759     error = otNetDataGetNextRoute(sInstance, &iterator, &routeConfig);
760 
761     switch (aExternalRouteMode)
762     {
763     case kNoRoute:
764         Log("VerifyExternalRouteInNetData(kNoRoute)");
765         VerifyOrQuit(error != kErrorNone);
766         break;
767 
768     case kDefaultRoute:
769         Log("VerifyExternalRouteInNetData(kDefaultRoute)");
770         VerifyOrQuit(error == kErrorNone);
771         VerifyOrQuit(routeConfig.mPrefix.mLength == 0);
772         VerifyOrQuit((aAdvPioMode == kSkipAdvPioCheck) || (routeConfig.mAdvPio == (aAdvPioMode == kWithAdvPioFlagSet)));
773         VerifyOrQuit(otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) != kErrorNone);
774         break;
775 
776     case kUlaRoute:
777         Log("VerifyExternalRouteInNetData(kUlaRoute)");
778         VerifyOrQuit(error == kErrorNone);
779         VerifyOrQuit(routeConfig.mPrefix.mLength == 7);
780         VerifyOrQuit(routeConfig.mPrefix.mPrefix.mFields.m8[0] == 0xfc);
781         VerifyOrQuit((aAdvPioMode == kSkipAdvPioCheck) || (routeConfig.mAdvPio == (aAdvPioMode == kWithAdvPioFlagSet)));
782         VerifyOrQuit(otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) != kErrorNone);
783         break;
784     }
785 }
786 
VerifyNat64PrefixInNetData(const Ip6::Prefix & aNat64Prefix)787 void VerifyNat64PrefixInNetData(const Ip6::Prefix &aNat64Prefix)
788 {
789     otNetworkDataIterator            iterator = OT_NETWORK_DATA_ITERATOR_INIT;
790     NetworkData::ExternalRouteConfig routeConfig;
791     bool                             didFind = false;
792 
793     Log("VerifyNat64PrefixInNetData()");
794 
795     while (otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) == kErrorNone)
796     {
797         if (!routeConfig.mNat64 || !routeConfig.GetPrefix().IsValidNat64())
798         {
799             continue;
800         }
801 
802         Log("   nat64 prefix:%s, prf:%s", routeConfig.GetPrefix().ToString().AsCString(),
803             PreferenceToString(routeConfig.mPreference));
804 
805         VerifyOrQuit(routeConfig.GetPrefix() == aNat64Prefix);
806         didFind = true;
807     }
808 
809     VerifyOrQuit(didFind);
810 }
811 
812 struct Pio
813 {
Pioot::Pio814     Pio(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime)
815         : mPrefix(aPrefix)
816         , mValidLifetime(aValidLifetime)
817         , mPreferredLifetime(aPreferredLifetime)
818     {
819     }
820 
821     const Ip6::Prefix &mPrefix;
822     uint32_t           mValidLifetime;
823     uint32_t           mPreferredLifetime;
824 };
825 
826 struct Rio
827 {
Rioot::Rio828     Rio(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, RoutePreference aPreference)
829         : mPrefix(aPrefix)
830         , mValidLifetime(aValidLifetime)
831         , mPreference(aPreference)
832     {
833     }
834 
835     const Ip6::Prefix &mPrefix;
836     uint32_t           mValidLifetime;
837     RoutePreference    mPreference;
838 };
839 
840 struct DefaultRoute
841 {
DefaultRouteot::DefaultRoute842     DefaultRoute(uint32_t aLifetime, RoutePreference aPreference)
843         : mLifetime(aLifetime)
844         , mPreference(aPreference)
845     {
846     }
847 
848     uint32_t        mLifetime;
849     RoutePreference mPreference;
850 };
851 
852 struct RaFlags : public Clearable<RaFlags>
853 {
RaFlagsot::RaFlags854     RaFlags(void)
855         : mManagedAddressConfigFlag(false)
856         , mOtherConfigFlag(false)
857         , mStubRouterFlag(false)
858     {
859     }
860 
861     bool mManagedAddressConfigFlag;
862     bool mOtherConfigFlag;
863     bool mStubRouterFlag;
864 };
865 
BuildRouterAdvert(Ip6::Nd::RouterAdvert::TxMessage & aRaMsg,const Pio * aPios,uint16_t aNumPios,const Rio * aRios,uint16_t aNumRios,const DefaultRoute & aDefaultRoute,const RaFlags & aRaFlags)866 void BuildRouterAdvert(Ip6::Nd::RouterAdvert::TxMessage &aRaMsg,
867                        const Pio                        *aPios,
868                        uint16_t                          aNumPios,
869                        const Rio                        *aRios,
870                        uint16_t                          aNumRios,
871                        const DefaultRoute               &aDefaultRoute,
872                        const RaFlags                    &aRaFlags)
873 {
874     Ip6::Nd::RouterAdvert::Header header;
875 
876     header.SetRouterLifetime(aDefaultRoute.mLifetime);
877     header.SetDefaultRouterPreference(aDefaultRoute.mPreference);
878 
879     if (aRaFlags.mManagedAddressConfigFlag)
880     {
881         header.SetManagedAddressConfigFlag();
882     }
883 
884     if (aRaFlags.mOtherConfigFlag)
885     {
886         header.SetOtherConfigFlag();
887     }
888 
889     SuccessOrQuit(aRaMsg.AppendHeader(header));
890 
891     if (aRaFlags.mStubRouterFlag)
892     {
893         SuccessOrQuit(aRaMsg.AppendFlagsExtensionOption(/* aStubRouterFlag */ true));
894     }
895 
896     for (; aNumPios > 0; aPios++, aNumPios--)
897     {
898         SuccessOrQuit(aRaMsg.AppendPrefixInfoOption(aPios->mPrefix, aPios->mValidLifetime, aPios->mPreferredLifetime));
899     }
900 
901     for (; aNumRios > 0; aRios++, aNumRios--)
902     {
903         SuccessOrQuit(aRaMsg.AppendRouteInfoOption(aRios->mPrefix, aRios->mValidLifetime, aRios->mPreference));
904     }
905 }
906 
SendRouterAdvert(const Ip6::Address & aRouterAddress,const Pio * aPios,uint16_t aNumPios,const Rio * aRios,uint16_t aNumRios,const DefaultRoute & aDefaultRoute,const RaFlags & aRaFlags)907 void SendRouterAdvert(const Ip6::Address &aRouterAddress,
908                       const Pio          *aPios,
909                       uint16_t            aNumPios,
910                       const Rio          *aRios,
911                       uint16_t            aNumRios,
912                       const DefaultRoute &aDefaultRoute,
913                       const RaFlags      &aRaFlags)
914 {
915     Ip6::Nd::RouterAdvert::TxMessage raMsg;
916     Icmp6Packet                      packet;
917 
918     BuildRouterAdvert(raMsg, aPios, aNumPios, aRios, aNumRios, aDefaultRoute, aRaFlags);
919     raMsg.GetAsPacket(packet);
920 
921     SendRouterAdvert(aRouterAddress, packet);
922     Log("Sending RA from router %s", aRouterAddress.ToString().AsCString());
923     LogRouterAdvert(packet);
924 }
925 
926 template <uint16_t kNumPios, uint16_t kNumRios>
SendRouterAdvert(const Ip6::Address & aRouterAddress,const Pio (& aPios)[kNumPios],const Rio (& aRios)[kNumRios],const DefaultRoute & aDefaultRoute=DefaultRoute (0,NetworkData::kRoutePreferenceMedium),const RaFlags & aRaFlags=RaFlags ())927 void SendRouterAdvert(const Ip6::Address &aRouterAddress,
928                       const Pio (&aPios)[kNumPios],
929                       const Rio (&aRios)[kNumRios],
930                       const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
931                       const RaFlags      &aRaFlags      = RaFlags())
932 {
933     SendRouterAdvert(aRouterAddress, aPios, kNumPios, aRios, kNumRios, aDefaultRoute, aRaFlags);
934 }
935 
936 template <uint16_t kNumPios>
SendRouterAdvert(const Ip6::Address & aRouterAddress,const Pio (& aPios)[kNumPios],const DefaultRoute & aDefaultRoute=DefaultRoute (0,NetworkData::kRoutePreferenceMedium),const RaFlags & aRaFlags=RaFlags ())937 void SendRouterAdvert(const Ip6::Address &aRouterAddress,
938                       const Pio (&aPios)[kNumPios],
939                       const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
940                       const RaFlags      &aRaFlags      = RaFlags())
941 {
942     SendRouterAdvert(aRouterAddress, aPios, kNumPios, nullptr, 0, aDefaultRoute, aRaFlags);
943 }
944 
945 template <uint16_t kNumRios>
SendRouterAdvert(const Ip6::Address & aRouterAddress,const Rio (& aRios)[kNumRios],const DefaultRoute & aDefaultRoute=DefaultRoute (0,NetworkData::kRoutePreferenceMedium),const RaFlags & aRaFlags=RaFlags ())946 void SendRouterAdvert(const Ip6::Address &aRouterAddress,
947                       const Rio (&aRios)[kNumRios],
948                       const DefaultRoute &aDefaultRoute = DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
949                       const RaFlags      &aRaFlags      = RaFlags())
950 {
951     SendRouterAdvert(aRouterAddress, nullptr, 0, aRios, kNumRios, aDefaultRoute, aRaFlags);
952 }
953 
SendRouterAdvert(const Ip6::Address & aRouterAddress,const DefaultRoute & aDefaultRoute,const RaFlags & aRaFlags=RaFlags ())954 void SendRouterAdvert(const Ip6::Address &aRouterAddress,
955                       const DefaultRoute &aDefaultRoute,
956                       const RaFlags      &aRaFlags = RaFlags())
957 {
958     SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, aDefaultRoute, aRaFlags);
959 }
960 
SendRouterAdvert(const Ip6::Address & aRouterAddress,const RaFlags & aRaFlags)961 void SendRouterAdvert(const Ip6::Address &aRouterAddress, const RaFlags &aRaFlags)
962 {
963     SendRouterAdvert(aRouterAddress, nullptr, 0, nullptr, 0, DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
964                      aRaFlags);
965 }
966 
SendRouterAdvertToBorderRoutingProcessIcmp6Ra(const Pio (& aPios)[kNumPios])967 template <uint16_t kNumPios> void SendRouterAdvertToBorderRoutingProcessIcmp6Ra(const Pio (&aPios)[kNumPios])
968 {
969     Ip6::Nd::RouterAdvert::TxMessage raMsg;
970     Icmp6Packet                      packet;
971 
972     BuildRouterAdvert(raMsg, aPios, kNumPios, nullptr, 0, DefaultRoute(0, NetworkData::kRoutePreferenceMedium),
973                       RaFlags());
974     raMsg.GetAsPacket(packet);
975 
976     otPlatBorderRoutingProcessIcmp6Ra(sInstance, packet.GetBytes(), packet.GetLength());
977     Log("Passing RA to otPlatBorderRoutingProcessIcmp6Ra");
978     LogRouterAdvert(packet);
979 }
980 
981 struct OnLinkPrefix : public Pio
982 {
OnLinkPrefixot::OnLinkPrefix983     OnLinkPrefix(const Ip6::Prefix  &aPrefix,
984                  uint32_t            aValidLifetime,
985                  uint32_t            aPreferredLifetime,
986                  const Ip6::Address &aRouterAddress)
987         : Pio(aPrefix, aValidLifetime, aPreferredLifetime)
988         , mRouterAddress(aRouterAddress)
989     {
990     }
991 
992     const Ip6::Address &mRouterAddress;
993 };
994 
995 struct RoutePrefix : public Rio
996 {
RoutePrefixot::RoutePrefix997     RoutePrefix(const Ip6::Prefix  &aPrefix,
998                 uint32_t            aValidLifetime,
999                 RoutePreference     aPreference,
1000                 const Ip6::Address &aRouterAddress)
1001         : Rio(aPrefix, aValidLifetime, aPreference)
1002         , mRouterAddress(aRouterAddress)
1003     {
1004     }
1005 
1006     const Ip6::Address &mRouterAddress;
1007 };
1008 
1009 template <uint16_t kNumOnLinkPrefixes, uint16_t kNumRoutePrefixes>
VerifyPrefixTable(const OnLinkPrefix (& aOnLinkPrefixes)[kNumOnLinkPrefixes],const RoutePrefix (& aRoutePrefixes)[kNumRoutePrefixes])1010 void VerifyPrefixTable(const OnLinkPrefix (&aOnLinkPrefixes)[kNumOnLinkPrefixes],
1011                        const RoutePrefix (&aRoutePrefixes)[kNumRoutePrefixes])
1012 {
1013     VerifyPrefixTable(aOnLinkPrefixes, kNumOnLinkPrefixes, aRoutePrefixes, kNumRoutePrefixes);
1014 }
1015 
VerifyPrefixTable(const OnLinkPrefix (& aOnLinkPrefixes)[kNumOnLinkPrefixes])1016 template <uint16_t kNumOnLinkPrefixes> void VerifyPrefixTable(const OnLinkPrefix (&aOnLinkPrefixes)[kNumOnLinkPrefixes])
1017 {
1018     VerifyPrefixTable(aOnLinkPrefixes, kNumOnLinkPrefixes, nullptr, 0);
1019 }
1020 
VerifyPrefixTable(const RoutePrefix (& aRoutePrefixes)[kNumRoutePrefixes])1021 template <uint16_t kNumRoutePrefixes> void VerifyPrefixTable(const RoutePrefix (&aRoutePrefixes)[kNumRoutePrefixes])
1022 {
1023     VerifyPrefixTable(nullptr, 0, aRoutePrefixes, kNumRoutePrefixes);
1024 }
1025 
VerifyPrefixTable(const OnLinkPrefix * aOnLinkPrefixes,uint16_t aNumOnLinkPrefixes,const RoutePrefix * aRoutePrefixes,uint16_t aNumRoutePrefixes)1026 void VerifyPrefixTable(const OnLinkPrefix *aOnLinkPrefixes,
1027                        uint16_t            aNumOnLinkPrefixes,
1028                        const RoutePrefix  *aRoutePrefixes,
1029                        uint16_t            aNumRoutePrefixes)
1030 {
1031     BorderRouter::RoutingManager::PrefixTableIterator iter;
1032     BorderRouter::RoutingManager::PrefixTableEntry    entry;
1033     uint16_t                                          onLinkPrefixCount = 0;
1034     uint16_t                                          routePrefixCount  = 0;
1035 
1036     Log("VerifyPrefixTable()");
1037 
1038     sInstance->Get<BorderRouter::RoutingManager>().InitPrefixTableIterator(iter);
1039 
1040     while (sInstance->Get<BorderRouter::RoutingManager>().GetNextPrefixTableEntry(iter, entry) == kErrorNone)
1041     {
1042         bool didFind = false;
1043 
1044         if (entry.mIsOnLink)
1045         {
1046             Log("   on-link prefix:%s, valid:%u, preferred:%u, router:%s, age:%u",
1047                 AsCoreType(&entry.mPrefix).ToString().AsCString(), entry.mValidLifetime, entry.mPreferredLifetime,
1048                 AsCoreType(&entry.mRouter.mAddress).ToString().AsCString(), entry.mMsecSinceLastUpdate / 1000);
1049 
1050             onLinkPrefixCount++;
1051 
1052             for (uint16_t index = 0; index < aNumOnLinkPrefixes; index++)
1053             {
1054                 const OnLinkPrefix &onLinkPrefix = aOnLinkPrefixes[index];
1055 
1056                 if ((onLinkPrefix.mPrefix == AsCoreType(&entry.mPrefix)) &&
1057                     (AsCoreType(&entry.mRouter.mAddress) == onLinkPrefix.mRouterAddress))
1058                 {
1059                     VerifyOrQuit(entry.mValidLifetime == onLinkPrefix.mValidLifetime);
1060                     VerifyOrQuit(entry.mPreferredLifetime == onLinkPrefix.mPreferredLifetime);
1061                     didFind = true;
1062                     break;
1063                 }
1064             }
1065         }
1066         else
1067         {
1068             Log("   route prefix:%s, valid:%u, prf:%s, router:%s, age:%u",
1069                 AsCoreType(&entry.mPrefix).ToString().AsCString(), entry.mValidLifetime,
1070                 PreferenceToString(entry.mRoutePreference), AsCoreType(&entry.mRouter.mAddress).ToString().AsCString(),
1071                 entry.mMsecSinceLastUpdate / 1000);
1072 
1073             routePrefixCount++;
1074 
1075             for (uint16_t index = 0; index < aNumRoutePrefixes; index++)
1076             {
1077                 const RoutePrefix &routePrefix = aRoutePrefixes[index];
1078 
1079                 if ((routePrefix.mPrefix == AsCoreType(&entry.mPrefix)) &&
1080                     (AsCoreType(&entry.mRouter.mAddress) == routePrefix.mRouterAddress))
1081                 {
1082                     VerifyOrQuit(entry.mValidLifetime == routePrefix.mValidLifetime);
1083                     VerifyOrQuit(static_cast<int8_t>(entry.mRoutePreference) == routePrefix.mPreference);
1084                     didFind = true;
1085                     break;
1086                 }
1087             }
1088         }
1089 
1090         VerifyOrQuit(didFind);
1091     }
1092 
1093     VerifyOrQuit(onLinkPrefixCount == aNumOnLinkPrefixes);
1094     VerifyOrQuit(routePrefixCount == aNumRoutePrefixes);
1095 }
1096 
VerifyPrefixTableIsEmpty(void)1097 void VerifyPrefixTableIsEmpty(void) { VerifyPrefixTable(nullptr, 0, nullptr, 0); }
1098 
1099 struct InfraRouter
1100 {
InfraRouterot::InfraRouter1101     InfraRouter(const Ip6::Address &aAddress,
1102                 bool                aManagedAddressConfigFlag,
1103                 bool                aOtherConfigFlag,
1104                 bool                aStubRouterFlag)
1105         : mAddress(aAddress)
1106     {
1107         mFlags.Clear();
1108         mFlags.mManagedAddressConfigFlag = aManagedAddressConfigFlag;
1109         mFlags.mOtherConfigFlag          = aOtherConfigFlag;
1110         mFlags.mStubRouterFlag           = aStubRouterFlag;
1111     }
1112 
1113     Ip6::Address mAddress;
1114     RaFlags      mFlags;
1115 };
1116 
VerifyDiscoveredRouters(const InfraRouter (& aRouters)[kNumRouters])1117 template <uint16_t kNumRouters> void VerifyDiscoveredRouters(const InfraRouter (&aRouters)[kNumRouters])
1118 {
1119     VerifyDiscoveredRouters(aRouters, kNumRouters);
1120 }
1121 
VerifyDiscoveredRouters(const InfraRouter * aRouters,uint16_t aNumRouters)1122 void VerifyDiscoveredRouters(const InfraRouter *aRouters, uint16_t aNumRouters)
1123 {
1124     BorderRouter::RoutingManager::PrefixTableIterator iter;
1125     BorderRouter::RoutingManager::RouterEntry         entry;
1126     uint16_t                                          count = 0;
1127 
1128     Log("VerifyDiscoveredRouters()");
1129 
1130     sInstance->Get<BorderRouter::RoutingManager>().InitPrefixTableIterator(iter);
1131 
1132     while (sInstance->Get<BorderRouter::RoutingManager>().GetNextRouterEntry(iter, entry) == kErrorNone)
1133     {
1134         bool didFind = false;
1135 
1136         Log("   address:%s, M:%u, O:%u, StubRouter:%u", AsCoreType(&entry.mAddress).ToString().AsCString(),
1137             entry.mManagedAddressConfigFlag, entry.mOtherConfigFlag, entry.mStubRouterFlag);
1138 
1139         for (uint16_t index = 0; index < aNumRouters; index++)
1140         {
1141             if (AsCoreType(&entry.mAddress) == aRouters[index].mAddress)
1142             {
1143                 VerifyOrQuit(entry.mManagedAddressConfigFlag == aRouters[index].mFlags.mManagedAddressConfigFlag);
1144                 VerifyOrQuit(entry.mOtherConfigFlag == aRouters[index].mFlags.mOtherConfigFlag);
1145                 VerifyOrQuit(entry.mStubRouterFlag == aRouters[index].mFlags.mStubRouterFlag);
1146                 didFind = true;
1147             }
1148         }
1149 
1150         VerifyOrQuit(didFind);
1151         count++;
1152     }
1153 
1154     VerifyOrQuit(count == aNumRouters);
1155 }
1156 
VerifyDiscoveredRoutersIsEmpty(void)1157 void VerifyDiscoveredRoutersIsEmpty(void) { VerifyDiscoveredRouters(nullptr, 0); }
1158 
InitTest(bool aEnablBorderRouting=false,bool aAfterReset=false)1159 void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false)
1160 {
1161     uint32_t delay = 10000;
1162 
1163     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1164     // Initialize OT instance.
1165 
1166     sNow      = 0;
1167     sAlarmOn  = false;
1168     sInstance = static_cast<Instance *>(testInitInstance());
1169 
1170     if (aAfterReset)
1171     {
1172         delay += 26000; // leader reset sync delay
1173     }
1174 
1175     memset(&sRadioTxFrame, 0, sizeof(sRadioTxFrame));
1176     sRadioTxFrame.mPsdu = sRadioTxFramePsdu;
1177     sRadioTxOngoing     = false;
1178 
1179     SuccessOrQuit(sInfraIfAddress.FromString(kInfraIfAddress));
1180 
1181     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1182     // Initialize and start Border Router and Thread operation.
1183 
1184     SuccessOrQuit(otBorderRoutingInit(sInstance, kInfraIfIndex, /* aInfraIfIsRunning */ true));
1185 
1186     otOperationalDatasetTlvs datasetTlvs;
1187 
1188     SuccessOrQuit(otDatasetConvertToTlvs(&kDataset, &datasetTlvs));
1189     SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs));
1190 
1191     SuccessOrQuit(otIp6SetEnabled(sInstance, true));
1192     SuccessOrQuit(otThreadSetEnabled(sInstance, true));
1193     SuccessOrQuit(otBorderRoutingSetEnabled(sInstance, aEnablBorderRouting));
1194 
1195     // Reset all test flags
1196     sRsEmitted   = false;
1197     sRaValidated = false;
1198     sExpectedPio = kNoPio;
1199     sExpectedRios.Clear();
1200     sRespondToNs              = true;
1201     sExpectedRaHeaderFlags    = kRaHeaderFlagsNone;
1202     sCheckRaHeaderLifetime    = true;
1203     sExpectedRaHeaderLifetime = 0;
1204 
1205     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1206     // Ensure device starts as leader.
1207 
1208     AdvanceTime(delay);
1209 
1210     VerifyOrQuit(otThreadGetDeviceRole(sInstance) == OT_DEVICE_ROLE_LEADER);
1211 }
1212 
FinalizeTest(void)1213 void FinalizeTest(void)
1214 {
1215     SuccessOrQuit(otIp6SetEnabled(sInstance, false));
1216     SuccessOrQuit(otThreadSetEnabled(sInstance, false));
1217     SuccessOrQuit(otInstanceErasePersistentInfo(sInstance));
1218     testFreeInstance(sInstance);
1219 }
1220 
1221 //---------------------------------------------------------------------------------------------------------------------
1222 
TestSamePrefixesFromMultipleRouters(void)1223 void TestSamePrefixesFromMultipleRouters(void)
1224 {
1225     Ip6::Prefix  localOnLink;
1226     Ip6::Prefix  localOmr;
1227     Ip6::Prefix  onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
1228     Ip6::Prefix  routePrefix    = PrefixFromString("2000:1234:5678::", 64);
1229     Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
1230     Ip6::Address routerAddressB = AddressFromString("fd00::bbbb");
1231     uint16_t     heapAllocations;
1232 
1233     Log("--------------------------------------------------------------------------------------------");
1234     Log("TestSamePrefixesFromMultipleRouters");
1235 
1236     InitTest();
1237 
1238     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1239     // Start Routing Manager. Check emitted RS and RA messages.
1240 
1241     sRsEmitted   = false;
1242     sRaValidated = false;
1243     sExpectedPio = kPioAdvertisingLocalOnLink;
1244     sExpectedRios.Clear();
1245 
1246     heapAllocations = sHeapAllocatedPtrs.GetLength();
1247     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
1248 
1249     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
1250     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
1251 
1252     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
1253     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
1254 
1255     sExpectedRios.Add(localOmr);
1256 
1257     AdvanceTime(30000);
1258 
1259     VerifyOrQuit(sRsEmitted);
1260     VerifyOrQuit(sRaValidated);
1261     VerifyOrQuit(sExpectedRios.SawAll());
1262     Log("Received RA was validated");
1263 
1264     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1265     // Check Network Data to include the local OMR and on-link prefix.
1266 
1267     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1268     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1269 
1270     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1271     // Send an RA from router A with a new on-link (PIO) and route prefix (RIO).
1272 
1273     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)},
1274                      {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)});
1275 
1276     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1277     // Check that the local on-link prefix is now deprecating in the new RA.
1278 
1279     sRaValidated = false;
1280     sExpectedPio = kPioDeprecatingLocalOnLink;
1281 
1282     AdvanceTime(10000);
1283     VerifyOrQuit(sRaValidated);
1284 
1285     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1286     // Check the discovered prefix table and ensure info from router A
1287     // is present in the table.
1288 
1289     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)},
1290                       {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)});
1291 
1292     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1293     // Check Network Data to include new prefixes from router A.
1294 
1295     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ true);
1296     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1297 
1298     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1299     // Send the same RA again from router A with the on-link (PIO) and route prefix (RIO).
1300 
1301     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)},
1302                      {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)});
1303 
1304     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1305     // Check the discovered prefix table and ensure info from router A
1306     // remains unchanged.
1307 
1308     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)},
1309                       {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)});
1310 
1311     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1312     // Send an RA from router B with same route prefix (RIO) but with
1313     // high route preference.
1314 
1315     SendRouterAdvert(routerAddressB, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh)});
1316 
1317     AdvanceTime(10000);
1318 
1319     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1320     // Check the discovered prefix table and ensure info from router B
1321     // is also included in the table.
1322 
1323     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)},
1324                       {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA),
1325                        RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh, routerAddressB)});
1326 
1327     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1328     // Check Network Data.
1329 
1330     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ true);
1331     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1332 
1333     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1334     // Send an RA from router B removing the route prefix.
1335 
1336     SendRouterAdvert(routerAddressB, {Rio(routePrefix, 0, NetworkData::kRoutePreferenceHigh)});
1337 
1338     AdvanceTime(10000);
1339 
1340     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1341     // Check the discovered prefix table and ensure info from router B
1342     // is now removed from the table.
1343 
1344     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)},
1345                       {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)});
1346 
1347     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1348     // Check Network Data.
1349 
1350     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1351 
1352     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1353 
1354     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
1355     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
1356 
1357     Log("End of TestSamePrefixesFromMultipleRouters");
1358 
1359     FinalizeTest();
1360 }
1361 
TestOmrSelection(void)1362 void TestOmrSelection(void)
1363 {
1364     Ip6::Prefix                     localOnLink;
1365     Ip6::Prefix                     localOmr;
1366     Ip6::Prefix                     omrPrefix = PrefixFromString("2000:0000:1111:4444::", 64);
1367     NetworkData::OnMeshPrefixConfig prefixConfig;
1368     uint16_t                        heapAllocations;
1369 
1370     Log("--------------------------------------------------------------------------------------------");
1371     Log("TestOmrSelection");
1372 
1373     InitTest();
1374 
1375     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1376     // Start Routing Manager. Check emitted RS and RA messages.
1377 
1378     sRsEmitted   = false;
1379     sRaValidated = false;
1380     sExpectedPio = kPioAdvertisingLocalOnLink;
1381     sExpectedRios.Clear();
1382 
1383     heapAllocations = sHeapAllocatedPtrs.GetLength();
1384     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
1385 
1386     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
1387     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
1388 
1389     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
1390     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
1391 
1392     sExpectedRios.Add(localOmr);
1393 
1394     AdvanceTime(30000);
1395 
1396     VerifyOrQuit(sRsEmitted);
1397     VerifyOrQuit(sRaValidated);
1398     VerifyOrQuit(sExpectedRios.SawAll());
1399     VerifyOrQuit(sExpectedRios[0].mLifetime == kRioValidLifetime);
1400 
1401     Log("Received RA was validated");
1402 
1403     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1404     // Check Network Data to include the local OMR and on-link prefix.
1405 
1406     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1407     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1408 
1409     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1410     // Add a new OMR prefix directly into net data. The new prefix should
1411     // be favored over the local OMR prefix.
1412 
1413     prefixConfig.Clear();
1414     prefixConfig.mPrefix       = omrPrefix;
1415     prefixConfig.mStable       = true;
1416     prefixConfig.mSlaac        = true;
1417     prefixConfig.mPreferred    = true;
1418     prefixConfig.mOnMesh       = true;
1419     prefixConfig.mDefaultRoute = false;
1420     prefixConfig.mPreference   = NetworkData::kRoutePreferenceMedium;
1421 
1422     SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
1423     SuccessOrQuit(otBorderRouterRegister(sInstance));
1424 
1425     AdvanceTime(100);
1426 
1427     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1428     // Make sure BR emits RA with the new OMR prefix now, and deprecates the old OMR prefix.
1429 
1430     sRaValidated = false;
1431     sExpectedPio = kPioAdvertisingLocalOnLink;
1432     sExpectedRios.Clear();
1433     sExpectedRios.Add(omrPrefix);
1434     sExpectedRios.Add(localOmr);
1435 
1436     AdvanceTime(20000);
1437 
1438     VerifyOrQuit(sRaValidated);
1439     VerifyOrQuit(sExpectedRios.SawAll());
1440     VerifyOrQuit(sExpectedRios[0].mLifetime == kRioValidLifetime);
1441     VerifyOrQuit(sExpectedRios[1].mLifetime <= kRioDeprecatingLifetime);
1442 
1443     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1444     // Check Network Data. We should now see that the local OMR prefix
1445     // is removed.
1446 
1447     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ false);
1448     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1449 
1450     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1451     // Remove the OMR prefix previously added in net data.
1452 
1453     SuccessOrQuit(otBorderRouterRemoveOnMeshPrefix(sInstance, &omrPrefix));
1454     SuccessOrQuit(otBorderRouterRegister(sInstance));
1455 
1456     AdvanceTime(100);
1457 
1458     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1459     // Make sure BR emits RA with local OMR prefix again and start
1460     // deprecating the previously added OMR prefix.
1461 
1462     sRaValidated = false;
1463     sExpectedRios.Clear();
1464     sExpectedRios.Add(omrPrefix);
1465     sExpectedRios.Add(localOmr);
1466 
1467     AdvanceTime(20000);
1468 
1469     VerifyOrQuit(sRaValidated);
1470     VerifyOrQuit(sExpectedRios.SawAll());
1471     VerifyOrQuit(sExpectedRios[0].mLifetime <= kRioDeprecatingLifetime);
1472     VerifyOrQuit(sExpectedRios[1].mLifetime == kRioValidLifetime);
1473 
1474     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1475     // Check Network Data. We should see that the local OMR prefix is
1476     // added again.
1477 
1478     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1479     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1480 
1481     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1482     // Wait enough for old deprecating OMR prefix deprecating to expire.
1483 
1484     sRaValidated = false;
1485     sExpectedRios.Clear();
1486     sExpectedRios.Add(omrPrefix);
1487     sExpectedRios.Add(localOmr);
1488 
1489     AdvanceTime(310000);
1490 
1491     VerifyOrQuit(sRaValidated);
1492     VerifyOrQuit(sExpectedRios.SawAll());
1493     VerifyOrQuit(sExpectedRios[0].mLifetime == 0);
1494     VerifyOrQuit(sExpectedRios[1].mLifetime == kRioValidLifetime);
1495 
1496     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1497 
1498     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
1499     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
1500 
1501     Log("End of TestOmrSelection");
1502     FinalizeTest();
1503 }
1504 
TestDefaultRoute(void)1505 void TestDefaultRoute(void)
1506 {
1507     Ip6::Prefix                     localOnLink;
1508     Ip6::Prefix                     localOmr;
1509     Ip6::Prefix                     omrPrefix      = PrefixFromString("2000:0000:1111:4444::", 64);
1510     Ip6::Prefix                     defaultRoute   = PrefixFromString("::", 0);
1511     Ip6::Address                    routerAddressA = AddressFromString("fd00::aaaa");
1512     NetworkData::OnMeshPrefixConfig prefixConfig;
1513     uint16_t                        heapAllocations;
1514 
1515     Log("--------------------------------------------------------------------------------------------");
1516     Log("TestDefaultRoute");
1517 
1518     InitTest();
1519 
1520     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1521     // Start Routing Manager. Check emitted RS and RA messages.
1522 
1523     sRsEmitted   = false;
1524     sRaValidated = false;
1525     sExpectedPio = kPioAdvertisingLocalOnLink;
1526     sExpectedRios.Clear();
1527 
1528     heapAllocations = sHeapAllocatedPtrs.GetLength();
1529     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
1530 
1531     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
1532     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
1533 
1534     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
1535     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
1536 
1537     sExpectedRios.Add(localOmr);
1538 
1539     AdvanceTime(30000);
1540 
1541     VerifyOrQuit(sRsEmitted);
1542     VerifyOrQuit(sRaValidated);
1543     VerifyOrQuit(sExpectedRios.SawAll());
1544     Log("Received RA was validated");
1545 
1546     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1547     // Check Network Data to include the local OMR and ULA prefix.
1548 
1549     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1550     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1551 
1552     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1553     // Send RA from router A advertising a default route.
1554 
1555     SendRouterAdvert(routerAddressA, DefaultRoute(kValidLitime, NetworkData::kRoutePreferenceLow));
1556 
1557     AdvanceTime(10000);
1558 
1559     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1560     // Check the discovered prefix table and ensure default route
1561     // from router A is in the table.
1562 
1563     VerifyPrefixTable({RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceLow, routerAddressA)});
1564 
1565     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1566     // Check Network Data. We should not see default route in
1567     // Network Data yet since there is no infrastructure-derived
1568     // OMR prefix (with preference medium or higher).
1569 
1570     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1571     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1572 
1573     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1574     // Add an OMR prefix directly into Network Data with
1575     // preference medium (infrastructure-derived).
1576 
1577     prefixConfig.Clear();
1578     prefixConfig.mPrefix       = omrPrefix;
1579     prefixConfig.mStable       = true;
1580     prefixConfig.mSlaac        = true;
1581     prefixConfig.mPreferred    = true;
1582     prefixConfig.mOnMesh       = true;
1583     prefixConfig.mDefaultRoute = true;
1584     prefixConfig.mPreference   = NetworkData::kRoutePreferenceMedium;
1585 
1586     SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
1587     SuccessOrQuit(otBorderRouterRegister(sInstance));
1588 
1589     AdvanceTime(10000);
1590 
1591     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1592     // Check Network Data. Now that we have an infrastructure-derived
1593     // OMR prefix, the default route should be published.
1594 
1595     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1596     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1597 
1598     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1599     // Remove the OMR prefix from Network Data.
1600 
1601     SuccessOrQuit(otBorderRouterRemoveOnMeshPrefix(sInstance, &omrPrefix));
1602     SuccessOrQuit(otBorderRouterRegister(sInstance));
1603 
1604     AdvanceTime(10000);
1605 
1606     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1607     // Check Network Data. We should again go back to ULA prefix. The
1608     // default route advertised by router A should be still present in
1609     // the discovered prefix table.
1610 
1611     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1612     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1613 
1614     VerifyPrefixTable({RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceLow, routerAddressA)});
1615 
1616     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1617     // Add the OMR prefix again.
1618 
1619     SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
1620     SuccessOrQuit(otBorderRouterRegister(sInstance));
1621 
1622     AdvanceTime(10000);
1623 
1624     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1625     // Check Network Data. Again the default route should be published.
1626 
1627     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1628     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1629 
1630     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1631     // Send RA from router A removing the default route.
1632 
1633     SendRouterAdvert(routerAddressA, DefaultRoute(0, NetworkData::kRoutePreferenceLow));
1634 
1635     AdvanceTime(10000);
1636 
1637     VerifyPrefixTableIsEmpty();
1638 
1639     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1640     // Check Network Data. Now that router A no longer advertised
1641     // a default-route, we should go back to publishing ULA route.
1642 
1643     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1644     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1645 
1646     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1647     // Send RA from router A again advertising a default route.
1648 
1649     SendRouterAdvert(routerAddressA, DefaultRoute(kValidLitime, NetworkData::kRoutePreferenceLow));
1650 
1651     AdvanceTime(10000);
1652 
1653     VerifyPrefixTable({RoutePrefix(defaultRoute, kValidLitime, NetworkData::kRoutePreferenceLow, routerAddressA)});
1654 
1655     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1656     // Check Network Data. We should see default route published.
1657 
1658     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1659     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1660 
1661     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1662 
1663     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
1664     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
1665 
1666     Log("End of TestDefaultRoute");
1667 
1668     FinalizeTest();
1669 }
1670 
TestAdvNonUlaRoute(void)1671 void TestAdvNonUlaRoute(void)
1672 {
1673     Ip6::Prefix                     localOnLink;
1674     Ip6::Prefix                     localOmr;
1675     Ip6::Prefix                     omrPrefix      = PrefixFromString("2000:0000:1111:4444::", 64);
1676     Ip6::Prefix                     routePrefix    = PrefixFromString("2000:1234:5678::", 64);
1677     Ip6::Address                    routerAddressA = AddressFromString("fd00::aaaa");
1678     NetworkData::OnMeshPrefixConfig prefixConfig;
1679     uint16_t                        heapAllocations;
1680 
1681     Log("--------------------------------------------------------------------------------------------");
1682     Log("TestAdvNonUlaRoute");
1683 
1684     InitTest();
1685 
1686     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1687     // Start Routing Manager. Check emitted RS and RA messages.
1688 
1689     sRsEmitted   = false;
1690     sRaValidated = false;
1691     sExpectedPio = kPioAdvertisingLocalOnLink;
1692     sExpectedRios.Clear();
1693 
1694     heapAllocations = sHeapAllocatedPtrs.GetLength();
1695     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
1696 
1697     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
1698     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
1699 
1700     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
1701     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
1702 
1703     sExpectedRios.Add(localOmr);
1704 
1705     AdvanceTime(30000);
1706 
1707     VerifyOrQuit(sRsEmitted);
1708     VerifyOrQuit(sRaValidated);
1709     VerifyOrQuit(sExpectedRios.SawAll());
1710     Log("Received RA was validated");
1711 
1712     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1713     // Check Network Data to include the local OMR and ULA prefix.
1714 
1715     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1716     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1717 
1718     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1719     // Send RA from router A advertising a non-ULA.
1720 
1721     SendRouterAdvert(routerAddressA, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)});
1722 
1723     AdvanceTime(10000);
1724 
1725     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1726     // Check the discovered prefix table and ensure the non-ULA
1727     // from router A is in the table.
1728 
1729     VerifyPrefixTable({RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)});
1730 
1731     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1732     // Check Network Data. We should not see default route in
1733     // Network Data yet since there is no infrastructure-derived
1734     // OMR prefix (with preference medium or higher).
1735 
1736     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1737     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1738 
1739     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1740     // Add an OMR prefix directly into Network Data with
1741     // preference medium (infrastructure-derived).
1742 
1743     prefixConfig.Clear();
1744     prefixConfig.mPrefix       = omrPrefix;
1745     prefixConfig.mStable       = true;
1746     prefixConfig.mSlaac        = true;
1747     prefixConfig.mPreferred    = true;
1748     prefixConfig.mOnMesh       = true;
1749     prefixConfig.mDefaultRoute = true;
1750     prefixConfig.mPreference   = NetworkData::kRoutePreferenceMedium;
1751 
1752     SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
1753     SuccessOrQuit(otBorderRouterRegister(sInstance));
1754 
1755     AdvanceTime(10000);
1756 
1757     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1758     // Check Network Data. Now that we have an infrastructure-derived
1759     // OMR prefix, the default route should be published.
1760 
1761     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1762     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1763 
1764     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1765     // Remove the OMR prefix from Network Data.
1766 
1767     SuccessOrQuit(otBorderRouterRemoveOnMeshPrefix(sInstance, &omrPrefix));
1768     SuccessOrQuit(otBorderRouterRegister(sInstance));
1769 
1770     AdvanceTime(10000);
1771 
1772     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1773     // Check Network Data. We should again go back to ULA prefix. The
1774     // non-ULA route advertised by router A should be still present in
1775     // the discovered prefix table.
1776 
1777     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1778     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1779 
1780     VerifyPrefixTable({RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)});
1781 
1782     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1783     // Add the OMR prefix again.
1784 
1785     SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
1786     SuccessOrQuit(otBorderRouterRegister(sInstance));
1787 
1788     AdvanceTime(10000);
1789 
1790     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1791     // Check Network Data. Again the default route should be published.
1792 
1793     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1794     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1795 
1796     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1797     // Send RA from router A removing the route.
1798 
1799     SendRouterAdvert(routerAddressA, {Rio(routePrefix, 0, NetworkData::kRoutePreferenceMedium)});
1800 
1801     AdvanceTime(10000);
1802 
1803     VerifyPrefixTableIsEmpty();
1804 
1805     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1806     // Check Network Data. Now that router A no longer advertised
1807     // the route, we should go back to publishing the ULA route.
1808 
1809     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1810     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1811 
1812     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1813     // Send RA from router A again advertising the route again.
1814 
1815     SendRouterAdvert(routerAddressA, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)});
1816 
1817     AdvanceTime(10000);
1818 
1819     VerifyPrefixTable({RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)});
1820 
1821     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1822     // Check Network Data. We should see default route published.
1823 
1824     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ true);
1825     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
1826 
1827     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1828 
1829     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
1830     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
1831 
1832     Log("End of TestAdvNonUlaRoute");
1833 
1834     FinalizeTest();
1835 }
1836 
TestLocalOnLinkPrefixDeprecation(void)1837 void TestLocalOnLinkPrefixDeprecation(void)
1838 {
1839     static constexpr uint32_t kMaxRaTxInterval = 601; // In seconds
1840 
1841     Ip6::Prefix  localOnLink;
1842     Ip6::Prefix  localOmr;
1843     Ip6::Prefix  onLinkPrefix   = PrefixFromString("fd00:abba:baba::", 64);
1844     Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
1845     uint32_t     localOnLinkLifetime;
1846     uint16_t     heapAllocations;
1847 
1848     Log("--------------------------------------------------------------------------------------------");
1849     Log("TestLocalOnLinkPrefixDeprecation");
1850 
1851     InitTest();
1852 
1853     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1854     // Start Routing Manager. Check emitted RS and RA messages.
1855 
1856     heapAllocations = sHeapAllocatedPtrs.GetLength();
1857     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
1858 
1859     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
1860     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
1861 
1862     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
1863     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
1864 
1865     sRsEmitted   = false;
1866     sRaValidated = false;
1867     sExpectedPio = kPioAdvertisingLocalOnLink;
1868     sExpectedRios.Clear();
1869     sExpectedRios.Add(localOmr);
1870 
1871     AdvanceTime(30000);
1872 
1873     VerifyOrQuit(sRsEmitted);
1874     VerifyOrQuit(sRaValidated);
1875     VerifyOrQuit(sExpectedRios.SawAll());
1876     Log("Local on-link prefix is being advertised, lifetime: %d", sOnLinkLifetime);
1877     localOnLinkLifetime = sOnLinkLifetime;
1878 
1879     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1880     // Check Network Data to include the local OMR and on-link prefix.
1881 
1882     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1883     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1884 
1885     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1886     // Send an RA from router A with a new on-link (PIO) which is preferred over
1887     // the local on-link prefix.
1888 
1889     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kInfiniteLifetime, kInfiniteLifetime)});
1890 
1891     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1892     // Check that the local on-link prefix is now deprecating in the new RA.
1893 
1894     sRaValidated = false;
1895     sExpectedPio = kPioDeprecatingLocalOnLink;
1896     sExpectedRios.Clear();
1897     sExpectedRios.Add(localOmr);
1898 
1899     AdvanceTime(10000);
1900     VerifyOrQuit(sRaValidated);
1901     VerifyOrQuit(sExpectedRios.SawAll());
1902     Log("On-link prefix is deprecating, remaining lifetime:%d", sOnLinkLifetime);
1903     VerifyOrQuit(sOnLinkLifetime < localOnLinkLifetime);
1904     localOnLinkLifetime = sOnLinkLifetime;
1905 
1906     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1907     // Check Network Data. We must see the new on-link prefix from router A
1908     // along with the deprecating local on-link prefix.
1909 
1910     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1911     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
1912 
1913     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1914     // Wait for local on-link prefix to expire
1915 
1916     while (localOnLinkLifetime > kMaxRaTxInterval)
1917     {
1918         // Send same RA from router A to keep the on-link prefix alive.
1919 
1920         SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
1921 
1922         // Ensure Network Data entries remain as before. Mainly we still
1923         // see the deprecating local on-link prefix.
1924 
1925         VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1926         VerifyExternalRouteInNetData(kUlaRoute, kSkipAdvPioCheck);
1927 
1928         // Keep checking the emitted RAs and make sure on-link prefix
1929         // is included with smaller lifetime every time.
1930 
1931         sRaValidated = false;
1932         sExpectedPio = kPioDeprecatingLocalOnLink;
1933         sExpectedRios.Clear();
1934         sExpectedRios.Add(localOmr);
1935 
1936         AdvanceTime(kMaxRaTxInterval * 1000);
1937 
1938         VerifyOrQuit(sRaValidated);
1939         VerifyOrQuit(sExpectedRios.SawAll());
1940         Log("On-link prefix is deprecating, remaining lifetime:%d", sOnLinkLifetime);
1941         VerifyOrQuit(sOnLinkLifetime < localOnLinkLifetime);
1942         localOnLinkLifetime = sOnLinkLifetime;
1943     }
1944 
1945     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1946     // The local on-link prefix must be expired and should no
1947     // longer be seen in the emitted RA message.
1948 
1949     sRaValidated = false;
1950     sExpectedPio = kNoPio;
1951     sExpectedRios.Clear();
1952     sExpectedRios.Add(localOmr);
1953 
1954     AdvanceTime(kMaxRaTxInterval * 1000);
1955 
1956     VerifyOrQuit(sRaValidated);
1957     VerifyOrQuit(sExpectedRios.SawAll());
1958     Log("On-link prefix is now expired");
1959 
1960     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1961     // Check Network Data.
1962 
1963     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
1964     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioCleared);
1965 
1966     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1967 
1968     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
1969     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
1970 
1971     Log("End of TestLocalOnLinkPrefixDeprecation");
1972 
1973     FinalizeTest();
1974 }
1975 
1976 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
TestDomainPrefixAsOmr(void)1977 void TestDomainPrefixAsOmr(void)
1978 {
1979     Ip6::Prefix                     localOnLink;
1980     Ip6::Prefix                     localOmr;
1981     Ip6::Prefix                     domainPrefix = PrefixFromString("2000:0000:1111:4444::", 64);
1982     NetworkData::OnMeshPrefixConfig prefixConfig;
1983     uint16_t                        heapAllocations;
1984 
1985     Log("--------------------------------------------------------------------------------------------");
1986     Log("TestDomainPrefixAsOmr");
1987 
1988     InitTest();
1989 
1990     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1991     // Start Routing Manager. Check emitted RS and RA messages.
1992 
1993     sRsEmitted   = false;
1994     sRaValidated = false;
1995     sExpectedPio = kPioAdvertisingLocalOnLink;
1996     sExpectedRios.Clear();
1997 
1998     heapAllocations = sHeapAllocatedPtrs.GetLength();
1999     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
2000 
2001     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2002     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
2003 
2004     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
2005     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
2006 
2007     sExpectedRios.Add(localOmr);
2008 
2009     AdvanceTime(30000);
2010 
2011     VerifyOrQuit(sRsEmitted);
2012     VerifyOrQuit(sRaValidated);
2013     VerifyOrQuit(sExpectedRios.SawAll());
2014     Log("Received RA was validated");
2015 
2016     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2017     // Check Network Data to include the local OMR and on-link prefix.
2018 
2019     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
2020     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2021 
2022     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2023     // Add a domain prefix directly into net data. The new prefix should
2024     // be favored over the local OMR prefix.
2025 
2026     otBackboneRouterSetEnabled(sInstance, true);
2027 
2028     prefixConfig.Clear();
2029     prefixConfig.mPrefix       = domainPrefix;
2030     prefixConfig.mStable       = true;
2031     prefixConfig.mSlaac        = true;
2032     prefixConfig.mPreferred    = true;
2033     prefixConfig.mOnMesh       = true;
2034     prefixConfig.mDefaultRoute = false;
2035     prefixConfig.mDp           = true;
2036     prefixConfig.mPreference   = NetworkData::kRoutePreferenceMedium;
2037 
2038     SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
2039     SuccessOrQuit(otBorderRouterRegister(sInstance));
2040 
2041     AdvanceTime(100);
2042 
2043     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2044     // Make sure BR emits RA without domain prefix or previous local OMR.
2045 
2046     sRaValidated = false;
2047     sExpectedPio = kPioAdvertisingLocalOnLink;
2048     sExpectedRios.Clear();
2049     sExpectedRios.Add(domainPrefix);
2050     sExpectedRios.Add(localOmr);
2051 
2052     AdvanceTime(20000);
2053 
2054     VerifyOrQuit(sRaValidated);
2055 
2056     // We should see RIO removing the local OMR prefix with lifetime zero
2057     // and should not see the domain prefix as RIO.
2058 
2059     VerifyOrQuit(sExpectedRios[0].mPrefix == domainPrefix);
2060     VerifyOrQuit(!sExpectedRios[0].mSawInRa);
2061 
2062     VerifyOrQuit(sExpectedRios[1].mPrefix == localOmr);
2063     VerifyOrQuit(sExpectedRios[1].mSawInRa);
2064     VerifyOrQuit(sExpectedRios[1].mLifetime <= kRioDeprecatingLifetime);
2065 
2066     // Wait long enough for deprecating RIO prefix to expire
2067     AdvanceTime(3200000);
2068 
2069     sRaValidated = false;
2070     sExpectedPio = kPioAdvertisingLocalOnLink;
2071     sExpectedRios.Clear();
2072     sExpectedRios.Add(domainPrefix);
2073     sExpectedRios.Add(localOmr);
2074 
2075     // Wait for next RA (650 seconds).
2076 
2077     AdvanceTime(650000);
2078 
2079     VerifyOrQuit(sRaValidated);
2080 
2081     // We should not see either domain prefix or local OMR
2082     // as RIO.
2083 
2084     VerifyOrQuit(!sExpectedRios[0].mSawInRa);
2085     VerifyOrQuit(!sExpectedRios[1].mSawInRa);
2086 
2087     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2088     // Check Network Data. We should now see that the local OMR prefix
2089     // is removed.
2090 
2091     VerifyOmrPrefixInNetData(domainPrefix, /* aDefaultRoute */ false);
2092     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2093 
2094     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2095     // Remove the domain prefix from net data.
2096 
2097     SuccessOrQuit(otBorderRouterRemoveOnMeshPrefix(sInstance, &domainPrefix));
2098     SuccessOrQuit(otBorderRouterRegister(sInstance));
2099 
2100     AdvanceTime(100);
2101 
2102     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2103     // Make sure BR emits RA with local OMR prefix again.
2104 
2105     sRaValidated = false;
2106     sExpectedRios.Clear();
2107     sExpectedRios.Add(localOmr);
2108 
2109     AdvanceTime(20000);
2110 
2111     VerifyOrQuit(sRaValidated);
2112     VerifyOrQuit(sExpectedRios.SawAll());
2113 
2114     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2115     // Check Network Data. We should see that the local OMR prefix is
2116     // added again.
2117 
2118     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
2119     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2120 
2121     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2122 
2123     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
2124     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
2125 
2126     Log("End of TestDomainPrefixAsOmr");
2127     FinalizeTest();
2128 }
2129 #endif // OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
2130 
TestExtPanIdChange(void)2131 void TestExtPanIdChange(void)
2132 {
2133     static constexpr uint32_t kMaxRaTxInterval = 601; // In seconds
2134 
2135     static const otExtendedPanId kExtPanId1 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x08}};
2136     static const otExtendedPanId kExtPanId2 = {{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x99, 0x88}};
2137     static const otExtendedPanId kExtPanId3 = {{0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, 0xcd, 0xef}};
2138     static const otExtendedPanId kExtPanId4 = {{0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00}};
2139     static const otExtendedPanId kExtPanId5 = {{0x77, 0x88, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55}};
2140 
2141     Ip6::Prefix          localOnLink;
2142     Ip6::Prefix          oldLocalOnLink;
2143     Ip6::Prefix          localOmr;
2144     Ip6::Prefix          onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
2145     Ip6::Address         routerAddressA = AddressFromString("fd00::aaaa");
2146     uint32_t             oldPrefixLifetime;
2147     Ip6::Prefix          oldPrefixes[4];
2148     otOperationalDataset dataset;
2149     uint16_t             heapAllocations;
2150 
2151     Log("--------------------------------------------------------------------------------------------");
2152     Log("TestExtPanIdChange");
2153 
2154     InitTest();
2155 
2156     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2157     // Start Routing Manager. Check emitted RS and RA messages.
2158 
2159     heapAllocations = sHeapAllocatedPtrs.GetLength();
2160     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
2161 
2162     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2163     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
2164 
2165     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
2166     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
2167 
2168     sRsEmitted   = false;
2169     sRaValidated = false;
2170     sExpectedPio = kPioAdvertisingLocalOnLink;
2171     sExpectedRios.Clear();
2172     sExpectedRios.Add(localOmr);
2173 
2174     AdvanceTime(30000);
2175 
2176     VerifyOrQuit(sRsEmitted);
2177     VerifyOrQuit(sRaValidated);
2178     VerifyOrQuit(sExpectedRios.SawAll());
2179     Log("Local on-link prefix is being advertised, lifetime: %d", sOnLinkLifetime);
2180 
2181     //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2182     // Check behavior when ext PAN ID changes while the local on-link is
2183     // being advertised.
2184 
2185     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2186     // Change the extended PAN ID.
2187 
2188     Log("Changing ext PAN ID");
2189 
2190     oldLocalOnLink    = localOnLink;
2191     oldPrefixLifetime = sOnLinkLifetime;
2192 
2193     sRaValidated = false;
2194     sExpectedPio = kPioAdvertisingLocalOnLink;
2195 
2196     SuccessOrQuit(otDatasetGetActive(sInstance, &dataset));
2197 
2198     VerifyOrQuit(dataset.mComponents.mIsExtendedPanIdPresent);
2199 
2200     dataset.mExtendedPanId = kExtPanId1;
2201     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2202 
2203     AdvanceTime(500);
2204     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2205     Log("Local on-link prefix changed to %s from %s", localOnLink.ToString().AsCString(),
2206         oldLocalOnLink.ToString().AsCString());
2207 
2208     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2209     // Validate the received RA message and that it contains the
2210     // old on-link prefix being deprecated.
2211 
2212     AdvanceTime(30000);
2213 
2214     VerifyOrQuit(sRaValidated);
2215     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2216     VerifyOrQuit(sDeprecatingPrefixes[0].mPrefix == oldLocalOnLink);
2217     oldPrefixLifetime = sDeprecatingPrefixes[0].mLifetime;
2218 
2219     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2220     // Validate Network Data.
2221 
2222     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
2223     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2224 
2225     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2226     // Stop BR and validate that a final RA is emitted deprecating
2227     // both current local on-link prefix and old prefix.
2228 
2229     sRaValidated = false;
2230     sExpectedPio = kPioDeprecatingLocalOnLink;
2231 
2232     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
2233     AdvanceTime(100);
2234 
2235     VerifyOrQuit(sRaValidated);
2236     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2237     VerifyOrQuit(sDeprecatingPrefixes[0].mPrefix == oldLocalOnLink);
2238     oldPrefixLifetime = sDeprecatingPrefixes[0].mLifetime;
2239 
2240     sRaValidated = false;
2241     AdvanceTime(350000);
2242     VerifyOrQuit(!sRaValidated);
2243 
2244     VerifyNoOmrPrefixInNetData();
2245     VerifyExternalRouteInNetData(kNoRoute);
2246 
2247     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2248     // Start BR again and validate old prefix will continue to
2249     // be deprecated.
2250 
2251     sRaValidated = false;
2252     sExpectedPio = kPioAdvertisingLocalOnLink;
2253 
2254     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
2255 
2256     AdvanceTime(300000);
2257     VerifyOrQuit(sRaValidated);
2258     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2259     VerifyOrQuit(sDeprecatingPrefixes[0].mPrefix == oldLocalOnLink);
2260     VerifyOrQuit(oldPrefixLifetime > sDeprecatingPrefixes[0].mLifetime);
2261     oldPrefixLifetime = sDeprecatingPrefixes[0].mLifetime;
2262 
2263     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2264     // Wait for old local on-link prefix to expire.
2265 
2266     while (oldPrefixLifetime > 2 * kMaxRaTxInterval)
2267     {
2268         // Ensure Network Data entries remain as before.
2269 
2270         VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2271 
2272         // Keep checking the emitted RAs and make sure the prefix
2273         // is included with smaller lifetime every time.
2274 
2275         sRaValidated = false;
2276 
2277         AdvanceTime(kMaxRaTxInterval * 1000);
2278 
2279         VerifyOrQuit(sRaValidated);
2280         VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2281         Log("Old on-link prefix is deprecating, remaining lifetime:%d", sDeprecatingPrefixes[0].mLifetime);
2282         VerifyOrQuit(sDeprecatingPrefixes[0].mLifetime < oldPrefixLifetime);
2283         oldPrefixLifetime = sDeprecatingPrefixes[0].mLifetime;
2284     }
2285 
2286     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2287     // The local on-link prefix must be expired now and should no
2288     // longer be seen in the emitted RA message.
2289 
2290     sRaValidated = false;
2291 
2292     AdvanceTime(3 * kMaxRaTxInterval * 1000);
2293 
2294     VerifyOrQuit(sRaValidated);
2295     VerifyOrQuit(sDeprecatingPrefixes.IsEmpty());
2296     Log("Old on-link prefix is now expired");
2297 
2298     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2299     // Validate the Network Data.
2300 
2301     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
2302     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2303 
2304     //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2305     // Check behavior when ext PAN ID changes while the local on-link is being
2306     // deprecated.
2307 
2308     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2309     // Send an RA from router A with a new on-link (PIO) which is preferred over
2310     // the local on-link prefix.
2311 
2312     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
2313 
2314     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2315     // Validate that the local on-link prefix is deprecated.
2316 
2317     sRaValidated = false;
2318     sExpectedPio = kPioDeprecatingLocalOnLink;
2319 
2320     AdvanceTime(30000);
2321 
2322     VerifyOrQuit(sRaValidated);
2323 
2324     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2325     // Change the extended PAN ID.
2326 
2327     oldLocalOnLink    = localOnLink;
2328     oldPrefixLifetime = sOnLinkLifetime;
2329 
2330     dataset.mExtendedPanId = kExtPanId2;
2331     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2332 
2333     AdvanceTime(500);
2334     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2335     Log("Local on-link prefix changed to %s from %s", localOnLink.ToString().AsCString(),
2336         oldLocalOnLink.ToString().AsCString());
2337 
2338     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2339     // Validate that the old local on-link prefix is still being included
2340     // as PIO in the emitted RA.
2341 
2342     sRaValidated = false;
2343     sExpectedPio = kNoPio;
2344 
2345     AdvanceTime(30000);
2346 
2347     VerifyOrQuit(sRaValidated);
2348     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2349     VerifyOrQuit(sDeprecatingPrefixes[0].mPrefix == oldLocalOnLink);
2350 
2351     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2352     // Validate that Network Data.
2353 
2354     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ true);
2355     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioCleared);
2356 
2357     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2358     // Wait for old local on-link prefix to expire.
2359 
2360     while (oldPrefixLifetime > 2 * kMaxRaTxInterval)
2361     {
2362         // Send same RA from router A to keep its on-link prefix alive.
2363 
2364         SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
2365 
2366         // Ensure Network Data entries remain as before.
2367 
2368         VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioCleared);
2369 
2370         // Keep checking the emitted RAs and make sure the prefix
2371         // is included with smaller lifetime every time.
2372 
2373         sRaValidated = false;
2374 
2375         AdvanceTime(kMaxRaTxInterval * 1000);
2376 
2377         VerifyOrQuit(sRaValidated);
2378         VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2379         Log("Old on-link prefix is deprecating, remaining lifetime:%d", sDeprecatingPrefixes[0].mLifetime);
2380         VerifyOrQuit(sDeprecatingPrefixes[0].mLifetime < oldPrefixLifetime);
2381         oldPrefixLifetime = sDeprecatingPrefixes[0].mLifetime;
2382     }
2383 
2384     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2385     // The old on-link prefix must be expired now and should no
2386     // longer be seen in the emitted RA message.
2387 
2388     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
2389 
2390     sRaValidated = false;
2391 
2392     AdvanceTime(kMaxRaTxInterval * 1000);
2393     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
2394     AdvanceTime(kMaxRaTxInterval * 1000);
2395     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
2396     AdvanceTime(kMaxRaTxInterval * 1000);
2397 
2398     VerifyOrQuit(sRaValidated);
2399     VerifyOrQuit(sDeprecatingPrefixes.IsEmpty());
2400     Log("Old on-link prefix is now expired");
2401 
2402     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2403     // Validate the Network Data.
2404 
2405     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ true);
2406     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioCleared);
2407 
2408     //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2409     // Check behavior when ext PAN ID changes while the local on-link is not
2410     // advertised.
2411 
2412     Log("Changing ext PAN ID again");
2413 
2414     oldLocalOnLink = localOnLink;
2415 
2416     sRaValidated = false;
2417     sExpectedPio = kNoPio;
2418 
2419     dataset.mExtendedPanId = kExtPanId3;
2420     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2421 
2422     AdvanceTime(500);
2423     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2424     Log("Local on-link prefix changed to %s from %s", localOnLink.ToString().AsCString(),
2425         oldLocalOnLink.ToString().AsCString());
2426 
2427     AdvanceTime(35000);
2428     VerifyOrQuit(sRaValidated);
2429     VerifyOrQuit(sDeprecatingPrefixes.IsEmpty());
2430 
2431     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2432     // Validate the Network Data.
2433 
2434     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ true);
2435     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioCleared);
2436 
2437     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2438     // Remove the on-link prefix PIO being advertised by router A
2439     // and ensure local on-link prefix is advertised again.
2440 
2441     sRaValidated = false;
2442     sExpectedPio = kPioAdvertisingLocalOnLink;
2443 
2444     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, 0)});
2445 
2446     AdvanceTime(300000);
2447     VerifyOrQuit(sRaValidated);
2448     VerifyOrQuit(sDeprecatingPrefixes.IsEmpty());
2449 
2450     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2451     // Wait for longer than valid lifetime of PIO entry from router A.
2452     // Validate that default route is unpublished from network data.
2453 
2454     AdvanceTime(2000 * 1000);
2455     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
2456     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2457 
2458     //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2459     // Multiple PAN ID changes and multiple deprecating old prefixes.
2460 
2461     oldPrefixes[0] = localOnLink;
2462 
2463     dataset.mExtendedPanId = kExtPanId2;
2464     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2465 
2466     sRaValidated = false;
2467     sExpectedPio = kPioAdvertisingLocalOnLink;
2468 
2469     AdvanceTime(30000);
2470     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2471     VerifyOrQuit(sRaValidated);
2472     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2473     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0]));
2474 
2475     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2476 
2477     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2478     // Change the prefix again. We should see two deprecating prefixes.
2479 
2480     oldPrefixes[1] = localOnLink;
2481 
2482     dataset.mExtendedPanId = kExtPanId1;
2483     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2484 
2485     sRaValidated = false;
2486     sExpectedPio = kPioAdvertisingLocalOnLink;
2487 
2488     AdvanceTime(30000);
2489     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2490     VerifyOrQuit(sRaValidated);
2491     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 2);
2492     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0]));
2493     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[1]));
2494 
2495     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2496 
2497     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2498     // Wait for 15 minutes and then change ext PAN ID again.
2499     // Now we should see three deprecating prefixes.
2500 
2501     AdvanceTime(15 * 60 * 1000);
2502 
2503     oldPrefixes[2] = localOnLink;
2504 
2505     dataset.mExtendedPanId = kExtPanId4;
2506     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2507 
2508     sRaValidated = false;
2509     sExpectedPio = kPioAdvertisingLocalOnLink;
2510 
2511     AdvanceTime(30000);
2512     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2513     VerifyOrQuit(sRaValidated);
2514     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 3);
2515     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0]));
2516     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[1]));
2517     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[2]));
2518 
2519     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2520 
2521     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2522     // Change ext PAN ID back to previous value of `kExtPanId1`.
2523     // We should still see three deprecating prefixes and the last prefix
2524     // at `oldPrefixes[2]` should again be treated as local on-link prefix.
2525 
2526     oldPrefixes[3] = localOnLink;
2527 
2528     dataset.mExtendedPanId = kExtPanId1;
2529     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2530 
2531     sRaValidated = false;
2532     sExpectedPio = kPioAdvertisingLocalOnLink;
2533 
2534     AdvanceTime(30000);
2535     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2536     VerifyOrQuit(sRaValidated);
2537     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 3);
2538     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0]));
2539     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[1]));
2540     VerifyOrQuit(oldPrefixes[2] == localOnLink);
2541     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[3]));
2542 
2543     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2544 
2545     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2546     // Stop BR and validate the final emitted RA to contain
2547     // all deprecating prefixes.
2548 
2549     sRaValidated = false;
2550     sExpectedPio = kPioDeprecatingLocalOnLink;
2551 
2552     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
2553     AdvanceTime(100);
2554 
2555     VerifyOrQuit(sRaValidated);
2556     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 3);
2557     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0]));
2558     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[1]));
2559     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[3]));
2560 
2561     VerifyNoOmrPrefixInNetData();
2562     VerifyExternalRouteInNetData(kNoRoute);
2563 
2564     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2565     // Wait for 15 minutes while BR stays disabled and validate
2566     // there are no emitted RAs. We want to check that deprecating
2567     // prefixes continue to expire while BR is stopped.
2568 
2569     sRaValidated = false;
2570     AdvanceTime(15 * 60 * 1000);
2571 
2572     VerifyOrQuit(!sRaValidated);
2573 
2574     VerifyNoOmrPrefixInNetData();
2575     VerifyExternalRouteInNetData(kNoRoute);
2576 
2577     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2578     // Start BR again, and check that we only see the last deprecating prefix
2579     // at `oldPrefixes[3]` in emitted RA and the other two are expired and
2580     // no longer included as PIO and/or in network data.
2581 
2582     sRaValidated = false;
2583     sExpectedPio = kPioAdvertisingLocalOnLink;
2584 
2585     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
2586 
2587     AdvanceTime(30000);
2588 
2589     VerifyOrQuit(sRaValidated);
2590     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
2591     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[3]));
2592 
2593     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2594 
2595     //= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2596     // Validate the oldest prefix is removed when we have too many
2597     // back-to-back PAN ID changes.
2598 
2599     // Remember the oldest deprecating prefix (associated with `kExtPanId4`).
2600     oldLocalOnLink = oldPrefixes[3];
2601 
2602     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(oldPrefixes[0]));
2603     dataset.mExtendedPanId = kExtPanId2;
2604     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2605     AdvanceTime(30000);
2606 
2607     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(oldPrefixes[1]));
2608     dataset.mExtendedPanId = kExtPanId3;
2609     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2610     AdvanceTime(30000);
2611 
2612     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(oldPrefixes[2]));
2613     dataset.mExtendedPanId = kExtPanId5;
2614     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
2615 
2616     sRaValidated = false;
2617 
2618     AdvanceTime(30000);
2619 
2620     VerifyOrQuit(sRaValidated);
2621     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2622     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 3);
2623     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[0]));
2624     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[1]));
2625     VerifyOrQuit(sDeprecatingPrefixes.ContainsMatching(oldPrefixes[2]));
2626     VerifyOrQuit(!sDeprecatingPrefixes.ContainsMatching(oldLocalOnLink));
2627 
2628     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
2629 
2630     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2631 
2632     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
2633     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
2634 
2635     Log("End of TestExtPanIdChange");
2636     FinalizeTest();
2637 }
2638 
TestRouterNsProbe(void)2639 void TestRouterNsProbe(void)
2640 {
2641     Ip6::Prefix  localOnLink;
2642     Ip6::Prefix  localOmr;
2643     Ip6::Prefix  onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
2644     Ip6::Prefix  routePrefix    = PrefixFromString("2000:1234:5678::", 64);
2645     Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
2646     Ip6::Address routerAddressB = AddressFromString("fd00::bbbb");
2647     uint16_t     heapAllocations;
2648 
2649     Log("--------------------------------------------------------------------------------------------");
2650     Log("TestRouterNsProbe");
2651 
2652     InitTest();
2653 
2654     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2655     // Start Routing Manager. Check emitted RS and RA messages.
2656 
2657     sRsEmitted   = false;
2658     sRaValidated = false;
2659     sExpectedPio = kPioAdvertisingLocalOnLink;
2660     sExpectedRios.Clear();
2661 
2662     heapAllocations = sHeapAllocatedPtrs.GetLength();
2663     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
2664 
2665     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2666     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
2667 
2668     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
2669     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
2670 
2671     sExpectedRios.Add(localOmr);
2672 
2673     AdvanceTime(30000);
2674 
2675     VerifyOrQuit(sRsEmitted);
2676     VerifyOrQuit(sRaValidated);
2677     VerifyOrQuit(sExpectedRios.SawAll());
2678     Log("Received RA was validated");
2679 
2680     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2681     // Send an RA from router A with a new on-link (PIO) and route prefix (RIO).
2682 
2683     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)},
2684                      {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium)});
2685 
2686     sExpectedPio = kPioDeprecatingLocalOnLink;
2687 
2688     AdvanceTime(10);
2689 
2690     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2691     // Check the discovered prefix table and ensure info from router A
2692     // is present in the table.
2693 
2694     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)},
2695                       {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA)});
2696 
2697     AdvanceTime(30000);
2698 
2699     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2700     // Send an RA from router B with same route prefix (RIO) but with
2701     // high route preference.
2702 
2703     SendRouterAdvert(routerAddressB, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh)});
2704 
2705     AdvanceTime(200);
2706 
2707     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2708     // Check the discovered prefix table and ensure entries from
2709     // both router A and B are seen.
2710 
2711     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, kPreferredLifetime, routerAddressA)},
2712                       {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceMedium, routerAddressA),
2713                        RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh, routerAddressB)});
2714 
2715     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2716     // Check that BR emitted an NS to ensure routers are active.
2717 
2718     sNsEmitted = false;
2719     sRsEmitted = false;
2720 
2721     AdvanceTime(160 * 1000);
2722 
2723     VerifyOrQuit(sNsEmitted);
2724     VerifyOrQuit(!sRsEmitted);
2725 
2726     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2727     // Disallow responding to NS message.
2728     //
2729     // This should trigger `RoutingManager` to send RS (which will get
2730     // no response as well) and then remove all router entries.
2731 
2732     sRespondToNs = false;
2733 
2734     sExpectedPio = kPioAdvertisingLocalOnLink;
2735     sRaValidated = false;
2736     sNsEmitted   = false;
2737 
2738     AdvanceTime(240 * 1000);
2739 
2740     VerifyOrQuit(sNsEmitted);
2741     VerifyOrQuit(sRaValidated);
2742 
2743     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2744     // Check the discovered prefix table. We should see the on-link entry from
2745     // router A as deprecated and no route prefix.
2746 
2747     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, 0, routerAddressA)});
2748 
2749     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2750     // Verify that no more NS is being sent (since there is no more valid
2751     // router entry in the table).
2752 
2753     sExpectedPio = kPioAdvertisingLocalOnLink;
2754     sRaValidated = false;
2755     sNsEmitted   = false;
2756 
2757     AdvanceTime(6 * 60 * 1000);
2758 
2759     VerifyOrQuit(!sNsEmitted);
2760 
2761     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2762     // Send an RA from router B and verify that we see router B
2763     // entry in prefix table.
2764 
2765     SendRouterAdvert(routerAddressB, {Rio(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh)});
2766 
2767     VerifyPrefixTable({OnLinkPrefix(onLinkPrefix, kValidLitime, 0, routerAddressA)},
2768                       {RoutePrefix(routePrefix, kValidLitime, NetworkData::kRoutePreferenceHigh, routerAddressB)});
2769 
2770     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2771     // Wait for longer than router active time before NS probe.
2772     // Check again that NS are sent again.
2773 
2774     sRespondToNs = true;
2775     sNsEmitted   = false;
2776     sRsEmitted   = false;
2777 
2778     AdvanceTime(3 * 60 * 1000);
2779 
2780     VerifyOrQuit(sNsEmitted);
2781     VerifyOrQuit(!sRsEmitted);
2782 
2783     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2784 
2785     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
2786     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
2787 
2788     Log("End of TestRouterNsProbe");
2789     FinalizeTest();
2790 }
2791 
TestLearningAndCopyingOfFlags(void)2792 void TestLearningAndCopyingOfFlags(void)
2793 {
2794     Ip6::Prefix  localOnLink;
2795     Ip6::Prefix  localOmr;
2796     Ip6::Prefix  onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
2797     Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
2798     Ip6::Address routerAddressB = AddressFromString("fd00::bbbb");
2799     Ip6::Address routerAddressC = AddressFromString("fd00::cccc");
2800     uint16_t     heapAllocations;
2801     RaFlags      raFlags;
2802 
2803     Log("--------------------------------------------------------------------------------------------");
2804     Log("TestLearningAndCopyingOfFlags");
2805 
2806     InitTest();
2807 
2808     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2809     // Start Routing Manager. Check emitted RS and RA messages.
2810 
2811     sRsEmitted   = false;
2812     sRaValidated = false;
2813     sExpectedPio = kPioAdvertisingLocalOnLink;
2814     sExpectedRios.Clear();
2815 
2816     heapAllocations = sHeapAllocatedPtrs.GetLength();
2817     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
2818 
2819     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2820     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
2821 
2822     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
2823     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
2824 
2825     sExpectedRios.Add(localOmr);
2826 
2827     AdvanceTime(30000);
2828 
2829     VerifyOrQuit(sRsEmitted);
2830     VerifyOrQuit(sRaValidated);
2831     VerifyOrQuit(sExpectedRios.SawAll());
2832     Log("Received RA was validated");
2833 
2834     VerifyDiscoveredRoutersIsEmpty();
2835 
2836     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2837     // Send an RA from router A with M flag set, and make sure the
2838     // emitted RA from BR also includes M flag.
2839 
2840     raFlags.Clear();
2841     raFlags.mManagedAddressConfigFlag = true;
2842 
2843     SendRouterAdvert(routerAddressA, raFlags);
2844 
2845     AdvanceTime(1);
2846     VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ false)});
2847 
2848     sRaValidated           = false;
2849     sExpectedRaHeaderFlags = kRaHeaderFlagsOnlyM;
2850 
2851     AdvanceTime(610 * 1000);
2852     VerifyOrQuit(sRaValidated);
2853 
2854     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2855     // Send an RA from router A without the M flag. Now the emitted
2856     // RA should no longer contain the M flag.
2857 
2858     raFlags.Clear();
2859 
2860     SendRouterAdvert(routerAddressA, raFlags);
2861 
2862     sRaValidated           = false;
2863     sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
2864 
2865     AdvanceTime(1);
2866     VerifyDiscoveredRoutersIsEmpty();
2867 
2868     AdvanceTime(610 * 1000);
2869     VerifyOrQuit(sRaValidated);
2870 
2871     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2872     // Send an RA from router A with both M and StubRouter flags.
2873     // Since it is from a stub router, the M flag should be ignored.
2874     // Ensure emitted RA does not set the M flag.
2875 
2876     raFlags.Clear();
2877     raFlags.mManagedAddressConfigFlag = true;
2878     raFlags.mStubRouterFlag           = true;
2879 
2880     SendRouterAdvert(routerAddressA, raFlags);
2881 
2882     AdvanceTime(1);
2883     VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true)});
2884 
2885     sRaValidated           = false;
2886     sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
2887 
2888     AdvanceTime(610 * 1000);
2889     VerifyOrQuit(sRaValidated);
2890 
2891     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2892     // Send an RA from router B with O flag and check that emitted
2893     // RA include the same flag.
2894 
2895     raFlags.Clear();
2896     raFlags.mOtherConfigFlag = true;
2897 
2898     SendRouterAdvert(routerAddressB, raFlags);
2899 
2900     AdvanceTime(1);
2901     VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true),
2902                              InfraRouter(routerAddressB, /* M */ false, /* O */ true, /* StubRouter */ false)});
2903 
2904     sRaValidated           = false;
2905     sExpectedRaHeaderFlags = kRaHeaderFlagsOnlyO;
2906 
2907     AdvanceTime(610 * 1000);
2908     VerifyOrQuit(sRaValidated);
2909 
2910     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2911     // Send an RA from router C with M flag and check that emitted
2912     // RA now includes both M and O flags.
2913 
2914     raFlags.Clear();
2915     raFlags.mManagedAddressConfigFlag = true;
2916 
2917     SendRouterAdvert(routerAddressC, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)},
2918                      DefaultRoute(0, NetworkData::kRoutePreferenceMedium), raFlags);
2919 
2920     AdvanceTime(1);
2921     VerifyDiscoveredRouters({InfraRouter(routerAddressA, /* M */ true, /* O */ false, /* StubRouter */ true),
2922                              InfraRouter(routerAddressB, /* M */ false, /* O */ true, /* StubRouter */ false),
2923                              InfraRouter(routerAddressC, /* M */ true, /* O */ false, /* StubRouter */ false)});
2924 
2925     sRaValidated           = false;
2926     sExpectedPio           = kPioDeprecatingLocalOnLink;
2927     sExpectedRaHeaderFlags = kRaHeaderFlagsBothMAndO;
2928 
2929     AdvanceTime(610 * 1000);
2930     VerifyOrQuit(sRaValidated);
2931 
2932     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2933     // Stop responding to NS, this should cause all routers
2934     // to age and considered offline
2935 
2936     sRespondToNs = false;
2937 
2938     sExpectedRaHeaderFlags = kRaHeaderFlagsSkipChecking;
2939 
2940     AdvanceTime(300 * 1000);
2941 
2942     // Router C should be in the table since it will have a deprecating
2943     // on-link prefix.
2944     VerifyDiscoveredRouters({InfraRouter(routerAddressC, /* M */ true, /* O */ false, /* StubRouter */ false)});
2945 
2946     sRaValidated           = false;
2947     sExpectedPio           = kPioAdvertisingLocalOnLink;
2948     sExpectedRaHeaderFlags = kRaHeaderFlagsNone;
2949 
2950     AdvanceTime(610 * 1000);
2951     VerifyOrQuit(sRaValidated);
2952 
2953     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2954 
2955     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
2956     VerifyDiscoveredRoutersIsEmpty();
2957 
2958     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
2959 
2960     Log("End of TestLearningAndCopyingOfFlags");
2961     FinalizeTest();
2962 }
2963 
TestLearnRaHeader(void)2964 void TestLearnRaHeader(void)
2965 {
2966     Ip6::Prefix localOnLink;
2967     Ip6::Prefix localOmr;
2968     Ip6::Prefix onLinkPrefix = PrefixFromString("2000:abba:baba::", 64);
2969     uint16_t    heapAllocations;
2970 
2971     Log("--------------------------------------------------------------------------------------------");
2972     Log("TestLearnRaHeader");
2973 
2974     InitTest();
2975 
2976     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2977     // Start Routing Manager. Check emitted RS and RA messages.
2978 
2979     sRsEmitted   = false;
2980     sRaValidated = false;
2981     sExpectedPio = kPioAdvertisingLocalOnLink;
2982     sExpectedRios.Clear();
2983 
2984     heapAllocations = sHeapAllocatedPtrs.GetLength();
2985     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
2986 
2987     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
2988     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
2989 
2990     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
2991     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
2992 
2993     sExpectedRios.Add(localOmr);
2994 
2995     AdvanceTime(30000);
2996 
2997     VerifyOrQuit(sRsEmitted);
2998     VerifyOrQuit(sRaValidated);
2999     VerifyOrQuit(sExpectedRios.SawAll());
3000     Log("Received RA was validated");
3001 
3002     VerifyDiscoveredRoutersIsEmpty();
3003 
3004     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3005     // Send an RA from the same address (another entity on the device)
3006     // advertising a default route.
3007 
3008     SendRouterAdvert(sInfraIfAddress, DefaultRoute(1000, NetworkData::kRoutePreferenceLow));
3009 
3010     AdvanceTime(1);
3011     VerifyDiscoveredRouters({InfraRouter(sInfraIfAddress, /* M */ false, /* O */ false, /* StubRouter */ false)});
3012 
3013     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3014     // RoutingManager should learn the header from the
3015     // received RA (from same address) and start advertising
3016     // the same default route lifetime in the emitted RAs.
3017 
3018     sRaValidated              = false;
3019     sCheckRaHeaderLifetime    = true;
3020     sExpectedRaHeaderLifetime = 1000;
3021 
3022     AdvanceTime(30 * 1000);
3023     VerifyOrQuit(sRaValidated);
3024 
3025     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3026     // Wait for longer than entry lifetime (for it to expire) and
3027     // make sure `RoutingManager` stops advertising default route.
3028 
3029     sCheckRaHeaderLifetime = false;
3030 
3031     AdvanceTime(1000 * 1000);
3032 
3033     sRaValidated              = false;
3034     sCheckRaHeaderLifetime    = true;
3035     sExpectedRaHeaderLifetime = 0;
3036 
3037     AdvanceTime(700 * 1000);
3038     VerifyOrQuit(sRaValidated);
3039 
3040     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3041 
3042     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
3043     VerifyDiscoveredRoutersIsEmpty();
3044 
3045     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
3046 
3047     Log("End of TestLearnRaHeader");
3048     FinalizeTest();
3049 }
3050 
TestConflictingPrefix(void)3051 void TestConflictingPrefix(void)
3052 {
3053     static const otExtendedPanId kExtPanId1 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x08}};
3054 
3055     Ip6::Prefix          localOnLink;
3056     Ip6::Prefix          oldLocalOnLink;
3057     Ip6::Prefix          localOmr;
3058     Ip6::Prefix          onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
3059     Ip6::Address         routerAddressA = AddressFromString("fd00::aaaa");
3060     Ip6::Address         routerAddressB = AddressFromString("fd00::bbbb");
3061     otOperationalDataset dataset;
3062     uint16_t             heapAllocations;
3063 
3064     Log("--------------------------------------------------------------------------------------------");
3065     Log("TestConflictingPrefix");
3066 
3067     InitTest();
3068 
3069     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3070     // Start Routing Manager. Check emitted RS and RA messages.
3071 
3072     sRsEmitted   = false;
3073     sRaValidated = false;
3074     sExpectedPio = kPioAdvertisingLocalOnLink;
3075     sExpectedRios.Clear();
3076 
3077     heapAllocations = sHeapAllocatedPtrs.GetLength();
3078     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
3079 
3080     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
3081     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
3082 
3083     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
3084     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
3085 
3086     sExpectedRios.Add(localOmr);
3087 
3088     AdvanceTime(30000);
3089 
3090     VerifyOrQuit(sRsEmitted);
3091     VerifyOrQuit(sRaValidated);
3092     VerifyOrQuit(sExpectedRios.SawAll());
3093     Log("Received RA was validated");
3094 
3095     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3096     // Check Network Data to include the local OMR and on-link prefix.
3097 
3098     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3099     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
3100 
3101     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3102     // Send an RA from router A with our local on-link prefix as RIO.
3103 
3104     Log("Send RA from router A with local on-link as RIO");
3105     SendRouterAdvert(routerAddressA, {Rio(localOnLink, kValidLitime, NetworkData::kRoutePreferenceMedium)});
3106 
3107     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3108     // Check that the local on-link prefix is still being advertised.
3109 
3110     sRaValidated = false;
3111     AdvanceTime(610000);
3112     VerifyOrQuit(sRaValidated);
3113 
3114     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3115     // Check Network Data to still include the local OMR and ULA prefix.
3116 
3117     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3118     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
3119 
3120     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3121     // Send an RA from router A removing local on-link prefix as RIO.
3122 
3123     SendRouterAdvert(routerAddressA, {Rio(localOnLink, 0, NetworkData::kRoutePreferenceMedium)});
3124 
3125     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3126     // Verify that ULA prefix is still included in Network Data and
3127     // the change by router A did not cause it to be unpublished.
3128 
3129     AdvanceTime(10000);
3130     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
3131 
3132     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3133     // Check that the local on-link prefix is still being advertised.
3134 
3135     sRaValidated = false;
3136     AdvanceTime(610000);
3137     VerifyOrQuit(sRaValidated);
3138 
3139     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
3140 
3141     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3142     // Send RA from router B advertising an on-link prefix. This
3143     // should cause local on-link prefix to be deprecated.
3144 
3145     SendRouterAdvert(routerAddressB, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
3146 
3147     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3148     // Check that the local on-link prefix is now deprecating.
3149 
3150     sRaValidated = false;
3151     sExpectedPio = kPioDeprecatingLocalOnLink;
3152 
3153     AdvanceTime(10000);
3154     VerifyOrQuit(sRaValidated);
3155     VerifyOrQuit(sExpectedRios.SawAll());
3156     Log("On-link prefix is deprecating, remaining lifetime:%d", sOnLinkLifetime);
3157 
3158     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3159     // Check Network Data to include the default route now due
3160     // the new on-link prefix from router B.
3161 
3162     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ true);
3163     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3164 
3165     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3166     // Send an RA from router A again adding local on-link prefix as RIO.
3167 
3168     Log("Send RA from router A with local on-link as RIO");
3169     SendRouterAdvert(routerAddressA, {Rio(localOnLink, kValidLitime, NetworkData::kRoutePreferenceMedium)});
3170 
3171     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3172     // Check that the local on-link prefix is still being deprecated.
3173 
3174     sRaValidated = false;
3175     AdvanceTime(610000);
3176     VerifyOrQuit(sRaValidated);
3177 
3178     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3179     // Check Network Data remains unchanged.
3180 
3181     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3182 
3183     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3184     // Send an RA from router A removing the previous RIO.
3185 
3186     SendRouterAdvert(routerAddressA, {Rio(localOnLink, 0, NetworkData::kRoutePreferenceMedium)});
3187 
3188     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3189     // Check Network Data remains unchanged.
3190 
3191     AdvanceTime(60000);
3192     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3193 
3194     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3195     // Send RA from router B removing its on-link prefix.
3196 
3197     SendRouterAdvert(routerAddressB, {Pio(onLinkPrefix, kValidLitime, 0)});
3198 
3199     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3200     // Check that the local on-link prefix is once again being advertised.
3201 
3202     sRaValidated = false;
3203     sExpectedPio = kPioAdvertisingLocalOnLink;
3204 
3205     AdvanceTime(10000);
3206     VerifyOrQuit(sRaValidated);
3207 
3208     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3209     // Check Network Data to remain unchanged.
3210 
3211     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3212 
3213     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3214     // Change the extended PAN ID.
3215 
3216     Log("Changing ext PAN ID");
3217 
3218     SuccessOrQuit(otDatasetGetActive(sInstance, &dataset));
3219 
3220     VerifyOrQuit(dataset.mComponents.mIsExtendedPanIdPresent);
3221 
3222     dataset.mExtendedPanId = kExtPanId1;
3223     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
3224     AdvanceTime(10000);
3225 
3226     oldLocalOnLink = localOnLink;
3227     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
3228 
3229     Log("Local on-link prefix is changed to %s from %s", localOnLink.ToString().AsCString(),
3230         oldLocalOnLink.ToString().AsCString());
3231 
3232     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3233     // Check Network Data contains default route due to the
3234     // deprecating on-link prefix from router B.
3235 
3236     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3237 
3238     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3239     // Send an RA from router A again adding the old local on-link prefix
3240     // as RIO.
3241 
3242     SendRouterAdvert(routerAddressA, {Rio(oldLocalOnLink, kValidLitime, NetworkData::kRoutePreferenceMedium)});
3243 
3244     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3245     // Check Network Data remains unchanged.
3246 
3247     AdvanceTime(10000);
3248     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3249 
3250     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3251     // Send an RA from router A removing the previous RIO.
3252 
3253     SendRouterAdvert(routerAddressA, {Rio(localOnLink, 0, NetworkData::kRoutePreferenceMedium)});
3254 
3255     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3256     // Check Network Data remains unchanged.
3257 
3258     AdvanceTime(10000);
3259     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3260 
3261     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3262 
3263     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
3264     VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength());
3265 
3266     Log("End of TestConflictingPrefix");
3267 
3268     FinalizeTest();
3269 }
3270 
3271 #if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
TestSavedOnLinkPrefixes(void)3272 void TestSavedOnLinkPrefixes(void)
3273 {
3274     static const otExtendedPanId kExtPanId1 = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x6, 0x7, 0x08}};
3275 
3276     Ip6::Prefix          localOnLink;
3277     Ip6::Prefix          oldLocalOnLink;
3278     Ip6::Prefix          localOmr;
3279     Ip6::Prefix          onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
3280     Ip6::Address         routerAddressA = AddressFromString("fd00::aaaa");
3281     otOperationalDataset dataset;
3282 
3283     Log("--------------------------------------------------------------------------------------------");
3284     Log("TestSavedOnLinkPrefixes");
3285 
3286     InitTest(/* aEnablBorderRouting */ true);
3287 
3288     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3289     // Check emitted RS and RA messages.
3290 
3291     sRsEmitted   = false;
3292     sRaValidated = false;
3293     sExpectedPio = kPioAdvertisingLocalOnLink;
3294     sExpectedRios.Clear();
3295 
3296     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
3297     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
3298 
3299     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
3300     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
3301 
3302     sExpectedRios.Add(localOmr);
3303 
3304     AdvanceTime(30000);
3305 
3306     VerifyOrQuit(sRsEmitted);
3307     VerifyOrQuit(sRaValidated);
3308     VerifyOrQuit(sExpectedRios.SawAll());
3309 
3310     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3311     // Check Network Data to include the local OMR and ULA prefix.
3312 
3313     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3314     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
3315 
3316     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3317     // Disable the instance and re-enable it.
3318 
3319     Log("Disabling and re-enabling OT Instance");
3320 
3321     testFreeInstance(sInstance);
3322 
3323     InitTest(/* aEnablBorderRouting */ true, /* aAfterReset */ true);
3324 
3325     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
3326 
3327     sExpectedPio = kPioAdvertisingLocalOnLink;
3328 
3329     AdvanceTime(30000);
3330 
3331     VerifyOrQuit(sRsEmitted);
3332     VerifyOrQuit(sRaValidated);
3333     VerifyOrQuit(sExpectedRios.SawAll());
3334 
3335     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3336     // Check Network Data to include the local OMR and ULA prefix.
3337 
3338     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3339     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
3340 
3341     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3342     // Send RA from router A advertising an on-link prefix.
3343 
3344     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
3345 
3346     sRaValidated = false;
3347     sExpectedPio = kPioDeprecatingLocalOnLink;
3348 
3349     AdvanceTime(30000);
3350 
3351     VerifyOrQuit(sRaValidated);
3352     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 0);
3353 
3354     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3355     // Disable the instance and re-enable it.
3356 
3357     Log("Disabling and re-enabling OT Instance");
3358 
3359     testFreeInstance(sInstance);
3360 
3361     InitTest(/* aEnablBorderRouting */ true, /* aAfterReset */ true);
3362 
3363     sExpectedPio = kPioAdvertisingLocalOnLink;
3364 
3365     AdvanceTime(30000);
3366 
3367     VerifyOrQuit(sRsEmitted);
3368     VerifyOrQuit(sRaValidated);
3369     VerifyOrQuit(sExpectedRios.SawAll());
3370 
3371     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3372     // Check Network Data to include the local OMR and ULA prefix.
3373 
3374     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3375     VerifyExternalRouteInNetData(kUlaRoute, kWithAdvPioFlagSet);
3376 
3377     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3378 
3379     Log("Changing ext PAN ID");
3380 
3381     oldLocalOnLink = localOnLink;
3382 
3383     sRaValidated = false;
3384     sExpectedPio = kPioAdvertisingLocalOnLink;
3385 
3386     SuccessOrQuit(otDatasetGetActive(sInstance, &dataset));
3387 
3388     VerifyOrQuit(dataset.mComponents.mIsExtendedPanIdPresent);
3389 
3390     dataset.mExtendedPanId = kExtPanId1;
3391     dataset.mActiveTimestamp.mSeconds++;
3392     SuccessOrQuit(otDatasetSetActive(sInstance, &dataset));
3393 
3394     AdvanceTime(30000);
3395 
3396     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
3397     Log("Local on-link prefix changed to %s from %s", localOnLink.ToString().AsCString(),
3398         oldLocalOnLink.ToString().AsCString());
3399 
3400     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3401     // Disable the instance and re-enable it.
3402 
3403     Log("Disabling and re-enabling OT Instance");
3404 
3405     testFreeInstance(sInstance);
3406 
3407     InitTest(/* aEnablBorderRouting */ false, /* aAfterReset */ true);
3408 
3409     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3410     // Start Routing Manager.
3411 
3412     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
3413 
3414     AdvanceTime(100);
3415 
3416     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3417     // Send RA from router A advertising an on-link prefix.
3418     // This ensures the local on-link prefix is not advertised, but
3419     // it must be deprecated since it was advertised last time and
3420     // saved in `Settings`.
3421 
3422     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
3423 
3424     sRaValidated = false;
3425     sExpectedPio = kPioDeprecatingLocalOnLink;
3426 
3427     AdvanceTime(30000);
3428 
3429     VerifyOrQuit(sRaValidated);
3430     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 1);
3431 
3432     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3433     // Check Network Data to now use default route due to the
3434     // on-link prefix from router A.
3435 
3436     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioFlagSet);
3437 
3438     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3439     // Wait for more than 1800 seconds to let the deprecating
3440     // prefixes expire (keep sending RA from router A).
3441 
3442     for (uint16_t index = 0; index < 185; index++)
3443     {
3444         SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
3445         AdvanceTime(10 * 1000);
3446     }
3447 
3448     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioCleared);
3449 
3450     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3451     // Disable the instance and re-enable it and restart Routing Manager.
3452 
3453     Log("Disabling and re-enabling OT Instance again");
3454 
3455     testFreeInstance(sInstance);
3456     InitTest(/* aEnablBorderRouting */ false, /* aAfterReset */ true);
3457 
3458     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
3459     AdvanceTime(100);
3460 
3461     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3462     // Send RA from router A advertising an on-link prefix.
3463 
3464     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
3465 
3466     sRaValidated = false;
3467     sExpectedPio = kNoPio;
3468 
3469     AdvanceTime(30000);
3470 
3471     VerifyOrQuit(sRaValidated);
3472     VerifyOrQuit(sDeprecatingPrefixes.GetLength() == 0);
3473 
3474     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3475     // Check Network Data still contains the default route.
3476 
3477     VerifyExternalRouteInNetData(kDefaultRoute, kWithAdvPioCleared);
3478 
3479     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3480 
3481     Log("End of TestSavedOnLinkPrefixes");
3482     FinalizeTest();
3483 }
3484 #endif // OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
3485 
3486 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
TestAutoEnableOfSrpServer(void)3487 void TestAutoEnableOfSrpServer(void)
3488 {
3489     Ip6::Prefix  localOnLink;
3490     Ip6::Prefix  localOmr;
3491     Ip6::Address routerAddressA = AddressFromString("fd00::aaaa");
3492     Ip6::Prefix  onLinkPrefix   = PrefixFromString("2000:abba:baba::", 64);
3493     uint16_t     heapAllocations;
3494 
3495     Log("--------------------------------------------------------------------------------------------");
3496     Log("TestAutoEnableOfSrpServer");
3497 
3498     InitTest();
3499 
3500     heapAllocations = sHeapAllocatedPtrs.GetLength();
3501 
3502     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3503     // Check SRP Server state and enable auto-enable mode
3504 
3505     otSrpServerSetAutoEnableMode(sInstance, true);
3506     VerifyOrQuit(otSrpServerIsAutoEnableMode(sInstance));
3507     VerifyOrQuit(otSrpServerGetState(sInstance) == OT_SRP_SERVER_STATE_DISABLED);
3508 
3509     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3510     // Start Routing Manager. Check emitted RS and RA messages.
3511 
3512     sRsEmitted   = false;
3513     sRaValidated = false;
3514     sExpectedPio = kPioAdvertisingLocalOnLink;
3515     sExpectedRios.Clear();
3516 
3517     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
3518 
3519     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
3520     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
3521 
3522     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
3523     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
3524 
3525     sExpectedRios.Add(localOmr);
3526 
3527     AdvanceTime(30000);
3528 
3529     VerifyOrQuit(sRsEmitted);
3530     VerifyOrQuit(sRaValidated);
3531     VerifyOrQuit(sExpectedRios.SawAll());
3532     Log("Received RA was validated");
3533 
3534     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3535     // Validate that SRP server was auto-enabled
3536 
3537     VerifyOrQuit(otSrpServerGetState(sInstance) != OT_SRP_SERVER_STATE_DISABLED);
3538     Log("Srp::Server is enabled");
3539 
3540     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3541     // Signal that infra if state changed and is no longer running.
3542     // This should stop Routing Manager and in turn the SRP server.
3543 
3544     sRaValidated = false;
3545     sExpectedPio = kPioDeprecatingLocalOnLink;
3546 
3547     Log("Signal infra if is not running");
3548     SuccessOrQuit(otPlatInfraIfStateChanged(sInstance, kInfraIfIndex, false));
3549     AdvanceTime(1);
3550 
3551     VerifyOrQuit(sRaValidated);
3552 
3553     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3554     // Check that SRP server is disabled.
3555 
3556     VerifyOrQuit(otSrpServerGetState(sInstance) == OT_SRP_SERVER_STATE_DISABLED);
3557     Log("Srp::Server is disabled");
3558 
3559     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3560     // Signal that infra if state changed and is running again.
3561 
3562     sRsEmitted   = false;
3563     sRaValidated = false;
3564     sExpectedPio = kPioAdvertisingLocalOnLink;
3565     sExpectedRios.Add(localOmr);
3566 
3567     Log("Signal infra if is running");
3568     SuccessOrQuit(otPlatInfraIfStateChanged(sInstance, kInfraIfIndex, true));
3569 
3570     AdvanceTime(30000);
3571 
3572     VerifyOrQuit(sRsEmitted);
3573     VerifyOrQuit(sRaValidated);
3574     VerifyOrQuit(sExpectedRios.SawAll());
3575     Log("Received RA was validated");
3576 
3577     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3578     // Check that SRP server is enabled again.
3579 
3580     VerifyOrQuit(otSrpServerGetState(sInstance) != OT_SRP_SERVER_STATE_DISABLED);
3581     Log("Srp::Server is enabled");
3582 
3583     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3584     // Disable `RoutingManager` explicitly.
3585 
3586     sRaValidated = false;
3587     sExpectedPio = kPioDeprecatingLocalOnLink;
3588 
3589     Log("Disabling RoutingManager");
3590     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
3591     AdvanceTime(1);
3592 
3593     VerifyOrQuit(sRaValidated);
3594 
3595     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3596     // Check that SRP server is also disabled.
3597 
3598     VerifyOrQuit(otSrpServerGetState(sInstance) == OT_SRP_SERVER_STATE_DISABLED);
3599     Log("Srp::Server is disabled");
3600 
3601     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3602     // Disable auto-enable mode on SRP server.
3603 
3604     otSrpServerSetAutoEnableMode(sInstance, false);
3605     VerifyOrQuit(!otSrpServerIsAutoEnableMode(sInstance));
3606     VerifyOrQuit(otSrpServerGetState(sInstance) == OT_SRP_SERVER_STATE_DISABLED);
3607 
3608     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3609     // Re-start Routing Manager. Check emitted RS and RA messages.
3610     // This cycle, router A will send a RA including a PIO.
3611 
3612     sRsEmitted   = false;
3613     sRaValidated = false;
3614     sExpectedPio = kNoPio;
3615     sExpectedRios.Clear();
3616 
3617     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
3618 
3619     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOnLinkPrefix(localOnLink));
3620     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
3621 
3622     Log("Local on-link prefix is %s", localOnLink.ToString().AsCString());
3623     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
3624 
3625     sExpectedRios.Add(localOmr);
3626 
3627     AdvanceTime(2000);
3628 
3629     SendRouterAdvert(routerAddressA, {Pio(onLinkPrefix, kValidLitime, kPreferredLifetime)});
3630 
3631     AdvanceTime(30000);
3632 
3633     VerifyOrQuit(sRsEmitted);
3634     VerifyOrQuit(sRaValidated);
3635     VerifyOrQuit(sExpectedRios.SawAll());
3636     Log("Received RA was validated");
3637 
3638     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3639     // Check that SRP server is still disabled.
3640 
3641     VerifyOrQuit(otSrpServerGetState(sInstance) == OT_SRP_SERVER_STATE_DISABLED);
3642     Log("Srp::Server is disabled");
3643 
3644     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3645     // Enable auto-enable mode on SRP server. Since `RoutingManager`
3646     // is already done with initial policy evaluation, the SRP server
3647     // must be started immediately.
3648 
3649     otSrpServerSetAutoEnableMode(sInstance, true);
3650     VerifyOrQuit(otSrpServerIsAutoEnableMode(sInstance));
3651 
3652     VerifyOrQuit(otSrpServerGetState(sInstance) != OT_SRP_SERVER_STATE_DISABLED);
3653     Log("Srp::Server is enabled");
3654 
3655     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3656     // Disable auto-enable mode on SRP server. It must not impact
3657     // its current state and it should remain enabled.
3658 
3659     otSrpServerSetAutoEnableMode(sInstance, false);
3660     VerifyOrQuit(!otSrpServerIsAutoEnableMode(sInstance));
3661 
3662     AdvanceTime(2000);
3663     VerifyOrQuit(otSrpServerGetState(sInstance) != OT_SRP_SERVER_STATE_DISABLED);
3664     Log("Srp::Server is enabled");
3665 
3666     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3667     // Signal that infra if state changed and is no longer running.
3668     // This should stop Routing Manager.
3669 
3670     sRaValidated = false;
3671 
3672     Log("Signal infra if is not running");
3673     SuccessOrQuit(otPlatInfraIfStateChanged(sInstance, kInfraIfIndex, false));
3674     AdvanceTime(1);
3675 
3676     VerifyOrQuit(sRaValidated);
3677 
3678     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3679     // Re-enable auto-enable mode on SRP server. Since `RoutingManager`
3680     // is stopped (infra if is down), the SRP serer must be stopped
3681     // immediately.
3682 
3683     otSrpServerSetAutoEnableMode(sInstance, true);
3684     VerifyOrQuit(otSrpServerIsAutoEnableMode(sInstance));
3685 
3686     VerifyOrQuit(otSrpServerGetState(sInstance) == OT_SRP_SERVER_STATE_DISABLED);
3687     Log("Srp::Server is disabled");
3688 
3689     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3690 
3691     VerifyOrQuit(sHeapAllocatedPtrs.GetLength() == heapAllocations);
3692 
3693     Log("End of TestAutoEnableOfSrpServer");
3694     FinalizeTest();
3695 }
3696 #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
3697 
3698 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
TestNat64PrefixSelection(void)3699 void TestNat64PrefixSelection(void)
3700 {
3701     Ip6::Prefix                     localNat64;
3702     Ip6::Prefix                     ailNat64 = PrefixFromString("2000:0:0:1:0:0::", 96);
3703     Ip6::Prefix                     localOmr;
3704     Ip6::Prefix                     omrPrefix = PrefixFromString("2000:0000:1111:4444::", 64);
3705     NetworkData::OnMeshPrefixConfig prefixConfig;
3706     uint16_t                        heapAllocations;
3707 
3708     Log("--------------------------------------------------------------------------------------------");
3709     Log("TestNat64PrefixSelection");
3710 
3711     InitTest();
3712 
3713     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3714     // Start Routing Manager. Check local NAT64 prefix generation.
3715 
3716     heapAllocations = sHeapAllocatedPtrs.GetLength();
3717     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(true));
3718     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetNat64Prefix(localNat64));
3719     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
3720 
3721     Log("Local nat64 prefix is %s", localNat64.ToString().AsCString());
3722     Log("Local OMR prefix is %s", localOmr.ToString().AsCString());
3723 
3724     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3725     // Enable Nat64 Prefix Manager. Check local NAT64 prefix in Network Data.
3726 
3727     sInstance->Get<BorderRouter::RoutingManager>().SetNat64PrefixManagerEnabled(true);
3728 
3729     AdvanceTime(20000);
3730 
3731     VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3732     VerifyNat64PrefixInNetData(localNat64);
3733 
3734     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3735     // AIL NAT64 prefix discovered. No infra-derived OMR prefix in Network Data.
3736     // Check local NAT64 prefix in Network Data.
3737 
3738     DiscoverNat64Prefix(ailNat64);
3739 
3740     AdvanceTime(20000);
3741 
3742     VerifyNat64PrefixInNetData(localNat64);
3743 
3744     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3745     // Add a medium preference OMR prefix into Network Data.
3746     // Check AIL NAT64 prefix published in Network Data.
3747 
3748     prefixConfig.Clear();
3749     prefixConfig.mPrefix       = omrPrefix;
3750     prefixConfig.mStable       = true;
3751     prefixConfig.mSlaac        = true;
3752     prefixConfig.mPreferred    = true;
3753     prefixConfig.mOnMesh       = true;
3754     prefixConfig.mDefaultRoute = false;
3755     prefixConfig.mPreference   = NetworkData::kRoutePreferenceMedium;
3756 
3757     SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig));
3758     SuccessOrQuit(otBorderRouterRegister(sInstance));
3759 
3760     AdvanceTime(20000);
3761 
3762     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ false);
3763     VerifyNat64PrefixInNetData(ailNat64);
3764 
3765     //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3766     // AIL NAT64 prefix removed.
3767     // Check local NAT64 prefix in Network Data.
3768 
3769     ailNat64.Clear();
3770     DiscoverNat64Prefix(ailNat64);
3771 
3772     AdvanceTime(20000);
3773 
3774     VerifyOmrPrefixInNetData(omrPrefix, /* aDefaultRoute */ false);
3775     VerifyNat64PrefixInNetData(localNat64);
3776 
3777     SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().SetEnabled(false));
3778     VerifyOrQuit(sHeapAllocatedPtrs.GetLength() == heapAllocations);
3779 
3780     Log("End of TestNat64PrefixSelection");
3781     FinalizeTest();
3782 }
3783 #endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
3784 
3785 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
VerifyPdOmrPrefix(const Ip6::Prefix & aPrefix)3786 void VerifyPdOmrPrefix(const Ip6::Prefix &aPrefix)
3787 {
3788     otBorderRoutingPrefixTableEntry platformPrefixInfo;
3789 
3790     VerifyOrQuit(otBorderRoutingGetPdOmrPrefix(sInstance, &platformPrefixInfo) == OT_ERROR_NONE);
3791     VerifyOrQuit(AsCoreType(&platformPrefixInfo.mPrefix) == aPrefix);
3792 }
3793 
VerifyNoPdOmrPrefix()3794 void VerifyNoPdOmrPrefix()
3795 {
3796     otBorderRoutingPrefixTableEntry platformPrefixInfo;
3797 
3798     VerifyOrQuit(otBorderRoutingGetPdOmrPrefix(sInstance, &platformPrefixInfo) == OT_ERROR_NOT_FOUND);
3799 }
3800 
TestBorderRoutingProcessPlatfromGeneratedNd(void)3801 void TestBorderRoutingProcessPlatfromGeneratedNd(void)
3802 {
3803     Ip6::Prefix localOmr;
3804     uint16_t    heapAllocations;
3805 
3806     Log("--------------------------------------------------------------------------------------------");
3807     Log("TestBorderRoutingProcessPlatfromGeneratedNd");
3808 
3809     InitTest(/* aEnableBorderRouting */ true);
3810     heapAllocations = sHeapAllocatedPtrs.GetLength();
3811 
3812     otBorderRoutingDhcp6PdSetEnabled(sInstance, true);
3813 
3814     {
3815         SuccessOrQuit(sInstance->Get<BorderRouter::RoutingManager>().GetOmrPrefix(localOmr));
3816     }
3817 
3818     // 0. Reject invalid RA.
3819     Log("0. Invalid RA message.");
3820     {
3821         {
3822             const uint8_t testInvalidRaMessage[] = {
3823                 0x86, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3824             };
3825 
3826             otPlatBorderRoutingProcessIcmp6Ra(sInstance, testInvalidRaMessage, sizeof(testInvalidRaMessage));
3827             VerifyNoPdOmrPrefix();
3828         }
3829 
3830         {
3831             const uint8_t testInvalidRaMessage[] = {
3832                 0x87, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3833             };
3834 
3835             otPlatBorderRoutingProcessIcmp6Ra(sInstance, testInvalidRaMessage, sizeof(testInvalidRaMessage));
3836             VerifyNoPdOmrPrefix();
3837         }
3838 
3839         {
3840             const uint8_t testRaMessageWithInvalidPrefix[] = {
3841                 0x86, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3842                 0x03, 0x04, 0x41, 0xc0, 0x00, 0x00, 0x10, 0xe1, 0x00, 0x00, 0x04, 0xd2, 0x00, 0x00, 0x00, 0x00,
3843                 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3844             };
3845 
3846             otPlatBorderRoutingProcessIcmp6Ra(sInstance, testRaMessageWithInvalidPrefix,
3847                                               sizeof(testRaMessageWithInvalidPrefix));
3848             VerifyNoPdOmrPrefix();
3849         }
3850     }
3851 
3852     // 1. Publish a prefix, and wait until it expired.
3853     Log("1. Simple RA message.");
3854     {
3855         Ip6::Prefix raPrefix = PrefixFromString("2001:db8:dead:beef::", 64);
3856 
3857         SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)});
3858 
3859         sExpectedRios.Add(raPrefix);
3860         AdvanceTime(10000);
3861 
3862         VerifyPdOmrPrefix(raPrefix);
3863         VerifyOrQuit(sExpectedRios.SawAll());
3864         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3865 
3866         AdvanceTime(1500000);
3867         sExpectedRios.Clear();
3868         VerifyPdOmrPrefix(raPrefix);
3869         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3870 
3871         AdvanceTime(400000);
3872         // Deprecated prefixes will be removed.
3873         VerifyNoPdOmrPrefix();
3874         VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3875     }
3876 
3877     // 1.1. Publish a prefix, and wait until it expired.
3878     //      Multiple prefixes are advertised, only the smallest one will be used.
3879     Log("1.1. RA message with multiple prefixes.");
3880     {
3881         Ip6::Prefix raPrefix    = PrefixFromString("2001:db8:dead:beef::", 64);
3882         Ip6::Prefix ulaRaPrefix = PrefixFromString("fd01:db8:deaf:beef::", 64);
3883 
3884         SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(ulaRaPrefix, kValidLitime * 2, kPreferredLifetime * 2),
3885                                                        Pio(raPrefix, kValidLitime, kPreferredLifetime)});
3886 
3887         sExpectedRios.Add(raPrefix);
3888         AdvanceTime(10000);
3889 
3890         VerifyPdOmrPrefix(raPrefix);
3891         VerifyOrQuit(sExpectedRios.SawAll());
3892         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3893 
3894         AdvanceTime(1500000);
3895         sExpectedRios.Clear();
3896         VerifyPdOmrPrefix(raPrefix);
3897         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3898 
3899         AdvanceTime(400000);
3900         // Deprecated prefixes will be removed.
3901         VerifyNoPdOmrPrefix();
3902         VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3903     }
3904 
3905     // 2. Publish a prefix, and renew it before it expired.
3906     Log("2. Renew prefix lifetime.");
3907     {
3908         Ip6::Prefix raPrefix = PrefixFromString("2001:db8:1:2::", 64);
3909 
3910         SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)});
3911 
3912         sExpectedRios.Add(raPrefix);
3913         AdvanceTime(10000);
3914 
3915         VerifyPdOmrPrefix(raPrefix);
3916         VerifyOrQuit(sExpectedRios.SawAll());
3917         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3918 
3919         AdvanceTime(1500000);
3920         sExpectedRios.Clear();
3921         VerifyPdOmrPrefix(raPrefix);
3922         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3923 
3924         SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)});
3925 
3926         AdvanceTime(400000);
3927         VerifyPdOmrPrefix(raPrefix);
3928         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3929 
3930         AdvanceTime(1500000);
3931         VerifyNoPdOmrPrefix();
3932         VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3933     }
3934 
3935     // 3. Publish a prefix, and publish another prefix to replace it (with goodbye ra).
3936     Log("3. Update prefix.");
3937     {
3938         Ip6::Prefix raPrefix    = PrefixFromString("2001:db8:1:2::", 64);
3939         Ip6::Prefix newRaPrefix = PrefixFromString("2001:db8:3:4::", 64);
3940 
3941         SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(raPrefix, kValidLitime, kPreferredLifetime)});
3942 
3943         sExpectedRios.Add(raPrefix);
3944         sExpectedRios.Clear();
3945         AdvanceTime(10000);
3946 
3947         VerifyPdOmrPrefix(raPrefix);
3948         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3949 
3950         AdvanceTime(1000000);
3951         VerifyPdOmrPrefix(raPrefix);
3952 
3953         SendRouterAdvertToBorderRoutingProcessIcmp6Ra(
3954             {Pio(raPrefix, 0, 0), Pio(newRaPrefix, kValidLitime, kPreferredLifetime)});
3955         sExpectedRios.Add(newRaPrefix);
3956 
3957         AdvanceTime(1000000);
3958         VerifyOrQuit(sExpectedRios.SawAll());
3959         VerifyPdOmrPrefix(newRaPrefix);
3960 
3961         AdvanceTime(1000000);
3962         VerifyNoPdOmrPrefix();
3963         VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3964     }
3965 
3966     // 4. Short prefix will be extended to /64.
3967     Log("Short prefix");
3968     {
3969         // The prefix will be padded to a /64 prefix.
3970         Ip6::Prefix raPrefix = PrefixFromString("2001:db8:cafe:0::", 64);
3971         Ip6::Prefix realRaPrefix;
3972 
3973         realRaPrefix.Set(raPrefix.GetBytes(), 48);
3974         SendRouterAdvertToBorderRoutingProcessIcmp6Ra({Pio(realRaPrefix, kValidLitime, kPreferredLifetime)});
3975 
3976         sExpectedRios.Add(raPrefix);
3977         AdvanceTime(10000);
3978 
3979         VerifyPdOmrPrefix(raPrefix);
3980         VerifyOrQuit(sExpectedRios.SawAll());
3981         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3982 
3983         AdvanceTime(1500000);
3984         sExpectedRios.Clear();
3985         VerifyPdOmrPrefix(raPrefix);
3986         VerifyOmrPrefixInNetData(raPrefix, /* aDefaultRoute */ false);
3987 
3988         AdvanceTime(400000);
3989         // Deprecated prefixes will be removed.
3990         VerifyNoPdOmrPrefix();
3991         VerifyOmrPrefixInNetData(localOmr, /* aDefaultRoute */ false);
3992     }
3993 
3994     SuccessOrQuit(otBorderRoutingSetEnabled(sInstance, false));
3995     VerifyOrQuit(sHeapAllocatedPtrs.GetLength() <= heapAllocations);
3996 
3997     Log("End of TestBorderRoutingProcessPlatfromGeneratedNd");
3998 
3999     FinalizeTest();
4000 }
4001 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
4002 
4003 #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
4004 
4005 } // namespace ot
4006 
main(void)4007 int main(void)
4008 {
4009 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
4010     ot::TestSamePrefixesFromMultipleRouters();
4011     ot::TestOmrSelection();
4012     ot::TestDefaultRoute();
4013     ot::TestAdvNonUlaRoute();
4014     ot::TestLocalOnLinkPrefixDeprecation();
4015 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
4016     ot::TestDomainPrefixAsOmr();
4017 #endif
4018     ot::TestExtPanIdChange();
4019     ot::TestConflictingPrefix();
4020     ot::TestRouterNsProbe();
4021     ot::TestLearningAndCopyingOfFlags();
4022     ot::TestLearnRaHeader();
4023 #if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
4024     ot::TestSavedOnLinkPrefixes();
4025 #endif
4026 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
4027     ot::TestAutoEnableOfSrpServer();
4028 #endif
4029 #if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
4030     ot::TestNat64PrefixSelection();
4031 #endif
4032 #if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
4033     ot::TestBorderRoutingProcessPlatfromGeneratedNd();
4034 #endif
4035 
4036     printf("All tests passed\n");
4037 #else
4038     printf("BORDER_ROUTING feature is not enabled\n");
4039 #endif
4040 
4041     return 0;
4042 }
4043