手当たり次第に書くんだ

飽きっぽいのは本能

Ubuntu 26.04 OVS-DPDK と vhost-user の基本構成 – 物理 NIC なしで KVM VM との疎通を確認する

はじめに

OVS-DPDK の検証では、物理 NIC を DPDK 対応ドライバーへ bind し、外部ネットワークとの通信や転送性能まで確認する構成を想像しがちです。ただし、OVS-DPDK と vhost-user の接続関係を確認するだけであれば、物理 NIC を使わない閉じた検証環境でも十分に意味があります。

この記事では、Ubuntu 26.04 の KVM ホスト上で、既存の Open vSwitch 環境を残したまま検証専用の OVS-DPDK bridge を追加します。その bridge に vhost-user インターフェースを持つ KVM VM を 2 台接続し、ホストから各 VM への疎通、vhost-user の接続ログ、PMD thread のパケット受信を確認します。

目的は性能評価ではありません。物理 NIC を使わない最小構成で、OVS-DPDK、QEMU / KVM、vhost-user の基本的な接続が成立することを、再現しやすい手順として確認することです。

  • Ubuntu 26.04 で OVS-DPDK を有効化する
  • 既存の system datapath bridge と DPDK 用の netdev bridge を共存させる
  • 物理 NIC を使用しない閉じた検証ネットワークを作る
  • QEMU を vhost-user server、OVS を client として接続する
  • 通常の virtio-net を使用する VM との疎通を確認する

今回の検証範囲

今回確認した範囲は次のとおりです。

項目対象
OVS-DPDK の起動対象
datapath_type=netdev の bridge 作成対象
dpdkvhostuserclient の接続対象
KVM VM への vhost-user NIC 接続対象
ホストから VM への疎通対象
既存 system datapath bridge との共存対象
物理 NIC の DPDK bind対象外
異なる物理ホスト間の通信対象外
VM 相互間の通信対象外
通常 OVS との性能比較対象外
OVS-DPDK の性能測定対象外
ゲスト内 DPDK対象外
VPP や DPDK アプリケーションの動作対象外

今回の VM は、ゲスト OS 内では通常の Linux virtio-net ドライバーを使用しています。

ゲスト Linux
  └─ virtio-net
       └─ vhost-user
            └─ OVS-DPDK userspace datapath

ゲスト内で DPDK を動作させる構成ではありません。DPDK を使用しているのは、ホスト側の Open vSwitch です。

検証環境

対象ホストは次のとおりです。

kvm-host.example.local

主なソフトウェアのバージョンは次のとおりです。

ソフトウェアバージョン
Ubuntu26.04
Open vSwitch3.7.1
DPDK25.11.0
仮想化基盤KVM/libvirt

実際の ovs-vswitchd --version では、OVS と DPDK の両方のバージョンを確認できました。

ovs-vswitchd (Open vSwitch) 3.7.1
DPDK 25.11.0

既存環境には、通常の kernel datapath を使用する bridge が存在しています。

br-int
brphys0

今回、検証用として次の bridge を追加しました。

br-dpdk-test

全体構成は次のとおりです。

ovs-vswitchd
  ├─ br-int
  │    └─ datapath_type=system
  │
  ├─ brphys0
  │    └─ system datapath
  │
  └─ br-dpdk-test
       └─ datapath_type=netdev
            ├─ internal port
            │    └─ ホスト IP: 192.0.2.1/24
            │
            ├─ vhost-user-test0
            │    └─ ovs-dpdk-test0: 192.0.2.10/24
            │
            └─ vhost-user-test1
                 └─ ovs-dpdk-test1: 192.0.2.11/24

物理 NIC は br-dpdk-test へ接続していません。また、物理 NIC を VFIO や UIO ドライバーへ bind する作業も行っていません。 なお、bridge とデータパスは分離されていますが、OVSDB と ovs-vswitchd プロセスは既存 bridge と共通です。検証用 bridge を追加したからといって、OVS の管理プレーンまで完全に分離されるわけではありません。

必要なパッケージを導入する

次のパッケージを導入しました。

apt update
apt install \
  openvswitch-switch-dpdk \
  dpdk \
  libguestfs-tools

openvswitch-switch-dpdk は、DPDK 対応版の ovs-vswitchd を使用するために必要です。 libguestfs-tools は OVS-DPDK 自体の必須パッケージではありません。今回は、VM を起動する前に clone したゲストディスク内の netplan などを変更するために使用しました。

DPDK 対応版の ovs-vswitchd へ切り替える

Ubuntu の Open vSwitch パッケージでは、通常版と DPDK 対応版の ovs-vswitchd を alternative で切り替えられます。

update-alternatives --config ovs-vswitchd

今回選択した実体は次のファイルです。

/usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk

実際の状態は次のとおりです。

ovs-vswitchd - manual mode
 link best version is /usr/lib/openvswitch-switch/ovs-vswitchd
 link currently points to /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk

通常版の ovs-vswitchd を使用したまま DPDK を有効化しようとすると、次のエラーが記録されました。

DPDK not supported in this copy of Open vSwitch.

このため、OVS-DPDK を使用する前に、DPDK 対応版へ切り替わっていることを確認する必要があります。

update-alternatives --display ovs-vswitchd

OVS-DPDK を有効化する

今回設定した DPDK 関連の値は次のとおりです。

ovs-vsctl --no-wait set Open_vSwitch . \
  other_config:dpdk-init=true \
  other_config:dpdk-lcore-mask=0x10 \
  other_config:pmd-cpu-mask=0x20 \
  other_config:dpdk-socket-mem=1024 \
  other_config:vlan-limit=0

実際の other_config は次のようになりました。

{
 dpdk-init="true",
 dpdk-lcore-mask="0x10",
 dpdk-socket-mem="1024",
 pmd-cpu-mask="0x20",
 vlan-limit="0"
}

各設定の意味は次のとおりです。

設定内容
dpdk-inittrueOVS 起動時に DPDK を初期化する
dpdk-lcore-mask0x10DPDK の制御用 lcore を CPU 4 へ割り当てる
pmd-cpu-mask0x20PMD thread を CPU 5 へ割り当てる
dpdk-socket-mem1024NUMA socket 0 で使用する DPDK memory を 1024MB 確保する
vlan-limit0今回の環境で設定した OVS の VLAN 関連値

CPU mask はビットマスクです。

0x10 = CPU 4
0x20 = CPU 5

vlan-limit=0 は今回の環境で設定した値ですが、今回の untagged な vhost-user 疎通に必要な設定として一般化するものではありません。 設定後、Open vSwitch を再起動します。

systemctl restart openvswitch-switch

DPDK の初期化状態を確認します。

ovs-vsctl get Open_vSwitch . dpdk_initialized
ovs-vsctl get Open_vSwitch . dpdk_version

今回の結果は次のとおりです。

true
"DPDK 25.11.0"

–vhost-owner と –vhost-perm は使用できなかった

当初、DPDK の追加引数として次の設定も試しました。

dpdk-extra="--vhost-owner libvirt-qemu:kvm --vhost-perm 0660"

しかし、DPDK 25.11.0 では次のエラーが発生しました。

ARGPARSE: unknown argument --vhost-owner!

このエラーにより、 ovs-vswitchd は起動に失敗し、systemd による再起動を繰り返しました。

ovs-vswitchd.service: Start request repeated too quickly.
ovs-vswitchd.service: Failed with result 'exit-code'.

--vhost-owner--vhost-perm を削除した後、 ovs-vswitchd は正常に起動しました。 今回採用した dpdkvhostuserclient 構成では、QEMU が vhost-user socket を作成し、OVS が client として接続します。そのため、今回の構成ではこれらの引数を使用せずに接続できました。

確認できた事実は、Ubuntu 26.04 の DPDK 25.11.0 環境では、少なくとも --vhost-owner が DPDK の引数として受理されなかったということです。

検証用の OVS-DPDK bridge を作成する

検証用 bridge を datapath_type=netdev として作成します。

ovs-vsctl add-br br-dpdk-test \
  -- set Bridge br-dpdk-test datapath_type=netdev

状態を確認します。

ovs-vsctl list Bridge br-dpdk-test

実際の結果では、次の値が確認できました。

name : br-dpdk-test
datapath_type : netdev

既存 bridge はそのまま残っています。

Bridge brphys0
Bridge br-dpdk-test
 datapath_type: netdev
Bridge br-int
 datapath_type: system

これにより、同じ OVS 環境内で、既存の system datapath bridge と検証用の netdev datapath bridge を共存させられることを確認しました。

vhost-user-client port を作成する

2 台の VM に対応する vhost-user port を作成します。

ovs-vsctl add-port br-dpdk-test vhost-user-test0 \
  -- set Interface vhost-user-test0 \
  type=dpdkvhostuserclient \
  options:vhost-server-path=/run/libvirt/qemu/vhost-user-test0
ovs-vsctl add-port br-dpdk-test vhost-user-test1 \
  -- set Interface vhost-user-test1 \
  type=dpdkvhostuserclient \
  options:vhost-server-path=/run/libvirt/qemu/vhost-user-test1

実際の OVSDB では次のように確認できます。

Port vhost-user-test0
 Interface vhost-user-test0
 type: dpdkvhostuserclient
 options: {
 vhost-server-path="/run/libvirt/qemu/vhost-user-test0"
 }

Port vhost-user-test1
 Interface vhost-user-test1
 type: dpdkvhostuserclient
 options: {
 vhost-server-path="/run/libvirt/qemu/vhost-user-test1"
 }

dpdkvhostuserclient では、OVS が client として動作します。 vhost-server-path には、QEMU が server として作成する Unix domain socket のパスを指定します。

socket path 変更後に接続しない場合

検証中に vhost-server-path を変更したところ、設定値を変更しただけでは接続が回復しない状態が発生しました。 今回の環境では、該当 port を削除して再作成することで復旧しました。

ovs-vsctl del-port br-dpdk-test vhost-user-test0
ovs-vsctl add-port br-dpdk-test vhost-user-test0 \
  -- set Interface vhost-user-test0 \
  type=dpdkvhostuserclient \
  options:vhost-server-path=/run/libvirt/qemu/vhost-user-test0

これは今回の OVS 3.7.1 環境で確認した挙動です。すべての環境で port の再作成が必須という意味ではありませんが、接続が回復しない場合の対処方法として有効でした。

検証用 VM を作成する

既存の Ubuntu テンプレートディスクから、2 台の linked clone を作成しました。 元のテンプレートは次のファイルです。

/var/lib/libvirt/images/ubuntu-template-40g.qcow2

作成したディスクは次のとおりです。

/var/lib/libvirt/images/ovs-dpdk-test0.qcow2
/var/lib/libvirt/images/ovs-dpdk-test1.qcow2

作成した VM は次の 2 台です。

ovs-dpdk-test0
ovs-dpdk-test1

VM の主な条件は次のとおりです。

項目設定
メモリー1024MiB
vCPU1
CPU modehost-passthrough
メモリーHugePages を使用
NICvhost-user
NIC modelvirtio
consoleserial console
graphicsなし

OVS-DPDK 側から QEMU のゲストメモリーへアクセスするため、VM のメモリーは共有可能な HugePages 上へ配置しました。 libvirt XML の主な設定は次のとおりです。

<memoryBacking>
 <hugepages/>
 <access mode='shared'/>
</memoryBacking>

vhost-user インターフェースは、QEMU を server とするため mode='server' で定義します。 ovs-dpdk-test0 の例は次のとおりです。

<interface type='vhostuser'>
 <mac address='52:54:00:5b:af:ad'/>
 <source type='unix'
 path='/run/libvirt/qemu/vhost-user-test0'
 mode='server'/>
 <model type='virtio'/>
</interface>

ovs-dpdk-test1 では、socket path と MAC アドレスを変更します。

<interface type='vhostuser'>
 <mac address='52:54:00:12:e4:26'/>
 <source type='unix'
 path='/run/libvirt/qemu/vhost-user-test1'
 mode='server'/>
 <model type='virtio'/>
</interface>

実際の QEMU 起動引数では、HugePages と共有メモリーが次のように設定されていました。

-object {
 "qom-type":"memory-backend-file",
 "mem-path":"/dev/hugepages/libvirt/qemu/...",
 "share":true,
 "prealloc":true,
 "size":1073741824
}

vhost-user インターフェースは次の構成です。

-chardev socket,
 id=charnet0,
 path=/run/libvirt/qemu/vhost-user-test0,
 server=on

-netdev {
 "type":"vhost-user",
 "chardev":"charnet0",
 "id":"hostnet0"
}

-device {
 "driver":"virtio-net-pci",
 "netdev":"hostnet0",
 "mac":"52:54:00:5b:af:ad"
}

接続関係は次のとおりです。

QEMU
 └─ vhost-user server
 └─ Unix domain socket
 └─ OVS dpdkvhostuserclient

ゲスト OS の IP アドレスを設定する

VM 起動前に、clone ディスク内の netplan を変更しました。 ovs-dpdk-test0 では次の設定を使用しています。

network:
  version: 2
  ethernets:
    dpdk0:
      match:
        macaddress: "52:54:00:5b:af:ad"
      set-name: dpdk0
      addresses:
        - 192.0.2.10/24
      dhcp4: false
      dhcp6: false

ovs-dpdk-test1 では次の設定を使用しています。

network:
  version: 2
  ethernets:
    dpdk0:
      match:
        macaddress: "52:54:00:12:e4:26"
      set-name: dpdk0
      addresses:
        - 192.0.2.11/24
      dhcp4: false
      dhcp6: false

ここで使用している dpdk0 は、ゲスト OS 上のインターフェース名です。ゲスト内で DPDK を使用しているという意味ではありません。 netplan の設定ファイルは次の権限に変更しました。

chmod 0600 /etc/netplan/00-installer-config.yaml

また、検証用 VM では systemd-networkd-wait-online.service を disable および mask しました。

systemctl disable systemd-networkd-wait-online.service
systemctl mask systemd-networkd-wait-online.service

これらの変更は、今回作成した検証用 clone ディスクだけに適用しています。

ホスト側に IP アドレスを設定する

ホストから VM へ疎通確認するため、 br-dpdk-test へ IP アドレスを設定しました。

ip link set br-dpdk-test up
ip address add 192.0.2.1/24 dev br-dpdk-test

実際の状態は次のとおりです。

br-dpdk-test:
 state UNKNOWN
 mtu 1500
 inet 192.0.2.1/24

ルーティングテーブルには、接続ルートが追加されています。

192.0.2.0/24 dev br-dpdk-test
 proto kernel
 scope link
 src 192.0.2.1

OVS の internal port は物理インターフェースのような carrier 状態を持たないため、 state UNKNOWN と表示される場合があります。今回の疎通には問題ありませんでした。 なお、この IP アドレスは ip address add で設定した一時的な値です。OS 再起動後にも維持するには、別途永続設定が必要です。

VM を起動する

2 台の VM を起動します。

virsh start ovs-dpdk-test0
virsh start ovs-dpdk-test1

実際の起動結果は次のとおりです。

Domain 'ovs-dpdk-test0' started
Domain 'ovs-dpdk-test1' started

QEMU が起動すると、次の socket が作成されます。

/run/libvirt/qemu/vhost-user-test0
/run/libvirt/qemu/vhost-user-test1

OVS はこれらの socket へ client として接続します。

vhost-user の接続を確認する

VM 起動中の OVS ログでは、vhost-user 接続の成立を確認できました。

VHOST_CONFIG: (/run/libvirt/qemu/vhost-user-test0) connected
VHOST_CONFIG: (/run/libvirt/qemu/vhost-user-test0) new device

続いて、vhost-user protocol feature のネゴシエーションが行われています。

VHOST_USER_GET_FEATURES
VHOST_USER_GET_PROTOCOL_FEATURES
VHOST_USER_SET_PROTOCOL_FEATURES

vring も有効化されています。

VHOST_USER_SET_VRING_ENABLE
set queue enable: 1 to qp idx: 0
set queue enable: 1 to qp idx: 1

さらに、ゲストメモリーの共有と virtio device の準備完了を確認できました。

VHOST_USER_SET_MEM_TABLE
guest memory region size: 0x40000000
virtio is now ready for processing.
vHost Device '/run/libvirt/qemu/vhost-user-test0'
has been added on numa node 0

test1 側でも同様のログを確認しています。 これにより、単に Unix domain socket へ接続しただけではなく、feature negotiation、ゲストメモリー共有、vring 設定、virtio device の処理開始まで完了したことが分かります。

VM 停止後は disconnected になる

VM を停止すると、QEMU が作成していた socket も削除されます。 OVS ログでは次のように記録されました。

vhost peer closed
connection has been destroyed
failed to connect: No such file or directory
reconnecting...

VM 停止後に取得した OVS interface の状態は次のとおりです。

link_state : down
status : {
 mode=client,
 status=disconnected
}

これは異常ではありません。 dpdkvhostuserclient では QEMU が server として socket を作成するため、VM が停止して socket が存在しなくなると、OVS 側は down および disconnected になります。 したがって、接続確認では、VM 起動中の OVS ログと、停止後の OVSDB 状態を区別して確認する必要があります。

PMD thread を確認する

今回の設定では、PMD thread を CPU 5 へ割り当てています。

pmd-cpu-mask="0x20"

PMD の統計を確認します。

ovs-appctl dpif-netdev/pmd-stats-show

実際の結果は次のとおりです。

pmd thread numa_id 0 core_id 5:
 packets received: 119
 packet recirculations: 0
 avg. datapath passes per packet: 1.00
 idle cycles: 9404624953260 (100.00%)
 processing cycles: 17720348 (0.00%)

この結果から、次のことを確認できます。

  • PMD thread は NUMA node 0、CPU 5 で動作している
  • PMD は実際に 119 packet を受信した
  • トラフィックが非常に少ないため、累積 cycle のほぼすべてが idle として表示されている
  • processing cycles も実際には記録されている

表示上は processing cycles: 0.00% ですが、実際の値はゼロではありません。全体に占める割合が極めて小さいため、小数点以下の表示で 0.00%になっています。 今回の目的は性能測定ではないため、この値を転送性能の評価には使用していません。PMD thread が指定した CPU 上で動作し、実際にパケットを処理したことの確認に使用しています。

ホストから各 VM への疎通を確認する

ホストの br-dpdk-test から、ovs-dpdk-test0 へ ping を実行しました。

ping -c 3 -W 2 192.0.2.10

結果は次のとおりです。

3 packets transmitted, 3 received, 0% packet loss
rtt min/avg/max/mdev = 0.162/0.228/0.316/0.064 ms

ovs-dpdk-test1 についても同様に確認しました。

ping -c 3 -W 2 192.0.2.11

結果は次のとおりです。

3 packets transmitted, 3 received, 0% packet loss
rtt min/avg/max/mdev = 0.170/0.273/0.464/0.134 ms

これにより、次の経路が成立していることを確認できました。

ホスト Linux IP stack
 ↓
br-dpdk-test internal port
 ↓
OVS-DPDK userspace datapath
 ↓
dpdkvhostuserclient
 ↓
vhost-user socket
 ↓
QEMU virtio-net
 ↓
ゲスト Linux IP stack

この ping 結果は、構成と疎通の成立を確認するためのものです。DPDK の性能を評価する数値ではありません。

検証中に発生した問題

今回の検証で発生した、OVS-DPDK と vhost-user に直接関係する問題を整理します。

現象原因または状況対処
DPDK not supported が出る通常版 ovs-vswitchd が起動していたDPDK 対応版へ alternative を切り替えた
--vhost-owner が unknown argument になるDPDK 25.11.0 で引数として受理されなかったdpdk-extra から削除した
socket path 変更後に接続しない設定変更だけでは接続が回復しなかったOVS port を削除して再作成した
VM 停止後に interface が down になるQEMU が server socket を削除するため正常な停止後状態として扱った
PMD 統計がほぼ idle になる疎通確認程度の少量トラフィックだったPMD の配置と packet 受信数を確認した

検証後の状態

疎通確認後、検証用 VM は停止しました。

virsh destroy ovs-dpdk-test0
virsh destroy ovs-dpdk-test1

ホストには次の構成が残っています。

  • openvswitch-switch-dpdk パッケージ
  • DPDK 対応版 ovs-vswitchd の alternative 設定
  • OVS の DPDK 関連 other_config
  • br-dpdk-test
  • vhost-user-test0
  • vhost-user-test1
  • 検証用 VM 定義
  • 検証用 VM ディスク
  • br-dpdk-test192.0.2.1/24

既存の構成管理には変更を加えていません。 ただし、構成管理を変更していないことと、ホストの構成が変更されていないことは別です。現在の状態は構成管理の管理外で追加した構成であり、構成管理上はドリフトになります。 検証構成を継続して使用する場合は、今後 Ansible の管理対象へ取り込む必要があります。検証を終了する場合は、追加した bridge、port、VM、ディスク、OVS 設定、alternative 設定を元へ戻します。

まとめ

今回の検証では、Ubuntu 26.04 上で OVS-DPDK と vhost-user を使用した最小構成を作成しました。物理 NIC を DPDK へ bind せず、既存の system datapath bridge を維持したまま、検証用の netdev bridge を追加しています。

QEMU を vhost-user server、OVS を dpdkvhostuserclient として接続し、vhost-user インターフェースを持つ 2 台の KVM VM を起動しました。その上で、vhost-user socket への接続、feature negotiation、ゲストメモリー共有、vring の有効化、PMD thread によるパケット受信、ホストから VM への ping 疎通を確認しています。

実際のログでは、次の処理を確認できました。

  • vhost-user socket への接続
  • protocol feature のネゴシエーション
  • virtio feature のネゴシエーション
  • ゲストメモリー情報の共有
  • vring の設定と有効化
  • virtio is now ready for processing
  • PMD thread によるパケット受信

最終的に、ホストから各 VM への ping 疎通を確認しました。今回確認した構成は次のとおりです。

既存 OVS 環境
  ├─ system datapath bridge
  │    ├─ br-int
  │    └─ brphys0
  │
  └─ netdev datapath bridge
       └─ br-dpdk-test
            ├─ internal port
            │    └─ ホスト Linux IP stack
            │
            ├─ dpdkvhostuserclient
            │    └─ QEMU vhost-user server
            │         └─ virtio-net VM
            │
            └─ dpdkvhostuserclient
                 └─ QEMU vhost-user server
                      └─ virtio-net VM

この結果から、物理 NIC を使用しない閉じた環境でも、OVS-DPDK、vhost-user、QEMU / KVM を組み合わせた基本構成を作成できることを確認しました。性能比較、物理 NIC を使用した外部通信、VM 相互間の通信、ゲスト内 DPDK は今回の対象には含めていません。

この記事の結論は、Ubuntu 26.04 上で OVS-DPDK と vhost-user の基本構成を作成し、ホストと vhost-user VM 間の疎通を確認できたという範囲に限定されます。DPDK を使えば必ず速くなる、または物理 NIC を含む本番構成まで確認できた、という意味ではありません。

関連する記事
Ubuntu 26.04 OVS-DPDK と vhost-user の基本構成 – 物理 NIC なしで KVM VM との疎通を確認する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トップへ戻る