mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 01:47:47 +00:00
Implement MLE Discovery Request and Response. (#322)
This commit is contained in:
@@ -160,6 +160,8 @@ typedef struct otExtAddress
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_PANID_BROADCAST 0xffff ///< IEEE 802.15.4 Broadcast PAN ID
|
||||
|
||||
#define OT_CHANNEL_11_MASK (1 << 11) ///< Channel 11
|
||||
#define OT_CHANNEL_12_MASK (1 << 12) ///< Channel 12
|
||||
#define OT_CHANNEL_13_MASK (1 << 13) ///< Channel 13
|
||||
|
||||
+23
-1
@@ -232,7 +232,7 @@ typedef void (*otHandleActiveScanResult)(otActiveScanResult *aResult);
|
||||
*
|
||||
* @param[in] aScanChannels A bit vector indicating which channels to scan (e.g. OT_CHANNEL_11_MASK).
|
||||
* @param[in] aScanDuration The time in milliseconds to spend scanning each channel.
|
||||
* @param[in] aCallback A pointer to a function that is called when a beacon is received or the scan completes.
|
||||
* @param[in] aCallback A pointer to a function called on receiving a beacon or scan completes.
|
||||
*
|
||||
* @retval kThreadError_None Accepted the Active Scan request.
|
||||
* @retval kThreadError_Busy Already performing an Active Scan.
|
||||
@@ -247,6 +247,28 @@ ThreadError otActiveScan(uint32_t aScanChannels, uint16_t aScanDuration, otHandl
|
||||
*/
|
||||
bool otActiveScanInProgress(void);
|
||||
|
||||
/**
|
||||
* This function starts a Thread Discovery scan.
|
||||
*
|
||||
* @param[in] aScanChannels A bit vector indicating which channels to scan (e.g. OT_CHANNEL_11_MASK).
|
||||
* @param[in] aScanDuration The time in milliseconds to spend scanning each channel.
|
||||
* @param[in] aPanId The PAN ID filter (set to Broadcast PAN to disable filter).
|
||||
* @param[in] aCallback A pointer to a function called on receiving an MLE Discovery Response or scan completes.
|
||||
*
|
||||
* @retval kThreadError_None Accepted the Thread Discovery request.
|
||||
* @retval kThreadError_Busy Already performing an Thread Discovery.
|
||||
*
|
||||
*/
|
||||
ThreadError otDiscover(uint32_t aScanChannels, uint16_t aScanDuration, uint16_t aPanid,
|
||||
otHandleActiveScanResult aCallback);
|
||||
|
||||
/**
|
||||
* This function determines if an MLE Thread Discovery is currently in progress.
|
||||
*
|
||||
* @returns true if an active scan is in progress.
|
||||
*/
|
||||
bool otDiscoverInProgress(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
+18
-3
@@ -12,6 +12,7 @@ OpenThread test scripts use the CLI to execute test cases.
|
||||
* [childtimeout](#childtimeout)
|
||||
* [contextreusedelay](#contextreusedelay)
|
||||
* [counter](#counter)
|
||||
* [discover](#discover)
|
||||
* [eidcache](#eidcache)
|
||||
* [extaddr](#extaddr)
|
||||
* [extpanid](#extpanid)
|
||||
@@ -168,6 +169,20 @@ RxTotal: 11
|
||||
RxErrOther: 0
|
||||
```
|
||||
|
||||
### discover \[channel\]
|
||||
|
||||
Perform an MLE Discovery operation.
|
||||
|
||||
* channel: The channel to discover on. If no channel is provided, the discovery will cover all valid channels.
|
||||
|
||||
```bash
|
||||
> discover
|
||||
| J | Network Name | Extended PAN | PAN | MAC Address | Ch | dBm | LQI |
|
||||
+---+------------------+------------------+------+------------------+----+-----+-----+
|
||||
| 0 | OpenThread | dead00beef00cafe | ffff | f1d92a82c8d8fe43 | 11 | -20 | 0 |
|
||||
Done
|
||||
```
|
||||
|
||||
### eidcache
|
||||
|
||||
Print the EID-to-RLOC cache entries.
|
||||
@@ -574,9 +589,9 @@ Perform an IEEE 802.15.4 Active Scan.
|
||||
|
||||
```bash
|
||||
> scan
|
||||
| J | Network Name | Extended PAN | PAN | MAC Address | Ch | dBm |
|
||||
+---+------------------+------------------+------+------------------+----+-----+
|
||||
| 0 | OpenThread | dead00beef00cafe | ffff | f1d92a82c8d8fe43 | 11 | -20 |
|
||||
| J | Network Name | Extended PAN | PAN | MAC Address | Ch | dBm | LQI |
|
||||
+---+------------------+------------------+------+------------------+----+-----+-----+
|
||||
| 0 | OpenThread | dead00beef00cafe | ffff | f1d92a82c8d8fe43 | 11 | -20 | 0 |
|
||||
Done
|
||||
```
|
||||
|
||||
|
||||
+26
-2
@@ -56,6 +56,7 @@ const struct Command Interpreter::sCommands[] =
|
||||
{ "childtimeout", &ProcessChildTimeout },
|
||||
{ "contextreusedelay", &ProcessContextIdReuseDelay },
|
||||
{ "counter", &ProcessCounters },
|
||||
{ "discover", &ProcessDiscover },
|
||||
{ "eidcache", &ProcessEidCache },
|
||||
{ "extaddr", &ProcessExtAddress },
|
||||
{ "extpanid", &ProcessExtPanId },
|
||||
@@ -353,6 +354,28 @@ void Interpreter::ProcessCounters(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::ProcessDiscover(int argc, char *argv[])
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint32_t scanChannels = 0;
|
||||
long value;
|
||||
|
||||
if (argc > 0)
|
||||
{
|
||||
SuccessOrExit(error = ParseLong(argv[0], value));
|
||||
scanChannels = 1 << value;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otDiscover(scanChannels, 0, OT_PANID_BROADCAST, &HandleActiveScanResult));
|
||||
sServer->OutputFormat("| J | Network Name | Extended PAN | PAN | MAC Address | Ch | dBm | LQI |\r\n");
|
||||
sServer->OutputFormat("+---+------------------+------------------+------+------------------+----+-----+-----+\r\n");
|
||||
|
||||
return;
|
||||
|
||||
exit:
|
||||
AppendResult(error);
|
||||
}
|
||||
|
||||
void Interpreter::ProcessEidCache(int argc, char *argv[])
|
||||
{
|
||||
otEidCacheEntry entry;
|
||||
@@ -1246,7 +1269,9 @@ void Interpreter::HandleActiveScanResult(otActiveScanResult *aResult)
|
||||
|
||||
if (aResult->mExtPanId != NULL)
|
||||
{
|
||||
sServer->OutputFormat("| ");
|
||||
OutputBytes(aResult->mExtPanId, OT_EXT_PAN_ID_SIZE);
|
||||
sServer->OutputFormat(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1254,9 +1279,8 @@ void Interpreter::HandleActiveScanResult(otActiveScanResult *aResult)
|
||||
}
|
||||
|
||||
sServer->OutputFormat("| %04x | ", aResult->mPanId);
|
||||
|
||||
OutputBytes(aResult->mExtAddress.m8, OT_EXT_ADDRESS_SIZE);
|
||||
sServer->OutputFormat("| %2d ", aResult->mChannel);
|
||||
sServer->OutputFormat(" | %2d ", aResult->mChannel);
|
||||
sServer->OutputFormat("| %3d ", aResult->mRssi);
|
||||
sServer->OutputFormat("| %3d |\r\n", aResult->mLqi);
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ private:
|
||||
static void ProcessChildTimeout(int argc, char *argv[]);
|
||||
static void ProcessContextIdReuseDelay(int argc, char *argv[]);
|
||||
static void ProcessCounters(int argc, char *argv[]);
|
||||
static void ProcessDiscover(int argc, char *argv[]);
|
||||
static void ProcessEidCache(int argc, char *argv[]);
|
||||
static void ProcessExtAddress(int argc, char *argv[]);
|
||||
static void ProcessExtPanId(int argc, char *argv[]);
|
||||
|
||||
@@ -100,6 +100,7 @@ noinst_HEADERS = \
|
||||
thread/key_manager.hpp \
|
||||
thread/link_quality.hpp \
|
||||
thread/lowpan.hpp \
|
||||
thread/meshcop_tlvs.hpp \
|
||||
thread/mesh_forwarder.hpp \
|
||||
thread/mle.hpp \
|
||||
thread/mle_constants.hpp \
|
||||
|
||||
+40
-10
@@ -440,16 +440,6 @@ void Message::SetDatagramTag(uint16_t aTag)
|
||||
mInfo.mDatagramTag = aTag;
|
||||
}
|
||||
|
||||
uint8_t Message::GetTimeout(void) const
|
||||
{
|
||||
return mInfo.mTimeout;
|
||||
}
|
||||
|
||||
void Message::SetTimeout(uint8_t aTimeout)
|
||||
{
|
||||
mInfo.mTimeout = aTimeout;
|
||||
}
|
||||
|
||||
bool Message::GetChildMask(uint8_t aChildIndex) const
|
||||
{
|
||||
assert(aChildIndex < sizeof(mInfo.mChildMask) * 8);
|
||||
@@ -484,6 +474,26 @@ exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint16_t Message::GetPanId(void) const
|
||||
{
|
||||
return mInfo.mPanId;
|
||||
}
|
||||
|
||||
void Message::SetPanId(uint16_t aPanId)
|
||||
{
|
||||
mInfo.mPanId = aPanId;
|
||||
}
|
||||
|
||||
uint8_t Message::GetTimeout(void) const
|
||||
{
|
||||
return mInfo.mTimeout;
|
||||
}
|
||||
|
||||
void Message::SetTimeout(uint8_t aTimeout)
|
||||
{
|
||||
mInfo.mTimeout = aTimeout;
|
||||
}
|
||||
|
||||
bool Message::GetDirectTransmission(void) const
|
||||
{
|
||||
return mInfo.mDirectTx;
|
||||
@@ -509,6 +519,26 @@ void Message::SetLinkSecurityEnabled(bool aLinkSecurityEnabled)
|
||||
mInfo.mLinkSecurity = aLinkSecurityEnabled;
|
||||
}
|
||||
|
||||
bool Message::IsMleDiscoverRequest(void) const
|
||||
{
|
||||
return mInfo.mMleDiscoverRequest;
|
||||
}
|
||||
|
||||
void Message::SetMleDiscoverRequest(bool aMleDiscoverRequest)
|
||||
{
|
||||
mInfo.mMleDiscoverRequest = aMleDiscoverRequest;
|
||||
}
|
||||
|
||||
bool Message::IsMleDiscoverResponse(void) const
|
||||
{
|
||||
return mInfo.mMleDiscoverResponse;
|
||||
}
|
||||
|
||||
void Message::SetMleDiscoverResponse(bool aMleDiscoverResponse)
|
||||
{
|
||||
mInfo.mMleDiscoverResponse = aMleDiscoverResponse;
|
||||
}
|
||||
|
||||
uint16_t Message::UpdateChecksum(uint16_t aChecksum, uint16_t aOffset, uint16_t aLength) const
|
||||
{
|
||||
Buffer *curBuffer;
|
||||
|
||||
+71
-16
@@ -108,13 +108,16 @@ struct MessageInfo
|
||||
uint16_t mLength; ///< Number of bytes within the message.
|
||||
uint16_t mOffset; ///< A byte offset within the message.
|
||||
uint16_t mDatagramTag; ///< The datagram tag used for 6LoWPAN fragmentation.
|
||||
uint8_t mTimeout; ///< Seconds remaining before dropping the message.
|
||||
|
||||
uint8_t mChildMask[8]; ///< A bit-vector to indicate which sleepy children need to receive this message.
|
||||
uint8_t mChildMask[8]; ///< A bit-vector to indicate which sleepy children need to receive this.
|
||||
uint16_t mPanId; ///< The Destination PAN ID.
|
||||
uint8_t mTimeout; ///< Seconds remaining before dropping the message.
|
||||
|
||||
uint8_t mType : 2; ///< Identifies the type of message.
|
||||
bool mDirectTx : 1; ///< Used to indicate whether a direct transmission is required.
|
||||
bool mLinkSecurity : 1; ///< Indicates whether or not link security is enabled.
|
||||
bool mMleDiscoverRequest : 1; ///< Identifies MLE Discover Request.
|
||||
bool mMleDiscoverResponse : 1; ///< Identifies MLE Discover Response.
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -353,20 +356,6 @@ public:
|
||||
*/
|
||||
void SetDatagramTag(uint16_t aTag);
|
||||
|
||||
/**
|
||||
* This method returns the timeout used for 6LoWPAN reassembly.
|
||||
*
|
||||
* @returns The time remaining in seconds.
|
||||
*
|
||||
*/
|
||||
uint8_t GetTimeout(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the timeout used for 6LoWPAN reassembly.
|
||||
*
|
||||
*/
|
||||
void SetTimeout(uint8_t aTimeout);
|
||||
|
||||
/**
|
||||
* This method returns whether or not the message forwarding is scheduled for the child.
|
||||
*
|
||||
@@ -403,6 +392,38 @@ public:
|
||||
*/
|
||||
bool IsChildPending(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
*/
|
||||
uint16_t GetPanId(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
* @param[in] aPanId The IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
*/
|
||||
void SetPanId(uint16_t aPanId);
|
||||
|
||||
/**
|
||||
* This method returns the timeout used for 6LoWPAN reassembly.
|
||||
*
|
||||
* @returns The time remaining in seconds.
|
||||
*
|
||||
*/
|
||||
uint8_t GetTimeout(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the timeout used for 6LoWPAN reassembly.
|
||||
*
|
||||
* @param[in] aTimeout The timeout value.
|
||||
*
|
||||
*/
|
||||
void SetTimeout(uint8_t aTimeout);
|
||||
|
||||
/**
|
||||
* This method returns whether or not message forwarding is scheduled for direct transmission.
|
||||
*
|
||||
@@ -441,6 +462,40 @@ public:
|
||||
*/
|
||||
void SetLinkSecurityEnabled(bool aLinkSecurityEnabled);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not this message is an MLE Discovery Request.
|
||||
*
|
||||
* @retval TRUE If this message is an MLE Discovery Request.
|
||||
* @retval FALSE If this message is not an MLE Discovery Request.
|
||||
*
|
||||
*/
|
||||
bool IsMleDiscoverRequest(void) const;
|
||||
|
||||
/**
|
||||
* This method sets whether or not this message is an MLE Discovery Request.
|
||||
*
|
||||
* @param[in] aLinkSecurityEnabled TRUE if this message is an MLE Discovery Request, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void SetMleDiscoverRequest(bool aMleDiscoverRequest);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not this message is an MLE Discovery Response.
|
||||
*
|
||||
* @retval TRUE If this message is an MLE Discovery Response.
|
||||
* @retval FALSE If this message is not an MLE Discovery Response.
|
||||
*
|
||||
*/
|
||||
bool IsMleDiscoverResponse(void) const;
|
||||
|
||||
/**
|
||||
* This method sets whether or not this message is an MLE Discovery Response.
|
||||
*
|
||||
* @param[in] aLinkSecurityEnabled TRUE if this message is an MLE Discovery Response, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void SetMleDiscoverResponse(bool aMleDiscoverResponse);
|
||||
|
||||
/**
|
||||
* This method is used to update a checksum value.
|
||||
*
|
||||
|
||||
@@ -382,15 +382,16 @@ exit:
|
||||
|
||||
ThreadError Frame::SetSrcPanId(PanId aPanId)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint8_t *buf;
|
||||
|
||||
buf = FindSrcPanId();
|
||||
assert(buf != NULL);
|
||||
VerifyOrExit((buf = FindSrcPanId()) != NULL, error = kThreadError_Parse);
|
||||
|
||||
buf[0] = aPanId;
|
||||
buf[1] = aPanId >> 8;
|
||||
|
||||
return kThreadError_None;
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t *Frame::FindSrcAddr(void)
|
||||
|
||||
@@ -60,6 +60,7 @@ extern "C" {
|
||||
static otDEFINE_ALIGNED_VAR(sThreadNetifRaw, sizeof(ThreadNetif), uint64_t);
|
||||
|
||||
static void HandleActiveScanResult(void *aContext, Mac::Frame *aFrame);
|
||||
static void HandleMleDiscover(otActiveScanResult *aResult, void *aContext);
|
||||
|
||||
void otProcessNextTasklet(void)
|
||||
{
|
||||
@@ -813,6 +814,19 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadError otDiscover(uint32_t aScanChannels, uint16_t aScanDuration, uint16_t aPanId,
|
||||
otHandleActiveScanResult aCallback)
|
||||
{
|
||||
return sThreadNetif->GetMle().Discover(aScanChannels, aScanDuration, aPanId, &HandleMleDiscover,
|
||||
reinterpret_cast<void *>(aCallback));
|
||||
}
|
||||
|
||||
void HandleMleDiscover(otActiveScanResult *aResult, void *aContext)
|
||||
{
|
||||
otHandleActiveScanResult handler = reinterpret_cast<otHandleActiveScanResult>(aContext);
|
||||
handler(aResult);
|
||||
}
|
||||
|
||||
void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback)
|
||||
{
|
||||
Ip6::Ip6::SetReceiveDatagramCallback(aCallback);
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Thread {
|
||||
MeshForwarder::MeshForwarder(ThreadNetif &aThreadNetif):
|
||||
mMacReceiver(&HandleReceivedFrame, this),
|
||||
mMacSender(&HandleFrameRequest, &HandleSentFrame, this),
|
||||
mDiscoverTimer(&HandleDiscoverTimer, this),
|
||||
mPollTimer(&HandlePollTimer, this),
|
||||
mReassemblyTimer(&HandleReassemblyTimer, this),
|
||||
mScheduleTransmissionTask(ScheduleTransmissionTask, this),
|
||||
@@ -461,8 +462,6 @@ ThreadError MeshForwarder::UpdateIp6Route(Message &aMessage)
|
||||
switch (mMle.GetDeviceState())
|
||||
{
|
||||
case Mle::kDeviceStateDisabled:
|
||||
break;
|
||||
|
||||
case Mle::kDeviceStateDetached:
|
||||
if (ip6Header.GetDestination().IsLinkLocal() || ip6Header.GetDestination().IsLinkLocalMulticast())
|
||||
{
|
||||
@@ -661,6 +660,25 @@ ThreadError MeshForwarder::HandleFrameRequest(Mac::Frame &aFrame)
|
||||
switch (mSendMessage->GetType())
|
||||
{
|
||||
case Message::kTypeIp6:
|
||||
if (mSendMessage->IsMleDiscoverRequest())
|
||||
{
|
||||
if (!mScanning)
|
||||
{
|
||||
mScanChannel = kPhyMinChannel;
|
||||
mRestoreChannel = mMac.GetChannel();
|
||||
mScanning = true;
|
||||
}
|
||||
|
||||
while ((mScanChannels & 1) == 0)
|
||||
{
|
||||
mScanChannels >>= 1;
|
||||
mScanChannel++;
|
||||
}
|
||||
|
||||
mMac.SetChannel(mScanChannel);
|
||||
aFrame.SetChannel(mScanChannel);
|
||||
}
|
||||
|
||||
SendFragment(*mSendMessage, aFrame);
|
||||
assert(aFrame.GetLength() != 7);
|
||||
break;
|
||||
@@ -772,6 +790,7 @@ ThreadError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
int payloadLength;
|
||||
int hcLength;
|
||||
uint16_t fragmentLength;
|
||||
uint16_t dstpan;
|
||||
|
||||
if (mAddMeshHeader)
|
||||
{
|
||||
@@ -787,7 +806,7 @@ ThreadError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
}
|
||||
|
||||
// initialize MAC header
|
||||
fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfPanidCompression | Mac::Frame::kFcfFrameVersion2006;
|
||||
fcf = Mac::Frame::kFcfFrameData | Mac::Frame::kFcfFrameVersion2006;
|
||||
fcf |= (mMacDest.mLength == 2) ? Mac::Frame::kFcfDstAddrShort : Mac::Frame::kFcfDstAddrExt;
|
||||
fcf |= (mMacSource.mLength == 2) ? Mac::Frame::kFcfSrcAddrShort : Mac::Frame::kFcfSrcAddrExt;
|
||||
|
||||
@@ -802,8 +821,23 @@ ThreadError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
fcf |= Mac::Frame::kFcfSecurityEnabled;
|
||||
}
|
||||
|
||||
if (aMessage.IsMleDiscoverRequest() || aMessage.IsMleDiscoverResponse())
|
||||
{
|
||||
dstpan = aMessage.GetPanId();
|
||||
}
|
||||
else
|
||||
{
|
||||
dstpan = mMac.GetPanId();
|
||||
}
|
||||
|
||||
if (dstpan == mMac.GetPanId())
|
||||
{
|
||||
fcf |= Mac::Frame::kFcfPanidCompression;
|
||||
}
|
||||
|
||||
aFrame.InitMacHeader(fcf, Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32);
|
||||
aFrame.SetDstPanId(mMac.GetPanId());
|
||||
aFrame.SetDstPanId(dstpan);
|
||||
aFrame.SetSrcPanId(mMac.GetPanId());
|
||||
|
||||
if (mMacDest.mLength == 2)
|
||||
{
|
||||
@@ -961,6 +995,13 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame)
|
||||
mSendMessage->ClearDirectTransmission();
|
||||
mSendMessage->SetOffset(0);
|
||||
}
|
||||
|
||||
if (mSendMessage->IsMleDiscoverRequest())
|
||||
{
|
||||
mSendBusy = true;
|
||||
mDiscoverTimer.Start(mScanDuration);
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
if (mSendMessage->GetDirectTransmission() == false && mSendMessage->IsChildPending() == false)
|
||||
@@ -975,6 +1016,44 @@ exit:
|
||||
{}
|
||||
}
|
||||
|
||||
void MeshForwarder::SetDiscoverParameters(uint32_t aScanChannels, uint16_t aScanDuration)
|
||||
{
|
||||
mScanChannels = (aScanChannels == 0) ? static_cast<uint32_t>(Mac::kScanChannelsAll) : aScanChannels;
|
||||
mScanDuration = (aScanDuration == 0) ? static_cast<uint16_t>(Mac::kScanDurationDefault) : aScanDuration;
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleDiscoverTimer(void *aContext)
|
||||
{
|
||||
MeshForwarder *obj = static_cast<MeshForwarder *>(aContext);
|
||||
obj->HandleDiscoverTimer();
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleDiscoverTimer(void)
|
||||
{
|
||||
do
|
||||
{
|
||||
mScanChannels >>= 1;
|
||||
mScanChannel++;
|
||||
|
||||
if (mScanChannel > kPhyMaxChannel)
|
||||
{
|
||||
mSendQueue.Dequeue(*mSendMessage);
|
||||
Message::Free(*mSendMessage);
|
||||
mMac.SetChannel(mRestoreChannel);
|
||||
mScanning = false;
|
||||
mMle.HandleDiscoverComplete();
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
while ((mScanChannels & 1) == 0);
|
||||
|
||||
mSendMessage->SetDirectTransmission();
|
||||
|
||||
exit:
|
||||
mSendBusy = false;
|
||||
mScheduleTransmissionTask.Post();
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleReceivedFrame(void *aContext, Mac::Frame &aFrame, ThreadError aError)
|
||||
{
|
||||
MeshForwarder *obj = reinterpret_cast<MeshForwarder *>(aContext);
|
||||
@@ -1028,6 +1107,8 @@ void MeshForwarder::HandleReceivedFrame(Mac::Frame &aFrame, ThreadError aError)
|
||||
}
|
||||
|
||||
SuccessOrExit(aFrame.GetDstAddr(macDest));
|
||||
aFrame.GetSrcPanId(messageInfo.mPanId);
|
||||
messageInfo.mChannel = aFrame.GetChannel();
|
||||
messageInfo.mRss = aFrame.GetPower();
|
||||
messageInfo.mLqi = aFrame.GetLqi();
|
||||
messageInfo.mLinkSecurity = aFrame.GetSecurityEnabled();
|
||||
@@ -1117,6 +1198,7 @@ void MeshForwarder::HandleMesh(uint8_t *aFrame, uint8_t aFrameLength, const Thre
|
||||
SuccessOrExit(error = message->SetLength(aFrameLength));
|
||||
message->Write(0, aFrameLength, aFrame);
|
||||
message->SetLinkSecurityEnabled(aMessageInfo.mLinkSecurity);
|
||||
message->SetPanId(aMessageInfo.mPanId);
|
||||
|
||||
SendMessage(*message);
|
||||
}
|
||||
@@ -1175,6 +1257,7 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength,
|
||||
|
||||
VerifyOrExit((message = Message::New(Message::kTypeIp6, 0)) != NULL, error = kThreadError_NoBufs);
|
||||
message->SetLinkSecurityEnabled(aMessageInfo.mLinkSecurity);
|
||||
message->SetPanId(aMessageInfo.mPanId);
|
||||
headerLength = mLowpan.Decompress(*message, aMacSource, aMacDest, aFrame, aFrameLength, datagramLength);
|
||||
VerifyOrExit(headerLength > 0, error = kThreadError_NoBufs);
|
||||
|
||||
@@ -1279,6 +1362,7 @@ void MeshForwarder::HandleLowpanHC(uint8_t *aFrame, uint8_t aFrameLength,
|
||||
|
||||
VerifyOrExit((message = Message::New(Message::kTypeIp6, 0)) != NULL, ;);
|
||||
message->SetLinkSecurityEnabled(aMessageInfo.mLinkSecurity);
|
||||
message->SetPanId(aMessageInfo.mPanId);
|
||||
|
||||
headerLength = mLowpan.Decompress(*message, aMacSource, aMacDest, aFrame, aFrameLength, 0);
|
||||
VerifyOrExit(headerLength > 0, ;);
|
||||
|
||||
@@ -140,6 +140,15 @@ public:
|
||||
*/
|
||||
void SetPollPeriod(uint32_t aPeriod);
|
||||
|
||||
/**
|
||||
* This method sets the scan parameters for MLE Discovery Request messages.
|
||||
*
|
||||
* @param[in] aScanChannels A bit vector indicating which channels to scan.
|
||||
* @param[in] aScanDuration The time in milliseconds to spend scanning each channel.
|
||||
*
|
||||
*/
|
||||
void SetDiscoverParameters(uint32_t aScanChannels, uint16_t aScanDuration);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
@@ -178,6 +187,8 @@ private:
|
||||
static void HandleSentFrame(void *aContext, Mac::Frame &aFrame);
|
||||
void HandleSentFrame(Mac::Frame &aFrame);
|
||||
|
||||
static void HandleDiscoverTimer(void *aContext);
|
||||
void HandleDiscoverTimer(void);
|
||||
static void HandleReassemblyTimer(void *aContext);
|
||||
void HandleReassemblyTimer(void);
|
||||
static void HandlePollTimer(void *aContext);
|
||||
@@ -188,6 +199,7 @@ private:
|
||||
|
||||
Mac::Receiver mMacReceiver;
|
||||
Mac::Sender mMacSender;
|
||||
Timer mDiscoverTimer;
|
||||
Timer mPollTimer;
|
||||
Timer mReassemblyTimer;
|
||||
|
||||
@@ -210,6 +222,12 @@ private:
|
||||
Tasklet mScheduleTransmissionTask;
|
||||
bool mEnabled;
|
||||
|
||||
uint32_t mScanChannels;
|
||||
uint16_t mScanDuration;
|
||||
uint8_t mScanChannel;
|
||||
uint8_t mRestoreChannel;
|
||||
bool mScanning;
|
||||
|
||||
ThreadNetif &mNetif;
|
||||
AddressResolver &mAddressResolver;
|
||||
Lowpan::Lowpan &mLowpan;
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* 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 generating and processing MeshCoP TLVs.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MESHCOP_TLVS_HPP_
|
||||
#define MESHCOP_TLVS_HPP_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <common/encoding.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
namespace Thread {
|
||||
namespace MeshCoP {
|
||||
|
||||
/**
|
||||
* This class implements MeshCoP TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* MeshCoP TLV Types.
|
||||
*
|
||||
*/
|
||||
enum Type
|
||||
{
|
||||
kExtendedPanId = 2, ///< Extended PAN ID TLV
|
||||
kNetworkName = 3, ///< Newtork Name TLV
|
||||
kDiscoveryRequest = 128, ///< Discovery Request TLV
|
||||
kDiscoveryResponse = 129, ///< Discovery Response TLV
|
||||
};
|
||||
|
||||
/**
|
||||
* This method returns the Type value.
|
||||
*
|
||||
* @returns The Type value.
|
||||
*
|
||||
*/
|
||||
Type GetType(void) const { return static_cast<Type>(mType); }
|
||||
|
||||
/**
|
||||
* This method sets the Type value.
|
||||
*
|
||||
* @param[in] aType The Type value.
|
||||
*
|
||||
*/
|
||||
void SetType(Type aType) { mType = static_cast<uint8_t>(aType); }
|
||||
|
||||
/**
|
||||
* This method returns the Length value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLength(void) const { return mLength; }
|
||||
|
||||
/**
|
||||
* This method sets the Length value.
|
||||
*
|
||||
* @param[in] aLength The Length value.
|
||||
*
|
||||
*/
|
||||
void SetLength(uint8_t aLength) { mLength = aLength; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Value.
|
||||
*
|
||||
* @returns A pointer to the value.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetValue() { return reinterpret_cast<uint8_t *>(this) + sizeof(Tlv); }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the next TLV.
|
||||
*
|
||||
* @returns A pointer to the next TLV.
|
||||
*
|
||||
*/
|
||||
Tlv *GetNext() {
|
||||
return reinterpret_cast<Tlv *>(reinterpret_cast<uint8_t *>(this) + sizeof(*this) + mLength);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t mType;
|
||||
uint8_t mLength;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Extended PAN ID TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ExtendedPanIdTlv: public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void) { SetType(kExtendedPanId); SetLength(sizeof(*this) - sizeof(Tlv)); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() == sizeof(*this) - sizeof(Tlv); }
|
||||
|
||||
/**
|
||||
* This method returns the Extended PAN ID value.
|
||||
*
|
||||
* @returns The Extended PAN ID value.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetExtendedPanId(void) const { return mExtendedPanId; }
|
||||
|
||||
/**
|
||||
* This method sets the Extended PAN ID value.
|
||||
*
|
||||
* @param[in] aExtendedPanId A pointer to the Extended PAN ID value.
|
||||
*
|
||||
*/
|
||||
void SetExtendedPanId(const uint8_t *aExtendedPanId) {
|
||||
memcpy(mExtendedPanId, aExtendedPanId, OT_EXT_PAN_ID_SIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t mExtendedPanId[OT_EXT_PAN_ID_SIZE];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Network Name TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class NetworkNameTlv: public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void) { SetType(kNetworkName); SetLength(sizeof(*this) - sizeof(Tlv)); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() <= sizeof(*this) - sizeof(Tlv); }
|
||||
|
||||
/**
|
||||
* This method returns the Network Name value.
|
||||
*
|
||||
* @returns The Network Name value.
|
||||
*
|
||||
*/
|
||||
const char *GetNetworkName(void) const { return mNetworkName; }
|
||||
|
||||
/**
|
||||
* This method sets the Network Name value.
|
||||
*
|
||||
* @param[in] aNetworkName A pointer to the Network Name value.
|
||||
*
|
||||
*/
|
||||
void SetNetworkName(const char *aNetworkName) {
|
||||
int length = strnlen(aNetworkName, sizeof(mNetworkName));
|
||||
memcpy(mNetworkName, aNetworkName, length);
|
||||
SetLength(length);
|
||||
}
|
||||
|
||||
private:
|
||||
char mNetworkName[OT_NETWORK_NAME_SIZE];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Discovery Request TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class DiscoveryRequestTlv: public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void) { SetType(kDiscoveryRequest); SetLength(sizeof(*this) - sizeof(Tlv)); mReserved = 0; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() == sizeof(*this) - sizeof(Tlv); }
|
||||
|
||||
/**
|
||||
* This method returns the Version value.
|
||||
*
|
||||
* @returns The Version value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetVersion(void) const { return mFlags >> kVersionOffset; }
|
||||
|
||||
/**
|
||||
* This method sets the Version value.
|
||||
*
|
||||
* @param[in] aVersion The Version value.
|
||||
*
|
||||
*/
|
||||
void SetVersion(uint8_t aVersion) { mFlags = (mFlags & ~kVersionMask) | (aVersion << kVersionOffset); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Joiner flag is set.
|
||||
*
|
||||
* @retval TRUE If the Joiner flag is set.
|
||||
* @retval FALSE If the Joiner flag is not set.
|
||||
*
|
||||
*/
|
||||
bool IsJoiner(void) { return mFlags & kJoinerMask; }
|
||||
|
||||
/**
|
||||
* This method sets the Joiner flag.
|
||||
*
|
||||
* @param[in] aJoiner TRUE if set, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void SetJoiner(bool aJoiner) {
|
||||
if (aJoiner) {
|
||||
mFlags |= kJoinerMask;
|
||||
}
|
||||
else {
|
||||
mFlags &= ~kJoinerMask;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kVersionOffset = 4,
|
||||
kVersionMask = 0xf << kVersionOffset,
|
||||
kJoinerOffset = 3,
|
||||
kJoinerMask = 1 << kJoinerOffset,
|
||||
};
|
||||
uint8_t mFlags;
|
||||
uint8_t mReserved;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Discovery Response TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class DiscoveryResponseTlv: public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void) { SetType(kDiscoveryResponse); SetLength(sizeof(*this) - sizeof(Tlv)); mReserved = 0; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() == sizeof(*this) - sizeof(Tlv); }
|
||||
|
||||
/**
|
||||
* This method returns the Version value.
|
||||
*
|
||||
* @returns The Version value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetVersion(void) const { return mFlags >> kVersionOffset; }
|
||||
|
||||
/**
|
||||
* This method sets the Version value.
|
||||
*
|
||||
* @param[in] aVersion The Version value.
|
||||
*
|
||||
*/
|
||||
void SetVersion(uint8_t aVersion) { mFlags = (mFlags & ~kVersionMask) | (aVersion << kVersionOffset); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the Native Commissioner flag is set.
|
||||
*
|
||||
* @retval TRUE If the Native Commissioner flag is set.
|
||||
* @retval FALSE If the Native Commissioner flag is not set.
|
||||
*
|
||||
*/
|
||||
bool IsNativeCommissioner(void) { return mFlags & kNativeMask; }
|
||||
|
||||
/**
|
||||
* This method sets the Native Commissioner flag.
|
||||
*
|
||||
* @param[in] aNativeCommissioner TRUE if set, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void SetNativeCommissioner(bool aNativeCommissioner) {
|
||||
if (aNativeCommissioner) {
|
||||
mFlags |= kNativeMask;
|
||||
}
|
||||
else {
|
||||
mFlags &= ~kNativeMask;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kVersionOffset = 4,
|
||||
kVersionMask = 0xf << kVersionOffset,
|
||||
kNativeOffset = 3,
|
||||
kNativeMask = 1 << kNativeOffset,
|
||||
};
|
||||
uint8_t mFlags;
|
||||
uint8_t mReserved;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
} // namespace MeshCoP
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // MESHCOP_TLVS_HPP_
|
||||
+359
-43
@@ -43,6 +43,7 @@
|
||||
#include <platform/radio.h>
|
||||
#include <platform/random.h>
|
||||
#include <thread/address_resolver.hpp>
|
||||
#include <thread/meshcop_tlvs.hpp>
|
||||
#include <thread/key_manager.hpp>
|
||||
#include <thread/mle_router.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
@@ -144,20 +145,39 @@ Mle::Mle(ThreadNetif &aThreadNetif) :
|
||||
mNetif.RegisterCallback(mNetifCallback);
|
||||
}
|
||||
|
||||
ThreadError Mle::Start(void)
|
||||
ThreadError Mle::Enable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Ip6::SockAddr sockaddr;
|
||||
|
||||
// cannot bring up the interface if IEEE 802.15.4 promiscuous mode is enabled
|
||||
VerifyOrExit(otPlatRadioGetPromiscuous() == false, error = kThreadError_Busy);
|
||||
VerifyOrExit(mNetif.IsUp(), error = kThreadError_InvalidState);
|
||||
|
||||
// memcpy(&sockaddr.mAddr, &mLinkLocal64.GetAddress(), sizeof(sockaddr.mAddr));
|
||||
sockaddr.mPort = kUdpPort;
|
||||
SuccessOrExit(error = mSocket.Open(&HandleUdpReceive, this));
|
||||
SuccessOrExit(error = mSocket.Bind(sockaddr));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::Disable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
SuccessOrExit(error = Stop());
|
||||
SuccessOrExit(error = mSocket.Close());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::Start(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
// cannot bring up the interface if IEEE 802.15.4 promiscuous mode is enabled
|
||||
VerifyOrExit(otPlatRadioGetPromiscuous() == false, error = kThreadError_Busy);
|
||||
VerifyOrExit(mNetif.IsUp(), error = kThreadError_InvalidState);
|
||||
|
||||
mDeviceState = kDeviceStateDetached;
|
||||
SetStateDetached();
|
||||
|
||||
@@ -183,13 +203,68 @@ exit:
|
||||
ThreadError Mle::Stop(void)
|
||||
{
|
||||
SetStateDetached();
|
||||
mSocket.Close();
|
||||
mNetif.RemoveUnicastAddress(mLinkLocal16);
|
||||
mNetif.RemoveUnicastAddress(mMeshLocal16);
|
||||
mDeviceState = kDeviceStateDisabled;
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Mle::Discover(uint32_t aScanChannels, uint16_t aScanDuration, uint16_t aPanId,
|
||||
DiscoverHandler aCallback, void *aContext)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Message *message;
|
||||
Ip6::Address destination;
|
||||
Tlv tlv;
|
||||
MeshCoP::DiscoveryRequestTlv discoveryRequest;
|
||||
uint16_t startOffset;
|
||||
|
||||
mDiscoverHandler = aCallback;
|
||||
mDiscoverContext = aContext;
|
||||
mMesh.SetDiscoverParameters(aScanChannels, aScanDuration);
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, ;);
|
||||
message->SetLinkSecurityEnabled(false);
|
||||
message->SetMleDiscoverRequest(true);
|
||||
message->SetPanId(aPanId);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandDiscoveryRequest));
|
||||
|
||||
// Discovery TLV
|
||||
tlv.SetType(Tlv::kDiscovery);
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
|
||||
startOffset = message->GetLength();
|
||||
|
||||
// Discovery Request TLV
|
||||
discoveryRequest.Init();
|
||||
discoveryRequest.SetVersion(kVersion);
|
||||
SuccessOrExit(error = message->Append(&discoveryRequest, sizeof(discoveryRequest)));
|
||||
|
||||
tlv.SetLength(message->GetLength() - startOffset);
|
||||
message->Write(startOffset - sizeof(tlv), sizeof(tlv), &tlv);
|
||||
|
||||
memset(&destination, 0, sizeof(destination));
|
||||
destination.mFields.m16[0] = HostSwap16(0xff02);
|
||||
destination.mFields.m16[7] = HostSwap16(0x0002);
|
||||
SuccessOrExit(error = SendMessage(*message, destination));
|
||||
|
||||
otLogInfoMle("Sent discovery request\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void Mle::HandleDiscoverComplete(void)
|
||||
{
|
||||
mDiscoverHandler(NULL, mDiscoverContext);
|
||||
}
|
||||
|
||||
ThreadError Mle::BecomeDetached(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -514,17 +589,24 @@ ThreadError Mle::AppendHeader(Message &aMessage, Header::Command aCommand)
|
||||
|
||||
header.Init();
|
||||
|
||||
if (aCommand == Header::kCommandAdvertisement ||
|
||||
aCommand == Header::kCommandChildIdRequest ||
|
||||
aCommand == Header::kCommandLinkReject ||
|
||||
aCommand == Header::kCommandParentRequest ||
|
||||
aCommand == Header::kCommandParentResponse)
|
||||
switch (aCommand)
|
||||
{
|
||||
case Header::kCommandDiscoveryRequest:
|
||||
case Header::kCommandDiscoveryResponse:
|
||||
header.SetSecuritySuite(255);
|
||||
break;
|
||||
|
||||
case Header::kCommandAdvertisement:
|
||||
case Header::kCommandChildIdRequest:
|
||||
case Header::kCommandLinkReject:
|
||||
case Header::kCommandParentRequest:
|
||||
case Header::kCommandParentResponse:
|
||||
header.SetKeyIdMode2();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
default:
|
||||
header.SetKeyIdMode1();
|
||||
break;
|
||||
}
|
||||
|
||||
header.SetCommand(aCommand);
|
||||
@@ -1149,36 +1231,42 @@ ThreadError Mle::SendMessage(Message &aMessage, const Ip6::Address &aDestination
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
aMessage.Read(0, sizeof(header), &header);
|
||||
header.SetFrameCounter(mKeyManager.GetMleFrameCounter());
|
||||
|
||||
keySequence = mKeyManager.GetCurrentKeySequence();
|
||||
header.SetKeyId(keySequence);
|
||||
|
||||
aMessage.Write(0, header.GetLength(), &header);
|
||||
|
||||
GenerateNonce(*mMac.GetExtAddress(), mKeyManager.GetMleFrameCounter(), Mac::Frame::kSecEncMic32, nonce);
|
||||
|
||||
aesCcm.SetKey(mKeyManager.GetCurrentMleKey(), 16);
|
||||
aesCcm.Init(16 + 16 + header.GetHeaderLength(), aMessage.GetLength() - (header.GetLength() - 1),
|
||||
sizeof(tag), nonce, sizeof(nonce));
|
||||
|
||||
aesCcm.Header(&mLinkLocal64.GetAddress(), sizeof(mLinkLocal64.GetAddress()));
|
||||
aesCcm.Header(&aDestination, sizeof(aDestination));
|
||||
aesCcm.Header(header.GetBytes() + 1, header.GetHeaderLength());
|
||||
|
||||
aMessage.SetOffset(header.GetLength() - 1);
|
||||
|
||||
while (aMessage.GetOffset() < aMessage.GetLength())
|
||||
if (header.GetSecuritySuite() == 0)
|
||||
{
|
||||
length = aMessage.Read(aMessage.GetOffset(), sizeof(buf), buf);
|
||||
aesCcm.Payload(buf, buf, length, true);
|
||||
aMessage.Write(aMessage.GetOffset(), length, buf);
|
||||
aMessage.MoveOffset(length);
|
||||
}
|
||||
header.SetFrameCounter(mKeyManager.GetMleFrameCounter());
|
||||
|
||||
tagLength = sizeof(tag);
|
||||
aesCcm.Finalize(tag, &tagLength);
|
||||
SuccessOrExit(aMessage.Append(tag, tagLength));
|
||||
keySequence = mKeyManager.GetCurrentKeySequence();
|
||||
header.SetKeyId(keySequence);
|
||||
|
||||
aMessage.Write(0, header.GetLength(), &header);
|
||||
|
||||
GenerateNonce(*mMac.GetExtAddress(), mKeyManager.GetMleFrameCounter(), Mac::Frame::kSecEncMic32, nonce);
|
||||
|
||||
aesCcm.SetKey(mKeyManager.GetCurrentMleKey(), 16);
|
||||
aesCcm.Init(16 + 16 + header.GetHeaderLength(), aMessage.GetLength() - (header.GetLength() - 1),
|
||||
sizeof(tag), nonce, sizeof(nonce));
|
||||
|
||||
aesCcm.Header(&mLinkLocal64.GetAddress(), sizeof(mLinkLocal64.GetAddress()));
|
||||
aesCcm.Header(&aDestination, sizeof(aDestination));
|
||||
aesCcm.Header(header.GetBytes() + 1, header.GetHeaderLength());
|
||||
|
||||
aMessage.SetOffset(header.GetLength() - 1);
|
||||
|
||||
while (aMessage.GetOffset() < aMessage.GetLength())
|
||||
{
|
||||
length = aMessage.Read(aMessage.GetOffset(), sizeof(buf), buf);
|
||||
aesCcm.Payload(buf, buf, length, true);
|
||||
aMessage.Write(aMessage.GetOffset(), length, buf);
|
||||
aMessage.MoveOffset(length);
|
||||
}
|
||||
|
||||
tagLength = sizeof(tag);
|
||||
aesCcm.Finalize(tag, &tagLength);
|
||||
SuccessOrExit(aMessage.Append(tag, tagLength));
|
||||
|
||||
mKeyManager.IncrementMleFrameCounter();
|
||||
}
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
memcpy(&messageInfo.GetPeerAddr(), &aDestination, sizeof(messageInfo.GetPeerAddr()));
|
||||
@@ -1187,8 +1275,6 @@ ThreadError Mle::SendMessage(Message &aMessage, const Ip6::Address &aDestination
|
||||
messageInfo.mInterfaceId = mNetif.GetInterfaceId();
|
||||
messageInfo.mHopLimit = 255;
|
||||
|
||||
mKeyManager.IncrementMleFrameCounter();
|
||||
|
||||
SuccessOrExit(error = mSocket.SendTo(aMessage, messageInfo));
|
||||
|
||||
exit:
|
||||
@@ -1224,6 +1310,29 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
aMessage.Read(aMessage.GetOffset(), sizeof(header), &header);
|
||||
VerifyOrExit(header.IsValid(),);
|
||||
|
||||
if (header.GetSecuritySuite() == 255)
|
||||
{
|
||||
aMessage.MoveOffset(header.GetLength());
|
||||
|
||||
switch (header.GetCommand())
|
||||
{
|
||||
case Header::kCommandDiscoveryRequest:
|
||||
HandleDiscoveryRequest(aMessage, aMessageInfo);
|
||||
break;
|
||||
|
||||
case Header::kCommandDiscoveryResponse:
|
||||
HandleDiscoveryResponse(aMessage, aMessageInfo);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(mDeviceState != kDeviceStateDisabled && header.GetSecuritySuite() == 0, ;);
|
||||
|
||||
if (header.IsKeyIdMode1())
|
||||
{
|
||||
keyid = header.GetKeyId();
|
||||
@@ -1879,6 +1988,213 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Tlv tlv;
|
||||
MeshCoP::Tlv meshcopTlv;
|
||||
MeshCoP::DiscoveryRequestTlv discoveryRequest;
|
||||
MeshCoP::ExtendedPanIdTlv extPanId;
|
||||
uint16_t offset;
|
||||
uint16_t end;
|
||||
|
||||
otLogInfoMle("Received discovery request\n");
|
||||
|
||||
// only Routers and REEDs respond
|
||||
VerifyOrExit((mDeviceMode & ModeTlv::kModeFFD) != 0, ;);
|
||||
|
||||
offset = aMessage.GetOffset();
|
||||
end = aMessage.GetLength();
|
||||
|
||||
// find MLE Discovery TLV
|
||||
while (offset < end)
|
||||
{
|
||||
aMessage.Read(offset, sizeof(tlv), &tlv);
|
||||
|
||||
if (tlv.GetType() == Tlv::kDiscovery)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(tlv) + tlv.GetLength();
|
||||
}
|
||||
|
||||
VerifyOrExit(offset < end, error = kThreadError_Parse);
|
||||
|
||||
offset += sizeof(tlv);
|
||||
end = offset + sizeof(tlv) + tlv.GetLength();
|
||||
|
||||
while (offset < end)
|
||||
{
|
||||
aMessage.Read(offset, sizeof(meshcopTlv), &meshcopTlv);
|
||||
|
||||
switch (meshcopTlv.GetType())
|
||||
{
|
||||
case MeshCoP::Tlv::kDiscoveryRequest:
|
||||
aMessage.Read(offset, sizeof(discoveryRequest), &discoveryRequest);
|
||||
VerifyOrExit(discoveryRequest.IsValid(), error = kThreadError_Parse);
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kExtendedPanId:
|
||||
aMessage.Read(offset, sizeof(extPanId), &extPanId);
|
||||
VerifyOrExit(extPanId.IsValid(), error = kThreadError_Parse);
|
||||
VerifyOrExit(memcmp(mMac.GetExtendedPanId(), extPanId.GetExtendedPanId(), OT_EXT_PAN_ID_SIZE),
|
||||
error = kThreadError_Drop);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
|
||||
}
|
||||
|
||||
error = SendDiscoveryResponse(aMessageInfo.GetPeerAddr(), aMessage.GetPanId());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::SendDiscoveryResponse(const Ip6::Address &aDestination, uint16_t aPanId)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Message *message;
|
||||
uint16_t startOffset;
|
||||
Tlv tlv;
|
||||
MeshCoP::DiscoveryResponseTlv discoveryResponse;
|
||||
MeshCoP::ExtendedPanIdTlv extPanId;
|
||||
MeshCoP::NetworkNameTlv networkName;
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, ;);
|
||||
message->SetLinkSecurityEnabled(false);
|
||||
message->SetMleDiscoverResponse(true);
|
||||
message->SetPanId(aPanId);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandDiscoveryResponse));
|
||||
|
||||
// Discovery TLV
|
||||
tlv.SetType(Tlv::kDiscovery);
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
|
||||
startOffset = message->GetLength();
|
||||
|
||||
// Discovery Response TLV
|
||||
discoveryResponse.Init();
|
||||
discoveryResponse.SetVersion(kVersion);
|
||||
SuccessOrExit(error = message->Append(&discoveryResponse, sizeof(discoveryResponse)));
|
||||
|
||||
// Extended PAN ID TLV
|
||||
extPanId.Init();
|
||||
extPanId.SetExtendedPanId(mMac.GetExtendedPanId());
|
||||
SuccessOrExit(error = message->Append(&extPanId, sizeof(extPanId)));
|
||||
|
||||
// Network Name TLV
|
||||
networkName.Init();
|
||||
networkName.SetNetworkName(mMac.GetNetworkName());
|
||||
SuccessOrExit(error = message->Append(&networkName, sizeof(tlv) + networkName.GetLength()));
|
||||
|
||||
tlv.SetLength(message->GetLength() - startOffset);
|
||||
message->Write(startOffset - sizeof(tlv), sizeof(tlv), &tlv);
|
||||
|
||||
SuccessOrExit(error = SendMessage(*message, aDestination));
|
||||
|
||||
otLogInfoMle("Sent discovery response\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
const ThreadMessageInfo *threadMessageInfo = reinterpret_cast<const ThreadMessageInfo *>(aMessageInfo.mLinkInfo);
|
||||
Tlv tlv;
|
||||
MeshCoP::Tlv meshcopTlv;
|
||||
MeshCoP::DiscoveryResponseTlv discoveryResponse;
|
||||
MeshCoP::ExtendedPanIdTlv extPanId;
|
||||
MeshCoP::NetworkNameTlv networkName;
|
||||
otActiveScanResult result;
|
||||
uint16_t offset;
|
||||
uint16_t end;
|
||||
char networkNameBuf[OT_NETWORK_NAME_SIZE];
|
||||
|
||||
otLogInfoMle("Handle discovery response\n");
|
||||
|
||||
offset = aMessage.GetOffset();
|
||||
end = aMessage.GetLength();
|
||||
|
||||
// find MLE Discovery TLV
|
||||
while (offset < end)
|
||||
{
|
||||
aMessage.Read(offset, sizeof(tlv), &tlv);
|
||||
|
||||
if (tlv.GetType() == Tlv::kDiscovery)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(tlv) + tlv.GetLength();
|
||||
}
|
||||
|
||||
VerifyOrExit(offset < end, error = kThreadError_Parse);
|
||||
|
||||
offset += sizeof(tlv);
|
||||
end = offset + sizeof(tlv) + tlv.GetLength();
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
result.mPanId = threadMessageInfo->mPanId;
|
||||
result.mChannel = threadMessageInfo->mChannel;
|
||||
result.mRssi = threadMessageInfo->mRss;
|
||||
result.mLqi = threadMessageInfo->mLqi;
|
||||
static_cast<Mac::ExtAddress *>(&result.mExtAddress)->Set(aMessageInfo.GetPeerAddr());
|
||||
|
||||
// process MeshCoP TLVs
|
||||
while (offset < end)
|
||||
{
|
||||
aMessage.Read(offset, sizeof(meshcopTlv), &meshcopTlv);
|
||||
|
||||
switch (meshcopTlv.GetType())
|
||||
{
|
||||
case MeshCoP::Tlv::kDiscoveryResponse:
|
||||
aMessage.Read(offset, sizeof(discoveryResponse), &discoveryResponse);
|
||||
VerifyOrExit(discoveryResponse.IsValid(), error = kThreadError_Parse);
|
||||
result.mVersion = discoveryResponse.GetVersion();
|
||||
result.mIsNative = discoveryResponse.IsNativeCommissioner();
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kExtendedPanId:
|
||||
aMessage.Read(offset, sizeof(extPanId), &extPanId);
|
||||
VerifyOrExit(extPanId.IsValid(), error = kThreadError_Parse);
|
||||
result.mExtPanId = extPanId.GetExtendedPanId();
|
||||
break;
|
||||
|
||||
case MeshCoP::Tlv::kNetworkName:
|
||||
aMessage.Read(offset, sizeof(networkName), &networkName);
|
||||
VerifyOrExit(networkName.IsValid(), error = kThreadError_Parse);
|
||||
memcpy(networkNameBuf, networkName.GetNetworkName(), networkName.GetLength());
|
||||
memset(networkNameBuf + networkName.GetLength(), 0, sizeof(networkNameBuf) - networkName.GetLength());
|
||||
result.mNetworkName = networkNameBuf;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
|
||||
}
|
||||
|
||||
// signal callback
|
||||
mDiscoverHandler(&result, mDiscoverContext);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Neighbor *Mle::GetNeighbor(uint16_t aAddress)
|
||||
{
|
||||
return (mParent.mState == Neighbor::kStateValid && mParent.mValid.mRloc16 == aAddress) ? &mParent : NULL;
|
||||
|
||||
+109
-9
@@ -124,9 +124,10 @@ public:
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const {
|
||||
return mSecuritySuite == 0 &&
|
||||
(mSecurityControl == (Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32) ||
|
||||
mSecurityControl == (Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecEncMic32));
|
||||
return (mSecuritySuite == 255) ||
|
||||
(mSecuritySuite == 0 &&
|
||||
(mSecurityControl == (Mac::Frame::kKeyIdMode1 | Mac::Frame::kSecEncMic32) ||
|
||||
mSecurityControl == (Mac::Frame::kKeyIdMode2 | Mac::Frame::kSecEncMic32)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,10 +137,31 @@ public:
|
||||
*
|
||||
*/
|
||||
uint8_t GetLength(void) const {
|
||||
return sizeof(mSecuritySuite) + sizeof(mSecurityControl) + sizeof(mFrameCounter) +
|
||||
(IsKeyIdMode1() ? 1 : 5) + sizeof(mCommand);
|
||||
uint8_t rval = sizeof(mSecuritySuite) + sizeof(mCommand);
|
||||
|
||||
if (mSecuritySuite == 0) {
|
||||
rval += sizeof(mSecurityControl) + sizeof(mFrameCounter) + (IsKeyIdMode1() ? 1 : 5);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Security Suite value.
|
||||
*
|
||||
* @returns The Security Suite value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetSecuritySuite(void) const { return mSecuritySuite; }
|
||||
|
||||
/**
|
||||
* This method sets the Security Suite value.
|
||||
*
|
||||
* @param[in] aSecuritySuite The Security Suite value.
|
||||
*
|
||||
*/
|
||||
void SetSecuritySuite(uint8_t aSecuritySuite) { mSecuritySuite = aSecuritySuite; }
|
||||
|
||||
/**
|
||||
* This method returns the MLE header length (excluding the Command Type).
|
||||
*
|
||||
@@ -269,6 +291,8 @@ public:
|
||||
kCommandChildIdResponse = 12, ///< Child ID Response
|
||||
kCommandChildUpdateRequest = 13, ///< Child Update Request
|
||||
kCommandChildUpdateResponse = 14, ///< Child Update Response
|
||||
kCommandDiscoveryRequest = 16, ///< Discovery Request
|
||||
kCommandDiscoveryResponse = 17, ///< Discovery Response
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -278,8 +302,13 @@ public:
|
||||
*
|
||||
*/
|
||||
Command GetCommand(void) const {
|
||||
const uint8_t *command = IsKeyIdMode1() ? mKeyIdentifier + 1 : &mCommand;
|
||||
return static_cast<Command>(*command);
|
||||
if (mSecuritySuite == 255) {
|
||||
return static_cast<Command>(mSecurityControl);
|
||||
}
|
||||
else {
|
||||
const uint8_t *command = IsKeyIdMode1() ? mKeyIdentifier + 1 : &mCommand;
|
||||
return static_cast<Command>(*command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,8 +318,13 @@ public:
|
||||
*
|
||||
*/
|
||||
void SetCommand(Command aCommand) {
|
||||
uint8_t *commandField = IsKeyIdMode1() ? mKeyIdentifier + 1 : &mCommand;
|
||||
*commandField = static_cast<uint8_t>(aCommand);
|
||||
if (mSecuritySuite == 255) {
|
||||
mSecurityControl = static_cast<uint8_t>(aCommand);
|
||||
}
|
||||
else {
|
||||
uint8_t *commandField = IsKeyIdMode1() ? mKeyIdentifier + 1 : &mCommand;
|
||||
*commandField = static_cast<uint8_t>(aCommand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,6 +359,24 @@ public:
|
||||
*/
|
||||
explicit Mle(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method enables MLE.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enabled MLE.
|
||||
* @retval kThreadError_Busy MLE was already enabled.
|
||||
*
|
||||
*/
|
||||
ThreadError Enable(void);
|
||||
|
||||
/**
|
||||
* This method disables MLE.
|
||||
*
|
||||
* @retval kThreadError_None Successfully disabled MLE.
|
||||
* @retval kThreadError_Busy MLE was already disabled.
|
||||
*
|
||||
*/
|
||||
ThreadError Disable(void);
|
||||
|
||||
/**
|
||||
* This method starts the MLE protocol operation.
|
||||
*
|
||||
@@ -343,6 +395,37 @@ public:
|
||||
*/
|
||||
ThreadError Stop(void);
|
||||
|
||||
/**
|
||||
* This function pointer is called on receiving an MLE Discovery Response message.
|
||||
*
|
||||
* @param[in] aResult A valid pointer to the Discovery Response information or NULL when the Discovery completes.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
typedef void (*DiscoverHandler)(otActiveScanResult *aResult, void *aContext);
|
||||
|
||||
/**
|
||||
* This method initiates a Thread Discovery.
|
||||
*
|
||||
* @param[in] aScanChannels A bit vector indicating which channels to scan.
|
||||
* @param[in] aScanDuration The time in milliseconds to spend scanning each channel.
|
||||
* @param[in] aPanId The PAN ID filter (set to Broadcast PAN to disable filter).
|
||||
* @param[in] aHandler A pointer to a function that is called on receiving an MLE Discovery Response.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
* @retval kThreadError_None Successfully started a Thread Discovery.
|
||||
* @retval kThreadError_Busy Thread Discovery is already in progress.
|
||||
*
|
||||
*/
|
||||
ThreadError Discover(uint32_t aScanChannels, uint16_t aScanDuration, uint16_t aPanId,
|
||||
DiscoverHandler aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* This method is called by the MeshForwarder to indicate that discovery is complete.
|
||||
*
|
||||
*/
|
||||
void HandleDiscoverComplete(void);
|
||||
|
||||
/**
|
||||
* This method causes the Thread interface to detach from the Thread network.
|
||||
*
|
||||
@@ -774,6 +857,17 @@ protected:
|
||||
*/
|
||||
ThreadError AppendAddressRegistration(Message &aMessage);
|
||||
|
||||
/**
|
||||
* This method appends a Thread Discovery TLV to a message.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
* @retval kThreadError_None Successfully appended the Thread Discovery TLV.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers available to append the Address Registration TLV.
|
||||
*
|
||||
*/
|
||||
ThreadError AppendDiscovery(Message &aMessage);
|
||||
|
||||
/**
|
||||
* This method checks if the destination is reachable.
|
||||
*
|
||||
@@ -975,9 +1069,12 @@ private:
|
||||
ThreadError HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
uint32_t aKeySequence);
|
||||
ThreadError HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
ThreadError SendParentRequest(void);
|
||||
ThreadError SendChildIdRequest(void);
|
||||
ThreadError SendDiscoveryResponse(const Ip6::Address &aDestination, uint16_t aPanId);
|
||||
|
||||
bool IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, ConnectivityTlv &aConnectivityTlv) const;
|
||||
|
||||
@@ -1004,6 +1101,9 @@ private:
|
||||
Ip6::UdpSocket mSocket;
|
||||
uint32_t mTimeout;
|
||||
|
||||
DiscoverHandler mDiscoverHandler;
|
||||
void *mDiscoverContext;
|
||||
|
||||
Ip6::NetifUnicastAddress mLinkLocal16;
|
||||
Ip6::NetifUnicastAddress mLinkLocal64;
|
||||
Ip6::NetifUnicastAddress mMeshLocal64;
|
||||
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
kStatus = 17, ///< Status TLV
|
||||
kVersion = 18, ///< Version TLV
|
||||
kAddressRegistration = 19, ///< Address Registration TLV
|
||||
kDiscovery = 26, ///< Thread Discovery TLV
|
||||
kInvalid = 255,
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ ThreadError ThreadNetif::Up(void)
|
||||
Netif::AddNetif();
|
||||
mMeshForwarder.Start();
|
||||
mCoapServer.Start();
|
||||
mMleRouter.Enable();
|
||||
mIsUp = true;
|
||||
|
||||
exit:
|
||||
@@ -90,7 +91,7 @@ exit:
|
||||
ThreadError ThreadNetif::Down(void)
|
||||
{
|
||||
mCoapServer.Stop();
|
||||
mMleRouter.Stop();
|
||||
mMleRouter.Disable();
|
||||
mMeshForwarder.Stop();
|
||||
Netif::RemoveNetif();
|
||||
mIsUp = false;
|
||||
|
||||
@@ -225,9 +225,11 @@ private:
|
||||
*/
|
||||
struct ThreadMessageInfo
|
||||
{
|
||||
int8_t mRss; ///< The Received Signal Strength in dBm.
|
||||
uint8_t mLqi; ///< The Link Quality Indicator for a received message.
|
||||
bool mLinkSecurity; ///< Indicates whether or not link security is enabled.
|
||||
uint16_t mPanId; ///< Source PAN ID
|
||||
uint8_t mChannel; ///< 802.15.4 Channel
|
||||
int8_t mRss; ///< Received Signal Strength in dBm.
|
||||
uint8_t mLqi; ///< Link Quality Indicator for a received message.
|
||||
bool mLinkSecurity; ///< Indicates whether or not link security is enabled.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user