以内核v6.6代码,介绍tcpdump程序如何与内核交互,加载bpf程序的。
加载:
libpcap通过sockopt里的“SO_ATTACH_FILTER“,
在 packet socket下的”sk_filter“挂载prog呈现。
运行:
当skb报文到达packet_rcv时候, 通过调用___bpf_prog_run函数(注意,这个函数是3个下滑线,区别于2个下划线的函数)
运行”sk_filter“对应的prog。
其中prog的
==>packet_rcv
==> ==> run_filter
==> ==> ==>bpf_prog_run_clear_cb
563 struct sk_filter {
564 refcount_t refcnt;
565 struct rcu_head rcu;
566 struct bpf_prog *prog;
567 };
加载调用栈:
1 | ==> pcap_setfilter |
函数定义
1 | 3723 int |
1 | 992 static int |
1 | 4315 static int |
1 | 5414 static int |
1 | ——————————————————kernel—————————————————— |
1 | 1094 int sk_setsockopt(struct sock *sk, int level, int optname, |
1 | 1528 int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) |
1 | 1481 static |
1 | 1312 static struct bpf_prog *bpf_prepare_filter(struct bpf_prog *fp, |
1 | 1242 static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp) |
1 | 2179 struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err) |
1 | 2157 static void bpf_prog_select_func(struct bpf_prog *fp) |
1 | 1455 static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk) |
============================== 内核态运行 ========================================
运行:
当skb报文到达packet_rcv时候, 通过调用bpf run函数,
运行”sk_filter“对应的prog。
prog的bpf_func在attach时候被初始化为interpreters函数指针中对应的栈大小的函数。也就是___bpf_prog_run函数。
1 | ==>packet_rcv |
1 | 2121 static int packet_rcv(struct sk_buff *skb, struct net_device *dev, |
1 | 2079 static unsigned int run_filter(struct sk_buff *skb, |
1 | 749 static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog, |
1 | 618 static inline u32 bpf_prog_run_pin_on_cpu(const struct bpf_prog *prog, |
1 | 605 static __always_inline u32 bpf_prog_run(const struct bpf_prog *prog, const void *ctx) |
1 | 581 static __always_inline u32 __bpf_prog_run(const struct bpf_prog *prog, |
1 | 1162 static __always_inline __nocfi unsigned int bpf_dispatcher_nop_func( |
1 | 1644 /** |