FreeBSD 上で Qemu を母艦と同じネットワークに置く2009年03月05日 10時51分57秒

Qemu を FreeBSD 上で動かす。その時に、ホストとなる FreeBSD と同じネットワークに置くことで、qemu からの外部に接続したり、ホストの FreeBSD と NFS でファイルを共有できる様になる。特に、カーネルを変更して実験していると panic を起こすことも否応にある。NFS でファイルを母艦と共有することにより、fsck を避けると共に、コンパイルも母艦で行ないインストールだけ qemu 内で行なうことが出来る。

FreeBSD での tap の設定と、bridge の設定の応用になる。qemu-ifup を設定する事も出来るが、ここではどの様な操作が必要なのかを示すため使わない。

まずは、必要なカーネルモジュールを読み込む。


host$ kldload kqemu
host$ kldload aio
host$ kldload if_tap
host$ kldload if_bridge

kqemu は必須ではない。aio は qemu が非同期 I/O を使うので必須だ。if_tap と if_bridge はネットワーク関連に使う。

tap を準備する。


host$ sysctl net.link.tap.user_open=1
host$ ifconfig tap0 create
host$ ifconfig tap0 up
host$ chown uyota:uyota /dev/tap0

chown で所有者を変える。chmod と /etc/group で権限を与えても良い。
host$ ifconfig bridge create
bridge0
host$ ifconfig bridge0 addm nfe0 addm tap0 up

tap0 と母艦の nfe0 を bridge0 で繋ぐ。

qemu は tap0 を用いて起動する。


host% qemu -hda FreeBSD.img -net nic -net tap,ifname=tap0

DHCP サーバがあるときは、このまま qemu 内で実行する。


qemu$ dhclient ed0
DHCPREQUEST on ed0 to 255.255.255.255 port 67
DHCPACK from 192.168.0.1
bound to 192.168.0.196 -- renewal in 86400 seconds.
qemu# ifconfig
ed0: flags=8843 metric 0 mtu 1500
        ether 52:54:00:12:34:56
        inet 192.168.0.196 netmask 0xffffff00 broadcast 255.255.255.255
        media: Ethernet 10baseT/UTP 

qemu 内の dhclient が qemu 内の ed0 の MAC アドレス を使い、DHCP サーバに登録される。qemu 内の ed0 から母艦の tap0 へパケットが流れて、tap0 から bridge0 を通過して、母艦の nfe0 から、DHCP リクエストが流れて、処理される。

host$ ping 192.168.0.196
PING 192.168.0.196 (192.168.0.196): 56 data bytes
64 bytes from 192.168.0.196: icmp_seq=0 ttl=64 time=2.379 ms
64 bytes from 192.168.0.196: icmp_seq=1 ttl=64 time=0.647 ms
64 bytes from 192.168.0.196: icmp_seq=2 ttl=64 time=0.631 ms
^C
--- 192.168.0.196 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.631/1.219/2.379/0.820 ms
host$ netstat -r
Routing tables

Internet:
Destination        Gateway            Flags    Refs      Use  Netif Expire
default            dslrouter          UGS         0    55858   nfe0
localhost          localhost          UH          0     5219    lo0
192.168.0.0        link#3             UC          0        0   nfe0
dslrouter          00:0f:db:35:37:41  UHLW        2     1096   nfe0   1200
qemu               52:54:00:12:34:56  UHLW        1        3   nfe0   1195
host$ ifconfig tap0
tap0: flags=8943 metric 0 mtu 1500
        ether 00:bd:26:22:5d:00
        Opened by PID 2334

母艦の FreeBSD から、ping は正しく届くが tap0 は IP アドレスを持たない。また、netstat で見られる MAC アドレスは qemu 内のものだ。また、母艦にて qemu のホスト名の qemu が netstat で見られる。

今度は、手動で IP アドレスを割り当てる場合。


qemu$ reboot
login: root
password:
qemu$ ifconfig ed0 192.168.0.100
qemu$ route add default 192.168.0.1
add net default: gateway 192.168.0.1

外に出たいのならデフォルトのルーティングも設定も必要だ。それが無くても、母艦とは通信出来る。

host$ ping 192.168.0.100
PING 192.168.0.100 (192.168.0.100): 56 data bytes
64 bytes from 192.168.0.100: icmp_seq=0 ttl=64 time=2.888 ms
64 bytes from 192.168.0.100: icmp_seq=1 ttl=64 time=0.580 ms
^C
--- 192.168.0.100 ping statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.580/1.734/2.888/1.154 ms

母艦も含めて外部とネットワークを持たないのなら、tap と bridge の設定をした後に、それぞれから IP アドレスを割り当てる。外には繋がないので route の設定はする必要は無い。


host$ ifconfig nfe0 10.0.0.1


qemu$ ifconfig ed0 10.0.0.2