diff --git a/Info/CiscoStack.pm b/Info/CiscoStack.pm index cc8c9621..f02845fc 100644 --- a/Info/CiscoStack.pm +++ b/Info/CiscoStack.pm @@ -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 - -=item $stack->cps_notify() - -B - -=item $stack->cps_rate() - -B - -=item $stack->cps_enable() - -B - -=item $stack->cps_mac_count() - -B - -=item $stack->cps_mac_max() - -B - -=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) is auto +then the operational duplex can not be determined. Otherwise it uses the +reported port duplex (B). =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) which if set to +autonegotiate then the duplex will also autonegotiate, otherwise it uses the +reported port duplex (B). =item $stack->set_i_speed_admin(speed, ifIndex) @@ -673,147 +606,4 @@ B =back - -=head2 CISCO-PORT-SECURITY-MIB - Interface Config Table - -See CISCO-PORT-SECURITY-MIB for details. - -=over - -=item $stack->cps_i_limit_val() - -B - -=item $stack->cps_i_limit() - -B - -=item $stack->cps_i_sticky() - -B - -=item $stack->cps_i_clear_type() - -B - -=item $stack->cps_i_shutdown() - -B - -=item $stack->cps_i_flood() - -B - -=item $stack->cps_i_clear() - -B - -=item $stack->cps_i_mac() - -B - -=item $stack->cps_i_count() - -B - -=item $stack->cps_i_action() - -B - -=item $stack->cps_i_mac_static() - -B - -=item $stack->cps_i_mac_type() - -B - -=item $stack->cps_i_mac_age() - -B - -=item $stack->cps_i_mac_count() - -B - -=item $stack->cps_i_mac_max() - -B - -=item $stack->cps_i_status() - -B - -=item $stack->cps_i_enable() - -B - -=back - -=head2 CISCO-PORT-SECURITY-MIB::cpsIfVlanTable - -=over - -=item $stack->cps_i_v_mac_count() - -B - -=item $stack->cps_i_v_mac_max() - -B - -=item $stack->cps_i_v() - -B - -=back - -=head2 CISCO-PORT-SECURITY-MIB::cpsIfVlanSecureMacAddrTable - -=over - -=item $stack->cps_i_v_mac_status() - -B - -=item $stack->cps_i_v_mac_age() - -B - -=item $stack->cps_i_v_mac_type() - -B - -=item $stack->cps_i_v_vlan() - -B - -=item $stack->cps_i_v_mac() - -B - -=back - -=head2 CISCO-PORT-SECURITY-MIB::cpsSecureMacAddressTable - -=over - -=item $stack->cps_m_status() - -B - -=item $stack->cps_m_age() - -B - -=item $stack->cps_m_type() - -B - -=item $stack->cps_m_mac() - -B - -=back - =cut diff --git a/Info/Layer2/Catalyst.pm b/Info/Layer2/Catalyst.pm index 21f0c33a..492fdafb 100644 --- a/Info/Layer2/Catalyst.pm +++ b/Info/Layer2/Catalyst.pm @@ -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 + =item $cat->bp_index() Returns reference to hash of bridge port table entries map back to interface diff --git a/Info/Layer3/C3550.pm b/Info/Layer3/C3550.pm index f44a0ef5..ab6958b4 100644 --- a/Info/Layer3/C3550.pm +++ b/Info/Layer3/C3550.pm @@ -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 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 for el_duplex() method and +L 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 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 for details. diff --git a/Info/Layer3/C6500.pm b/Info/Layer3/C6500.pm index fc09aaf0..56c8f90b 100644 --- a/Info/Layer3/C6500.pm +++ b/Info/Layer3/C6500.pm @@ -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 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 for el_duplex() method and +L 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 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 for details.