From 57b5e27d3d74f8dbb77ac909b405d99d555eca46 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Thu, 22 Dec 2016 10:33:28 +0100 Subject: [PATCH] qemu: set default vhost-user ifname Based on work of Mehdi Abaakouk . When parsing vhost-user interface XML and no ifname is found we can try to fill it in in post parse callback. The way this works is we try to make up interface name from given socket path and then ask openvswitch whether it knows the interface. Signed-off-by: Michal Privoznik --- src/libvirt_private.syms | 1 + src/qemu/qemu_domain.c | 21 +++++--- src/util/virnetdevopenvswitch.c | 53 +++++++++++++++++++ src/util/virnetdevopenvswitch.h | 4 ++ tests/Makefile.am | 7 +++ tests/qemuxml2argvmock.c | 8 +++ tests/qemuxml2xmlmock.c | 33 ++++++++++++ .../qemuxml2xmlout-net-vhostuser.xml | 2 + tests/qemuxml2xmltest.c | 2 +- 9 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 tests/qemuxml2xmlmock.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cfeb43cf0d..a2866a3a06 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2072,6 +2072,7 @@ virNetDevMidonetUnbindPort; # util/virnetdevopenvswitch.h virNetDevOpenvswitchAddPort; virNetDevOpenvswitchGetMigrateData; +virNetDevOpenvswitchGetVhostuserIfname; virNetDevOpenvswitchInterfaceStats; virNetDevOpenvswitchRemovePort; virNetDevOpenvswitchSetMigrateData; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c676042228..3df7e4bfc1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -41,6 +41,7 @@ #include "domain_addr.h" #include "domain_event.h" #include "virtime.h" +#include "virnetdevopenvswitch.h" #include "virstoragefile.h" #include "virstring.h" #include "virthreadjob.h" @@ -3004,12 +3005,20 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, def->emulator); } - if (dev->type == VIR_DOMAIN_DEVICE_NET && - dev->data.net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV && - !dev->data.net->model) { - if (VIR_STRDUP(dev->data.net->model, - qemuDomainDefaultNetModel(def, qemuCaps)) < 0) - goto cleanup; + if (dev->type == VIR_DOMAIN_DEVICE_NET) { + if (dev->data.net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV && + !dev->data.net->model) { + if (VIR_STRDUP(dev->data.net->model, + qemuDomainDefaultNetModel(def, qemuCaps)) < 0) + goto cleanup; + } + if (dev->data.net->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER && + !dev->data.net->ifname) { + if (virNetDevOpenvswitchGetVhostuserIfname( + dev->data.net->data.vhostuser->data.nix.path, + &dev->data.net->ifname) < 0) + goto cleanup; + } } /* set default disk types and drivers */ diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c index f003b3b134..e6cb096dfd 100644 --- a/src/util/virnetdevopenvswitch.c +++ b/src/util/virnetdevopenvswitch.c @@ -377,3 +377,56 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname, virCommandFree(cmd); return ret; } + +/** + * virNetDevOpenvswitchVhostuserGetIfname: + * @path: the path of the unix socket + * @ifname: the retrieved name of the interface + * + * Retreives the ovs ifname from vhostuser unix socket path. + * + * Returns: 1 if interface is an openvswitch interface, + * 0 if it is not, but no other error occurred, + * -1 otherwise. + */ +int +virNetDevOpenvswitchGetVhostuserIfname(const char *path, + char **ifname) +{ + virCommandPtr cmd = NULL; + char *tmpIfname = NULL; + char **tokens = NULL; + size_t ntokens = 0; + int status; + int ret = -1; + + /* Openvswitch vhostuser path are hardcoded to + * //openvswitch/ + * for example: /var/run/openvswitch/dpdkvhostuser0 + * + * so we pick the filename and check it's a openvswitch interface + */ + if (!path || + !(tmpIfname = strrchr(path, '/'))) { + ret = 0; + goto cleanup; + } + + cmd = virCommandNewArgList(OVSVSCTL, "--timeout=5", "get", "Interface", + tmpIfname, "name", NULL); + if (virCommandRun(cmd, &status) < 0 || + status) { + /* it's not a openvswitch vhostuser interface. */ + ret = 0; + goto cleanup; + } + + if (VIR_STRDUP(*ifname, tmpIfname) < 0) + goto cleanup; + ret = 1; + + cleanup: + virStringListFreeCount(tokens, ntokens); + virCommandFree(cmd); + return ret; +} diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h index 0f9e1dfa66..8f5faf14ed 100644 --- a/src/util/virnetdevopenvswitch.h +++ b/src/util/virnetdevopenvswitch.h @@ -52,4 +52,8 @@ int virNetDevOpenvswitchInterfaceStats(const char *ifname, virDomainInterfaceStatsPtr stats) ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK; +int virNetDevOpenvswitchGetVhostuserIfname(const char *path, + char **ifname) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + #endif /* __VIR_NETDEV_OPENVSWITCH_H__ */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 6d4af8cc9e..e923178f21 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -281,6 +281,7 @@ test_helpers += qemucapsprobe test_libraries += libqemumonitortestutils.la \ libqemutestdriver.la \ qemuxml2argvmock.la \ + qemuxml2xmlmock.la \ qemucaps2xmlmock.la \ qemucapsprobemock.la \ $(NULL) @@ -558,6 +559,12 @@ qemuxml2argvmock_la_CFLAGS = $(AM_CFLAGS) qemuxml2argvmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS) qemuxml2argvmock_la_LIBADD = $(MOCKLIBS_LIBS) +qemuxml2xmlmock_la_SOURCES = \ + qemuxml2xmlmock.c +qemuxml2xmlmock_la_CFLAGS = $(AM_CFLAGS) +qemuxml2xmlmock_la_LDFLAGS = $(MOCKLIBS_LDFLAGS) +qemuxml2xmlmock_la_LIBADD = $(MOCKLIBS_LIBS) + qemuxml2xmltest_SOURCES = \ qemuxml2xmltest.c testutilsqemu.c testutilsqemu.h \ testutils.c testutils.h diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c index c501b59acb..177b24e0a9 100644 --- a/tests/qemuxml2argvmock.c +++ b/tests/qemuxml2argvmock.c @@ -28,6 +28,7 @@ #include "virnetdev.h" #include "virnetdevip.h" #include "virnetdevtap.h" +#include "virnetdevopenvswitch.h" #include "virnuma.h" #include "virrandom.h" #include "virscsi.h" @@ -180,3 +181,10 @@ virCryptoGenerateRandom(size_t nbytes) return buf; } + +int +virNetDevOpenvswitchGetVhostuserIfname(const char *path ATTRIBUTE_UNUSED, + char **ifname) +{ + return VIR_STRDUP(*ifname, "vhost-user0"); +} diff --git a/tests/qemuxml2xmlmock.c b/tests/qemuxml2xmlmock.c new file mode 100644 index 0000000000..0d3e6f2bd6 --- /dev/null +++ b/tests/qemuxml2xmlmock.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Michal Privoznik + */ + +#include + +#include "virnetdevopenvswitch.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +int +virNetDevOpenvswitchGetVhostuserIfname(const char *path ATTRIBUTE_UNUSED, + char **ifname) +{ + return VIR_STRDUP(*ifname, "vhost-user0"); +} diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml index ac1d7e1101..2bdcac358a 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-vhostuser.xml @@ -30,12 +30,14 @@ +
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 5040b7a819..53c0e71138 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1059,7 +1059,7 @@ mymain(void) return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -VIRT_TEST_MAIN(mymain) +VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/qemuxml2xmlmock.so") #else -- 2.47.2