diff --git a/include/openthread-types.h b/include/openthread-types.h index 6657324b1..7bfa3a3d5 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -116,12 +116,16 @@ typedef enum ThreadError */ kThreadError_NotFound = 25, - /** * The operation is already in progress. */ kThreadError_Already = 26, + /** + * Received a frame filtered by the blacklist. + */ + kThreadError_BlacklistFiltered = 27, + kThreadError_Error = 255, } ThreadError; @@ -486,6 +490,16 @@ typedef struct otMacWhitelistEntry bool mFixedRssi : 1; ///< Indicates whether or not the RSSI value is fixed. } otMacWhitelistEntry; +/** + * This structure represents a blacklist entry. + * + */ +typedef struct otMacBlacklistEntry +{ + otExtAddress mExtAddress; ///< IEEE 802.15.4 Extended Address + bool mValid; ///< Indicates whether or not the blacklist entry is vaild +} otMacBlacklistEntry; + /** * @} * diff --git a/include/openthread.h b/include/openthread.h index 1a136614c..dfe5c6e6e 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -638,6 +638,24 @@ ThreadError otGetPendingDataset(otOperationalDataset *aDataset); */ ThreadError otSetPendingDataset(otOperationalDataset *aDataset); +/** + * Get the data poll period of sleepy end deivce. + * + * @returns The data poll period of sleepy end device. + * + * @sa otSetPollPeriod + */ +uint32_t otGetPollPeriod(void); + +/** + * Set the data poll period for sleepy end deivce. + * + * param[in] aPollPeriod data poll period. + * + * @sa otGetPollPeriod + */ +void otSetPollPeriod(uint32_t aPollPeriod); + /** * @} */ @@ -655,7 +673,7 @@ ThreadError otSetPendingDataset(otOperationalDataset *aDataset); /** * Get the Thread Leader Weight used when operating in the Leader role. * - * @returns The Thread Child Timeout value. + * @returns The Thread Leader Weight value. * * @sa otSetLeaderWeight */ @@ -670,6 +688,22 @@ uint8_t otGetLocalLeaderWeight(void); */ void otSetLocalLeaderWeight(uint8_t aWeight); +/** + * Get the Thread Leader Partition Id used when operating in the Leader role. + * + * @returns The Thread Leader Partition Id value. + * + */ +uint32_t otGetLocalLeaderPartitionId(void); + +/** + * Set the Thread Leader Partition Id used when operating in the Leader role. + * + * @param[in] aPartitionId The Thread Leader Partition Id value. + * + */ +void otSetLocalLeaderPartitionId(uint32_t aPartitionId); + /** * @} */ @@ -1026,6 +1060,124 @@ ThreadError otBecomeRouter(void); */ ThreadError otBecomeLeader(void); +/** + * Add an IEEE 802.15.4 Extended Address to the MAC blacklist. + * + * @param[in] aExtAddr A pointer to the IEEE 802.15.4 Extended Address. + * + * @retval kThreadErrorNone Successfully added to the MAC blacklist. + * @retval kThreadErrorNoBufs No buffers available for a new MAC blacklist entry. + * + * @sa otRemoveMacBlacklist + * @sa otClearMacBlacklist + * @sa otGetMacBlacklistEntry + * @sa otDisableMacBlacklist + * @sa otEnableMacBlacklist + */ +ThreadError otAddMacBlacklist(const uint8_t *aExtAddr); + +/** + * Remove an IEEE 802.15.4 Extended Address from the MAC blacklist. + * + * @param[in] aExtAddr A pointer to the IEEE 802.15.4 Extended Address. + * + * @sa otAddMacBlacklist + * @sa otClearMacBlacklist + * @sa otGetMacBlacklistEntry + * @sa otDisableMacBlacklist + * @sa otEnableMacBlacklist + */ +void otRemoveMacBlacklist(const uint8_t *aExtAddr); + +/** + * This function gets a MAC Blacklist entry. + * + * @param[in] aIndex An index into the MAC Blacklist table. + * @param[out] aEntry A pointer to where the information is placed. + * + * @retval kThreadError_None Successfully retrieved the MAC Blacklist entry. + * @retval kThreadError_InvalidArgs @p aIndex is out of bounds or @p aEntry is NULL. + * + */ +ThreadError otGetMacBlacklistEntry(uint8_t aIndex, otMacBlacklistEntry *aEntry); + +/** + * Remove all entries from the MAC Blacklist. + * + * @sa otAddMacBlacklist + * @sa otRemoveMacBlacklist + * @sa otGetMacBlacklistEntry + * @sa otDisableMacBlacklist + * @sa otEnableMacBlacklist + */ +void otClearMacBlacklist(void); + +/** + * Disable MAC blacklist filtering. + * + * + * @sa otAddMacBlacklist + * @sa otRemoveMacBlacklist + * @sa otClearMacBlacklist + * @sa otGetMacBlacklistEntry + * @sa otEnableMacBlacklist + */ +void otDisableMacBlacklist(void); + +/** + * Enable MAC Blacklist filtering. + * + * @sa otAddMacBlacklist + * @sa otRemoveMacBlacklist + * @sa otClearMacBlacklist + * @sa otGetMacBlacklistEntry + * @sa otDisableMacBlacklist + */ +void otEnableMacBlacklist(void); + +/** + * This function indicates whether or not the MAC Blacklist is enabled. + * + * @returns TRUE if the MAC Blacklist is enabled, FALSE otherwise. + * + * @sa otAddMacBlacklist + * @sa otRemoveMacBlacklist + * @sa otClearMacBlacklist + * @sa otGetMacBlacklistEntry + * @sa otDisableMacBlacklist + * @sa otEnableMacBlacklist + * + */ +bool otIsMacBlacklistEnabled(void); + +/** + * Get the assigned link quality which is on the link to a given extended address. + * + * @param[in] aExtAddr A pointer to the IEEE 802.15.4 Extended Address. + * @param[in] aLinkQuality A pointer to the assigned link quality. + * + * @retval kThreadError_None Successfully retrieved the link quality to aLinkQuality. + * @retval kThreadError_InvalidState No attached child matches with a given extended address. + * + * @sa otSetAssignLinkQuality + */ +ThreadError otGetAssignLinkQuality(const uint8_t *aExtAddr, uint8_t *aLinkQuality); + +/** + * Set the link quality which is on the link to a given extended address. + * + * @param[in] aExtAddr A pointer to the IEEE 802.15.4 Extended Address. + * @param[in] aLinkQuality The link quality to be set on the link. + * + * @sa otGetAssignLinkQuality + */ +void otSetAssignLinkQuality(const uint8_t *aExtAddr, uint8_t aLinkQuality); + +/** + * This method triggers platform reset. + */ +void otPlatformReset(void); + /** * @} * @@ -1150,6 +1302,14 @@ uint8_t otGetRouterIdSequence(void); */ ThreadError otGetRouterInfo(uint16_t aRouterId, otRouterInfo *aRouterInfo); +/** + * The function retains diagnostic information for a Thread Router as parent. + * + * @param[out] aParentInfo A pointer to where the parent router information is placed. + * + */ +ThreadError otGetParentInfo(otRouterInfo *aParentInfo); + /** * Get the Stable Network Data Version. * diff --git a/src/cli/README.md b/src/cli/README.md index 3d9379f80..dd58aa4f4 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -8,6 +8,7 @@ OpenThread test scripts use the CLI to execute test cases. ## OpenThread Command List * [channel](#channel) +* [blacklist](#blacklist) * [child](#child) * [childtimeout](#childtimeout) * [contextreusedelay](#contextreusedelay) @@ -19,16 +20,21 @@ OpenThread test scripts use the CLI to execute test cases. * [ifconfig](#ifconfig) * [ipaddr](#ipaddr) * [keysequence](#keysequence) +* [leaderpartitionid](#leaderpartitionid) * [leaderweight](#leaderweight) +* [linkquality](#linkquality) * [masterkey](#masterkey) * [mode](#mode) * [netdataregister](#netdataregister) * [networkidtimeout](#networkidtimeout) * [networkname](#networkname) * [panid](#panid) +* [parent](#parent) * [ping](#ping) +* [pollperiod](#pollperiod) * [prefix](#prefix) * [releaserouterid](#releaserouterid) +* [reset](#reset) * [rloc16](#rloc16) * [route](#route) * [router](#router) @@ -42,6 +48,62 @@ OpenThread test scripts use the CLI to execute test cases. ## OpenThread Command Details +### blacklist + +List the blacklist entries. + +```bash +> blacklist +Enabled +166e0a0000000002 +166e0a0000000003 +Done +``` + +### blacklist add \ + +Add an IEEE 802.15.4 Extended Address to the blacklist. + +```bash +> blacklist add 166e0a0000000002 +Done +``` + +### blacklist clear + +Clear all entries from the blacklist. + +```bash +> blacklist clear +Done +``` + +### blacklist disable + +Disable MAC blacklist filtering. + +```bash +> blacklist disable +Done +``` + +### blacklist enable + +Enable MAC blacklist filtering. + +```bash +> blacklist enable +Done +``` + +### blacklist remove \ + +Remove an IEEE 802.15.4 Extended Address from the blacklist. + +```bash +> blacklist remove 166e0a0000000002 +Done +``` ### channel Get the IEEE 802.15.4 Channel value. @@ -312,6 +374,25 @@ Set the Thread Key Sequence. Done ``` +### leaderpartitionid + +Get the Thread Leader Partition ID. + +```bash +> leaderpartitionid +4294967295 +Done +``` + +### leaderpartitionid \\ + +Set the Thread Leader Partition ID. + +```bash +> leaderpartitionid 0xffffffff +Done +``` + ### leaderweight Get the Thread Leader Weight. @@ -331,6 +412,25 @@ Set the Thread Leader Weight. Done ``` +### linkquality \\ + +Get the link quality on the link to a given extended address. + +```bash +> linkquality 36c1dd7a4f5201ff +3 +Done +``` + +### linkquality \\ \\ + +Set the link quality on the link to a given extended address. + +```bash +> linkquality 36c1dd7a4f5201ff 3 +Done +``` + ### masterkey Get the Thread Master Key value. @@ -445,6 +545,17 @@ Set the IEEE 802.15.4 PAN ID value. Done ``` +### parent + +Get the diagnostic information for a Thread Router as parent. + +```bash +> parent +Ext Addr: be1857c6c21dce55 +Rloc: 5c00 +Done +``` + ### ping \ [size] [count] [interval] Send an ICMPv6 Echo Request. @@ -454,6 +565,25 @@ Send an ICMPv6 Echo Request. 16 bytes from fdde:ad00:beef:0:558:f56b:d688:799: icmp_seq=1 hlim=64 time=28ms ``` +### pollperiod + +Get the data poll period of sleepy end device + +```bash +> pollperiod +240 +Done +``` + +### pollperiod \\ + +Set the data poll period for sleepy end device + +```bash +> pollperiod 240 +Done +``` + ### prefix add \ [pvdcsr] [prf] Add a valid prefix to the Network Data. @@ -483,11 +613,19 @@ Done ### releaserouterid \ Release a Router ID that has been allocated by the device in the Leader role. + ```bash > releaserouterid 16 Done ``` +### reset +Signal a platform reset. + +```bash +> reset +``` + ### rloc16 Get the Thread RLOC16 value. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index d43647c3c..5df10b8d6 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -53,6 +53,7 @@ namespace Cli { const struct Command Interpreter::sCommands[] = { { "help", &ProcessHelp }, + { "blacklist", &ProcessBlacklist }, { "channel", &ProcessChannel }, { "child", &ProcessChild }, { "childtimeout", &ProcessChildTimeout }, @@ -67,16 +68,21 @@ const struct Command Interpreter::sCommands[] = { "ipaddr", &ProcessIpAddr }, { "keysequence", &ProcessKeySequence }, { "leaderdata", &ProcessLeaderData }, + { "leaderpartitionid", &ProcessLeaderPartitionId }, { "leaderweight", &ProcessLeaderWeight }, + { "linkquality", &ProcessLinkQuality }, { "masterkey", &ProcessMasterKey }, { "mode", &ProcessMode }, { "netdataregister", &ProcessNetworkDataRegister }, { "networkidtimeout", &ProcessNetworkIdTimeout }, { "networkname", &ProcessNetworkName }, { "panid", &ProcessPanId }, + { "parent", &ProcessParent }, { "ping", &ProcessPing }, + { "pollperiod", &ProcessPollPeriod }, { "prefix", &ProcessPrefix }, { "releaserouterid", &ProcessReleaseRouterId }, + { "reset", &ProcessReset }, { "rloc16", &ProcessRloc16 }, { "route", &ProcessRoute }, { "router", &ProcessRouter }, @@ -192,6 +198,13 @@ ThreadError Interpreter::ParseLong(char *argv, long &value) return (*endptr == '\0') ? kThreadError_None : kThreadError_Parse; } +ThreadError Interpreter::ParseUnsignedLong(char *argv, unsigned long &value) +{ + char *endptr; + value = strtoul(argv, &endptr, 0); + return (*endptr == '\0') ? kThreadError_None : kThreadError_Parse; +} + void Interpreter::ProcessHelp(int argc, char *argv[]) { for (unsigned int i = 0; i < sizeof(sCommands) / sizeof(sCommands[0]); i++) @@ -203,6 +216,72 @@ void Interpreter::ProcessHelp(int argc, char *argv[]) (void)argv; } +void Interpreter::ProcessBlacklist(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + otMacBlacklistEntry entry; + int argcur = 0; + uint8_t extAddr[8]; + + if (argcur >= argc) + { + if (otIsMacBlacklistEnabled()) + { + sServer->OutputFormat("Enabled\r\n"); + } + else + { + sServer->OutputFormat("Disabled\r\n"); + } + + for (uint8_t i = 0; ; i++) + { + if (otGetMacBlacklistEntry(i, &entry) != kThreadError_None) + { + break; + } + + if (entry.mValid == false) + { + continue; + } + + OutputBytes(entry.mExtAddress.m8, OT_EXT_ADDRESS_SIZE); + + sServer->OutputFormat("\r\n"); + } + } + else if (strcmp(argv[argcur], "add") == 0) + { + VerifyOrExit(++argcur < argc, error = kThreadError_Parse); + VerifyOrExit(Hex2Bin(argv[argcur], extAddr, sizeof(extAddr)) == sizeof(extAddr), error = kThreadError_Parse); + + otAddMacBlacklist(extAddr); + VerifyOrExit(otAddMacBlacklist(extAddr) == kThreadError_None, error = kThreadError_Parse); + } + else if (strcmp(argv[argcur], "clear") == 0) + { + otClearMacBlacklist(); + } + else if (strcmp(argv[argcur], "disable") == 0) + { + otDisableMacBlacklist(); + } + else if (strcmp(argv[argcur], "enable") == 0) + { + otEnableMacBlacklist(); + } + else if (strcmp(argv[argcur], "remove") == 0) + { + VerifyOrExit(++argcur < argc, error = kThreadError_Parse); + VerifyOrExit(Hex2Bin(argv[argcur], extAddr, sizeof(extAddr)) == sizeof(extAddr), error = kThreadError_Parse); + otRemoveMacBlacklist(extAddr); + } + +exit: + AppendResult(error); +} + void Interpreter::ProcessChannel(int argc, char *argv[]) { ThreadError error = kThreadError_None; @@ -597,7 +676,7 @@ void Interpreter::ProcessLeaderData(int argc, char *argv[]) SuccessOrExit(error = otGetLeaderData(&leaderData)); - sServer->OutputFormat("Partition ID: %d\r\n", leaderData.mPartitionId); + sServer->OutputFormat("Partition ID: %u\r\n", leaderData.mPartitionId); sServer->OutputFormat("Weighting: %d\r\n", leaderData.mWeighting); sServer->OutputFormat("Data Version: %d\r\n", leaderData.mDataVersion); sServer->OutputFormat("Stable Data Version: %d\r\n", leaderData.mStableDataVersion); @@ -609,6 +688,25 @@ exit: AppendResult(error); } +void Interpreter::ProcessLeaderPartitionId(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + unsigned long value; + + if (argc == 0) + { + sServer->OutputFormat("%u\r\n", otGetLocalLeaderPartitionId()); + } + else + { + SuccessOrExit(error = ParseUnsignedLong(argv[0], value)); + otSetLocalLeaderPartitionId(static_cast(value)); + } + +exit: + AppendResult(error); +} + void Interpreter::ProcessLeaderWeight(int argc, char *argv[]) { ThreadError error = kThreadError_None; @@ -628,6 +726,31 @@ exit: AppendResult(error); } +void Interpreter::ProcessLinkQuality(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + uint8_t extAddress[8]; + uint8_t linkQuality; + long value; + + VerifyOrExit(Hex2Bin(argv[0], extAddress, OT_EXT_ADDRESS_SIZE) >= 0, error = kThreadError_Parse); + + if (argc == 1) + { + VerifyOrExit(otGetAssignLinkQuality(extAddress, &linkQuality) == kThreadError_None, + error = kThreadError_InvalidArgs); + sServer->OutputFormat("%d\r\n", linkQuality); + } + else + { + SuccessOrExit(error = ParseLong(argv[1], value)); + otSetAssignLinkQuality(extAddress, static_cast(value)); + } + +exit: + AppendResult(error); +} + void Interpreter::ProcessMasterKey(int argc, char *argv[]) { ThreadError error = kThreadError_None; @@ -790,6 +913,29 @@ exit: AppendResult(error); } +void Interpreter::ProcessParent(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + otRouterInfo parentInfo; + + SuccessOrExit(error = otGetParentInfo(&parentInfo)); + sServer->OutputFormat("Ext Addr: "); + + for (size_t i = 0; i < sizeof(parentInfo.mExtAddress); i++) + { + sServer->OutputFormat("%02x", parentInfo.mExtAddress.m8[i]); + } + + sServer->OutputFormat("\r\n"); + + sServer->OutputFormat("Rloc: %x\r\n", parentInfo.mRloc16); + +exit: + (void)argc; + (void)argv; + AppendResult(error); +} + void Interpreter::HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Ip6::IcmpHeader icmp6Header; @@ -887,6 +1033,25 @@ void Interpreter::HandlePingTimer(void *aContext) (void)aContext; } +void Interpreter::ProcessPollPeriod(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + long value; + + if (argc == 0) + { + sServer->OutputFormat("%d\r\n", otGetPollPeriod()); + } + else + { + SuccessOrExit(error = ParseLong(argv[0], value)); + otSetPollPeriod(static_cast(value)); + } + +exit: + AppendResult(error); +} + ThreadError Interpreter::ProcessPrefixAdd(int argc, char *argv[]) { ThreadError error = kThreadError_None; @@ -1048,6 +1213,13 @@ exit: AppendResult(error); } +void Interpreter::ProcessReset(int argc, char *argv[]) +{ + otPlatformReset(); + (void)argc; + (void)argv; +} + void Interpreter::ProcessRloc16(int argc, char *argv[]) { sServer->OutputFormat("%04x\r\n", otGetRloc16()); diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 2cb638926..ea76b7720 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -97,6 +97,18 @@ public: */ static ThreadError ParseLong(char *aString, long &aLong); + /** + * This method parses an ASCII string as an unsigned long. + * + * @param[in] aString A pointer to the ASCII string. + * @param[out] aUnsignedLong A reference to where the parsed unsigned long is placed. + * + * @retval kThreadError_None Successfully parsed the ASCII string. + * @retval kThreadError_Parse Could not parse the ASCII string. + * + */ + static ThreadError ParseUnsignedLong(char *aString, unsigned long &aUnsignedLong); + /** * This method converts a hex string to binary. * @@ -118,6 +130,7 @@ private: static void OutputBytes(const uint8_t *aBytes, uint8_t aLength); static void ProcessHelp(int argc, char *argv[]); + static void ProcessBlacklist(int argc, char *argv[]); static void ProcessChannel(int argc, char *argv[]); static void ProcessChild(int argc, char *argv[]); static void ProcessChildTimeout(int argc, char *argv[]); @@ -134,18 +147,23 @@ private: static ThreadError ProcessIpAddrDel(int argc, char *argv[]); static void ProcessKeySequence(int argc, char *argv[]); static void ProcessLeaderData(int argc, char *argv[]); + static void ProcessLeaderPartitionId(int argc, char *argv[]); static void ProcessLeaderWeight(int argc, char *argv[]); + static void ProcessLinkQuality(int argc, char *argv[]); static void ProcessMasterKey(int argc, char *argv[]); static void ProcessMode(int argc, char *argv[]); static void ProcessNetworkDataRegister(int argc, char *argv[]); static void ProcessNetworkIdTimeout(int argc, char *argv[]); static void ProcessNetworkName(int argc, char *argv[]); static void ProcessPanId(int argc, char *argv[]); + static void ProcessParent(int argc, char *argv[]); static void ProcessPing(int argc, char *argv[]); + static void ProcessPollPeriod(int argc, char *argv[]); static void ProcessPrefix(int argc, char *argv[]); static ThreadError ProcessPrefixAdd(int argc, char *argv[]); static ThreadError ProcessPrefixRemove(int argc, char *argv[]); static void ProcessReleaseRouterId(int argc, char *argv[]); + static void ProcessReset(int argc, char *argv[]); static void ProcessRoute(int argc, char *argv[]); static void ProcessRouter(int argc, char *argv[]); static ThreadError ProcessRouteAdd(int argc, char *argv[]); diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 5278263cf..11e9a6b36 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -47,6 +47,7 @@ libopenthread_a_SOURCES = \ mac/mac.cpp \ mac/mac_frame.cpp \ mac/mac_whitelist.cpp \ + mac/mac_blacklist.cpp \ net/icmp6.cpp \ net/ip6.cpp \ net/ip6_address.cpp \ @@ -90,6 +91,7 @@ noinst_HEADERS = \ mac/mac.hpp \ mac/mac_frame.hpp \ mac/mac_whitelist.hpp \ + mac/mac_blacklist.hpp \ net/icmp6.hpp \ net/ip6.hpp \ net/ip6_address.hpp \ diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 22dfb8739..dd8d3540e 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -74,7 +74,8 @@ Mac::Mac(ThreadNetif &aThreadNetif): mKeyManager(aThreadNetif.GetKeyManager()), mMle(aThreadNetif.GetMle()), mNetif(aThreadNetif), - mWhitelist() + mWhitelist(), + mBlacklist() { sMac = this; @@ -802,7 +803,8 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError) Address dstaddr; PanId panid; Neighbor *neighbor; - otMacWhitelistEntry *entry; + otMacWhitelistEntry *whitelistEntry; + otMacBlacklistEntry *blacklistEntry; int8_t rssi; ThreadError error = aError; @@ -847,14 +849,20 @@ void Mac::ReceiveDoneTask(Frame *aFrame, ThreadError aError) // Source Whitelist Processing if (srcaddr.mLength != 0 && mWhitelist.IsEnabled()) { - VerifyOrExit((entry = mWhitelist.Find(srcaddr.mExtAddress)) != NULL, error = kThreadError_WhitelistFiltered); + VerifyOrExit((whitelistEntry = mWhitelist.Find(srcaddr.mExtAddress)) != NULL, error = kThreadError_WhitelistFiltered); - if (mWhitelist.GetFixedRssi(*entry, rssi) == kThreadError_None) + if (mWhitelist.GetFixedRssi(*whitelistEntry, rssi) == kThreadError_None) { aFrame->mPower = rssi; } } + // Source Blacklist Processing + if (srcaddr.mLength != 0 && mBlacklist.IsEnabled()) + { + VerifyOrExit((blacklistEntry = mBlacklist.Find(srcaddr.mExtAddress)) == NULL, error = kThreadError_BlacklistFiltered); + } + // Destination Address Filtering aFrame->GetDstAddr(dstaddr); @@ -1044,6 +1052,11 @@ Whitelist &Mac::GetWhitelist(void) return mWhitelist; } +Blacklist &Mac::GetBlacklist(void) +{ + return mBlacklist; +} + otMacCounters &Mac::GetCounters(void) { return mCounters; diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index ccd442fa9..50a16cca7 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -363,6 +364,14 @@ public: */ Whitelist &GetWhitelist(void); + /** + * This method returns the MAC blacklist filter. + * + * @returns A reference to the MAC blacklist filter. + * + */ + Blacklist &GetBlacklist(void); + /** * This method is called to handle receive events. * @@ -493,6 +502,7 @@ private: otLinkPcapCallback mPcapCallback; Whitelist mWhitelist; + Blacklist mBlacklist; otMacCounters mCounters; }; diff --git a/src/core/mac/mac_blacklist.cpp b/src/core/mac/mac_blacklist.cpp new file mode 100644 index 000000000..0ba700f68 --- /dev/null +++ b/src/core/mac/mac_blacklist.cpp @@ -0,0 +1,148 @@ +/* + * 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 implements blacklist IEEE 802.15.4 frame filtering based on MAC address. + */ + +#include + +#include +#include + +namespace Thread { +namespace Mac { + +Blacklist::Blacklist(void) +{ + mEnabled = false; + + for (int i = 0; i < kMaxEntries; i++) + { + mBlacklist[i].mValid = false; + } +} + +void Blacklist::Enable(void) +{ + mEnabled = true; +} + +void Blacklist::Disable(void) +{ + mEnabled = false; +} + +bool Blacklist::IsEnabled(void) const +{ + return mEnabled; +} + +int Blacklist::GetMaxEntries(void) const +{ + return kMaxEntries; +} + +ThreadError Blacklist::GetEntry(uint8_t aIndex, Entry &aEntry) const +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aIndex < kMaxEntries, error = kThreadError_InvalidArgs); + + memcpy(&aEntry.mExtAddress, &mBlacklist[aIndex].mExtAddress, sizeof(aEntry.mExtAddress)); + aEntry.mValid = mBlacklist[aIndex].mValid; + +exit: + return error; +} + +Blacklist::Entry *Blacklist::Add(const ExtAddress &address) +{ + Entry *rval; + + VerifyOrExit((rval = Find(address)) == NULL, ;); + + for (int i = 0; i < kMaxEntries; i++) + { + if (mBlacklist[i].mValid) + { + continue; + } + + memcpy(&mBlacklist[i].mExtAddress, &address, sizeof(mBlacklist[i].mExtAddress)); + mBlacklist[i].mValid = true; + ExitNow(rval = &mBlacklist[i]); + } + +exit: + return rval; +} + +void Blacklist::Clear(void) +{ + for (int i = 0; i < kMaxEntries; i++) + { + mBlacklist[i].mValid = false; + } +} + +void Blacklist::Remove(const ExtAddress &address) +{ + Entry *entry; + + VerifyOrExit((entry = Find(address)) != NULL, ;); + memset(entry, 0, sizeof(*entry)); + +exit: + {} +} + +Blacklist::Entry *Blacklist::Find(const ExtAddress &address) +{ + Entry *rval = NULL; + + for (int i = 0; i < kMaxEntries; i++) + { + if (!mBlacklist[i].mValid) + { + continue; + } + + if (memcmp(&mBlacklist[i].mExtAddress, &address, sizeof(mBlacklist[i].mExtAddress)) == 0) + { + ExitNow(rval = &mBlacklist[i]); + } + } + +exit: + return rval; +} + +} // namespace Mac +} // namespace Thread diff --git a/src/core/mac/mac_blacklist.hpp b/src/core/mac/mac_blacklist.hpp new file mode 100644 index 000000000..94f70ff66 --- /dev/null +++ b/src/core/mac/mac_blacklist.hpp @@ -0,0 +1,161 @@ +/* + * 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 IEEE 802.15.4 frame filtering based on MAC address. + */ + +#ifndef MAC_BLACKLIST_HPP_ +#define MAC_BLACKLIST_HPP_ + +#include + +#include +#include + +namespace Thread { +namespace Mac { + +/** + * @addtogroup core-mac + * + * @{ + * + */ + +/** + * This class implements blacklist filtering on IEEE 802.15.4 frames. + * + */ +class Blacklist +{ +public: + typedef otMacBlacklistEntry Entry; + + enum + { + kMaxEntries = 32, + }; + + /** + * This constructor initializes the blacklist filter. + * + */ + Blacklist(void); + + /** + * This method enables the blacklist filter. + * + */ + void Enable(void); + + /** + * This method disables the blacklist filter. + * + */ + void Disable(void); + + /** + * This method indicates whether or not the blacklist filter is enabled. + * + * @retval TRUE If the blacklist filter is enabled. + * @retval FALSE If the blacklist filter is disabled. + * + */ + bool IsEnabled(void) const; + + /** + * This method returns the maximum number of blacklist entries. + * + * @returns The maximum number of blacklist entries. + * + */ + int GetMaxEntries(void) const; + + /** + * This method gets a blacklist entry. + * + * @param[in] aIndex An index into the MAC blacklist table. + * @param[out] aEntry A reference to where the information is placed. + * + * @retval kThreadError_None Successfully retrieved the MAC blacklist entry. + * @retval kThreadError_InvalidArgs @p aIndex is out of bounds or @p aEntry is NULL. + * + */ + ThreadError GetEntry(uint8_t aIndex, Entry &aEntry) const; + + /** + * This method adds an Extended Address to the blacklist filter. + * + * @param[in] aAddress A reference to the Extended Address. + * + * @returns A pointer to the blacklist entry or NULL if there are no available entries. + * + */ + Entry *Add(const ExtAddress &aAddress); + + /** + * This method removes an Extended Address to the blacklist filter. + * + * @param[in] aAddress A reference to the Extended Address. + * + */ + void Remove(const ExtAddress &aAddress); + + /** + * This method removes all entries from the blacklist filter. + * + */ + void Clear(void); + + /** + * This method finds a blacklist entry. + * + * @param[in] aAddress A reference to the Extended Address. + * + * @returns A pointer to the blacklist entry or NULL if the entry could not be found. + * + */ + Entry *Find(const ExtAddress &aAddress); + +private: + Entry mBlacklist[kMaxEntries]; + + bool mEnabled; +}; + +/** + * @} + * + */ + +} // namespace Mac +} // namespace Thread + +#endif // MAC_BLACKLIST_HPP_ diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index b25dcc4c5..235b184d4 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include namespace Thread { @@ -293,6 +294,16 @@ void otSetLocalLeaderWeight(uint8_t aWeight) sThreadNetif->GetMle().SetLeaderWeight(aWeight); } +uint32_t otGetLocalLeaderPartitionId(void) +{ + return sThreadNetif->GetMle().GetLeaderPartitionId(); +} + +void otSetLocalLeaderPartitionId(uint32_t aPartitionId) +{ + return sThreadNetif->GetMle().SetLeaderPartitionId(aPartitionId); +} + ThreadError otAddBorderRouter(const otBorderRouterConfig *aConfig) { uint8_t flags = 0; @@ -453,7 +464,7 @@ void otClearMacWhitelist(void) ThreadError otGetMacWhitelistEntry(uint8_t aIndex, otMacWhitelistEntry *aEntry) { - ThreadError error; + ThreadError error = kThreadError_None; VerifyOrExit(aEntry != NULL, error = kThreadError_InvalidArgs); error = sThreadNetif->GetMac().GetWhitelist().GetEntry(aIndex, *aEntry); @@ -497,6 +508,79 @@ ThreadError otBecomeLeader(void) return sThreadNetif->GetMle().BecomeLeader(); } +ThreadError otAddMacBlacklist(const uint8_t *aExtAddr) +{ + ThreadError error = kThreadError_None; + + if (sThreadNetif->GetMac().GetBlacklist().Add(*reinterpret_cast(aExtAddr)) == NULL) + { + error = kThreadError_NoBufs; + } + + return error; +} + +void otRemoveMacBlacklist(const uint8_t *aExtAddr) +{ + sThreadNetif->GetMac().GetBlacklist().Remove(*reinterpret_cast(aExtAddr)); +} + +void otClearMacBlacklist(void) +{ + sThreadNetif->GetMac().GetBlacklist().Clear(); +} + +ThreadError otGetMacBlacklistEntry(uint8_t aIndex, otMacBlacklistEntry *aEntry) +{ + ThreadError error = kThreadError_None; + + VerifyOrExit(aEntry != NULL, error = kThreadError_InvalidArgs); + error = sThreadNetif->GetMac().GetBlacklist().GetEntry(aIndex, *aEntry); + +exit: + return error; +} + +void otDisableMacBlacklist(void) +{ + sThreadNetif->GetMac().GetBlacklist().Disable(); +} + +void otEnableMacBlacklist(void) +{ + sThreadNetif->GetMac().GetBlacklist().Enable(); +} + +bool otIsMacBlacklistEnabled(void) +{ + return sThreadNetif->GetMac().GetBlacklist().IsEnabled(); +} + +ThreadError otGetAssignLinkQuality(const uint8_t *aExtAddr, uint8_t *aLinkQuality) +{ + Mac::ExtAddress extAddress; + + memset(&extAddress, 0, sizeof(extAddress)); + memcpy(extAddress.m8, aExtAddr, OT_EXT_ADDRESS_SIZE); + + return sThreadNetif->GetMle().GetAssignLinkQuality(extAddress, *aLinkQuality); +} + +void otSetAssignLinkQuality(const uint8_t *aExtAddr, uint8_t aLinkQuality) +{ + Mac::ExtAddress extAddress; + + memset(&extAddress, 0, sizeof(extAddress)); + memcpy(extAddress.m8, aExtAddr, OT_EXT_ADDRESS_SIZE); + + sThreadNetif->GetMle().SetAssignLinkQuality(extAddress, aLinkQuality); +} + +void otPlatformReset(void) +{ + otPlatReset(); +} + ThreadError otGetChildInfoById(uint16_t aChildId, otChildInfo *aChildInfo) { ThreadError error = kThreadError_None; @@ -616,6 +700,21 @@ exit: return error; } +ThreadError otGetParentInfo(otRouterInfo *aParentInfo) +{ + ThreadError error = kThreadError_None; + Router *parent; + + VerifyOrExit(aParentInfo != NULL, error = kThreadError_InvalidArgs); + + parent = sThreadNetif->GetMle().GetParent(); + memcpy(aParentInfo->mExtAddress.m8, parent->mMacAddr.m8, OT_EXT_ADDRESS_SIZE); + aParentInfo->mRloc16 = parent->mValid.mRloc16; + +exit: + return error; +} + uint8_t otGetStableNetworkDataVersion(void) { return sThreadNetif->GetMle().GetLeaderDataTlv().GetStableDataVersion(); @@ -692,6 +791,16 @@ const char *otGetVersionString(void) return sVersion; } +uint32_t otGetPollPeriod() +{ + return sThreadNetif->GetMeshForwarder().GetPollPeriod(); +} + +void otSetPollPeriod(uint32_t aPollPeriod) +{ + sThreadNetif->GetMeshForwarder().SetPollPeriod(aPollPeriod); +} + ThreadError otEnable(void) { ThreadError error = kThreadError_None; diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 21afbf7cd..0776d6f52 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -66,6 +66,7 @@ MeshForwarder::MeshForwarder(ThreadNetif &aThreadNetif): { mFragTag = static_cast(otPlatRandomGet()); mPollPeriod = 0; + mPollPeriodAssigned = false; mSendMessage = NULL; mSendBusy = false; mEnabled = false; @@ -573,12 +574,32 @@ void MeshForwarder::SetRxOnWhenIdle(bool aRxOnWhenIdle) void MeshForwarder::SetPollPeriod(uint32_t aPeriod) { - if (mMac.GetRxOnWhenIdle() == false && mPollPeriod != aPeriod) + if (!mNetif.IsUp()) + { + mPollPeriodAssigned = true; + mPollPeriod = aPeriod; + ExitNow(); + } + + if (mPollPeriodAssigned && mMac.GetRxOnWhenIdle() == false) + { + mPollTimer.Start(mPollPeriod); + ExitNow(); + } + else if (mMac.GetRxOnWhenIdle() == false && mPollPeriod != aPeriod) { mPollTimer.Start(aPeriod); } mPollPeriod = aPeriod; + +exit: + return; +} + +uint32_t MeshForwarder::GetPollPeriod() +{ + return mPollPeriod; } void MeshForwarder::HandlePollTimer(void *aContext) diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 1c0e8dac0..f3cf6a150 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -140,6 +140,14 @@ public: */ void SetPollPeriod(uint32_t aPeriod); + /** + * This method gets the Data Poll period. + * + * @returns The Data Poll period in milliseconds. + * + */ + uint32_t GetPollPeriod(void); + /** * This method sets the scan parameters for MLE Discovery Request messages. * @@ -209,6 +217,7 @@ private: uint16_t mFragTag; uint16_t mMessageNextOffset; uint32_t mPollPeriod; + bool mPollPeriodAssigned; Message *mSendMessage; Mac::Address mMacSource; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 9b75ef56a..5abea457b 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -143,6 +143,11 @@ Mle::Mle(ThreadNetif &aThreadNetif) : mNetifCallback.Set(&HandleNetifStateChanged, this); mNetif.RegisterCallback(mNetifCallback); + + isAssignLinkQuality = false; + mAssignLinkQuality = 0; + mAssignLinkMargin = 0; + memset(&mAddr64, 0, sizeof(mAddr64)); } ThreadError Mle::Enable(void) @@ -490,8 +495,12 @@ ThreadError Mle::SetRloc16(uint16_t aRloc16) if (aRloc16 != Mac::kShortAddrInvalid) { // link-local 16 - mLinkLocal16.GetAddress().mFields.m16[7] = HostSwap16(aRloc16); - mNetif.AddUnicastAddress(mLinkLocal16); + // add link-local 16 only for sleepy end device + if ((mDeviceMode & ModeTlv::kModeRxOnWhenIdle) == 0) + { + mLinkLocal16.GetAddress().mFields.m16[7] = HostSwap16(aRloc16); + mNetif.AddUnicastAddress(mLinkLocal16); + } // mesh-local 16 mMeshLocal16.GetAddress().mFields.m16[7] = HostSwap16(aRloc16); @@ -571,6 +580,49 @@ exit: return error; } +ThreadError Mle::GetAssignLinkQuality(const Mac::ExtAddress aMacAddr, uint8_t &aLinkQuality) +{ + ThreadError error; + + VerifyOrExit((memcmp(aMacAddr.m8, mAddr64.m8, OT_EXT_ADDRESS_SIZE)) == 0, error = kThreadError_InvalidArgs); + + aLinkQuality = mAssignLinkQuality; + + return kThreadError_None; + +exit: + return error; +} + +void Mle::SetAssignLinkQuality(const Mac::ExtAddress aMacAddr, uint8_t aLinkQuality) +{ + isAssignLinkQuality = true; + mAddr64 = aMacAddr; + + mAssignLinkQuality = aLinkQuality; + + switch (aLinkQuality) + { + case 3: + mAssignLinkMargin = 0xff; // 21 - 255 + break; + + case 2: + mAssignLinkMargin = 0x14; // 11 - 20 + break; + + case 1: + mAssignLinkMargin = 0x09; // 3 - 9 + break; + + case 0: + mAssignLinkMargin = 0x0; // 0 - 2 + + default: + break; + } +} + void Mle::GenerateNonce(const Mac::ExtAddress &aMacAddr, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce) { @@ -1763,6 +1815,15 @@ ThreadError Mle::HandleParentResponse(const Message &aMessage, const Ip6::Messag linkMargin = linkMarginTlv.GetLinkMargin(); } + // add for Thread Certification testing + if (isAssignLinkQuality) + { + linkMargin = linkMarginTlv.GetLinkMargin(); + + // clear flag for subsequent normal MLE message + isAssignLinkQuality = false; + } + linkQuality = LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMargin); VerifyOrExit(mParentRequestState != kParentRequestRouter || linkQuality == 3, ;); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 7bd2c0787..1c77d541d 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -623,6 +623,27 @@ public: */ ThreadError GetLeaderData(otLeaderData &aLeaderData); + /** + * This method returns the link quality on the link to a given extended address. + * + * @param[in] aMacAddr The IEEE 802.15.4 Extended Mac Address. + * @param[in] aLinkQuality A reference to the assigned link quality. + * + * @retval kThreadError_None Successfully retrieve the link quality to aLinkQuality. + * @retval kThreadError_InvalidArgs No match found with a given extended address. + * + */ + ThreadError GetAssignLinkQuality(const Mac::ExtAddress aMacAddr, uint8_t &aLinkQuality); + + /** + * This method sets the link quality on the link to a given extended address. + * + * @param[in] aMacAddr The IEEE 802.15.4 Extended Mac Address. + * @param[in] aLinkQaulity The link quality to be set on the link. + * + */ + void SetAssignLinkQuality(const Mac::ExtAddress aMacAddr, uint8_t aLinkQuality); + /** * This method returns the Child ID portion of an RLOC16. * @@ -1047,6 +1068,11 @@ protected: Router mParent; ///< Parent information. uint8_t mDeviceMode; ///< Device mode setting. + bool isAssignLinkQuality; ///< Indicating an assigned link quality is used on the link + uint8_t mAssignLinkQuality; ///< The assigned link quality value + uint8_t mAssignLinkMargin; ///< The maximum link margin corresponding to mAssignLinkQuality + Mac::ExtAddress mAddr64; ///< A given IEEE 802.15.4 Extended Address + /** * States when searching for a parent. * diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 482229c2f..c3f4e9453 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -64,6 +64,7 @@ MleRouter::MleRouter(ThreadNetif &aThreadNetif): mNetworkIdTimeout = kNetworkIdTimeout; mRouterUpgradeThreshold = kRouterUpgradeThreshold; mLeaderWeight = 0; + mFixedLeaderPartitionId = 0; mRouterId = kMaxRouterId; mPreviousRouterId = kMaxRouterId; mAdvertiseInterval = kAdvertiseIntervalMin; @@ -246,7 +247,15 @@ ThreadError MleRouter::BecomeLeader(void) memcpy(&mRouters[mRouterId].mMacAddr, mMac.GetExtAddress(), sizeof(mRouters[mRouterId].mMacAddr)); - SetLeaderData(otPlatRandomGet(), mLeaderWeight, mRouterId); + if (mFixedLeaderPartitionId != 0) + { + SetLeaderData(mFixedLeaderPartitionId, mLeaderWeight, mRouterId); + } + else + { + SetLeaderData(otPlatRandomGet(), mLeaderWeight, mRouterId); + } + mRouterIdSequence = static_cast(otPlatRandomGet()); mNetworkData.Reset(); @@ -1674,7 +1683,18 @@ ThreadError MleRouter::SendParentResponse(Child *aChild, const ChallengeTlv &cha } SuccessOrExit(error = AppendChallenge(*message, aChild->mPending.mChallenge, sizeof(aChild->mPending.mChallenge))); - SuccessOrExit(error = AppendLinkMargin(*message, aChild->mLinkInfo.GetLinkMargin())); + + if (isAssignLinkQuality && + (memcmp(mAddr64.m8, aChild->mMacAddr.m8, OT_EXT_ADDRESS_SIZE) == 0)) + { + // use assigned one to ensure the link quality + SuccessOrExit(error = AppendLinkMargin(*message, mAssignLinkMargin)); + } + else + { + SuccessOrExit(error = AppendLinkMargin(*message, aChild->mLinkInfo.GetLinkMargin())); + } + SuccessOrExit(error = AppendConnectivity(*message)); SuccessOrExit(error = AppendVersion(*message)); @@ -2504,6 +2524,16 @@ void MleRouter::SetLeaderWeight(uint8_t aWeight) mLeaderWeight = aWeight; } +uint32_t MleRouter::GetLeaderPartitionId(void) const +{ + return mFixedLeaderPartitionId; +} + +void MleRouter::SetLeaderPartitionId(uint32_t aPartitionId) +{ + mFixedLeaderPartitionId = aPartitionId; +} + void MleRouter::HandleMacDataRequest(const Child &aChild) { static const uint8_t tlvs[] = {Tlv::kLeaderData, Tlv::kNetworkData}; diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 1eec9ac45..a1c9692d2 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -149,6 +149,22 @@ public: */ void SetLeaderWeight(uint8_t aWeight); + /** + * This method returns the fixed Partition Id of Thread network partition for certification testing. + * + * @returns The Partition Id for this Thread network partition. + * + */ + uint32_t GetLeaderPartitionId(void) const; + + /** + * This method sets the fixed Partition Id for Thread network partition for certification testing. + * + * @param[in] aPartitionId The Leader Partition Id. + * + */ + void SetLeaderPartitionId(uint32_t aPartitionId); + /** * This method returns the next hop towards an RLOC16 destination. * @@ -490,6 +506,7 @@ private: uint8_t mNetworkIdTimeout; uint8_t mRouterUpgradeThreshold; uint8_t mLeaderWeight; + uint32_t mFixedLeaderPartitionId; ///< only for certification testing bool mRouterRoleEnabled; uint8_t mRouterId;