アプリケーションデータがNICから出力されるまでの過程

Application
スポンサーリンク

アプリケーションデータがどのようにパケットとしてサーバやPCから出ていくのか、その過程を正確に理解する必要がありました。その過程でに身に着けた知識を1枚の図に落とし込みました。

図1:アプリケーションのデータがNICから出ていくまでの過程

過程は以下の通りです。
①アプリケーションデータをソケットに渡す
②カーネル(OS)によって分割、TCP,IP,Ethernetヘッダを付与
③NICドライバを通過
④NICを通過
①アプリケーションデータをソケットに渡す

ネットワークエンジニアやサーバエンジニアといったインフアエンジニアからすると
ソケットという言葉は聞いたことがあっても何か知らない人が多いと思います。
以下の記事をご覧ください。

アプリケーションからすると、とりあえずデータをソケットに渡しておけば
後は勝手にデータを必要な相手に届けてくれるという利点があります。

②カーネル(OS)によって分割、TCP,IP,Ethernetヘッダが付与

ソケットに渡させたデータはMSSの値を元に分割されます。
MSSというのはMaximum Segment Sizeの略で、MTU(maximum Transmit Unit)から算出されます。
MSS = MTU -20byte(IPヘッダ)-20byte(TCPヘッダ)

MTUサイズはデフォルトで1500のため、基本的には上の計算式に従い1460byteとなります。
windowsでは以下のコマンドをコマンドプロンプトで入力すると、NICのMTUサイズがわかります。
コマンド:netsh interface ipv4 show interface

図2:netsh interface ipv4 show interfaceの実行結果

そのため、ソケットから引き渡されたデータが14600byteの場合、14600 ÷ 1460 = 10個のデータに分割されます。この時、各データに対してTCPヘッダが付与されます。
MSSでデータが分割されTCPでカプセル化されることをTCPセグメンテーションと呼びます。

さらに、ルーティングをするためにIPヘッダ、L2レイヤの通信をするためEthernetヘッダが付与されます。この時、FCSはまだ付与されていません。

③NICドライバを通過

その後はNICドライバを経由してNICにパケットが渡されます。
パケット分析ツールで名高いWiresharkはこのNICドライバのパケットを盗み見することでパケットキャプチャを実現しています。
そのため、OSが行っているTCPセグメンテーション・再構築を肩代わり(オフロード)する機能である一括送信オフロード(大量送信オフロード)がNICドライバで有効の場合は以下の記事にある通り、1514byte以上のパケットが観測されます。1518byte(フレームの最大長)ではなく1514byteなのは、FCS(4byte)が付与されていないためです。

図3:NICドライバのプロパティ(大量送信オフロード)

ちなみに過去の経験上、NICドライバが古い場合でCPUの性能が良い場合は、OSで処理した方が処理が速くなるため一括送信オフロード機能を無効化した場合に通信速度が向上することがあります。

④NICを通過

NICではTCPチェックサムやUDPチェックサムといったパケットに欠損がないか確認する機能を実施します。そのため、TCPチェックサムやUDPチェックサムのパケットをwireshrakで取得したい場合はこの機能を無効化する必要があります。
以下のようにNICドライバの画面で無効化することが可能です。

図4:NICドライバのプロパティ(TCP/UDPチェックサムのオフロード)

※図では有効化されています

チェックサムについては以下の日経クロステックの記事がざっくりと理解するにはいいと思います。

送信パケットのTCP/UDPチェックサムが行われた後にパケットがNICから送信され、隣接機器へ伝搬されていきます。

基本的にその後は、IPフラグメンテーションが発生しない限りはパケットは分割されずに通信されていきます。Microsoft製品ですとPMTUDがデフォルトでは有効化されています。
通信経路上の最小MTUサイズを元にMSSが定められるためIPフラグメンテーションが発生することはまずないでしょう。

PMTUDについては
SEの道標さんの記事が良いと思いますのでリンクを張っておきます。

ちなみに、通信先までの最小MTUサイズを計測したい場合は送信元にて以下のコマンドを打てば確認できます。コマンド例では最小MTUサイズが1500の場合のコマンドです。
コマンド例:ping -f -l 1472 宛先IPアドレス
※-f:df-bit(dont’t fragment bitを付与)
※-l:データの長さを指定
※IPヘッダ(20byte) + ICMP(8byte) = 28byteとなるため、1500-28=1472(byte)となります。

また、MTUサイズは変更することが可能です
コマンド:netsh interface ipv4 set interface Idx番号 変更したいMTUサイズ

図5:netsh interface ipv4 set interface Idx番号 変更したいMTUサイズの実行結果

参考

ブラックホール問題に対するWindows側での対応方法(ブラックホールを検知する)やMTUサイズの変更などについては、マイクロソフトのドキュメントにまとめられています。
参考程度ですがリンクを張っておきます。

※ただし、WANリンクにてMTUが576より小さい場合の推奨設定のためほぼ使うことはないでしょう…。

コメント