DPDK 命令行

一:利用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

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值