mirror of
https://github.com/espressif/openthread.git
synced 2026-09-19 15:40:07 +00:00
[mac] update the cached supported channel mask when the region code changes (#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.
This commit is contained in:
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
|
||||
+4
-4
@@ -6658,7 +6658,7 @@ exit:
|
||||
* Done
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otPlatRadioGetRegion
|
||||
* #otLinkGetRegion
|
||||
*/
|
||||
template <> otError Interpreter::Process<Cmd("region")>(Arg aArgs[])
|
||||
{
|
||||
@@ -6667,7 +6667,7 @@ template <> otError Interpreter::Process<Cmd("region")>(Arg aArgs[])
|
||||
|
||||
if (aArgs[0].IsEmpty())
|
||||
{
|
||||
SuccessOrExit(error = otPlatRadioGetRegion(GetInstancePtr(), ®ionCode));
|
||||
SuccessOrExit(error = otLinkGetRegion(GetInstancePtr(), ®ionCode));
|
||||
OutputLine("%c%c", regionCode >> 8, regionCode & 0xff);
|
||||
}
|
||||
/**
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+17
-2
@@ -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);
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -720,6 +720,36 @@ public:
|
||||
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;
|
||||
|
||||
|
||||
@@ -733,6 +733,36 @@ public:
|
||||
((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()); }
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user