From f3ef4046dbc97820da77448965ec47b547505660 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Mon, 10 Oct 2016 09:40:08 -0700 Subject: [PATCH] Steering data. (#743) --- etc/visual-studio/libopenthread.vcxproj | 2 + etc/visual-studio/libopenthread_k.vcxproj | 2 + include/openthread-types.h | 25 ++-- src/core/Makefile.am | 2 + src/core/common/crc16.cpp | 75 +++++++++++ src/core/common/crc16.hpp | 91 +++++++++++++ src/core/meshcop/commissioner.cpp | 120 ++++++++++++++++-- src/core/meshcop/commissioner.hpp | 18 ++- src/core/meshcop/joiner.cpp | 29 ++++- src/core/thread/meshcop_tlvs.hpp | 24 +++- src/core/thread/mle.cpp | 29 +++++ .../thread-cert/Cert_8_1_01_Commissioning.py | 3 +- .../thread-cert/Cert_8_1_02_Commissioning.py | 1 + 13 files changed, 389 insertions(+), 32 deletions(-) create mode 100644 src/core/common/crc16.cpp create mode 100644 src/core/common/crc16.hpp diff --git a/etc/visual-studio/libopenthread.vcxproj b/etc/visual-studio/libopenthread.vcxproj index 155c6d504..be9d951d7 100644 --- a/etc/visual-studio/libopenthread.vcxproj +++ b/etc/visual-studio/libopenthread.vcxproj @@ -21,6 +21,7 @@ + @@ -79,6 +80,7 @@ + diff --git a/etc/visual-studio/libopenthread_k.vcxproj b/etc/visual-studio/libopenthread_k.vcxproj index 72e5e9232..defeda33d 100644 --- a/etc/visual-studio/libopenthread_k.vcxproj +++ b/etc/visual-studio/libopenthread_k.vcxproj @@ -21,6 +21,7 @@ + @@ -79,6 +80,7 @@ + diff --git a/include/openthread-types.h b/include/openthread-types.h index a2733da6b..0e9c49146 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -317,6 +317,18 @@ typedef struct otIp6Address otIp6Address; #define OT_CHANNEL_ALL 0xffffffff ///< All channels +#define OT_STEERING_DATA_MAX_LENGTH 16 ///< Max steering data length (bytes) + +/** + * This structure represents the steering data. + * + */ +typedef struct otSteeringData +{ + uint8_t mLength; + uint8_t m8[OT_STEERING_DATA_MAX_LENGTH]; +} otSteeringData; + /** * This struct represents a received IEEE 802.15.4 Beacon. * @@ -326,6 +338,7 @@ typedef struct otActiveScanResult otExtAddress mExtAddress; ///< IEEE 802.15.4 Extended Address otNetworkName mNetworkName; ///< Thread Network Name otExtendedPanId mExtendedPanId; ///< Thread Extended PAN ID + otSteeringData mSteeringData; ///< Steering Data uint16_t mPanId; ///< IEEE 802.15.4 PAN ID uint16_t mJoinerUdpPort; ///< Joiner UDP Port uint8_t mChannel; ///< IEEE 802.15.4 Channel @@ -404,18 +417,6 @@ typedef struct otOperationalDataset bool mIsChannelMaskPage0Set : 1; ///< TRUE if Channel Mask Page 0 is set, FALSE otherwise. } otOperationalDataset; -#define OT_STEERING_DATA_MAX_LENGTH 16 ///< Max steering data length (bytes) - -/** - * This structure represents the steering data. - * - */ -typedef struct otSteeringData -{ - uint8_t mLength; - uint8_t m8[OT_STEERING_DATA_MAX_LENGTH]; -} otSteeringData; - /** * This structure represents a Commissioning Dataset. * diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 196a61b37..56205e630 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -39,6 +39,7 @@ libopenthread_a_SOURCES = \ openthread.cpp \ coap/coap_header.cpp \ coap/coap_server.cpp \ + common/crc16.cpp \ common/logging.cpp \ common/message.cpp \ common/tasklet.cpp \ @@ -115,6 +116,7 @@ noinst_HEADERS = \ coap/coap_header.hpp \ coap/coap_server.hpp \ common/code_utils.hpp \ + common/crc16.hpp \ common/debug.hpp \ common/encoding.hpp \ common/logging.hpp \ diff --git a/src/core/common/crc16.cpp b/src/core/common/crc16.cpp new file mode 100644 index 000000000..e2e720f6e --- /dev/null +++ b/src/core/common/crc16.cpp @@ -0,0 +1,75 @@ +/* + * 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 CRC16 computations. + */ + +#include + +namespace Thread { + +Crc16::Crc16(Polynomial aPolynomial) +{ + mPolynomial = static_cast(aPolynomial); + Init(); +} + +void Crc16::Init(void) +{ + mCrc = 0xffff; +} + +void Crc16::Update(uint8_t aByte) +{ + uint8_t i; + + mCrc = mCrc ^ static_cast(aByte << 8); + i = 8; + + do + { + if (mCrc & 0x8000) + { + mCrc = static_cast(mCrc << 1) ^ mPolynomial; + } + else + { + mCrc = static_cast(mCrc << 1); + } + } + while (--i); +} + +uint16_t Crc16::Get(void) const +{ + return mCrc; +} + +} // namespace Thread diff --git a/src/core/common/crc16.hpp b/src/core/common/crc16.hpp new file mode 100644 index 000000000..0ea6be19f --- /dev/null +++ b/src/core/common/crc16.hpp @@ -0,0 +1,91 @@ +/* + * 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 CRC16 computations. + */ + +#ifndef CRC16_HPP_ +#define CRC16_HPP_ + +#include + +namespace Thread { + +/** + * This class implements CRC16 computations. + * + */ +class Crc16 +{ +public: + enum Polynomial + { + kCcitt = 0x1021, ///< CRC16_CCITT + kAnsi = 0x8005, ///< CRC16-ANSI + }; + + /** + * This constructor initializes the object. + * + * @param[in] aPolynomial The polynomial value. + * + */ + Crc16(Polynomial aPolynomial); + + /** + * This method initializes the CRC16 computation. + * + */ + void Init(void); + + /*c* + * This method feeds a byte value into the CRC16 computation. + * + * @param[in] aByte The byte value. + * + */ + void Update(uint8_t aByte); + + /** + * This method gets the current CRC16 value. + * + * @returns The current CRC16 value. + * + */ + uint16_t Get(void) const; + +private: + uint16_t mPolynomial; + uint16_t mCrc; +}; + +} // namespace Thread + +#endif // CRC16_HPP_ diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index e3bcc1a2f..aff9c4543 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -81,7 +82,10 @@ ThreadError Commissioner::Start(void) VerifyOrExit(mState == kStateDisabled, error = kThreadError_InvalidState); SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this)); + mState = kStatePetition; + mTransmitAttempts = 0; + SendPetition(); exit: @@ -90,10 +94,84 @@ exit: ThreadError Commissioner::Stop(void) { + ThreadError error = kThreadError_None; + + VerifyOrExit(mState != kStateDisabled, error = kThreadError_InvalidState); + mState = kStateDisabled; + mTransmitAttempts = 0; + SendKeepAlive(); - mTimer.Start(1000); - return kThreadError_None; + +exit: + return error; +} + +ThreadError Commissioner::SendCommissionerSet(void) +{ + ThreadError error; + otCommissioningDataset dataset; + SteeringDataTlv steeringData; + + VerifyOrExit(mState == kStateActive, error = kThreadError_InvalidState); + + memset(&dataset, 0, sizeof(dataset)); + + // session id + dataset.mSessionId = mSessionId; + dataset.mIsSessionIdSet = true; + + // compute bloom filter + steeringData.Init(); + steeringData.Clear(); + + for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++) + { + Crc16 ccitt(Crc16::kCcitt); + Crc16 ansi(Crc16::kAnsi); + + if (!mJoiners[i].mValid) + { + continue; + } + + if (mJoiners[i].mAny) + { + steeringData.SetLength(1); + steeringData.Set(); + break; + } + + for (size_t j = 0; j < sizeof(mJoiners[i].mExtAddress.m8); j++) + { + uint8_t byte = mJoiners[i].mExtAddress.m8[j]; + ccitt.Update(byte); + ansi.Update(byte); + } + + steeringData.SetBit(ccitt.Get() % steeringData.GetNumBits()); + steeringData.SetBit(ansi.Get() % steeringData.GetNumBits()); + } + + // set bloom filter + memcpy(dataset.mSteeringData.m8, steeringData.GetValue(), steeringData.GetLength()); + dataset.mSteeringData.mLength = steeringData.GetLength(); + dataset.mIsSteeringDataSet = true; + + SuccessOrExit(error = SendMgmtCommissionerSetRequest(dataset, NULL, 0)); + +exit: + return error; +} + +void Commissioner::ClearJoiners(void) +{ + for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++) + { + mJoiners[i].mValid = false; + } + + SendCommissionerSet(); } ThreadError Commissioner::AddJoiner(const Mac::ExtAddress *aExtAddress, const char *aPSKd) @@ -122,6 +200,9 @@ ThreadError Commissioner::AddJoiner(const Mac::ExtAddress *aExtAddress, const ch strncpy(mJoiners[i].mPsk, aPSKd, sizeof(mJoiners[i].mPsk)); mJoiners[i].mValid = true; + + SendCommissionerSet(); + ExitNow(error = kThreadError_None); } @@ -153,6 +234,9 @@ ThreadError Commissioner::RemoveJoiner(const Mac::ExtAddress *aExtAddress) } mJoiners[i].mValid = false; + + SendCommissionerSet(); + ExitNow(error = kThreadError_None); } @@ -189,7 +273,6 @@ void Commissioner::HandleTimer(void) case kStateActive: SendKeepAlive(); - mTimer.Start(5000); break; } } @@ -333,10 +416,19 @@ ThreadError Commissioner::SendPetition(void) { ThreadError error = kThreadError_None; Coap::Header header; - Message *message; + Message *message = NULL; Ip6::MessageInfo messageInfo; CommissionerIdTlv commissionerId; + if (mTransmitAttempts >= kPetitionRetryCount) + { + mState = kStateDisabled; + ExitNow(); + } + + mTimer.Start(Timer::SecToMsec(kPetitionRetryDelay)); + mTransmitAttempts++; + for (size_t i = 0; i < sizeof(mCoapToken); i++) { mCoapToken[i] = otPlatRandomGet() & 0xff; @@ -379,11 +471,20 @@ ThreadError Commissioner::SendKeepAlive(void) { ThreadError error = kThreadError_None; Coap::Header header; - Message *message; + Message *message = NULL; Ip6::MessageInfo messageInfo; StateTlv state; CommissionerSessionIdTlv sessionId; + if (mTransmitAttempts >= kPetitionRetryCount) + { + mState = kStateDisabled; + ExitNow(); + } + + mTimer.Start(Timer::SecToMsec(kPetitionRetryDelay)); + mTransmitAttempts++; + for (size_t i = 0; i < sizeof(mCoapToken); i++) { mCoapToken[i] = otPlatRandomGet() & 0xff; @@ -582,16 +683,19 @@ void Commissioner::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a case kStatePetition: SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerSessionId, sizeof(sessionId), sessionId)); VerifyOrExit(sessionId.IsValid(), ;); - mSessionId = sessionId.GetCommissionerSessionId(); - mState = kStateActive; - mTimer.Start(5000); otLogInfoMeshCoP("received petition response\r\n"); + + mState = kStateActive; + mTransmitAttempts = 0; + mTimer.Start(Timer::SecToMsec(kKeepAliveTimeout) / 2); break; case kStateActive: otLogInfoMeshCoP("received keep alive response\r\n"); + mTransmitAttempts = 0; + mTimer.Start(Timer::SecToMsec(kKeepAliveTimeout) / 2); break; } diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp index f83ca49cc..0de4f4ab4 100644 --- a/src/core/meshcop/commissioner.hpp +++ b/src/core/meshcop/commissioner.hpp @@ -79,6 +79,12 @@ public: */ ThreadError Stop(void); + /** + * This method clears all Joiner entries. + * + */ + void ClearJoiners(void); + /** * This method adds a Joiner entry. * @@ -152,6 +158,14 @@ public: PanIdQueryClient mPanIdQuery; private: + enum + { + kPetitionAttemptDelay = 5, ///< COMM_PET_ATTEMPT_DELAY (seconds) + kPetitionRetryCount = 2, ///< COMM_PET_RETRY_COUNT + kPetitionRetryDelay = 1, ///< COMM_PET_RETRY_DELAY (seconds) + kKeepAliveTimeout = 50, ///< TIMEOUT_COMM_PET (seconds) + }; + static void HandleTimer(void *aContext); void HandleTimer(void); @@ -179,7 +193,7 @@ private: void SendJoinFinalizeResponse(const Coap::Header &aRequestHeader, StateTlv::State aState); void SendDatasetChangedResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo); - + ThreadError SendCommissionerSet(void); ThreadError SendPetition(void); ThreadError SendKeepAlive(void); @@ -208,6 +222,7 @@ private: Message *mTransmitMessage; Timer mTimer; Tasklet mTransmitTask; + uint8_t mTransmitAttempts; bool mSendKek; Ip6::UdpSocket mSocket; @@ -218,7 +233,6 @@ private: Coap::Resource mDatasetChanged; Coap::Server &mCoapServer; ThreadNetif &mNetif; - bool mIsSendMgmtCommRequest; }; diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index 432ae153f..33cb331cd 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -102,10 +103,30 @@ void Joiner::HandleDiscoverResult(otActiveScanResult *aResult) { if (aResult != NULL) { - mJoinerUdpPort = aResult->mJoinerUdpPort; - mJoinerRouterPanId = aResult->mPanId; - mJoinerRouterChannel = aResult->mChannel; - memcpy(&mJoinerRouter, &aResult->mExtAddress, sizeof(mJoinerRouter)); + SteeringDataTlv steeringData; + Mac::ExtAddress extAddress; + Crc16 ccitt(Crc16::kCcitt); + Crc16 ansi(Crc16::kAnsi); + + mNetif.GetMac().GetHashMacAddress(&extAddress); + + for (size_t i = 0; i < sizeof(extAddress); i++) + { + ccitt.Update(extAddress.m8[i]); + ansi.Update(extAddress.m8[i]); + } + + steeringData.SetLength(aResult->mSteeringData.mLength); + memcpy(steeringData.GetValue(), aResult->mSteeringData.m8, steeringData.GetLength()); + + if (steeringData.GetBit(ccitt.Get() % steeringData.GetNumBits()) && + steeringData.GetBit(ansi.Get() % steeringData.GetNumBits())) + { + mJoinerUdpPort = aResult->mJoinerUdpPort; + mJoinerRouterPanId = aResult->mPanId; + mJoinerRouterChannel = aResult->mChannel; + memcpy(&mJoinerRouter, &aResult->mExtAddress, sizeof(mJoinerRouter)); + } } else { diff --git a/src/core/thread/meshcop_tlvs.hpp b/src/core/thread/meshcop_tlvs.hpp index 03be430a9..4a2955742 100644 --- a/src/core/thread/meshcop_tlvs.hpp +++ b/src/core/thread/meshcop_tlvs.hpp @@ -568,13 +568,27 @@ public: * @retval FALSE If the TLV does not appear to be well-formed. * */ - bool IsValid(void) const { return GetLength() == sizeof(*this) - sizeof(Tlv); } + bool IsValid(void) const { return GetLength() <= sizeof(*this) - sizeof(Tlv); } /** * This method sets all bits in the Bloom Filter to zero. * */ - void Clear(void) { memset(mSteeringData, 0, sizeof(mSteeringData)); } + void Clear(void) { memset(mSteeringData, 0, GetLength()); } + + /** + * Ths method sets all bits in the Bloom Filter to one. + * + */ + void Set(void) { memset(mSteeringData, 0xff, GetLength()); } + + /** + * This method returns the number of bits in the Bloom Filter. + * + * @returns The number of bits in the Bloom Filter. + * + */ + uint8_t GetNumBits(void) const { return GetLength() * 8; } /** * This method indicates whether or not bit @p aBit is set. @@ -585,7 +599,7 @@ public: * @retval FALSE If bit @p aBit is not set. * */ - bool GetBit(uint8_t aBit) const { return (mSteeringData[aBit / 8] & (1 << (aBit % 8))) != 0; } + bool GetBit(uint8_t aBit) const { return (mSteeringData[GetLength() - 1 - (aBit / 8)] & (1 << (aBit % 8))) != 0; } /** * This method clears bit @p aBit. @@ -593,7 +607,7 @@ public: * @param[in] aBit The bit offset. * */ - void ClearBit(uint8_t aBit) { mSteeringData[aBit / 8] &= ~(1 << (aBit % 8)); } + void ClearBit(uint8_t aBit) { mSteeringData[GetLength() - 1 - (aBit / 8)] &= ~(1 << (aBit % 8)); } /** * This method sets bit @p aBit. @@ -601,7 +615,7 @@ public: * @param[in] aBit The bit offset. * */ - void SetBit(uint8_t aBit) { mSteeringData[aBit / 8] |= 1 << (aBit % 8); } + void SetBit(uint8_t aBit) { mSteeringData[GetLength() - 1 - (aBit / 8)] |= 1 << (aBit % 8); } private: uint8_t mSteeringData[OT_STEERING_DATA_MAX_LENGTH]; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index d40324ac4..f23c321f5 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2406,6 +2406,8 @@ ThreadError Mle::SendDiscoveryResponse(const Ip6::Address &aDestination, uint16_ MeshCoP::ExtendedPanIdTlv extPanId; MeshCoP::NetworkNameTlv networkName; MeshCoP::JoinerUdpPortTlv joinerUdpPort; + uint8_t *cur; + uint8_t length; VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, ;); message->SetLinkSecurityEnabled(false); @@ -2434,6 +2436,25 @@ ThreadError Mle::SendDiscoveryResponse(const Ip6::Address &aDestination, uint16_ networkName.SetNetworkName(mMac.GetNetworkName()); SuccessOrExit(error = message->Append(&networkName, sizeof(tlv) + networkName.GetLength())); + // Steering Data TLV + if ((cur = mNetif.GetNetworkDataLeader().GetCommissioningData(length)) != NULL) + { + uint8_t *end = cur + length; + + while (cur < end) + { + MeshCoP::Tlv *meshcop = reinterpret_cast(cur); + + if (meshcop->GetType() == MeshCoP::Tlv::kSteeringData) + { + SuccessOrExit(message->Append(meshcop, sizeof(*meshcop) + meshcop->GetLength())); + break; + } + + cur += sizeof(*meshcop) + meshcop->GetLength(); + } + } + // Joiner UDP Port TLV joinerUdpPort.Init(); joinerUdpPort.SetUdpPort(mJoinerRouter.GetJoinerUdpPort()); @@ -2465,6 +2486,7 @@ ThreadError Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::Mes MeshCoP::DiscoveryResponseTlv discoveryResponse; MeshCoP::ExtendedPanIdTlv extPanId; MeshCoP::NetworkNameTlv networkName; + MeshCoP::SteeringDataTlv steeringData; MeshCoP::JoinerUdpPortTlv JoinerUdpPort; otActiveScanResult result; uint16_t offset; @@ -2528,6 +2550,13 @@ ThreadError Mle::HandleDiscoveryResponse(const Message &aMessage, const Ip6::Mes memcpy(&result.mNetworkName, networkName.GetNetworkName(), networkName.GetLength()); break; + case MeshCoP::Tlv::kSteeringData: + aMessage.Read(offset, sizeof(steeringData), &steeringData); + VerifyOrExit(steeringData.IsValid(), error = kThreadError_Parse); + result.mSteeringData.mLength = steeringData.GetLength(); + memcpy(result.mSteeringData.m8, steeringData.GetValue(), result.mSteeringData.mLength); + break; + case MeshCoP::Tlv::kJoinerUdpPort: aMessage.Read(offset, sizeof(JoinerUdpPort), &JoinerUdpPort); VerifyOrExit(JoinerUdpPort.IsValid(), error = kThreadError_Parse); diff --git a/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py b/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py index c3dda15e8..7d8d889df 100755 --- a/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py +++ b/tests/scripts/thread-cert/Cert_8_1_01_Commissioning.py @@ -60,7 +60,8 @@ class Cert_8_1_01_Commissioning(unittest.TestCase): time.sleep(5) self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader') self.nodes[COMMISSIONER].commissioner_start() - self.nodes[COMMISSIONER].commissioner_add_joiner('*', 'openthread') + time.sleep(3) + self.nodes[COMMISSIONER].commissioner_add_joiner(self.nodes[JOINER].get_hashmacaddr(), 'openthread') self.nodes[JOINER].interface_up() self.nodes[JOINER].joiner_start('openthread') diff --git a/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py b/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py index b54da808d..51d38f699 100755 --- a/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py +++ b/tests/scripts/thread-cert/Cert_8_1_02_Commissioning.py @@ -60,6 +60,7 @@ class Cert_8_1_02_Commissioning(unittest.TestCase): time.sleep(5) self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader') self.nodes[COMMISSIONER].commissioner_start() + time.sleep(3) self.nodes[COMMISSIONER].commissioner_add_joiner(self.nodes[JOINER].get_hashmacaddr(), 'openthread') self.nodes[JOINER].interface_up()