]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
util: Add vlan support to virNetDevBridgeAddPort
authorLeigh Brown <leigh@solinno.co.uk>
Wed, 8 Jan 2025 13:31:28 +0000 (13:31 +0000)
committerLaine Stump <laine@redhat.com>
Wed, 8 Jan 2025 22:04:27 +0000 (17:04 -0500)
Add virNetDevBridgeSetupVlans function to configure a bridge
interface using the passed virNetDevVlan struct.

Add virVlan parameter to the Linux version of virNetDevBridgeAddPort
and call virNetDevBridgeSetupVlans to set up the required vlan
configuration.

Update callers of virNetDevBridgeAddPort to pass NULL for now.

Signed-off-by: Leigh Brown <leigh@solinno.co.uk>
Reviewed-by: Laine Stump <laine@redhat.com>
src/lxc/lxc_process.c
src/util/virnetdevbridge.c
src/util/virnetdevbridge.h
src/util/virnetdevtap.c

index c2982244f095935ec9d5070c6fecf9e6ce2b789f..7c760cec40301a6f698325d9df1b418ea35214f2 100644 (file)
@@ -289,7 +289,7 @@ virLXCProcessSetupInterfaceTap(virDomainDef *vm,
                                             vport, virDomainNetGetActualVlan(net)) < 0)
                 return NULL;
         } else {
-            if (virNetDevBridgeAddPort(brname, parentVeth) < 0)
+            if (virNetDevBridgeAddPort(brname, parentVeth, NULL) < 0)
                 return NULL;
 
             if (virDomainNetGetActualPortOptionsIsolated(net) == VIR_TRISTATE_BOOL_YES &&
index 5fd88f31952be41925aafe7d5c8361b3bddeb16c..c79d0c79b7b16a0a070b5013ed7df9d0a63b1c38 100644 (file)
@@ -313,6 +313,66 @@ virNetDevBridgePortSetIsolated(const char *brname,
     return virNetDevBridgePortSet(brname, ifname, "isolated", enable ? 1 : 0);
 }
 
+static int
+virNetDevBridgeSetupVlans(const char *ifname, const virNetDevVlan *virtVlan)
+{
+    int error = 0;
+    unsigned short flags;
+
+    if (!virtVlan || !virtVlan->nTags)
+        return 0;
+
+    // The interface will have been automatically added to vlan 1, so remove it
+    if (virNetlinkBridgeVlanFilterSet(ifname, RTM_DELLINK, 0, 1, &error) < 0) {
+        if (error != 0) {
+            virReportSystemError(-error,
+                                 _("error removing vlan filter from interface %1$s"),
+                                 ifname);
+        }
+        return -1;
+    }
+
+    // If trunk mode, add the native VLAN then add the others, if any
+    if (virtVlan->trunk) {
+        size_t i;
+
+        if (virtVlan->nativeTag) {
+            flags = BRIDGE_VLAN_INFO_PVID;
+            if (virtVlan->nativeMode == VIR_NATIVE_VLAN_MODE_UNTAGGED ||
+                virtVlan->nativeMode == VIR_NATIVE_VLAN_MODE_DEFAULT) {
+                flags |= BRIDGE_VLAN_INFO_UNTAGGED;
+            }
+
+            if (virNetlinkBridgeVlanFilterSet(ifname, RTM_SETLINK, flags,
+                                              virtVlan->nativeTag, &error) < 0) {
+                goto error;
+            }
+        }
+
+        for (i = 0; i < virtVlan->nTags; i++) {
+            if (virtVlan->tag[i] != virtVlan->nativeTag)
+                if (virNetlinkBridgeVlanFilterSet(ifname, RTM_SETLINK, 0,
+                                                  virtVlan->tag[i], &error) < 0) {
+                    goto error;
+                }
+        }
+    } else {
+        // In native mode, add the single VLAN as pvid untagged
+        flags = BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED;
+        if (virNetlinkBridgeVlanFilterSet(ifname, RTM_SETLINK, flags,
+                                          virtVlan->tag[0], &error) < 0) {
+            goto error;
+        }
+    }
+
+    return 0;
+
+ error:
+    if (error != 0)
+        virReportSystemError(-error, _("error adding vlan filter to interface %1$s"), ifname);
+    return -1;
+}
+
 
 #else
 int
@@ -593,7 +653,8 @@ int virNetDevBridgeDelete(const char *brname G_GNUC_UNUSED)
  */
 #if defined(WITH_STRUCT_IFREQ) && defined(SIOCBRADDIF)
 int virNetDevBridgeAddPort(const char *brname,
-                           const char *ifname)
+                           const char *ifname,
+                           const virNetDevVlan *virtVlan)
 {
     struct ifreq ifr;
     VIR_AUTOCLOSE fd = -1;
@@ -613,14 +674,20 @@ int virNetDevBridgeAddPort(const char *brname,
         return -1;
     }
 
-    return 0;
+    return virNetDevBridgeSetupVlans(ifname, virtVlan);
 }
 #elif defined(WITH_BSD_BRIDGE_MGMT)
 int virNetDevBridgeAddPort(const char *brname,
-                           const char *ifname)
+                           const char *ifname,
+                           const virNetDevVlan *virtVlan)
 {
     struct ifbreq req = { 0 };
 
+    if (virtVlan) {
+        virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
+        return -1;
+    }
+
     if (virStrcpyStatic(req.ifbr_ifsname, ifname) < 0) {
         virReportSystemError(ERANGE,
                              _("Network interface name '%1$s' is too long"),
@@ -638,7 +705,8 @@ int virNetDevBridgeAddPort(const char *brname,
 }
 #else
 int virNetDevBridgeAddPort(const char *brname,
-                           const char *ifname)
+                           const char *ifname,
+                           const virNetDevVlan *virtVlan G_GNUC_UNUSED)
 {
     virReportSystemError(ENOSYS,
                          _("Unable to add bridge %1$s port %2$s"), brname, ifname);
index db4099bf0bd5215791b3d0b47620e5bf2b5d5c0a..5f51656abe2af385ac21ff9785d5cc9b07db2a05 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "internal.h"
 #include "virmacaddr.h"
+#include "virnetdevvlan.h"
 
 int virNetDevBridgeCreate(const char *brname,
                           const virMacAddr *mac)
@@ -28,7 +29,8 @@ int virNetDevBridgeDelete(const char *brname)
     ATTRIBUTE_NONNULL(1) G_GNUC_WARN_UNUSED_RESULT;
 
 int virNetDevBridgeAddPort(const char *brname,
-                           const char *ifname)
+                           const char *ifname,
+                           const virNetDevVlan *virtVlan)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) G_GNUC_WARN_UNUSED_RESULT;
 
 int virNetDevBridgeRemovePort(const char *brname,
index 2701ba6dfc22b01bee83f00a77bde82267b06f14..a9573eb8e1924a5a2ab917f64d78a46f3f459dfd 100644 (file)
@@ -483,7 +483,7 @@ virNetDevTapAttachBridge(const char *tapname,
                 return -1;
         }
     } else {
-        if (virNetDevBridgeAddPort(brname, tapname) < 0)
+        if (virNetDevBridgeAddPort(brname, tapname, NULL) < 0)
             return -1;
 
         if (isolatedPort == VIR_TRISTATE_BOOL_YES &&