2011-09-02 19:34:48 +02:00
|
|
|
/*
|
2019-06-13 17:33:58 +02:00
|
|
|
* Human Monitor Interface commands
|
2011-09-02 19:34:48 +02:00
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2011
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
|
|
|
*
|
2012-01-13 17:44:23 +01:00
|
|
|
* Contributions after 2012-01-13 are licensed under the terms of the
|
|
|
|
* GNU GPL, version 2 or (at your option) any later version.
|
2011-09-02 19:34:48 +02:00
|
|
|
*/
|
|
|
|
|
2016-01-29 18:50:05 +01:00
|
|
|
#include "qemu/osdep.h"
|
2019-06-19 22:10:36 +02:00
|
|
|
#include "monitor/hmp.h"
|
2012-10-24 08:43:34 +02:00
|
|
|
#include "net/net.h"
|
2015-06-11 03:21:21 +02:00
|
|
|
#include "net/eth.h"
|
2019-08-12 07:23:59 +02:00
|
|
|
#include "sysemu/runstate.h"
|
2012-12-17 18:20:00 +01:00
|
|
|
#include "qemu/sockets.h"
|
2020-11-11 11:52:22 +01:00
|
|
|
#include "qemu/help_option.h"
|
2023-01-09 20:03:17 +01:00
|
|
|
#include "monitor/monitor.h"
|
2018-02-01 12:18:31 +01:00
|
|
|
#include "qapi/error.h"
|
2019-06-20 20:47:03 +02:00
|
|
|
#include "qapi/clone-visitor.h"
|
2018-02-11 10:36:05 +01:00
|
|
|
#include "qapi/qapi-builtin-visit.h"
|
2018-02-27 00:13:27 +01:00
|
|
|
#include "qapi/qapi-commands-block.h"
|
2020-01-29 11:22:37 +01:00
|
|
|
#include "qapi/qapi-commands-control.h"
|
2018-02-27 00:13:27 +01:00
|
|
|
#include "qapi/qapi-commands-migration.h"
|
|
|
|
#include "qapi/qapi-commands-misc.h"
|
|
|
|
#include "qapi/qapi-commands-net.h"
|
|
|
|
#include "qapi/qapi-commands-rocker.h"
|
|
|
|
#include "qapi/qapi-commands-run-state.h"
|
2022-04-26 12:17:35 +02:00
|
|
|
#include "qapi/qapi-commands-stats.h"
|
2018-02-27 00:13:27 +01:00
|
|
|
#include "qapi/qapi-commands-tpm.h"
|
2022-08-11 14:24:44 +02:00
|
|
|
#include "qapi/qapi-commands-virtio.h"
|
2019-06-20 20:47:03 +02:00
|
|
|
#include "qapi/qapi-visit-net.h"
|
2019-01-16 10:35:55 +01:00
|
|
|
#include "qapi/qapi-visit-migration.h"
|
2018-02-01 12:18:39 +01:00
|
|
|
#include "qapi/qmp/qdict.h"
|
2015-03-17 17:22:46 +01:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2017-05-16 11:37:45 +02:00
|
|
|
#include "qapi/string-input-visitor.h"
|
2014-05-14 11:43:35 +02:00
|
|
|
#include "qapi/string-output-visitor.h"
|
2016-02-10 19:40:59 +01:00
|
|
|
#include "qom/object_interfaces.h"
|
2016-03-20 18:16:19 +01:00
|
|
|
#include "qemu/cutils.h"
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
#include "qemu/error-report.h"
|
2022-04-26 12:17:35 +02:00
|
|
|
#include "hw/core/cpu.h"
|
2016-09-26 22:23:27 +02:00
|
|
|
#include "hw/intc/intc.h"
|
2017-04-20 14:25:55 +02:00
|
|
|
#include "migration/snapshot.h"
|
2017-06-27 06:10:19 +02:00
|
|
|
#include "migration/misc.h"
|
2011-09-02 19:34:48 +02:00
|
|
|
|
2021-10-28 17:18:25 +02:00
|
|
|
bool hmp_handle_error(Monitor *mon, Error *err)
|
2011-11-22 19:32:37 +01:00
|
|
|
{
|
2019-12-05 18:46:18 +01:00
|
|
|
if (err) {
|
|
|
|
error_reportf_err(err, "Error: ");
|
2021-10-28 17:18:25 +02:00
|
|
|
return true;
|
2011-11-22 19:32:37 +01:00
|
|
|
}
|
2021-10-28 17:18:25 +02:00
|
|
|
return false;
|
2011-11-22 19:32:37 +01:00
|
|
|
}
|
|
|
|
|
2019-06-20 20:47:03 +02:00
|
|
|
/*
|
|
|
|
* Produce a strList from a comma separated list.
|
|
|
|
* A NULL or empty input string return NULL.
|
|
|
|
*/
|
|
|
|
static strList *strList_from_comma_list(const char *in)
|
|
|
|
{
|
|
|
|
strList *res = NULL;
|
2021-01-13 23:10:12 +01:00
|
|
|
strList **tail = &res;
|
2019-06-20 20:47:03 +02:00
|
|
|
|
|
|
|
while (in && in[0]) {
|
|
|
|
char *comma = strchr(in, ',');
|
2021-01-13 23:10:12 +01:00
|
|
|
char *value;
|
2019-06-20 20:47:03 +02:00
|
|
|
|
|
|
|
if (comma) {
|
2021-01-13 23:10:12 +01:00
|
|
|
value = g_strndup(in, comma - in);
|
2019-06-20 20:47:03 +02:00
|
|
|
in = comma + 1; /* skip the , */
|
|
|
|
} else {
|
2021-01-13 23:10:12 +01:00
|
|
|
value = g_strdup(in);
|
2019-06-20 20:47:03 +02:00
|
|
|
in = NULL;
|
|
|
|
}
|
2021-01-13 23:10:12 +01:00
|
|
|
QAPI_LIST_APPEND(tail, value);
|
2019-06-20 20:47:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_name(Monitor *mon, const QDict *qdict)
|
2011-09-02 19:34:48 +02:00
|
|
|
{
|
|
|
|
NameInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_name(NULL);
|
2022-11-04 17:06:59 +01:00
|
|
|
if (info->name) {
|
2011-09-02 19:34:48 +02:00
|
|
|
monitor_printf(mon, "%s\n", info->name);
|
|
|
|
}
|
|
|
|
qapi_free_NameInfo(info);
|
|
|
|
}
|
2011-08-26 22:38:13 +02:00
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_version(Monitor *mon, const QDict *qdict)
|
2011-08-26 22:38:13 +02:00
|
|
|
{
|
|
|
|
VersionInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_version(NULL);
|
|
|
|
|
|
|
|
monitor_printf(mon, "%" PRId64 ".%" PRId64 ".%" PRId64 "%s\n",
|
2015-05-04 17:05:31 +02:00
|
|
|
info->qemu->major, info->qemu->minor, info->qemu->micro,
|
2011-08-26 22:38:13 +02:00
|
|
|
info->package);
|
|
|
|
|
|
|
|
qapi_free_VersionInfo(info);
|
|
|
|
}
|
2011-09-12 20:10:53 +02:00
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_status(Monitor *mon, const QDict *qdict)
|
2011-09-12 22:54:20 +02:00
|
|
|
{
|
|
|
|
StatusInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_status(NULL);
|
|
|
|
|
|
|
|
monitor_printf(mon, "VM status: %s%s",
|
|
|
|
info->running ? "running" : "paused",
|
|
|
|
info->singlestep ? " (single step mode)" : "");
|
|
|
|
|
|
|
|
if (!info->running && info->status != RUN_STATE_PAUSED) {
|
2017-08-24 10:46:08 +02:00
|
|
|
monitor_printf(mon, " (%s)", RunState_str(info->status));
|
2011-09-12 22:54:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
|
|
|
|
qapi_free_StatusInfo(info);
|
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
2011-09-13 22:37:16 +02:00
|
|
|
{
|
|
|
|
MigrationInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_migrate(NULL);
|
2012-08-06 20:42:47 +02:00
|
|
|
|
2017-06-27 06:10:19 +02:00
|
|
|
migration_global_dump(mon);
|
|
|
|
|
2021-04-29 16:04:24 +02:00
|
|
|
if (info->blocked_reasons) {
|
migration: Display the migration blockers
Update 'info migrate' to display migration blocking information.
If the outbound migration is not blocked, there is no change, however
if it is blocked a message is displayed with a list of reasons why,
e.g.
qemu-system-x86_64 -nographic -smp 4 -m 4G -M pc,usb=on \
-chardev null,id=n -device usb-serial,chardev=n \
-virtfs local,path=/home,mount_tag=fs,security_model=none \
-drive if=virtio,file=myimage.qcow2
(qemu) info migrate
globals:
store-global-state: on
only-migratable: off
send-configuration: on
send-section-footer: on
decompress-error-check: on
clear-bitmap-shift: 18
Outgoing migration blocked:
Migration is disabled when VirtFS export path '/home' is mounted in the guest using mount_tag 'fs'
non-migratable device: 0000:00:01.2/1/usb-serial
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-Id: <20210202135522.127380-3-dgilbert@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
2021-02-02 14:55:22 +01:00
|
|
|
strList *reasons = info->blocked_reasons;
|
|
|
|
monitor_printf(mon, "Outgoing migration blocked:\n");
|
|
|
|
while (reasons) {
|
|
|
|
monitor_printf(mon, " %s\n", reasons->value);
|
|
|
|
reasons = reasons->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-13 22:37:16 +02:00
|
|
|
if (info->has_status) {
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
monitor_printf(mon, "Migration status: %s",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationStatus_str(info->status));
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->status == MIGRATION_STATUS_FAILED && info->error_desc) {
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
monitor_printf(mon, " (%s)\n", info->error_desc);
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
2020-03-31 10:22:07 +02:00
|
|
|
monitor_printf(mon, "total time: %" PRIu64 " ms\n",
|
2012-08-18 13:17:10 +02:00
|
|
|
info->total_time);
|
2012-08-13 09:53:12 +02:00
|
|
|
if (info->has_expected_downtime) {
|
2020-03-31 10:22:07 +02:00
|
|
|
monitor_printf(mon, "expected downtime: %" PRIu64 " ms\n",
|
2012-08-13 09:53:12 +02:00
|
|
|
info->expected_downtime);
|
|
|
|
}
|
2012-08-13 09:35:16 +02:00
|
|
|
if (info->has_downtime) {
|
2020-03-31 10:22:07 +02:00
|
|
|
monitor_printf(mon, "downtime: %" PRIu64 " ms\n",
|
2012-08-13 09:35:16 +02:00
|
|
|
info->downtime);
|
|
|
|
}
|
2013-07-22 16:01:58 +02:00
|
|
|
if (info->has_setup_time) {
|
2020-03-31 10:22:07 +02:00
|
|
|
monitor_printf(mon, "setup: %" PRIu64 " ms\n",
|
2013-07-22 16:01:58 +02:00
|
|
|
info->setup_time);
|
|
|
|
}
|
2011-09-13 22:37:16 +02:00
|
|
|
}
|
|
|
|
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->ram) {
|
2011-09-13 22:37:16 +02:00
|
|
|
monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->transferred >> 10);
|
2013-06-26 03:35:30 +02:00
|
|
|
monitor_printf(mon, "throughput: %0.2f mbps\n",
|
|
|
|
info->ram->mbps);
|
2011-09-13 22:37:16 +02:00
|
|
|
monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->remaining >> 10);
|
|
|
|
monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->total >> 10);
|
2012-08-06 20:42:56 +02:00
|
|
|
monitor_printf(mon, "duplicate: %" PRIu64 " pages\n",
|
|
|
|
info->ram->duplicate);
|
2013-03-26 10:58:37 +01:00
|
|
|
monitor_printf(mon, "skipped: %" PRIu64 " pages\n",
|
|
|
|
info->ram->skipped);
|
2012-08-06 20:42:56 +02:00
|
|
|
monitor_printf(mon, "normal: %" PRIu64 " pages\n",
|
|
|
|
info->ram->normal);
|
|
|
|
monitor_printf(mon, "normal bytes: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->normal_bytes >> 10);
|
2014-04-04 11:57:55 +02:00
|
|
|
monitor_printf(mon, "dirty sync count: %" PRIu64 "\n",
|
|
|
|
info->ram->dirty_sync_count);
|
2017-03-21 03:22:43 +01:00
|
|
|
monitor_printf(mon, "page size: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->page_size >> 10);
|
2018-06-26 15:20:11 +02:00
|
|
|
monitor_printf(mon, "multifd bytes: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->multifd_bytes >> 10);
|
2019-01-11 07:37:30 +01:00
|
|
|
monitor_printf(mon, "pages-per-second: %" PRIu64 "\n",
|
|
|
|
info->ram->pages_per_second);
|
2017-03-21 03:22:43 +01:00
|
|
|
|
2012-08-13 12:31:25 +02:00
|
|
|
if (info->ram->dirty_pages_rate) {
|
|
|
|
monitor_printf(mon, "dirty pages rate: %" PRIu64 " pages\n",
|
|
|
|
info->ram->dirty_pages_rate);
|
|
|
|
}
|
2016-06-13 13:16:42 +02:00
|
|
|
if (info->ram->postcopy_requests) {
|
|
|
|
monitor_printf(mon, "postcopy request count: %" PRIu64 "\n",
|
|
|
|
info->ram->postcopy_requests);
|
|
|
|
}
|
2021-12-21 10:34:41 +01:00
|
|
|
if (info->ram->precopy_bytes) {
|
|
|
|
monitor_printf(mon, "precopy ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->precopy_bytes >> 10);
|
|
|
|
}
|
|
|
|
if (info->ram->downtime_bytes) {
|
|
|
|
monitor_printf(mon, "downtime ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->downtime_bytes >> 10);
|
|
|
|
}
|
|
|
|
if (info->ram->postcopy_bytes) {
|
|
|
|
monitor_printf(mon, "postcopy ram: %" PRIu64 " kbytes\n",
|
|
|
|
info->ram->postcopy_bytes >> 10);
|
|
|
|
}
|
2022-07-11 23:11:12 +02:00
|
|
|
if (info->ram->dirty_sync_missed_zero_copy) {
|
|
|
|
monitor_printf(mon,
|
|
|
|
"Zero-copy-send fallbacks happened: %" PRIu64 " times\n",
|
|
|
|
info->ram->dirty_sync_missed_zero_copy);
|
|
|
|
}
|
2011-09-13 22:37:16 +02:00
|
|
|
}
|
|
|
|
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->disk) {
|
2011-09-13 22:37:16 +02:00
|
|
|
monitor_printf(mon, "transferred disk: %" PRIu64 " kbytes\n",
|
|
|
|
info->disk->transferred >> 10);
|
|
|
|
monitor_printf(mon, "remaining disk: %" PRIu64 " kbytes\n",
|
|
|
|
info->disk->remaining >> 10);
|
|
|
|
monitor_printf(mon, "total disk: %" PRIu64 " kbytes\n",
|
|
|
|
info->disk->total >> 10);
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->xbzrle_cache) {
|
2012-08-06 20:42:57 +02:00
|
|
|
monitor_printf(mon, "cache size: %" PRIu64 " bytes\n",
|
|
|
|
info->xbzrle_cache->cache_size);
|
|
|
|
monitor_printf(mon, "xbzrle transferred: %" PRIu64 " kbytes\n",
|
|
|
|
info->xbzrle_cache->bytes >> 10);
|
|
|
|
monitor_printf(mon, "xbzrle pages: %" PRIu64 " pages\n",
|
|
|
|
info->xbzrle_cache->pages);
|
2020-06-03 10:09:02 +02:00
|
|
|
monitor_printf(mon, "xbzrle cache miss: %" PRIu64 " pages\n",
|
2012-08-06 20:42:57 +02:00
|
|
|
info->xbzrle_cache->cache_miss);
|
2014-04-04 11:57:56 +02:00
|
|
|
monitor_printf(mon, "xbzrle cache miss rate: %0.2f\n",
|
|
|
|
info->xbzrle_cache->cache_miss_rate);
|
2020-04-30 02:59:35 +02:00
|
|
|
monitor_printf(mon, "xbzrle encoding rate: %0.2f\n",
|
|
|
|
info->xbzrle_cache->encoding_rate);
|
2020-03-20 15:32:16 +01:00
|
|
|
monitor_printf(mon, "xbzrle overflow: %" PRIu64 "\n",
|
2012-08-06 20:42:57 +02:00
|
|
|
info->xbzrle_cache->overflow);
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->compression) {
|
2018-09-06 09:01:00 +02:00
|
|
|
monitor_printf(mon, "compression pages: %" PRIu64 " pages\n",
|
|
|
|
info->compression->pages);
|
|
|
|
monitor_printf(mon, "compression busy: %" PRIu64 "\n",
|
|
|
|
info->compression->busy);
|
|
|
|
monitor_printf(mon, "compression busy rate: %0.2f\n",
|
|
|
|
info->compression->busy_rate);
|
2020-06-03 10:09:02 +02:00
|
|
|
monitor_printf(mon, "compressed size: %" PRIu64 " kbytes\n",
|
|
|
|
info->compression->compressed_size >> 10);
|
2018-09-06 09:01:00 +02:00
|
|
|
monitor_printf(mon, "compression rate: %0.2f\n",
|
|
|
|
info->compression->compression_rate);
|
|
|
|
}
|
|
|
|
|
2016-04-21 20:07:18 +02:00
|
|
|
if (info->has_cpu_throttle_percentage) {
|
2015-09-08 19:12:36 +02:00
|
|
|
monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n",
|
2016-04-21 20:07:18 +02:00
|
|
|
info->cpu_throttle_percentage);
|
2015-09-08 19:12:36 +02:00
|
|
|
}
|
|
|
|
|
2018-03-22 19:17:27 +01:00
|
|
|
if (info->has_postcopy_blocktime) {
|
|
|
|
monitor_printf(mon, "postcopy blocktime: %u\n",
|
|
|
|
info->postcopy_blocktime);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->has_postcopy_vcpu_blocktime) {
|
|
|
|
Visitor *v;
|
|
|
|
char *str;
|
|
|
|
v = string_output_visitor_new(false, &str);
|
2020-04-24 10:43:35 +02:00
|
|
|
visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime,
|
|
|
|
&error_abort);
|
2018-03-22 19:17:27 +01:00
|
|
|
visit_complete(v, &str);
|
|
|
|
monitor_printf(mon, "postcopy vcpu blocktime: %s\n", str);
|
|
|
|
g_free(str);
|
|
|
|
visit_free(v);
|
|
|
|
}
|
2019-02-27 11:51:27 +01:00
|
|
|
if (info->has_socket_address) {
|
|
|
|
SocketAddressList *addr;
|
|
|
|
|
|
|
|
monitor_printf(mon, "socket address: [\n");
|
|
|
|
|
|
|
|
for (addr = info->socket_address; addr; addr = addr->next) {
|
2022-10-21 11:09:18 +02:00
|
|
|
char *s = socket_uri(addr->value);
|
2019-02-27 11:51:27 +01:00
|
|
|
monitor_printf(mon, "\t%s\n", s);
|
|
|
|
g_free(s);
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "]\n");
|
|
|
|
}
|
2020-10-26 10:36:27 +01:00
|
|
|
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->vfio) {
|
2020-10-26 10:36:27 +01:00
|
|
|
monitor_printf(mon, "vfio device transferred: %" PRIu64 " kbytes\n",
|
|
|
|
info->vfio->transferred >> 10);
|
|
|
|
}
|
|
|
|
|
2011-09-13 22:37:16 +02:00
|
|
|
qapi_free_MigrationInfo(info);
|
2012-08-06 20:42:47 +02:00
|
|
|
}
|
|
|
|
|
2013-01-14 07:06:25 +01:00
|
|
|
void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict)
|
2012-08-06 20:42:47 +02:00
|
|
|
{
|
|
|
|
MigrationCapabilityStatusList *caps, *cap;
|
|
|
|
|
|
|
|
caps = qmp_query_migrate_capabilities(NULL);
|
|
|
|
|
|
|
|
if (caps) {
|
|
|
|
for (cap = caps; cap; cap = cap->next) {
|
2017-04-01 10:18:44 +02:00
|
|
|
monitor_printf(mon, "%s: %s\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationCapability_str(cap->value->capability),
|
2012-08-06 20:42:47 +02:00
|
|
|
cap->value->state ? "on" : "off");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MigrationCapabilityStatusList(caps);
|
2011-09-13 22:37:16 +02:00
|
|
|
}
|
|
|
|
|
2015-03-23 09:32:29 +01:00
|
|
|
void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
MigrationParameters *params;
|
|
|
|
|
|
|
|
params = qmp_query_migrate_parameters(NULL);
|
|
|
|
|
|
|
|
if (params) {
|
2019-02-27 14:24:06 +01:00
|
|
|
monitor_printf(mon, "%s: %" PRIu64 " ms\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_INITIAL),
|
|
|
|
params->announce_initial);
|
|
|
|
monitor_printf(mon, "%s: %" PRIu64 " ms\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_MAX),
|
|
|
|
params->announce_max);
|
|
|
|
monitor_printf(mon, "%s: %" PRIu64 "\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_ROUNDS),
|
|
|
|
params->announce_rounds);
|
|
|
|
monitor_printf(mon, "%s: %" PRIu64 " ms\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_STEP),
|
|
|
|
params->announce_step);
|
2016-09-09 05:14:15 +02:00
|
|
|
assert(params->has_compress_level);
|
2017-12-01 13:08:38 +01:00
|
|
|
monitor_printf(mon, "%s: %u\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_LEVEL),
|
2015-03-23 09:32:29 +01:00
|
|
|
params->compress_level);
|
2016-09-09 05:14:15 +02:00
|
|
|
assert(params->has_compress_threads);
|
2017-12-01 13:08:38 +01:00
|
|
|
monitor_printf(mon, "%s: %u\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_THREADS),
|
2015-03-23 09:32:29 +01:00
|
|
|
params->compress_threads);
|
2018-08-21 10:10:20 +02:00
|
|
|
assert(params->has_compress_wait_thread);
|
|
|
|
monitor_printf(mon, "%s: %s\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_COMPRESS_WAIT_THREAD),
|
|
|
|
params->compress_wait_thread ? "on" : "off");
|
2016-09-09 05:14:15 +02:00
|
|
|
assert(params->has_decompress_threads);
|
2017-12-01 13:08:38 +01:00
|
|
|
monitor_printf(mon, "%s: %u\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_DECOMPRESS_THREADS),
|
2015-03-23 09:32:29 +01:00
|
|
|
params->decompress_threads);
|
2020-02-24 03:31:42 +01:00
|
|
|
assert(params->has_throttle_trigger_threshold);
|
|
|
|
monitor_printf(mon, "%s: %u\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD),
|
|
|
|
params->throttle_trigger_threshold);
|
2016-09-09 05:14:15 +02:00
|
|
|
assert(params->has_cpu_throttle_initial);
|
2017-12-01 13:08:38 +01:00
|
|
|
monitor_printf(mon, "%s: %u\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL),
|
2016-04-21 20:07:18 +02:00
|
|
|
params->cpu_throttle_initial);
|
2016-09-09 05:14:15 +02:00
|
|
|
assert(params->has_cpu_throttle_increment);
|
2017-12-01 13:08:38 +01:00
|
|
|
monitor_printf(mon, "%s: %u\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT),
|
2016-04-21 20:07:18 +02:00
|
|
|
params->cpu_throttle_increment);
|
2020-04-13 12:15:08 +02:00
|
|
|
assert(params->has_cpu_throttle_tailslow);
|
|
|
|
monitor_printf(mon, "%s: %s\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW),
|
|
|
|
params->cpu_throttle_tailslow ? "on" : "off");
|
2018-08-01 15:00:20 +02:00
|
|
|
assert(params->has_max_cpu_throttle);
|
|
|
|
monitor_printf(mon, "%s: %u\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_MAX_CPU_THROTTLE),
|
|
|
|
params->max_cpu_throttle);
|
2022-11-04 17:06:58 +01:00
|
|
|
assert(params->tls_creds);
|
2017-04-01 10:18:45 +02:00
|
|
|
monitor_printf(mon, "%s: '%s'\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_TLS_CREDS),
|
2017-07-18 12:04:54 +02:00
|
|
|
params->tls_creds);
|
2022-11-04 17:06:58 +01:00
|
|
|
assert(params->tls_hostname);
|
2017-04-01 10:18:45 +02:00
|
|
|
monitor_printf(mon, "%s: '%s'\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_TLS_HOSTNAME),
|
2017-07-18 12:04:54 +02:00
|
|
|
params->tls_hostname);
|
2016-09-15 18:20:28 +02:00
|
|
|
assert(params->has_max_bandwidth);
|
2017-12-01 13:08:38 +01:00
|
|
|
monitor_printf(mon, "%s: %" PRIu64 " bytes/second\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH),
|
2016-09-15 18:20:28 +02:00
|
|
|
params->max_bandwidth);
|
|
|
|
assert(params->has_downtime_limit);
|
2020-06-03 10:08:58 +02:00
|
|
|
monitor_printf(mon, "%s: %" PRIu64 " ms\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_DOWNTIME_LIMIT),
|
2016-09-15 18:20:28 +02:00
|
|
|
params->downtime_limit);
|
2016-11-02 08:42:09 +01:00
|
|
|
assert(params->has_x_checkpoint_delay);
|
2020-06-03 10:08:58 +02:00
|
|
|
monitor_printf(mon, "%s: %u ms\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY),
|
2016-10-27 08:43:01 +02:00
|
|
|
params->x_checkpoint_delay);
|
2017-04-05 18:32:37 +02:00
|
|
|
assert(params->has_block_incremental);
|
|
|
|
monitor_printf(mon, "%s: %s\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_BLOCK_INCREMENTAL),
|
|
|
|
params->block_incremental ? "on" : "off");
|
2017-12-01 13:08:38 +01:00
|
|
|
monitor_printf(mon, "%s: %u\n",
|
2019-02-06 13:54:06 +01:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_CHANNELS),
|
|
|
|
params->multifd_channels);
|
2019-01-16 10:35:55 +01:00
|
|
|
monitor_printf(mon, "%s: %s\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_COMPRESSION),
|
|
|
|
MultiFDCompression_str(params->multifd_compression));
|
2020-06-03 10:08:58 +02:00
|
|
|
monitor_printf(mon, "%s: %" PRIu64 " bytes\n",
|
2017-10-05 21:30:10 +02:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE),
|
|
|
|
params->xbzrle_cache_size);
|
2018-06-13 12:26:40 +02:00
|
|
|
monitor_printf(mon, "%s: %" PRIu64 "\n",
|
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH),
|
|
|
|
params->max_postcopy_bandwidth);
|
2020-03-25 02:49:30 +01:00
|
|
|
monitor_printf(mon, "%s: '%s'\n",
|
migration: add support for a "tls-authz" migration parameter
The QEMU instance that runs as the server for the migration data
transport (ie the target QEMU) needs to be able to configure access
control so it can prevent unauthorized clients initiating an incoming
migration. This adds a new 'tls-authz' migration parameter that is used
to provide the QOM ID of a QAuthZ subclass instance that provides the
access control check. This is checked against the x509 certificate
obtained during the TLS handshake.
For example, when starting a QEMU for incoming migration, it is
possible to give an example identity of the source QEMU that is
intended to be connecting later:
$QEMU \
-monitor stdio \
-incoming defer \
...other args...
(qemu) object_add tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
(qemu) object_add authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB \
(qemu) migrate_incoming tcp:localhost:9000
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
2019-02-27 15:53:24 +01:00
|
|
|
MigrationParameter_str(MIGRATION_PARAMETER_TLS_AUTHZ),
|
2020-03-25 02:49:30 +01:00
|
|
|
params->tls_authz);
|
2020-08-20 17:07:23 +02:00
|
|
|
|
|
|
|
if (params->has_block_bitmap_mapping) {
|
|
|
|
const BitmapMigrationNodeAliasList *bmnal;
|
|
|
|
|
|
|
|
monitor_printf(mon, "%s:\n",
|
|
|
|
MigrationParameter_str(
|
|
|
|
MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING));
|
|
|
|
|
|
|
|
for (bmnal = params->block_bitmap_mapping;
|
|
|
|
bmnal;
|
|
|
|
bmnal = bmnal->next)
|
|
|
|
{
|
|
|
|
const BitmapMigrationNodeAlias *bmna = bmnal->value;
|
|
|
|
const BitmapMigrationBitmapAliasList *bmbal;
|
|
|
|
|
|
|
|
monitor_printf(mon, " '%s' -> '%s'\n",
|
|
|
|
bmna->node_name, bmna->alias);
|
|
|
|
|
|
|
|
for (bmbal = bmna->bitmaps; bmbal; bmbal = bmbal->next) {
|
|
|
|
const BitmapMigrationBitmapAlias *bmba = bmbal->value;
|
|
|
|
|
|
|
|
monitor_printf(mon, " '%s' -> '%s'\n",
|
|
|
|
bmba->name, bmba->alias);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-23 09:32:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MigrationParameters(params);
|
|
|
|
}
|
|
|
|
|
2016-09-26 22:23:27 +02:00
|
|
|
static int hmp_info_pic_foreach(Object *obj, void *opaque)
|
|
|
|
{
|
|
|
|
InterruptStatsProvider *intc;
|
|
|
|
InterruptStatsProviderClass *k;
|
|
|
|
Monitor *mon = opaque;
|
|
|
|
|
|
|
|
if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
|
|
|
|
intc = INTERRUPT_STATS_PROVIDER(obj);
|
|
|
|
k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
|
|
|
|
if (k->print_info) {
|
|
|
|
k->print_info(intc, mon);
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "Interrupt controller information not available for %s.\n",
|
|
|
|
object_get_typename(obj));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_info_pic(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
object_child_foreach_recursive(object_get_root(),
|
|
|
|
hmp_info_pic_foreach, mon);
|
|
|
|
}
|
|
|
|
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
void hmp_info_tpm(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2021-06-15 16:21:21 +02:00
|
|
|
#ifdef CONFIG_TPM
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
TPMInfoList *info_list, *info;
|
|
|
|
Error *err = NULL;
|
|
|
|
unsigned int c = 0;
|
|
|
|
TPMPassthroughOptions *tpo;
|
2017-09-29 13:10:20 +02:00
|
|
|
TPMEmulatorOptions *teo;
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
|
|
|
|
info_list = qmp_query_tpm(&err);
|
|
|
|
if (err) {
|
|
|
|
monitor_printf(mon, "TPM device not supported\n");
|
|
|
|
error_free(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info_list) {
|
|
|
|
monitor_printf(mon, "TPM device:\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (info = info_list; info; info = info->next) {
|
|
|
|
TPMInfo *ti = info->value;
|
|
|
|
monitor_printf(mon, " tpm%d: model=%s\n",
|
2017-08-24 10:46:08 +02:00
|
|
|
c, TpmModel_str(ti->model));
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
|
|
|
|
monitor_printf(mon, " \\ %s: type=%s",
|
2021-09-17 16:31:16 +02:00
|
|
|
ti->id, TpmType_str(ti->options->type));
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
|
2015-10-26 23:35:00 +01:00
|
|
|
switch (ti->options->type) {
|
2021-09-17 16:31:16 +02:00
|
|
|
case TPM_TYPE_PASSTHROUGH:
|
qapi: Don't special-case simple union wrappers
Simple unions were carrying a special case that hid their 'data'
QMP member from the resulting C struct, via the hack method
QAPISchemaObjectTypeVariant.simple_union_type(). But by using
the work we started by unboxing flat union and alternate
branches, coupled with the ability to visit the members of an
implicit type, we can now expose the simple union's implicit
type in qapi-types.h:
| struct q_obj_ImageInfoSpecificQCow2_wrapper {
| ImageInfoSpecificQCow2 *data;
| };
|
| struct q_obj_ImageInfoSpecificVmdk_wrapper {
| ImageInfoSpecificVmdk *data;
| };
...
| struct ImageInfoSpecific {
| ImageInfoSpecificKind type;
| union { /* union tag is @type */
| void *data;
|- ImageInfoSpecificQCow2 *qcow2;
|- ImageInfoSpecificVmdk *vmdk;
|+ q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
|+ q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
| } u;
| };
Doing this removes asymmetry between QAPI's QMP side and its
C side (both sides now expose 'data'), and means that the
treatment of a simple union as sugar for a flat union is now
equivalent in both languages (previously the two approaches used
a different layer of dereferencing, where the simple union could
be converted to a flat union with equivalent C layout but
different {} on the wire, or to an equivalent QMP wire form
but with different C representation). Using the implicit type
also lets us get rid of the simple_union_type() hack.
Of course, now all clients of simple unions have to adjust from
using su->u.member to using su->u.member.data; while this touches
a number of files in the tree, some earlier cleanup patches
helped minimize the change to the initialization of a temporary
variable rather than every single member access. The generated
qapi-visit.c code is also affected by the layout change:
|@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
| }
| switch (obj->type) {
| case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
|- visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
|+ visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
| break;
| case IMAGE_INFO_SPECIFIC_KIND_VMDK:
|- visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
|+ visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
| break;
| default:
| abort();
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-17 23:48:37 +01:00
|
|
|
tpo = ti->options->u.passthrough.data;
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
monitor_printf(mon, "%s%s%s%s",
|
2022-11-04 17:07:07 +01:00
|
|
|
tpo->path ? ",path=" : "",
|
|
|
|
tpo->path ?: "",
|
|
|
|
tpo->cancel_path ? ",cancel-path=" : "",
|
|
|
|
tpo->cancel_path ?: "");
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
break;
|
2021-09-17 16:31:16 +02:00
|
|
|
case TPM_TYPE_EMULATOR:
|
2017-09-29 13:10:20 +02:00
|
|
|
teo = ti->options->u.emulator.data;
|
|
|
|
monitor_printf(mon, ",chardev=%s", teo->chardev);
|
|
|
|
break;
|
2021-09-17 16:31:16 +02:00
|
|
|
case TPM_TYPE__MAX:
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
qapi_free_TPMInfoList(info_list);
|
2021-06-15 16:21:21 +02:00
|
|
|
#else
|
|
|
|
monitor_printf(mon, "TPM device not supported\n");
|
|
|
|
#endif /* CONFIG_TPM */
|
Support for TPM command line options
This patch adds support for TPM command line options.
The command line options supported here are
./qemu-... -tpmdev passthrough,path=<path to TPM device>,id=<id>
-device tpm-tis,tpmdev=<id>,id=<other id>
and
./qemu-... -tpmdev help
where the latter works similar to -soundhw help and shows a list of
available TPM backends (for example 'passthrough').
Using the type parameter, the backend is chosen, i.e., 'passthrough' for the
passthrough driver. The interpretation of the other parameters along
with determining whether enough parameters were provided is pushed into
the backend driver, which needs to implement the interface function
'create' and return a TPMDriverOpts structure if the VM can be started or
'NULL' if not enough or bad parameters were provided.
Monitor support for 'info tpm' has been added. It for example prints the
following:
(qemu) info tpm
TPM devices:
tpm0: model=tpm-tis
\ tpm0: type=passthrough,path=/dev/tpm0,cancel-path=/sys/devices/pnp0/00:09/cancel
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
Reviewed-by: Joel Schopp <jschopp@linux.vnet.ibm.com>
Message-id: 1361987275-26289-2-git-send-email-stefanb@linux.vnet.ibm.com
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2013-02-27 18:47:49 +01:00
|
|
|
}
|
|
|
|
|
2011-09-15 19:20:28 +02:00
|
|
|
void hmp_quit(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
monitor_suspend(mon);
|
|
|
|
qmp_quit(NULL);
|
|
|
|
}
|
2011-09-15 19:34:39 +02:00
|
|
|
|
|
|
|
void hmp_stop(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
qmp_stop(NULL);
|
|
|
|
}
|
2011-09-15 19:41:46 +02:00
|
|
|
|
2018-08-15 22:00:03 +02:00
|
|
|
void hmp_sync_profile(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *op = qdict_get_try_str(qdict, "op");
|
|
|
|
|
|
|
|
if (op == NULL) {
|
|
|
|
bool on = qsp_is_enabled();
|
|
|
|
|
|
|
|
monitor_printf(mon, "sync-profile is %s\n", on ? "on" : "off");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!strcmp(op, "on")) {
|
|
|
|
qsp_enable();
|
|
|
|
} else if (!strcmp(op, "off")) {
|
|
|
|
qsp_disable();
|
|
|
|
} else if (!strcmp(op, "reset")) {
|
|
|
|
qsp_reset();
|
|
|
|
} else {
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
error_setg(&err, QERR_INVALID_PARAMETER, op);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2018-08-15 22:00:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-20 17:39:46 +02:00
|
|
|
void hmp_exit_preconfig(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2018-07-05 11:14:02 +02:00
|
|
|
qmp_x_exit_preconfig(&err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2018-06-20 17:39:46 +02:00
|
|
|
}
|
|
|
|
|
2011-10-06 19:31:39 +02:00
|
|
|
void hmp_cpu(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
int64_t cpu_index;
|
|
|
|
|
|
|
|
/* XXX: drop the monitor_set_cpu() usage when all HMP commands that
|
|
|
|
use it are converted to the QAPI */
|
|
|
|
cpu_index = qdict_get_int(qdict, "index");
|
2020-10-05 17:58:42 +02:00
|
|
|
if (monitor_set_cpu(mon, cpu_index) < 0) {
|
2011-10-06 19:31:39 +02:00
|
|
|
monitor_printf(mon, "invalid CPU index\n");
|
|
|
|
}
|
|
|
|
}
|
2011-11-22 19:32:37 +01:00
|
|
|
|
2011-11-22 20:58:31 +01:00
|
|
|
void hmp_cont(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-22 20:58:31 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_cont(&err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2011-11-22 20:58:31 +01:00
|
|
|
}
|
2011-11-23 15:55:53 +01:00
|
|
|
|
2011-11-23 16:11:55 +01:00
|
|
|
void hmp_set_link(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
2015-05-16 00:25:00 +02:00
|
|
|
bool up = qdict_get_bool(qdict, "up");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2011-11-23 16:11:55 +01:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_set_link(name, up, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2011-11-23 16:11:55 +01:00
|
|
|
}
|
2011-11-23 16:28:21 +01:00
|
|
|
|
2017-04-18 11:40:56 +02:00
|
|
|
void hmp_loadvm(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
int saved_vm_running = runstate_is_running();
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
2017-04-18 18:12:35 +02:00
|
|
|
Error *err = NULL;
|
2017-04-18 11:40:56 +02:00
|
|
|
|
|
|
|
vm_stop(RUN_STATE_RESTORE_VM);
|
|
|
|
|
2021-05-11 18:31:51 +02:00
|
|
|
if (load_snapshot(name, NULL, false, NULL, &err) && saved_vm_running) {
|
2017-04-18 11:40:56 +02:00
|
|
|
vm_start();
|
|
|
|
}
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2017-04-18 11:40:56 +02:00
|
|
|
}
|
|
|
|
|
2017-04-18 11:44:16 +02:00
|
|
|
void hmp_savevm(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2017-04-18 18:12:35 +02:00
|
|
|
Error *err = NULL;
|
|
|
|
|
2021-02-04 13:48:30 +01:00
|
|
|
save_snapshot(qdict_get_try_str(qdict, "name"),
|
|
|
|
true, NULL, false, NULL, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2017-04-18 11:44:16 +02:00
|
|
|
}
|
|
|
|
|
2017-04-18 11:46:23 +02:00
|
|
|
void hmp_delvm(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2018-02-25 02:47:51 +01:00
|
|
|
Error *err = NULL;
|
2017-04-18 11:46:23 +02:00
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
|
2021-02-04 13:48:31 +01:00
|
|
|
delete_snapshot(name, false, NULL, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2017-04-18 11:46:23 +02:00
|
|
|
}
|
|
|
|
|
2019-02-27 14:24:12 +01:00
|
|
|
void hmp_announce_self(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2019-06-20 20:47:03 +02:00
|
|
|
const char *interfaces_str = qdict_get_try_str(qdict, "interfaces");
|
2019-06-20 20:47:05 +02:00
|
|
|
const char *id = qdict_get_try_str(qdict, "id");
|
2019-06-20 20:47:03 +02:00
|
|
|
AnnounceParameters *params = QAPI_CLONE(AnnounceParameters,
|
|
|
|
migrate_announce_params());
|
|
|
|
|
|
|
|
qapi_free_strList(params->interfaces);
|
|
|
|
params->interfaces = strList_from_comma_list(interfaces_str);
|
|
|
|
params->has_interfaces = params->interfaces != NULL;
|
2019-06-20 20:47:05 +02:00
|
|
|
params->id = g_strdup(id);
|
2019-06-20 20:47:03 +02:00
|
|
|
qmp_announce_self(params, NULL);
|
|
|
|
qapi_free_AnnounceParameters(params);
|
2019-02-27 14:24:12 +01:00
|
|
|
}
|
|
|
|
|
2011-11-28 01:54:09 +01:00
|
|
|
void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
qmp_migrate_cancel(NULL);
|
|
|
|
}
|
2011-11-28 02:18:01 +01:00
|
|
|
|
2017-10-20 11:05:54 +02:00
|
|
|
void hmp_migrate_continue(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *state = qdict_get_str(qdict, "state");
|
|
|
|
int val = qapi_enum_parse(&MigrationStatus_lookup, state, -1, &err);
|
|
|
|
|
|
|
|
if (val >= 0) {
|
|
|
|
qmp_migrate_continue(val, &err);
|
|
|
|
}
|
|
|
|
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2017-10-20 11:05:54 +02:00
|
|
|
}
|
|
|
|
|
2015-02-19 12:40:28 +01:00
|
|
|
void hmp_migrate_incoming(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *uri = qdict_get_str(qdict, "uri");
|
|
|
|
|
|
|
|
qmp_migrate_incoming(uri, &err);
|
|
|
|
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2015-02-19 12:40:28 +01:00
|
|
|
}
|
|
|
|
|
2018-05-02 12:47:37 +02:00
|
|
|
void hmp_migrate_recover(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *uri = qdict_get_str(qdict, "uri");
|
|
|
|
|
|
|
|
qmp_migrate_recover(uri, &err);
|
|
|
|
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2018-05-02 12:47:37 +02:00
|
|
|
}
|
|
|
|
|
2018-05-02 12:47:40 +02:00
|
|
|
void hmp_migrate_pause(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_migrate_pause(&err);
|
|
|
|
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2018-05-02 12:47:40 +02:00
|
|
|
}
|
|
|
|
|
2011-12-07 14:17:51 +01:00
|
|
|
|
2012-08-06 20:42:48 +02:00
|
|
|
void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *cap = qdict_get_str(qdict, "capability");
|
|
|
|
bool state = qdict_get_bool(qdict, "state");
|
|
|
|
Error *err = NULL;
|
2020-11-13 02:13:37 +01:00
|
|
|
MigrationCapabilityStatusList *caps = NULL;
|
|
|
|
MigrationCapabilityStatus *value;
|
2017-08-24 10:46:00 +02:00
|
|
|
int val;
|
2012-08-06 20:42:48 +02:00
|
|
|
|
2017-08-24 10:46:10 +02:00
|
|
|
val = qapi_enum_parse(&MigrationCapability_lookup, cap, -1, &err);
|
2017-08-24 10:46:00 +02:00
|
|
|
if (val < 0) {
|
|
|
|
goto end;
|
2012-08-06 20:42:48 +02:00
|
|
|
}
|
|
|
|
|
2020-11-13 02:13:37 +01:00
|
|
|
value = g_malloc0(sizeof(*value));
|
|
|
|
value->capability = val;
|
|
|
|
value->state = state;
|
|
|
|
QAPI_LIST_PREPEND(caps, value);
|
2017-08-24 10:46:00 +02:00
|
|
|
qmp_migrate_set_capabilities(caps, &err);
|
2020-11-13 02:13:37 +01:00
|
|
|
qapi_free_MigrationCapabilityStatusList(caps);
|
2012-08-06 20:42:48 +02:00
|
|
|
|
2017-08-24 10:46:00 +02:00
|
|
|
end:
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2012-08-06 20:42:48 +02:00
|
|
|
}
|
|
|
|
|
2015-03-23 09:32:29 +01:00
|
|
|
void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *param = qdict_get_str(qdict, "parameter");
|
2016-04-27 12:05:15 +02:00
|
|
|
const char *valuestr = qdict_get_str(qdict, "value");
|
2017-05-16 11:37:45 +02:00
|
|
|
Visitor *v = string_input_visitor_new(valuestr);
|
migration: Unshare MigrationParameters struct for now
Commit de63ab6 "migrate: Share common MigrationParameters struct"
reused MigrationParameters for the arguments of
migrate-set-parameters, with the following rationale:
It is rather verbose, and slightly error-prone, to repeat
the same set of parameters for input (migrate-set-parameters)
as for output (query-migrate-parameters), where the only
difference is whether the members are optional. We can just
document that the optional members will always be present
on output, and then share a common struct between both
commands. The next patch can then reduce the amount of
code needed on input.
I need to unshare them to correct a design flaw in a stupid, but
minimally invasive way, in the next commit. We can restore the
sharing when we redo that patch in a less stupid way. Add a suitable
TODO comment.
Note that I revert only the sharing part of commit de63ab6, not the
part that made the members of query-migrate-parameters' result
optional. The schema (and thus introspection) remains inaccurate for
query-migrate-parameters. If we decide not to restore the sharing, we
should revert that part, too.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2017-07-18 13:42:11 +02:00
|
|
|
MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
|
2017-02-21 21:14:07 +01:00
|
|
|
uint64_t valuebw = 0;
|
2017-10-05 21:30:10 +02:00
|
|
|
uint64_t cache_size;
|
2015-03-23 09:32:29 +01:00
|
|
|
Error *err = NULL;
|
2017-08-24 10:46:01 +02:00
|
|
|
int val, ret;
|
2016-04-27 12:05:15 +02:00
|
|
|
|
2017-08-24 10:46:10 +02:00
|
|
|
val = qapi_enum_parse(&MigrationParameter_lookup, param, -1, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
if (val < 0) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (val) {
|
|
|
|
case MIGRATION_PARAMETER_COMPRESS_LEVEL:
|
|
|
|
p->has_compress_level = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->compress_level, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_COMPRESS_THREADS:
|
|
|
|
p->has_compress_threads = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->compress_threads, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
break;
|
2018-08-21 10:10:20 +02:00
|
|
|
case MIGRATION_PARAMETER_COMPRESS_WAIT_THREAD:
|
|
|
|
p->has_compress_wait_thread = true;
|
|
|
|
visit_type_bool(v, param, &p->compress_wait_thread, &err);
|
|
|
|
break;
|
2017-08-24 10:46:01 +02:00
|
|
|
case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
|
|
|
|
p->has_decompress_threads = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->decompress_threads, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
break;
|
2020-02-24 03:31:42 +01:00
|
|
|
case MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD:
|
|
|
|
p->has_throttle_trigger_threshold = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->throttle_trigger_threshold, &err);
|
2020-03-18 08:16:20 +01:00
|
|
|
break;
|
2017-08-24 10:46:01 +02:00
|
|
|
case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
|
|
|
|
p->has_cpu_throttle_initial = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->cpu_throttle_initial, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
|
|
|
|
p->has_cpu_throttle_increment = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->cpu_throttle_increment, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
break;
|
2020-04-13 12:15:08 +02:00
|
|
|
case MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW:
|
|
|
|
p->has_cpu_throttle_tailslow = true;
|
|
|
|
visit_type_bool(v, param, &p->cpu_throttle_tailslow, &err);
|
|
|
|
break;
|
2018-08-01 15:00:20 +02:00
|
|
|
case MIGRATION_PARAMETER_MAX_CPU_THROTTLE:
|
|
|
|
p->has_max_cpu_throttle = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->max_cpu_throttle, &err);
|
2018-08-01 15:00:20 +02:00
|
|
|
break;
|
2017-08-24 10:46:01 +02:00
|
|
|
case MIGRATION_PARAMETER_TLS_CREDS:
|
|
|
|
p->tls_creds = g_new0(StrOrNull, 1);
|
|
|
|
p->tls_creds->type = QTYPE_QSTRING;
|
|
|
|
visit_type_str(v, param, &p->tls_creds->u.s, &err);
|
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_TLS_HOSTNAME:
|
|
|
|
p->tls_hostname = g_new0(StrOrNull, 1);
|
|
|
|
p->tls_hostname->type = QTYPE_QSTRING;
|
|
|
|
visit_type_str(v, param, &p->tls_hostname->u.s, &err);
|
|
|
|
break;
|
migration: add support for a "tls-authz" migration parameter
The QEMU instance that runs as the server for the migration data
transport (ie the target QEMU) needs to be able to configure access
control so it can prevent unauthorized clients initiating an incoming
migration. This adds a new 'tls-authz' migration parameter that is used
to provide the QOM ID of a QAuthZ subclass instance that provides the
access control check. This is checked against the x509 certificate
obtained during the TLS handshake.
For example, when starting a QEMU for incoming migration, it is
possible to give an example identity of the source QEMU that is
intended to be connecting later:
$QEMU \
-monitor stdio \
-incoming defer \
...other args...
(qemu) object_add tls-creds-x509,id=tls0,dir=/home/berrange/qemutls,\
endpoint=server,verify-peer=yes \
(qemu) object_add authz-simple,id=auth0,identity=CN=laptop.example.com,,\
O=Example Org,,L=London,,ST=London,,C=GB \
(qemu) migrate_incoming tcp:localhost:9000
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
2019-02-27 15:53:24 +01:00
|
|
|
case MIGRATION_PARAMETER_TLS_AUTHZ:
|
|
|
|
p->tls_authz = g_new0(StrOrNull, 1);
|
|
|
|
p->tls_authz->type = QTYPE_QSTRING;
|
|
|
|
visit_type_str(v, param, &p->tls_authz->u.s, &err);
|
|
|
|
break;
|
2017-08-24 10:46:01 +02:00
|
|
|
case MIGRATION_PARAMETER_MAX_BANDWIDTH:
|
|
|
|
p->has_max_bandwidth = true;
|
|
|
|
/*
|
|
|
|
* Can't use visit_type_size() here, because it
|
|
|
|
* defaults to Bytes rather than Mebibytes.
|
|
|
|
*/
|
|
|
|
ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
|
|
|
|
if (ret < 0 || valuebw > INT64_MAX
|
|
|
|
|| (size_t)valuebw != valuebw) {
|
|
|
|
error_setg(&err, "Invalid size %s", valuestr);
|
2015-03-23 09:32:29 +01:00
|
|
|
break;
|
|
|
|
}
|
2017-08-24 10:46:01 +02:00
|
|
|
p->max_bandwidth = valuebw;
|
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
|
|
|
|
p->has_downtime_limit = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_size(v, param, &p->downtime_limit, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
|
|
|
|
p->has_x_checkpoint_delay = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint32(v, param, &p->x_checkpoint_delay, &err);
|
2017-08-24 10:46:01 +02:00
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_BLOCK_INCREMENTAL:
|
|
|
|
p->has_block_incremental = true;
|
|
|
|
visit_type_bool(v, param, &p->block_incremental, &err);
|
|
|
|
break;
|
2019-02-06 13:54:06 +01:00
|
|
|
case MIGRATION_PARAMETER_MULTIFD_CHANNELS:
|
|
|
|
p->has_multifd_channels = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->multifd_channels, &err);
|
2016-01-15 08:56:17 +01:00
|
|
|
break;
|
2019-01-16 10:35:55 +01:00
|
|
|
case MIGRATION_PARAMETER_MULTIFD_COMPRESSION:
|
|
|
|
p->has_multifd_compression = true;
|
2020-07-07 18:05:44 +02:00
|
|
|
visit_type_MultiFDCompression(v, param, &p->multifd_compression,
|
|
|
|
&err);
|
2019-01-16 10:35:55 +01:00
|
|
|
break;
|
2020-01-23 17:08:52 +01:00
|
|
|
case MIGRATION_PARAMETER_MULTIFD_ZLIB_LEVEL:
|
|
|
|
p->has_multifd_zlib_level = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->multifd_zlib_level, &err);
|
2020-01-23 17:08:52 +01:00
|
|
|
break;
|
2020-01-23 17:41:36 +01:00
|
|
|
case MIGRATION_PARAMETER_MULTIFD_ZSTD_LEVEL:
|
|
|
|
p->has_multifd_zstd_level = true;
|
2021-02-02 15:17:31 +01:00
|
|
|
visit_type_uint8(v, param, &p->multifd_zstd_level, &err);
|
2020-01-23 17:41:36 +01:00
|
|
|
break;
|
2017-10-05 21:30:10 +02:00
|
|
|
case MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE:
|
|
|
|
p->has_xbzrle_cache_size = true;
|
2020-07-07 18:05:46 +02:00
|
|
|
if (!visit_type_size(v, param, &cache_size, &err)) {
|
2019-04-03 13:49:51 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (cache_size > INT64_MAX || (size_t)cache_size != cache_size) {
|
2017-10-05 21:30:10 +02:00
|
|
|
error_setg(&err, "Invalid size %s", valuestr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p->xbzrle_cache_size = cache_size;
|
|
|
|
break;
|
2018-06-13 12:26:40 +02:00
|
|
|
case MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH:
|
|
|
|
p->has_max_postcopy_bandwidth = true;
|
|
|
|
visit_type_size(v, param, &p->max_postcopy_bandwidth, &err);
|
|
|
|
break;
|
2019-02-27 14:24:06 +01:00
|
|
|
case MIGRATION_PARAMETER_ANNOUNCE_INITIAL:
|
|
|
|
p->has_announce_initial = true;
|
|
|
|
visit_type_size(v, param, &p->announce_initial, &err);
|
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_ANNOUNCE_MAX:
|
|
|
|
p->has_announce_max = true;
|
|
|
|
visit_type_size(v, param, &p->announce_max, &err);
|
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_ANNOUNCE_ROUNDS:
|
|
|
|
p->has_announce_rounds = true;
|
|
|
|
visit_type_size(v, param, &p->announce_rounds, &err);
|
|
|
|
break;
|
|
|
|
case MIGRATION_PARAMETER_ANNOUNCE_STEP:
|
|
|
|
p->has_announce_step = true;
|
|
|
|
visit_type_size(v, param, &p->announce_step, &err);
|
|
|
|
break;
|
2020-08-20 17:07:23 +02:00
|
|
|
case MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING:
|
|
|
|
error_setg(&err, "The block-bitmap-mapping parameter can only be set "
|
|
|
|
"through QMP");
|
|
|
|
break;
|
2017-08-24 10:46:01 +02:00
|
|
|
default:
|
|
|
|
assert(0);
|
2015-03-23 09:32:29 +01:00
|
|
|
}
|
|
|
|
|
2017-08-24 10:46:01 +02:00
|
|
|
if (err) {
|
|
|
|
goto cleanup;
|
2015-03-23 09:32:29 +01:00
|
|
|
}
|
|
|
|
|
2017-08-24 10:46:01 +02:00
|
|
|
qmp_migrate_set_parameters(p, &err);
|
|
|
|
|
2016-04-27 12:05:15 +02:00
|
|
|
cleanup:
|
migration: Unshare MigrationParameters struct for now
Commit de63ab6 "migrate: Share common MigrationParameters struct"
reused MigrationParameters for the arguments of
migrate-set-parameters, with the following rationale:
It is rather verbose, and slightly error-prone, to repeat
the same set of parameters for input (migrate-set-parameters)
as for output (query-migrate-parameters), where the only
difference is whether the members are optional. We can just
document that the optional members will always be present
on output, and then share a common struct between both
commands. The next patch can then reduce the amount of
code needed on input.
I need to unshare them to correct a design flaw in a stupid, but
minimally invasive way, in the next commit. We can restore the
sharing when we redo that patch in a less stupid way. Add a suitable
TODO comment.
Note that I revert only the sharing part of commit de63ab6, not the
part that made the members of query-migrate-parameters' result
optional. The schema (and thus introspection) remains inaccurate for
query-migrate-parameters. If we decide not to restore the sharing, we
should revert that part, too.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
2017-07-18 13:42:11 +02:00
|
|
|
qapi_free_MigrateSetParameters(p);
|
2017-05-16 11:37:45 +02:00
|
|
|
visit_free(v);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2015-03-23 09:32:29 +01:00
|
|
|
}
|
|
|
|
|
2015-03-05 17:29:02 +01:00
|
|
|
void hmp_client_migrate_info(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *protocol = qdict_get_str(qdict, "protocol");
|
|
|
|
const char *hostname = qdict_get_str(qdict, "hostname");
|
|
|
|
bool has_port = qdict_haskey(qdict, "port");
|
|
|
|
int port = qdict_get_try_int(qdict, "port", -1);
|
|
|
|
bool has_tls_port = qdict_haskey(qdict, "tls-port");
|
|
|
|
int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
|
|
|
|
const char *cert_subject = qdict_get_try_str(qdict, "cert-subject");
|
|
|
|
|
|
|
|
qmp_client_migrate_info(protocol, hostname,
|
|
|
|
has_port, port, has_tls_port, tls_port,
|
2022-11-04 17:06:58 +01:00
|
|
|
cert_subject, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2015-03-05 17:29:02 +01:00
|
|
|
}
|
|
|
|
|
2015-11-05 19:10:56 +01:00
|
|
|
void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
qmp_migrate_start_postcopy(&err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2015-11-05 19:10:56 +01:00
|
|
|
}
|
|
|
|
|
COLO: Add 'x-colo-lost-heartbeat' command to trigger failover
We leave users to choose whatever heartbeat solution they want,
if the heartbeat is lost, or other errors they detect, they can use
experimental command 'x_colo_lost_heartbeat' to tell COLO to do failover,
COLO will do operations accordingly.
For example, if the command is sent to the Primary side,
the Primary side will exit COLO mode, does cleanup work,
and then, PVM will take over the service work. If sent to the Secondary side,
the Secondary side will run failover work, then takes over PVM's service work.
Cc: Luiz Capitulino <lcapitulino@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Amit Shah <amit@amitshah.net>
2016-10-27 08:43:03 +02:00
|
|
|
void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_x_colo_lost_heartbeat(&err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
COLO: Add 'x-colo-lost-heartbeat' command to trigger failover
We leave users to choose whatever heartbeat solution they want,
if the heartbeat is lost, or other errors they detect, they can use
experimental command 'x_colo_lost_heartbeat' to tell COLO to do failover,
COLO will do operations accordingly.
For example, if the command is sent to the Primary side,
the Primary side will exit COLO mode, does cleanup work,
and then, PVM will take over the service work. If sent to the Secondary side,
the Secondary side will run failover work, then takes over PVM's service work.
Cc: Luiz Capitulino <lcapitulino@redhat.com>
Cc: Eric Blake <eblake@redhat.com>
Cc: Markus Armbruster <armbru@redhat.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Amit Shah <amit@amitshah.net>
2016-10-27 08:43:03 +02:00
|
|
|
}
|
|
|
|
|
2011-12-08 14:13:50 +01:00
|
|
|
void hmp_change(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *device = qdict_get_str(qdict, "device");
|
|
|
|
const char *target = qdict_get_str(qdict, "target");
|
|
|
|
const char *arg = qdict_get_try_str(qdict, "arg");
|
2015-10-26 21:39:18 +01:00
|
|
|
const char *read_only = qdict_get_try_str(qdict, "read-only-mode");
|
2022-04-13 00:18:46 +02:00
|
|
|
bool force = qdict_get_try_bool(qdict, "force", false);
|
2015-10-26 21:39:18 +01:00
|
|
|
BlockdevChangeReadOnlyMode read_only_mode = 0;
|
2011-12-08 14:13:50 +01:00
|
|
|
Error *err = NULL;
|
|
|
|
|
qapi: add conditions to VNC type/commands/events on the schema
Add #if defined(CONFIG_VNC) in generated code, and adjust the
qmp/hmp code accordingly.
query-qmp-schema no longer reports the command/events etc as
available when disabled at compile.
Commands made conditional:
* query-vnc, query-vnc-servers, change-vnc-password
Before the patch, the commands for !CONFIG_VNC are stubs that fail
like this:
{"error": {"class": "GenericError",
"desc": "The feature 'vnc' is not enabled"}}
Afterwards, they fail like this:
{"error": {"class": "CommandNotFound",
"desc": "The command FOO has not been found"}}
I call that an improvement, because it lets clients distinguish
between command unavailable (class CommandNotFound) and command failed
(class GenericError).
Events made conditional:
* VNC_CONNECTED, VNC_INITIALIZED, VNC_DISCONNECTED
HMP change:
* info vnc
Will return "unknown command: 'info vnc'" when VNC is compiled
out (same as error for spice when --disable-spice)
Occurrences of VNC (case insensitive) in the schema that aren't
covered by this change:
* add_client
Command has other uses, including "socket bases character devices".
These are unconditional as far as I can tell.
* set_password, expire_password
In theory, these commands could be used for managing any service's
password. In practice, they're used for VNC and SPICE services.
They're documented for "remote display session" / "remote display
server".
The service is selected by argument @protocol. The code special-cases
protocol-specific argument checking, then calls a protocol-specific
function to do the work. If it fails, the command fails with "Could
not set password". It does when the service isn't compiled in (it's a
stub then).
We could make these commands conditional on the conjunction of all
services [currently: defined(CONFIG_VNC) || defined(CONFIG_SPICE)],
but I doubt it's worthwhile.
* change
Command has other uses, namely changing media.
This patch inlines a stub; no functional change.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180703155648.11933-14-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2018-07-03 17:56:47 +02:00
|
|
|
#ifdef CONFIG_VNC
|
2015-10-26 21:39:16 +01:00
|
|
|
if (strcmp(device, "vnc") == 0) {
|
2023-01-09 20:03:17 +01:00
|
|
|
hmp_change_vnc(mon, device, target, arg, read_only, force, &err);
|
qapi: add conditions to VNC type/commands/events on the schema
Add #if defined(CONFIG_VNC) in generated code, and adjust the
qmp/hmp code accordingly.
query-qmp-schema no longer reports the command/events etc as
available when disabled at compile.
Commands made conditional:
* query-vnc, query-vnc-servers, change-vnc-password
Before the patch, the commands for !CONFIG_VNC are stubs that fail
like this:
{"error": {"class": "GenericError",
"desc": "The feature 'vnc' is not enabled"}}
Afterwards, they fail like this:
{"error": {"class": "CommandNotFound",
"desc": "The command FOO has not been found"}}
I call that an improvement, because it lets clients distinguish
between command unavailable (class CommandNotFound) and command failed
(class GenericError).
Events made conditional:
* VNC_CONNECTED, VNC_INITIALIZED, VNC_DISCONNECTED
HMP change:
* info vnc
Will return "unknown command: 'info vnc'" when VNC is compiled
out (same as error for spice when --disable-spice)
Occurrences of VNC (case insensitive) in the schema that aren't
covered by this change:
* add_client
Command has other uses, including "socket bases character devices".
These are unconditional as far as I can tell.
* set_password, expire_password
In theory, these commands could be used for managing any service's
password. In practice, they're used for VNC and SPICE services.
They're documented for "remote display session" / "remote display
server".
The service is selected by argument @protocol. The code special-cases
protocol-specific argument checking, then calls a protocol-specific
function to do the work. If it fails, the command fails with "Could
not set password". It does when the service isn't compiled in (it's a
stub then).
We could make these commands conditional on the conjunction of all
services [currently: defined(CONFIG_VNC) || defined(CONFIG_SPICE)],
but I doubt it's worthwhile.
* change
Command has other uses, namely changing media.
This patch inlines a stub; no functional change.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180703155648.11933-14-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2018-07-03 17:56:47 +02:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2015-10-26 21:39:18 +01:00
|
|
|
if (read_only) {
|
|
|
|
read_only_mode =
|
2017-08-24 10:46:10 +02:00
|
|
|
qapi_enum_parse(&BlockdevChangeReadOnlyMode_lookup,
|
2017-08-24 10:45:57 +02:00
|
|
|
read_only,
|
2015-10-26 21:39:18 +01:00
|
|
|
BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN, &err);
|
|
|
|
if (err) {
|
2020-06-03 10:09:01 +02:00
|
|
|
goto end;
|
2015-10-26 21:39:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:06:52 +01:00
|
|
|
qmp_blockdev_change_medium(device, NULL, target, arg, true, force,
|
2022-04-13 00:18:46 +02:00
|
|
|
!!read_only, read_only_mode,
|
2016-09-20 13:38:47 +02:00
|
|
|
&err);
|
2011-12-08 14:13:50 +01:00
|
|
|
}
|
|
|
|
|
2020-06-03 10:09:01 +02:00
|
|
|
end:
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2011-12-08 14:13:50 +01:00
|
|
|
}
|
2011-12-14 19:49:14 +01:00
|
|
|
|
2020-11-25 02:45:12 +01:00
|
|
|
typedef struct HMPMigrationStatus {
|
2011-12-05 17:48:01 +01:00
|
|
|
QEMUTimer *timer;
|
|
|
|
Monitor *mon;
|
|
|
|
bool is_block_migration;
|
2015-03-13 09:08:39 +01:00
|
|
|
} HMPMigrationStatus;
|
2011-12-05 17:48:01 +01:00
|
|
|
|
|
|
|
static void hmp_migrate_status_cb(void *opaque)
|
|
|
|
{
|
2015-03-13 09:08:39 +01:00
|
|
|
HMPMigrationStatus *status = opaque;
|
2011-12-05 17:48:01 +01:00
|
|
|
MigrationInfo *info;
|
|
|
|
|
|
|
|
info = qmp_query_migrate(NULL);
|
2015-03-13 09:08:40 +01:00
|
|
|
if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE ||
|
|
|
|
info->status == MIGRATION_STATUS_SETUP) {
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->disk) {
|
2011-12-05 17:48:01 +01:00
|
|
|
int progress;
|
|
|
|
|
|
|
|
if (info->disk->remaining) {
|
|
|
|
progress = info->disk->transferred * 100 / info->disk->total;
|
|
|
|
} else {
|
|
|
|
progress = 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(status->mon, "Completed %d %%\r", progress);
|
|
|
|
monitor_flush(status->mon);
|
|
|
|
}
|
|
|
|
|
2013-08-21 17:03:08 +02:00
|
|
|
timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
|
2011-12-05 17:48:01 +01:00
|
|
|
} else {
|
|
|
|
if (status->is_block_migration) {
|
|
|
|
monitor_printf(status->mon, "\n");
|
|
|
|
}
|
2022-11-04 17:06:58 +01:00
|
|
|
if (info->error_desc) {
|
migration: add reporting of errors for outgoing migration
Currently if an application initiates an outgoing migration,
it may or may not, get an error reported back on failure. If
the error occurs synchronously to the 'migrate' command
execution, the client app will see the error message. This
is the case for DNS lookup failures. If the error occurs
asynchronously to the monitor command though, the error
will be thrown away and the client left guessing about
what went wrong. This is the case for failure to connect
to the TCP server (eg due to wrong port, or firewall
rules, or other similar errors).
In the future we'll be adding more scope for errors to
happen asynchronously with the TLS protocol handshake.
TLS errors are hard to diagnose even when they are well
reported, so discarding errors entirely will make it
impossible to debug TLS connection problems.
Management apps which do migration are already using
'query-migrate' / 'info migrate' to check up on progress
of background migration operations and to see their end
status. This is a fine place to also include the error
message when things go wrong.
This patch thus adds an 'error-desc' field to the
MigrationInfo struct, which will be populated when
the 'status' is set to 'failed':
(qemu) migrate -d tcp:localhost:9001
(qemu) info migrate
capabilities: xbzrle: off rdma-pin-all: off auto-converge: off zero-blocks: off compress: off events: off x-postcopy-ram: off
Migration status: failed (Error connecting to socket: Connection refused)
total time: 0 milliseconds
In the HMP, when doing non-detached migration, it is
also possible to display this error message directly
to the app.
(qemu) migrate tcp:localhost:9001
Error connecting to socket: Connection refused
Or with QMP
{
"execute": "query-migrate",
"arguments": {}
}
{
"return": {
"status": "failed",
"error-desc": "address resolution failed for myhost:9000: No address associated with hostname"
}
}
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Message-Id: <1461751518-12128-11-git-send-email-berrange@redhat.com>
Signed-off-by: Amit Shah <amit.shah@redhat.com>
2016-04-27 12:05:00 +02:00
|
|
|
error_report("%s", info->error_desc);
|
|
|
|
}
|
2011-12-05 17:48:01 +01:00
|
|
|
monitor_resume(status->mon);
|
2018-09-01 15:46:52 +02:00
|
|
|
timer_free(status->timer);
|
2011-12-05 17:48:01 +01:00
|
|
|
g_free(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_MigrationInfo(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_migrate(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2015-05-16 00:25:00 +02:00
|
|
|
bool detach = qdict_get_try_bool(qdict, "detach", false);
|
|
|
|
bool blk = qdict_get_try_bool(qdict, "blk", false);
|
|
|
|
bool inc = qdict_get_try_bool(qdict, "inc", false);
|
2018-05-02 12:47:23 +02:00
|
|
|
bool resume = qdict_get_try_bool(qdict, "resume", false);
|
2011-12-05 17:48:01 +01:00
|
|
|
const char *uri = qdict_get_str(qdict, "uri");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2018-05-02 12:47:23 +02:00
|
|
|
qmp_migrate(uri, !!blk, blk, !!inc, inc,
|
|
|
|
false, false, true, resume, &err);
|
2021-10-28 17:18:25 +02:00
|
|
|
if (hmp_handle_error(mon, err)) {
|
2011-12-05 17:48:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!detach) {
|
2015-03-13 09:08:39 +01:00
|
|
|
HMPMigrationStatus *status;
|
2011-12-05 17:48:01 +01:00
|
|
|
|
|
|
|
if (monitor_suspend(mon) < 0) {
|
|
|
|
monitor_printf(mon, "terminal does not allow synchronous "
|
|
|
|
"migration, continuing detached\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = g_malloc0(sizeof(*status));
|
|
|
|
status->mon = mon;
|
|
|
|
status->is_block_migration = blk || inc;
|
2013-08-21 17:03:08 +02:00
|
|
|
status->timer = timer_new_ms(QEMU_CLOCK_REALTIME, hmp_migrate_status_cb,
|
2011-12-05 17:48:01 +01:00
|
|
|
status);
|
2013-08-21 17:03:08 +02:00
|
|
|
timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
|
2011-12-05 17:48:01 +01:00
|
|
|
}
|
|
|
|
}
|
2012-03-29 17:38:50 +02:00
|
|
|
|
2012-04-18 22:34:15 +02:00
|
|
|
void hmp_netdev_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
QemuOpts *opts;
|
2020-11-11 11:52:22 +01:00
|
|
|
const char *type = qdict_get_try_str(qdict, "type");
|
2012-04-18 22:34:15 +02:00
|
|
|
|
2020-11-11 11:52:22 +01:00
|
|
|
if (type && is_help_option(type)) {
|
|
|
|
show_netdevs();
|
|
|
|
return;
|
|
|
|
}
|
2012-04-18 22:34:15 +02:00
|
|
|
opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
|
2014-01-30 15:07:28 +01:00
|
|
|
if (err) {
|
2012-04-18 22:34:15 +02:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
netdev_add(opts, &err);
|
2014-01-30 15:07:28 +01:00
|
|
|
if (err) {
|
2012-04-18 22:34:15 +02:00
|
|
|
qemu_opts_del(opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2012-04-18 22:34:15 +02:00
|
|
|
}
|
2012-04-16 19:36:32 +02:00
|
|
|
|
|
|
|
void hmp_netdev_del(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *id = qdict_get_str(qdict, "id");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
qmp_netdev_del(id, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2012-04-16 19:36:32 +02:00
|
|
|
}
|
2012-06-22 20:36:09 +02:00
|
|
|
|
2013-12-20 23:21:10 +01:00
|
|
|
void hmp_object_add(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
2021-02-17 15:27:54 +01:00
|
|
|
const char *options = qdict_get_str(qdict, "object");
|
2013-12-20 23:21:10 +01:00
|
|
|
Error *err = NULL;
|
|
|
|
|
2021-02-17 15:27:54 +01:00
|
|
|
user_creatable_add_from_str(options, &err);
|
2020-06-03 10:09:00 +02:00
|
|
|
hmp_handle_error(mon, err);
|
2013-12-20 23:21:10 +01:00
|
|
|
}
|
|
|
|
|
2012-06-22 20:36:09 +02:00
|
|
|
void hmp_getfd(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *fdname = qdict_get_str(qdict, "fdname");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2012-06-22 20:36:09 +02:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_getfd(fdname, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2012-06-22 20:36:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_closefd(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *fdname = qdict_get_str(qdict, "fdname");
|
2014-05-02 13:26:29 +02:00
|
|
|
Error *err = NULL;
|
2012-06-22 20:36:09 +02:00
|
|
|
|
2014-05-02 13:26:29 +02:00
|
|
|
qmp_closefd(fdname, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2012-06-22 20:36:09 +02:00
|
|
|
}
|
2012-08-31 04:56:26 +02:00
|
|
|
|
2013-12-20 23:21:09 +01:00
|
|
|
void hmp_object_del(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *id = qdict_get_str(qdict, "id");
|
|
|
|
Error *err = NULL;
|
|
|
|
|
2016-02-10 19:40:59 +01:00
|
|
|
user_creatable_del(id, &err);
|
2019-12-05 18:46:18 +01:00
|
|
|
hmp_handle_error(mon, err);
|
2013-12-20 23:21:09 +01:00
|
|
|
}
|
2014-05-14 11:43:35 +02:00
|
|
|
|
2015-06-26 10:07:13 +02:00
|
|
|
void hmp_info_iothreads(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
IOThreadInfoList *info_list = qmp_query_iothreads(NULL);
|
|
|
|
IOThreadInfoList *info;
|
2017-02-10 10:41:17 +01:00
|
|
|
IOThreadInfo *value;
|
2015-06-26 10:07:13 +02:00
|
|
|
|
|
|
|
for (info = info_list; info; info = info->next) {
|
2017-02-10 10:41:17 +01:00
|
|
|
value = info->value;
|
|
|
|
monitor_printf(mon, "%s:\n", value->id);
|
|
|
|
monitor_printf(mon, " thread_id=%" PRId64 "\n", value->thread_id);
|
|
|
|
monitor_printf(mon, " poll-max-ns=%" PRId64 "\n", value->poll_max_ns);
|
|
|
|
monitor_printf(mon, " poll-grow=%" PRId64 "\n", value->poll_grow);
|
|
|
|
monitor_printf(mon, " poll-shrink=%" PRId64 "\n", value->poll_shrink);
|
2021-07-21 11:42:10 +02:00
|
|
|
monitor_printf(mon, " aio-max-batch=%" PRId64 "\n",
|
|
|
|
value->aio_max_batch);
|
2015-06-26 10:07:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_IOThreadInfoList(info_list);
|
|
|
|
}
|
|
|
|
|
2015-06-11 03:21:21 +02:00
|
|
|
void hmp_rocker(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
RockerSwitch *rocker;
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
rocker = qmp_query_rocker(name, &err);
|
2021-10-28 17:18:25 +02:00
|
|
|
if (hmp_handle_error(mon, err)) {
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "name: %s\n", rocker->name);
|
|
|
|
monitor_printf(mon, "id: 0x%" PRIx64 "\n", rocker->id);
|
|
|
|
monitor_printf(mon, "ports: %d\n", rocker->ports);
|
|
|
|
|
|
|
|
qapi_free_RockerSwitch(rocker);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_rocker_ports(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
RockerPortList *list, *port;
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
list = qmp_query_rocker_ports(name, &err);
|
2021-10-28 17:18:25 +02:00
|
|
|
if (hmp_handle_error(mon, err)) {
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, " ena/ speed/ auto\n");
|
|
|
|
monitor_printf(mon, " port link duplex neg?\n");
|
|
|
|
|
|
|
|
for (port = list; port; port = port->next) {
|
2021-10-09 17:24:01 +02:00
|
|
|
monitor_printf(mon, "%10s %-4s %-3s %2s %s\n",
|
2015-06-11 03:21:21 +02:00
|
|
|
port->value->name,
|
|
|
|
port->value->enabled ? port->value->link_up ?
|
|
|
|
"up" : "down" : "!ena",
|
|
|
|
port->value->speed == 10000 ? "10G" : "??",
|
|
|
|
port->value->duplex ? "FD" : "HD",
|
|
|
|
port->value->autoneg ? "Yes" : "No");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_RockerPortList(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
RockerOfDpaFlowList *list, *info;
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
uint32_t tbl_id = qdict_get_try_int(qdict, "tbl_id", -1);
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
list = qmp_query_rocker_of_dpa_flows(name, tbl_id != -1, tbl_id, &err);
|
2021-10-28 17:18:25 +02:00
|
|
|
if (hmp_handle_error(mon, err)) {
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "prio tbl hits key(mask) --> actions\n");
|
|
|
|
|
|
|
|
for (info = list; info; info = info->next) {
|
|
|
|
RockerOfDpaFlow *flow = info->value;
|
|
|
|
RockerOfDpaFlowKey *key = flow->key;
|
|
|
|
RockerOfDpaFlowMask *mask = flow->mask;
|
|
|
|
RockerOfDpaFlowAction *action = flow->action;
|
|
|
|
|
|
|
|
if (flow->hits) {
|
|
|
|
monitor_printf(mon, "%-4d %-3d %-4" PRIu64,
|
|
|
|
key->priority, key->tbl_id, flow->hits);
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, "%-4d %-3d ",
|
|
|
|
key->priority, key->tbl_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_in_pport) {
|
|
|
|
monitor_printf(mon, " pport %d", key->in_pport);
|
|
|
|
if (mask->has_in_pport) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->in_pport);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_vlan_id) {
|
|
|
|
monitor_printf(mon, " vlan %d",
|
|
|
|
key->vlan_id & VLAN_VID_MASK);
|
|
|
|
if (mask->has_vlan_id) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->vlan_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_tunnel_id) {
|
|
|
|
monitor_printf(mon, " tunnel %d", key->tunnel_id);
|
|
|
|
if (mask->has_tunnel_id) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->tunnel_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_eth_type) {
|
|
|
|
switch (key->eth_type) {
|
|
|
|
case 0x0806:
|
|
|
|
monitor_printf(mon, " ARP");
|
|
|
|
break;
|
|
|
|
case 0x0800:
|
|
|
|
monitor_printf(mon, " IP");
|
|
|
|
break;
|
|
|
|
case 0x86dd:
|
|
|
|
monitor_printf(mon, " IPv6");
|
|
|
|
break;
|
|
|
|
case 0x8809:
|
|
|
|
monitor_printf(mon, " LACP");
|
|
|
|
break;
|
|
|
|
case 0x88cc:
|
|
|
|
monitor_printf(mon, " LLDP");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
monitor_printf(mon, " eth type 0x%04x", key->eth_type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:07:04 +01:00
|
|
|
if (key->eth_src) {
|
2015-06-11 03:21:21 +02:00
|
|
|
if ((strcmp(key->eth_src, "01:00:00:00:00:00") == 0) &&
|
2022-11-04 17:07:04 +01:00
|
|
|
mask->eth_src &&
|
2015-06-11 03:21:21 +02:00
|
|
|
(strcmp(mask->eth_src, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " src <any mcast/bcast>");
|
|
|
|
} else if ((strcmp(key->eth_src, "00:00:00:00:00:00") == 0) &&
|
2022-11-04 17:07:04 +01:00
|
|
|
mask->eth_src &&
|
2015-06-11 03:21:21 +02:00
|
|
|
(strcmp(mask->eth_src, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " src <any ucast>");
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, " src %s", key->eth_src);
|
2022-11-04 17:07:04 +01:00
|
|
|
if (mask->eth_src) {
|
2015-06-11 03:21:21 +02:00
|
|
|
monitor_printf(mon, "(%s)", mask->eth_src);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:07:04 +01:00
|
|
|
if (key->eth_dst) {
|
2015-06-11 03:21:21 +02:00
|
|
|
if ((strcmp(key->eth_dst, "01:00:00:00:00:00") == 0) &&
|
2022-11-04 17:07:04 +01:00
|
|
|
mask->eth_dst &&
|
2015-06-11 03:21:21 +02:00
|
|
|
(strcmp(mask->eth_dst, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " dst <any mcast/bcast>");
|
|
|
|
} else if ((strcmp(key->eth_dst, "00:00:00:00:00:00") == 0) &&
|
2022-11-04 17:07:04 +01:00
|
|
|
mask->eth_dst &&
|
2015-06-11 03:21:21 +02:00
|
|
|
(strcmp(mask->eth_dst, "01:00:00:00:00:00") == 0)) {
|
|
|
|
monitor_printf(mon, " dst <any ucast>");
|
|
|
|
} else {
|
|
|
|
monitor_printf(mon, " dst %s", key->eth_dst);
|
2022-11-04 17:07:04 +01:00
|
|
|
if (mask->eth_dst) {
|
2015-06-11 03:21:21 +02:00
|
|
|
monitor_printf(mon, "(%s)", mask->eth_dst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_ip_proto) {
|
|
|
|
monitor_printf(mon, " proto %d", key->ip_proto);
|
|
|
|
if (mask->has_ip_proto) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->ip_proto);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (key->has_ip_tos) {
|
|
|
|
monitor_printf(mon, " TOS %d", key->ip_tos);
|
|
|
|
if (mask->has_ip_tos) {
|
|
|
|
monitor_printf(mon, "(0x%x)", mask->ip_tos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:07:04 +01:00
|
|
|
if (key->ip_dst) {
|
2015-06-11 03:21:21 +02:00
|
|
|
monitor_printf(mon, " dst %s", key->ip_dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_goto_tbl || action->has_group_id ||
|
|
|
|
action->has_new_vlan_id) {
|
|
|
|
monitor_printf(mon, " -->");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_new_vlan_id) {
|
|
|
|
monitor_printf(mon, " apply new vlan %d",
|
|
|
|
ntohs(action->new_vlan_id));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_group_id) {
|
|
|
|
monitor_printf(mon, " write group 0x%08x", action->group_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->has_goto_tbl) {
|
|
|
|
monitor_printf(mon, " goto tbl %d", action->goto_tbl);
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_RockerOfDpaFlowList(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
RockerOfDpaGroupList *list, *g;
|
|
|
|
const char *name = qdict_get_str(qdict, "name");
|
|
|
|
uint8_t type = qdict_get_try_int(qdict, "type", 9);
|
2015-12-18 16:35:27 +01:00
|
|
|
Error *err = NULL;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
2015-12-18 16:35:27 +01:00
|
|
|
list = qmp_query_rocker_of_dpa_groups(name, type != 9, type, &err);
|
2021-10-28 17:18:25 +02:00
|
|
|
if (hmp_handle_error(mon, err)) {
|
2015-06-11 03:21:21 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "id (decode) --> buckets\n");
|
|
|
|
|
|
|
|
for (g = list; g; g = g->next) {
|
|
|
|
RockerOfDpaGroup *group = g->value;
|
2020-03-02 14:07:15 +01:00
|
|
|
bool set = false;
|
2015-06-11 03:21:21 +02:00
|
|
|
|
|
|
|
monitor_printf(mon, "0x%08x", group->id);
|
|
|
|
|
|
|
|
monitor_printf(mon, " (type %s", group->type == 0 ? "L2 interface" :
|
|
|
|
group->type == 1 ? "L2 rewrite" :
|
|
|
|
group->type == 2 ? "L3 unicast" :
|
|
|
|
group->type == 3 ? "L2 multicast" :
|
|
|
|
group->type == 4 ? "L2 flood" :
|
|
|
|
group->type == 5 ? "L3 interface" :
|
|
|
|
group->type == 6 ? "L3 multicast" :
|
|
|
|
group->type == 7 ? "L3 ECMP" :
|
|
|
|
group->type == 8 ? "L2 overlay" :
|
|
|
|
"unknown");
|
|
|
|
|
|
|
|
if (group->has_vlan_id) {
|
|
|
|
monitor_printf(mon, " vlan %d", group->vlan_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_pport) {
|
|
|
|
monitor_printf(mon, " pport %d", group->pport);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_index) {
|
|
|
|
monitor_printf(mon, " index %d", group->index);
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, ") -->");
|
|
|
|
|
|
|
|
if (group->has_set_vlan_id && group->set_vlan_id) {
|
|
|
|
set = true;
|
|
|
|
monitor_printf(mon, " set vlan %d",
|
|
|
|
group->set_vlan_id & VLAN_VID_MASK);
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:07:04 +01:00
|
|
|
if (group->set_eth_src) {
|
2015-06-11 03:21:21 +02:00
|
|
|
if (!set) {
|
|
|
|
set = true;
|
|
|
|
monitor_printf(mon, " set");
|
|
|
|
}
|
|
|
|
monitor_printf(mon, " src %s", group->set_eth_src);
|
|
|
|
}
|
|
|
|
|
2022-11-04 17:07:04 +01:00
|
|
|
if (group->set_eth_dst) {
|
2015-06-11 03:21:21 +02:00
|
|
|
if (!set) {
|
|
|
|
monitor_printf(mon, " set");
|
|
|
|
}
|
|
|
|
monitor_printf(mon, " dst %s", group->set_eth_dst);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_ttl_check && group->ttl_check) {
|
|
|
|
monitor_printf(mon, " check TTL");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_group_id && group->group_id) {
|
|
|
|
monitor_printf(mon, " group id 0x%08x", group->group_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_pop_vlan && group->pop_vlan) {
|
|
|
|
monitor_printf(mon, " pop vlan");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_out_pport) {
|
|
|
|
monitor_printf(mon, " out pport %d", group->out_pport);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (group->has_group_ids) {
|
|
|
|
struct uint32List *id;
|
|
|
|
|
|
|
|
monitor_printf(mon, " groups [");
|
|
|
|
for (id = group->group_ids; id; id = id->next) {
|
|
|
|
monitor_printf(mon, "0x%08x", id->value);
|
|
|
|
if (id->next) {
|
|
|
|
monitor_printf(mon, ",");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "]");
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_RockerOfDpaGroupList(list);
|
|
|
|
}
|
2016-02-18 06:16:55 +01:00
|
|
|
|
2022-04-26 12:17:35 +02:00
|
|
|
static void print_stats_schema_value(Monitor *mon, StatsSchemaValue *value)
|
|
|
|
{
|
|
|
|
const char *unit = NULL;
|
|
|
|
monitor_printf(mon, " %s (%s%s", value->name, StatsType_str(value->type),
|
|
|
|
value->has_unit || value->exponent ? ", " : "");
|
|
|
|
|
|
|
|
if (value->has_unit) {
|
|
|
|
if (value->unit == STATS_UNIT_SECONDS) {
|
|
|
|
unit = "s";
|
|
|
|
} else if (value->unit == STATS_UNIT_BYTES) {
|
|
|
|
unit = "B";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (unit && value->base == 10 &&
|
|
|
|
value->exponent >= -18 && value->exponent <= 18 &&
|
|
|
|
value->exponent % 3 == 0) {
|
2022-09-29 13:42:12 +02:00
|
|
|
monitor_puts(mon, si_prefix(value->exponent));
|
2022-04-26 12:17:35 +02:00
|
|
|
} else if (unit && value->base == 2 &&
|
|
|
|
value->exponent >= 0 && value->exponent <= 60 &&
|
|
|
|
value->exponent % 10 == 0) {
|
|
|
|
|
2022-09-29 13:42:12 +02:00
|
|
|
monitor_puts(mon, iec_binary_prefix(value->exponent));
|
2022-04-26 12:17:35 +02:00
|
|
|
} else if (value->exponent) {
|
|
|
|
/* Use exponential notation and write the unit's English name */
|
|
|
|
monitor_printf(mon, "* %d^%d%s",
|
|
|
|
value->base, value->exponent,
|
|
|
|
value->has_unit ? " " : "");
|
|
|
|
unit = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value->has_unit) {
|
2022-09-29 13:42:12 +02:00
|
|
|
monitor_puts(mon, unit ? unit : StatsUnit_str(value->unit));
|
2022-04-26 12:17:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Print bucket size for linear histograms */
|
|
|
|
if (value->type == STATS_TYPE_LINEAR_HISTOGRAM && value->has_bucket_size) {
|
|
|
|
monitor_printf(mon, ", bucket size=%d", value->bucket_size);
|
|
|
|
}
|
|
|
|
monitor_printf(mon, ")");
|
|
|
|
}
|
|
|
|
|
|
|
|
static StatsSchemaValueList *find_schema_value_list(
|
|
|
|
StatsSchemaList *list, StatsProvider provider,
|
|
|
|
StatsTarget target)
|
|
|
|
{
|
|
|
|
StatsSchemaList *node;
|
|
|
|
|
|
|
|
for (node = list; node; node = node->next) {
|
|
|
|
if (node->value->provider == provider &&
|
|
|
|
node->value->target == target) {
|
|
|
|
return node->value->stats;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_stats_results(Monitor *mon, StatsTarget target,
|
2022-04-26 13:58:59 +02:00
|
|
|
bool show_provider,
|
2022-04-26 12:17:35 +02:00
|
|
|
StatsResult *result,
|
|
|
|
StatsSchemaList *schema)
|
|
|
|
{
|
|
|
|
/* Find provider schema */
|
|
|
|
StatsSchemaValueList *schema_value_list =
|
|
|
|
find_schema_value_list(schema, result->provider, target);
|
|
|
|
StatsList *stats_list;
|
|
|
|
|
|
|
|
if (!schema_value_list) {
|
|
|
|
monitor_printf(mon, "failed to find schema list for %s\n",
|
|
|
|
StatsProvider_str(result->provider));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-04-26 13:58:59 +02:00
|
|
|
if (show_provider) {
|
|
|
|
monitor_printf(mon, "provider: %s\n",
|
|
|
|
StatsProvider_str(result->provider));
|
|
|
|
}
|
2022-04-26 12:17:35 +02:00
|
|
|
|
|
|
|
for (stats_list = result->stats; stats_list;
|
|
|
|
stats_list = stats_list->next,
|
|
|
|
schema_value_list = schema_value_list->next) {
|
|
|
|
|
|
|
|
Stats *stats = stats_list->value;
|
|
|
|
StatsValue *stats_value = stats->value;
|
|
|
|
StatsSchemaValue *schema_value = schema_value_list->value;
|
|
|
|
|
|
|
|
/* Find schema entry */
|
|
|
|
while (!g_str_equal(stats->name, schema_value->name)) {
|
|
|
|
if (!schema_value_list->next) {
|
|
|
|
monitor_printf(mon, "failed to find schema entry for %s\n",
|
|
|
|
stats->name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
schema_value_list = schema_value_list->next;
|
|
|
|
schema_value = schema_value_list->value;
|
|
|
|
}
|
|
|
|
|
|
|
|
print_stats_schema_value(mon, schema_value);
|
|
|
|
|
|
|
|
if (stats_value->type == QTYPE_QNUM) {
|
|
|
|
monitor_printf(mon, ": %" PRId64 "\n", stats_value->u.scalar);
|
2022-07-14 14:08:09 +02:00
|
|
|
} else if (stats_value->type == QTYPE_QBOOL) {
|
|
|
|
monitor_printf(mon, ": %s\n", stats_value->u.boolean ? "yes" : "no");
|
2022-04-26 12:17:35 +02:00
|
|
|
} else if (stats_value->type == QTYPE_QLIST) {
|
|
|
|
uint64List *list;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
monitor_printf(mon, ": ");
|
|
|
|
for (list = stats_value->u.list, i = 1;
|
|
|
|
list;
|
|
|
|
list = list->next, i++) {
|
|
|
|
monitor_printf(mon, "[%d]=%" PRId64 " ", i, list->value);
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create the StatsFilter that is needed for an "info stats" invocation. */
|
2022-04-26 14:09:31 +02:00
|
|
|
static StatsFilter *stats_filter(StatsTarget target, const char *names,
|
|
|
|
int cpu_index, StatsProvider provider)
|
2022-04-26 12:17:35 +02:00
|
|
|
{
|
|
|
|
StatsFilter *filter = g_malloc0(sizeof(*filter));
|
2022-04-26 14:09:31 +02:00
|
|
|
StatsProvider provider_idx;
|
|
|
|
StatsRequestList *request_list = NULL;
|
2022-04-26 12:17:35 +02:00
|
|
|
|
|
|
|
filter->target = target;
|
|
|
|
switch (target) {
|
|
|
|
case STATS_TARGET_VM:
|
|
|
|
break;
|
|
|
|
case STATS_TARGET_VCPU:
|
|
|
|
{
|
|
|
|
strList *vcpu_list = NULL;
|
|
|
|
CPUState *cpu = qemu_get_cpu(cpu_index);
|
|
|
|
char *canonical_path = object_get_canonical_path(OBJECT(cpu));
|
|
|
|
|
|
|
|
QAPI_LIST_PREPEND(vcpu_list, canonical_path);
|
|
|
|
filter->u.vcpu.has_vcpus = true;
|
|
|
|
filter->u.vcpu.vcpus = vcpu_list;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2022-04-26 13:58:59 +02:00
|
|
|
|
2022-04-26 14:09:31 +02:00
|
|
|
if (!names && provider == STATS_PROVIDER__MAX) {
|
2022-04-26 13:58:59 +02:00
|
|
|
return filter;
|
|
|
|
}
|
|
|
|
|
2022-04-26 14:09:31 +02:00
|
|
|
/*
|
|
|
|
* "info stats" can only query either one or all the providers. Querying
|
|
|
|
* by name, but not by provider, requires the creation of one filter per
|
|
|
|
* provider.
|
|
|
|
*/
|
|
|
|
for (provider_idx = 0; provider_idx < STATS_PROVIDER__MAX; provider_idx++) {
|
|
|
|
if (provider == STATS_PROVIDER__MAX || provider == provider_idx) {
|
|
|
|
StatsRequest *request = g_new0(StatsRequest, 1);
|
|
|
|
request->provider = provider_idx;
|
|
|
|
if (names && !g_str_equal(names, "*")) {
|
|
|
|
request->has_names = true;
|
|
|
|
request->names = strList_from_comma_list(names);
|
|
|
|
}
|
|
|
|
QAPI_LIST_PREPEND(request_list, request);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-26 13:58:59 +02:00
|
|
|
filter->has_providers = true;
|
2022-04-26 14:09:31 +02:00
|
|
|
filter->providers = request_list;
|
2022-04-26 12:17:35 +02:00
|
|
|
return filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_info_stats(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
const char *target_str = qdict_get_str(qdict, "target");
|
2022-04-26 13:58:59 +02:00
|
|
|
const char *provider_str = qdict_get_try_str(qdict, "provider");
|
2022-04-26 14:09:31 +02:00
|
|
|
const char *names = qdict_get_try_str(qdict, "names");
|
2022-04-26 13:58:59 +02:00
|
|
|
|
|
|
|
StatsProvider provider = STATS_PROVIDER__MAX;
|
2022-04-26 12:17:35 +02:00
|
|
|
StatsTarget target;
|
|
|
|
Error *err = NULL;
|
|
|
|
g_autoptr(StatsSchemaList) schema = NULL;
|
|
|
|
g_autoptr(StatsResultList) stats = NULL;
|
|
|
|
g_autoptr(StatsFilter) filter = NULL;
|
|
|
|
StatsResultList *entry;
|
|
|
|
|
|
|
|
target = qapi_enum_parse(&StatsTarget_lookup, target_str, -1, &err);
|
|
|
|
if (err) {
|
|
|
|
monitor_printf(mon, "invalid stats target %s\n", target_str);
|
|
|
|
goto exit_no_print;
|
|
|
|
}
|
2022-04-26 13:58:59 +02:00
|
|
|
if (provider_str) {
|
|
|
|
provider = qapi_enum_parse(&StatsProvider_lookup, provider_str, -1, &err);
|
|
|
|
if (err) {
|
|
|
|
monitor_printf(mon, "invalid stats provider %s\n", provider_str);
|
|
|
|
goto exit_no_print;
|
|
|
|
}
|
|
|
|
}
|
2022-04-26 12:17:35 +02:00
|
|
|
|
2022-04-26 13:58:59 +02:00
|
|
|
schema = qmp_query_stats_schemas(provider_str ? true : false,
|
|
|
|
provider, &err);
|
2022-04-26 12:17:35 +02:00
|
|
|
if (err) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (target) {
|
|
|
|
case STATS_TARGET_VM:
|
2022-04-26 14:09:31 +02:00
|
|
|
filter = stats_filter(target, names, -1, provider);
|
2022-04-26 12:17:35 +02:00
|
|
|
break;
|
|
|
|
case STATS_TARGET_VCPU: {}
|
|
|
|
int cpu_index = monitor_get_cpu_index(mon);
|
2022-04-26 14:09:31 +02:00
|
|
|
filter = stats_filter(target, names, cpu_index, provider);
|
2022-04-26 12:17:35 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
stats = qmp_query_stats(filter, &err);
|
|
|
|
if (err) {
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
for (entry = stats; entry; entry = entry->next) {
|
2022-04-26 13:58:59 +02:00
|
|
|
print_stats_results(mon, target, provider_str == NULL, entry->value, schema);
|
2022-04-26 12:17:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if (err) {
|
|
|
|
monitor_printf(mon, "%s\n", error_get_pretty(err));
|
|
|
|
}
|
|
|
|
exit_no_print:
|
|
|
|
error_free(err);
|
|
|
|
}
|
2022-08-11 14:24:44 +02:00
|
|
|
|
|
|
|
static void hmp_virtio_dump_protocols(Monitor *mon,
|
|
|
|
VhostDeviceProtocols *pcol)
|
|
|
|
{
|
|
|
|
strList *pcol_list = pcol->protocols;
|
|
|
|
while (pcol_list) {
|
|
|
|
monitor_printf(mon, "\t%s", pcol_list->value);
|
|
|
|
pcol_list = pcol_list->next;
|
|
|
|
if (pcol_list != NULL) {
|
|
|
|
monitor_printf(mon, ",\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
if (pcol->has_unknown_protocols) {
|
|
|
|
monitor_printf(mon, " unknown-protocols(0x%016"PRIx64")\n",
|
|
|
|
pcol->unknown_protocols);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hmp_virtio_dump_status(Monitor *mon,
|
|
|
|
VirtioDeviceStatus *status)
|
|
|
|
{
|
|
|
|
strList *status_list = status->statuses;
|
|
|
|
while (status_list) {
|
|
|
|
monitor_printf(mon, "\t%s", status_list->value);
|
|
|
|
status_list = status_list->next;
|
|
|
|
if (status_list != NULL) {
|
|
|
|
monitor_printf(mon, ",\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
if (status->has_unknown_statuses) {
|
|
|
|
monitor_printf(mon, " unknown-statuses(0x%016"PRIx32")\n",
|
|
|
|
status->unknown_statuses);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void hmp_virtio_dump_features(Monitor *mon,
|
|
|
|
VirtioDeviceFeatures *features)
|
|
|
|
{
|
|
|
|
strList *transport_list = features->transports;
|
|
|
|
while (transport_list) {
|
|
|
|
monitor_printf(mon, "\t%s", transport_list->value);
|
|
|
|
transport_list = transport_list->next;
|
|
|
|
if (transport_list != NULL) {
|
|
|
|
monitor_printf(mon, ",\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
strList *list = features->dev_features;
|
|
|
|
if (list) {
|
|
|
|
while (list) {
|
|
|
|
monitor_printf(mon, "\t%s", list->value);
|
|
|
|
list = list->next;
|
|
|
|
if (list != NULL) {
|
|
|
|
monitor_printf(mon, ",\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (features->has_unknown_dev_features) {
|
|
|
|
monitor_printf(mon, " unknown-features(0x%016"PRIx64")\n",
|
|
|
|
features->unknown_dev_features);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_virtio_query(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
VirtioInfoList *list = qmp_x_query_virtio(&err);
|
|
|
|
VirtioInfoList *node;
|
|
|
|
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (list == NULL) {
|
|
|
|
monitor_printf(mon, "No VirtIO devices\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
node = list;
|
|
|
|
while (node) {
|
|
|
|
monitor_printf(mon, "%s [%s]\n", node->value->path,
|
|
|
|
node->value->name);
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
qapi_free_VirtioInfoList(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_virtio_status(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *path = qdict_get_try_str(qdict, "path");
|
|
|
|
VirtioStatus *s = qmp_x_query_virtio_status(path, &err);
|
|
|
|
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "%s:\n", path);
|
|
|
|
monitor_printf(mon, " device_name: %s %s\n",
|
2022-11-04 17:07:10 +01:00
|
|
|
s->name, s->vhost_dev ? "(vhost)" : "");
|
2022-08-11 14:24:44 +02:00
|
|
|
monitor_printf(mon, " device_id: %d\n", s->device_id);
|
|
|
|
monitor_printf(mon, " vhost_started: %s\n",
|
|
|
|
s->vhost_started ? "true" : "false");
|
|
|
|
monitor_printf(mon, " bus_name: %s\n", s->bus_name);
|
|
|
|
monitor_printf(mon, " broken: %s\n",
|
|
|
|
s->broken ? "true" : "false");
|
|
|
|
monitor_printf(mon, " disabled: %s\n",
|
|
|
|
s->disabled ? "true" : "false");
|
|
|
|
monitor_printf(mon, " disable_legacy_check: %s\n",
|
|
|
|
s->disable_legacy_check ? "true" : "false");
|
|
|
|
monitor_printf(mon, " started: %s\n",
|
|
|
|
s->started ? "true" : "false");
|
|
|
|
monitor_printf(mon, " use_started: %s\n",
|
|
|
|
s->use_started ? "true" : "false");
|
|
|
|
monitor_printf(mon, " start_on_kick: %s\n",
|
|
|
|
s->start_on_kick ? "true" : "false");
|
|
|
|
monitor_printf(mon, " use_guest_notifier_mask: %s\n",
|
|
|
|
s->use_guest_notifier_mask ? "true" : "false");
|
|
|
|
monitor_printf(mon, " vm_running: %s\n",
|
|
|
|
s->vm_running ? "true" : "false");
|
|
|
|
monitor_printf(mon, " num_vqs: %"PRId64"\n", s->num_vqs);
|
|
|
|
monitor_printf(mon, " queue_sel: %d\n",
|
|
|
|
s->queue_sel);
|
|
|
|
monitor_printf(mon, " isr: %d\n", s->isr);
|
|
|
|
monitor_printf(mon, " endianness: %s\n",
|
|
|
|
s->device_endian);
|
|
|
|
monitor_printf(mon, " status:\n");
|
|
|
|
hmp_virtio_dump_status(mon, s->status);
|
|
|
|
monitor_printf(mon, " Guest features:\n");
|
|
|
|
hmp_virtio_dump_features(mon, s->guest_features);
|
|
|
|
monitor_printf(mon, " Host features:\n");
|
|
|
|
hmp_virtio_dump_features(mon, s->host_features);
|
|
|
|
monitor_printf(mon, " Backend features:\n");
|
|
|
|
hmp_virtio_dump_features(mon, s->backend_features);
|
|
|
|
|
2022-11-04 17:07:10 +01:00
|
|
|
if (s->vhost_dev) {
|
2022-08-11 14:24:44 +02:00
|
|
|
monitor_printf(mon, " VHost:\n");
|
|
|
|
monitor_printf(mon, " nvqs: %d\n",
|
|
|
|
s->vhost_dev->nvqs);
|
|
|
|
monitor_printf(mon, " vq_index: %"PRId64"\n",
|
|
|
|
s->vhost_dev->vq_index);
|
|
|
|
monitor_printf(mon, " max_queues: %"PRId64"\n",
|
|
|
|
s->vhost_dev->max_queues);
|
|
|
|
monitor_printf(mon, " n_mem_sections: %"PRId64"\n",
|
|
|
|
s->vhost_dev->n_mem_sections);
|
|
|
|
monitor_printf(mon, " n_tmp_sections: %"PRId64"\n",
|
|
|
|
s->vhost_dev->n_tmp_sections);
|
|
|
|
monitor_printf(mon, " backend_cap: %"PRId64"\n",
|
|
|
|
s->vhost_dev->backend_cap);
|
|
|
|
monitor_printf(mon, " log_enabled: %s\n",
|
|
|
|
s->vhost_dev->log_enabled ? "true" : "false");
|
|
|
|
monitor_printf(mon, " log_size: %"PRId64"\n",
|
|
|
|
s->vhost_dev->log_size);
|
|
|
|
monitor_printf(mon, " Features:\n");
|
|
|
|
hmp_virtio_dump_features(mon, s->vhost_dev->features);
|
|
|
|
monitor_printf(mon, " Acked features:\n");
|
|
|
|
hmp_virtio_dump_features(mon, s->vhost_dev->acked_features);
|
|
|
|
monitor_printf(mon, " Backend features:\n");
|
|
|
|
hmp_virtio_dump_features(mon, s->vhost_dev->backend_features);
|
|
|
|
monitor_printf(mon, " Protocol features:\n");
|
|
|
|
hmp_virtio_dump_protocols(mon, s->vhost_dev->protocol_features);
|
|
|
|
}
|
|
|
|
|
|
|
|
qapi_free_VirtioStatus(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_vhost_queue_status(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *path = qdict_get_try_str(qdict, "path");
|
|
|
|
int queue = qdict_get_int(qdict, "queue");
|
|
|
|
VirtVhostQueueStatus *s =
|
|
|
|
qmp_x_query_virtio_vhost_queue_status(path, queue, &err);
|
|
|
|
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "%s:\n", path);
|
|
|
|
monitor_printf(mon, " device_name: %s (vhost)\n",
|
|
|
|
s->name);
|
|
|
|
monitor_printf(mon, " kick: %"PRId64"\n", s->kick);
|
|
|
|
monitor_printf(mon, " call: %"PRId64"\n", s->call);
|
|
|
|
monitor_printf(mon, " VRing:\n");
|
|
|
|
monitor_printf(mon, " num: %"PRId64"\n", s->num);
|
|
|
|
monitor_printf(mon, " desc: 0x%016"PRIx64"\n", s->desc);
|
|
|
|
monitor_printf(mon, " desc_phys: 0x%016"PRIx64"\n",
|
|
|
|
s->desc_phys);
|
|
|
|
monitor_printf(mon, " desc_size: %"PRId32"\n", s->desc_size);
|
|
|
|
monitor_printf(mon, " avail: 0x%016"PRIx64"\n", s->avail);
|
|
|
|
monitor_printf(mon, " avail_phys: 0x%016"PRIx64"\n",
|
|
|
|
s->avail_phys);
|
|
|
|
monitor_printf(mon, " avail_size: %"PRId32"\n", s->avail_size);
|
|
|
|
monitor_printf(mon, " used: 0x%016"PRIx64"\n", s->used);
|
|
|
|
monitor_printf(mon, " used_phys: 0x%016"PRIx64"\n",
|
|
|
|
s->used_phys);
|
|
|
|
monitor_printf(mon, " used_size: %"PRId32"\n", s->used_size);
|
|
|
|
|
|
|
|
qapi_free_VirtVhostQueueStatus(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *path = qdict_get_try_str(qdict, "path");
|
|
|
|
int queue = qdict_get_int(qdict, "queue");
|
|
|
|
VirtQueueStatus *s = qmp_x_query_virtio_queue_status(path, queue, &err);
|
|
|
|
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "%s:\n", path);
|
|
|
|
monitor_printf(mon, " device_name: %s\n", s->name);
|
|
|
|
monitor_printf(mon, " queue_index: %d\n", s->queue_index);
|
|
|
|
monitor_printf(mon, " inuse: %d\n", s->inuse);
|
|
|
|
monitor_printf(mon, " used_idx: %d\n", s->used_idx);
|
|
|
|
monitor_printf(mon, " signalled_used: %d\n",
|
|
|
|
s->signalled_used);
|
|
|
|
monitor_printf(mon, " signalled_used_valid: %s\n",
|
|
|
|
s->signalled_used_valid ? "true" : "false");
|
|
|
|
if (s->has_last_avail_idx) {
|
|
|
|
monitor_printf(mon, " last_avail_idx: %d\n",
|
|
|
|
s->last_avail_idx);
|
|
|
|
}
|
|
|
|
if (s->has_shadow_avail_idx) {
|
|
|
|
monitor_printf(mon, " shadow_avail_idx: %d\n",
|
|
|
|
s->shadow_avail_idx);
|
|
|
|
}
|
|
|
|
monitor_printf(mon, " VRing:\n");
|
|
|
|
monitor_printf(mon, " num: %"PRId32"\n", s->vring_num);
|
|
|
|
monitor_printf(mon, " num_default: %"PRId32"\n",
|
|
|
|
s->vring_num_default);
|
|
|
|
monitor_printf(mon, " align: %"PRId32"\n",
|
|
|
|
s->vring_align);
|
|
|
|
monitor_printf(mon, " desc: 0x%016"PRIx64"\n",
|
|
|
|
s->vring_desc);
|
|
|
|
monitor_printf(mon, " avail: 0x%016"PRIx64"\n",
|
|
|
|
s->vring_avail);
|
|
|
|
monitor_printf(mon, " used: 0x%016"PRIx64"\n",
|
|
|
|
s->vring_used);
|
|
|
|
|
|
|
|
qapi_free_VirtQueueStatus(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict)
|
|
|
|
{
|
|
|
|
Error *err = NULL;
|
|
|
|
const char *path = qdict_get_try_str(qdict, "path");
|
|
|
|
int queue = qdict_get_int(qdict, "queue");
|
|
|
|
int index = qdict_get_try_int(qdict, "index", -1);
|
|
|
|
VirtioQueueElement *e;
|
|
|
|
VirtioRingDescList *list;
|
|
|
|
|
|
|
|
e = qmp_x_query_virtio_queue_element(path, queue, index != -1,
|
|
|
|
index, &err);
|
|
|
|
if (err != NULL) {
|
|
|
|
hmp_handle_error(mon, err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
monitor_printf(mon, "%s:\n", path);
|
|
|
|
monitor_printf(mon, " device_name: %s\n", e->name);
|
|
|
|
monitor_printf(mon, " index: %d\n", e->index);
|
|
|
|
monitor_printf(mon, " desc:\n");
|
|
|
|
monitor_printf(mon, " descs:\n");
|
|
|
|
|
|
|
|
list = e->descs;
|
|
|
|
while (list) {
|
|
|
|
monitor_printf(mon, " addr 0x%"PRIx64" len %d",
|
|
|
|
list->value->addr, list->value->len);
|
|
|
|
if (list->value->flags) {
|
|
|
|
strList *flag = list->value->flags;
|
|
|
|
monitor_printf(mon, " (");
|
|
|
|
while (flag) {
|
|
|
|
monitor_printf(mon, "%s", flag->value);
|
|
|
|
flag = flag->next;
|
|
|
|
if (flag) {
|
|
|
|
monitor_printf(mon, ", ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
monitor_printf(mon, ")");
|
|
|
|
}
|
|
|
|
list = list->next;
|
|
|
|
if (list) {
|
|
|
|
monitor_printf(mon, ",\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
monitor_printf(mon, "\n");
|
|
|
|
monitor_printf(mon, " avail:\n");
|
|
|
|
monitor_printf(mon, " flags: %d\n", e->avail->flags);
|
|
|
|
monitor_printf(mon, " idx: %d\n", e->avail->idx);
|
|
|
|
monitor_printf(mon, " ring: %d\n", e->avail->ring);
|
|
|
|
monitor_printf(mon, " used:\n");
|
|
|
|
monitor_printf(mon, " flags: %d\n", e->used->flags);
|
|
|
|
monitor_printf(mon, " idx: %d\n", e->used->idx);
|
|
|
|
|
|
|
|
qapi_free_VirtioQueueElement(e);
|
|
|
|
}
|