mirror of
https://github.com/espressif/openthread.git
synced 2026-07-31 08:07:47 +00:00
[ping-sender] allow setting multicast loop (#9494)
This commit updates `PingSender` and its config to include a `mMulticastLoop` flag and allow the caller to set this flag. When set, multicast ping echo request messages are looped back and received by the device itself if it is subscribed to the same address. The `ping` CLI command is also updated to allow setting this flag. This commit also updates `test-008-multicast-traffic.py` to add new test cases to cover the multicast loop flag behavior (pinging with or without this flag). In particular, it covers when the ping destination is a realm-local multicast address and when it is a larger-than-realm-local multicast address (where the `ot::Ip6` module would use a tunnel header for forwarding the message).
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 (363)
|
||||
#define OPENTHREAD_API_VERSION (364)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -120,6 +120,7 @@ typedef struct otPingSenderConfig
|
||||
///< Zero to use default.
|
||||
uint8_t mHopLimit; ///< Hop limit (used if `mAllowZeroHopLimit` is false). Zero for default.
|
||||
bool mAllowZeroHopLimit; ///< Indicates whether hop limit is zero.
|
||||
bool mMulticastLoop; ///< Allow looping back pings to multicast address that device is subscribed to.
|
||||
} otPingSenderConfig;
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -89,7 +89,7 @@ Done
|
||||
- [parent](#parent)
|
||||
- [parentpriority](#parentpriority)
|
||||
- [partitionid](#partitionid)
|
||||
- [ping](#ping-async--i-source-ipaddr-size-count-interval-hoplimit-timeout)
|
||||
- [ping](#ping-async--i-source--m-ipaddr-size-count-interval-hoplimit-timeout)
|
||||
- [platform](#platform)
|
||||
- [pollperiod](#pollperiod-pollperiod)
|
||||
- [preferrouterid](#preferrouterid-routerid)
|
||||
@@ -2728,12 +2728,13 @@ Set the preferred Thread Leader Partition ID.
|
||||
Done
|
||||
```
|
||||
|
||||
### ping \[async\] \[-I source\] \<ipaddr\> \[size\] \[count\] \[interval\] \[hoplimit\] \[timeout\]
|
||||
### ping \[async\] \[-I source\] \[-m] \<ipaddr\> \[size\] \[count\] \[interval\] \[hoplimit\] \[timeout\]
|
||||
|
||||
Send an ICMPv6 Echo Request.
|
||||
|
||||
- async: Use the non-blocking mode. New commands are allowed before the ping process terminates.
|
||||
- source: The source IPv6 address of the echo request.
|
||||
- -m: multicast loop, which allows looping back pings to multicast addresses that the device itself is subscribed to.
|
||||
- size: The number of data bytes to be sent.
|
||||
- count: The number of ICMPv6 Echo Requests to be sent.
|
||||
- interval: The interval between two consecutive ICMPv6 Echo Requests in seconds. The value may have fractional form, for example `0.5`.
|
||||
|
||||
+10
-1
@@ -6019,7 +6019,7 @@ void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics
|
||||
* 1 packets transmitted, 1 packets received. Packet loss = 0.0%. Round-trip min/avg/max = 0/0.0/0 ms.
|
||||
* Done
|
||||
* @endcode
|
||||
* @cparam ping [@ca{async}] [@ca{-I source}] @ca{ipaddrc} [@ca{size}] [@ca{count}] <!--
|
||||
* @cparam ping [@ca{async}] [@ca{-I source}] [@ca{-m}] @ca{ipaddrc} [@ca{size}] [@ca{count}] <!--
|
||||
* --> [@ca{interval}] [@ca{hoplimit}] [@ca{timeout}]
|
||||
* @par
|
||||
* Send an ICMPv6 Echo Request.
|
||||
@@ -6027,6 +6027,9 @@ void Interpreter::HandlePingStatistics(const otPingSenderStatistics *aStatistics
|
||||
* The address can be an IPv4 address, which will be synthesized to an IPv6 address using the preferred NAT64 prefix
|
||||
* from the network data.
|
||||
* @par
|
||||
* The optional `-m` flag sets the multicast loop flag, which allows looping back pings to multicast addresses that the
|
||||
* device itself is subscribed to.
|
||||
* @par
|
||||
* Note: The command will return InvalidState when the preferred NAT64 prefix is unavailable.
|
||||
* @sa otPingSenderPing
|
||||
*/
|
||||
@@ -6085,6 +6088,12 @@ template <> otError Interpreter::Process<Cmd("ping")>(Arg aArgs[])
|
||||
aArgs += 2;
|
||||
}
|
||||
|
||||
if (aArgs[0] == "-m")
|
||||
{
|
||||
config.mMulticastLoop = true;
|
||||
aArgs++;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = ParseToIp6Address(GetInstancePtr(), aArgs[0], config.mDestination, nat64SynthesizedAddress));
|
||||
if (nat64SynthesizedAddress)
|
||||
{
|
||||
|
||||
@@ -134,6 +134,7 @@ void PingSender::SendPing(void)
|
||||
messageInfo.SetPeerAddr(mConfig.GetDestination());
|
||||
messageInfo.mHopLimit = mConfig.mHopLimit;
|
||||
messageInfo.mAllowZeroHopLimit = mConfig.mAllowZeroHopLimit;
|
||||
messageInfo.mMulticastLoop = mConfig.mMulticastLoop;
|
||||
|
||||
message = Get<Ip6::Icmp>().NewMessage();
|
||||
VerifyOrExit(message != nullptr);
|
||||
|
||||
@@ -53,8 +53,17 @@ import time
|
||||
# - r1 =>> mesh-local all-thread (two hops). Expected response from [r2, r3, fed].
|
||||
# - r1 =>> mesh-local all-thread (three hops). Expected response from [r2, r3, r4, fed].
|
||||
# - r1 =>> mesh-local all-thread (four hops). Expected response from [r2, r3, r4, fed, sed].
|
||||
# - r1 =>> specific address (on r2 and sed). Expected to receive on [r2, sed].
|
||||
#
|
||||
# - r1 =>> realm-local scope mcast addr (on r2 and sed). Expected to receive on [r2, sed].
|
||||
# - r2 =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [sed].
|
||||
# - r2 =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
|
||||
# - sed =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [r2].
|
||||
# - sed =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
|
||||
#
|
||||
# - r3 =>> site-local mcast addr (on r1, r2, sed). Expected to receive from [r1, r2, sed].
|
||||
# - r1 =>> site-local mcast addr (on r1, r2, sed) with `multicast-loop`. Expected to receive from [r1, r2, sed].
|
||||
# - r1 =>> site-local mcast addr (on r1, r2, sed) without `multicast-loop`. Expected to receive from [r2, sed].
|
||||
# - sed =>> site-local mcast addr (on r1, r2, sed). Expected to receive from [r1, r2].
|
||||
|
||||
test_name = __file__[:-3] if __file__.endswith('.py') else __file__
|
||||
print('-' * 120)
|
||||
@@ -223,7 +232,7 @@ for node in [r2, r3, r4, fed, sed]:
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Subscribe to a specific multicast address on r2 and sed
|
||||
# Subscribe to a realm-local scope multicast address on r2 and sed
|
||||
|
||||
mcast_addr = 'ff03:0:0:0:0:0:0:114'
|
||||
r2.add_ip_maddr(mcast_addr)
|
||||
@@ -234,12 +243,93 @@ verify(any(mcast_addr in maddr for maddr in maddrs))
|
||||
maddrs = sed.get_ip_maddrs()
|
||||
verify(any(mcast_addr in maddr for maddr in maddrs))
|
||||
|
||||
# r1 =>> realm-local scope mcast addr (on r2 and sed). Expected to receive on [r2, sed].
|
||||
|
||||
outputs = r1.cli('ping', mcast_addr)
|
||||
verify(len(outputs) == 3)
|
||||
for node in [r2, sed]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# r2 =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [sed].
|
||||
|
||||
outputs = r2.cli('ping', mcast_addr)
|
||||
verify(len(outputs) == 2)
|
||||
for node in [sed]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# r2 =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
|
||||
|
||||
outputs = r2.cli('ping', '-m', mcast_addr)
|
||||
verify(len(outputs) == 3)
|
||||
for node in [r2, sed]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# sed =>> realm-local scope mcast addr (on r2 and sed) without `multicast-loop`. Expected to receive from [r2].
|
||||
|
||||
outputs = sed.cli('ping', mcast_addr)
|
||||
verify(len(outputs) == 2)
|
||||
for node in [r2]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# sed =>> realm-local scope mcast addr (on r2 and sed) with `multicast-loop`. Expected to receive from [r2, sed].
|
||||
|
||||
outputs = sed.cli('ping', '-m', mcast_addr)
|
||||
verify(len(outputs) == 3)
|
||||
for node in [r2, sed]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
# Subscribe to a larger than realm-local scope (site-local) multicast address on r1, r2, and sed
|
||||
|
||||
mcast_addr = 'ff05:0:0:0:0:0:0:abcd'
|
||||
r1.add_ip_maddr(mcast_addr)
|
||||
r2.add_ip_maddr(mcast_addr)
|
||||
sed.add_ip_maddr(mcast_addr)
|
||||
time.sleep(1)
|
||||
maddrs = r1.get_ip_maddrs()
|
||||
verify(any(mcast_addr in maddr for maddr in maddrs))
|
||||
maddrs = r2.get_ip_maddrs()
|
||||
verify(any(mcast_addr in maddr for maddr in maddrs))
|
||||
maddrs = sed.get_ip_maddrs()
|
||||
verify(any(mcast_addr in maddr for maddr in maddrs))
|
||||
|
||||
# r3 =>> site-local mcast addr (on r1, r2, sed) with `multicast-loop`. Expected to receive from [r1, r2, sed].
|
||||
|
||||
outputs = r3.cli('ping', '-m', mcast_addr)
|
||||
verify(len(outputs) == 4)
|
||||
for node in [r1, r2, sed]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# r1 =>> site-local mcast addr (on r1, r2, sed) with `multicast-loop`. Expected to receive from [r1, r2, sed].
|
||||
|
||||
outputs = r1.cli('ping', '-m', mcast_addr)
|
||||
verify(len(outputs) == 4)
|
||||
for node in [r1, r2, sed]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# r1 =>> site-local mcast addr (on r1, r2, sed) without `multicast-loop`. Expected to receive from [r2, sed].
|
||||
|
||||
outputs = r1.cli('ping', mcast_addr)
|
||||
verify(len(outputs) == 3)
|
||||
for node in [r2, sed]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# sed =>> site-local mcast addr (on r1, r2, sed) without `multicast-loop`. Expected to receive from [r1, r2].
|
||||
|
||||
outputs = sed.cli('ping', mcast_addr)
|
||||
verify(len(outputs) >= 3)
|
||||
for node in [r1, r2]:
|
||||
ml_addr = node.get_mleid_ip_addr()
|
||||
verify(any(ml_addr in line for line in outputs))
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------------
|
||||
# Test finished
|
||||
|
||||
|
||||
Reference in New Issue
Block a user