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());
}