diff --git a/include/openthread-windows-config.h b/include/openthread-windows-config.h index 2327ee84d..9691efe9b 100644 --- a/include/openthread-windows-config.h +++ b/include/openthread-windows-config.h @@ -85,6 +85,9 @@ /* Define to 1 to enable Service feature. */ #define OPENTHREAD_ENABLE_SERVICE 0 +/* Define to 1 to enable long routes support. */ +#define OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES 0 + /* Name of package */ #define PACKAGE "openthread" diff --git a/src/core/openthread-core-default-config.h b/src/core/openthread-core-default-config.h index 001fbecc7..755b18a21 100644 --- a/src/core/openthread-core-default-config.h +++ b/src/core/openthread-core-default-config.h @@ -1749,4 +1749,15 @@ #endif #endif +/** + * @def OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES + * + * Enable experimental mode for 'deep' networks, allowing packet routes up to 32 nodes. + * This mode is incompatible with Thread 1.1.1 and older. + * + */ +#ifndef OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES +#define OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES 0 +#endif + #endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_ diff --git a/src/core/thread/mle_constants.hpp b/src/core/thread/mle_constants.hpp index ae07a48d0..3c1c7b1ac 100644 --- a/src/core/thread/mle_constants.hpp +++ b/src/core/thread/mle_constants.hpp @@ -91,13 +91,21 @@ enum */ enum { - kAdvertiseIntervalMin = 1, ///< ADVERTISEMENT_I_MIN (sec) - kAdvertiseIntervalMax = 32, ///< ADVERTISEMENT_I_MAX (sec) - kFailedRouterTransmissions = 4, ///< FAILED_ROUTER_TRANSMISSIONS - kRouterIdReuseDelay = 100, ///< ID_REUSE_DELAY (sec) - kRouterIdSequencePeriod = 10, ///< ID_SEQUENCE_PERIOD (sec) - kMaxNeighborAge = 100, ///< MAX_NEIGHBOR_AGE (sec) - kMaxRouteCost = 16, ///< MAX_ROUTE_COST + kAdvertiseIntervalMin = 1, ///< ADVERTISEMENT_I_MIN (sec) +#if OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES + kAdvertiseIntervalMax = 5, ///< ADVERTISEMENT_I_MAX (sec) proposal +#else + kAdvertiseIntervalMax = 32, ///< ADVERTISEMENT_I_MAX (sec) +#endif + kFailedRouterTransmissions = 4, ///< FAILED_ROUTER_TRANSMISSIONS + kRouterIdReuseDelay = 100, ///< ID_REUSE_DELAY (sec) + kRouterIdSequencePeriod = 10, ///< ID_SEQUENCE_PERIOD (sec) + kMaxNeighborAge = 100, ///< MAX_NEIGHBOR_AGE (sec) +#if OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES + kMaxRouteCost = 127, ///< MAX_ROUTE_COST proposal +#else + kMaxRouteCost = 16, ///< MAX_ROUTE_COST +#endif kMaxRouterId = 62, ///< MAX_ROUTER_ID kInvalidRouterId = kMaxRouterId + 1, ///< Value indicating incorrect Router Id kMaxRouters = OPENTHREAD_CONFIG_MAX_ROUTERS, ///< MAX_ROUTERS @@ -128,10 +136,10 @@ enum enum { - kLinkQuality3LinkCost = 1, ///< Link Cost for Link Quality 3 - kLinkQuality2LinkCost = 2, ///< Link Cost for Link Quality 2 - kLinkQuality1LinkCost = 4, ///< Link Cost for Link Quality 1 - kLinkQuality0LinkCost = 16, ///< Link Cost for Link Quality 0 + kLinkQuality3LinkCost = 1, ///< Link Cost for Link Quality 3 + kLinkQuality2LinkCost = 2, ///< Link Cost for Link Quality 2 + kLinkQuality1LinkCost = 4, ///< Link Cost for Link Quality 1 + kLinkQuality0LinkCost = kMaxRouteCost, ///< Link Cost for Link Quality 0 }; /** diff --git a/src/core/thread/mle_tlvs.hpp b/src/core/thread/mle_tlvs.hpp index dcee8f630..39e0739ae 100644 --- a/src/core/thread/mle_tlvs.hpp +++ b/src/core/thread/mle_tlvs.hpp @@ -473,6 +473,8 @@ private: uint32_t mFrameCounter; } OT_TOOL_PACKED_END; +#if !OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES + /** * This class implements Source Address TLV generation and parsing. * @@ -647,6 +649,222 @@ private: uint8_t mRouteData[kMaxRouterId + 1]; } OT_TOOL_PACKED_END; +#else // OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES + +/** + * This class implements Source Address TLV generation and parsing. + * + */ +OT_TOOL_PACKED_BEGIN +class RouteTlv : public Tlv +{ +public: + /** + * This method initializes the TLV. + * + */ + void Init(void) + { + SetType(kRoute); + SetLength(sizeof(*this) - sizeof(Tlv)); + } + + /** + * This method indicates whether or not the TLV appears to be well-formed. + * + * @retval TRUE If the TLV appears to be well-formed. + * @retval FALSE If the TLV does not appear to be well-formed. + * + */ + bool IsValid(void) const + { + return GetLength() >= sizeof(mRouterIdSequence) + sizeof(mRouterIdMask) && + GetLength() <= sizeof(*this) - sizeof(Tlv); + } + + /** + * This method returns the Router ID Sequence value. + * + * @returns The Router ID Sequence value. + * + */ + uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; } + + /** + * This method sets the Router ID Sequence value. + * + * @param[in] aSequence The Router ID Sequence value. + * + */ + void SetRouterIdSequence(uint8_t aSequence) { mRouterIdSequence = aSequence; } + + /** + * This method clears the Router ID Mask. + * + */ + void ClearRouterIdMask(void) { memset(mRouterIdMask, 0, sizeof(mRouterIdMask)); } + + /** + * This method indicates whether or not a Router ID bit is set. + * + * @param[in] aRouterId The Router ID. + * + * @retval TRUE If the Router ID bit is set. + * @retval FALSE If the Router ID bit is not set. + * + */ + bool IsRouterIdSet(uint8_t aRouterId) const + { + return (mRouterIdMask[aRouterId / 8] & (0x80 >> (aRouterId % 8))) != 0; + } + + /** + * This method sets the Router ID bit. + * + * @param[in] aRouterId The Router ID bit to set. + * + */ + void SetRouterId(uint8_t aRouterId) { mRouterIdMask[aRouterId / 8] |= 0x80 >> (aRouterId % 8); } + + /** + * This method returns the Route Data Length value. + * + * @returns The Route Data Length value in bytes + * + */ + uint8_t GetRouteDataLength(void) const { return GetLength() - sizeof(mRouterIdSequence) - sizeof(mRouterIdMask); } + + /** + * This method sets the Route Data Length value. + * + * @param[in] aLength The Route Data Length value in number of router entries + * + */ + void SetRouteDataLength(uint8_t aLength) + { + SetLength(sizeof(mRouterIdSequence) + sizeof(mRouterIdMask) + aLength + (aLength + 1) / 2); + } + + /** + * This method returns the Route Cost value for a given Router ID. + * + * @returns The Route Cost value for a given Router ID. + * + */ + uint8_t GetRouteCost(uint8_t aRouterId) const + { + if (aRouterId & 1) + { + return mRouteData[aRouterId + aRouterId / 2 + 1]; + } + else + { + return static_cast((mRouteData[aRouterId + aRouterId / 2] & kRouteCostMask) << kOddEntryOffset) | + ((mRouteData[aRouterId + aRouterId / 2 + 1] & + static_cast(kRouteCostMask << kOddEntryOffset)) >> + kOddEntryOffset); + } + } + + /** + * This method sets the Route Cost value for a given Router ID. + * + * @param[in] aRouterId The Router ID. + * @param[in] aRouteCost The Route Cost value. + * + */ + void SetRouteCost(uint8_t aRouterId, uint8_t aRouteCost) + { + if (aRouterId & 1) + { + mRouteData[aRouterId + aRouterId / 2 + 1] = aRouteCost; + } + else + { + mRouteData[aRouterId + aRouterId / 2] = (mRouteData[aRouterId + aRouterId / 2] & ~kRouteCostMask) | + ((aRouteCost >> kOddEntryOffset) & kRouteCostMask); + mRouteData[aRouterId + aRouterId / 2 + 1] = static_cast( + (mRouteData[aRouterId + aRouterId / 2 + 1] & ~(kRouteCostMask << kOddEntryOffset)) | + ((aRouteCost & kRouteCostMask) << kOddEntryOffset)); + } + } + + /** + * This method returns the Link Quality In value for a given Router ID. + * + * @returns The Link Quality In value for a given Router ID. + * + */ + uint8_t GetLinkQualityIn(uint8_t aRouterId) const + { + int offset = ((aRouterId & 1) ? kOddEntryOffset : 0); + return (mRouteData[aRouterId + aRouterId / 2] & (kLinkQualityInMask >> offset)) >> + (kLinkQualityInOffset - offset); + } + + /** + * This method sets the Link Quality In value for a given Router ID. + * + * @param[in] aRouterId The Router ID. + * @param[in] aLinkQuality The Link Quality In value for a given Router ID. + * + */ + void SetLinkQualityIn(uint8_t aRouterId, uint8_t aLinkQuality) + { + int offset = ((aRouterId & 1) ? kOddEntryOffset : 0); + mRouteData[aRouterId + aRouterId / 2] = + (mRouteData[aRouterId + aRouterId / 2] & ~(kLinkQualityInMask >> offset)) | + ((aLinkQuality << (kLinkQualityInOffset - offset)) & (kLinkQualityInMask >> offset)); + } + + /** + * This method returns the Link Quality Out value for a given Router ID. + * + * @returns The Link Quality Out value for a given Router ID. + * + */ + uint8_t GetLinkQualityOut(uint8_t aRouterId) const + { + int offset = ((aRouterId & 1) ? kOddEntryOffset : 0); + return (mRouteData[aRouterId + aRouterId / 2] & (kLinkQualityOutMask >> offset)) >> + (kLinkQualityOutOffset - offset); + } + + /** + * This method sets the Link Quality Out value for a given Router ID. + * + * @param[in] aRouterId The Router ID. + * @param[in] aLinkQuality The Link Quality Out value for a given Router ID. + * + */ + void SetLinkQualityOut(uint8_t aRouterId, uint8_t aLinkQuality) + { + int offset = ((aRouterId & 1) ? kOddEntryOffset : 0); + mRouteData[aRouterId + aRouterId / 2] = + (mRouteData[aRouterId + aRouterId / 2] & ~(kLinkQualityOutMask >> offset)) | + ((aLinkQuality << (kLinkQualityOutOffset - offset)) & (kLinkQualityOutMask >> offset)); + } + +private: + enum + { + kLinkQualityOutOffset = 6, + kLinkQualityOutMask = 3 << kLinkQualityOutOffset, + kLinkQualityInOffset = 4, + kLinkQualityInMask = 3 << kLinkQualityInOffset, + kRouteCostOffset = 0, + kRouteCostMask = 0xf << kRouteCostOffset, + kOddEntryOffset = 4, + }; + uint8_t mRouterIdSequence; + uint8_t mRouterIdMask[BitVectorBytes(kMaxRouterId + 1)]; + // Since we do hold 12 (compressable to 11) bits of data per router, each entry occupies 1.5 bytes, consecutively. + // First 4 bits are link qualities, remaining 8 bits are route cost. + uint8_t mRouteData[kMaxRouterId + 1 + kMaxRouterId / 2 + 1]; +} OT_TOOL_PACKED_END; + +#endif // OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES + /** * This class implements Source Address TLV generation and parsing. * diff --git a/src/core/thread/topology.hpp b/src/core/thread/topology.hpp index d2b154c6c..0d3367327 100644 --- a/src/core/thread/topology.hpp +++ b/src/core/thread/topology.hpp @@ -911,7 +911,12 @@ public: private: uint8_t mNextHop; ///< The next hop towards this router uint8_t mLinkQualityOut : 2; ///< The link quality out for this router - uint8_t mCost : 4; ///< The cost to this router via neighbor router + +#if OPENTHREAD_CONFIG_ENABLE_LONG_ROUTES + uint8_t mCost; ///< The cost to this router via neighbor router +#else + uint8_t mCost : 4; ///< The cost to this router via neighbor router +#endif }; } // namespace ot