Statistics
| Branch: | Revision:

root / migration-tcp.c @ 371c6489

History | View | Annotate | Download (4.2 kB)

1 34c9dd8e aliguori
/*
2 34c9dd8e aliguori
 * QEMU live migration
3 34c9dd8e aliguori
 *
4 34c9dd8e aliguori
 * Copyright IBM, Corp. 2008
5 34c9dd8e aliguori
 *
6 34c9dd8e aliguori
 * Authors:
7 34c9dd8e aliguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 34c9dd8e aliguori
 *
9 34c9dd8e aliguori
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 34c9dd8e aliguori
 * the COPYING file in the top-level directory.
11 34c9dd8e aliguori
 *
12 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
13 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
14 34c9dd8e aliguori
 */
15 34c9dd8e aliguori
16 34c9dd8e aliguori
#include "qemu-common.h"
17 34c9dd8e aliguori
#include "qemu_socket.h"
18 34c9dd8e aliguori
#include "migration.h"
19 34c9dd8e aliguori
#include "qemu-char.h"
20 34c9dd8e aliguori
#include "buffered_file.h"
21 34c9dd8e aliguori
#include "block.h"
22 34c9dd8e aliguori
23 34c9dd8e aliguori
//#define DEBUG_MIGRATION_TCP
24 34c9dd8e aliguori
25 34c9dd8e aliguori
#ifdef DEBUG_MIGRATION_TCP
26 d0f2c4c6 malc
#define DPRINTF(fmt, ...) \
27 34c9dd8e aliguori
    do { printf("migration-tcp: " fmt, ## __VA_ARGS__); } while (0)
28 34c9dd8e aliguori
#else
29 d0f2c4c6 malc
#define DPRINTF(fmt, ...) \
30 34c9dd8e aliguori
    do { } while (0)
31 34c9dd8e aliguori
#endif
32 34c9dd8e aliguori
33 22f00a44 Juan Quintela
static int socket_errno(MigrationState *s)
34 34c9dd8e aliguori
{
35 8ad9fa5d aliguori
    return socket_error();
36 34c9dd8e aliguori
}
37 34c9dd8e aliguori
38 22f00a44 Juan Quintela
static int socket_write(MigrationState *s, const void * buf, size_t size)
39 34c9dd8e aliguori
{
40 065e2813 aliguori
    return send(s->fd, buf, size, 0);
41 34c9dd8e aliguori
}
42 34c9dd8e aliguori
43 22f00a44 Juan Quintela
static int tcp_close(MigrationState *s)
44 34c9dd8e aliguori
{
45 61a5872f Eduardo Habkost
    int r = 0;
46 d0f2c4c6 malc
    DPRINTF("tcp_close\n");
47 34c9dd8e aliguori
    if (s->fd != -1) {
48 61a5872f Eduardo Habkost
        if (close(s->fd) < 0) {
49 61a5872f Eduardo Habkost
            r = -errno;
50 61a5872f Eduardo Habkost
        }
51 ff8d81d8 aliguori
        s->fd = -1;
52 34c9dd8e aliguori
    }
53 61a5872f Eduardo Habkost
    return r;
54 34c9dd8e aliguori
}
55 34c9dd8e aliguori
56 34c9dd8e aliguori
static void tcp_wait_for_connect(void *opaque)
57 34c9dd8e aliguori
{
58 22f00a44 Juan Quintela
    MigrationState *s = opaque;
59 34c9dd8e aliguori
    int val, ret;
60 4761a48b blueswir1
    socklen_t valsize = sizeof(val);
61 34c9dd8e aliguori
62 d0f2c4c6 malc
    DPRINTF("connect completed\n");
63 34c9dd8e aliguori
    do {
64 0a656f5f malc
        ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize);
65 efab4718 Juan Quintela
    } while (ret == -1 && (socket_error()) == EINTR);
66 34c9dd8e aliguori
67 34c9dd8e aliguori
    if (ret < 0) {
68 065e2813 aliguori
        migrate_fd_error(s);
69 34c9dd8e aliguori
        return;
70 34c9dd8e aliguori
    }
71 34c9dd8e aliguori
72 34c9dd8e aliguori
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
73 34c9dd8e aliguori
74 34c9dd8e aliguori
    if (val == 0)
75 065e2813 aliguori
        migrate_fd_connect(s);
76 34c9dd8e aliguori
    else {
77 d0f2c4c6 malc
        DPRINTF("error connecting %d\n", val);
78 065e2813 aliguori
        migrate_fd_error(s);
79 34c9dd8e aliguori
    }
80 34c9dd8e aliguori
}
81 34c9dd8e aliguori
82 07af4452 Juan Quintela
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
83 34c9dd8e aliguori
{
84 34c9dd8e aliguori
    struct sockaddr_in addr;
85 34c9dd8e aliguori
    int ret;
86 34c9dd8e aliguori
87 07af4452 Juan Quintela
    ret = parse_host_port(&addr, host_port);
88 07af4452 Juan Quintela
    if (ret < 0) {
89 07af4452 Juan Quintela
        return ret;
90 07af4452 Juan Quintela
    }
91 ee86c61f Juan Quintela
92 065e2813 aliguori
    s->get_error = socket_errno;
93 065e2813 aliguori
    s->write = socket_write;
94 065e2813 aliguori
    s->close = tcp_close;
95 34c9dd8e aliguori
96 40ff6d7e Kevin Wolf
    s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
97 34c9dd8e aliguori
    if (s->fd == -1) {
98 ee86c61f Juan Quintela
        DPRINTF("Unable to open socket");
99 8414ff3b Juan Quintela
        return -socket_error();
100 34c9dd8e aliguori
    }
101 34c9dd8e aliguori
102 17e90973 aliguori
    socket_set_nonblock(s->fd);
103 34c9dd8e aliguori
104 34c9dd8e aliguori
    do {
105 34c9dd8e aliguori
        ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
106 8414ff3b Juan Quintela
        if (ret == -1) {
107 8414ff3b Juan Quintela
            ret = -socket_error();
108 8414ff3b Juan Quintela
        }
109 8414ff3b Juan Quintela
        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
110 34c9dd8e aliguori
            qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
111 8414ff3b Juan Quintela
            return 0;
112 8414ff3b Juan Quintela
        }
113 34c9dd8e aliguori
    } while (ret == -EINTR);
114 34c9dd8e aliguori
115 8414ff3b Juan Quintela
    if (ret < 0) {
116 d0f2c4c6 malc
        DPRINTF("connect failed\n");
117 304e3a7c Yoshiaki Tamura
        migrate_fd_error(s);
118 8414ff3b Juan Quintela
        return ret;
119 8414ff3b Juan Quintela
    }
120 8414ff3b Juan Quintela
    migrate_fd_connect(s);
121 07af4452 Juan Quintela
    return 0;
122 34c9dd8e aliguori
}
123 34c9dd8e aliguori
124 34c9dd8e aliguori
static void tcp_accept_incoming_migration(void *opaque)
125 34c9dd8e aliguori
{
126 34c9dd8e aliguori
    struct sockaddr_in addr;
127 34c9dd8e aliguori
    socklen_t addrlen = sizeof(addr);
128 e0efb993 Stefan Weil
    int s = (intptr_t)opaque;
129 34c9dd8e aliguori
    QEMUFile *f;
130 511c0231 Juan Quintela
    int c;
131 34c9dd8e aliguori
132 34c9dd8e aliguori
    do {
133 40ff6d7e Kevin Wolf
        c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
134 c1d36665 aliguori
    } while (c == -1 && socket_error() == EINTR);
135 34c9dd8e aliguori
136 d0f2c4c6 malc
    DPRINTF("accepted migration\n");
137 34c9dd8e aliguori
138 34c9dd8e aliguori
    if (c == -1) {
139 34c9dd8e aliguori
        fprintf(stderr, "could not accept migration connection\n");
140 d092c108 Shahar Havivi
        goto out2;
141 34c9dd8e aliguori
    }
142 34c9dd8e aliguori
143 c1d36665 aliguori
    f = qemu_fopen_socket(c);
144 34c9dd8e aliguori
    if (f == NULL) {
145 34c9dd8e aliguori
        fprintf(stderr, "could not qemu_fopen socket\n");
146 34c9dd8e aliguori
        goto out;
147 34c9dd8e aliguori
    }
148 34c9dd8e aliguori
149 511c0231 Juan Quintela
    process_incoming_migration(f);
150 34c9dd8e aliguori
    qemu_fclose(f);
151 34c9dd8e aliguori
out:
152 d092c108 Shahar Havivi
    close(c);
153 d092c108 Shahar Havivi
out2:
154 cfaf6d36 Juan Quintela
    qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
155 cfaf6d36 Juan Quintela
    close(s);
156 34c9dd8e aliguori
}
157 34c9dd8e aliguori
158 34c9dd8e aliguori
int tcp_start_incoming_migration(const char *host_port)
159 34c9dd8e aliguori
{
160 34c9dd8e aliguori
    struct sockaddr_in addr;
161 34c9dd8e aliguori
    int val;
162 34c9dd8e aliguori
    int s;
163 34c9dd8e aliguori
164 ee86c61f Juan Quintela
    DPRINTF("Attempting to start an incoming migration\n");
165 ee86c61f Juan Quintela
166 34c9dd8e aliguori
    if (parse_host_port(&addr, host_port) < 0) {
167 34c9dd8e aliguori
        fprintf(stderr, "invalid host/port combination: %s\n", host_port);
168 34c9dd8e aliguori
        return -EINVAL;
169 34c9dd8e aliguori
    }
170 34c9dd8e aliguori
171 40ff6d7e Kevin Wolf
    s = qemu_socket(PF_INET, SOCK_STREAM, 0);
172 ee86c61f Juan Quintela
    if (s == -1) {
173 c1d36665 aliguori
        return -socket_error();
174 ee86c61f Juan Quintela
    }
175 34c9dd8e aliguori
176 34c9dd8e aliguori
    val = 1;
177 34c9dd8e aliguori
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
178 34c9dd8e aliguori
179 ee86c61f Juan Quintela
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
180 34c9dd8e aliguori
        goto err;
181 ee86c61f Juan Quintela
    }
182 ee86c61f Juan Quintela
    if (listen(s, 1) == -1) {
183 34c9dd8e aliguori
        goto err;
184 ee86c61f Juan Quintela
    }
185 34c9dd8e aliguori
186 34c9dd8e aliguori
    qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
187 e0efb993 Stefan Weil
                         (void *)(intptr_t)s);
188 34c9dd8e aliguori
189 34c9dd8e aliguori
    return 0;
190 34c9dd8e aliguori
191 34c9dd8e aliguori
err:
192 34c9dd8e aliguori
    close(s);
193 c1d36665 aliguori
    return -socket_error();
194 34c9dd8e aliguori
}