現在位置: ホーム / みらくるブログ / #2 DPDK 17.02をCentOS 7.3で使う

#2 DPDK 17.02をCentOS 7.3で使う

第2回目の本稿では、CentOS 7.3にDPDKをインストールしてます。新しいバージョンのDPDKを使うためにソースからコンパイルします。前回Ubuntuベースで構築したマシンとのパケット対向実験も行います。

使用マシン

今回使用するマシンとOSのスペックを下記に記載します。

CPU Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
Memory DDR3-1600 8GB x4
DPDK用NIC Intel Corporation Ethernet Controller 10-Gigabit X540-AT2
OS CentOS 7.3
DPDK 17.02

DKDKのビルド

ビルドに必要なパッケージをインストールしておきます。

$ sudo yum install make gcc kernel-devel

執筆での最新版である17.02をインストールします。適当な作業ディレクトリで次のコマンドを実行します。オプション-O3については、最適化のために使用することを推奨しますが、-g3はデバッグオプションですので、GDBを用いてデバッグする予定がなければ不要です。

$ curl http://fast.dpdk.org/rel/dpdk-17.02.tar.xz | tar xJvf -
(出力結果省略)
$ cd  dpdk-17.02
$ sudo make install T=x86_64-native-linuxapp-gcc DESTDIR=/usr/local EXTRA_CFLAGS="-O3 -g3"

セットアップ

前回と同様にHuge Pagesの設定を行います。/etc/default/grubに次の設定を加えます。水色の部分が追加項目です。パラメータの意味は、前回の記事で解説した通りですが、今後、Open vSwitchやKVMなどでも利用を目論んでいるため、多めに1GiBページを確保しました。

GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet default_hugepagesz=1G hugepagesz=1G hugepages=16"

その後、設定を有効にします。

# grub2-mkconfig -o /boot/grub2/grub.cfg

また、起動時にカーネルモジュールがロードされるように、/etc/sysconfig/modules/igb_uio.modulesというファイルを作成し、次の内容を記載します。

#!/bin/sh

modprobe uio
insmod /usr/local/lib/modules/3.10.0-514.6.1.el7.x86_64/extra/dpdk/igb_uio.ko

実行属性も付与し、再起動します。

# chmod +x /etc/sysconfig/modules/igb_uio.modules

再起動後、以下のようにロードされていることを確認します。

$ lsmod | grep uio
igb_uio                13224  0
uio                    19259  1 igb_uio

また、Huge Pageが確保されていることも確認しておきます。

$ cat /proc/meminfo | grep ^Huge
HugePages_Total:      16
HugePages_Free:       16
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:    1048576 kB

対向実験

前回セットアップしたUbuntuベースのマシン1とし、今回セットアップしたマシンをマシン2として、以下の図のように接続にします。X540-AT2は、2つのポートを持っています。それぞれを対向するホストのポートに直結しました。

02-conn.png

NICがDPDK用にバインドされていない場合(本ブログの手順通りに作業すると、再起動後はバインドされていない状態です)、それぞれのマシンで次のようにNICをDPDK用にバインドします。--statusコマンドで、NICのリストを表示して、先頭に表示されるPCIバスアドレス(水色で表示)を確認します。

# /usr/local/sbin/dpdk-devbind --status

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

Network devices using kernel driver
===================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' if=enp1s0f0 drv=ixgbe unused=igb_uio
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' if=enp1s0f1 drv=ixgbe unused=igb_uio
0000:03:00.0 'RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller' if=enp3s0 drv=r8169 unused=igb_uio *Active*
(以下省略)

これらを次のコマンドでバインドします。引数の最後のアドレスには以下のように、複数のNICを列挙することができます。

# /usr/local/sbin/dpdk-devbind -b igb_uio 0000:01:00.0 0000:01:00.1

再度、バインド状態を確認すると、2つのNICがNetwork devices using DPDK-compatible driverに移動していることがわかります。

# /usr/local/sbin/dpdk-devbind --status

Network devices using DPDK-compatible driver
============================================
0000:01:00.0 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe
0000:01:00.1 'Ethernet Controller 10-Gigabit X540-AT2' drv=igb_uio unused=ixgbe

Network devices using kernel driver
===================================
0000:03:00.0 'RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller' if=enp3s0 drv=r8169 unused=igb_uio *Active*
(以下省略)

パケット転送

パケットの転送は、最初にホスト1で、パケットを生成してホスト2に送ります。以降は、以下の図のように2つのホスト間で循環的に転送が継続されます。02-conn-flow.png

まず、ホスト2で次のようにtestpmd(DPDK標準のパケット転送ツール)を起動し、startコマンドを実行します。startコマンドはパケット転送機能を有効にします。

# testpmd -- -i
(省略)
Port 0 Link Up - speed 10000 Mbps - full-duplex
Port 1 Link Up - speed 10000 Mbps - full-duplex
Done
testpmd> start
io packet forwarding - ports=2 - cores=1 - streams=2 - NUMA support disabled, MP over anonymous pages disabled
Logical Core 1 (socket 0) forwards packets on 2 streams:
  RX P=0/Q=0 (socket 0) -> TX P=1/Q=0 (socket 0) peer=02:00:00:00:00:01
  RX P=1/Q=0 (socket 0) -> TX P=0/Q=0 (socket 0) peer=02:00:00:00:00:00
(省略)

上記の表示されたメッセージでの着目すべきところを水色にしています。水色で表示したcore=1は転送を1つのCPUコア(PMDスレッド)で行うという意味です。RX P=0/Q=0 -> TX P=1/Q=0は、Port 0のQueue 0に到達したパケットをPoart 1のQueue 0に転送するという意味です。RX P=1/Q=0 -> TX P=0/Q=0も同様です。Queueは、パケット入出力用のバッファですが、1つのポートに対して複数Queueを作成して性能を向上することができます。まずは、デフォルトのNICのポート1つにQueue 1つの構成で進めます。したがって、1つのPMDスレッドが2つのQueueをポーリングしていることになります。

続いて、ホスト1でもtestpmdを起動します。start tx_firstと入力します。tx_firstは、最初にパケット生成して送信するためのオプションです。10秒経過したあと、stopと入力します。

# testpmd -- -i
(省略)
testpmd> start tx_first
(省略)
10秒経過後
testpmd> stop
Telling cores to stop...
Waiting for lcores to finish...
testpmd> stop
Telling cores to stop...
Waiting for lcores to finish...


---------------------- Forward statistics for port 0 ----------------------
RX-packets: 10308311 RX-dropped: 0 RX-total: 10308311
TX-packets: 10298580 TX-dropped: 0 TX-total: 10298580
----------------------------------------------------------------------------


---------------------- Forward statistics for port 1 ----------------------
RX-packets: 10298580 RX-dropped: 0 RX-total: 10298580
TX-packets: 10308311 TX-dropped: 0 TX-total: 10308311
----------------------------------------------------------------------------
(以下省略)

また、ホスト2でもstopを実行します。

testpmd> stop
(以下省略)

上記のように筆者の環境では10秒で上記の送受信パケット数でしたので、おおよそ1.0Mpps (packets/sec.)の転送性能でした。testpmdは64バイトのパケットを送信するので、データ転送レートに換算すると約0.5Gbpsです。10Gbit NICのN/W帯域をフルに使っているわけではないことが分かります。これには、いくつか理由がありますが、次回以降で見ていきましょう。

なお、10Gbit NICで64バイトパケットをほぼ100%の効率で転送すると約7.6Gbpsになります。なお、この値が10Gbpsより小さいのは、Ethernetではプリアンブルやインターフレームギャップなどの実データ以外の情報も回線を使用するためです。

次回は、PMDスレッドの数やQueueを増やすことで転送性能の向上を行います。