UDP数据包丢弃 - INErrors Vs .RcvbufErrors

时间:2014-02-09 20:57:22

标签: linux linux-kernel udp epoll

我编写了一个简单的UDP服务器程序,以了解有关可能的网络瓶颈的更多信息。

UDP服务器:创建UDP套接字,将其绑定到指定的端口和地址,并将套接字文件描述符添加到epoll兴趣列表。然后它的epoll等待传入的数据包。收到传入数据包(EPOLLIN)后,它会读取数据包并只打印接收到的数据包长度。很简单,对吧:)

UDP客户端:我使用hping如下所示:

  

hping3 192.168.1.2 --udp -p 9996 --flood -d 100

当我以每秒100个数据包发送udp数据包时,我没有发现任何UDP数据包丢失。但是当我泛洪udp数据包时(如上面的命令所示),我看到了重要的数据包丢失。

测试1: 当从UDP客户端泛洪26356个数据包时,我的示例程序只接收12127个数据包,剩余的14230个数据包被内核丢弃,如/ proc / net / snmp输出所示。

  

cat / proc / net / snmp | grep Udp:
  Udp:InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
  Udp:12372 0 14230 218 14230 0

对于Test1,丢包率为~53%。

我确认在客户端和服务器端使用“ethtool -S ethX”命令在硬件级别上没有太多损失,而在应用程序级别,我看到如上所述损失了53%。

因此减少数据包丢失我尝试了这些:
- 使用命令提高示例程序的优先级。
- 增加接收缓冲区大小(在系统级和进程级别)

将优先级提高到-20:

  

renice -20 2022
  2022(进程ID)旧优先级0,新优先级-20

将接收缓冲区大小增加到16MB:

  

处理级别:
  int sockbufsize = 16777216;
  setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char *)& sockbufsize,(int)sizeof(sockbufsize))
  内核级别:
  cat / proc / sys / net / core / rmem_default
  16777216
  cat / proc / sys / net / core / rmem_max
  16777216

完成这些更改后,执行Test2。

的Test2: 当1985076数据包从UDP客户端泛洪时,我的示例程序接收到1848791个数据包,剩余的136286数据包被内核丢弃,如/ proc / net / snmp输出所示。

  

cat / proc / net / snmp | grep Udp:
  Udp:InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
  Udp:1849064 0 136286 236 0 0

对于Test2,丢包率为6%。

数据包丢失显着减少。但我有以下问题:

  1. 可以进一步减少数据包丢失吗?!?我知道我在这里很贪心:)但我只是想知道是否有可能进一步减少数据包丢失。
  2. 与Test1不同,在Test2中,InErrors与RcvbufErrors不匹配,RcvbufErrors始终为零。有人可以解释一下背后的原因吗?!? InErrors和RcvbufErrors之间究竟有什么区别。我理解RcvbufErrors但不是InErrors。
  3. 感谢您的帮助和时间!!!

3 个答案:

答案 0 :(得分:5)

调整Linux内核的网络堆栈以减少数据包丢失有点涉及,因为从驱动程序到网络堆栈一直有批次调优选项。

我写了一个long blog post从上到下解释所有调整参数,并解释/proc/net/snmp中每个字段的含义,这样你就可以弄清楚这些错误发生的原因。看一看,我认为它可以帮助您将网络降至0。

答案 1 :(得分:1)

如果硬件级别没有下降,那么应该主要是内存问题,你应该能够调整内核配置参数以达到0分(显然你需要一个合理的平衡硬件来处理网络流量) recv'ing)。

我认为你错过了netdev_max_backlog,这对于传入的数据包很重要:

  

当接口接收到比内核更快的数据包时,在INPUT端排队的最大数据包数可以处理它们。

答案 2 :(得分:0)

InErrors由以下内容组成:

  • 损坏的数据包(不正确的标头或校验和)
  • 完整RCV缓冲区大小

所以我的猜测是你修复了缓冲区溢出问题(RcvbufErrors为0),剩下的是校验和错误的数据包。