C++ 使用 recvmmsg 丢弃 UDP 数据包

c++ drops udp packets with recvmmsg

本文关键字:UDP 数据包 丢弃 recvmmsg 使用 C++      更新时间:2023-10-16

我正在开发一个 c++ 程序,该程序通过以太网使用来自 FPGA 的 UDP 数据流。 FPGA 和以太网卡之间没有集线器或路由器。 数据为 10446 pps,速率为 125350.0 kbps。

我的 c++ 应用程序使用专用线程和 recvmmsg 来清空数据。 每个数据包都有一个序列号作为前 4 个字节,后跟 1468 字节的流数据。 我正在使用recvmmsg,我已经尝试了VLEN(10,100)和MSG_WAITFORONEMSG_DONTWAIT0标志的组合。

我看到的症状是这样的:

  • 在程序启动之前,流以固定速度运行。
  • 当程序启动时,我有一个很短的初始周期,其中recvmmsg的返回值与VLEN相同。 如果我理解正确,这是 Linux 内核缓冲区的耗尽。
  • 在此之后,我总是得到一个值1作为返回值recvmmsg
  • 如果我在系统上造成较小的负载(例如调整 gui 窗口的大小)。我看到 UDP 数据包丢弃,如缺少序列号所示。 (没有重新排序,只是缺少)。
  • 在下降期间/之后,我没有获得更大的返回值recvmmsg
  • Wireshark/tcpdump 不显示任何缺失的数据,所有序列号都存在。

如果我观察netstat -suna的输出,我看到RcvbufErrors:的值增加。

如果我观察ifconfig的输出,我看不到任何丢弃的数据包(RX packets:602492703 errors:0 dropped:0 overruns:0 frame:0)。

这些是我的问题:

  • 为什么在丢弃情况下,我永远不会从recvmmsg收到多个数据包?
  • 为什么 wireshark 能够捕获数据包,而我的 c++ 不能?
  • 可以使用哪些工具来更好地了解我为什么会掉线?

我尝试调整以下可调参数:

  • sysctl -w net.core.netdev_max_backlog=10000
  • sysctl -w net.core.rmem_max=9926214400

请不要建议我切换到TCP。 这不是此特定应用程序的选项。 谢谢。

增加接收套接字的接收缓冲区的大小应该可以解决此问题:

setsockopt (fd, IPPROTO_UDP, SO_RCVBUF, desired_receive_buffer_size);

文档在这里。