in prov/gni/src/gnix_fabric.c [447:682]
static int _gnix_ep_getinfo(enum fi_ep_type ep_type, uint32_t version,
const char *node, const char *service,
uint64_t flags, const struct fi_info *hints,
struct fi_info **info)
{
uint64_t mode = GNIX_FAB_MODES;
struct fi_info *gnix_info = NULL;
int ret = -FI_ENODATA;
int mr_mode;
GNIX_TRACE(FI_LOG_FABRIC, "\n");
if ((hints && hints->ep_attr) &&
(hints->ep_attr->type != FI_EP_UNSPEC &&
hints->ep_attr->type != ep_type)) {
return -FI_ENODATA;
}
gnix_info = _gnix_allocinfo();
if (!gnix_info)
return -FI_ENOMEM;
gnix_info->ep_attr->type = ep_type;
if (hints) {
/* TODO: Add version check when we decide on how to do it */
if (hints->addr_format == FI_ADDR_STR) {
gnix_info->addr_format = FI_ADDR_STR;
}
if (hints->ep_attr) {
/* 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 > GNIX_SEP_MAX_CNT) &&
(hints->ep_attr->tx_ctx_cnt !=
FI_SHARED_CONTEXT)) {
goto err;
}
if (hints->ep_attr->rx_ctx_cnt > GNIX_SEP_MAX_CNT)
goto err;
if (hints->ep_attr->tx_ctx_cnt)
gnix_info->ep_attr->tx_ctx_cnt =
hints->ep_attr->tx_ctx_cnt;
if (hints->ep_attr->rx_ctx_cnt)
gnix_info->ep_attr->rx_ctx_cnt =
hints->ep_attr->rx_ctx_cnt;
if (hints->ep_attr->max_msg_size > GNIX_MAX_MSG_SIZE)
goto err;
}
GNIX_DEBUG(FI_LOG_FABRIC, "Passed EP attributes check\n");
/*
* 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 (FI_VERSION_LT(version, FI_VERSION(1, 5))) {
mode = hints->mode & ~FI_NOTIFY_FLAGS_ONLY;
}
}
GNIX_DEBUG(FI_LOG_FABRIC, "Passed mode check\n");
if (hints->caps) {
/* The provider must support all requested
* capabilities. */
if ((hints->caps & GNIX_EP_CAPS_FULL) != hints->caps)
goto err;
}
GNIX_DEBUG(FI_LOG_FABRIC, "Passed caps check gnix_info->caps = 0x%016lx\n",
gnix_info->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;
}
GNIX_DEBUG(FI_LOG_FABRIC, "Passed TX attributes check\n");
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;
}
GNIX_DEBUG(FI_LOG_FABRIC, "Passed fabric name check\n");
if (hints->domain_attr) {
mr_mode = hints->domain_attr->mr_mode;
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;
/* If basic registration isn't being requested,
require FI_MR_MMU_NOTIFY */
if (!(hints->domain_attr->mr_mode &
(FI_MR_BASIC | FI_MR_ALLOCATED)))
gnix_info->domain_attr->mr_mode |= FI_MR_MMU_NOTIFY;
if (ofi_check_mr_mode(&gnix_prov, version,
gnix_info->domain_attr->mr_mode,
hints) != FI_SUCCESS) {
GNIX_INFO(FI_LOG_DOMAIN,
"failed ofi_check_mr_mode, "
"ret=%d\n", ret);
goto err;
}
if (FI_VERSION_LT(version, FI_VERSION(1, 5))) {
switch (mr_mode) {
case FI_MR_UNSPEC:
case FI_MR_BASIC:
mr_mode = FI_MR_BASIC;
break;
default:
GNIX_DEBUG(FI_LOG_FABRIC,
"unsupported mr_mode selected, "
"ret=%d\n", ret);
goto err;
}
} else {
/* define the mode we return to the user
* prefer basic until scalable
* has more testing time */
if (mr_mode & FI_MR_BASIC)
mr_mode = OFI_MR_BASIC_MAP;
else if ((mr_mode & GNIX_MR_BASIC_REQ) ==
GNIX_MR_BASIC_REQ)
mr_mode &= GNIX_MR_BASIC_BITS;
else
mr_mode &= GNIX_MR_SCALABLE_BITS;
}
gnix_info->domain_attr->mr_mode = mr_mode;
switch (hints->domain_attr->threading) {
case FI_THREAD_COMPLETION:
gnix_info->domain_attr->threading =
hints->domain_attr->threading;
break;
default:
break;
}
if (hints->domain_attr->caps) {
if (hints->domain_attr->caps & ~GNIX_DOM_CAPS) {
GNIX_WARN(FI_LOG_FABRIC,
"Invalid domain caps\n");
goto err;
}
gnix_info->domain_attr->caps =
hints->domain_attr->caps;
}
}
}
ret = __gnix_getinfo_resolve_node(node, service, flags, hints,
gnix_info);
if (ret != FI_SUCCESS)
goto err;
ofi_alter_info(gnix_info, hints, version);
GNIX_DEBUG(FI_LOG_FABRIC, "Passed the domain attributes check\n");
/* The provider may silently enable secondary
* capabilities that do not introduce any overhead. */
if (hints && hints->caps)
gnix_info->caps = hints->caps | GNIX_EP_SEC_CAPS;
else
gnix_info->caps = GNIX_EP_CAPS_FULL | GNIX_EP_SEC_CAPS;
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;
*info = gnix_info;
GNIX_DEBUG(FI_LOG_FABRIC, "Returning EP type: %s\n",
fi_tostr(&ep_type, FI_TYPE_EP_TYPE));
return FI_SUCCESS;
err:
fi_freeinfo(gnix_info);
return ret;
}