void BcmPort::updateStats() { // TODO: It would be nicer to use a monotonic clock, but unfortunately // the ServiceData code currently expects everyone to use system time. auto now = duration_cast<seconds>(system_clock::now().time_since_epoch()); updateStat(now, &inBytes_, opennsl_spl_snmpIfHCInOctets); updateStat(now, &inUnicastPkts_, opennsl_spl_snmpIfHCInUcastPkts); updateStat(now, &inMulticastPkts_, opennsl_spl_snmpIfHCInMulticastPkts); updateStat(now, &inBroadcastPkts_, opennsl_spl_snmpIfHCInBroadcastPkts); updateStat(now, &inDiscards_, opennsl_spl_snmpIfInDiscards); updateStat(now, &inErrors_, opennsl_spl_snmpIfInErrors); updateStat(now, &outBytes_, opennsl_spl_snmpIfHCOutOctets); updateStat(now, &outUnicastPkts_, opennsl_spl_snmpIfHCOutUcastPkts); updateStat(now, &outMulticastPkts_, opennsl_spl_snmpIfHCOutMulticastPkts); updateStat(now, &outBroadcastPkts_, opennsl_spl_snmpIfHCOutBroadcastPckts); updateStat(now, &outDiscards_, opennsl_spl_snmpIfOutDiscards); updateStat(now, &outErrors_, opennsl_spl_snmpIfOutErrors); setAdditionalStats(now); // Update the queue length stat uint32_t qlength; auto ret = opennsl_port_queued_count_get(unit_, port_, &qlength); if (OPENNSL_FAILURE(ret)) { LOG(ERROR) << "Failed to get queue length for port " << port_ << " :" << opennsl_errmsg(ret); } else { SpinLockHolder guard(outQueueLen_.first.get()); outQueueLen_.second->addValue(now, qlength); // TODO: outQueueLen_ only exports the average queue length over the last // 60 seconds, 10 minutes, etc. // We should also export the current value. We could use a simple counter // or a dynamic counter for this. } // Update the packet length histograms updatePktLenHist(now, &inPktLengths_, kInPktLengthStats); updatePktLenHist(now, &outPktLengths_, kOutPktLengthStats); };
void BcmPort::updateStats() { // TODO: It would be nicer to use a monotonic clock, but unfortunately // the ServiceData code currently expects everyone to use system time. if (!shouldReportStats()) { return; } auto now = duration_cast<seconds>(system_clock::now().time_since_epoch()); HwPortStats curPortStats; updateStat( now, kInBytes, opennsl_spl_snmpIfHCInOctets, &curPortStats.inBytes_); updateStat( now, kInUnicastPkts, opennsl_spl_snmpIfHCInUcastPkts, &curPortStats.inUnicastPkts_); updateStat( now, kInMulticastPkts, opennsl_spl_snmpIfHCInMulticastPkts, &curPortStats.inMulticastPkts_); updateStat( now, kInBroadcastPkts, opennsl_spl_snmpIfHCInBroadcastPkts, &curPortStats.inBroadcastPkts_); updateStat( now, kInDiscards, opennsl_spl_snmpIfInDiscards, &curPortStats.inDiscards_); updateStat( now, kInErrors, opennsl_spl_snmpIfInErrors, &curPortStats.inErrors_); updateStat( now, kInIpv4HdrErrors, opennsl_spl_snmpIpInHdrErrors, &curPortStats.inIpv4HdrErrors_); updateStat( now, kInIpv6HdrErrors, opennsl_spl_snmpIpv6IfStatsInHdrErrors, &curPortStats.inIpv6HdrErrors_); updateStat( now, kInPause, opennsl_spl_snmpDot3InPauseFrames, &curPortStats.inPause_); // Egress Stats updateStat( now, kOutBytes, opennsl_spl_snmpIfHCOutOctets, &curPortStats.outBytes_); updateStat( now, kOutUnicastPkts, opennsl_spl_snmpIfHCOutUcastPkts, &curPortStats.outUnicastPkts_); updateStat( now, kOutMulticastPkts, opennsl_spl_snmpIfHCOutMulticastPkts, &curPortStats.outMulticastPkts_); updateStat( now, kOutBroadcastPkts, opennsl_spl_snmpIfHCOutBroadcastPckts, &curPortStats.outBroadcastPkts_); updateStat( now, kOutDiscards, opennsl_spl_snmpIfOutDiscards, &curPortStats.outDiscards_); updateStat( now, kOutErrors, opennsl_spl_snmpIfOutErrors, &curPortStats.outErrors_); updateStat( now, kOutPause, opennsl_spl_snmpDot3OutPauseFrames, &curPortStats.outPause_); setAdditionalStats(now, &curPortStats); // Compute non pause discards const auto kUninit = hardware_stats_constants::STAT_UNINITIALIZED(); if (isMmuLossy() && portStats_.inDiscards_ != kUninit && portStats_.inPause_ != kUninit) { // If MMU setup as lossy, all incoming pause frames will be // discarded and will count towards in discards. This makes in discards // counter somewhat useless. So instead calculate "in_non_pause_discards", // as std::max(0, (inDiscardsSincePrev - inPauseSincePrev)). // std::max(..) is used, since stats from h/w are synced non atomically, // So depending on what get synced later # of pause maybe be slightly // higher than # of discards. auto inPauseSincePrev = curPortStats.inPause_ - portStats_.inPause_; auto inDiscardsSincePrev = curPortStats.inDiscards_ - portStats_.inDiscards_; if (inPauseSincePrev >= 0 && inDiscardsSincePrev >=0) { // Account for counter rollover. auto inNonPauseDiscardsSincePrev = std::max(0L, (inDiscardsSincePrev - inPauseSincePrev)); // Init current port stats from prev value or 0 curPortStats.inNonPauseDiscards_ = (portStats_.inNonPauseDiscards_ == kUninit ? 0 : portStats_.inNonPauseDiscards_); // Counters are cumalative curPortStats.inNonPauseDiscards_ += inNonPauseDiscardsSincePrev; auto inNonPauseDiscards = getPortCounterIf(kInNonPauseDiscards); inNonPauseDiscards->updateValue(now, curPortStats.inNonPauseDiscards_); } } portStats_ = curPortStats; // Update the queue length stat uint32_t qlength; auto ret = opennsl_port_queued_count_get(unit_, port_, &qlength); if (OPENNSL_FAILURE(ret)) { LOG(ERROR) << "Failed to get queue length for port " << port_ << " :" << opennsl_errmsg(ret); } else { outQueueLen_.addValue(now.count(), qlength); // TODO: outQueueLen_ only exports the average queue length over the last // 60 seconds, 10 minutes, etc. // We should also export the current value. We could use a simple counter // or a dynamic counter for this. } // Update the packet length histograms updatePktLenHist(now, &inPktLengths_, kInPktLengthStats); updatePktLenHist(now, &outPktLengths_, kOutPktLengthStats); };