提交 90074ecf 编写于 作者: M Michal Privoznik 提交者: Daniel Veillard

bandwidth: Implement functions to enable and disable QoS

These function executes 'tc' with appropriate arguments to set
desired QoS setting on interface or bridge during its creation.
上级 aaa98b08
......@@ -170,6 +170,8 @@ AC_PATH_PROG([RADVD], [radvd], [radvd],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_PATH_PROG([BRCTL], [brctl], [brctl],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_PATH_PROG([TC], [tc], [tc],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_PATH_PROG([UDEVADM], [udevadm], [],
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
AC_PATH_PROG([UDEVSETTLE], [udevsettle], [],
......@@ -183,6 +185,8 @@ AC_DEFINE_UNQUOTED([RADVD],["$RADVD"],
[Location or name of the radvd program])
AC_DEFINE_UNQUOTED([BRCTL],["$BRCTL"],
[Location or name of the brctl program (see bridge-utils)])
AC_DEFINE_UNQUOTED([TC],["$TC"],
[Location or name of the tc profram (see iproute2)])
if test -n "$UDEVADM"; then
AC_DEFINE_UNQUOTED([UDEVADM],["$UDEVADM"],
[Location or name of the udevadm program])
......
......@@ -250,7 +250,7 @@ Requires: %{name}-client = %{version}-%{release}
Requires: bridge-utils
# for modprobe of pci devices
Requires: module-init-tools
# for /sbin/ip
# for /sbin/ip & /sbin/tc
Requires: iproute
%endif
%if %{with_network}
......
......@@ -713,6 +713,8 @@ nlComm;
virBandwidthDefFormat;
virBandwidthDefFree;
virBandwidthDefParseNode;
virBandwidthDisable;
virBandwidthEnable;
virSocketAddrBroadcast;
virSocketAddrBroadcastByPrefix;
virSocketAddrIsNetmask;
......
......@@ -1822,10 +1822,23 @@ networkStartNetworkVirtual(struct network_driver *driver,
if (v6present && networkStartRadvd(network) < 0)
goto err4;
if (virBandwidthEnable(network->def->bandwidth, network->def->bridge) < 0) {
networkReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
network->def->bridge);
goto err5;
}
VIR_FREE(macTapIfName);
return 0;
err5:
if (virBandwidthDisable(network->def->bridge, true) < 0) {
VIR_WARN("Failed to disable QoS on %s",
network->def->bridge);
}
err4:
if (!save_err)
save_err = virSaveLastError();
......@@ -1883,6 +1896,11 @@ static int networkShutdownNetworkVirtual(struct network_driver *driver,
int err;
char ebuf[1024];
if (virBandwidthDisable(network->def->bridge, true) < 0) {
VIR_WARN("Failed to disable QoS on %s",
network->def->name);
}
if (network->radvdPid > 0) {
char *radvdpidbase;
......
......@@ -132,7 +132,7 @@ qemuPhysIfaceConnect(virDomainDefPtr def,
vnet_hdr, def->uuid,
virDomainNetGetActualDirectVirtPortProfile(net),
&res_ifname,
vmop, driver->stateDir);
vmop, driver->stateDir, net->bandwidth);
if (rc >= 0) {
virDomainAuditNetDevice(def, net, res_ifname, true);
VIR_FREE(net->ifname);
......@@ -298,6 +298,15 @@ qemuNetworkIfaceConnect(virDomainDefPtr def,
}
}
if (tapfd >= 0 &&
virBandwidthEnable(net->bandwidth, net->ifname) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
net->ifname);
VIR_FORCE_CLOSE(tapfd);
goto cleanup;
}
if (tapfd >= 0) {
if ((net->filter) && (net->ifname)) {
err = virDomainConfNWFilterInstantiate(conn, net);
......
......@@ -267,7 +267,8 @@ openMacvtapTap(const char *tgifname,
virVirtualPortProfileParamsPtr virtPortProfile,
char **res_ifname,
enum virVMOperationType vmOp,
char *stateDir)
char *stateDir,
virBandwidthPtr bandwidth)
{
const char *type = "macvtap";
int c, rc;
......@@ -361,6 +362,15 @@ create_name:
} else
goto disassociate_exit;
if (virBandwidthEnable(bandwidth, cr_ifname) < 0) {
macvtapError(VIR_ERR_INTERNAL_ERROR,
_("cannot set bandwidth limits on %s"),
cr_ifname);
rc = -1;
goto disassociate_exit;
}
return rc;
disassociate_exit:
......
......@@ -62,7 +62,8 @@ int openMacvtapTap(const char *ifname,
virVirtualPortProfileParamsPtr virtPortProfile,
char **res_ifname,
enum virVMOperationType vmop,
char *stateDir);
char *stateDir,
virBandwidthPtr bandwidth);
void delMacvtap(const char *ifname,
const unsigned char *macaddress,
......
......@@ -16,6 +16,7 @@
#include "network.h"
#include "util.h"
#include "virterror_internal.h"
#include "command.h"
#define VIR_FROM_THIS VIR_FROM_NONE
#define virSocketError(code, ...) \
......@@ -1102,3 +1103,163 @@ virBandwidthDefFormat(virBufferPtr buf,
cleanup:
return ret;
}
/**
* virBandwidthEnable:
* @bandwidth: rates to set
* @iface: on which interface
*
* This function enables QoS on specified interface
* and set given traffic limits for both, incoming
* and outgoing traffic. Any previous setting get
* overwritten.
*
* Return 0 on success, -1 otherwise.
*/
int
virBandwidthEnable(virBandwidthPtr bandwidth,
const char *iface)
{
int ret = -1;
virCommandPtr cmd = NULL;
char *average = NULL;
char *peak = NULL;
char *burst = NULL;
if (!iface)
return -1;
if (!bandwidth) {
/* nothing to be enabled */
ret = 0;
goto cleanup;
}
if (virBandwidthDisable(iface, true) < 0)
goto cleanup;
if (bandwidth->in) {
if (virAsprintf(&average, "%llukbps", bandwidth->in->average) < 0)
goto cleanup;
if (bandwidth->in->peak &&
(virAsprintf(&peak, "%llukbps", bandwidth->in->peak) < 0))
goto cleanup;
if (bandwidth->in->burst &&
(virAsprintf(&burst, "%llukb", bandwidth->in->burst) < 0))
goto cleanup;
cmd = virCommandNew(TC);
virCommandAddArgList(cmd, "qdisc", "add", "dev", iface, "root",
"handle", "1:", "htb", "default", "1", NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
virCommandFree(cmd);
cmd = virCommandNew(TC);
virCommandAddArgList(cmd,"class", "add", "dev", iface, "parent",
"1:", "classid", "1:1", "htb", NULL);
virCommandAddArgList(cmd, "rate", average, NULL);
if (peak)
virCommandAddArgList(cmd, "ceil", peak, NULL);
if (burst)
virCommandAddArgList(cmd, "burst", burst, NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
virCommandFree(cmd);
cmd = virCommandNew(TC);
virCommandAddArgList(cmd,"filter", "add", "dev", iface, "parent",
"1:0", "protocol", "ip", "handle", "1", "fw",
"flowid", "1", NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
VIR_FREE(average);
VIR_FREE(peak);
VIR_FREE(burst);
}
if (bandwidth->out) {
if (virAsprintf(&average, "%llukbps", bandwidth->out->average) < 0)
goto cleanup;
if (virAsprintf(&burst, "%llukb", bandwidth->out->burst ?
bandwidth->out->burst : bandwidth->out->average) < 0)
goto cleanup;
virCommandFree(cmd);
cmd = virCommandNew(TC);
virCommandAddArgList(cmd, "qdisc", "add", "dev", iface,
"ingress", NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
virCommandFree(cmd);
cmd = virCommandNew(TC);
virCommandAddArgList(cmd, "filter", "add", "dev", iface, "parent",
"ffff:", "protocol", "ip", "u32", "match", "ip",
"src", "0.0.0.0/0", "police", "rate", average,
"burst", burst, "mtu", burst, "drop", "flowid",
":1", NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
}
ret = 0;
cleanup:
virCommandFree(cmd);
VIR_FREE(average);
VIR_FREE(peak);
VIR_FREE(burst);
return ret;
}
/**
* virBandwidthDisable:
* @iface: on which interface
* @may_fail: should be unsuccessful disable considered fatal?
*
* This function tries to disable QoS on specified interface
* by deleting root and ingress qdisc. However, this may fail
* if we try to remove the default one.
*
* Return 0 on success, -1 otherwise.
*/
int
virBandwidthDisable(const char *iface,
bool may_fail)
{
int ret = -1;
int status;
virCommandPtr cmd = NULL;
if (!iface)
return -1;
cmd = virCommandNew(TC);
virCommandAddArgList(cmd, "qdisc", "del", "dev", iface, "root", NULL);
if ((virCommandRun(cmd, &status) < 0) ||
(!may_fail && status))
goto cleanup;
virCommandFree(cmd);
cmd = virCommandNew(TC);
virCommandAddArgList(cmd, "qdisc", "del", "dev", iface, "ingress", NULL);
if ((virCommandRun(cmd, &status) < 0) ||
(!may_fail && status))
goto cleanup;
ret = 0;
cleanup:
virCommandFree(cmd);
return ret;
}
......@@ -155,4 +155,7 @@ void virBandwidthDefFree(virBandwidthPtr def);
int virBandwidthDefFormat(virBufferPtr buf,
virBandwidthPtr def,
const char *indent);
int virBandwidthEnable(virBandwidthPtr bandwidth, const char *iface);
int virBandwidthDisable(const char *iface, bool may_fail);
#endif /* __VIR_NETWORK_H__ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册