BitVisorの仮想virtio-netデバイスを使う

BitVisorの仮想virtio-netデバイスを使うと、ハードウェアに搭載されたネットワークデバイスの種類に関わらず、仮想マシンにvirtio-netデバイスを追加できます。使い方を簡単に紹介します。

# Config

make configコマンドで、以下の設定を有効にします。デフォルトで有効です。

```
    [*] NET_V_VIRTIO_NET     Enable virtio-net virtual driver
```

defconfig、または、bitvisor.confに以下のような設定を追加します:

```
vmm.telnet_dbgsh=1
vmm.driver.pci_virtual=driver=virtio-net, net=ip
ip.use_dhcp=0
ip.ipaddr=192.168.12.13
ip.netmask=255.255.255.0
```

BitVisorの設定は以上です。

# 見え方

次に、この設定で起動したBitVisor上のGNU/Linuxでのデバイスの見え方を紹介します。まず、dmesgコマンドで表示されるメッセージの中でvirtio関連のメッセージを検索します:

```shell

$ dmesg|grep virtio
[    1.378632] virtio-pci 0000:00:01.0: enabling device (0005 -> 0007)
[    1.378760] virtio-pci 0000:00:01.0: virtio_pci: leaving for legacy driver
[    2.731786] virtio_net virtio0 enp0s1: renamed from eth0
```

このようにenp0s1というネットワークインターフェイスになっていることがわかります。次に、そのネットワークデバイスの情報を調べます:

```shell

$ ip link show dev enp0s1
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 02:48:84:76:70:00 brd ff:ff:ff:ff:ff:ff
```

このように、state UNKNOWNの胡散臭いネットワークインターフェイスが見えます。一応、lspciコマンドでも見てみることにします。enp0s1というインターフェイス名から、デバイスは00:01.0に追加されていることがわかりますので、以下のコマンドで確認できます:

```shell
$ sudo lspci -s 00:01.0 -vvv
00:01.0 Ethernet controller: Red Hat, Inc Virtio network device
	Subsystem: Red Hat, Inc Virtio network device
	Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupt: pin A routed to IRQ 16
	Region 0: I/O ports at 1000 [size=32]
	Region 5: Memory at 8fa00000 (32-bit, non-prefetchable) [disabled] [size=4K]
	Capabilities: [40] MSI-X: Enable+ Count=3 Masked-
		Vector table: BAR=5 offset=00000000
		PBA: BAR=5 offset=00000800
	Kernel driver in use: virtio-pci
```

Capabilitiesがひとつしかないというめちゃくちゃ怪しいvirtio-netデバイスが見えています。それでは通信してみます:

```shell

$ sudo ifconfig enp0s1 192.168.12.14
[sudo] password for a: 
$ ping -c 3 192.168.12.13
PING 192.168.12.13 (192.168.12.13) 56(84) bytes of data.
64 bytes from 192.168.12.13: icmp_seq=1 ttl=255 time=0.073 ms
64 bytes from 192.168.12.13: icmp_seq=2 ttl=255 time=0.058 ms
64 bytes from 192.168.12.13: icmp_seq=3 ttl=255 time=0.081 ms

--- 192.168.12.13 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.058/0.070/0.081/0.013 ms
$ telnet 192.168.12.13
Trying 192.168.12.13...
Connected to 192.168.12.13.
Escape character is '^]'.
> log 
Starting BitVisor...
Copyright (c) 2007, 2008 University of Tsukuba
All rights reserved.
ACPI DMAR found.
FACS address 0x8AD18000
Module not found.
Processor 0 (BSP)
Using VMX.
Processor 0 2000051616 Hz (Invariant TSC)
Loading drivers.
AES/AES-XTS Encryption Engine initialized (AES=openssl)
Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
Generic ATA/ATAPI para pass-through driver 0.4 registered
Generic AHCI para pass-through driver registered
Generic RAID para pass-through driver registered
Generic IEEE1394 para pass-through driver 0.1 registered
Broadcom NetXtreme Gigabit Ethernet Driver registered
VPN for Intel PRO/100 registered
Intel PRO/1000 driver registered
Realtek Ethernet Driver registered
virtio-net virtual driver registered
NVMe para pass-through driver registered
NVMe para pass-through driver registered
PCI device concealer registered
PCI device monitor registered
Generic EHCI para pass-through driver 0.9 registered
Generic EHCI para pass-through driver 0.9 registered
Generic UHCI para pass-through driver 1.0 registered
xHCI para pass-through driver 0.1 registered
Intel Corporation Ethernet Controller 10 Gigabit X540 Driver registered
PCI: finding devices...
PCI: 23 devices found
PCI: 1 virtual devices created
MCFG [0] 0000:00-9A (E0000000,9B00000)
Starting a virtual machine.
IP address changed: 0.0.0.0 -> 192.168.12.13
telnet server "dbgsh" ready
Processor 1 (AP)
Processor 2 (AP)
Processor 3 (AP)
Processor 3 2000059680 Hz (Invariant TSC)
Processor 1 2000065376 Hz (Invariant TSC)
Processor 2 2000055424 Hz (Invariant TSC)
MSI-X Config [0x0042] 0x00000002 /0,0
virtio_net hook 0x5000
core_io_unregister_handler: port: 5000-501f
virtio_net hook 0x5000
core_io_unregister_handler: port: 5000-501f
virtio_net hook 0x1000
virtio_net: reset
MSI-X Config [0x0042] 0x00000002 /0,0
MSI-X Config [0x0042] 0x0000C002 /1,1
MSI-X Config [0x0042] 0x00008002 /1,0
> exit   
Connection closed by foreign host.
```

このようにBitVisorとの間で通信ができています。

# MACアドレスの問題

実はだいぶ適当に実装してしまったため、ゲストオペレーティングシステムとBitVisorがまったく同じMACアドレスを使って通信しています:

```shell
$ sudo tcpdump -n -e -i enp0s1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s1, link-type EN10MB (Ethernet), capture size 262144 bytes
09:16:41.300797 02:48:84:76:70:00 > 02:48:84:76:70:00, ethertype IPv4 (0x0800), length 74: 192.168.12.14.52790 > 192.168.12.13.23: Flags [S], seq 1149471749, win 29200, options [mss 1460,sackOK,TS val 301355 ecr 0,nop,wscale 7], length 0
09:16:41.300834 02:48:84:76:70:00 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.12.14 tell 192.168.12.13, length 28
09:16:41.300849 02:48:84:76:70:00 > 02:48:84:76:70:00, ethertype ARP (0x0806), length 42: Reply 192.168.12.14 is-at 02:48:84:76:70:00, length 28
09:16:41.300860 02:48:84:76:70:00 > 02:48:84:76:70:00, ethertype IPv4 (0x0800), length 58: 192.168.12.13.23 > 192.168.12.14.52790: Flags [S.], seq 7054, ack 1149471750, win 2144, options [mss 536], length 0
(以下省略)
```

それでも通信できちゃうんですね。へー。

なお、皆様お気づきのことと思いますが、24884767の部分はphonewordでBitVisorを表しています。02で始まるローカルアドレスですので、ブリッジを構成する際は衝突にお気をつけください。

# 割り込みの問題

MSI-X割り込みが使用可能でないと、割り込みが発生せず通信できません。

上で示したのはiMac Mid-2014上のUbuntu 16.04.1環境です。以下のように割り込みが発生していることが確認できます:

```shell

$ grep virtio /proc/interrupts 
 46:          0          0          0          0   PCI-MSI 16384-edge      virtio0-config
 47:          6         15          6          8   PCI-MSI 16385-edge      virtio0-input.0
 48:          0          1          0          0   PCI-MSI 16386-edge      virtio0-output.0
```

実は最初Ryzen 2700搭載のPCで試したのですが、MSI-Xとして設定はされていたにも関わらず、割り込みがまったく発生しなかったため通信できませんでした。チップセットもプロセッサもカーネルのバージョンも違うので原因は特定できていないのですが、何かが間違っているみたいです。うまく通信できない場合は、受信パケット数が増えているか、割り込みが発生しているか、といった部分を確認してみてください。割り込みが発生していないようであれば、何かを見つけて修正してパッチを送っていただくか、または、別の環境でお試しください。