From 861d40565e9a53fdf127b8b3a2fe4029dcb6219f Mon Sep 17 00:00:00 2001 From: james robson Date: Thu, 23 May 2013 18:12:10 +0100 Subject: [PATCH] Configure native vlan modes on Open vSwitch ports This patch adds functionality to allow libvirt to configure the 'native-tagged' and 'native-untagged' modes on openvswitch networks. Signed-off-by: Laine Stump --- docs/formatdomain.html.in | 16 ++++++++ docs/formatnetwork.html.in | 15 +++++++ docs/schemas/networkcommon.rng | 8 ++++ src/conf/netdev_vlan_conf.c | 43 ++++++++++++++++++++- src/util/virnetdevopenvswitch.c | 14 +++++++ src/util/virnetdevvlan.c | 8 +++- src/util/virnetdevvlan.h | 15 ++++++- tests/networkxml2xmlin/openvswitch-net.xml | 9 +++++ tests/networkxml2xmlout/openvswitch-net.xml | 9 +++++ 9 files changed, 134 insertions(+), 3 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 77126a56fe..17ea9c2486 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3523,6 +3523,13 @@ qemu-kvm -net nic,model=? /dev/null <parameters interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/> </virtualport> </interface> + <interface type='bridge'> + <vlan trunk='yes'> + <tag id='42'/> + <tag id='123' nativeMode='untagged'/> + </vlan> + ... + </interface> <devices> ... @@ -3549,6 +3556,15 @@ qemu-kvm -net nic,model=? /dev/null vlan element.

+

+ For network connections using openvswitch it is possible to + configure the 'native-tagged' and 'native-untagged' vlan modes + Since 1.0.7. This uses the optional + nativeMode attribute on the <tag> + element: nativeMode may be set to 'tagged' or + 'untagged'. The id atribute of the element sets the native vlan. +

+
Modifying virtual link state
   ...
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index a1198ce6be..6a4b36df2a 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -446,6 +446,13 @@
         <parameters interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
       </virtualport>
     </interface>
+    <interface type='bridge'>
+      <vlan trunk='yes'>
+        <tag id='42'/>
+        <tag id='123' nativeMode='untagged'/>
+      </vlan>
+      ...
+    </interface>
   <devices>
   ...
@@ -468,6 +475,14 @@ is desired, the optional attribute trunk='yes' can be added to the vlan element.

+

+ For network connections using openvswitch it is possible to + configure the 'native-tagged' and 'native-untagged' vlan modes + Since 1.0.7. This uses the optional + nativeMode attribute on the <tag> + element: nativeMode may be set to 'tagged' or + 'untagged'. The id atribute of the element sets the native vlan. +

<vlan> elements can also be specified in a <portgroup> element, as well as directly in diff --git a/docs/schemas/networkcommon.rng b/docs/schemas/networkcommon.rng index 51ff7592ea..e60f1fc99d 100644 --- a/docs/schemas/networkcommon.rng +++ b/docs/schemas/networkcommon.rng @@ -204,6 +204,14 @@ 4095 + + + + tagged + untagged + + + diff --git a/src/conf/netdev_vlan_conf.c b/src/conf/netdev_vlan_conf.c index 13ba8c6ab8..82ff9e8b65 100644 --- a/src/conf/netdev_vlan_conf.c +++ b/src/conf/netdev_vlan_conf.c @@ -17,6 +17,7 @@ * * Authors: * Laine Stump + * James Robson */ #include @@ -27,12 +28,16 @@ #define VIR_FROM_THIS VIR_FROM_NONE +VIR_ENUM_IMPL(virNativeVlanMode, VIR_NATIVE_VLAN_MODE_LAST, + "default", "tagged", "untagged") + int virNetDevVlanParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virNetDevVlanPtr def) { int ret = -1; xmlNodePtr save = ctxt->node; const char *trunk = NULL; + const char *nativeMode = NULL; xmlNodePtr *tagNodes = NULL; int nTags, ii; @@ -54,6 +59,8 @@ virNetDevVlanParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virNetDevVlanPtr de goto error; } + def->nativeMode = 0; + def->nativeTag = 0; for (ii = 0; ii < nTags; ii++) { unsigned long id; @@ -68,6 +75,22 @@ virNetDevVlanParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virNetDevVlanPtr de _("vlan tag id %lu too large (maximum 4095)"), id); goto error; } + if ((nativeMode = virXPathString("string(./@nativeMode)", ctxt))) { + if (def->nativeMode != 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("duplicate native vlan setting")); + goto error; + } + if ((def->nativeMode + = virNativeVlanModeTypeFromString(nativeMode)) <= 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid \"nativeMode='%s'\" " + "in vlan element"), + nativeMode); + goto error; + } + def->nativeTag = id; + } def->tag[ii] = id; } @@ -89,6 +112,12 @@ virNetDevVlanParse(xmlNodePtr node, xmlXPathContextPtr ctxt, virNetDevVlanPtr de "is required for more than one vlan tag"), trunk); goto error; } + if (def->nativeMode != 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("invalid configuration in - \"trunk='no'\" is " + "not allowed with a native vlan id")); + goto error; + } /* allow (but discard) "trunk='no' if there is a single tag */ if (STRCASENEQ(trunk, "no")) { virReportError(VIR_ERR_XML_ERROR, @@ -125,7 +154,19 @@ virNetDevVlanFormat(virNetDevVlanPtr def, virBufferPtr buf) virBufferAsprintf(buf, "\n", def->trunk ? " trunk='yes'" : ""); for (ii = 0; ii < def->nTags; ii++) { - virBufferAsprintf(buf, " \n", def->tag[ii]); + if (def->nativeMode != VIR_NATIVE_VLAN_MODE_DEFAULT && + def->nativeTag == def->tag[ii]) { + /* check the nativeMode in case we get */ + const char *mode = virNativeVlanModeTypeToString(def->nativeMode); + if (!mode) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Bad value for nativeMode")); + } + virBufferAsprintf(buf, " \n", + def->tag[ii], mode); + } else { + virBufferAsprintf(buf, " \n", def->tag[ii]); + } } virBufferAddLit(buf, "\n"); return 0; diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c index 2aee445a58..5834e4e413 100644 --- a/src/util/virnetdevopenvswitch.c +++ b/src/util/virnetdevopenvswitch.c @@ -109,6 +109,20 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname, virCommandAddArgList(cmd, "--timeout=5", "--", "--may-exist", "add-port", brname, ifname, NULL); + switch (virtVlan->nativeMode) { + case VIR_NATIVE_VLAN_MODE_TAGGED: + virCommandAddArg(cmd, "vlan_mode=native-tagged"); + virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag); + break; + case VIR_NATIVE_VLAN_MODE_UNTAGGED: + virCommandAddArg(cmd, "vlan_mode=native-untagged"); + virCommandAddArgFormat(cmd, "tag=%d", virtVlan->nativeTag); + break; + case VIR_NATIVE_VLAN_MODE_DEFAULT: + default: + break; + } + if (virBufferUse(&buf) != 0) virCommandAddArgList(cmd, virBufferCurrentContent(&buf), NULL); diff --git a/src/util/virnetdevvlan.c b/src/util/virnetdevvlan.c index 2fe2017b58..eed32f75ab 100644 --- a/src/util/virnetdevvlan.c +++ b/src/util/virnetdevvlan.c @@ -33,6 +33,8 @@ virNetDevVlanClear(virNetDevVlanPtr vlan) { VIR_FREE(vlan->tag); vlan->nTags = 0; + vlan->nativeMode = 0; + vlan->nativeTag = 0; } void @@ -54,7 +56,9 @@ virNetDevVlanEqual(const virNetDevVlanPtr a, const virNetDevVlanPtr b) return false; if (a->trunk != b->trunk || - a->nTags != b->nTags) { + a->nTags != b->nTags || + a->nativeMode != b->nativeMode || + a->nativeTag != b->nativeTag) { return false; } @@ -89,6 +93,8 @@ virNetDevVlanCopy(virNetDevVlanPtr dst, const virNetDevVlanPtr src) dst->trunk = src->trunk; dst->nTags = src->nTags; + dst->nativeMode = src->nativeMode; + dst->nativeTag = src->nativeTag; memcpy(dst->tag, src->tag, src->nTags * sizeof(*src->tag)); return 0; } diff --git a/src/util/virnetdevvlan.h b/src/util/virnetdevvlan.h index c6b16efd2e..fd1762a266 100644 --- a/src/util/virnetdevvlan.h +++ b/src/util/virnetdevvlan.h @@ -18,16 +18,29 @@ * Authors: * Laine Stump */ - #ifndef __VIR_NETDEV_VLAN_H__ # define __VIR_NETDEV_VLAN_H__ +# include + +typedef enum { + VIR_NATIVE_VLAN_MODE_DEFAULT = 0, + VIR_NATIVE_VLAN_MODE_TAGGED, + VIR_NATIVE_VLAN_MODE_UNTAGGED, + + VIR_NATIVE_VLAN_MODE_LAST +} virNativeVlanMode; + +VIR_ENUM_DECL(virNativeVlanMode) + typedef struct _virNetDevVlan virNetDevVlan; typedef virNetDevVlan *virNetDevVlanPtr; struct _virNetDevVlan { bool trunk; /* true if this is a trunk */ int nTags; /* number of tags in array */ unsigned int *tag; /* pointer to array of tags */ + int nativeMode; /* enum virNativeVlanMode */ + unsigned int nativeTag; }; void virNetDevVlanClear(virNetDevVlanPtr vlan); diff --git a/tests/networkxml2xmlin/openvswitch-net.xml b/tests/networkxml2xmlin/openvswitch-net.xml index a3d82b165e..2f6084d690 100644 --- a/tests/networkxml2xmlin/openvswitch-net.xml +++ b/tests/networkxml2xmlin/openvswitch-net.xml @@ -21,4 +21,13 @@ + + + + + + + + + diff --git a/tests/networkxml2xmlout/openvswitch-net.xml b/tests/networkxml2xmlout/openvswitch-net.xml index a3d82b165e..2f6084d690 100644 --- a/tests/networkxml2xmlout/openvswitch-net.xml +++ b/tests/networkxml2xmlout/openvswitch-net.xml @@ -21,4 +21,13 @@ + + + + + + + + +