This patch allows libvirt to add interfaces to already
existing Open vSwitch bridges. The following syntax in
domain XML file must be used:
<interface type='bridge'>
<mac address='52:54:00:d0:3f:f2'/>
<source bridge='ovsbr'/>
<virtualport type='openvswitch'>
<parameters interfaceid='921a80cd-e6de-5a2e-db9c-ab27f15a6e1d'/>
</virtualport>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
</interface>
or if libvirt should auto-generate the interfaceid us following syntax:
<interface type='bridge'>
<mac address='52:54:00:d0:3f:f2'/>
<source bridge='ovsbr'/>
<virtualport type='openvswitch'>
</virtualport>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x03' function='0x0'/>
</interface>
To create Open vSwitch bridge us following command:
ovs-vsctl add-br ovsbr
1. This patch has been tested only on Ubuntu 11.10 with KVM
2. Auto-generated interfaceid is not persistent across libvirt reboots
---
configure.ac | 5 ++
src/Makefile.am | 2 +
src/conf/domain_conf.c | 46 ++++++++++++++
src/conf/domain_conf.h | 6 ++
src/conf/netdev_openvswitch_conf.c | 94 +++++++++++++++++++++++++++++
src/conf/netdev_openvswitch_conf.h | 39 ++++++++++++
src/libvirt_private.syms | 12 ++++
src/lxc/lxc_driver.c | 19 ++++--
src/network/bridge_driver.c | 3 +-
src/qemu/qemu_command.c | 3 +-
src/qemu/qemu_hotplug.c | 7 ++-
src/qemu/qemu_process.c | 3 +
src/uml/uml_conf.c | 3 +-
src/util/uuid.c | 19 ++++++
src/util/uuid.h | 1 +
src/util/virnetdevopenvswitch.c | 114 ++++++++++++++++++++++++++++++++++++
src/util/virnetdevopenvswitch.h | 46 ++++++++++++++
src/util/virnetdevtap.c | 32 +++++++++-
src/util/virnetdevtap.h | 8 ++-
19 files changed, 447 insertions(+), 15 deletions(-)
create mode 100644 src/conf/netdev_openvswitch_conf.c
create mode 100644 src/conf/netdev_openvswitch_conf.h
create mode 100644 src/util/virnetdevopenvswitch.c
create mode 100644 src/util/virnetdevopenvswitch.h
diff --git a/configure.ac b/configure.ac
index 9fb7bfc..dca178f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -213,6 +213,8 @@ AC_PATH_PROG([UDEVSETTLE], [udevsettle], [],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_PATH_PROG([MODPROBE], [modprobe], [],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
+AC_PATH_PROG([OVSVSCTL], [ovs-vsctl], [ovs-vsctl],
+ [/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_DEFINE_UNQUOTED([DNSMASQ],["$DNSMASQ"],
[Location or name of the dnsmasq program])
@@ -220,6 +222,9 @@ AC_DEFINE_UNQUOTED([RADVD],["$RADVD"],
[Location or name of the radvd program])
AC_DEFINE_UNQUOTED([TC],["$TC"],
[Location or name of the tc profram (see iproute2)])
+AC_DEFINE_UNQUOTED([OVSVSCTL],["$OVSVSCTL"],
+ [Location or name of the ovs-vsctl program])
+
if test -n "$UDEVADM"; then
AC_DEFINE_UNQUOTED([UDEVADM],["$UDEVADM"],
[Location or name of the udevadm program])
diff --git a/src/Makefile.am b/src/Makefile.am
index a3dd847..79a2dde 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -95,6 +95,7 @@ UTIL_SOURCES = \
util/virmacaddr.h util/virmacaddr.c \
util/virnetdev.h util/virnetdev.c \
util/virnetdevbandwidth.h util/virnetdevbandwidth.c \
+ util/virnetdevopenvswitch.h util/virnetdevopenvswitch.c \
util/virnetdevbridge.h util/virnetdevbridge.c \
util/virnetdevmacvlan.c util/virnetdevmacvlan.h \
util/virnetdevtap.h util/virnetdevtap.c \
@@ -136,6 +137,7 @@ LOCK_DRIVER_SANLOCK_SOURCES = \
NETDEV_CONF_SOURCES = \
conf/netdev_bandwidth_conf.h conf/netdev_bandwidth_conf.c \
+ conf/netdev_openvswitch_conf.h conf/netdev_openvswitch_conf.c \
conf/netdev_vport_profile_conf.h conf/netdev_vport_profile_conf.c
# XML configuration format handling sources
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index aa4b32d..abec371 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -31,6 +31,7 @@
#include <sys/time.h>
#include <strings.h>
+#include "internal.h"
#include "virterror_internal.h"
#include "datatypes.h"
#include "domain_conf.h"
@@ -50,6 +51,7 @@
#include "count-one-bits.h"
#include "secret_conf.h"
#include "netdev_vport_profile_conf.h"
+#include "netdev_openvswitch_conf.h"
#include "netdev_bandwidth_conf.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@@ -952,6 +954,7 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
+ VIR_FREE(def->data.bridge.ovsPort);
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
VIR_FREE(def->data.direct.linkdev);
@@ -995,6 +998,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
VIR_FREE(def->data.bridge.ipaddr);
+ VIR_FREE(def->data.bridge.ovsPort);
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
@@ -3737,7 +3741,15 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
}
if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+ xmlNodePtr virtPortNode = virXPathNode("./virtualport", ctxt);
actual->data.bridge.brname =
virXPathString("string(./source[1]/@bridge)", ctxt);
+ if (virtPortNode && virXMLPropString(virtPortNode, "type")
&&
+ STREQ(virXMLPropString(virtPortNode, "type"),
"openvswitch")) {
+ if (!(actual->data.bridge.ovsPort =
+ virNetDevOpenvswitchPortParse(virtPortNode))) {
+ goto error;
+ }
+ }
} else if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
xmlNodePtr virtPortNode;
@@ -3817,6 +3829,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *linkstate = NULL;
virNWFilterHashTablePtr filterparams = NULL;
virNetDevVPortProfilePtr virtPort = NULL;
+ virNetDevOpenvswitchPortPtr ovsPort = NULL;
virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node;
int ret;
@@ -3870,6 +3883,13 @@ virDomainNetDefParseXML(virCapsPtr caps,
xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
if (!(virtPort = virNetDevVPortProfileParse(cur)))
goto error;
+ } else if ((ovsPort == NULL) &&
+ ((def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
+ xmlStrEqual(cur->name, BAD_CAST "virtualport")
&&
+ virXMLPropString(cur, "type") &&
+ STREQ(virXMLPropString(cur, "type"),
"openvswitch"))) {
+ if (!(ovsPort = virNetDevOpenvswitchPortParse(cur)))
+ goto error;
} else if ((network == NULL) &&
((def->type == VIR_DOMAIN_NET_TYPE_SERVER) ||
(def->type == VIR_DOMAIN_NET_TYPE_CLIENT) ||
@@ -4005,6 +4025,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
def->data.bridge.ipaddr = address;
address = NULL;
}
+ def->data.bridge.ovsPort = ovsPort;
+ ovsPort = NULL;
break;
case VIR_DOMAIN_NET_TYPE_CLIENT:
@@ -10427,6 +10449,12 @@ virDomainActualNetDefFormat(virBufferPtr buf,
case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferEscapeString(buf, " <source
bridge='%s'/>\n",
def->data.bridge.brname);
+ if (def->data.bridge.ovsPort) {
+ virBufferAdjustIndent(buf, 6);
+ if (virNetDevOpenvswitchPortFormat(def->data.bridge.ovsPort, buf) < 0)
+ return -1;
+ virBufferAdjustIndent(buf, -6);
+ }
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
@@ -10514,6 +10542,12 @@ virDomainNetDefFormat(virBufferPtr buf,
if (def->data.bridge.ipaddr)
virBufferAsprintf(buf, " <ip address='%s'/>\n",
def->data.bridge.ipaddr);
+ if (def->data.bridge.ovsPort) {
+ virBufferAdjustIndent(buf, 6);
+ if (virNetDevOpenvswitchPortFormat(def->data.bridge.ovsPort, buf) < 0)
+ return -1;
+ virBufferAdjustIndent(buf, -6);
+ }
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
@@ -13851,6 +13885,18 @@ virDomainNetGetActualBandwidth(virDomainNetDefPtr iface)
return iface->bandwidth;
}
+virNetDevOpenvswitchPortPtr
+virDomainNetGetActualOpenvswitchPortPtr(virDomainNetDefPtr iface)
+{
+ if (iface->type != VIR_DOMAIN_NET_TYPE_BRIDGE)
+ return NULL;
+ if (iface->data.bridge.ovsPort)
+ return iface->data.bridge.ovsPort;
+ if (!iface->data.network.actual)
+ return NULL;
+ return iface->data.network.actual->data.bridge.ovsPort;
+}
+
/* Return listens[ii] from the appropriate union for the graphics
* type, or NULL if this is an unsuitable type, or the index is out of
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0a2795d..b7eb7d1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -41,6 +41,7 @@
# include "virnetdevmacvlan.h"
# include "sysinfo.h"
# include "virnetdevvportprofile.h"
+# include "virnetdevopenvswitch.h"
# include "virnetdevbandwidth.h"
/* Different types of hypervisor */
@@ -594,6 +595,7 @@ struct _virDomainActualNetDef {
union {
struct {
char *brname;
+ virNetDevOpenvswitchPortPtr ovsPort;
} bridge;
struct {
char *linkdev;
@@ -645,6 +647,7 @@ struct _virDomainNetDef {
struct {
char *brname;
char *ipaddr;
+ virNetDevOpenvswitchPortPtr ovsPort;
} bridge;
struct {
char *name;
@@ -1877,6 +1880,9 @@ virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr
iface);
virNetDevBandwidthPtr
virDomainNetGetActualBandwidth(virDomainNetDefPtr iface);
+virNetDevOpenvswitchPortPtr
+virDomainNetGetActualOpenvswitchPortPtr(virDomainNetDefPtr iface);
+
int virDomainControllerInsert(virDomainDefPtr def,
virDomainControllerDefPtr controller);
void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
diff --git a/src/conf/netdev_openvswitch_conf.c b/src/conf/netdev_openvswitch_conf.c
new file mode 100644
index 0000000..ddae3aa
--- /dev/null
+++ b/src/conf/netdev_openvswitch_conf.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 Nicira, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Dan Wendlandt <dan(a)nicira.com>
+ * Kyle Mestery <kmestery(a)cisco.com>
+ * Ansis Atteka <aatteka(a)nicira.com>
+ */
+
+#include <config.h>
+
+#include "netdev_openvswitch_conf.h"
+#include "virterror_internal.h"
+#include "memory.h"
+#include "uuid.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+#define virNetDevError(code, ...) \
+ virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+
+
+virNetDevOpenvswitchPortPtr
+virNetDevOpenvswitchPortParse(xmlNodePtr node)
+{
+ char *InterfaceID = NULL;
+ virNetDevOpenvswitchPortPtr ovsPort = NULL;
+ xmlNodePtr cur = node->children;
+
+ if (VIR_ALLOC(ovsPort) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+
+ while (cur != NULL) {
+ if (xmlStrEqual(cur->name, BAD_CAST "parameters")) {
+ InterfaceID = virXMLPropString(cur, "interfaceid");
+ break;
+ }
+ cur = cur->next;
+ }
+
+ if (InterfaceID == NULL || (strlen(InterfaceID) == 0)) {
+ // interfaceID does not have to be a UUID,
+ // but a UUID is a reasonable default
+ if (virUUIDGenerateStr(ovsPort->InterfaceID)) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot generate a random uuid for interfaceid"));
+ goto error;
+ }
+ } else {
+ if (virStrcpyStatic(ovsPort->InterfaceID, InterfaceID) == NULL) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("InterfaceID parameter too long"));
+ goto error;
+ }
+ }
+
+cleanup:
+ return ovsPort;
+
+error:
+ VIR_FREE(ovsPort);
+ goto cleanup;
+}
+
+
+int
+virNetDevOpenvswitchPortFormat(virNetDevOpenvswitchPortPtr ovsPort,
+ virBufferPtr buf)
+{
+ if (ovsPort == NULL)
+ return 0;
+
+ virBufferAsprintf(buf, "<virtualport
type='openvswitch'>\n");
+ virBufferAsprintf(buf, " <parameters interfaceid='%s'/>\n",
+ ovsPort->InterfaceID);
+ virBufferAddLit(buf, "</virtualport>\n");
+ return 0;
+}
diff --git a/src/conf/netdev_openvswitch_conf.h b/src/conf/netdev_openvswitch_conf.h
new file mode 100644
index 0000000..fd8e079
--- /dev/null
+++ b/src/conf/netdev_openvswitch_conf.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 Nicira, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Dan Wendlandt <dan(a)nicira.com>
+ * Kyle Mestery <kmestery(a)cisco.com>
+ * Ansis Atteka <aatteka(a)nicira.com>
+ */
+
+#ifndef __VIR_NETDEV_OPENVSWITCH_CONF_H__
+# define __VIR_NETDEV_OPENVSWITCH_CONF_H__
+
+# include "internal.h"
+# include "virnetdevopenvswitch.h"
+# include "buf.h"
+# include "xml.h"
+
+virNetDevOpenvswitchPortPtr
+virNetDevOpenvswitchPortParse(xmlNodePtr node);
+
+int
+virNetDevOpenvswitchPortFormat(virNetDevOpenvswitchPortPtr ovsPort,
+ virBufferPtr buf);
+
+#endif /* __VIR_NETDEV_OPENVSWITCH_CONF_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d6ad36c..0666d5c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -379,6 +379,7 @@ virDomainNetGetActualBridgeName;
virDomainNetGetActualDirectDev;
virDomainNetGetActualDirectMode;
virDomainNetGetActualDirectVirtPortProfile;
+virDomainNetGetActualOpenvswitchPortPtr;
virDomainNetGetActualType;
virDomainNetIndexByMac;
virDomainNetInsert;
@@ -738,6 +739,10 @@ virShrinkN;
virNetDevBandwidthFormat;
virNetDevBandwidthParse;
+# netdev_openvswitch_conf.h
+virNetDevOpenvswitchPortFormat;
+virNetDevOpenvswitchPortParse;
+
# netdev_vportprofile_conf.h
virNetDevVPortProfileFormat;
@@ -1145,6 +1150,7 @@ virGetHostUUID;
virSetHostUUIDStr;
virUUIDFormat;
virUUIDGenerate;
+virUUIDGenerateStr;
virUUIDParse;
@@ -1237,10 +1243,16 @@ virNetDevMacVLanCreateWithVPortProfile;
virNetDevMacVLanDeleteWithVPortProfile;
+# virnetdevopenvswitch.h
+virNetDevOpenvswitchAddPort;
+virNetDevOpenvswitchDelPort;
+
+
# virnetdevtap.h
virNetDevTapCreate;
virNetDevTapCreateInBridgePort;
virNetDevTapDelete;
+virNetDevTapDeleteInBridgePort;
# virnetdevveth.h
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index b712da4..1fab77a 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -56,6 +56,7 @@
#include "domain_nwfilter.h"
#include "network/bridge_driver.h"
#include "virnetdev.h"
+#include "virnetdevtap.h"
#include "virnodesuspend.h"
#include "virtime.h"
#include "virtypedparam.h"
@@ -1132,10 +1133,12 @@ static void lxcVmCleanup(lxc_driver_t *driver,
priv->monitorWatch = -1;
for (i = 0 ; i < vm->def->nnets ; i++) {
- ignore_value(virNetDevSetOnline(vm->def->nets[i]->ifname, false));
- ignore_value(virNetDevVethDelete(vm->def->nets[i]->ifname));
-
- networkReleaseActualDevice(vm->def->nets[i]);
+ virDomainNetDefPtr iface = vm->def->nets[i];
+ ignore_value(virNetDevSetOnline(iface->ifname, false));
+ ignore_value(virNetDevVethDelete(iface->ifname));
+ ignore_value(virNetDevTapDeleteInBridgePort(iface->ifname,
+ virDomainNetGetActualOpenvswitchPortPtr(iface)));
+ networkReleaseActualDevice(iface);
}
virDomainConfVMNWFilterTeardown(vm);
@@ -1377,8 +1380,12 @@ static int lxcSetupInterfaces(virConnectPtr conn,
cleanup:
if (ret != 0) {
- for (i = 0 ; i < def->nnets ; i++)
- networkReleaseActualDevice(def->nets[i]);
+ for (i = 0 ; i < def->nnets ; i++) {
+ virDomainNetDefPtr iface = def->nets[i];
+ ignore_value(virNetDevTapDeleteInBridgePort(iface->ifname,
+ virDomainNetGetActualOpenvswitchPortPtr(iface)));
+ networkReleaseActualDevice(iface);
+ }
}
return ret;
}
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 57ebb9f..1423d3f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1765,7 +1765,8 @@ networkStartNetworkVirtual(struct network_driver *driver,
goto err0;
}
if (virNetDevTapCreateInBridgePort(network->def->bridge,
- &macTapIfName, network->def->mac, 0,
false, NULL) < 0) {
+ &macTapIfName, network->def->mac, 0,
+ false, NULL, NULL) < 0) {
VIR_FREE(macTapIfName);
goto err0;
}
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 0e26df1..d6a81f1 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -247,7 +247,8 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
err = virNetDevTapCreateInBridgePort(brname, &net->ifname, tapmac,
- vnet_hdr, true, &tapfd);
+ vnet_hdr, true, &tapfd,
+ virDomainNetGetActualOpenvswitchPortPtr(net));
virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0);
if (err < 0) {
if (template_ifname)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index b4870be..85a004d 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -40,6 +40,7 @@
#include "qemu_cgroup.h"
#include "locking/domain_lock.h"
#include "network/bridge_driver.h"
+#include "virnetdevtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -837,7 +838,8 @@ cleanup:
if (iface_connected)
virDomainConfNWFilterTeardown(net);
-
+ ignore_value(virNetDevTapDeleteInBridgePort(net->ifname,
+ virDomainNetGetActualOpenvswitchPortPtr(net)));
networkReleaseActualDevice(net);
}
@@ -1937,7 +1939,8 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
detach->ifname);
}
}
-
+ ignore_value(virNetDevTapDeleteInBridgePort(detach->ifname,
+ virDomainNetGetActualOpenvswitchPortPtr(detach)));
networkReleaseActualDevice(detach);
if (vm->def->nnets > 1) {
memmove(vm->def->nets + i,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 2d92d66..14eeef8 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -62,6 +62,7 @@
#include "network/bridge_driver.h"
#include "uuid.h"
#include "virtime.h"
+#include "virnetdevtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -3731,6 +3732,8 @@ void qemuProcessStop(struct qemud_driver *driver,
/* release the physical device (or any other resources used by
* this interface in the network driver
*/
+ ignore_value(virNetDevTapDeleteInBridgePort(net->ifname,
+ virDomainNetGetActualOpenvswitchPortPtr(net)));
networkReleaseActualDevice(net);
}
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 316d558..b8610ea 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -142,7 +142,8 @@ umlConnectTapDevice(virConnectPtr conn,
memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
if (virNetDevTapCreateInBridgePort(bridge, &net->ifname, tapmac,
- 0, true, NULL) < 0) {
+ 0, true, NULL,
+ virDomainNetGetActualOpenvswitchPortPtr(net)) < 0) {
if (template_ifname)
VIR_FREE(net->ifname);
goto error;
diff --git a/src/util/uuid.c b/src/util/uuid.c
index 23822ec..d8188b7 100644
--- a/src/util/uuid.c
+++ b/src/util/uuid.c
@@ -116,6 +116,25 @@ virUUIDGenerate(unsigned char *uuid)
}
/**
+ * virUUIDGenerateString:
+ * @uuid: string of VIR_UUID_STRING_BUFLEN characters to store the UUID
+ *
+ *
+ * Generates a randomized unique identifier
+ * Returns 0 in case of success and -1 in case of failure
+ */
+int
+virUUIDGenerateStr(char *uuidstr)
+{
+ unsigned char uuid[VIR_UUID_BUFLEN];
+
+ if (virUUIDGenerate(uuid) < 0)
+ return -1;
+ virUUIDFormat(uuid, uuidstr);
+ return 0;
+}
+
+/**
* virUUIDParse:
* @uuidstr: zero terminated string representation of the UUID
* @uuid: array of VIR_UUID_BUFLEN bytes to store the raw UUID
diff --git a/src/util/uuid.h b/src/util/uuid.h
index 7dbfad5..1ae7efb 100644
--- a/src/util/uuid.h
+++ b/src/util/uuid.h
@@ -30,6 +30,7 @@ int virGetHostUUID(unsigned char *host_uuid) ATTRIBUTE_NONNULL(1);
int virUUIDIsValid(unsigned char *uuid);
int virUUIDGenerate(unsigned char *uuid);
+int virUUIDGenerateStr(char *struuid);
int virUUIDParse(const char *uuidstr,
unsigned char *uuid)
diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
new file mode 100644
index 0000000..c5bef8d
--- /dev/null
+++ b/src/util/virnetdevopenvswitch.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 Nicira, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Dan Wendlandt <dan(a)nicira.com>
+ * Kyle Mestery <kmestery(a)cisco.com>
+ * Ansis Atteka <aatteka(a)nicira.com>
+ */
+
+#include <config.h>
+
+#include "virnetdevopenvswitch.h"
+#include "command.h"
+#include "memory.h"
+#include "virterror_internal.h"
+#include "ignore-value.h"
+#include "virmacaddr.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+/**
+ * virNetDevOpenvswitchAddPort:
+ * @brname: the bridge name
+ * @ifname: the network interface name
+ * @macaddr: the mac address of the virtual interface
+ *
+ * Add an interface to the OVS bridge
+ *
+ * Returns 0 in case of success or -1 in case of failure.
+ */
+int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+ const unsigned char *macaddr,
+ virNetDevOpenvswitchPortPtr ovsport)
+{
+ int ret = -1;
+ virCommandPtr cmd = NULL;
+ char macaddrstr[VIR_MAC_STRING_BUFLEN];
+ char *attachedmac_ex_id = NULL;
+ char *ifaceid_ex_id = NULL;
+
+ virMacAddrFormat(macaddr, macaddrstr);
+
+ if (virAsprintf(&attachedmac_ex_id,
"external-ids:attached-mac=\"%s\"",
+ macaddrstr) < 0)
+ goto cleanup;
+ if (virAsprintf(&ifaceid_ex_id,
"external-ids:iface-id=\"%s\"",
+ ovsport->InterfaceID) < 0)
+ goto cleanup;
+
+ cmd = virCommandNew(OVSVSCTL);
+ virCommandAddArgList(cmd, "--", "--may-exist",
"add-port",
+ brname, ifname,
+ "--", "set", "Interface", ifname,
attachedmac_ex_id,
+ "--", "set", "Interface", ifname,
ifaceid_ex_id,
+ "--", "set", "Interface", ifname,
+ "external-ids:iface-status=active",
+ NULL);
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to add port %s to OVS bridge %s"),
+ ifname, brname);
+ goto cleanup;
+ }
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(attachedmac_ex_id);
+ VIR_FREE(ifaceid_ex_id);
+ virCommandFree(cmd);
+ return ret;
+}
+
+/**
+ * virNetDevOpenvswitchDelPort:
+ * @ifname: the network interface name
+ *
+ * Deletes an interface from a OVS bridge
+ *
+ * Returns 0 in case of success or -1 in case of failure.
+ */
+int virNetDevOpenvswitchDelPort(const char *ifname)
+{
+ int ret = -1;
+ virCommandPtr cmd = NULL;
+
+ cmd = virCommandNew(OVSVSCTL);
+ virCommandAddArgList(cmd, "--", "--if-exists",
"del-port", ifname, NULL);
+
+ if (virCommandRun(cmd, NULL) < 0) {
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to delete port %s from OVS"), ifname);
+ goto cleanup;
+ }
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h
new file mode 100644
index 0000000..210546b
--- /dev/null
+++ b/src/util/virnetdevopenvswitch.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Nicira, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Dan Wendlandt <dan(a)nicira.com>
+ * Kyle Mestery <kmestery(a)cisco.com>
+ * Ansis Atteka <aatteka(a)nicira.com>
+ */
+
+#ifndef __VIR_NETDEV_OPENVSWITCH_H__
+# define __VIR_NETDEV_OPENVSWITCH_H__
+
+# include "internal.h"
+# include "util.h"
+
+typedef struct _virNetDevOpenvswitchPort virNetDevOpenvswitchPort;
+typedef virNetDevOpenvswitchPort *virNetDevOpenvswitchPortPtr;
+struct _virNetDevOpenvswitchPort {
+ char InterfaceID[VIR_UUID_STRING_BUFLEN];
+};
+
+int virNetDevOpenvswitchAddPort(const char *brname,
+ const char *ifname,
+ const unsigned char *macaddr,
+ virNetDevOpenvswitchPortPtr ovsport)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevOpenvswitchDelPort(const char *ifname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
+#endif /* __VIR_NETDEV_OPENVSWITCH_H__ */
diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c
index 2ed53c6..975bb85 100644
--- a/src/util/virnetdevtap.c
+++ b/src/util/virnetdevtap.c
@@ -25,6 +25,7 @@
#include "virnetdevtap.h"
#include "virnetdev.h"
#include "virnetdevbridge.h"
+#include "virnetdevopenvswitch.h"
#include "virterror_internal.h"
#include "virfile.h"
#include "virterror_internal.h"
@@ -249,6 +250,7 @@ int virNetDevTapDelete(const char *ifname ATTRIBUTE_UNUSED)
* @macaddr: desired MAC address (VIR_MAC_BUFLEN long)
* @vnet_hdr: whether to try enabling IFF_VNET_HDR
* @tapfd: file descriptor return value for the new tap device
+ * @ovsport: Open vSwitch specific configuration
*
* This function creates a new tap device on a bridge. @ifname can be either
* a fixed name or a name template with '%d' for dynamic name allocation.
@@ -265,7 +267,8 @@ int virNetDevTapCreateInBridgePort(const char *brname,
const unsigned char *macaddr,
int vnet_hdr,
bool up,
- int *tapfd)
+ int *tapfd,
+ virNetDevOpenvswitchPortPtr ovsport)
{
if (virNetDevTapCreate(ifname, vnet_hdr, tapfd) < 0)
return -1;
@@ -286,8 +289,13 @@ int virNetDevTapCreateInBridgePort(const char *brname,
if (virNetDevSetMTUFromDevice(*ifname, brname) < 0)
goto error;
- if (virNetDevBridgeAddPort(brname, *ifname) < 0)
- goto error;
+ if (ovsport) {
+ if (virNetDevOpenvswitchAddPort(brname, *ifname, macaddr, ovsport) < 0)
+ goto error;
+ } else {
+ if (virNetDevBridgeAddPort(brname, *ifname) < 0)
+ goto error;
+ }
if (virNetDevSetOnline(*ifname, up) < 0)
goto error;
@@ -299,3 +307,21 @@ int virNetDevTapCreateInBridgePort(const char *brname,
return errno;
}
+
+/**
+ * virNetDevTapDeleteInBridgePort:
+ * @ifname: the interface name (or name template)
+ * @ovsport: Open vSwitch specific configuration
+ *
+ * This function detaches tap device from a bridge.
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+int virNetDevTapDeleteInBridgePort(char *ifname,
+ virNetDevOpenvswitchPortPtr ovsport)
+{
+ int ret = 0;
+ if (ovsport)
+ ret = virNetDevOpenvswitchDelPort(ifname);
+ return ret;
+}
diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h
index fb35ac5..5b16570 100644
--- a/src/util/virnetdevtap.h
+++ b/src/util/virnetdevtap.h
@@ -24,6 +24,7 @@
# define __VIR_NETDEV_TAP_H__
# include "internal.h"
+# include "conf/domain_conf.h"
int virNetDevTapCreate(char **ifname,
int vnet_hdr,
@@ -38,8 +39,13 @@ int virNetDevTapCreateInBridgePort(const char *brname,
const unsigned char *macaddr,
int vnet_hdr,
bool up,
- int *tapfd)
+ int *tapfd,
+ virNetDevOpenvswitchPortPtr ovsport)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_RETURN_CHECK;
+int virNetDevTapDeleteInBridgePort(char *ifname,
+ virNetDevOpenvswitchPortPtr ovsport)
+ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+
#endif /* __VIR_NETDEV_TAP_H__ */
--
1.7.5.4