Beispiel #1
0
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;
}
Beispiel #2
0
/* Check all things related to a device. Make sure it's okay, the source address
 * matches the requested address, the destination is reachable from the device,
 * the device fabric name matches the requested fabric name, and the device
 * domain name matches the requested domain name.
 *
 * @param version Libfabric API version used to verify the domain / fabric name.
 * @param hints   Hints passed to fi_getinfo.
 * @param src     Source address being requested.
 * @param dest    Destination address to communicate with.
 * @param dep     usNIC device entry being checked.
 *
 * @return true on success, false on failure. For debug logging can be enabled
 *         to see why a device was disqualified.
 */
static bool usdf_check_device(uint32_t version, const struct fi_info *hints,
			      void *src, void *dest,
			      struct usdf_dev_entry *dep)
{
	char dest_str[INET_ADDRSTRLEN];
	char src_str[INET_ADDRSTRLEN];
	char dev_str[INET_ADDRSTRLEN];
	struct usd_device_attrs *dap;
	struct sockaddr_in *sin;
	int reachable;
	int ret;

	reachable = -1;
	dap = &dep->ue_dattr;

	/* Skip the device if it has problems. */
	if (!dep->ue_dev_ok) {
		USDF_WARN_SYS(FABRIC, "skipping %s/%s device not ok\n",
			      dap->uda_devname, dap->uda_ifname);
		return false;
	}

	/* If the given source address is not INADDR_ANY, compare against the
	 * device.
	 */
	if (src) {
		sin = usdf_format_to_sin(hints, src);
		if (sin->sin_addr.s_addr != INADDR_ANY) {
			if (sin->sin_addr.s_addr != dap->uda_ipaddr_be) {
				inet_ntop(AF_INET, &sin->sin_addr.s_addr,
					  src_str, sizeof(src_str));
				inet_ntop(AF_INET, &dap->uda_ipaddr_be,
					  dev_str, sizeof(dev_str));
				USDF_WARN_SYS(FABRIC,
					      "src addr<%s> != dev addr<%s>\n",
					      src_str, dev_str);
				goto fail;
			}
		}

		usdf_free_sin_if_needed(hints, sin);
	}

	/* Check that the given destination address is reachable from the
	 * interface.
	 */
	if (dest) {
		sin = usdf_format_to_sin(hints, dest);
		if (sin->sin_addr.s_addr != INADDR_ANY) {
			ret = usdf_get_distance(dap, sin->sin_addr.s_addr,
						&reachable);
			if (ret) {
				inet_ntop(AF_INET,
					  &sin->sin_addr.s_addr, dest_str,
					  sizeof(dest_str));
				USDF_WARN_SYS(FABRIC,
					      "get_distance failed @ %s\n",
					      dest_str);
				goto fail;
			}
		}

		if (reachable == -1) {
			inet_ntop(AF_INET, &sin->sin_addr.s_addr, dest_str,
				  sizeof(dest_str));
			USDF_WARN_SYS(FABRIC,
				      "dest %s unreachable from %s/%s, skipping\n",
				      dest_str, dap->uda_devname,
				      dap->uda_ifname);
			goto fail;
		}

		usdf_free_sin_if_needed(hints, sin);
	}

	/* Checks that the fabric name is correct for the given interface. The
	 * fabric name contains the CIDR notation for the interface.
	 */
	if (hints && hints->fabric_attr && hints->fabric_attr->name) {
		if (!usdf_fabric_checkname(version, dap,
					  hints->fabric_attr->name))
			return false;
	}

	/* Check that the domain name is correct for the given interface. The
	 * domain name is the device name.
	 */
	if (hints && hints->domain_attr && hints->domain_attr->name) {
		if (!usdf_domain_checkname(version, dap,
					   hints->domain_attr->name))
			return false;
	}

	return true;

fail:
	usdf_free_sin_if_needed(hints, sin);

	return false;
}