3

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.

これはなぜですか?

実行中のキューはほとんどありません。

  1. ネットワーク カードのリング バッファ。
  2. nic からカーネル que へ
  3. ソケット 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);
 }
4

2 に答える 2

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 の 3 分の 1 だけがパケット データを保持していることを意味します。2/3 は sk_buff のオーバーヘッドです。

SO_RCVBUF :262142 の場合、

262142/3 = 87380 バイトがパケット データに使用できます。

87380/100 = 873 は、保持できるパケットの数です。

1000 - 873 = 1000 のうち 127 のドロップが予想されます。

私が得たのは170で、これは予想から遠く離れていません。

次の章/本は本当に役に立ちました。

[1] Christian Benvenuti による Linux ネットワークの内部構造の理解
パート III: 送信と受信

[2] Essential Linux Device Drivers by Sreekrishnan Venkateswaran
Chapter 15. ネットワーク インターフェイス カード

  • サリンダー
于 2013-04-15T04:11:51.320 に答える
-2

ロングショットですが、完全なコードを示していないため、ファイアウォールに関連している可能性があります. マルウェアの亜種の中には、ICMP パケット ストームを使用するものがあるため、ファイアウォール ソフトウェアが実行されている場合、そのソフトウェアが邪魔をしている可能性があります。

于 2013-03-29T16:14:53.847 に答える