Commit 3904e45b authored by 's avatar
Browse files

Documentation updated


git-svn-id: file:///home/svn/mapi/trunk@811 8d5bb341-7cf1-0310-8cf6-ba355fef3186
parent 97ccd5c6
INTRODUCTION
ABW is application for passive monitoring of bandwidth usage and distribution
among protocols. It is written on top of DiMAPI (Distributed Monitoring
Application Interface). Primary advantages of monitoring bandwidth by ABW when
compared to using SNMP to read router interface byte counters are the following:
- We can distinquish bandwidth used by different protocols at different
layers (L2, L3, L4 or application protocols)
- We can monitor bandwidth usage in short intervals (e.g., 1 second)
and thus detect short peaks
Detecting application protocols requires a combination of header filtering
and payload searching. Support to show the most active sources and destinations
and to show packet size distribution is planned to be added in the future
release.
ABW can be used in two modes, arrows in the following pictures show
data flow.
1) With DiMAPI and a central machine gathering results from remote
monitoring stations:
WEB SERVER CENTRAL STATION REMOTE MONITORING
STATION(-S)
ABW application <------ mapid +
| DiMAPI mapicommd
v
RRD files
|
v
PHP scripts <----- shell scripts
ssh
2) With MAPI and a web server communicating directly with remote
monitoring stations (without central monitoring station):
WEB SERVER REMOTE MONITORING
STATION(-S)
ABW application <------ mapid
| MAPI
v
RRD files
|
v
PHP scripts <----- shell scripts
ssh
ABW can also use a combination of these two modes, that is the web server
communicates with some remote monitoring stations directly and obtains results
from other monitoring stations through the central station. You simply point
the PHP scripts to the right station for each monitored link (to the central
station or to some remote monitoring station). Using the central station
makes configuration of PHP scripts a little bit simpler, but contacting
the remote monitoring stations directly currently provides faster response.
Each remote monitoring station has one or more monitoring cards (regular NICs,
DAG cards or COMBO cards), which receive traffic tapped from the monitored
links (using optical splitters or monitoring ports on routers).
The two directions of one monitored link can be monitored by a) two ports
on a multi-port monitoring card, b) two single-port monitoring cards in
one remote monitoring station, c) two single-port monitoring cards in
two remote monitoring stations. ABW splits or gathers results correctly
and displays them in one graph (inbound traffic in upper part of graph
and outbound traffic in lower part of graph).
INSTALLATION
0. Prerequisitives
I. Prerequisitives
The following standard packages are needed:
libtool (needed by autoconf)
readline-dev
rrdtool >= 1.2.15
libart-2.0 (needed by rrdtool)
libart-2.0-dev (needed by rrdtool)
libpcap
Install these packages using package management in your distribution
of Linux (e.g., dselect in Debian or yast in SuSe) or from sources.
Note 1: Graphs are not produced correctly with rrdtool 1.2.11, which
includes bug in time resolution processing.
You need libtool, readline-dev, rrdtool (tested with 1.2.15, did not
work with 1.0.49 because --slope-mode was not accepted), libart-2.0
and libart-2.0-dev (the last two are required by rrdtool) packages.
Note 2: If you want to monitor MPLS links and do packet classification
on L3 or L4 headers, which are after MPLS headers, you need the
latest libpcap from CVS, because support for IP filtering of
MPLS packets is not yet in libpcap available in packages or as
a tarball. See http://www.tcpdump.org how to checkout libpcap
sources from CVS and compile them.
Install them using package management in your distribution of Linux
(e.g., dselect in Debian or yast in SuSe) or from sources.
II. Checkout MAPI and ABW application from SVN:
I. Checkout MAPI and ABW application from SVN:
Do this on remote monitoring stations, on a central station (if you use
the central station) and on the web server (which only needs content of
htdocs directory from ABW application, you can delete the rest).
svn co --username public --password public \
https://svn.testnett.uninett.no/mapi/trunk
II. Compile and install MAPI
III. Compile and install MAPI
Do this on remote monitoring stations and on a central station (if you
use the central station).
These instructions are also included in README file in MAPI sources.
1) cd trunk
2) ./bootstrap.sh
3) ./configure --prefix=/usr/local/mapi --enable-dimapi --enable-trackflib \
[ --enable-anonlib --enable-ipfixflib ]
3) ./configure --prefix=/usr/local/mapi --enable-trackflib \
[ --enable-dimapi ] \
[ --with-libpcap=/usr/local/src/libpcap ] \
[ --enable-dag --with-libdag=/usr/local/dag ]
[ --enable-anonlib --enable-ipfixflib --enable-extraflib ] \
If you want to gather results from remote monitoring stations on
a central station, use --enable-dimapi.
If you use some specific libpcap, such as the latest sources from CVS
in order to monitor MPLS links, use --with-libpcap.
If you want to read packets from DAG card, you need DAG software
installed and use --enable-dag and --with-libdag.
Features enabled by --enable-anonlib, --enable-ipfixlib and
--enable-extraflib are currently not used by abw application,
but you can include them in your installation of MAPI for future use.
4) make
5) make install
6) vi /usr/local/mapi/etc/mapi.conf
add monitoring interfaces
add monitoring interfaces, such as eth1, /dev/dag0, etc.
7) vi /etc/ld.so.conf
......@@ -37,19 +147,29 @@ II. Compile and install MAPI
8) ldconfig
III. Install scripts on web server
IV. Install scripts on the web server
Do this on the web server.
1) Tell the PHP scripts where to get measurement results
vi htdocs/index.php
1) Copy contents of htdocs directory in distribution of abw application
Edit part between "BEGINNING OF USER CONFIGURATION SECTION" and
"END OF USER CONFIGURATION SECTION".
2) Copy contents of htdocs directory in the distribution of abw application
to some directory on a web server dedicated for user interface of abw
application. For example:
cp htdocs/* /var/www/perfmon/abw
2) Generate SSH key for the user under which the web server is running
and set up access rights. For example, when the web server runs under
3) Generate SSH key for the user under which the web server is running
and set access rights to it. For example, when the web server runs under
www-data user and its home directory configured in /etc/passwd is
/usr/local/perfmon (outside of directory tree accessible by the web server,
so that the web server cannot be misused to read or write the key):
/usr/local/perfmon (it is a good idea to make it outside of directory
tree accessible by the web server, so that the web server cannot be
misused to read or write the key):
ssh-keygen -t dsa store the key in /usr/local/perfmon/.ssh/id_dsa
touch /usr/local/perfmon/.ssh/known_hosts
......@@ -63,8 +183,11 @@ III. Install scripts on web server
chmod 600 /usr/local/perfmon/.ssh/id_dsa
chmod 640 /usr/local/perfmon/.ssh/id_dsa.pub
chmod 644 /usr/local/perfmon/.ssh/known_hosts
V. Compile and install ABW application
IV. Compile and install ABW application on monitoring stations
Do this on remote monitoring stations and on a central station (if you
use the central station).
1) cd trunk/applications/abw
......@@ -85,17 +208,27 @@ IV. Compile and install ABW application on monitoring stations
copy public SSH key of a user on the web server under which the web
server is running (usually user www-data) and which will be used
to connect to "abw" user on this machine to retrieve results
6) make install
to connect to "abw" user on monitoring machines to retrieve results
6) vi abw.cfg
ABW uses this is configuration file to learn about monitoring adapters
and what protocols to monitor.
If you contact some remote monitoring station directly, you must
edit abw.cfg on this remote monitoring station. Otherwise you must
edit abw.cfg on the central monitoring station. The syntax is exactly
the same in both cases.
7) make install
7) rm authorized_keys
8) rm authorized_keys
the key was copied to $HOME/.ssh of "abw" user and can be removed here
8) crontab -e
9) crontab -e
periodically call abw_mapi.sh to check is ABW and MAPI are running and
periodically call abw_mapi.sh to check if ABW and MAPI are running and
possibly restart them, for example:
0,15,30,45 * * * * /usr/local/bin/abw_mapi.sh 2>&1 > /dev/null
......@@ -2,11 +2,14 @@
[global]
# There must be one [subject] section for each monitored link. Each [subject]
# section MUST include id, hostname, interface and label. It CAN optionally
# include description and direction. Direction can be in our out, default is in.
# [subject] sections for the same link, but the oposite direction (in and out)
# MUST have the same label (other lines can be different).
# There must be one [subject] section for each direction of each monitored link.
# Each [subject] section MUST include id, hostname, interface and label. It CAN
# optionally include description and direction. Direction can be in our out,
# default is in. [subject] sections for the same link, but the oposite direction
# (in and out) MUST have the same label (other lines can be different). Hostname
# and interface say where the monitoring adapter is located. If the hostname is
# the same as that where the ABW application is running for all [subjects] in
# a scope, then MAPI will be used, otherwise DiMAPI will be used.
[subject]
id=1
......
<?php
require_once("common.php");
/* require_once("common.php"); */
define(NET_IMG, "cesnet2-20051216-passivem.jpg");
define(REMOTE_USERNAME, "abw");
define(GRAPH_SCRIPT, "/usr/local/abw/bin/rrd_graph_all.sh");
define(GRAPH_DIR, "/var/www/perfmon/abw/graph");
define(REMOTE_GRAPH_DIR, "/usr/local/abw/graph");
/* BEGINNING OF USER CONFIGURATION SECTION */
/* Picture of the monitored network to be shown in the user interface */
define(NET_IMG, "cesnet2-20060804-passivem.jpg");
/*
* Define subjects
*/
/*
* This must be the same as "label" field in [subject] section in
* the configuration file.
* Single-word names (without spaces) refering to monitored links.
* They must be the same as "label" field in [subject] section in
* the abw.cfg configuration file. You can choose them here and edit
* abw.cfg afterwards.
*/
$subject_label=array(
"GN2_CESNET",
......@@ -30,13 +31,10 @@ $subject_label=array(
"Usti_PoP"
);
/* If 1 then subject is disabled (shown gray in the form) */
$subject_disabled=array( 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1 );
/*
* This is what will appear as graph description, it can be anything,
* but it is probably a good idea to make it the same as "description"
* field in [subject] section in the configuration file.
* Description of monitored links, can include spaces. It is probably a good
* idea to make it the same as "description" field in [subject] section in
* the abw.cfg configuration file (but it is not required).
*/
$subject_description=array(
"GN2 CESNET2",
......@@ -54,10 +52,9 @@ $subject_description=array(
/*
* Hostnames where results are stored in RRD files and from which they should
* be retrieved. It can be one central station that communicates with remote
* be retrieved. It can be a central station that communicates with remote
* monitoring stations via DiMAPI. Or it can be individual remote monitoring
* stations if monitoring application runs locally on remote monitoring
* stations and uses MAPI.
* stations directly.
*/
$subject_hostname=array(
"jra1-2.cesnet.cz",
......@@ -67,12 +64,22 @@ $subject_hostname=array(
"perfmon-liberec.cesnet.cz",
"perfmon-olomouc.cesnet.cz",
"perfmon-ostrava.cesnet.cz",
"perfmon-pardubice.cesnet.cz",
"195.113.125.254",
"perfmon-plzen.cesnet.cz",
"perfmon1.cesnet.cz",
"perfmon-usti.cesnet.cz"
);
/* If 1 then the subject is disabled (shown gray in the user interface) */
$subject_disabled=array( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 );
/* END OF USER CONFIGURATION SECTION */
define(REMOTE_USERNAME, "abw");
define(GRAPH_SCRIPT, "/usr/local/abw/bin/rrd_graph_all.sh");
define(GRAPH_DIR, "/var/www/perfmon/abw/graph");
define(REMOTE_GRAPH_DIR, "/usr/local/abw/graph");
/*
* Predefined time intervals and granularities
*
......@@ -138,6 +145,44 @@ $graph_type_description=array("L4", "Application");
$monthNumberToLongName=array("January", "February", "March", "April", "May",
"June", "July", "August", "September", "October", "November", "December");
function time_to_sec($number, $unit) {
switch ($unit) {
case "Seconds":
return $number;
case "Minutes":
return $number * 60;
case "Hours":
return $number * 3600;
case "Days":
return $number * 86400;
case "Weeks":
return $number * 86400 * 7;
case "Months":
return $number * 86400 * 30;
case "Years":
return $number * 86400 * 365;
default:
return -1;
}
} /* time_to_sec() */
function time_diff($time1, $time2) {
if ($time2["sec"] > $time1["sec"]) {
if ($time2["sec"] > ($time1["sec"]+1))
$res=$time2["sec"] - $time1["sec"];
else
$res=0;
$res=$res+(float)(1000000-$time1["usec"])/1000000 +
(float)($time2["usec"])/1000000;
}
else
$res=(float)($time2["usec"]-$time1["usec"])/1000000;
return $res;
} /* time_diff() */
/*
* Start application
*/
......@@ -258,46 +303,92 @@ echo "</table></td>\n";
echo "<td>&nbsp;</td><td><p>Start or end time:<br>";
echo "<select name=time_hour>";
for ($i=0; $i<=23; $i++) {
echo "<option value=$i";
if ($time_hour==$i)
echo " selected";
echo ">";
printf("%02d", $i);
echo "</option>\n";
}
echo "</select>\n";
echo "<select name=time_minute>";
for ($i=0; $i<=59; $i++) {
echo "<option value=$i";
if ($time_minute==$i)
echo " selected";
echo ">";
printf("%02d", $i);
echo "</option>\n";
}
echo "</select>\n";
echo "<select name=time_day>";
for ($i=1; $i<=31; $i++)
echo "<option value=$i>$i</option>\n";
for ($i=1; $i<=31; $i++) {
echo "<option value=$i";
if ($time_day==$i)
echo " selected";
echo ">$i</option>\n";
}
echo "</select>\n";
echo "<select name=time_month>";
for ($i=1; $i<=12; $i++)
echo "<option value=$i>" . $monthNumberToLongName[$i-1] . "</option>\n";
for ($i=1; $i<=12; $i++) {
echo "<option value=$i";
if ($time_month==$i)
echo " selected";
echo ">" . $monthNumberToLongName[$i-1] . "</option>\n";
}
echo "</select>\n";
echo "<select name=time_year>";
for ($i=2006; $i<=2015; $i++)
echo "<option value=$i>$i</option>\n";
for ($i=2006; $i<=2015; $i++) {
echo "<option value=$i";
if ($time_year==$i)
echo " selected";
echo ">$i</option>\n";
}
echo "</select>\n";
echo "<p>Time length:<br>\n";
echo "<input type=text size=3 name=time_length_number></input>\n";
echo "<input type=text size=3 name=time_length_number value=\"$time_length_number\"></input>\n";
echo "<select name=time_length_unit>";
$time_length_units=array("Minutes", "Hours", "Days", "Weeks", "Months",
"Years");
foreach ($time_length_units as $value)
echo "<option value=$value>$value</option>\n";
foreach ($time_length_units as $value) {
echo "<option value=$value";
if ($time_length_unit==$value)
echo " selected";
echo ">$value</option>\n";
}
echo "</select>\n";
/* Interval + avg/max are as a separate table */
echo "<p><table><tr><td>Interval:</td><td>Avg/Max:</td></tr><tr>\n";
echo "<td><input type=text size=3 name=r1_number></input>\n";
echo "<td><input type=text size=3 name=r1_number value=\"$r1_number\"></input>\n";
echo "<select name=r1_unit>";
$r1_units=array("Seconds", "Minutes", "Hours", "Days", "Weeks", "Months",
"Years");
foreach ($r1_units as $value)
echo "<option value=$value>$value</option>\n";
foreach ($r1_units as $value) {
echo "<option value=$value";
if ($r1_unit==$value)
echo " selected";
echo ">$value</option>\n";
}
echo "</select></td>\n";
echo "<td><input type=text size=3 name=r2_number></input>\n";
echo "<td><input type=text size=3 name=r2_number value=\"$r2_number\"></input>\n";
echo "<select name=r2_unit>";
$r2_units=array("Seconds", "Minutes", "Hours", "Days", "Weeks", "Months",
"Years");
foreach ($r2_units as $value)
echo "<option value=$value>$value</option>\n";
foreach ($r2_units as $value) {
echo "<option value=$value";
if ($r2_unit==$value)
echo " selected";
echo ">$value</option>\n";
}
echo "</select></td>\n";
echo "</tr></table>\n";
......@@ -307,22 +398,22 @@ if (!isset($time_type))
echo "<p>Time type:<br>\n";
echo "Predefined <input type=radio name=\"time_type\" value=\"predefined\"";
if (!strcmp($time_type, "predefined"))
echo " selected";
echo " checked";
echo ">";
echo " Start time <input type=radio name=\"time_type\" value=\"start_time\"";
if (!strcmp($time_type, "start_time"))
echo " selected";
echo " checked";
echo ">";
echo " End time <input type=radio name=\"time_type\" value=\"end_time\"";
if (!strcmp($time_type, "end_time"))
echo " selected";
echo " checked";
echo ">";
echo "</td>\n";
echo "</tr></table\n";
echo "<p>Note: selecting all time periods will require a lot of processing time\n";
/* echo "<p>Note: selecting all time periods will require a lot of processing time\n"; */
echo "<p>\n";
echo "<input type=submit name=button_name value=\"Generate graphs\">\n";
......@@ -332,7 +423,6 @@ echo "</form><br>\n";
if ($action=="gen_graph") {
$current_time=date("G:i:s Ymd", time());
echo "current_time: $current_time<br>\n";
foreach (glob(GRAPH_DIR . "/*") as $filename)
unlink($filename);
......@@ -342,52 +432,132 @@ if ($action=="gen_graph") {
if (isset($graph_types) &&
(isset($subjects) || $subject_all) &&
(isset($times) || $time_all)) {
(isset($times) || $time_all || strcmp($time_type, "predefined"))) {
/* Go over all selected graph types */
foreach($graph_types as $graph_type) {
/* Go over all subjects and for each selected subject issue
one remote command to generate graphs */
$total_time=0;
echo "<p>\n";
echo "<table>\n";
echo "<tr><td>Graph type</td><td>Link</td><td>Time (gen / copy)</td></tr>\n";
$i=0;
foreach ($subject_label as $subject_key => $subject_value) {
if (($subject_all || in_array($subject_value, $subjects)) &&
!$subject_disabled[$subject_key]) {
$hostname=$subject_hostname[$i];
$command="ssh " . REMOTE_USERNAME . "@" . $subject_hostname[$i] .
" \"" . GRAPH_SCRIPT . " -r --protocols=" . $graph_type .
" --label=" . $subject_value . " --parameters_id=1";
/* Append one --time argument for each selected time period */
foreach ($time_description as $time_key => $time_value) {
$time_label=$r1[$time_key] . "_" . $r2[$time_key] . "_" .
$time_length[$time_key];
if ($time_all || in_array($time_label, $times)) {
$hhmmYYYYMMDD=date("G:i Ymd", (int)(time() / $r2[$time_key]) * $r2[$time_key] - $r2[$time_key]);
echo "r2: $r2[$time_key], hhmmYYMMDD: $hhmmYYYYMMDD<br>\n";
/* Go over all selected graph types */
$command=$command . " --time=\\\"" .
$r1[$time_key] . " " . $r2[$time_key] . " " .
$time_length[$time_key] . " " . $hhmmYYYYMMDD . "\\\"";
foreach($graph_type_label as $graph_type_key => $graph_type_value) {
if (in_array($graph_type_value, $graph_types)) {
/* Go over all subjects and for each selected subject issue
one remote command to generate graphs */
$i=0;
foreach ($subject_label as $subject_key => $subject_value) {
if (($subject_all || in_array($subject_value, $subjects)) &&
!$subject_disabled[$subject_key]) {
$hostname=$subject_hostname[$i];
$command="ssh " . REMOTE_USERNAME . "@" . $subject_hostname[$i] . " \"" . GRAPH_SCRIPT . " -r --protocols=" . $graph_type_value . " --label=" . $subject_value . " --parameters_id=1";
/* Append one --time argument for each selected time period */
if (!strcmp($time_type, "predefined")) {
foreach ($time_description as $time_key => $time_value) {
$time_label=$r1[$time_key] . "_" . $r2[$time_key] .
"_" . $time_length[$time_key];
if ($time_all || in_array($time_label, $times)) {
$hhmmYYYYMMDD=date("G:i Ymd", (int)(time() / $r2[$time_key]) * $r2[$time_key] - $r2[$time_key]);
$command=$command . " --time=\\\"" .
$r1[$time_key] . " " . $r2[$time_key] . " " .
$time_length[$time_key] . " " . $hhmmYYYYMMDD . "\\\"";
}
}
} /* if (!strcmp($time_type, "predefined")) */
else {
/* echo "time_type: $time_type<br>\n";
echo "time_hour: $time_hour<br>\n";
echo "time_minute: $time_minute<br>\n";
echo "time_day: $time_day<br>\n";
echo "time_month: $time_month<br>\n";
echo "time_year: $time_year<br>\n";
echo "time_length_number: $time_length_number, time_length_unit: $time_length_unit<br>\n";
echo "r1_number: $r1_number, r1_unit: $r1_unit<br>\n";
echo "r2_number: $r2_number, r2_unit: $r2_unit<br>\n"; */
/* Convert R1, R2 and time length to seconds,
adjust time_length to R2 boundary */
$r1_sec=time_to_sec($r1_number, $r1_unit);
$r2_sec=time_to_sec($r2_number, $r2_unit);
/* echo "r1_sec: $r1_sec, r2_sec: $r2_sec<br>\n"; */
if ($r1_sec<=0 || $r2_sec<=0 || $r2_sec<$r1_sec ||
($r2_sec%$r1_sec)>0) {
echo "Incorrect time or date specification.<br>\n";
exit();
}
$time_length_sec=time_to_sec($time_length_number,
$time_length_unit);
$time_length_sec=
((int)($time_length_sec / $r2_sec)) * $r2_sec;
if ($time_length_sec<=0) {