[PATCH v2] lxc: fix lxcContainerMountAllFS() DEREF_BEFORE_CHECK
by Dmitry Frolov
vmDef->fss[i]->src->path may be NULL,
so check is needed before passing it to VIR_DEBUG.
Also removed checking vmDef->fss[i]->src for NULL, since it may not be NULL.
Fixes: 57487085dc ("lxc: don't try to reference NULL when mounting filesystems")
Signed-off-by: Dmitry Frolov <frolov(a)swemel.ru>
---
src/lxc/lxc_container.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 21220661f7..9601061b23 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1467,12 +1467,12 @@ static int lxcContainerMountAllFS(virDomainDef *vmDef,
if (STREQ(vmDef->fss[i]->dst, "/"))
continue;
- VIR_DEBUG("Mounting '%s' -> '%s'", vmDef->fss[i]->src->path, vmDef->fss[i]->dst);
+ VIR_DEBUG("Mounting '%s' -> '%s'", NULLSTR(vmDef->fss[i]->src->path), vmDef->fss[i]->dst);
if (lxcContainerResolveSymlinks(vmDef->fss[i], false) < 0)
return -1;
- if (!(vmDef->fss[i]->src && vmDef->fss[i]->src->path &&
+ if (!(vmDef->fss[i]->src->path &&
STRPREFIX(vmDef->fss[i]->src->path, vmDef->fss[i]->dst)) &&
lxcContainerUnmountSubtree(vmDef->fss[i]->dst, false) < 0)
return -1;
--
2.34.1
1 year, 2 months
[PATCH] Send event on persistent config modification
by Fima Shevrin
Currently, libvirt doesn't send events when devices are attached,
detached or updated. Thus, any services that listen to events are
unaware of the change to persistent config.
Signed-off-by: Fima Shevrin <efim.shevrin(a)virtuozzo.com>
---
src/qemu/qemu_driver.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 43d96739d5..86da8da777 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7209,6 +7209,7 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObj *vm,
unsigned int flags)
{
qemuDomainObjPrivate *priv = vm->privateData;
+ virObjectEvent *event = NULL;
g_autoptr(virDomainDef) vmdef = NULL;
g_autoptr(virQEMUDriverConfig) cfg = NULL;
g_autoptr(virDomainDeviceDef) devConf = NULL;
@@ -7292,6 +7293,12 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObj *vm,
return -1;
virDomainObjAssignDef(vm, &vmdef, false, NULL);
+
+ /* Event sending if persistent config has changed */
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_DEFINED,
+ VIR_DOMAIN_EVENT_DEFINED_UPDATED);
+ virObjectEventStateQueue(driver->domainEventState, event);
}
return 0;
@@ -7348,6 +7355,7 @@ qemuDomainUpdateDeviceFlags(virDomainPtr dom,
virQEMUDriver *driver = dom->conn->privateData;
virDomainObj *vm = NULL;
qemuDomainObjPrivate *priv;
+ virObjectEvent *event = NULL;
g_autoptr(virDomainDef) vmdef = NULL;
g_autoptr(virDomainDeviceDef) dev_config = NULL;
g_autoptr(virDomainDeviceDef) dev_live = NULL;
@@ -7419,8 +7427,16 @@ qemuDomainUpdateDeviceFlags(virDomainPtr dom,
/* Finally, if no error until here, we can save config. */
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
ret = virDomainDefSave(vmdef, driver->xmlopt, cfg->configDir);
- if (!ret)
+ if (!ret) {
virDomainObjAssignDef(vm, &vmdef, false, NULL);
+
+ /* Event sending if persistent config has changed */
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_DEFINED,
+ VIR_DOMAIN_EVENT_DEFINED_UPDATED);
+
+ virObjectEventStateQueue(driver->domainEventState, event);
+ }
}
endjob:
@@ -7438,6 +7454,7 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver *driver,
unsigned int flags)
{
qemuDomainObjPrivate *priv = vm->privateData;
+ virObjectEvent *event = NULL;
g_autoptr(virQEMUDriverConfig) cfg = NULL;
g_autoptr(virDomainDeviceDef) dev_config = NULL;
g_autoptr(virDomainDeviceDef) dev_live = NULL;
@@ -7495,6 +7512,12 @@ qemuDomainDetachDeviceLiveAndConfig(virQEMUDriver *driver,
return -1;
virDomainObjAssignDef(vm, &vmdef, false, NULL);
+
+ /* Event sending if persistent config has changed */
+ event = virDomainEventLifecycleNewFromObj(vm,
+ VIR_DOMAIN_EVENT_DEFINED,
+ VIR_DOMAIN_EVENT_DEFINED_UPDATED);
+ virObjectEventStateQueue(driver->domainEventState, event);
}
return 0;
--
2.39.3
1 year, 2 months
[PATCH] fix error in printf format string
by zhujun2
use '%u' to printf unsigned int
Signed-off-by: zhujun2 <zhujun2(a)cmss.chinamobile.com>
---
examples/c/misc/event-test.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c
index 813bca2699..07d86500cd 100644
--- a/examples/c/misc/event-test.c
+++ b/examples/c/misc/event-test.c
@@ -969,7 +969,7 @@ myDomainEventMemoryFailureCallback(virConnectPtr conn G_GNUC_UNUSED,
void *opaque G_GNUC_UNUSED)
{
printf("%s EVENT: Domain %s(%d) memory failure: recipient '%d', "
- "aciont '%d', flags '%d'\n", __func__, virDomainGetName(dom),
+ "aciont '%d', flags '%u'\n", __func__, virDomainGetName(dom),
virDomainGetID(dom), recipient, action, flags);
return 0;
}
--
2.17.1
1 year, 2 months
[libvirt PATCH] logging: lockdown the systemd service configuration
by Daniel P. Berrangé
The 'systemd-analyze security' command looks at the unit file
configuration and reports on any settings which increase the
attack surface for the daemon. Since most systemd units are
fairly minimalist, this is generally informing us about settings
that we never put any thought into using before.
In its current configuration it reports
# systemd-analyze security virtlogd.service
...snip...
→ Overall exposure level for virtlogd.service: 9.6 UNSAFE 😨
which is pretty terrible as a score.
If we apply all of the recommendations that appear possible
without (knowingly) breaking functionality it reports:
# systemd-analyze security virtlogd.service
...snip...
→ Overall exposure level for virtlogd.service: 2.2 OK 🙂
which is a pretty decent improvement.
Some of the settings we would like to enable require a systemd
version that is newer than that available in our oldest distro
target - RHEL-8 at v239.
NB, RestrictSUIDSGID is technically newer than 239, but RHEL-8
backported it, and other distros we target have it by default.
Remaining recommendations are
✗ CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)
We block FOWNER/IPC_OWNER, but can't block the two DAC
capabilities. Historically apps/users might point QEMU
to log files in $HOME, pre-created with their own user
ID.
✗ IPAddressDeny=
Not required since RestrictAddressFamilies blocks IP
usage. Ignoring this avoids the overhead of creating
a traffic filter than will never be used.
✗ NoNewPrivileges=
Highly desirable, but cannot enable it yet, because it
will block the ability to transition to the virtlogd_t
SELinux domain during execve. The SELinux policy needs
fixing to permit this transition under NNP first.
✗ PrivateTmp=
There is a decent chance people have VMs configured
with a serial port logfile pointing at /tmp. We would
cause a regression to use private /tmp for logging
✗ PrivateUsers=
This would put virtlogd inside a user namespace where
its root is in fact unprivileged. Same problem as the
User= setting below
✗ ProcSubset=
Libraries we link to might read certain non-PID related
files from /proc
✗ ProtectClock=
Requires v245
✗ ProtectHome=
Same problem as PrivateTmp=. There's a decent chance
that someone has a VM configured to write a logfile
to /home
✗ ProtectHostname=
Requires v241
✗ ProtectKernelLogs
Requires v244
✗ ProtectProc
Requires v247
✗ ProtectSystem=
We only set it to 'full', as 'strict' is not viable for
our required usage
✗ RootDirectory=/RootImage=
We are not capable of running inside a custom chroot
given needs to write log files to arbitrary places
✗ RestrictAddressFamilies=~AF_UNIX
We need AF_UNIX to communicate with other libvirt daemons
✗ SystemCallFilter=~@resources
We link to libvirt.so which links to libnuma.so which has
a constructor that calls set_mempolicy. This is highly
undesirable todo during a constructor.
✗ User=/DynamicUser=
This is highly desirable, but we currently read/write
logs as root, and directories we're told to write into
could be anywhere. So using a non-root user would have
a major risk of regressions for applications and also
have upgrade implications
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
src/logging/virtlogd.service.in | 94 +++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/src/logging/virtlogd.service.in b/src/logging/virtlogd.service.in
index 8e245ddb43..9e3838ff34 100644
--- a/src/logging/virtlogd.service.in
+++ b/src/logging/virtlogd.service.in
@@ -20,5 +20,99 @@ OOMScoreAdjust=-900
# per systemd recommendations
LimitNOFILE=1024:524288
+CapabilityBoundingSet=~CAP_AUDIT_CONTROL
+CapabilityBoundingSet=~CAP_AUDIT_READ
+CapabilityBoundingSet=~CAP_AUDIT_WRITE
+CapabilityBoundingSet=~CAP_BLOCK_SUSPEND
+CapabilityBoundingSet=~CAP_CHOWN
+# Mgmt app/user might have pre-created log files that we're
+# told to open and write to, or be storing them in otherwise
+# inaccessible locations like $HOME. So we need to ignore
+# DAC permission checks.
+#CapabilityBoundingSet=~CAP_DAC_OVERRIDE
+#CapabilityBoundingSet=~CAP_DAC_READ_SEARCH
+CapabilityBoundingSet=~CAP_FOWNER
+CapabilityBoundingSet=~CAP_FSETID
+CapabilityBoundingSet=~CAP_IPC_LOCK
+CapabilityBoundingSet=~CAP_IPC_OWNER
+CapabilityBoundingSet=~CAP_KILL
+CapabilityBoundingSet=~CAP_LEASE
+CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE
+CapabilityBoundingSet=~CAP_MAC_ADMIN
+CapabilityBoundingSet=~CAP_MAC_OVERRIDE
+CapabilityBoundingSet=~CAP_MKNOD
+CapabilityBoundingSet=~CAP_NET_ADMIN
+CapabilityBoundingSet=~CAP_NET_BIND_SERVICE
+CapabilityBoundingSet=~CAP_NET_BROADCAST
+CapabilityBoundingSet=~CAP_NET_RAW
+CapabilityBoundingSet=~CAP_SETFCAP
+CapabilityBoundingSet=~CAP_SETPCAP
+CapabilityBoundingSet=~CAP_SETGID
+CapabilityBoundingSet=~CAP_SETUID
+CapabilityBoundingSet=~CAP_SYSLOG
+CapabilityBoundingSet=~CAP_SYS_ADMIN
+CapabilityBoundingSet=~CAP_SYS_BOOT
+CapabilityBoundingSet=~CAP_SYS_CHROOT
+CapabilityBoundingSet=~CAP_SYS_MODULE
+CapabilityBoundingSet=~CAP_SYS_NICE
+CapabilityBoundingSet=~CAP_SYS_PACCT
+CapabilityBoundingSet=~CAP_SYS_PTRACE
+CapabilityBoundingSet=~CAP_SYS_RAWIO
+CapabilityBoundingSet=~CAP_SYS_RESOURCE
+CapabilityBoundingSet=~CAP_SYS_TIME
+CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG
+CapabilityBoundingSet=~CAP_WAKE_ALARM
+
+LockPersonality=true
+MemoryDenyWriteExecute=true
+# Cannot enable this as it prevents transitioning to
+# the confined SELinux virtlogd_t domain on execve
+# unless we modify the policy to allow this.
+#NoNewPrivileges=true
+PrivateDevices=true
+PrivateMounts=true
+PrivateNetwork=true
+# XXX someone could configure QEMU to log a serial port to an
+# arbitrary directory, including /tmp, even if this is ill-advised
+#PrivateTmp=true
+# Not until oldest build target has systemd >= v245
+#ProtectClock=true
+ProtectControlGroups=true
+# Not until oldest build target has systemd >= v241
+#ProtectHostname=true
+# Not until oldest build target has systemd >= v244
+#ProtectKernelLogs=true
+ProtectKernelModules=true
+ProtectKernelTunables=true
+# Not until oldest build target has systemd >= v247
+#ProtectProc=invisible
+ProtectSystem=full
+RestrictAddressFamilies=AF_UNIX
+RestrictNamespaces=~cgroup
+RestrictNamespaces=~ipc
+RestrictNamespaces=~mnt
+RestrictNamespaces=~net
+RestrictNamespaces=~pid
+RestrictNamespaces=~user
+RestrictNamespaces=~uts
+RestrictRealtime=true
+RestrictSUIDSGID=true
+SystemCallArchitectures=native
+SystemCallFilter=~@clock
+SystemCallFilter=~@debug
+SystemCallFilter=~@module
+SystemCallFilter=~@mount
+SystemCallFilter=~@raw-io
+SystemCallFilter=~@reboot
+SystemCallFilter=~@swap
+SystemCallFilter=~@privileged
+# Unfortunately we link to libnuma via libvirt.so which
+# has a constructor that runs unconditionally that invokes
+# set_mempolicy()
+#SystemCallFilter=~@resources
+SystemCallFilter=~@cpu-emulation
+SystemCallFilter=~@obsolete
+UMask=077
+
[Install]
Also=virtlogd.socket
--
2.41.0
1 year, 2 months
[libvirt PATCH v3] hypervisor: Move interface mgmt methods to hypervisor
by Praveen K Paladugu
Move guest interface management methods from qemu to hypervisor. These
methods will be shared by networking support in ch driver.
Signed-off-by: Praveen K Paladugu <prapal(a)linux.microsoft.com>
---
po/POTFILES | 1 +
src/hypervisor/domain_interface.c | 368 ++++++++++++++++++++++++++++++
src/hypervisor/domain_interface.h | 41 ++++
src/hypervisor/meson.build | 1 +
src/libvirt_private.syms | 8 +
src/qemu/qemu_command.c | 6 +-
src/qemu/qemu_hotplug.c | 5 +-
src/qemu/qemu_interface.c | 339 +--------------------------
src/qemu/qemu_interface.h | 11 -
src/qemu/qemu_process.c | 5 +-
10 files changed, 434 insertions(+), 351 deletions(-)
create mode 100644 src/hypervisor/domain_interface.c
create mode 100644 src/hypervisor/domain_interface.h
diff --git a/po/POTFILES b/po/POTFILES
index 3a51aea5cb..023c041f61 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -92,6 +92,7 @@ src/hyperv/hyperv_util.c
src/hyperv/hyperv_wmi.c
src/hypervisor/domain_cgroup.c
src/hypervisor/domain_driver.c
+src/hypervisor/domain_interface.c
src/hypervisor/virhostdev.c
src/interface/interface_backend_netcf.c
src/interface/interface_backend_udev.c
diff --git a/src/hypervisor/domain_interface.c b/src/hypervisor/domain_interface.c
new file mode 100644
index 0000000000..f726cb2bea
--- /dev/null
+++ b/src/hypervisor/domain_interface.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.c: methods to manage guest/domain interfaces
+ *
+ * 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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "virconftypes.h"
+#include "virmacaddr.h"
+#include "virnetdevtap.h"
+#include "domain_audit.h"
+#include "domain_conf.h"
+#include "domain_interface.h"
+#include "domain_nwfilter.h"
+#include "viralloc.h"
+#include "virebtables.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virnetdevbridge.h"
+#include "network_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_INTERFACE
+
+VIR_LOG_INIT("interface.interface_connect");
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net)
+{
+ return (virDomainNetIsVirtioModel(net) ||
+ net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
+ net->model == VIR_DOMAIN_NET_MODEL_IGB ||
+ net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
+}
+
+/* virDomainInterfaceEthernetConnect:
+ * @def: the definition of the VM
+ * @driver: qemu driver data
+ * @net: pointer to the VM's interface description
+ * @tapfd: array of file descriptor return value for the new device
+ * @tapfdsize: number of file descriptors in @tapfd
+ *
+ * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
+ * (i.e. if the connection is made with a tap device)
+ */
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+ virDomainNetDef *net,
+ ebtablesContext *ebtables,
+ bool macFilter,
+ bool privileged,
+ int *tapfd,
+ size_t tapfdSize)
+{
+ virMacAddr tapmac;
+ int ret = -1;
+ unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
+ bool template_ifname = false;
+ const char *tunpath = "/dev/net/tun";
+ const char *auditdev = tunpath;
+
+ if (net->backend.tap) {
+ tunpath = net->backend.tap;
+ if (!privileged) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("cannot use custom tap device in session mode"));
+ goto cleanup;
+ }
+ }
+
+ if (virDomainInterfaceIsVnetCompatModel(net))
+ tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
+
+ if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
+ if (!net->ifname) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("target dev must be supplied when managed='no'"));
+ goto cleanup;
+ }
+ if (virNetDevExists(net->ifname) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("target managed='no' but specified dev doesn't exist"));
+ goto cleanup;
+ }
+
+ tap_create_flags |= VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING;
+
+ if (virNetDevMacVLanIsMacvtap(net->ifname)) {
+ auditdev = net->ifname;
+ if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
+ goto cleanup;
+ if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
+ virDomainInterfaceIsVnetCompatModel(net)) < 0) {
+ goto cleanup;
+ }
+ } else {
+ if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
+ tap_create_flags) < 0)
+ goto cleanup;
+ }
+ } else {
+
+ if (!net->ifname)
+ template_ifname = true;
+
+ if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
+ tap_create_flags) < 0) {
+ goto cleanup;
+ }
+
+ /* The tap device's MAC address cannot match the MAC address
+ * used by the guest. This results in "received packet on
+ * vnetX with own address as source address" error logs from
+ * the kernel.
+ */
+ virMacAddrSet(&tapmac, &net->mac);
+ if (tapmac.addr[0] == 0xFE)
+ tapmac.addr[0] = 0xFA;
+ else
+ tapmac.addr[0] = 0xFE;
+
+ if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
+ goto cleanup;
+
+ if (virNetDevSetOnline(net->ifname, true) < 0)
+ goto cleanup;
+ }
+
+ if (net->script &&
+ virNetDevRunEthernetScript(net->ifname, net->script) < 0)
+ goto cleanup;
+
+ if (macFilter &&
+ ebtablesAddForwardAllowIn(ebtables,
+ net->ifname,
+ &net->mac) < 0)
+ goto cleanup;
+
+ if (net->filter &&
+ virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 0) {
+ goto cleanup;
+ }
+
+ virDomainAuditNetDevice(def, net, auditdev, true);
+
+ ret = 0;
+
+ cleanup:
+ if (ret < 0) {
+ size_t i;
+
+ virDomainAuditNetDevice(def, net, auditdev, false);
+ for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
+ VIR_FORCE_CLOSE(tapfd[i]);
+ if (template_ifname)
+ VIR_FREE(net->ifname);
+ }
+
+ return ret;
+}
+
+/**
+ * virDomainInterfaceStartDevice:
+ * @net: net device to start
+ *
+ * Based upon the type of device provided, perform the appropriate
+ * work to completely activate the device and make it reachable from
+ * the rest of the network.
+ */
+int
+virDomainInterfaceStartDevice(virDomainNetDef *net)
+{
+ virDomainNetType actualType = virDomainNetGetActualType(net);
+
+ switch (actualType) {
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ if (virDomainNetGetActualBridgeMACTableManager(net)
+ == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
+ /* libvirt is managing the FDB of the bridge this device
+ * is attaching to, so we have turned off learning and
+ * unicast_flood on the device to prevent the kernel from
+ * adding any FDB entries for it. This means we need to
+ * add an fdb entry ourselves, using the MAC address from
+ * the interface config.
+ */
+ if (virNetDevBridgeFDBAdd(&net->mac, net->ifname,
+ VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
+ VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_DIRECT: {
+ const char *physdev = virDomainNetGetActualDirectDev(net);
+ bool isOnline = true;
+
+ /* set the physdev online if necessary. It may already be up,
+ * in which case we shouldn't re-up it just in case that causes
+ * some sort of "blip" in the physdev's status.
+ */
+ if (physdev && virNetDevGetOnline(physdev, &isOnline) < 0)
+ return -1;
+ if (!isOnline && virNetDevSetOnline(physdev, true) < 0)
+ return -1;
+
+ /* macvtap devices share their MAC address with the guest
+ * domain, and if they are set online prior to the domain CPUs
+ * being started, the host may send out traffic from this
+ * device that could confuse other entities on the network (in
+ * particular, if this new domain is the destination of a
+ * migration, and the source domain is still running, another
+ * host may mistakenly direct traffic for the guest to the
+ * destination domain rather than source domain). To prevent
+ * this, we create the macvtap device with IFF_UP false
+ * (i.e. "offline") then wait to bring it online until just as
+ * we are starting the domain CPUs.
+ */
+ if (virNetDevSetOnline(net->ifname, true) < 0)
+ return -1;
+ break;
+ }
+
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ if (virNetDevIPInfoAddToDev(net->ifname, &net->hostIP) < 0)
+ return -1;
+
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_USER:
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+ case VIR_DOMAIN_NET_TYPE_SERVER:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_MCAST:
+ case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_INTERNAL:
+ case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
+ case VIR_DOMAIN_NET_TYPE_NULL:
+ case VIR_DOMAIN_NET_TYPE_VDS:
+ case VIR_DOMAIN_NET_TYPE_LAST:
+ /* these types all require no action */
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * virDomainInterfaceStartDevices:
+ * @def: domain definition
+ *
+ * Set all ifaces associated with this domain to the online state.
+ */
+int
+virDomainInterfaceStartDevices(virDomainDef *def)
+{
+ size_t i;
+
+ for (i = 0; i < def->nnets; i++) {
+ if (virDomainInterfaceStartDevice(def->nets[i]) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * virDomainInterfaceStopDevice:
+ * @net: net device to stop
+ *
+ * Based upon the type of device provided, perform the appropriate
+ * work to deactivate the device so that packets aren't forwarded to
+ * it from the rest of the network.
+ */
+int
+virDomainInterfaceStopDevice(virDomainNetDef *net)
+{
+ virDomainNetType actualType = virDomainNetGetActualType(net);
+
+ switch (actualType) {
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ if (virDomainNetGetActualBridgeMACTableManager(net)
+ == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
+ /* remove the FDB entries that were added during
+ * virDomainInterfaceStartDevices()
+ */
+ if (virNetDevBridgeFDBDel(&net->mac, net->ifname,
+ VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
+ VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_DIRECT: {
+ const char *physdev = virDomainNetGetActualDirectDev(net);
+
+ /* macvtap interfaces need to be marked !IFF_UP (ie "down") to
+ * prevent any host-generated traffic sent from this interface
+ * from putting bad info into the arp caches of other machines
+ * on this network.
+ */
+ if (virNetDevSetOnline(net->ifname, false) < 0)
+ return -1;
+
+ /* also mark the physdev down for passthrough macvtap, as the
+ * physdev has the same MAC address as the macvtap device.
+ */
+ if (virDomainNetGetActualDirectMode(net) ==
+ VIR_NETDEV_MACVLAN_MODE_PASSTHRU &&
+ physdev && virNetDevSetOnline(physdev, false) < 0)
+ return -1;
+ break;
+ }
+
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ case VIR_DOMAIN_NET_TYPE_USER:
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+ case VIR_DOMAIN_NET_TYPE_SERVER:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_MCAST:
+ case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_INTERNAL:
+ case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
+ case VIR_DOMAIN_NET_TYPE_NULL:
+ case VIR_DOMAIN_NET_TYPE_VDS:
+ case VIR_DOMAIN_NET_TYPE_LAST:
+ /* these types all require no action */
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * virDomainInterfaceStopDevices:
+ * @def: domain definition
+ *
+ * Make all interfaces associated with this domain inaccessible from
+ * the rest of the network.
+ */
+int
+virDomainInterfaceStopDevices(virDomainDef *def)
+{
+ size_t i;
+
+ for (i = 0; i < def->nnets; i++) {
+ if (virDomainInterfaceStopDevice(def->nets[i]) < 0)
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/hypervisor/domain_interface.h b/src/hypervisor/domain_interface.h
new file mode 100644
index 0000000000..68bf2ae51d
--- /dev/null
+++ b/src/hypervisor/domain_interface.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.h: methods to manage guest/domain interfaces
+ *
+ * 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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "virebtables.h"
+
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+ virDomainNetDef *net,
+ ebtablesContext *ebtables,
+ bool macFilter,
+ bool privileged,
+ int *tapfd,
+ size_t tapfdSize);
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net);
+
+int virDomainInterfaceStartDevice(virDomainNetDef *net);
+int virDomainInterfaceStartDevices(virDomainDef *def);
+int virDomainInterfaceStopDevice(virDomainNetDef *net);
+int virDomainInterfaceStopDevices(virDomainDef *def);
diff --git a/src/hypervisor/meson.build b/src/hypervisor/meson.build
index f35565b16b..819a9a82a2 100644
--- a/src/hypervisor/meson.build
+++ b/src/hypervisor/meson.build
@@ -1,6 +1,7 @@
hypervisor_sources = [
'domain_cgroup.c',
'domain_driver.c',
+ 'domain_interface.c',
'virclosecallbacks.c',
'virhostdev.c',
]
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 553b01b8c0..b7f329be43 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1630,6 +1630,14 @@ virDomainDriverNodeDeviceReset;
virDomainDriverParseBlkioDeviceStr;
virDomainDriverSetupPersistentDefBlkioParams;
+# hypervisor/domain_interface.h
+virDomainInterfaceEthernetConnect;
+virDomainInterfaceIsVnetCompatModel;
+virDomainInterfaceStartDevice;
+virDomainInterfaceStartDevices;
+virDomainInterfaceStopDevice;
+virDomainInterfaceStopDevices;
+
# hypervisor/virclosecallbacks.h
virCloseCallbacksDomainAdd;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d40d3a4e13..1ac39937b9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -43,6 +43,7 @@
#include "domain_nwfilter.h"
#include "domain_addr.h"
#include "domain_conf.h"
+#include "domain_interface.h"
#include "netdev_bandwidth_conf.h"
#include "virnetdevopenvswitch.h"
#include "device_conf.h"
@@ -8525,7 +8526,10 @@ qemuBuildInterfaceConnect(virDomainObj *vm,
break;
case VIR_DOMAIN_NET_TYPE_ETHERNET:
- if (qemuInterfaceEthernetConnect(vm->def, priv->driver, net,
+ if (virDomainInterfaceEthernetConnect(vm->def, net,
+ priv->driver->ebtables,
+ priv->driver->config->macFilter,
+ priv->driver->privileged,
tapfd, tapfdSize) < 0)
return -1;
vhostfd = true;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 1f7f5bdd26..76e911c8b0 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -39,6 +39,7 @@
#include "qemu_virtiofs.h"
#include "domain_audit.h"
#include "domain_cgroup.h"
+#include "domain_interface.h"
#include "netdev_bandwidth_conf.h"
#include "domain_nwfilter.h"
#include "virlog.h"
@@ -1269,7 +1270,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
}
/* Set device online immediately */
- if (qemuInterfaceStartDevice(net) < 0)
+ if (virDomainInterfaceStartDevice(net) < 0)
goto cleanup;
qemuDomainInterfaceSetDefaultQDisc(driver, net);
@@ -4769,7 +4770,7 @@ qemuDomainRemoveNetDevice(virQEMUDriver *driver,
* affect the parent device (e.g. macvtap passthrough mode sets
* the parent device offline)
*/
- ignore_value(qemuInterfaceStopDevice(net));
+ ignore_value(virDomainInterfaceStopDevice(net));
qemuDomainObjEnterMonitor(vm);
if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index 8856bb95a8..c2007c7043 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -24,6 +24,7 @@
#include "network_conf.h"
#include "domain_audit.h"
#include "domain_nwfilter.h"
+#include "domain_interface.h"
#include "qemu_interface.h"
#include "viralloc.h"
#include "virlog.h"
@@ -41,211 +42,6 @@
VIR_LOG_INIT("qemu.qemu_interface");
-/**
- * qemuInterfaceStartDevice:
- * @net: net device to start
- *
- * Based upon the type of device provided, perform the appropriate
- * work to completely activate the device and make it reachable from
- * the rest of the network.
- */
-int
-qemuInterfaceStartDevice(virDomainNetDef *net)
-{
- virDomainNetType actualType = virDomainNetGetActualType(net);
-
- switch (actualType) {
- case VIR_DOMAIN_NET_TYPE_BRIDGE:
- case VIR_DOMAIN_NET_TYPE_NETWORK:
- if (virDomainNetGetActualBridgeMACTableManager(net)
- == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
- /* libvirt is managing the FDB of the bridge this device
- * is attaching to, so we have turned off learning and
- * unicast_flood on the device to prevent the kernel from
- * adding any FDB entries for it. This means we need to
- * add an fdb entry ourselves, using the MAC address from
- * the interface config.
- */
- if (virNetDevBridgeFDBAdd(&net->mac, net->ifname,
- VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
- VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
- return -1;
- }
- break;
-
- case VIR_DOMAIN_NET_TYPE_DIRECT: {
- const char *physdev = virDomainNetGetActualDirectDev(net);
- bool isOnline = true;
-
- /* set the physdev online if necessary. It may already be up,
- * in which case we shouldn't re-up it just in case that causes
- * some sort of "blip" in the physdev's status.
- */
- if (physdev && virNetDevGetOnline(physdev, &isOnline) < 0)
- return -1;
- if (!isOnline && virNetDevSetOnline(physdev, true) < 0)
- return -1;
-
- /* macvtap devices share their MAC address with the guest
- * domain, and if they are set online prior to the domain CPUs
- * being started, the host may send out traffic from this
- * device that could confuse other entities on the network (in
- * particular, if this new domain is the destination of a
- * migration, and the source domain is still running, another
- * host may mistakenly direct traffic for the guest to the
- * destination domain rather than source domain). To prevent
- * this, we create the macvtap device with IFF_UP false
- * (i.e. "offline") then wait to bring it online until just as
- * we are starting the domain CPUs.
- */
- if (virNetDevSetOnline(net->ifname, true) < 0)
- return -1;
- break;
- }
-
- case VIR_DOMAIN_NET_TYPE_ETHERNET:
- if (virNetDevIPInfoAddToDev(net->ifname, &net->hostIP) < 0)
- return -1;
-
- break;
-
- case VIR_DOMAIN_NET_TYPE_USER:
- case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
- case VIR_DOMAIN_NET_TYPE_SERVER:
- case VIR_DOMAIN_NET_TYPE_CLIENT:
- case VIR_DOMAIN_NET_TYPE_MCAST:
- case VIR_DOMAIN_NET_TYPE_UDP:
- case VIR_DOMAIN_NET_TYPE_INTERNAL:
- case VIR_DOMAIN_NET_TYPE_HOSTDEV:
- case VIR_DOMAIN_NET_TYPE_VDPA:
- case VIR_DOMAIN_NET_TYPE_NULL:
- case VIR_DOMAIN_NET_TYPE_VDS:
- case VIR_DOMAIN_NET_TYPE_LAST:
- /* these types all require no action */
- break;
- }
-
- return 0;
-}
-
-/**
- * qemuInterfaceStartDevices:
- * @def: domain definition
- *
- * Set all ifaces associated with this domain to the online state.
- */
-int
-qemuInterfaceStartDevices(virDomainDef *def)
-{
- size_t i;
-
- for (i = 0; i < def->nnets; i++) {
- if (qemuInterfaceStartDevice(def->nets[i]) < 0)
- return -1;
- }
- return 0;
-}
-
-
-/**
- * qemuInterfaceStopDevice:
- * @net: net device to stop
- *
- * Based upon the type of device provided, perform the appropriate
- * work to deactivate the device so that packets aren't forwarded to
- * it from the rest of the network.
- */
-int
-qemuInterfaceStopDevice(virDomainNetDef *net)
-{
- virDomainNetType actualType = virDomainNetGetActualType(net);
-
- switch (actualType) {
- case VIR_DOMAIN_NET_TYPE_BRIDGE:
- case VIR_DOMAIN_NET_TYPE_NETWORK:
- if (virDomainNetGetActualBridgeMACTableManager(net)
- == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
- /* remove the FDB entries that were added during
- * qemuInterfaceStartDevices()
- */
- if (virNetDevBridgeFDBDel(&net->mac, net->ifname,
- VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
- VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
- return -1;
- }
- break;
-
- case VIR_DOMAIN_NET_TYPE_DIRECT: {
- const char *physdev = virDomainNetGetActualDirectDev(net);
-
- /* macvtap interfaces need to be marked !IFF_UP (ie "down") to
- * prevent any host-generated traffic sent from this interface
- * from putting bad info into the arp caches of other machines
- * on this network.
- */
- if (virNetDevSetOnline(net->ifname, false) < 0)
- return -1;
-
- /* also mark the physdev down for passthrough macvtap, as the
- * physdev has the same MAC address as the macvtap device.
- */
- if (virDomainNetGetActualDirectMode(net) ==
- VIR_NETDEV_MACVLAN_MODE_PASSTHRU &&
- physdev && virNetDevSetOnline(physdev, false) < 0)
- return -1;
- break;
- }
-
- case VIR_DOMAIN_NET_TYPE_ETHERNET:
- case VIR_DOMAIN_NET_TYPE_USER:
- case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
- case VIR_DOMAIN_NET_TYPE_SERVER:
- case VIR_DOMAIN_NET_TYPE_CLIENT:
- case VIR_DOMAIN_NET_TYPE_MCAST:
- case VIR_DOMAIN_NET_TYPE_UDP:
- case VIR_DOMAIN_NET_TYPE_INTERNAL:
- case VIR_DOMAIN_NET_TYPE_HOSTDEV:
- case VIR_DOMAIN_NET_TYPE_VDPA:
- case VIR_DOMAIN_NET_TYPE_NULL:
- case VIR_DOMAIN_NET_TYPE_VDS:
- case VIR_DOMAIN_NET_TYPE_LAST:
- /* these types all require no action */
- break;
- }
-
- return 0;
-}
-
-/**
- * qemuInterfaceStopDevices:
- * @def: domain definition
- *
- * Make all interfaces associated with this domain inaccessible from
- * the rest of the network.
- */
-int
-qemuInterfaceStopDevices(virDomainDef *def)
-{
- size_t i;
-
- for (i = 0; i < def->nnets; i++) {
- if (qemuInterfaceStopDevice(def->nets[i]) < 0)
- return -1;
- }
- return 0;
-}
-
-
-static bool
-qemuInterfaceIsVnetCompatModel(const virDomainNetDef *net)
-{
- return (virDomainNetIsVirtioModel(net) ||
- net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
- net->model == VIR_DOMAIN_NET_MODEL_IGB ||
- net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
-}
-
-
/**
* qemuInterfaceDirectConnect:
* @def: the definition of the VM (needed by 802.1Qbh and audit)
@@ -271,7 +67,7 @@ qemuInterfaceDirectConnect(virDomainDef *def,
unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_WITH_TAP;
qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
- if (qemuInterfaceIsVnetCompatModel(net))
+ if (virDomainInterfaceIsVnetCompatModel(net))
macvlan_create_flags |= VIR_NETDEV_MACVLAN_VNET_HDR;
if (virNetDevMacVLanCreateWithVPortProfile(net->ifname,
@@ -409,133 +205,6 @@ qemuCreateInBridgePortWithHelper(virQEMUDriverConfig *cfg,
return *tapfd < 0 ? -1 : 0;
}
-
-/* qemuInterfaceEthernetConnect:
- * @def: the definition of the VM
- * @driver: qemu driver data
- * @net: pointer to the VM's interface description
- * @tapfd: array of file descriptor return value for the new device
- * @tapfdsize: number of file descriptors in @tapfd
- *
- * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
- * (i.e. if the connection is made with a tap device)
- */
-int
-qemuInterfaceEthernetConnect(virDomainDef *def,
- virQEMUDriver *driver,
- virDomainNetDef *net,
- int *tapfd,
- size_t tapfdSize)
-{
- virMacAddr tapmac;
- int ret = -1;
- unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
- bool template_ifname = false;
- g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
- const char *tunpath = "/dev/net/tun";
- const char *auditdev = tunpath;
-
- if (net->backend.tap) {
- tunpath = net->backend.tap;
- if (!driver->privileged) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("cannot use custom tap device in session mode"));
- goto cleanup;
- }
- }
-
- if (qemuInterfaceIsVnetCompatModel(net))
- tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
-
- if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
- if (!net->ifname) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("target dev must be supplied when managed='no'"));
- goto cleanup;
- }
- if (virNetDevExists(net->ifname) != 1) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("target managed='no' but specified dev doesn't exist"));
- goto cleanup;
- }
-
- tap_create_flags |= VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING;
-
- if (virNetDevMacVLanIsMacvtap(net->ifname)) {
- auditdev = net->ifname;
- if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
- goto cleanup;
- if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
- qemuInterfaceIsVnetCompatModel(net)) < 0) {
- goto cleanup;
- }
- } else {
- if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
- tap_create_flags) < 0)
- goto cleanup;
- }
- } else {
-
- if (!net->ifname)
- template_ifname = true;
-
- if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
- tap_create_flags) < 0) {
- goto cleanup;
- }
-
- /* The tap device's MAC address cannot match the MAC address
- * used by the guest. This results in "received packet on
- * vnetX with own address as source address" error logs from
- * the kernel.
- */
- virMacAddrSet(&tapmac, &net->mac);
- if (tapmac.addr[0] == 0xFE)
- tapmac.addr[0] = 0xFA;
- else
- tapmac.addr[0] = 0xFE;
-
- if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
- goto cleanup;
-
- if (virNetDevSetOnline(net->ifname, true) < 0)
- goto cleanup;
- }
-
- if (net->script &&
- virNetDevRunEthernetScript(net->ifname, net->script) < 0)
- goto cleanup;
-
- if (cfg->macFilter &&
- ebtablesAddForwardAllowIn(driver->ebtables,
- net->ifname,
- &net->mac) < 0)
- goto cleanup;
-
- if (net->filter &&
- virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 0) {
- goto cleanup;
- }
-
- virDomainAuditNetDevice(def, net, auditdev, true);
-
- ret = 0;
-
- cleanup:
- if (ret < 0) {
- size_t i;
-
- virDomainAuditNetDevice(def, net, auditdev, false);
- for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
- VIR_FORCE_CLOSE(tapfd[i]);
- if (template_ifname)
- VIR_FREE(net->ifname);
- }
-
- return ret;
-}
-
-
/* qemuInterfaceBridgeConnect:
* @def: the definition of the VM
* @driver: qemu driver data
@@ -578,7 +247,7 @@ qemuInterfaceBridgeConnect(virDomainDef *def,
if (!net->ifname)
template_ifname = true;
- if (qemuInterfaceIsVnetCompatModel(net))
+ if (virDomainInterfaceIsVnetCompatModel(net))
tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
if (driver->privileged) {
@@ -598,7 +267,7 @@ qemuInterfaceBridgeConnect(virDomainDef *def,
* is attaching to, so we need to turn off learning and
* unicast_flood on the device to prevent the kernel from
* adding any FDB entries for it. We will add an fdb
- * entry ourselves (during qemuInterfaceStartDevices(),
+ * entry ourselves (during virDomainInterfaceStartDevices(),
* using the MAC address from the interface config.
*/
if (virNetDevBridgePortSetLearning(brname, net->ifname, false) < 0)
diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
index 6eed3e6bd7..47d7ec03fd 100644
--- a/src/qemu/qemu_interface.h
+++ b/src/qemu/qemu_interface.h
@@ -25,11 +25,6 @@
#include "qemu_domain.h"
#include "qemu_slirp.h"
-int qemuInterfaceStartDevice(virDomainNetDef *net);
-int qemuInterfaceStartDevices(virDomainDef *def);
-int qemuInterfaceStopDevice(virDomainNetDef *net);
-int qemuInterfaceStopDevices(virDomainDef *def);
-
int qemuInterfaceDirectConnect(virDomainDef *def,
virQEMUDriver *driver,
virDomainNetDef *net,
@@ -37,12 +32,6 @@ int qemuInterfaceDirectConnect(virDomainDef *def,
size_t tapfdSize,
virNetDevVPortProfileOp vmop);
-int qemuInterfaceEthernetConnect(virDomainDef *def,
- virQEMUDriver *driver,
- virDomainNetDef *net,
- int *tapfd,
- size_t tapfdSize);
-
int qemuInterfaceBridgeConnect(virDomainDef *def,
virQEMUDriver *driver,
virDomainNetDef *net,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 63c0c62a46..991609beac 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -74,6 +74,7 @@
#include "virhostcpu.h"
#include "domain_audit.h"
#include "domain_cgroup.h"
+#include "domain_interface.h"
#include "domain_nwfilter.h"
#include "domain_postparse.h"
#include "domain_validate.h"
@@ -3121,7 +3122,7 @@ qemuProcessStartCPUs(virQEMUDriver *driver, virDomainObj *vm,
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
/* Bring up netdevs before starting CPUs */
- if (qemuInterfaceStartDevices(vm->def) < 0)
+ if (virDomainInterfaceStartDevices(vm->def) < 0)
return -1;
VIR_DEBUG("Using lock state '%s'", NULLSTR(priv->lockState));
@@ -3184,7 +3185,7 @@ int qemuProcessStopCPUs(virQEMUDriver *driver,
goto cleanup;
/* de-activate netdevs after stopping CPUs */
- ignore_value(qemuInterfaceStopDevices(vm->def));
+ ignore_value(virDomainInterfaceStopDevices(vm->def));
if (vm->job->current)
ignore_value(virTimeMillisNow(&vm->job->current->stopped));
--
2.41.0
1 year, 2 months
[libvirt PATCH v2] hypervisor: Move interface mgmt methods to hypervisor
by Praveen K Paladugu
Move guest interface management methods from qemu to hypervisor. These
methods will be shared by networking support in ch driver.
Signed-off-by: Praveen K Paladugu <prapal(a)linux.microsoft.com>
---
po/POTFILES | 1 +
src/hypervisor/domain_interface.c | 280 ++++++++++++++++++++++++++++++
src/hypervisor/domain_interface.h | 39 +++++
src/hypervisor/meson.build | 1 +
src/libvirt_private.syms | 6 +
src/qemu/qemu_command.c | 7 +-
src/qemu/qemu_hotplug.c | 3 +-
src/qemu/qemu_interface.c | 246 +-------------------------
src/qemu/qemu_interface.h | 6 -
src/qemu/qemu_process.c | 3 +-
10 files changed, 343 insertions(+), 249 deletions(-)
create mode 100644 src/hypervisor/domain_interface.c
create mode 100644 src/hypervisor/domain_interface.h
diff --git a/po/POTFILES b/po/POTFILES
index 3a51aea5cb..023c041f61 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -92,6 +92,7 @@ src/hyperv/hyperv_util.c
src/hyperv/hyperv_wmi.c
src/hypervisor/domain_cgroup.c
src/hypervisor/domain_driver.c
+src/hypervisor/domain_interface.c
src/hypervisor/virhostdev.c
src/interface/interface_backend_netcf.c
src/interface/interface_backend_udev.c
diff --git a/src/hypervisor/domain_interface.c b/src/hypervisor/domain_interface.c
new file mode 100644
index 0000000000..592c4253df
--- /dev/null
+++ b/src/hypervisor/domain_interface.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.c: methods to manage guest/domain interfaces
+ *
+ * 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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "virconftypes.h"
+#include "virmacaddr.h"
+#include "virnetdevtap.h"
+#include "domain_audit.h"
+#include "domain_conf.h"
+#include "domain_interface.h"
+#include "domain_nwfilter.h"
+#include "viralloc.h"
+#include "virebtables.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virnetdevbridge.h"
+#include "network_conf.h"
+
+#define VIR_FROM_THIS VIR_FROM_INTERFACE
+
+VIR_LOG_INIT("interface.interface_connect");
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net)
+{
+ return (virDomainNetIsVirtioModel(net) ||
+ net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
+ net->model == VIR_DOMAIN_NET_MODEL_IGB ||
+ net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
+}
+
+/* virDomainInterfaceEthernetConnect:
+ * @def: the definition of the VM
+ * @driver: qemu driver data
+ * @net: pointer to the VM's interface description
+ * @tapfd: array of file descriptor return value for the new device
+ * @tapfdsize: number of file descriptors in @tapfd
+ *
+ * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
+ * (i.e. if the connection is made with a tap device)
+ */
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+ virDomainNetDef *net,
+ ebtablesContext *ebtables,
+ bool macFilter,
+ bool privileged,
+ int *tapfd,
+ size_t tapfdSize)
+{
+ virMacAddr tapmac;
+ int ret = -1;
+ unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
+ bool template_ifname = false;
+ const char *tunpath = "/dev/net/tun";
+ const char *auditdev = tunpath;
+
+ if (net->backend.tap) {
+ tunpath = net->backend.tap;
+ if (!privileged) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("cannot use custom tap device in session mode"));
+ goto cleanup;
+ }
+ }
+ VIR_WARN("PPK: interfaceEthernetConnect Called\n");
+ if (virDomainInterfaceIsVnetCompatModel(net))
+ tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
+
+ if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
+ if (!net->ifname) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("target dev must be supplied when managed='no'"));
+ goto cleanup;
+ }
+ if (virNetDevExists(net->ifname) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("target managed='no' but specified dev doesn't exist"));
+ goto cleanup;
+ }
+
+ tap_create_flags |= VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING;
+
+ if (virNetDevMacVLanIsMacvtap(net->ifname)) {
+ auditdev = net->ifname;
+ if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
+ goto cleanup;
+ if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
+ virDomainInterfaceIsVnetCompatModel(net)) < 0) {
+ goto cleanup;
+ }
+ } else {
+ if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
+ tap_create_flags) < 0)
+ goto cleanup;
+ }
+ } else {
+
+ if (!net->ifname)
+ template_ifname = true;
+
+ if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
+ tap_create_flags) < 0) {
+ goto cleanup;
+ }
+
+ /* The tap device's MAC address cannot match the MAC address
+ * used by the guest. This results in "received packet on
+ * vnetX with own address as source address" error logs from
+ * the kernel.
+ */
+ virMacAddrSet(&tapmac, &net->mac);
+ if (tapmac.addr[0] == 0xFE)
+ tapmac.addr[0] = 0xFA;
+ else
+ tapmac.addr[0] = 0xFE;
+
+ if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
+ goto cleanup;
+
+ if (virNetDevSetOnline(net->ifname, true) < 0)
+ goto cleanup;
+ }
+
+ if (net->script &&
+ virNetDevRunEthernetScript(net->ifname, net->script) < 0)
+ goto cleanup;
+
+ if (macFilter &&
+ ebtablesAddForwardAllowIn(ebtables,
+ net->ifname,
+ &net->mac) < 0)
+ goto cleanup;
+
+ if (net->filter &&
+ virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 0) {
+ goto cleanup;
+ }
+
+ virDomainAuditNetDevice(def, net, auditdev, true);
+
+ ret = 0;
+
+ cleanup:
+ if (ret < 0) {
+ size_t i;
+
+ virDomainAuditNetDevice(def, net, auditdev, false);
+ for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
+ VIR_FORCE_CLOSE(tapfd[i]);
+ if (template_ifname)
+ VIR_FREE(net->ifname);
+ }
+
+ return ret;
+}
+
+/**
+ * qemuInterfaceStartDevice:
+ * @net: net device to start
+ *
+ * Based upon the type of device provided, perform the appropriate
+ * work to completely activate the device and make it reachable from
+ * the rest of the network.
+ */
+int
+virDomainInterfaceStartDevice(virDomainNetDef *net)
+{
+ virDomainNetType actualType = virDomainNetGetActualType(net);
+
+ switch (actualType) {
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ if (virDomainNetGetActualBridgeMACTableManager(net)
+ == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
+ /* libvirt is managing the FDB of the bridge this device
+ * is attaching to, so we have turned off learning and
+ * unicast_flood on the device to prevent the kernel from
+ * adding any FDB entries for it. This means we need to
+ * add an fdb entry ourselves, using the MAC address from
+ * the interface config.
+ */
+ if (virNetDevBridgeFDBAdd(&net->mac, net->ifname,
+ VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
+ VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
+ return -1;
+ }
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_DIRECT: {
+ const char *physdev = virDomainNetGetActualDirectDev(net);
+ bool isOnline = true;
+
+ /* set the physdev online if necessary. It may already be up,
+ * in which case we shouldn't re-up it just in case that causes
+ * some sort of "blip" in the physdev's status.
+ */
+ if (physdev && virNetDevGetOnline(physdev, &isOnline) < 0)
+ return -1;
+ if (!isOnline && virNetDevSetOnline(physdev, true) < 0)
+ return -1;
+
+ /* macvtap devices share their MAC address with the guest
+ * domain, and if they are set online prior to the domain CPUs
+ * being started, the host may send out traffic from this
+ * device that could confuse other entities on the network (in
+ * particular, if this new domain is the destination of a
+ * migration, and the source domain is still running, another
+ * host may mistakenly direct traffic for the guest to the
+ * destination domain rather than source domain). To prevent
+ * this, we create the macvtap device with IFF_UP false
+ * (i.e. "offline") then wait to bring it online until just as
+ * we are starting the domain CPUs.
+ */
+ if (virNetDevSetOnline(net->ifname, true) < 0)
+ return -1;
+ break;
+ }
+
+ case VIR_DOMAIN_NET_TYPE_ETHERNET:
+ if (virNetDevIPInfoAddToDev(net->ifname, &net->hostIP) < 0)
+ return -1;
+
+ break;
+
+ case VIR_DOMAIN_NET_TYPE_USER:
+ case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
+ case VIR_DOMAIN_NET_TYPE_SERVER:
+ case VIR_DOMAIN_NET_TYPE_CLIENT:
+ case VIR_DOMAIN_NET_TYPE_MCAST:
+ case VIR_DOMAIN_NET_TYPE_UDP:
+ case VIR_DOMAIN_NET_TYPE_INTERNAL:
+ case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+ case VIR_DOMAIN_NET_TYPE_VDPA:
+ case VIR_DOMAIN_NET_TYPE_NULL:
+ case VIR_DOMAIN_NET_TYPE_VDS:
+ case VIR_DOMAIN_NET_TYPE_LAST:
+ /* these types all require no action */
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * virDomainInterfaceStartDevices:
+ * @def: domain definition
+ *
+ * Set all ifaces associated with this domain to the online state.
+ */
+int
+virDomainInterfaceStartDevices(virDomainDef *def)
+{
+ size_t i;
+
+ for (i = 0; i < def->nnets; i++) {
+ if (virDomainInterfaceStartDevice(def->nets[i]) < 0)
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/hypervisor/domain_interface.h b/src/hypervisor/domain_interface.h
new file mode 100644
index 0000000000..5594b79bdd
--- /dev/null
+++ b/src/hypervisor/domain_interface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat, Inc.
+ * Copyright IBM Corp. 2014
+ *
+ * domain_interface.h: methods to manage guest/domain interfaces
+ *
+ * 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
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "virebtables.h"
+
+int
+virDomainInterfaceEthernetConnect(virDomainDef *def,
+ virDomainNetDef *net,
+ ebtablesContext *ebtables,
+ bool macFilter,
+ bool privileged,
+ int *tapfd,
+ size_t tapfdSize);
+
+bool
+virDomainInterfaceIsVnetCompatModel(const virDomainNetDef *net);
+
+int virDomainInterfaceStartDevice(virDomainNetDef *net);
+int virDomainInterfaceStartDevices(virDomainDef *def);
diff --git a/src/hypervisor/meson.build b/src/hypervisor/meson.build
index f35565b16b..819a9a82a2 100644
--- a/src/hypervisor/meson.build
+++ b/src/hypervisor/meson.build
@@ -1,6 +1,7 @@
hypervisor_sources = [
'domain_cgroup.c',
'domain_driver.c',
+ 'domain_interface.c',
'virclosecallbacks.c',
'virhostdev.c',
]
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4e475d5b1a..cae0ecb857 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1630,6 +1630,12 @@ virDomainDriverNodeDeviceReset;
virDomainDriverParseBlkioDeviceStr;
virDomainDriverSetupPersistentDefBlkioParams;
+# hypervisor/domain_interface.h
+virDomainInterfaceEthernetConnect;
+virDomainInterfaceIsVnetCompatModel;
+virDomainInterfaceStartDevice;
+virDomainInterfaceStartDevices;
+
# hypervisor/virclosecallbacks.h
virCloseCallbacksDomainAdd;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8a7b80719f..eda5327293 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -43,6 +43,7 @@
#include "domain_nwfilter.h"
#include "domain_addr.h"
#include "domain_conf.h"
+#include "domain_interface.h"
#include "netdev_bandwidth_conf.h"
#include "virnetdevopenvswitch.h"
#include "device_conf.h"
@@ -53,6 +54,7 @@
#include "virmdev.h"
#include "virutil.h"
+
#include <sys/stat.h>
#include <fcntl.h>
@@ -8523,7 +8525,10 @@ qemuBuildInterfaceConnect(virDomainObj *vm,
break;
case VIR_DOMAIN_NET_TYPE_ETHERNET:
- if (qemuInterfaceEthernetConnect(vm->def, priv->driver, net,
+ if (virDomainInterfaceEthernetConnect(vm->def, net,
+ priv->driver->ebtables,
+ priv->driver->config->macFilter,
+ priv->driver->privileged,
tapfd, tapfdSize) < 0)
return -1;
vhostfd = true;
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 1f7f5bdd26..8e76cb8b38 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -39,6 +39,7 @@
#include "qemu_virtiofs.h"
#include "domain_audit.h"
#include "domain_cgroup.h"
+#include "domain_interface.h"
#include "netdev_bandwidth_conf.h"
#include "domain_nwfilter.h"
#include "virlog.h"
@@ -1269,7 +1270,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
}
/* Set device online immediately */
- if (qemuInterfaceStartDevice(net) < 0)
+ if (virDomainInterfaceStartDevice(net) < 0)
goto cleanup;
qemuDomainInterfaceSetDefaultQDisc(driver, net);
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index 8856bb95a8..48e3422ae1 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -24,6 +24,7 @@
#include "network_conf.h"
#include "domain_audit.h"
#include "domain_nwfilter.h"
+#include "domain_interface.h"
#include "qemu_interface.h"
#include "viralloc.h"
#include "virlog.h"
@@ -41,110 +42,9 @@
VIR_LOG_INIT("qemu.qemu_interface");
-/**
- * qemuInterfaceStartDevice:
- * @net: net device to start
- *
- * Based upon the type of device provided, perform the appropriate
- * work to completely activate the device and make it reachable from
- * the rest of the network.
- */
-int
-qemuInterfaceStartDevice(virDomainNetDef *net)
-{
- virDomainNetType actualType = virDomainNetGetActualType(net);
-
- switch (actualType) {
- case VIR_DOMAIN_NET_TYPE_BRIDGE:
- case VIR_DOMAIN_NET_TYPE_NETWORK:
- if (virDomainNetGetActualBridgeMACTableManager(net)
- == VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
- /* libvirt is managing the FDB of the bridge this device
- * is attaching to, so we have turned off learning and
- * unicast_flood on the device to prevent the kernel from
- * adding any FDB entries for it. This means we need to
- * add an fdb entry ourselves, using the MAC address from
- * the interface config.
- */
- if (virNetDevBridgeFDBAdd(&net->mac, net->ifname,
- VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
- VIR_NETDEVBRIDGE_FDB_FLAG_TEMP) < 0)
- return -1;
- }
- break;
-
- case VIR_DOMAIN_NET_TYPE_DIRECT: {
- const char *physdev = virDomainNetGetActualDirectDev(net);
- bool isOnline = true;
-
- /* set the physdev online if necessary. It may already be up,
- * in which case we shouldn't re-up it just in case that causes
- * some sort of "blip" in the physdev's status.
- */
- if (physdev && virNetDevGetOnline(physdev, &isOnline) < 0)
- return -1;
- if (!isOnline && virNetDevSetOnline(physdev, true) < 0)
- return -1;
-
- /* macvtap devices share their MAC address with the guest
- * domain, and if they are set online prior to the domain CPUs
- * being started, the host may send out traffic from this
- * device that could confuse other entities on the network (in
- * particular, if this new domain is the destination of a
- * migration, and the source domain is still running, another
- * host may mistakenly direct traffic for the guest to the
- * destination domain rather than source domain). To prevent
- * this, we create the macvtap device with IFF_UP false
- * (i.e. "offline") then wait to bring it online until just as
- * we are starting the domain CPUs.
- */
- if (virNetDevSetOnline(net->ifname, true) < 0)
- return -1;
- break;
- }
-
- case VIR_DOMAIN_NET_TYPE_ETHERNET:
- if (virNetDevIPInfoAddToDev(net->ifname, &net->hostIP) < 0)
- return -1;
-
- break;
- case VIR_DOMAIN_NET_TYPE_USER:
- case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
- case VIR_DOMAIN_NET_TYPE_SERVER:
- case VIR_DOMAIN_NET_TYPE_CLIENT:
- case VIR_DOMAIN_NET_TYPE_MCAST:
- case VIR_DOMAIN_NET_TYPE_UDP:
- case VIR_DOMAIN_NET_TYPE_INTERNAL:
- case VIR_DOMAIN_NET_TYPE_HOSTDEV:
- case VIR_DOMAIN_NET_TYPE_VDPA:
- case VIR_DOMAIN_NET_TYPE_NULL:
- case VIR_DOMAIN_NET_TYPE_VDS:
- case VIR_DOMAIN_NET_TYPE_LAST:
- /* these types all require no action */
- break;
- }
- return 0;
-}
-/**
- * qemuInterfaceStartDevices:
- * @def: domain definition
- *
- * Set all ifaces associated with this domain to the online state.
- */
-int
-qemuInterfaceStartDevices(virDomainDef *def)
-{
- size_t i;
-
- for (i = 0; i < def->nnets; i++) {
- if (qemuInterfaceStartDevice(def->nets[i]) < 0)
- return -1;
- }
- return 0;
-}
/**
@@ -166,7 +66,7 @@ qemuInterfaceStopDevice(virDomainNetDef *net)
if (virDomainNetGetActualBridgeMACTableManager(net)
== VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LIBVIRT) {
/* remove the FDB entries that were added during
- * qemuInterfaceStartDevices()
+ * virDomainInterfaceStartDevices()
*/
if (virNetDevBridgeFDBDel(&net->mac, net->ifname,
VIR_NETDEVBRIDGE_FDB_FLAG_MASTER |
@@ -236,14 +136,7 @@ qemuInterfaceStopDevices(virDomainDef *def)
}
-static bool
-qemuInterfaceIsVnetCompatModel(const virDomainNetDef *net)
-{
- return (virDomainNetIsVirtioModel(net) ||
- net->model == VIR_DOMAIN_NET_MODEL_E1000E ||
- net->model == VIR_DOMAIN_NET_MODEL_IGB ||
- net->model == VIR_DOMAIN_NET_MODEL_VMXNET3);
-}
+
/**
@@ -271,7 +164,7 @@ qemuInterfaceDirectConnect(virDomainDef *def,
unsigned int macvlan_create_flags = VIR_NETDEV_MACVLAN_CREATE_WITH_TAP;
qemuDomainNetworkPrivate *netpriv = QEMU_DOMAIN_NETWORK_PRIVATE(net);
- if (qemuInterfaceIsVnetCompatModel(net))
+ if (virDomainInterfaceIsVnetCompatModel(net))
macvlan_create_flags |= VIR_NETDEV_MACVLAN_VNET_HDR;
if (virNetDevMacVLanCreateWithVPortProfile(net->ifname,
@@ -409,133 +302,6 @@ qemuCreateInBridgePortWithHelper(virQEMUDriverConfig *cfg,
return *tapfd < 0 ? -1 : 0;
}
-
-/* qemuInterfaceEthernetConnect:
- * @def: the definition of the VM
- * @driver: qemu driver data
- * @net: pointer to the VM's interface description
- * @tapfd: array of file descriptor return value for the new device
- * @tapfdsize: number of file descriptors in @tapfd
- *
- * Called *only* called if actualType is VIR_DOMAIN_NET_TYPE_ETHERNET
- * (i.e. if the connection is made with a tap device)
- */
-int
-qemuInterfaceEthernetConnect(virDomainDef *def,
- virQEMUDriver *driver,
- virDomainNetDef *net,
- int *tapfd,
- size_t tapfdSize)
-{
- virMacAddr tapmac;
- int ret = -1;
- unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
- bool template_ifname = false;
- g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
- const char *tunpath = "/dev/net/tun";
- const char *auditdev = tunpath;
-
- if (net->backend.tap) {
- tunpath = net->backend.tap;
- if (!driver->privileged) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("cannot use custom tap device in session mode"));
- goto cleanup;
- }
- }
-
- if (qemuInterfaceIsVnetCompatModel(net))
- tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
-
- if (net->managed_tap == VIR_TRISTATE_BOOL_NO) {
- if (!net->ifname) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("target dev must be supplied when managed='no'"));
- goto cleanup;
- }
- if (virNetDevExists(net->ifname) != 1) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("target managed='no' but specified dev doesn't exist"));
- goto cleanup;
- }
-
- tap_create_flags |= VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING;
-
- if (virNetDevMacVLanIsMacvtap(net->ifname)) {
- auditdev = net->ifname;
- if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
- goto cleanup;
- if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
- qemuInterfaceIsVnetCompatModel(net)) < 0) {
- goto cleanup;
- }
- } else {
- if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
- tap_create_flags) < 0)
- goto cleanup;
- }
- } else {
-
- if (!net->ifname)
- template_ifname = true;
-
- if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
- tap_create_flags) < 0) {
- goto cleanup;
- }
-
- /* The tap device's MAC address cannot match the MAC address
- * used by the guest. This results in "received packet on
- * vnetX with own address as source address" error logs from
- * the kernel.
- */
- virMacAddrSet(&tapmac, &net->mac);
- if (tapmac.addr[0] == 0xFE)
- tapmac.addr[0] = 0xFA;
- else
- tapmac.addr[0] = 0xFE;
-
- if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
- goto cleanup;
-
- if (virNetDevSetOnline(net->ifname, true) < 0)
- goto cleanup;
- }
-
- if (net->script &&
- virNetDevRunEthernetScript(net->ifname, net->script) < 0)
- goto cleanup;
-
- if (cfg->macFilter &&
- ebtablesAddForwardAllowIn(driver->ebtables,
- net->ifname,
- &net->mac) < 0)
- goto cleanup;
-
- if (net->filter &&
- virDomainConfNWFilterInstantiate(def->name, def->uuid, net, false) < 0) {
- goto cleanup;
- }
-
- virDomainAuditNetDevice(def, net, auditdev, true);
-
- ret = 0;
-
- cleanup:
- if (ret < 0) {
- size_t i;
-
- virDomainAuditNetDevice(def, net, auditdev, false);
- for (i = 0; i < tapfdSize && tapfd[i] >= 0; i++)
- VIR_FORCE_CLOSE(tapfd[i]);
- if (template_ifname)
- VIR_FREE(net->ifname);
- }
-
- return ret;
-}
-
-
/* qemuInterfaceBridgeConnect:
* @def: the definition of the VM
* @driver: qemu driver data
@@ -578,7 +344,7 @@ qemuInterfaceBridgeConnect(virDomainDef *def,
if (!net->ifname)
template_ifname = true;
- if (qemuInterfaceIsVnetCompatModel(net))
+ if (virDomainInterfaceIsVnetCompatModel(net))
tap_create_flags |= VIR_NETDEV_TAP_CREATE_VNET_HDR;
if (driver->privileged) {
@@ -598,7 +364,7 @@ qemuInterfaceBridgeConnect(virDomainDef *def,
* is attaching to, so we need to turn off learning and
* unicast_flood on the device to prevent the kernel from
* adding any FDB entries for it. We will add an fdb
- * entry ourselves (during qemuInterfaceStartDevices(),
+ * entry ourselves (during virDomainInterfaceStartDevices(),
* using the MAC address from the interface config.
*/
if (virNetDevBridgePortSetLearning(brname, net->ifname, false) < 0)
diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h
index 6eed3e6bd7..feb299dd6c 100644
--- a/src/qemu/qemu_interface.h
+++ b/src/qemu/qemu_interface.h
@@ -37,12 +37,6 @@ int qemuInterfaceDirectConnect(virDomainDef *def,
size_t tapfdSize,
virNetDevVPortProfileOp vmop);
-int qemuInterfaceEthernetConnect(virDomainDef *def,
- virQEMUDriver *driver,
- virDomainNetDef *net,
- int *tapfd,
- size_t tapfdSize);
-
int qemuInterfaceBridgeConnect(virDomainDef *def,
virQEMUDriver *driver,
virDomainNetDef *net,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ae0bb7bf80..8a87e7e685 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -74,6 +74,7 @@
#include "virhostcpu.h"
#include "domain_audit.h"
#include "domain_cgroup.h"
+#include "domain_interface.h"
#include "domain_nwfilter.h"
#include "domain_postparse.h"
#include "domain_validate.h"
@@ -3121,7 +3122,7 @@ qemuProcessStartCPUs(virQEMUDriver *driver, virDomainObj *vm,
g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver);
/* Bring up netdevs before starting CPUs */
- if (qemuInterfaceStartDevices(vm->def) < 0)
+ if (virDomainInterfaceStartDevices(vm->def) < 0)
return -1;
VIR_DEBUG("Using lock state '%s'", NULLSTR(priv->lockState));
--
2.41.0
1 year, 2 months
Plans for 9.9.0 release (freeze on Thursday 26 Oct)
by Jiri Denemark
We are getting close to 9.9.0 release of libvirt. To aim for the
release on Wednesday 01 Nov I suggest entering the freeze on Thursday
26 Oct and tagging RC2 on Monday 30 Oct.
I hope this works for everyone.
Jirka
1 year, 2 months
ANNOUNCE: Virtualization linting library
by Michal Prívozník
Users of virtualization may struggle with keeping their guest configuration
optimal. And while libvirt is perfect tool for its job, it merely just do
whatever it is told. For instance, it does not check whether there's enough of
free memory to start a guest. It just starts it and hope for the best.
This led management applications to have some code that performs (more or
less) similar checks. And this is my attempt to unify that code, move it out
of individual projects under this umbrella project. It's named virt-lint.
While it's written in Rust, it has C bindings from which bindings to other
languages can be written (I've written Golang so far).
I've created initial commit here:
https://gitlab.com/MichalPrivoznik/virt-lint
There is README.md which covers all the basic information.
So far, I've written four very basic checks (see src/validators.rs):
1) whether there exists set of NUMA nodes large enough to accommodate given
domain,
2) whether there exists set of NUMA nodes with enough of free memory to
accommodate given domain,
3) whether the virtualization node has suitable emulator binary for given
domain,
4) if domain is of Q35 machine type, whether it has at least one
pcie-root-port (for hotplugging).
Please keep in mind, these checks are just examples and possibly buggy.
Writing proper checks is part of future work, for now I want to gather
feedback on overall design, APIs, CLI, etc.
I've also built RPMs and copied them over here:
https://mprivozn.fedorapeople.org/rpms/virt-lint/
I appreciate any feedback.
Michal
1 year, 2 months
[PATCH v7 0/4] Migration deprecated parts
by Juan Quintela
Based on: Message-ID: <20231018100651.32674-1-quintela(a)redhat.com>
[PULL 00/11] Migration 20231018 patches
And here we are, at v7:
- drop black line at the end of deprecated.rst
- change qemu-iotest output due to warnings for deprecation.
The only real change is the output of the qemu-iotest. That is the
reason why I maintained the reviewed-by. But will be happy if anyone
of the block people ack the changes.
Thanks, Juan.
On this v6:
- Fixed Markus comments
- 1st patch is reviewed
- dropped the RFC ones.
Later, Juan.
On this v5:
- Rebased on top of last migration pull requesnt:
- address markus comments. Basically we recommend always
blockdev-mirror + NBD. In deprecated.rst we also put the posiblity
of using block-incremental and block, but we state that they are
also deprecated.
I know, I know, I deprecated them in the following patch.
- Dropped the removal of block-migration and block-incremental I am
only interested in showing why I want to remove the -b/-i options.
Please review.
Later, Juan.
On this v4:
- addressed all markus comments.
- rebased on latest.
- improve formatting of migration.json
- print block migration status when needed.
- patches 7-10 are not mean to merge, they just show why we want to
deprecate block migration and remove its support.
- Patch 7 just drop support for -i/-b and qmp equivalents.
- Patch 8 shows all the helpers and convolutions we need to have to
support that -i and -d.
- patch 9 drops block-incremental migration support.
- patch 9 drops block migration support.
Please review.
Thanks, Juan.
On this v3:
- Rebase on top of upstream.
- Changed v8.1 to 8.2 (I left the reviewed by anyways)
- missing the block deprecation code, please.
Please, review.
Later, Juan.
On this v2:
- dropped -incoming <uri> deprecation
Paolo came with a better solution using keyvalues.
- skipped field is already ready for next pull request, so dropped.
- dropped the RFC bits, nermal PATCH.
- Assessed all the review comments.
- Added indentation of migration.json.
- Used the documentation pointer to substitute block migration.
Please review.
[v1]
Hi this series describe the migration parts that have to be deprecated.
- It is an rfc because I doubt that I did the deprecation process right. Hello Markus O:-)
- skipped field: It is older than me, I have never know what it stands
for. As far as I know it has always been zero.
- inc/blk migrate command options. They are only used by block
migration (that I deprecate on the following patch). And they are really bad.
grep must_remove_block_options.
- block migration. block jobs, whatever they are called this week are
way more flexible. Current code works, but we broke it here and
there, and really nobody has stand up to maintain it. It is quite
contained and can be left there. Is anyone really using it?
- old compression method. It don't work. See last try from Lukas to
make a test that works reliabely. I failed with the same task years
ago. It is really slow, and if compression is good for you, multifd
+ zlib is going to perform/compress way more.
I don't know what to do with this code, really.
* Remove it for this release? It don't work, and haven't work
reliabely in quite a few time.
* Deprecate it and remove in another couple of releases, i.e. normal
deprecation.
* Ideas?
- -incoming <uri>
if you need to set parameters (multifd cames to mind, and preempt has
the same problem), you really needs to use defer. So what should we do here?
This part is not urget, because management apps have a working
option that are already using "defer", and the code simplifacation
if we remove it is not so big. So we can leave it until 9.0 or
whatever we think fit.
What do you think?
Later, Juan.
Juan Quintela (4):
migration: migrate 'inc' command option is deprecated.
migration: migrate 'blk' command option is deprecated.
migration: Deprecate block migration
migration: Deprecate old compression method
docs/about/deprecated.rst | 35 +++++++++++++
qapi/migration.json | 93 ++++++++++++++++++++++++++--------
migration/block.c | 3 ++
migration/migration-hmp-cmds.c | 10 ++++
migration/migration.c | 10 ++++
migration/options.c | 22 +++++++-
tests/qemu-iotests/183.out | 2 +
7 files changed, 152 insertions(+), 23 deletions(-)
--
2.41.0
1 year, 2 months