Skip to content

Commit

Permalink
Make sure socket send buffers are set to a reasonable size, reduce re…
Browse files Browse the repository at this point in the history
…ceive buffers for sockets that won't be used to receive data.
  • Loading branch information
dkulp committed Oct 25, 2024
1 parent b170bbc commit 331adfd
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 23 deletions.
3 changes: 1 addition & 2 deletions src/boot/FPPINIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ static void setupNetwork() {
}

printf("FPP - Setting max IGMP memberships\n");
exec("/usr/sbin/sysctl net/ipv4/igmp_max_memberships=512 > /dev/null 2>&1");
exec("/usr/sbin/sysctl -w net/core/rmem_max=393216 net/core/wmem_max=393216 net/ipv4/igmp_max_memberships=512 > /dev/null 2>&1");
if (ipForward) {
exec("/usr/sbin/sysctl net.ipv4.ip_forward=1");
} else {
Expand Down Expand Up @@ -1374,4 +1374,3 @@ int main(int argc, char* argv[]) {
printf("------------------------------\n");
return 0;
}

59 changes: 38 additions & 21 deletions src/channeloutput/UDPOutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,37 +443,46 @@ int UDPOutput::SendMessages(unsigned int socketKey, SendSocketInfo* socketInfo,

int newSockKey = socketKey;
int sendSocket = socketInfo->sockets[socketInfo->curSocket];
++socketInfo->curSocket;
if (socketInfo->curSocket == socketInfo->sockets.size()) {
socketInfo->curSocket = 0;
}

errno = 0;
int oc = sendmmsg(sendSocket, msgs, msgCount, MSG_DONTWAIT);
int outputCount = 0;
if (oc > 0) {
outputCount = oc;
}

if (outputCount != msgCount) {
// in many cases, a simple thread yield will allow the network stack
// to flush some data and free up space, give that a chance first
std::this_thread::yield();
oc = sendmmsg(sendSocket, &msgs[outputCount], msgCount - outputCount, MSG_DONTWAIT);
if (oc > 0) {
outputCount += oc;
}
}
int errCount = 0;
while (outputCount != msgCount) {
LogErr(VB_CHANNELOUT, "sendmmsg() failed for UDP output (key: %X Socket: %d output count: %d/%d) with error: %d %s\n",
socketKey, sendSocket,
outputCount, msgCount,
errno,
strerror(errno));
if (errno != 0) {
LogErr(VB_CHANNELOUT, "sendmmsg() failed for UDP output (key: %X Socket: %d output count: %d/%d) with error: %d %s\n",
socketKey, sendSocket,
outputCount, msgCount,
errno,
strerror(errno));
}

int newSock = sendSocket;
if (errno == EAGAIN || errno == EWOULDBLOCK) {
if (socketKey != BROADCAST_MESSAGES_KEY) {
++socketInfo->curSocket;
if (socketInfo->curSocket == socketInfo->sockets.size()) {
socketInfo->curSocket = 0;
if (socketInfo->sockets.size() < 5) {
// this will trigger a create socket
socketInfo->sockets.push_back(-1);
} else {
socketInfo->curSocket = 0;
}
}
newSock = socketInfo->sockets[socketInfo->curSocket];
if (newSock == -1) {
sendSocket = socketInfo->sockets[socketInfo->curSocket];
if (sendSocket == -1) {
socketInfo->sockets[socketInfo->curSocket] = createSocket();
newSock = socketInfo->sockets[socketInfo->curSocket];
sendSocket = socketInfo->sockets[socketInfo->curSocket];
}
} else {
return outputCount;
Expand All @@ -484,7 +493,7 @@ int UDPOutput::SendMessages(unsigned int socketKey, SendSocketInfo* socketInfo,
return outputCount;
}
errno = 0;
int oc = sendmmsg(newSock, &msgs[outputCount], msgCount - outputCount, MSG_DONTWAIT);
int oc = sendmmsg(sendSocket, &msgs[outputCount], msgCount - outputCount, MSG_DONTWAIT);
if (oc > 0) {
outputCount += oc;
}
Expand Down Expand Up @@ -546,7 +555,7 @@ int UDPOutput::SendData(unsigned char* channelData) {
auto t1 = clock.now();
for (auto& msgs : messages.messages) {
if (!msgs.second.empty() && msgs.first < LATE_MULTICAST_MESSAGES_KEY) {
SendSocketInfo* socketInfo = findOrCreateSocket(msgs.first, 5);
SendSocketInfo* socketInfo = findOrCreateSocket(msgs.first);

std::unique_lock<std::mutex> lock(workMutex);
workQueue.push_back(WorkItem(msgs.first, socketInfo, msgs.second));
Expand All @@ -573,7 +582,7 @@ int UDPOutput::SendData(unsigned char* channelData) {
// now output the LATE/Broadcast packets (likely sync packets)
for (auto& msgs : messages.messages) {
if (!msgs.second.empty()) {
SendSocketInfo* socketInfo = findOrCreateSocket(msgs.first, 5);
SendSocketInfo* socketInfo = findOrCreateSocket(msgs.first);
if (msgs.first >= LATE_MULTICAST_MESSAGES_KEY) {
t1 = clock.now();
int outputCount = SendMessages(msgs.first, socketInfo, msgs.second);
Expand Down Expand Up @@ -604,7 +613,7 @@ int UDPOutput::SendData(unsigned char* channelData) {
}
for (auto& msgs : messages.messages) {
if (!msgs.second.empty()) {
SendSocketInfo* socketInfo = findOrCreateSocket(msgs.first, 5);
SendSocketInfo* socketInfo = findOrCreateSocket(msgs.first);
auto t1 = clock.now();
int outputCount = SendMessages(msgs.first, socketInfo, msgs.second);
auto t2 = clock.now();
Expand Down Expand Up @@ -740,13 +749,21 @@ int UDPOutput::createSocket(int port, bool broadCast) {
address.sin_port = ntohs(port);

errno = 0;
/* Disable loopback so I do not receive my own datagrams. */
// Disable loopback so I do not receive my own datagrams.
char loopch = 0;
if (setsockopt(sendSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&loopch, sizeof(loopch)) < 0) {
LogErr(VB_CHANNELOUT, "Error setting IP_MULTICAST_LOOP error\n");
close(sendSocket);
return -1;
}
// make sure the send buffer is actually set to a reasonable size
int bufSize = 512 * 1024;
setsockopt(sendSocket, SOL_SOCKET, SO_SNDBUF, &bufSize, sizeof(bufSize));
// these sockets are for sending only, don't need a large receive buffer so
// free some memory by setting to just a single page
bufSize = 4096;
setsockopt(sendSocket, SOL_SOCKET, SO_RCVBUF, &bufSize, sizeof(bufSize));

if (broadCast) {
int broadcast = 1;
if (setsockopt(sendSocket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0) {
Expand Down
2 changes: 2 additions & 0 deletions src/e131bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ int CreateArtNetSocket() {
#endif
int bufSize = 512 * 1024;
setsockopt(artnetSock, SOL_SOCKET, SO_RCVBUF, &bufSize, sizeof(bufSize));
bufSize = 512 * 1024;
setsockopt(artnetSock, SOL_SOCKET, SO_SNDBUF, &bufSize, sizeof(bufSize));

memset((char*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
Expand Down

0 comments on commit 331adfd

Please sign in to comment.