字节跳动开源Linux内核网络抓包工具netcap
一、背景引见
在 Linux 内核网络开发环节中,网络丢包疑问是一个经常出现的应战。传统的网络抓包工具(如tcpdump)只管能够协助开发者定位疑问,但其效率较低,且在深度网络疑问定位方面才干有限。随着 eBPF技术的极速开展,产生了更初级的疑问跟踪才干。字节跳动 STE 团队基于此技术开发了 下一代内核网络抓包工具 :(net capture,外部原名:xcap,并 正式对外开源 ,GitHub 地址:。
与 tcpdump 工具只能作用于内核网络协定栈预备发包和收包的固定点相比,netcap可以简直跟踪整个内核网络协定栈(有skb作为参数的函数)。字节跳动 STE 团队经常使用 tcpdump 语法作为过滤条件,以 skb(socket buffer)为高低文,可以轻松把握整个报文在内核网络协定栈的完整形迹,从而协助开发者大大提高内核网络丢包疑问的定位效率。
二、经常使用举例
例1 :检查 ip 10.227.0.45 的 icmp 包能否抵达内核预期的函数调用点, 这样做的好处是:在定位排查网络疑问的时刻,可以繁难的增加疑心范围,提高效率。
netcap skb -f icmp_rcv@1 -i eth0 -e "host 10.227.0.45" -t "-nnv"
其中 -f 前面的参数是 kprobe 或许 tracepoint 的详细函数(自动是kprobe),并且须要通知 netcap,skb 在这个函数(本例是 icmp_rcv )的第几个参数(从1开局),本例是第1个。
例2: 检查内核查于 tcp 端口 9000 的报文的丢包位置
netcap skb -f tracepoint:skb:kfree_skb -e "tcp port 9000" -S
其中 -f 前面的参数是 kprobe 或许 tracepoint 的详细函数,tracepoint 不须要传递 skb 是第几个参数。
-S 示意连带着打印出此调用的 stack,本例中经过 stack 可以看到是哪里丢包的。
举个例子,在机器上性能一个丢包的 iptables 规定把来访的 tcp 9000 的包丢掉,如下图所示:
iptables -A INPUT -p tcp --dport 9000 -j DROP
而后经常使用 netcap上方的命令观察丢包状况:
其它命令行参数可以经过浏览开源代码的 README 或命令 netcap help skb 来详细了解。
三、设计与成功
主体框架
netcap 经过 kprobe / tracepoint 模式成功函数的 hook,经过函数参数失掉 skb 和 sock 关键结构体,拿到网络包的数据,经过 bpf map 和用户态启动数据传递。
成功原理
netcap 的 上班原理大体如下:在 eBPF 程序中成功数据包的过滤,找出 tcpdump 语法过滤的包,而后把这个包给到 netcap 运行程序,netcap 运行程序再把这个包发去给 tcpdump 显示,或许间接输入 pcap 文件。如下图所示:
1. 如何按 tcpdump 语法过滤
tcpdump 的过滤语法是基于 cBPF的,经常使用开源库:这里可以把 tcpdump的过滤语法转化成一个 C 函数,这个 C 函数可以嵌入到 netcap 的 eBPF 的程序中。转成 C 函数的基本原理如下:先应用libpcap 库把 tcpdump 过滤语法转成 cBPF 指令码,而后基于此指令码转化成 C 言语的函数。如下图所示:
2. 如何把数据包内容用 tcpdump 显示进去
netcap 程序启动后,也会启动一个 tcpdump 的程序,tcpdump 的规范输入接纳 pcap 格局的输入流,而后以不同的参数(例如 -e 是显示 mac 地址)从其规范输入打印出解析后的格局。如下图所示:
3. 如何找到数据包的内容
在内核中,是用 skb 来形容数据包的,找到 skb 中所指定的不同 header 的位置,就可以找到整个数据包,skb 的结构大体如下所示:
4. 发送方向数据包不完整,如何过滤数据包
在发送数据包的时刻,例如 __ip_finish_output 函数,有时未填充完整的 eth头、ip 头、tcp 头,那么是怎样失掉完整的包呢?
netcap 会尽力依据 skb 的 sock 结构来推导,恢双数据包,此时抓进去的包有些非关键信息会与实践状况不分歧(比如 ip 头的 id 字段)。skb 经过sock来推导数据包内容的逻辑大体如下图所示:
四、其余用法及裁减
多Trace点汇总剖析
netcap 可以统计数据包经过多个点的期间,而后汇总输入,从而剖析性能,举个例子,经常使用上方的命令:
netcap skb -f tracepoint:net:netif_receive_skb,ip_local_deliver@1,ip_local_deliver_finish@3,icmp_rcv@1 -e "host 10.227.0.72 and icmp" -i eth0--gather --gather-output-color cyan
可以观察到输入如下,依据抵达 trace 点的期间,就能够剖析出数据包性能损耗在哪里,或许在哪里或许引入了提前。
裁减性能
用户可以自定义自己的过滤函数和输入函数,这里举例如下,
netcap skb -f icmp_rcv@1 -e "host 10.227.0.72" -i eth0 --user-filter skb_user_filter.c --user-action skb_user_action.c --user-output-color green
其中裁减过滤文件 skb_user_filter.c 如下:
// Return 0 means it's not need, pls filter out it.static inline int xcap_user_filter(void *ctx, void *pkt, u16 trace_index){return 1;}
这个裁减函数的前往值假设是 0,示意在 tcpdump 语法的过滤后,再启动一次性用户自定义过滤,比如可以繁难的写几行脚本,而后依照 skb->mark 来过滤。
其中裁减输入文件 skb_user_action.c 如下:
structxcap_user_extend {inta; // format: 0x%xuint32_tb; //int64_tc;uint8_tx1; // format: %cuint8_tx2; // format: 0x%xuint16_tx3; // format: 0x%x};// Return 0 means not need to ouputstatic inline int xcap_user_action(void *ctx, void *pkt, u32 pkt_len, struct xcap_user_extend *user, u16 trace_index){user->a = 0x12345678;user->b = 1000;user->c = 2002;user->x1 = 'M';user->x2 = 0x11;user->x3 = 0xabcd;return 1;}
其中 struct xcap_user_extend 是用户自定义的结构体,想输入什么信息,就在这个结构体定义并赋值即可。结构体可允许的类型如下(注:不允许指针,也不允许数组):int8_t, uint8_t, char, int16_t, uint16_t, int,uint32_t,int64_t, uint64_t 。
这样就可以附带一些信息输入了,如下图:
五、未来展望
在开发者的日常上班中,网络抓包工具成为了网络工程师、测试工程师等必备的技艺之一,字节跳动 STE 团队开源的 netcap 网络抓包工具,希冀能够协助大家提高定位内核网络丢包疑问的效率,十分欢迎开发者们一同添加并奉献PR,独特推动开源名目开展。未来咱们也将在以下几个方向启动提升,敬请关注。