大发送套接字缓冲区大小导致UDP数据包丢失

时间:2021-06-17 03:15:45

标签: linux sockets tcp udp kernel

操作系统:Centos7.6.10 内核:3.10.0-957.el7.x86_64 我使用netperf测试UDP。当我设置发送套接字大小为8129920;接收套接字大小为212992时,UDP数据包丢失了很多。只有大数据包才会出现在这个问题中。two pc netperf test我尝试tcpdump,我发现发送的 UDP 数据不完整,总是缺少一个 IP 帧,所以对方无法合并这些帧。tcpdump result 我在发送端 PC 上使用 dropwatch 查找内核问题,然后我找到了这些

1581 drops at brk_limit+369bd232 (0xffffffffc0437232)
1 drops at skb_queue_purge+18 (0xffffffff88a235d8)
1632 drops at brk_limit+369bd232 (0xffffffffc0437232)
1682 drops at brk_limit+369bd232 (0xffffffffc0437232)
1732 drops at brk_limit+369bd232 (0xffffffffc0437232)
1 drops at brk_limit+369bd232 (0xffffffffc0437232)
1783 drops at brk_limit+369bd232 (0xffffffffc0437232)
1834 drops at brk_limit+369bd232 (0xffffffffc0437232)
1882 drops at brk_limit+369bd232 (0xffffffffc0437232)
2 drops at brk_limit+369bd232 (0xffffffffc0437232)
1934 drops at brk_limit+369bd232 (0xffffffffc0437232)
1984 drops at brk_limit+369bd232 (0xffffffffc0437232)
2 drops at brk_limit+369bd232 (0xffffffffc0437232)
2036 drops at brk_limit+369bd232 (0xffffffffc0437232)
2087 drops at brk_limit+369bd232 (0xffffffffc0437232)
2135 drops at brk_limit+369bd232 (0xffffffffc0437232)
4 drops at brk_limit+369bd232 (0xffffffffc0437232)
2187 drops at brk_limit+369bd232 (0xffffffffc0437232)
2237 drops at brk_limit+369bd232 (0xffffffffc0437232)
2289 drops at brk_limit+369bd232 (0xffffffffc0437232)
2338 drops at brk_limit+369bd232 (0xffffffffc0437232)
2 drops at brk_limit+369bd232 (0xffffffffc0437232)
2390 drops at brk_limit+369bd232 (0xffffffffc0437232)
2439 drops at brk_limit+369bd232 (0xffffffffc0437232)
3 drops at brk_limit+369bd232 (0xffffffffc0437232)
2492 drops at brk_limit+369bd232 (0xffffffffc0437232)
2544 drops at brk_limit+369bd232 (0xffffffffc0437232)
2595 drops at brk_limit+369bd232 (0xffffffffc0437232)
2641 drops at brk_limit+369bd232 (0xffffffffc0437232)
2694 drops at brk_limit+369bd232 (0xffffffffc0437232)
2745 drops at brk_limit+369bd232 (0xffffffffc0437232)
2 drops at udp4_lib_rcv+b9 (0xffffffff88ab5139)
2795 drops at brk_limit+369bd232 (0xffffffffc0437232)
2846 drops at brk_limit+369bd232 (0xffffffffc0437232)
2898 drops at brk_limit+369bd232 (0xffffffffc0437232)
2949 drops at brk_limit+369bd232 (0xffffffffc0437232)
3000 drops at brk_limit+369bd232 (0xffffffffc0437232)
251 drops at __brk_limit+369bd232 (0xffffffffc0437232)
6 drops at icmp_rcv+125 (0xffffffff88aba7a5)**

the network card info 我无法理解这个现象。希望你能帮我解决这个问题,谢谢!

2 个答案:

答案 0 :(得分:2)

这是预期的行为。假设您发送一个 65,500 字节的数据报,并且您的最大数据包大小为 1,500 字节。这意味着每个数据报需要 44 个数据包。现在假设您的丢包率是 1%。这意味着您的数据报丢失率为 35%。哎哟。

不要使用这么大的数据报。或者不要使用UDP。

答案 1 :(得分:0)

Linux 提供了一些栈内流量控制,设置一个非常大的 UDP 发送套接字缓冲区可以短路它。堆栈内流量控制取决于出口接口具有足够大的传输队列 (txqueuelen) 以容纳比 UDP 发送套接字缓冲区更多的数据报。或者换句话说,UDP 发送套接字缓冲区不能容纳超过可以排队到接口传输队列的缓冲区。

否则,当发送 UDP 数据报的速度超过它们离开接口的速度时,而不是填充发送套接字缓冲区,从而使套接字不可写,直到某些数据报离开系统,接口传输队列溢出,数据包开始出站掉线。

您可能会在 netstat -s 输出的 Udp: 部分看到相关统计信息。

您“应该”做的不是让发送套接字缓冲区变得如此大。对于 UDP,它需要足够大,以便最大限度地从接口中获取数据报。 10 次中有 99 次(原文如此)默认应该没问题。您可能需要增加接收器上的接收套接字缓冲区的大小。

此外,除非您的应用程序发送 65507 字节的消息,否则您应该添加一个特定于测试的 -m 选项来告诉 netperf 发送的字节数与您的应用程序通常发送的字节数一样多。

就目前而言,您将发送套接字缓冲区设置为 8129920 字节意味着它可以容纳 124、65507 字节的 UDP 数据报。当这些被分割成 44 个 IP 数据报片段时,正如大卫指出的那样,这将类似于 5456 个数据包。默认接口传输队列长度为 1000 个数据包...