[スイッチ] Linuxのネットワーク - プロセスのデータパケットを受信します

、ターンオリジナル:  https://segmentfault.com/a/1190000008836467

-------------------------------------------------- -------------------------------------------------- -------------

この記事では、Linuxシステムでは、パケットがカードのプロセスの手から渡される方法をステップバイステップで説明します。

英語は問題ではない場合、私は強く、より詳細な導入され、2件の記事で次の参照を読んでお勧めします。

唯一のイーサネットNICの物理的なこの記事で説明するには、仮想デバイス、および例として、UDPパケットを受信するためのプロセスを必要としません。

あなたのカーネルが、このバージョンではない場合、カーネル3.13.0からの関数呼び出し関係に記載されているこの例では、関数名とそれに関連するパスが異なる場合がありますが、その背後にある原理は同じ(またはわずかに異なる)でなければなりません

メモリカード

NICは仕事にドライバが必要ですが、ドライバがカーネルモジュールにロードされ、ネットワークアダプタカードとカーネルモジュールを担当し、負荷時の駆動には、独自のネットワークモジュール、対応するネットワークカードがパケットを受信し、ネットワークモジュールに登録されます適切なドライバがデータを処理呼び出します。

次の図に示すデータパケット(パケット)をどのようにメモリに入るために、コアネットワークモジュール起動処理:

                   +-----+
                   |     |                            Memroy
+--------+   1     |     |  2  DMA     +--------+--------+--------+--------+
| Packet |-------->| NIC |------------>| Packet | Packet | Packet | ...... | +--------+ | | +--------+--------+--------+--------+ | |<--------+ +-----+ | | +---------------+ | | 3 | Raise IRQ | Disable IRQ | 5 | | | ↓ | +-----+ +------------+ | | Run IRQ handler | | | CPU |------------------>| NIC Driver | | | 4 | | +-----+ +------------+ | 6 | Raise soft IRQ | ↓ 
  • 1:物理NICパケットは、外部からネットワークに入ります。宛先アドレスがカードではなく、カードが無差別モードになっていない場合、パケットは、カードを破棄されます。
  • 2:NICを介してデータパケットDMA指定されたメモリアドレスモードに書き込まれ、アドレスは、NICドライバによって割り当てられ、初期化されます。注:古いカードは、DMAをサポートしていないかもしれませんが、新しいカードは、一般的にサポートしています。
  • 3:ハードウェア割り込み(IRQ)を介して、NIC通知CPU、データにそれを伝えます
  • 4:CPU割り込みテーブルによれば、登録された割り込み関数を呼び出し、割り込み関数は、対応する関数でドライバ(NICドライバ)に転送されます
  • 5:回避のCPUにはない、ドライバーがすでに効率を向上させることができるので、CPUに通知していない、それを直接次のデータパケットのメモリ書き込みを受け取るためにカードを教えて、メモリ内のデータがあることを知っていることを示す、ネットワークカードのドライバの割り込み禁止停止が中断されます。
  • 6:ソフト割り込みを開始します。このステップの後、ハードウェア割り込みハンドラの端が返さ。実行中のハード割り込みハンドラを中断することはできませんので、それはあまりにも長い間行われた場合、その応答は、他のハードウェア割り込み、ソフトウェア割り込み時間のかかるハンドラ部分ハードウェア割り込みをすることができ導入上のカーネルにCPUを引き起こすことができませんゆっくりとプロセスへの内部のソフト割り込みハンドラを移動します。

コア・ネットワークモジュール

次のようにネットワークカーネルモジュールソフト割り込みハンドラ、その後の手順があるソフト割り込みトリガ

                                                     +-----+
                                             17      |     |
                                        +----------->| NIC |
                                        |            |     |
                                        |Enable IRQ +-----+ | | +------------+ Memroy | | Read +--------+--------+--------+--------+ +--------------->| NIC Driver |<--------------------- | Packet | Packet | Packet | ...... | | | | 9 +--------+--------+--------+--------+ | +------------+ | | | skb Poll | 8 Raise softIRQ | 6 +-----------------+ | | 10 | | ↓ ↓ +---------------+ Call +-----------+ +------------------+ +--------------------+ 12 +---------------------+ | net_rx_action |<-------| ksoftirqd | | napi_gro_receive |------->| enqueue_to_backlog |----->| CPU input_pkt_queue | +---------------+ 7 +-----------+ +------------------+ 11 +--------------------+ +---------------------+ | | 13 14 | + - - - - - - - - - - - - - - - - - - - - - - + ↓ ↓ +--------------------------+ 15 +------------------------+ | __netif_receive_skb_core |----------->| packet taps(AF_PACKET) | +--------------------------+ +------------------------+ | | 16 ↓ +-----------------+ | protocol layers | +-----------------+ 
  • 7:それはソフト割り込みを受信した場合、それはNICドライバモジュール上記のステップ6に対応する機能を割り込み処理に適切なソフトウェアを呼び出す、ソフトハンドリング割り込みを担当ksoftirqdプロセスカーネルはソフト割り込みをスローされ、 ksoftirqdは、ネットワーク機能モジュールのnet_rx_actionを呼び出します
  • 8:net_rx_actionは、データ・パケットを一つずつ処理するポーリング機能にNICドライバを呼び出します
  • 9:プール機能では、ドライブが知っている1つのパケットメモリに書き込まれたカード、データパケットのメモリ形式のみドライバを読み込みます
  • 10:ドライバコアネットワークSKBフォーマットを識別するためのメモリモジュールにパケット、及び、関数napi_gro_receiveを呼び出し
  • 11:napi_gro_receiveハンドルGROでの関連コンテンツは、あなたが唯一のプロトコルスタックを呼び出す必要があるので、マージにデータパケットをマージすることができるようになります。次に開くかどうかを判断RPSを、開いた場合、enqueue_to_backlog呼び出します。
  • 12:フルinput_pkt_queue場合、パケットはドロップされenqueue_to_backlog機能、パケットはCPUのsoftnet_data構造、そして次に戻るinput_pkt_queue配置される、キューのサイズはnet.core.netdev_max_backlogすることができますコンフィギュレーション
  • 13:CPUコンテキストで独自のソフト割り込みネットワーク・データ処理input_pkt_queueが続く(コール__netif_receive_skb_core)
  • 14:あなたが開いていない場合はRPSを、napi_gro_receive直接呼び出し__netif_receive_skb_core
  • 15:AF_PACKET(私たちは多くの場合、元のソケットと言う、である)ソケットのタイプが参照可能な場合、データのコピー、それことです。tcpdumpのパケットキャプチャはここでキャッチされます。
  • 16:プロセスへの関数呼び出しスタック、プロトコル・スタック・パケットを対応します。
  • 17:次回のカードを、データを受信したCPUをお知らせいたしますので、その割り込みすべてのパケットが完成するメモリで処理された後(つまり、ポーリング機能の実行が完了すると)、ハード対応のネットワークカード
enqueue_to_backlog機能は、デバイスがパケット機能を送信するときに、それが呼ばれnetif_rx netif_rx関数と呼ばれ、LOれます

スタック

IP層

UDPパケットので、最初のステップは、IP層に入り、その後、レベルの機能に下ります:

          |
          |
          ↓         promiscuous mode &&
      +--------+    PACKET_OTHERHOST (set by driver)   +-----------------+
      | ip_rcv |-------------------------------------->| drop this packet|
      +--------+                                       +-----------------+
          | | ↓ +---------------------+ | NF_INET_PRE_ROUTING | +---------------------+ | | ↓ +---------+ | | enabled ip forword +------------+ +----------------+ | routing |-------------------->| ip_forward |------->| NF_INET_FORWARD | | | +------------+ +----------------+ +---------+ | | | | destination IP is local ↓ ↓ +---------------+ +------------------+ | dst_output_sk | | ip_local_deliver | +---------------+ +------------------+ | | ↓ +------------------+ | NF_INET_LOCAL_IN | +------------------+ | | ↓ +-----------+ | UDP layer | +-----------+
  • ip_rcv:ip_rcv入力機能を呼び出し、その後、その機能に、まず最初にジャンクデータにある、(代わりに現在のカードの宛先MACアドレスが、カードがセットされている無差別モードがで受信された)IPモジュールの関数であり、直接失われましたNF_INET_PRE_ROUTING機能に登録
  • NF_INET_PRE_ROUTING:netfilterのフックをプロトコルスタック上で、いくつかのパケットは、パケットが廃棄されていない場合は、我々がダウンしていきます、変更またはパケットを破棄するように、iptablesのハンドラを介して注入してもよいです
  • ルーティング:ルーティング、それはローカルIP送信先IPではない、とフォワード機能IPなった場合には、no ipフォワード機能に、そのパケットはドロップされません、それが機能ip_forwardを入力した場合
  • ip_forward:最初のnetfilterを呼び出しますip_forwardは、データパケットが破棄されていない場合、それは次の関数呼び出しdst_output_skしていきます、NF_INET_FORWARD相関関数を登録しました
  • dst_output_sk:この関数は次で送信されるデータパケットの流れの後半を説明するように、データパケットの適切な機能は、IP層に送信されたコール。
  • ip_local_deliver:IPは、上記のルーティング先がローカルIPであることを時間ならば、それが渡された場合、パケットはUDP層まで送信されます、関数が最初にコールNF_INET_LOCAL_INフックに関連され、関数を呼び出します

UDP層

          |
          |
          ↓
      +---------+            +-----------------------+
      | udp_rcv |----------->| __udp4_lib_lookup_skb |
      +---------+            +-----------------------+
          | | ↓ +--------------------+ +-----------+ | sock_queue_rcv_skb |----->| sk_filter | +--------------------+ +-----------+ | | ↓ +------------------+ | __skb_queue_tail | +------------------+ | | ↓ +---------------+ | sk_data_ready | +---------------+ 
  • udp_rcv:udp_rcvエントリ機能は、コールが重要__udp4_lib_lookup_skbで必要なチェックを行うには主に、他の関数を呼び出しますUDPモジュールの機能があり、場合、送信先IPソケットポートに対応する機能を見つけてます対応ソケットが見つからない場合、そのパケットは続けるそうでない場合、削除されます
  • sock_queue_rcv_skb:主に二つのことをやった、1ソケットのを確認し、バッファがいっぱい場合は、そのパケットを破棄し、そして、フルでないsk_filter呼び出す現在のソケットならば、このパッケージは、パッケージの条件を満たすことであるかどうかを確認することです受信します設定されたフィルタ、及び条件が満たされない場合、パケットは、パケットは(Linuxでは、各ソケットは、内部のtcpdumpと同じ定義することができる廃棄されるフィルタの条件が満たされず、パケットは破棄されます)
  • __skb_queue_tail:受信キュー内のパケットのソケット端
  • sk_data_ready:通知ソケットパケットレディ
呼び出しsk_data_ready後、パケット処理はソフト割り込みのコンテキスト内のすべての上記の機能の実行中に、読むためのアプリケーションプログラムを待って、完成されています。

ソケット

アプリケーション層データを受信するための2つの方法があるソケットは、通知の受信は、のrecvfromは目覚め、その後データ受信キュー読み取られる場合と、一方はこの場合には、のrecvfrom機能ブロックにデータを待っている、別の通知を受けたときに種のepollによって、または対応するリスニングソケットを選択し、その後、関数呼び出しは、受信したデータキューを読み取るためのrecvfrom。これらの両方は、通常、対応するデータ・パケットを受信することができます。

結論

、プロセスパケットは、私たちがデータパケットを監視し、変更することができますどのような分野を見つけ出す助けに助けを受け、パケットがどのような状況の下で落下することができる理解し、私たちは、ネットワークの問題に対処するためのいくつかのリファレンスを提供し、我々は適切なnetfilterのフックを理解しますiptablesのの使用を理解する位置には、確かに役立ちますが、また、私たちはより良いLinuxで、その後の仮想ネットワークデバイスを理解するのに役立ちます。

次のいくつかの記事では、Linuxで仮想ネットワークデバイスとiptablesをご紹介します。

参照

Linuxのネットワークスタックを監視およびチューニング:データ受信
のLinuxネットワーキングスタックの監視およびチューニングイラストガイド:データ受信
NAPIを

おすすめ

転載: www.cnblogs.com/oxspirt/p/12041537.html