From: Amos Kong <akong@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: aliguori@us.ibm.com, kvm@vger.kernel.org, quintela@redhat.com,
jasowang@redhat.com, qemu-devel@nongnu.org, laine@redhat.com
Subject: Re: [PATCH 1/4] Use getaddrinfo for migration
Date: Fri, 02 Mar 2012 11:33:11 +0800 [thread overview]
Message-ID: <4F503F77.4010003@redhat.com> (raw)
In-Reply-To: <4F475378.1090809@redhat.com>
On 24/02/12 17:08, Kevin Wolf wrote:
> Am 10.02.2012 07:27, schrieb Amos Kong:
>> This allows us to use ipv4/ipv6 for migration addresses.
>> Once there, it also uses /etc/services names (it came free).
>>
>> Signed-off-by: Juan Quintela<quintela@redhat.com>
>> Signed-off-by: Amos Kong<akong@redhat.com>
>> ---
>> migration-tcp.c | 60 ++++++++-----------------------
>> net.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> qemu_socket.h | 3 ++
>> 3 files changed, 127 insertions(+), 44 deletions(-)
>
> This patch is making too many changes at once:
>
> 1. Move code around
> 2. Remove duplicated code between client and server
> 3. Replace parse_host_port() with an open-coded version
> 4. Modify the open-coded parse_host_port() to use getaddrinfo instead of
> inet_aton/gethostbyname (Why can't we just change parse_host_port? Are
> there valid reasons to use the old implementation? Which?)
tcp_common_start() needs to use the address list which is got by
getaddrinfo(),
But I agree with verifying host/port by getaddrinfo() in parse_host_port.
> This makes it rather hard to review.
>
>> diff --git a/migration-tcp.c b/migration-tcp.c
>> index 35a5781..644bb8f 100644
>> --- a/migration-tcp.c
>> +++ b/migration-tcp.c
>> @@ -81,43 +81,27 @@ static void tcp_wait_for_connect(void *opaque)
>>
>> int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
>> {
>> - struct sockaddr_in addr;
>> int ret;
>> -
>> - ret = parse_host_port(&addr, host_port);
>> - if (ret< 0) {
>> - return ret;
>> - }
>> + int fd;
>>
>> 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();
>> - }
>> -
>> - 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) {
>> - qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
>> - return 0;
>> - }
>> - } while (ret == -EINTR);
>> -
>> - if (ret< 0) {
>> + ret = tcp_client_start(host_port,&fd);
>> + s->fd = fd;
>> + if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
>> + DPRINTF("connect in progress");
>> + qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
>> + } else if (ret< 0) {
>> DPRINTF("connect failed\n");
>> - migrate_fd_error(s);
>> + if (ret != -EINVAL) {
>> + migrate_fd_error(s);
>> + }
>
> This looks odd. It is probably needed to keep the old behaviour where a
> failed parse_host_port() wouldn't call migrate_fd_error(). Is this
> really required? Maybe I'm missing something, but the caller can't know
> which failure case we had and if migrate_fd_error() has been called.
getaddrinfo() is used in tcp_common_start(), -EINVAL will be returned
when getaddrinfo() doesn't return 0.
>> return ret;
>> + } else {
>> + migrate_fd_connect(s);
>> }
>> - migrate_fd_connect(s);
>> return 0;
>> }
>>
>> @@ -157,28 +141,16 @@ out2:
>>
>> int tcp_start_incoming_migration(const char *host_port)
>> {
>> - struct sockaddr_in addr;
>> - int val;
>> + int ret;
>> int s;
>>
>> DPRINTF("Attempting to start an incoming migration\n");
>>
>> - 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();
>> + ret = tcp_server_start(host_port,&s);
>> + if (ret< 0) {
>> + return ret;
>> }
>>
>> - 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;
>> }
>> diff --git a/net.c b/net.c
>> index c34474f..f63014c 100644
>> --- a/net.c
>> +++ b/net.c
>> @@ -99,6 +99,114 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
>> return 0;
>> }
>>
>> +static int tcp_server_bind(int fd, struct addrinfo *rp)
>> +{
>> + int ret;
>> + int val = 1;
>> +
>> + /* allow fast reuse */
>> + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
>> +
>> + ret = bind(fd, rp->ai_addr, rp->ai_addrlen);
>> +
>> + if (ret == -1) {
>> + ret = -socket_error();
>> + }
>> + return ret;
>> +
>> +}
>> +
>> +static int tcp_client_connect(int fd, struct addrinfo *rp)
>> +{
>> + int ret;
>> +
>> + do {
>> + ret = connect(fd, rp->ai_addr, rp->ai_addrlen);
>> + if (ret == -1) {
>> + ret = -socket_error();
>> + }
>> + } while (ret == -EINTR);
>> +
>> + return ret;
>> +}
>> +
>> +
>> +static int tcp_start_common(const char *str, int *fd, bool server)
>> +{
>> + char hostname[512];
>> + const char *service;
>> + const char *name;
>> + struct addrinfo hints;
>> + struct addrinfo *result, *rp;
>> + int s;
>> + int sfd;
>> + int ret = -EINVAL;
>> +
>> + *fd = -1;
>> + service = str;
>> + if (get_str_sep(hostname, sizeof(hostname),&service, ':')< 0) {
>> + return -EINVAL;
>> + }
>
> Separating host name and port at the first colon looks wrong for IPv6.
I fixed this in [PATCH 3/4] net: split hostname and service by last colon
>> + if (server&& strlen(hostname) == 0) {
>> + name = NULL;
>> + } else {
>> + name = hostname;
>> + }
>> +
>> + /* Obtain address(es) matching host/port */
>> +
>> + memset(&hints, 0, sizeof(struct addrinfo));
>> + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
>> + hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
>> +
>> + if (server) {
>> + hints.ai_flags = AI_PASSIVE;
>> + }
>> +
>> + s = getaddrinfo(name, service,&hints,&result);
>> + if (s != 0) {
>> + fprintf(stderr, "qemu: getaddrinfo: %s\n", gai_strerror(s));
>
> error_report?
yes
> Kevin
--
Amos.
WARNING: multiple messages have this Message-ID (diff)
From: Amos Kong <akong@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>
Cc: aliguori@us.ibm.com, kvm@vger.kernel.org, quintela@redhat.com,
jasowang@redhat.com, qemu-devel@nongnu.org, laine@redhat.com
Subject: Re: [Qemu-devel] [PATCH 1/4] Use getaddrinfo for migration
Date: Fri, 02 Mar 2012 11:33:11 +0800 [thread overview]
Message-ID: <4F503F77.4010003@redhat.com> (raw)
In-Reply-To: <4F475378.1090809@redhat.com>
On 24/02/12 17:08, Kevin Wolf wrote:
> Am 10.02.2012 07:27, schrieb Amos Kong:
>> This allows us to use ipv4/ipv6 for migration addresses.
>> Once there, it also uses /etc/services names (it came free).
>>
>> Signed-off-by: Juan Quintela<quintela@redhat.com>
>> Signed-off-by: Amos Kong<akong@redhat.com>
>> ---
>> migration-tcp.c | 60 ++++++++-----------------------
>> net.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> qemu_socket.h | 3 ++
>> 3 files changed, 127 insertions(+), 44 deletions(-)
>
> This patch is making too many changes at once:
>
> 1. Move code around
> 2. Remove duplicated code between client and server
> 3. Replace parse_host_port() with an open-coded version
> 4. Modify the open-coded parse_host_port() to use getaddrinfo instead of
> inet_aton/gethostbyname (Why can't we just change parse_host_port? Are
> there valid reasons to use the old implementation? Which?)
tcp_common_start() needs to use the address list which is got by
getaddrinfo(),
But I agree with verifying host/port by getaddrinfo() in parse_host_port.
> This makes it rather hard to review.
>
>> diff --git a/migration-tcp.c b/migration-tcp.c
>> index 35a5781..644bb8f 100644
>> --- a/migration-tcp.c
>> +++ b/migration-tcp.c
>> @@ -81,43 +81,27 @@ static void tcp_wait_for_connect(void *opaque)
>>
>> int tcp_start_outgoing_migration(MigrationState *s, const char *host_port)
>> {
>> - struct sockaddr_in addr;
>> int ret;
>> -
>> - ret = parse_host_port(&addr, host_port);
>> - if (ret< 0) {
>> - return ret;
>> - }
>> + int fd;
>>
>> 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();
>> - }
>> -
>> - 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) {
>> - qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
>> - return 0;
>> - }
>> - } while (ret == -EINTR);
>> -
>> - if (ret< 0) {
>> + ret = tcp_client_start(host_port,&fd);
>> + s->fd = fd;
>> + if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) {
>> + DPRINTF("connect in progress");
>> + qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
>> + } else if (ret< 0) {
>> DPRINTF("connect failed\n");
>> - migrate_fd_error(s);
>> + if (ret != -EINVAL) {
>> + migrate_fd_error(s);
>> + }
>
> This looks odd. It is probably needed to keep the old behaviour where a
> failed parse_host_port() wouldn't call migrate_fd_error(). Is this
> really required? Maybe I'm missing something, but the caller can't know
> which failure case we had and if migrate_fd_error() has been called.
getaddrinfo() is used in tcp_common_start(), -EINVAL will be returned
when getaddrinfo() doesn't return 0.
>> return ret;
>> + } else {
>> + migrate_fd_connect(s);
>> }
>> - migrate_fd_connect(s);
>> return 0;
>> }
>>
>> @@ -157,28 +141,16 @@ out2:
>>
>> int tcp_start_incoming_migration(const char *host_port)
>> {
>> - struct sockaddr_in addr;
>> - int val;
>> + int ret;
>> int s;
>>
>> DPRINTF("Attempting to start an incoming migration\n");
>>
>> - 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();
>> + ret = tcp_server_start(host_port,&s);
>> + if (ret< 0) {
>> + return ret;
>> }
>>
>> - 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;
>> }
>> diff --git a/net.c b/net.c
>> index c34474f..f63014c 100644
>> --- a/net.c
>> +++ b/net.c
>> @@ -99,6 +99,114 @@ static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
>> return 0;
>> }
>>
>> +static int tcp_server_bind(int fd, struct addrinfo *rp)
>> +{
>> + int ret;
>> + int val = 1;
>> +
>> + /* allow fast reuse */
>> + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val));
>> +
>> + ret = bind(fd, rp->ai_addr, rp->ai_addrlen);
>> +
>> + if (ret == -1) {
>> + ret = -socket_error();
>> + }
>> + return ret;
>> +
>> +}
>> +
>> +static int tcp_client_connect(int fd, struct addrinfo *rp)
>> +{
>> + int ret;
>> +
>> + do {
>> + ret = connect(fd, rp->ai_addr, rp->ai_addrlen);
>> + if (ret == -1) {
>> + ret = -socket_error();
>> + }
>> + } while (ret == -EINTR);
>> +
>> + return ret;
>> +}
>> +
>> +
>> +static int tcp_start_common(const char *str, int *fd, bool server)
>> +{
>> + char hostname[512];
>> + const char *service;
>> + const char *name;
>> + struct addrinfo hints;
>> + struct addrinfo *result, *rp;
>> + int s;
>> + int sfd;
>> + int ret = -EINVAL;
>> +
>> + *fd = -1;
>> + service = str;
>> + if (get_str_sep(hostname, sizeof(hostname),&service, ':')< 0) {
>> + return -EINVAL;
>> + }
>
> Separating host name and port at the first colon looks wrong for IPv6.
I fixed this in [PATCH 3/4] net: split hostname and service by last colon
>> + if (server&& strlen(hostname) == 0) {
>> + name = NULL;
>> + } else {
>> + name = hostname;
>> + }
>> +
>> + /* Obtain address(es) matching host/port */
>> +
>> + memset(&hints, 0, sizeof(struct addrinfo));
>> + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
>> + hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
>> +
>> + if (server) {
>> + hints.ai_flags = AI_PASSIVE;
>> + }
>> +
>> + s = getaddrinfo(name, service,&hints,&result);
>> + if (s != 0) {
>> + fprintf(stderr, "qemu: getaddrinfo: %s\n", gai_strerror(s));
>
> error_report?
yes
> Kevin
--
Amos.
next prev parent reply other threads:[~2012-03-02 3:33 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-10 6:26 [PATCH 0/4] support to migrate with IPv6 address Amos Kong
2012-02-10 6:26 ` [Qemu-devel] " Amos Kong
2012-02-10 6:27 ` [PATCH 1/4] Use getaddrinfo for migration Amos Kong
2012-02-10 6:27 ` [Qemu-devel] " Amos Kong
2012-02-24 9:08 ` Kevin Wolf
2012-03-02 3:33 ` Amos Kong [this message]
2012-03-02 3:33 ` Amos Kong
2012-03-02 10:28 ` Kevin Wolf
2012-02-24 9:34 ` Kevin Wolf
2012-03-02 2:50 ` Amos Kong
2012-03-02 2:50 ` [Qemu-devel] " Amos Kong
2012-03-02 10:21 ` Kevin Wolf
2012-03-02 10:21 ` [Qemu-devel] " Kevin Wolf
2012-03-02 10:25 ` Michael Tokarev
2012-03-02 10:25 ` [Qemu-devel] " Michael Tokarev
2012-03-02 10:41 ` Daniel P. Berrange
2012-03-02 10:41 ` Daniel P. Berrange
2012-03-05 8:03 ` Amos Kong
2012-03-05 8:03 ` Amos Kong
2012-02-10 6:27 ` [PATCH 2/4] net/socket: allow ipv6 for net_socket_listen_init and socket_connect_init Amos Kong
2012-02-10 6:27 ` [Qemu-devel] " Amos Kong
2012-02-24 9:25 ` Kevin Wolf
2012-02-10 6:27 ` [PATCH 3/4] net: split hostname and service by last colon Amos Kong
2012-02-10 6:27 ` [Qemu-devel] " Amos Kong
2012-02-24 9:29 ` Kevin Wolf
2012-03-02 3:38 ` Amos Kong
2012-03-02 9:58 ` Amos Kong
2012-03-02 10:35 ` Kevin Wolf
2012-03-02 19:54 ` Laine Stump
2012-03-02 19:54 ` Laine Stump
2012-03-05 8:57 ` Kevin Wolf
2012-03-05 8:57 ` Kevin Wolf
2012-03-05 8:59 ` Amos Kong
2012-03-05 9:06 ` Kevin Wolf
2012-02-10 6:27 ` [PATCH 4/4] net: support to include ipv6 address by brackets Amos Kong
2012-02-10 6:27 ` [Qemu-devel] " Amos Kong
2012-02-24 9:40 ` [Qemu-devel] [PATCH 0/4] support to migrate with IPv6 address Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F503F77.4010003@redhat.com \
--to=akong@redhat.com \
--cc=aliguori@us.ibm.com \
--cc=jasowang@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=kwolf@redhat.com \
--cc=laine@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.