長いfilm ribbonが、amber routeの入口を塞いだ。
第27話でイトが切り替えた、遠回りのalternate pathだ。
その最初の中継gateは、cyan routeのgateより少し狭い。
次のanime cutを一塊にした光は、gateのframeから大きくはみ出している。
後ろでは、voice datagramが三個待っていた。
遠隔stageの波形が、また短く欠ける。
ユイのcue lampが点いた。
「映像previewまで、八秒です」
イトは、長いribbonを抱え直した。
「dataが一つなら、packetも一個。その方が余計なものが少ないはず」
一個の巨大なpacket cradleへ、ribbonを押し込む。
残り七秒。
巨大packetは、狭い次のlinkへ出られなかった
source routerは、巨大packetのdestinationを調べた。
forwarding tableは、amber next hopを選んだ。
routingもforwardingも、今回は正しい。
だが、outgoing linkのgateが閉じた。
packet sizeが、この先で一度に運べる上限を超えている。
この上限が MTU、Maximum Transmission Unitだ。
一つのlinkが、一つのpacketとして運べる最大sizeを表す。
pathには複数のlinkがある。
その途中に小さなMTUがあれば、sourceはそこへ収まるpacket sizeを考えなければならない。
今回のtrialはIPv6 laneだ。
IPv6の仕様であるRFC 8200では、forward先linkのMTUより大きいpacketを中継nodeが見つけた場合、そのnodeはpacketをdiscardし、sourceへICMPv6 Packet Too Bigを返す。IPv6でfragmentするのは途中のrouterではなくsource nodeだ。
gateから、巨大packetが押し戻された。
voice datagramは、その後ろで動けない。
イト
道は合ってるのに、大きさで止まった
マコト
一個にまとめるとheaderは少ない。でも、その一個がpathへ入らないんだね
ピコ
じゃあ、どこで、どの単位へ分ける?
残り六秒。
イトは、いちばん小さく切って失敗した
イトは、ribbon cutterの目盛を左端まで動かした。
「入らないなら、最小まで切る」
cutterが走る。
長いanime cutは、光の粉のようなtiny piecesになった。
一片ずつ、別のUDP datagramへ入れる。
一片ずつ、UDP headerとIP headerが付く。
宛先。
port。
length。
checksum。
IP addressや、ほかのcontrol fields。
payloadは小さいのに、外側の情報はpacketごとに必要だった。
packing benchが、tiny packetで埋まる。
送信queueへ並べる回数も、routerが扱うpacket数も、受信側が確認するpiece数も増えた。
残り五秒。
まだ一枚のanime cutにならない。
ユイ
小さければ小さいほど、よいわけではなさそうです
イト
中身を小さくしすぎて、外箱と整理の仕事を増やした
「dataを分ける」は、一層だけの話ではない
作業台が、四段に開いた。
上段には、applicationが作ったanime cut。
その下に、transportのsegmentまたはdatagram。
さらに、IP packet。
いちばん下に、各linkが運ぶframe。
画面で一つに見えるdataが、networkの一箇所で一度だけ切られるとは限らない。
たとえばTCPは、applicationから受け取ったbyte streamをTCP segmentへpacketizeする。
現在のTCP仕様であるRFC 9293は、TCP segmentの境界がapplicationのwrite境界と一対一ではないことを示す。大きいsegmentはpacket数やheader overheadを減らし、小さいsegmentはpath MTU超過やapplication dataの待ちを避ける方向に働く。sizeにはtradeoffがある。
一方、今回のlabはUDPを使っている。
UDP datagramはmessage boundaryを持つ。
applicationが一つの長いanime cutを複数のUDP datagramへ分けるなら、受信applicationがchunkの識別、順序、欠け、期限、必要ならretryを扱う。
これは、巨大なIP packetをsourceでIP fragmentに分ける話と同じではない。
UDP利用指針のRFC 8085は、IP fragmentationが効率と信頼性を下げ、fragment一個のlossで元packet全体を再構成できなくなる問題を示す。application messageを複数UDP datagramへ分けるなら、各datagramを独立して受け取り、必要なら独立して再送できる形を勧めている。
ここでは、application自身が意味のあるmedia chunkへ分ける方法を選ぶ。

残り四秒。
小分けにすると、別のflowを間へ入れられる
amber linkは、animeだけの専用路ではない。
voiceも通る。
subtitleも通る。
ほかの端末のpacketも、同じ出口を待つ。
巨大なribbon一個が送信時間を長く占めれば、その後ろに来た小さなvoiceは待つ。
finite packetへ分かれていれば、schedulerはvideo packetの次にvoice packet、その次に別のpacketを送り出せる。
これは、すべてのpacketが必ず公平に一個ずつ交互になるという意味ではない。
queueingや優先制御は別の設計だ。
ただ、packetという有限の境界があるから、shared linkをflowごとに固定して占有せず、複数trafficが時間的に使い合える。
Internet architectureの指針であるRFC 3439は、packet switchingに内在するstatistical multiplexingが、限られたbandwidthを効率よく使う基礎だと説明している。
イトは、巨大ribbonと光の粉を見比べた。
一個では、gateを通らない。
粉では、headerと作業が増えすぎる。
三つの切り方
作業台に、三枚のdecision cardが出た。
- 巨大な一個へ戻す。sourceでIP fragmentが必要になっても、元packetは一個のままにする
- tiny piecesをそのまま送る。payloadを最小にし、packet数とheader overheadを受け入れる
- pathの上限より小さい独立media chunksへ測って分ける。header分の余白を残し、voiceを間へ入れ、lost chunkだけをapplication側で扱えるようにする
一つ目は、applicationのchunk管理を減らせる。
だが、fragment一個が欠ければ、巨大な元packetを再構成できない。途中routerが自由に切ってくれる前提にもできない。
二つ目なら、どのgateにも入りやすい。
しかし、payloadに対するheaderの割合、packet処理、chunk metadata、受信側の並べ直しが増える。
三つ目にもcostはある。
chunk ID、期限、受信bufferが必要だ。
最後のchunkだけ小さくなることもある。
pathが変われば、使える上限を見直す必要もある。
それでも、一個のlossで長いcut全体を巻き戻す範囲を避け、voiceが入る境界を作れる。
残り二秒。
イトは、三枚目を選んだ。
イトは、MTUより小さいchunkへ測り直した
イトはtiny cutterを止めた。
光の粉を、元のanime cutへ戻す。
次に、amber pathから届いたsize frameをribbonへ重ねた。
frameいっぱいには切らない。
外側に付くIP headerとUDP headerのぶんを残す。
applicationのchunk markerを置く余白も残す。
イトはribbonを、五つのmedia chunkへ切った。
四つは同じ幅。
最後だけ少し短い。
これは世界共通の「五分割」が正解という意味ではない。
このlabのribbonと、いまのamber pathで選んだ結果だ。
各chunkを、別のUDP datagramへ入れる。
受信側が識別できるmarkerとplayout deadlineをapplication側へ付ける。
イトは送信queueを組み直した。
video chunk。
video chunk。
voice datagram。
video chunk。
subtitle datagram。
残りのvideo chunks。
一つの長いribbonが、linkを塞いだままにはならない。
一個が落ちても、残りは進んだ
最初のvideo chunkが、amber gateを通った。
二個目も通る。
間に置いたvoice datagramが遠隔stageへ届き、波形をつなぐ。
三個目のvideo chunk。
subtitle datagram。
四個目が、labのloss shutterに触れた。
その一個だけが、dark retry trayへ落ちる。
五個目は止まらず、先へ進んだ。
受信applicationのassembly railには、四個分が並んだ。
空いているのは、一箇所だけ。
applicationはUDPに自動再送を求めなかった。
欠けたchunkを自分で識別し、deadlineまでに間に合うと判断して、その一個だけretry requestへ載せた。
イトは四個目だけを送り直した。
amber routeを通る。
空いた一箇所へ収まる。
anime cutが、remote previewへ現れた。

preview lampは、cue lampが赤へ変わった直後に点いた。
間に合わなかった。
voiceは止めずに済んだ。
巨大なcut全体を送り直さずにも済んだ。
だが、四個目を待ったぶん、映像の開始は一拍遅れた。
ユイ
小分けでlossの範囲は小さくなりました。でも、待ち時間は残りました
イト
packetを選べば、時間まで消えるわけじゃない。headerもassemblyもretryも増えた
ピコ
その一拍を、次は測ってみよう
packetは、小さいほど速いわけではない
受信側のassembly railに、五つのchunkがそろった。
そこからapplicationがanime cutを作る。
この組み立ては、IPv6 fragment reassemblyと同じ処理ではない。
applicationが自分で分けたmedia chunksを、applicationの意味に沿って扱っている。
今回、小分けで得たものは三つある。
- amber pathのpacket size上限へ収まった
- videoの境界でvoiceやsubtitleをshared linkへ入れられた
- lossした一個だけをapplication側のretry対象にできた
同時に、失ったものもある。
- packetごとにheaderが付く
- sourceとrouterが扱うpacket数が増える
- chunk ID、ordering、deadline、buffer、assemblyが必要になる
大きすぎれば、pathへ入らないか、fragmentationへ依存する。
小さすぎれば、payloadより外側と処理の比重が増える。
packetizationは、「最小」を探す作業ではない。
path、application、loss、delay、overheadの間で、使える境界を選ぶ作業だ。
小箱は、別々に進めるから意味がある
イトは、巨大packet cradleを空にした。
tiny pieces用のtrayも閉じた。
送信queueには、次のanime cutを分けた五つのpacketと、voice datagramが並ぶ。
amber linkへ、一個ずつ出る。
video。
voice。
video。
それぞれに有限の終わりがあり、次のpacketへlinkを渡せる。
lost chunkだけを見つけ、必要ならその単位でやり直せる。
その代わり、packetごとの外箱と、受信側で意味へ戻す仕事を引き受ける。
イトは、届いた五つのchunkを見た。
四個目だけ、ほかより遅れて光っている。
小分けにした理由と、遅れが消えない理由が、同じrailに残った。
次回:一拍の遅れは、どこで生まれた?
remote previewの横に、二つのclockが現れた。
一つは、first packetを送った瞬間。
もう一つは、last required chunkが届いた瞬間。
二つの針は、同じ場所を指していない。
routeはamberへ切り替わった。
packet sizeはgateへ収まった。
それでも、送信、伝送、queue、処理、retryに時間を使った。
イトは、遅れて光った四個目へclock probeを置いた。
「遅いって、どの時間のことなんだろう」
次回、ピコルート第29話。
レイテンシって、何が遅れているの?
画面のむこう側をもっと知る
packet switching、packet size、分割と再構成を図で整理するなら、パケット通信とは?で確かめられます。

