From f9a08f650211977b48d8e982697a4c789e5b2ab3 Mon Sep 17 00:00:00 2001 From: Damien Millescamps Date: Wed, 12 Jun 2013 07:51:27 +0200 Subject: [PATCH] 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 Signed-off-by: Jean-Mickael Guerin Signed-off-by: Thomas Monjalon --- lib/librte_eal/linuxapp/eal/eal.c | 53 ++++++++++++++++++++++++++++--- mk/exec-env/linuxapp/rte.vars.mk | 7 +++- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c index dde9126e6a..9ff2a443e9 100644 --- a/lib/librte_eal/linuxapp/eal/eal.c +++ b/lib/librte_eal/linuxapp/eal/eal.c @@ -2,6 +2,7 @@ * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012-2013 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,6 +42,8 @@ #include #include #include +#include +#include #include #include #include @@ -116,6 +119,21 @@ /* Allow the application to print its usage message too if set */ 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 */ 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" " -n NUM : Number of memory channels\n" " -v : Display version information on startup\n" + " -d LIB.so : add driver (can be used multiple times)\n" " -b : to prevent EAL from using specified " "PCI device\n" " (multiple -b options are allowed)\n" @@ -631,6 +650,7 @@ eal_parse_args(int argc, char **argv) {OPT_XEN_DOM0, 0, 0, 0}, {0, 0, 0, 0} }; + struct shared_driver *solib; argvopt = argv; @@ -658,7 +678,7 @@ eal_parse_args(int argc, char **argv) internal_config.vmware_tsc_map = 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) { switch (opt) { @@ -679,6 +699,18 @@ eal_parse_args(int argc, char **argv) } coremask_ok = 1; 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 */ case 'm': internal_config.memory = atoi(optarg); @@ -908,6 +940,7 @@ 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); + struct shared_driver *solib = NULL; if (!rte_atomic32_test_and_set(&run_once)) return -1; @@ -992,9 +1025,6 @@ rte_eal_init(int argc, char **argv) if (rte_eal_timer_init() < 0) 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(); rte_eal_mcfg_complete(); @@ -1002,6 +1032,21 @@ rte_eal_init(int argc, char **argv) if (rte_eal_non_pci_ethdev_init() < 0) 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) { /* diff --git a/mk/exec-env/linuxapp/rte.vars.mk b/mk/exec-env/linuxapp/rte.vars.mk index 995c163728..68edaabb8c 100644 --- a/mk/exec-env/linuxapp/rte.vars.mk +++ b/mk/exec-env/linuxapp/rte.vars.mk @@ -56,4 +56,9 @@ endif # force applications to link with gcc/icc instead of using ld 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 -- 2.20.1