1. 前言
在使用RDMA操作之前,我們需要了解一些RDMA API中的一些需要的值。其中在ibv_send_wr我們需要一個sg_list的數(shù)組,sg_list是用來存放ibv_sge元素,那么什么是SGL以及什么是sge呢?對于一個使用RDMA進行開發(fā)的程序員來說,我們需要了解這一系列細節(jié)。
2. SGE簡介
在NVMe over PCIe中,I/O命令支持SGL(Scatter Gather List 分散聚合表)和PRP(Physical Region Page 物理(內(nèi)存)區(qū)域頁), 而管理命令只支持PRP;而在NVMe over Fabrics中,無論是管理命令還是I/O命令都只支持SGL。
RDMA編程中,SGL(Scatter/Gather List)是最基本的數(shù)據(jù)組織形式。 SGL是一個數(shù)組,該數(shù)組中的元素被稱之為SGE(Scatter/Gather Element),每一個SGE就是一個Data Segment(數(shù)據(jù)段)。RDMA支持Scatter/Gather操作,具體來講就是RDMA可以支持一個連續(xù)的Buffer空間,進行Scatter分散到多個目的主機的不連續(xù)的Buffer空間。Gather指的就是多個不連續(xù)的Buffer空間,可以Gather到目的主機的一段連續(xù)的Buffer空間。
下面我們就來看一下ibv_sge的定義:
struct ibv_sge {
? ? ? ? uint64_t ? ? ? ?addr;
? ? ? ? uint32_t ? ? ? ?length;
? ? ? ? uint32_t ? ? ? ?lkey;
};
addr: 數(shù)據(jù)段所在的虛擬內(nèi)存的起始地址 (Virtual Address of the Data Segment (i.e. Buffer))
length: 數(shù)據(jù)段長度(Length of the Data Segment)
lkey: 該數(shù)據(jù)段對應(yīng)的L_Key (Key of the local Memory Region)
2. ivc_post_send接口
而在數(shù)據(jù)傳輸中,發(fā)送/接收使用的Verbs API為:
ibv_post_send() - post a list of work requests (WRs) to a send queue 將一個WR列表放置到發(fā)送隊列中
ibv_post_recv() - post a list of work requests (WRs) to a receive queue 將一個WR列表放置到接收隊列中
下面以ibv_post_send()為例,說明SGL是如何被放置到RDMA硬件的線纜(Wire)上的。
ibv_post_send()的函數(shù)原型
#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()將以send_wr開頭的工作請求(WR)的列表發(fā)布到Queue Pair的Send Queue。 它會在第一次失敗時停止處理此列表中的WR(可以在發(fā)布請求時立即檢測到),并通過bad_wr返回此失敗的WR。
參數(shù)wr是一個ibv_send_wr結(jié)構(gòu),如<infiniband / verbs.h>中所定義。
3. ibv_send_wr結(jié)構(gòu)
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;
};
在調(diào)用ibv_post_send()之前,必須填充好數(shù)據(jù)結(jié)構(gòu)wr。 wr是一個鏈表,每一個結(jié)點包含了一個sg_list(i.e. SGL: 由一個或多個SGE構(gòu)成的數(shù)組), sg_list的長度為num_sge。
4. RDMA 提交WR流程
下面圖解一下SGL和WR鏈表的對應(yīng)關(guān)系,并說明一個SGL (struct ibv_sge *sg_list)里包含的多個數(shù)據(jù)段是如何被RDMA硬件聚合成一個連續(xù)的數(shù)據(jù)段的。
4.1 第一步:創(chuàng)建SGL
從上圖中,我們可以看到wr鏈表中的每一個結(jié)點都包含了一個SGL,SGL是一個數(shù)組,包含一個或多個SGE。通過ibv_post_send提交一個RDMA SEND 請求。這個WR請求中,包括一個sg_list的元素。它是一個SGE鏈表,SGE指向具體需要發(fā)送數(shù)據(jù)的Buffer。
list<ibv_send_wr> + vector<ibv_sge> + send_flags + 保序 = M : N的Scatter&Gather
4.2 第二步:使用PD進行內(nèi)存保護
我們在發(fā)送一段內(nèi)存地址的時候,我們需要將這段內(nèi)存地址通過Memory Registration注冊到RDMA中。也就是說注冊到PD內(nèi)存保護域當(dāng)中。一個SGL至少被一個MR保護, 多個MR存在同一個PD中。如圖所示一段內(nèi)存MR可以保護多個SGE元素。
4.3 調(diào)用ibv_post_send()將SGL發(fā)送到wire上去
在上圖中,一個SGL數(shù)組包含了3個SGE, 長度分別為N1, N2, N3字節(jié)。我們可以看到,這3個buffer并不連續(xù),它們Scatter(分散)在內(nèi)存中的各個地方。RDMA硬件讀取到SGL后,進行Gather(聚合)操作,于是在RDMA硬件的Wire上看到的就是N3+N2+N1個連續(xù)的字節(jié)。換句話說,通過使用SGL, 我們可以把分散(Scatter)在內(nèi)存中的多個數(shù)據(jù)段(不連續(xù))交給RDMA硬件去聚合(Gather)成連續(xù)的數(shù)據(jù)段。
附錄一: OFED Verbs文章來源:http://www.zghlxwxcb.cn/news/detail-807623.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-807623.html
到了這里,關(guān)于RDMA Scatter Gather List詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!