diff --git a/doc/nethogs.8 b/doc/nethogs.8 index 7a3e9a2..a333ae7 100644 --- a/doc/nethogs.8 +++ b/doc/nethogs.8 @@ -7,7 +7,7 @@ nethogs \- Net top tool grouping bandwidth per process .ft B .B nethogs .RB [ "\-h" ] -.RB [ "\-V" ] +.RB [ "\-V" ] .RB [ "\-d" ] .RB [ "\-v" ] .RB [ "\-t" ] @@ -18,7 +18,7 @@ nethogs \- Net top tool grouping bandwidth per process .RB [ "\-l" ] .RI [device(s)] .SH DESCRIPTION -NetHogs is a small 'net top' tool. Instead of breaking the traffic down per protocol or per subnet, like most such tools do, it groups bandwidth by process - and does not rely on a special kernel module to be loaded. So if there's suddenly a lot of network traffic, you can fire up NetHogs and immediately see which PID is causing this, and if it's some kind of spinning process, kill it. +NetHogs is a small 'net top' tool. Instead of breaking the traffic down per protocol or per subnet, like most such tools do, it groups bandwidth by process - and does not rely on a special kernel module to be loaded. So if there's suddenly a lot of network traffic, you can fire up NetHogs and immediately see which PID is causing this, and if it's some kind of spinning process, kill it. .SS Options .TP @@ -58,7 +58,7 @@ to monitor. By default eth0 is being used .SH "INTERACTIVE CONTROL" .TP m -cycle between display modes (KB/s, KB, B, MB) +cycle between display modes (KB/s, KB, B, MB, MB/s, GB/s) .TP l display command line diff --git a/src/cui.cpp b/src/cui.cpp index 12c3c7d..efb71a1 100644 --- a/src/cui.cpp +++ b/src/cui.cpp @@ -64,6 +64,9 @@ const char *COLUMN_FORMAT_PID = "%7d"; const char *COLUMN_FORMAT_SENT = "%11.3f"; const char *COLUMN_FORMAT_RECEIVED = "%11.3f"; +// All descriptions are padded to 6 characters in length with spaces +const char* const desc_view_mode[VIEWMODE_COUNT] = {"KB/sec", "KB ", "B ", "MB ", "MB/sec", "GB/sec"}; + class Line { public: Line(const char *name, const char *cmdline, double n_recv_value, @@ -207,15 +210,7 @@ void Line::show(int row, unsigned int proglen, unsigned int devlen) { mvprintw(row, column_offset_sent, COLUMN_FORMAT_SENT, sent_value); mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, recv_value); - if (viewMode == VIEWMODE_KBPS) { - mvaddstr(row, column_offset_unit, "KB/sec"); - } else if (viewMode == VIEWMODE_TOTAL_MB) { - mvaddstr(row, column_offset_unit, "MB "); - } else if (viewMode == VIEWMODE_TOTAL_KB) { - mvaddstr(row, column_offset_unit, "KB "); - } else if (viewMode == VIEWMODE_TOTAL_B) { - mvaddstr(row, column_offset_unit, "B "); - } + mvaddstr(row, column_offset_unit, desc_view_mode[viewMode]); } void Line::log() { @@ -239,7 +234,7 @@ int get_devlen(Line *lines[], int nproc, int rows) if(devlen > MAX_COLUMN_WIDTH_DEV) devlen = MAX_COLUMN_WIDTH_DEV; - + return devlen; } @@ -355,8 +350,8 @@ void show_ncurses(Line *lines[], int nproc) { cols = PROGNAME_WIDTH; - //issue #110 - maximum devicename length min=5, max=15 - int devlen = get_devlen(lines, nproc, rows); + //issue #110 - maximum devicename length min=5, max=15 + int devlen = get_devlen(lines, nproc, rows); proglen = cols - 50 - devlen; @@ -381,15 +376,7 @@ void show_ncurses(Line *lines[], int nproc) { int totalrow = std::min(rows - 1, 3 + 1 + i); mvprintw(totalrow, 0, " TOTAL %-*.*s %-*.*s %11.3f %11.3f ", proglen, proglen, "", devlen,devlen, "", sent_global, recv_global); - if (viewMode == VIEWMODE_KBPS) { - mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "KB/sec "); - } else if (viewMode == VIEWMODE_TOTAL_B) { - mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "B "); - } else if (viewMode == VIEWMODE_TOTAL_KB) { - mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "KB "); - } else if (viewMode == VIEWMODE_TOTAL_MB) { - mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, "MB "); - } + mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, desc_view_mode[viewMode]); attroff(A_REVERSE); mvprintw(totalrow + 1, 0, ""); refresh(); @@ -400,7 +387,7 @@ void do_refresh() { refreshconninode(); refreshcount++; - if (viewMode == VIEWMODE_KBPS) { + if (viewMode == VIEWMODE_KBPS || viewMode == VIEWMODE_MBPS || viewMode == VIEWMODE_GBPS) { remove_timed_out_processes(); } @@ -425,6 +412,10 @@ void do_refresh() { if (viewMode == VIEWMODE_KBPS) { curproc->getVal()->getkbps(&value_recv, &value_sent); + } else if (viewMode == VIEWMODE_MBPS) { + curproc->getVal()->getmbps(&value_recv, &value_sent); + } else if (viewMode == VIEWMODE_GBPS) { + curproc->getVal()->getgbps(&value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_KB) { curproc->getVal()->gettotalkb(&value_recv, &value_sent); } else if (viewMode == VIEWMODE_TOTAL_MB) { diff --git a/src/main.cpp b/src/main.cpp index f90ae2e..18c2b3f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,7 +35,7 @@ static void help(bool iserror) { output << " -d : delay for update refresh rate in seconds. default " "is 1.\n"; output << " -v : view mode (0 = KB/s, 1 = total KB, 2 = total B, 3 " - "= total MB). default is 0.\n"; + "= total MB, 4 = MB/s, 5 = GB/s). default is 0.\n"; output << " -c : number of updates. default is 0 (unlimited).\n"; output << " -t : tracemode.\n"; // output << " -f : format of packets on interface, default is @@ -44,7 +44,7 @@ static void help(bool iserror) { output << " -s : sort output by sent column.\n"; output << " -l : display command line.\n"; output << " -a : monitor all devices, even loopback/stopped ones.\n"; - output << " -C : capture TCP and UDP.\n"; + output << " -C : capture TCP and UDP.\n"; output << " -f : EXPERIMENTAL: specify string pcap filter (like tcpdump)." " This may be removed or changed in a future version.\n"; output << " device : device(s) to monitor. default is all " @@ -55,7 +55,7 @@ static void help(bool iserror) { output << " s: sort by SENT traffic\n"; output << " r: sort by RECEIVE traffic\n"; output << " l: display command line\n"; - output << " m: switch between total (KB, B, MB) and KB/s mode\n"; + output << " m: switch between total (KB, B, MB) and throughput (KB/s, MB/s, GB/s) mode\n"; } void quit_cb(int /* i */) { diff --git a/src/nethogs.h b/src/nethogs.h index 7457926..da1830e 100644 --- a/src/nethogs.h +++ b/src/nethogs.h @@ -63,11 +63,15 @@ #define PROGNAME_WIDTH 512 // viewMode: how to represent numbers -#define VIEWMODE_KBPS 0 -#define VIEWMODE_TOTAL_KB 1 -#define VIEWMODE_TOTAL_B 2 -#define VIEWMODE_TOTAL_MB 3 -#define VIEWMODE_COUNT 4 +enum { + VIEWMODE_KBPS, + VIEWMODE_TOTAL_KB, + VIEWMODE_TOTAL_B, + VIEWMODE_TOTAL_MB, + VIEWMODE_MBPS, + VIEWMODE_GBPS, + VIEWMODE_COUNT +}; #define NORETURN __attribute__((__noreturn__)) diff --git a/src/process.cpp b/src/process.cpp index 155f31a..f39509e 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -65,17 +65,23 @@ Process *unknownudp; Process *unknownip; ProcList *processes; -float tomb(u_int64_t bytes) { return ((double)bytes) / 1024 / 1024; } -float tokb(u_int64_t bytes) { return ((double)bytes) / 1024; } +#define KB (1UL << 10) +#define MB (1UL << 20) +#define GB (1UL << 30) -float tokbps(u_int64_t bytes) { return (((double)bytes) / PERIOD) / 1024; } +float tomb(u_int64_t bytes) { return ((double)bytes) / MB; } +float tokb(u_int64_t bytes) { return ((double)bytes) / KB; } + +float tokbps(u_int64_t bytes) { return (((double)bytes) / PERIOD) / KB; } +float tombps(u_int64_t bytes) { return (((double)bytes) / PERIOD) / MB; } +float togbps(u_int64_t bytes) { return (((double)bytes) / PERIOD) / GB; } void process_init() { unknowntcp = new Process(0, "", "unknown TCP"); processes = new ProcList(unknowntcp, NULL); if(catchall) - { + { unknownudp = new Process (0, "", "unknown UDP"); processes = new ProcList (unknownudp, processes); // unknownip = new Process (0, "", "unknown IP"); @@ -96,25 +102,23 @@ int Process::getLastPacket() { return lastpacket; } -/** Get the kb/s values for this process */ -void Process::getkbps(float *recvd, float *sent) { - u_int64_t sum_sent = 0, sum_recv = 0; - - /* walk though all this process's connections, and sum +/** get total values for this process for only active connections */ +static void sum_active_connections(Process* process_ptr, u_int64_t& sum_sent, u_int64_t& sum_recv) { + /* walk though all process_ptr process's connections, and sum * them up */ - ConnList *curconn = this->connections; + ConnList *curconn = process_ptr->connections; ConnList *previous = NULL; while (curconn != NULL) { if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT) { /* capture sent and received totals before deleting */ - this->sent_by_closed_bytes += curconn->getVal()->sumSent; - this->rcvd_by_closed_bytes += curconn->getVal()->sumRecv; + process_ptr->sent_by_closed_bytes += curconn->getVal()->sumSent; + process_ptr->rcvd_by_closed_bytes += curconn->getVal()->sumRecv; /* stalled connection, remove. */ ConnList *todelete = curconn; Connection *conn_todelete = curconn->getVal(); curconn = curconn->getNext(); - if (todelete == this->connections) - this->connections = curconn; + if (todelete == process_ptr->connections) + process_ptr->connections = curconn; if (previous != NULL) previous->setNext(curconn); delete (todelete); @@ -128,10 +132,35 @@ void Process::getkbps(float *recvd, float *sent) { curconn = curconn->getNext(); } } +} + +/** Get the kb/s values for this process */ +void Process::getkbps(float *recvd, float *sent) { + u_int64_t sum_sent = 0, sum_recv = 0; + + sum_active_connections(this, sum_sent, sum_recv); *recvd = tokbps(sum_recv); *sent = tokbps(sum_sent); } +/** Get the mb/s values for this process */ +void Process::getmbps(float *recvd, float *sent) { + u_int64_t sum_sent = 0, sum_recv = 0; + + sum_active_connections(this, sum_sent, sum_recv); + *recvd = tombps(sum_recv); + *sent = tombps(sum_sent); +} + +/** Get the gb/s values for this process */ +void Process::getgbps(float *recvd, float *sent) { + u_int64_t sum_sent = 0, sum_recv = 0; + + sum_active_connections(this, sum_sent, sum_recv); + *recvd = togbps(sum_recv); + *sent = togbps(sum_sent); +} + /** get total values for this process */ void Process::gettotal(u_int64_t *recvd, u_int64_t *sent) { u_int64_t sum_sent = 0, sum_recv = 0; diff --git a/src/process.h b/src/process.h index 4e69711..3e293a4 100644 --- a/src/process.h +++ b/src/process.h @@ -93,6 +93,8 @@ public: void gettotal(u_int64_t *recvd, u_int64_t *sent); void getkbps(float *recvd, float *sent); + void getmbps(float *recvd, float *sent); + void getgbps(float *recvd, float *sent); void gettotalmb(float *recvd, float *sent); void gettotalkb(float *recvd, float *sent); void gettotalb(float *recvd, float *sent);