DPDK 设备命令行添加

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

(1)命令行数据结构,如下:

struct cmd_obj_add_result {                
	cmdline_fixed_string_t action;              //cmdline_fixed_string_t字符数组类型的别名;
	cmdline_fixed_string_t name;                //
	cmdline_ipaddr_t ip;                        //
};

(2)命令行功能函数,如下:

static void cmd_obj_add_parsed(void *parsed_result,struct cmdline *cl, __attribute__((unused)) void *data)//参数貌似固定  ????
{
	struct cmd_obj_add_result *res = parsed_result;   //初始化命令行的结构体;
	struct object *o;
	char ip_str[INET6_ADDRSTRLEN];

	SLIST_FOREACH(o, &global_obj_list, next) {          //SLIST_FOREACH什么意思?????????????????
		if (!strcmp(res->name, o->name)) {
			cmdline_printf(cl, "Object %s already exist\n", res->name);
			return;
		}
		break;
	}

	o = malloc(sizeof(*o));
	if (!o) {
		cmdline_printf(cl, "mem error\n");
		return;
	}
	snprintf(o->name, sizeof(o->name), "%s", res->name);
	o->ip = res->ip;
	SLIST_INSERT_HEAD(&global_obj_list, o, next);

	if (o->ip.family == AF_INET)
		snprintf(ip_str, sizeof(ip_str), NIPQUAD_FMT,
			 NIPQUAD(o->ip.addr.ipv4));
	else
		snprintf(ip_str, sizeof(ip_str), NIP6_FMT,
			 NIP6(o->ip.addr.ipv6));

	cmdline_printf(cl, "Object %s added, ip=%s\n",
		       o->name, ip_str);
}
(3)对命令行中的每个参数进行校验解析,如下:

cmdline_parse_token_string_t cmd_obj_action_add =                        //add zxw 10.190.3.19---说明需要三个token
	TOKEN_STRING_INITIALIZER(struct cmd_obj_add_result, action, "add");
cmdline_parse_token_string_t cmd_obj_name =                        //这里需要字符串;
	TOKEN_STRING_INITIALIZER(struct cmd_obj_add_result, name, NULL);  //所有字符串都可以
cmdline_parse_token_ipaddr_t cmd_obj_ip =                          //这里需要ip;
	TOKEN_IPADDR_INITIALIZER(struct cmd_obj_add_result, ip);

(4)初始化命令行,如下:

cmdline_parse_inst_t cmd_obj_add = {
	.f = cmd_obj_add_parsed,  /* function to call */
	.data = NULL,      /* 2nd arg of func */
	.help_str = "Add an object (name, val)",
	.tokens = {                               /* token列表, NULL结束 */
		(void *)&cmd_obj_action_add,
		(void *)&cmd_obj_name,
		(void *)&cmd_obj_ip,
		NULL,
	},
};

上面都实现完以后,需要将初始化的命令行添加到一个保存命令行的数组中,数组以NULL结束;

cmdline_parse_ctx_t main_ctx[] = {
	(cmdline_parse_inst_t *)&cmd_obj_add,
	NULL,
};

然后在mian( )函数中创建命令行对象,通过控制台和用户交互,具体实现如下:

int main(int argc, char **argv)
{
	int ret;
	struct cmdline *cl;                   //命令行对象cl;

	ret = rte_eal_init(argc, argv);
	if (ret < 0)
		rte_panic("Cannot init EAL\n");

	cl = cmdline_stdin_new(main_ctx, "example> ");   //创建一个命令行对象并且通过控制台和用户交互;
	//将命令行模块初始化,其中main_ctx是一个结构体指针,在commands.c中;
	
	if (cl == NULL)
		rte_panic("Cannot create cmdline instance\n");
	cmdline_interact(cl);
	cmdline_stdin_exit(cl);          //上面这两行,是命令行模块的运行和退出函数;
	                                 //当用户键入ctrl - d时,cmd line_interact()函数返回,在本例中是应用程序退出。

	return 0;
}


上面是一个简答的命令行,根据需要可以添加自己需要的命令行,我目前给设备添加的部分命令行代码如下(不包含头文件):

extern int fwd_get_port_mac(uint16_t port);
extern int fwd_set_port_mac(uint16_t port, uint32_t hmac, uint32_t lmac);




/*******************************************************************/
struct cmd_help_result {
	cmdline_fixed_string_t help;
};

static void cmd_help_parsed(__attribute__((unused)) void *parsed_result,
			    struct cmdline *cl,
			    __attribute__((unused)) void *data)
{
	cmdline_printf(cl,
		       "\n\nDemo example of command line interface in RTE\n"
		       "This is a readline-like interface that can be used to\n"
		       "debug your RTE application. It supports some features\n"
		       "of GNU readline like completion, cut/paste, and some\n"
		       "other special bindings.\n\n"
		       "This demo shows how rte_cmdline library can be\n"
		       "extended to handle a list of objects. There are\n"
		       "3 commands:\n"
                       "- fwd_log_level_set level\n"
                       "- fwd_tbl_set_phy2lport entryId slot_id logical_port nat_flag\n"
	 	       "- fwd_set_port_mac port hmac lmac\n"
                       "- fwd_get_port_mac port\n"
			    "- fwd_get_shortflow src_phy_port svlan cvlan\n");
}

cmdline_parse_token_string_t cmd_help_help =
	TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help");

cmdline_parse_inst_t cmd_help = {
	.f = cmd_help_parsed,  /* function to call */
	.data = NULL,      /* 2nd arg of func */
	.help_str = "show help",
	.tokens = {        /* token list, NULL terminated */
		(void *)&cmd_help_help,
		NULL,
	},
};
/***************************************************************/


/************************(1)*******************************/
struct cmd_fwd_log_level_set_result                //在DPDK_fwd_debug.c中
{
	cmdline_fixed_string_t action;
	int level;                
};

static void cmd_fwd_log_level_set_parased(void*parsed_result,
			       struct cmdline *cl,
			       __attribute__((unused)) void *data)
{   
    struct cmd_fwd_log_level_set_result * res=parsed_result;
	fwd_log_level_set(res->level);
    cmdline_printf(cl,"cmd_obj_math_parased() is called!\n");	
}

cmdline_parse_token_string_t cmd_fwd_log_level_set_action=
    TOKEN_STRING_INITIALIZER(struct cmd_fwd_log_level_set_result, action, "fwd_log_level_set");	
cmdline_parse_token_num_t cmd_fwd_log_level_set_level=
	TOKEN_NUM_INITIALIZER(struct cmd_fwd_log_level_set_result, level,INT32); 

cmdline_parse_inst_t cmd_fwd_log_level_set = {
	.f = cmd_fwd_log_level_set_parased,  /* function to call */
	.data = NULL,      /* 2nd arg of func */
	.help_str = "cmd_fwd_log_level_set level",
	.tokens = {        /* token list, NULL terminated */
		(void *)&cmd_fwd_log_level_set_action,
		(void *)&cmd_fwd_log_level_set_level,
		NULL,
	},
};

/************************ (1)**********************************/


/************************(2)*******************************/
struct cmd_fwd_tbl_set_phy2lport_result    //在DPDK_fwd_debug.c中
{
	cmdline_fixed_string_t action;
	uint32_t entryId;
	int slot_id;
	int logical_port;
	int nat_flag;
};

static void cmd_fwd_tbl_set_phy2lport_parased(void*parsed_result,
			       struct cmdline *cl,
			       __attribute__((unused)) void *data)
{
    struct cmd_fwd_tbl_set_phy2lport_result *res=parsed_result;
	fwd_tbl_set_phy2lport(res->entryId, res->slot_id, res->logical_port, res->nat_flag);
	cmdline_printf(cl,"fwd_tbl_set_phy2lport() is called!\n");					   
}

cmdline_parse_token_string_t cmd_fwd_tbl_set_phy2lport_action=
    TOKEN_STRING_INITIALIZER(struct cmd_fwd_tbl_set_phy2lport_result, action, "fwd_tbl_set_phy2lport");		
cmdline_parse_token_num_t cmd_fwd_tbl_set_phy2lport_entryId=
	TOKEN_NUM_INITIALIZER(struct cmd_fwd_tbl_set_phy2lport_result, entryId,INT32); 
cmdline_parse_token_num_t cmd_fwd_tbl_set_phy2lport_slot_id=
	TOKEN_NUM_INITIALIZER(struct cmd_fwd_tbl_set_phy2lport_result, slot_id,INT32); 
cmdline_parse_token_num_t cmd_fwd_tbl_set_phy2lport_logical_port=
	TOKEN_NUM_INITIALIZER(struct cmd_fwd_tbl_set_phy2lport_result, logical_port,INT32); 
cmdline_parse_token_num_t cmd_fwd_tbl_set_phy2lport_nat_flag=
	TOKEN_NUM_INITIALIZER(struct cmd_fwd_tbl_set_phy2lport_result, nat_flag,INT32); 

cmdline_parse_inst_t cmd_fwd_tbl_set_phy2lport= {
	.f = cmd_fwd_tbl_set_phy2lport_parased,  /* function to call */
	.data = NULL,      /* 2nd arg of func */
	.help_str = "fwd_tbl_set_phy2lport entryId slot_id logical_port nat_flag",
	.tokens = {        /* token list, NULL terminated */
		(void *)&cmd_fwd_tbl_set_phy2lport_action,
		(void *)&cmd_fwd_tbl_set_phy2lport_entryId,
		(void *)&cmd_fwd_tbl_set_phy2lport_slot_id,
		(void *)&cmd_fwd_tbl_set_phy2lport_logical_port,
		(void *)&cmd_fwd_tbl_set_phy2lport_nat_flag,
		NULL,
	},
};	

/************************(2)*******************************/

/************************(3)*******************************/
struct cmd_fwd_set_port_mac_resuct       //在Netdev_api.c中
{
	cmdline_fixed_string_t action;
	int port;
	int hmac;
	int lmac;
};

static void cmd_fwd_set_port_mac_parased(void*parsed_result,
			       struct cmdline *cl,
			       __attribute__((unused)) void *data)
{
	struct cmd_fwd_set_port_mac_resuct *res=parsed_result;
	
	fwd_set_port_mac(res->port, res->hmac, res->lmac);
	cmdline_printf(cl,"fwd_set_port_mac() is called!\n");					   
}

cmdline_parse_token_string_t cmd_fwd_set_port_mac_action=
    TOKEN_STRING_INITIALIZER(struct cmd_fwd_set_port_mac_resuct, action, "fwd_set_port_mac");	
cmdline_parse_token_num_t cmd_fwd_set_port_mac_port=
    TOKEN_NUM_INITIALIZER(struct cmd_fwd_set_port_mac_resuct,port,INT32);
cmdline_parse_token_num_t cmd_fwd_set_port_mac_hmac=
    TOKEN_NUM_INITIALIZER(struct cmd_fwd_set_port_mac_resuct,hmac,INT64);
cmdline_parse_token_num_t cmd_fwd_set_port_mac_lmac=
    TOKEN_NUM_INITIALIZER(struct cmd_fwd_set_port_mac_resuct,lmac,INT64);

cmdline_parse_inst_t cmd_fwd_set_port_mac={
	.f = cmd_fwd_set_port_mac_parased,
	.data = NULL,
	.help_str = "cmd_fwd_set_port_mac port hmac lmac",
	.tokens = {
		(void *)&cmd_fwd_set_port_mac_action,
		(void *)&cmd_fwd_set_port_mac_port,
		(void *)&cmd_fwd_set_port_mac_hmac,
		(void *)&cmd_fwd_set_port_mac_lmac,
		NULL,
	},
};
/************************(3)*******************************/

/************************(4)*******************************/
struct cmd_fwd_get_port_mac_resuct{               //同上
	cmdline_fixed_string_t action;
	int port;
};

static void cmd_fwd_get_port_mac_parased(void*parsed_result,
			       struct cmdline *cl,
			       __attribute__((unused)) void *data)
{
	struct cmd_fwd_get_port_mac_resuct *res=parsed_result;
	fwd_get_port_mac(res->port);
	cmdline_printf(cl,"fwd_get_port_mac() is called!\n");			   
}

cmdline_parse_token_string_t cmd_fwd_get_port_mac_action=
    TOKEN_STRING_INITIALIZER(struct cmd_fwd_get_port_mac_resuct, action, "fwd_get_port_mac");	
cmdline_parse_token_num_t cmd_fwd_get_port_mac_port=
    TOKEN_NUM_INITIALIZER(struct cmd_fwd_get_port_mac_resuct,port,INT32);

cmdline_parse_inst_t cmd_fwd_get_port_mac={
	.f = cmd_fwd_get_port_mac_parased,
	.data = NULL,
	.help_str = "cmd_fwd_get_port_mac port",
	.tokens = {
		(void *)&cmd_fwd_get_port_mac_action,
		(void *)&cmd_fwd_get_port_mac_port,
		NULL,
	},
};
/************************(4)*******************************/

/************************(5)*******************************/
//fwd_get_shortflow
struct cmd_fwd_get_shortflow_resuct{
	cmdline_fixed_string_t action;
	int src_phy_port;
	int svlan;
	int cvlan;
};

static void cmd_fwd_get_shortflow_parased(void*parsed_result,
			       struct cmdline *cl,
			       __attribute__((unused)) void *data)
{
	struct cmd_fwd_get_shortflow_resuct *res=parsed_result;
	fwd_get_shortflow(res->src_phy_port, res->svlan, res->cvlan);
	cmdline_printf(cl,"fwd_fwd_get_shortflow() is called!\n");					   
}

cmdline_parse_token_string_t cmd_fwd_get_shortflow_action=
    TOKEN_STRING_INITIALIZER(struct cmd_fwd_get_shortflow_resuct, action, "fwd_get_shortflow");
cmdline_parse_token_num_t  cmd_fwd_get_shortflow_src_phy_port=
    TOKEN_NUM_INITIALIZER(struct cmd_fwd_get_shortflow_resuct,src_phy_port,INT32);
cmdline_parse_token_num_t  cmd_fwd_get_shortflow_src_svlan=
    TOKEN_NUM_INITIALIZER(struct cmd_fwd_get_shortflow_resuct,svlan,INT32);
cmdline_parse_token_num_t  cmd_fwd_get_shortflow_src_cvlan=
    TOKEN_NUM_INITIALIZER(struct cmd_fwd_get_shortflow_resuct,cvlan,INT32);

cmdline_parse_inst_t cmd_fwd_get_shortflow={
	.f = cmd_fwd_get_shortflow_parased,
	.data = NULL,
	.help_str = "fwd_get_shortflow_parased src_phy_port svlan cvlan",
	.tokens = {
		(void *)&cmd_fwd_get_shortflow_action,
		(void *)&cmd_fwd_get_shortflow_src_phy_port,
		(void *)&cmd_fwd_get_shortflow_src_svlan,
		(void *)&cmd_fwd_get_shortflow_src_cvlan,
		NULL,
	},
};
/************************(5)*******************************/


/**********************************************************/
/****** CONTEXT (list of instruction) */
cmdline_parse_ctx_t main_ctx[] = {
	(cmdline_parse_inst_t *)&cmd_help,
    (cmdline_parse_inst_t *)&cmd_fwd_log_level_set,
    (cmdline_parse_inst_t *)&cmd_fwd_tbl_set_phy2lport,
	(cmdline_parse_inst_t *)&cmd_fwd_set_port_mac,
	(cmdline_parse_inst_t *)&cmd_fwd_get_port_mac,
	(cmdline_parse_inst_t *)&cmd_fwd_get_shortflow,
	NULL,
};



你可能感兴趣的:(DPDK,DPDK)