virDomainActualNetDefParseXML(xmlNodePtr node,
                              xmlXPathContextPtr ctxt,
                              virDomainNetDefPtr parent,
                              virDomainActualNetDefPtr *def,
                              unsigned int flags)
{
    virDomainActualNetDefPtr actual = NULL;
    int ret = -1;
    VIR_XPATH_NODE_AUTORESTORE(ctxt);
    xmlNodePtr bandwidth_node = NULL;
    xmlNodePtr vlanNode;
    xmlNodePtr virtPortNode;
    g_autofree char *type = NULL;
    g_autofree char *mode = NULL;
    g_autofree char *addrtype = NULL;
    g_autofree char *trustGuestRxFilters = NULL;
    g_autofree char *macTableManager = NULL;

    if (VIR_ALLOC(actual) < 0)
        return -1;

    ctxt->node = node;

    type = virXMLPropString(node, "type");
    if (!type) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing type attribute in interface's <actual> element"));
        goto error;
    }
    if ((actual->type = virDomainNetTypeFromString(type)) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unknown type '%s' in interface's <actual> element"), type);
        goto error;
    }
    if (actual->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
        actual->type != VIR_DOMAIN_NET_TYPE_DIRECT &&
        actual->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
        actual->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported type '%s' in interface's <actual> element"),
                       type);
        goto error;
    }

    trustGuestRxFilters = virXMLPropString(node, "trustGuestRxFilters");
    if (trustGuestRxFilters &&
        ((actual->trustGuestRxFilters
          = virTristateBoolTypeFromString(trustGuestRxFilters)) <= 0)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unknown trustGuestRxFilters value '%s'"),
                       trustGuestRxFilters);
        goto error;
    }

    virtPortNode = virXPathNode("./virtualport", ctxt);
    if (virtPortNode) {
        if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
            actual->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
            actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
            /* the virtualport in <actual> should always already
             * have an instanceid/interfaceid if its required,
             * so don't let the parser generate one */
            if (!(actual->virtPortProfile
                  = virNetDevVPortProfileParse(virtPortNode,
                                               VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES |
                                               VIR_VPORT_XML_REQUIRE_TYPE))) {
                goto error;
            }
        } else {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("<virtualport> element unsupported for type='%s'"
                             " in interface's <actual> element"), type);
            goto error;
        }
    }

    if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
        xmlNodePtr sourceNode = virXPathNode("./source[1]", ctxt);

        if (sourceNode) {
            actual->data.direct.linkdev = virXMLPropString(sourceNode, "dev");

            mode = virXMLPropString(sourceNode, "mode");
            if (mode) {
                int m;
                if ((m = virNetDevMacVLanModeTypeFromString(mode)) < 0) {
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("Unknown mode '%s' in interface <actual> element"),
                                   mode);
                    goto error;
                }
                actual->data.direct.mode = m;
            }
        }
    } else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
        virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def;

        hostdev->parentnet = parent;
        hostdev->info = &parent->info;
        /* The helper function expects type to already be found and
         * passed in as a string, since it is in a different place in
         * NetDef vs HostdevDef.
         */
        addrtype = virXPathString("string(./source/address/@type)", ctxt);
        /* if not explicitly stated, source/vendor implies usb device */
        if (!addrtype && virXPathNode("./source/vendor", ctxt))
            addrtype = g_strdup("usb");
        hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
        if (virDomainHostdevDefParseXMLSubsys(node, ctxt, addrtype,
                                              hostdev, flags) < 0) {
            goto error;
        }
    } else if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
               actual->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
        g_autofree char *class_id = NULL;
        xmlNodePtr sourceNode;

        class_id = virXPathString("string(./class/@id)", ctxt);
        if (class_id &&
            virStrToLong_ui(class_id, NULL, 10, &actual->class_id) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unable to parse class id '%s'"),
                           class_id);
            goto error;
        }

        sourceNode = virXPathNode("./source", ctxt);
        if (sourceNode) {
            char *brname = virXMLPropString(sourceNode, "bridge");

            if (!brname && actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Missing <source> element with bridge name in "
                                 "interface's <actual> element"));
                goto error;
            }
            actual->data.bridge.brname = brname;
            macTableManager = virXMLPropString(sourceNode, "macTableManager");
            if (macTableManager &&
                (actual->data.bridge.macTableManager
                 = virNetworkBridgeMACTableManagerTypeFromString(macTableManager)) <= 0) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("Invalid macTableManager setting '%s' "
                                 "in domain interface's <actual> element"),
                               macTableManager);
                goto error;
            }
        }
    }

    bandwidth_node = virXPathNode("./bandwidth", ctxt);
    if (bandwidth_node &&
        virNetDevBandwidthParse(&actual->bandwidth,
                                NULL,
                                bandwidth_node,
                                actual->type == VIR_DOMAIN_NET_TYPE_NETWORK) < 0)
        goto error;

    vlanNode = virXPathNode("./vlan", ctxt);
    if (vlanNode && virNetDevVlanParse(vlanNode, ctxt, &actual->vlan) < 0)
        goto error;

    if (virNetworkPortOptionsParseXML(ctxt, &actual->isolatedPort) < 0)
        goto error;

    *def = g_steal_pointer(&actual);
    ret = 0;
 error:
    virDomainActualNetDefFree(actual);

    return ret;
}