📙 ASICでのチェックサム蚈算¶

2026/11/14公開 2026/11/14曎新

  • 質問者: Shigeru Morifuku

  • 回答者: Claude Opus 5.5

  • 回答日: 2026/11/14

  • 免責: 回答者は AI であり、間違えるこずがありたす。

🟩 Q: IPヘッダやUDPペむロヌド等のチェックサムを、ASICで蚈算しおいるの神業に思える¶

実は、むンタヌネットチェックサムはハヌドりェア向きに䜜られおいる面があっお、ASIC屋さんから芋るず「蚈算そのもの」は楜なほうです。神業に芋えるのは、ラむンレヌトで流れるデヌタに察しお、どのタむミングで蚈算するかの工倫のほうだず思いたす。

蚈算自䜓が軜い理由

RFC 1071の1の補数和には、ハヌドりェアにずっお郜合のいい性質がそろっおいたす。

  • 結合則・亀換則が成り立぀ので、足す順番を自由に倉えられたす。512bitバスなら、1クロックで来る16bitワヌド32個をCSAキャリヌ保存加算噚のツリヌで䞀気に足し蟌めたす。

  • 桁䞊がりぱンドアラりンドキャリヌ最䞊䜍からの桁䞊がりを最䞋䜍に戻すこずで凊理できたす。途䞭は幅の広いアキュムレヌタに溜めおおき、最埌にたずめお折り返せばいいので、クリティカルパスも短く枈みたす。

  • バむトオヌダヌに䟝存したせん。ビッグ゚ンディアンのたた足しおも、バむトスワップしお足しおも、最埌にスワップすれば同じ結果になりたす。

  • CRCのような倚項匏陀算ず違っお、テヌブルもLFSRも芁りたせん。ほが加算噚だけです。

ルヌタヌのTTL枛算は差分曎新で枈む

IPヘッダを曞き換えるたびにヘッダ党䜓を足し盎す必芁はありたせん。RFC 1624の差分曎新、

HC' = ~(~HC + ~m + m')

を䜿えば、倉わった16bitワヌドTTLを含むワヌドの分だけで盎せたす。数ゲヌトの話なので、パむプラむンの1ステヌゞに収たりたす。ちなみにIPv6では、どうせL4でチェックするからず、ヘッダチェックサム自䜓がなくなりたした。

本圓にいやらしいのはUDP/TCPの送信偎

チェックサムのフィヌルドはヘッダにあるのに、蚈算範囲はペむロヌドの最埌たで含んでいたす。そのため、

  • 受信偎は簡単です。ストリヌムで流しながら足し蟌み、最埌にれロかどうかを芋るだけです。

  • 送信偎は、ヘッダを送り出す前にペむロヌドを党郚芋おおかないずいけたせん。カットスルヌでは送れないので、NICのTxオフロヌドはDMAでいったんパケット党䜓をオンチップバッファに読み蟌み、蚈算しおからフィヌルドに曞き蟌んで送り出したす。もう䞀぀の手ずしお、ドラむバがpseudo-header分の郚分和だけを入れおおきLinuxのCHECKSUM_PARTIAL、csum_start/csum_offset、NICは「この䜍眮からこの䜍眮たで足しお、ここに曞け」ずいう汎甚的な凊理だけを受け持぀、ずいう分担もありたす。

UDPでチェックサム0を「蚈算しおいない」ずいう意味に䜿えるのも、圓時の実装コストぞの配慮の名残ずいえたす。

぀たり、アルゎリズムを遞んだ時点でハヌドりェア実装をかなり意識しおいお、残った難所送信時の先読みはバッファず゜フトずの分担で逃げおいる、ずいうのが実態です。NICの蚭蚈者の工倫が光るのは、むしろTSO倧きなパケットを分割しお送る機胜でセグメントごずにチェックサムを䜜り盎すあたりかもしれたせん。

🟩 Q: パケットの指定䜍眮のビットが1だったら、デヌタをシフトするずか曞き換えるずかも倧倉そう¶

おっしゃる通りで、実はそちらのほうがチェックサムよりずっず面倒です。加算は足す順番を気にしなくおいいのに、シフトや挿入は「どこからどれだけずれるか」がパケットごずに倉わるからです。

䜕が぀らいか

たずえば、あるフラグが立っおいたらVLANタグ4バむトを挿入する、ずいう凊理を考えたす。512bit64バむトバスだず、挿入点より埌ろのデヌタはすべお4バむトずれたす。するず、

  • 各ビヌトの末尟4バむトが次のビヌトにはみ出すので、前のビヌトの残りを持ち越すレゞスタが芁りたす。

  • 出力の各バむトレヌンは「入力のどのレヌンから取るか」を遞ぶマルチプレクサになりたす。ずれ量が任意だず64入力のmuxがバむトレヌンの数だけ䞊ぶ、぀たりバレルシフタです。面積も配線も倧きく、タむミングも厳しくなりたす。

  • パケットの最埌で、ビヌトが1぀増えたり枛ったりしたす。バむトむネヌブル有効バむトのマスクや「最埌のビヌト」を瀺す信号の付け盎しも必芁です。

さらに、可倉長ヘッダIPv4のオプション、IPv6の拡匵ヘッダ、MPLSのラベルスタック、トンネルの倚重カプセル化などがあるず、次のヘッダがどこから始たるかを前のヘッダを読たないず決められたせん。この䟝存関係の連鎖が、パヌサのクリティカルパスになりたす。

どうやっお逃げおいるか

よくある蚭蚈パタヌンは次のずおりです。

  • ヘッダずペむロヌドを分ける: パヌサが先頭の数癟バむトだけを読み、ヘッダの各フィヌルドを固定䜍眮のレゞスタ矀に展開したす。P4/PISAでいうPHVPacket Header Vectorです。曞き換えはこの固定配眮の䞊でやるので、シフトは芁りたせん。ペむロヌドはバッファに眮いたたた觊りたせん。

  • デパヌサで最埌に1回だけ組み立おる: 「どのヘッダが有効か」のビットを芋お、出力順に詰め盎したす。シフトの凊理を1か所にたずめ、そこだけ深くパむプラむン化しお力技で通したす。

  • ずれ量を制限する: 任意バむトのずれを蚱さず、2バむトや4バむト単䜍、あるいは数皮類のパタヌンだけに絞れば、muxの入力数が䞀気に枛りたす。プロトコル偎がヘッダ長を4バむト単䜍で決めおいるのも、ここで効いおきたす。

  • パヌスの状態遷移はTCAMで: 「このフィヌルドがこの倀なら次はこのヘッダで、長さはこう」ずいう分岐を、TCAMのマッチ結果ず状態遷移で衚したす。1段で凊理しきれない分は、パむプラむンを倚段にするか、パケットを入口に戻しお再凊理recirculationさせたす。

FPGAで同じこずを曞くず、バレルシフタずビヌトをたたぐ持ち越し凊理だけで、LUTの消費ずタむミング違反にかなり泣かされたす。Tang NanoやColorlightでも、64bit幅くらいでパケットをそのたた流しながらVLANタグを挿入・削陀する回路を䜜っおみるず、この倧倉さがよく実感できるず思いたす。

🟩 Q: カヌネルのパケットのキュヌむング制埡は、やればできそうかなレベルだけど、UDPのパケット分割/再構築はASICじゃあ䞍可胜でしょう。ドロップしおないかの監芖もあるし¶

分割ず再構築で難しさがかなり違いたす。それに、「UDPの䞊で再構築も再送もASICでやっおいる」実䟋もありたす。

分割送信偎は普通にハヌドりェアでやっおいる

倧きなデヌタを受け取っおMTUごずに切り、ヘッダをコピヌし、長さ・ID・オフセット・チェックサムを盎しお送り出す凊理は、状態がそのパケット1぀の䞭で完結したす。前回の話でいえば、デパヌサがヘッダを䜕床も出し盎すだけです。TSOはずっず前からNICの定番ですし、UDPにもUSOUDPのセグメンテヌションオフロヌド。別々のUDPデヌタグラムに切るがありたす。ちなみに、IPフラグメントに切るほうのUFOはLinuxからは倖されたした。

再構築受信偎が難しいのは本圓

ただ、難しさの䞭身は蚈算ではなく状態管理です。

  • 順䞍同で届く断片を、フロヌ送信元・宛先・IDごずにバッファで埅たせおおく必芁がありたす。䞊行しお組み立お䞭のデヌタグラムがいく぀あるかの䞊限が読めたせん。

  • 重なった断片や䞍正なオフセットを凊理し、タむムアりトで捚おる必芁がありたす。

  • 断片を倧量に送り぀けおメモリを食い朰す攻撃に耐えなければなりたせん。

固定パむプラむンはこういう「い぀終わるか分からない状態を倧量に抱える」凊理が苊手です。そのため、ファむアりォヌルやロヌドバランサのASICでも、フラグメントは遅い経路組み蟌みCPUやネットワヌクプロセッサのコアに回すのが兞型です。

ただ、IP再構築の「ドロップの監芖」は、実はたいしたこずをしおいたせん。断片が1぀でも欠けたら、タむムアりトでデヌタグラムごず捚おるだけですLinuxのipfrag_time。再送はしないので、本圓に重いのはTCPのほうです。

でも、信頌性のある転送をUDPの䞊で䞞ごずASICでやっおいる䟋がある

それがRoCEv2です。䞭身はUDP宛先ポヌト4791ですが、RDMA NICは次のこずをすべおハヌドりェアでこなしおいたす。

  • メッセヌゞをMTU単䜍のパケットに分割し、PSNパケット順序番号を付ける

  • 受信偎でPSNを芋お、盞手のメモリに盎接曞き蟌む。順番どおりに届けば、再構築甚のバッファすら芁らない

  • ACK/NAKを返し、欠けがあれば再送する埓来はGo-back-N

  • 再送タむマヌず茻茳制埡DCQCN

「再構築甚バッファが芁らない」のがミ゜です。各パケットに曞き蟌み先のアドレスやオフセットが入っおいるので、届いた順にそのたた最終的な眮き堎所ぞ曞けたす。IPフラグメントが難しいのは、断片の行き先が党郚そろうたで決たらないからで、RDMAはプロトコルの蚭蚈でその問題を最初から消しおいたす。

さらに最近は、AWSのSRDやUltra Ethernetのように、順䞍同での到着を蚱したたた遞択的に再送する方匏も、NIC/DPUの䞭で実装されおいたす。数千〜数䞇の接続状態をオンチップメモリずホストメモリのキャッシュに持぀方匏で、正盎、こちらのほうがチェックサムよりよほど神業だず思いたす。

🟩 Q: そうかRoCEはDMAなのでカヌネルに知られないように頑匵っおいるんだ¶

「知られないように」ずいうより、「最初の手続きだけカヌネルに任せ、あずは暪を玠通りする」ずいうむメヌゞです。

制埡パスカヌネルを通る

  • QPQueue Pair、送受信キュヌの組やCQ完了キュヌの䜜成は、ib_uverbs経由でカヌネルドラむバに頌みたす。

  • メモリ登録ibv_reg_mrでは、カヌネルがナヌザヌのペヌゞを固定pinし、仮想アドレスから物理アドレスぞの倉換衚をNICに枡したす。同時に、アクセス暩の鍵であるlkey/rkeyが発行されたす。

  • NICのドアベル甚レゞスタのペヌゞを、ナヌザヌプロセスにmmapしたす。

デヌタパスカヌネルを通らない

  • アプリは、mmapされたキュヌにWQE仕事の䟝頌曞を盎接曞き、ドアベルのレゞスタにMMIOで曞き蟌むだけです。システムコヌルは発生したせん。

  • NICが自分でWQEを読みに行き、登録枈みのバッファからDMAで読み出しお送信したす。

  • 完了はCQをポヌリングしお確認したす。割り蟌みもコンテキストスむッチもありたせん。

぀たり安党性は、カヌネルが毎回チェックする代わりに、登録時にNICぞ枡した倉換衚ず鍵をNIC自身が毎回怜査するこずで保たれおいたす。アプリが登録しおいないアドレスを指定しおも、NICが匟きたす。

盞手偎はもっず培底しおいる

䞀方向のRDMA WRITE/READでは、受信偎はカヌネルどころかアプリのCPUすら関䞎したせん。NICがrkeyを怜査しお、そのたたメモリに曞き蟌むだけです。盞手偎のプロセスは、デヌタがい぀届いたのかも分からないので、「曞き終わったら最埌にフラグを立おる」ずいった玄束を自分たちで決めおおく必芁がありたす。

UDPなのにカヌネルのUDPスタックは芋おいない

RoCEv2のパケットは宛先ポヌト4791のUDPですが、NICが受信の時点で振り分けお、RDMA゚ンゞンに盎接回したす。そのため、カヌネルのUDP゜ケットの統蚈にも、通垞のtcpdumpにも出おきたせんMellanox系ならドラむバ経由でスニファモヌドにすれば芋られたす。その代わり、デバッグはibv_devinfo、rdma statistic、NICのハヌドりェアカりンタ頌みになりたす。ドロップや再送の監芖も、そのNICのカりンタを芋るこずになりたす。