2012 Kernel/VM Advent Calendar 21 日目 @hdk_2: VDE のお話
カーネル/VM Advent Calendar 2012 : ATND 2012-12-21
去年、一昨年に引き続き参加してみます。今回は、ちょっと高いレイヤーの VDE のお話です。Kernel/VM ということで、一応、VM にこじつけてみます。
VDE とは、知っている人も多いと思いますが、Virtual Distributed Ethernet の略です。仮想イーサネットと言っていいのかどうかわかりませんが、ソフトウェアで実現したイーサネット、みたいな。SoftEther とかを思い出す人もいるかも知れませんが、独自の認証機能などがあるわけではなく、Unix ドメインソケットを利用した、ずっとシンプルなものです。
Debian では vde2 というパッケージになっています。
vde_switch - 仮想的なスイッチングハブ
vde_switch コマンドは、仮想的なスイッチングハブとして機能します。
$ vde_switch -s /tmp/hoge
このように実行すると、他のプログラムから /tmp/hoge という名前を使ってこのスイッチングハブに仮想的なケーブルを接続したりできます。
Debian の vde2 パッケージには、起動時に自動的に開始する設定方法があります。この方法では、/etc/network/interfaces に以下のように記述します。
auto vde0
iface vde0 inet manual
vde2-switch -
このように書くと、ifup/ifdown コマンドで vde_switch の開始・停止ができ、auto の記述により起動時に自動的に開始されるようになります。名前は /var/run/vde2/vde0.ctl という名前になっており、接続には vde2-net グループの権限が必要です。
vde_plug2tap - vde_switch と tap デバイスの間にケーブルを接続する
vde_plug2tap コマンドは、vde_switch にケーブルを接続し、その先を仮想的なネットワークインターフェイスである tap デバイスに接続します。
# vde_plug2tap -s /tmp/hoge tap0
このように実行すると、tap0 インターフェイスと /tmp/hoge のスイッチングハブが接続されます。ifconfig tap0 10.11.12.13 などと設定して使いましょう。(といっても、スイッチングハブに一本ケーブルを接続しただけでは何もできませんが...)
Debian の vde2 パッケージで /etc/network/interfaces に記述する場合は以下のようになります。
iface tap0 inet static
address 10.11.12.13
netmask 255.0.0.0
vde2-switch -
この場合の vde_switch の名前は /var/run/vde2/tap0.ctl となります。
dpipe と vde_plug - ふたつの vde_switch の間にケーブルを接続する
dpipe コマンドと vde_plug コマンドを使用して、ふたつの vde_switch の間にケーブルを接続することができます。
$ dpipe vde_plug /var/run/vde2/tap0.ctl = vde_plug /tmp/hoge
これは、/var/run/vde2/tap0.ctl と /tmp/hoge のスイッチングハブの間をケーブルで接続します。
$ dpipe vde_plug -s /tmp/hoge = ssh hoge vde_plug -s /tmp/hoge
これは、遠隔ホストとの間で接続する例です。使い方次第で、VPN にもなります。
Debian の vde2 パッケージで /etc/network/interfaces に記述する場合は以下のように書けるらしいです。
iface tap0 inet static
address 10.11.12.13
netmask 255.0.0.0
vde2-switch -
vde2-plug ssh hoge vde_plug /var/run/vde2/tap0.ctl
VirtualBox の仮想マシンと vde_switch の間にケーブルを接続する
知っている人も多いと思いますが、VirtualBox の Linux 版と FreeBSD 版は VDE に対応しています。以前のバージョンでは OSE 版でのみ利用可能で、GUI での設定が可能でした。現在は generic という選択肢になっており、VBoxManage コマンドで設定を行います。
$ VBoxManage modifyvm MyVM --nic1 generic
$ VBoxManage modifyvm MyVM --nicgenericdrv1 VDE
$ VBoxManage modifyvm MyVM --nicproperty1 network=/tmp/hoge
QEMU/KVM の仮想マシンと vde_switch の間にケーブルを接続する
こちらもご存知の方は多いと思いますが、QEMU も VDE に対応しています。
$ qemu -net nic -net vde,sock=/tmp/hoge
Lguest の仮想マシンと vde_switch の間にケーブルを接続する
Linux kernel source に Lguest のサンプルとして入っている Documentation/virtual/lguest/lguest.c.gz は VDE に対応していません。そのため、簡単な改造が必要です。
まず、ヘッダーファイルの include 文を追加します。
#include <libvdeplug.h>
次に、setup_tun_net() 関数を書き換えます。get_tun_device() の行の代わりに、以下のプログラムを書きます。
int s[2];
socketpair(PF_UNIX,SOCK_DGRAM,0,s);
net_info->tunfd=s[0];
if(!fork()){
struct vde_open_args a;
VDECONN*conn;
char buf[2048]="\0\0\0\0\0\0\0\0\0\0";
int l;
close(s[0]);
a.port=0;a.group=NULL;a.mode=0700;
conn=vde_open(arg,"lguest:",&a);
if(!fork())for(;;){
l=vde_recv(conn,buf+10,sizeof buf-10,0);
if(l<=0)
err(1,"vde_recv");
write(s[1],buf,l+10);
}
for(;;){
l=read(s[1],buf,sizeof buf);
if(l<=0)
err(1,"read");
vde_send(conn,buf+10,l-10,0);
}
}
close(s[1]);
あとは、この下のほうにある socket() から configure_device() までと、close(ipfd); は消します。
最後に、Makefile でオプションを指定します。
CFLAGS+=`pkg-config --cflags vdeplug`
LDFLAGS+=`pkg-config --libs vdeplug`
Debian 環境でコンパイルするときは libvdeplug2-dev パッケージを入れておきます。
使い方は、以下のように --tunnet オプションで vde_switch の名前を指定するだけです。
$ ./lguest 64 vmlinux --initrd initrd --tunnet=/tmp/hoge
おわりに
そんなわけで、VDE のコマンドの一部と、VDE 対応の仮想マシンソフトウェアと、プログラムから VDE の API を使う例を紹介してみました。Unix らしいシンプルなツール群と API になっているのがわかると思います。ここで紹介したもの以外にもコマンドがいくつかあって、いろいろ遊べるようになっているみたいなので、ネットワーク好きな人にはお勧めです。