注意:いろいろ試行錯誤しながら試した際のメモ書きです。私の試した設定が正しい、必須とも限らないですし、動かなかったのも私の環境、設定が原因の可能性があります。
概要とメモ
- Windows10でHyper-Vを動かし、その上のUbuntuでDPDKのNetVSC PMDを使ってのDPDKのプログラムを動かした
- Hyper-Vは便利そうな機能がならんでるけど、いろいろQEMU+KVMと違う
- GUIのワンクリックでチェックポイントができる。便利そうだが試してない。Azureみたいにディスク書き込みを何重かしてるのかもしれないのでオフにした方がいいかもしれない。
- 動的メモリ割り当ては謎の動きをするので切ったほうが良さそう(おかしくなったのは1GのHugepageをとったせいかも)
- 自宅のPCで試す際、会社のサーバのノリで無邪気にVM2台同時起動するとHDDが刺さって死ぬ
- PC再起動の度(?)に、VMのアドレスが変わってつらい
- IPアドレスの使い方が謎。変なNetworkingされることがある。
試した環境
- Host
- Windows 10 Pro 64bit
- Core i7-6700K CPU @ 4.00GHz
- Memory 16GB
- VM
- Ubuntu Server 18.04.2 LTS (kernelは4.18に上げた)
- vCPU: 4
- Memory: 8192 MB
- DPDK 18.11.1
仮想マシン準備
- Hyper-Vの準備はこちらを参考にした
- Hyper-V Quick Createは使わなかった。仮想マシンを作るたびに十数GBダウンロードするので普通にCDインストールした方が早い。
- VMの構成は下の図のような感じ
- 動的メモリは無効にした
- Ubuntu Serverをインストールしたisoは、the traditional installerな方を使った(liveの方は1度試して失敗した)
- とある事情でハイパーバイザは第一世代を選択
- メモリとCPUを減らした同じような構成のVMを対向として用意した
仮想マシン起動の注意
- 2台同時に起動してはいけない。1台目を起動して、タスクマネージャーでディスクの読み書きが落ち着いてから2台目を起動する(SSDな人は関係ないかも)。
Hyper-V でできる仮想マシン
Microsoftのページによると、Hyper-Vのアーキテクチャはこんな感じらしい。
ネットワークやストレージなどのハードウェア リソースは図のVMBus(≠Virtio)を介して利用される。HostにVSP(Virtual Service Provider)があり、ここからVMBusを通して、各VMにあるVSC(Virtual Service Client)とやりとりがなされる。VirtioはPCIデバイスのようにふるまうが、VMBusを介したVSCはそんなことはしないので、lspci
やlstopo
で何も見えない。
root@ubuntu:~# lspci
00:00.0 Host bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (rev 03)
00:07.0 ISA bridge: Intel Corporation 82371AB/EB/MB PIIX4 ISA (rev 01)
00:07.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)
00:07.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 02)
00:08.0 VGA compatible controller: Microsoft Corporation Hyper-V virtual VGA
root@ubuntu:~# lstopo
Machine (7954MB)
Package L#0 + L3 L#0 (8192KB)
L2 L#0 (256KB) + L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0
PU L#0 (P#0)
PU L#1 (P#1)
L2 L#1 (256KB) + L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1
PU L#2 (P#2)
PU L#3 (P#3)
HostBridge L#0
PCI 8086:7111
Block(Removable Media Device) L#0 "sr0"
PCI 1414:5353
root@ubuntu:~# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:15:5d:00:07:0a brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:15:5d:00:07:0c brd ff:ff:ff:ff:ff:ff
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 00:15:5d:00:07:0d brd ff:ff:ff:ff:ff:ff
lshw
をするとNetwork interfaceが見えるが、PCIアドレスはない。
root@ubuntu:~# lshw -c network
*-network:0 DISABLED
description: Ethernet interface
physical id: 1
logical name: eth1
serial: 00:15:5d:00:07:0c
size: 10Gbit/s
capabilities: ethernet physical
configuration: autonegotiation=off broadcast=yes driver=hv_netvsc duplex=full firmware=N/A link=no multicast=yes speed=10Gbit/s
*-network:1 DISABLED
description: Ethernet interface
physical id: 2
logical name: eth2
serial: 00:15:5d:00:07:0d
size: 10Gbit/s
capabilities: ethernet physical
configuration: autonegotiation=off broadcast=yes driver=hv_netvsc duplex=full firmware=N/A link=no multicast=yes speed=10Gbit/s
*-network:2
description: Ethernet interface
physical id: 3
logical name: eth0
serial: 00:15:5d:00:07:0a
size: 10Gbit/s
capabilities: ethernet physical
configuration: autonegotiation=off broadcast=yes driver=hv_netvsc duplex=full firmware=N/A ip=172.18.86.134 link=yes multicast=yes speed=10Gbit/s
余談だが、lshw -c cpu
をみると合計64個のCPUが見えるので見てみると面白い(60個はDISABLEDになってる)
Hyper-V上のUbuntuからDPDKを利用する
やっと本編。まず、カーネルのバージョンは上げておく
sudo apt install linux-generic-hwe-18.04
sudo apt update && sudo apt upgrade -y
sudo reboot
DPDKはconfig/common_baseの
CONFIG_RTE_LIBRTE_NETVSC_PMD
とCONFIG_RTE_LIBRTE_VDEV_NETVSC_PMD
をy
にし、通常通りインストールする。
interfaceのbind
前述のようにHyper-V上のVMは特殊なインターフェースを持っているので通常のDPDKの手順は使えない。
bind方法はNetvsc-PMDのドキュメントに記述がある。
vmBusはPCIアドレスの代わりにUUIDを使用している。このUUIDを得る。
$ export DEV_UUID_ETH1=$(basename $(readlink /sys/class/net/eth1/device))
$ export DEV_UUID_ETH2=$(basename $(readlink /sys/class/net/eth2/device))
$ echo $DEV_UUID_ETH1 $DEV_UUID_ETH2
f38e3534-f2a7-4e4e-ab92-b5dfdafb9545 e88ee1b4-ffaa-462d-9617-d934d5c8d21d
※このあとのbindまでの操作はkernel 4.18以降で driverctl
というコマンドで簡単にできるようになるらしい。Ubuntu 4.18.2ではkernelバージョンあげてもできなかったが。
Netvsc-PMDは、uio_pci_generic
ではなく、uio_hv_generic
を使う
$ sudo modprobe uio_hv_generic
なんだかよくわからないNET_UUIDなるものをuio_hv_genericにいれる。なんでもいいのかマジックナンバーなのかは分からない。
# NET_UUID="f8615163-df3e-46c5-913f-f2d2f965ed0e"
# echo $NET_UUID > /sys/bus/vmbus/drivers/uio_hv_generic/new_id
あとはデバイスのhv_netvscからのunbindとuio_hv_genericへのbind
# echo $DEV_UUID_ETH1 > /sys/bus/vmbus/drivers/hv_netvsc/unbind
# echo $DEV_UUID_ETH1 > /sys/bus/vmbus/drivers/uio_hv_generic/bind
# echo $DEV_UUID_ETH2 > /sys/bus/vmbus/drivers/hv_netvsc/unbind
# echo $DEV_UUID_ETH2 > /sys/bus/vmbus/drivers/uio_hv_generic/bind
ちゃんとバインドができていると、/sys/bus/vmbus/drivers/uio_hv_generic/
以下にUUIDと一致するリンクができており、ip linkからeth1とeth2が消えている
$ ls /sys/bus/vmbus/drivers/uio_hv_generic/
bind e88ee1b4-ffaa-462d-9617-d934d5c8d21d f38e3534-f2a7-4e4e-ab92-b5dfdafb9545 module new_id remove_id uevent unbind
$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 00:15:5d:00:07:0a brd ff:ff:ff:ff:ff:ff
ここまででちゃんと成功すると、testpmd
でportを確認できる。なお、dpdk-devbind
では確認できないので注意。
Hyper-Vにはどうやら賢いSwitchがVM間に入っているらしく、testpmdのパケットは落とされるため、パケットを送るとカウンタが回るくらいしか確認できない。
$ sudo ./testpmd -- -i
EAL: Detected 4 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Probing VFIO support...
EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -> using unreliable clock cycles !
vmbus_probe_one_driver(): Invalid NUMA socket, default to 0
vmbus_probe_one_driver(): Invalid NUMA socket, default to 0
Interactive-mode selected
testpmd: create a new mbuf pool <mbuf_pool_socket_0>: n=171456, size=2176, socket=0
testpmd: preferred mempool ops selected: ring_mp_mc
Configuring Port 0 (socket 0)
Port 0: 00:15:5D:00:07:0D
Configuring Port 1 (socket 0)
Port 1: 00:15:5D:00:07:0C
Checking link statuses...
Done
testpmd> show port summary all
Number of available ports: 2
Port MAC Address Name Driver Status Link
0 00:15:5D:00:07:0D e88ee1b4-ffaa-462d-9617-d934d5c8d21d net_netvsc down 0Mbps
1 00:15:5D:00:07:0C f38e3534-f2a7-4e4e-ab92-b5dfdafb9545 net_netvsc down 0Mbps
他のDPDKアプリケーションで利用する際にはPCIアドレスの代わりにUUIDを指定すると動作する(と思われる)。少なくともLagopusは動作するらしい。
また終了時の処理が怪しいらしく、アプリケーションを再起動するにはPCも再起動する必要があるっぽい。