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:
@@ -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
|
||||||
|
|||||||
35
src/cui.cpp
35
src/cui.cpp
@@ -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) {
|
||||||
|
|||||||
@@ -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 */) {
|
||||||
|
|||||||
@@ -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__))
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user