AF_XDP技术简介
本文分享自天翼云开发者社区@《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,如需转载,请联系作者。
AF_XDP技术简介的更多相关文章
- Java Servlet 技术简介
Java Servlet 技术简介 Java 开发人员兼培训师 Roy Miller 将我们现有的 servlet 介绍资料修改成了这篇易于学习的实用教程.Roy 将介绍并解释 servlet 是什么 ...
- 【转】Android 防破解技术简介
http://www.cnblogs.com/likeandroid/p/4888808.html Android 防破解技术简介 这几年随着互联网的不断发展,Android App 也越来越多!但是 ...
- InfiniBand技术简介
InfiniBand技术简介 转载请在文首保留原文出处:EMC中文支持论坛https://community.emc.com/go/chinese 介绍 随着CPU和通讯处理速度的 ...
- Windows NT 技术简介
Windows NT 技术简介 NT:New Technoly(新技术,因比DOS.WIN9X采用了很多新技术而得名) Windows NT基本介绍 WindowsNT是Microsoft推出的面向工 ...
- CSS border三角、圆角图形生成技术简介
http://www.zhangxinxu.com/wordpress/?p=794 一.前言 利用CSS的border属性可以生成一些图形,例如三角或是圆角.纯粹的CSS2的内容,没有兼容性的问题, ...
- FC总线技术简介
FC是由美国标准化委员会(ANSI)的X3T11小组于1988年提出的高速串行传输总线,解决了并行总线SCSI遇到的技术瓶颈,并在同一大的协议平台框架下可以映射更多FC-4上层协议.FC具备通道和网络 ...
- P2P技术简介
P2P技术简介 NAT( Network Address Translation)穿越(俗称打洞)技术 前言: p2p已经存在于我们生活的方方面面:我们通过下载在工具(比如迅雷,bitorent,各种 ...
- 常见爬虫/BOT 对抗技术简介(二)
上一篇文章分别从网络协议,Robots文件,JS渲染,行为分析等多方面讲了些“反爬虫”,“反-反爬虫”技术. 点击查看:<常见爬虫/BOT 对抗技术简介(一)> 本文将主要介绍各种IP地址 ...
- 【CUDA并行程序设计系列(1)】GPU技术简介
http://www.cnblogs.com/5long/p/cuda-parallel-programming-1.html 本系列目录: [CUDA并行程序设计系列(1)]GPU技术简介 [CUD ...
- Android 防破解技术简介
Android 防破解技术简介 这几年随着互联网的不断发展,Android App 也越来越多!但是随之而来的问题也越来越多,这其中比较令人头疼的问题就是:有些不法分子利用反编译技术破解 App,修改 ...
随机推荐
- WPF VB.NET 代码实现界面动画效果
WPF VB.NET 代码实现界面动画效果 Imports System.Windows.Media.Animation 例子: Dim result As New Storyboard Dim an ...
- Python在字典中通过键名查找键值
def find(target, dict_data): """ :param target: 需要查找的键名 :param dict_data: 需要查找的列表 :re ...
- 记录搜索的例子 浙大c
#include <stdio.h> struct{ int amount; char *name; } coins[] = { {1, "penny"}, {5, & ...
- Informatica常用组件整理
1. 表达式转换组件 (expression) expression 属于被动组件类型(passive),是一种行级表达式,不改变数据行数,功能强大,操作简单. 主要在以下情况下应用: 对流入数据的类 ...
- NOIP2014普及组
T2]比例简化 其实比较简单,主要是比较的方法以前没看过吧 要学会知识迁移啊! #include<iostream> #include<cstring> #include< ...
- 入门文章学习(一)-Beginner Tutorial
Abstract: 参照"背景知识查阅"一文的学习路径,对几篇文章的学习做了记录.这是"Beginner Tutorial"一文的学习笔记. 文章链接: htt ...
- CentOS7带图形界面不能扫描网卡。
CentOS7在带有图形界面,在配置/sysconfig/network-script/ifcfg-ens*后不能识别到网卡,有可能是NetworkManager打开导致,可以使用systemctl ...
- vuw3学习大全(2)
# composition(组合式api) ## 1.为什么使用composition vue3里面不需要Mixins了?因为有compoition api 能讲逻辑进行抽离和复用 大型组件中,其中* ...
- 2022.07.25 TypeScript基础类型介绍
基础类型: 字符串(string)(String) let first: string = 'niu' // 直接赋值 let fourth: string = `niu` // 模板字符串 let ...
- 【Golang】Demo
并发控制 package main // demo 参考地址https://studygolang.com/articles/25950 import ( "github.com/siddo ...