dpdk学习之ip_pipeline源代码分析
首先从main函数开始,我们一个函数一个函数的逐层进行分析
开启日志,日志级别是stderr
3.app_config_preproc(&app);
int
app_config_parse(struct app_params *app,const char *file_name)
{
struct rte_cfgfile *cfg;
char **section_names;
int i,j,sect_count;
/* Implicit mempools */
create_implicit_mempools(app);
/* Port mask 根据port mask生成link_params参数,并记录下portid */
if (app->port_mask)
create_implicit_links_from_port_mask(app,app->port_mask);
/* Load application configuration file * 读取配置文件 */
cfg = rte_cfgfile_load(file_name,0);
APP_CHECK((cfg != NULL),"Parse error: Unable to load config "
"file %s",file_name);
//获取section数
sect_count = rte_cfgfile_num_sections(cfg,NULL,0);
APP_CHECK((sect_count > 0),"Parse error: number of sections "
"in file "%s" return %d",file_name,sect_count);
//为section申请资源
section_names = malloc(sect_count * sizeof(char *));
PARSE_ERROR_MALLOC(section_names != NULL);
for (i = 0; i < sect_count; i++)
section_names[i] = malloc(CFG_NAME_LEN);
//sect_count为section个数
rte_cfgfile_sections(cfg,section_names,sect_count);
for (i = 0; i < sect_count; i++) {
const struct config_section *sch_s;
int len,cfg_name_len;
cfg_name_len = strlen(section_names[i]);
/* Find section type */
for (j = 0; j < (int)RTE_DIM(cfg_file_scheme); j++) {
sch_s = &cfg_file_scheme[j];
len = strlen(sch_s->prefix);
if (cfg_name_len < len)
continue;
/* After section name we expect only ' ' or digit or * digit dot digit,so protect against false matching,* for example: "ABC" should match section name * "ABC0.0",but it should not match section_name * "ABCDEF". */
if ((section_names[i][len] != ' ') &&
!isdigit(section_names[i][len]))
continue;
if (strncmp(sch_s->prefix,section_names[i],len) == 0)
break;
}
APP_CHECK(j < (int)RTE_DIM(cfg_file_scheme),"Parse error: unknown section %s",section_names[i]);
APP_CHECK(validate_name(section_names[i],sch_s->prefix,sch_s->numbers) == 0,"Parse error: invalid section name "%s"",section_names[i]);
sch_s->load(app,cfg);
}
for (i = 0; i < sect_count; i++)
free(section_names[i]);
free(section_names);
rte_cfgfile_close(cfg);
//统计app中每一种section元素的配置数量
APP_PARAM_COUNT(app->mempool_params,app->n_mempools);
APP_PARAM_COUNT(app->link_params,app->n_links);//这里获取到的n_links容易出错啊
APP_PARAM_COUNT(app->hwq_in_params,app->n_pktq_hwq_in);
APP_PARAM_COUNT(app->hwq_out_params,app->n_pktq_hwq_out);
APP_PARAM_COUNT(app->swq_params,app->n_pktq_swq);
APP_PARAM_COUNT(app->tm_params,app->n_pktq_tm);
APP_PARAM_COUNT(app->tap_params,app->n_pktq_tap);
APP_PARAM_COUNT(app->kni_params,app->n_pktq_kni);
APP_PARAM_COUNT(app->source_params,app->n_pktq_source);
APP_PARAM_COUNT(app->sink_params,app->n_pktq_sink);
APP_PARAM_COUNT(app->msgq_params,app->n_msgq);
APP_PARAM_COUNT(app->pipeline_params,app->n_pipelines);
/*app->port_mask为0的情况*/
if (app->port_mask == 0)
assign_link_pmd_id_from_pci_bdf(app);
/* Save configuration to output file 将配置文件保存到app->output_file指定的文件中 */
app_config_save(app,app->output_file);
/* Load TM configuration files */
app_config_parse_tm(app);
return 0;
}
create_implicit_mempools(app);函数中 读取配置文件中的section数,然后为section申请内存资源. 调用APP_PARAM_COUNT去统计pipeline中每一种section元素的配置数量 最后将配置文件保存到app->output_file指定的文件中,方便我们日后排查问题时查看.
6.1 初始化内存池 6.2 初始化link链接 /获取rx queue数量/ /设置rte_eth_conf结构体/ 调用关键函数rte_eth_dev_configure,这个函数不多说 /获取端口的mac地址/ /设置混杂模式/ 下面分别是创建接收队列 /* TXQ 创建发送队列*/ /检测link状态/ 6.3 创建软队列 6.4 注册pipeline节点类型 struct pipeline_type pipeline_master = { pipeline_flow_actions的定义 pipeline_flow_actions_be_ops定义如下: static int pipeline_msg_req_handle(p); rte_pipeline_flush(p->p); return 0; } for (msgq_id = 0; msgq_id < p->n_msgq; msgq_id++) { for ( ; ; ) { struct pipeline_msg_req *req; pipeline_msg_req_handler f_handle; req = pipeline_msg_recv(p,msgq_id); if (req == NULL) break; f_handle = (req->type < PIPELINE_MSG_REQS) ? p->handlers[req->type] : pipeline_msg_req_invalid_handler; if (f_handle == NULL) f_handle = pipeline_msg_req_invalid_handler; pipeline_msg_send(p,msgq_id,f_handle(p,(void *) req)); } } return 0; } 6.5 app_init_pipelines 初始化pipeline模块 back-end 和 front-end 这个后续研究透了,再补充下 struct pipeline_type {
const char *name;
/* pipeline back-end */
struct pipeline_be_ops *be_ops;
/* pipeline front-end */
struct pipeline_fe_ops *fe_ops;
};
struct pipeline_fe_ops {
pipeline_fe_op_init f_init;
pipeline_fe_op_post_init f_post_init;
pipeline_fe_op_free f_free;
pipeline_fe_op_track f_track;
cmdline_parse_ctx_t *cmds;
};
pipeline_fe_ops结构体中的成员都是函数指针类型的,函数指针类型的定义如下
typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params,void *arg);
typedef int (*pipeline_fe_op_post_init)(void *pipeline);
typedef int (*pipeline_fe_op_free)(void *pipeline);
typedef int (*pipeline_fe_op_track)(struct pipeline_params *params,uint32_t port_in,uint32_t *port_out);
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |