[RFC v2 PATCH 1/4] util: Add virNetDevBridgeSetupVlans function

Leigh Brown posted 4 patches 1 day, 15 hours ago
[RFC v2 PATCH 1/4] util: Add virNetDevBridgeSetupVlans function
Posted by Leigh Brown 1 day, 15 hours ago
In preparation for adding vlan support using iproute2 bridge vlan
functionality, add the virNetDevBridgeSetupVlans function that
configures a bridge interface using the passed virNetDevVlan
struct.

Signed-off-by: Leigh Brown <leigh@solinno.co.uk>
---
 meson.build                |  1 +
 src/util/virnetdevbridge.c | 57 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/meson.build b/meson.build
index ca1b915737..39c01ebeef 100644
--- a/meson.build
+++ b/meson.build
@@ -857,6 +857,7 @@ optional_programs = [
   'ovs-vsctl',
   'rmmod',
   'tc',
+  'bridge',
 ] + optional_test_programs
 
 missing_optional_programs = []
diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c
index 5fd88f3195..353f95b040 100644
--- a/src/util/virnetdevbridge.c
+++ b/src/util/virnetdevbridge.c
@@ -24,6 +24,7 @@
 #include "virfile.h"
 #include "virlog.h"
 #include "virstring.h"
+#include "vircommand.h"
 
 #ifdef WITH_NET_IF_H
 # include <net/if.h>
@@ -379,8 +380,64 @@ virNetDevBridgePortSetIsolated(const char *brname G_GNUC_UNUSED,
                          _("Unable to set bridge port isolated on this platform"));
     return -1;
 }
+
 #endif
 
+static int
+virNetDevBridgeSetupVlans(const char *ifname, const virNetDevVlan *virtVlan)
+{
+    g_autoptr(virCommand) cmd = NULL;
+
+    if (!virtVlan || !virtVlan->nTags)
+        return 0;
+
+    // The interface will have been automatically added to vlan 1, so remove it
+    cmd = virCommandNewArgList(BRIDGE, "vlan", "delete",
+                                       "dev", ifname, "vid", "1", NULL);
+    if (virCommandRun(cmd, NULL) < 0)
+        return -1;
+
+    // If trunk mode, add the native VLAN then add any others
+    if (virtVlan->trunk) {
+        size_t i;
+
+        if (virtVlan->nativeTag) {
+            virCommandFree(cmd);
+            cmd = virCommandNewArgList(BRIDGE, "vlan", "add",
+                                       "dev", ifname, "vid", NULL);
+            virCommandAddArgFormat(cmd, "%d", virtVlan->nativeTag);
+            virCommandAddArg(cmd, "pvid");
+            if (virtVlan->nativeMode == VIR_NATIVE_VLAN_MODE_UNTAGGED ||
+                virtVlan->nativeMode == VIR_NATIVE_VLAN_MODE_DEFAULT)
+                virCommandAddArg(cmd, "untagged");
+            if (virCommandRun(cmd, NULL) < 0)
+                return -1;
+        }
+
+        for (i = 0; i < virtVlan->nTags; i++) {
+            if (virtVlan->tag[i] != virtVlan->nativeTag) {
+                virCommandFree(cmd);
+                cmd = virCommandNewArgList(BRIDGE, "vlan", "add",
+                                           "dev", ifname, "vid", NULL);
+                virCommandAddArgFormat(cmd, "%d", virtVlan->tag[i]);
+                if (virCommandRun(cmd, NULL) < 0)
+                    return -1;
+            }
+        }
+    } else {
+        // In native mode, add the single VLAN as pvid untagged
+        virCommandFree(cmd);
+        cmd = virCommandNewArgList(BRIDGE, "vlan", "add",
+                                   "dev", ifname, "vid", NULL);
+        virCommandAddArgFormat(cmd, "%d", virtVlan->tag[0]);
+        virCommandAddArgList(cmd, "pvid", "untagged", NULL);
+        if (virCommandRun(cmd, NULL) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
 
 /**
  * virNetDevBridgeCreate:
-- 
2.39.5