下面是一个简单的vpp插件示例,该插件使用VLIB库来处理IPv4数据包并输出打印消息:
- 定义插件的输入和输出结构体。在这个例子中,我们定义了input_structure_t和output_structure_t结构体,用于输入和输出数据:
typedef struct {
u32 data;
} input_structure_t;
typedef struct {
u8 message[256];
} output_structure_t;
- 编写插件代码。在这个例子中,我们编写了ipv4_hello_world.c文件,其中包含了整个插件的实现。具体代码如下:
#include <vnet/plugin/plugin.h>
#include <vnet/ip/ip.h>
typedef struct {
u32 data;
} input_structure_t;
typedef struct {
u8 message[256];
} output_structure_t;
typedef struct {
u32 next_index;
} ipv4_hello_world_trace_t;
/* packet trace format function */
static u8 * format_ipv4_hello_world_trace (u8 * s, va_list * args) {
return s;
}
/* trace config structure */
typedef struct {
/* per-packet trace data */
ipv4_hello_world_trace_t *traces;
/* packet buffer flags */
u8 *buffer_flags;
} ipv4_hello_world_trace_config_t;
/* stats */
#define foreach_ipv4_hello_world_error \
_(NONE, "No error") \
_(DROP, "Drop packets")
typedef enum {
#define _(sym,str) IPV4_HELLO_WORLD_ERROR_##sym,
foreach_ipv4_hello_world_error
#undef _
IPV4_HELLO_WORLD_N_ERROR,
} ipv4_hello_world_error_t;
static char * ipv4_hello_world_error_strings[] = {
#define _(sym,string) string,
foreach_ipv4_hello_world_error
#undef _
};
typedef struct {
/* counter for dropped packets */
vlib_simple_counter_main_t drop_counters;
} ipv4_hello_world_main_t;
/* packet processing function */
static uword ipv4_hello_world_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) {
u32 n_left_from, *from, *to_next;
ipv4_hello_world_main_t *hwm = &ipv4_hello_world_main;
vlib_node_t *n = vlib_get_node_by_name (vm, (u8 *) "ipv4-hello-world");
/* get input/output buffer index */
u32 input_buffer_index = vlib_frame_vector_args (frame);
u32 output_buffer_index = vlib_frame_alloc_output_buffer (vm, &to_next, frame, 1);
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
while (n_left_from > 0) {
u32 n_left_to_next = VLIB_FRAME_SIZE - to_next;
while (n_left_from > 0 && n_left_to_next > 0) {
u32 bi0;
vlib_buffer_t *b0;
input_structure_t *input_data;
output_structure_t *output_data;
int next_index = 0;
bi0 = from[0];
from += 1;
n_left_from -= 1;
b0 = vlib_get_buffer (vm, bi0);
/* get input buffer data */
input_data = vlib_buffer_get_current (b0);
/* get output buffer data */
output_data = vlib_buffer_get_current (vm->buffers[output_buffer_index]);
/* copy message to output */
snprintf ((char *)output_data->message, sizeof(output_data->message), "Hello world! Data: %d", input_data->data);
/* set next node index */
next_index = n->next_nodes[0];
/* send packet to next node */
to_next[0] = bi0;
to_next += 1;
n_left_to_next -= 1;
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, bi0, output_buffer_index, 0);
}
}
/* send packets to the next node */
vlib_put_next_frame (vm, node, n->index, frame->n_vectors);
return frame->n_vectors;
}
/* register nodes and create arcs */
static clib_error_t * ipv4_hello_world_init (vlib_main_t * vm) {
/* declare node functions */
vlib_node_t *node = &ipv4_hello_world_node;
vlib_node_register (vm, node);
/* set node flags */
node->flags |= VLIB_NODE_FLAG_TRACE_SUPPORTED;
node->function = ipv4_hello_world_node_fn;
/* register input/output structs */
vlib_register_input_node (vm, node->index, VLIB_NODE_STATE_DISABLED, 1, sizeof(input_structure_t), NULL);
vlib_register_output_node (vm, node->index, VLIB_NODE_STATE_DISABLED, 1, sizeof(output_structure_t), NULL);
return 0;
}
VLIB_INIT_FUNCTION (ipv4_hello_world_init);
- 将插件添加到vpp中。我们可以将上面的代码保存在$VPP_ROOT/plugins/ipv4_hello_world目录下,并使用以下命令来构建插件:
$ cd $VPP_ROOT
$ make build
- 在vpp中测试插件。可以使用以下命令来启用插件并测试它:
$ vppctl
# set interface ip address GigabitEthernet0/8/0 10.0.0.1/24
# create host-interface name test-hif
# set int state test-hif up
# set int l2 bridge test-hif 1 bvi
# set int ip address test-bvi 10.0.1.1/24
# trace add node ipv4-hello-world
# ping 10.0.1.2 verbose
在上面的代码中,我们添加了一个名为ipv4-hello-world的新节点,并使用trace add命令跟踪该节点。然后,我们ping测试10.0.1.2,并查看输出结果。
调试和优化插件。确保插件可以正常运行,并使用调试工具和技术来优化其性能和可靠性。
发布插件。如果插件被认为是有价值的,则可以将其发布到VPP社区中,并与其他开发者共享。