2025/11/18 03:31 The Life of a Packet in the Linux kernel: From write() to recv()

やあ、ロボ子。今日のITニュースは、Linuxカーネルにおけるネットワークパケットのライフサイクルじゃ。`write()`から`recv()`までの一生を追う冒険に出発だぞ!

博士、よろしくお願いします!パケットの一生、興味深いです。

`write()`システムコールでアプリケーションからカーネルにデータが渡されるのが始まりじゃ。TCPは大きなバッファをセグメントに分割するんじゃったな。

はい、各セグメントにはシーケンス番号が割り当てられ、受信側での順序保証に使われるんですよね。

その通り!そしてカーネルは宛先IPアドレスに基づいて最適なルートを選択する。ローカルネットワークか、ゲートウェイか…。

宛先IPアドレスに対応するMACアドレスをARPキャッシュから検索するんですね。見つからない場合はARPリクエストをブロードキャストしてMACアドレスを取得すると。

そうじゃ。そしてパケットはqdisc(キューイングディシプリン)に入る。ここでは、バーストの平滑化や帯域幅の公平な共有などが行われるんじゃ。

qdisc、奥が深いですね。fq_codelやfqを選択してバッファブロートを防ぐこともできるんですね。

そうじゃぞ。そして、カーネルのネットワークドライバがパケットをNICに渡し、NICがDMAを使ってデータを読み取り、ネットワーク信号に変換して送信!

送信されたイーサネットフレームは、スイッチやルータを経由して宛先へ向かうのですね。ルータはTTLをデクリメントするんでしたね。

その通り。受信側では、NICがNAPIを使って効率的にフレームを処理する。割り込みとポーリングの組み合わせじゃ。

NAPIは割り込みを一度だけ発生させ、ポーリングに切り替えてパケットをまとめて処理するんですね。効率的です。

そして、カーネルはIPヘッダを検証し、宛先IPアドレスが自身のアドレスと一致するかを確認。一致すれば上位層へ、そうでなければ転送じゃ。

ファイアウォールが設定されている場合は、PREROUTINGやINPUTなどのフックでパケットをフィルタリングするんですね。

最後に、TCPスタックがセグメントを順序通りに並べ替え、欠落がないか確認し、ACKを送信。データが準備できると、`recv()`で待機しているプロセスを起動するんじゃ。

なるほど。`write()`から`recv()`まで、パケットは色々な場所を通って、たくさんの処理を受けているんですね。

そうじゃ。トラブルシューティングのヒントもいくつかあったな。`ip neigh`でFAILEDが表示される場合はL2の到達性を確認するとか。

小さなpingは通るけど大きな転送が止まる場合は、MTUの不一致を疑う、と。

非対称ルーティングとrp_filter=1の組み合わせは要注意じゃぞ。リターントラフィックがドロップされる可能性がある。

高負荷時に新しい接続がリセットされる場合は、アプリケーションのバックログとnet.core.somaxconnを増やすんですね。

今日はパケット君の一生を学んだわけじゃが、ロボ子、パケット君は最後にどうなるか知ってるか?

えっと…、アプリケーションにデータが渡されて、役目を終える…、ですか?

ブー! 正解は…、deleteされる!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。