summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Wiles <keith.wiles@intel.com>2019-03-18 12:05:52 -0500
committerKeith Wiles <keith.wiles@intel.com>2019-03-18 12:05:52 -0500
commit0c39019020c8a54b7e599d1a9111a087417fc246 (patch)
treeb22e2584695205f46c6462ee093bff336a0f0e05
parentf6e9e335a3ca40464eccfba13a5cd146eb1a39c0 (diff)
downloadpktgen-dpdk-0c39019020c8a54b7e599d1a9111a087417fc246.zip
pktgen-dpdk-0c39019020c8a54b7e599d1a9111a087417fc246.tar.gz
pktgen-dpdk-0c39019020c8a54b7e599d1a9111a087417fc246.tar.xz
Cleanup build, add plugin support and meson build not working
Signed-off-by: Keith Wiles <keith.wiles@intel.com>
-rw-r--r--app/Makefile9
-rw-r--r--app/cli-functions.c60
-rw-r--r--app/meson.build5
-rw-r--r--app/pktgen-port-cfg.c4
-rw-r--r--cfg/two-ports-shared.cfg71
-rw-r--r--cfg/two-ports.cfg3
-rw-r--r--lib/Makefile3
-rw-r--r--lib/lua/Makefile1
-rw-r--r--lib/lua/meson.build2
-rw-r--r--lib/meson.build5
-rw-r--r--lib/plugin/Makefile26
-rw-r--r--lib/plugin/meson.build8
-rw-r--r--lib/plugin/plugin.c391
-rw-r--r--lib/plugin/plugin.h256
-rw-r--r--lib/plugin/plugin_version.map6
-rw-r--r--lib/utils/meson.build2
-rw-r--r--lib/vec/meson.build2
-rw-r--r--meson.build8
-rwxr-xr-xtools/run.py22
19 files changed, 866 insertions, 18 deletions
diff --git a/app/Makefile b/app/Makefile
index 20bc66c..5c70f63 100644
--- a/app/Makefile
+++ b/app/Makefile
@@ -44,6 +44,7 @@ CLI_INC := -I$(RTE_SRCDIR)/../lib/cli
UTILS_INC := -I$(RTE_SRCDIR)/../lib/utils
VEC_INC := -I$(RTE_SRCDIR)/../lib/vec
GUI_INC := -I$(RTE_SRCDIR)/../gui/gui
+PLUGIN_INC := -I$(RTE_SRCDIR)/../lib/plugin
COMMON_LIB := -L$(RTE_SRCDIR)/../lib/common/$(RTE_TARGET)/lib
LUA_LIB := -L$(RTE_SRCDIR)/../lib/lua/$(RTE_TARGET)/lib
@@ -51,6 +52,7 @@ CLI_LIB := -L$(RTE_SRCDIR)/../lib/cli/$(RTE_TARGET)/lib
UTILS_LIB := -L$(RTE_SRCDIR)/../lib/utils/$(RTE_TARGET)/lib
VEC_LIB := -L$(RTE_SRCDIR)/../lib/vec/$(RTE_TARGET)/lib
GUI_LIB := -L$(RTE_SRCDIR)/../gui/$(RTE_TARGET)/lib
+PLUGIN_LIB := -L$(RTE_SRCDIR)/../lib/plugin/$(RTE_TARGET)/lib
COMMON_LD := -lcommon
LUA_LD := -lpktgen_lua
@@ -58,11 +60,12 @@ CLI_LD := -lcli
UTILS_LD := -lutils
VEC_LD := -lvec
GUI_LD := -lgui
+PLUGIN_LD := -lplugin
# default vars to using common information
-__CFLAGS := $(COMMON_INC)
-__LIBS := $(COMMON_LIB)
-__LDFLAGS := $(COMMON_LD)
+__CFLAGS := $(COMMON_INC) $(PLUGIN_INC)
+__LIBS := $(COMMON_LIB) $(PLUGIN_LIB)
+__LDFLAGS := $(COMMON_LD) $(PLUGIN_LD)
ifeq ($(CONFIG_RTE_LIBRTE_LUA),y)
else
diff --git a/app/cli-functions.c b/app/cli-functions.c
index 74c9fb2..21e5231 100644
--- a/app/cli-functions.c
+++ b/app/cli-functions.c
@@ -31,6 +31,7 @@
#include <cli.h>
#include <cli_map.h>
+#include <plugin.h>
#include "copyright_info.h"
#include "pktgen-cmds.h"
@@ -1521,6 +1522,63 @@ page_cmd(int argc, char **argv)
return 0;
}
+static struct cli_map plugin_map[] = {
+ { 10, "plugin" },
+ { 20, "plugin load %s" },
+ { 21, "plugin load %s %s" },
+ { 30, "plugin %|rm|del|delete %s" },
+ { -1, NULL }
+};
+
+static const char *plugin_help[] = {
+ "",
+ "plugin - Show the plugins currently installed",
+ "plugin load <filename> - Load a plugin file",
+ "plugin load <filename> <path> - Load a plugin file at path",
+ "plugin rm|delete <plugin> - Remove or delete a plugin",
+ CLI_HELP_PAUSE,
+ NULL
+};
+
+static int
+plugin_cmd(int argc, char **argv)
+{
+ struct cli_map *m;
+ int inst;
+
+ m = cli_mapping(plugin_map, argc, argv);
+ if (!m)
+ return cli_cmd_error("Plugin invalid command", "Plugin", argc, argv);
+
+ switch(m->index) {
+ case 10:
+ plugin_dump(stdout);
+ break;
+ case 20:
+ case 21:
+ if ((inst = plugin_create(argv[2], argv[3])) < 0) {
+ printf("Plugin not loaded %s, %s\n", argv[2], argv[3]);
+ return -1;
+ }
+
+ if (plugin_start(inst, NULL) , 0) {
+ plugin_destroy(inst);
+ return -1;
+ }
+ break;
+ case 30:
+ inst = plugin_find_by_name(argv[2]);
+ if (inst < 0)
+ return -1;
+ plugin_stop(inst);
+ plugin_destroy(inst);
+ break;
+ default:
+ return cli_cmd_error("Plugin invalid command", "Plugin", argc, argv);
+ }
+ return 0;
+}
+
/**********************************************************/
/**********************************************************/
/****** CONTEXT (list of instruction) */
@@ -1565,6 +1623,7 @@ static struct cli_tree default_tree[] = {
c_cmd("pcap", pcap_cmd, "pcap commands"),
c_cmd("set", set_cmd, "set a number of options"),
c_cmd("dbg", dbg_cmd, "debug commands"),
+ c_cmd("plugin", plugin_cmd, "Plugin a shared object file"),
c_alias("on", "enable screen", "Enable screen updates"),
c_alias("off", "disable screen", "Disable screen updates"),
@@ -1594,6 +1653,7 @@ init_tree(void)
cli_help_add("Debug", dbg_map, dbg_help);
cli_help_add("Misc", misc_map, misc_help);
cli_help_add("Theme", theme_map, theme_help);
+ cli_help_add("Plugin", plugin_map, plugin_help);
cli_help_add("Status", NULL, status_help);
/* Make sure the pktgen commands are executable in search path */
diff --git a/app/meson.build b/app/meson.build
index 0e8e441..8c7247e 100644
--- a/app/meson.build
+++ b/app/meson.build
@@ -9,10 +9,9 @@ sources = files(
)
#TODO fixme - assumes previously build lua using make
-lua_dir = '../lib/lua/src/x86_64-native-linuxapp-gcc'
+lua_dir = '../lib/lua/x86_64-native-linuxapp-gcc'
lua_inc = include_directories(join_paths(lua_dir, 'include'))
-lua = declare_dependency(include_directories: lua_inc,
- link_args: ['-L' + lua_dir, '-lrte_lua'])
+lua = declare_dependency(include_directories: lua_inc, link_args: ['-L' + lua_dir, '-lrte_lua'])
pktgen = executable('dpdk-pktgen',
sources,
diff --git a/app/pktgen-port-cfg.c b/app/pktgen-port-cfg.c
index 5321731..fb2873e 100644
--- a/app/pktgen-port-cfg.c
+++ b/app/pktgen-port-cfg.c
@@ -121,7 +121,7 @@ pktgen_mbuf_pool_create(const char *type, uint8_t pid, uint8_t queue_id,
if (mp == NULL)
pktgen_log_panic(
"Cannot create mbuf pool (%s) port %d, queue %d, nb_mbufs %d, socket_id %d: %s",
- name, pid, queue_id, nb_mbufs, socket_id, rte_strerror(errno));
+ name, pid, queue_id, nb_mbufs, socket_id, rte_strerror(rte_errno));
return mp;
}
@@ -248,7 +248,7 @@ pktgen_config_ports(void)
if ( (ret = rte_eth_dev_configure(pid, rt.rx, rt.tx, &default_port_conf)) < 0)
pktgen_log_panic(
"Cannot configure device: port=%d, Num queues %d,%d (%d)%s",
- pid, rt.rx, rt.tx, errno, rte_strerror(-ret));
+ pid, rt.rx, rt.tx, -ret, rte_strerror(-ret));
pkt = &info->seq_pkt[SINGLE_PKT];
diff --git a/cfg/two-ports-shared.cfg b/cfg/two-ports-shared.cfg
new file mode 100644
index 0000000..8e41bb1
--- /dev/null
+++ b/cfg/two-ports-shared.cfg
@@ -0,0 +1,71 @@
+description = 'A Pktgen default simple configuration'
+
+# Setup configuration
+setup = {
+ 'exec': (
+ 'sudo', '-E'
+ ),
+
+ 'devices': (
+ '81:00.0', '81:00.1', '81:00.2', '81:00.3',
+ '83:00.0', '83:00.1', '83:00.2', '83:00.3'
+ ),
+ # UIO module type, igb_uio, vfio-pci or uio_pci_generic
+ 'uio': 'vfio-pci'
+ }
+
+# Run command and options
+run = {
+ 'exec': (
+ 'sudo', '-E'
+ ),
+
+ 'ld_path': (
+ '%(sdk)s/%(target)s/lib',
+ '/work/home/rkwiles/projects/intel/pmdk/build/lib',
+ './lib/common/%(target)s/lib',
+ './lib/utils/%(target)s/lib',
+ './lib/cli/%(target)s/lib',
+ './lib/plugin/%(target)s/lib',
+ './lib/vec/%(target)s/lib',
+ './lib/lua/%(target)s/lib'
+ ),
+
+ # Application name and use app_path to help locate the app
+ 'app_name': 'pktgen',
+
+ # using (sdk) or (target) for specific variables
+ # add (app_name) of the application
+ # Each path is tested for the application
+ 'app_path': (
+ './app/%(target)s/%(app_name)s',
+ '%(sdk)s/%(target)s/app/%(app_name)s',
+ ),
+
+ 'cores': '14,15-18',
+ 'nrank': '4',
+ 'proc': 'primary',
+ 'log': '7',
+ 'prefix': 'pg',
+ 'plugin': (
+ '/tmp/sofiles/librte_mempool_ring.so.1.1',
+ '/tmp/sofiles/librte_pmd_i40e.so.2.1'
+ ),
+
+ 'blacklist': (
+ '81:00.0', '81:00.1', '81:00.2', '81:00.3',
+ #'83:00.0', '83:00.1', '83:00.2', '83:00.3',
+ '83:00.2', '83:00.3'
+ ),
+
+ 'opts': (
+ '-T',
+ '-P',
+ ),
+ 'map': (
+ '[15:16].0',
+ '[17:18].1'
+ ),
+
+ 'theme': 'themes/black-yellow.theme'
+ }
diff --git a/cfg/two-ports.cfg b/cfg/two-ports.cfg
index 21016a7..92b5890 100644
--- a/cfg/two-ports.cfg
+++ b/cfg/two-ports.cfg
@@ -20,6 +20,9 @@ run = {
'sudo', '-E'
),
+ 'ld_path': (
+ ),
+
# Application name and use app_path to help locate the app
'app_name': 'pktgen',
diff --git a/lib/Makefile b/lib/Makefile
index 1d9f621..b645234 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -6,6 +6,9 @@ include $(RTE_SDK)/mk/rte.vars.mk
DIRS-y += common
DEPDIRS-common =
+DIRS-y += plugin
+DEPDIRS-plugin = common
+
ifeq ($(CONFIG_RTE_LIBRTE_UTILS),y)
else
DIRS-y += utils
diff --git a/lib/lua/Makefile b/lib/lua/Makefile
index 6925d72..fab51c2 100644
--- a/lib/lua/Makefile
+++ b/lib/lua/Makefile
@@ -30,6 +30,7 @@ CFLAGS += -O3 -g -DLUA_USE_LINUX -DUSE_64_BIT -DALLOW_EXPERIMENTAL_API
CFLAGS += -D_GNU_SOURCE $(WERROR_FLAGS) -I$(RTE_SRCDIR) -fno-stack-protector
LDLIBS += -lrte_eal -lrte_mempool -lrte_ethdev -lrte_mbuf -lrte_timer
+LDLIBS += -L/work/projects/intel/pktgen/lib/utils/x86_64-native-linuxapp-gcc/lib -lutils
ifeq ($(CONFIG_RTE_LIBRTE_VEC),y)
else
diff --git a/lib/lua/meson.build b/lib/lua/meson.build
index 786f7f8..ceeadfd 100644
--- a/lib/lua/meson.build
+++ b/lib/lua/meson.build
@@ -21,5 +21,5 @@ headers = files(
'rte_lua_stdio.h',
'rte_lua_utils.h',
'rte_lua_vec.h')
-deps += ['eal', 'ethdev', 'mempool']
+#deps += ['eal', 'ethdev', 'mempool']
diff --git a/lib/meson.build b/lib/meson.build
index bdf97de..9ec0305 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2019 Intel Corporation
-libraries = ['common', 'utils', 'vec', 'lua']
+libraries = ['common', 'utils', 'vec', 'plugin', 'lua']
# Set default cflags
#default_cflags = glb_default_cflags
@@ -14,6 +14,7 @@ foreach l:libraries
allow_experimental_apis = false
sources = []
headers = []
+ enabled_libs = []
includes = [global_inc]
cflags = default_cflags
objs = [] # other object files to link against, used e.g. for
@@ -30,7 +31,7 @@ foreach l:libraries
if build
enabled_libs += name
- pmdk_conf.set('PME_LIB' + name.to_upper(), 1)
+ # pmdk_conf.set('PME_LIB' + name.to_upper(), 1)
install_headers(headers)
libname = name
diff --git a/lib/plugin/Makefile b/lib/plugin/Makefile
new file mode 100644
index 0000000..fd5ddf4
--- /dev/null
+++ b/lib/plugin/Makefile
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = libplugin.a
+
+CFLAGS += -D_GNU_SOURCE
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+
+CFLAGS_plugin.o := -Wno-format-nonliteral
+
+LDLIBS += -lrte_eal -lrte_hash -ldl
+
+EXPORT_MAP := plugin_version.map
+
+LIBABIVER := 1
+
+# all source are stored in SRCS-y
+SRCS-y := plugin.c
+
+# install includes
+SYMLINK-y-include := plugin.h
+
+include $(RTE_SDK)/mk/rte.extlib.mk
diff --git a/lib/plugin/meson.build b/lib/plugin/meson.build
new file mode 100644
index 0000000..a8cca4b
--- /dev/null
+++ b/lib/plugin/meson.build
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+version = 1
+sources = files('plugin.c')
+headers = files('plugin.h')
+
+#deps +=['hash']
diff --git a/lib/plugin/plugin.c b/lib/plugin/plugin.c
new file mode 100644
index 0000000..f939b6e
--- /dev/null
+++ b/lib/plugin/plugin.c
@@ -0,0 +1,391 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <dlfcn.h>
+
+#include <rte_config.h>
+#include <rte_compat.h>
+#include <rte_rwlock.h>
+
+#ifdef RTE_ARCH_X86
+#include <rte_hash_crc.h>
+#define hash_func rte_hash_crc
+#else
+#include <rte_jhash.h>
+#define hash_func rte_jhash
+#endif
+
+#include "plugin.h"
+
+static rte_rwlock_t _plugin_rwlock = RTE_RWLOCK_INITIALIZER;
+rte_rwlock_t *plugin_rwlock = &_plugin_rwlock;
+#define RTE_PLUGIN_TAILQ_RWLOCK plugin_rwlock
+
+static TAILQ_HEAD(plugin_list, plugin) plugin_head = TAILQ_HEAD_INITIALIZER(plugin_head);
+
+static struct plugin *plugin_inst[PLUGIN_MAX_INST];
+
+static const char *plugin_fmts[] = {
+ "%s",
+ "%s.so",
+ "lib%s",
+ "lib%s.so",
+ "librte_%s.so",
+ "librte_pmd_%s.so",
+ NULL
+};
+
+struct plugin *
+plugin_get(int inst)
+{
+ if (inst < 0 || inst >= PLUGIN_MAX_INST)
+ return NULL;
+ return plugin_inst[inst]; /* This could be NULL as well */
+}
+
+static int
+plugin_add_inst(struct plugin *pin)
+{
+ int inst;
+
+ rte_rwlock_write_lock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ for(inst = 0; inst < PLUGIN_MAX_INST; inst++) {
+ if (plugin_inst[inst] == NULL) {
+ plugin_inst[inst] = pin;
+
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+ return inst;
+ }
+ }
+
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+ return -1;
+}
+
+static int
+plugin_del_inst(int inst)
+{
+ struct plugin *pin = plugin_get(inst);
+
+ if (!pin) {
+ PLUGIN_LOG(DEBUG, "Plugin pointer is NULL or info is NULL\n");
+ return -1;
+ }
+
+ /* remove the plugin from the global list */
+ rte_rwlock_write_lock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ plugin_inst[inst] = NULL;
+
+ if (rte_atomic32_dec_and_test(&pin->refcnt)) {
+ /* remove instance when refcnt becomes zero */
+ TAILQ_REMOVE(&plugin_head, pin, next);
+
+ dlclose(pin->dl);
+
+ free(pin->plugin);
+ free(pin->path);
+ free(pin);
+ }
+
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+ return 0;
+}
+
+static int
+plugin_find_inst(struct plugin *pin)
+{
+ int inst;
+
+ rte_rwlock_write_lock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ for(inst = 0; inst < PLUGIN_MAX_INST; inst++) {
+ if (plugin_inst[inst] == pin) {
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+ return inst;
+ }
+ }
+
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+ return -1;
+}
+
+/**
+ * Routine to search for and open a plugin.
+ *
+ * @param pin
+ * The plugin structure pointer.
+ * @return
+ * 0 if plugin found and loaded or -1 on not found.
+ */
+static int
+plugin_open(struct plugin *pin)
+{
+ char file[1024];
+ int i;
+
+ for(i = 0; plugin_fmts[i]; i++) {
+ char fn[64];
+
+ snprintf(fn, sizeof(fn), plugin_fmts[i], pin->plugin);
+
+ if (pin->path)
+ snprintf(file, sizeof(file), "%s/%s", pin->path, fn);
+ else
+ snprintf(file, sizeof(file), "%s", fn);
+
+ printf("Trying to load this file (%s)\n", file);
+ pin->dl = dlopen(file, RTLD_NOW | RTLD_LOCAL);
+ if (pin->dl)
+ return 0;
+ printf("dlopen: %s\n", dlerror());
+ }
+ return -1;
+}
+
+int
+plugin_get_symbol(struct plugin *pin, const char *sym, char **ret)
+{
+ char *val;
+ void *v;
+
+ if (!pin || !ret)
+ return -1;
+
+ *ret = NULL;
+ (void)dlerror(); /* Clear errors */
+
+ PLUGIN_LOG(INFO, "dlsym %p for %s:%d\n",
+ pin->dl, pin->plugin, pin->inst);
+ v = dlsym(pin->dl, sym); /* could return NULL */
+
+ val = dlerror();
+ if (val) {
+ PLUGIN_LOG(ERR, "failed to get symbol (%s)\n", val);
+ return -1;
+ }
+
+ *ret = v;
+
+ return 0;
+}
+
+int
+plugin_create(char *plugin, char *path)
+{
+ struct plugin *pin;
+ struct plugin_info *info;
+ int inst, ret;
+ char sym[64];
+
+ /* Make sure we have not already loaded this plugin */
+ inst = plugin_find_by_name(plugin);
+ if (inst >= 0) {
+ pin = plugin_get(inst);
+
+ /* Did we find a new instance of the same plugin */
+ if (pin && !strcmp(path, pin->path)) {
+ info = pin->info;
+
+ PLUGIN_LOG(DEBUG, "Plugin: '%s' - %s, version: %d.%02d.%02d-rc%d\n",
+ pin->plugin, info->desc,
+ info->major, info->minor, info->patch,
+ info->release);
+ return inst;
+ }
+ /* not the same plugin */
+ }
+
+ /* Create the plugin structure and begin loading plugin */
+ pin = malloc(sizeof(struct plugin));
+ if (!pin)
+ return -1;
+ memset(pin, 0, sizeof(struct plugin));
+ pin->inst = -1;
+
+ inst = plugin_add_inst(pin);
+ if (inst < 0) {
+ PLUGIN_LOG(ERR, "plugin_add_inst() failed for %s\n", plugin);
+ free(pin);
+ return -1;
+ }
+
+ pin->inst = inst;
+
+ /* Save these away for later comparsions */
+ pin->plugin = strdup(plugin);
+ pin->path = strdup(path);
+
+ if (plugin_open(pin)) {
+ PLUGIN_LOG(ERR, "dlopen() unable to load %s\n", pin->plugin);
+ PLUGIN_LOG(ERR, "dlerror: %s\n", dlerror());
+ goto err_exit;
+ }
+
+ /* Look for the plugin information structure */
+ snprintf(sym, sizeof(sym), "%s_plugin_info", pin->plugin);
+ ret = plugin_get_symbol(pin, sym, (char **)&info);
+ if (ret < 0) {
+ PLUGIN_LOG(ERR, "Invalid plugin %s not found\n", sym);
+ goto err_exit;
+ }
+ pin->info = info;
+
+ PLUGIN_LOG(DEBUG, "Plugin: '%s' - %s, version: %d.%02d.%02d-rc%d\n",
+ pin->plugin, info->desc,
+ info->major, info->minor, info->patch, info->release);
+
+ /* Create the CRC 32bit value using plugin name, path and info data */
+ pin->hash = hash_func(pin->plugin, strlen(pin->plugin), pin->hash);
+ pin->hash = hash_func(pin->path, strlen(pin->path), pin->hash);
+ pin->hash = hash_func(pin->info, sizeof(struct plugin_info), pin->hash);
+
+ /* add the plugin to the global list */
+ rte_rwlock_write_lock(RTE_PLUGIN_TAILQ_RWLOCK);
+ TAILQ_INSERT_TAIL(&plugin_head, pin, next);
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ return inst;
+
+err_exit:
+ PLUGIN_LOG(ERR, "Failed to create plugin %s\n", plugin);
+ plugin_del_inst(inst);
+ return -1;
+}
+
+int
+plugin_destroy(int inst)
+{
+ if (inst < 0)
+ return -1;
+ return plugin_del_inst(inst);
+}
+
+int
+plugin_start(int inst, void *arg)
+{
+ struct plugin *pin = plugin_get(inst);
+
+ if (!pin) {
+ PLUGIN_LOG(DEBUG, "Plugin pointer is NULL\n");
+ return -1;
+ }
+
+ /* if we have a entry point then call to unload plugin */
+ if (pin->info->start(inst, arg)) {
+ PLUGIN_LOG(DEBUG, "Start of %s failed\n", pin->plugin);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+plugin_stop(int inst)
+{
+ struct plugin *pin = plugin_get(inst);
+
+ if (!pin) {
+ PLUGIN_LOG(DEBUG, "Plugin pointer is NULL or info is NULL\n");
+ return -1;
+ }
+
+ /* if we have a entry point then call to unload plugin */
+ if (pin->info->stop(inst)) {
+ PLUGIN_LOG(DEBUG, "Start of %s failed\n", pin->plugin);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+plugin_find_by_name(const char *name)
+{
+ struct plugin *pin;
+
+ rte_rwlock_write_lock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ TAILQ_FOREACH(pin, &plugin_head, next) {
+ if (!strcmp(name, pin->plugin)) {
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+ return pin->inst;
+ }
+ }
+
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ return -1;
+}
+
+int
+plugin_find_by_id(uint32_t h)
+{
+ struct plugin *pin;
+
+ rte_rwlock_write_lock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ TAILQ_FOREACH(pin, &plugin_head, next) {
+ if (h == pin->hash) {
+ int inst = plugin_find_inst(pin);
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+ return inst;
+ }
+ }
+
+ rte_rwlock_write_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ return -1;
+}
+
+static void
+_plugin_dump(FILE * f, struct plugin *pin)
+{
+ if (!f)
+ f = stderr;
+
+ if (!pin) {
+ fprintf(f, "*** Plugin pointer is NULL\n");
+ return;
+ }
+
+ fprintf(f, "%08x %-16s %6d %s\n", pin->hash, pin->plugin,
+ rte_atomic32_read(&pin->refcnt),
+ (pin->info)? pin->info->desc : "---");
+}
+
+void
+plugin_dump(FILE *f)
+{
+ struct plugin *pin = NULL;
+ int cnt = 0;
+
+ rte_rwlock_read_lock(RTE_PLUGIN_TAILQ_RWLOCK);
+
+ fprintf(f, "**** Plugins ****\n");
+ fprintf(f, "%-8s %-16s %-6s %s\n", "ID", "Name", "refcnt", "Description");
+ TAILQ_FOREACH(pin, &plugin_head, next) {
+ _plugin_dump(f, pin);
+ cnt++;
+ }
+ fprintf(f, "Total plugins found: %d\n", cnt);
+
+ rte_rwlock_read_unlock(RTE_PLUGIN_TAILQ_RWLOCK);
+}
+
+int libplugin_logtype;
+
+RTE_INIT(libplugin_init_log)
+{
+ libplugin_logtype = rte_log_register("librte.plugin");
+ if (libplugin_logtype >= 0)
+ rte_log_set_level(libplugin_logtype, RTE_LOG_INFO);
+}
diff --git a/lib/plugin/plugin.h b/lib/plugin/plugin.h
new file mode 100644
index 0000000..950c71d
--- /dev/null
+++ b/lib/plugin/plugin.h
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation.
+ */
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_tailq.h>
+#include <rte_atomic.h>
+
+/**
+ * @file
+ * PLUGIN
+ *
+ * The plugin library provides the ability to add and remove modules written
+ * in C or other languages in a .so format.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PLUGIN_MAX_INST 32
+
+extern int libplugin_logtype;
+#define PLUGIN_LOG(level, fmt, args...) \
+ rte_log(RTE_LOG_ ## level, libplugin_logtype, "%s(%d): " fmt, \
+ __func__, getpid(), ## args)
+
+#define PLUGIN_MKVER(_M, _m, _p, _r) \
+ .major = _M, .minor = _m, .patch = _p, .release = _r
+
+#define PLUGIN_INFO(_n, _d, _f, _v) \
+ struct plugin_info _n ## _plugin_info = { \
+ .desc = _d, \
+ .start = _n ## _start, \
+ .stop = _n ## _stop, \
+ .pfuncs = (void *)_f, \
+ _v \
+ }
+
+struct plugin_info {
+ const char *desc; /**< Short plugin description */
+
+ int (*start)(int inst, void *arg); /**< start function optional */
+ int (*stop)(int inst); /**< stop function optional */
+ void *pfuncs; /**< plugin defined functions/info */
+
+ RTE_STD_C11
+ union {
+ uint32_t version; /* 18.04.00-rc1 == 18040001 */
+ struct {
+ uint8_t major; /**< Version of Plugin */
+ uint8_t minor;
+ uint8_t patch;
+ uint8_t release;
+ };
+ };
+};
+
+struct plugin {
+ TAILQ_ENTRY(plugin) next; /**< Next plugin pointer */
+
+ char *plugin; /**< short name of plugin <name>.do */
+ char *path; /**< path to plugin */
+ void *dl; /**< dlopen handle pointer */
+ rte_atomic32_t refcnt; /**< reference count */
+ uint32_t hash; /**< Plugin ID value */
+ int inst; /**< Plugin instance ID value */
+ struct plugin_info *info; /**< Pointer to plugin info struct */
+};
+
+/**
+ * Create a plugin instance by defining the name and path if needed.
+ *
+ * @param name
+ * The short name of the plugin minus the .so or .do, no path included.
+ * @param path
+ * The path to the plugin if not in LD_LIBRARY_PATH environment variable.
+ * @return
+ * the instance number or -1 if error
+ */
+int plugin_create(char *name, char *path);
+
+/**
+ * Destroy a given instance of a plugin
+ *
+ * @param inst
+ * The inst number for the plugin.
+ * @return
+ * < 0 is error and 0 is success.
+ */
+int plugin_destroy(int inst);
+
+/**
+ * start the plugin
+ *
+ * @param inst
+ * The instance number
+ * @param arg
+ * User defined value to the plugin on start up.
+ * @return
+ * -1 on error or 0 if OK.
+ */
+int plugin_start(int inst, void *arg);
+
+/**
+ * stop the plugin
+ *
+ * @param inst
+ * The instance number
+ * @return
+ * -1 on error or 0 if OK.
+ */
+int plugin_stop(int inst);
+
+/**
+ * Return the struct plugin pointer by instance index
+ *
+ * @param inst
+ * The instance index value
+ * @return
+ * The struct rte+plugin pointer for the instance or NULL
+ */
+struct plugin *plugin_get(int inst);
+
+/**
+ * Locate the plugin information by name.
+ *
+ * @param name
+ * The short name of the plugin to be found.
+ * @return
+ * instance number or -1 on error
+ */
+int plugin_find_by_name(const char *name);
+
+/**
+ * Locate the plugin information by ID value.
+ *
+ * @param id
+ * ID of the plugin.
+ * @return
+ * The instance number or -1 on error
+ */
+int plugin_find_by_id(uint32_t id);
+
+/**
+ * Dump out the list of plugins in the system.
+ *
+ * @param f
+ * The file pointer used to output the information, if NULL use stderr.
+ */
+void plugin_dump(FILE *f);
+
+/**
+ * return the description for the given instance id value
+ *
+ * @param pin
+ * The plugin_info pointer
+ * @return
+ * The description string or NULL if not found.
+ */
+static inline const char *
+plugin_desc(struct plugin *pin)
+{
+ if (pin && pin->info)
+ return pin->info->desc;
+
+ return NULL;
+}
+
+/**
+ * return the plugin hash ID for the given instance id value
+ *
+ * @param pin
+ * The plugin data structure pointer
+ * @param id
+ * Varable to put the id value.
+ * @return
+ * -1 on error or 0 on success
+ */
+static inline int
+plugin_get_id(struct plugin *pin, uint32_t *id)
+{
+ if (!pin || !id)
+ return -1;
+
+ *id = pin->hash;
+
+ return 0;
+}
+
+/**
+ * Get the version word from the plugin information
+ *
+ * @param inst
+ * The instance index value
+ * @return
+ * The 32bit unsigned version number of the plugin
+ * @return
+ * -1 is error and 0 on success
+ */
+static inline uint32_t
+plugin_get_version(int inst)
+{
+ struct plugin *pin = plugin_get(inst);
+
+ if (!pin || !pin->info)
+ return -1;
+
+ return pin->info->version;
+}
+
+/**
+ * Get the struct plugin_info structure suppled by the plugin.
+ *
+ * @param inst
+ * The instance index value
+ * @return
+ * NULL on error or pointer to info structure.
+ */
+static inline struct plugin_info *
+plugin_get_info(int inst)
+{
+ struct plugin *pin = plugin_get(inst);
+
+ if (!pin)
+ return NULL;
+ return pin->info;
+}
+
+/**
+ * Return a pointer to a global symbol in the plugin code.
+ *
+ * @param ping
+ * The instance of plugin structure
+ * @param symbol_name
+ * The symbol string to search for in the plugin.
+ * @param ret
+ * Place to put the symbol address if found.
+ * @return
+ * -1 on error or 0 if success and ret contains the address.
+ */
+int plugin_get_symbol(struct plugin *pin, const char *symbol_name, char **ret);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PLUGIN_H_ */
diff --git a/lib/plugin/plugin_version.map b/lib/plugin/plugin_version.map
new file mode 100644
index 0000000..89228c1
--- /dev/null
+++ b/lib/plugin/plugin_version.map
@@ -0,0 +1,6 @@
+DPDK_18.05 {
+ global: *;
+
+ local: *;
+};
+
diff --git a/lib/utils/meson.build b/lib/utils/meson.build
index 27d13f0..e0455ef 100644
--- a/lib/utils/meson.build
+++ b/lib/utils/meson.build
@@ -16,5 +16,5 @@ sources = files(
'rte_portlist.c',
'rte_strings.c',
'rte_heap.c')
-deps += ['ethdev']
+#deps += ['ethdev']
#deps += ['mbuf', 'dbuf']
diff --git a/lib/vec/meson.build b/lib/vec/meson.build
index 658d8cc..8831264 100644
--- a/lib/vec/meson.build
+++ b/lib/vec/meson.build
@@ -4,4 +4,4 @@
version = 1
sources = files('rte_vec.c')
headers = files('rte_vec.h')
-rte_deps += ['ethdev']
+#rte_deps += ['ethdev']
diff --git a/meson.build b/meson.build
index d2761e9..33c810a 100644
--- a/meson.build
+++ b/meson.build
@@ -1,4 +1,5 @@
project('pktgen', 'C',
+ version: '19.05.0-rc0',
license: 'BSD',
default_options: ['buildtype=release', 'default_library=static'],
meson_version: '>= 0.47.1'
@@ -31,6 +32,13 @@ dpdk_static_libraries = []
dpdk_drivers = []
dpdk_extra_ldflags = []
dpdk_app_link_libraries = []
+global_inc = []
+dpdk_dep = []
+pmdk_shared_libraries = []
+pmdk_static_libraries = []
+
+pver = meson.project_version().split('.')
+major_version = '@0@.@1@'.format(pver.get(0), pver.get(1))
add_project_arguments('-D_GNU_SOURCE', '-O3', '-g', language: 'c')
diff --git a/tools/run.py b/tools/run.py
index 1153656..04d61a1 100755
--- a/tools/run.py
+++ b/tools/run.py
@@ -88,15 +88,24 @@ def mk_tuple(lst, s):
return t[s]
+def add_ld_options(s, arg_list):
+ ''' Append LD_LIBRARY_PATH option to arg list '''
+ if s in cfg.run:
+ str = 'LD_LIBRARY_PATH=.'
+ for a in mk_tuple(cfg.run, s):
+ _p = a % globals()
+ str = str + ':' + _p
+ arg_list.append(str)
+
def add_run_options(s, arg_list, p):
''' Append options to arg list '''
if s in cfg.run:
- for a in mk_tuple(cfg.run, s):
- if p is not None:
- arg_list.append(p)
+ for a in mk_tuple(cfg.run, s):
+ if p is not None:
+ arg_list.append(p)
- _p = a % globals()
- arg_list.append(_p)
+ _p = a % globals()
+ arg_list.append(_p)
def add_setup_options(s, arg_list):
''' Append options to arg list '''
@@ -165,8 +174,11 @@ def run_cfg(cfg_file):
cfg = load_cfg(cfg_file)
args = []
+
add_run_options('exec', args, None)
+ add_ld_options('ld_path', args)
+
if not 'app_path' in cfg.run:
err_exit("'app_path' variable is missing from cfg.run in config file")