なかなか実機ではテストするのがめんどくさいので、VirtualBoxでDPDKのサンプルをビルドして動かすところまでやってみます。
仮想マシンの作成
VirtualBoxで仮想マシンを作成する、この時注意することがいくつかあります。
- CPUは2コア以上にする
- メモリは4GB以上にする
- NICは3つ用意する
- 1杖のNICはインターネット接続用、デフォルトのままでOK
- 2,3枚目のNICはDPDK動かす用、詳細から種類として
Intel PRO/1000 MT Server (82545EM)
を選択すること
OSインストール
Ubuntu Server 16.04を普通にISOからインストールします。
aptで開発環境として必要そうなものをインストールしておきます。
sudo apt-get install build-essential
DPDKのインストール
aptではいるらしい。
sudo apt-get install dpdk dpdk-dev dpdk-doc libdpdk-dev
各種設定
HUGEPAGE
編集して、
GRUB_CMDLINE_LINUX="hugepages=1024"
反映。
sudo grub-mkconfig -o /boot/grub/grub.cfg
fstabも編集して、
nodev /mnt/huge hugetlbfs defaults 0 0
ディレクトリ作成して再起動。
sudo mkdir /mnt/huge
sudo reboot
DPDKで使うNICの設定
DPDKとNICのバインドはスクリプト /usr/share/dpdk/tools/dpdk_nic_bind.py
で行います。
まず、現在の設定を確認しましょう。
sudo insmod /lib/modules/4.4.0-31-generic/kernel/drivers/uio/uio_pci_generic.ko
/usr/share/dpdk/tools/dpdk_nic_bind.py --status
Network devices using DPDK-compatible driver
============================================
<none>
Network devices using kernel driver
===================================
0000:00:03.0 'Virtio network device' if= drv=virtio-pci unused=
0000:00:08.0 '82545EM Gigabit Ethernet Controller (Copper)' if=enp0s8 drv=e1000 unused=uio_pci_generic
0000:00:09.0 '82545EM Gigabit Ethernet Controller (Copper)' if=enp0s9 drv=e1000 unused=uio_pci_generic
Other network devices
=====================
<none>
まだ何も設定されていないことがわかります。
そこで、2つのIntel NICをDPDKにバインドしてみましょう。
/usr/share/dpdk/tools/dpdk_nic_bind.py --bind=uio_pci_generic 0000:00:08.0
/usr/share/dpdk/tools/dpdk_nic_bind.py --bind=uio_pci_generic 0000:00:09.0
もう一度状態を確認すると、DPDKにバインドされてることがわかります。
/usr/share/dpdk/tools/dpdk_nic_bind.py --status
Network devices using DPDK-compatible driver
============================================
0000:00:08.0 '82545EM Gigabit Ethernet Controller (Copper)' drv=uio_pci_generic unused=e1000
0000:00:09.0 '82545EM Gigabit Ethernet Controller (Copper)' drv=uio_pci_generic unused=e1000
Network devices using kernel driver
===================================
0000:00:03.0 'Virtio network device' if= drv=virtio-pci unused=uio_pci_generic
Other network devices
=====================
<none>
インターフェースの永続化
設定を永続化するには、ファイルに記載しておきます。
pci 0000:00:08.0 uio_pci_generic
pci 0000:00:09.0 uio_pci_generic
サンプルファイルのビルド
cp -R /usr/share/dpdk/examples ~/dpdk-examples
cd ~/dpdk-examples/helloworld/
source /usr/share/dpdk/dpdk-sdk-env.sh
make
CC main.o
LD helloworld
/usr/bin/ld: -lpcap が見つかりません
/usr/bin/ld: -lxenstore が見つかりません
collect2: error: ld returned 1 exit status
/usr/share/dpdk//mk/rte.app.mk:221: ターゲット 'helloworld' のレシピで失敗しました
make[1]: *** [helloworld] エラー 1
/usr/share/dpdk//mk/rte.extapp.mk:42: ターゲット 'all' のレシピで失敗しました
make: *** [all] エラー 2
パッケージが足りないようなのでインストールしてやり直します。
sudo apt-get install libpcap-dev libxen-dev
make
今度は通りました。
実行してみます。root権限が必要です。
sudo ./build/helloworld
EAL: PCI device 0000:00:03.0 on NUMA socket -1
EAL: probe driver: 1af4:1000 rte_virtio_pmd
PMD: device not available for DPDK (in use by kernel)
EAL: Error - exiting with code: 1
Cause: Requested device 0000:00:03.0 cannot be used
あれ?動かない...掴んで欲しくないNICをつかもうとしてます。
コマンドライン引数で、ブラックリストを指定できるという情報を得たので、再チャレンジ。
sudo ./build/helloworld -b 0000:00:03.0
EAL: Master lcore 0 is ready (tid=177968c0;cpuset=[0])
EAL: lcore 1 is ready (tid=937fe700;cpuset=[1])
EAL: PCI device 0000:00:03.0 on NUMA socket -1
EAL: probe driver: 1af4:1000 rte_virtio_pmd
EAL: Device is blacklisted, not initializing
EAL: PCI device 0000:00:08.0 on NUMA socket -1
EAL: probe driver: 8086:100f rte_em_pmd
EAL: PCI memory mapped at 0x7f5114c00000
PMD: eth_em_dev_init(): port_id 0 vendorID=0x8086 deviceID=0x100f
EAL: PCI device 0000:00:09.0 on NUMA socket -1
EAL: probe driver: 8086:100f rte_em_pmd
EAL: PCI memory mapped at 0x7f5114c20000
PMD: eth_em_dev_init(): port_id 1 vendorID=0x8086 deviceID=0x100f
hello from core 1
hello from core 0
今度はNIC2つを掴んで成功です!
コマンドライン引数の正体
helloworld/main.c
ではコマンドライン引数の処理をしてないように見えますが、
ret = rte_eal_init(argc, argv);
ここで、EALを初期化するときにコマンドラインオプションが色々渡せるようになっています。
渡せるオプションはたくさんあって、DPDKのドキュメントにも載っていました。
http://dpdk.org/doc/guides/testpmd_app_ug/run_app.html