diff --git a/examples/platforms/simulation/misc.c b/examples/platforms/simulation/misc.c index 235f0859e..79c548041 100644 --- a/examples/platforms/simulation/misc.c +++ b/examples/platforms/simulation/misc.c @@ -122,3 +122,7 @@ void otPlatAssertFail(const char *aFilename, int aLineNumber) assert(false); exit(1); } + +#if OPENTHREAD_CONFIG_OTNS_ENABLE && !OPENTHREAD_SIMULATION_VIRTUAL_TIME +void otPlatOtnsStatus(const char *aStatus) { OT_UNUSED_VARIABLE(aStatus); } +#endif diff --git a/examples/platforms/simulation/platform-config.h b/examples/platforms/simulation/platform-config.h index 4ee27d9f2..9e8638c31 100644 --- a/examples/platforms/simulation/platform-config.h +++ b/examples/platforms/simulation/platform-config.h @@ -76,17 +76,6 @@ #define OPENTHREAD_CONFIG_NCP_SPI_ENABLE 0 #endif -/** - * Check OTNS configurations - */ -#if OPENTHREAD_CONFIG_OTNS_ENABLE - -#if !OPENTHREAD_SIMULATION_VIRTUAL_TIME -#error "OTNS requires virtual time simulations" -#endif - -#endif // OPENTHREAD_CONFIG_OTNS_ENABLE - /** * @def OPENTHREAD_SIMULATION_MAX_NETWORK_SIZE * diff --git a/script/make-pretty b/script/make-pretty index fa8e8d280..c4a61d2f9 100755 --- a/script/make-pretty +++ b/script/make-pretty @@ -129,6 +129,7 @@ OT_CLANG_TIDY_BUILD_OPTS=( '-DOT_NAT64_TRANSLATOR=ON' '-DOT_NETDATA_PUBLISHER=ON' '-DOT_NETDIAG_CLIENT=ON' + '-DOT_OTNS=ON' '-DOT_PING_SENDER=ON' '-DOT_REFERENCE_DEVICE=ON' '-DOT_SERVICE=ON' diff --git a/src/core/utils/otns.cpp b/src/core/utils/otns.cpp index 1b43ef224..f9f0fe766 100644 --- a/src/core/utils/otns.cpp +++ b/src/core/utils/otns.cpp @@ -42,13 +42,12 @@ namespace Utils { RegisterLogModule("Otns"); -const int kMaxStatusStringLength = 128; +void Otns::EmitShortAddress(uint16_t aShortAddress) const { EmitStatus("rloc16=%d", aShortAddress); } -void Otns::EmitShortAddress(uint16_t aShortAddress) { EmitStatus("rloc16=%d", aShortAddress); } - -void Otns::EmitExtendedAddress(const Mac::ExtAddress &aExtAddress) +void Otns::EmitExtendedAddress(const Mac::ExtAddress &aExtAddress) const { Mac::ExtAddress revExtAddress; + revExtAddress.Set(aExtAddress.m8, Mac::ExtAddress::kReverseByteOrder); EmitStatus("extaddr=%s", revExtAddress.ToString().AsCString()); } @@ -56,35 +55,36 @@ void Otns::EmitExtendedAddress(const Mac::ExtAddress &aExtAddress) void Otns::EmitPingRequest(const Ip6::Address &aPeerAddress, uint16_t aPingLength, uint32_t aTimestamp, - uint8_t aHopLimit) + uint8_t aHopLimit) const { OT_UNUSED_VARIABLE(aHopLimit); - EmitStatus("ping_request=%s,%d,%lu", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp); + EmitStatus("ping_request=%s,%d,%lu", aPeerAddress.ToString().AsCString(), aPingLength, ToUlong(aTimestamp)); } -void Otns::EmitPingReply(const Ip6::Address &aPeerAddress, uint16_t aPingLength, uint32_t aTimestamp, uint8_t aHopLimit) +void Otns::EmitPingReply(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit) const { - EmitStatus("ping_reply=%s,%u,%lu,%d", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp, aHopLimit); + EmitStatus("ping_reply=%s,%u,%lu,%d", aPeerAddress.ToString().AsCString(), aPingLength, ToUlong(aTimestamp), + aHopLimit); } -void Otns::EmitStatus(const char *aFmt, ...) +void Otns::EmitStatus(const char *aFmt, ...) const { - char statusStr[kMaxStatusStringLength + 1]; - int n; + StatusString string; + va_list args; - va_list ap; - va_start(ap, aFmt); + va_start(args, aFmt); + string.AppendVarArgs(aFmt, args); + va_end(args); - n = vsnprintf(statusStr, sizeof(statusStr), aFmt, ap); - OT_UNUSED_VARIABLE(n); - OT_ASSERT(n >= 0); - - va_end(ap); - - otPlatOtnsStatus(statusStr); + EmitStatus(string); } -void Otns::HandleNotifierEvents(Events aEvents) +void Otns::EmitStatus(const StatusString &aString) const { otPlatOtnsStatus(aString.AsCString()); } + +void Otns::HandleNotifierEvents(Events aEvents) const { if (aEvents.Contains(kEventThreadRoleChanged)) { @@ -93,7 +93,7 @@ void Otns::HandleNotifierEvents(Events aEvents) if (aEvents.Contains(kEventThreadPartitionIdChanged)) { - EmitStatus("parid=%x", Get().GetLeaderData().GetPartitionId()); + EmitStatus("parid=%lx", ToUlong(Get().GetLeaderData().GetPartitionId())); } #if OPENTHREAD_CONFIG_JOINER_ENABLE @@ -104,95 +104,118 @@ void Otns::HandleNotifierEvents(Events aEvents) #endif } -void Otns::EmitNeighborChange(NeighborTable::Event aEvent, const Neighbor &aNeighbor) +void Otns::EmitNeighborChange(NeighborTable::Event aEvent, const Neighbor &aNeighbor) const { + StatusString string; + switch (aEvent) { case NeighborTable::kRouterAdded: - EmitStatus("router_added=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + string.Append("router_added"); break; case NeighborTable::kRouterRemoved: - EmitStatus("router_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + string.Append("router_removed"); break; case NeighborTable::kChildAdded: - EmitStatus("child_added=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + string.Append("child_added"); break; case NeighborTable::kChildRemoved: - EmitStatus("child_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + string.Append("child_removed"); break; case NeighborTable::kChildModeChanged: - break; + ExitNow(); } + + string.Append("=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + EmitStatus(string); + +exit: + return; } -void Otns::EmitTransmit(const Mac::TxFrame &aFrame) +void Otns::EmitTransmit(const Mac::TxFrame &aFrame) const { + StatusString string; Mac::Address dst; - uint16_t frameControlField = aFrame.GetFrameControlField(); - uint8_t channel = aFrame.GetChannel(); - uint8_t sequence = aFrame.GetSequence(); IgnoreError(aFrame.GetDstAddr(dst)); + string.Append("transmit=%d,%04x,%d", aFrame.GetChannel(), aFrame.GetFrameControlField(), aFrame.GetSequence()); + if (dst.IsShort()) { - EmitStatus("transmit=%d,%04x,%d,%04x", channel, frameControlField, sequence, dst.GetShort()); + string.Append(",%04x", dst.GetShort()); } else if (dst.IsExtended()) { - EmitStatus("transmit=%d,%04x,%d,%s", channel, frameControlField, sequence, dst.ToString().AsCString()); + string.Append(",%s", dst.ToString().AsCString()); } - else + + EmitStatus(string); +} + +void Otns::EmitDeviceMode(Mle::DeviceMode aMode) const +{ + StatusString string; + + string.Append("mode="); + + if (aMode.IsRxOnWhenIdle()) { - EmitStatus("transmit=%d,%04x,%d", channel, frameControlField, sequence); + string.Append("r"); } + + if (aMode.IsFullThreadDevice()) + { + string.Append("d"); + } + + if (aMode.GetNetworkDataType() == NetworkData::kFullSet) + { + string.Append("m"); + } + + EmitStatus(string); } -void Otns::EmitDeviceMode(Mle::DeviceMode aMode) +void Otns::EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const { - EmitStatus("mode=%s%s%s", aMode.IsRxOnWhenIdle() ? "r" : "", aMode.IsFullThreadDevice() ? "d" : "", - (aMode.GetNetworkDataType() == NetworkData::kFullSet) ? "n" : ""); + EmitCoapStatus("send", aMessage, aMessageInfo); } -void Otns::EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void Otns::EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const { - char uriPath[Coap::Message::kMaxReceivedUriPath + 1]; - Error error; + EmitCoapStatus("recv", aMessage, aMessageInfo); +} + +void Otns::EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const +{ + EmitCoapStatus("send_error", aMessage, aMessageInfo, &aError); +} + +void Otns::EmitCoapStatus(const char *aAction, + const Coap::Message &aMessage, + const Ip6::MessageInfo &aMessageInfo, + Error *aError) const +{ + Error error; + char uriPath[Coap::Message::kMaxReceivedUriPath + 1]; + StatusString string; SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath)); - EmitStatus("coap=send,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath, - aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort()); + string.Append("coap=%s,%d,%d,%d,%s,%s,%d", aAction, aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), + uriPath, aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort()); + + if (aError != nullptr) + { + string.Append(",%s", ErrorToString(*aError)); + } + + EmitStatus(string); exit: - LogWarnOnError(error, "EmitCoapSend"); -} - -void Otns::EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) -{ - char uriPath[Coap::Message::kMaxReceivedUriPath + 1]; - Error error = kErrorNone; - - SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath)); - - EmitStatus("coap=recv,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath, - aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort()); -exit: - LogWarnOnError(error, "EmitCoapReceive"); -} - -void Otns::EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) -{ - char uriPath[Coap::Message::kMaxReceivedUriPath + 1]; - Error error = kErrorNone; - - SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath)); - - EmitStatus("coap=send_error,%d,%d,%d,%s,%s,%d,%s", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), - uriPath, aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort(), - ErrorToString(aError)); -exit: - LogWarnOnError(error, "EmitCoapSendFailure"); + LogWarnOnError(error, "EmitCoapStatus"); } } // namespace Utils diff --git a/src/core/utils/otns.hpp b/src/core/utils/otns.hpp index 38f15228a..ddf854e4e 100644 --- a/src/core/utils/otns.hpp +++ b/src/core/utils/otns.hpp @@ -46,6 +46,7 @@ #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "common/notifier.hpp" +#include "common/string.hpp" #include "mac/mac_frame.hpp" #include "mac/mac_types.hpp" #include "net/ip6_address.hpp" @@ -78,14 +79,14 @@ public: * * @param[in] aShortAddress The new short address. */ - static void EmitShortAddress(uint16_t aShortAddress); + void EmitShortAddress(uint16_t aShortAddress) const; /** * Emits radio extended address to OTNS when changed. * * @param[in] aExtAddress The new extended address. */ - static void EmitExtendedAddress(const Mac::ExtAddress &aExtAddress); + void EmitExtendedAddress(const Mac::ExtAddress &aExtAddress) const; /** * Emits ping request information to OTNS when sending. @@ -95,10 +96,10 @@ public: * @param[in] aTimestamp The timestamp of the ping request. * @param[in] aHopLimit The hop limit of the ping request. */ - static void EmitPingRequest(const Ip6::Address &aPeerAddress, - uint16_t aPingLength, - uint32_t aTimestamp, - uint8_t aHopLimit); + void EmitPingRequest(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit) const; /** * Emits ping reply information to OTNS when received. @@ -108,10 +109,10 @@ public: * @param[in] aTimestamp The timestamp of the ping reply. * @param[in] aHopLimit The hop limit of the ping reply. */ - static void EmitPingReply(const Ip6::Address &aPeerAddress, - uint16_t aPingLength, - uint32_t aTimestamp, - uint8_t aHopLimit); + void EmitPingReply(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit) const; /** * Emits a neighbor table event to OTNS when a neighbor is added or removed. @@ -119,21 +120,21 @@ public: * @param[in] aEvent The event type. * @param[in] aNeighbor The neighbor that is added or removed. */ - static void EmitNeighborChange(NeighborTable::Event aEvent, const Neighbor &aNeighbor); + void EmitNeighborChange(NeighborTable::Event aEvent, const Neighbor &aNeighbor) const; /** * Emits a transmit event to OTNS. * * @param[in] aFrame The frame of the transmission. */ - static void EmitTransmit(const Mac::TxFrame &aFrame); + void EmitTransmit(const Mac::TxFrame &aFrame) const; /** * Emits the device mode to OTNS. * * @param[in] aMode The device mode. */ - static void EmitDeviceMode(Mle::DeviceMode aMode); + void EmitDeviceMode(Mle::DeviceMode aMode) const; /** * Emits the sending COAP message info to OTNS. @@ -141,7 +142,7 @@ public: * @param[in] aMessage The sending COAP message. * @param[in] aMessageInfo The message info. */ - static void EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const; /** * Emits the COAP message sending failure to OTNS. @@ -150,7 +151,7 @@ public: * @param[in] aMessage The COAP message failed to send. * @param[in] aMessageInfo The message info. */ - static void EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const; /** * Emits the received COAP message info to OTNS. @@ -158,11 +159,21 @@ public: * @param[in] aMessage The received COAP message. * @param[in] aMessageInfo The message info. */ - static void EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const; private: - static void EmitStatus(const char *aFmt, ...); - void HandleNotifierEvents(Events aEvents); + static constexpr uint16_t kStatusStringLength = 128; + + using StatusString = String; + + void EmitStatus(const StatusString &aString) const; + void EmitStatus(const char *aFmt, ...) const OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 3); + void EmitCoapStatus(const char *aAction, + const Coap::Message &aMessage, + const Ip6::MessageInfo &aMessageInfo, + Error *aError = nullptr) const; + + void HandleNotifierEvents(Events aEvents) const; }; } // namespace Utils diff --git a/tests/gtest/fake_platform.cpp b/tests/gtest/fake_platform.cpp index 6926ae38d..cc568970b 100644 --- a/tests/gtest/fake_platform.cpp +++ b/tests/gtest/fake_platform.cpp @@ -607,5 +607,10 @@ otError otPlatUdpLeaveMulticastGroup(otUdpSocket *, otNetifIdentifier, const otI { return OT_ERROR_NOT_IMPLEMENTED; } + +#if OPENTHREAD_CONFIG_OTNS_ENABLE +void otPlatOtnsStatus(const char *aStatus) { OT_UNUSED_VARIABLE(aStatus); } +#endif + void otPlatAssertFail(const char *, int) {} } // extern "C" diff --git a/tests/toranj/openthread-core-toranj-config-simulation.h b/tests/toranj/openthread-core-toranj-config-simulation.h index 85412ff3d..fc6bca09a 100644 --- a/tests/toranj/openthread-core-toranj-config-simulation.h +++ b/tests/toranj/openthread-core-toranj-config-simulation.h @@ -97,4 +97,6 @@ #define OPENTHREAD_CONFIG_TREL_USE_HEAP_ENABLE 0 +#define OPENTHREAD_CONFIG_OTNS_ENABLE 1 + #endif /* OPENTHREAD_CORE_TORANJ_CONFIG_SIMULATION_H_ */