OVS currently uses other_config:dpdk-lcore-mask <coremask> directly in DPDK rte_eal_init() with '-c <coremask>' argument.
'-c' argument is now deprecated from DPDK and will be removed in DPDK 25.11, so OVS will no longer be able to use the '-c <coremask>' argument. Convert dpdk-lcore-mask core mask to a core list that can be used with '--lcores' and add some tests. Using the '--lcores' argument also adds compability for using a core in the core mask that is greater than the max lcore, similar to commit fe53b478f86e ("dpdk: Fix main lcore on systems with many cores.") Signed-off-by: Kevin Traynor <ktray...@redhat.com> --- lib/dpdk.c | 76 +++++++++++++++++++++++++++++++++++-- tests/pmd.at | 15 -------- tests/system-dpdk-macros.at | 15 ++++++++ tests/system-dpdk.at | 73 +++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 5 files changed, 161 insertions(+), 19 deletions(-) diff --git a/lib/dpdk.c b/lib/dpdk.c index 1f4f2bf08..a3e397f3c 100644 --- a/lib/dpdk.c +++ b/lib/dpdk.c @@ -65,4 +65,58 @@ args_contains(const struct svec *args, const char *value) } +#define LCORE_MAX_STR_SIZE 23 /* Max size of single lcore assignment. */ +#define LCORE_MAX_ARGS_LENGTH 256 /* Max size of DPDK lcores list. */ + +/* Converts a hexadecimal core mask to DPDK lcore list format. */ +static char * +cmask_to_lcore_list(const char *cmask) +{ + char cvalue[LCORE_MAX_STR_SIZE] = ""; + char *lcores = NULL; + int num_lcores = 0; + int core_id = 0; + int end_idx = 0; + + /* Ignore leading 0x. */ + if (!strncmp(cmask, "0x", 2) || !strncmp(cmask, "0X", 2)) { + end_idx = 2; + } + + for (int i = strlen(cmask) - 1; i >= end_idx; i--) { + char hex = cmask[i]; + int bin; + + bin = hexit_value(hex); + if (bin == -1) { + VLOG_WARN("Invalid lcore mask: %c", cmask[i]); + bin = 0; + } + for (int j = 0; j < 4; j++) { + if ((bin >> j) & 0x1) { + if (!num_lcores) { + lcores = xmalloc(LCORE_MAX_STR_SIZE); + lcores[0] = '\0'; + snprintf(cvalue, LCORE_MAX_STR_SIZE, "0@%d", core_id); + num_lcores++; + } else { + int new_size = strlen(lcores) + LCORE_MAX_STR_SIZE; + + if (new_size > LCORE_MAX_ARGS_LENGTH) { + VLOG_INFO("Concatenating DPDK lcore list from" + " dpdk-lcore-mask as string too long."); + return lcores; + } + lcores = xrealloc(lcores, new_size); + snprintf(cvalue, LCORE_MAX_STR_SIZE, ",%d@%d", + num_lcores++, core_id); + } + strncat(lcores, cvalue, LCORE_MAX_STR_SIZE); + } + core_id++; + } + } + return lcores; +} + static void construct_dpdk_options(const struct smap *ovs_other_config, struct svec *args) @@ -71,10 +125,11 @@ construct_dpdk_options(const struct smap *ovs_other_config, struct svec *args) const char *ovs_configuration; const char *dpdk_option; + char *(*param_conversion) (const char *); bool default_enabled; const char *default_value; } opts[] = { - {"dpdk-lcore-mask", "-c", false, NULL}, - {"dpdk-hugepage-dir", "--huge-dir", false, NULL}, - {"dpdk-socket-limit", "--socket-limit", false, NULL}, + {"dpdk-lcore-mask", "--lcores", cmask_to_lcore_list, false, NULL}, + {"dpdk-hugepage-dir", "--huge-dir", NULL, false, NULL}, + {"dpdk-socket-limit", "--socket-limit", NULL, false, NULL}, }; @@ -91,9 +146,22 @@ construct_dpdk_options(const struct smap *ovs_other_config, struct svec *args) if (value) { if (!args_contains(args, opts[i].dpdk_option)) { + char *dpdk_val = NULL; + + if (opts[i].param_conversion) { + dpdk_val = (opts[i].param_conversion)(value); + if (!dpdk_val) { + VLOG_WARN("Ignoring database defined option '%s'" + " due to invalid value '%s'", + opts[i].ovs_configuration, value); + continue; + } + value = dpdk_val; + } svec_add(args, opts[i].dpdk_option); svec_add(args, value); + free(dpdk_val); } else { VLOG_WARN("Ignoring database defined option '%s' due to " - "dpdk-extra config", opts[i].dpdk_option); + "dpdk-extra config", opts[i].ovs_configuration); } } diff --git a/tests/pmd.at b/tests/pmd.at index 35a44b4df..8254ac3b0 100644 --- a/tests/pmd.at +++ b/tests/pmd.at @@ -27,19 +27,4 @@ flow_dump_prepend_pmd () { m4_divert_pop([PREPARE_TESTS]) -dnl CHECK_CPU_DISCOVERED([n_cpu]) -dnl -dnl Waits until CPUs discovered and checks if number of discovered CPUs -dnl is greater or equal to 'n_cpu'. Without parameters checks that at -dnl least one CPU discovered. -m4_define([CHECK_CPU_DISCOVERED], [ - PATTERN="Discovered [[0-9]]* NUMA nodes and [[0-9]]* CPU cores" - OVS_WAIT_UNTIL([grep "$PATTERN" ovs-vswitchd.log]) - N_CPU=$(grep "$PATTERN" ovs-vswitchd.log | sed -e 's/.* \([[0-9]]*\) CPU cores/\1/') - if [[ -z "$1" ]] - then AT_CHECK([test "$N_CPU" -gt "0"]) - else AT_SKIP_IF([test "$N_CPU" -lt "$1"]) - fi -]) - dnl CHECK_PMD_THREADS_CREATED([n_threads], [numa_id], [+line]) dnl diff --git a/tests/system-dpdk-macros.at b/tests/system-dpdk-macros.at index f8ba76673..aae49d90f 100644 --- a/tests/system-dpdk-macros.at +++ b/tests/system-dpdk-macros.at @@ -200,2 +200,17 @@ m4_define([CONFIGURE_VETH_OFFLOADS], AT_CHECK([ethtool -K $1 txvlan off], [0], [ignore], [ignore])] ) + +dnl CHECK_CPU_DISCOVERED([n_cpu]) +dnl +dnl Waits until CPUs discovered and checks if number of discovered CPUs +dnl is greater or equal to 'n_cpu'. Without parameters checks that at +dnl least one CPU discovered. +m4_define([CHECK_CPU_DISCOVERED], [ + PATTERN="Discovered [[0-9]]* NUMA nodes and [[0-9]]* CPU cores" + OVS_WAIT_UNTIL([grep "$PATTERN" ovs-vswitchd.log]) + N_CPU=$(grep "$PATTERN" ovs-vswitchd.log | sed -e 's/.* \([[0-9]]*\) CPU cores/\1/') + if [[ -z "$1" ]] + then AT_CHECK([test "$N_CPU" -gt "0"]) + else AT_SKIP_IF([test "$N_CPU" -lt "$1"]) + fi +]) \ No newline at end of file diff --git a/tests/system-dpdk.at b/tests/system-dpdk.at index e79c75565..afbf84f59 100644 --- a/tests/system-dpdk.at +++ b/tests/system-dpdk.at @@ -52,7 +52,80 @@ AT_CLEANUP dnl -------------------------------------------------------------------------- +dnl Check dpdk-lcore-mask conversion for only first bit +AT_SETUP([OVS-DPDK - dpdk-lcore-mask conversion - single]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +OVS_DPDK_START_OVSDB() +OVS_DPDK_START_VSWITCHD([--no-pci]) +CHECK_CPU_DISCOVERED() +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0x1]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true]) +expected_lcores="lcores 0@0" +OVS_WAIT_UNTIL([grep "$expected_lcores" ovs-vswitchd.log]) +OVS_DPDK_STOP_VSWITCHD +AT_CLEANUP +dnl -------------------------------------------------------------------------- + +dnl Check dpdk-lcore-mask conversion for only multiple bits +AT_SETUP([OVS-DPDK - dpdk-lcore-mask conversion - multi]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +OVS_DPDK_START_OVSDB() +OVS_DPDK_START_VSWITCHD([--no-pci]) +CHECK_CPU_DISCOVERED(4) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xf]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true]) +expected_lcores="lcores 0@0,1@1,2@2,3@3" +OVS_WAIT_UNTIL([grep "$expected_lcores" ovs-vswitchd.log]) +OVS_DPDK_STOP_VSWITCHD +AT_CLEANUP +dnl -------------------------------------------------------------------------- +dnl Check dpdk-lcore-mask conversion for max length string +AT_SETUP([OVS-DPDK - dpdk-lcore-mask conversion - max]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +OVS_DPDK_START_OVSDB() +OVS_DPDK_START_VSWITCHD([--no-pci]) +CHECK_CPU_DISCOVERED(42) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0x7ffffffffff]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true]) +expected_lcores="lcores 0@0,1@1,2@2,3@3,4@4,5@5,6@6,7@7,8@8,9@9,10@10,11@11,12@12,13@13,14@14,15@15,16@16,17@17,18@18,19@19,20@20,21@21,22@22,23@23,24@24,25@25,26@26,27@27,28@28,29@29,30@30,31@31,32@32,33@33,34@34,35@35,36@36,37@37,38@38,39@39,40@40,41@41,42@42" +OVS_WAIT_UNTIL([grep "$expected_lcores" ovs-vswitchd.log]) +OVS_DPDK_STOP_VSWITCHD +AT_CLEANUP +dnl -------------------------------------------------------------------------- +dnl Check dpdk-lcore-mask conversion for > max length string +AT_SETUP([OVS-DPDK - dpdk-lcore-mask conversion - cat]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +OVS_DPDK_START_OVSDB() +OVS_DPDK_START_VSWITCHD([--no-pci]) +CHECK_CPU_DISCOVERED(42) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xfffffffffff]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true]) +OVS_WAIT_UNTIL([grep "Concatenating DPDK lcore list from dpdk-lcore-mask as string too long." ovs-vswitchd.log]) +expected_lcores="lcores 0@0,1@1,2@2,3@3,4@4,5@5,6@6,7@7,8@8,9@9,10@10,11@11,12@12,13@13,14@14,15@15,16@16,17@17,18@18,19@19,20@20,21@21,22@22,23@23,24@24,25@25,26@26,27@27,28@28,29@29,30@30,31@31,32@32,33@33,34@34,35@35,36@36,37@37,38@38,39@39,40@40,41@41,42@42" +OVS_WAIT_UNTIL([grep "$expected_lcores" ovs-vswitchd.log]) +OVS_DPDK_STOP_VSWITCHD +AT_CLEANUP dnl -------------------------------------------------------------------------- + +dnl Check dpdk-lcore-mask conversion for zero +AT_SETUP([OVS-DPDK - dpdk-lcore-mask conversion - zeromask]) +AT_KEYWORDS([dpdk]) +OVS_DPDK_PRE_CHECK() +OVS_DPDK_START_OVSDB() +OVS_DPDK_START_VSWITCHD([--no-pci]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0x0]) +AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true]) +OVS_WAIT_UNTIL([grep "Ignoring database defined option 'dpdk-lcore-mask' due to invalid value '0x0'" ovs-vswitchd.log]) +expected_lcores="lcores 0@0" +OVS_WAIT_UNTIL([grep "$expected_lcores" ovs-vswitchd.log]) +OVS_DPDK_STOP_VSWITCHD(["/Ignoring database defined option/d"]) +AT_CLEANUP +dnl -------------------------------------------------------------------------- + dnl Add standard DPDK PHY port AT_SETUP([OVS-DPDK - add standard DPDK port]) diff --git a/tests/testsuite.at b/tests/testsuite.at index 9d77a9f51..51e12583b 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -20,4 +20,5 @@ m4_include([tests/ovs-macros.at]) m4_include([tests/ovsdb-macros.at]) m4_include([tests/ofproto-macros.at]) +m4_include([tests/system-dpdk-macros.at]) m4_include([tests/completion.at]) -- 2.51.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev