diff --git a/include/openthread/thread.h b/include/openthread/thread.h index 35431f125..7442b842e 100644 --- a/include/openthread/thread.h +++ b/include/openthread/thread.h @@ -836,6 +836,23 @@ typedef void (*otThreadDiscoveryRequestCallback)(const otThreadDiscoveryRequestI void otThreadSetDiscoveryRequestCallback(otInstance * aInstnace, otThreadDiscoveryRequestCallback aCallback, void * aContext); + +/** + * This function sends a Proactive Address Notification (ADDR_NTF.ntf) message. + * + * This function is only available when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aDestination The destination to send the ADDR_NTF.ntf message. + * @param[in] aTarget The target address of the ADDR_NTF.ntf message. + * @param[in] aMlIid The ML-IID of the ADDR_NTF.ntf message. + * + */ +void otThreadSendAddressNotification(otInstance * aInstance, + otIp6Address * aDestination, + otIp6Address * aTarget, + otIp6InterfaceIdentifier *aMlIid); + /** * @} * diff --git a/src/cli/README.md b/src/cli/README.md index 6e6b7de20..3fe78a8fa 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -47,6 +47,7 @@ Done - [extaddr](#extaddr) - [extpanid](#extpanid) - [factoryreset](#factoryreset) +- [fake](#fake) - [ifconfig](#ifconfig) - [ipaddr](#ipaddr) - [ipmaddr](#ipmaddr) @@ -807,6 +808,19 @@ Delete all stored settings, and signal a platform reset. > factoryreset ``` +### fake + +Send fake Thread messages. + +Note: Only for certification test. + +#### fake /a/an \ \ \ + +```bash +> fake /a/an fdde:ad00:beef:0:0:ff:fe00:a800 fd00:7d03:7d03:7d03:55f2:bb6a:7a43:a03b 1111222233334444 +Done +``` + ### ifconfig Show the status of the IPv6 interface. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 090e69258..2990721cf 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1560,6 +1560,33 @@ otError Interpreter::ProcessFactoryReset(uint8_t aArgsLength, char *aArgs[]) return OT_ERROR_NONE; } +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +otError Interpreter::ProcessFake(uint8_t aArgsLength, char *aArgs[]) +{ + otError error = OT_ERROR_INVALID_COMMAND; + + VerifyOrExit(aArgsLength >= 1, OT_NOOP); + + if (strcmp(aArgs[0], "/a/an") == 0) + { + otIp6Address destination, target; + otIp6InterfaceIdentifier mlIid; + + VerifyOrExit(aArgsLength == 4, error = OT_ERROR_INVALID_ARGS); + + SuccessOrExit(error = otIp6AddressFromString(aArgs[1], &destination)); + SuccessOrExit(error = otIp6AddressFromString(aArgs[2], &target)); + VerifyOrExit(Hex2Bin(aArgs[3], mlIid.mFields.m8, sizeof(otIp6InterfaceIdentifier)) == + sizeof(otIp6InterfaceIdentifier), + error = OT_ERROR_INVALID_ARGS); + + otThreadSendAddressNotification(mInstance, &destination, &target, &mlIid); + } +exit: + return error; +} +#endif + otError Interpreter::ProcessIfconfig(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index bdd98fff0..41328f6a1 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -346,6 +346,9 @@ private: otError ProcessExtAddress(uint8_t aArgsLength, char *aArgs[]); otError ProcessExtPanId(uint8_t aArgsLength, char *aArgs[]); otError ProcessFactoryReset(uint8_t aArgsLength, char *aArgs[]); +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + otError ProcessFake(uint8_t aArgsLength, char *aArgs[]); +#endif otError ProcessIfconfig(uint8_t aArgsLength, char *aArgs[]); otError ProcessIpAddr(uint8_t aArgsLength, char *aArgs[]); otError ProcessIpAddrAdd(uint8_t aArgsLength, char *aArgs[]); @@ -605,6 +608,9 @@ private: {"extaddr", &Interpreter::ProcessExtAddress}, {"extpanid", &Interpreter::ProcessExtPanId}, {"factoryreset", &Interpreter::ProcessFactoryReset}, +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + {"fake", &Interpreter::ProcessFake}, +#endif {"help", &Interpreter::ProcessHelp}, {"ifconfig", &Interpreter::ProcessIfconfig}, {"ipaddr", &Interpreter::ProcessIpAddr}, diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index d79579325..3bde808f1 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -391,4 +391,19 @@ void otThreadSetDiscoveryRequestCallback(otInstance * aInsta instance.Get().SetDiscoveryRequestCallback(aCallback, aContext); } + +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE +void otThreadSendAddressNotification(otInstance * aInstance, + otIp6Address * aDestination, + otIp6Address * aTarget, + otIp6InterfaceIdentifier *aMlIid) +{ + Instance &instance = *static_cast(aInstance); + + instance.Get().SendAddressQueryResponse(static_cast(*aTarget), + static_cast(*aMlIid), nullptr, + static_cast(*aDestination)); +} +#endif + #endif // OPENTHREAD_FTD diff --git a/src/core/thread/address_resolver.hpp b/src/core/thread/address_resolver.hpp index df33d8ac7..2cd84c45b 100644 --- a/src/core/thread/address_resolver.hpp +++ b/src/core/thread/address_resolver.hpp @@ -177,6 +177,21 @@ public: */ void RestartAddressQueries(void); + /** + * This method sends an Address Notification (ADDR_NTF.ans) message. + * + * @param[in] aTarget The target address of the ADDR_NTF.ans message. + * @param[in] aMeshLocalIid The ML-IID of the ADDR_NTF.ans message. + * @param[in] aLastTransactionTimeTlv A pointer to the Last Transaction Time if the ADDR_NTF.ans message contains + * a Last Transaction Time TLV. + * @param[in] aDestination The destination to send the ADDR_NTF.ans message. + * + */ + void SendAddressQueryResponse(const Ip6::Address & aTarget, + const Ip6::InterfaceIdentifier &aMeshLocalIid, + const uint32_t * aLastTransactionTimeTlv, + const Ip6::Address & aDestination); + private: enum { @@ -288,10 +303,6 @@ private: void SendAddressError(const Ip6::Address & aTarget, const Ip6::InterfaceIdentifier &aMeshLocalIid, const Ip6::Address * aDestination); - void SendAddressQueryResponse(const Ip6::Address & aTarget, - const Ip6::InterfaceIdentifier &aMeshLocalIid, - const uint32_t * aLastTransactionTimeTlv, - const Ip6::Address & aDestination); static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index a52103f95..78b391392 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -1866,6 +1866,11 @@ class NodeImpl: return router_table + def send_address_notification(self, dst: str, target: str, mliid: str): + cmd = f'fake /a/an {dst} {target} {mliid}' + self.send_command(cmd) + self._expect("Done") + class Node(NodeImpl, OtCli): pass