写点什么

系列解读 smc-金马国际

  • 2022 年 4 月 24 日
  • 本文字数:5046 字

    阅读完需:约 17 分钟

通过上一篇文章 《系列解读 smc-r:透明无感提升云上 tcp 应用网络性能(一)》我们了解到,rdma 相对于 tcp 具有旁路软件协议栈、卸载网络工作到硬件的特点,能有效增加网络带宽、降低网络时延与 cpu 负载。而内核网络协议 smc-r 在利用 rdma 技术的同时、又进一步完美兼容了 socket 接口,能够透明无感的为 tcp 应用带来网络性能提升。因此,龙蜥社区高性能网络 sig 认为 smc-r 将成为下一代数据中心内核协议的重要组成,对其进行了大量优化,并积极将这些优化回馈到上游 linux 社区。


本篇文章作为 smc-r 系列的第二篇,将聚焦一次完整的 smc-r 通信流程。通过具体的建连、传输、销毁过程,使读者进一步体会到 smc-r 是一个融合了通用 tcp 与高性能 rdma 的 "hybrid" 金马国际的解决方案。

通信流程


如前篇所述,使用 smc-r 协议有两种方法。其一,是在应用程序中显式创建 af_smc 族的 socket;其二,是利用 ld_preload 或 ulp ebpf 的方式透明的将应用程序中的 af_inet 族 socket 替换为 af_smc 族 socket。


我们默认使用 smc-r 通信的节点已经加载了 smc 内核模块,并通过上述方式将应用程序运行在 smc-r 协议上。接下来,我们以 first contact  (通信两端建立首个连接) 场景为例,介绍 smc-r 通信流程。

确认对端能力


使用 smc-r 通信时,我们首先需要确认对端是否同样支持 smc-r 协议。因此,smc-r 协议栈为应用程序创建 smc 类型 socket (smc socket) 的同时,还会在内核创建并维护一个与之关联的 tcp 类型 socket (clcsock),并基于 clcsock 与对端建立起 tcp 连接。


(图/tcp 握手确认对端 smc-r 能力)


在 tcp 连接三次握手中,使用 smc-r 协议的一端发送的 syn/ack 中携带了特殊的 tcp 选项 (kind = 254,magic number = 0xe2d4),用于表明自身支持 smc-r。通过检查对端发送的 syn/ack,通信节点得知其 smc-r 能力,进而决定是否继续使用 smc-r 通信。


(图/三次握手携带特殊 tcp 选项[1])


(图/代表 smc-r 的 tcp 选项)

协议回退


若在上述 tcp 握手过程中,通信两端其一表示无法支持 smc-r,则进入协议回退 (fallback) 流程。

协议回退时,应用程序所持有的 fd 对应的 smc socket 将被替换为 clcsock。从此,应用程序将使用 tcp 协议通信,从而确保数据传输不会因为协议兼容问题而中断。


需要注意的是,协议回退仅发生在通信协商过程中,如前文提到的 tcp 握手阶段,或是下文提到的 smc-r 建连阶段。为便于跟踪诊断,smc-r 协议详细分类了潜在的回退可能,用户可以通过用户态工具 smc-tools 观测到协议回退事件及原因。


(图/smc-tools 观测回退现象)

建立 smc-r 连接


若在 tcp 握手中,两端均表示支持 smc-r,则进入 smc-r 建连流程。smc-r 连接的建立依赖 tcp 连接传递控制消息,这种控制消息被称为 connection layer control (clc) 消息。


(图/使用 clc 消息建立 smc-r 连接)


clc 消息的主要职责是同步通信两端的 rdma 资源以及共享内存等信息。使用 clc 消息建立 smc-r 连接的过程与 ssl 握手类似,主要包含 proposal、accept、decline、confirm 等语义。在建连过程中,若遇到不可恢复的异常 (如 rdma 资源失效) 导致后续 smc-r 通信无法继续,也将触发前文所述的协议回退流程。


(图/smc-r 握手过程[1])


first contact 场景下,由于通信两端首次接触,两者间尚不存在使用 rdma 通信的条件。所以,在建立首个 smc-r 连接时,还将创建 smc-r 通信所需的 rdma 资源,建立 rdma 链路,申请 rdma 内存。


创建 rdma 资源


smc-r 建连初期,两端根据应用程序传递的 ip 地址在本地寻找可用 (如相同 pnet id) 的 rdma 设备,并基于找到的设备创建必要的 rdma 资源,包括 queue pair (qp),completion queue (cq),memory region (mr),protect domain (pd) 等等。


其中,qp 与 cq 是 rdma 通信的基础,提供了一套 rdma 使用者 (如 smc 内核协议栈) 与 rdma 设备 (rnic) 之间的异步通信机制。


qp 本质是存放工作任务 (work request, wr) 的工作队列 (work queue, wq)。负责发送任务的 wq 称为 send queue (sq),负责接收任务的 wq 称为 receive queue (rq),两者总是成对出现,称为 qp。用户将希望 rnic 完成的任务打包为工作队列元素 (work queue element, wqe),post 到 qp 中。rnic 从 qp 中取出 wqe,完成 wqe 中定义的工作。


cq 本质是存放工作完成信息 (work completion, wc) 的队列。rnic 完成 wr 后,将完成信息打包为完成队列元素 (completion queue element, cqe) 放入 cq 中。用户从 cq 中 poll 出 cqe,获悉 rnic 已经完成某个 wr。


(图/)rdma 工作队列模型)


建立 rdma 链路


通信两端将已创建的 rdma 资源通过 clc 消息同步到对端,进而在两端之间建立起基于 rc (reliable connection) qp 的 rdma 链路。smc-r 中将这种点对点逻辑上的 rdma 链路称为 smc-r link。一条 smc-r link 承载着多条 smc-r 连接的数据流量。


(图/smc link)


若通信节点之间存在不止一对可用的 rnic,则会建立不止一条 link。这些 link 在逻辑上组成一个小组,称为 smc-r link group。


(图/smc-r link group)


在 linux 实现中,每个 link group 具备 1-3 条 link,最多承载 255 条 smc-r 连接。这些连接被均衡的关联到 link group 的某一 link 上。应用程序通过 smc-r 连接发送的数据将由关联的 link (也即 rdma 链路) 传输。


同一个 link group 中,所有的 link 互相“平等”。这个“平等”体现在同一 link group 中的 link 具备访问 group 中所有 smc-r 连接收发缓冲区 (下文提到的 sndbuf 与 rmb) 的权限,具备承载任意 smc-r 连接数据流的能力。因此,当某一 link 失效时 (如 rnic down),关联此 link 的所有连接可以迁移到同 link group 的另一条 link 上。这使得 smc-r 通信稳定可靠,具备一定的容灾能力。


smc-r 中,link (group) 在 first contact 时创建,在最后一条 smc-r 连接断开一段时间 (linux 实现中为 10 mins) 后销毁,具备比连接更长的生命周期。first contact 之后创建的 smc-r 连接都将尝试复用已有的 link (group)。这样的设计充分利用了已有的 rdma 资源,避免了频繁创建与销毁带来的额外开销。


申请 rdma 内存


smc-r 协议栈为每条 smc-r 连接分配了独属的收发缓冲区:sndbuf (发送缓冲区) 与 rmb (接收缓冲区,remote memory buffer)。这是两片地址连续,长度在 16 kb ~ 512 kb 间的内核态 ring buffer。

(图/smc-r 连接 ring buffer)


其中,sndbuf 用于存放连接待发送的数据,被注册为 dma 内存。本地 rnic 设备可以直接访问 sndbuf,从中取走有效负载 (payload)。而 rmb 用于存放远程节点 rnic 写入的数据,即连接待接收的数据。由于需要被远程节点访问,因此 rmb 被注册为 rdma 内存。


注册 rdma 内存的过程称为 memory registration,主要完成以下操作:


  • 生成地址翻译表


rdma 使用者 (如本地/远程 smc-r 协议栈) 通常使用虚拟地址 (va) 描述内存,而 rnic 则通过物理地址 (pa) 寻址。rnic 从 wqe 或数据包中取得数据 va 后通过查表得到 pa,进而访问正确内存空间。因此 memory registration 首要任务就是形成目标内存的地址翻译表。


  • pin 住内存


现代 os 会置换暂不使用的内存数据,这将导致地址翻译表中的映射关系失效。因此,memory registration 会将目标内存 pin 住,锁定 va-to-pa 映射关系。


  • 限制内存访问权限


为避免内存非法访问,memory registration 会为目标内存生成两把内存密钥:local key (l_key) 和 remote key (r_key)。内存密钥实质是一串序列,本地或远端凭借  l_key 或 r_key 访问 rdma 内存,确保内存访问合法。


smc-r 中,远程节点访问本地 rmb 所需的 addr 与 r_key 被封装为远程访问令牌 (remote token, rtoken),通过 clc 消息传递到远端,使其具备远程访问本地 rmb 的权限。


smc-r 连接销毁后,对应的 sndbuf 与 rmb 将被回收到 link group 维护的内存池中,供后续新连接复用,以此减小 rdma 内存创建/销毁对建连性能的影响。


(图/sndbuf / rmb 内存池)

验证 smc-r link


由于 first contact 场景下新建立的 smc-r link 尚未经过验证,所以在正式使用 link 传输应用数据前,通信两端会基于 link 发送 link layer control (llc) 消息,用于检验 link 是否可用。


(图/使用 llc 消息确认 smc link 可用)


llc 消息通常为请求-回复模式,用于传输 link 层面的控制信息,如添加/删除/确认 link,确认/删除 r_key 等。


(图/llc 消息请求-回复模式)


类型
说明
add_link
向 link group 中添加新的 link。
confirm_link
确认新创建的 link 是否能够正常工作。
delete_link
删除一个特定的 link 或整个 link group。
confirm_rkey
新增 rmb 时通知 link 对端。
delete_rkey
删除一个或多个 rmb 时通知 link 对端。
test_link
确认 link 是否健康、活跃。

(表/典型 llc 消息含义)


llc 消息的传输基于 rdma 的 send 操作完成,与之相对的是后文提到的 rdma write 操作。


(图/send 操作)


send 操作又被称为“双边操作”,这是因为 send 操作要通信两端都参与进来。一次 send 的传输过程为:


  • 接收端 rdma 使用者 (smc-r 内核协议栈) 向本地 rq 中 post rwqe,rwqe 中记录了待接收数据的长度以及预留内存地址;

  • 发送端 rdma 使用者 (smc-r 内核协议栈) 向本地 sq 中 post swqe,swqe 中记录了待发送数据长度和内存地址。发送端 rnic 根据 swqe 记录的信息取出相应长度的数据发送到对端;

  • 接收端 rnic 接收到数据后,取出 rq 中的第一个 rwqe,依照其中记录的内存地址和长度存放数据。


通过在 link 上收发 confirm_link 类型的 llc 消息,通信两端确认了新创建的 link 具备 rdma 通信的能力,可以用于传输 smc-r 连接数据。

基于共享内存通信


通过上述重重步骤,first contact 场景下 smc-r 建连工作终于结束。接下来,应用程序将通过已建立好的 smc-r 连接传输数据。


(图/基于 rdma 共享内存通信)


应用程序下发到 smc-r 连接中的数据由关联的 link 通过 rdma write 操作写入远程节点 rmb 中。


(图/rdma write 操作)


与上文提到的 send 操作不同,rdma write 又被称为“单边操作”。这是因为数据传输只有 rdma write 发起的一方参与,而接收数据一方的 rdma 使用者完全不参与数据传输,也不知晓数据的到来。一次 rdma write 操作过程如下:


  • 前期准备阶段,接收端 rdma 使用者 (smc-r 内核协议栈) 将接收缓冲区注册为 rdma 内存,将远程访问密钥 rkey 告知发送端,使其拥有直接访问接收端内存的权限,这个过程我们在前文介绍过。

  • 发送端 rdma 使用者 (smc-r 内核协议栈) 向 sq 中 post swqe。与 send 不同的是,rdma write 的 swqe 中不仅包含数据在本地的内存地址和长度,还包含数据即将存放在接收端的内存地址,以及访问接收端内存所需的 r_key。发送端 rnic 根据 swqe 中记录的信息将数据传输到接收端。

  • 接收端 rnic 核实数据包中的 r_key,将数据存放到指定内存地址中。此时的接收端 rdma 使用者并不知道数据已经被写入内存。


由于 rdma write 操作不需要接收端 rdma 使用者参与,因此非常适合大量数据的直接写入。不过,由于接收端并不知晓数据到来,发送端写入数据后需要通过 send 操作发送控制消息通知接收端。在 smc-r 中,这种控制消息称为 connection data control (cdc) 消息。cdc 消息中包含 rmb 相关控制信息用以同步数据读写。


内容
含义
sequence number
cdc 消息序列号
alert token
发送此消息的 smc-r 连接 id
producer cursor
rmb 数据生产游标 (写者更新)
producer cursor wrap seqno
rmb 数据生产 wrap 次数 (写者更新)
consumer cursor wrap seqno
rmb 数据消费wrap 次数 (读者更新)
consumer cursor
rmb 数据消费 游标 (读者更新)

(表/cdc 消息主要内容)


在系列文章的第一篇中我们提到,smc-r 名称中的“共享内存”指的是接收端的 rmb。结合上述的 rdma write 操作与 cdc 消息,smc-r 的共享内存通信流程可以总结为:


(图/共享内存通信细节)


  • 发送端的数据通过 socket 接口,由应用缓冲区拷贝至内核 sndbuf 中 (图中未画出 sndbuf)

  • 协议栈通过 rdma write 单边操作将数据写入接收端 rmb 中

  • 发送端通过 send 双边操作发送 cdc 消息告知接收端有新的数据到来

  • 接收端从 rmb 中拷贝数据至应用缓冲区

  • 接收端通过 send 双边操作发送 cdc 消息告知发送端 rmb 中部分数据已被使用

连接关闭与资源销毁


结束数据传输后,主动关闭方发起 smc-r 连接关闭流程。与 tcp 相似,smc-r 连接也存在半关闭/全关闭状态。断开的 smc-r 连接与 link (group) 解绑,相关的 sndbuf 与 rmb 也将被回收到内存池中,等待复用。同时,与 smc-r 连接关联的 tcp 连接也进入关闭流程,最终释放。


若 link (group) 中不再存在活跃的 smc-r 连接,则等待一段时间后 (linux 实现中为 10 mins) 进入 link (group) 销毁流程。销毁 link (group) 将释放与之相关的所有 rdma 资源,包括 qp、cq、pd、mr、以及所有的 sndbuf 与 rmb。link (group) 销毁后,再次创建 smc-r 连接则需要重新经历 first contact 流程。

总结


本篇作为 smc-r 系列文章的第二篇,以 first contact 场景为例,介绍了完整的 smc-r 通信流程。


包括:通过 tcp 握手确认对端 smc-r 能力;使用 tcp 连接传递 clc 消息,交换 rdma 资源、创建 rdma 链路、建立 smc-r 连接;通过 rdma send 操作发送 llc 消息验证 link 可用;基于 link 使用 rdma write 传输应用程序数据,并利用 cdc 消息同步 rmb 中数据变化;关闭 smc-r、tcp 连接,销毁 rdma 资源等一系列过程。


上述过程充分体现了 smc-r 的 "hybrid" 特点。smc-r 既利用了 tcp 的通用性 ,如通过 tcp 连接确认对端能力,建立 smc-r 连接与 rdma 链路;又利用了 rdma 的高性能 ,如通过 link 传输应用程序数据流量。正因为如此,smc-r 能够在兼容现有 tcp/ip 生态系统关键功能的同时为 tcp 应用提供透明无感的网络性能提升。


参考链接:

[1]

2022 年 4 月 24 日 15:171236

评论 1 条评论

发布
这是阿里那个么
2022 年 04 月 27 日 17:44
回复
没有更多了
发现更多内容
网站地图