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