[PATCH v2 10/19] Refactoring virDomainNetDefParseXML() to use XPath

Kristina Hanicova khanicov at redhat.com
Tue May 4 11:40:04 UTC 2021


Signed-off-by: Kristina Hanicova <khanicov at redhat.com>
---
 src/conf/domain_conf.c | 340 +++++++++++++++++++----------------------
 1 file changed, 157 insertions(+), 183 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d7bee155e7..dc72a91d8d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -10245,7 +10245,13 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
 {
     virDomainNetDef *def;
     virDomainHostdevDef *hostdev;
-    xmlNodePtr cur;
+    xmlNodePtr source_node = NULL;
+    xmlNodePtr virtualport_node = NULL;
+    xmlNodePtr driver_node = NULL;
+    xmlNodePtr filterref_node = NULL;
+    xmlNodePtr actual_node = NULL;
+    xmlNodePtr vlan_node = NULL;
+    xmlNodePtr bandwidth_node = NULL;
     xmlNodePtr tmpNode;
     GHashTable *filterparams = NULL;
     virDomainActualNetDef *actual = NULL;
@@ -10288,6 +10294,8 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
     g_autofree char *vhostuser_path = NULL;
     g_autofree char *vhostuser_type = NULL;
     g_autofree char *vhost_path = NULL;
+    g_autofree char *tap = NULL;
+    g_autofree char *vhost = NULL;
     const char *prefix = xmlopt ? xmlopt->config.netPrefix : NULL;
 
     if (!(def = virDomainNetDefNew(xmlopt)))
@@ -10306,195 +10314,158 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
                                &def->trustGuestRxFilters) < 0)
         goto error;
 
-    cur = node->children;
-    while (cur != NULL) {
-        if (cur->type == XML_ELEMENT_NODE) {
-            if (virXMLNodeNameEqual(cur, "source")) {
-                xmlNodePtr tmpnode = ctxt->node;
+    if ((source_node = virXPathNode("./source", ctxt))) {
+        xmlNodePtr tmpnode = ctxt->node;
+        ctxt->node = source_node;
+        if (virDomainNetIPInfoParseXML(_("interface host IP"), ctxt, &def->hostIP) < 0)
+            goto error;
+        ctxt->node = tmpnode;
 
-                ctxt->node = cur;
-                if (virDomainNetIPInfoParseXML(_("interface host IP"),
-                                               ctxt, &def->hostIP) < 0)
-                    goto error;
-                ctxt->node = tmpnode;
-            }
-            if (!macaddr && virXMLNodeNameEqual(cur, "mac")) {
-                macaddr = virXMLPropString(cur, "address");
-                macaddr_type = virXMLPropString(cur, "type");
-                macaddr_check = virXMLPropString(cur, "check");
-            } else if (!network &&
-                       def->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
-                       virXMLNodeNameEqual(cur, "source")) {
-                network = virXMLPropString(cur, "network");
-                portgroup = virXMLPropString(cur, "portgroup");
-                if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
-                    portid = virXMLPropString(cur, "portid");
-            } else if (!internal &&
-                       def->type == VIR_DOMAIN_NET_TYPE_INTERNAL &&
-                       virXMLNodeNameEqual(cur, "source")) {
-                internal = virXMLPropString(cur, "name");
-            } else if (!bridge &&
-                       def->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
-                       virXMLNodeNameEqual(cur, "source")) {
-                bridge = virXMLPropString(cur, "bridge");
-            } else if (!dev && def->type == VIR_DOMAIN_NET_TYPE_DIRECT &&
-                       virXMLNodeNameEqual(cur, "source")) {
-                dev  = virXMLPropString(cur, "dev");
-                mode = virXMLPropString(cur, "mode");
-            } else if (!dev && def->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
-                       virXMLNodeNameEqual(cur, "source")) {
-                /* This clause is only necessary because from 2010 to
-                 * 2016 it was possible (but never documented) to
-                 * configure the name of the guest-side interface of
-                 * an openvz domain with <source dev='blah'/>.  That
-                 * was blatant misuse of <source>, so was likely
-                 * (hopefully) never used, but just in case there was
-                 * somebody using it, we need to generate an error. If
-                 * the openvz driver is ever deprecated, this clause
-                 * can be removed from here.
-                 */
-                if ((dev = virXMLPropString(cur, "dev"))) {
-                    virReportError(VIR_ERR_XML_ERROR,
-                                   _("Invalid attempt to set <interface type='ethernet'> "
-                                     "device name with <source dev='%s'/>. "
-                                     "Use <target dev='%s'/> (for host-side) "
-                                     "or <guest dev='%s'/> (for guest-side) instead."),
-                                   dev, dev, dev);
-                    goto error;
-                }
-            } else if (!vhostuser_path && !vhostuser_mode && !vhostuser_type
-                       && def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER
-                       && virXMLNodeNameEqual(cur, "source")) {
-                vhostuser_type = virXMLPropString(cur, "type");
-                vhostuser_path = virXMLPropString(cur, "path");
-                vhostuser_mode = virXMLPropString(cur, "mode");
-                if (virDomainChrSourceReconnectDefParseXML(&reconnect, cur, ctxt) < 0)
-                    goto error;
+        if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+            network = virXMLPropString(source_node, "network");
+            portgroup = virXMLPropString(source_node, "portgroup");
+            if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
+                portid = virXMLPropString(source_node, "portid");
+        }
 
-            } else if (!dev
-                       && def->type == VIR_DOMAIN_NET_TYPE_VDPA
-                       && virXMLNodeNameEqual(cur, "source")) {
-                dev = virXMLPropString(cur, "dev");
-            } else if (!def->virtPortProfile
-                       && virXMLNodeNameEqual(cur, "virtualport")) {
-                if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
-                    if (!(def->virtPortProfile
-                          = virNetDevVPortProfileParse(cur,
-                                                       VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS))) {
-                        goto error;
-                    }
-                } else if (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
-                           def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
-                           def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
-                    if (!(def->virtPortProfile
-                          = virNetDevVPortProfileParse(cur,
-                                                       VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS|
-                                                       VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES|
-                                                       VIR_VPORT_XML_REQUIRE_TYPE))) {
-                        goto error;
-                    }
-                } else {
-                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                                   _("<virtualport> element unsupported for"
-                                     " <interface type='%s'>"),
-                                     virDomainNetTypeToString(def->type));
-                    goto error;
-                }
-            } else if (!address &&
-                       (def->type == VIR_DOMAIN_NET_TYPE_SERVER ||
-                        def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
-                        def->type == VIR_DOMAIN_NET_TYPE_MCAST ||
-                        def->type == VIR_DOMAIN_NET_TYPE_UDP) &&
-                       virXMLNodeNameEqual(cur, "source")) {
-                address = virXMLPropString(cur, "address");
-                port = virXMLPropString(cur, "port");
-                if (!localaddr && def->type == VIR_DOMAIN_NET_TYPE_UDP) {
-                    xmlNodePtr tmpnode = ctxt->node;
-                    ctxt->node = cur;
-                    if ((tmpNode = virXPathNode("./local", ctxt))) {
-                        localaddr = virXMLPropString(tmpNode, "address");
-                        localport = virXMLPropString(tmpNode, "port");
-                    }
-                    ctxt->node = tmpnode;
-                }
-            } else if (!ifname &&
-                       virXMLNodeNameEqual(cur, "target")) {
-                ifname = virXMLPropString(cur, "dev");
-                managed_tap = virXMLPropString(cur, "managed");
-            } else if ((!ifname_guest || !ifname_guest_actual) &&
-                       virXMLNodeNameEqual(cur, "guest")) {
-                ifname_guest = virXMLPropString(cur, "dev");
-                ifname_guest_actual = virXMLPropString(cur, "actual");
-            } else if (!linkstate &&
-                       virXMLNodeNameEqual(cur, "link")) {
-                linkstate = virXMLPropString(cur, "state");
-            } else if (!script &&
-                       virXMLNodeNameEqual(cur, "script")) {
-                script = virXMLPropString(cur, "path");
-            } else if (!downscript &&
-                       virXMLNodeNameEqual(cur, "downscript")) {
-                downscript = virXMLPropString(cur, "path");
-            } else if (!domain_name &&
-                       virXMLNodeNameEqual(cur, "backenddomain")) {
-                domain_name = virXMLPropString(cur, "name");
-            } else if (virXMLNodeNameEqual(cur, "model")) {
-                model = virXMLPropString(cur, "type");
-            } else if (virXMLNodeNameEqual(cur, "driver")) {
-                backend = virXMLPropString(cur, "name");
-                txmode = virXMLPropString(cur, "txmode");
-                ioeventfd = virXMLPropString(cur, "ioeventfd");
-                event_idx = virXMLPropString(cur, "event_idx");
-                queues = virXMLPropString(cur, "queues");
-                rx_queue_size = virXMLPropString(cur, "rx_queue_size");
-                tx_queue_size = virXMLPropString(cur, "tx_queue_size");
+        if (def->type == VIR_DOMAIN_NET_TYPE_INTERNAL)
+            internal = virXMLPropString(source_node, "name");
 
-                if (virDomainVirtioOptionsParseXML(cur, &def->virtio) < 0)
-                    goto error;
-            } else if (virXMLNodeNameEqual(cur, "filterref")) {
-                if (filter) {
-                    virReportError(VIR_ERR_XML_ERROR, "%s",
-                                   _("Invalid specification of multiple <filterref>s "
-                                     "in a single <interface>"));
-                    goto error;
-                }
-                filter = virXMLPropString(cur, "filter");
-                virHashFree(filterparams);
-                filterparams = virNWFilterParseParamAttributes(cur);
-            } else if (virXMLNodeNameEqual(cur, "boot")) {
-                /* boot is parsed as part of virDomainDeviceInfoParseXML */
-            } else if (!actual &&
-                       (flags & VIR_DOMAIN_DEF_PARSE_ACTUAL_NET) &&
-                       def->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
-                       virXMLNodeNameEqual(cur, "actual")) {
-                if (virDomainActualNetDefParseXML(cur, ctxt, def,
-                                                  &actual, flags, xmlopt) < 0) {
-                    goto error;
-                }
-            } else if (virXMLNodeNameEqual(cur, "bandwidth")) {
-                if (virNetDevBandwidthParse(&def->bandwidth,
-                                            NULL,
-                                            cur,
-                                            def->type == VIR_DOMAIN_NET_TYPE_NETWORK) < 0)
-                    goto error;
-            } else if (virXMLNodeNameEqual(cur, "vlan")) {
-                if (virNetDevVlanParse(cur, ctxt, &def->vlan) < 0)
-                    goto error;
-            } else if (virXMLNodeNameEqual(cur, "backend")) {
-                char *tmp = NULL;
+        if (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE)
+            bridge = virXMLPropString(source_node, "bridge");
 
-                if ((tmp = virXMLPropString(cur, "tap")))
-                    def->backend.tap = virFileSanitizePath(tmp);
-                VIR_FREE(tmp);
+        if (def->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+            dev = virXMLPropString(source_node, "dev");
+            mode = virXMLPropString(source_node, "mode");
+        }
 
-                if (!vhost_path && (tmp = virXMLPropString(cur, "vhost")))
-                    vhost_path = virFileSanitizePath(tmp);
-                VIR_FREE(tmp);
+        /* This clause is only necessary because from 2010 to 2016 it was
+         * possible (but never documented) to configure the name of the
+         * guest-side interface of an openvz domain with <source dev='blah'/>.
+         * That was blatant misuse of <source>, so was likely (hopefully)
+         * never used, but just in case there was somebody using it, we
+         * need to generate an error. If the openvz driver is ever
+         * deprecated, this clause can be removed from here.
+         */
+        if (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
+            (dev = virXMLPropString(source_node, "dev"))) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid attempt to set <interface type='ethernet'> "
+                             "device name with <source dev='%s'/>. "
+                             "Use <target dev='%s'/> (for host-side) "
+                             "or <guest dev='%s'/> (for guest-side) instead."),
+                           dev, dev, dev);
+            goto error;
+        }
+
+        if (def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+            vhostuser_type = virXMLPropString(source_node, "type");
+            vhostuser_path = virXMLPropString(source_node, "path");
+            vhostuser_mode = virXMLPropString(source_node, "mode");
+            if (virDomainChrSourceReconnectDefParseXML(&reconnect, source_node, ctxt) < 0)
+                goto error;
+        }
+
+        if (def->type == VIR_DOMAIN_NET_TYPE_VDPA)
+            dev = virXMLPropString(source_node, "dev");
+
+        if (def->type == VIR_DOMAIN_NET_TYPE_SERVER ||
+            def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
+            def->type == VIR_DOMAIN_NET_TYPE_MCAST ||
+            def->type == VIR_DOMAIN_NET_TYPE_UDP) {
+
+            address = virXMLPropString(source_node, "address");
+            port = virXMLPropString(source_node, "port");
+            if (def->type == VIR_DOMAIN_NET_TYPE_UDP) {
+                xmlNodePtr tmp_node = ctxt->node;
+                ctxt->node = source_node;
+                if ((tmpNode = virXPathNode("./local", ctxt))) {
+                    localaddr = virXMLPropString(tmpNode, "address");
+                    localport = virXMLPropString(tmpNode, "port");
+                }
+                ctxt->node = tmp_node;
             }
         }
-        cur = cur->next;
     }
 
-    if (macaddr) {
+    if ((virtualport_node = virXPathNode("./virtualport", ctxt))) {
+        if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+            if (!(def->virtPortProfile
+                  = virNetDevVPortProfileParse(virtualport_node,
+                                               VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS))) {
+                goto error;
+            }
+        } else if (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+                   def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
+                   def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+            if (!(def->virtPortProfile
+                  = virNetDevVPortProfileParse(virtualport_node, VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS|
+                                               VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES|
+                                               VIR_VPORT_XML_REQUIRE_TYPE))) {
+                goto error;
+            }
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("<virtualport> element unsupported for"
+                             " <interface type='%s'>"),
+                             virDomainNetTypeToString(def->type));
+            goto error;
+        }
+    }
+
+    ifname = virXPathString("string(./target/@dev)", ctxt);
+    managed_tap = virXPathString("string(./target/@managed)", ctxt);
+
+    ifname_guest = virXPathString("string(./guest/@dev)", ctxt);
+    ifname_guest_actual = virXPathString("string(./guest/@actual)", ctxt);
+
+    linkstate = virXPathString("string(./link/@state)", ctxt);
+    script = virXPathString("string(./script/@path)", ctxt);
+    downscript = virXPathString("string(./downscript/@path)", ctxt);
+    domain_name = virXPathString("string(./backenddomain/@name)", ctxt);
+    model = virXPathString("string(./model/@type)", ctxt);
+
+    if ((driver_node = virXPathNode("./driver", ctxt)) &&
+        (virDomainVirtioOptionsParseXML(driver_node, &def->virtio) < 0))
+        goto error;
+
+    backend = virXMLPropString(driver_node, "name");
+    txmode = virXMLPropString(driver_node, "txmode");
+    ioeventfd = virXMLPropString(driver_node, "ioeventfd");
+    event_idx = virXMLPropString(driver_node, "event_idx");
+    queues = virXMLPropString(driver_node, "queues");
+    rx_queue_size = virXMLPropString(driver_node, "rx_queue_size");
+    tx_queue_size = virXMLPropString(driver_node, "tx_queue_size");
+
+    if ((filterref_node = virXPathNode("./filterref", ctxt))) {
+        filter = virXMLPropString(filterref_node, "filter");
+        virHashFree(filterparams);
+        filterparams = virNWFilterParseParamAttributes(filterref_node);
+    }
+
+    if ((flags & VIR_DOMAIN_DEF_PARSE_ACTUAL_NET) &&
+        def->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+        (actual_node = virXPathNode("./actual", ctxt)) &&
+        (virDomainActualNetDefParseXML(actual_node, ctxt, def,
+                                      &actual, flags, xmlopt) < 0))
+        goto error;
+
+    if ((bandwidth_node = virXPathNode("./bandwidth", ctxt)) &&
+        (virNetDevBandwidthParse(&def->bandwidth, NULL, bandwidth_node,
+                                 def->type == VIR_DOMAIN_NET_TYPE_NETWORK) < 0))
+        goto error;
+
+    if ((vlan_node = virXPathNode("./vlan", ctxt)) &&
+        (virNetDevVlanParse(vlan_node, ctxt, &def->vlan) < 0))
+        goto error;
+
+    if ((tap = virXPathString("string(./backend/@tap)", ctxt)))
+        def->backend.tap = virFileSanitizePath(tap);
+
+    if ((vhost = virXPathString("string(./backend/@vhost)", ctxt)))
+        vhost_path = virFileSanitizePath(vhost);
+
+    if ((macaddr = virXPathString("string(./mac/@address)", ctxt))) {
         if (virMacAddrParse((const char *)macaddr, &def->mac) < 0) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("unable to parse mac address '%s'"),
@@ -10512,8 +10483,9 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
         def->mac_generated = true;
     }
 
-    if (macaddr_type) {
+    if ((macaddr_type = virXPathString("string(./mac/@type)", ctxt))) {
         int tmp;
+
         if ((tmp = virDomainNetMacTypeTypeFromString(macaddr_type)) <= 0) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("invalid mac address type value: '%s'. Valid "
@@ -10523,8 +10495,10 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
         }
         def->mac_type = tmp;
     }
-    if (macaddr_check) {
+
+    if ((macaddr_check = virXPathString("string(./mac/@check)", ctxt))) {
         int tmpCheck;
+
         if ((tmpCheck = virTristateBoolTypeFromString(macaddr_check)) < 0) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("invalid mac address check value: '%s'"),
-- 
2.30.2




More information about the libvir-list mailing list