diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 5371a06f7..f3b151ebd 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (48) +#define OPENTHREAD_API_VERSION (49) /** * @addtogroup api-instance diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h index e71369497..beb01ad4d 100644 --- a/include/openthread/ip6.h +++ b/include/openthread/ip6.h @@ -223,6 +223,7 @@ typedef struct otMessageInfo ///< Otherwise, specifies the IPv6 Hop Limit. bool mIsHostInterface : 1; ///< TRUE if packets sent/received via host interface, FALSE otherwise. bool mAllowZeroHopLimit : 1; ///< TRUE to allow IPv6 Hop Limit 0 in `mHopLimit`, FALSE otherwise. + bool mMulticastLoop : 1; ///< TRUE to allow looping back mutlicast, FALSE otherwise. } otMessageInfo; /** diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index c86585eea..2926a7fdb 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -4450,7 +4450,9 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError, aError, aMessage, static_cast(aMessageInfo)); } -void Interpreter::HandleDiagnosticGetResponse(otError aError, const otMessage *aMessage, const Ip6::MessageInfo *) +void Interpreter::HandleDiagnosticGetResponse(otError aError, + const otMessage * aMessage, + const Ip6::MessageInfo *aMessageInfo) { uint8_t buf[16]; uint16_t bytesToPrint; @@ -4461,7 +4463,9 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError, const otMessage *a SuccessOrExit(aError); - OutputFormat("DIAG_GET.rsp/ans: "); + OutputFormat("DIAG_GET.rsp/ans from "); + OutputIp6Address(aMessageInfo->mPeerAddr); + OutputFormat(": "); length = otMessageGetLength(aMessage) - otMessageGetOffset(aMessage); diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index 21b853c7c..36f4c9d2b 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -217,6 +217,7 @@ otError CoapBase::SendMessage(Message & aMessage, metadata.mSourceAddress = aMessageInfo.GetSockAddr(); metadata.mDestinationPort = aMessageInfo.GetPeerPort(); metadata.mDestinationAddress = aMessageInfo.GetPeerAddr(); + metadata.mMulticastLoop = aMessageInfo.GetMulticastLoop(); metadata.mResponseHandler = aHandler; metadata.mResponseContext = aContext; metadata.mRetransmissionsRemaining = aTxParameters.mMaxRetransmit; @@ -383,6 +384,7 @@ void CoapBase::HandleRetransmissionTimer(void) messageInfo.SetHopLimit(metadata.mHopLimit); messageInfo.SetIsHostInterface(metadata.mIsHostInterface); #endif + messageInfo.SetMulticastLoop(metadata.mMulticastLoop); SendCopy(*message, messageInfo); } diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index 35d188d44..8a1d983d1 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -543,8 +543,9 @@ private: #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE uint8_t mHopLimit; // The hop limit. #endif - bool mAcknowledged : 1; // Information that request was acknowledged. - bool mConfirmable : 1; // Information that message is confirmable. + bool mAcknowledged : 1; // Information that request was acknowledged. + bool mConfirmable : 1; // Information that message is confirmable. + bool mMulticastLoop : 1; // Information that multicast loop is enabled. #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE bool mIsHostInterface : 1; // TRUE if packets sent/received via host interface, FALSE otherwise. #endif diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp index 03979c067..7fef09235 100644 --- a/src/core/common/message.hpp +++ b/src/core/common/message.hpp @@ -165,14 +165,15 @@ struct MessageMetadata uint8_t mChannel; ///< Used for MLE Announce. } mPanIdChannel; ///< Used for MLE Discover Request, Response, and Announce messages. - uint8_t mType : 3; ///< Identifies the type of message. - uint8_t mSubType : 4; ///< Identifies the message sub type. - bool mDirectTx : 1; ///< Used to indicate whether a direct transmission is required. - bool mLinkSecurity : 1; ///< Indicates whether or not link security is enabled. - uint8_t mPriority : 2; ///< Identifies the message priority level (higher value is higher priority). - bool mInPriorityQ : 1; ///< Indicates whether the message is queued in normal or priority queue. - bool mTxSuccess : 1; ///< Indicates whether the direct tx of the message was successful. - bool mDoNotEvict : 1; ///< Indicates whether or not this message may be evicted. + uint8_t mType : 3; ///< Identifies the type of message. + uint8_t mSubType : 4; ///< Identifies the message sub type. + bool mDirectTx : 1; ///< Used to indicate whether a direct transmission is required. + bool mLinkSecurity : 1; ///< Indicates whether or not link security is enabled. + uint8_t mPriority : 2; ///< Identifies the message priority level (higher value is higher priority). + bool mInPriorityQ : 1; ///< Indicates whether the message is queued in normal or priority queue. + bool mTxSuccess : 1; ///< Indicates whether the direct tx of the message was successful. + bool mDoNotEvict : 1; ///< Indicates whether or not this message may be evicted. + bool mMulticastLoop : 1; ///< Indicates whether or not this multicast message may be looped back. #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE bool mTimeSync : 1; ///< Indicates whether the message is also used for time sync purpose. uint8_t mTimeSyncSeq; ///< The time sync sequence. @@ -529,6 +530,23 @@ public: */ bool IsSubTypeMle(void) const; + /** + * This method checks whether this multicast message may be looped back. + * + * @retval TRUE If message may be looped back. + * @retval FALSE If message must not be looped back. + * + */ + bool GetMulticastLoop(void) const { return GetMetadata().mMulticastLoop; } + + /** + * This method sets whether multicast may be looped back. + * + * @param[in] aMulticastLoop Whether allow looping back multicast. + * + */ + void SetMulticastLoop(bool aMulticastLoop) { GetMetadata().mMulticastLoop = aMulticastLoop; } + /** * This method returns the message priority level. * diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index aa5cc1ce4..7ae11f4dd 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -501,6 +501,8 @@ otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t SuccessOrExit(error = AddTunneledMplOption(aMessage, header, aMessageInfo)); } + aMessage.SetMulticastLoop(aMessageInfo.GetMulticastLoop()); + if (aMessage.GetLength() > kMaxDatagramLength) { error = FragmentDatagram(aMessage, aIpProto); @@ -531,7 +533,7 @@ void Ip6::HandleSendQueue(void) } } -otError Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool &aForward) +otError Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool &aForward, bool &aReceive) { otError error = OT_ERROR_NONE; HopByHopHeader hbhHeader; @@ -561,7 +563,7 @@ otError Ip6::HandleOptions(Message &aMessage, Header &aHeader, bool &aForward) switch (optionHeader.GetType()) { case OptionMpl::kType: - SuccessOrExit(error = mMpl.ProcessOption(aMessage, aHeader.GetSource(), aForward)); + SuccessOrExit(error = mMpl.ProcessOption(aMessage, aHeader.GetSource(), aForward, aReceive)); break; default: @@ -890,7 +892,7 @@ otError Ip6::HandleExtensionHeaders(Message & aMessage, uint8_t & aNextHeader, bool aForward, bool aFromNcpHost, - bool aReceive) + bool & aReceive) { otError error = OT_ERROR_NONE; ExtensionHeader extHeader; @@ -902,7 +904,7 @@ otError Ip6::HandleExtensionHeaders(Message & aMessage, switch (aNextHeader) { case kProtoHopOpts: - SuccessOrExit(error = HandleOptions(aMessage, aHeader, aForward)); + SuccessOrExit(error = HandleOptions(aMessage, aHeader, aForward, aReceive)); break; case kProtoFragment: @@ -913,7 +915,7 @@ otError Ip6::HandleExtensionHeaders(Message & aMessage, break; case kProtoDstOpts: - SuccessOrExit(error = HandleOptions(aMessage, aHeader, aForward)); + SuccessOrExit(error = HandleOptions(aMessage, aHeader, aForward, aReceive)); break; case kProtoIp6: @@ -934,14 +936,31 @@ exit: return error; } -otError Ip6::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto) +otError Ip6::HandlePayload(Message & aMessage, + MessageInfo & aMessageInfo, + uint8_t aIpProto, + Message::Ownership aMessageOwnership) { - otError error = OT_ERROR_NONE; + otError error = OT_ERROR_NONE; + Message *message = nullptr; + + VerifyOrExit(aIpProto == kProtoUdp || aIpProto == kProtoIcmp6); + + switch (aMessageOwnership) + { + case Message::kTakeCustody: + message = &aMessage; + break; + + case Message::kCopyToUse: + VerifyOrExit((message = aMessage.Clone()) != nullptr, error = OT_ERROR_NO_BUFS); + break; + } switch (aIpProto) { case kProtoUdp: - error = mUdp.HandleMessage(aMessage, aMessageInfo); + error = mUdp.HandleMessage(*message, aMessageInfo); if (error == OT_ERROR_DROP) { otLogNoteIp6("Error UDP Checksum"); @@ -949,13 +968,21 @@ otError Ip6::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo, uint8_t break; case kProtoIcmp6: - error = mIcmp.HandleMessage(aMessage, aMessageInfo); + error = mIcmp.HandleMessage(*message, aMessageInfo); break; default: break; } +exit: + if (error != OT_ERROR_NONE) + { + otLogNoteIp6("Failed to handle payload: %s", otThreadErrorToString(error)); + } + + FreeMessage(message); + return error; } @@ -1107,6 +1134,7 @@ otError Ip6::HandleDatagram(Message &aMessage, Netif *aNetif, const void *aLinkM bool forward; bool multicastPromiscuous; bool shouldFreeMessage; + bool shouldForwardToHost; uint8_t nextHeader; start: @@ -1126,17 +1154,10 @@ start: // determine destination of packet if (header.GetDestination().IsMulticast()) { + Netif *netif; + if (aNetif != nullptr) { - if (aNetif->IsMulticastSubscribed(header.GetDestination())) - { - receive = true; - } - else if (aNetif->IsMulticastPromiscuousEnabled()) - { - multicastPromiscuous = true; - } - #if OPENTHREAD_FTD if (header.GetDestination().IsMulticastLargerThanRealmLocal() && Get().HasSleepyChildWithAddress(header.GetDestination())) @@ -1144,10 +1165,23 @@ start: forward = true; } #endif + + netif = aNetif; } else { forward = true; + + netif = &Get(); + } + + if ((aNetif != nullptr || aMessage.GetMulticastLoop()) && netif->IsMulticastSubscribed(header.GetDestination())) + { + receive = true; + } + else if (netif->IsMulticastPromiscuousEnabled()) + { + multicastPromiscuous = true; } } else @@ -1173,6 +1207,8 @@ start: SuccessOrExit(error = HandleExtensionHeaders(aMessage, aNetif, messageInfo, header, nextHeader, forward, aFromNcpHost, receive)); + shouldForwardToHost = forward && !ShouldForwardToThread(messageInfo, aFromNcpHost); + // process IPv6 Payload if (receive) { @@ -1199,9 +1235,16 @@ start: } #endif - IgnoreError(ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost, Message::kCopyToUse)); + error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost, Message::kCopyToUse); - SuccessOrExit(error = HandlePayload(aMessage, messageInfo, nextHeader)); + if ((error == OT_ERROR_NONE || error == OT_ERROR_NO_ROUTE) && shouldForwardToHost) + { + forward = false; + } + + error = + HandlePayload(aMessage, messageInfo, nextHeader, (forward ? Message::kCopyToUse : Message::kTakeCustody)); + shouldFreeMessage = forward; } else if (multicastPromiscuous) { @@ -1212,7 +1255,7 @@ start: { uint8_t hopLimit; - if (!ShouldForwardToThread(messageInfo, aFromNcpHost)) + if (shouldForwardToHost) { // try passing to host error = ProcessReceiveCallback(aMessage, messageInfo, nextHeader, aFromNcpHost, Message::kTakeCustody); diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index f79b4c97d..858c0a4c1 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -343,7 +343,7 @@ private: uint8_t & aNextHeader, bool aForward, bool aFromNcpHost, - bool aReceive); + bool & aReceive); otError FragmentDatagram(Message &aMessage, uint8_t aIpProto); otError HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMessageInfo, bool aFromNcpHost); #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE @@ -356,8 +356,11 @@ private: otError AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo); otError InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo); otError RemoveMplOption(Message &aMessage); - otError HandleOptions(Message &aMessage, Header &aHeader, bool &aForward); - otError HandlePayload(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aIpProto); + otError HandleOptions(Message &aMessage, Header &aHeader, bool &aForward, bool &aReceive); + otError HandlePayload(Message & aMessage, + MessageInfo & aMessageInfo, + uint8_t aIpProto, + Message::Ownership aMessageOwnership); bool ShouldForwardToThread(const MessageInfo &aMessageInfo, bool aFromNcpHost) const; bool IsOnLink(const Address &aAddress) const; diff --git a/src/core/net/ip6_mpl.cpp b/src/core/net/ip6_mpl.cpp index 1a3801ecc..d59af2c8a 100644 --- a/src/core/net/ip6_mpl.cpp +++ b/src/core/net/ip6_mpl.cpp @@ -77,7 +77,7 @@ void Mpl::InitOption(OptionMpl &aOption, const Address &aAddress) } } -otError Mpl::ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound) +otError Mpl::ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive) { otError error; OptionMpl option; @@ -104,6 +104,7 @@ otError Mpl::ProcessOption(Message &aMessage, const Address &aAddress, bool aIsO } else if (aIsOutbound) { + aReceive = false; // In case MPL Data Message is generated locally, ignore potential error of the MPL Seed Set // to allow subsequent retransmissions with the same sequence number. ExitNow(error = OT_ERROR_NONE); diff --git a/src/core/net/ip6_mpl.hpp b/src/core/net/ip6_mpl.hpp index 07c1de459..9549b72fc 100644 --- a/src/core/net/ip6_mpl.hpp +++ b/src/core/net/ip6_mpl.hpp @@ -216,12 +216,14 @@ public: * @param[in] aMessage A reference to the message. * @param[in] aAddress A reference to the IPv6 Source Address. * @param[in] aIsOutbound TRUE if this message was locally generated, FALSE otherwise. + * @param[out] aReceive Set to FALSE if the MPL message is a duplicate and must not + * go through the receiving process again, untouched otherwise. * * @retval OT_ERROR_NONE Successfully processed the MPL option. * @retval OT_ERROR_DROP The MPL message is a duplicate and should be dropped. * */ - otError ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound); + otError ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive); /** * This method returns the MPL Seed Id value. diff --git a/src/core/net/socket.hpp b/src/core/net/socket.hpp index 4a3ebc7b6..9c9a2ef1e 100644 --- a/src/core/net/socket.hpp +++ b/src/core/net/socket.hpp @@ -161,6 +161,23 @@ public: */ void SetHopLimit(uint8_t aHopLimit) { mHopLimit = aHopLimit; } + /** + * This method returns whether multicast may be looped back. + * + * @retval TRUE If message may be looped back. + * @retval FALSE If message must not be looped back. + * + */ + bool GetMulticastLoop(void) const { return mMulticastLoop; } + + /** + * This method sets whether multicast may be looped back. + * + * @param[in] aMulticastLoop Whether allow looping back multicast. + * + */ + void SetMulticastLoop(bool aMulticastLoop) { mMulticastLoop = aMulticastLoop; } + /** * This method returns a pointer to the link-specific information object. * diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index 7c6ca346d..a26525bf1 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -90,6 +90,7 @@ otError NetworkDiagnostic::SendDiagnosticGet(const Ip6::Address &aDestination, if (aDestination.IsMulticast()) { SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kDiagnosticGetQuery)); + messageInfo.SetMulticastLoop(true); } else { diff --git a/src/posix/platform/udp.cpp b/src/posix/platform/udp.cpp index e8bdb26a9..87e13718f 100644 --- a/src/posix/platform/udp.cpp +++ b/src/posix/platform/udp.cpp @@ -415,18 +415,31 @@ exit: otError otPlatUdpSend(otUdpSocket *aUdpSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo) { - otError error = OT_ERROR_NONE; - int fd; + otError error = OT_ERROR_NONE; + int fd; + uint16_t len; + uint8_t payload[kMaxUdpSize]; VerifyOrExit(aUdpSocket->mHandle != nullptr, error = OT_ERROR_INVALID_ARGS); fd = FdFromHandle(aUdpSocket->mHandle); - { - uint8_t payload[kMaxUdpSize]; - uint16_t len = otMessageGetLength(aMessage); + len = otMessageGetLength(aMessage); + VerifyOrExit(len == otMessageRead(aMessage, 0, payload, len), error = OT_ERROR_INVALID_ARGS); - VerifyOrExit(len == otMessageRead(aMessage, 0, payload, len), error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = transmitPacket(fd, payload, len, *aMessageInfo)); + if (aMessageInfo->mMulticastLoop) + { + int value = 1; + + VerifyOrDie(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &value, sizeof(value)) == 0, OT_EXIT_ERROR_ERRNO); + } + + error = transmitPacket(fd, payload, len, *aMessageInfo); + + if (aMessageInfo->mMulticastLoop) + { + int value = 0; + + VerifyOrDie(setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &value, sizeof(value)) == 0, OT_EXIT_ERROR_ERRNO); } exit: diff --git a/tests/scripts/expect/_common.exp b/tests/scripts/expect/_common.exp index d41cb37d1..54fe060a2 100644 --- a/tests/scripts/expect/_common.exp +++ b/tests/scripts/expect/_common.exp @@ -125,9 +125,9 @@ proc dispose_all {} { } } -proc get_mleid {} { - send "ipaddr mleid\n" - expect "ipaddr mleid" +proc get_ipaddr {type} { + send "ipaddr $type\n" + expect "ipaddr $type" expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} set rval $expect_out(1,string) expect "Done" @@ -144,4 +144,14 @@ proc get_extaddr {} { return $rval } +proc get_rloc16 {} { + send "rloc16\n" + expect "rloc16" + expect -re {([0-9a-fA-F]{4})} + set rval $expect_out(1,string) + expect "Done" + + return $rval +} + set timeout 10 diff --git a/tests/scripts/expect/cli-multicast-loop.exp b/tests/scripts/expect/cli-multicast-loop.exp new file mode 100755 index 000000000..48b91f3fe --- /dev/null +++ b/tests/scripts/expect/cli-multicast-loop.exp @@ -0,0 +1,136 @@ +#!/usr/bin/expect -f +# +# 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. +# + +# This script verifies multicast loop back. + +# +# +# R1 -- R2 -- R3 -- E4 +# + +source "tests/scripts/expect/_common.exp" + +spawn_node 1 + +set timeout 1 + +send "panid 0xface\n" +expect "Done" + +send "ifconfig up\n" +expect "Done" + +send "thread start\n" +expect "Done" + +wait_for "state" "leader" +expect "Done" + +set extaddr1 [get_extaddr] + +get_rloc16 + +spawn_node 2 cli + +send "panid 0xface\n" +expect "Done" + +send "ifconfig up\n" +expect "Done" + +send "thread start\n" +expect "Done" + +wait_for "state" "router" +expect "Done" +sleep 3 + +get_rloc16 + +spawn_node 3 cli + +send "panid 0xface\n" +expect "Done" + +send "macfilter addr add ${extaddr1}\n" +expect "Done" + +send "macfilter addr denylist\n" +expect "Done" + +send "ifconfig up\n" +expect "Done" + +send "thread start\n" +expect "Done" + +wait_for "state" "router" +expect "Done" +sleep 4 + +set extaddr3 [get_extaddr] + +get_rloc16 + +spawn_node 4 cli + +send "panid 0xface\n" +expect "Done" + +send "mode rn\n" +expect "Done" + +send "macfilter addr add ${extaddr3}\n" +expect "Done" + +send "macfilter addr allowlist\n" +expect "Done" + +send "ifconfig up\n" +expect "Done" + +send "thread start\n" +expect "Done" + +wait_for "state" "child" +expect "Done" + +get_rloc16 + +switch_node 1 + +set rloc(1) [get_ipaddr "rloc"] + +send "networkdiagnostic get ff03::2 5 16\n" +expect "DIAG_GET.rsp/ans from $rloc(1)" +expect "Done" + +sleep 5 + +dispose_all diff --git a/tests/scripts/expect/tun-realm-local-multicast.exp b/tests/scripts/expect/tun-realm-local-multicast.exp index 51d022452..daba3438e 100755 --- a/tests/scripts/expect/tun-realm-local-multicast.exp +++ b/tests/scripts/expect/tun-realm-local-multicast.exp @@ -112,7 +112,7 @@ expect "Done" wait_for "state" "child" -set mleid4 [get_mleid] +set mleid4 [get_ipaddr "mleid"] switch_node 1