/**
 * virNetDevBandwidthParse:
 * @bandwidth: parsed bandwidth
 * @node: XML node
 * @allowFloor: whether "floor" setting is supported
 *
 * Parse bandwidth XML and return pointer to structure.
 * The @allowFloor attribute indicates whether the caller
 * is able to support use of the "floor" setting.
 *
 * Returns !NULL on success, NULL on error.
 */
int
virNetDevBandwidthParse(virNetDevBandwidthPtr *bandwidth,
                        xmlNodePtr node,
                        bool allowFloor)
{
    int ret = -1;
    virNetDevBandwidthPtr def = NULL;
    xmlNodePtr cur;
    xmlNodePtr in = NULL, out = NULL;

    if (VIR_ALLOC(def) < 0)
        return ret;

    if (!node || !virXMLNodeNameEqual(node, "bandwidth")) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("invalid argument supplied"));
        goto cleanup;
    }

    cur = node->children;

    while (cur) {
        if (cur->type == XML_ELEMENT_NODE) {
            if (virXMLNodeNameEqual(cur, "inbound")) {
                if (in) {
                    virReportError(VIR_ERR_XML_DETAIL, "%s",
                                   _("Only one child <inbound> "
                                     "element allowed"));
                    goto cleanup;
                }
                in = cur;
            } else if (virXMLNodeNameEqual(cur, "outbound")) {
                if (out) {
                    virReportError(VIR_ERR_XML_DETAIL, "%s",
                                   _("Only one child <outbound> "
                                     "element allowed"));
                    goto cleanup;
                }
                out = cur;
            }
            /* Silently ignore unknown elements */
        }
        cur = cur->next;
    }

    if (in) {
        if (VIR_ALLOC(def->in) < 0)
            goto cleanup;

        if (virNetDevBandwidthParseRate(in, def->in) < 0) {
            /* helper reported error for us */
            goto cleanup;
        }

        if (def->in->floor && !allowFloor) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("floor attribute is not supported for this config"));
            goto cleanup;
        }
    }

    if (out) {
        if (VIR_ALLOC(def->out) < 0)
            goto cleanup;

        if (virNetDevBandwidthParseRate(out, def->out) < 0) {
            /* helper reported error for us */
            goto cleanup;
        }

        if (def->out->floor) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("'floor' attribute allowed "
                             "only in <inbound> element"));
            goto cleanup;
        }
    }

    if (!def->in && !def->out)
        VIR_FREE(def);

    *bandwidth = def;
    def = NULL;
    ret = 0;

 cleanup:
    virNetDevBandwidthFree(def);
    return ret;
}
Beispiel #2
0
/**
 * virNetDevBandwidthParse:
 * @node: XML node
 * @net_type: one of virDomainNetType
 *
 * Parse bandwidth XML and return pointer to structure.
 * @net_type tell to which type will/is interface connected to.
 * Pass -1 if this is not called on interface.
 *
 * Returns !NULL on success, NULL on error.
 */
virNetDevBandwidthPtr
virNetDevBandwidthParse(xmlNodePtr node,
                        int net_type)
{
    virNetDevBandwidthPtr def = NULL;
    xmlNodePtr cur;
    xmlNodePtr in = NULL, out = NULL;

    if (VIR_ALLOC(def) < 0)
        return NULL;

    if (!node || !xmlStrEqual(node->name, BAD_CAST "bandwidth")) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("invalid argument supplied"));
        goto error;
    }

    cur = node->children;

    while (cur) {
        if (cur->type == XML_ELEMENT_NODE) {
            if (xmlStrEqual(cur->name, BAD_CAST "inbound")) {
                if (in) {
                    virReportError(VIR_ERR_XML_DETAIL, "%s",
                                   _("Only one child <inbound> "
                                     "element allowed"));
                    goto error;
                }
                in = cur;
            } else if (xmlStrEqual(cur->name, BAD_CAST "outbound")) {
                if (out) {
                    virReportError(VIR_ERR_XML_DETAIL, "%s",
                                   _("Only one child <outbound> "
                                     "element allowed"));
                    goto error;
                }
                out = cur;
            }
            /* Silently ignore unknown elements */
        }
        cur = cur->next;
    }

    if (in) {
        if (VIR_ALLOC(def->in) < 0)
            goto error;

        if (virNetDevBandwidthParseRate(in, def->in) < 0) {
            /* helper reported error for us */
            goto error;
        }

        if (def->in->floor && net_type != VIR_DOMAIN_NET_TYPE_NETWORK) {
            if (net_type == -1) {
                /* 'floor' on network isn't supported */
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("floor attribute isn't supported for "
                                 "network's bandwidth yet"));
            } else {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                               _("floor attribute is supported only for "
                                 "interfaces of type network"));
            }
            goto error;
        }
    }

    if (out) {
        if (VIR_ALLOC(def->out) < 0)
            goto error;

        if (virNetDevBandwidthParseRate(out, def->out) < 0) {
            /* helper reported error for us */
            goto error;
        }

        if (def->out->floor) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("'floor' attribute allowed "
                             "only in <inbound> element"));
            goto error;
        }
    }

    return def;

 error:
    virNetDevBandwidthFree(def);
    return NULL;
}