eBPF 是一项革命性技术,它能在内核中运行沙箱程序(sandbox programs), 而无需修改内核源码或者加载内核模块。
eBPF的一个重要特性是能够使用高级语言(如C)来实现程序。LLVM有一个eBPF后端,用于编辑包含eBPF指令的ELF文件,前端(如clang)可以用于生成程序。
在一个后端转换为字节码后,使用bpf()系统调用加载bpf程序,并校验安全性。JIT会将字节码编译进CPU架构中,并将该程序附加到内核对象上,当这些对象发生事件时会触发程序的执行(例如,当从一个网络接口发送报文时)。
eBPF map是用户空间和内核空间之间的数据交换、信息传递的桥梁。本质上是以「键/值」方式存储在内核中的数据结构,它们可以被任何知道它们的BPF程序访问。在内核空间的程序创建BPF Map并返回对应的文件描述符,在用户空间运行的程序就可以通过这个文件描述符来访问并操作BPF Map,这就是为什么BPF Map在BPF世界中是桥梁的存在了。
1.数据包达到物理网卡(RX FIFO),通过DMA到内存中。内存指的是网卡的接收的Ring Buffer。
2.并且拷贝成一个一个的sk_buffer.
3.触发硬中断,通知CPU,已经有数据来了,CPU根据注册的中断函数,中断函数调用驱动程序,驱动先禁用网卡的中断,目的下次再来数据就直接处理就可以,就不再通知CPU的硬中断。
4.弥补硬中断处理时间问题,需要启用一个软中断。(主要是弥补硬中断处理时间不及的问题)
5.数据单元的sk_buffer然后再交给我们的协议栈处理。实际上就是交给网络层和传输层来处理。[被ip层协议和传输层协议处理]
6.去处掉网络层和传输层的头以后,CPU就把数据Copy到用户空间的应用程序。
网络相关的(子系统),但对于存储和其他系统,问题都是类似的。图中列出了对这些子系统进行操作所需的工具。例如:
配置以太网驱动或者网络设备需要使用 ethtool 命令;
配置路由使用 ip 命令;
配置过滤使用 seccom 命令;
配置 IP 防火墙使用 iptables 命令,但如果你使用的是 raw sockets,那有很多地方都 会 bypass,因此这并不是一个完整的防火墙;
配置流量整形使用 tc 命令;
抓包使用 tcpdump 命令,但同样的,它并没有展示出全部信息,因为它只关注了一层;
如果有虚拟交换机,那使用 brctl 或 ovsctl;
所以我们看到,每个子系统都有自己的 API,这意味着如果要自动化这些东西,必须单独的使用这些工具。有一些工具这样做了,但这种方式意味着我们需要了解其中的每一层。
BPF XDP ---> sk_buffer ---> TC[network stack Dividing Line] ---> IPv4 And IPv6 ---> Netfilter ---> TCP UDP RAW
XDP 代表 eXpress Data Path,提供了 BPF 框架,可在 Linux 内核中实现高性能可编程数据包处理。它在软件中尽早运行 BPF 程序,即在网络驱动程序收到数据包时。
在XDP中,驱动程序只是从ring buff中接收数据包,而没有执行任何其他的操作,例如分配 skb 将数据包进一步推入网络堆栈,也没有将数据包推入 GRO 引擎因此,XDP BPF 程序在 CPU 处理时最早执行。
XDP 中传递给 BPF 程序的数据包表示形式为 BPF 上下文如下所示:
struct xdp_buff {
void *data;
void *data_end;
void *data_meta;
void *data_hard_start;
struct xdp_rxq_info *rxq;
};
处理后返回状态:
enum xdp_action {
XDP_ABORTED = 0,
XDP_DROP,
XDP_PASS,
XDP_TX,
XDP_REDIRECT,
};
XDP_DROP:在驱动层丢弃报文,通常用于实现DDos或防火墙
XDP_PASS:允许报文上送到内核网络栈,同时处理该报文的CPU会分配并填充一个skb,将其传递到GRO引擎。之后的处理与没有XDP程序的过程相同。
XDP_TX:BPF程序通过该选项可以将网络报文从接收到该报文的NIC上发送出去。例如当集群中的部分机器实现了防火墙和负载均衡时,这些机器就可以作为hairpinned模式的负载均衡,在接收到报文,经过XDP BPF修改后将该报文原路发送出去。
XDP_REDIRECT:与XDP_TX类似,但是通过另一个网卡将包发出去。另外, XDP_REDIRECT 还可以将包重定向到一个 BPF cpumap,即,当前执行 XDP 程序的 CPU 可以将这个包交给某个远端 CPU,由后者将这个包送到更上层的内核栈,当前 CPU 则继续在这个网卡执行接收和处理包的任务。这和 XDP_PASS 类似,但当前 CPU 不用去做将包送到内核协议栈的准备工作(分配 skb,初始化等等),这部分开销还是很大的。
XDP_ABORTED:表示程序产生了异常,其行为和 XDP_DROP相同,但 XDP_ABORTED 会经过 trace_xdp_exception tracepoint,因此可以通过 tracing 工具来监控这种非正常行为。
除了XDP之外,BPF 还可以工作在网络数据路径中的内核 TC(流量控制)层。 XDP BPF 程序与 tc BPF 的主要区别:
tc BPF 程序可以在ingress方向触发,也可以网络数据路径中的egress方向触发。
没有eBPF处理丢包的网络包路径:
netfilter 丢包处理的网络包路径:
tc 丢包处理的网络包路径:
XDP 丢包处理的网络包路径:
下面是一张不同的网络包处理技术在处理路径图: