int rdma_create_id(struct rdma_event_channel *channel, struct rdma_cm_id **id, void *context, enum rdma_port_space ps) { struct ucma_abi_create_id_resp *resp; struct ucma_abi_create_id *cmd; struct cma_id_private *id_priv; void *msg; int ret, size; ret = cma_dev_cnt ? 0 : ucma_init(); if (ret) return ret; id_priv = ucma_alloc_id(channel, context, ps); if (!id_priv) return ERR(ENOMEM); CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_CREATE_ID, size); cmd->uid = (uintptr_t) id_priv; cmd->ps = ps; ret = write(channel->fd, msg, size); if (ret != size) goto err; VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); id_priv->handle = resp->id; *id = &id_priv->id; return 0; err: ucma_free_id(id_priv); return ret; }
int rdma_getaddrinfo(char *node, char *service, struct rdma_addrinfo *hints, struct rdma_addrinfo **res) { struct rdma_addrinfo *rai; int ret; if (!service && !node && !hints) return ERR(EINVAL); ret = ucma_init(); if (ret) return ret; rai = calloc(1, sizeof(*rai)); if (!rai) return ERR(ENOMEM); if (!hints) hints = &nohints; if (node || service) { ret = ucma_getaddrinfo(node, service, hints, rai); } else { rai->ai_flags = hints->ai_flags; rai->ai_family = hints->ai_family; rai->ai_qp_type = hints->ai_qp_type; rai->ai_port_space = hints->ai_port_space; if (hints->ai_dst_len) { ret = ucma_copy_addr(&rai->ai_dst_addr, &rai->ai_dst_len, hints->ai_dst_addr, hints->ai_dst_len); } } if (ret) goto err; if (!rai->ai_src_len && hints->ai_src_len) { ret = ucma_copy_addr(&rai->ai_src_addr, &rai->ai_src_len, hints->ai_src_addr, hints->ai_src_len); if (ret) goto err; } if (!(rai->ai_flags & RAI_PASSIVE)) ucma_ib_resolve(&rai, hints); *res = rai; return 0; err: rdma_freeaddrinfo(rai); return ret; }
struct rdma_event_channel *rdma_create_event_channel(void) { struct rdma_event_channel *channel; if (!cma_dev_cnt && ucma_init()) return NULL; channel = malloc(sizeof *channel); if (!channel) return NULL; channel->fd = open("/dev/rdma_cm", O_RDWR); if (channel->fd < 0) { printf("CMA: unable to open /dev/rdma_cm\n"); goto err; } return channel; err: free(channel); return NULL; }
int rdma_get_cm_event(struct rdma_event_channel *channel, struct rdma_cm_event **event) { struct ucma_abi_event_resp *resp; struct ucma_abi_get_event *cmd; struct cma_event *evt; void *msg; int ret, size; ret = cma_dev_cnt ? 0 : ucma_init(); if (ret) return ret; if (!event) return ERR(EINVAL); evt = malloc(sizeof *evt); if (!evt) return ERR(ENOMEM); retry: memset(evt, 0, sizeof *evt); CMA_CREATE_MSG_CMD_RESP(msg, cmd, resp, UCMA_CMD_GET_EVENT, size); ret = write(channel->fd, msg, size); if (ret != size) { free(evt); return (ret >= 0) ? ERR(ECONNREFUSED) : -1; } VALGRIND_MAKE_MEM_DEFINED(resp, sizeof *resp); evt->event.event = resp->event; evt->id_priv = (void *) (uintptr_t) resp->uid; evt->event.id = &evt->id_priv->id; evt->event.status = resp->status; switch (resp->event) { case RDMA_CM_EVENT_ADDR_RESOLVED: evt->event.status = ucma_query_route(&evt->id_priv->id); if (evt->event.status) evt->event.event = RDMA_CM_EVENT_ADDR_ERROR; break; case RDMA_CM_EVENT_ROUTE_RESOLVED: evt->event.status = ucma_query_route(&evt->id_priv->id); if (evt->event.status) evt->event.event = RDMA_CM_EVENT_ROUTE_ERROR; break; case RDMA_CM_EVENT_CONNECT_REQUEST: evt->id_priv = (void *) (uintptr_t) resp->uid; if (ucma_is_ud_ps(evt->id_priv->id.ps)) ucma_copy_ud_event(evt, &resp->param.ud); else ucma_copy_conn_event(evt, &resp->param.conn); ret = ucma_process_conn_req(evt, resp->id); if (ret) goto retry; break; case RDMA_CM_EVENT_CONNECT_RESPONSE: ucma_copy_conn_event(evt, &resp->param.conn); evt->event.status = ucma_process_conn_resp(evt->id_priv); if (!evt->event.status) evt->event.event = RDMA_CM_EVENT_ESTABLISHED; else { evt->event.event = RDMA_CM_EVENT_CONNECT_ERROR; evt->id_priv->connect_error = 1; } break; case RDMA_CM_EVENT_ESTABLISHED: if (ucma_is_ud_ps(evt->id_priv->id.ps)) { ucma_copy_ud_event(evt, &resp->param.ud); break; } ucma_copy_conn_event(evt, &resp->param.conn); evt->event.status = ucma_process_establish(&evt->id_priv->id); if (evt->event.status) { evt->event.event = RDMA_CM_EVENT_CONNECT_ERROR; evt->id_priv->connect_error = 1; } break; case RDMA_CM_EVENT_REJECTED: if (evt->id_priv->connect_error) { ucma_complete_event(evt->id_priv); goto retry; } ucma_copy_conn_event(evt, &resp->param.conn); ucma_modify_qp_err(evt->event.id); break; case RDMA_CM_EVENT_DISCONNECTED: if (evt->id_priv->connect_error) { ucma_complete_event(evt->id_priv); goto retry; } ucma_copy_conn_event(evt, &resp->param.conn); break; case RDMA_CM_EVENT_MULTICAST_JOIN: evt->mc = (void *) (uintptr_t) resp->uid; evt->id_priv = evt->mc->id_priv; evt->event.id = &evt->id_priv->id; ucma_copy_ud_event(evt, &resp->param.ud); evt->event.param.ud.private_data = evt->mc->context; evt->event.status = ucma_process_join(evt); if (evt->event.status) evt->event.event = RDMA_CM_EVENT_MULTICAST_ERROR; break; case RDMA_CM_EVENT_MULTICAST_ERROR: evt->mc = (void *) (uintptr_t) resp->uid; evt->id_priv = evt->mc->id_priv; evt->event.id = &evt->id_priv->id; evt->event.param.ud.private_data = evt->mc->context; break; default: evt->id_priv = (void *) (uintptr_t) resp->uid; evt->event.id = &evt->id_priv->id; evt->event.status = resp->status; if (ucma_is_ud_ps(evt->id_priv->id.ps)) ucma_copy_ud_event(evt, &resp->param.ud); else ucma_copy_conn_event(evt, &resp->param.conn); break; } *event = &evt->event; return 0; }