Skip to content

Commit

Permalink
[mac] update the cached supported channel mask when the region code c…
Browse files Browse the repository at this point in the history
…hanges (openthread#9418)

The current code of the `mac.cpp` caches the supported channel mask to
a local variable. But the supported channel mask may be changed after
the country code is changed. This will cause the supported channel
mask used in `mac.cpp` to be inconsistent with the actual supported
channel mask.

This commit adds an API `otLinkSetRegion()` to set the region code and
then update the cached supported channel mask to avoid the channel
mask inconsistencies. The current Thread channel may be not included
in the new supported channel mask. When the Thread stack detects this
case, it detaches the current Thread network gracefully.
  • Loading branch information
zhanglongxia authored Oct 24, 2023
1 parent d26f4e5 commit 4275c58
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 7 deletions.
33 changes: 33 additions & 0 deletions include/openthread/link.h
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,39 @@ bool otLinkIsCslSupported(otInstance *aInstance);
*/
otError otLinkSendEmptyData(otInstance *aInstance);

/**
* Sets the region code.
*
* The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char
* and the `aRegionCode & 0xff` is the second ascii char.
*
* @retval OT_ERROR_FAILED Other platform specific errors.
* @retval OT_ERROR_NONE Successfully set region code.
* @retval OT_ERROR_NOT_IMPLEMENTED The feature is not implemented.
*
*/
otError otLinkSetRegion(otInstance *aInstance, uint16_t aRegionCode);

/**
* Get the region code.
*
* The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
* @param[in] aInstance The OpenThread instance structure.
* @param[out] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char
* and the `aRegionCode & 0xff` is the second ascii char.
*
* @retval OT_ERROR_INVALID_ARGS @p aRegionCode is nullptr.
* @retval OT_ERROR_FAILED Other platform specific errors.
* @retval OT_ERROR_NONE Successfully got region code.
* @retval OT_ERROR_NOT_IMPLEMENTED The feature is not implemented.
*
*/
otError otLinkGetRegion(otInstance *aInstance, uint16_t *aRegionCode);

/**
* @}
*
Expand Down
3 changes: 2 additions & 1 deletion include/openthread/platform/radio.h
Original file line number Diff line number Diff line change
Expand Up @@ -1186,7 +1186,8 @@ otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aCh
* ISO 3166 alpha-2 code.
*
* @param[in] aInstance The OpenThread instance structure.
* @param[in] aRegionCode The radio region.
* @param[in] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char
* and the `aRegionCode & 0xff` is the second ascii char.
*
* @retval OT_ERROR_FAILED Other platform specific errors.
* @retval OT_ERROR_NONE Successfully set region code.
Expand Down
8 changes: 4 additions & 4 deletions src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6658,7 +6658,7 @@ template <> otError Interpreter::Process<Cmd("rcp")>(Arg aArgs[])
* Done
* @endcode
* @par api_copy
* #otPlatRadioGetRegion
* #otLinkGetRegion
*/
template <> otError Interpreter::Process<Cmd("region")>(Arg aArgs[])
{
Expand All @@ -6667,7 +6667,7 @@ template <> otError Interpreter::Process<Cmd("region")>(Arg aArgs[])

if (aArgs[0].IsEmpty())
{
SuccessOrExit(error = otPlatRadioGetRegion(GetInstancePtr(), &regionCode));
SuccessOrExit(error = otLinkGetRegion(GetInstancePtr(), &regionCode));
OutputLine("%c%c", regionCode >> 8, regionCode & 0xff);
}
/**
Expand All @@ -6677,7 +6677,7 @@ template <> otError Interpreter::Process<Cmd("region")>(Arg aArgs[])
* Done
* @endcode
* @par api_copy
* #otPlatRadioSetRegion
* #otLinkSetRegion
* @par
* Changing this can affect the transmit power limit.
*/
Expand All @@ -6688,7 +6688,7 @@ template <> otError Interpreter::Process<Cmd("region")>(Arg aArgs[])

regionCode = static_cast<uint16_t>(static_cast<uint16_t>(aArgs[0].GetCString()[0]) << 8) +
static_cast<uint16_t>(aArgs[0].GetCString()[1]);
error = otPlatRadioSetRegion(GetInstancePtr(), regionCode);
error = otLinkSetRegion(GetInstancePtr(), regionCode);
}

exit:
Expand Down
21 changes: 21 additions & 0 deletions src/core/api/link_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,3 +460,24 @@ otError otLinkSendEmptyData(otInstance *aInstance)
return AsCoreType(aInstance).Get<MeshForwarder>().SendEmptyMessage();
}
#endif

otError otLinkSetRegion(otInstance *aInstance, uint16_t aRegionCode)
{
return AsCoreType(aInstance).Get<Mac::Mac>().SetRegion(aRegionCode);
}

otError otLinkGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
{
Error error;

if (aRegionCode == nullptr)
{
error = kErrorInvalidArgs;
}
else
{
error = AsCoreType(aInstance).Get<Mac::Mac>().GetRegion(*aRegionCode);
}

return error;
}
19 changes: 17 additions & 2 deletions src/core/mac/mac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ void Mac::Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanD

if (aScanChannels == 0)
{
aScanChannels = GetSupportedChannelMask().GetMask();
aScanChannels = mSupportedChannelMask.GetMask();
}

mScanChannelMask.SetMask(aScanChannels);
Expand Down Expand Up @@ -474,7 +474,7 @@ void Mac::SetSupportedChannelMask(const ChannelMask &aMask)
{
ChannelMask newMask = aMask;

newMask.Intersect(ChannelMask(Get<Radio>().GetSupportedChannelMask()));
newMask.Intersect(mSupportedChannelMask);
IgnoreError(Get<Notifier>().Update(mSupportedChannelMask, newMask, kEventSupportedChannelMaskChanged));
}

Expand Down Expand Up @@ -2105,6 +2105,21 @@ void Mac::SetPromiscuous(bool aPromiscuous)
UpdateIdleMode();
}

Error Mac::SetRegion(uint16_t aRegionCode)
{
Error error;
ChannelMask oldMask = mSupportedChannelMask;

SuccessOrExit(error = Get<Radio>().SetRegion(aRegionCode));
mSupportedChannelMask.SetMask(Get<Radio>().GetSupportedChannelMask());
IgnoreError(Get<Notifier>().Update(oldMask, mSupportedChannelMask, kEventSupportedChannelMaskChanged));

exit:
return error;
}

Error Mac::GetRegion(uint16_t &aRegionCode) const { return Get<Radio>().GetRegion(aRegionCode); }

#if OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
const uint32_t *Mac::GetDirectRetrySuccessHistogram(uint8_t &aNumberOfEntries)
{
Expand Down
30 changes: 30 additions & 0 deletions src/core/mac/mac.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,36 @@ class Mac : public InstanceLocator, private NonCopyable
bool IsRadioFilterEnabled(void) const { return mLinks.GetSubMac().IsRadioFilterEnabled(); }
#endif

/**
* Sets the region code.
*
* The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
*
* @param[in] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char
* and the `aRegionCode & 0xff` is the second ascii char.
*
* @retval kErrorFailed Other platform specific errors.
* @retval kErrorNone Successfully set region code.
* @retval kErrorNotImplemented The feature is not implemented.
*
*/
Error SetRegion(uint16_t aRegionCode);

/**
* Get the region code.
*
* The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
*
* @param[out] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char
* and the `aRegionCode & 0xff` is the second ascii char.
*
* @retval kErrorFailed Other platform specific errors.
* @retval kErrorNone Successfully set region code.
* @retval kErrorNotImplemented The feature is not implemented.
*
*/
Error GetRegion(uint16_t &aRegionCode) const;

private:
static constexpr uint16_t kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW;

Expand Down
30 changes: 30 additions & 0 deletions src/core/radio/radio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,36 @@ class Radio : public InstanceLocator, private NonCopyable
((kChannelMin == aCslChannel) || ((kChannelMin < aCslChannel) && (aCslChannel <= kChannelMax))));
}

/**
* Sets the region code.
*
* The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
*
* @param[in] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char
* and the `aRegionCode & 0xff` is the second ascii char.
*
* @retval kErrorFailed Other platform specific errors.
* @retval kErrorNone Successfully set region code.
* @retval kErrorNotImplemented The feature is not implemented.
*
*/
Error SetRegion(uint16_t aRegionCode) { return otPlatRadioSetRegion(GetInstancePtr(), aRegionCode); }

/**
* Get the region code.
*
* The radio region format is the 2-bytes ascii representation of the ISO 3166 alpha-2 code.
*
* @param[out] aRegionCode The radio region code. The `aRegionCode >> 8` is first ascii char
* and the `aRegionCode & 0xff` is the second ascii char.
*
* @retval kErrorFailed Other platform specific errors.
* @retval kErrorNone Successfully set region code.
* @retval kErrorNotImplemented The feature is not implemented.
*
*/
Error GetRegion(uint16_t &aRegionCode) const { return otPlatRadioGetRegion(GetInstancePtr(), &aRegionCode); }

private:
otInstance *GetInstancePtr(void) const { return reinterpret_cast<otInstance *>(&InstanceLocator::GetInstance()); }

Expand Down
12 changes: 12 additions & 0 deletions src/core/thread/mle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,18 @@ void Mle::HandleNotifierEvents(Events aEvents)
}
#endif

if (aEvents.Contains(kEventSupportedChannelMaskChanged))
{
Mac::ChannelMask channelMask = Get<Mac::Mac>().GetSupportedChannelMask();

if (!channelMask.ContainsChannel(Get<Mac::Mac>().GetPanChannel()) && (mRole != kRoleDisabled))
{
LogWarn("Channel %u is not in the supported channel mask %s, detach the network gracefully!",
Get<Mac::Mac>().GetPanChannel(), channelMask.ToString().AsCString());
IgnoreError(DetachGracefully(nullptr, nullptr));
}
}

exit:
return;
}
Expand Down
34 changes: 34 additions & 0 deletions tests/scripts/expect/posix-channel-mask.exp
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,38 @@ send "channel preferred\n"
expect "0x1fff800"
expect_line "Done"

send "region US\n"
expect_line "Done"

send "channel supported\n"
expect "0x7fff800"
expect_line "Done"

send "dataset init new\n"
expect_line "Done"
send "dataset channel 26\n"
expect_line "Done"
send "dataset commit active\n"
expect_line "Done"

attach "leader"

send "channel\n"
expect "26"
expect_line "Done"

send "region WW\n"
expect_line "Done"

wait_for "state" "disabled"
expect_line "Done"

send "channel supported\n"
expect "0x3fff800"
expect_line "Done"

send "channel\n"
expect "26"
expect_line "Done"

dispose_node 1

0 comments on commit 4275c58

Please sign in to comment.