I am working on a C++ application to receive multicast UDP data on a Windows machine. I have encountered an issue where the application is missing data packets when using a Mellanox network card. However, the same application works perfectly with a Solarflare network card.
Setup:
Windows operating system.
Mellanox network card.
Multicast UDP receiver written in C++.
The same machine also has Wireshark installed.
Observations:
When I use Wireshark to join the multicast group and receive data from the Mellanox card, no data packets are missing.
When I run my C++ application to receive multicast data on the Mellanox card, it misses some data packets.
The same C++ application works fine with a Solarflare network card, receiving all data packets without any loss.
Code snippet :
<code>// Initialize Winsock
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
std::cerr << "WSAStartup failed with error: " << result << std::endl;
SOCKET fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd == INVALID_SOCKET) {
std::cerr << "socket creation failed with error: " << WSAGetLastError() << std::endl;
// Allow multiple sockets to use the same port number
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes)) == SOCKET_ERROR) {
std::cerr << "setsockopt SO_REUSEADDR failed with error: " << WSAGetLastError() << std::endl;
// Set receive buffer size
int receiveBufferSize = 655360000; // 250 * 1024 * 1024;
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&receiveBufferSize, sizeof(receiveBufferSize)) == SOCKET_ERROR) {
std::cerr << "setsockopt SO_RCVBUF failed with error: " << WSAGetLastError() << std::endl;
// Bind to the specified interface and port
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(_interface.c_str());
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
// Join the multicast group
mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
mreq.imr_interface.s_addr = inet_addr(_interface.c_str());
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == SOCKET_ERROR) {
std::cerr << "setsockopt IP_ADD_MEMBERSHIP failed with error: " << WSAGetLastError() << std::endl;
LOG_INFO << "Successfully created socket IP: " << group << ", PORT: " << port << " & INTERFACE: " << _interface;
int addrlen = sizeof(addr);
int nbytes = recvfrom(fd, msgbuf, max_length, 0, (struct sockaddr*)&addr, &addrlen);
if (nbytes == SOCKET_ERROR) {
std::cerr << "recvfrom failed with error: " << WSAGetLastError() << std::endl;
// Process received packet
char* ptr = new char[nbytes];
memcpy(ptr, msgbuf, nbytes);
multicast_q.push(queueMsg);
<code>// Initialize Winsock
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cerr << "WSAStartup failed with error: " << result << std::endl;
return;
}
// Create socket
SOCKET fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd == INVALID_SOCKET) {
std::cerr << "socket creation failed with error: " << WSAGetLastError() << std::endl;
WSACleanup();
return;
}
// Allow multiple sockets to use the same port number
BOOL yes = TRUE;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes)) == SOCKET_ERROR) {
std::cerr << "setsockopt SO_REUSEADDR failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Set receive buffer size
int receiveBufferSize = 655360000; // 250 * 1024 * 1024;
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&receiveBufferSize, sizeof(receiveBufferSize)) == SOCKET_ERROR) {
std::cerr << "setsockopt SO_RCVBUF failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Bind to the specified interface and port
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(_interface.c_str());
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Join the multicast group
ip_mreq mreq{};
mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
mreq.imr_interface.s_addr = inet_addr(_interface.c_str());
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == SOCKET_ERROR) {
std::cerr << "setsockopt IP_ADD_MEMBERSHIP failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
LOG_INFO << "Successfully created socket IP: " << group << ", PORT: " << port << " & INTERFACE: " << _interface;
// Main receiving loop
while (true) {
char msgbuf[max_length];
int addrlen = sizeof(addr);
int nbytes = recvfrom(fd, msgbuf, max_length, 0, (struct sockaddr*)&addr, &addrlen);
if (nbytes == SOCKET_ERROR) {
std::cerr << "recvfrom failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Process received packet
char* ptr = new char[nbytes];
memcpy(ptr, msgbuf, nbytes);
FIN_STRUCT queueMsg;
queueMsg.msg = ptr;
queueMsg.len = nbytes;
multicast_q.push(queueMsg);
}
</code>
// Initialize Winsock
WSADATA wsaData;
int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != 0) {
std::cerr << "WSAStartup failed with error: " << result << std::endl;
return;
}
// Create socket
SOCKET fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd == INVALID_SOCKET) {
std::cerr << "socket creation failed with error: " << WSAGetLastError() << std::endl;
WSACleanup();
return;
}
// Allow multiple sockets to use the same port number
BOOL yes = TRUE;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes)) == SOCKET_ERROR) {
std::cerr << "setsockopt SO_REUSEADDR failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Set receive buffer size
int receiveBufferSize = 655360000; // 250 * 1024 * 1024;
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&receiveBufferSize, sizeof(receiveBufferSize)) == SOCKET_ERROR) {
std::cerr << "setsockopt SO_RCVBUF failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Bind to the specified interface and port
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(_interface.c_str());
addr.sin_port = htons(port);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
std::cerr << "bind failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Join the multicast group
ip_mreq mreq{};
mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
mreq.imr_interface.s_addr = inet_addr(_interface.c_str());
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == SOCKET_ERROR) {
std::cerr << "setsockopt IP_ADD_MEMBERSHIP failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
LOG_INFO << "Successfully created socket IP: " << group << ", PORT: " << port << " & INTERFACE: " << _interface;
// Main receiving loop
while (true) {
char msgbuf[max_length];
int addrlen = sizeof(addr);
int nbytes = recvfrom(fd, msgbuf, max_length, 0, (struct sockaddr*)&addr, &addrlen);
if (nbytes == SOCKET_ERROR) {
std::cerr << "recvfrom failed with error: " << WSAGetLastError() << std::endl;
closesocket(fd);
WSACleanup();
return;
}
// Process received packet
char* ptr = new char[nbytes];
memcpy(ptr, msgbuf, nbytes);
FIN_STRUCT queueMsg;
queueMsg.msg = ptr;
queueMsg.len = nbytes;
multicast_q.push(queueMsg);
}
What could be causing my C++ application to miss data packets when using the Mellanox network card?
Are there any specific configurations or optimizations needed for Mellanox cards to handle multicast traffic efficiently in a C++ application on Windows?
Why does Wireshark not miss any packets while my C++ application does?
Any suggestions or troubleshooting steps to resolve this issue?
Any help or pointers would be greatly appreciated. Thanks in advance!
I have tried change the recive buffer on the mellonox card .
Same mellonox card is working on the linux machine
I did change widows receive buffer but nothing works
Is there any document available on mellnox support for windows
Or does any one already worked with the mellnox with windows os