sums, not eating 100% cpu :)

This commit is contained in:
Arnout Engelen
2006-12-19 20:35:33 +00:00
parent 06bd2d4a25
commit c0e6a385e4
10 changed files with 140 additions and 25 deletions

View File

@@ -8,10 +8,10 @@ DESTDIR := /usr/local
bin := $(DESTDIR)/bin bin := $(DESTDIR)/bin
man8 := $(DESTDIR)/share/man/man8/ man8 := $(DESTDIR)/share/man/man8/
all: nethogs decpcap_test all: nethogs decpcap_test nethogs_testsum
#CFLAGS=-g -Wall CFLAGS=-g -Wall
CFLAGS=-O2 #CFLAGS=-O2
OBJS=packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o OBJS=packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o
.PHONY: tgz .PHONY: tgz
@@ -28,6 +28,8 @@ install: nethogs nethogs.8
nethogs: nethogs.cpp $(OBJS) nethogs: nethogs.cpp $(OBJS)
$(CXX) $(CFLAGS) nethogs.cpp $(OBJS) -o nethogs -lpcap -lm -lncurses -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" $(CXX) $(CFLAGS) nethogs.cpp $(OBJS) -o nethogs -lpcap -lm -lncurses -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\"
nethogs_testsum: nethogs_testsum.cpp $(OBJS)
$(CXX) $(CFLAGS) -g nethogs_testsum.cpp $(OBJS) -o nethogs_testsum -lpcap -lm -lncurses -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\"
decpcap_test: decpcap_test.cpp decpcap.o decpcap_test: decpcap_test.cpp decpcap.o
$(CXX) $(CFLAGS) decpcap_test.cpp decpcap.o -o decpcap_test -lpcap -lm $(CXX) $(CFLAGS) decpcap_test.cpp decpcap.o -o decpcap_test -lpcap -lm

View File

@@ -69,19 +69,25 @@ Connection::Connection (Packet * packet)
connections = new ConnList (this, connections); connections = new ConnList (this, connections);
sent_packets = new PackList (); sent_packets = new PackList ();
recv_packets = new PackList (); recv_packets = new PackList ();
sumSent = 0;
sumRecv = 0;
if (DEBUG)
{
std::cout << "New connection, with package len " << packet->len << std::endl;
}
if (packet->Outgoing()) if (packet->Outgoing())
{ {
sumSent += packet->len;
sent_packets->add(packet); sent_packets->add(packet);
refpacket = new Packet (*packet); refpacket = new Packet (*packet);
} else { } else {
sumRecv += packet->len;
recv_packets->add(packet); recv_packets->add(packet);
refpacket = packet->newInverted(); refpacket = packet->newInverted();
} }
lastpacket = packet->time.tv_sec; lastpacket = packet->time.tv_sec;
if (DEBUG) if (DEBUG)
std::cout << "New reference packet created at " << refpacket << std::endl; std::cout << "New reference packet created at " << refpacket << std::endl;
sumSent = 0;
sumRecv = 0;
} }
Connection::~Connection () Connection::~Connection ()
@@ -126,12 +132,21 @@ void Connection::add (Packet * packet)
lastpacket = packet->time.tv_sec; lastpacket = packet->time.tv_sec;
if (packet->Outgoing()) if (packet->Outgoing())
{ {
if (DEBUG)
{
std::cout << "Outgoing: " << packet->len << std::endl;
}
sumSent += packet->len; sumSent += packet->len;
sent_packets->add (packet); sent_packets->add (packet);
} }
else else
{ {
if (DEBUG)
{
std::cout << "Incoming: " << packet->len << std::endl;
}
sumRecv += packet->len; sumRecv += packet->len;
std::cout << "sumRecv now: " << sumRecv << std::endl;
recv_packets->add (packet); recv_packets->add (packet);
} }
} }
@@ -168,7 +183,7 @@ Connection * findConnection (Packet * packet)
* Returns sum of sent packages (by address) * Returns sum of sent packages (by address)
* sum of recieved packages (by address) * sum of recieved packages (by address)
*/ */
void Connection::sumanddel (timeval t, u_int32_t * sent, u_int32_t * recv) void Connection::sumanddel (timeval t, u_int32_t * recv, u_int32_t * sent)
{ {
(*sent)=(*recv)=0; (*sent)=(*recv)=0;

View File

@@ -73,7 +73,7 @@ public:
/* sums up the total bytes used /* sums up the total bytes used
* and removes 'old' packets. */ * and removes 'old' packets. */
void sumanddel(timeval curtime, u_int32_t * sent, u_int32_t * recv); void sumanddel(timeval curtime, u_int32_t * recv, u_int32_t * sent);
/* for checking if a packet is part of this connection */ /* for checking if a packet is part of this connection */
/* the reference packet is always *outgoing*. */ /* the reference packet is always *outgoing*. */

85
cui.cpp
View File

@@ -20,15 +20,17 @@ extern Process * unknownip;
// sort on sent or received? // sort on sent or received?
bool sortRecv = true; bool sortRecv = true;
// viewMode: kb/s or total // viewMode: kb/s or total
int viewMode = 0;
int VIEWMODE_KBPS = 0; int VIEWMODE_KBPS = 0;
int VIEWMODE_TOTAL_KB = 1; int VIEWMODE_TOTAL_KB = 1;
int nViewModes = 2; int VIEWMODE_TOTAL_B = 2;
int VIEWMODE_TOTAL_MB = 3;
int viewMode = VIEWMODE_TOTAL_B;
int nViewModes = 4;
class Line class Line
{ {
public: public:
Line (const char * name, double n_sent_value, double n_recv_value, pid_t pid, uid_t uid, const char * n_devicename) Line (const char * name, double n_recv_value, double n_sent_value, pid_t pid, uid_t uid, const char * n_devicename)
{ {
if (!ROBUST) if (!ROBUST)
{ {
@@ -116,9 +118,17 @@ void Line::show (int row)
{ {
mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB/sec"); mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB/sec");
} }
else if (viewMode == VIEWMODE_TOTAL_MB)
{
mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "MB ");
}
else if (viewMode == VIEWMODE_TOTAL_KB) else if (viewMode == VIEWMODE_TOTAL_KB)
{ {
mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB"); mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "KB ");
}
else if (viewMode == VIEWMODE_TOTAL_B)
{
mvprintw (3+row, 6 + 9 + PROGNAME_WIDTH + 2 + 6 + 9 + 3 + 11, "B ");
} }
} }
@@ -200,6 +210,14 @@ void ui_tick ()
} }
} }
float tomb (u_int32_t bytes)
{
return ((double)bytes) / 1024 / 1024;
}
float tokb (u_int32_t bytes)
{
return ((double)bytes) / 1024;
}
float tokbps (u_int32_t bytes) float tokbps (u_int32_t bytes)
{ {
return (((double)bytes) / PERIOD) / 1024; return (((double)bytes) / PERIOD) / 1024;
@@ -233,7 +251,7 @@ void getkbps (Process * curproc, float * recvd, float * sent)
else else
{ {
u_int32_t sent = 0, recv = 0; u_int32_t sent = 0, recv = 0;
curconn->getVal()->sumanddel(curtime, &sent, &recv); curconn->getVal()->sumanddel(curtime, &recv, &sent);
sum_sent += sent; sum_sent += sent;
sum_recv += recv; sum_recv += recv;
previous = curconn; previous = curconn;
@@ -245,7 +263,7 @@ void getkbps (Process * curproc, float * recvd, float * sent)
} }
/** get total values for this process */ /** get total values for this process */
void gettotal(Process * curproc, float * recvd, float * sent) void gettotal(Process * curproc, u_int32_t * recvd, u_int32_t * sent)
{ {
u_int32_t sum_sent = 0, u_int32_t sum_sent = 0,
sum_recv = 0; sum_recv = 0;
@@ -257,8 +275,39 @@ void gettotal(Process * curproc, float * recvd, float * sent)
sum_recv += conn->sumRecv; sum_recv += conn->sumRecv;
curconn = curconn->getNext(); curconn = curconn->getNext();
} }
*recvd = tokbps(sum_recv); //std::cout << "Sum sent: " << sum_sent << std::endl;
*sent = tokbps(sum_sent); //std::cout << "Sum recv: " << sum_recv << std::endl;
*recvd = sum_recv;
*sent = sum_sent;
}
void gettotalmb(Process * curproc, float * recvd, float * sent)
{
u_int32_t sum_sent = 0,
sum_recv = 0;
gettotal(curproc, &sum_recv, &sum_sent);
*recvd = tomb(sum_recv);
*sent = tomb(sum_sent);
}
/** get total values for this process */
void gettotalkb(Process * curproc, float * recvd, float * sent)
{
u_int32_t sum_sent = 0,
sum_recv = 0;
gettotal(curproc, &sum_recv, &sum_sent);
*recvd = tokb(sum_recv);
*sent = tokb(sum_sent);
}
void gettotalb(Process * curproc, float * recvd, float * sent)
{
u_int32_t sum_sent = 0,
sum_recv = 0;
gettotal(curproc, &sum_recv, &sum_sent);
//std::cout << "Total sent: " << sum_sent << std::endl;
*sent = sum_sent;
*recvd = sum_recv;
} }
// Display all processes and relevant network traffic using show function // Display all processes and relevant network traffic using show function
@@ -335,11 +384,23 @@ void do_refresh()
if (viewMode == VIEWMODE_KBPS) if (viewMode == VIEWMODE_KBPS)
{ {
std::cout << "kbps viemode" << std::endl;
getkbps (curproc->getVal(), &value_recv, &value_sent); getkbps (curproc->getVal(), &value_recv, &value_sent);
} }
else if (viewMode == VIEWMODE_TOTAL_KB) else if (viewMode == VIEWMODE_TOTAL_KB)
{ {
gettotal(curproc->getVal(), &value_recv, &value_sent); //std::cout << "total viemode" << std::endl;
gettotalkb(curproc->getVal(), &value_recv, &value_sent);
}
else if (viewMode == VIEWMODE_TOTAL_MB)
{
//std::cout << "total viemode" << std::endl;
gettotalmb(curproc->getVal(), &value_recv, &value_sent);
}
else if (viewMode == VIEWMODE_TOTAL_B)
{
//std::cout << "total viemode" << std::endl;
gettotalb(curproc->getVal(), &value_recv, &value_sent);
} }
else else
{ {
@@ -354,7 +415,7 @@ void do_refresh()
assert (curproc->getVal()->pid >= 0); assert (curproc->getVal()->pid >= 0);
assert (n < nproc); assert (n < nproc);
} }
lines[n] = new Line (curproc->getVal()->name, value_sent, value_recv, lines[n] = new Line (curproc->getVal()->name, value_recv, value_sent,
curproc->getVal()->pid, uid, curproc->getVal()->devicename); curproc->getVal()->pid, uid, curproc->getVal()->devicename);
previousproc = curproc; previousproc = curproc;
curproc = curproc->next; curproc = curproc->next;
@@ -399,8 +460,12 @@ void do_refresh()
if (viewMode == VIEWMODE_KBPS) if (viewMode == VIEWMODE_KBPS)
{ {
mvprintw (3+1+i, 73, "KB/sec "); mvprintw (3+1+i, 73, "KB/sec ");
} else if (viewMode == VIEWMODE_TOTAL_B) {
mvprintw (3+1+i, 73, "B ");
} else if (viewMode == VIEWMODE_TOTAL_KB) { } else if (viewMode == VIEWMODE_TOTAL_KB) {
mvprintw (3+1+i, 73, "KB "); mvprintw (3+1+i, 73, "KB ");
} else if (viewMode == VIEWMODE_TOTAL_MB) {
mvprintw (3+1+i, 73, "MB ");
} }
attroff(A_REVERSE); attroff(A_REVERSE);
mvprintw (4+1+i, 0, ""); mvprintw (4+1+i, 0, "");

View File

@@ -7,6 +7,8 @@
#include <pcap.h> #include <pcap.h>
#include "decpcap.h" #include "decpcap.h"
#define DP_DEBUG 0
/* functions to set up a handle (which is basically just a pcap handle) */ /* functions to set up a handle (which is basically just a pcap handle) */
struct dp_handle * dp_fillhandle(pcap_t * phandle) struct dp_handle * dp_fillhandle(pcap_t * phandle)
@@ -92,6 +94,10 @@ void dp_parse_tcp (struct dp_handle * handle, const dp_header * header, const u_
void dp_parse_ip (struct dp_handle * handle, const dp_header * header, const u_char * packet) void dp_parse_ip (struct dp_handle * handle, const dp_header * header, const u_char * packet)
{ {
const struct ip * ip = (struct ip *) packet; const struct ip * ip = (struct ip *) packet;
if (DP_DEBUG)
{
fprintf(stdout, "Looking at packet with length %ud\n", header->len);
}
u_char * payload = (u_char *) packet + sizeof (struct ip); u_char * payload = (u_char *) packet + sizeof (struct ip);
if (handle->callback[dp_packet_ip] != NULL) if (handle->callback[dp_packet_ip] != NULL)

View File

@@ -2,7 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include <pcap.h> #include <pcap.h>
#define DP_ERRBUFF_SIZE PCAP_ERRBUF_SIZE #define DP_ERRBUF_SIZE PCAP_ERRBUF_SIZE
/* definitions */ /* definitions */
@@ -24,6 +24,7 @@ enum dp_packet_type {
};*/ };*/
/*struct dp_header { /*struct dp_header {
* pcap
};*/ };*/
typedef struct pcap_pkthdr dp_header; typedef struct pcap_pkthdr dp_header;

View File

@@ -6,9 +6,9 @@ extern "C" {
int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_packet) { int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_packet) {
std::cout << "Callback for processing TCP packet called" << std::endl; std::cout << "Callback for processing TCP packet called" << std::endl;
return 0;
} }
int main (int argc, char ** argv) int main (int argc, char ** argv)
{ {
if (argc < 2) if (argc < 2)
@@ -16,7 +16,7 @@ int main (int argc, char ** argv)
std::cout << "Please, enter a filename" << std::endl; std::cout << "Please, enter a filename" << std::endl;
} }
char* errbuf = new char[DP_ERRBUFF_SIZE]; char* errbuf = new char[DP_ERRBUF_SIZE];
dp_handle * newhandle = dp_open_offline(argv[1], errbuf); dp_handle * newhandle = dp_open_offline(argv[1], errbuf);
dp_addcb (newhandle, dp_packet_tcp, process_tcp); dp_addcb (newhandle, dp_packet_tcp, process_tcp);
@@ -25,5 +25,4 @@ int main (int argc, char ** argv)
{ {
std::cout << "Error dispatching: " << dp_geterr(newhandle); std::cout << "Error dispatching: " << dp_geterr(newhandle);
} }
} }

View File

@@ -111,7 +111,7 @@ void get_info_by_linkname (char * pid, char * linkname) {
/* updates the `inodeproc' inode-to-prg_node /* updates the `inodeproc' inode-to-prg_node
* for all inodes belonging to this PID * for all inodes belonging to this PID
* (/proc/pid/fd/*) * (/proc/pid/fd/42)
* */ * */
void get_info_for_pid(char * pid) { void get_info_for_pid(char * pid) {
size_t dirlen = 10 + strlen(pid); size_t dirlen = 10 + strlen(pid);

View File

@@ -345,7 +345,8 @@ int main (int argc, char** argv)
if (newhandle != NULL) if (newhandle != NULL)
{ {
/* The following code solves sf.net bug 1019381, but is only available /* The following code solves sf.net bug 1019381, but is only available
* in newer versions (from 0.8 it seems) of libpcap */ * in newer versions (from 0.8 it seems) of libpcap
*/
if (dp_setnonblock (newhandle, 1, errbuf) == -1) if (dp_setnonblock (newhandle, 1, errbuf) == -1)
{ {
// ERROR // ERROR
@@ -359,29 +360,54 @@ int main (int argc, char** argv)
signal (SIGALRM, &alarm_cb); signal (SIGALRM, &alarm_cb);
signal (SIGINT, &quit_cb); signal (SIGINT, &quit_cb);
alarm (refreshdelay); alarm (refreshdelay);
fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n"); fprintf(stderr, "Waiting for first packet to arrive (see sourceforge.net bug 1019381)\n");
// Main loop:
//
// Walks though the 'handles' list, which contains handles opened in non-blocking mode.
// This causes the CPU utilisation to go up to 100%. This is tricky:
while (1) while (1)
{ {
bool packets_read = false;
handle * current_handle = handles; handle * current_handle = handles;
while (current_handle != NULL) while (current_handle != NULL)
{ {
struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs)); struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));
userdata->sa_family = AF_UNSPEC; userdata->sa_family = AF_UNSPEC;
currentdevice = current_handle->devicename; currentdevice = current_handle->devicename;
dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs)); int retval = dp_dispatch (current_handle->content, -1, (u_char *)userdata, sizeof (struct dpargs));
if (retval == -1 || retval == -2)
{
std::cerr << "Error dispatching" << std::endl;
}
else if (retval != 0)
{
packets_read = true;
}
free (userdata); free (userdata);
current_handle = current_handle->next; current_handle = current_handle->next;
} }
if ((!DEBUG)&&(!tracemode)) { if ((!DEBUG)&&(!tracemode))
{
// handle user input // handle user input
ui_tick(); ui_tick();
} }
if (needrefresh) if (needrefresh)
{ {
do_refresh(); do_refresh();
needrefresh = false; needrefresh = false;
} }
// If no packets were read at all this iteration, pause to prevent 100%
// CPU utilisation;
if (!packets_read)
{
usleep(100);
}
} }
} }

View File

@@ -46,6 +46,7 @@ public:
/* the process makes a copy of the device name and name. */ /* the process makes a copy of the device name and name. */
Process (unsigned long m_inode, char * m_devicename, char * m_name = NULL) Process (unsigned long m_inode, char * m_devicename, char * m_name = NULL)
{ {
//std::cout << "ARN: Process created with dev " << m_devicename << std::endl;
if (DEBUG) if (DEBUG)
std::cout << "PROC: Process created at " << this << std::endl; std::cout << "PROC: Process created at " << this << std::endl;
inode = m_inode; inode = m_inode;