[libvirt] [PATCHv2 2/3] support new forward mode 'vlan' for virtual network

Shi Lei shilei.massclouds at gmx.com
Tue Aug 14 07:00:51 UTC 2018


Signed-off-by: Shi Lei <shilei.massclouds at gmx.com>
---
 src/conf/domain_conf.c       |  1 +
 src/conf/network_conf.c      | 24 +++++++++++++++++--
 src/conf/network_conf.h      |  1 +
 src/conf/virnetworkobj.c     |  1 +
 src/esx/esx_network_driver.c |  1 +
 src/network/bridge_driver.c  | 55 ++++++++++++++++++++++++++++++++++++++++++--
 src/qemu/qemu_process.c      |  1 +
 7 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 77cc737..0b6d247 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -30369,6 +30369,7 @@ virDomainNetResolveActualType(virDomainNetDefPtr iface)
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         /* for these forward types, the actual net type really *is*
          * NETWORK; we just keep the info from the portgroup in
          * iface->data.network.actual
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index c08456b..cb51c7b 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -50,7 +50,7 @@ VIR_ENUM_IMPL(virNetworkForward,
               VIR_NETWORK_FORWARD_LAST,
               "none", "nat", "route", "open",
               "bridge", "private", "vepa", "passthrough",
-              "hostdev")
+              "hostdev", "vlan")
 
 VIR_ENUM_IMPL(virNetworkBridgeMACTableManager,
               VIR_NETWORK_BRIDGE_MAC_TABLE_MANAGER_LAST,
@@ -1914,6 +1914,24 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         }
         break;
 
+    case VIR_NETWORK_FORWARD_VLAN:
+        if (def->forward.nifs != 1 ||
+            strlen(def->forward.ifs[0].device.dev) == 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("network '%s' in forward mode 'vlan' requests "
+                             "one and only one interface"),
+                           def->name);
+            goto error;
+        }
+        if (def->vlan.nTags != 1 || def->vlan.tag[0] >= 4096) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("network '%s' in forward mode 'vlan' requests "
+                             "one and only one VLan-Tag"),
+                           def->name);
+            goto error;
+        }
+        break;
+
     case VIR_NETWORK_FORWARD_PRIVATE:
     case VIR_NETWORK_FORWARD_VEPA:
     case VIR_NETWORK_FORWARD_PASSTHROUGH:
@@ -1970,6 +1988,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         case VIR_NETWORK_FORWARD_NAT:
         case VIR_NETWORK_FORWARD_ROUTE:
         case VIR_NETWORK_FORWARD_OPEN:
+        case VIR_NETWORK_FORWARD_VLAN:
             break;
 
         case VIR_NETWORK_FORWARD_BRIDGE:
@@ -1978,7 +1997,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         case VIR_NETWORK_FORWARD_PASSTHROUGH:
         case VIR_NETWORK_FORWARD_HOSTDEV:
             virReportError(VIR_ERR_XML_ERROR,
-                           _("mtu size only allowed in open, route, nat, "
+                           _("mtu size only allowed in open, route, nat, vlan "
                              "and isolated mode, not in %s (network '%s')"),
                            virNetworkForwardTypeToString(def->forward.type),
                            def->name);
@@ -2494,6 +2513,7 @@ virNetworkDefFormatBuf(virBufferPtr buf,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         hasbridge = true;
         break;
 
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 54c8ed1..47bb83e 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -53,6 +53,7 @@ typedef enum {
     VIR_NETWORK_FORWARD_VEPA,
     VIR_NETWORK_FORWARD_PASSTHROUGH,
     VIR_NETWORK_FORWARD_HOSTDEV,
+    VIR_NETWORK_FORWARD_VLAN,
 
     VIR_NETWORK_FORWARD_LAST,
 } virNetworkForwardType;
diff --git a/src/conf/virnetworkobj.c b/src/conf/virnetworkobj.c
index b13e5a7..fd5c268 100644
--- a/src/conf/virnetworkobj.c
+++ b/src/conf/virnetworkobj.c
@@ -1014,6 +1014,7 @@ virNetworkLoadConfig(virNetworkObjListPtr nets,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         if (!def->mac_specified) {
             virNetworkSetBridgeMacAddr(def);
             virNetworkSaveConfig(configDir, def);
diff --git a/src/esx/esx_network_driver.c b/src/esx/esx_network_driver.c
index 31bceb7..8f91ae9 100644
--- a/src/esx/esx_network_driver.c
+++ b/src/esx/esx_network_driver.c
@@ -334,6 +334,7 @@ esxNetworkDefineXML(virConnectPtr conn, const char *xml)
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
     case VIR_NETWORK_FORWARD_PRIVATE:
     case VIR_NETWORK_FORWARD_VEPA:
     case VIR_NETWORK_FORWARD_PASSTHROUGH:
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 588b0d1..2e203f5 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -451,6 +451,7 @@ networkUpdateState(virNetworkObjPtr obj,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         /* If bridge doesn't exist, then mark it inactive */
         if (!(def->bridge && virNetDevExists(def->bridge) == 1))
             virNetworkObjSetActive(obj, false);
@@ -2099,6 +2100,7 @@ networkRefreshDaemonsHelper(virNetworkObjPtr obj,
         case VIR_NETWORK_FORWARD_NAT:
         case VIR_NETWORK_FORWARD_ROUTE:
         case VIR_NETWORK_FORWARD_OPEN:
+        case VIR_NETWORK_FORWARD_VLAN:
             /* Only the three L3 network types that are configured by
              * libvirt will have a dnsmasq or radvd daemon associated
              * with them.  Here we send a SIGHUP to an existing
@@ -2155,6 +2157,7 @@ networkReloadFirewallRulesHelper(virNetworkObjPtr obj,
         case VIR_NETWORK_FORWARD_NONE:
         case VIR_NETWORK_FORWARD_NAT:
         case VIR_NETWORK_FORWARD_ROUTE:
+        case VIR_NETWORK_FORWARD_VLAN:
             /* Only three of the L3 network types that are configured by
              * libvirt need to have iptables rules reloaded. The 4th L3
              * network type, forward='open', doesn't need this because it
@@ -2552,6 +2555,29 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver,
     if (virNetDevBandwidthSet(def->bridge, def->bandwidth, true, true) < 0)
         goto err5;
 
+    if (def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
+        /* ifs[0].device.dev and vlan.tag[0] have been validated
+         * in virNetworkDefParseXML
+         */
+        VIR_AUTOFREE(char *) vlanDevName = NULL;
+        if (virNetDevCreateVLanDev(def->forward.ifs[0].device.dev, def->vlan.tag[0],
+                                   &vlanDevName) < 0)
+            goto err5;
+
+        if (virNetDevBridgeAddPort(def->bridge, vlanDevName) < 0) {
+            virNetDevDestroyVLanDev(def->forward.ifs[0].device.dev,
+                                    def->vlan.tag[0], vlanDevName);
+            goto err5;
+        }
+
+        if (virNetDevSetOnline(vlanDevName, true) < 0) {
+            ignore_value(virNetDevBridgeRemovePort(def->bridge, vlanDevName));
+            virNetDevDestroyVLanDev(def->forward.ifs[0].device.dev,
+                                    def->vlan.tag[0], vlanDevName);
+            goto err5;
+        }
+    }
+
     VIR_FREE(macTapIfName);
     VIR_FREE(macMapFile);
 
@@ -2616,6 +2642,17 @@ networkShutdownNetworkVirtual(virNetworkDriverStatePtr driver,
     pid_t radvdPid;
     pid_t dnsmasqPid;
 
+    if (def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
+        VIR_AUTOFREE(char *) vlanDevName = NULL;
+        if (!virNetDevGetVLanDevName(def->forward.ifs[0].device.dev,
+                                     def->vlan.tag[0], &vlanDevName)) {
+            ignore_value(virNetDevSetOnline(vlanDevName, false));
+            ignore_value(virNetDevBridgeRemovePort(def->bridge, vlanDevName));
+            virNetDevDestroyVLanDev(def->forward.ifs[0].device.dev,
+                                    def->vlan.tag[0], vlanDevName);
+        }
+    }
+
     if (def->bandwidth)
         virNetDevBandwidthClear(def->bridge);
 
@@ -2759,6 +2796,7 @@ networkCreateInterfacePool(virNetworkDefPtr netdef)
         case VIR_NETWORK_FORWARD_NAT:
         case VIR_NETWORK_FORWARD_ROUTE:
         case VIR_NETWORK_FORWARD_OPEN:
+        case VIR_NETWORK_FORWARD_VLAN:
             /* by definition these will never be encountered here */
             break;
 
@@ -2861,6 +2899,7 @@ networkStartNetwork(virNetworkDriverStatePtr driver,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         if (networkStartNetworkVirtual(driver, obj) < 0)
             goto cleanup;
         break;
@@ -2948,6 +2987,7 @@ networkShutdownNetwork(virNetworkDriverStatePtr driver,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         ret = networkShutdownNetworkVirtual(driver, obj);
         break;
 
@@ -3332,6 +3372,7 @@ networkValidate(virNetworkDriverStatePtr driver,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         /* if no bridge name was given in the config, find a name
          * unused by any other libvirt networks and assign it.
          */
@@ -3510,11 +3551,12 @@ networkValidate(virNetworkDriverStatePtr driver,
 
     /* The only type of networks that currently support transparent
      * vlan configuration are those using hostdev sr-iov devices from
-     * a pool, and those using an Open vSwitch bridge.
+     * a pool, and those using an Open vSwitch bridge or based on 8021q.
      */
 
     vlanAllowed = (def->forward.type == VIR_NETWORK_FORWARD_HOSTDEV ||
                    def->forward.type == VIR_NETWORK_FORWARD_PASSTHROUGH ||
+                   def->forward.type == VIR_NETWORK_FORWARD_VLAN ||
                    (def->forward.type == VIR_NETWORK_FORWARD_BRIDGE &&
                     def->virtPortProfile &&
                     def->virtPortProfile->virtPortType
@@ -3596,6 +3638,11 @@ networkValidate(virNetworkDriverStatePtr driver,
             }
         }
     }
+
+    if (def->forward.type == VIR_NETWORK_FORWARD_VLAN) {
+        if (virNetDevLoad8021Q() < 0)
+            return -1;
+    }
     return 0;
 }
 
@@ -3825,6 +3872,7 @@ networkUpdate(virNetworkPtr net,
         case VIR_NETWORK_FORWARD_NONE:
         case VIR_NETWORK_FORWARD_NAT:
         case VIR_NETWORK_FORWARD_ROUTE:
+        case VIR_NETWORK_FORWARD_VLAN:
             switch (section) {
             case VIR_NETWORK_SECTION_FORWARD:
             case VIR_NETWORK_SECTION_FORWARD_INTERFACE:
@@ -4531,6 +4579,7 @@ networkAllocateActualDevice(virDomainDefPtr dom,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         /* for these forward types, the actual net type really *is*
          * NETWORK; we just keep the info from the portgroup in
          * iface->data.network.actual
@@ -4792,7 +4841,8 @@ networkAllocateActualDevice(virDomainDefPtr dom,
          * mode) and openvswitch bridges. Otherwise log an error and
          * fail
          */
-        if (!(actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
+        if (!(netdef->forward.type == VIR_NETWORK_FORWARD_VLAN ||
+              actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
               (actualType == VIR_DOMAIN_NET_TYPE_DIRECT &&
                virDomainNetGetActualDirectMode(iface)
                == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) ||
@@ -5133,6 +5183,7 @@ networkReleaseActualDevice(virDomainDefPtr dom,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         if (iface->data.network.actual && networkUnplugBandwidth(obj, iface) < 0)
             goto error;
         break;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 02fdc55..ae725a8 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4550,6 +4550,7 @@ qemuProcessGetNetworkAddress(const char *netname,
     case VIR_NETWORK_FORWARD_NAT:
     case VIR_NETWORK_FORWARD_ROUTE:
     case VIR_NETWORK_FORWARD_OPEN:
+    case VIR_NETWORK_FORWARD_VLAN:
         ipdef = virNetworkDefGetIPByIndex(netdef, AF_UNSPEC, 0);
         if (!ipdef) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
-- 
2.7.4




More information about the libvir-list mailing list