diff --git a/src/cli/README_NETDATA.md b/src/cli/README_NETDATA.md index ad33bb993..940288596 100644 --- a/src/cli/README_NETDATA.md +++ b/src/cli/README_NETDATA.md @@ -334,10 +334,12 @@ Done ### show -Usage: `netdata show [local] [-x]` +Usage: `netdata show [local] [-x] [\]` Print entries in Network Data, on-mesh prefixes, external routes, services, and 6LoWPAN context information. +If the optional `rloc16` input is specified, prints the entries associated with the given RLOC16 only. The RLOC16 filtering can be used when `-x` or `local` are not used. + On-mesh prefixes are listed under `Prefixes` header: - The on-mesh prefix @@ -406,6 +408,19 @@ Commissioning: Done ``` +Print Network Data entries from the Leader associated with `0xa00` RLOC16. + +```bash +> netdata show 0xa00 +Prefixes: +fd00:dead:beef:cafe::/64 paros med a000 +Routes: +fd00:1234:0:0::/64 s med a000 +Services: +44970 5d fddead00beef00007bad0069ce45948504d2 s a000 +Done +``` + Print Network Data received from the Leader as hex-encoded TLVs. ```bash diff --git a/src/cli/cli_network_data.cpp b/src/cli/cli_network_data.cpp index fc25c9b56..7aa0dd5ed 100644 --- a/src/cli/cli_network_data.cpp +++ b/src/cli/cli_network_data.cpp @@ -564,7 +564,7 @@ otError NetworkData::GetNextPrefix(otNetworkDataIterator *aIterator, otBorderRou return error; } -void NetworkData::OutputNetworkData(bool aLocal) +void NetworkData::OutputNetworkData(bool aLocal, uint16_t aRloc16) { otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; otBorderRouterConfig prefix; @@ -577,7 +577,10 @@ void NetworkData::OutputNetworkData(bool aLocal) while (GetNextPrefix(&iterator, &prefix, aLocal) == OT_ERROR_NONE) { - OutputPrefix(prefix); + if ((aRloc16 == kAnyRloc16) || (aRloc16 == prefix.mRloc16)) + { + OutputPrefix(prefix); + } } OutputLine("Routes:"); @@ -585,7 +588,10 @@ void NetworkData::OutputNetworkData(bool aLocal) while (GetNextRoute(&iterator, &route, aLocal) == OT_ERROR_NONE) { - OutputRoute(route); + if ((aRloc16 == kAnyRloc16) || (aRloc16 == route.mRloc16)) + { + OutputRoute(route); + } } OutputLine("Services:"); @@ -593,10 +599,14 @@ void NetworkData::OutputNetworkData(bool aLocal) while (GetNextService(&iterator, &service, aLocal) == OT_ERROR_NONE) { - OutputService(service); + if ((aRloc16 == kAnyRloc16) || (aRloc16 == service.mServerConfig.mRloc16)) + { + OutputService(service); + } } VerifyOrExit(!aLocal); + VerifyOrExit(aRloc16 == kAnyRloc16); OutputLine("Contexts:"); iterator = OT_NETWORK_DATA_ITERATOR_INIT; @@ -716,8 +726,16 @@ exit: * 08040b02174703140040fd00deadbeefcafe0504dc00330007021140 * Done * @endcode - * @cparam netdata show [@ca{-x}] + * @code + * netdata show 0xdc00 + * Prefixes: + * fd00:dead:beef:cafe::/64 paros med dc00 + * Routes: + * Services: + * Done + * @cparam netdata show [@ca{-x}|@ca{rloc16}] * * The optional `-x` argument gets Network Data as hex-encoded TLVs. + * * The optional `rloc16` argument gets all prefix/route/service entries associated with a given RLOC16. * @par * `netdata show` from OT CLI gets full Network Data received from the Leader. This command uses several * API functions to combine prefixes, routes, and services, including #otNetDataGetNextOnMeshPrefix, @@ -774,9 +792,10 @@ exit: */ template <> otError NetworkData::Process(Arg aArgs[]) { - otError error = OT_ERROR_INVALID_ARGS; - bool local = false; - bool binary = false; + otError error = OT_ERROR_INVALID_ARGS; + uint16_t rloc16 = kAnyRloc16; + bool local = false; + bool binary = false; for (uint8_t i = 0; !aArgs[i].IsEmpty(); i++) { @@ -811,17 +830,22 @@ template <> otError NetworkData::Process(Arg aArgs[]) } else { - ExitNow(error = OT_ERROR_INVALID_ARGS); + SuccessOrExit(error = aArgs[i].ParseAsUint16(rloc16)); } } + if (local || binary) + { + VerifyOrExit(rloc16 == kAnyRloc16, error = OT_ERROR_INVALID_ARGS); + } + if (binary) { error = OutputBinary(local); } else { - OutputNetworkData(local); + OutputNetworkData(local, rloc16); error = OT_ERROR_NONE; } diff --git a/src/cli/cli_network_data.hpp b/src/cli/cli_network_data.hpp index 61cd81897..ba8f281c4 100644 --- a/src/cli/cli_network_data.hpp +++ b/src/cli/cli_network_data.hpp @@ -130,6 +130,8 @@ public: private: using Command = CommandEntry; + static constexpr uint16_t kAnyRloc16 = 0xffff; + template otError Process(Arg aArgs[]); otError GetNextPrefix(otNetworkDataIterator *aIterator, otBorderRouterConfig *aConfig, bool aLocal); @@ -137,7 +139,7 @@ private: otError GetNextService(otNetworkDataIterator *aIterator, otServiceConfig *aConfig, bool aLocal); otError OutputBinary(bool aLocal); - void OutputNetworkData(bool aLocal); + void OutputNetworkData(bool aLocal, uint16_t aRloc16); #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL static void HandleNetdataFull(void *aContext) { static_cast(aContext)->HandleNetdataFull(); } diff --git a/tests/toranj/cli/cli.py b/tests/toranj/cli/cli.py index 78c0229f2..89be4701e 100644 --- a/tests/toranj/cli/cli.py +++ b/tests/toranj/cli/cli.py @@ -398,19 +398,23 @@ class Node(object): #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # netdata - def get_netdata(self): - outputs = self.cli('netdata show') + def get_netdata(self, rloc16=None): + outputs = self.cli('netdata show', rloc16) outputs = [line.strip() for line in outputs] routes_index = outputs.index('Routes:') services_index = outputs.index('Services:') - contexts_index = outputs.index('Contexts:') - commissioning_index = outputs.index('Commissioning:') + if rloc16 is None: + contexts_index = outputs.index('Contexts:') + commissioning_index = outputs.index('Commissioning:') result = {} result['prefixes'] = outputs[1:routes_index] result['routes'] = outputs[routes_index + 1:services_index] - result['services'] = outputs[services_index + 1:contexts_index] - result['contexts'] = outputs[contexts_index + 1:commissioning_index] - result['commissioning'] = outputs[commissioning_index + 1:] + if rloc16 is None: + result['services'] = outputs[services_index + 1:contexts_index] + result['contexts'] = outputs[contexts_index + 1:commissioning_index] + result['commissioning'] = outputs[commissioning_index + 1:] + else: + result['services'] = outputs[services_index + 1:] return result diff --git a/tests/toranj/cli/test-011-network-data-timeout.py b/tests/toranj/cli/test-011-network-data-timeout.py index a3a4086a7..bf524878f 100755 --- a/tests/toranj/cli/test-011-network-data-timeout.py +++ b/tests/toranj/cli/test-011-network-data-timeout.py @@ -89,11 +89,6 @@ nodes = [r1, r2, c2] # ----------------------------------------------------------------------------------------------------------------------- # Test Implementation -common_prefix = 'fd00:cafe::' -prefix1 = 'fd00:1::' -prefix2 = 'fd00:2::' -prefix3 = 'fd00:3::' - # Each node adds its own prefix. r1.add_prefix('fd00:1::/64', 'paros', 'med') r2.add_prefix('fd00:2::/64', 'paros', 'med') @@ -104,6 +99,9 @@ r1.add_prefix('fd00:abba::/64', 'paros', 'high') r2.add_prefix('fd00:abba::/64', 'paros', 'med') c2.add_prefix('fd00:abba::/64', 'paros', 'low') +r1.add_route('fd00:cafe::/64', 's', 'med') +r2.add_route('fd00:cafe::/64', 's', 'med') + r1.register_netdata() r2.register_netdata() c2.register_netdata() @@ -112,12 +110,19 @@ c2.register_netdata() def check_netdata_on_all_nodes(): for node in nodes: netdata = node.get_netdata() - prefixes = netdata['prefixes'] - verify(len(prefixes) == 6) + verify(len(netdata['prefixes']) == 6) + verify(len(netdata['routes']) == 2) verify_within(check_netdata_on_all_nodes, 10) +# Check netdata filtering for r1 entries only. + +r1_rloc = int(r1.get_rloc16(), 16) +netdata = r1.get_netdata(r1_rloc) +verify(len(netdata['prefixes']) == 2) +verify(len(netdata['routes']) == 1) + # Remove `r2`. This should trigger all the prefixes added by it or its # child to timeout and be removed. @@ -127,8 +132,11 @@ r2.interface_down() def check_netdata_on_r1(): netdata = r1.get_netdata() - prefixes = netdata['prefixes'] - verify(len(prefixes) == 2) + verify(len(netdata['prefixes']) == 2) + verify(len(netdata['routes']) == 1) + netdata = r1.get_netdata(r1_rloc) + verify(len(netdata['prefixes']) == 2) + verify(len(netdata['routes']) == 1) verify_within(check_netdata_on_r1, 120)