--- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list