[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:
Abtin Keshavarzian
2018-07-02 10:43:45 -05:00
committed by Jonathan Hui
parent fdb3d0ef58
commit 31698ecaf7
13 changed files with 142 additions and 23 deletions
+1
View File
@@ -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
};
/**
+25 -1
View File
@@ -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.
*
+21
View File
@@ -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);
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+12
View File
@@ -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;
+1 -1
View File
@@ -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);
}
+3 -2
View File
@@ -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
};
+2 -4
View File
@@ -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)
+1 -2
View File
@@ -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;
+3
View File
@@ -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
View File
@@ -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);