Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
Marcelo Cerri <mhcerri@linux.vnet.ibm.com>
Hendrik Schwartke <hendrik@os-t.de>
+ Ansis Atteka <aatteka@nicira.com>
+ Dan Wendlandt <dan@nicira.com>
+ Kyle Mestery <kmestery@cisco.com>
[....send patches to get your name here....]
[/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])
[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])
src/util/virnetdev.c
src/util/virnetdevbridge.c
src/util/virnetdevmacvlan.c
+src/util/virnetdevopenvswitch.c
src/util/virnetdevtap.c
src/util/virnetdevvportprofile.c
src/util/virnetlink.c
util/virnetdevbandwidth.h util/virnetdevbandwidth.c \
util/virnetdevbridge.h util/virnetdevbridge.c \
util/virnetdevmacvlan.c util/virnetdevmacvlan.h \
+ util/virnetdevopenvswitch.h util/virnetdevopenvswitch.c \
util/virnetdevtap.h util/virnetdevtap.c \
util/virnetdevveth.h util/virnetdevveth.c \
util/virnetdevvportprofile.h util/virnetdevvportprofile.c \
#include <sys/time.h>
#include <strings.h>
+#include "internal.h"
#include "virterror_internal.h"
#include "datatypes.h"
#include "domain_conf.h"
switch (def->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
+ VIR_FREE(def->data.bridge.virtPortProfile);
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
VIR_FREE(def->data.direct.linkdev);
case VIR_DOMAIN_NET_TYPE_BRIDGE:
VIR_FREE(def->data.bridge.brname);
VIR_FREE(def->data.bridge.ipaddr);
+ VIR_FREE(def->data.bridge.virtPortProfile);
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
}
if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
- actual->data.bridge.brname = virXPathString("string(./source[1]/@bridge)", ctxt);
+ xmlNodePtr virtPortNode = virXPathNode("./virtualport", ctxt);
+ if (virtPortNode &&
+ (!(actual->data.bridge.virtPortProfile =
+ virNetDevVPortProfileParse(virtPortNode))))
+ goto error;
} else if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
xmlNodePtr virtPortNode;
mode = virXMLPropString(cur, "mode");
} else if ((virtPort == NULL) &&
((def->type == VIR_DOMAIN_NET_TYPE_DIRECT) ||
- (def->type == VIR_DOMAIN_NET_TYPE_NETWORK)) &&
+ (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) ||
+ (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE)) &&
xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
if (!(virtPort = virNetDevVPortProfileParse(cur)))
goto error;
def->data.bridge.ipaddr = address;
address = NULL;
}
+ def->data.bridge.virtPortProfile = virtPort;
+ virtPort = NULL;
break;
case VIR_DOMAIN_NET_TYPE_CLIENT:
case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferEscapeString(buf, " <source bridge='%s'/>\n",
def->data.bridge.brname);
+ if (def->data.bridge.virtPortProfile) {
+ virBufferAdjustIndent(buf, 6);
+ if (virNetDevVPortProfileFormat(def->data.bridge.virtPortProfile, buf) < 0)
+ return -1;
+ virBufferAdjustIndent(buf, -6);
+ }
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
if (def->data.bridge.ipaddr)
virBufferAsprintf(buf, " <ip address='%s'/>\n",
def->data.bridge.ipaddr);
+ if (def->data.bridge.virtPortProfile) {
+ virBufferAdjustIndent(buf, 6);
+ if (virNetDevVPortProfileFormat(def->data.bridge.virtPortProfile, buf) < 0)
+ return -1;
+ virBufferAdjustIndent(buf, -6);
+ }
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
virNetDevVPortProfilePtr
virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
{
- if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
+ switch (iface->type) {
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
return iface->data.direct.virtPortProfile;
- if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
- return NULL;
- if (!iface->data.network.actual)
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ return iface->data.bridge.virtPortProfile;
+ case VIR_DOMAIN_NET_TYPE_NETWORK:
+ if (!iface->data.network.actual)
+ return NULL;
+ switch (iface->data.network.actual->type) {
+ case VIR_DOMAIN_NET_TYPE_DIRECT:
+ return iface->data.network.actual->data.direct.virtPortProfile;
+ case VIR_DOMAIN_NET_TYPE_BRIDGE:
+ return iface->data.network.actual->data.bridge.virtPortProfile;
+ default:
+ return NULL;
+ }
+ default:
return NULL;
- return iface->data.network.actual->data.direct.virtPortProfile;
+ }
}
virNetDevBandwidthPtr
# include "virnetdevmacvlan.h"
# include "sysinfo.h"
# include "virnetdevvportprofile.h"
+# include "virnetdevopenvswitch.h"
# include "virnetdevbandwidth.h"
/* Different types of hypervisor */
union {
struct {
char *brname;
+ virNetDevVPortProfilePtr virtPortProfile;
} bridge;
struct {
char *linkdev;
struct {
char *brname;
char *ipaddr;
+ virNetDevVPortProfilePtr virtPortProfile;
} bridge;
struct {
char *name;
VIR_ENUM_IMPL(virNetDevVPort, VIR_NETDEV_VPORT_PROFILE_LAST,
"none",
"802.1Qbg",
- "802.1Qbh")
+ "802.1Qbh",
+ "openvswitch")
virNetDevVPortProfilePtr
char *virtPortTypeIDVersion = NULL;
char *virtPortInstanceID = NULL;
char *virtPortProfileID = NULL;
+ char *virtPortInterfaceID = NULL;
virNetDevVPortProfilePtr virtPort = NULL;
xmlNodePtr cur = node->children;
virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion");
virtPortInstanceID = virXMLPropString(cur, "instanceid");
virtPortProfileID = virXMLPropString(cur, "profileid");
-
+ virtPortInterfaceID = virXMLPropString(cur, "interfaceid");
break;
}
goto error;
}
break;
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
+ if (virtPortInterfaceID != NULL) {
+ if (virUUIDParse(virtPortInterfaceID,
+ virtPort->u.openvswitch.interfaceID)) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse interfaceid parameter as a uuid"));
+ goto error;
+ }
+ } else {
+ if (virUUIDGenerate(virtPort->u.openvswitch.interfaceID)) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot generate a random uuid for interfaceid"));
+ goto error;
+ }
+ }
+ /* profileid is not mandatory for Open vSwitch */
+ if (virtPortProfileID != NULL) {
+ if (virStrcpyStatic(virtPort->u.openvswitch.profileID,
+ virtPortProfileID) == NULL) {
+ virNetDevError(VIR_ERR_XML_ERROR, "%s",
+ _("profileid parameter too long"));
+ goto error;
+ }
+ } else {
+ virtPort->u.openvswitch.profileID[0] = '\0';
+ }
+ break;
default:
virNetDevError(VIR_ERR_XML_ERROR,
virtPort->u.virtPort8021Qbh.profileID);
break;
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
+ virUUIDFormat(virtPort->u.openvswitch.interfaceID,
+ uuidstr);
+ if (virtPort->u.openvswitch.profileID[0] == '\0') {
+ virBufferAsprintf(buf, " <parameters interfaceid='%s'/>\n",
+ uuidstr);
+ } else {
+ virBufferAsprintf(buf, " <parameters interfaceid='%s' "
+ "profileid='%s'/>\n", uuidstr,
+ virtPort->u.openvswitch.profileID);
+ }
+
+ break;
+
default:
virNetDevError(VIR_ERR_XML_ERROR,
_("unexpected virtualport type %d"), virtPort->virtPortType);
virNetDevMacVLanDeleteWithVPortProfile;
+# virnetdevopenvswitch.h
+virNetDevOpenvswitchAddPort;
+virNetDevOpenvswitchRemovePort;
+
+
# virnetdevtap.h
virNetDevTapCreate;
virNetDevTapCreateInBridgePort;
#include "domain_nwfilter.h"
#include "network/bridge_driver.h"
#include "virnetdev.h"
+#include "virnetdevtap.h"
#include "virnodesuspend.h"
#include "virtime.h"
#include "virtypedparam.h"
virCgroupPtr cgroup;
int i;
lxcDomainObjPrivatePtr priv = vm->privateData;
+ virNetDevVPortProfilePtr vport = NULL;
/* now that we know it's stopped call the hook if present */
if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
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];
+ vport = virDomainNetGetActualVirtPortProfile(iface);
+ ignore_value(virNetDevSetOnline(iface->ifname, false));
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(iface),
+ iface->ifname));
+ ignore_value(virNetDevVethDelete(iface->ifname));
+ networkReleaseActualDevice(iface);
}
virDomainConfVMNWFilterTeardown(vm);
int ret = -1;
char *parentVeth;
char *containerVeth = NULL;
+ const virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(net);
VIR_DEBUG("calling vethCreate()");
parentVeth = net->ifname;
if (virNetDevSetMAC(containerVeth, net->mac) < 0)
goto cleanup;
- if (virNetDevBridgeAddPort(brname, parentVeth) < 0)
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ret = virNetDevOpenvswitchAddPort(brname, parentVeth, net->mac, vport);
+ else
+ ret = virNetDevBridgeAddPort(brname, parentVeth);
+ if (ret < 0)
goto cleanup;
if (virNetDevSetOnline(parentVeth, true) < 0)
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];
+ virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(iface);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(iface),
+ iface->ifname));
+ networkReleaseActualDevice(iface);
+ }
}
return ret;
}
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;
}
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,
+ virDomainNetGetActualVirtPortProfile(net));
virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0);
if (err < 0) {
if (template_ifname)
#include "qemu_cgroup.h"
#include "locking/domain_lock.h"
#include "network/bridge_driver.h"
+#include "virnetdevtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
int vhostfd = -1;
char *nicstr = NULL;
char *netstr = NULL;
+ virNetDevVPortProfilePtr vport = NULL;
int ret = -1;
virDomainDevicePCIAddress guestAddr;
int vlan;
if (iface_connected)
virDomainConfNWFilterTeardown(net);
+ vport = virDomainNetGetActualVirtPortProfile(net);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(net), net->ifname));
+
networkReleaseActualDevice(net);
}
qemuDomainObjPrivatePtr priv = vm->privateData;
int vlan;
char *hostnet_name = NULL;
+ virNetDevVPortProfilePtr vport = NULL;
for (i = 0 ; i < vm->def->nnets ; i++) {
virDomainNetDefPtr net = vm->def->nets[i];
}
}
+ vport = virDomainNetGetActualVirtPortProfile(detach);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(detach),
+ detach->ifname));
+
networkReleaseActualDevice(detach);
if (vm->def->nnets > 1) {
memmove(vm->def->nets + i,
#include "network/bridge_driver.h"
#include "uuid.h"
#include "virtime.h"
+#include "virnetdevtap.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
qemuDomainObjPrivatePtr priv = vm->privateData;
virErrorPtr orig_err;
virDomainDefPtr def;
+ virNetDevVPortProfilePtr vport = NULL;
int i;
int logfile = -1;
char *timestamp;
/* release the physical device (or any other resources used by
* this interface in the network driver
*/
+ vport = virDomainNetGetActualVirtPortProfile(net);
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
+ ignore_value(virNetDevOpenvswitchRemovePort(
+ virDomainNetGetActualBridgeName(net),
+ net->ifname));
+
networkReleaseActualDevice(net);
}
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,
+ virDomainNetGetActualVirtPortProfile(net)) < 0) {
if (template_ifname)
VIR_FREE(net->ifname);
goto error;
--- /dev/null
+/*
+ * 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@nicira.com>
+ * Kyle Mestery <kmestery@cisco.com>
+ * Ansis Atteka <aatteka@nicira.com>
+ */
+
+#include <config.h>
+
+#include "virnetdevopenvswitch.h"
+#include "command.h"
+#include "memory.h"
+#include "virterror_internal.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
+ * @ovsport: the ovs specific fields
+ *
+ * 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,
+ virNetDevVPortProfilePtr ovsport)
+{
+ int ret = -1;
+ virCommandPtr cmd = NULL;
+ char macaddrstr[VIR_MAC_STRING_BUFLEN];
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *attachedmac_ex_id = NULL;
+ char *ifaceid_ex_id = NULL;
+ char *profile_ex_id = NULL;
+
+ virMacAddrFormat(macaddr, macaddrstr);
+ virUUIDFormat(ovsport->u.openvswitch.interfaceID, uuidstr);
+
+ if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"",
+ macaddrstr) < 0)
+ goto cleanup;
+ if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"",
+ uuidstr) < 0)
+ goto cleanup;
+ if (ovsport->u.openvswitch.profileID[0] != '\0') {
+ if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"",
+ ovsport->u.openvswitch.profileID) < 0)
+ goto cleanup;
+ }
+
+ cmd = virCommandNew(OVSVSCTL);
+ if (ovsport->u.openvswitch.profileID[0] == '\0') {
+ 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);
+ } else {
+ virCommandAddArgList(cmd, "--", "--may-exist", "add-port",
+ brname, ifname,
+ "--", "set", "Interface", ifname, attachedmac_ex_id,
+ "--", "set", "Interface", ifname, ifaceid_ex_id,
+ "--", "set", "Interface", ifname, profile_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);
+ VIR_FREE(profile_ex_id);
+ virCommandFree(cmd);
+ return ret;
+}
+
+/**
+ * virNetDevOpenvswitchRemovePort:
+ * @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 virNetDevOpenvswitchRemovePort(const char *brname ATTRIBUTE_UNUSED, 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;
+}
--- /dev/null
+/*
+ * 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@nicira.com>
+ * Kyle Mestery <kmestery@cisco.com>
+ * Ansis Atteka <aatteka@nicira.com>
+ */
+
+#ifndef __VIR_NETDEV_OPENVSWITCH_H__
+# define __VIR_NETDEV_OPENVSWITCH_H__
+
+# include "internal.h"
+# include "util.h"
+# include "virnetdevvportprofile.h"
+
+
+int virNetDevOpenvswitchAddPort(const char *brname,
+ const char *ifname,
+ const unsigned char *macaddr,
+ virNetDevVPortProfilePtr ovsport)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevOpenvswitchRemovePort(const char *brname, const char *ifname)
+ ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+#endif /* __VIR_NETDEV_OPENVSWITCH_H__ */
#include "virnetdevtap.h"
#include "virnetdev.h"
#include "virnetdevbridge.h"
+#include "virnetdevopenvswitch.h"
#include "virterror_internal.h"
#include "virfile.h"
#include "virterror_internal.h"
* @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
+ * @virtPortProfile: bridge/port 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.
const unsigned char *macaddr,
int vnet_hdr,
bool up,
- int *tapfd)
+ int *tapfd,
+ virNetDevVPortProfilePtr virtPortProfile)
{
if (virNetDevTapCreate(ifname, vnet_hdr, tapfd) < 0)
return -1;
if (virNetDevSetMTUFromDevice(*ifname, brname) < 0)
goto error;
- if (virNetDevBridgeAddPort(brname, *ifname) < 0)
- goto error;
+ if (virtPortProfile) {
+ if (virNetDevOpenvswitchAddPort(brname, *ifname, macaddr,
+ virtPortProfile) < 0) {
+ goto error;
+ }
+ } else {
+ if (virNetDevBridgeAddPort(brname, *ifname) < 0)
+ goto error;
+ }
if (virNetDevSetOnline(*ifname, up) < 0)
goto error;
# define __VIR_NETDEV_TAP_H__
# include "internal.h"
+# include "virnetdevvportprofile.h"
int virNetDevTapCreate(char **ifname,
int vnet_hdr,
const unsigned char *macaddr,
int vnet_hdr,
bool up,
- int *tapfd)
+ int *tapfd,
+ virNetDevVPortProfilePtr virtPortProfile)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_RETURN_CHECK;
+
#endif /* __VIR_NETDEV_TAP_H__ */
switch (virtPort->virtPortType) {
case VIR_NETDEV_VPORT_PROFILE_NONE:
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
case VIR_NETDEV_VPORT_PROFILE_LAST:
break;
switch (virtPort->virtPortType) {
case VIR_NETDEV_VPORT_PROFILE_NONE:
+ case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
case VIR_NETDEV_VPORT_PROFILE_LAST:
break;
VIR_NETDEV_VPORT_PROFILE_NONE,
VIR_NETDEV_VPORT_PROFILE_8021QBG,
VIR_NETDEV_VPORT_PROFILE_8021QBH,
+ VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH,
VIR_NETDEV_VPORT_PROFILE_LAST,
};
};
VIR_ENUM_DECL(virNetDevVPortProfileOp)
-/* profile data for macvtap (VEPA) */
+/* profile data for macvtap (VEPA) and openvswitch */
typedef struct _virNetDevVPortProfile virNetDevVPortProfile;
typedef virNetDevVPortProfile *virNetDevVPortProfilePtr;
struct _virNetDevVPortProfile {
struct {
char profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX];
} virtPort8021Qbh;
+ struct {
+ unsigned char interfaceID[VIR_UUID_BUFLEN];
+ char profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX];
+ } openvswitch;
} u;
};