virsh: Rework parseRateStr

The function is used to parse a tuple delimited by commas into
virNetDevBandwidth structure. So far only three out of fore
fields are supported: average, peak and burst. The single missing
field is floor. Well, the parsing works, but I think we can do
better. Especially when we will need to parse floor too in very
close future.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2015-08-01 08:13:54 +02:00
parent 5ee6d243fc
commit 6983d6d2c3

View File

@ -865,36 +865,58 @@ static const vshCmdOptDef opts_attach_interface[] = {
/* parse inbound and outbound which are in the format of /* parse inbound and outbound which are in the format of
* 'average,peak,burst', in which peak and burst are optional, * 'average,peak,burst', in which peak and burst are optional,
* thus 'average,,burst' and 'average,peak' are also legal. */ * thus 'average,,burst' and 'average,peak' are also legal. */
static int parseRateStr(const char *rateStr, virNetDevBandwidthRatePtr rate) static int parseRateStr(vshControl *ctl,
const char *rateStr,
virNetDevBandwidthRatePtr rate)
{ {
const char *average = NULL; char *token;
char *peak = NULL, *burst = NULL; char *next;
char *saveptr = NULL;
enum {
AVERAGE, PEAK, BURST
} state;
int ret = -1;
average = rateStr; if (!rateStr)
if (!average)
return -1;
if (virStrToLong_ull(average, &peak, 10, &rate->average) < 0)
return -1; return -1;
/* peak will be updated to point to the end of rateStr in case next = vshStrdup(ctl, rateStr);
* of 'average' */
if (peak && *peak != '\0') { for (state = AVERAGE; state <= BURST; state++) {
burst = strchr(peak + 1, ','); unsigned long long *tmp;
if (!(burst && (burst - peak == 1))) { const char *field_name;
if (virStrToLong_ull(peak + 1, &burst, 10, &rate->peak) < 0)
return -1; if (!(token = strtok_r(next, ",", &saveptr)))
break;
next = NULL;
switch (state) {
case AVERAGE:
tmp = &rate->average;
field_name = "average";
break;
case PEAK:
tmp = &rate->peak;
field_name = "peak";
break;
case BURST:
tmp = &rate->burst;
field_name = "burst";
break;
} }
/* burst will be updated to point to the end of rateStr in case if (virStrToLong_ullp(token, NULL, 10, tmp) < 0) {
* of 'average,peak' */ vshError(ctl, _("malformed %s field"), field_name);
if (burst && *burst != '\0') { goto cleanup;
if (virStrToLong_ull(burst + 1, NULL, 10, &rate->burst) < 0)
return -1;
} }
} }
ret = 0;
return 0; cleanup:
VIR_FREE(next);
return ret;
} }
static bool static bool
@ -952,10 +974,8 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
if (inboundStr) { if (inboundStr) {
memset(&inbound, 0, sizeof(inbound)); memset(&inbound, 0, sizeof(inbound));
if (parseRateStr(inboundStr, &inbound) < 0) { if (parseRateStr(ctl, inboundStr, &inbound) < 0)
vshError(ctl, _("inbound format is incorrect"));
goto cleanup; goto cleanup;
}
if (inbound.average == 0) { if (inbound.average == 0) {
vshError(ctl, _("inbound average is mandatory")); vshError(ctl, _("inbound average is mandatory"));
goto cleanup; goto cleanup;
@ -963,10 +983,8 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
} }
if (outboundStr) { if (outboundStr) {
memset(&outbound, 0, sizeof(outbound)); memset(&outbound, 0, sizeof(outbound));
if (parseRateStr(outboundStr, &outbound) < 0) { if (parseRateStr(ctl, outboundStr, &outbound) < 0)
vshError(ctl, _("outbound format is incorrect"));
goto cleanup; goto cleanup;
}
if (outbound.average == 0) { if (outbound.average == 0) {
vshError(ctl, _("outbound average is mandatory")); vshError(ctl, _("outbound average is mandatory"));
goto cleanup; goto cleanup;
@ -3280,10 +3298,8 @@ cmdDomIftune(vshControl *ctl, const vshCmd *cmd)
memset(&outbound, 0, sizeof(outbound)); memset(&outbound, 0, sizeof(outbound));
if (inboundStr) { if (inboundStr) {
if (parseRateStr(inboundStr, &inbound) < 0) { if (parseRateStr(ctl, inboundStr, &inbound) < 0)
vshError(ctl, _("inbound format is incorrect"));
goto cleanup; goto cleanup;
}
/* we parse the rate as unsigned long long, but the API /* we parse the rate as unsigned long long, but the API
* only accepts UINT */ * only accepts UINT */
if (inbound.average > UINT_MAX || inbound.peak > UINT_MAX || if (inbound.average > UINT_MAX || inbound.peak > UINT_MAX ||
@ -3316,10 +3332,8 @@ cmdDomIftune(vshControl *ctl, const vshCmd *cmd)
} }
if (outboundStr) { if (outboundStr) {
if (parseRateStr(outboundStr, &outbound) < 0) { if (parseRateStr(ctl, outboundStr, &outbound) < 0)
vshError(ctl, _("outbound format is incorrect"));
goto cleanup; goto cleanup;
}
if (outbound.average > UINT_MAX || outbound.peak > UINT_MAX || if (outbound.average > UINT_MAX || outbound.peak > UINT_MAX ||
outbound.burst > UINT_MAX) { outbound.burst > UINT_MAX) {
vshError(ctl, _("outbound rate larger than maximum %u"), vshError(ctl, _("outbound rate larger than maximum %u"),