[channelmask] add radio supported and preferred channel mask (#3732)

Add new radio platform APIs:
 * otPlatRadioGetSupportedChannelMask(); // supported channel mask: the device is allowed to be on;
 * otPlatRadioGetPreferredChannelMask(); // preferred channel mask: the device prefers to form on.

Implement some default radio platform APIs.

Add spinel property `SPINEL_PROP_PHY_CHAN_PREFERRED` to retrieve Preferred ChannelMask.
This commit is contained in:
Shu Chen
2019-04-09 01:35:18 +08:00
committed by Jonathan Hui
parent 174d076722
commit 4c06b47c34
22 changed files with 174 additions and 37 deletions
+1
View File
@@ -163,6 +163,7 @@ LOCAL_SRC_FILES := \
src/core/net/ip6_routes.cpp \
src/core/net/netif.cpp \
src/core/net/udp6.cpp \
src/core/phy/radio_weak.cpp \
src/core/thread/address_resolver.cpp \
src/core/thread/announce_begin_server.cpp \
src/core/thread/announce_sender.cpp \
+1
View File
@@ -126,6 +126,7 @@
<ClCompile Include="..\..\src\core\net\ip6_routes.cpp" />
<ClCompile Include="..\..\src\core\net\netif.cpp" />
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp" />
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp" />
@@ -213,6 +213,9 @@
<ClCompile Include="..\..\src\core\net\netif.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp">
<Filter>Source Files\phy</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
@@ -133,6 +133,7 @@
<ClCompile Include="..\..\src\core\net\ip6_routes.cpp" />
<ClCompile Include="..\..\src\core\net\netif.cpp" />
<ClCompile Include="..\..\src\core\net\udp6.cpp" />
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp" />
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_begin_server.cpp" />
<ClCompile Include="..\..\src\core\thread\announce_sender.cpp" />
@@ -207,6 +207,9 @@
<ClCompile Include="..\..\src\core\net\netif.cpp">
<Filter>Source Files\net</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\phy\radio_weak.cpp">
<Filter>Source Files\phy</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\address_resolver.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
-10
View File
@@ -821,16 +821,6 @@ OTAPI uint8_t OTCALL otLinkGetPhyChannelMin(otInstance *aInstance);
*/
OTAPI uint8_t OTCALL otLinkGetPhyChannelMax(otInstance *aInstance);
/**
* This function gets the supported channel mask of IEEE 802.15.4 physical layer.
*
* @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.
*
*/
OTAPI uint32_t OTCALL otLinkGetPhySupportedChannelMask(otInstance *aInstance);
/**
* @}
*
+20
View File
@@ -694,6 +694,26 @@ void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance);
*/
void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance);
/**
* Get the radio supported channel mask that the device is allowed to be on.
*
* @param[in] aInstance The OpenThread instance structure.
*
* @returns The radio supported channel mask.
*
*/
uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance);
/**
* Get the radio preferred channel mask that the device prefers to form on.
*
* @param[in] aInstance The OpenThread instance strucyyture.
*
* @returns The radio preferred channel mask.
*
*/
uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance);
/**
* @}
*
+2
View File
@@ -187,6 +187,7 @@ SOURCES_COMMON = \
net/netif.cpp \
net/sntp_client.cpp \
net/udp6.cpp \
phy/radio_weak.cpp \
thread/address_resolver.cpp \
thread/announce_begin_server.cpp \
thread/announce_sender.cpp \
@@ -244,6 +245,7 @@ libopenthread_radio_a_SOURCES = \
mac/mac_frame.cpp \
mac/sub_mac.cpp \
mac/sub_mac_callbacks.cpp \
phy/radio_weak.cpp \
thread/link_quality.cpp \
utils/missing_strlcat.c \
utils/missing_strlcpy.c \
-6
View File
@@ -443,9 +443,3 @@ uint8_t otLinkGetPhyChannelMax(otInstance *aInstance)
OT_UNUSED_VARIABLE(aInstance);
return Phy::kChannelMax;
}
uint32_t otLinkGetPhySupportedChannelMask(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return Phy::kSupportedChannels;
}
+3 -3
View File
@@ -91,7 +91,7 @@ Mac::Mac(Instance &aInstance)
, mPanChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
, mRadioChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
, mRadioChannelAcquisitionId(0)
, mSupportedChannelMask(Phy::kSupportedChannels)
, mSupportedChannelMask(otPlatRadioGetSupportedChannelMask(&aInstance))
, mScanChannel(Phy::kChannelMin)
, mScanDuration(0)
, mScanChannelMask()
@@ -166,7 +166,7 @@ void Mac::Scan(Operation aScanOperation, uint32_t aScanChannels, uint16_t aScanD
if (aScanChannels == 0)
{
aScanChannels = Phy::kSupportedChannels;
aScanChannels = GetSupportedChannelMask().GetMask();
}
mScanChannelMask.SetMask(aScanChannels);
@@ -425,7 +425,7 @@ void Mac::SetSupportedChannelMask(const ChannelMask &aMask)
{
ChannelMask newMask = aMask;
newMask.Intersect(ChannelMask(Phy::kSupportedChannels));
newMask.Intersect(ChannelMask(otPlatRadioGetSupportedChannelMask(&GetInstance())));
VerifyOrExit(newMask != mSupportedChannelMask, Get<Notifier>().SignalIfFirst(OT_CHANGED_SUPPORTED_CHANNEL_MASK));
mSupportedChannelMask = newMask;
+1 -1
View File
@@ -227,7 +227,7 @@ otError DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const
VerifyOrExit(channelMaskTlv != NULL, error = OT_ERROR_NOT_FOUND);
VerifyOrExit((mask = channelMaskTlv->GetChannelMask()) != 0);
aChannelMask.SetMask(mask & Phy::kSupportedChannels);
aChannelMask.SetMask(mask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
VerifyOrExit(!aChannelMask.IsEmpty(), error = OT_ERROR_NOT_FOUND);
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2019, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements the default radio platform APIs.
*/
#include <openthread/platform/radio.h>
#include "phy/phy.hpp"
using namespace ot;
OT_TOOL_WEAK uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return Phy::kSupportedChannels;
}
OT_TOOL_WEAK uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance)
{
return otPlatRadioGetSupportedChannelMask(aInstance);
}
+1 -1
View File
@@ -69,7 +69,7 @@ otError AnnounceSenderBase::SendAnnounce(Mac::ChannelMask aChannelMask,
VerifyOrExit(aPeriod != 0, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aJitter < aPeriod, error = OT_ERROR_INVALID_ARGS);
aChannelMask.Intersect(Mac::ChannelMask(Phy::kSupportedChannels));
aChannelMask.Intersect(Get<Mac::Mac>().GetSupportedChannelMask());
VerifyOrExit(!aChannelMask.IsEmpty(), error = OT_ERROR_INVALID_ARGS);
mChannelMask = aChannelMask;
+3 -2
View File
@@ -1153,9 +1153,10 @@ exit:
void MeshForwarder::SetDiscoverParameters(const Mac::ChannelMask &aScanChannels)
{
uint32_t mask;
uint32_t supportedMask = Get<Mac::Mac>().GetSupportedChannelMask().GetMask();
mask = aScanChannels.IsEmpty() ? static_cast<uint32_t>(Phy::kSupportedChannels) : aScanChannels.GetMask();
mScanChannels.SetMask(mask & Phy::kSupportedChannels);
mask = aScanChannels.IsEmpty() ? supportedMask : aScanChannels.GetMask();
mScanChannels.SetMask(mask & supportedMask);
}
void MeshForwarder::HandleDiscoverTimer(Timer &aTimer)
+2 -2
View File
@@ -480,14 +480,14 @@ exit:
void ChannelManager::SetSupportedChannels(uint32_t aChannelMask)
{
mSupportedChannelMask.SetMask(aChannelMask & Phy::kSupportedChannels);
mSupportedChannelMask.SetMask(aChannelMask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
otLogInfoUtil("ChannelManager: Supported channels: %s", mSupportedChannelMask.ToString().AsCString());
}
void ChannelManager::SetFavoredChannels(uint32_t aChannelMask)
{
mFavoredChannelMask.SetMask(aChannelMask & Phy::kSupportedChannels);
mFavoredChannelMask.SetMask(aChannelMask & Get<Mac::Mac>().GetSupportedChannelMask().GetMask());
otLogInfoUtil("ChannelManager: Favored channels: %s", mFavoredChannelMask.ToString().AsCString());
}
+14
View File
@@ -2173,6 +2173,20 @@ exit:
return error;
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
{
#if OPENTHREAD_RADIO
return EncodeChannelMask(otPlatRadioGetSupportedChannelMask(mInstance));
#else
return EncodeChannelMask(otLinkGetSupportedChannelMask(mInstance));
#endif // OPENTHREAD_RADIO
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_PREFERRED>(void)
{
return EncodeChannelMask(otPlatRadioGetPreferredChannelMask(mInstance));
}
} // namespace Ncp
} // namespace ot
+6 -3
View File
@@ -134,6 +134,12 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
case SPINEL_PROP_VENDOR_ID:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_VENDOR_ID>;
break;
case SPINEL_PROP_PHY_CHAN_SUPPORTED:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>;
break;
case SPINEL_PROP_PHY_CHAN_PREFERRED:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_PREFERRED>;
break;
// --------------------------------------------------------------------------
// MTD (or FTD) Properties (Get Handler)
@@ -171,9 +177,6 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
case SPINEL_PROP_MSG_BUFFER_COUNTERS:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_MSG_BUFFER_COUNTERS>;
break;
case SPINEL_PROP_PHY_CHAN_SUPPORTED:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>;
break;
case SPINEL_PROP_PHY_FREQ:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_FREQ>;
break;
-5
View File
@@ -207,11 +207,6 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_FREQ>(void)
return mEncoder.WriteUint32(freq_khz);
}
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
{
return EncodeChannelMask(otLinkGetPhySupportedChannelMask(mInstance));
}
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_PHY_CHAN_SUPPORTED>(void)
{
uint32_t newMask = 0;
+4
View File
@@ -1295,6 +1295,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
ret = "PHY_PCAP_ENABLED";
break;
case SPINEL_PROP_PHY_CHAN_PREFERRED:
ret = "PHY_CHAN_PREFERRED";
break;
case SPINEL_PROP_JAM_DETECT_ENABLE:
ret = "JAM_DETECT_ENABLE";
break;
+1
View File
@@ -1198,6 +1198,7 @@ typedef enum
SPINEL_PROP_PHY_RSSI = SPINEL_PROP_PHY__BEGIN + 6, ///< dBm [c]
SPINEL_PROP_PHY_RX_SENSITIVITY = SPINEL_PROP_PHY__BEGIN + 7, ///< dBm [c]
SPINEL_PROP_PHY_PCAP_ENABLED = SPINEL_PROP_PHY__BEGIN + 8, ///< [b]
SPINEL_PROP_PHY_CHAN_PREFERRED = SPINEL_PROP_PHY__BEGIN + 9, ///< [A(C)]
SPINEL_PROP_PHY__END = 0x30,
SPINEL_PROP_PHY_EXT__BEGIN = 0x1200,
+42
View File
@@ -1361,6 +1361,36 @@ otError RadioSpinel::PlatDiagProcess(const char *aString, char *aOutput, size_t
}
#endif
uint32_t RadioSpinel::GetRadioChannelMask(bool aPreferred)
{
uint8_t maskBuffer[kChannelMaskBufferSize];
otError error = OT_ERROR_NONE;
uint32_t channelMask = 0;
const uint8_t *maskData = maskBuffer;
spinel_size_t maskLength = sizeof(maskBuffer);
SuccessOrExit(error = Get(aPreferred ? SPINEL_PROP_PHY_CHAN_PREFERRED : SPINEL_PROP_PHY_CHAN_SUPPORTED,
SPINEL_DATATYPE_DATA_S, maskBuffer, &maskLength));
while (maskLength > 0)
{
uint8_t channel;
spinel_ssize_t unpacked;
unpacked = spinel_datatype_unpack(maskData, maskLength, SPINEL_DATATYPE_UINT8_S, &channel);
VerifyOrExit(unpacked > 0, error = OT_ERROR_FAILED);
VerifyOrExit(channel < kChannelMaskBufferSize, error = OT_ERROR_PARSE);
channelMask |= (1UL << channel);
maskData += unpacked;
maskLength -= static_cast<spinel_size_t>(unpacked);
}
exit:
LogIfFail("Get radio channel mask failed", error);
return channelMask;
}
} // namespace PosixApp
} // namespace ot
@@ -1695,3 +1725,15 @@ void otPlatDiagAlarmCallback(otInstance *aInstance)
OT_UNUSED_VARIABLE(aInstance);
}
#endif // OPENTHREAD_ENABLE_DIAG
uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return sRadioSpinel.GetRadioChannelMask(false);
}
uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return sRadioSpinel.GetRadioChannelMask(true);
}
+17 -4
View File
@@ -439,6 +439,18 @@ public:
otError PlatDiagProcess(const char *aString, char *aOutput, size_t aOutputMaxLen);
#endif
/**
* This method returns the radio channel mask.
*
* @param[in] aPreferred TRUE to get preferred channel mask, FALSE to get supported channel mask.
*
* @returns The radio channel mask according to @aPreferred:
* The radio supported channel mask that the device is allowed to be on.
* The radio preferred channel mask that the device prefers to form on.
*
*/
uint32_t GetRadioChannelMask(bool aPreferred);
/**
* This method processes a received Spinel frame.
*
@@ -449,10 +461,11 @@ public:
private:
enum
{
kMaxSpinelFrame = HdlcInterface::kMaxFrameSize,
kMaxWaitTime = 2000, ///< Max time to wait for response in milliseconds.
kVersionStringSize = 128, ///< Max size of version string.
kCapsBufferSize = 100, ///< Max buffer size used to store `SPINEL_PROP_CAPS` value.
kMaxSpinelFrame = HdlcInterface::kMaxFrameSize,
kMaxWaitTime = 2000, ///< Max time to wait for response in milliseconds.
kVersionStringSize = 128, ///< Max size of version string.
kCapsBufferSize = 100, ///< Max buffer size used to store `SPINEL_PROP_CAPS` value.
kChannelMaskBufferSize = 32, ///< Max buffer size used to store `SPINEL_PROP_PHY_CHAN_SUPPORTED` value.
};
enum State