mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-22 22:13:18 +00:00
support setting bandwidth from virsh attach-interface
Adds two options, inbound and outbound, to attach-interface to set bandwidth when attaching interfaces
This commit is contained in:
parent
80710c69fe
commit
7b2723c5c1
@ -59,6 +59,7 @@
|
|||||||
#include "threads.h"
|
#include "threads.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "virkeycode.h"
|
#include "virkeycode.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
static char *progname;
|
static char *progname;
|
||||||
|
|
||||||
@ -11228,15 +11229,54 @@ static const vshCmdOptDef opts_attach_interface[] = {
|
|||||||
{"script", VSH_OT_DATA, 0, N_("script used to bridge network interface")},
|
{"script", VSH_OT_DATA, 0, N_("script used to bridge network interface")},
|
||||||
{"model", VSH_OT_DATA, 0, N_("model type")},
|
{"model", VSH_OT_DATA, 0, N_("model type")},
|
||||||
{"persistent", VSH_OT_BOOL, 0, N_("persist interface attachment")},
|
{"persistent", VSH_OT_BOOL, 0, N_("persist interface attachment")},
|
||||||
|
{"inbound", VSH_OT_DATA, VSH_OFLAG_NONE, N_("control domain's incoming traffics")},
|
||||||
|
{"outbound", VSH_OT_DATA, VSH_OFLAG_NONE, N_("control domain's outgoing traffics")},
|
||||||
{NULL, 0, 0, NULL}
|
{NULL, 0, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* parse inbound and outbound which are in the format of
|
||||||
|
* 'average,peak,burst', in which peak and burst are optional,
|
||||||
|
* thus 'average,,burst' and 'average,peak' are also legal. */
|
||||||
|
static int parseRateStr(const char *rateStr, virRatePtr rate)
|
||||||
|
{
|
||||||
|
const char *average = NULL;
|
||||||
|
char *peak = NULL, *burst = NULL;
|
||||||
|
|
||||||
|
average = rateStr;
|
||||||
|
if (!average)
|
||||||
|
return -1;
|
||||||
|
if (virStrToLong_ull(average, &peak, 10, &rate->average) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* peak will be updated to point to the end of rateStr in case
|
||||||
|
* of 'average' */
|
||||||
|
if (peak && *peak != '\0') {
|
||||||
|
burst = strchr(peak + 1, ',');
|
||||||
|
if (!(burst && (burst - peak == 1))) {
|
||||||
|
if (virStrToLong_ull(peak + 1, &burst, 10, &rate->peak) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* burst will be updated to point to the end of rateStr in case
|
||||||
|
* of 'average,peak' */
|
||||||
|
if (burst && *burst != '\0') {
|
||||||
|
if (virStrToLong_ull(burst + 1, NULL, 10, &rate->burst) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
|
cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
|
||||||
{
|
{
|
||||||
virDomainPtr dom = NULL;
|
virDomainPtr dom = NULL;
|
||||||
const char *mac = NULL, *target = NULL, *script = NULL,
|
const char *mac = NULL, *target = NULL, *script = NULL,
|
||||||
*type = NULL, *source = NULL, *model = NULL;
|
*type = NULL, *source = NULL, *model = NULL,
|
||||||
|
*inboundStr = NULL, *outboundStr = NULL;
|
||||||
|
virRate inbound, outbound;
|
||||||
int typ;
|
int typ;
|
||||||
int ret;
|
int ret;
|
||||||
bool functionReturn = false;
|
bool functionReturn = false;
|
||||||
@ -11257,7 +11297,9 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
|
|||||||
vshCommandOptString(cmd, "target", &target) < 0 ||
|
vshCommandOptString(cmd, "target", &target) < 0 ||
|
||||||
vshCommandOptString(cmd, "mac", &mac) < 0 ||
|
vshCommandOptString(cmd, "mac", &mac) < 0 ||
|
||||||
vshCommandOptString(cmd, "script", &script) < 0 ||
|
vshCommandOptString(cmd, "script", &script) < 0 ||
|
||||||
vshCommandOptString(cmd, "model", &model) < 0) {
|
vshCommandOptString(cmd, "model", &model) < 0 ||
|
||||||
|
vshCommandOptString(cmd, "inbound", &inboundStr) < 0 ||
|
||||||
|
vshCommandOptString(cmd, "outbound", &outboundStr) < 0) {
|
||||||
vshError(ctl, "missing argument");
|
vshError(ctl, "missing argument");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -11273,6 +11315,29 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inboundStr) {
|
||||||
|
memset(&inbound, 0, sizeof(inbound));
|
||||||
|
if (parseRateStr(inboundStr, &inbound) < 0) {
|
||||||
|
vshError(ctl, _("inbound format is incorrect"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (inbound.average == 0) {
|
||||||
|
vshError(ctl, _("inbound average is mandatory"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outboundStr) {
|
||||||
|
memset(&outbound, 0, sizeof(outbound));
|
||||||
|
if (parseRateStr(outboundStr, &outbound) < 0) {
|
||||||
|
vshError(ctl, _("outbound format is incorrect"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (outbound.average == 0) {
|
||||||
|
vshError(ctl, _("outbound average is mandatory"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Make XML of interface */
|
/* Make XML of interface */
|
||||||
virBufferAsprintf(&buf, "<interface type='%s'>\n", type);
|
virBufferAsprintf(&buf, "<interface type='%s'>\n", type);
|
||||||
|
|
||||||
@ -11290,6 +11355,27 @@ cmdAttachInterface(vshControl *ctl, const vshCmd *cmd)
|
|||||||
if (model != NULL)
|
if (model != NULL)
|
||||||
virBufferAsprintf(&buf, " <model type='%s'/>\n", model);
|
virBufferAsprintf(&buf, " <model type='%s'/>\n", model);
|
||||||
|
|
||||||
|
if (inboundStr || outboundStr) {
|
||||||
|
virBufferAsprintf(&buf, " <bandwidth>\n");
|
||||||
|
if (inboundStr && inbound.average > 0) {
|
||||||
|
virBufferAsprintf(&buf, " <inbound average='%llu'", inbound.average);
|
||||||
|
if (inbound.peak > 0)
|
||||||
|
virBufferAsprintf(&buf, " peak='%llu'", inbound.peak);
|
||||||
|
if (inbound.burst > 0)
|
||||||
|
virBufferAsprintf(&buf, " burst='%llu'", inbound.burst);
|
||||||
|
virBufferAsprintf(&buf, "/>\n");
|
||||||
|
}
|
||||||
|
if (outboundStr && outbound.average > 0) {
|
||||||
|
virBufferAsprintf(&buf, " <outbound average='%llu'", outbound.average);
|
||||||
|
if (outbound.peak > 0)
|
||||||
|
virBufferAsprintf(&buf, " peak='%llu'", outbound.peak);
|
||||||
|
if (outbound.burst > 0)
|
||||||
|
virBufferAsprintf(&buf, " burst='%llu'", outbound.burst);
|
||||||
|
virBufferAsprintf(&buf, "/>\n");
|
||||||
|
}
|
||||||
|
virBufferAsprintf(&buf, " </bandwidth>\n");
|
||||||
|
}
|
||||||
|
|
||||||
virBufferAddLit(&buf, "</interface>\n");
|
virBufferAddLit(&buf, "</interface>\n");
|
||||||
|
|
||||||
if (virBufferError(&buf)) {
|
if (virBufferError(&buf)) {
|
||||||
|
@ -1237,7 +1237,7 @@ scsi:controller.bus.unit or ide:controller.bus.unit.
|
|||||||
|
|
||||||
=item B<attach-interface> I<domain-id> I<type> I<source>
|
=item B<attach-interface> I<domain-id> I<type> I<source>
|
||||||
[I<--target target>] [I<--mac mac>] [I<--script script>] [I<--model model>]
|
[I<--target target>] [I<--mac mac>] [I<--script script>] [I<--model model>]
|
||||||
[I<--persistent>]
|
[I<--persistent>] [I<--inbound average,peak,burst>] [I<--outbound average,peak,burst>]
|
||||||
|
|
||||||
Attach a new network interface to the domain.
|
Attach a new network interface to the domain.
|
||||||
I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device.
|
I<type> can be either I<network> to indicate a physical network device or I<bridge> to indicate a bridge to a device.
|
||||||
@ -1248,6 +1248,9 @@ I<script> allows to specify a path to a script handling a bridge instead of
|
|||||||
the default one.
|
the default one.
|
||||||
I<model> allows to specify the model type.
|
I<model> allows to specify the model type.
|
||||||
I<persistent> indicates the changes will affect the next boot of the domain.
|
I<persistent> indicates the changes will affect the next boot of the domain.
|
||||||
|
I<inbound> and I<outbound> control the bandwidth of the interface. I<peak>
|
||||||
|
and I<burst> are optional, so "average,peak", "average,,burst" and
|
||||||
|
"average" are also legal.
|
||||||
|
|
||||||
B<Note>: the optional target value is the name of a device to be created
|
B<Note>: the optional target value is the name of a device to be created
|
||||||
as the back-end on the node. If not provided a device named "vnetN" or "vifN"
|
as the back-end on the node. If not provided a device named "vnetN" or "vifN"
|
||||||
|
Loading…
Reference in New Issue
Block a user