[mac] serialize access to the radio channel (#2694)

This commit is contained in:
pvanhorn
2018-05-11 08:36:01 -07:00
committed by Jonathan Hui
parent 585080e3a0
commit 27fb81673c
10 changed files with 159 additions and 41 deletions
+2 -2
View File
@@ -46,7 +46,7 @@ uint8_t otLinkGetChannel(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.GetThreadNetif().GetMac().GetChannel();
return instance.GetThreadNetif().GetMac().GetPanChannel();
}
otError otLinkSetChannel(otInstance *aInstance, uint8_t aChannel)
@@ -57,7 +57,7 @@ otError otLinkSetChannel(otInstance *aInstance, uint8_t aChannel)
VerifyOrExit(instance.GetThreadNetif().GetMle().GetRole() == OT_DEVICE_ROLE_DISABLED,
error = OT_ERROR_INVALID_STATE);
SuccessOrExit(error = instance.GetThreadNetif().GetMac().SetChannel(aChannel));
SuccessOrExit(error = instance.GetThreadNetif().GetMac().SetPanChannel(aChannel));
instance.GetThreadNetif().GetActiveDataset().Clear();
instance.GetThreadNetif().GetPendingDataset().Clear();
+64 -11
View File
@@ -168,7 +168,9 @@ Mac::Mac(Instance &aInstance)
, mReceiveTimer(aInstance, &Mac::HandleReceiveTimer, this)
, mShortAddress(kShortAddrInvalid)
, mPanId(kPanIdBroadcast)
, mChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
, mPanChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
, mRadioChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
, mRadioChannelAcquisitionId(0)
, mSendHead(NULL)
, mSendTail(NULL)
, mReceiveHead(NULL)
@@ -507,13 +509,64 @@ otError Mac::SetShortAddress(ShortAddress aShortAddress)
return OT_ERROR_NONE;
}
otError Mac::SetChannel(uint8_t aChannel)
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);
mChannel = aChannel;
mPanChannel = aChannel;
VerifyOrExit(!mRadioChannelAcquisitionId);
mRadioChannel = mPanChannel;
UpdateIdleMode();
exit:
return error;
}
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(mRadioChannelAcquisitionId && aAcquisitionId == mRadioChannelAcquisitionId,
error = OT_ERROR_INVALID_STATE);
mRadioChannel = aChannel;
UpdateIdleMode();
exit:
return error;
}
otError Mac::AcquireRadioChannel(uint16_t *aAcquisitionId)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(aAcquisitionId != NULL, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(!mRadioChannelAcquisitionId, error = OT_ERROR_INVALID_STATE);
mRadioChannelAcquisitionId = Random::GetUint16InRange(1, kMaxAcquisitionId);
*aAcquisitionId = mRadioChannelAcquisitionId;
exit:
return error;
}
otError Mac::ReleaseRadioChannel(void)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(mRadioChannelAcquisitionId, error = OT_ERROR_INVALID_STATE);
mRadioChannelAcquisitionId = 0;
mRadioChannel = mPanChannel;
UpdateIdleMode();
exit:
@@ -602,8 +655,8 @@ void Mac::UpdateIdleMode(void)
// the radio in receive mode.
}
otLogDebgMac(GetInstance(), "Idle mode: Radio receiving on channel %d", mChannel);
RadioReceive(mChannel);
otLogDebgMac(GetInstance(), "Idle mode: Radio receiving on channel %d", mRadioChannel);
RadioReceive(mRadioChannel);
exit:
return;
@@ -680,7 +733,7 @@ void Mac::PerformOperation(void)
{
mPendingWaitingForData = false;
mOperation = kOperationWaitingForData;
RadioReceive(mChannel);
RadioReceive(mRadioChannel);
}
else if (mPendingTransmitOobFrame)
{
@@ -959,7 +1012,7 @@ void Mac::StartCsmaBackoff(void)
break;
default:
RadioReceive(mChannel);
RadioReceive(mRadioChannel);
break;
}
}
@@ -1050,14 +1103,14 @@ void Mac::BeginTransmit(void)
break;
case kOperationTransmitBeacon:
sendFrame.SetChannel(mChannel);
sendFrame.SetChannel(mRadioChannel);
SendBeacon(sendFrame);
sendFrame.SetSequence(mBeaconSequence++);
sendFrame.SetMaxTxAttempts(kDirectFrameMacTxAttempts);
break;
case kOperationTransmitData:
sendFrame.SetChannel(mChannel);
sendFrame.SetChannel(mRadioChannel);
SuccessOrExit(error = mSendHead->HandleFrameRequest(sendFrame));
// If the frame is marked as a retransmission, then data sequence number is already set by the `Sender`.
@@ -1892,9 +1945,9 @@ void Mac::HandleReceivedFrame(Frame *aFrame, otError aError)
// We can possibly receive a data frame while either active or
// energy scan is ongoing. We continue to process the frame only
// if the current scan channel matches `mChannel`.
// if the current scan channel matches `mPanChannel`.
VerifyOrExit(mScanChannel == mChannel, mCounters.mRxOther++);
VerifyOrExit(mScanChannel == mPanChannel, mCounters.mRxOther++);
break;
case kOperationWaitingForData:
+54 -8
View File
@@ -554,22 +554,65 @@ public:
otError SetShortAddress(ShortAddress aShortAddress);
/**
* This method returns the IEEE 802.15.4 Channel.
* This method returns the IEEE 802.15.4 PAN Channel.
*
* @returns The IEEE 802.15.4 Channel.
* @returns The IEEE 802.15.4 PAN Channel.
*
*/
uint8_t GetChannel(void) const { return mChannel; }
uint8_t GetPanChannel(void) const { return mPanChannel; }
/**
* This method sets the IEEE 802.15.4 Channel.
* This method sets the IEEE 802.15.4 PAN Channel.
*
* @param[in] aChannel The IEEE 802.15.4 Channel.
* @param[in] aChannel The IEEE 802.15.4 PAN Channel.
*
* @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Channel.
* @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 PAN Channel.
*
*/
otError SetChannel(uint8_t aChannel);
otError SetPanChannel(uint8_t aChannel);
/**
* This method returns the IEEE 802.15.4 Radio Channel.
*
* @returns The IEEE 802.15.4 Radio Channel.
*
*/
uint8_t GetRadioChannel(void) const { return mRadioChannel; }
/**
* This method sets the IEEE 802.15.4 Radio Channel. It can only be called
* after successfully calling AcquireRadioChannel().
*
* @param[in] aChannel The IEEE 802.15.4 Radio Channel.
*
* @retval OT_ERROR_NONE Successfully set the IEEE 802.15.4 Radio Channel.
*
*/
otError SetRadioChannel(uint16_t aAcquisitionId, uint8_t aChannel);
/**
* This method acquires external ownership of the Radio channel so that future calls to
* SetRadioChannel will succeed.
*
* @param[out] aAcquisitionId The AcquisitionId that the caller should use when
* calling SetRadioChannel().
*
* @retval OT_ERROR_NONE Successfully acquired permission to Set the Radio Channel.
* @retval OT_ERROR_INVALID_STATE Failed to acquire permission as the radio Channel
* has already been acquired.
*
*/
otError AcquireRadioChannel(uint16_t *aAcquisitionId);
/**
* This method releases external ownership of the radio Channel
* that was acquired with AcquireRadioChannel(). The channel
* will re-adopt the PAN Channel when this API is called.
*
* @retval OT_ERROR_NONE Successfully released the IEEE 802.15.4 Radio Channel.
*
*/
otError ReleaseRadioChannel(void);
/**
* This method returns the IEEE 802.15.4 Network Name.
@@ -810,6 +853,7 @@ private:
{
kInvalidRssiValue = 127,
kMaxCcaSampleCount = OPENTHREAD_CONFIG_CCA_FAILURE_RATE_AVERAGING_WINDOW,
kMaxAcquisitionId = 0xffff,
/**
* Interval between RSSI samples when performing Energy Scan.
@@ -904,7 +948,9 @@ private:
ExtAddress mExtAddress;
ShortAddress mShortAddress;
PanId mPanId;
uint8_t mChannel;
uint8_t mPanChannel;
uint8_t mRadioChannel;
uint16_t mRadioChannelAcquisitionId;
otNetworkName mNetworkName;
otExtendedPanId mExtendedPanId;
+2 -2
View File
@@ -548,9 +548,9 @@ otError Dataset::ApplyConfiguration(Instance &aInstance) const
{
uint8_t channel = static_cast<uint8_t>(static_cast<const ChannelTlv *>(cur)->GetChannel());
if (mac.GetChannel() != channel)
if (mac.GetPanChannel() != channel)
{
error = mac.SetChannel(channel);
error = mac.SetPanChannel(channel);
if (error != OT_ERROR_NONE)
{
+2 -2
View File
@@ -162,7 +162,7 @@ otError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6:
channel.GetChannel() <= OT_RADIO_CHANNEL_MAX,
state = StateTlv::kReject);
if (channel.GetChannel() != netif.GetMac().GetChannel())
if (channel.GetChannel() != netif.GetMac().GetPanChannel())
{
doesAffectConnectivity = true;
}
@@ -609,7 +609,7 @@ otError ActiveDataset::GenerateLocal(void)
ChannelTlv tlv;
tlv.Init();
tlv.SetChannelPage(0);
tlv.SetChannel(netif.GetMac().GetChannel());
tlv.SetChannel(netif.GetMac().GetPanChannel());
dataset.Set(tlv);
}
+1 -1
View File
@@ -292,7 +292,7 @@ otError Joiner::TryNextJoin()
joinerRouter->mPriority = 0;
netif.GetMac().SetPanId(joinerRouter->mPanId);
netif.GetMac().SetChannel(joinerRouter->mChannel);
netif.GetMac().SetPanChannel(joinerRouter->mChannel);
netif.GetIp6Filter().AddUnsecurePort(netif.GetCoapSecure().GetPort());
messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xfe80);
+25 -6
View File
@@ -74,7 +74,7 @@ MeshForwarder::MeshForwarder(Instance &aInstance)
, mEnabled(false)
, mScanChannels(0)
, mScanChannel(0)
, mRestoreChannel(0)
, mMacRadioAcquisitionId(0)
, mRestorePanId(Mac::kPanIdBroadcast)
, mScanning(false)
#if OPENTHREAD_FTD
@@ -121,7 +121,12 @@ otError MeshForwarder::Stop(void)
if (mScanning)
{
netif.GetMac().SetChannel(mRestoreChannel);
if (mMacRadioAcquisitionId)
{
netif.GetMac().ReleaseRadioChannel();
mMacRadioAcquisitionId = 0;
}
mScanning = false;
netif.GetMle().HandleDiscoverComplete();
}
@@ -204,8 +209,9 @@ otError MeshForwarder::PrepareDiscoverRequest(void)
mScanChannel = OT_RADIO_CHANNEL_MIN;
mScanChannels >>= OT_RADIO_CHANNEL_MIN;
mRestoreChannel = netif.GetMac().GetChannel();
mRestorePanId = netif.GetMac().GetPanId();
mRestorePanId = netif.GetMac().GetPanId();
SuccessOrExit(error = netif.GetMac().AcquireRadioChannel(&mMacRadioAcquisitionId));
while ((mScanChannels & 1) == 0)
{
@@ -214,6 +220,12 @@ otError MeshForwarder::PrepareDiscoverRequest(void)
if (mScanChannel > OT_RADIO_CHANNEL_MAX)
{
if (mMacRadioAcquisitionId)
{
netif.GetMac().ReleaseRadioChannel();
mMacRadioAcquisitionId = 0;
}
netif.GetMle().HandleDiscoverComplete();
ExitNow(error = OT_ERROR_DROP);
}
@@ -479,7 +491,8 @@ otError MeshForwarder::HandleFrameRequest(Mac::Frame &aFrame)
case Message::kTypeIp6:
if (mSendMessage->GetSubType() == Message::kSubTypeMleDiscoverRequest)
{
netif.GetMac().SetChannel(mScanChannel);
SuccessOrExit(error = netif.GetMac().SetRadioChannel(mMacRadioAcquisitionId, mScanChannel));
aFrame.SetChannel(mScanChannel);
// In case a specific PAN ID of a Thread Network to be discovered is not known, Discovery
@@ -1053,7 +1066,13 @@ void MeshForwarder::HandleDiscoverTimer(void)
mSendQueue.Dequeue(*mSendMessage);
mSendMessage->Free();
mSendMessage = NULL;
netif.GetMac().SetChannel(mRestoreChannel);
if (mMacRadioAcquisitionId)
{
netif.GetMac().ReleaseRadioChannel();
mMacRadioAcquisitionId = 0;
}
netif.GetMac().SetPanId(mRestorePanId);
mScanning = false;
netif.GetMle().HandleDiscoverComplete();
+1 -1
View File
@@ -366,7 +366,7 @@ private:
uint32_t mScanChannels;
uint8_t mScanChannel;
uint8_t mRestoreChannel;
uint16_t mMacRadioAcquisitionId;
uint16_t mRestorePanId;
bool mScanning;
+4 -4
View File
@@ -1533,7 +1533,7 @@ uint32_t Mle::Reattach(void)
{
if (mPreviousPanId != Mac::kPanIdBroadcast)
{
netif.GetMac().SetChannel(mPreviousChannel);
netif.GetMac().SetPanChannel(mPreviousChannel);
netif.GetMac().SetPanId(mPreviousPanId);
mPreviousPanId = Mac::kPanIdBroadcast;
BecomeDetached();
@@ -2010,7 +2010,7 @@ otError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Add
channel.Init();
channel.SetChannelPage(0);
channel.SetChannel(netif.GetMac().GetChannel());
channel.SetChannel(netif.GetMac().GetPanChannel());
SuccessOrExit(error = message->Append(&channel, sizeof(channel)));
if (aOrphanAnnounce)
@@ -3224,7 +3224,7 @@ otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMe
if (localTimestamp == NULL || localTimestamp->Compare(timestamp) > 0)
{
uint8_t curChannel = netif.GetMac().GetChannel();
uint8_t curChannel = netif.GetMac().GetPanChannel();
uint16_t curPanId = netif.GetMac().GetPanId();
// No action is required if device is detached, and current
@@ -3236,7 +3236,7 @@ otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMe
Stop(false);
mPreviousChannel = curChannel;
mPreviousPanId = curPanId;
netif.GetMac().SetChannel(channel);
netif.GetMac().SetPanChannel(channel);
netif.GetMac().SetPanId(panId);
Start(false, true);
}
+4 -4
View File
@@ -67,7 +67,7 @@ void ChannelManager::RequestChannelChange(uint8_t aChannel)
{
otLogInfoUtil(GetInstance(), "ChannelManager: Request to change to channel %d with delay %d sec", aChannel, mDelay);
if (aChannel == GetInstance().Get<Mac::Mac>().GetChannel())
if (aChannel == GetInstance().Get<Mac::Mac>().GetPanChannel())
{
otLogInfoUtil(GetInstance(), "ChannelManager: Already operating on the requested channel %d", aChannel);
ExitNow();
@@ -107,7 +107,7 @@ void ChannelManager::PreparePendingDataset(void)
VerifyOrExit(mState == kStateChangeRequested);
VerifyOrExit(mChannel != GetInstance().Get<Mac::Mac>().GetChannel());
VerifyOrExit(mChannel != GetInstance().Get<Mac::Mac>().GetPanChannel());
if (netif.GetPendingDataset().Get(dataset) == OT_ERROR_NONE)
{
@@ -264,7 +264,7 @@ void ChannelManager::HandleStateChanged(Notifier::Callback &aCallback, uint32_t
void ChannelManager::HandleStateChanged(uint32_t aFlags)
{
VerifyOrExit((aFlags & OT_CHANGED_THREAD_CHANNEL) != 0);
VerifyOrExit(mChannel == GetInstance().Get<Mac::Mac>().GetChannel());
VerifyOrExit(mChannel == GetInstance().Get<Mac::Mac>().GetPanChannel());
mState = kStateIdle;
StartAutoSelectTimer();
@@ -395,7 +395,7 @@ otError ChannelManager::RequestChannelSelect(bool aSkipQualityCheck)
SuccessOrExit(error = FindBetterChannel(newChannel, newOccupancy));
curChannel = GetInstance().Get<Mac::Mac>().GetChannel();
curChannel = GetInstance().Get<Mac::Mac>().GetPanChannel();
curOccupancy = GetInstance().GetChannelMonitor().GetChannelOccupancy(curChannel);
if (newChannel == curChannel)