Red Hat Training

A Red Hat training course is available for RHEL 8

第 50 章 了解 RHEL 中的 eBPF 网络功能

扩展的 Berkeley Packet 过滤器(eBPF)是一个内核中的虚拟机,允许在内核空间中执行代码。此代码运行在一个受限的沙箱环境中,仅可访问有限功能集。

在网络中,您可以使用 eBPF 来补充或替换内核数据包处理。根据您使用的 hook,eBPF 程序有:

  • 对元数据的读和写的访问权限
  • 可以查找套接字和路由
  • 可以设置套接字选项
  • 可以重定向数据包

50.1. RHEL 中网络 eBPF 功能概述

您可以将扩展的 Berkeley Paket Filter(eBPF)联网程序附加到 RHEL 中的以下 hook:

  • Express Data Path(XDP):在内核网络堆栈处理它们前提供对接收的数据包的早期访问。
  • tc 带有 direct-action 标志的 eBPF 分类器:在入口和出口上提供强大的数据包处理。
  • 控制组群版本 2(cgroup v2):启用过滤和覆盖控制组群中程序执行的基于套接字的操作。
  • 套接字过滤:启用对从套接字接收的数据包进行过滤。这个功能也可用于经典 Berkeley Packet Filter(cBPF),但已扩展为支持 eBPF 程序。
  • 流解析器:启用将流分成单独的消息、过滤并将其重定向到套接字。
  • SO_REUSEPORT 套接字选择:提供从 reuseport 套接字组中可编程选择的接收套接字。
  • 流 dissector:在某些情况下可以覆盖内核解析数据包标头的方式。
  • TCP 阻塞控制回调:启用自定义 TCP 阻塞控制算法。
  • 带有封装的路由: 允许创建自定义隧道封装。

请注意,红帽并不支持 RHEL 中的所有 eBPF 功能,如下所述。如需了解更多与每个 hook 相关的信息,请参阅 RHEL 8 发行注记和以下概述。

XDP

您可以将 BPF_PROG_TYPE_XDP 类型的程序附加到网络接口。然后,在内核网络堆栈开始处理之前,内核会在接收的数据包上执行该程序。这在某些情况下允许快速数据包转发,如快速数据包丢弃,以防止分布式拒绝服务(DDoS)攻击,并为负载平衡场景快速数据包重定向。

您还可以使用 XDP 进行不同类型的数据包监控和抽样。内核允许 XDP 程序修改数据包,并将其传送到内核网络堆栈进行进一步处理。

以下的 XDP 模式可用:

  • 原生(driver)XDP:内核在数据包接收过程中从最先执行该程序。目前,内核无法解析数据包,因此无法使用内核提供的元数据。这个模式要求网络接口驱动程序支持 XDP,但并非所有驱动程序都支持这种原生模式。
  • 通用 XDP:内核网络栈在进程早期执行 XDP 程序。此时内核数据结构已被分配,数据包已被预先处理。如果数据包被丢弃或重定向,与原生模式相比,这需要大量开销。但是,通用模式不需要支持网络接口驱动,它可适用于所有网络接口。
  • Offloaded XDP:内核在网络接口而不是主机 CPU 上执行 XDP 程序。请注意,这需要特定的硬件,这个模式中只有某些 eBPF 功能可用。

在 RHEL 上,使用 libxdp 库载入所有 XDP 程序。这个程序库启用系统控制的 XDP 使用。

注意

目前,XDP 程序有一些系统配置限制。例如:您必须禁用接收接口中某些硬件卸载功能。另外,并非所有功能都可用于支持原生模式的所有驱动程序。

在 RHEL 8.4 中,红帽仅在满足以下条件时支持 XDP 功能:

  • 您可以在 AMD 或者 Intel 64 位构架中载入 XDP 程序。
  • 您可以使用 libxdp 库将程序加载到内核中。
  • XDP 程序不使用 XDP 硬件卸载。

另外,红帽还提供以下使用 XDP 功能作为不受支持的技术预览:

  • 在 AMD 和 Intel 64 位以外的构架中载入 XDP 程序。请注意, libxdp 库不适用于 AMD 和 Intel 64 位以外的构架。
  • XDP 硬件卸载。

AF_XDP

使用过滤并将数据包重定向到给定 AF_XDP 套接字的 XDP 程序,您可以使用 AF_XDP 协议系列中的一个或者多个套接字快速从内核复制到用户空间。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

流量控制

流量控制(tc)子系统提供以下 eBPF 程序类型:

  • BPF_PROG_TYPE_SCHED_CLS
  • BPF_PROG_TYPE_SCHED_ACT

这些类型允许您在 eBPF 中编写自定义 tc 分类器和 tc 操作。这与 tc 生态系统的部分一起,提供了强大的数据包处理能力,也是一些容器联网编配解决方案的核心部分。

在大多数情况下,只有类符被使用,与 direct-action 标记一样,eBPF 分类器可以直接从同一 eBPF 程序执行操作。clsact Queueing Discipline(qdisc)已设计在入口端启用此功能。

请注意,使用一个流 Unsector eBPF 程序可能会影响其他 qdiscstc 类器(如 flower)的操作。

RHEL 8.2 及更新的版本完全支持 tc 功能的 eBPF。

套接字过滤器

一些实用程序会使用或在过去使用了 classic Berkeley Packet Filter(cBPF)过滤套接字上接收到的数据包。例如,tcpdump 实用程序允许用户指定表达式,tcpdump 然后会把它转换为 cBPF 代码。

作为 cBPF 的替代方案,内核允许 BPF_PROG_TYPE_SOCKET_FILTER 类型的 eBPF 程序达到同样目的。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

控制组群

在 RHEL 中,您可以使用多种 eBPF 程序,供您附加到 cgroup。当给定 cgroup 中的某个程序执行某个操作时,内核会执行这些程序。请注意,您只能使用 cgroups 版本 2。

RHEL 中提供以下与网络相关的 cgroup eBPF 程序:

  • BPF_PROG_TYPE_SOCK_OPS:内核在 TCP connect 中调用该程序,并允许在每个套接字设置 TCP 操作。
  • BPF_PROG_TYPE_CGROUP_SOCK_ADDR:内核在 connectbindsendtorecvmsg 操作中调用该程序。该程序允许更改 IP 地址和端口。
  • BPF_PROG_TYPE_CGROUP_SOCKOPT:内核在 setsockoptgetsockopt 操作中调用这个程序并允许修改选项。
  • BPF_PROG_TYPE_CGROUP_SOCK: 内核在套接字创建、套接字释放和绑定到地址时调用这个程序。您可以使用这些程序来允许或拒绝操作,或者只检查套接字创建统计信息。
  • BPF_PROG_TYPE_CGROUP_SKB:此程序在入口和出口中过滤独立的数据包,并可以接受或拒绝数据包。
  • BPF_PROG_TYPE_CGROUP_SYSCTL:该程序允许过滤系统控制(sysctl)的访问。
  • BPF_CGROUP_INET4_GETPEERNAMEBPF_CGROUP_INET6_GETPEERNAMEBPF_CGROUP_INET4_GETSOCKNAMEBPF_CGROUP_INET6_GETSOCKNAME:使用这些程序,您可以覆盖 getsocknamegetpeername 系统调用的结果。当您在 eBPF 中实现基于套接字的网络地址转换(NAT)时,这非常有用。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

流解析器(Stream Parser)

流解析程序在添加到特殊 eBPF 映射的一组套接字上运行。然后 eBPF 程序处理内核接收的数据包或者在那些套接字上发送。

RHEL 中提供了以下流解析程序 eBPF 程序:

  • BPF_PROG_TYPE_SK_SKB:eBPF 程序将从套接字接收的数据包解析到单个消息中,并指示内核丢弃这些信息,或者将其发送到组中的另一套接字。
  • BPF_PROG_TYPE_SK_MSG:此程序过滤出口信息。eBPF 程序将数据包解析到单个信息中,并批准或拒绝它们。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

SO_REUSEPORT 套接字选择

使用这个套接字选项,您可以绑定多个套接字到相同的 IP 地址和端口。如果没有 eBPF,内核会根据连接散列选择接收套接字。使用 BPF_PROG_TYPE_SK_REUSEPORT 程序,选择接收套接字可以完全被编程。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

dissector 流程

当内核需要在不处理全部协议解码的情况下处理数据包标头时,就会出现 dissected。例如:这会在 tc 子系统、多路径路由、绑定或者计算数据包散列时发生。在这种情况下,内核解析数据包的标头,并使用数据包标头中的信息填充内部结构。您可以使用 BPF_PROG_TYPE_FLOW_DISSECTOR 程序替换这个内部解析。请注意,您只能在 RHEL 的 eBPF 的 IPv4 和 IPv6 上分离 TCP 和 UDP。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

TCP 阻塞控制

您可以使用实现了 struct tcp_congestion_oops 回调的 BPF_PROG_TYPE_STRUCT_OPS 程序中的一个自定义 TCP 阻塞控制算法编写自定义 TCP 阻塞控制算法。采用这种方法的算法以及内置的内核算法可供系统使用。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

带有封装的路由

您可以将以下 eBPF 程序类型之一附加到路由表中作为隧道封装属性的路由:

  • BPF_PROG_TYPE_LWT_IN
  • BPF_PROG_TYPE_LWT_OUT
  • BPF_PROG_TYPE_LWT_XMIT

这样的 eBPF 程序的功能仅限于特定的隧道配置,它不允许创建通用封装或封装解决方案。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

套接字查找

要绕过 bind 系统调用的限制,请使用 BPF_PROG_TYPE_SK_LOOKUP 类型的 eBPF 程序。这样的程序可以为进入的 TCP 连接选择侦听套接字,或者为 UDP 数据包选择未连接的套接字。

在 RHEL 8.4 中,红帽将此功能作为不受支持的技术预览提供。

50.2. 根据网卡划分的 XDP 功能概述

以下是启用了 XDP 的网卡和 XDP 功能的概述:

网卡驱动Basic重定向目标HW 卸载zero-copy

Amazon Elastic 网络适配器

ena

Broadcom NetXtreme-C/E 10/25/40igabit Ethernet

bnxt_en

[a] [b]

Cavium Thunder Virtual function

nicvf

Intel® Ethernet Controller XL710 Family

i40e

[a] [b]

Intel® Ethernet Connection E800 Series

ice

[a] [b]

Intel® 10GbE PCI Express adapters

ixgbe

[a] [b]

Intel® 10GbE PCI Express Virtual Function Ethernet

ixgbevf

MellanoxLink 1/10/40Gbit Ethernet

mlx4_en

Mellanox 5th 网络适配器(ConnectX 系列)

mlx5_core

[b]

Netronome® NFP4000/NFP6000 NIC

nfp

QLogic QED 25/40/100Gb Ethernet NIC

qede

Solarflare SFC9000/SFC9100/EF100-family

sfc

[b]

Microsoft Hyper-V 虚拟网络

hv_netvsc

通用 TUN/TAP 设备

tun

虚拟以太网对设备

veth

[c]

QEMU Virtio 网络

virtio_net

[a] [b]

[a] 仅在接口上载入 XDP 程序。
[b] 需要分配的一些 XDP TX 队列,它们大于或等于最大 CPU 索引。
[c] 仅在对等设备中载入 XDP 程序时。

Llegend:

  • Base:支持基本返回代码: DROPPASSABORTEDTX
  • 重定向: 支持 REDIRECT 返回代码。
  • 目标:可以作为 REDIRECT 返回代码的目标。
  • HW offload:支持 XDP 硬件卸载。
  • zero-copy:支持 AF_XDP 协议系列的零复制模式。