DPDK初始化

Posted mysky007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DPDK初始化相关的知识,希望对你有一定的参考价值。

一. DPDK源码版本: DPDK19.02    http://core.dpdk.org/download/

二. DPDK 初始化部分

  1.初始化EAL环境,rte_eal_init();

  2.解析参数,因为DPDK的参数在EAL初始化时就进行了解析,所以,这里主要解析的是我们自己的参数,可以使用getopt_long函数。

  3.初始化内存池等,这里要注意放在接口的初始化之前,为接收数据包做准备。

  4.初始化接口

  5.启动所有核上的线程。rte_eal_mp_remote_launch()

三. 下面详细讲解初始化作用过程:

2.1 EAL初始化

1)EAL功能作用:

• Intel® DPDK loading and launching
• Support for multi-process and multi-thread execution types
• Core affinity/assignment procedures
• System memory allocation/de-allocation
• Atomic/lock operations
• Time reference
• PCI bus access
• Trace and debug functions
• CPU feature identification
• Interrupt handling
• Alarm operations

ref: http://doc.dpdk.org/guides/prog_guide/   (详细可参考文章)

2) 初始化程序: 源文件eal.c

技术图片
  1 /* Launch threads, called at application init(). */
  2 int
  3 rte_eal_init(int argc, char **argv)
  4 
  5     int i, fctret, ret;
  6     pthread_t thread_id;
  7     static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
  8     const char *p;
  9     static char logid[PATH_MAX];
 10     char cpuset[RTE_CPU_AFFINITY_STR_LEN];
 11     char thread_name[RTE_MAX_THREAD_NAME_LEN];
 12 
 13     /* checks if the machine is adequate */
 14     if (!rte_cpu_is_supported()) 
 15         rte_eal_init_alert("unsupported cpu type.");
 16         rte_errno = ENOTSUP;
 17         return -1;
 18     
 19 
 20     if (!rte_atomic32_test_and_set(&run_once)) 
 21         rte_eal_init_alert("already called initialization.");
 22         rte_errno = EALREADY;
 23         return -1;
 24     
 25 
 26     p = strrchr(argv[0], /);
 27     strlcpy(logid, p ? p + 1 : argv[0], sizeof(logid));
 28     thread_id = pthread_self();
 29 
 30     eal_reset_internal_config(&internal_config);
 31 
 32     /* set log level as early as possible */
 33     eal_log_level_parse(argc, argv);
 34 
 35     if (rte_eal_cpu_init() < 0) 
 36         rte_eal_init_alert("Cannot detect lcores.");
 37         rte_errno = ENOTSUP;
 38         return -1;
 39     
 40 
 41     fctret = eal_parse_args(argc, argv);
 42     if (fctret < 0) 
 43         rte_eal_init_alert("Invalid ‘command line‘ arguments.");
 44         rte_errno = EINVAL;
 45         rte_atomic32_clear(&run_once);
 46         return -1;
 47     
 48 
 49     if (eal_plugins_init() < 0) 
 50         rte_eal_init_alert("Cannot init plugins");
 51         rte_errno = EINVAL;
 52         rte_atomic32_clear(&run_once);
 53         return -1;
 54     
 55 
 56     if (eal_option_device_parse()) 
 57         rte_errno = ENODEV;
 58         rte_atomic32_clear(&run_once);
 59         return -1;
 60     
 61 
 62     rte_config_init();
 63 
 64     if (rte_eal_intr_init() < 0) 
 65         rte_eal_init_alert("Cannot init interrupt-handling thread");
 66         return -1;
 67     
 68 
 69     /* Put mp channel init before bus scan so that we can init the vdev
 70      * bus through mp channel in the secondary process before the bus scan.
 71      */
 72     if (rte_mp_channel_init() < 0) 
 73         rte_eal_init_alert("failed to init mp channel");
 74         if (rte_eal_process_type() == RTE_PROC_PRIMARY) 
 75             rte_errno = EFAULT;
 76             return -1;
 77         
 78     
 79 
 80     /* register multi-process action callbacks for hotplug */
 81     if (rte_mp_dev_hotplug_init() < 0) 
 82         rte_eal_init_alert("failed to register mp callback for hotplug");
 83         return -1;
 84     
 85 
 86     if (rte_bus_scan()) 
 87         rte_eal_init_alert("Cannot scan the buses for devices");
 88         rte_errno = ENODEV;
 89         rte_atomic32_clear(&run_once);
 90         return -1;
 91     
 92 
 93     /* if no EAL option "--iova-mode=<pa|va>", use bus IOVA scheme */
 94     if (internal_config.iova_mode == RTE_IOVA_DC) 
 95         /* autodetect the IOVA mapping mode (default is RTE_IOVA_PA) */
 96         rte_eal_get_configuration()->iova_mode =
 97             rte_bus_get_iommu_class();
 98 
 99         /* Workaround for KNI which requires physical address to work */
100         if (rte_eal_get_configuration()->iova_mode == RTE_IOVA_VA &&
101                 rte_eal_check_module("rte_kni") == 1) 
102             rte_eal_get_configuration()->iova_mode = RTE_IOVA_PA;
103             RTE_LOG(WARNING, EAL,
104                 "Some devices want IOVA as VA but PA will be used because.. "
105                 "KNI module inserted\n");
106         
107      else 
108         rte_eal_get_configuration()->iova_mode =
109             internal_config.iova_mode;
110     
111 
112     if (internal_config.no_hugetlbfs == 0) 
113         /* rte_config isn‘t initialized yet */
114         ret = internal_config.process_type == RTE_PROC_PRIMARY ?
115                 eal_hugepage_info_init() :
116                 eal_hugepage_info_read();
117         if (ret < 0) 
118             rte_eal_init_alert("Cannot get hugepage information.");
119             rte_errno = EACCES;
120             rte_atomic32_clear(&run_once);
121             return -1;
122         
123     
124 
125     if (internal_config.memory == 0 && internal_config.force_sockets == 0) 
126         if (internal_config.no_hugetlbfs)
127             internal_config.memory = MEMSIZE_IF_NO_HUGE_PAGE;
128     
129 
130     if (internal_config.vmware_tsc_map == 1) 
131 #ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT
132         rte_cycles_vmware_tsc_map = 1;
133         RTE_LOG (DEBUG, EAL, "Using VMWARE TSC MAP, "
134                 "you must have monitor_control.pseudo_perfctr = TRUE\n");
135 #else
136         RTE_LOG (WARNING, EAL, "Ignoring --vmware-tsc-map because "
137                 "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set\n");
138 #endif
139     
140 
141     rte_srand(rte_rdtsc());
142 
143     if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0) 
144         rte_eal_init_alert("Cannot init logging.");
145         rte_errno = ENOMEM;
146         rte_atomic32_clear(&run_once);
147         return -1;
148     
149 
150 #ifdef VFIO_PRESENT
151     if (rte_eal_vfio_setup() < 0) 
152         rte_eal_init_alert("Cannot init VFIO");
153         rte_errno = EAGAIN;
154         rte_atomic32_clear(&run_once);
155         return -1;
156     
157 #endif
158     /* in secondary processes, memory init may allocate additional fbarrays
159      * not present in primary processes, so to avoid any potential issues,
160      * initialize memzones first.
161      */
162     if (rte_eal_memzone_init() < 0) 
163         rte_eal_init_alert("Cannot init memzone");
164         rte_errno = ENODEV;
165         return -1;
166     
167 
168     if (rte_eal_memory_init() < 0) 
169         rte_eal_init_alert("Cannot init memory");
170         rte_errno = ENOMEM;
171         return -1;
172     
173 
174     /* the directories are locked during eal_hugepage_info_init */
175     eal_hugedirs_unlock();
176 
177     if (rte_eal_malloc_heap_init() < 0) 
178         rte_eal_init_alert("Cannot init malloc heap");
179         rte_errno = ENODEV;
180         return -1;
181     
182 
183     if (rte_eal_tailqs_init() < 0) 
184         rte_eal_init_alert("Cannot init tail queues for objects");
185         rte_errno = EFAULT;
186         return -1;
187     
188 
189     if (rte_eal_alarm_init() < 0) 
190         rte_eal_init_alert("Cannot init interrupt-handling thread");
191         /* rte_eal_alarm_init sets rte_errno on failure. */
192         return -1;
193     
194 
195     if (rte_eal_timer_init() < 0) 
196         rte_eal_init_alert("Cannot init HPET or TSC timers");
197         rte_errno = ENOTSUP;
198         return -1;
199     
200 
201     eal_check_mem_on_local_socket();
202 
203     eal_thread_init_master(rte_config.master_lcore);
204 
205     ret = eal_thread_dump_affinity(cpuset, sizeof(cpuset));
206 
207     RTE_LOG(DEBUG, EAL, "Master lcore %u is ready (tid=%zx;cpuset=[%s%s])\n",
208         rte_config.master_lcore, (uintptr_t)thread_id, cpuset,
209         ret == 0 ? "" : "...");
210 
211     RTE_LCORE_FOREACH_SLAVE(i) 
212 
213         /*
214          * create communication pipes between master thread
215          * and children
216          */
217         if (pipe(lcore_config[i].pipe_master2slave) < 0)
218             rte_panic("Cannot create pipe\n");
219         if (pipe(lcore_config[i].pipe_slave2master) < 0)
220             rte_panic("Cannot create pipe\n");
221 
222         lcore_config[i].state = WAIT;
223 
224         /* create a thread for each lcore */
225         ret = pthread_create(&lcore_config[i].thread_id, NULL,
226                      eal_thread_loop, NULL);
227         if (ret != 0)
228             rte_panic("Cannot create thread\n");
229 
230         /* Set thread_name for aid in debugging. */
231         snprintf(thread_name, sizeof(thread_name),
232             "lcore-slave-%d", i);
233         ret = rte_thread_setname(lcore_config[i].thread_id,
234                         thread_name);
235         if (ret != 0)
236             RTE_LOG(DEBUG, EAL,
237                 "Cannot set name for lcore thread\n");
238     
239 
240     /*
241      * Launch a dummy function on all slave lcores, so that master lcore
242      * knows they are all ready when this function returns.
243      */
244     rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
245     rte_eal_mp_wait_lcore();
246 
247     /* initialize services so vdevs register service during bus_probe. */
248     ret = rte_service_init();
249     if (ret) 
250         rte_eal_init_alert("rte_service_init() failed");
251         rte_errno = ENOEXEC;
252         return -1;
253     
254 
255     /* Probe all the buses and devices/drivers on them */
256     if (rte_bus_probe()) 
257         rte_eal_init_alert("Cannot probe devices");
258         rte_errno = ENOTSUP;
259         return -1;
260     
261 
262 #ifdef VFIO_PRESENT
263     /* Register mp action after probe() so that we got enough info */
264     if (rte_vfio_is_enabled("vfio") && vfio_mp_sync_setup() < 0)
265         return -1;
266 #endif
267 
268     /* initialize default service/lcore mappings and start running. Ignore
269      * -ENOTSUP, as it indicates no service coremask passed to EAL.
270      */
271     ret = rte_service_start_with_defaults();
272     if (ret < 0 && ret != -ENOTSUP) 
273         rte_errno = ENOEXEC;
274         return -1;
275     
276 
277     /*
278      * Clean up unused files in runtime directory. We do this at the end of
279      * init and not at the beginning because we want to clean stuff up
280      * whether we are primary or secondary process, but we cannot remove
281      * primary process‘ files because secondary should be able to run even
282      * if primary process is dead.
283      *
284      * In no_shconf mode, no runtime directory is created in the first
285      * place, so no cleanup needed.
286      */
287     if (!internal_config.no_shconf && eal_clean_runtime_dir() < 0) 
288         rte_eal_init_alert("Cannot clear runtime directory\n");
289         return -1;
290     
291 
292     rte_eal_mcfg_complete();
293 
294     /* Call each registered callback, if enabled */
295     rte_option_init();
296 
297     return fctret;
298 
View Code

 

以上是关于DPDK初始化的主要内容,如果未能解决你的问题,请参考以下文章

dpdk源码分析:交互式命令行的实现 初始化与退出

dpdk源码分析:交互式命令行的实现 初始化与退出

dpdk源码分析:交互式命令行的实现 初始化与退出

[转]dpdk内存管理

dpdk-pktgen简单使用

dpdk和socket有何区别?两者的作用是不是有重叠。