From 8423ed3042a95602596afff2d90fc075b17098e7 Mon Sep 17 00:00:00 2001 From: Simon Lin Date: Thu, 2 Apr 2020 01:19:36 +0800 Subject: [PATCH] [simulation] enhance simulation for OTNS (#4268) This commit is to support OTNS by: - raising the max number of simulating nodes to 999 if OTNS=1 - implementing the status-push mechanism To build: $ make -f examples/Makefile-simulation OTNS=1 This commit should have no change of OpenThread behaviors on platforms except simulation. --- Android.mk | 1 + etc/cmake/options.cmake | 5 + examples/Makefile-simulation | 4 + examples/common-switches.mk | 5 + examples/platforms/simulation/CMakeLists.txt | 1 + examples/platforms/simulation/Makefile.am | 1 + .../platforms/simulation/platform-config.h | 16 ++ .../simulation/platform-simulation.h | 5 + .../platforms/simulation/virtual_time/otns.c | 50 +++++++ include/openthread/instance.h | 1 + include/openthread/platform/Makefile.am | 1 + include/openthread/platform/otns.h | 83 +++++++++++ src/cli/cli.cpp | 44 +++++- src/cli/cli.hpp | 9 ++ src/core/CMakeLists.txt | 3 + src/core/Makefile.am | 4 + src/core/common/instance.cpp | 3 + src/core/common/instance.hpp | 15 +- .../config/openthread-core-default-config.h | 10 ++ src/core/meshcop/joiner.cpp | 8 +- src/core/radio/radio.cpp | 54 +++++++ src/core/radio/radio.hpp | 7 +- src/core/thread/mle_router.cpp | 5 + src/core/utils/otns.cpp | 134 +++++++++++++++++ src/core/utils/otns.hpp | 140 ++++++++++++++++++ 25 files changed, 597 insertions(+), 12 deletions(-) create mode 100644 examples/platforms/simulation/virtual_time/otns.c create mode 100644 include/openthread/platform/otns.h create mode 100644 src/core/radio/radio.cpp create mode 100644 src/core/utils/otns.cpp create mode 100644 src/core/utils/otns.hpp diff --git a/Android.mk b/Android.mk index ed6f2197b..2ae5accf7 100644 --- a/Android.mk +++ b/Android.mk @@ -216,6 +216,7 @@ LOCAL_SRC_FILES := \ src/core/net/ip6_mpl.cpp \ src/core/net/netif.cpp \ src/core/net/udp6.cpp \ + src/core/radio/radio.cpp \ src/core/radio/radio_callbacks.cpp \ src/core/radio/radio_platform.cpp \ src/core/thread/address_resolver.cpp \ diff --git a/etc/cmake/options.cmake b/etc/cmake/options.cmake index ecc250276..2f418a685 100644 --- a/etc/cmake/options.cmake +++ b/etc/cmake/options.cmake @@ -213,3 +213,8 @@ if(OT_FULL_LOGS) list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL=1") list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_LOG_PREPEND_REGION=1") endif() + +option(OT_OTNS "enable OTNS support") +if(OT_OTNS) + list(APPEND OT_PRIVATE_DEFINES "OPENTHREAD_CONFIG_OTNS_ENABLE=1") +endif() diff --git a/examples/Makefile-simulation b/examples/Makefile-simulation index 0a71ab0e5..9634ff292 100644 --- a/examples/Makefile-simulation +++ b/examples/Makefile-simulation @@ -91,6 +91,10 @@ else COMMONCFLAGS += -DOPENTHREAD_CONFIG_NCP_UART_ENABLE=1 endif # NCP_SPI == 1 +ifeq ($(OTNS),1) +VIRTUAL_TIME ?= 1 +endif + ifeq ($(VIRTUAL_TIME),1) COMMONCFLAGS += -DOPENTHREAD_SIMULATION_VIRTUAL_TIME=1 endif diff --git a/examples/common-switches.mk b/examples/common-switches.mk index e7fa7d0bb..91a36ee75 100644 --- a/examples/common-switches.mk +++ b/examples/common-switches.mk @@ -60,6 +60,7 @@ endif LINK_RAW ?= 0 MAC_FILTER ?= 0 MTD_NETDIAG ?= 0 +OTNS ?= 0 PLATFORM_UDP ?= 0 REFERENCE_DEVICE ?= 0 SERVICE ?= 0 @@ -253,6 +254,10 @@ ifeq ($(SETTINGS_RAM),1) COMMONCFLAGS += -DOPENTHREAD_SETTINGS_RAM=1 endif +ifeq ($(OTNS),1) +COMMONCFLAGS += -DOPENTHREAD_CONFIG_OTNS_ENABLE=1 +endif + ifeq ($(FULL_LOGS),1) # HINT: Add more here, or comment out ones you do not need/want LOG_FLAGS += -DOPENTHREAD_CONFIG_LOG_LEVEL=OT_LOG_LEVEL_DEBG diff --git a/examples/platforms/simulation/CMakeLists.txt b/examples/platforms/simulation/CMakeLists.txt index 2b7c270f7..1fe76dde3 100644 --- a/examples/platforms/simulation/CMakeLists.txt +++ b/examples/platforms/simulation/CMakeLists.txt @@ -66,6 +66,7 @@ add_library(openthread-simulation system.c uart.c virtual_time/alarm-sim.c + virtual_time/otns.c virtual_time/platform-sim.c $ ) diff --git a/examples/platforms/simulation/Makefile.am b/examples/platforms/simulation/Makefile.am index 5eb755793..444a5a3e7 100644 --- a/examples/platforms/simulation/Makefile.am +++ b/examples/platforms/simulation/Makefile.am @@ -52,6 +52,7 @@ PLATFORM_SOURCES = \ system.c \ uart.c \ virtual_time/alarm-sim.c \ + virtual_time/otns.c \ virtual_time/platform-sim.c \ $(NULL) diff --git a/examples/platforms/simulation/platform-config.h b/examples/platforms/simulation/platform-config.h index 11f446ff4..6cf347490 100644 --- a/examples/platforms/simulation/platform-config.h +++ b/examples/platforms/simulation/platform-config.h @@ -81,3 +81,19 @@ #ifndef OPENTHREAD_CONFIG_NCP_SPI_ENABLE #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 + +#if OPENTHREAD_SIMULATION_VIRTUAL_TIME_UART +#error "OTNS does not support virtual time UART" +#endif + +#endif // OPENTHREAD_CONFIG_OTNS_ENABLE diff --git a/examples/platforms/simulation/platform-simulation.h b/examples/platforms/simulation/platform-simulation.h index 0cf363b2b..b80ab0a81 100644 --- a/examples/platforms/simulation/platform-simulation.h +++ b/examples/platforms/simulation/platform-simulation.h @@ -66,6 +66,7 @@ enum OT_SIM_EVENT_RADIO_RECEIVED = 1, OT_SIM_EVENT_UART_WRITE = 2, OT_SIM_EVENT_RADIO_SPINEL_WRITE = 3, + OT_SIM_EVENT_OTNS_STATUS_PUSH = 5, OT_EVENT_DATA_MAX_SIZE = 1024, }; @@ -80,7 +81,11 @@ struct Event enum { +#if OPENTHREAD_CONFIG_OTNS_ENABLE + WELLKNOWN_NODE_ID = 1000, ///< Well-known Unique ID used by a simulated radio that supports promiscuous mode. +#else WELLKNOWN_NODE_ID = 34, ///< Well-known Unique ID used by a simulated radio that supports promiscuous mode. +#endif }; /** diff --git a/examples/platforms/simulation/virtual_time/otns.c b/examples/platforms/simulation/virtual_time/otns.c new file mode 100644 index 000000000..9b0204893 --- /dev/null +++ b/examples/platforms/simulation/virtual_time/otns.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-simulation.h" + +#if OPENTHREAD_CONFIG_OTNS_ENABLE + +#include + +void otPlatOtnsStatus(const char *aStatus) +{ + struct Event event; + uint16_t statusLength = (uint16_t)strlen(aStatus); + + assert(statusLength < sizeof(event.mData)); + + memcpy(event.mData, aStatus, statusLength); + event.mDataLength = statusLength; + event.mDelay = 0; + event.mEvent = OT_SIM_EVENT_OTNS_STATUS_PUSH; + + otSimSendEvent(&event); +} + +#endif // OPENTHREAD_CONFIG_OTNS_ENABLE diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 89a094724..205b80a45 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -149,6 +149,7 @@ enum OT_CHANGED_THREAD_NETIF_STATE = 1 << 24, ///< Thread network interface state changed OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE = 1 << 25, ///< Backbone Router state changed OT_CHANGED_THREAD_BACKBONE_ROUTER_LOCAL = 1 << 26, ///< Local Backbone Router configuration changed + OT_CHANGED_JOINER_STATE = 1 << 27, ///< Joiner state changed }; /** diff --git a/include/openthread/platform/Makefile.am b/include/openthread/platform/Makefile.am index 90f3baf52..3441ae49d 100644 --- a/include/openthread/platform/Makefile.am +++ b/include/openthread/platform/Makefile.am @@ -38,6 +38,7 @@ ot_platform_headers = \ memory.h \ misc.h \ logging.h \ + otns.h \ radio.h \ time.h \ uart.h \ diff --git a/include/openthread/platform/otns.h b/include/openthread/platform/otns.h new file mode 100644 index 000000000..6d862e24c --- /dev/null +++ b/include/openthread/platform/otns.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief + * This file includes the abstraction for the platform OTNS utilities. + * + * OTNS is an OpenThread Network Simulator that simulates Thread networks using OpenThread simulation instances and + * provides visualization and management of those simulated networks. + * Refer to https://github.com/openthread/ot-ns for more information about OTNS. + */ + +#ifndef OPENTHREAD_PLATFORM_OTNS_H_ +#define OPENTHREAD_PLATFORM_OTNS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup plat-otns + * + * @brief + * This module includes the platform abstraction for OTNS. + * + * @{ + * + */ + +/** + * This function exports status information to OTNS. + * + * The status information is represented by a null-terminated string with format recognizable by OTNS. + * Each call to `otPlatOtnsStatus` can send multiple statuses, separated by ';', e.x. "parid=577fbc37;lrid=5". + * Each status contains key and value separated by '='. + * Status value can be further separated into multiple fields using ',', + * e.x. "ping_request=fdde:ad00:beef:0:459e:d7b4:b65e:5480,4,112000". + * + * New statuses should follow these conventions. + * + * Currently, OTNS only supports virtual time simulation. + * + * @param[in] aStatus The status string. + * + */ +void otPlatOtnsStatus(const char *aStatus); + +/** + * @} + * + */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // OPENTHREAD_PLATFORM_OTNS_H_ diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index bfe4b3ced..1efd910f3 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -65,6 +65,7 @@ #include "common/new.hpp" #include "net/ip6.hpp" +#include "utils/otns.hpp" #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) #include @@ -2164,13 +2165,14 @@ void Interpreter::HandleIcmpReceive(otMessage * aMessage, const otMessageInfo *aMessageInfo, const otIcmp6Header *aIcmpHeader) { - uint32_t timestamp; + uint32_t timestamp = 0; + uint16_t dataSize; VerifyOrExit(aIcmpHeader->mType == OT_ICMP6_TYPE_ECHO_REPLY); VerifyOrExit((mPingIdentifier != 0) && (mPingIdentifier == HostSwap16(aIcmpHeader->mData.m16[0]))); - mServer->OutputFormat("%u bytes from ", otMessageGetLength(aMessage) - otMessageGetOffset(aMessage) + - static_cast(sizeof(otIcmp6Header))); + dataSize = otMessageGetLength(aMessage) - otMessageGetOffset(aMessage); + mServer->OutputFormat("%u bytes from ", dataSize + static_cast(sizeof(otIcmp6Header))); OutputIp6Address(aMessageInfo->mPeerAddr); @@ -2183,6 +2185,9 @@ void Interpreter::HandleIcmpReceive(otMessage * aMessage, mServer->OutputFormat("\r\n"); + SignalPingReply(static_cast(aMessageInfo)->GetPeerAddr(), dataSize, HostSwap32(timestamp), + aMessageInfo->mHopLimit); + exit: return; } @@ -2284,6 +2289,9 @@ void Interpreter::SendPing(void) SuccessOrExit(otMessageSetLength(message, mPingLength)); SuccessOrExit(otIcmp6SendEchoRequest(mInstance, message, &messageInfo, mPingIdentifier)); + SignalPingRequest(static_cast(&messageInfo)->GetPeerAddr(), mPingLength, HostSwap32(timestamp), + messageInfo.mHopLimit); + message = NULL; exit: @@ -4175,6 +4183,36 @@ Interpreter &Interpreter::GetOwner(OwnerLocator &aOwnerLocator) return interpreter; } +void Interpreter::SignalPingRequest(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit) +{ + OT_UNUSED_VARIABLE(aPeerAddress); + OT_UNUSED_VARIABLE(aPingLength); + OT_UNUSED_VARIABLE(aTimestamp); + OT_UNUSED_VARIABLE(aHopLimit); + +#if OPENTHREAD_CONFIG_OTNS_ENABLE + mInstance->Get().EmitPingRequest(aPeerAddress, aPingLength, aTimestamp, aHopLimit); +#endif +} + +void Interpreter::SignalPingReply(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit) +{ + OT_UNUSED_VARIABLE(aPeerAddress); + OT_UNUSED_VARIABLE(aPingLength); + OT_UNUSED_VARIABLE(aTimestamp); + OT_UNUSED_VARIABLE(aHopLimit); + +#if OPENTHREAD_CONFIG_OTNS_ENABLE + mInstance->Get().EmitPingReply(aPeerAddress, aPingLength, aTimestamp, aHopLimit); +#endif +} + extern "C" void otCliSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength) { Server::sServer->GetInterpreter().SetUserCommands(aUserCommands, aLength); diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 42b90ca02..7649c4c97 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -304,6 +304,15 @@ private: #endif void ProcessPing(uint8_t aArgsLength, char *aArgs[]); void ProcessPollPeriod(uint8_t aArgsLength, char *aArgs[]); + void SignalPingRequest(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit); + void SignalPingReply(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit); + #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE void ProcessPrefix(uint8_t aArgsLength, char *aArgs[]); otError ProcessPrefixAdd(uint8_t aArgsLength, char *aArgs[]); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b1656b822..1cd6edf01 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -169,6 +169,7 @@ set(COMMON_SOURCES net/netif.cpp net/sntp_client.cpp net/udp6.cpp + radio/radio.cpp radio/radio_callbacks.cpp radio/radio_platform.cpp thread/address_resolver.cpp @@ -203,6 +204,7 @@ set(COMMON_SOURCES utils/flash.cpp utils/heap.cpp utils/jam_detector.cpp + utils/otns.cpp utils/parse_cmdline.cpp utils/slaac_address.cpp ) @@ -233,6 +235,7 @@ target_sources(openthread-radio PRIVATE mac/mac_types.cpp mac/sub_mac.cpp mac/sub_mac_callbacks.cpp + radio/radio.cpp radio/radio_callbacks.cpp radio/radio_platform.cpp thread/link_quality.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 16737a425..a58760e3c 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -207,6 +207,7 @@ SOURCES_COMMON = \ net/netif.cpp \ net/sntp_client.cpp \ net/udp6.cpp \ + radio/radio.cpp \ radio/radio_callbacks.cpp \ radio/radio_platform.cpp \ thread/address_resolver.cpp \ @@ -241,6 +242,7 @@ SOURCES_COMMON = \ utils/flash.cpp \ utils/heap.cpp \ utils/jam_detector.cpp \ + utils/otns.cpp \ utils/parse_cmdline.cpp \ utils/slaac_address.cpp \ $(NULL) @@ -269,6 +271,7 @@ libopenthread_radio_a_SOURCES = \ mac/mac_types.cpp \ mac/sub_mac.cpp \ mac/sub_mac_callbacks.cpp \ + radio/radio.cpp \ radio/radio_callbacks.cpp \ radio/radio_platform.cpp \ thread/link_quality.cpp \ @@ -445,6 +448,7 @@ HEADERS_COMMON = \ utils/flash.hpp \ utils/heap.hpp \ utils/jam_detector.hpp \ + utils/otns.hpp \ utils/parse_cmdline.hpp \ utils/slaac_address.hpp \ utils/static_assert.hpp \ diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index a2b52ff7a..33c21377b 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -94,6 +94,9 @@ Instance::Instance(void) #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE , mAnnounceSender(*this) #endif +#if OPENTHREAD_CONFIG_OTNS_ENABLE + , mOtns(*this) +#endif #endif // OPENTHREAD_MTD || OPENTHREAD_FTD #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE , mLinkRaw(*this) diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index d8fad2315..0d62ed0ce 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -87,7 +87,9 @@ #if OPENTHREAD_ENABLE_VENDOR_EXTENSION #include "common/extension.hpp" #endif - +#if OPENTHREAD_CONFIG_OTNS_ENABLE +#include "utils/otns.hpp" +#endif /** * @addtogroup core-instance * @@ -361,6 +363,10 @@ private: AnnounceSender mAnnounceSender; #endif +#if OPENTHREAD_CONFIG_OTNS_ENABLE + Utils::Otns mOtns; +#endif + #endif // OPENTHREAD_MTD || OPENTHREAD_FTD #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE Mac::LinkRaw mLinkRaw; @@ -709,6 +715,13 @@ template <> inline BackboneRouter::Local &Instance::Get(void) #endif #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#if OPENTHREAD_CONFIG_OTNS_ENABLE +template <> inline Utils::Otns &Instance::Get(void) +{ + return mOtns; +} +#endif + #endif // OPENTHREAD_MTD || OPENTHREAD_FTD #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE diff --git a/src/core/config/openthread-core-default-config.h b/src/core/config/openthread-core-default-config.h index 15708a583..452b6af92 100644 --- a/src/core/config/openthread-core-default-config.h +++ b/src/core/config/openthread-core-default-config.h @@ -440,4 +440,14 @@ #define OPENTHREAD_CONFIG_LEGACY_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_OTNS_ENABLE + * + * Define to 1 to enable OTNS interactions. + * + */ +#ifndef OPENTHREAD_CONFIG_OTNS_ENABLE +#define OPENTHREAD_CONFIG_OTNS_ENABLE 0 +#endif + #endif // OPENTHREAD_CORE_DEFAULT_CONFIG_H_ diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index 2d5263031..937f0dcf1 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -45,6 +45,7 @@ #include "radio/radio.hpp" #include "thread/thread_netif.hpp" #include "thread/thread_uri_paths.hpp" +#include "utils/otns.hpp" #if OPENTHREAD_CONFIG_JOINER_ENABLE @@ -75,11 +76,12 @@ void Joiner::GetJoinerId(Mac::ExtAddress &aJoinerId) const void Joiner::SetState(otJoinerState aState) { - VerifyOrExit(aState != mState); + otJoinerState oldState = mState; + OT_UNUSED_VARIABLE(oldState); - otLogInfoMeshCoP("JoinerState: %s -> %s", JoinerStateToString(mState), JoinerStateToString(aState)); - mState = aState; + SuccessOrExit(Get().Update(mState, aState, OT_CHANGED_JOINER_STATE)); + otLogInfoMeshCoP("JoinerState: %s -> %s", JoinerStateToString(oldState), JoinerStateToString(aState)); exit: return; } diff --git a/src/core/radio/radio.cpp b/src/core/radio/radio.cpp new file mode 100644 index 000000000..9f3cebe01 --- /dev/null +++ b/src/core/radio/radio.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "radio.hpp" + +#include "common/locator-getters.hpp" +#include "utils/otns.hpp" + +namespace ot { + +void Radio::SetExtendedAddress(const Mac::ExtAddress &aExtAddress) +{ + otPlatRadioSetExtendedAddress(GetInstance(), &aExtAddress); + +#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE + Get().EmitExtendedAddress(aExtAddress); +#endif +} + +void Radio::SetShortAddress(Mac::ShortAddress aShortAddress) +{ + otPlatRadioSetShortAddress(GetInstance(), aShortAddress); + +#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE + Get().EmitShortAddress(aShortAddress); +#endif +} + +} // namespace ot diff --git a/src/core/radio/radio.hpp b/src/core/radio/radio.hpp index 0b551670d..88a252133 100644 --- a/src/core/radio/radio.hpp +++ b/src/core/radio/radio.hpp @@ -237,10 +237,7 @@ public: * @param[in] aExtAddress The IEEE 802.15.4 Extended Address stored in little-endian byte order. * */ - void SetExtendedAddress(const Mac::ExtAddress &aExtAddress) - { - otPlatRadioSetExtendedAddress(GetInstance(), &aExtAddress); - } + void SetExtendedAddress(const Mac::ExtAddress &aExtAddress); /** * This method sets the Short Address for address filtering. @@ -248,7 +245,7 @@ public: * @param[in] aShortAddress The IEEE 802.15.4 Short Address. * */ - void SetShortAddress(Mac::ShortAddress aShortAddress) { otPlatRadioSetShortAddress(GetInstance(), aShortAddress); } + void SetShortAddress(Mac::ShortAddress aShortAddress); /** * This method gets the radio's transmit power in dBm. diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index e4c5e9ce7..0504e7598 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -49,6 +49,7 @@ #include "thread/thread_tlvs.hpp" #include "thread/thread_uri_paths.hpp" #include "thread/time_sync_service.hpp" +#include "utils/otns.hpp" using ot::Encoding::BigEndian::HostSwap16; @@ -4786,6 +4787,10 @@ void MleRouter::Signal(otNeighborTableEvent aEvent, Neighbor &aNeighbor) mNeighborTableChangedCallback(aEvent, &info); } +#if OPENTHREAD_CONFIG_OTNS_ENABLE + Get().EmitNeighborChange(aEvent, aNeighbor); +#endif + switch (aEvent) { case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED: diff --git a/src/core/utils/otns.cpp b/src/core/utils/otns.cpp new file mode 100644 index 000000000..16e7f37d4 --- /dev/null +++ b/src/core/utils/otns.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements OTNS utilities. + * + */ + +#include "otns.hpp" + +#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE + +#include "common/debug.hpp" +#include "common/locator-getters.hpp" + +namespace ot { +namespace Utils { + +const int kMaxStatusStringLength = 128; + +void Otns::EmitShortAddress(uint16_t aShortAddress) +{ + EmitStatus("rloc16=%d", aShortAddress); +} + +void Otns::EmitExtendedAddress(const Mac::ExtAddress &aExtAddress) +{ + Mac::ExtAddress revExtAddress; + revExtAddress.Set(aExtAddress.m8, Mac::ExtAddress::kReverseByteOrder); + EmitStatus("extaddr=%s", revExtAddress.ToString().AsCString()); +} + +void Otns::EmitPingRequest(const Ip6::Address &aPeerAddress, + uint16_t aPingLength, + uint32_t aTimestamp, + uint8_t aHopLimit) +{ + OT_UNUSED_VARIABLE(aHopLimit); + EmitStatus("ping_request=%s,%d,%lu", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp); +} + +void Otns::EmitPingReply(const Ip6::Address &aPeerAddress, uint16_t aPingLength, uint32_t aTimestamp, uint8_t aHopLimit) +{ + EmitStatus("ping_reply=%s,%u,%lu,%d", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp, aHopLimit); +} + +void Otns::EmitStatus(const char *aFmt, ...) +{ + char statusStr[kMaxStatusStringLength + 1]; + int n; + + va_list ap; + va_start(ap, aFmt); + + n = vsnprintf(statusStr, sizeof(statusStr), aFmt, ap); + OT_ASSERT(n >= 0); + + va_end(ap); + + otPlatOtnsStatus(statusStr); +} + +void Otns::HandleStateChanged(Notifier::Callback &aCallback, otChangedFlags aFlags) +{ + aCallback.GetOwner().HandleStateChanged(aFlags); +} + +void Otns::HandleStateChanged(otChangedFlags aFlags) +{ + if ((aFlags & OT_CHANGED_THREAD_ROLE) != 0) + { + EmitStatus("role=%d", Get().GetRole()); + } + + if ((aFlags & OT_CHANGED_THREAD_PARTITION_ID) != 0) + { + EmitStatus("parid=%x", Get().GetLeaderData().GetPartitionId()); + } + + if ((aFlags & OT_CHANGED_JOINER_STATE) != 0) + { + EmitStatus("joiner_state=%d", Get().GetState()); + } +} + +void Otns::EmitNeighborChange(otNeighborTableEvent aEvent, Neighbor &aNeighbor) +{ + switch (aEvent) + { + case OT_NEIGHBOR_TABLE_EVENT_ROUTER_ADDED: + EmitStatus("router_added=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + break; + case OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED: + EmitStatus("router_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + break; + case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED: + EmitStatus("child_added=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + break; + case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED: + EmitStatus("child_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString()); + break; + } +} + +} // namespace Utils +} // namespace ot + +#endif // (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE diff --git a/src/core/utils/otns.hpp b/src/core/utils/otns.hpp new file mode 100644 index 000000000..bd93b546f --- /dev/null +++ b/src/core/utils/otns.hpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file wraps the calls to platform OTNS abstrations. + */ + +#ifndef UTILS_OTNS_HPP_ +#define UTILS_OTNS_HPP_ + +#include "openthread-core-config.h" + +#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE + +#include +#include +#include + +#include "common/locator.hpp" +#include "common/notifier.hpp" +#include "mac/mac_types.hpp" +#include "net/ip6_address.hpp" +#include "thread/topology.hpp" + +namespace ot { +namespace Utils { + +/** + * This class implements the OTNS Stub that interacts with OTNS. + * + */ +class Otns : public InstanceLocator +{ +public: + /** + * This constructor initializes the object. + * + * @param[in] aInstance A reference to the OpenThread instance. + * + */ + explicit Otns(Instance &aInstance) + : InstanceLocator(aInstance) + , mNotifierCallback(aInstance, &Otns::HandleStateChanged, this) + { + } + + /** + * This function emits radio short address to OTNS when changed. + * + * @param[in] aShortAddress The new short address. + * + */ + static void EmitShortAddress(uint16_t aShortAddress); + + /** + * This function emits radio extended address to OTNS when changed. + * + * @param[in] aExtAddress The new extended address. + * + */ + static void EmitExtendedAddress(const Mac::ExtAddress &aExtAddress); + + /** + * This function emits ping request information to OTNS when sending. + * + * @param[in] aPeerAddress The peer address of the ping request. + * @param[in] aPingLength The data length of the ping request. + * @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); + + /** + * This function emits ping reply information to OTNS when received. + * + * @param[in] aPeerAddress The peer address of the ping request. + * @param[in] aPingLength The data length of the ping reply. + * @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); + + /** + * This function emits a neighbor table event to OTNS when a neighbor is added or removed. + * + * @param[in] aEvent The event type. + * @param[in] aNeighbor The neighbor that is added or removed. + * + */ + static void EmitNeighborChange(otNeighborTableEvent aEvent, Neighbor &aNeighbor); + +private: + static void EmitStatus(const char *aFmt, ...); + + static void HandleStateChanged(Notifier::Callback &aCallback, otChangedFlags aFlags); + void HandleStateChanged(otChangedFlags aFlags); + + Notifier::Callback mNotifierCallback; +}; + +} // namespace Utils +} // namespace ot + +#endif //(OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE + +#endif // UTILS_OTNS_HPP_