mirror of
https://github.com/munin-monitoring/contrib.git
synced 2018-11-08 00:59:34 +01:00
810 lines
20 KiB
Perl
Executable File
810 lines
20 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. 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 usually used for VLAN interfaces. Tunnel
|
|
would normally 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.
|
|
|
|
Sub-graphs are created, one per interface, akin to snmp__if_multi
|
|
plugin.
|
|
|
|
=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 dynamically 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_combined 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',
|
|
5 => 'ifSpeed',
|
|
# Oper: 1) up 2) down 3) testing
|
|
# 4) unknown, 5) dormant 6) not present
|
|
# 7) lowerLayerDown
|
|
8 => 'ifOperStatus',
|
|
10 => 'ifInOctets',
|
|
13 => 'ifInDiscards',
|
|
14 => 'ifInErrors',
|
|
16 => 'ifOutOctets',
|
|
19 => 'ifOutDiscards',
|
|
20 => 'ifOutErrors',
|
|
});
|
|
|
|
# ifXEntry - SNMP v2 and up only - on some devices
|
|
$snmpinfoX = $session->get_hash(
|
|
-baseoid => $ifv2OIDBase,
|
|
-cols =>
|
|
{ 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 = 'ALL';
|
|
|
|
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 <<END;
|
|
|
|
multigraph snmp_if_combined
|
|
graph_title $host interfaces traffic
|
|
graph_args --base 1000
|
|
graph_vlabel bits in (-) / out (+) per \${graph_period}
|
|
graph_category network
|
|
graph_info This graph shows the total traffic for $host.$extrainfo
|
|
END
|
|
|
|
print "graph_order";
|
|
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
|
|
print " recv$if=snmp_if_combined.$if.recv send$if=snmp_if_combined.$if.send";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
|
|
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)";
|
|
}
|
|
|
|
print <<END;
|
|
recv$if.label $alias
|
|
recv$if.graph no
|
|
send$if.label $alias
|
|
send$if.negative recv$if
|
|
END
|
|
}
|
|
|
|
print <<END;
|
|
|
|
multigraph snmp_if_combined_err
|
|
graph_title $host interfaces errors
|
|
graph_args --base 1000
|
|
graph_vlabel errors in (-) / out (+) per \${graph_period}
|
|
graph_category network
|
|
END
|
|
|
|
print "graph_order";
|
|
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
|
|
print " recv$if=snmp_if_combined_err.$if.total_in send$if=snmp_if_combined_err.$if.total_out";
|
|
}
|
|
print "\n";
|
|
|
|
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
|
|
my $alias = $snmpinfoX->{$if}->{ifAlias} || $snmpinfo->{$if}->{ifDescr} || "Interface $if";
|
|
|
|
if (! ($alias =~ /\d+/) ) {
|
|
# If there are no numbers in the $alias add the if index
|
|
$alias .=" (if $if)";
|
|
}
|
|
|
|
print <<END;
|
|
recv$if.label $alias
|
|
recv$if.graph no
|
|
send$if.label $alias
|
|
send$if.negative recv$if
|
|
END
|
|
}
|
|
}
|
|
|
|
sub do_config_if {
|
|
my ($host,$version,$if) = @_;
|
|
|
|
my $alias = $snmpinfoX->{$if}->{ifAlias} || $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 <<END;
|
|
multigraph snmp_if_combined.$if
|
|
graph_title $alias traffic
|
|
graph_args --base 1000
|
|
graph_vlabel bits in (-) / out (+) per \${graph_period}
|
|
graph_category network
|
|
|
|
recv.label bps
|
|
recv.type DERIVE
|
|
recv.graph no
|
|
recv.min 0
|
|
send.label bps
|
|
send.type DERIVE
|
|
send.negative recv
|
|
send.min 0
|
|
END
|
|
|
|
if ( defined($speed) ) {
|
|
printf("recv.max %s\nsend.max %s\n", $speed, $speed);
|
|
}
|
|
|
|
if ( defined($warn) ) {
|
|
printf("recv.warning %s\nsend.warning %s\n", $warn, $warn);
|
|
}
|
|
|
|
print <<END;
|
|
multigraph snmp_if_combined_err.$if
|
|
graph_title $alias errors
|
|
graph_args --base 1000
|
|
graph_vlabel errors in (-) / out (+) per \${graph_period}
|
|
graph_category network
|
|
|
|
errors_in.label $alias
|
|
errors_in.graph no
|
|
errors_in.label recv
|
|
errors_in.type DERIVE
|
|
errors_in.min 0
|
|
errors_out.label Errors
|
|
errors_out.negative errors_in
|
|
errors_out.type DERIVE
|
|
errors_out.min 0
|
|
|
|
discards_in.label $alias
|
|
discards_in.graph no
|
|
discards_in.type DERIVE
|
|
discards_in.min 0
|
|
discards_out.label Discards
|
|
discards_out.negative discards_in
|
|
discards_out.type DERIVE
|
|
discards_out.min 0
|
|
|
|
total_in.label $alias
|
|
total_in.graph no
|
|
total_in.type DERIVE
|
|
total_in.min 0
|
|
total_out.label $alias
|
|
total_out.graph no
|
|
total_out.type DERIVE
|
|
total_out.min 0
|
|
END
|
|
}
|
|
|
|
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.
|
|
|
|
print "multigraph snmp_if_combined.$if\n";
|
|
|
|
if ($status == 2) {
|
|
# Interface is down
|
|
print "recv.value U\n";
|
|
print "send.value U\n";
|
|
print "send.extinfo This interface is currently down.\n";
|
|
goto if_errors;
|
|
}
|
|
|
|
$response = $snmpinfoX->{$if}->{ifHCInOctets} || $snmpinfo->{$if}->{ifInOctets};
|
|
printf("recv.value %s\n", defined($response) ? ($response * 8) : "U");
|
|
|
|
$response = $snmpinfoX->{$if}->{ifHCOutOctets} || $snmpinfo->{$if}->{ifOutOctets};
|
|
printf("send.value %s\n", defined($response) ? ($response * 8) : "U");
|
|
|
|
if_errors:
|
|
|
|
print "multigraph snmp_if_combined_err.$if\n";
|
|
|
|
if ($status == 2) {
|
|
print <<END;
|
|
errors_in.value U
|
|
errors_out.value U
|
|
discards_in.value U
|
|
discards_out.value U
|
|
total_in.value U
|
|
total_out.value U
|
|
errors_out.extinfo This interface is currently down
|
|
END
|
|
return;
|
|
}
|
|
|
|
my $errors = $snmpinfo->{$if}->{ifInErrors};
|
|
my $discards = $snmpinfo->{$if}->{ifInDiscards};
|
|
printf("errors_in %s\n".
|
|
"discards_in %s\n".
|
|
"total_in %s\n",
|
|
$errors || "U",
|
|
$discards || "U",
|
|
($errors || 0) + ($discards || 0)
|
|
);
|
|
|
|
$errors = $snmpinfo->{$if}->{ifOutErrors};
|
|
$discards = $snmpinfo->{$if}->{ifOutDiscards};
|
|
printf("errors_out %s\n".
|
|
"discards_out %s\n".
|
|
"total_out %s\n",
|
|
$errors || "U",
|
|
$discards || "U",
|
|
($errors || 0) + ($discards || 0)
|
|
);
|
|
}
|
|
|
|
sub do_config {
|
|
|
|
my ($host,undef,$version) = Munin::Plugin::SNMP->config_session();
|
|
|
|
print "host_name $host\n" unless $host eq 'localhost';
|
|
|
|
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
|
|
do_config_if($host,$version,$if);
|
|
}
|
|
|
|
do_config_root($host,$version);
|
|
}
|
|
|
|
# ############################## 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);
|
|
}
|