iftop unit
This article aims to clarify the units used in iftop, a popular network monitoring tool. A common point of confusion is whether iftop uses base 1000 or base 1024 for its data speed units. After thorough investigation, including code review, we can confirm that iftop uses base 1024 units, with some exceptions.
iftop unit basics
- Default: Uses bits (without
-B
option) - With
-B
option: Uses bytes - Unit base: 1024 for both bits and bytes, except when using log scale
- Log scale: Uses base 1000
notation in iftop
iftop uses abbreviated notation to display information compactly:
- Omits “ps” or “/s” to indicate “per second”
- Skips the “i” in binary prefixes (e.g., MiB), which can lead to confusion
recommended usage
To get the most informative output, use the following parameters:
iftop -nNBP -i eth0
Where:
-n
,-N
: Use numerical IPs and port numbers instead of names-B
: Display in bytes instead of bits-P
: Show ports for more detailed information-i eth0
: Specify the network interface to monitor
reading the output
When using bytes (-B
option), the units are displayed as follows:
Interpretation:
- All rates are per second
- All units are base 1024 (binary units)
- Columns represent 2-second, 10-second, and 40-second averages
- First row: Transfer rate (e.g., 14.0 MiB/s, 14.1 MiB/s, 14.2 MiB/s)
- Second row: Receive rate (e.g., 2.61 GiB/s, 2.62 GiB/s, 2.63 GiB/s)
- Third row: Total rate (sum of transfer and receive)
Note: When displaying cumulative total transfers (toggled with ‘T’ key), iftop uses base 1000 units.
conclusion
Understanding that iftop primarily uses base 1024 units (binary units) is crucial for accurate interpretation of network traffic data. The tool’s compact notation, while space-efficient, requires users to remember that ‘MB’ in iftop’s output actually represents MiB (Mebibytes) when the -B
option is used.
code analysis
Here are code snippets from the official iftop code base: https://code.blinkace.com/pdw/iftop
The converstion of units happens in https://code.blinkace.com/pdw/iftop/-/blob/master/ui_common.c
// --------------------- //
// Look at readable_size //
// --------------------- //
#define UNIT_DIVISIONS 4
char* unit_disp[][UNIT_DIVISIONS] = {
[OPTION_BW_BITS] = { "b", "Kb", "Mb", "Gb"},
[OPTION_BW_BYTES] = { "B", "KB", "MB", "GB"},
[OPTION_BW_PKTS] = { "p", "Kp", "Mp", "GB"},
};
/*
* Format a data size in human-readable format
*/
void readable_size(float n, char* buf, int bsize, int ksize,
option_bw_unit_t unit) {
int i = 0;
float size = 1;
/* Convert to bits? */
if (unit == OPTION_BW_BITS) {
n *= 8;
}
/* Force power of ten for pps */
if (unit == OPTION_BW_PKTS)
ksize = 1000;
while(1) {
if(n < size * 1000 || i >= UNIT_DIVISIONS - 1) {
snprintf(buf, bsize, " %4.0f%s", n / size, unit_disp[unit][i]);
break;
}
i++;
size *= ksize;
if(n < size * 10) {
snprintf(buf, bsize, " %4.2f%s", n / size, unit_disp[unit][i]);
break;
}
else if(n < size * 100) {
snprintf(buf, bsize, " %4.1f%s", n / size, unit_disp[unit][i]);
break;
}
}
}
// -------------------------------------------------------------------------------------------- //
// And this is how its called note ksize is 1024, which how the value what the value is divide by
// For 1000 base it would have been 1000; which we see only mentioned for log scale
// -------------------------------------------------------------------------------------------- //
iftop# grep -nirI readable_size
tui.c:90: readable_size(screen_line->sent[j], buf0_10, 10, 1024, options.bandwidth_unit);
tui.c:94: readable_size(screen_line->total_sent, buf0_10, 10, 1024, 1);
tui.c:100: readable_size(screen_line->recv[j], buf0_10, 10, 1024, options.bandwidth_unit);
tui.c:104: readable_size(screen_line->total_recv, buf0_10, 10, 1024, 1);
tui.c:118: readable_size(((host_pair_line *)&totals)->sent[j], buf0_10, 10, 1024, options.bandwidth_unit);
tui.c:125: readable_size(((host_pair_line *)&totals)->recv[j], buf0_10, 10, 1024, options.bandwidth_unit);
tui.c:132: readable_size(((host_pair_line *)&totals)->sent[j] + ((host_pair_line *)&totals)->recv[j], buf0_10, 10, 1024, options.bandwidth_unit);
tui.c:144: readable_size(peaksent / RESOLUTION, buf0_10, 10, 1024, options.bandwidth_unit);
tui.c:145: readable_size(peakrecv / RESOLUTION, buf1_10, 10, 1024, options.bandwidth_unit);
tui.c:146: readable_size(peaktotal / RESOLUTION, buf2_10, 10, 1024, options.bandwidth_unit);
tui.c:151: readable_size(history_totals.total_sent, buf0_10, 10, 1024, 1);
tui.c:152: readable_size(history_totals.total_recv, buf1_10, 10, 1024, 1);
tui.c:153: readable_size(history_totals.total_recv + history_totals.total_sent, buf2_10, 10, 1024, 1);
ui_common.c:127:void readable_size(float n, char* buf, int bsize, int ksize,
ui.c:158: readable_size(i, s, sizeof s, options.log_scale ? 1000 : 1024, options.bandwidth_unit); <======= only time its 1000 based is if there is logbased
ui.c:201: readable_size(n, buf, 10, 1024, unit);
ui.c:252: readable_size((totals->sent[j] + totals->recv[j]) , buf, 10, 1024, options.bandwidth_unit);
ui.c:387: readable_size(history_totals.total_sent, line, 10, 1024, cumunit);
ui.c:390: readable_size(history_totals.total_recv, line, 10, 1024, cumunit);
ui.c:393: readable_size(history_totals.total_recv + history_totals.total_sent, line, 10, 1024, cumunit);
ui.c:399: readable_size(peaksent / RESOLUTION, line, 10, 1024, options.bandwidth_unit);
ui.c:402: readable_size(peakrecv / RESOLUTION, line, 10, 1024, options.bandwidth_unit);
ui.c:405: readable_size(peaktotal / RESOLUTION, line, 10, 1024, options.bandwidth_unit);
ui_common.h:46:void readable_size(float, char*, int, int, option_bw_unit_t);