int main(int argc, char *argv[]) { struct ibv_device *ib_dev; struct pingpong_context ctx; struct pingpong_dest *my_dest,*rem_dest; struct perftest_parameters user_param; struct perftest_comm user_comm; int i = 0; memset(&ctx,0,sizeof(struct pingpong_context)); memset(&user_param, 0, sizeof(struct perftest_parameters)); memset(&user_comm,0,sizeof(struct perftest_comm)); user_param.verb = WRITE; user_param.tst = BW; user_param.spec = PL; user_param.version = VERSION; // Configure the parameters values according to user arguments or defalut values. if (parser(&user_param,argv,argc)) { fprintf(stderr," Parser function exited with Error\n"); return 1; } // Finding the IB device selected (or defalut if no selected). ib_dev = ctx_find_dev(user_param.ib_devname); if (!ib_dev) { fprintf(stderr," Unable to find the Infiniband/RoCE deivce\n"); return 1; } // Getting the relevant context from the device ctx.context = ibv_open_device(ib_dev); if (!ctx.context) { fprintf(stderr, " Couldn't get context for the device\n"); return 1; } // See if MTU and link type are valid and supported. if (check_link_and_mtu(ctx.context,&user_param)) { fprintf(stderr, " Couldn't get context for the device\n"); return FAILURE; } // Print basic test information. ctx_print_test_info(&user_param); ALLOCATE(my_dest , struct pingpong_dest , user_param.num_of_qps); memset(my_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); ALLOCATE(rem_dest , struct pingpong_dest , user_param.num_of_qps); memset(rem_dest, 0, sizeof(struct pingpong_dest)*user_param.num_of_qps); // copy the rellevant user parameters to the comm struct + creating rdma_cm resources. if (create_comm_struct(&user_comm,&user_param)) { fprintf(stderr," Unable to create RDMA_CM resources\n"); return 1; } // Create (if nessacery) the rdma_cm ids and channel. if (user_param.work_rdma_cm == ON) { if (create_rdma_resources(&ctx,&user_param)) { fprintf(stderr," Unable to create the rdma_resources\n"); return FAILURE; } if (user_param.machine == CLIENT) { if (rdma_client_connect(&ctx,&user_param)) { fprintf(stderr,"Unable to perform rdma_client function\n"); return FAILURE; } } else { if (rdma_server_connect(&ctx,&user_param)) { fprintf(stderr,"Unable to perform rdma_client function\n"); return FAILURE; } } } else { // create all the basic IB resources (data buffer, PD, MR, CQ and events channel) if (ctx_init(&ctx,&user_param)) { fprintf(stderr, " Couldn't create IB resources\n"); return FAILURE; } } // Set up the Connection. if (set_up_connection(&ctx,&user_param,my_dest)) { fprintf(stderr," Unable to set up socket connection\n"); return FAILURE; } // Print this machine QP information for (i=0; i < user_param.num_of_qps; i++) ctx_print_pingpong_data(&my_dest[i],&user_comm); // Init the connection and print the local data. if (establish_connection(&user_comm)) { fprintf(stderr," Unable to init the socket connection\n"); return FAILURE; } // shaking hands and gather the other side info. for (i=0; i < user_param.num_of_qps; i++) { if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { fprintf(stderr," Failed to exchange date between server and clients\n"); return 1; } // Print remote machine QP information user_comm.rdma_params->side = REMOTE; ctx_print_pingpong_data(&rem_dest[i],&user_comm); if (user_param.work_rdma_cm == OFF) { if (pp_connect_ctx(&ctx,my_dest[i].psn,&rem_dest[i],&user_param,i)) { fprintf(stderr," Unable to Connect the HCA's through the link\n"); return FAILURE; } } // An additional handshake is required after moving qp to RTR. if (ctx_hand_shake(&user_comm,&my_dest[i],&rem_dest[i])) { fprintf(stderr," Failed to exchange date between server and clients\n"); return FAILURE; } } printf(RESULT_LINE); printf(RESULT_FMT); // For half duplex tests, server just waits for client to exit if (user_param.machine == SERVER && !user_param.duplex) { if (ctx_close_connection(&user_comm,&my_dest[0],&rem_dest[0])) { fprintf(stderr,"Failed to close connection between server and client\n"); return 1; } printf(RESULT_LINE); return 0; } ALLOCATE(tposted,cycles_t,user_param.iters*user_param.num_of_qps); ALLOCATE(tcompleted,cycles_t,user_param.iters*user_param.num_of_qps); if (user_param.all == ON) { for (i = 1; i < 24 ; ++i) { user_param.size = 1 << i; if(run_iter(&ctx,&user_param,rem_dest)) return 17; print_report(&user_param); } } else { if(run_iter(&ctx,&user_param,rem_dest)) return 18; print_report(&user_param); } free(tposted); free(tcompleted); // Closing connection. if (ctx_close_connection(&user_comm,&my_dest[0],&rem_dest[0])) { fprintf(stderr,"Failed to close connection between server and client\n"); return 1; } free(my_dest); free(rem_dest); printf(RESULT_LINE); return 0; }
static int pp_open_port(struct pingpong_context *ctx, const char * servername, int ib_port, int port, struct pingpong_dest *rem_dest,struct user_parameters *user_parm) { char addr_fmt[] = "%8s address: LID %#04x QPN %#06x PSN %#06x\n"; struct pingpong_dest my_dest; int sockfd; int rc; union ibv_gid gid; /* Create connection between client and server. * We do it by exchanging data over a TCP socket connection. */ my_dest.lid = pp_get_local_lid(ctx, ib_port); my_dest.qpn = ctx->qp->qp_num; my_dest.psn = lrand48() & 0xffffff; if (user_parm->gid_index < 0) {/*We do not fail test upon lid in RDMA0E/Eth conf*/ if (!my_dest.lid) { fprintf(stderr, "Local lid 0x0 detected. Is an SM running?\n"); return -1; } } if (user_parm->gid_index != -1) { int err=0; err = ibv_query_gid (ctx->context, ib_port, user_parm->gid_index, &gid); if (err) { return -1; } ctx->dgid=gid; } my_dest.dgid = gid; my_dest.rkey = ctx->mr->rkey; my_dest.vaddr = (uintptr_t)ctx->buf + ctx->size; printf(addr_fmt, "local", my_dest.lid, my_dest.qpn, my_dest.psn); if (user_parm->gid_index > -1) { printf(" GID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", my_dest.dgid.raw[0],my_dest.dgid.raw[1], my_dest.dgid.raw[2], my_dest.dgid.raw[3], my_dest.dgid.raw[4], my_dest.dgid.raw[5], my_dest.dgid.raw[6], my_dest.dgid.raw[7], my_dest.dgid.raw[8], my_dest.dgid.raw[9], my_dest.dgid.raw[10], my_dest.dgid.raw[11], my_dest.dgid.raw[12], my_dest.dgid.raw[13], my_dest.dgid.raw[14], my_dest.dgid.raw[15]); } sockfd = servername ? pp_client_connect(servername, port) : pp_server_connect(port); if (sockfd < 0) { printf("pp_connect_sock(%s,%d) failed (%d)!\n", servername, port, sockfd); return sockfd; } rc = servername ? pp_client_exch_dest(sockfd, &my_dest, rem_dest, user_parm) : pp_server_exch_dest(sockfd, &my_dest, rem_dest, user_parm); if (rc) return rc; printf(addr_fmt, "remote", rem_dest->lid, rem_dest->qpn, rem_dest->psn, rem_dest->rkey, rem_dest->vaddr); if (user_parm->gid_index > -1) { printf(" GID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", rem_dest->dgid.raw[0],rem_dest->dgid.raw[1], rem_dest->dgid.raw[2], rem_dest->dgid.raw[3], rem_dest->dgid.raw[4], rem_dest->dgid.raw[5], rem_dest->dgid.raw[6], rem_dest->dgid.raw[7], rem_dest->dgid.raw[8], rem_dest->dgid.raw[9], rem_dest->dgid.raw[10], rem_dest->dgid.raw[11], rem_dest->dgid.raw[12], rem_dest->dgid.raw[13], rem_dest->dgid.raw[14], rem_dest->dgid.raw[15]); } if ((rc = pp_connect_ctx(ctx, ib_port, my_dest.psn, rem_dest,user_parm))) return rc; /* An additional handshake is required *after* moving qp to RTR. * Arbitrarily reuse exch_dest for this purpose. */ rc = servername ? pp_client_exch_dest(sockfd, &my_dest, rem_dest, user_parm) : pp_server_exch_dest(sockfd, &my_dest, rem_dest, user_parm); if (rc) return rc; if (write(sockfd, "done", sizeof "done") != sizeof "done"){ perror("write"); fprintf(stderr, "Couldn't write to socket\n"); return 1; } close(sockfd); return 0; }
static struct pingpong_dest *pp_server_exch_dest(struct pingpong_context *ctx, int ib_port, enum ibv_mtu mtu, int port, int sl, const struct pingpong_dest *my_dest) { struct addrinfo *res, *t; struct addrinfo hints = { .ai_flags = AI_PASSIVE, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; char *service; char msg[sizeof "0000:000000:000000"]; int n; int sockfd = -1, connfd; struct pingpong_dest *rem_dest = NULL; if (asprintf(&service, "%d", port) < 0) return NULL; n = getaddrinfo(NULL, service, &hints, &res); if (n < 0) { fprintf(stderr, "%s for port %d\n", gai_strerror(n), port); free(service); return NULL; } for (t = res; t; t = t->ai_next) { sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol); if (sockfd >= 0) { n = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n); if (!bind(sockfd, t->ai_addr, t->ai_addrlen)) break; close(sockfd); sockfd = -1; } } freeaddrinfo(res); free(service); if (sockfd < 0) { fprintf(stderr, "Couldn't listen to port %d\n", port); return NULL; } listen(sockfd, 1); connfd = accept(sockfd, NULL, 0); close(sockfd); if (connfd < 0) { fprintf(stderr, "accept() failed\n"); return NULL; } n = read(connfd, msg, sizeof msg); if (n != sizeof msg) { perror("server read"); fprintf(stderr, "%d/%d: Couldn't read remote address\n", n, (int) sizeof msg); goto out; } rem_dest = malloc(sizeof *rem_dest); if (!rem_dest) goto out; sscanf(msg, "%x:%x:%x", &rem_dest->lid, &rem_dest->qpn, &rem_dest->psn); if (pp_connect_ctx(ctx, ctx->qp, ib_port, my_dest->psn, mtu, sl, rem_dest)) { fprintf(stderr, "Couldn't connect to remote QP\n"); free(rem_dest); rem_dest = NULL; goto out; } sprintf(msg, "%04x:%06x:%06x", my_dest->lid, my_dest->qpn, my_dest->psn); if (write(connfd, msg, sizeof msg) != sizeof msg) { fprintf(stderr, "Couldn't send local address\n"); free(rem_dest); rem_dest = NULL; goto out; } /* expecting "done" msg */ if (read(connfd, msg, sizeof(msg)) <= 0) { fprintf(stderr, "Couldn't read \"done\" msg\n"); free(rem_dest); rem_dest = NULL; goto out; } out: close(connfd); return rem_dest; }
int main(int argc, char *argv[]) { int i = 0; struct report_options report = {}; struct pingpong_context ctx; struct ibv_device *ib_dev; struct perftest_parameters user_param; struct pingpong_dest my_dest,rem_dest; struct perftest_comm user_comm; /* init default values to user's parameters */ memset(&ctx,0,sizeof(struct pingpong_context)); memset(&user_param,0,sizeof(struct perftest_parameters)); memset(&user_comm,0,sizeof(struct perftest_comm)); memset(&my_dest,0,sizeof(struct pingpong_dest)); memset(&rem_dest,0,sizeof(struct pingpong_dest)); user_param.verb = READ; user_param.tst = LAT; user_param.r_flag = &report; user_param.version = VERSION; // Configure the parameters values according to user arguments or defalut values. if (parser(&user_param,argv,argc)) { fprintf(stderr," Parser function exited with Error\n"); return FAILURE; } // Finding the IB device selected (or defalut if no selected). ib_dev = ctx_find_dev(user_param.ib_devname); if (!ib_dev) { fprintf(stderr," Unable to find the Infiniband/RoCE deivce\n"); return FAILURE; } // Getting the relevant context from the device ctx.context = ibv_open_device(ib_dev); if (!ctx.context) { fprintf(stderr, " Couldn't get context for the device\n"); return 1; } // See if MTU and link type are valid and supported. if (check_link_and_mtu(ctx.context,&user_param)) { fprintf(stderr, " Couldn't get context for the device\n"); return FAILURE; } // Print basic test information. ctx_print_test_info(&user_param); // copy the rellevant user parameters to the comm struct + creating rdma_cm resources. if (create_comm_struct(&user_comm,&user_param)) { fprintf(stderr," Unable to create RDMA_CM resources\n"); return 1; } // Create (if nessacery) the rdma_cm ids and channel. if (user_param.work_rdma_cm == ON) { if (create_rdma_resources(&ctx,&user_param)) { fprintf(stderr," Unable to create the rdma_resources\n"); return FAILURE; } if (user_param.machine == CLIENT) { if (rdma_client_connect(&ctx,&user_param)) { fprintf(stderr,"Unable to perform rdma_client function\n"); return FAILURE; } } else { if (rdma_server_connect(&ctx,&user_param)) { fprintf(stderr,"Unable to perform rdma_client function\n"); return FAILURE; } } } else { // create all the basic IB resources (data buffer, PD, MR, CQ and events channel) if (ctx_init(&ctx,&user_param)) { fprintf(stderr, " Couldn't create IB resources\n"); return FAILURE; } } // Set up the Connection. if (set_up_connection(&ctx,&user_param,&my_dest)) { fprintf(stderr," Unable to set up socket connection\n"); return 1; } ctx_print_pingpong_data(&my_dest,&user_comm); // Init the connection and print the local data. if (establish_connection(&user_comm)) { fprintf(stderr," Unable to init the socket connection\n"); return 1; } // shaking hands and gather the other side info. if (ctx_hand_shake(&user_comm,&my_dest,&rem_dest)) { fprintf(stderr,"Failed to exchange date between server and clients\n"); return 1; } user_comm.rdma_params->side = REMOTE; ctx_print_pingpong_data(&rem_dest,&user_comm); if (user_param.work_rdma_cm == OFF) { if (pp_connect_ctx(&ctx,my_dest.psn,&rem_dest,my_dest.out_reads,&user_param)) { fprintf(stderr," Unable to Connect the HCA's through the link\n"); return 1; } } // An additional handshake is required after moving qp to RTR. if (ctx_hand_shake(&user_comm,&my_dest,&rem_dest)) { fprintf(stderr,"Failed to exchange date between server and clients\n"); return 1; } ALLOCATE(tstamp,cycles_t,user_param.iters); // Only Client post read request. if (user_param.machine == SERVER) { if (ctx_close_connection(&user_comm,&my_dest,&rem_dest)) { fprintf(stderr,"Failed to close connection between server and client\n"); return 1; } printf(RESULT_LINE); return 0; // destroy_ctx(&ctx,&user_param); } if (user_param.use_event) { if (ibv_req_notify_cq(ctx.send_cq, 0)) { fprintf(stderr, "Couldn't request CQ notification\n"); return 1; } } printf(RESULT_LINE); printf(RESULT_FMT_LAT); if (user_param.all == ON) { for (i = 1; i < 24 ; ++i) { user_param.size = 1 << i; if(run_iter(&ctx,&user_param,&rem_dest)) return 17; print_report(&user_param); } } else { if(run_iter(&ctx,&user_param,&rem_dest)) return 18; print_report(&user_param); } if (ctx_close_connection(&user_comm,&my_dest,&rem_dest)) { fprintf(stderr,"Failed to close connection between server and client\n"); return 1; } printf(RESULT_LINE); return 0; // destroy_ctx(&ctx,&user_param); }
int main(int argc, char *argv[]) { uint64_t flags = 0; char *service = NULL; char *node = NULL; struct pingpong_context *ctx; struct timeval start, end; unsigned long size = 4096; // No provider support yet //enum ibv_mtu mtu = IBV_MTU_1024; //size_t mtu = 1024; int rx_depth_default = 500; int rx_depth = 0; int iters = 1000; int use_event = 0; int rcnt, scnt; int ret, rc = 0; char * ptr; srand48(getpid() * time(NULL)); opts = INIT_OPTS; hints = fi_allocinfo(); if (!hints) return 1; while (1) { int c; c = getopt(argc, argv, "S:m:r:n:eh" ADDR_OPTS INFO_OPTS); if (c == -1) break; switch (c) { case 'S': errno = 0; size = strtol(optarg, &ptr, 10); if (ptr == optarg || *ptr != '\0' || ((size == LONG_MIN || size == LONG_MAX) && errno == ERANGE)) { fprintf(stderr, "Cannot convert from string to long\n"); rc = 1; goto err1; } break; // No provider support yet /*case 'm': mtu = strtol(optarg, NULL, 0); mtu = pp_mtu_to_enum(strtol(optarg, NULL, 0)); if (mtu < 0) { usage(argv[0]); return 1; } break; */ case 'r': rx_depth = strtol(optarg, NULL, 0); break; case 'n': iters = strtol(optarg, NULL, 0); break; case 'e': ++use_event; break; default: ft_parse_addr_opts(c, optarg, &opts); ft_parseinfo(c, optarg, hints); break; case '?': case 'h': usage(argv[0]); return 1; } } if (optind == argc - 1) opts.dst_addr = argv[optind]; else if (optind < argc) { usage(argv[0]); return 1; } page_size = sysconf(_SC_PAGESIZE); hints->ep_attr->type = FI_EP_MSG; hints->caps = FI_MSG; hints->mode = FI_LOCAL_MR; rc = ft_read_addr_opts(&node, &service, hints, &flags, &opts); if (rc) return -rc; rc = fi_getinfo(FT_FIVERSION, node, service, flags, hints, &fi); if (rc) { FT_PRINTERR("fi_getinfo", rc); return -rc; } fi_freeinfo(hints); if (rx_depth) { if (rx_depth > fi->rx_attr->size) { fprintf(stderr, "rx_depth requested: %d, " "rx_depth supported: %zd\n", rx_depth, fi->rx_attr->size); rc = 1; goto err1; } } else { rx_depth = (rx_depth_default > fi->rx_attr->size) ? fi->rx_attr->size : rx_depth_default; } ctx = pp_init_ctx(fi, size, rx_depth, use_event); if (!ctx) { rc = 1; goto err1; } if (opts.dst_addr) { /* client connect */ if (pp_connect_ctx(ctx)) { rc = 1; goto err2; } } else { /* server listen and accept */ pp_listen_ctx(ctx); pp_accept_ctx(ctx); } ctx->pending = PINGPONG_RECV_WCID; if (opts.dst_addr) { if (pp_post_send(ctx)) { fprintf(stderr, "Couldn't post send\n"); rc = 1; goto err3; } ctx->pending |= PINGPONG_SEND_WCID; } if (gettimeofday(&start, NULL)) { perror("gettimeofday"); rc = 1; goto err3; } rcnt = scnt = 0; while (rcnt < iters || scnt < iters) { struct fi_cq_entry wc; struct fi_cq_err_entry cq_err; int rd; if (use_event) { /* Blocking read */ rd = fi_cq_sread(ctx->cq, &wc, 1, NULL, -1); } else { do { rd = fi_cq_read(ctx->cq, &wc, 1); } while (rd == -FI_EAGAIN); } if (rd < 0) { fi_cq_readerr(ctx->cq, &cq_err, 0); fprintf(stderr, "cq fi_cq_readerr() %s (%d)\n", fi_cq_strerror(ctx->cq, cq_err.err, cq_err.err_data, NULL, 0), cq_err.err); rc = rd; goto err3; } switch ((int) (uintptr_t) wc.op_context) { case PINGPONG_SEND_WCID: ++scnt; break; case PINGPONG_RECV_WCID: if (--ctx->routs <= 1) { ctx->routs += pp_post_recv(ctx, ctx->rx_depth - ctx->routs); if (ctx->routs < ctx->rx_depth) { fprintf(stderr, "Couldn't post receive (%d)\n", ctx->routs); rc = 1; goto err3; } } ++rcnt; break; default: fprintf(stderr, "Completion for unknown wc_id %d\n", (int) (uintptr_t) wc.op_context); rc = 1; goto err3; } ctx->pending &= ~(int) (uintptr_t) wc.op_context; if (scnt < iters && !ctx->pending) { if (pp_post_send(ctx)) { fprintf(stderr, "Couldn't post send\n"); rc = 1; goto err3; } ctx->pending = PINGPONG_RECV_WCID | PINGPONG_SEND_WCID; } } if (gettimeofday(&end, NULL)) { perror("gettimeofday"); rc = 1; goto err3; } { float usec = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); long long bytes = (long long) size * iters * 2; printf("%lld bytes in %.2f seconds = %.2f Mbit/sec\n", bytes, usec / 1000000., bytes * 8. / usec); printf("%d iters in %.2f seconds = %.2f usec/iter\n", iters, usec / 1000000., usec / iters); } err3: fi_shutdown(ctx->ep, 0); err2: ret = pp_close_ctx(ctx); if (!rc) rc = ret; err1: fi_freeinfo(fi); return rc; }