diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index aff9c4543..95dd44295 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -313,7 +313,7 @@ ThreadError Commissioner::SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, } memset(&messageInfo, 0, sizeof(messageInfo)); - mNetif.GetMle().GetLeaderAddress(messageInfo.GetPeerAddr()); + mNetif.GetMle().GetLeaderAloc(messageInfo.GetPeerAddr()); messageInfo.mPeerPort = kCoapUdpPort; SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); @@ -395,7 +395,7 @@ ThreadError Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDa } memset(&messageInfo, 0, sizeof(messageInfo)); - mNetif.GetMle().GetLeaderAddress(messageInfo.GetPeerAddr()); + mNetif.GetMle().GetLeaderAloc(messageInfo.GetPeerAddr()); messageInfo.mPeerPort = kCoapUdpPort; SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); @@ -451,7 +451,7 @@ ThreadError Commissioner::SendPetition(void) SuccessOrExit(error = message->Append(&commissionerId, sizeof(Tlv) + commissionerId.GetLength())); memset(&messageInfo, 0, sizeof(messageInfo)); - mNetif.GetMle().GetLeaderAddress(*static_cast(&messageInfo.mPeerAddr)); + mNetif.GetMle().GetLeaderAloc(*static_cast(&messageInfo.mPeerAddr)); messageInfo.mPeerPort = kCoapUdpPort; SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); @@ -510,7 +510,7 @@ ThreadError Commissioner::SendKeepAlive(void) SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); memset(&messageInfo, 0, sizeof(messageInfo)); - mNetif.GetMle().GetLeaderAddress(*static_cast(&messageInfo.mPeerAddr)); + mNetif.GetMle().GetLeaderAloc(*static_cast(&messageInfo.mPeerAddr)); messageInfo.mPeerPort = kCoapUdpPort; SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index ebb9e9a1d..42360755c 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -588,6 +588,7 @@ ThreadError MeshForwarder::UpdateIp6Route(Message &aMessage) ThreadError error = kThreadError_None; Ip6::Header ip6Header; uint16_t rloc16; + uint16_t aloc16; Neighbor *neighbor; mAddMeshHeader = false; @@ -653,6 +654,21 @@ ThreadError MeshForwarder::UpdateIp6Route(Message &aMessage) VerifyOrExit(mMle.IsRouterIdValid(mMle.GetRouterId(rloc16)), error = kThreadError_Drop); mMeshDest = rloc16; } + else if (mMle.IsAnycastLocator(ip6Header.GetDestination())) + { + // only support Leader ALOC for now + aloc16 = HostSwap16(ip6Header.GetDestination().mFields.m16[7]); + + if (aloc16 == Mle::kAloc16Leader) + { + mMeshDest = mMle.GetRloc16(mMle.GetLeaderId()); + } + else + { + // TODO: support ALOC for DHCPv6 Agent, Service, Commissioner, Neighbor Discovery Agent + ExitNow(error = kThreadError_Drop); + } + } else if ((neighbor = mMle.GetNeighbor(ip6Header.GetDestination())) != NULL) { mMeshDest = neighbor->mValid.mRloc16; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index c9acc6e5b..70d3ebcc6 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -229,6 +229,12 @@ ThreadError Mle::Stop(void) SetStateDetached(); mNetif.RemoveUnicastAddress(mLinkLocal16); mNetif.RemoveUnicastAddress(mMeshLocal16); + + if (mDeviceState == kDeviceStateLeader) + { + mNetif.RemoveUnicastAddress(mLeaderAloc); + } + mDeviceState = kDeviceStateDisabled; return kThreadError_None; } @@ -354,6 +360,11 @@ ThreadError Mle::SetStateDetached(void) mNetif.SetStateChangedFlags(OT_NET_ROLE); } + if (mDeviceState == kDeviceStateLeader) + { + mNetif.RemoveUnicastAddress(mLeaderAloc); + } + mAddressResolver.Clear(); mDeviceState = kDeviceStateDetached; mParentRequestState = kParentIdle; @@ -373,6 +384,11 @@ ThreadError Mle::SetStateChild(uint16_t aRloc16) mNetif.SetStateChangedFlags(OT_NET_ROLE); } + if (mDeviceState == kDeviceStateLeader) + { + mNetif.RemoveUnicastAddress(mLeaderAloc); + } + SetRloc16(aRloc16); mDeviceState = kDeviceStateChild; mParentRequestState = kParentIdle; @@ -506,6 +522,13 @@ ThreadError Mle::SetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix) mNetif.AddUnicastAddress(mMeshLocal16); } + // update Leader ALOC + if (mDeviceState == kDeviceStateLeader) + { + mNetif.RemoveUnicastAddress(mLeaderAloc); + AddLeaderAloc(); + } + // Changing the prefix also causes the mesh local address to be different. mNetif.SetStateChangedFlags(OT_IP6_ML_ADDR_CHANGED); @@ -596,6 +619,36 @@ exit: return error; } +ThreadError Mle::GetLeaderAloc(Ip6::Address &aAddress) const +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kThreadError_Detached); + + memcpy(&aAddress, &mMeshLocal16.GetAddress(), 8); + aAddress.mFields.m16[4] = HostSwap16(0x0000); + aAddress.mFields.m16[5] = HostSwap16(0x00ff); + aAddress.mFields.m16[6] = HostSwap16(0xfe00); + aAddress.mFields.m16[7] = HostSwap16(kAloc16Leader); + +exit: + return error; +} + +ThreadError Mle::AddLeaderAloc(void) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(mDeviceState == kDeviceStateLeader, error = kThreadError_InvalidState); + + SuccessOrExit(error = GetLeaderAloc(mLeaderAloc.GetAddress())); + + error = mNetif.AddUnicastAddress(mLeaderAloc); + +exit: + return error; +} + const LeaderDataTlv &Mle::GetLeaderDataTlv(void) { mLeaderData.SetDataVersion(mNetworkData.GetVersion()); @@ -2677,7 +2730,12 @@ uint16_t Mle::GetNextHop(uint16_t aDestination) const bool Mle::IsRoutingLocator(const Ip6::Address &aAddress) const { - return memcmp(&mMeshLocal16, &aAddress, kRlocPrefixLength) == 0; + return memcmp(&mMeshLocal16, &aAddress, kRlocPrefixLength) == 0 && aAddress.mFields.m8[14] != kAloc16Mask; +} + +bool Mle::IsAnycastLocator(const Ip6::Address &aAddress) const +{ + return memcmp(&mMeshLocal16, &aAddress, kRlocPrefixLength) == 0 && aAddress.mFields.m8[14] == kAloc16Mask; } Router *Mle::GetParent() diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index ca8e6e700..8139673c5 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -103,6 +103,24 @@ enum DeviceState kDeviceStateLeader = 4, ///< Thread interface participating as a Leader. }; +/** + * This enumeration represents the allocation of the ALOC Space + * + */ +enum AlocAllocation +{ + kAloc16Mask = 0xfc, + kAloc16Leader = 0xfc00, + kAloc16DHCPv6AgentStart = 0xfc01, + kAloc16DHCPv6AgentEnd = 0xfc0f, + kAloc16ServiceStart = 0xfc10, + kAloc16ServiceEnd = 0xfc2f, + kAloc16CommissionerStart = 0xfc30, + kAloc16CommissionerEnd = 0xfc37, + kAloc16NeighborDiscoveryAgentStart = 0xfc40, + kAloc16NeighborDiscoveryAgentEnd = 0xfc4e, +}; + /** * This class implements MLE Header generation and parsing. * @@ -536,6 +554,15 @@ public: */ bool IsRoutingLocator(const Ip6::Address &aAddress) const; + /** + * This method indicates whether or not an IPv6 address is an ALOC. + * + * @retval TRUE If @p aAddress is an ALOC. + * @retval FALSE If @p aAddress is not an ALOC. + * + */ + bool IsAnycastLocator(const Ip6::Address &aAddress) const; + /** * This method returns the MLE Timeout value. * @@ -593,6 +620,27 @@ public: */ ThreadError GetLeaderAddress(Ip6::Address &aAddress) const; + /** + * This method retrieves the Leader's ALOC. + * + * @param[out] aAddress A reference to the Leader's ALOC. + * + * @retval kThreadError_None Successfully retrieved the Leader's ALOC. + * @retval kThreadError_Error The Thread interface is not currently attached to a Thread Partition. + * + */ + ThreadError GetLeaderAloc(Ip6::Address &aAddress) const; + + /** + * This method adds Leader's ALOC to its Thread interface. + * + * @retval kThreadError_None Successfully added the Leader's ALOC. + * @retval kThreadError_Busy The Leader's ALOC address was already added. + * @retval kThreadError_InvalidState The device's role is not Leader. + * + */ + ThreadError AddLeaderAloc(void); + /** * This method returns the most recently received Leader Data TLV. * @@ -1176,6 +1224,8 @@ private: uint8_t mPreviousChannel; uint16_t mPreviousPanId; + Ip6::NetifUnicastAddress mLeaderAloc; + Ip6::NetifUnicastAddress mLinkLocal16; Ip6::NetifUnicastAddress mLinkLocal64; Ip6::NetifUnicastAddress mMeshLocal64; diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 35e63dae9..f8fb441bf 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -279,6 +279,8 @@ ThreadError MleRouter::BecomeLeader(void) SuccessOrExit(error = SetStateLeader(GetRloc16(mRouterId))); + SuccessOrExit(error = AddLeaderAloc()); + ResetAdvertiseInterval(); exit: