2016-10-04 17:58:05 -07:00
|
|
|
/*
|
2017-03-08 15:44:39 -08:00
|
|
|
* Copyright (c) 2014, 2015, 2016, 2017 Nicira, Inc.
|
2016-10-04 17:58:05 -07:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include "dpdk.h"
|
|
|
|
|
2017-03-06 09:49:11 +03:00
|
|
|
#include <stdio.h>
|
2016-10-04 17:58:05 -07:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
|
2020-07-13 13:42:13 +01:00
|
|
|
#include <rte_cpuflags.h>
|
2018-05-03 15:08:00 -04:00
|
|
|
#include <rte_errno.h>
|
2017-03-06 09:49:11 +03:00
|
|
|
#include <rte_log.h>
|
2016-10-04 17:58:05 -07:00
|
|
|
#include <rte_memzone.h>
|
2018-01-15 19:21:12 +01:00
|
|
|
#include <rte_version.h>
|
2016-10-04 17:58:05 -07:00
|
|
|
|
|
|
|
#include "dirs.h"
|
2016-10-13 18:27:51 +01:00
|
|
|
#include "fatal-signal.h"
|
2016-10-04 17:58:05 -07:00
|
|
|
#include "netdev-dpdk.h"
|
2019-05-07 12:24:08 +03:00
|
|
|
#include "netdev-offload-provider.h"
|
2016-10-04 17:58:05 -07:00
|
|
|
#include "openvswitch/dynamic-string.h"
|
|
|
|
#include "openvswitch/vlog.h"
|
2018-05-09 11:14:25 +01:00
|
|
|
#include "ovs-numa.h"
|
2016-10-04 17:58:05 -07:00
|
|
|
#include "smap.h"
|
2019-01-29 11:11:49 +03:00
|
|
|
#include "svec.h"
|
dpdk: Add commands to configure log levels.
Enabling debug logs in dpdk can be a challenge to be sure of what is
actually enabled, add commands to list and change those log levels.
However, these commands do not help when tracking issues in dpdk init
itself: dump log levels right after init.
Example:
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is info
id 1: lib.malloc, level is info
id 2: lib.ring, level is info
id 3: lib.mempool, level is info
id 4: lib.timer, level is info
id 5: pmd, level is info
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is info
[...]
$ ovs-appctl dpdk/log-set debug pmd.*:notice
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is debug
id 1: lib.malloc, level is debug
id 2: lib.ring, level is debug
id 3: lib.mempool, level is debug
id 4: lib.timer, level is debug
id 5: pmd, level is debug
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is notice
[...]
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2020-07-13 10:06:21 +02:00
|
|
|
#include "unixctl.h"
|
2019-05-14 16:08:43 +03:00
|
|
|
#include "util.h"
|
2018-05-03 15:08:01 -04:00
|
|
|
#include "vswitch-idl.h"
|
2016-10-04 17:58:05 -07:00
|
|
|
|
|
|
|
VLOG_DEFINE_THIS_MODULE(dpdk);
|
|
|
|
|
2017-03-06 09:49:11 +03:00
|
|
|
static FILE *log_stream = NULL; /* Stream for DPDK log redirection */
|
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
static char *vhost_sock_dir = NULL; /* Location of vhost-user sockets */
|
netdev-dpdk: vHost IOMMU support
DPDK v17.11 introduces support for the vHost IOMMU feature.
This is a security feature, which restricts the vhost memory
that a virtio device may access.
This feature also enables the vhost REPLY_ACK protocol, the
implementation of which is known to work in newer versions of
QEMU (i.e. v2.10.0), but is buggy in older versions (v2.7.0 -
v2.9.0, inclusive). As such, the feature is disabled by default
in (and should remain so), for the aforementioned older QEMU
verions. Starting with QEMU v2.9.1, vhost-iommu-support can
safely be enabled, even without having an IOMMU device, with
no performance penalty.
This patch adds a new global config option, vhost-iommu-support,
that controls enablement of the vhost IOMMU feature:
ovs-vsctl set Open_vSwitch . other_config:vhost-iommu-support=true
This value defaults to false; to enable IOMMU support, this field
should be set to true when setting other global parameters on init
(such as "dpdk-socket-mem", for example). Changing the value at
runtime is not supported, and requires restarting the vswitch daemon.
Signed-off-by: Mark Kavanagh <mark.b.kavanagh@intel.com>
Acked-by: Kevin Traynor <ktraynor@redhat.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
2017-12-08 10:53:47 +00:00
|
|
|
static bool vhost_iommu_enabled = false; /* Status of vHost IOMMU support */
|
2019-05-14 16:08:43 +03:00
|
|
|
static bool vhost_postcopy_enabled = false; /* Status of vHost POSTCOPY
|
|
|
|
* support. */
|
2018-05-03 15:08:01 -04:00
|
|
|
static bool dpdk_initialized = false; /* Indicates successful initialization
|
|
|
|
* of DPDK. */
|
2018-06-27 14:58:31 +01:00
|
|
|
static bool per_port_memory = false; /* Status of per port memory support */
|
2016-10-04 17:58:05 -07:00
|
|
|
|
|
|
|
static int
|
2017-02-09 03:25:41 -08:00
|
|
|
process_vhost_flags(char *flag, const char *default_val, int size,
|
2016-10-04 17:58:05 -07:00
|
|
|
const struct smap *ovs_other_config,
|
|
|
|
char **new_val)
|
|
|
|
{
|
|
|
|
const char *val;
|
|
|
|
int changed = 0;
|
|
|
|
|
|
|
|
val = smap_get(ovs_other_config, flag);
|
|
|
|
|
|
|
|
/* Process the vhost-sock-dir flag if it is provided, otherwise resort to
|
|
|
|
* default value.
|
|
|
|
*/
|
|
|
|
if (val && (strlen(val) <= size)) {
|
|
|
|
changed = 1;
|
|
|
|
*new_val = xstrdup(val);
|
|
|
|
VLOG_INFO("User-provided %s in use: %s", flag, *new_val);
|
|
|
|
} else {
|
|
|
|
VLOG_INFO("No %s provided - defaulting to %s", flag, default_val);
|
2017-02-09 03:25:41 -08:00
|
|
|
*new_val = xstrdup(default_val);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
2019-01-29 11:11:49 +03:00
|
|
|
args_contains(const struct svec *args, const char *value)
|
2016-10-04 17:58:05 -07:00
|
|
|
{
|
2019-01-29 11:11:49 +03:00
|
|
|
const char *arg;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
/* We can't just use 'svec_contains' because args are not sorted. */
|
|
|
|
SVEC_FOR_EACH (i, arg, args) {
|
|
|
|
if (!strcmp(arg, value)) {
|
2016-10-04 17:58:05 -07:00
|
|
|
return true;
|
2019-01-29 11:11:49 +03:00
|
|
|
}
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
static void
|
|
|
|
construct_dpdk_options(const struct smap *ovs_other_config, struct svec *args)
|
2016-10-04 17:58:05 -07:00
|
|
|
{
|
|
|
|
struct dpdk_options_map {
|
|
|
|
const char *ovs_configuration;
|
|
|
|
const char *dpdk_option;
|
|
|
|
bool default_enabled;
|
|
|
|
const char *default_value;
|
|
|
|
} opts[] = {
|
dpdk: Limit DPDK memory usage.
Since 18.05 release, DPDK moved to dynamic memory model in which
hugepages could be allocated on demand. At the same time '--socket-mem'
option was re-defined as a size of pre-allocated memory, i.e. memory
that should be allocated at startup and could not be freed.
So, DPDK with a new memory model could allocate more hugepage memory
than specified in '--socket-mem' or '-m' options.
This change adds new configurable 'other_config:dpdk-socket-limit'
which could be used to limit the ammount of memory DPDK could use.
It uses new DPDK option '--socket-limit'.
Ex.:
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-limit="1024,1024"
Also, in order to preserve old behaviour, if '--socket-limit' is not
specified, it will be defaulted to the amount of memory specified by
'--socket-mem' option, i.e. OVS will not be able to allocate more.
This is needed, for example, to disallow OVS to allocate more memory
than reserved for it by Nova in OpenStack installations.
Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
2019-01-29 11:11:50 +03:00
|
|
|
{"dpdk-lcore-mask", "-c", false, NULL},
|
|
|
|
{"dpdk-hugepage-dir", "--huge-dir", false, NULL},
|
|
|
|
{"dpdk-socket-limit", "--socket-limit", false, NULL},
|
2016-10-04 17:58:05 -07:00
|
|
|
};
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
int i;
|
2016-10-04 17:58:05 -07:00
|
|
|
|
|
|
|
/*First, construct from the flat-options (non-mutex)*/
|
|
|
|
for (i = 0; i < ARRAY_SIZE(opts); ++i) {
|
2019-01-29 11:11:49 +03:00
|
|
|
const char *value = smap_get(ovs_other_config,
|
|
|
|
opts[i].ovs_configuration);
|
|
|
|
if (!value && opts[i].default_enabled) {
|
|
|
|
value = opts[i].default_value;
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
if (value) {
|
|
|
|
if (!args_contains(args, opts[i].dpdk_option)) {
|
|
|
|
svec_add(args, opts[i].dpdk_option);
|
|
|
|
svec_add(args, value);
|
2016-10-04 17:58:05 -07:00
|
|
|
} else {
|
|
|
|
VLOG_WARN("Ignoring database defined option '%s' due to "
|
2019-01-29 11:11:49 +03:00
|
|
|
"dpdk-extra config", opts[i].dpdk_option);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 11:14:25 +01:00
|
|
|
static char *
|
|
|
|
construct_dpdk_socket_mem(void)
|
|
|
|
{
|
|
|
|
const char *def_value = "1024";
|
2019-01-22 16:22:30 +03:00
|
|
|
int numa, numa_nodes = ovs_numa_get_n_numas();
|
|
|
|
struct ds dpdk_socket_mem = DS_EMPTY_INITIALIZER;
|
2018-05-09 11:14:25 +01:00
|
|
|
|
|
|
|
if (numa_nodes == 0 || numa_nodes == OVS_NUMA_UNSPEC) {
|
|
|
|
numa_nodes = 1;
|
|
|
|
}
|
|
|
|
|
2019-01-22 16:22:30 +03:00
|
|
|
ds_put_cstr(&dpdk_socket_mem, def_value);
|
2018-05-09 11:14:25 +01:00
|
|
|
for (numa = 1; numa < numa_nodes; ++numa) {
|
2019-01-22 16:22:30 +03:00
|
|
|
ds_put_format(&dpdk_socket_mem, ",%s", def_value);
|
2018-05-09 11:14:25 +01:00
|
|
|
}
|
|
|
|
|
2019-01-22 16:22:30 +03:00
|
|
|
return ds_cstr(&dpdk_socket_mem);
|
2018-05-09 11:14:25 +01:00
|
|
|
}
|
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
#define MAX_DPDK_EXCL_OPTS 10
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
static void
|
2016-10-04 17:58:05 -07:00
|
|
|
construct_dpdk_mutex_options(const struct smap *ovs_other_config,
|
2019-01-29 11:11:49 +03:00
|
|
|
struct svec *args)
|
2016-10-04 17:58:05 -07:00
|
|
|
{
|
2018-05-09 11:14:25 +01:00
|
|
|
char *default_dpdk_socket_mem = construct_dpdk_socket_mem();
|
2019-01-29 11:11:49 +03:00
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
struct dpdk_exclusive_options_map {
|
|
|
|
const char *category;
|
|
|
|
const char *ovs_dpdk_options[MAX_DPDK_EXCL_OPTS];
|
|
|
|
const char *eal_dpdk_options[MAX_DPDK_EXCL_OPTS];
|
|
|
|
const char *default_value;
|
|
|
|
int default_option;
|
|
|
|
} excl_opts[] = {
|
|
|
|
{"memory type",
|
|
|
|
{"dpdk-alloc-mem", "dpdk-socket-mem", NULL,},
|
|
|
|
{"-m", "--socket-mem", NULL,},
|
2018-05-09 11:14:25 +01:00
|
|
|
default_dpdk_socket_mem, 1
|
2016-10-04 17:58:05 -07:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
int i;
|
2016-10-04 17:58:05 -07:00
|
|
|
for (i = 0; i < ARRAY_SIZE(excl_opts); ++i) {
|
|
|
|
int found_opts = 0, scan, found_pos = -1;
|
|
|
|
const char *found_value;
|
|
|
|
struct dpdk_exclusive_options_map *popt = &excl_opts[i];
|
|
|
|
|
|
|
|
for (scan = 0; scan < MAX_DPDK_EXCL_OPTS
|
|
|
|
&& popt->ovs_dpdk_options[scan]; ++scan) {
|
2019-01-29 11:11:49 +03:00
|
|
|
const char *value = smap_get(ovs_other_config,
|
|
|
|
popt->ovs_dpdk_options[scan]);
|
|
|
|
if (value && strlen(value)) {
|
2016-10-04 17:58:05 -07:00
|
|
|
found_opts++;
|
|
|
|
found_pos = scan;
|
2019-01-29 11:11:49 +03:00
|
|
|
found_value = value;
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found_opts) {
|
|
|
|
if (popt->default_option) {
|
|
|
|
found_pos = popt->default_option;
|
|
|
|
found_value = popt->default_value;
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found_opts > 1) {
|
|
|
|
VLOG_ERR("Multiple defined options for %s. Please check your"
|
|
|
|
" database settings and reconfigure if necessary.",
|
|
|
|
popt->category);
|
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
if (!args_contains(args, popt->eal_dpdk_options[found_pos])) {
|
|
|
|
svec_add(args, popt->eal_dpdk_options[found_pos]);
|
|
|
|
svec_add(args, found_value);
|
2016-10-04 17:58:05 -07:00
|
|
|
} else {
|
|
|
|
VLOG_WARN("Ignoring database defined option '%s' due to "
|
2019-01-29 11:11:49 +03:00
|
|
|
"dpdk-extra config", popt->eal_dpdk_options[found_pos]);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 11:14:25 +01:00
|
|
|
free(default_dpdk_socket_mem);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
static void
|
|
|
|
construct_dpdk_args(const struct smap *ovs_other_config, struct svec *args)
|
2016-10-04 17:58:05 -07:00
|
|
|
{
|
2019-01-29 11:11:49 +03:00
|
|
|
const char *extra_configuration = smap_get(ovs_other_config, "dpdk-extra");
|
2016-10-04 17:58:05 -07:00
|
|
|
|
|
|
|
if (extra_configuration) {
|
2019-01-29 11:11:49 +03:00
|
|
|
svec_parse_words(args, extra_configuration);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
construct_dpdk_options(ovs_other_config, args);
|
|
|
|
construct_dpdk_mutex_options(ovs_other_config, args);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
2017-03-06 09:49:11 +03:00
|
|
|
static ssize_t
|
|
|
|
dpdk_log_write(void *c OVS_UNUSED, const char *buf, size_t size)
|
|
|
|
{
|
2018-03-23 12:56:53 +03:00
|
|
|
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(600, 600);
|
|
|
|
static struct vlog_rate_limit dbg_rl = VLOG_RATE_LIMIT_INIT(600, 600);
|
2017-03-06 09:49:11 +03:00
|
|
|
|
|
|
|
switch (rte_log_cur_msg_loglevel()) {
|
|
|
|
case RTE_LOG_DEBUG:
|
2019-09-06 13:26:02 +02:00
|
|
|
VLOG_DBG_RL(&dbg_rl, "%.*s", (int) size, buf);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_INFO:
|
|
|
|
case RTE_LOG_NOTICE:
|
2019-09-06 13:26:02 +02:00
|
|
|
VLOG_INFO_RL(&rl, "%.*s", (int) size, buf);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_WARNING:
|
2019-09-06 13:26:02 +02:00
|
|
|
VLOG_WARN_RL(&rl, "%.*s", (int) size, buf);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_ERR:
|
2019-09-06 13:26:02 +02:00
|
|
|
VLOG_ERR_RL(&rl, "%.*s", (int) size, buf);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_CRIT:
|
|
|
|
case RTE_LOG_ALERT:
|
|
|
|
case RTE_LOG_EMERG:
|
2019-09-06 13:26:02 +02:00
|
|
|
VLOG_EMER("%.*s", (int) size, buf);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
OVS_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cookie_io_functions_t dpdk_log_func = {
|
|
|
|
.write = dpdk_log_write,
|
|
|
|
};
|
|
|
|
|
dpdk: Add commands to configure log levels.
Enabling debug logs in dpdk can be a challenge to be sure of what is
actually enabled, add commands to list and change those log levels.
However, these commands do not help when tracking issues in dpdk init
itself: dump log levels right after init.
Example:
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is info
id 1: lib.malloc, level is info
id 2: lib.ring, level is info
id 3: lib.mempool, level is info
id 4: lib.timer, level is info
id 5: pmd, level is info
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is info
[...]
$ ovs-appctl dpdk/log-set debug pmd.*:notice
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is debug
id 1: lib.malloc, level is debug
id 2: lib.ring, level is debug
id 3: lib.mempool, level is debug
id 4: lib.timer, level is debug
id 5: pmd, level is debug
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is notice
[...]
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2020-07-13 10:06:21 +02:00
|
|
|
static void
|
|
|
|
dpdk_unixctl_mem_stream(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
|
|
|
const char *argv[] OVS_UNUSED, void *aux)
|
|
|
|
{
|
|
|
|
void (*callback)(FILE *) = aux;
|
|
|
|
char *response = NULL;
|
|
|
|
FILE *stream;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
stream = open_memstream(&response, &size);
|
|
|
|
if (!stream) {
|
|
|
|
response = xasprintf("Unable to open memstream: %s.",
|
|
|
|
ovs_strerror(errno));
|
|
|
|
unixctl_command_reply_error(conn, response);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(stream);
|
|
|
|
fclose(stream);
|
|
|
|
unixctl_command_reply(conn, response);
|
|
|
|
out:
|
|
|
|
free(response);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dpdk_parse_log_level(const char *s)
|
|
|
|
{
|
|
|
|
static const char * const levels[] = {
|
|
|
|
[RTE_LOG_EMERG] = "emergency",
|
|
|
|
[RTE_LOG_ALERT] = "alert",
|
|
|
|
[RTE_LOG_CRIT] = "critical",
|
|
|
|
[RTE_LOG_ERR] = "error",
|
|
|
|
[RTE_LOG_WARNING] = "warning",
|
|
|
|
[RTE_LOG_NOTICE] = "notice",
|
|
|
|
[RTE_LOG_INFO] = "info",
|
|
|
|
[RTE_LOG_DEBUG] = "debug",
|
|
|
|
};
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 1; i < ARRAY_SIZE(levels); ++i) {
|
|
|
|
if (!strcmp(s, levels[i])) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
dpdk_unixctl_log_set(struct unixctl_conn *conn, int argc, const char *argv[],
|
|
|
|
void *aux OVS_UNUSED)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* With no argument, set all components level to 'debug'. */
|
|
|
|
if (argc == 1) {
|
|
|
|
rte_log_set_level_pattern("*", RTE_LOG_DEBUG);
|
|
|
|
}
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
char *err_msg = NULL;
|
|
|
|
char *level_string;
|
|
|
|
char *pattern;
|
|
|
|
char *s;
|
|
|
|
int level;
|
|
|
|
|
|
|
|
s = xstrdup(argv[i]);
|
|
|
|
level_string = strchr(s, ':');
|
|
|
|
if (level_string == NULL) {
|
|
|
|
pattern = "*";
|
|
|
|
level_string = s;
|
|
|
|
} else {
|
|
|
|
pattern = s;
|
|
|
|
level_string[0] = '\0';
|
|
|
|
level_string++;
|
|
|
|
}
|
|
|
|
|
|
|
|
level = dpdk_parse_log_level(level_string);
|
|
|
|
if (level == -1) {
|
|
|
|
err_msg = xasprintf("invalid log level: '%s'", level_string);
|
|
|
|
} else if (rte_log_set_level_pattern(pattern, level) < 0) {
|
|
|
|
err_msg = xasprintf("cannot set log level for '%s'", argv[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err_msg) {
|
|
|
|
unixctl_command_reply_error(conn, err_msg);
|
|
|
|
free(err_msg);
|
|
|
|
free(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
unixctl_command_reply(conn, NULL);
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:08:00 -04:00
|
|
|
static bool
|
2016-10-04 17:58:05 -07:00
|
|
|
dpdk_init__(const struct smap *ovs_other_config)
|
|
|
|
{
|
2019-01-29 11:11:49 +03:00
|
|
|
char *sock_dir_subcomponent;
|
|
|
|
char **argv = NULL;
|
2016-10-04 17:58:05 -07:00
|
|
|
int result;
|
|
|
|
bool auto_determine = true;
|
|
|
|
int err = 0;
|
2019-08-13 14:28:26 +03:00
|
|
|
struct ovs_numa_dump *affinity = NULL;
|
2019-01-29 11:11:49 +03:00
|
|
|
struct svec args = SVEC_EMPTY_INITIALIZER;
|
2016-10-04 17:58:05 -07:00
|
|
|
|
2017-03-06 09:49:11 +03:00
|
|
|
log_stream = fopencookie(NULL, "w+", dpdk_log_func);
|
|
|
|
if (log_stream == NULL) {
|
|
|
|
VLOG_ERR("Can't redirect DPDK log: %s.", ovs_strerror(errno));
|
|
|
|
} else {
|
|
|
|
setbuf(log_stream, NULL);
|
|
|
|
rte_openlog_stream(log_stream);
|
|
|
|
}
|
|
|
|
|
2017-02-09 03:25:41 -08:00
|
|
|
if (process_vhost_flags("vhost-sock-dir", ovs_rundir(),
|
2016-10-04 17:58:05 -07:00
|
|
|
NAME_MAX, ovs_other_config,
|
|
|
|
&sock_dir_subcomponent)) {
|
|
|
|
struct stat s;
|
|
|
|
if (!strstr(sock_dir_subcomponent, "..")) {
|
|
|
|
vhost_sock_dir = xasprintf("%s/%s", ovs_rundir(),
|
|
|
|
sock_dir_subcomponent);
|
|
|
|
|
|
|
|
err = stat(vhost_sock_dir, &s);
|
|
|
|
if (err) {
|
|
|
|
VLOG_ERR("vhost-user sock directory '%s' does not exist.",
|
|
|
|
vhost_sock_dir);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
vhost_sock_dir = xstrdup(ovs_rundir());
|
|
|
|
VLOG_ERR("vhost-user sock directory request '%s/%s' has invalid"
|
|
|
|
"characters '..' - using %s instead.",
|
|
|
|
ovs_rundir(), sock_dir_subcomponent, ovs_rundir());
|
|
|
|
}
|
|
|
|
free(sock_dir_subcomponent);
|
|
|
|
} else {
|
|
|
|
vhost_sock_dir = sock_dir_subcomponent;
|
|
|
|
}
|
|
|
|
|
netdev-dpdk: vHost IOMMU support
DPDK v17.11 introduces support for the vHost IOMMU feature.
This is a security feature, which restricts the vhost memory
that a virtio device may access.
This feature also enables the vhost REPLY_ACK protocol, the
implementation of which is known to work in newer versions of
QEMU (i.e. v2.10.0), but is buggy in older versions (v2.7.0 -
v2.9.0, inclusive). As such, the feature is disabled by default
in (and should remain so), for the aforementioned older QEMU
verions. Starting with QEMU v2.9.1, vhost-iommu-support can
safely be enabled, even without having an IOMMU device, with
no performance penalty.
This patch adds a new global config option, vhost-iommu-support,
that controls enablement of the vhost IOMMU feature:
ovs-vsctl set Open_vSwitch . other_config:vhost-iommu-support=true
This value defaults to false; to enable IOMMU support, this field
should be set to true when setting other global parameters on init
(such as "dpdk-socket-mem", for example). Changing the value at
runtime is not supported, and requires restarting the vswitch daemon.
Signed-off-by: Mark Kavanagh <mark.b.kavanagh@intel.com>
Acked-by: Kevin Traynor <ktraynor@redhat.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
2017-12-08 10:53:47 +00:00
|
|
|
vhost_iommu_enabled = smap_get_bool(ovs_other_config,
|
|
|
|
"vhost-iommu-support", false);
|
|
|
|
VLOG_INFO("IOMMU support for vhost-user-client %s.",
|
|
|
|
vhost_iommu_enabled ? "enabled" : "disabled");
|
|
|
|
|
2019-05-14 16:08:43 +03:00
|
|
|
vhost_postcopy_enabled = smap_get_bool(ovs_other_config,
|
|
|
|
"vhost-postcopy-support", false);
|
|
|
|
if (vhost_postcopy_enabled && memory_locked()) {
|
|
|
|
VLOG_WARN("vhost-postcopy-support and mlockall are not compatible.");
|
|
|
|
vhost_postcopy_enabled = false;
|
|
|
|
}
|
|
|
|
VLOG_INFO("POSTCOPY support for vhost-user-client %s.",
|
|
|
|
vhost_postcopy_enabled ? "enabled" : "disabled");
|
|
|
|
|
2018-06-27 14:58:31 +01:00
|
|
|
per_port_memory = smap_get_bool(ovs_other_config,
|
|
|
|
"per-port-memory", false);
|
|
|
|
VLOG_INFO("Per port memory for DPDK devices %s.",
|
|
|
|
per_port_memory ? "enabled" : "disabled");
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
svec_add(&args, ovs_get_program_name());
|
|
|
|
construct_dpdk_args(ovs_other_config, &args);
|
2016-10-04 17:58:05 -07:00
|
|
|
|
dpdk: Limit DPDK memory usage.
Since 18.05 release, DPDK moved to dynamic memory model in which
hugepages could be allocated on demand. At the same time '--socket-mem'
option was re-defined as a size of pre-allocated memory, i.e. memory
that should be allocated at startup and could not be freed.
So, DPDK with a new memory model could allocate more hugepage memory
than specified in '--socket-mem' or '-m' options.
This change adds new configurable 'other_config:dpdk-socket-limit'
which could be used to limit the ammount of memory DPDK could use.
It uses new DPDK option '--socket-limit'.
Ex.:
ovs-vsctl set Open_vSwitch . other_config:dpdk-socket-limit="1024,1024"
Also, in order to preserve old behaviour, if '--socket-limit' is not
specified, it will be defaulted to the amount of memory specified by
'--socket-mem' option, i.e. OVS will not be able to allocate more.
This is needed, for example, to disallow OVS to allocate more memory
than reserved for it by Nova in OpenStack installations.
Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
2019-01-29 11:11:50 +03:00
|
|
|
if (!args_contains(&args, "--legacy-mem")
|
|
|
|
&& !args_contains(&args, "--socket-limit")) {
|
|
|
|
const char *arg;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
SVEC_FOR_EACH (i, arg, &args) {
|
|
|
|
if (!strcmp(arg, "--socket-mem")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < args.n - 1) {
|
|
|
|
svec_add(&args, "--socket-limit");
|
|
|
|
svec_add(&args, args.names[i + 1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
if (args_contains(&args, "-c") || args_contains(&args, "-l")) {
|
|
|
|
auto_determine = false;
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* NOTE: This is an unsophisticated mechanism for determining the DPDK
|
|
|
|
* lcore for the DPDK Master.
|
|
|
|
*/
|
|
|
|
if (auto_determine) {
|
2019-08-13 14:28:26 +03:00
|
|
|
const struct ovs_numa_info_core *core;
|
2019-01-29 11:11:49 +03:00
|
|
|
int cpu = 0;
|
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
/* Get the main thread affinity */
|
2019-08-13 14:28:26 +03:00
|
|
|
affinity = ovs_numa_thread_getaffinity_dump();
|
|
|
|
if (affinity) {
|
|
|
|
cpu = INT_MAX;
|
|
|
|
FOR_EACH_CORE_ON_DUMP (core, affinity) {
|
|
|
|
if (cpu > core->core_id) {
|
|
|
|
cpu = core->core_id;
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* User did not set dpdk-lcore-mask and unable to get current
|
2019-01-29 11:11:49 +03:00
|
|
|
* thread affintity - default to core #0 */
|
2019-08-13 14:28:26 +03:00
|
|
|
VLOG_ERR("Thread getaffinity failed. Using core #0");
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
2019-01-29 11:11:49 +03:00
|
|
|
svec_add(&args, "-l");
|
|
|
|
svec_add_nocopy(&args, xasprintf("%d", cpu));
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
svec_terminate(&args);
|
2016-10-04 17:58:05 -07:00
|
|
|
|
|
|
|
optind = 1;
|
|
|
|
|
|
|
|
if (VLOG_IS_INFO_ENABLED()) {
|
2019-01-29 11:11:49 +03:00
|
|
|
struct ds eal_args = DS_EMPTY_INITIALIZER;
|
|
|
|
char *joined_args = svec_join(&args, " ", ".");
|
|
|
|
|
|
|
|
ds_put_format(&eal_args, "EAL ARGS: %s", joined_args);
|
2016-10-04 17:58:05 -07:00
|
|
|
VLOG_INFO("%s", ds_cstr_ro(&eal_args));
|
|
|
|
ds_destroy(&eal_args);
|
2019-01-29 11:11:49 +03:00
|
|
|
free(joined_args);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
2019-01-29 11:11:49 +03:00
|
|
|
/* Copy because 'rte_eal_init' will change the argv, i.e. it will remove
|
|
|
|
* some arguments from it. '+1' to copy the terminating NULL. */
|
|
|
|
argv = xmemdup(args.names, (args.n + 1) * sizeof args.names[0]);
|
2016-12-09 11:22:27 -05:00
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
/* Make sure things are initialized ... */
|
2019-01-29 11:11:49 +03:00
|
|
|
result = rte_eal_init(args.n, argv);
|
|
|
|
|
|
|
|
free(argv);
|
|
|
|
svec_destroy(&args);
|
2016-10-04 17:58:05 -07:00
|
|
|
|
|
|
|
/* Set the main thread affinity back to pre rte_eal_init() value */
|
2019-08-13 14:28:26 +03:00
|
|
|
if (affinity) {
|
|
|
|
ovs_numa_thread_setaffinity_dump(affinity);
|
|
|
|
ovs_numa_dump_destroy(affinity);
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
2018-05-03 15:08:00 -04:00
|
|
|
if (result < 0) {
|
|
|
|
VLOG_EMER("Unable to initialize DPDK: %s", ovs_strerror(rte_errno));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-03-14 17:43:48 +03:00
|
|
|
if (VLOG_IS_DBG_ENABLED()) {
|
|
|
|
size_t size;
|
|
|
|
char *response = NULL;
|
|
|
|
FILE *stream = open_memstream(&response, &size);
|
|
|
|
|
|
|
|
if (stream) {
|
dpdk: Add commands to configure log levels.
Enabling debug logs in dpdk can be a challenge to be sure of what is
actually enabled, add commands to list and change those log levels.
However, these commands do not help when tracking issues in dpdk init
itself: dump log levels right after init.
Example:
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is info
id 1: lib.malloc, level is info
id 2: lib.ring, level is info
id 3: lib.mempool, level is info
id 4: lib.timer, level is info
id 5: pmd, level is info
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is info
[...]
$ ovs-appctl dpdk/log-set debug pmd.*:notice
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is debug
id 1: lib.malloc, level is debug
id 2: lib.ring, level is debug
id 3: lib.mempool, level is debug
id 4: lib.timer, level is debug
id 5: pmd, level is debug
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is notice
[...]
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2020-07-13 10:06:21 +02:00
|
|
|
fprintf(stream, "rte_memzone_dump:\n");
|
2019-03-14 17:43:48 +03:00
|
|
|
rte_memzone_dump(stream);
|
dpdk: Add commands to configure log levels.
Enabling debug logs in dpdk can be a challenge to be sure of what is
actually enabled, add commands to list and change those log levels.
However, these commands do not help when tracking issues in dpdk init
itself: dump log levels right after init.
Example:
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is info
id 1: lib.malloc, level is info
id 2: lib.ring, level is info
id 3: lib.mempool, level is info
id 4: lib.timer, level is info
id 5: pmd, level is info
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is info
[...]
$ ovs-appctl dpdk/log-set debug pmd.*:notice
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is debug
id 1: lib.malloc, level is debug
id 2: lib.ring, level is debug
id 3: lib.mempool, level is debug
id 4: lib.timer, level is debug
id 5: pmd, level is debug
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is notice
[...]
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2020-07-13 10:06:21 +02:00
|
|
|
fprintf(stream, "rte_log_dump:\n");
|
|
|
|
rte_log_dump(stream);
|
2019-03-14 17:43:48 +03:00
|
|
|
fclose(stream);
|
dpdk: Add commands to configure log levels.
Enabling debug logs in dpdk can be a challenge to be sure of what is
actually enabled, add commands to list and change those log levels.
However, these commands do not help when tracking issues in dpdk init
itself: dump log levels right after init.
Example:
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is info
id 1: lib.malloc, level is info
id 2: lib.ring, level is info
id 3: lib.mempool, level is info
id 4: lib.timer, level is info
id 5: pmd, level is info
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is info
[...]
$ ovs-appctl dpdk/log-set debug pmd.*:notice
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is debug
id 1: lib.malloc, level is debug
id 2: lib.ring, level is debug
id 3: lib.mempool, level is debug
id 4: lib.timer, level is debug
id 5: pmd, level is debug
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is notice
[...]
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2020-07-13 10:06:21 +02:00
|
|
|
VLOG_DBG("%s", response);
|
2019-03-14 17:43:48 +03:00
|
|
|
free(response);
|
|
|
|
} else {
|
dpdk: Add commands to configure log levels.
Enabling debug logs in dpdk can be a challenge to be sure of what is
actually enabled, add commands to list and change those log levels.
However, these commands do not help when tracking issues in dpdk init
itself: dump log levels right after init.
Example:
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is info
id 1: lib.malloc, level is info
id 2: lib.ring, level is info
id 3: lib.mempool, level is info
id 4: lib.timer, level is info
id 5: pmd, level is info
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is info
[...]
$ ovs-appctl dpdk/log-set debug pmd.*:notice
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is debug
id 1: lib.malloc, level is debug
id 2: lib.ring, level is debug
id 3: lib.mempool, level is debug
id 4: lib.timer, level is debug
id 5: pmd, level is debug
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is notice
[...]
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2020-07-13 10:06:21 +02:00
|
|
|
VLOG_DBG("Could not dump memzone and log levels. "
|
|
|
|
"Unable to open memstream: %s.", ovs_strerror(errno));
|
2019-03-14 17:43:48 +03:00
|
|
|
}
|
|
|
|
}
|
2016-10-04 17:58:05 -07:00
|
|
|
|
dpdk: Add commands to configure log levels.
Enabling debug logs in dpdk can be a challenge to be sure of what is
actually enabled, add commands to list and change those log levels.
However, these commands do not help when tracking issues in dpdk init
itself: dump log levels right after init.
Example:
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is info
id 1: lib.malloc, level is info
id 2: lib.ring, level is info
id 3: lib.mempool, level is info
id 4: lib.timer, level is info
id 5: pmd, level is info
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is info
[...]
$ ovs-appctl dpdk/log-set debug pmd.*:notice
$ ovs-appctl dpdk/log-list
global log level is debug
id 0: lib.eal, level is debug
id 1: lib.malloc, level is debug
id 2: lib.ring, level is debug
id 3: lib.mempool, level is debug
id 4: lib.timer, level is debug
id 5: pmd, level is debug
[...]
id 37: pmd.net.bnxt.driver, level is notice
id 38: pmd.net.e1000.init, level is notice
id 39: pmd.net.e1000.driver, level is notice
id 40: pmd.net.enic, level is notice
[...]
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
2020-07-13 10:06:21 +02:00
|
|
|
unixctl_command_register("dpdk/log-list", "", 0, 0,
|
|
|
|
dpdk_unixctl_mem_stream, rte_log_dump);
|
|
|
|
unixctl_command_register("dpdk/log-set", "{level | pattern:level}", 0,
|
|
|
|
INT_MAX, dpdk_unixctl_log_set, NULL);
|
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
/* We are called from the main thread here */
|
|
|
|
RTE_PER_LCORE(_lcore_id) = NON_PMD_CORE_ID;
|
|
|
|
|
|
|
|
/* Finally, register the dpdk classes */
|
|
|
|
netdev_dpdk_register();
|
2019-05-07 12:24:09 +03:00
|
|
|
netdev_register_flow_api_provider(&netdev_offload_dpdk);
|
2018-05-03 15:08:00 -04:00
|
|
|
return true;
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dpdk_init(const struct smap *ovs_other_config)
|
|
|
|
{
|
2016-10-04 17:58:05 -07:00
|
|
|
static bool enabled = false;
|
|
|
|
|
|
|
|
if (enabled || !ovs_other_config) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:08:01 -04:00
|
|
|
const char *dpdk_init_val = smap_get_def(ovs_other_config, "dpdk-init",
|
|
|
|
"false");
|
|
|
|
|
2019-03-01 14:59:33 +03:00
|
|
|
bool try_only = !strcasecmp(dpdk_init_val, "try");
|
|
|
|
if (!strcasecmp(dpdk_init_val, "true") || try_only) {
|
2016-10-04 17:58:05 -07:00
|
|
|
static struct ovsthread_once once_enable = OVSTHREAD_ONCE_INITIALIZER;
|
2016-10-04 17:58:05 -07:00
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
if (ovsthread_once_start(&once_enable)) {
|
2018-01-15 19:21:12 +01:00
|
|
|
VLOG_INFO("Using %s", rte_version());
|
2016-10-04 17:58:05 -07:00
|
|
|
VLOG_INFO("DPDK Enabled - initializing...");
|
2018-05-03 15:08:00 -04:00
|
|
|
enabled = dpdk_init__(ovs_other_config);
|
|
|
|
if (enabled) {
|
|
|
|
VLOG_INFO("DPDK Enabled - initialized");
|
2018-05-03 15:08:01 -04:00
|
|
|
} else if (!try_only) {
|
2018-05-03 15:08:00 -04:00
|
|
|
ovs_abort(rte_errno, "Cannot init EAL");
|
|
|
|
}
|
2016-10-04 17:58:05 -07:00
|
|
|
ovsthread_once_done(&once_enable);
|
2018-05-03 15:08:00 -04:00
|
|
|
} else {
|
|
|
|
VLOG_ERR_ONCE("DPDK Initialization Failed.");
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
} else {
|
2017-03-08 15:44:39 -08:00
|
|
|
VLOG_INFO_ONCE("DPDK Disabled - Use other_config:dpdk-init to enable");
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
2018-05-03 15:08:01 -04:00
|
|
|
dpdk_initialized = enabled;
|
2016-10-04 17:58:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
dpdk_get_vhost_sock_dir(void)
|
|
|
|
{
|
|
|
|
return vhost_sock_dir;
|
|
|
|
}
|
|
|
|
|
netdev-dpdk: vHost IOMMU support
DPDK v17.11 introduces support for the vHost IOMMU feature.
This is a security feature, which restricts the vhost memory
that a virtio device may access.
This feature also enables the vhost REPLY_ACK protocol, the
implementation of which is known to work in newer versions of
QEMU (i.e. v2.10.0), but is buggy in older versions (v2.7.0 -
v2.9.0, inclusive). As such, the feature is disabled by default
in (and should remain so), for the aforementioned older QEMU
verions. Starting with QEMU v2.9.1, vhost-iommu-support can
safely be enabled, even without having an IOMMU device, with
no performance penalty.
This patch adds a new global config option, vhost-iommu-support,
that controls enablement of the vhost IOMMU feature:
ovs-vsctl set Open_vSwitch . other_config:vhost-iommu-support=true
This value defaults to false; to enable IOMMU support, this field
should be set to true when setting other global parameters on init
(such as "dpdk-socket-mem", for example). Changing the value at
runtime is not supported, and requires restarting the vswitch daemon.
Signed-off-by: Mark Kavanagh <mark.b.kavanagh@intel.com>
Acked-by: Kevin Traynor <ktraynor@redhat.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
2017-12-08 10:53:47 +00:00
|
|
|
bool
|
|
|
|
dpdk_vhost_iommu_enabled(void)
|
|
|
|
{
|
|
|
|
return vhost_iommu_enabled;
|
|
|
|
}
|
|
|
|
|
2019-05-14 16:08:43 +03:00
|
|
|
bool
|
|
|
|
dpdk_vhost_postcopy_enabled(void)
|
|
|
|
{
|
|
|
|
return vhost_postcopy_enabled;
|
|
|
|
}
|
|
|
|
|
2018-06-27 14:58:31 +01:00
|
|
|
bool
|
|
|
|
dpdk_per_port_memory(void)
|
|
|
|
{
|
|
|
|
return per_port_memory;
|
|
|
|
}
|
|
|
|
|
2019-07-05 08:43:15 -04:00
|
|
|
bool
|
|
|
|
dpdk_available(void)
|
|
|
|
{
|
|
|
|
return dpdk_initialized;
|
|
|
|
}
|
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
void
|
|
|
|
dpdk_set_lcore_id(unsigned cpu)
|
|
|
|
{
|
|
|
|
/* NON_PMD_CORE_ID is reserved for use by non pmd threads. */
|
|
|
|
ovs_assert(cpu != NON_PMD_CORE_ID);
|
|
|
|
RTE_PER_LCORE(_lcore_id) = cpu;
|
|
|
|
}
|
2018-01-15 19:21:12 +01:00
|
|
|
|
|
|
|
void
|
|
|
|
print_dpdk_version(void)
|
|
|
|
{
|
|
|
|
puts(rte_version());
|
|
|
|
}
|
2018-05-03 15:08:01 -04:00
|
|
|
|
2020-07-13 13:42:13 +01:00
|
|
|
#define CHECK_CPU_FEATURE(feature, name_str, RTE_CPUFLAG) \
|
|
|
|
do { \
|
|
|
|
if (strncmp(feature, name_str, strlen(name_str)) == 0) { \
|
|
|
|
int has_isa = rte_cpu_get_flag_enabled(RTE_CPUFLAG); \
|
|
|
|
VLOG_DBG("CPU flag %s, available %s\n", name_str, \
|
|
|
|
has_isa ? "yes" : "no"); \
|
|
|
|
return true; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
bool
|
|
|
|
dpdk_get_cpu_has_isa(const char *arch, const char *feature)
|
|
|
|
{
|
|
|
|
/* Ensure Arch is x86_64. */
|
|
|
|
if (strncmp(arch, "x86_64", 6) != 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if __x86_64__
|
|
|
|
/* CPU flags only defined for the architecture that support it. */
|
|
|
|
CHECK_CPU_FEATURE(feature, "avx512f", RTE_CPUFLAG_AVX512F);
|
|
|
|
CHECK_CPU_FEATURE(feature, "bmi2", RTE_CPUFLAG_BMI2);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
VLOG_WARN("Unknown CPU arch,feature: %s,%s. Returning not supported.\n",
|
|
|
|
arch, feature);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:08:01 -04:00
|
|
|
void
|
|
|
|
dpdk_status(const struct ovsrec_open_vswitch *cfg)
|
|
|
|
{
|
|
|
|
if (cfg) {
|
|
|
|
ovsrec_open_vswitch_set_dpdk_initialized(cfg, dpdk_initialized);
|
|
|
|
ovsrec_open_vswitch_set_dpdk_version(cfg, rte_version());
|
|
|
|
}
|
|
|
|
}
|