blob: ca3319a30985c420020281391206ef418a014e3c [file] [log] [blame]
Juan Quinteladd4339c2017-04-17 17:07:04 +02001/*
2 * QEMU live migration channel operations
3 *
4 * Copyright Red Hat, Inc. 2016
5 *
6 * Authors:
7 * Daniel P. Berrange <berrange@redhat.com>
8 *
9 * Contributions after 2012-01-13 are licensed under the terms of the
10 * GNU GPL, version 2 or (at your option) any later version.
11 */
12
13#include "qemu/osdep.h"
14#include "channel.h"
Juan Quintela41d64222017-04-05 17:45:16 +020015#include "tls.h"
Juan Quintela6666c962017-04-24 20:07:27 +020016#include "migration.h"
Daniel P. Berrangé77ef2dc2022-06-20 12:02:05 +010017#include "qemu-file.h"
Juan Quinteladd4339c2017-04-17 17:07:04 +020018#include "trace.h"
19#include "qapi/error.h"
20#include "io/channel-tls.h"
Lukas Straubb5eea992020-12-28 16:08:52 +010021#include "io/channel-socket.h"
22#include "qemu/yank.h"
Lukas Straub1a92d6d2021-03-23 18:52:42 +010023#include "yank_functions.h"
Juan Quinteladd4339c2017-04-17 17:07:04 +020024
Juan Quintela8e1a1932017-07-24 12:55:26 +020025/**
26 * @migration_channel_process_incoming - Create new incoming migration channel
27 *
28 * Notice that TLS is special. For it we listen in a listener socket,
29 * and then create a new client socket from the TLS library.
30 *
31 * @ioc: Channel to which we are connecting
32 */
Juan Quintela54314712017-04-17 17:15:02 +020033void migration_channel_process_incoming(QIOChannel *ioc)
Juan Quinteladd4339c2017-04-17 17:07:04 +020034{
Juan Quintela54314712017-04-17 17:15:02 +020035 MigrationState *s = migrate_get_current();
Fei Li49ed0d22019-01-13 22:08:46 +080036 Error *local_err = NULL;
Juan Quintela54314712017-04-17 17:15:02 +020037
Juan Quinteladd4339c2017-04-17 17:07:04 +020038 trace_migration_set_incoming_channel(
39 ioc, object_get_typename(OBJECT(ioc)));
40
Peter Xu85a85782022-07-07 14:55:13 -040041 if (migrate_channel_requires_tls_upgrade(ioc)) {
Juan Quinteladd4339c2017-04-17 17:07:04 +020042 migration_tls_channel_process_incoming(s, ioc, &local_err);
Juan Quinteladd4339c2017-04-17 17:07:04 +020043 } else {
Peter Xu18711402021-07-22 13:58:39 -040044 migration_ioc_register_yank(ioc);
Fei Li49ed0d22019-01-13 22:08:46 +080045 migration_ioc_process_incoming(ioc, &local_err);
46 }
47
48 if (local_err) {
49 error_report_err(local_err);
Juan Quinteladd4339c2017-04-17 17:07:04 +020050 }
51}
52
53
Juan Quintela8e1a1932017-07-24 12:55:26 +020054/**
55 * @migration_channel_connect - Create new outgoing migration channel
56 *
57 * @s: Current migration state
58 * @ioc: Channel to which we are connecting
59 * @hostname: Where we want to connect
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000060 * @error: Error indicating failure to connect, free'd here
Juan Quintela8e1a1932017-07-24 12:55:26 +020061 */
Juan Quinteladd4339c2017-04-17 17:07:04 +020062void migration_channel_connect(MigrationState *s,
63 QIOChannel *ioc,
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000064 const char *hostname,
65 Error *error)
Juan Quinteladd4339c2017-04-17 17:07:04 +020066{
67 trace_migration_set_outgoing_channel(
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000068 ioc, object_get_typename(OBJECT(ioc)), hostname, error);
Juan Quinteladd4339c2017-04-17 17:07:04 +020069
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000070 if (!error) {
Peter Xu85a85782022-07-07 14:55:13 -040071 if (migrate_channel_requires_tls_upgrade(ioc)) {
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000072 migration_tls_channel_connect(s, ioc, hostname, &error);
Dr. David Alan Gilbert8b7bf2b2018-04-30 19:59:43 +010073
74 if (!error) {
75 /* tls_channel_connect will call back to this
76 * function after the TLS handshake,
77 * so we mustn't call migrate_fd_connect until then
78 */
79
80 return;
81 }
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000082 } else {
Daniel P. Berrangé77ef2dc2022-06-20 12:02:05 +010083 QEMUFile *f = qemu_file_new_output(ioc);
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000084
Peter Xu18711402021-07-22 13:58:39 -040085 migration_ioc_register_yank(ioc);
Leonardo Bras7de2e852021-06-01 02:40:31 -030086
Peter Xu62df0662018-05-02 18:47:38 +080087 qemu_mutex_lock(&s->qemu_file_lock);
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000088 s->to_dst_file = f;
Peter Xu62df0662018-05-02 18:47:38 +080089 qemu_mutex_unlock(&s->qemu_file_lock);
Juan Quinteladd4339c2017-04-17 17:07:04 +020090 }
Juan Quinteladd4339c2017-04-17 17:07:04 +020091 }
Dr. David Alan Gilbert688a3dc2017-12-15 17:16:55 +000092 migrate_fd_connect(s, error);
93 error_free(error);
Juan Quinteladd4339c2017-04-17 17:07:04 +020094}
manish.mishra6720c2b2022-12-20 18:44:18 +000095
96
97/**
98 * @migration_channel_read_peek - Peek at migration channel, without
99 * actually removing it from channel buffer.
100 *
101 * @ioc: the channel object
102 * @buf: the memory region to read data into
103 * @buflen: the number of bytes to read in @buf
104 * @errp: pointer to a NULL-initialized error object
105 *
106 * Returns 0 if successful, returns -1 and sets @errp if fails.
107 */
108int migration_channel_read_peek(QIOChannel *ioc,
109 const char *buf,
110 const size_t buflen,
111 Error **errp)
112{
113 ssize_t len = 0;
114 struct iovec iov = { .iov_base = (char *)buf, .iov_len = buflen };
115
116 while (true) {
117 len = qio_channel_readv_full(ioc, &iov, 1, NULL, NULL,
118 QIO_CHANNEL_READ_FLAG_MSG_PEEK, errp);
119
120 if (len <= 0 && len != QIO_CHANNEL_ERR_BLOCK) {
121 error_setg(errp,
122 "Failed to peek at channel");
123 return -1;
124 }
125
126 if (len == buflen) {
127 break;
128 }
129
130 /* 1ms sleep. */
131 if (qemu_in_coroutine()) {
132 qemu_co_sleep_ns(QEMU_CLOCK_REALTIME, 1000000);
133 } else {
134 g_usleep(1000);
135 }
136 }
137
138 return 0;
139}