XDP

XDP

简介

XDP(eXpress Data Path)为Linux内核提供了高性能、可编程的网络数据路径。由于网络包在还未进入网络协议栈之前就处理,它给Linux网络带来了巨大的性能提升(性能比DPDK还要高)。

架构

xdppacketprocessing

特性

  • 在网络协议栈前处理
  • 无锁设计
  • 批量I/O操作
  • 轮询式
  • 直接队列访问
  • 不需要分配skbuff
  • 支持网络卸载
  • DDIO
  • XDP程序快速执行并结束,没有循环
  • Packeting steering

相对于DPDK,XDP具有以下优点

  • 无需第三方代码库和许可
  • 同时支持轮询式和中断式网络
  • 无需分配大页
  • 无需专用的CPU
  • 无需定义新的安全网络模型

操作

1
2
# 检查内核是否支持xdp
$ sudo sysctl net/core/bpf_jit_enable

XDP输入参数

XDP暴露的钩子具有特定的输入上下文,它是单一输入参数。它的类型为 struct xdp_md,在内核头文件bpf.h 中定义,具体字段如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/* user accessible metadata for XDP packet hook
 * new fields must be added to the end of this structure
 */
struct xdp_md {
    __u32 data;        //数据包开始指针
    __u32 data_end;    //数据包结束的指针
    __u32 data_meta;   //XDP程序与其他层交换数据包元数据
    /* Below access go through struct xdp_rxq_info */
    __u32 ingress_ifindex; /* rxq->dev->ifindex */
    __u32 rx_queue_index;  /* rxq->queue_index  */
};

程序执行时,datadata_end字段分别是数据包开始和结束的指针,它们是用来获取和解析传来的数据,第三个值是data_meta指针,初始阶段它是一个空闲的内存地址,供XDP程序与其他层交换数据包元数据时使用。最后两个字段分别是接收数据包的接口和对应的RX队列的索引。当访问这两个值时,BPF代码会在内核内部重写,以访问实际持有这些值的内核结构struct xdp_rxq_info

XDP输出参数

在处理完一个数据包后,XDP程序会返回一个动作(Action)作为输出,它代表了程序退出后对数据包应该做什么样的最终裁决,也是在内核头文件bpf.h 定义了以下5种动作类型:

1
2
3
4
5
6
7
enum xdp_action {
 XDP_ABORTED = 0, // 丢弃数据包并报告一个异常
 XDP_DROP, // 安静的丢弃数据包
 XDP_PASS, // 允许内核栈对数据包进行进一步处理
 XDP_TX, // Transmit from the interface it came from
 XDP_REDIRECT, // Transmit packet from another interface
};

可以看出这个动作的本质是一个int值。前面4个动作是不需要参数的,最后一个动作需要额外指定一个NIC网络设备名称,作为转发这个数据包的目的地。

引入XDP之后网络Data Path

在没有引入XDP之前,原来是的网络数据包传输路径是这样的:

启用XDP后,网络包传输路径是这样的:

可以看到多了3个红色方框圈起来的新链路,我们来一一介绍:

  • offload模式,XDP程序直接hook到可编程网卡硬件设备上,与其他两种模式相比,它的处理性能最强;由于处于数据链路的最前端,过滤效率也是最高的。如果需要使用这种模式,需要在加载程序时明确声明。目前支持这种模式的网卡设备不多,有一家叫netronome
  • native模式,XDP程序hook到网络设备的驱动上,它是XDP最原始的模式,因为还是先于操作系统进行数据处理,它的执行性能还是很高的,当然你的网络驱动需要支持,目前已知的有i40e, nfp, mlx系列ixgbe系列
  • generic模式,这是操作系统内核提供的通用 XDP兼容模式,它可以在没有硬件或驱动程序支持的主机上执行XDP程序。在这种模式下,XDP的执行是由操作系统本身来完成的,以模拟native模式执行。好处是,只要内核够高,人人都能玩XDP;缺点是由于是仿真执行,需要分配额外的套接字缓冲区(SKB),导致处理性能下降,跟native模式在10倍左右的差距。

当前主流内核版本的Linux系统在加载XDP BPF程序时,会自动在native和generic这两种模式选择,完成加载后,可以使用ip命令行工具来查看选择的模式。

updatedupdated2024-05-152024-05-15