Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / snmp / snmp__if_combined @ 8589c6df

Historique | Voir | Annoter | Télécharger (20 ko)

1
#!/usr/bin/perl -w
2
# -*- perl -*-
3

    
4
=head1 NAME
5

    
6
snmp__if_combined - SNMP card plugin to monitor the network interfaces of any networked equipment.
7

    
8
=head1 APPLICABLE SYSTEMS
9

    
10
Any SNMP capable networked computer equipment.  Using a command such
11
as "munin-node-configure --snmp switch.langfeldt.net --snmpversion 2c
12
--snmpcommunity public | sh -x" should auto-detect all applicable
13
interfaces.  On a typical switch you will get one plugin pr. ethernet
14
port.  On a router you might get one plugin per VLAN interface.
15

    
16
=head1 CONFIGURATION
17

    
18
As a rule SNMP plugins need site specific configuration.  The default
19
configuration (shown here) will only work on insecure sites/devices:
20

    
21
   [snmp_*]
22
	env.version 2
23
        env.community public
24
        env.ifTypeOnly ethernetCsmacd
25

    
26
In general SNMP is not very secure at all unless you use SNMP version
27
3 which supports authentication and privacy (encryption).  But in any
28
case the community string for your devices should not be "public".
29

    
30
Please see 'perldoc Munin::Plugin::SNMP' for further configuration
31
information.
32

    
33
The ifTypeOnly is a space separated list of media types to show. To
34
see what interface types your switch, router, or other net thing uses
35
you can use this command:
36

    
37
  snmpwalk -c public -v 2c switch 1.3.6.1.2.1.2.2.1.3
38

    
39
It may show something like this:
40

    
41
  IF-MIB::ifType.1 = INTEGER: ethernetCsmacd(6)
42
  IF-MIB::ifType.4 = INTEGER: mplsTunnel(150)
43
  IF-MIB::ifType.5 = INTEGER: other(1)
44
  IF-MIB::ifType.6 = INTEGER: softwareLoopback(24)
45
  IF-MIB::ifType.8 = INTEGER: tunnel(131)
46
  IF-MIB::ifType.13 = INTEGER: propVirtual(53)
47
  IF-MIB::ifType.123 = INTEGER: l2vlan(135)
48

    
49
propVirtual or l2vlan is usually used for VLAN interfaces.  Tunnel
50
would normally be for VPNs.  A minor horde of different interface types
51
are supposted, please see IANAifType-MIB (on your system or find with
52
Google) for a full list.
53

    
54
=head1 INTERPRETATION
55

    
56
A single graph is generated with all the interfaces overlaid one over
57
the other: incoming traffic is received on the interface from the
58
connected device, outgoing is sent to it instead.
59

    
60
Sub-graphs are created, one per interface, akin to snmp__if_multi
61
plugin.
62

    
63
=head1 MIB INFORMATION
64

    
65
This plugin requires the IF-MIB the standard IETF MIB for network
66
interfaces.
67

    
68
It reports the contents of the
69
IF-MIB::ifHCInOctets/IF-MIB::ifHCOutOctets if available,
70
IF-MIB::ifInOctets/IF-MIB::ifOutOctets if not.  The former are 64 bit
71
counters only available with SNMP 2 and later.  The later are 32 bit
72
counters (see FEATURES below).
73

    
74
=head1 MAGIC MARKERS
75

    
76
  #%# family=snmpauto
77
  #%# capabilities=snmpconf
78

    
79
=head1 VERSION
80

    
81
  $Id: snmp__if_.in 1818 2009-01-03 19:29:30Z janl $
82

    
83
=head1 BUGS
84

    
85
Should support indexing by
86

    
87
  - ifIndex
88
  - ifName
89
  - ifDescr
90
  - ifAlias
91
  - mac-address
92

    
93
(and anything else MRTG can index by) in addition to OID-index as now.
94

    
95
Pulling in a user definable set of ifName/ifDescr/ifAlias for textual
96
description and even graph_title would also be nice.
97

    
98
IFF we get a patch to support the .oldname attribute then we may use
99
that to let the operator change the indexing dynamically without data
100
loss.
101

    
102
=head1 FEATURES
103

    
104
You may get strange results if you use SNMPv1, or SNMPv2 on
105
switches that do not support 64 bit byte counters.  If the interface
106
traffic exceeds about 50Mbps a 32 bit byte counter will wrap around in
107
less than 5 minutes making the graph for the interface show random
108
results.
109

    
110
If you have a switch/device that supports 64 bit byte counters this
111
plugin will use them and the graph will be fine.  The graph
112
information will inform about this.  You must use SNMPv2c or SNMPv3 to
113
be able to use 64 bit counters - if the device supports them.
114

    
115
This problem is a feature of the device SNMP implementation or your
116
usage of it, it is nothing the plugin can fix.  In the future Munin
117
may be able to run the plugin more often than the counter wraps
118
around.
119

    
120
=head1 AUTHOR
121

    
122
Copyright (C) 2012 Diego Elio Pettenò.
123

    
124
Original snmp__if_multi: Copyright (C) 2004-2010 Jimmy Olsen, Dagfinn
125
Ilmari Mannsaaker, Nicolai Langfeldt, Redpill Linpro AS and others.
126

    
127
Original snmp__if_ plugin: Copyright (C) 2004-2009 Jimmy Olsen, Dagfinn
128
Ilmari Mannsaaker.
129

    
130
Initial SNMPv3 support by "Confusedhacker".
131

    
132
Documentation, porting to Munin::Plugin::SNMP and
133
further grooming by Nicolai Langfeldt.
134

    
135
Reworked to snmp__if_multi by Nicolai Langfeldt.
136

    
137
Reworked to snmp__if_combined by Diego Elio Pettenò.
138

    
139
=head1 LICENSE
140

    
141
GPLv2
142

    
143
=cut
144

    
145
use strict;
146
use Munin::Plugin;
147
use Munin::Plugin::SNMP;
148

    
149
my $response;
150
my $iface;
151

    
152
# This is the snmpwalk:
153
# .1.3.6.1.2.1.2.1.0 = INTEGER: 2
154
# .1.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1
155
# .1.3.6.1.2.1.2.2.1.1.65539 = INTEGER: 65539
156
# .1.3.6.1.2.1.2.2.1.2.1 = STRING: MS TCP Loopback interface
157
# .1.3.6.1.2.1.2.2.1.2.65539 = STRING: Broadcom NetXtreme Gigabit Ethernet
158
# .1.3.6.1.2.1.2.2.1.3.1 = INTEGER: softwareLoopback(24)
159
# .1.3.6.1.2.1.2.2.1.3.65539 = INTEGER: ethernetCsmacd(6)
160
# .1.3.6.1.2.1.2.2.1.4.1 = INTEGER: 1520
161
# .1.3.6.1.2.1.2.2.1.4.65539 = INTEGER: 1500
162
# .1.3.6.1.2.1.2.2.1.5.1 = Gauge32: 10000000
163
# .1.3.6.1.2.1.2.2.1.5.65539 = Gauge32: 1000000000
164
# .1.3.6.1.2.1.2.2.1.6.1 = STRING:
165
# .1.3.6.1.2.1.2.2.1.6.65539 = STRING: 0:30:48:75:65:5e
166
# .1.3.6.1.2.1.2.2.1.7.1 = INTEGER: up(1)
167
# .1.3.6.1.2.1.2.2.1.7.65539 = INTEGER: up(1)
168
# .1.3.6.1.2.1.2.2.1.8.1 = INTEGER: up(1)
169
# .1.3.6.1.2.1.2.2.1.8.65539 = INTEGER: up(1)
170
#
171
# 64 bit counters:
172
# .1.3.6.1.2.1.31.1.1.1.6.   Counter64 ifHCInOctets
173
# .1.3.6.1.2.1.31.1.1.1.10.  Counter64 ifHCOutOctets
174

    
175
if (defined $ARGV[0] and $ARGV[0] eq "snmpconf") {
176
	print "require 1.3.6.1.2.1.2.2.1.1.\n";
177
	exit 0;
178
}
179

    
180
my $sysDescr           = '1.3.6.1.2.1.1.1.0';
181
my $sysLocation        = '1.3.6.1.2.1.1.6.0';
182
my $sysContact         = '1.3.6.1.2.1.1.4.0';
183
my $sysName            = '1.3.6.1.2.1.1.5.0';
184

    
185
my $ifOIDBase          = "1.3.6.1.2.1.2.2.1";		# ifEntry
186
my $ifv2OIDBase        = "1.3.6.1.2.1.31.1.1.1";	# ifXEntry
187

    
188
my %ifTypes = (
189
    other => 1,
190
    regular1822 => 2,
191
    hdh1822 => 3,
192
    ddnX25 => 4,
193
    rfc877x25 => 5,
194
    ethernetCsmacd => 6,
195
    iso88023Csmacd => 7,
196
    iso88024TokenBus => 8,
197
    iso88025TokenRing => 9,
198
    iso88026Man => 10,
199
    starLan => 11,
200
    proteon10Mbit => 12,
201
    proteon80Mbit => 13,
202
    hyperchannel => 14,
203
    fddi => 15,
204
    lapb => 16,
205
    sdlc => 17,
206
    ds1 => 18,
207
    e1 => 19,
208
    basicISDN => 20,
209
    primaryISDN => 21,
210
    propPointToPointSerial => 22,
211
    ppp => 23,
212
    softwareLoopback => 24,
213
    eon => 25,
214
    ethernet3Mbit => 26,
215
    nsip => 27,
216
    slip => 28,
217
    ultra => 29,
218
    ds3 => 30,
219
    sip => 31,
220
    frameRelay => 32,
221
    rs232 => 33,
222
    para => 34,
223
    arcnet => 35,
224
    arcnetPlus => 36,
225
    atm => 37,
226
    miox25 => 38,
227
    sonet => 39,
228
    x25ple => 40,
229
    iso88022llc => 41,
230
    localTalk => 42,
231
    smdsDxi => 43,
232
    frameRelayService => 44,
233
    v35 => 45,
234
    hssi => 46,
235
    hippi => 47,
236
    modem => 48,
237
    aal5 => 49,
238
    sonetPath => 50,
239
    sonetVT => 51,
240
    smdsIcip => 52,
241
    propVirtual => 53,
242
    propMultiplexor => 54,
243
    ieee80212 => 55,
244
    fibreChannel => 56,
245
    hippiInterface => 57,
246
    frameRelayInterconnect => 58,
247
    aflane8023 => 59,
248
    aflane8025 => 60,
249
    cctEmul => 61,
250
    fastEther => 62,
251
    isdn => 63,
252
    v11 => 64,
253
    v36 => 65,
254
    g703at64k => 66,
255
    g703at2mb => 67,
256
    qllc => 68,
257
    fastEtherFX => 69,
258
    channel => 70,
259
    ieee80211 => 71,
260
    ibm370parChan => 72,
261
    escon => 73,
262
    dlsw => 74,
263
    isdns => 75,
264
    isdnu => 76,
265
    lapd => 77,
266
    ipSwitch => 78,
267
    rsrb => 79,
268
    atmLogical => 80,
269
    ds0 => 81,
270
    ds0Bundle => 82,
271
    bsc => 83,
272
    async => 84,
273
    cnr => 85,
274
    iso88025Dtr => 86,
275
    eplrs => 87,
276
    arap => 88,
277
    propCnls => 89,
278
    hostPad => 90,
279
    termPad => 91,
280
    frameRelayMPI => 92,
281
    x213 => 93,
282
    adsl => 94,
283
    radsl => 95,
284
    sdsl => 96,
285
    vdsl => 97,
286
    iso88025CRFPInt => 98,
287
    myrinet => 99,
288
    voiceEM => 100,
289
    voiceFXO => 101,
290
    voiceFXS => 102,
291
    voiceEncap => 103,
292
    voiceOverIp => 104,
293
    atmDxi => 105,
294
    atmFuni => 106,
295
    atmIma => 107,
296
    pppMultilinkBundle => 108,
297
    ipOverCdlc => 109,
298
    ipOverClaw => 110,
299
    stackToStack => 111,
300
    virtualIpAddress => 112,
301
    mpc => 113,
302
    ipOverAtm => 114,
303
    iso88025Fiber => 115,
304
    tdlc => 116,
305
    gigabitEthernet => 117,
306
    hdlc => 118,
307
    lapf => 119,
308
    v37 => 120,
309
    x25mlp => 121,
310
    x25huntGroup => 122,
311
    trasnpHdlc => 123,
312
    interleave => 124,
313
    fast => 125,
314
    ip => 126,
315
    docsCableMaclayer => 127,
316
    docsCableDownstream => 128,
317
    docsCableUpstream => 129,
318
    a12MppSwitch => 130,
319
    tunnel => 131,
320
    coffee => 132,
321
    ces => 133,
322
    atmSubInterface => 134,
323
    l2vlan => 135,
324
    l3ipvlan => 136,
325
    l3ipxvlan => 137,
326
    digitalPowerline => 138,
327
    mediaMailOverIp => 139,
328
    dtm => 140,
329
    dcn => 141,
330
    ipForward => 142,
331
    msdsl => 143,
332
    ieee1394 => 144,
333
    'if-gsn' => 145,
334
    dvbRccMacLayer => 146,
335
    dvbRccDownstream => 147,
336
    dvbRccUpstream => 148,
337
    atmVirtual => 149,
338
    mplsTunnel => 150,
339
    srp => 151,
340
    voiceOverAtm => 152,
341
    voiceOverFrameRelay => 153,
342
    idsl => 154,
343
    compositeLink => 155,
344
    ss7SigLink => 156,
345
    propWirelessP2P => 157,
346
    frForward => 158,
347
    rfc1483 => 159,
348
    usb => 160,
349
    ieee8023adLag => 161,
350
    bgppolicyaccounting => 162,
351
    frf16MfrBundle => 163,
352
    h323Gatekeeper => 164,
353
    h323Proxy => 165,
354
    mpls => 166,
355
    mfSigLink => 167,
356
    hdsl2 => 168,
357
    shdsl => 169,
358
    ds1FDL => 170,
359
    pos => 171,
360
    dvbAsiIn => 172,
361
    dvbAsiOut => 173,
362
    plc => 174,
363
    nfas => 175,
364
    tr008 => 176,
365
    gr303RDT => 177,
366
    gr303IDT => 178,
367
    isup => 179,
368
    propDocsWirelessMaclayer => 180,
369
    propDocsWirelessDownstream => 181,
370
    propDocsWirelessUpstream => 182,
371
    hiperlan2 => 183,
372
    propBWAp2Mp => 184,
373
    sonetOverheadChannel => 185,
374
    digitalWrapperOverheadChannel => 186,
375
    aal2 => 187,
376
    radioMAC => 188,
377
    atmRadio => 189,
378
    imt => 190,
379
    mvl => 191,
380
    reachDSL => 192,
381
    frDlciEndPt => 193,
382
    atmVciEndPt => 194,
383
    opticalChannel => 195,
384
    opticalTransport => 196,
385
    propAtm => 197,
386
    voiceOverCable => 198,
387
    infiniband => 199,
388
    teLink => 200,
389
    q2931 => 201,
390
    virtualTg => 202,
391
    sipTg => 203,
392
    sipSig => 204,
393
    docsCableUpstreamChannel => 205,
394
    econet => 206,
395
    pon155 => 207,
396
    pon622 => 208,
397
    bridge => 209,
398
    linegroup => 210,
399
    voiceEMFGD => 211,
400
    voiceFGDEANA => 212,
401
    voiceDID => 213,
402
    mpegTransport => 214,
403
    sixToFour => 215,
404
    gtp => 216,
405
    pdnEtherLoop1 => 217,
406
    pdnEtherLoop2 => 218,
407
    opticalChannelGroup => 219,
408
    homepna => 220,
409
    gfp => 221,
410
    ciscoISLvlan => 222,
411
    actelisMetaLOOP => 223,
412
    fcipLink => 224,
413
    rpr => 225,
414
    qam => 226,
415
    lmp => 227,
416
    cblVectaStar => 228,
417
    docsCableMCmtsDownstream => 229,
418
    adsl2 => 230,
419
    macSecControlledIF => 231,
420
    macSecUncontrolledIF => 232,
421
    aviciOpticalEther => 233,
422
    atmbond => 234,
423
    voiceFGDOS => 235,
424
    mocaVersion1 => 236,
425
    ieee80216WMAN => 237,
426
    adsl2plus => 238,
427
    dvbRcsMacLayer => 239,
428
    dvbTdm => 240,
429
    dvbRcsTdma => 241,
430
    x86Laps => 242,
431
    wwanPP => 243,
432
    wwanPP2 => 244
433
    );
434

    
435
my %ifTypeByNum = map { $ifTypes{$_} => $_; } keys %ifTypes;
436

    
437
# Needed as globals
438
my $snmpinfo;
439
my $snmpinfoX;
440

    
441
sub do_collect {
442
    # Collect information from SNMP agent
443

    
444
    my $session = Munin::Plugin::SNMP->session();
445

    
446
    $snmpinfo = $session->get_hash(
447
	-baseoid => $ifOIDBase,
448
	-cols    =>
449
	{ 2  => 'ifDescr',
450
	  # Type: See above
451
	  3  => 'ifType',
452
	  5  => 'ifSpeed',
453
	  # Oper: 1) up 2) down 3) testing
454
	  # 4) unknown, 5) dormant 6) not present
455
	  # 7) lowerLayerDown
456
	  8  => 'ifOperStatus',
457
	  10 => 'ifInOctets',
458
	  13 => 'ifInDiscards',
459
	  14 => 'ifInErrors',
460
	  16 => 'ifOutOctets',
461
	  19 => 'ifOutDiscards',
462
	  20 => 'ifOutErrors',
463
	});
464

    
465
    # ifXEntry - SNMP v2 and up only - on some devices
466
    $snmpinfoX = $session->get_hash(
467
	-baseoid => $ifv2OIDBase,
468
	-cols    =>
469
	{ 6  => 'ifHCInOctets',
470
	  10 => 'ifHCOutOctets',
471
	  15 => 'ifHighSpeed',
472
	  18 => 'ifAlias',
473
	});
474
}
475

    
476

    
477

    
478
sub do_preprocess_if {
479
    my ($mediatype, $if) = @_;
480

    
481
    my $response = $snmpinfo->{$if}->{ifType} || 1;
482

    
483
    if (defined($mediatype)) {
484
	if (defined($mediatype->{$response})) {
485
	    # This is one of the interesting media types
486
	} else {
487
	    # This media type is not interesting.  Remove.
488
	    delete $snmpinfo->{$if} if exists $snmpinfo->{$if};
489
	    delete $snmpinfoX->{$if} if exists $snmpinfoX->{$if};
490
	    return;
491
	}
492
    }
493

    
494
    if (defined ($response = $snmpinfo->{$if}->{ifOperStatus})) {
495
	# 1 = up,  2 = down,  7 = lowerLayerDown
496
	if ($response == 2 or $response == 7) {
497
	    # Fold recognized down states into one.
498
	    $response = $snmpinfo->{$if}->{ifOperStatus} = 2;
499
	} elsif ($response != 1) {
500
	    # This interface is fishy, remove and forget.
501
	    delete $snmpinfo->{$if} if exists $snmpinfo->{$if};
502
	    delete $snmpinfoX->{$if} if exists $snmpinfoX->{$if};
503
	    return;
504
	}
505
    }
506
}
507

    
508

    
509
sub do_preprocess {
510
    my $mediatypes = 'ALL';
511

    
512
    if (exists( $ENV{'ifTypeOnly'} )) {
513
	$mediatypes = $ENV{'ifTypeOnly'};
514
    }
515

    
516
    my @mediatypes = split(/[ ,]+/,$mediatypes);
517

    
518
    # Hash of numerical media types the user finds interesting.
519
    my $mediatype={};
520

    
521
    if ($mediatypes eq 'ALL') {
522
	$mediatype = undef;
523
    } else {
524
	foreach my $type (@mediatypes) {
525
	    if (exists($ifTypes{$type})) {
526
		$mediatype->{$ifTypes{$type}} = 1;
527
	    } else {
528
		die "Unknown media type '$type' specified in ifTypeOnly\n";
529
	    }
530
	}
531
    }
532

    
533
    foreach my $if (keys %{$snmpinfo}) {
534
	do_preprocess_if($mediatype, $if);
535
    }
536
}
537

    
538

    
539
sub do_config_root {
540
    my ($host, $version) = @_;
541

    
542
    my $extrainfo="";
543

    
544
    if (defined ($snmpinfoX->{0}->{ifHCInOctets})) {
545
	# If we get an answer at the 64 bit OID then this switch
546
	# supports the extended MIB
547

    
548
	$extrainfo .= " This switch supports 64 bit byte counters and these are used by this plugin.";
549
    } else {
550
	# If not we only have a 32 bit counter and are lost.
551
	$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.";
552

    
553
	# unless perhaps the operator can get us snmp version 2c or 3?
554
	$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."
555
	  if $version == 1;
556
    }
557

    
558
    print <<END;
559

    
560
multigraph snmp_if_combined
561
graph_title $host interfaces traffic
562
graph_args --base 1000
563
graph_vlabel bits in (-) / out (+) per \${graph_period}
564
graph_category network
565
graph_info This graph shows the total traffic for $host.$extrainfo
566
END
567

    
568
    print "graph_order";
569
    foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
570
      print " recv$if=snmp_if_combined.$if.recv send$if=snmp_if_combined.$if.send";
571
    }
572
    print "\n";
573

    
574
    foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
575
      my $alias = $snmpinfo->{$if}->{ifDescr} || "Interface $if";
576

    
577
      if (! ($alias =~ /\d+/) ) {
578
	# If there are no numbers in the $alias add the if index
579
	$alias .=" (if $if)";
580
      }
581

    
582
      print <<END;
583
recv$if.label $alias
584
recv$if.graph no
585
send$if.label $alias
586
send$if.negative recv$if
587
END
588
    }
589

    
590
    print <<END;
591

    
592
multigraph snmp_if_combined_err
593
graph_title $host interfaces errors
594
graph_args --base 1000
595
graph_vlabel errors in (-) / out (+) per \${graph_period}
596
graph_category network
597
END
598

    
599
    print "graph_order";
600
    foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
601
      print " recv$if=snmp_if_combined_err.$if.total_in send$if=snmp_if_combined_err.$if.total_out";
602
    }
603
    print "\n";
604

    
605
    foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
606
      my $alias = $snmpinfoX->{$if}->{ifAlias} || $snmpinfo->{$if}->{ifDescr} || "Interface $if";
607

    
608
      if (! ($alias =~ /\d+/) ) {
609
	# If there are no numbers in the $alias add the if index
610
	$alias .=" (if $if)";
611
      }
612

    
613
      print <<END;
614
recv$if.label $alias
615
recv$if.graph no
616
send$if.label $alias
617
send$if.negative recv$if
618
END
619
    }
620
}
621

    
622
sub do_config_if {
623
    my ($host,$version,$if) = @_;
624

    
625
    my $alias = $snmpinfoX->{$if}->{ifAlias} || $snmpinfo->{$if}->{ifDescr} || "Interface $if";
626

    
627
    if (! ($alias =~ /\d+/) ) {
628
	# If there are no numbers in the $alias add the if index
629
	$alias .=" (if $if)";
630
    }
631

    
632
    my $warn = undef;
633
    my $speed = 0;
634
    my $extrainfo = "";
635

    
636
    if (defined ($speed = $snmpinfoX->{$if}->{ifHighSpeed}) and $speed) {
637
      # Speed in 1,000,000 bits per second
638
      $speed = $speed * 1000000;
639
      $warn = $speed / 75 * 100;
640

    
641
      my $textspeed = scaleNumber($speed,'bps','',
642
				  'The interface speed is %.1f%s%s.');
643

    
644
      $extrainfo .= ' '.$textspeed if $textspeed;
645
    } elsif (defined ($speed = $snmpinfo->{$if}->{ifSpeed}) and $speed) {
646
        # Speed in bits pr. second
647
	$warn = $speed*100/75;
648

    
649
	my $textspeed = scaleNumber($speed,'bps','',
650
				    'The interface speed is %.1f%s%s.');
651

    
652
	$extrainfo .= " ".$textspeed if $textspeed;
653
    }
654

    
655
    $response = $snmpinfo->{$if}->{ifType};
656

    
657
    print <<END;
658
multigraph snmp_if_combined.$if
659
graph_title $alias traffic
660
graph_args --base 1000
661
graph_vlabel bits in (-) / out (+) per \${graph_period}
662
graph_category network
663

    
664
recv.label bps
665
recv.type DERIVE
666
recv.graph no
667
recv.min 0
668
send.label bps
669
send.type DERIVE
670
send.negative recv
671
send.min 0
672
END
673

    
674
    if ( defined($speed) ) {
675
      printf("recv.max %s\nsend.max %s\n", $speed, $speed);
676
    }
677

    
678
    if ( defined($warn) ) {
679
      printf("recv.warning %s\nsend.warning %s\n", $warn, $warn);
680
    }
681

    
682
    print <<END;
683
multigraph snmp_if_combined_err.$if
684
graph_title $alias errors
685
graph_args --base 1000
686
graph_vlabel errors in (-) / out (+) per \${graph_period}
687
graph_category network
688

    
689
errors_in.label $alias
690
errors_in.graph no
691
errors_in.label recv
692
errors_in.type DERIVE
693
errors_in.min 0
694
errors_out.label Errors
695
errors_out.negative errors_in
696
errors_out.type DERIVE
697
errors_out.min 0
698

    
699
discards_in.label $alias
700
discards_in.graph no
701
discards_in.type DERIVE
702
discards_in.min 0
703
discards_out.label Discards
704
discards_out.negative discards_in
705
discards_out.type DERIVE
706
discards_out.min 0
707

    
708
total_in.label $alias
709
total_in.graph no
710
total_in.type DERIVE
711
total_in.min 0
712
total_out.label $alias
713
total_out.graph no
714
total_out.type DERIVE
715
total_out.min 0
716
END
717
}
718

    
719
sub do_fetch_if {
720
    my($if) = @_;
721

    
722
    my $status = $snmpinfo->{$if}->{ifOperStatus} || 1;
723

    
724
    my $response;
725

    
726
    # 1 means up
727
    # 2 means set to down
728
    # Everything else we ignore.
729

    
730
    print "multigraph snmp_if_combined.$if\n";
731

    
732
    if ($status == 2) {
733
	# Interface is down
734
	print "recv.value U\n";
735
	print "send.value U\n";
736
	print "send.extinfo This interface is currently down.\n";
737
	goto if_errors;
738
    }
739

    
740
    $response = $snmpinfoX->{$if}->{ifHCInOctets} || $snmpinfo->{$if}->{ifInOctets};
741
    printf("recv.value %s\n", defined($response) ? ($response * 8) : "U");
742

    
743
    $response = $snmpinfoX->{$if}->{ifHCOutOctets} || $snmpinfo->{$if}->{ifOutOctets};
744
    printf("send.value %s\n", defined($response) ? ($response * 8) : "U");
745

    
746
  if_errors:
747

    
748
    print "multigraph snmp_if_combined_err.$if\n";
749

    
750
    if ($status == 2) {
751
	print <<END;
752
errors_in.value U
753
errors_out.value U
754
discards_in.value U
755
discards_out.value U
756
total_in.value U
757
total_out.value U
758
errors_out.extinfo This interface is currently down
759
END
760
	return;
761
    }
762

    
763
    my $errors = $snmpinfo->{$if}->{ifInErrors};
764
    my $discards = $snmpinfo->{$if}->{ifInDiscards};
765
    printf("errors_in %s\n".
766
	   "discards_in %s\n".
767
	   "total_in %s\n",
768
	   $errors || "U",
769
	   $discards || "U",
770
	   ($errors || 0) + ($discards || 0)
771
	  );
772

    
773
    $errors = $snmpinfo->{$if}->{ifOutErrors};
774
    $discards = $snmpinfo->{$if}->{ifOutDiscards};
775
    printf("errors_out %s\n".
776
	   "discards_out %s\n".
777
	   "total_out %s\n",
778
	   $errors || "U",
779
	   $discards || "U",
780
	   ($errors || 0) + ($discards || 0)
781
	  );
782
}
783

    
784
sub do_config {
785

    
786
    my ($host,undef,$version) = Munin::Plugin::SNMP->config_session();
787

    
788
    print "host_name $host\n" unless $host eq 'localhost';
789

    
790
    foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
791
	do_config_if($host,$version,$if);
792
    }
793

    
794
    do_config_root($host,$version);
795
}
796

    
797
# ############################## MAIN ################################
798

    
799
do_collect;
800
do_preprocess;
801

    
802
if ($ARGV[0] and $ARGV[0] eq "config") {
803
    do_config();
804
    exit 0;
805
}
806

    
807
foreach my $if (sort {$a <=> $b} keys %{$snmpinfo}) {
808
    do_fetch_if($if);
809
}