根据众多博客资料,言简意赅的介绍xdp-ebpf. 小白一个,个人理解。勿喷!
1、bfp:
Berkeley Packet Filter, 用于过滤filter 网络报文packet的架构。
是tcpdump(linux)和wireshark(windows)乃至网络监控(network monitoring)领域的基石。
其背后的思想是:“与其把数据包复制到用户空间执行用户态程序过滤,不如把过滤程序灌进内核去”
简单来讲,BPF是一套完整的计算机体系结构 。和x86,ARM这些类似,BPF包含自己的指令集和运行时逻辑,同理,就像在x86平台编程,
最终要落实到x86汇编指令一样,BPF字节码也可以看成是汇编指令的序列。我们通过tcpdump的-d/-dd参数可见一斑:
[root@localhost ~]# tcpdump -i any tcp and host 1.1.1.1 -d
(000) ldh [14]
(001) jeq #0x86dd jt 10 jf 2
(002) jeq #0x800 jt 3 jf 10
(003) ldb [25]
(004) jeq #0x6 jt 5 jf 10
(005) ld [28]
(006) jeq #0x1010101 jt 9 jf 7
(007) ld [32]
(008) jeq #0x1010101 jt 9 jf 10
(009) ret #262144
(010) ret #0
[root@localhost ~]#
bpf的核心功能包括:
a)过滤filter:根据外界输入的规则过滤报文;
b) 复制copy:将符合条件的报文由内核空间复制到用户空间
以tcpdump为例:
位于内核之中的 BPF 模块是整个流程之中最核心的一环:
它一方面接受 tcpdump 经由 libpcap 转码而来的滤包条件(Pseudo Machine Language) ,
另一方面也将符合条件的报文复制到用户空间最终经由 libpcap 发送给 tcpdump。
bpf设计
途经网卡驱动层的报文在上报给协议栈的同时会多出一路来传送给BPF,再经后者过滤后最终拷贝给用户态的应用。
2、eBPF
eBPF是最新加入linux内核模块,源于bpf,后来加入了JIT, 使得它实际上成了一个虚拟机。
eBPF 程序支持自己的字节码语言,基于该字节码语言编译成内核原生代码,就像 BPF 程序一样。
eBPF在内核中运行。
eBPF 程序对内核内存访问是有限制的。只能通过内核提供的函数去获取严格限制的必须的内存。
eBPF可以和User空间的程序通过 BPF Map进行通讯。
eBPF 必须编译成字节码才能使用。
3、bcc
直接手写ebpf字节码显得非常笨拙又低效,于是人们开始使用c语言直接编写ebpf程序,然后使用编译器将其编译成为eBPF字节码。
目前支持eBPF字节码的编译器只有llvm,即使是gcc编译过的内核bpf范例调用也要通过llvm编译后才能执行。直接对ebpf编程还是非常困难,
为了便于使用,出现了很多ebpf框架便于我们使用,如bcc和bpftrace。
4、xdp
如何用eBPF实现一个学习型网桥: https://www.hy-print.com/licai/69858.html
XDP, eXpress Data Path, 它其实是位于网卡驱动程序里的一个快速处理包的HOOK点。
为什么快?
--数据包处理位于非常底层(在网卡的驱动程序处),避免了很多内核skb处理开销(socket buffer, 数据包的管理结构);可以将很多处理逻辑offload到网卡硬件。
--显而,在XDP这个HOOK点灌进来一点eBPF字节码,将是一件令人愉快的事情。
5、流程图
注:用户态的程序通过响应 perf-event 事件进行收包,即使是在XDP_DROP动作下。
通常就是设置xdp_drop 动作下,来进行高速抓包。其他动作会影响性能。
推荐>
【超全】深入理解 BPF:一个阅读清单 https://linux.cn/article-9507-1.html
github 源码:
https://github.com/cloudflare/xdpcap
https://github.com/xdp-project/xdp-tutorial/