From b617c44e61f348d4c4ff25f06b027d8de866d44f Mon Sep 17 00:00:00 2001 From: "Srivats P." Date: Wed, 18 Feb 2015 21:20:27 +0530 Subject: [PATCH] 64bit stats support added for Linux if supported by the kernel and driver Fixes issue 70 --- server/drone.pro | 2 + server/linuxport.cpp | 107 +++++++++++++++++++++++++++++++------------ 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/server/drone.pro b/server/drone.pro index 54efd8b..d22f138 100644 --- a/server/drone.pro +++ b/server/drone.pro @@ -3,6 +3,8 @@ CONFIG += qt ver_info QT += network script QT -= gui DEFINES += HAVE_REMOTE WPCAP +linux*:system(grep -q IFLA_STATS64 /usr/include/linux/if_link.h): \ + DEFINES += HAVE_IFLA_STATS64 INCLUDEPATH += "../rpc" win32 { CONFIG += console diff --git a/server/linuxport.cpp b/server/linuxport.cpp index 18cf525..55468ef 100644 --- a/server/linuxport.cpp +++ b/server/linuxport.cpp @@ -40,6 +40,15 @@ QList LinuxPort::allPorts_; LinuxPort::StatsMonitor *LinuxPort::monitor_; const quint32 kMaxValue32 = 0xffffffff; +const quint64 kMaxValue64 = 0xffffffffffffffffULL; + +#ifdef HAVE_IFLA_STATS64 +#define X_IFLA_STATS IFLA_STATS64 +typedef struct rtnl_link_stats64 x_rtnl_link_stats; +#else +#define X_IFLA_STATS IFLA_STATS +typedef struct rtnl_link_stats x_rtnl_link_stats; +#endif LinuxPort::LinuxPort(int id, const char *device) : PcapPort(id, device) @@ -62,7 +71,10 @@ LinuxPort::LinuxPort(int id, const char *device) qDebug("adding dev to all ports list <%s>", device); allPorts_.append(this); - maxStatsValue_ = 0xffffffff; + // A port can support either 32 or 64 bit stats - we will attempt + // to guess this for each port and initialize this variable at + // run time when the counter wraps around + maxStatsValue_ = 0; } LinuxPort::~LinuxPort() @@ -332,6 +344,7 @@ void LinuxPort::StatsMonitor::procStats() AbstractPort::PortStats *stats = portStats[index]; if (stats) { + // TODO: fix the pps/Bps calc similar to netlink stats stats->rxPps = ((rxPkts >= stats->rxPkts) ? rxPkts - stats->rxPkts : @@ -378,6 +391,7 @@ void LinuxPort::StatsMonitor::procStats() int LinuxPort::StatsMonitor::netlinkStats() { QHash portStats; + QHash portMaxStatsValue; QHash linkState; int fd; struct sockaddr_nl local; @@ -555,6 +569,8 @@ _retry: if (strcmp(port->name(), ifname) == 0) { portStats[uint(ifi->ifi_index)] = &(port->stats_); + portMaxStatsValue[uint(ifi->ifi_index)] = + &(port->maxStatsValue_); linkState[uint(ifi->ifi_index)] = &(port->linkState_); if (setPromisc(port->name())) @@ -640,43 +656,76 @@ _retry_recv: rtaLen = len - NLMSG_LENGTH(sizeof(*ifi)); while (RTA_OK(rta, rtaLen)) { - // TODO: IFLA_STATS64 - if (rta->rta_type == IFLA_STATS) + if (rta->rta_type == X_IFLA_STATS) { - struct rtnl_link_stats *rtnlStats = - (struct rtnl_link_stats*) RTA_DATA(rta); + x_rtnl_link_stats *rtnlStats = + (x_rtnl_link_stats*) RTA_DATA(rta); AbstractPort::PortStats *stats = portStats[ifi->ifi_index]; + quint64 *maxStatsValue = portMaxStatsValue[ifi->ifi_index]; OstProto::LinkState *state = linkState[ifi->ifi_index]; if (!stats) break; - stats->rxPps = - ((rtnlStats->rx_packets >= stats->rxPkts) ? - rtnlStats->rx_packets - stats->rxPkts : - rtnlStats->rx_packets + (kMaxValue32 - - stats->rxPkts)) - / kRefreshFreq_; - stats->rxBps = - ((rtnlStats->rx_bytes >= stats->rxBytes) ? - rtnlStats->rx_bytes - stats->rxBytes : - rtnlStats->rx_bytes + (kMaxValue32 - - stats->rxBytes)) - / kRefreshFreq_; + if (rtnlStats->rx_packets >= stats->rxPkts) { + stats->rxPps = (rtnlStats->rx_packets - stats->rxPkts) + / kRefreshFreq_; + } + else { + if (*maxStatsValue == 0) { + *maxStatsValue = stats->rxPkts > kMaxValue32 ? + kMaxValue64 : kMaxValue32; + } + stats->rxPps = ((*maxStatsValue - stats->rxPkts) + + rtnlStats->rx_packets) + / kRefreshFreq_; + } + + if (rtnlStats->rx_bytes >= stats->rxBytes) { + stats->rxBps = (rtnlStats->rx_bytes - stats->rxBytes) + / kRefreshFreq_; + } + else { + if (*maxStatsValue == 0) { + *maxStatsValue = stats->rxBytes > kMaxValue32 ? + kMaxValue64 : kMaxValue32; + } + stats->rxBps = ((*maxStatsValue - stats->rxBytes) + + rtnlStats->rx_bytes) + / kRefreshFreq_; + } + stats->rxPkts = rtnlStats->rx_packets; stats->rxBytes = rtnlStats->rx_bytes; - stats->txPps = - ((rtnlStats->tx_packets >= stats->txPkts) ? - rtnlStats->tx_packets - stats->txPkts : - rtnlStats->tx_packets + (kMaxValue32 - - stats->txPkts)) - / kRefreshFreq_; - stats->txBps = - ((rtnlStats->tx_bytes >= stats->txBytes) ? - rtnlStats->tx_bytes - stats->txBytes : - rtnlStats->tx_bytes + (kMaxValue32 - - stats->txBytes)) - / kRefreshFreq_; + + if (rtnlStats->tx_packets >= stats->txPkts) { + stats->txPps = (rtnlStats->tx_packets - stats->txPkts) + / kRefreshFreq_; + } + else { + if (*maxStatsValue == 0) { + *maxStatsValue = stats->txPkts > kMaxValue32 ? + kMaxValue64 : kMaxValue32; + } + stats->txPps = ((*maxStatsValue - stats->txPkts) + + rtnlStats->tx_packets) + / kRefreshFreq_; + } + + if (rtnlStats->tx_bytes >= stats->txBytes) { + stats->txBps = (rtnlStats->tx_bytes - stats->txBytes) + / kRefreshFreq_; + } + else { + if (*maxStatsValue == 0) { + *maxStatsValue = stats->txBytes > kMaxValue32 ? + kMaxValue64 : kMaxValue32; + } + stats->txBps = ((*maxStatsValue - stats->txBytes) + + rtnlStats->tx_bytes) + / kRefreshFreq_; + } + stats->txPkts = rtnlStats->tx_packets; stats->txBytes = rtnlStats->tx_bytes;