eBPF理解
Posted 为了维护世界和平_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了eBPF理解相关的知识,希望对你有一定的参考价值。
目录
一、编程接口
#include <linux/bpf.h>
int bpf(int cmd, union bpf_attr *attr, unsigned int size);
cmd 类型,attr属性(map)
本文围绕类型,属性(映射),以及程序的分类进行介绍
二、命令码的类型
include/uapi/linux/bpf.h内核头文件中定义
enum bpf_cmd
BPF_MAP_CREATE,
BPF_MAP_LOOKUP_ELEM,
BPF_MAP_UPDATE_ELEM,
BPF_MAP_DELETE_ELEM,
BPF_MAP_GET_NEXT_KEY,
BPF_PROG_LOAD,
BPF_OBJ_PIN,
BPF_OBJ_GET,
BPF_PROG_ATTACH,
BPF_PROG_DETACH,
BPF_PROG_TEST_RUN,
BPF_PROG_GET_NEXT_ID,
BPF_MAP_GET_NEXT_ID,
BPF_PROG_GET_FD_BY_ID,
BPF_MAP_GET_FD_BY_ID,
BPF_OBJ_GET_INFO_BY_FD,
BPF_PROG_QUERY,
BPF_RAW_TRACEPOINT_OPEN,
BPF_BTF_LOAD,
BPF_BTF_GET_FD_BY_ID,
BPF_TASK_FD_QUERY,
BPF_MAP_LOOKUP_AND_DELETE_ELEM,
BPF_MAP_FREEZE,
BPF_BTF_GET_NEXT_ID,
BPF_MAP_LOOKUP_BATCH,
BPF_MAP_LOOKUP_AND_DELETE_BATCH,
BPF_MAP_UPDATE_BATCH,
BPF_MAP_DELETE_BATCH,
BPF_LINK_CREATE,
BPF_LINK_UPDATE,
BPF_LINK_GET_FD_BY_ID,
BPF_LINK_GET_NEXT_ID,
BPF_ENABLE_STATS,
BPF_ITER_CREATE,
BPF_LINK_DETACH,
BPF_PROG_BIND_MAP,
;
BPF辅助函数
可以查询辅助函数
# bpftool feature probe
...
eBPF helpers supported for program type socket_filter:
- bpf_map_lookup_elem
- bpf_map_update_elem
- bpf_map_delete_elem
- bpf_ktime_get_ns
- bpf_get_prandom_u32
- bpf_get_smp_processor_id
- bpf_tail_call
- bpf_perf_event_output
- bpf_skb_load_bytes
...
使用man bpf-helpers或者在内核源码bpf辅助函数中,可以查看其使用说明
三、BPF映射
BPF映射用于提供大块的键值存储,这些存储可被用户空间程序访问,进而获取 eBPF 程序的运行状态。 在eBPF 程序需要大块存储时,就不能像常规的内核代码那样去分配内存了,而是必须通过 BPF 映射(BPF Map)来完成。
bpf_map_type 类型在内核源码 include/uapi/linux/bpf.h
enum bpf_map_type
BPF_MAP_TYPE_UNSPEC,
BPF_MAP_TYPE_HASH,
BPF_MAP_TYPE_ARRAY,
BPF_MAP_TYPE_PROG_ARRAY,
BPF_MAP_TYPE_PERF_EVENT_ARRAY,
BPF_MAP_TYPE_PERCPU_HASH,
BPF_MAP_TYPE_PERCPU_ARRAY,
BPF_MAP_TYPE_STACK_TRACE,
BPF_MAP_TYPE_CGROUP_ARRAY,
BPF_MAP_TYPE_LRU_HASH,
BPF_MAP_TYPE_LRU_PERCPU_HASH,
BPF_MAP_TYPE_LPM_TRIE,
BPF_MAP_TYPE_ARRAY_OF_MAPS,
BPF_MAP_TYPE_HASH_OF_MAPS,
BPF_MAP_TYPE_DEVMAP,
BPF_MAP_TYPE_SOCKMAP,
BPF_MAP_TYPE_CPUMAP,
BPF_MAP_TYPE_XSKMAP,
BPF_MAP_TYPE_SOCKHASH,
BPF_MAP_TYPE_CGROUP_STORAGE,
BPF_MAP_TYPE_REUSEPORT_SOCKARRAY,
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
BPF_MAP_TYPE_QUEUE,
BPF_MAP_TYPE_STACK,
BPF_MAP_TYPE_SK_STORAGE,
BPF_MAP_TYPE_DEVMAP_HASH,
BPF_MAP_TYPE_STRUCT_OPS,
BPF_MAP_TYPE_RINGBUF,
BPF_MAP_TYPE_INODE_STORAGE,
BPF_MAP_TYPE_TASK_STORAGE,
;
通过以下代码创建一个BPF映射,通过用户态程序的系统调用来创建
int bpf_create_map(enum bpf_map_type map_type,
unsigned int key_size,
unsigned int value_size, unsigned int max_entries)
union bpf_attr attr =
.map_type = map_type,
.key_size = key_size,
.value_size = value_size,
.max_entries = max_entries
;
return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
如果eBPF程序使用了BCC库,可以使用预定义的宏简化BPF的映射创建
四、程序的分类
bpf_prog_type
enum bpf_prog_type
BPF_PROG_TYPE_UNSPEC,
BPF_PROG_TYPE_SOCKET_FILTER,
BPF_PROG_TYPE_KPROBE,
BPF_PROG_TYPE_SCHED_CLS,
BPF_PROG_TYPE_SCHED_ACT,
BPF_PROG_TYPE_TRACEPOINT,
BPF_PROG_TYPE_XDP,
BPF_PROG_TYPE_PERF_EVENT,
BPF_PROG_TYPE_CGROUP_SKB,
BPF_PROG_TYPE_CGROUP_SOCK,
BPF_PROG_TYPE_LWT_IN,
BPF_PROG_TYPE_LWT_OUT,
BPF_PROG_TYPE_LWT_XMIT,
BPF_PROG_TYPE_SOCK_OPS,
BPF_PROG_TYPE_SK_SKB,
BPF_PROG_TYPE_CGROUP_DEVICE,
BPF_PROG_TYPE_SK_MSG,
BPF_PROG_TYPE_RAW_TRACEPOINT,
BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
BPF_PROG_TYPE_LWT_SEG6LOCAL,
BPF_PROG_TYPE_LIRC_MODE2,
BPF_PROG_TYPE_SK_REUSEPORT,
BPF_PROG_TYPE_FLOW_DISSECTOR,
BPF_PROG_TYPE_CGROUP_SYSCTL,
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
BPF_PROG_TYPE_CGROUP_SOCKOPT,
BPF_PROG_TYPE_TRACING,
BPF_PROG_TYPE_STRUCT_OPS,
BPF_PROG_TYPE_EXT,
BPF_PROG_TYPE_LSM,
BPF_PROG_TYPE_SK_LOOKUP,
;
也可以使用
bpftool feature probe | grep program_type
应用程序类型大致可以分为三类
1,跟踪,从内核和程序的运行状态中提取跟踪信息
2,网络,对网络数据包进行过滤和处理
3、其他,安全,BPF扩展
跟踪类
主要用于从系统中提取跟踪信息,为监控、排错,性能优化提供数据支撑;
程序的类型有
类型 | 描述 |
BPF_PROG_TYPE_KPROBE | 用于对特定函数进行插装kprobe,uprobe |
BPF_PROG_TYPE_TRACEPOINT | 用于内核静态跟踪点 |
BPF_PROG_TYPE_PERF_EVENT | 用于性能事件跟踪,内核调用,定时器,硬件等 |
网络类
主要用于对网络数据包进行过滤和处理,进而实现网络的观测、过滤、流量控制等功能
又可分为XDP,TC,套接字和cgroup程序
1、XDP程序
类型 :BPF_PROG_TYPE_XDP
在网络驱动程序刚收到数据包时触发,无需通过网络协议栈,可用来实现高性能网络处理方案,常用于DDos防御,防火墙,4层负载均衡等场景。
XDP程序在处理网络包后,有不同处理方式
命令码 | 含义 | 使用场景 |
XDP_DROP | 丢包 | 防火墙,DDOS攻击防御 |
XDP_PASS | 传递到内核协议栈 | 正常处理 |
XDP_TX XDP_REDIRECT | 转发到同一/不同网卡 | 负载均衡 |
XDP_ABORTED | 错误 | XDP处理错误 |
命令行使用
# eth1 为网卡名
# xdpgeneric 设置运行模式为通用模式
# xdp-example.o 为编译后的 XDP 字节码
sudo ip link set dev eth1 xdpgeneric object xdp-example.o
#卸载
sudo ip link set veth1 xdpgeneric off
BCC库函数
from bcc import BPF
# 编译XDP程序
b = BPF(src_file="xdp-example.c")
fn = b.load_func("xdp-example", BPF.XDP)
# 加载XDP程序到eth0网卡
device = "eth0"
b.attach_xdp(device, fn, 0)
...
# 卸载XDP程序
b.remove_xdp(device)
2、TC程序
类型:BPF_PROG_TYPE_SCHED_CLS 和 BPF_PROG_TYPE_SCHED_ACT
分别作为 Linux 流量控制 的分类器和执行器,Linux 流量控制通过网卡队列、排队规则、分类器、过滤器以及执行器等,实现了对网络流量的整形调度和带宽控制。
TC可以直接获取内核解析后的网络报文数据结构sk_buff,可以在发送和接收两个方向上执行
- 接收网络包,TC程序在网卡接收(GRO)之后、协议栈处理之前
- 发送网络包,TC乘坐在协议栈处理之后,数据包发送到网卡队列之前(GOS)执行
# 创建 clsact 类型的排队规则
sudo tc qdisc add dev eth0 clsact
# 加载接收方向的 eBPF 程序
sudo tc filter add dev eth0 ingress bpf da obj tc-example.o sec ingress
# 加载发送方向的 eBPF 程序
sudo tc filter add dev eth0 egress bpf da obj tc-example.o sec egress
Traffic Control HOWTO (linux-ip.net)
3、套接字程序
用于过滤,观测或重定向套接字网络包。
可以挂载到套接字socket,控制组cgroup以及网络命名空间netns等位置
类型以及说明
类型 | 说明 |
BPF_PROG_TYPE_SOCKET_FILTER | 套接字过滤和观测 |
BPF_PROG_TYPE_SOCK_OPS | 套接字修改重定向 |
BPF_PROG_TYPE_SK_SKB | 用于套接字修改或消息流动态解析 |
BPF_PROG_TYPE_SK_MSG | 用于控制内核是否发送消息套解析 |
BPF_PROG_TYPE_SK_REUSEPORT | 控制端口是否重用 |
BPF_PROG_TYPE_SK_LOOKUP | 用于TCP连接选择监听套接字或为UDP数据包选择未连接的套接字,绕过bind系统调用 |
使用例子第一条如:用户态 setsockopt(sock,SOL_SOCKET,SO_ATTACH_BPF,...)绑定BPF到具体的socket上。
4、cgroup程序
对cgroup内所有的进程的网络过滤、套接字选项以及转发等进行动态控制
典型用在容器中多进程进行网络控制
类型及说明
类型 | 说明 |
BPF_PROG_TYPE_CGROUP_SKB | 在入口和出口过滤包,并可以接收或拒绝数据包 |
BPF_PROG_TYPE_CGROUP_SOCK | 在套接字创建、释放和绑定地址时,接受或拒绝操作,也可用于统计套接字信息 |
BPF_PROG_TYPE_CGROUP_DEVICE | 对设备文件访问进行过滤 |
BPF_PROG_TYPE_CGROUP_SOCK_ADDR | 在connect,bind,sendto,recvmsg中修改IP地址和端口 |
BPF_PROG_TYPE_CGROUP_SYSCTL | 对设备文件访问过滤 |
BPF_PROG_TYPE_CGROUP_SOCKOPT | 在setsockopt和getsockopt操作中修改套接字 |
这些类型的BPF程序都可以通过BPF系统调用的BPF_PROG_ATTACH进行挂载。如
union bpf_attr attr = ;
attr.target_fd = target_fd; // cgroup文件描述符
attr.attach_bpf_fd = prog_fd; // BPF程序文件描述符
attr.attach_type = BPF_CGROUP_DEVICE; // 挂载类型为BPF_CGROUP_DEVICE
if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0)
return -errno;
...
其他eBPF程序
类型 | 说明 |
BPF_PROG_TYPE_LSM | 用于安全模块访问控制和审计策略 |
BPF_PROG_TYPE_LWT_IN, BPF_PROG_TYPE_LWT_OUT, BPF_PROG_TYPE_LWT_XMIT, | 用于轻量级的封装或解封装 |
BPF_PROG_TYPE_STRUCT_OPS | 拥塞控制 |
BPF_PROG_TYPE_FLOW_DISSECTOR | 流量解析器 |
BPF_PROG_TYPE_EXT | 扩展程序 |
参考
bpf.h - include/uapi/linux/bpf.h - Linux source code (v5.13) - Bootlin
Traffic Control HOWTO (linux-ip.net)
以上是关于eBPF理解的主要内容,如果未能解决你的问题,请参考以下文章