mirror of
https://github.com/espressif/openthread.git
synced 2026-09-16 06:00:13 +00:00
[mac] serialize access to the radio channel (#2694)
This commit is contained in:
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -366,7 +366,7 @@ private:
|
||||
|
||||
uint32_t mScanChannels;
|
||||
uint8_t mScanChannel;
|
||||
uint8_t mRestoreChannel;
|
||||
uint16_t mMacRadioAcquisitionId;
|
||||
uint16_t mRestorePanId;
|
||||
bool mScanning;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user