NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

系列解读 SMC-R:融合 TCP 与 RDMA 的 SMC-R 通信(二)

  • 2022-04-24
  • 本文字数:5046 字

    阅读完需:约 17 分钟

系列解读 SMC-R:融合 TCP 与 RDMA 的 SMC-R 通信(二)

通过上一篇文章 《系列解读 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] https://datatracker.ietf.org/doc/html/rfc7609

2022-04-24 15:171997

评论 1 条评论

发布
用户头像
这是阿里那个么
2022-04-27 17:44
回复
没有更多了
发现更多内容

面试多次被拒,“两个月”61天,我收到了蚂蚁金服P7级的offer

Java spring 程序员 架构 编程语言

凌晨加班回家路上捡到阿里技术人限产的MySQL高级笔记及面试宝典,从此我的人生像开挂一样!

Java 架构 面试 程序人生 编程语言

一女程序员因薪酬问题离职,rm -f * 删库,瘫痪6个小时,被判9个月

收到请回复

Java 程序员 面试 面经

升级了 Windows 11 正式版,有坑吗?

王磊

真香!兜兜转转还是得看你“阿里面试参考指南”

Java 程序员 架构 面试 后端

碉堡了!Alibaba爆款Java高并发核心编程手册,在牛博网上被疯狂转载!

Java 架构 面试 程序人生 编程语言

ToB产品如何自传播(上)

石云升

产品经理 产品设计 产品思维 10月月更

Thread 的状态改变操作学习笔记

风翱

Thread 10月月更

神马操作!Kafka 竟然宣布弃用 Java 8

收到请回复

Java kafka 后端 java8

横空出世!IDEA画图神器来了,比Visio快10倍

收到请回复

Java IDEA idea插件

被疫情“带飞”的家庭健身市场,是时候卷起来了

脑极体

Leetcode题目解析:274. H 指数

程序员架构进阶

面试 算法 LeetCode 10月月更

这么卷吗?大三学生喜获阿里提前批

Java 程序员 架构 后端

通关宝典!Java 面试核心知识让你面试过,过,过!

Java 程序员 面试 后端 构架

刚上岸字节年薪60W的Java架构师,耗时半年总结的24W字面试手册

Java 程序员 架构 面试 后端

Node.js 日志最佳实践指南

devpoint

Node console 10月月更

无敌!学透美团老哥的这套微服务进阶学习手册拿个P7还是so easy!

Java 架构 面试 程序人生 编程语言

飞桨与海光人工智能加速卡DCU系列完成互证,助力国产AI加速 卡人工智能应用创新

百度大脑

人工智能 深度学习 飞桨

互动视频和5G的相互成就

脑极体

SpringBoot 实战:在 RequestBody 中优雅的使用枚举参数

看山

Java Spring Boot Effective Spring 10月月更

Java高级、架构师必备!Lucene+ElasticStack入门至项目实战!

Java 架构 面试 程序人生 编程语言

TypeScript 中的 Index Signatures

Regan Yue

typescript ReganYue 10月月更

字节总监毕生心血总结:收获,不止SQL优化抓住SQL的本质

Java 程序员 架构 面试 计算机

谁说GitHub才能出经典?出自牛客网的Java程序员逆袭手册才是YYDS

Java 程序员 架构 面试 计算机

Prometheus 的 Metric 数据类型

耳东@Erdong

Prometheus 10月月更

自定义View:如何绘制一个饼图

Changing Lin

10月月更

发布两小时,霸榜GitHub!Spring Boot实战文档

Java 编程 程序员 后端 计算机

想不到吧!这本字节算法大佬562页《算法中文手册》,在Gihub上排名第一!

Java 架构 面试 程序人生 编程语言

4年CRUD小职员,五面阿里艰苦经历(定薪45K),回馈一波心得体会

收到请回复

Java 程序员 面试 后端 面经

内卷破坏者!“阿里爸爸”全新出品SpringBoot高级笔记(全彩版)

Java 编程 架构 IT 计算机

双非本科毕业竟能四面阿里稳操胜券,轻松拿offer,定级P6+,怎么做到的?!

Java 程序员 架构 面试 后端

系列解读 SMC-R:融合 TCP 与 RDMA 的 SMC-R 通信(二)_文化 & 方法_龙蜥社区高性能网络SIG_InfoQ精选文章