-
Notifications
You must be signed in to change notification settings - Fork 16
/
rte_eal_init详解.txt
190 lines (150 loc) · 7.33 KB
/
rte_eal_init详解.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
int
rte_eal_init(int argc, char **argv)
{
int i, fctret, ret;
pthread_t thread_id;
static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
const char *logid;
char cpuset[RTE_CPU_AFFINITY_STR_LEN];
char thread_name[RTE_MAX_THREAD_NAME_LEN];
//判断run_once是否为1。确保rte_eal_init只调用一次,即只对dpdk做一次初始化。
if (!rte_atomic32_test_and_set(&run_once))
return -1;
logid = strrchr(argv[0], '/');
logid = strdup(logid ? logid + 1: argv[0]);
//获取调用rte_eal_init函数的线程的线程id
thread_id = pthread_self();
//初始化日志的流。
if (rte_eal_log_early_init() < 0)
rte_panic("Cannot init early logs\n");
//通过命令行参数,得到日志等级
eal_log_level_parse(argc, argv);
//设置日志等级
rte_set_log_level(internal_config.log_level);
//得到CPU核信息,初始化变量struct rte_config *config和struct lcore_config lcore_config[RTE_MAX_LCORE];
//两个变量都为全局变量,lcore_config用于记录每个核的信息;config用于记录整体信息。
if (rte_eal_cpu_init() < 0)
rte_panic("Cannot detect lcores\n");
//对其他命令行参数进行解析
fctret = eal_parse_args(argc, argv);
if (fctret < 0)
exit(1);
//获取系统大页的信息,包括:页大小,也要挂载的路径,页个数。。。等。
if (internal_config.no_hugetlbfs == 0 &&
internal_config.process_type != RTE_PROC_SECONDARY &&
internal_config.xen_dom0_support == 0 &&
eal_hugepage_info_init() < 0)
rte_panic("Cannot get hugepage information\n");
if (internal_config.memory == 0 && internal_config.force_sockets == 0) {
if (internal_config.no_hugetlbfs)
internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE;
else
internal_config.memory = eal_get_hugepage_mem_size();
}
if (internal_config.vmware_tsc_map == 1)
{
#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT
rte_cycles_vmware_tsc_map = 1;
RTE_LOG (DEBUG, EAL, "Using VMWARE TSC MAP, "
"you must have monitor_control.pseudo_perfctr = TRUE\n");
#else
RTE_LOG (WARNING, EAL, "Ignoring --vmware-tsc-map because "
"RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set\n");
#endif
}
//设置随机数种子
rte_srand(rte_rdtsc());
//如果是主进程,那么分配rte_config.mem_config(struct rte_mem_config)空间,建立内存映射,便于从进程访问。内存映射路径默认为:/var/run/.rte_config
//如果是从进程,那么通过内存映射获取主进程rte_config.mem_config的地址并对自己的结构赋值。
rte_config_init();
//通过文件/sys/bus/pci/devices,获取所有pci设备的信息
if (rte_eal_pci_init() < 0)
rte_panic("Cannot init PCI\n");
#ifdef RTE_LIBRTE_IVSHMEM
if (rte_eal_ivshmem_init() < 0)
rte_panic("Cannot init IVSHMEM\n");
#endif
//------如果是主进程调用函数rte_eal_hugepage_init,那么对大页做如下初始化;
//1.为每个大页建立一个内存映射文件,默认建立路径为:/mnt/huge
//2.通过内存映射的虚拟地址得到物理地址
//3.得到大页的socket id
//4.重新组织大页,将大页连续的虚拟地址和物理地址,已经想通的也大小和socket的页,作为一个整体,便于分配,保存到变量rte_config.mem_config.memseg中。
//5.创建一个/var/run/.rte_hugepage_info文件,用于保存每个大页的rte_hugepage_info结构。
//--------如果是从进程调用rte_eal_hugepage_attach,那么将其attach到大页中:
//1.第一次映射判断是否能够联系映射
//2.通过读取/var/run/.rte_hugepage_info文件的也信息结构,通过计算得到页个数
//3。然后通过信息进行映射
if (rte_eal_memory_init() < 0)
rte_panic("Cannot init memory\n");
/* the directories are locked during eal_hugepage_info_init */
eal_hugedirs_unlock();
//通过rte_confige.rte_mem_config.memseg建立内存链表,其中memzone为内存分配器。
if (rte_eal_memzone_init() < 0)
rte_panic("Cannot init memzone\n");
if (rte_eal_tailqs_init() < 0)
rte_panic("Cannot init tail queues for objects\n");
#ifdef RTE_LIBRTE_IVSHMEM
if (rte_eal_ivshmem_obj_init() < 0)
rte_panic("Cannot init IVSHMEM objects\n");
#endif
if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
rte_panic("Cannot init logs\n");
if (rte_eal_alarm_init() < 0)
rte_panic("Cannot init interrupt-handling thread\n");
if (rte_eal_timer_init() < 0)
rte_panic("Cannot init HPET or TSC timers\n");
eal_check_mem_on_local_socket();
if (eal_plugins_init() < 0)
rte_panic("Cannot init plugins\n");
eal_thread_init_master(rte_config.master_lcore);
ret = eal_thread_dump_affinity(cpuset, RTE_CPU_AFFINITY_STR_LEN);
RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%x;cpuset=[%s%s])\n",
rte_config.master_lcore, (int)thread_id, cpuset,
ret == 0 ? "" : "...");
//通过得到的dev_driver_list,遍历dev_driver_list,调用每个driver的初始化函数,将驱动注册到pci_driver_list中,元素结构体为rte_pci_driver。
//rte_eal_init[eal.c] ------> rte_eal_dev_init[eal.c] -----> 遍历dev_driver_list列表,调用每个driver的init(driver->init(......))
// rte_eth_driver_register[eal_commmon_pci.c](注册设备初始化函数和卸载函数 rte_eth_dev_init与rte_eth_dev_uninit)
// -----> rte_eal_pci_register[eal_commmon_pci.c] ----> TAILQ_INSERT_TAIL(&pci_driver_list, driver, next)
if (rte_eal_dev_init() < 0)
rte_panic("Cannot init pmd devices\n");
if (rte_eal_intr_init() < 0)
rte_panic("Cannot init interrupt-handling thread\n");
RTE_LCORE_FOREACH_SLAVE(i) {
/*
* create communication pipes between master thread
* and children
*/
if (pipe(lcore_config[i].pipe_master2slave) < 0)
rte_panic("Cannot create pipe\n");
if (pipe(lcore_config[i].pipe_slave2master) < 0)
rte_panic("Cannot create pipe\n");
lcore_config[i].state = WAIT;
/* create a thread for each lcore */
ret = pthread_create(&lcore_config[i].thread_id, NULL,
eal_thread_loop, NULL);
if (ret != 0)
rte_panic("Cannot create thread\n");
/* Set thread_name for aid in debugging. */
snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN,
"lcore-slave-%d", i);
ret = rte_thread_setname(lcore_config[i].thread_id,
thread_name);
if (ret != 0)
RTE_LOG(ERR, EAL,
"Cannot set name for lcore thread\n");
}
/*
* Launch a dummy function on all slave lcores, so that master lcore
* knows they are all ready when this function returns.
*/
rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
rte_eal_mp_wait_lcore();
//rte_eal_init[eal.c] ------> rte_eal_pci_probe[eal_commmon_pci.c] ----> 遍历pci_device_list,循环调用pci_probe_all_drivers[eal_commmon_pci.c]
// -----> 遍历pci_driver_list,循环调用rte_eal_pci_probe_one_driver[eal_commmon_pci.c] ----> 循环查找驱动列表,找到对应PCI设备的驱动
// 通过比较4个参数来确认匹配(vendor_id、device_id、subsystem_vendor_id、subsystem_device_id),并判断驱动名称是否和dpdk自己实现的驱动名称相同
// ----> 调用devinit函数进行初始化为rte_eth_dev_init[rte_ethdev.c] ----->其中会调用驱动eth_driver的eth_dev_init函数,此函数在驱动文件中
if (rte_eal_pci_probe())
rte_panic("Cannot probe PCI\n");
rte_eal_mcfg_complete();
return fctret;
}