Commit aef11b8d authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/amit-migration/tags/migration-2.7-2' into staging



migration: add TLS support to the migration data channel

This is a big refactoring of the migration backend code - moving away from
QEMUFile to the new QIOChannel framework introduced here.  This brings a
good level of abstraction and reduction of many lines of code.

This series also adds the ability for many backends (all except RDMA) to
use TLS for encrypting the migration data between the endpoints.

# gpg: Signature made Thu 26 May 2016 07:07:08 BST using RSA key ID 657EF670
# gpg: Good signature from "Amit Shah <amit@amitshah.net>"
# gpg:                 aka "Amit Shah <amit@kernel.org>"
# gpg:                 aka "Amit Shah <amitshah@gmx.net>"

* remotes/amit-migration/tags/migration-2.7-2: (28 commits)
  migration: remove qemu_get_fd method from QEMUFile
  migration: remove support for non-iovec based write handlers
  migration: add support for encrypting data with TLS
  migration: define 'tls-creds' and 'tls-hostname' migration parameters
  migration: don't use an array for storing migrate parameters
  migration: move definition of struct QEMUFile back into qemu-file.c
  migration: delete QEMUFile stdio implementation
  migration: delete QEMUFile sockets implementation
  migration: delete QEMUSizedBuffer struct
  migration: delete QEMUFile buffer implementation
  migration: convert savevm to use QIOChannel for writing to files
  migration: convert RDMA to use QIOChannel interface
  migration: convert exec socket protocol to use QIOChannel
  migration: convert fd socket protocol to use QIOChannel
  migration: convert tcp socket protocol to use QIOChannel
  migration: rename unix.c to socket.c
  migration: convert unix socket protocol to use QIOChannel
  migration: convert post-copy to use QIOChannelBuffer
  migration: add reporting of errors for outgoing migration
  migration: add helpers for creating QEMUFile from a QIOChannel
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2c56d06b 12992c16
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -403,8 +403,8 @@ listen thread: --- page -- page -- page -- page -- page --

On receipt of CMD_PACKAGED (1)
   All the data associated with the package - the ( ... ) section in the
diagram - is read into memory (into a QEMUSizedBuffer), and the main thread
recurses into qemu_loadvm_state_main to process the contents of the package (2)
diagram - is read into memory, and the main thread recurses into
qemu_loadvm_state_main to process the contents of the package (2)
which contains commands (3,6) and devices (4...)

On receipt of 'postcopy listen' - 3 -(i.e. the 1st command in the package)
+1 −1
Original line number Diff line number Diff line
@@ -1008,7 +1008,7 @@ ETEXI

    {
        .name       = "migrate_set_parameter",
        .args_type  = "parameter:s,value:i",
        .args_type  = "parameter:s,value:s",
        .params     = "parameter value",
        .help       = "Set the parameter for migration",
        .mhandler.cmd = hmp_migrate_set_parameter,
+50 −7
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include "block/qapi.h"
#include "qemu-io.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"

#ifdef CONFIG_SPICE
#include <spice/enums.h>
@@ -168,8 +169,15 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
    }

    if (info->has_status) {
        monitor_printf(mon, "Migration status: %s\n",
        monitor_printf(mon, "Migration status: %s",
                       MigrationStatus_lookup[info->status]);
        if (info->status == MIGRATION_STATUS_FAILED &&
            info->has_error_desc) {
            monitor_printf(mon, " (%s)\n", info->error_desc);
        } else {
            monitor_printf(mon, "\n");
        }

        monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
                       info->total_time);
        if (info->has_expected_downtime) {
@@ -286,6 +294,12 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
        monitor_printf(mon, " %s: %" PRId64,
            MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT],
            params->cpu_throttle_increment);
        monitor_printf(mon, " %s: '%s'",
            MigrationParameter_lookup[MIGRATION_PARAMETER_TLS_CREDS],
            params->tls_creds ? : "");
        monitor_printf(mon, " %s: '%s'",
            MigrationParameter_lookup[MIGRATION_PARAMETER_TLS_HOSTNAME],
            params->tls_hostname ? : "");
        monitor_printf(mon, "\n");
    }

@@ -1235,13 +1249,17 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
{
    const char *param = qdict_get_str(qdict, "parameter");
    int value = qdict_get_int(qdict, "value");
    const char *valuestr = qdict_get_str(qdict, "value");
    long valueint = 0;
    Error *err = NULL;
    bool has_compress_level = false;
    bool has_compress_threads = false;
    bool has_decompress_threads = false;
    bool has_cpu_throttle_initial = false;
    bool has_cpu_throttle_increment = false;
    bool has_tls_creds = false;
    bool has_tls_hostname = false;
    bool use_int_value = false;
    int i;

    for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
@@ -1249,25 +1267,46 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
            switch (i) {
            case MIGRATION_PARAMETER_COMPRESS_LEVEL:
                has_compress_level = true;
                use_int_value = true;
                break;
            case MIGRATION_PARAMETER_COMPRESS_THREADS:
                has_compress_threads = true;
                use_int_value = true;
                break;
            case MIGRATION_PARAMETER_DECOMPRESS_THREADS:
                has_decompress_threads = true;
                use_int_value = true;
                break;
            case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
                has_cpu_throttle_initial = true;
                use_int_value = true;
                break;
            case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
                has_cpu_throttle_increment = true;
                break;
            case MIGRATION_PARAMETER_TLS_CREDS:
                has_tls_creds = true;
                break;
            case MIGRATION_PARAMETER_TLS_HOSTNAME:
                has_tls_hostname = true;
                break;
            }
            qmp_migrate_set_parameters(has_compress_level, value,
                                       has_compress_threads, value,
                                       has_decompress_threads, value,
                                       has_cpu_throttle_initial, value,
                                       has_cpu_throttle_increment, value,

            if (use_int_value) {
                if (qemu_strtol(valuestr, NULL, 10, &valueint) < 0) {
                    error_setg(&err, "Unable to parse '%s' as an int",
                               valuestr);
                    goto cleanup;
                }
            }

            qmp_migrate_set_parameters(has_compress_level, valueint,
                                       has_compress_threads, valueint,
                                       has_decompress_threads, valueint,
                                       has_cpu_throttle_initial, valueint,
                                       has_cpu_throttle_increment, valueint,
                                       has_tls_creds, valuestr,
                                       has_tls_hostname, valuestr,
                                       &err);
            break;
        }
@@ -1277,6 +1316,7 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
        error_setg(&err, QERR_INVALID_PARAMETER, param);
    }

 cleanup:
    if (err) {
        error_report_err(err);
    }
@@ -1533,6 +1573,9 @@ static void hmp_migrate_status_cb(void *opaque)
        if (status->is_block_migration) {
            monitor_printf(status->mon, "\n");
        }
        if (info->has_error_desc) {
            error_report("%s", info->error_desc);
        }
        monitor_resume(status->mon);
        timer_del(status->timer);
        g_free(status);
+14 −12
Original line number Diff line number Diff line
@@ -47,15 +47,11 @@ void s390_skeys_init(void)
    qdev_init_nofail(DEVICE(obj));
}

static void write_keys(QEMUFile *f, uint8_t *keys, uint64_t startgfn,
static void write_keys(FILE *f, uint8_t *keys, uint64_t startgfn,
                       uint64_t count, Error **errp)
{
    uint64_t curpage = startgfn;
    uint64_t maxpage = curpage + count - 1;
    const char *fmt = "page=%03" PRIx64 ": key(%d) => ACC=%X, FP=%d, REF=%d,"
                      " ch=%d, reserved=%d\n";
    char buf[128];
    int len;

    for (; curpage <= maxpage; curpage++) {
        uint8_t acc = (*keys & 0xF0) >> 4;
@@ -64,10 +60,9 @@ static void write_keys(QEMUFile *f, uint8_t *keys, uint64_t startgfn,
        int ch = (*keys & 0x02);
        int res = (*keys & 0x01);

        len = snprintf(buf, sizeof(buf), fmt, curpage,
                       *keys, acc, fp, ref, ch, res);
        assert(len < sizeof(buf));
        qemu_put_buffer(f, (uint8_t *)buf, len);
        fprintf(f, "page=%03" PRIx64 ": key(%d) => ACC=%X, FP=%d, REF=%d,"
                " ch=%d, reserved=%d\n",
                curpage, *keys, acc, fp, ref, ch, res);
        keys++;
    }
}
@@ -116,7 +111,8 @@ void qmp_dump_skeys(const char *filename, Error **errp)
    vaddr cur_gfn = 0;
    uint8_t *buf;
    int ret;
    QEMUFile *f;
    int fd;
    FILE *f;

    /* Quick check to see if guest is using storage keys*/
    if (!skeyclass->skeys_enabled(ss)) {
@@ -125,8 +121,14 @@ void qmp_dump_skeys(const char *filename, Error **errp)
        return;
    }

    f = qemu_fopen(filename, "wb");
    fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    if (fd < 0) {
        error_setg_file_open(errp, errno, filename);
        return;
    }
    f = fdopen(fd, "wb");
    if (!f) {
        close(fd);
        error_setg_file_open(errp, errno, filename);
        return;
    }
@@ -162,7 +164,7 @@ out_free:
    error_propagate(errp, lerr);
    g_free(buf);
out:
    qemu_fclose(f);
    fclose(f);
}

static void qemu_s390_skeys_init(Object *obj)
+24 −2
Original line number Diff line number Diff line
@@ -135,9 +135,12 @@ struct MigrationState
    QemuThread thread;
    QEMUBH *cleanup_bh;
    QEMUFile *to_dst_file;
    int parameters[MIGRATION_PARAMETER__MAX];

    /* New style params from 'migrate-set-parameters' */
    MigrationParameters parameters;

    int state;
    /* Old style params from 'migrate' command */
    MigrationParams params;

    /* State related to return path */
@@ -171,6 +174,9 @@ struct MigrationState
    QSIMPLEQ_HEAD(src_page_requests, MigrationSrcPageRequest) src_page_requests;
    /* The RAMBlock used in the last src_page_request */
    RAMBlock *last_req_rb;

    /* The last error that occurred */
    Error *error;
};

void migrate_set_state(int *state, int old_state, int new_state);
@@ -179,6 +185,22 @@ void process_incoming_migration(QEMUFile *f);

void qemu_start_incoming_migration(const char *uri, Error **errp);

void migration_set_incoming_channel(MigrationState *s,
                                    QIOChannel *ioc);

void migration_tls_set_incoming_channel(MigrationState *s,
                                        QIOChannel *ioc,
                                        Error **errp);

void migration_set_outgoing_channel(MigrationState *s,
                                    QIOChannel *ioc,
                                    const char *hostname);

void migration_tls_set_outgoing_channel(MigrationState *s,
                                        QIOChannel *ioc,
                                        const char *hostname,
                                        Error **errp);

uint64_t migrate_max_downtime(void);

void exec_start_incoming_migration(const char *host_port, Error **errp);
@@ -201,7 +223,7 @@ void rdma_start_outgoing_migration(void *opaque, const char *host_port, Error **

void rdma_start_incoming_migration(const char *host_port, Error **errp);

void migrate_fd_error(MigrationState *s);
void migrate_fd_error(MigrationState *s, const Error *error);

void migrate_fd_connect(MigrationState *s);

Loading