eBPF
eBPF 相当于在内核中有一个运行特定字节码的虚拟机,可以动态将 eBPF 字节码注入进内核。eBPF 程序会 attach 到指定的内核代码路径中,当执行到该代码路径时,会执行对应的 eBPF 程序
XDP
XDP 是专门针对于网络数据,是基于 eBPF 的高性能数据链路。可以在以下三种模式运行:
- Native:工作在网络驱动早期接收队列上
- Offload: 直接运行在网卡中,需要特定的智能网卡支持
- Generic:对于不能支持 Native 和 Offload 模式下, 内核提供一种通用模式。该模式运行在网络协议栈处理早期,不需要特定网卡支持,但性能会远低于以上两种模式 XDP 对每个报文的处理称之为 action,支持以下action:
- DROP: 在驱动层直接丢弃数据包,通常用于丢弃 DDos 攻击报文
- PASS: 允许数据包进入协议栈处理,之后数据包的处理就跟传统的处理方式一样
- TX:可将报文从接收到该报文的 NIC 发送出去
- REDIRECT: 与 TX 模式一样,但是重定向到另一个 NIC 发送出去,或可以将数据包重定向到 AF_XDP socket 的用户空间程序 mmap 映射的内存中
- ABORTED:表示程序发生了异常,效果与 DROP 一样,但可以在用户空间来监控这种异常发生
AF_XDP
区别于传统 socket 数据流经内核协议栈的方式,XDP 程序在网卡驱动中直接取得网卡收到的数据包,然后直接送到用户态应用程序
应用程序利用 AF_XDP 协议族的 socket 接收数据。 XDP 程序会把数据帧送到一个在用户态可以读写的内存中,用户态应可在该内存中直接完成数据包的读取和写入,整个过程是完全 zero copy
UMEM
使用 XDP socket 之前,需要在用户态通过 mmap 创建一段用户空间的内存,称之为 UMEM。这是一段连续的内存,被分割为若干个相同大小的 frame,每个 frame 可容纳一个数据包。
通过 socket 系统调用创建 AF_XDP socket,创建之后每个 socket 都各自分配了一个 RX ring 和 TX ring。这两个 ring 需要通过 socket 选项 XDP_RX_RING 和 XDP_TX_RING 进行注册。每个 socket 必须至少具有其中一个ring。RX 或 TX ring 存储着描述符集合,每个描述符指向 UMEM 中的一个 frame,描述符通过引用 frame 在 UMEM 中的 偏移量来引用 frame。RX 和 TX 可以共享相同的UMEM,所以一个报文无需在 RX 和 TX 之间进行拷贝。
UMEM 也包含两个 ring:Filling ring 和 Completion ring。应用程序会使用 Fill ring 下发描述符,让内核填写 RX 包数据后发送,一旦接收到报文,就绪的描述符也会被填入 RX ring,可以在用户态使用 poll
来等待就绪描述符的到来。通过写入 Completion ring,通知内核有一个或多个数据包已经就绪,请求内核进行数据发送。
本文作者: Ifan Tsai (菜菜)
本文链接: https://cloud.tencent.com/developer/article/2164606
版权声明: 本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!