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; }
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; } }
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; }
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; }
/******************************************************************************* * 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; }
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); }
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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }