[libvirt] [PATCH 7/7] conf: split <forward> parser/clear into separate functions

Laine Stump laine at laine.org
Fri Dec 7 18:56:17 UTC 2012


virNetworkDefUpdateForward requires separate functions to parse and
clear a virNetworkForwardDef by itself, but they were previously just
inlined in the virNetworkDef parse and free functions. This patch
makes them into separate functions.
---
 src/conf/network_conf.c | 515 ++++++++++++++++++++++++++----------------------
 1 file changed, 280 insertions(+), 235 deletions(-)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 64b0557..8142e98 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -176,7 +176,24 @@ virNetworkDNSDefClear(virNetworkDNSDefPtr def)
     }
 }
 
-void virNetworkDefFree(virNetworkDefPtr def)
+static void
+virNetworkForwardDefClear(virNetworkForwardDefPtr def)
+{
+    int ii;
+
+    for (ii = 0 ; ii < def->npfs && def->pfs ; ii++) {
+        virNetworkForwardPfDefClear(&def->pfs[ii]);
+    }
+    VIR_FREE(def->pfs);
+
+    for (ii = 0 ; ii < def->nifs && def->ifs ; ii++) {
+        virNetworkForwardIfDefClear(&def->ifs[ii]);
+    }
+    VIR_FREE(def->ifs);
+}
+
+void
+virNetworkDefFree(virNetworkDefPtr def)
 {
     int ii;
 
@@ -187,15 +204,7 @@ void virNetworkDefFree(virNetworkDefPtr def)
     VIR_FREE(def->bridge);
     VIR_FREE(def->domain);
 
-    for (ii = 0 ; ii < def->forward.npfs && def->forward.pfs ; ii++) {
-        virNetworkForwardPfDefClear(&def->forward.pfs[ii]);
-    }
-    VIR_FREE(def->forward.pfs);
-
-    for (ii = 0 ; ii < def->forward.nifs && def->forward.ifs ; ii++) {
-        virNetworkForwardIfDefClear(&def->forward.ifs[ii]);
-    }
-    VIR_FREE(def->forward.ifs);
+    virNetworkForwardDefClear(&def->forward);
 
     for (ii = 0 ; ii < def->nips && def->ips ; ii++) {
         virNetworkIpDefClear(&def->ips[ii]);
@@ -1269,6 +1278,211 @@ cleanup:
     return result;
 }
 
+static int
+virNetworkForwardDefParseXML(const char *networkName,
+                             xmlNodePtr node,
+                             xmlXPathContextPtr ctxt,
+                             virNetworkForwardDefPtr def)
+{
+    int ii, ret = -1;
+    xmlNodePtr *forwardIfNodes = NULL;
+    xmlNodePtr *forwardPfNodes = NULL;
+    xmlNodePtr *forwardAddrNodes = NULL;
+    int nForwardIfs, nForwardAddrs, nForwardPfs;
+    char *forwardDev = NULL;
+    char *forwardManaged = NULL;
+    char *type = NULL;
+    xmlNodePtr save = ctxt->node;
+
+    ctxt->node = node;
+
+    if (!(type = virXPathString("string(./@mode)", ctxt))) {
+        def->type = VIR_NETWORK_FORWARD_NAT;
+    } else {
+        if ((def->type = virNetworkForwardTypeFromString(type)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("unknown forwarding type '%s'"), type);
+            goto cleanup;
+        }
+        VIR_FREE(type);
+    }
+
+    forwardManaged = virXPathString("string(./@managed)", ctxt);
+    if (forwardManaged != NULL &&
+        STRCASEEQ(forwardManaged, "yes")) {
+        def->managed = true;
+    }
+
+    /* bridge and hostdev modes can use a pool of physical interfaces */
+    nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
+    if (nForwardIfs < 0) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("invalid <interface> element found in <forward> of network %s"),
+                       networkName);
+        goto cleanup;
+    }
+
+    nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes);
+    if (nForwardAddrs < 0) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("invalid <address> element found in <forward> of network %s"),
+                       networkName);
+        goto cleanup;
+    }
+
+    nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes);
+    if (nForwardPfs < 0) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("invalid <pf> element found in <forward> of network %s"),
+                       networkName);
+        goto cleanup;
+    }
+
+    if (((nForwardIfs > 0) + (nForwardAddrs > 0) + (nForwardPfs > 0)) > 1) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("<address>, <interface>, and <pf> elements in <forward> "
+                         "of network %s are mutually exclusive"),
+                       networkName);
+        goto cleanup;
+    }
+
+    forwardDev = virXPathString("string(./@dev)", ctxt);
+    if (forwardDev && (nForwardAddrs > 0 || nForwardPfs > 0)) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+                       _("the <forward> 'dev' attribute cannot be used when "
+                         "<address> or <pf> sub-elements are present "
+                         "in network %s"));
+        goto cleanup;
+    }
+
+    if (nForwardIfs > 0 || forwardDev) {
+
+        if (VIR_ALLOC_N(def->ifs, MAX(nForwardIfs, 1)) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (forwardDev) {
+            def->ifs[0].device.dev = forwardDev;
+            def->ifs[0].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
+            forwardDev = NULL;
+            def->nifs++;
+        }
+
+        /* parse each <interface> */
+        for (ii = 0; ii < nForwardIfs; ii++) {
+            forwardDev = virXMLPropString(forwardIfNodes[ii], "dev");
+            if (!forwardDev) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("Missing required dev attribute in "
+                                 "<forward> <interface> element of network %s"),
+                               networkName);
+                goto cleanup;
+            }
+
+            if ((ii == 0) && (def->nifs == 1)) {
+                /* both <forward dev='x'> and <interface dev='x'/> are
+                 * present.  If they don't match, it's an error.
+                 */
+                if (STRNEQ(forwardDev, def->ifs[0].device.dev)) {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   _("<forward dev='%s'> must match first "
+                                     "<interface dev='%s'/> in network %s"),
+                                   def->ifs[0].device.dev,
+                                   forwardDev, networkName);
+                    goto cleanup;
+                }
+                VIR_FREE(forwardDev);
+                continue;
+            }
+
+            def->ifs[ii].device.dev = forwardDev;
+            forwardDev = NULL;
+            def->ifs[ii].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
+            def->nifs++;
+        }
+
+    } else if (nForwardAddrs > 0) {
+
+        if (VIR_ALLOC_N(def->ifs, nForwardAddrs) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        for (ii = 0; ii < nForwardAddrs; ii++) {
+            if (!(type = virXMLPropString(forwardAddrNodes[ii], "type"))) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("missing address type in network %s"),
+                               networkName);
+                goto cleanup;
+            }
+
+            if ((def->ifs[ii].type = virNetworkForwardHostdevDeviceTypeFromString(type)) < 0) {
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("unknown address type '%s' in network %s"),
+                               type, networkName);
+                goto cleanup;
+            }
+
+            switch (def->ifs[ii].type) {
+            case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI:
+                if (virDevicePCIAddressParseXML(forwardAddrNodes[ii],
+                                                &def->ifs[ii].device.pci) < 0) {
+                    goto cleanup;
+                }
+                break;
+
+            /* Add USB case here if we ever find a reason to support it */
+
+            default:
+                virReportError(VIR_ERR_XML_ERROR,
+                               _("unsupported address type '%s' in network %s"),
+                               type, networkName);
+                goto cleanup;
+            }
+            VIR_FREE(type);
+            def->nifs++;
+        }
+
+    } else if (nForwardPfs > 1) {
+        virReportError(VIR_ERR_XML_ERROR,
+                       _("Only one <pf> element is allowed in <forward> of network %s"),
+                       networkName);
+        goto cleanup;
+    } else if (nForwardPfs == 1) {
+
+        if (VIR_ALLOC_N(def->pfs, nForwardPfs) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        forwardDev = virXMLPropString(*forwardPfNodes, "dev");
+        if (!forwardDev) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Missing required dev attribute "
+                             "in <pf> element of network '%s'"),
+                           networkName);
+            goto cleanup;
+        }
+
+        def->pfs->dev = forwardDev;
+        forwardDev = NULL;
+        def->npfs++;
+
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(type);
+    VIR_FREE(forwardDev);
+    VIR_FREE(forwardManaged);
+    VIR_FREE(forwardPfNodes);
+    VIR_FREE(forwardIfNodes);
+    VIR_FREE(forwardAddrNodes);
+    ctxt->node = save;
+    return ret;
+}
+
 static virNetworkDefPtr
 virNetworkDefParseXML(xmlXPathContextPtr ctxt)
 {
@@ -1277,17 +1491,11 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     char *stp = NULL;
     xmlNodePtr *ipNodes = NULL;
     xmlNodePtr *portGroupNodes = NULL;
-    xmlNodePtr *forwardIfNodes = NULL;
-    xmlNodePtr *forwardPfNodes = NULL;
-    xmlNodePtr *forwardAddrNodes = NULL;
+    int nIps, nPortGroups;
     xmlNodePtr dnsNode = NULL;
     xmlNodePtr virtPortNode = NULL;
     xmlNodePtr forwardNode = NULL;
-    int nIps, nPortGroups, nForwardIfs, nForwardPfs, nForwardAddrs;
     char *ipv6nogwStr = NULL;
-    char *forwardDev = NULL;
-    char *forwardManaged = NULL;
-    char *type = NULL;
     xmlNodePtr save = ctxt->node;
     xmlNodePtr bandwidthNode = NULL;
     xmlNodePtr vlanNode;
@@ -1353,6 +1561,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     /* Parse bridge information */
     def->bridge = virXPathString("string(./bridge[1]/@name)", ctxt);
     stp = virXPathString("string(./bridge[1]/@stp)", ctxt);
+    def->stp = (stp && STREQ(stp, "off")) ? 0 : 1;
 
     if (virXPathULong("string(./bridge[1]/@delay)", ctxt, &def->delay) < 0)
         def->delay = 0;
@@ -1437,246 +1646,82 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     VIR_FREE(ipNodes);
 
     forwardNode = virXPathNode("./forward", ctxt);
-    if (!forwardNode) {
-        def->forward.type = VIR_NETWORK_FORWARD_NONE;
-        def->stp = (stp && STREQ(stp, "off")) ? 0 : 1;
-    } else {
-        ctxt->node = forwardNode;
-        tmp = virXPathString("string(./@mode)", ctxt);
-        if (tmp) {
-            if ((def->forward.type = virNetworkForwardTypeFromString(tmp)) < 0) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("unknown forwarding type '%s'"), tmp);
-                VIR_FREE(tmp);
-                goto error;
-            }
-            VIR_FREE(tmp);
-        } else {
-            def->forward.type = VIR_NETWORK_FORWARD_NAT;
-        }
-
-        forwardDev = virXPathString("string(./@dev)", ctxt);
-        forwardManaged = virXPathString("string(./@managed)", ctxt);
-        if (forwardManaged != NULL) {
-            if (STRCASEEQ(forwardManaged, "yes"))
-                def->forward.managed = true;
-        }
+    if (forwardNode &&
+        virNetworkForwardDefParseXML(def->name, forwardNode, ctxt, &def->forward) < 0) {
+        goto error;
+    }
 
-        /* all of these modes can use a pool of physical interfaces */
-        nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
-        nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes);
-        nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes);
+    /* Validate some items in the main NetworkDef that need to align
+     * with the chosen forward mode.
+     */
+    switch (def->forward.type) {
+    case VIR_NETWORK_FORWARD_NONE:
+        break;
 
-        if (nForwardIfs < 0 || nForwardPfs < 0 || nForwardAddrs < 0) {
-            virReportError(VIR_ERR_XML_ERROR, "%s",
-                           _("No interface pool or SRIOV physical device given"));
+    case VIR_NETWORK_FORWARD_ROUTE:
+    case VIR_NETWORK_FORWARD_NAT:
+        /* It's pointless to specify L3 forwarding without specifying
+         * the network we're on.
+         */
+        if (def->nips == 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("%s forwarding requested, "
+                             "but no IP address provided for network '%s'"),
+                           virNetworkForwardTypeToString(def->forward.type),
+                           def->name);
             goto error;
         }
-
-        if ((nForwardIfs > 0) && (nForwardAddrs > 0)) {
-            virReportError(VIR_ERR_XML_ERROR, "%s",
-                           _("Address and interface attributes are mutually exclusive"));
+        if (def->forward.nifs > 1) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("multiple forwarding interfaces specified "
+                             "for network '%s', only one is supported"),
+                           def->name);
             goto error;
         }
+        break;
 
-        if ((nForwardPfs > 0) && ((nForwardIfs > 0) || (nForwardAddrs > 0))) {
-            virReportError(VIR_ERR_XML_ERROR, "%s",
-                           _("Address/interface attributes and Physical function are mutually exclusive "));
+    case VIR_NETWORK_FORWARD_PRIVATE:
+    case VIR_NETWORK_FORWARD_VEPA:
+    case VIR_NETWORK_FORWARD_PASSTHROUGH:
+    case VIR_NETWORK_FORWARD_HOSTDEV:
+        if (def->bridge) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("bridge name not allowed in %s mode (network '%s')"),
+                           virNetworkForwardTypeToString(def->forward.type),
+                           def->name);
             goto error;
         }
-
-        if (nForwardPfs == 1) {
-            if (VIR_ALLOC_N(def->forward.pfs, nForwardPfs) < 0) {
-                virReportOOMError();
-                goto error;
-            }
-
-            if (forwardDev) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("A forward Dev should not be used when using a SRIOV PF"));
-                goto error;
-            }
-
-            forwardDev = virXMLPropString(*forwardPfNodes, "dev");
-            if (!forwardDev) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("Missing required dev attribute in network '%s' pf element"),
-                               def->name);
-                goto error;
-            }
-
-            def->forward.pfs->dev = forwardDev;
-            forwardDev = NULL;
-            def->forward.npfs++;
-        } else if (nForwardPfs > 1) {
-            virReportError(VIR_ERR_XML_ERROR, "%s",
-                           _("Use of more than one physical interface is not allowed"));
+        /* fall through to next case */
+    case VIR_NETWORK_FORWARD_BRIDGE:
+        if (def->delay || stp) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("bridge delay/stp options only allowed in route, nat, and isolated mode, not in %s (network '%s')"),
+                           virNetworkForwardTypeToString(def->forward.type),
+                           def->name);
             goto error;
         }
-        if (nForwardAddrs > 0) {
-            int ii;
-
-            if (VIR_ALLOC_N(def->forward.ifs, nForwardAddrs) < 0) {
-                virReportOOMError();
-                goto error;
-            }
-
-            if (forwardDev) {
-                virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("A forward Dev should not be used when using address attribute"));
-                goto error;
-            }
-
-            for (ii = 0; ii < nForwardAddrs; ii++) {
-                type = virXMLPropString(forwardAddrNodes[ii], "type");
-
-                if (type) {
-                    if ((def->forward.ifs[ii].type = virNetworkForwardHostdevDeviceTypeFromString(type)) < 0) {
-                        virReportError(VIR_ERR_XML_ERROR,
-                                       _("unknown address type '%s'"), type);
-                        goto error;
-                    }
-                } else {
-                    virReportError(VIR_ERR_XML_ERROR,
-                                   "%s", _("No type specified for device address"));
-                    goto error;
-                }
-
-                switch (def->forward.ifs[ii].type) {
-                case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI:
-                    if (virDevicePCIAddressParseXML(forwardAddrNodes[ii], &(def->forward.ifs[ii].device.pci)) < 0)
-                        goto error;
-                    break;
-
-                /* Add USB case here */
-
-                default:
-                    virReportError(VIR_ERR_XML_ERROR,
-                                   _("unknown address type '%s'"), type);
-                    goto error;
-                }
-                VIR_FREE(type);
-                def->forward.nifs++;
-            }
-        }
-        else if (nForwardIfs > 0 || forwardDev) {
-            int ii;
-
-            /* allocate array to hold all the portgroups */
-            if (VIR_ALLOC_N(def->forward.ifs, MAX(nForwardIfs, 1)) < 0) {
-                virReportOOMError();
-                goto error;
-            }
-
-            if (forwardDev) {
-                def->forward.ifs[0].device.dev = forwardDev;
-                def->forward.ifs[0].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
-                forwardDev = NULL;
-                def->forward.nifs++;
-            }
-
-            /* parse each forwardIf */
-            for (ii = 0; ii < nForwardIfs; ii++) {
-                forwardDev = virXMLPropString(forwardIfNodes[ii], "dev");
-                if (!forwardDev) {
-                    virReportError(VIR_ERR_XML_ERROR,
-                                   _("Missing required dev attribute in network '%s' forward interface element"),
-                                   def->name);
-                    goto error;
-                }
-
-                if ((ii == 0) && (def->forward.nifs == 1)) {
-                    /* both forwardDev and an interface element are present.
-                     * If they don't match, it's an error. */
-                    if (STRNEQ(forwardDev, def->forward.ifs[0].device.dev)) {
-                        virReportError(VIR_ERR_XML_ERROR,
-                                       _("forward dev '%s' must match first interface element dev '%s' in network '%s'"),
-                                       def->forward.ifs[0].device.dev,
-                                       forwardDev, def->name);
-                        goto error;
-                    }
-                    VIR_FREE(forwardDev);
-                    continue;
-                }
-
-                def->forward.ifs[ii].device.dev = forwardDev;
-                forwardDev = NULL;
-                def->forward.ifs[ii].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
-                def->forward.nifs++;
-            }
-        }
-        VIR_FREE(type);
-        VIR_FREE(forwardDev);
-        VIR_FREE(forwardManaged);
-        VIR_FREE(forwardPfNodes);
-        VIR_FREE(forwardIfNodes);
-        VIR_FREE(forwardAddrNodes);
-        switch (def->forward.type) {
-        case VIR_NETWORK_FORWARD_ROUTE:
-        case VIR_NETWORK_FORWARD_NAT:
-            /* It's pointless to specify L3 forwarding without specifying
-             * the network we're on.
-             */
-            if (def->nips == 0) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("%s forwarding requested, but no IP address provided for network '%s'"),
-                               virNetworkForwardTypeToString(def->forward.type),
-                               def->name);
-                goto error;
-            }
-            if (def->forward.nifs > 1) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("multiple forwarding interfaces specified for network '%s', only one is supported"),
-                               def->name);
-                goto error;
-            }
-            def->stp = (stp && STREQ(stp, "off")) ? 0 : 1;
-            break;
-        case VIR_NETWORK_FORWARD_PRIVATE:
-        case VIR_NETWORK_FORWARD_VEPA:
-        case VIR_NETWORK_FORWARD_PASSTHROUGH:
-        case VIR_NETWORK_FORWARD_HOSTDEV:
-            if (def->bridge) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("bridge name not allowed in %s mode (network '%s')"),
-                               virNetworkForwardTypeToString(def->forward.type),
-                               def->name);
-                goto error;
-            }
-            /* fall through to next case */
-        case VIR_NETWORK_FORWARD_BRIDGE:
-            if (def->delay || stp) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("bridge delay/stp options only allowed in route, nat, and isolated mode, not in %s (network '%s')"),
-                               virNetworkForwardTypeToString(def->forward.type),
-                               def->name);
-                goto error;
-            }
-            if (def->bridge && (def->forward.nifs || def->forward.npfs)) {
-                virReportError(VIR_ERR_XML_ERROR,
-                               _("A network with forward mode='%s' can specify "
-                                 "a  bridge name or a forward dev, but not "
-                                 "both (network '%s')"),
-                               virNetworkForwardTypeToString(def->forward.type),
-                               def->name);
-                goto error;
-            }
-            break;
+        if (def->bridge && (def->forward.nifs || def->forward.npfs)) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("A network with forward mode='%s' can specify "
+                             "a  bridge name or a forward dev, but not "
+                             "both (network '%s')"),
+                           virNetworkForwardTypeToString(def->forward.type),
+                           def->name);
+            goto error;
         }
+        break;
     }
+
     VIR_FREE(stp);
     ctxt->node = save;
     return def;
 
- error:
+error:
     VIR_FREE(stp);
     virNetworkDefFree(def);
     VIR_FREE(ipNodes);
     VIR_FREE(portGroupNodes);
-    VIR_FREE(forwardIfNodes);
-    VIR_FREE(forwardPfNodes);
     VIR_FREE(ipv6nogwStr);
-    VIR_FREE(forwardDev);
     ctxt->node = save;
     return NULL;
 }
-- 
1.7.11.7




More information about the libvir-list mailing list