- Correct operational and administrative duplex reporting.
- Remove device specific i_type() use standard IF-MIB values. - Remove PORT-SECURITY-MIB from CiscoStack as these are now in CiscoPortSecurity class. - Move interfaces() and i_name() methods out of CiscoStack to L2::Catalyst so we can remove globs from L3:C3550 and L3::C6500.
This commit is contained in:
		| @@ -28,7 +28,7 @@ | ||||
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  | ||||
| package SNMP::Info::CiscoStack; | ||||
| $VERSION = '1.04'; | ||||
| $VERSION = '1.05'; | ||||
| # $Id$ | ||||
|  | ||||
| use strict; | ||||
| @@ -42,7 +42,6 @@ use vars qw/$VERSION $DEBUG %MIBS %FUNCS %GLOBALS %MUNGE %PORTSTAT $INIT/; | ||||
|  | ||||
| %MIBS    = ( | ||||
|             'CISCO-STACK-MIB'         => 'ciscoStackMIB', | ||||
|             'CISCO-PORT-SECURITY-MIB' => 'ciscoPortSecurityMIB', | ||||
|            ); | ||||
|  | ||||
| %GLOBALS = ( | ||||
| @@ -58,17 +57,9 @@ use vars qw/$VERSION $DEBUG %MIBS %FUNCS %GLOBALS %MUNGE %PORTSTAT $INIT/; | ||||
|             'ps2_status'  => 'chassisPs2Status',     | ||||
|             'slots'       => 'chassisNumSlots',     | ||||
|             'fan'         => 'chassisFanStatus', | ||||
|             # CISCO-PORT-SECURITY-MIB | ||||
|             'cps_clear'     => 'cpsGlobalClearSecureMacAddresses', | ||||
|             'cps_notify'    => 'cpsGlobalSNMPNotifControl', | ||||
|             'cps_rate'      => 'cpsGlobalSNMPNotifRate', | ||||
|             'cps_enable'    => 'cpsGlobalPortSecurityEnable', | ||||
|             'cps_mac_count' => 'cpsGlobalTotalSecureAddress', | ||||
|             'cps_mac_max'   => 'cpsGlobalMaxSecureAddress', | ||||
|            ); | ||||
|  | ||||
| %FUNCS   = ( | ||||
|             'i_type2'        => 'ifType', | ||||
|             # CISCO-STACK-MIB::moduleEntry | ||||
|             #   These are blades in a catalyst device | ||||
|             'm_type'         => 'moduleType', | ||||
| @@ -101,47 +92,11 @@ use vars qw/$VERSION $DEBUG %MIBS %FUNCS %GLOBALS %MUNGE %PORTSTAT $INIT/; | ||||
|             # CISCO-STACK-MIB::PortCpbEntry | ||||
|             'p_speed_admin'  => 'portCpbSpeed', | ||||
|             'p_duplex_admin' => 'portCpbDuplex', | ||||
|             # CISCO-PORT-SECURITY-MIB::cpsIfConfigTable | ||||
|             'cps_i_limit_val'  => 'cpsIfInvalidSrcRateLimitValue', | ||||
|             'cps_i_limit'      => 'cpsIfInvalidSrcRateLimitEnable', | ||||
|             'cps_i_sticky'     => 'cpsIfStickyEnable', | ||||
|             'cps_i_clear_type' => 'cpsIfClearSecureMacAddresses', | ||||
|             'cps_i_shutdown'   => 'cpsIfShutdownTimeout', | ||||
|             'cps_i_flood'      => 'cpsIfUnicastFloodingEnable', | ||||
|             'cps_i_clear'      => 'cpsIfClearSecureAddresses', | ||||
|             'cps_i_mac'        => 'cpsIfSecureLastMacAddress', | ||||
|             'cps_i_count'      => 'cpsIfViolationCount', | ||||
|             'cps_i_action'     => 'cpsIfViolationAction', | ||||
|             'cps_i_mac_static' => 'cpsIfStaticMacAddrAgingEnable', | ||||
|             'cps_i_mac_type'   => 'cpsIfSecureMacAddrAgingType', | ||||
|             'cps_i_mac_age'    => 'cpsIfSecureMacAddrAgingTime', | ||||
|             'cps_i_mac_count'  => 'cpsIfCurrentSecureMacAddrCount', | ||||
|             'cps_i_mac_max'    => 'cpsIfMaxSecureMacAddr', | ||||
|             'cps_i_status'     => 'cpsIfPortSecurityStatus', | ||||
|             'cps_i_enable'     => 'cpsIfPortSecurityEnable', | ||||
|             # CISCO-PORT-SECURITY-MIB::cpsIfVlanTable | ||||
|             'cps_i_v_mac_count' => 'cpsIfVlanCurSecureMacAddrCount', | ||||
|             'cps_i_v_mac_max'   => 'cpsIfVlanMaxSecureMacAddr', | ||||
|             'cps_i_v'           => 'cpsIfVlanIndex', | ||||
|             # CISCO-PORT-SECURITY-MIB::cpsIfVlanSecureMacAddrTable | ||||
|             'cps_i_v_mac_status' => 'cpsIfVlanSecureMacAddrRowStatus', | ||||
|             'cps_i_v_mac_age'    => 'cpsIfVlanSecureMacAddrRemainAge', | ||||
|             'cps_i_v_mac_type'   => 'cpsIfVlanSecureMacAddrType', | ||||
|             'cps_i_v_vlan'       => 'cpsIfVlanSecureVlanIndex', | ||||
|             'cps_i_v_mac'        => 'cpsIfVlanSecureMacAddress', | ||||
|             # CISCO-PORT-SECURITY-MIB::cpsSecureMacAddressTable | ||||
|             'cps_m_status' => 'cpsSecureMacAddrRowStatus', | ||||
|             'cps_m_age' => 'cpsSecureMacAddrRemainingAge', | ||||
|             'cps_m_type' => 'cpsSecureMacAddrType', | ||||
|             'cps_m_mac' => 'cpsSecureMacAddress', | ||||
|            ); | ||||
|  | ||||
| %MUNGE   = ( | ||||
|             'm_ports_status' => \&munge_port_status, | ||||
|             'p_duplex_admin' => \&SNMP::Info::munge_bits, | ||||
|             'cps_i_mac'      => \&SNMP::Info::munge_mac,  | ||||
|             'cps_m_mac'      => \&SNMP::Info::munge_mac, | ||||
|             'cps_i_v_mac'    => \&SNMP::Info::munge_mac, | ||||
|            ); | ||||
|  | ||||
| %PORTSTAT = (1 => 'other', | ||||
| @@ -167,83 +122,104 @@ sub serial { | ||||
|     return undef; | ||||
| } | ||||
|  | ||||
| sub i_type { | ||||
|     my $stack = shift; | ||||
|  | ||||
|     my $p_port = $stack->p_port() || {}; | ||||
|     my $p_type = $stack->p_type() || {}; | ||||
|  | ||||
|     # Get more generic port types from IF-MIB | ||||
|     my $i_type  = $stack->i_type2() || {}; | ||||
|  | ||||
|     # Now Override w/ port entries | ||||
|     foreach my $port (keys %$p_type) { | ||||
|         my $iid = $p_port->{$port}; | ||||
|         next unless defined $iid; | ||||
|         $i_type->{$iid} = $p_type->{$port};   | ||||
|     } | ||||
|  | ||||
|     return $i_type; | ||||
| } | ||||
|  | ||||
| # p_* functions are indexed to physical port.  let's index these | ||||
| #   to snmp iid | ||||
| sub i_name { | ||||
|     my $stack = shift; | ||||
|  | ||||
|     my $p_port = $stack->p_port() || {}; | ||||
|     my $p_name = $stack->p_name() || {}; | ||||
|  | ||||
|     my %i_name; | ||||
|     foreach my $port (keys %$p_name) { | ||||
|         my $iid = $p_port->{$port}; | ||||
|         next unless defined $iid; | ||||
|         $i_name{$iid} = $p_name->{$port}; | ||||
|     } | ||||
|     return \%i_name;  | ||||
| } | ||||
| # Rules for older CatOS devices using CiscoStack | ||||
| # | ||||
| # You can configure Ethernet and Fast Ethernet interfaces to either full | ||||
| # duplex or half duplex.  | ||||
| # | ||||
| # You cannot configure the duplex mode on Gigabit Ethernet ports (they are | ||||
| # always in full-duplex mode). | ||||
| # | ||||
| # If you set the port speed to auto, duplex mode is automatically set to auto.  | ||||
| # | ||||
| # For operational duplex if portCpbDuplex is all zeros the port is a gigabit | ||||
| # port and duplex is always full.  If the port is not operational and auto | ||||
| # return value will be undef since we don't know the operational status. | ||||
| # | ||||
| # Newer devices use ETHERLIKE-MIB to report operational duplex, this will be | ||||
| # checked in the device class. | ||||
|  | ||||
| sub i_duplex { | ||||
|     my $stack = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     #my $i_duplex = $stack->SUPER::i_duplex(); | ||||
|     my $p_port   = $stack->p_port()   || {}; | ||||
|     my $p_duplex = $stack->p_duplex() || {}; | ||||
|     my $p_port       = $stack->p_port()   || {}; | ||||
|     my $p_duplex     = $stack->p_duplex() || {}; | ||||
|     my $p_duplex_cap = $stack->p_duplex_admin() || {}; | ||||
|  | ||||
|     my $i_duplex = {}; | ||||
|     foreach my $port (keys %$p_duplex) { | ||||
|         my $iid = $p_port->{$port}; | ||||
|         next unless defined $iid; | ||||
|         $i_duplex->{$iid} = $p_duplex->{$port}; | ||||
|         next if (defined $partial and $iid !~ /^$partial$/); | ||||
|         # Test for gigabit  | ||||
|         if ($p_duplex_cap->{$port} == 0) { | ||||
|             $i_duplex->{$iid} = 'full'; | ||||
|         } | ||||
|         # Auto is not a valid operational state | ||||
|         elsif ($p_duplex->{$port} eq 'auto') { | ||||
|             next; | ||||
|         } | ||||
|         else { | ||||
|             $i_duplex->{$iid} = $p_duplex->{$port}; | ||||
|         } | ||||
|     } | ||||
|     return $i_duplex;  | ||||
| } | ||||
|  | ||||
| # For administrative duplex if portCpbDuplex is all zeros the port is a gigabit | ||||
| # port and duplex is always full.  If portAdminSpeed is set to auto then the | ||||
| # duplex will be auto, otherwise use portDuplex. | ||||
|  | ||||
| sub i_duplex_admin { | ||||
|     my $stack = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my $p_port         = $stack->p_port()         || {}; | ||||
|     my $p_duplex_admin = $stack->p_duplex_admin() || {}; | ||||
|     my $p_port       = $stack->p_port()   || {}; | ||||
|     my $p_duplex     = $stack->p_duplex() || {}; | ||||
|     my $p_duplex_cap = $stack->p_duplex_admin() || {}; | ||||
|     my $p_speed      = $stack->p_speed() || {}; | ||||
|  | ||||
|     my %i_duplex_admin; | ||||
|     foreach my $port (keys %$p_duplex_admin) { | ||||
|     my $i_duplex_admin = {}; | ||||
|     foreach my $port (keys %$p_duplex) { | ||||
|         my $iid = $p_port->{$port}; | ||||
|         next unless defined $iid; | ||||
|         my $duplex = $p_duplex_admin->{$port}; | ||||
|         next unless defined $duplex; | ||||
|  | ||||
|         my $string = 'other'; | ||||
|         # see CISCO-STACK-MIB for a description of the bits | ||||
|         $string = 'half' if ($duplex =~ /001$/ or $duplex =~ /0100.$/); | ||||
|         $string = 'full' if ($duplex =~ /010$/ or $duplex =~ /100.0$/); | ||||
|         # we'll call it auto if both full and half are turned on, or if the | ||||
|         #   specifically 'auto' flag bit is set. | ||||
|         $string = 'auto'  | ||||
|             if ($duplex =~ /1..$/ or $duplex =~ /110..$/ or $duplex =~ /..011$/); | ||||
|         | ||||
|         $i_duplex_admin{$iid} = $string; | ||||
|         next if (defined $partial and $iid !~ /^$partial$/); | ||||
|         # Test for gigabit  | ||||
|         if ($p_duplex_cap->{$port} == 0) { | ||||
|             $i_duplex_admin->{$iid} = 'full'; | ||||
|         } | ||||
|         # Check admin speed for auto | ||||
|         elsif ($p_speed->{$port} =~ /auto/) { | ||||
|             $i_duplex_admin->{$iid} = 'auto'; | ||||
|         } | ||||
|         else { | ||||
|             $i_duplex_admin->{$iid} = $p_duplex->{$port}; | ||||
|         } | ||||
|     } | ||||
|     return \%i_duplex_admin;  | ||||
|     return $i_duplex_admin;  | ||||
| } | ||||
|  | ||||
| sub i_speed_admin { | ||||
|     my $stack = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my %i_speed_admin; | ||||
|     my $p_port  = $stack->p_port(); | ||||
|     my %mapping = reverse %$p_port; | ||||
|     my $p_speed = $stack->p_speed($mapping{$partial}); | ||||
|  | ||||
|     my %speeds = ('autoDetect'      => 'auto', | ||||
|                   'autoDetect10100' => 'auto', | ||||
|                   's10000000'       => '10 Mbps', | ||||
|                   's100000000'      => '100 Mbps', | ||||
|                   's1000000000'     => '1.0 Gbps', | ||||
|                   's10G'            => '10 Gbps', | ||||
|                  ); | ||||
|  | ||||
|     %i_speed_admin = map { $p_port->{$_} => $speeds{$p_speed->{$_}} } keys %$p_port; | ||||
|  | ||||
|     return \%i_speed_admin; | ||||
| } | ||||
|  | ||||
| sub set_i_speed_admin { | ||||
| @@ -261,7 +237,7 @@ sub set_i_speed_admin { | ||||
|  | ||||
|     $iid = $reverse_p_port{$iid}; | ||||
|  | ||||
|     return $stack->set_p_speed($speeds{$speed}, $iid); | ||||
|     return $stack->set_p_speed_admin($speeds{$speed}, $iid); | ||||
| } | ||||
|  | ||||
| sub set_i_duplex_admin { | ||||
| @@ -270,6 +246,14 @@ sub set_i_duplex_admin { | ||||
|  | ||||
|     my $stack = shift; | ||||
|     my ($duplex, $iid) = @_; | ||||
|     if ($duplex eq 'auto') { | ||||
|         $stack->error_throw("Software doesn't support setting auto duplex with | ||||
|                             set_i_duplex_admin() you must use | ||||
|                             set_i_speed_admin() and set both speed and duplex | ||||
|                             to auto"); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     my $p_port  = $stack->p_port() || {}; | ||||
|     my %reverse_p_port = reverse %$p_port; | ||||
|  | ||||
| @@ -282,31 +266,14 @@ sub set_i_duplex_admin { | ||||
|     return $stack->set_p_duplex($duplexes{$duplex}, $iid); | ||||
| } | ||||
|  | ||||
|  | ||||
| # $stack->interfaces() - Maps the ifIndex table to a physical port | ||||
| sub interfaces { | ||||
|     my $self = shift; | ||||
|     my $i_index    = $self->i_index(); | ||||
|     my $portnames  = $self->p_port() || {}; | ||||
|     my %portmap    = reverse %$portnames; | ||||
|  | ||||
|     my %interfaces = (); | ||||
|     foreach my $iid (keys %$i_index) { | ||||
|         next unless defined $iid; | ||||
|         my $if   = $i_index->{$iid}; | ||||
|         my $port = $portmap{$iid}; | ||||
|         $interfaces{$iid} = $port || $if; | ||||
|     } | ||||
|  | ||||
|     return \%interfaces; | ||||
| } | ||||
|  | ||||
| 1; | ||||
|  | ||||
| __END__ | ||||
|  | ||||
| =head1 NAME | ||||
|  | ||||
| SNMP::Info::CiscoStack - Intefaces to data from CISCO-STACK-MIB and CISCO-PORT-SECURITY-MIB | ||||
| SNMP::Info::CiscoStack - SNMP Inteface to data from CISCO-STACK-MIB and | ||||
| CISCO-PORT-SECURITY-MIB | ||||
|  | ||||
| =head1 AUTHOR | ||||
|  | ||||
| @@ -325,7 +292,7 @@ Max Baker | ||||
|                         )  | ||||
|     or die "Can't connect to DestHost.\n"; | ||||
|  | ||||
|  my $class      = $ciscostats->class(); | ||||
|  my $class = $ciscostats->class(); | ||||
|  print "SNMP::Info determined this device to fall under subclass : $class\n"; | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
| @@ -346,8 +313,6 @@ none. | ||||
|  | ||||
| =item CISCO-STACK-MIB | ||||
|  | ||||
| =item CISCO-PORT-SECURITY-MIB | ||||
|  | ||||
| =back | ||||
|  | ||||
| MIBs can be found at ftp://ftp.cisco.com/pub/mibs/v2/v2.tar.gz or from | ||||
| @@ -399,48 +364,12 @@ Netdisco-mib package at netdisco.org. | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head2 CISCO-PORT-SECURITY-MIB globals | ||||
|  | ||||
| See CISCO-PORT-SECURITY-MIB for details. | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $stack->cps_clear() | ||||
|  | ||||
| B<cpsGlobalClearSecureMacAddresses> | ||||
|  | ||||
| =item $stack->cps_notify() | ||||
|  | ||||
| B<cpsGlobalSNMPNotifControl> | ||||
|  | ||||
| =item $stack->cps_rate() | ||||
|  | ||||
| B<cpsGlobalSNMPNotifRate> | ||||
|  | ||||
| =item $stack->cps_enable() | ||||
|  | ||||
| B<cpsGlobalPortSecurityEnable> | ||||
|  | ||||
| =item $stack->cps_mac_count() | ||||
|  | ||||
| B<cpsGlobalTotalSecureAddress> | ||||
|  | ||||
| =item $stack->cps_mac_max() | ||||
|  | ||||
| B<cpsGlobalMaxSecureAddress> | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head1 TABLE METHODS | ||||
|  | ||||
| =head2 Interface Tables | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $stack->interfaces() | ||||
|  | ||||
| Crosses p_port() with i_index() to get physical names. | ||||
|  | ||||
| =item $stack->i_physical() | ||||
|  | ||||
| Returns a map to IID for ports that are physical ports, not vlans, etc. | ||||
| @@ -451,19 +380,23 @@ Crosses p_port() with p_type() and returns the results. | ||||
|  | ||||
| Overrides with ifType if p_type() isn't available. | ||||
|  | ||||
| =item $stack->i_name() | ||||
|  | ||||
| Crosses p_name with p_port and returns results. | ||||
|  | ||||
| =item $stack->i_duplex() | ||||
|  | ||||
| Crosses p_duplex with p_port and returns results. | ||||
| Returns reference to hash of iid to current link duplex setting. | ||||
|  | ||||
| First checks for fixed gigabit ports which are always full duplex.  Next, if | ||||
| the port is not operational and reported port duplex (B<portDuplex>) is auto | ||||
| then the operational duplex can not be determined.  Otherwise it uses the | ||||
| reported port duplex (B<portDuplex>). | ||||
|  | ||||
| =item $stack->i_duplex_admin() | ||||
|  | ||||
| Crosses p_duplex_admin with p_port. | ||||
| Returns reference to hash of iid to administrative duplex setting. | ||||
|  | ||||
| Munges bit_string returned from p_duplex_admin to get duplex settings. | ||||
| First checks for fixed gigabit ports which are always full duplex. Next checks | ||||
| the port administrative speed (B<portAdminSpeed>) which if set to | ||||
| autonegotiate then the duplex will also autonegotiate, otherwise it uses the | ||||
| reported port duplex (B<portDuplex>). | ||||
|  | ||||
| =item $stack->set_i_speed_admin(speed, ifIndex) | ||||
|  | ||||
| @@ -673,147 +606,4 @@ B<portAdminTxFlowControl> | ||||
|  | ||||
| =back | ||||
|  | ||||
|  | ||||
| =head2 CISCO-PORT-SECURITY-MIB - Interface Config Table | ||||
|  | ||||
| See CISCO-PORT-SECURITY-MIB for details. | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $stack->cps_i_limit_val() | ||||
|  | ||||
| B<cpsIfInvalidSrcRateLimitValue> | ||||
|  | ||||
| =item $stack->cps_i_limit() | ||||
|  | ||||
| B<cpsIfInvalidSrcRateLimitEnable> | ||||
|  | ||||
| =item $stack->cps_i_sticky() | ||||
|  | ||||
| B<cpsIfStickyEnable> | ||||
|  | ||||
| =item $stack->cps_i_clear_type() | ||||
|  | ||||
| B<cpsIfClearSecureMacAddresses> | ||||
|  | ||||
| =item $stack->cps_i_shutdown() | ||||
|  | ||||
| B<cpsIfShutdownTimeout> | ||||
|  | ||||
| =item $stack->cps_i_flood() | ||||
|  | ||||
| B<cpsIfUnicastFloodingEnable> | ||||
|  | ||||
| =item $stack->cps_i_clear() | ||||
|  | ||||
| B<cpsIfClearSecureAddresses> | ||||
|  | ||||
| =item $stack->cps_i_mac() | ||||
|  | ||||
| B<cpsIfSecureLastMacAddress> | ||||
|  | ||||
| =item $stack->cps_i_count() | ||||
|  | ||||
| B<cpsIfViolationCount> | ||||
|  | ||||
| =item $stack->cps_i_action() | ||||
|  | ||||
| B<cpsIfViolationAction> | ||||
|  | ||||
| =item $stack->cps_i_mac_static() | ||||
|  | ||||
| B<cpsIfStaticMacAddrAgingEnable> | ||||
|  | ||||
| =item $stack->cps_i_mac_type() | ||||
|  | ||||
| B<cpsIfSecureMacAddrAgingType> | ||||
|  | ||||
| =item $stack->cps_i_mac_age() | ||||
|  | ||||
| B<cpsIfSecureMacAddrAgingTime> | ||||
|  | ||||
| =item $stack->cps_i_mac_count() | ||||
|  | ||||
| B<cpsIfCurrentSecureMacAddrCount> | ||||
|  | ||||
| =item $stack->cps_i_mac_max() | ||||
|  | ||||
| B<cpsIfMaxSecureMacAddr> | ||||
|  | ||||
| =item $stack->cps_i_status() | ||||
|  | ||||
| B<cpsIfPortSecurityStatus> | ||||
|  | ||||
| =item $stack->cps_i_enable() | ||||
|  | ||||
| B<cpsIfPortSecurityEnable> | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head2 CISCO-PORT-SECURITY-MIB::cpsIfVlanTable | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $stack->cps_i_v_mac_count() | ||||
|  | ||||
| B<cpsIfVlanCurSecureMacAddrCount> | ||||
|  | ||||
| =item $stack->cps_i_v_mac_max() | ||||
|  | ||||
| B<cpsIfVlanMaxSecureMacAddr> | ||||
|  | ||||
| =item $stack->cps_i_v() | ||||
|  | ||||
| B<cpsIfVlanIndex> | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head2 CISCO-PORT-SECURITY-MIB::cpsIfVlanSecureMacAddrTable | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $stack->cps_i_v_mac_status() | ||||
|  | ||||
| B<cpsIfVlanSecureMacAddrRowStatus> | ||||
|  | ||||
| =item $stack->cps_i_v_mac_age() | ||||
|  | ||||
| B<cpsIfVlanSecureMacAddrRemainAge> | ||||
|  | ||||
| =item $stack->cps_i_v_mac_type() | ||||
|  | ||||
| B<cpsIfVlanSecureMacAddrType> | ||||
|  | ||||
| =item $stack->cps_i_v_vlan() | ||||
|  | ||||
| B<cpsIfVlanSecureVlanIndex> | ||||
|  | ||||
| =item $stack->cps_i_v_mac() | ||||
|  | ||||
| B<cpsIfVlanSecureMacAddress> | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head2 CISCO-PORT-SECURITY-MIB::cpsSecureMacAddressTable | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $stack->cps_m_status() | ||||
|  | ||||
| B<cpsSecureMacAddrRowStatus> | ||||
|  | ||||
| =item $stack->cps_m_age() | ||||
|  | ||||
| B<cpsSecureMacAddrRemainingAge> | ||||
|  | ||||
| =item $stack->cps_m_type() | ||||
|  | ||||
| B<cpsSecureMacAddrType> | ||||
|  | ||||
| =item $stack->cps_m_mac() | ||||
|  | ||||
| B<cpsSecureMacAddress> | ||||
|  | ||||
| =back | ||||
|  | ||||
| =cut | ||||
|   | ||||
| @@ -143,6 +143,41 @@ sub cisco_comm_indexing { | ||||
|     1; | ||||
| } | ||||
|  | ||||
| sub interfaces { | ||||
|     my $self = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my $i_index    = $self->i_index($partial); | ||||
|     my $portnames  = $self->p_port() || {}; | ||||
|     my %portmap    = reverse %$portnames; | ||||
|  | ||||
|     my %interfaces = (); | ||||
|     foreach my $iid (keys %$i_index) { | ||||
|         next unless defined $iid; | ||||
|         my $if   = $i_index->{$iid}; | ||||
|         my $port = $portmap{$iid}; | ||||
|         $interfaces{$iid} = $port || $if; | ||||
|     } | ||||
|     return \%interfaces; | ||||
| } | ||||
|  | ||||
| sub i_name { | ||||
|     my $stack = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my $p_port = $stack->p_port() || {}; | ||||
|     my %mapping = reverse %$p_port; | ||||
|     my $p_name = $stack->p_name($mapping{$partial}) || {}; | ||||
|  | ||||
|     my %i_name; | ||||
|     foreach my $port (keys %$p_name) { | ||||
|         my $iid = $p_port->{$port}; | ||||
|         next unless defined $iid; | ||||
|         $i_name{$iid} = $p_name->{$port}; | ||||
|     } | ||||
|     return \%i_name;  | ||||
| } | ||||
|  | ||||
| 1; | ||||
| __END__ | ||||
|  | ||||
| @@ -288,6 +323,16 @@ to a hash. | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $cat->interfaces() | ||||
|  | ||||
| Returns the map between SNMP Interface Identifier (iid) and physical port name.  | ||||
|  | ||||
| =item $cat->i_name() | ||||
|  | ||||
| Returns reference to hash of iid to human set name.  | ||||
|  | ||||
| B<portName> | ||||
|  | ||||
| =item $cat->bp_index() | ||||
|  | ||||
| Returns reference to hash of bridge port table entries map back to interface | ||||
|   | ||||
| @@ -93,11 +93,6 @@ use vars qw/$VERSION $DEBUG %GLOBALS %MIBS %FUNCS %MUNGE $INIT/ ; | ||||
|             %SNMP::Info::CiscoVTP::MUNGE, | ||||
|          ); | ||||
|  | ||||
| # Override Inheritance for these specific methods | ||||
|  | ||||
| *SNMP::Info::Layer3::C3550::interfaces = \&SNMP::Info::Layer3::interfaces; | ||||
| *SNMP::Info::Layer3::C3550::i_name     = \&SNMP::Info::Layer3::i_name; | ||||
|  | ||||
| sub vendor { | ||||
|     return 'cisco'; | ||||
| } | ||||
| @@ -129,6 +124,90 @@ sub ports { | ||||
|     return $ports2; | ||||
| } | ||||
|  | ||||
| #  Verions prior to 12.1(22)EA1a use the older CiscoStack method | ||||
| #  Newer versions use the ETHERLIKE-MIB to report operational duplex. | ||||
| #  See http://www.ciscosystems.com/en/US/products/hw/switches/ps646/prod_release_note09186a00802a08ee.html | ||||
|  | ||||
| sub i_duplex { | ||||
|     my $c3550 = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my $el_duplex = $c3550->el_duplex($partial); | ||||
|  | ||||
|     # Newer software      | ||||
|     if (defined $el_duplex and scalar(keys %$el_duplex)){ | ||||
|         my %i_duplex; | ||||
|         foreach my $el_port (keys %$el_duplex){ | ||||
|             my $duplex = $el_duplex->{$el_port}; | ||||
|             next unless defined $duplex; | ||||
|  | ||||
|             $i_duplex{$el_port} = 'half' if $duplex =~ /half/i; | ||||
|             $i_duplex{$el_port} = 'full' if $duplex =~ /full/i; | ||||
|         } | ||||
|         return \%i_duplex; | ||||
|     } | ||||
|     # Fall back to CiscoStack method | ||||
|     else { | ||||
|         return $c3550->SUPER::i_duplex($partial); | ||||
|     } | ||||
| } | ||||
|  | ||||
| # Software >= 12.1(22)EA1a uses portDuplex as admin setting | ||||
|  | ||||
| sub i_duplex_admin { | ||||
|     my $c3550 = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my $el_duplex = $c3550->el_duplex($partial); | ||||
|  | ||||
|     # Newer software      | ||||
|     if (defined $el_duplex and scalar(keys %$el_duplex)){ | ||||
|         my $p_port   = $c3550->p_port()   || {}; | ||||
|         my $p_duplex = $c3550->p_duplex() || {}; | ||||
|          | ||||
|         my $i_duplex_admin = {}; | ||||
|         foreach my $port (keys %$p_duplex) { | ||||
|             my $iid = $p_port->{$port}; | ||||
|             next unless defined $iid; | ||||
|             next if (defined $partial and $iid !~ /^$partial$/); | ||||
|              | ||||
|             $i_duplex_admin->{$iid} = $p_duplex->{$port}; | ||||
|         } | ||||
|         return $i_duplex_admin; | ||||
|     } | ||||
|     # Fall back to CiscoStack method | ||||
|     else { | ||||
|         return $c3550->SUPER::i_duplex_admin($partial); | ||||
|     }     | ||||
| } | ||||
|  | ||||
| sub set_i_duplex_admin { | ||||
|     # map a textual duplex to an integer one the switch understands | ||||
|     my %duplexes = qw/half 1 full 2 auto 4/; | ||||
|  | ||||
|     my $c3550 = shift; | ||||
|     my ($duplex, $iid) = @_; | ||||
|  | ||||
|     my $el_duplex = $c3550->el_duplex($iid); | ||||
|  | ||||
|     # Auto duplex only supported on newer software | ||||
|     if (defined $el_duplex and scalar(keys %$el_duplex)){ | ||||
|         my $p_port  = $c3550->p_port() || {}; | ||||
|         my %reverse_p_port = reverse %$p_port; | ||||
|  | ||||
|        $duplex = lc($duplex); | ||||
|  | ||||
|        return 0 unless defined $duplexes{$duplex}; | ||||
|  | ||||
|        $iid = $reverse_p_port{$iid}; | ||||
|  | ||||
|        return $c3550->set_p_duplex($duplexes{$duplex}, $iid); | ||||
|     } | ||||
|     else { | ||||
|         $c3550->SUPER::set_i_duplex_admin; | ||||
|     } | ||||
| } | ||||
|  | ||||
| sub cisco_comm_indexing { | ||||
|     1; | ||||
| } | ||||
| @@ -272,6 +351,46 @@ See documentation in L<SNMP::Info::CiscoImage/"GLOBALS"> for details. | ||||
| These are methods that return tables of information in the form of a reference | ||||
| to a hash. | ||||
|  | ||||
| =head2 Overrides | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $c3550->i_duplex() | ||||
|  | ||||
| Returns reference to hash of iid to current link duplex setting. | ||||
|  | ||||
| Software version 12.1(22)EA1a or greater returns duplex based upon the | ||||
| result of $c3550->el_duplex().  Otherwise it uses the result of | ||||
| the call to CiscoStack i_duplex(). | ||||
|  | ||||
| See L<SNMP::Info::Etherlike> for el_duplex() method and | ||||
| L<SNMP::Info::CiscoStack> for its i_duplex() method. | ||||
|  | ||||
| =item $c3550->i_duplex_admin() | ||||
|  | ||||
| Returns reference to hash of iid to administrative duplex setting. | ||||
|  | ||||
| Software version 12.1(22)EA1a or greater returns duplex based upon the | ||||
| result of $c3550->p_duplex().  Otherwise it uses the result of | ||||
| the call to CiscoStack i_duplex(). | ||||
|  | ||||
| See L<SNMP::Info::CiscoStack> for its i_duplex() and p_duplex() methods. | ||||
|  | ||||
| =item $c3550->set_i_duplex_admin(duplex, ifIndex) | ||||
|  | ||||
| Sets port duplex, must be supplied with duplex and port ifIndex. | ||||
|  | ||||
| Speed choices are 'auto', 'half', 'full'. | ||||
|  | ||||
| Crosses $c3550->p_port() with $c3550->p_duplex() to utilize port ifIndex. | ||||
|  | ||||
|     Example: | ||||
|     my %if_map = reverse %{$c3550->interfaces()}; | ||||
|     $c3550->set_i_duplex_admin('auto', $if_map{'FastEthernet0/1'})  | ||||
|         or die "Couldn't change port duplex. ",$c3550->error(1); | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head2 Table Methods imported from SNMP::Info::Layer3 | ||||
|  | ||||
| See documentation in L<SNMP::Info::Layer3/"TABLE METHODS"> for details. | ||||
|   | ||||
| @@ -96,11 +96,6 @@ $VERSION = '1.05'; | ||||
|             %SNMP::Info::CiscoVTP::MUNGE, | ||||
|          ); | ||||
|  | ||||
| # Override Inheritance for these specific methods | ||||
|  | ||||
| *SNMP::Info::Layer3::C6500::interfaces = \&SNMP::Info::Layer3::interfaces; | ||||
| *SNMP::Info::Layer3::C6500::i_name     = \&SNMP::Info::Layer3::i_name; | ||||
|  | ||||
| sub vendor { | ||||
|     return 'cisco'; | ||||
| } | ||||
| @@ -109,6 +104,88 @@ sub vendor { | ||||
| sub bulkwalk_no { 1; } | ||||
| sub cisco_comm_indexing { 1; } | ||||
|  | ||||
| #  Newer versions use the ETHERLIKE-MIB to report operational duplex. | ||||
|  | ||||
| sub i_duplex { | ||||
|     my $c6500 = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my $el_duplex = $c6500->el_duplex($partial); | ||||
|  | ||||
|     # Newer software      | ||||
|     if (defined $el_duplex and scalar(keys %$el_duplex)){ | ||||
|         my %i_duplex; | ||||
|         foreach my $el_port (keys %$el_duplex){ | ||||
|             my $duplex = $el_duplex->{$el_port}; | ||||
|             next unless defined $duplex; | ||||
|  | ||||
|             $i_duplex{$el_port} = 'half' if $duplex =~ /half/i; | ||||
|             $i_duplex{$el_port} = 'full' if $duplex =~ /full/i; | ||||
|         } | ||||
|         return \%i_duplex; | ||||
|     } | ||||
|     # Fall back to CiscoStack method | ||||
|     else { | ||||
|         return $c6500->SUPER::i_duplex($partial); | ||||
|     } | ||||
| } | ||||
|  | ||||
| # Newer software uses portDuplex as admin setting | ||||
|  | ||||
| sub i_duplex_admin { | ||||
|     my $c6500 = shift; | ||||
|     my $partial = shift; | ||||
|  | ||||
|     my $el_duplex = $c6500->el_duplex($partial); | ||||
|  | ||||
|     # Newer software      | ||||
|     if (defined $el_duplex and scalar(keys %$el_duplex)){ | ||||
|         my $p_port   = $c6500->p_port()   || {}; | ||||
|         my $p_duplex = $c6500->p_duplex() || {}; | ||||
|          | ||||
|         my $i_duplex_admin = {}; | ||||
|         foreach my $port (keys %$p_duplex) { | ||||
|             my $iid = $p_port->{$port}; | ||||
|             next unless defined $iid; | ||||
|             next if (defined $partial and $iid !~ /^$partial$/); | ||||
|              | ||||
|             $i_duplex_admin->{$iid} = $p_duplex->{$port}; | ||||
|         } | ||||
|         return $i_duplex_admin; | ||||
|     } | ||||
|     # Fall back to CiscoStack method | ||||
|     else { | ||||
|         return $c6500->SUPER::i_duplex_admin($partial); | ||||
|     }     | ||||
| } | ||||
|  | ||||
| sub set_i_duplex_admin { | ||||
|     # map a textual duplex to an integer one the switch understands | ||||
|     my %duplexes = qw/half 1 full 2 auto 4/; | ||||
|  | ||||
|     my $c6500 = shift; | ||||
|     my ($duplex, $iid) = @_; | ||||
|  | ||||
|     my $el_duplex = $c6500->el_duplex($iid); | ||||
|  | ||||
|     # Auto duplex only supported on newer software | ||||
|     if (defined $el_duplex and scalar(keys %$el_duplex)){ | ||||
|         my $p_port  = $c6500->p_port() || {}; | ||||
|         my %reverse_p_port = reverse %$p_port; | ||||
|  | ||||
|        $duplex = lc($duplex); | ||||
|  | ||||
|        return 0 unless defined $duplexes{$duplex}; | ||||
|  | ||||
|        $iid = $reverse_p_port{$iid}; | ||||
|  | ||||
|        return $c6500->set_p_duplex($duplexes{$duplex}, $iid); | ||||
|     } | ||||
|     else { | ||||
|         $c6500->SUPER::set_i_duplex_admin; | ||||
|     } | ||||
| } | ||||
|  | ||||
| 1; | ||||
| __END__ | ||||
|  | ||||
| @@ -250,6 +327,46 @@ See documentation in L<SNMP::Info::Layer3/"GLOBALS"> for details. | ||||
| These are methods that return tables of information in the form of a reference | ||||
| to a hash. | ||||
|  | ||||
| =head2 Overrides | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item $c6500->i_duplex() | ||||
|  | ||||
| Returns reference to hash of iid to current link duplex setting. | ||||
|  | ||||
| Newer software versions return duplex based upon the result of | ||||
| $c6500->el_duplex().  Otherwise it uses the result of the call to | ||||
| CiscoStack i_duplex(). | ||||
|  | ||||
| See L<SNMP::Info::Etherlike> for el_duplex() method and | ||||
| L<SNMP::Info::CiscoStack> for its i_duplex() method. | ||||
|  | ||||
| =item $c6500->i_duplex_admin() | ||||
|  | ||||
| Returns reference to hash of iid to administrative duplex setting. | ||||
|  | ||||
| Newer software versions return duplex based upon the result of | ||||
| $c6500->p_duplex().  Otherwise it uses the result of the call to | ||||
| CiscoStack i_duplex(). | ||||
|  | ||||
| See L<SNMP::Info::CiscoStack> for its i_duplex() and p_duplex() methods. | ||||
|  | ||||
| =item $c6500->set_i_duplex_admin(duplex, ifIndex) | ||||
|  | ||||
| Sets port duplex, must be supplied with duplex and port ifIndex. | ||||
|  | ||||
| Speed choices are 'auto', 'half', 'full'. | ||||
|  | ||||
| Crosses $c6500->p_port() with $c6500->p_duplex() to utilize port ifIndex. | ||||
|  | ||||
|     Example: | ||||
|     my %if_map = reverse %{$c6500->interfaces()}; | ||||
|     $c6500->set_i_duplex_admin('auto', $if_map{'FastEthernet0/1'})  | ||||
|         or die "Couldn't change port duplex. ",$c6500->error(1); | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head2 Table Methods imported from SNMP::Info::CiscoVTP | ||||
|  | ||||
| See documentation in L<SNMP::Info::CiscoVTP/"TABLE METHODS"> for details. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Eric Miller
					Eric Miller