---
daemon/remote.c | 132 ++++++++++++++++++++++++++++++++++++++++++
src/remote/remote_driver.c | 64 ++++++++++++++++++++
src/remote/remote_protocol.x | 32 ++++++++++-
src/rpc/gendispatch.pl | 30 ++++++++++
4 files changed, 257 insertions(+), 1 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 9e6cf77..c83a8fa 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -100,6 +100,17 @@ remoteDeserializeTypedParameters(remote_typed_param
*args_params_val,
u_int args_params_len,
int limit,
int *nparams);
+static int
+remoteSerializeVcpuBandwidth(virDomainVcpuBWDefPtr vcpubw,
+ int nvcpubw,
+ remote_vcpu_bandwidth **args_vcpubw_val,
+ u_int *args_vcpubw_len);
+static virDomainVcpuBWDefPtr
+remoteDeserializeVcpuBandwidth(remote_vcpu_bandwidth *ret_vcpubw_val,
+ u_int ret_vcpubw_len,
+ int limit,
+ int *nvcpubw);
+
#include "remote_dispatch.h"
#include "qemu_dispatch.h"
@@ -2857,6 +2868,127 @@ cleanup:
}
+/* Helper to serialize vcpu bandwidth. */
+static int remoteSerializeVcpuBandwidth(virDomainVcpuBWDefPtr vcpubw,
+ int nvcpubw,
+ remote_vcpu_bandwidth **ret_vcpubw_val,
+ u_int *ret_vcpubw_len)
+{
+ int i;
+ int rv = -1;
+ remote_vcpu_bandwidth *val;
+
+ if (VIR_ALLOC_N(val, nvcpubw) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ for (i = 0; i < nvcpubw; i++) {
+ val[i].vcpuid = vcpubw[i].vcpuid;
+ val[i].period = vcpubw[i].period;
+ val[i].quota = vcpubw[i].quota;
+ }
+
+ *ret_vcpubw_val = val;
+ *ret_vcpubw_len = nvcpubw;
+ val = NULL;
+ rv = 0;
+
+cleanup:
+ VIR_FREE(val);
+ return rv;
+}
+
+
+/* Helper to deserialize vcpu bandwidth. */
+static virDomainVcpuBWDefPtr
+remoteDeserializeVcpuBandwidth(remote_vcpu_bandwidth *args_vcpubw_val,
+ u_int args_vcpubw_len,
+ int limit,
+ int *nvcpubw)
+{
+ int i;
+ virDomainVcpuBWDefPtr vcpubw = NULL;
+
+ /* Check the length of the returned list carefully. */
+ if (args_vcpubw_len > limit) {
+ virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("returned number of vcpubw exceeds limit"));
+ goto cleanup;
+ }
+ if (VIR_ALLOC_N(vcpubw, args_vcpubw_len) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ /* Deserialise the result. */
+ for (i = 0; i < args_vcpubw_len; i++) {
+ vcpubw[i].vcpuid = args_vcpubw_val[i].vcpuid;
+ vcpubw[i].period = args_vcpubw_val[i].period;
+ vcpubw[i].quota = args_vcpubw_val[i].quota;
+ }
+
+ *nvcpubw = args_vcpubw_len;
+
+cleanup:
+ return vcpubw;
+}
+
+
+static int
+remoteDispatchDomainGetVcpuBW(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client ATTRIBUTE_UNUSED,
+ virNetMessageHeaderPtr hdr ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ remote_domain_get_vcpu_b_w_args *args,
+ remote_domain_get_vcpu_b_w_ret *ret)
+{
+ virDomainPtr dom = NULL;
+ virDomainVcpuBWDefPtr vcpubw = NULL;
+ int nvcpubw = args->nvcpubw_list;
+ int rv = -1;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not
open"));
+ goto cleanup;
+ }
+
+ if (nvcpubw > REMOTE_DOMAIN_VCPU_MAX) {
+ virNetError(VIR_ERR_INTERNAL_ERROR, "%s", _("nvcpubw too
large"));
+ goto cleanup;
+ }
+ if (VIR_ALLOC_N(vcpubw, nvcpubw) < 0)
+ goto no_memory;
+
+ if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+ goto cleanup;
+
+ if (virDomainGetVcpuBW(dom, vcpubw, &nvcpubw, args->flags) < 0)
+ goto cleanup;
+
+ if (remoteSerializeVcpuBandwidth(vcpubw, nvcpubw,
+ &ret->vcpubw_list.vcpubw_list_val,
+ &ret->vcpubw_list.vcpubw_list_len) < 0)
+ goto cleanup;
+
+ rv = 0;
+
+cleanup:
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ if (dom)
+ virDomainFree(dom);
+ VIR_FREE(vcpubw);
+ return rv;
+
+no_memory:
+ virReportOOMError();
+ goto cleanup;
+}
+
+
/*----- Helpers. -----*/
/* get_nonnull_domain and get_nonnull_network turn an on-wire
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 0e68bc5..fe3a4ab 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1317,6 +1317,68 @@ cleanup:
return rv;
}
+/* Helper to serialize vcpu bandwidth. */
+static int remoteSerializeVcpuBandwidth(virDomainVcpuBWDefPtr vcpubw,
+ int nvcpubw,
+ remote_vcpu_bandwidth **args_vcpubw_val,
+ u_int *args_vcpubw_len)
+{
+ int i;
+ int rv = -1;
+ remote_vcpu_bandwidth *val;
+
+ if (VIR_ALLOC_N(val, nvcpubw) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ for (i = 0; i < nvcpubw; i++) {
+ val[i].vcpuid = vcpubw[i].vcpuid;
+ val[i].period = vcpubw[i].period;
+ val[i].quota = vcpubw[i].quota;
+ }
+
+ *args_vcpubw_val = val;
+ *args_vcpubw_len = nvcpubw;
+ val = NULL;
+ rv = 0;
+
+cleanup:
+ VIR_FREE(val);
+ return rv;
+}
+
+/* Helper to deserialize vcpu bandwidth. */
+static int remoteDeserializeVcpuBandwidth(remote_vcpu_bandwidth *ret_vcpubw_val,
+ u_int ret_vcpubw_len,
+ int limit,
+ virDomainVcpuBWDefPtr vcpubw,
+ int *nvcpubw)
+{
+ int i;
+ int rv = -1;
+
+ /* Check the length of the returned list carefully. */
+ if (ret_vcpubw_len > limit || ret_vcpubw_len > *nvcpubw) {
+ remoteError(VIR_ERR_RPC, "%s",
+ _("returned number of vcpubw exceeds limit"));
+ goto cleanup;
+ }
+
+ /* Deserialise the result. */
+ for (i = 0; i < ret_vcpubw_len; i++) {
+ vcpubw[i].vcpuid = ret_vcpubw_val[i].vcpuid;
+ vcpubw[i].period = ret_vcpubw_val[i].period;
+ vcpubw[i].quota = ret_vcpubw_val[i].quota;
+ }
+
+ rv = 0;
+ *nvcpubw = ret_vcpubw_len;
+
+cleanup:
+ return rv;
+}
+
static int
remoteDomainGetMemoryParameters (virDomainPtr domain,
virTypedParameterPtr params, int *nparams,
@@ -4234,6 +4296,8 @@ static virDriver remote_driver = {
.domainMigrateFinish3 = remoteDomainMigrateFinish3, /* 0.9.2 */
.domainMigrateConfirm3 = remoteDomainMigrateConfirm3, /* 0.9.2 */
.domainSendKey = remoteDomainSendKey, /* 0.9.3 */
+ .domainGetVcpuBW = remoteDomainGetVcpuBW, /* 0.9.4 */
+ .domainSetVcpuBW = remoteDomainSetVcpuBW, /* 0.9.4 */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 7c3539c..3771ed1 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -193,6 +193,11 @@ const REMOTE_CPU_BASELINE_MAX = 256;
*/
const REMOTE_DOMAIN_SEND_KEY_MAX = 16;
+/*
+ * Max number of vcpu
+ */
+const REMOTE_DOMAIN_VCPU_MAX = 4096;
+
/* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
@@ -331,6 +336,12 @@ struct remote_node_get_memory_stats {
unsigned hyper value;
};
+struct remote_vcpu_bandwidth {
+ int vcpuid;
+ uint64_t period;
+ int64_t quota;
+};
+
/*----- Calls. -----*/
/* For each call we may have a 'remote_CALL_args' and 'remote_CALL_ret'
@@ -2115,6 +2126,22 @@ struct remote_domain_get_control_info_ret { /* insert@1 */
unsigned hyper stateTime;
};
+struct remote_domain_get_vcpu_b_w_args {
+ remote_nonnull_domain dom;
+ int nvcpubw_list; /* call-by-reference */
+ unsigned int flags;
+};
+
+struct remote_domain_get_vcpu_b_w_ret {
+ remote_vcpu_bandwidth vcpubw_list<REMOTE_DOMAIN_VCPU_MAX>; /* insert@1 */
+};
+
+struct remote_domain_set_vcpu_b_w_args {
+ remote_nonnull_domain dom;
+ remote_vcpu_bandwidth vcpubw_list<REMOTE_DOMAIN_VCPU_MAX>;
+ unsigned int flags;
+};
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -2383,7 +2410,10 @@ enum remote_procedure {
REMOTE_PROC_NODE_GET_CPU_STATS = 227, /* skipgen skipgen */
REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /* skipgen skipgen */
REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /* autogen autogen */
- REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230 /* skipgen skipgen */
+ REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230, /* skipgen skipgen */
+
+ REMOTE_PROC_DOMAIN_GET_VCPU_B_W = 231, /* skipgen autogen */
+ REMOTE_PROC_DOMAIN_SET_VCPU_B_W = 232 /* autogen autogen */
/*
* Notice how the entries are grouped in sets of 10 ?
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
index 027560c..7ea1c52 100755
--- a/src/rpc/gendispatch.pl
+++ b/src/rpc/gendispatch.pl
@@ -423,6 +423,17 @@ elsif ($opt_b) {
"
&n$1)) == NULL)\n" .
" goto cleanup;\n");
push(@free_list, " VIR_FREE(params);");
+ } elsif ($args_member =~ m/^remote_vcpu_bandwidth (\S+)<(\S+)>;/)
{
+ push(@vars_list, "virDomainVcpuBWDefPtr $1 = NULL");
+ push(@vars_list, "int n$1");
+ push(@args_list, "$1");
+ push(@args_list, "n$1");
+ push(@getters_list, " if (($1 =
remoteDeserializeVcpuBandwidth(args->$1.$1_val,\n" .
+ "
args->$1.$1_len,\n" .
+ "
$2,\n" .
+ "
&n$1)) == NULL)\n" .
+ " goto cleanup;\n");
+ push(@free_list, " VIR_FREE(vcpubw_list);");
} elsif ($args_member =~ m/<\S+>;/ or $args_member =~ m/\[\S+\];/)
{
# just make all other array types fail
die "unhandled type for argument value: $args_member";
@@ -1099,6 +1110,13 @@ elsif ($opt_k) {
"
xdr_free((xdrproc_t)xdr_$call->{args}, (char *)&args);\n" .
" goto done;\n" .
" }");
+ } elsif ($args_member =~ m/^remote_vcpu_bandwidth (\S+)<(\S+)>;/)
{
+ push(@args_list, "virDomainVcpuBWDefPtr $1");
+ push(@args_list, "int n$1");
+ push(@setters_list2, "if (remoteSerializeVcpuBandwidth($1, n$1,
&args.$1.$1_val, &args.$1.$1_len) < 0) {\n" .
+ "
xdr_free((xdrproc_t)xdr_$call->{args}, (char *)&args);\n" .
+ " goto done;\n" .
+ " }");
} elsif ($args_member =~ m/^((?:unsigned )?int)
(\S+);\s*\/\*\s*call-by-reference\s*\*\//) {
my $type_name = "$1 *";
my $arg_name = $2;
@@ -1264,6 +1282,18 @@ elsif ($opt_k) {
} elsif ($ret_member =~ m/^remote_typed_param (\S+)<\S+>;/) {
# error out on unannotated arrays
die "remote_typed_param array without insert@<offset>
annotation: $ret_member";
+ } elsif ($ret_member =~ m/^remote_vcpu_bandwidth
(\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
+ splice(@args_list, int($3), 0, ("virDomainVcpuBWDefPtr
$1"));
+ push(@ret_list2, "if
(remoteDeserializeVcpuBandwidth(ret.$1.$1_val,\n" .
+ "
ret.$1.$1_len,\n" .
+ "
$2,\n" .
+ "
$1,\n" .
+ " n$1)
< 0)\n" .
+ " goto cleanup;\n");
+ $single_ret_cleanup = 1;
+ } elsif ($ret_member =~ m/^remote_vcpu_bandwidth (\S+)<\S+>;/) {
+ # error out on unannotated arrays
+ die "remote_vcpu_bandwidth array without insert@<offset>
annotation: $ret_member";
} elsif ($ret_member =~ m/^int (\S+);/) {
my $arg_name = $1;
--
1.7.1