diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 8a357138e..fbbb1a27f 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -95,6 +95,7 @@ noinst_HEADERS = \ net/icmp6.hpp \ net/ip6.hpp \ net/ip6_address.hpp \ + net/ip6_headers.hpp \ net/ip6_filter.hpp \ net/ip6_mpl.hpp \ net/ip6_routes.hpp \ diff --git a/src/core/net/icmp6.cpp b/src/core/net/icmp6.cpp index 06f9136e4..2a9bdcc0e 100644 --- a/src/core/net/icmp6.cpp +++ b/src/core/net/icmp6.cpp @@ -43,6 +43,9 @@ using Thread::Encoding::BigEndian::HostSwap16; namespace Thread { + +extern Ip6::Ip6 *sIp6; + namespace Ip6 { bool Icmp::sIsEchoEnabled = true; @@ -54,7 +57,7 @@ void *Icmp::sEchoReplyContext = NULL; Message *Icmp::NewMessage(uint16_t aReserved) { - return Ip6::NewMessage(sizeof(IcmpHeader) + aReserved); + return sIp6->NewMessage(sizeof(IcmpHeader) + aReserved); } ThreadError Icmp::RegisterCallbacks(IcmpHandler &aHandler) @@ -97,7 +100,7 @@ ThreadError Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessage SuccessOrExit(error = aMessage.Prepend(&icmpHeader, sizeof(icmpHeader))); aMessage.SetOffset(0); - SuccessOrExit(error = Ip6::SendDatagram(aMessage, messageInfoLocal, kProtoIcmp6)); + SuccessOrExit(error = sIp6->SendDatagram(aMessage, messageInfoLocal, kProtoIcmp6)); otLogInfoIcmp("Sent echo request\n"); @@ -113,7 +116,7 @@ ThreadError Icmp::SendError(const Address &aDestination, IcmpHeader::Type aType, Message *message = NULL; IcmpHeader icmp6Header; - VerifyOrExit((message = Ip6::NewMessage(0)) != NULL, error = kThreadError_NoBufs); + VerifyOrExit((message = sIp6->NewMessage(0)) != NULL, error = kThreadError_NoBufs); SuccessOrExit(error = message->SetLength(sizeof(icmp6Header) + sizeof(aHeader))); message->Write(sizeof(icmp6Header), sizeof(aHeader), &aHeader); @@ -126,7 +129,7 @@ ThreadError Icmp::SendError(const Address &aDestination, IcmpHeader::Type aType, memset(&messageInfo, 0, sizeof(messageInfo)); messageInfo.mPeerAddr = aDestination; - SuccessOrExit(error = Ip6::SendDatagram(*message, messageInfo, kProtoIcmp6)); + SuccessOrExit(error = sIp6->SendDatagram(*message, messageInfo, kProtoIcmp6)); otLogInfoIcmp("Sent ICMPv6 Error\n"); @@ -203,7 +206,7 @@ ThreadError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo icmp6Header.Init(); icmp6Header.SetType(IcmpHeader::kTypeEchoReply); - VerifyOrExit((replyMessage = Ip6::NewMessage(0)) != NULL, otLogDebgIcmp("icmp fail\n")); + VerifyOrExit((replyMessage = sIp6->NewMessage(0)) != NULL, otLogDebgIcmp("icmp fail\n")); payloadLength = aRequestMessage.GetLength() - aRequestMessage.GetOffset() - IcmpHeader::GetDataOffset(); SuccessOrExit(replyMessage->SetLength(IcmpHeader::GetDataOffset() + payloadLength)); @@ -221,7 +224,7 @@ ThreadError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo replyMessageInfo.mInterfaceId = aMessageInfo.mInterfaceId; - SuccessOrExit(error = Ip6::SendDatagram(*replyMessage, replyMessageInfo, kProtoIcmp6)); + SuccessOrExit(error = sIp6->SendDatagram(*replyMessage, replyMessageInfo, kProtoIcmp6)); otLogInfoIcmp("Sent Echo Reply\n"); diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 1073fd55f..2cf22b658 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -48,32 +47,22 @@ namespace Thread { namespace Ip6 { -static otDEFINE_ALIGNED_VAR(sMplBuf, sizeof(Mpl), uint64_t); -static Mpl *sMpl; -static bool sForwardingEnabled; - -static otReceiveIp6DatagramCallback sReceiveIp6DatagramCallback = NULL; -static void *sReceiveIp6DatagramCallbackContext = NULL; -static bool sIsReceiveIp6FilterEnabled; - -static ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo); +Ip6::Ip6(void): + mForwardingEnabled(false), + mReceiveIp6DatagramCallback(NULL), + mReceiveIp6DatagramCallbackContext(NULL), + mIsReceiveIp6FilterEnabled(false) +{ +} Message *Ip6::NewMessage(uint16_t reserved) { - return Message::New(Message::kTypeIp6, - sizeof(Header) + sizeof(HopByHopHeader) + sizeof(OptionMpl) + reserved); -} - -void Ip6::Init(void) -{ - sMpl = new(&sMplBuf) Mpl; - sForwardingEnabled = false; - sIsReceiveIp6FilterEnabled = true; + return Message::New(Message::kTypeIp6, sizeof(Header) + sizeof(HopByHopHeader) + sizeof(OptionMpl) + reserved); } void Ip6::SetForwardingEnabled(bool aEnable) { - sForwardingEnabled = aEnable; + mForwardingEnabled = aEnable; } uint16_t Ip6::UpdateChecksum(uint16_t checksum, uint16_t val) @@ -113,21 +102,21 @@ uint16_t Ip6::ComputePseudoheaderChecksum(const Address &src, const Address &dst void Ip6::SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback, void *aCallbackContext) { - sReceiveIp6DatagramCallback = aCallback; - sReceiveIp6DatagramCallbackContext = aCallbackContext; + mReceiveIp6DatagramCallback = aCallback; + mReceiveIp6DatagramCallbackContext = aCallbackContext; } bool Ip6::IsReceiveIp6FilterEnabled(void) { - return sIsReceiveIp6FilterEnabled; + return mIsReceiveIp6FilterEnabled; } void Ip6::SetReceiveIp6FilterEnabled(bool aEnabled) { - sIsReceiveIp6FilterEnabled = aEnabled; + mIsReceiveIp6FilterEnabled = aEnabled; } -ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength) +ThreadError Ip6::AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength) { ThreadError error = kThreadError_None; HopByHopHeader hbhHeader; @@ -135,7 +124,7 @@ ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, u hbhHeader.SetNextHeader(nextHeader); hbhHeader.SetLength(0); - sMpl->InitOption(mplOption, HostSwap16(header.GetSource().mFields.m16[7])); + mMpl.InitOption(mplOption, HostSwap16(header.GetSource().mFields.m16[7])); SuccessOrExit(error = message.Prepend(&mplOption, sizeof(mplOption))); SuccessOrExit(error = message.Prepend(&hbhHeader, sizeof(hbhHeader))); header.SetPayloadLength(sizeof(hbhHeader) + sizeof(mplOption) + payloadLength); @@ -209,7 +198,7 @@ exit: return error; } -ThreadError HandleOptions(Message &message) +ThreadError Ip6::HandleOptions(Message &message) { ThreadError error = kThreadError_None; HopByHopHeader hbhHeader; @@ -228,7 +217,7 @@ ThreadError HandleOptions(Message &message) switch (optionHeader.GetType()) { case OptionMpl::kType: - SuccessOrExit(error = sMpl->ProcessOption(message)); + SuccessOrExit(error = mMpl.ProcessOption(message)); break; default: @@ -260,7 +249,7 @@ exit: return error; } -ThreadError HandleFragment(Message &message) +ThreadError Ip6::HandleFragment(Message &message) { ThreadError error = kThreadError_None; FragmentHeader fragmentHeader; @@ -276,7 +265,7 @@ exit: return error; } -ThreadError HandleExtensionHeaders(Message &message, uint8_t &nextHeader, bool receive) +ThreadError Ip6::HandleExtensionHeaders(Message &message, uint8_t &nextHeader, bool receive) { ThreadError error = kThreadError_None; ExtensionHeader extensionHeader; @@ -339,9 +328,9 @@ void Ip6::ProcessReceiveCallback(const Message &aMessage, const MessageInfo &mes ThreadError error = kThreadError_None; Message *messageCopy = NULL; - VerifyOrExit(sReceiveIp6DatagramCallback != NULL, ;); + VerifyOrExit(mReceiveIp6DatagramCallback != NULL, ;); - if (sIsReceiveIp6FilterEnabled) + if (mIsReceiveIp6FilterEnabled) { // do not pass messages sent to/from an RLOC VerifyOrExit(!messageInfo.GetSockAddr().IsRoutingLocator() && @@ -384,7 +373,7 @@ void Ip6::ProcessReceiveCallback(const Message &aMessage, const MessageInfo &mes aMessage.CopyTo(0, 0, aMessage.GetLength(), *messageCopy); messageCopy->SetLinkSecurityEnabled(aMessage.IsLinkSecurityEnabled()); - sReceiveIp6DatagramCallback(messageCopy, sReceiveIp6DatagramCallbackContext); + mReceiveIp6DatagramCallback(messageCopy, mReceiveIp6DatagramCallbackContext); exit: @@ -464,7 +453,7 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, int8_t interface } } - if (!sForwardingEnabled && netif != NULL) + if (!mForwardingEnabled && netif != NULL) { forward = false; } @@ -516,7 +505,7 @@ exit: return error; } -ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo) +ThreadError Ip6::ForwardMessage(Message &message, MessageInfo &messageInfo) { ThreadError error = kThreadError_None; int8_t interfaceId; diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index a72473f83..8f1bfa036 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -84,393 +86,6 @@ namespace Ip6 { * */ -/** - * Internet Protocol Numbers - */ -enum IpProto -{ - kProtoHopOpts = 0, ///< IPv6 Hop-by-Hop Option - kProtoTcp = 6, ///< Transmission Control Protocol - kProtoUdp = 17, ///< User Datagram - kProtoIp6 = 41, ///< IPv6 encapsulation - kProtoRouting = 43, ///< Routing Header for IPv6 - kProtoFragment = 44, ///< Fragment Header for IPv6 - kProtoIcmp6 = 58, ///< ICMP for IPv6 - kProtoNone = 59, ///< No Next Header for IPv6 - kProtoDstOpts = 60, ///< Destination Options for IPv6 -}; - -enum -{ - kVersionClassFlowSize = 4, ///< Combined size of Version, Class, Flow Label in bytes. -}; - -/** - * This structure represents an IPv6 header. - * - */ -OT_TOOL_PACKED_BEGIN -struct HeaderPoD -{ - union - { - uint8_t m8[kVersionClassFlowSize / sizeof(uint8_t)]; - uint16_t m16[kVersionClassFlowSize / sizeof(uint16_t)]; - uint32_t m32[kVersionClassFlowSize / sizeof(uint32_t)]; - } mVersionClassFlow; ///< Version, Class, Flow Label - uint16_t mPayloadLength; ///< Payload Length - uint8_t mNextHeader; ///< Next Header - uint8_t mHopLimit; ///< Hop Limit - otIp6Address mSource; ///< Source - otIp6Address mDestination; ///< Destination -} OT_TOOL_PACKED_END; - -/** - * This class implements IPv6 header generation and parsing. - * - */ -OT_TOOL_PACKED_BEGIN -class Header: private HeaderPoD -{ -public: - /** - * This method initializes the IPv6 header. - * - */ - void Init() { mVersionClassFlow.m32[0] = 0; mVersionClassFlow.m8[0] = kVersion6; } - - /** - * This method indicates whether or not the IPv6 Version is set to 6. - * - * @retval TRUE If the IPv6 Version is set to 6. - * @retval FALSE If the IPv6 Version is not set to 6. - * - */ - bool IsVersion6() const { return (mVersionClassFlow.m8[0] & kVersionMask) == kVersion6; } - - /** - * This method returns the IPv6 Payload Length value. - * - * @returns The IPv6 Payload Length value. - * - */ - uint16_t GetPayloadLength() { return HostSwap16(mPayloadLength); } - - /** - * This method sets the IPv6 Payload Length value. - * - * @param[in] aLength The IPv6 Payload Length value. - * - */ - void SetPayloadLength(uint16_t aLength) { mPayloadLength = HostSwap16(aLength); } - - /** - * This method returns the IPv6 Next Header value. - * - * @returns The IPv6 Next Header value. - * - */ - IpProto GetNextHeader() const { return static_cast(mNextHeader); } - - /** - * This method sets the IPv6 Next Header value. - * - * @param[in] aNextHeader The IPv6 Next Header value. - * - */ - void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast(aNextHeader); } - - /** - * This method returns the IPv6 Hop Limit value. - * - * @returns The IPv6 Hop Limit value. - * - */ - uint8_t GetHopLimit() const { return mHopLimit; } - - /** - * This method sets the IPv6 Hop Limit value. - * - * @param[in] aHopLimit The IPv6 Hop Limit value. - * - */ - void SetHopLimit(uint8_t aHopLimit) { mHopLimit = aHopLimit; } - - /** - * This method returns the IPv6 Source address. - * - * @returns A reference to the IPv6 Source address. - * - */ - Address &GetSource() { return static_cast
(mSource); } - - /** - * This method sets the IPv6 Source address. - * - * @param[in] aSource A reference to the IPv6 Source address. - * - */ - void SetSource(const Address &aSource) { mSource = aSource; } - - /** - * This method returns the IPv6 Destination address. - * - * @returns A reference to the IPv6 Destination address. - * - */ - Address &GetDestination() { return static_cast
(mDestination); } - - /** - * This method sets the IPv6 Destination address. - * - * @param[in] aDestination A reference to the IPv6 Destination address. - * - */ - void SetDestination(const Address &aDestination) { mDestination = aDestination; } - - /** - * This static method returns the byte offset of the IPv6 Payload Length field. - * - * @returns The byte offset of the IPv6 Payload Length field. - * - */ - static uint8_t GetPayloadLengthOffset() { return offsetof(HeaderPoD, mPayloadLength); } - - /** - * This static method returns the byte offset of the IPv6 Hop Limit field. - * - * @returns The byte offset of the IPv6 Hop Limit field. - * - */ - static uint8_t GetHopLimitOffset() { return offsetof(HeaderPoD, mHopLimit); } - - /** - * This static method returns the size of the IPv6 Hop Limit field. - * - * @returns The size of the IPv6 Hop Limit field. - * - */ - static uint8_t GetHopLimitSize() { return sizeof(uint8_t); } - - /** - * This static method returns the byte offset of the IPv6 Destination field. - * - * @returns The byte offset of the IPv6 Destination field. - * - */ - static uint8_t GetDestinationOffset() { return offsetof(HeaderPoD, mDestination); } - -private: - enum - { - kVersion6 = 0x60, - kVersionMask = 0xf0, - }; -} OT_TOOL_PACKED_END; - -/** - * This class implements IPv6 Extension Header generation and processing. - * - */ -OT_TOOL_PACKED_BEGIN -class ExtensionHeader -{ -public: - /** - * This method returns the IPv6 Next Header value. - * - * @returns The IPv6 Next Header value. - * - */ - IpProto GetNextHeader() const { return static_cast(mNextHeader); } - - /** - * This method sets the IPv6 Next Header value. - * - * @param[in] aNextHeader The IPv6 Next Header value. - * - */ - void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast(aNextHeader); } - - /** - * This method returns the IPv6 Header Extension Length value. - * - * @returns The IPv6 Header Extension Length value. - * - */ - uint8_t GetLength() const { return mLength; } - - /** - * This method sets the IPv6 Header Extension Length value. - * - * @param[in] aLength The IPv6 Header Extension Length value. - * - */ - void SetLength(uint8_t aLength) { mLength = aLength; } - -private: - uint8_t mNextHeader; - uint8_t mLength; -} OT_TOOL_PACKED_END; - -/** - * This class implements IPv6 Hop-by-Hop Options Header generation and parsing. - * - */ -OT_TOOL_PACKED_BEGIN -class HopByHopHeader: public ExtensionHeader -{ -} OT_TOOL_PACKED_END; - -/** - * This class implements IPv6 Options generation and parsing. - * - */ -OT_TOOL_PACKED_BEGIN -class OptionHeader -{ -public: - /** - * This method returns the IPv6 Option Type value. - * - * @returns The IPv6 Option Type value. - * - */ - uint8_t GetType() const { return mType; } - - /** - * This method sets the IPv6 Option Type value. - * - * @param[in] aType The IPv6 Option Type value. - * - */ - void SetType(uint8_t aType) { mType = aType; } - - /** - * IPv6 Option Type actions for unrecognized IPv6 Options. - * - */ - enum Action - { - kActionSkip = 0x00, ///< skip over this option and continue processing the header - kActionDiscard = 0x40, ///< discard the packet - kActionForceIcmp = 0x80, ///< discard the packet and forcibly send an ICMP Parameter Problem - kActionIcmp = 0xc0, ///< discard packet and conditionally send an ICMP Parameter Problem - kActionMask = 0xc0, ///< mask for action bits - }; - - /** - * This method returns the IPv6 Option action for unrecognized IPv6 Options. - * - * @returns The IPv6 Option action for unrecognized IPv6 Options. - * - */ - Action GetAction() const { return static_cast(mType & kActionMask); } - - /** - * This method returns the IPv6 Option Length value. - * - * @returns The IPv6 Option Length value. - * - */ - uint8_t GetLength() const { return mLength; } - - /** - * This method sets the IPv6 Option Length value. - * - * @param[in] aLength The IPv6 Option Length value. - * - */ - void SetLength(uint8_t aLength) { mLength = aLength; } - -private: - uint8_t mType; - uint8_t mLength; -} OT_TOOL_PACKED_END; - -/** - * This class implements IPv6 Fragment Header generation and parsing. - * - */ -OT_TOOL_PACKED_BEGIN -class FragmentHeader -{ -public: - /** - * This method initializes the IPv6 Fragment header. - * - */ - void Init() { mReserved = 0; mIdentification = 0; } - - /** - * This method returns the IPv6 Next Header value. - * - * @returns The IPv6 Next Header value. - * - */ - IpProto GetNextHeader() const { return static_cast(mNextHeader); } - - /** - * This method sets the IPv6 Next Header value. - * - * @param[in] aNextHeader The IPv6 Next Header value. - * - */ - void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast(aNextHeader); } - - /** - * This method returns the Fragment Offset value. - * - * @returns The Fragment Offset value. - * - */ - uint16_t GetOffset() { return (HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; } - - /** - * This method sets the Fragment Offset value. - * - * @param[in] aOffset The Fragment Offset value. - */ - void SetOffset(uint16_t aOffset) { - uint16_t tmp = HostSwap16(mOffsetMore); - tmp = (tmp & ~kOffsetMask) | ((aOffset << kOffsetOffset) & kOffsetMask); - mOffsetMore = HostSwap16(tmp); - } - - /** - * This method returns the M flag value. - * - * @returns The M flag value. - * - */ - bool IsMoreFlagSet() { return HostSwap16(mOffsetMore) & kMoreFlag; } - - /** - * This method clears the M flag value. - * - */ - void ClearMoreFlag() { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) & ~kMoreFlag); } - - /** - * This method sets the M flag value. - * - */ - void SetMoreFlag() { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) | kMoreFlag); } - -private: - uint8_t mNextHeader; - uint8_t mReserved; - - enum - { - kOffsetOffset = 3, - kOffsetMask = 0xfff8, - kMoreFlag = 1, - }; - uint16_t mOffsetMore; - uint32_t mIdentification; -} OT_TOOL_PACKED_END; - /** * This class implements the core IPv6 message processing. * @@ -485,22 +100,22 @@ public: }; /** - * This static method allocates a new message buffer from the buffer pool. + * This method allocates a new message buffer from the buffer pool. * * @param[in] aReserved The number of header bytes to reserve following the IPv6 header. * * @returns A pointer to the message or NULL if insufficient message buffers are available. * */ - static Message *NewMessage(uint16_t aReserved); + Message *NewMessage(uint16_t aReserved); /** - * This static method for initialization. + * This constructor initializes the object. */ - static void Init(void); + Ip6(void); /** - * This static method sends an IPv6 datagram. + * This method sends an IPv6 datagram. * * @param[in] aMessage A reference to the message. * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. @@ -510,10 +125,10 @@ public: * @retval kThreadError_NoBufs Insufficient available buffer to add the IPv6 headers. * */ - static ThreadError SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, IpProto aIpProto); + ThreadError SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, IpProto aIpProto); /** - * This static method processes a received IPv6 datagram. + * This method processes a received IPv6 datagram. * * @param[in] aMessage A reference to the message. * @param[in] aNetif A pointer to the network interface that received the message. @@ -525,8 +140,8 @@ public: * @retval kThreadError_Drop Message processing failed and the message should be dropped. * */ - static ThreadError HandleDatagram(Message &aMessage, Netif *aNetif, int8_t aInterfaceId, - const void *aLinkMessageInfo, bool aFromNcpHost); + ThreadError HandleDatagram(Message &aMessage, Netif *aNetif, int8_t aInterfaceId, + const void *aLinkMessageInfo, bool aFromNcpHost); /** * This static method updates a checksum. @@ -590,7 +205,7 @@ public: * @sa SetReceiveIp6FilterEnabled * */ - static void SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback, void *aCallbackContext); + void SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback, void *aCallbackContext); /** * This method indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams @@ -602,7 +217,7 @@ public: * @sa SetReceiveIp6FilterEnabled * */ - static bool IsReceiveIp6FilterEnabled(void); + bool IsReceiveIp6FilterEnabled(void); /** * This method sets whether or not Thread control traffic is filtered out when delivering IPv6 datagrams @@ -614,18 +229,30 @@ public: * @sa IsReceiveIp6FilterEnabled * */ - static void SetReceiveIp6FilterEnabled(bool aEnabled); + void SetReceiveIp6FilterEnabled(bool aEnabled); /** - * This static method enables/disables IPv6 forwarding. + * This method enables/disables IPv6 forwarding. * * @param[in] aEnable TRUE to enable IPv6 forwarding, FALSE otherwise. * */ - static void SetForwardingEnabled(bool aEnable); + void SetForwardingEnabled(bool aEnable); private: - static void ProcessReceiveCallback(const Message &aMessage, const MessageInfo &aMessageInfo, uint8_t aIpProto); + void ProcessReceiveCallback(const Message &aMessage, const MessageInfo &aMessageInfo, uint8_t aIpProto); + ThreadError HandleExtensionHeaders(Message &message, uint8_t &nextHeader, bool receive); + ThreadError HandleFragment(Message &message); + ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength); + ThreadError HandleOptions(Message &message); + ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo); + + Mpl mMpl; + bool mForwardingEnabled; + + otReceiveIp6DatagramCallback mReceiveIp6DatagramCallback; + void *mReceiveIp6DatagramCallbackContext; + bool mIsReceiveIp6FilterEnabled; }; /** diff --git a/src/core/net/ip6_headers.hpp b/src/core/net/ip6_headers.hpp new file mode 100644 index 000000000..10a7d18be --- /dev/null +++ b/src/core/net/ip6_headers.hpp @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2016, Nest Labs, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes definitions for IPv6 packet processing. + */ + +#ifndef IP6_HEADERS_HPP_ +#define IP6_HEADERS_HPP_ + +#include + +#include +#include +#include +#include +#include +#include + +using Thread::Encoding::BigEndian::HostSwap16; + +namespace Thread { + +/** + * @namespace Thread::Ip6 + * + * @brief + * This namespace includes definitions for IPv6 networking. + * + */ +namespace Ip6 { + +/** + * @addtogroup core-ipv6 + * + * @brief + * This module includes definitions for the IPv6 network layer. + * + * @{ + * + * @defgroup core-ip6-icmp6 ICMPv6 + * @defgroup core-ip6-ip6 IPv6 + * @defgroup core-ip6-mpl MPL + * @defgroup core-ip6-netif Network Interfaces + * + * @} + * + */ + +/** + * @addtogroup core-ip6-ip6 + * + * @brief + * This module includes definitions for core IPv6 networking. + * + * @{ + * + */ + +/** + * Internet Protocol Numbers + */ +enum IpProto +{ + kProtoHopOpts = 0, ///< IPv6 Hop-by-Hop Option + kProtoTcp = 6, ///< Transmission Control Protocol + kProtoUdp = 17, ///< User Datagram + kProtoIp6 = 41, ///< IPv6 encapsulation + kProtoRouting = 43, ///< Routing Header for IPv6 + kProtoFragment = 44, ///< Fragment Header for IPv6 + kProtoIcmp6 = 58, ///< ICMP for IPv6 + kProtoNone = 59, ///< No Next Header for IPv6 + kProtoDstOpts = 60, ///< Destination Options for IPv6 +}; + +enum +{ + kVersionClassFlowSize = 4, ///< Combined size of Version, Class, Flow Label in bytes. +}; + +/** + * This structure represents an IPv6 header. + * + */ +OT_TOOL_PACKED_BEGIN +struct HeaderPoD +{ + union + { + uint8_t m8[kVersionClassFlowSize / sizeof(uint8_t)]; + uint16_t m16[kVersionClassFlowSize / sizeof(uint16_t)]; + uint32_t m32[kVersionClassFlowSize / sizeof(uint32_t)]; + } mVersionClassFlow; ///< Version, Class, Flow Label + uint16_t mPayloadLength; ///< Payload Length + uint8_t mNextHeader; ///< Next Header + uint8_t mHopLimit; ///< Hop Limit + otIp6Address mSource; ///< Source + otIp6Address mDestination; ///< Destination +} OT_TOOL_PACKED_END; + +/** + * This class implements IPv6 header generation and parsing. + * + */ +OT_TOOL_PACKED_BEGIN +class Header: private HeaderPoD +{ +public: + /** + * This method initializes the IPv6 header. + * + */ + void Init() { mVersionClassFlow.m32[0] = 0; mVersionClassFlow.m8[0] = kVersion6; } + + /** + * This method indicates whether or not the IPv6 Version is set to 6. + * + * @retval TRUE If the IPv6 Version is set to 6. + * @retval FALSE If the IPv6 Version is not set to 6. + * + */ + bool IsVersion6() const { return (mVersionClassFlow.m8[0] & kVersionMask) == kVersion6; } + + /** + * This method returns the IPv6 Payload Length value. + * + * @returns The IPv6 Payload Length value. + * + */ + uint16_t GetPayloadLength() { return HostSwap16(mPayloadLength); } + + /** + * This method sets the IPv6 Payload Length value. + * + * @param[in] aLength The IPv6 Payload Length value. + * + */ + void SetPayloadLength(uint16_t aLength) { mPayloadLength = HostSwap16(aLength); } + + /** + * This method returns the IPv6 Next Header value. + * + * @returns The IPv6 Next Header value. + * + */ + IpProto GetNextHeader() const { return static_cast(mNextHeader); } + + /** + * This method sets the IPv6 Next Header value. + * + * @param[in] aNextHeader The IPv6 Next Header value. + * + */ + void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast(aNextHeader); } + + /** + * This method returns the IPv6 Hop Limit value. + * + * @returns The IPv6 Hop Limit value. + * + */ + uint8_t GetHopLimit() const { return mHopLimit; } + + /** + * This method sets the IPv6 Hop Limit value. + * + * @param[in] aHopLimit The IPv6 Hop Limit value. + * + */ + void SetHopLimit(uint8_t aHopLimit) { mHopLimit = aHopLimit; } + + /** + * This method returns the IPv6 Source address. + * + * @returns A reference to the IPv6 Source address. + * + */ + Address &GetSource() { return static_cast
(mSource); } + + /** + * This method sets the IPv6 Source address. + * + * @param[in] aSource A reference to the IPv6 Source address. + * + */ + void SetSource(const Address &aSource) { mSource = aSource; } + + /** + * This method returns the IPv6 Destination address. + * + * @returns A reference to the IPv6 Destination address. + * + */ + Address &GetDestination() { return static_cast
(mDestination); } + + /** + * This method sets the IPv6 Destination address. + * + * @param[in] aDestination A reference to the IPv6 Destination address. + * + */ + void SetDestination(const Address &aDestination) { mDestination = aDestination; } + + /** + * This static method returns the byte offset of the IPv6 Payload Length field. + * + * @returns The byte offset of the IPv6 Payload Length field. + * + */ + static uint8_t GetPayloadLengthOffset() { return offsetof(HeaderPoD, mPayloadLength); } + + /** + * This static method returns the byte offset of the IPv6 Hop Limit field. + * + * @returns The byte offset of the IPv6 Hop Limit field. + * + */ + static uint8_t GetHopLimitOffset() { return offsetof(HeaderPoD, mHopLimit); } + + /** + * This static method returns the size of the IPv6 Hop Limit field. + * + * @returns The size of the IPv6 Hop Limit field. + * + */ + static uint8_t GetHopLimitSize() { return sizeof(uint8_t); } + + /** + * This static method returns the byte offset of the IPv6 Destination field. + * + * @returns The byte offset of the IPv6 Destination field. + * + */ + static uint8_t GetDestinationOffset() { return offsetof(HeaderPoD, mDestination); } + +private: + enum + { + kVersion6 = 0x60, + kVersionMask = 0xf0, + }; +} OT_TOOL_PACKED_END; + +/** + * This class implements IPv6 Extension Header generation and processing. + * + */ +OT_TOOL_PACKED_BEGIN +class ExtensionHeader +{ +public: + /** + * This method returns the IPv6 Next Header value. + * + * @returns The IPv6 Next Header value. + * + */ + IpProto GetNextHeader() const { return static_cast(mNextHeader); } + + /** + * This method sets the IPv6 Next Header value. + * + * @param[in] aNextHeader The IPv6 Next Header value. + * + */ + void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast(aNextHeader); } + + /** + * This method returns the IPv6 Header Extension Length value. + * + * @returns The IPv6 Header Extension Length value. + * + */ + uint8_t GetLength() const { return mLength; } + + /** + * This method sets the IPv6 Header Extension Length value. + * + * @param[in] aLength The IPv6 Header Extension Length value. + * + */ + void SetLength(uint8_t aLength) { mLength = aLength; } + +private: + uint8_t mNextHeader; + uint8_t mLength; +} OT_TOOL_PACKED_END; + +/** + * This class implements IPv6 Hop-by-Hop Options Header generation and parsing. + * + */ +OT_TOOL_PACKED_BEGIN +class HopByHopHeader: public ExtensionHeader +{ +} OT_TOOL_PACKED_END; + +/** + * This class implements IPv6 Options generation and parsing. + * + */ +OT_TOOL_PACKED_BEGIN +class OptionHeader +{ +public: + /** + * This method returns the IPv6 Option Type value. + * + * @returns The IPv6 Option Type value. + * + */ + uint8_t GetType() const { return mType; } + + /** + * This method sets the IPv6 Option Type value. + * + * @param[in] aType The IPv6 Option Type value. + * + */ + void SetType(uint8_t aType) { mType = aType; } + + /** + * IPv6 Option Type actions for unrecognized IPv6 Options. + * + */ + enum Action + { + kActionSkip = 0x00, ///< skip over this option and continue processing the header + kActionDiscard = 0x40, ///< discard the packet + kActionForceIcmp = 0x80, ///< discard the packet and forcibly send an ICMP Parameter Problem + kActionIcmp = 0xc0, ///< discard packet and conditionally send an ICMP Parameter Problem + kActionMask = 0xc0, ///< mask for action bits + }; + + /** + * This method returns the IPv6 Option action for unrecognized IPv6 Options. + * + * @returns The IPv6 Option action for unrecognized IPv6 Options. + * + */ + Action GetAction() const { return static_cast(mType & kActionMask); } + + /** + * This method returns the IPv6 Option Length value. + * + * @returns The IPv6 Option Length value. + * + */ + uint8_t GetLength() const { return mLength; } + + /** + * This method sets the IPv6 Option Length value. + * + * @param[in] aLength The IPv6 Option Length value. + * + */ + void SetLength(uint8_t aLength) { mLength = aLength; } + +private: + uint8_t mType; + uint8_t mLength; +} OT_TOOL_PACKED_END; + +/** + * This class implements IPv6 Fragment Header generation and parsing. + * + */ +OT_TOOL_PACKED_BEGIN +class FragmentHeader +{ +public: + /** + * This method initializes the IPv6 Fragment header. + * + */ + void Init() { mReserved = 0; mIdentification = 0; } + + /** + * This method returns the IPv6 Next Header value. + * + * @returns The IPv6 Next Header value. + * + */ + IpProto GetNextHeader() const { return static_cast(mNextHeader); } + + /** + * This method sets the IPv6 Next Header value. + * + * @param[in] aNextHeader The IPv6 Next Header value. + * + */ + void SetNextHeader(IpProto aNextHeader) { mNextHeader = static_cast(aNextHeader); } + + /** + * This method returns the Fragment Offset value. + * + * @returns The Fragment Offset value. + * + */ + uint16_t GetOffset() { return (HostSwap16(mOffsetMore) & kOffsetMask) >> kOffsetOffset; } + + /** + * This method sets the Fragment Offset value. + * + * @param[in] aOffset The Fragment Offset value. + */ + void SetOffset(uint16_t aOffset) { + uint16_t tmp = HostSwap16(mOffsetMore); + tmp = (tmp & ~kOffsetMask) | ((aOffset << kOffsetOffset) & kOffsetMask); + mOffsetMore = HostSwap16(tmp); + } + + /** + * This method returns the M flag value. + * + * @returns The M flag value. + * + */ + bool IsMoreFlagSet() { return HostSwap16(mOffsetMore) & kMoreFlag; } + + /** + * This method clears the M flag value. + * + */ + void ClearMoreFlag() { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) & ~kMoreFlag); } + + /** + * This method sets the M flag value. + * + */ + void SetMoreFlag() { mOffsetMore = HostSwap16(HostSwap16(mOffsetMore) | kMoreFlag); } + +private: + uint8_t mNextHeader; + uint8_t mReserved; + + enum + { + kOffsetOffset = 3, + kOffsetMask = 0xfff8, + kMoreFlag = 1, + }; + uint16_t mOffsetMore; + uint32_t mIdentification; +} OT_TOOL_PACKED_END; + +/** + * @} + * + */ + +} // namespace Ip6 +} // namespace Thread + +#endif // NET_IP6_HEADERS_HPP_ diff --git a/src/core/net/ip6_mpl.hpp b/src/core/net/ip6_mpl.hpp index d623f4e63..ec8428d06 100644 --- a/src/core/net/ip6_mpl.hpp +++ b/src/core/net/ip6_mpl.hpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include namespace Thread { namespace Ip6 { diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp index 0d5ef8266..6824ff65d 100644 --- a/src/core/net/netif.cpp +++ b/src/core/net/netif.cpp @@ -42,8 +42,9 @@ namespace Ip6 { Netif *Netif::sNetifListHead = NULL; int8_t Netif::sNextInterfaceId = 1; -Netif::Netif() : - mStateChangedTask(&HandleStateChangedTask, this) +Netif::Netif(Ip6 &aIp6): + mStateChangedTask(&HandleStateChangedTask, this), + mIp6(aIp6) { mCallbacks = NULL; mUnicastAddresses = NULL; @@ -146,6 +147,11 @@ Netif *Netif::GetNext() const return mNext; } +Ip6 &Netif::GetIp6(void) +{ + return mIp6; +} + Netif *Netif::GetNetifById(int8_t aInterfaceId) { Netif *netif; diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp index 9bc9e92c3..b99a03aeb 100644 --- a/src/core/net/netif.hpp +++ b/src/core/net/netif.hpp @@ -43,6 +43,8 @@ namespace Thread { namespace Ip6 { +class Ip6; + /** * @addtogroup core-ip6-netif * @@ -196,8 +198,10 @@ public: /** * This constructor initializes the network interface. * + * @param[in] aIp6 A reference to the IPv6 network object. + * */ - Netif(void); + Netif(Ip6 &aIp6); /** * This method enables the network interface. @@ -217,6 +221,14 @@ public: */ ThreadError RemoveNetif(void); + /** + * This method returns a reference to the IPv6 network object. + * + * @returns A reference to the IPv6 network object. + * + */ + Ip6 &GetIp6(void); + /** * This method returns the next network interface in the list. * @@ -472,6 +484,8 @@ private: Tasklet mStateChangedTask; Netif *mNext; + Ip6 &mIp6; + uint32_t mStateChangedFlags; NetifUnicastAddress mExtUnicastAddresses[OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS]; diff --git a/src/core/net/tcp.hpp b/src/core/net/tcp.hpp index e7acb13d8..cb5d77627 100644 --- a/src/core/net/tcp.hpp +++ b/src/core/net/tcp.hpp @@ -35,7 +35,7 @@ #define TCP_HPP_ #include -#include +#include namespace Thread { namespace Ip6 { diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp index ab7811ea7..7f7cca990 100644 --- a/src/core/net/udp6.cpp +++ b/src/core/net/udp6.cpp @@ -41,6 +41,9 @@ using Thread::Encoding::BigEndian::HostSwap16; namespace Thread { + +extern Ip6::Ip6 *sIp6; + namespace Ip6 { UdpSocket *Udp::sSockets = NULL; @@ -135,7 +138,7 @@ ThreadError UdpSocket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo SuccessOrExit(error = aMessage.Prepend(&udpHeader, sizeof(udpHeader))); aMessage.SetOffset(0); - SuccessOrExit(error = Ip6::SendDatagram(aMessage, messageInfoLocal, kProtoUdp)); + SuccessOrExit(error = sIp6->SendDatagram(aMessage, messageInfoLocal, kProtoUdp)); exit: return error; @@ -143,7 +146,7 @@ exit: Message *Udp::NewMessage(uint16_t aReserved) { - return Ip6::NewMessage(sizeof(UdpHeader) + aReserved); + return sIp6->NewMessage(sizeof(UdpHeader) + aReserved); } ThreadError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo) diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index d6a99b978..baea4a73b 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -57,6 +57,9 @@ ThreadNetif *sThreadNetif; static Ip6::NetifCallback sNetifCallback; static bool mEnabled = false; +static otDEFINE_ALIGNED_VAR(sIp6Raw, sizeof(Ip6::Ip6), uint64_t); +Ip6::Ip6 *sIp6; + #ifdef __cplusplus extern "C" { #endif @@ -870,8 +873,8 @@ ThreadError otEnable(void) otLogInfoApi("otEnable\n"); Message::Init(); - sThreadNetif = new(&sThreadNetifRaw) ThreadNetif; - Ip6::Ip6::Init(); + sIp6 = new(&sIp6Raw) Ip6::Ip6; + sThreadNetif = new(&sThreadNetifRaw) ThreadNetif(*sIp6); mEnabled = true; exit: @@ -1047,23 +1050,22 @@ void HandleMleDiscover(otActiveScanResult *aResult, void *aContext) void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback, void *aCallbackContext) { - Ip6::Ip6::SetReceiveDatagramCallback(aCallback, aCallbackContext); + sIp6->SetReceiveDatagramCallback(aCallback, aCallbackContext); } bool otIsReceiveIp6DatagramFilterEnabled(void) { - return Ip6::Ip6::IsReceiveIp6FilterEnabled(); + return sIp6->IsReceiveIp6FilterEnabled(); } void otSetReceiveIp6DatagramFilterEnabled(bool aEnabled) { - Ip6::Ip6::SetReceiveIp6FilterEnabled(aEnabled); + sIp6->SetReceiveIp6FilterEnabled(aEnabled); } ThreadError otSendIp6Datagram(otMessage aMessage) { - return Ip6::Ip6::HandleDatagram(*static_cast(aMessage), NULL, sThreadNetif->GetInterfaceId(), - NULL, true); + return sIp6->HandleDatagram(*static_cast(aMessage), NULL, sThreadNetif->GetInterfaceId(), NULL, true); } otMessage otNewUdpMessage(void) diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index ce351401c..a4662650f 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -1441,7 +1441,7 @@ exit: ThreadError MeshForwarder::HandleDatagram(Message &aMessage, const ThreadMessageInfo &aMessageInfo) { - return Ip6::Ip6::HandleDatagram(aMessage, &mNetif, mNetif.GetInterfaceId(), &aMessageInfo, false); + return mNetif.GetIp6().HandleDatagram(aMessage, &mNetif, mNetif.GetInterfaceId(), &aMessageInfo, false); } void MeshForwarder::UpdateFramePending() diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 356daf32a..5a98b5aa4 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -344,7 +344,7 @@ ThreadError Mle::SetStateDetached(void) mParentRequestTimer.Stop(); mMesh.SetRxOnWhenIdle(true); mMleRouter.HandleDetachStart(); - Ip6::Ip6::SetForwardingEnabled(false); + mNetif.GetIp6().SetForwardingEnabled(false); otLogInfoMle("Mode -> Detached\n"); return kThreadError_None; @@ -371,7 +371,7 @@ ThreadError Mle::SetStateChild(uint16_t aRloc16) mMleRouter.HandleChildStart(mParentRequestMode); } - Ip6::Ip6::SetForwardingEnabled(false); + mNetif.GetIp6().SetForwardingEnabled(false); otLogInfoMle("Mode -> Child\n"); return kThreadError_None; diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index e54a9b13d..648e7f415 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -340,7 +340,7 @@ ThreadError MleRouter::SetStateRouter(uint16_t aRloc16) mRouters[mRouterId].mNextHop = mRouterId; mNetworkData.Stop(); mStateUpdateTimer.Start(kStateUpdatePeriod); - Ip6::Ip6::SetForwardingEnabled(true); + mNetif.GetIp6().SetForwardingEnabled(true); otLogInfoMle("Mode -> Router\n"); return kThreadError_None; @@ -367,7 +367,7 @@ ThreadError MleRouter::SetStateLeader(uint16_t aRloc16) mNetif.GetPendingDataset().ApplyLocalToNetwork(); mCoapServer.AddResource(mAddressSolicit); mCoapServer.AddResource(mAddressRelease); - Ip6::Ip6::SetForwardingEnabled(true); + mNetif.GetIp6().SetForwardingEnabled(true); otLogInfoMle("Mode -> Leader %d\n", mLeaderData.GetPartitionId()); return kThreadError_None; diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index bfb567af3..d4f8ea349 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -54,7 +54,8 @@ static const uint8_t kThreadMasterKey[] = static const char name[] = "thread"; -ThreadNetif::ThreadNetif(void): +ThreadNetif::ThreadNetif(Ip6::Ip6 &aIp6): + Netif(aIp6), mCoapServer(kCoapUdpPort), mAddressResolver(*this), mActiveDataset(*this), diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp index dab355b76..11cfda6ff 100644 --- a/src/core/thread/thread_netif.hpp +++ b/src/core/thread/thread_netif.hpp @@ -63,8 +63,10 @@ public: /** * This constructor initializes the Thread network interface. * + * @param[in] aIp6 A reference to the IPv6 network object. + * */ - ThreadNetif(void); + ThreadNetif(Ip6::Ip6 &aIp6); /** * This method enables the Thread network interface. diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index de1193f83..27d509f06 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -45,6 +45,7 @@ namespace Thread { extern ThreadNetif *sThreadNetif; +extern Ip6::Ip6 *sIp6; static NcpBase *sNcpContext = NULL; @@ -3102,7 +3103,7 @@ ThreadError NcpBase::SetPropertyHandler_STREAM_NET_INSECURE(uint8_t header, spin unsigned int frame_len(0); const uint8_t *meta_ptr(NULL); unsigned int meta_len(0); - Message *message(Ip6::Ip6::NewMessage(0)); + Message *message(Message::New(Message::kTypeIp6, 0)); if (message == NULL) { @@ -3173,7 +3174,7 @@ ThreadError NcpBase::SetPropertyHandler_STREAM_NET(uint8_t header, spinel_prop_k unsigned int frame_len(0); const uint8_t *meta_ptr(NULL); unsigned int meta_len(0); - Message *message(Ip6::Ip6::NewMessage(0)); + Message *message(Message::New(Message::kTypeIp6, 0)); if (message == NULL) { diff --git a/tests/unit/test_lowpan.cpp b/tests/unit/test_lowpan.cpp index fe906d1e1..fecc78107 100644 --- a/tests/unit/test_lowpan.cpp +++ b/tests/unit/test_lowpan.cpp @@ -75,7 +75,8 @@ extern "C" void otPlatDiagRadioReceiveDone(RadioPacket *aFrame, ThreadError aErr (void)aError; } -ThreadNetif sMockThreadNetif; +Ip6::Ip6 sIp6; +ThreadNetif sMockThreadNetif(sIp6); Lowpan::Lowpan sMockLowpan(sMockThreadNetif); void TestLowpanIphc(void) @@ -116,7 +117,7 @@ void TestLowpanIphc(void) frame.GetSrcAddr(macSource); frame.GetDstAddr(macDest); - VerifyOrQuit((message = Ip6::Ip6::NewMessage(0)) != NULL, + VerifyOrQuit((message = sIp6.NewMessage(0)) != NULL, "6lo: Ip6::NewMessage failed"); // ===> Test Lowpan::Decompress