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
以上是关于DPDK初始化的主要内容,如果未能解决你的问题,请参考以下文章