static void uct_cm_iface_handle_sidr_req(uct_cm_iface_t *iface, struct ib_cm_event *event) { uct_cm_hdr_t *hdr = event->private_data; struct ib_cm_sidr_rep_param rep; ucs_status_t status; void *cm_desc, *desc; int ret; VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof(hdr)); VALGRIND_MAKE_MEM_DEFINED(hdr + 1, hdr->length); uct_cm_iface_trace_data(iface, UCT_AM_TRACE_TYPE_RECV, hdr, "RX: SIDR_REQ"); /* Allocate temporary buffer to serve as receive descriptor */ cm_desc = ucs_malloc(iface->super.config.rx_payload_offset + hdr->length, "cm_recv_desc"); if (cm_desc == NULL) { ucs_error("failed to allocate cm receive descriptor"); return; } /* Send reply */ ucs_trace_data("TX: SIDR_REP [id %p{%u}]", event->cm_id, event->cm_id->handle); memset(&rep, 0, sizeof rep); rep.status = IB_SIDR_SUCCESS; ret = ib_cm_send_sidr_rep(event->cm_id, &rep); if (ret) { ucs_error("ib_cm_send_sidr_rep() failed: %m"); } /* Call active message handler */ desc = cm_desc + iface->super.config.rx_headroom_offset; uct_recv_desc_iface(desc) = &iface->super.super.super; status = uct_iface_invoke_am(&iface->super.super, hdr->am_id, hdr + 1, hdr->length, desc); if (status == UCS_OK) { ucs_free(cm_desc); } }
ssize_t uct_cm_ep_am_bcopy(uct_ep_h tl_ep, uint8_t am_id, uct_pack_callback_t pack_cb, void *arg) { uct_cm_iface_t *iface = ucs_derived_of(tl_ep->iface, uct_cm_iface_t); uct_cm_ep_t *ep = ucs_derived_of(tl_ep, uct_cm_ep_t); struct ib_cm_sidr_req_param req; struct ibv_sa_path_rec path; struct ib_cm_id *id; ucs_status_t status; uct_cm_hdr_t *hdr; size_t payload_len; size_t total_len; int ret; UCT_CHECK_AM_ID(am_id); uct_cm_enter(iface); if (iface->num_outstanding >= iface->config.max_outstanding) { status = UCS_ERR_NO_RESOURCE; goto err; } /* Allocate temporary contiguous buffer */ hdr = ucs_malloc(IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE, "cm_send_buf"); if (hdr == NULL) { status = UCS_ERR_NO_MEMORY; goto err; } payload_len = pack_cb(hdr + 1, arg); hdr->am_id = am_id; hdr->length = payload_len; total_len = sizeof(*hdr) + payload_len; status = uct_cm_ep_fill_path_rec(ep, &path); if (status != UCS_OK) { goto err_free; } /* Fill SIDR request */ memset(&req, 0, sizeof req); req.path = &path; req.service_id = ep->dest_addr.id; req.timeout_ms = iface->config.timeout_ms; req.private_data = hdr; req.private_data_len = total_len; req.max_cm_retries = iface->config.retry_count; /* Create temporary ID for this message. Will be released when getting REP. */ ret = ib_cm_create_id(iface->cmdev, &id, NULL); if (ret) { ucs_error("ib_cm_create_id() failed: %m"); status = UCS_ERR_IO_ERROR; goto err_free; } uct_cm_dump_path(&path); ret = ib_cm_send_sidr_req(id, &req); if (ret) { ucs_error("ib_cm_send_sidr_req() failed: %m"); status = UCS_ERR_IO_ERROR; goto err_destroy_id; } iface->outstanding[iface->num_outstanding++] = id; UCT_TL_EP_STAT_OP(&ep->super, AM, BCOPY, payload_len); uct_cm_leave(iface); uct_cm_iface_trace_data(iface, UCT_AM_TRACE_TYPE_SEND, hdr, "TX: SIDR_REQ [dlid %d svc 0x%"PRIx64"]", ntohs(path.dlid), req.service_id); ucs_free(hdr); return payload_len; err_destroy_id: ib_cm_destroy_id(id); err_free: ucs_free(hdr); err: uct_cm_leave(iface); return status; }