void getPortInfoHelper()

in fboss/agent/ThriftHandler.cpp [170:342]


void getPortInfoHelper(
    const SwSwitch& sw,
    PortInfoThrift& portInfo,
    const std::shared_ptr<Port> port) {
  *portInfo.portId() = port->getID();
  *portInfo.name() = port->getName();
  *portInfo.description() = port->getDescription();
  *portInfo.speedMbps() = static_cast<int>(port->getSpeed());
  for (auto entry : port->getVlans()) {
    portInfo.vlans()->push_back(entry.first);
  }

  std::shared_ptr<QosPolicy> qosPolicy;
  auto state = sw.getState();
  if (port->getQosPolicy().has_value()) {
    auto appliedPolicyName = port->getQosPolicy();
    qosPolicy =
        *appliedPolicyName == state->getDefaultDataPlaneQosPolicy()->getName()
        ? state->getDefaultDataPlaneQosPolicy()
        : state->getQosPolicy(*appliedPolicyName);
    if (!qosPolicy) {
      throw std::runtime_error("qosPolicy state is null");
    }
  }

  for (const auto& queue : port->getPortQueues()) {
    PortQueueThrift pq;
    *pq.id() = queue->getID();
    *pq.mode() = apache::thrift::TEnumTraits<cfg::QueueScheduling>::findName(
        queue->getScheduling());
    if (queue->getScheduling() ==
        facebook::fboss::cfg::QueueScheduling::WEIGHTED_ROUND_ROBIN) {
      pq.weight() = queue->getWeight();
    }
    if (queue->getReservedBytes()) {
      pq.reservedBytes() = queue->getReservedBytes().value();
    }
    if (queue->getScalingFactor()) {
      pq.scalingFactor() =
          apache::thrift::TEnumTraits<cfg::MMUScalingFactor>::findName(
              queue->getScalingFactor().value());
    }
    if (!queue->getAqms().empty()) {
      std::vector<ActiveQueueManagement> aqms;
      for (const auto& aqm : queue->getAqms()) {
        ActiveQueueManagement aqmThrift;
        switch (aqm.second.detection()->getType()) {
          case facebook::fboss::cfg::QueueCongestionDetection::Type::linear:
            aqmThrift.detection()->linear() = LinearQueueCongestionDetection();
            *aqmThrift.detection()->linear()->minimumLength() =
                *aqm.second.detection()->get_linear().minimumLength();
            *aqmThrift.detection()->linear()->maximumLength() =
                *aqm.second.detection()->get_linear().maximumLength();
            aqmThrift.detection()->linear()->probability() =
                *aqm.second.detection()->get_linear().probability();
            break;
          case facebook::fboss::cfg::QueueCongestionDetection::Type::__EMPTY__:
            XLOG(WARNING) << "Invalid queue congestion detection config";
            break;
        }
        *aqmThrift.behavior() = QueueCongestionBehavior(aqm.first);
        aqms.push_back(aqmThrift);
      }
      pq.aqms() = {};
      pq.aqms()->swap(aqms);
    }
    if (queue->getName()) {
      *pq.name() = queue->getName().value();
    }

    if (queue->getPortQueueRate().has_value()) {
      if (queue->getPortQueueRate().value().getType() ==
          cfg::PortQueueRate::Type::pktsPerSec) {
        Range range;
        range.minimum() =
            *queue->getPortQueueRate().value().get_pktsPerSec().minimum();
        range.maximum() =
            *queue->getPortQueueRate().value().get_pktsPerSec().maximum();
        PortQueueRate portQueueRate;
        portQueueRate.pktsPerSec_ref() = range;

        pq.portQueueRate() = portQueueRate;
      } else if (
          queue->getPortQueueRate().value().getType() ==
          cfg::PortQueueRate::Type::kbitsPerSec) {
        Range range;
        range.minimum() =
            *queue->getPortQueueRate().value().get_kbitsPerSec().minimum();
        range.maximum() =
            *queue->getPortQueueRate().value().get_kbitsPerSec().maximum();
        PortQueueRate portQueueRate;
        portQueueRate.kbitsPerSec_ref() = range;

        pq.portQueueRate() = portQueueRate;
      }
    }

    if (queue->getBandwidthBurstMinKbits()) {
      pq.bandwidthBurstMinKbits() = queue->getBandwidthBurstMinKbits().value();
    }

    if (queue->getBandwidthBurstMaxKbits()) {
      pq.bandwidthBurstMaxKbits() = queue->getBandwidthBurstMaxKbits().value();
    }

    if (!port->getLookupClassesToDistributeTrafficOn().empty()) {
      // On MH-NIC setup, RSW downlinks implement queue-pe-host.
      // For such configurations traffic goes to queue corresponding
      // to host regardless of DSCP value
      auto kMaxDscp = 64;
      std::vector<signed char> dscps(kMaxDscp);
      std::iota(dscps.begin(), dscps.end(), 0);
      pq.dscps() = dscps;
    } else if (qosPolicy) {
      std::vector<signed char> dscps;
      auto tcToDscp = qosPolicy->getDscpMap().from();
      auto tcToQueueId = qosPolicy->getTrafficClassToQueueId();
      for (const auto& entry : tcToDscp) {
        if (tcToQueueId[entry.trafficClass()] == queue->getID()) {
          dscps.push_back(entry.attr());
        }
      }
      pq.dscps() = dscps;
    }

    portInfo.portQueues()->push_back(pq);
  }

  *portInfo.adminState() = PortAdminState(
      port->getAdminState() == facebook::fboss::cfg::PortState::ENABLED);
  *portInfo.operState() =
      PortOperState(port->getOperState() == Port::OperState::UP);

  *portInfo.profileID() = apache::thrift::util::enumName(port->getProfileID());

  if (port->isEnabled()) {
    const auto platformPort = sw.getPlatform()->getPlatformPort(port->getID());
    PortHardwareDetails hw;
    hw.profile() = port->getProfileID();
    hw.profileConfig() =
        platformPort->getPortProfileConfigFromCache(*hw.profile());
    hw.pinConfig() = platformPort->getPortPinConfigs(*hw.profile());
    // Use SW Port pinConfig directly
    hw.pinConfig()->iphy() = port->getPinConfigs();
    hw.chips() = platformPort->getPortDataplaneChips(*hw.profile());
    portInfo.hw() = hw;

    auto fec = hw.profileConfig()->iphy()->fec().value();
    portInfo.fecEnabled() = fec != phy::FecMode::NONE;
    portInfo.fecMode() = apache::thrift::util::enumName(fec);
  }

  auto pause = port->getPause();
  *portInfo.txPause() = *pause.tx();
  *portInfo.rxPause() = *pause.rx();

  if (port->getPfc().has_value()) {
    PfcConfig pc;
    auto pfc = port->getPfc();
    pc.tx() = *pfc->tx();
    pc.rx() = *pfc->rx();
    pc.watchdog() = pfc->watchdog().has_value();
    portInfo.pfc() = pc;
  }
  try {
    portInfo.transceiverIdx() =
        sw.getPlatform()->getPortMapping(port->getID(), port->getSpeed());
  } catch (const facebook::fboss::FbossError& err) {
    // No problem, we just don't set the other info
  }

  fillPortStats(portInfo, portInfo.portQueues()->size());
}