【问题标题】:Linux locally dropping UDP packets (Receive buffer overflow)Linux 本地丢弃 UDP 数据包(接收缓冲区溢出)
【发布时间】:2019-08-06 23:49:07
【问题描述】:

我构建了一个简单的测试程序,它每 250 毫秒发送 100 个 UDP 数据包,每个数据包大小为 1000 字节。我发现两个独立的 linux 机器正在丢弃其中一些数据包。

我的期望是,当我写入 100 个 UDP 数据包时,内核缓冲区能够保存所有这些数据包。 netstat -us 表示每个被丢弃的数据包都有RcvbufErrors。所以看起来内核接收缓冲区溢出了。但我不明白为什么。

/proc/sys/net/core/rmem_default 显示的值为 212992,因此我认为增加它不会有帮助,因为它已经大于此测试发送的 100kB 批次。

我进行了第二次测试,每 10 毫秒发送 50 个 UDP 数据包,每个数据包大小为 1000 字节。我发现在这个测试中没有数据包被丢弃。这表明 100kB 会溢出缓冲区,而 50kB 不会。它还进一步表明我不受 CPU 限制或数据包限制——这个测试发送数据包的速度比第一个快很多倍。

我使用的两台 linux 机器:macbook 上的 virtualbox 和 AWS m5a.xlarge

我的测试程序:https://github.com/theicfire/rando/tree/master/udp-fail-batch-stack-overflow

【问题讨论】:

  • 哎呀,为什么投反对票?

标签: linux sockets networking udp


【解决方案1】:

您正处于缓冲区大小的边缘,尽管它看起来不像。

rmem_default 的值并不意味着有那么多字节可供使用。在阅读man page 设置SO_RECVBUF 时,我得到了提示:

          The kernel doubles this value (to allow space for bookkeeping
          overhead) when it is set using setsockopt(2), and this doubled
          value is returned by getsockopt(2).

这意味着内核占用了这个缓冲区的一部分。可能是相当大的数量(即,它可能使用了 rmem_default 设置的一半。

SO_RCVBUF 选项设置为 125,000 会阻止数据包丢弃。将其设置为 100,000(由于数据包标头,比您发送的数据包批次少一点)会导致数据包被丢弃。即使 getsockopt 的结果分别是 250,000 和 200,000。

【讨论】:

  • 绝对不要依赖系统的默认大小。如果您预先知道要接收的流量大小,请使用setsockopt() 明确设置您需要的实际缓冲区大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-17
相关资源
最近更新 更多