mirror of https://github.com/xemu-project/xemu.git
cryptodev: support QoS
Add 'throttle-bps' and 'throttle-ops' limitation to set QoS. The two arguments work with both QEMU command line and QMP command. Example of QEMU command line: -object cryptodev-backend-builtin,id=cryptodev1,throttle-bps=1600,\ throttle-ops=100 Example of QMP command: virsh qemu-monitor-command buster --hmp qom-set /objects/cryptodev1 \ throttle-ops 100 or cancel limitation: virsh qemu-monitor-command buster --hmp qom-set /objects/cryptodev1 \ throttle-ops 0 Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: zhenwei pi <pizhenwei@bytedance.com> Message-Id: <20230301105847.253084-11-pizhenwei@bytedance.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
e7a775fd9f
commit
2580b452ff
|
@ -28,6 +28,7 @@
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "qemu/main-loop.h"
|
||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "hw/virtio/virtio-crypto.h"
|
#include "hw/virtio/virtio-crypto.h"
|
||||||
|
|
||||||
|
@ -203,17 +204,53 @@ static int cryptodev_backend_account(CryptoDevBackend *backend,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cryptodev_backend_throttle_timer_cb(void *opaque)
|
||||||
|
{
|
||||||
|
CryptoDevBackend *backend = (CryptoDevBackend *)opaque;
|
||||||
|
CryptoDevBackendOpInfo *op_info, *tmpop;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
QTAILQ_FOREACH_SAFE(op_info, &backend->opinfos, next, tmpop) {
|
||||||
|
QTAILQ_REMOVE(&backend->opinfos, op_info, next);
|
||||||
|
ret = cryptodev_backend_account(backend, op_info);
|
||||||
|
if (ret < 0) {
|
||||||
|
op_info->cb(op_info->opaque, ret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
throttle_account(&backend->ts, true, ret);
|
||||||
|
cryptodev_backend_operation(backend, op_info);
|
||||||
|
if (throttle_enabled(&backend->tc) &&
|
||||||
|
throttle_schedule_timer(&backend->ts, &backend->tt, true)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int cryptodev_backend_crypto_operation(
|
int cryptodev_backend_crypto_operation(
|
||||||
CryptoDevBackend *backend,
|
CryptoDevBackend *backend,
|
||||||
CryptoDevBackendOpInfo *op_info)
|
CryptoDevBackendOpInfo *op_info)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!throttle_enabled(&backend->tc)) {
|
||||||
|
goto do_account;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (throttle_schedule_timer(&backend->ts, &backend->tt, true) ||
|
||||||
|
!QTAILQ_EMPTY(&backend->opinfos)) {
|
||||||
|
QTAILQ_INSERT_TAIL(&backend->opinfos, op_info, next);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_account:
|
||||||
ret = cryptodev_backend_account(backend, op_info);
|
ret = cryptodev_backend_account(backend, op_info);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throttle_account(&backend->ts, true, ret);
|
||||||
|
|
||||||
return cryptodev_backend_operation(backend, op_info);
|
return cryptodev_backend_operation(backend, op_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,12 +282,98 @@ cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
|
||||||
backend->conf.peers.queues = value;
|
backend->conf.peers.queues = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cryptodev_backend_set_throttle(CryptoDevBackend *backend, int field,
|
||||||
|
uint64_t value, Error **errp)
|
||||||
|
{
|
||||||
|
uint64_t orig = backend->tc.buckets[field].avg;
|
||||||
|
bool enabled = throttle_enabled(&backend->tc);
|
||||||
|
|
||||||
|
if (orig == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
backend->tc.buckets[field].avg = value;
|
||||||
|
if (!throttle_enabled(&backend->tc)) {
|
||||||
|
throttle_timers_destroy(&backend->tt);
|
||||||
|
cryptodev_backend_throttle_timer_cb(backend); /* drain opinfos */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!throttle_is_valid(&backend->tc, errp)) {
|
||||||
|
backend->tc.buckets[field].avg = orig; /* revert change */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
throttle_init(&backend->ts);
|
||||||
|
throttle_timers_init(&backend->tt, qemu_get_aio_context(),
|
||||||
|
QEMU_CLOCK_REALTIME,
|
||||||
|
cryptodev_backend_throttle_timer_cb, /* FIXME */
|
||||||
|
cryptodev_backend_throttle_timer_cb, backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
throttle_config(&backend->ts, QEMU_CLOCK_REALTIME, &backend->tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cryptodev_backend_get_bps(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||||
|
uint64_t value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
||||||
|
|
||||||
|
visit_type_uint64(v, name, &value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cryptodev_backend_set_bps(Object *obj, Visitor *v, const char *name,
|
||||||
|
void *opaque, Error **errp)
|
||||||
|
{
|
||||||
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||||
|
uint64_t value;
|
||||||
|
|
||||||
|
if (!visit_type_uint64(v, name, &value, errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cryptodev_backend_get_ops(Object *obj, Visitor *v, const char *name,
|
||||||
|
void *opaque, Error **errp)
|
||||||
|
{
|
||||||
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||||
|
uint64_t value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
||||||
|
|
||||||
|
visit_type_uint64(v, name, &value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cryptodev_backend_set_ops(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||||
|
uint64_t value;
|
||||||
|
|
||||||
|
if (!visit_type_uint64(v, name, &value, errp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
cryptodev_backend_complete(UserCreatable *uc, Error **errp)
|
||||||
{
|
{
|
||||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
|
||||||
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
|
||||||
uint32_t services;
|
uint32_t services;
|
||||||
|
uint64_t value;
|
||||||
|
|
||||||
|
QTAILQ_INIT(&backend->opinfos);
|
||||||
|
value = backend->tc.buckets[THROTTLE_OPS_TOTAL].avg;
|
||||||
|
cryptodev_backend_set_throttle(backend, THROTTLE_OPS_TOTAL, value, errp);
|
||||||
|
value = backend->tc.buckets[THROTTLE_BPS_TOTAL].avg;
|
||||||
|
cryptodev_backend_set_throttle(backend, THROTTLE_BPS_TOTAL, value, errp);
|
||||||
|
|
||||||
if (bc->init) {
|
if (bc->init) {
|
||||||
bc->init(backend, errp);
|
bc->init(backend, errp);
|
||||||
|
@ -294,8 +417,12 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc)
|
||||||
|
|
||||||
static void cryptodev_backend_instance_init(Object *obj)
|
static void cryptodev_backend_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||||
|
|
||||||
/* Initialize devices' queues property to 1 */
|
/* Initialize devices' queues property to 1 */
|
||||||
object_property_set_int(obj, "queues", 1, NULL);
|
object_property_set_int(obj, "queues", 1, NULL);
|
||||||
|
|
||||||
|
throttle_config_init(&backend->tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cryptodev_backend_finalize(Object *obj)
|
static void cryptodev_backend_finalize(Object *obj)
|
||||||
|
@ -303,6 +430,9 @@ static void cryptodev_backend_finalize(Object *obj)
|
||||||
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
|
||||||
|
|
||||||
cryptodev_backend_cleanup(backend, NULL);
|
cryptodev_backend_cleanup(backend, NULL);
|
||||||
|
if (throttle_enabled(&backend->tc)) {
|
||||||
|
throttle_timers_destroy(&backend->tt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -318,6 +448,14 @@ cryptodev_backend_class_init(ObjectClass *oc, void *data)
|
||||||
cryptodev_backend_get_queues,
|
cryptodev_backend_get_queues,
|
||||||
cryptodev_backend_set_queues,
|
cryptodev_backend_set_queues,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
object_class_property_add(oc, "throttle-bps", "uint64",
|
||||||
|
cryptodev_backend_get_bps,
|
||||||
|
cryptodev_backend_set_bps,
|
||||||
|
NULL, NULL);
|
||||||
|
object_class_property_add(oc, "throttle-ops", "uint64",
|
||||||
|
cryptodev_backend_get_ops,
|
||||||
|
cryptodev_backend_set_ops,
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo cryptodev_backend_info = {
|
static const TypeInfo cryptodev_backend_info = {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define CRYPTODEV_H
|
#define CRYPTODEV_H
|
||||||
|
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
|
#include "qemu/throttle.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
#include "qapi/qapi-types-cryptodev.h"
|
#include "qapi/qapi-types-cryptodev.h"
|
||||||
|
|
||||||
|
@ -187,6 +188,7 @@ typedef struct CryptoDevBackendOpInfo {
|
||||||
CryptoDevBackendSymOpInfo *sym_op_info;
|
CryptoDevBackendSymOpInfo *sym_op_info;
|
||||||
CryptoDevBackendAsymOpInfo *asym_op_info;
|
CryptoDevBackendAsymOpInfo *asym_op_info;
|
||||||
} u;
|
} u;
|
||||||
|
QTAILQ_ENTRY(CryptoDevBackendOpInfo) next;
|
||||||
} CryptoDevBackendOpInfo;
|
} CryptoDevBackendOpInfo;
|
||||||
|
|
||||||
struct CryptoDevBackendClass {
|
struct CryptoDevBackendClass {
|
||||||
|
@ -273,6 +275,11 @@ struct CryptoDevBackend {
|
||||||
CryptoDevBackendConf conf;
|
CryptoDevBackendConf conf;
|
||||||
CryptodevBackendSymStat *sym_stat;
|
CryptodevBackendSymStat *sym_stat;
|
||||||
CryptodevBackendAsymStat *asym_stat;
|
CryptodevBackendAsymStat *asym_stat;
|
||||||
|
|
||||||
|
ThrottleState ts;
|
||||||
|
ThrottleTimers tt;
|
||||||
|
ThrottleConfig tc;
|
||||||
|
QTAILQ_HEAD(, CryptoDevBackendOpInfo) opinfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CryptodevSymStatInc(be, op, bytes) do { \
|
#define CryptodevSymStatInc(be, op, bytes) do { \
|
||||||
|
|
|
@ -278,10 +278,16 @@
|
||||||
# cryptodev-backend and must be 1 for cryptodev-backend-builtin.
|
# cryptodev-backend and must be 1 for cryptodev-backend-builtin.
|
||||||
# (default: 1)
|
# (default: 1)
|
||||||
#
|
#
|
||||||
|
# @throttle-bps: limit total bytes per second (Since 8.0)
|
||||||
|
#
|
||||||
|
# @throttle-ops: limit total operations per second (Since 8.0)
|
||||||
|
#
|
||||||
# Since: 2.8
|
# Since: 2.8
|
||||||
##
|
##
|
||||||
{ 'struct': 'CryptodevBackendProperties',
|
{ 'struct': 'CryptodevBackendProperties',
|
||||||
'data': { '*queues': 'uint32' } }
|
'data': { '*queues': 'uint32',
|
||||||
|
'*throttle-bps': 'uint64',
|
||||||
|
'*throttle-ops': 'uint64' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @CryptodevVhostUserProperties:
|
# @CryptodevVhostUserProperties:
|
||||||
|
|
Loading…
Reference in New Issue