For Linux added specific code to put interfaces in PROMISC mode, since we no longer use PCAP to do stats (which was indirectly setting PROMISC). Also added signal handlers to do cleanup for SIGTERM and SIGINT. Some code indentation fixes also.
Fixes issue 52
This commit is contained in:
parent
264b446410
commit
e188655e67
@ -21,10 +21,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "../common/protocolmanager.h"
|
#include "../common/protocolmanager.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
#include "signal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
extern ProtocolManager *OstProtocolManager;
|
extern ProtocolManager *OstProtocolManager;
|
||||||
|
|
||||||
int myport;
|
int myport;
|
||||||
|
|
||||||
|
void cleanup(int /*signum*/)
|
||||||
|
{
|
||||||
|
qApp->exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
@ -39,11 +48,24 @@ int main(int argc, char *argv[])
|
|||||||
if (!drone.init())
|
if (!drone.init())
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
struct sigaction sa;
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sa_handler = cleanup;
|
||||||
|
if (sigaction(SIGTERM, &sa, NULL))
|
||||||
|
qDebug("Failed to install SIGTERM handler. Cleanup may not happen!!!");
|
||||||
|
if (sigaction(SIGINT, &sa, NULL))
|
||||||
|
qDebug("Failed to install SIGINT handler. Cleanup may not happen!!!");
|
||||||
|
#endif
|
||||||
|
|
||||||
drone.setWindowFlags(drone.windowFlags()
|
drone.setWindowFlags(drone.windowFlags()
|
||||||
| Qt::WindowMaximizeButtonHint
|
| Qt::WindowMaximizeButtonHint
|
||||||
| Qt::WindowMinimizeButtonHint);
|
| Qt::WindowMinimizeButtonHint);
|
||||||
drone.showMinimized();
|
drone.showMinimized();
|
||||||
app.exec();
|
app.exec();
|
||||||
|
|
||||||
|
delete OstProtocolManager;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <errno.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
QList<LinuxPort*> LinuxPort::allPorts_;
|
QList<LinuxPort*> LinuxPort::allPorts_;
|
||||||
LinuxPort::StatsMonitor *LinuxPort::monitor_;
|
LinuxPort::StatsMonitor *LinuxPort::monitor_;
|
||||||
@ -33,13 +37,16 @@ LinuxPort::StatsMonitor *LinuxPort::monitor_;
|
|||||||
LinuxPort::LinuxPort(int id, const char *device)
|
LinuxPort::LinuxPort(int id, const char *device)
|
||||||
: PcapPort(id, device)
|
: PcapPort(id, device)
|
||||||
{
|
{
|
||||||
|
clearPromisc_ = false;
|
||||||
|
|
||||||
// We don't need per port Rx/Tx monitors for Linux
|
// We don't need per port Rx/Tx monitors for Linux
|
||||||
delete monitorRx_;
|
delete monitorRx_;
|
||||||
delete monitorTx_;
|
delete monitorTx_;
|
||||||
|
monitorRx_ = monitorTx_ = NULL;
|
||||||
|
|
||||||
// We have one monitor for both Rx/Tx of all ports
|
// We have one monitor for both Rx/Tx of all ports
|
||||||
if (!monitor_)
|
if (!monitor_)
|
||||||
monitor_ = new StatsMonitor();
|
monitor_ = new StatsMonitor();
|
||||||
|
|
||||||
data_.set_is_exclusive_control(hasExclusiveControl());
|
data_.set_is_exclusive_control(hasExclusiveControl());
|
||||||
minPacketSetSize_ = 16;
|
minPacketSetSize_ = 16;
|
||||||
@ -50,6 +57,32 @@ LinuxPort::LinuxPort(int id, const char *device)
|
|||||||
|
|
||||||
LinuxPort::~LinuxPort()
|
LinuxPort::~LinuxPort()
|
||||||
{
|
{
|
||||||
|
qDebug("In %s", __FUNCTION__);
|
||||||
|
|
||||||
|
if (clearPromisc_)
|
||||||
|
{
|
||||||
|
int sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
strncpy(ifr.ifr_name, name(), sizeof(ifr.ifr_name));
|
||||||
|
|
||||||
|
if (ioctl(sd, SIOCGIFFLAGS, &ifr) != -1)
|
||||||
|
{
|
||||||
|
if (ifr.ifr_flags & IFF_PROMISC)
|
||||||
|
{
|
||||||
|
ifr.ifr_flags &= ~IFF_PROMISC;
|
||||||
|
if (ioctl(sd, SIOCSIFFLAGS, &ifr) == -1)
|
||||||
|
qDebug("Failed clearing promisc flag. SIOCSIFFLAGS failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
qDebug("Failed clearing promisc flag. SIOCGIFFLAGS failed: %s",
|
||||||
|
strerror(errno));
|
||||||
|
|
||||||
|
close(sd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxPort::init()
|
void LinuxPort::init()
|
||||||
@ -57,7 +90,7 @@ void LinuxPort::init()
|
|||||||
// TODO: Update Notes with Promisc/Non-Promisc
|
// TODO: Update Notes with Promisc/Non-Promisc
|
||||||
|
|
||||||
if (!monitor_->isRunning())
|
if (!monitor_->isRunning())
|
||||||
monitor_->start();
|
monitor_->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
OstProto::LinkState LinuxPort::linkState()
|
OstProto::LinkState LinuxPort::linkState()
|
||||||
@ -86,16 +119,17 @@ LinuxPort::StatsMonitor::StatsMonitor()
|
|||||||
void LinuxPort::StatsMonitor::run()
|
void LinuxPort::StatsMonitor::run()
|
||||||
{
|
{
|
||||||
PortStats **portStats;
|
PortStats **portStats;
|
||||||
int fd;
|
int fd, sd;
|
||||||
QByteArray buf;
|
QByteArray buf;
|
||||||
int len;
|
int len;
|
||||||
char *p, *end;
|
char *p, *end;
|
||||||
int count, index;
|
int count, index;
|
||||||
const char* fmtopt[] = {
|
const char* fmtopt[] = {
|
||||||
"%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u\n",
|
"%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u\n",
|
||||||
"%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u%n\n",
|
"%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u%n\n",
|
||||||
};
|
};
|
||||||
const char *fmt;
|
const char *fmt;
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
//
|
//
|
||||||
// We first setup stuff before we start polling for stats
|
// We first setup stuff before we start polling for stats
|
||||||
@ -103,16 +137,16 @@ void LinuxPort::StatsMonitor::run()
|
|||||||
fd = open("/proc/net/dev", O_RDONLY);
|
fd = open("/proc/net/dev", O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
qWarning("Unable to open /proc/net/dev - no stats will be available");
|
qWarning("Unable to open /proc/net/dev - no stats will be available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.fill('\0', 8192);
|
buf.fill('\0', 8192);
|
||||||
len = read(fd, (void*) buf.data(), buf.size());
|
len = read(fd, (void*) buf.data(), buf.size());
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
{
|
||||||
qWarning("initial buffer size is too small. no stats will be available");
|
qWarning("initial buffer size is too small. no stats will be available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = buf.data();
|
p = buf.data();
|
||||||
@ -120,29 +154,33 @@ void LinuxPort::StatsMonitor::run()
|
|||||||
|
|
||||||
// Select scanf format
|
// Select scanf format
|
||||||
if (strstr(buf, "compressed"))
|
if (strstr(buf, "compressed"))
|
||||||
fmt = fmtopt[0];
|
fmt = fmtopt[0];
|
||||||
else
|
else
|
||||||
fmt = fmtopt[1];
|
fmt = fmtopt[1];
|
||||||
|
|
||||||
// Count number of lines - number of ports is 2 less than number of lines
|
// Count number of lines - number of ports is 2 less than number of lines
|
||||||
count = 0;
|
count = 0;
|
||||||
while (p < end)
|
while (p < end)
|
||||||
{
|
{
|
||||||
if (*p == '\n')
|
if (*p == '\n')
|
||||||
count++;
|
count++;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
count -= 2;
|
count -= 2;
|
||||||
|
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
{
|
{
|
||||||
qWarning("no ports in /proc/dev/net - no stats will be available");
|
qWarning("no ports in /proc/dev/net - no stats will be available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
portStats = (PortStats**) calloc(count, sizeof(PortStats));
|
portStats = (PortStats**) calloc(count, sizeof(PortStats));
|
||||||
Q_ASSERT(portStats != NULL);
|
Q_ASSERT(portStats != NULL);
|
||||||
|
|
||||||
|
sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
Q_ASSERT(sd >= 0);
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Populate the port stats array
|
// Populate the port stats array
|
||||||
//
|
//
|
||||||
@ -150,48 +188,73 @@ void LinuxPort::StatsMonitor::run()
|
|||||||
|
|
||||||
// Skip first two lines
|
// Skip first two lines
|
||||||
while (*p != '\n')
|
while (*p != '\n')
|
||||||
p++;
|
p++;
|
||||||
p++;
|
p++;
|
||||||
while (*p != '\n')
|
while (*p != '\n')
|
||||||
p++;
|
p++;
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
while (p < end)
|
while (p < end)
|
||||||
{
|
{
|
||||||
char* q;
|
char* q;
|
||||||
|
|
||||||
// Skip whitespace
|
// Skip whitespace
|
||||||
while ((p < end) && (*p == ' '))
|
while ((p < end) && (*p == ' '))
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
q = p;
|
|
||||||
|
|
||||||
// Get interface name
|
q = p;
|
||||||
while ((q < end) && (*q != ':') && (*q != '\n'))
|
|
||||||
q++;
|
|
||||||
|
|
||||||
if ((q < end) && (*q == ':'))
|
// Get interface name
|
||||||
{
|
while ((q < end) && (*q != ':') && (*q != '\n'))
|
||||||
foreach(LinuxPort* port, allPorts_)
|
q++;
|
||||||
|
|
||||||
|
if ((q < end) && (*q == ':'))
|
||||||
{
|
{
|
||||||
if (strncmp(port->name(), p, int(q-p)) == 0)
|
foreach(LinuxPort* port, allPorts_)
|
||||||
{
|
{
|
||||||
portStats[index] = &(port->stats_);
|
if (strncmp(port->name(), p, int(q-p)) == 0)
|
||||||
break;
|
{
|
||||||
}
|
portStats[index] = &(port->stats_);
|
||||||
}
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
|
|
||||||
// Skip till newline
|
// Set promisc mode, if not already set
|
||||||
p = q;
|
strncpy(ifr.ifr_name, port->name(), sizeof(ifr.ifr_name));
|
||||||
while (*p != '\n')
|
if (ioctl(sd, SIOCGIFFLAGS, &ifr) != -1)
|
||||||
|
{
|
||||||
|
if ((ifr.ifr_flags & IFF_PROMISC) == 0)
|
||||||
|
{
|
||||||
|
ifr.ifr_flags |= IFF_PROMISC;
|
||||||
|
if (ioctl(sd, SIOCSIFFLAGS, &ifr) != -1)
|
||||||
|
port->clearPromisc_ = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug("%s: failed to set promisc; "
|
||||||
|
"SIOCSIFFLAGS failed (%s)",
|
||||||
|
port->name(), strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug("%s: failed to set promisc; SIOCGIFFLAGS failed (%s)",
|
||||||
|
port->name(), strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
|
||||||
|
// Skip till newline
|
||||||
|
p = q;
|
||||||
|
while (*p != '\n')
|
||||||
|
p++;
|
||||||
p++;
|
p++;
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
Q_ASSERT(index == count);
|
Q_ASSERT(index == count);
|
||||||
|
|
||||||
|
close(sd);
|
||||||
|
|
||||||
qDebug("stats for %d ports setup", count);
|
qDebug("stats for %d ports setup", count);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -199,77 +262,77 @@ void LinuxPort::StatsMonitor::run()
|
|||||||
//
|
//
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
len = read(fd, (void*) buf.data(), buf.size());
|
len = read(fd, (void*) buf.data(), buf.size());
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
|
||||||
if (buf.size() > 1*1024*1024)
|
|
||||||
{
|
{
|
||||||
qWarning("buffer size hit limit. no more stats");
|
if (buf.size() > 1*1024*1024)
|
||||||
return;
|
{
|
||||||
}
|
qWarning("buffer size hit limit. no more stats");
|
||||||
qDebug("doubling buffer size. curr = %d", buf.size());
|
return;
|
||||||
buf.resize(buf.size() * 2);
|
}
|
||||||
continue;
|
qDebug("doubling buffer size. curr = %d", buf.size());
|
||||||
}
|
buf.resize(buf.size() * 2);
|
||||||
|
continue;
|
||||||
p = buf.data();
|
|
||||||
end = p + len;
|
|
||||||
|
|
||||||
// Skip first two lines
|
|
||||||
while (*p != '\n')
|
|
||||||
p++;
|
|
||||||
p++;
|
|
||||||
while (*p != '\n')
|
|
||||||
p++;
|
|
||||||
p++;
|
|
||||||
|
|
||||||
index = 0;
|
|
||||||
while (p < end)
|
|
||||||
{
|
|
||||||
uint dummy;
|
|
||||||
quint64 rxBytes, rxPkts;
|
|
||||||
quint64 txBytes, txPkts;
|
|
||||||
|
|
||||||
// Skip interface name - we assume the number and order of ports
|
|
||||||
// won't change since we parsed the output before we started polling
|
|
||||||
while ((p < end) && (*p != ':') && (*p != '\n'))
|
|
||||||
p++;
|
|
||||||
if (p >= end)
|
|
||||||
break;
|
|
||||||
if (*p == '\n')
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
|
|
||||||
sscanf(p, fmt,
|
|
||||||
&rxBytes, &rxPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy,
|
|
||||||
&txBytes, &txPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy);
|
|
||||||
|
|
||||||
if (index < count)
|
|
||||||
{
|
|
||||||
AbstractPort::PortStats *stats = portStats[index];
|
|
||||||
if (stats)
|
|
||||||
{
|
|
||||||
stats->rxPps = (rxPkts - stats->rxPkts)/kRefreshFreq_;
|
|
||||||
stats->rxBps = (rxBytes - stats->rxBytes)/kRefreshFreq_;
|
|
||||||
stats->rxPkts = rxPkts;
|
|
||||||
stats->rxBytes = rxBytes;
|
|
||||||
stats->txPps = (txPkts - stats->txPkts)/kRefreshFreq_;
|
|
||||||
stats->txBps = (txBytes - stats->txBytes)/kRefreshFreq_;
|
|
||||||
stats->txPkts = txPkts;
|
|
||||||
stats->txBytes = txBytes;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p = buf.data();
|
||||||
|
end = p + len;
|
||||||
|
|
||||||
|
// Skip first two lines
|
||||||
while (*p != '\n')
|
while (*p != '\n')
|
||||||
|
p++;
|
||||||
p++;
|
p++;
|
||||||
|
while (*p != '\n')
|
||||||
|
p++;
|
||||||
p++;
|
p++;
|
||||||
index++;
|
|
||||||
}
|
index = 0;
|
||||||
QThread::sleep(kRefreshFreq_);
|
while (p < end)
|
||||||
|
{
|
||||||
|
uint dummy;
|
||||||
|
quint64 rxBytes, rxPkts;
|
||||||
|
quint64 txBytes, txPkts;
|
||||||
|
|
||||||
|
// Skip interface name - we assume the number and order of ports
|
||||||
|
// won't change since we parsed the output before we started polling
|
||||||
|
while ((p < end) && (*p != ':') && (*p != '\n'))
|
||||||
|
p++;
|
||||||
|
if (p >= end)
|
||||||
|
break;
|
||||||
|
if (*p == '\n')
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
|
||||||
|
sscanf(p, fmt,
|
||||||
|
&rxBytes, &rxPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy,
|
||||||
|
&txBytes, &txPkts, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy);
|
||||||
|
|
||||||
|
if (index < count)
|
||||||
|
{
|
||||||
|
AbstractPort::PortStats *stats = portStats[index];
|
||||||
|
if (stats)
|
||||||
|
{
|
||||||
|
stats->rxPps = (rxPkts - stats->rxPkts)/kRefreshFreq_;
|
||||||
|
stats->rxBps = (rxBytes - stats->rxBytes)/kRefreshFreq_;
|
||||||
|
stats->rxPkts = rxPkts;
|
||||||
|
stats->rxBytes = rxBytes;
|
||||||
|
stats->txPps = (txPkts - stats->txPkts)/kRefreshFreq_;
|
||||||
|
stats->txBps = (txBytes - stats->txBytes)/kRefreshFreq_;
|
||||||
|
stats->txPkts = txPkts;
|
||||||
|
stats->txBytes = txBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*p != '\n')
|
||||||
|
p++;
|
||||||
|
p++;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
QThread::sleep(kRefreshFreq_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ protected:
|
|||||||
static const int kRefreshFreq_ = 1; // in seconds
|
static const int kRefreshFreq_ = 1; // in seconds
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool clearPromisc_;
|
||||||
static QList<LinuxPort*> allPorts_;
|
static QList<LinuxPort*> allPorts_;
|
||||||
static StatsMonitor *monitor_; // rx/tx stats for ALL ports
|
static StatsMonitor *monitor_; // rx/tx stats for ALL ports
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user