1# SNMP::Info::CiscoStpExtensions 2# 3# Copyright (c)2009 Carlos Vicente 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 notice, 12# this list of conditions and the following disclaimer in the documentation 13# and/or other materials provided with the distribution. 14# * Neither the name of the author 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" AND 19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29package SNMP::Info::CiscoStpExtensions; 30 31use strict; 32use warnings; 33use Exporter; 34use SNMP::Info; 35use SNMP::Info::Bridge; 36 37our ($VERSION, $DEBUG, %MIBS, %FUNCS, %GLOBALS, %MUNGE, %PORTSTAT, $INIT); 38 39$VERSION = '3.81'; 40 41@SNMP::Info::CiscoStpExtensions::ISA = qw/SNMP::Info::Bridge SNMP::Info Exporter/; 42@SNMP::Info::CiscoStpExtensions::EXPORT_OK = qw//; 43 44%MIBS = ( 45 %SNMP::Info::Bridge::MIBS, 46 'CISCO-STP-EXTENSIONS-MIB' => 'stpxSpanningTreeType', 47 ); 48 49%GLOBALS = ( 50 %SNMP::Info::Bridge::GLOBALS, 51 'stpx_mst_config_digest' => 'stpxSMSTConfigDigest', 52 'stpx_mst_region_name' => 'stpxMSTRegionName', 53 'stpx_mst_region_rev' => 'stpxSMSTRegionRevision', 54 'stpx_stp_type' => 'stpxSpanningTreeType', 55 'stpx_bpduguard_enable' => 'stpxFastStartBpduGuardEnable', 56 'stpx_bpdufilter_enable' => 'stpxFastStartBpduFilterEnable', 57 'stpx_faststart_default' => 'stpxFastStartGlobalDefaultMode', 58 ); 59 60%FUNCS = ( 61 %SNMP::Info::Bridge::FUNCS, 62 'stpx_rootguard_enabled' => 'stpxRootGuardConfigEnabled', 63 'stpx_loopguard_enabled' => 'stpxLoopGuardConfigEnabled', 64 'stpx_faststart_enabled' => 'stpxFastStartPortEnable', 65 'stpx_faststart_operational' => 'stpxFastStartPortMode', 66 'stpx_port_bpduguard_mode' => 'stpxFastStartPortBpduGuardMode', 67 'stpx_port_bpdufilter_mode' => 'stpxFastStartPortBpduFilterMode', 68 'stpx_smst_root' => 'stpxSMSTInstanceCISTRegionalRoot', 69 'stpx_smst_vlans_mapped_1k2k' => 'stpxSMSTInstanceVlansMapped1k2k', 70 'stpx_smst_vlans_mapped_3k4k' => 'stpxSMSTInstanceVlansMapped3k4k', 71 ); 72 73%MUNGE = ( 74 %SNMP::Info::Bridge::MUNGE, 75 'stpx_mst_config_digest' => \&SNMP::Info::CiscoStpExtensions::oct2str, 76 ); 77 78 79# Report version of STP via standard method 80sub stp_ver { 81 my $self = shift; 82 my $stp_ver = $self->SUPER::stp_ver(); 83 if ( !defined($stp_ver) || $stp_ver eq 'unknown' ){ 84 if ( defined $self->stpx_stp_type() ){ 85 $stp_ver = $self->stpx_stp_type(); 86 } 87 } 88 return $stp_ver; 89} 90 91sub mst_config_digest { 92 my $self = shift; 93 return $self->stpx_mst_config_digest; 94} 95 96sub mst_region_name { 97 my $self = shift; 98 return $self->stpx_mst_region_name; 99} 100 101sub mst_region_rev { 102 my $self = shift; 103 return $self->stpx_mst_region_rev; 104} 105 106 107sub mst_vlan2instance { 108 my $self = shift; 109 110 # Get MST vlan-to-instance mapping 111 my $m1k2k = $self->stpx_smst_vlans_mapped_1k2k; 112 my $m3k4k = $self->stpx_smst_vlans_mapped_3k4k; 113 114 # Get list of VLANs 115 my $vlan_membership = $self->i_vlan_membership; 116 my @vlans; 117 foreach my $iid ( keys %$vlan_membership ){ 118 if ( my $vm = $vlan_membership->{$iid} ){ 119 foreach my $vid ( @$vm ){ 120 push @vlans, $vid; 121 } 122 } 123 } 124 my %res; 125 foreach my $vlan ( @vlans ){ 126 if ( $vlan < 2048 ){ 127 foreach my $inst ( keys %$m1k2k ){ 128 my $list = $m1k2k->{$inst}; 129 my $vlanlist = [split(//, unpack("B*", $list))]; 130 if ( @$vlanlist[$vlan] ){ 131 $res{$vlan} = $inst; 132 last; 133 } 134 } 135 }else{ 136 foreach my $inst ( keys %$m3k4k ){ 137 my $list = $m3k4k->{$inst}; 138 my $vlanlist = [split(//, unpack("B*", $list))]; 139 if ( @$vlanlist[$vlan-2048] ){ 140 $res{$vlan} = $inst; 141 last; 142 } 143 } 144 } 145 } 146 return \%res; 147} 148 149sub i_rootguard_enabled { 150 my $self = shift; 151 my $partial = shift; 152 153 my $rg_enabled = $self->stpx_rootguard_enabled(); 154 my $bp_index = $self->bp_index($partial); 155 156 my %res; 157 foreach my $index ( keys %$rg_enabled ){ 158 my $enabled = $rg_enabled->{$index}; 159 my $iid = $bp_index->{$index}; 160 next unless defined $iid; 161 next unless defined $enabled; 162 $res{$iid} = $enabled; 163 } 164 return \%res; 165} 166 167sub i_loopguard_enabled { 168 my $self = shift; 169 my $partial = shift; 170 171 my $lg_enabled = $self->stpx_loopguard_enabled(); 172 my $bp_index = $self->bp_index($partial); 173 174 my %res; 175 foreach my $index ( keys %$lg_enabled ){ 176 my $enabled = $lg_enabled->{$index}; 177 my $iid = $bp_index->{$index}; 178 next unless defined $iid; 179 next unless defined $enabled; 180 $res{$iid} = $enabled; 181 } 182 return \%res; 183} 184 185sub i_bpduguard_enabled { 186 my $self = shift; 187 my $partial = shift; 188 189 my $bpdugm_default = $self->stpx_bpduguard_enable(); 190 my $bp_index = $self->bp_index($partial); 191 my $bpdugm = $self->stpx_port_bpduguard_mode(); 192 193 my %res; 194 foreach my $index ( keys %$bpdugm ){ 195 my $mode = $bpdugm->{$index}; 196 my $iid = $bp_index->{$index}; 197 next unless defined $iid; 198 next unless defined $mode; 199 if ( $mode eq 'default' ){ 200 $res{$iid} = $bpdugm_default; 201 }else{ 202 $res{$iid} = $mode; 203 } 204 } 205 return \%res; 206} 207 208sub i_bpdufilter_enabled { 209 my $self = shift; 210 my $partial = shift; 211 212 my $bpdufm_default = $self->stpx_bpdufilter_enable(); 213 my $bp_index = $self->bp_index($partial); 214 my $bpdufm = $self->stpx_port_bpdufilter_mode(); 215 216 my %res; 217 foreach my $index ( keys %$bpdufm ){ 218 my $mode = $bpdufm->{$index}; 219 my $iid = $bp_index->{$index}; 220 next unless defined $iid; 221 next unless defined $mode; 222 if ( $mode eq 'default' ){ 223 $res{$iid} = $bpdufm_default; 224 }else{ 225 $res{$iid} = $mode; 226 } 227 } 228 return \%res; 229} 230 231sub i_faststart_enabled { 232 my $self = shift; 233 my $partial = shift; 234 235 my $faststart_default = $self->stpx_faststart_default(); 236 my $bp_index = $self->bp_index($partial); 237 my $faststart = $self->stpx_faststart_enabled(); 238 my $faststart_oper = $self->stpx_faststart_operational(); 239 240 my %res; 241 # stpxFastStartPortEnable is deprecated in favour of stpxFastStartPortMode 242 # see https://github.com/netdisco/netdisco/issues/12 243 foreach my $index ( keys %$faststart, keys %$faststart_oper ){ 244 my $mode = $faststart_oper->{$index} || $faststart->{$index}; 245 my $iid = $bp_index->{$index}; 246 next unless defined $iid; 247 next unless defined $mode; 248 if ( $mode eq 'default' ){ 249 $res{$iid} = $faststart_default; 250 }else{ 251 $res{$iid} = $mode; 252 } 253 $res{$iid} = 'enable' if $res{$iid} eq 'true'; 254 $res{$iid} = 'disable' if $res{$iid} eq 'false'; 255 $res{$iid} = 1 if $res{$iid} =~ m/enable/i; # enableForTrunk 256 $res{$iid} = 0 if $res{$iid} eq 'disable'; 257 } 258 return \%res; 259} 260 261 262sub oct2str { 263 my ($v) = @_; 264 return sprintf('%s', unpack('H*', $v)); 265} 266 2671; 268__END__ 269 270=head1 NAME 271 272SNMP::Info::CiscoStpExtensions - SNMP Interface to C<CISCO-STP-EXTENSIONS-MIB> 273 274=head1 AUTHOR 275 276Carlos Vicente 277 278=head1 SYNOPSIS 279 280 my $stpx = new SNMP::Info( 281 AutoSpecify => 1, 282 Debug => 1, 283 DestHost => 'myswitch', 284 Community => 'public', 285 Version => 2 286 ) 287 288 or die "Can't connect to DestHost.\n"; 289 290 my $class = $stpx->class(); 291 print " Using device sub class : $class\n"; 292 293=head1 DESCRIPTION 294 295Create or use a subclass of SNMP::Info that inherits this class. Do not use 296directly. 297 298For debugging you can call new() directly as you would in SNMP::Info 299 300 my $stpx = new SNMP::Info::CiscoStpExtensions(...); 301 302=head2 Inherited Classes 303 304=over 305 306=item SNMP::Info 307 308=item SNMP::Info::Bridge 309 310=back 311 312=head2 Required MIBs 313 314=over 315 316=item F<CISCO-STP-EXTENSIONS-MIB> 317 318=back 319 320=head1 GLOBALS 321 322These are methods that return scalar values from SNMP 323 324=over 325 326=item $stpx->stp_ver() 327 328Returns the particular STP version running on this device. 329Meant to override SNMP::Info::Brigde::stp_ver() 330 331Values: C<pvstPlus>, C<mistp>, C<mistpPvstPlus>, C<mst>, C<rapidPvstPlus> 332 333(C<stpxSpanningTreeType>) 334 335=back 336 337=head1 TABLE METHODS 338 339These are methods that return tables of information in the form of a reference 340to a hash. 341 342=over 343 344=item $stpx->mst_config_digest() 345 346Returns the Multiple Spanning Tree (MST) configuration digest 347 348(C<stpxSMSTConfigDigest>) 349 350=item $stpx->mst_region_name() 351 352Returns the Multiple Spanning Tree (MST) region name 353 354(C<stpxMSTRegionName>) 355 356=item $stpx->mst_region_rev() 357 358Returns the Multiple Spanning Tree (MST) region name 359 360(C<stpxSMSTRegionRevision>) 361 362=item $stpx->mst_vlan2instance() 363 364Returns the mapping of vlan to MST instance in the form of a hash reference 365with key = VLAN id, value = STP instance 366 367=item $stpx->i_rootguard_enabled() 368 369Returns 1 or 0 depending on whether C<RootGuard> is enabled on a given port. 370Format is a hash reference with key = C<ifIndex>, value = [1|0] 371 372(C<stpxRootGuardConfigEnabled>) 373 374=item $stpx->i_loopguard_enabled() 375 376Returns 1 or 0 depending on whether C<LoopGuard> is enabled on a given port. 377Format is a hash reference with key = C<ifIndex>, value = [1|0] 378 379(C<stpxLoopGuardConfigEnabled>) 380 381=item $stpx->i_bpduguard_enabled() 382 383Returns 1 or 0 depending on whether C<BpduGuard> is enabled on a given port. 384Format is a hash reference with key = C<ifIndex>, value = [1|0] 385 386(C<stpxFastStartPortBpduGuardMode>) 387 388=item $stpx->i_bpdufilter_enabled() 389 390Returns 1 or 0 depending on whether C<BpduFilter> is enabled on a given port. 391Format is a hash reference with key = C<ifIndex>, value = [1|0] 392 393(C<stpxFastStartBpduFilterEnable>) 394 395=item $stpx->i_faststart_enabled() 396 397Returns 1 or 0 depending on whether FastStart (aka PortFast) is enabled on a 398given port. Format is a hash reference with key = C<ifIndex>, value = [1|0] 399 400(C<stpxFastStartPortEnable> and C<stpxFastStartPortMode>) 401 402=back 403 404=head1 MUNGES 405 406=over 407 408=item oct2str() 409 410Unpacks H* into a string 411 412=back 413 414=cut 415