[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.
This commit is contained in:
Abtin Keshavarzian
2023-10-11 14:56:35 -07:00
committed by GitHub
parent be317ecb73
commit 543b5da0b8
+28 -5
View File
@@ -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<MeshForwarder>().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<MeshForwarder>().LogMessage(MeshForwarder::kMessageReceive, *messageCopy);
IgnoreError(HandleDatagram(*messageCopy, aLinkMessageInfo, aIsReassembled));
receive = false;
forwardHost = false;
}
if ((forwardHost || receive) && !aIsReassembled)