《Linux内核观测技术BPF》
《Linux内核观测技术BPF》
目录
XDP
介绍
简单介绍
- 是什么: XDP 是 Linux 网络数据路径上内核集成的数据包处理器
- 特点: 安全、可编程、高性能
- 作用: 当网卡驱动程序收到数据包时, 该处理器执行 BPF 程序。这使得 XDP 程序可以在最早的时间点 , 对接收到的数据包进行丢弃、修改或允
许等操作。
注意点:
- 使用 XDP 进行数据包处理时,没有内存分配。
- XDP 程序仅适用于线性的、无碎片的数据包,并且有数据包的头指针和尾指针 。
- XDP 程序无法访问完整的数据包元数据,这种程序接收的输入上下文是
xdp_buff
类型,而不是在第 6 章中提到的sk_buff
结构(比较见下) - 由于 XDP 程序是 eBPF 程序,在网络管道中 XDP 程序的使用开销是固定的,所以 XDP 程序的执行时间有限。
当谈论 XDP 时, 我们需要记住的是 XDP 不是一个内核旁路机制。 XDP 的设计旨在与其他内核组件和 Linux 内部安全模型集成。
xdp_buff vs sk_buff
- XDP 程序无法访问完整的数据包元数据,这种程序接收的输入上下文是
xdp_buff
类型,而不是在第 6 章中提到的sk_buff
结构 xdp_buff
结构可视为sk_buff
的 "轻量级"版本- 两者之间的区别在于:
sk_buff
于保留数据包的元数据,允许与这些数据包的元数据 (包括原型、标记和类型) 联合使用,这些元数据仅在网络管道的更高级别可用。xdp_buf
创建很早,不依赖其他内核层,所以 XDP 可以更快地获得和处理数据包。
- 另一个原因是
xdp_buff
与使用sk_buff
的程序类型有所差异,xdp_buff
并不保存对路由、流量控制钩子或其他类型的数据包元数据的引用。
XDP 程序概述
介绍
作用:
本质上 XDP 程序所做的是对接收的数据包进行决策,然后对接收的数据包内容进行编辑或者仅返回一个结果码。
结果码用于决定对数据包进行的操作。你可以丢弃数据包,或将其发送到同一接口,也可以将其传递给其余的网络栈。
此外, XDP 程序可与网络技协作推送和拉取数据包头。例如,如果当前内核不支持封装格式或协议, XDP 程序可以对其进行解包或转换协议,然后
将结果发送到内核进行处理 。
XDP 和 eBPF 之间有什么关联呢?
XDP 程序是通过 bpf 系统调用进行控制的,使用程序类型 BPF_PROG_TYPE_XDP 进行加载。执行驱动程序将挂钩执行 BPF 字节码。
当编写 XDP 程序时,我们要理解的一个重要慨念是程序运行的上下文,也称为操作模式。
操作模式
XDP 有三种操作模式 :
- 原生 XDP
- 卸载 XDP
- 通用 XDP
(1) 原生 XDP
这是默认模式 。 在这种模式下, XDP 的 BPF 程序在网络驱动程序的早期接收路径之外直接运行。
检查是否支持该模式:
使用此模式时需要检查驱动程序是否支持此模式。你可以在给定内核版本的源代码上执行如下命令进行检查:
# Clone the linux-stab1e repository
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stab1e/linux-stable.git\
linux-stable
# Checkout the tag for your current kernel version
cd linux-stable
git checkout tags/v4.18
# Check the availab1e drivers
git grep -l XDP_SETUP_PROG drivers/
命令输出结果如下:
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
drivers/net/ethernet/cavium/thunder/nicvf main.c
drivers/net/ethernet/intel/i40e/i40e main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main . c
drivers/net/ethernet/mel1anox/mlx4/en netdev.c
drivers/net/ethernet/mel1anox/mlx5/core/en main.c
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/qlogic/qede/qede_filter.c
drivers/net/netdevsim/bpf.c
drivers/net/tun.c
drivers/net/virtio net.c
如我们所见,内核 4 . 18 支持以下驱动:
- Broadcom NetXtreme-C/E 网络驱动 bnxt
- Cavium thunderx 驱动
- lntel i40 驱动
- Intel ixgbe and ixgvevf 驱动
- Mellanox mlx4 and mlx5 驱动
- Netronome 网络流处理器
- QLogic qede NIC 驱动
- TUNrrAP
- Virtio
在熟悉原生 XDP 操作模式 后 ,我们将继续看一 下如何通过网卡使用卸载 XDP 来直接处理 XDP 程序。
(2) 卸载 XDP
(这里翻译成卸载有点……emmm)
在这种模式下 XDP 的 BPF 程序直接卸载到网卡上,而不是在主机 CPU 上执行。因为将执行从 CPU 上移出,所以这种模式比原生 XDP 具有更高的性能。
检查是否支持该模式:
我们可以重复使用克隆的内核源代码,通过查找 XDP_SE TUP_PROG_HW。检查在内核 4.18 上哪些网卡驱动程序支持硬件卸载:
git grep -1 XDP_SETUP_PROG_HW driversl
命令输出如下:
include/linux/netdevice.h
886: XDP_SETUP_PROG_HW, net/core/dev.c
8001: xdp.command XDP_SETUP_PROG_HW;
drivers/net/netdevsim/bpf.c
200: if (bp手-)c创rnand == XDP SETUP PRC巳二刷抽 !ns-)bpf_xd阳忏1oad_accept) {
205: if (bpf• command XDP_SETUP_PROG_HW) {
560: case XDP SETUP PROG HW:
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
3476: case XDP SETUP PROG HW:
这里仅显示了 Netronome Network Flow Processor (nfp)。这意味着该驱动支持硬件卸载 XDP 和原生 XDP 两种操作模式。
现在,你可能要问:如果我没有网卡和驱动程序来测试 XDP 程序,该怎么办?答案很简单,使用通用 XDP!
(3) 通用 XDP
如果开发人员想要编写和运行 XDP 程序,但是没有原生 XDP 或卸载 XDP 的功能,可以使用通用 XDP ,通用 XDP 是一种测试模式。
检查是否支持该模式:
内核从版本 4.12 开始支持通用 XDP。你可以在 veth 设备上使用这种模式。我们将在后续的示例中使用该模式来演示 XDP 的功能,无须购买特定的硬件。
但是,谁负责所有组件和操作模式之间的协调呢?下面我们将介绍数据包处理器。
总结 - 比较三种XDP
数据包处理器
XDP 数据包处理器可以在 XDP 数据包上执行 BPF 程序,并协调 BPF 程序和网络技之间的交互。
数据包处理器是 XDP 程序的内核组件,一旦数据包被网卡接收,数据包处理器直接处理接收 (RX) 队列上的数据包。数据包处理器保证数据包是可读写的,井允许以操作的形式附加处理后决策。数据包处理器可以在运行时原子性地更新程序和加载新程序,并且不会导致网络和相关流量中断服务。在运行时, XDP 可以使用"忙轮询"模式,在这种模式下,CPU 会一直保持处理每个 RX 队列上的数据包,由于避免了上下文切换,可使得数据包到达后立即被处理,无论 IRQ 亲和性如何。另一方面, XDP 可以使用的另一种模式是"中断驱动"模式,在该模式下, CPU 可以进行其他处理,当接收到数据包时,会产生一个事件中断行为指令,通知 CPU 在继续正常处理的同时必须处理一个新事件。