ということで、今回からはProtocol Layerである(Photo01)。PCI ExpressではTransaction Layerと称されていた部分になる。この部分は、Link Layerよりもう少し高レベルでのデータ転送を担うことになる。

Photo01: Link Layerの上位層にあたるのがこのProtocol Layer。

ところでLink LayerはPoint-to-Point、Protocol LayerはEnd-to-Endと分類される(Link Managementのみ、Point-to-Pointになる)。この両者はどう異なるか、である。

例えば図1の様な構成でHubやDeviceがHostにぶら下がっている場合、

Host⇔Hub A
Host⇔Device A
Hub A⇔Hub B
Hub A⇔Device B
Hub B⇔Device C
Hub B⇔Device D

の間の接続がPoint-to-Pointで、

Host⇔Device A
Host⇔Device B
Host⇔Device C
Host⇔Device D

という接続がEnd-to-Endということになる。Link Layerはあくまでも個々の接続のみを制御するものであり、最終的に必要となるHost⇔Device間の制御は行えない。これを司るのがProtocol Layerということになる。

そのProtocol Layerだが、設計目標はこんな形になっている(Photo02)、USBのPIPEモデルを維持し、かつ全ての転送モードをサポートしながら、CPUからのポーリングを不要にするのがここにおける最大のチャレンジである。ちなみに最大でも25Gbpsの転送性能を謳っているが、これはあくまでWG(Working Group)内での目標ということであって、将来バージョン(それがUSB 3.1になるのか4.0になるのかは不明だが)でここまでサポートするという訳ではないそうだ。そうした議論は、USB 3.0の普及が一段落してから考えるという話で、とりあえずある程度のヘッドルームを確保しつつ、プロトコルに無駄な負荷が掛からない(例えば100Gbpsまでスケール出来る事を前提にすると、タイミングとかパケット長などに大幅な見直しをしないと効果的な転送が実現できないだろう)範囲が25Gbpsだったらしい。

Photo02: 互換性に関しては、要するにClass Driverや、(理論上は)Filter Driverの類も正しく動くことである。Filterに関して「理論上」と但し書きを付けるのは、ここの実装はClass Driverほど厳密な検証が行われていない事で、場合によっては動かない事も起こりえるからだ。このあたり、普通にClass Libraryを使っている限りは互換性が取れる筈だが、筆者はアドホックな実装をしている例を若干ながら知っているので、100%の互換性はやや怪しいところだ。

さて、まずPacketの流れを考える。先の図1で、Device→Hostという流れに関しては、これは一意に「Upstreamポートに送り出す」だけである。Deviceは自分のUpstream側に送出すればそれで済むし、Hubは「Downstreamから受け取ったPacketをそのままUpstreamに送り出す」という動作を行えば良い(図2)。

が、問題はHost→Deviceである。USB 1.1/2.0の場合、これはBroadcastingで実施していた(図3)。Hostから転送したデータが、全てのDeviceに送られる仕組みだ。各Deviceは、それが自分宛のPacketならば受け取った後でそれを解釈・処理するし、自分宛でなければそのまま破棄するというインプリメントになる。初期の(というか、現在でもSwitching Hubを使わない)Ethernetがまさしくこの方式で実装されている。

この方式は実装が簡単な反面、

  • 確実にHost→Deviceの通信が行われる事を担保するためには、全てのHub/Deviceが正常に受信するのを待たなければならない
  • 毎回全てのDevice及びHubが動作することになり、システム全体としての消費電力が減らない

という問題がある。前者は通信のレイテンシ増加(=最終的には転送速度のオーバーヘッド)に繋がるし、後者は消費電力増加に繋がる(Photo03)。

Photo03: 「そんなにUSB Hubを介在させるか?」という問題は勿論ある。が、例えばUSB 1.1/2.0でも初期は2ポートしか持っておらず、USB 3.0でも最初に登場するコントローラはほぼ全てが1ないし2ポートである。なので、最低でも1つは介在するだろう。長期的には、例えば液晶DisplayとかKVMスイッチとか、様々なものにHubが入ることが予想され、それをディジーチェーン式に繋ぐことは十分可能性としてありえるだろう。

理想としては、やはり図4の様に「Packetの宛先に繋がる経路だけ、通信が行われる」形にするのが望ましい。

だからといって、EthernetのL2/L3 Switchの様に各DeviceにユニークなAddress(それはMAC AddressだったりIP Addressだったり)を割り振り、各Hubが自分の配下にあるDeviceのAddressを記憶する形でRoutingするのは、あまりに手間が掛かりすぎることになる。そこで、もう少し簡単な形でのRounting方法が実装された。

(続く)