/* called with rxlock, process all RR's up to signal marker at wr_last */ static void m_pi_post_writeto(struct mcm_qp *m_qp, struct mcm_wr_rx *wr_sig, struct ibv_wc *wc) { mcm_scif_dev_t *smd = m_qp->smd; struct mcm_wr_rx *wr_rx; struct mcm_sr *m_sr = NULL; off_t l_off, l_off_wr, r_off; int ret, i, l_start, l_end, l_len, sg_len, w_len, num_sge, wr_idx, wr_cnt = 0; int wt_flag; wr_idx = m_qp->wr_tl_r_wt; /* from WT tail, process RR's posted until reaching wr_last */ while (m_qp->pi_rr_cnt) { /* RR's pending */ wr_rx = (struct mcm_wr_rx *)(m_qp->wrc.wr_addr + (m_qp->wrc.wr_sz * wr_idx)); if (!(wr_rx->flags & M_READ_POSTED)) { /* reached RR signaled marker, or head pointer */ if (wr_idx == wr_sig->w_idx || wr_idx == m_qp->wr_hd_r) break; wr_idx = (wr_idx + 1) & m_qp->wrc.wr_end; /* next WR */ continue; } wr_cnt++; #if MCM_PROFILE if (wr_rx == wr_sig) mcm_qp_prof_ts(m_qp, MCM_QP_IB_RR, wr_rx->time, wr_rx->qcnt, wr_cnt); #endif mlog(4, " WR_rx[%d-%d] %p m_qp %p wc %p wc->op %x wr_rx->wr.op %x\n", wr_rx->w_idx, wr_sig->w_idx, wr_rx, m_qp, wc, wc->opcode, wr_rx->wr.opcode); m_qp->pi_rr_cnt--; /* rdma read complete */ MCNTR(smd->md, MCM_QP_READ_DONE); /* if SR or RW_imm, need a posted receive */ if ((wr_rx->wr.opcode & IBV_WR_SEND) || (wr_rx->wr.opcode & IBV_WR_RDMA_WRITE_WITH_IMM)) { m_sr = m_pi_get_sr(m_qp, wr_rx->w_idx); if (!m_sr) { mlog(0, " WARNING: SR stalled, no RCV messages posted" " m_qp %p, sr_tl %d sr_hd %d\n", m_qp, m_qp->sr_tl, m_qp->sr_hd); wr_rx->flags |= M_RECV_PAUSED; return; } wr_rx->s_idx = m_sr->s_idx; /* link WR_RX and SR */ m_sr->len = 0; num_sge = m_sr->num_sge; sg_len = m_sr->sg[0].length; r_off = m_sr->sg[0].addr; /* post recv buffer address */ mlog(4, " WR SR or RW_IMM: m_sr[%d] %p -> scif r_off %Lx ln %d\n", m_sr->s_idx, m_sr, r_off, sg_len); } /* need to translate to rdma write dst */ if (!(wr_rx->wr.opcode & IBV_WR_SEND)) { num_sge = 1; sg_len = wr_rx->sg[2].length; r_off = m_pi_mr_trans(smd, wr_rx->wr.wr.rdma.remote_addr, wr_rx->wr.wr.rdma.rkey, sg_len); if (!r_off) goto bail; mlog(4, " RDMA_WRITE op: wr_rx[%d] %p -> scif r_off %Lx len %d\n", wr_rx->w_idx, wr_rx, r_off, sg_len, 0); } /* sg[0] entry == proxy-out buffer, src for IB RR */ /* sg[1] entry == proxy-in buffer, dst for IB RR */ /* sg[2] entry == proxy-in buffer src for scif_sendto */ /* wr.rdma.remote_addr, wr.rdma.rkey, dst for scif_sento - TPT to sci_off */ wr_rx->wr.wr_id = 0; l_off_wr = (uint64_t) (m_qp->wr_off_r + (wr_rx->w_idx * m_qp->wrc.wr_sz)); l_off = wr_rx->sg[2].addr; l_len = wr_rx->sg[2].length; l_start = l_off - (uint64_t)smd->m_offset_r; l_end = l_start + l_len; for (i=0; (i<num_sge && l_len); i++) { w_len = min(sg_len, l_len); wt_flag = 0; mlog(4, " WR_rx[%d] %p writeto l_off %Lx r_off %Lx rb_off 0x%x-0x%x ln %d org_id %Lx tl %d hd %d\n", wr_rx->w_idx, wr_rx, l_off, r_off, l_start, l_end, w_len, wr_rx->org_id, m_qp->wr_tl_r, m_qp->wr_hd_r); #if MCM_PROFILE wr_rx->time = mcm_ts_us(); wr_rx->qcnt = m_qp->post_cnt_wt; #endif if (w_len < 256) wt_flag = SCIF_RMA_USECPU; ret = scif_writeto(smd->scif_tx_ep, l_off, w_len, r_off, wt_flag); if (ret) { mlog(0, " ERR: scif_sendto, ret %d err: %d %s\n", ret, errno, strerror(errno)); goto bail; } MCNTR(smd->md, MCM_SCIF_WRITE_TO); /* adjust for multiple SG entries on post_recv */ l_off += w_len; l_len = l_len - w_len; if (m_sr) { m_sr->len += w_len; r_off = m_sr->sg[i].addr; /* next SR segment */ sg_len = m_sr->sg[i].length; } } if (l_len) { mlog(0, " ERR: RX overrun: written %d remaining %d sge's %d\n", wr_rx->sg[2].length, l_len, num_sge); goto bail; } /* signal last segment */ mlog(4, " SCIF_fence_signal: l_off_wr %p, wr_rx %p wr_idx %d\n", l_off_wr, wr_rx, wr_rx->w_idx); ret = scif_fence_signal(smd->scif_tx_ep, l_off_wr, wr_rx->org_id, 0, 0, SCIF_FENCE_INIT_SELF | SCIF_SIGNAL_LOCAL); if (ret) { mlog(0," ERR: scif_fence_signal, ret %d %s\n", ret, strerror(errno)); goto bail; } MCNTR(smd->md, MCM_SCIF_SIGNAL); wr_rx->flags &= ~M_READ_POSTED; /* reset READ_POSTED */ wr_rx->flags |= M_READ_DONE; wr_rx->flags |= M_READ_WRITE_TO; m_qp->post_cnt_wt++; /* reached RR signaled marker, or head */ if (wr_idx == wr_sig->w_idx || wr_idx == m_qp->wr_hd_r) break; wr_idx = (wr_idx + 1) & m_qp->wrc.wr_end; /* next WR */ } write(smd->md->mc->rx_pipe[1], "w", sizeof "w"); /* signal rx_thread */ return; bail: /* report error via WC back to proxy-out */ mlog(0, " ERR: writeto: wr_rx[%d] %p -> raddr %Lx rkey %x (scif r_off %Lx) len %d\n", wr_rx->w_idx, wr_rx, wr_rx->wr.wr.rdma.remote_addr, wr_rx->wr.wr.rdma.rkey, r_off, sg_len); return; }
int main( ) { size_t len = 536870912; int align = 4096; scif_epd_t endpoint; struct scif_portID portid; int ret; uint8_t *in_key = malloc(16 * sizeof(uint8_t)); struct crypto_tfm *tfm = malloc( sizeof(struct crypto_tfm) + sizeof(struct crypto_aes_ctx) ); struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); ctx->key_length = AES_KEYSIZE_256; crypto_aes_set_key(tfm, in_key, AES_KEYSIZE_256); endpoint = scif_open( ); if( endpoint == SCIF_OPEN_FAILED ) { printf("scif open failed\n"); return 1; } ret = scif_bind(endpoint, 23955); if(ret==-1) { printf("scif_bind failed"); return 1; } portid.node = 0; portid.port = 23968; ret = scif_connect(endpoint, &portid); for( int attempt = 0; ret == -1 && attempt < 10; ++attempt ) { sleep(1); ret = scif_connect(endpoint, &portid); } if (ret==-1) { printf("scif_connect failed\n"); return 1; } void *ptr; ret = posix_memalign((void**)&ptr, align, len); if (ret) { printf("Allocating memory failed\n"); return 1; } memset(ptr, 0, len); if( SCIF_REGISTER_FAILED == scif_register(endpoint, ptr, len, (long)ptr, SCIF_PROT_READ | SCIF_PROT_WRITE, SCIF_MAP_FIXED ) ) { printf("scif_register of ptr failed due to: %s\n", strerror(errno)); return 1; } void *tempbuffer; ret = posix_memalign((void**)&tempbuffer, align, len); if (ret) { printf("Allocating tempbuffer failed\n"); return 1; } if( SCIF_REGISTER_FAILED == scif_register(endpoint, tempbuffer, len, (long)tempbuffer, SCIF_PROT_READ | SCIF_PROT_WRITE, SCIF_MAP_FIXED ) ) { printf("scif_register of temp failed due to: %s\n", strerror(errno)); return 1; } void *outbuffer; ret = posix_memalign((void**)&outbuffer, align, len); if (ret) { printf("Allocating outbuffer failed %s\n", strerror(errno)); return 1; } if( SCIF_REGISTER_FAILED == scif_register(endpoint, outbuffer, len, (long)outbuffer, SCIF_PROT_READ | SCIF_PROT_WRITE, SCIF_MAP_FIXED ) ) { printf("scif_register of outbuffer failed due to: %s\n", strerror(errno)); return 1; } void *remote_ptr; void *return_ptr; ret = scif_recv(endpoint, &remote_ptr, sizeof(void*), SCIF_RECV_BLOCK); if (ret==-1) { printf("scif_recv failed due to: %s\n", strerror(errno)); return 1; } ret = scif_recv(endpoint, &return_ptr, sizeof(void*), SCIF_RECV_BLOCK); if (ret==-1) { printf("scif_recv failed due to: %s\n", strerror(errno)); return 1; } struct timespec start_enc, stop_enc; clock_gettime(CLOCK_REALTIME, &start_enc); if (scif_readfrom(endpoint, (long)ptr, len, (long)remote_ptr, SCIF_RMA_SYNC)) { printf("scif_readfrom failed due to: %s\n", strerror(errno)); return 1; } #pragma omp parallel for for (int k = 0; k<len; k+=16) { aes_encrypt(tfm, (uint8_t*)&tempbuffer[k], (uint8_t*)&ptr[k]); } if (scif_writeto(endpoint, (long)tempbuffer, len, (long)return_ptr, SCIF_RMA_SYNC)) { printf("scif_writeto failed due to: %s\n", strerror(errno)); return 1; } clock_gettime(CLOCK_REALTIME, &stop_enc); double time_enc = (stop_enc.tv_sec - start_enc.tv_sec) + ( stop_enc.tv_nsec - start_enc.tv_nsec) / NANOSECONDS; double result0 = len/time_enc/1048576; printf("%1f,", result0); struct timespec start_for, stop_for; clock_gettime(CLOCK_REALTIME, &start_for); if (scif_readfrom(endpoint, (long)ptr, len, (long)remote_ptr, SCIF_RMA_SYNC)) { printf("scif_readfrom failed due to: %s\n", strerror(errno)); return 1; } #pragma omp parallel for for (int k=0; k<len; k+=16) { aes_decrypt(tfm, (uint8_t*)&outbuffer[k], (uint8_t*)&tempbuffer[k]); } if (scif_writeto(endpoint, (long)outbuffer, len, (long)return_ptr, SCIF_RMA_SYNC)) { printf("scif_writeto failed due to: %s\n", strerror(errno)); return 1; } clock_gettime(CLOCK_REALTIME, &stop_for); double time_for = (stop_for.tv_sec - start_for.tv_sec) + ( stop_for.tv_nsec - start_for.tv_nsec) / NANOSECONDS; double result = 536870912/time_for/1048576; printf("%1f \n", result); ret = scif_send(endpoint, &ptr, sizeof(long), SCIF_SEND_BLOCK); if (ret==-1) { printf("scif_send failed due to: %s\n", strerror(errno)); return 1; } ret = scif_unregister(endpoint, (off_t)ptr, len ); if(ret==-1 && errno!=ENOTCONN ) { printf("scif_unregister failed %s\n", strerror(errno)); return 1; } scif_close(endpoint); }