diff --git a/Info.pm b/Info.pm index a88717f5..3d0efe26 100644 --- a/Info.pm +++ b/Info.pm @@ -924,7 +924,10 @@ sub device_type { $objtype = 'SNMP::Info::Layer1::Asante' if ($desc =~ /asante/i); # Bay Hub - $objtype = 'SNMP::Info::Layer1::Bayhub' if ($desc =~ /NMM.*Agent/); + $objtype = 'SNMP::Info::Layer1::Bayhub' if ($desc =~ /Bay.*NMM.*Agent/); + + # Synoptics Hub + $objtype = 'SNMP::Info::Layer1::S3000' if ($desc =~ /synoptics/i); # These devices don't claim to have Layer1-3 but we like em anyways. } else { diff --git a/Info/Layer1/S3000.pm b/Info/Layer1/S3000.pm new file mode 100644 index 00000000..6269c46a --- /dev/null +++ b/Info/Layer1/S3000.pm @@ -0,0 +1,524 @@ +# SNMP::Info::Layer1::S3000 +# Eric Miller +# $Id$ +# +# Copyright (c) 2006 Eric Miller +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the University of California, Santa Cruz nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package SNMP::Info::Layer1::S3000; +$VERSION = 1.0; +use strict; + +use Exporter; +use SNMP::Info::Layer1; +use SNMP::Info::Bridge; + +@SNMP::Info::Layer1::S3000::ISA = qw/SNMP::Info::Layer1 SNMP::Info::Bridge/; +@SNMP::Info::Layer1::S3000::EXPORT_OK = qw//; + +use vars qw/$VERSION %FUNCS %GLOBALS %MIBS %MUNGE $AUTOLOAD $INIT $DEBUG/; + +%MIBS = ( + %SNMP::Info::Layer1::MIBS, + %SNMP::Info::Bridge::MIBS, + 'SYNOPTICS-ETHERNET-MIB' => 's3EnetPortTable', + 'SYNOPTICS-COMMON-MIB' => 's3AgentType', + ); + +%GLOBALS = ( + %SNMP::Info::Layer1::GLOBALS, + %SNMP::Info::Bridge::GLOBALS, + # From SYNOPTICS-COMMON-MIB + 'os_bin' => 's3AgentFwVer', + 's3000_major_ver' => 's3AgentSwMajorVer', + 's3000_minor_ver' => 's3AgentSwMinorVer', + 's3000_maint_ver' => 's3AgentSwMaintVer', + ); + +%FUNCS = ( + %SNMP::Info::Layer1::FUNCS, + %SNMP::Info::Bridge::FUNCS, + # SYNOPTICS-ETHERNET-MIB::s3EnetPortTable + 's3000_pb_index' => 's3EnetPortBoardIndex', + 's3000_pp_index' => 's3EnetPortIndex', + 's3000_up_admin' => 's3EnetPortPartStatus', + 's3000_up' => 's3EnetPortLinkStatus', + # SYNOPTICS-ETHERNET-MIB::s3EnetShowNodesTable + 's3000_nb_index' => 's3EnetShowNodesSlotIndex', + 's3000_np_index' => 's3EnetShowNodesPortIndex', + 'fw_mac' => 's3EnetShowNodesMacAddress', + # SYNOPTICS-ETHERNET-MIB::s3EnetTopNmmTable + 's3000_topo_port' => 's3EnetTopNmmPort', + 's3000_topo_mac' => 's3EnetTopNmmMacAddr', + ); + +%MUNGE = ( + %SNMP::Info::Layer1::MUNGE, + %SNMP::Info::Bridge::MUNGE, + 's3000_topo_mac' => \&SNMP::Info::munge_mac + ); + +sub layers { + return '00000011'; +} + +sub os { + return 'synoptics'; +} + +sub vendor { + return 'nortel'; +} + +sub model { + my $s3000 = shift; + my $id = $s3000->id(); + return undef unless defined $id; + my $model = &SNMP::translateObj($id); + return $id unless defined $model; + $model =~ s/^s3reg-//i; + + return $1 if ($model =~ /((\d+){3}[\dX])/); + return $model; +} + +sub os_ver { + my $s3000 = shift; + my $major_ver = $s3000->s3000_major_ver() || 0; + my $minor_ver = $s3000->s3000_minor_ver() || 0; + my $maint_ver = $s3000->s3000_maint_ver() || 0; + + my $ver = "$major_ver.$minor_ver.$maint_ver"; + return $ver; +} + +sub mac { + my $s3000 = shift; + my $topo_port = $s3000->s3000_topo_port(); + my $topo_mac = $s3000->s3000_topo_mac(); + + foreach my $entry (keys %$topo_port){ + my $port = $topo_port->{$entry}; + next unless $port == 0; + my $mac = $topo_mac->{$entry}; + return $mac; + } + # Topology turned off, not supported. + return undef; +} + +# Hubs do not support ifMIB requirements for get MAC +# and port status +sub i_index { + my $s3000 = shift; + my $b_index = $s3000->s3000_pb_index(); + my $p_index = $s3000->s3000_pp_index(); + + my %i_index; + foreach my $iid (keys %$b_index){ + my $board = $b_index->{$iid}; + next unless defined $board; + my $port = $p_index->{$iid}||0; + + # We need to make up an index for multiple board instances. + my $index = ($board*256)+$port; + + $i_index{$iid} = $index; + } + return \%i_index; +} + +sub interfaces { + my $s3000 = shift; + my $i_index = $s3000->i_index(); + + my %if; + foreach my $iid (keys %$i_index){ + my $index = $i_index->{$iid}; + next unless defined $index; + + # Index numbers are deterministic slot * 256 + port - see i_index() + my $port = $index % 256; + my $slot = int($index / 256); + + my $slotport = "$slot.$port"; + + $if{$index} = $slotport; + } + + return \%if; +} + +sub i_duplex { + my $s3000 = shift; + my $port_index = $s3000->i_index(); + + my %i_duplex; + foreach my $iid (keys %$port_index){ + my $index = $port_index->{$iid}; + next unless defined $index; + + # Hubs only function half duplex + my $duplex = 'half'; + $i_duplex{$index}=$duplex; + } + return \%i_duplex; +} + +sub i_duplex_admin { + my $s3000 = shift; + my $port_index = $s3000->i_index(); + + my %i_duplex_admin; + foreach my $iid (keys %$port_index){ + my $index = $port_index->{$iid}; + next unless defined $index; + + # Hubs only function half duplex + my $duplex = 'half'; + $i_duplex_admin{$index}=$duplex; + } + return \%i_duplex_admin; +} + +sub i_speed { + my $s3000 = shift; + my $port_index = $s3000->i_index(); + + my %i_speed; + foreach my $iid (keys %$port_index){ + my $index = $port_index->{$iid}; + next unless defined $index; + + # These hubs only support 10Mbs + my $speed = '10000000'; + $i_speed{$index}=$speed; + } + return \%i_speed; +} + +sub i_up { + my $s3000 = shift; + my $port_index = $s3000->i_index(); + my $link_stat = $s3000->s3000_up(); + + my %i_up; + foreach my $iid (keys %$port_index){ + my $index = $port_index->{$iid}; + next unless defined $index; + my $link_stat = $link_stat->{$iid}; + next unless defined $link_stat; + + $link_stat = 'up' if $link_stat =~ /on/i; + $link_stat = 'down' if $link_stat =~ /off/i; + + $i_up{$index}=$link_stat; + } + return \%i_up; +} + +sub i_up_admin { + my $s3000 = shift; + my $i_index = $s3000->i_index(); + my $link_stat = $s3000->s3000_up_admin(); + + my %i_up_admin; + foreach my $iid (keys %$i_index){ + my $index = $i_index->{$iid}; + next unless defined $index; + my $link_stat = $link_stat->{$iid}; + next unless defined $link_stat; + + $i_up_admin{$index}=$link_stat; + } + return \%i_up_admin; +} + +sub set_i_up_admin { + # map setting to those the hub will understand + my %setting = qw/up 2 down 3/; + + my $s3000 = shift; + my ($setting, $iid) = @_; + + my $i_index = $s3000->i_index(); + my %reverse_i_index = reverse %$i_index; + + $setting = lc($setting); + + return 0 unless defined $setting{$setting}; + + $iid = $reverse_i_index{$iid}; + + return $s3000->set_s3000_up_admin($setting{$setting}, $iid); +} + +# Hubs do not support the standard Bridge MIB +sub bp_index { + my $s3000 = shift; + my $b_index = $s3000->s3000_nb_index(); + my $p_index = $s3000->s3000_np_index(); + my $model = $s3000->model(); + + my %bp_index; + foreach my $iid (keys %$b_index){ + my $board = $b_index->{$iid}; + next unless defined $board; + my $port = $p_index->{$iid}||0; + + my $index = ($board*256)+$port; + + $bp_index{$index} = $index; + } + return \%bp_index; +} + +sub fw_port { + my $s3000 = shift; + my $b_index = $s3000->s3000_nb_index(); + my $p_index = $s3000->s3000_np_index(); + my $model = $s3000->model(); + + my %fw_port; + foreach my $iid (keys %$b_index){ + my $board = $b_index->{$iid}; + next unless defined $board; + my $port = $p_index->{$iid}||0; + + my $index = ($board*256)+$port; + + $fw_port{$iid} = $index; + } + return \%fw_port; +} + +1; +__END__ + +=head1 NAME + +SNMP::Info::Layer1::S3000 - SNMP Interface to Synoptics / Nortel Hubs + +=head1 AUTHOR + +Eric Miller + +=head1 SYNOPSIS + + #Let SNMP::Info determine the correct subclass for you. + + my $s3000 = new SNMP::Info( + AutoSpecify => 1, + Debug => 1, + # These arguments are passed directly on to SNMP::Session + DestHost => 'myswitch', + Community => 'public', + Version => 2 + ) + + or die "Can't connect to DestHost.\n"; + + my $class = $s3000->class(); + print "SNMP::Info determined this device to fall under subclass : $class\n"; + +=head1 DESCRIPTION + +Provides abstraction to the configuration information obtainable from a +Bayhub device through SNMP. Also provides device MAC to port mapping through the propietary MIB. + +For speed or debugging purposes you can call the subclass directly, but not after determining +a more specific class using the method above. + +my $s3000 = new SNMP::Info::Layer1::S3000(...); + +=head2 Inherited Classes + +=over + +=item SNMP::Info::Layer1 + +=item SNMP::Info::Bridge + +=back + +=head2 Required MIBs + +=over + +=item SYNOPTICS-COMMON-MIB + +=item SYNOPTICS-ETHERNET-MIB + +=item Inherited Classes' MIBs + +See SNMP::Info::Layer1 for its own MIB requirements. + +See SNMP::Info::Bridge for its own MIB requirements. + +=back + +=head1 GLOBALS + +These are methods that return scalar value from SNMP + +=over + +=item $s3000->vendor() + +Returns 'nortel' + +=item $s3000->os() + +Returns 'synoptics' + +=item $s3000->model() + +Cross references $s3000->id() to the SYNOPTICS-MIB and returns +the results. + +Removes sreg- from the model name and returns only the numeric model identifier. + +=item $stack->os_ver() + +Returns the software version specified as major.minor.maint. + +(B).(B).(B) + +=item $stack->os_bin() + +Returns the firmware version. (B) + +=item $s3000->mac() + +Returns MAC of the advertised IP address of the device. + +=back + +=head2 Overrides + +=over + +=item $s3000->layers() + +Returns 00000011. Class emulates Layer 2 functionality through proprietary MIBs. + +=back + +=head2 Globals imported from SNMP::Info::Layer1 + +See documentation in SNMP::Info::Layer1 for details. + +=head2 Globals imported from SNMP::Info::Bridge + +See documentation in SNMP::Info::Bridge for details. + +=head1 TABLE ENTRIES + +These are methods that return tables of information in the form of a reference +to a hash. + +=head2 Overrides + +=over + +=item $s3000->i_index() + +Returns reference to map of IIDs to Interface index. + +Since hubs do not support ifIndex, the interface index is created using the +formula (board * 256 + port). This is required to support devices with more than one module. + +=item $s3000->interfaces() + +Returns reference to map of IIDs to physical ports. + +=item $s3000->i_duplex() + +Returns half, hubs do not support full duplex. + +=item $s3000->i_duplex_admin() + +Returns half, hubs do not support full duplex. + +=item $s3000->i_speed() + +Returns 10000000. The hubs only support 10Mbs Ethernet. + +=item $s3000->i_up() + +Returns (B) for each port. Translates on/off to up/down. + +=item $s3000->i_up_admin() + +Returns (B) for each port. + +=item $s3000->set_i_up_admin(state, ifIndex) + +Sets port state, must be supplied with state and port ifIndex + +State choices are 'up'or 'down' + +Example: + my %if_map = reverse %{$s3000->interfaces()}; + $s3000->set_i_up_admin('down', $if_map{'1.1'}) + or die "Couldn't change port state. ",$s3000->error(1); + +=item $s3000->bp_index() + +Simulates bridge MIB by returning reference to a hash containing the index for +both the keys and values. + +=item $s3000->fw_port() + +Returns reference to map of IIDs of the SYNOPTICS-ETHERNET-MIB::s3EnetShowNodesTable +to the Interface index. + +=item $s3000->fw_mac() + +(B) + +=item $s3000->s3000_topo_port() + +Returns reference to hash. Key: Table entry, Value:Port Number (interface iid) + +(B) + +=item $s3000->s3000_topo_mac() + +(B) + +Returns reference to hash. Key: Table entry, Value:Remote MAC address + +=back + +=head2 Table Methods imported from SNMP::Info::Layer1 + +See documentation in SNMP::Info::Layer1 for details. + +=head2 Table Methods imported from SNMP::Info::Bridge + +See documentation in SNMP::Info::Bridge for details. + +=cut