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;