From bb5f9a4c7f87cdc051b23afd265df88ec6c136e2 Mon Sep 17 00:00:00 2001 From: ZhangLe2016 <156590889+ZhangLe2016@users.noreply.github.com> Date: Tue, 3 Dec 2024 02:08:29 +0000 Subject: [PATCH] [api] enable DIAG_RST notify funcation into commissioner (#305) This commit adds DIAG_RST notify command into the commissioner module, allowing users to reset MacCounters(9) TLV from a peer Thread device by settting the device's mesh local address and TLV mask bits flag. --- include/commissioner/commissioner.hpp | 32 +++++++++++++++++++ src/app/cli/interpreter.cpp | 28 +++++++++++++++- src/app/commissioner_app.cpp | 8 +++++ src/app/commissioner_app.hpp | 1 + src/app/commissioner_app_dummy.cpp | 7 ++++ src/app/commissioner_app_mock.hpp | 1 + src/app/json.cpp | 25 +++++++++++++++ src/app/json.hpp | 1 + src/library/commissioner_impl.cpp | 46 +++++++++++++++++++++++++++ src/library/commissioner_impl.hpp | 2 ++ src/library/commissioner_safe.cpp | 13 ++++++++ src/library/commissioner_safe.hpp | 2 ++ tests/integration/test_cli.sh | 13 ++++++++ 13 files changed, 178 insertions(+), 1 deletion(-) diff --git a/include/commissioner/commissioner.hpp b/include/commissioner/commissioner.hpp index c162fd2d..3909efa4 100644 --- a/include/commissioner/commissioner.hpp +++ b/include/commissioner/commissioner.hpp @@ -1195,6 +1195,38 @@ class Commissioner * */ virtual Error CommandDiagGetQuery(const std::string &aAddr, uint64_t aDiagDataFlags) = 0; + + /** + * @brief Asynchronously reset dedicated diagnostic TLV(s) on a Thread device. + * + * This method sends a DIAG_RST.ntf message to the specified Thread device, + * resetting the diagnostic TLVs such as MacCounters indicated by `aDiagDataFlags`. + * The response, or any errors encountered, will be delivered to the provided `aHandler`. + * + * @param[in, out] aHandler A handler to process the response or any errors. + * This handler is guaranteed to be called. + * @param[in] aAddr Unicast mesh local address of the target Thread device, + * the leader ALOC will be used if it is empty. + * @param[in] aDiagDataFlags Diagnostic data flags indicate which TLVs are wanted. + * + */ + virtual void CommandDiagReset(ErrorHandler aHandler, const std::string &aAddr, uint64_t aDiagDataFlags) = 0; + + /** + * @brief Synchronously reset dedicated diagnostic TLVs on a Thread device. + * + * This method sends a DIAG_RST.ntf message to the specified Thread device, + * resetting the diagnostic TLVs such as MacCounters indicated by `aDiagDataFlags`. + * The method blocks until a response is received or an error occurs. + * + * @param[in] aAddr Unicast mesh local address of the target Thread device, + * the leader ALOC will be used if it is empty. + * @param[in] aDiagDataFlags Diagnostic data flags indicate which TLVs are wanted. + * + * @return Error::kNone, succeed; Otherwise, failed. + * + */ + virtual Error CommandDiagReset(const std::string &aAddr, uint64_t aDiagDataFlags) = 0; }; } // namespace commissioner diff --git a/src/app/cli/interpreter.cpp b/src/app/cli/interpreter.cpp index 7cca806e..8a35f9ad 100644 --- a/src/app/cli/interpreter.cpp +++ b/src/app/cli/interpreter.cpp @@ -117,6 +117,7 @@ #define WARN_NETWORK_SELECTION_CHANGED "Network selection was changed by the command" #define DIAG_GET_QRY_TYPE 1 +#define DIAG_RST_NTF_TYPE 2 #define COLOR_ALIAS_FAILED Console::Color::kYellow @@ -281,7 +282,8 @@ const std::map &Interpreter::mUsageMap = *new std::map "panid conflict "}, {"energy", "energy scan \n" "energy report []"}, - {"netdiag", "netdiag query [extaddr | rloc16] "}, + {"netdiag", "netdiag query [extaddr | rloc16] \n" + "netdiag reset maccounters "}, {"exit", "exit"}, {"quit", "quit\n" "(an alias to 'exit' command)"}, @@ -2591,6 +2593,10 @@ Interpreter::Value Interpreter::ProcessNetworkDiagJob(CommissionerAppPtr &aCommi { operationType = DIAG_GET_QRY_TYPE; } + else if (CaseInsensitiveEqual(aExpr[1], "reset")) + { + operationType = DIAG_RST_NTF_TYPE; + } else { ExitNow(value = ERROR_INVALID_COMMAND(SYNTAX_INVALID_SUBCOMMAND, aExpr[1])); @@ -2628,6 +2634,26 @@ Interpreter::Value Interpreter::ProcessNetworkDiagJob(CommissionerAppPtr &aCommi } } } + if (CaseInsensitiveEqual(aExpr[2], "maccounters")) + { + flags = NetDiagData::kMacCountersBit; + if (operationType == DIAG_RST_NTF_TYPE) + { + SuccessOrExit(value = aCommissioner->CommandDiagReset(dstAddr, flags)); + } + else if (operationType == DIAG_GET_QRY_TYPE) + { + SuccessOrExit(value = aCommissioner->CommandDiagGetQuery(dstAddr, flags)); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + diagData.mPresentFlags = flags; + DiagAnsDataMap diagAnsDataMaps = aCommissioner->GetNetDiagTlvs(); + for (auto &diagAnsDataMap : diagAnsDataMaps) + { + value = "Peer Address: " + (diagAnsDataMap.first).ToString() + + "\nContent: " + NetDiagDataToJson(diagAnsDataMap.second); + } + } + } exit: return value; diff --git a/src/app/commissioner_app.cpp b/src/app/commissioner_app.cpp index 780e757e..976b1116 100644 --- a/src/app/commissioner_app.cpp +++ b/src/app/commissioner_app.cpp @@ -1413,6 +1413,14 @@ const DiagAnsDataMap &CommissionerApp::GetNetDiagTlvs() const return mDiagAnsDataMap; } +Error CommissionerApp::CommandDiagReset(const std::string &aAddr, uint64_t aDiagDataFlags) +{ + Error error; + + error = mCommissioner->CommandDiagReset(aAddr, aDiagDataFlags); + return error; +} + } // namespace commissioner } // namespace ot diff --git a/src/app/commissioner_app.hpp b/src/app/commissioner_app.hpp index e383636e..4a30e885 100644 --- a/src/app/commissioner_app.hpp +++ b/src/app/commissioner_app.hpp @@ -236,6 +236,7 @@ class CommissionerApp : public CommissionerHandler // Network Diagnostic MOCKABLE Error CommandDiagGetQuery(const std::string &aAddr, uint64_t aDiagDataFlags); + MOCKABLE Error CommandDiagReset(const std::string &aAddr, uint64_t aDiagDataFlags); /* * BBR Dataset APIs diff --git a/src/app/commissioner_app_dummy.cpp b/src/app/commissioner_app_dummy.cpp index 2cd9f6da..1f312bc9 100644 --- a/src/app/commissioner_app_dummy.cpp +++ b/src/app/commissioner_app_dummy.cpp @@ -538,6 +538,13 @@ Error CommissionerApp::CommandDiagGetQuery(const std::string &aAddr, uint64_t aD return Error{}; } +Error CommissionerApp::CommandDiagReset(const std::string &aAddr, uint64_t aDiagTlvFlags) +{ + UNUSED(aAddr); + UNUSED(aDiagTlvFlags); + return Error{}; +} + } // namespace commissioner } // namespace ot diff --git a/src/app/commissioner_app_mock.hpp b/src/app/commissioner_app_mock.hpp index 851849a9..d3f9260d 100644 --- a/src/app/commissioner_app_mock.hpp +++ b/src/app/commissioner_app_mock.hpp @@ -141,6 +141,7 @@ class CommissionerAppMock : public ::ot::commissioner::CommissionerApp MOCK_METHOD(const EnergyReportMap &, GetAllEnergyReports, (), (const)); MOCK_METHOD(const DiagAnsDataMap &, GetNetDiagTlvs, (), (const)); MOCK_METHOD(Error, CommandDiagGetQuery, (const std::string &, uint64_t)); + MOCK_METHOD(Error, CommandDiagReset, (const std::string &, uint64_t)); }; class CommissionerAppStaticExpecter diff --git a/src/app/json.cpp b/src/app/json.cpp index 6cbffa80..6aab9823 100644 --- a/src/app/json.cpp +++ b/src/app/json.cpp @@ -777,6 +777,10 @@ static void to_json(Json &aJson, const NetDiagData &aNetDiagData) SET_IF_PRESENT(ExtMacAddr); SET_IF_PRESENT(MacAddr); #undef SET_IF_PRESENT + if (aNetDiagData.mPresentFlags & NetDiagData::kMacCountersBit) + { + aJson["MacCounters"] = MacCountersToJson(aNetDiagData.mMacCounters); + } } std::string NetDiagDataToJson(const NetDiagData &aNetDiagData) @@ -785,6 +789,27 @@ std::string NetDiagDataToJson(const NetDiagData &aNetDiagData) return json.dump(JSON_INDENT_DEFAULT); } +static void to_json(Json &aJson, const MacCounters &aMacCounters) +{ +#define SET(name) aJson[#name] = aMacCounters.m##name; + SET(IfInUnknownProtos); + SET(IfInErrors); + SET(IfOutErrors); + SET(IfInUcastPkts); + SET(IfInBroadcastPkts); + SET(IfInDiscards); + SET(IfOutUcastPkts); + SET(IfOutBroadcastPkts); + SET(IfOutDiscards); +#undef SET +} + +std::string MacCountersToJson(const MacCounters &aMacCounters) +{ + Json json = aMacCounters; + return json.dump(JSON_INDENT_DEFAULT); +} + Error JsonFromFile(std::string &aJson, const std::string &aPath) { Error error; diff --git a/src/app/json.hpp b/src/app/json.hpp index c563310e..26ffe816 100644 --- a/src/app/json.hpp +++ b/src/app/json.hpp @@ -63,6 +63,7 @@ struct NetworkData Error NetworkDataFromJson(NetworkData &aNetworkData, const std::string &aJson); std::string NetworkDataToJson(const NetworkData &aNetworkData); +std::string MacCountersToJson(const MacCounters &aMacCounters); Error CommissionerDatasetFromJson(CommissionerDataset &aDataset, const std::string &aJson); std::string CommissionerDatasetToJson(const CommissionerDataset &aDataset); diff --git a/src/library/commissioner_impl.cpp b/src/library/commissioner_impl.cpp index 9878a3bb..728472f8 100644 --- a/src/library/commissioner_impl.cpp +++ b/src/library/commissioner_impl.cpp @@ -692,6 +692,52 @@ void CommissionerImpl::HandleDiagGetAnswer(const coap::Request &aRequest) } } +void CommissionerImpl::CommandDiagReset(ErrorHandler aHandler, const std::string &aAddr, uint64_t aDiagDataFlags) +{ + Error error; + Address dstAddr; + coap::Request request{coap::Type::kConfirmable, coap::Code::kPost}; + auto onResponse = [aHandler](const coap::Response *aResponse, Error aError) { + Error error; + + SuccessOrExit(error = aError); + SuccessOrExit(error = CheckCoapResponseCode(*aResponse)); + + exit: + aHandler(error); + }; + + VerifyOrExit(IsActive(), error = ERROR_INVALID_STATE("commissioner is not active")); + SuccessOrExit(error = request.SetUriPath(uri::kDiagRst)); + SuccessOrExit(error = AppendTlv(request, {tlv::Type::kNetworkDiagTypeList, GetNetDiagTlvTypes(aDiagDataFlags), + tlv::Scope::kNetworkDiag})); + +#if OT_COMM_CONFIG_CCM_ENABLE + if (IsCcmMode()) + { + SuccessOrExit(error = SignRequest(request)); + } +#endif + + LOG_INFO(LOG_REGION_MESHDIAG, "sending DIAG_RST.ntf"); + if (aAddr.empty()) + { + mProxyClient.SendRequest(request, onResponse, kLeaderAloc16, kDefaultMmPort); + } + else + { + SuccessOrExit(error = dstAddr.Set(aAddr)); + mProxyClient.SendRequest(request, onResponse, dstAddr, kDefaultMmPort); + } + LOG_INFO(LOG_REGION_MESHDIAG, "sent DIAG_RST.ntf"); + +exit: + if (error != ErrorCode::kNone) + { + aHandler(error); + } +} + void CommissionerImpl::SetPendingDataset(ErrorHandler aHandler, const PendingOperationalDataset &aPendingDataset) { Error error; diff --git a/src/library/commissioner_impl.hpp b/src/library/commissioner_impl.hpp index a1346b83..7a4fd277 100644 --- a/src/library/commissioner_impl.hpp +++ b/src/library/commissioner_impl.hpp @@ -195,6 +195,8 @@ class CommissionerImpl : public Commissioner void CommandDiagGetQuery(ErrorHandler aHandler, const std::string &aAddr, uint64_t aDiagDataFlags) override; Error CommandDiagGetQuery(const std::string &, uint64_t) override { return ERROR_UNIMPLEMENTED(""); } + void CommandDiagReset(ErrorHandler aHandler, const std::string &aAddr, uint64_t aDiagDataFlags) override; + Error CommandDiagReset(const std::string &, uint64_t) override { return ERROR_UNIMPLEMENTED(""); } Error SetToken(const ByteArray &aSignedToken) override; diff --git a/src/library/commissioner_safe.cpp b/src/library/commissioner_safe.cpp index b36dba2c..b59c64d7 100644 --- a/src/library/commissioner_safe.cpp +++ b/src/library/commissioner_safe.cpp @@ -574,6 +574,19 @@ void CommissionerSafe::Invoke(evutil_socket_t, short, void *aContext) } } +void CommissionerSafe::CommandDiagReset(ErrorHandler aHandler, const std::string &aAddr, uint64_t aDiagDataFlags) +{ + PushAsyncRequest([=]() { mImpl->CommandDiagReset(aHandler, aAddr, aDiagDataFlags); }); +} + +Error CommissionerSafe::CommandDiagReset(const std::string &aAddr, uint64_t aDiagDataFlags) +{ + std::promise pro; + auto wait = [&pro](Error error) { pro.set_value(error); }; + CommandDiagReset(wait, aAddr, aDiagDataFlags); + return pro.get_future().get(); +} + void CommissionerSafe::PushAsyncRequest(AsyncRequest &&aAsyncRequest) { std::lock_guard _(mInvokeMutex); diff --git a/src/library/commissioner_safe.hpp b/src/library/commissioner_safe.hpp index f4beb3e7..2380494e 100644 --- a/src/library/commissioner_safe.hpp +++ b/src/library/commissioner_safe.hpp @@ -143,6 +143,8 @@ class CommissionerSafe : public Commissioner void CommandDiagGetQuery(ErrorHandler aHandler, const std::string &aAddr, uint64_t aDiagDataFlags) override; Error CommandDiagGetQuery(const std::string &aAddr, uint64_t aDiagDataFlags) override; + void CommandDiagReset(ErrorHandler aHandler, const std::string &aAddr, uint64_t aDiagDataFlags) override; + Error CommandDiagReset(const std::string &aAddr, uint64_t aDiagDataFlags) override; void CommandMigrate(ErrorHandler aHandler, const std::string &aDstAddr, diff --git a/tests/integration/test_cli.sh b/tests/integration/test_cli.sh index ef37257f..e7370974 100755 --- a/tests/integration/test_cli.sh +++ b/tests/integration/test_cli.sh @@ -67,3 +67,16 @@ test_execute_diag_command() stop_daemon } + +test_execute_diag_command() +{ + start_daemon + form_network "${PSKC}" + + start_commissioner "${NON_CCM_CONFIG}" + petition_commissioner + send_command_to_commissioner "netdiag reset maccounters" + stop_commissioner + + stop_daemon +}