diff --git a/src/cli/README.md b/src/cli/README.md index a4919081e..41e4b5219 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -123,9 +123,9 @@ BBR Primary: None Done ``` -### bbr mgmt dua \ [meshLocalIid] +### bbr mgmt dua \ [meshLocalIid] -Configure the response status for DUA.req with meshLocalIid in payload. Without meshLocalIid, simply respond any coming DUA.req next with the specified status. +Configure the response status for DUA.req with meshLocalIid in payload. Without meshLocalIid, simply respond any coming DUA.req next with the specified status or COAP code. Only for testing/reference device. @@ -138,10 +138,13 @@ known status value: - 4: ST_DUA_NO_RESOURCES - 5: ST_DUA_BBR_NOT_PRIMARY - 6: ST_DUA_GENERAL_FAILURE +- 160: COAP code 5.00 ```bash > bbr mgmt dua 1 2f7c235e5025a2fd Done +> bbr mgmt dua 160 +Done ``` ### bbr mgmt mlr listener diff --git a/src/core/backbone_router/bbr_manager.cpp b/src/core/backbone_router/bbr_manager.cpp index 0f85e2636..658f14ed5 100644 --- a/src/core/backbone_router/bbr_manager.cpp +++ b/src/core/backbone_router/bbr_manager.cpp @@ -296,6 +296,9 @@ void Manager::HandleDuaRegistration(const Coap::Message &aMessage, const Ip6::Me bool hasLastTransactionTime; Ip6::Address target; Ip6::InterfaceIdentifier meshLocalIid; +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + Coap::Code duaRespCoapCode = Coap::kCodeEmpty; +#endif VerifyOrExit(aMessageInfo.GetPeerAddr().GetIid().IsRoutingLocator(), error = OT_ERROR_DROP); VerifyOrExit(aMessage.IsConfirmablePostRequest(), error = OT_ERROR_PARSE); @@ -307,7 +310,15 @@ void Manager::HandleDuaRegistration(const Coap::Message &aMessage, const Ip6::Me if (mDuaResponseIsSpecified && (mDuaResponseTargetMlIid.IsUnspecified() || mDuaResponseTargetMlIid == meshLocalIid)) { mDuaResponseIsSpecified = false; - ExitNow(status = mDuaResponseStatus); + if (mDuaResponseStatus >= Coap::kCodeResponseMin) + { + duaRespCoapCode = static_cast(mDuaResponseStatus); + } + else + { + status = static_cast(mDuaResponseStatus); + } + ExitNow(); } #endif @@ -343,7 +354,16 @@ exit: if (error == OT_ERROR_NONE) { - SendDuaRegistrationResponse(aMessage, aMessageInfo, target, status); +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + if (duaRespCoapCode != Coap::kCodeEmpty) + { + IgnoreError(Get().SendEmptyAck(aMessage, aMessageInfo, duaRespCoapCode)); + } + else +#endif + { + SendDuaRegistrationResponse(aMessage, aMessageInfo, target, status); + } } } @@ -385,7 +405,7 @@ void Manager::ConfigNextDuaRegistrationResponse(const Ip6::InterfaceIdentifier * mDuaResponseTargetMlIid.Clear(); } - mDuaResponseStatus = static_cast(aStatus); + mDuaResponseStatus = aStatus; } void Manager::ConfigNextMulticastListenerRegistrationResponse(ThreadStatusTlv::MlrStatus aStatus) diff --git a/src/core/backbone_router/bbr_manager.hpp b/src/core/backbone_router/bbr_manager.hpp index d7a1998df..09d649adc 100644 --- a/src/core/backbone_router/bbr_manager.hpp +++ b/src/core/backbone_router/bbr_manager.hpp @@ -179,7 +179,7 @@ private: #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE Ip6::InterfaceIdentifier mDuaResponseTargetMlIid; - ThreadStatusTlv::DuaStatus mDuaResponseStatus; + uint8_t mDuaResponseStatus; ThreadStatusTlv::MlrStatus mMlrResponseStatus; bool mDuaResponseIsSpecified : 1; bool mMlrResponseIsSpecified : 1; diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index ee2093a0c..f602b23fe 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -252,10 +252,9 @@ otError CoapBase::SendAck(const Message &aRequest, const Ip6::MessageInfo &aMess return SendEmptyMessage(kTypeAck, aRequest, aMessageInfo); } -otError CoapBase::SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) +otError CoapBase::SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode) { - return (aRequest.IsConfirmable() ? SendHeaderResponse(kCodeChanged, aRequest, aMessageInfo) - : OT_ERROR_INVALID_ARGS); + return (aRequest.IsConfirmable() ? SendHeaderResponse(aCode, aRequest, aMessageInfo) : OT_ERROR_INVALID_ARGS); } otError CoapBase::SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index 6ba52696f..182b13b89 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -437,13 +437,14 @@ public: * * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. * @param[in] aMessageInfo The message info corresponding to the CoAP request. + * @param[in] aCode The CoAP code of the dummy CoAP response. * * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. * @retval OT_ERROR_INVALID_ARGS The @p aRequest header is not of confirmable type. * */ - otError SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); + otError SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode = kCodeChanged); /** * This method sends a header-only CoAP message to indicate no resource matched for the request. diff --git a/src/core/coap/coap_message.hpp b/src/core/coap/coap_message.hpp index 312a43248..c44de7cb1 100644 --- a/src/core/coap/coap_message.hpp +++ b/src/core/coap/coap_message.hpp @@ -96,12 +96,13 @@ enum Code : uint8_t // Response Codes: - kCodeCreated = OT_COAP_CODE_CREATED, ///< Created - kCodeDeleted = OT_COAP_CODE_DELETED, ///< Deleted - kCodeValid = OT_COAP_CODE_VALID, ///< Valid - kCodeChanged = OT_COAP_CODE_CHANGED, ///< Changed - kCodeContent = OT_COAP_CODE_CONTENT, ///< Content - kCodeContinue = OT_COAP_CODE_CONTINUE, ///< RFC7959 Continue + kCodeResponseMin = OT_COAP_CODE_RESPONSE_MIN, ///< 2.00 + kCodeCreated = OT_COAP_CODE_CREATED, ///< Created + kCodeDeleted = OT_COAP_CODE_DELETED, ///< Deleted + kCodeValid = OT_COAP_CODE_VALID, ///< Valid + kCodeChanged = OT_COAP_CODE_CHANGED, ///< Changed + kCodeContent = OT_COAP_CODE_CONTENT, ///< Content + kCodeContinue = OT_COAP_CODE_CONTINUE, ///< RFC7959 Continue // Client Error Codes: diff --git a/src/core/thread/dua_manager.cpp b/src/core/thread/dua_manager.cpp index f41777007..947241ee6 100644 --- a/src/core/thread/dua_manager.cpp +++ b/src/core/thread/dua_manager.cpp @@ -504,7 +504,8 @@ void DuaManager::PerformNextRegistration(void) SuccessOrExit(error = Get().SendMessage(*message, messageInfo, &DuaManager::HandleDuaResponse, this)); - mIsDuaPending = true; + mIsDuaPending = true; + mRegisteringDua = dua; // TODO: (DUA) need update when CSL is enabled. if (!Get().IsRxOnWhenIdle()) @@ -535,7 +536,9 @@ void DuaManager::HandleDuaResponse(Coap::Message &aMessage, const Ip6::MessageIn ExitNow(error = aResult); } - VerifyOrExit(aResult == OT_ERROR_NONE && aMessage.GetCode() == Coap::kCodeChanged, error = OT_ERROR_PARSE); + VerifyOrExit(aResult == OT_ERROR_NONE, error = OT_ERROR_PARSE); + VerifyOrExit(aMessage.GetCode() == Coap::kCodeChanged || aMessage.GetCode() >= Coap::kCodeBadRequest, + error = OT_ERROR_PARSE); error = ProcessDuaResponse(aMessage); @@ -574,8 +577,16 @@ otError DuaManager::ProcessDuaResponse(Coap::Message &aMessage) Ip6::Address target; uint8_t status; - SuccessOrExit(error = Tlv::FindUint8Tlv(aMessage, ThreadTlv::kStatus, status)); - SuccessOrExit(error = Tlv::FindTlv(aMessage, ThreadTlv::kTarget, &target, sizeof(target))); + if (aMessage.GetCode() >= Coap::kCodeBadRequest) + { + status = ThreadStatusTlv::kDuaGeneralFailure; + target = mRegisteringDua; + } + else + { + SuccessOrExit(error = Tlv::FindUint8Tlv(aMessage, ThreadTlv::kStatus, status)); + SuccessOrExit(error = Tlv::FindTlv(aMessage, ThreadTlv::kTarget, &target, sizeof(target))); + } #if OPENTHREAD_CONFIG_DUA_ENABLE if (Get().HasUnicastAddress(target)) diff --git a/src/core/thread/dua_manager.hpp b/src/core/thread/dua_manager.hpp index 3ec82baa1..d0eccd57b 100644 --- a/src/core/thread/dua_manager.hpp +++ b/src/core/thread/dua_manager.hpp @@ -218,8 +218,8 @@ private: Tasklet mRegistrationTask; Coap::Resource mDuaNotification; - - bool mIsDuaPending : 1; + Ip6::Address mRegisteringDua; + bool mIsDuaPending : 1; #if OPENTHREAD_CONFIG_DUA_ENABLE enum DuaState diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index 136294f27..97d1e5f47 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -723,7 +723,13 @@ class NodeImpl: self.remove_prefix(prefix) self.register_netdata() - def set_next_dua_response(self, status, iid=None): + def set_next_dua_response(self, status: Union[str, int], iid=None): + # Convert 5.00 to COAP CODE 160 + if isinstance(status, str): + assert '.' in status + status = status.split('.') + status = (int(status[0]) << 5) + int(status[1]) + cmd = 'bbr mgmt dua {}'.format(status) if iid is not None: cmd += ' ' + str(iid) diff --git a/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py b/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py index 8af8e06d2..e27e8b8af 100755 --- a/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py +++ b/tests/scripts/thread-cert/v1_2_test_domain_unicast_address_registration.py @@ -281,8 +281,8 @@ class TestDomainUnicastAddressRegistration(thread_cert.TestCase): # - increase BBR seqno to trigger reregistration # - ROUTER_1_2 should re-register within BBR_REREGISTRATION_DELAY. For the not fatal errors, ROUTER_1_2 # should re-register within another BBR_REREGISTRATION_DELAY (with least delay if ST_DUA_REREGISTER) - for status in [ST_DUA_REREGISTER, ST_DUA_NO_RESOURCES, ST_DUA_BBR_NOT_PRIMARY, ST_DUA_GENERAL_FAILURE]: - print('Testing Status %d...'.format(status)) + for status in ['5.00', ST_DUA_REREGISTER, ST_DUA_NO_RESOURCES, ST_DUA_BBR_NOT_PRIMARY, ST_DUA_GENERAL_FAILURE]: + print(f'Testing Status {status}...') # Flush relative message queues. self.flush_nodes([ROUTER_1_2]) seq_num = seq_num + 1