use inet_listen()/inet_connect() to support ipv6 migration
Use help functions in qemu-socket.c for tcp migration,
which already support ipv6 addresses.
Currently errp will be set to UNDEFINED_ERROR when migration fails,
qemu would output "migration failed: ...", and current user can
see a message("An undefined error has occurred") in monitor.
This patch changed tcp_start_outgoing_migration()/inet_connect()
/inet_connect_opts(), socket error would be passed back,
then current user can see a meaningful err message in monitor.
Qemu will exit if listening fails, so output socket error
to qemu stderr.
For IPv6 brackets must be mandatory if you require a port.
Referencing to RFC5952, the recommended format is:
  [2312::8274]:5200
test status: Successed
listen side: qemu-kvm .... -incoming tcp:[2312::8274]:5200
client side: qemu-kvm ...
             (qemu) migrate -d tcp:[2312::8274]:5200
Signed-off-by: Amos Kong <akong@redhat.com>
Reviewed-by: Orit Wasserman <owasserm@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
			
			
This commit is contained in:
		
							parent
							
								
									029409e5a9
								
							
						
					
					
						commit
						d5c5dacc70
					
				| 
						 | 
				
			
			@ -79,45 +79,32 @@ static void tcp_wait_for_connect(void *opaque)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
 | 
			
		||||
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
 | 
			
		||||
                                 Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    struct sockaddr_in addr;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    ret = parse_host_port(&addr, host_port);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->get_error = socket_errno;
 | 
			
		||||
    s->write = socket_write;
 | 
			
		||||
    s->close = tcp_close;
 | 
			
		||||
 | 
			
		||||
    s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
 | 
			
		||||
    if (s->fd == -1) {
 | 
			
		||||
        DPRINTF("Unable to open socket");
 | 
			
		||||
        return -socket_error();
 | 
			
		||||
    }
 | 
			
		||||
    s->fd = inet_connect(host_port, false, errp);
 | 
			
		||||
 | 
			
		||||
    socket_set_nonblock(s->fd);
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
 | 
			
		||||
        if (ret == -1) {
 | 
			
		||||
            ret = -socket_error();
 | 
			
		||||
        }
 | 
			
		||||
        if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
 | 
			
		||||
    if (!error_is_set(errp)) {
 | 
			
		||||
        migrate_fd_connect(s);
 | 
			
		||||
    } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_IN_PROGRESS)) {
 | 
			
		||||
        DPRINTF("connect in progress\n");
 | 
			
		||||
        qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
    } while (ret == -EINTR);
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
    } else if (error_is_type(*errp, QERR_SOCKET_CREATE_FAILED)) {
 | 
			
		||||
        DPRINTF("connect failed\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    } else if (error_is_type(*errp, QERR_SOCKET_CONNECT_FAILED)) {
 | 
			
		||||
        DPRINTF("connect failed\n");
 | 
			
		||||
        migrate_fd_error(s);
 | 
			
		||||
        return ret;
 | 
			
		||||
        return -1;
 | 
			
		||||
    } else {
 | 
			
		||||
        DPRINTF("unknown error\n");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    migrate_fd_connect(s);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -155,40 +142,18 @@ out2:
 | 
			
		|||
    close(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tcp_start_incoming_migration(const char *host_port)
 | 
			
		||||
int tcp_start_incoming_migration(const char *host_port, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    struct sockaddr_in addr;
 | 
			
		||||
    int val;
 | 
			
		||||
    int s;
 | 
			
		||||
 | 
			
		||||
    DPRINTF("Attempting to start an incoming migration\n");
 | 
			
		||||
    s = inet_listen(host_port, NULL, 256, SOCK_STREAM, 0, errp);
 | 
			
		||||
 | 
			
		||||
    if (parse_host_port(&addr, host_port) < 0) {
 | 
			
		||||
        fprintf(stderr, "invalid host/port combination: %s\n", host_port);
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s = qemu_socket(PF_INET, SOCK_STREAM, 0);
 | 
			
		||||
    if (s == -1) {
 | 
			
		||||
        return -socket_error();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val = 1;
 | 
			
		||||
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
 | 
			
		||||
 | 
			
		||||
    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
 | 
			
		||||
        goto err;
 | 
			
		||||
    }
 | 
			
		||||
    if (listen(s, 1) == -1) {
 | 
			
		||||
        goto err;
 | 
			
		||||
    if (s < 0) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL,
 | 
			
		||||
                         (void *)(intptr_t)s);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
err:
 | 
			
		||||
    close(s);
 | 
			
		||||
    return -socket_error();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,13 +60,13 @@ static MigrationState *migrate_get_current(void)
 | 
			
		|||
    return ¤t_migration;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qemu_start_incoming_migration(const char *uri)
 | 
			
		||||
int qemu_start_incoming_migration(const char *uri, Error **errp)
 | 
			
		||||
{
 | 
			
		||||
    const char *p;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (strstart(uri, "tcp:", &p))
 | 
			
		||||
        ret = tcp_start_incoming_migration(p);
 | 
			
		||||
        ret = tcp_start_incoming_migration(p, errp);
 | 
			
		||||
#if !defined(WIN32)
 | 
			
		||||
    else if (strstart(uri, "exec:", &p))
 | 
			
		||||
        ret =  exec_start_incoming_migration(p);
 | 
			
		||||
| 
						 | 
				
			
			@ -414,7 +414,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
 | 
			
		|||
    s = migrate_init(blk, inc);
 | 
			
		||||
 | 
			
		||||
    if (strstart(uri, "tcp:", &p)) {
 | 
			
		||||
        ret = tcp_start_outgoing_migration(s, p);
 | 
			
		||||
        ret = tcp_start_outgoing_migration(s, p, errp);
 | 
			
		||||
#if !defined(WIN32)
 | 
			
		||||
    } else if (strstart(uri, "exec:", &p)) {
 | 
			
		||||
        ret = exec_start_outgoing_migration(s, p);
 | 
			
		||||
| 
						 | 
				
			
			@ -429,9 +429,11 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        if (!error_is_set(errp)) {
 | 
			
		||||
            DPRINTF("migration failed: %s\n", strerror(-ret));
 | 
			
		||||
            /* FIXME: we should return meaningful errors */
 | 
			
		||||
            error_set(errp, QERR_UNDEFINED_ERROR);
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ struct MigrationState
 | 
			
		|||
 | 
			
		||||
void process_incoming_migration(QEMUFile *f);
 | 
			
		||||
 | 
			
		||||
int qemu_start_incoming_migration(const char *uri);
 | 
			
		||||
int qemu_start_incoming_migration(const char *uri, Error **errp);
 | 
			
		||||
 | 
			
		||||
uint64_t migrate_max_downtime(void);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -49,9 +49,10 @@ int exec_start_incoming_migration(const char *host_port);
 | 
			
		|||
 | 
			
		||||
int exec_start_outgoing_migration(MigrationState *s, const char *host_port);
 | 
			
		||||
 | 
			
		||||
int tcp_start_incoming_migration(const char *host_port);
 | 
			
		||||
int tcp_start_incoming_migration(const char *host_port, Error **errp);
 | 
			
		||||
 | 
			
		||||
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port);
 | 
			
		||||
int tcp_start_outgoing_migration(MigrationState *s, const char *host_port,
 | 
			
		||||
                                 Error **errp);
 | 
			
		||||
 | 
			
		||||
int unix_start_incoming_migration(const char *path);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								vl.c
								
								
								
								
							
							
						
						
									
										7
									
								
								vl.c
								
								
								
								
							| 
						 | 
				
			
			@ -3629,8 +3629,13 @@ int main(int argc, char **argv, char **envp)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (incoming) {
 | 
			
		||||
        int ret = qemu_start_incoming_migration(incoming);
 | 
			
		||||
        Error *errp = NULL;
 | 
			
		||||
        int ret = qemu_start_incoming_migration(incoming, &errp);
 | 
			
		||||
        if (ret < 0) {
 | 
			
		||||
            if (error_is_set(&errp)) {
 | 
			
		||||
                fprintf(stderr, "Migrate: %s\n", error_get_pretty(errp));
 | 
			
		||||
                error_free(errp);
 | 
			
		||||
            }
 | 
			
		||||
            fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
 | 
			
		||||
                    incoming, ret);
 | 
			
		||||
            exit(ret);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue