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
man8 := $(DESTDIR)/share/man/man8/
all: nethogs decpcap_test
all: nethogs decpcap_test nethogs_testsum
#CFLAGS=-g -Wall
CFLAGS=-O2
CFLAGS=-g -Wall
#CFLAGS=-O2
OBJS=packet.o connection.o process.o refresh.o decpcap.o cui.o inode2prog.o
.PHONY: tgz
@@ -28,6 +28,8 @@ install: nethogs nethogs.8
nethogs: nethogs.cpp $(OBJS)
$(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
$(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);
sent_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())
{
sumSent += packet->len;
sent_packets->add(packet);
refpacket = new Packet (*packet);
} else {
sumRecv += packet->len;
recv_packets->add(packet);
refpacket = packet->newInverted();
}
lastpacket = packet->time.tv_sec;
if (DEBUG)
std::cout << "New reference packet created at " << refpacket << std::endl;
sumSent = 0;
sumRecv = 0;
}
Connection::~Connection ()
@@ -126,12 +132,21 @@ void Connection::add (Packet * packet)
lastpacket = packet->time.tv_sec;
if (packet->Outgoing())
{
if (DEBUG)
{
std::cout << "Outgoing: " << packet->len << std::endl;
}
sumSent += packet->len;
sent_packets->add (packet);
}
else
{
if (DEBUG)
{
std::cout << "Incoming: " << packet->len << std::endl;
}
sumRecv += packet->len;
std::cout << "sumRecv now: " << sumRecv << std::endl;
recv_packets->add (packet);
}
}
@@ -168,7 +183,7 @@ Connection * findConnection (Packet * packet)
* Returns sum of sent 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;

View File

@@ -73,7 +73,7 @@ public:
/* sums up the total bytes used
* 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 */
/* the reference packet is always *outgoing*. */

83
cui.cpp
View File

@@ -20,15 +20,17 @@ extern Process * unknownip;
// sort on sent or received?
bool sortRecv = true;
// viewMode: kb/s or total
int viewMode = 0;
int VIEWMODE_KBPS = 0;
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
{
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)
{
@@ -116,10 +118,18 @@ void Line::show (int row)
{
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)
{
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 ");
}
}
int GreatestFirst (const void * ma, const void * mb)
@@ -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)
{
return (((double)bytes) / PERIOD) / 1024;
@@ -233,7 +251,7 @@ void getkbps (Process * curproc, float * recvd, float * sent)
else
{
u_int32_t sent = 0, recv = 0;
curconn->getVal()->sumanddel(curtime, &sent, &recv);
curconn->getVal()->sumanddel(curtime, &recv, &sent);
sum_sent += sent;
sum_recv += recv;
previous = curconn;
@@ -245,7 +263,7 @@ void getkbps (Process * curproc, float * recvd, float * sent)
}
/** 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,
sum_recv = 0;
@@ -257,8 +275,39 @@ void gettotal(Process * curproc, float * recvd, float * sent)
sum_recv += conn->sumRecv;
curconn = curconn->getNext();
}
*recvd = tokbps(sum_recv);
*sent = tokbps(sum_sent);
//std::cout << "Sum sent: " << sum_sent << std::endl;
//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
@@ -335,11 +384,23 @@ void do_refresh()
if (viewMode == VIEWMODE_KBPS)
{
std::cout << "kbps viemode" << std::endl;
getkbps (curproc->getVal(), &value_recv, &value_sent);
}
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
{
@@ -354,7 +415,7 @@ void do_refresh()
assert (curproc->getVal()->pid >= 0);
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);
previousproc = curproc;
curproc = curproc->next;
@@ -399,8 +460,12 @@ void do_refresh()
if (viewMode == VIEWMODE_KBPS)
{
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) {
mvprintw (3+1+i, 73, "KB ");
} else if (viewMode == VIEWMODE_TOTAL_MB) {
mvprintw (3+1+i, 73, "MB ");
}
attroff(A_REVERSE);
mvprintw (4+1+i, 0, "");

View File

@@ -7,6 +7,8 @@
#include <pcap.h>
#include "decpcap.h"
#define DP_DEBUG 0
/* functions to set up a handle (which is basically just a pcap handle) */
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)
{
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);
if (handle->callback[dp_packet_ip] != NULL)

View File

@@ -2,7 +2,7 @@
#include <stdio.h>
#include <pcap.h>
#define DP_ERRBUFF_SIZE PCAP_ERRBUF_SIZE
#define DP_ERRBUF_SIZE PCAP_ERRBUF_SIZE
/* definitions */
@@ -24,6 +24,7 @@ enum dp_packet_type {
};*/
/*struct dp_header {
* pcap
};*/
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) {
std::cout << "Callback for processing TCP packet called" << std::endl;
return 0;
}
int main (int argc, char ** argv)
{
if (argc < 2)
@@ -16,7 +16,7 @@ int main (int argc, char ** argv)
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_addcb (newhandle, dp_packet_tcp, process_tcp);
@@ -25,5 +25,4 @@ int main (int argc, char ** argv)
{
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
* for all inodes belonging to this PID
* (/proc/pid/fd/*)
* (/proc/pid/fd/42)
* */
void get_info_for_pid(char * pid) {
size_t dirlen = 10 + strlen(pid);

View File

@@ -345,7 +345,8 @@ int main (int argc, char** argv)
if (newhandle != NULL)
{
/* 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)
{
// ERROR
@@ -359,29 +360,54 @@ int main (int argc, char** argv)
signal (SIGALRM, &alarm_cb);
signal (SIGINT, &quit_cb);
alarm (refreshdelay);
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)
{
bool packets_read = false;
handle * current_handle = handles;
while (current_handle != NULL)
{
struct dpargs * userdata = (dpargs *) malloc (sizeof (struct dpargs));
userdata->sa_family = AF_UNSPEC;
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);
current_handle = current_handle->next;
}
if ((!DEBUG)&&(!tracemode)) {
if ((!DEBUG)&&(!tracemode))
{
// handle user input
ui_tick();
}
if (needrefresh)
{
do_refresh();
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. */
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)
std::cout << "PROC: Process created at " << this << std::endl;
inode = m_inode;