static int run_test() { int ret; size_t size = 1000; uint64_t remote_cq_data; struct fi_cq_data_entry comp; /* Set remote_cq_data based on the cq_data_size we got from fi_getinfo */ remote_cq_data = 0x0123456789abcdef & ((0x1ULL << (cq_data_size * 8)) - 1); if (dst_addr) { fprintf(stdout, "Posting send with immediate data: %lx\n", remote_cq_data); ret = fi_senddata(ep, buf, size, fi_mr_desc(mr), remote_cq_data, 0, buf); if (ret) { FI_PRINTERR("fi_send", ret); return ret; } wait_for_completion(scq, 1); fprintf(stdout, "Done\n"); } else { ret = fi_recv(ep, buf, size, fi_mr_desc(mr), 0, buf); if (ret) { FI_PRINTERR("fi_recv", ret); return ret; } fprintf(stdout, "Waiting for immediate data from client\n"); ret = fi_cq_sread(rcq, &comp, 1, NULL, -1); if (ret < 0) { if (ret == -FI_EAVAIL) { cq_readerr(rcq, "rcq"); } else { FI_PRINTERR("fi_cq_read: rcq", ret); } return ret; } /* Verify completion data */ if (comp.flags & FI_REMOTE_CQ_DATA) { if (comp.data == remote_cq_data) fprintf(stdout, "remote_cq_data: success\n"); else fprintf(stdout, "remote_cq_data: failure\n"); fprintf(stdout, "Expected data:0x%lx, Received data:0x%lx\n", remote_cq_data, comp.data); } } return 0; }
int bind_fid( fid_t ep, fid_t res, uint64_t flags) { int ret; ret = fi_bind(ep, res, flags); if (ret) FI_PRINTERR("fi_bind", ret); return ret; }
void cq_readerr(struct fid_cq *cq, char *cq_str) { struct fi_cq_err_entry cq_err; const char *err_str; int ret; ret = fi_cq_readerr(cq, &cq_err, 0); if (ret < 0) FI_PRINTERR("fi_cq_readerr", ret); err_str = fi_cq_strerror(cq, cq_err.prov_errno, cq_err.err_data, NULL, 0); FI_DEBUG("%s %s (%d)\n", cq_str, err_str, cq_err.prov_errno); }
int wait_for_completion(struct fid_cq *cq, int num_completions) { int ret; struct fi_cq_entry comp; while (num_completions > 0) { ret = fi_cq_read(cq, &comp, 1); if (ret > 0) { num_completions--; } else if (ret < 0) { if (ret == -FI_EAVAIL) { cq_readerr(cq, "cq"); } else { FI_PRINTERR("fi_cq_read", ret); } return ret; } } return 0; }
static int init_av(void) { int ret; if (dst_addr) { // get local address blob. Find the addrlen first. We set // addrlen as 0 and fi_getname will return the actual addrlen addrlen = 0; ret = fi_getname(&ep->fid, local_addr, &addrlen); if (ret != -FI_ETOOSMALL) { FI_PRINTERR("fi_getname", ret); return ret; } local_addr = malloc(addrlen); ret = fi_getname(&ep->fid, local_addr, &addrlen); if (ret) { FI_PRINTERR("fi_getname", ret); return ret; } ret = fi_av_insert(av, remote_addr, 1, &remote_fi_addr, 0, &fi_ctx_av); if (ret != 1) { FI_PRINTERR("fi_av_insert", ret); return ret; } // send local addr size and local addr memcpy(buf, &addrlen, sizeof(size_t)); memcpy(buf + sizeof(size_t), local_addr, addrlen); ret = send_msg(sizeof(size_t) + addrlen); if (ret) return ret; // receive ACK from server ret = post_recv(); if (ret) return ret; } else { // post a recv to get the remote address ret = post_recv(); if (ret) return ret; memcpy(&addrlen, buf, sizeof(size_t)); remote_addr = malloc(addrlen); memcpy(remote_addr, buf + sizeof(size_t), addrlen); ret = fi_av_insert(av, remote_addr, 1, &remote_fi_addr, 0, &fi_ctx_av); if (ret != 1) { FI_PRINTERR("fi_av_insert", ret); return ret; } // send ACK ret = send_msg(16); if (ret) return ret; } return ret; }
static int init_fabric(void) { struct fi_info *fi; char *node; uint64_t flags = 0; int ret; if (src_addr) { ret = getaddr(src_addr, NULL, (struct sockaddr **) &hints.src_addr, (socklen_t *) &hints.src_addrlen); if (ret) { fprintf(stderr, "source address error %s\n", gai_strerror(ret)); return ret; } } if (dst_addr) { node = dst_addr; } else { node = src_addr; flags = FI_SOURCE; } ret = fi_getinfo(FI_VERSION(1, 0), node, port, flags, &hints, &fi); if (ret) { FI_PRINTERR("fi_getinfo", ret); return ret; } // we use provider MR attributes and direct address (no offsets) // for RMA calls if (!(fi->mode & FI_PROV_MR_ATTR)) fi->mode |= FI_PROV_MR_ATTR; // get remote address if (dst_addr) { addrlen = fi->dest_addrlen; remote_addr = malloc(addrlen); memcpy(remote_addr, fi->dest_addr, addrlen); } ret = fi_fabric(fi->fabric_attr, &fab, NULL); if (ret) { FI_PRINTERR("fi_fabric", ret); goto err0; } ret = fi_domain(fab, fi, &dom, NULL); if (ret) { FI_PRINTERR("fi_domain", ret); goto err1; } ret = fi_endpoint(dom, fi, &ep, NULL); if (ret) { FI_PRINTERR("fi_endpoint", ret); goto err2; } if (dst_addr == NULL) { printf("EP opened on fabric %s\n", fi->fabric_attr->name); } ret = alloc_ep_res(fi); if (ret) goto err3; ret = bind_ep_res(); if (ret) goto err4; return 0; err4: free_ep_res(); err3: fi_close(&ep->fid); err2: fi_close(&dom->fid); err1: fi_close(&fab->fid); err0: fi_freeinfo(fi); return ret; }
static int alloc_ep_res(struct fi_info *fi) { struct fi_cq_attr cq_attr; struct fi_av_attr av_attr; int ret; buffer_size = !run_all_sizes ? test_size[TEST_CNT - 1].size : transfer_size; buf = malloc(MAX(buffer_size, sizeof(uint64_t))); if (!buf) { perror("malloc"); return -1; } result = malloc(MAX(buffer_size, sizeof(uint64_t))); if (!result) { perror("malloc"); return -1; } compare = malloc(MAX(buffer_size, sizeof(uint64_t))); if (!compare) { perror("malloc"); return -1; } memset(&cq_attr, 0, sizeof cq_attr); cq_attr.format = FI_CQ_FORMAT_CONTEXT; cq_attr.wait_obj = FI_WAIT_NONE; cq_attr.size = 128; ret = fi_cq_open(dom, &cq_attr, &scq, NULL); if (ret) { fprintf(stderr, "fi_cq_open send comp %s\n", fi_strerror(-ret)); goto err1; } ret = fi_cq_open(dom, &cq_attr, &rcq, NULL); if (ret) { fprintf(stderr, "fi_cq_open recv comp %s\n", fi_strerror(-ret)); goto err2; } // registers local data buffer buff that specifies // the first operand of the atomic operation ret = fi_mr_reg(dom, buf, MAX(buffer_size, sizeof(uint64_t)), FI_REMOTE_READ | FI_REMOTE_WRITE, 0, 0, 0, &mr, NULL); if (ret) { fprintf(stderr, "fi_mr_reg %s\n", fi_strerror(-ret)); goto err3; } // registers local data buffer that stores initial value of // the remote buffer ret = fi_mr_reg(dom, result, MAX(buffer_size, sizeof(uint64_t)), FI_REMOTE_READ | FI_REMOTE_WRITE, 0, 0, 0, &mr_result, NULL); if (ret) { fprintf(stderr, "fi_mr_reg %s\n", fi_strerror(-ret)); goto err4; } // registers local data buffer that contains comparison data ret = fi_mr_reg(dom, compare, MAX(buffer_size, sizeof(uint64_t)), FI_REMOTE_READ | FI_REMOTE_WRITE, 0, 0, 0, &mr_compare, NULL); if (ret) { fprintf(stderr, "fi_mr_reg %s\n", fi_strerror(-ret)); goto err5; } memset(&av_attr, 0, sizeof av_attr); av_attr.type = FI_AV_MAP; av_attr.count = 1; av_attr.name = NULL; ret = fi_av_open(dom, &av_attr, &av, NULL); if (ret) { FI_PRINTERR("fi_av_open", ret); goto err6; } return 0; err6: fi_close(&mr_compare->fid); err5: fi_close(&mr_result->fid); err4: fi_close(&mr->fid); err3: fi_close(&rcq->fid); err2: fi_close(&scq->fid); err1: free(buf); free(result); free(compare); return ret; }