/* Since a race can accure on requests. Meaning - a response is received before the send_callback is called - we will save both the madw_p and the fact whether or not it is a response. A race can occure only on requests that did not fail, and then the madw_p will be put back in the pool before the callback. */ uint64_t __osm_set_wrid_by_p_madw(IN osm_madw_t * p_madw) { uint64_t wrid = 0; CL_ASSERT(p_madw->p_mad); memcpy(&wrid, &p_madw, sizeof(osm_madw_t *)); wrid = (wrid << 1) | ib_mad_is_response(p_madw->p_mad) | (p_madw->p_mad->method == IB_MAD_METHOD_TRAP_REPRESS); return wrid; }
static osmv_disp_route_t __osmv_dispatch_route(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, OUT osmv_txn_ctx_t ** pp_txn) { ib_api_status_t ret; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; boolean_t is_resp = ib_mad_is_response(p_mad); boolean_t is_txn; uint64_t key = cl_ntoh64(p_mad->trans_id); CL_ASSERT(NULL != pp_txn); ret = osmv_txn_lookup(h_bind, key, pp_txn); is_txn = (IB_SUCCESS == ret); if (FALSE == is_txn && TRUE == is_resp) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Received a response to a non-started/aged-out transaction (tid=0x%" PRIx64 "). " "Dropping the MAD.\n", key); return OSMV_ROUTE_DROP; } if (TRUE == osmv_mad_is_rmpp(p_mad)) { /* An RMPP transaction. The filtering is more delicate there */ return OSMV_ROUTE_RMPP; } if (TRUE == is_txn && FALSE == is_resp) { /* Does this MAD try to start a transaction with duplicate tid? */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Duplicate TID 0x%" PRIx64 " received (not a response). " "Dropping the MAD.\n", key); return OSMV_ROUTE_DROP; } return OSMV_ROUTE_SIMPLE; }
/********************************************************************** * TS RCV Thread callback * HACK: - we need to make this support arbitrary size mads. **********************************************************************/ void __osm_ts_rcv_callback(IN osm_ts_bind_info_t * p_bind, IN osm_mad_addr_t * p_mad_addr, IN uint32_t mad_size, IN void *p_mad) { ib_api_status_t status; osm_madw_t *p_req_madw = NULL; osm_madw_t *p_madw; osm_vend_wrap_t *p_new_vw; ib_mad_t *p_mad_buf; osm_log_t *const p_log = p_bind->p_vend->p_log; OSM_LOG_ENTER(p_log); /* if it is a response MAD we mustbe able to get the request */ if (ib_mad_is_response((ib_mad_t *) p_mad)) { /* can we find a matching madw by this payload TID */ status = osm_transaction_mgr_get_madw_for_tid(p_bind->p_vend, (ib_mad_t *) p_mad, &p_req_madw); if (status != IB_SUCCESS) { osm_log(p_log, OSM_LOG_ERROR, "__osm_ts_rcv_callback: ERR 5008: " "Error obtaining request madw by TID (%d).\n", status); p_req_madw = NULL; } if (p_req_madw == NULL) { osm_log(p_log, OSM_LOG_ERROR, "__osm_ts_rcv_callback: ERR 5009: " "Fail to obtain request madw for receined MAD. Aborting CB.\n"); goto Exit; } } /* do we have a request ??? */ if (p_req_madw == NULL) { /* if not - get new osm_madw and arrange it. */ /* create the new madw in the pool */ p_madw = osm_mad_pool_get(p_bind->p_osm_pool, (osm_bind_handle_t) p_bind, mad_size, p_mad_addr); if (p_madw == NULL) { osm_log(p_log, OSM_LOG_ERROR, "__osm_ts_rcv_callback: ERR 5010: " "Error request for a new madw.\n"); goto Exit; } /* HACK: we cust to avoid the const ??? */ p_mad_buf = (void *)p_madw->p_mad; } else { /* we have the madw defined during the send and stored in the vend_wrap */ /* we need to make sure the wrapper is correctly init there */ CL_ASSERT(p_req_madw->vend_wrap.p_resp_madw != 0); p_madw = p_req_madw->vend_wrap.p_resp_madw; CL_ASSERT(p_madw->h_bind); p_mad_buf = osm_vendor_get(p_madw->h_bind, mad_size, &p_madw->vend_wrap); if (p_mad_buf == NULL) { osm_log(p_log, OSM_LOG_ERROR, "__osm_ts_rcv_callback: ERR 5011: " "Unable to acquire wire MAD.\n"); goto Exit; } /* Finally, attach the wire MAD to this wrapper. */ osm_madw_set_mad(p_madw, p_mad_buf); } /* init some fields of the vendor wrapper */ p_new_vw = osm_madw_get_vend_ptr(p_madw); p_new_vw->h_bind = p_bind; p_new_vw->size = mad_size; p_new_vw->p_resp_madw = NULL; p_new_vw->p_mad_buf = p_mad_buf; memcpy(p_new_vw->p_mad_buf, p_mad, mad_size); /* attach the buffer to the wrapper */ p_madw->p_mad = p_mad_buf; /* we can also make sure we marked the size and bind on the returned madw */ p_madw->h_bind = p_new_vw->h_bind; /* call the CB */ (*(osm_vend_mad_recv_callback_t) p_bind->rcv_callback) (p_madw, p_bind->client_context, p_req_madw); Exit: OSM_LOG_EXIT(p_log); }
static void __osm_al_rcv_callback(IN void *mad_svc_context, IN ib_mad_element_t * p_elem) { osm_al_bind_info_t *const p_bind = (osm_al_bind_info_t *) mad_svc_context; osm_vendor_t *const p_vend = p_bind->p_vend; osm_madw_t *p_old_madw; osm_madw_t *p_new_madw; osm_vend_wrap_t *p_old_vw; osm_vend_wrap_t *p_new_vw; ib_mad_t *p_new_mad; osm_mad_addr_t mad_addr; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_elem->context1 == NULL); CL_ASSERT(p_elem->context2 == NULL); p_new_mad = ib_get_mad_buf(p_elem); /* In preperation for initializing the new mad wrapper, Initialize the mad_addr structure for the received wire MAD. */ mad_addr.dest_lid = p_elem->remote_lid; mad_addr.path_bits = p_elem->path_bits; /* TO DO - figure out which #define to use for the 2.5 Gb rate... */ mad_addr.static_rate = 0; if (p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID || p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR) { mad_addr.addr_type.smi.source_lid = p_elem->remote_lid; } else { mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp; mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey; mad_addr.addr_type.gsi.pkey_ix = p_elem->pkey_index; mad_addr.addr_type.gsi.service_level = p_elem->remote_sl; mad_addr.addr_type.gsi.global_route = FALSE; } /* If this MAD is a response to a previous request, then grab our pre-allocated MAD wrapper. Otherwise, allocate a new MAD wrapper. */ if (ib_mad_is_response(p_new_mad)) { CL_ASSERT(p_elem->send_context1 != NULL); CL_ASSERT(p_elem->send_context2 == NULL); p_old_madw = (osm_madw_t *) p_elem->send_context1; p_old_vw = osm_madw_get_vend_ptr(p_old_madw); p_new_madw = p_old_vw->p_resp_madw; CL_ASSERT(p_new_madw); osm_madw_init(p_new_madw, p_bind, p_elem->size, &mad_addr); osm_madw_set_mad(p_new_madw, p_new_mad); } else { CL_ASSERT(p_elem->send_context1 == NULL); CL_ASSERT(p_elem->send_context2 == NULL); p_new_madw = osm_mad_pool_get_wrapper(p_bind->p_osm_pool, p_bind, p_elem->size, p_new_mad, &mad_addr); } CL_ASSERT(p_new_madw); p_new_vw = osm_madw_get_vend_ptr(p_new_madw); p_new_vw->h_bind = p_bind; p_new_vw->size = p_elem->size; p_new_vw->p_elem = p_elem; p_new_vw->h_av = 0; p_new_vw->p_resp_madw = NULL; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_al_rcv_callback: " "Calling receive callback function %p.\n", p_bind->rcv_callback); p_bind->rcv_callback(p_new_madw, p_bind->client_context, p_elem->send_context1); OSM_LOG_EXIT(p_vend->p_log); }