在NVMe over PCIe中,I/O命令支持SGL(Scatter Gather List 分散聚合表)和PRP(Physical Region Page 物理(内存)区域页), 而管理命令只支持PRP;而在NVMe over Fabrics中,无论是管理命令还是I/O命令都只支持SGL。NVMe over Fabrics既支持FC网络,又支持RDMA网络。众所周知,在RDMA编程中,SGL(Scatter/Gather List)是最基本的数据组织形式。 SGL是一个数组,该数组中的元素被称之为SGE(Scatter/Gather Element),每一个SGE就是一个Data Segment(数据段)。其中,SGE的定义如下(参见verbs.h):

struct ibv_sge {uint64_t        addr;uint32_t        length;uint32_t        lkey;
};

  • addr: 数据段所在的虚拟内存的起始地址 (Virtual Address of the Data Segment (i.e. Buffer))
  • length: 数据段长度(Length of the Data Segment)
  • lkey: 该数据段对应的L_Key (Key of the local Memory Region)

而在数据传输中,发送/接收使用的Verbs API为:

  • ibv_post_send() - post a list of work requests (WRs) to a send queue 将一个WR列表放置到发送队列中
  • ibv_post_recv() - post a list of work requests (WRs) to a receive queue 将一个WR列表放置到接收队列中

下面以ibv_post_send()为例,说明SGL是如何被放置到RDMA硬件的线缆(Wire)上的。

  • ibv_post_send()的函数原型
#include <infiniband/verbs.h>int ibv_post_send(struct ibv_qp *qp, struct ibv_send_wr *wr,struct ibv_send_wr **bad_wr);

ibv_post_send() posts the linked list of work requests (WRs) starting with wr to the send queue of the queue pair qp. It stops processing WRs from this list at the first failure (that can be detected immediately while requests are being posted), and returns this failing WR through bad_wr.

The argument wr is an ibv_send_wr struct, as defined in <infiniband/verbs.h>.

struct ibv_send_wr {uint64_t                wr_id;                  /* User defined WR ID */struct ibv_send_wr     *next;                   /* Pointer to next WR in list, NULL if last WR */struct ibv_sge         *sg_list;                /* Pointer to the s/g array */int                     num_sge;                /* Size of the s/g array */enum ibv_wr_opcode      opcode;                 /* Operation type */int                     send_flags;             /* Flags of the WR properties */uint32_t                imm_data;               /* Immediate data (in network byte order) */union {struct {uint64_t        remote_addr;    /* Start address of remote memory buffer */uint32_t        rkey;           /* Key of the remote Memory Region */} rdma;struct {uint64_t        remote_addr;    /* Start address of remote memory buffer */uint64_t        compare_add;    /* Compare operand */uint64_t        swap;           /* Swap operand */uint32_t        rkey;           /* Key of the remote Memory Region */} atomic;struct {struct ibv_ah  *ah;             /* Address handle (AH) for the remote node address */uint32_t        remote_qpn;     /* QP number of the destination QP */uint32_t        remote_qkey;    /* Q_Key number of the destination QP */} ud;} wr;
};struct ibv_sge {uint64_t        addr;   /* Start address of the local memory buffer */uint32_t        length; /* Length of the buffer */uint32_t        lkey;   /* Key of the local Memory Region */
};

在调用ibv_post_send()之前,必须填充好数据结构wr。 wr是一个链表,每一个结点包含了一个sg_list(i.e. SGL: 由一个或多个SGE构成的数组), sg_list的长度为num_sge。

下面图解一下SGL和WR链表的对应关系,并说明一个SGL (struct ibv_sge *sg_list)里包含的多个数据段是如何被RDMA硬件聚合成一个连续的数据段的。

  • 01 - 创建SGL

从上图中,我们可以看到wr链表中的每一个结点都包含了一个SGL,SGL是一个数组,包含一个或多个SGE。

  • 02 - 使用PD做内存保护

一个SGL至少被一个MR保护, 多个MR存在同一个PD中。

  • 03 - 调用ibv_post_send()将SGL发送到wire上去

在上图中,一个SGL数组包含了3个SGE, 长度分别为N1, N2, N3字节。我们可以看到,这3个buffer并不连续,它们Scatter(分散)在内存中的各个地方。RDMA硬件读取到SGL后,进行Gather(聚合)操作,于是在RDMA硬件的Wire上看到的就是N3+N2+N1个连续的字节。换句话说,通过使用SGL, 我们可以把分散(Scatter)在内存中的多个数据段(不连续)交给RDMA硬件去聚合(Gather)成连续的数据段

最后,作为一个代码控(不喜欢纸上谈兵),贴一小段代码展示一下如何为调用ibv_post_send()准备SGL和WR以加深理解。

 1 #define BUFFER_SIZE     1024
 2
 3 struct connection {
 4         struct rdma_cm_id       *id;
 5         struct ibv_qp           *qp;
 6
 7         struct ibv_mr           *recv_mr;
 8         struct ibv_mr           *send_mr;
 9
10         char                    recv_region[BUFFER_SIZE];
11         char                    send_region[BUFFER_SIZE];
12
13         int                     num_completions;
14 };
15
16 void foo_send(void *context)
17 {
18         struct connection *conn = (struct connection *)context;
19
20         /* 1. Fill the array SGL having only one element */
21         struct ibv_sge sge;
22
23         memset(&sge, 0, sizeof(sge));
24         sge.addr        = (uintptr_t)conn->send_region;
25         sge.length      = BUFFER_SIZE;
26         sge.lkey        = conn->send_mr->lkey;
27
28         /* 2. Fill the singly-linked list WR having only one node */
29         struct ibv_send_wr wr;
30         struct ibv_send_wr *bad_wr = NULL;
31
32         memset(&wr, 0, sizeof(wr));
33         wr.wr_id        = (uintptr_t)conn;
34         wr.opcode       = IBV_WR_SEND;
35         wr.sg_list      = &sge;
36         wr.num_sge      = 1;
37         wr.send_flags   = IBV_SEND_SIGNALED;
38
39         /* 3. Now send ... */
40         ibv_post_send(conn->qp, &wr, &bad_wr);
41
42         ...<snip>...
43 }

附录一: OFED Verbs

A great ship asks deep waters. | 是大船就得走深水,是蛟龙就得去大海里畅游。

转载于:https://www.cnblogs.com/vlhn/p/7986875.html

[SPDK/NVMe存储技术分析]010 - 理解SGL相关推荐

  1. SPDK/NVMe存储技术分析之理解SGL

    在NVMe over PCIe中,I/O命令支持SGL(Scatter Gather List 分散聚合表)和PRP(Physical Region Page 物理(内存)区域页), 而管理命令只支持 ...

  2. [SPDK/NVMe存储技术分析]012 - 用户态ibv_post_send()源码分析

    OFA定义了一组标准的Verbs,并提供了一个标准库libibvers.在用户态实现NVMe over RDMA的Host(i.e. Initiator)和Target, 少不了要跟OFA定义的Ver ...

  3. 弘易信泰,企业级SAAS数据存储技术分析

    前言 "大数据" 通常指的是那些数量巨大.难于收集.处理.分析的数据集,指那些在传统基础设施中长期保存的数据,大数据存储将这些数据集持久化到计算机中.行政易作为一款SaaS软件产品 ...

  4. 【技术新趋势】面向图像文档的版面智能分析与理解

    目录 一.什么是OCR?什么是版面分析理解? 二.文档版面分析 2.1.版面布局类型 2.2.面向文档图像版面分析的实例分割 2.3.逻辑结构分析 三.文档版面理解 3.1.位置嵌入 3.2.表格数据 ...

  5. 【存储技术分享】SGL和SGE

    1.SGL Scatter Gather List(SGL)是一种数据结构,用于描述分散存储的数据块(即散布在不同的物理地址上的数据块)和聚合存储的数据块(即连续存储在同一物理地址上的数据块).SGL ...

  6. 2020 存储技术热点与趋势总结

    作者 | 张凯,SmartX 联合创始人 & CTO. 2 年前我们发表了一遍文章 2018 存储技术热点与趋势总结,受到了不少朋友的关注.2 年过去了,存储行业也在不断的发生着变化.今天,我 ...

  7. SPDK+NVMe SSD对接Virtio支撑红包场景性能

    原文链接:http://mp.weixin.qq.com/s/nP62NpX0NAo4BZhpkAWaQg 本文转载自云栖社区,原文标题<红包场景下,高性能本地存储技术将硬件性能发挥到极致> ...

  8. linux存储技术学习资料

    参考 https://www.cnblogs.com/pengdonglin137/p/16525428.html Linux I/O栈 Linux内核的I/O栈大图 知乎Linux I/O专栏1 L ...

  9. 2020年存储技术展望:AI推动数据存储理念进化

    2020年存储技术展望:AI推动数据存储理念进化 2020年以意想不到的方式在展开,让人们愈发渴望AI的到来. 大家知道早在60年前,"人工智能"概念就正式提出.其发展曾经历了两次 ...

最新文章

  1. C# + MySql 存贮过程开发示例
  2. Javascript-稳妥构造函数模式
  3. 51nod 1073 约瑟夫环
  4. 区块链游戏为何只剩下“炒币”的价值?
  5. ElasticSearch logo 分布式搜索引擎 ElasticSearch
  6. wireshark抓包分析tcp连接与断开
  7. 第三次学JAVA再学不好就吃翔(part52)--String类的其他功能
  8. Netweaver和SAP云平台的quota管理
  9. .NET基础 (03)生成、部署和管理
  10. 和一个刚毕业不久的朋友聊天
  11. java 正负随机_如何产生一个随机的[0, n)范围内的Short值
  12. sql分区表上创建索引_SQL Server中分区表和索引的选项
  13. 百度地图Map属性和方法
  14. Collectors.averagingDouble()
  15. 华为将发布定制款“鸿蒙字体”,可以免费商用
  16. (2021系统架构设计师)个人对于软考的一些总结
  17. 大型仓库进销存管理系统php源代码,多仓版进销存管理系统PHP源码ERP仓库管理系统php网络版进销存源码...
  18. iOS动态库重签名步骤
  19. 【FXCG】心态问题出现的原因
  20. 宝塔面板分析网站蜘蛛日志?

热门文章

  1. 买什么样的运动型蓝牙耳机好、运动型蓝牙耳机推荐
  2. 美国习惯用语第24讲:top gun; bottom line
  3. Shell 的string 操作
  4. Dijkstra 单源最短路径算法 Java实现
  5. 网工协议基础(5)ARP协议
  6. requireJS用法
  7. 六月过一旬了,下面剩下不到20天写个简短的计划吧
  8. 火柴人跑酷c++(附源码)
  9. java char unicode_在Java的基本数据类型中,char型采用Unicode编码方案,每个Unicode码占用______字节内存空间,这样,无论是中文_搜题易...
  10. 图像处理(五)——连通域