关于cgroup/skb中idle进程流量与%pI4h显示异常的技术问询
Cgroup网络流量监控eBPF问题解答
环境信息
- 发行版:Arch Linux
- 内核版本:Linux 6.10.3
- Clang版本:18.1.8
- Libbpf版本:1.4.3
eBPF代码
void stat_traffic_impl(struct __sk_buff* skb) { switch (skb->family) { case AF_INET: bpf_printk("%u -> %u", skb->local_ip4, skb->remote_ip4); bpf_printk("%pI4h -> %pI4h", skb->local_ip4, skb->remote_ip4); break; default: return; } } SEC("cgroup/skb") int stat_traffic(struct __sk_buff* skb) { stat_traffic_impl(skb); return true; // let packet pass }
运行输出
cat-554297 [000] ..s11 48045.305791: bpf_trace_printk: 1562355904 -> 3395707859 cat-554297 [000] ..s11 48045.305791: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0 <idle>-0 [001] ..s21 48045.305824: bpf_trace_printk: 1562355904 -> 3395707859 <idle>-0 [001] ..s21 48045.305825: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0 cat-554297 [000] ..s11 48045.305839: bpf_trace_printk: 1562355904 -> 3395707859 cat-554297 [000] ..s11 48045.305840: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0 <idle>-0 [000] ..s21 48045.305895: bpf_trace_printk: 1562355904 -> 3563480019 <idle>-0 [000] .Ns21 48045.305898: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0 <idle>-0 [001] ..s21 48045.306075: bpf_trace_printk: 1562355904 -> 3563480019 <idle>-0 [001] ..s21 48045.306079: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0 <idle>-0 [000] ..s21 48045.306103: bpf_trace_printk: 1562355904 -> 3395707859 <idle>-0 [000] .Ns21 48045.306105: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0 <idle>-0 [001] ..s21 48045.306126: bpf_trace_printk: 1562355904 -> 3563480019 <idle>-0 [001] ..s21 48045.306129: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0 <idle>-0 [001] ..s21 48045.306131: bpf_trace_printk: 1562355904 -> 3395707859 <idle>-0 [001] ..s21 48045.306133: bpf_trace_printk: 0.0.0.0 -> 0.0.0.0
技术疑问解答
1. 为何使用%pI4h格式化skb->local_ip4和skb->remote_ip4时,始终显示为0.0.0.0?
%pI4h 这类格式化符要求传入指向IP地址的指针,但代码中直接传递了 skb->local_ip4 和 skb->remote_ip4 的值(它们是 __be32 类型的无符号32位整数)。bpf_printk会把这个整数值当作内存地址去访问,而该地址并非有效的IP地址存储区域,因此读取到的内容无效,最终输出 0.0.0.0。
修正方法是传递变量的指针,同时注意 skb 中的IP地址是网络字节序,%pI4 会自动处理网络字节序到主机字节序的转换,推荐写法:
bpf_printk("%pI4 -> %pI4", &skb->local_ip4, &skb->remote_ip4);
2. 为何idle进程会产生大量网络流量,该进程在此场景下具体执行了什么操作?
这里的 <idle>-0 不是用户态的idle进程,而是内核的idle线程(PID为0),CPU空闲时由内核调度运行。这些流量并非idle线程主动发起,而是内核在idle线程上下文处理的网络包:
- 常见场景包括TCP应答包、连接关闭后的清理包、TCP keepalive探测包等;
- 当网络包由内核直接处理(而非用户进程发起),或者原发起进程已退出,内核会在idle线程的上下文中完成包的处理流程,因此trace输出中关联的进程显示为idle;
- 也可能是反向路径的响应包,比如对cat进程发起请求的回复,内核处理时复用了idle线程的上下文。
内容的提问来源于stack exchange,提问作者QuarticCat
相关产品推荐
相关产品推荐

