mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
MLE Announce. (#736)
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
<ClCompile Include="..\..\src\core\mac\mac_blacklist.cpp" />
|
||||
<ClCompile Include="..\..\src\core\mac\mac_frame.cpp" />
|
||||
<ClCompile Include="..\..\src\core\mac\mac_whitelist.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\announce_begin_client.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\commissioner.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dtls.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\energy_scan_client.cpp" />
|
||||
@@ -52,6 +53,7 @@
|
||||
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
|
||||
<ClCompile Include="..\..\src\core\openthread.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\energy_scan_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\key_manager.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\link_quality.cpp" />
|
||||
@@ -94,6 +96,7 @@
|
||||
<ClInclude Include="..\..\src\core\mac\mac_blacklist.hpp" />
|
||||
<ClInclude Include="..\..\src\core\mac\mac_frame.hpp" />
|
||||
<ClInclude Include="..\..\src\core\mac\mac_whitelist.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\announce_begin_client.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\commissioner.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dtls.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\energy_scan_client.hpp" />
|
||||
@@ -113,6 +116,7 @@
|
||||
<ClInclude Include="..\..\src\core\openthread-core-config.h" />
|
||||
<ClInclude Include="..\..\src\core\openthreadcontext.h" />
|
||||
<ClInclude Include="..\..\src\core\thread\address_resolver.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\announce_begin_server.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\energy_scan_server.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\key_manager.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\link_quality.hpp" />
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<ClCompile Include="..\..\src\core\mac\mac_whitelist.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\commissioner.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\dtls.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\announce_begin_client.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\energy_scan_client.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\joiner.cpp" />
|
||||
<ClCompile Include="..\..\src\core\meshcop\joiner_router.cpp" />
|
||||
@@ -52,6 +53,7 @@
|
||||
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
|
||||
<ClCompile Include="..\..\src\core\openthread.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\energy_scan_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\key_manager.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\link_quality.cpp" />
|
||||
@@ -94,6 +96,7 @@
|
||||
<ClInclude Include="..\..\src\core\mac\mac_blacklist.hpp" />
|
||||
<ClInclude Include="..\..\src\core\mac\mac_frame.hpp" />
|
||||
<ClInclude Include="..\..\src\core\mac\mac_whitelist.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\announce_begin_client.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\commissioner.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\dtls.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\energy_scan_client.hpp" />
|
||||
@@ -113,6 +116,7 @@
|
||||
<ClInclude Include="..\..\src\core\openthread-core-config.h" />
|
||||
<ClInclude Include="..\..\src\core\openthreadcontext.h" />
|
||||
<ClInclude Include="..\..\src\core\thread\address_resolver.hpp" />
|
||||
<ClInclude Include="..\..\src\core\meshcop\announce_begin_server.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\energy_scan_server.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\key_manager.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\link_quality.hpp" />
|
||||
|
||||
@@ -104,6 +104,22 @@ ThreadError otCommissionerRemoveJoiner(otInstance *aIntsance, const otExtAddress
|
||||
*/
|
||||
ThreadError otCommissionerSetProvisioningUrl(otInstance *aInstance, const char *aProvisioningUrl);
|
||||
|
||||
/**
|
||||
* This function sends an Announce Begin message.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aChannelMask The channel mask value.
|
||||
* @param[in] aCount The number of energy measurements per channel.
|
||||
* @param[in] aPeriod The time between energy measurements (milliseconds).
|
||||
* @param[in] aAddress A pointer to the IPv6 destination.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the Announce Begin message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers to generate an Announce Begin message.
|
||||
*
|
||||
*/
|
||||
ThreadError otCommissionerAnnounceBegin(otInstance *aInstance, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
|
||||
const otIp6Address *aAddress);
|
||||
|
||||
/**
|
||||
* This function pointer is called when the Commissioner receives an Energy Report.
|
||||
*
|
||||
|
||||
@@ -2029,6 +2029,33 @@ void Interpreter::ProcessCommissioner(int argc, char *argv[])
|
||||
{
|
||||
SuccessOrExit(error = otCommissionerSetProvisioningUrl(mInstance, (argc > 1) ? argv[1] : NULL));
|
||||
}
|
||||
else if (strcmp(argv[0], "announce") == 0)
|
||||
{
|
||||
long mask;
|
||||
long count;
|
||||
long period;
|
||||
otIp6Address address;
|
||||
|
||||
VerifyOrExit(argc > 4, error = kThreadError_Parse);
|
||||
|
||||
// mask
|
||||
SuccessOrExit(error = ParseLong(argv[1], mask));
|
||||
|
||||
// count
|
||||
SuccessOrExit(error = ParseLong(argv[2], count));
|
||||
|
||||
// period
|
||||
SuccessOrExit(error = ParseLong(argv[3], period));
|
||||
|
||||
// destination
|
||||
SuccessOrExit(error = otIp6AddressFromString(argv[4], &address));
|
||||
|
||||
SuccessOrExit(error = otCommissionerAnnounceBegin(mInstance,
|
||||
static_cast<uint32_t>(mask),
|
||||
static_cast<uint8_t>(count),
|
||||
static_cast<uint16_t>(period),
|
||||
&address));
|
||||
}
|
||||
else if (strcmp(argv[0], "energy") == 0)
|
||||
{
|
||||
long mask;
|
||||
|
||||
@@ -64,6 +64,7 @@ libopenthread_a_SOURCES = \
|
||||
net/netif.cpp \
|
||||
net/udp6.cpp \
|
||||
thread/address_resolver.cpp \
|
||||
thread/announce_begin_server.cpp \
|
||||
thread/energy_scan_server.cpp \
|
||||
thread/key_manager.cpp \
|
||||
thread/link_quality.cpp \
|
||||
@@ -88,6 +89,7 @@ libopenthread_a_SOURCES = \
|
||||
|
||||
if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
libopenthread_a_SOURCES += \
|
||||
meshcop/announce_begin_client.cpp \
|
||||
meshcop/commissioner.cpp \
|
||||
meshcop/energy_scan_client.cpp \
|
||||
meshcop/panid_query_client.cpp \
|
||||
@@ -129,6 +131,7 @@ noinst_HEADERS = \
|
||||
mac/mac_frame.hpp \
|
||||
mac/mac_whitelist.hpp \
|
||||
mac/mac_blacklist.hpp \
|
||||
meshcop/announce_begin_client.hpp \
|
||||
meshcop/commissioner.hpp \
|
||||
meshcop/dtls.hpp \
|
||||
meshcop/energy_scan_client.hpp \
|
||||
@@ -148,6 +151,7 @@ noinst_HEADERS = \
|
||||
net/udp6.hpp \
|
||||
net/tcp.hpp \
|
||||
thread/address_resolver.hpp \
|
||||
thread/announce_begin_server.hpp \
|
||||
thread/energy_scan_server.hpp \
|
||||
thread/key_manager.hpp \
|
||||
thread/link_quality.hpp \
|
||||
|
||||
+20
-30
@@ -238,6 +238,16 @@ void Message::SetType(uint8_t aType)
|
||||
mInfo.mType = aType;
|
||||
}
|
||||
|
||||
uint8_t Message::GetSubType(void) const
|
||||
{
|
||||
return mInfo.mSubType;
|
||||
}
|
||||
|
||||
void Message::SetSubType(uint8_t aSubType)
|
||||
{
|
||||
mInfo.mSubType = aSubType;
|
||||
}
|
||||
|
||||
ThreadError Message::Append(const void *aBuf, uint16_t aLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -498,6 +508,16 @@ void Message::SetPanId(uint16_t aPanId)
|
||||
mInfo.mPanId = aPanId;
|
||||
}
|
||||
|
||||
uint8_t Message::GetChannel(void) const
|
||||
{
|
||||
return mInfo.mChannel;
|
||||
}
|
||||
|
||||
void Message::SetChannel(uint8_t aChannel)
|
||||
{
|
||||
mInfo.mChannel = aChannel;
|
||||
}
|
||||
|
||||
uint8_t Message::GetTimeout(void) const
|
||||
{
|
||||
return mInfo.mTimeout;
|
||||
@@ -543,36 +563,6 @@ 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;
|
||||
}
|
||||
|
||||
bool Message::IsJoinerEntrust(void) const
|
||||
{
|
||||
return mInfo.mJoinerEntrust;
|
||||
}
|
||||
|
||||
void Message::SetJoinerEntrust(bool aJoinerEntrust)
|
||||
{
|
||||
mInfo.mJoinerEntrust = aJoinerEntrust;
|
||||
}
|
||||
|
||||
uint16_t Message::UpdateChecksum(uint16_t aChecksum, uint16_t aOffset, uint16_t aLength) const
|
||||
{
|
||||
Buffer *curBuffer;
|
||||
|
||||
+55
-55
@@ -118,16 +118,18 @@ struct MessageInfo
|
||||
uint16_t mDatagramTag; ///< The datagram tag used for 6LoWPAN fragmentation.
|
||||
|
||||
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.
|
||||
int8_t mInterfaceId; ///< The interface ID.
|
||||
union
|
||||
{
|
||||
uint16_t mPanId; ///< Used for MLE Discover Request and Response messages.
|
||||
uint8_t mChannel; ///< Used for MLE Announce.
|
||||
};
|
||||
|
||||
uint8_t mType : 2; ///< Identifies the type of message.
|
||||
uint8_t mSubType : 3; ///< Identifies the message sub type.
|
||||
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.
|
||||
bool mJoinerEntrust : 1; ///< Indicates whether or not this message is a Joiner Entrust.
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -221,6 +223,15 @@ public:
|
||||
kTypeMacDataPoll = 2, ///< A MAC data poll message
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kSubTypeNone = 0, ///< None
|
||||
kSubTypeMleAnnounce = 1, ///< MLE Announce
|
||||
kSubTypeMleDiscoverRequest = 2, ///< MLE Discover Request
|
||||
kSubTypeMleDiscoverResponse = 3, ///< MLE Discover Response
|
||||
kSubTypeJoinerEntrust = 4, ///< Joiner Entrust
|
||||
};
|
||||
|
||||
/**
|
||||
* This method frees this message buffer.
|
||||
*
|
||||
@@ -292,6 +303,22 @@ public:
|
||||
*/
|
||||
uint8_t GetType(void) const;
|
||||
|
||||
/**
|
||||
* This method returns the sub type of the message.
|
||||
*
|
||||
* @returns The sub type of the message.
|
||||
*
|
||||
*/
|
||||
uint8_t GetSubType(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the message sub type.
|
||||
*
|
||||
* @param[in] aSubType The message sub type.
|
||||
*
|
||||
*/
|
||||
void SetSubType(uint8_t aSubType);
|
||||
|
||||
/**
|
||||
* This method prepends bytes to the front of the message.
|
||||
*
|
||||
@@ -412,6 +439,8 @@ public:
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
* @note Only use this when sending MLE Discover Request or Response messages.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
*/
|
||||
@@ -420,11 +449,33 @@ public:
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
* @note Only use this when sending MLE Discover Request or Response messages.
|
||||
*
|
||||
* @param[in] aPanId The IEEE 802.15.4 Destination PAN ID.
|
||||
*
|
||||
*/
|
||||
void SetPanId(uint16_t aPanId);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Channel to use for transmission.
|
||||
*
|
||||
* @note Only use this when sending MLE Announce messages.
|
||||
*
|
||||
* @returns The IEEE 802.15.4 Channel to use for transmission.
|
||||
*
|
||||
*/
|
||||
uint8_t GetChannel(void) const;
|
||||
|
||||
/**
|
||||
* This method sets the IEEE 802.15.4 Channel to use for transmission.
|
||||
*
|
||||
* @note Only use this when sending MLE Announce messages.
|
||||
*
|
||||
* @param[in] aChannel The IEEE 802.15.4 Channel to use for transmission.
|
||||
*
|
||||
*/
|
||||
void SetChannel(uint8_t aChannel);
|
||||
|
||||
/**
|
||||
* This method returns the timeout used for 6LoWPAN reassembly.
|
||||
*
|
||||
@@ -495,57 +546,6 @@ 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 indicates whether or not this message is an Joiner Entrust.
|
||||
*
|
||||
* @retval TRUE If this message is an Joiner Entrust.
|
||||
* @retval FALSE If this message is not an Joiner Entrust.
|
||||
*
|
||||
*/
|
||||
bool IsJoinerEntrust(void) const;
|
||||
|
||||
/**
|
||||
* This method sets whether or not this message is an Joiner Entrust.
|
||||
*
|
||||
* @param[in] aLinkSecurityEnabled TRUE if this message is an Joiner Entrust, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void SetJoinerEntrust(bool aJoinerEntrust);
|
||||
|
||||
/**
|
||||
* This method is used to update a checksum value.
|
||||
*
|
||||
|
||||
+31
-2
@@ -55,6 +55,16 @@
|
||||
namespace Thread {
|
||||
namespace Mac {
|
||||
|
||||
static const uint8_t sMode2Key[] =
|
||||
{
|
||||
0x78, 0x58, 0x16, 0x86, 0xfd, 0xb4, 0x58, 0x0f, 0xb0, 0x92, 0x54, 0x6a, 0xec, 0xbd, 0x15, 0x66
|
||||
};
|
||||
|
||||
static const otExtAddress sMode2ExtAddress =
|
||||
{
|
||||
{ 0x35, 0x06, 0xfe, 0xb8, 0x23, 0xd4, 0x87, 0x12 },
|
||||
};
|
||||
|
||||
static const uint8_t sExtendedPanidInit[] = {0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xfe};
|
||||
static const char sNetworkNameInit[] = "OpenThread";
|
||||
static Mac *sMac;
|
||||
@@ -561,6 +571,7 @@ void Mac::ProcessTransmitSecurity(Frame &aFrame)
|
||||
uint8_t tagLength;
|
||||
Crypto::AesCcm aesCcm;
|
||||
const uint8_t *key = NULL;
|
||||
const ExtAddress *extAddress = NULL;
|
||||
|
||||
if (aFrame.GetSecurityEnabled() == false)
|
||||
{
|
||||
@@ -574,6 +585,7 @@ void Mac::ProcessTransmitSecurity(Frame &aFrame)
|
||||
case Frame::kKeyIdMode0:
|
||||
key = mKeyManager.GetKek();
|
||||
frameCounter = mKeyManager.GetKekFrameCounter();
|
||||
extAddress = &mExtAddress;
|
||||
break;
|
||||
|
||||
case Frame::kKeyIdMode1:
|
||||
@@ -581,6 +593,14 @@ void Mac::ProcessTransmitSecurity(Frame &aFrame)
|
||||
frameCounter = mKeyManager.GetMacFrameCounter();
|
||||
mKeyManager.IncrementMacFrameCounter();
|
||||
aFrame.SetKeyId((mKeyManager.GetCurrentKeySequence() & 0x7f) + 1);
|
||||
extAddress = &mExtAddress;
|
||||
break;
|
||||
|
||||
case Frame::kKeyIdMode2:
|
||||
key = sMode2Key;
|
||||
frameCounter = 0xffffffff;
|
||||
aFrame.SetKeyId(0xff);
|
||||
extAddress = static_cast<const ExtAddress *>(&sMode2ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -591,7 +611,7 @@ void Mac::ProcessTransmitSecurity(Frame &aFrame)
|
||||
aFrame.GetSecurityLevel(securityLevel);
|
||||
aFrame.SetFrameCounter(frameCounter);
|
||||
|
||||
GenerateNonce(mExtAddress, frameCounter, securityLevel, nonce);
|
||||
GenerateNonce(*extAddress, frameCounter, securityLevel, nonce);
|
||||
|
||||
aesCcm.SetKey(key, 16);
|
||||
tagLength = aFrame.GetFooterLength() - Frame::kFcsSize;
|
||||
@@ -915,6 +935,7 @@ ThreadError Mac::ProcessReceiveSecurity(Frame &aFrame, const Address &aSrcAddr,
|
||||
uint8_t keyid;
|
||||
uint32_t keySequence = 0;
|
||||
const uint8_t *macKey;
|
||||
const ExtAddress *extAddress;
|
||||
Crypto::AesCcm aesCcm;
|
||||
|
||||
aFrame.SetSecurityValid(false);
|
||||
@@ -934,6 +955,7 @@ ThreadError Mac::ProcessReceiveSecurity(Frame &aFrame, const Address &aSrcAddr,
|
||||
{
|
||||
case Frame::kKeyIdMode0:
|
||||
VerifyOrExit((macKey = mKeyManager.GetKek()) != NULL, error = kThreadError_Security);
|
||||
extAddress = &aSrcAddr.mExtAddress;
|
||||
break;
|
||||
|
||||
case Frame::kKeyIdMode1:
|
||||
@@ -970,6 +992,13 @@ ThreadError Mac::ProcessReceiveSecurity(Frame &aFrame, const Address &aSrcAddr,
|
||||
(frameCounter >= aNeighbor->mValid.mLinkFrameCounter)),
|
||||
error = kThreadError_Security);
|
||||
|
||||
extAddress = &aSrcAddr.mExtAddress;
|
||||
|
||||
break;
|
||||
|
||||
case Frame::kKeyIdMode2:
|
||||
macKey = sMode2Key;
|
||||
extAddress = static_cast<const ExtAddress *>(&sMode2ExtAddress);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -977,7 +1006,7 @@ ThreadError Mac::ProcessReceiveSecurity(Frame &aFrame, const Address &aSrcAddr,
|
||||
break;
|
||||
}
|
||||
|
||||
GenerateNonce(aSrcAddr.mExtAddress, frameCounter, securityLevel, nonce);
|
||||
GenerateNonce(*extAddress, frameCounter, securityLevel, nonce);
|
||||
tagLength = aFrame.GetFooterLength() - Frame::kFcsSize;
|
||||
|
||||
aesCcm.SetKey(macKey, 16);
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* 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 implements the Announce Begin Client.
|
||||
*/
|
||||
|
||||
#define WPP_NAME "announce_begin_client.tmh"
|
||||
|
||||
#ifdef OPENTHREAD_CONFIG_FILE
|
||||
#include OPENTHREAD_CONFIG_FILE
|
||||
#else
|
||||
#include <openthread-config.h>
|
||||
#endif
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <meshcop/announce_begin_client.hpp>
|
||||
#include <thread/meshcop_tlvs.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_uris.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
AnnounceBeginClient::AnnounceBeginClient(ThreadNetif &aThreadNetif) :
|
||||
mSocket(aThreadNetif.GetIp6().mUdp),
|
||||
mNetif(aThreadNetif)
|
||||
{
|
||||
mSocket.Open(HandleUdpReceive, this);
|
||||
mCoapMessageId = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
ThreadError AnnounceBeginClient::SendRequest(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
|
||||
const Ip6::Address &aAddress)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Coap::Header header;
|
||||
MeshCoP::CommissionerSessionIdTlv sessionId;
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct
|
||||
{
|
||||
MeshCoP::ChannelMaskTlv tlv;
|
||||
MeshCoP::ChannelMaskEntry header;
|
||||
uint32_t mask;
|
||||
} OT_TOOL_PACKED_END channelMask;
|
||||
|
||||
MeshCoP::CountTlv count;
|
||||
MeshCoP::PeriodTlv period;
|
||||
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Message *message;
|
||||
|
||||
for (size_t i = 0; i < sizeof(mCoapToken); i++)
|
||||
{
|
||||
mCoapToken[i] = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
header.Init();
|
||||
header.SetType(aAddress.IsMulticast() ? Coap::Header::kTypeNonConfirmable : Coap::Header::kTypeConfirmable);
|
||||
header.SetCode(Coap::Header::kCodePost);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(mCoapToken, sizeof(mCoapToken));
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_ANNOUNCE_BEGIN);
|
||||
header.Finalize();
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
sessionId.Init();
|
||||
sessionId.SetCommissionerSessionId(mNetif.GetCommissioner().GetSessionId());
|
||||
SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId)));
|
||||
|
||||
channelMask.tlv.Init();
|
||||
channelMask.tlv.SetLength(sizeof(channelMask.header) + sizeof(channelMask.mask));
|
||||
channelMask.header.SetChannelPage(0);
|
||||
channelMask.header.SetMaskLength(sizeof(channelMask.mask));
|
||||
channelMask.mask = HostSwap32(aChannelMask);
|
||||
SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask)));
|
||||
|
||||
count.Init();
|
||||
count.SetCount(aCount);
|
||||
SuccessOrExit(error = message->Append(&count, sizeof(count)));
|
||||
|
||||
period.Init();
|
||||
period.SetPeriod(aPeriod);
|
||||
SuccessOrExit(error = message->Append(&period, sizeof(period)));
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.GetPeerAddr() = aAddress;
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
messageInfo.mInterfaceId = mNetif.GetInterfaceId();
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoMeshCoP("sent announce begin query\r\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void AnnounceBeginClient::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
otLogInfoMeshCoP("received announce begin response\r\n");
|
||||
(void)aContext;
|
||||
(void)aMessage;
|
||||
(void)aMessageInfo;
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* 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 responding to Announce Requests.
|
||||
*/
|
||||
|
||||
#ifndef ANNOUNCE_BEGIN_CLIENT_HPP_
|
||||
#define ANNOUNCE_BEGIN_CLIENT_HPP_
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread-types.h>
|
||||
#include <commissioning/commissioner.h>
|
||||
#include <coap/coap_server.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
#include <net/udp6.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
class ThreadNetif;
|
||||
|
||||
/**
|
||||
* This class implements handling Announce Begin Requests.
|
||||
*
|
||||
*/
|
||||
class AnnounceBeginClient
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
*/
|
||||
AnnounceBeginClient(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method sends a Announce Begin message.
|
||||
*
|
||||
* @param[in] aChannelMask The channel mask value.
|
||||
* @param[in] aCount The number of energy measurements per channel.
|
||||
* @param[in] aPeriod The time between energy measurements (milliseconds).
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the Announce Begin message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers to generate a Announce Begin message.
|
||||
*
|
||||
*/
|
||||
ThreadError SendRequest(uint32_t aChannelMask, uint8_t aCount, uint16_t mPeriod, const Ip6::Address &aAddress);
|
||||
|
||||
private:
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
Ip6::UdpSocket mSocket;
|
||||
uint8_t mCoapToken[2];
|
||||
uint16_t mCoapMessageId;
|
||||
ThreadNetif &mNetif;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // ANNOUNCE_BEGIN_CLIENT_HPP_
|
||||
@@ -56,6 +56,7 @@ namespace Thread {
|
||||
namespace MeshCoP {
|
||||
|
||||
Commissioner::Commissioner(ThreadNetif &aThreadNetif):
|
||||
mAnnounceBegin(aThreadNetif),
|
||||
mEnergyScan(aThreadNetif),
|
||||
mPanIdQuery(aThreadNetif),
|
||||
mTimer(aThreadNetif.GetIp6().mTimerScheduler, HandleTimer, this),
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <coap/coap_server.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <meshcop/announce_begin_client.hpp>
|
||||
#include <meshcop/dtls.hpp>
|
||||
#include <meshcop/energy_scan_client.hpp>
|
||||
#include <meshcop/panid_query_client.hpp>
|
||||
@@ -120,9 +121,6 @@ public:
|
||||
*/
|
||||
uint16_t GetSessionId(void) const;
|
||||
|
||||
EnergyScanClient mEnergyScan;
|
||||
PanIdQueryClient mPanIdQuery;
|
||||
|
||||
/**
|
||||
* This method sends MGMT_COMMISSIONER_GET.
|
||||
*
|
||||
@@ -149,6 +147,10 @@ public:
|
||||
ThreadError SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
|
||||
const uint8_t *aTlvs, uint8_t aLength);
|
||||
|
||||
AnnounceBeginClient mAnnounceBegin;
|
||||
EnergyScanClient mEnergyScan;
|
||||
PanIdQueryClient mPanIdQuery;
|
||||
|
||||
private:
|
||||
static void HandleTimer(void *aContext);
|
||||
void HandleTimer(void);
|
||||
|
||||
@@ -340,7 +340,7 @@ ThreadError JoinerRouter::SendJoinerEntrust(const Ip6::MessageInfo &aMessageInfo
|
||||
Tlv *tlv;
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
message->SetJoinerEntrust(true);
|
||||
message->SetSubType(Message::kSubTypeJoinerEntrust);
|
||||
|
||||
header.Init();
|
||||
header.SetType(Coap::Header::kTypeConfirmable);
|
||||
|
||||
@@ -1445,6 +1445,13 @@ ThreadError otCommissionerSetProvisioningUrl(otInstance *, const char *aProvisio
|
||||
return sThreadNetif->GetCommissioner().SetProvisioningUrl(aProvisioningUrl);
|
||||
}
|
||||
|
||||
ThreadError otCommissionerAnnounceBegin(otInstance *, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
|
||||
const otIp6Address *aAddress)
|
||||
{
|
||||
return sThreadNetif->GetCommissioner().mAnnounceBegin.SendRequest(aChannelMask, aCount, aPeriod,
|
||||
*static_cast<const Ip6::Address *>(aAddress));
|
||||
}
|
||||
|
||||
ThreadError otCommissionerEnergyScan(otInstance *, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
|
||||
uint16_t aScanDuration, const otIp6Address *aAddress,
|
||||
otCommissionerEnergyReportCallback aCallback, void *aContext)
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* 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 implements the Announce Begin Server.
|
||||
*/
|
||||
|
||||
#define WPP_NAME "announce_begin_server.tmh"
|
||||
|
||||
#ifdef OPENTHREAD_CONFIG_FILE
|
||||
#include OPENTHREAD_CONFIG_FILE
|
||||
#else
|
||||
#include <openthread-config.h>
|
||||
#endif
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <platform/radio.h>
|
||||
#include <thread/meshcop_tlvs.hpp>
|
||||
#include <thread/announce_begin_server.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_uris.hpp>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap32;
|
||||
|
||||
namespace Thread {
|
||||
|
||||
AnnounceBeginServer::AnnounceBeginServer(ThreadNetif &aThreadNetif) :
|
||||
mTimer(aThreadNetif.GetIp6().mTimerScheduler, &AnnounceBeginServer::HandleTimer, this),
|
||||
mAnnounceBegin(OPENTHREAD_URI_ANNOUNCE_BEGIN, &AnnounceBeginServer::HandleRequest, this),
|
||||
mCoapServer(aThreadNetif.GetCoapServer()),
|
||||
mNetif(aThreadNetif)
|
||||
{
|
||||
mCoapServer.AddResource(mAnnounceBegin);
|
||||
}
|
||||
|
||||
ThreadError AnnounceBeginServer::SendAnnounce(uint32_t aChannelMask)
|
||||
{
|
||||
return SendAnnounce(aChannelMask, kDefaultCount, kDefaultPeriod);
|
||||
}
|
||||
|
||||
ThreadError AnnounceBeginServer::SendAnnounce(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
mChannelMask = aChannelMask;
|
||||
mCount = aCount;
|
||||
mPeriod = aPeriod;
|
||||
mChannel = kPhyMinChannel;
|
||||
|
||||
while ((mChannelMask & (1 << mChannel)) == 0)
|
||||
{
|
||||
mChannel++;
|
||||
VerifyOrExit(mChannel <= kPhyMaxChannel,);
|
||||
}
|
||||
|
||||
mTimer.Start(mPeriod);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void AnnounceBeginServer::HandleRequest(void *aContext, Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
static_cast<AnnounceBeginServer *>(aContext)->HandleRequest(aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void AnnounceBeginServer::HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct
|
||||
{
|
||||
MeshCoP::ChannelMaskTlv tlv;
|
||||
MeshCoP::ChannelMaskEntry entry;
|
||||
uint32_t mask;
|
||||
} OT_TOOL_PACKED_END channelMask;
|
||||
|
||||
MeshCoP::CountTlv count;
|
||||
MeshCoP::PeriodTlv period;
|
||||
|
||||
VerifyOrExit(aHeader.GetCode() == Coap::Header::kCodePost, ;);
|
||||
|
||||
SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kChannelMask, sizeof(channelMask), channelMask.tlv));
|
||||
VerifyOrExit(channelMask.tlv.IsValid() &&
|
||||
channelMask.entry.GetChannelPage() == 0 &&
|
||||
channelMask.entry.GetMaskLength() == sizeof(uint32_t), ;);
|
||||
|
||||
SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kCount, sizeof(count), count));
|
||||
VerifyOrExit(count.IsValid(), ;);
|
||||
|
||||
SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kPeriod, sizeof(period), period));
|
||||
VerifyOrExit(period.IsValid(), ;);
|
||||
|
||||
SendAnnounce(HostSwap32(channelMask.mask), count.GetCount(), period.GetPeriod());
|
||||
|
||||
SendResponse(aHeader, aMessageInfo);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadError AnnounceBeginServer::SendResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aRequestInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Message *message = NULL;
|
||||
Coap::Header responseHeader;
|
||||
Ip6::MessageInfo responseInfo;
|
||||
|
||||
VerifyOrExit(aRequestHeader.GetType() == Coap::Header::kTypeConfirmable, ;);
|
||||
|
||||
VerifyOrExit((message = mCoapServer.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
responseHeader.Init();
|
||||
responseHeader.SetType(Coap::Header::kTypeAcknowledgment);
|
||||
responseHeader.SetCode(Coap::Header::kCodeChanged);
|
||||
responseHeader.SetMessageId(aRequestHeader.GetMessageId());
|
||||
responseHeader.SetToken(aRequestHeader.GetToken(), aRequestHeader.GetTokenLength());
|
||||
responseHeader.Finalize();
|
||||
SuccessOrExit(error = message->Append(responseHeader.GetBytes(), responseHeader.GetLength()));
|
||||
|
||||
memcpy(&responseInfo, &aRequestInfo, sizeof(responseInfo));
|
||||
memset(&responseInfo.mSockAddr, 0, sizeof(responseInfo.mSockAddr));
|
||||
SuccessOrExit(error = mCoapServer.SendMessage(*message, responseInfo));
|
||||
|
||||
otLogInfoMeshCoP("sent announce begin response\r\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void AnnounceBeginServer::HandleTimer(void *aContext)
|
||||
{
|
||||
static_cast<AnnounceBeginServer *>(aContext)->HandleTimer();
|
||||
}
|
||||
|
||||
void AnnounceBeginServer::HandleTimer(void)
|
||||
{
|
||||
mNetif.GetMle().SendAnnounce(mChannel++);
|
||||
|
||||
while (mCount > 0)
|
||||
{
|
||||
if (mChannelMask & (1 << mChannel))
|
||||
{
|
||||
mTimer.Start(mPeriod);
|
||||
break;
|
||||
}
|
||||
|
||||
mChannel++;
|
||||
|
||||
if (mChannel > kPhyMaxChannel)
|
||||
{
|
||||
mChannel = kPhyMinChannel;
|
||||
mCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* 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 responding to Announce Requests.
|
||||
*/
|
||||
|
||||
#ifndef ANNOUNCE_BEGIN_SERVER_HPP_
|
||||
#define ANNOUNCE_BEGIN_SERVER_HPP_
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread-types.h>
|
||||
#include <coap/coap_server.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
class ThreadNetif;
|
||||
|
||||
/**
|
||||
* This class implements handling Announce Begin Requests.
|
||||
*
|
||||
*/
|
||||
class AnnounceBeginServer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
*/
|
||||
AnnounceBeginServer(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method begins the MLE Announce transmission process using Count=3 and Period=1s.
|
||||
*
|
||||
* @param[in] aChannelMask The channels to use for transmission.
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the transmission process.
|
||||
*
|
||||
*/
|
||||
ThreadError SendAnnounce(uint32_t aChannelMask);
|
||||
|
||||
/**
|
||||
* This method begins the MLE Announce transmission process.
|
||||
*
|
||||
* @param[in] aChannelMask The channels to use for transmission.
|
||||
* @param[in] aCount The number of transmissions per channel.
|
||||
* @param[in] aPeriod The time between transmissions (milliseconds).
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the transmission process.
|
||||
*
|
||||
*/
|
||||
ThreadError SendAnnounce(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kDefaultCount = 3,
|
||||
kDefaultPeriod = 1000,
|
||||
};
|
||||
|
||||
static void HandleRequest(void *aContext, Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
ThreadError SendResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aRequestMessageInfo);
|
||||
|
||||
static void HandleTimer(void *aContext);
|
||||
void HandleTimer(void);
|
||||
|
||||
uint32_t mChannelMask;
|
||||
uint16_t mPeriod;
|
||||
uint8_t mCount;
|
||||
uint8_t mChannel;
|
||||
|
||||
Timer mTimer;
|
||||
|
||||
Coap::Resource mAnnounceBegin;
|
||||
Coap::Server &mCoapServer;
|
||||
ThreadNetif &mNetif;
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
#endif // ANNOUNCE_BEGIN_SERVER_HPP_
|
||||
@@ -613,7 +613,16 @@ ThreadError MeshForwarder::UpdateIp6Route(Message &aMessage)
|
||||
if (aMessage.IsLinkSecurityEnabled())
|
||||
{
|
||||
mMacDest.mLength = sizeof(mMacDest.mShortAddress);
|
||||
mMacDest.mShortAddress = mMle.GetNextHop(Mac::kShortAddrBroadcast);
|
||||
|
||||
if (ip6Header.GetDestination().IsLinkLocalMulticast())
|
||||
{
|
||||
mMacDest.mShortAddress = Mac::kShortAddrBroadcast;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMacDest.mShortAddress = mMle.GetNextHop(Mac::kShortAddrBroadcast);
|
||||
}
|
||||
|
||||
GetMacSourceAddress(ip6Header.GetSource(), mMacSource);
|
||||
}
|
||||
else if (ip6Header.GetDestination().IsLinkLocal() || ip6Header.GetDestination().IsLinkLocalMulticast())
|
||||
@@ -824,7 +833,7 @@ ThreadError MeshForwarder::HandleFrameRequest(Mac::Frame &aFrame)
|
||||
switch (mSendMessage->GetType())
|
||||
{
|
||||
case Message::kTypeIp6:
|
||||
if (mSendMessage->IsMleDiscoverRequest())
|
||||
if (mSendMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
|
||||
{
|
||||
if (!mScanning)
|
||||
{
|
||||
@@ -995,17 +1004,41 @@ ThreadError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
if (aMessage.IsLinkSecurityEnabled())
|
||||
{
|
||||
fcf |= Mac::Frame::kFcfSecurityEnabled;
|
||||
secCtl = static_cast<uint8_t>(aMessage.IsJoinerEntrust() ? Mac::Frame::kKeyIdMode0 : Mac::Frame::kKeyIdMode1);
|
||||
|
||||
switch (aMessage.GetSubType())
|
||||
{
|
||||
case Message::kSubTypeJoinerEntrust:
|
||||
secCtl = static_cast<uint8_t>(Mac::Frame::kKeyIdMode0);
|
||||
break;
|
||||
|
||||
case Message::kSubTypeMleAnnounce:
|
||||
secCtl = static_cast<uint8_t>(Mac::Frame::kKeyIdMode2);
|
||||
break;
|
||||
|
||||
default:
|
||||
secCtl = static_cast<uint8_t>(Mac::Frame::kKeyIdMode1);
|
||||
break;
|
||||
}
|
||||
|
||||
secCtl |= Mac::Frame::kSecEncMic32;
|
||||
}
|
||||
|
||||
if (aMessage.IsMleDiscoverRequest() || aMessage.IsMleDiscoverResponse())
|
||||
dstpan = mMac.GetPanId();
|
||||
|
||||
switch (aMessage.GetSubType())
|
||||
{
|
||||
case Message::kSubTypeMleAnnounce:
|
||||
aFrame.SetChannel(aMessage.GetChannel());
|
||||
dstpan = Mac::kPanIdBroadcast;
|
||||
break;
|
||||
|
||||
case Message::kSubTypeMleDiscoverRequest:
|
||||
case Message::kSubTypeMleDiscoverResponse:
|
||||
dstpan = aMessage.GetPanId();
|
||||
}
|
||||
else
|
||||
{
|
||||
dstpan = mMac.GetPanId();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dstpan == mMac.GetPanId())
|
||||
@@ -1219,7 +1252,7 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame, ThreadError aError)
|
||||
mSendMessage->SetOffset(0);
|
||||
}
|
||||
|
||||
if (mSendMessage->IsMleDiscoverRequest())
|
||||
if (mSendMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
|
||||
{
|
||||
mSendBusy = true;
|
||||
mDiscoverTimer.Start(mScanDuration);
|
||||
|
||||
+101
-4
@@ -161,6 +161,8 @@ Mle::Mle(ThreadNetif &aThreadNetif) :
|
||||
|
||||
mRouterSelectionJitterTimeout = 0;
|
||||
mRouterSelectionJitter = kRouterSelectionJitter;
|
||||
|
||||
mPreviousPanId = Mac::kPanIdBroadcast;
|
||||
}
|
||||
|
||||
ThreadError Mle::Enable(void)
|
||||
@@ -245,7 +247,7 @@ ThreadError Mle::Discover(uint32_t aScanChannels, uint16_t aScanDuration, uint16
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, ;);
|
||||
message->SetLinkSecurityEnabled(false);
|
||||
message->SetMleDiscoverRequest(true);
|
||||
message->SetSubType(Message::kSubTypeMleDiscoverRequest);
|
||||
message->SetPanId(aPanId);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandDiscoveryRequest));
|
||||
|
||||
@@ -384,6 +386,12 @@ ThreadError Mle::SetStateChild(uint16_t aRloc16)
|
||||
mNetif.GetNetworkDataLocal().ClearResubmitDelayTimer();
|
||||
mNetif.GetIp6().SetForwardingEnabled(false);
|
||||
|
||||
if (mPreviousPanId != Mac::kPanIdBroadcast)
|
||||
{
|
||||
mPreviousPanId = Mac::kPanIdBroadcast;
|
||||
mNetif.GetAnnounceBeginServer().SendAnnounce(1 << mPreviousChannel);
|
||||
}
|
||||
|
||||
otLogInfoMle("Mode -> Child\n");
|
||||
return kThreadError_None;
|
||||
}
|
||||
@@ -1064,7 +1072,14 @@ void Mle::HandleParentRequestTimer(void)
|
||||
switch (mParentRequestMode)
|
||||
{
|
||||
case kMleAttachAnyPartition:
|
||||
if (mMleRouter.BecomeLeader() != kThreadError_None)
|
||||
if (mPreviousPanId != Mac::kPanIdBroadcast)
|
||||
{
|
||||
mMac.SetChannel(mPreviousChannel);
|
||||
mMac.SetPanId(mPreviousPanId);
|
||||
mPreviousPanId = Mac::kPanIdBroadcast;
|
||||
BecomeDetached();
|
||||
}
|
||||
else if (mMleRouter.BecomeLeader() != kThreadError_None)
|
||||
{
|
||||
mParentRequestState = kParentIdle;
|
||||
BecomeDetached();
|
||||
@@ -1326,6 +1341,48 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::SendAnnounce(uint8_t aChannel)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ChannelTlv channel;
|
||||
PanIdTlv panid;
|
||||
Ip6::Address destination;
|
||||
Message *message;
|
||||
(void)aChannel;
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, ;);
|
||||
message->SetSubType(Message::kSubTypeMleAnnounce);
|
||||
message->SetChannel(aChannel);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandAnnounce));
|
||||
|
||||
channel.Init();
|
||||
channel.SetChannelPage(0);
|
||||
channel.SetChannel(mMac.GetChannel());
|
||||
SuccessOrExit(error = message->Append(&channel, sizeof(channel)));
|
||||
|
||||
SuccessOrExit(error = AppendActiveTimestamp(*message));
|
||||
|
||||
panid.Init();
|
||||
panid.SetPanId(mMac.GetPanId());
|
||||
SuccessOrExit(error = message->Append(&panid, sizeof(panid)));
|
||||
|
||||
memset(&destination, 0, sizeof(destination));
|
||||
destination.mFields.m16[0] = HostSwap16(0xff02);
|
||||
destination.mFields.m16[7] = HostSwap16(0x0001);
|
||||
SuccessOrExit(error = SendMessage(*message, destination));
|
||||
|
||||
otLogInfoMle("sent announce on channel %d\n", aChannel);
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::SendMessage(Message &aMessage, const Ip6::Address &aDestination)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -1554,7 +1611,8 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
command == Header::kCommandParentRequest ||
|
||||
command == Header::kCommandParentResponse ||
|
||||
command == Header::kCommandChildIdRequest ||
|
||||
command == Header::kCommandChildUpdateRequest))
|
||||
command == Header::kCommandChildUpdateRequest ||
|
||||
command == Header::kCommandAnnounce))
|
||||
{
|
||||
otLogDebgMle("mle sequence unknown! %d\n", command);
|
||||
ExitNow();
|
||||
@@ -1614,6 +1672,10 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
case Header::kCommandChildUpdateResponse:
|
||||
HandleChildUpdateResponse(aMessage, aMessageInfo);
|
||||
break;
|
||||
|
||||
case Header::kCommandAnnounce:
|
||||
HandleAnnounce(aMessage, aMessageInfo);
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -2211,6 +2273,41 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ChannelTlv channel;
|
||||
ActiveTimestampTlv timestamp;
|
||||
const MeshCoP::Timestamp *localTimestamp;
|
||||
PanIdTlv panid;
|
||||
|
||||
otLogInfoMle("Received announce\n");
|
||||
|
||||
SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kChannel, sizeof(channel), channel));
|
||||
VerifyOrExit(channel.IsValid(),);
|
||||
|
||||
SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kActiveTimestamp, sizeof(timestamp), timestamp));
|
||||
VerifyOrExit(timestamp.IsValid(),);
|
||||
|
||||
SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kPanId, sizeof(panid), panid));
|
||||
VerifyOrExit(panid.IsValid(),);
|
||||
|
||||
localTimestamp = mNetif.GetActiveDataset().GetNetwork().GetTimestamp();
|
||||
|
||||
VerifyOrExit(localTimestamp == NULL || localTimestamp->Compare(timestamp) > 0,);
|
||||
|
||||
Stop();
|
||||
mPreviousChannel = mMac.GetChannel();
|
||||
mPreviousPanId = mMac.GetPanId();
|
||||
mMac.SetChannel(static_cast<uint8_t>(channel.GetChannel()));
|
||||
mMac.SetPanId(panid.GetPanId());
|
||||
Start();
|
||||
|
||||
exit:
|
||||
(void)aMessageInfo;
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Mle::HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
@@ -2291,7 +2388,7 @@ ThreadError Mle::SendDiscoveryResponse(const Ip6::Address &aDestination, uint16_
|
||||
|
||||
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, ;);
|
||||
message->SetLinkSecurityEnabled(false);
|
||||
message->SetMleDiscoverResponse(true);
|
||||
message->SetSubType(Message::kSubTypeMleDiscoverResponse);
|
||||
message->SetPanId(aPanId);
|
||||
SuccessOrExit(error = AppendHeader(*message, Header::kCommandDiscoveryResponse));
|
||||
|
||||
|
||||
+17
-1
@@ -277,6 +277,7 @@ public:
|
||||
kCommandChildIdResponse = 12, ///< Child ID Response
|
||||
kCommandChildUpdateRequest = 13, ///< Child Update Request
|
||||
kCommandChildUpdateResponse = 14, ///< Child Update Response
|
||||
kCommandAnnounce = 15, ///< Announce
|
||||
kCommandDiscoveryRequest = 16, ///< Discovery Request
|
||||
kCommandDiscoveryResponse = 17, ///< Discovery Response
|
||||
};
|
||||
@@ -410,6 +411,17 @@ public:
|
||||
*/
|
||||
void HandleDiscoverComplete(void);
|
||||
|
||||
/**
|
||||
* This method generates an MLE Announce message.
|
||||
*
|
||||
* @param[in] aChannel The channel to use when transmitting.
|
||||
*
|
||||
* @retval kThreadError_None Successfully generated an MLE Announce message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers to generate the MLE Announce message.
|
||||
*
|
||||
*/
|
||||
ThreadError SendAnnounce(uint8_t aChannel);
|
||||
|
||||
/**
|
||||
* This method causes the Thread interface to detach from the Thread network.
|
||||
*
|
||||
@@ -1002,7 +1014,7 @@ protected:
|
||||
/**
|
||||
* This method generates an MLE Child Update Request message.
|
||||
*
|
||||
* @retval kThreadError_None Successfully generated an MLE Child Update Request message..
|
||||
* @retval kThreadError_None Successfully generated an MLE Child Update Request message.
|
||||
* @retval kThreadError_NoBufs Insufficient buffers to generate the MLE Child Update Request message.
|
||||
*
|
||||
*/
|
||||
@@ -1121,6 +1133,7 @@ private:
|
||||
ThreadError HandleDataResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
|
||||
uint32_t aKeySequence);
|
||||
ThreadError HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleDiscoveryRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
ThreadError HandleDiscoveryResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
@@ -1159,6 +1172,9 @@ private:
|
||||
void *mDiscoverContext;
|
||||
bool mIsDiscoverInProgress;
|
||||
|
||||
uint8_t mPreviousChannel;
|
||||
uint16_t mPreviousPanId;
|
||||
|
||||
Ip6::NetifUnicastAddress mLinkLocal16;
|
||||
Ip6::NetifUnicastAddress mLinkLocal64;
|
||||
Ip6::NetifUnicastAddress mMeshLocal64;
|
||||
|
||||
@@ -94,6 +94,8 @@ public:
|
||||
kStatus = 17, ///< Status TLV
|
||||
kVersion = 18, ///< Version TLV
|
||||
kAddressRegistration = 19, ///< Address Registration TLV
|
||||
kChannel = 20, ///< Channel TLV
|
||||
kPanId = 21, ///< PAN ID TLV
|
||||
kActiveTimestamp = 22, ///< Active Timestamp TLV
|
||||
kPendingTimestamp = 23, ///< Pending Timestamp TLV
|
||||
kActiveDataset = 24, ///< Active Operational Dataset TLV
|
||||
@@ -1450,6 +1452,109 @@ private:
|
||||
AddressRegistrationEntry mAddresses[4];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Channel TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ChannelTlv: public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void) { SetType(kChannel); 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 Channel Page value.
|
||||
*
|
||||
* @returns The Channel Page value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetChannelPage(void) const { return mChannelPage; }
|
||||
|
||||
/**
|
||||
* This method sets the Channel Page value.
|
||||
*
|
||||
* @param[in] aChannelPage The Channel Page value.
|
||||
*
|
||||
*/
|
||||
void SetChannelPage(uint8_t aChannelPage) { mChannelPage = aChannelPage; }
|
||||
|
||||
/**
|
||||
* This method returns the Channel value.
|
||||
*
|
||||
* @returns The Channel value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetChannel(void) const { return HostSwap16(mChannel); }
|
||||
|
||||
/**
|
||||
* This method sets the Channel value.
|
||||
*
|
||||
* @param[in] aChannel The Channel value.
|
||||
*
|
||||
*/
|
||||
void SetChannel(uint16_t aChannel) { mChannel = HostSwap16(aChannel); }
|
||||
|
||||
private:
|
||||
uint8_t mChannelPage;
|
||||
uint16_t mChannel;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements PAN ID TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class PanIdTlv: public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void) { SetType(kPanId); 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 PAN ID value.
|
||||
*
|
||||
* @returns The PAN ID value.
|
||||
*
|
||||
*/
|
||||
uint16_t GetPanId(void) const { return HostSwap16(mPanId); }
|
||||
|
||||
/**
|
||||
* This method sets the PAN ID value.
|
||||
*
|
||||
* @param[in] aPanId The PAN ID value.
|
||||
*
|
||||
*/
|
||||
void SetPanId(uint16_t aPanId) { mPanId = HostSwap16(aPanId); }
|
||||
|
||||
private:
|
||||
uint16_t mPanId;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Active Timestamp TLV generation and parsing.
|
||||
*
|
||||
|
||||
@@ -79,6 +79,7 @@ ThreadNetif::ThreadNetif(Ip6::Ip6 &aIp6):
|
||||
#endif // OPENTHREAD_ENABLE_JOINER
|
||||
mJoinerRouter(*this),
|
||||
mLeader(*this),
|
||||
mAnnounceBegin(*this),
|
||||
mPanIdQuery(*this),
|
||||
mEnergyScan(*this)
|
||||
{
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <net/ip6_filter.hpp>
|
||||
#include <net/netif.hpp>
|
||||
#include <thread/address_resolver.hpp>
|
||||
#include <thread/announce_begin_server.hpp>
|
||||
#include <thread/energy_scan_server.hpp>
|
||||
#include <thread/network_diag.hpp>
|
||||
#include <thread/key_manager.hpp>
|
||||
@@ -246,6 +247,8 @@ public:
|
||||
|
||||
MeshCoP::JoinerRouter &GetJoinerRouter(void) { return mJoinerRouter; }
|
||||
|
||||
AnnounceBeginServer &GetAnnounceBeginServer(void) { return mAnnounceBegin; }
|
||||
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
MeshCoP::Commissioner &GetCommissioner(void) { return mCommissioner; }
|
||||
#endif // OPENTHREAD_ENABLE_COMMISSIONER
|
||||
@@ -288,6 +291,7 @@ private:
|
||||
|
||||
MeshCoP::JoinerRouter mJoinerRouter;
|
||||
MeshCoP::Leader mLeader;
|
||||
AnnounceBeginServer mAnnounceBegin;
|
||||
PanIdQueryServer mPanIdQuery;
|
||||
EnergyScanServer mEnergyScan;
|
||||
};
|
||||
|
||||
@@ -130,6 +130,14 @@ namespace Thread {
|
||||
*/
|
||||
#define OPENTHREAD_URI_SERVER_DATA "a/sd"
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_URI_ANNOUNCE_BEGIN
|
||||
*
|
||||
* The URI Path for Announce Begin.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_URI_ANNOUNCE_BEGIN "c/ab"
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_URI_RELAY_RX
|
||||
*
|
||||
|
||||
@@ -104,6 +104,7 @@ EXTRA_DIST = \
|
||||
thread-cert/Cert_7_1_05_BorderRouterAsRouter.py \
|
||||
thread-cert/Cert_8_1_01_Commissioning.py \
|
||||
thread-cert/Cert_8_1_02_Commissioning.py \
|
||||
thread-cert/Cert_9_2_12_Announce.py \
|
||||
thread-cert/Cert_9_2_13_EnergyScan.py \
|
||||
thread-cert/Cert_9_2_14_PanIdQuery.py \
|
||||
thread-cert/node.py \
|
||||
@@ -222,6 +223,7 @@ check_SCRIPTS += \
|
||||
thread-cert/Cert_7_1_05_BorderRouterAsRouter.py \
|
||||
thread-cert/Cert_8_1_01_Commissioning.py \
|
||||
thread-cert/Cert_8_1_02_Commissioning.py \
|
||||
thread-cert/Cert_9_2_12_Announce.py \
|
||||
thread-cert/Cert_9_2_13_EnergyScan.py \
|
||||
thread-cert/Cert_9_2_14_PanIdQuery.py \
|
||||
$(NULL)
|
||||
@@ -242,6 +244,7 @@ TESTS = \
|
||||
XFAIL_NCP_TESTS = \
|
||||
thread-cert/Cert_8_1_01_Commissioning.py \
|
||||
thread-cert/Cert_8_1_02_Commissioning.py \
|
||||
thread-cert/Cert_9_2_12_Announce.py \
|
||||
thread-cert/Cert_9_2_13_EnergyScan.py \
|
||||
thread-cert/Cert_9_2_14_PanIdQuery.py \
|
||||
$(NULL)
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2016, The OpenThread Authors.
|
||||
# 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.
|
||||
#
|
||||
|
||||
import time
|
||||
import unittest
|
||||
|
||||
import node
|
||||
|
||||
LEADER1 = 1
|
||||
ROUTER1 = 2
|
||||
LEADER2 = 3
|
||||
ROUTER2 = 4
|
||||
MED = 5
|
||||
|
||||
DATASET1_TIMESTAMP = 20
|
||||
DATASET1_CHANNEL = 11
|
||||
DATASET1_PANID = 0xface
|
||||
|
||||
DATASET2_TIMESTAMP = 10
|
||||
DATASET2_CHANNEL = 12
|
||||
DATASET2_PANID = 0xafce
|
||||
|
||||
class Cert_9_2_12_Announce(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.nodes = {}
|
||||
for i in range(1,6):
|
||||
self.nodes[i] = node.Node(i)
|
||||
|
||||
self.nodes[LEADER1].set_active_dataset(DATASET1_TIMESTAMP, channel=DATASET1_CHANNEL, panid=DATASET1_PANID)
|
||||
self.nodes[LEADER1].set_mode('rsdn')
|
||||
self.nodes[LEADER1].add_whitelist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[LEADER1].enable_whitelist()
|
||||
|
||||
self.nodes[ROUTER1].set_active_dataset(DATASET1_TIMESTAMP, channel=DATASET1_CHANNEL, panid=DATASET1_PANID)
|
||||
self.nodes[ROUTER1].set_mode('rsdn')
|
||||
self.nodes[ROUTER1].add_whitelist(self.nodes[LEADER1].get_addr64())
|
||||
self.nodes[ROUTER1].add_whitelist(self.nodes[LEADER2].get_addr64())
|
||||
self.nodes[ROUTER1].enable_whitelist()
|
||||
self.nodes[ROUTER1].set_router_selection_jitter(1)
|
||||
|
||||
self.nodes[LEADER2].set_active_dataset(DATASET2_TIMESTAMP, channel=DATASET2_CHANNEL, panid=DATASET1_PANID)
|
||||
self.nodes[LEADER2].set_mode('rsdn')
|
||||
self.nodes[LEADER2].add_whitelist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[LEADER2].add_whitelist(self.nodes[ROUTER2].get_addr64())
|
||||
self.nodes[LEADER2].enable_whitelist()
|
||||
self.nodes[LEADER2].set_router_selection_jitter(1)
|
||||
|
||||
self.nodes[ROUTER2].set_active_dataset(DATASET2_TIMESTAMP, channel=DATASET2_CHANNEL, panid=DATASET1_PANID)
|
||||
self.nodes[ROUTER2].set_mode('rsdn')
|
||||
self.nodes[ROUTER2].add_whitelist(self.nodes[LEADER2].get_addr64())
|
||||
self.nodes[ROUTER2].add_whitelist(self.nodes[MED].get_addr64())
|
||||
self.nodes[ROUTER2].enable_whitelist()
|
||||
self.nodes[ROUTER2].set_router_selection_jitter(1)
|
||||
|
||||
self.nodes[MED].set_active_dataset(DATASET2_TIMESTAMP, channel=DATASET2_CHANNEL, panid=DATASET1_PANID)
|
||||
self.nodes[MED].set_mode('rsn')
|
||||
self.nodes[MED].add_whitelist(self.nodes[ROUTER2].get_addr64())
|
||||
self.nodes[MED].enable_whitelist()
|
||||
|
||||
def tearDown(self):
|
||||
for node in list(self.nodes.values()):
|
||||
node.stop()
|
||||
del self.nodes
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER1].start()
|
||||
self.nodes[LEADER1].set_state('leader')
|
||||
self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
time.sleep(5)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[LEADER2].start()
|
||||
self.nodes[LEADER2].set_state('leader')
|
||||
self.assertEqual(self.nodes[LEADER2].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
time.sleep(5)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[MED].start()
|
||||
time.sleep(5)
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
ipaddrs = self.nodes[ROUTER1].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
|
||||
self.nodes[LEADER1].announce_begin(0x1000, 1, 1000, ipaddr)
|
||||
time.sleep(30)
|
||||
self.assertEqual(self.nodes[LEADER2].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
ipaddrs = self.nodes[MED].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER1].ping(ipaddr))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -425,5 +425,31 @@ class Node:
|
||||
self.send_command(cmd)
|
||||
self.pexpect.expect('Done')
|
||||
|
||||
def set_active_dataset(self, timestamp, panid=None, channel=None):
|
||||
self.send_command('dataset clear')
|
||||
self.pexpect.expect('Done')
|
||||
|
||||
cmd = 'dataset activetimestamp %d' % timestamp
|
||||
self.send_command(cmd)
|
||||
self.pexpect.expect('Done')
|
||||
|
||||
if panid != None:
|
||||
cmd = 'dataset panid %d' % panid
|
||||
self.send_command(cmd)
|
||||
self.pexpect.expect('Done')
|
||||
|
||||
if channel != None:
|
||||
cmd = 'dataset channel %d' % channel
|
||||
self.send_command(cmd)
|
||||
self.pexpect.expect('Done')
|
||||
|
||||
self.send_command('dataset commit active')
|
||||
self.pexpect.expect('Done')
|
||||
|
||||
def announce_begin(self, mask, count, period, ipaddr):
|
||||
cmd = 'commissioner announce ' + str(mask) + ' ' + str(count) + ' ' + str(period) + ' ' + ipaddr
|
||||
self.send_command(cmd)
|
||||
self.pexpect.expect('Done')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user