第25話の実験台から、イトはconnection ledgerを外した。
cumulative ACKのreturn pathも外す。
retransmission timer ringも外す。
send sequence railも外した。
台の上には、live voiceの青いpayloadだけが残った。
「これなら、いちばん軽い」
イトはpayloadを、open datagram cradleへ置いた。
send leverを押す。
光はremote hostまで届いた。
しかしhostには、subtitle applicationとvoice applicationの二つの入口が開いている。
payloadは、どちらへ渡るか決められず、入口の手前で止まった。
stageのspeakerから、音は出ない。
イト
TCPの仕組みを全部外したのに、UDPとして届かない
ユイ
reliabilityを外すことと、transportの情報を全部なくすことは別ですね
ピコ
その光は、まだUDP datagramになっていないよ
remote stageで次のlive voice cueが始まるまで、あと八秒。
current voiceを正しいapplicationへ渡し、送りすぎない設計まで戻さなければならない。
UDPにも、eight-octet headerがある
ピコはopen cradleの横へ、four field slotsだけを残した。
二つのport slot。
一つのlength frame。
一つのchecksum seal。
IETFのUDP標準RFC 768が定めるheaderだ。
four fieldsは、それぞれ16 bit。
header全体はminimum eight octetsになる。
UDPはraw payloadを裸のまま投げる仕組みではない。
minimalなmessage-passing transportだ。
イト
TCPのconnection ledgerはない。でも、datagramを届け分けるためのheaderはある
マコト
minimalはzeroではない、ということだね
ピコ
fieldを一つずつ、役割へ戻そう
stage gateは、残り六秒。
portは、hostの中の入口を分ける
イトはdestination port slotへ、voice applicationの入口と合うplain tokenを置いた。
もう一つのsource port slotには、reply先として使うこのlab processのtokenを置く。
source portは、用途によってzeroにできるoptional fieldだ。
このtrialでは、application feedbackのreturn先として使う。
datagramをもう一度送る。
remote hostへ届くと、destination port tokenがvoice application slotと合った。
subtitle slotではない。
voice payloadが、正しいprocessの入口へ進んだ。
port numberが選ぶのは、destination hostの中のapplication endpointだ。
network途中でどのrouterを通るかを選ぶ札ではない。
lengthは、一つのmessageの端を持つ
イトはvoice payloadをlength frameへ収めた。
UDP lengthは、headerとdataを合わせたdatagram全体のoctet数を示す。
このframeが、一つのdatagramの端を保つ。
TCPがapplicationへbyte streamを提供するのに対し、UDPはdatagramのmessage boundaryを保つ。
first voice datagramとsecond voice datagramは、一つのcontinuous byte streamへ溶けない。
ただし、boundaryを保つことはdelivery guaranteeではない。
一つが丸ごと失われることも、順番が入れ替わることも、duplicateが届くこともあり得る。
checksumは、直してくれない
最後にイトは、checksum sealを閉じた。
このlabでは、nonzero UDP checksumを使う。
route途中で、voice datagramの一部が一bitだけ変わった。
receiverで計算した値が、sealと合わない。
IETFのhost requirement RFC 1122に従い、nonzero checksumがinvalidなdatagramはquietly discardedされた。
イトは、discard trayを見て待った。
「checksumが直して、もう一度送ってくれる?」
何も戻らない。
UDP checksumはdamageを検出する手がかりで、dataをrepairする機能でもretransmitを要求する機能でもない。
イト
checksumで壊れた一片を使わずに済む。でも、失った声を補う責任までは持っていない
ユイ
検出と回復を同じものにしない、ですね
ピコ
UDP headerを戻しても、TCPのreliabilityが戻ったわけではないよ
UDP checksumの扱いにはIP versionなどの条件がある。
ここではheader fieldの役割と、invalid nonzero checksumを受け取ったこのlab trialだけを見る。
stage gateは、残り四秒。
どこまでをUDPへ戻す?
操作台に、三枚のdesign cardが開いた。
- headerもportも外し、raw voice payloadだけを送る
- UDP baseへconnection ledger、cumulative ACK、in-order wait、retransmission timerをすべて戻す
- UDPのminimal headerは保ち、sequence / playout time / late-drop / loss handling / congestion responseはvoice application protocol側へ置く
一番目は、正しいapplication endpointへpayloadを渡せなかった。
二番目のようなreliable upper protocolを作ることはできる。
でも、このvoice trialで古い一片がcurrent playoutを待たせる問題まで戻る。
三番目なら、datagram deliveryに必要なminimal boundaryと、live voiceが必要なpolicyを分けられる。
イトは三番目のcardを持ち上げた。
voice payloadへfour-field UDP headerを閉じる。
その上へ、application protocolのsequence markとplayout clockを置いた。
deadlineを過ぎたdataをcurrent voiceへ戻さないdividerも置く。
network feedbackでsend rateを絞るvalveを、application側へ残した。
イト
軽くするために全部は外さない。UDPが持つheaderは残し、voice固有の順番、時刻、lossの扱い、送りすぎない制御は上で持つ
マコト
責任を消したのではなく、必要な場所へ分けたんだね
ピコ
その設計で、このdiscard trialを動かそう
ピコはheaderを閉じなかった。
application policyを置かなかった。
全部を外す失敗から戻り、third cardを実装したのはイトだった。
lost datagramの後ろを進めた
first voice datagramがremote hostへ届く。
destination portでvoice application slotへ渡る。
second voice datagramは、checksum mismatchでdiscardされた。
UDP自身からretransmissionは起きない。
third voice datagramが、そのまま次のmessageとして届く。
UDPがsecondの回復を待ってthirdをtransport内で保留することもない。
voice applicationはsequence gapを見つけた。
missing pieceのplayout deadlineは、すでに過ぎている。
イトはlost pieceを待つ設定へ戻さなかった。
このlab applicationはtiny gapをconcealし、third datagramのcurrent voiceを再生する。
一瞬だけ音が薄くなった。
話し手の現在の口元と声は、大きく離れずに続いた。
stage gateは、一秒を残して開いた。

成功したのは、このlabのone voice flow / one loss trialだ。
すべてのvoice applicationが同じgapを許せるわけではない。
UDPは「無制限に送れる」ではない
イトはsend-rate valveへ手を残した。
UDP自身には、TCPのようなinherent congestion control mechanismがない。
だからといって、applicationがline rateで好きなだけ送ってよいわけではない。
IETFのUDP Usage Guidelines RFC 8085は、UDPをInternet transportとして使うapplication / upper protocolも、congestion collapseを防ぎ、他flowと公平にpathを使うためのmechanismを持つよう求めている。
同じguidelineは、UDPがlost packetをretransmitせず、duplicate protectionも提供しないため、reliable message deliveryが必要ならapplication側で適切なmechanismを実装する必要があるとする。
UDPを使う理由は、次の言い換えではない。
connection setupがないから、いつでも最速。
retransmissionがないから、考えずに送ってよい。
UDPはconnection establishment / teardown overheadとassociated transport stateを小さくできる。
ただし体感delayやthroughputは、path、loss、application design、message size、congestion responseなどでも変わる。
「UDPだから速い」は、結果の保証ではない。
関連ガイド「UDPとは」では、header、datagram、port、reliability boundaryを一覧で確認できる。
軽さの代わりに残ったもの
stage voiceには、tiny gapが残った。
applicationには、sequence / playout / deadline / loss policyの実装が残った。
send-rate feedbackも残った。
checksumでdiscardしたdataは、自動では戻らなかった。
UDP baseが持たないものを、世界から消したわけではない。
必要ならupper protocolが引き受ける。
必要でなければ、gapやduplicateという結果をapplicationが受け入れる。
イトは、外したTCP ledgerと、残したUDP headerを重ねなかった。
軽いか重いかの勝負ではなく、誰がどの責任を持つかの設計だった。
次回:portは、道を選ばない
完成したUDP datagramが、labの外側へ進んだ。
destination port tokenは、remote voice applicationを指している。
しかし最初のrouterの前で、道が二つに分かれた。
port tokenは光らない。
代わりに、IP destination tagとroute tableが開く。
イトはdatagramを持ったまま、分岐の中央に立った。
次回、ピコルート第27話。
routerは、destination IPからどのnext hopを選ぶ?

