static int
testVirNetDevBandwidthSet(const void *data)
{
    int ret = -1;
    const struct testSetStruct *info = data;
    const char *iface = info->iface;
    virNetDevBandwidthPtr band = NULL;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *actual_cmd = NULL;

    PARSE(info->band, band);

    if (!iface)
        iface = "eth0";

    virCommandSetDryRun(&buf, NULL, NULL);

    if (virNetDevBandwidthSet(iface, band, info->hierarchical_class) < 0)
        goto cleanup;

    if (!(actual_cmd = virBufferContentAndReset(&buf))) {
        int err = virBufferError(&buf);
        if (err) {
            fprintf(stderr, "buffer's in error state: %d", err);
            goto cleanup;
        }
        /* This is interesting, no command has been executed.
         * Maybe that's expected, actually. */
    }

    if (STRNEQ_NULLABLE(info->exp_cmd, actual_cmd)) {
        virTestDifference(stderr,
                          NULLSTR(info->exp_cmd),
                          NULLSTR(actual_cmd));
        goto cleanup;
    }

    ret = 0;
cleanup:
    virCommandSetDryRun(NULL, NULL, NULL);
    virNetDevBandwidthFree(band);
    virBufferFreeAndReset(&buf);
    VIR_FREE(actual_cmd);
    return ret;
}
Exemple #2
0
/*
 * virNetDevBandwidthCopy:
 * @dest: destination
 * @src:  source (may be NULL)
 *
 * Returns -1 on OOM error (which gets reported),
 * 0 otherwise.
 */
int
virNetDevBandwidthCopy(virNetDevBandwidthPtr *dest,
                       const virNetDevBandwidthPtr src)
{
    int ret = -1;

    *dest = NULL;
    if (!src) {
        /* nothing to be copied */
        return 0;
    }

    if (VIR_ALLOC(*dest) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    if (src->in) {
        if (VIR_ALLOC((*dest)->in) < 0) {
            virReportOOMError();
            goto cleanup;
        }
        memcpy((*dest)->in, src->in, sizeof(*src->in));
    }

    if (src->out) {
        if (VIR_ALLOC((*dest)->out) < 0) {
            virReportOOMError();
            VIR_FREE((*dest)->in);
            goto cleanup;
        }
        memcpy((*dest)->out, src->out, sizeof(*src->out));
    }

    ret = 0;

cleanup:
    if (ret < 0) {
        virNetDevBandwidthFree(*dest);
        *dest = NULL;
    }
    return ret;
}
/**
 * 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;
}
/**
 * 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;
}