예제 #1
0
static int
__gnix_fab_ops_set_val(struct fid *fid, fab_ops_val_t t, void *val)
{
	int v;

	assert(val);

	if (fid->fclass != FI_CLASS_FABRIC) {
		GNIX_WARN(FI_LOG_FABRIC, "Invalid fabric\n");
		return -FI_EINVAL;
	}

	switch (t) {
	case GNI_WAIT_THREAD_SLEEP:
		v = *(uint32_t *) val;
		gnix_wait_thread_sleep_time = v;
		break;
	case GNI_DEFAULT_USER_REGISTRATION_LIMIT:
		v = *(uint32_t *) val;
		if (v > GNIX_MAX_SCALABLE_REGISTRATIONS) {
			GNIX_ERR(FI_LOG_FABRIC,
				"User specified an invalid user registration "
				"limit, requested=%d maximum=%d\n",
				v, GNIX_MAX_SCALABLE_REGISTRATIONS);
			return -FI_EINVAL;
		}
		gnix_default_user_registration_limit = v;
		break;
	case GNI_DEFAULT_PROV_REGISTRATION_LIMIT:
		v = *(uint32_t *) val;
		if (v > GNIX_MAX_SCALABLE_REGISTRATIONS) {
			GNIX_ERR(FI_LOG_FABRIC,
				"User specified an invalid prov registration "
				"limit, requested=%d maximum=%d\n",
				v, GNIX_MAX_SCALABLE_REGISTRATIONS);
			return -FI_EINVAL;
		}
		gnix_default_prov_registration_limit = v;
		break;
	default:
		GNIX_WARN(FI_LOG_FABRIC, ("Invalid fab_ops_val\n"));
		return -FI_EINVAL;
	}

	return FI_SUCCESS;
}
예제 #2
0
void _gnix_signal_wait_obj(struct fid_wait *wait)
{
	static char msg = 'g';
	size_t len = sizeof(msg);
	struct gnix_fid_wait *wait_priv;

	wait_priv = container_of(wait, struct gnix_fid_wait, wait);

	switch (wait_priv->type) {
	case FI_WAIT_FD:
		if (write(wait_priv->fd[WAIT_WRITE], &msg, len) != len)
			GNIX_ERR(WAIT_SUB, "failed to signal wait object.\n");
		break;
	case FI_WAIT_MUTEX_COND:
		pthread_cond_signal(&wait_priv->cond);
		break;
	default:
		GNIX_ERR(WAIT_SUB,
			 "error signaling wait object: type: %d not supported.\n",
			 wait_priv->type);
		return;
	}
}
예제 #3
0
static int gnix_init_wait_obj(struct gnix_fid_wait *wait, enum fi_wait_obj type)
{
	long flags = 0;

	GNIX_TRACE(WAIT_SUB, "\n");

	wait->type = type;

	switch (type) {
	case FI_WAIT_FD:
		if (socketpair(AF_LOCAL, SOCK_STREAM, 0, wait->fd))
			goto err;

		fcntl(wait->fd[WAIT_READ], F_GETFL, &flags);
		if (fcntl(wait->fd[WAIT_READ], F_SETFL, flags | O_NONBLOCK))
			goto cleanup;
		break;
	case FI_WAIT_MUTEX_COND:
		pthread_mutex_init(&wait->mutex, NULL);
		pthread_cond_init(&wait->cond, NULL);
		break;
	default:
		GNIX_ERR(WAIT_SUB, "Invalid wait type: %d\n",
			 type);
		return -FI_EINVAL;
	}

	return FI_SUCCESS;

cleanup:
	close(wait->fd[WAIT_READ]);
	close(wait->fd[WAIT_WRITE]);
err:
	GNIX_ERR(WAIT_SUB, "%s\n", strerror(errno));
	return -FI_EOTHER;
}
예제 #4
0
int gnix_wait_open(struct fid_fabric *fabric, struct fi_wait_attr *attr,
		   struct fid_wait **waitset)
{
	struct gnix_fid_fabric *fab_priv;
	struct gnix_fid_wait *wait_priv;
	int ret = FI_SUCCESS;

	GNIX_TRACE(WAIT_SUB, "\n");

	ret = gnix_verify_wait_attr(attr);
	if (ret)
		goto err;

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

	wait_priv = calloc(1, sizeof(*wait_priv));
	if (!wait_priv) {
		GNIX_ERR(WAIT_SUB,
			 "failed to allocate memory for wait set.\n");
		ret = -FI_ENOMEM;
		goto err;
	}

	ret = gnix_init_wait_obj(wait_priv, attr->wait_obj);
	if (ret)
		goto cleanup;

	slist_init(&wait_priv->set);

	wait_priv->wait.fid.fclass = FI_CLASS_WAIT;
	wait_priv->wait.fid.ops = &gnix_fi_ops;
	wait_priv->wait.ops = &gnix_wait_ops;

	wait_priv->fabric = fab_priv;

	_gnix_ref_get(fab_priv);
	*waitset = &wait_priv->wait;

	return ret;

cleanup:
	free(wait_priv);
err:
	return ret;
}
예제 #5
0
/*******************************************************************************
 * Exposed helper functions.
 ******************************************************************************/
int _gnix_wait_set_add(struct fid_wait *wait, struct fid *wait_obj)
{
	struct gnix_fid_wait *wait_priv;
	struct gnix_wait_entry *wait_entry;

	GNIX_TRACE(WAIT_SUB, "\n");

	wait_entry = calloc(1, sizeof(*wait_entry));
	if (!wait_entry) {
		GNIX_ERR(WAIT_SUB,
			 "failed to allocate memory for wait entry.\n");
		return -FI_ENOMEM;
	}

	wait_priv = container_of(wait, struct gnix_fid_wait, wait.fid);

	wait_entry->wait_obj = wait_obj;

	gnix_slist_insert_tail(&wait_entry->entry, &wait_priv->set);

	return FI_SUCCESS;
}
예제 #6
0
static void __gnix_amo_fr_complete(struct gnix_fab_req *req)
{
	int rc;

	if (req->flags & FI_LOCAL_MR) {
		GNIX_INFO(FI_LOG_EP_DATA, "freeing auto-reg MR: %p\n",
			  req->amo.loc_md);
		rc = fi_close(&req->amo.loc_md->mr_fid.fid);
		if (rc != FI_SUCCESS) {
			GNIX_ERR(FI_LOG_DOMAIN,
				"failed to deregister auto-registered region, "
				"rc=%d\n", rc);
		}

		req->flags &= ~FI_LOCAL_MR;
	}

	ofi_atomic_dec32(&req->vc->outstanding_tx_reqs);

	/* Schedule VC TX queue in case the VC is 'fenced'. */
	_gnix_vc_tx_schedule(req->vc);

	_gnix_fr_free(req->vc->ep, req);
}
예제 #7
0
int _gnix_get_wait_obj(struct fid_wait *wait, void *arg)
{
	struct fi_mutex_cond mutex_cond;
	struct gnix_fid_wait *wait_priv;
	size_t copy_size;
	const void *src;

	GNIX_TRACE(WAIT_SUB, "\n");

	if (!wait || !arg)
		return -FI_EINVAL;

	wait_priv = container_of(wait, struct gnix_fid_wait, wait);

	switch (wait_priv->type) {
	case FI_WAIT_FD:
		copy_size = sizeof(wait_priv->fd[WAIT_READ]);
		src = &wait_priv->fd[WAIT_READ];
		break;
	case FI_WAIT_MUTEX_COND:
		mutex_cond.mutex = &wait_priv->mutex;
		mutex_cond.cond = &wait_priv->cond;

		copy_size = sizeof(mutex_cond);
		src = &mutex_cond;
		break;
	default:
		GNIX_ERR(WAIT_SUB, "wait type: %d not supported.\n",
			 wait_priv->type);
		return -FI_EINVAL;
	}

	memcpy(arg, src, copy_size);

	return FI_SUCCESS;
}
예제 #8
0
int gnix_ep_open(struct fid_domain *domain, struct fi_info *info,
		 struct fid_ep **ep, void *context)
{
	int ret = FI_SUCCESS;
	struct gnix_fid_domain *domain_priv;
	struct gnix_fid_ep *ep_priv;
	gnix_hashtable_attr_t gnix_ht_attr;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	if ((domain == NULL) || (info == NULL) || (ep == NULL))
		return -FI_EINVAL;

	if (info->ep_attr->type != FI_EP_RDM)
		return -FI_ENOSYS;

	domain_priv = container_of(domain, struct gnix_fid_domain, domain_fid);

	ep_priv = calloc(1, sizeof *ep_priv);
	if (!ep_priv)
		return -FI_ENOMEM;

	ep_priv->ep_fid.fid.fclass = FI_CLASS_EP;
	ep_priv->ep_fid.fid.context = context;

	ep_priv->ep_fid.fid.ops = &gnix_ep_fi_ops;
	ep_priv->ep_fid.ops = &gnix_ep_ops;
	ep_priv->domain = domain_priv;
	ep_priv->type = info->ep_attr->type;

	fastlock_init(&ep_priv->vc_list_lock);
	dlist_init(&ep_priv->wc_vc_list);
	atomic_initialize(&ep_priv->active_fab_reqs, 0);
	atomic_initialize(&ep_priv->ref_cnt, 0);

	fastlock_init(&ep_priv->recv_queue_lock);
	slist_init(&ep_priv->unexp_recv_queue);
	slist_init(&ep_priv->posted_recv_queue);
	slist_init(&ep_priv->pending_recv_comp_queue);

	if (info->tx_attr)
		ep_priv->op_flags = info->tx_attr->op_flags;
	if (info->rx_attr)
		ep_priv->op_flags |= info->rx_attr->op_flags;

	ret = __fr_freelist_init(ep_priv);
	if (ret != FI_SUCCESS) {
		GNIX_ERR(FI_LOG_EP_CTRL,
			 "Error allocating gnix_fab_req freelist (%s)",
			 fi_strerror(-ret));
		goto err1;
	}

	ep_priv->ep_fid.msg = &gnix_ep_msg_ops;
	ep_priv->ep_fid.rma = &gnix_ep_rma_ops;
	ep_priv->ep_fid.tagged = &gnix_ep_tagged_ops;
	ep_priv->ep_fid.atomic = NULL;

	ep_priv->ep_fid.cm = &gnix_cm_ops;

	/*
	 * TODO, initialize vc hash table
	 */
	if (ep_priv->type == FI_EP_RDM) {
		ret = _gnix_cm_nic_alloc(domain_priv,
					 &ep_priv->cm_nic);
		if (ret != FI_SUCCESS)
			goto err;

		gnix_ht_attr.ht_initial_size = domain_priv->params.ct_init_size;
		gnix_ht_attr.ht_maximum_size = domain_priv->params.ct_max_size;
		gnix_ht_attr.ht_increase_step = domain_priv->params.ct_step;
		gnix_ht_attr.ht_increase_type = GNIX_HT_INCREASE_MULT;
		gnix_ht_attr.ht_collision_thresh = 500;
		gnix_ht_attr.ht_hash_seed = 0xdeadbeefbeefdead;
		gnix_ht_attr.ht_internal_locking = 1;

		ep_priv->vc_ht = calloc(1, sizeof(struct gnix_hashtable));
		if (ep_priv->vc_ht == NULL)
			goto err;
		ret = _gnix_ht_init(ep_priv->vc_ht, &gnix_ht_attr);
		if (ret != FI_SUCCESS) {
			GNIX_WARN(FI_LOG_EP_CTRL,
				    "gnix_ht_init call returned %d\n",
				     ret);
			goto err;
		}

	} else {
		ep_priv->cm_nic = NULL;
		ep_priv->vc = NULL;
	}

	ep_priv->progress_fn = NULL;
	ep_priv->rx_progress_fn = NULL;

	ret = gnix_nic_alloc(domain_priv, &ep_priv->nic);
	if (ret != FI_SUCCESS) {
		GNIX_WARN(FI_LOG_EP_CTRL,
			    "_gnix_nic_alloc call returned %d\n",
			     ret);
		goto err;
	}

	/*
	 * if smsg callbacks not present hook them up now
	 */

	if (ep_priv->nic->smsg_callbacks == NULL)
		ep_priv->nic->smsg_callbacks = gnix_ep_smsg_callbacks;

	atomic_inc(&domain_priv->ref_cnt);
	*ep = &ep_priv->ep_fid;
	return ret;

err1:
	__fr_freelist_destroy(ep_priv);
err:
	if (ep_priv->vc_ht != NULL) {
		_gnix_ht_destroy(ep_priv->vc_ht); /* may not be initialized but
						     okay */
		free(ep_priv->vc_ht);
		ep_priv->vc_ht = NULL;
	}
	if (ep_priv->cm_nic != NULL)
		ret = _gnix_cm_nic_free(ep_priv->cm_nic);
	free(ep_priv);
	return ret;

}
예제 #9
0
static int __gnix_auth_key_set_val(
	uint8_t *auth_key,
	size_t auth_key_size,
	gnix_auth_key_opt_t opt,
	void *val)
{
	struct gnix_auth_key *info;
	int v;
	int ret;

	if (!val)
		return -FI_EINVAL;

	info = _gnix_auth_key_lookup(auth_key, auth_key_size);

	if (!info) {
		ret = __gnix_auth_key_initialize(auth_key, auth_key_size, NULL);
		assert(ret == FI_SUCCESS);

		info = _gnix_auth_key_lookup(auth_key, auth_key_size);
		assert(info);
	}

	/* if the limits have already been set, and the user is
	 * trying to modify it, kick it back */
	if (opt == GNIX_USER_KEY_LIMIT || opt == GNIX_PROV_KEY_LIMIT) {
		fastlock_acquire(&info->lock);
		if (info->enabled) {
			fastlock_release(&info->lock);
			GNIX_INFO(FI_LOG_FABRIC, "authorization key already "
				"enabled and cannot be modified\n");
			return -FI_EAGAIN;
		}
	}

	switch (opt) {
	case GNIX_USER_KEY_LIMIT:
		v = *(int *) val;
		if (v >= GNIX_MAX_SCALABLE_REGISTRATIONS) {
			GNIX_ERR(FI_LOG_FABRIC,
				"User is requesting more registrations than is present on node\n");
			ret = -FI_EINVAL;
		} else
			info->attr.user_key_limit = v;
		fastlock_release(&info->lock);
		break;
	case GNIX_PROV_KEY_LIMIT:
		v = *(int *) val;
		if (v >= GNIX_MAX_SCALABLE_REGISTRATIONS) {
			GNIX_ERR(FI_LOG_FABRIC,
				"User is requesting more registrations than is present on node\n");
			ret = -FI_EINVAL;
		}
		info->attr.prov_key_limit = v;
		fastlock_release(&info->lock);
		break;
	case GNIX_TOTAL_KEYS_NEEDED:
		GNIX_WARN(FI_LOG_FABRIC,
			"GNIX_TOTAL_KEYS_NEEDED is not a definable value.\n");
		return -FI_EOPNOTSUPP;
	default:
		GNIX_WARN(FI_LOG_FABRIC, ("Invalid fab_ops_val\n"));
		return -FI_EINVAL;
	}

	return ret;
}
예제 #10
0
int _gnix_cm_nic_alloc(struct gnix_fid_domain *domain,
			struct gnix_cm_nic **cm_nic_ptr)
{
	int ret = FI_SUCCESS;
	struct gnix_cm_nic *cm_nic = NULL;
	uint32_t device_addr, cdm_id;
	gni_return_t status;

	GNIX_TRACE(FI_LOG_EP_CTRL, "\n");

	*cm_nic_ptr = NULL;

	cm_nic = (struct gnix_cm_nic *)calloc(1, sizeof(*cm_nic));
	if (cm_nic == NULL) {
		ret = -FI_ENOMEM;
		goto err;
	}

	ret = _gnix_get_new_cdm_id(domain, &cdm_id);
	if (ret != FI_SUCCESS)
		goto err;

	GNIX_INFO(FI_LOG_EP_CTRL, "creating cm_nic for %u/0x%x/%u\n",
		      domain->ptag, domain->cookie, cdm_id);

	status = GNI_CdmCreate(cdm_id,
			       domain->ptag,
			       domain->cookie,
			       gnix_cdm_modes,
			       &cm_nic->gni_cdm_hndl);
	if (status != GNI_RC_SUCCESS) {
		GNIX_ERR(FI_LOG_EP_CTRL, "GNI_CdmCreate returned %s\n",
			       gni_err_str[status]);
		ret = gnixu_to_fi_errno(status);
		goto err;
	}

	/*
	 * Okay, now go for the attach
	 */
	status = GNI_CdmAttach(cm_nic->gni_cdm_hndl, 0, &device_addr,
			       &cm_nic->gni_nic_hndl);
	if (status != GNI_RC_SUCCESS) {
		GNIX_ERR(FI_LOG_EP_CTRL, "GNI_CdmAttach returned %s\n",
		       gni_err_str[status]);
		ret = gnixu_to_fi_errno(status);
		goto err;
	}

	cm_nic->cdm_id = cdm_id;
	cm_nic->ptag = domain->ptag;
	cm_nic->cookie = domain->cookie;
	cm_nic->device_addr = device_addr;
	cm_nic->control_progress = domain->control_progress;
	fastlock_init(&cm_nic->lock);
	fastlock_init(&cm_nic->wq_lock);
	list_head_init(&cm_nic->cm_nic_wq);

	/*
	 * prep the cm nic's dgram component
	 */
	ret = _gnix_dgram_hndl_alloc(domain->fabric,
				     cm_nic,
				     domain->control_progress,
				     &cm_nic->dgram_hndl);
	if (ret != FI_SUCCESS)
		goto err;

	*cm_nic_ptr = cm_nic;
	return ret;

err:
	if (cm_nic->dgram_hndl)
		_gnix_dgram_hndl_free(cm_nic->dgram_hndl);

	if (cm_nic->gni_cdm_hndl)
		GNI_CdmDestroy(cm_nic->gni_cdm_hndl);

	if (cm_nic != NULL)
		free(cm_nic);

	return ret;
}
예제 #11
0
static int gnix_getinfo(uint32_t version, const char *node, const char *service,
			uint64_t flags, struct fi_info *hints,
			struct fi_info **info)
{
	int ret = 0;
	int ep_type_unspec = 1;
	uint64_t mode = GNIX_FAB_MODES;
	uint64_t caps = GNIX_EP_RDM_CAPS;
	struct fi_info *gnix_info = NULL;
	struct gnix_ep_name *dest_addr = NULL;
	struct gnix_ep_name *src_addr = NULL;
	struct gnix_ep_name *addr = NULL;
	char *str_src_addr = NULL;
	char *str_dest_addr = NULL;

	/*
	 * the code below for resolving a node/service to what
	 * will be a gnix_ep_name address is not fully implemented,
	 * but put a place holder in place
	 */
	if (node) {
		addr = malloc(sizeof(*addr));
		if (!addr) {
			goto err;
		}

		/* resolve node/service to gnix_ep_name */
		ret = gnix_resolve_name(node, service, flags, addr);
		if (ret) {
			goto err;
		}

		if (flags & FI_SOURCE) {
			/* resolved address is the local address */
			src_addr = addr;
			if (hints && hints->dest_addr)
				dest_addr = hints->dest_addr;
		} else {
			/* resolved address is a peer */
			dest_addr = addr;
			if (hints && hints->src_addr)
				src_addr = hints->src_addr;
		}
	}

	if (src_addr)
		GNIX_INFO(FI_LOG_FABRIC, "src_pe: 0x%x src_port: 0x%lx\n",
			  src_addr->gnix_addr.device_addr,
			  src_addr->gnix_addr.cdm_id);
	if (dest_addr)
		GNIX_INFO(FI_LOG_FABRIC, "dest_pe: 0x%x dest_port: 0x%lx\n",
			  dest_addr->gnix_addr.device_addr,
			  dest_addr->gnix_addr.cdm_id);

	/*
	 * fill in the gnix_info struct
	 */
	gnix_info = fi_allocinfo();
	if (gnix_info == NULL) {
		goto err;
	}

	/*
	 * Set the default values
	 */
	gnix_info->tx_attr->op_flags = 0;
	gnix_info->rx_attr->op_flags = 0;
	gnix_info->ep_attr->type = FI_EP_RDM;
	gnix_info->ep_attr->protocol = FI_PROTO_GNI;
	gnix_info->ep_attr->max_msg_size = GNIX_MAX_MSG_SIZE;
	/* TODO: need to work on this */
	gnix_info->ep_attr->mem_tag_format = 0x0;
	gnix_info->ep_attr->tx_ctx_cnt = 1;
	gnix_info->ep_attr->rx_ctx_cnt = 1;

	gnix_info->domain_attr->threading = FI_THREAD_SAFE;
	gnix_info->domain_attr->control_progress = FI_PROGRESS_AUTO;
	gnix_info->domain_attr->data_progress = FI_PROGRESS_AUTO;
	gnix_info->domain_attr->av_type = FI_AV_UNSPEC;
	gnix_info->domain_attr->tx_ctx_cnt = gnix_max_nics_per_ptag;
	/* only one aries per node */
	gnix_info->domain_attr->name = strdup(gnix_dom_name);
	gnix_info->domain_attr->cq_data_size = sizeof(uint64_t);
	gnix_info->domain_attr->mr_mode = FI_MR_BASIC;
	gnix_info->domain_attr->resource_mgmt = FI_RM_ENABLED;

	gnix_info->next = NULL;
	gnix_info->addr_format = FI_ADDR_GNI;
	gnix_info->src_addrlen = 0;
	gnix_info->dest_addrlen = 0;
	gnix_info->src_addr = NULL;
	gnix_info->dest_addr = NULL;
	if (src_addr) {
		str_src_addr = malloc(GNIX_AV_MAX_STR_ADDR_LEN);
		if (!str_src_addr) {
			goto err;
		}
		gnix_info->src_addrlen = GNIX_AV_MAX_STR_ADDR_LEN;
		gnix_av_straddr(NULL, (void *) src_addr, (char *) str_src_addr,
			 &gnix_info->src_addrlen);
		gnix_info->src_addr = str_src_addr;
	}
	if (dest_addr) {
		str_dest_addr = malloc(GNIX_AV_MAX_STR_ADDR_LEN);
		if (!str_dest_addr) {
			goto err;
		}
		gnix_info->dest_addrlen = GNIX_AV_MAX_STR_ADDR_LEN;
		gnix_av_straddr(NULL, (void *) addr, (char *) str_dest_addr,
			 &gnix_info->dest_addrlen);
		gnix_info->dest_addr = str_dest_addr;
	}
	/* prov_name gets filled in by fi_getinfo from the gnix_prov struct */
	/* let's consider gni copyrighted :) */

	gnix_info->tx_attr->msg_order = FI_ORDER_SAS;
	gnix_info->tx_attr->comp_order = FI_ORDER_NONE;
	gnix_info->tx_attr->size = GNIX_TX_SIZE_DEFAULT;
	gnix_info->tx_attr->iov_limit = 1;
	gnix_info->tx_attr->inject_size = GNIX_INJECT_SIZE;
	gnix_info->tx_attr->rma_iov_limit = 1;
	gnix_info->rx_attr->msg_order = FI_ORDER_SAS;
	gnix_info->rx_attr->comp_order = FI_ORDER_NONE;
	gnix_info->rx_attr->size = GNIX_RX_SIZE_DEFAULT;
	gnix_info->rx_attr->iov_limit = 1;

	if (hints) {
		if (hints->ep_attr) {
			/*
			 * support FI_EP_RDM, FI_EP_DGRAM endpoint types
			 */
			switch (hints->ep_attr->type) {
			case FI_EP_UNSPEC:
				break;
			case FI_EP_RDM:
			case FI_EP_DGRAM:
				gnix_info->ep_attr->type = hints->ep_attr->type;
				ep_type_unspec = 0;
				break;
			default:
				goto err;
			}

			/*
			 * only support FI_PROTO_GNI protocol
			 */
			switch (hints->ep_attr->protocol) {
			case FI_PROTO_UNSPEC:
			case FI_PROTO_GNI:
				break;
			default:
				goto err;
			}

			if (hints->ep_attr->tx_ctx_cnt > 1) {
				goto err;
			}

			if (hints->ep_attr->rx_ctx_cnt > 1) {
				goto err;
			}

			if (hints->ep_attr->max_msg_size > GNIX_MAX_MSG_SIZE) {
				goto err;
			}
		}

		/*
		 * check the mode field
		 */
		if (hints->mode) {
			if ((hints->mode & GNIX_FAB_MODES) != GNIX_FAB_MODES) {
				goto err;
			}
			mode = hints->mode & ~GNIX_FAB_MODES_CLEAR;
		}

		if ((hints->caps & GNIX_EP_RDM_CAPS) != hints->caps) {
			goto err;
		}

		if (hints->caps) {
			caps = hints->caps & GNIX_EP_RDM_CAPS;
		}

		if (hints->tx_attr) {
			if ((hints->tx_attr->op_flags & GNIX_EP_OP_FLAGS) !=
				hints->tx_attr->op_flags) {
				goto err;
			}
			if (hints->tx_attr->inject_size > GNIX_INJECT_SIZE) {
				goto err;
			}

			gnix_info->tx_attr->op_flags =
				hints->tx_attr->op_flags & GNIX_EP_OP_FLAGS;
		}

		if (hints->rx_attr) {
			if ((hints->rx_attr->op_flags & GNIX_EP_OP_FLAGS) !=
					hints->rx_attr->op_flags) {
				goto err;
			}

			gnix_info->rx_attr->op_flags =
				hints->rx_attr->op_flags & GNIX_EP_OP_FLAGS;
		}

		if (hints->fabric_attr && hints->fabric_attr->name &&
		    strncmp(hints->fabric_attr->name, gnix_fab_name,
			    strlen(gnix_fab_name))) {
			goto err;
		}

		if (hints->domain_attr) {
			if (hints->domain_attr->name &&
			    strncmp(hints->domain_attr->name, gnix_dom_name,
				    strlen(gnix_dom_name))) {
				goto err;
			}

			if (hints->domain_attr->control_progress !=
				FI_PROGRESS_UNSPEC)
				gnix_info->domain_attr->control_progress =
					hints->domain_attr->control_progress;

			if (hints->domain_attr->data_progress !=
				FI_PROGRESS_UNSPEC)
				gnix_info->domain_attr->data_progress =
					hints->domain_attr->data_progress;

			switch (hints->domain_attr->mr_mode) {
			case FI_MR_UNSPEC:
			case FI_MR_BASIC:
				gnix_info->domain_attr->mr_mode =
					hints->domain_attr->mr_mode;
				break;
			case FI_MR_SCALABLE:
				goto err;
			}

			ret = fi_check_domain_attr(&gnix_prov,
						   gnix_info->domain_attr,
						   hints->domain_attr,
						   FI_MATCH_EXACT);
			if (ret)
				goto err;
		}
	}

	/*
	 * Set the values based on hints
	 */

	switch (gnix_info->ep_attr->type) {
	case FI_EP_RDM:
	case FI_EP_DGRAM:
		gnix_info->caps = caps | GNIX_EP_RDM_SEC_CAPS;
		break;
	case FI_EP_MSG:
		gnix_info->caps = caps | GNIX_EP_MSG_SEC_CAPS;
		break;
	default:
		GNIX_ERR(FI_LOG_FABRIC, "unknown ep type %d",
			 gnix_info->ep_attr->type);
		break;
	}

	gnix_info->mode = mode;
	gnix_info->fabric_attr->name = strdup(gnix_fab_name);
	gnix_info->tx_attr->caps = gnix_info->caps;
	gnix_info->tx_attr->mode = gnix_info->mode;
	gnix_info->rx_attr->caps = gnix_info->caps;
	gnix_info->rx_attr->mode = gnix_info->mode;

	if (ep_type_unspec) {
		struct fi_info *dg_info = fi_dupinfo(gnix_info);

		if (!dg_info) {
			GNIX_WARN(FI_LOG_FABRIC, "cannot copy info\n");
			goto err;
		}

		dg_info->ep_attr->type = FI_EP_DGRAM;
		gnix_info->next = dg_info;
	}

	*info = gnix_info;

	return 0;
err:
	if (gnix_info) {
		if (gnix_info->tx_attr) free(gnix_info->tx_attr);
		if (gnix_info->rx_attr) free(gnix_info->rx_attr);
		if (gnix_info->ep_attr) free(gnix_info->ep_attr);
		if (gnix_info->domain_attr) free(gnix_info->domain_attr);
		if (gnix_info->fabric_attr) free(gnix_info->fabric_attr);
		free(gnix_info);
	}

	if (addr) {
		free(addr);
	}

	if (str_src_addr) {
		free(str_src_addr);
	}

	if (str_dest_addr) {
		free(str_dest_addr);
	}

	/*
	 *  for the getinfo method, we need to return -FI_ENODATA  otherwise
	 *  the fi_getinfo call will make an early exit without querying
	 *  other providers which may be avaialble.
	 */
	return -FI_ENODATA;
}
예제 #12
0
/*
 * gnix_resolve_name: given a node hint and a valid pointer to a gnix_ep_name
 * will resolve the gnix specific address of node and fill the provided
 * gnix_ep_name pointer with the information.
 *
 * node (IN) : Node name being resolved to gnix specific address
 * resolved_addr (IN/OUT) : Pointer that must be provided to contain the
 *	resolved address.
 *
 * TODO: consider a use for service.
 */
int gnix_resolve_name(IN const char *node, IN const char *service,
		      INOUT struct gnix_ep_name *resolved_addr)
{
	int sock = -1;
	uint32_t pe = -1;
	uint32_t cpu_id = -1;
	struct addrinfo *result = NULL;
	struct addrinfo *rp = NULL;

	struct ifreq ifr = {{{0}}};

	struct sockaddr_in *sa = NULL;
	struct sockaddr_in *sin = NULL;

	int ret = FI_SUCCESS;
	gni_return_t status = GNI_RC_SUCCESS;

	struct addrinfo hints = {
		.ai_family = AF_INET,
		.ai_socktype = SOCK_DGRAM,
		.ai_flags = AI_CANONNAME
	};

	if (!resolved_addr) {
		GNIX_ERR(FI_LOG_FABRIC,
			 "Resolved_addr must be a valid pointer.\n");
		ret = -FI_EINVAL;
		goto err;
	}

	sock = socket(AF_INET, SOCK_DGRAM, 0);

	if (sock == -1) {
		GNIX_ERR(FI_LOG_FABRIC, "Socket creation failed: %s\n",
			 strerror(errno));
		ret = -FI_EIO;
		goto err;
	}

	/* Get the address for the ipogif0 interface */
	ifr.ifr_addr.sa_family = AF_INET;
	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", "ipogif0");

	ret = ioctl(sock, SIOCGIFADDR, &ifr);
	if (ret == -1) {
		GNIX_ERR(FI_LOG_FABRIC,
			 "Failed to get address for ipogif0: %s\n",
			 strerror(errno));
		ret = -FI_EIO;
		goto sock_cleanup;
	}

	sin = (struct sockaddr_in *) &ifr.ifr_addr;

	ret = getaddrinfo(node, "domain", &hints, &result);
	if (ret != 0) {
		GNIX_ERR(FI_LOG_FABRIC,
			 "Failed to get address for node provided: %s\n",
			 strerror(errno));
		ret = -FI_EINVAL;
		goto sock_cleanup;
	}

	for (rp = result; rp != NULL; rp = rp->ai_next) {
		assert(rp->ai_addr->sa_family == AF_INET);
		sa = (struct sockaddr_in *) rp->ai_addr;

		/*
		 * If we are trying to resolve localhost then use
		 * CdmGetNicAddress.
		 */
		if (sa->sin_addr.s_addr == sin->sin_addr.s_addr) {
			status = GNI_CdmGetNicAddress(0, &pe, &cpu_id);
			if(status == GNI_RC_SUCCESS) {
				break;
			} else {
				GNIX_ERR(FI_LOG_FABRIC,
					 "Unable to get NIC address.");
				ret = gnixu_to_fi_errno(status);
				goto sock_cleanup;
			}
		} else {
			ret =
			    gnixu_get_pe_from_ip(inet_ntoa(sa->sin_addr), &pe);
			if (ret == 0) {
				break;
			}
		}
	}

	/*
	 * Make sure address is valid.
	 */
	if (pe == -1) {
		GNIX_ERR(FI_LOG_FABRIC,
			 "Unable to acquire valid address for node %s\n",
			 node);
		ret = -FI_EADDRNOTAVAIL;
		goto sock_cleanup;
	}

	/*
	 * Fill the INOUT parameter resolved_addr with the address information
	 * acquired for the provided node parameter.
	 */
	memset(resolved_addr, 0, sizeof(struct gnix_ep_name));

	resolved_addr->gnix_addr.device_addr = pe;
	/* TODO: have to write a nameserver to get this info */
	resolved_addr->gnix_addr.cdm_id = 0;
	/* TODO: likely depend on service? */
	resolved_addr->name_type = 0;
sock_cleanup:
	if(close(sock) == -1) {
		GNIX_ERR(FI_LOG_FABRIC, "Unable to close socket: %s\n",
			 strerror(errno));
	}
err:
	if (result != NULL) {
		freeaddrinfo(result);
	}
	return ret;
}
예제 #13
0
static inline void *__gnix_generic_register(
		struct gnix_fid_domain *domain,
		struct gnix_fid_mem_desc *md,
		void *address,
		size_t length,
		gni_cq_handle_t dst_cq_hndl,
		int flags,
		int vmdh_index)
{
	struct gnix_nic *nic;
	gni_return_t grc = GNI_RC_SUCCESS;
	int rc;

	pthread_mutex_lock(&gnix_nic_list_lock);

	/* If the nic list is empty, create a nic */
	if (unlikely((dlist_empty(&gnix_nic_list_ptag[domain->ptag])))) {
		/* release the lock because we are not checking the list after
			this point. Additionally, gnix_nic_alloc takes the 
			lock to add the nic. */
		pthread_mutex_unlock(&gnix_nic_list_lock);

		rc = gnix_nic_alloc(domain, NULL, &nic);
		if (rc) {
			GNIX_INFO(FI_LOG_MR,
				  "could not allocate nic to do mr_reg,"
				  " ret=%i\n", rc);
			return NULL;
		}
	} else {
		nic = dlist_first_entry(&gnix_nic_list_ptag[domain->ptag], 
			struct gnix_nic, ptag_nic_list);
		if (unlikely(nic == NULL)) {
			GNIX_ERR(FI_LOG_MR, "Failed to find nic on "
				"ptag list\n");
			pthread_mutex_unlock(&gnix_nic_list_lock);
			return NULL;
		}
		_gnix_ref_get(nic);	
		pthread_mutex_unlock(&gnix_nic_list_lock);
        }

	COND_ACQUIRE(nic->requires_lock, &nic->lock);
	grc = GNI_MemRegister(nic->gni_nic_hndl, (uint64_t) address,
				  length,	dst_cq_hndl, flags,
				  vmdh_index, &md->mem_hndl);
	COND_RELEASE(nic->requires_lock, &nic->lock);

	if (unlikely(grc != GNI_RC_SUCCESS)) {
		GNIX_INFO(FI_LOG_MR, "failed to register memory with uGNI, "
			  "ret=%s\n", gni_err_str[grc]);
		_gnix_ref_put(nic);

		return NULL;
	}

	/* set up the mem desc */
	md->nic = nic;
	md->domain = domain;

	/* take references on domain */
	_gnix_ref_get(md->domain);

	return md;
}