我正在向C程序中的250个节点发送icmp echo。 套接字是这样创建的
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多滴。
我发送所有echo请求,然后使用recvfrom()来获取数据包。 很明显,回复包在socket的rcv缓冲区中累积, 但rcv缓冲区大到足以容纳3120个数据包。
接收主机上的数据包在ehtereal中正确显示。
当我设置:
sysctl -w net.core.rmem_max=1048576
and SO_RCVBUF to 2MB, the drops were 0.
为什么会这样?
行动中排队很少。
我猜net.core.rmem_max只会改变每个套接字rcv缓冲区。
正确方向的任何链接。
Platform Linux suse10/x86
- 添加更多
我禁用了所述无线接口并开始使用有线接口 以太网控制器:Broadcom Corporation NetXtreme BCM5705M_2千兆以太网(rev 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个 用默认值200的ethtool -G改变了rx,tx但是没有效果。
然后我更改了每个套接字rcv buffer max
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头)时,为什么在1000个数据包中发生了丢包。 即使在线数据包最大为100字节,262142也可以存储2600个数据包。
ethereal能够大部分时间获取数据包,ifconfig计数器显示没有丢弃,因此在nic驱动程序将数据包发送到内核之后就是这样。
ethereal也错过了几个小包,但这种情况发生的次数较少。
仅改变上述内容
sysctl -w net.core.rmem_max=1024000
下降96/1000 下降0/6000
sysctl -w net.core.rmem_max=2048000
sysctl -w net.core.rmem_max=512000
sysctl -w net.core.netdev_max_backlog=3000
sysctl -w net.core.rmem_max=256000
sysctl -w net.core.netdev_max_backlog=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);
}
答案 0 :(得分:2)
(从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]了解Linux网络内部由Christian Benvenuti撰写 第三部分:传输和接收
[2] Sreekrishnan Venkateswaran的基本Linux设备驱动程序 第15章网络接口卡
答案 1 :(得分:-2)
这是一个很长的镜头,但由于你没有显示完整的代码,它可能与防火墙有关。某些恶意软件变种使用ICMP数据包风暴,因此如果有任何正在运行,防火墙软件可能会受阻。