예제 #1
0
Test(dg_allocation,  dgram_wc_post_exchg)
{
	int ret = 0;
	struct gnix_cm_nic *cm_nic;
	struct gnix_datagram *dgram_wc, *dgram_bnd;

	ep_priv = container_of(ep, struct gnix_fid_ep, ep_fid);
	cm_nic = ep_priv->cm_nic;
	cr_assert((cm_nic != NULL), "cm_nic NULL");

	cr_assert((cm_nic->dgram_hndl != NULL), "cm_nic dgram_hndl NULL");

	ret = _gnix_dgram_alloc(cm_nic->dgram_hndl, GNIX_DGRAM_WC,
				&dgram_wc);
	cr_assert(!ret, "_gnix_dgram_alloc wc");

	dgram_wc->callback_fn = dgram_callback_fn;
	ret = _gnix_dgram_wc_post(dgram_wc);
	cr_assert((ret == 0), "_gnix_dgram_alloc wc");

	ret = _gnix_dgram_alloc(cm_nic->dgram_hndl, GNIX_DGRAM_BND,
				&dgram_bnd);
	cr_assert((ret == 0), "_gnix_dgram_alloc bnd");

	dgram_bnd->target_addr = cm_nic->my_name.gnix_addr;

	local_address = cm_nic->my_name.gnix_addr;

	dgram_bnd->callback_fn = dgram_callback_fn;
	ret = _gnix_dgram_bnd_post(dgram_bnd);
	cr_assert(ret == 0);

	/*
	 * progress auto, don't need to do anything
	 */
	while (dgram_match != 1) {
		ret = _gnix_cm_nic_progress(cm_nic);
		cr_assert(ret == 0);
		pthread_yield();
	}

	ret = _gnix_dgram_free(dgram_bnd);
	cr_assert(!ret, "_gnix_dgram_free bnd");

	ret = _gnix_dgram_free(dgram_wc);
	cr_assert(!ret, "_gnix_dgram_free wc");

}
예제 #2
0
Test(dg_allocation, dgram_alloc_bnd)
{
	int ret = 0, i;
	struct gnix_cm_nic *cm_nic;
	struct gnix_datagram **dgram_ptr;
	struct gnix_fid_fabric *fab_priv;

	ep_priv = container_of(ep, struct gnix_fid_ep, ep_fid);
	cm_nic = ep_priv->cm_nic;
	cr_assert((cm_nic != NULL), "cm_nic NULL");

	cr_assert((cm_nic->dgram_hndl != NULL), "cm_nic dgram_hndl NULL");

	fab_priv = container_of(fab, struct gnix_fid_fabric, fab_fid);

	dgram_ptr = calloc(fab_priv->n_bnd_dgrams,
			   sizeof(struct gnix_datagram *));
	cr_assert((dgram_ptr != NULL), "calloc failed");

	for (i = 0; i < fab_priv->n_bnd_dgrams; i++) {
		ret = _gnix_dgram_alloc(cm_nic->dgram_hndl, GNIX_DGRAM_BND,
					&dgram_ptr[i]);
		cr_assert(!ret, "_gnix_dgram_alloc bnd");
	}

	for (i = 0; i < fab_priv->n_wc_dgrams; i++) {
		ret = _gnix_dgram_free(dgram_ptr[i]);
		cr_assert(!ret, "_gnix_dgram_free bnd");
	}

	free(dgram_ptr);
}
예제 #3
0
Test(dg_allocation, dgram_pack_unpack)
{
	int ret = 0;
	ssize_t len;
	struct gnix_cm_nic *cm_nic;
	struct gnix_datagram *dgram_ptr;
	char in_buf[] = "0xdeadbeef";
	char out_buf[GNI_DATAGRAM_MAXSIZE];

	ep_priv = container_of(ep, struct gnix_fid_ep, ep_fid);
	cm_nic = ep_priv->cm_nic;
	cr_assert((cm_nic != NULL), "cm_nic NULL");

	cr_assert((cm_nic->dgram_hndl != NULL), "cm_nic dgram_hndl NULL");

	ret = _gnix_dgram_alloc(cm_nic->dgram_hndl, GNIX_DGRAM_BND,
				&dgram_ptr);
	cr_assert(!ret, "_gnix_dgram_alloc bnd");

	/*
	 * check pack/unpack for GNIX_DGRAM_IN_BUF
	 */

	len = _gnix_dgram_pack_buf(dgram_ptr, GNIX_DGRAM_IN_BUF,
					in_buf, sizeof(in_buf));
	cr_assert(len > 0);
	cr_assert_eq(len, (ssize_t)sizeof(in_buf));

	len = _gnix_dgram_unpack_buf(dgram_ptr, GNIX_DGRAM_IN_BUF,
					out_buf, sizeof(in_buf));
	cr_assert(len > 0);
	cr_assert_eq(len, (ssize_t)sizeof(in_buf));

	cr_assert_eq(0, strcmp(in_buf, out_buf));

	/*
	 * check pack/unpack for GNIX_DGRAM_OUT_BUF
	 */

	len = _gnix_dgram_pack_buf(dgram_ptr, GNIX_DGRAM_OUT_BUF,
					in_buf, sizeof(in_buf));
	cr_assert(len > 0);
	cr_assert_eq(len, (ssize_t)sizeof(in_buf));

	memset(out_buf, 0, sizeof(out_buf));

	len = _gnix_dgram_unpack_buf(dgram_ptr, GNIX_DGRAM_OUT_BUF,
					out_buf, sizeof(in_buf));
	cr_assert(len > 0);
	cr_assert_eq(len, (ssize_t)sizeof(in_buf));

	cr_assert_eq(0, strcmp(in_buf, out_buf));

	ret = _gnix_dgram_free(dgram_ptr);
	cr_assert(!ret, "_gnix_dgram_free bnd");

}
예제 #4
0
Test(dg_allocation, dgram_alloc_wc_alt)
{
	int ret = 0, i;
	struct gnix_cm_nic *cm_nic;
	struct gnix_datagram *dgram_ptr;
	struct gnix_fid_fabric *fab_priv;

	ep_priv = container_of(ep, struct gnix_fid_ep, ep_fid);
	cm_nic = ep_priv->cm_nic;
	cr_assert((cm_nic != NULL), "cm_nic NULL");

	cr_assert((cm_nic->dgram_hndl != NULL), "cm_nic dgram_hndl NULL");

	fab_priv = container_of(fab, struct gnix_fid_fabric, fab_fid);

	for (i = 0; i < fab_priv->n_wc_dgrams; i++) {
		ret = _gnix_dgram_alloc(cm_nic->dgram_hndl, GNIX_DGRAM_WC,
					&dgram_ptr);
		cr_assert(!ret, "_gnix_dgram_alloc wc");
		ret = _gnix_dgram_free(dgram_ptr);
		cr_assert(!ret, "_gnix_dgram_free wc");
	}
}
예제 #5
0
/* Destroy an unconnected VC.  More Support is needed to shutdown and destroy
 * an active VC. */
int _gnix_vc_destroy(struct gnix_vc *vc)
{
	int ret = FI_SUCCESS;
	struct gnix_nic *nic = NULL;
	gni_return_t status;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if (vc->ep == NULL) {
		GNIX_WARN(FI_LOG_EP_CTRL, "ep null\n");
		return -FI_EINVAL;
	}

	nic = vc->ep->nic;
	if (nic == NULL) {
		GNIX_WARN(FI_LOG_EP_CTRL, "ep nic null for vc %p\n", vc);
		return -FI_EINVAL;
	}

	/*
	 * move vc state to terminating
	 */

	vc->conn_state = GNIX_VC_CONN_TERMINATING;

	/*
	 * try to unbind the gni_ep if non-NULL.
	 * If there are SMSG or PostFMA/RDMA outstanding
	 * wait here for them to complete
	 */

	if (vc->gni_ep != NULL) {
		while (status == GNI_RC_NOT_DONE) {

			fastlock_acquire(&nic->lock);
			status = GNI_EpUnbind(vc->gni_ep);
			fastlock_release(&nic->lock);

			if ((status != GNI_RC_NOT_DONE) &&
				(status != GNI_RC_SUCCESS)) {
				GNIX_WARN(FI_LOG_EP_CTRL,
					"GNI_EpUnBind returned %s\n",
					  gni_err_str[status]);
				break;
			}

			if (status == GNI_RC_NOT_DONE)
				_gnix_nic_progress(nic);
		}
		fastlock_acquire(&nic->lock);
		status = GNI_EpDestroy(vc->gni_ep);
		fastlock_release(&nic->lock);
		if (status != GNI_RC_SUCCESS)
			GNIX_WARN(FI_LOG_EP_CTRL,
				"GNI_EpDestroy returned %s\n",
				  gni_err_str[status]);
	}

	/*
	 * if the vc is in a nic's work queue, remove it
	 */
	__gnix_vc_cancel(vc);

	/*
	 * We may eventually want to check the state of the VC, if we
	 * implement true VC shutdown.

	if ((vc->conn_state != GNIX_VC_CONN_NONE)
		&& (vc->conn_state != GNIX_VC_CONN_TERMINATED)) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			      "vc conn state  %d\n",
			       vc->conn_state);
		GNIX_WARN(FI_LOG_EP_CTRL, "vc conn state error\n");
		return -FI_EBUSY;
	}
	 */

	/*
	 * if send_q not empty, return -FI_EBUSY
	 * Note for FI_EP_MSG type eps, this behavior
	 * may not be correct for handling fi_shutdown.
	 */

	if (!slist_empty(&vc->tx_queue)) {
		GNIX_WARN(FI_LOG_EP_CTRL, "vc sendqueue not empty\n");
		return -FI_EBUSY;
	}

	fastlock_destroy(&vc->tx_queue_lock);

	if (vc->smsg_mbox != NULL) {
		ret = _gnix_mbox_free(vc->smsg_mbox);
		if (ret != FI_SUCCESS)
			GNIX_WARN(FI_LOG_EP_CTRL,
			      "_gnix_mbox_free returned %s\n",
			      fi_strerror(-ret));
		vc->smsg_mbox = NULL;
	}

	if (vc->dgram != NULL) {
		ret = _gnix_dgram_free(vc->dgram);
		if (ret != FI_SUCCESS)
			GNIX_WARN(FI_LOG_EP_CTRL,
			      "_gnix_dgram_free returned %s\n",
			      fi_strerror(-ret));
		vc->dgram = NULL;
	}

	ret = _gnix_nic_free_rem_id(nic, vc->vc_id);
	if (ret != FI_SUCCESS)
		GNIX_WARN(FI_LOG_EP_CTRL,
		      "__gnix_vc_free_id returned %s\n",
		      fi_strerror(-ret));

	_gnix_free_bitmap(&vc->flags);

	free(vc);

	return ret;
}
예제 #6
0
static int __process_datagram(struct gnix_datagram *dgram,
				 struct gnix_address peer_address,
				 gni_post_state_t state)
{
	int ret = FI_SUCCESS;
	struct gnix_cm_nic *cm_nic = NULL;
	uint8_t in_tag = 0, out_tag = 0;
	char rcv_buf[GNIX_CM_NIC_MAX_MSG_SIZE];

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	cm_nic = (struct gnix_cm_nic *)dgram->cache;
	if (cm_nic == NULL) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			"process_datagram, null cache\n");
		goto err;
	}

	if (state != GNI_POST_COMPLETED) {
		ret = __process_dgram_w_error(cm_nic,
					      dgram,
					      peer_address,
					      state);
		GNIX_WARN(FI_LOG_EP_CTRL,
			"process_datagram bad post state %d\n", state);
		goto err;
	}

	__dgram_get_in_tag(dgram, &in_tag);
	if ((in_tag != GNIX_CM_NIC_BND_TAG) &&
		(in_tag != GNIX_CM_NIC_WC_TAG)) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			"datagram with unknown in tag %d\n", in_tag);
		goto err;
	}

	 __dgram_unpack_out_tag(dgram, &out_tag);
	if ((out_tag != GNIX_CM_NIC_BND_TAG) &&
		(out_tag != GNIX_CM_NIC_WC_TAG)) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			"datagram with unknown out tag %d\n", out_tag);
		goto err;
	}

	/*
	 * if out buf actually has data, call consumer's
	 * receive callback
	 */

	if (out_tag == GNIX_CM_NIC_BND_TAG) {
		_gnix_dgram_unpack_buf(dgram,
					GNIX_DGRAM_OUT_BUF,
					rcv_buf,
					GNIX_CM_NIC_MAX_MSG_SIZE);
		ret = cm_nic->rcv_cb_fn(cm_nic,
					rcv_buf,
					peer_address);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				"cm_nic->rcv_cb_fn returned %s\n",
				fi_strerror(-ret));
			goto err;
		}

		ret = _gnix_cm_nic_progress(cm_nic);
		if (ret != FI_SUCCESS)
			GNIX_WARN(FI_LOG_EP_CTRL,
				  "_gnix_cm_nic_progress returned %s\n",
				  fi_strerror(-ret));
	}

	/*
	 * if we are processing a WC datagram, repost, otherwise
	 * just put back on the freelist.
	 */
	if (in_tag == GNIX_CM_NIC_WC_TAG) {
		dgram->callback_fn = __process_datagram;
		dgram->cache = cm_nic;
		 __dgram_set_tag(dgram, in_tag);
		ret = _gnix_dgram_wc_post(dgram);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				"_gnix_dgram_wc_post returned %s\n",
				fi_strerror(-ret));
			goto err;
		}
	} else {
		ret  = _gnix_dgram_free(dgram);
		if (ret != FI_SUCCESS)
			GNIX_WARN(FI_LOG_EP_CTRL,
				"_gnix_dgram_free returned %s\n",
				fi_strerror(-ret));
	}

	return ret;

err:
	if (in_tag == GNIX_CM_NIC_BND_TAG)
		_gnix_dgram_free(dgram);
	return ret;
}
예제 #7
0
int _gnix_cm_nic_enable(struct gnix_cm_nic *cm_nic)
{
	int i, ret = FI_SUCCESS;
	struct gnix_fid_fabric *fabric;
	struct gnix_datagram *dg_ptr;
	uint8_t tag = GNIX_CM_NIC_WC_TAG;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if (cm_nic == NULL)
		return -FI_EINVAL;

	if (cm_nic->domain == NULL) {
		GNIX_FATAL(FI_LOG_EP_CTRL, "domain is NULL\n");
	}

	if (cm_nic->domain->fabric == NULL) {
		GNIX_FATAL(FI_LOG_EP_CTRL, "fabric is NULL\n");
	}

	fabric = cm_nic->domain->fabric;

	assert(cm_nic->dgram_hndl != NULL);

	for (i = 0; i < fabric->n_wc_dgrams; i++) {
		ret = _gnix_dgram_alloc(cm_nic->dgram_hndl, GNIX_DGRAM_WC,
					&dg_ptr);

		/*
 		 * wildcards may already be posted to the cm_nic,
 		 * so just break if -FI_EAGAIN is returned by
 		 * _gnix_dgram_alloc
 		 */

		if (ret == -FI_EAGAIN) {
			ret = FI_SUCCESS;
			break;
		}

		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
			     "_gnix_dgram_alloc call returned %d\n", ret);
				goto err;
		}

		dg_ptr->callback_fn = __process_datagram;
		dg_ptr->cache = cm_nic;
		 __dgram_set_tag(dg_ptr, tag);

		ret = _gnix_dgram_wc_post(dg_ptr);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				"_gnix_dgram_wc_post returned %d\n", ret);
			_gnix_dgram_free(dg_ptr);
			goto err;
		}
	}

	/*
	 * TODO: better cleanup in error case
	 */
err:
	return ret;
}
예제 #8
0
int _gnix_cm_nic_send(struct gnix_cm_nic *cm_nic,
		      char *sbuf, size_t len,
		      struct gnix_address target_addr)
{
	int ret = FI_SUCCESS;
	struct gnix_datagram *dgram = NULL;
	ssize_t  __attribute__((unused)) plen;
	uint8_t tag;
	struct gnix_work_req *work_req;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if ((cm_nic == NULL) || (sbuf == NULL))
		return -FI_EINVAL;

	if (len > GNI_DATAGRAM_MAXSIZE)
		return -FI_ENOSPC;

	ret = _gnix_dgram_alloc(cm_nic->dgram_hndl,
				GNIX_DGRAM_BND,
				&dgram);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			  "_gnix_dgram_alloc returned %s\n",
			  fi_strerror(-ret));
		goto exit;
	}

	dgram->target_addr = target_addr;
	dgram->callback_fn = __process_datagram;
	dgram->cache = cm_nic;

	tag = GNIX_CM_NIC_BND_TAG;
	 __dgram_set_tag(dgram, tag);

	plen = _gnix_dgram_pack_buf(dgram, GNIX_DGRAM_IN_BUF,
				   sbuf, len);
	assert (plen == len);

	/* If connecting with the same CM NIC, skip datagram exchange.  The
	 * caller could be holding an endpoint lock, so schedule connection
	 * completion for later. */
	if (GNIX_ADDR_EQUAL(target_addr, cm_nic->my_name.gnix_addr)) {
		char tmp_buf[GNIX_CM_NIC_MAX_MSG_SIZE];

		/* Pack output buffer with input data. */
		_gnix_dgram_unpack_buf(dgram, GNIX_DGRAM_IN_BUF, tmp_buf,
				       GNIX_CM_NIC_MAX_MSG_SIZE);
		_gnix_dgram_pack_buf(dgram, GNIX_DGRAM_OUT_BUF, tmp_buf,
				       GNIX_CM_NIC_MAX_MSG_SIZE);

		work_req = calloc(1, sizeof(*work_req));
		if (work_req == NULL) {
			_gnix_dgram_free(dgram);
			return -FI_ENOMEM;
		}

		work_req->progress_fn = __gnix_cm_nic_intra_progress_fn;
		work_req->data = dgram;
		work_req->completer_fn = NULL;

		fastlock_acquire(&cm_nic->wq_lock);
		dlist_insert_before(&work_req->list, &cm_nic->cm_nic_wq);
		fastlock_release(&cm_nic->wq_lock);

		GNIX_INFO(FI_LOG_EP_CTRL, "Initiated intra-CM NIC connect\n");
	} else {
		ret = _gnix_dgram_bnd_post(dgram);
		if (ret == -FI_EBUSY) {
			ret = -FI_EAGAIN;
			_gnix_dgram_free(dgram);
		}
	}

exit:
	return ret;
}