ということで、今回からはProtocol Layerである(Photo01)。PCI ExpressではTransaction Layerと称されていた部分になる。この部分は、Link 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だったらしい。
さて、まず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)。
理想としては、やはり図4の様に「Packetの宛先に繋がる経路だけ、通信が行われる」形にするのが望ましい。
だからといって、EthernetのL2/L3 Switchの様に各DeviceにユニークなAddress(それはMAC AddressだったりIP Addressだったり)を割り振り、各Hubが自分の配下にあるDeviceのAddressを記憶する形でRoutingするのは、あまりに手間が掛かりすぎることになる。そこで、もう少し簡単な形でのRounting方法が実装された。
(続く)