Open vSwitchをKVM環境で使う

ここ以来、なかなかコードを読めていないのだけど、とりあえず環境を作ったので、忘れる前にメモ。まずはOpen vSwitchをLinux標準のブリッジの代わりに使うことを考える。Open vSwitchのバージョンはv1.6.1。OSはDebian GNU/Linux 7.0 (testing)。Debianのパッケージ(1.4.2ベース)は使わずに野良ビルド
ここに書いたことはトップディレクトリ直下にあるINSTALL.LinuxとINSTALL.KVMの抜粋なので、まずはそこに目を通すべし。

Open vSwitchの構成

基本的な構成要素は次の三つ。Open vSwitchデーモン(ovs-vswitchd)、構成情報を管理するDBサーバ(ovsdb-server)、パケットの転送処理(データパス)を行うカーネルモジュール(openvswitch_mod.ko)である。ovs-switchdとovsdb-serverはUNIXドメインソケットなどで接続される。brctl互換に振る舞うためのovs-brcompatdとbrcompat_mod.koなども存在するがここでは割愛する。
ovs-vsctlコマンドなどを実行したときの制御フローは、ovs-vsctl -> ovsdb-server -> ovs-vswitchd -> openvswitch_mod.koとなるようだ。

インストール

gitからコンパイルする。

$ git clone git://openvswitch.org/openvswitch
$ cd openvswitch
$ git checkout -b v1.6.1 v1.6.1
$ ./boot.sh
$ ./configure --prefix=/opt --with-linux=/lib/modules/`uname -r`/build
$ make
$ sudo make install
$ sudo insmod datapath/linux/openvswitch_mod.ko

ovs-vswitchdの前にovsdb-serverを起動する必要がある。初めて起動するときは、まずovsdb-toolを使ってDBを初期化する。

$ sudo mkdir -p /opt/etc/openvswitch
$ sudo ovsdb-tool create /opt/etc/openvswitch/conf.db vswitchd/vswitch.ovsschema

ovsdb-serverの起動(SSLサポートなしの場合)。

$ sudo ovsdb-server --remote=punix:/opt/var/run/openvswitch/db.sock \
                     --remote=db:Open_vSwitch,manager_options \
                     --pidfile --detach

次に、ovs-vswitchdを起動すればいいのだけど、初回起動時にはDBの処理化のおまじないが必要になる。

$ sudo ovs-vsctl --no-wait init

$ sudo ovs-vswitchd --pidfile --detach

これで準備は完了。

ブリッジの作成

brctlと考え方は同じ。ブリッジbr0を作り、物理デバイスeth1をつなぐ場合は次の通り。

$ sudo ovs-vsctl add-br br0
$ sudo ovs-vsctl add-port br0 eth1

KVMの設定

tapデバイスをブリッジにつなぎこむ場合、「-net tap,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown」のようにスクリプトを実行していると思うが、このスクリプトを以下のようなものに差し替えればOK。これでQEMU/KVM起動時にtapデバイスの着脱が自動的に実行される。

$ cat /etc/ovs-ifup
#!/bin/sh

switch='br0'
/sbin/ip link set $1 up
/opt/bin/ovs-vsctl add-port ${switch} $1
$ cat /etc/ovs-ifdown
#!/bin/sh

switch='br0'
/sbin/ip link set $1 down
/opt/bin/ovs-vsctl del-port ${switch} $1

ovs-vsctl showコマンドで構成を確認することができる。ovs-vsctl list-brとova-vsctl list-ports br0でも同様な結果が得られる。

$ sudo ovs-vsctl show
01f36f74-52d7-4726-a143-28eb85439345
    Bridge "br0"
        Port "eth1"
            Interface "eth1"
        Port "tap0"
            Interface "tap0"
        Port "br0"
            Interface "br0"
                type: internal

この状態でもOpenFlowのフローベースでスイッチングされている。OpenFlowコントローラとは接続してないけど、ovs-ofctlコマンドを使ってフローテーブルを設定することができる。例えば、ovs-ofctlコマンドでフローテーブルを見ると、フローテーブルにはNORMALアクションのエントリが一つだけあることがわかる。

$ sudo ovs-ofctl dump-flows br0
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=6988.236s, table=0, n_packets=25756163, n_bytes=30708661340, idle_age=0,priority=0 actions=NORMAL

終了方法

Debianパッケージだとちゃんとrc.dスクリプトが準備されていると思うけど、pidファイルをcatしてkillすればOK。

$ sudo kill `cd /opt/var/run/openvswitch && cat ovsdb-server.pid ovs-vswitchd.pid`