void TcpInfo::initCcInfoFromFd()

in folly/net/TcpInfo.cpp [484:568]


void TcpInfo::initCcInfoFromFd(
    const NetworkSocket& fd,
    TcpInfo& wrappedInfo,
    netops::Dispatcher& netopsDispatcher) {
#ifndef FOLLY_HAVE_TCP_CC_INFO
  return; // platform not supported
#elif defined(__linux__)
  if (NetworkSocket() == fd) {
    return;
  }

  // identification strings returned by Linux Kernel for TCP_CONGESTION
  static constexpr auto kLinuxCcNameStrReno = "reno";
  static constexpr auto kLinuxCcNameStrCubic = "cubic";
  static constexpr auto kLinuxCcNameStrBic = "bic";
  static constexpr auto kLinuxCcNameStrBbr = "bbr";
  static constexpr auto kLinuxCcNameStrVegas = "vegas";
  static constexpr auto kLinuxCcNameStrDctcp = "dctcp";
  static constexpr auto kLinuxCcNameStrDctcpReno = "dctcp_reno";
  static constexpr auto kLinuxCcNameStrDctcpCubic = "dctcp_cubic";

  std::array<char, (unsigned int)kLinuxTcpCaNameMax> tcpCongestion{{0}};
  socklen_t optlen = tcpCongestion.size();
  if (netopsDispatcher.getsockopt(
          fd, IPPROTO_TCP, TCP_CONGESTION, tcpCongestion.data(), &optlen) < 0) {
    VLOG(4) << "Error calling getsockopt(): " << folly::errnoStr(errno);
    return;
  }

  {
    auto ccStr = std::string(tcpCongestion.data());
    if (ccStr == kLinuxCcNameStrReno) {
      wrappedInfo.maybeCcEnum = CongestionControlName::RENO;
    } else if (ccStr == kLinuxCcNameStrCubic) {
      wrappedInfo.maybeCcEnum = CongestionControlName::CUBIC;
    } else if (ccStr == kLinuxCcNameStrBic) {
      wrappedInfo.maybeCcEnum = CongestionControlName::BIC;
    } else if (ccStr == kLinuxCcNameStrBbr) {
      wrappedInfo.maybeCcEnum = CongestionControlName::BBR;
    } else if (ccStr == kLinuxCcNameStrVegas) {
      wrappedInfo.maybeCcEnum = CongestionControlName::VEGAS;
    } else if (ccStr == kLinuxCcNameStrDctcp) {
      wrappedInfo.maybeCcEnum = CongestionControlName::DCTCP;
    } else if (ccStr == kLinuxCcNameStrDctcpReno) {
      wrappedInfo.maybeCcEnum = CongestionControlName::DCTCP_RENO;
    } else if (ccStr == kLinuxCcNameStrDctcpCubic) {
      wrappedInfo.maybeCcEnum = CongestionControlName::DCTCP_CUBIC;
    } else {
      wrappedInfo.maybeCcEnum = CongestionControlName::UNKNOWN;
    }
    wrappedInfo.maybeCcNameRaw.emplace(std::move(ccStr));
  }

  // get TCP_CC_INFO if supported for the congestion control algorithm
  switch (wrappedInfo.maybeCcEnum.value_or(CongestionControlName::UNKNOWN)) {
    case CongestionControlName::UNKNOWN:
    case CongestionControlName::RENO:
    case CongestionControlName::CUBIC:
    case CongestionControlName::BIC:
      return; // no TCP_CC_INFO for these congestion controls, exit out
    case CongestionControlName::BBR:
    case CongestionControlName::VEGAS:
    case CongestionControlName::DCTCP:
    case CongestionControlName::DCTCP_RENO:
    case CongestionControlName::DCTCP_CUBIC:
      break; // supported, proceed
    case CongestionControlName::NumCcTypes:
      LOG(FATAL) << "CongestionControlName::NumCcTypes is not a valid CC type";
  }

  tcp_cc_info ccInfo = {};
  socklen_t len = sizeof(tcp_cc_info);
  const int ret = netopsDispatcher.getsockopt(
      fd, IPPROTO_TCP, TCP_CC_INFO, (void*)&ccInfo, &len);
  if (ret < 0) {
    int errnoCopy = errno;
    VLOG(4) << "Error calling getsockopt(): " << folly::errnoStr(errnoCopy);
    return;
  }
  wrappedInfo.maybeCcInfo = ccInfo;
  wrappedInfo.tcpCcInfoBytesRead = len;
#else
  return;
#endif
}