[nexus] optimize HandleIp6Receive and SendIp6 to use OwnedPtr (#12846)

This commit updates the IPv6 receive path in the Nexus platform to
utilize `OwnedPtr<Message>` for message lifecycle management. It
also removes the need for a large local buffer and redundant
message allocations.

Previously, `Node::HandleReceive()` copied the entire `otMessage`
payload into a local array, and `InfraIf::SendIp6()` allocated a new
`Message` to enqueue for transmission.

With this change:
- `Node::HandleIp6Receive()` wraps the received `otMessage` in an
  `OwnedPtr<Message>`, ensuring proper cleanup upon exit without
  explicitly calling `otMessageFree()`.
- The `Ip6::Header::ParseFrom` is used which reads and validates
  the IPv6 header and the message.
- The hop limit is updated in-place within the `Message` using
  `Write()` to overwrite previous header.
- `InfraIf::SendIp6()` accepts the `OwnedPtr<Message>` directly,
  taking ownership and enqueuing it without requiring reallocation
  or memory copying.
- Condition checks in `Node::HandleIp6Receive()` are reordered
  to match the comment.
This commit is contained in:
Abtin Keshavarzian
2026-04-07 13:22:55 -05:00
committed by GitHub
parent 641e84aed4
commit a24e841ad2
4 changed files with 25 additions and 38 deletions
+5 -12
View File
@@ -293,21 +293,14 @@ void InfraIf::HandleRouterSolicitation(const Ip6::Address &aSrcAddress)
}
}
void InfraIf::SendIp6(const Ip6::Address &aSrcAddress,
const Ip6::Address &aDestAddress,
const uint8_t *aBuffer,
uint16_t aBufferLength)
void InfraIf::SendIp6(const Ip6::Header &aHeader, OwnedPtr<Message> aMessagePtr)
{
Message *message = GetNode().Get<MessagePool>().Allocate(Message::kTypeIp6);
VerifyOrQuit(aMessagePtr != nullptr);
VerifyOrQuit(message != nullptr);
Log("InfraIf::SendIp6 from %s to %s (len:%u)", aHeader.GetSource().ToString().AsCString(),
aHeader.GetDestination().ToString().AsCString(), aMessagePtr->GetLength());
Log("InfraIf::SendIp6 from %s to %s (len:%u)", aSrcAddress.ToString().AsCString(),
aDestAddress.ToString().AsCString(), aBufferLength);
SuccessOrQuit(message->AppendBytes(aBuffer, aBufferLength));
mPendingTxQueue.Enqueue(*message);
mPendingTxQueue.Enqueue(*aMessagePtr.Release());
}
void InfraIf::SendEchoRequest(const Ip6::Address &aSrcAddress,
+1 -4
View File
@@ -64,10 +64,7 @@ public:
const Ip6::Prefix *aRioPrefix);
void StartRouterAdvertisement(const Ip6::Prefix &aPioPrefix, const Ip6::Prefix *aRioPrefix = nullptr);
void StopRouterAdvertisement(void);
void SendIp6(const Ip6::Address &aSrcAddress,
const Ip6::Address &aDestAddress,
const uint8_t *aBuffer,
uint16_t aBufferLength);
void SendIp6(const Ip6::Header &aHeader, OwnedPtr<Message> aMessagePtr);
void SendEchoRequest(const Ip6::Address &aSrcAddress,
const Ip6::Address &aDestAddress,
uint16_t aIdentifier,
+17 -21
View File
@@ -142,46 +142,42 @@ void Node::SetName(const char *aPrefix, uint16_t aIndex) { mName.Clear().Append(
void Node::HandleIp6Receive(otMessage *aMessage, void *aContext)
{
static_cast<Node *>(aContext)->HandleReceive(aMessage);
OwnedPtr<Message> messagePtr(AsCoreTypePtr(aMessage));
static_cast<Node *>(aContext)->HandleIp6Receive(messagePtr.PassOwnership());
}
void Node::HandleReceive(otMessage *aMessage)
void Node::HandleIp6Receive(OwnedPtr<Message> aMessagePtr)
{
uint16_t length = otMessageGetLength(aMessage);
uint8_t buffer[1500];
Ip6::Header *header;
Ip6::Header header;
VerifyOrExit(length <= sizeof(buffer));
VerifyOrQuit(otMessageRead(aMessage, 0, buffer, length) == length);
VerifyOrExit(length >= sizeof(Ip6::Header));
header = reinterpret_cast<Ip6::Header *>(buffer);
VerifyOrExit(aMessagePtr != nullptr);
SuccessOrExit(header.ParseFrom(*aMessagePtr));
// Forward packets to InfraIf if they are intended for the backbone.
// We avoid forwarding link-local and realm-local scope packets.
VerifyOrExit(mInfraIf.IsInitialized());
VerifyOrExit(header->GetHopLimit() > 1);
header->SetHopLimit(header->GetHopLimit() - 1);
VerifyOrExit(header.GetHopLimit() > 1);
header.SetHopLimit(header.GetHopLimit() - 1);
aMessagePtr->Write(0, header);
VerifyOrExit(header->GetDestination().GetScope() > Ip6::Address::kRealmLocalScope);
VerifyOrExit(header.GetDestination().GetScope() > Ip6::Address::kRealmLocalScope);
if (header->GetDestination().IsMulticast())
if (header.GetDestination().IsMulticast())
{
VerifyOrExit(Get<BackboneRouter::Local>().IsPrimary());
}
VerifyOrExit(Get<NetworkData::Leader>().IsOnMesh(header->GetSource()));
VerifyOrExit(!header.GetSource().IsLinkLocalUnicastOrMulticast());
VerifyOrExit(!Get<Mle::Mle>().IsMeshLocalAddress(header.GetSource()));
VerifyOrExit(Get<NetworkData::Leader>().IsOnMesh(header.GetSource()));
// Only forward if source is NOT Link-Local and NOT Mesh-Local.
VerifyOrExit(!header->GetSource().IsLinkLocalUnicastOrMulticast());
VerifyOrExit(!Get<Mle::Mle>().IsMeshLocalAddress(header->GetSource()));
mInfraIf.SendIp6(header->GetSource(), header->GetDestination(), buffer, length);
mInfraIf.SendIp6(header, aMessagePtr.PassOwnership());
exit:
otMessageFree(aMessage);
return;
}
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+2 -1
View File
@@ -135,7 +135,6 @@ public:
static Node &From(otInstance *aInstance) { return static_cast<Node &>(*aInstance); }
static void HandleIp6Receive(otMessage *aMessage, void *aContext);
void HandleReceive(otMessage *aMessage);
using Platform::mAlarmMicro;
using Platform::mAlarmMilli;
@@ -160,6 +159,8 @@ private:
{
}
void HandleIp6Receive(OwnedPtr<Message> aMessagePtr);
String<32> mName;
};