#!/usr/bin/perl
# **********************************************************************
# $Log: bang (BANdwidth Get),v $
# Revision 1.4  2002/05/02 17:08:58
# Author: bang@69link.net (Jonas Lindqvist)
# Initial revision
#
# **********************************************************************
#	Rev	Datum	Sign	Beskrivning
#	1.4	020502	jl	Minor cosmetica
#	1.3	020219	jl	Found/fixed a bug when using -c (count)
#	1.0	020107	jl	Created a little util with the looks of "ping".
#				Its called "bang" and measures bandwith.
# **********************************************************************
# Band (BANdwidth Get)
$VERSION = "1.4";
$SIG{INT} = \&endit;	# Catch CTRL+C and send it to sub endit.

$argc = @ARGV;
if ($argc eq 0) {	# Print usage if no arguments
	usage();
	exit();
}
for ($x = 0; $x+1 <= $argc; $x++) {	#loop through argumentlist
	if ($ARGV[$x] eq "--help") {	# print help and exit
		help();
		exit();
	} if ($ARGV[$x] eq "-c") {		# if flag "-c" set, $count = argument
		$count = $ARGV[$x+1];
		$x = $x + 2;
	} else {
		$count = 18446744073709551615;	# quadword
	}
	if ($ARGV[$x] eq "-s") {		# if flag "-s" set, $sleep = argument
		$sleep = $ARGV[$x+1];
		if ($sleep == 0) { $sleep = 1;}
		$x = $x + 2;
	} else {
		$sleep = 1;
	}
	if ($ARGV[$x] eq "-n") {		# numeric output
		$x++;
		$numeric = 1;
	} else {
		$numeric = 0;
	}
		if (! $marked) {			# do this only once
		$net_if = $ARGV[$x];
	}
	$marked = 1;
}




##################################
# Main loop
#
($down1, $up1) = get_netinfo();
$down2 = $down1;
$up2 = $up1;
for ($x = 1; $x <= $count; $x++) {
	$down1 = $down2;
	$up1 = $up2;
	sleep $sleep;
	($down2, $up2) = get_netinfo();

	$down_spd = ($down2 - $down1) / $sleep;
	$up_spd = ($up2 - $up1) / $sleep;
	$accdown_spd = $accdown_spd + $down_spd;
	$accup_spd = $accup_spd + $up_spd;
	if (! $numeric) {
		printf ("RX=%s, TX=%s seq=%s time=%s\n", unit_prefix($down_spd), unit_prefix($up_spd), $x, $sleep);
	} else {
		printf ("RX=%s, TX=%s seq=%s time=%s\n", $down_spd, $up_spd, $x, $sleep);
	}

	if ($x == 1) { $lowup_spd = $up_spd; $lowdown_spd = $down_spd;}	# lowup/down shouldn't be 0 as default
	if ($maxup_spd < $up_spd) { $maxup_spd = $up_spd;}
	if ($lowup_spd > $up_spd) { $lowup_spd = $up_spd;}
	if ($maxdown_spd < $down_spd) { $maxdown_spd = $down_spd;}
	if ($lowdown_spd > $down_spd) { $lowdown_spd = $down_spd;}
	$averageup_spd = $accup_spd / $x;
	$averagedown_spd = $accdown_spd / $x;
}
endit();
exit();


##################################
sub get_netinfo
# Return column 2 and 10 from /proc/net/dev
{
	open(INFILE, "/proc/net/dev");
	@device = <INFILE>;
	close INFILE;
	foreach (@device) {
		@str = split(/[\ \:]+/, $_);		#Split with space as delimiter
		if ($str[1] eq $net_if) { last; }
	}
	unless ($str[1] eq $net_if) { die "Did not find interface: $net_if\n" }

	return $str[2], $str[10];
}


##################################
sub unit_prefix
# Function to convert numbers to a string with proper units eg: 1628652 = 1.6MB
{
	$size = $_[0];
	if ($size < 1024) {
		return sprintf("%.0fB", $size);
	} elsif (($size / 1024) < 1024) {
		return sprintf("%.0fKB", ($size/1024));
	} elsif (($size/(1024*1024)) < 1024) {
		return sprintf("%.1fMB", ($size/(1024*1024)));
	} elsif (($size/(1024*1024*1024)) < 1024) {
		return sprintf("%.1fGB", ($size/(1024*1024*1024)));
	} elsif (($size/(1024*1024*1024*1024)) < 1024) {
		return sprintf("%.1fTB", ($size/(1024*1024*1024*1024)));
	}
	return sprintf("ERROR");
}

##################################
sub usage()
# Write usage
{
	print "Bang v$VERSION\n";
	print "Usage: bang [-c count] [-s sampletime] [-n numeric] interface\n";
	print "       --help\n";
}

##################################
sub help()
# Write helptext
{
	usage();
	print "Example: bang -c 3 -s 7 eth1\n";
}


sub endit()
{
#	$SIG{INT} = \&endit;
	print "\n--- $net_if bandwitdh statistics ---\n";
	if (! $numeric) {
		printf ("RX bandwidth min/avg/max = %s/%s/%s\n", unit_prefix($lowdown_spd), unit_prefix($averagedown_spd), unit_prefix($maxdown_spd));
		printf ("TX bandwidth min/avg/max = %s/%s/%s\n", unit_prefix($lowup_spd), unit_prefix($averageup_spd), unit_prefix($maxup_spd));
	} else {
		printf ("RX bandwidth min/avg/max = %.0f/%.0f/%.0f\n", $lowdown_spd, $averagedown_spd, $maxdown_spd);
		printf ("TX bandwidth min/avg/max = %.0f/%.0f/%.0f\n", $lowup_spd, $averageup_spd, $maxup_spd);
	}
	exit();
}
