2
0
mirror of https://github.com/munin-monitoring/contrib.git synced 2018-11-08 00:59:34 +01:00
contrib-munin/plugins/snmp/snmp__if_combined
Diego Elio Pettenò c0e85a7cfa snmp__if_combined: create a single graph showing traffic from all interfaces.
This allows normalising the graph range and shows aberrations in the
bandwidth usage more clearly.
2012-08-09 13:47:14 -07:00

683 lines
18 KiB
Perl
Executable File

#!/usr/bin/perl -w
# -*- perl -*-
=head1 NAME
snmp__if_combined - SNMP card plugin to monitor the network interfaces of any networked equipment.
=head1 APPLICABLE SYSTEMS
Any SNMP capable networked computer equipment. Using a command such
as "munin-node-configure --snmp switch.langfeldt.net --snmpversion 2c
--snmpcommunity public | sh -x" should auto-detect all applicable
interfaces. On a typical switch you will get one plugin pr. ethernet
port. On a router you might get one plugin per VLAN interface.
=head1 CONFIGURATION
As a rule SNMP plugins need site specific configuration. The default
configuration (shown here) will only work on insecure sites/devices:
[snmp_*]
env.version 2
env.community public
env.ifTypeOnly ethernetCsmacd
In general SNMP is not very secure at all unless you use SNMP version
3 which supports authentication and privacy (encryption). But in any
case the community string for your devices should not be "public".
Please see 'perldoc Munin::Plugin::SNMP' for further configuration
information.
The ifTypeOnly is a space separated list of media types to show. By
default the plugin shows only interfaces identified as
'ethernetCsmacd'. To see what interface types your switch, router, or
other net thing uses you can use this command:
snmpwalk -c public -v 2c switch 1.3.6.1.2.1.2.2.1.3
It may show something like this:
IF-MIB::ifType.1 = INTEGER: ethernetCsmacd(6)
IF-MIB::ifType.4 = INTEGER: mplsTunnel(150)
IF-MIB::ifType.5 = INTEGER: other(1)
IF-MIB::ifType.6 = INTEGER: softwareLoopback(24)
IF-MIB::ifType.8 = INTEGER: tunnel(131)
IF-MIB::ifType.13 = INTEGER: propVirtual(53)
IF-MIB::ifType.123 = INTEGER: l2vlan(135)
propVirtual or l2vlan is usualy used for VLAN interfaces. Tunnel
would normaly be for VPNs. A minor horde of different interface types
are supposted, please see IANAifType-MIB (on your system or find with
Google) for a full list.
=head1 INTERPRETATION
A single graph is generated with all the interfaces overlaid one over
the other: incoming traffic is received on the interface from the
connected device, outgoing is sent to it instead.
=head1 MIB INFORMATION
This plugin requires the IF-MIB the standard IETF MIB for network
interfaces.
It reports the contents of the
IF-MIB::ifHCInOctets/IF-MIB::ifHCOutOctets if available,
IF-MIB::ifInOctets/IF-MIB::ifOutOctets if not. The former are 64 bit
counters only available with SNMP 2 and later. The later are 32 bit
counters (see FEATURES below).
=head1 MAGIC MARKERS
#%# family=snmpauto
#%# capabilities=snmpconf
=head1 VERSION
$Id: snmp__if_.in 1818 2009-01-03 19:29:30Z janl $
=head1 BUGS
Should support indexing by
- ifIndex
- ifName
- ifDescr
- ifAlias
- mac-address
(and anything else MRTG can index by) in addition to OID-index as now.
Pulling in a user definable set of ifName/ifDescr/ifAlias for textual
description and even graph_title would also be nice.
IFF we get a patch to support the .oldname attribute then we may use
that to let the operator change the indexing dynamicaly without data
loss.
=head1 FEATURES
You may get strange results if you use SNMPv1, or SNMPv2 on
switches that do not support 64 bit byte counters. If the interface
traffic exceeds about 50Mbps a 32 bit byte counter will wrap around in
less than 5 minutes making the graph for the interface show random
results.
If you have a switch/device that supports 64 bit byte counters this
plugin will use them and the graph will be fine. The graph
information will inform about this. You must use SNMPv2c or SNMPv3 to
be able to use 64 bit counters - if the device supports them.
This problem is a feature of the device SNMP implementation or your
usage of it, it is nothing the plugin can fix. In the future Munin
may be able to run the plugin more often than the counter wraps
around.
=head1 AUTHOR
Copyright (C) 2012 Diego Elio Pettenò.
Original snmp__if_multi: Copyright (C) 2004-2010 Jimmy Olsen, Dagfinn
Ilmari Mannsaaker, Nicolai Langfeldt, Redpill Linpro AS and others.
Original snmp__if_ plugin: Copyright (C) 2004-2009 Jimmy Olsen, Dagfinn
Ilmari Mannsaaker.
Initial SNMPv3 support by "Confusedhacker".
Documentation, porting to Munin::Plugin::SNMP and
further grooming by Nicolai Langfeldt.
Reworked to snmp__if_multi by Nicolai Langfeldt.
Reworked to snmp__if_all by Diego Elio Pettenò.
=head1 LICENSE
GPLv2
=cut
use strict;
use Munin::Plugin;
use Munin::Plugin::SNMP;
my $response;
my $iface;
# This is the snmpwalk:
# .1.3.6.1.2.1.2.1.0 = INTEGER: 2
# .1.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1
# .1.3.6.1.2.1.2.2.1.1.65539 = INTEGER: 65539
# .1.3.6.1.2.1.2.2.1.2.1 = STRING: MS TCP Loopback interface
# .1.3.6.1.2.1.2.2.1.2.65539 = STRING: Broadcom NetXtreme Gigabit Ethernet
# .1.3.6.1.2.1.2.2.1.3.1 = INTEGER: softwareLoopback(24)
# .1.3.6.1.2.1.2.2.1.3.65539 = INTEGER: ethernetCsmacd(6)
# .1.3.6.1.2.1.2.2.1.4.1 = INTEGER: 1520
# .1.3.6.1.2.1.2.2.1.4.65539 = INTEGER: 1500
# .1.3.6.1.2.1.2.2.1.5.1 = Gauge32: 10000000
# .1.3.6.1.2.1.2.2.1.5.65539 = Gauge32: 1000000000
# .1.3.6.1.2.1.2.2.1.6.1 = STRING:
# .1.3.6.1.2.1.2.2.1.6.65539 = STRING: 0:30:48:75:65:5e
# .1.3.6.1.2.1.2.2.1.7.1 = INTEGER: up(1)
# .1.3.6.1.2.1.2.2.1.7.65539 = INTEGER: up(1)
# .1.3.6.1.2.1.2.2.1.8.1 = INTEGER: up(1)
# .1.3.6.1.2.1.2.2.1.8.65539 = INTEGER: up(1)
#
# 64 bit counters:
# .1.3.6.1.2.1.31.1.1.1.6. Counter64 ifHCInOctets
# .1.3.6.1.2.1.31.1.1.1.10. Counter64 ifHCOutOctets
if (defined $ARGV[0] and $ARGV[0] eq "snmpconf") {
print "require 1.3.6.1.2.1.2.2.1.1.\n";
exit 0;
}
my $sysDescr = '1.3.6.1.2.1.1.1.0';
my $sysLocation = '1.3.6.1.2.1.1.6.0';
my $sysContact = '1.3.6.1.2.1.1.4.0';
my $sysName = '1.3.6.1.2.1.1.5.0';
my $ifOIDBase = "1.3.6.1.2.1.2.2.1"; # ifEntry
my $ifv2OIDBase = "1.3.6.1.2.1.31.1.1.1"; # ifXEntry
my %ifTypes = (
other => 1,
regular1822 => 2,
hdh1822 => 3,
ddnX25 => 4,
rfc877x25 => 5,
ethernetCsmacd => 6,
iso88023Csmacd => 7,
iso88024TokenBus => 8,
iso88025TokenRing => 9,
iso88026Man => 10,
starLan => 11,
proteon10Mbit => 12,
proteon80Mbit => 13,
hyperchannel => 14,
fddi => 15,
lapb => 16,
sdlc => 17,
ds1 => 18,
e1 => 19,
basicISDN => 20,
primaryISDN => 21,
propPointToPointSerial => 22,
ppp => 23,
softwareLoopback => 24,
eon => 25,
ethernet3Mbit => 26,
nsip => 27,
slip => 28,
ultra => 29,
ds3 => 30,
sip => 31,
frameRelay => 32,
rs232 => 33,
para => 34,
arcnet => 35,
arcnetPlus => 36,
atm => 37,
miox25 => 38,
sonet => 39,
x25ple => 40,
iso88022llc => 41,
localTalk => 42,
smdsDxi => 43,
frameRelayService => 44,
v35 => 45,
hssi => 46,
hippi => 47,
modem => 48,
aal5 => 49,
sonetPath => 50,
sonetVT => 51,
smdsIcip => 52,
propVirtual => 53,
propMultiplexor => 54,
ieee80212 => 55,
fibreChannel => 56,
hippiInterface => 57,
frameRelayInterconnect => 58,
aflane8023 => 59,
aflane8025 => 60,
cctEmul => 61,
fastEther => 62,
isdn => 63,
v11 => 64,
v36 => 65,
g703at64k => 66,
g703at2mb => 67,
qllc => 68,
fastEtherFX => 69,
channel => 70,
ieee80211 => 71,
ibm370parChan => 72,
escon => 73,
dlsw => 74,
isdns => 75,
isdnu => 76,
lapd => 77,
ipSwitch => 78,
rsrb => 79,
atmLogical => 80,
ds0 => 81,
ds0Bundle => 82,
bsc => 83,
async => 84,
cnr => 85,
iso88025Dtr => 86,
eplrs => 87,
arap => 88,
propCnls => 89,
hostPad => 90,
termPad => 91,
frameRelayMPI => 92,
x213 => 93,
adsl => 94,
radsl => 95,
sdsl => 96,
vdsl => 97,
iso88025CRFPInt => 98,
myrinet => 99,
voiceEM => 100,
voiceFXO => 101,
voiceFXS => 102,
voiceEncap => 103,
voiceOverIp => 104,
atmDxi => 105,
atmFuni => 106,
atmIma => 107,
pppMultilinkBundle => 108,
ipOverCdlc => 109,
ipOverClaw => 110,
stackToStack => 111,
virtualIpAddress => 112,
mpc => 113,
ipOverAtm => 114,
iso88025Fiber => 115,
tdlc => 116,
gigabitEthernet => 117,
hdlc => 118,
lapf => 119,
v37 => 120,
x25mlp => 121,
x25huntGroup => 122,
trasnpHdlc => 123,
interleave => 124,
fast => 125,
ip => 126,
docsCableMaclayer => 127,
docsCableDownstream => 128,
docsCableUpstream => 129,
a12MppSwitch => 130,
tunnel => 131,
coffee => 132,
ces => 133,
atmSubInterface => 134,
l2vlan => 135,
l3ipvlan => 136,
l3ipxvlan => 137,
digitalPowerline => 138,
mediaMailOverIp => 139,
dtm => 140,
dcn => 141,
ipForward => 142,
msdsl => 143,
ieee1394 => 144,
'if-gsn' => 145,
dvbRccMacLayer => 146,
dvbRccDownstream => 147,
dvbRccUpstream => 148,
atmVirtual => 149,
mplsTunnel => 150,
srp => 151,
voiceOverAtm => 152,
voiceOverFrameRelay => 153,
idsl => 154,
compositeLink => 155,
ss7SigLink => 156,
propWirelessP2P => 157,
frForward => 158,
rfc1483 => 159,
usb => 160,
ieee8023adLag => 161,
bgppolicyaccounting => 162,
frf16MfrBundle => 163,
h323Gatekeeper => 164,
h323Proxy => 165,
mpls => 166,
mfSigLink => 167,
hdsl2 => 168,
shdsl => 169,
ds1FDL => 170,
pos => 171,
dvbAsiIn => 172,
dvbAsiOut => 173,
plc => 174,
nfas => 175,
tr008 => 176,
gr303RDT => 177,
gr303IDT => 178,
isup => 179,
propDocsWirelessMaclayer => 180,
propDocsWirelessDownstream => 181,
propDocsWirelessUpstream => 182,
hiperlan2 => 183,
propBWAp2Mp => 184,
sonetOverheadChannel => 185,
digitalWrapperOverheadChannel => 186,
aal2 => 187,
radioMAC => 188,
atmRadio => 189,
imt => 190,
mvl => 191,
reachDSL => 192,
frDlciEndPt => 193,
atmVciEndPt => 194,
opticalChannel => 195,
opticalTransport => 196,
propAtm => 197,
voiceOverCable => 198,
infiniband => 199,
teLink => 200,
q2931 => 201,
virtualTg => 202,
sipTg => 203,
sipSig => 204,
docsCableUpstreamChannel => 205,
econet => 206,
pon155 => 207,
pon622 => 208,
bridge => 209,
linegroup => 210,
voiceEMFGD => 211,
voiceFGDEANA => 212,
voiceDID => 213,
mpegTransport => 214,
sixToFour => 215,
gtp => 216,
pdnEtherLoop1 => 217,
pdnEtherLoop2 => 218,
opticalChannelGroup => 219,
homepna => 220,
gfp => 221,
ciscoISLvlan => 222,
actelisMetaLOOP => 223,
fcipLink => 224,
rpr => 225,
qam => 226,
lmp => 227,
cblVectaStar => 228,
docsCableMCmtsDownstream => 229,
adsl2 => 230,
macSecControlledIF => 231,
macSecUncontrolledIF => 232,
aviciOpticalEther => 233,
atmbond => 234,
voiceFGDOS => 235,
mocaVersion1 => 236,
ieee80216WMAN => 237,
adsl2plus => 238,
dvbRcsMacLayer => 239,
dvbTdm => 240,
dvbRcsTdma => 241,
x86Laps => 242,
wwanPP => 243,
wwanPP2 => 244
);
my %ifTypeByNum = map { $ifTypes{$_} => $_; } keys %ifTypes;
# Needed as globals
my $snmpinfo;
my $snmpinfoX;
sub do_collect {
# Collect information from SNMP agent
my $session = Munin::Plugin::SNMP->session();
$snmpinfo = $session->get_hash(
-baseoid => $ifOIDBase,
-cols =>
{ 2 => 'ifDescr',
# Type: See above
3 => 'ifType',
4 => 'ifMtu',
5 => 'ifSpeed',
6 => 'ifMac',
7 => 'ifAdminStatus',
# Oper: 1) up 2) down 3) testing
# 4) unknown, 5) dormant 6) not present
# 7) lowerLayerDown
8 => 'ifOperStatus',
10 => 'ifInOctets',
11 => 'ifInUcastPkts',
15 => 'ifUnUnknownProtos',
16 => 'ifOutOctets',
18 => 'ifOutNUcastPkts',
});
# ifXEntry - SNMP v2 and up only - on some devices
$snmpinfoX = $session->get_hash(
-baseoid => $ifv2OIDBase,
-cols =>
{ 2 => 'ifInMulticastPkts',
3 => 'ifInBroadcastPkts',
4 => 'ifOutMulticastPkts',
5 => 'ifOutBroadcastPkts',
6 => 'ifHCInOctets',
10 => 'ifHCOutOctets',
15 => 'ifHighSpeed',
18 => 'ifAlias',
});
}
sub do_preprocess_if {
my ($mediatype, $if) = @_;
my $response = $snmpinfo->{$if}->{ifType} || 1;
if (defined($mediatype)) {
if (defined($mediatype->{$response})) {
# This is one of the interesting media types
} else {
# This media type is not interesting. Remove.
delete $snmpinfo->{$if} if exists $snmpinfo->{$if};
delete $snmpinfoX->{$if} if exists $snmpinfoX->{$if};
return;
}
}
if (defined ($response = $snmpinfo->{$if}->{ifOperStatus})) {
# 1 = up, 2 = down, 7 = lowerLayerDown
if ($response == 2 or $response == 7) {
# Fold recognized down states into one.
$response = $snmpinfo->{$if}->{ifOperStatus} = 2;
} elsif ($response != 1) {
# This interface is fishy, remove and forget.
delete $snmpinfo->{$if} if exists $snmpinfo->{$if};
delete $snmpinfoX->{$if} if exists $snmpinfoX->{$if};
return;
}
}
}
sub do_preprocess {
my $mediatypes = 'ethernetCsmacd';
if (exists( $ENV{'ifTypeOnly'} )) {
$mediatypes = $ENV{'ifTypeOnly'};
}
my @mediatypes = split(/[ ,]+/,$mediatypes);
# Hash of numerical media types the user finds interesting.
my $mediatype={};
if ($mediatypes eq 'ALL') {
$mediatype = undef;
} else {
foreach my $type (@mediatypes) {
if (exists($ifTypes{$type})) {
$mediatype->{$ifTypes{$type}} = 1;
} else {
die "Unknown media type '$type' specified in ifTypeOnly\n";
}
}
}
foreach my $if (keys %{$snmpinfo}) {
do_preprocess_if($mediatype, $if);
}
}
sub do_config_root {
my ($host, $version) = @_;
my $extrainfo="";
if (defined ($snmpinfoX->{0}->{ifHCInOctets})) {
# If we get an answer at the 64 bit OID then this switch
# supports the extended MIB
$extrainfo .= " This switch supports 64 bit byte counters and these are used by this plugin.";
} else {
# If not we only have a 32 bit counter and are lost.
$extrainfo .= " NOTE! This switch supports only 32 bit byte counters which makes the plugin unreliable and unsuitable for most 100Mb (or faster) interfaces, where bursts are expected to exceed 50Mbps. This means that for interfaces where much traffic is sent this plugin will report false thruputs and cannot be trusted.";
# unless perhaps the operator can get us snmp version 2c or 3?
$extrainfo .= " I notice that you use SNMP version 1 which does not support 64 bit quantities. You may get better results if you switch to SNMP version 2c or 3. Please refer to the plugin documentation."
if $version == 1;
}
print "graph_title $host interfaces traffic\n";
print "graph_args --base 1000\n";
print "graph_vlabel bits in (-) / out (+) per \${graph_period}\n";
print "graph_category network\n";
print "graph_info This graph shows the total traffic for $host.$extrainfo\n";
}
sub do_config_if {
my ($host,$version,$if) = @_;
my $alias = $snmpinfo->{$if}->{ifDescr} || "Interface $if";
if (! ($alias =~ /\d+/) ) {
# If there are no numbers in the $alias add the if index
$alias .=" (if $if)";
}
my $warn = undef;
my $speed = 0;
my $extrainfo = "";
if (defined ($speed = $snmpinfoX->{$if}->{ifHighSpeed}) and $speed) {
# Speed in 1,000,000 bits per second
$speed = $speed * 1000000;
$warn = $speed / 75 * 100;
my $textspeed = scaleNumber($speed,'bps','',
'The interface speed is %.1f%s%s.');
$extrainfo .= ' '.$textspeed if $textspeed;
} elsif (defined ($speed = $snmpinfo->{$if}->{ifSpeed}) and $speed) {
# Speed in bits pr. second
$warn = $speed*100/75;
my $textspeed = scaleNumber($speed,'bps','',
'The interface speed is %.1f%s%s.');
$extrainfo .= " ".$textspeed if $textspeed;
}
$response = $snmpinfo->{$if}->{ifType};
print "recv$if.label $alias\n";
print "recv$if.type DERIVE\n";
print "recv$if.graph no\n";
print "recv$if.cdef recv$if,8,*\n";
print "recv$if.max $speed\n" if $speed;
print "recv$if.min 0\n";
print "recv$if.warning ", (-$warn), "\n" if defined $warn;
print "send$if.label $alias\n";
print "send$if.type DERIVE\n";
print "send$if.negative recv$if\n";
print "send$if.cdef send$if,8,*\n";
print "send$if.max $speed\n" if $speed;
print "send$if.min 0\n";
print "send$if.warning $warn\n" if defined $warn;
}
sub do_fetch_if {
my($if) = @_;
my $status = $snmpinfo->{$if}->{ifOperStatus} || 1;
my $response;
# 1 means up
# 2 means set to down
# Everything else we ignore.
if ($status == 2) {
# Interface is down
print "recv$if.value U\n";
print "send$if.value U\n";
print "send$if.extinfo This interface is currently down.\n";
return;
}
if (defined ($response = $snmpinfoX->{$if}->{ifHCInOctets} ||
$snmpinfo->{$if}->{ifInOctets})) {
print "recv$if.value ", $response, "\n";
} else {
# No response...
print "recv$if.value U\n";
}
if (defined ($response = $snmpinfoX->{$if}->{ifHCOutOctets} ||
$snmpinfo->{$if}->{ifOutOctets})) {
print "send$if.value ", $response, "\n";
} else {
# No response...
print "send$if.value U\n";
}
}
sub do_config {
my ($host,undef,$version) = Munin::Plugin::SNMP->config_session();
print "host_name $host\n" unless $host eq 'localhost';
do_config_root($host,$version);
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
do_config_if($host,$version,$if);
}
}
# ############################## MAIN ################################
do_collect;
do_preprocess;
if ($ARGV[0] and $ARGV[0] eq "config") {
do_config();
exit 0;
}
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
do_fetch_if($if);
}