前段时间有人在微信群询问通过vlib_frame_t地址,如果获取到报文vlib_buffer_t结构信息。本文以ping回应报文处理流程中节点ip4_icmp_input为例简单分析一下:
下面是ip4_icmp_input节点中获取获取vlib_buffer_t结构的代码简化流程,主要分为2步:1、获取报文缓冲区的索引。2、通过索引获取到vlib_buffer_t结构地址。
代码语言:javascript复制static uword
ip4_icmp_input (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
//1、获取报文缓冲区的索引
u32 *from = vlib_frame_vector_args (frame);
//2、通过索引获取到vlib_buffer_t结构地址。
vlib_buffer_t *p0 = vlib_get_buffer (vm, from[0]);
下面通过gdb调试打印vlib_buffer_t结构信息。 1、获取报文缓冲区索引,将vlib_frame_vector_args 函数展开。
代码语言:javascript复制/*返回数值等于x四舍五入下一个2的次幂(以pow2对齐)*/
always_inline uword round_pow2 (uword x, uword pow2)
{
return (x pow2 - 1) & ~(pow2 - 1);
}
/* Byte alignment for vector arguments.
* 16字节对齐*/
#define VLIB_FRAME_VECTOR_ALIGN (1 << 4)
always_inline u32 vlib_frame_vector_byte_offset (u32 scalar_size)
{
return round_pow2 (sizeof (vlib_frame_t) scalar_size,
VLIB_FRAME_VECTOR_ALIGN);
}
always_inline void * vlib_frame_vector_args (vlib_frame_t * f)
{
return (void *) f vlib_frame_vector_byte_offset (f->scalar_size);
}
关于f->scalar_size的大小,取决于node节点声明时填充的scalar_size大小,如下面ip4-icmp-input对应node节点全局变量scalar_size未进行赋值也就是0。
代码语言:javascript复制VLIB_REGISTER_NODE (ip4_icmp_input_node) = {
.function = ip4_icmp_input,
.name = "ip4-icmp-input",
.vector_size = sizeof (u32),
.format_trace = format_icmp_input_trace,
.n_errors = ARRAY_LEN (icmp_error_strings),
.error_strings = icmp_error_strings,
.n_next_nodes = 1,
.next_nodes = {
[ICMP_INPUT_NEXT_ERROR] = "ip4-punt",
},
};
目前vpp代码中node节点赋值scalar_size,大概用途是用于存储node节点向下一个node节点传递一些私有数据。目前只有接口interface-tx节点中有使用,用于interface-output节点赋值一些私有信息给interface-tx节点有使用。在vnet_register_interface节点函数中对node节点的参数r.scalar_size = sizeof (vnet_hw_if_tx_frame_t)进行了赋值。没有过多研究,感兴趣的可以深入一下代码。 所以我们可以计算出scalar_size为0时,vlib_frame_vector_byte_offset(0)的大小为16.
代码语言:javascript复制(gdb) p round_pow2 (sizeof (vlib_frame_t),16)
$3 = 16
所有我们可以查询到from[0]的大小。
代码语言:javascript复制(gdb) bt
#0 ip4_icmp_input (vm=0x7fffb68e0680, node=0x7fffb71b0600, frame=0x7fffb7c80400)
at /home/jinsh/workspace/vpp/src/vnet/ip/icmp4.c:150
#1 0x00007ffff6ea41a9 in dispatch_node (vm=0x7fffb68e0680, node=0x7fffb71b0600,
type=VLIB_NODE_TYPE_INTERNAL, dispatch_state=VLIB_NODE_STATE_POLLING,
frame=0x7fffb7c80400, last_time_stamp=172750623838647)
at /home/jinsh/workspace/vpp/src/vlib/main.c:1024
(gdb) p frame[0]
$4 = {frame_flags = 6, flags = 0, scalar_size = 0 '