ebpf xdp和tc


参考链接:

https://toutiao.io/posts/glvi9rz/preview

https://houmin.cc/posts/28ca4f79/

http://arthurchiao.art/blog/understanding-ebpf-datapath-in-cilium-zh/

1.xdp 获得的数据

以太网帧 数据结构体是 ethhdr,使用 xdp_buff 结构体来表示以太网帧的头部

2.tc获得的数据

ip数据报  数据结构体是 sk_buffer

tc BPF hook 的 BPF 程序可以读取 skb 的 markpkt_type、 protocolpriorityqueue_mappingnapi_idcb[]hashtc_classid 、tc_index、vlan 元数据、XDP 层传过来的自定义元数据以及其他信息。 tc BPF 的 BPF 上下文中使用了 struct __sk_buff,这个结构体中的所有成员字段都定 义在 linux/bpf.h 系统头文件。

3.sk_buff 和 xdp_buff 完全不同,二者各有优劣

  • sk_buff 修改与其关联的元数据非常方便,但它包含了大量协议相关的信息(例如 GSO 相关的状态),这使得无法仅仅通过重写包数据来切换协议。
  • 这是因为协议栈是基于元数据处理包的,而不是每次都去读包的内容。因此,BPF 辅助函数需要额外的转换,并且还要正确处理 sk_buff 内部信息。
  • xdp_buff 没有这些问题,因为它所处的阶段非常早,此时内核还没有分配 sk_buff,因此很容易实现各种类型的数据包重写。
  • 但是,xdp_buff 的缺点是在它这个阶段进行 mangling 的时候,无法利用到 sk_buff 元数据。
  • 解决这个问题的方式是从 XDP BPF 传递自定义的元数据到 tc BPF。这样,根据使用场景的不同,可以同时利用这两者 BPF 程序,以达到互补的效果。

 

4.hook 触发点

tc BPF 程序在数据路径上的 ingress 和 egress 点都可以触发;而 XDP BPF 程序只能在 ingress 点触发。内核两个 hook 点:

  • ingress hook sch_handle_ingress():由 __netif_receive_skb_core() 触发
  • egress hook sch_handle_egress():由 __dev_queue_xmit() 触发

__netif_receive_skb_core() 和 __dev_queue_xmit() 是 data path 的主要接收和发送函数,不考虑 XDP 的话(XDP 可能会拦截或修改,导致不经过这两个 hook 点), 每个网络进入或离开系统的网络包都会经过这两个点,从而使得 tc BPF 程序具备完全可观测性。

是否依赖驱动支持

tc BPF 程序不需要驱动做任何改动,因为它们运行在网络栈通用层中的 hook 点。因此,它们可以 attach 到任何类型的网络设备上。

Ingress

这提供了很好的灵活性,但跟运行在原生 XDP 层的程序相比,性能要差一些。然而,tc BPF 程序仍然是内核的通用 data path 做完 GRO 之后、且处理任何协议之前 最早的处理点。传统的 iptables 防火墙也是在这里处理的,例如 iptables PREROUTING 或 nftables ingress hook 或其他数据包包处理过程。

Egress

类似的,对于 egress,tc BPF 程序在将包交给驱动之前的最晚的地方执行,这个地方在传统 iptables 防火墙 hook 之后(例如 iptables POSTROUTING), 但在内核 GSO 引擎之前。

唯一需要驱动做改动的场景是:将 tc BPF 程序 offload 到网卡。形式通常和 XDP offload 类似,只是特性列表不同,因为二者的 BPF 输入上下文、辅助函数和返回码( verdict)不同。支持 offload tc BPF 程序的驱动 Netronome/nfp。

 

相对于DPDK,XDP:

优点

  • 无需第三方代码库和许可

  • 同时支持轮询式和中断式网络

  • 无需分配大页

  • 无需专用的CPU

  • 无需定义新的安全网络模型

缺点

注意XDP的性能提升是有代价的,它牺牲了通用型和公平性

  • XDP不提供缓存队列(qdisc),TX设备太慢时直接丢包,因而不要在RX比TX快的设备上使用XDP

  • XDP程序是专用的,不具备网络协议栈的通用性

如何选择?

  • 内核延伸项目,不想bypass内核的下一代高性能方案;

  • 想直接重用内核代码;

  • 不支持DPDK程序环境;

XDP适合场景

  • DDoS防御

  • 防火墙

  • 基于XDP_TX的负载均衡

  • 网络统计

  • 流量监控

  • 栈前过滤/处理

  • ...