From 543b5da0b8987f108d8e72d2bb139d8335284328 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 11 Oct 2023 14:56:35 -0700 Subject: [PATCH] [ip6] update tunnel message receive in `HandleDatagram()` (#9503) This commit updates how `Ip6::HandleDatagram()` processes a tunneled IP-in-IP message. Previously, if a message was marked for both `receive` and `forwardThread`, e.g., possible for a multicast message from host with multicast-loop flag, it would be received but not forwarded to the Thread mesh. This commit ensures that such messages are handled properly. Without this change, multicast transmission still works fine due to the MPL layer retransmitting the message, which would then be forwarded to the Thread mesh. However, this change improves the multicast behavior by ensuring that the original/first message is also forwarded to the Thread mesh. This commit changes the code so that if we need to both `receive` and `forwardThread`, we create a copy of the message by cloning it. Otherwise, we take ownership of the original message and use it directly. We then remove the encapsulating header before processing the embedded message by calling the `HandleDatagram()` recursively. --- src/core/net/ip6.cpp | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 5fc60089f..22b383450 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -1145,7 +1145,6 @@ Error Ip6::HandleDatagram(Message &aMessage, const void *aLinkMessageInfo, bool bool shouldFreeMessage; uint8_t nextHeader; -start: receive = false; forwardThread = false; forwardHost = false; @@ -1229,10 +1228,34 @@ start: if (receive && (nextHeader == kProtoIp6)) { - // Remove encapsulating header and start over. - aMessage.RemoveHeader(aMessage.GetOffset()); - Get().LogMessage(MeshForwarder::kMessageReceive, aMessage); - goto start; + // Process the embedded IPv6 message in an IPv6 tunnel message. + // If we need to `forwardThread` we create a copy by cloning + // the message, otherwise we take ownership of `aMessage` + // itself and use it directly. The encapsulating header is + // then removed before processing the embedded message. + + Message *messageCopy; + + if (forwardThread) + { + messageCopy = aMessage.Clone(); + VerifyOrExit(messageCopy != nullptr, error = kErrorNoBufs); + messageCopy->SetMulticastLoop(aMessage.GetMulticastLoop()); + } + else + { + messageCopy = &aMessage; + shouldFreeMessage = false; + } + + messageCopy->RemoveHeader(messageCopy->GetOffset()); + + Get().LogMessage(MeshForwarder::kMessageReceive, *messageCopy); + + IgnoreError(HandleDatagram(*messageCopy, aLinkMessageInfo, aIsReassembled)); + + receive = false; + forwardHost = false; } if ((forwardHost || receive) && !aIsReassembled)