1# SNMP::Info::Layer2::Baystack
2#
3# Copyright (c) 2008 Max Baker changes from version 0.8 and beyond.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are met:
8#
9#     * Redistributions of source code must retain the above copyright notice,
10#       this list of conditions and the following disclaimer.
11#     * Redistributions in binary form must reproduce the above copyright
12#       notice, this list of conditions and the following disclaimer in the
13#       documentation and/or other materials provided with the distribution.
14#     * Neither the name of the University of California, Santa Cruz nor the
15#       names of its contributors may be used to endorse or promote products
16#       derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22# LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29
30package SNMP::Info::Layer2::Baystack;
31
32use strict;
33use warnings;
34use Exporter;
35use SNMP::Info::SONMP;
36use SNMP::Info::NortelStack;
37use SNMP::Info::RapidCity;
38use SNMP::Info::Layer3;
39
40@SNMP::Info::Layer2::Baystack::ISA
41    = qw/SNMP::Info::SONMP SNMP::Info::NortelStack
42    SNMP::Info::RapidCity
43    SNMP::Info::Layer3 Exporter/;
44@SNMP::Info::Layer2::Baystack::EXPORT_OK = qw//;
45
46our ($VERSION, %FUNCS, %GLOBALS, %MIBS, %MUNGE);
47
48$VERSION = '3.81';
49
50%MIBS = (
51    %SNMP::Info::Layer3::MIBS,
52    %SNMP::Info::RapidCity::MIBS, %SNMP::Info::NortelStack::MIBS,
53    %SNMP::Info::SONMP::MIBS,
54    'BAY-STACK-PETH-EXT-MIB' => 'bspePethPsePortExtMeasuredPower',
55);
56
57%GLOBALS = (
58    %SNMP::Info::Layer3::GLOBALS,
59    %SNMP::Info::RapidCity::GLOBALS, %SNMP::Info::NortelStack::GLOBALS,
60    %SNMP::Info::SONMP::GLOBALS,
61);
62
63%FUNCS = (
64    %SNMP::Info::Layer3::FUNCS,
65    %SNMP::Info::RapidCity::FUNCS, %SNMP::Info::NortelStack::FUNCS,
66    %SNMP::Info::SONMP::FUNCS,
67    'peth_port_power' => 'bspePethPsePortExtMeasuredPower',
68);
69
70# 450's report full duplex as speed = 20mbps?!
71$SNMP::Info::SPEED_MAP{20_000_000}    = '10 Mbps';
72$SNMP::Info::SPEED_MAP{200_000_000}   = '100 Mbps';
73$SNMP::Info::SPEED_MAP{2_000_000_000} = '1.0 Gbps';
74
75%MUNGE = (
76    %SNMP::Info::Layer3::MUNGE,
77    %SNMP::Info::RapidCity::MUNGE, %SNMP::Info::NortelStack::MUNGE,
78    %SNMP::Info::SONMP::MUNGE,
79);
80
81sub os {
82    my $baystack = shift;
83    my $descr    = $baystack->description() || "";
84    my $model    = $baystack->model() || "";
85
86    if ( $descr =~ /Business Ethernet Switch.*SW:v/i ) {
87        return 'bes';
88    }
89    if (   ( ( $model =~ /(420|425|BPS)/ ) and ( $descr =~ m/SW:v[1-2]/i ) )
90        or ( ( $model =~ /(410|450|380)/ ) ) )
91    {
92        return 'baystack';
93    }
94    if ( $model =~ /VSP/ ) {
95        return 'vsp';
96    }
97
98    return 'boss';
99}
100
101sub os_bin {
102    my $baystack = shift;
103    my $descr    = $baystack->description();
104    return unless defined $descr;
105
106    # 303 / 304
107    if ( $descr =~ m/Rev: \d+\.(\d+\.\d+\.\d+)-\d+\.\d+\.\d+\.\d+/ ) {
108        return $1;
109    }
110
111    # 450
112    if ( $descr =~ m/FW:V(\d+\.\d+)/ ) {
113        return $1;
114    }
115
116    if ( $descr =~ m/FW:(\d+\.\d+\.\d+\.\d+)/i ) {
117        return $1;
118    }
119    return;
120}
121
122sub vendor {
123    return 'avaya';
124}
125
126sub model {
127    my $baystack = shift;
128    my $id       = $baystack->id();
129    return unless defined $id;
130    my $model = &SNMP::translateObj($id);
131    return $id unless defined $model;
132
133    my $descr = $baystack->description();
134
135    return '303' if ( defined $descr and $descr =~ /\D303\D/ );
136    return '304' if ( defined $descr and $descr =~ /\D304\D/ );
137    return 'BPS' if ( $model =~ /BPS2000/i );
138
139    # Pull sreg- from all
140    $model =~ s/^sreg-//;
141    # Strip ES/ERS/BayStack etc. from those families
142    $model =~ s/^(E(R)?S|BayStack|Ethernet(Routing)?Switch)-?//;
143    $model =~ s/-ethSwitchNMM//;
144
145    return $model;
146}
147
148sub interfaces {
149    my $baystack = shift;
150    my $partial  = shift;
151
152    my $i_index      = $baystack->i_index($partial) || {};
153    my $index_factor = $baystack->index_factor();
154    my $slot_offset  = $baystack->slot_offset();
155
156    my %if;
157    foreach my $iid ( keys %$i_index ) {
158        my $index = $i_index->{$iid};
159        next unless defined $index;
160
161        # Ignore cascade ports
162        next if $index > $index_factor * 8;
163
164        my $port = ( $index % $index_factor );
165        my $slot = ( int( $index / $index_factor ) ) + $slot_offset;
166
167        my $slotport = "$slot.$port";
168        $if{$iid} = $slotport;
169    }
170    return \%if;
171}
172
173sub i_mac {
174    my $baystack = shift;
175    my $partial  = shift;
176
177    my $i_mac = $baystack->orig_i_mac($partial) || {};
178
179    my %i_mac;
180
181    # Baystack 303's with a hw rev < 2.11.4.5 report the mac as all zeros
182    foreach my $iid ( keys %$i_mac ) {
183        my $mac = $i_mac->{$iid};
184        next unless defined $mac;
185        next if $mac eq '00:00:00:00:00:00';
186        $i_mac{$iid} = $mac;
187    }
188    return \%i_mac;
189}
190
191sub i_name {
192    my $baystack = shift;
193    my $partial  = shift;
194
195    my $i_index = $baystack->i_index($partial)     || {};
196    my $i_alias = $baystack->i_alias($partial)     || {};
197    my $i_name2 = $baystack->orig_i_name($partial) || {};
198
199    my %i_name;
200    foreach my $iid ( keys %$i_name2 ) {
201        my $name  = $i_name2->{$iid};
202        my $alias = $i_alias->{$iid};
203        $i_name{$iid}
204            = ( defined $alias and $alias !~ /^\s*$/ )
205            ? $alias
206            : $name;
207    }
208
209    return \%i_name;
210}
211
212sub index_factor {
213    my $baystack = shift;
214    my $model    = $baystack->model() || "";
215    my $os       = $baystack->os();
216    my $os_ver   = $baystack->os_ver();
217    my $op_mode  = $baystack->ns_op_mode();
218
219    $op_mode = 'pure' unless defined $op_mode;
220    if ( $os_ver =~ m/^(\d+)\./ ) {
221        $os_ver = $1;
222    } else {
223        $os_ver = 1;
224    }
225
226    my $index_factor = 32;
227    $index_factor = 64
228        if ( ( $model =~ /(470)/ )
229        or ( $os =~ m/(boss|bes)/ ) and ( $op_mode eq 'pure' ) );
230    $index_factor = 128
231        if ( ( $model =~ /(5[56]\d\d)|VSP|4950|59100/ )
232        and ( $os_ver >= 6 ) );
233
234    return $index_factor;
235}
236
237
238
239# Newer devices support ENTITY-MIB, use if available otherwise use proprietary
240# methods.
241
242sub e_index {
243    my $stack   = shift;
244    my $partial = shift;
245
246    return $stack->SUPER::e_index($partial) || $stack->ns_e_index($partial);
247}
248
249sub e_class {
250    my $stack   = shift;
251    my $partial = shift;
252
253    return $stack->SUPER::e_class($partial) || $stack->ns_e_class($partial);
254}
255
256sub e_descr {
257    my $stack   = shift;
258    my $partial = shift;
259
260    return $stack->SUPER::e_descr($partial) || $stack->ns_e_descr($partial);
261}
262
263sub e_name {
264    my $stack   = shift;
265    my $partial = shift;
266
267    return $stack->SUPER::e_name($partial) || $stack->ns_e_name($partial);
268}
269
270sub e_fwver {
271    my $stack   = shift;
272    my $partial = shift;
273
274    return $stack->SUPER::e_fwver($partial) || $stack->ns_e_fwver($partial);
275}
276
277sub e_hwver {
278    my $stack   = shift;
279    my $partial = shift;
280
281    return $stack->SUPER::e_hwver($partial) || $stack->ns_e_hwver($partial);
282}
283
284sub e_parent {
285    my $stack   = shift;
286    my $partial = shift;
287
288    return $stack->SUPER::e_parent($partial) || $stack->ns_e_parent($partial);
289}
290
291sub e_pos {
292    my $stack   = shift;
293    my $partial = shift;
294
295    return $stack->SUPER::e_pos($partial) || $stack->ns_e_pos($partial);
296}
297
298sub e_serial {
299    my $stack   = shift;
300    my $partial = shift;
301
302    return $stack->SUPER::e_serial($partial) || $stack->ns_e_serial($partial);
303}
304
305sub e_swver {
306    my $stack   = shift;
307    my $partial = shift;
308
309    return $stack->SUPER::e_swver($partial) || $stack->ns_e_swver($partial);
310}
311
312sub e_type {
313    my $stack   = shift;
314    my $partial = shift;
315
316    return $stack->SUPER::e_type($partial) || $stack->ns_e_type($partial);
317}
318
319sub e_vendor {
320    my $stack   = shift;
321    my $partial = shift;
322
323    return $stack->SUPER::e_vendor($partial) || $stack->ns_e_vendor($partial);
324}
325
326# fix for stack of switches without POE on module 1
327# https://sourceforge.net/tracker/?func=detail&aid=3317739&group_id=70362&atid=527529
328sub peth_port_ifindex {
329    my $stack = shift;
330    my $partial = shift;
331
332    my %peth_port_ifindex = ();
333    my $poe_port_st = $stack->peth_port_status($partial);
334    my $if_index = $stack->interfaces($partial);
335
336    foreach my $i (keys %$if_index) {
337        next unless defined $poe_port_st->{$if_index->{$i}};
338        $peth_port_ifindex{$if_index->{$i}} = $i;
339    }
340    return \%peth_port_ifindex;
341}
342
343# Currently only ERS 4800 v5.8+ support the rcBridgeSpbmMacTable
344# which holds the FDB for a SPBM edge deployment.
345#
346# Q-BRIDGE still holds some entries when the rcBridgeSpbmMacTable is in use
347# so we merge hash entries.
348
349sub fw_mac {
350    my $rapidcity = shift;
351
352    my $qb = $rapidcity->SUPER::fw_mac() || {};
353    my $spbm = $rapidcity->rc_spbm_fw_mac() || {};
354    my $fw_mac = { %$qb, %$spbm };
355
356    return $fw_mac;
357}
358
359sub fw_port {
360    my $rapidcity = shift;
361
362    my $qb = $rapidcity->SUPER::fw_port() || {};
363    my $spbm = $rapidcity->rc_spbm_fw_port() || {};
364    my $fw_port = { %$qb, %$spbm };
365
366    return $fw_port;
367}
368
369sub fw_status {
370    my $rapidcity = shift;
371
372    my $qb = $rapidcity->SUPER::fw_status() || {};
373    my $spbm = $rapidcity->rc_spbm_fw_status() || {};
374    my $fw_status = { %$qb, %$spbm };
375
376    return $fw_status;
377}
378
379sub qb_fw_vlan {
380    my $rapidcity = shift;
381
382    my $qb = $rapidcity->SUPER::qb_fw_vlan() || {};
383    my $spbm = $rapidcity->rc_spbm_fw_vlan() || {};
384    my $qb_fw_vlan = { %$qb, %$spbm };
385
386    return $qb_fw_vlan;
387}
388
389# Baystack uses S5-AGENT-MIB (loaded in NortelStack) versus RAPID-CITY
390sub stp_ver {
391    my $rapidcity = shift;
392
393    return $rapidcity->s5AgSysSpanningTreeOperMode()
394      || $rapidcity->SUPER::stp_ver();
395}
396
3971;
398
399__END__
400
401=head1 NAME
402
403SNMP::Info::Layer2::Baystack - SNMP Interface to Avaya Ethernet Switch
404(Baystack) and VSP 7000 series switches
405
406=head1 AUTHOR
407
408Eric Miller
409
410=head1 SYNOPSIS
411
412 # Let SNMP::Info determine the correct subclass for you.
413 my $baystack = new SNMP::Info(
414                          AutoSpecify => 1,
415                          Debug       => 1,
416                          DestHost    => 'myswitch',
417                          Community   => 'public',
418                          Version     => 2
419                        )
420  or die "Can't connect to DestHost.\n";
421
422 my $class = $baystack->class();
423 print "SNMP::Info determined this device to fall under subclass : $class\n";
424
425=head1 DESCRIPTION
426
427Provides abstraction to the configuration information obtainable from an
428Avaya Ethernet Switch (formerly Nortel/Bay Baystack) and VSP 7000 series
429through SNMP.
430
431=head2 Inherited Classes
432
433=over
434
435=item SNMP::Info::SONMP
436
437=item SNMP::Info::NortelStack
438
439=item SNMP::Info::RapidCity
440
441=item SNMP::Info::Layer3
442
443=back
444
445=head2 Required MIBs
446
447=over
448
449=item F<BAY-STACK-PETH-EXT-MIB>
450
451=back
452
453=head2 Inherited MIBs
454
455See L<SNMP::Info::SONMP/"Required MIBs"> for its MIB requirements.
456
457See L<SNMP::Info::NortelStack/"Required MIBs"> for its MIB requirements.
458
459See L<SNMP::Info::RapidCity/"Required MIBs"> for its MIB requirements.
460
461See L<SNMP::Info::Layer3/"Required MIBs"> for its MIB requirements.
462
463=head1 GLOBALS
464
465These are methods that return scalar value from SNMP
466
467=over
468
469=item $baystack->vendor()
470
471Returns 'avaya'
472
473=item $baystack->model()
474
475Cross references $baystack->id() to the F<SYNOPTICS-MIB> and returns
476the results.  303s and 304s have the same ID, so we have a hack
477to return depending on which it is.
478
479Returns BPS for Business Policy Switch
480
481For others extracts and returns the switch numeric designation.
482
483=item $baystack->os()
484
485Returns 'baystack' or 'boss' depending on software version.
486
487=item $baystack->os_bin()
488
489Returns the firmware version extracted from C<sysDescr>.
490
491=item $baystack->stp_ver()
492
493Returns the particular STP version running on this device.
494
495Values: C<nortelStpg>, C<pvst>, C<rstp>, C<mstp>, C<ieee8021d>
496
497(C<s5AgSysSpanningTreeOperMode>)
498
499=back
500
501=head2 Overrides
502
503=over
504
505=item  $baystack->index_factor()
506
507Required by SNMP::Info::SONMP.  Number representing the number of ports
508reserved per slot within the device MIB.
509
510Index factor on the Baystack switches are determined by the formula: Index
511Factor = 64 if (model = 470 or (os eq 'boss' and operating in pure mode))
512or else Index factor = 32.
513
514Returns either 32 or 64 based upon the formula.
515
516=back
517
518=head2 Global Methods imported from SNMP::Info::SONMP
519
520See L<SNMP::Info::SONMP/"GLOBALS"> for details.
521
522=head2 Globals imported from SNMP::Info::NortelStack
523
524See L<SNMP::Info::NortelStack/"GLOBALS"> for details.
525
526=head2 Global Methods imported from SNMP::Info::RapidCity
527
528See L<SNMP::Info::RapidCity/"GLOBALS"> for details.
529
530=head2 Globals imported from SNMP::Info::Layer3
531
532See L<SNMP::Info::Layer3/"GLOBALS"> for details.
533
534=head1 TABLE METHODS
535
536These are methods that return tables of information in the form of a reference
537to a hash.
538
539=head2 Overrides
540
541=over
542
543=item $baystack->interfaces()
544
545Returns reference to the map between IID and physical Port.
546
547  Slot and port numbers on the Baystack switches are determined by the
548  formula:
549
550  port = (Interface index % Index factor)
551  slot = (int(Interface index / Index factor)) + Slot offset
552
553  The physical port name is returned as slot.port.
554
555=item $baystack->i_mac()
556
557Returns the C<ifPhysAddress> table entries.
558
559Removes all entries matching '00:00:00:00:00:00' -- Certain
560revisions of Baystack firmware report all zeros for each port mac.
561
562=item $baystack->i_name()
563
564Crosses C<ifName> with C<ifAlias> and returns the human set port name if
565exists.
566
567=item $baystack->peth_port_ifindex()
568
569Maps the C<pethPsePortTable> to C<ifIndex> by way of the F<ENTITY-MIB>.
570
571=item $baystack->peth_port_power()
572
573Power supplied by PoE ports, in milliwatts
574
575(C<bspePethPsePortExtMeasuredPower>)
576
577=back
578
579=head2 F<ENTITY-MIB> Information
580
581For older devices which do not support F<ENTITY-MIB>, these methods emulate
582Physical Table methods using F<S5-CHASSIS-MIB>.  See
583L<SNMP::Info::NortelStack/"TABLE METHODS"> for details on ns_e_* methods.
584
585=over
586
587=item $baystack->e_index()
588
589If the device doesn't support C<entPhysicalDescr>, this will try ns_e_index().
590Note that this is based on C<entPhysicalDescr> due to implementation
591details of SNMP::Info::Entity::e_index().
592
593=item $baystack->e_class()
594
595If the device doesn't support C<entPhysicalClass>, this will try ns_e_class().
596
597=item $baystack->e_descr()
598
599If the device doesn't support C<entPhysicalDescr>, this will try ns_e_descr().
600
601=item $baystack->e_name()
602
603If the device doesn't support C<entPhysicalName>, this will try ns_e_name().
604
605=item $baystack->e_fwver()
606
607If the device doesn't support C<entPhysicalFirmwareRev>, this will try
608ns_e_fwver().
609
610=item $baystack->e_hwver()
611
612If the device doesn't support C<entPhysicalHardwareRev>, this will try
613ns_e_hwver().
614
615=item $baystack->e_parent()
616
617If the device doesn't support C<entPhysicalContainedIn>, this will try
618ns_e_parent().
619
620=item $baystack->e_pos()
621
622If the device doesn't support C<entPhysicalParentRelPos>, this will try
623ns_e_pos().
624
625=item $baystack->e_serial()
626
627If the device doesn't support C<entPhysicalSerialNum>, this will try
628ns_e_serial().
629
630=item $baystack->e_swver()
631
632If the device doesn't support C<entPhysicalSoftwareRev>, this will try
633ns_e_swver().
634
635=item $baystack->e_type()
636
637If the device doesn't support C<entPhysicalVendorType>, this will try
638ns_e_type().
639
640=item $baystack->e_vendor()
641
642If the device doesn't support C<entPhysicalMfgName>, this will try
643ns_e_vendor().
644
645=back
646
647=head2 Layer 2 Forwarding Database
648
649These methods try to obtain the layer 2 forwarding database entries via the
650normal bridge methods as well as SPBM entries via rapid city methods.
651
652=over
653
654=item $baystack->fw_mac()
655
656Returns reference to hash of forwarding table MAC Addresses
657
658=item $baystack->fw_port()
659
660Returns reference to hash of forwarding table entries port interface
661identifier (iid)
662
663=item $baystack->qb_fw_vlan()
664
665Returns reference to hash of forwarding table entries VLAN ID
666
667=item $baystack->fw_status()
668
669Returns reference to hash of forwarding table entries status
670
671=back
672
673=head2 Table Methods imported from SNMP::Info::SONMP
674
675See L<SNMP::Info::SONMP/"TABLE METHODS"> for details.
676
677=head2 Table Methods imported from SNMP::Info::NortelStack
678
679See L<SNMP::Info::NortelStack/"TABLE METHODS"> for details.
680
681=head2 Table Methods imported from SNMP::Info::RapidCity
682
683See L<SNMP::Info::RapidCity/"TABLE METHODS"> for details.
684
685=head2 Table Methods imported from SNMP::Info::Layer3
686
687See L<SNMP::Info::Layer3/"TABLE METHODS"> for details.
688
689=cut
690