TL

GRO/GSO/TSO:セグメンテーションオフロードの原理

10Gbps級でCPUがパケット処理に飽和する理由と、分割をNICへ委ね受信を束ねて処理回数を減らすオフロードの原理が分かる。tcpdumpで巨大パケットが見える謎まで内部から押さえられる。

応用TSOGSOGROオフロードNIC最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.1パケットごとにヘッダ生成・チェックサム・スタック通過のCPUコストがかかるため、高帯域ではパケット数そのものが律速になる。オフロードはこの「処理回数」を減らす最適化で、データ量ではなくパケット数にコストが比例する事実が出発点。
  • 2.送信側はTSO/GSOで一つの巨大セグメント(最大64KB)をスタックに通し、MSSへの分割を最後にNIC(TSO)または直前のソフトウェア(GSO)へ委ねる。受信側はGRO/LROで同一フローの連続セグメントを一つの巨大バッファに束ねてからスタックへ上げる。
  • 3.オフロードはMTU/MSSの実体を変えず、ホスト内部の処理単位だけを大きくする。だからtcpdumpはMTU超の巨大パケットを表示し、回線上の実フレームとはズレる。計測時はこの「見かけ」を理解しないと誤読する。

なぜパケット数そのものがコストになるのか

TCP/IPの送受信コストは、転送する バイト数 よりも パケット数 に強く比例します。1パケットを処理するたびに、IP/TCPヘッダの生成や検査、チェックサム計算、ルーティング・ネットフィルタの通過、ソケットバッファとの受け渡し、そしてプロトコルスタックを一段ずつ降りる/昇る関数呼び出しが発生するからです。これらは概ね「1パケットあたり固定費」で、ペイロードが小さくても大きくても大差ありません。

ここでイーサネットのMTU(標準1500バイト)が効いてきます。MTUとMSS(TCPが1セグメントに載せる最大データ量)の関係は MTU(最大転送単位)とは の通りで、標準MTUなら1セグメントは約1460バイトです。10Gbpsを標準MTUで埋めると毎秒80万パケットを超え、固定費がCPUを食い潰します。データ量ではなくパケット数が律速 になる——これがオフロードの出発点です。

ジャンボフレームとオフロードは同じ問題への別解

パケット数を減らす素直な手はMTUを9000バイト等へ拡大する ジャンボフレーム です。1パケットあたりのペイロードが約6倍になり、同じ帯域でパケット数が約1/6に減ります。ただしジャンボフレームは経路上の全機器が対応しないとPMTUDやフラグメントの問題を招きます(IPフラグメンテーションとPMTUD を参照)。オフロードは回線のMTUを変えずに ホスト内部の処理単位だけ を大きくする解で、対向や経路に何も要求しないのが利点です。

送信オフロード:分割を最後に委ねる(TSO/GSO)

送信側の発想は「スタックの中ではできるだけ大きな塊のまま運び、MSSへの分割は最後の最後に行う」ことです。アプリが64KBを send() したとき、素朴な実装はスタックの上流で1460バイトごとに約45個のセグメントへ刻み、その45個それぞれにヘッダ生成・チェックサム・スタック通過のコストを払います。

TSO(TCP Segmentation Offload) は、この分割を NICのハードウェア へ委ねます。スタックは64KBの巨大セグメントを1つの単位として扱い、テンプレートとなるTCP/IPヘッダを1つ付けてNICへ渡すだけ。NICが送出直前にそれをMSSごとの実フレームへ刻み、各フレームのシーケンス番号・チェックサム・長さフィールドを埋めます。スタックを通る単位が1/45になるので、ホスト側の固定費が劇的に減ります。

TSOなし: アプリ64KB → スタックが45個に分割 → 45回ぶんのヘッダ生成/checksum/スタック通過 → NIC
TSOあり: アプリ64KB → スタックは1個のまま処理 → NICが送出時に45個へ分割

GSO(Generic Segmentation Offload) は同じ発想をソフトウェアで実現する一般化です。NICがTSO非対応でも、あるいはトンネル等で複雑な場合でも、分割をスタックの できるだけ下流(デバイスへ渡す直前) まで遅らせます。NICがハードウェア分割できるならそこで委ね、できなければ直前にソフトウェアで分割する。GSOは「分割の遅延」という原理だけを取り出した枠組みで、TSOはそのハードウェア実装と捉えると整理できます。チェックサム計算自体をNICへ任せる チェックサムオフロード も併用され、send() から recv() までのデータ移動を最小化する ソケットバッファとゼロコピー送受信 と組み合わせて送信パスのCPU効率を上げます。

機構分割を行う主体対象プロトコル前提
TSONICハードウェアTCPのみNICがTSO対応
GSOソフトウェア(送出直前)TCP/UDP等汎用NIC非対応でも可
UFO(廃止)NIC/ソフトUDP断片化現在は非推奨

受信オフロード:連続セグメントを束ねる(GRO/LRO)

受信側は逆向きの最適化です。回線からはMSSサイズの小さなフレームが大量に届きますが、それを1個ずつスタックへ上げると、やはりパケット数ぶんの固定費がかかります。そこで 受信側で連続するセグメントを束ねてから スタックへ渡します。

GRO(Generic Receive Offload) は、同一フロー(同じ5タプル)に属し、シーケンス番号が連続する複数のセグメントを、ソフトウェアで1つの巨大なバッファ(最大64KB相当)に マージ します。スタックはその巨大セグメントを1単位として処理するので、IP/TCP処理やソケットへの受け渡しが1回で済みます。受信処理の文脈は カーネルのパケット受信経路:NAPIと割り込み緩和 の通りで、GROはNAPIの poll() がリングから刈り取った直後、まだソフトIRQの中にいる段階で束ねが行われます。1回のポーリングでまとめて取り出したパケット群を、フローごとに合体させるわけです。

マージできるのは厳密な条件を満たすときだけです。同一フローで、シーケンスが隙間なく連続し、TCPフラグやオプション(タイムスタンプ等)が整合し、合体しても64KBを超えない——この条件を外れると、GROはそこで束ねを打ち切って現在の塊をスタックへ吐き出します(フラッシュ)。だから順序が乱れたり別フローが混ざると、束ねは小さい単位で切れます。

GRO(可逆)と LRO(不可逆)の決定的な違い

LRO(Large Receive Offload) はNICハードウェアが行う先行世代の束ねです。GROより速い反面、束ねの基準が粗く 元の境界やヘッダ情報を捨てて しまうため、合体したものを正確に元のセグメント列へ戻せません。ここが致命的なのは フォワーディング のときです。ルータやブリッジとして受信パケットを別インタフェースへ転送する場合、対向のMTUに合わせて再分割する必要がありますが、LROで情報が失われていると正しく再構成できません。GROは元のセグメント境界を復元できる 可逆的 な設計なので、転送やブリッジでも安全に使えます。ルータ/ブリッジ用途やKVMのホストではLROを切りGROを使うのが定石です。

計測への影響:見かけと実体がズレる

オフロードを理解していないと、計測が必ず誤読を招きます。最大の罠は tcpdump(libpcap)が見るのはオフロード処理の「ホスト内部」側 だという点です。tcpdumpはスタックの入口(送信ではデバイスへ渡す直前、受信ではGRO束ね後)でパケットをキャプチャするため、TSO/GSOやGROで作られた MTUを大きく超える巨大パケット(数KB〜64KB)がそのまま表示されます。

tcpdump が表示する length: 28960  ← GROで束ねられた見かけのサイズ
実際に回線を流れるフレーム:        1500バイト × 約20個

つまり「キャプチャ上の1パケット」と「ワイヤ上の1フレーム」は一致しません。1パケットあたりのMSSや、実際のパケット数・ペース(パケット間隔)を回線レベルで見たいなら、tcpdumpの値を鵜呑みにせず、ethtool -K で該当機能を一時的に無効化するか、回線上で観測する必要があります。

観測・指標オフロードの影響正しい読み方
tcpdumpのlengthMTU超の巨大値が出るワイヤ上のフレーム数とは別物
pps(パケット/秒)カウンタ計測点で値が変わるNICのethtool統計でワイヤ実数を見る
MSS/区切りの解析境界がGROで消える(LRO)GROなら可逆、LROは無効化して観測

実用上の害もあります。TSO/GSOで巨大な塊を一気にNICへ渡すと、回線へは短時間にバースト状に送出されやすく、これがTCPのペーシングや小さいバッファと相性が悪い場面があります。逆にGROは束ねるぶん、個々のセグメントのACK生成が遅れたりRTT計測がわずかにブレ得ます。多くの場合オフロードはCPU節約の利得が圧倒的に勝ちますが、低遅延が至上命題の用途や精密なRTT計測では、意図的に切る判断もあります。フロー制御・ウィンドウの挙動を精密に追うときは TCPのフロー制御とウィンドウスケーリング と合わせ、オフロードの有無を意識する必要があります。

トラブル切り分けでまず疑う設定

原因不明のスループット低下・チェックサム異常・VM間通信の不調では、まず ethtool -k <iface>tso/gso/gro/lro の状態を確認します。古いNICやドライバではオフロードのバグで破損パケットや性能劣化が起きることがあり、ethtool -K <iface> tso off gso off gro off で切って症状が消えればオフロードが原因と特定できます。ただし常用設定として安易に切るとCPU負荷が跳ね上がるため、切り分け用と割り切るのが定石です。

まとめ

TCP/IP処理のコストはバイト数よりパケット数に比例し、高帯域では標準MTUゆえにパケット数が律速になります。送信側のTSO/GSOは、64KBの巨大セグメントをスタックに通し、MSSへの分割を最後にNIC(TSO)または送出直前のソフトウェア(GSO)へ委ねることで、ホスト側のヘッダ生成・チェックサム・スタック通過の回数を激減させます。受信側のGRO/LROは、同一フローの連続セグメントを巨大バッファへ束ねてから1回でスタックへ上げ、GROは元の境界を復元できる可逆設計ゆえ転送・ブリッジでも安全(LROは不可逆で転送に不向き)です。いずれも回線のMTU/MSSは変えず、ホスト内部の処理単位だけを大きくする最適化なので、tcpdumpにはMTU超の巨大パケットが見える——この「見かけと実体のズレ」を理解することが、オフロード環境での計測とトラブル切り分けの要です。

試験・面接で問われる急所

「なぜオフロードが効くか」→ コストはバイト数でなくパケット数に比例し、固定費(ヘッダ生成・checksum・スタック通過)を処理単位の巨大化で削る。「TSOとGSOの違い」→ TSOはNICハードでの分割(TCP限定)、GSOは分割を送出直前まで遅らせる汎用ソフト枠組みでNIC非対応でも可。「GROとLROの違い」→ GROはソフトで可逆(境界復元可、転送可)、LROはハードで不可逆ゆえルータ/ブリッジでは無効化。「tcpdumpでMTU超の巨大パケットが見える理由」→ キャプチャ点がオフロードのホスト内部側で、回線上の実フレームとは別物。

ネットワーク Article

GRO/GSO/TSO:セグメンテーションオフロードの原理を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

TSO

比較で見る軸

難易度: advanced / カテゴリ: ネットワーク / タグ数: 5

導入後に効く点

送信側はTSO/GSOで一つの巨大セグメント(最大64KB)をスタックに通し、MSSへの分割を最後にNIC(TSO)または直前のソフトウェア(GSO)へ委ねる。受信側はGRO/LROで同一フローの連続セグメントを一つの巨大バッファに束ねてからスタックへ上げる。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
ネットワーク
タグ数
5

判断チェックリスト

  • 自社の用途が「TSO / GSO」に近いか確認する。
  • 強みである「1パケットごとにヘッダ生成・チェックサム・スタック通過のCPUコストがかかるため、高帯域ではパケット数そのものが律速になる。オフロードはこの「処理回数」を減らす最適化で、データ量ではなくパケット数にコストが比例する事実が出発点。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

TSOGSOGROオフロードNICTSOGSOGRO