XDP 或 eXpress Data Path 在 Linux 内核中提供高性能、可编程的网络数据路径。
XDP 在软件堆栈的最低点提供裸机数据包处理,这使得它非常适合在不影响可编程性的情况下提高速度。
无需修改内核即可通过集成的快速路径动态实现新功能。
XDP 数据包进程包括一个内核组件,该组件通过功能接口直接从驱动程序处理 RX 数据包页面,而无需提前分配 skbuff 或软件队列。 通常,每个 RX 队列分配一个 CPU,但在此模型中,没有锁定 RX 队列,CPU 可以专用于忙轮询或中断模型。
BPF 程序执行诸如数据包解析、表查找、创建/管理有状态过滤器、封装/去封装数据包等处理。
BPF 的可扩展性与数据包检查和操作功能、流和表查找以及利用可移植到用户空间和其他操作系统的 BPF 程序的应用程序处理保持完整。
用例包括
○ 堆栈前处理,如过滤以进行 DOS 缓解
○ 转发和负载均衡
○ 批处理技术,例如通用接收卸载
○ 流量采样、监测
○ ULP 处理(例如消息描述)
如果传统的内核网络堆栈是高速公路,则内核旁路是建立高速列车基础设施的建议,而 XDP 是在高速公路上增加拼车车道的建议。
提高性能的技术
- 无锁
- 批量 I/O 操作
- 忙轮询
- 直接队列访问
- 页面回收,尽可能避免页面分配/空闲
- 无元数据(skbuff)分配的数据包处理
- 高效的表(流状态)查找
- 数据包导向
- 孤立处理,最大限度地减少跨 CPU/NUMA 节点操作
- RX 流哈希
- 常见的 NIC 卸载
- 明智的缓存预取,DDIO
一些硬件要求
- 多队列网卡
- 通用协议通用卸载
○ TX/RX 校验和卸载
○ 接收端缩放 (RSS)
○ 传输分段卸载 (TSO)
- LRO、aRFS、来自设备的流散列是“不错的选择”
XDP数据包处理器:
- 在处理 RX 数据包的内核组件中
- 直接从驱动程序处理 RX “packet-pages”
○ 功能界面
○ 没有提前分配 skbuff,没有 SW 队列
- 名义上为每个 RX 队列分配一个 CPU
○ 无锁RX队列
○ CPU 可以专用于忙轮询或使用中断模式
- BPF 程序执行处理
○ 解析数据包
○ 执行表查找,创建/管理有状态过滤器
○ 操作数据包(例如用于封装/去封装)
○ 退货操作
基本的 XDP 数据包处理器操作
- 转发
○ 可能在数据包修改之后(例如 NAT、ILA 路由器)
○ TX 队列是同一个 CPU 独占的,所以不需要锁
- 丢弃
○ 只是从函数中返回错误
○ 驱动回收页
- 正常接收
○ 分配 skbuff 并接收到堆栈
○ 将数据包转向另一个 CPU 进行处理
○ 允许用户空间的“原始”接口,如 AF_PACKET、netmap
- 通用接收卸载
○ 合并相同连接的数据包
○ 执行大数据包的接收
可编程性
- 数据包检查,BPF 程序发现的动作
○ 灵活(无循环)协议头解析
○ 可能由于流查找而有状态
○ 简单的包字段重写(encap/decap)
- 优化查找
○ 流查找(例如使用设备提供的流哈希)
○ 固定长度查找(例如,ILA 的 64 位标识符查找)
○ 有状态,使临时状态(例如 GRO 需要)
- 可扩展模型
○ 应用程序处理(例如应用层协议 GRO)
○ 利用正在进行的工作将 BPF 卸载到 HW
○ BPF 程序可以移植到用户空间或其他操作系统
依赖关系
主要依赖项是 libbpf、llvm、clang 和 libelf。 LLVM+clang 将我们的受限 C 程序编译成 BPF 字节代码,该代码存储在一个 ELF 目标文件 (libelf) 中,由 libbpf 通过 bpf 系统调用加载到内核中。 一些课程还使用 perf 实用程序通过跟踪点跟踪内核行为。