eal: add support for shared object drivers
authorDamien Millescamps <damien.millescamps@6wind.com>
Wed, 12 Jun 2013 05:51:27 +0000 (07:51 +0200)
committerDavid Marchand <david.marchand@6wind.com>
Wed, 26 Feb 2014 10:01:13 +0000 (11:01 +0100)
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>
lib/librte_eal/linuxapp/eal/eal.c
mk/exec-env/linuxapp/rte.vars.mk

index dde9126..9ff2a44 100644 (file)
@@ -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 <syslog.h>
 #include <getopt.h>
 #include <sys/file.h>
+#include <fcntl.h>
+#include <dlfcn.h>
 #include <stddef.h>
 #include <errno.h>
 #include <limits.h>
 
 /* 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 <domain:bus:devid.func>: 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) {
 
                /*
index 995c163..68edaab 100644 (file)
@@ -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