int8_t NetworkData::PrefixMatch(const uint8_t *a, const uint8_t *b, uint8_t aLength) { uint8_t rval = 0; uint8_t bytes = BitVectorBytes(aLength); uint8_t diff; for (uint8_t i = 0; i < bytes; i++) { diff = a[i] ^ b[i]; if (diff == 0) { rval += 8; } else { while ((diff & 0x80) == 0) { rval++; diff <<= 1; } break; } } return (rval >= aLength) ? rval : -1; }
ThreadError Local::AddHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf, bool aStable) { PrefixTlv *prefixTlv; HasRouteTlv *hasRouteTlv; RemoveHasRoutePrefix(aPrefix, aPrefixLength); prefixTlv = reinterpret_cast<PrefixTlv *>(mTlvs + mLength); Insert(reinterpret_cast<uint8_t *>(prefixTlv), sizeof(PrefixTlv) + BitVectorBytes(aPrefixLength) + sizeof(HasRouteTlv) + sizeof(HasRouteEntry)); prefixTlv->Init(0, aPrefixLength, aPrefix); prefixTlv->SetSubTlvsLength(sizeof(HasRouteTlv) + sizeof(HasRouteEntry)); hasRouteTlv = reinterpret_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(); } otDumpDebgNetData("add route done", mTlvs, mLength); return kThreadError_None; }
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; 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); VerifyOrExit(Ip6::Address::PrefixMatch(aPrefix, Get<Mle::MleRouter>().GetMeshLocalPrefix().m8, prefixLengthBytes) < Ip6::Address::kMeshLocalPrefixLength, error = OT_ERROR_INVALID_ARGS); RemoveOnMeshPrefix(aPrefix, aPrefixLength); appendLength = sizeof(PrefixTlv) + prefixLengthBytes + sizeof(BorderRouterTlv) + sizeof(BorderRouterEntry); 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(BorderRouterTlv) + sizeof(BorderRouterEntry)); 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 (aStable) { prefixTlv->SetStable(); brTlv->SetStable(); } ClearResubmitDelayTimer(); otDumpDebgNetData("add prefix done", mTlvs, mLength); exit: 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; }