1、trace命令
此命令行推荐度十分,用来详细跟踪报文处理的node节点及记录node节点流程处理中一些关键信息。但是需要注意有些node节点没有增加trace记录不会在trace中体现。可以通过show runtime来查询报文处理node节点。基本用法如下:
clear trace
trace add dpdk-input 10
show trace
并所有的节点都支持trace的。比如下面BondEthernet2-output就会提示当前node不支持。在vpp官方文档有列出哪些节点支持trace,具体链接如下:node 节点支持trace列表
learning_vpp1# trace add BondEthernet2-output 10
trace add: node 'BondEthernet2-output' doesn't support per-node tracing.
There may be another way to initiate trace on this node.
我们可以在代码中搜索一下下面的宏定义,有node节点flags置位,就是支持的。
#define VLIB_NODE_FLAG_TRACE_SUPPORTED (1 << 8)
trace目前支持基于流分类classify来查询报文,具体可以查看代码中
src\vnet\classify\vnet_classify.c,函数classify_filter_command_fn的注释,下面就举例说明一下:
#1、配置classify fliter
classify filter trace mask l3 ip4 src dst match l3 ip4 src 200.1.1.1 dst 200.1.2.2
#可以通过命令行来查询设置结果
learning_vpp1# show classify filter
Filter Used By Table(s)
-------------- --------
packet tracer: first table 1
learning_vpp1# show classify tables index 1 verbose
TableIdx Sessions NextTbl NextNode
1 1 0 -1
Heap: base 0x7fffa8799000, size 128k, locked, unmap-on-destroy, name 'classify'
page stats: page-size 4K, total 32, mapped 2, not-mapped 0, unknown 30
numa 0: 2 pages, 8k bytes
total: 127.95K, used: 1.38K, free: 126.58K, trimmable: 126.50K
nbuckets 8, skip 1 match 2 flag 0 offset 0
mask 00000000000000000000ffffffffffffffff0000000000000000000000000000
linear-search buckets 0
[1]: heap offset 1280, elts 2, normal
0: [1280]: next_index 0 advance 0 opaque 0 action 0 metadata 0
k: 00000000000000000000c8010101c80102020000000000000000000000000000
hits 0, last_heard 0.00
1 active elements
1 free lists
0 linear-search buckets
#2、设置trace转包
trace add dpdk-input 10 filter verbose
#3、show trace查询显示 这里就不贴显示结果、
show trace
另外trace支持基于node节点来抓包,设置比较简单,这里不过多介绍了,具体配置如下:
#1、设置需要查询node节点 trace filter none | [include|exclude] NODE COUNT
#具体参数信息none:取消,include:只显示包含指定node节点,exclude 显示除指定节点之外
trace filter include ip4-icmp-echo-request 10
#2、设置trace起始node及数量
trace add dpdk-input 10
3、show trace
2、pacp抓包
pcap抓包支持2种模式:
一种是pcap dispatch trace:用来抓取单个数据包转发node图,可以显示vlib_buff_t结构体数据及trace node图数据,并且支持支持vpp程序异常时存储pacp报文。
另外一种就是pacp trace 用来转发rx(接收)、tx(发送)、drop(丢弃)的报文,并且支持基于classify进行过滤抓包。下面就分别来学习一下:
1、pcap dispatch trace
目前vpp dispatch trace 抓取报文解析器已经集成到wireshark主线版本中,可以直接使用wireshark查看。下面来介绍一下。命令行参数如下:
max:设置抓取报文的总数量。
file :指定存储报文的文件名称。
buffer-trace :测试情况看应该是自动开启trace功能并设置trace 数量,不需要再执行trace add xxx num了。我们可以通过show trace来查询。这个应该和trace add的一样,同时在pacp报文中也会显示trace.
post-mortem:中文意思是事后剖析,大概的用法应该是设置pcap dispatch trace xxx post-mortem后,vpp异常时,首先把已经抓的包存储下来。这个功能还真是不错。没有模拟试验,感兴趣的可以尝试一下。基于这个功能应该可以开发很多有用的定位手段,非常赞!值得详细研究一下。
pcap dispatch trace [on|off] [max <nn>] [file <name>] [status]
[buffer-trace <input-node-name> <nn>][post-mortem]
下面参考vpp官方介绍,来动手试验一下。
learning_vpp1# clear trace
learning_vpp1# pcap dispatch trace on max 10 file vppcapture.pcap buffer-trace dpdk-input 2
learning_vpp1# pcap dispatch trace status#获取pacp dispatch状态
pcap dispatch capture enabled: 10 of 10 pkts...#已经抓取10个报文
capture to file /tmp/vppcapture.pcap #报文存储路径。
Buffer trace of 100 pkts from dpdk-input enabled...
#buffer trace显示100,这里有点问题,并不是上面手动设置的2,而是代码默认是100,这里没有设置
learning_vpp1# pcap dispatch trace off #关闭pcap dispatch trace
Write 10 packets to /tmp/vppcapture.pcap, and stop capture...
learning_vpp1# show trace #查询只抓了2个报文。这里不再显示。
Packet 1
遇到的问题:
1、单独执行pcap dispatch trace on max 10000 file vppcapture.pcap后,无法抓取报文。个人感觉是个bug。
2、执行pcap dispatch trace on max 10000 file vppcapture buffer-trace ip4-input 1000后,可以正常抓取报文,但是pcap文件中并未显示trace信息。ip4-input节点本身是不支持per-node tracing的。
3、执行pcap dispatch trace on max 10000 file vppcapture buffer-trace dpdk-input 1000。pcap包中可以显示trace信息,show trace中也可以正常显示。
2、pcap trace命令
pcap trace 命令行是经常使用的,主要说一下参数:
max-bytes-per-pkt:指定抓取报文的长度,要求设置数值范围大于等于32且小于等于9000。当实际报文长度大于设置值时,报文存储长度按照设置长度存储;当报文小于设置长度数值时,按照报文实际长度存储。
filter:配合classify filter使用,可以进行报文过滤抓包。
preallocate-data:预分配报文存储缓存区。按照pcap设置抓包数量大小分配一次性分配好报文缓存区。大概作用就是提示性能吧。
free-data:删除数据缓存区。默认pcap报文缓存区设置后,一直存在。需要设置free-data来释放数据缓存区内存。
pcap trace [rx] [tx] [drop] [off] [max <nn>] [intfc <interface>|any]
[file <name>] [status] [max-bytes-per-pkt <nnnn>][filter]
[preallocate-data][free-data]
下面具体pcap trace filter抓包设置流程:
#1、设置抓取指定sip+dip报文
classify filter pcap mask l3 ip4 src dst match l3 ip4 src 200.1.1.2 dst 200.1.2.2
#查询设置信息。
learning_vpp1# show classify filter
Filter Used By Table(s)
-------------- --------
packet tracer: first table none
pcap rx/tx/drop: first table 0 #clasifiy id
#查询设置内容。
learning_vpp1# show classify tables index 0 verbose
TableIdx Sessions NextTbl NextNode
0 2 -1 -1
Heap: base 0x7fffa87fb000, size 128k, locked, unmap-on-destroy, name 'classify'
page stats: page-size 4K, total 32, mapped 2, not-mapped 0, unknown 30
numa 0: 2 pages, 8k bytes
total: 127.95K, used: 1.59K, free: 126.36K, trimmable: 126.28K
nbuckets 8, skip 1 match 2 flag 0 offset 0
mask 00000000000000000000ffffffffffffffff0000000000000000000000000000
linear-search buckets 0
[1]: heap offset 1280, elts 2, normal
0: [1280]: next_index 0 advance 0 opaque 0 action 0 metadata 0
k: 00000000000000000000c8010101c80102020000000000000000000000000000
hits 0, last_heard 0.00
[2]: heap offset 1536, elts 2, normal
0: [1536]: next_index 0 advance 0 opaque 0 action 0 metadata 0
k: 00000000000000000000c8010102c80102020000000000000000000000000000
hits 4, last_heard 0.00
2 active elements
1 free lists
0 linear-search buckets
#2、抓取rx报文。
pcap trace rx max 100 file 1.pcap filter
#3、取消classify filter pcap设置。
classify filter pcap del
3、VLIB_BUFFER_TRACE_TRAJECTORY
vpp源码中提供了一种方法,就是跟踪报文所走的node节点。默认是关闭的,需要自己打开。buffer trace在vppdebug版本中才能使用,在定位异常报文导致vpp挂死、vpp buffer泄漏问题很有帮助。
宏定义在文件src\vlib\buffer.h中
#define VLIB_BUFFER_TRACE_TRAJECTORY 0
#if VLIB_BUFFER_TRACE_TRAJECTORY > 0
extern void (*vlib_buffer_trace_trajectory_cb) (vlib_buffer_t * b, u32 index);
extern void (*vlib_buffer_trace_trajectory_init_cb) (vlib_buffer_t * b);
extern void vlib_buffer_trace_trajectory_init (vlib_buffer_t * b);
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) \
vlib_buffer_trace_trajectory_init (b);
#else
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
#endif /* VLIB_BUFFER_TRACE_TRAJECTORY */
node节点的信息存储在私有字段2中,指针:trajectory_trace,文件src\vnet\buffer.h
typedef struct
{
.......
union
{
struct
{
#if VLIB_BUFFER_TRACE_TRAJECTORY > 0
/* buffer trajectory tracing */
u16 *trajectory_trace;
#endif
};
..........
};
} vnet_buffer_opaque2_t;
在代码中没有找到能打印trajectory_trace的地方,可能只能借助gdb了吧。
但是使用中可能存在问题,我们可以看一下vlib_buffer_copy函数中是一段代码如下:
clib_memcpy_fast (d->opaque2, s->opaque2, sizeof (s->opaque2));
默认情况下是是一个buffer对应一个trajectory_trace内存,在copy或者clone函数都是直接复制的,就会导致转发过程中判断异常。目前没有找到好的方法修改,我们借鉴其的方法利用buffer结构中pre-data字段来存储node索引。下面是我修改后的patch文件。
1diff --git a/src/vlib/buffer.h b/src/vlib/buffer.h
2index 42e3cdf98..472d3c27f 100755
3--- a/src/vlib/buffer.h
4+++ b/src/vlib/buffer.h
5@@ -487,6 +487,8 @@ extern void (*vlib_buffer_trace_trajectory_init_cb) (vlib_buffer_t * b);
6 extern void vlib_buffer_trace_trajectory_init (vlib_buffer_t * b);
7 #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) \
8 vlib_buffer_trace_trajectory_init (b);
9+#elif CLIB_DEBUG > 0
10+#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) ((b)->pre_data[0] = 0)
11 #else
12 #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
13 #endif /* VLIB_BUFFER_TRACE_TRAJECTORY */
14diff --git a/src/vlib/main.c b/src/vlib/main.c
15old mode 100644
16new mode 100755
17index 90ce53de5..c6e738eaf
18--- a/src/vlib/main.c
19+++ b/src/vlib/main.c
20@@ -1198,6 +1198,26 @@ dispatch_node (vlib_main_t * vm,
21 dispatch_pcap_trace (vm, node, frame);
22 n = node->function (vm, node, frame);
23 }
24+ #if CLIB_DEBUG > 0
25+ else if ((CLIB_DEBUG > 0) && frame)
26+ {
27+ int i;
28+ u32 *from;
29+ from = vlib_frame_vector_args (frame);
30+ for (i = 0; i < frame->n_vectors; i++)
31+ {
32+ vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
33+ b->pre_data[0]++;
34+ if (b->pre_data[0] < 32)
35+ {
36+ b->pre_data[b->pre_data[0]] = (u8)node->node_index;
37+ }
38+ }
39+ if (PREDICT_FALSE (vm->dispatch_pcap_enable))
40+ dispatch_pcap_trace (vm, node, frame);
41+ n = node->function (vm, node, frame);
42+ }
43+ #endif
44 else
45 {
46 if (PREDICT_FALSE (vm->dispatch_pcap_enable))
如果存在buffer泄露,我们可以大致根据在buffer池中找到buffer索引,多查询几个索引的node路径,能大致确认是那个接口处理存在的问题。再去详细阅读代码。
