mirror of
https://github.com/espressif/openthread.git
synced 2026-09-16 22:20:07 +00:00
MPL: Introduce multicast forwarding. (#827)
* Message: Add a new optional parameter to Clone method. * MPL: Introduce MPL Forwarding This commit introduces MPL Forwarding for Routers. All references to MPL Seed have been replaced with MPL Seed Id.
This commit is contained in:
committed by
Jonathan Hui
parent
ad39a59ff9
commit
78d4b678e3
@@ -474,14 +474,14 @@ int Message::CopyTo(uint16_t aSourceOffset, uint16_t aDestinationOffset, uint16_
|
|||||||
return bytesCopied;
|
return bytesCopied;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message *Message::Clone(void) const
|
Message *Message::Clone(uint16_t aLength) const
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
Message *messageCopy;
|
Message *messageCopy;
|
||||||
|
|
||||||
VerifyOrExit((messageCopy = GetMessagePool()->New(GetType(), GetReserved())) != NULL, error = kThreadError_NoBufs);
|
VerifyOrExit((messageCopy = GetMessagePool()->New(GetType(), GetReserved())) != NULL, error = kThreadError_NoBufs);
|
||||||
SuccessOrExit(error = messageCopy->SetLength(GetLength()));
|
SuccessOrExit(error = messageCopy->SetLength(aLength));
|
||||||
CopyTo(0, 0, GetLength(), *messageCopy);
|
CopyTo(0, 0, aLength, *messageCopy);
|
||||||
|
|
||||||
// Copy selected message information.
|
// Copy selected message information.
|
||||||
messageCopy->SetOffset(GetOffset());
|
messageCopy->SetOffset(GetOffset());
|
||||||
|
|||||||
@@ -386,11 +386,21 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates a copy of the current Message. It allocates the new one
|
* This method creates a copy of the current Message. It allocates the new one
|
||||||
* from the same Message Poll as the original Message.
|
* from the same Message Poll as the original Message and copies @p aLength octets of a payload.
|
||||||
|
*
|
||||||
|
* @param[in] aLength Number of payload bytes to copy.
|
||||||
*
|
*
|
||||||
* @returns A pointer to the message or NULL if insufficient message buffers are available.
|
* @returns A pointer to the message or NULL if insufficient message buffers are available.
|
||||||
*/
|
*/
|
||||||
Message *Clone(void) const;
|
Message *Clone(uint16_t aLength) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates a copy of the current Message. It allocates the new one
|
||||||
|
* from the same Message Poll as the original Message and copies a full payload.
|
||||||
|
*
|
||||||
|
* @returns A pointer to the message or NULL if insufficient message buffers are available.
|
||||||
|
*/
|
||||||
|
Message *Clone(void) const { return Clone(GetLength()); };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the datagram tag used for 6LoWPAN fragmentation.
|
* This method returns the datagram tag used for 6LoWPAN fragmentation.
|
||||||
|
|||||||
@@ -151,6 +151,12 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ip6::EnqueueDatagram(Message &aMessage)
|
||||||
|
{
|
||||||
|
mSendQueue.Enqueue(aMessage);
|
||||||
|
mSendQueueTask.Post();
|
||||||
|
}
|
||||||
|
|
||||||
ThreadError Ip6::SendDatagram(Message &message, MessageInfo &messageInfo, IpProto ipproto)
|
ThreadError Ip6::SendDatagram(Message &message, MessageInfo &messageInfo, IpProto ipproto)
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
@@ -211,8 +217,7 @@ exit:
|
|||||||
if (error == kThreadError_None)
|
if (error == kThreadError_None)
|
||||||
{
|
{
|
||||||
message.SetInterfaceId(messageInfo.mInterfaceId);
|
message.SetInterfaceId(messageInfo.mInterfaceId);
|
||||||
mSendQueue.Enqueue(message);
|
EnqueueDatagram(message);
|
||||||
mSendQueueTask.Post();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
@@ -308,7 +313,7 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError Ip6::HandleExtensionHeaders(Message &message, Header &header, uint8_t &nextHeader, bool &forward,
|
ThreadError Ip6::HandleExtensionHeaders(Message &message, Header &header, uint8_t &nextHeader, bool forward,
|
||||||
bool receive)
|
bool receive)
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
@@ -488,6 +493,7 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, int8_t interface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message.SetInterfaceId(interfaceId);
|
||||||
message.SetOffset(sizeof(header));
|
message.SetOffset(sizeof(header));
|
||||||
|
|
||||||
// process IPv6 Extension Headers
|
// process IPv6 Extension Headers
|
||||||
|
|||||||
@@ -146,6 +146,14 @@ public:
|
|||||||
ThreadError HandleDatagram(Message &aMessage, Netif *aNetif, int8_t aInterfaceId,
|
ThreadError HandleDatagram(Message &aMessage, Netif *aNetif, int8_t aInterfaceId,
|
||||||
const void *aLinkMessageInfo, bool aFromNcpHost);
|
const void *aLinkMessageInfo, bool aFromNcpHost);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This methods adds a full IPv6 packet to the transmit queue.
|
||||||
|
*
|
||||||
|
* @param aMessage A reference to the message.
|
||||||
|
*/
|
||||||
|
void EnqueueDatagram(Message &aMessage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This static method updates a checksum.
|
* This static method updates a checksum.
|
||||||
*
|
*
|
||||||
@@ -335,7 +343,7 @@ 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, Header &header, uint8_t &nextHeader, bool &forward,
|
ThreadError HandleExtensionHeaders(Message &message, Header &header, uint8_t &nextHeader, bool forward,
|
||||||
bool receive);
|
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);
|
||||||
|
|||||||
+250
-42
@@ -35,17 +35,31 @@
|
|||||||
#include <common/message.hpp>
|
#include <common/message.hpp>
|
||||||
#include <net/ip6.hpp>
|
#include <net/ip6.hpp>
|
||||||
#include <net/ip6_mpl.hpp>
|
#include <net/ip6_mpl.hpp>
|
||||||
|
#include <platform/random.h>
|
||||||
|
|
||||||
namespace Thread {
|
namespace Thread {
|
||||||
namespace Ip6 {
|
namespace Ip6 {
|
||||||
|
|
||||||
|
void MplBufferedMessageMetadata::GenerateNextTransmissionTime(uint32_t aCurrentTime, uint8_t aInterval)
|
||||||
|
{
|
||||||
|
// Emulate Trickle timer behavior and set up the next retransmission within [0,I) range.
|
||||||
|
uint8_t t = otPlatRandomGet() % aInterval;
|
||||||
|
|
||||||
|
// Set transmission time at the beginning of the next interval.
|
||||||
|
SetTransmissionTime(aCurrentTime + GetIntervalOffset() + t);
|
||||||
|
SetIntervalOffset(aInterval - t);
|
||||||
|
}
|
||||||
|
|
||||||
Mpl::Mpl(Ip6 &aIp6):
|
Mpl::Mpl(Ip6 &aIp6):
|
||||||
mTimer(aIp6.mTimerScheduler, &Mpl::HandleTimer, this),
|
mIp6(aIp6),
|
||||||
|
mSeedSetTimer(aIp6.mTimerScheduler, &Mpl::HandleSeedSetTimer, this),
|
||||||
|
mRetransmissionTimer(aIp6.mTimerScheduler, &Mpl::HandleRetransmissionTimer, this),
|
||||||
|
mTimerExpirations(0),
|
||||||
|
mSequence(0),
|
||||||
|
mSeedId(0),
|
||||||
mMatchingAddress(NULL)
|
mMatchingAddress(NULL)
|
||||||
{
|
{
|
||||||
memset(mEntries, 0, sizeof(mEntries));
|
memset(mSeedSet, 0, sizeof(mSeedSet));
|
||||||
mSequence = 0;
|
|
||||||
mSeed = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mpl::InitOption(OptionMpl &aOption, const Address &aAddress)
|
void Mpl::InitOption(OptionMpl &aOption, const Address &aAddress)
|
||||||
@@ -53,49 +67,41 @@ void Mpl::InitOption(OptionMpl &aOption, const Address &aAddress)
|
|||||||
aOption.Init();
|
aOption.Init();
|
||||||
aOption.SetSequence(mSequence++);
|
aOption.SetSequence(mSequence++);
|
||||||
|
|
||||||
// Check if Seed can be elided.
|
// Check if Seed Id can be elided.
|
||||||
if (mMatchingAddress && aAddress == *mMatchingAddress)
|
if (mMatchingAddress && aAddress == *mMatchingAddress)
|
||||||
{
|
{
|
||||||
aOption.SetSeedLength(OptionMpl::kSeedLength0);
|
aOption.SetSeedIdLength(OptionMpl::kSeedIdLength0);
|
||||||
|
|
||||||
// Decrease default option length.
|
// Decrease default option length.
|
||||||
aOption.SetLength(aOption.GetLength() - sizeof(mSeed));
|
aOption.SetLength(aOption.GetLength() - sizeof(mSeedId));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
aOption.SetSeedLength(OptionMpl::kSeedLength2);
|
aOption.SetSeedIdLength(OptionMpl::kSeedIdLength2);
|
||||||
aOption.SetSeed(mSeed);
|
aOption.SetSeedId(mSeedId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError Mpl::ProcessOption(const Message &aMessage, const Address &aAddress, bool &aForward)
|
ThreadError Mpl::UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence)
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
OptionMpl option;
|
MplSeedEntry *entry = NULL;
|
||||||
MplEntry *entry = NULL;
|
|
||||||
int8_t diff;
|
int8_t diff;
|
||||||
|
|
||||||
VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(option), &option) >= OptionMpl::kMinLength &&
|
for (uint32_t i = 0; i < kNumSeedEntries; i++)
|
||||||
(option.GetSeedLength() == OptionMpl::kSeedLength0 ||
|
|
||||||
option.GetSeedLength() == OptionMpl::kSeedLength2),
|
|
||||||
error = kThreadError_Drop);
|
|
||||||
|
|
||||||
if (option.GetSeedLength() == OptionMpl::kSeedLength0)
|
|
||||||
{
|
{
|
||||||
// Retrieve Seed from the IPv6 Source Address.
|
if (mSeedSet[i].GetLifetime() == 0)
|
||||||
option.SetSeed(HostSwap16(aAddress.mFields.m16[7]));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < kNumEntries; i++)
|
|
||||||
{
|
|
||||||
if (mEntries[i].mLifetime == 0)
|
|
||||||
{
|
{
|
||||||
entry = &mEntries[i];
|
// Start allocating from the first possible entry to speed up process of searching.
|
||||||
|
if (entry == NULL)
|
||||||
|
{
|
||||||
|
entry = &mSeedSet[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mEntries[i].mSeed == option.GetSeed())
|
else if (mSeedSet[i].GetSeedId() == aSeedId)
|
||||||
{
|
{
|
||||||
entry = &mEntries[i];
|
entry = &mSeedSet[i];
|
||||||
diff = static_cast<int8_t>(option.GetSequence() - entry->mSequence);
|
diff = static_cast<int8_t>(aSequence - entry->GetSequence());
|
||||||
|
|
||||||
VerifyOrExit(diff > 0, error = kThreadError_Drop);
|
VerifyOrExit(diff > 0, error = kThreadError_Drop);
|
||||||
|
|
||||||
@@ -105,38 +111,240 @@ ThreadError Mpl::ProcessOption(const Message &aMessage, const Address &aAddress,
|
|||||||
|
|
||||||
VerifyOrExit(entry != NULL, error = kThreadError_Drop);
|
VerifyOrExit(entry != NULL, error = kThreadError_Drop);
|
||||||
|
|
||||||
aForward = true;
|
entry->SetSeedId(aSeedId);
|
||||||
|
entry->SetSequence(aSequence);
|
||||||
entry->mSeed = option.GetSeed();
|
entry->SetLifetime(kSeedEntryLifetime);
|
||||||
entry->mSequence = option.GetSequence();
|
mSeedSetTimer.Start(kSeedEntryLifetimeDt);
|
||||||
entry->mLifetime = kLifetime;
|
|
||||||
mTimer.Start(1000);
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mpl::HandleTimer(void *aContext)
|
void Mpl::UpdateBufferedSet(uint16_t aSeedId, uint8_t aSequence)
|
||||||
{
|
{
|
||||||
static_cast<Mpl *>(aContext)->HandleTimer();
|
int8_t diff;
|
||||||
|
MplBufferedMessageMetadata messageMetadata;
|
||||||
|
|
||||||
|
Message *message = mBufferedMessageSet.GetHead();
|
||||||
|
Message *nextMessage = NULL;
|
||||||
|
|
||||||
|
// Check if multicast forwarding is enabled.
|
||||||
|
VerifyOrExit(GetTimerExpirations() > 0, ;);
|
||||||
|
|
||||||
|
while (message != NULL)
|
||||||
|
{
|
||||||
|
nextMessage = message->GetNext();
|
||||||
|
messageMetadata.ReadFrom(*message);
|
||||||
|
|
||||||
|
if (messageMetadata.GetSeedId() == aSeedId)
|
||||||
|
{
|
||||||
|
diff = static_cast<int8_t>(aSequence - messageMetadata.GetSequence());
|
||||||
|
|
||||||
|
if (diff > 0)
|
||||||
|
{
|
||||||
|
// Stop retransmitting MPL Data Message that is consider to be old.
|
||||||
|
mBufferedMessageSet.Dequeue(*message);
|
||||||
|
message->Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message = nextMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mpl::HandleTimer()
|
void Mpl::AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound)
|
||||||
|
{
|
||||||
|
uint32_t now = Timer::GetNow();
|
||||||
|
ThreadError error = kThreadError_None;
|
||||||
|
Message *messageCopy = NULL;
|
||||||
|
MplBufferedMessageMetadata messageMetadata;
|
||||||
|
uint32_t nextTransmissionTime;
|
||||||
|
uint8_t hopLimit;
|
||||||
|
|
||||||
|
VerifyOrExit((messageCopy = aMessage.Clone()) != NULL, error = kThreadError_NoBufs);
|
||||||
|
|
||||||
|
if (!aIsOutbound)
|
||||||
|
{
|
||||||
|
aMessage.Read(Header::GetHopLimitOffset(), Header::GetHopLimitSize(), &hopLimit);
|
||||||
|
VerifyOrExit(--hopLimit > 0, error = kThreadError_Drop);
|
||||||
|
messageCopy->Write(Header::GetHopLimitOffset(), Header::GetHopLimitSize(), &hopLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMetadata.SetSeedId(aSeedId);
|
||||||
|
messageMetadata.SetSequence(aSequence);
|
||||||
|
messageMetadata.SetTransmissionCount(aIsOutbound ? 1 : 0);
|
||||||
|
messageMetadata.GenerateNextTransmissionTime(now, kDataMessageInterval);
|
||||||
|
|
||||||
|
// Append the message with MplBufferedMessageMetadata and add it to the queue.
|
||||||
|
SuccessOrExit(error = messageMetadata.AppendTo(*messageCopy));
|
||||||
|
mBufferedMessageSet.Enqueue(*messageCopy);
|
||||||
|
|
||||||
|
if (mRetransmissionTimer.IsRunning())
|
||||||
|
{
|
||||||
|
// If timer is already running, check if it should be restarted with earlier fire time.
|
||||||
|
nextTransmissionTime = mRetransmissionTimer.Gett0() + mRetransmissionTimer.Getdt();
|
||||||
|
|
||||||
|
if (messageMetadata.IsEarlier(nextTransmissionTime))
|
||||||
|
{
|
||||||
|
mRetransmissionTimer.Start(messageMetadata.GetTransmissionTime() - now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise just set the timer.
|
||||||
|
mRetransmissionTimer.Start(messageMetadata.GetTransmissionTime() - now);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
if (error != kThreadError_None && messageCopy != NULL)
|
||||||
|
{
|
||||||
|
messageCopy->Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError Mpl::ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound)
|
||||||
|
{
|
||||||
|
ThreadError error;
|
||||||
|
OptionMpl option;
|
||||||
|
|
||||||
|
VerifyOrExit(aMessage.Read(aMessage.GetOffset(), sizeof(option), &option) >= OptionMpl::kMinLength &&
|
||||||
|
(option.GetSeedIdLength() == OptionMpl::kSeedIdLength0 ||
|
||||||
|
option.GetSeedIdLength() == OptionMpl::kSeedIdLength2),
|
||||||
|
error = kThreadError_Drop);
|
||||||
|
|
||||||
|
if (option.GetSeedIdLength() == OptionMpl::kSeedIdLength0)
|
||||||
|
{
|
||||||
|
// Retrieve MPL Seed Id from the IPv6 Source Address.
|
||||||
|
option.SetSeedId(HostSwap16(aAddress.mFields.m16[7]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check MPL Data Messages in the MPL Buffered Set against sequence number.
|
||||||
|
UpdateBufferedSet(option.GetSeedId(), option.GetSequence());
|
||||||
|
|
||||||
|
// Check if the MPL Data Message is new.
|
||||||
|
error = UpdateSeedSet(option.GetSeedId(), option.GetSequence());
|
||||||
|
|
||||||
|
if (error == kThreadError_None)
|
||||||
|
{
|
||||||
|
AddBufferedMessage(aMessage, option.GetSeedId(), option.GetSequence(), aIsOutbound);
|
||||||
|
}
|
||||||
|
else if (aIsOutbound)
|
||||||
|
{
|
||||||
|
// In case MPL Data Message is generated locally, ignore potential error of the MPL Seed Set
|
||||||
|
// to allow subsequent retransmissions with the same sequence number.
|
||||||
|
ExitNow(error = kThreadError_None);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mpl::HandleRetransmissionTimer(void *aContext)
|
||||||
|
{
|
||||||
|
static_cast<Mpl *>(aContext)->HandleRetransmissionTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mpl::HandleRetransmissionTimer()
|
||||||
|
{
|
||||||
|
uint32_t now = Timer::GetNow();
|
||||||
|
uint32_t nextDelta = 0xffffffff;
|
||||||
|
MplBufferedMessageMetadata messageMetadata;
|
||||||
|
|
||||||
|
Message *message = mBufferedMessageSet.GetHead();
|
||||||
|
Message *nextMessage = NULL;
|
||||||
|
|
||||||
|
while (message != NULL)
|
||||||
|
{
|
||||||
|
nextMessage = message->GetNext();
|
||||||
|
messageMetadata.ReadFrom(*message);
|
||||||
|
|
||||||
|
if (messageMetadata.IsLater(now))
|
||||||
|
{
|
||||||
|
// Calculate the next retransmission time and choose the lowest.
|
||||||
|
if (messageMetadata.GetTransmissionTime() - now < nextDelta)
|
||||||
|
{
|
||||||
|
nextDelta = messageMetadata.GetTransmissionTime() - now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Update the number of transmission timer expirations.
|
||||||
|
messageMetadata.SetTransmissionCount(messageMetadata.GetTransmissionCount() + 1);
|
||||||
|
|
||||||
|
if (messageMetadata.GetTransmissionCount() < GetTimerExpirations())
|
||||||
|
{
|
||||||
|
Message *messageCopy = message->Clone(message->GetLength() - sizeof(MplBufferedMessageMetadata));
|
||||||
|
|
||||||
|
if (messageCopy != NULL)
|
||||||
|
{
|
||||||
|
mIp6.EnqueueDatagram(*messageCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
messageMetadata.GenerateNextTransmissionTime(now, kDataMessageInterval);
|
||||||
|
messageMetadata.UpdateIn(*message);
|
||||||
|
|
||||||
|
// Check if retransmission time is lower than the current lowest one.
|
||||||
|
if (messageMetadata.GetTransmissionTime() - now < nextDelta)
|
||||||
|
{
|
||||||
|
nextDelta = messageMetadata.GetTransmissionTime() - now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mBufferedMessageSet.Dequeue(*message);
|
||||||
|
|
||||||
|
if (messageMetadata.GetTransmissionCount() == GetTimerExpirations())
|
||||||
|
{
|
||||||
|
// Remove the extra metadata from the MPL Data Message.
|
||||||
|
messageMetadata.RemoveFrom(*message);
|
||||||
|
mIp6.EnqueueDatagram(*message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Stop retransmitting if the number of timer expirations is already exceeded.
|
||||||
|
message->Free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message = nextMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextDelta != 0xffffffff)
|
||||||
|
{
|
||||||
|
mRetransmissionTimer.Start(nextDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mpl::HandleSeedSetTimer(void *aContext)
|
||||||
|
{
|
||||||
|
static_cast<Mpl *>(aContext)->HandleSeedSetTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mpl::HandleSeedSetTimer()
|
||||||
{
|
{
|
||||||
bool startTimer = false;
|
bool startTimer = false;
|
||||||
|
|
||||||
for (int i = 0; i < kNumEntries; i++)
|
for (int i = 0; i < kNumSeedEntries; i++)
|
||||||
{
|
{
|
||||||
if (mEntries[i].mLifetime > 0)
|
if (mSeedSet[i].GetLifetime() > 0)
|
||||||
{
|
{
|
||||||
mEntries[i].mLifetime--;
|
mSeedSet[i].SetLifetime(mSeedSet[i].GetLifetime() - 1);
|
||||||
startTimer = true;
|
startTimer = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startTimer)
|
if (startTimer)
|
||||||
{
|
{
|
||||||
mTimer.Start(1000);
|
mSeedSetTimer.Start(kSeedEntryLifetimeDt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+327
-47
@@ -86,31 +86,31 @@ public:
|
|||||||
uint8_t GetTotalLength() const { return OptionHeader::GetLength() + sizeof(OptionHeader); }
|
uint8_t GetTotalLength() const { return OptionHeader::GetLength() + sizeof(OptionHeader); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MPL Seed lengths.
|
* MPL Seed Id lengths.
|
||||||
*/
|
*/
|
||||||
enum SeedLength
|
enum SeedIdLength
|
||||||
{
|
{
|
||||||
kSeedLength0 = 0 << 6, ///< 0-byte MPL Seed Length.
|
kSeedIdLength0 = 0 << 6, ///< 0-byte MPL Seed Id Length.
|
||||||
kSeedLength2 = 1 << 6, ///< 2-byte MPL Seed Length.
|
kSeedIdLength2 = 1 << 6, ///< 2-byte MPL Seed Id Length.
|
||||||
kSeedLength8 = 2 << 6, ///< 8-byte MPL Seed Length.
|
kSeedIdLength8 = 2 << 6, ///< 8-byte MPL Seed Id Length.
|
||||||
kSeedLength16 = 3 << 6, ///< 16-byte MPL Seed Length.
|
kSeedIdLength16 = 3 << 6, ///< 16-byte MPL Seed Id Length.
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the MPL Seed Length value.
|
* This method returns the MPL Seed Id Length value.
|
||||||
*
|
*
|
||||||
* @returns The MPL Seed Length value.
|
* @returns The MPL Seed Id Length value.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
SeedLength GetSeedLength() { return static_cast<SeedLength>(mControl & kSeedLengthMask); }
|
SeedIdLength GetSeedIdLength() { return static_cast<SeedIdLength>(mControl & kSeedIdLengthMask); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the MPL Seed Length value.
|
* This method sets the MPL Seed Id Length value.
|
||||||
*
|
*
|
||||||
* @param[in] aSeedLength The MPL Seed Length.
|
* @param[in] aSeedIdLength The MPL Seed Length.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void SetSeedLength(SeedLength aSeedLength) { mControl = static_cast<uint8_t>((mControl & ~kSeedLengthMask) | aSeedLength); }
|
void SetSeedIdLength(SeedIdLength aSeedIdLength) { mControl = static_cast<uint8_t>((mControl & ~kSeedIdLengthMask) | aSeedIdLength); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method indicates whether or not the MPL M flag is set.
|
* This method indicates whether or not the MPL M flag is set.
|
||||||
@@ -145,33 +145,281 @@ public:
|
|||||||
* This method sets the MPL Sequence value.
|
* This method sets the MPL Sequence value.
|
||||||
*
|
*
|
||||||
* @param[in] aSequence The MPL Sequence value.
|
* @param[in] aSequence The MPL Sequence value.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
|
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the MPL Seed value.
|
* This method returns the MPL Seed Id value.
|
||||||
*
|
*
|
||||||
* @returns The MPL Seed value.
|
* @returns The MPL Seed Id value.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
uint16_t GetSeed() const { return HostSwap16(mSeed); }
|
uint16_t GetSeedId() const { return HostSwap16(mSeedId); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the MPL Seed value.
|
* This method sets the MPL Seed Id value.
|
||||||
|
*
|
||||||
|
* @param[in] aSeedId The MPL Seed Id value.
|
||||||
*
|
*
|
||||||
* @param[in] aSeed The MPL Seed value.
|
|
||||||
*/
|
*/
|
||||||
void SetSeed(uint16_t aSeed) { mSeed = HostSwap16(aSeed); }
|
void SetSeedId(uint16_t aSeedId) { mSeedId = HostSwap16(aSeedId); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kSeedLengthMask = 3 << 6,
|
kSeedIdLengthMask = 3 << 6,
|
||||||
kMaxFlag = 1 << 5
|
kMaxFlag = 1 << 5
|
||||||
};
|
};
|
||||||
uint8_t mControl;
|
uint8_t mControl;
|
||||||
uint8_t mSequence;
|
uint8_t mSequence;
|
||||||
uint16_t mSeed;
|
uint16_t mSeedId;
|
||||||
|
} OT_TOOL_PACKED_END;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents an MPL's Seed Set entry.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class MplSeedEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* This method returns the MPL Seed Id value.
|
||||||
|
*
|
||||||
|
* @returns The MPL Seed Id value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint16_t GetSeedId() const { return mSeedId; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the MPL Seed Id value.
|
||||||
|
*
|
||||||
|
* @param[in] aSeedId The MPL Seed Id value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetSeedId(uint16_t aSeedId) { mSeedId = aSeedId; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the MPL Sequence value.
|
||||||
|
*
|
||||||
|
* @returns The MPL Sequence value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t GetSequence() const { return mSequence; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the MPL Sequence value.
|
||||||
|
*
|
||||||
|
* @param[in] aSequence The MPL Sequence value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the MPL Seed Set entry's remaining lifetime.
|
||||||
|
*
|
||||||
|
* @returns The MPL Seed Set entry's remaining lifetime.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t GetLifetime() const { return mLifetime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the remaining lifetime of the Seed Set entry.
|
||||||
|
*
|
||||||
|
* @param[in] aLifetime The remaining lifetime of the Seed Set entry.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetLifetime(uint8_t aLifetime) { mLifetime = aLifetime; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t mSeedId;
|
||||||
|
uint8_t mSequence;
|
||||||
|
uint8_t mLifetime;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents metadata required for MPL retransmissions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
OT_TOOL_PACKED_BEGIN
|
||||||
|
class MplBufferedMessageMetadata
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Default constructor for the object.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
MplBufferedMessageMetadata(void):
|
||||||
|
mSeedId(0),
|
||||||
|
mSequence(0),
|
||||||
|
mTransmissionCount(0),
|
||||||
|
mTransmissionTime(0),
|
||||||
|
mIntervalOffset(0) {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method appends MPL Buffered Message metadata to the message.
|
||||||
|
*
|
||||||
|
* @param[in] aMessage A reference to the message.
|
||||||
|
*
|
||||||
|
* @retval kThreadError_None Successfully appended the bytes.
|
||||||
|
* @retval kThreadError_NoBufs Insufficient available buffers to grow the message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ThreadError AppendTo(Message &aMessage) const {
|
||||||
|
return aMessage.Append(this, sizeof(*this));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method reads request data from the message.
|
||||||
|
*
|
||||||
|
* @param[in] aMessage A reference to the message.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes that have been read.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint16_t ReadFrom(const Message &aMessage) {
|
||||||
|
return aMessage.Read(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method removes MPL Buffered Messsage metadata from the message.
|
||||||
|
*
|
||||||
|
* @param[in] aMessage A reference to the message.
|
||||||
|
*
|
||||||
|
* @retval kThreadError_None Successfully removed the header.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ThreadError RemoveFrom(Message &aMessage) {
|
||||||
|
return aMessage.SetLength(aMessage.GetLength() - sizeof(*this));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method updates MPL Buffered Messsage metadata in the message.
|
||||||
|
*
|
||||||
|
* @param[in] aMessage A reference to the message.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes that have been updated.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int UpdateIn(Message &aMessage) const {
|
||||||
|
return aMessage.Write(aMessage.GetLength() - sizeof(*this), sizeof(*this), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if the message shall be sent before the given time.
|
||||||
|
*
|
||||||
|
* @param[in] aTime A time to compare.
|
||||||
|
*
|
||||||
|
* @retval TRUE If the message shall be sent before the given time.
|
||||||
|
* @retval FALSE Otherwise.
|
||||||
|
*/
|
||||||
|
bool IsEarlier(uint32_t aTime) const { return (static_cast<int32_t>(aTime - mTransmissionTime) > 0); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if the message shall be sent after the given time.
|
||||||
|
*
|
||||||
|
* @param[in] aTime A time to compare.
|
||||||
|
*
|
||||||
|
* @retval TRUE If the message shall be sent after the given time.
|
||||||
|
* @retval FALSE Otherwise.
|
||||||
|
*/
|
||||||
|
bool IsLater(uint32_t aTime) const { return (static_cast<int32_t>(aTime - mTransmissionTime) < 0); };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the MPL Seed Id value.
|
||||||
|
*
|
||||||
|
* @returns The MPL Seed Id value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint16_t GetSeedId() const { return mSeedId; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the MPL Seed Id value.
|
||||||
|
*
|
||||||
|
* @param[in] aSeedId The MPL Seed Id value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetSeedId(uint16_t aSeedId) { mSeedId = aSeedId; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the MPL Sequence value.
|
||||||
|
*
|
||||||
|
* @returns The MPL Sequence value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t GetSequence() const { return mSequence; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the MPL Sequence value.
|
||||||
|
*
|
||||||
|
* @param[in] aSequence The MPL Sequence value.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the number of already preformed transmissions.
|
||||||
|
*
|
||||||
|
* @returns The number of already preformed transmissions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t GetTransmissionCount() const { return mTransmissionCount; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the number of already performed transmissions.
|
||||||
|
*
|
||||||
|
* @param[in] aTransmissionCount The number of already performed transmissions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetTransmissionCount(uint8_t aTransmissionCount) { mTransmissionCount = aTransmissionCount; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the transmission timestamp of the message.
|
||||||
|
*
|
||||||
|
* @returns The transmission timestamp of the message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint32_t GetTransmissionTime() const { return mTransmissionTime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the transmission timestamp of the message.
|
||||||
|
*
|
||||||
|
* @param[in] aTransmissionTime The transmission timestamp of the message.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetTransmissionTime(uint32_t aTransmissionTime) { mTransmissionTime = aTransmissionTime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the offset from the transmission time to the end of trickle interval.
|
||||||
|
*
|
||||||
|
* @returns The offset from the the transmission time to the end of trickle interval.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint32_t GetIntervalOffset() const { return mIntervalOffset; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the offset from the transmission time to the end of trickle interval.
|
||||||
|
*
|
||||||
|
* @param[in] aIntervalOffset The offset from the the transmission time to the end of trickle interval.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetIntervalOffset(uint8_t aIntervalOffset) { mIntervalOffset = aIntervalOffset; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method generates the next transmission time for the MPL Data Message.
|
||||||
|
*
|
||||||
|
* @param[in] aCurrentTime Current time (in milliseconds).
|
||||||
|
* @param[in] aInterval The current interval size (in milliseconds).
|
||||||
|
*/
|
||||||
|
void GenerateNextTransmissionTime(uint32_t aCurrentTime, uint8_t aInterval);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t mSeedId;
|
||||||
|
uint8_t mSequence;
|
||||||
|
uint8_t mTransmissionCount;
|
||||||
|
uint32_t mTransmissionTime;
|
||||||
|
uint8_t mIntervalOffset;
|
||||||
} OT_TOOL_PACKED_END;
|
} OT_TOOL_PACKED_END;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -199,65 +447,97 @@ public:
|
|||||||
void InitOption(OptionMpl &aOption, const Address &aAddress);
|
void InitOption(OptionMpl &aOption, const Address &aAddress);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method processes an MPL option.
|
* This method processes an MPL option. When the MPL module acts as an MPL Forwarder
|
||||||
|
* it disseminates MPL Data Message using Trickle timer expirations. When acts as an
|
||||||
|
* MPL Seed it allows to send the first MPL Data Message directly, then sets up Trickle
|
||||||
|
* timer expirations for subsequent retransmissions.
|
||||||
*
|
*
|
||||||
* @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.
|
* @param[in] aAddress A reference to the IPv6 Source Address.
|
||||||
* @param[out] aForward TRUE if this message should be forwarded, FALSE otherwise.
|
* @param[in] aIsOutbound TRUE if this message was locally generated, FALSE otherwise.
|
||||||
*
|
*
|
||||||
* @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, const Address &aAddress, bool &aForward);
|
ThreadError ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the MPL Seed value.
|
* This method returns the MPL Seed Id value.
|
||||||
*
|
*
|
||||||
* @returns The MPL Seed value.
|
* @returns The MPL Seed Id value.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
uint16_t GetSeed() const { return mSeed; }
|
uint16_t GetSeedId() const { return mSeedId; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets the MPL Seed value.
|
* This method sets the MPL Seed Id value.
|
||||||
|
*
|
||||||
|
* @param[in] aSeedId The MPL Seed Id value.
|
||||||
*
|
*
|
||||||
* @param[in] aSeed The MPL Seed value.
|
|
||||||
*/
|
*/
|
||||||
void SetSeed(uint16_t aSeed) { mSeed = aSeed; }
|
void SetSeedId(uint16_t aSeedId) { mSeedId = aSeedId; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets IPv6 matching address, that allows to elide seed-id.
|
* This method gets the MPL number of Trickle timer expirations that occur before
|
||||||
|
* terminating the Trickle algorithm's retransmission of a given MPL Data Message.
|
||||||
|
*
|
||||||
|
* @returns The MPL number of Trickle timer expirations.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
uint8_t GetTimerExpirations() const { return mTimerExpirations; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the MPL number of Trickle timer expirations that occur before
|
||||||
|
* terminating the Trickle algorithm's retransmission of a given MPL Data Message.
|
||||||
|
*
|
||||||
|
* @param[in] aTimerExpirations The number of Trickle timer expirations.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetTimerExpirations(uint8_t aTimerExpirations) { mTimerExpirations = aTimerExpirations; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the IPv6 matching address, that allows to elide MPL Seed Id.
|
||||||
|
*
|
||||||
|
* @param[in] aAddress The reference to the IPv6 matching address.
|
||||||
*
|
*
|
||||||
* @param[in] aAddress The reference to IPv6 matching address.
|
|
||||||
*/
|
*/
|
||||||
void SetMatchingAddress(const Address &aAddress) { mMatchingAddress = &aAddress; }
|
void SetMatchingAddress(const Address &aAddress) { mMatchingAddress = &aAddress; }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
kNumEntries = OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES,
|
kNumSeedEntries = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES,
|
||||||
kLifetime = OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME,
|
kSeedEntryLifetime = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME,
|
||||||
|
kSeedEntryLifetimeDt = 1000,
|
||||||
|
kDataMessageInterval = 64
|
||||||
};
|
};
|
||||||
|
|
||||||
static void HandleTimer(void *context);
|
ThreadError UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence);
|
||||||
void HandleTimer();
|
void UpdateBufferedSet(uint16_t aSeedId, uint8_t aSequence);
|
||||||
|
void AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound);
|
||||||
|
|
||||||
Timer mTimer;
|
static void HandleSeedSetTimer(void *aContext);
|
||||||
|
void HandleSeedSetTimer();
|
||||||
|
|
||||||
|
static void HandleRetransmissionTimer(void *aContext);
|
||||||
|
void HandleRetransmissionTimer();
|
||||||
|
|
||||||
|
Ip6 &mIp6;
|
||||||
|
|
||||||
|
Timer mSeedSetTimer;
|
||||||
|
Timer mRetransmissionTimer;
|
||||||
|
|
||||||
|
uint8_t mTimerExpirations;
|
||||||
uint8_t mSequence;
|
uint8_t mSequence;
|
||||||
uint16_t mSeed;
|
uint16_t mSeedId;
|
||||||
const Address *mMatchingAddress;
|
const Address *mMatchingAddress;
|
||||||
|
|
||||||
struct MplEntry
|
MplSeedEntry mSeedSet[kNumSeedEntries];
|
||||||
{
|
MessageQueue mBufferedMessageSet;
|
||||||
uint16_t mSeed;
|
|
||||||
uint8_t mSequence;
|
|
||||||
uint8_t mLifetime;
|
|
||||||
};
|
|
||||||
MplEntry mEntries[kNumEntries];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -136,24 +136,24 @@
|
|||||||
#endif // OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
|
#endif // OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES
|
* @def OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES
|
||||||
*
|
*
|
||||||
* The number of MPL cache entries for duplicate detection.
|
* The number of MPL Seed Set entries for duplicate detection.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES
|
#ifndef OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES
|
||||||
#define OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES 32
|
#define OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES 32
|
||||||
#endif // OPENTHREAD_CONFIG_MPL_CACHE_ENTRIES
|
#endif // OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME
|
* @def OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME
|
||||||
*
|
*
|
||||||
* The MPL cache entry lifetime in seconds.
|
* The MPL Seed Set entry lifetime in seconds.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME
|
#ifndef OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME
|
||||||
#define OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME 5
|
#define OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME 5
|
||||||
#endif // OPENTHREAD_CONFIG_MPL_CACHE_ENTRY_LIFETIME
|
#endif // OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_JOINER_UDP_PORT
|
* @def OPENTHREAD_CONFIG_JOINER_UDP_PORT
|
||||||
@@ -360,4 +360,3 @@
|
|||||||
#endif // OPENTHREAD_CONFIG_SETTINGS_PAGE_NUM
|
#endif // OPENTHREAD_CONFIG_SETTINGS_PAGE_NUM
|
||||||
|
|
||||||
#endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_
|
#endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_
|
||||||
|
|
||||||
|
|||||||
@@ -390,6 +390,7 @@ ThreadError Mle::SetStateDetached(void)
|
|||||||
mMesh.SetRxOnWhenIdle(true);
|
mMesh.SetRxOnWhenIdle(true);
|
||||||
mMleRouter.HandleDetachStart();
|
mMleRouter.HandleDetachStart();
|
||||||
mNetif.GetIp6().SetForwardingEnabled(false);
|
mNetif.GetIp6().SetForwardingEnabled(false);
|
||||||
|
mNetif.GetIp6().mMpl.SetTimerExpirations(0);
|
||||||
|
|
||||||
otLogInfoMle("Mode -> Detached");
|
otLogInfoMle("Mode -> Detached");
|
||||||
return kThreadError_None;
|
return kThreadError_None;
|
||||||
@@ -423,6 +424,7 @@ ThreadError Mle::SetStateChild(uint16_t aRloc16)
|
|||||||
|
|
||||||
mNetif.GetNetworkDataLocal().ClearResubmitDelayTimer();
|
mNetif.GetNetworkDataLocal().ClearResubmitDelayTimer();
|
||||||
mNetif.GetIp6().SetForwardingEnabled(false);
|
mNetif.GetIp6().SetForwardingEnabled(false);
|
||||||
|
mNetif.GetIp6().mMpl.SetTimerExpirations(kMplChildDataMessageTimerExpirations);
|
||||||
|
|
||||||
if (mPreviousPanId != Mac::kPanIdBroadcast && (mDeviceMode & ModeTlv::kModeFFD))
|
if (mPreviousPanId != Mac::kPanIdBroadcast && (mDeviceMode & ModeTlv::kModeFFD))
|
||||||
{
|
{
|
||||||
@@ -589,7 +591,7 @@ ThreadError Mle::SetRloc16(uint16_t aRloc16)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mMac.SetShortAddress(aRloc16);
|
mMac.SetShortAddress(aRloc16);
|
||||||
mNetif.GetIp6().mMpl.SetSeed(aRloc16);
|
mNetif.GetIp6().mMpl.SetSeedId(aRloc16);
|
||||||
|
|
||||||
return kThreadError_None;
|
return kThreadError_None;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,16 @@ enum
|
|||||||
kMinAssignedLinkMargin0 = 0x00, ///< minimal link margin for LQI 0 (0 - 2)
|
kMinAssignedLinkMargin0 = 0x00, ///< minimal link margin for LQI 0 (0 - 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multicast Forwarding Constants
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kMplChildDataMessageTimerExpirations = 0, ///< Number of MPL retransmissions for Children.
|
||||||
|
kMplRouterDataMessageTimerExpirations = 2, ///< Number of MPL retransmissions for Routers.
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Mle
|
} // namespace Mle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -359,6 +359,7 @@ ThreadError MleRouter::SetStateRouter(uint16_t aRloc16)
|
|||||||
mNetworkData.Stop();
|
mNetworkData.Stop();
|
||||||
mStateUpdateTimer.Start(kStateUpdatePeriod);
|
mStateUpdateTimer.Start(kStateUpdatePeriod);
|
||||||
mNetif.GetIp6().SetForwardingEnabled(true);
|
mNetif.GetIp6().SetForwardingEnabled(true);
|
||||||
|
mNetif.GetIp6().mMpl.SetTimerExpirations(kMplRouterDataMessageTimerExpirations);
|
||||||
|
|
||||||
otLogInfoMle("Mode -> Router");
|
otLogInfoMle("Mode -> Router");
|
||||||
return kThreadError_None;
|
return kThreadError_None;
|
||||||
@@ -386,6 +387,7 @@ ThreadError MleRouter::SetStateLeader(uint16_t aRloc16)
|
|||||||
mCoapServer.AddResource(mAddressSolicit);
|
mCoapServer.AddResource(mAddressSolicit);
|
||||||
mCoapServer.AddResource(mAddressRelease);
|
mCoapServer.AddResource(mAddressRelease);
|
||||||
mNetif.GetIp6().SetForwardingEnabled(true);
|
mNetif.GetIp6().SetForwardingEnabled(true);
|
||||||
|
mNetif.GetIp6().mMpl.SetTimerExpirations(kMplRouterDataMessageTimerExpirations);
|
||||||
|
|
||||||
otLogInfoMle("Mode -> Leader %d", mLeaderData.GetPartitionId());
|
otLogInfoMle("Mode -> Leader %d", mLeaderData.GetPartitionId());
|
||||||
return kThreadError_None;
|
return kThreadError_None;
|
||||||
|
|||||||
Reference in New Issue
Block a user