1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for generating and processing MLE TLVs. 32 */ 33 34 #ifndef MLE_TLVS_HPP_ 35 #define MLE_TLVS_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/encoding.hpp" 40 #include "common/message.hpp" 41 #include "common/preference.hpp" 42 #include "common/tlvs.hpp" 43 #include "meshcop/timestamp.hpp" 44 #include "net/ip6_address.hpp" 45 #include "thread/link_metrics_tlvs.hpp" 46 #include "thread/mle_types.hpp" 47 48 namespace ot { 49 50 namespace Mle { 51 52 /** 53 * @addtogroup core-mle-tlvs 54 * 55 * @brief 56 * This module includes definitions for generating and processing MLE TLVs. 57 * 58 * @{ 59 * 60 */ 61 62 /** 63 * Implements MLE TLV generation and parsing. 64 * 65 */ 66 OT_TOOL_PACKED_BEGIN 67 class Tlv : public ot::Tlv 68 { 69 public: 70 /** 71 * MLE TLV Types. 72 * 73 */ 74 enum Type : uint8_t 75 { 76 kSourceAddress = 0, ///< Source Address TLV 77 kMode = 1, ///< Mode TLV 78 kTimeout = 2, ///< Timeout TLV 79 kChallenge = 3, ///< Challenge TLV 80 kResponse = 4, ///< Response TLV 81 kLinkFrameCounter = 5, ///< Link-Layer Frame Counter TLV 82 kLinkQuality = 6, ///< Link Quality TLV 83 kNetworkParameter = 7, ///< Network Parameter TLV 84 kMleFrameCounter = 8, ///< MLE Frame Counter TLV 85 kRoute = 9, ///< Route64 TLV 86 kAddress16 = 10, ///< Address16 TLV 87 kLeaderData = 11, ///< Leader Data TLV 88 kNetworkData = 12, ///< Network Data TLV 89 kTlvRequest = 13, ///< TLV Request TLV 90 kScanMask = 14, ///< Scan Mask TLV 91 kConnectivity = 15, ///< Connectivity TLV 92 kLinkMargin = 16, ///< Link Margin TLV 93 kStatus = 17, ///< Status TLV 94 kVersion = 18, ///< Version TLV 95 kAddressRegistration = 19, ///< Address Registration TLV 96 kChannel = 20, ///< Channel TLV 97 kPanId = 21, ///< PAN ID TLV 98 kActiveTimestamp = 22, ///< Active Timestamp TLV 99 kPendingTimestamp = 23, ///< Pending Timestamp TLV 100 kActiveDataset = 24, ///< Active Operational Dataset TLV 101 kPendingDataset = 25, ///< Pending Operational Dataset TLV 102 kDiscovery = 26, ///< Thread Discovery TLV 103 kSupervisionInterval = 27, ///< Supervision Interval TLV 104 kCslChannel = 80, ///< CSL Channel TLV 105 kCslTimeout = 85, ///< CSL Timeout TLV 106 kCslClockAccuracy = 86, ///< CSL Clock Accuracy TLV 107 kLinkMetricsQuery = 87, ///< Link Metrics Query TLV 108 kLinkMetricsManagement = 88, ///< Link Metrics Management TLV 109 kLinkMetricsReport = 89, ///< Link Metrics Report TLV 110 kLinkProbe = 90, ///< Link Probe TLV 111 112 /** 113 * Applicable/Required only when time synchronization service 114 * (`OPENTHREAD_CONFIG_TIME_SYNC_ENABLE`) is enabled. 115 * 116 */ 117 kTimeRequest = 252, ///< Time Request TLV 118 kTimeParameter = 253, ///< Time Parameter TLV 119 kXtalAccuracy = 254, ///< XTAL Accuracy TLV 120 121 kInvalid = 255, 122 }; 123 124 /** 125 * Returns the Type value. 126 * 127 * @returns The Type value. 128 * 129 */ GetType(void) const130 Type GetType(void) const { return static_cast<Type>(ot::Tlv::GetType()); } 131 132 /** 133 * Sets the Type value. 134 * 135 * @param[in] aType The Type value. 136 * 137 */ SetType(Type aType)138 void SetType(Type aType) { ot::Tlv::SetType(static_cast<uint8_t>(aType)); } 139 140 } OT_TOOL_PACKED_END; 141 142 /** 143 * Defines Source Address TLV constants and types. 144 * 145 */ 146 typedef UintTlvInfo<Tlv::kSourceAddress, uint16_t> SourceAddressTlv; 147 148 /** 149 * Defines Mode TLV constants and types. 150 * 151 */ 152 typedef UintTlvInfo<Tlv::kMode, uint8_t> ModeTlv; 153 154 /** 155 * Defines Timeout TLV constants and types. 156 * 157 */ 158 typedef UintTlvInfo<Tlv::kTimeout, uint32_t> TimeoutTlv; 159 160 /** 161 * Defines Challenge TLV constants and types. 162 * 163 */ 164 typedef TlvInfo<Tlv::kChallenge> ChallengeTlv; 165 166 /** 167 * Defines Response TLV constants and types. 168 * 169 */ 170 typedef TlvInfo<Tlv::kResponse> ResponseTlv; 171 172 /** 173 * Defines Link Frame Counter TLV constants and types. 174 * 175 */ 176 typedef UintTlvInfo<Tlv::kLinkFrameCounter, uint32_t> LinkFrameCounterTlv; 177 178 /** 179 * Defines MLE Frame Counter TLV constants and types. 180 * 181 */ 182 typedef UintTlvInfo<Tlv::kMleFrameCounter, uint32_t> MleFrameCounterTlv; 183 184 /** 185 * Defines Address16 TLV constants and types. 186 * 187 */ 188 typedef UintTlvInfo<Tlv::kAddress16, uint16_t> Address16Tlv; 189 190 /** 191 * Defines Network Data TLV constants and types. 192 * 193 */ 194 typedef TlvInfo<Tlv::kNetworkData> NetworkDataTlv; 195 196 /** 197 * Defines TLV Request TLV constants and types. 198 * 199 */ 200 typedef TlvInfo<Tlv::kTlvRequest> TlvRequestTlv; 201 202 /** 203 * Defines Link Margin TLV constants and types. 204 * 205 */ 206 typedef UintTlvInfo<Tlv::kLinkMargin, uint8_t> LinkMarginTlv; 207 208 /** 209 * Defines Version TLV constants and types. 210 * 211 */ 212 typedef UintTlvInfo<Tlv::kVersion, uint16_t> VersionTlv; 213 214 /** 215 * Defines PAN ID TLV constants and types. 216 * 217 */ 218 typedef UintTlvInfo<Tlv::kPanId, uint16_t> PanIdTlv; 219 220 /** 221 * Defines Active Timestamp TLV constants and types. 222 * 223 */ 224 typedef SimpleTlvInfo<Tlv::kActiveTimestamp, MeshCoP::Timestamp> ActiveTimestampTlv; 225 226 /** 227 * Defines Pending Timestamp TLV constants and types. 228 * 229 */ 230 typedef SimpleTlvInfo<Tlv::kPendingTimestamp, MeshCoP::Timestamp> PendingTimestampTlv; 231 232 /** 233 * Defines Timeout TLV constants and types. 234 * 235 */ 236 typedef UintTlvInfo<Tlv::kSupervisionInterval, uint16_t> SupervisionIntervalTlv; 237 238 /** 239 * Defines CSL Timeout TLV constants and types. 240 * 241 */ 242 typedef UintTlvInfo<Tlv::kCslTimeout, uint32_t> CslTimeoutTlv; 243 244 /** 245 * Defines XTAL Accuracy TLV constants and types. 246 * 247 */ 248 typedef UintTlvInfo<Tlv::kXtalAccuracy, uint16_t> XtalAccuracyTlv; 249 250 #if !OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE 251 252 /** 253 * Implements Route TLV generation and parsing. 254 * 255 */ 256 OT_TOOL_PACKED_BEGIN 257 class RouteTlv : public Tlv, public TlvInfo<Tlv::kRoute> 258 { 259 public: 260 /** 261 * Initializes the TLV. 262 * 263 */ 264 void Init(void); 265 266 /** 267 * Indicates whether or not the TLV appears to be well-formed. 268 * 269 * @retval TRUE If the TLV appears to be well-formed. 270 * @retval FALSE If the TLV does not appear to be well-formed. 271 * 272 */ 273 bool IsValid(void) const; 274 275 /** 276 * Returns the Router ID Sequence value. 277 * 278 * @returns The Router ID Sequence value. 279 * 280 */ GetRouterIdSequence(void) const281 uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; } 282 283 /** 284 * Sets the Router ID Sequence value. 285 * 286 * @param[in] aSequence The Router ID Sequence value. 287 * 288 */ SetRouterIdSequence(uint8_t aSequence)289 void SetRouterIdSequence(uint8_t aSequence) { mRouterIdSequence = aSequence; } 290 291 /** 292 * Gets the Router ID Mask. 293 * 294 */ GetRouterIdMask(void) const295 const RouterIdSet &GetRouterIdMask(void) const { return mRouterIdMask; } 296 297 /** 298 * Sets the Router ID Mask. 299 * 300 * @param[in] aRouterIdSet The Router ID Mask to set. 301 * 302 */ SetRouterIdMask(const RouterIdSet & aRouterIdSet)303 void SetRouterIdMask(const RouterIdSet &aRouterIdSet) { mRouterIdMask = aRouterIdSet; } 304 305 /** 306 * Indicates whether or not a Router ID bit is set. 307 * 308 * @param[in] aRouterId The Router ID bit. 309 * 310 * @retval TRUE If the Router ID bit is set. 311 * @retval FALSE If the Router ID bit is not set. 312 * 313 */ IsRouterIdSet(uint8_t aRouterId) const314 bool IsRouterIdSet(uint8_t aRouterId) const { return mRouterIdMask.Contains(aRouterId); } 315 316 /** 317 * Indicates whether the `RouteTlv` is a singleton, i.e., only one router is allocated. 318 * 319 * @retval TRUE It is a singleton. 320 * @retval FALSE It is not a singleton. 321 * 322 */ IsSingleton(void) const323 bool IsSingleton(void) const { return IsValid() && (mRouterIdMask.GetNumberOfAllocatedIds() <= 1); } 324 325 /** 326 * Returns the Route Data Length value. 327 * 328 * @returns The Route Data Length value. 329 * 330 */ GetRouteDataLength(void) const331 uint8_t GetRouteDataLength(void) const { return GetLength() - sizeof(mRouterIdSequence) - sizeof(mRouterIdMask); } 332 333 /** 334 * Sets the Route Data Length value. 335 * 336 * @param[in] aLength The Route Data Length value. 337 * 338 */ SetRouteDataLength(uint8_t aLength)339 void SetRouteDataLength(uint8_t aLength) { SetLength(sizeof(mRouterIdSequence) + sizeof(mRouterIdMask) + aLength); } 340 341 /** 342 * Returns the Route Cost value for a given Router index. 343 * 344 * @param[in] aRouterIndex The Router index. 345 * 346 * @returns The Route Cost value for a given Router index. 347 * 348 */ GetRouteCost(uint8_t aRouterIndex) const349 uint8_t GetRouteCost(uint8_t aRouterIndex) const { return mRouteData[aRouterIndex] & kRouteCostMask; } 350 351 /** 352 * Returns the Link Quality In value for a given Router index. 353 * 354 * @param[in] aRouterIndex The Router index. 355 * 356 * @returns The Link Quality In value for a given Router index. 357 * 358 */ GetLinkQualityIn(uint8_t aRouterIndex) const359 LinkQuality GetLinkQualityIn(uint8_t aRouterIndex) const 360 { 361 return static_cast<LinkQuality>((mRouteData[aRouterIndex] & kLinkQualityInMask) >> kLinkQualityInOffset); 362 } 363 364 /** 365 * Returns the Link Quality Out value for a given Router index. 366 * 367 * @param[in] aRouterIndex The Router index. 368 * 369 * @returns The Link Quality Out value for a given Router index. 370 * 371 */ GetLinkQualityOut(uint8_t aRouterIndex) const372 LinkQuality GetLinkQualityOut(uint8_t aRouterIndex) const 373 { 374 return static_cast<LinkQuality>((mRouteData[aRouterIndex] & kLinkQualityOutMask) >> kLinkQualityOutOffset); 375 } 376 377 /** 378 * Sets the Route Data (Link Quality In/Out and Route Cost) for a given Router index. 379 * 380 * @param[in] aRouterIndex The Router index. 381 * @param[in] aLinkQualityIn The Link Quality In value. 382 * @param[in] aLinkQualityOut The Link Quality Out value. 383 * @param[in] aRouteCost The Route Cost value. 384 * 385 */ SetRouteData(uint8_t aRouterIndex,LinkQuality aLinkQualityIn,LinkQuality aLinkQualityOut,uint8_t aRouteCost)386 void SetRouteData(uint8_t aRouterIndex, LinkQuality aLinkQualityIn, LinkQuality aLinkQualityOut, uint8_t aRouteCost) 387 { 388 mRouteData[aRouterIndex] = (((aLinkQualityIn << kLinkQualityInOffset) & kLinkQualityInMask) | 389 ((aLinkQualityOut << kLinkQualityOutOffset) & kLinkQualityOutMask) | 390 ((aRouteCost << kRouteCostOffset) & kRouteCostMask)); 391 } 392 393 private: 394 static constexpr uint8_t kLinkQualityOutOffset = 6; 395 static constexpr uint8_t kLinkQualityOutMask = 3 << kLinkQualityOutOffset; 396 static constexpr uint8_t kLinkQualityInOffset = 4; 397 static constexpr uint8_t kLinkQualityInMask = 3 << kLinkQualityInOffset; 398 static constexpr uint8_t kRouteCostOffset = 0; 399 static constexpr uint8_t kRouteCostMask = 0xf << kRouteCostOffset; 400 401 uint8_t mRouterIdSequence; 402 RouterIdSet mRouterIdMask; 403 uint8_t mRouteData[kMaxRouterId + 1]; 404 } OT_TOOL_PACKED_END; 405 406 #else // OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE 407 408 /** 409 * Implements Route TLV generation and parsing. 410 * 411 */ 412 OT_TOOL_PACKED_BEGIN 413 class RouteTlv : public Tlv, public TlvInfo<Tlv::kRoute> 414 { 415 public: 416 /** 417 * Initializes the TLV. 418 * 419 */ Init(void)420 void Init(void) 421 { 422 SetType(kRoute); 423 SetLength(sizeof(*this) - sizeof(Tlv)); 424 } 425 426 /** 427 * Indicates whether or not the TLV appears to be well-formed. 428 * 429 * @retval TRUE If the TLV appears to be well-formed. 430 * @retval FALSE If the TLV does not appear to be well-formed. 431 * 432 */ IsValid(void) const433 bool IsValid(void) const { return GetLength() >= sizeof(mRouterIdSequence) + sizeof(mRouterIdMask); } 434 435 /** 436 * Returns the Router ID Sequence value. 437 * 438 * @returns The Router ID Sequence value. 439 * 440 */ GetRouterIdSequence(void) const441 uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; } 442 443 /** 444 * Sets the Router ID Sequence value. 445 * 446 * @param[in] aSequence The Router ID Sequence value. 447 * 448 */ SetRouterIdSequence(uint8_t aSequence)449 void SetRouterIdSequence(uint8_t aSequence) { mRouterIdSequence = aSequence; } 450 451 /** 452 * Gets the Router ID Mask. 453 * 454 */ GetRouterIdMask(void) const455 const RouterIdSet &GetRouterIdMask(void) const { return mRouterIdMask; } 456 457 /** 458 * Sets the Router ID Mask. 459 * 460 * @param[in] aRouterIdSet The Router ID Mask to set. 461 * 462 */ SetRouterIdMask(const RouterIdSet & aRouterIdSet)463 void SetRouterIdMask(const RouterIdSet &aRouterIdSet) { mRouterIdMask = aRouterIdSet; } 464 465 /** 466 * Indicates whether or not a Router ID bit is set. 467 * 468 * @param[in] aRouterId The Router ID. 469 * 470 * @retval TRUE If the Router ID bit is set. 471 * @retval FALSE If the Router ID bit is not set. 472 * 473 */ IsRouterIdSet(uint8_t aRouterId) const474 bool IsRouterIdSet(uint8_t aRouterId) const { return mRouterIdMask.Contains(aRouterId); } 475 476 /** 477 * Indicates whether the `RouteTlv` is a singleton, i.e., only one router is allocated. 478 * 479 * @retval TRUE It is a singleton. 480 * @retval FALSE It is not a singleton. 481 * 482 */ IsSingleton(void) const483 bool IsSingleton(void) const { return IsValid() && (mRouterIdMask.GetNumberOfAllocatedIds() <= 1); } 484 485 /** 486 * Sets the Router ID bit. 487 * 488 * @param[in] aRouterId The Router ID bit to set. 489 * 490 */ SetRouterId(uint8_t aRouterId)491 void SetRouterId(uint8_t aRouterId) { mRouterIdMask.Add(aRouterId); } 492 493 /** 494 * Returns the Route Data Length value. 495 * 496 * @returns The Route Data Length value in bytes 497 * 498 */ GetRouteDataLength(void) const499 uint8_t GetRouteDataLength(void) const { return GetLength() - sizeof(mRouterIdSequence) - sizeof(mRouterIdMask); } 500 501 /** 502 * Sets the Route Data Length value. 503 * 504 * @param[in] aLength The Route Data Length value in number of router entries 505 * 506 */ SetRouteDataLength(uint8_t aLength)507 void SetRouteDataLength(uint8_t aLength) 508 { 509 SetLength(sizeof(mRouterIdSequence) + sizeof(mRouterIdMask) + aLength + (aLength + 1) / 2); 510 } 511 512 /** 513 * Returns the Route Cost value for a given Router index. 514 * 515 * @param[in] aRouterIndex The Router index. 516 * 517 * @returns The Route Cost value for a given Router index. 518 * 519 */ GetRouteCost(uint8_t aRouterIndex) const520 uint8_t GetRouteCost(uint8_t aRouterIndex) const 521 { 522 if (aRouterIndex & 1) 523 { 524 return mRouteData[aRouterIndex + aRouterIndex / 2 + 1]; 525 } 526 else 527 { 528 return static_cast<uint8_t>((mRouteData[aRouterIndex + aRouterIndex / 2] & kRouteCostMask) 529 << kOddEntryOffset) | 530 ((mRouteData[aRouterIndex + aRouterIndex / 2 + 1] & 531 static_cast<uint8_t>(kRouteCostMask << kOddEntryOffset)) >> 532 kOddEntryOffset); 533 } 534 } 535 536 /** 537 * Returns the Link Quality In value for a given Router index. 538 * 539 * @param[in] aRouterIndex The Router index. 540 * 541 * @returns The Link Quality In value for a given Router index. 542 * 543 */ GetLinkQualityIn(uint8_t aRouterIndex) const544 LinkQuality GetLinkQualityIn(uint8_t aRouterIndex) const 545 { 546 int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0); 547 return static_cast<LinkQuality>( 548 (mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityInMask >> offset)) >> 549 (kLinkQualityInOffset - offset)); 550 } 551 552 /** 553 * Returns the Link Quality Out value for a given Router index. 554 * 555 * @param[in] aRouterIndex The Router index. 556 * 557 * @returns The Link Quality Out value for a given Router index. 558 * 559 */ GetLinkQualityOut(uint8_t aRouterIndex) const560 LinkQuality GetLinkQualityOut(uint8_t aRouterIndex) const 561 { 562 int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0); 563 return static_cast<LinkQuality>( 564 (mRouteData[aRouterIndex + aRouterIndex / 2] & (kLinkQualityOutMask >> offset)) >> 565 (kLinkQualityOutOffset - offset)); 566 } 567 568 /** 569 * Sets the Route Data (Link Quality In/Out and Route Cost) for a given Router index. 570 * 571 * @param[in] aRouterIndex The Router index. 572 * @param[in] aLinkQualityIn The Link Quality In value. 573 * @param[in] aLinkQualityOut The Link Quality Out value. 574 * @param[in] aRouteCost The Route Cost value. 575 * 576 */ SetRouteData(uint8_t aRouterIndex,LinkQuality aLinkQualityIn,LinkQuality aLinkQualityOut,uint8_t aRouteCost)577 void SetRouteData(uint8_t aRouterIndex, LinkQuality aLinkQualityIn, LinkQuality aLinkQualityOut, uint8_t aRouteCost) 578 { 579 SetLinkQualityIn(aRouterIndex, aLinkQualityIn); 580 SetLinkQualityOut(aRouterIndex, aLinkQualityOut); 581 SetRouteCost(aRouterIndex, aRouteCost); 582 } 583 584 private: 585 static constexpr uint8_t kLinkQualityOutOffset = 6; 586 static constexpr uint8_t kLinkQualityOutMask = 3 << kLinkQualityOutOffset; 587 static constexpr uint8_t kLinkQualityInOffset = 4; 588 static constexpr uint8_t kLinkQualityInMask = 3 << kLinkQualityInOffset; 589 static constexpr uint8_t kRouteCostOffset = 0; 590 static constexpr uint8_t kRouteCostMask = 0xf << kRouteCostOffset; 591 static constexpr uint8_t kOddEntryOffset = 4; 592 SetRouteCost(uint8_t aRouterIndex,uint8_t aRouteCost)593 void SetRouteCost(uint8_t aRouterIndex, uint8_t aRouteCost) 594 { 595 if (aRouterIndex & 1) 596 { 597 mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = aRouteCost; 598 } 599 else 600 { 601 mRouteData[aRouterIndex + aRouterIndex / 2] = 602 (mRouteData[aRouterIndex + aRouterIndex / 2] & ~kRouteCostMask) | 603 ((aRouteCost >> kOddEntryOffset) & kRouteCostMask); 604 mRouteData[aRouterIndex + aRouterIndex / 2 + 1] = static_cast<uint8_t>( 605 (mRouteData[aRouterIndex + aRouterIndex / 2 + 1] & ~(kRouteCostMask << kOddEntryOffset)) | 606 ((aRouteCost & kRouteCostMask) << kOddEntryOffset)); 607 } 608 } 609 SetLinkQualityIn(uint8_t aRouterIndex,uint8_t aLinkQuality)610 void SetLinkQualityIn(uint8_t aRouterIndex, uint8_t aLinkQuality) 611 { 612 int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0); 613 mRouteData[aRouterIndex + aRouterIndex / 2] = 614 (mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityInMask >> offset)) | 615 ((aLinkQuality << (kLinkQualityInOffset - offset)) & (kLinkQualityInMask >> offset)); 616 } 617 SetLinkQualityOut(uint8_t aRouterIndex,LinkQuality aLinkQuality)618 void SetLinkQualityOut(uint8_t aRouterIndex, LinkQuality aLinkQuality) 619 { 620 int offset = ((aRouterIndex & 1) ? kOddEntryOffset : 0); 621 mRouteData[aRouterIndex + aRouterIndex / 2] = 622 (mRouteData[aRouterIndex + aRouterIndex / 2] & ~(kLinkQualityOutMask >> offset)) | 623 ((aLinkQuality << (kLinkQualityOutOffset - offset)) & (kLinkQualityOutMask >> offset)); 624 } 625 626 uint8_t mRouterIdSequence; 627 RouterIdSet mRouterIdMask; 628 // Since we do hold 12 (compressible to 11) bits of data per router, each entry occupies 1.5 bytes, 629 // consecutively. First 4 bits are link qualities, remaining 8 bits are route cost. 630 uint8_t mRouteData[kMaxRouterId + 1 + kMaxRouterId / 2 + 1]; 631 } OT_TOOL_PACKED_END; 632 633 #endif // OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE 634 635 /** 636 * Implements Leader Data TLV generation and parsing. 637 * 638 */ 639 OT_TOOL_PACKED_BEGIN 640 class LeaderDataTlv : public Tlv, public TlvInfo<Tlv::kLeaderData> 641 { 642 public: 643 /** 644 * Initializes the TLV. 645 * 646 */ Init(void)647 void Init(void) 648 { 649 SetType(kLeaderData); 650 SetLength(sizeof(*this) - sizeof(Tlv)); 651 } 652 653 /** 654 * Indicates whether or not the TLV appears to be well-formed. 655 * 656 * @retval TRUE If the TLV appears to be well-formed. 657 * @retval FALSE If the TLV does not appear to be well-formed. 658 * 659 */ IsValid(void) const660 bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } 661 662 /** 663 * Gets the Leader Data info from TLV. 664 * 665 * @param[out] aLeaderData A reference to output Leader Data info. 666 * 667 */ Get(LeaderData & aLeaderData) const668 void Get(LeaderData &aLeaderData) const 669 { 670 aLeaderData.SetPartitionId(BigEndian::HostSwap32(mPartitionId)); 671 aLeaderData.SetWeighting(mWeighting); 672 aLeaderData.SetDataVersion(mDataVersion); 673 aLeaderData.SetStableDataVersion(mStableDataVersion); 674 aLeaderData.SetLeaderRouterId(mLeaderRouterId); 675 } 676 677 /** 678 * Sets the Leader Data. 679 * 680 * @param[in] aLeaderData A Leader Data. 681 * 682 */ Set(const LeaderData & aLeaderData)683 void Set(const LeaderData &aLeaderData) 684 { 685 mPartitionId = BigEndian::HostSwap32(aLeaderData.GetPartitionId()); 686 mWeighting = aLeaderData.GetWeighting(); 687 mDataVersion = aLeaderData.GetDataVersion(NetworkData::kFullSet); 688 mStableDataVersion = aLeaderData.GetDataVersion(NetworkData::kStableSubset); 689 mLeaderRouterId = aLeaderData.GetLeaderRouterId(); 690 } 691 692 private: 693 uint32_t mPartitionId; 694 uint8_t mWeighting; 695 uint8_t mDataVersion; 696 uint8_t mStableDataVersion; 697 uint8_t mLeaderRouterId; 698 } OT_TOOL_PACKED_END; 699 700 /** 701 * Implements Scan Mask TLV generation and parsing. 702 * 703 */ 704 class ScanMaskTlv : public UintTlvInfo<Tlv::kScanMask, uint8_t> 705 { 706 public: 707 static constexpr uint8_t kRouterFlag = 1 << 7; ///< Scan Mask Router Flag. 708 static constexpr uint8_t kEndDeviceFlag = 1 << 6; ///< Scan Mask End Device Flag. 709 710 /** 711 * Indicates whether or not the Router flag is set. 712 * 713 * @param[in] aMask A scan mask value. 714 * 715 * @retval TRUE If the Router flag is set. 716 * @retval FALSE If the Router flag is not set. 717 */ IsRouterFlagSet(uint8_t aMask)718 static bool IsRouterFlagSet(uint8_t aMask) { return (aMask & kRouterFlag) != 0; } 719 720 /** 721 * Indicates whether or not the End Device flag is set. 722 * 723 * @param[in] aMask A scan mask value. 724 * 725 * @retval TRUE If the End Device flag is set. 726 * @retval FALSE If the End Device flag is not set. 727 */ IsEndDeviceFlagSet(uint8_t aMask)728 static bool IsEndDeviceFlagSet(uint8_t aMask) { return (aMask & kEndDeviceFlag) != 0; } 729 }; 730 731 /** 732 * Implements Connectivity TLV generation and parsing. 733 * 734 */ 735 OT_TOOL_PACKED_BEGIN 736 class ConnectivityTlv : public Tlv, public TlvInfo<Tlv::kConnectivity> 737 { 738 public: 739 /** 740 * Initializes the TLV. 741 * 742 */ Init(void)743 void Init(void) 744 { 745 SetType(kConnectivity); 746 SetLength(sizeof(*this) - sizeof(Tlv)); 747 } 748 749 /** 750 * Indicates whether or not the TLV appears to be well-formed. 751 * 752 * @retval TRUE If the TLV appears to be well-formed. 753 * @retval FALSE If the TLV does not appear to be well-formed. 754 * 755 */ IsValid(void) const756 bool IsValid(void) const 757 { 758 return IsSedBufferingIncluded() || 759 (GetLength() == sizeof(*this) - sizeof(Tlv) - sizeof(mSedBufferSize) - sizeof(mSedDatagramCount)); 760 } 761 762 /** 763 * Indicates whether or not the sed buffer size and datagram count are included. 764 * 765 * @retval TRUE If the sed buffer size and datagram count are included. 766 * @retval FALSE If the sed buffer size and datagram count are not included. 767 * 768 */ IsSedBufferingIncluded(void) const769 bool IsSedBufferingIncluded(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } 770 771 /** 772 * Returns the Parent Priority value. 773 * 774 * @returns The Parent Priority value. 775 * 776 */ 777 int8_t GetParentPriority(void) const; 778 779 /** 780 * Sets the Parent Priority value. 781 * 782 * @param[in] aParentPriority The Parent Priority value. 783 * 784 */ 785 void SetParentPriority(int8_t aParentPriority); 786 787 /** 788 * Returns the Link Quality 3 value. 789 * 790 * @returns The Link Quality 3 value. 791 * 792 */ GetLinkQuality3(void) const793 uint8_t GetLinkQuality3(void) const { return mLinkQuality3; } 794 795 /** 796 * Sets the Link Quality 3 value. 797 * 798 * @param[in] aLinkQuality The Link Quality 3 value. 799 * 800 */ SetLinkQuality3(uint8_t aLinkQuality)801 void SetLinkQuality3(uint8_t aLinkQuality) { mLinkQuality3 = aLinkQuality; } 802 803 /** 804 * Returns the Link Quality 2 value. 805 * 806 * @returns The Link Quality 2 value. 807 * 808 */ GetLinkQuality2(void) const809 uint8_t GetLinkQuality2(void) const { return mLinkQuality2; } 810 811 /** 812 * Sets the Link Quality 2 value. 813 * 814 * @param[in] aLinkQuality The Link Quality 2 value. 815 * 816 */ SetLinkQuality2(uint8_t aLinkQuality)817 void SetLinkQuality2(uint8_t aLinkQuality) { mLinkQuality2 = aLinkQuality; } 818 819 /** 820 * Sets the Link Quality 1 value. 821 * 822 * @returns The Link Quality 1 value. 823 * 824 */ GetLinkQuality1(void) const825 uint8_t GetLinkQuality1(void) const { return mLinkQuality1; } 826 827 /** 828 * Sets the Link Quality 1 value. 829 * 830 * @param[in] aLinkQuality The Link Quality 1 value. 831 * 832 */ SetLinkQuality1(uint8_t aLinkQuality)833 void SetLinkQuality1(uint8_t aLinkQuality) { mLinkQuality1 = aLinkQuality; } 834 835 /** 836 * Increments the Link Quality N field in TLV for a given Link Quality N (1,2,3). 837 * 838 * The Link Quality N field specifies the number of neighboring router devices with which the sender shares a link 839 * of quality N. 840 * 841 * @param[in] aLinkQuality The Link Quality N (1,2,3) field to update. 842 * 843 */ 844 void IncrementLinkQuality(LinkQuality aLinkQuality); 845 846 /** 847 * Sets the Active Routers value. 848 * 849 * @returns The Active Routers value. 850 * 851 */ GetActiveRouters(void) const852 uint8_t GetActiveRouters(void) const { return mActiveRouters; } 853 854 /** 855 * Indicates whether or not the partition is a singleton based on Active Routers value. 856 * 857 * @retval TRUE The partition is a singleton. 858 * @retval FALSE The partition is not a singleton. 859 * 860 */ IsSingleton(void) const861 bool IsSingleton(void) const { return (mActiveRouters <= 1); } 862 863 /** 864 * Sets the Active Routers value. 865 * 866 * @param[in] aActiveRouters The Active Routers value. 867 * 868 */ SetActiveRouters(uint8_t aActiveRouters)869 void SetActiveRouters(uint8_t aActiveRouters) { mActiveRouters = aActiveRouters; } 870 871 /** 872 * Returns the Leader Cost value. 873 * 874 * @returns The Leader Cost value. 875 * 876 */ GetLeaderCost(void) const877 uint8_t GetLeaderCost(void) const { return mLeaderCost; } 878 879 /** 880 * Sets the Leader Cost value. 881 * 882 * @param[in] aCost The Leader Cost value. 883 * 884 */ SetLeaderCost(uint8_t aCost)885 void SetLeaderCost(uint8_t aCost) { mLeaderCost = aCost; } 886 887 /** 888 * Returns the ID Sequence value. 889 * 890 * @returns The ID Sequence value. 891 * 892 */ GetIdSequence(void) const893 uint8_t GetIdSequence(void) const { return mIdSequence; } 894 895 /** 896 * Sets the ID Sequence value. 897 * 898 * @param[in] aSequence The ID Sequence value. 899 * 900 */ SetIdSequence(uint8_t aSequence)901 void SetIdSequence(uint8_t aSequence) { mIdSequence = aSequence; } 902 903 /** 904 * Returns the SED Buffer Size value. 905 * 906 * @returns The SED Buffer Size value. 907 * 908 */ GetSedBufferSize(void) const909 uint16_t GetSedBufferSize(void) const 910 { 911 uint16_t buffersize = OPENTHREAD_CONFIG_DEFAULT_SED_BUFFER_SIZE; 912 913 if (IsSedBufferingIncluded()) 914 { 915 buffersize = BigEndian::HostSwap16(mSedBufferSize); 916 } 917 return buffersize; 918 } 919 920 /** 921 * Sets the SED Buffer Size value. 922 * 923 * @param[in] aSedBufferSize The SED Buffer Size value. 924 * 925 */ SetSedBufferSize(uint16_t aSedBufferSize)926 void SetSedBufferSize(uint16_t aSedBufferSize) { mSedBufferSize = BigEndian::HostSwap16(aSedBufferSize); } 927 928 /** 929 * Returns the SED Datagram Count value. 930 * 931 * @returns The SED Datagram Count value. 932 * 933 */ GetSedDatagramCount(void) const934 uint8_t GetSedDatagramCount(void) const 935 { 936 uint8_t count = OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT; 937 938 if (IsSedBufferingIncluded()) 939 { 940 count = mSedDatagramCount; 941 } 942 return count; 943 } 944 945 /** 946 * Sets the SED Datagram Count value. 947 * 948 * @param[in] aSedDatagramCount The SED Datagram Count value. 949 * 950 */ SetSedDatagramCount(uint8_t aSedDatagramCount)951 void SetSedDatagramCount(uint8_t aSedDatagramCount) { mSedDatagramCount = aSedDatagramCount; } 952 953 private: 954 static constexpr uint8_t kFlagsParentPriorityOffset = 6; 955 static constexpr uint8_t kFlagsParentPriorityMask = (3 << kFlagsParentPriorityOffset); 956 957 uint8_t mFlags; 958 uint8_t mLinkQuality3; 959 uint8_t mLinkQuality2; 960 uint8_t mLinkQuality1; 961 uint8_t mLeaderCost; 962 uint8_t mIdSequence; 963 uint8_t mActiveRouters; 964 uint16_t mSedBufferSize; 965 uint8_t mSedDatagramCount; 966 } OT_TOOL_PACKED_END; 967 968 /** 969 * Specifies Status TLV status values. 970 * 971 */ 972 struct StatusTlv : public UintTlvInfo<Tlv::kStatus, uint8_t> 973 { 974 /** 975 * Status values. 976 */ 977 enum Status : uint8_t 978 { 979 kError = 1, ///< Error. 980 }; 981 }; 982 983 /** 984 * Provides constants and methods for generation and parsing of Address Registration TLV. 985 * 986 */ 987 class AddressRegistrationTlv : public TlvInfo<Tlv::kAddressRegistration> 988 { 989 public: 990 /** 991 * This constant defines the control byte to use in an uncompressed entry where the full IPv6 address is included in 992 * the TLV. 993 * 994 */ 995 static constexpr uint8_t kControlByteUncompressed = 0; 996 997 /** 998 * Returns the control byte to use in a compressed entry where the 64-prefix is replaced with a 999 * 6LoWPAN context identifier. 1000 * 1001 * @param[in] aContextId The 6LoWPAN context ID. 1002 * 1003 * @returns The control byte associated with compressed entry with @p aContextId. 1004 * 1005 */ ControlByteFor(uint8_t aContextId)1006 static uint8_t ControlByteFor(uint8_t aContextId) { return kCompressed | (aContextId & kContextIdMask); } 1007 1008 /** 1009 * Indicates whether or not an address entry is using compressed format. 1010 * 1011 * @param[in] aControlByte The control byte (the first byte in the entry). 1012 * 1013 * @retval TRUE If the entry uses compressed format. 1014 * @retval FALSE If the entry uses uncompressed format. 1015 * 1016 */ IsEntryCompressed(uint8_t aControlByte)1017 static bool IsEntryCompressed(uint8_t aControlByte) { return (aControlByte & kCompressed); } 1018 1019 /** 1020 * Gets the context ID in a compressed entry. 1021 * 1022 * @param[in] aControlByte The control byte (the first byte in the entry). 1023 * 1024 * @returns The 6LoWPAN context ID. 1025 * 1026 */ GetContextId(uint8_t aControlByte)1027 static uint8_t GetContextId(uint8_t aControlByte) { return (aControlByte & kContextIdMask); } 1028 1029 AddressRegistrationTlv(void) = delete; 1030 1031 private: 1032 static constexpr uint8_t kCompressed = 1 << 7; 1033 static constexpr uint8_t kContextIdMask = 0xf; 1034 }; 1035 1036 /** 1037 * Implements Channel TLV value format. 1038 * 1039 * This is used by both Channel TLV and CSL Channel TLV. 1040 * 1041 */ 1042 OT_TOOL_PACKED_BEGIN 1043 class ChannelTlvValue 1044 { 1045 public: 1046 /** 1047 * Default constructor. 1048 * 1049 */ 1050 ChannelTlvValue(void) = default; 1051 1052 /** 1053 * Initializes the `ChannelTlvValue` with a given channel page and channel values. 1054 * 1055 * @param[in] aChannelPage The channel page. 1056 * @param[in] aChannel The channel. 1057 * 1058 */ ChannelTlvValue(uint8_t aChannelPage,uint16_t aChannel)1059 ChannelTlvValue(uint8_t aChannelPage, uint16_t aChannel) 1060 : mChannelPage(aChannelPage) 1061 , mChannel(BigEndian::HostSwap16(aChannel)) 1062 { 1063 } 1064 1065 /** 1066 * Initializes the `ChannelTlvValue` with zero channel page and a given channel value. 1067 * 1068 * @param[in] aChannel The channel. 1069 * 1070 */ ChannelTlvValue(uint16_t aChannel)1071 ChannelTlvValue(uint16_t aChannel) 1072 : ChannelTlvValue(0, aChannel) 1073 { 1074 } 1075 1076 /** 1077 * Returns the Channel Page value. 1078 * 1079 * @returns The Channel Page value. 1080 * 1081 */ GetChannelPage(void) const1082 uint8_t GetChannelPage(void) const { return mChannelPage; } 1083 1084 /** 1085 * Sets the Channel Page value. 1086 * 1087 * @param[in] aChannelPage The Channel Page value. 1088 * 1089 */ SetChannelPage(uint8_t aChannelPage)1090 void SetChannelPage(uint8_t aChannelPage) { mChannelPage = aChannelPage; } 1091 1092 /** 1093 * Returns the Channel value. 1094 * 1095 * @returns The Channel value. 1096 * 1097 */ GetChannel(void) const1098 uint16_t GetChannel(void) const { return BigEndian::HostSwap16(mChannel); } 1099 1100 /** 1101 * Sets the Channel value. 1102 * 1103 * @param[in] aChannel The Channel value. 1104 * 1105 */ SetChannel(uint16_t aChannel)1106 void SetChannel(uint16_t aChannel) { mChannel = BigEndian::HostSwap16(aChannel); } 1107 1108 /** 1109 * Sets the Channel and determines and sets the Channel Page from the given channel. 1110 * 1111 * @param[in] aChannel The Channel value. 1112 * 1113 */ 1114 void SetChannelAndPage(uint16_t aChannel); 1115 1116 /** 1117 * Indicates whether or not the Channel and Channel Page values are valid. 1118 * 1119 * @retval TRUE If the Channel and Channel Page values are valid. 1120 * @retval FALSE If the Channel and Channel Page values are not valid. 1121 * 1122 */ 1123 bool IsValid(void) const; 1124 1125 private: 1126 uint8_t mChannelPage; 1127 uint16_t mChannel; 1128 } OT_TOOL_PACKED_END; 1129 1130 /** 1131 * Defines Channel TLV constants and types. 1132 * 1133 */ 1134 typedef SimpleTlvInfo<Tlv::kChannel, ChannelTlvValue> ChannelTlv; 1135 1136 /** 1137 * Defines CSL Channel TLV constants and types. 1138 * 1139 */ 1140 typedef SimpleTlvInfo<Tlv::kCslChannel, ChannelTlvValue> CslChannelTlv; 1141 1142 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1143 /** 1144 * Defines Time Request TLV constants and types. 1145 * 1146 */ 1147 typedef TlvInfo<Tlv::kTimeRequest> TimeRequestTlv; 1148 1149 /** 1150 * Implements Time Parameter TLV generation and parsing. 1151 * 1152 */ 1153 OT_TOOL_PACKED_BEGIN 1154 class TimeParameterTlv : public Tlv, public TlvInfo<Tlv::kTimeParameter> 1155 { 1156 public: 1157 /** 1158 * Initializes the TLV. 1159 * 1160 */ Init(void)1161 void Init(void) 1162 { 1163 SetType(kTimeParameter); 1164 SetLength(sizeof(*this) - sizeof(Tlv)); 1165 } 1166 1167 /** 1168 * Indicates whether or not the TLV appears to be well-formed. 1169 * 1170 * @retval TRUE If the TLV appears to be well-formed. 1171 * @retval FALSE If the TLV does not appear to be well-formed. 1172 * 1173 */ IsValid(void) const1174 bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } 1175 1176 /** 1177 * Returns the time sync period. 1178 * 1179 * @returns The time sync period. 1180 * 1181 */ GetTimeSyncPeriod(void) const1182 uint16_t GetTimeSyncPeriod(void) const { return BigEndian::HostSwap16(mTimeSyncPeriod); } 1183 1184 /** 1185 * Sets the time sync period. 1186 * 1187 * @param[in] aTimeSyncPeriod The time sync period. 1188 * 1189 */ SetTimeSyncPeriod(uint16_t aTimeSyncPeriod)1190 void SetTimeSyncPeriod(uint16_t aTimeSyncPeriod) { mTimeSyncPeriod = BigEndian::HostSwap16(aTimeSyncPeriod); } 1191 1192 /** 1193 * Returns the XTAL accuracy threshold. 1194 * 1195 * @returns The XTAL accuracy threshold. 1196 * 1197 */ GetXtalThreshold(void) const1198 uint16_t GetXtalThreshold(void) const { return BigEndian::HostSwap16(mXtalThreshold); } 1199 1200 /** 1201 * Sets the XTAL accuracy threshold. 1202 * 1203 * @param[in] aXTALThreshold The XTAL accuracy threshold. 1204 * 1205 */ SetXtalThreshold(uint16_t aXtalThreshold)1206 void SetXtalThreshold(uint16_t aXtalThreshold) { mXtalThreshold = BigEndian::HostSwap16(aXtalThreshold); } 1207 1208 private: 1209 uint16_t mTimeSyncPeriod; 1210 uint16_t mXtalThreshold; 1211 } OT_TOOL_PACKED_END; 1212 1213 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE 1214 1215 #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 1216 /** 1217 * Implements CSL Clock Accuracy TLV generation and parsing. 1218 * 1219 */ 1220 OT_TOOL_PACKED_BEGIN 1221 class CslClockAccuracyTlv : public Tlv, public TlvInfo<Tlv::kCslClockAccuracy> 1222 { 1223 public: 1224 /** 1225 * Initializes the TLV. 1226 * 1227 */ Init(void)1228 void Init(void) 1229 { 1230 SetType(kCslClockAccuracy); 1231 SetLength(sizeof(*this) - sizeof(Tlv)); 1232 } 1233 1234 /** 1235 * Indicates whether or not the TLV appears to be well-formed. 1236 * 1237 * @retval TRUE If the TLV appears to be well-formed. 1238 * @retval FALSE If the TLV does not appear to be well-formed. 1239 * 1240 */ IsValid(void) const1241 bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); } 1242 1243 /** 1244 * Returns the CSL Clock Accuracy value. 1245 * 1246 * @returns The CSL Clock Accuracy value. 1247 * 1248 */ GetCslClockAccuracy(void) const1249 uint8_t GetCslClockAccuracy(void) const { return mCslClockAccuracy; } 1250 1251 /** 1252 * Sets the CSL Clock Accuracy value. 1253 * 1254 * @param[in] aCslClockAccuracy The CSL Clock Accuracy value. 1255 * 1256 */ SetCslClockAccuracy(uint8_t aCslClockAccuracy)1257 void SetCslClockAccuracy(uint8_t aCslClockAccuracy) { mCslClockAccuracy = aCslClockAccuracy; } 1258 1259 /** 1260 * Returns the Clock Uncertainty value. 1261 * 1262 * @returns The Clock Uncertainty value. 1263 * 1264 */ GetCslUncertainty(void) const1265 uint8_t GetCslUncertainty(void) const { return mCslUncertainty; } 1266 1267 /** 1268 * Sets the CSL Uncertainty value. 1269 * 1270 * @param[in] aCslUncertainty The CSL Uncertainty value. 1271 * 1272 */ SetCslUncertainty(uint8_t aCslUncertainty)1273 void SetCslUncertainty(uint8_t aCslUncertainty) { mCslUncertainty = aCslUncertainty; } 1274 1275 private: 1276 uint8_t mCslClockAccuracy; 1277 uint8_t mCslUncertainty; 1278 } OT_TOOL_PACKED_END; 1279 1280 #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 1281 /** 1282 * @} 1283 * 1284 */ 1285 1286 } // namespace Mle 1287 1288 } // namespace ot 1289 1290 #endif // MLE_TLVS_HPP_ 1291