From 76afed26b73fb3ca73cc63c6c085dc542dbe1071 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Tue, 24 Jun 2008 20:01:10 +0000 Subject: [PATCH] bugtracking mode, performance improvement by earlier caching of inode2pid data --- connection.cpp | 26 +++++++++++++++++++++----- cui.cpp | 3 ++- inode2prog.cpp | 22 +++++++++++++++++++++- inode2prog.h | 3 +++ nethogs.cpp | 16 +++++++++------- packet.cpp | 2 +- process.cpp | 46 ++++++++++++++++++++++++++++++++++++++-------- process.h | 1 + 8 files changed, 96 insertions(+), 23 deletions(-) diff --git a/connection.cpp b/connection.cpp index 8c6df0f..f65171d 100644 --- a/connection.cpp +++ b/connection.cpp @@ -154,18 +154,33 @@ void Connection::add (Packet * packet) } } -/* finds connection to which this packet belongs. +/* + * finds connection to which this packet belongs. * a packet belongs to a connection if it matches - * to its reference packet */ + * to its reference packet + */ Connection * findConnection (Packet * packet) { ConnList * current = connections; - Packet * invertedPacket = packet->newInverted(); while (current != NULL) { /* the reference packet is always *outgoing* */ - if ((packet->match(current->val->refpacket)) - || (invertedPacket->match(current->val->refpacket))) + if (packet->match(current->val->refpacket)) + { + return current->val; + } + + current = current->next; + } + + // Try again, now with the packet inverted: + current = connections; + Packet * invertedPacket = packet->newInverted(); + + while (current != NULL) + { + /* the reference packet is always *outgoing* */ + if (invertedPacket->match(current->val->refpacket)) { delete invertedPacket; return current->val; @@ -173,6 +188,7 @@ Connection * findConnection (Packet * packet) current = current->next; } + delete invertedPacket; return NULL; } diff --git a/cui.cpp b/cui.cpp index 1338008..8af8917 100644 --- a/cui.cpp +++ b/cui.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -386,7 +387,7 @@ void do_refresh() if (viewMode == VIEWMODE_KBPS) { - std::cout << "kbps viemode" << std::endl; + //std::cout << "kbps viemode" << std::endl; getkbps (curproc->getVal(), &value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_KB) diff --git a/inode2prog.cpp b/inode2prog.cpp index 7760f0a..2774bcb 100644 --- a/inode2prog.cpp +++ b/inode2prog.cpp @@ -15,6 +15,8 @@ #include "inode2prog.h" +extern bool bughuntmode; + /* maps from inode to program-struct */ std::map inodeproc; @@ -193,11 +195,29 @@ struct prg_node * findPID (unsigned long inode) struct prg_node * node = inodeproc[inode]; if (node != NULL) + { + if (bughuntmode) + { + std::cout << ":) Found pid in inodeproc table" << std::endl; + } return node; + } reread_mapping(); - return inodeproc[inode]; + struct prg_node * retval = inodeproc[inode]; + if (bughuntmode) + { + if (retval == NULL) + { + std::cout << ":( No pid after inodeproc refresh" << std::endl; + } + else + { + std::cout << ":) Found pid after inodeproc refresh" << std::endl; + } + } + return retval; } void prg_cache_clear() {}; diff --git a/inode2prog.h b/inode2prog.h index d7edf61..bbaace5 100644 --- a/inode2prog.h +++ b/inode2prog.h @@ -14,3 +14,6 @@ struct prg_node { struct prg_node * findPID (unsigned long inode); void prg_cache_clear(); + +// reread the inode-to-prg_node-mapping +void reread_mapping (); diff --git a/nethogs.cpp b/nethogs.cpp index 13084a1..760cc36 100644 --- a/nethogs.cpp +++ b/nethogs.cpp @@ -31,6 +31,7 @@ extern Process * unknownudp; unsigned refreshdelay = 1; bool tracemode = false; +bool bughuntmode = false; bool needrefresh = true; //packet_type packettype = packet_ethernet; //dp_link_type linktype = dp_link_ethernet; @@ -89,7 +90,7 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p curtime = header->ts; - /* TODO get info from userdata, then call getPacket */ + /* get info from userdata, then call getPacket */ Packet * packet; switch (args->sa_family) { @@ -101,9 +102,6 @@ int process_tcp (u_char * userdata, const dp_header * header, const u_char * m_p break; } - //if (DEBUG) - // std::cout << "Got packet from " << packet->gethashstring() << std::endl; - Connection * connection = findConnection(packet); if (connection != NULL) @@ -229,12 +227,13 @@ static void versiondisplay(void) static void help(void) { - //std::cerr << "usage: nethogs [-V] [-d seconds] [-t] [-p] [-f (eth|ppp))] [device [device [device ...]]]\n"; - std::cerr << "usage: nethogs [-V] [-d seconds] [-t] [-p] [device [device [device ...]]]\n"; + //std::cerr << "usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [-f (eth|ppp))] [device [device [device ...]]]\n"; + std::cerr << "usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [device [device [device ...]]]\n"; std::cerr << " -V : prints version.\n"; std::cerr << " -d : delay for update refresh rate in seconds. default is 1.\n"; std::cerr << " -t : tracemode.\n"; //std::cerr << " -f : format of packets on interface, default is eth.\n"; + std::cerr << " -b : bughunt mode - implies tracemode.\n"; std::cerr << " -p : sniff in promiscious mode (not recommended).\n"; std::cerr << " device : device(s) to monitor. default is eth0\n"; std::cerr << std::endl; @@ -284,6 +283,9 @@ int main (int argc, char** argv) exit(0); case 'h': help(); exit(0); + case 'b': bughuntmode = true; + tracemode = true; + break; case 't': tracemode = true; break; case 'p': promisc = 1; @@ -324,7 +326,7 @@ int main (int argc, char** argv) } if (NEEDROOT && (getuid() != 0)) - forceExit("You need to be root to run NetHogs !"); + forceExit("You need to be root to run NetHogs!"); char errbuf[PCAP_ERRBUF_SIZE]; diff --git a/packet.cpp b/packet.cpp index a858be3..700ecfd 100644 --- a/packet.cpp +++ b/packet.cpp @@ -43,7 +43,7 @@ void getLocal (const char *device, bool tracemode) } strcpy(iFreq.ifr_name, device); if(ioctl(sock, SIOCGIFADDR, &iFreq)<0){ - forceExit("ioctl failed while establishing local IP for device ", device); + forceExit("ioctl failed while establishing local IP for selected device ", device); } saddr=(struct sockaddr_in*)&iFreq.ifr_addr; local_addrs = new local_addr (saddr->sin_addr.s_addr, local_addrs); diff --git a/process.cpp b/process.cpp index 5bf0611..a9beaee 100644 --- a/process.cpp +++ b/process.cpp @@ -238,7 +238,11 @@ Process * findProcess (unsigned long inode) } /* check if we have identified any previously unknown - * connections are now known */ + * connections are now known + * + * When this is the case, something weird is going on. + * This function is only called in bughunt-mode + */ void reviewUnknown () { ConnList * curr_conn = unknowntcp->connections; @@ -251,8 +255,8 @@ void reviewUnknown () Process * proc = findProcess (inode); if (proc != unknowntcp && proc != NULL) { - if (DEBUG) - std::cout << "ITP: WARNING: Previously unknown inode " << inode << " now got process...??\n"; + if (DEBUG || bughuntmode) + std::cout << "FIXME: Previously unknown inode " << inode << " now got process - apparently it makes sense to review unknown connections\n"; /* Yay! - but how can this happen? */ if (!ROBUST) assert(false); @@ -327,7 +331,7 @@ Process * getProcess (unsigned long inode, char * devicename) if (node == NULL) { - if (DEBUG) + if (DEBUG || bughuntmode) std::cout << "No PID information for inode " << inode << std::endl; return unknowntcp; } @@ -386,11 +390,28 @@ Process * getProcess (Connection * connection, char * devicename) if (inode == 0) { // no? refresh and check conn/inode table -#if DEBUG - std::cout << "LOC: new connection not in connection-to-inode table.\n"; -#endif + if (bughuntmode) + { + std::cout << "? new connection not in connection-to-inode table before refresh.\n"; + } + // refresh the inode->pid table first. Presumably processing the renewed connection->inode table + // is slow, making this worthwhile. + // We take the fact for granted that we might already know the inode->pid (unlikely anyway if we + // haven't seen the connection->inode yet though). + reread_mapping(); refreshconninode(); inode = conninode[connection->refpacket->gethashstring()]; + if (bughuntmode) + { + if (inode == 0) + { + std::cout << ":( inode for connection not found after refresh.\n"; + } + else + { + std::cout << ":) inode for connection found after refresh.\n"; + } + } #if REVERSEHACK if (inode == 0) { @@ -406,7 +427,7 @@ Process * getProcess (Connection * connection, char * devicename) if (inode == 0) { delete reversepacket; - if (DEBUG) + if (bughuntmode || DEBUG) std::cout << "LOC: " << connection->refpacket->gethashstring() << " STILL not in connection-to-inode table - adding to the unknown process\n"; unknowntcp->connections = new ConnList (connection, unknowntcp->connections); return unknowntcp; @@ -417,6 +438,15 @@ Process * getProcess (Connection * connection, char * devicename) } #endif } + else if (bughuntmode) + { + std::cout << ";) new connection in connection-to-inode table before refresh.\n"; + } + + if (bughuntmode) + { + std::cout << " inode # " << inode << std::endl; + } Process * proc; if (inode == 0) { diff --git a/process.h b/process.h index af8824f..2cdce4b 100644 --- a/process.h +++ b/process.h @@ -6,6 +6,7 @@ #include "connection.h" extern bool tracemode; +extern bool bughuntmode; void check_all_procs ();