gpt4 book ai didi

linux socket recv buffer packet drops even for "pktcount * pktsize"< SO_RCVBUF

转载 作者:太空狗 更新时间:2023-10-29 11:22:38 25 4
gpt4 key购买 nike

我在 C 程序中向 250 个节点发送 icmp 回显。套接字是这样创建的

sfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);

我有 getsockopt SO_RCVBUF :262142 .i.e 262KB由于一个数据包需要 84 字节(包括 IP,100 字节在线),因此 rcv 缓冲区应该能够容纳262142/84 = 3120 个数据包

sysctl parameters  (defaults)
net.core.rmem_max = 131071
net.core.rmem_default = 113664

但是有 10 多滴。

我正在发送所有回显请求,然后使用 recvfrom() 获取数据包。很明显,回复数据包在套接字的 rcv 缓冲区中累积,但是 rcv 缓冲区足够容纳 3120 个数据包。

数据包在接收主机上正确显示在 ehtereal 中。

当我设置时:

sysctl -w net.core.rmem_max=1048576
and SO_RCVBUF to 2MB, the drops were 0.

为什么会这样?

运行中的队列很少。

  1. 网卡环形缓冲区。
  2. nic 到内核问题
  3. 每个套接字接收缓冲区

我猜 net.core.rmem_max 只会根据套接字 rcv 缓冲区发生变化。

任何正确方向的链接。

Platform Linux suse10/x86

NIC : Intel Corporation PRO/Wireless 2200BG

-- 添加更多

我禁用了上述无线接口(interface)并开始使用有线接口(interface)以太网 Controller :Broadcom Corporation NetXtreme BCM5705M_2 千兆以太网(版本 03)情况发生了重大变化。

net.core.netdev_budget = 300
net.core.netdev_max_backlog = 1000
net.core.rmem_max = 131071
net.core.wmem_max = 131071

getsockopt SO_RCVBUF :262142
getsockopt SO_SNDBUF :262142
# ethtool -g eth1
Current hardware settings:
RX: 200
TX: 200
#

eth1 txqueuelen:1000

现在每 250 个数据包有 0 个数据包,大约每 1000 个数据包有 170 个数据包使用 ethtool -G 从默认值 200 更改了 rx,tx,但这没有效果。

然后我改变了每个套接字接收缓冲区的最大值

sysctl -w net.core.rmem_max=1024000

这允许每 6000 滴 0每 7000 滴 500 滴

进一步增加 per-socket-rcv-buffer-max

sysctl -w net.core.rmem_max=2048000

每 7000 包 0 滴

有线网络给出了更加一致和协作的结果。

但问题仍然悬而未决当 262142 字节的缓冲区可以容纳 3000 个大小为 84 的数据包(带有 IP header )时,为什么丢弃发生在 1000 个数据包时。即使在线数据包最大为 100 字节,262142 也可以容纳 2600 个数据包。

ethereal 大部分时间都能够获取数据包,而 ifconfig 计数器显示没有丢失,所以它是在 nic 驱动程序将数据包提供给内核之后发生的事情。

ethereal 也错过了几个数据包,但发生的次数较少。

只改变上面这些

sysctl -w net.core.rmem_max=1024000

掉落 96/1000下降 0/6000

掉落 500/7000

sysctl -w net.core.rmem_max=2048000

下降 0/7000

sysctl -w net.core.rmem_max=512000
sysctl -w net.core.netdev_max_backlog=3000

掉落 0/3000

sysctl -w net.core.rmem_max=256000
sysctl -w net.core.netdev_max_backlog=3000

掉落 1400/3000

hold = 2 * 1024 * 1024;
setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));

for(;;)
...
if(recvfrom(sfd,(char *)packet, packlen, 0, (struct sockaddr *)&from, &fromlen)) < 0) {
rcvcount++;
process_packet(packet,packlen);
}

最佳答案

(转载我在 nntp:comp.os.linux.networking 的回答)

以下代码回答了我的问题。

http://lxr.linux.no/#linux+v3.8.7/net/core/sock.c#L689

708set_rcvbuf:
709 sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
710 /*
711 * We double it on the way in to account for
712 * "struct sk_buff" etc. overhead. Applications
713 * assume that the SO_RCVBUF setting they make will
714 * allow that much actual data to be received on that
715 * socket.
716 *
717 * Applications are unaware that "struct sk_buff" and
718 * other overheads allocate from the receive buffer
719 * during socket buffer allocation.
720 *
721 * And after considering the possible alternatives,
722 * returning the value we actually used in getsockopt
723 * is the most desirable behavior.
724 */
725 sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF);
726 break;

由于我的数据包低于 100 字节数据,因此 sk_buff 开销会按比例相当高。目测sk_buff,对于32位系统,sk_buff的大小似乎在200字节左右。

对于 100 字节的在线数据包,这意味着只有三分之一的 rcvbuf 用于保存数据包。 2/3 是 sk_buff 开销。

所以对于 SO_RCVBUF :262142,

262142/3 = 87380 字节可用于数据包数据。

87380/100 = 873 是其中可以容纳的数据包数。

1000 - 873 = 预计 1000 人中有 127 人掉落。

我得到的是170,和预期相差不远。

后面的章节/书籍真的很有帮助。

[1] Christian Benvenuti 理解 Linux 网络内部结构
第三部分:传输和接收

[2] Sreekrishnan Venkateswaran 的《基本 Linux 设备驱动程序》
第 15 章网络接口(interface)卡

  • 苏林德

关于linux socket recv buffer packet drops even for "pktcount * pktsize"< SO_RCVBUF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15706949/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com