mirror of
https://github.com/espressif/openthread.git
synced 2026-08-10 20:57:47 +00:00
[ip6] enable multicast loop (#5848)
This commit enables the feature IPV6_MULTICAST_LOOP into OpenThread IPv6 stack. The default-enabled feature allows a node receives a multicast message sent by its own.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
+6
-2
@@ -4450,7 +4450,9 @@ void Interpreter::HandleDiagnosticGetResponse(otError aError,
|
||||
aError, aMessage, static_cast<const Ip6::MessageInfo *>(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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
+64
-21
@@ -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<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
|
||||
@@ -1144,10 +1165,23 @@ start:
|
||||
forward = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
netif = aNetif;
|
||||
}
|
||||
else
|
||||
{
|
||||
forward = true;
|
||||
|
||||
netif = &Get<ThreadNetif>();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -90,6 +90,7 @@ otError NetworkDiagnostic::SendDiagnosticGet(const Ip6::Address &aDestination,
|
||||
if (aDestination.IsMulticast())
|
||||
{
|
||||
SuccessOrExit(error = message->InitAsNonConfirmablePost(UriPath::kDiagnosticGetQuery));
|
||||
messageInfo.SetMulticastLoop(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
+136
@@ -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
|
||||
@@ -112,7 +112,7 @@ expect "Done"
|
||||
|
||||
wait_for "state" "child"
|
||||
|
||||
set mleid4 [get_mleid]
|
||||
set mleid4 [get_ipaddr "mleid"]
|
||||
|
||||
switch_node 1
|
||||
|
||||
|
||||
Reference in New Issue
Block a user