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>
|
|
|
|
|
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-13 18:27:51 +01:00
|
|
|
#ifdef DPDK_PDUMP
|
|
|
|
#include <rte_mempool.h>
|
|
|
|
#include <rte_pdump.h>
|
|
|
|
#endif
|
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"
|
|
|
|
#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"
|
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 */
|
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-lcore-mask", "-c", false, NULL},
|
|
|
|
{"dpdk-hugepage-dir", "--huge-dir", false, NULL},
|
|
|
|
};
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
char *str = xmemdup0(buf, 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:
|
2018-03-23 12:56:53 +03:00
|
|
|
VLOG_DBG_RL(&dbg_rl, "%s", str);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_INFO:
|
|
|
|
case RTE_LOG_NOTICE:
|
2018-03-23 12:56:53 +03:00
|
|
|
VLOG_INFO_RL(&rl, "%s", str);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_WARNING:
|
2018-03-23 12:56:53 +03:00
|
|
|
VLOG_WARN_RL(&rl, "%s", str);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_ERR:
|
2018-03-23 12:56:53 +03:00
|
|
|
VLOG_ERR_RL(&rl, "%s", str);
|
2017-03-06 09:49:11 +03:00
|
|
|
break;
|
|
|
|
case RTE_LOG_CRIT:
|
|
|
|
case RTE_LOG_ALERT:
|
|
|
|
case RTE_LOG_EMERG:
|
|
|
|
VLOG_EMER("%s", str);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
OVS_NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
|
|
|
free(str);
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static cookie_io_functions_t dpdk_log_func = {
|
|
|
|
.write = dpdk_log_write,
|
|
|
|
};
|
|
|
|
|
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;
|
|
|
|
cpu_set_t cpuset;
|
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");
|
|
|
|
|
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
|
|
|
|
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-01-29 11:11:49 +03:00
|
|
|
int cpu = 0;
|
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
/* Get the main thread affinity */
|
|
|
|
CPU_ZERO(&cpuset);
|
|
|
|
err = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
|
|
|
|
&cpuset);
|
|
|
|
if (!err) {
|
2019-01-29 11:11:49 +03:00
|
|
|
for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
|
|
|
|
if (CPU_ISSET(cpu, &cpuset)) {
|
|
|
|
break;
|
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 */
|
|
|
|
VLOG_ERR("Thread getaffinity error %d. Using core #0", err);
|
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 */
|
|
|
|
if (auto_determine && !err) {
|
|
|
|
err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t),
|
|
|
|
&cpuset);
|
|
|
|
if (err) {
|
|
|
|
VLOG_ERR("Thread setaffinity error %d", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-03 15:08:00 -04:00
|
|
|
if (result < 0) {
|
|
|
|
VLOG_EMER("Unable to initialize DPDK: %s", ovs_strerror(rte_errno));
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-10-04 17:58:05 -07:00
|
|
|
rte_memzone_dump(stdout);
|
|
|
|
|
|
|
|
/* We are called from the main thread here */
|
|
|
|
RTE_PER_LCORE(_lcore_id) = NON_PMD_CORE_ID;
|
|
|
|
|
|
|
|
#ifdef DPDK_PDUMP
|
|
|
|
VLOG_INFO("DPDK pdump packet capture enabled");
|
|
|
|
err = rte_pdump_init(ovs_rundir());
|
|
|
|
if (err) {
|
|
|
|
VLOG_INFO("Error initialising DPDK pdump");
|
|
|
|
rte_pdump_uninit();
|
|
|
|
} else {
|
|
|
|
char *server_socket_path;
|
|
|
|
|
|
|
|
server_socket_path = xasprintf("%s/%s", ovs_rundir(),
|
|
|
|
"pdump_server_socket");
|
|
|
|
fatal_signal_add_file_to_unlink(server_socket_path);
|
|
|
|
free(server_socket_path);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Finally, register the dpdk classes */
|
|
|
|
netdev_dpdk_register();
|
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");
|
|
|
|
|
|
|
|
bool try_only = !strcmp(dpdk_init_val, "try");
|
|
|
|
if (!strcmp(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;
|
|
|
|
}
|
|
|
|
|
2018-06-27 14:58:31 +01:00
|
|
|
bool
|
|
|
|
dpdk_per_port_memory(void)
|
|
|
|
{
|
|
|
|
return per_port_memory;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|