[mesh-forwarder] simplify multicast forward to sleepy children (#9505)

This commit simplifies the `MeshForwarder::SendMessage()` method and
its logic for determining whether to send a multicast message to
sleepy children. We first determine whether the destination address
is link-local or realm-local all-nodes, meaning it is destined to all
nodes. Otherwise, we need to check whether each sleepy child is
subscribed to the address. We then iterate through the child table
and mark the message for indirect transmission accordingly.
This commit is contained in:
Abtin Keshavarzian
2023-10-10 10:03:45 -07:00
committed by GitHub
parent 8cefa49877
commit 2fe077037d
+17 -27
View File
@@ -48,8 +48,7 @@ RegisterLogModule("MeshForwarder");
Error MeshForwarder::SendMessage(Message &aMessage)
{
Mle::MleRouter &mle = Get<Mle::MleRouter>();
Error error = kErrorNone;
Error error = kErrorNone;
aMessage.SetOffset(0);
aMessage.SetDatagramTag(0);
@@ -60,57 +59,48 @@ Error MeshForwarder::SendMessage(Message &aMessage)
{
case Message::kTypeIp6:
{
Ip6::Header ip6Header;
Ip6::Header ip6Header;
const Ip6::Address &destination = ip6Header.GetDestination();
IgnoreError(aMessage.Read(0, ip6Header));
if (ip6Header.GetDestination().IsMulticast())
if (destination.IsMulticast())
{
// For traffic destined to multicast address larger than realm local, generally it uses IP-in-IP
// encapsulation (RFC2473), with outer destination as ALL_MPL_FORWARDERS. So here if the destination
// is multicast address larger than realm local, it should be for indirection transmission for the
// device's sleepy child, thus there should be no direct transmission.
if (!ip6Header.GetDestination().IsMulticastLargerThanRealmLocal())
if (!destination.IsMulticastLargerThanRealmLocal())
{
// schedule direct transmission
aMessage.SetDirectTransmission();
}
if (aMessage.GetSubType() != Message::kSubTypeMplRetransmission)
{
if (ip6Header.GetDestination() == mle.GetLinkLocalAllThreadNodesAddress() ||
ip6Header.GetDestination() == mle.GetRealmLocalAllThreadNodesAddress())
// Check if we need to forward the multicast message
// to any sleepy child. This is skipped for MPL retx
// (only the first MPL transmission is forwarded to
// sleepy children).
bool destinedForAll = ((destination == Get<Mle::Mle>().GetLinkLocalAllThreadNodesAddress()) ||
(destination == Get<Mle::Mle>().GetRealmLocalAllThreadNodesAddress()));
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
{
// destined for all sleepy children
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
if (!child.IsRxOnWhenIdle() && (destinedForAll || child.HasIp6Address(destination)))
{
if (!child.IsRxOnWhenIdle())
{
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
}
}
}
else
{
// destined for some sleepy children which subscribed the multicast address.
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateValidOrRestoring))
{
if (!child.IsRxOnWhenIdle() && child.HasIp6Address(ip6Header.GetDestination()))
{
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
}
mIndirectSender.AddMessageForSleepyChild(aMessage, child);
}
}
}
}
else // Destination is unicast
{
Neighbor *neighbor = Get<NeighborTable>().FindNeighbor(ip6Header.GetDestination());
Neighbor *neighbor = Get<NeighborTable>().FindNeighbor(destination);
if ((neighbor != nullptr) && !neighbor->IsRxOnWhenIdle() && !aMessage.IsDirectTransmission() &&
Get<ChildTable>().Contains(*neighbor))
{
// Destined for a sleepy child
mIndirectSender.AddMessageForSleepyChild(aMessage, *static_cast<Child *>(neighbor));
}
else