CentOS7上でSPDKをビルドして、NVMe-oF(NVMe over Fabric) targetを構築しました。
1.環境
1-1.筐体1 NVMe over Fabric Target
筐体 : ProLiant DL360p Gen8
System ROM : P71 01/22/2018
NIC : Mellanox ConnectX-3pro MCX311A-XCCT
SSD : Samsung SSD 250GB 970 EVO M.2 Type2280 PCIe3.0×4 NVMe1.3
Adapter : GLOTRENDS M.2 PCIe NVMe or PCIe AHCI SSD to PCIe 3.0 x4 Adapter Card
OS : CentOS7.5(1804)
Kernel : 4.18.4-1.el7.elrepo.x86_64
Installed Environment Groups : Minimal Install
SPDK : v18.10-pre
DPDK : v18.05.0
1-2.筐体2 NVMe over Fabric Initiator
筐体 : ProLiant DL360p Gen8
System ROM : P71 01/22/2018
NIC : Mellanox ConnectX-3pro MCX311A-XCCT
OS : CentOS7.5(1804)
Kernel : 4.18.4-1.el7.elrepo.x86_64
Installed Environment Groups : Minimal Install
1-3.全体の構成
RoCEv2のフレームをPcapしたかったためTargetとInitiatorの間にスイッチを挟んでいますが、DAS(直結)構成でも大丈夫です。
1-4.全体の流れ
Kernelのアップグレード
事前準備
SPDKのビルド
SPDKのnvmf.conf設定
NVMe-oF Initiatorからのアクセス
2.Kernelのアップグレード
今回の構成ではRoCEv2を使用します。
RoCEv2を使用する場合、Kernel4.5以上でないとサポートされないため、ELRepoから最新のKernelにアップグレードします。
この作業はTargetおよびInitiatorの両方で行ってください。
2-2.Kernelのアップグレード
yum --enablerepo=elrepo-kernel install kernel-ml
最新Kernelのインストール*1
# awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
0 : CentOS Linux (4.18.4-1.el7.elrepo.x86_64) 7 (Core)
1 : CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)
2 : CentOS Linux (0-rescue-626b869879714a9cbe128e5b6f85dd89) 7 (Core)
# grub2-set-default 0
# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.18.4-1.el7.elrepo.x86_64
Found initrd image: /boot/initramfs-4.18.4-1.el7.elrepo.x86_64.img
Found linux image: /boot/vmlinuz-3.10.0-862.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-862.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-626b869879714a9cbe128e5b6f85dd89
Found initrd image: /boot/initramfs-0-rescue-626b869879714a9cbe128e5b6f85dd89.img
done
# reboot
menuentryを確認
初期起動Kernelに4.18.4-1.el7.elrepo.x86_64を選択
grub.cfgへの反映
再起動
なお、Initiatorはここまでで完了です。
Targetはspdkのビルドを行うため、この後のkernel-ml-develやkernel-ml-headersのインストールも行ってください。
2-3.既存Kernel削除とその他のアップグレード
uname -r
yum remove kernel
yum list installed | grep kernel
yum -y update kernel-tools-libs kernel-tools
yum list installed | grep kernel
起動Kernelのバージョン確認
既存Kernelの削除
現在インストールされているKernel関連のパッケージの確認
tools類のアップデート*2
現在インストールされているKernel関連のパッケージの再確認
2-5.tools類のアップグレードとdevel&headersのインストール
yum swap kernel-tools-libs kernel-tools -- kernel-ml-tools-libs kernel-ml-tools
yum -y install kernel-ml-devel kernel-ml-headers
yum list installed | grep kernel
kernel-*とkernel-ml-*のswap
kernel-ml-develとkernel-ml-headersのインストール
現在インストールされているKernel関連のパッケージの確認
# yum list installed | grep kernel
kernel-ml.x86_64 4.18.4-1.el7.elrepo @elrepo-kernel
kernel-ml-devel.x86_64 4.18.4-1.el7.elrepo @elrepo-kernel
kernel-ml-headers.x86_64 4.18.4-1.el7.elrepo @elrepo-kernel
kernel-ml-tools.x86_64 4.18.4-1.el7.elrepo @elrepo-kernel
kernel-ml-tools-libs.x86_64 4.18.4-1.el7.elrepo @elrepo-kernel
上記のような出力になっていれば完了です。
3.事前準備
3-1.セキュリティ設定の無効化
firewalldとSELinuxを無効化します。
systemctl disable firewalld
vi /etc/selinux/config
で開いて
SELINUX=disabled
にして保存。
grubにHugePageの設定追加
vi /etc/default/grub
GRUB_CMDLINE_LINUX=の行末に追加
default_hugepagesz=1G hugepagesz=1G hugepages=8
保存後、grubに反映
grub2-mkconfig -o /etc/grub2.cfg
nmcli devなどでMellanox製NICのデバイス名を確認の上、IPアドレスを設定してください。今回構築するNVMe-oF targetはRoCEv2で動作するため、NICにはIPアドレスが必要となります。
nmcli connection add type ethernet autoconnect yes con-name ens1 ifname ens1
nmcli connection modify ens1 ipv4.method manual ipv4.addresses 192.168.20.200/24
nmcli connection up ens1
3-4.numactl-develのインストール
dpdkがnumactl-develやopenssl-devel を必要とするようなのでインストール。
yum -y install numactl-devel openssl-devel
reboot
再起動後にHugePageを確認。
# cat /proc/meminfo | grep ^Huge
HugePages_Total: 8
HugePages_Free: 8
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
4.SPDKのビルド
4-1.gitインストールからspdkのビルドまで
以下を流し込んでください。
yum -y install git && \
cd /usr/src && \
git clone https://github.com/spdk/spdk && \
cd spdk && \
git submodule update --init && \
scripts/pkgdep.sh && \
./configure --with-rdma --enable-debug && \
make
gitインストール
/usr/srcにcd
spdkのソースをgitから取得
/usr/src/spdkにcd*3
アップデート
必要なパッケージのインストール
makeファイル生成
ビルド
iSCSI Targetと異なる点
--with-rdmaは必須となります。
また、nvmf_tgtを起動した際に「-L」オプションでDebugログが見れるようになるため、--enable-debugを追加しています。正常起動しているのか?固まっているのか?を見極めるためにも、あった方がいいかなと思います。
4-2.unittest.shの実行
ビルドが完了したら、最後に各モジュールのテストを実施してみてください。
./test/unit/unittest.sh
出力結果省略
=====================
All unit tests passed
=====================
WARN: lcov not installed or SPDK built without coverage!
WARN: neither valgrind nor ASAN is enabled!
多数の出力結果が表示されますが、最後に「All unit tests passed」と表示されればOKです。
Warringが2件表示されてますが、気にせず先に進んでください。
5.spdkのnvmf.confファイル設定
5-1.設定ファイルの作成
# cd /usr/src/spdk/app/nvmf_tgt
# vi nvmf.conf
[Global]
ReactorMask 0x0F
[Nvmf]
MaxQueuesPerSession 4
MaxQueueDepth 1024
AcceptorPollRate 10000
[Nvme]
TransportId "trtype:PCIe traddr:0000:04:00.0" Nvme0
RetryCount 4
TimeoutUsec 1
ActionOnTimeout None
AdminPollRate 100000
HotplugEnable No
[Subsystem1]
NQN nqn.2016-06.io.spdk:cnode1
Listen RDMA 192.168.20.200:4791
AllowAnyHost Yes
Host nqn.2016-06.io.spdk:init
SN SPDK00000000000001
Namespace Nvme0n1 1
ReactorMaskの掛け方は最後に詳細を記載したいと思います。
わからなければ、コメントアウトしても問題ありません。
TransportIdの確認方法
私の場合、Samsung SSD 250GB 970を使用したため、lspciで以下のようにgrepしました。
# lspci |grep Samsung
04:00.0 Non-Volatile memory controller: Samsung Electronics Co Ltd Device a808
SSDのbsf(bus slot function)番号が判明したら、頭にDomain番号「0000:」を付けてください。
サンプルconfがspdk/etc/spdk/nvmf.conf.inにあるので、これをコピーしてnvmf.confを作成してもよいと思います。
5-2.setup.shの起動
カーネル上での制御からSPDK(正確にはDPDK)上での制御に移行します。
ますはステータス確認から。
# cd /usr/src/spdk
# scripts/setup.sh status
Hugepages
node hugesize free / total
node0 1048576kB 8 / 8
node1 1048576kB 8 / 8
NVMe devices
BDF Numa Node Driver name Device name
0000:03:00.0 0 nvme nvme0
I/OAT DMA
BDF Numa Node Driver Name
0000:00:04.0 0 ioatdma
0000:20:04.0 1 ioatdma
0000:00:04.1 0 ioatdma
0000:20:04.1 1 ioatdma
0000:00:04.2 0 ioatdma
0000:20:04.2 1 ioatdma
0000:00:04.3 0 ioatdma
0000:20:04.3 1 ioatdma
0000:00:04.4 0 ioatdma
0000:20:04.4 1 ioatdma
0000:00:04.5 0 ioatdma
0000:20:04.5 1 ioatdma
0000:00:04.6 0 ioatdma
0000:20:04.6 1 ioatdma
0000:00:04.7 0 ioatdma
0000:20:04.7 1 ioatdma
virtio
BDF Numa Node Driver Name Device Name
現在はカーネル上のnvmeやioatdmaドライバで制御していることがわかります。
オプション無しでsetup.shを実行すると、uio_pci_genericに移行します。*4
# scripts/setup.sh
0000:03:00.0 (144d a808): nvme -> uio_pci_generic
0000:00:04.0 (8086 3c20): ioatdma -> uio_pci_generic
0000:20:04.0 (8086 3c20): ioatdma -> uio_pci_generic
0000:00:04.1 (8086 3c21): ioatdma -> uio_pci_generic
0000:20:04.1 (8086 3c21): ioatdma -> uio_pci_generic
0000:00:04.2 (8086 3c22): ioatdma -> uio_pci_generic
0000:20:04.2 (8086 3c22): ioatdma -> uio_pci_generic
0000:00:04.3 (8086 3c23): ioatdma -> uio_pci_generic
0000:20:04.3 (8086 3c23): ioatdma -> uio_pci_generic
0000:00:04.4 (8086 3c24): ioatdma -> uio_pci_generic
0000:20:04.4 (8086 3c24): ioatdma -> uio_pci_generic
0000:00:04.5 (8086 3c25): ioatdma -> uio_pci_generic
0000:20:04.5 (8086 3c25): ioatdma -> uio_pci_generic
0000:00:04.6 (8086 3c26): ioatdma -> uio_pci_generic
0000:20:04.6 (8086 3c26): ioatdma -> uio_pci_generic
0000:00:04.7 (8086 3c27): ioatdma -> uio_pci_generic
0000:20:04.7 (8086 3c27): ioatdma -> uio_pci_generic
以下のようになっていれば、OKです。
# scripts/setup.sh status
Hugepages
node hugesize free / total
node0 1048576kB 0 / 1
node1 1048576kB 0 / 1
NVMe devices
BDF Numa Node Driver name Device name
0000:03:00.0 0 uio_pci_generic -
I/OAT DMA
BDF Numa Node Driver Name
0000:00:04.0 0 uio_pci_generic
0000:20:04.0 1 uio_pci_generic
0000:00:04.1 0 uio_pci_generic
0000:20:04.1 1 uio_pci_generic
0000:00:04.2 0 uio_pci_generic
0000:20:04.2 1 uio_pci_generic
0000:00:04.3 0 uio_pci_generic
0000:20:04.3 1 uio_pci_generic
0000:00:04.4 0 uio_pci_generic
0000:20:04.4 1 uio_pci_generic
0000:00:04.5 0 uio_pci_generic
0000:20:04.5 1 uio_pci_generic
0000:00:04.6 0 uio_pci_generic
0000:20:04.6 1 uio_pci_generic
0000:00:04.7 0 uio_pci_generic
0000:20:04.7 1 uio_pci_generic
virtio
BDF Numa Node Driver Name Device Name
5-3.Targetプログラムの実行
/usr/src/spdkのパス上で以下を実行。
app/nvmf_tgt/nvmf_tgt -c app/nvmf_tgt/nvmf.conf
以下、出力結果。
# app/nvmf_tgt/nvmf_tgt -c app/nvmf_tgt/nvmf.conf
Starting SPDK v18.07-pre / DPDK 18.02.0 initialization...
[ DPDK EAL parameters: nvmf -c 0x0F --file-prefix=spdk_pid23820 ]
EAL: Detected 8 lcore(s)
EAL: Multi-process socket /var/run/.spdk_pid23820_unix
EAL: Probing VFIO support...
app.c: 530:spdk_app_start: *NOTICE*: Total cores available: 4
reactor.c: 718:spdk_reactors_init: *NOTICE*: Occupied cpu socket mask is 0x1
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 1 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 2 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 3 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 0 on socket 0
EAL: PCI device 0000:03:00.0 on NUMA socket 0
EAL: probe driver: 144d:a808 spdk_nvme
rdma.c:1454:spdk_nvmf_rdma_create: *ERROR*: rdma_create_event_channel() failed, No such device
Segmentation fault (core dumped)
初回起動時に赤文字のエラーを吐く場合は、一度サーバを再起動してみてください。
nvmf_tgtはフォアグラウンドで稼働してしまうため、上記出力(赤文字以外の出力)でプロンプトが停止したように見えますが、nvmf targetは正常に起動できています。
iscsi targetとは異なり、-b(バックグラウンド)オプションはないようです。
また、Debugオプションを使用したい場合、まずは-Lに指定可能な引数を確認するため、-hオプションでnvmf_tgtを起動してあげてください。
# app/nvmf_tgt/nvmf_tgt -h
app/nvmf_tgt/nvmf_tgt [options]
options:
-c config config file (default /usr/local/etc/nvmf/nvmf.conf)
-d disable coredump file enabling
-e mask tracepoint group mask for spdk trace buffers (default 0x0)
-g force creating just one hugetlbfs file
-h show this usage
-i shared memory ID (optional)
-m mask core mask for DPDK
-n channel number of memory channels used for DPDK
-p core master (primary) core for DPDK
-q disable notice level logging to stderr
-r RPC listen address (default /var/tmp/spdk.sock)
-s size memory size in MB for DPDK (default: all hugepage memory)
-u disable PCI access.
-w wait for RPCs to initialize subsystems
-B addr pci addr to blacklist
-R unlink huge files after initialization
-W addr pci addr to whitelist (-B and -W cannot be used at the same time)
-L flag enable debug log flag (all, aio, bdev, bdev_malloc, bdev_null, bdev_nvme, blob, blob_rw, copy_ioat, gpt_parse, ioat, log, lvol, lvolrpc, nbd, nvme, nvmf, rdma, reactor, rpc, vbdev_gpt, vbdev_lvol, vbdev_passthru, vbdev_split, virtio, virtio_blk, virtio_dev, virtio_pci, virtio_user)
実際にDebugオプションを付けて起動した場合は、こんな感じです。
このように起動した後、Initiatorからアクセスすると、Targetの動きがわかります。
# app/nvmf_tgt/nvmf_tgt -L nvme -L nvmf -L rdma -c app/nvmf_tgt/nvmf.conf
6.NVMe-oF Initiatorからのアクセス
6-1.Initiator側の事前準備
Initiatorのインストール
yum -y install nvme-cli
modprobe実施
modprobe ib_core
modprobe ib_umad
modprobe ib_uverbs
modprobe iw_cm
modprobe rdma_cm
modprobe rdma_ucm
modprobe mlx4_core
modprobe mlx4_ib
modprobe nvme_rdma
上記のmodprobeが正常終了していれば、以下のように/dev/nvme-fabricsが追加されているハズです。
# ls /dev/
autofs fuse net rtc tty13 tty30 tty48 tty8 vcs6
block hpet network_latency rtc0 tty14 tty31 tty49 tty9 vcsa
bsg hpilo network_throughput sda tty15 tty32 tty5 ttyS0 vcsa1
btrfs-control hugepages null sda1 tty16 tty33 tty50 ttyS1 vcsa2
bus hwrng nvme-fabrics sda2 tty17 tty34 tty51 ttyS2 vcsa3
centos infiniband nvram sg0 tty18 tty35 tty52 ttyS3 vcsa4
char initctl port sg1 tty19 tty36 tty53 uhid vcsa5
console input ppp shm tty2 tty37 tty54 uinput vcsa6
core ipmi0 ptmx snapshot tty20 tty38 tty55 urandom vfio
cpu kmsg ptp0 snd tty21 tty39 tty56 usbmon0 vga_arbiter
cpu_dma_latency kvm ptp1 stderr tty22 tty4 tty57 usbmon1 vhci
cuse lightnvm ptp2 stdin tty23 tty40 tty58 usbmon2 vhost-net
disk log ptp3 stdout tty24 tty41 tty59 usbmon3 vhost-vsock
dm-0 loop-control ptp4 tty tty25 tty42 tty6 vcs watchdog
dm-1 mapper ptp5 tty0 tty26 tty43 tty60 vcs1 watchdog0
dri mcelog ptp6 tty1 tty27 tty44 tty61 vcs2 zero
fb0 mem pts tty10 tty28 tty45 tty62 vcs3
fd memory_bandwidth random tty11 tty29 tty46 tty63 vcs4
full mqueue raw tty12 tty3 tty47 tty7 vcs5
Discover実施Initiator側
# nvme discover -t rdma -a 192.168.20.200 -s 4791
Discovery Log Number of Records 1, Generation counter 4
=====Discovery Log Entry 0======
trtype: rdma
adrfam: ipv4
subtype: nvme subsystem
treq: not specified
portid: 0
trsvcid: 4791
subnqn: nqn.2016-06.io.spdk:cnode1
traddr: 192.168.20.200
rdma_prtype: not specified
rdma_qptype: connected
rdma_cms: rdma-cm
rdma_pkey: 0x0000
Discover実施Target側
# app/nvmf_tgt/nvmf_tgt -L nvmf -c app/nvmf_tgt/nvmf.conf
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x01 cid 1
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbeee9c800 key 0x10110 len 0x400
ctrlr.c: 321:spdk_nvmf_ctrlr_connect: *INFO*: recfmt 0x0 qid 0 sqsize 31
ctrlr.c: 323:spdk_nvmf_ctrlr_connect: *INFO*: Connect data:
ctrlr.c: 324:spdk_nvmf_ctrlr_connect: *INFO*: cntlid: 0xffff
ctrlr.c: 332:spdk_nvmf_ctrlr_connect: *INFO*: hostid: 0259e14b-3479-4850-be97-f6006ffa084c ***
ctrlr.c: 349:spdk_nvmf_ctrlr_connect: *INFO*: subnqn: "nqn.2014-08.org.nvmexpress.discovery"
ctrlr.c: 366:spdk_nvmf_ctrlr_connect: *INFO*: hostnqn: "nqn.2014-08.org.nvmexpress:uuid:eb63ddbc-c01f-4435-8e0b-bbbaf22639f2"
ctrlr.c: 389:spdk_nvmf_ctrlr_connect: *INFO*: Connect Admin Queue for controller ID 0xffff
ctrlr.c: 207:spdk_nvmf_ctrlr_create: *INFO*: cap 0x20010103ff
ctrlr.c: 208:spdk_nvmf_ctrlr_create: *INFO*: vs 0x10300
ctrlr.c: 209:spdk_nvmf_ctrlr_create: *INFO*: cc 0x0
ctrlr.c: 210:spdk_nvmf_ctrlr_create: *INFO*: csts 0x0
ctrlr.c: 104:ctrlr_add_qpair_and_update_rsp: *INFO*: connect capsule response: cntlid = 0x0001
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=1 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 26
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x460001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00000000
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00460001
ctrlr.c: 449:nvmf_prop_set_cc: *INFO*: Property Set CC Enable!
ctrlr.c: 480:nvmf_prop_set_cc: *INFO*: Prop Set IOSQES = 6 (64 bytes)
ctrlr.c: 487:nvmf_prop_set_cc: *INFO*: Prop Set IOCQES = 4 (16 bytes)
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x1
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x8
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: vs
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x10300
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00010300 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 26 nsid 0 cdw10 0x00000001
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc026a1000 key 0x10111 len 0x1000
ctrlr.c:1172:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ctrlr data: maxcmd 0x400
ctrlr.c:1173:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: sgls data: 0x100005
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x02 fuse 0 cid 26 nsid 0 cdw10 0x00030070
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc09c46000 key 0x10112 len 0x10
ctrlr.c:1082:spdk_nvmf_ctrlr_get_log_page: *INFO*: Get log page: LID=0x70 offset=0x0 len=0x10
ctrlr_discovery.c: 63:nvmf_update_discovery_log: *INFO*: Generating log page for genctr 4
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x02 fuse 0 cid 26 nsid 0 cdw10 0x01ff0070
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbdc640000 key 0x10113 len 0x800
ctrlr.c:1082:spdk_nvmf_ctrlr_get_log_page: *INFO*: Get log page: LID=0x70 offset=0x0 len=0x800
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 8
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x464001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00460001
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00464001
ctrlr.c: 463:nvmf_prop_set_cc: *INFO*: Property Set CC Shutdown 01b!
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=8 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 8
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x8
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=8 cdw0=0x00000008 rsvd1=0 status=0x0000
Connect実施Initiator側
iSCSIのときとは違い、Successなどは出力されません。
# nvme connect -t rdma -n nqn.2016-06.io.spdk:cnode1 -a 192.168.20.200 -s 4791
Connect実施Target側
Connectが完了すると、定期的にKeepaliveメッセージが流れます。
# nvme connect -t rdma -n nqn.2016-06.io.spdk:cnode1 -a 192.168.20.200 -s 4791
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x01 cid 0
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbeee99000 key 0x10111 len 0x400
ctrlr.c: 321:spdk_nvmf_ctrlr_connect: *INFO*: recfmt 0x0 qid 0 sqsize 31
ctrlr.c: 323:spdk_nvmf_ctrlr_connect: *INFO*: Connect data:
ctrlr.c: 324:spdk_nvmf_ctrlr_connect: *INFO*: cntlid: 0xffff
ctrlr.c: 332:spdk_nvmf_ctrlr_connect: *INFO*: hostid: 07ca1c45-8f62-493f-a732-7fd3c721f6f9 ***
ctrlr.c: 349:spdk_nvmf_ctrlr_connect: *INFO*: subnqn: "nqn.2016-06.io.spdk:cnode1"
ctrlr.c: 366:spdk_nvmf_ctrlr_connect: *INFO*: hostnqn: "nqn.2014-08.org.nvmexpress:uuid:eb63ddbc-c01f-4435-8e0b-bbbaf22639f2"
ctrlr.c: 389:spdk_nvmf_ctrlr_connect: *INFO*: Connect Admin Queue for controller ID 0xffff
ctrlr.c: 207:spdk_nvmf_ctrlr_create: *INFO*: cap 0x20010103ff
ctrlr.c: 208:spdk_nvmf_ctrlr_create: *INFO*: vs 0x10300
ctrlr.c: 209:spdk_nvmf_ctrlr_create: *INFO*: cc 0x0
ctrlr.c: 210:spdk_nvmf_ctrlr_create: *INFO*: csts 0x0
ctrlr.c: 104:ctrlr_add_qpair_and_update_rsp: *INFO*: connect capsule response: cntlid = 0x0001
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=0 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 26
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x460001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00000000
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00460001
ctrlr.c: 449:nvmf_prop_set_cc: *INFO*: Property Set CC Enable!
ctrlr.c: 480:nvmf_prop_set_cc: *INFO*: Prop Set IOSQES = 6 (64 bytes)
ctrlr.c: 487:nvmf_prop_set_cc: *INFO*: Prop Set IOCQES = 4 (16 bytes)
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x1
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000001 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x8
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: vs
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x10300
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00010300 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 26
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 1, offset 0x0
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: cap
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x20010103ff
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x010103ff rsvd1=32 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 26 nsid 0 cdw10 0x00000001
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc026a2000 key 0x10112 len 0x1000
ctrlr.c:1172:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ctrlr data: maxcmd 0x400
ctrlr.c:1173:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: sgls data: 0x100005
ctrlr_bdev.c: 73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 3
ctrlr_bdev.c: 73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 9
ctrlr.c:1215:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ioccsz 0x104
ctrlr.c:1217:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: iorcsz 0x1
ctrlr.c:1219:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: icdoff 0x0
ctrlr.c:1221:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ctrattr 0x0
ctrlr.c:1223:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: msdbd 0x1
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x02 fuse 0 cid 26 nsid 4294967295 cdw10 0x03ff0005
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xc026a3000 key 0x10113 len 0x1000
ctrlr.c:1082:spdk_nvmf_ctrlr_get_log_page: *INFO*: Get log page: LID=0x05 offset=0x0 len=0x1000
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=26 cdw0=0x00000000 rsvd1=0 status=0x0000
~・~一部省略~・~
ctrlr.c:1548:spdk_nvmf_ctrlr_keep_alive: *INFO*: Keep Alive
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=0 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x18 fuse 0 cid 0 nsid 0 cdw10 0x00000000
ctrlr.c:1548:spdk_nvmf_ctrlr_keep_alive: *INFO*: Keep Alive
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=0 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: o
List確認Initiator側
# nvme list
Node SN Model Namespace Usage Format FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 SPDK00000000000001 SPDK bdev Controller 1 250.06 GB / 250.06 GB 512 B + 0 B 18.10
List確認Target側
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 18 nsid 0 cdw10 0x00000001
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbe37f8000 key 0x10120 len 0x1000
ctrlr.c:1172:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ctrlr data: maxcmd 0x400
ctrlr.c:1173:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: sgls data: 0x100005
ctrlr_bdev.c: 73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 3
ctrlr_bdev.c: 73:spdk_nvmf_subsystem_bdev_io_type_supported: *INFO*: All devices in Subsystem nqn.2016-06.io.spdk:cnode1 support io_type 9
ctrlr.c:1215:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ioccsz 0x104
ctrlr.c:1217:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: iorcsz 0x1
ctrlr.c:1219:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: icdoff 0x0
ctrlr.c:1221:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: ctrattr 0x0
ctrlr.c:1223:spdk_nvmf_ctrlr_identify_ctrlr: *INFO*: ext ctrlr data: msdbd 0x1
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 121:nvmf_trace_command: *INFO*: Admin cmd: opc 0x06 fuse 0 cid 18 nsid 1 cdw10 0x00000000
request.c: 136:nvmf_trace_command: *INFO*: SGL: Keyed (Inv): addr 0xbe37f8000 key 0x10121 len 0x1000
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000000 rsvd1=0 status=0x0000
bdevとして認識されていることを確認*5
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 136.8G 0 disk
tqsda1 8:1 0 1G 0 part /boot
mqsda2 8:2 0 135.7G 0 part
tqcentos-root 253:0 0 131.7G 0 lvm /
mqcentos-swap 253:1 0 4G 0 lvm [SWAP]
sr0 11:0 1 1024M 0 rom
nvme0n1 259:0 0 232.9G 0 disk
Disconnect実施Initiator側
# nvme disconnect -n "nqn.2016-06.io.spdk:cnode1"
NQN:nqn.2016-06.io.spdk:cnode1 disconnected 1 controller(s)
Disconnect実施Target側
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x00 cid 18
ctrlr.c: 598:spdk_nvmf_property_set: *INFO*: size 0, offset 0x14, value 0x464001
ctrlr.c: 608:spdk_nvmf_property_set: *INFO*: name: cc
ctrlr.c: 438:nvmf_prop_set_cc: *INFO*: cur CC: 0x00460001
ctrlr.c: 439:nvmf_prop_set_cc: *INFO*: new CC: 0x00464001
ctrlr.c: 463:nvmf_prop_set_cc: *INFO*: Property Set CC Shutdown 01b!
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000000 rsvd1=0 status=0x0000
request.c: 116:nvmf_trace_command: *INFO*: Admin Fabrics cmd: fctype 0x04 cid 18
ctrlr.c: 557:spdk_nvmf_property_get: *INFO*: size 0, offset 0x1c
ctrlr.c: 573:spdk_nvmf_property_get: *INFO*: name: csts
ctrlr.c: 583:spdk_nvmf_property_get: *INFO*: response value: 0x8
request.c: 92:spdk_nvmf_request_complete: *INFO*: cpl: cid=18 cdw0=0x00000008 rsvd1=0 status=0x0000
上記InitiatorとTargetのやり取りをPcapしたファイルを以下にアップしておきます。
roce02.pcapng
あとは、iSCSI Targetと同様に動作しますので、Initiator側でmkfsするなり、fioで速度測定するなりご自由にどうぞ。
以上です。
7.補足その1:ReactorMaskについて
ReactorMaskとは、PMD(Poll Mode Driver)で専有させるCPUコアを明示的に指定するためのものです。NVMe-oF targetの場合、SSDが管理されているNUMA socket*6と同じNUMA socket上のCPUコアを明示的に指定することでパフォーマンスが向上します。このため、ReactorMaskでPMDが専有するCPUコアを明示的に指定することが重要となってきます。
それでは、CPUコアを明示的に指定する方法を具体例を交えて解説します。
lscpuの結果
# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel
CPU family: 6
Model: 45
Model name: Intel(R) Xeon(R) CPU E5-2407 0 @ 2.20GHz
Stepping: 7
CPU MHz: 1200.000
CPU max MHz: 2200.0000
CPU min MHz: 1200.0000
BogoMIPS: 4389.14
Virtualization: VT-x
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 10240K
NUMA node0 CPU(s): 0-3
NUMA node1 CPU(s): 4-7
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx lahf_lm epb tpr_shadow vnmi flexpriority ept vpid xsaveopt ibpb ibrs stibp dtherm arat pln pts spec_ctrl intel_stibp
今回使用したサーバ(DL360e)の場合、2ソケット、Hyperスレッド無し、4コアなので、トータル8コアあります。
さらに、NUMA socketの割り当ては以下のようになっています。
NUMA socket(node)0:0-3コア
NUMA socket(node)1:4-7コア
また、nvmf_tgtの実行結果から、SSDがNUMA socket(node)0で動作していることがわかります。
# app/nvmf_tgt/nvmf_tgt -c app/nvmf_tgt/nvmf.conf
Starting SPDK v18.07-pre / DPDK 18.02.0 initialization...
[ DPDK EAL parameters: nvmf -c 0x0E --file-prefix=spdk_pid17014 ]
EAL: Detected 8 lcore(s)
EAL: Multi-process socket /var/run/.spdk_pid17014_unix
EAL: Probing VFIO support...
app.c: 530:spdk_app_start: *NOTICE*: Total cores available: 3
reactor.c: 718:spdk_reactors_init: *NOTICE*: Occupied cpu socket mask is 0x1
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 2 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 3 on socket 0
reactor.c: 492:_spdk_reactor_run: *NOTICE*: Reactor started on core 1 on socket 0
EAL: PCI device 0000:03:00.0 on NUMA socket 0
EAL: probe driver: 144d:a808 spdk_nvme
上記結果より、PMDに専有させたいコアは「NUMA socket(node)0:0-3」となります。
このときのReactorMaskの指定方法は、
[Global]
ReactorMask 0x0F
となります。
CPUコアの並び順は以下のようになっています。
7654 3210
lscpuの結果より、
7654がNUMA socket(node)1
3210がNUMA socket(node)0
となります。
ReactorMaskのうち、0x0Fを2進数に変換すると、以下のようになります。
16進数
0x0F
2進数
0000 1111
CPUコアの並びと2進数に変換したReactorMaskを合わせると
7654 3210
0000 1111
となり、ReactorMaskのうち「1」が立っているCPUがPMDに専有されます。
考え方としては、SubnetMaskと同様ですね。
今回の場合、あまり意味はないですが、例えば、奇数番号のコアだけを使用したい場合は、
CPUコア
7654 3210
2進数
1010 1010
16進数
0xAA
となります。
8.補足その2:fioの実施結果
fioを実施してみました。
結果、10Gbpsをフルに使用したパフォーマンスを出してくれました。
但し、Samsung SSD 250GB 970 EVOのシーケンシャルリードの公称値が3400MBps(27.2Gbps)なので、Mellanox製NICがボトルネックとなっています。
これについては、40GNIC or 100GNICで試せたらいいなと考えています。
fio設定ファイル
# cat seqread4.fio
[global]
filename=/dev/nvme0n1
group_reporting=1
direct=1
ioengine=libaio
[seqread4]
readwrite=read
blocksize=32m
size=10g
numjobs=2
loops=2
fio実行結果
# fio seqread4.fio
seqread4: (g=0): rw=read, bs=(R) 32.0MiB-32.0MiB, (W) 32.0MiB-32.0MiB, (T) 32.0MiB-32.0MiB, ioengine=libaio, iodepth=1
...
fio-3.1
Starting 2 processes
Jobs: 2 (f=2): [R(2)][100.0%][r=1185MiB/s,w=0KiB/s][r=37,w=0 IOPS][eta 00m:00s]
seqread4: (groupid=0, jobs=2): err= 0: pid=13105: Thu Aug 23 15:26:47 2018
read: IOPS=36, BW=1167MiB/s (1224MB/s)(40.0GiB/35097msec)
slat (usec): min=26489, max=30909, avg=28159.67, stdev=289.25
clat (usec): min=13362, max=27098, avg=26659.48, stdev=449.47
lat (usec): min=40354, max=56431, avg=54820.49, stdev=422.94
clat percentiles (usec):
| 1.00th=[25560], 5.00th=[26346], 10.00th=[26346], 20.00th=[26608],
| 30.00th=[26608], 40.00th=[26608], 50.00th=[26608], 60.00th=[26608],
| 70.00th=[26870], 80.00th=[26870], 90.00th=[26870], 95.00th=[26870],
| 99.00th=[26870], 99.50th=[26870], 99.90th=[27132], 99.95th=[27132],
| 99.99th=[27132]
bw ( KiB/s): min=588646, max=656673, per=49.95%, avg=596887.99, stdev=20330.41, samples=140
iops : min= 17, max= 20, avg=18.20, stdev= 0.61, samples=140
lat (msec) : 20=0.08%, 50=99.92%
cpu : usr=0.02%, sys=3.94%, ctx=21806, majf=0, minf=1107
IO depths : 1=100.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwt: total=1280,0,0, short=0,0,0, dropped=0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
READ: bw=1167MiB/s (1224MB/s), 1167MiB/s-1167MiB/s (1224MB/s-1224MB/s), io=40.0GiB (42.9GB), run=35097-35097msec
Disk stats (read/write):
nvme0n1: ios=325850/0, merge=0/0, ticks=6298513/0, in_queue=6471868, util=99.76%
1224MBps=9792Mbps