0%

eBPF:XDP,内核高速路

诞生背景

Linux内核的TCP/IP协议栈在诞生之初更注重的是通用性,随着技术的发展,10G、25G、100G甚至更高规格的网卡出现,原生的TCP/IP协议栈的开销会更容易被注意到。

在2010年时,Intel领导提出了DPDK高性能网络应用开发解决方案,全称Data Plane Development Kit
DPDK架构图

使用DPDK开发的应用的网络数据包在传递的时候,数据将绕过Linux TCP/IP内核协议栈。

也正式由于DPDK绕开Linux TCP/IP协议栈的原因,Linux开发者们认为,并不是最好的解决方案。2016年,随着eBPF技术的成熟,Linux内核迎来了自己的高速网络通道XDP。

XDP具有在特定使用条件下媲美DPDK性能的同时,能更加与Linux内核整合。但是需要注意的是,目前Linux内核只有ingress链路的XDP能力,对于egress链路的数据,暂时没有XDP支持。

XDP的架构图如下图

XDP架构图
XDP运行在TCP/IP协议栈与网络设备/驱动之间,对于接收到的网络请求,可以更早地执行DROP丢弃或FORWARD转发,并且具备修改网络数据包的能力。

XDP加载模式

XDP有三种加载模式,分别是Generic模式、Native模式和Offload模式,这三种模式运行的注册点位不一样,性能也会有一定区别
性能排序从强到弱:Offload > Native > Generic

1. Generic模式

XDP_FLAGS_SKB_MODE
若网卡和驱动都没原生支持XDP运行的话,Linux内核提供了通用的XDP加载方式,这种方式不需要对驱动程序进行任何修改,hook运行在网络堆栈较后面阶段,因此性能相比另外两种方法较差。

从代码来看,这个模式的hook点位在`

1
static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,struct packet_type **ppt_prev)

在这个方法中通过do_xdp_generic方法来进行处理。

2. Native模式

XDP_FLAGS_DRV_MODE
这种模式需要网卡的驱动程序支持,运行的hook点位挂载在网卡驱动的poll()方法,当驱动rx队列有数据时,就可以立刻进行处理。

这篇博客中记录了 https://blog.csdn.net/already_skb/article/details/123073814

3. Offload模式

XDP_FLAGS_HW_MODE
这种模式需要网卡硬件支持,运行在这种模式时,相关的XDP程序会被加载到网卡上运行,XDP部分的逻辑理论不再需要CPU的占用,但是支持这种模式的网卡不太多,已知支持的是Netronome NFP系列服务器网卡。

1
2
3
4
在CSDN上找到了有一个大佬分析Native和Generic的hook点位的记录,可以看看大佬的文章学习一下找hook点位的过程

Native:https://blog.csdn.net/already_skb/article/details/123073814
Generic:https://blog.csdn.net/already_skb/article/details/123091334

XDP 函数返回值

1
2
3
4
5
XDP_ABORTED = 0,
XDP_DROP,
XDP_PASS,
XDP_TX,
XDP_REDIRECT,
  1. XDP_ABORTED:程序运行异常的时候退出,数据包相当于XDP_DROP,在XDP_DROP的基础上,可以在内核tracepipe中看到异常事件
  2. XDP_DROP:丢弃这个数据包
  3. XDP_PASS:数据包交付到内核TCP/IP协议栈继续传输
  4. XDP_TX:将数据包从接收的网卡发出去
  5. XDP_REDIRECT:类似XDP_TX,但是可以用别的网卡发送

应用XDP技术的项目

负载均衡器:https://github.com/davidcoles/vc5
负载均衡器:https://github.com/MageekChiu/xdp4slb
NetBird团队使用XDP在多个DNS解析器之间共享默认53端口:https://netbird.io/knowledge-hub/using-xdp-ebpf-to-share-default-dns-port-between-resolvers
基于XDP实现类似TCPDUMP功能:https://github.com/xdp-project/xdp-tools/tree/master/xdp-dump


这一篇简单介绍了一下XDP技术,屏幕前的你应该对XDP技术有了一定的了解。在之后的推送中,我会分别利用python+bcc方式和libbpf方式来演示XDP程序的开发,展示对ICMP包进行丢包、修改等操作。