static int usdf_getinfo(uint32_t version, const char *node, const char *service, uint64_t flags, struct fi_info *hints, struct fi_info **info) { struct usdf_usnic_info *dp; struct usdf_dev_entry *dep; struct usd_device_attrs *dap; struct fi_info *fi_first; struct fi_info *fi_last; struct addrinfo *ai; struct sockaddr_in *src; struct sockaddr_in *dest; enum fi_ep_type ep_type; int metric; int d; int ret; USDF_TRACE("\n"); fi_first = NULL; fi_last = NULL; ai = NULL; src = NULL; dest = NULL; /* * Get and cache usNIC device info */ if (__usdf_devinfo == NULL) { ret = usdf_get_devinfo(); if (ret != 0) { USDF_WARN("failed to usdf_get_devinfo, ret=%d (%s)\n", ret, fi_strerror(-ret)); if (ret == -FI_ENODEV) ret = -FI_ENODATA; goto fail; } } dp = __usdf_devinfo; if (node != NULL || service != NULL) { ret = getaddrinfo(node, service, NULL, &ai); if (ret != 0) { USDF_DBG("getaddrinfo failed, likely bad node/service specified (%s:%s)\n", node, service); ret = -errno; goto fail; } if (flags & FI_SOURCE) { src = (struct sockaddr_in *)ai->ai_addr; } else { dest = (struct sockaddr_in *)ai->ai_addr; } } if (hints != NULL) { if (dest == NULL && hints->dest_addr != NULL) { dest = hints->dest_addr; } if (src == NULL && hints->src_addr != NULL) { src = hints->src_addr; } } for (d = 0; d < dp->uu_num_devs; ++d) { dep = &dp->uu_info[d]; dap = &dep->ue_dattr; /* skip this device if it has some problem */ if (!dep->ue_dev_ok) { USDF_DBG("skipping %s/%s\n", dap->uda_devname, dap->uda_ifname); continue; } /* See if dest is reachable from this device */ if (dest != NULL && dest->sin_addr.s_addr != INADDR_ANY) { ret = usdf_get_distance(dap, dest->sin_addr.s_addr, &metric); if (ret != 0) { goto fail; } if (metric == -1) { USDF_DBG("dest %s unreachable from %s/%s, skipping\n", inet_ntoa(dest->sin_addr), dap->uda_devname, dap->uda_ifname); continue; } } /* Does this device match requested attributes? */ if (hints != NULL) { ret = usdf_validate_hints(hints, dap); if (ret != 0) { USDF_DBG("hints do not match for %s/%s, skipping\n", dap->uda_devname, dap->uda_ifname); continue; } ep_type = hints->ep_attr ? hints->ep_attr->type : FI_EP_UNSPEC; } else { ep_type = FI_EP_UNSPEC; } if (ep_type == FI_EP_DGRAM || ep_type == FI_EP_UNSPEC) { ret = usdf_fill_info_dgram(version, hints, src, dest, dap, &fi_first, &fi_last); if (ret != 0 && ret != -FI_ENODATA) { goto fail; } } if (ep_type == FI_EP_MSG || ep_type == FI_EP_UNSPEC) { ret = usdf_fill_info_msg(hints, src, dest, dap, &fi_first, &fi_last); if (ret != 0 && ret != -FI_ENODATA) { goto fail; } } if (ep_type == FI_EP_RDM || ep_type == FI_EP_UNSPEC) { ret = usdf_fill_info_rdm(hints, src, dest, dap, &fi_first, &fi_last); if (ret != 0 && ret != -FI_ENODATA) { goto fail; } } } if (fi_first != NULL) { *info = fi_first; ret = 0; } else { ret = -FI_ENODATA; } fail: if (ret != 0) { fi_freeinfo(fi_first); } if (ai != NULL) { freeaddrinfo(ai); } if (ret != 0) { USDF_INFO("returning %d (%s)\n", ret, fi_strerror(-ret)); } return ret; }
static int usdf_getinfo(uint32_t version, const char *node, const char *service, uint64_t flags, const struct fi_info *hints, struct fi_info **info) { struct usdf_usnic_info *dp; struct usdf_dev_entry *dep; struct usd_device_attrs *dap; struct fi_info *fi_first; struct fi_info *fi_last; struct addrinfo *ai; void *src; void *dest; enum fi_ep_type ep_type; int d; int ret; USDF_TRACE("\n"); fi_first = NULL; fi_last = NULL; ai = NULL; src = NULL; dest = NULL; /* * Get and cache usNIC device info */ if (__usdf_devinfo == NULL) { ret = usdf_get_devinfo(); if (ret != 0) { USDF_WARN("failed to usdf_get_devinfo, ret=%d (%s)\n", ret, fi_strerror(-ret)); if (ret == -FI_ENODEV) ret = -FI_ENODATA; goto fail; } } dp = __usdf_devinfo; /* Check the hints up front and fail if they're invalid. */ if (hints) { ret = usdf_validate_hints(version, hints); if (ret) { USDF_WARN_SYS(FABRIC, "hints failed to validate\n"); goto fail; } } /* Get the src and dest if user specified. */ ret = usdf_handle_node_and_service(node, service, flags, &src, &dest, hints, &ai); if (ret) { USDF_WARN_SYS(FABRIC, "failed to handle node and service.\n"); goto fail; } if (hints != NULL) { if (dest == NULL && hints->dest_addr != NULL) dest = hints->dest_addr; if (src == NULL && hints->src_addr != NULL) src = hints->src_addr; } for (d = 0; d < dp->uu_num_devs; ++d) { dep = &dp->uu_info[d]; dap = &dep->ue_dattr; /* If the device has an issue or the hints don't match the * device information, then skip. */ if (!usdf_check_device(version, hints, src, dest, dep)) continue; if (hints && hints->ep_attr) ep_type = hints->ep_attr->type; else ep_type = FI_EP_UNSPEC; if (ep_type == FI_EP_DGRAM || ep_type == FI_EP_UNSPEC) { ret = usdf_fill_info_dgram(version, hints, src, dest, dap, &fi_first, &fi_last); if (ret != 0 && ret != -FI_ENODATA) { goto fail; } } if (ep_type == FI_EP_MSG || ep_type == FI_EP_UNSPEC) { ret = usdf_fill_info_msg(version, hints, src, dest, dap, &fi_first, &fi_last); if (ret != 0 && ret != -FI_ENODATA) { goto fail; } } if (ep_type == FI_EP_RDM || ep_type == FI_EP_UNSPEC) { ret = usdf_fill_info_rdm(version, hints, src, dest, dap, &fi_first, &fi_last); if (ret != 0 && ret != -FI_ENODATA) { goto fail; } } } if (fi_first != NULL) { *info = fi_first; ret = 0; } else { ret = -FI_ENODATA; } fail: if (ai) freeaddrinfo(ai); if (ret != 0) { fi_freeinfo(fi_first); USDF_INFO("returning %d (%s)\n", ret, fi_strerror(-ret)); } return ret; }