diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 2003d8b3b..2188a6405 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -53,7 +53,9 @@ Ip6::Ip6(void): mForwardingEnabled(false), mReceiveIp6DatagramCallback(NULL), mReceiveIp6DatagramCallbackContext(NULL), - mIsReceiveIp6FilterEnabled(false) + mIsReceiveIp6FilterEnabled(false), + mNetifListHead(NULL), + mNextInterfaceId(1) { } @@ -150,7 +152,7 @@ ThreadError Ip6::SendDatagram(Message &message, MessageInfo &messageInfo, IpProt if (messageInfo.GetSockAddr().IsUnspecified()) { - VerifyOrExit((source = Netif::SelectSourceAddress(messageInfo)) != NULL, error = kThreadError_Error); + VerifyOrExit((source = SelectSourceAddress(messageInfo)) != NULL, error = kThreadError_Error); header.SetSource(source->GetAddress()); } else @@ -441,7 +443,7 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, int8_t interface } else { - if (Netif::IsUnicastAddress(header.GetDestination())) + if (IsUnicastAddress(header.GetDestination())) { receive = true; } @@ -523,7 +525,7 @@ ThreadError Ip6::ForwardMessage(Message &message, MessageInfo &messageInfo) // on-link link-local address interfaceId = messageInfo.mInterfaceId; } - else if ((interfaceId = Netif::GetOnLinkNetif(messageInfo.GetSockAddr())) > 0) + else if ((interfaceId = GetOnLinkNetif(messageInfo.GetSockAddr())) > 0) { // on-link global address ; @@ -540,12 +542,237 @@ ThreadError Ip6::ForwardMessage(Message &message, MessageInfo &messageInfo) } // submit message to interface - VerifyOrExit((netif = Netif::GetNetifById(interfaceId)) != NULL, error = kThreadError_NoRoute); + VerifyOrExit((netif = GetNetifById(interfaceId)) != NULL, error = kThreadError_NoRoute); SuccessOrExit(error = netif->SendMessage(message)); exit: return error; } +ThreadError Ip6::AddNetif(Netif &aNetif) +{ + ThreadError error = kThreadError_None; + Netif *netif; + + if (mNetifListHead == NULL) + { + mNetifListHead = &aNetif; + } + else + { + netif = mNetifListHead; + + do + { + if (netif == &aNetif) + { + ExitNow(error = kThreadError_Busy); + } + } + while (netif->mNext); + + netif->mNext = &aNetif; + } + + aNetif.mNext = NULL; + + if (aNetif.mInterfaceId < 0) + { + aNetif.mInterfaceId = mNextInterfaceId++; + } + +exit: + return error; +} + +ThreadError Ip6::RemoveNetif(Netif &aNetif) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(mNetifListHead != NULL, error = kThreadError_Busy); + + if (mNetifListHead == &aNetif) + { + mNetifListHead = aNetif.mNext; + } + else + { + for (Netif *netif = mNetifListHead; netif->mNext; netif = netif->mNext) + { + if (netif->mNext != &aNetif) + { + continue; + } + + netif->mNext = aNetif.mNext; + break; + } + } + + aNetif.mNext = NULL; + +exit: + return error; +} + +Netif *Ip6::GetNetifList() +{ + return mNetifListHead; +} + +Netif *Ip6::GetNetifById(int8_t aInterfaceId) +{ + Netif *netif; + + for (netif = mNetifListHead; netif; netif = netif->mNext) + { + if (netif->GetInterfaceId() == aInterfaceId) + { + ExitNow(); + } + } + +exit: + return netif; +} + +Netif *Ip6::GetNetifByName(char *aName) +{ + Netif *netif; + + for (netif = mNetifListHead; netif; netif = netif->mNext) + { + if (strcmp(netif->GetName(), aName) == 0) + { + ExitNow(); + } + } + +exit: + return netif; +} + +bool Ip6::IsUnicastAddress(const Address &aAddress) +{ + bool rval = false; + + for (Netif *netif = mNetifListHead; netif; netif = netif->mNext) + { + rval = netif->IsUnicastAddress(aAddress); + + if (rval) + { + ExitNow(); + } + } + +exit: + return rval; +} + +const NetifUnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo) +{ + Address *destination = &aMessageInfo.GetPeerAddr(); + int interfaceId = aMessageInfo.mInterfaceId; + const NetifUnicastAddress *rvalAddr = NULL; + const Address *candidateAddr; + int8_t candidateId; + int8_t rvalIface = 0; + + for (Netif *netif = GetNetifList(); netif; netif = netif->mNext) + { + candidateId = netif->GetInterfaceId(); + + for (const NetifUnicastAddress *addr = netif->mUnicastAddresses; addr; addr = addr->GetNext()) + { + candidateAddr = &addr->GetAddress(); + + if (destination->IsLinkLocal() || destination->IsMulticast()) + { + if (interfaceId != candidateId) + { + continue; + } + } + + if (rvalAddr == NULL) + { + // Rule 0: Prefer any address + rvalAddr = addr; + rvalIface = candidateId; + } + else if (*candidateAddr == *destination) + { + // Rule 1: Prefer same address + rvalAddr = addr; + rvalIface = candidateId; + goto exit; + } + else if (candidateAddr->GetScope() < rvalAddr->GetAddress().GetScope()) + { + // Rule 2: Prefer appropriate scope + if (candidateAddr->GetScope() >= destination->GetScope()) + { + rvalAddr = addr; + rvalIface = candidateId; + } + } + else if (candidateAddr->GetScope() > rvalAddr->GetAddress().GetScope()) + { + if (rvalAddr->GetAddress().GetScope() < destination->GetScope()) + { + rvalAddr = addr; + rvalIface = candidateId; + } + } + else if (addr->mPreferredLifetime != 0 && rvalAddr->mPreferredLifetime == 0) + { + // Rule 3: Avoid deprecated addresses + rvalAddr = addr; + rvalIface = candidateId; + } + else if (aMessageInfo.mInterfaceId != 0 && aMessageInfo.mInterfaceId == candidateId && + rvalIface != candidateId) + { + // Rule 4: Prefer home address + // Rule 5: Prefer outgoing interface + rvalAddr = addr; + rvalIface = candidateId; + } + else if (destination->PrefixMatch(*candidateAddr) > destination->PrefixMatch(rvalAddr->GetAddress())) + { + // Rule 6: Prefer matching label + // Rule 7: Prefer public address + // Rule 8: Use longest prefix matching + rvalAddr = addr; + rvalIface = candidateId; + } + } + } + +exit: + aMessageInfo.mInterfaceId = rvalIface; + return rvalAddr; +} + +int8_t Ip6::GetOnLinkNetif(const Address &aAddress) +{ + int8_t rval = -1; + + for (Netif *netif = mNetifListHead; netif; netif = netif->mNext) + { + for (const NetifUnicastAddress *cur = netif->mUnicastAddresses; cur; cur = cur->GetNext()) + { + if (cur->GetAddress().PrefixMatch(aAddress) >= cur->mPrefixLength) + { + ExitNow(rval = netif->GetInterfaceId()); + } + } + } + +exit: + return rval; +} + } // namespace Ip6 } // namespace Thread diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index a7ee3577b..7a10e7b88 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -241,6 +241,87 @@ public: */ void SetForwardingEnabled(bool aEnable); + /** + * This method enables the network interface. + * + * @param aNetif A reference to the network interface. + * + * @retval kThreadError_None Successfully enabled the network interface. + * @retval KThreadError_Busy The network interface was already enabled. + * + */ + ThreadError AddNetif(Netif &aNetif); + + /** + * This method disables the network interface. + * + * @param aNetif A reference to the network interface. + * + * @retval kThreadError_None Successfully disabled the network interface. + * @retval KThreadError_Busy The network interface was already disabled. + * + */ + ThreadError RemoveNetif(Netif &aNetif); + + /** + * This method returns the network interface list. + * + * @returns A pointer to the network interface list. + * + */ + Netif *GetNetifList(void); + + /** + * This method returns the network interface identified by @p aInterfaceId. + * + * @param[in] aInterfaceId The network interface ID. + * + * @returns A pointer to the network interface or NULL if none is found. + * + */ + Netif *GetNetifById(int8_t aInterfaceId); + + /** + * This method returns the network interface identified by @p aName. + * + * @param[in] aName A pointer to a NULL-terminated string. + * + * @returns A pointer to the network interface or NULL if none is found. + * + */ + Netif *GetNetifByName(char *aName); + + /** + * This method indicates whether or not @p aAddress is assigned to a network interface. + * + * @param[in] aAddress A reference to the IPv6 address. + * + * @retval TRUE If the IPv6 address is assigned to a network interface. + * @retval FALSE If the IPv6 address is not assigned to any network interface. + * + */ + bool IsUnicastAddress(const Address &aAddress); + + /** + * This method perform default source address selection. + * + * @param[in] aMessageInfo A reference to the message information. + * + * @returns A pointer to the selected IPv6 source address or NULL if no source address was found. + * + */ + const NetifUnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo); + + /** + * This method determines which network interface @p aAddress is on-link, if any. + * + * @param[in] aAddress A reference to the IPv6 address. + * + * @returns The network interface identifier for the on-link interface or -1 if none is found. + * + */ + int8_t GetOnLinkNetif(const Address &aAddress); + Icmp mIcmp; Udp mUdp; @@ -259,6 +340,9 @@ private: otReceiveIp6DatagramCallback mReceiveIp6DatagramCallback; void *mReceiveIp6DatagramCallbackContext; bool mIsReceiveIp6FilterEnabled; + + Netif *mNetifListHead; + int8_t mNextInterfaceId; }; /** diff --git a/src/core/net/ip6_routes.cpp b/src/core/net/ip6_routes.cpp index df54f1f0b..4c59aae1e 100644 --- a/src/core/net/ip6_routes.cpp +++ b/src/core/net/ip6_routes.cpp @@ -31,12 +31,16 @@ * This file implements IPv6 route tables. */ +#include #include #include #include #include namespace Thread { + +extern Ip6::Ip6 *sIp6; + namespace Ip6 { static Route *sRoutes = NULL; @@ -109,7 +113,7 @@ int8_t Routes::Lookup(const Address &aSource, const Address &aDestination) rval = cur->mInterfaceId; } - for (Netif *netif = Netif::GetNetifList(); netif; netif = netif->GetNext()) + for (Netif *netif = sIp6->GetNetifList(); netif; netif = netif->GetNext()) { if (netif->RouteLookup(aSource, aDestination, &prefixMatch) == kThreadError_None && static_cast(prefixMatch) > maxPrefixMatch) diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp index 6824ff65d..830db0361 100644 --- a/src/core/net/netif.cpp +++ b/src/core/net/netif.cpp @@ -39,12 +39,9 @@ namespace Thread { namespace Ip6 { -Netif *Netif::sNetifListHead = NULL; -int8_t Netif::sNextInterfaceId = 1; - Netif::Netif(Ip6 &aIp6): - mStateChangedTask(&HandleStateChangedTask, this), - mIp6(aIp6) + mIp6(aIp6), + mStateChangedTask(&HandleStateChangedTask, this) { mCallbacks = NULL; mUnicastAddresses = NULL; @@ -76,72 +73,6 @@ exit: return error; } -ThreadError Netif::AddNetif() -{ - ThreadError error = kThreadError_None; - Netif *netif; - - if (sNetifListHead == NULL) - { - sNetifListHead = this; - } - else - { - netif = sNetifListHead; - - do - { - if (netif == this) - { - ExitNow(error = kThreadError_Busy); - } - } - while (netif->mNext); - - netif->mNext = this; - } - - mNext = NULL; - - if (mInterfaceId < 0) - { - mInterfaceId = sNextInterfaceId++; - } - -exit: - return error; -} - -ThreadError Netif::RemoveNetif() -{ - ThreadError error = kThreadError_None; - - VerifyOrExit(sNetifListHead != NULL, error = kThreadError_Busy); - - if (sNetifListHead == this) - { - sNetifListHead = mNext; - } - else - { - for (Netif *netif = sNetifListHead; netif->mNext; netif = netif->mNext) - { - if (netif->mNext != this) - { - continue; - } - - netif->mNext = mNext; - break; - } - } - - mNext = NULL; - -exit: - return error; -} - Netif *Netif::GetNext() const { return mNext; @@ -152,38 +83,6 @@ Ip6 &Netif::GetIp6(void) return mIp6; } -Netif *Netif::GetNetifById(int8_t aInterfaceId) -{ - Netif *netif; - - for (netif = sNetifListHead; netif; netif = netif->mNext) - { - if (netif->mInterfaceId == aInterfaceId) - { - ExitNow(); - } - } - -exit: - return netif; -} - -Netif *Netif::GetNetifByName(char *aName) -{ - Netif *netif; - - for (netif = sNetifListHead; netif; netif = netif->mNext) - { - if (strcmp(netif->GetName(), aName) == 0) - { - ExitNow(); - } - } - -exit: - return netif; -} - int8_t Netif::GetInterfaceId() const { return mInterfaceId; @@ -332,7 +231,6 @@ exit: return error; } - ThreadError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress) { ThreadError error = kThreadError_None; @@ -422,23 +320,15 @@ exit: return error; } -Netif *Netif::GetNetifList() -{ - return sNetifListHead; -} - -bool Netif::IsUnicastAddress(const Address &aAddress) +bool Netif::IsUnicastAddress(const Address &aAddress) const { bool rval = false; - for (Netif *netif = sNetifListHead; netif; netif = netif->mNext) + for (const NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext()) { - for (NetifUnicastAddress *cur = netif->mUnicastAddresses; cur; cur = cur->GetNext()) + if (cur->GetAddress() == aAddress) { - if (cur->GetAddress() == aAddress) - { - ExitNow(rval = true); - } + ExitNow(rval = true); } } @@ -446,109 +336,6 @@ exit: return rval; } -const NetifUnicastAddress *Netif::SelectSourceAddress(MessageInfo &aMessageInfo) -{ - Address *destination = &aMessageInfo.GetPeerAddr(); - int interfaceId = aMessageInfo.mInterfaceId; - const NetifUnicastAddress *rvalAddr = NULL; - const Address *candidateAddr; - int8_t candidateId; - int8_t rvalIface = 0; - - for (Netif *netif = GetNetifList(); netif; netif = netif->mNext) - { - candidateId = netif->GetInterfaceId(); - - for (const NetifUnicastAddress *addr = netif->GetUnicastAddresses(); addr; addr = addr->GetNext()) - { - candidateAddr = &addr->GetAddress(); - - if (destination->IsLinkLocal() || destination->IsMulticast()) - { - if (interfaceId != candidateId) - { - continue; - } - } - - if (rvalAddr == NULL) - { - // Rule 0: Prefer any address - rvalAddr = addr; - rvalIface = candidateId; - } - else if (*candidateAddr == *destination) - { - // Rule 1: Prefer same address - rvalAddr = addr; - rvalIface = candidateId; - goto exit; - } - else if (candidateAddr->GetScope() < rvalAddr->GetAddress().GetScope()) - { - // Rule 2: Prefer appropriate scope - if (candidateAddr->GetScope() >= destination->GetScope()) - { - rvalAddr = addr; - rvalIface = candidateId; - } - } - else if (candidateAddr->GetScope() > rvalAddr->GetAddress().GetScope()) - { - if (rvalAddr->GetAddress().GetScope() < destination->GetScope()) - { - rvalAddr = addr; - rvalIface = candidateId; - } - } - else if (addr->mPreferredLifetime != 0 && rvalAddr->mPreferredLifetime == 0) - { - // Rule 3: Avoid deprecated addresses - rvalAddr = addr; - rvalIface = candidateId; - } - else if (aMessageInfo.mInterfaceId != 0 && aMessageInfo.mInterfaceId == candidateId && - rvalIface != candidateId) - { - // Rule 4: Prefer home address - // Rule 5: Prefer outgoing interface - rvalAddr = addr; - rvalIface = candidateId; - } - else if (destination->PrefixMatch(*candidateAddr) > destination->PrefixMatch(rvalAddr->GetAddress())) - { - // Rule 6: Prefer matching label - // Rule 7: Prefer public address - // Rule 8: Use longest prefix matching - rvalAddr = addr; - rvalIface = candidateId; - } - } - } - -exit: - aMessageInfo.mInterfaceId = rvalIface; - return rvalAddr; -} - -int8_t Netif::GetOnLinkNetif(const Address &aAddress) -{ - int8_t rval = -1; - - for (Netif *netif = sNetifListHead; netif; netif = netif->mNext) - { - for (NetifUnicastAddress *cur = netif->mUnicastAddresses; cur; cur = cur->GetNext()) - { - if (cur->GetAddress().PrefixMatch(aAddress) >= cur->mPrefixLength) - { - ExitNow(rval = netif->mInterfaceId); - } - } - } - -exit: - return rval; -} bool Netif::IsStateChangedCallbackPending(void) { diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp index b99a03aeb..56130433f 100644 --- a/src/core/net/netif.hpp +++ b/src/core/net/netif.hpp @@ -194,6 +194,8 @@ private: */ class Netif { + friend class Ip6; + public: /** * This constructor initializes the network interface. @@ -203,24 +205,6 @@ public: */ Netif(Ip6 &aIp6); - /** - * This method enables the network interface. - * - * @retval kThreadError_None Successfully enabled the network interface. - * @retval KThreadError_Busy The network interface was already enabled. - * - */ - ThreadError AddNetif(void); - - /** - * This method disables the network interface. - * - * @retval kThreadError_None Successfully disabled the network interface. - * @retval KThreadError_Busy The network interface was already disabled. - * - */ - ThreadError RemoveNetif(void); - /** * This method returns a reference to the IPv6 network object. * @@ -298,6 +282,16 @@ public: */ ThreadError RemoveExternalUnicastAddress(const Address &aAddress); + /** + * This method indicates whether or not an address is assigned to this interface. + * + * @param[in] aAddress A reference to the unicast address. + * + * @returns TRUE if @p aAddress is assigned to this interface, FALSE otherwise. + * + */ + bool IsUnicastAddress(const Address &aAddress) const; + /** * This method indicates whether or not the network interface is subscribed to a multicast address. * @@ -413,64 +407,8 @@ public: virtual ThreadError RouteLookup(const Address &aSource, const Address &aDestination, uint8_t *aPrefixMatch) = 0; - /** - * This static method returns the network interface list. - * - * @returns A pointer to the network interface list. - * - */ - static Netif *GetNetifList(void); - - /** - * This static method returns the network interface identified by @p aInterfaceId. - * - * @param[in] aInterfaceId The network interface ID. - * - * @returns A pointer to the network interface or NULL if none is found. - * - */ - static Netif *GetNetifById(int8_t aInterfaceId); - - /** - * This static method returns the network interface identified by @p aName. - * - * @param[in] aName A pointer to a NULL-terminated string. - * - * @returns A pointer to the network interface or NULL if none is found. - * - */ - static Netif *GetNetifByName(char *aName); - - /** - * This static method indicates whether or not @p aAddress is assigned to a network interface. - * - * @param[in] aAddress A reference to the IPv6 address. - * - * @retval TRUE If the IPv6 address is assigned to a network interface. - * @retval FALSE If the IPv6 address is not assigned to any network interface. - * - */ - static bool IsUnicastAddress(const Address &aAddress); - - /** - * This static method perform default source address selection. - * - * @param[in] aMessageInfo A reference to the message information. - * - * @returns A pointer to the selected IPv6 source address or NULL if no source address was found. - * - */ - static const NetifUnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo); - - /** - * This static method determines which network interface @p aAddress is on-link, if any. - * - * @param[in] aAddress A reference to the IPv6 address. - * - * @returns The network interface identifier for the on-link interface or -1 if none is found. - * - */ - static int8_t GetOnLinkNetif(const Address &aAddress); +protected: + Ip6 &mIp6; private: static void HandleStateChangedTask(void *aContext); @@ -484,8 +422,6 @@ private: Tasklet mStateChangedTask; Netif *mNext; - Ip6 &mIp6; - uint32_t mStateChangedFlags; NetifUnicastAddress mExtUnicastAddresses[OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS]; diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index 0a4ef4037..d8080510c 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -82,7 +82,7 @@ ThreadError ThreadNetif::Up(void) VerifyOrExit(!mIsUp, error = kThreadError_Already); - Netif::AddNetif(); + mIp6.AddNetif(*this); mMeshForwarder.Start(); mCoapServer.Start(); mMleRouter.Enable(); @@ -97,7 +97,7 @@ ThreadError ThreadNetif::Down(void) mCoapServer.Stop(); mMleRouter.Disable(); mMeshForwarder.Stop(); - Netif::RemoveNetif(); + mIp6.RemoveNetif(*this); mIsUp = false; return kThreadError_None; }