AF_XDP技术简介

天翼云开发者社区
• 阅读 358

本文分享自天翼云开发者社区@《AF_XDP技术简介》,作者: l****n

一.概述 AF_XDP 是一项新增的,针对高性能数据包处理进行优化的地址族协议。 本文档假设读者已经熟悉 BPF 和 XDP。如果没有,可以参考开源Cilium 项目在 (http://cilium.readthedocs.io/en/latest/bpf/ ) 通过XDP 的 XDP_REDIRECT 操作,XDP程序可以使用 bpf_redirect_map() 函数将入口帧重定向到其他启用 XDP 的网络设备。AF_XDP 套接字使 XDP 程序能够将帧重定向到用户程序中的一块内存缓冲区。

AF_XDP 套接字 (以下简称XSK) 可以使用通用的socket() 系统调用创建。与每个 XSK 相关的有两个环:RX Ring和 TX Ring。套接字可以在 RX 环上接收数据包,也可以在 TX 环上发送数据包。这些环分别使用 setsockopts XDP_RX_RING 和 XDP_TX_RING 注册和调整大小。每个socket必须至少有一个这样的环。RX 或 TX 描述符环指向称为 UMEM中的数据缓冲区。RX 和 TX 可以共享相同的 UMEM,因此不必在 RX 和 TX 之间复制数据包。此外,如果一个数据包由于可能重新传输而需要保留一段时间,则可以将指向该数据包的描述符更改为指向另一个并立即重新使用。这避免了再次复制数据。

UMEM 由许多大小相同的块组成。环中的描述符通过引用其地址来引用帧。addr 只是整个 UMEM 区域内的偏移量。用户空间可以使用合适的任何方式(比如malloc、mmap、大页面等)为此 UMEM 分配内存。然后使用新的 setsockopt XDP_UMEM_REG 向内核注册此内存区域。UMEM 也有两个环:FILL Ring和 COMPLETION Ring。应用程序使用 FILL 环向下发送 addr 以供内核填充 RX 数据包。一旦收到每个数据包,对这些帧的引用就会出现在 RX 环中。另一方面,COMPLETION 环包含内核已完全传输的帧地址,现在可以由用户空间再次使用,用于 TX 或 RX。因此,出现在 COMPLETION 环中的帧地址是先前使用 TX 环传输的地址。总之,RX 和 FILL 环用于 RX 路径,TX 和 COMPLETION 环用于 TX 路径。

套接字最终通过 bind() 系统调用和一个设备上的特定队列 ID 绑定,绑定完成后,流量才开始流动。

如果需要,可以在进程之间共享 UMEM。如果一个进程想要这样做,它只需跳过 UMEM 的注册及其相应的两个环,在绑定调用中设置 XDP_SHARED_UMEM 标志并提交它想要共享 UMEM 的进程的 XSK 以及它自己的新创建 XSK 套接字。然后,新进程将在其自己的 RX 环中接收指向此共享 UMEM 的帧地址引用。请注意,由于环结构是单消费者/单生产者(出于性能原因),新进程必须创建自己的带有相关 RX 和 TX 环的套接字,因为它不能与其他进程共享。这也是每个 UMEM 只有一组 FILL 和 COMPLETION 环的原因。处理 UMEM 是单个进程的责任。

数据包是如何从 XDP 程序分发到 XSK 的呢?有一个称为 XSKMAP(BPF_MAP_TYPE_XSKMAP)的 BPF 映射。用户空间应用程序可以将 XSK 放置在此映射中的任意位置。然后 XDP 程序可以将数据包重定向到此映射中的特定索引,XDP 验证该映射中的 XSK 确实绑定到该设备和环号。如果不是,则丢弃该数据包。如果映射在该索引处为空,则数据包也将被丢弃。

AF_XDP 可以在两种不同的模式下运行:XDP_SKB 和 XDP_DRV。如果驱动程序不支持 XDP,或者在加载 XDP 程序时显式选择了 XDP_SKB,则采用 XDP_SKB 模式,该模式将 SKB复制到用户空间,适用于任何网络设备的后备模式,该模式在协议栈开始处运行。另一方面,如果驱动程序支持 XDP,AF_XDP 代码将使用它来提供更好的性能,但仍有一份数据复制到用户空间。该模式在驱动处运行,性能比XDP_SKB模式好。 文章来源:英文翻译(https://www.kernel.org/doc/html/latest/networking/af_xdp.html)

二.概念 为了使用 AF_XDP 套接字,需要设置许多关联对象。这些对象及其选项将在以下部分中进行说明。 有关 AF_XDP 工作原理的概述,您还可以查看 2018 年有关该主题的 Linux Plumbers 论文:http: //vger.kernel.org/lpc_net2018_talks/lpc18_paper_af_xdp_perf-v2.pdf。不要查阅 2017 年关于“AF_PACKET v4”的论文,这是 AF_XDP 的第一次尝试。从那以后,几乎一切都发生了变化。Jonathan Corbet 还写了一篇关于 LWN 的优秀文章,“使用 AF_XDP 加速网络”。它可以在https://lwn.net/Articles/750845/找到。 UMEM UMEM 是一个虚拟的连续内存区域,被分成大小相等的帧。UMEM 与 netdev 和该 netdev 的特定队列 id 相关联。它是通过使用 XDP_UMEM_REG setsockopt 系统调用创建和配置的(块大小、headroom、起始地址和大小)。UMEM 通过 bind() 系统调用绑定到 netdev 和该netdev的队列 id。

一个 AF_XDP 是连接到单个 UMEM 的套接字,但一个 UMEM 可以有多个 AF_XDP 套接字。要共享套接字 A 创建的 UMEM,下一个套接字 B 可以通过在 struct sockaddr_xdp 成员 sxdp_flags 中设置 XDP_SHARED_UMEM 标志并将 A 的文件描述符传递给 struct sockaddr_xdp 成员 sxdp_shared_umem_fd 来实现。 UMEM 有两个单生产者/单消费者环,用于在内核和用户空间应用程序之间转移 UMEM 帧的所有权。

Rings 有四种不同类型的环:FILL、COMPLETION、RX 和 TX。所有环都是单生产者/单消费者,因此用户空间应用程序需要显式同步多个进程/线程正在读取/写入它们。 UMEM 使用两个环:FILL 和 COMPLETION。每个与 UMEM 关联的套接字必须有一个 RX 队列、TX 队列或两者兼有。 这些环是基于头部(生产者)/尾部(消费者)的环。生产者将数据写入struct xdp_ring生产者成员指向的索引处,并增加生产者索引。消费者读取struct xdp_ring消费者成员指向的索引处的数据环,并增加消费者索引。 环是通过 _RING setsockopt 系统调用配置和创建的,然后使用 mmap() 的适当偏移量(XDP_PGOFF_RX_RING、XDP_PGOFF_TX_RING、XDP_UMEM_PGOFF_FILL_RING 和 XDP_UMEM_PGOFF_COMPLETION_RING)映射到用户空间。 注:环的大小需要是 2 的大小幂。

UMEM Fill Ring FILL 环用于将 UMEM 的所有权从用户空间转移到内核空间。UMEM 地址在环中传递。例如,如果 UMEM 是 64k 并且每个块是 4k,那么 UMEM 有 16 个块并且可以传递 0 到 64k 之间的地址。 传递给内核的帧用于入口路径(RX 环)。 用户应用程序为该环生成 UMEM 地址。请注意,如果以对齐的块模式运行应用程序,内核将屏蔽传入的地址。例如,对于 2k 的块大小,addr 的 log2(2048) LSB 将被屏蔽掉,这意味着 2048、2050 和 3000 指的是同一个块。如果用户应用程序在未对齐的块模式下运行,那么传入的 addr 将保持不变。

UMEM Completion Ring COMPLETION Ring 用于将 UMEM 的所有权从内核空间转移到用户空间。就像 FILL 环一样,使用 UMEM 索引。 从内核传递到用户空间的帧是已经发送的帧(TX 环),可以再次被用户空间使用。 用户应用程序消费此环中的 UMEM 地址。

RX Ring RX 环是套接字的接收端。环中的每个条目都是一个 struct xdp_desc 描述符。描述符包含 UMEM 偏移量 (addr) 和数据长度 (len)。 如果没有帧通过 FILL 环传递给内核,则没有描述符出现在 RX 环上。 用户应用程序消费此环中的 struct xdp_desc 描述符。

TX Ring TX 环用于发送帧。struct xdp_desc 描述符被填充(索引、长度和偏移量)并传递到环中。 要开始传输,需要 sendmsg() 系统调用。未来可能会放宽。 用户应用程序为、在此环生产struct xdp_desc 描述符。

三.用法 使用 AF_XDP 套接字,有两个部分是需要的。用户空间应用程序和 XDP 程序。有关完整的设置和使用示例,请参阅示例应用程序。用户空间端是 xdpsock_user.c,XDP 端是 libbpf 的一部分。 tools/lib/bpf/xsk.c 中包含的 XDP 代码示例如下: SEC("xdp_sock") int xdp_sock_prog(struct xdp_md ctx) { int index = ctx->rx_queue_index; // A set entry here means that the corresponding queue_id // has an active AF_XDP socket bound to it. if (bpf_map_lookup_elem(&xsks_map, &index)) return bpf_redirect_map(&xsks_map, index, 0); return XDP_PASS; } 一个简单但性能不高的 ring dequeue 和 enqueue 可能如下所示: // struct xdp_rxtx_ring { // __u32 *producer; // __u32 *consumer; // struct xdp_desc *desc; // }; // struct xdp_umem_ring { // __u32 *producer; // __u32 *consumer; // __u64 *desc; // }; // typedef struct xdp_rxtx_ring RING; // typedef struct xdp_umem_ring RING; // typedef struct xdp_desc RING_TYPE; // typedef __u64 RING_TYPE; int dequeue_one(RING *ring, RING_TYPE *item) { __u32 entries = *ring->producer - *ring->consumer; if (entries == 0) return -1; // read-barrier! *item = ring->desc[ring->consumer & (RING_SIZE - 1)]; (ring->consumer)++; return 0; } int enqueue_one(RING *ring, const RING_TYPE *item) { u32 free_entries = RING_SIZE - (ring->producer - ring->consumer); if (free_entries == 0) return -1; ring->desc[ring->producer & (RING_SIZE - 1)] = item; // write-barrier! (ring->producer)++; return 0; }

四.示例应用程序 下面是一个 xdpsock测试应用程序,演示如何将 AF_XDP 套接字与私有 UMEM 一起使用。假设你希望来自端口 4242 的 UDP 流量最终进入队列 16,使用 ethtool启用 AF_XDP: ethtool -N p3p2 rx-flow-hash udp4 fn ethtool -N p3p2 flow-type udp4 src-port 4242 dst-port 4242
action 16 然后可以使用以下命令在 XDP_DRV 模式下运行 rxdrop 基准测试: samples/bpf/xdpsock -i p3p2 -q 16 -r -N 对于 XDP_SKB 模式,使用开关“-S”而不是“-N”。 原文链接:https://www.kernel.org/doc/html/latest/networking/af_xdp.html 作者:kernel development community,如需转载,请联系作者。

点赞
收藏
评论区
推荐文章
Springfox与SpringDoc——swagger如何选择(SpringDoc入门)
本文分享自天翼云开发者社区@《》,作者:才开始学技术的小白0.引言之前写过一篇关于swagger(实际上是springfox)的使用指南(https://www.ctyun.cn/developer/article/371704742199365),涵盖了
如何计算真实的数据库成本
本文分享自天翼云开发者社区《》作者:王乾在云计算占主导地位之前,计算数据库的成本是一个非常简单的等式:软件成本硬件成本数据库成本。如果你选择了一个开源产品,软件成本可能会消失。虽然云计算已经从根本上改变了我们使用和部署软件的方式,但仍有太多人在使用这种过
Stella981 Stella981
3年前
Android调试神器stetho使用详解和改造
本文由云社区发表作者:NaOH概述stetho是Facebook开源的一个Android调试工具,项目地址:facebook/stetho通过Stetho,开发者可以使用chrome的inspect功能,对Android应用进行调试和查看。功能概述stetho提供的功能主要有:Networ
通通透透看无服务器计算:由来、场景和问题
本文分享自天翼云开发者社区@《》,作者:我是小朋友一、无服务器(Serverless)计算是什么云计算涌现出很多改变传统IT架构和运维方式的新技术,比如虚拟机、容器、微服务,无论这些技术应用在哪些场景,降低成本、提升效率是云服务永恒的主题。过去十年来,我们
HPC调度基础:slurm集群的部署
本文分享自天翼云开发者社区@《》,作者:才开始学技术的小白0.引言HPC(HighPerformanceComputing,以下简称HPC)是一个领域,试图在任何时间点和技术上对于相关技术、方法和应用等多种方面实现最大的计算能力;换而言之其目的就是求解一类
使用element-ui 的上传组件upload完成自定义上传到天翼云oss云服务器
本文分享自天翼云开发者社区@《》,作者:我是小朋友首先配置天翼云,如下操作1、要求在使用OOS之前,首先需要在www.ctyun.cn注册一个账号(Account)。创建AccessKeyId和AccessSecretKey。AccessKeyId和Acc
服务器通用背板管理(UBM)实现
本文分享自天翼云开发者社区《》,作者:乘风一UBM概述通过SGPIO进行SAS和SATA背板管理的SCSI机箱服务(SES)标准于2003年首次推出。该规范提供主机控制LED,并允许主机检测槽位和已安装驱动器的存在,以及槽位编号方案。该规范提供了驱动器活动
基于Linux系统的PXE搭建方法
本文分享自天翼云开发者社区《》,作者:tn一、底层环境准备1、安装RedHat7.6系统2、关闭防火墙和Selinuxsystemctlstopfirewalldchkconfigfirewalldoffvim/etc/sysconfig/selinux修
PostgreSQL:内存结构
本文分享自天翼云开发者社区@《》,作者:我是小朋友在Postgresql中,内存大概被分为两块Localmemoryarea:为每一个backendprocess分配的内存Sharedmemoryarea:PostgreSQLserver所有的backgr
隐私计算之浅谈联邦学习
本文分享自天翼云开发者社区《》作者:ln一、背景“数据孤岛”简单的讲,各组织都持有各自的数据,这些数据之间互有关系但又独立存储于各组织。出于安全性、合规性等方面考虑,各组织只能查询、使用己方数据,无法交换其它组织的数据。在联邦学习出现前,针对数据隐私保护的
天翼云开发者社区
天翼云开发者社区
Lv1
天翼云是中国电信倾力打造的云服务品牌,致力于成为领先的云计算服务提供商。提供云主机、CDN、云电脑、大数据及AI等全线产品和场景化解决方案。
文章
675
粉丝
15
获赞
40