diff mbox

rdma: bugfix: make IPv6 support work

Message ID 1374891788-17567-1-git-send-email-mrhines@linux.vnet.ibm.com
State New
Headers show

Commit Message

mrhines@linux.vnet.ibm.com July 27, 2013, 2:23 a.m. UTC
From: "Michael R. Hines" <mrhines@us.ibm.com>

When testing with libvirt, a simple IPv6 migration test failed
because we were not using getaddrinfo() properly.
This makes IPv6 migration over RDMA work.

Also, we forgot to turn the DPRINTF flag off =).

Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
---
 migration-rdma.c |   35 ++++++++++++++++++++++-------------
 1 file changed, 22 insertions(+), 13 deletions(-)

Comments

Andreas Färber July 27, 2013, 2:30 a.m. UTC | #1
Am 27.07.2013 04:23, schrieb mrhines@linux.vnet.ibm.com:
> From: "Michael R. Hines" <mrhines@us.ibm.com>
> 
> When testing with libvirt, a simple IPv6 migration test failed
> because we were not using getaddrinfo() properly.
> This makes IPv6 migration over RDMA work.
> 
> Also, we forgot to turn the DPRINTF flag off =).
> 
> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
> ---
>  migration-rdma.c |   35 ++++++++++++++++++++++-------------
>  1 file changed, 22 insertions(+), 13 deletions(-)
> 
> diff --git a/migration-rdma.c b/migration-rdma.c
> index d044830..3256c9b 100644
> --- a/migration-rdma.c
> +++ b/migration-rdma.c
> @@ -27,7 +27,7 @@
>  #include <string.h>
>  #include <rdma/rdma_cma.h>
>  
> -#define DEBUG_RDMA
> +//#define DEBUG_RDMA
>  //#define DEBUG_RDMA_VERBOSE
>  //#define DEBUG_RDMA_REALLY_VERBOSE
>  
> @@ -392,6 +392,7 @@ typedef struct RDMAContext {
>      uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
>  
>      GHashTable *blockmap;
> +    bool ipv6;
>  } RDMAContext;
>  
>  /*
> @@ -744,6 +745,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>      char port_str[16];
>      struct rdma_cm_event *cm_event;
>      char ip[40] = "unknown";
> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>  
>      if (rdma->host == NULL || !strcmp(rdma->host, "")) {
>          ERROR(errp, "RDMA hostname has not been set\n");
> @@ -773,7 +775,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>          goto err_resolve_get_addr;
>      }
>  
> -    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
> +    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>                                  ip, sizeof ip);
>      DPRINTF("%s => %s\n", rdma->host, ip);
>  
> @@ -2236,9 +2238,12 @@ err_rdma_source_connect:
>  static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>  {
>      int ret = -EINVAL, idx;
> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>      struct sockaddr_in sin;
>      struct rdma_cm_id *listen_id;
>      char ip[40] = "unknown";
> +    struct addrinfo *res;
> +    char port_str[16];
>  
>      for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
>          rdma->wr_data[idx].control_len = 0;
> @@ -2266,27 +2271,30 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>      }
>  
>      memset(&sin, 0, sizeof(sin));
> -    sin.sin_family = AF_INET;
> +    sin.sin_family = af; 
>      sin.sin_port = htons(rdma->port);
> +    snprintf(port_str, 16, "%d", rdma->port);
> +    port_str[15] = '\0';
>  
>      if (rdma->host && strcmp("", rdma->host)) {
> -        struct hostent *dest_addr;
> -        dest_addr = gethostbyname(rdma->host);
> -        if (!dest_addr) {
> -            ERROR(errp, "migration could not gethostbyname!\n");
> -            ret = -EINVAL;
> +        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
> +        if (ret < 0) {
> +            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
>              goto err_dest_init_bind_addr;
>          }
> -        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
> -                dest_addr->h_length);
> -        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
> +
> +
> +        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
> +                                    ip, sizeof ip);
>      } else {
> -        sin.sin_addr.s_addr = INADDR_ANY;
> +        ERROR(errp, "migration host and port not specified!\n");

Since ERROR() appears to be operating on errp, none of them should be
adding a \n.

Andreas

> +        ret = -EINVAL;
> +        goto err_dest_init_bind_addr;
>      }
>  
>      DPRINTF("%s => %s\n", rdma->host, ip);
>  
> -    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
> +    ret = rdma_bind_addr(listen_id, res->ai_addr);
>      if (ret) {
>          ERROR(errp, "Error: could not rdma_bind_addr!\n");
>          goto err_dest_init_bind_addr;
> @@ -2321,6 +2329,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
>          if (addr != NULL) {
>              rdma->port = atoi(addr->port);
>              rdma->host = g_strdup(addr->host);
> +            rdma->ipv6 = addr->ipv6;
>          } else {
>              ERROR(errp, "bad RDMA migration address '%s'", host_port);
>              g_free(rdma);
>
mrhines@linux.vnet.ibm.com July 27, 2013, 2:37 a.m. UTC | #2
On 07/26/2013 10:30 PM, Andreas Färber wrote:
> Am 27.07.2013 04:23, schrieb mrhines@linux.vnet.ibm.com:
>> From: "Michael R. Hines" <mrhines@us.ibm.com>
>>
>> When testing with libvirt, a simple IPv6 migration test failed
>> because we were not using getaddrinfo() properly.
>> This makes IPv6 migration over RDMA work.
>>
>> Also, we forgot to turn the DPRINTF flag off =).
>>
>> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
>> ---
>>   migration-rdma.c |   35 ++++++++++++++++++++++-------------
>>   1 file changed, 22 insertions(+), 13 deletions(-)
>>
>> diff --git a/migration-rdma.c b/migration-rdma.c
>> index d044830..3256c9b 100644
>> --- a/migration-rdma.c
>> +++ b/migration-rdma.c
>> @@ -27,7 +27,7 @@
>>   #include <string.h>
>>   #include <rdma/rdma_cma.h>
>>   
>> -#define DEBUG_RDMA
>> +//#define DEBUG_RDMA
>>   //#define DEBUG_RDMA_VERBOSE
>>   //#define DEBUG_RDMA_REALLY_VERBOSE
>>   
>> @@ -392,6 +392,7 @@ typedef struct RDMAContext {
>>       uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
>>   
>>       GHashTable *blockmap;
>> +    bool ipv6;
>>   } RDMAContext;
>>   
>>   /*
>> @@ -744,6 +745,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>       char port_str[16];
>>       struct rdma_cm_event *cm_event;
>>       char ip[40] = "unknown";
>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>   
>>       if (rdma->host == NULL || !strcmp(rdma->host, "")) {
>>           ERROR(errp, "RDMA hostname has not been set\n");
>> @@ -773,7 +775,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>           goto err_resolve_get_addr;
>>       }
>>   
>> -    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>> +    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>                                   ip, sizeof ip);
>>       DPRINTF("%s => %s\n", rdma->host, ip);
>>   
>> @@ -2236,9 +2238,12 @@ err_rdma_source_connect:
>>   static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>   {
>>       int ret = -EINVAL, idx;
>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>       struct sockaddr_in sin;
>>       struct rdma_cm_id *listen_id;
>>       char ip[40] = "unknown";
>> +    struct addrinfo *res;
>> +    char port_str[16];
>>   
>>       for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
>>           rdma->wr_data[idx].control_len = 0;
>> @@ -2266,27 +2271,30 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>       }
>>   
>>       memset(&sin, 0, sizeof(sin));
>> -    sin.sin_family = AF_INET;
>> +    sin.sin_family = af;
>>       sin.sin_port = htons(rdma->port);
>> +    snprintf(port_str, 16, "%d", rdma->port);
>> +    port_str[15] = '\0';
>>   
>>       if (rdma->host && strcmp("", rdma->host)) {
>> -        struct hostent *dest_addr;
>> -        dest_addr = gethostbyname(rdma->host);
>> -        if (!dest_addr) {
>> -            ERROR(errp, "migration could not gethostbyname!\n");
>> -            ret = -EINVAL;
>> +        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
>> +        if (ret < 0) {
>> +            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
>>               goto err_dest_init_bind_addr;
>>           }
>> -        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
>> -                dest_addr->h_length);
>> -        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
>> +
>> +
>> +        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>> +                                    ip, sizeof ip);
>>       } else {
>> -        sin.sin_addr.s_addr = INADDR_ANY;
>> +        ERROR(errp, "migration host and port not specified!\n");
> Since ERROR() appears to be operating on errp, none of them should be
> adding a \n.
>
> Andreas

Acknowledged.

>> +        ret = -EINVAL;
>> +        goto err_dest_init_bind_addr;
>>       }
>>   
>>       DPRINTF("%s => %s\n", rdma->host, ip);
>>   
>> -    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
>> +    ret = rdma_bind_addr(listen_id, res->ai_addr);
>>       if (ret) {
>>           ERROR(errp, "Error: could not rdma_bind_addr!\n");
>>           goto err_dest_init_bind_addr;
>> @@ -2321,6 +2329,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
>>           if (addr != NULL) {
>>               rdma->port = atoi(addr->port);
>>               rdma->host = g_strdup(addr->host);
>> +            rdma->ipv6 = addr->ipv6;
>>           } else {
>>               ERROR(errp, "bad RDMA migration address '%s'", host_port);
>>               g_free(rdma);
>>
>
Orit Wasserman July 30, 2013, 8:14 a.m. UTC | #3
On 07/27/2013 05:23 AM, mrhines@linux.vnet.ibm.com wrote:
> From: "Michael R. Hines" <mrhines@us.ibm.com>
> 
> When testing with libvirt, a simple IPv6 migration test failed
> because we were not using getaddrinfo() properly.
> This makes IPv6 migration over RDMA work.
> 
> Also, we forgot to turn the DPRINTF flag off =).
> 
> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
> ---
>  migration-rdma.c |   35 ++++++++++++++++++++++-------------
>  1 file changed, 22 insertions(+), 13 deletions(-)
> 
> diff --git a/migration-rdma.c b/migration-rdma.c
> index d044830..3256c9b 100644
> --- a/migration-rdma.c
> +++ b/migration-rdma.c
> @@ -27,7 +27,7 @@
>  #include <string.h>
>  #include <rdma/rdma_cma.h>
>  
> -#define DEBUG_RDMA
> +//#define DEBUG_RDMA

Can you put this in a separate patch?

>  //#define DEBUG_RDMA_VERBOSE
>  //#define DEBUG_RDMA_REALLY_VERBOSE
>  
> @@ -392,6 +392,7 @@ typedef struct RDMAContext {
>      uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
>  
>      GHashTable *blockmap;
> +    bool ipv6;
>  } RDMAContext;
>  
>  /*
> @@ -744,6 +745,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>      char port_str[16];
>      struct rdma_cm_event *cm_event;
>      char ip[40] = "unknown";
> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;

We have code that handles ipv6 in utils/qemu-sockets.c, it also handle host 
and port parsing please take a look at inet_parse_connect_opts.
I think it can be reused here and for the destination.

Regards,
Orit
>  
>      if (rdma->host == NULL || !strcmp(rdma->host, "")) {
>          ERROR(errp, "RDMA hostname has not been set\n");
> @@ -773,7 +775,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>          goto err_resolve_get_addr;
>      }
>  
> -    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
> +    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>                                  ip, sizeof ip);
>      DPRINTF("%s => %s\n", rdma->host, ip);
>  
> @@ -2236,9 +2238,12 @@ err_rdma_source_connect:
>  static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>  {
>      int ret = -EINVAL, idx;
> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>      struct sockaddr_in sin;
>      struct rdma_cm_id *listen_id;
>      char ip[40] = "unknown";
> +    struct addrinfo *res;
> +    char port_str[16];
>  
>      for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
>          rdma->wr_data[idx].control_len = 0;
> @@ -2266,27 +2271,30 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>      }
>  
>      memset(&sin, 0, sizeof(sin));
> -    sin.sin_family = AF_INET;
> +    sin.sin_family = af; 
>      sin.sin_port = htons(rdma->port);
> +    snprintf(port_str, 16, "%d", rdma->port);
> +    port_str[15] = '\0';
>  
>      if (rdma->host && strcmp("", rdma->host)) {
> -        struct hostent *dest_addr;
> -        dest_addr = gethostbyname(rdma->host);
> -        if (!dest_addr) {
> -            ERROR(errp, "migration could not gethostbyname!\n");
> -            ret = -EINVAL;
> +        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
> +        if (ret < 0) {
> +            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
>              goto err_dest_init_bind_addr;
>          }
> -        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
> -                dest_addr->h_length);
> -        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
> +
> +
> +        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
> +                                    ip, sizeof ip);
>      } else {
> -        sin.sin_addr.s_addr = INADDR_ANY;
> +        ERROR(errp, "migration host and port not specified!\n");
> +        ret = -EINVAL;
> +        goto err_dest_init_bind_addr;
>      }
>  
>      DPRINTF("%s => %s\n", rdma->host, ip);
>  
> -    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
> +    ret = rdma_bind_addr(listen_id, res->ai_addr);
>      if (ret) {
>          ERROR(errp, "Error: could not rdma_bind_addr!\n");
>          goto err_dest_init_bind_addr;
> @@ -2321,6 +2329,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
>          if (addr != NULL) {
>              rdma->port = atoi(addr->port);
>              rdma->host = g_strdup(addr->host);
> +            rdma->ipv6 = addr->ipv6;
>          } else {
>              ERROR(errp, "bad RDMA migration address '%s'", host_port);
>              g_free(rdma);
>
mrhines@linux.vnet.ibm.com July 30, 2013, 2:57 p.m. UTC | #4
On 07/30/2013 04:14 AM, Orit Wasserman wrote:
> On 07/27/2013 05:23 AM, mrhines@linux.vnet.ibm.com wrote:
>> From: "Michael R. Hines" <mrhines@us.ibm.com>
>>
>> When testing with libvirt, a simple IPv6 migration test failed
>> because we were not using getaddrinfo() properly.
>> This makes IPv6 migration over RDMA work.
>>
>> Also, we forgot to turn the DPRINTF flag off =).
>>
>> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
>> ---
>>   migration-rdma.c |   35 ++++++++++++++++++++++-------------
>>   1 file changed, 22 insertions(+), 13 deletions(-)
>>
>> diff --git a/migration-rdma.c b/migration-rdma.c
>> index d044830..3256c9b 100644
>> --- a/migration-rdma.c
>> +++ b/migration-rdma.c
>> @@ -27,7 +27,7 @@
>>   #include <string.h>
>>   #include <rdma/rdma_cma.h>
>>   
>> -#define DEBUG_RDMA
>> +//#define DEBUG_RDMA
> Can you put this in a separate patch?

Acknowledged.

>>   //#define DEBUG_RDMA_VERBOSE
>>   //#define DEBUG_RDMA_REALLY_VERBOSE
>>   
>> @@ -392,6 +392,7 @@ typedef struct RDMAContext {
>>       uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
>>   
>>       GHashTable *blockmap;
>> +    bool ipv6;
>>   } RDMAContext;
>>   
>>   /*
>> @@ -744,6 +745,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>       char port_str[16];
>>       struct rdma_cm_event *cm_event;
>>       char ip[40] = "unknown";
>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
> We have code that handles ipv6 in utils/qemu-sockets.c, it also handle host
> and port parsing please take a look at inet_parse_connect_opts.
> I think it can be reused here and for the destination.

RDMA cannot use that function - it creates a socket and RDMA does not 
use sockets.

RDMA is *already*, however, using inet_parse() which does exactly what 
you said.

> Regards,
> Orit
>>   
>>       if (rdma->host == NULL || !strcmp(rdma->host, "")) {
>>           ERROR(errp, "RDMA hostname has not been set\n");
>> @@ -773,7 +775,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>           goto err_resolve_get_addr;
>>       }
>>   
>> -    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>> +    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>                                   ip, sizeof ip);
>>       DPRINTF("%s => %s\n", rdma->host, ip);
>>   
>> @@ -2236,9 +2238,12 @@ err_rdma_source_connect:
>>   static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>   {
>>       int ret = -EINVAL, idx;
>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>       struct sockaddr_in sin;
>>       struct rdma_cm_id *listen_id;
>>       char ip[40] = "unknown";
>> +    struct addrinfo *res;
>> +    char port_str[16];
>>   
>>       for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
>>           rdma->wr_data[idx].control_len = 0;
>> @@ -2266,27 +2271,30 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>       }
>>   
>>       memset(&sin, 0, sizeof(sin));
>> -    sin.sin_family = AF_INET;
>> +    sin.sin_family = af;
>>       sin.sin_port = htons(rdma->port);
>> +    snprintf(port_str, 16, "%d", rdma->port);
>> +    port_str[15] = '\0';
>>   
>>       if (rdma->host && strcmp("", rdma->host)) {
>> -        struct hostent *dest_addr;
>> -        dest_addr = gethostbyname(rdma->host);
>> -        if (!dest_addr) {
>> -            ERROR(errp, "migration could not gethostbyname!\n");
>> -            ret = -EINVAL;
>> +        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
>> +        if (ret < 0) {
>> +            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
>>               goto err_dest_init_bind_addr;
>>           }
>> -        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
>> -                dest_addr->h_length);
>> -        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
>> +
>> +
>> +        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>> +                                    ip, sizeof ip);
>>       } else {
>> -        sin.sin_addr.s_addr = INADDR_ANY;
>> +        ERROR(errp, "migration host and port not specified!\n");
>> +        ret = -EINVAL;
>> +        goto err_dest_init_bind_addr;
>>       }
>>   
>>       DPRINTF("%s => %s\n", rdma->host, ip);
>>   
>> -    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
>> +    ret = rdma_bind_addr(listen_id, res->ai_addr);
>>       if (ret) {
>>           ERROR(errp, "Error: could not rdma_bind_addr!\n");
>>           goto err_dest_init_bind_addr;
>> @@ -2321,6 +2329,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
>>           if (addr != NULL) {
>>               rdma->port = atoi(addr->port);
>>               rdma->host = g_strdup(addr->host);
>> +            rdma->ipv6 = addr->ipv6;
>>           } else {
>>               ERROR(errp, "bad RDMA migration address '%s'", host_port);
>>               g_free(rdma);
>>
Orit Wasserman July 30, 2013, 3:31 p.m. UTC | #5
On 07/30/2013 05:57 PM, Michael R. Hines wrote:
> On 07/30/2013 04:14 AM, Orit Wasserman wrote:
>> On 07/27/2013 05:23 AM, mrhines@linux.vnet.ibm.com wrote:
>>> From: "Michael R. Hines" <mrhines@us.ibm.com>
>>>
>>> When testing with libvirt, a simple IPv6 migration test failed
>>> because we were not using getaddrinfo() properly.
>>> This makes IPv6 migration over RDMA work.
>>>
>>> Also, we forgot to turn the DPRINTF flag off =).
>>>
>>> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
>>> ---
>>>   migration-rdma.c |   35 ++++++++++++++++++++++-------------
>>>   1 file changed, 22 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/migration-rdma.c b/migration-rdma.c
>>> index d044830..3256c9b 100644
>>> --- a/migration-rdma.c
>>> +++ b/migration-rdma.c
>>> @@ -27,7 +27,7 @@
>>>   #include <string.h>
>>>   #include <rdma/rdma_cma.h>
>>>   -#define DEBUG_RDMA
>>> +//#define DEBUG_RDMA
>> Can you put this in a separate patch?
> 
> Acknowledged.
> 
>>>   //#define DEBUG_RDMA_VERBOSE
>>>   //#define DEBUG_RDMA_REALLY_VERBOSE
>>>   @@ -392,6 +392,7 @@ typedef struct RDMAContext {
>>>       uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
>>>         GHashTable *blockmap;
>>> +    bool ipv6;
>>>   } RDMAContext;
>>>     /*
>>> @@ -744,6 +745,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>>       char port_str[16];
>>>       struct rdma_cm_event *cm_event;
>>>       char ip[40] = "unknown";
>>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>> We have code that handles ipv6 in utils/qemu-sockets.c, it also handle host
>> and port parsing please take a look at inet_parse_connect_opts.
>> I think it can be reused here and for the destination.
> 
> RDMA cannot use that function - it creates a socket and RDMA does not use sockets.
> 
> RDMA is *already*, however, using inet_parse() which does exactly what you said.
> 

You can update the function so it can be used for RDMA also.

Orit

>> Regards,
>> Orit
>>>         if (rdma->host == NULL || !strcmp(rdma->host, "")) {
>>>           ERROR(errp, "RDMA hostname has not been set\n");
>>> @@ -773,7 +775,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>>           goto err_resolve_get_addr;
>>>       }
>>>   -    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>> +    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>>                                   ip, sizeof ip);
>>>       DPRINTF("%s => %s\n", rdma->host, ip);
>>>   @@ -2236,9 +2238,12 @@ err_rdma_source_connect:
>>>   static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>>   {
>>>       int ret = -EINVAL, idx;
>>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>>       struct sockaddr_in sin;
>>>       struct rdma_cm_id *listen_id;
>>>       char ip[40] = "unknown";
>>> +    struct addrinfo *res;
>>> +    char port_str[16];
>>>         for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
>>>           rdma->wr_data[idx].control_len = 0;
>>> @@ -2266,27 +2271,30 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>>       }
>>>         memset(&sin, 0, sizeof(sin));
>>> -    sin.sin_family = AF_INET;
>>> +    sin.sin_family = af;
>>>       sin.sin_port = htons(rdma->port);
>>> +    snprintf(port_str, 16, "%d", rdma->port);
>>> +    port_str[15] = '\0';
>>>         if (rdma->host && strcmp("", rdma->host)) {
>>> -        struct hostent *dest_addr;
>>> -        dest_addr = gethostbyname(rdma->host);
>>> -        if (!dest_addr) {
>>> -            ERROR(errp, "migration could not gethostbyname!\n");
>>> -            ret = -EINVAL;
>>> +        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
>>> +        if (ret < 0) {
>>> +            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
>>>               goto err_dest_init_bind_addr;
>>>           }
>>> -        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
>>> -                dest_addr->h_length);
>>> -        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
>>> +
>>> +
>>> +        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>> +                                    ip, sizeof ip);
>>>       } else {
>>> -        sin.sin_addr.s_addr = INADDR_ANY;
>>> +        ERROR(errp, "migration host and port not specified!\n");
>>> +        ret = -EINVAL;
>>> +        goto err_dest_init_bind_addr;
>>>       }
>>>         DPRINTF("%s => %s\n", rdma->host, ip);
>>>   -    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
>>> +    ret = rdma_bind_addr(listen_id, res->ai_addr);
>>>       if (ret) {
>>>           ERROR(errp, "Error: could not rdma_bind_addr!\n");
>>>           goto err_dest_init_bind_addr;
>>> @@ -2321,6 +2329,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
>>>           if (addr != NULL) {
>>>               rdma->port = atoi(addr->port);
>>>               rdma->host = g_strdup(addr->host);
>>> +            rdma->ipv6 = addr->ipv6;
>>>           } else {
>>>               ERROR(errp, "bad RDMA migration address '%s'", host_port);
>>>               g_free(rdma);
>>>
>
mrhines@linux.vnet.ibm.com July 31, 2013, 1:39 p.m. UTC | #6
On 07/30/2013 11:31 AM, Orit Wasserman wrote:
> On 07/30/2013 05:57 PM, Michael R. Hines wrote:
>> On 07/30/2013 04:14 AM, Orit Wasserman wrote:
>>> On 07/27/2013 05:23 AM, mrhines@linux.vnet.ibm.com wrote:
>>>> From: "Michael R. Hines" <mrhines@us.ibm.com>
>>>>
>>>> When testing with libvirt, a simple IPv6 migration test failed
>>>> because we were not using getaddrinfo() properly.
>>>> This makes IPv6 migration over RDMA work.
>>>>
>>>> Also, we forgot to turn the DPRINTF flag off =).
>>>>
>>>> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
>>>> ---
>>>>    migration-rdma.c |   35 ++++++++++++++++++++++-------------
>>>>    1 file changed, 22 insertions(+), 13 deletions(-)
>>>>
>>>> diff --git a/migration-rdma.c b/migration-rdma.c
>>>> index d044830..3256c9b 100644
>>>> --- a/migration-rdma.c
>>>> +++ b/migration-rdma.c
>>>> @@ -27,7 +27,7 @@
>>>>    #include <string.h>
>>>>    #include <rdma/rdma_cma.h>
>>>>    -#define DEBUG_RDMA
>>>> +//#define DEBUG_RDMA
>>> Can you put this in a separate patch?
>> Acknowledged.
>>
>>>>    //#define DEBUG_RDMA_VERBOSE
>>>>    //#define DEBUG_RDMA_REALLY_VERBOSE
>>>>    @@ -392,6 +392,7 @@ typedef struct RDMAContext {
>>>>        uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
>>>>          GHashTable *blockmap;
>>>> +    bool ipv6;
>>>>    } RDMAContext;
>>>>      /*
>>>> @@ -744,6 +745,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>>>        char port_str[16];
>>>>        struct rdma_cm_event *cm_event;
>>>>        char ip[40] = "unknown";
>>>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>> We have code that handles ipv6 in utils/qemu-sockets.c, it also handle host
>>> and port parsing please take a look at inet_parse_connect_opts.
>>> I think it can be reused here and for the destination.
>> RDMA cannot use that function - it creates a socket and RDMA does not use sockets.
>>
>> RDMA is *already*, however, using inet_parse() which does exactly what you said.
>>
> You can update the function so it can be used for RDMA also.

The inet_parse() function does everything that we need -
it already understands IPv6 without opening an actual socket.

Any more than that would require CONFIG_RDMA to be
conditionalized inside of the utils/ source code,
and that seems like a lot of work for such a small reward.

- Michael

> Orit
>
>>> Regards,
>>> Orit
>>>>          if (rdma->host == NULL || !strcmp(rdma->host, "")) {
>>>>            ERROR(errp, "RDMA hostname has not been set\n");
>>>> @@ -773,7 +775,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>>>            goto err_resolve_get_addr;
>>>>        }
>>>>    -    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>>> +    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>>>                                    ip, sizeof ip);
>>>>        DPRINTF("%s => %s\n", rdma->host, ip);
>>>>    @@ -2236,9 +2238,12 @@ err_rdma_source_connect:
>>>>    static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>>>    {
>>>>        int ret = -EINVAL, idx;
>>>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>>>        struct sockaddr_in sin;
>>>>        struct rdma_cm_id *listen_id;
>>>>        char ip[40] = "unknown";
>>>> +    struct addrinfo *res;
>>>> +    char port_str[16];
>>>>          for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
>>>>            rdma->wr_data[idx].control_len = 0;
>>>> @@ -2266,27 +2271,30 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>>>        }
>>>>          memset(&sin, 0, sizeof(sin));
>>>> -    sin.sin_family = AF_INET;
>>>> +    sin.sin_family = af;
>>>>        sin.sin_port = htons(rdma->port);
>>>> +    snprintf(port_str, 16, "%d", rdma->port);
>>>> +    port_str[15] = '\0';
>>>>          if (rdma->host && strcmp("", rdma->host)) {
>>>> -        struct hostent *dest_addr;
>>>> -        dest_addr = gethostbyname(rdma->host);
>>>> -        if (!dest_addr) {
>>>> -            ERROR(errp, "migration could not gethostbyname!\n");
>>>> -            ret = -EINVAL;
>>>> +        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
>>>> +        if (ret < 0) {
>>>> +            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
>>>>                goto err_dest_init_bind_addr;
>>>>            }
>>>> -        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
>>>> -                dest_addr->h_length);
>>>> -        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
>>>> +
>>>> +
>>>> +        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>>> +                                    ip, sizeof ip);
>>>>        } else {
>>>> -        sin.sin_addr.s_addr = INADDR_ANY;
>>>> +        ERROR(errp, "migration host and port not specified!\n");
>>>> +        ret = -EINVAL;
>>>> +        goto err_dest_init_bind_addr;
>>>>        }
>>>>          DPRINTF("%s => %s\n", rdma->host, ip);
>>>>    -    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
>>>> +    ret = rdma_bind_addr(listen_id, res->ai_addr);
>>>>        if (ret) {
>>>>            ERROR(errp, "Error: could not rdma_bind_addr!\n");
>>>>            goto err_dest_init_bind_addr;
>>>> @@ -2321,6 +2329,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
>>>>            if (addr != NULL) {
>>>>                rdma->port = atoi(addr->port);
>>>>                rdma->host = g_strdup(addr->host);
>>>> +            rdma->ipv6 = addr->ipv6;
>>>>            } else {
>>>>                ERROR(errp, "bad RDMA migration address '%s'", host_port);
>>>>                g_free(rdma);
>>>>
Orit Wasserman July 31, 2013, 4:03 p.m. UTC | #7
On 07/31/2013 04:39 PM, Michael R. Hines wrote:
> On 07/30/2013 11:31 AM, Orit Wasserman wrote:
>> On 07/30/2013 05:57 PM, Michael R. Hines wrote:
>>> On 07/30/2013 04:14 AM, Orit Wasserman wrote:
>>>> On 07/27/2013 05:23 AM, mrhines@linux.vnet.ibm.com wrote:
>>>>> From: "Michael R. Hines" <mrhines@us.ibm.com>
>>>>>
>>>>> When testing with libvirt, a simple IPv6 migration test failed
>>>>> because we were not using getaddrinfo() properly.
>>>>> This makes IPv6 migration over RDMA work.
>>>>>
>>>>> Also, we forgot to turn the DPRINTF flag off =).
>>>>>
>>>>> Signed-off-by: Michael R. Hines <mrhines@us.ibm.com>
>>>>> ---
>>>>>    migration-rdma.c |   35 ++++++++++++++++++++++-------------
>>>>>    1 file changed, 22 insertions(+), 13 deletions(-)
>>>>>
>>>>> diff --git a/migration-rdma.c b/migration-rdma.c
>>>>> index d044830..3256c9b 100644
>>>>> --- a/migration-rdma.c
>>>>> +++ b/migration-rdma.c
>>>>> @@ -27,7 +27,7 @@
>>>>>    #include <string.h>
>>>>>    #include <rdma/rdma_cma.h>
>>>>>    -#define DEBUG_RDMA
>>>>> +//#define DEBUG_RDMA
>>>> Can you put this in a separate patch?
>>> Acknowledged.
>>>
>>>>>    //#define DEBUG_RDMA_VERBOSE
>>>>>    //#define DEBUG_RDMA_REALLY_VERBOSE
>>>>>    @@ -392,6 +392,7 @@ typedef struct RDMAContext {
>>>>>        uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
>>>>>          GHashTable *blockmap;
>>>>> +    bool ipv6;
>>>>>    } RDMAContext;
>>>>>      /*
>>>>> @@ -744,6 +745,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>>>>        char port_str[16];
>>>>>        struct rdma_cm_event *cm_event;
>>>>>        char ip[40] = "unknown";
>>>>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>>> We have code that handles ipv6 in utils/qemu-sockets.c, it also handle host
>>>> and port parsing please take a look at inet_parse_connect_opts.
>>>> I think it can be reused here and for the destination.
>>> RDMA cannot use that function - it creates a socket and RDMA does not use sockets.
>>>
>>> RDMA is *already*, however, using inet_parse() which does exactly what you said.
>>>
>> You can update the function so it can be used for RDMA also.
> 
> The inet_parse() function does everything that we need -
> it already understands IPv6 without opening an actual socket.
> 
> Any more than that would require CONFIG_RDMA to be
> conditionalized inside of the utils/ source code,
> and that seems like a lot of work for such a small reward.
> 

Agreed,
Orit

> - Michael
> 
>> Orit
>>
>>>> Regards,
>>>> Orit
>>>>>          if (rdma->host == NULL || !strcmp(rdma->host, "")) {
>>>>>            ERROR(errp, "RDMA hostname has not been set\n");
>>>>> @@ -773,7 +775,7 @@ static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
>>>>>            goto err_resolve_get_addr;
>>>>>        }
>>>>>    -    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>>>> +    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>>>>                                    ip, sizeof ip);
>>>>>        DPRINTF("%s => %s\n", rdma->host, ip);
>>>>>    @@ -2236,9 +2238,12 @@ err_rdma_source_connect:
>>>>>    static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>>>>    {
>>>>>        int ret = -EINVAL, idx;
>>>>> +    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
>>>>>        struct sockaddr_in sin;
>>>>>        struct rdma_cm_id *listen_id;
>>>>>        char ip[40] = "unknown";
>>>>> +    struct addrinfo *res;
>>>>> +    char port_str[16];
>>>>>          for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
>>>>>            rdma->wr_data[idx].control_len = 0;
>>>>> @@ -2266,27 +2271,30 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
>>>>>        }
>>>>>          memset(&sin, 0, sizeof(sin));
>>>>> -    sin.sin_family = AF_INET;
>>>>> +    sin.sin_family = af;
>>>>>        sin.sin_port = htons(rdma->port);
>>>>> +    snprintf(port_str, 16, "%d", rdma->port);
>>>>> +    port_str[15] = '\0';
>>>>>          if (rdma->host && strcmp("", rdma->host)) {
>>>>> -        struct hostent *dest_addr;
>>>>> -        dest_addr = gethostbyname(rdma->host);
>>>>> -        if (!dest_addr) {
>>>>> -            ERROR(errp, "migration could not gethostbyname!\n");
>>>>> -            ret = -EINVAL;
>>>>> +        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
>>>>> +        if (ret < 0) {
>>>>> +            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
>>>>>                goto err_dest_init_bind_addr;
>>>>>            }
>>>>> -        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
>>>>> -                dest_addr->h_length);
>>>>> -        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
>>>>> +
>>>>> +
>>>>> +        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
>>>>> +                                    ip, sizeof ip);
>>>>>        } else {
>>>>> -        sin.sin_addr.s_addr = INADDR_ANY;
>>>>> +        ERROR(errp, "migration host and port not specified!\n");
>>>>> +        ret = -EINVAL;
>>>>> +        goto err_dest_init_bind_addr;
>>>>>        }
>>>>>          DPRINTF("%s => %s\n", rdma->host, ip);
>>>>>    -    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
>>>>> +    ret = rdma_bind_addr(listen_id, res->ai_addr);
>>>>>        if (ret) {
>>>>>            ERROR(errp, "Error: could not rdma_bind_addr!\n");
>>>>>            goto err_dest_init_bind_addr;
>>>>> @@ -2321,6 +2329,7 @@ static void *qemu_rdma_data_init(const char *host_port, Error **errp)
>>>>>            if (addr != NULL) {
>>>>>                rdma->port = atoi(addr->port);
>>>>>                rdma->host = g_strdup(addr->host);
>>>>> +            rdma->ipv6 = addr->ipv6;
>>>>>            } else {
>>>>>                ERROR(errp, "bad RDMA migration address '%s'", host_port);
>>>>>                g_free(rdma);
>>>>>
>
Anthony Liguori Aug. 14, 2013, 4:29 p.m. UTC | #8
Applied.  Thanks.

Regards,

Anthony Liguori
diff mbox

Patch

diff --git a/migration-rdma.c b/migration-rdma.c
index d044830..3256c9b 100644
--- a/migration-rdma.c
+++ b/migration-rdma.c
@@ -27,7 +27,7 @@ 
 #include <string.h>
 #include <rdma/rdma_cma.h>
 
-#define DEBUG_RDMA
+//#define DEBUG_RDMA
 //#define DEBUG_RDMA_VERBOSE
 //#define DEBUG_RDMA_REALLY_VERBOSE
 
@@ -392,6 +392,7 @@  typedef struct RDMAContext {
     uint64_t unregistrations[RDMA_SIGNALED_SEND_MAX];
 
     GHashTable *blockmap;
+    bool ipv6;
 } RDMAContext;
 
 /*
@@ -744,6 +745,7 @@  static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
     char port_str[16];
     struct rdma_cm_event *cm_event;
     char ip[40] = "unknown";
+    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
 
     if (rdma->host == NULL || !strcmp(rdma->host, "")) {
         ERROR(errp, "RDMA hostname has not been set\n");
@@ -773,7 +775,7 @@  static int qemu_rdma_resolve_host(RDMAContext *rdma, Error **errp)
         goto err_resolve_get_addr;
     }
 
-    inet_ntop(AF_INET, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
+    inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
                                 ip, sizeof ip);
     DPRINTF("%s => %s\n", rdma->host, ip);
 
@@ -2236,9 +2238,12 @@  err_rdma_source_connect:
 static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
 {
     int ret = -EINVAL, idx;
+    int af = rdma->ipv6 ? PF_INET6 : PF_INET;
     struct sockaddr_in sin;
     struct rdma_cm_id *listen_id;
     char ip[40] = "unknown";
+    struct addrinfo *res;
+    char port_str[16];
 
     for (idx = 0; idx <= RDMA_WRID_MAX; idx++) {
         rdma->wr_data[idx].control_len = 0;
@@ -2266,27 +2271,30 @@  static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
     }
 
     memset(&sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
+    sin.sin_family = af; 
     sin.sin_port = htons(rdma->port);
+    snprintf(port_str, 16, "%d", rdma->port);
+    port_str[15] = '\0';
 
     if (rdma->host && strcmp("", rdma->host)) {
-        struct hostent *dest_addr;
-        dest_addr = gethostbyname(rdma->host);
-        if (!dest_addr) {
-            ERROR(errp, "migration could not gethostbyname!\n");
-            ret = -EINVAL;
+        ret = getaddrinfo(rdma->host, port_str, NULL, &res);
+        if (ret < 0) {
+            ERROR(errp, "could not getaddrinfo address %s\n", rdma->host);
             goto err_dest_init_bind_addr;
         }
-        memcpy(&sin.sin_addr.s_addr, dest_addr->h_addr,
-                dest_addr->h_length);
-        inet_ntop(AF_INET, dest_addr->h_addr, ip, sizeof ip);
+
+
+        inet_ntop(af, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
+                                    ip, sizeof ip);
     } else {
-        sin.sin_addr.s_addr = INADDR_ANY;
+        ERROR(errp, "migration host and port not specified!\n");
+        ret = -EINVAL;
+        goto err_dest_init_bind_addr;
     }
 
     DPRINTF("%s => %s\n", rdma->host, ip);
 
-    ret = rdma_bind_addr(listen_id, (struct sockaddr *)&sin);
+    ret = rdma_bind_addr(listen_id, res->ai_addr);
     if (ret) {
         ERROR(errp, "Error: could not rdma_bind_addr!\n");
         goto err_dest_init_bind_addr;
@@ -2321,6 +2329,7 @@  static void *qemu_rdma_data_init(const char *host_port, Error **errp)
         if (addr != NULL) {
             rdma->port = atoi(addr->port);
             rdma->host = g_strdup(addr->host);
+            rdma->ipv6 = addr->ipv6;
         } else {
             ERROR(errp, "bad RDMA migration address '%s'", host_port);
             g_free(rdma);