mirror of
https://github.com/espressif/openthread.git
synced 2026-10-26 01:04:06 +00:00
MPL: Seed-id field handling (#663)
* MPL: Fix seed-id field handling. Add Pad1 and PadN options. This commit fixes issue #599 by allowing MPL module to elide its seed-id as well as retrieve elided seed-id from RLOC. Additionally Pad options have been introduced and bug with incorrect parsing of Pad1 option has been fixed. * Lowpan: Introduce compression and decompression of Pad1 and PadN options. This commit fixes issue #599.
This commit is contained in:
committed by
Jonathan Hui
parent
a853ffc784
commit
465affadb9
+26
-9
@@ -128,11 +128,20 @@ ThreadError Ip6::AddMplOption(Message &message, Header &header, IpProto nextHead
|
|||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
HopByHopHeader hbhHeader;
|
HopByHopHeader hbhHeader;
|
||||||
OptionMpl mplOption;
|
OptionMpl mplOption;
|
||||||
|
OptionPadN padOption;
|
||||||
|
|
||||||
hbhHeader.SetNextHeader(nextHeader);
|
hbhHeader.SetNextHeader(nextHeader);
|
||||||
hbhHeader.SetLength(0);
|
hbhHeader.SetLength(0);
|
||||||
mMpl.InitOption(mplOption, HostSwap16(header.GetSource().mFields.m16[7]));
|
mMpl.InitOption(mplOption, header.GetSource());
|
||||||
SuccessOrExit(error = message.Prepend(&mplOption, sizeof(mplOption)));
|
|
||||||
|
// Mpl option may require two bytes padding.
|
||||||
|
if ((mplOption.GetTotalLength() + sizeof(hbhHeader)) % 8)
|
||||||
|
{
|
||||||
|
padOption.Init(2);
|
||||||
|
SuccessOrExit(error = message.Prepend(&padOption, padOption.GetTotalLength()));
|
||||||
|
}
|
||||||
|
|
||||||
|
SuccessOrExit(error = message.Prepend(&mplOption, mplOption.GetTotalLength()));
|
||||||
SuccessOrExit(error = message.Prepend(&hbhHeader, sizeof(hbhHeader)));
|
SuccessOrExit(error = message.Prepend(&hbhHeader, sizeof(hbhHeader)));
|
||||||
header.SetPayloadLength(sizeof(hbhHeader) + sizeof(mplOption) + payloadLength);
|
header.SetPayloadLength(sizeof(hbhHeader) + sizeof(mplOption) + payloadLength);
|
||||||
header.SetNextHeader(kProtoHopOpts);
|
header.SetNextHeader(kProtoHopOpts);
|
||||||
@@ -222,7 +231,7 @@ void Ip6::HandleSendQueue(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError Ip6::HandleOptions(Message &message)
|
ThreadError Ip6::HandleOptions(Message &message, Header &header)
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
HopByHopHeader hbhHeader;
|
HopByHopHeader hbhHeader;
|
||||||
@@ -241,7 +250,7 @@ ThreadError Ip6::HandleOptions(Message &message)
|
|||||||
switch (optionHeader.GetType())
|
switch (optionHeader.GetType())
|
||||||
{
|
{
|
||||||
case OptionMpl::kType:
|
case OptionMpl::kType:
|
||||||
SuccessOrExit(error = mMpl.ProcessOption(message));
|
SuccessOrExit(error = mMpl.ProcessOption(message, header.GetSource()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -266,7 +275,15 @@ ThreadError Ip6::HandleOptions(Message &message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
message.MoveOffset(sizeof(optionHeader) + optionHeader.GetLength());
|
if (optionHeader.GetType() == OptionPad1::kType)
|
||||||
|
{
|
||||||
|
message.MoveOffset(sizeof(OptionPad1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message.MoveOffset(sizeof(optionHeader) + optionHeader.GetLength());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -289,7 +306,7 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError Ip6::HandleExtensionHeaders(Message &message, uint8_t &nextHeader, bool receive)
|
ThreadError Ip6::HandleExtensionHeaders(Message &message, Header &header, uint8_t &nextHeader, bool receive)
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
ExtensionHeader extensionHeader;
|
ExtensionHeader extensionHeader;
|
||||||
@@ -303,7 +320,7 @@ ThreadError Ip6::HandleExtensionHeaders(Message &message, uint8_t &nextHeader, b
|
|||||||
switch (nextHeader)
|
switch (nextHeader)
|
||||||
{
|
{
|
||||||
case kProtoHopOpts:
|
case kProtoHopOpts:
|
||||||
SuccessOrExit(error = HandleOptions(message));
|
SuccessOrExit(error = HandleOptions(message, header));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kProtoFragment:
|
case kProtoFragment:
|
||||||
@@ -311,7 +328,7 @@ ThreadError Ip6::HandleExtensionHeaders(Message &message, uint8_t &nextHeader, b
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case kProtoDstOpts:
|
case kProtoDstOpts:
|
||||||
SuccessOrExit(error = HandleOptions(message));
|
SuccessOrExit(error = HandleOptions(message, header));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kProtoIp6:
|
case kProtoIp6:
|
||||||
@@ -489,7 +506,7 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, int8_t interface
|
|||||||
|
|
||||||
// process IPv6 Extension Headers
|
// process IPv6 Extension Headers
|
||||||
nextHeader = static_cast<uint8_t>(header.GetNextHeader());
|
nextHeader = static_cast<uint8_t>(header.GetNextHeader());
|
||||||
SuccessOrExit(error = HandleExtensionHeaders(message, nextHeader, receive));
|
SuccessOrExit(error = HandleExtensionHeaders(message, header, nextHeader, receive));
|
||||||
|
|
||||||
// process IPv6 Payload
|
// process IPv6 Payload
|
||||||
if (receive)
|
if (receive)
|
||||||
|
|||||||
@@ -326,6 +326,7 @@ public:
|
|||||||
Routes mRoutes;
|
Routes mRoutes;
|
||||||
Icmp mIcmp;
|
Icmp mIcmp;
|
||||||
Udp mUdp;
|
Udp mUdp;
|
||||||
|
Mpl mMpl;
|
||||||
|
|
||||||
MessagePool mMessagePool;
|
MessagePool mMessagePool;
|
||||||
TaskletScheduler mTaskletScheduler;
|
TaskletScheduler mTaskletScheduler;
|
||||||
@@ -336,14 +337,13 @@ private:
|
|||||||
void HandleSendQueue(void);
|
void HandleSendQueue(void);
|
||||||
|
|
||||||
ThreadError ProcessReceiveCallback(const Message &aMessage, const MessageInfo &aMessageInfo, uint8_t aIpProto);
|
ThreadError ProcessReceiveCallback(const Message &aMessage, const MessageInfo &aMessageInfo, uint8_t aIpProto);
|
||||||
ThreadError HandleExtensionHeaders(Message &message, uint8_t &nextHeader, bool receive);
|
ThreadError HandleExtensionHeaders(Message &message, Header &header, uint8_t &nextHeader, bool receive);
|
||||||
ThreadError HandleFragment(Message &message);
|
ThreadError HandleFragment(Message &message);
|
||||||
ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength);
|
ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength);
|
||||||
ThreadError HandleOptions(Message &message);
|
ThreadError HandleOptions(Message &message, Header &header);
|
||||||
ThreadError HandlePayload(Message &message, MessageInfo &messageInfo, uint8_t ipproto);
|
ThreadError HandlePayload(Message &message, MessageInfo &messageInfo, uint8_t ipproto);
|
||||||
ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo, uint8_t ipproto);
|
ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo, uint8_t ipproto);
|
||||||
|
|
||||||
Mpl mMpl;
|
|
||||||
bool mForwardingEnabled;
|
bool mForwardingEnabled;
|
||||||
|
|
||||||
MessageQueue mSendQueue;
|
MessageQueue mSendQueue;
|
||||||
|
|||||||
@@ -387,6 +387,72 @@ private:
|
|||||||
uint8_t mLength;
|
uint8_t mLength;
|
||||||
} OT_TOOL_PACKED_END;
|
} OT_TOOL_PACKED_END;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements IPv6 PadN Option generation and parsing.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
OT_TOOL_PACKED_BEGIN
|
||||||
|
class OptionPadN : public OptionHeader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kType = 0x01, ///< PadN type
|
||||||
|
kData = 0x00, ///< PadN specific data
|
||||||
|
kMaxLength = 0x05 ///< Maximum length of PadN option data
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method initializes the PadN header.
|
||||||
|
*
|
||||||
|
* @param[in] aPadLength The length of needed padding. Allowed value from
|
||||||
|
* range 2-7.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Init(uint8_t aPadLength) {
|
||||||
|
OptionHeader::SetType(kType);
|
||||||
|
OptionHeader::SetLength(aPadLength - sizeof(OptionHeader));
|
||||||
|
memset(mPad, kData, aPadLength - sizeof(OptionHeader));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the total IPv6 Option Length value including option
|
||||||
|
* header.
|
||||||
|
*
|
||||||
|
* @returns The total IPv6 Option Length.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t GetTotalLength() const { return OptionHeader::GetLength() + sizeof(OptionHeader); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t mPad[kMaxLength];
|
||||||
|
} OT_TOOL_PACKED_END;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements IPv6 Pad1 Option generation and parsing. Pad1 does not
|
||||||
|
* followdefault option header structure.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
OT_TOOL_PACKED_BEGIN
|
||||||
|
class OptionPad1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kType = 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method initializes the Pad1 header.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Init() { mType = kType; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t mType;
|
||||||
|
} OT_TOOL_PACKED_END;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements IPv6 Fragment Header generation and parsing.
|
* This class implements IPv6 Fragment Header generation and parsing.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -40,31 +40,52 @@ namespace Thread {
|
|||||||
namespace Ip6 {
|
namespace Ip6 {
|
||||||
|
|
||||||
Mpl::Mpl(Ip6 &aIp6):
|
Mpl::Mpl(Ip6 &aIp6):
|
||||||
mTimer(aIp6.mTimerScheduler, &Mpl::HandleTimer, this)
|
mTimer(aIp6.mTimerScheduler, &Mpl::HandleTimer, this),
|
||||||
|
mMatchingAddress(NULL)
|
||||||
{
|
{
|
||||||
memset(mEntries, 0, sizeof(mEntries));
|
memset(mEntries, 0, sizeof(mEntries));
|
||||||
mSequence = 0;
|
mSequence = 0;
|
||||||
|
mSeed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mpl::InitOption(OptionMpl &aOption, uint16_t aSeed)
|
void Mpl::InitOption(OptionMpl &aOption, const Address &aAddress)
|
||||||
{
|
{
|
||||||
aOption.Init();
|
aOption.Init();
|
||||||
aOption.SetSeedLength(OptionMpl::kSeedLength2);
|
|
||||||
aOption.SetSequence(mSequence++);
|
aOption.SetSequence(mSequence++);
|
||||||
aOption.SetSeed(aSeed);
|
|
||||||
|
// Check if Seed can be elided.
|
||||||
|
if (mMatchingAddress && aAddress == *mMatchingAddress)
|
||||||
|
{
|
||||||
|
aOption.SetSeedLength(OptionMpl::kSeedLength0);
|
||||||
|
|
||||||
|
// Decrease default option length.
|
||||||
|
aOption.SetLength(aOption.GetLength() - sizeof(mSeed));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aOption.SetSeedLength(OptionMpl::kSeedLength2);
|
||||||
|
aOption.SetSeed(mSeed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError Mpl::ProcessOption(const Message &aMessage)
|
ThreadError Mpl::ProcessOption(const Message &aMessage, const Address &aAddress)
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
OptionMpl option;
|
OptionMpl option;
|
||||||
MplEntry *entry = NULL;
|
MplEntry *entry = NULL;
|
||||||
int8_t diff;
|
int8_t diff;
|
||||||
|
|
||||||
VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(option), &option) == sizeof(option) &&
|
VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(option), &option) >= OptionMpl::kMinLength &&
|
||||||
option.GetLength() == sizeof(OptionMpl) - sizeof(OptionHeader),
|
(option.GetSeedLength() == OptionMpl::kSeedLength0 ||
|
||||||
|
option.GetSeedLength() == OptionMpl::kSeedLength2),
|
||||||
error = kThreadError_Drop);
|
error = kThreadError_Drop);
|
||||||
|
|
||||||
|
if (option.GetSeedLength() == OptionMpl::kSeedLength0)
|
||||||
|
{
|
||||||
|
// Retrieve Seed from the IPv6 Source Address.
|
||||||
|
option.SetSeed(HostSwap16(aAddress.mFields.m16[7]));
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < kNumEntries; i++)
|
for (int i = 0; i < kNumEntries; i++)
|
||||||
{
|
{
|
||||||
if (mEntries[i].mLifetime == 0)
|
if (mEntries[i].mLifetime == 0)
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public:
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kType = 0x6d, /* 01 1 01101 */
|
kType = 0x6d, /* 01 1 01101 */
|
||||||
|
kMinLength = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,8 +73,18 @@ public:
|
|||||||
void Init() {
|
void Init() {
|
||||||
OptionHeader::SetType(kType);
|
OptionHeader::SetType(kType);
|
||||||
OptionHeader::SetLength(sizeof(*this) - sizeof(OptionHeader));
|
OptionHeader::SetLength(sizeof(*this) - sizeof(OptionHeader));
|
||||||
|
mControl = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the total MPL Option length value including option
|
||||||
|
* header.
|
||||||
|
*
|
||||||
|
* @returns The total IPv6 Option Length.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t GetTotalLength() const { return OptionHeader::GetLength() + sizeof(OptionHeader); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MPL Seed lengths.
|
* MPL Seed lengths.
|
||||||
*/
|
*/
|
||||||
@@ -156,7 +167,7 @@ private:
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kSeedLengthMask = 3 << 6,
|
kSeedLengthMask = 3 << 6,
|
||||||
kMaxFlag = 1 << 5,
|
kMaxFlag = 1 << 5
|
||||||
};
|
};
|
||||||
uint8_t mControl;
|
uint8_t mControl;
|
||||||
uint8_t mSequence;
|
uint8_t mSequence;
|
||||||
@@ -181,22 +192,46 @@ public:
|
|||||||
/**
|
/**
|
||||||
* This method initializes the MPL option.
|
* This method initializes the MPL option.
|
||||||
*
|
*
|
||||||
* @param[in] aOption A reference to the MPL header to initialize.
|
* @param[in] aOption A reference to the MPL header to initialize.
|
||||||
* @param[in] aSeed The MPL Seed value to use.
|
* @param[in] aAddress A reference to the IPv6 Source Address.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void InitOption(OptionMpl &aOption, uint16_t aSeed);
|
void InitOption(OptionMpl &aOption, const Address &aAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method processes an MPL option.
|
* This method processes an MPL option.
|
||||||
*
|
*
|
||||||
* @param[in] aMessage A reference to the message.
|
* @param[in] aMessage A reference to the message.
|
||||||
|
* @param[in] aAddress A reference to the IPv6 Source Address.
|
||||||
*
|
*
|
||||||
* @retval kThreadError_None Successfully processed the MPL option.
|
* @retval kThreadError_None Successfully processed the MPL option.
|
||||||
* @retval kThreadError_Drop The MPL message is a duplicate and should be dropped.
|
* @retval kThreadError_Drop The MPL message is a duplicate and should be dropped.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
ThreadError ProcessOption(const Message &aMessage);
|
ThreadError ProcessOption(const Message &aMessage, const Address &aAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the MPL Seed value.
|
||||||
|
*
|
||||||
|
* @returns The MPL Seed value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint16_t GetSeed() const { return mSeed; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the MPL Seed value.
|
||||||
|
*
|
||||||
|
* @param[in] aSeed The MPL Seed value.
|
||||||
|
*/
|
||||||
|
void SetSeed(uint16_t aSeed) { mSeed = aSeed; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets IPv6 matching address, that allows to elide seed-id.
|
||||||
|
*
|
||||||
|
* @param[in] aAddress The reference to IPv6 matching address.
|
||||||
|
*/
|
||||||
|
void SetMatchingAddress(const Address &aAddress) { mMatchingAddress = &aAddress; }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
@@ -210,6 +245,8 @@ private:
|
|||||||
|
|
||||||
Timer mTimer;
|
Timer mTimer;
|
||||||
uint8_t mSequence;
|
uint8_t mSequence;
|
||||||
|
uint16_t mSeed;
|
||||||
|
const Address *mMatchingAddress;
|
||||||
|
|
||||||
struct MplEntry
|
struct MplEntry
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -384,14 +384,16 @@ exit:
|
|||||||
int Lowpan::CompressExtensionHeader(Message &aMessage, uint8_t *aBuf, uint8_t &aNextHeader)
|
int Lowpan::CompressExtensionHeader(Message &aMessage, uint8_t *aBuf, uint8_t &aNextHeader)
|
||||||
{
|
{
|
||||||
Ip6::ExtensionHeader extHeader;
|
Ip6::ExtensionHeader extHeader;
|
||||||
|
Ip6::OptionHeader optionHeader;
|
||||||
uint8_t *cur = aBuf;
|
uint8_t *cur = aBuf;
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
|
uint8_t padLength = 0;
|
||||||
|
uint16_t offset;
|
||||||
|
|
||||||
aMessage.Read(aMessage.GetOffset(), sizeof(extHeader), &extHeader);
|
aMessage.Read(aMessage.GetOffset(), sizeof(extHeader), &extHeader);
|
||||||
aMessage.MoveOffset(sizeof(extHeader));
|
aMessage.MoveOffset(sizeof(extHeader));
|
||||||
|
|
||||||
cur[0] = kExtHdrDispatch | kExtHdrEidHbh;
|
cur[0] = kExtHdrDispatch | kExtHdrEidHbh;
|
||||||
aNextHeader = static_cast<uint8_t>(extHeader.GetNextHeader());
|
|
||||||
|
|
||||||
switch (extHeader.GetNextHeader())
|
switch (extHeader.GetNextHeader())
|
||||||
{
|
{
|
||||||
@@ -408,11 +410,49 @@ int Lowpan::CompressExtensionHeader(Message &aMessage, uint8_t *aBuf, uint8_t &a
|
|||||||
cur++;
|
cur++;
|
||||||
|
|
||||||
len = (extHeader.GetLength() + 1) * 8 - sizeof(extHeader);
|
len = (extHeader.GetLength() + 1) * 8 - sizeof(extHeader);
|
||||||
|
|
||||||
|
// RFC 6282 says: "IPv6 Hop-by-Hop and Destination Options Headers may use a trailing
|
||||||
|
// Pad1 or PadN to achieve 8-octet alignment. When there is a single trailing Pad1 or PadN
|
||||||
|
// option of 7 octets or less and the containing header is a multiple of 8 octets, the trailing
|
||||||
|
// Pad1 or PadN option MAY be elided by the compressor."
|
||||||
|
if (aNextHeader == Ip6::kProtoHopOpts || aNextHeader == Ip6::kProtoDstOpts)
|
||||||
|
{
|
||||||
|
offset = aMessage.GetOffset();
|
||||||
|
|
||||||
|
while (offset < len + aMessage.GetOffset())
|
||||||
|
{
|
||||||
|
aMessage.Read(offset, sizeof(optionHeader), &optionHeader);
|
||||||
|
|
||||||
|
if (optionHeader.GetType() == Ip6::OptionPad1::kType)
|
||||||
|
{
|
||||||
|
offset += sizeof(Ip6::OptionPad1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset += sizeof(optionHeader) + optionHeader.GetLength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the last option can be compressed.
|
||||||
|
if (optionHeader.GetType() == Ip6::OptionPad1::kType)
|
||||||
|
{
|
||||||
|
padLength = sizeof(Ip6::OptionPad1);
|
||||||
|
}
|
||||||
|
else if (optionHeader.GetType() == Ip6::OptionPadN::kType)
|
||||||
|
{
|
||||||
|
padLength = sizeof(optionHeader) + optionHeader.GetLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
len -= padLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
aNextHeader = static_cast<uint8_t>(extHeader.GetNextHeader());
|
||||||
|
|
||||||
cur[0] = len;
|
cur[0] = len;
|
||||||
cur++;
|
cur++;
|
||||||
|
|
||||||
aMessage.Read(aMessage.GetOffset(), len, cur);
|
aMessage.Read(aMessage.GetOffset(), len, cur);
|
||||||
aMessage.MoveOffset(len);
|
aMessage.MoveOffset(len + padLength);
|
||||||
cur += len;
|
cur += len;
|
||||||
|
|
||||||
return static_cast<int>(cur - aBuf);
|
return static_cast<int>(cur - aBuf);
|
||||||
@@ -756,6 +796,9 @@ int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, ui
|
|||||||
uint8_t len;
|
uint8_t len;
|
||||||
Ip6::IpProto nextHeader;
|
Ip6::IpProto nextHeader;
|
||||||
uint8_t ctl = cur[0];
|
uint8_t ctl = cur[0];
|
||||||
|
uint8_t padLength;
|
||||||
|
Ip6::OptionPad1 optionPad1;
|
||||||
|
Ip6::OptionPadN optionPadN;
|
||||||
|
|
||||||
cur++;
|
cur++;
|
||||||
|
|
||||||
@@ -788,6 +831,27 @@ int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, ui
|
|||||||
aMessage.MoveOffset(len);
|
aMessage.MoveOffset(len);
|
||||||
cur += len;
|
cur += len;
|
||||||
|
|
||||||
|
// The RFC6282 says: "The trailing Pad1 or PadN option MAY be elided by the compressor.
|
||||||
|
// A decompressor MUST ensure that the containing header is padded out to a multiple of 8 octets
|
||||||
|
// in length, using a Pad1 or PadN option if necessary."
|
||||||
|
padLength = 8 - ((len + sizeof(hdr)) & 0x07);
|
||||||
|
|
||||||
|
if (padLength != 8)
|
||||||
|
{
|
||||||
|
if (padLength == 1)
|
||||||
|
{
|
||||||
|
optionPad1.Init();
|
||||||
|
SuccessOrExit(error = aMessage.Append(&optionPad1, padLength));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionPadN.Init(padLength);
|
||||||
|
SuccessOrExit(error = aMessage.Append(&optionPadN, padLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
aMessage.MoveOffset(padLength);
|
||||||
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
(void)aBufLength;
|
(void)aBufLength;
|
||||||
return (error == kThreadError_None) ? static_cast<int>(cur - aBuf) : -1;
|
return (error == kThreadError_None) ? static_cast<int>(cur - aBuf) : -1;
|
||||||
|
|||||||
@@ -131,6 +131,9 @@ Mle::Mle(ThreadNetif &aThreadNetif) :
|
|||||||
mMeshLocal16.mPreferredLifetime = 0xffffffff;
|
mMeshLocal16.mPreferredLifetime = 0xffffffff;
|
||||||
mMeshLocal16.mValidLifetime = 0xffffffff;
|
mMeshLocal16.mValidLifetime = 0xffffffff;
|
||||||
|
|
||||||
|
// Store RLOC address reference in MPL module.
|
||||||
|
mNetif.GetIp6().mMpl.SetMatchingAddress(mMeshLocal16.GetAddress());
|
||||||
|
|
||||||
// link-local all thread nodes
|
// link-local all thread nodes
|
||||||
mLinkLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff32);
|
mLinkLocalAllThreadNodes.GetAddress().mFields.m16[0] = HostSwap16(0xff32);
|
||||||
mLinkLocalAllThreadNodes.GetAddress().mFields.m16[6] = HostSwap16(0x0000);
|
mLinkLocalAllThreadNodes.GetAddress().mFields.m16[6] = HostSwap16(0x0000);
|
||||||
@@ -522,6 +525,7 @@ ThreadError Mle::SetRloc16(uint16_t aRloc16)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mMac.SetShortAddress(aRloc16);
|
mMac.SetShortAddress(aRloc16);
|
||||||
|
mNetif.GetIp6().mMpl.SetSeed(aRloc16);
|
||||||
|
|
||||||
return kThreadError_None;
|
return kThreadError_None;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user