C プログラムで 250 ノードに icmp echo を送信しています。ソケットはこのように作成されます
sfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
私は getsockopt SO_RCVBUF :262142 を持っています。つまり、1 つのパケットに 84 バイト (IP を含む、ワイヤ上の 100 バイト) が必要なため、262KB です。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.
これはなぜですか?
実行中のキューはほとんどありません。
- ネットワーク カードのリング バッファ。
- nic からカーネル que へ
- ソケット rcv バッファごと
net.core.rmem_max は、ソケットの rcv バッファーごとにのみ変更されると思います。
正しい方向へのリンク。
Platform Linux suse10/x86
NIC : インテル コーポレーション PRO/Wireless 2200BG
-- さらに追加
上記のワイヤレス インターフェイスを無効にして、有線インターフェイスのイーサネット コントローラーを使い始めました。
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 バイトのバッファーがサイズ 84 (IP ヘッダーを含む) の 3000 パケットを保持できる場合、なぜ 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);
}