で、今は簡単にRoutingと紹介したが、具体的に何をやるかがここからである(Photo01)。まず受信したら、最初に行うのはPacketの正当性チェックである。これはPacket HeaderのCRC-16とCRC-5を計算しなおし、正しいかを確認するもので、ここでエラーがあった場合はエラー処理(これはどんなPacketかで振る舞いが変わるので一意には言いがたい)を行う。問題がなければそのままRouteStringを参照して、ターゲットとなるDownstream PortにPacket HeaderをRouting(つまりUpstreamのHeader BufferからDownstreamのHeader Bufferへ移動)する。また同時に、LGOOD_xをUpstream Port側に送り出し、またLCRD_xも送り出すことになる。

Photo01: これはまぁ正常に受信したことをHostに通知するために必要な作業である。

さて、これとは別にHubにはDPP向けのBufferを別に用意することが必要である。なぜこうしたBufferingがなぜ必要か、をまとめたのがこちら(Photo02)である。まずUpstream Portが4つ分のPacket Headerを送信し、その後で1KBのDPPを送信し始めるが、同じタイミングでDownstreamからも1KBのDPPを受信するというケースである。このケースでは、まずHubはHeader 1~4を受信、RoutingしてDownstream側のHeader Bufferに積むわけだが、この積み替えたHeader 1~4を送信し始める前にUpstream側からのDPPの受信を開始しなければならない。しかも、これと並行してDownstream側からもDPPが送られてくるから、こちらも受信しなければならない。このケースで、仮にBufferが無い場合、HubはHeader 1~4を送信し終わらないとDownstreamからの受信ができなくなる。というのは、Header 1~4を(Hubが)受信したというLGOOD_x/LCRD_xをUpstream側に送信しないと、Downstream側から受信した1KBのDPPを送り出すわけにはいかないからだ。ところがBuffer無しだと、Downstreamから受け取ったDPPをすぐUpstream側に転送しなければDPPの取りこぼしが発生してしまい、転送が正常に行えなくなる。こうした事を避けるために、DPH用のHeader Bufferとは別に、Data Bufferが別途必要となるわけだ。

Photo02: これはData Packet Headerに続き、1KBのData Packet Payloadが続いた場合のケース。

このData Bufferについて、Specificationでは細かな定めはない。Specificationによれば、Upstream用とDownstream用に、独立して動作するBufferが1組必要である、と規定しているだけである。ただ現実問題として最低でも1単位は1KB程度のサイズは必要になるだろうし、最小はUpstream/Downstream共に1個で構成できるが、実際はDownstream向けにはもう少し数を増やさないとHubが追いつかなくなるケースが出てきそうだ。

ちなみにこのDataBufferは、

  • BERが規定より高くなった場合
  • LinkがLow Power Stateになった場合
  • (ネットワークの世界ならDoSにあたるような)、大きなパケットを限度以上に連続して送り続けられる場合

などは、データをドロップしていいことになっている。もっとも最後の条件、普通に考えればDeviceに何かの異常が発生した(例えば内部のコントローラが暴走した)などの理由でやたらめったら意味の無いパケットを大量に送信するというケースだろうが、ただインプリメントするほうとしては、具体的にどの程度の頻度ならば無視するのかという指針が無いのはちょっと微妙なところ。恐らくは、例えば10回連続して不正なPacketが来たらBufferをDropするとかそういった実装になると思うが、これで十分なのかはちょっと筆者にも見当がつかないところだ。

Photo03: このあたりの設計で、Hubの性能が決まってくることになるだろう。特にFlash Storageなどの高速なDeviceを複数ぶら下げ、その間でデータのコピーなんてやる場合、それなりの数のBufferがないとHubがボトルネックになりそうである。

(続く)