- 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:
Eric Miller
2007-06-20 03:05:29 +00:00
parent 659d38b0db
commit ce1fac9e86
4 changed files with 394 additions and 323 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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.