Example #1
0
static void handle_accept_conn(struct poll_fd_mgr *poll_mgr,
			       struct poll_fd_info *poll_info)
{
	struct fi_eq_cm_entry cm_entry;
	struct fi_eq_err_entry err_entry;
	struct tcpx_ep *ep;
	int ret;

	assert(poll_info->fid->fclass == FI_CLASS_EP);
	ep = container_of(poll_info->fid, struct tcpx_ep, util_ep.ep_fid.fid);

	ret = tx_cm_data(ep->conn_fd, ofi_ctrl_connresp, poll_info);
	if (ret)
		goto err;

	cm_entry.fid =  poll_info->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 = fi_fd_nonblock(ep->conn_fd);
	return;
err:
	memset(&err_entry, 0, sizeof err_entry);
	err_entry.fid = poll_info->fid;
	err_entry.context = poll_info->fid->context;
	err_entry.err = ret;

	fi_eq_write(&ep->util_ep.eq->eq_fid, FI_SHUTDOWN,
		    &err_entry, sizeof(err_entry), UTIL_FLAG_ERROR);
}
DIRECT_FN STATIC int gnix_shutdown(struct fid_ep *ep, uint64_t flags)
{
	int ret;
	struct gnix_fid_ep *ep_priv;
	struct fi_eq_cm_entry eq_entry = {0};

	if (!ep)
		return -FI_EINVAL;

	ep_priv = container_of(ep, struct gnix_fid_ep, ep_fid.fid);

	COND_ACQUIRE(ep_priv->requires_lock, &ep_priv->vc_lock);

	eq_entry.fid = &ep_priv->ep_fid.fid;

	ret = fi_eq_write(&ep_priv->eq->eq_fid, FI_SHUTDOWN, &eq_entry,
			  sizeof(eq_entry), 0);
	if (ret != sizeof(eq_entry)) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "fi_eq_write failed, err: %d\n", ret);
	} else {
		ret = FI_SUCCESS;
	}

	COND_RELEASE(ep_priv->requires_lock, &ep_priv->vc_lock);

	return ret;
}
Example #3
0
static int proc_conn_resp(struct poll_fd_mgr *poll_mgr,
			  struct poll_fd_info *poll_info,
			  struct tcpx_ep *ep,
			  int index)
{
	struct ofi_ctrl_hdr conn_resp;
	struct fi_eq_cm_entry *cm_entry;
	int ret = FI_SUCCESS;

	assert(poll_mgr->poll_fds[index].revents == POLLIN);
	ret = rx_cm_data(ep->conn_fd, &conn_resp, ofi_ctrl_connresp, poll_info);
	if (ret)
		return ret;

	cm_entry = calloc(1, sizeof(*cm_entry) + poll_info->cm_data_sz);
	if (!cm_entry) {
		FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "mem alloc failed\n");
		return -FI_ENOMEM;
	}

	cm_entry->fid = poll_info->fid;
	memcpy(cm_entry->data, poll_info->cm_data, poll_info->cm_data_sz);

	ret = (int) fi_eq_write(&ep->util_ep.eq->eq_fid, FI_CONNECTED, 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 err;
	}
	ret = fi_fd_nonblock(ep->conn_fd);
err:
	free(cm_entry);
	return ret;
}
Example #4
0
static int proc_conn_resp(struct tcpx_cm_context *cm_ctx,
			  struct tcpx_ep *ep)
{
	struct ofi_ctrl_hdr conn_resp;
	struct fi_eq_cm_entry *cm_entry;
	ssize_t len;
	int ret = FI_SUCCESS;

	ret = rx_cm_data(ep->conn_fd, &conn_resp, ofi_ctrl_connresp, cm_ctx);
	if (ret)
		return ret;

	cm_entry = calloc(1, sizeof(*cm_entry) + cm_ctx->cm_data_sz);
	if (!cm_entry)
		return -FI_ENOMEM;

	cm_entry->fid = cm_ctx->fid;
	memcpy(cm_entry->data, cm_ctx->cm_data, cm_ctx->cm_data_sz);

	ret = tcpx_ep_msg_xfer_enable(ep);
	if (ret)
		goto err;

	len = fi_eq_write(&ep->util_ep.eq->eq_fid, FI_CONNECTED, cm_entry,
			  sizeof(*cm_entry) + cm_ctx->cm_data_sz, 0);
	if (len < 0) {
		ret = (int) len;
		goto err;
	}
err:
	free(cm_entry);
	return ret;
}
Example #5
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);
}
Example #6
0
static ssize_t hook_eq_write(struct fid_eq *eq, uint32_t event,
			     const void *buf, size_t len, uint64_t flags)
{
	struct hook_eq *myeq = container_of(eq, struct hook_eq, eq);

	return fi_eq_write(myeq->heq, event, buf, len, flags);
}
Example #7
0
static void ip_av_write_event(struct util_av *av, uint64_t data,
			      int err, void *context)
{
	struct fi_eq_err_entry entry;
	size_t size;
	ssize_t ret;
	uint64_t flags;

	entry.fid = &av->av_fid.fid;
	entry.context = context;
	entry.data = data;

	if (err) {
		FI_INFO(av->prov, FI_LOG_AV, "writing error entry to EQ\n");
		entry.err = err;
		size = sizeof(struct fi_eq_err_entry);
		flags = UTIL_FLAG_ERROR;
	} else {
		FI_DBG(av->prov, FI_LOG_AV, "writing entry to EQ\n");
		size = sizeof(struct fi_eq_entry);
		flags = 0;
	}

	ret = fi_eq_write(&av->eq->eq_fid, FI_AV_COMPLETE, &entry,
			  size, flags);
	if (ret != size)
		FI_WARN(av->prov, FI_LOG_AV, "error writing to EQ\n");
}
/* Process an incoming connection request at a listening PEP. */
static int __gnix_pep_connreq(struct gnix_fid_pep *pep, int fd)
{
	int ret;
	struct gnix_pep_sock_conn *conn;
	struct fi_eq_cm_entry *eq_entry;
	int eqe_size;

	/* Create and initialize a new connection request. */
	conn = calloc(1, sizeof(*conn));
	if (!conn) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Failed to alloc accepted socket conn\n");
		return -FI_ENOMEM;
	}

	conn->fid.fclass = FI_CLASS_CONNREQ;
	conn->fid.context = pep;
	conn->sock_fd = fd;

	/* Pull request data from the listening socket. */
	conn->bytes_read += read(fd, &conn->req, sizeof(conn->req));
	if (conn->bytes_read != sizeof(conn->req)) {
		/* TODO Wait for more bytes. */
		GNIX_FATAL(FI_LOG_EP_CTRL, "Unexpected read size\n");
	}

	conn->req.info.src_addr = &conn->req.src_addr;
	conn->req.info.dest_addr = &conn->req.dest_addr;
	conn->req.info.tx_attr = &conn->req.tx_attr;
	conn->req.info.rx_attr = &conn->req.rx_attr;
	conn->req.info.ep_attr = &conn->req.ep_attr;
	conn->req.info.domain_attr = &conn->req.domain_attr;
	conn->req.info.fabric_attr = &conn->req.fabric_attr;
	conn->req.info.domain_attr->name = NULL;
	conn->req.info.fabric_attr->name = NULL;
	conn->req.info.fabric_attr->prov_name = NULL;

	conn->info = &conn->req.info;
	conn->info->handle = &conn->fid;

	/* Tell user of a new conn req via the EQ. */
	eq_entry = (struct fi_eq_cm_entry *)conn->req.eqe_buf;
	eq_entry->fid = &pep->pep_fid.fid;
	eq_entry->info = fi_dupinfo(conn->info);

	eqe_size = sizeof(*eq_entry) + conn->req.cm_data_len;
	ret = fi_eq_write(&pep->eq->eq_fid, FI_CONNREQ, eq_entry, eqe_size, 0);
	if (ret != eqe_size) {
		GNIX_WARN(FI_LOG_EP_CTRL, "fi_eq_write failed, err: %d\n", ret);
		fi_freeinfo(conn->info);
		free(conn);
		return ret;
	}

	GNIX_DEBUG(FI_LOG_EP_CTRL, "Added FI_CONNREQ EQE: %p, %p\n",
		   pep->eq, pep);

	return FI_SUCCESS;
}
Example #9
0
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);
}
Example #10
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);
}
Example #11
0
static void tcpx_report_error(struct tcpx_ep *tcpx_ep, int err)
{
	struct fi_eq_err_entry err_entry = {0};

	tcpx_cq_report_xfer_fail(tcpx_ep, err);
	err_entry.fid = &tcpx_ep->util_ep.ep_fid.fid;
	err_entry.context = tcpx_ep->util_ep.ep_fid.fid.context;
	err_entry.err = -err;

	fi_eq_write(&tcpx_ep->util_ep.eq->eq_fid, FI_NOTIFY,
		    &err_entry, sizeof(err_entry), UTIL_FLAG_ERROR);
}
Example #12
0
/*
 * Tests:
 * - write overflow
 */
static int
eq_write_overflow()
{
	struct fi_eq_entry entry;
	int testret;
	int ret;
	int i;

	testret = FAIL;

	ret = create_eq(32, FI_WRITE, FI_WAIT_NONE);
	if (ret != 0) {
		sprintf(err_buf, "fi_eq_open ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	/* Insert some events */
	for (i = 0; i < 32; ++i) {
		entry.fid = &fabric->fid;
		entry.context = (void *)(uintptr_t)i;
		ret = fi_eq_write(eq, FI_NOTIFY, &entry, sizeof(entry), 0);
		if (ret != sizeof(entry)) {
			sprintf(err_buf, "fi_eq_write ret=%d, %s", ret, fi_strerror(-ret));
			goto fail;
		}
	}

	ret = fi_eq_write(eq, FI_NOTIFY, &entry, sizeof(entry), 0);
	if (ret != -FI_EAGAIN && ret != sizeof(entry)) {
		sprintf(err_buf, "fi_eq_write of full EQ returned %d", ret);
		goto fail;
	}

	testret = PASS;

fail:
	FT_CLOSE_FID(eq);
	return TEST_RET_VAL(ret, testret);
}
Example #13
0
static void psmx_av_post_completion(struct psmx_fid_av *av, void *context,
				    uint64_t data, int prov_errno)
{
	if (prov_errno) {
		struct fi_eq_err_entry entry;
		entry.fid = &av->av.fid;
		entry.context = context;
		entry.data = data;
		entry.err = -psmx_errno(prov_errno);
		entry.prov_errno = prov_errno;
		entry.err_data = NULL;
		entry.err_data_size = 0;
		fi_eq_write(av->eq, FI_AV_COMPLETE, &entry, sizeof(entry),
			    UTIL_FLAG_ERROR);
	} else {
		struct fi_eq_entry entry;
		entry.fid = &av->av.fid;
		entry.context = context;
		entry.data = data;
		fi_eq_write(av->eq, FI_AV_COMPLETE, &entry, sizeof(entry), 0);
	}
}
Example #14
0
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);
}
Example #15
0
int tcpx_ep_shutdown_report(struct tcpx_ep *ep, fid_t fid)
{
	struct fi_eq_cm_entry cm_entry = {0};
	ssize_t len;

	if (ep->cm_state == TCPX_EP_SHUTDOWN)
		return FI_SUCCESS;
	tcpx_cq_report_xfer_fail(ep, -FI_ENOTCONN);
	ep->cm_state = TCPX_EP_SHUTDOWN;
	cm_entry.fid = fid;
	len =  fi_eq_write(&ep->util_ep.eq->eq_fid, FI_SHUTDOWN,
			   &cm_entry, sizeof(cm_entry), 0);
	if (len < 0)
		return (int) len;

	return FI_SUCCESS;
}
Example #16
0
static int insert_events(size_t count)
{
	struct fi_eq_entry entry;
	size_t i;
	int ret;

	for (i = 0; i < count; i++) {
		ret = fi_eq_write(eq, FI_NOTIFY, &entry, sizeof(entry), 0);
		if (ret != sizeof(entry)) {
			sprintf(err_buf, "fi_eq_write ret=%d, %s", ret,
					fi_strerror(-ret));
			return ret;
		}
	}

	return FI_SUCCESS;
}
Example #17
0
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);
	}
}
Example #18
0
static void handle_connect(struct poll_fd_mgr *poll_mgr,
			   int index)
{
	struct tcpx_ep *ep;
	struct poll_fd_info *poll_info = &poll_mgr->poll_info[index];
	struct fi_eq_err_entry err_entry;
	int ret;

	assert(poll_info->fid->fclass == FI_CLASS_EP);
	ep = container_of(poll_info->fid, struct tcpx_ep, util_ep.ep_fid.fid);

	switch (poll_info->state) {
	case ESTABLISH_CONN:
		ret = send_conn_req(poll_mgr, poll_info, ep, index);
		if (ret)
			goto err;

		poll_info->state = RCV_RESP;
		poll_mgr->poll_fds[index].events = POLLIN;
		break;
	case RCV_RESP:
		ret = proc_conn_resp(poll_mgr, poll_info, ep, index);
		if (ret)
			goto err;

		poll_info->state = CONNECT_DONE;
		break;
	default:
		FI_WARN(&tcpx_prov, FI_LOG_EP_CTRL, "Invalid connection state\n");
		ret = -FI_EINVAL;
		goto err;
	}
	return;
err:
	memset(&err_entry, 0, sizeof err_entry);
	err_entry.fid = poll_info->fid;
	err_entry.context = poll_info->fid->context;
	err_entry.err = ret;

	poll_info->state = CONNECT_DONE;
	fi_eq_write(&ep->util_ep.eq->eq_fid, FI_SHUTDOWN,
		    &err_entry, sizeof(err_entry), UTIL_FLAG_ERROR);
}
Example #19
0
/*
 * Tests:
 * - extracting FD from EQ with FI_WAIT_FD
 * - wait on fd with nothing pending
 * - wait on fd with event pending
 */
static int
eq_wait_fd_poll()
{
	int fd;
	struct fi_eq_entry entry;
	struct pollfd pfd;
	struct fid *fids[1];
	int testret;
	int ret;

	testret = FAIL;

	ret = create_eq(32, FI_WRITE, FI_WAIT_FD);
	if (ret != 0) {
		sprintf(err_buf, "fi_eq_open ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	ret = fi_control(&eq->fid, FI_GETWAIT, &fd);
	if (ret != 0) {
		sprintf(err_buf, "fi_control ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	fids[0] = &eq->fid;
	if (fi_trywait(fabric, fids, 1) != FI_SUCCESS) {
		sprintf(err_buf, "fi_trywait ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	pfd.fd = fd;
	pfd.events = POLLIN;
	ret = poll(&pfd, 1, 0);
	if (ret < 0) {
		sprintf(err_buf, "poll errno=%d, %s", errno, fi_strerror(-errno));
		goto fail;
	}
	if (ret > 0) {
		sprintf(err_buf, "poll returned %d, should be 0", ret);
		goto fail;
	}

	/* write an event */
	entry.fid = &eq->fid;
	entry.context = eq;
	ret = fi_eq_write(eq, FI_NOTIFY, &entry, sizeof(entry), 0);
	if (ret != sizeof(entry)) {
		sprintf(err_buf, "fi_eq_write ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	pfd.fd = fd;
	pfd.events = POLLIN;
	ret = poll(&pfd, 1, 0);
	if (ret < 0) {
		sprintf(err_buf, "poll errno=%d, %s", errno, fi_strerror(-errno));
		goto fail;
	}
	if (ret != 1) {
		sprintf(err_buf, "poll returned %d, should be 1", ret);
		goto fail;
	}

	testret = PASS;
fail:
	FT_CLOSE_FID(eq);
	return TEST_RET_VAL(ret, testret);
}
Example #20
0
/*
 * Tests:
 * - sread with event pending
 * - sread with no event pending
 */
static int
eq_wait_fd_sread()
{
	struct fi_eq_entry entry;
	uint32_t event;
	int64_t elapsed;
	int testret;
	int ret;

	testret = FAIL;

	ret = create_eq(32, FI_WRITE, FI_WAIT_FD);
	if (ret != 0) {
		sprintf(err_buf, "fi_eq_open ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	/* timed sread on empty EQ, 2s timeout */
	ft_start();
	ret = fi_eq_sread(eq, &event, &entry, sizeof(entry), 2000, 0);
	if (ret != -FI_EAGAIN) {
		sprintf(err_buf, "fi_eq_read of empty EQ returned %d", ret);
		goto fail;
	}

	/* check timeout accuracy */
	ft_stop();
	elapsed = get_elapsed(&start, &end, MILLI);
	if (elapsed < 1500 || elapsed > 2500) {
		sprintf(err_buf, "fi_eq_sread slept %d ms, expected 2000",
				(int)elapsed);
		goto fail;
	}

	/* write an event */
	entry.fid = &eq->fid;
	entry.context = eq;
	ret = fi_eq_write(eq, FI_NOTIFY, &entry, sizeof(entry), 0);
	if (ret != sizeof(entry)) {
		sprintf(err_buf, "fi_eq_write ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	/* timed sread on EQ with event, 2s timeout */
	ft_start();
	event = ~0;
	memset(&entry, 0, sizeof(entry));
	ret = fi_eq_sread(eq, &event, &entry, sizeof(entry), 2000, 0);
	if (ret != sizeof(entry)) {
		sprintf(err_buf, "fi_eq_read ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	/* check that no undue waiting occurred */
	ft_stop();
	elapsed = get_elapsed(&start, &end, MILLI);
	if (elapsed > 5) {
		sprintf(err_buf, "fi_eq_sread slept %d ms, expected immediate return",
				(int)elapsed);
		goto fail;
	}

	if (event != FI_NOTIFY) {
		sprintf(err_buf, "fi_eq_sread: event = %d, should be %d\n", event,
				FI_NOTIFY);
		goto fail;
	}
	if (entry.fid != &eq->fid) {
		sprintf(err_buf, "fi_eq_sread: fid mismatch: %p should be %p\n",
				entry.fid, &eq->fid);
		goto fail;
	}
	if (entry.context != eq) {
		sprintf(err_buf, "fi_eq_sread: context mismatch: %p should be %p\n",
				entry.context, eq);
		goto fail;
	}

	testret = PASS;
fail:
	FT_CLOSE_FID(eq);
	return TEST_RET_VAL(ret, testret);
}
Example #21
0
/*
 * Tests:
 * - writing to EQ
 * - reading from EQ with and without FI_PEEK
 * - underflow read
 */
static int
eq_write_read_self()
{
	struct fi_eq_entry entry;
	uint32_t event;
	int testret;
	int ret;
	int i;

	testret = FAIL;

	ret = create_eq(32, FI_WRITE, FI_WAIT_NONE);
	if (ret != 0) {
		sprintf(err_buf, "fi_eq_open ret=%d, %s", ret, fi_strerror(-ret));
		goto fail;
	}

	/* Insert some events */
	for (i = 0; i < 5; ++i) {
		if (i & 1) {
			entry.fid = &fabric->fid;
		} else {
			entry.fid = &eq->fid;
		}
		entry.context = (void *)(uintptr_t)i;
		ret = fi_eq_write(eq, FI_NOTIFY, &entry, sizeof(entry), 0);
		if (ret != sizeof(entry)) {
			sprintf(err_buf, "fi_eq_write ret=%d, %s", ret, fi_strerror(-ret));
			goto fail;
		}
	}

	/* Now read them back, peeking first at each one */
	for (i = 0; i < 10; ++i) {
		event = ~0;
		memset(&entry, 0, sizeof(entry));
		ret = fi_eq_read(eq, &event, &entry, sizeof(entry),
				(i & 1) ? 0 : FI_PEEK);
		if (ret != sizeof(entry)) {
			sprintf(err_buf, "fi_eq_read ret=%d, %s", ret, fi_strerror(-ret));
			goto fail;
		}

		if (event != FI_NOTIFY) {
			sprintf(err_buf, "iter %d: event = %d, should be %d\n", i, event,
					FI_NOTIFY);
			goto fail;
		}

		if ((int)(uintptr_t)entry.context != i / 2) {
			sprintf(err_buf, "iter %d: context mismatch %d != %d", i,
					(int)(uintptr_t)entry.context, i / 2);
			goto fail;
		}

		if (entry.fid != ((i & 2) ? &fabric->fid : &eq->fid)) {
			sprintf(err_buf, "iter %d: fid mismatch %p != %p", i,
					entry.fid, ((i & 2) ? &fabric->fid : &eq->fid));
			goto fail;
		}
	}

	/* queue is now empty */
	ret = fi_eq_read(eq, &event, &entry, sizeof(entry), 0);
	if (ret != -FI_EAGAIN) {
		sprintf(err_buf, "fi_eq_read of empty EQ returned %d", ret);
		goto fail;
	}
	testret = PASS;

fail:
	FT_CLOSE_FID(eq);
	return TEST_RET_VAL(ret, testret);
}
Example #22
0
DIRECT_FN STATIC int gnix_accept(struct fid_ep *ep, const void *param,
				 size_t paramlen)
{
	int ret;
	struct gnix_vc *vc;
	struct gnix_fid_ep *ep_priv;
	struct gnix_pep_sock_conn *conn;
	struct gnix_pep_sock_connresp resp;
	struct fi_eq_cm_entry eq_entry, *eqe_ptr;
	struct gnix_mbox *mbox = NULL;
	struct gnix_av_addr_entry av_entry;

	if (!ep || (paramlen && !param) || paramlen > GNIX_CM_DATA_MAX_SIZE)
		return -FI_EINVAL;

	ep_priv = container_of(ep, struct gnix_fid_ep, ep_fid.fid);

	COND_ACQUIRE(ep_priv->requires_lock, &ep_priv->vc_lock);

	/* Look up and unpack the connection request used to create this EP. */
	conn = (struct gnix_pep_sock_conn *)ep_priv->info->handle;
	if (!conn || conn->fid.fclass != FI_CLASS_CONNREQ) {
		ret = -FI_EINVAL;
		goto err_unlock;
	}

	/* Create new VC without CM data. */
	av_entry.gnix_addr = ep_priv->dest_addr.gnix_addr;
	av_entry.cm_nic_cdm_id = ep_priv->dest_addr.cm_nic_cdm_id;
	ret = _gnix_vc_alloc(ep_priv, &av_entry, &vc);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL, "Failed to create VC: %d\n", ret);
		goto err_unlock;
	}
	ep_priv->vc = vc;
	ep_priv->vc->peer_caps = conn->req.peer_caps;
	ep_priv->vc->peer_id = conn->req.vc_id;

	ret = _gnix_mbox_alloc(vc->ep->nic->mbox_hndl, &mbox);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_DATA, "_gnix_mbox_alloc returned %s\n",
			  fi_strerror(-ret));
		goto err_mbox_alloc;
	}
	vc->smsg_mbox = mbox;

	/* Initialize the GNI connection. */
	ret = _gnix_vc_smsg_init(vc, conn->req.vc_id,
				 &conn->req.vc_mbox_attr,
				 &conn->req.cq_irq_mdh);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "_gnix_vc_smsg_init returned %s\n",
			  fi_strerror(-ret));
		goto err_smsg_init;
	}

	vc->conn_state = GNIX_VC_CONNECTED;

	/* Send ACK with VC attrs to allow peer to initialize GNI connection. */
	resp.cmd = GNIX_PEP_SOCK_RESP_ACCEPT;

	resp.vc_id = vc->vc_id;
	resp.vc_mbox_attr.msg_type = GNI_SMSG_TYPE_MBOX_AUTO_RETRANSMIT;
	resp.vc_mbox_attr.msg_buffer = mbox->base;
	resp.vc_mbox_attr.buff_size =  vc->ep->nic->mem_per_mbox;
	resp.vc_mbox_attr.mem_hndl = *mbox->memory_handle;
	resp.vc_mbox_attr.mbox_offset = (uint64_t)mbox->offset;
	resp.vc_mbox_attr.mbox_maxcredit =
			ep_priv->domain->params.mbox_maxcredit;
	resp.vc_mbox_attr.msg_maxsize =
			ep_priv->domain->params.mbox_msg_maxsize;
	resp.cq_irq_mdh = ep_priv->nic->irq_mem_hndl;
	resp.peer_caps = ep_priv->caps;

	resp.cm_data_len = paramlen;
	if (paramlen) {
		eqe_ptr = (struct fi_eq_cm_entry *)resp.eqe_buf;
		memcpy(eqe_ptr->data, param, paramlen);
	}

	ret = write(conn->sock_fd, &resp, sizeof(resp));
	if (ret != sizeof(resp)) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "Failed to send resp, errno: %d\n",
			  errno);
		ret = -FI_EIO;
		goto err_write;
	}

	/* Notify user that this side is connected. */
	eq_entry.fid = &ep_priv->ep_fid.fid;

	ret = fi_eq_write(&ep_priv->eq->eq_fid, FI_CONNECTED, &eq_entry,
			  sizeof(eq_entry), 0);
	if (ret != sizeof(eq_entry)) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "fi_eq_write failed, err: %d\n", ret);
		goto err_eq_write;
	}

	/* Free the connection request. */
	free(conn);

	ep_priv->conn_state = GNIX_EP_CONNECTED;

	COND_RELEASE(ep_priv->requires_lock, &ep_priv->vc_lock);

	GNIX_DEBUG(FI_LOG_EP_CTRL, "Sent conn accept: %p\n", ep_priv);

	return FI_SUCCESS;

err_eq_write:
err_write:
err_smsg_init:
	_gnix_mbox_free(ep_priv->vc->smsg_mbox);
	ep_priv->vc->smsg_mbox = NULL;
err_mbox_alloc:
	_gnix_vc_destroy(ep_priv->vc);
	ep_priv->vc = NULL;
err_unlock:
	COND_RELEASE(ep_priv->requires_lock, &ep_priv->vc_lock);

	return ret;
}
Example #23
0
/* Process a connection response on an FI_EP_MSG. */
static int __gnix_ep_connresp(struct gnix_fid_ep *ep,
			      struct gnix_pep_sock_connresp *resp)
{
	int ret = FI_SUCCESS;
	struct fi_eq_cm_entry *eq_entry;
	int eqe_size;

	switch (resp->cmd) {
	case GNIX_PEP_SOCK_RESP_ACCEPT:
		ep->vc->peer_caps = resp->peer_caps;
		ep->vc->peer_id = resp->vc_id;

		/* Initialize the GNI connection. */
		ret = _gnix_vc_smsg_init(ep->vc, resp->vc_id,
					 &resp->vc_mbox_attr,
					 &resp->cq_irq_mdh);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				  "_gnix_vc_smsg_init returned %s\n",
				  fi_strerror(-ret));
			return ret;
		}

		ep->vc->conn_state = GNIX_VC_CONNECTED;
		ep->conn_state = GNIX_EP_CONNECTED;

		/* Notify user that this side is connected. */
		eq_entry = (struct fi_eq_cm_entry *)resp->eqe_buf;
		eq_entry->fid = &ep->ep_fid.fid;

		eqe_size = sizeof(*eq_entry) + resp->cm_data_len;
		ret = fi_eq_write(&ep->eq->eq_fid, FI_CONNECTED, eq_entry,
				  eqe_size, 0);
		if (ret != eqe_size) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				  "fi_eq_write failed, err: %d\n", ret);
			return ret;
		}

		GNIX_DEBUG(FI_LOG_EP_CTRL, "Received conn accept: %p\n", ep);

		break;
	case GNIX_PEP_SOCK_RESP_REJECT:
		/* Undo the connect and generate a failure EQE. */
		close(ep->conn_fd);
		ep->conn_fd = -1;

		_gnix_mbox_free(ep->vc->smsg_mbox);
		ep->vc->smsg_mbox = NULL;

		_gnix_vc_destroy(ep->vc);
		ep->vc = NULL;

		ep->conn_state = GNIX_EP_UNCONNECTED;

		/* Generate EQE. */
		eq_entry = (struct fi_eq_cm_entry *)resp->eqe_buf;
		eq_entry->fid = &ep->ep_fid.fid;

		eq_entry = (struct fi_eq_cm_entry *)resp->eqe_buf;
		ret = _gnix_eq_write_error(ep->eq, &ep->ep_fid.fid, NULL, 0,
					   FI_ECONNREFUSED, FI_ECONNREFUSED,
					   &eq_entry->data, resp->cm_data_len);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				  "fi_eq_write failed, err: %d\n", ret);
			return ret;
		}

		GNIX_DEBUG(FI_LOG_EP_CTRL, "Conn rejected: %p\n", ep);

		break;
	default:
		GNIX_INFO(FI_LOG_EP_CTRL, "Invalid response command: %d\n",
			  resp->cmd);
		return -FI_EINVAL;
	}

	return FI_SUCCESS;
}