[nexus] mark pending action when enqueuing packets on infra interface (#13699)

Unlike otTaskletsSignalPending() and otPlatRadioTransmit(), InfraIf
previously enqueued outgoing packets into mPendingTxQueue without
calling Core::Get().MarkPendingAction().

When a higher-index node (e.g., an unattached candidate node1) sends a
packet over InfraIf to a lower-index node (e.g., node0 Border Agent),
ProcessInfraIf(node1) delivers the packet into node0.mInfraIf.Receive()
after Process(node0) has already run in the current Core::AdvanceTime()
pass. Any synchronous response packet enqueued into
node0.mInfraIf.mPendingTxQueue remained undelivered when mPendingAction
stayed false, causing Core::AdvanceTime() to jump mNow forward to the
next unrelated scheduled timer. For a 6-flight DTLS handshake between
node1 and node0, all three server flights stalled until separate
background timers expired, intermittently pushing handshake completion
past 1 second.

Add InfraIf::EnqueueTxPacket() to enqueue outgoing messages and call
Core::Get().MarkPendingAction(), make mPendingTxQueue private with
Core as a friend class, and add InfraIf::Reset() for Node::Reset().
This commit is contained in:
Yakun Xu
2026-10-10 00:22:36 -07:00
committed by GitHub
parent 90224407f0
commit 0297ea0a0a
3 changed files with 21 additions and 8 deletions
+14 -5
View File
@@ -30,6 +30,7 @@
#include <openthread/platform/infra_if.h>
#include "nexus_core.hpp"
#include "nexus_node.hpp"
namespace ot {
@@ -62,6 +63,8 @@ void InfraIf::AfterInit(void)
AddAddress(address);
}
void InfraIf::Reset(void) { mPendingTxQueue.DequeueAndFreeAll(); }
bool InfraIf::HasAddress(const Ip6::Address &aAddress) const { return mAddresses.Contains(aAddress); }
void InfraIf::AddAddress(const Ip6::Address &aAddress)
@@ -177,7 +180,13 @@ void InfraIf::SendIcmp6Nd(const Ip6::Address &aDestAddress, const uint8_t *aBuff
message->SetOffset(sizeof(Ip6::Header));
Checksum::UpdateMessageChecksum(*message, ip6Header.GetSource(), ip6Header.GetDestination(), Ip6::kProtoIcmp6);
mPendingTxQueue.Enqueue(*message);
EnqueueTxPacket(*message);
}
void InfraIf::EnqueueTxPacket(Message &aMessage)
{
mPendingTxQueue.Enqueue(aMessage);
Core::Get().MarkPendingAction();
}
void InfraIf::SendRouterAdvertisement(const Ip6::Address &aDestination,
@@ -341,7 +350,7 @@ void InfraIf::SendIp6(const Ip6::Header &aHeader, OwnedPtr<Message> aMessagePtr)
Log("InfraIf::SendIp6 from %s to %s (len:%u)", aHeader.GetSource().ToString().AsCString(),
aHeader.GetDestination().ToString().AsCString(), aMessagePtr->GetLength());
mPendingTxQueue.Enqueue(*aMessagePtr.Release());
EnqueueTxPacket(*aMessagePtr.Release());
}
void InfraIf::SendEchoRequest(const Ip6::Address &aSrcAddress,
@@ -378,7 +387,7 @@ void InfraIf::SendEchoRequest(const Ip6::Address &aSrcAddress,
SuccessOrQuit(message->Prepend(ip6Header));
mPendingTxQueue.Enqueue(*message);
EnqueueTxPacket(*message);
}
void InfraIf::SendUdp(const Ip6::Address &aSrcAddress,
@@ -418,7 +427,7 @@ void InfraIf::SendUdp(const Ip6::Address &aSrcAddress,
loopbackMessage->Free();
}
mPendingTxQueue.Enqueue(aPayload);
EnqueueTxPacket(aPayload);
}
void InfraIf::SetDhcp6ListeningEnabled(bool aEnable) { mDhcp6PdListening = aEnable; }
@@ -619,7 +628,7 @@ void InfraIf::HandleEchoRequest(const Ip6::Header &aHeader, Message &aMessage)
SuccessOrQuit(replyMessage->Prepend(replyHeader));
mPendingTxQueue.Enqueue(*replyMessage);
EnqueueTxPacket(*replyMessage);
}
void InfraIf::HandleEchoReply(const Ip6::Header &aHeader, Message &aMessage)
+6 -2
View File
@@ -38,12 +38,15 @@ class Node;
class InfraIf : public InstanceLocator
{
friend class Core;
public:
using LinkLayerAddress = BorderRouter::InfraIf::LinkLayerAddress;
explicit InfraIf(Instance &aInstance);
void AfterInit(void);
void Reset(void);
bool IsInitialized(void) const { return mIfIndex != 0; }
@@ -93,9 +96,8 @@ public:
typedef bool (*UdpHook)(Instance &aInstance, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SetUdpHook(UdpHook aHook) { mUdpHook = aHook; }
MessageQueue mPendingTxQueue;
private:
void EnqueueTxPacket(Message &aMessage);
void ProcessIcmp6Nd(const Ip6::Address &aSrcAddress, const uint8_t *aBuffer, uint16_t aBufferLength);
void SendPeriodicRouterAdvertisement(void);
void HandlePrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio);
@@ -105,6 +107,8 @@ private:
void HandleRaTimer(void);
MessageQueue mPendingTxQueue;
uint32_t mIfIndex;
Heap::Array<Ip6::Address> mAddresses;
Callback<EchoReplyHandler> mEchoReplyCallback;
+1 -1
View File
@@ -55,7 +55,7 @@ void Node::Reset(void)
mAlarmMicro.Reset();
mMdns.Reset();
mUpstreamDns.Reset();
mInfraIf.mPendingTxQueue.DequeueAndFreeAll();
mInfraIf.Reset();
mPendingTasklet = false;
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE