[network-data] adding helper methods, simplify code (#4743)

This commit contains the following changes in `NetworkData` modules:

- Add helper `FindTlv()` and template version `FindTlv<TlvType>()` 
  methods to search within a sequence of TLVs to find a TLV with a 
  given type (and/or stable  status).
- Add methods to help with iterating over Network Data content 
  (`FindTlv`, `IterateToNextTlv()`, etc).
- Add `AppendTlv()` and `RemoveTlv()` helper methods to simplify 
  adding and removing of entire TLV from Network Data.
- Change `PrefixMatch()` to use `Ip6::Address` method.
- Simplify and fix `RemoveTemporaryData()` (use cast to get the 
  sub-TLV during iteration).
- Simplify `GetNextServer()` implementation to use other methods to 
  iterate over all on-mesh prefix, external route, and service 
  entries in Network Data. 
- Simplify the `Local::UpdateRloc()` implementation.  
- Add `Local::AddPrefix()` and `Local::RemovePrefix()` methods to 
  share common code for adding on-mesh or external route entries.
- Add helper `GetTlvsStart()`/`GetTlvsEnd()` to get the start/end 
  of Network Data TLV sequence.
This commit is contained in:
Abtin Keshavarzian
2020-03-30 12:21:20 -07:00
committed by GitHub
parent f8de062657
commit eb5b3a41a9
8 changed files with 683 additions and 874 deletions
File diff suppressed because it is too large Load Diff
+151 -6
View File
@@ -323,6 +323,22 @@ public:
void ClearResubmitDelayTimer(void);
protected:
/**
* This method returns a pointer to the start of Network Data TLV sequence.
*
* @returns A pointer to the start of Network Data TLV sequence.
*
*/
NetworkDataTlv *GetTlvsStart(void) { return reinterpret_cast<NetworkDataTlv *>(mTlvs); }
/**
* This method returns a pointer to the end of Network Data TLV sequence.
*
* @returns A pointer to the end of Network Data TLV sequence.
*
*/
NetworkDataTlv *GetTlvsEnd(void) { return reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); }
/**
* This method returns a pointer to the Border Router TLV within a given Prefix TLV.
*
@@ -337,7 +353,7 @@ protected:
* This method returns a pointer to the stable or non-stable Border Router TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
* @param[in] aStable TRUE if requesting a stable Border Router TLV, FALSE otherwise.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable..
*
* @returns A pointer to the Border Router TLV if one is found or NULL if no Border Router TLV exists.
*
@@ -358,7 +374,7 @@ protected:
* This method returns a pointer to the stable or non-stable Has Route TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
* @param[in] aStable TRUE if requesting a stable Has Route TLV, FALSE otherwise.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the Has Route TLV if one is found or NULL if no Has Route TLV exists.
*
@@ -429,6 +445,20 @@ protected:
uint8_t * aTlvs,
uint8_t aTlvsLength);
/**
* This method grows the Network Data to append a TLV with a requested size.
*
* On success, the returned TLV is not initialized (i.e., the TLV Length field is not set) but the requested
* size for it (@p aTlvSize number of bytes) is reserved in the Network Data.
*
* @param[in] aTlvSize The size of TLV (total number of bytes including Type, Length, and Value fields)
*
* @returns A pointer to the TLV if there is space to grow Network Data, or NULL if no space to grow the Network
* Data with requested @p aTlvSize number of bytes.
*
*/
NetworkDataTlv *AppendTlv(uint8_t aTlvSize);
/**
* This method inserts bytes into the Network Data.
*
@@ -436,16 +466,24 @@ protected:
* @param[in] aLength The number of bytes to insert.
*
*/
void Insert(uint8_t *aStart, uint8_t aLength);
void Insert(void *aStart, uint8_t aLength);
/**
* This method removes bytes from the Network Data.
*
* @param[in] aStart A pointer to the beginning of the removal.
* @param[in] aLength The number of bytes to remove.
* @param[in] aRemoveStart A pointer to the beginning of the removal.
* @param[in] aRemoveLength The number of bytes to remove.
*
*/
void Remove(uint8_t *aStart, uint8_t aLength);
void Remove(void *aRemoveStart, uint8_t aRemoveLength);
/**
* This method removes a TLV from the Network Data.
*
* @param[in] aTlv The TLV to remove.
*
*/
void RemoveTlv(NetworkDataTlv *aTlv);
/**
* This method strips non-stable data from the Thread Network Data.
@@ -502,6 +540,67 @@ protected:
*/
otError SendServerDataNotification(uint16_t aRloc16);
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
*
* @returns A pointer to the TLV if found, or NULL if not found.
*
*/
static NetworkDataTlv *FindTlv(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, NetworkDataTlv::Type aType);
/**
* This static template method searches in a given sequence of TLVs to find the first TLV with a give template
* `TlvType`.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
*
* @returns A pointer to the TLV if found, or NULL if not found.
*
*/
template <typename TlvType> static TlvType *FindTlv(NetworkDataTlv *aStart, NetworkDataTlv *aEnd)
{
return static_cast<TlvType *>(FindTlv(aStart, aEnd, static_cast<NetworkDataTlv::Type>(TlvType::kType)));
}
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type and stable
* flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param [in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or NULL if not found.
*
*/
static NetworkDataTlv *FindTlv(NetworkDataTlv * aStart,
NetworkDataTlv * aEnd,
NetworkDataTlv::Type aType,
bool aStable);
/**
* This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type and
* stable flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param [in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or NULL if not found.
*
*/
template <typename TlvType> static TlvType *FindTlv(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, bool aStable)
{
return static_cast<TlvType *>(
FindTlv(aStart, aEnd, static_cast<NetworkDataTlv::Type>(TlvType::kType), aStable));
}
uint8_t mTlvs[kMaxSize]; ///< The Network Data buffer.
uint8_t mLength; ///< The number of valid bytes in @var mTlvs.
@@ -516,6 +615,13 @@ private:
class NetworkDataIterator
{
public:
enum Type
{
kTypeOnMeshPrefix = 0,
kTypeExternalRoute = 1,
kTypeService = 2,
};
explicit NetworkDataIterator(Iterator &aIterator)
: mIteratorBuffer(reinterpret_cast<uint8_t *>(&aIterator))
{
@@ -524,9 +630,24 @@ private:
uint8_t GetTlvOffset(void) const { return mIteratorBuffer[kTlvPosition]; }
uint8_t GetSubTlvOffset(void) const { return mIteratorBuffer[kSubTlvPosition]; }
uint8_t GetEntryIndex(void) const { return mIteratorBuffer[kEntryPosition]; }
Type GetType(void) const { return static_cast<Type>(mIteratorBuffer[kTypePosition]); }
void SetTlvOffset(uint8_t aOffset) { mIteratorBuffer[kTlvPosition] = aOffset; }
void SetSubTlvOffset(uint8_t aOffset) { mIteratorBuffer[kSubTlvPosition] = aOffset; }
void SetEntryIndex(uint8_t aIndex) { mIteratorBuffer[kEntryPosition] = aIndex; }
void SetType(Type aType) { mIteratorBuffer[kTypePosition] = static_cast<uint8_t>(aType); }
bool IsNewEntry(void) const { return GetEntryIndex() == 0; }
void MarkEntryAsNotNew(void) { SetEntryIndex(1); }
NetworkDataTlv *GetTlv(uint8_t *aTlvs) const
{
return reinterpret_cast<NetworkDataTlv *>(aTlvs + GetTlvOffset());
}
NetworkDataTlv *GetSubTlv(NetworkDataTlv *aSubTlvs)
{
return reinterpret_cast<NetworkDataTlv *>(reinterpret_cast<uint8_t *>(aSubTlvs) + GetSubTlvOffset());
}
void SaveTlvOffset(const NetworkDataTlv *aTlv, const uint8_t *aTlvs)
{
@@ -545,11 +666,35 @@ private:
kTlvPosition = 0,
kSubTlvPosition = 1,
kEntryPosition = 2,
kTypePosition = 3,
};
uint8_t *mIteratorBuffer;
};
static void Remove(uint8_t *aData, uint8_t &aDataLength, uint8_t *aRemoveStart, uint8_t aRemoveLength);
static void RemoveTlv(uint8_t *aData, uint8_t &aDataLength, NetworkDataTlv *aTlv);
NetworkDataTlv *FindTlv(NetworkDataIterator &aIterator, NetworkDataTlv::Type aTlvType);
void IterateToNextTlv(NetworkDataIterator &aIterator);
NetworkDataTlv *FindSubTlv(NetworkDataIterator &aIterator,
NetworkDataTlv::Type aSubTlvType,
NetworkDataTlv * aSubTlvs,
NetworkDataTlv * aSubTlvsEnd);
void IterateToNextSubTlv(NetworkDataIterator &aIterator, NetworkDataTlv *aSubTlvs);
template <typename TlvType> TlvType *FindTlv(NetworkDataIterator &aIterator)
{
return static_cast<TlvType *>(FindTlv(aIterator, static_cast<NetworkDataTlv::Type>(TlvType::kType)));
}
template <typename TlvType>
TlvType *FindSubTlv(NetworkDataIterator &aIterator, NetworkDataTlv *aSubTlvs, NetworkDataTlv *aSubTlvsEnd)
{
return static_cast<TlvType *>(
FindSubTlv(aIterator, static_cast<NetworkDataTlv::Type>(TlvType::kType), aSubTlvs, aSubTlvsEnd));
}
const Type mType;
TimeMilli mLastAttempt;
};
+66 -108
View File
@@ -98,7 +98,7 @@ otError LeaderBase::GetBackboneRouterPrimary(BackboneRouter::BackboneRouterConfi
{
otError error = OT_ERROR_NOT_FOUND;
uint8_t serviceData = ServiceTlv::kServiceDataBackboneRouter;
const ServerTlv * rvalServerTlv = NULL;
ServerTlv * rvalServerTlv = NULL;
const BackboneRouterServerData *rvalServerData = NULL;
ServiceTlv * serviceTlv;
NetworkDataTlv * subCur;
@@ -106,24 +106,16 @@ otError LeaderBase::GetBackboneRouterPrimary(BackboneRouter::BackboneRouterConfi
serviceTlv = Get<Leader>().FindService(THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData));
if (serviceTlv == NULL)
{
aConfig.mServer16 = Mac::kShortAddrInvalid;
ExitNow();
}
VerifyOrExit(serviceTlv != NULL, aConfig.mServer16 = Mac::kShortAddrInvalid);
subCur = serviceTlv->GetSubTlvs();
subEnd = serviceTlv->GetNext();
while (subCur < subEnd)
while ((subCur = FindTlv(subCur, subEnd, NetworkDataTlv::kTypeServer)) != NULL)
{
ServerTlv * serverTlv;
const BackboneRouterServerData *serverData;
VerifyOrExit((subCur + 1) <= subEnd && subCur->GetNext() <= subEnd, error = OT_ERROR_PARSE);
serverTlv = static_cast<ServerTlv *>(subCur);
serverData = reinterpret_cast<const BackboneRouterServerData *>(serverTlv->GetServerData());
ServerTlv * serverTlv = static_cast<ServerTlv *>(subCur);
const BackboneRouterServerData *serverData =
reinterpret_cast<const BackboneRouterServerData *>(serverTlv->GetServerData());
if (rvalServerTlv == NULL ||
(serverTlv->GetServer16() == Mle::Mle::Rloc16FromRouterId(Get<Mle::MleRouter>().GetLeaderId())) ||
@@ -131,7 +123,7 @@ otError LeaderBase::GetBackboneRouterPrimary(BackboneRouter::BackboneRouterConfi
(serverData->GetSequenceNumber() == rvalServerData->GetSequenceNumber() &&
serverTlv->GetServer16() > rvalServerTlv->GetServer16()))
{
rvalServerTlv = const_cast<ServerTlv *>(serverTlv);
rvalServerTlv = serverTlv;
rvalServerData = serverData;
}
@@ -152,23 +144,12 @@ exit:
}
#endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext)
PrefixTlv *LeaderBase::FindNextMatchingPrefix(const Ip6::Address &aAddress, PrefixTlv *aPrevTlv)
{
PrefixTlv * prefix;
ContextTlv *contextTlv;
PrefixTlv * prefix;
NetworkDataTlv *start = (aPrevTlv == NULL) ? GetTlvsStart() : aPrevTlv->GetNext();
aContext.mPrefixLength = 0;
if (PrefixMatch(Get<Mle::MleRouter>().GetMeshLocalPrefix().m8, aAddress.mFields.m8, 64) >= 0)
{
aContext.mPrefix = Get<Mle::MleRouter>().GetMeshLocalPrefix().m8;
aContext.mPrefixLength = 64;
aContext.mContextId = Mle::kMeshLocalPrefixContextId;
aContext.mCompressFlag = true;
}
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
for (NetworkDataTlv *cur = start; cur < GetTlvsEnd(); cur = cur->GetNext())
{
if (cur->GetType() != NetworkDataTlv::kTypePrefix)
{
@@ -182,6 +163,32 @@ otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aC
continue;
}
ExitNow();
}
prefix = NULL;
exit:
return prefix;
}
otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext)
{
PrefixTlv * prefix = NULL;
ContextTlv *contextTlv;
aContext.mPrefixLength = 0;
if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
{
aContext.mPrefix = Get<Mle::MleRouter>().GetMeshLocalPrefix().m8;
aContext.mPrefixLength = Mle::MeshLocalPrefix::kLength;
aContext.mContextId = Mle::kMeshLocalPrefixContextId;
aContext.mCompressFlag = true;
}
while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != NULL)
{
contextTlv = FindContext(*prefix);
if (contextTlv == NULL)
@@ -210,14 +217,13 @@ otError LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext)
if (aContextId == Mle::kMeshLocalPrefixContextId)
{
aContext.mPrefix = Get<Mle::MleRouter>().GetMeshLocalPrefix().m8;
aContext.mPrefixLength = 64;
aContext.mPrefixLength = Mle::MeshLocalPrefix::kLength;
aContext.mContextId = Mle::kMeshLocalPrefixContextId;
aContext.mCompressFlag = true;
ExitNow(error = OT_ERROR_NONE);
}
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
for (NetworkDataTlv *cur = GetTlvsStart(); cur < GetTlvsEnd(); cur = cur->GetNext())
{
if (cur->GetType() != NetworkDataTlv::kTypePrefix)
{
@@ -275,29 +281,13 @@ exit:
bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress)
{
PrefixTlv *prefix;
bool rval = false;
PrefixTlv *prefix = NULL;
bool rval = false;
if (memcmp(aAddress.mFields.m8, Get<Mle::MleRouter>().GetMeshLocalPrefix().m8, sizeof(otMeshLocalPrefix)) == 0)
VerifyOrExit(!Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress), rval = true);
while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != NULL)
{
ExitNow(rval = true);
}
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
{
if (cur->GetType() != NetworkDataTlv::kTypePrefix)
{
continue;
}
prefix = static_cast<PrefixTlv *>(cur);
if (PrefixMatch(prefix->GetPrefix(), aAddress.mFields.m8, prefix->GetPrefixLength()) < 0)
{
continue;
}
if (FindBorderRouter(*prefix) == NULL)
{
continue;
@@ -315,35 +305,24 @@ otError LeaderBase::RouteLookup(const Ip6::Address &aSource,
uint8_t * aPrefixMatch,
uint16_t * aRloc16)
{
otError error = OT_ERROR_NO_ROUTE;
PrefixTlv *prefix;
otError error = OT_ERROR_NO_ROUTE;
PrefixTlv *prefix = NULL;
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
while ((prefix = FindNextMatchingPrefix(aSource, prefix)) != NULL)
{
if (cur->GetType() != NetworkDataTlv::kTypePrefix)
if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatch, aRloc16) == OT_ERROR_NONE)
{
continue;
ExitNow(error = OT_ERROR_NONE);
}
prefix = static_cast<PrefixTlv *>(cur);
if (PrefixMatch(prefix->GetPrefix(), aSource.mFields.m8, prefix->GetPrefixLength()) >= 0)
if (DefaultRouteLookup(*prefix, aRloc16) == OT_ERROR_NONE)
{
if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatch, aRloc16) == OT_ERROR_NONE)
if (aPrefixMatch)
{
ExitNow(error = OT_ERROR_NONE);
*aPrefixMatch = 0;
}
if (DefaultRouteLookup(*prefix, aRloc16) == OT_ERROR_NONE)
{
if (aPrefixMatch)
{
*aPrefixMatch = 0;
}
ExitNow(error = OT_ERROR_NONE);
}
ExitNow(error = OT_ERROR_NONE);
}
}
@@ -366,8 +345,7 @@ otError LeaderBase::ExternalRouteLookup(uint8_t aDomainId,
NetworkDataTlv *cur;
NetworkDataTlv *subCur;
for (cur = reinterpret_cast<NetworkDataTlv *>(mTlvs); cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
cur = cur->GetNext())
for (cur = GetTlvsStart(); cur < GetTlvsEnd(); cur = cur->GetNext())
{
if (cur->GetType() != NetworkDataTlv::kTypePrefix)
{
@@ -524,18 +502,18 @@ exit:
otError LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength)
{
otError error = OT_ERROR_NONE;
uint8_t remaining = kMaxSize - mLength;
otError error = OT_ERROR_NONE;
CommissioningDataTlv *commissioningDataTlv;
VerifyOrExit(sizeof(NetworkDataTlv) + aValueLength < remaining, error = OT_ERROR_NO_BUFS);
RemoveCommissioningData();
if (aValueLength > 0)
{
commissioningDataTlv = reinterpret_cast<CommissioningDataTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(commissioningDataTlv), sizeof(CommissioningDataTlv) + aValueLength);
VerifyOrExit(aValueLength <= kMaxSize - sizeof(CommissioningDataTlv), error = OT_ERROR_NO_BUFS);
commissioningDataTlv =
static_cast<CommissioningDataTlv *>(AppendTlv(sizeof(CommissioningDataTlv) + aValueLength));
VerifyOrExit(commissioningDataTlv != NULL, error = OT_ERROR_NO_BUFS);
commissioningDataTlv->Init();
commissioningDataTlv->SetLength(aValueLength);
memcpy(commissioningDataTlv->GetValue(), aValue, aValueLength);
@@ -548,23 +526,9 @@ exit:
return error;
}
NetworkDataTlv *LeaderBase::GetCommissioningData(void)
CommissioningDataTlv *LeaderBase::GetCommissioningData(void)
{
NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
NetworkDataTlv *end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
for (; cur < end; cur = cur->GetNext())
{
if (cur->GetType() == NetworkDataTlv::kTypeCommissioningData)
{
ExitNow();
}
}
cur = NULL;
exit:
return cur;
return FindTlv<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
}
MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType)
@@ -616,17 +580,11 @@ exit:
otError LeaderBase::RemoveCommissioningData(void)
{
otError error = OT_ERROR_NOT_FOUND;
otError error = OT_ERROR_NONE;
CommissioningDataTlv *tlv = GetCommissioningData();
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
{
if (cur->GetType() == NetworkDataTlv::kTypeCommissioningData)
{
Remove(reinterpret_cast<uint8_t *>(cur), sizeof(NetworkDataTlv) + cur->GetLength());
ExitNow(error = OT_ERROR_NONE);
}
}
VerifyOrExit(tlv != NULL, error = OT_ERROR_NOT_FOUND);
RemoveTlv(tlv);
exit:
return error;
+3 -1
View File
@@ -187,7 +187,7 @@ public:
* @returns A pointer to the Commissioning Data or NULL if no Commissioning Data exists.
*
*/
NetworkDataTlv *GetCommissioningData(void);
CommissioningDataTlv *GetCommissioningData(void);
/**
* This method returns a pointer to the Commissioning Data Sub-TLV.
@@ -270,6 +270,8 @@ protected:
uint8_t mVersion;
private:
PrefixTlv *FindNextMatchingPrefix(const Ip6::Address &aAddress, PrefixTlv *aPrevTlv);
otError RemoveCommissioningData(void);
otError ExternalRouteLookup(uint8_t aDomainId,
+67 -116
View File
@@ -195,6 +195,7 @@ void Leader::HandleCommissioningSet(Coap::Message &aMessage, const Ip6::MessageI
bool hasSessionId = false;
bool hasValidTlv = false;
uint16_t sessionId = 0;
CommissioningDataTlv * commDataTlv;
MeshCoP::Tlv *cur;
MeshCoP::Tlv *end;
@@ -248,27 +249,25 @@ void Leader::HandleCommissioningSet(Coap::Message &aMessage, const Ip6::MessageI
VerifyOrExit(hasValidTlv);
// Find Commissioning Data TLV
for (NetworkDataTlv *netDataTlv = reinterpret_cast<NetworkDataTlv *>(mTlvs);
netDataTlv < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); netDataTlv = netDataTlv->GetNext())
commDataTlv = GetCommissioningData();
if (commDataTlv != NULL)
{
if (netDataTlv->GetType() == NetworkDataTlv::kTypeCommissioningData)
// Iterate over MeshCoP TLVs and extract desired data
for (cur = reinterpret_cast<MeshCoP::Tlv *>(commDataTlv->GetValue());
cur < reinterpret_cast<MeshCoP::Tlv *>(commDataTlv->GetValue() + commDataTlv->GetLength());
cur = cur->GetNext())
{
// Iterate over MeshCoP TLVs and extract desired data
for (cur = reinterpret_cast<MeshCoP::Tlv *>(netDataTlv->GetValue());
cur < reinterpret_cast<MeshCoP::Tlv *>(netDataTlv->GetValue() + netDataTlv->GetLength());
cur = cur->GetNext())
if (cur->GetType() == MeshCoP::Tlv::kCommissionerSessionId)
{
if (cur->GetType() == MeshCoP::Tlv::kCommissionerSessionId)
{
VerifyOrExit(sessionId ==
static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur)->GetCommissionerSessionId());
}
else if (cur->GetType() == MeshCoP::Tlv::kBorderAgentLocator)
{
VerifyOrExit(length + cur->GetSize() <= sizeof(tlvs));
memcpy(tlvs + length, reinterpret_cast<uint8_t *>(cur), cur->GetSize());
length += cur->GetSize();
}
VerifyOrExit(sessionId ==
static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur)->GetCommissionerSessionId());
}
else if (cur->GetType() == MeshCoP::Tlv::kBorderAgentLocator)
{
VerifyOrExit(length + cur->GetSize() <= sizeof(tlvs));
memcpy(tlvs + length, reinterpret_cast<uint8_t *>(cur), cur->GetSize());
length += cur->GetSize();
}
}
}
@@ -307,25 +306,23 @@ void Leader::SendCommissioningGetResponse(const Coap::Message & aRequest,
uint16_t aLength,
const Ip6::MessageInfo &aMessageInfo)
{
otError error = OT_ERROR_NONE;
Coap::Message *message;
uint8_t * data = NULL;
uint8_t length = 0;
otError error = OT_ERROR_NONE;
Coap::Message * message;
CommissioningDataTlv *commDataTlv;
uint8_t * data = NULL;
uint8_t length = 0;
VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(Get<Coap::Coap>())) != NULL, error = OT_ERROR_NO_BUFS);
SuccessOrExit(error = message->SetDefaultResponseHeader(aRequest));
SuccessOrExit(error = message->SetPayloadMarker());
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
commDataTlv = GetCommissioningData();
if (commDataTlv != NULL)
{
if (cur->GetType() == NetworkDataTlv::kTypeCommissioningData)
{
data = cur->GetValue();
length = cur->GetLength();
break;
}
data = commDataTlv->GetValue();
length = commDataTlv->GetLength();
}
VerifyOrExit(data && length, error = OT_ERROR_DROP);
@@ -907,8 +904,7 @@ otError Leader::AddHasRoute(PrefixTlv &aPrefix, HasRouteTlv &aHasRoute)
if (dstPrefix == NULL)
{
dstPrefix = reinterpret_cast<PrefixTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(dstPrefix), sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength()));
dstPrefix = static_cast<PrefixTlv *>(AppendTlv(sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength())));
dstPrefix->Init(aPrefix.GetDomainId(), aPrefix.GetPrefixLength(), aPrefix.GetPrefix());
}
@@ -920,7 +916,7 @@ otError Leader::AddHasRoute(PrefixTlv &aPrefix, HasRouteTlv &aHasRoute)
if (dstHasRoute == NULL)
{
dstHasRoute = static_cast<HasRouteTlv *>(dstPrefix->GetNext());
Insert(reinterpret_cast<uint8_t *>(dstHasRoute), sizeof(HasRouteTlv));
Insert(dstHasRoute, sizeof(HasRouteTlv));
dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(HasRouteTlv));
dstHasRoute->Init();
@@ -930,7 +926,7 @@ otError Leader::AddHasRoute(PrefixTlv &aPrefix, HasRouteTlv &aHasRoute)
}
}
Insert(reinterpret_cast<uint8_t *>(dstHasRoute->GetNext()), sizeof(HasRouteEntry));
Insert(dstHasRoute->GetNext(), sizeof(HasRouteEntry));
dstHasRoute->SetLength(dstHasRoute->GetLength() + sizeof(HasRouteEntry));
dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(HasRouteEntry));
memcpy(dstHasRoute->GetEntry(dstHasRoute->GetNumEntries() - 1), aHasRoute.GetEntry(0), sizeof(HasRouteEntry));
@@ -996,8 +992,8 @@ otError Leader::AddServer(ServiceTlv &aService, ServerTlv &aServer, uint8_t *aOl
VerifyOrExit(i <= Mle::kServiceMaxId, error = OT_ERROR_NO_BUFS);
}
dstService = reinterpret_cast<ServiceTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(dstService), serviceInsertLength);
dstService = static_cast<ServiceTlv *>(AppendTlv(serviceInsertLength));
dstService->Init();
dstService->SetServiceId(serviceId);
dstService->SetEnterpriseNumber(aService.GetEnterpriseNumber());
@@ -1007,7 +1003,7 @@ otError Leader::AddServer(ServiceTlv &aService, ServerTlv &aServer, uint8_t *aOl
dstServer = static_cast<ServerTlv *>(dstService->GetNext());
Insert(reinterpret_cast<uint8_t *>(dstServer), sizeof(ServerTlv) + aServer.GetServerDataLength());
Insert(dstServer, sizeof(ServerTlv) + aServer.GetServerDataLength());
dstServer->Init();
dstServer->SetServer16(aServer.GetServer16());
dstServer->SetServerData(aServer.GetServerData(), aServer.GetServerDataLength());
@@ -1026,8 +1022,8 @@ exit:
ServiceTlv *Leader::FindServiceById(uint8_t aServiceId)
{
NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
NetworkDataTlv *end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
NetworkDataTlv *cur = GetTlvsStart();
NetworkDataTlv *end = GetTlvsEnd();
ServiceTlv * compare = NULL;
while (cur < end)
@@ -1097,15 +1093,14 @@ otError Leader::AddBorderRouter(PrefixTlv &aPrefix, BorderRouterTlv &aBorderRout
if (dstPrefix == NULL)
{
dstPrefix = reinterpret_cast<PrefixTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(dstPrefix), sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength()));
dstPrefix = static_cast<PrefixTlv *>(AppendTlv(sizeof(PrefixTlv) + BitVectorBytes(aPrefix.GetPrefixLength())));
dstPrefix->Init(aPrefix.GetDomainId(), aPrefix.GetPrefixLength(), aPrefix.GetPrefix());
}
if (dstContext == NULL)
{
dstContext = static_cast<ContextTlv *>(dstPrefix->GetNext());
Insert(reinterpret_cast<uint8_t *>(dstContext), sizeof(ContextTlv));
Insert(dstContext, sizeof(ContextTlv));
dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(ContextTlv));
dstContext->Init();
dstContext->SetCompress();
@@ -1119,12 +1114,12 @@ otError Leader::AddBorderRouter(PrefixTlv &aPrefix, BorderRouterTlv &aBorderRout
if (dstBorderRouter == NULL)
{
dstBorderRouter = static_cast<BorderRouterTlv *>(dstPrefix->GetNext());
Insert(reinterpret_cast<uint8_t *>(dstBorderRouter), sizeof(BorderRouterTlv));
Insert(dstBorderRouter, sizeof(BorderRouterTlv));
dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(BorderRouterTlv));
dstBorderRouter->Init();
}
Insert(reinterpret_cast<uint8_t *>(dstBorderRouter->GetNext()), sizeof(BorderRouterEntry));
Insert(dstBorderRouter->GetNext(), sizeof(BorderRouterEntry));
dstBorderRouter->SetLength(dstBorderRouter->GetLength() + sizeof(BorderRouterEntry));
dstPrefix->SetLength(dstPrefix->GetLength() + sizeof(BorderRouterEntry));
memcpy(dstBorderRouter->GetEntry(dstBorderRouter->GetNumEntries() - 1), aBorderRouter.GetEntry(0),
@@ -1205,30 +1200,21 @@ exit:
void Leader::RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode)
{
NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
NetworkDataTlv *end;
PrefixTlv * prefix;
ServiceTlv * service;
NetworkDataTlv *cur = GetTlvsStart();
while (1)
while (cur < GetTlvsEnd())
{
end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
if (cur >= end)
{
break;
}
switch (cur->GetType())
{
case NetworkDataTlv::kTypePrefix:
{
prefix = static_cast<PrefixTlv *>(cur);
PrefixTlv *prefix = static_cast<PrefixTlv *>(cur);
RemoveRloc(*prefix, aRloc16, aMatchMode);
if (prefix->GetSubTlvsLength() == 0)
{
Remove(reinterpret_cast<uint8_t *>(prefix), sizeof(NetworkDataTlv) + prefix->GetLength());
RemoveTlv(prefix);
continue;
}
@@ -1238,12 +1224,13 @@ void Leader::RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode)
case NetworkDataTlv::kTypeService:
{
service = static_cast<ServiceTlv *>(cur);
ServiceTlv *service = static_cast<ServiceTlv *>(cur);
RemoveRloc(*service, aRloc16, aMatchMode);
if (service->GetSubTlvsLength() == 0)
{
Remove(reinterpret_cast<uint8_t *>(service), sizeof(NetworkDataTlv) + service->GetLength());
RemoveTlv(service);
continue;
}
@@ -1265,18 +1252,10 @@ void Leader::RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode)
void Leader::RemoveRloc(PrefixTlv &aPrefix, uint16_t aRloc16, MatchMode aMatchMode)
{
NetworkDataTlv *cur = aPrefix.GetSubTlvs();
NetworkDataTlv *end;
ContextTlv * context;
while (1)
while (cur < aPrefix.GetNext())
{
end = aPrefix.GetNext();
if (cur >= end)
{
break;
}
switch (cur->GetType())
{
case NetworkDataTlv::kTypeHasRoute:
@@ -1286,7 +1265,7 @@ void Leader::RemoveRloc(PrefixTlv &aPrefix, uint16_t aRloc16, MatchMode aMatchMo
if (cur->GetLength() == 0)
{
aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(HasRouteTlv));
Remove(reinterpret_cast<uint8_t *>(cur), sizeof(HasRouteTlv));
RemoveTlv(cur);
continue;
}
@@ -1299,7 +1278,7 @@ void Leader::RemoveRloc(PrefixTlv &aPrefix, uint16_t aRloc16, MatchMode aMatchMo
if (cur->GetLength() == 0)
{
aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(BorderRouterTlv));
Remove(reinterpret_cast<uint8_t *>(cur), sizeof(BorderRouterTlv));
RemoveTlv(cur);
continue;
}
@@ -1330,19 +1309,10 @@ void Leader::RemoveRloc(PrefixTlv &aPrefix, uint16_t aRloc16, MatchMode aMatchMo
void Leader::RemoveRloc(ServiceTlv &aService, uint16_t aRloc16, MatchMode aMatchMode)
{
NetworkDataTlv *cur = aService.GetSubTlvs();
NetworkDataTlv *end;
ServerTlv * server;
uint8_t removeLength;
while (1)
while (cur < aService.GetNext())
{
end = aService.GetNext();
if (cur >= end)
{
break;
}
switch (cur->GetType())
{
case NetworkDataTlv::kTypeServer:
@@ -1350,9 +1320,9 @@ void Leader::RemoveRloc(ServiceTlv &aService, uint16_t aRloc16, MatchMode aMatch
if (RlocMatch(server->GetServer16(), aRloc16, aMatchMode))
{
removeLength = sizeof(ServerTlv) + server->GetServerDataLength();
aService.SetSubTlvsLength(aService.GetSubTlvsLength() - removeLength);
Remove(reinterpret_cast<uint8_t *>(cur), removeLength);
uint8_t subTlvSize = server->GetSize();
RemoveTlv(server);
aService.SetSubTlvsLength(aService.GetSubTlvsLength() - subTlvSize);
continue;
}
@@ -1376,7 +1346,7 @@ void Leader::RemoveRloc(PrefixTlv &aPrefix, HasRouteTlv &aHasRoute, uint16_t aRl
{
aHasRoute.SetLength(aHasRoute.GetLength() - sizeof(HasRouteEntry));
aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(HasRouteEntry));
Remove(reinterpret_cast<uint8_t *>(entry), sizeof(HasRouteEntry));
Remove(entry, sizeof(HasRouteEntry));
continue;
}
@@ -1394,7 +1364,7 @@ void Leader::RemoveRloc(PrefixTlv &aPrefix, BorderRouterTlv &aBorderRouter, uint
{
aBorderRouter.SetLength(aBorderRouter.GetLength() - sizeof(BorderRouterEntry));
aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - sizeof(BorderRouterEntry));
Remove(reinterpret_cast<uint8_t *>(entry), sizeof(*entry));
Remove(entry, sizeof(*entry));
continue;
}
@@ -1404,29 +1374,21 @@ void Leader::RemoveRloc(PrefixTlv &aPrefix, BorderRouterTlv &aBorderRouter, uint
void Leader::RemoveContext(uint8_t aContextId)
{
NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
NetworkDataTlv *end;
PrefixTlv * prefix;
NetworkDataTlv *cur = GetTlvsStart();
while (1)
while (cur < GetTlvsEnd())
{
end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
if (cur >= end)
{
break;
}
switch (cur->GetType())
{
case NetworkDataTlv::kTypePrefix:
{
prefix = static_cast<PrefixTlv *>(cur);
PrefixTlv *prefix = static_cast<PrefixTlv *>(cur);
RemoveContext(*prefix, aContextId);
if (prefix->GetSubTlvsLength() == 0)
{
Remove(reinterpret_cast<uint8_t *>(prefix), sizeof(NetworkDataTlv) + prefix->GetLength());
RemoveTlv(prefix);
continue;
}
@@ -1447,31 +1409,21 @@ void Leader::RemoveContext(uint8_t aContextId)
void Leader::RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId)
{
NetworkDataTlv *cur = aPrefix.GetSubTlvs();
NetworkDataTlv *end;
ContextTlv * context;
uint8_t length;
while (1)
while (cur < aPrefix.GetNext())
{
end = aPrefix.GetNext();
if (cur >= end)
{
break;
}
switch (cur->GetType())
{
case NetworkDataTlv::kTypeContext:
{
// remove context tlv
context = static_cast<ContextTlv *>(cur);
ContextTlv *context = static_cast<ContextTlv *>(cur);
if (context->GetContextId() == aContextId)
{
length = sizeof(NetworkDataTlv) + context->GetLength();
aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - length);
Remove(reinterpret_cast<uint8_t *>(context), length);
uint8_t subTlvSize = context->GetSize();
RemoveTlv(context);
aPrefix.SetSubTlvsLength(aPrefix.GetSubTlvsLength() - subTlvSize);
continue;
}
@@ -1492,8 +1444,7 @@ void Leader::UpdateContextsAfterReset(void)
ContextTlv *contextTlv;
// Iterate through Network Data and synchronize missing contexts.
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
for (NetworkDataTlv *cur = GetTlvsStart(); cur < GetTlvsEnd(); cur = cur->GetNext())
{
if (cur->GetType() != NetworkDataTlv::kTypePrefix)
{
+79 -109
View File
@@ -56,43 +56,86 @@ Local::Local(Instance &aInstance)
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
otError Local::AddOnMeshPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, uint8_t aFlags, bool aStable)
{
otError error = OT_ERROR_NONE;
uint8_t prefixLengthBytes = BitVectorBytes(aPrefixLength);
uint8_t appendLength;
PrefixTlv * prefixTlv;
BorderRouterTlv *brTlv;
return AddPrefix(aPrefix, aPrefixLength, NetworkDataTlv::kTypeBorderRouter, aPrf, aFlags, aStable);
}
otError Local::RemoveOnMeshPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
{
return RemovePrefix(aPrefix, aPrefixLength, NetworkDataTlv::kTypeBorderRouter);
}
otError Local::AddHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, bool aStable)
{
return AddPrefix(aPrefix, aPrefixLength, NetworkDataTlv::kTypeHasRoute, aPrf, /* aFlags */ 0, aStable);
}
otError Local::RemoveHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
{
return RemovePrefix(aPrefix, aPrefixLength, NetworkDataTlv::kTypeHasRoute);
}
otError Local::AddPrefix(const uint8_t * aPrefix,
uint8_t aPrefixLength,
NetworkDataTlv::Type aSubTlvType,
int8_t aPrf,
uint8_t aFlags,
bool aStable)
{
otError error = OT_ERROR_NONE;
uint8_t prefixLengthBytes = BitVectorBytes(aPrefixLength);
uint8_t subTlvLength;
PrefixTlv *prefixTlv;
VerifyOrExit(prefixLengthBytes <= sizeof(Ip6::Address), error = OT_ERROR_INVALID_ARGS);
VerifyOrExit((aPrf == OT_ROUTE_PREFERENCE_LOW) || (aPrf == OT_ROUTE_PREFERENCE_MED) ||
(aPrf == OT_ROUTE_PREFERENCE_HIGH),
error = OT_ERROR_INVALID_ARGS);
switch (aPrf)
{
case OT_ROUTE_PREFERENCE_LOW:
case OT_ROUTE_PREFERENCE_MED:
case OT_ROUTE_PREFERENCE_HIGH:
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
VerifyOrExit(Ip6::Address::PrefixMatch(aPrefix, Get<Mle::MleRouter>().GetMeshLocalPrefix().m8, prefixLengthBytes) <
Mle::MeshLocalPrefix::kLength,
error = OT_ERROR_INVALID_ARGS);
RemoveOnMeshPrefix(aPrefix, aPrefixLength);
RemovePrefix(aPrefix, aPrefixLength, aSubTlvType);
appendLength = sizeof(PrefixTlv) + prefixLengthBytes + sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry);
VerifyOrExit(mLength + appendLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS);
subTlvLength = (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
? sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry)
: sizeof(HasRouteTlv) + sizeof(HasRouteEntry);
prefixTlv = static_cast<PrefixTlv *>(AppendTlv(sizeof(PrefixTlv) + prefixLengthBytes + subTlvLength));
VerifyOrExit(prefixTlv != NULL, error = OT_ERROR_NO_BUFS);
prefixTlv = reinterpret_cast<PrefixTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(prefixTlv), appendLength);
prefixTlv->Init(0, aPrefixLength, aPrefix);
prefixTlv->SetSubTlvsLength(sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry));
prefixTlv->SetSubTlvsLength(subTlvLength);
brTlv = static_cast<BorderRouterTlv *>(prefixTlv->GetSubTlvs());
brTlv->Init();
brTlv->SetLength(brTlv->GetLength() + sizeof(BorderRouterEntry));
brTlv->GetEntry(0)->Init();
brTlv->GetEntry(0)->SetPreference(aPrf);
brTlv->GetEntry(0)->SetFlags(aFlags);
if (aSubTlvType == NetworkDataTlv::kTypeBorderRouter)
{
BorderRouterTlv *brTlv = static_cast<BorderRouterTlv *>(prefixTlv->GetSubTlvs());
brTlv->Init();
brTlv->SetLength(brTlv->GetLength() + sizeof(BorderRouterEntry));
brTlv->GetEntry(0)->Init();
brTlv->GetEntry(0)->SetPreference(aPrf);
brTlv->GetEntry(0)->SetFlags(aFlags);
}
else // aSubTlvType is NetworkDataTlv::kTypeHasRoute
{
HasRouteTlv *hasRouteTlv = static_cast<HasRouteTlv *>(prefixTlv->GetSubTlvs());
hasRouteTlv->Init();
hasRouteTlv->SetLength(hasRouteTlv->GetLength() + sizeof(HasRouteEntry));
hasRouteTlv->GetEntry(0)->Init();
hasRouteTlv->GetEntry(0)->SetPreference(aPrf);
}
if (aStable)
{
prefixTlv->SetStable();
brTlv->SetStable();
prefixTlv->GetSubTlvs()->SetStable();
}
ClearResubmitDelayTimer();
@@ -103,73 +146,14 @@ exit:
return error;
}
otError Local::RemoveOnMeshPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
otError Local::RemovePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, NetworkDataTlv::Type aSubTlvType)
{
otError error = OT_ERROR_NONE;
PrefixTlv *tlv;
VerifyOrExit((tlv = FindPrefix(aPrefix, aPrefixLength)) != NULL, error = OT_ERROR_NOT_FOUND);
VerifyOrExit(FindBorderRouter(*tlv) != NULL, error = OT_ERROR_NOT_FOUND);
Remove(reinterpret_cast<uint8_t *>(tlv), sizeof(NetworkDataTlv) + tlv->GetLength());
ClearResubmitDelayTimer();
exit:
otDumpDebgNetData("remove done", mTlvs, mLength);
return error;
}
otError Local::AddHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, bool aStable)
{
otError error = OT_ERROR_NONE;
uint8_t prefixLengthBytes = BitVectorBytes(aPrefixLength);
PrefixTlv * prefixTlv;
HasRouteTlv *hasRouteTlv;
uint8_t appendLength;
VerifyOrExit(prefixLengthBytes <= sizeof(Ip6::Address), error = OT_ERROR_INVALID_ARGS);
VerifyOrExit((aPrf == OT_ROUTE_PREFERENCE_LOW) || (aPrf == OT_ROUTE_PREFERENCE_MED) ||
(aPrf == OT_ROUTE_PREFERENCE_HIGH),
error = OT_ERROR_INVALID_ARGS);
RemoveHasRoutePrefix(aPrefix, aPrefixLength);
appendLength = sizeof(PrefixTlv) + prefixLengthBytes + sizeof(HasRouteTlv) + sizeof(HasRouteEntry);
VerifyOrExit(mLength + appendLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS);
prefixTlv = reinterpret_cast<PrefixTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(prefixTlv), appendLength);
prefixTlv->Init(0, aPrefixLength, aPrefix);
prefixTlv->SetSubTlvsLength(sizeof(HasRouteTlv) + sizeof(HasRouteEntry));
hasRouteTlv = static_cast<HasRouteTlv *>(prefixTlv->GetSubTlvs());
hasRouteTlv->Init();
hasRouteTlv->SetLength(hasRouteTlv->GetLength() + sizeof(HasRouteEntry));
hasRouteTlv->GetEntry(0)->Init();
hasRouteTlv->GetEntry(0)->SetPreference(aPrf);
if (aStable)
{
prefixTlv->SetStable();
hasRouteTlv->SetStable();
}
ClearResubmitDelayTimer();
otDumpDebgNetData("add route done", mTlvs, mLength);
exit:
return error;
}
otError Local::RemoveHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength)
{
otError error = OT_ERROR_NONE;
PrefixTlv *tlv;
VerifyOrExit((tlv = FindPrefix(aPrefix, aPrefixLength)) != NULL, error = OT_ERROR_NOT_FOUND);
VerifyOrExit(FindHasRoute(*tlv) != NULL, error = OT_ERROR_NOT_FOUND);
Remove(reinterpret_cast<uint8_t *>(tlv), sizeof(NetworkDataTlv) + tlv->GetLength());
VerifyOrExit(FindTlv(tlv->GetSubTlvs(), tlv->GetNext(), aSubTlvType) != NULL, error = OT_ERROR_NOT_FOUND);
RemoveTlv(tlv);
ClearResubmitDelayTimer();
exit:
@@ -179,16 +163,18 @@ exit:
void Local::UpdateRloc(PrefixTlv &aPrefix)
{
uint16_t rloc16 = Get<Mle::MleRouter>().GetRloc16();
for (NetworkDataTlv *cur = aPrefix.GetSubTlvs(); cur < aPrefix.GetNext(); cur = cur->GetNext())
{
switch (cur->GetType())
{
case NetworkDataTlv::kTypeHasRoute:
UpdateRloc(*static_cast<HasRouteTlv *>(cur));
static_cast<HasRouteTlv *>(cur)->GetEntry(0)->SetRloc(rloc16);
break;
case NetworkDataTlv::kTypeBorderRouter:
UpdateRloc(*static_cast<BorderRouterTlv *>(cur));
static_cast<BorderRouterTlv *>(cur)->GetEntry(0)->SetRloc(rloc16);
break;
default:
@@ -198,18 +184,6 @@ void Local::UpdateRloc(PrefixTlv &aPrefix)
}
}
void Local::UpdateRloc(HasRouteTlv &aHasRoute)
{
HasRouteEntry *entry = aHasRoute.GetEntry(0);
entry->SetRloc(Get<Mle::MleRouter>().GetRloc16());
}
void Local::UpdateRloc(BorderRouterTlv &aBorderRouter)
{
BorderRouterEntry *entry = aBorderRouter.GetEntry(0);
entry->SetRloc(Get<Mle::MleRouter>().GetRloc16());
}
bool Local::IsOnMeshPrefixConsistent(void)
{
return (Get<Leader>().ContainsOnMeshPrefixes(*this, Get<Mle::MleRouter>().GetRloc16()) &&
@@ -241,10 +215,10 @@ otError Local::AddService(uint32_t aEnterpriseNumber,
RemoveService(aEnterpriseNumber, aServiceData, aServiceDataLength);
VerifyOrExit(mLength + sizeof(NetworkDataTlv) + serviceTlvLength <= sizeof(mTlvs), error = OT_ERROR_NO_BUFS);
VerifyOrExit(serviceTlvLength + sizeof(NetworkDataTlv) <= kMaxSize, error = OT_ERROR_NO_BUFS);
serviceTlv = reinterpret_cast<ServiceTlv *>(mTlvs + mLength);
Insert(reinterpret_cast<uint8_t *>(serviceTlv), static_cast<uint8_t>(serviceTlvLength) + sizeof(NetworkDataTlv));
serviceTlv = static_cast<ServiceTlv *>(AppendTlv(static_cast<uint8_t>(serviceTlvLength + sizeof(NetworkDataTlv))));
VerifyOrExit(serviceTlv != NULL, error = OT_ERROR_NO_BUFS);
serviceTlv->Init();
serviceTlv->SetEnterpriseNumber(aEnterpriseNumber);
@@ -282,7 +256,7 @@ otError Local::RemoveService(uint32_t aEnterpriseNumber, const uint8_t *aService
VerifyOrExit((tlv = FindService(aEnterpriseNumber, aServiceData, aServiceDataLength)) != NULL,
error = OT_ERROR_NOT_FOUND);
Remove(reinterpret_cast<uint8_t *>(tlv), sizeof(NetworkDataTlv) + tlv->GetLength());
RemoveTlv(tlv);
ClearResubmitDelayTimer();
exit:
@@ -292,12 +266,14 @@ exit:
void Local::UpdateRloc(ServiceTlv &aService)
{
uint16_t rloc16 = Get<Mle::MleRouter>().GetRloc16();
for (NetworkDataTlv *cur = aService.GetSubTlvs(); cur < aService.GetNext(); cur = cur->GetNext())
{
switch (cur->GetType())
{
case NetworkDataTlv::kTypeServer:
UpdateRloc(*static_cast<ServerTlv *>(cur));
static_cast<ServerTlv *>(cur)->SetServer16(rloc16);
break;
default:
@@ -307,11 +283,6 @@ void Local::UpdateRloc(ServiceTlv &aService)
}
}
void Local::UpdateRloc(ServerTlv &aServer)
{
aServer.SetServer16(Get<Mle::MleRouter>().GetRloc16());
}
bool Local::IsServiceConsistent(void)
{
return (Get<Leader>().ContainsServices(*this, Get<Mle::MleRouter>().GetRloc16()) &&
@@ -322,8 +293,7 @@ bool Local::IsServiceConsistent(void)
void Local::UpdateRloc(void)
{
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength); cur = cur->GetNext())
for (NetworkDataTlv *cur = GetTlvsStart(); cur < GetTlvsEnd(); cur = cur->GetNext())
{
switch (cur->GetType())
{
+10 -6
View File
@@ -173,16 +173,20 @@ public:
private:
void UpdateRloc(void);
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
void UpdateRloc(PrefixTlv &aPrefix);
void UpdateRloc(HasRouteTlv &aHasRoute);
void UpdateRloc(BorderRouterTlv &aBorderRouter);
bool IsOnMeshPrefixConsistent(void);
bool IsExternalRouteConsistent(void);
otError AddPrefix(const uint8_t * aPrefix,
uint8_t aPrefixLength,
NetworkDataTlv::Type aSubTlvType,
int8_t aPrf,
uint8_t aFlags,
bool aStable);
otError RemovePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, NetworkDataTlv::Type aSubTlvType);
void UpdateRloc(PrefixTlv &aPrefix);
bool IsOnMeshPrefixConsistent(void);
bool IsExternalRouteConsistent(void);
#endif
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
void UpdateRloc(ServiceTlv &aService);
void UpdateRloc(ServerTlv &aServer);
bool IsServiceConsistent(void);
#endif
+40 -1
View File
@@ -121,6 +121,14 @@ public:
*/
void SetLength(uint8_t aLength) { mLength = aLength; }
/**
* This method returns the TLV's total size (number of bytes) including Type, Length, and Value fields.
*
* @returns The total size include Type, Length, and Value fields.
*
*/
uint8_t GetSize(void) const { return sizeof(NetworkDataTlv) + mLength; }
/**
* This method returns a pointer to the Value.
*
@@ -253,6 +261,11 @@ OT_TOOL_PACKED_BEGIN
class HasRouteTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeHasRoute, ///< The TLV Type.
};
/**
* This method initializes the TLV.
*
@@ -315,6 +328,11 @@ OT_TOOL_PACKED_BEGIN
class PrefixTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypePrefix, ///< The TLV Type.
};
/**
* This method initializes the TLV.
*
@@ -638,6 +656,11 @@ OT_TOOL_PACKED_BEGIN
class BorderRouterTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeBorderRouter, ///< The TLV Type.
};
/**
* This method initializes the TLV.
*
@@ -700,6 +723,11 @@ OT_TOOL_PACKED_BEGIN
class ContextTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeContext, ///< The TLV Type.
};
/**
* This method initializes the TLV.
*
@@ -788,6 +816,11 @@ OT_TOOL_PACKED_BEGIN
class CommissioningDataTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeCommissioningData, ///< The TLV Type.
};
/**
* This method initializes the TLV.
*
@@ -810,7 +843,8 @@ class ServiceTlv : public NetworkDataTlv
public:
enum
{
kServiceDataBackboneRouter = 0x01, // const THREAD_SERVICE_DATA_BBR
kType = kTypeService, ///< The TLV Type.
kServiceDataBackboneRouter = 0x01, ///< const THREAD_SERVICE_DATA_BBR
};
/**
@@ -1037,6 +1071,11 @@ OT_TOOL_PACKED_BEGIN
class ServerTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeServer, ///< The TLV Type.
};
/**
* This method initializes the TLV.
*