ib_api_status_t osmv_simple_send_madw(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_retry) { ib_api_status_t ret; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_mad_addr_t *p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw); uint8_t mad_buf[MAD_BLOCK_SIZE]; ib_mad_t *p_mad = (ib_mad_t *) mad_buf; uint64_t key = 0; OSM_LOG_ENTER(p_bo->p_vendor->p_log); CL_ASSERT(p_madw->mad_size <= MAD_BLOCK_SIZE); memset(p_mad, 0, MAD_BLOCK_SIZE); memcpy(p_mad, osm_madw_get_mad_ptr(p_madw), p_madw->mad_size); if (NULL != p_txn) { /* Push a fake txn id to the MAD */ key = osmv_txn_get_key(p_txn); p_mad->trans_id = cl_hton64(key); } /* Add call for packet drop randomizer. This is a testing feature. If run_randomizer flag is set to TRUE, the randomizer will be called, and randomally will drop a packet. This is used for simulating unstable fabric. */ if (p_bo->p_vendor->run_randomizer == TRUE) { /* Try the randomizer */ if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log, p_bo->p_vendor-> p_pkt_randomizer, p_mad) == TRUE) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "The MAD will not be sent. \n"); ret = IB_SUCCESS; } else { ret = osmv_transport_mad_send(h_bind, p_mad, p_mad_addr); } } else { ret = osmv_transport_mad_send(h_bind, p_mad, p_mad_addr); } if ((IB_SUCCESS == ret) && (NULL != p_txn) && (!is_retry)) { /* Set the timeout for receiving the response MAD */ ret = osmv_txn_set_timeout_ev(h_bind, key, p_bo->p_vendor->resp_timeout); } OSM_LOG_EXIT(p_bo->p_vendor->p_log); return ret; }
ib_api_status_t osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_init_by_peer) { ib_api_status_t st; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; uint64_t key = osmv_txn_get_key(p_txn); CL_ASSERT(p_txn); /* Double-Sided RMPP Direction Switch */ osmv_txn_remove_timeout_ev(h_bind, key); /* Set the Transaction Timeout value */ st = osmv_txn_set_timeout_ev(h_bind, key, p_bo->p_vendor->ttime_timeout); if (IB_SUCCESS != st) { return st; } p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_RECEIVER; p_txn->rmpp_txfr.is_rmpp_init_by_peer = is_init_by_peer; p_txn->rmpp_txfr.p_rmpp_recv_ctx = malloc(sizeof(osmv_rmpp_recv_ctx_t)); if (!p_txn->rmpp_txfr.p_rmpp_recv_ctx) { osmv_txn_remove_timeout_ev(h_bind, key); return IB_INSUFFICIENT_MEMORY; } memset(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 0, sizeof(osmv_rmpp_recv_ctx_t)); st = osmv_rmpp_recv_ctx_init(p_txn->rmpp_txfr.p_rmpp_recv_ctx, p_txn->p_log); return st; }
ib_api_status_t osmv_rmpp_send_madw(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_rmpp_ds) { ib_api_status_t ret = IB_SUCCESS; uint32_t i, total_segs; osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; OSM_LOG_ENTER(p_bo->p_vendor->p_log); total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx); CL_ASSERT(total_segs >= 1); /* In the double-sided transfer, wait for ACK 0 */ for (;;) { if (p_send_ctx->window_first > total_segs) { /* Every segment is acknowledged */ break; } /* Send the next burst. */ for (i = p_send_ctx->window_first; i <= p_send_ctx->window_last; i++) { /* Send a segment and setup a timeout timer */ ret = __osmv_rmpp_send_segment(h_bind, p_txn, i); if (IB_SUCCESS != ret) { goto send_done; } } /* Set the Response Timeout for the ACK on the last DATA segment */ ret = osmv_txn_set_timeout_ev(h_bind, osmv_txn_get_key(p_txn), p_bo->p_vendor->resp_timeout); if (IB_SUCCESS != ret) { goto send_done; } /* Going to sleep. Let the others access the transaction DB */ osmv_txn_unlock(p_bo); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "RMPP Sender thread (madw=%p) going to sleep ...\n", p_madw); /* Await the next event to happen */ cl_event_wait_on(&p_send_ctx->event, EVENT_NO_TIMEOUT, TRUE /* interruptible */ ); /* Got a signal from the MAD dispatcher/timeout handler */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "RMPP Sender thread (madw=%p) waking up on a signal ...\n", p_madw); /* Let's see what changed... Make this atomic - re-acquire the lock. */ osmv_txn_lock(p_bo); if (TRUE == p_bo->is_closing) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_rmpp_send_madw: ERR 6601: " "The bind handle %p is being closed. " "Stopping the RMPP Send of MADW %p\n", h_bind, p_madw); ret = IB_TIMEOUT; return IB_INTERRUPTED; } /* STOP? ABORT? TIMEOUT? */ if (IB_SUCCESS != p_send_ctx->status) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_rmpp_send_madw: ERR 6602: " "An error (%s) happened during the RMPP send of %p. Bailing out.\n", ib_get_err_str(p_send_ctx->status), p_madw); ret = p_send_ctx->status; goto send_done; } } if (TRUE == is_rmpp_ds) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Double-sided RMPP - switching to be the receiver.\n"); ret = osmv_txn_init_rmpp_receiver(h_bind, p_txn, FALSE /*Send was initiated by me */ ); if (IB_SUCCESS == ret) { /* Send ACK on the 0 segment */ ret = __osmv_rmpp_send_segment(h_bind, p_txn, 0); } } send_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); return ret; }