読者です 読者をやめる 読者になる 読者になる

仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

Ubuntu Xenial (16.04) でOpen vSwitch+DPDKな環境を作る(前編)

Open vSwitch+DPDKが今、熱いようです。

早速、Ubuntu XenialでOpen vSwitch+DPDKな環境を作ってみることにしました。

次のバージョンのUbuntuを使って動作確認しました。

$ cat /proc/version_signature
Ubuntu 4.4.0-53.74-generic 4.4.30
$ cat /etc/lsb-release |grep DISTRIB_DESCRIPTION
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

NICの確認

まずは動かそうとしているサーバーに対応するNICが実装されていることを確認します。 なお、NICによってサポートしている機能に差があるため、使おうとしている機能がそのNICで使えることを確認してください。

PPAの追加

Ubuntu XenialのOVSはバージョン2.5がサポートされます。より新しいバージョンのOVSをUbuntuで使うには、OpenStackのリポジトリー「CloudArchive」にあるパッケージを使うと便利です。次のコマンドを実行します。

Newtonより新しいバージョンのOpenStackが提供された場合はより新しいバージョンを指定してください。

# add-apt-repository cloud-archive:newton
# apt-get update

インストール

次のようにコマンドを実行してDPDKとDPDK EnableなOVSをインストールします。 パッケージの依存関係で普通のOVSもインストールされるので、二個目のコマンドで切り替えています。

# apt-get install openvswitch-switch-dpdk dpdk
# update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk

NICのバインド

NIC用のドライバーをバインドするため、modprobeコマンドで読み込みます。

ex.

# modprobe uio_pci_generic 
or
# modprobe vfio-pci 

uio_pci_generic でも良い(パフォーマンスはでない)が、使える環境ならvfio-pciの方が良いようです。

また、e1000のように対応しているNICの場合はuio_pci_genericの代わりに、よりパフォーマンスの良いigb_uioを使うこともできます。Ubuntu Xenialではdpdk-igb-uio-dkmsパッケージの導入により、利用可能になります。

前の手順で読み込んだモジュールを再起動後も読み込むように/etc/modulesに書き込んでください。

# echo "uio_pci_generic" >> /etc/modules

モジュールについてはmodinfoコマンドで概要を確認できます。カーネルを更新すると新しいモジュールが利用できますので最新のものを使うことをおすすめします。Linuxカーネルの更新後は必ずシステムの再起動が必要です。

$ modinfo uio_pci_generic
filename:       /lib/modules/4.4.0-53-generic/kernel/drivers/uio/uio_pci_generic.ko
description:    Generic UIO driver for PCI 2.3 devices
author:         Michael S. Tsirkin <mst@redhat.com>
license:        GPL v2
version:        0.01.0
srcversion:     41BEEDE6B2A7E267E6CCD84
depends:        uio
intree:         Y
vermagic:       4.4.0-53-generic SMP mod_unload modversions

以降の手順は汎用的に利用可能なuio_pci_genericを使う例とします。

ネットワーク設定

管理用NIC以外はコメントアウトします。DPDKがネットワークを管轄するためです。 リモートアクセス用のNICとDPDK用のデバイスは別のものを用意するといいと思います。

# vi /etc/network/interfaces
auto eno1
iface eno1 inet static
address 172.16.214.100
netmask 255.255.0.0
gateway 172.16.0.1
dns-nameservers 8.8.8.8 8.8.4.4

#auto ens1f0
…
#auto ens1f1
…

OVS-DPDK関連の設定変更

まず、次のコマンドを実行してHugePagesを設定します。 ページサイズはのちに動かすアプリケーションに合わせたサイズを指定する必要があります。

# vi /etc/dpdk/dpdk.conf
#NR_2M_PAGES=64
↓
NR_2M_PAGES=6144
...

Linuxカーネルパラメーターへの記述

次のように実行して、カーネル起動後もIOMMUを有効にするためを入れておきます。 なお、uio_pci_genericを使う場合はこの設定は不要です。

# vi /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="iommu=pt intel_iommu=on"

vfio-pciを使う場合にはVT-dが必要なため、iommu=pt intel_iommu=on の記述が必要です。反映させるために次のように実行して、再起動します。

# update-grub && reboot

なお、HPEのサーバーでIOMMUを使うには、次の情報を確認して対応してください。 この対処を施した場合、IOMMUが利用可能になりますが、サーバー前面のステータスランプが警告表示(常時、赤ランプ点滅)になります。ちなみにDellのサーバーでは特に何をする必要もありませんでした。

デバイスの確認とバインド

まず、DPDKのバインド状況を確認します。

# dpdk-devbind --status

初期状態ではコマンドを実行すると次のような出力がされます。「Network devices using DPDK-compatible driver」がnoneと表示されるはずです。この状態ではDPDKがNICに対して有効化されていない状態です。

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:01:00.0 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno1 drv=bnx2 unused=uio_pci_generic *Active*
0000:01:00.1 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno2 drv=bnx2 unused=uio_pci_generic
0000:02:00.0 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno3 drv=bnx2 unused=uio_pci_generic
0000:02:00.1 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno4 drv=bnx2 unused=uio_pci_generic
0000:07:00.0 '82575GB Gigabit Network Connection' if=enp7s0f0 drv=igb unused=uio_pci_generic
0000:07:00.1 '82575GB Gigabit Network Connection' if=enp7s0f1 drv=igb unused=uio_pci_generic
0000:08:00.0 '82575GB Gigabit Network Connection' if=enp8s0f0 drv=igb unused=uio_pci_generic
0000:08:00.1 '82575GB Gigabit Network Connection' if=enp8s0f1 drv=igb unused=uio_pci_generic

Other network devices
=====================
<none>

Active」とステータスが出ているNICは別の処理で使用中のNICです。NetworkサービスでStaticなIPアドレスを割り当ててUPしているNICであるためです。Linux側で利用しているデバイスはDPDKドライバーを読み込むことはできません。

例えばuio_pci_genericとして、デバイス番号「0000:07:00.0」のNICをバインドするには次のように実行します。アンバインドするには-bオプションを-uに変えて実行してください。

# dpdk-devbind -b uio_pci_generic  0000:07:00.0

もう一度ステータスを確認すると次のように出力されるはずです。これで指定したデバイスでDPDK-compatible driverが読み込まれます。

# dpdk-devbind --status
...
Network devices using DPDK-compatible driver
============================================
0000:07:00.0 '82575GB Gigabit Network Connection' drv=uio_pci_generic unused=igb
...

DPDKモジュールの自動読み込みに関する設定

先の手順で手動でバインドしましたが、これは/etc/dpdk/interfacesに記述することで自動的にバインドさせることができます。次のように実行して、指定したデバイス番号のNICでDPDK対応ドライバーを利用するための設定を行っておきます。

# vi /etc/dpdk/interfaces
pci 0000:07:00.0 uio_pci_generic ←追記  

UEFIモードで起動しているシステムにUbuntuをインストールした場合、この方法で自動読み込みを設定するとうまく動かない可能性があります。BIOSアーキテクチャでは再起動後も正常に動作するようです。

DPDKとOVSのセットアップ

ここまでできたら、次にOVSの設定を行います。通常のようにOVSを使うのと異なり、いくつかオプションを指定します。以下のページの情報を参考にしましたが、次に実行するコマンドを列挙します。

Documentation/vhost-user-ovs-dpdk - QEMU

# mkdir -p /var/run/openvswitch
# mount -t hugetlbfs -o pagesize=2048k none /dev/hugepages

# modprobe openvswitch

# killall ovsdb-server ovs-vswitchd
# rm -f /var/run/openvswitch/vhost-user*
# rm -f /etc/openvswitch/conf.db

# export DB_SOCK=/var/run/openvswitch/db.sock
# ovsdb-tool create /etc/openvswitch/conf.db /usr/share/openvswitch/vswitch.ovsschema
# ovsdb-server --remote=punix:$DB_SOCK --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach

# ovs-vsctl --no-wait init
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xf
# ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0x2
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=1024
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
# ovs-vswitchd unix:$DB_SOCK --pidfile --detach --log-file=/var/log/openvswitch/ovs-vswitchd.log
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-extra="--vhost-owner libvirt-qemu:kvm --vhost-perm 0664"
# service openvswitch-switch restart

# ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
# ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
# ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser
# ovs-vsctl show
cd83e731-6786-4985-9102-25c874b87255
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "vhost-user2"
            Interface "vhost-user2"
                type: dpdkvhostuser
        Port "vhost-user1"
            Interface "vhost-user1"
                type: dpdkvhostuser

OVSにDPDKデバイスをバインドします。次のように実行します。

# ovs-vsctl add-port ovsbr0 dpdk0 -- set Interface dpdk0 type=dpdk
(物理デバイスを指定するのではなく、dpdk番号を指定する)

Interface "dpdk0"が追加されたことを確認します。

# ovs-vsctl show
cd83e731-6786-4985-9102-25c874b87255
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "vhost-user2"
            Interface "vhost-user2"
                type: dpdkvhostuser
        Port "vhost-user1"
            Interface "vhost-user1"
                type: dpdkvhostuser
        Port "dpdk0"
            Interface "dpdk0"   ←追加された
                type: dpdk

以上でUbuntu Server XenialにOpen vSwitch+DPDKをインストールできます。

再起動後の復旧

DPDKホストを再起動してしまうとDPDKとの関連づけが消えてしまうことがあります。この場合は次のコマンドを実行して復旧できます。これはおそらくUbuntu自体やUbuntuのパッケージングの問題ではないと思われます。

# dpdk-devbind -b uio_pci_generic 0000:07:00.0
# dpdk-devbind --status
# ovs-vsctl del-port ovsbr0 dpdk0
# service openvswitch-switch restart
# ovs-vsctl add-port ovsbr0 dpdk0 -- set Interface dpdk0 type=dpdk

DPDKドライバーの切り替え

-uオプションは稀に失敗するので、unbindせずに新しいドライバーをバインドすると上書きできるようです。

# ovs-vsctl del-port ovsbr0 dpdk0
# dpdk-devbind -b igb_uio 0000:07:00.0
# dpdk-devbind --status
Network devices using DPDK-compatible driver
============================================
0000:07:00.0 '82575GB Gigabit Network Connection' drv=igb_uio unused=igb,uio_pci_generic
...
# service openvswitch-switch restart
# ovs-vsctl add-port ovsbr0 dpdk0 -- set Interface dpdk0 type=dpdk

OVSパラメーターの追加

other_configでパラメータを追加してOVSを再起動すると良いようです。

# ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0x2
# service openvswitch-switch restart

後編に続きます。

tech.virtualtech.jp