eal: add support for shared object drivers
Add an option to specify libraries to be loaded before probing the PCI. For instance, testpmd -d librte_pmd_xxx.so can be used to enable xxx driver support on testpmd without any recompilation of testpmd. Plugins are loaded before creating threads because we want the threads to inherit any property that could be set while loading a plugin, such as iopl(). Signed-off-by: Damien Millescamps <damien.millescamps@6wind.com> Signed-off-by: Jean-Mickael Guerin <jean-mickael.guerin@6wind.com> Signed-off-by: Thomas Monjalon <thomas.monjalon@6wind.com>
This commit is contained in:
parent
527f2cb8a3
commit
f9a08f6502
@ -2,6 +2,7 @@
|
|||||||
* BSD LICENSE
|
* BSD LICENSE
|
||||||
*
|
*
|
||||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||||
|
* Copyright(c) 2012-2013 6WIND S.A.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -41,6 +42,8 @@
|
|||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
@ -116,6 +119,21 @@
|
|||||||
|
|
||||||
/* Allow the application to print its usage message too if set */
|
/* Allow the application to print its usage message too if set */
|
||||||
static rte_usage_hook_t rte_application_usage_hook = NULL;
|
static rte_usage_hook_t rte_application_usage_hook = NULL;
|
||||||
|
|
||||||
|
TAILQ_HEAD(shared_driver_list, shared_driver);
|
||||||
|
|
||||||
|
/* Definition for shared object drivers. */
|
||||||
|
struct shared_driver {
|
||||||
|
TAILQ_ENTRY(shared_driver) next;
|
||||||
|
|
||||||
|
char name[PATH_MAX];
|
||||||
|
void* lib_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* List of external loadable drivers */
|
||||||
|
static struct shared_driver_list solib_list =
|
||||||
|
TAILQ_HEAD_INITIALIZER(solib_list);
|
||||||
|
|
||||||
/* early configuration structure, when memory config is not mmapped */
|
/* early configuration structure, when memory config is not mmapped */
|
||||||
static struct rte_mem_config early_mem_config;
|
static struct rte_mem_config early_mem_config;
|
||||||
|
|
||||||
@ -329,6 +347,7 @@ eal_usage(const char *prgname)
|
|||||||
" -c COREMASK : A hexadecimal bitmask of cores to run on\n"
|
" -c COREMASK : A hexadecimal bitmask of cores to run on\n"
|
||||||
" -n NUM : Number of memory channels\n"
|
" -n NUM : Number of memory channels\n"
|
||||||
" -v : Display version information on startup\n"
|
" -v : Display version information on startup\n"
|
||||||
|
" -d LIB.so : add driver (can be used multiple times)\n"
|
||||||
" -b <domain:bus:devid.func>: to prevent EAL from using specified "
|
" -b <domain:bus:devid.func>: to prevent EAL from using specified "
|
||||||
"PCI device\n"
|
"PCI device\n"
|
||||||
" (multiple -b options are allowed)\n"
|
" (multiple -b options are allowed)\n"
|
||||||
@ -631,6 +650,7 @@ eal_parse_args(int argc, char **argv)
|
|||||||
{OPT_XEN_DOM0, 0, 0, 0},
|
{OPT_XEN_DOM0, 0, 0, 0},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
struct shared_driver *solib;
|
||||||
|
|
||||||
argvopt = argv;
|
argvopt = argv;
|
||||||
|
|
||||||
@ -658,7 +678,7 @@ eal_parse_args(int argc, char **argv)
|
|||||||
internal_config.vmware_tsc_map = 0;
|
internal_config.vmware_tsc_map = 0;
|
||||||
internal_config.base_virtaddr = 0;
|
internal_config.base_virtaddr = 0;
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argvopt, "b:c:m:n:r:v",
|
while ((opt = getopt_long(argc, argvopt, "b:c:d:m:n:r:v",
|
||||||
lgopts, &option_index)) != EOF) {
|
lgopts, &option_index)) != EOF) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@ -679,6 +699,18 @@ eal_parse_args(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
coremask_ok = 1;
|
coremask_ok = 1;
|
||||||
break;
|
break;
|
||||||
|
/* force loading of external driver */
|
||||||
|
case 'd':
|
||||||
|
solib = malloc(sizeof(*solib));
|
||||||
|
if (solib == NULL) {
|
||||||
|
RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset(solib, 0, sizeof(*solib));
|
||||||
|
strncpy(solib->name, optarg, PATH_MAX-1);
|
||||||
|
solib->name[PATH_MAX-1] = 0;
|
||||||
|
TAILQ_INSERT_TAIL(&solib_list, solib, next);
|
||||||
|
break;
|
||||||
/* size of memory */
|
/* size of memory */
|
||||||
case 'm':
|
case 'm':
|
||||||
internal_config.memory = atoi(optarg);
|
internal_config.memory = atoi(optarg);
|
||||||
@ -908,6 +940,7 @@ rte_eal_init(int argc, char **argv)
|
|||||||
int i, fctret, ret;
|
int i, fctret, ret;
|
||||||
pthread_t thread_id;
|
pthread_t thread_id;
|
||||||
static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
|
static rte_atomic32_t run_once = RTE_ATOMIC32_INIT(0);
|
||||||
|
struct shared_driver *solib = NULL;
|
||||||
|
|
||||||
if (!rte_atomic32_test_and_set(&run_once))
|
if (!rte_atomic32_test_and_set(&run_once))
|
||||||
return -1;
|
return -1;
|
||||||
@ -992,9 +1025,6 @@ rte_eal_init(int argc, char **argv)
|
|||||||
if (rte_eal_timer_init() < 0)
|
if (rte_eal_timer_init() < 0)
|
||||||
rte_panic("Cannot init HPET or TSC timers\n");
|
rte_panic("Cannot init HPET or TSC timers\n");
|
||||||
|
|
||||||
RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
|
|
||||||
rte_config.master_lcore, (int)thread_id);
|
|
||||||
|
|
||||||
eal_check_mem_on_local_socket();
|
eal_check_mem_on_local_socket();
|
||||||
|
|
||||||
rte_eal_mcfg_complete();
|
rte_eal_mcfg_complete();
|
||||||
@ -1002,6 +1032,21 @@ rte_eal_init(int argc, char **argv)
|
|||||||
if (rte_eal_non_pci_ethdev_init() < 0)
|
if (rte_eal_non_pci_ethdev_init() < 0)
|
||||||
rte_panic("Cannot init non-PCI eth_devs\n");
|
rte_panic("Cannot init non-PCI eth_devs\n");
|
||||||
|
|
||||||
|
TAILQ_FOREACH(solib, &solib_list, next) {
|
||||||
|
solib->lib_handle = dlopen(solib->name, RTLD_NOW);
|
||||||
|
if ((solib->lib_handle == NULL) && (solib->name[0] != '/')) {
|
||||||
|
/* relative path: try again with "./" prefix */
|
||||||
|
char sopath[PATH_MAX];
|
||||||
|
snprintf(sopath, sizeof(sopath), "./%s", solib->name);
|
||||||
|
solib->lib_handle = dlopen(sopath, RTLD_NOW);
|
||||||
|
}
|
||||||
|
if (solib->lib_handle == NULL)
|
||||||
|
RTE_LOG(WARNING, EAL, "%s\n", dlerror());
|
||||||
|
}
|
||||||
|
|
||||||
|
RTE_LOG(DEBUG, EAL, "Master core %u is ready (tid=%x)\n",
|
||||||
|
rte_config.master_lcore, (int)thread_id);
|
||||||
|
|
||||||
RTE_LCORE_FOREACH_SLAVE(i) {
|
RTE_LCORE_FOREACH_SLAVE(i) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -56,4 +56,9 @@ endif
|
|||||||
# force applications to link with gcc/icc instead of using ld
|
# force applications to link with gcc/icc instead of using ld
|
||||||
LINK_USING_CC := 1
|
LINK_USING_CC := 1
|
||||||
|
|
||||||
export EXECENV_CFLAGS EXECENV_LDFLAGS EXECENV_ASFLAGS
|
# For shared libraries
|
||||||
|
EXECENV_LDFLAGS += -export-dynamic
|
||||||
|
# Add library to the group to resolve symbols
|
||||||
|
EXECENV_LDLIBS += -ldl
|
||||||
|
|
||||||
|
export EXECENV_CFLAGS EXECENV_LDFLAGS EXECENV_ASFLAGS EXECENV_LDLIBS
|
||||||
|
Loading…
Reference in New Issue
Block a user