[mle] support for long routes (#2775)

This commit introduces changes necessary to support long routes (i.e. route
cost >= 16).

This is an experimental feature that requires changes to the route
information communicated in MLE messages.  As a result, it is not compatible
with the Thread 1.1 specification.

This feature is disabled by default.
This commit is contained in:
Kamil Burzynski
2018-07-26 02:14:49 -05:00
committed by Jonathan Hui
parent bb064cd074
commit c7e62553e5
5 changed files with 257 additions and 12 deletions
+3
View File
@@ -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"
+11
View File
@@ -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_
+19 -11
View File
@@ -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
};
/**
+218
View File
@@ -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<uint8_t>((mRouteData[aRouterId + aRouterId / 2] & kRouteCostMask) << kOddEntryOffset) |
((mRouteData[aRouterId + aRouterId / 2 + 1] &
static_cast<uint8_t>(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<uint8_t>(
(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.
*
+6 -1
View File
@@ -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