Skip to content

Commit 444d1dd

Browse files
authored
[mle] implement alternate RLOC16 usage during role transition (openthread#10006)
This commit introduces a mechanism for a device transitioning from child to router role to keep receiving frames addressed to its previous short address for a brief period. A new radio platform API, `otPlatRadioSetAlternateShortAddress()`, is introduced. This allows the OT stack to configure an alternate short address. Radio platform support for this function is indicated by the `OT_RADIO_CAPS_ALT_SHORT_ADDR` capability in `otPlatRadioGetCaps()` The same function can be used with `OT_RADIO_INVALID_SHORT_ADDR` (`0xfffe`) to clear a previously set alternate short address. Support for the new API is implemented in RCP and `RadioSpinel`, ensuring backward compatibility by dynamically checking supported radio capabilities. MLE code is updated to instruct the radio to use the old child RLOC16 as an alternate address upon role transition. The MLE layer will automatically clear the alternate address after eight seconds, or if other state/mode changes occur. This eight-second window ensures the new router can transmit four MLE Advertisement messages.
1 parent a5e1c91 commit 444d1dd

35 files changed

+519
-28
lines changed

examples/platforms/simulation/radio.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,15 @@ void otPlatRadioSetShortAddress(otInstance *aInstance, otShortAddress aShortAddr
382382
sRadioContext.mShortAddress = aShortAddress;
383383
}
384384

385+
void otPlatRadioSetAlternateShortAddress(otInstance *aInstance, otShortAddress aShortAddress)
386+
{
387+
OT_UNUSED_VARIABLE(aInstance);
388+
389+
assert(aInstance != NULL);
390+
391+
sRadioContext.mAlternateShortAddress = aShortAddress;
392+
}
393+
385394
void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
386395
{
387396
OT_UNUSED_VARIABLE(aInstance);
@@ -849,9 +858,9 @@ void radioProcessFrame(otInstance *aInstance)
849858

850859
otEXPECT(sPromiscuous == false);
851860

852-
otEXPECT_ACTION(
853-
otMacFrameDoesAddrMatch(&sReceiveFrame, sPanid, sRadioContext.mShortAddress, &sRadioContext.mExtAddress),
854-
error = OT_ERROR_ABORT);
861+
otEXPECT_ACTION(otMacFrameDoesAddrMatchAny(&sReceiveFrame, sPanid, sRadioContext.mShortAddress,
862+
sRadioContext.mAlternateShortAddress, &sRadioContext.mExtAddress),
863+
error = OT_ERROR_ABORT);
855864

856865
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
857866
otEXPECT_ACTION(otMacFrameGetSrcAddr(&sReceiveFrame, &macAddress) == OT_ERROR_NONE, error = OT_ERROR_PARSE);

examples/platforms/utils/mac_frame.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
4141
otPanId aPanId,
4242
otShortAddress aShortAddress,
4343
const otExtAddress *aExtAddress)
44+
{
45+
return otMacFrameDoesAddrMatchAny(aFrame, aPanId, aShortAddress, Mac::kShortAddrInvalid, aExtAddress);
46+
}
47+
48+
bool otMacFrameDoesAddrMatchAny(const otRadioFrame *aFrame,
49+
otPanId aPanId,
50+
otShortAddress aShortAddress,
51+
otShortAddress aAltShortAddress,
52+
const otExtAddress *aExtAddress)
4453
{
4554
const Mac::Frame &frame = *static_cast<const Mac::Frame *>(aFrame);
4655
bool rval = true;
@@ -52,7 +61,9 @@ bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
5261
switch (dst.GetType())
5362
{
5463
case Mac::Address::kTypeShort:
55-
VerifyOrExit(dst.GetShort() == Mac::kShortAddrBroadcast || dst.GetShort() == aShortAddress, rval = false);
64+
VerifyOrExit(dst.GetShort() == Mac::kShortAddrBroadcast || dst.GetShort() == aShortAddress ||
65+
(aAltShortAddress != Mac::kShortAddrInvalid && dst.GetShort() == aAltShortAddress),
66+
rval = false);
5667
break;
5768

5869
case Mac::Address::kTypeExtended:

examples/platforms/utils/mac_frame.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,25 @@ bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
132132
otShortAddress aShortAddress,
133133
const otExtAddress *aExtAddress);
134134

135+
/**
136+
* Check if @p aFrame matches the @p aPandId and @p aShortAddress, or @p aAltShortAddress or @p aExtAddress.
137+
*
138+
* @param[in] aFrame A pointer to the frame.
139+
* @param[in] aPanId The PAN id to match with.
140+
* @param[in] aShortAddress The short address to match with.
141+
* @param[in] aAltShortAddress The alternate short address to match with. Can be `OT_RADIO_INVALID_SHORT_ADDR` if
142+
* there is no alternate address.
143+
* @param[in] aExtAddress The extended address to match with.
144+
*
145+
* @retval true It is a broadcast or matches with the PAN id and one of the addresses.
146+
* @retval false It doesn't match.
147+
*/
148+
bool otMacFrameDoesAddrMatchAny(const otRadioFrame *aFrame,
149+
otPanId aPanId,
150+
otShortAddress aShortAddress,
151+
otShortAddress aAltShortAddress,
152+
const otExtAddress *aExtAddress);
153+
135154
/**
136155
* Get source MAC address.
137156
*
@@ -319,6 +338,7 @@ typedef struct otRadioContext
319338
uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer.
320339
uint16_t mCslPeriod; ///< In unit of 10 symbols.
321340
otShortAddress mShortAddress;
341+
otShortAddress mAlternateShortAddress;
322342
otRadioKeyType mKeyType;
323343
uint8_t mKeyId;
324344
otMacKeyMaterial mPrevKey;

include/openthread/instance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extern "C" {
5252
*
5353
* @note This number versions both OpenThread platform and user APIs.
5454
*/
55-
#define OPENTHREAD_API_VERSION (460)
55+
#define OPENTHREAD_API_VERSION (461)
5656

5757
/**
5858
* @addtogroup api-instance

include/openthread/link.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,10 +588,19 @@ otError otLinkSetPollPeriod(otInstance *aInstance, uint32_t aPollPeriod);
588588
*
589589
* @param[in] aInstance A pointer to an OpenThread instance.
590590
*
591-
* @returns A pointer to the IEEE 802.15.4 Short Address.
591+
* @returns The IEEE 802.15.4 Short Address.
592592
*/
593593
otShortAddress otLinkGetShortAddress(otInstance *aInstance);
594594

595+
/**
596+
* Get the IEEE 802.15.4 alternate short address.
597+
*
598+
* @param[in] aInstance A pointer to an OpenThread instance.
599+
*
600+
* @returns The alternate short address, or `OT_RADIO_INVALID_SHORT_ADDR` (0xfffe) if there is no alternate address.
601+
*/
602+
otShortAddress otLinkGetAlternateShortAddress(otInstance *aInstance);
603+
595604
/**
596605
* Returns the maximum number of frame retries during direct transmission.
597606
*

include/openthread/link_raw.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,26 @@ otError otLinkRawSetPromiscuous(otInstance *aInstance, bool aEnable);
115115
*/
116116
otError otLinkRawSetShortAddress(otInstance *aInstance, uint16_t aShortAddress);
117117

118+
/**
119+
* Set the alternate short address.
120+
*
121+
* This is an optional API. Support for this is indicated by including the capability `OT_RADIO_CAPS_ALT_SHORT_ADDR` in
122+
* `otLinkRawGetCaps()`.
123+
*
124+
* When supported, the radio will accept received frames destined to the specified alternate short address in addition
125+
* to the short address provided in `otLinkRawSetShortAddress()`.
126+
*
127+
* The @p aShortAddress can be set to `OT_RADIO_INVALID_SHORT_ADDR` (0xfffe) to clear any previously set alternate
128+
* short address.
129+
*
130+
* @param[in] aInstance The OpenThread instance structure.
131+
* @param[in] aShortAddress The alternate short address. `OT_RADIO_INVALID_SHORT_ADDR` to clear.
132+
*
133+
* @retval OT_ERROR_NONE Successfully set the alternate short address.
134+
* @retval OT_ERROR_INVALID_STATE The raw link-layer is not enabled.
135+
*/
136+
otError otLinkRawSetAlternateShortAddress(otInstance *aInstance, otShortAddress aShortAddress);
137+
118138
/**
119139
* Transition the radio from Receive to Sleep.
120140
* Turn off the radio.

include/openthread/platform/radio.h

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ enum
8282
OT_RADIO_LQI_NONE = 0, ///< LQI measurement not supported
8383
OT_RADIO_RSSI_INVALID = 127, ///< Invalid or unknown RSSI value
8484
OT_RADIO_POWER_INVALID = 127, ///< Invalid or unknown power value
85+
86+
OT_RADIO_INVALID_SHORT_ADDR = 0xfffe, ///< Invalid short address.
87+
OT_RADIO_BROADCAST_SHORT_ADDR = 0xffff, ///< Broadcast short address.
8588
};
8689

8790
/**
@@ -120,17 +123,18 @@ typedef uint16_t otRadioCaps;
120123
*/
121124
enum
122125
{
123-
OT_RADIO_CAPS_NONE = 0, ///< Radio supports no capability.
124-
OT_RADIO_CAPS_ACK_TIMEOUT = 1 << 0, ///< Radio supports AckTime event.
125-
OT_RADIO_CAPS_ENERGY_SCAN = 1 << 1, ///< Radio supports Energy Scans.
126-
OT_RADIO_CAPS_TRANSMIT_RETRIES = 1 << 2, ///< Radio supports tx retry logic with collision avoidance (CSMA).
127-
OT_RADIO_CAPS_CSMA_BACKOFF = 1 << 3, ///< Radio supports CSMA backoff for frame transmission (but no retry).
128-
OT_RADIO_CAPS_SLEEP_TO_TX = 1 << 4, ///< Radio supports direct transition from sleep to TX with CSMA.
129-
OT_RADIO_CAPS_TRANSMIT_SEC = 1 << 5, ///< Radio supports tx security.
130-
OT_RADIO_CAPS_TRANSMIT_TIMING = 1 << 6, ///< Radio supports tx at specific time.
131-
OT_RADIO_CAPS_RECEIVE_TIMING = 1 << 7, ///< Radio supports rx at specific time.
132-
OT_RADIO_CAPS_RX_ON_WHEN_IDLE = 1 << 8, ///< Radio supports RxOnWhenIdle handling.
133-
OT_RADIO_CAPS_TRANSMIT_FRAME_POWER = 1 << 9, ///< Radio supports setting per-frame transmit power.
126+
OT_RADIO_CAPS_NONE = 0, ///< Radio supports no capability.
127+
OT_RADIO_CAPS_ACK_TIMEOUT = 1 << 0, ///< Radio supports AckTime event.
128+
OT_RADIO_CAPS_ENERGY_SCAN = 1 << 1, ///< Radio supports Energy Scans.
129+
OT_RADIO_CAPS_TRANSMIT_RETRIES = 1 << 2, ///< Radio supports tx retry logic with collision avoidance (CSMA).
130+
OT_RADIO_CAPS_CSMA_BACKOFF = 1 << 3, ///< Radio supports CSMA backoff for frame tx (but no retry).
131+
OT_RADIO_CAPS_SLEEP_TO_TX = 1 << 4, ///< Radio supports direct transition from sleep to TX with CSMA.
132+
OT_RADIO_CAPS_TRANSMIT_SEC = 1 << 5, ///< Radio supports tx security.
133+
OT_RADIO_CAPS_TRANSMIT_TIMING = 1 << 6, ///< Radio supports tx at specific time.
134+
OT_RADIO_CAPS_RECEIVE_TIMING = 1 << 7, ///< Radio supports rx at specific time.
135+
OT_RADIO_CAPS_RX_ON_WHEN_IDLE = 1 << 8, ///< Radio supports RxOnWhenIdle handling.
136+
OT_RADIO_CAPS_TRANSMIT_FRAME_POWER = 1 << 9, ///< Radio supports setting per-frame transmit power.
137+
OT_RADIO_CAPS_ALT_SHORT_ADDR = 1 << 10, ///< Radio supports setting alternate short address.
134138
};
135139

136140
#define OT_PANID_BROADCAST 0xffff ///< IEEE 802.15.4 Broadcast PAN ID
@@ -517,6 +521,26 @@ void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aE
517521
*/
518522
void otPlatRadioSetShortAddress(otInstance *aInstance, otShortAddress aShortAddress);
519523

524+
/**
525+
* Set the alternate short address.
526+
*
527+
* This is an optional radio platform API. The radio platform MUST indicate support for this API by including the
528+
* capability `OT_RADIO_CAPS_ALT_SHORT_ADDR` in `otPlatRadioGetCaps()`.
529+
*
530+
* When supported, the radio should accept received frames destined to the specified alternate short address in
531+
* addition to the short address provided in `otPlatRadioSetShortAddress()`.
532+
*
533+
* The @p aShortAddress can be set to `OT_RADIO_INVALID_SHORT_ADDR` (0xfffe) to clear any previously set alternate
534+
* short address.
535+
*
536+
* This function is used by OpenThread stack during child-to-router role transitions, allowing the device to continue
537+
* receiving frames addressed to its previous short address for a short period.
538+
*
539+
* @param[in] aInstance The OpenThread instance structure.
540+
* @param[in] aShortAddress The alternate IEEE 802.15.4 short address. `OT_RADIO_INVALID_SHORT_ADDR` to clear.
541+
*/
542+
void otPlatRadioSetAlternateShortAddress(otInstance *aInstance, otShortAddress aShortAddress);
543+
520544
/**
521545
* Get the radio's transmit power in dBm.
522546
*

src/cli/README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Done
7070
- [linkmetricsmgr](#linkmetricsmgr-disable)
7171
- [locate](#locate)
7272
- [log](#log-filename-filename)
73-
- [mac](#mac-retries-direct)
73+
- [mac](#mac-altshortaddr)
7474
- [macfilter](#macfilter)
7575
- [meshdiag](#meshdiag-topology-ip6-addrs-children)
7676
- [mliid](#mliid-iid)
@@ -4196,6 +4196,16 @@ Print API version number.
41964196
Done
41974197
```
41984198
4199+
### mac altshortaddr
4200+
4201+
Get the alternate short address used by MAC layer. Can be `0xfffe` if not set.
4202+
4203+
```bash
4204+
> mac altshortaddr
4205+
0x4801
4206+
Done
4207+
```
4208+
41994209
### mac retries direct
42004210
42014211
Get the number of direct TX retries on the MAC layer.

src/cli/cli.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7306,7 +7306,21 @@ template <> otError Interpreter::Process<Cmd("mac")>(Arg aArgs[])
73067306
{
73077307
otError error = OT_ERROR_NONE;
73087308

7309-
if (aArgs[0] == "retries")
7309+
/**
7310+
* @cli mac altshortaddr
7311+
* @code
7312+
* mac altshortaddr
7313+
* 0x4802
7314+
* Done
7315+
* @endcode
7316+
* @par api_copy
7317+
* otLinkGetAlternateShortAddress
7318+
*/
7319+
if (aArgs[0] == "altshortaddr")
7320+
{
7321+
OutputLine("0x%04x", otLinkGetAlternateShortAddress(GetInstancePtr()));
7322+
}
7323+
else if (aArgs[0] == "retries")
73107324
{
73117325
/**
73127326
* @cli mac retries direct (get,set)

src/core/api/link_api.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ otShortAddress otLinkGetShortAddress(otInstance *aInstance)
182182
return AsCoreType(aInstance).Get<Mac::Mac>().GetShortAddress();
183183
}
184184

185+
otShortAddress otLinkGetAlternateShortAddress(otInstance *aInstance)
186+
{
187+
return AsCoreType(aInstance).Get<Mac::Mac>().GetAlternateShortAddress();
188+
}
189+
185190
uint8_t otLinkGetMaxFrameRetriesDirect(otInstance *aInstance)
186191
{
187192
return AsCoreType(aInstance).Get<Mac::Mac>().GetMaxFrameRetriesDirect();

0 commit comments

Comments
 (0)