一:利用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 proto "
"ip-src ip-src-mask "
"ip-dst ip-dst-mask "
"l4-src-port "
"l4-dst-port "
"redirect-port " ,
.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