■LANのデータ転送速度が,ギガビット・イーサネット(GbE)や10GbEの登場で高速化している。これに伴い,サーバーのCPUにおけるTCP/IPネットワーク処理の負荷が問題になっている。
■そこで注目されるのがTCP/IP処理をNIC上の専用プロセッサに任せるオフロード機能である。Windowsのネットワーク・タスクのオフロード機能を説明するとともに,その有効性を検証した。
(2005年3月号「Windowsテクノロジ徹底解説」より)

(飯島 徹)

 


 昨今,サーバー機が使用するLAN(ローカル・エリア・ネットワーク)は,データ転送速度100Mビット/秒のファースト・イーサネットから1Gビット/秒のギガビット・イーサネット(以後GbEと表記)へとシフトしている。近い将来,10Gビット/秒の10GbEが普及するのも確実である。

 従来は,ネットワークが高速化しても,サーバー機で帯域幅を最大限に利用しにくかった。TCP/IPの通信では,すべてのプロトコルがOS上のソフトウエアで実装される。CPUはデータ転送をはじめ,割り込み処理やパケットのチェックサム計算などネットワークの処理を担う必要がある。ネットワークが高速化すればするほど,サーバー機のCPU使用率はTCP/IPネットワーク処理に割かれてしまう。

 現在では,この問題に対処するため,GbEのような高速ネットワークを使う場合,サーバーに搭載された複数のCPUのうち1つ分をTCP/IP処理用に用意するのが常とう手段の1つとされる。CPUの高速化により,この方法でもGbEの理論値に近い性能が得られる。

 だが,ネットワーク・パフォーマンスの大幅な向上と引き換えに,本来はアプリケーションを処理するためのCPU能力を,TCP/IP処理で消費してしまっている状況は無視できない。近い将来,普及が見込まれている10GbEを考慮すれば,さらに大量のTCP/IPネットワーク処理が必要で,すべてをCPUに任せるのは現実的ではない。この問題を解消するのが,ネットワーク・タスクのオフロード,またはNICオフロードと呼ばれる機能だ。

Windows 2000から備わる
NICオフロード機能

 ネットワーク・タスクのオフロードは,TCP/IPネットワーク処理のうち,特にCPUに負荷がかかっている処理をNIC(ネットワーク・インターフェース・カード)上の専用プロセッサに負担させることで,CPUの負荷を軽減させる仕組みである。

 Windowsでは,Windows 2000で採用されたネットワーク・ドライバのインターフェース仕様「NDIS 5」から,このオフロード機能の実装が始まった。

 具体的には,

(1) TCP/IPチェックサムのオフロード
(2) TCP(トラスミッション・コントロール・プロトコル)セグメント化オフロード
(3)IPSec(インターネット・プロトコル・セキュリティ)オフロード

——の3つが利用可能である。

 このうち,TCPセグメント化オフロードは,Windows 2000が出荷された当時開発者向けとして位置付けられ,デフォルトでは[disable]だった。

 一方,ハードウエアであるNIC側では,Windows 2000の出荷以降,サーバー機用のNICからTCP/IPチェックサムのオフロード機能が実装され始めた。当初,サーバー機用の普及価格帯のNICでは,オフロード機能による性能向上は期待されたほどではなかった。また,当時TCP/IPネットワーク処理のCPU負荷を軽減したい場合は,TOE(TCP/IPオフロード・エンジン)対応といわれる,OSのTCP/IPプロトコル・スタックに独自に手を加えたドライバなどを使う高価な専用のNIC(10数万円程度)が必要だった。

 最近,その状況が変わっている。Windows Server 2003が出荷されて以降,NIC上の専用プロセッサ,ミニポート・ドライバ,TCP/IPドライバ,NDISドライバ,それぞれの効率が徐々に改善された。

 現在では約1万~2万円と普及価格帯のNICであっても,OS標準のオフロード機能によるCPU負荷軽減の効果が得られる。Windows Server 2003で実装されたNDIS 5.1からはTCPセグメント化オフロード機能がデフォルトで[enable](利用可能)になっている効果も大きい。

チェックサムとセグメント化の
オフロード機能が主流

 そこでこの記事では,現在Windows Server 2003で利用可能なTCP/IPチェックサムとTCPセグメント化のオフロード機能を例に取り,基本的な仕組みと効果を紹介する。

 前述した通り,Windows ServerではWindows 2000から,TCP/IPチェックサムのオフロード,TCPセグメント化オフロード,IPSecオフロードの実装が始まった。

 このうち,IPSecのオフロードに関しては,NICによる実装があまり進んでいない。理由は,(1)IPSec自体がLAN上で標準的に広く利用される状況にない,(2)IPSec用のロジックを普及価格帯のNICに搭載できるほど安価に生産する技術が確立していない——ことだと推測される。この状況は今後,市場に合わせて変化していくだろう。

 まず,具体的にどのような処理がオフロードの対象になっているのかを知るため,Windows Server 2003でオフロードの対象とされているTCP/IPチェックサム,TCPセグメント化の処理内容をそれぞれ解説しよう。

単純な演算ではあるが
演算回数は多いチェックサムの計算


△ 図をクリックすると拡大されます
図1●IPヘッダーの中のヘッダー・チェックサム
 TCP/IPには2種類のチェックサムが存在する。1つはIPヘッダーのチェックサムで,IPヘッダーが壊れていないかどうかを16ビットのフィールドでチェックする(図1

 送信側では,ヘッダー・チェックサム以外のフィールドを,メモリーからの単純な値のコピーもしくは数回の簡単な加減算によって埋める。しかし,ヘッダー・チェックサムは,ヘッダー全体を16ビット単位で「『1の補数の和』の1の補数」を計算して求められる。単純ではあるが演算回数は多い。


△ 図をクリックすると拡大されます
図2●実際に収集した通信パケット・データ

△ 図をクリックすると拡大されます
図3●IPヘッダー・チェックサムの計算例
 実際のパケットを例にIPヘッダーのチェックサムの計算例を示す。図2は,ネットワーク・プロトコル・アナライザー・ソフト「Ethereal」(無償のオンライン・ソフトでhttp://www.ethereal.com/を参照)を使い,実際の通信データをキャプチャしたUDP(ユーザー・データグラム・プロトコル)パケットの例である。IPヘッダーに該当する部分をフォーマットに合わせて表示したものを図3に示す。

 まず,送信側では,ヘッダー・チェックサムのフィールドを0x0として,IPヘッダーの16ビット単位の「1の補数の和」を求める。計算式は次の通りである。

0x4500+0x3F+0xC1+0x0+0x8011+0x0+0xA01+0x14A+0xA01+0x104=0xDC61

 次に「『1の補数の和』の1の補数」を計算する。「『1の補数の和として算出された0xDC61』の1の補数」は,けたあふれがないことから,単純に「0xDC61」のビット反転により求められ「0x239E」となる。この0x239Eがヘッダー・チェックサムの値である。


△ 図をクリックすると拡大されます
図4●TCPとUDPヘッダーの構造

△ 図をクリックすると拡大されます
図5●UDP疑似ヘッダーの構造
 受信側では,IPヘッダーのすべてのフィールド(ヘッダー・チェックサムを含む)を使い16ビット単位で「1の補数の和」を計算し,結果が0xFFFFとなればデータが正しいと判断する。

 TCPヘッダーとUDPヘッダーの構成を,それぞれ図4図5に示す。TCP/UDPのチェックサムは,TCP/UDPヘッダーおよびデータが壊れていないかどうかをチェックするための16ビットのフィールドである。TCP/UDPチェックサム以外のフィールドは,メモリーからの単純な値のコピーもしくは数回の単調な増減演算によって埋められる。

 しかし,TCP/UDPチェックサムは,「疑似ヘッダー+ヘッダー+データ」を16ビット単位で「『1の補数の和』の1の補数」を計算することにより求められる。やはり単純な演算ではあるが,データ部が含まれることもあり,パケットの長さによっては演算数がとても多くなる。


△ 図をクリックすると拡大されます
図6●UDPチェックサムの計算例
 次に,先のUDPパケットを使って,UDPチェックサムの計算例を示す。基本的にはIPヘッダーのチェックサムと同様であるが,(1)パケットの長さが16ビットの倍数になるように,必要であればパケットの最後に「0」を追加して計算する,(2)チェックサムの計算にのみ利用する疑似ヘッダー(図6)が計算に加わる——という点が異なる。疑似ヘッダーに代入する値のうち,発信元IPアドレス,あて先IPアドレス,プロトコル番号はIPヘッダー,UDPパケット長はUDPヘッダーのものと同じである。

 まず,送信側では,チェックサム・フィールドを0x0として,16ビット単位で「1の補数の和」を求める。計算方法はIPヘッダーのときと同様に以下のようになる。

「UDP疑似ヘッダー」+「UDPヘッダー」+「UDPデータ」=0x3581D

 さらに,「『1の補数の和』の1の補数」を計算する。「『1の補数の和として算出された0x3581D』の1の補数」は,16ビット単位で見たときに,けたあふれがあるので,1の補数の性質通り,けたあふれ補正の処理が必要になる。具体的には,あふれた部分の0x3を残り部分の0x581Dの下位ビットに加える。計算すると,

0x3+0x581D=0x5820

となる。求めた0x5820のビットを反転させると0xA7DFになり,この値をチェックサム・フィールドに代入して,データを送信する。

 受信側では,チェックサム・フィールドを含むUDPのすべてのフィールドで,16ビット単位の「1の補数の和」を計算し,結果が0xFFFFとなれば整合したと見なす。
(次のページへ続く)