Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
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;
}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
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) {
		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;
}
Esempio n. 14
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;
	}
}
Esempio n. 15
0
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]);
}