From 7d2b91b86a814d8469fd3aed10cff264ccab70cf Mon Sep 17 00:00:00 2001 From: Kyle Mestery Date: Fri, 17 Aug 2012 00:04:54 -0400 Subject: [PATCH] network: add support for setting VLANs on Open vSwitch ports Add the ability to support VLAN tags for Open vSwitch virtual port types. To accomplish this, modify virNetDevOpenvswitchAddPort and virNetDevTapCreateInBridgePort to take a virNetDevVlanPtr argument. When adding the port to the OVS bridge, setup either a single VLAN or a trunk port based on the configuration from the virNetDevVlanPtr. Signed-off-by: Kyle Mestery --- src/lxc/lxc_process.c | 2 +- src/network/bridge_driver.c | 2 +- src/qemu/qemu_command.c | 1 + src/uml/uml_conf.c | 1 + src/util/virnetdevopenvswitch.c | 34 ++++++++++++++++++++++++++++++--- src/util/virnetdevopenvswitch.h | 4 +++- src/util/virnetdevtap.c | 3 ++- src/util/virnetdevtap.h | 2 ++ 8 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 046ed8699c..dc34bef972 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -325,7 +325,7 @@ static int virLXCProcessSetupInterfaceBridged(virConnectPtr conn, if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) ret = virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac, - vm->uuid, vport); + vm->uuid, vport, &net->vlan); else ret = virNetDevBridgeAddPort(brname, parentVeth); if (ret < 0) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 474bbfadeb..a78e3b6eb9 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -1763,7 +1763,7 @@ networkStartNetworkVirtual(struct network_driver *driver, } if (virNetDevTapCreateInBridgePort(network->def->bridge, &macTapIfName, &network->def->mac, - NULL, NULL, NULL, + NULL, NULL, NULL, NULL, VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE) < 0) { VIR_FREE(macTapIfName); goto err0; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9383530445..e0062a116d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -255,6 +255,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, err = virNetDevTapCreateInBridgePort(brname, &net->ifname, &net->mac, def->uuid, &tapfd, virDomainNetGetActualVirtPortProfile(net), + &net->vlan, tap_create_flags); virDomainAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0); if (err < 0) { diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c index 4c299d8eaa..5461b42a8e 100644 --- a/src/uml/uml_conf.c +++ b/src/uml/uml_conf.c @@ -141,6 +141,7 @@ umlConnectTapDevice(virConnectPtr conn, if (virNetDevTapCreateInBridgePort(bridge, &net->ifname, &net->mac, vm->uuid, NULL, virDomainNetGetActualVirtPortProfile(net), + &net->vlan, VIR_NETDEV_TAP_CREATE_IFUP) < 0) { if (template_ifname) VIR_FREE(net->ifname); diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c index b57532b326..601d79e629 100644 --- a/src/util/virnetdevopenvswitch.c +++ b/src/util/virnetdevopenvswitch.c @@ -46,9 +46,11 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, const virMacAddrPtr macaddr, const unsigned char *vmuuid, - virNetDevVPortProfilePtr ovsport) + virNetDevVPortProfilePtr ovsport, + virNetDevVlanPtr virtVlan) { int ret = -1; + int i = 0; virCommandPtr cmd = NULL; char macaddrstr[VIR_MAC_STRING_BUFLEN]; char ifuuidstr[VIR_UUID_STRING_BUFLEN]; @@ -57,6 +59,7 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, char *ifaceid_ex_id = NULL; char *profile_ex_id = NULL; char *vmid_ex_id = NULL; + virBufferPtr buf; virMacAddrFormat(macaddr, macaddrstr); virUUIDFormat(ovsport->interfaceID, ifuuidstr); @@ -76,11 +79,35 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, ovsport->profileID) < 0) goto out_of_memory; } + if (virtVlan) { + if (VIR_ALLOC(buf) < 0) + goto out_of_memory; + + /* Trunk port first */ + if (virtVlan->trunk) { + virBufferAddLit(buf, "trunk="); + + /* + * Trunk ports have at least one VLAN. Do the first one + * outside the "for" loop so we can put a "," at the + * start of the for loop if there are more than one VLANs + * on this trunk port. + */ + virBufferAsprintf(buf, "%d", virtVlan->tag[i]); + + for (i = 1; i < virtVlan->nTags; i++) { + virBufferAddLit(buf, ","); + virBufferAsprintf(buf, "%d", virtVlan->tag[i]); + } + } else { + virBufferAsprintf(buf, "tag=%d", virtVlan->tag[0]); + } + } cmd = virCommandNew(OVSVSCTL); if (ovsport->profileID[0] == '\0') { virCommandAddArgList(cmd, "--", "--may-exist", "add-port", - brname, ifname, + brname, ifname, virBufferContentAndReset(buf), "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, vmid_ex_id, @@ -89,7 +116,7 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, NULL); } else { virCommandAddArgList(cmd, "--", "--may-exist", "add-port", - brname, ifname, + brname, ifname, virBufferContentAndReset(buf), "--", "set", "Interface", ifname, attachedmac_ex_id, "--", "set", "Interface", ifname, ifaceid_ex_id, "--", "set", "Interface", ifname, vmid_ex_id, @@ -108,6 +135,7 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, ret = 0; cleanup: + VIR_FREE(buf); VIR_FREE(attachedmac_ex_id); VIR_FREE(ifaceid_ex_id); VIR_FREE(vmid_ex_id); diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h index fbf91687ac..58b4ddadd8 100644 --- a/src/util/virnetdevopenvswitch.h +++ b/src/util/virnetdevopenvswitch.h @@ -27,13 +27,15 @@ # include "internal.h" # include "util.h" # include "virnetdevvportprofile.h" +# include "virnetdevvlan.h" int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, const virMacAddrPtr macaddr, const unsigned char *vmuuid, - virNetDevVPortProfilePtr ovsport) + virNetDevVPortProfilePtr ovsport, + virNetDevVlanPtr virtVlan) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; diff --git a/src/util/virnetdevtap.c b/src/util/virnetdevtap.c index 192d180ecb..24f30b5063 100644 --- a/src/util/virnetdevtap.c +++ b/src/util/virnetdevtap.c @@ -280,6 +280,7 @@ int virNetDevTapCreateInBridgePort(const char *brname, const unsigned char *vmuuid, int *tapfd, virNetDevVPortProfilePtr virtPortProfile, + virNetDevVlanPtr virtVlan, unsigned int flags) { virMacAddr tapmac; @@ -324,7 +325,7 @@ int virNetDevTapCreateInBridgePort(const char *brname, if (virtPortProfile) { if (virNetDevOpenvswitchAddPort(brname, *ifname, macaddr, vmuuid, - virtPortProfile) < 0) { + virtPortProfile, virtVlan) < 0) { goto error; } } else { diff --git a/src/util/virnetdevtap.h b/src/util/virnetdevtap.h index ce3365eb39..45d0c08173 100644 --- a/src/util/virnetdevtap.h +++ b/src/util/virnetdevtap.h @@ -25,6 +25,7 @@ # include "internal.h" # include "virnetdevvportprofile.h" +# include "virnetdevvlan.h" int virNetDevTapCreate(char **ifname, int *tapfd, @@ -50,6 +51,7 @@ int virNetDevTapCreateInBridgePort(const char *brname, const unsigned char *vmuuid, int *tapfd, virNetDevVPortProfilePtr virtPortProfile, + virNetDevVlanPtr virtVlan, unsigned int flags) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK;