Implemented better testing and fixed skipepd frames
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "MemoryOperationsHelper.h"
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
namespace MARTe {
|
||||
@@ -26,6 +27,7 @@ UDPSClient::UDPSClient()
|
||||
maxPayloadSize(UDPS_CLIENT_DEFAULT_MAX_PAYLOAD),
|
||||
cpuMask(0xFFFFFFFFu),
|
||||
stackSize(65536u),
|
||||
recvBufferSize(UDPS_CLIENT_DEFAULT_RECV_BUFFER),
|
||||
listener(NULL_PTR(UDPSClientListener *)),
|
||||
threadService(*this),
|
||||
connected(false),
|
||||
@@ -98,6 +100,9 @@ bool UDPSClient::Initialise(StructuredDataI &data) {
|
||||
(void) data.Read("CPUMask", cpuMask);
|
||||
(void) data.Read("StackSize", stackSize);
|
||||
|
||||
recvBufferSize = UDPS_CLIENT_DEFAULT_RECV_BUFFER;
|
||||
(void) data.Read("RecvBufferSize", recvBufferSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -209,6 +214,23 @@ bool UDPSClient::Connect() {
|
||||
return ok;
|
||||
}
|
||||
|
||||
void UDPSClient::SetRecvBufferSize(BasicUDPSocket &sock) {
|
||||
/* BasicUDPSocket exposes no SO_RCVBUF API; the OS default (Linux
|
||||
* rmem_default, typically ~208 KiB) is easily overrun by high-throughput
|
||||
* sources, causing silent kernel-level datagram drops. Work around this
|
||||
* by calling setsockopt() directly on the raw handle. Best-effort: a
|
||||
* failure here just leaves the OS default in place. */
|
||||
Handle fd = sock.GetReadHandle();
|
||||
if (fd >= 0) {
|
||||
int32 sz = static_cast<int32>(recvBufferSize);
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) != 0) {
|
||||
REPORT_ERROR_STATIC(ErrorManagement::Warning,
|
||||
"UDPSClient: Could not set SO_RCVBUF to %u bytes.",
|
||||
recvBufferSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UDPSClient::ConnectUnicast() {
|
||||
// Open a local UDP socket bound to an ephemeral port
|
||||
if (!recvSocket.Open()) {
|
||||
@@ -216,6 +238,7 @@ bool UDPSClient::ConnectUnicast() {
|
||||
"UDPSClient: Could not open receive socket.");
|
||||
return false;
|
||||
}
|
||||
SetRecvBufferSize(recvSocket);
|
||||
|
||||
if (!recvSocket.Listen(0u)) {
|
||||
REPORT_ERROR_STATIC(ErrorManagement::Warning,
|
||||
@@ -256,6 +279,7 @@ bool UDPSClient::ConnectMulticast() {
|
||||
"UDPSClient: Could not open multicast socket.");
|
||||
return false;
|
||||
}
|
||||
SetRecvBufferSize(mcastSocket);
|
||||
|
||||
bool ok = mcastSocket.Listen(dataPort);
|
||||
if (!ok) {
|
||||
@@ -378,6 +402,15 @@ bool UDPSClient::ReceiveAndProcess() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* HI-6: guard against FD_SETSIZE overflow */
|
||||
if (fd < 0 || fd >= FD_SETSIZE ||
|
||||
(tcpFd >= 0 && tcpFd >= FD_SETSIZE)) {
|
||||
REPORT_ERROR_STATIC(ErrorManagement::Warning,
|
||||
"UDPSClient: fd >= FD_SETSIZE (%d/%d) — skipping select.",
|
||||
fd, tcpFd);
|
||||
return false;
|
||||
}
|
||||
|
||||
fd_set rset;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(fd, &rset);
|
||||
|
||||
@@ -95,6 +95,12 @@ public:
|
||||
/** Default maximum payload size (bytes, excluding 17-byte header). */
|
||||
static const uint32 UDPS_CLIENT_DEFAULT_MAX_PAYLOAD = 1400u;
|
||||
|
||||
/** Default OS UDP receive socket buffer size (bytes). The Linux default
|
||||
* (rmem_default, typically ~208 KiB) is easily overrun by high-throughput
|
||||
* sources (e.g. multi-hundred-KiB bursts every few ms), causing silent
|
||||
* kernel-level datagram drops. 4 MiB gives generous burst headroom. */
|
||||
static const uint32 UDPS_CLIENT_DEFAULT_RECV_BUFFER = 4194304u; // 4 MiB
|
||||
|
||||
UDPSClient();
|
||||
virtual ~UDPSClient();
|
||||
|
||||
@@ -111,6 +117,7 @@ public:
|
||||
* - MaxPayloadSize (uint32) Max payload bytes per datagram, excluding header. Default 1400.
|
||||
* - CPUMask (uint32) CPU affinity mask for the receive thread. Default 0xFFFFFFFF.
|
||||
* - StackSize (uint32) Stack size for the receive thread. Default 65536.
|
||||
* - RecvBufferSize (uint32) OS UDP receive socket buffer size (bytes). Default 4 MiB.
|
||||
*/
|
||||
bool Initialise(StructuredDataI &data);
|
||||
|
||||
@@ -165,6 +172,9 @@ private:
|
||||
bool ConnectUnicast();
|
||||
bool ConnectMulticast();
|
||||
|
||||
/** Set the OS receive buffer size (SO_RCVBUF) on a UDP socket's raw handle. */
|
||||
void SetRecvBufferSize(BasicUDPSocket &sock);
|
||||
|
||||
void ProcessDatagram(const uint8 *buf, uint32 size);
|
||||
/** Read one full UDPS frame (header + payload) from the TCP control socket. */
|
||||
bool ReceiveTCPFrame();
|
||||
@@ -188,6 +198,7 @@ private:
|
||||
uint32 maxPayloadSize;
|
||||
uint32 cpuMask;
|
||||
uint32 stackSize;
|
||||
uint32 recvBufferSize;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Runtime state
|
||||
|
||||
@@ -268,6 +268,7 @@ void UDPSServer::ServiceClients() {
|
||||
}
|
||||
// Non-blocking peek
|
||||
int fd = tcpClients[i]->GetReadHandle();
|
||||
if (fd < 0 || fd >= FD_SETSIZE) { continue; /* HI-6: skip FDs outside select range */ }
|
||||
fd_set rset;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(fd, &rset);
|
||||
@@ -303,6 +304,7 @@ void UDPSServer::ServiceClients() {
|
||||
return;
|
||||
}
|
||||
int fd = serverSocket.GetReadHandle();
|
||||
if (fd < 0 || fd >= FD_SETSIZE) { return; /* HI-6 */ }
|
||||
fd_set rset;
|
||||
FD_ZERO(&rset);
|
||||
FD_SET(fd, &rset);
|
||||
|
||||
Reference in New Issue
Block a user