std::tuple lookupAddrLikeNccl()

in tensorpipe/transport/uv/utility.cc [138:215]


std::tuple<Error, std::string> lookupAddrLikeNccl(
    optional<sa_family_t> familyFilter) {
  int rv;
  InterfaceAddresses addresses;
  int count;
  std::tie(rv, addresses, count) = getInterfaceAddresses();
  if (rv < 0) {
    return std::make_tuple(TP_CREATE_ERROR(UVError, rv), std::string());
  }

  // Libuv already only returns the interfaces that are up and running, whose
  // address is not null, and whose family is IPv4 or IPv6.

  // NCCL prioritizes the interfaces whose name starts with "ib" (for IP over
  // InfiniBand?), and deprioritizes those that start with "docker" or "lo".
  optional<std::string> withIbPrefix;
  optional<std::string> withoutPrefix;
  optional<std::string> withDockerPrefix;
  optional<std::string> withLoPrefix;

  for (auto i = 0; i < count; i++) {
    const uv_interface_address_t& interface = addresses[i];
    const struct sockaddr* sockaddr =
        reinterpret_cast<const struct sockaddr*>(&interface.address);

    // NCCL also seems to ignore any IPv6 loopback address.
    if (sockaddr->sa_family == AF_INET6 && interface.is_internal) {
      continue;
    }

    if (familyFilter.has_value() &&
        sockaddr->sa_family != familyFilter.value()) {
      continue;
    }

    std::string addr;
    switch (sockaddr->sa_family) {
      case AF_INET:
        addr = Sockaddr(sockaddr, sizeof(struct sockaddr_in)).str();
        break;
      case AF_INET6:
        addr = Sockaddr(sockaddr, sizeof(struct sockaddr_in6)).str();
        break;
    }

    std::string name = interface.name;
    if (name.find("ib") == 0) {
      if (!withIbPrefix.has_value()) {
        withIbPrefix = std::move(addr);
      }
    } else if (name.find("docker") == 0) {
      if (!withDockerPrefix.has_value()) {
        withDockerPrefix = std::move(addr);
      }
    } else if (name.find("lo") == 0) {
      if (!withLoPrefix.has_value()) {
        withLoPrefix = std::move(addr);
      }
    } else {
      if (!withoutPrefix.has_value()) {
        withoutPrefix = std::move(addr);
      }
    }
  }

  if (withIbPrefix.has_value()) {
    return std::make_tuple(Error::kSuccess, std::move(withIbPrefix).value());
  } else if (withoutPrefix.has_value()) {
    return std::make_tuple(Error::kSuccess, std::move(withoutPrefix).value());
  } else if (withDockerPrefix.has_value()) {
    return std::make_tuple(
        Error::kSuccess, std::move(withDockerPrefix).value());
  } else if (withLoPrefix.has_value()) {
    return std::make_tuple(Error::kSuccess, std::move(withLoPrefix).value());
  }

  return std::make_tuple(TP_CREATE_ERROR(NoAddrFoundError), std::string());
}