static void server_recv_connreq(struct util_wait *wait, struct tcpx_cm_context *cm_ctx) { struct tcpx_conn_handle *handle; struct fi_eq_cm_entry *cm_entry; struct ofi_ctrl_hdr conn_req; int ret; assert(cm_ctx->fid->fclass == FI_CLASS_CONNREQ); handle = container_of(cm_ctx->fid, struct tcpx_conn_handle, handle); ret = rx_cm_data(handle->conn_fd, &conn_req, ofi_ctrl_connreq, cm_ctx); if (ret) goto err1; cm_entry = calloc(1, sizeof(*cm_entry) + cm_ctx->cm_data_sz); if (!cm_entry) goto err1; cm_entry->fid = &handle->pep->util_pep.pep_fid.fid; cm_entry->info = fi_dupinfo(&handle->pep->info); if (!cm_entry->info) goto err2; cm_entry->info->handle = &handle->handle; memcpy(cm_entry->data, cm_ctx->cm_data, cm_ctx->cm_data_sz); ret = (int) fi_eq_write(&handle->pep->util_pep.eq->eq_fid, FI_CONNREQ, cm_entry, sizeof(*cm_entry) + cm_ctx->cm_data_sz, 0); if (ret < 0) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "Error writing to EQ\n"); goto err3; } ret = ofi_wait_fd_del(wait, handle->conn_fd); if (ret) FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "fd deletion from ofi_wait failed\n"); free(cm_entry); free(cm_ctx); return; err3: fi_freeinfo(cm_entry->info); err2: free(cm_entry); err1: ofi_wait_fd_del(wait, handle->conn_fd); ofi_close_socket(handle->conn_fd); free(cm_ctx); free(handle); }
static void client_send_connreq(struct util_wait *wait, struct tcpx_cm_context *cm_ctx) { struct tcpx_ep *ep; struct fi_eq_err_entry err_entry; socklen_t len; int status, ret = FI_SUCCESS; FI_DBG(&tcpx_prov, FI_LOG_EP_CTRL, "client send connreq\n"); assert(cm_ctx->fid->fclass == FI_CLASS_EP); ep = container_of(cm_ctx->fid, struct tcpx_ep, util_ep.ep_fid.fid); len = sizeof(status); ret = getsockopt(ep->conn_fd, SOL_SOCKET, SO_ERROR, (char *) &status, &len); if (ret < 0 || status) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "connection failure\n"); ret = (ret < 0)? -ofi_sockerr() : status; goto err; } ret = tx_cm_data(ep->conn_fd, ofi_ctrl_connreq, cm_ctx); if (ret) goto err; ret = ofi_wait_fd_del(wait, ep->conn_fd); if (ret) goto err; cm_ctx->type = CLIENT_RECV_CONNRESP; ret = ofi_wait_fd_add(wait, ep->conn_fd, FI_EPOLL_IN, tcpx_eq_wait_try_func, NULL, cm_ctx); if (ret) goto err; wait->signal(wait); return; err: memset(&err_entry, 0, sizeof err_entry); err_entry.fid = cm_ctx->fid; err_entry.context = cm_ctx->fid->context; err_entry.err = -ret; free(cm_ctx); fi_eq_write(&ep->util_ep.eq->eq_fid, FI_NOTIFY, &err_entry, sizeof(err_entry), UTIL_FLAG_ERROR); }
static void server_send_cm_accept(struct util_wait *wait, struct tcpx_cm_context *cm_ctx) { struct fi_eq_cm_entry cm_entry = {0}; struct fi_eq_err_entry err_entry; struct tcpx_ep *ep; int ret; assert(cm_ctx->fid->fclass == FI_CLASS_EP); ep = container_of(cm_ctx->fid, struct tcpx_ep, util_ep.ep_fid.fid); ret = tx_cm_data(ep->conn_fd, ofi_ctrl_connresp, cm_ctx); if (ret) goto err; cm_entry.fid = cm_ctx->fid; ret = (int) fi_eq_write(&ep->util_ep.eq->eq_fid, FI_CONNECTED, &cm_entry, sizeof(cm_entry), 0); if (ret < 0) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "Error writing to EQ\n"); } ret = ofi_wait_fd_del(wait, ep->conn_fd); if (ret) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "Could not remove fd from wait\n"); goto err; } ret = tcpx_ep_msg_xfer_enable(ep); if (ret) goto err; FI_DBG(&tcpx_prov, FI_LOG_EP_CTRL, "Connection Accept Successful\n"); free(cm_ctx); return; err: memset(&err_entry, 0, sizeof err_entry); err_entry.fid = cm_ctx->fid; err_entry.context = cm_ctx->fid->context; err_entry.err = -ret; free(cm_ctx); fi_eq_write(&ep->util_ep.eq->eq_fid, FI_NOTIFY, &err_entry, sizeof(err_entry), UTIL_FLAG_ERROR); }
static void client_recv_connresp(struct util_wait *wait, struct tcpx_cm_context *cm_ctx) { struct fi_eq_err_entry err_entry = { 0 }; struct tcpx_ep *ep; ssize_t ret; assert(cm_ctx->fid->fclass == FI_CLASS_EP); ep = container_of(cm_ctx->fid, struct tcpx_ep, util_ep.ep_fid.fid); ret = ofi_wait_fd_del(wait, ep->conn_fd); if (ret) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "Could not remove fd from wait\n"); goto err; } ret = proc_conn_resp(cm_ctx, ep); if (ret) goto err; FI_DBG(&tcpx_prov, FI_LOG_EP_CTRL, "Received Accept from server\n"); free(cm_ctx); return; err: err_entry.fid = cm_ctx->fid; err_entry.context = cm_ctx->fid->context; err_entry.err = -ret; if (cm_ctx->cm_data_sz) { err_entry.err_data = calloc(1, cm_ctx->cm_data_sz); if (OFI_LIKELY(err_entry.err_data != NULL)) { memcpy(err_entry.err_data, cm_ctx->cm_data, cm_ctx->cm_data_sz); err_entry.err_data_size = cm_ctx->cm_data_sz; } } FI_DBG(&tcpx_prov, FI_LOG_EP_CTRL, "fi_eq_write the conn refused %"PRId64"\n", ret); free(cm_ctx); /* `err_entry.err_data` must live until it is passed to user */ ret = fi_eq_write(&ep->util_ep.eq->eq_fid, FI_NOTIFY, &err_entry, sizeof(err_entry), UTIL_FLAG_ERROR); if (OFI_UNLIKELY(ret < 0)) { free(err_entry.err_data); } }
static int tcpx_ep_close(struct fid *fid) { struct tcpx_ep *ep = container_of(fid, struct tcpx_ep, util_ep.ep_fid.fid); tcpx_ep_tx_rx_queues_release(ep); tcpx_cq_wait_ep_del(ep); if (ep->util_ep.eq->wait) ofi_wait_fd_del(ep->util_ep.eq->wait, ep->conn_fd); ofi_eq_remove_fid_events(ep->util_ep.eq, &ep->util_ep.ep_fid.fid); ofi_close_socket(ep->conn_fd); ofi_endpoint_close(&ep->util_ep); fastlock_destroy(&ep->lock); free(ep); return 0; }