Open vSwitchソースコードリーディングに向けて その5

PORTINGの内容の続き

移植の戦略

OSのネットワークデバイスに対応したnetdevを実装したのちの移植戦略としては以下の3つがとれる。

一番手間がかからないのは"userspace switch"を使うこと。この場合、パケットの受信動作に対応するようにnetdevを実装していれば、追加のコードを書く必要はない。一方で、全てのパケットがovs-vswitchdのプロセスを通過するので性能は低くなる。"userspace swtich"の構成の仕方はINSTALL.userpaceに書いてある。

ユーザー空間のスイッチを使うことが移植の際に適切ではない場合には、よりコードを書く必要がある。"ofproto provider"か"dpif provider"どちらかを実装するかを選択でき、どちらを選択すべきなのかは状況によって異なる。

  • ofproto providerを使う場合においてのみハードウェア的にワイルドカードをサポートする機能(たとえば、ACLテーブルやTCAM)を十分に活用できる。
  • dpif providerを使うことで、Open vSwitchでサポートされているボンディング、LACP, 802.1ag, 802.1Q VLANなどの機能を活用できる。それらの機能についてハードウェアのサポートがある場合には、ofproto providerでは、独自の実装が必要になる。
  • 通常は、dpif providerを実装する方が容易で、最もソフトウェアスイッチングに適した方法である。dpif providerを用いる場合には、ワイルドカードのルールをexact-matchエントリーの中に"爆発?"させる。

ofproto provider

"ofproto provider"は、ofprotoが直接OpenFlow-capableスイッチをモニターしたり制御したりするために使うものである。新規のハードウェア、ソフトウェアのためのofproto providerを実装するためのインターフェイスがofproto/ofproto-provider.hの中のofproto_class構造体で定義されている。この構造体には、多くの関数ポインタがあり、それぞれについてその動作の詳細を説明するコメントがある。もしそのコメントの意味が不明確であれば、バグとして報告してほしい。

ofproto providerのインターフェイスはまだ十分ではないので、もしあなたの目的にそぐわない場合には教えてほしい。改善するようにする。

dpif providerを書く

"dpif"と呼ばれるdatapathを操作するためのライブラリの最上部に作られた"ofproto-dpif"と呼ばれる組み込みのofproto providerがOpen vSwitchにある。"datapath"は単純なフローテーブルであり、exact-matchフローのみをサポートする。つまり、ワイルドカードはサポートしていない。ネットワークデバイスにパケットが到着すると、datapathはexact-matchテーブルから対応するものを探す。一致するものが存在すれば、対応するアクションを実行する。一致するものがなければ、ofproto-dpifにパケットが渡される。ofproto-dpifは、OpenFlowのフローテーブル(ワイルドカードをサポートしている)の状態を維持するものである。このフローテーブルに合致するならば、ofproto-dpifはそのアクションを実行し、新しいexact-matchエントリーとしてdpifフローテーブルにエントリーを追加する。(それ以外の場合には、ofproto-pdifはofprotoにパケットを渡し、パケットがOpenFlowコントローラに送信されるように設定されているならば、OpenFlowコントローラにパケットが送信される)

"dpif"ライブラリは自信の多くの機能を"dpif provider"に委譲している。以下の図が、dpif providerがどのようにOpen vSwtichのアーキテクチャに合わせているのかを示したものである。

                _
               |   +-------------------+
               |   |    ovs-vswitchd   |<-->ovsdb-server
               |   +-------------------+
               |   |      ofproto      |<-->OpenFlow controllers
               |   +--------+-+--------+  _
               |   | netdev | |ofproto-|   |
     userspace |   +--------+ |  dpif  |   |
               |   | netdev | +--------+   |
               |   |provider| |  dpif  |   |
               |   +---||---+ +--------+   |
               |       ||     |  dpif  |   | implementation of
               |       ||     |provider|   | ofproto provider
               |_      ||     +---||---+   |
                       ||         ||       |
                _  +---||-----+---||---+   |
               |   |          |datapath|   |
        kernel |   |          +--------+  _|
               |   |                   |
               |_  +--------||---------+
                            ||
                         physical
                           NIC

lib/dpif-provider.hの中にあるdpif_struct構造体は、新しいハードウェア、ソフトウェアのためのdpif providerを実装するために必要なインターフェイスを定義している。この構造体には、多くの関数ポインタがあり、それぞれについてその動作の詳細を説明するコメントがある。もしそのコメントの意味が不明確であれば、バグとして報告してほしい。

既存のdpifの実装は2種類あり、それらは移植の際に有用な実例として参考になるはずである。

  • lib/dpif-linux.cはLinuxに特化したdpifの実装であり、Open vSwitch特有のカーネルモジュール(datapath/のディレクトリに格納されている)とやりとりを行う実装である。カーネルモジュールはスイッチングにに必要な作業全てを実行し、どのフローテーブルのエントリーにもマッチしないパケットをユーザー空間に渡す。dpifの実装は必然的にこのカーネルモジュールのラッパーになる。
  • lib/dpif-netdev.cは一般的なdpifの実装で、スイッチング動作をその内部で全て行っている。Open vSwitchのユーザー空間のスイッチがこれによって実装されている。

その他

  • uint_16t, uint32_t, uint64_tというホストバイトオーダーの固定長の型が使われている
  • ovs_be16, ovs_be32, ovs_be64はネットワークバイトオーダーの固定長の型が使われている
  • それぞれビット長が等しいものは等価なものであるが、使用意図を明確にするために名前を変えている
  • lib/entropy.cは、起動時に/dev/urandomを読み出すことで得られる高品質な乱数のシードを得ることが出来るということを前提にしている。対象とするプラットフォームでその前提が成立しないなら変更する必要がある。
  • vswitchd/system-stats.cはLinuxでのいくつかの統計情報の取得方法だけを知っている。対象とするプラとフォームにあわせて実装が必要になる可能性がある。