diff --git a/man/perftest.1 b/man/perftest.1 index d3f6f780..6fc8e816 100644 --- a/man/perftest.1 +++ b/man/perftest.1 @@ -268,6 +268,10 @@ many different options and modes. Use IPv6 GID. Default is IPv4. Not relevant for RawEth. .TP +.B --ipv6-addr= + Use IPv6 address for parameters negotiation. Default is IPv4. + Not relevant for RawEth. +.TP .B --bind_source_ip Source IP of the interface used for connection establishment. By default taken from routing table. Not relevant for RawEth. diff --git a/src/perftest_communication.c b/src/perftest_communication.c index db9ae6dd..1c464d59 100755 --- a/src/perftest_communication.c +++ b/src/perftest_communication.c @@ -669,7 +669,7 @@ static int ethernet_client_connect(struct perftest_comm *comm) int sockfd = -1; memset(&hints, 0, sizeof hints); - hints.ai_family = AF_INET; + hints.ai_family = comm->rdma_params->ai_family; hints.ai_socktype = SOCK_STREAM; if (comm->rdma_params->has_source_ip) { @@ -726,7 +726,7 @@ static int ethernet_server_connect(struct perftest_comm *comm) memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; - hints.ai_family = AF_INET; + hints.ai_family = comm->rdma_params->ai_family; hints.ai_socktype = SOCK_STREAM; if (check_add_port(&service,comm->rdma_params->port,src_ip,&hints,&res)) @@ -736,6 +736,9 @@ static int ethernet_server_connect(struct perftest_comm *comm) } for (t = res; t; t = t->ai_next) { + if (t->ai_family != comm->rdma_params->ai_family) + continue; + sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol); if (sockfd >= 0) { @@ -906,7 +909,8 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters { char *service; int temp,num_of_retry= NUM_OF_RETRIES; - struct sockaddr_in sin, source_sin; + struct sockaddr_storage source_sin; + struct sockaddr *sin; struct sockaddr *source_ptr = NULL; struct addrinfo *res; struct rdma_cm_event *event; @@ -914,7 +918,7 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters struct addrinfo hints; memset(&hints, 0, sizeof hints); - hints.ai_family = AF_INET; + hints.ai_family = user_param->ai_family; hints.ai_socktype = SOCK_STREAM; if (check_add_port(&service,user_param->port,user_param->servername,&hints,&res)) { @@ -922,13 +926,13 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters return FAILURE; } - if (res->ai_family != PF_INET) { + if (res->ai_family != user_param->ai_family) { freeaddrinfo(res); return FAILURE; } - memcpy(&sin, res->ai_addr, sizeof(sin)); - freeaddrinfo(res); - sin.sin_port = htons((unsigned short)user_param->port); + + sin = res->ai_addr; + sockaddr_set_port(sin, (unsigned short)user_param->port); if (user_param->has_source_ip) { if (check_add_port(&service, 0x0, user_param->source_ip, &hints, &res)) @@ -940,7 +944,6 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters //coverity[deref_after_free] memcpy(&source_sin, res->ai_addr, sizeof(source_sin)); source_ptr = (struct sockaddr *)&source_sin; - freeaddrinfo(res); } while (1) { @@ -950,12 +953,14 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters return FAILURE; } - if (rdma_resolve_addr(ctx->cm_id, source_ptr, (struct sockaddr *)&sin, 2000)) { + if (rdma_resolve_addr(ctx->cm_id, source_ptr, sin, 2000)) { + freeaddrinfo(res); fprintf(stderr, "rdma_resolve_addr failed\n"); return FAILURE; } if (rdma_get_cm_event(ctx->cm_channel,&event)) { + freeaddrinfo(res); fprintf(stderr, "rdma_get_cm_events failed\n"); return FAILURE; } @@ -969,6 +974,7 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters if (event->event != RDMA_CM_EVENT_ADDR_RESOLVED) { fprintf(stderr, "unexpected CM event %d\n",event->event); + freeaddrinfo(res); rdma_ack_cm_event(event); return FAILURE; } @@ -977,6 +983,8 @@ int rdma_client_connect(struct pingpong_context *ctx,struct perftest_parameters break; } + freeaddrinfo(res); + if (user_param->tos != DEF_TOS) { if (rdma_set_option(ctx->cm_id,RDMA_OPTION_ID,RDMA_OPTION_ID_TOS,&user_param->tos,sizeof(uint8_t))) { @@ -1124,35 +1132,36 @@ int rdma_server_connect(struct pingpong_context *ctx, struct rdma_conn_param conn_param; struct addrinfo hints; char *service; - struct sockaddr_in sin; + struct sockaddr *sin; char* src_ip = user_param->has_source_ip ? user_param->source_ip : NULL; memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; - hints.ai_family = AF_INET; + hints.ai_family = user_param->ai_family; hints.ai_socktype = SOCK_STREAM; - memset(&sin, 0x0, sizeof(sin)); - if (check_add_port(&service,user_param->port,src_ip,&hints,&res)) { fprintf(stderr, "Problem in resolving basic address and port\n"); return FAILURE; } - if (res->ai_family != PF_INET) { + if (res->ai_family != user_param->ai_family) { freeaddrinfo(res); return FAILURE; } - memcpy(&sin, res->ai_addr, sizeof(sin)); - sin.sin_port = htons((unsigned short)user_param->port); - freeaddrinfo(res); - if (rdma_bind_addr(ctx->cm_id_control,(struct sockaddr *)&sin)) { + sin = res->ai_addr; + sockaddr_set_port(sin, (unsigned short)user_param->port); + + if (rdma_bind_addr(ctx->cm_id_control, sin)) { + freeaddrinfo(res); fprintf(stderr," rdma_bind_addr failed\n"); return 1; } + freeaddrinfo(res); + if (rdma_listen(ctx->cm_id_control, user_param->num_of_qps)) { fprintf(stderr, "rdma_listen failed\n"); return 1; @@ -1243,6 +1252,7 @@ int create_comm_struct(struct perftest_comm *comm, memset(comm->rdma_params, 0, sizeof(struct perftest_parameters)); comm->rdma_params->port = user_param->port; + comm->rdma_params->ai_family = user_param->ai_family; comm->rdma_params->sockfd = -1; comm->rdma_params->gid_index = user_param->gid_index; comm->rdma_params->gid_index2 = user_param->gid_index2; @@ -2034,7 +2044,7 @@ int rdma_cm_get_rdma_address(struct perftest_parameters *user_param, char port[6] = "", error_message[ERROR_MSG_SIZE] = ""; sprintf(port, "%d", user_param->port); - hints->ai_family = AF_INET; + hints->ai_family = user_param->ai_family; // if we have servername specified, it is a client, we should use server name // if it is not specified, we should use explicit source_ip if possible if ((NULL != user_param->servername) || (!user_param->has_source_ip)) { diff --git a/src/perftest_parameters.c b/src/perftest_parameters.c index 1257f8f8..67281f70 100755 --- a/src/perftest_parameters.c +++ b/src/perftest_parameters.c @@ -461,6 +461,8 @@ static void usage(const char *argv0, VerbType verb, TestType tst, int connection if (connection_type != RawEth) { printf(" --ipv6 "); printf(" Use IPv6 GID. Default is IPv4\n"); + printf(" --ipv6-addr= "); + printf(" Use IPv6 address for parameters negotiation. Default is IPv4\n"); } // please note it is a different source_ip from raw_ethernet case @@ -816,6 +818,7 @@ static void init_perftest_params(struct perftest_parameters *user_param) user_param->retry_count = DEF_RETRY_COUNT; user_param->dont_xchg_versions = 0; user_param->ipv6 = 0; + user_param->ai_family = AF_INET; user_param->report_per_port = 0; user_param->use_odp = 0; user_param->use_hugepages = 0; @@ -2175,6 +2178,7 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc) static int mmap_file_flag = 0; static int mmap_offset_flag = 0; static int ipv6_flag = 0; + static int ipv6_addr_flag = 0; static int raw_ipv6_flag = 0; static int report_per_port_flag = 0; static int odp_flag = 0; @@ -2326,6 +2330,7 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc) { .name = "mmap", .has_arg = 1, .flag = &mmap_file_flag, .val = 1}, { .name = "mmap-offset", .has_arg = 1, .flag = &mmap_offset_flag, .val = 1}, { .name = "ipv6", .has_arg = 0, .flag = &ipv6_flag, .val = 1}, + { .name = "ipv6-addr", .has_arg = 0, .flag = &ipv6_addr_flag, .val = 1}, #ifdef HAVE_IPV6 { .name = "raw_ipv6", .has_arg = 0, .flag = &raw_ipv6_flag, .val = 1}, #endif @@ -3047,6 +3052,10 @@ int parser(struct perftest_parameters *user_param,char *argv[], int argc) user_param->ipv6 = 1; } + if (ipv6_addr_flag) { + user_param->ai_family = AF_INET6; + } + if (raw_ipv6_flag) { if (user_param->is_new_raw_eth_param) { if (user_param->is_server_ip) { diff --git a/src/perftest_parameters.h b/src/perftest_parameters.h index 0ed65ba5..559bfa48 100755 --- a/src/perftest_parameters.h +++ b/src/perftest_parameters.h @@ -602,6 +602,7 @@ struct perftest_parameters { int dont_xchg_versions; int ipv6; int raw_ipv6; + int ai_family; int report_per_port; int use_odp; int use_hugepages; diff --git a/src/perftest_resources.c b/src/perftest_resources.c index 971eb8fe..d9ec4319 100755 --- a/src/perftest_resources.c +++ b/src/perftest_resources.c @@ -831,13 +831,30 @@ int check_add_port(char **service,int port, free(*service); if (number < 0) { - fprintf(stderr, "%s for %s:%d\n", gai_strerror(number), servername, port); + fprintf(stderr, "%s for ai_family: %x service: %s port: %d\n", + gai_strerror(number), hints->ai_family, servername, port); return FAILURE; } return SUCCESS; } +/****************************************************************************** + * + ******************************************************************************/ +int sockaddr_set_port(struct sockaddr *sin,int port) +{ + switch (sin->sa_family) { + case AF_INET: ((struct sockaddr_in*) sin)->sin_port = htons(port); + break; + case AF_INET6: ((struct sockaddr_in6*) sin)->sin6_port = htons(port); + break; + default: + fprintf(stderr, "ai_family: %x is not yet supported\n", sin->sa_family); + return FAILURE; + } + return SUCCESS; +} /****************************************************************************** * ******************************************************************************/ diff --git a/src/perftest_resources.h b/src/perftest_resources.h index 274c9e7c..e782dded 100755 --- a/src/perftest_resources.h +++ b/src/perftest_resources.h @@ -260,6 +260,19 @@ int check_add_port(char **service,int port, struct addrinfo *hints, struct addrinfo **res); +/* sockaddr_set_port + * + * Description : Initialize port for given sockaddr structure + * + * Parameters : + * service - an empty char** to contain the service name. + * port - The selected port on which the server will listen. + * sin - sockaddr params for the connection. + * + * Return Value : SUCCESS, FAILURE. + */ +int sockaddr_set_port(struct sockaddr *sin,int port); + /* ctx_find_dev * * Description : Returns the device corresponding to ib_devname