| /* |
| * Copyright (c) 2025, The OpenThread Authors. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holder nor the |
| * names of its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <openthread/config.h> |
| |
| #include "test_platform.h" |
| #include "test_util.hpp" |
| |
| #include <openthread/dataset_ftd.h> |
| #include <openthread/thread.h> |
| #include <openthread/platform/border_routing.h> |
| #include <openthread/platform/infra_if.h> |
| |
| #include "border_router/dhcp6_pd_client.hpp" |
| #include "common/arg_macros.hpp" |
| #include "common/array.hpp" |
| #include "common/num_utils.hpp" |
| #include "instance/instance.hpp" |
| |
| namespace ot { |
| |
| #if OT_CONFIG_DHCP6_PD_CLIENT_ENABLE |
| |
| // Logs a message and adds current time (sNow) as "<hours>:<min>:<secs>.<msec>" |
| #define Log(...) \ |
| printf("%02u:%02u:%02u.%03u " OT_FIRST_ARG(__VA_ARGS__) "\n", (sNow / 3600000), (sNow / 60000) % 60, \ |
| (sNow / 1000) % 60, sNow % 1000 OT_REST_ARGS(__VA_ARGS__)) |
| |
| static constexpr uint32_t kInfraIfIndex = 1; |
| |
| static Instance *sInstance; |
| |
| static uint32_t sNow = 0; |
| static uint32_t sAlarmTime; |
| static bool sAlarmOn = false; |
| |
| //---------------------------------------------------------------------------------------------------------------------- |
| // Function prototypes |
| |
| void ProcessTasklets(void); |
| void AdvanceTime(uint32_t aDuration); |
| void AdvanceNowTo(uint32_t aNewNow); |
| |
| extern "C" { |
| |
| #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED |
| #if OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE |
| void otPlatLogOutput(otInstance *, otLogLevel, const char *aLogLine) { printf(" %s\n", aLogLine); } |
| #else |
| void otPlatLog(otLogLevel, otLogRegion, const char *aFormat, ...) |
| { |
| va_list args; |
| |
| printf(" "); |
| va_start(args, aFormat); |
| vprintf(aFormat, args); |
| va_end(args); |
| printf("\n"); |
| } |
| #endif |
| #endif |
| |
| //---------------------------------------------------------------------------------------------------------------------- |
| // otPlatAlarams |
| |
| void otPlatAlarmMilliStop(otInstance *) { sAlarmOn = false; } |
| |
| void otPlatAlarmMilliStartAt(otInstance *, uint32_t aT0, uint32_t aDt) |
| { |
| sAlarmOn = true; |
| sAlarmTime = aT0 + aDt; |
| } |
| |
| uint32_t otPlatAlarmMilliGetNow(void) { return sNow; } |
| |
| //---------------------------------------------------------------------------------------------------------------------- |
| // Heap |
| |
| Array<void *, 500> sHeapAllocatedPtrs; |
| |
| #if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE |
| |
| void *otPlatCAlloc(size_t aNum, size_t aSize) |
| { |
| void *ptr = calloc(aNum, aSize); |
| |
| SuccessOrQuit(sHeapAllocatedPtrs.PushBack(ptr)); |
| |
| return ptr; |
| } |
| |
| void otPlatFree(void *aPtr) |
| { |
| if (aPtr != nullptr) |
| { |
| void **entry = sHeapAllocatedPtrs.Find(aPtr); |
| |
| VerifyOrQuit(entry != nullptr, "A heap allocated item is freed twice"); |
| sHeapAllocatedPtrs.Remove(*entry); |
| } |
| |
| free(aPtr); |
| } |
| |
| #endif |
| |
| } // extern "C" |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| // Dhcp6Msg |
| |
| struct Dhcp6Msg : public Clearable<Dhcp6Msg> |
| { |
| static constexpr uint16_t kMaxIaPds = 2; |
| static constexpr uint16_t kMaxIaPrefixes = 3; |
| static constexpr uint16_t kMaxReqOptions = 3; |
| static constexpr uint16_t kInfoStringSize = 100; |
| |
| typedef String<kInfoStringSize> InfoString; |
| |
| struct IaPrefix : public Clearable<IaPrefix> |
| { |
| Ip6::Prefix mPrefix; |
| uint32_t mPreferredLifetime; |
| uint32_t mValidLifetime; |
| }; |
| |
| using IaPrefixArray = Array<IaPrefix, kMaxIaPrefixes>; |
| |
| struct IaPd : Clearable<IaPd> |
| { |
| bool Matches(uint32_t aIaid) const { return mIaid == aIaid; } |
| |
| uint32_t mIaid; |
| uint32_t mT1; |
| uint32_t mT2; |
| bool mHasStatus; |
| uint16_t mStatusCode; |
| IaPrefixArray mIaPrefixes; |
| }; |
| |
| using IaPdArray = Array<IaPd, kMaxIaPds>; |
| |
| struct Duid |
| { |
| InfoString ToString(void) const |
| { |
| InfoString string; |
| |
| string.AppendHexBytes(mShared.mBytes, mLength); |
| return string; |
| } |
| |
| union |
| { |
| uint8_t mBytes[Dhcp6::Duid::kMaxSize]; |
| Dhcp6::Eui64Duid mEui64; |
| } mShared; |
| uint16_t mLength; |
| }; |
| |
| using ReqOptionArray = Array<uint16_t, kMaxReqOptions>; |
| |
| void LogMsg(const char *aAction) const; |
| void ParseFrom(const Message &aMessage); |
| void PrepareMessage(Message &aMessage); |
| |
| uint8_t mMsgType; |
| Dhcp6::TransactionId mTransactionId; |
| bool mHasStatus : 1; |
| bool mHasElapsedTime : 1; |
| bool mHasClientId : 1; |
| bool mHasServerId : 1; |
| bool mHasOptionRequest : 1; |
| bool mHasPreference : 1; |
| bool mHasSolMaxRt : 1; |
| uint16_t mStatusCode; |
| uint16_t mElapsedTime; |
| Duid mClientDuid; |
| Duid mServerDuid; |
| ReqOptionArray mRequestedOptions; |
| uint8_t mPreference; |
| uint16_t mSolMaxRt; |
| IaPdArray mIaPds; |
| }; |
| |
| static const char *Dhcp6MsgTypeToString(uint8_t aMsgType) |
| { |
| const char *str = "Unknown"; |
| |
| switch (aMsgType) |
| { |
| case Dhcp6::kMsgTypeSolicit: |
| str = "Solicit"; |
| break; |
| case Dhcp6::kMsgTypeAdvertise: |
| str = "Advertise"; |
| break; |
| case Dhcp6::kMsgTypeRequest: |
| str = "Request"; |
| break; |
| case Dhcp6::kMsgTypeRenew: |
| str = "Renew"; |
| break; |
| case Dhcp6::kMsgTypeRebind: |
| str = "Rebind"; |
| break; |
| case Dhcp6::kMsgTypeReply: |
| str = "Reply"; |
| break; |
| case Dhcp6::kMsgTypeRelease: |
| str = "Release"; |
| break; |
| case Dhcp6::kMsgTypeReconfigure: |
| str = "Reconfigure"; |
| break; |
| } |
| |
| return str; |
| } |
| |
| void Dhcp6Msg::LogMsg(const char *aAction) const |
| { |
| const uint8_t *txnId = reinterpret_cast<const uint8_t *>(&mTransactionId); |
| |
| Log("%s %s message", aAction, Dhcp6MsgTypeToString(mMsgType)); |
| |
| Log(" %-13s : %02x%02x%02x", "TransactionId", txnId[0], txnId[1], txnId[2]); |
| |
| if (mHasStatus) |
| { |
| Log(" %-13s : %u", "StatusCode", mStatusCode); |
| } |
| |
| if (mHasElapsedTime) |
| { |
| Log(" %-13s : %u", "ElapsedTime", mElapsedTime); |
| } |
| |
| if (mHasClientId) |
| { |
| Log(" %-13s : %s", "ClientId", mClientDuid.ToString().AsCString()); |
| } |
| |
| if (mHasServerId) |
| { |
| Log(" %-13s : %s", "ServerId", mServerDuid.ToString().AsCString()); |
| } |
| |
| if (mHasOptionRequest) |
| { |
| InfoString string; |
| |
| string.Append("[ "); |
| for (uint16_t optionCode : mRequestedOptions) |
| { |
| string.Append("%u ", optionCode); |
| } |
| string.Append("]"); |
| Log(" %-13s : %s", "ReqOptions", string.AsCString()); |
| } |
| |
| if (mHasPreference) |
| { |
| Log(" %-13s : %u", "Preference", mPreference); |
| } |
| |
| if (mHasSolMaxRt) |
| { |
| Log(" %-13s : %lu", "SolMaxRt", ToUlong(mSolMaxRt)); |
| } |
| |
| for (const IaPd &iaPd : mIaPds) |
| { |
| Log(" %-13s : Iaid:%lu, T1:%lu, T2:%lu", "IaPd", ToUlong(iaPd.mIaid), ToUlong(iaPd.mT1), ToUlong(iaPd.mT2)); |
| |
| if (iaPd.mHasStatus) |
| { |
| Log(" %-11s : %u", "StatusCode", iaPd.mStatusCode); |
| } |
| |
| for (const IaPrefix &iaPrefix : iaPd.mIaPrefixes) |
| { |
| Log(" %-11s : %s, preferred:%lu, valid:%lu", "Prefix", iaPrefix.mPrefix.ToString().AsCString(), |
| ToUlong(iaPrefix.mPreferredLifetime), ToUlong(iaPrefix.mValidLifetime)); |
| } |
| } |
| } |
| |
| void Dhcp6Msg::ParseFrom(const Message &aMessage) |
| { |
| OffsetRange offsetRange; |
| OffsetRange optionOffsetRange; |
| OffsetRange subOptionOffsetRange; |
| Dhcp6::Header header; |
| IaPd *iaPd; |
| IaPrefix *iaPrefix; |
| union |
| { |
| Dhcp6::Option option; |
| Dhcp6::StatusCodeOption statusOption; |
| Dhcp6::ElapsedTimeOption elapsedTimeOption; |
| Dhcp6::PreferenceOption preferenceOption; |
| Dhcp6::SolMaxRtOption solMaxRtOption; |
| Dhcp6::IaPdOption iaPdOption; |
| Dhcp6::IaPrefixOption iaPrefixOption; |
| }; |
| |
| Clear(); |
| offsetRange.InitFromMessageFullLength(aMessage); |
| |
| SuccessOrQuit(aMessage.ReadAndAdvance(offsetRange, header)); |
| mMsgType = header.GetMsgType(); |
| mTransactionId = header.GetTransactionId(); |
| |
| while (!offsetRange.IsEmpty()) |
| { |
| SuccessOrQuit(aMessage.Read(offsetRange, option)); |
| VerifyOrQuit(offsetRange.Contains(option.GetSize())); |
| |
| optionOffsetRange = offsetRange; |
| optionOffsetRange.ShrinkLength(static_cast<uint16_t>(option.GetSize())); |
| offsetRange.AdvanceOffset(option.GetSize()); |
| |
| switch (option.GetCode()) |
| { |
| case Dhcp6::Option::kStatusCode: |
| VerifyOrQuit(!mHasStatus); |
| mHasStatus = true; |
| SuccessOrQuit(aMessage.Read(optionOffsetRange, statusOption)); |
| mStatusCode = statusOption.GetStatusCode(); |
| break; |
| |
| case Dhcp6::Option::kElapsedTime: |
| VerifyOrQuit(!mHasElapsedTime); |
| mHasElapsedTime = true; |
| SuccessOrQuit(aMessage.Read(optionOffsetRange, elapsedTimeOption)); |
| mElapsedTime = elapsedTimeOption.GetElapsedTime(); |
| break; |
| |
| case Dhcp6::Option::kClientId: |
| VerifyOrQuit(!mHasClientId); |
| mHasClientId = true; |
| optionOffsetRange.AdvanceOffset(sizeof(Dhcp6::Option)); |
| VerifyOrQuit(optionOffsetRange.GetLength() >= Dhcp6::Duid::kMinSize); |
| VerifyOrQuit(optionOffsetRange.GetLength() <= Dhcp6::Duid::kMaxSize); |
| mClientDuid.mLength = optionOffsetRange.GetLength(); |
| aMessage.ReadBytes(optionOffsetRange, mClientDuid.mShared.mBytes); |
| break; |
| |
| case Dhcp6::Option::kServerId: |
| VerifyOrQuit(!mHasServerId); |
| mHasServerId = true; |
| optionOffsetRange.AdvanceOffset(sizeof(Dhcp6::Option)); |
| VerifyOrQuit(optionOffsetRange.GetLength() >= Dhcp6::Duid::kMinSize); |
| VerifyOrQuit(optionOffsetRange.GetLength() <= Dhcp6::Duid::kMaxSize); |
| mServerDuid.mLength = optionOffsetRange.GetLength(); |
| aMessage.ReadBytes(optionOffsetRange, mServerDuid.mShared.mBytes); |
| break; |
| |
| case Dhcp6::Option::kOptionRequest: |
| VerifyOrQuit(!mHasOptionRequest); |
| mHasOptionRequest = true; |
| optionOffsetRange.AdvanceOffset(sizeof(Dhcp6::Option)); |
| VerifyOrQuit(optionOffsetRange.GetLength() > 0); |
| |
| while (!optionOffsetRange.IsEmpty()) |
| { |
| uint16_t reqOption; |
| |
| SuccessOrQuit(aMessage.Read(optionOffsetRange, reqOption)); |
| reqOption = BigEndian::HostSwap16(reqOption); |
| SuccessOrQuit(mRequestedOptions.PushBack(reqOption)); |
| optionOffsetRange.AdvanceOffset(sizeof(uint16_t)); |
| } |
| |
| break; |
| |
| case Dhcp6::Option::kPreference: |
| VerifyOrQuit(!mHasPreference); |
| mHasPreference = true; |
| SuccessOrQuit(aMessage.Read(optionOffsetRange, preferenceOption)); |
| mPreference = preferenceOption.GetPreference(); |
| break; |
| |
| case Dhcp6::Option::kSolMaxRt: |
| VerifyOrQuit(!mHasSolMaxRt); |
| mHasSolMaxRt = true; |
| SuccessOrQuit(aMessage.Read(optionOffsetRange, solMaxRtOption)); |
| mSolMaxRt = solMaxRtOption.GetSolMaxRt(); |
| break; |
| |
| case Dhcp6::Option::kIaPd: |
| SuccessOrQuit(aMessage.ReadAndAdvance(optionOffsetRange, iaPdOption)); |
| VerifyOrQuit(!mIaPds.ContainsMatching(iaPdOption.GetIaid())); |
| |
| iaPd = mIaPds.PushBack(); |
| VerifyOrQuit(iaPd != nullptr); |
| iaPd->Clear(); |
| iaPd->mIaid = iaPdOption.GetIaid(); |
| iaPd->mT1 = iaPdOption.GetT1(); |
| iaPd->mT2 = iaPdOption.GetT2(); |
| |
| while (!optionOffsetRange.IsEmpty()) |
| { |
| SuccessOrQuit(aMessage.Read(optionOffsetRange, option)); |
| VerifyOrQuit(optionOffsetRange.Contains(option.GetSize())); |
| |
| subOptionOffsetRange = optionOffsetRange; |
| subOptionOffsetRange.ShrinkLength(static_cast<uint16_t>(option.GetSize())); |
| |
| optionOffsetRange.AdvanceOffset(option.GetSize()); |
| |
| switch (option.GetCode()) |
| { |
| case Dhcp6::Option::kStatusCode: |
| VerifyOrQuit(!iaPd->mHasStatus); |
| iaPd->mHasStatus = true; |
| SuccessOrQuit(aMessage.Read(subOptionOffsetRange, statusOption)); |
| iaPd->mStatusCode = statusOption.GetStatusCode(); |
| break; |
| |
| case Dhcp6::Option::kIaPrefix: |
| SuccessOrQuit(aMessage.Read(subOptionOffsetRange, iaPrefixOption)); |
| iaPrefix = iaPd->mIaPrefixes.PushBack(); |
| VerifyOrQuit(iaPrefix != nullptr); |
| iaPrefix->Clear(); |
| iaPrefixOption.GetPrefix(iaPrefix->mPrefix); |
| iaPrefix->mPreferredLifetime = iaPrefixOption.GetPreferredLifetime(); |
| iaPrefix->mValidLifetime = iaPrefixOption.GetValidLifetime(); |
| break; |
| |
| default: |
| // Unexpected sub-option |
| VerifyOrQuit(false); |
| break; |
| } |
| } |
| break; |
| |
| default: |
| // Unexpected option |
| VerifyOrQuit(false); |
| break; |
| } |
| } |
| } |
| |
| void Dhcp6Msg::PrepareMessage(Message &aMessage) |
| { |
| Dhcp6::Header header; |
| union |
| { |
| Dhcp6::Option option; |
| Dhcp6::StatusCodeOption statusOption; |
| Dhcp6::ElapsedTimeOption elapsedTimeOption; |
| Dhcp6::PreferenceOption preferenceOption; |
| Dhcp6::SolMaxRtOption solMaxRtOption; |
| Dhcp6::IaPdOption iaPdOption; |
| Dhcp6::IaPrefixOption iaPrefixOption; |
| }; |
| |
| header.SetMsgType(static_cast<Dhcp6::MsgType>(mMsgType)); |
| header.SetTransactionId(mTransactionId); |
| SuccessOrQuit(aMessage.Append(header)); |
| |
| if (mHasStatus) |
| { |
| statusOption.Init(); |
| statusOption.SetStatusCode(static_cast<Dhcp6::StatusCodeOption::Status>(mStatusCode)); |
| SuccessOrQuit(aMessage.Append(statusOption)); |
| } |
| |
| if (mHasElapsedTime) |
| { |
| elapsedTimeOption.Init(); |
| elapsedTimeOption.SetElapsedTime(mElapsedTime); |
| SuccessOrQuit(aMessage.Append(elapsedTimeOption)); |
| } |
| |
| if (mHasClientId) |
| { |
| SuccessOrQuit(Dhcp6::Option::AppendOption(aMessage, Dhcp6::Option::kClientId, mClientDuid.mShared.mBytes, |
| mClientDuid.mLength)); |
| } |
| |
| if (mHasServerId) |
| { |
| SuccessOrQuit(Dhcp6::Option::AppendOption(aMessage, Dhcp6::Option::kServerId, mServerDuid.mShared.mBytes, |
| mServerDuid.mLength)); |
| } |
| |
| if (mHasOptionRequest) |
| { |
| option.SetCode(Dhcp6::Option::kOptionRequest); |
| option.SetLength(mRequestedOptions.GetLength() * sizeof(uint16_t)); |
| SuccessOrQuit(aMessage.Append(option)); |
| |
| for (uint16_t reqOption : mRequestedOptions) |
| { |
| uint16_t swapedOption = BigEndian::HostSwap16(reqOption); |
| |
| SuccessOrQuit(aMessage.Append(swapedOption)); |
| } |
| } |
| |
| if (mHasPreference) |
| { |
| preferenceOption.Init(); |
| preferenceOption.SetPreference(mPreference); |
| SuccessOrQuit(aMessage.Append(preferenceOption)); |
| } |
| |
| if (mHasSolMaxRt) |
| { |
| solMaxRtOption.Init(); |
| solMaxRtOption.SetSolMaxRt(mSolMaxRt); |
| SuccessOrQuit(aMessage.Append(solMaxRtOption)); |
| } |
| |
| for (const IaPd &iaPd : mIaPds) |
| { |
| uint16_t length; |
| |
| length = sizeof(Dhcp6::IaPdOption) - sizeof(Dhcp6::Option); |
| |
| if (mHasStatus) |
| { |
| length += sizeof(Dhcp6::StatusCodeOption); |
| } |
| |
| length += sizeof(Dhcp6::IaPrefixOption) * iaPd.mIaPrefixes.GetLength(); |
| |
| iaPdOption.Init(); |
| iaPdOption.SetLength(length); |
| iaPdOption.SetIaid(iaPd.mIaid); |
| iaPdOption.SetT1(iaPd.mT1); |
| iaPdOption.SetT2(iaPd.mT2); |
| SuccessOrQuit(aMessage.Append(iaPdOption)); |
| |
| if (mHasStatus) |
| { |
| statusOption.Init(); |
| statusOption.SetStatusCode(static_cast<Dhcp6::StatusCodeOption::Status>(iaPd.mStatusCode)); |
| SuccessOrQuit(aMessage.Append(statusOption)); |
| } |
| |
| for (const IaPrefix &iaPrefix : iaPd.mIaPrefixes) |
| { |
| iaPrefixOption.Init(); |
| iaPrefixOption.SetPreferredLifetime(iaPrefix.mPreferredLifetime); |
| iaPrefixOption.SetValidLifetime(iaPrefix.mValidLifetime); |
| iaPrefixOption.SetPrefix(iaPrefix.mPrefix); |
| SuccessOrQuit(aMessage.Append(iaPrefixOption)); |
| } |
| } |
| } |
| |
| //---------------------------------------------------------------------------------------------------------------------- |
| // Dhcp6RxMsg |
| |
| static const uint32_t kExpectedIaid = 0; |
| static const uint8_t kExpectedPrefixLength = 64; |
| |
| static const uint16_t kMaxDhcp6RxMsgs = 32; |
| |
| class Dhcp6RxMsg : public Dhcp6Msg |
| { |
| public: |
| void ValidateAsSolicit(void) const; |
| |
| void ValidateAsRequest(const Ip6::Prefix &aPrefix, const Mac::ExtAddress &aServerMacAddr) const; |
| |
| void ValidateAsRenew(const Ip6::Prefix &aPrefix, const Mac::ExtAddress &aServerMacAddr) const; |
| |
| void ValidateAsRebind(const Ip6::Prefix &aPrefix) const; |
| |
| void ValidateAsRelease(const Ip6::Prefix &aPrefix, const Mac::ExtAddress &aServerMacAddr) const; |
| |
| uint32_t mRxTime; |
| Ip6::Address mDstAddr; |
| |
| private: |
| void Validate(Dhcp6::MsgType aMsgType, |
| const Ip6::Prefix &aPrefix, |
| const Mac::ExtAddress *aServerMacAddr = nullptr) const; |
| }; |
| |
| Ip6::Prefix PrefixFromString(const char *aString, uint8_t aPrefixLength) |
| { |
| Ip6::Prefix prefix; |
| |
| SuccessOrQuit(AsCoreType(&prefix.mPrefix).FromString(aString)); |
| prefix.mLength = aPrefixLength; |
| |
| return prefix; |
| } |
| |
| Ip6::Address AddressFromString(const char *aString) |
| { |
| Ip6::Address address; |
| |
| SuccessOrQuit(address.FromString(aString)); |
| |
| return address; |
| } |
| |
| void Dhcp6RxMsg::ValidateAsSolicit(void) const |
| { |
| Ip6::Prefix prefix; |
| |
| VerifyOrQuit(mMsgType == Dhcp6::kMsgTypeSolicit); |
| VerifyOrQuit(mDstAddr == AddressFromString("ff02::1:2")); |
| |
| prefix.Clear(); |
| prefix.SetLength(kExpectedPrefixLength); |
| |
| Validate(Dhcp6::kMsgTypeSolicit, prefix); |
| } |
| |
| void Dhcp6RxMsg::ValidateAsRequest(const Ip6::Prefix &aPrefix, const Mac::ExtAddress &aServerMacAddr) const |
| { |
| Validate(Dhcp6::kMsgTypeRequest, aPrefix, &aServerMacAddr); |
| } |
| |
| void Dhcp6RxMsg::ValidateAsRenew(const Ip6::Prefix &aPrefix, const Mac::ExtAddress &aServerMacAddr) const |
| { |
| Validate(Dhcp6::kMsgTypeRenew, aPrefix, &aServerMacAddr); |
| } |
| |
| void Dhcp6RxMsg::ValidateAsRebind(const Ip6::Prefix &aPrefix) const { Validate(Dhcp6::kMsgTypeRebind, aPrefix); } |
| |
| void Dhcp6RxMsg::ValidateAsRelease(const Ip6::Prefix &aPrefix, const Mac::ExtAddress &aServerMacAddr) const |
| { |
| Validate(Dhcp6::kMsgTypeRelease, aPrefix, &aServerMacAddr); |
| } |
| |
| void Dhcp6RxMsg::Validate(Dhcp6::MsgType aMsgType, |
| const Ip6::Prefix &aPrefix, |
| const Mac::ExtAddress *aServerMacAddr) const |
| { |
| VerifyOrQuit(mMsgType == aMsgType); |
| |
| VerifyOrQuit(mDstAddr == AddressFromString("ff02::1:2")); |
| |
| VerifyOrQuit(!mHasStatus); |
| VerifyOrQuit(!mHasPreference); |
| VerifyOrQuit(!mHasSolMaxRt); |
| |
| VerifyOrQuit(mHasElapsedTime); |
| |
| VerifyOrQuit(mHasOptionRequest); |
| VerifyOrQuit(mRequestedOptions.GetLength() == 1); |
| VerifyOrQuit(mRequestedOptions[0] == Dhcp6::Option::kSolMaxRt); |
| |
| VerifyOrQuit(mHasClientId); |
| VerifyOrQuit(mClientDuid.mShared.mEui64.IsValid()); |
| VerifyOrQuit(mClientDuid.mShared.mEui64.GetLinkLayerAddress() == sInstance->Get<Mac::Mac>().GetExtAddress()); |
| |
| if (aServerMacAddr != nullptr) |
| { |
| VerifyOrQuit(mHasServerId); |
| VerifyOrQuit(mServerDuid.mShared.mEui64.IsValid()); |
| VerifyOrQuit(mServerDuid.mShared.mEui64.GetLinkLayerAddress() == *aServerMacAddr); |
| } |
| else |
| { |
| VerifyOrQuit(!mHasServerId); |
| } |
| |
| VerifyOrQuit(mIaPds.GetLength() == 1); |
| VerifyOrQuit(mIaPds[0].mIaid == kExpectedIaid); |
| VerifyOrQuit(mIaPds[0].mT1 == 0); |
| VerifyOrQuit(mIaPds[0].mT2 == 0); |
| VerifyOrQuit(!mIaPds[0].mHasStatus); |
| VerifyOrQuit(mIaPds[0].mIaPrefixes.GetLength() == 1); |
| VerifyOrQuit(mIaPds[0].mIaPrefixes[0].mPrefix == aPrefix); |
| VerifyOrQuit(mIaPds[0].mIaPrefixes[0].mPreferredLifetime == 0); |
| VerifyOrQuit(mIaPds[0].mIaPrefixes[0].mValidLifetime == 0); |
| } |
| |
| //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| |
| struct Dhcp6TxMsg : public Dhcp6Msg |
| { |
| struct PrefixInfo |
| { |
| uint16_t mIaid; |
| uint32_t mT1; |
| uint32_t mT2; |
| uint32_t mPreferredLifetime; |
| uint32_t mValidLifetime; |
| Ip6::Prefix mPrefix; |
| }; |
| |
| void PrepareAdvertise(const Dhcp6RxMsg &aClientMsg, const Mac::ExtAddress &aServerMacAddr); |
| void PrepareReply(const Dhcp6RxMsg &aClientMsg, const Mac::ExtAddress &aServerMacAddr); |
| void AddIaPrefix(const PrefixInfo &aInfo); |
| void Send(void); |
| }; |
| |
| void Dhcp6TxMsg::PrepareAdvertise(const Dhcp6RxMsg &aClientMsg, const Mac::ExtAddress &aServerMacAddr) |
| { |
| Clear(); |
| mMsgType = Dhcp6::kMsgTypeAdvertise; |
| mTransactionId = aClientMsg.mTransactionId; |
| mHasClientId = true; |
| mHasServerId = true; |
| mClientDuid = aClientMsg.mClientDuid; |
| mServerDuid.mShared.mEui64.Init(aServerMacAddr); |
| mServerDuid.mLength = sizeof(Dhcp6::Eui64Duid); |
| } |
| |
| void Dhcp6TxMsg::PrepareReply(const Dhcp6RxMsg &aClientMsg, const Mac::ExtAddress &aServerMacAddr) |
| { |
| Clear(); |
| mMsgType = Dhcp6::kMsgTypeReply; |
| mTransactionId = aClientMsg.mTransactionId; |
| mHasClientId = true; |
| mHasServerId = true; |
| mClientDuid = aClientMsg.mClientDuid; |
| mServerDuid.mShared.mEui64.Init(aServerMacAddr); |
| mServerDuid.mLength = sizeof(Dhcp6::Eui64Duid); |
| } |
| |
| void Dhcp6TxMsg::AddIaPrefix(const PrefixInfo &aInfo) |
| { |
| IaPd *iaPd = nullptr; |
| IaPrefix *iaPrefix; |
| |
| for (IaPd &ia : mIaPds) |
| { |
| if (ia.mIaid == aInfo.mIaid) |
| { |
| iaPd = &ia; |
| break; |
| } |
| } |
| |
| if (iaPd == nullptr) |
| { |
| iaPd = mIaPds.PushBack(); |
| VerifyOrQuit(iaPd != nullptr); |
| } |
| |
| iaPd->mIaid = aInfo.mIaid; |
| iaPd->mT1 = aInfo.mT1; |
| iaPd->mT2 = aInfo.mT2; |
| |
| iaPrefix = iaPd->mIaPrefixes.PushBack(); |
| VerifyOrQuit(iaPrefix != nullptr); |
| iaPrefix->mPrefix = aInfo.mPrefix; |
| iaPrefix->mPreferredLifetime = aInfo.mPreferredLifetime; |
| iaPrefix->mValidLifetime = aInfo.mValidLifetime; |
| } |
| |
| void Dhcp6TxMsg::Send(void) |
| { |
| Message *message; |
| |
| message = sInstance->Get<MessagePool>().Allocate(Message::kTypeOther); |
| VerifyOrQuit(message != nullptr); |
| PrepareMessage(*message); |
| |
| LogMsg("Sending"); |
| |
| otPlatInfraIfDhcp6PdClientHandleReceived(sInstance, message, kInfraIfIndex); |
| } |
| |
| //---------------------------------------------------------------------------------------------------------------------- |
| // otPlatInfraIf |
| |
| typedef BorderRouter::Dhcp6PdClient::DelegatedPrefix DelegatedPrefix; |
| |
| static bool sDhcp6ListeningEnabled = false; |
| static Array<Dhcp6RxMsg, kMaxDhcp6RxMsgs> sDhcp6RxMsgs; |
| |
| extern "C" { |
| |
| void otPlatInfraIfDhcp6PdClientSetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex) |
| { |
| Log("otPlatInfraIfDhcp6PdClientSetListeningEnabled(aEnable:%u)", aEnable); |
| |
| VerifyOrQuit(aInstance == sInstance); |
| VerifyOrQuit(aInfraIfIndex == kInfraIfIndex); |
| sDhcp6ListeningEnabled = aEnable; |
| } |
| |
| void otPlatInfraIfDhcp6PdClientSend(otInstance *aInstance, |
| otMessage *aMessage, |
| otIp6Address *aDestAddress, |
| uint32_t aInfraIfIndex) |
| { |
| Message *message = AsCoreTypePtr(aMessage); |
| Dhcp6RxMsg *rxMsg; |
| |
| VerifyOrQuit(aInstance == sInstance); |
| VerifyOrQuit(aInfraIfIndex == kInfraIfIndex); |
| VerifyOrQuit(message != nullptr); |
| VerifyOrQuit(aDestAddress != nullptr); |
| |
| Log("otPlatInfraIfDhcp6PdClientSend(%s)", AsCoreType(aDestAddress).ToString().AsCString()); |
| |
| rxMsg = sDhcp6RxMsgs.PushBack(); |
| VerifyOrQuit(rxMsg != nullptr); |
| |
| rxMsg->ParseFrom(*message); |
| rxMsg->LogMsg("Received"); |
| |
| rxMsg->mRxTime = sNow; |
| rxMsg->mDstAddr = AsCoreType(aDestAddress); |
| |
| message->Free(); |
| } |
| |
| } // extern "C" |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| void ProcessTasklets(void) |
| { |
| do |
| { |
| otTaskletsProcess(sInstance); |
| } while (otTaskletsArePending(sInstance)); |
| } |
| |
| void AdvanceTime(uint32_t aDuration) |
| { |
| uint32_t time = sNow + aDuration; |
| |
| Log("AdvanceTime for %u.%03u", aDuration / 1000, aDuration % 1000); |
| |
| while (TimeMilli(sAlarmTime) <= TimeMilli(time)) |
| { |
| ProcessTasklets(); |
| sNow = sAlarmTime; |
| otPlatAlarmMilliFired(sInstance); |
| } |
| |
| ProcessTasklets(); |
| sNow = time; |
| } |
| |
| void AdvanceNowTo(uint32_t aNewNow) |
| { |
| VerifyOrQuit(aNewNow >= sNow); |
| AdvanceTime(aNewNow - sNow); |
| } |
| |
| void InitTest(void) |
| { |
| //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| // Initialize OT instance. |
| |
| sNow = 0; |
| sAlarmOn = false; |
| sInstance = static_cast<Instance *>(testInitInstance()); |
| |
| sDhcp6ListeningEnabled = false; |
| sDhcp6RxMsgs.Clear(); |
| |
| SuccessOrQuit(otBorderRoutingInit(sInstance, kInfraIfIndex, /* aInfraIfIsRunning */ true)); |
| AdvanceTime(100); |
| } |
| |
| void FinalizeTest(void) { testFreeInstance(sInstance); } |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| void TestDhcp6PdPrefixDelegation(bool aShortPrefix) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Ip6::Prefix adjustedPrefix; |
| Mac::ExtAddress serverMacAddr; |
| const DelegatedPrefix *delegatedPrefix; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdPrefixDelegation(aShortPrefix:%u)", aShortPrefix); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| if (aShortPrefix) |
| { |
| prefix = PrefixFromString("2001:1111::", 48); |
| adjustedPrefix = PrefixFromString("2001:1111::", 64); |
| } |
| else |
| { |
| prefix = PrefixFromString("2001:2222::", 64); |
| adjustedPrefix = prefix; |
| } |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and wait for the first two Solicit messages"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| AdvanceTime(2200); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| sDhcp6RxMsgs.Clear(); |
| |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| VerifyOrQuit(sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix() == nullptr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate Request message is received"); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix, serverMacAddr); |
| |
| for (uint16_t iter = 0; iter < 3; iter++) |
| { |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Reply message to %s", iter == 0 ? "Request" : "Renew"); |
| |
| sDhcp6RxMsgs.Clear(); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate the delegated prefix on the client"); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == prefixInfo.mT1); |
| VerifyOrQuit(delegatedPrefix->mT2 == prefixInfo.mT2); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == prefixInfo.mPreferredLifetime); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that no messages is received until renew time T1"); |
| |
| AdvanceTime(prefixInfo.mT1 * 1000 - 1); |
| VerifyOrQuit(sDhcp6RxMsgs.IsEmpty()); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that at T1 time Renew message is received"); |
| |
| AdvanceTime(5); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| |
| sDhcp6RxMsgs[0].ValidateAsRenew(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| } |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Do not send a Reply to the Renew. Wait till T2 time and check the Renew message retries"); |
| |
| AdvanceTime((prefixInfo.mT2 - prefixInfo.mT1) * 1000 - 6); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() > 1); |
| |
| for (uint16_t index = 2; index < sDhcp6RxMsgs.GetLength(); index++) |
| { |
| sDhcp6RxMsgs[index].ValidateAsRenew(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mElapsedTime > 0); |
| } |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the delegated prefix on the client remains unchanged"); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == prefixInfo.mT1); |
| VerifyOrQuit(delegatedPrefix->mT2 == prefixInfo.mT2); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == prefixInfo.mPreferredLifetime); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that Rebind message is received at T2 time"); |
| |
| sDhcp6RxMsgs.Clear(); |
| AdvanceTime(10); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRebind(prefix); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Reply to Rebind"); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| sDhcp6RxMsgs.Clear(); |
| |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the delegated prefix on the client is renewed"); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == prefixInfo.mT1); |
| VerifyOrQuit(delegatedPrefix->mT2 == prefixInfo.mT2); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == prefixInfo.mPreferredLifetime); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that no message is received until renew time T1"); |
| |
| AdvanceTime(prefixInfo.mT1 * 1000 - 1); |
| VerifyOrQuit(sDhcp6RxMsgs.IsEmpty()); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate Renew message is received"); |
| |
| AdvanceTime(5); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| |
| sDhcp6RxMsgs[0].ValidateAsRenew(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait till T2 time and check that Renew message is retried"); |
| |
| AdvanceTime((prefixInfo.mT2 - prefixInfo.mT1) * 1000 - 6); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() > 1); |
| |
| for (uint16_t index = 2; index < sDhcp6RxMsgs.GetLength(); index++) |
| { |
| sDhcp6RxMsgs[index].ValidateAsRenew(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mElapsedTime > 0); |
| } |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that Rebind message is received after T2 time"); |
| |
| sDhcp6RxMsgs.Clear(); |
| AdvanceTime(5); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRebind(prefix); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait till preferred time and check that Rebind message is now retried"); |
| |
| AdvanceTime((prefixInfo.mPreferredLifetime - prefixInfo.mT2) * 1000 - 6); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() > 1); |
| |
| for (uint16_t index = 2; index < sDhcp6RxMsgs.GetLength(); index++) |
| { |
| sDhcp6RxMsgs[index].ValidateAsRebind(prefix); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mElapsedTime > 0); |
| } |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the delegated prefix is still present on the client right before its expire time"); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == prefixInfo.mT1); |
| VerifyOrQuit(delegatedPrefix->mT2 == prefixInfo.mT2); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == prefixInfo.mPreferredLifetime); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the delegated prefix is removed after its expire time"); |
| |
| sDhcp6RxMsgs.Clear(); |
| AdvanceTime(5); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix == nullptr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that Solicit messages are sent again"); |
| |
| AdvanceTime(10 * 1000); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() > 1); |
| |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| |
| for (uint16_t index = 2; index < sDhcp6RxMsgs.GetLength(); index++) |
| { |
| sDhcp6RxMsgs[index].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mElapsedTime > 0); |
| } |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement, check Request message and respond with Reply"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix, serverMacAddr); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate the delegated prefix on the client"); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == prefixInfo.mT1); |
| VerifyOrQuit(delegatedPrefix->mT2 == prefixInfo.mT2); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == prefixInfo.mPreferredLifetime); |
| |
| AdvanceTime(5 * 1000); |
| VerifyOrQuit(sDhcp6RxMsgs.IsEmpty()); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client, and validate that Release message is received"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRelease(prefix, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Reply to Release message and check that no more messages is received"); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(20 * 1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.IsEmpty()); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdPrefixDelegation(aShortPrefix:%u)", aShortPrefix); |
| |
| FinalizeTest(); |
| } |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| void TestDhcp6PdSolicitRetries(void) |
| { |
| static uint32_t kMaxTimeout = 3600 * 1000; |
| |
| uint16_t heapAllocations; |
| uint32_t firstRxTime; |
| uint32_t timeout; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdSolicitRetries"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and check initial delay for first Solicit"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| // Initial random delay of [0, 1000] msec to send first solicit |
| AdvanceTime(1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| firstRxTime = sDhcp6RxMsgs[0].mRxTime; |
| |
| VerifyOrQuit(sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix() == nullptr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait for more than 30 minutes and collect all Solicit messages"); |
| |
| AdvanceTime(20000 * 1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() >= 14); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate the retx timing of Solicit messages"); |
| |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[1].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[1].mElapsedTime == (sDhcp6RxMsgs[1].mRxTime - firstRxTime) / 10); |
| timeout = sDhcp6RxMsgs[1].mRxTime - firstRxTime; |
| |
| // The initial time should be randomly picked from [1, 1.1] sec. |
| |
| VerifyOrQuit(timeout >= 1000); |
| VerifyOrQuit(timeout <= 1100); |
| |
| for (uint16_t index = 2; index < sDhcp6RxMsgs.GetLength(); index++) |
| { |
| uint32_t newTimeout; |
| uint32_t minTimeout; |
| uint32_t maxTimeout; |
| uint32_t elapsedTime; |
| |
| sDhcp6RxMsgs[index].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| |
| newTimeout = sDhcp6RxMsgs[index].mRxTime - sDhcp6RxMsgs[index - 1].mRxTime; |
| |
| minTimeout = 2 * timeout - timeout / 10; |
| maxTimeout = 2 * timeout + timeout / 10; |
| |
| if (maxTimeout > kMaxTimeout) |
| { |
| minTimeout = Min(minTimeout, kMaxTimeout - kMaxTimeout / 10); |
| maxTimeout = kMaxTimeout + kMaxTimeout / 10; |
| } |
| |
| Log("Solicit %2u -> timeout:%lu, min:%lu, max:%lu", index, ToUlong(newTimeout), ToUlong(minTimeout), |
| ToUlong(maxTimeout)); |
| |
| elapsedTime = (sDhcp6RxMsgs[index].mRxTime - firstRxTime) / 10; |
| VerifyOrQuit(sDhcp6RxMsgs[index].mElapsedTime == ClampToUint16(elapsedTime)); |
| |
| VerifyOrQuit(newTimeout >= minTimeout); |
| VerifyOrQuit(newTimeout <= maxTimeout); |
| |
| timeout = newTimeout; |
| } |
| |
| VerifyOrQuit(sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix() == nullptr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client and make sure there are no more transmissions"); |
| |
| sDhcp6RxMsgs.Clear(); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| |
| AdvanceTime(200 * 1000); |
| VerifyOrQuit(sDhcp6RxMsgs.IsEmpty()); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start again and check the Solicit message tx"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| // Initial random delay of [0, 1000] msec to send first solicit |
| AdvanceTime(1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| AdvanceTime(15 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdSolicitRetries"); |
| |
| FinalizeTest(); |
| } |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| void TestDhcp6PdRequestRetries(void) |
| { |
| static constexpr uint32_t kInitialRequestTimeout = 1000; |
| static constexpr uint32_t kMaxRequestTimeout = 30 * 1000; |
| static constexpr uint16_t kMaxRequestRetxCount = 10; |
| |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Mac::ExtAddress serverMacAddr; |
| uint32_t firstRxTime; |
| uint32_t timeout; |
| uint32_t newTimeout; |
| uint32_t minTimeout; |
| uint32_t maxTimeout; |
| uint32_t elapsedTime; |
| uint16_t index; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdRequestRetries"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix = PrefixFromString("2001:aa::", 64); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and wait for the first two Solicit messages"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| AdvanceTime(2200); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate Request message is received"); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| firstRxTime = sDhcp6RxMsgs[0].mRxTime; |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait for 5 minutes and collect all messages"); |
| |
| AdvanceTime(300 * 1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() > kMaxRequestRetxCount); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate the retx timing of Request messages"); |
| |
| sDhcp6RxMsgs[1].ValidateAsRequest(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[1].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[1].mElapsedTime == (sDhcp6RxMsgs[1].mRxTime - firstRxTime) / 10); |
| timeout = sDhcp6RxMsgs[1].mRxTime - firstRxTime; |
| |
| // Validate the initial timeout |
| |
| minTimeout = kInitialRequestTimeout - kInitialRequestTimeout / 10; |
| maxTimeout = kInitialRequestTimeout + kInitialRequestTimeout / 10; |
| |
| Log("Request %2u -> timeout:%lu, min:%lu, max:%lu", 1, ToUlong(timeout), ToUlong(minTimeout), ToUlong(maxTimeout)); |
| |
| VerifyOrQuit(timeout >= minTimeout); |
| VerifyOrQuit(timeout <= maxTimeout); |
| |
| for (index = 2; index <= kMaxRequestRetxCount; index++) |
| { |
| sDhcp6RxMsgs[index].ValidateAsRequest(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| |
| newTimeout = sDhcp6RxMsgs[index].mRxTime - sDhcp6RxMsgs[index - 1].mRxTime; |
| |
| minTimeout = 2 * timeout - timeout / 10; |
| maxTimeout = 2 * timeout + timeout / 10; |
| |
| if (maxTimeout > kMaxRequestTimeout) |
| { |
| minTimeout = Min(minTimeout, kMaxRequestTimeout - kMaxRequestTimeout / 10); |
| maxTimeout = kMaxRequestTimeout + kMaxRequestTimeout / 10; |
| } |
| |
| Log("Request %2u -> timeout:%lu, min:%lu, max:%lu", index, ToUlong(newTimeout), ToUlong(minTimeout), |
| ToUlong(maxTimeout)); |
| |
| elapsedTime = (sDhcp6RxMsgs[index].mRxTime - firstRxTime) / 10; |
| VerifyOrQuit(sDhcp6RxMsgs[index].mElapsedTime == ClampToUint16(elapsedTime)); |
| |
| VerifyOrQuit(newTimeout >= minTimeout); |
| VerifyOrQuit(newTimeout <= maxTimeout); |
| |
| timeout = newTimeout; |
| } |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that after the Request Retries are finished, client restarts sending Solicit"); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() > kMaxRequestRetxCount + 1); |
| |
| index = kMaxRequestRetxCount + 1; |
| |
| sDhcp6RxMsgs[index].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mTransactionId != sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[index].mElapsedTime == 0); |
| |
| // Check the timeout of the last Request message |
| timeout = sDhcp6RxMsgs[index].mRxTime - sDhcp6RxMsgs[index - 1].mRxTime; |
| VerifyOrQuit(timeout >= minTimeout); |
| VerifyOrQuit(timeout <= maxTimeout); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| AdvanceTime(15 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdRequestRetries"); |
| |
| FinalizeTest(); |
| } |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| void TestDhcp6PdSelectBetweenMultipleServers(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix1; |
| Ip6::Prefix prefix2; |
| Ip6::Prefix prefix3; |
| Mac::ExtAddress serverMacAddr1; |
| Mac::ExtAddress serverMacAddr2; |
| Mac::ExtAddress serverMacAddr3; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdSelectBetweenMultipleServers()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr1.GenerateRandom(); |
| serverMacAddr2.GenerateRandom(); |
| serverMacAddr3.GenerateRandom(); |
| |
| prefix1 = PrefixFromString("2001:ff::", 64); |
| prefix2 = PrefixFromString("2001:0::", 48); |
| prefix3 = PrefixFromString("2001:dad0::", 40); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and wait for the first Solicit message"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| AdvanceTime(1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send multiple Advertisements from different servers providing different prefixes"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr1); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix1; |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr2); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix2; |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr3); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix3; |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the client does wait for the full timeout (on first Solicit) "); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| |
| // First timeout is at least 1000 msec |
| AdvanceNowTo(sDhcp6RxMsgs[0].mRxTime + 1000 - 1); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate Request message is received and its for the preferred prefix from server2"); |
| |
| AdvanceTime(200); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[1].ValidateAsRequest(prefix2, serverMacAddr2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| |
| AdvanceTime(5 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdSelectBetweenMultipleServers()"); |
| |
| FinalizeTest(); |
| } |
| |
| void TestDhcp6PdServerWithMaxPreferrence(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Mac::ExtAddress serverMacAddr; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdServerWithMaxPreferrence()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix = PrefixFromString("2001:7::", 64); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and wait for the first Solicit message"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| AdvanceTime(1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| |
| // On the first Solicit, the client must wait for the full timeout |
| // unless preference is in Advertisement is set to max (255). |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with Preference Option string preference to max to the first Solicit"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.mHasPreference = true; |
| txMsg.mPreference = 255; |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the client does not wait any longer and sends Request immediately"); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[1].ValidateAsRequest(prefix, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| |
| AdvanceTime(5 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdServerWithMaxPreferrence()"); |
| |
| FinalizeTest(); |
| } |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| void TestDhcp6PdServerOfferingMultiplePrefixes(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix1; |
| Ip6::Prefix prefix2; |
| Ip6::Prefix prefix3; |
| Mac::ExtAddress serverMacAddr; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdServerOfferingMultiplePrefixes()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix1 = PrefixFromString("2001:5:baba:beef::", 64); |
| prefix2 = PrefixFromString("2001:4::", 48); |
| prefix3 = PrefixFromString("2001:ef::", 40); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and wait for the first Solicit message"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| AdvanceTime(1000); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisements from server offering three prefixes"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix1; |
| txMsg.AddIaPrefix(prefixInfo); |
| prefixInfo.mPrefix = prefix2; |
| txMsg.AddIaPrefix(prefixInfo); |
| prefixInfo.mPrefix = prefix3; |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the client does wait for the full timeout (on first Solicit) "); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| AdvanceNowTo(sDhcp6RxMsgs[0].mRxTime + 1000 - 1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate Request message is received and its for the preferred prefix"); |
| |
| AdvanceTime(200); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[1].ValidateAsRequest(prefix2, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| |
| AdvanceTime(5 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdServerOfferingMultiplePrefixes()"); |
| |
| FinalizeTest(); |
| } |
| |
| void TestDhcp6PdInvalidOrUnusablePrefix(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Mac::ExtAddress serverMacAddr; |
| Dhcp6RxMsg modifiedSolicitRxMsg; |
| Mac::ExtAddress modifiedClientMacAddr; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdInvalidOrUnusablePrefix"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix = PrefixFromString("2001:9::", 64); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and wait for the first two Solicit messages"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| AdvanceTime(2200); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with wrong TransactionId and ensure it is not accepted"); |
| |
| modifiedSolicitRxMsg = sDhcp6RxMsgs[0]; |
| |
| do |
| { |
| modifiedSolicitRxMsg.mTransactionId.GenerateRandom(); |
| } while (modifiedSolicitRxMsg.mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| |
| txMsg.PrepareAdvertise(modifiedSolicitRxMsg, serverMacAddr); |
| prefixInfo.mIaid = modifiedSolicitRxMsg.mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with wrong Client ID and ensure it is not accepted"); |
| |
| modifiedSolicitRxMsg = sDhcp6RxMsgs[0]; |
| |
| do |
| { |
| modifiedClientMacAddr.GenerateRandom(); |
| } while (modifiedClientMacAddr == sDhcp6RxMsgs[0].mClientDuid.mShared.mEui64.GetLinkLayerAddress()); |
| |
| modifiedSolicitRxMsg.mClientDuid.mShared.mEui64.Init(modifiedClientMacAddr); |
| |
| txMsg.PrepareAdvertise(modifiedSolicitRxMsg, serverMacAddr); |
| prefixInfo.mIaid = modifiedSolicitRxMsg.mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with no Client ID and ensure it is not accepted"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.mHasClientId = false; |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with no Server ID and ensure it is not accepted"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.mHasServerId = false; |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with a wrong `Iaid` and ensure it is not accepted"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid + 1; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with a long prefix and ensure it is not accepted"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = PrefixFromString("2001:dead:beef:cafe::", 65); |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement T1 longer than T2 and ensure it is not accepted"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 3000; |
| prefixInfo.mT2 = 2000; |
| prefixInfo.mPreferredLifetime = 3600; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement preferred lifetime longer than valid lifetime and ensure it is not accepted"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 2000; |
| prefixInfo.mT2 = 3200; |
| prefixInfo.mPreferredLifetime = 4000; |
| prefixInfo.mValidLifetime = 3600; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisement with preferred lifetime below the min required threshold of 30 min"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 900; |
| prefixInfo.mT2 = 1000; |
| prefixInfo.mPreferredLifetime = 1799; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Finally send Advertisement with everything valid and ensure it is accepted"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 1800; |
| prefixInfo.mValidLifetime = 4000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.Send(); |
| AdvanceTime(1); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 3); |
| |
| sDhcp6RxMsgs[2].ValidateAsRequest(prefix, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| AdvanceTime(15 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdInvalidOrUnusablePrefix"); |
| |
| FinalizeTest(); |
| } |
| |
| void TestDhcp6PdLifetimeT1AndT2Adjustments(void) |
| { |
| struct TestCase |
| { |
| uint32_t mT1; |
| uint32_t mT2; |
| uint32_t mPreferredLifetime; |
| uint32_t mExpectedT1; |
| uint32_t mExpectedT2; |
| uint32_t mExpectedPreferredLifetime; |
| }; |
| |
| // Validate client will adjust the T1 and T2 and lifetime to reasonable range. |
| |
| static const TestCase kTestCases[] = { |
| // T1 and T2 are zero. Client must pick 0.5 and 0.8 times lifetime for T1 and T2. |
| {0, 0, 1800, 900, 1440, 1800}, |
| |
| // Only T1 is zero. |
| {0, 1300, 1800, 900, 1300, 1800}, |
| |
| // Only T2 is zero. |
| {800, 0, 1800, 800, 1440, 1800}, |
| |
| // T1 is zero, but default T1 (half of preferred lifetime) will be larger than given T2. |
| {0, 800, 1800, 900, 900, 1800}, |
| |
| // T1 and T2 are given but way too short. Client enforces min of 300s (5 min). |
| {1, 5, 1800, 300, 300, 1800}, |
| |
| // T1 and T2 zero with preferred lifetime of 7200 (2 hours). |
| {0, 0, 7200, 3600, 5760, 7200}, |
| |
| // T1 and T2 longer than lifetime. |
| {2000, 2500, 1800, 900, 1440, 1800}, |
| |
| // Given T1 and T2 (shorter than 0.5 and 0.8) with preferred lifetime of 7200 (2 hours). |
| {1000, 1200, 7200, 1000, 1200, 7200}, |
| |
| // Given T1 and T2 are too close to the preferred lifetime of 7200 (2 hours). |
| {7100, 7150, 7200, 6300, 6840, 7200}, |
| |
| // Very long preferred lifetime. Client limit it to 4 hours (14400) |
| {0, 0, 14500, 7200, 11520, 14400}, |
| |
| // Very long preferred lifetime. Client limit it to 4 hours (14400) |
| {2000, 2500, 14500, 2000, 2500, 14400}, |
| |
| // Infinite lifetime and T1 and T2. Client limit to 4 hours. |
| {0xffffffff, 0xffffffff, 0xffffffff, 13500, 14040, 14400}}; |
| |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Ip6::Prefix adjustedPrefix; |
| Mac::ExtAddress serverMacAddr; |
| const DelegatedPrefix *delegatedPrefix; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdLifetimeT1AndT2Adjustments()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix = PrefixFromString("2001:13::", 48); |
| adjustedPrefix = PrefixFromString("2001:13::", 64); |
| |
| for (const TestCase &testCase : kTestCases) |
| { |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Test case: {T1:%lu T2:%lu prf:%lu } --> Expected {T1:%lu T2:%lu prf:%lu}", ToUlong(testCase.mT1), |
| ToUlong(testCase.mT2), ToUlong(testCase.mPreferredLifetime), ToUlong(testCase.mExpectedT1), |
| ToUlong(testCase.mExpectedT2), ToUlong(testCase.mExpectedPreferredLifetime)); |
| |
| sDhcp6RxMsgs.Clear(); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| |
| AdvanceTime(2200); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = testCase.mT1; |
| prefixInfo.mT2 = testCase.mT2; |
| prefixInfo.mPreferredLifetime = testCase.mPreferredLifetime; |
| prefixInfo.mValidLifetime = testCase.mPreferredLifetime; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix, serverMacAddr); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| Log("Delegated Prefix -> {T1:%lu T2:%lu prf:%lu}", ToUlong(delegatedPrefix->mT1), ToUlong(delegatedPrefix->mT2), |
| ToUlong(delegatedPrefix->mPreferredLifetime)); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == testCase.mExpectedT1); |
| VerifyOrQuit(delegatedPrefix->mT2 == testCase.mExpectedT2); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == testCase.mExpectedPreferredLifetime); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| AdvanceTime(100); |
| } |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdLifetimeT1AndT2Adjustments"); |
| |
| FinalizeTest(); |
| } |
| |
| void TestDhcp6PdServerVoidingLeaseDuringRenew(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Ip6::Prefix adjustedPrefix; |
| Mac::ExtAddress serverMacAddr; |
| const DelegatedPrefix *delegatedPrefix; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdServerVoidingLeaseDuringRenew()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix = PrefixFromString("2001:cafe:5555::", 48); |
| adjustedPrefix = PrefixFromString("2001:cafe:5555::", 64); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start client, interact with it to successfully delegate a prefix"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| |
| AdvanceTime(2200); |
| |
| // Listen for Solicit and send Advertise |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 1800; |
| prefixInfo.mValidLifetime = 1800; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| // Listen for Request and send Reply |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix, serverMacAddr); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == 900); |
| VerifyOrQuit(delegatedPrefix->mT2 == 1440); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == 1800); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait till T1 time for client to renew"); |
| |
| AdvanceTime(900 * 1000 + 10); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRenew(prefix, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send a Reply invalidating the previously delegated prefix"); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 0; |
| prefixInfo.mValidLifetime = 0; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix == nullptr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| AdvanceTime(5 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdServerVoidingLeaseDuringRenew"); |
| |
| FinalizeTest(); |
| } |
| |
| void TestDhcp6PdServerNotExtendingLeaseDuringRenew(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Ip6::Prefix adjustedPrefix; |
| Mac::ExtAddress serverMacAddr; |
| const DelegatedPrefix *delegatedPrefix; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdServerNotExtendingLeaseDuringRenew()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix = PrefixFromString("2001:4567::", 48); |
| adjustedPrefix = PrefixFromString("2001:4567::", 64); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start client, interact with it to successfully delegate a prefix"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| |
| AdvanceTime(2200); |
| |
| // Listen for Solicit and send Advertise |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 1800; |
| prefixInfo.mValidLifetime = 1800; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| // Listen for Request and send Reply |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix, serverMacAddr); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == 900); |
| VerifyOrQuit(delegatedPrefix->mT2 == 1440); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == 1800); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait till T1 time for client to renew"); |
| |
| AdvanceTime(900 * 1000 + 10); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRenew(prefix, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send a Reply including the previously delegated prefix but with short lifetime"); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 100; |
| prefixInfo.mValidLifetime = 100; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == adjustedPrefix); |
| VerifyOrQuit(delegatedPrefix->mT1 == 100); |
| VerifyOrQuit(delegatedPrefix->mT2 == 100); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == 100); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait for the short lifetime to expire and validate that the delegated prefix is removed"); |
| |
| AdvanceTime(100 * 1000 + 1); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix == nullptr); |
| |
| AdvanceTime(5 * 1000); |
| |
| VerifyOrQuit(!sDhcp6RxMsgs.IsEmpty()); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| AdvanceTime(5 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdServerNotExtendingLeaseDuringRenew"); |
| |
| FinalizeTest(); |
| } |
| |
| void TestDhcp6PdServerReplacingPrefix(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix1; |
| Ip6::Prefix prefix2; |
| Mac::ExtAddress serverMacAddr; |
| const DelegatedPrefix *delegatedPrefix; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdServerReplacingPrefix()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix1 = PrefixFromString("2001:b2d4:1111::", 64); |
| prefix1 = PrefixFromString("2001:b2d4:2222::", 64); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start client, interact with it to successfully delegate a prefix"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| |
| AdvanceTime(2200); |
| |
| // Listen for Solicit and send Advertise |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 1800; |
| prefixInfo.mValidLifetime = 1800; |
| prefixInfo.mPrefix = prefix1; |
| txMsg.AddIaPrefix(prefixInfo); |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| // Listen for Request and send Reply |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix1, serverMacAddr); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| txMsg.AddIaPrefix(prefixInfo); |
| txMsg.Send(); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix1); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == prefix1); |
| VerifyOrQuit(delegatedPrefix->mT1 == 900); |
| VerifyOrQuit(delegatedPrefix->mT2 == 1440); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == 1800); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Wait till T1 time for client to renew"); |
| |
| AdvanceTime(900 * 1000 + 10); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRenew(prefix1, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send a Reply including a new prefix with old one with short lifetime"); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 120; |
| prefixInfo.mValidLifetime = 120; |
| prefixInfo.mPrefix = prefix1; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| prefixInfo.mPreferredLifetime = 1800; |
| prefixInfo.mValidLifetime = 1800; |
| prefixInfo.mPrefix = prefix2; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| AdvanceTime(1); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix2); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == prefix2); |
| VerifyOrQuit(delegatedPrefix->mT1 == 900); |
| VerifyOrQuit(delegatedPrefix->mT2 == 1440); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == 1800); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| AdvanceTime(5 * 1000); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdServerReplacingPrefix"); |
| |
| FinalizeTest(); |
| } |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| //--------------------------------------------------------------------------------------------------------------------- |
| |
| void TestDhcp6PdServerReplyWithNoBindingToRelease(void) |
| { |
| uint16_t heapAllocations; |
| Dhcp6TxMsg txMsg; |
| Dhcp6TxMsg::PrefixInfo prefixInfo; |
| Ip6::Prefix prefix; |
| Mac::ExtAddress serverMacAddr; |
| const DelegatedPrefix *delegatedPrefix; |
| |
| Log("--------------------------------------------------------------------------------------------"); |
| Log("TestDhcp6PdServerReplyWithNoBindingToRelease()"); |
| |
| InitTest(); |
| |
| heapAllocations = sHeapAllocatedPtrs.GetLength(); |
| |
| serverMacAddr.GenerateRandom(); |
| |
| prefix = PrefixFromString("2001:8765::", 64); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Start the client and wait for the first two Solicit messages"); |
| |
| VerifyOrQuit(!sDhcp6ListeningEnabled); |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Start(); |
| VerifyOrQuit(sDhcp6ListeningEnabled); |
| |
| AdvanceTime(2200); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[0].ValidateAsSolicit(); |
| sDhcp6RxMsgs[1].ValidateAsSolicit(); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mTransactionId == sDhcp6RxMsgs[1].mTransactionId); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Advertisements from server offering three prefixes"); |
| |
| txMsg.PrepareAdvertise(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| prefixInfo.mT1 = 0; |
| prefixInfo.mT2 = 0; |
| prefixInfo.mPreferredLifetime = 5000; |
| prefixInfo.mValidLifetime = 5000; |
| prefixInfo.mPrefix = prefix; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate Request message is received"); |
| |
| AdvanceTime(1); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRequest(prefix, serverMacAddr); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send Reply message"); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| delegatedPrefix = sInstance->Get<BorderRouter::Dhcp6PdClient>().GetDelegatedPrefix(); |
| VerifyOrQuit(delegatedPrefix != nullptr); |
| |
| VerifyOrQuit(delegatedPrefix->mPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mAdjustedPrefix == prefix); |
| VerifyOrQuit(delegatedPrefix->mPreferredLifetime == prefixInfo.mPreferredLifetime); |
| |
| sDhcp6RxMsgs.Clear(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Stop the client to release the prefix"); |
| |
| sInstance->Get<BorderRouter::Dhcp6PdClient>().Stop(); |
| |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 1); |
| sDhcp6RxMsgs[0].ValidateAsRelease(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[0].mElapsedTime == 0); |
| |
| AdvanceTime(1200); |
| VerifyOrQuit(sDhcp6RxMsgs.GetLength() == 2); |
| sDhcp6RxMsgs[1].ValidateAsRelease(prefix, serverMacAddr); |
| VerifyOrQuit(sDhcp6RxMsgs[1].mTransactionId == sDhcp6RxMsgs[0].mTransactionId); |
| VerifyOrQuit(sDhcp6RxMsgs[1].mElapsedTime > 0); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Send a Reply to the Release with status code NoBinding, validate that it is accepted"); |
| |
| txMsg.PrepareReply(sDhcp6RxMsgs[0], serverMacAddr); |
| prefixInfo.mIaid = sDhcp6RxMsgs[0].mIaPds[0].mIaid; |
| txMsg.AddIaPrefix(prefixInfo); |
| |
| txMsg.mIaPds[0].mHasStatus = true; |
| txMsg.mIaPds[0].mStatusCode = Dhcp6::StatusCodeOption::kNoBinding; |
| |
| sDhcp6RxMsgs.Clear(); |
| txMsg.Send(); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| Log("Validate that the client accepts the Reply and there are no more retries of Release"); |
| |
| AdvanceTime(30 * 1000); |
| VerifyOrQuit(sDhcp6RxMsgs.IsEmpty()); |
| |
| Log("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "); |
| |
| VerifyOrQuit(heapAllocations == sHeapAllocatedPtrs.GetLength()); |
| |
| Log("End of TestDhcp6PdServerReplyWithNoBindingToRelease()"); |
| |
| FinalizeTest(); |
| } |
| |
| #endif // OT_CONFIG_DHCP6_PD_CLIENT_ENABLE |
| |
| } // namespace ot |
| |
| int main(void) |
| { |
| #if OT_CONFIG_DHCP6_PD_CLIENT_ENABLE |
| ot::TestDhcp6PdPrefixDelegation(/* aShortPrefix */ false); |
| ot::TestDhcp6PdPrefixDelegation(/* aShortPrefix */ true); |
| ot::TestDhcp6PdSolicitRetries(); |
| ot::TestDhcp6PdRequestRetries(); |
| ot::TestDhcp6PdSelectBetweenMultipleServers(); |
| ot::TestDhcp6PdServerWithMaxPreferrence(); |
| ot::TestDhcp6PdServerOfferingMultiplePrefixes(); |
| ot::TestDhcp6PdInvalidOrUnusablePrefix(); |
| ot::TestDhcp6PdLifetimeT1AndT2Adjustments(); |
| ot::TestDhcp6PdServerVoidingLeaseDuringRenew(); |
| ot::TestDhcp6PdServerNotExtendingLeaseDuringRenew(); |
| ot::TestDhcp6PdServerReplacingPrefix(); |
| ot::TestDhcp6PdServerReplyWithNoBindingToRelease(); |
| |
| printf("All tests passed\n"); |
| #else |
| printf("DHCP6_PD_CLIENT_ENABLE feature is not enabled\n"); |
| #endif |
| |
| return 0; |
| } |