static void handle_connreq(struct poll_fd_mgr *poll_mgr, struct poll_fd_info *poll_info) { struct tcpx_conn_handle *handle; struct tcpx_pep *pep; struct fi_eq_cm_entry *cm_entry; struct ofi_ctrl_hdr conn_req; SOCKET sock; int ret; assert(poll_info->fid->fclass == FI_CLASS_PEP); pep = container_of(poll_info->fid, struct tcpx_pep, util_pep.pep_fid.fid); sock = accept(pep->sock, NULL, 0); if (sock < 0) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "accept error: %d\n", ofi_sockerr()); return; } ret = rx_cm_data(sock, &conn_req, ofi_ctrl_connreq, poll_info); if (ret) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "cm data recv failed \n"); goto err1; } handle = calloc(1, sizeof(*handle)); if (!handle) goto err1; cm_entry = calloc(1, sizeof(*cm_entry) + poll_info->cm_data_sz); if (!cm_entry) goto err2; handle->conn_fd = sock; cm_entry->fid = poll_info->fid; cm_entry->info = fi_dupinfo(&pep->info); if (!cm_entry->info) goto err3; cm_entry->info->handle = &handle->handle; memcpy(cm_entry->data, poll_info->cm_data, poll_info->cm_data_sz); ret = (int) fi_eq_write(&pep->util_pep.eq->eq_fid, FI_CONNREQ, cm_entry, sizeof(*cm_entry) + poll_info->cm_data_sz, 0); if (ret < 0) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "Error writing to EQ\n"); goto err4; } free(cm_entry); return; err4: fi_freeinfo(cm_entry->info); err3: free(cm_entry); err2: free(handle); err1: ofi_close_socket(sock); }
void sock_conn_release_entry(struct sock_conn_map *map, struct sock_conn *conn) { fi_epoll_del(map->epoll_set, conn->sock_fd); ofi_close_socket(conn->sock_fd); conn->address_published = 0; conn->connected = 0; conn->sock_fd = -1; }
static void *_sock_conn_listen(void *arg) { int conn_fd, ret; char tmp; socklen_t addr_size; struct sockaddr_in remote; struct pollfd poll_fds[2]; struct sock_ep_attr *ep_attr = (struct sock_ep_attr *)arg; struct sock_conn_listener *listener = &ep_attr->listener; struct sock_conn_map *map = &ep_attr->cmap; poll_fds[0].fd = listener->sock; poll_fds[1].fd = listener->signal_fds[1]; poll_fds[0].events = poll_fds[1].events = POLLIN; listener->is_ready = 1; while (listener->do_listen) { if (poll(poll_fds, 2, -1) > 0) { if (poll_fds[1].revents & POLLIN) { ret = ofi_read_socket(listener->signal_fds[1], &tmp, 1); if (ret != 1) { SOCK_LOG_ERROR("Invalid signal\n"); goto err; } continue; } } else { goto err; } addr_size = sizeof(remote); conn_fd = accept(listener->sock, (struct sockaddr *) &remote, &addr_size); SOCK_LOG_DBG("CONN: accepted conn-req: %d\n", conn_fd); if (conn_fd < 0) { SOCK_LOG_ERROR("failed to accept: %s\n", strerror(errno)); goto err; } SOCK_LOG_DBG("ACCEPT: %s, %d\n", inet_ntoa(remote.sin_addr), ntohs(remote.sin_port)); fastlock_acquire(&map->lock); sock_conn_map_insert(ep_attr, &remote, conn_fd, 1); fastlock_release(&map->lock); sock_pe_signal(ep_attr->domain->pe); } err: ofi_close_socket(listener->sock); SOCK_LOG_DBG("Listener thread exited\n"); return NULL; }
static int tcpx_pep_sock_create(struct tcpx_pep *pep) { int ret, af; switch (pep->info->addr_format) { case FI_SOCKADDR: case FI_SOCKADDR_IN: case FI_SOCKADDR_IN6: af = ((struct sockaddr *)pep->info->src_addr)->sa_family; break; default: FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "invalid source address format\n"); return -FI_EINVAL; } pep->sock = ofi_socket(af, SOCK_STREAM, 0); if (pep->sock == INVALID_SOCKET) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "failed to create listener: %s\n", strerror(ofi_sockerr())); return -FI_EIO; } if (ofi_addr_get_port(pep->info->src_addr) != 0 || port_range.high == 0) { ret = tcpx_setup_socket(pep->sock); if (ret) { goto err; } ret = bind(pep->sock, pep->info->src_addr, (socklen_t) pep->info->src_addrlen); } else { ret = tcpx_setup_socket_nodelay(pep->sock); if (ret) { goto err; } ret = tcpx_bind_to_port_range(pep->sock, pep->info->src_addr, pep->info->src_addrlen); } if (ret) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "failed to bind listener: %s\n", strerror(ofi_sockerr())); goto err; } return FI_SUCCESS; err: ofi_close_socket(pep->sock); pep->sock = INVALID_SOCKET; return ret; }
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); }
void sock_conn_map_destroy(struct sock_conn_map *cmap) { int i; for (i = 0; i < cmap->used; i++) { ofi_close_socket(cmap->table[i].sock_fd); } free(cmap->table); cmap->table = NULL; cmap->used = cmap->size = 0; sock_epoll_close(&cmap->epoll_set); fastlock_destroy(&cmap->lock); }
static void server_sock_accept(struct util_wait *wait, struct tcpx_cm_context *cm_ctx) { struct tcpx_conn_handle *handle; struct tcpx_pep *pep; SOCKET sock; int ret; FI_DBG(&tcpx_prov, FI_LOG_EP_CTRL, "Received Connreq\n"); assert(cm_ctx->fid->fclass == FI_CLASS_PEP); pep = container_of(cm_ctx->fid, struct tcpx_pep, util_pep.pep_fid.fid); sock = accept(pep->sock, NULL, 0); if (sock < 0) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "accept error: %d\n", ofi_sockerr()); return; } handle = calloc(1, sizeof(*handle)); if (!handle) { FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "cannot allocate memory \n"); goto err1; } cm_ctx = calloc(1, sizeof(*cm_ctx)); if (!cm_ctx) goto err2; handle->conn_fd = sock; handle->handle.fclass = FI_CLASS_CONNREQ; handle->pep = pep; cm_ctx->fid = &handle->handle; cm_ctx->type = SERVER_RECV_CONNREQ; ret = ofi_wait_fd_add(wait, sock, FI_EPOLL_IN, tcpx_eq_wait_try_func, NULL, (void *) cm_ctx); if (ret) goto err3; wait->signal(wait); return; err3: free(cm_ctx); err2: free(handle); err1: ofi_close_socket(sock); }
void sock_conn_map_destroy(struct sock_ep_attr *ep_attr) { int i; struct sock_conn_map *cmap = &ep_attr->cmap; for (i = 0; i < cmap->used; i++) { sock_epoll_del(&cmap->epoll_set, cmap->table[i].sock_fd); sock_pe_poll_del(ep_attr->domain->pe, cmap->table[i].sock_fd); ofi_close_socket(cmap->table[i].sock_fd); } free(cmap->table); cmap->table = NULL; cmap->used = cmap->size = 0; sock_epoll_close(&cmap->epoll_set); fastlock_destroy(&cmap->lock); }
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; }
static int sock_ep_close(struct fid *fid) { struct sock_ep *sock_ep; char c = 0; switch (fid->fclass) { case FI_CLASS_EP: sock_ep = container_of(fid, struct sock_ep, ep.fid); break; case FI_CLASS_SEP: sock_ep = container_of(fid, struct sock_ep, ep.fid); break; default: return -FI_EINVAL; } if (sock_ep->is_alias) { atomic_dec(&sock_ep->attr->ref); return 0; } if (atomic_get(&sock_ep->attr->ref) || atomic_get(&sock_ep->attr->num_rx_ctx) || atomic_get(&sock_ep->attr->num_tx_ctx)) return -FI_EBUSY; if (sock_ep->attr->ep_type == FI_EP_MSG) { sock_ep->attr->cm.do_listen = 0; if (ofi_write_socket(sock_ep->attr->cm.signal_fds[0], &c, 1) != 1) SOCK_LOG_DBG("Failed to signal\n"); if (sock_ep->attr->cm.listener_thread && pthread_join(sock_ep->attr->cm.listener_thread, NULL)) { SOCK_LOG_ERROR("pthread join failed (%d)\n", errno); } ofi_close_socket(sock_ep->attr->cm.signal_fds[0]); ofi_close_socket(sock_ep->attr->cm.signal_fds[1]); } else { if (sock_ep->attr->av) atomic_dec(&sock_ep->attr->av->ref); } pthread_mutex_lock(&sock_ep->attr->domain->pe->list_lock); if (sock_ep->attr->tx_shared) { fastlock_acquire(&sock_ep->attr->tx_ctx->lock); dlist_remove(&sock_ep->attr->tx_ctx_entry); fastlock_release(&sock_ep->attr->tx_ctx->lock); } if (sock_ep->attr->rx_shared) { fastlock_acquire(&sock_ep->attr->rx_ctx->lock); dlist_remove(&sock_ep->attr->rx_ctx_entry); fastlock_release(&sock_ep->attr->rx_ctx->lock); } pthread_mutex_unlock(&sock_ep->attr->domain->pe->list_lock); if (sock_ep->attr->listener.do_listen) { sock_ep->attr->listener.do_listen = 0; if (ofi_write_socket(sock_ep->attr->listener.signal_fds[0], &c, 1) != 1) SOCK_LOG_DBG("Failed to signal\n"); if (sock_ep->attr->listener.listener_thread && pthread_join(sock_ep->attr->listener.listener_thread, NULL)) { SOCK_LOG_ERROR("pthread join failed (%d)\n", errno); } ofi_close_socket(sock_ep->attr->listener.signal_fds[0]); ofi_close_socket(sock_ep->attr->listener.signal_fds[1]); } fastlock_destroy(&sock_ep->attr->cm.lock); if (sock_ep->attr->fclass != FI_CLASS_SEP) { if (!sock_ep->attr->tx_shared) sock_pe_remove_tx_ctx(sock_ep->attr->tx_array[0]); sock_tx_ctx_close(sock_ep->attr->tx_array[0]); sock_tx_ctx_free(sock_ep->attr->tx_array[0]); } if (sock_ep->attr->fclass != FI_CLASS_SEP) { if (!sock_ep->attr->rx_shared) sock_pe_remove_rx_ctx(sock_ep->attr->rx_array[0]); sock_rx_ctx_close(sock_ep->attr->rx_array[0]); sock_rx_ctx_free(sock_ep->attr->rx_array[0]); } idm_reset(&sock_ep->attr->conn_idm); idm_reset(&sock_ep->attr->av_idm); free(sock_ep->attr->tx_array); free(sock_ep->attr->rx_array); if (sock_ep->attr->src_addr) free(sock_ep->attr->src_addr); if (sock_ep->attr->dest_addr) free(sock_ep->attr->dest_addr); sock_conn_map_destroy(&sock_ep->attr->cmap); atomic_dec(&sock_ep->attr->domain->ref); fastlock_destroy(&sock_ep->attr->lock); free(sock_ep->attr); free(sock_ep); return 0; }
struct sock_conn *sock_ep_connect(struct sock_ep_attr *ep_attr, fi_addr_t index) { int conn_fd = -1, ret; int do_retry = sock_conn_retry; struct sock_conn *conn, *new_conn; struct sockaddr_in addr; socklen_t lon; int valopt = 0; struct pollfd poll_fd; if (ep_attr->ep_type == FI_EP_MSG) { /* Need to check that destination address has been passed to endpoint */ assert(ep_attr->dest_addr); addr = *ep_attr->dest_addr; addr.sin_port = htons(ep_attr->msg_dest_port); } else { addr = *((struct sockaddr_in *)&ep_attr->av->table[index].addr); } do_connect: fastlock_acquire(&ep_attr->cmap.lock); conn = sock_ep_lookup_conn(ep_attr, index, &addr); fastlock_release(&ep_attr->cmap.lock); if (conn != SOCK_CM_CONN_IN_PROGRESS) return conn; conn_fd = ofi_socket(AF_INET, SOCK_STREAM, 0); if (conn_fd == -1) { SOCK_LOG_ERROR("failed to create conn_fd, errno: %d\n", errno); errno = FI_EOTHER; return NULL; } ret = fd_set_nonblock(conn_fd); if (ret) { SOCK_LOG_ERROR("failed to set conn_fd nonblocking, errno: %d\n", errno); errno = FI_EOTHER; ofi_close_socket(conn_fd); return NULL; } SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); SOCK_LOG_DBG("Connecting using address:%s\n", inet_ntoa(ep_attr->src_addr->sin_addr)); ret = connect(conn_fd, (struct sockaddr *) &addr, sizeof addr); if (ret < 0) { if (ofi_sockerr() == EINPROGRESS) { poll_fd.fd = conn_fd; poll_fd.events = POLLOUT; ret = poll(&poll_fd, 1, 15 * 1000); if (ret < 0) { SOCK_LOG_DBG("poll failed\n"); goto retry; } lon = sizeof(int); ret = getsockopt(conn_fd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon); if (ret < 0) { SOCK_LOG_DBG("getsockopt failed: %d, %d\n", ret, conn_fd); goto retry; } if (valopt) { SOCK_LOG_DBG("Error in connection() %d - %s - %d\n", valopt, strerror(valopt), conn_fd); SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); SOCK_LOG_DBG("Connecting using address:%s\n", inet_ntoa(ep_attr->src_addr->sin_addr)); goto retry; } goto out; } else { SOCK_LOG_DBG("Timeout or error() - %s: %d\n", strerror(errno), conn_fd); SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); SOCK_LOG_DBG("Connecting using address:%s\n", inet_ntoa(ep_attr->src_addr->sin_addr)); goto retry; } } else { goto out; } retry: do_retry--; sleep(10); if (!do_retry) goto err; if (conn_fd != -1) { ofi_close_socket(conn_fd); conn_fd = -1; } SOCK_LOG_ERROR("Connect error, retrying - %s - %d\n", strerror(errno), conn_fd); SOCK_LOG_DBG("Connecting to: %s:%d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); SOCK_LOG_DBG("Connecting using address:%s\n", inet_ntoa(ep_attr->src_addr->sin_addr)); goto do_connect; out: fastlock_acquire(&ep_attr->cmap.lock); new_conn = sock_conn_map_insert(ep_attr, &addr, conn_fd, 0); if (!new_conn) { fastlock_release(&ep_attr->cmap.lock); goto err; } new_conn->av_index = (ep_attr->ep_type == FI_EP_MSG) ? FI_ADDR_NOTAVAIL : index; conn = ofi_idm_lookup(&ep_attr->av_idm, index); if (conn == SOCK_CM_CONN_IN_PROGRESS) { if (ofi_idm_set(&ep_attr->av_idm, index, new_conn) < 0) SOCK_LOG_ERROR("ofi_idm_set failed\n"); conn = new_conn; } fastlock_release(&ep_attr->cmap.lock); return conn; err: ofi_close_socket(conn_fd); return NULL; }
int sock_conn_listen(struct sock_ep_attr *ep_attr) { struct addrinfo *s_res = NULL, *p; struct addrinfo hints = { 0 }; int listen_fd = 0, ret; socklen_t addr_size; struct sockaddr_in addr; struct sock_conn_listener *listener = &ep_attr->listener; char service[NI_MAXSERV] = {0}; char *port; char ipaddr[24]; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; memcpy(&addr, ep_attr->src_addr, sizeof(addr)); if (getnameinfo((void *)ep_attr->src_addr, sizeof(*ep_attr->src_addr), NULL, 0, listener->service, sizeof(listener->service), NI_NUMERICSERV)) { SOCK_LOG_ERROR("could not resolve src_addr\n"); return -FI_EINVAL; } if (ep_attr->ep_type == FI_EP_MSG) { memset(listener->service, 0, NI_MAXSERV); port = NULL; addr.sin_port = 0; } else port = listener->service; inet_ntop(addr.sin_family, &addr.sin_addr, ipaddr, sizeof(ipaddr)); ret = getaddrinfo(ipaddr, port, &hints, &s_res); if (ret) { SOCK_LOG_ERROR("no available AF_INET address, service %s, %s\n", listener->service, gai_strerror(ret)); return -FI_EINVAL; } SOCK_LOG_DBG("Binding listener thread to port: %s\n", listener->service); for (p = s_res; p; p = p->ai_next) { listen_fd = ofi_socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (listen_fd >= 0) { sock_set_sockopts(listen_fd); if (!bind(listen_fd, s_res->ai_addr, s_res->ai_addrlen)) break; ofi_close_socket(listen_fd); listen_fd = -1; } } freeaddrinfo(s_res); if (listen_fd < 0) { SOCK_LOG_ERROR("failed to listen to port: %s\n", listener->service); goto err; } if (atoi(listener->service) == 0) { addr_size = sizeof(addr); if (getsockname(listen_fd, (struct sockaddr *) &addr, &addr_size)) goto err; snprintf(listener->service, sizeof listener->service, "%d", ntohs(addr.sin_port)); SOCK_LOG_DBG("Bound to port: %s - %d\n", listener->service, getpid()); ep_attr->msg_src_port = ntohs(addr.sin_port); } if (ep_attr->src_addr->sin_addr.s_addr == 0) { snprintf(service, sizeof service, "%s", listener->service); ret = sock_get_src_addr_from_hostname(ep_attr->src_addr, service); if (ret) goto err; } if (listen(listen_fd, sock_cm_def_map_sz)) { SOCK_LOG_ERROR("failed to listen socket: %s\n", strerror(errno)); goto err; } if (((struct sockaddr_in *) (ep_attr->src_addr))->sin_port == 0) { ((struct sockaddr_in *) (ep_attr->src_addr))->sin_port = htons(atoi(listener->service)); } listener->sock = listen_fd; if (socketpair(AF_UNIX, SOCK_STREAM, 0, listener->signal_fds) < 0) goto err; listener->do_listen = 1; fd_set_nonblock(listener->signal_fds[1]); if (pthread_create(&listener->listener_thread, 0, _sock_conn_listen, ep_attr)) { SOCK_LOG_ERROR("failed to create conn listener thread\n"); goto err; } while (!*((volatile int*)&listener->is_ready)); return 0; err: if (listen_fd >= 0) ofi_close_socket(listen_fd); return -FI_EINVAL; }
static int sock_ep_close(struct fid *fid) { struct sock_ep *sock_ep; char c = 0; switch (fid->fclass) { case FI_CLASS_EP: sock_ep = container_of(fid, struct sock_ep, ep.fid); break; case FI_CLASS_SEP: sock_ep = container_of(fid, struct sock_ep, ep.fid); break; default: return -FI_EINVAL; } if (sock_ep->is_alias) { ofi_atomic_dec32(&sock_ep->attr->ref); return 0; } if (ofi_atomic_get32(&sock_ep->attr->ref) || ofi_atomic_get32(&sock_ep->attr->num_rx_ctx) || ofi_atomic_get32(&sock_ep->attr->num_tx_ctx)) return -FI_EBUSY; if (sock_ep->attr->ep_type == FI_EP_MSG) { sock_ep->attr->cm.do_listen = 0; if (ofi_write_socket(sock_ep->attr->cm.signal_fds[0], &c, 1) != 1) SOCK_LOG_DBG("Failed to signal\n"); if (sock_ep->attr->cm.listener_thread && pthread_join(sock_ep->attr->cm.listener_thread, NULL)) { SOCK_LOG_ERROR("pthread join failed (%d)\n", ofi_syserr()); } ofi_close_socket(sock_ep->attr->cm.signal_fds[0]); ofi_close_socket(sock_ep->attr->cm.signal_fds[1]); } else { if (sock_ep->attr->av) ofi_atomic_dec32(&sock_ep->attr->av->ref); } if (sock_ep->attr->av) { fastlock_acquire(&sock_ep->attr->av->list_lock); fid_list_remove(&sock_ep->attr->av->ep_list, &sock_ep->attr->lock, &sock_ep->ep.fid); fastlock_release(&sock_ep->attr->av->list_lock); } pthread_mutex_lock(&sock_ep->attr->domain->pe->list_lock); if (sock_ep->attr->tx_shared) { fastlock_acquire(&sock_ep->attr->tx_ctx->lock); dlist_remove(&sock_ep->attr->tx_ctx_entry); fastlock_release(&sock_ep->attr->tx_ctx->lock); } if (sock_ep->attr->rx_shared) { fastlock_acquire(&sock_ep->attr->rx_ctx->lock); dlist_remove(&sock_ep->attr->rx_ctx_entry); fastlock_release(&sock_ep->attr->rx_ctx->lock); } pthread_mutex_unlock(&sock_ep->attr->domain->pe->list_lock); if (sock_ep->attr->conn_handle.do_listen) { fastlock_acquire(&sock_ep->attr->domain->conn_listener.signal_lock); fi_epoll_del(sock_ep->attr->domain->conn_listener.emap, sock_ep->attr->conn_handle.sock); fastlock_release(&sock_ep->attr->domain->conn_listener.signal_lock); ofi_close_socket(sock_ep->attr->conn_handle.sock); sock_ep->attr->conn_handle.do_listen = 0; } fastlock_destroy(&sock_ep->attr->cm.lock); if (sock_ep->attr->eq) { fastlock_acquire(&sock_ep->attr->eq->lock); sock_ep_clear_eq_list(&sock_ep->attr->eq->list, &sock_ep->ep); /* Any err_data if present would be freed by * sock_eq_clean_err_data_list when EQ is closed */ sock_ep_clear_eq_list(&sock_ep->attr->eq->err_list, &sock_ep->ep); fastlock_release(&sock_ep->attr->eq->lock); } if (sock_ep->attr->fclass != FI_CLASS_SEP) { if (!sock_ep->attr->tx_shared) sock_pe_remove_tx_ctx(sock_ep->attr->tx_array[0]); sock_tx_ctx_close(sock_ep->attr->tx_array[0]); sock_tx_ctx_free(sock_ep->attr->tx_array[0]); } if (sock_ep->attr->fclass != FI_CLASS_SEP) { if (!sock_ep->attr->rx_shared) sock_pe_remove_rx_ctx(sock_ep->attr->rx_array[0]); sock_rx_ctx_close(sock_ep->attr->rx_array[0]); sock_rx_ctx_free(sock_ep->attr->rx_array[0]); } free(sock_ep->attr->tx_array); free(sock_ep->attr->rx_array); if (sock_ep->attr->src_addr) free(sock_ep->attr->src_addr); if (sock_ep->attr->dest_addr) free(sock_ep->attr->dest_addr); fastlock_acquire(&sock_ep->attr->domain->pe->lock); ofi_idm_reset(&sock_ep->attr->av_idm); sock_conn_map_destroy(sock_ep->attr); fastlock_release(&sock_ep->attr->domain->pe->lock); ofi_atomic_dec32(&sock_ep->attr->domain->ref); fastlock_destroy(&sock_ep->attr->lock); free(sock_ep->attr); free(sock_ep); return 0; }
static void *util_ns_name_server_func(void *args) { struct util_ns *ns; struct addrinfo hints = { .ai_flags = AI_PASSIVE, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; struct addrinfo *res, *p; void *cleanup_args[2]; char *service; SOCKET listenfd = INVALID_SOCKET, connfd; int n, ret; struct util_ns_cmd cmd = (const struct util_ns_cmd){ 0 }; ns = (struct util_ns *)args; if (asprintf(&service, "%d", ns->ns_port) < 0) return NULL; n = getaddrinfo(NULL, service, &hints, &res); if (n < 0) { free(service); return NULL; } for (p = res; p; p = p->ai_next) { listenfd = ofi_socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (listenfd != INVALID_SOCKET) { n = 1; (void) setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); if (!bind(listenfd, p->ai_addr, p->ai_addrlen)) break; ofi_close_socket(listenfd); listenfd = INVALID_SOCKET; } } freeaddrinfo(res); free(service); if (listenfd == INVALID_SOCKET) return NULL; if (util_ns_map_init(ns)) goto done; ret = listen(listenfd, 256); if (ret) goto done; cleanup_args[0] = (void *)(uintptr_t)listenfd; cleanup_args[1] = (void *)ns; pthread_cleanup_push(util_ns_name_server_cleanup, (void *)cleanup_args); while (1) { connfd = accept(listenfd, NULL, 0); if (connfd != INVALID_SOCKET) { /* Read service data */ ret = ofi_read_socket(connfd, &cmd, cmd_len); if (ret == cmd_len) { (void) util_ns_op_dispatcher(ns, &cmd, connfd); } ofi_close_socket(connfd); } } pthread_cleanup_pop(1); done: ofi_close_socket(listenfd); return NULL; } /* * Name server API: client side */ static int util_ns_connect_server(struct util_ns *ns, const char *server) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; struct addrinfo *res, *p; char *service; SOCKET sockfd = INVALID_SOCKET; int n; if (asprintf(&service, "%d", ns->ns_port) < 0) return -1; n = getaddrinfo(server, service, &hints, &res); if (n < 0) { free(service); return -1; } for (p = res; p; p = p->ai_next) { sockfd = ofi_socket(p->ai_family, p->ai_socktype, p->ai_protocol); if (sockfd != INVALID_SOCKET) { if (!connect(sockfd, p->ai_addr, p->ai_addrlen)) break; ofi_close_socket(sockfd); sockfd = INVALID_SOCKET; } } freeaddrinfo(res); free(service); return sockfd; } int ofi_ns_add_local_name(struct util_ns *ns, void *service, void *name) { SOCKET sockfd; int ret; char *server = (ns->ns_hostname ? ns->ns_hostname : OFI_NS_DEFAULT_HOSTNAME); void *write_buf; size_t write_len = 0; struct util_ns_cmd cmd = { .op = OFI_UTIL_NS_ADD, .status = 0, }; write_buf = calloc(cmd_len + ns->service_len + ns->name_len, 1); if (!write_buf) { ret = -FI_ENOMEM; goto err1; } memcpy(write_buf, &cmd, cmd_len); write_len += cmd_len; memcpy((void *)((char *)write_buf + write_len), service, ns->service_len); write_len += ns->service_len; memcpy((void *)((char *)write_buf + write_len), name, ns->name_len); write_len += ns->name_len; sockfd = util_ns_connect_server(ns, server); if (sockfd == INVALID_SOCKET) { ret = -FI_ENODATA; goto err2; } ret = util_ns_write_socket_op(sockfd, write_buf, write_len); ret = ((ret == write_len) ? FI_SUCCESS : -FI_ENODATA); ofi_close_socket(sockfd); err2: free(write_buf); err1: return ret; } int ofi_ns_del_local_name(struct util_ns *ns, void *service, void *name) { SOCKET sockfd; int ret; const char *server_hostname = (ns->ns_hostname ? ns->ns_hostname : OFI_NS_DEFAULT_HOSTNAME); void *write_buf; size_t write_len = 0; struct util_ns_cmd cmd = { .op = OFI_UTIL_NS_DEL, .status = 0, }; write_buf = calloc(cmd_len + ns->service_len + ns->name_len, 1); if (!write_buf) { ret = -FI_ENOMEM; goto err1; } memcpy(write_buf, &cmd, cmd_len); write_len += cmd_len; memcpy((void *)((char *)write_buf + write_len), service, ns->service_len); write_len += ns->service_len; memcpy((void *)((char *)write_buf + write_len), name, ns->name_len); write_len += ns->name_len; sockfd = util_ns_connect_server(ns, server_hostname); if (sockfd == INVALID_SOCKET) { ret = -FI_ENODATA; goto err2; } ret = util_ns_write_socket_op(sockfd, write_buf, write_len); ret = ((ret == write_len) ? FI_SUCCESS : -FI_ENODATA); ofi_close_socket(sockfd); err2: free(write_buf); err1: return ret; } void *ofi_ns_resolve_name(struct util_ns *ns, const char *server_hostname, void *service) { void *dest_addr = NULL, *io_buf; size_t io_len = 0; SOCKET sockfd; ssize_t ret = 0; struct util_ns_cmd cmd = { .op = OFI_UTIL_NS_QUERY, .status = 0, }; sockfd = util_ns_connect_server(ns, server_hostname); if (sockfd == INVALID_SOCKET) goto err1; io_buf = calloc(cmd_len + ns->service_len, 1); if (!io_buf) goto err2; memcpy(io_buf, &cmd, cmd_len); io_len += cmd_len; memcpy((void *)((char *)io_buf + io_len), service, ns->service_len); io_len += ns->service_len; ret = util_ns_write_socket_op(sockfd, io_buf, io_len); if (ret < 0) goto err3; free(io_buf); io_len = ns->service_len + ns->name_len; io_buf = calloc(io_len, 1); if (!io_buf) goto err2; ret = util_ns_read_socket_op(sockfd, &cmd, cmd_len); if (ret < 0 || cmd.status) goto err3; ret = util_ns_read_socket_op(sockfd, io_buf, io_len); if (ret == io_len) { dest_addr = calloc(ns->name_len, 1); if (!dest_addr) goto err3; io_len = 0; memcpy(service, (void *)((char *)io_buf + io_len), ns->service_len); io_len += ns->service_len; memcpy(dest_addr, (void *)((char *)io_buf + io_len), ns->name_len); } err3: free(io_buf); err2: ofi_close_socket(sockfd); err1: return dest_addr; } /* * Name server API: server side */ void ofi_ns_start_server(struct util_ns *ns) { int ret; SOCKET sockfd; int sleep_usec = 1000; char *server_hostname = (ns->ns_hostname ? ns->ns_hostname : OFI_NS_DEFAULT_HOSTNAME); ofi_osd_init(); ret = pthread_create(&ns->ns_thread, NULL, util_ns_name_server_func, (void *)ns); if (ret) { /* * use the main thread's ID as invalid * value for the new thread */ ns->ns_thread = pthread_self(); } /* * Wait for the local name server to come up. It could be the thread * created above, or the thread created by another process on the same * node. The total wait time is about (1+2+4+...+8192)ms = 16 seconds. */ while (sleep_usec < 10000) { sockfd = util_ns_connect_server(ns, server_hostname); if (sockfd != INVALID_SOCKET) { ofi_close_socket(sockfd); return; } usleep(sleep_usec); sleep_usec *= 2; } }
static void util_ns_name_server_cleanup(void *args) { void **cleanup_args = (void **)args; ofi_close_socket((uintptr_t)cleanup_args[0]); util_ns_map_fini((struct util_ns *)cleanup_args[1]); }