/* ssize_t fi_tsenddata(struct fid_ep *ep, void *buf, size_t len, void *desc, uint64_t data, fi_addr_t dest_addr, void *context); */ void do_tsenddata(int len) { int ret; ssize_t sz; int source_done = 0, dest_done = 0; struct fi_cq_tagged_entry s_cqe, d_cqe; rdm_tagged_sr_init_data(source, len, 0xab); rdm_tagged_sr_init_data(target, len, 0); sz = fi_tsenddata(ep[0], source, len, loc_mr, (uint64_t)source, gni_addr[1], len, target); cr_assert_eq(sz, 0); sz = fi_trecv(ep[1], target, len, rem_mr, gni_addr[0], len, 0, source); cr_assert_eq(sz, 0); /* need to progress both CQs simultaneously for rendezvous */ do { ret = fi_cq_read(msg_cq[0], &s_cqe, 1); if (ret == 1) { source_done = 1; } ret = fi_cq_read(msg_cq[1], &d_cqe, 1); if (ret == 1) { dest_done = 1; } } while (!(source_done && dest_done)); dbg_printf("got context events!\n"); cr_assert(rdm_tagged_sr_check_data(source, target, len), "Data mismatch"); }
void api_tagged_send_recv(int len) { ssize_t sz; uint64_t caps = fi[0]->caps; rdm_api_init_data(source, len, 0xab); rdm_api_init_data(target, len, 0); sz = fi_tsend(ep[0], source, len, loc_mr, gni_addr[1], len, target); if (TAG_SEND_ALLOWED(caps)) { cr_assert(sz == 0, "fi_tsend failed caps:0x%lx err:%ld", caps, sz); } else { cr_assert(sz < 0, "fi_tsend should fail caps:0x%lx err:%ld", caps, sz); } sz = fi_trecv(ep[1], target, len, rem_mr, gni_addr[0], len, 0, source); if (TAG_RECV_ALLOWED(caps)) { cr_assert(sz == 0, "fi_trecv failed caps:0x%lx err:%ld", caps, sz); } else { cr_assert(sz < 0, "fi_trecv should fail caps:0x%lx err:%ld", caps, sz); } }
static int recv_xfer(int size) { struct fi_cq_tagged_entry comp; int ret; do { ret = fi_cq_read(rcq, &comp, 1); if (ret < 0 && ret != -FI_EAGAIN) { if (ret == -FI_EAVAIL) { cq_readerr(rcq, "rcq"); } else { FT_PRINTERR("fi_cq_read", ret); } return ret; } } while (ret == -FI_EAGAIN); /* Posting recv for next send. Hence tag_data + 1 */ ret = fi_trecv(ep, buf, buffer_size, fi_mr_desc(mr), remote_fi_addr, tag_data + 1, 0, &fi_ctx_trecv); if (ret) FT_PRINTERR("fi_trecv", ret); return ret; }
void do_tinject(int len) { int ret; ssize_t sz; struct fi_cq_tagged_entry cqe; rdm_tagged_sr_init_data(source, len, 0x23); rdm_tagged_sr_init_data(target, len, 0); sz = fi_tinject(ep[0], source, len, gni_addr[1], len); cr_assert_eq(sz, 0); sz = fi_trecv(ep[1], target, len, rem_mr, gni_addr[0], len, 0, source); cr_assert_eq(sz, 0); while ((ret = fi_cq_read(msg_cq[1], &cqe, 1)) == -FI_EAGAIN) { pthread_yield(); } cr_assert_eq(ret, 1); cr_assert_eq((uint64_t)cqe.op_context, (uint64_t)source); dbg_printf("got recv context event!\n"); cr_assert(rdm_tagged_sr_check_data(source, target, len), "Data mismatch"); }
Test(rdm_tagged_sr, multi_tsend_trecv) { int i, it, ridx, ret; const int iters = 37; const int num_msgs = 17; const int slen = 256; uint64_t tags[num_msgs]; uint64_t rtag = 0x01000000; uint64_t ignore = 0xf0ffffff; char msg[num_msgs][slen]; struct fi_cq_tagged_entry cqe; srand(time(NULL)); for (it = 0; it < iters; it++) { for (i = 0; i < num_msgs; i++) { tags[i] = 0x01010abc + it*iters + i; sprintf(msg[i], "%d\n", i); ret = fi_tsend(ep[1], msg[i], strlen(msg[i]), NULL, gni_addr[0], tags[i], NULL); cr_assert(ret == FI_SUCCESS); do { ret = fi_cq_read(msg_cq[1], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(cqe.len == 0); cr_assert(cqe.tag == 0); } for (i = 0; i < num_msgs; i++) { ret = fi_trecv(ep[0], target, BUF_SZ, fi_mr_desc(loc_mr), gni_addr[1], rtag, ignore, NULL); cr_assert(ret == FI_SUCCESS); do { ret = fi_cq_read(msg_cq[0], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(rtag != cqe.tag); ret = sscanf(target, "%d", &ridx); cr_assert(ret == 1); cr_assert(cqe.len == strlen(msg[ridx])); /* zero out the tag for error checking below */ tags[ridx] = 0; } /* Make sure we got everything */ for (i = 0; i < num_msgs; i++) cr_assert(tags[i] == 0); } }
static int post_recv(uint64_t tag) { int ret; // posting recv for next send ret = fi_trecv(ep, buf, buffer_size, fi_mr_desc(mr), remote_fi_addr, tag, 0, &fi_ctx_recv); if (ret) FT_PRINTERR("fi_trecv", ret); return ret; }
static int receive_loop(size_t size) { int ret; int q_opts = 0; struct fi_context recv_ctx[max_opts]; while (q_opts < max_opts) { do { ft_tag = q_opts + 1; if (tagged) ret = fi_trecv(ep, rx_buf, size, NULL, remote_fi_addr, ft_tag, 0x0, (void *) &recv_ctx[q_opts]); else ret = fi_recv(ep, rx_buf, size, NULL, remote_fi_addr, (void *) &recv_ctx[q_opts]); if (ret == FI_SUCCESS) { rx_seq++; q_opts++; } } while (!ret && (q_opts != max_opts)); if (ret < 0) { if (ret == -FI_EAGAIN) { if (delay > 0) sleep(delay); ret = ft_get_rx_comp(rx_seq); if (ret) return ret; } else { FT_PRINTERR("Recv OP", ret); return ret; } } } if (delay > 0) sleep(delay); ret = ft_get_rx_comp(rx_seq); if (ret) return ret; if (opts.verbose) printf("Success: Completed %d queued ops\n", q_opts); return 0; }
static int recv_msg(uint64_t tag) { int ret; // posting recv for next send ret = fi_trecv(ep, buf, buffer_size, fi_mr_desc(mr), remote_fi_addr, tag, 0, &fi_ctx_recv); if (ret) FT_PRINTERR("fi_trecv", ret); // wait for the completion event ret = wait_for_tagged_completion(rcq, 1); return ret; }
static int recv_msg(void) { int ret; ret = fi_trecv(ep, buf, buffer_size, fi_mr_desc(mr), remote_fi_addr, tag_control, 0, &fi_ctx_trecv); if (ret) { FT_PRINTERR("fi_trecv", ret); return ret; } ret = wait_for_completion_tagged(rcq, 1); return ret; }
/* ssize_t fi_tsendmsg(struct fid_ep *ep, const struct fi_msg *msg, uint64_t flags); */ void do_tsendmsg(int len) { int ret; ssize_t sz; int source_done = 0, dest_done = 0; struct fi_cq_tagged_entry s_cqe, d_cqe; struct fi_msg_tagged msg; struct iovec iov; iov.iov_base = source; iov.iov_len = len; msg.msg_iov = &iov; msg.desc = (void **)&loc_mr; msg.iov_count = 1; msg.addr = gni_addr[1]; msg.context = target; msg.data = (uint64_t)target; msg.tag = len; msg.ignore = 0; rdm_tagged_sr_init_data(source, len, 0xef); rdm_tagged_sr_init_data(target, len, 0); sz = fi_tsendmsg(ep[0], &msg, 0); cr_assert_eq(sz, 0); sz = fi_trecv(ep[1], target, len, rem_mr, gni_addr[0], len, 0, source); cr_assert_eq(sz, 0); /* need to progress both CQs simultaneously for rendezvous */ do { ret = fi_cq_read(msg_cq[0], &s_cqe, 1); if (ret == 1) { source_done = 1; } ret = fi_cq_read(msg_cq[1], &d_cqe, 1); if (ret == 1) { dest_done = 1; } } while (!(source_done && dest_done)); dbg_printf("got context events!\n"); cr_assert(rdm_tagged_sr_check_data(source, target, len), "Data mismatch"); }
/* ssize_t fi_tsendv(struct fid_ep *ep, const struct iovec *iov, void **desc, size_t count, fi_addr_t dest_addr, uint64_t tag, void *context); */ void do_tsendv(int len) { int i, ret, iov_cnt; ssize_t sz; int source_done = 0, dest_done = 0; struct fi_cq_tagged_entry s_cqe, d_cqe; sz = fi_tsendv(ep[0], src_iov, NULL, 0, gni_addr[1], len * IOV_CNT, iov_dest_buf); cr_assert_eq(sz, -FI_EINVAL); for (iov_cnt = 1; iov_cnt <= IOV_CNT; iov_cnt++) { rdm_tagged_sr_init_data(iov_dest_buf, len * iov_cnt, 0); for (i = 0; i < iov_cnt; i++) { rdm_tagged_sr_init_data(src_iov[i].iov_base, len, 0xab); src_iov[i].iov_len = len; } sz = fi_tsendv(ep[0], src_iov, NULL, iov_cnt, gni_addr[1], len * iov_cnt, iov_dest_buf); cr_assert_eq(sz, 0); sz = fi_trecv(ep[1], iov_dest_buf, len * iov_cnt, NULL, gni_addr[0], len * iov_cnt, 0, src_iov); cr_assert_eq(sz, 0); /* need to progress both CQs simultaneously for rendezvous */ do { ret = fi_cq_read(msg_cq[0], &s_cqe, 1); if (ret == 1) { source_done = 1; } ret = fi_cq_read(msg_cq[1], &d_cqe, 1); if (ret == 1) { dest_done = 1; } } while (!(source_done && dest_done)); dbg_printf("got recv context event!\n"); cr_assert(rdm_tagged_sr_check_iov_data(src_iov, iov_dest_buf, iov_cnt), "Data mismatch"); source_done = dest_done = 0; } }
ssize_t ft_post_rx(size_t size) { ssize_t ret; if (hints->caps & FI_TAGGED) { ret = fi_trecv(ep, rx_buf, size + ft_rx_prefix_size(), fi_mr_desc(mr), 0, rx_seq, 0, &rx_ctx); } else { ret = fi_recv(ep, rx_buf, size + ft_rx_prefix_size(), fi_mr_desc(mr), 0, &rx_ctx); } if (ret) { FT_PRINTERR("receive", ret); return ret; } rx_seq++; return 0; }
static void do_tagged_sr_pipelined(void) { int i, it, s, ret; const int iters = 37; const int num_msgs = 61; const int msgs_per_stage = 17; const int num_stages = num_msgs/msgs_per_stage + (num_msgs%msgs_per_stage != 0); const int slen = 256; uint64_t tags[num_msgs]; uint64_t rtag = 0x01000000; uint64_t ignore = 0xf0ffffff; char msg[num_msgs][slen]; struct fi_cq_tagged_entry cqe; srand(time(NULL)); for (it = 0; it < iters; it++) { dbg_printf("iter %d\n", it); for (s = 0; s < num_stages; s++) { dbg_printf("\tsending stage %d\n", s); for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { tags[i] = 0x01010abc + it*iters + i; sprintf(msg[i], "%d\n", i%10); ret = fi_tsend(ep[1], msg[i], strlen(msg[i]), NULL, gni_addr[0], tags[i], NULL); cr_assert(ret == FI_SUCCESS); } for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { do { ret = fi_cq_read(msg_cq[1], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(cqe.tag == 0); } cr_assert(cqe.len == 0); } for (s = 0; s < num_stages; s++) { dbg_printf("\treceiving stage %d\n", s); for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { ret = fi_trecv(ep[0], &target[i], BUF_SZ, fi_mr_desc(loc_mr), gni_addr[1], rtag, ignore, NULL); cr_assert(ret == FI_SUCCESS); } for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { do { ret = fi_cq_read(msg_cq[0], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(rtag != cqe.tag); cr_assert(ret == 1); cr_assert(cqe.len == 2); /* zero out the tag for error checking below */ tags[cqe.tag - (0x01010abc + it*iters)] = 0; } } /* Make sure we got everything */ for (i = 0; i < num_msgs; i++) { cr_assert(tags[i] == 0); } } }
static int init_av(void) { int ret; if (opts.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) { FT_PRINTERR("fi_getname", ret); return ret; } local_addr = malloc(addrlen); ret = fi_getname(&ep->fid, local_addr, &addrlen); if (ret) { FT_PRINTERR("fi_getname", ret); return ret; } ret = fi_av_insert(av, remote_addr, 1, &remote_fi_addr, 0, &fi_ctx_av); if (ret != 1) { FT_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 = recv_msg(); if (ret) return ret; } else { /* Post a recv to get the remote address */ ret = recv_msg(); 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) { FT_PRINTERR("fi_av_insert", ret); return ret; } /* Send ACK */ ret = send_msg(16); if (ret) return ret; } /* Post first recv */ ret = fi_trecv(ep, buf, buffer_size, fi_mr_desc(mr), remote_fi_addr, tag_data, 0, &fi_ctx_trecv); if (ret) FT_PRINTERR("fi_trecv", ret); return ret; }
static int run(void) { int ret; ret = init_fabric(); if (ret) return ret; ret = ft_init_av(); if (ret) return ret; if (opts.dst_addr) { printf("Searching for a bad msg\n"); ret = tagged_peek(0xbad); if (ret != -FI_ENOMSG) { FT_PRINTERR("FI_PEEK", ret); return ret; } printf("Synchronizing with sender..\n"); ret = ft_sync(); if (ret) return ret; printf("Searching for a good msg\n"); ret = tagged_peek(0x900d); if (ret != 1) { FT_PRINTERR("FI_PEEK", ret); return ret; } printf("Receiving msg\n"); ret = fi_trecv(ep, buf, rx_size, fi_mr_desc(mr), remote_fi_addr, 0x900d, 0, &rx_ctx); if (ret) { FT_PRINTERR("fi_trecv", ret); return ret; } printf("Completing recv\n"); ret = ft_get_rx_comp(++rx_seq); if (ret) return ret; } else { printf("Sending tagged message\n"); ret = fi_tsend(ep, tx_buf, tx_size, fi_mr_desc(mr), remote_fi_addr, 0x900d, &tx_ctx); if (ret) return ret; printf("Synchronizing with receiver..\n"); ret = ft_sync(); if (ret) return ret; printf("Getting send completion\n"); ret = ft_get_tx_comp(tx_seq + 1); if (ret) return ret; } ft_finalize(); return 0; }