diff --git a/src/core/api/backbone_router_ftd_api.cpp b/src/core/api/backbone_router_ftd_api.cpp index 738aea56f..0be7eef72 100644 --- a/src/core/api/backbone_router_ftd_api.cpp +++ b/src/core/api/backbone_router_ftd_api.cpp @@ -107,7 +107,8 @@ otError otBackboneRouterGetDomainPrefix(otInstance *aInstance, otBorderRouterCon OT_ASSERT(aConfig != nullptr); - return instance.Get().GetDomainPrefix(*aConfig); + return instance.Get().GetDomainPrefix( + *static_cast(aConfig)); } #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE diff --git a/src/core/api/border_router_api.cpp b/src/core/api/border_router_api.cpp index ea52592cc..80b31974f 100644 --- a/src/core/api/border_router_api.cpp +++ b/src/core/api/border_router_api.cpp @@ -53,8 +53,9 @@ otError otBorderRouterGetNetData(otInstance *aInstance, bool aStable, uint8_t *a otError otBorderRouterAddOnMeshPrefix(otInstance *aInstance, const otBorderRouterConfig *aConfig) { - otError error = OT_ERROR_NONE; - Instance &instance = *static_cast(aInstance); + otError error = OT_ERROR_NONE; + Instance & instance = *static_cast(aInstance); + const NetworkData::OnMeshPrefixConfig *config = static_cast(aConfig); OT_ASSERT(aConfig != nullptr); // Add Prefix validation check: @@ -62,16 +63,15 @@ otError otBorderRouterAddOnMeshPrefix(otInstance *aInstance, const otBorderRoute // "A valid prefix MUST NOT allow both DHCPv6 and SLAAC for address configuration" VerifyOrExit(!aConfig->mDhcp || !aConfig->mSlaac, error = OT_ERROR_INVALID_ARGS); - error = instance.Get().AddOnMeshPrefix(*aConfig); + error = instance.Get().AddOnMeshPrefix(*config); #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE // Only try to configure Domain Prefix after the parameter is vaidated via above `AddOnMeshPrefix()`. if (error == OT_ERROR_NONE && aConfig->mDp) { // Restore local server data - IgnoreError(instance.Get().RemoveOnMeshPrefix(aConfig->mPrefix.mPrefix.mFields.m8, - aConfig->mPrefix.mLength)); + IgnoreError(instance.Get().RemoveOnMeshPrefix(config->GetPrefix())); - instance.Get().SetDomainPrefix(*aConfig); + instance.Get().SetDomainPrefix(*config); } #endif @@ -81,18 +81,19 @@ exit: otError otBorderRouterRemoveOnMeshPrefix(otInstance *aInstance, const otIp6Prefix *aPrefix) { - otError error = OT_ERROR_NONE; - Instance &instance = *static_cast(aInstance); + otError error = OT_ERROR_NONE; + Instance & instance = *static_cast(aInstance); + const Ip6::Prefix *prefix = static_cast(aPrefix); OT_ASSERT(aPrefix != nullptr); #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE - error = instance.Get().RemoveDomainPrefix(*aPrefix); + error = instance.Get().RemoveDomainPrefix(*prefix); if (error == OT_ERROR_NOT_FOUND) #endif { - error = instance.Get().RemoveOnMeshPrefix(aPrefix->mPrefix.mFields.m8, aPrefix->mLength); + error = instance.Get().RemoveOnMeshPrefix(*prefix); } return error; @@ -102,11 +103,12 @@ otError otBorderRouterGetNextOnMeshPrefix(otInstance * aInstance, otNetworkDataIterator *aIterator, otBorderRouterConfig * aConfig) { - Instance &instance = *static_cast(aInstance); + Instance & instance = *static_cast(aInstance); + NetworkData::OnMeshPrefixConfig *config = static_cast(aConfig); OT_ASSERT(aIterator != nullptr && aConfig != nullptr); - return instance.Get().GetNextOnMeshPrefix(*aIterator, *aConfig); + return instance.Get().GetNextOnMeshPrefix(*aIterator, *config); } otError otBorderRouterAddRoute(otInstance *aInstance, const otExternalRouteConfig *aConfig) @@ -116,7 +118,7 @@ otError otBorderRouterAddRoute(otInstance *aInstance, const otExternalRouteConfi OT_ASSERT(aConfig != nullptr); return instance.Get().AddHasRoutePrefix( - aConfig->mPrefix.mPrefix.mFields.m8, aConfig->mPrefix.mLength, aConfig->mPreference, aConfig->mStable); + *static_cast(aConfig)); } otError otBorderRouterRemoveRoute(otInstance *aInstance, const otIp6Prefix *aPrefix) @@ -125,7 +127,7 @@ otError otBorderRouterRemoveRoute(otInstance *aInstance, const otIp6Prefix *aPre OT_ASSERT(aPrefix != nullptr); - return instance.Get().RemoveHasRoutePrefix(aPrefix->mPrefix.mFields.m8, aPrefix->mLength); + return instance.Get().RemoveHasRoutePrefix(*static_cast(aPrefix)); } otError otBorderRouterGetNextRoute(otInstance * aInstance, @@ -136,7 +138,8 @@ otError otBorderRouterGetNextRoute(otInstance * aInstance, OT_ASSERT(aIterator != nullptr && aConfig != nullptr); - return instance.Get().GetNextExternalRoute(*aIterator, *aConfig); + return instance.Get().GetNextExternalRoute( + *aIterator, *static_cast(aConfig)); } otError otBorderRouterRegister(otInstance *aInstance) diff --git a/src/core/api/netdata_api.cpp b/src/core/api/netdata_api.cpp index 2c49c6cc8..38b494f75 100644 --- a/src/core/api/netdata_api.cpp +++ b/src/core/api/netdata_api.cpp @@ -53,12 +53,13 @@ otError otNetDataGetNextOnMeshPrefix(otInstance * aInstance, otNetworkDataIterator *aIterator, otBorderRouterConfig * aConfig) { - otError error = OT_ERROR_NONE; - Instance &instance = *static_cast(aInstance); + otError error = OT_ERROR_NONE; + Instance & instance = *static_cast(aInstance); + NetworkData::OnMeshPrefixConfig *config = static_cast(aConfig); VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS); - error = instance.Get().GetNextOnMeshPrefix(*aIterator, *aConfig); + error = instance.Get().GetNextOnMeshPrefix(*aIterator, *config); exit: return error; @@ -71,7 +72,8 @@ otError otNetDataGetNextRoute(otInstance *aInstance, otNetworkDataIterator *aIte VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS); - error = instance.Get().GetNextExternalRoute(*aIterator, *aConfig); + error = instance.Get().GetNextExternalRoute( + *aIterator, *static_cast(aConfig)); exit: return error; @@ -84,7 +86,8 @@ otError otNetDataGetNextService(otInstance *aInstance, otNetworkDataIterator *aI VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS); - error = instance.Get().GetNextService(*aIterator, *aConfig); + error = instance.Get().GetNextService(*aIterator, + *static_cast(aConfig)); exit: return error; diff --git a/src/core/api/server_api.cpp b/src/core/api/server_api.cpp index 3d01e1c70..d6b94cedf 100644 --- a/src/core/api/server_api.cpp +++ b/src/core/api/server_api.cpp @@ -78,7 +78,8 @@ otError otServerGetNextService(otInstance *aInstance, otNetworkDataIterator *aIt VerifyOrExit(aIterator && aConfig, error = OT_ERROR_INVALID_ARGS); - error = instance.Get().GetNextService(*aIterator, *aConfig); + error = instance.Get().GetNextService(*aIterator, + *static_cast(aConfig)); exit: return error; diff --git a/src/core/backbone_router/bbr_leader.cpp b/src/core/backbone_router/bbr_leader.cpp index ca61092b2..3240a73bb 100644 --- a/src/core/backbone_router/bbr_leader.cpp +++ b/src/core/backbone_router/bbr_leader.cpp @@ -54,7 +54,7 @@ void Leader::Reset(void) mConfig.mServer16 = Mac::kShortAddrInvalid; // Domain Prefix Length 0 indicates no available Domain Prefix in the Thread network. - mDomainPrefix.mLength = 0; + mDomainPrefix.SetLength(0); } otError Leader::GetConfig(BackboneRouterConfig &aConfig) const @@ -97,12 +97,9 @@ void Leader::LogBackboneRouterPrimary(State aState, const BackboneRouterConfig & } } -void Leader::LogDomainPrefix(DomainPrefixState aState, const otIp6Prefix &aPrefix) const +void Leader::LogDomainPrefix(DomainPrefixState aState, const Ip6::Prefix &aPrefix) const { - otLogInfoBbr("Domain Prefix: %s/%d, state: %s", - aPrefix.mLength == 0 ? "" - : static_cast(&aPrefix.mPrefix)->ToString().AsCString(), - aPrefix.mLength, DomainPrefixStateToString(aState)); + otLogInfoBbr("Domain Prefix: %s, state: %s", aPrefix.ToString().AsCString(), DomainPrefixStateToString(aState)); } const char *Leader::StateToString(State aState) @@ -250,20 +247,18 @@ void Leader::UpdateDomainPrefixConfig(void) if (!found) { - if (mDomainPrefix.mLength != 0) + if (mDomainPrefix.GetLength() != 0) { // Domain Prefix does not exist any more. - mDomainPrefix.mLength = 0; - state = kDomainPrefixRemoved; + mDomainPrefix.SetLength(0); + state = kDomainPrefixRemoved; } else { state = kDomainPrefixNone; } } - else if (config.mPrefix.mLength == mDomainPrefix.mLength && - Ip6::Address::PrefixMatch(mDomainPrefix.mPrefix.mFields.m8, config.mPrefix.mPrefix.mFields.m8, - BitVectorBytes(mDomainPrefix.mLength)) >= mDomainPrefix.mLength) + else if (config.GetPrefix() == mDomainPrefix) { state = kDomainPrefixUnchanged; } @@ -278,7 +273,7 @@ void Leader::UpdateDomainPrefixConfig(void) state = kDomainPrefixRefreshed; } - mDomainPrefix = config.mPrefix; + mDomainPrefix = config.GetPrefix(); } LogDomainPrefix(state, mDomainPrefix); @@ -294,7 +289,7 @@ void Leader::UpdateDomainPrefixConfig(void) bool Leader::IsDomainUnicast(const Ip6::Address &aAddress) const { - return HasDomainPrefix() && aAddress.PrefixMatch(mDomainPrefix.mPrefix) >= mDomainPrefix.mLength; + return HasDomainPrefix() && aAddress.MatchesPrefix(mDomainPrefix); } } // namespace BackboneRouter diff --git a/src/core/backbone_router/bbr_leader.hpp b/src/core/backbone_router/bbr_leader.hpp index 5df7ac050..5ba177002 100644 --- a/src/core/backbone_router/bbr_leader.hpp +++ b/src/core/backbone_router/bbr_leader.hpp @@ -142,7 +142,10 @@ public: * @retval A pointer to the Domain Prefix or nullptr if there is no Domain Prefix. * */ - const otIp6Prefix *GetDomainPrefix(void) const { return (mDomainPrefix.mLength == 0) ? nullptr : &mDomainPrefix; } + const Ip6::Prefix *GetDomainPrefix(void) const + { + return (mDomainPrefix.GetLength() == 0) ? nullptr : &mDomainPrefix; + } /** * This method indicates whether or not the Domain Prefix is available in the Thread Network. @@ -150,7 +153,7 @@ public: * @retval TRUE if there is Domain Prefix, FALSE otherwise. * */ - bool HasDomainPrefix(void) const { return (mDomainPrefix.mLength > 0); } + bool HasDomainPrefix(void) const { return (mDomainPrefix.GetLength() > 0); } /** * This method indicates whether or not the address is a Domain Unicast Address. @@ -168,16 +171,16 @@ private: void UpdateDomainPrefixConfig(void); #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1) void LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const; - void LogDomainPrefix(DomainPrefixState aState, const otIp6Prefix &aPrefix) const; + void LogDomainPrefix(DomainPrefixState aState, const Ip6::Prefix &aPrefix) const; static const char *StateToString(State aState); static const char *DomainPrefixStateToString(DomainPrefixState aState); #else void LogBackboneRouterPrimary(State, const BackboneRouterConfig &) const {} - void LogDomainPrefix(DomainPrefixState, const otIp6Prefix &) const {} + void LogDomainPrefix(DomainPrefixState, const Ip6::Prefix &) const {} #endif BackboneRouterConfig mConfig; ///< Primary Backbone Router information. - otIp6Prefix mDomainPrefix; ///< Domain Prefix in the Thread network. + Ip6::Prefix mDomainPrefix; ///< Domain Prefix in the Thread network. }; } // namespace BackboneRouter diff --git a/src/core/backbone_router/bbr_local.cpp b/src/core/backbone_router/bbr_local.cpp index 0a9d70e40..417900ad7 100644 --- a/src/core/backbone_router/bbr_local.cpp +++ b/src/core/backbone_router/bbr_local.cpp @@ -56,7 +56,7 @@ Local::Local(Instance &aInstance) , mRegistrationJitter(Mle::kBackboneRouterRegistrationJitter) , mIsServiceAdded(false) { - mDomainPrefixConfig.mPrefix.mLength = 0; + mDomainPrefixConfig.GetPrefix().SetLength(0); // Primary Backbone Router Aloc mBackboneRouterPrimaryAloc.Clear(); @@ -312,7 +312,7 @@ otError Local::GetDomainPrefix(NetworkData::OnMeshPrefixConfig &aConfig) { otError error = OT_ERROR_NONE; - VerifyOrExit(mDomainPrefixConfig.mPrefix.mLength > 0, error = OT_ERROR_NOT_FOUND); + VerifyOrExit(mDomainPrefixConfig.GetPrefix().GetLength() > 0, error = OT_ERROR_NOT_FOUND); aConfig = mDomainPrefixConfig; @@ -320,24 +320,19 @@ exit: return error; } -otError Local::RemoveDomainPrefix(const otIp6Prefix &aPrefix) +otError Local::RemoveDomainPrefix(const Ip6::Prefix &aPrefix) { otError error = OT_ERROR_NONE; - VerifyOrExit(aPrefix.mLength > 0, error = OT_ERROR_INVALID_ARGS); - - VerifyOrExit(mDomainPrefixConfig.mPrefix.mLength == aPrefix.mLength, error = OT_ERROR_NOT_FOUND); - - VerifyOrExit(Ip6::Address::PrefixMatch(mDomainPrefixConfig.mPrefix.mPrefix.mFields.m8, aPrefix.mPrefix.mFields.m8, - BitVectorBytes(aPrefix.mLength)) >= aPrefix.mLength, - error = OT_ERROR_NOT_FOUND); + VerifyOrExit(aPrefix.GetLength() > 0, error = OT_ERROR_INVALID_ARGS); + VerifyOrExit(mDomainPrefixConfig.GetPrefix() == aPrefix, error = OT_ERROR_NOT_FOUND); if (IsEnabled()) { RemoveDomainPrefixFromNetworkData(); } - mDomainPrefixConfig.mPrefix.mLength = 0; + mDomainPrefixConfig.GetPrefix().SetLength(0); exit: return error; @@ -407,8 +402,7 @@ void Local::RemoveDomainPrefixFromNetworkData(void) if (mDomainPrefixConfig.mPrefix.mLength > 0) { - error = Get().RemoveOnMeshPrefix(mDomainPrefixConfig.mPrefix.mPrefix.mFields.m8, - mDomainPrefixConfig.mPrefix.mLength); + error = Get().RemoveOnMeshPrefix(mDomainPrefixConfig.GetPrefix()); } LogDomainPrefix("Remove", error); @@ -418,7 +412,7 @@ void Local::AddDomainPrefixToNetworkData(void) { otError error = OT_ERROR_NOT_FOUND; // only used for logging. - if (mDomainPrefixConfig.mPrefix.mLength > 0) + if (mDomainPrefixConfig.GetPrefix().GetLength() > 0) { error = Get().AddOnMeshPrefix(mDomainPrefixConfig); } @@ -429,11 +423,8 @@ void Local::AddDomainPrefixToNetworkData(void) #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_BBR == 1) void Local::LogDomainPrefix(const char *aAction, otError aError) { - otLogInfoBbr("%s Domain Prefix: %s/%d, %s", aAction, - mDomainPrefixConfig.mPrefix.mLength > 0 - ? (*static_cast(&mDomainPrefixConfig.mPrefix.mPrefix)).ToString().AsCString() - : "", - mDomainPrefixConfig.mPrefix.mLength, otThreadErrorToString(aError)); + otLogInfoBbr("%s Domain Prefix: %s, %s", aAction, mDomainPrefixConfig.GetPrefix().ToString().AsCString(), + otThreadErrorToString(aError)); } void Local::LogBackboneRouterService(const char *aAction, otError aError) diff --git a/src/core/backbone_router/bbr_local.hpp b/src/core/backbone_router/bbr_local.hpp index fc37c9f0b..018d5ba49 100644 --- a/src/core/backbone_router/bbr_local.hpp +++ b/src/core/backbone_router/bbr_local.hpp @@ -188,7 +188,7 @@ public: * @retval OT_ERROR_NOT_FOUND No Domain Prefix was configured or @p aPrefix doesn't match. * */ - otError RemoveDomainPrefix(const otIp6Prefix &aPrefix); + otError RemoveDomainPrefix(const Ip6::Prefix &aPrefix); /** * This method sets the local Domain Prefix configuration. diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp index f1a58209b..7e2d4b5eb 100644 --- a/src/core/net/dhcp6_client.cpp +++ b/src/core/net/dhcp6_client.cpp @@ -57,10 +57,9 @@ Client::Client(Instance &aInstance) memset(mIdentityAssociations, 0, sizeof(mIdentityAssociations)); } -bool Client::MatchNetifAddressWithPrefix(const Ip6::NetifUnicastAddress &aNetifAddress, const otIp6Prefix &aIp6Prefix) +bool Client::MatchNetifAddressWithPrefix(const Ip6::NetifUnicastAddress &aNetifAddress, const Ip6::Prefix &aIp6Prefix) { - return (aIp6Prefix.mLength == aNetifAddress.mPrefixLength) && - (aNetifAddress.GetAddress().PrefixMatch(aIp6Prefix.mPrefix) >= aIp6Prefix.mLength); + return aNetifAddress.HasPrefix(aIp6Prefix); } void Client::UpdateAddresses(void) @@ -88,7 +87,7 @@ void Client::UpdateAddresses(void) continue; } - if (MatchNetifAddressWithPrefix(idAssociation.mNetifAddress, config.mPrefix)) + if (MatchNetifAddressWithPrefix(idAssociation.mNetifAddress, config.GetPrefix())) { found = true; break; @@ -127,7 +126,7 @@ void Client::UpdateAddresses(void) idAssociation = &ia; } } - else if (MatchNetifAddressWithPrefix(ia.mNetifAddress, config.mPrefix)) + else if (MatchNetifAddressWithPrefix(ia.mNetifAddress, config.GetPrefix())) { found = true; idAssociation = &ia; diff --git a/src/core/net/dhcp6_client.hpp b/src/core/net/dhcp6_client.hpp index a06c2ae68..482fe3959 100644 --- a/src/core/net/dhcp6_client.hpp +++ b/src/core/net/dhcp6_client.hpp @@ -109,7 +109,7 @@ private: void Start(void); void Stop(void); - static bool MatchNetifAddressWithPrefix(const Ip6::NetifUnicastAddress &aAddress, const otIp6Prefix &aIp6Prefix); + static bool MatchNetifAddressWithPrefix(const Ip6::NetifUnicastAddress &aAddress, const Ip6::Prefix &aIp6Prefix); void Solicit(uint16_t aRloc16); diff --git a/src/core/net/dhcp6_server.cpp b/src/core/net/dhcp6_server.cpp index 96173451b..f3f9a1c74 100644 --- a/src/core/net/dhcp6_server.cpp +++ b/src/core/net/dhcp6_server.cpp @@ -82,7 +82,7 @@ otError Server::UpdateService(void) continue; } - error = Get().GetContext(prefixAgent.GetPrefix(), lowpanContext); + error = Get().GetContext(prefixAgent.GetPrefixAsAddress(), lowpanContext); if ((error == OT_ERROR_NONE) && (prefixAgent.GetContextId() == lowpanContext.mContextId)) { @@ -114,7 +114,7 @@ otError Server::UpdateService(void) if (error == OT_ERROR_NONE) { - AddPrefixAgent(config.mPrefix, lowpanContext); + AddPrefixAgent(config.GetPrefix(), lowpanContext); } } @@ -144,7 +144,7 @@ void Server::Stop(void) IgnoreError(mSocket.Close()); } -void Server::AddPrefixAgent(const otIp6Prefix &aIp6Prefix, const Lowpan::Context &aContext) +void Server::AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, const Lowpan::Context &aContext) { otError error = OT_ERROR_NONE; PrefixAgent *newEntry = nullptr; @@ -155,7 +155,7 @@ void Server::AddPrefixAgent(const otIp6Prefix &aIp6Prefix, const Lowpan::Context { newEntry = &prefixAgent; } - else if (prefixAgent.IsPrefixMatch(aIp6Prefix)) + else if (prefixAgent.GetPrefix() == aIp6Prefix) { // already added ExitNow(); @@ -445,7 +445,7 @@ otError Server::AppendIaAddress(Message &aMessage, ClientIdentifier &aClientId) { if (mPrefixAgentsMask & (1 << i)) { - SuccessOrExit(error = AddIaAddress(aMessage, mPrefixAgents[i].GetPrefix(), aClientId)); + SuccessOrExit(error = AddIaAddress(aMessage, mPrefixAgents[i].GetPrefixAsAddress(), aClientId)); } } } @@ -456,7 +456,7 @@ otError Server::AppendIaAddress(Message &aMessage, ClientIdentifier &aClientId) { if (prefixAgent.IsValid()) { - SuccessOrExit(error = AddIaAddress(aMessage, prefixAgent.GetPrefix(), aClientId)); + SuccessOrExit(error = AddIaAddress(aMessage, prefixAgent.GetPrefixAsAddress(), aClientId)); } } } diff --git a/src/core/net/dhcp6_server.hpp b/src/core/net/dhcp6_server.hpp index bbaa26e6a..ceed5a7ee 100644 --- a/src/core/net/dhcp6_server.hpp +++ b/src/core/net/dhcp6_server.hpp @@ -84,21 +84,6 @@ private: class PrefixAgent { public: - /** - * This method indicates whether or not @p aPrefix matches this entry. - * - * @param[in] aPrefix The prefix to compare. - * - * @retval TRUE if the prefix matches. - * @retval FALSE if the prefix does not match. - * - */ - bool IsPrefixMatch(const otIp6Prefix &aPrefix) const - { - return (mPrefix.mLength == aPrefix.mLength) && - (GetPrefix().PrefixMatch(static_cast(aPrefix.mPrefix)) >= mPrefix.mLength); - } - /** * This method indicates whether or not @p aAddress has a matching prefix. * @@ -108,10 +93,7 @@ private: * @retval FALSE if the address does not have a matching prefix. * */ - bool IsPrefixMatch(const Ip6::Address &aAddress) const - { - return (aAddress.PrefixMatch(static_cast(mPrefix.mPrefix)) >= mPrefix.mLength); - } + bool IsPrefixMatch(const Ip6::Address &aAddress) const { return aAddress.MatchesPrefix(GetPrefix()); } /** * This method indicates whether or not this entry is valid. @@ -150,7 +132,26 @@ private: * @returns The IPv6 prefix. * */ - const Ip6::Address &GetPrefix(void) const { return static_cast(mPrefix.mPrefix); } + const Ip6::Prefix &GetPrefix(void) const { return mPrefix; } + + /** + * This method returns the IPv6 prefix. + * + * @returns The IPv6 prefix. + * + */ + Ip6::Prefix &GetPrefix(void) { return mPrefix; } + + /** + * This method returns the IPv6 prefix as an IPv6 address. + * + * @returns The IPv6 prefix as an IPv6 address. + * + */ + const Ip6::Address &GetPrefixAsAddress(void) const + { + return static_cast(mPrefix.mPrefix); + } /** * This method sets the ALOC. @@ -160,7 +161,7 @@ private: * @param[in] aContextId The 6LoWPAN Context ID. * */ - void Set(const otIp6Prefix &aPrefix, const Mle::MeshLocalPrefix &aMeshLocalPrefix, uint8_t aContextId) + void Set(const Ip6::Prefix &aPrefix, const Mle::MeshLocalPrefix &aMeshLocalPrefix, uint8_t aContextId) { mPrefix = aPrefix; @@ -173,7 +174,7 @@ private: private: Ip6::NetifUnicastAddress mAloc; - otIp6Prefix mPrefix; + Ip6::Prefix mPrefix; }; enum : uint16_t @@ -184,7 +185,7 @@ private: void Start(void); void Stop(void); - void AddPrefixAgent(const otIp6Prefix &aIp6Prefix, const Lowpan::Context &aContext); + void AddPrefixAgent(const Ip6::Prefix &aIp6Prefix, const Lowpan::Context &aContext); otError AppendHeader(Message &aMessage, const TransactionId &aTransactionId); otError AppendClientIdentifier(Message &aMessage, ClientIdentifier &aClientId); diff --git a/src/core/net/ip6_address.cpp b/src/core/net/ip6_address.cpp index 5b053d03c..f5ed71db4 100644 --- a/src/core/net/ip6_address.cpp +++ b/src/core/net/ip6_address.cpp @@ -56,6 +56,69 @@ otError NetworkPrefix::GenerateRandomUla(void) return Random::Crypto::FillBuffer(&m8[1], kSize - 1); } +//--------------------------------------------------------------------------------------------------------------------- +// Prefix methods + +void Prefix::Set(const uint8_t *aPrefix, uint8_t aLength) +{ + memcpy(mPrefix.mFields.m8, aPrefix, SizeForLength(aLength)); + mLength = aLength; +} + +bool Prefix::IsEqual(const uint8_t *aPrefixBytes, uint8_t aPrefixLength) const +{ + return (mLength == aPrefixLength) && (MatchLength(GetBytes(), aPrefixBytes, GetBytesSize()) >= mLength); +} + +uint8_t Prefix::MatchLength(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxSize) +{ + uint8_t matchedLength = 0; + + OT_ASSERT(aMaxSize <= Address::kSize); + + for (uint8_t i = 0; i < aMaxSize; i++) + { + uint8_t diff = aPrefixA[i] ^ aPrefixB[i]; + + if (diff == 0) + { + matchedLength += CHAR_BIT; + } + else + { + while ((diff & 0x80) == 0) + { + matchedLength++; + diff <<= 1; + } + + break; + } + } + + return matchedLength; +} + +Prefix::InfoString Prefix::ToString(void) const +{ + InfoString string; + uint8_t sizeInUint16 = (GetBytesSize() + sizeof(uint16_t) - 1) / sizeof(uint16_t); + + for (uint16_t i = 0; i < sizeInUint16; i++) + { + IgnoreError(string.Append("%s%x", (i > 0) ? ":" : "", HostSwap16(mPrefix.mFields.m16[i]))); + } + + if (GetBytesSize() < Address::kSize - 1) + { + IgnoreError(string.Append("::")); + } + + IgnoreError(string.Append("/%d", mLength)); + + return string; +} + //--------------------------------------------------------------------------------------------------------------------- // InterfaceIdentifier methods @@ -262,14 +325,24 @@ void Address::SetToRealmLocalAllMplForwarders(void) *this = GetRealmLocalAllMplForwarders(); } +bool Address::MatchesPrefix(const Prefix &aPrefix) const +{ + return Prefix::MatchLength(mFields.m8, aPrefix.GetBytes(), aPrefix.GetBytesSize()) >= aPrefix.GetLength(); +} + +bool Address::MatchesPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const +{ + return Prefix::MatchLength(mFields.m8, aPrefix, Prefix::SizeForLength(aPrefixLength)) >= aPrefixLength; +} + void Address::SetPrefix(const NetworkPrefix &aNetworkPrefix) { mFields.mComponents.mNetworkPrefix = aNetworkPrefix; } -void Address::SetPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) +void Address::SetPrefix(const Prefix &aPrefix) { - SetPrefix(0, aPrefix, aPrefixLength); + SetPrefix(0, aPrefix.GetBytes(), aPrefix.GetLength()); } void Address::SetPrefix(uint8_t aOffset, const uint8_t *aPrefix, uint8_t aPrefixLength) @@ -331,42 +404,9 @@ uint8_t Address::GetScope(void) const return rval; } -uint8_t Address::PrefixMatch(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxLength) +uint8_t Address::PrefixMatch(const Address &aOther) const { - uint8_t rval = 0; - uint8_t diff; - - if (aMaxLength > sizeof(Address)) - { - aMaxLength = sizeof(Address); - } - - for (uint8_t i = 0; i < aMaxLength; i++) - { - diff = aPrefixA[i] ^ aPrefixB[i]; - - if (diff == 0) - { - rval += 8; - } - else - { - while ((diff & 0x80) == 0) - { - rval++; - diff <<= 1; - } - - break; - } - } - - return rval; -} - -uint8_t Address::PrefixMatch(const otIp6Address &aOther) const -{ - return PrefixMatch(mFields.m8, aOther.mFields.m8, sizeof(Address)); + return Prefix::MatchLength(mFields.m8, aOther.mFields.m8, sizeof(Address)); } bool Address::MatchesFilter(TypeFilter aFilter) const diff --git a/src/core/net/ip6_address.hpp b/src/core/net/ip6_address.hpp index 4fb4d9ee3..286c75835 100644 --- a/src/core/net/ip6_address.hpp +++ b/src/core/net/ip6_address.hpp @@ -82,6 +82,189 @@ public: } OT_TOOL_PACKED_END; +/** + * This class represents an IPv6 Prefix. + * + */ +OT_TOOL_PACKED_BEGIN +class Prefix : public otIp6Prefix +{ +public: + enum : uint8_t + { + kMaxLength = OT_IP6_ADDRESS_SIZE * CHAR_BIT, ///< Max length of a prefix in bits. + kMaxSize = OT_IP6_ADDRESS_SIZE, ///< Max (byte) size of a prefix. + }; + + enum : uint16_t + { + kInfoStringSize = 45, ///< Max chars for the info string (`ToString()`). + }; + + /** + * This type defines the fixed-length `String` object returned from `ToString()`. + * + */ + typedef String InfoString; + + /** + * This method gets the prefix as a pointer to a byte array. + * + * @returns A pointer to a byte array containing the Prefix. + * + */ + const uint8_t *GetBytes(void) const { return mPrefix.mFields.m8; } + + /** + * This method gets the prefix length (in bits). + * + * @returns The prefix length (in bits). + * + */ + uint8_t GetLength(void) const { return mLength; } + + /** + * This method returns the size (in bytes) of the prefix. + * + * @returns The size (in bytes) of the prefix array. + * + */ + uint8_t GetBytesSize(void) const { return SizeForLength(mLength); } + + /** + * This method sets the prefix. + * + * @param[in] aPrefix A pointer to buffer containing the prefix bytes. + * @param[in] aLength The length or prefix in bits. + * + */ + void Set(const uint8_t *aPrefix, uint8_t aLength); + + /** + * This method sets the prefix from a given Network Prefix. + * + * @param[in] aNetworkPrefix A Network Prefix. + * + */ + void Set(const NetworkPrefix &aNetworkPrefix) { Set(aNetworkPrefix.m8, NetworkPrefix::kLength); } + + /** + * This method set the prefix length. + * + * @param[in] aLength The new prefix length (in bits). + * + */ + void SetLength(uint8_t aLength) { mLength = aLength; } + + /** + * This method indicates whether prefix length is valid (smaller or equal to max length). + * + * @retval TRUE The prefix length is valid. + * @retval FALSE The prefix length is not valid. + * + */ + bool IsValid(void) const { return (mLength <= kMaxLength); } + + /** + * This method indicates whether the prefix is equal to a given prefix. + * + * @param[in] aPrefixBytes A pointer to buffer containing the prefix bytes to compare with. + * @param[in] aPrefixLength The length of prefix (in bits) specified by @p aPrefixBytes. + * + * @retval TRUE If the prefix is equal to the specified prefix by @p aPrefixBytes and @p aPrefixLength. + * @retval FALSE If the prefix is not equal to the specified prefix by @p aPrefixBytes and @p aPrefixLength. + * + */ + bool IsEqual(const uint8_t *aPrefixBytes, uint8_t aPrefixLength) const; + + /** + * This method indicates whether the prefix contains a sub-prefix. + * + * @param[in] aSubPrefix A sub-prefix. + * + * @retval TRUE The prefix contains the @p aSubPrefix + * @retval FALSE The prefix does not contains the @p aSubPrefix. + * + */ + bool ContainsPrefix(const Prefix &aSubPrefix) const + { + return (mLength >= aSubPrefix.mLength) && + (MatchLength(GetBytes(), aSubPrefix.GetBytes(), aSubPrefix.GetBytesSize()) >= aSubPrefix.GetLength()); + } + + /** + * This method indicates whether the prefix contains a sub-prefix (given as a `NetworkPrefix`). + * + * @param[in] aSubPrefix A sub-prefix (as a `NetworkPrefix`). + * + * @retval TRUE The prefix contains the @p aSubPrefix + * @retval FALSE The prefix does not contains the @p aSubPrefix. + * + */ + bool ContainsPrefix(const NetworkPrefix &aSubPrefix) const + { + return (mLength >= NetworkPrefix::kLength) && + (MatchLength(GetBytes(), aSubPrefix.m8, NetworkPrefix::kSize) >= NetworkPrefix::kLength); + } + + /** + * This method overloads operator `==` to evaluate whether or not two prefixes are equal. + * + * @param[in] aOther The other prefix to compare with. + * + * @retval TRUE If the two prefixes are equal. + * @retval FALSE If the two prefixes are not equal. + * + */ + bool operator==(const Prefix &aOther) const + { + return (mLength == aOther.mLength) && + (MatchLength(GetBytes(), aOther.GetBytes(), GetBytesSize()) >= GetLength()); + } + + /** + * This method overloads operator `==` to evaluate whether or not two prefixes are unequal. + * + * @param[in] aOther The other prefix to compare with. + * + * @retval TRUE If the two prefixes are unequal. + * @retval FALSE If the two prefixes are not unequal. + * + */ + bool operator!=(const Prefix &aOther) const { return !(*this == aOther); } + + /** + * This static method converts a prefix length (in bits) to size (number of bytes). + * + * @param[in] aLength A prefix length (in bits). + * + * @returns The size (in bytes) of the prefix. + * + */ + static uint8_t SizeForLength(uint8_t aLength) { return BitVectorBytes(aLength); } + + /** + * This static method returns the number of IPv6 prefix bits that match. + * + * @param[in] aPrefixA A pointer to a byte array containing a first prefix. + * @param[in] aPrefixB A pointer to a byte array containing a second prefix. + * @param[in] aMaxSize Number of bytes of the two prefixes. + * + * @returns The number of prefix bits that match. + * + */ + static uint8_t MatchLength(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxSize); + + /** + * This method converts the prefix to a string. + * + * @returns An `InfoString` containing the string representation of the Prefix. + * + */ + InfoString ToString(void) const; + +} OT_TOOL_PACKED_END; + /** * This class represents the Interface Identifier of an IPv6 address. * @@ -534,17 +717,40 @@ public: return static_cast(mFields.mComponents.mNetworkPrefix); } + /** + * This method indicates whether the IPv6 address matches a given prefix. + * + * @param[in] aPrefix An IPv6 prefix to match with. + * + * @retval TRUE The IPv6 address matches the @p aPrefix. + * @retval FALSE The IPv6 address does not match the @p aPrefix. + * + */ + bool MatchesPrefix(const Prefix &aPrefix) const; + + /** + * This method indicates whether the IPv6 address matches a given prefix. + * + * @param[in] aPrefix A buffer containing the prefix. + * @param[in] aPrefixLength The prefix length (in bits). + * + * @retval TRUE The IPv6 address matches the @p aPrefix. + * @retval FALSE The IPv6 address does not match the @p aPrefix. + * + */ + bool MatchesPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const; + /** * This method sets the IPv6 address prefix. * * This method only changes the first @p aPrefixLength bits of the address and keeps the rest of the bits in the * address as before. * - * @param[in] aPrefix A buffer containing the prefix + * @param[in] aPrefix A buffer containing the prefix. * @param[in] aPrefixLength The prefix length (in bits). * */ - void SetPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength); + void SetPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) { SetPrefix(0, aPrefix, aPrefixLength); } /** * This method sets the IPv6 address prefix to the given Network Prefix. @@ -554,6 +760,17 @@ public: */ void SetPrefix(const NetworkPrefix &aNetworkPrefix); + /** + * This method sets the IPv6 address prefix. + * + * This method only changes the initial prefix length bits of the IPv6 address and keeps the rest of the bits in + * the address as before. + * + * @param[in] aPrefix An IPv6 prefix. + * + */ + void SetPrefix(const Prefix &aPrefix); + /** * This method sets the prefix content of the Prefix-Based Multicast Address. * @@ -577,12 +794,12 @@ public: /** * This method sets the prefix content of Prefix-Based Multicast Address. * - * @param[in] aPrefix A reference to an IPv6 Prefix. + * @param[in] aPrefix An IPv6 Prefix. * */ - void SetMulticastNetworkPrefix(const otIp6Prefix &aPrefix) + void SetMulticastNetworkPrefix(const Prefix &aPrefix) { - SetMulticastNetworkPrefix(aPrefix.mPrefix.mFields.m8, aPrefix.mLength); + SetMulticastNetworkPrefix(aPrefix.GetBytes(), aPrefix.GetLength()); } /** @@ -628,7 +845,7 @@ public: * @returns The number of IPv6 prefix bits that match. * */ - uint8_t PrefixMatch(const otIp6Address &aOther) const; + uint8_t PrefixMatch(const Address &aOther) const; /** * This method indicates whether address matches a given type filter. @@ -660,18 +877,6 @@ public: */ InfoString ToString(void) const; - /** - * This method returns the number of IPv6 prefix bits that match. - * - * @param[in] aPrefixA A pointer to the prefix to match. - * @param[in] aPrefixB A pointer to the prefix to match against. - * @param[in] aMaxLength Number of bytes of the two prefixes. - * - * @returns The number of prefix bits that match. - * - */ - static uint8_t PrefixMatch(const uint8_t *aPrefixA, const uint8_t *aPrefixB, uint8_t aMaxLength); - private: void SetPrefix(uint8_t aOffset, const uint8_t *aPrefix, uint8_t aPrefixLength); void SetToLocator(const NetworkPrefix &aNetworkPrefix, uint16_t aLocator); diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp index c9bae015f..7ff541b3c 100644 --- a/src/core/net/netif.hpp +++ b/src/core/net/netif.hpp @@ -91,6 +91,28 @@ public: */ Address &GetAddress(void) { return static_cast
(mAddress); } + /** + * This method returns the address's prefix length (in bits). + * + * @returns The prefix length (in bits). + * + */ + uint8_t GetPrefixLength(void) const { return mPrefixLength; } + + /** + * This method indicates whether the address has a given prefix (i.e. same prefix length and matches the prefix). + * + * @param[in] aPrefix A prefix to check against. + * + * @retval TRUE The address has and fully matches the @p aPrefix. + * @retval FALSE The address does not contain or match the @p aPrefix. + * + */ + bool HasPrefix(const Prefix &aPrefix) const + { + return (mPrefixLength == aPrefix.GetLength()) && GetAddress().MatchesPrefix(aPrefix); + } + /** * This method returns the IPv6 scope value. * diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp index 95027b93b..1b5e1c7a3 100644 --- a/src/core/thread/dua_manager.cpp +++ b/src/core/thread/dua_manager.cpp @@ -62,7 +62,7 @@ DuaManager::DuaManager(Instance &aInstance) void DuaManager::UpdateDomainUnicastAddress(BackboneRouter::Leader::DomainPrefixState aState) { - const otIp6Prefix *prefix; + const Ip6::Prefix *prefix; if ((aState == BackboneRouter::Leader::kDomainPrefixRemoved) || (aState == BackboneRouter::Leader::kDomainPrefixRefreshed)) @@ -78,9 +78,9 @@ void DuaManager::UpdateDomainUnicastAddress(BackboneRouter::Leader::DomainPrefix OT_ASSERT(prefix != nullptr); - mDomainUnicastAddress.mPrefixLength = prefix->mLength; + mDomainUnicastAddress.mPrefixLength = prefix->GetLength(); mDomainUnicastAddress.GetAddress().Clear(); - mDomainUnicastAddress.GetAddress().SetPrefix(prefix->mPrefix.mFields.m8, prefix->mLength); + mDomainUnicastAddress.GetAddress().SetPrefix(*prefix); // Apply cached DUA Interface Identifier manually specified. if (IsFixedDuaInterfaceIdentifierSet()) diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp index bd4850e57..b32ae7de9 100644 --- a/src/core/thread/lowpan.cpp +++ b/src/core/thread/lowpan.cpp @@ -57,7 +57,7 @@ Lowpan::Lowpan(Instance &aInstance) void Lowpan::CopyContext(const Context &aContext, Ip6::Address &aAddress) { - aAddress.SetPrefix(aContext.mPrefix, aContext.mPrefixLength); + aAddress.SetPrefix(aContext.mPrefix); } otError Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress) @@ -78,12 +78,12 @@ otError Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext ExitNow(error = OT_ERROR_PARSE); } - if (aContext.mPrefixLength > 64) + if (aContext.mPrefix.GetLength() > 64) { - for (int i = (aContext.mPrefixLength & ~7); i < aContext.mPrefixLength; i++) + for (int i = (aContext.mPrefix.GetLength() & ~7); i < aContext.mPrefix.GetLength(); i++) { aIpAddress.mFields.m8[i / CHAR_BIT] &= ~(0x80 >> (i % CHAR_BIT)); - aIpAddress.mFields.m8[i / CHAR_BIT] |= aContext.mPrefix[i / CHAR_BIT] & (0x80 >> (i % CHAR_BIT)); + aIpAddress.mFields.m8[i / CHAR_BIT] |= aContext.mPrefix.GetBytes()[i / CHAR_BIT] & (0x80 >> (i % CHAR_BIT)); } } @@ -213,8 +213,8 @@ otError Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, { // Check if multicast address can be compressed using Context ID 0. if (Get().GetContext(0, multicastContext) == OT_ERROR_NONE && - multicastContext.mPrefixLength == aIpAddr.mFields.m8[3] && - memcmp(multicastContext.mPrefix, aIpAddr.mFields.m8 + 4, 8) == 0) + multicastContext.mPrefix.GetLength() == aIpAddr.mFields.m8[3] && + memcmp(multicastContext.mPrefix.GetBytes(), aIpAddr.mFields.m8 + 4, 8) == 0) { aHcCtl |= kHcDstAddrContext | kHcDstAddrMode0; SuccessOrExit(error = buf.Write(aIpAddr.mFields.m8 + 1, 2)); @@ -684,8 +684,8 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, VerifyOrExit((hcCtl & kHcDispatchMask) == kHcDispatch, OT_NOOP); // Context Identifier - srcContext.mPrefixLength = 0; - dstContext.mPrefixLength = 0; + srcContext.mPrefix.SetLength(0); + dstContext.mPrefix.SetLength(0); if ((hcCtl & kHcContextId) != 0) { @@ -909,8 +909,8 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, VerifyOrExit(dstContextValid, OT_NOOP); aIp6Header.GetDestination().mFields.m8[1] = cur[0]; aIp6Header.GetDestination().mFields.m8[2] = cur[1]; - aIp6Header.GetDestination().mFields.m8[3] = dstContext.mPrefixLength; - memcpy(aIp6Header.GetDestination().mFields.m8 + 4, dstContext.mPrefix, 8); + aIp6Header.GetDestination().mFields.m8[3] = dstContext.mPrefix.GetLength(); + memcpy(aIp6Header.GetDestination().mFields.m8 + 4, dstContext.mPrefix.GetBytes(), 8); memcpy(aIp6Header.GetDestination().mFields.m8 + 12, cur + 2, 4); cur += 6; break; diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp index 13bf9a48f..1e951feb6 100644 --- a/src/core/thread/lowpan.hpp +++ b/src/core/thread/lowpan.hpp @@ -71,10 +71,9 @@ using ot::Encoding::BigEndian::HostSwap16; */ struct Context { - const uint8_t *mPrefix; ///< A pointer to the prefix. - uint8_t mPrefixLength; ///< The prefix length. - uint8_t mContextId; ///< The Context ID. - bool mCompressFlag; ///< The Context compression flag. + Ip6::Prefix mPrefix; ///< The Prefix + uint8_t mContextId; ///< The Context ID. + bool mCompressFlag; ///< The Context compression flag. }; /** diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 79887df2f..ead540fdb 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2093,7 +2093,8 @@ otError MleRouter::UpdateChildAddresses(const Message &aMessage, uint16_t aOffse continue; } - memcpy(&address, context.mPrefix, BitVectorBytes(context.mPrefixLength)); + address.Clear(); + address.SetPrefix(context.mPrefix); address.SetIid(entry.GetIid()); } else diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index 2cbc95dbd..77219d3d1 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -218,7 +218,7 @@ otError NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aCon { if (cur->GetType() == NetworkDataTlv::kTypePrefix) { - const PrefixTlv *prefix = static_cast(cur); + const PrefixTlv *prefixTlv = static_cast(cur); switch (subCur->GetType()) { @@ -239,22 +239,20 @@ otError NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aCon aConfig.mExternalRoute = nullptr; aConfig.mService = nullptr; - memset(aConfig.mOnMeshPrefix, 0, sizeof(OnMeshPrefixConfig)); + aConfig.mOnMeshPrefix->Clear(); - memcpy(&aConfig.mOnMeshPrefix->mPrefix.mPrefix, prefix->GetPrefix(), - BitVectorBytes(prefix->GetPrefixLength())); - aConfig.mOnMeshPrefix->mPrefix.mLength = prefix->GetPrefixLength(); - aConfig.mOnMeshPrefix->mPreference = borderRouterEntry->GetPreference(); - aConfig.mOnMeshPrefix->mPreferred = borderRouterEntry->IsPreferred(); - aConfig.mOnMeshPrefix->mSlaac = borderRouterEntry->IsSlaac(); - aConfig.mOnMeshPrefix->mDhcp = borderRouterEntry->IsDhcp(); - aConfig.mOnMeshPrefix->mConfigure = borderRouterEntry->IsConfigure(); - aConfig.mOnMeshPrefix->mDefaultRoute = borderRouterEntry->IsDefaultRoute(); - aConfig.mOnMeshPrefix->mOnMesh = borderRouterEntry->IsOnMesh(); - aConfig.mOnMeshPrefix->mStable = borderRouter->IsStable(); - aConfig.mOnMeshPrefix->mRloc16 = borderRouterEntry->GetRloc(); - aConfig.mOnMeshPrefix->mNdDns = borderRouterEntry->IsNdDns(); - aConfig.mOnMeshPrefix->mDp = borderRouterEntry->IsDp(); + prefixTlv->CopyPrefixTo(aConfig.mOnMeshPrefix->GetPrefix()); + aConfig.mOnMeshPrefix->mPreference = borderRouterEntry->GetPreference(); + aConfig.mOnMeshPrefix->mPreferred = borderRouterEntry->IsPreferred(); + aConfig.mOnMeshPrefix->mSlaac = borderRouterEntry->IsSlaac(); + aConfig.mOnMeshPrefix->mDhcp = borderRouterEntry->IsDhcp(); + aConfig.mOnMeshPrefix->mConfigure = borderRouterEntry->IsConfigure(); + aConfig.mOnMeshPrefix->mDefaultRoute = borderRouterEntry->IsDefaultRoute(); + aConfig.mOnMeshPrefix->mOnMesh = borderRouterEntry->IsOnMesh(); + aConfig.mOnMeshPrefix->mStable = borderRouter->IsStable(); + aConfig.mOnMeshPrefix->mRloc16 = borderRouterEntry->GetRloc(); + aConfig.mOnMeshPrefix->mNdDns = borderRouterEntry->IsNdDns(); + aConfig.mOnMeshPrefix->mDp = borderRouterEntry->IsDp(); ExitNow(error = OT_ERROR_NONE); } @@ -280,14 +278,12 @@ otError NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aCon aConfig.mOnMeshPrefix = nullptr; aConfig.mService = nullptr; - memset(aConfig.mExternalRoute, 0, sizeof(ExternalRouteConfig)); + aConfig.mExternalRoute->Clear(); - memcpy(&aConfig.mExternalRoute->mPrefix.mPrefix, prefix->GetPrefix(), - BitVectorBytes(prefix->GetPrefixLength())); - aConfig.mExternalRoute->mPrefix.mLength = prefix->GetPrefixLength(); - aConfig.mExternalRoute->mPreference = hasRouteEntry->GetPreference(); - aConfig.mExternalRoute->mStable = hasRoute->IsStable(); - aConfig.mExternalRoute->mRloc16 = hasRouteEntry->GetRloc(); + prefixTlv->CopyPrefixTo(aConfig.mExternalRoute->GetPrefix()); + aConfig.mExternalRoute->mPreference = hasRouteEntry->GetPreference(); + aConfig.mExternalRoute->mStable = hasRoute->IsStable(); + aConfig.mExternalRoute->mRloc16 = hasRouteEntry->GetRloc(); aConfig.mExternalRoute->mNextHopIsThisDevice = (hasRouteEntry->GetRloc() == Get().GetRloc16()); @@ -319,7 +315,7 @@ otError NetworkData::Iterate(Iterator &aIterator, uint16_t aRloc16, Config &aCon { aConfig.mOnMeshPrefix = nullptr; aConfig.mExternalRoute = nullptr; - memset(aConfig.mService, 0, sizeof(ServiceConfig)); + aConfig.mService->Clear(); aConfig.mService->mServiceId = service->GetServiceId(); aConfig.mService->mEnterpriseNumber = service->GetEnterpriseNumber(); @@ -671,8 +667,7 @@ const PrefixTlv *NetworkData::FindPrefix(const uint8_t *aPrefix, VerifyOrExit(prefixTlv != nullptr, OT_NOOP); - if (prefixTlv->GetPrefixLength() == aPrefixLength && - PrefixMatch(prefixTlv->GetPrefix(), aPrefix, aPrefixLength) >= aPrefixLength) + if (prefixTlv->IsEqual(aPrefix, aPrefixLength)) { ExitNow(); } @@ -686,18 +681,6 @@ exit: return prefixTlv; } -int8_t NetworkData::PrefixMatch(const uint8_t *a, const uint8_t *b, uint8_t aLength) -{ - uint8_t matchedLength; - - // Note that he `Ip6::Address::PrefixMatch` expects the prefix - // length to be in bytes unit. - - matchedLength = Ip6::Address::PrefixMatch(a, b, BitVectorBytes(aLength)); - - return (matchedLength >= aLength) ? static_cast(matchedLength) : -1; -} - const ServiceTlv *NetworkData::FindService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength) const diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index 179c23bd4..1cd3a27a9 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -40,6 +40,7 @@ #include #include "coap/coap.hpp" +#include "common/clearable.hpp" #include "common/locator.hpp" #include "common/timer.hpp" #include "net/udp6.hpp" @@ -96,22 +97,60 @@ enum typedef otNetworkDataIterator Iterator; /** - * This type represents an On Mesh Prefix (Border Router) configuration. + * This class represents an On Mesh Prefix (Border Router) configuration. * */ -typedef otBorderRouterConfig OnMeshPrefixConfig; +class OnMeshPrefixConfig : public otBorderRouterConfig, public Clearable +{ +public: + /** + * This method get the prefix. + * + * @return The prefix. + * + */ + const Ip6::Prefix &GetPrefix(void) const { return static_cast(mPrefix); } + + /** + * This method get the prefix. + * + * @return The prefix. + * + */ + Ip6::Prefix &GetPrefix(void) { return static_cast(mPrefix); } +}; /** - * This type represents an External Route configuration. + * This class represents an External Route configuration. * */ -typedef otExternalRouteConfig ExternalRouteConfig; +class ExternalRouteConfig : public otExternalRouteConfig, public Clearable +{ +public: + /** + * This method get the prefix. + * + * @return The prefix. + * + */ + const Ip6::Prefix &GetPrefix(void) const { return static_cast(mPrefix); } + + /** + * This method get the prefix. + * + * @return The prefix. + * + */ + Ip6::Prefix &GetPrefix(void) { return static_cast(mPrefix); } +}; /** * This type represents a Service configuration. * */ -typedef otServiceConfig ServiceConfig; +class ServiceConfig : public otServiceConfig, public Clearable +{ +}; /** * This class implements Network Data processing. @@ -450,7 +489,7 @@ protected: * * @param[in] aPrefix A reference to the Prefix TLV. * - * @returns A pointer to the Context TLV is one is found or nullptr if no Context TLV exists. + * @returns A pointer to the Context TLV if one is found or nullptr if no Context TLV exists. * */ static ContextTlv *FindContext(PrefixTlv &aPrefix) @@ -463,7 +502,7 @@ protected: * * @param[in] aPrefix A reference to the Prefix TLV. * - * @returns A pointer to the Context TLV is one is found or nullptr if no Context TLV exists. + * @returns A pointer to the Context TLV if one is found or nullptr if no Context TLV exists. * */ static const ContextTlv *FindContext(const PrefixTlv &aPrefix); @@ -472,9 +511,9 @@ protected: * This method returns a pointer to a Prefix TLV. * * @param[in] aPrefix A pointer to an IPv6 prefix. - * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix. + * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits). * - * @returns A pointer to the Prefix TLV is one is found or nullptr if no matching Prefix TLV exists. + * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists. * */ PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) @@ -486,13 +525,36 @@ protected: * This method returns a pointer to a Prefix TLV. * * @param[in] aPrefix A pointer to an IPv6 prefix. - * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix. + * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits). * - * @returns A pointer to the Prefix TLV is one is found or nullptr if no matching Prefix TLV exists. + * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists. * */ const PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const; + /** + * This method returns a pointer to a Prefix TLV. + * + * @param[in] aPrefix An IPv6 prefix. + * + * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists. + * + */ + PrefixTlv *FindPrefix(const Ip6::Prefix &aPrefix) { return FindPrefix(aPrefix.GetBytes(), aPrefix.GetLength()); } + + /** + * This method returns a pointer to a Prefix TLV. + * + * @param[in] aPrefix An IPv6 prefix. + * + * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists. + * + */ + const PrefixTlv *FindPrefix(const Ip6::Prefix &aPrefix) const + { + return FindPrefix(aPrefix.GetBytes(), aPrefix.GetLength()); + } + /** * This method returns a pointer to a Prefix TLV in a specified tlvs buffer. * @@ -501,7 +563,7 @@ protected: * @param[in] aTlvs A pointer to a specified tlvs buffer. * @param[in] aTlvsLength The specified tlvs buffer length pointed to by @p aTlvs. * - * @returns A pointer to the Prefix TLV is one is found or nullptr if no matching Prefix TLV exists. + * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists. * */ static PrefixTlv *FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, uint8_t *aTlvs, uint8_t aTlvsLength) @@ -518,7 +580,7 @@ protected: * @param[in] aTlvs A pointer to a specified tlvs buffer. * @param[in] aTlvsLength The specified tlvs buffer length pointed to by @p aTlvs. * - * @returns A pointer to the Prefix TLV is one is found or nullptr if no matching Prefix TLV exists. + * @returns A pointer to the Prefix TLV if one is found or nullptr if no matching Prefix TLV exists. * */ static const PrefixTlv *FindPrefix(const uint8_t *aPrefix, @@ -533,7 +595,7 @@ protected: * @param[in] aServiceData A pointer to a Service Data. * @param[in] aServiceDataLength The Service Data length pointed to by @p aServiceData. * - * @returns A pointer to the Service TLV is one is found or nullptr if no matching Service TLV exists. + * @returns A pointer to the Service TLV if one is found or nullptr if no matching Service TLV exists. * */ ServiceTlv *FindService(uint32_t aEnterpriseNumber, const uint8_t *aServiceData, uint8_t aServiceDataLength) @@ -549,7 +611,7 @@ protected: * @param[in] aServiceData A pointer to a Service Data. * @param[in] aServiceDataLength The Service Data length pointed to by @p aServiceData. * - * @returns A pointer to the Service TLV is one is found or nullptr if no matching Service TLV exists. + * @returns A pointer to the Service TLV if one is found or nullptr if no matching Service TLV exists. * */ const ServiceTlv *FindService(uint32_t aEnterpriseNumber, @@ -565,7 +627,7 @@ protected: * @param[in] aTlvs A pointer to a specified tlvs buffer. * @param[in] aTlvsLength The specified tlvs buffer length pointed to by @p aTlvs. * - * @returns A pointer to the Service TLV is one is found or nullptr if no matching Service TLV exists. + * @returns A pointer to the Service TLV if one is found or nullptr if no matching Service TLV exists. * */ static ServiceTlv *FindService(uint32_t aEnterpriseNumber, @@ -587,7 +649,7 @@ protected: * @param[in] aTlvs A pointer to a specified tlvs buffer. * @param[in] aTlvsLength The specified tlvs buffer length pointed to by @p aTlvs. * - * @returns A pointer to the Service TLV is one is found or nullptr if no matching Service TLV exists. + * @returns A pointer to the Service TLV if one is found or nullptr if no matching Service TLV exists. * */ static const ServiceTlv *FindService(uint32_t aEnterpriseNumber, @@ -658,18 +720,6 @@ protected: */ static void RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength); - /** - * This method computes the number of IPv6 Prefix bits that match. - * - * @param[in] a A pointer to the first IPv6 Prefix. - * @param[in] b A pointer to the second IPv6 prefix. - * @param[in] aLength The maximum length in bits to compare. - * - * @returns The number of matching bits. - * - */ - static int8_t PrefixMatch(const uint8_t *a, const uint8_t *b, uint8_t aLength); - /** * This method sends a Server Data Notification message to the Leader. * diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 4497f3797..ed36817ad 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -73,9 +73,9 @@ otError LeaderBase::GetServiceId(uint32_t aEnterpriseNumber, bool aServerStable, uint8_t & aServiceId) const { - otError error = OT_ERROR_NOT_FOUND; - Iterator iterator = kIteratorInit; - otServiceConfig serviceConfig; + otError error = OT_ERROR_NOT_FOUND; + Iterator iterator = kIteratorInit; + ServiceConfig serviceConfig; while (GetNextService(iterator, serviceConfig) == OT_ERROR_NONE) { @@ -140,19 +140,19 @@ exit: const PrefixTlv *LeaderBase::FindNextMatchingPrefix(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const { - const PrefixTlv *prefix; + const PrefixTlv *prefixTlv; for (const NetworkDataTlv *start = (aPrevTlv == nullptr) ? GetTlvsStart() : aPrevTlv->GetNext(); - (prefix = FindTlv(start, GetTlvsEnd())) != nullptr; start = prefix->GetNext()) + (prefixTlv = FindTlv(start, GetTlvsEnd())) != nullptr; start = prefixTlv->GetNext()) { - if (PrefixMatch(prefix->GetPrefix(), aAddress.mFields.m8, prefix->GetPrefixLength()) >= 0) + if (aAddress.MatchesPrefix(prefixTlv->GetPrefix(), prefixTlv->GetPrefixLength())) { ExitNow(); } } exit: - return prefix; + return prefixTlv; } otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) const @@ -160,12 +160,11 @@ otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aC const PrefixTlv * prefix = nullptr; const ContextTlv *contextTlv; - aContext.mPrefixLength = 0; + aContext.mPrefix.SetLength(0); if (Get().IsMeshLocalAddress(aAddress)) { - aContext.mPrefix = Get().GetMeshLocalPrefix().m8; - aContext.mPrefixLength = Mle::MeshLocalPrefix::kLength; + aContext.mPrefix.Set(Get().GetMeshLocalPrefix()); aContext.mContextId = Mle::kMeshLocalPrefixContextId; aContext.mCompressFlag = true; } @@ -179,16 +178,15 @@ otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aC continue; } - if (prefix->GetPrefixLength() > aContext.mPrefixLength) + if (prefix->GetPrefixLength() > aContext.mPrefix.GetLength()) { - aContext.mPrefix = prefix->GetPrefix(); - aContext.mPrefixLength = prefix->GetPrefixLength(); + aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength()); aContext.mContextId = contextTlv->GetContextId(); aContext.mCompressFlag = contextTlv->IsCompress(); } } - return (aContext.mPrefixLength > 0) ? OT_ERROR_NONE : OT_ERROR_NOT_FOUND; + return (aContext.mPrefix.GetLength() > 0) ? OT_ERROR_NONE : OT_ERROR_NOT_FOUND; } otError LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const @@ -198,8 +196,7 @@ otError LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) co if (aContextId == Mle::kMeshLocalPrefixContextId) { - aContext.mPrefix = Get().GetMeshLocalPrefix().m8; - aContext.mPrefixLength = Mle::MeshLocalPrefix::kLength; + aContext.mPrefix.Set(Get().GetMeshLocalPrefix()); aContext.mContextId = Mle::kMeshLocalPrefixContextId; aContext.mCompressFlag = true; ExitNow(error = OT_ERROR_NONE); @@ -215,8 +212,7 @@ otError LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) co continue; } - aContext.mPrefix = prefix->GetPrefix(); - aContext.mPrefixLength = prefix->GetPrefixLength(); + aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength()); aContext.mContextId = contextTlv->GetContextId(); aContext.mCompressFlag = contextTlv->IsCompress(); ExitNow(error = OT_ERROR_NONE); @@ -238,8 +234,7 @@ otError LeaderBase::GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16) co while (GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE) { - if (otIp6PrefixMatch(&(config.mPrefix.mPrefix), reinterpret_cast( - lowpanContext.mPrefix)) >= config.mPrefix.mLength) + if (lowpanContext.mPrefix.ContainsPrefix(config.GetPrefix())) { aRloc16 = config.mRloc16; ExitNow(error = OT_ERROR_NONE); @@ -287,7 +282,7 @@ exit: otError LeaderBase::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, - uint8_t * aPrefixMatch, + uint8_t * aPrefixMatchLength, uint16_t * aRloc16) const { otError error = OT_ERROR_NO_ROUTE; @@ -295,16 +290,16 @@ otError LeaderBase::RouteLookup(const Ip6::Address &aSource, while ((prefix = FindNextMatchingPrefix(aSource, prefix)) != nullptr) { - if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatch, aRloc16) == OT_ERROR_NONE) + if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatchLength, aRloc16) == OT_ERROR_NONE) { ExitNow(error = OT_ERROR_NONE); } if (DefaultRouteLookup(*prefix, aRloc16) == OT_ERROR_NONE) { - if (aPrefixMatch) + if (aPrefixMatchLength) { - *aPrefixMatch = 0; + *aPrefixMatchLength = 0; } ExitNow(error = OT_ERROR_NONE); @@ -317,62 +312,66 @@ exit: otError LeaderBase::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, - uint8_t * aPrefixMatch, + uint8_t * aPrefixMatchLength, uint16_t * aRloc16) const { otError error = OT_ERROR_NO_ROUTE; - const PrefixTlv * prefix; - const HasRouteEntry *rvalRoute = nullptr; - uint8_t rval_plen = 0; + const PrefixTlv * prefixTlv; + const HasRouteEntry *bestRouteEntry = nullptr; + uint8_t bestMatchLength = 0; - for (const NetworkDataTlv *start = GetTlvsStart(); (prefix = FindTlv(start, GetTlvsEnd())) != nullptr; - start = prefix->GetNext()) + for (const NetworkDataTlv *start = GetTlvsStart(); (prefixTlv = FindTlv(start, GetTlvsEnd())) != nullptr; + start = prefixTlv->GetNext()) { const HasRouteTlv *hasRoute; - int8_t plen; + uint8_t prefixLength = prefixTlv->GetPrefixLength(); - if (prefix->GetDomainId() != aDomainId) + if (prefixTlv->GetDomainId() != aDomainId) { continue; } - plen = PrefixMatch(prefix->GetPrefix(), aDestination.mFields.m8, prefix->GetPrefixLength()); - - if (plen <= rval_plen) + if (!aDestination.MatchesPrefix(prefixTlv->GetPrefix(), prefixLength)) { continue; } - for (const NetworkDataTlv *subStart = prefix->GetSubTlvs(); - (hasRoute = FindTlv(subStart, prefix->GetNext())) != nullptr; subStart = hasRoute->GetNext()) + if (prefixLength <= bestMatchLength) + { + continue; + } + + for (const NetworkDataTlv *subStart = prefixTlv->GetSubTlvs(); + (hasRoute = FindTlv(subStart, prefixTlv->GetNext())) != nullptr; + subStart = hasRoute->GetNext()) { for (const HasRouteEntry *entry = hasRoute->GetFirstEntry(); entry <= hasRoute->GetLastEntry(); entry = entry->GetNext()) { - if (rvalRoute == nullptr || entry->GetPreference() > rvalRoute->GetPreference() || - (entry->GetPreference() == rvalRoute->GetPreference() && + if (bestRouteEntry == nullptr || entry->GetPreference() > bestRouteEntry->GetPreference() || + (entry->GetPreference() == bestRouteEntry->GetPreference() && (entry->GetRloc() == Get().GetRloc16() || - (rvalRoute->GetRloc() != Get().GetRloc16() && + (bestRouteEntry->GetRloc() != Get().GetRloc16() && Get().GetCost(entry->GetRloc()) < - Get().GetCost(rvalRoute->GetRloc()))))) + Get().GetCost(bestRouteEntry->GetRloc()))))) { - rvalRoute = entry; - rval_plen = static_cast(plen); + bestRouteEntry = entry; + bestMatchLength = prefixLength; } } } } - if (rvalRoute != nullptr) + if (bestRouteEntry != nullptr) { if (aRloc16 != nullptr) { - *aRloc16 = rvalRoute->GetRloc(); + *aRloc16 = bestRouteEntry->GetRloc(); } - if (aPrefixMatch != nullptr) + if (aPrefixMatchLength != nullptr) { - *aPrefixMatch = rval_plen; + *aPrefixMatchLength = bestMatchLength; } error = OT_ERROR_NONE; diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp index 2120ccbb1..774d58608 100644 --- a/src/core/thread/network_data_leader.hpp +++ b/src/core/thread/network_data_leader.hpp @@ -137,10 +137,10 @@ public: /** * This method performs a route lookup using the Network Data. * - * @param[in] aSource A reference to the IPv6 source address. - * @param[in] aDestination A reference to the IPv6 destination address. - * @param[out] aPrefixMatch A pointer to the longest prefix match length in bits. - * @param[out] aRloc16 A pointer to the RLOC16 for the selected route. + * @param[in] aSource A reference to the IPv6 source address. + * @param[in] aDestination A reference to the IPv6 destination address. + * @param[out] aPrefixMatchLength A pointer to output the longest prefix match length in bits. + * @param[out] aRloc16 A pointer to the RLOC16 for the selected route. * * @retval OT_ERROR_NONE Successfully found a route. * @retval OT_ERROR_NO_ROUTE No valid route was found. @@ -148,7 +148,7 @@ public: */ otError RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination, - uint8_t * aPrefixMatch, + uint8_t * aPrefixMatchLength, uint16_t * aRloc16) const; /** @@ -300,7 +300,7 @@ private: otError ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination, - uint8_t * aPrefixMatch, + uint8_t * aPrefixMatchLength, uint16_t * aRloc16) const; otError DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const; }; diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp index a65ad8a6d..8b39b6b34 100644 --- a/src/core/thread/network_data_local.cpp +++ b/src/core/thread/network_data_local.cpp @@ -100,38 +100,37 @@ otError Local::AddOnMeshPrefix(const OnMeshPrefixConfig &aConfig) } #endif - return AddPrefix(aConfig.mPrefix.mPrefix.mFields.m8, aConfig.mPrefix.mLength, NetworkDataTlv::kTypeBorderRouter, - aConfig.mPreference, flags, aConfig.mStable); + return AddPrefix(aConfig.GetPrefix(), NetworkDataTlv::kTypeBorderRouter, aConfig.mPreference, flags, + aConfig.mStable); } -otError Local::RemoveOnMeshPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) +otError Local::RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix) { - return RemovePrefix(aPrefix, aPrefixLength, NetworkDataTlv::kTypeBorderRouter); + return RemovePrefix(aPrefix, NetworkDataTlv::kTypeBorderRouter); } -otError Local::AddHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, bool aStable) +otError Local::AddHasRoutePrefix(const ExternalRouteConfig &aConfig) { - return AddPrefix(aPrefix, aPrefixLength, NetworkDataTlv::kTypeHasRoute, aPrf, /* aFlags */ 0, aStable); + return AddPrefix(aConfig.GetPrefix(), NetworkDataTlv::kTypeHasRoute, aConfig.mPreference, /* aFlags */ 0, + aConfig.mStable); } -otError Local::RemoveHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) +otError Local::RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix) { - return RemovePrefix(aPrefix, aPrefixLength, NetworkDataTlv::kTypeHasRoute); + return RemovePrefix(aPrefix, NetworkDataTlv::kTypeHasRoute); } -otError Local::AddPrefix(const uint8_t * aPrefix, - uint8_t aPrefixLength, +otError Local::AddPrefix(const Ip6::Prefix & aPrefix, NetworkDataTlv::Type aSubTlvType, int8_t aPrf, uint16_t aFlags, bool aStable) { - otError error = OT_ERROR_NONE; - uint8_t prefixLengthBytes = BitVectorBytes(aPrefixLength); + otError error = OT_ERROR_NONE; uint8_t subTlvLength; PrefixTlv *prefixTlv; - VerifyOrExit(aPrefixLength > 0 && prefixLengthBytes <= sizeof(Ip6::Address), error = OT_ERROR_INVALID_ARGS); + VerifyOrExit((aPrefix.GetLength() > 0) && aPrefix.IsValid(), error = OT_ERROR_INVALID_ARGS); switch (aPrf) { @@ -143,20 +142,18 @@ otError Local::AddPrefix(const uint8_t * aPrefix, ExitNow(error = OT_ERROR_INVALID_ARGS); } - VerifyOrExit(Ip6::Address::PrefixMatch(aPrefix, Get().GetMeshLocalPrefix().m8, prefixLengthBytes) < - Mle::MeshLocalPrefix::kLength, - error = OT_ERROR_INVALID_ARGS); + VerifyOrExit(!aPrefix.ContainsPrefix(Get().GetMeshLocalPrefix()), error = OT_ERROR_INVALID_ARGS); - IgnoreError(RemovePrefix(aPrefix, aPrefixLength, aSubTlvType)); + IgnoreError(RemovePrefix(aPrefix, aSubTlvType)); subTlvLength = (aSubTlvType == NetworkDataTlv::kTypeBorderRouter) ? sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry) : sizeof(HasRouteTlv) + sizeof(HasRouteEntry); - prefixTlv = static_cast(AppendTlv(sizeof(PrefixTlv) + prefixLengthBytes + subTlvLength)); + prefixTlv = static_cast(AppendTlv(sizeof(PrefixTlv) + aPrefix.GetBytesSize() + subTlvLength)); VerifyOrExit(prefixTlv != nullptr, error = OT_ERROR_NO_BUFS); - prefixTlv->Init(0, aPrefixLength, aPrefix); + prefixTlv->Init(0, aPrefix); prefixTlv->SetSubTlvsLength(subTlvLength); if (aSubTlvType == NetworkDataTlv::kTypeBorderRouter) @@ -189,12 +186,12 @@ exit: return error; } -otError Local::RemovePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, NetworkDataTlv::Type aSubTlvType) +otError Local::RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType) { otError error = OT_ERROR_NONE; PrefixTlv *tlv; - VerifyOrExit((tlv = FindPrefix(aPrefix, aPrefixLength)) != nullptr, error = OT_ERROR_NOT_FOUND); + VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr, error = OT_ERROR_NOT_FOUND); VerifyOrExit(FindTlv(tlv->GetSubTlvs(), tlv->GetNext(), aSubTlvType) != nullptr, error = OT_ERROR_NOT_FOUND); RemoveTlv(tlv); @@ -203,11 +200,11 @@ exit: return error; } -void Local::UpdateRloc(PrefixTlv &aPrefix) +void Local::UpdateRloc(PrefixTlv &aPrefixTlv) { uint16_t rloc16 = Get().GetRloc16(); - for (NetworkDataTlv *cur = aPrefix.GetSubTlvs(); cur < aPrefix.GetNext(); cur = cur->GetNext()) + for (NetworkDataTlv *cur = aPrefixTlv.GetSubTlvs(); cur < aPrefixTlv.GetNext(); cur = cur->GetNext()) { switch (cur->GetType()) { diff --git a/src/core/thread/network_data_local.hpp b/src/core/thread/network_data_local.hpp index 025bee5f6..2242fcb99 100644 --- a/src/core/thread/network_data_local.hpp +++ b/src/core/thread/network_data_local.hpp @@ -85,40 +85,35 @@ public: /** * This method removes a Border Router entry from the Thread Network Data. * - * @param[in] aPrefix A pointer to the prefix. - * @param[in] aPrefixLength The prefix length in bits. + * @param[in] aPrefix The Prefix to remove. * * @retval OT_ERROR_NONE Successfully removed the Border Router entry. * @retval OT_ERROR_NOT_FOUND Could not find the Border Router entry. * */ - otError RemoveOnMeshPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength); + otError RemoveOnMeshPrefix(const Ip6::Prefix &aPrefix); /** * This method adds a Has Route entry to the Thread Network data. * - * @param[in] aPrefix A pointer to the prefix. - * @param[in] aPrefixLength The prefix length in bits. - * @param[in] aPrf The preference value. - * @param[in] aStable The Stable value. + * @param[in] aConfig A reference to the external route configuration. * * @retval OT_ERROR_NONE Successfully added the Has Route entry. * @retval OT_ERROR_NO_BUFS Insufficient space to add the Has Route entry. * */ - otError AddHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, bool aStable); + otError AddHasRoutePrefix(const ExternalRouteConfig &aConfig); /** * This method removes a Border Router entry from the Thread Network Data. * - * @param[in] aPrefix A pointer to the prefix. - * @param[in] aPrefixLength The prefix length in bits. + * @param[in] aPrefix The Prefix to remove. * * @retval OT_ERROR_NONE Successfully removed the Border Router entry. * @retval OT_ERROR_NOT_FOUND Could not find the Border Router entry. * */ - otError RemoveHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength); + otError RemoveHasRoutePrefix(const Ip6::Prefix &aPrefix); #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE @@ -174,14 +169,13 @@ public: private: void UpdateRloc(void); #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE - otError AddPrefix(const uint8_t * aPrefix, - uint8_t aPrefixLength, + otError AddPrefix(const Ip6::Prefix & aPrefix, NetworkDataTlv::Type aSubTlvType, int8_t aPrf, uint16_t aFlags, bool aStable); - otError RemovePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, NetworkDataTlv::Type aSubTlvType); - void UpdateRloc(PrefixTlv &aPrefix); + otError RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType); + void UpdateRloc(PrefixTlv &aPrefixTlv); bool IsOnMeshPrefixConsistent(void) const; bool IsExternalRouteConsistent(void) const; #endif diff --git a/src/core/thread/network_data_tlvs.hpp b/src/core/thread/network_data_tlvs.hpp index a93ffd61c..ed01d0036 100644 --- a/src/core/thread/network_data_tlvs.hpp +++ b/src/core/thread/network_data_tlvs.hpp @@ -429,10 +429,22 @@ public: SetType(kTypePrefix); mDomainId = aDomainId; mPrefixLength = aPrefixLength; - memcpy(GetPrefix(), aPrefix, BitVectorBytes(aPrefixLength)); + memcpy(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength)); SetSubTlvsLength(0); } + /** + * This method initializes the TLV. + * + * @param[in] aDomainId The Domain ID. + * @param[in] aPrefix The Prefix. + * + */ + void Init(uint8_t aDomainId, const Ip6::Prefix aPrefix) + { + Init(aDomainId, aPrefix.GetLength(), aPrefix.GetBytes()); + } + /** * This method indicates whether or not the TLV appears to be well-formed. * @@ -443,8 +455,8 @@ public: bool IsValid(void) const { return ((GetLength() >= sizeof(*this) - sizeof(NetworkDataTlv)) && - (GetLength() >= BitVectorBytes(mPrefixLength) + sizeof(*this) - sizeof(NetworkDataTlv)) && - (BitVectorBytes(mPrefixLength) <= sizeof(Ip6::Address))); + (GetLength() >= Ip6::Prefix::SizeForLength(mPrefixLength) + sizeof(*this) - sizeof(NetworkDataTlv)) && + (Ip6::Prefix::SizeForLength(mPrefixLength) <= sizeof(Ip6::Address))); } /** @@ -479,6 +491,42 @@ public: */ const uint8_t *GetPrefix(void) const { return reinterpret_cast(this) + sizeof(*this); } + /** + * This method copies the Prefix from TLV into a given `Ip6::Prefix`. + * + * @param[out] aPrefix An `Ip6::Prefix` to copy the Prefix from TLV into. + * + */ + void CopyPrefixTo(Ip6::Prefix &aPrefix) const { aPrefix.Set(GetPrefix(), GetPrefixLength()); } + + /** + * This method indicates whether the Prefix from TLV is equal to a given `Ip6::Prefix`. + * + * @param[in] aPrefix A Prefix to compare with. + * + * @retval TRUE The TLV's Prefix is equal to @p aPrefix. + * @retval FALSE The TLV's Prefix is not equal to @p aPrefix. + * + */ + bool IsEqual(Ip6::Prefix &aPrefix) const { return aPrefix.IsEqual(GetPrefix(), GetPrefixLength()); } + + /** + * This method indicates whether the Prefix from TLV is equal to a given Prefix. + * + * @param[in] aPrefix A pointer to an IPv6 prefix to compare with. + * @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits). + * + * @retval TRUE The TLV's Prefix is equal to @p aPrefix. + * @retval FALSE The TLV's Prefix is not euqal @p aPrefix. + * + */ + bool IsEqual(const uint8_t *aPrefix, uint8_t aPrefixLength) const + { + return (aPrefixLength == mPrefixLength) && + (Ip6::Prefix::MatchLength(GetPrefix(), aPrefix, Ip6::Prefix::SizeForLength(aPrefixLength)) >= + mPrefixLength); + } + /** * This method returns a pointer to the Sub-TLVs. * @@ -487,7 +535,7 @@ public: */ NetworkDataTlv *GetSubTlvs(void) { - return reinterpret_cast(GetPrefix() + BitVectorBytes(mPrefixLength)); + return reinterpret_cast(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength)); } /** @@ -498,7 +546,7 @@ public: */ const NetworkDataTlv *GetSubTlvs(void) const { - return reinterpret_cast(GetPrefix() + BitVectorBytes(mPrefixLength)); + return reinterpret_cast(GetPrefix() + Ip6::Prefix::SizeForLength(mPrefixLength)); } /** @@ -509,7 +557,7 @@ public: */ uint8_t GetSubTlvsLength(void) const { - return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv) + BitVectorBytes(mPrefixLength)); + return GetLength() - (sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength)); } /** @@ -520,7 +568,7 @@ public: */ void SetSubTlvsLength(uint8_t aLength) { - SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + BitVectorBytes(mPrefixLength) + aLength); + SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength) + aLength); } /** @@ -534,7 +582,10 @@ public: * @returns The size (number of bytes) of the Prefix TLV. * */ - static uint16_t CalculateSize(uint8_t aPrefixLength) { return sizeof(PrefixTlv) + BitVectorBytes(aPrefixLength); } + static uint16_t CalculateSize(uint8_t aPrefixLength) + { + return sizeof(PrefixTlv) + Ip6::Prefix::SizeForLength(aPrefixLength); + } private: uint8_t mDomainId; diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp index 4971f386b..7af3c1e97 100644 --- a/src/core/utils/slaac_address.cpp +++ b/src/core/utils/slaac_address.cpp @@ -94,7 +94,7 @@ exit: return; } -bool Slaac::ShouldFilter(const otIp6Prefix &aPrefix) const +bool Slaac::ShouldFilter(const Ip6::Prefix &aPrefix) const { return (mFilter != nullptr) && mFilter(&GetInstance(), &aPrefix); } @@ -143,7 +143,7 @@ bool Slaac::DoesConfigMatchNetifAddr(const NetworkData::OnMeshPrefixConfig &aCon { return (((aConfig.mOnMesh && (aAddr.mPrefixLength == aConfig.mPrefix.mLength)) || (!aConfig.mOnMesh && (aAddr.mPrefixLength == 128))) && - (aAddr.GetAddress().PrefixMatch(aConfig.mPrefix.mPrefix) >= aConfig.mPrefix.mLength)); + (aAddr.GetAddress().MatchesPrefix(aConfig.GetPrefix()))); } void Slaac::Update(UpdateMode aMode) @@ -179,7 +179,8 @@ void Slaac::Update(UpdateMode aMode) continue; } - if (config.mSlaac && !ShouldFilter(config.mPrefix) && DoesConfigMatchNetifAddr(config, *slaacAddr)) + if (config.mSlaac && !ShouldFilter(config.GetPrefix()) && + DoesConfigMatchNetifAddr(config, *slaacAddr)) { found = true; break; @@ -205,7 +206,7 @@ void Slaac::Update(UpdateMode aMode) while (Get().GetNextOnMeshPrefix(iterator, config) == OT_ERROR_NONE) { - otIp6Prefix &prefix = config.mPrefix; + Ip6::Prefix &prefix = config.GetPrefix(); if (config.mDp || !config.mSlaac || ShouldFilter(prefix)) { @@ -236,7 +237,7 @@ void Slaac::Update(UpdateMode aMode) } slaacAddr->Clear(); - memcpy(&slaacAddr->mAddress, &prefix.mPrefix, BitVectorBytes(prefix.mLength)); + slaacAddr->GetAddress().SetPrefix(prefix); slaacAddr->mPrefixLength = config.mOnMesh ? prefix.mLength : 128; slaacAddr->mAddressOrigin = OT_ADDRESS_ORIGIN_SLAAC; diff --git a/src/core/utils/slaac_address.hpp b/src/core/utils/slaac_address.hpp index 3c035cec3..b122112a6 100644 --- a/src/core/utils/slaac_address.hpp +++ b/src/core/utils/slaac_address.hpp @@ -159,7 +159,7 @@ private: typedef uint8_t UpdateMode; - bool ShouldFilter(const otIp6Prefix &aPrefix) const; + bool ShouldFilter(const Ip6::Prefix &aPrefix) const; void Update(UpdateMode aMode); void GetIidSecretKey(IidSecretKey &aKey) const; static void HandleNotifierEvents(Notifier::Receiver &aReceiver, Events aEvents); diff --git a/tests/unit/test_ip6_address.cpp b/tests/unit/test_ip6_address.cpp index 42f8449e9..db4f39908 100644 --- a/tests/unit/test_ip6_address.cpp +++ b/tests/unit/test_ip6_address.cpp @@ -217,10 +217,68 @@ void TestIp6AddressSetPrefix(void) } } +void TestIp6Prefix(void) +{ + const uint8_t kPrefixes[][OT_IP6_ADDRESS_SIZE] = { + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, + {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + }; + + ot::Ip6::Prefix prefix; + ot::Ip6::Address address1, address2; + + for (auto prefixBytes : kPrefixes) + { + memcpy(address1.mFields.m8, prefixBytes, sizeof(address1)); + address2 = address1; + address2.mFields.m8[0] ^= 0x80; // Change first bit. + + for (uint8_t prefixLength = 1; prefixLength <= ot::Ip6::Prefix::kMaxLength; prefixLength++) + { + prefix.Set(prefixBytes, prefixLength); + + printf("Prefix %s\n", prefix.ToString().AsCString()); + + VerifyOrQuit(prefix.GetLength() == prefixLength, "Prefix::GetLength() failed"); + VerifyOrQuit(prefix.IsValid(), "Prefix::IsValid() failed"); + VerifyOrQuit(prefix.IsEqual(prefixBytes, prefixLength), "Prefix::IsEqual() failed"); + + VerifyOrQuit(address1.MatchesPrefix(prefix), "Address::MatchesPrefix() failed"); + VerifyOrQuit(!address2.MatchesPrefix(prefix), "Address::MatchedPrefix() failed"); + + VerifyOrQuit(prefix == prefix, "Prefix::operator==() failed"); + + for (uint8_t subPrefixLength = 1; subPrefixLength <= prefixLength; subPrefixLength++) + { + ot::Ip6::Prefix subPrefix; + + subPrefix.Set(prefixBytes, subPrefixLength); + + VerifyOrQuit(prefix.ContainsPrefix(subPrefix), "Prefix::ContainsPrefix() failed"); + + if (prefixLength == subPrefixLength) + { + VerifyOrQuit(prefix == subPrefix, "Prefix::operator==() failed"); + VerifyOrQuit(prefix.IsEqual(subPrefix.GetBytes(), subPrefix.GetLength()), + "Prefix::IsEqual() failed"); + } + else + { + VerifyOrQuit(prefix != subPrefix, "Prefix::operator!= failed"); + VerifyOrQuit(!prefix.IsEqual(subPrefix.GetBytes(), subPrefix.GetLength()), + "Prefix::IsEqual() failed"); + } + } + } + } +} + int main(void) { TestIp6AddressSetPrefix(); TestIp6AddressFromString(); + TestIp6Prefix(); printf("All tests passed\n"); return 0; } diff --git a/tests/unit/test_network_data.cpp b/tests/unit/test_network_data.cpp index 534a6be34..accc48cc1 100644 --- a/tests/unit/test_network_data.cpp +++ b/tests/unit/test_network_data.cpp @@ -63,7 +63,7 @@ void PrintExternalRouteConfig(const ExternalRouteConfig &aConfig) } // Returns true if the two given ExternalRouteConfig match (intentionally ignoring mNextHopIsThisDevice). -bool CompareExternalRouteConfig(const ExternalRouteConfig &aConfig1, const ExternalRouteConfig &aConfig2) +bool CompareExternalRouteConfig(const otExternalRouteConfig &aConfig1, const otExternalRouteConfig &aConfig2) { return (memcmp(aConfig1.mPrefix.mPrefix.mFields.m8, aConfig2.mPrefix.mPrefix.mFields.m8, sizeof(aConfig1.mPrefix.mPrefix)) == 0) && @@ -85,7 +85,7 @@ void TestNetworkDataIterator(void) 0xFD, 0x00, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC8, 0x00, 0x40, 0x01, 0x03, 0x54, 0x00, 0x00}; - ExternalRouteConfig routes[] = { + otExternalRouteConfig routes[] = { { {{{{0xfd, 0x00, 0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, 64}, @@ -126,7 +126,7 @@ void TestNetworkDataIterator(void) 0x31, 0x00, 0x02, 0x0F, 0x00, 0x40, 0xFD, 0x00, 0xAB, 0xBA, 0xCD, 0xDC, 0x00, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x03, 0x0E, 0x00, 0x20, 0xFD, 0x00, 0xAB, 0xBA, 0x01, 0x06, 0x54, 0x00, 0x00, 0x04, 0x00, 0x00}; - ExternalRouteConfig routes[] = { + otExternalRouteConfig routes[] = { {{{{{0xfd, 0x00, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}}, 64}, 0x1000, 1,