系列解读SMC-R:透明无感提升云上TCP应用网络性能(一)龙蜥技术

系列解读SMC-R:透明⽆感提升云上TCP应⽤⽹络性能(⼀)龙蜥技术
简介:已有的应⽤若想使⽤RDMA技术改造成本⾼,那么有没有⼀种技术是不做任何改造就可以享受RDMA带来的性能优势?
⽂/龙蜥社区⾼性能⽹络SIG
引⾔
Shared Memory Communication over RDMA (SMC-R) 是⼀种基于 RDMA 技术、兼容 socket 接⼝的内核⽹络协议,由IBM 提出并在 2017 年贡献⾄ Linux 内核。SMC-R 能够帮助 TCP ⽹络应⽤程序透明使⽤ RDMA,获得⾼带宽、低时延的⽹络通信服务。阿⾥云云上操作系统 Alibaba Cloud Linux 3 以及龙蜥社区开源操作系统 Anolis 8 配合神龙弹性RDMA (eRDMA) ⾸次将 SMC-R 带上云上场景,助⼒云上应⽤获得更好的⽹络性能:《技术揭秘:阿⾥云发布第四代神龙,SMC-R 让⽹络性能提升 20%》。
由于 RDMA 技术在数据中⼼领域的⼴泛使⽤,龙蜥社区⾼性能⽹络 SIG 认为 SMC-R 将成为下⼀代数据中⼼内核协议栈的重要⽅向之⼀。为此,我们对其进⾏了⼤量的优化,并积极将这些优化回馈到上游 Linux 社区。⽬前,龙蜥社区⾼性能⽹络 SIG 是除 IBM 以外最⼤的 SMC-R 代码贡献团体。由于 SMC-R 相关中⽂资料极少,我们希望通过⼀系列⽂章,让更多的国内读者了解并接触 SMC-R,也欢迎有兴趣
的读者加⼊龙蜥社区⾼性能⽹络 SIG ⼀起沟通交流(⼆维码见⽂末)。本篇作为系列⽂章的第⼀篇,将从宏观的⾓度带领读者初探 SMC-R。
⼀、从 RDMA 谈起
Shared Memory Communication over RDMA 的名称包含了 SMC-R ⽹络协议的⼀⼤特点——基于 RDMA。因此,在介绍 SMC-R 前我们先来看看这个⾼性能⽹络领域中的绝对主⼒:Remote Direct Memory Access (RDMA) 技术。
1.1 为什么需要 RDMA ?
随着数据中⼼、分布式系统、⾼性能计算领域的快速发展,⽹络设备性能进步显著,主流物理⽹络带宽已达到了 25-100 Gb/s,⽹络时延也进⼊了⼗微秒的时代。然⽽,⽹络设备性能提升的同时⼀个问题也逐渐显露:⽹络性能与 CPU 算⼒逐渐失配。传统⽹络中,负责⽹络报⽂封装、解析和⽤户态/内核态间数据搬运的 CPU 在⾼速增长的⽹络带宽⾯前逐渐显得⼒不从⼼,⾯临越来越⼤的压⼒。以 TCP/IP ⽹络的⼀次数据发送与接收过程为例。发送节点 CPU ⾸先将数据从⽤户态内存拷贝⾄内核态内存,在内核态协议栈中完成数据包封装;再由 DMA 控制器将封装好的数据包搬运到NIC 上发送到对端。接收端 NIC 获得数据包后通过 DMA 控制器搬运到内核态内存中,由内核协议栈解析,层层剥离帧⾸或包头后再由 CPU 将有效负载 (payload) 拷贝到⽤户态内存中,完成⼀次数据传输。
(图/传统 TCP/IP ⽹络传输模型)
在这⼀过程中,CPU 需要负责:
1)⽤户态与内核态间的数据拷贝。
2)⽹络报⽂的封装、解析⼯作。
这些⼯作“重复低级”,占⽤了⼤量 CPU 资源 (如 100 Gb/s 的⽹卡跑到满带宽需要打满多个 CPU 核资源),使得 CPU 在数据密集型场景下⽆法将算⼒⽤到更有益的地⽅。
所以,解决⽹络性能与 CPU 算⼒失配问题成为了⾼性能⽹络发展的关键。考虑到摩尔定律逐渐失效,CPU 性能短时间内发展缓慢,将⽹络数据处理⼯作从 CPU 卸载到硬件设备的思路就成为了主流解决⽅案。这使得以往专⽤于特定⾼性能领域的 RDMA 在通⽤场景下得到愈来愈多的应⽤。
1.2 RDMA 的优势
RDMA (Remote Direct Memory Access) 是⼀种远程内存直接访问技术,⾃提出以来经过 20 余年的发展已经成为了⾼
性能⽹络的重要组成。那么 RDMA 是如何完成⼀次数据传输的呢?
(图/⽤户态 RDMA ⽹络传输模型)
RDMA ⽹络 (⽤户态模式) 中,具备 RDMA 能⼒的⽹卡 RNIC 直接从发送端⽤户态内存中取得数据,在⽹卡中完成数据封装后传输到接收端,再由接收端 RNIC 将数据解析剥离,将有效负载 (payload) 直接放⼊⽤户态内存中完成数据传输。这⼀过程中 CPU 除了必要的控制⾯功能外,⼏乎不⽤参与数据传输。数据就像是通过 RNIC 直接写⼊到远程节点的内存中⼀样。因此,与传统⽹络相⽐,RDMA 将 CPU 从⽹络传输中解放了出来,使得⽹络传输就像是远程内存直接访问⼀样⽅便快捷。
(图/传统⽹络与 RDMA ⽹络协议栈对⽐)
对⽐传统⽹络协议,RDMA ⽹络协议具有以下三个特点:
1.旁路软件协议栈
RDMA ⽹络依赖 RNIC 在⽹卡内部完成数据包封装与解析,旁路了⽹络传输相关的软件协议栈。对于⽤户态应⽤程序,RDMA ⽹络的数据路径旁路了整个内核;对于内核应⽤程序,则旁路了内核中的部分协议栈。由于旁路了软件协议栈,将数据处理⼯作卸载到了硬件设备,因⽽ RDMA 能够有效降低⽹络时延。
2.CPU 卸载
RDMA ⽹络中,CPU 仅负责控制⾯⼯作。数据路径上,有效负载由 RNIC 的 DMA 模块在应⽤缓冲区和⽹卡缓冲区中拷贝 (应⽤缓冲区提前注册,授权⽹卡访问的前提下),不再需要 CPU 参与数据搬运,因此可以降低⽹络传输中的 CPU 占⽤率。
3.内存直接访问
RDMA ⽹络中,RNIC ⼀旦获得远程内存的访问权限,即可直接向远程内存中写⼊或从远程内存中读出数据,不需要远程节点参与,⾮常适合⼤块数据传输。
⼆、回到 SMC-R
通过上述介绍,相信读者对 RDMA 主要特点以及性能优势有了初步的了解。不过,虽然 RDMA 技术能够带来可喜的⽹络性能提升,但是想使⽤ RDMA 透明提升现有 TCP 应⽤的⽹络性能仍有困难,这是因为 RDMA ⽹络的使⽤依赖⼀系列新的语义接⼝,包括 ibverbs 接⼝与 rdmacm 接⼝(后统称 verbs 接⼝)。
部分 ibverbs与rdmacm接⼝[1]
相较于传统 POSIX socket 接⼝,verbs 接⼝数量多,且更接近硬件语义。对于已有的基于 POSIX socket 接⼝实现的TCP ⽹络应⽤,想要享受 RDMA 带来的性能红利就不得不对应⽤程序进⾏⼤量改
造,成本巨⼤。
因此,我们希望能够在使⽤ RDMA ⽹络的同时沿⽤ socket 接⼝,使现有 socket 应⽤程序透明的享受 RDMA 服务。
针对这⼀需求,业界提出了以下两个⽅案:
其⼀,是基于 libvma 的⽤户态⽅案。libvma 的原理是通过 LD_PRELOAD 来将应⽤所有 socket 调⽤引⼊⾃定义实现,在⾃定义实现中调⽤ verbs 接⼝,完成数据收发。但是,由于实现在⽤户态,libvma ⼀⽅⾯缺少内核统⼀资源管理,另⼀⽅⾯对 socket 接⼝的兼容性较差。
其⼆,是基于 SMC-R 的内核态⽅案。作为内核态协议栈,SMC-R 对 TCP 应⽤的兼容性相较于⽤户态⽅案会好很多,这种 100% 兼容意味着极低的推⼴和复⽤成本。此外,实现在内核态使得 SMC-R 协议栈中的 RDMA 资源能够被⽤户态不同进程共享,提⾼资源利⽤率的同时降低频繁资源申请与释放的开销。不过,完全兼容 socket 接⼝就意味着需要牺牲极致的 RDMA 性能 (因为⽤户态 RDMA 程序可以做到数据路径旁路内核与零拷贝,⽽ SMC-R 为了兼容 socket 接⼝,⽆法实现零拷贝),但这也换来兼容与易⽤,以及对⽐ TCP 协议栈的透明性能提升。未来,我们还计划拓展接⼝,以牺牲⼩部分兼容性的代价将零拷贝特性应⽤于 SMC-R,使它的性能得到进⼀步改善。
以牺牲⼩部分兼容性的代价将零拷贝特性应⽤于 SMC-R,使它的性能得到进⼀步改善。
2.1 透明替换 TCP
SMC-R is an open sockets over RDMA protocol that provides transparent exploitation of RDMA (for TCP based applications) while preserving key functions and qualities of service from the TCP/IP ecosystem that enterprise level servers/network depend on!
摘⾃:
SMC-R 作为⼀套与 TCP/IP 协议平⾏,向上兼容 socket 接⼝,底层使⽤ RDMA 完成共享内存通信的内核协议栈,其设计意图是为 TCP 应⽤提供透明的 RDMA 服务,同时保留了 TCP/IP ⽣态系统中的关键功能。为此,SMC-R 在内核中定义了新的⽹络协议族 AF_SMC,其 proto_ops 与 TCP ⾏为完全⼀致。
/* must look like tcp */
投票箱制作static const struct proto_ops smc_sock_ops = {
.family = PF_SMC,
.owner = THIS_MODULE,
.release = smc_release,
.bind = smc_bind,
.connect = smc_connect,
.socketpair = sock_no_socketpair,
.accept = smc_accept,
绝缘升降平台.getname = smc_getname,
.poll = smc_poll,
.ioctl = smc_ioctl,
.listen = smc_listen,
按摩锤.shutdown = smc_shutdown,
.setsockopt = smc_setsockopt,
.
刷握getsockopt = smc_getsockopt,
.sendmsg = smc_sendmsg,
.recvmsg = smc_recvmsg,
.mmap = sock_no_mmap,
.sendpage = smc_sendpage,
.splice_read = smc_splice_read,
.splice_read = smc_splice_read,
};
由于 SMC-R 协议⽀持与 TCP ⾏为⼀致的 socket 接⼝,使⽤ SMC-R 协议⾮常简单。总体来说有两个⽅法:
(图/SMC-R 的使⽤⽅法)
其⼀,使⽤ SMC-R 协议族 AF_SMC 开发。通过创建 AF_SMC 类型的 socket,应⽤程序的流量将进⼊到 SMC-R 协议栈;
其⼆,透明替换协议栈。将应⽤程序创建的 TCP 类型 socket 透明替换为 SMC 类型 socket。透明替换可以通过以下两种⽅式实现:
•使⽤ LD_PRELOAD 实现协议栈透明替换。在运⾏ TCP 应⽤程序时预加载⼀个动态库。在动态库中实现⾃定义socket() 函数,将 TCP 应⽤程序创建的 AF_INET 类型 socket 转换为 AF_SMC 类型的 socket,再调⽤标准 socket 创建流程,从⽽将 TCP 应⽤流量引⼊ SMC-R 协议栈。
int socket(int domain, int type, int protocol)
{
int rc;
if (!dl_handle)
initialize();
/* check if socket is eligible for AF_SMC */
if ((domain == AF_INET || domain == AF_INET6) &&
// see kernel code, include/linux/net.h, SOCK_TYPE_MASK
(type & 0xf) == SOCK_STREAM &&
(protocol == IPPROTO_IP || protocol == IPPROTO_TCP)) {
dbg_msg(stderr, "libsmc-preload: map sock to AF_SMC\n");
if (domain == AF_INET)
protocol = SMCPROTO_SMC;
else /* AF_INET6 */
protocol = SMCPROTO_SMC6;
domain = AF_SMC;
}
rc = (*orig_socket)(domain, type, protocol);
return rc;
return rc;
}
开源⽤户态⼯具集 smc-tools 中的 smc_run 指令即实现上述功能[2]。
•通过 ULP + eBPF 实现协议栈透明替换。SMC-R ⽀持 TCP ULP 是龙蜥社区⾼性能⽹络 SIG 贡献到上游 Linux 社区的新特性。⽤户可以通过 setsockopt() 指定新创建的 TCP 类型 socket 转换为 SMC 类型 socket。同时,为避免应⽤程序改造,⽤户可以通过 eBPF 在合适的 hook 点 (如 BPF_CGROUP_INET_SOCK_CREATE、
BPF_CGROUP_INET4_BIND、BPF_CGROUP_INET6_BIND 等) 注⼊ setsockopt(),实现透明替换。这种⽅式更适合在容器场景下可以依据⾃定义规则,批量的完成协议转换。
static int smc_ulp_init(struct sock *sk)
{
struct socket *tcp = sk->sk_socket;
struct net *net = sock_net(sk);
struct socket *smcsock;
大功率led天花灯int protocol, ret;
/* only TCP can be replaced */
if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
(sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
return -ESOCKTNOSUPPORT;
/* don't handle wq now */
if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
return -ENOTCONN;
if (sk->sk_family == AF_INET)
protocol = SMCPROTO_SMC;
else
protocol = SMCPROTO_SMC6;
楔形塞尺smcsock = sock_alloc();
if (!smcsock)
return -ENFILE;
<...>
}

本文发布于:2024-09-25 08:31:26,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/4/158393.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:性能   数据   内核   协议   内存   户态   透明
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议