mirror of
https://github.com/espressif/openthread.git
synced 2026-08-07 19:27:46 +00:00
[mac] tracking supported channel mask (#2838)
This commit contains the following changes: - Adds new logic to `Mac` to track supported channel mask along get/set methods. - Adds public OT APIs `otLinkGetSupportedChannelMask()` and `otLinkSetSupportedChannelMask()` to get/set the channel mask. - Ensures supported channel mask from `Mac` is included in Dataset TLVs when a local Dataset is generated. - Ensures the channel mask at `Mac` gets updated when a new Dataset configuration is applied. - Adds `OT_CHANGED` notification for signaling channel mask changes. - Updates `NcpBase` and `PHY_CHAN_SUPPORTED` spinel property get/set handlers to adopt the new public APIs. - Updates `NcpBase` to emit async `PHY_CHAN_SUPPORTED` updated on OT_CHANGED channel mask notification.
This commit is contained in:
committed by
Jonathan Hui
parent
fdb3d0ef58
commit
31698ecaf7
@@ -248,6 +248,7 @@ enum
|
||||
OT_CHANGED_PSKC = 1 << 21, ///< PSKc changed
|
||||
OT_CHANGED_SECURITY_POLICY = 1 << 22, ///< Security Policy changed
|
||||
OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL = 1 << 23, ///< Channel Manager new pending Thread channel changed
|
||||
OT_CHANGED_SUPPORTED_CHANNEL_MASK = 1 << 24, ///< Supported channel mask changed
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -189,7 +189,7 @@ OTAPI uint8_t OTCALL otLinkGetChannel(otInstance *aInstance);
|
||||
* @param[in] aChannel The IEEE 802.15.4 channel.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the channel.
|
||||
* @retval OT_ERROR_INVALID_ARGS If @p aChnanel is not in the range [11, 26].
|
||||
* @retval OT_ERROR_INVALID_ARGS If @p aChannel is not in the range [11, 26] or is not in the supported channel mask.
|
||||
* @retval OT_ERROR_INVALID_STATE Thread protocols are enabled.
|
||||
*
|
||||
* @sa otLinkGetChannel
|
||||
@@ -197,6 +197,30 @@ OTAPI uint8_t OTCALL otLinkGetChannel(otInstance *aInstance);
|
||||
*/
|
||||
OTAPI otError OTCALL otLinkSetChannel(otInstance *aInstance, uint8_t aChannel);
|
||||
|
||||
/**
|
||||
* Get the supported channel mask.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @returns The supported channel mask as `uint32_t` with bit 0 (lsb) mapping to channel 0, bit 1 to channel 1, so on.
|
||||
*
|
||||
*/
|
||||
uint32_t otLinkGetSupportedChannelMask(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Set the supported channel mask.
|
||||
*
|
||||
* This function succeeds only when Thread protocols are disabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aChannelMask The supported channel mask (bit 0 or lsb mapping to channel 0, and so on).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the supported channel mask.
|
||||
* @retval OT_ERROR_INVALID_STATE Thread protocols are enabled.
|
||||
*
|
||||
*/
|
||||
otError otLinkSetSupportedChannelMask(otInstance *aInstance, uint32_t aChannelMask);
|
||||
|
||||
/**
|
||||
* Get the IEEE 802.15.4 Extended Address.
|
||||
*
|
||||
|
||||
@@ -65,6 +65,27 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t otLinkGetSupportedChannelMask(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.GetThreadNetif().GetMac().GetSupportedChannelMask().GetMask();
|
||||
}
|
||||
|
||||
otError otLinkSetSupportedChannelMask(otInstance *aInstance, uint32_t aChannelMask)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
VerifyOrExit(instance.GetThreadNetif().GetMle().GetRole() == OT_DEVICE_ROLE_DISABLED,
|
||||
error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
instance.GetThreadNetif().GetMac().SetSupportedChannelMask(aChannelMask);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
const otExtAddress *otLinkGetExtendedAddress(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
@@ -328,6 +328,10 @@ const char *Notifier::FlagToString(otChangedFlags aFlag) const
|
||||
retval = "CMNewChan";
|
||||
break;
|
||||
|
||||
case OT_CHANGED_SUPPORTED_CHANNEL_MASK:
|
||||
retval = "ChanMask";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+26
-1
@@ -170,6 +170,7 @@ Mac::Mac(Instance &aInstance)
|
||||
, mPanChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
|
||||
, mRadioChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
|
||||
, mRadioChannelAcquisitionId(0)
|
||||
, mSupportedChannelMask(OT_RADIO_SUPPORTED_CHANNELS)
|
||||
, mSendHead(NULL)
|
||||
, mSendTail(NULL)
|
||||
, mReceiveHead(NULL)
|
||||
@@ -249,7 +250,14 @@ void Mac::Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanD
|
||||
mScanContext = aContext;
|
||||
mScanDuration = aScanDuration;
|
||||
mScanChannel = ChannelMask::kChannelIteratorFirst;
|
||||
mScanChannelMask.SetMask((aScanChannels == 0) ? static_cast<uint32_t>(kScanChannelsAll) : aScanChannels);
|
||||
|
||||
if (aScanChannels == 0)
|
||||
{
|
||||
aScanChannels = OT_RADIO_SUPPORTED_CHANNELS;
|
||||
}
|
||||
|
||||
mScanChannelMask.SetMask(aScanChannels);
|
||||
mScanChannelMask.Intersect(mSupportedChannelMask);
|
||||
StartOperation(aScanOperation);
|
||||
}
|
||||
|
||||
@@ -513,6 +521,7 @@ otError Mac::SetPanChannel(uint8_t aChannel)
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(OT_RADIO_CHANNEL_MIN <= aChannel && aChannel <= OT_RADIO_CHANNEL_MAX, error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit(mSupportedChannelMask.ContainsChannel(aChannel), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
VerifyOrExit(mPanChannel != aChannel, GetNotifier().SignalIfFirst(OT_CHANGED_THREAD_CHANNEL));
|
||||
|
||||
@@ -536,6 +545,8 @@ otError Mac::SetRadioChannel(uint16_t aAcquisitionId, uint8_t aChannel)
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(OT_RADIO_CHANNEL_MIN <= aChannel && aChannel <= OT_RADIO_CHANNEL_MAX, error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit(mSupportedChannelMask.ContainsChannel(aChannel), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
VerifyOrExit(mRadioChannelAcquisitionId && aAcquisitionId == mRadioChannelAcquisitionId,
|
||||
error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
@@ -577,6 +588,20 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Mac::SetSupportedChannelMask(const ChannelMask &aMask)
|
||||
{
|
||||
ChannelMask newMask = aMask;
|
||||
|
||||
newMask.Intersect(OT_RADIO_SUPPORTED_CHANNELS);
|
||||
VerifyOrExit(newMask != mSupportedChannelMask, GetNotifier().SignalIfFirst(OT_CHANGED_SUPPORTED_CHANNEL_MASK));
|
||||
|
||||
mSupportedChannelMask = newMask;
|
||||
GetNotifier().Signal(OT_CHANGED_SUPPORTED_CHANNEL_MASK);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError Mac::SetNetworkName(const char *aNetworkName)
|
||||
{
|
||||
return SetNetworkName(aNetworkName, OT_NETWORK_NAME_MAX_SIZE + 1);
|
||||
|
||||
+22
-2
@@ -598,7 +598,8 @@ public:
|
||||
*
|
||||
* @param[in] aChannel The IEEE 802.15.4 PAN Channel.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 PAN Channel.
|
||||
* @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 PAN Channel.
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aChannel is not in the supported channel mask.
|
||||
*
|
||||
*/
|
||||
otError SetPanChannel(uint8_t aChannel);
|
||||
@@ -617,7 +618,9 @@ public:
|
||||
*
|
||||
* @param[in] aChannel The IEEE 802.15.4 Radio Channel.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Radio Channel.
|
||||
* @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Radio Channel.
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aChannel is not in the supported channel mask.
|
||||
* @retval OT_ERROR_INVALID_STATE The acquisition ID is incorrect.
|
||||
*
|
||||
*/
|
||||
otError SetRadioChannel(uint16_t aAcquisitionId, uint8_t aChannel);
|
||||
@@ -643,6 +646,22 @@ public:
|
||||
*/
|
||||
otError ReleaseRadioChannel(void);
|
||||
|
||||
/**
|
||||
* This method returns the supported channel mask.
|
||||
*
|
||||
* @returns The supported channel mask.
|
||||
*
|
||||
*/
|
||||
const ChannelMask &GetSupportedChannelMask(void) const { return mSupportedChannelMask; }
|
||||
|
||||
/**
|
||||
* This method sets the supported channel mask
|
||||
*
|
||||
* @param[in] aMask The supported channel mask.
|
||||
*
|
||||
*/
|
||||
void SetSupportedChannelMask(const ChannelMask &aMask);
|
||||
|
||||
/**
|
||||
* This method returns the IEEE 802.15.4 Network Name.
|
||||
*
|
||||
@@ -1024,6 +1043,7 @@ private:
|
||||
uint8_t mPanChannel;
|
||||
uint8_t mRadioChannel;
|
||||
uint16_t mRadioChannelAcquisitionId;
|
||||
ChannelMask mSupportedChannelMask;
|
||||
|
||||
otNetworkName mNetworkName;
|
||||
otExtendedPanId mExtendedPanId;
|
||||
|
||||
@@ -550,6 +550,18 @@ otError Dataset::ApplyConfiguration(Instance &aInstance) const
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kChannelMask:
|
||||
{
|
||||
const ChannelMask0Entry *mask0Entry = static_cast<const ChannelMaskTlv *>(cur)->GetMask0Entry();
|
||||
|
||||
if (mask0Entry != NULL)
|
||||
{
|
||||
mac.SetSupportedChannelMask(mask0Entry->GetMask());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Tlv::kPanId:
|
||||
mac.SetPanId(static_cast<const PanIdTlv *>(cur)->GetPanId());
|
||||
break;
|
||||
|
||||
@@ -618,7 +618,7 @@ otError ActiveDataset::GenerateLocal(void)
|
||||
{
|
||||
ChannelMask0Tlv tlv;
|
||||
tlv.Init();
|
||||
tlv.SetMask(OT_RADIO_SUPPORTED_CHANNELS);
|
||||
tlv.SetMask(netif.GetMac().GetSupportedChannelMask().GetMask());
|
||||
dataset.Set(tlv);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Ncp {
|
||||
// number of entries in the list is always less than or equal to 32.
|
||||
//
|
||||
const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] = {
|
||||
// Spinel property Status (if prop is `LAST_STATUS`) IsFilterable?
|
||||
// Spinel property , Status (if prop is `LAST_STATUS`), IsFilterable?
|
||||
|
||||
{SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_RESET_UNKNOWN, false}, // 0
|
||||
{SPINEL_PROP_STREAM_DEBUG, SPINEL_STATUS_OK, true}, // 1
|
||||
@@ -79,8 +79,9 @@ const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] = {
|
||||
{SPINEL_PROP_NET_XPANID, SPINEL_STATUS_OK, true}, // 25
|
||||
{SPINEL_PROP_NET_MASTER_KEY, SPINEL_STATUS_OK, true}, // 26
|
||||
{SPINEL_PROP_NET_PSKC, SPINEL_STATUS_OK, true}, // 27
|
||||
{SPINEL_PROP_PHY_CHAN_SUPPORTED, SPINEL_STATUS_OK, true}, // 28
|
||||
#if OPENTHREAD_ENABLE_CHANNEL_MANAGER
|
||||
{SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_STATUS_OK, true}, // 28
|
||||
{SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_STATUS_OK, true}, // 29
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -183,11 +183,9 @@ NcpBase::NcpBase(Instance *aInstance)
|
||||
, mDecoder()
|
||||
, mHostPowerStateInProgress(false)
|
||||
, mLastStatus(SPINEL_STATUS_OK)
|
||||
, mSupportedChannelMask(OT_RADIO_SUPPORTED_CHANNELS)
|
||||
, mChannelMask(OT_RADIO_SUPPORTED_CHANNELS)
|
||||
, mScanChannelMask(OT_RADIO_SUPPORTED_CHANNELS)
|
||||
, mScanPeriod(200)
|
||||
, // ms
|
||||
mDiscoveryScanJoinerFlag(false)
|
||||
, mDiscoveryScanJoinerFlag(false)
|
||||
, mDiscoveryScanEnableFiltering(false)
|
||||
, mDiscoveryScanPanId(0xffff)
|
||||
, mUpdateChangedPropsTask(*aInstance, &NcpBase::UpdateChangedProps, this)
|
||||
|
||||
@@ -471,8 +471,7 @@ protected:
|
||||
};
|
||||
|
||||
spinel_status_t mLastStatus;
|
||||
uint32_t mSupportedChannelMask;
|
||||
uint32_t mChannelMask;
|
||||
uint32_t mScanChannelMask;
|
||||
uint16_t mScanPeriod;
|
||||
bool mDiscoveryScanJoinerFlag;
|
||||
bool mDiscoveryScanEnableFiltering;
|
||||
|
||||
@@ -651,6 +651,9 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
|
||||
// MTD (or FTD) Properties (Set Handler)
|
||||
|
||||
#if OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
case SPINEL_PROP_PHY_CHAN_SUPPORTED:
|
||||
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_SUPPORTED>;
|
||||
break;
|
||||
case SPINEL_PROP_MAC_DATA_POLL_PERIOD:
|
||||
handler = &NcpBase::HandlePropertySet<SPINEL_PROP_MAC_DATA_POLL_PERIOD>;
|
||||
break;
|
||||
|
||||
+21
-10
@@ -225,7 +225,19 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_FREQ>(void)
|
||||
|
||||
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
|
||||
{
|
||||
return EncodeChannelMask(mSupportedChannelMask);
|
||||
return EncodeChannelMask(otLinkGetSupportedChannelMask(mInstance));
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
|
||||
{
|
||||
uint32_t newMask = 0;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = DecodeChannelMask(newMask));
|
||||
error = otLinkSetSupportedChannelMask(mInstance, newMask);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_RSSI>(void)
|
||||
@@ -2577,7 +2589,7 @@ exit:
|
||||
|
||||
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_SCAN_MASK>(void)
|
||||
{
|
||||
return EncodeChannelMask(mChannelMask);
|
||||
return EncodeChannelMask(mScanChannelMask);
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_MASK>(void)
|
||||
@@ -2586,9 +2598,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_MASK>(void)
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = DecodeChannelMask(newMask));
|
||||
VerifyOrExit((~mSupportedChannelMask & newMask) == 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
mChannelMask = newMask;
|
||||
mScanChannelMask = newMask;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -2662,7 +2672,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>(void)
|
||||
else
|
||||
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
|
||||
{
|
||||
error = otLinkActiveScan(mInstance, mChannelMask, mScanPeriod, &HandleActiveScanResult_Jump, this);
|
||||
error = otLinkActiveScan(mInstance, mScanChannelMask, mScanPeriod, &HandleActiveScanResult_Jump, this);
|
||||
}
|
||||
|
||||
SuccessOrExit(error);
|
||||
@@ -2677,9 +2687,9 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>(void)
|
||||
// Make sure we aren't already scanning and that we have
|
||||
// only 1 bit set for the channel mask.
|
||||
VerifyOrExit(mCurScanChannel == kInvalidScanChannel, error = OT_ERROR_INVALID_STATE);
|
||||
VerifyOrExit(HasOnly1BitSet(mChannelMask), error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit(HasOnly1BitSet(mScanChannelMask), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
scanChannel = IndexOfMSB(mChannelMask);
|
||||
scanChannel = IndexOfMSB(mScanChannelMask);
|
||||
mCurScanChannel = (int8_t)scanChannel;
|
||||
|
||||
error = otLinkRawEnergyScan(mInstance, scanChannel, mScanPeriod, LinkRawEnergyScanDone);
|
||||
@@ -2687,14 +2697,14 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_SCAN_STATE>(void)
|
||||
else
|
||||
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
|
||||
{
|
||||
error = otLinkEnergyScan(mInstance, mChannelMask, mScanPeriod, &HandleEnergyScanResult_Jump, this);
|
||||
error = otLinkEnergyScan(mInstance, mScanChannelMask, mScanPeriod, &HandleEnergyScanResult_Jump, this);
|
||||
}
|
||||
|
||||
SuccessOrExit(error);
|
||||
break;
|
||||
|
||||
case SPINEL_SCAN_STATE_DISCOVER:
|
||||
error = otThreadDiscover(mInstance, mChannelMask, mDiscoveryScanPanId, mDiscoveryScanJoinerFlag,
|
||||
error = otThreadDiscover(mInstance, mScanChannelMask, mDiscoveryScanPanId, mDiscoveryScanJoinerFlag,
|
||||
mDiscoveryScanEnableFiltering, &HandleActiveScanResult_Jump, this);
|
||||
|
||||
SuccessOrExit(error);
|
||||
@@ -2938,6 +2948,7 @@ void NcpBase::ProcessThreadChangedFlags(void)
|
||||
{OT_CHANGED_MASTER_KEY, SPINEL_PROP_NET_MASTER_KEY},
|
||||
{OT_CHANGED_PSKC, SPINEL_PROP_NET_PSKC},
|
||||
{OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL, SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL},
|
||||
{OT_CHANGED_SUPPORTED_CHANNEL_MASK, SPINEL_PROP_PHY_CHAN_SUPPORTED},
|
||||
};
|
||||
|
||||
VerifyOrExit(mThreadChangedFlags != 0);
|
||||
|
||||
Reference in New Issue
Block a user