DPDK 命令行

    技术2022-07-12  75

    一:利用DPDK,给程序添加命令行代码,添加一个命令由四部分组成: 1. 命令行初始化 2. 命令行解析 3. 命令行参数的数据结构 4. 命令行的功能实现函数

    源码 dpdk-18.08/examples/cmdline 中提供了一个完整的 Demo 可以供参考

    一些结构体和变量 需要详细的可以看 源码Demo 可以 在主lcore上从main调用,启动命令行的线程

    /* 启动命令行线程 */ if (rte_ctrl_thread_create(&telnet_thread, "sf_cmdline", NULL, sf_cmdline_thread, NULL) < 0) { RTE_LOG(ERR, EAL, "failed to create cmdline thead: %s\n", strerror(errno)); } static void *sf_cmdline_thread(__attribute__((unused)) void *arg) { fflush(stdout); /* 启用命令行模式 */ sf_prompt(); printf("\nLog out cmdline !\n"); return NULL; } void sf_prompt(void) { softflow_cl = cmdline_stdin_new(sf_main_ctx, "example> ");//创建一个命令行对象并且通过控制台和用户交互; if (softflow_cl == NULL) { rte_panic("Cannot create cmdline instance\n"); } cmdline_interact(softflow_cl); cmdline_stdin_exit(softflow_cl); //上面这两行,是命令行模块的运行和退出函数; //当用户键入ctrl - d时,cmd line_interact()函数返回,在本例中是应用程序退出 }

    代码中的 sf_main_ctx 其实就是保存命令行的数组,该数组保存了所有命令行的实例(包含:定义、解析以及功能),以 NULL 结束:

    cmdline_parse_ctx_t sf_main_ctx[] = { (cmdline_parse_inst_t *) &cmd_help, (cmdline_parse_inst_t *) &cmd_quit, (cmdline_parse_inst_t *) &cmd_exit, (cmdline_parse_inst_t *) &cmd_acl_rule_add, NULL, };

    如何初始化命令行 随便拿一个举例 cmd_acl_rule_add 命令

    cmdline_parse_inst_t cmd_acl_rule_add = { .f = cmd_acl_rule_add_parsed, //要调用的函数,命令行的功能 .data = NULL, /* 2nd arg of func */ .help_str = "rule <rule_id> proto <proto_num> " "ip-src <ip_src> ip-src-mask <ip_src_mask> " "ip-dst <ip_dst> ip-dst-mask <ip_dst_mask> " "l4-src-port <l4_src_port> " "l4-dst-port <l4_dst_port> " "redirect-port <port_id>", .tokens = { //token 列表, 以 NULL 结束, (void *)&cmd_acl_rule_add_rule, (void *)&cmd_acl_rule_add_rule_id, (void *)&cmd_acl_rule_add_proto, (void *)&cmd_acl_rule_add_protol_num, (void *)&cmd_acl_rule_add_ip_src, (void *)&cmd_acl_rule_add_ip_src_value, (void *)&cmd_acl_rule_add_ip_src_mask, (void *)&cmd_acl_rule_add_ip_src_mask_value, (void *)&cmd_acl_rule_add_ip_dst, (void *)&cmd_acl_rule_add_ip_dst_value, (void *)&cmd_acl_rule_add_ip_dst_mask, (void *)&cmd_acl_rule_add_ip_dst_mask_value, (void *)&cmd_acl_rule_add_l4_src_port, (void *)&cmd_acl_rule_add_l4_src_port_value, (void *)&cmd_acl_rule_add_l4_dst_port, (void *)&cmd_acl_rule_add_l4_dst_port_value, (void *)&cmd_acl_rule_add_ip_redirect_port, (void *)&cmd_acl_rule_add_output_port_value, NULL, }, };

    .f 命令行的功能实现函数 .help_str 命令行格式的定义 .tokens 命令行的一个解析列表

    下面代码就是命令行的解析 ,将我们命令解析成我们想要的格式,存储到结构体中

    cmdline_parse_token_string_t cmd_acl_rule_add_rule = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, rule, "rule"); cmdline_parse_token_num_t cmd_acl_rule_add_rule_id = TOKEN_NUM_INITIALIZER(struct cmd_acl_rule_add_result, rule_id, UINT16); cmdline_parse_token_string_t cmd_acl_rule_add_proto = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, proto, "proto"); cmdline_parse_token_num_t cmd_acl_rule_add_protol_num = TOKEN_NUM_INITIALIZER(struct cmd_acl_rule_add_result, proto_num, UINT8); cmdline_parse_token_string_t cmd_acl_rule_add_ip_src = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, ip_src, "ip-src"); cmdline_parse_token_num_t cmd_acl_rule_add_ip_src_value = TOKEN_IPADDR_INITIALIZER(struct cmd_acl_rule_add_result, ip_src_value); cmdline_parse_token_string_t cmd_acl_rule_add_ip_src_mask = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, ip_src_mask, "ip-src-mask"); cmdline_parse_token_num_t cmd_acl_rule_add_ip_src_mask_value = TOKEN_IPADDR_INITIALIZER(struct cmd_acl_rule_add_result, ip_src_mask_value); cmdline_parse_token_string_t cmd_acl_rule_add_ip_dst = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, ip_dst, "ip-dst"); cmdline_parse_token_num_t cmd_acl_rule_add_ip_dst_value = TOKEN_IPADDR_INITIALIZER(struct cmd_acl_rule_add_result, ip_dst_value); cmdline_parse_token_string_t cmd_acl_rule_add_ip_dst_mask = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, ip_dst_mask, "ip-dst-mask"); cmdline_parse_token_num_t cmd_acl_rule_add_ip_dst_mask_value = TOKEN_IPADDR_INITIALIZER(struct cmd_acl_rule_add_result, ip_dst_mask_value); cmdline_parse_token_string_t cmd_acl_rule_add_l4_src_port = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, l4_src_port, "l4-src-port"); cmdline_parse_token_num_t cmd_acl_rule_add_l4_src_port_value = TOKEN_NUM_INITIALIZER(struct cmd_acl_rule_add_result, l4_src_port_value, UINT16); cmdline_parse_token_string_t cmd_acl_rule_add_l4_dst_port = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, l4_dst_port, "l4-dst-port"); cmdline_parse_token_num_t cmd_acl_rule_add_l4_dst_port_value = TOKEN_NUM_INITIALIZER(struct cmd_acl_rule_add_result, l4_dst_port_value, UINT16); cmdline_parse_token_string_t cmd_acl_rule_add_ip_redirect_port = TOKEN_STRING_INITIALIZER(struct cmd_acl_rule_add_result, ip_redirect_port, "redirect-port"); cmdline_parse_token_num_t cmd_acl_rule_add_output_port_value = TOKEN_NUM_INITIALIZER(struct cmd_acl_rule_add_result, output_port_value, UINT16);

    该结构体用于存储命令行的参数列

    /* *** ACL rule add *** */ struct cmd_acl_rule_add_result { cmdline_fixed_string_t rule; uint16_t rule_id; cmdline_fixed_string_t proto; uint8_t proto_num; cmdline_fixed_string_t ip_src; cmdline_ipaddr_t ip_src_value; cmdline_fixed_string_t ip_src_mask; cmdline_ipaddr_t ip_src_mask_value; cmdline_fixed_string_t ip_dst; cmdline_ipaddr_t ip_dst_value; cmdline_fixed_string_t ip_dst_mask; cmdline_ipaddr_t ip_dst_mask_value; cmdline_fixed_string_t l4_src_port; uint16_t l4_src_port_value; cmdline_fixed_string_t l4_dst_port; uint16_t l4_dst_port_value; cmdline_fixed_string_t ip_redirect_port; uint16_t output_port_value; };

    命令行的功能 cmd_acl_rule_add_parsed 执行某个命令具体完成的功能:

    static void cmd_acl_rule_add_parsed(void *parsed_result, struct cmdline *cl, __attribute__((unused)) void *data) { struct cmd_acl_rule_add_result *res = parsed_result; struct split_policy_node node = {0}; node.Rule_id = res->rule_id; node.Protocol_transport = res->proto_num; IPV4_ADDR_TO_UINT(res->ip_src_value, node.Source_ip); IPV4_ADDR_TO_UINT(res->ip_src_mask_value, node.Source_mask); IPV4_ADDR_TO_UINT(res->ip_dst_value, node.Dest_ip); IPV4_ADDR_TO_UINT(res->ip_dst_mask_value, node.Dest_mask); node.Src_port = res->l4_src_port_value; node.Dst_port = res->l4_dst_port_value; node.Action = REDIRECT_TO_PORT; node.Outbound_pg = res->output_port_value; if (node.Outbound_pg < 0 || node.Outbound_pg > 47) { cmdline_printf(cl, "The specified port id is out of range\n"); return; } if (split_policy_add(&node) == 0) { cmdline_printf(cl, "Add acl rule success\n"); } else { cmdline_printf(cl, "Add acl rule failed!\n"); } }

    *void parsed_result 参数 // 命令行参数结构体; 就是我们命令行解析出来的结构体

    参考文档 https://blog.csdn.net/zhang1051546117/article/details/78051240

    Processed: 0.012, SQL: 9