From 3e3690a068a2051d87be6afba8060ea2a9577e7d Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 11 Mar 2026 11:10:45 -0700 Subject: [PATCH] [ip6] simplify multicast forwarding logic in `DetermineAction()` (#12653) This commit simplifies and updates `Ip6::DetermineAction()` regarding how the `aForwardThread` flag is determined for multicast messages with a scope larger than realm-local. Such messages are sent using IP-in-IP encapsulation destined to the `RealmLocalAllMplForwarders` address. Both the encapsulated (outer) and embedded (inner) messages are processed. When processing the embedded IPv6 message, regardless of its origin, we only need to forward it to the Thread mesh if the device has a sleepy child subscribed to the multicast address. `MeshForwarder::SendMessage()` on an FTD will then check for these subscriptions and schedule indirect transmissions to those children. The behavior for FTDs remains functionally the same as before, though the code has been refactored to be clearer and easier to follow. The primary change applies to MTDs: if the multicast destination scope is larger than realm-local, the message is no longer forwarded to Thread, as an MTD cannot have any children to support. --- src/core/net/ip6.cpp | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 36b4db582..1f3565606 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -1099,18 +1099,33 @@ void Ip6::DetermineAction(const Message &aMessage, { // Destination is multicast - // Forward multicast message to thread unless we received it - // on Thread netif. - - aForwardThread = !aMessage.IsOriginThreadNetif(); + if (aHeader.GetDestination().IsMulticastLargerThanRealmLocal()) + { + // Multicast messages with scope larger than realm-local + // use IP-in-IP encapsulation destined to the "All MPL + // Forwarders" multicast address. Both the encapsulated + // (outer) and embedded (inner) messages are processed. + // + // For the inner message, we set `aForwardThread` if the + // device has a sleepy child that is subscribed to the + // destination address. `MeshForwarder::SendMessage()` on + // an FTD will then check for this and schedules the + // indirect tx to such children. This is skipped on an MTD + // (`aForwardThread` remains `false`) since an MTD cannot + // have children. #if OPENTHREAD_FTD - if (aMessage.IsOriginThreadNetif() && aHeader.GetDestination().IsMulticastLargerThanRealmLocal() && - Get().HasSleepyChildWithAddress(aHeader.GetDestination())) - { - aForwardThread = true; - } + aForwardThread = Get().HasSleepyChildWithAddress(aHeader.GetDestination()); #endif + } + else + { + // For all other multicast messages, we forward to the + // Thread network unless the message was received on the + // Thread netif. + + aForwardThread = !aMessage.IsOriginThreadNetif(); + } // Always forward multicast packets to host network stack aForwardHost = true;