351 lines
10 KiB
Diff
351 lines
10 KiB
Diff
Description: eal: provide option to set vhost_user socket owner/permissions
|
|
|
|
The API doesn't hold a way to specify a owner/permission set for vhost_user
|
|
created sockets.
|
|
|
|
Projects consuming DPDK started to do 'their own workarounds' like openvswitch
|
|
https://patchwork.ozlabs.org/patch/559043/
|
|
https://patchwork.ozlabs.org/patch/559045/
|
|
But for this specific example they are blocked/stalled behind a bigger
|
|
rework (https://patchwork.ozlabs.org/patch/604898/).
|
|
|
|
We need something now for existing code linking against DPDK. That implies to
|
|
avoid changing API/ABI. So I created a DPDK EAL commandline option based ideas
|
|
in the former patches.
|
|
|
|
Fixes LP: #1546565
|
|
|
|
Forwarded: yes
|
|
Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
|
|
Last-Update: 2016-04-24
|
|
|
|
Index: dpdk/lib/librte_eal/common/eal_common_options.c
|
|
===================================================================
|
|
--- dpdk.orig/lib/librte_eal/common/eal_common_options.c
|
|
+++ dpdk/lib/librte_eal/common/eal_common_options.c
|
|
@@ -95,6 +95,8 @@ eal_long_options[] = {
|
|
{OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM },
|
|
{OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM },
|
|
{OPT_XEN_DOM0, 0, NULL, OPT_XEN_DOM0_NUM },
|
|
+ {OPT_VHOST_OWNER, 1, NULL, OPT_VHOST_OWNER_NUM },
|
|
+ {OPT_VHOST_PERM, 1, NULL, OPT_VHOST_PERM_NUM },
|
|
{0, 0, NULL, 0 }
|
|
};
|
|
|
|
@@ -153,6 +155,8 @@ eal_reset_internal_config(struct interna
|
|
#endif
|
|
internal_cfg->vmware_tsc_map = 0;
|
|
internal_cfg->create_uio_dev = 0;
|
|
+ internal_cfg->vhost_sock_owner = NULL;
|
|
+ internal_cfg->vhost_sock_perm = NULL;
|
|
}
|
|
|
|
static int
|
|
Index: dpdk/lib/librte_eal/common/eal_internal_cfg.h
|
|
===================================================================
|
|
--- dpdk.orig/lib/librte_eal/common/eal_internal_cfg.h
|
|
+++ dpdk/lib/librte_eal/common/eal_internal_cfg.h
|
|
@@ -83,6 +83,8 @@ struct internal_config {
|
|
volatile enum rte_intr_mode vfio_intr_mode;
|
|
const char *hugefile_prefix; /**< the base filename of hugetlbfs files */
|
|
const char *hugepage_dir; /**< specific hugetlbfs directory to use */
|
|
+ const char *vhost_sock_owner; /**< owner:group of vhost_user sockets */
|
|
+ const char *vhost_sock_perm; /**< permissions of vhost_user sockets */
|
|
|
|
unsigned num_hugepage_sizes; /**< how many sizes on this system */
|
|
struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES];
|
|
Index: dpdk/lib/librte_eal/common/eal_options.h
|
|
===================================================================
|
|
--- dpdk.orig/lib/librte_eal/common/eal_options.h
|
|
+++ dpdk/lib/librte_eal/common/eal_options.h
|
|
@@ -83,6 +83,10 @@ enum {
|
|
OPT_VMWARE_TSC_MAP_NUM,
|
|
#define OPT_XEN_DOM0 "xen-dom0"
|
|
OPT_XEN_DOM0_NUM,
|
|
+#define OPT_VHOST_OWNER "vhost-owner"
|
|
+ OPT_VHOST_OWNER_NUM,
|
|
+#define OPT_VHOST_PERM "vhost-perm"
|
|
+ OPT_VHOST_PERM_NUM,
|
|
OPT_LONG_MAX_NUM
|
|
};
|
|
|
|
Index: dpdk/lib/librte_vhost/vhost_user/vhost-net-user.c
|
|
===================================================================
|
|
--- dpdk.orig/lib/librte_vhost/vhost_user/vhost-net-user.c
|
|
+++ dpdk/lib/librte_vhost/vhost_user/vhost-net-user.c
|
|
@@ -51,6 +51,8 @@
|
|
#include "vhost-net.h"
|
|
#include "virtio-net-user.h"
|
|
|
|
+#include <rte_eal.h>
|
|
+
|
|
#define MAX_VIRTIO_BACKLOG 128
|
|
|
|
static void vserver_new_vq_conn(int fd, void *data, int *remove);
|
|
@@ -482,6 +484,8 @@ rte_vhost_driver_register(const char *pa
|
|
return -1;
|
|
}
|
|
|
|
+ rte_eal_set_socket_permissions(path);
|
|
+
|
|
vserver->path = strdup(path);
|
|
vserver->fh = -1;
|
|
|
|
Index: dpdk/lib/librte_eal/linuxapp/eal/eal.c
|
|
===================================================================
|
|
--- dpdk.orig/lib/librte_eal/linuxapp/eal/eal.c
|
|
+++ dpdk/lib/librte_eal/linuxapp/eal/eal.c
|
|
@@ -53,6 +53,9 @@
|
|
#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686)
|
|
#include <sys/io.h>
|
|
#endif
|
|
+#include <sys/types.h>
|
|
+#include <pwd.h>
|
|
+#include <grp.h>
|
|
|
|
#include <rte_common.h>
|
|
#include <rte_debug.h>
|
|
@@ -343,6 +346,8 @@ eal_usage(const char *prgname)
|
|
" --"OPT_CREATE_UIO_DEV" Create /dev/uioX (usually done by hotplug)\n"
|
|
" --"OPT_VFIO_INTR" Interrupt mode for VFIO (legacy|msi|msix)\n"
|
|
" --"OPT_XEN_DOM0" Support running on Xen dom0 without hugetlbfs\n"
|
|
+ " --"OPT_VHOST_OWNER" Create vhost-user sockets with this owner:group\n"
|
|
+ " --"OPT_VHOST_PERM" Create vhost-user sockets with these permissions\n"
|
|
"\n");
|
|
/* Allow the application to print its usage message too if hook is set */
|
|
if ( rte_application_usage_hook ) {
|
|
@@ -618,6 +623,14 @@ eal_parse_args(int argc, char **argv)
|
|
internal_config.create_uio_dev = 1;
|
|
break;
|
|
|
|
+ case OPT_VHOST_OWNER_NUM:
|
|
+ internal_config.vhost_sock_owner = optarg;
|
|
+ break;
|
|
+
|
|
+ case OPT_VHOST_PERM_NUM:
|
|
+ internal_config.vhost_sock_perm = optarg;
|
|
+ break;
|
|
+
|
|
default:
|
|
if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
|
|
RTE_LOG(ERR, EAL, "Option %c is not supported "
|
|
@@ -932,3 +945,172 @@ rte_eal_check_module(const char *module_
|
|
/* Module has been found */
|
|
return 1;
|
|
}
|
|
+
|
|
+/* Try to double the size of '*buf', return true
|
|
+ * if successful, and '*sizep' will be updated with
|
|
+ * the new size. Otherwise, return false. */
|
|
+static int
|
|
+enlarge_buffer(char **buf, size_t *sizep)
|
|
+{
|
|
+ size_t newsize = *sizep * 2;
|
|
+
|
|
+ if (newsize > *sizep) {
|
|
+ *buf = realloc(*buf, newsize);
|
|
+ *sizep = newsize;
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+get_owners_from_str(const char *user_spec, uid_t *uid, gid_t *gid)
|
|
+{
|
|
+ size_t bufsize = 4096;
|
|
+
|
|
+ char *pos = strchr(user_spec, ':');
|
|
+ user_spec += strspn(user_spec, " \t\r\n");
|
|
+ size_t len = pos ? (size_t)(pos - user_spec) : strlen(user_spec);
|
|
+
|
|
+ char *buf = NULL;
|
|
+ struct passwd pwd, *res;
|
|
+ int e;
|
|
+
|
|
+ buf = malloc(bufsize);
|
|
+ char *user_search = NULL;
|
|
+ if (len) {
|
|
+ user_search = malloc(len + 1);
|
|
+ memcpy(user_search, user_spec, len);
|
|
+ user_search[len] = '\0';
|
|
+ while ((e = getpwnam_r(user_search, &pwd, buf, bufsize, &res)) == ERANGE) {
|
|
+ if (!enlarge_buffer(&buf, &bufsize)) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (e != 0) {
|
|
+ RTE_LOG(ERR, EAL,"Failed to retrive user %s's uid (%s), aborting.",
|
|
+ user_search, strerror(e));
|
|
+ goto release;
|
|
+ }
|
|
+ if (res == NULL) {
|
|
+ RTE_LOG(ERR, EAL,"user %s not found, aborting.",
|
|
+ user_search);
|
|
+ e = -1;
|
|
+ goto release;
|
|
+ }
|
|
+ } else {
|
|
+ /* User name is not specified, use current user. */
|
|
+ while ((e = getpwuid_r(getuid(), &pwd, buf, bufsize, &res)) == ERANGE) {
|
|
+ if (!enlarge_buffer(&buf, &bufsize)) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (e != 0) {
|
|
+ RTE_LOG(ERR, EAL,"Failed to retrive current user's uid "
|
|
+ "(%s), aborting.", strerror(e));
|
|
+ goto release;
|
|
+ }
|
|
+ user_search = strdup(pwd.pw_name);
|
|
+ }
|
|
+
|
|
+ if (uid)
|
|
+ *uid = pwd.pw_uid;
|
|
+
|
|
+ free(buf);
|
|
+ buf = NULL;
|
|
+
|
|
+ if (pos) {
|
|
+ char *grpstr = pos + 1;
|
|
+ grpstr += strspn(grpstr, " \t\r\n");
|
|
+
|
|
+ if (*grpstr) {
|
|
+ struct group grp, *res;
|
|
+
|
|
+ bufsize = 4096;
|
|
+ buf = malloc(bufsize);
|
|
+ while ((e = getgrnam_r(grpstr, &grp, buf, bufsize, &res))
|
|
+ == ERANGE) {
|
|
+ if (!enlarge_buffer(&buf, &bufsize)) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (e) {
|
|
+ RTE_LOG(ERR, EAL,"Failed to get group entry for %s, "
|
|
+ "(%s), aborting.", grpstr,
|
|
+ strerror(e));
|
|
+ goto release;
|
|
+ }
|
|
+ if (res == NULL) {
|
|
+ RTE_LOG(ERR, EAL,"Group %s not found, aborting.",
|
|
+ grpstr);
|
|
+ e = -1;
|
|
+ goto release;
|
|
+ }
|
|
+
|
|
+ if (gid)
|
|
+ *gid = grp.gr_gid;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ release:
|
|
+ free(buf);
|
|
+ free(user_search);
|
|
+ return e;
|
|
+}
|
|
+
|
|
+static void
|
|
+vhost_set_permissions(const char *vhost_sock_location)
|
|
+{
|
|
+ unsigned long int mode = strtoul(internal_config.vhost_sock_perm, NULL, 0);
|
|
+ int err = chmod(vhost_sock_location, (mode_t)mode);
|
|
+ if (err) {
|
|
+ RTE_LOG(ERR, EAL,"vhost-user socket cannot set"
|
|
+ " permissions to %s (%s).\n",
|
|
+ internal_config.vhost_sock_perm, strerror(err));
|
|
+ return;
|
|
+ }
|
|
+ RTE_LOG(INFO, EAL,"Socket %s changed permissions"
|
|
+ " to %s\n", vhost_sock_location,
|
|
+ internal_config.vhost_sock_perm);
|
|
+}
|
|
+
|
|
+static void
|
|
+vhost_set_ownership(const char *vhost_sock_location)
|
|
+{
|
|
+ uid_t vhuid=0;
|
|
+ gid_t vhgid=0;
|
|
+
|
|
+ if (get_owners_from_str(internal_config.vhost_sock_owner, &vhuid, &vhgid)) {
|
|
+ RTE_LOG(ERR, EAL,"vhost-user socket unable to get"
|
|
+ " specified user/group: %s\n",
|
|
+ internal_config.vhost_sock_owner);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ int err = chown(vhost_sock_location, vhuid, vhgid);
|
|
+ if (err) {
|
|
+ RTE_LOG(ERR, EAL,"vhost-user socket unable to set"
|
|
+ " ownership to %s (%s).\n",
|
|
+ internal_config.vhost_sock_owner, strerror(err));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ RTE_LOG(INFO, EAL,"Socket %s changed ownership"
|
|
+ " to %s.\n", vhost_sock_location,
|
|
+ internal_config.vhost_sock_owner);
|
|
+}
|
|
+
|
|
+void
|
|
+rte_eal_set_socket_permissions(const char *path)
|
|
+{
|
|
+ if (internal_config.vhost_sock_perm) {
|
|
+ vhost_set_permissions(path);
|
|
+ }
|
|
+
|
|
+ if (internal_config.vhost_sock_owner) {
|
|
+ vhost_set_ownership(path);
|
|
+ }
|
|
+}
|
|
Index: dpdk/lib/librte_eal/common/include/rte_eal.h
|
|
===================================================================
|
|
--- dpdk.orig/lib/librte_eal/common/include/rte_eal.h
|
|
+++ dpdk/lib/librte_eal/common/include/rte_eal.h
|
|
@@ -234,6 +234,11 @@ static inline int rte_gettid(void)
|
|
return RTE_PER_LCORE(_thread_id);
|
|
}
|
|
|
|
+/**
|
|
+ * Set owner/permissions on sockets if requested on EAL commandline
|
|
+ */
|
|
+void rte_eal_set_socket_permissions(const char *);
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
Index: dpdk/doc/guides/testpmd_app_ug/run_app.rst
|
|
===================================================================
|
|
--- dpdk.orig/doc/guides/testpmd_app_ug/run_app.rst
|
|
+++ dpdk/doc/guides/testpmd_app_ug/run_app.rst
|
|
@@ -156,6 +156,25 @@ See the DPDK Getting Started Guides for
|
|
|
|
Use malloc instead of hugetlbfs.
|
|
|
|
+* ``--vhost-owner``
|
|
+
|
|
+ When creating vhost_user sockets change owner and group to the specified value.
|
|
+ This can be given as ``user:group``, but also only ``user`` or ``:group`` are supported.
|
|
+
|
|
+ Examples::
|
|
+
|
|
+ --vhost-owner 'libvirt-qemu:kvm'
|
|
+ --vhost-owner 'libvirt-qemu'
|
|
+ --vhost-owner ':kvm'
|
|
+
|
|
+* ``--vhost-perm``
|
|
+
|
|
+ When creating vhost_user sockets set them up with these permissions.
|
|
+
|
|
+ For example::
|
|
+
|
|
+ --vhost-perm '0664'
|
|
+
|
|
|
|
Testpmd Command-line Options
|
|
----------------------------
|