From: Ray Kinsella <mdr@ashroe.eu>
To: dev@dpdk.org
Cc: mdr@ashroe.eu, bruce.richardson@intel.com,
vladimir.medvedkin@intel.com, john.mcnamara@intel.com,
marko.kovacevic@intel.com
Subject: [dpdk-dev] [PATCH v2 1/2] app/test: add abi version testing functionality
Date: Thu, 22 Aug 2019 17:07:16 +0100 [thread overview]
Message-ID: <20190822160717.13584-2-mdr@ashroe.eu> (raw)
In-Reply-To: <20190822160717.13584-1-mdr@ashroe.eu>
This patchset adds ABI Version Testing functionality to the app/test
unit test framework, comprised of
1. The TEST_DPDK_ABI_VERSION_* and REGISTER_TEST_ABI_VERSION macros to
register abi versions with infrastructure.
2. The MAP_ABI_SYMBOL_VERSION macro to remap symbols based on their ABI
version.
3. The set_abi_version command to switch between ABI versions.
4. The BIND_VERSION_SYMBOL macro to bind against specific symbol
versions.
Signed-off-by: Ray Kinsella <mdr@ashroe.eu>
---
app/test/commands.c | 131 ++++++++++++++++++---
app/test/test.c | 2 +
app/test/test.h | 52 ++++++--
doc/guides/contributing/versioning.rst | 4 +
lib/librte_eal/common/include/rte_compat.h | 7 ++
5 files changed, 170 insertions(+), 26 deletions(-)
diff --git a/app/test/commands.c b/app/test/commands.c
index 8d5a03a95..06fc33ee5 100644
--- a/app/test/commands.c
+++ b/app/test/commands.c
@@ -50,12 +50,22 @@
/****************/
+static uint8_t test_abi_version = TEST_DPDK_ABI_VERSION_DEFAULT;
+
+static struct test_abi_version_list abi_version_list =
+ TAILQ_HEAD_INITIALIZER(abi_version_list);
+
static struct test_commands_list commands_list =
TAILQ_HEAD_INITIALIZER(commands_list);
-void
-add_test_command(struct test_command *t)
+void add_abi_version(struct test_abi_version *av)
+{
+ TAILQ_INSERT_TAIL(&abi_version_list, av, next);
+}
+
+void add_test_command(struct test_command *t, uint8_t abi_version)
{
+ t->abi_version = abi_version;
TAILQ_INSERT_TAIL(&commands_list, t, next);
}
@@ -63,6 +73,12 @@ struct cmd_autotest_result {
cmdline_fixed_string_t autotest;
};
+cmdline_parse_token_string_t
+cmd_autotest_autotest[TEST_DPDK_ABI_VERSION_MAX] = {
+ [0 ... TEST_DPDK_ABI_VERSION_MAX-1] =
+ TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest, "")
+};
+
static void cmd_autotest_parsed(void *parsed_result,
__attribute__((unused)) struct cmdline *cl,
__attribute__((unused)) void *data)
@@ -72,7 +88,8 @@ static void cmd_autotest_parsed(void *parsed_result,
int ret = 0;
TAILQ_FOREACH(t, &commands_list, next) {
- if (!strcmp(res->autotest, t->command))
+ if (!strcmp(res->autotest, t->command)
+ && t->abi_version == test_abi_version)
ret = t->callback();
}
@@ -86,10 +103,6 @@ static void cmd_autotest_parsed(void *parsed_result,
fflush(stdout);
}
-cmdline_parse_token_string_t cmd_autotest_autotest =
- TOKEN_STRING_INITIALIZER(struct cmd_autotest_result, autotest,
- "");
-
cmdline_parse_inst_t cmd_autotest = {
.f = cmd_autotest_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
@@ -244,6 +257,53 @@ cmdline_parse_inst_t cmd_quit = {
/****************/
+struct cmd_set_abi_version_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t abi_version_name;
+};
+
+static void cmd_set_abi_version_parsed(
+ void *parsed_result,
+ __attribute__((unused)) struct cmdline *cl,
+ __attribute__((unused)) void *data)
+{
+ struct test_abi_version *av;
+ struct cmd_set_abi_version_result *res = parsed_result;
+
+ TAILQ_FOREACH(av, &abi_version_list, next) {
+ if (!strcmp(res->abi_version_name, av->version_name)) {
+
+ printf("abi version set to %s\n", av->version_name);
+ test_abi_version = av->version_id;
+ cmd_autotest.tokens[0] =
+ (void *)&cmd_autotest_autotest[av->version_id];
+ }
+ }
+
+ fflush(stdout);
+}
+
+cmdline_parse_token_string_t cmd_set_abi_version_set =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_abi_version_result, set,
+ "set_abi_version");
+
+cmdline_parse_token_string_t cmd_set_abi_version_abi_version =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_abi_version_result,
+ abi_version_name, NULL);
+
+cmdline_parse_inst_t cmd_set_abi_version = {
+ .f = cmd_set_abi_version_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set abi version: ",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_set_abi_version_set,
+ (void *)&cmd_set_abi_version_abi_version,
+ NULL,
+ },
+};
+
+/****************/
+
struct cmd_set_rxtx_result {
cmdline_fixed_string_t set;
cmdline_fixed_string_t mode;
@@ -259,7 +319,7 @@ static void cmd_set_rxtx_parsed(void *parsed_result, struct cmdline *cl,
cmdline_parse_token_string_t cmd_set_rxtx_set =
TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, set,
- "set_rxtx_mode");
+ "set_rxtx_mode");
cmdline_parse_token_string_t cmd_set_rxtx_mode =
TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_result, mode, NULL);
@@ -360,29 +420,66 @@ cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_set_rxtx,
(cmdline_parse_inst_t *)&cmd_set_rxtx_anchor,
(cmdline_parse_inst_t *)&cmd_set_rxtx_sc,
+ (cmdline_parse_inst_t *)&cmd_set_abi_version,
NULL,
};
int commands_init(void)
{
+ struct test_abi_version *av;
struct test_command *t;
- char *commands;
- int commands_len = 0;
+ char *commands[TEST_DPDK_ABI_VERSION_MAX];
+ char *help;
+
+ int commands_len[TEST_DPDK_ABI_VERSION_MAX] = {
+ [0 ... TEST_DPDK_ABI_VERSION_MAX-1] = 0
+ };
+ int help_len = strlen(cmd_set_abi_version.help_str);
+ int abi_version;
+
+ /* set the set_abi_version command help string */
+ TAILQ_FOREACH(av, &abi_version_list, next) {
+ help_len += strlen(av->version_name) + 1;
+ }
+
+ help = (char *)calloc(help_len, sizeof(char));
+ if (!help)
+ return -1;
+
+ strlcat(help, cmd_set_abi_version.help_str, help_len);
+ TAILQ_FOREACH(av, &abi_version_list, next) {
+ strlcat(help, av->version_name, help_len);
+ if (TAILQ_NEXT(av, next) != NULL)
+ strlcat(help, "|", help_len);
+ }
+
+ cmd_set_abi_version.help_str = help;
+ /* set the parse strings for the command lists */
TAILQ_FOREACH(t, &commands_list, next) {
- commands_len += strlen(t->command) + 1;
+ commands_len[t->abi_version] += strlen(t->command) + 1;
}
- commands = (char *)calloc(commands_len, sizeof(char));
- if (!commands)
- return -1;
+ for (abi_version = 0; abi_version < TEST_DPDK_ABI_VERSION_MAX;
+ abi_version++) {
+ commands[abi_version] =
+ (char *)calloc(commands_len[abi_version], sizeof(char));
+ if (!commands[abi_version])
+ return -1;
+ }
TAILQ_FOREACH(t, &commands_list, next) {
- strlcat(commands, t->command, commands_len);
+ strlcat(commands[t->abi_version],
+ t->command, commands_len[t->abi_version]);
if (TAILQ_NEXT(t, next) != NULL)
- strlcat(commands, "#", commands_len);
+ strlcat(commands[t->abi_version],
+ "#", commands_len[t->abi_version]);
}
- cmd_autotest_autotest.string_data.str = commands;
+ for (abi_version = 0; abi_version < TEST_DPDK_ABI_VERSION_MAX;
+ abi_version++)
+ cmd_autotest_autotest[abi_version].string_data.str =
+ commands[abi_version];
+
return 0;
}
diff --git a/app/test/test.c b/app/test/test.c
index cd7aaf645..67179d4af 100644
--- a/app/test/test.c
+++ b/app/test/test.c
@@ -307,3 +307,5 @@ unit_test_suite_runner(struct unit_test_suite *suite)
return TEST_SKIPPED;
return TEST_SUCCESS;
}
+
+REGISTER_TEST_ABI_VERSION(default, TEST_DPDK_ABI_VERSION_DEFAULT)
diff --git a/app/test/test.h b/app/test/test.h
index ac0c50616..5ec3728d0 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -162,25 +162,59 @@ int test_set_rxtx_conf(cmdline_fixed_string_t mode);
int test_set_rxtx_anchor(cmdline_fixed_string_t type);
int test_set_rxtx_sc(cmdline_fixed_string_t type);
+#define MAP_ABI_SYMBOL_VERSION(name, abi_version) \
+ __asm(".symver "RTE_STR(name)","RTE_STR(name)"@"RTE_STR(abi_version))
+
+#define TEST_DPDK_ABI_VERSION_DEFAULT 0
+#define TEST_DPDK_ABI_VERSION_V1604 1
+#define TEST_DPDK_ABI_VERSION_V20 2
+#define TEST_DPDK_ABI_VERSION_MAX 3
+
+TAILQ_HEAD(test_abi_version_list, test_abi_version);
+struct test_abi_version {
+ TAILQ_ENTRY(test_abi_version) next;
+ const char *version_name;
+ uint8_t version_id;
+};
+
+void add_abi_version(struct test_abi_version *av);
+
+/* Register a test function with its command string */
+#define REGISTER_TEST_ABI_VERSION(name, id) \
+ static struct test_abi_version test_struct_##name = { \
+ .version_name = RTE_STR(name), \
+ .version_id = id, \
+ }; \
+ RTE_INIT(test_register_##name) \
+ { \
+ add_abi_version(&test_struct_##name); \
+ }
+
typedef int (test_callback)(void);
TAILQ_HEAD(test_commands_list, test_command);
struct test_command {
TAILQ_ENTRY(test_command) next;
const char *command;
test_callback *callback;
+ uint8_t abi_version;
};
-void add_test_command(struct test_command *t);
+void add_test_command(struct test_command *t, uint8_t abi_version);
+
+/* Register a test function with its command string and abi version */
+#define REGISTER_TEST_COMMAND_VERSION(cmd, func, abi_version) \
+ static struct test_command test_struct_##cmd = { \
+ .command = RTE_STR(cmd), \
+ .callback = func, \
+ }; \
+ RTE_INIT(test_register_##cmd) \
+ { \
+ add_test_command(&test_struct_##cmd, abi_version); \
+ }
/* Register a test function with its command string */
+
#define REGISTER_TEST_COMMAND(cmd, func) \
- static struct test_command test_struct_##cmd = { \
- .command = RTE_STR(cmd), \
- .callback = func, \
- }; \
- RTE_INIT(test_register_##cmd) \
- { \
- add_test_command(&test_struct_##cmd); \
- }
+ REGISTER_TEST_COMMAND_VERSION(cmd, func, TEST_DPDK_ABI_VERSION_DEFAULT)
#endif
diff --git a/doc/guides/contributing/versioning.rst b/doc/guides/contributing/versioning.rst
index 3ab2c4346..63ef53ea3 100644
--- a/doc/guides/contributing/versioning.rst
+++ b/doc/guides/contributing/versioning.rst
@@ -221,6 +221,10 @@ The macros exported are:
the linker to bind references to symbol ``b`` to the internal symbol
``b_e``.
+* ``BIND_VERSION_SYMBOL(b, n)``: Creates a symbol version entry instructing
+ the linker to bind references to symbol ``b`` to the external symbol
+ ``b@DPDK_n``
+
* ``MAP_STATIC_SYMBOL(f, p)``: Declare the prototype ``f``, and map it to the
fully qualified function ``p``, so that if a symbol becomes versioned, it
can still be mapped back to the public symbol name.
diff --git a/lib/librte_eal/common/include/rte_compat.h b/lib/librte_eal/common/include/rte_compat.h
index 92ff28faf..be9724f4c 100644
--- a/lib/librte_eal/common/include/rte_compat.h
+++ b/lib/librte_eal/common/include/rte_compat.h
@@ -50,6 +50,13 @@
#define BIND_DEFAULT_SYMBOL(b, e, n) __asm__(".symver " RTE_STR(b) RTE_STR(e) ", " RTE_STR(b) "@@DPDK_" RTE_STR(n))
#define __vsym __attribute__((used))
+/*
+ * BIND_VERSION_SYMBOL
+ * Creates a symbol version entry instructing the linker to bind references to
+ * symbol <b> to the symbol version <b>@DPDK_<n>
+ */
+#define BIND_VERSION_SYMBOL(b, n) __asm__(".symver " RTE_STR(b) ", " RTE_STR(b) "@DPDK_" RTE_STR(n))
+
/*
* MAP_STATIC_SYMBOL
* If a function has been bifurcated into multiple versions, none of which
--
2.17.1
next prev parent reply other threads:[~2019-08-22 16:08 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-22 16:07 [dpdk-dev] [PATCH v2 0/2] add abi version testing to app/test Ray Kinsella
2019-08-22 16:07 ` Ray Kinsella [this message]
2019-08-22 16:07 ` [dpdk-dev] [PATCH v2 2/2] app/test: lpm abi version testing Ray Kinsella
2019-08-23 15:49 ` [dpdk-dev] [PATCH v2 0/2] add abi version testing to app/test Aaron Conole
2019-08-26 16:45 ` Ray Kinsella
2019-08-27 8:17 ` Bruce Richardson
2019-08-27 8:28 ` Ray Kinsella
2019-08-27 14:19 ` Ray Kinsella
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190822160717.13584-2-mdr@ashroe.eu \
--to=mdr@ashroe.eu \
--cc=bruce.richardson@intel.com \
--cc=dev@dpdk.org \
--cc=john.mcnamara@intel.com \
--cc=marko.kovacevic@intel.com \
--cc=vladimir.medvedkin@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).