Skip to content

Commit 676d5c4

Browse files
committed
nettrace: add doc and man for --trace-stack
Signed-off-by: Menglong Dong <imagedong@tencent.com>
1 parent 0e86419 commit 676d5c4

5 files changed

Lines changed: 106 additions & 10 deletions

File tree

README.md

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ Usage:
164164
--monitor enable 'monitor' mode
165165
--drop-stack print the kernel function call stack of kfree_skb
166166
--min-latency the minial time to live of the skb
167+
--trace-stack print call stack for traces or group
167168
168169
-v show log information
169170
--debug show debug information
@@ -187,8 +188,9 @@ Usage:
187188
- `monitor`:启用监控模式。一种轻量化的实时监控系统中网络异常的模式(对内核版本有一定要求)。
188189
- `hooks`:结合netfilter做的适配,详见下文
189190
- `drop`:进行系统丢包监控,取代原先的`droptrace`
190-
- `drop-stack`: 打印kfree_skb内核函数的调用堆栈
191+
- `drop-stack`: 打印kfree_skb内核函数的调用堆栈,等价于`--trace-stack kfree_skb`
191192
- `min-latency`:根据报文的寿命进行过滤,仅打印处理时长超过该值的报文,单位为ms。该参数仅在默认和`diag`模式下可用。
193+
- `trace-stack`:指定需要进行堆栈打印的内核函数,可以指定多个,用“,”分隔。出于性能考虑,启用堆栈打印的内核函数不能超过16个。
192194
193195
下面我们首先来看一下默认模式下的工具使用方法。
194196
@@ -351,6 +353,76 @@ begin trace...
351353
[66.740110] [consume_skb ] ICMP: 192.168.122.8 -> 192.168.122.1 ping reply, seq: 1, id: 32535
352354
```
353355
356+
#### 3.1.6 堆栈打印
357+
358+
可以通过`--trace-stack`来指定需要进行内核堆栈打印的`traces`,使用方式与`--trace`完全一致。出于性能的考虑,目前启用堆栈打印的内核函数不能超过16个。基本用法:
359+
360+
```shell
361+
$ sudo ./nettrace -p icmp --trace-stack consume_skb,icmp_rcv
362+
begin trace...
363+
***************** ffff88882cafd200,ffff88882cafdc00 ***************
364+
[2846531.810609] [nf_hook_slow ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956 *ipv4 in chain: OUTPUT*
365+
[2846531.810612] [ip_output ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
366+
[2846531.810613] [nf_hook_slow ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956 *ipv4 in chain: POST_ROUTING*
367+
[2846531.810615] [ip_finish_output ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
368+
[2846531.810617] [ip_finish_output2 ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
369+
[2846531.810619] [__dev_queue_xmit ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
370+
[2846531.810621] [dev_hard_start_xmit ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956 *skb is successfully sent to the NIC driver*
371+
[2846531.810623] [enqueue_to_backlog ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
372+
[2846531.810630] [__netif_receive_skb_core.constprop.0] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
373+
[2846531.810632] [ip_rcv ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
374+
[2846531.810634] [ip_rcv_core ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
375+
[2846531.810635] [nf_hook_slow ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956 *ipv4 in chain: PRE_ROUTING*
376+
[2846531.810637] [ip_local_deliver ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
377+
[2846531.810639] [nf_hook_slow ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956 *ipv4 in chain: INPUT*
378+
[2846531.810640] [nft_do_chain ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956 *iptables table:filter, chain:INPUT*
379+
[2846531.810642] [ip_local_deliver_finish] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
380+
[2846531.810644] [skb_clone ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
381+
[2846531.810649] [icmp_rcv ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
382+
Call Stack:
383+
-> icmp_rcv+0x1
384+
-> ip_local_deliver_finish+0x7f
385+
-> ip_local_deliver+0xea
386+
-> ip_rcv+0x16d
387+
-> __netif_receive_skb_one_core+0x89
388+
-> process_backlog+0xa9
389+
-> __napi_poll+0x2e
390+
-> net_rx_action+0x28f
391+
-> __do_softirq+0xfb
392+
-> do_softirq+0xa7
393+
-> __local_bh_enable_ip+0x79
394+
-> ip_finish_output2+0x170
395+
-> __ip_finish_output+0xae
396+
-> ip_finish_output+0x36
397+
-> ip_output+0x73
398+
-> ip_push_pending_frames+0xab
399+
-> raw_sendmsg+0x651
400+
-> inet_sendmsg+0x6e
401+
-> sock_sendmsg+0x60
402+
-> __sys_sendto+0x10a
403+
-> __x64_sys_sendto+0x24
404+
-> do_syscall_64+0x3f
405+
-> entry_SYSCALL_64_after_hwframe+0x72
406+
407+
[2846531.810651] [ping_rcv ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
408+
[2846531.810653] [ping_lookup.isra.0 ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
409+
[2846531.810654] [kfree_skb ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
410+
[2846531.810659] [consume_skb ] ICMP: 127.0.0.1 -> 127.0.0.1 ping reply, seq: 3, id: 51956
411+
Call Stack:
412+
-> consume_skb+0xb8
413+
-> consume_skb+0xb8
414+
-> skb_free_datagram+0x11
415+
-> raw_recvmsg+0xb2
416+
-> inet_recvmsg+0x11d
417+
-> sock_recvmsg+0x6e
418+
-> ____sys_recvmsg+0x90
419+
-> ___sys_recvmsg+0x7c
420+
-> __sys_recvmsg+0x60
421+
-> __x64_sys_recvmsg+0x1d
422+
-> do_syscall_64+0x3f
423+
-> entry_SYSCALL_64_after_hwframe+0x72
424+
```
425+
354426
### 3.2 诊断模式
355427
356428
使用方式与上面的一致,加个`diag`参数即可使用诊断模式。上文的生命周期模式对于使用者的要求比较高,需要了解内核协议栈各个函数的用法、返回值的意义等,易用性较差。诊断模式是在生命周期模式的基础上,提供了更加丰富的信息,使得没有网络开发经验的人也可进行复杂网络问题的定位和分析。

docs/develop.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,19 @@ trace.yaml -- gen_trace.py |
8181

8282
这个配置文件是项目的核心配置,里面按照`yaml`格式保存了所有的支持的内核函数,按照树状图的结构来配置的。在树状图中,所有的叶节点表示的都是trace(跟踪点,内核函数或者tracepoint),非叶节点代表的都是网络模块,也可以理解为目录。
8383

84-
网络模块(目录)的格式如下
84+
**网络模块(目录)格式**
8585

8686
- name:名称
8787
- desc:一段描述
8888
- visual:是否对用户可见,默认true
8989
- children:子目录,或者当前目录下的traces
9090

91-
trace的格式:
91+
**trace的格式**
9292

93-
- name:在未指定target的情况下,这个名称就是要跟踪的内核函数的名称。其格式为:内核函数名称:skb:sock,其中skb指的是skb参数在该内核函数参数中的位置,从0开始;sock代表sk在该内核函数中的位置(非必须)。如果只跟踪skb,那只需要写成:function:skb的格式即可。
94-
注意:function:skb是一种简写,这样写完就不需要写skb了,不然要提供skb字段才行
93+
- name:在未指定target的情况下,这个名称就是要跟踪的内核函数的名称。
9594
- target:当前trace针对的内核函数。在name和内核函数不同的情况下,可以通过target来指定需要跟踪的内核函数。
9695
- skb:skb参数在该内核函数参数中的位置,从0开始
96+
- sock:sk参数在该内核函数参数中的位置,从0开始(仅用作--sock模式)
9797
- tp:tracepoint类型需要写的,tracepoint的位置。格式:dir:tracepoint
9898
- analyzer:解析器。该参数用于指定诊断模式下分析当前函数采集到的数据的诊断器,默认不进行特殊的数据格式检查和处理。
9999
- rules:定义诊断模式下的规则。规则有三种级别,分别是:
@@ -105,6 +105,16 @@ trace的格式:
105105
- msg:当命中规则后给出的信息
106106
- adv:诊断建议,一般用于`error`级别的规则。
107107

108+
**简写方式**
109+
110+
可以在`name`中指定skb或者sk的索引,其格式为:内核函数名称:skb/sock,其中skb指的是skb参数在该内核函数参数中的位置,从0开始;sock代表sk在该内核函数中的位置(非必须,--sock模式下的跟踪点)。如果只跟踪skb,那只需要写成:function:skb的格式即可。如果当前定义的trace只包含`name`,那么可以进一步对其进行简化,只需要将trace定义为字符串即可,如下所示:
111+
112+
```yaml
113+
- name: ip_rcv:0 # 定义了一个trace对象,跟踪的是内核函数ip_rcv,其中skb在这个函数参数中的索引为0
114+
- ip_rcv:0 # 使用字符串来定义trace,作用和上面的一样
115+
- name: inet_listen/0 # 定义了一个trace对象,跟踪的是内核函数inet_listen,其中sock在这个函数参数中的索引为0,该trace仅在sock模式下有效。
116+
```
117+
108118
### 3.2 诊断器开发
109119
110120
常规场景下,如果我们有需要跟踪的内核函数或者场景,只需要在`trace.yaml`中增加对应的`trace`即可。如果需要增加额外的数据采集和分析能力,就需要增加自定义`诊断器`了。新增诊断器所要做的修改包括以下内容:

script/bash-completion.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
complete -W '-s --saddr -d --daddr --addr -p -D --dport -S --sport -P --port --pid --netns --netns-current -t --trace -v --detail --debug --bpf-debug --ret --basic --diag --diag-quiet --diag-keep --sock --min-latency --date --drop --drop-stack --hooks --monitor -h --help' nettrace
1+
complete -W '-s --saddr -d --daddr --addr -p -D --dport -S --sport -P --port --pid --netns --netns-current -t --trace -v --detail --debug --bpf-debug --ret --basic --diag --diag-quiet --diag-keep --sock --min-latency --date --drop --drop-stack --hooks --monitor --trace-stack -h --help' nettrace
22
complete -W '-h -s -d --addr -p --dport --sport --port -t -v --detail --stack --stack-tracer --timeline -c --ret --skb-mode --force-stack --tcp-flags -o --output' nettrace-legacy

script/zh_CN/nettrace.8

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,15 @@ nettrace \- Linux系统下的网络报文跟踪、网络问题诊断工具
9494
进行系统丢包监控,取代原先的\fB\fCdroptrace\fR
9595
.TP
9696
\fB\fC\-\-drop\-stack\fR
97-
打印kfree_skb内核函数的调用堆栈
97+
打印kfree\fIskb内核函数的调用堆栈,等价于`\-\-trace\-stack kfree\fPskb`
9898
.TP
99-
\fB\fC\-\-min\-latency\fR
99+
\fB\fC\-\-min\-latency\fR \fIlatency in ms\fP
100100
根据报文的寿命进行过滤,仅打印处理时长超过该值的报文,单位为ms。该参数仅在默认和\fB\fCdiag\fR模式下可用。
101101
.TP
102+
\fB\fC\-\-trace\-stack\fR \fItraces\fP
103+
指定需要进行堆栈打印的内核函数,可以指定多个,用“,”分隔。出于性能考虑,启用堆栈打印的
104+
内核函数不能超过16个。用法和格式与\fB\fC\-\-trace\fR完全一致。
105+
.TP
102106
\fB\fC\-v\fR
103107
显示程序启动的日志信息
104108
.TP
@@ -115,6 +119,9 @@ nettrace \- Linux系统下的网络报文跟踪、网络问题诊断工具
115119
.TP
116120
显示详细信息:
117121
\fInettrace \-p icmp \-s 192.168.1.8 \-\-detail\fP
122+
.TP
123+
打印堆栈:
124+
\fInettrace \-p icmp \-s 192.168.1.8 \-\-trace\-stack consume\fIskb,icmp\fPrcv\fP
118125
.SS 诊断模式
119126
.PP
120127
使用方式与上面的一致,加个\fB\fCdiag\fR参数即可使用诊断模式。上文的生命周期模式对于使用者的

script/zh_CN/nettrace.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,15 @@ nettrace - Linux系统下的网络报文跟踪、网络问题诊断工具
9898
进行系统丢包监控,取代原先的`droptrace`
9999

100100
`--drop-stack`
101-
打印kfree_skb内核函数的调用堆栈
101+
打印kfree_skb内核函数的调用堆栈,等价于`--trace-stack kfree_skb`
102102

103-
`--min-latency`
103+
`--min-latency` *latency in ms*
104104
根据报文的寿命进行过滤,仅打印处理时长超过该值的报文,单位为ms。该参数仅在默认和`diag`模式下可用。
105105

106+
`--trace-stack` *traces*
107+
指定需要进行堆栈打印的内核函数,可以指定多个,用“,”分隔。出于性能考虑,启用堆栈打印的
108+
内核函数不能超过16个。用法和格式与`--trace`完全一致。
109+
106110
`-v`
107111
显示程序启动的日志信息
108112

@@ -122,6 +126,9 @@ nettrace - Linux系统下的网络报文跟踪、网络问题诊断工具
122126
显示详细信息:
123127
*nettrace -p icmp -s 192.168.1.8 --detail*
124128

129+
打印堆栈:
130+
*nettrace -p icmp -s 192.168.1.8 --trace-stack consume_skb,icmp_rcv*
131+
125132
### 诊断模式
126133

127134
使用方式与上面的一致,加个`diag`参数即可使用诊断模式。上文的生命周期模式对于使用者的

0 commit comments

Comments
 (0)