mirror of
https://github.com/espressif/openthread.git
synced 2026-10-21 06:58:21 +00:00
[posix] drain TREL UDP packets per mainloop iteration (#13324)
This commit updates `ReceivePacket()` in the POSIX TREL platform implementation (`trel.cpp`) to drain all available UDP datagrams in a loop whenever the TREL socket (`sSocket`) is readable. Previously, `ReceivePacket()` called `recvfrom()` exactly once per `platformTrelProcess()` iteration. When multiple TREL packets (such as an `AddressNotify` immediately followed by MLE or UDP traffic) arrived in rapid succession, only the first datagram was read, leaving the remaining packets buffered in the kernel until subsequent mainloop cycles. If an interleaved packet on another interface (such as `NcpSpinel` on 15.4) was processed before the next mainloop iteration, the neighbor's `mLastRxFragmentTag` advanced, causing the delayed TREL datagram (`AddressNotify`) to be dropped as `kErrorDuplicated` due to `!neighbor->IsLastRxFragmentTagAfter(tag)`. By looping over `recvfrom()` until `EAGAIN` or `EWOULDBLOCK` is returned (`sSocket` is non-blocking), all queued TREL packets are read and processed immediately in receipt order. A loop budget (`kMaxRxPacketsPerIteration = 64`) is included to prevent mainloop starvation during high-rate UDP floods. Additionally, a typo in the buffer overflow check (`sizeof(sRxPacketLength)` vs `sizeof(sRxPacketBuffer)`) is corrected.
This commit is contained in:
+37
-24
@@ -276,37 +276,50 @@ exit:
|
||||
|
||||
static void ReceivePacket(int aSocket, otInstance *aInstance)
|
||||
{
|
||||
struct sockaddr_in6 sockAddr;
|
||||
socklen_t sockAddrLen = sizeof(sockAddr);
|
||||
ssize_t ret;
|
||||
const uint16_t kMaxRxPacketsPerIteration = 64;
|
||||
|
||||
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||
|
||||
ret = recvfrom(aSocket, (char *)sRxPacketBuffer, sizeof(sRxPacketBuffer), 0, (struct sockaddr *)&sockAddr,
|
||||
&sockAddrLen);
|
||||
VerifyOrDie(ret >= 0, OT_EXIT_ERROR_ERRNO);
|
||||
|
||||
sRxPacketLength = (uint16_t)(ret);
|
||||
|
||||
if (sRxPacketLength > sizeof(sRxPacketBuffer))
|
||||
for (uint16_t i = 0; i < kMaxRxPacketsPerIteration;)
|
||||
{
|
||||
sRxPacketLength = sizeof(sRxPacketLength);
|
||||
}
|
||||
struct sockaddr_in6 sockAddr;
|
||||
socklen_t sockAddrLen = sizeof(sockAddr);
|
||||
ssize_t ret;
|
||||
|
||||
LogDebg("ReceivePacket() - received from [%s]:%d, id:%d, pkt:%s", Ip6AddrToString(&sockAddr.sin6_addr),
|
||||
ntohs(sockAddr.sin6_port), sockAddr.sin6_scope_id, BufferToString(sRxPacketBuffer, sRxPacketLength));
|
||||
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||
|
||||
if (sEnabled)
|
||||
{
|
||||
otSockAddr senderAddr;
|
||||
ret = recvfrom(aSocket, (char *)sRxPacketBuffer, sizeof(sRxPacketBuffer), 0, (struct sockaddr *)&sockAddr,
|
||||
&sockAddrLen);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
VerifyOrDie(false, OT_EXIT_ERROR_ERRNO);
|
||||
}
|
||||
|
||||
++sCounters.mRxPackets;
|
||||
sCounters.mRxBytes += sRxPacketLength;
|
||||
sRxPacketLength = (uint16_t)(ret);
|
||||
|
||||
memcpy(&senderAddr.mAddress, &sockAddr.sin6_addr, sizeof(otIp6Address));
|
||||
senderAddr.mPort = ntohs(sockAddr.sin6_port);
|
||||
LogDebg("ReceivePacket() - received from [%s]:%d, id:%d, pkt:%s", Ip6AddrToString(&sockAddr.sin6_addr),
|
||||
ntohs(sockAddr.sin6_port), sockAddr.sin6_scope_id, BufferToString(sRxPacketBuffer, sRxPacketLength));
|
||||
|
||||
otPlatTrelHandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength, &senderAddr);
|
||||
if (sEnabled)
|
||||
{
|
||||
otSockAddr senderAddr;
|
||||
|
||||
++sCounters.mRxPackets;
|
||||
sCounters.mRxBytes += sRxPacketLength;
|
||||
|
||||
memcpy(&senderAddr.mAddress, &sockAddr.sin6_addr, sizeof(otIp6Address));
|
||||
senderAddr.mPort = ntohs(sockAddr.sin6_port);
|
||||
|
||||
otPlatTrelHandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength, &senderAddr);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user