Add MB/s and GB/s view modes

- Refactored units presentation into a lookup table
- Other minor refactoring
- Updated man page
- Cleaned up trailing white space in the vicinity
This commit is contained in:
Peter M. Petrakis
2018-12-02 11:47:33 -05:00
parent d5c5078b4a
commit 677baffe6a
6 changed files with 73 additions and 47 deletions

View File

@@ -7,7 +7,7 @@ nethogs \- Net top tool grouping bandwidth per process
.ft B .ft B
.B nethogs .B nethogs
.RB [ "\-h" ] .RB [ "\-h" ]
.RB [ "\-V" ] .RB [ "\-V" ]
.RB [ "\-d" ] .RB [ "\-d" ]
.RB [ "\-v" ] .RB [ "\-v" ]
.RB [ "\-t" ] .RB [ "\-t" ]
@@ -18,7 +18,7 @@ nethogs \- Net top tool grouping bandwidth per process
.RB [ "\-l" ] .RB [ "\-l" ]
.RI [device(s)] .RI [device(s)]
.SH DESCRIPTION .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 .SS Options
.TP .TP
@@ -58,7 +58,7 @@ to monitor. By default eth0 is being used
.SH "INTERACTIVE CONTROL" .SH "INTERACTIVE CONTROL"
.TP .TP
m m
cycle between display modes (KB/s, KB, B, MB) cycle between display modes (KB/s, KB, B, MB, MB/s, GB/s)
.TP .TP
l l
display command line display command line

View File

@@ -64,6 +64,9 @@ const char *COLUMN_FORMAT_PID = "%7d";
const char *COLUMN_FORMAT_SENT = "%11.3f"; const char *COLUMN_FORMAT_SENT = "%11.3f";
const char *COLUMN_FORMAT_RECEIVED = "%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 { class Line {
public: public:
Line(const char *name, const char *cmdline, double n_recv_value, 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_sent, COLUMN_FORMAT_SENT, sent_value);
mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, recv_value); mvprintw(row, column_offset_received, COLUMN_FORMAT_RECEIVED, recv_value);
if (viewMode == VIEWMODE_KBPS) { mvaddstr(row, column_offset_unit, desc_view_mode[viewMode]);
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 ");
}
} }
void Line::log() { void Line::log() {
@@ -239,7 +234,7 @@ int get_devlen(Line *lines[], int nproc, int rows)
if(devlen > MAX_COLUMN_WIDTH_DEV) if(devlen > MAX_COLUMN_WIDTH_DEV)
devlen = MAX_COLUMN_WIDTH_DEV; devlen = MAX_COLUMN_WIDTH_DEV;
return devlen; return devlen;
} }
@@ -355,8 +350,8 @@ void show_ncurses(Line *lines[], int nproc) {
cols = PROGNAME_WIDTH; cols = PROGNAME_WIDTH;
//issue #110 - maximum devicename length min=5, max=15 //issue #110 - maximum devicename length min=5, max=15
int devlen = get_devlen(lines, nproc, rows); int devlen = get_devlen(lines, nproc, rows);
proglen = cols - 50 - devlen; proglen = cols - 50 - devlen;
@@ -381,15 +376,7 @@ void show_ncurses(Line *lines[], int nproc) {
int totalrow = std::min(rows - 1, 3 + 1 + i); int totalrow = std::min(rows - 1, 3 + 1 + i);
mvprintw(totalrow, 0, " TOTAL %-*.*s %-*.*s %11.3f %11.3f ", mvprintw(totalrow, 0, " TOTAL %-*.*s %-*.*s %11.3f %11.3f ",
proglen, proglen, "", devlen,devlen, "", sent_global, recv_global); proglen, proglen, "", devlen,devlen, "", sent_global, recv_global);
if (viewMode == VIEWMODE_KBPS) { mvprintw(3 + 1 + i, cols - COLUMN_WIDTH_UNIT, desc_view_mode[viewMode]);
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 ");
}
attroff(A_REVERSE); attroff(A_REVERSE);
mvprintw(totalrow + 1, 0, ""); mvprintw(totalrow + 1, 0, "");
refresh(); refresh();
@@ -400,7 +387,7 @@ void do_refresh() {
refreshconninode(); refreshconninode();
refreshcount++; refreshcount++;
if (viewMode == VIEWMODE_KBPS) { if (viewMode == VIEWMODE_KBPS || viewMode == VIEWMODE_MBPS || viewMode == VIEWMODE_GBPS) {
remove_timed_out_processes(); remove_timed_out_processes();
} }
@@ -425,6 +412,10 @@ void do_refresh() {
if (viewMode == VIEWMODE_KBPS) { if (viewMode == VIEWMODE_KBPS) {
curproc->getVal()->getkbps(&value_recv, &value_sent); 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) { } else if (viewMode == VIEWMODE_TOTAL_KB) {
curproc->getVal()->gettotalkb(&value_recv, &value_sent); curproc->getVal()->gettotalkb(&value_recv, &value_sent);
} else if (viewMode == VIEWMODE_TOTAL_MB) { } else if (viewMode == VIEWMODE_TOTAL_MB) {

View File

@@ -35,7 +35,7 @@ static void help(bool iserror) {
output << " -d : delay for update refresh rate in seconds. default " output << " -d : delay for update refresh rate in seconds. default "
"is 1.\n"; "is 1.\n";
output << " -v : view mode (0 = KB/s, 1 = total KB, 2 = total B, 3 " 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 << " -c : number of updates. default is 0 (unlimited).\n";
output << " -t : tracemode.\n"; output << " -t : tracemode.\n";
// output << " -f : format of packets on interface, default is // 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 << " -s : sort output by sent column.\n";
output << " -l : display command line.\n"; output << " -l : display command line.\n";
output << " -a : monitor all devices, even loopback/stopped ones.\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)." output << " -f : EXPERIMENTAL: specify string pcap filter (like tcpdump)."
" This may be removed or changed in a future version.\n"; " This may be removed or changed in a future version.\n";
output << " device : device(s) to monitor. default is all " 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 << " s: sort by SENT traffic\n";
output << " r: sort by RECEIVE traffic\n"; output << " r: sort by RECEIVE traffic\n";
output << " l: display command line\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 */) { void quit_cb(int /* i */) {

View File

@@ -63,11 +63,15 @@
#define PROGNAME_WIDTH 512 #define PROGNAME_WIDTH 512
// viewMode: how to represent numbers // viewMode: how to represent numbers
#define VIEWMODE_KBPS 0 enum {
#define VIEWMODE_TOTAL_KB 1 VIEWMODE_KBPS,
#define VIEWMODE_TOTAL_B 2 VIEWMODE_TOTAL_KB,
#define VIEWMODE_TOTAL_MB 3 VIEWMODE_TOTAL_B,
#define VIEWMODE_COUNT 4 VIEWMODE_TOTAL_MB,
VIEWMODE_MBPS,
VIEWMODE_GBPS,
VIEWMODE_COUNT
};
#define NORETURN __attribute__((__noreturn__)) #define NORETURN __attribute__((__noreturn__))

View File

@@ -65,17 +65,23 @@ Process *unknownudp;
Process *unknownip; Process *unknownip;
ProcList *processes; ProcList *processes;
float tomb(u_int64_t bytes) { return ((double)bytes) / 1024 / 1024; } #define KB (1UL << 10)
float tokb(u_int64_t bytes) { return ((double)bytes) / 1024; } #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() { void process_init() {
unknowntcp = new Process(0, "", "unknown TCP"); unknowntcp = new Process(0, "", "unknown TCP");
processes = new ProcList(unknowntcp, NULL); processes = new ProcList(unknowntcp, NULL);
if(catchall) if(catchall)
{ {
unknownudp = new Process (0, "", "unknown UDP"); unknownudp = new Process (0, "", "unknown UDP");
processes = new ProcList (unknownudp, processes); processes = new ProcList (unknownudp, processes);
// unknownip = new Process (0, "", "unknown IP"); // unknownip = new Process (0, "", "unknown IP");
@@ -96,25 +102,23 @@ int Process::getLastPacket() {
return lastpacket; return lastpacket;
} }
/** Get the kb/s values for this process */ /** get total values for this process for only active connections */
void Process::getkbps(float *recvd, float *sent) { static void sum_active_connections(Process* process_ptr, u_int64_t& sum_sent, u_int64_t& sum_recv) {
u_int64_t sum_sent = 0, sum_recv = 0; /* walk though all process_ptr process's connections, and sum
/* walk though all this process's connections, and sum
* them up */ * them up */
ConnList *curconn = this->connections; ConnList *curconn = process_ptr->connections;
ConnList *previous = NULL; ConnList *previous = NULL;
while (curconn != NULL) { while (curconn != NULL) {
if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT) { if (curconn->getVal()->getLastPacket() <= curtime.tv_sec - CONNTIMEOUT) {
/* capture sent and received totals before deleting */ /* capture sent and received totals before deleting */
this->sent_by_closed_bytes += curconn->getVal()->sumSent; process_ptr->sent_by_closed_bytes += curconn->getVal()->sumSent;
this->rcvd_by_closed_bytes += curconn->getVal()->sumRecv; process_ptr->rcvd_by_closed_bytes += curconn->getVal()->sumRecv;
/* stalled connection, remove. */ /* stalled connection, remove. */
ConnList *todelete = curconn; ConnList *todelete = curconn;
Connection *conn_todelete = curconn->getVal(); Connection *conn_todelete = curconn->getVal();
curconn = curconn->getNext(); curconn = curconn->getNext();
if (todelete == this->connections) if (todelete == process_ptr->connections)
this->connections = curconn; process_ptr->connections = curconn;
if (previous != NULL) if (previous != NULL)
previous->setNext(curconn); previous->setNext(curconn);
delete (todelete); delete (todelete);
@@ -128,10 +132,35 @@ void Process::getkbps(float *recvd, float *sent) {
curconn = curconn->getNext(); 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); *recvd = tokbps(sum_recv);
*sent = tokbps(sum_sent); *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 */ /** get total values for this process */
void Process::gettotal(u_int64_t *recvd, u_int64_t *sent) { void Process::gettotal(u_int64_t *recvd, u_int64_t *sent) {
u_int64_t sum_sent = 0, sum_recv = 0; u_int64_t sum_sent = 0, sum_recv = 0;

View File

@@ -93,6 +93,8 @@ public:
void gettotal(u_int64_t *recvd, u_int64_t *sent); void gettotal(u_int64_t *recvd, u_int64_t *sent);
void getkbps(float *recvd, float *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 gettotalmb(float *recvd, float *sent);
void gettotalkb(float *recvd, float *sent); void gettotalkb(float *recvd, float *sent);
void gettotalb(float *recvd, float *sent); void gettotalb(float *recvd, float *sent);