読者です 読者をやめる 読者になる 読者になる

livaの雑記帳

OSとか作ってみたい

自作OSに10GbE NICを移植する

(この記事は古いサイトから移行したものです)

 

f:id:liva_h:20170413193555j:plain

 

Raph Kernelでintel X540-T2を動かすために、slank君と一緒にixgbeドライバを実装しました。

10GbEってのはやはり夢がありますね。ボトルネックを筋肉で解決する感じの脳筋プレイ、嫌いじゃないです。大艦巨砲主義バンザイ。

 

独自OS向けに10GbEデバドラを用意するのは1ミリも新規性はないのですが、まあこれはあくまで僕の備忘録という事で。新規性を出すのはこの後ですね。

 

さて、ixgbeシリーズも基本的にはe1000(8254x/8257x)シリーズと殆ど同じ構造をしています。もちろん10Gbpsでも性能が出せるよう細かい部分が異なりますが、とりあえず動かすだけならe1000の構造を把握していればixgbeの実装で悩むことはないはずです。

 

livaは以前e1000 NIC独自実装freebsdドライバの移植をした事があるので、比較的容易でした。今回も独自実装ではなく、freebsdドライバを移植したのですが、その他のタスクと並行して作業しても二週間程度で終わりました。たぶん移植に全リソースを使えるならデバッグ含めても一週間あれば十分でしょう。

 

余談ですが、e1000の実装をした事がない人は、8254x NIC 仕様書の3.2 Packet Reception, 3.3 Packet Transmission, 3.4 Transmit Descriptor Ring Structure辺りを読むと大枠がつかめて良いと思います。他の項目は大体細かい設定周りの話なので、実装するよりも既存のデバドラコードを読んでしまった方が早いかもしれません。

3.2〜3.4に書かれていることは、

  1. 下図のようなキュー(リングバッファ)をOS側で受信、送信用にそれぞれ用意してあげて、特定のレジスタにその物理アドレスをセットする
  2. 受信キューの場合は、リングバッファの各エントリにさらにOS側で別途確保したメモリ領域の物理アドレスを設定する。HeadとTailがレジスタから取れ、その間のエントリはハードウェアによって受信されたパケットが格納されたエントリとなる。エントリを再設定した上で、レジスタを動かし、エントリをハードウェアが使えるようにする
  3. 送信キューの場合は、Tailが指すエントリに、パケットが格納されている物理メモリをセットし、Tailを動かす

といった内容です。e1000e(8257x)になるとマルチキューとかが出てくるのだけど、基本的には同じ話なので割愛。

f:id:liva_h:20170413193613p:plain

話が逸れました。freebsdのixgbeドライバを移植するにあたり、e1000ドライバとの違いは、

  1. pollingがない(ixgbe_pollが未実装)
  2. Descriptor Write Backの有効化が前提となっているので、その対応

ってな感じです。

1については、em_pollを見つつ、それっぽい感じで実装すれば動きます。定期的にixgbe_handle_linkを呼んで、リンクステータスチェックをしましょう。

2については、下に貼った図の通りで、受信キューでパケット受け取ると、エントリを各種情報で上書きするという物です。当然、エントリをこのまま使いまわす事ができないので、ixgbe_refresh_mbufs内でバッファアドレスを再度書き込むという処理をきちんと移植する必要があります。移植コスト自体は全く高くないのですが、理解してないとリングバッファ内にセットした物理アドレスが意味不明な値に上書きされるように見えるため、メモリ周りのエラーを疑い出して泥沼にハマります。

 

f:id:liva_h:20170413193609p:plain

 

まあそんな感じで頑張って、一日くらい夜を潰してデバッグした結果、以下のようにARPが返ってくるようになりました。

(見づらい写真でごめんなさい)

 

f:id:liva_h:20170413193550j:plain

 

下のMacBook(192.168.100.100)からarp-scanを掛けて、上のRaph Kernel(192.168.100.104)が応答しています。

ちなみに実験に使用したL2スイッチはNETGEAR ProSafe XS708T-100AJSです。ケーブルは一応Cat6e。Cat5でも2M程度なら10Gが出てしまうのですが、まあ流石にね。

 

 

デバッグで疲れたので、ベンチマークはまた別の記事(を書くかはわからないけれど)で。