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