always_inline void * vlib_add_trace (vlib_main_t * vm, //VPP的主数据结构
vlib_node_runtime_t * r, //当前节点的运行时数据结构
vlib_buffer_t * b, //要跟踪的缓冲区
u32 n_data_bytes) //要跟踪的数据大小(以字节为单位)
{ vlib_trace_main_t *tm = &vm->trace_main; //获取VPP中跟踪模块的指针 vlib_trace_header_t *h; u32 n_data_words;
ASSERT (vnet_trace_dummy); //断言,确保虚拟跟踪指针已分配
if (PREDICT_FALSE ((b->flags & VLIB_BUFFER_IS_TRACED) == 0)) //如果未标记为可跟踪,则返回虚拟跟踪指针
return vnet_trace_dummy;
if (PREDICT_FALSE (tm->add_trace_callback != 0)) //如果已注册回调函数,则调用回调函数以添加跟踪数据,并返回虚拟跟踪指针
{
return tm->add_trace_callback ((struct vlib_main_t *) vm,
(struct vlib_node_runtime_t *) r,
(struct vlib_buffer_t *) b,
n_data_bytes);
}
else if (PREDICT_FALSE (tm->trace_enable == 0)) //如果未启用跟踪,则返回虚拟跟踪指针
{
ASSERT (vec_len (vnet_trace_dummy) >= n_data_bytes + sizeof (*h)); //断言,确保虚拟跟踪指针足够大以容纳要跟踪的数据
return vnet_trace_dummy;
}
/* Are we trying to trace a handoff case? */ if (PREDICT_FALSE (vlib_buffer_get_trace_thread (b) != vm->thread_index)) //如果缓冲区在不同的线程中,则返回虚拟跟踪指针
return vnet_trace_dummy;
vlib_validate_trace (tm, b); //验证当前节点是否支持跟踪
n_data_bytes = round_pow2 (n_data_bytes, sizeof (vlib_trace_header_t)); //将数据大小舍入到VPP跟踪头部大小的倍数 n_data_words = n_data_bytes / sizeof (vlib_trace_header_t); //计算数据大小(以VPP跟踪头部为单位) vec_add2_aligned (tm->trace_buffer_pool[vlib_buffer_get_trace_index (b)], h,
1 + n_data_words, sizeof (h[0])); //在对应的跟踪缓冲池中分配空间以存储跟踪数据
h->time = vm->cpu_time_last_node_dispatch; //更新时间戳信息 h->n_data = n_data_words; //更新数据大小信息 h->node_index = r->node_index; //更新节点索引信息
return h->data; //返回指向新分配内存块中数据部分的指针,供用户填充实际的跟踪数据 }