1 Description: eal: provide option to set vhost_user socket owner/permissions
3 The API doesn't hold a way to specify a owner/permission set for vhost_user
6 Projects consuming DPDK started to do 'their own workarounds' like openvswitch
7 https://patchwork.ozlabs.org/patch/559043/
8 https://patchwork.ozlabs.org/patch/559045/
9 But for this specific example they are blocked/stalled behind a bigger
10 rework (https://patchwork.ozlabs.org/patch/604898/).
12 We need something now for existing code linking against DPDK. That implies to
13 avoid changing API/ABI. So I created a DPDK EAL commandline option based ideas
14 in the former patches.
19 - with the split libs it now nees to be listed in
20 lib/librte_eal/linuxapp/eal/rte_eal_version.map to work on link steps
21 - please note that upstream gravitates towards not extending but creating a
22 new the API in DPDK as long term solution (will take a while)
23 - also as listed before most affected projects seem to create their own
25 So over time we have to check when we can drop it at the price of a config
26 transition - likely OVS 2.6 won't need it anymore.
29 Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
30 Last-Update: 2016-07-25
32 diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
33 index 7712bd2..28776b9 100644
34 --- a/doc/guides/testpmd_app_ug/run_app.rst
35 +++ b/doc/guides/testpmd_app_ug/run_app.rst
36 @@ -156,6 +156,25 @@ See the DPDK Getting Started Guides for more information on these options.
38 Use malloc instead of hugetlbfs.
42 + When creating vhost_user sockets change owner and group to the specified value.
43 + This can be given as ``user:group``, but also only ``user`` or ``:group`` are supported.
47 + --vhost-owner 'libvirt-qemu:kvm'
48 + --vhost-owner 'libvirt-qemu'
49 + --vhost-owner ':kvm'
53 + When creating vhost_user sockets set them up with these permissions.
60 Testpmd Command-line Options
61 ----------------------------
62 diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
63 index 481c732..2126140 100644
64 --- a/lib/librte_eal/common/eal_common_options.c
65 +++ b/lib/librte_eal/common/eal_common_options.c
66 @@ -95,6 +95,8 @@ eal_long_options[] = {
67 {OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM },
68 {OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM },
69 {OPT_XEN_DOM0, 0, NULL, OPT_XEN_DOM0_NUM },
70 + {OPT_VHOST_OWNER, 1, NULL, OPT_VHOST_OWNER_NUM },
71 + {OPT_VHOST_PERM, 1, NULL, OPT_VHOST_PERM_NUM },
75 @@ -166,6 +168,8 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
77 internal_cfg->vmware_tsc_map = 0;
78 internal_cfg->create_uio_dev = 0;
79 + internal_cfg->vhost_sock_owner = NULL;
80 + internal_cfg->vhost_sock_perm = NULL;
84 diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
85 index 5f1367e..bdf34e3 100644
86 --- a/lib/librte_eal/common/eal_internal_cfg.h
87 +++ b/lib/librte_eal/common/eal_internal_cfg.h
88 @@ -83,6 +83,8 @@ struct internal_config {
89 volatile enum rte_intr_mode vfio_intr_mode;
90 const char *hugefile_prefix; /**< the base filename of hugetlbfs files */
91 const char *hugepage_dir; /**< specific hugetlbfs directory to use */
92 + const char *vhost_sock_owner; /**< owner:group of vhost_user sockets */
93 + const char *vhost_sock_perm; /**< permissions of vhost_user sockets */
95 unsigned num_hugepage_sizes; /**< how many sizes on this system */
96 struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES];
97 diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
98 index a881c62..1161083 100644
99 --- a/lib/librte_eal/common/eal_options.h
100 +++ b/lib/librte_eal/common/eal_options.h
101 @@ -83,6 +83,10 @@ enum {
102 OPT_VMWARE_TSC_MAP_NUM,
103 #define OPT_XEN_DOM0 "xen-dom0"
105 +#define OPT_VHOST_OWNER "vhost-owner"
106 + OPT_VHOST_OWNER_NUM,
107 +#define OPT_VHOST_PERM "vhost-perm"
108 + OPT_VHOST_PERM_NUM,
112 diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
113 index a71d6f5..506cf24 100644
114 --- a/lib/librte_eal/common/include/rte_eal.h
115 +++ b/lib/librte_eal/common/include/rte_eal.h
116 @@ -252,6 +252,11 @@ static inline int rte_gettid(void)
117 return RTE_PER_LCORE(_thread_id);
121 + * Set owner/permissions on sockets if requested on EAL commandline
123 +void rte_eal_set_socket_permissions(const char *);
128 diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
129 index 3fb2188..dc84c5b 100644
130 --- a/lib/librte_eal/linuxapp/eal/eal.c
131 +++ b/lib/librte_eal/linuxapp/eal/eal.c
133 #if defined(RTE_ARCH_X86)
136 +#include <sys/types.h>
140 #include <rte_common.h>
141 #include <rte_debug.h>
142 @@ -344,6 +347,8 @@ eal_usage(const char *prgname)
143 " --"OPT_CREATE_UIO_DEV" Create /dev/uioX (usually done by hotplug)\n"
144 " --"OPT_VFIO_INTR" Interrupt mode for VFIO (legacy|msi|msix)\n"
145 " --"OPT_XEN_DOM0" Support running on Xen dom0 without hugetlbfs\n"
146 + " --"OPT_VHOST_OWNER" Create vhost-user sockets with this owner:group\n"
147 + " --"OPT_VHOST_PERM" Create vhost-user sockets with these permissions\n"
149 /* Allow the application to print its usage message too if hook is set */
150 if ( rte_application_usage_hook ) {
151 @@ -601,6 +606,14 @@ eal_parse_args(int argc, char **argv)
152 internal_config.create_uio_dev = 1;
155 + case OPT_VHOST_OWNER_NUM:
156 + internal_config.vhost_sock_owner = optarg;
159 + case OPT_VHOST_PERM_NUM:
160 + internal_config.vhost_sock_perm = optarg;
164 if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
165 RTE_LOG(ERR, EAL, "Option %c is not supported "
166 @@ -943,3 +956,172 @@ rte_eal_check_module(const char *module_name)
167 /* Module has been found */
171 +/* Try to double the size of '*buf', return true
172 + * if successful, and '*sizep' will be updated with
173 + * the new size. Otherwise, return false. */
175 +enlarge_buffer(char **buf, size_t *sizep)
177 + size_t newsize = *sizep * 2;
179 + if (newsize > *sizep) {
180 + *buf = realloc(*buf, newsize);
189 +get_owners_from_str(const char *user_spec, uid_t *uid, gid_t *gid)
191 + size_t bufsize = 4096;
193 + char *pos = strchr(user_spec, ':');
194 + user_spec += strspn(user_spec, " \t\r\n");
195 + size_t len = pos ? (size_t)(pos - user_spec) : strlen(user_spec);
198 + struct passwd pwd, *res;
201 + buf = malloc(bufsize);
202 + char *user_search = NULL;
204 + user_search = malloc(len + 1);
205 + memcpy(user_search, user_spec, len);
206 + user_search[len] = '\0';
207 + while ((e = getpwnam_r(user_search, &pwd, buf, bufsize, &res)) == ERANGE) {
208 + if (!enlarge_buffer(&buf, &bufsize)) {
214 + RTE_LOG(ERR, EAL,"Failed to retrive user %s's uid (%s), aborting.",
215 + user_search, strerror(e));
219 + RTE_LOG(ERR, EAL,"user %s not found, aborting.",
225 + /* User name is not specified, use current user. */
226 + while ((e = getpwuid_r(getuid(), &pwd, buf, bufsize, &res)) == ERANGE) {
227 + if (!enlarge_buffer(&buf, &bufsize)) {
233 + RTE_LOG(ERR, EAL,"Failed to retrive current user's uid "
234 + "(%s), aborting.", strerror(e));
237 + user_search = strdup(pwd.pw_name);
247 + char *grpstr = pos + 1;
248 + grpstr += strspn(grpstr, " \t\r\n");
251 + struct group grp, *res;
254 + buf = malloc(bufsize);
255 + while ((e = getgrnam_r(grpstr, &grp, buf, bufsize, &res))
257 + if (!enlarge_buffer(&buf, &bufsize)) {
263 + RTE_LOG(ERR, EAL,"Failed to get group entry for %s, "
264 + "(%s), aborting.", grpstr,
269 + RTE_LOG(ERR, EAL,"Group %s not found, aborting.",
287 +vhost_set_permissions(const char *vhost_sock_location)
289 + unsigned long int mode = strtoul(internal_config.vhost_sock_perm, NULL, 0);
290 + int err = chmod(vhost_sock_location, (mode_t)mode);
292 + RTE_LOG(ERR, EAL,"vhost-user socket cannot set"
293 + " permissions to %s (%s).\n",
294 + internal_config.vhost_sock_perm, strerror(err));
297 + RTE_LOG(INFO, EAL,"Socket %s changed permissions"
298 + " to %s\n", vhost_sock_location,
299 + internal_config.vhost_sock_perm);
303 +vhost_set_ownership(const char *vhost_sock_location)
308 + if (get_owners_from_str(internal_config.vhost_sock_owner, &vhuid, &vhgid)) {
309 + RTE_LOG(ERR, EAL,"vhost-user socket unable to get"
310 + " specified user/group: %s\n",
311 + internal_config.vhost_sock_owner);
315 + int err = chown(vhost_sock_location, vhuid, vhgid);
317 + RTE_LOG(ERR, EAL,"vhost-user socket unable to set"
318 + " ownership to %s (%s).\n",
319 + internal_config.vhost_sock_owner, strerror(err));
323 + RTE_LOG(INFO, EAL,"Socket %s changed ownership"
324 + " to %s.\n", vhost_sock_location,
325 + internal_config.vhost_sock_owner);
329 +rte_eal_set_socket_permissions(const char *path)
331 + if (internal_config.vhost_sock_perm) {
332 + vhost_set_permissions(path);
335 + if (internal_config.vhost_sock_owner) {
336 + vhost_set_ownership(path);
339 diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
340 index db8c984..bb92e57 100644
341 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
342 +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
343 @@ -139,6 +139,7 @@ DPDK_2.2 {
344 rte_keepalive_register_core;
345 rte_xen_dom0_supported;
347 + rte_eal_set_socket_permissions;
351 diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c
352 index b35594d..dbdb8ad 100644
353 --- a/lib/librte_vhost/vhost_user/vhost-net-user.c
354 +++ b/lib/librte_vhost/vhost_user/vhost-net-user.c
355 @@ -79,6 +79,8 @@ struct vhost_user {
356 pthread_mutex_t mutex;
359 +#include <rte_eal.h>
361 #define MAX_VIRTIO_BACKLOG 128
363 static void vhost_user_server_new_connection(int fd, void *data, int *remove);
364 @@ -682,6 +684,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
367 memset(vsocket, 0, sizeof(struct vhost_user_socket));
368 + rte_eal_set_socket_permissions(path);
369 vsocket->path = strdup(path);
370 vsocket->connfd = -1;