前面我们简单了解了buffer相关初始化及内存分布情况,这篇文章来讲一下我目前遇到过buffer相关的一些问题及定位手段。没有阅读过前面2节内容的,需要先熟悉一下,链接如下:
我们可以通过下面的命令行来查询buffer使用情况:
DBGvpp# show buffers
Pool Name Index NUMA Size Data Size Total Avail Cached Used
default-numa-0 0 0 2496 2048 430185 424425 919 4841
当Used使用数量持续增加而不减少时,可能就存在buffer泄露了。
在vpp老的版本中可能需要查询dpdk buffer情况(老版本buffer还是由dpdk来申请)
DBGvpp# show dpdk buffer
name="vpp pool 0" available = 694 allocated = 429491 total = 430185
注意:在新版本中上面命令行是无效的。
其实vpp源码中提供了一种方法,就是跟踪报文所走的node节点。默认是关闭的,需要自己打开。 宏定义在文件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文件。
diff --git a/src/vlib/buffer.h b/src/vlib/buffer.h
index 42e3cdf98..472d3c27f 100755
--- a/src/vlib/buffer.h
+++ b/src/vlib/buffer.h
@@ -487,6 +487,8 @@ 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);
+#elif CLIB_DEBUG > 0
+#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) ((b)->pre_data[0] = 0)
#else
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
#endif /* VLIB_BUFFER_TRACE_TRAJECTORY */
diff --git a/src/vlib/main.c b/src/vlib/main.c
old mode 100644
new mode 100755
index 90ce53de5..c6e738eaf
--- a/src/vlib/main.c
+++ b/src/vlib/main.c
@@ -1198,6 +1198,26 @@ dispatch_node (vlib_main_t * vm,
dispatch_pcap_trace (vm, node, frame);
n = node->function (vm, node, frame);
}
+ #if CLIB_DEBUG > 0
+ else if ((CLIB_DEBUG > 0) && frame)
+ {
+ int i;
+ u32 *from;
+ from = vlib_frame_vector_args (frame);
+ for (i = 0; i < frame->n_vectors; i++)
+ {
+ vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
+ b->pre_data[0]++;
+ if (b->pre_data[0] < 32)
+ {
+ b->pre_data[b->pre_data[0]] = (u8)node->node_index;
+ }
+ }
+ if (PREDICT_FALSE (vm->dispatch_pcap_enable))
+ dispatch_pcap_trace (vm, node, frame);
+ n = node->function (vm, node, frame);
+ }
+ #endif
else
{
if (PREDICT_FALSE (vm->dispatch_pcap_enable))
如果存在buffer泄露,我们可以大致根据在buffer池中找到buffer索引,多查询几个索引的node路径,能大致确认是那个接口处理存在的问题。再去详细阅读代码。
本文只是详细介绍了定位buffer泄露问题的思路,当然具体问题还需要具体分析。通过一些手段来缩小排查范围。如果大家由更好的思路或者方法,欢迎交流。
本文分享自 DPDK VPP源码分析 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!