最新!SPDK宣布在NVMe-oF Fabrics中支持TCP transport

作者简介

杨子夜,Intel存储软件开发工程师,主要从事SPDK软件开发工作。

随着由NVM Express 发布新闻宣告发布了 NVMe/TCPtransport [1][2](NVMe-oF TP 8000 TCP Transport)的spec,SPDK 也基于master branch (https://github.com/SPDK) 发布了patch[3]进行对这个transport的支持。在这篇文章中我们会简要介绍一下为什么需要NVMe/TCP transport,并且对SPEC做简单介绍, 然后介绍SPDK library中对于NVMe/TCP transport的支持情况, 包括现状、发展蓝图以及一些简单的使用方法。

1.  NVMe/TCP transport spec的诞生

近日NVM Express (NVMe 协议标准工作组) 发布了NVMe_TP_8000这个SPEC文档。这个SPEC从2017年7月19日开始起草,历时16个月的时间,终于发布了第一个版本。这个SPEC 弥补了NVMe over Fabrics的一些短板。由于NVMe的初衷是提供一个协议用于高速访问本地的PCIe SSD (NVMe over PCIe), 去除SCSI 层,使用简化的并发协议,以提高性能。在本地高速访问协议出现以后,很自然地有用户希望NVMe可以进行远程访问(Remote Access)。就像SCSI 协议在以太网协议上扩展成为iSCSI协议,NVMe 协议也在Fabrics, 包括InfiniBand, Fibre Channel, Ethernet 上扩展成为了NVMe over Fabrics (简称NVMe-oF)协议,如图 1所示。为了保证NVMe低延迟的属性在fabrics 上继续延续,通过远程Fabrics的访问必须继续高效。于是最开始的NVMe-oF 协议制定了基于RDMA (Remote Direct Memory access) 协议的一个transport。 RDMA协议非常高效,对于极端情况,在fabrics上的延迟的开销会非常小。比如通过NVMe  协议对于本地盘进行随机读,对于(4KB大小,qd=1)的随机读的latency在几十微秒左右,那么在RDMA的transport上只会增加同样数量级的时延,这样NVMe协议的高效访问对于远程依然有效,NVMe协议的初衷依然得以保存和延续。于是用户可以使用各种Fabrics(例如Inifiniband 或者Ethernet), 只要该transport能够支持NVMe-oF协议中规定的使用RDMA的交互协议, 当然基于FC Transport的有专门的FC-NVMe 管理,定义在INCITS 540 Fibre Channel中。

640?wx_fmt=png

图 1 NVMe over Fabrics 架构

但是从去年开始,标准组织又开始制定基于TCP的transport。众所周知,和RDMA协议相比,使用TCP 协议会破坏NVMe 协议设计的初衷,主要原因是使用TCP 协议会带来远高于本地PCIe访问的网络延迟,使得NVMe协议低延迟的目标遭到破坏。不过笔者认为有以下4个原因(仅供参考)促使了NVMe/TCP Transport的诞生:

1. NVMe 虚拟化的出现。 在NVMe虚拟化实现的前提下,NVMe-oF target那端并不一定需要真实的NVMe 设备,可以是由分布式系统抽象虚拟出来的一个虚拟NVMe 设备,为此未必继承了物理NVMe设备的高性能的属性 。那么在这一前提下,使用低速的TCP协议也未尝不可。

2. 向后兼容性。NVMe-oF协议,在某种程度上希望替换掉iSCSI 协议(iSCSI最初的协议是RFC3720,有很多扩展)。iSCSI协议只可以在以太网上运行,对于网卡没有太多需求,并不需要网卡一定支持RDMA。 当然如果能支持RDMA, 则可以使用iSER协议,进行数据传输的CPU 资源卸载(workload offloading)。 但是NVMe-oF 协议一开始没有TCP的支持。于是当用户从iSCSI向NVMe-oF 转型的时候,很多已有的网络设备无法使用。这样会导致NVMe-oF协议的接受度下降。在用户不以性能为首要考量的前提下,显然已有NVMe-oF协议对硬件的要求,会给客户的转型造成障碍,使得用户数据中心的更新换代不能顺滑地进行。

 

3. TCP offloading。虽然TCP协议在很大程度上会降低性能,但是TCP也可以使用offloading,或者使用Smart NIC,或者FPGA。那么潜在的性能损失,可以得到一定的弥补。那么提供一个TCP协议的transport,是可行的。总的来说短期有性能损失,长期来讲协议对硬件的要求降低,性能可以改进。为此总的来讲,接受度会得到提升。

4. 和Software RoCE的比较。在没有TCP transport的时候,用户在不具备RDMA网卡设备的时候。如果要进行NVMe-oF的测试,需要通过Software RoCE,把网络设备模拟成一个具有RDMA功能的设备,然后进行相应的测试。其真实实现是通过内核的相应模块,实际UDP 包来封装模拟RDMA协议。有了TCP transport协议,则没有这么复杂,用户可以采用更可靠的TCP协议来进行NVMe-oF的一些相关测试。 从测试部署来讲更加简单,有效。

2. NVMe/TCCP transport 协议简要介绍

NVMe/TCP transport 的协议,在一定程度上借鉴了iSCSI的协议,例如iSCSI数据读写的传输协议 。这个不太意外,因为有些协议的指定参与者,也是iSCSI协议的指定参与者。另外iSCSI协议的某些部分确实写得很好。 但是NVMe/TCP  和iSCSI协议相比更加简单,可以说是取其精华。 接下来我们先看一些TCP transport协议的定义,然后再看一下基于TCP transport的交互过程。

NVMe/TCP PDU的定义

640?wx_fmt=png

图 2 和图3给出了NVMe/TCP PDU  (Protocol Data Unit)的定义,一共包括5个部分:HDR (= CH + PSH), HDGST, PAD, DATA, DDGST。HDR由CH + PSH 组成。这个 NVME PDU 被封装在一个TCP PDU 中, 也可以被分割在不同TCP PDU的Payload中。对于这个点,不需要使用NVMe/TCP transport的编程人员考虑。

 1 . HDR:  PDU header的头部定义。 由CH (Common header,通用头部) 和 PSH (PDU specific header)组成。

    a.  其中CH固定长度8个bytes,并且定义了以下的数据字段,以byte为单位。

     i.     PDU-type (offset=0, len=1): PDU的类型。一共有9种不同类型的PDU header。

     ii.     Flags (offset=1, len=1: 不同类型的PDU 有不同类型的标志位。

     iii.     Header Length (hlen: offset=2, len=1): PDU type的长度包括 header digest的长度。

     iv.     PDU Data Offset (PDO: offset=3, len=1): 如果有数据字段,这个值代表数了数据 (Data, 如果存在的话) 在整个PDU中的offset的起始值,这个值最大不超过128 。

     v.     PDU Length (PLEN: offset=4, len=4): 整个PDU的长度,包括CH + PSH  + HDGST(可选)  + PAD(可选) + DATA(可选) + DDGST (可选)。

    b. PSH:不同类型的PDU,请参考TP  8000SPEC( [2] 中ZIP包解压后名字叫做“NVMe-oF - TP 8000 TCP Transport 2018.11.13-Ratified”的文件)中描述的每个PDU的定义。

 2 . HDGST: Header Digest.  Header的摘要,其固定长度是4 bytes,header digest是可选的。 如果target 和host 协商需要使用Header Digest,相应的PDU 才会有。

 3 . PAD:主要用于数据的Padding。根据Spec的定义,Data在整个PDU中的最大的offload起始值是128,所以data padding的长度是有限。填充长度是根据CPDA(Controller PDU Data Align, target决定,当然是双方已经沟通好的值) 或者HPDA (Host PDU Data Align, 由host那段决定,当然是双方已经沟通好的值) 的值,构建出一个不超过128长度大小的值A,再减去(HDR 的Len以及可能的HDGST的长度 , 计为B)。 如果这个值(A - B)是负,则填充长度为0。 一般情况下,PAD的填充的长度是0, 也就是说未必有padding 的数据。

 4 .DATA. PDU中带有的数据,未必一定携带。Data的数据一般包含在C2HData或者H2CData中。当然在CapsuleCmd,H2CTermReq, ,2HTermReq 类型的PDU中也会包含。对于这些类型的PDU,Data size的长度可能会有最大长度的限制。

 5 . DDGST:是对持有PDU中持有数据的哈希值,其长度为4。Data Digest 也是可选的,只有target 和host协商使用Data Digest,相应的PDU才会有。

在9种不同类型的PDU 中,  Host端使用以下4种:

1)  Initialize Connection Request PDU (ICReq): 类型代号0x0

2)  Host to Controller Terminate Connection Request PDU (H2CTermReq):类型代号是0x2

3)  Command Capsule PDU (CapsuleCmd): 类型代号是 0x4

4)   Host To Controller Data Transfer PDU (H2CData):类型代码是0x6

Target 端使用的PDU类型:

1) Initialize Connection Response PDU (ICResp):类型代号 0x1

2) Controller to Host Terminate Connection Request PDU (C2HTermReq): 类型代码0x3

3) Response Capsule PDU (CapsuleResp):类型代号0x5

4) Controller To Host Data Transfer PDU (C2HData):类型代号0x7

5) Ready To Transfer PDU (R2T): 类型代号0x9

这9种PDU的类型不同,他们有以下的异同:

hlen:由于PSH长度不一样,所以HDR的长度(hlen)也不一样,但是hlen最大不会超过128。

 HDGST:  ICReq, H2CTermReq, ICResp 和C2HTermReq这4种类型的PDU是必然没有header digest。

 DDGST:  ICReq, H2CTermReq, ICResp, C2HTermreq, 

 CapsuleResp以及R2T 这六种类型的PDU 是必然没有data digest的。

640?wx_fmt=png

图2 NVMe/TCP PDU的定义

640?wx_fmt=png

图3 NVMe/TCP PDU header的定义

基于NVMe /TCP transport的交互

640?wx_fmt=png

使用TCP transport,  target 和host 需要建立相应的TCP 连接。然后NVMe协议中的每一对qpair (由submission queue, 和completion queue组成,  可以是admin qpair 或者是I/O qpair) 会被映射到一个TCP 连接上。举个例子,如果host和target了建立了1个admin qpair,3个I/O qpair, 那么就会有4个TCP连接。总的来讲,通过TCP transport 建立一个连接的简要流程如下:

Target 端监听到一个TCP 端口上,等到host的连接。

Host 通过TCP 请求发起一个连接,连接建立后。发送ICReq PDU, 然后等待Target端的反应。

Target端接收数据,解析PDU ,判断是否是ICReq,如果请求内容正确,则返回ICResp PDU,另外把这个连接设置为active状态,进入这个状态中,意味着不能再接收ICResp PDU。如果在解析过程中出现错误,则返回C2HTermReq, 同时target进入等待时间 (一般为设置为30 秒)。 如果host 没有关闭连接(指收到相应的数据包),则会主动关闭连接。

Host 端接收数据,解析PDU,判断是否是ICResp PDU在过程中,出现错误则返回H2CTermReq,然后关闭连接。再收到正确的ICResp PDU后,标记连接的状态是ACTIVE。以后再收到ICResp,则判断为错误状态。如果收到ICResp内容正确,Host会封装上层发送的NVMe command,封装成为CapsuleCmd,  发送出去。

Target端接收数据,发现是CapsuleCmd PDU后,会提取其中NVMe command (命令为64bytes)进行执行。

a.  如果从host传送过来的PDU已经包含数据 (指InCapsuleData),或者不需要数据,则直接交给NVMe-oF/NVMe 协议层处理; 如果需要数据(没有InCapsuleData, 说明这个NVMe command是写操作),但是没有发送过来,Target端就发送R2T PDU。 Host接收到R2T PDU后, 如果包解析正确,则会发送一个或者多个H2C PDU,然后host等待新的PDU 包过来。 Target收到所有H2C PDU后,获得数据后,则交给NVMe-oF/NVMe 层执行。

b.  在target端的NVMe-oF/NVMe层执行,最终会返回。如果是操作有数据返回(说明从host发过来的NVMe command的是读操作),则会返回若干个C2H PDU给host 端,然后发送CapsuleResp(封装16bytes的NVMe response命令), 其实这个回复是可选的, 如果NVMe SQ 的控制流被禁止了。 如果返回不需要数据,则直接发送CapsuleResp。

c. Host 接收相应的数据,要么是若干个C2H PDU + 可选的CapsuleResp, 要么是单独的CapsuleResp.

总的来讲,a、b、c 步骤完成了一轮从host 端发送封装NVMe command -> CaspsuleCmd PDU,然后最终target 端返回相应数据,以及CapsuleResp(对于读NVMe command非必需)的操作。当然在实际实现过程中,有相应的优化手段,远远没有这么简单。

3. 基于SPDK的NVMe-oF TCP 的transport 的实现以及使用介绍

SPDK  TCP transport的现状和细节

640?wx_fmt=png

SPDK 库支持NVMe/TCP transport的代码主要分为以下几块:

·头文件的定义: 主要位于spdk/include/spdk/nvme_spec.h, spdk/incude/spdk_internel/nvme_tcp.h

·Host端的实现:主要位于 spdk/lib/nvme 目录,主要实现在nvme_tcp.c文件中。

·Target端的实现: 主要位于spdk/lib/nvmf目录,主要实现在tcp.c文件中。

对于 SPDK第一版本的TCP transport实现,主要目标是基本功能的支持,  包括和kernel 实现的交互性。当然由于kernel版本也刚发布,可能会存在一些问题,比如SPDK 实现的bug,或者kernel实现的bug,为此还处于继续测试和集成的阶段。

另外在TCP transport的实现中,SPDK的target和host 端的TCP transport的PDU接收采用了同样的状态机的逻辑:

状态1:<接收 PDU CH>。 一旦接受满8个byte,则判断是否是个合法PDU。如果是则跳到状态2, 否则跳到状态4。

状态2:<接收 PSH + HDGST(可选) + PAD(可选)>; 如果接收的数据没问题 ,那么有两个可能: (a)需要继续接受数据,则跳到状态3;(b)执行相关NVMe-oF/NVMe 层的逻辑,并且跳到状态1,可以接续接收包。如果接收的数据有问题,则跳到状态4。

状态3: <接收 DATA +  DDGST(可选)>:接收相应的数据。数据正确,则执行相应的NVMe-oF/NVMe层的逻辑,PDU接收逻辑跳转到状态1, 否则进入状态4。

状态4:< 错误状态>。发送 termreq命令。 Target 发送C2HTermreq, host发送H2CTERMReq,同时停止接收处理后续的数据。

SPDK对于NVMe/TCP transport的一些Roadmap

640?wx_fmt=png

1. 功能的继续完善:继续遵循NVM Express 制定的有关TCP transport的SPEC。不仅确保了SPDK target 和host的交互性正常,另外要继续保证和Kernel 实现的交互性正常。

2.  性能优化,可能有以下几个方面:

  a. 优化已有的TCP transport中的代码。

  b. 采用用户态的TCP 协议栈  + 用户态的网卡驱动,比如集成VPP来优化TCP Transport, 就像iSCSI target可以整合VPP一样。

  c. 后续可能会使用hardware的offloading,诸如FPGA, Smart NIC。这个可能需要设计offloading的接口,来适配各种offloading的引擎。

测试基于TCP transport的SPDK NVMe-oF

640?wx_fmt=png

总的来讲,在SPDK 中使用NVMe/TCP transport比较简单。和使用RDMA transport相比,只要在原有的命令中把RDMA 替换成为 TCP 即可,以下是一些参考。

测试 SPDK NVMe-oF target

640?wx_fmt=gif

SPDK Target 端使用如下的配置(作为参考)

1. 下载支持TCP的branch([3]),编译后,启动SPDK NVMe-oF target。

     例如使用命令:./app/nvmf/nvmf_tgt.

2.  在另外一个Shell窗口执行以下RPC 命令:

# 创建一个大小是64M,每个块大小是512的malloc bdev,命名为Malloc0

scripts/rpc.py construct_malloc_bdev -b Malloc0 64 512

#创建一个TCP transport

scripts/rpc.py nvmf_create_transport -t TCP -p 4

#创建一个 NVMe-oF subsystem

scripts/rpc.py nvmf_subsystem_create nqn.2016-06.io.spdk:cnode1 -a -s SPDK00000000000001

#在这个subsystem的中添加Malloc0,作为相应的subsystem

scripts/rpc.py nvmf_subsystem_add_ns nqn.2016-06.io.spdk:cnode1 Malloc0

#在命名为nqn.2016-06.io.spdk:cnode1的subsystem 上创建一个监听socket,其中IP 地址是192.168.0.128 IP,TCP端口是4420

scripts/rpc.py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode1 -t tcp -a 192.168.0.128 -s 4420

Host 端的测试方法(作为参考)

1.  使用SPDK的自带程序测试基于SPDK的NVMe-oF target.

a.  使用 perf 程序:./spdk/examples/nvme/perf/perf -r 'trtype:TCP adrfam:IPv4 traddr: 192.168.0.128 trsvcid:4420' -s 512 -q 4 -o 4096 –w randrw -M 50 -t 10

b.  使用identify 程序: ./spdk/examples/nvme/identify/identify -r 'trtype:TCP adrfam:IPv4 traddr:192.168.0.128 trsvcid:4420'

2.   使用kernel host测试SPDK的NVMe-oF target.

a. ‍下载已经支持NVMe TCP transport的Linux Kernel [4]。 根据已有Linux kernel 系统的配置, 编译相应内核以及相关模块,替换掉已有的kernel。

b. 如果对应的nvme_tcp 编译为可加载的模块,则在shell中运行以下命令:

       modprobe nvme_tcp‍

c.  然后在shell中运行以下命令:

nvme connect -t tcp -n "nqn.2016-06.io.spdk:cnode1" -a 192.168.0.128 -s 4420

d.  如果连结成功,然后使用fdisk -l命令就可以看到一个新的NVMe相关的盘。比如/dev/nvme0n1。那么接着就可以使用fio 命令对发现的新盘进行相关的性能测试。

测试SPDK NVMe-oF Host

640?wx_fmt=gif

Kernel Target 端使用如下的配置(作为参考)

1. 可以采用以下的script, 进行简单配置。命名为add.sh。

modprobe null_blk nr_devices=1

modprobe nvmet

# 插入NVMe-tcp的模块

modprobe nvmet-tcp

mkdir /sys/kernel/config/nvmet/subsystems/mysubsystem

cd /sys/kernel/config/nvmet/subsystems/mysubsystem/

echo 1 > attr_allow_any_host

mkdir namespaces/10

cd namespaces/10/

echo -n /dev/nullb0 > device_path

echo 1 > enable

mkdir /sys/kernel/config/nvmet/ports/1

cd /sys/kernel/config/nvmet/ports/1

echo  $1 > addr_traddr

echo tcp > addr_trtype

echo $2 > addr_trsvcid

echo ipv4 > addr_adrfam

ln -s /sys/kernel/config/nvmet/subsystems/mysubsystem /sys/kernel/config/nvmet/ports/1/subsystems/mysubsystem

然后在shell中执行:

#配置IP地址是192.168.0.128,端口是4420监听端口transport

 ./add.sh  192.168.0.128 4420

2. 当然后续要清理的时候可以执行以下命名为delete.sh, 内容如下:

rm -rf /sys/kernel/config/nvmet/ports/1/subsystems/mysubsystem

echo 0 > /sys/kernel/config/nvmet/subsystems/mysubsystem/namespaces/10/enable

echo -n 0 > /sys/kernel/config/nvmet/subsystems/mysubsystem/namespaces/10/device_path

rmdir --ignore-fail-on-non-empty /sys/kernel/config/nvmet/subsystems/mysubsystem/namespaces/10

rmdir --ignore-fail-on-non-empty /sys/kernel/config/nvmet/subsystems/mysubsystem

rmdir --ignore-fail-on-non-empty /sys/kernel/config/nvmet/ports/1

rmmod nvmet-tcp

rmmod nvmet

rmmod null_blk

备注:add.sh和delete.sh 仅供参考。具体配置Linux kernel NVMe-oF Target请参考官方文档

Host 端的测试方法(作为参考)

a.使用 perf 程序:

./spdk/examples/nvme/perf/perf -r 'trtype:TCP adrfam:IPv4 traddr: 192.168.0.128 trsvcid:4420' -s 512 -q 4 -o 4096 –w randrw -M 50 -t 10

b.使用identify 程序:

 ./spdk/examples/nvme/identify/identify -r 'trtype:TCP adrfam:IPv4 traddr:192.168.0.128 trsvcid:4420'

备注:如果在Target端安装的Linux kernel 中的NVMe/TCP不支持header摘要(HDGST)或者 Data摘要(DDGST), 那么使用SPDK host的时候,需要在一开始发送ICReq PDU中,把相关Digest的bit清零。目前我们还没提供较为简易的使用SPDK NVMe-oF host的配置(之后的Patch会提供),但是可以参考Reference中的Patch [5]。

参考文献

[1] "WelcomeNVMe™/TCP to the NVMe-oF™ Family of Transports," [Online]. Available:https://nvmexpress.org/welcome-nvme-tcp-to-the-nvme-of-family-of-transports/.

[2] "NVMe/TCPTransport Binding specification," [Online]. Available:https://nvmexpress.org/wp-content/uploads/NVM-Express-over-Fabrics-1.0-Ratified-TPs.zip.

[3] "TheSPDK NVMe/TCP support," [Online]. Available:https://review.gerrithub.io/#/c/spdk/spdk/+/425191/.

[4] "TheLinux Kernel NVMe/TCP support," [Online]. Available:http://git.infradead.org/nvme.git/shortlog/refs/heads/nvme-tcp.

[5] "SPDKtemporary Patch for using SPDK host testing Linux TCP tranposrt based NVMe-oFtarget," [Online]. Available:https://review.gerrithub.io/#/c/spdk/spdk/+/427189/.

1

END

1

  推荐阅读 


送!京东电子卡

活动规则:带文字将本文转发至朋友圈,并将截图发至公众号后台,小编将随机抽取四位幸运读者:

一等奖1名,送50元京东电子卡

二等奖1名,送30元京东电子卡

三等奖2名,送10元京东电子卡

领取方式:后台发送卡号及卡密。

640?wx_fmt=jpeg

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SPDK(存储性能开发套件)官方文档文版。 第一章 简介 1 1.1.什么是SPDK? 1 1.2.入门 1 1.3. Vagrant开发环境 3 1.4.更新日志(略) 6 第二章 概念 6 2.1. 用户空间驱动程序** 6 2.2. 来自用户空间的DMA** 7 2.3. 消息传递和并发** 9 2.4. NAND Flash SSD内部 13 2.5. 将I / O提交到NVMe设备** 15 2.5.1 NVMe规范 15 2.5.2 SPDK NVMe驱动程序I / O路径 15 2.6. 使用Vhost-user进行虚拟化I / O. 16 2.6.1 介绍 16 2.6.2 QEMU 17 2.6.3 设备初始化 18 2.6.4 I / O路径 19 2.6.5 SPDK优化 20 2.7. SPDK目录结构概述 20 2.8. SPDK移植指南 22 第三章 用户指南 22 3.1. 系统配置用户指南 22 3.1.1 IOMMU配置 22 3.2. SPDK应用程序概述 23 3.2.1 配置SPDK应用程序 23 3.3. iSCSI Target 26 3.3.1. iSCSI Target入门指南 26 3.3.2. 通过配置文件配置iSCSI Target 27 3.3.3. 通过RPC方法配置iSCSI Target 28 3.3.4. 配置iSCSI启动器 29 3.3.5. rpc配置示例*** 30 3.3.6. iSCSI 热插拔 32 3.4. NVMe over Fabrics Target 32 3.5. Vhost Target(略) 37 3.6 块设备用户指南 38 3.6.1 bdev介绍 38 3.6.2 通用RPC命令 38 3.6.3 Ceph RBD 39 3.6.4 压缩虚拟Bdev模块 40 3.6.5 加密虚拟Bdev模块 41 3.6.6 延迟vbdev模块 41 3.6.7 GPT(GUID分区表) 42 3.6.8 iSCSI bdev 43 3.6.9 Linux AIO bdev 43 3.6.10 OCF虚拟bdev 43 3.6.11 Malloc bdev 44 3.6.12 NULL bdev 44 3.6.13 NVMe bdev 44 3.6.14 逻辑卷Lvol 45 3.6.15 RAID 46 3.6.16 Passthru 46 3.6.17 Pmem 46 3.6.18 Virtio Block 47 3.6.19 Virtio SCSI 47 3.7 BlobFS(Blobstore文件系统) 48 3.7.1 RocksDB集成 48 3.7.2 FUSE插件 49 3.8 JSON-RPC方法(略) 49 第四章 程序员指南 49 4.1. Blobstore程序员指南 49 4.1.1 介绍 50 4.1.2 运作理论 50 4.1.3 设计注意事项 52 4.1.4 例子 54 4.1.5配置 54 4.1.6 组件细节 54 4.2. 块设备层编程指南 56 4.3 编写自定义块设备模块 58 4.3.1 介绍 58 4.3.2 创建一个新模块 59 4.3.3创建虚拟Bdev 60 4.4 NVMe over Fabrics目标编程指南 61 4.4.1 介绍 61 4.4.2 原语结构体 61 4.4.3 基础函数 62 4.4.4访问控制 62 4.4.5发现子系统 62 4.4.6 传输 63 4.4.7选择线程模型 63 4.4.8 跨CPU核心扩展 63 4.4.9 零拷贝支持 63 4.4.10 RDMA 63 4.5 Flash传输层 64 4.5.1 术语 64 4.5.2 使用方法 67 4.6 GDB宏用户指南 69 4.6.1 介绍 69 4.6.2 加载gdb宏 71 4.6.3 使用gdb数据目录 72 4.6.4 使用.gdbinit加载宏 72 4.6.5 为什么我们需要显式调用spdk_load_macros 72 4.6.6 以上可用的宏总结 73 4.6.7 添加新宏 73 4.7 SPDK “Reduce”块压缩算法 73 4.7.1 介绍 73 4.7.2 例子 74 4.8 通知库 78 第五章 基本信息 79 5.1 事件框架 79 5.1.1 事件框架设计注意事项 80 5.1.2 SPDK事件框架组件 80 5.1.3 应用框架 80 5.2 逻辑卷 81 5.2.1 术语 81 5.2.2 配置逻辑卷 84 5.3 矢量数据包处理(略) 86 第六章 杂项 86 6.1 介绍 86 6.2 NVMe的P2P API 86 6.3 确定设备支持 87 6.4 P2P问题 87 第七章 驱动程序 88 7.1 NVMe驱动程序*** 88 7.1.1 介绍 88 7.1.2 例子 88 7.1.3 公共接口 89 7.1.4 NVMe驱动程序设计 89 7.1.5 NVMe over Fabrics主机支持 91 7.1.6 NVMe多进程 91 7.1.7 NVMe Hotplug 92 7.2 I/OAT驱动程序 93 7.2.1 公共接口 93 7.2.2 关键功能 93 7.3 Virtio驱动程序 93 7.3.1 介绍 93 7.3.2 2MB大页面 93 第八章 工具 94 8.1 SPDK CLI 94 8.1.1 安装所需的依赖项 94 8.1.2 运行SPDK应用程序实例 94 8.1.3 运行SPDK CLI 94 8.1.4 可选 - 创建Python虚拟环境 94 8.2 nvme-CLI 95 8.2.1 nvme-cli with SPDK入门指南 95 8.2.2 使用场景 95 第九章 性能测试报告(略) 96 第十章NVMe-oF Target跟踪点*** 96 10.1 介绍 96 10.2 启用跟踪点 97 10.3 捕获事件的快照 97 10.4 捕获足够的跟踪事件 98 10.5 添加新的跟踪点 99

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值