[libvirt] [PATCH] xen: Use internal interfaces in xenDomainUsedCpus
by Stefan Bader
Based on Daniel's feedback I did a split for public/private functions
for those that cause the lockup when getting XML. Maybe not complete
but at least seems to allow basic usage again (through virt-manager).
-Stefan
---
>From f406c6891fb92a45dc5d5a4d794c5d667965d096 Mon Sep 17 00:00:00 2001
From: Stefan Bader <stefan.bader(a)canonical.com>
Date: Mon, 15 Jul 2013 16:03:58 +0200
Subject: [PATCH] xen: Use internal interfaces in xenDomainUsedCpus
Since commit 95e18efd most public interfaces (xenUnified...) obtain
a virDomainDefPtr via xenGetDomainDefFor...() which take the unified
lock.
This is already taken before calling xenDomainUsedCpus(), so we get
a deadlock for active guests. Avoid this by splitting up
xenUnifiedDomainGetVcpusFlags() and xenUnifiedDomainGetVcpus() into
public and private function calls (which get the virDomainDefPtr passed)
and use those in xenDomainUsedCpus().
xenDomainUsedCpus
...
nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
return xenUnifiedDomainGetVcpusFlags(...)
...
if (!(def = xenGetDomainDefForDom(dom)))
return xenGetDomainDefForUUID(dom->conn, dom->uuid);
...
ret = xenHypervisorLookupDomainByUUID(conn, uuid);
...
xenUnifiedLock(priv);
name = xenStoreDomainGetName(conn, id);
xenUnifiedUnlock(priv);
...
if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
...
if (!(def = xenGetDomainDefForDom(dom)))
[again like above]
Signed-off-by: Stefan Bader <stefan.bader(a)canonical.com>
---
src/xen/xen_driver.c | 94 +++++++++++++++++++++++++++++++++-----------------
src/xen/xen_driver.h | 2 +-
2 files changed, 64 insertions(+), 32 deletions(-)
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index 39334b7..9ae728e 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -73,12 +73,14 @@
static int
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
+
static int
-xenUnifiedDomainGetMaxVcpus(virDomainPtr dom);
+__xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, virDomainDefPtr def,
+ unsigned int flags);
static int
-xenUnifiedDomainGetVcpus(virDomainPtr dom,
- virVcpuInfoPtr info, int maxinfo,
- unsigned char *cpumaps, int maplen);
+__xenUnifiedDomainGetVcpus(virDomainPtr dom, virDomainDefPtr def,
+ virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen);
static bool is_privileged = false;
@@ -173,6 +175,7 @@ xenNumaInit(virConnectPtr conn) {
/**
* xenDomainUsedCpus:
* @dom: the domain
+ * @def: the domain definition
*
* Analyze which set of CPUs are used by the domain and
* return a string providing the ranges.
@@ -181,7 +184,7 @@ xenNumaInit(virConnectPtr conn) {
* NULL if the domain uses all CPU or in case of error.
*/
char *
-xenDomainUsedCpus(virDomainPtr dom)
+xenDomainUsedCpus(virDomainPtr dom, virDomainDefPtr def)
{
char *res = NULL;
int ncpus;
@@ -202,9 +205,14 @@ xenDomainUsedCpus(virDomainPtr dom)
if (priv->nbNodeCpus <= 0)
return NULL;
- nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
+ nb_vcpu = __xenUnifiedDomainGetVcpusFlags(dom, def,
+ (VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_MAXIMUM));
if (nb_vcpu <= 0)
return NULL;
+ /* FIXME: To be consistent this should map to an internal interface, too.
+ * Currently it actually does map straight to xenDaemonNodeGetInfo().
+ */
if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
return NULL;
@@ -217,8 +225,8 @@ xenDomainUsedCpus(virDomainPtr dom)
VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0)
goto done;
- if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
- cpumap, cpumaplen)) >= 0) {
+ if ((ncpus = __xenUnifiedDomainGetVcpus(dom, def, cpuinfo, nb_vcpu,
+ cpumap, cpumaplen)) >= 0) {
for (n = 0; n < ncpus; n++) {
for (m = 0; m < priv->nbNodeCpus; m++) {
bool used;
@@ -1410,54 +1418,57 @@ cleanup:
}
static int
-xenUnifiedDomainGetVcpus(virDomainPtr dom,
- virVcpuInfoPtr info, int maxinfo,
- unsigned char *cpumaps, int maplen)
+__xenUnifiedDomainGetVcpus(virDomainPtr dom, virDomainDefPtr def,
+ virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen)
{
xenUnifiedPrivatePtr priv = dom->conn->privateData;
- virDomainDefPtr def = NULL;
int ret = -1;
- if (!(def = xenGetDomainDefForDom(dom)))
- goto cleanup;
-
- if (virDomainGetVcpusEnsureACL(dom->conn, def) < 0)
- goto cleanup;
-
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Cannot get VCPUs of inactive domain"));
- goto cleanup;
} else {
- ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo, cpumaps, maplen);
+ ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo,
+ cpumaps, maplen);
}
} else {
- ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps, maplen);
+ ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps,
+ maplen);
}
-cleanup:
- virDomainDefFree(def);
return ret;
}
static int
-xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+xenUnifiedDomainGetVcpus(virDomainPtr dom,
+ virVcpuInfoPtr info, int maxinfo,
+ unsigned char *cpumaps, int maplen)
{
- xenUnifiedPrivatePtr priv = dom->conn->privateData;
virDomainDefPtr def = NULL;
int ret = -1;
- virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
- VIR_DOMAIN_VCPU_CONFIG |
- VIR_DOMAIN_VCPU_MAXIMUM, -1);
-
if (!(def = xenGetDomainDefForDom(dom)))
goto cleanup;
- if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def) < 0)
+ if (virDomainGetVcpusEnsureACL(dom->conn, def) < 0)
goto cleanup;
+ ret = __xenUnifiedDomainGetVcpus(dom, def, info, maxinfo, cpumaps, maplen);
+
+cleanup:
+ virDomainDefFree(def);
+ return ret;
+}
+
+static int
+__xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, virDomainDefPtr def,
+ unsigned int flags)
+{
+ xenUnifiedPrivatePtr priv = dom->conn->privateData;
+ int ret = -1;
+
if (dom->id < 0) {
if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
ret = xenXMDomainGetVcpusFlags(dom->conn, def, flags);
@@ -1470,6 +1481,27 @@ xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags);
}
+ return ret;
+}
+
+static int
+xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
+{
+ virDomainDefPtr def = NULL;
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
+ VIR_DOMAIN_VCPU_CONFIG |
+ VIR_DOMAIN_VCPU_MAXIMUM, -1);
+
+ if (!(def = xenGetDomainDefForDom(dom)))
+ goto cleanup;
+
+ if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def) < 0)
+ goto cleanup;
+
+ ret = __xenUnifiedDomainGetVcpusFlags(dom, def, flags);
+
cleanup:
virDomainDefFree(def);
return ret;
@@ -1501,7 +1533,7 @@ xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
} else {
char *cpus;
xenUnifiedLock(priv);
- cpus = xenDomainUsedCpus(dom);
+ cpus = xenDomainUsedCpus(dom, def);
xenUnifiedUnlock(priv);
def = xenDaemonDomainGetXMLDesc(dom->conn, minidef, cpus);
VIR_FREE(cpus);
diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h
index 3c7a8cd..a363161 100644
--- a/src/xen/xen_driver.h
+++ b/src/xen/xen_driver.h
@@ -187,7 +187,7 @@ struct _xenUnifiedPrivate {
typedef struct _xenUnifiedPrivate *xenUnifiedPrivatePtr;
-char *xenDomainUsedCpus(virDomainPtr dom);
+char *xenDomainUsedCpus(virDomainPtr dom, virDomainDefPtr def);
virDomainXMLOptionPtr xenDomainXMLConfInit(void);
--
1.7.9.5
11 years, 4 months
[libvirt] [PATCH] Fix test case qemuagenttest compilation.
by Jincheng Miao
When compiling qemuagenttest, a link error occurs like:
./.libs/libqemumonitortestutils.a(qemumonitortestutils.o): In function `qemuMonitorTestFree':
libvirt/tests/qemumonitortestutils.c:346: undefined reference to `qemuMonitorClose'
./.libs/libqemumonitortestutils.a(qemumonitortestutils.o): In function `qemuMonitorTestNew':
libvirt/tests/qemumonitortestutils.c:870: undefined reference to `qemuMonitorOpen'
collect2: error: ld returned 1 exit status
And I checked this error, it caused by the position of
libqemumonitortestutils.a in gcc arguments.
If libqemumonitortestutils.a before libvirt_driver_qemu_impl.a
and libvirt_driver_network_impl.a, the compilation passed.
Otherwise, failed.
I think this should be a gcc's bug, but nevermind,
just fix it in libvirt.
---
tests/Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9c578fa..b36922e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -424,7 +424,7 @@ qemuagenttest_SOURCES = \
testutils.c testutils.h \
testutilsqemu.c testutilsqemu.h \
$(NULL)
-qemuagenttest_LDADD = $(qemu_LDADDS) libqemumonitortestutils.la
+qemuagenttest_LDADD = libqemumonitortestutils.la $(qemu_LDADDS)
qemuhotplugtest_SOURCES = \
qemuhotplugtest.c \
--
1.8.3.1
11 years, 4 months
[libvirt] [PATCH v2] bridge driver: extract platform specifics
by Roman Bogorodskiy
* Move platform specific things (e.g. firewalling and route
collision checks) into bridge_driver_platform
* Create two platform specific implementations:
- bridge_driver_linux: Linux implementation using iptables,
it's actually the code moved from bridge_driver.c
- bridge_driver_nop: dumb implementation that does nothing
---
src/network/bridge_driver_platform.h | 79 ++++
src/network/bridge_driver.c | 708 +--------------------------------
src/network/bridge_driver_linux.c | 709 ++++++++++++++++++++++++++++++++++
src/network/bridge_driver_nop.c | 78 ++++
src/network/bridge_driver_platform.c | 32 ++
po/POTFILES.in | 1 +
src/Makefile.am | 5 +-
7 files changed, 903 insertions(+), 709 deletions(-)
create mode 100644 src/network/bridge_driver_platform.h
create mode 100644 src/network/bridge_driver_linux.c
create mode 100644 src/network/bridge_driver_nop.c
create mode 100644 src/network/bridge_driver_platform.c
diff --git a/src/network/bridge_driver_platform.h b/src/network/bridge_driver_platform.h
new file mode 100644
index 0000000..289ab79
--- /dev/null
+++ b/src/network/bridge_driver_platform.h
@@ -0,0 +1,79 @@
+/*
+ * bridge_driver.h: platform specific routines for bridge driver
+ *
+ * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __VIR_BRIDGE_DRIVER_PLATFORM_H__
+# define __VIR_BRIDGE_DRIVER_PLATFORM_H__
+
+# include "internal.h"
+# include "virlog.h"
+# include "virthread.h"
+# include "virdnsmasq.h"
+# include "network_conf.h"
+
+/* Main driver state */
+struct _virNetworkDriverState {
+ virMutex lock;
+
+ virNetworkObjList networks;
+
+ char *networkConfigDir;
+ char *networkAutostartDir;
+ char *stateDir;
+ char *pidDir;
+ char *dnsmasqStateDir;
+ char *radvdStateDir;
+ dnsmasqCapsPtr dnsmasqCaps;
+};
+
+typedef struct _virNetworkDriverState virNetworkDriverState;
+typedef virNetworkDriverState *virNetworkDriverStatePtr;
+
+int networkCheckRouteCollision(virNetworkObjPtr network);
+
+int networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef);
+
+void networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef);
+
+int networkAddRoutingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef);
+
+void networkRemoveRoutingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef);
+
+int networkAddGeneralFirewallRules(virNetworkObjPtr network);
+
+void networkRemoveGeneralFirewallRules(virNetworkObjPtr network);
+
+int networkAddIpSpecificFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef);
+
+void networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef);
+
+int networkAddFirewallRules(virNetworkObjPtr network);
+
+void networkRemoveFirewallRules(virNetworkObjPtr network);
+
+#endif /* __VIR_BRIDGE_DRIVER_PLATFORM_H__ */
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 0bb57ea..a1b0dd5 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -45,6 +45,7 @@
#include "virerror.h"
#include "datatypes.h"
#include "bridge_driver.h"
+#include "bridge_driver_platform.h"
#include "network_conf.h"
#include "device_conf.h"
#include "driver.h"
@@ -69,24 +70,6 @@
#define VIR_FROM_THIS VIR_FROM_NETWORK
-/* Main driver state */
-struct _virNetworkDriverState {
- virMutex lock;
-
- virNetworkObjList networks;
-
- char *networkConfigDir;
- char *networkAutostartDir;
- char *stateDir;
- char *pidDir;
- char *dnsmasqStateDir;
- char *radvdStateDir;
- dnsmasqCapsPtr dnsmasqCaps;
-};
-
-typedef struct _virNetworkDriverState virNetworkDriverState;
-typedef virNetworkDriverState *virNetworkDriverStatePtr;
-
static void networkDriverLock(virNetworkDriverStatePtr driver)
{
virMutexLock(&driver->lock);
@@ -1507,597 +1490,6 @@ networkRefreshDaemons(virNetworkDriverStatePtr driver)
}
}
-static int
-networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
- virNetworkIpDefPtr ipdef)
-{
- int prefix = virNetworkIpDefPrefix(ipdef);
- const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
-
- if (prefix < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Invalid prefix or netmask for '%s'"),
- network->def->bridge);
- goto masqerr1;
- }
-
- /* allow forwarding packets from the bridge interface */
- if (iptablesAddForwardAllowOut(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow forwarding from '%s'"),
- network->def->bridge);
- goto masqerr1;
- }
-
- /* allow forwarding packets to the bridge interface if they are
- * part of an existing connection
- */
- if (iptablesAddForwardAllowRelatedIn(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow forwarding to '%s'"),
- network->def->bridge);
- goto masqerr2;
- }
-
- /*
- * Enable masquerading.
- *
- * We need to end up with 3 rules in the table in this order
- *
- * 1. protocol=tcp with sport mapping restriction
- * 2. protocol=udp with sport mapping restriction
- * 3. generic any protocol
- *
- * The sport mappings are required, because default IPtables
- * MASQUERADE maintain port numbers unchanged where possible.
- *
- * NFS can be configured to only "trust" port numbers < 1023.
- *
- * Guests using NAT thus need to be prevented from having port
- * numbers < 1023, otherwise they can bypass the NFS "security"
- * check on the source port number.
- *
- * Since we use '--insert' to add rules to the header of the
- * chain, we actually need to add them in the reverse of the
- * order just mentioned !
- */
-
- /* First the generic masquerade rule for other protocols */
- if (iptablesAddForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- NULL) < 0) {
- if (forwardIf)
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to enable masquerading to %s"),
- forwardIf);
- else
- virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
- _("failed to add iptables rule to enable masquerading"));
- goto masqerr3;
- }
-
- /* UDP with a source port restriction */
- if (iptablesAddForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- "udp") < 0) {
- if (forwardIf)
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to enable UDP masquerading to %s"),
- forwardIf);
- else
- virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
- _("failed to add iptables rule to enable UDP masquerading"));
- goto masqerr4;
- }
-
- /* TCP with a source port restriction */
- if (iptablesAddForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- "tcp") < 0) {
- if (forwardIf)
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to enable TCP masquerading to %s"),
- forwardIf);
- else
- virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
- _("failed to add iptables rule to enable TCP masquerading"));
- goto masqerr5;
- }
-
- return 0;
-
- masqerr5:
- iptablesRemoveForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- "udp");
- masqerr4:
- iptablesRemoveForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- NULL);
- masqerr3:
- iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf);
- masqerr2:
- iptablesRemoveForwardAllowOut(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf);
- masqerr1:
- return -1;
-}
-
-static void
-networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network,
- virNetworkIpDefPtr ipdef)
-{
- int prefix = virNetworkIpDefPrefix(ipdef);
- const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
-
- if (prefix >= 0) {
- iptablesRemoveForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- "tcp");
- iptablesRemoveForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- "udp");
- iptablesRemoveForwardMasquerade(&ipdef->address,
- prefix,
- forwardIf,
- &network->def->forward.addr,
- &network->def->forward.port,
- NULL);
-
- iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf);
- iptablesRemoveForwardAllowOut(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf);
- }
-}
-
-static int
-networkAddRoutingFirewallRules(virNetworkObjPtr network,
- virNetworkIpDefPtr ipdef)
-{
- int prefix = virNetworkIpDefPrefix(ipdef);
- const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
-
- if (prefix < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Invalid prefix or netmask for '%s'"),
- network->def->bridge);
- goto routeerr1;
- }
-
- /* allow routing packets from the bridge interface */
- if (iptablesAddForwardAllowOut(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow routing from '%s'"),
- network->def->bridge);
- goto routeerr1;
- }
-
- /* allow routing packets to the bridge interface */
- if (iptablesAddForwardAllowIn(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow routing to '%s'"),
- network->def->bridge);
- goto routeerr2;
- }
-
- return 0;
-
-routeerr2:
- iptablesRemoveForwardAllowOut(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf);
-routeerr1:
- return -1;
-}
-
-static void
-networkRemoveRoutingFirewallRules(virNetworkObjPtr network,
- virNetworkIpDefPtr ipdef)
-{
- int prefix = virNetworkIpDefPrefix(ipdef);
- const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
-
- if (prefix >= 0) {
- iptablesRemoveForwardAllowIn(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf);
-
- iptablesRemoveForwardAllowOut(&ipdef->address,
- prefix,
- network->def->bridge,
- forwardIf);
- }
-}
-
-/* Add all once/network rules required for IPv6.
- * If no IPv6 addresses are defined and <network ipv6='yes'> is
- * specified, then allow IPv6 commuinications between virtual systems.
- * If any IPv6 addresses are defined, then add the rules for regular operation.
- */
-static int
-networkAddGeneralIp6tablesRules(virNetworkObjPtr network)
-{
-
- if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
- !network->def->ipv6nogw) {
- return 0;
- }
-
- /* Catch all rules to block forwarding to/from bridges */
-
- if (iptablesAddForwardRejectOut(AF_INET6, network->def->bridge) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add ip6tables rule to block outbound traffic from '%s'"),
- network->def->bridge);
- goto err1;
- }
-
- if (iptablesAddForwardRejectIn(AF_INET6, network->def->bridge) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add ip6tables rule to block inbound traffic to '%s'"),
- network->def->bridge);
- goto err2;
- }
-
- /* Allow traffic between guests on the same bridge */
- if (iptablesAddForwardAllowCross(AF_INET6, network->def->bridge) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add ip6tables rule to allow cross bridge traffic on '%s'"),
- network->def->bridge);
- goto err3;
- }
-
- /* if no IPv6 addresses are defined, we are done. */
- if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
- return 0;
-
- /* allow DNS over IPv6 */
- if (iptablesAddTcpInput(AF_INET6, network->def->bridge, 53) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add ip6tables rule to allow DNS requests from '%s'"),
- network->def->bridge);
- goto err4;
- }
-
- if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 53) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add ip6tables rule to allow DNS requests from '%s'"),
- network->def->bridge);
- goto err5;
- }
-
- if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 547) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add ip6tables rule to allow DHCP6 requests from '%s'"),
- network->def->bridge);
- goto err6;
- }
-
- return 0;
-
- /* unwind in reverse order from the point of failure */
-err6:
- iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
-err5:
- iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
-err4:
- iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
-err3:
- iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
-err2:
- iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
-err1:
- return -1;
-}
-
-static void
-networkRemoveGeneralIp6tablesRules(virNetworkObjPtr network)
-{
- if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
- !network->def->ipv6nogw) {
- return;
- }
- if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) {
- iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 547);
- iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
- iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
- }
-
- /* the following rules are there if no IPv6 address has been defined
- * but network->def->ipv6nogw == true
- */
- iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
- iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
- iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
-}
-
-static int
-networkAddGeneralFirewallRules(virNetworkObjPtr network)
-{
- size_t i;
- virNetworkIpDefPtr ipv4def;
-
- /* First look for first IPv4 address that has dhcp or tftpboot defined. */
- /* We support dhcp config on 1 IPv4 interface only. */
- for (i = 0;
- (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
- i++) {
- if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
- break;
- }
-
- /* allow DHCP requests through to dnsmasq */
-
- if (iptablesAddTcpInput(AF_INET, network->def->bridge, 67) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow DHCP requests from '%s'"),
- network->def->bridge);
- goto err1;
- }
-
- if (iptablesAddUdpInput(AF_INET, network->def->bridge, 67) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow DHCP requests from '%s'"),
- network->def->bridge);
- goto err2;
- }
-
- /* If we are doing local DHCP service on this network, attempt to
- * add a rule that will fixup the checksum of DHCP response
- * packets back to the guests (but report failure without
- * aborting, since not all iptables implementations support it).
- */
-
- if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) &&
- (iptablesAddOutputFixUdpChecksum(network->def->bridge, 68) < 0)) {
- VIR_WARN("Could not add rule to fixup DHCP response checksums "
- "on network '%s'.", network->def->name);
- VIR_WARN("May need to update iptables package & kernel to support CHECKSUM rule.");
- }
-
- /* allow DNS requests through to dnsmasq */
- if (iptablesAddTcpInput(AF_INET, network->def->bridge, 53) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow DNS requests from '%s'"),
- network->def->bridge);
- goto err3;
- }
-
- if (iptablesAddUdpInput(AF_INET, network->def->bridge, 53) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow DNS requests from '%s'"),
- network->def->bridge);
- goto err4;
- }
-
- /* allow TFTP requests through to dnsmasq if necessary */
- if (ipv4def && ipv4def->tftproot &&
- iptablesAddUdpInput(AF_INET, network->def->bridge, 69) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow TFTP requests from '%s'"),
- network->def->bridge);
- goto err5;
- }
-
- /* Catch all rules to block forwarding to/from bridges */
-
- if (iptablesAddForwardRejectOut(AF_INET, network->def->bridge) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to block outbound traffic from '%s'"),
- network->def->bridge);
- goto err6;
- }
-
- if (iptablesAddForwardRejectIn(AF_INET, network->def->bridge) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to block inbound traffic to '%s'"),
- network->def->bridge);
- goto err7;
- }
-
- /* Allow traffic between guests on the same bridge */
- if (iptablesAddForwardAllowCross(AF_INET, network->def->bridge) < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("failed to add iptables rule to allow cross bridge traffic on '%s'"),
- network->def->bridge);
- goto err8;
- }
-
- /* add IPv6 general rules, if needed */
- if (networkAddGeneralIp6tablesRules(network) < 0) {
- goto err9;
- }
-
- return 0;
-
- /* unwind in reverse order from the point of failure */
-err9:
- iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
-err8:
- iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
-err7:
- iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
-err6:
- if (ipv4def && ipv4def->tftproot) {
- iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
- }
-err5:
- iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
-err4:
- iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
-err3:
- iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
-err2:
- iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
-err1:
- return -1;
-}
-
-static void
-networkRemoveGeneralFirewallRules(virNetworkObjPtr network)
-{
- size_t i;
- virNetworkIpDefPtr ipv4def;
-
- networkRemoveGeneralIp6tablesRules(network);
-
- for (i = 0;
- (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
- i++) {
- if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
- break;
- }
-
- iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
- iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
- iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
- if (ipv4def && ipv4def->tftproot) {
- iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
- }
- iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
- iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
- if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) {
- iptablesRemoveOutputFixUdpChecksum(network->def->bridge, 68);
- }
- iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
- iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
-}
-
-static int
-networkAddIpSpecificFirewallRules(virNetworkObjPtr network,
- virNetworkIpDefPtr ipdef)
-{
- /* NB: in the case of IPv6, routing rules are added when the
- * forward mode is NAT. This is because IPv6 has no NAT.
- */
-
- if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
- if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
- return networkAddMasqueradingFirewallRules(network, ipdef);
- else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
- return networkAddRoutingFirewallRules(network, ipdef);
- } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
- return networkAddRoutingFirewallRules(network, ipdef);
- }
- return 0;
-}
-
-static void
-networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network,
- virNetworkIpDefPtr ipdef)
-{
- if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
- if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
- networkRemoveMasqueradingFirewallRules(network, ipdef);
- else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
- networkRemoveRoutingFirewallRules(network, ipdef);
- } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
- networkRemoveRoutingFirewallRules(network, ipdef);
- }
-}
-
-/* Add all rules for all ip addresses (and general rules) on a network */
-static int
-networkAddFirewallRules(virNetworkObjPtr network)
-{
- size_t i, j;
- virNetworkIpDefPtr ipdef;
- virErrorPtr orig_error;
-
- /* Add "once per network" rules */
- if (networkAddGeneralFirewallRules(network) < 0)
- return -1;
-
- for (i = 0;
- (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
- i++) {
- /* Add address-specific iptables rules */
- if (networkAddIpSpecificFirewallRules(network, ipdef) < 0) {
- goto err;
- }
- }
- return 0;
-
-err:
- /* store the previous error message before attempting removal of rules */
- orig_error = virSaveLastError();
-
- /* The final failed call to networkAddIpSpecificFirewallRules will
- * have removed any rules it created, but we need to remove those
- * added for previous IP addresses.
- */
- for (j = 0; j < i; j++) {
- if ((ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, j)))
- networkRemoveIpSpecificFirewallRules(network, ipdef);
- }
- networkRemoveGeneralFirewallRules(network);
-
- /* return the original error */
- virSetError(orig_error);
- virFreeError(orig_error);
- return -1;
-}
-
-/* Remove all rules for all ip addresses (and general rules) on a network */
-static void
-networkRemoveFirewallRules(virNetworkObjPtr network)
-{
- size_t i;
- virNetworkIpDefPtr ipdef;
-
- for (i = 0;
- (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
- i++) {
- networkRemoveIpSpecificFirewallRules(network, ipdef);
- }
- networkRemoveGeneralFirewallRules(network);
-}
-
static void
networkReloadFirewallRules(virNetworkDriverStatePtr driver)
{
@@ -2206,104 +1598,6 @@ cleanup:
return ret;
}
-#define PROC_NET_ROUTE "/proc/net/route"
-
-/* XXX: This function can be a lot more exhaustive, there are certainly
- * other scenarios where we can ruin host network connectivity.
- * XXX: Using a proper library is preferred over parsing /proc
- */
-static int
-networkCheckRouteCollision(virNetworkObjPtr network)
-{
- int ret = 0, len;
- char *cur, *buf = NULL;
- /* allow for up to 100000 routes (each line is 128 bytes) */
- enum {MAX_ROUTE_SIZE = 128*100000};
-
- /* Read whole routing table into memory */
- if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
- goto out;
-
- /* Dropping the last character shouldn't hurt */
- if (len > 0)
- buf[len-1] = '\0';
-
- VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
-
- if (!STRPREFIX(buf, "Iface"))
- goto out;
-
- /* First line is just headings, skip it */
- cur = strchr(buf, '\n');
- if (cur)
- cur++;
-
- while (cur) {
- char iface[17], dest[128], mask[128];
- unsigned int addr_val, mask_val;
- virNetworkIpDefPtr ipdef;
- int num;
- size_t i;
-
- /* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
- char *nl = strchr(cur, '\n');
- if (nl) {
- *nl++ = '\0';
- }
-
- num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
- iface, dest, mask);
- cur = nl;
-
- if (num != 3) {
- VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
- continue;
- }
-
- if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
- VIR_DEBUG("Failed to convert network address %s to uint", dest);
- continue;
- }
-
- if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
- VIR_DEBUG("Failed to convert network mask %s to uint", mask);
- continue;
- }
-
- addr_val &= mask_val;
-
- for (i = 0;
- (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
- i++) {
-
- unsigned int net_dest;
- virSocketAddr netmask;
-
- if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
- VIR_WARN("Failed to get netmask of '%s'",
- network->def->bridge);
- continue;
- }
-
- net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
- netmask.data.inet4.sin_addr.s_addr);
-
- if ((net_dest == addr_val) &&
- (netmask.data.inet4.sin_addr.s_addr == mask_val)) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Network is already in use by interface %s"),
- iface);
- ret = -1;
- goto out;
- }
- }
- }
-
-out:
- VIR_FREE(buf);
- return ret;
-}
-
/* add an IP address to a bridge */
static int
networkAddAddrToBridge(virNetworkObjPtr network,
diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
new file mode 100644
index 0000000..80430a8
--- /dev/null
+++ b/src/network/bridge_driver_linux.c
@@ -0,0 +1,709 @@
+/*
+ * bridge_driver_linux.c: Linux implementation of bridge driver
+ *
+ * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include "viralloc.h"
+#include "virfile.h"
+#include "viriptables.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+#define PROC_NET_ROUTE "/proc/net/route"
+
+/* XXX: This function can be a lot more exhaustive, there are certainly
+ * other scenarios where we can ruin host network connectivity.
+ * XXX: Using a proper library is preferred over parsing /proc
+ */
+int networkCheckRouteCollision(virNetworkObjPtr network)
+{
+ int ret = 0, len;
+ char *cur, *buf = NULL;
+ /* allow for up to 100000 routes (each line is 128 bytes) */
+ enum {MAX_ROUTE_SIZE = 128*100000};
+
+ /* Read whole routing table into memory */
+ if ((len = virFileReadAll(PROC_NET_ROUTE, MAX_ROUTE_SIZE, &buf)) < 0)
+ goto out;
+
+ /* Dropping the last character shouldn't hurt */
+ if (len > 0)
+ buf[len-1] = '\0';
+
+ VIR_DEBUG("%s output:\n%s", PROC_NET_ROUTE, buf);
+
+ if (!STRPREFIX(buf, "Iface"))
+ goto out;
+
+ /* First line is just headings, skip it */
+ cur = strchr(buf, '\n');
+ if (cur)
+ cur++;
+
+ while (cur) {
+ char iface[17], dest[128], mask[128];
+ unsigned int addr_val, mask_val;
+ virNetworkIpDefPtr ipdef;
+ int num;
+ size_t i;
+
+ /* NUL-terminate the line, so sscanf doesn't go beyond a newline. */
+ char *nl = strchr(cur, '\n');
+ if (nl) {
+ *nl++ = '\0';
+ }
+
+ num = sscanf(cur, "%16s %127s %*s %*s %*s %*s %*s %127s",
+ iface, dest, mask);
+ cur = nl;
+
+ if (num != 3) {
+ VIR_DEBUG("Failed to parse %s", PROC_NET_ROUTE);
+ continue;
+ }
+
+ if (virStrToLong_ui(dest, NULL, 16, &addr_val) < 0) {
+ VIR_DEBUG("Failed to convert network address %s to uint", dest);
+ continue;
+ }
+
+ if (virStrToLong_ui(mask, NULL, 16, &mask_val) < 0) {
+ VIR_DEBUG("Failed to convert network mask %s to uint", mask);
+ continue;
+ }
+
+ addr_val &= mask_val;
+
+ for (i = 0;
+ (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
+ i++) {
+
+ unsigned int net_dest;
+ virSocketAddr netmask;
+
+ if (virNetworkIpDefNetmask(ipdef, &netmask) < 0) {
+ VIR_WARN("Failed to get netmask of '%s'",
+ network->def->bridge);
+ continue;
+ }
+
+ net_dest = (ipdef->address.data.inet4.sin_addr.s_addr &
+ netmask.data.inet4.sin_addr.s_addr);
+
+ if ((net_dest == addr_val) &&
+ (netmask.data.inet4.sin_addr.s_addr == mask_val)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Network is already in use by interface %s"),
+ iface);
+ ret = -1;
+ goto out;
+ }
+ }
+ }
+
+out:
+ VIR_FREE(buf);
+ return ret;
+}
+
+int networkAddMasqueradingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef)
+{
+ int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
+
+ if (prefix < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid prefix or netmask for '%s'"),
+ network->def->bridge);
+ goto masqerr1;
+ }
+
+ /* allow forwarding packets from the bridge interface */
+ if (iptablesAddForwardAllowOut(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow forwarding from '%s'"),
+ network->def->bridge);
+ goto masqerr1;
+ }
+
+ /* allow forwarding packets to the bridge interface if they are
+ * part of an existing connection
+ */
+ if (iptablesAddForwardAllowRelatedIn(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow forwarding to '%s'"),
+ network->def->bridge);
+ goto masqerr2;
+ }
+
+ /*
+ * Enable masquerading.
+ *
+ * We need to end up with 3 rules in the table in this order
+ *
+ * 1. protocol=tcp with sport mapping restriction
+ * 2. protocol=udp with sport mapping restriction
+ * 3. generic any protocol
+ *
+ * The sport mappings are required, because default IPtables
+ * MASQUERADE maintain port numbers unchanged where possible.
+ *
+ * NFS can be configured to only "trust" port numbers < 1023.
+ *
+ * Guests using NAT thus need to be prevented from having port
+ * numbers < 1023, otherwise they can bypass the NFS "security"
+ * check on the source port number.
+ *
+ * Since we use '--insert' to add rules to the header of the
+ * chain, we actually need to add them in the reverse of the
+ * order just mentioned !
+ */
+
+ /* First the generic masquerade rule for other protocols */
+ if (iptablesAddForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ NULL) < 0) {
+ if (forwardIf)
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to enable masquerading to %s"),
+ forwardIf);
+ else
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to add iptables rule to enable masquerading"));
+ goto masqerr3;
+ }
+
+ /* UDP with a source port restriction */
+ if (iptablesAddForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ "udp") < 0) {
+ if (forwardIf)
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to enable UDP masquerading to %s"),
+ forwardIf);
+ else
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to add iptables rule to enable UDP masquerading"));
+ goto masqerr4;
+ }
+
+ /* TCP with a source port restriction */
+ if (iptablesAddForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ "tcp") < 0) {
+ if (forwardIf)
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to enable TCP masquerading to %s"),
+ forwardIf);
+ else
+ virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+ _("failed to add iptables rule to enable TCP masquerading"));
+ goto masqerr5;
+ }
+
+ return 0;
+
+ masqerr5:
+ iptablesRemoveForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ "udp");
+ masqerr4:
+ iptablesRemoveForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ NULL);
+ masqerr3:
+ iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf);
+ masqerr2:
+ iptablesRemoveForwardAllowOut(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf);
+ masqerr1:
+ return -1;
+}
+
+void networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef)
+{
+ int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
+
+ if (prefix >= 0) {
+ iptablesRemoveForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ "tcp");
+ iptablesRemoveForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ "udp");
+ iptablesRemoveForwardMasquerade(&ipdef->address,
+ prefix,
+ forwardIf,
+ &network->def->forward.addr,
+ &network->def->forward.port,
+ NULL);
+
+ iptablesRemoveForwardAllowRelatedIn(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf);
+ iptablesRemoveForwardAllowOut(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf);
+ }
+}
+
+int networkAddRoutingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef)
+{
+ int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
+
+ if (prefix < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Invalid prefix or netmask for '%s'"),
+ network->def->bridge);
+ goto routeerr1;
+ }
+
+ /* allow routing packets from the bridge interface */
+ if (iptablesAddForwardAllowOut(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow routing from '%s'"),
+ network->def->bridge);
+ goto routeerr1;
+ }
+
+ /* allow routing packets to the bridge interface */
+ if (iptablesAddForwardAllowIn(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow routing to '%s'"),
+ network->def->bridge);
+ goto routeerr2;
+ }
+
+ return 0;
+
+routeerr2:
+ iptablesRemoveForwardAllowOut(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf);
+routeerr1:
+ return -1;
+}
+
+void networkRemoveRoutingFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef)
+{
+ int prefix = virNetworkIpDefPrefix(ipdef);
+ const char *forwardIf = virNetworkDefForwardIf(network->def, 0);
+
+ if (prefix >= 0) {
+ iptablesRemoveForwardAllowIn(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf);
+
+ iptablesRemoveForwardAllowOut(&ipdef->address,
+ prefix,
+ network->def->bridge,
+ forwardIf);
+ }
+}
+
+/* Add all once/network rules required for IPv6.
+ * If no IPv6 addresses are defined and <network ipv6='yes'> is
+ * specified, then allow IPv6 commuinications between virtual systems.
+ * If any IPv6 addresses are defined, then add the rules for regular operation.
+ */
+static int
+networkAddGeneralIp6tablesRules(virNetworkObjPtr network)
+{
+
+ if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
+ !network->def->ipv6nogw) {
+ return 0;
+ }
+
+ /* Catch all rules to block forwarding to/from bridges */
+
+ if (iptablesAddForwardRejectOut(AF_INET6, network->def->bridge) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add ip6tables rule to block outbound traffic from '%s'"),
+ network->def->bridge);
+ goto err1;
+ }
+
+ if (iptablesAddForwardRejectIn(AF_INET6, network->def->bridge) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add ip6tables rule to block inbound traffic to '%s'"),
+ network->def->bridge);
+ goto err2;
+ }
+
+ /* Allow traffic between guests on the same bridge */
+ if (iptablesAddForwardAllowCross(AF_INET6, network->def->bridge) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add ip6tables rule to allow cross bridge traffic on '%s'"),
+ network->def->bridge);
+ goto err3;
+ }
+
+ /* if no IPv6 addresses are defined, we are done. */
+ if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0))
+ return 0;
+
+ /* allow DNS over IPv6 */
+ if (iptablesAddTcpInput(AF_INET6, network->def->bridge, 53) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add ip6tables rule to allow DNS requests from '%s'"),
+ network->def->bridge);
+ goto err4;
+ }
+
+ if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 53) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add ip6tables rule to allow DNS requests from '%s'"),
+ network->def->bridge);
+ goto err5;
+ }
+
+ if (iptablesAddUdpInput(AF_INET6, network->def->bridge, 547) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add ip6tables rule to allow DHCP6 requests from '%s'"),
+ network->def->bridge);
+ goto err6;
+ }
+
+ return 0;
+
+ /* unwind in reverse order from the point of failure */
+err6:
+ iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
+err5:
+ iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
+err4:
+ iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
+err3:
+ iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
+err2:
+ iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
+err1:
+ return -1;
+}
+
+static void
+networkRemoveGeneralIp6tablesRules(virNetworkObjPtr network)
+{
+ if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) &&
+ !network->def->ipv6nogw) {
+ return;
+ }
+ if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) {
+ iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 547);
+ iptablesRemoveUdpInput(AF_INET6, network->def->bridge, 53);
+ iptablesRemoveTcpInput(AF_INET6, network->def->bridge, 53);
+ }
+
+ /* the following rules are there if no IPv6 address has been defined
+ * but network->def->ipv6nogw == true
+ */
+ iptablesRemoveForwardAllowCross(AF_INET6, network->def->bridge);
+ iptablesRemoveForwardRejectIn(AF_INET6, network->def->bridge);
+ iptablesRemoveForwardRejectOut(AF_INET6, network->def->bridge);
+}
+
+int networkAddGeneralFirewallRules(virNetworkObjPtr network)
+{
+ size_t i;
+ virNetworkIpDefPtr ipv4def;
+
+ /* First look for first IPv4 address that has dhcp or tftpboot defined. */
+ /* We support dhcp config on 1 IPv4 interface only. */
+ for (i = 0;
+ (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
+ i++) {
+ if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
+ break;
+ }
+
+ /* allow DHCP requests through to dnsmasq */
+
+ if (iptablesAddTcpInput(AF_INET, network->def->bridge, 67) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow DHCP requests from '%s'"),
+ network->def->bridge);
+ goto err1;
+ }
+
+ if (iptablesAddUdpInput(AF_INET, network->def->bridge, 67) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow DHCP requests from '%s'"),
+ network->def->bridge);
+ goto err2;
+ }
+
+ /* If we are doing local DHCP service on this network, attempt to
+ * add a rule that will fixup the checksum of DHCP response
+ * packets back to the guests (but report failure without
+ * aborting, since not all iptables implementations support it).
+ */
+
+ if (ipv4def && (ipv4def->nranges || ipv4def->nhosts) &&
+ (iptablesAddOutputFixUdpChecksum(network->def->bridge, 68) < 0)) {
+ VIR_WARN("Could not add rule to fixup DHCP response checksums "
+ "on network '%s'.", network->def->name);
+ VIR_WARN("May need to update iptables package & kernel to support CHECKSUM rule.");
+ }
+
+ /* allow DNS requests through to dnsmasq */
+ if (iptablesAddTcpInput(AF_INET, network->def->bridge, 53) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow DNS requests from '%s'"),
+ network->def->bridge);
+ goto err3;
+ }
+
+ if (iptablesAddUdpInput(AF_INET, network->def->bridge, 53) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow DNS requests from '%s'"),
+ network->def->bridge);
+ goto err4;
+ }
+
+ /* allow TFTP requests through to dnsmasq if necessary */
+ if (ipv4def && ipv4def->tftproot &&
+ iptablesAddUdpInput(AF_INET, network->def->bridge, 69) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow TFTP requests from '%s'"),
+ network->def->bridge);
+ goto err5;
+ }
+
+ /* Catch all rules to block forwarding to/from bridges */
+
+ if (iptablesAddForwardRejectOut(AF_INET, network->def->bridge) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to block outbound traffic from '%s'"),
+ network->def->bridge);
+ goto err6;
+ }
+
+ if (iptablesAddForwardRejectIn(AF_INET, network->def->bridge) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to block inbound traffic to '%s'"),
+ network->def->bridge);
+ goto err7;
+ }
+
+ /* Allow traffic between guests on the same bridge */
+ if (iptablesAddForwardAllowCross(AF_INET, network->def->bridge) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow cross bridge traffic on '%s'"),
+ network->def->bridge);
+ goto err8;
+ }
+
+ /* add IPv6 general rules, if needed */
+ if (networkAddGeneralIp6tablesRules(network) < 0) {
+ goto err9;
+ }
+
+ return 0;
+
+ /* unwind in reverse order from the point of failure */
+err9:
+ iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
+err8:
+ iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
+err7:
+ iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
+err6:
+ if (ipv4def && ipv4def->tftproot) {
+ iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
+ }
+err5:
+ iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
+err4:
+ iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
+err3:
+ iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
+err2:
+ iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
+err1:
+ return -1;
+}
+
+void networkRemoveGeneralFirewallRules(virNetworkObjPtr network)
+{
+ size_t i;
+ virNetworkIpDefPtr ipv4def;
+
+ networkRemoveGeneralIp6tablesRules(network);
+
+ for (i = 0;
+ (ipv4def = virNetworkDefGetIpByIndex(network->def, AF_INET, i));
+ i++) {
+ if (ipv4def->nranges || ipv4def->nhosts || ipv4def->tftproot)
+ break;
+ }
+
+ iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
+ iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
+ iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
+ if (ipv4def && ipv4def->tftproot) {
+ iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
+ }
+ iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
+ iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
+ if (ipv4def && (ipv4def->nranges || ipv4def->nhosts)) {
+ iptablesRemoveOutputFixUdpChecksum(network->def->bridge, 68);
+ }
+ iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
+ iptablesRemoveTcpInput(AF_INET, network->def->bridge, 67);
+}
+
+int networkAddIpSpecificFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef)
+{
+ /* NB: in the case of IPv6, routing rules are added when the
+ * forward mode is NAT. This is because IPv6 has no NAT.
+ */
+
+ if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
+ if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
+ return networkAddMasqueradingFirewallRules(network, ipdef);
+ else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
+ return networkAddRoutingFirewallRules(network, ipdef);
+ } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
+ return networkAddRoutingFirewallRules(network, ipdef);
+ }
+ return 0;
+}
+
+void networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network,
+ virNetworkIpDefPtr ipdef)
+{
+ if (network->def->forward.type == VIR_NETWORK_FORWARD_NAT) {
+ if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))
+ networkRemoveMasqueradingFirewallRules(network, ipdef);
+ else if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
+ networkRemoveRoutingFirewallRules(network, ipdef);
+ } else if (network->def->forward.type == VIR_NETWORK_FORWARD_ROUTE) {
+ networkRemoveRoutingFirewallRules(network, ipdef);
+ }
+}
+
+/* Add all rules for all ip addresses (and general rules) on a network */
+int networkAddFirewallRules(virNetworkObjPtr network)
+{
+ size_t i, j;
+ virNetworkIpDefPtr ipdef;
+ virErrorPtr orig_error;
+
+ /* Add "once per network" rules */
+ if (networkAddGeneralFirewallRules(network) < 0)
+ return -1;
+
+ for (i = 0;
+ (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
+ i++) {
+ /* Add address-specific iptables rules */
+ if (networkAddIpSpecificFirewallRules(network, ipdef) < 0) {
+ goto err;
+ }
+ }
+ return 0;
+
+err:
+ /* store the previous error message before attempting removal of rules */
+ orig_error = virSaveLastError();
+
+ /* The final failed call to networkAddIpSpecificFirewallRules will
+ * have removed any rules it created, but we need to remove those
+ * added for previous IP addresses.
+ */
+ for (j = 0; j < i; j++) {
+ if ((ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, j)))
+ networkRemoveIpSpecificFirewallRules(network, ipdef);
+ }
+ networkRemoveGeneralFirewallRules(network);
+
+ /* return the original error */
+ virSetError(orig_error);
+ virFreeError(orig_error);
+ return -1;
+}
+
+/* Remove all rules for all ip addresses (and general rules) on a network */
+void networkRemoveFirewallRules(virNetworkObjPtr network)
+{
+ size_t i;
+ virNetworkIpDefPtr ipdef;
+
+ for (i = 0;
+ (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i));
+ i++) {
+ networkRemoveIpSpecificFirewallRules(network, ipdef);
+ }
+ networkRemoveGeneralFirewallRules(network);
+}
diff --git a/src/network/bridge_driver_nop.c b/src/network/bridge_driver_nop.c
new file mode 100644
index 0000000..f983402
--- /dev/null
+++ b/src/network/bridge_driver_nop.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+int networkCheckRouteCollision(virNetworkObjPtr network)
+{
+ return 0;
+}
+
+int networkAddMasqueradingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
+ virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void networkRemoveMasqueradingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
+ virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
+{
+}
+
+int networkAddRoutingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
+ virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void networkRemoveRoutingFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
+ virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
+{
+}
+
+int networkAddGeneralFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void networkRemoveGeneralFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
+{
+}
+
+int networkAddIpSpecificFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
+ virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void networkRemoveIpSpecificFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED,
+ virNetworkIpDefPtr ipdef ATTRIBUTE_UNUSED)
+{
+}
+
+int networkAddFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void networkRemoveFirewallRules(virNetworkObjPtr network ATTRIBUTE_UNUSED)
+{
+}
diff --git a/src/network/bridge_driver_platform.c b/src/network/bridge_driver_platform.c
new file mode 100644
index 0000000..1d2fc02
--- /dev/null
+++ b/src/network/bridge_driver_platform.c
@@ -0,0 +1,32 @@
+/*
+ * bridge_driver_platform.c: platform specific part of bridge driver
+ *
+ * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * 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/>.
+ *
+ * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include "bridge_driver_platform.h"
+
+#if defined(__linux__)
+# include "bridge_driver_linux.c"
+#else
+# include "bridge_driver_nop.c"
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1fd84af..24b32db 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -70,6 +70,7 @@ src/lxc/lxc_process.c
src/libxl/libxl_driver.c
src/libxl/libxl_conf.c
src/network/bridge_driver.c
+src/network/bridge_driver_linux.c
src/node_device/node_device_driver.c
src/node_device/node_device_hal.c
src/node_device/node_device_linux_sysfs.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 84372cb..80309fa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -725,8 +725,9 @@ PARALLELS_DRIVER_SOURCES = \
parallels/parallels_storage.c \
parallels/parallels_network.c
-NETWORK_DRIVER_SOURCES = \
- network/bridge_driver.h network/bridge_driver.c
+NETWORK_DRIVER_SOURCES = \
+ network/bridge_driver.h network/bridge_driver.c \
+ network/bridge_driver_platform.h network/bridge_driver_platform.c
INTERFACE_DRIVER_SOURCES =
--
1.7.9.5
11 years, 5 months
[libvirt] [PATCH 00/20] tests: add qemu agent test
by Peter Krempa
As promised earlier I'm sending a unit test for guest agent interaction.
This series contains a few refactors and additions of monitor test utils
and then add tests for all agent interaction functions. The refactors
done in this series will allow to do a more thorough testing on the json
monitor too.
The small drawback of this test suite is a 6 second run time introduced
to test timeout of a guest agent command. The test may be removed in
case it's too much.
Peter Krempa (20):
conf: Export virDomainChrSourceDefClear()
qemu_agent: Output newline at the end of the sync JSON message
qemu_agent: Move updater function for VCPU hotplug into qemu_agent.c
qemu_agent: Remove obvious comments
qemumonitortestutils: Use consistent header style and line spacing
qemumonitortestutils: Use VIR_DELETE_ELEMENT and VIR_APPEND_ELEMENT
qemumonitortestutils: remove multiline function calls
qemumonitortestutils: Don't crash on non fully initialized test
qemumonitortestutils: Split up creation of the test to allow reuse
qemumonitortestutils: Refactor the test helpers to allow reuse
qemumonitortestutils: Split lines on \n instead of \r\n
qemumonitortestutils: Add instrumentation for guest agent testing
qemumonitortestutils: Improve error reporting from mock qemu monitor
qemumonitortestutils: Add the ability to check arguments of commands
tests: Add qemuagenttest
qemuagenttest: Test the filesystem trimming
qemuagenttest: Add testing of agent suspend modes
qemuagenttest: Introduce testing of shutdown commands
qemuagenttest: Test arbitrary qemu commands and timeouting of commands
qemuagenttest: Add tests for CPU plug functions and helpers
.gitignore | 1 +
src/conf/domain_conf.c | 2 +-
src/conf/domain_conf.h | 2 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_agent.c | 73 ++++-
src/qemu/qemu_agent.h | 3 +
src/qemu/qemu_driver.c | 64 +---
tests/Makefile.am | 11 +-
tests/qemuagenttest.c | 580 ++++++++++++++++++++++++++++++++++++
tests/qemumonitortestutils.c | 684 +++++++++++++++++++++++++++++++++----------
tests/qemumonitortestutils.h | 39 ++-
11 files changed, 1231 insertions(+), 229 deletions(-)
create mode 100644 tests/qemuagenttest.c
--
1.8.3.2
11 years, 5 months
[libvirt] [PATCH 0/2] add VIR_TEST_EXPENSIVE for faster 'make check' by default
by Eric Blake
Based on discussion of Peter's recent test additions, and
whether we should sleep waiting for a timeout by default.
I did _not_ wire up the use of VIR_TEST_EXPENSIVE as a way
to bypass Peter's sleep test, although I can help with that
as needed (although in Peter's case, it may be simpler to
just getenv("VIR_TEST_EXPENSIVE") inside the C code, instead
of trying to hack tests/Makefile.am to be conditional).
Tested with 'make distcheck' in both in-tree and VPATH builds
(which also the configure defaults when unpacking a tarball),
and in setups where I explicitly used --enable-gnulib-tests or
--disable-gnulib-tests, vs. running 'make check
VIR_TEST_EXPENSIVE=1'; in all cases, the gnulib tests were
skipped only when expected.
Patch 1/2 is something I noticed on the side (basically
side work from my first approach to compile out the directory
at configure time, but that approach failed 'make check');
patch 2/2 can be applied independently, and this is only a
series because both patches touch configure.
I realized (only now that I am sending this patch) that my
patch is one-way: you can turn on expensive tests (either at
configure time or at runtime) but can't turn them off.
Automake was able to have 'make V=0' and 'make V=1' override
configure defaults in both directions by using nested make
expansion, so if it is deemed necessary, I could respin to
try that approach instead of the approach I used here, where
an explicit VIR_TEST_EXPENSIVE=0 would then disable the tests
regardless of the choice made during configure. On the other
hand, having only a one-way road for turning on tests, with
no counterpart for turning them off, seems adequate.
I'm also open to bikeshedding, such as whether the configure
options should be named --enable-expensive-tests instead of
--enable-gnulib-tests, on the grounds that we might want
to make tests/Makefile.am conditional after all.
Eric Blake (2):
maint: use modern autoconf idioms
build: add configure option to disable gnulib tests
HACKING | 9 ++++++++
autobuild.sh | 3 +++
bootstrap.conf | 3 ++-
configure.ac | 60 ++++++++++++++++++++++++++++++++----------------
docs/hacking.html.in | 13 +++++++++++
gnulib/tests/Makefile.am | 13 ++++++++++-
libvirt.spec.in | 1 +
mingw-libvirt.spec.in | 4 ++--
8 files changed, 82 insertions(+), 24 deletions(-)
--
1.8.3.1
11 years, 5 months
[libvirt] [PATCH v2 0/3] ensure diskchain is not broken on guest bootup
by Guannan Ren
v1->v2: Add a helper function qemuDiskChainCheckBroken to check diskchain
after invoking qemuDomainDetermineDiskChain()
This patchset try to check whether the diskchain is broken or not when domain
boot up. If dischain is broken, report like:
virsh start rhel6qcow2
error: Failed to start domain rhel6qcow2
error: invalid argument: Backing file '/var/lib/libvirt/images/thirddisk' of \
image '/var/lib/libvirt/images/thirddisk.snap3' is missing.
For storage pool, it still can list volumes out even if their diskchain is broken
Guannan Ren(3)
qemu: refactor qemuDomainCheckDiskPresence for only disk presence check
qemu: add helper functions for diskchain checking
qemu: check presence of each disk and its backing file as well
src/libvirt_private.syms | 1 +
src/qemu/qemu_domain.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
src/qemu/qemu_domain.h | 3 ++
src/qemu/qemu_process.c | 6 ----
src/util/virstoragefile.c | 47 +++++++++++++++++++++++++++++++
src/util/virstoragefile.h | 2 ++
6 files changed, 141 insertions(+), 51 deletions(-)
11 years, 5 months
[libvirt] [PATCH] Configuring systemd to restart libvirt on abort
by Mooli Tayer
From: Mooli Tayer <mtayer(a)redhat.com>
This will create a respawn behaviour in case libvirt
process exits due to an uncaught signal not specified
as a clean exit status.
see http://www.freedesktop.org/software/systemd/man/systemd.service.html
---
daemon/libvirtd.service.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/daemon/libvirtd.service.in b/daemon/libvirtd.service.in
index aa5913b..b3c0849 100644
--- a/daemon/libvirtd.service.in
+++ b/daemon/libvirtd.service.in
@@ -15,6 +15,7 @@ EnvironmentFile=-/etc/sysconfig/libvirtd
ExecStart=@sbindir@/libvirtd $LIBVIRTD_ARGS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
+Restart=on-abort
# Override the maximum number of opened files
#LimitNOFILE=2048
--
1.8.3.1
11 years, 5 months
[libvirt] [PATCH] xen: Avoid double free of virDomainDef in xenDaemonCreateXML
by Stefan Bader
Beside dumpxml still being broken with the xen driver (hint [1] ;) )
there is also a quite annoying problem of creating new definitions
now failing. Using virt-manager this even disrupts the connection
to the host and the guest is not created persistent although
it does come up.
-Stefan
[1] https://www.redhat.com/archives/libvir-list/2013-July/msg01183.html
>From 0e90fac9004996a6517ce1bd4d7b9c6ebef6c45c Mon Sep 17 00:00:00 2001
From: Stefan Bader <stefan.bader(a)canonical.com>
Date: Tue, 30 Jul 2013 20:48:33 +0200
Subject: [PATCH] xen: Avoid double free of virDomainDef in xenDaemonCreateXML
The virDomainDef is allocated by the caller and also used after
calling to xenDaemonCreateXML. So it must not get freed by the
callee.
Signed-off-by: Stefan Bader <stefan.bader(a)canonical.com>
---
src/xen/xend_internal.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 9d61fca..1ce36e6 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -2171,7 +2171,6 @@ xenDaemonCreateXML(virConnectPtr conn, virDomainDefPtr def)
if (xenDaemonDomainResume(conn, def) < 0)
goto error;
- virDomainDefFree(def);
return 0;
error:
--
1.8.1.2
11 years, 5 months
[libvirt] [PATCH] Don't mark parentIndex with ATTRIBUTE_UNUSED
by Ján Tomko
parentIndex is used in virNetworkDefUpdateIPDHCPRange
---
Pushed as trivial.
src/conf/network_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index b903df9..e3998f3 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -3416,15 +3416,15 @@ cleanup:
virNetworkDHCPHostDefClear(&host);
return ret;
}
static int
virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
unsigned int command,
- int parentIndex ATTRIBUTE_UNUSED,
+ int parentIndex,
xmlXPathContextPtr ctxt,
/* virNetworkUpdateFlags */
unsigned int fflags ATTRIBUTE_UNUSED)
{
size_t i;
int ret = -1;
virNetworkIpDefPtr ipdef = virNetworkIpDefByIndex(def, parentIndex);
--
1.8.1.5
11 years, 5 months
[libvirt] [PATCH] Remove VIR_DOMAIN_SHUTDOWN_CRASHED from public API
by Daniel P. Berrange
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The VIR_DOMAIN_SHUTDOWN_CRASHED state constant does not appear
to be used in the QEMU code anyway. It also doesn't make much
(any) sense, since the 'shutdown' state is a transient state
between 'running' and 'shutoff' which is only used by the Xen
driver.
It was added in commit 14e7e0ae8db9843aea80245a3d9e6cf5f2ef720d
which post-dates v1.1.0, so is safe to remove before 1.1.1
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
include/libvirt/libvirt.h.in | 1 -
src/conf/domain_conf.c | 3 +--
tools/virsh-domain-monitor.c | 2 --
3 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index c0eb25b..4eae7bf 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -191,7 +191,6 @@ typedef enum {
typedef enum {
VIR_DOMAIN_SHUTDOWN_UNKNOWN = 0, /* the reason is unknown */
VIR_DOMAIN_SHUTDOWN_USER = 1, /* shutting down on user request */
- VIR_DOMAIN_SHUTDOWN_CRASHED = 2, /* domain crashed */
#ifdef VIR_ENUM_SENTINELS
VIR_DOMAIN_SHUTDOWN_LAST
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a86be8c..783df96 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -667,8 +667,7 @@ VIR_ENUM_IMPL(virDomainPausedReason, VIR_DOMAIN_PAUSED_LAST,
VIR_ENUM_IMPL(virDomainShutdownReason, VIR_DOMAIN_SHUTDOWN_LAST,
"unknown",
- "user",
- "crashed")
+ "user")
VIR_ENUM_IMPL(virDomainShutoffReason, VIR_DOMAIN_SHUTOFF_LAST,
"unknown",
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 773f96d..98fe7fe 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -240,8 +240,6 @@ vshDomainStateReasonToString(int state, int reason)
switch ((virDomainShutdownReason) reason) {
case VIR_DOMAIN_SHUTDOWN_USER:
return N_("user");
- case VIR_DOMAIN_SHUTDOWN_CRASHED:
- return N_("crashed");
case VIR_DOMAIN_SHUTDOWN_UNKNOWN:
case VIR_DOMAIN_SHUTDOWN_LAST:
;
--
1.8.1.4
11 years, 5 months