blob: 547fbed5be7b6de196afa14af1478d698dd6f487 [file] [log] [blame]
/*
* Copyright (c) 2023, 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 CLI for MAC Filter.
*/
#include "cli_mac_filter.hpp"
#include "cli/cli.hpp"
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
namespace ot {
namespace Cli {
void MacFilter::OutputFilter(uint8_t aFilters)
{
otMacFilterEntry entry;
otMacFilterIterator iterator;
if (aFilters & kAddressFilter)
{
if ((aFilters & ~kAddressFilter) != 0)
{
OutputFormat("Address Mode: ");
}
OutputLine("%s", AddressModeToString(otLinkFilterGetAddressMode(GetInstancePtr())));
iterator = OT_MAC_FILTER_ITERATOR_INIT;
while (otLinkFilterGetNextAddress(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
{
OutputEntry(entry);
}
}
if (aFilters & kRssFilter)
{
if ((aFilters & ~kRssFilter) != 0)
{
OutputLine("RssIn List:");
}
iterator = OT_MAC_FILTER_ITERATOR_INIT;
while (otLinkFilterGetNextRssIn(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
{
if (IsDefaultRss(entry.mExtAddress))
{
OutputLine("Default rss: %d (lqi %u)", entry.mRssIn,
otLinkConvertRssToLinkQuality(GetInstancePtr(), entry.mRssIn));
}
else
{
OutputEntry(entry);
}
}
}
}
bool MacFilter::IsDefaultRss(const otExtAddress &aExtAddress)
{
// In default RSS entry, the extended address will be all `0xff`.
bool isDefault = true;
for (uint8_t byte : aExtAddress.m8)
{
if (byte != 0xff)
{
isDefault = false;
break;
}
}
return isDefault;
}
const char *MacFilter::AddressModeToString(otMacFilterAddressMode aMode)
{
static const char *const kModeStrings[] = {
"Disabled", // (0) OT_MAC_FILTER_ADDRESS_MODE_DISABLED
"Allowlist", // (1) OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST
"Denylist", // (2) OT_MAC_FILTER_ADDRESS_MODE_DENYLIST
};
static_assert(0 == OT_MAC_FILTER_ADDRESS_MODE_DISABLED, "OT_MAC_FILTER_ADDRESS_MODE_DISABLED value is incorrect");
static_assert(1 == OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST, "OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST value is incorrect");
static_assert(2 == OT_MAC_FILTER_ADDRESS_MODE_DENYLIST, "OT_MAC_FILTER_ADDRESS_MODE_DENYLIST value is incorrect");
return Stringify(aMode, kModeStrings);
}
void MacFilter::OutputEntry(const otMacFilterEntry &aEntry)
{
OutputExtAddress(aEntry.mExtAddress);
if (aEntry.mRssIn != OT_MAC_FILTER_FIXED_RSS_DISABLED)
{
OutputFormat(" : rss %d (lqi %d)", aEntry.mRssIn,
otLinkConvertRssToLinkQuality(GetInstancePtr(), aEntry.mRssIn));
}
OutputNewLine();
}
template <> otError MacFilter::Process<Cmd("addr")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otExtAddress extAddr;
/**
* @cli macfilter addr
* @code
* macfilter addr
* Allowlist
* 0f6127e33af6b403 : rss -95 (lqi 1)
* 0f6127e33af6b402
* Done
* @endcode
* @par
* Is available when `OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` configuration is enabled.
* @par
* Provides the following information:
* - Current mode of the MAC filter list: Either `AllowList`, `DenyList,` or `Disabled`
* - A list of all the extended addresses in the filter. The received signal strength (rss) and
* link quality indicator (lqi) are listed next to the address if these values have been set to be
* different from the default values.
* @sa otLinkFilterGetAddressMode
*/
if (aArgs[0].IsEmpty())
{
OutputFilter(kAddressFilter);
}
/**
* @cli macfilter addr add
* @code
* macfilter addr add 0f6127e33af6b403 -95
* Done
* @endcode
* @code
* macfilter addr add 0f6127e33af6b402
* Done
* @endcode
* @cparam macfilter addr add @ca{extaddr} [@ca{rss}]
* @par
* Is available only when `OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` configuration is enabled.
* @par
* Adds an IEEE 802.15.4 Extended Address to the MAC filter list.
* If you specify the optional `rss` argument, this fixes the received signal strength for messages from the
* address. If you do not use the `rss` option, the address will use whatever default value you have set.
* If you have not set a default, the signal strength will be the over-air signal.
* @sa otLinkFilterAddAddress
*/
else if (aArgs[0] == "add")
{
SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
error = otLinkFilterAddAddress(GetInstancePtr(), &extAddr);
VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_ALREADY);
if (!aArgs[2].IsEmpty())
{
int8_t rss;
SuccessOrExit(error = aArgs[2].ParseAsInt8(rss));
SuccessOrExit(error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss));
}
}
/**
* @cli macfilter addr remove
* @code
* macfilter addr remove 0f6127e33af6b402
* Done
* @endcode
* @cparam macfilter addr remove @ca{extaddr}
* @par
* Is available when `OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` configuration is enabled.
* @par
* This command removes the specified extended address from the MAC filter list.
* @note No action is performed if the specified extended address does not match an entry in the MAC filter list.
* @sa otLinkFilterRemoveAddress
*/
else if (aArgs[0] == "remove")
{
SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
otLinkFilterRemoveAddress(GetInstancePtr(), &extAddr);
}
/**
* @cli macfilter addr clear
* @code
* macfilter addr clear
* Done
* @endcode
* @par
* Is available when `OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` configuration is enabled.
* @par
* This command clears all the extended addresses from the MAC filter list.
* @note This command does not affect entries in the `RssIn` list. That list contains extended addresses where the
* `rss` has been set to a fixed value that differs from the default.
* @sa otLinkFilterClearAddresses
*/
else if (aArgs[0] == "clear")
{
otLinkFilterClearAddresses(GetInstancePtr());
}
else
{
static const char *const kModeCommands[] = {
/**
* @cli macfilter addr disable
* @code
* macfilter addr disable
* Done
* @endcode
* @par
* Disables MAC filter modes.
*/
"disable", // (0) OT_MAC_FILTER_ADDRESS_MODE_DISABLED
/**
* @cli macfilter addr allowlist
* @code
* macfilter addr allowlist
* Done
* @endcode
* @par
* Enables the `allowlist` MAC filter mode, which means that only the MAC addresses in the MAC filter list
* will be allowed access.
* @sa otLinkFilterSetAddressMode
*/
"allowlist", // (1) OT_MAC_FILTER_ADDRESS_MODE_ALLOWLIST
/**
* @cli macfilter addr denylist
* @code
* macfilter addr denylist
* Done
* @endcode
* @par
* Enables the `denylist` MAC filter mode, which means that all MAC addresses in the MAC filter list
* will be denied access.
* @sa otLinkFilterSetAddressMode
*/
"denylist", // (2) OT_MAC_FILTER_ADDRESS_MODE_DENYLIST
};
for (size_t index = 0; index < OT_ARRAY_LENGTH(kModeCommands); index++)
{
if (aArgs[0] == kModeCommands[index])
{
VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
otLinkFilterSetAddressMode(GetInstancePtr(), static_cast<otMacFilterAddressMode>(index));
ExitNow();
}
}
error = OT_ERROR_INVALID_COMMAND;
}
exit:
return error;
}
/**
* @cli macfilter rss
* @code
* macfilter rss
* 0f6127e33af6b403 : rss -95 (lqi 1)
* Default rss: -50 (lqi 3)
* Done
* @endcode
* @par
* Provides the following information:
* - Listing of all the extended addresses
* where the received signal strength (`rss`) has been set to be different from
* the default value. The link quality indicator (`lqi`) is also shown. The `rss`
* and `lqi` settings map to each other. If you set one, the value of the other
* gets set automatically. This list of addresses is called the `RssIn List`.
* Setting either the `rsi` or the `lqi` adds the corresponding extended address
* to the `RssIn` list.
* - `Default rss`: Shows the default values, if applicable, for the `rss` and `lqi` settings.
* @sa otLinkFilterGetNextRssIn
*/
template <> otError MacFilter::Process<Cmd("rss")>(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otExtAddress extAddr;
int8_t rss;
if (aArgs[0].IsEmpty())
{
OutputFilter(kRssFilter);
}
/**
* @cli macfilter rss add-lqi
* @code
* macfilter rss add-lqi * 3
* Done
* @endcode
* @code
* macfilter rss add-lqi 0f6127e33af6b404 2
* Done
* @endcode
* @cparam macfilter rss add-lqi @ca{extaddr} @ca{lqi}
* To set a default value for the link quality indicator for all received messages,
* use the `*` for the `extaddr` argument. The allowed range is 0 to 3.
* @par
* Adds the specified Extended Address to the `RssIn` list (or modifies an existing address in the `RssIn` list)
* and sets the fixed link quality indicator for messages from that address.
* The Extended Address
* does not necessarily have to be in the `address allowlist/denylist` filter to set the `lqi`.
* @note The `RssIn` list contains Extended Addresses whose `lqi` or
* received signal strength (`rss`) values have been set to be different from the defaults.
* The `lqi` will automatically get converted to a corresponding `rss` value.
* @par
* This is available when `OPENTHREAD_CONFIG_MAC_FILTER_ENABLE` configuration is enabled.
* @sa otLinkConvertLinkQualityToRss
* @sa otLinkFilterSetDefaultRssIn
*/
else if (aArgs[0] == "add-lqi")
{
uint8_t linkQuality;
SuccessOrExit(error = aArgs[2].ParseAsUint8(linkQuality));
VerifyOrExit(linkQuality <= 3, error = OT_ERROR_INVALID_ARGS);
rss = otLinkConvertLinkQualityToRss(GetInstancePtr(), linkQuality);
if (aArgs[1] == "*")
{
otLinkFilterSetDefaultRssIn(GetInstancePtr(), rss);
}
else
{
SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss);
}
}
/**
* @cli macfilter rss add
* @code
* macfilter rss add * -50
* Done
* @endcode
* @code
* macfilter rss add 0f6127e33af6b404 -85
* Done
* @endcode
* @cparam macfilter rss add @ca{extaddr} @ca{rss}
* To set a default value for the received signal strength for all received messages,
* use the `*` for the `extaddr` argument.
* @par api_copy
* #otLinkFilterAddRssIn
*/
else if (aArgs[0] == "add")
{
SuccessOrExit(error = aArgs[2].ParseAsInt8(rss));
if (aArgs[1] == "*")
{
otLinkFilterSetDefaultRssIn(GetInstancePtr(), rss);
}
else
{
SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
error = otLinkFilterAddRssIn(GetInstancePtr(), &extAddr, rss);
}
}
/**
* @cli macfilter rss remove
* @code
* macfilter rss remove *
* Done
* @endcode
* @code
* macfilter rss remove 0f6127e33af6b404
* Done
* @endcode
* @cparam macfilter rss remove @ca{extaddr}
* If you wish to remove the default received signal strength and link quality indicator settings,
* use the `*` as the `extaddr`. This unsets the defaults but does not remove
* entries from the `RssIn` list.
* @par api_copy
* #otLinkFilterRemoveRssIn
*/
else if (aArgs[0] == "remove")
{
if (aArgs[1] == "*")
{
otLinkFilterClearDefaultRssIn(GetInstancePtr());
}
else
{
SuccessOrExit(error = aArgs[1].ParseAsHexString(extAddr.m8));
otLinkFilterRemoveRssIn(GetInstancePtr(), &extAddr);
}
}
/**
* @cli macfilter rss clear
* @code
* macfilter rss clear
* Done
* @endcode
* @par api_copy
* #otLinkFilterClearAllRssIn
*/
else if (aArgs[0] == "clear")
{
otLinkFilterClearAllRssIn(GetInstancePtr());
}
else
{
error = OT_ERROR_INVALID_COMMAND;
}
exit:
return error;
}
otError MacFilter::Process(Arg aArgs[])
{
#define CmdEntry(aCommandString) \
{ \
aCommandString, &MacFilter::Process<Cmd(aCommandString)> \
}
static constexpr Command kCommands[] = {
CmdEntry("addr"),
CmdEntry("rss"),
};
#undef CmdEntry
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
otError error = OT_ERROR_INVALID_COMMAND;
const Command *command;
/**
* @cli macfilter
* @code
* macfilter
* Address Mode: Allowlist
* 0f6127e33af6b403 : rss -95 (lqi 1)
* 0f6127e33af6b402
* RssIn List:
* 0f6127e33af6b403 : rss -95 (lqi 1)
* Default rss: -50 (lqi 3)
* Done
* @endcode
* @par
* Provides the following information:
* - `Address Mode`: Current mode of the MAC filter: Either `AllowList`, `DenyList,` or `Disabled`
* - A list of all the extended addresses in the MAC filter list. The received signal strength (rss) and
* link quality indicator (lqi) are listed next to the address if these values have been set to be
* different from the default values.
* - A separate list (`RssIn List`) that shows all the extended addresses where the `rss` has been set to
* be different from the default value.
* - `Default rss`: Shows the default values, if applicable, for the `rss` and `lqi` settings.
* @note An extended address can be in the `RssIn` list without being in the MAC filter list.
* @sa otLinkFilterSetAddressMode
* @sa otLinkFilterGetNextAddress
* @sa otLinkFilterGetNextRssIn
*/
if (aArgs[0].IsEmpty())
{
OutputFilter(kAddressFilter | kRssFilter);
ExitNow(error = OT_ERROR_NONE);
}
command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
VerifyOrExit(command != nullptr);
error = (this->*command->mHandler)(aArgs + 1);
exit:
return error;
}
} // namespace Cli
} // namespace ot
#endif // OPENTHREAD_CONFIG_MAC_FILTER_ENABLE