static UCS_CLASS_INIT_FUNC(uct_cm_iface_t, uct_pd_h pd, uct_worker_h worker, const char *dev_name, size_t rx_headroom, const uct_iface_config_t *tl_config) { uct_cm_iface_config_t *config = ucs_derived_of(tl_config, uct_cm_iface_config_t); ucs_status_t status; int ret; ucs_trace_func(""); UCS_CLASS_CALL_SUPER_INIT(uct_ib_iface_t, &uct_cm_iface_ops, pd, worker, dev_name, rx_headroom, 0 /* rx_priv_len */, 0 /* rx_hdr_len */, 1 /* tx_cq_len */, IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE, /* mss */ &config->super); if (worker->async == NULL) { ucs_error("cm must have async!=NULL"); return UCS_ERR_INVALID_PARAM; } self->service_id = (uint32_t)(ucs_generate_uuid((uintptr_t)self) & (~IB_CM_ASSIGN_SERVICE_ID_MASK)); self->num_outstanding = 0; self->config.timeout_ms = (int)(config->timeout * 1e3 + 0.5); self->config.max_outstanding = config->max_outstanding; self->config.retry_count = ucs_min(config->retry_count, UINT8_MAX); self->notify_q.head = NULL; ucs_queue_head_init(&self->notify_q); self->outstanding = ucs_calloc(self->config.max_outstanding, sizeof(*self->outstanding), "cm_outstanding"); if (self->outstanding == NULL) { status = UCS_ERR_NO_MEMORY; goto err; } self->cmdev = ib_cm_open_device(uct_ib_iface_device(&self->super)->ibv_context); if (self->cmdev == NULL) { ucs_error("ib_cm_open_device() failed: %m. Check if ib_ucm.ko module is loaded."); status = UCS_ERR_NO_DEVICE; goto err_free_outstanding; } status = ucs_sys_fcntl_modfl(self->cmdev->fd, O_NONBLOCK, 0); if (status != UCS_OK) { goto err_close_device; } ret = ib_cm_create_id(self->cmdev, &self->listen_id, self); if (ret) { ucs_error("ib_cm_create_id() failed: %m"); status = UCS_ERR_NO_DEVICE; goto err_close_device; } ret = ib_cm_listen(self->listen_id, self->service_id, 0); if (ret) { ucs_error("ib_cm_listen() failed: %m"); status = UCS_ERR_INVALID_ADDR; goto err_destroy_id; } if (config->async_mode == UCS_ASYNC_MODE_SIGNAL) { ucs_warn("ib_cm fd does not support SIGIO"); } status = ucs_async_set_event_handler(config->async_mode, self->cmdev->fd, POLLIN, uct_cm_iface_event_handler, self, worker->async); if (status != UCS_OK) { ucs_error("failed to set event handler"); goto err_destroy_id; } ucs_debug("listening for SIDR service_id 0x%x on fd %d", self->service_id, self->cmdev->fd); return UCS_OK; err_destroy_id: ib_cm_destroy_id(self->listen_id); err_close_device: ib_cm_close_device(self->cmdev); err_free_outstanding: ucs_free(self->outstanding); err: return status; }
static void uct_cm_iface_event_handler(void *arg) { uct_cm_iface_t *iface = arg; struct ib_cm_event *event; struct ib_cm_id *id; int destroy_id; int ret; ucs_trace_func(""); for (;;) { /* Fetch all events */ ret = ib_cm_get_event(iface->cmdev, &event); if (ret) { if (errno != EAGAIN) { ucs_warn("ib_cm_get_event() failed: %m"); } return; } id = event->cm_id; /* Handle the event */ switch (event->event) { case IB_CM_SIDR_REQ_ERROR: ucs_error("SIDR request error, status: %s", ibv_wc_status_str(event->param.send_status)); destroy_id = 1; break; case IB_CM_SIDR_REQ_RECEIVED: uct_cm_iface_handle_sidr_req(iface, event); destroy_id = 1; /* Destroy the ID created by the driver */ break; case IB_CM_SIDR_REP_RECEIVED: ucs_trace_data("RX: SIDR_REP [id %p{%u}]", id, id->handle); uct_cm_iface_outstanding_remove(iface, id); destroy_id = 1; /* Destroy the ID which was used for sending */ break; default: ucs_warn("Unexpected CM event: %d", event->event); destroy_id = 0; break; } /* Acknowledge CM event, remember the id, in case we would destroy it */ ret = ib_cm_ack_event(event); if (ret) { ucs_warn("ib_cm_ack_event() failed: %m"); } /* If there is an id which should be destroyed, do it now, after * acknowledging all events. */ if (destroy_id) { ret = ib_cm_destroy_id(id); if (ret) { ucs_error("ib_cm_destroy_id() failed: %m"); } } ucs_callbackq_add_safe(&uct_cm_iface_worker(iface)->progress_q, uct_cm_iface_progress, iface); } }
static ucs_status_t uct_perf_test_check_capabilities(ucx_perf_params_t *params, uct_iface_h iface) { uct_iface_attr_t attr; ucs_status_t status; uint64_t required_flags; size_t min_size, max_size, max_iov, message_size; status = uct_iface_query(iface, &attr); if (status != UCS_OK) { return status; } min_size = 0; max_iov = 1; message_size = ucx_perf_get_message_size(params); switch (params->command) { case UCX_PERF_CMD_AM: required_flags = __get_flag(params->uct.data_layout, UCT_IFACE_FLAG_AM_SHORT, UCT_IFACE_FLAG_AM_BCOPY, UCT_IFACE_FLAG_AM_ZCOPY); required_flags |= UCT_IFACE_FLAG_AM_CB_SYNC; min_size = __get_max_size(params->uct.data_layout, 0, 0, attr.cap.am.min_zcopy); max_size = __get_max_size(params->uct.data_layout, attr.cap.am.max_short, attr.cap.am.max_bcopy, attr.cap.am.max_zcopy); max_iov = attr.cap.am.max_iov; break; case UCX_PERF_CMD_PUT: required_flags = __get_flag(params->uct.data_layout, UCT_IFACE_FLAG_PUT_SHORT, UCT_IFACE_FLAG_PUT_BCOPY, UCT_IFACE_FLAG_PUT_ZCOPY); min_size = __get_max_size(params->uct.data_layout, 0, 0, attr.cap.put.min_zcopy); max_size = __get_max_size(params->uct.data_layout, attr.cap.put.max_short, attr.cap.put.max_bcopy, attr.cap.put.max_zcopy); max_iov = attr.cap.put.max_iov; break; case UCX_PERF_CMD_GET: required_flags = __get_flag(params->uct.data_layout, 0, UCT_IFACE_FLAG_GET_BCOPY, UCT_IFACE_FLAG_GET_ZCOPY); min_size = __get_max_size(params->uct.data_layout, 0, 0, attr.cap.get.min_zcopy); max_size = __get_max_size(params->uct.data_layout, 0, attr.cap.get.max_bcopy, attr.cap.get.max_zcopy); max_iov = attr.cap.get.max_iov; break; case UCX_PERF_CMD_ADD: required_flags = __get_atomic_flag(message_size, UCT_IFACE_FLAG_ATOMIC_ADD32, UCT_IFACE_FLAG_ATOMIC_ADD64); max_size = 8; break; case UCX_PERF_CMD_FADD: required_flags = __get_atomic_flag(message_size, UCT_IFACE_FLAG_ATOMIC_FADD32, UCT_IFACE_FLAG_ATOMIC_FADD64); max_size = 8; break; case UCX_PERF_CMD_SWAP: required_flags = __get_atomic_flag(message_size, UCT_IFACE_FLAG_ATOMIC_SWAP32, UCT_IFACE_FLAG_ATOMIC_SWAP64); max_size = 8; break; case UCX_PERF_CMD_CSWAP: required_flags = __get_atomic_flag(message_size, UCT_IFACE_FLAG_ATOMIC_CSWAP32, UCT_IFACE_FLAG_ATOMIC_CSWAP64); max_size = 8; break; default: if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("Invalid test command"); } return UCS_ERR_INVALID_PARAM; } status = ucx_perf_test_check_params(params); if (status != UCS_OK) { return status; } if (!ucs_test_all_flags(attr.cap.flags, required_flags) || !required_flags) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("Device does not support required operation"); } return UCS_ERR_UNSUPPORTED; } if (message_size < min_size) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("Message size too small"); } return UCS_ERR_UNSUPPORTED; } if (message_size > max_size) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("Message size too big"); } return UCS_ERR_UNSUPPORTED; } if (params->command == UCX_PERF_CMD_AM) { if ((params->uct.data_layout == UCT_PERF_DATA_LAYOUT_SHORT) && (params->am_hdr_size != sizeof(uint64_t))) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("Short AM header size must be 8 bytes"); } return UCS_ERR_INVALID_PARAM; } if ((params->uct.data_layout == UCT_PERF_DATA_LAYOUT_ZCOPY) && (params->am_hdr_size > attr.cap.am.max_hdr)) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("AM header size too big"); } return UCS_ERR_UNSUPPORTED; } if (params->am_hdr_size > message_size) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("AM header size larger than message size"); } return UCS_ERR_INVALID_PARAM; } if (params->uct.fc_window > UCT_PERF_TEST_MAX_FC_WINDOW) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("AM flow-control window too large (should be <= %d)", UCT_PERF_TEST_MAX_FC_WINDOW); } return UCS_ERR_INVALID_PARAM; } if ((params->flags & UCX_PERF_TEST_FLAG_ONE_SIDED) && (params->flags & UCX_PERF_TEST_FLAG_VERBOSE)) { ucs_warn("Running active-message test with on-sided progress"); } } if (UCT_PERF_DATA_LAYOUT_ZCOPY == params->uct.data_layout) { if (params->msg_size_cnt > max_iov) { if ((params->flags & UCX_PERF_TEST_FLAG_VERBOSE) || !params->msg_size_cnt) { ucs_error("Wrong number of IOV entries. Requested is %lu, " "should be in the range 1...%lu", params->msg_size_cnt, max_iov); } return UCS_ERR_UNSUPPORTED; } /* if msg_size_cnt == 1 the message size checked above */ if ((UCX_PERF_CMD_AM == params->command) && (params->msg_size_cnt > 1)) { if (params->am_hdr_size > params->msg_size_list[0]) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("AM header size (%lu) larger than the first IOV " "message size (%lu)", params->am_hdr_size, params->msg_size_list[0]); } return UCS_ERR_INVALID_PARAM; } } } return UCS_OK; }
static int init_device_list(uct_ugni_job_info_t *inf) { ucs_status_t status = UCS_OK; int i, num_active_devices; int *dev_ids = NULL; gni_return_t ugni_rc = GNI_RC_SUCCESS; /* check if devices were already initilized */ if (-1 != inf->num_devices) { ucs_debug("The device list is already initialized"); status = UCS_OK; goto err_zero; } ugni_rc = GNI_GetNumLocalDevices(&inf->num_devices); if (GNI_RC_SUCCESS != ugni_rc) { ucs_error("GNI_GetNumLocalDevices failed, Error status: %s %d", gni_err_str[ugni_rc], ugni_rc); status = UCS_ERR_NO_DEVICE; goto err_zero; } if (0 == inf->num_devices) { ucs_debug("UGNI No device found"); status = UCS_OK; goto err_zero; } if (inf->num_devices >= UCT_UGNI_MAX_DEVICES) { ucs_error("UGNI, number of discovered devices (%d) " \ "is above the maximum supported devices (%d)", inf->num_devices, UCT_UGNI_MAX_DEVICES); status = UCS_ERR_UNSUPPORTED; goto err_zero; } dev_ids = ucs_calloc(inf->num_devices, sizeof(int), "ugni device ids"); if (NULL == dev_ids) { ucs_error("Failed to allocate memory"); status = UCS_ERR_NO_MEMORY; goto err_zero; } ugni_rc = GNI_GetLocalDeviceIds(inf->num_devices, dev_ids); if (GNI_RC_SUCCESS != ugni_rc) { ucs_error("GNI_GetLocalDeviceIds failed, Error status: %s %d", gni_err_str[ugni_rc], ugni_rc); status = UCS_ERR_NO_DEVICE; goto err_dev_id; } num_active_devices = 0; for (i = 0; i < inf->num_devices; i++) { status = uct_ugni_device_create(dev_ids[i], num_active_devices, &inf->devices[i]); if (status != UCS_OK) { ucs_warn("Failed to initialize ugni device %d (%s), ignoring it", i, ucs_status_string(status)); } else { ++num_active_devices; } } if (num_active_devices != inf->num_devices) { ucs_warn("Error in detection devices"); status = UCS_ERR_NO_DEVICE; goto err_dev_id; } ucs_debug("Initialized UGNI component with %d devices", inf->num_devices); err_dev_id: ucs_free(dev_ids); err_zero: return status; }
static ucs_status_t ucp_perf_setup(ucx_perf_context_t *perf, ucx_perf_params_t *params) { ucp_params_t ucp_params; ucp_worker_params_t worker_params; ucp_config_t *config; ucs_status_t status; uint64_t features; status = ucp_perf_test_check_params(params, &features); if (status != UCS_OK) { goto err; } status = ucp_config_read(NULL, NULL, &config); if (status != UCS_OK) { goto err; } ucp_params.field_mask = UCP_PARAM_FIELD_FEATURES; ucp_params.features = features; status = ucp_init(&ucp_params, config, &perf->ucp.context); ucp_config_release(config); if (status != UCS_OK) { goto err; } worker_params.field_mask = UCP_WORKER_PARAM_FIELD_THREAD_MODE; worker_params.thread_mode = params->thread_mode; status = ucp_worker_create(perf->ucp.context, &worker_params, &perf->ucp.worker); if (status != UCS_OK) { goto err_cleanup; } status = ucp_perf_test_alloc_mem(perf, params); if (status != UCS_OK) { ucs_warn("ucp test failed to alocate memory"); goto err_destroy_worker; } status = ucp_perf_test_setup_endpoints(perf, features); if (status != UCS_OK) { if (params->flags & UCX_PERF_TEST_FLAG_VERBOSE) { ucs_error("Failed to setup endpoints: %s", ucs_status_string(status)); } goto err_free_mem; } return UCS_OK; err_free_mem: ucp_perf_test_free_mem(perf); err_destroy_worker: ucp_worker_destroy(perf->ucp.worker); err_cleanup: ucp_cleanup(perf->ucp.context); err: return status; }