1# SNMP::Info::Layer1::S3000 2# 3# Copyright (c) 2008 Eric Miller 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 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# * Neither the name of the University of California, Santa Cruz 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" 19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22# LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28# POSSIBILITY OF SUCH DAMAGE. 29 30package SNMP::Info::Layer1::S3000; 31 32use strict; 33use warnings; 34use Exporter; 35use SNMP::Info::Layer2; 36 37@SNMP::Info::Layer1::S3000::ISA = qw/SNMP::Info::Layer2 Exporter/; 38@SNMP::Info::Layer1::S3000::EXPORT_OK = qw//; 39 40our ($VERSION, %FUNCS, %GLOBALS, %MIBS, %MUNGE); 41 42$VERSION = '3.81'; 43 44%MIBS = ( 45 %SNMP::Info::Layer2::MIBS, 46 'SYNOPTICS-ETHERNET-MIB' => 's3EnetPortTable', 47 'SYNOPTICS-COMMON-MIB' => 's3AgentType', 48); 49 50%GLOBALS = ( 51 %SNMP::Info::Layer2::GLOBALS, 52 53 # From SYNOPTICS-COMMON-MIB 54 'os_bin' => 's3AgentFwVer', 55 's3000_major_ver' => 's3AgentSwMajorVer', 56 's3000_minor_ver' => 's3AgentSwMinorVer', 57 's3000_maint_ver' => 's3AgentSwMaintVer', 58); 59 60%FUNCS = ( 61 %SNMP::Info::Layer2::FUNCS, 62 63 # SYNOPTICS-ETHERNET-MIB::s3EnetPortTable 64 's3000_pb_index' => 's3EnetPortBoardIndex', 65 's3000_pp_index' => 's3EnetPortIndex', 66 's3000_up_admin' => 's3EnetPortPartStatus', 67 's3000_up' => 's3EnetPortLinkStatus', 68 69 # SYNOPTICS-ETHERNET-MIB::s3EnetShowNodesTable 70 's3000_nb_index' => 's3EnetShowNodesSlotIndex', 71 's3000_np_index' => 's3EnetShowNodesPortIndex', 72 'fw_mac' => 's3EnetShowNodesMacAddress', 73 74 # SYNOPTICS-ETHERNET-MIB::s3EnetTopNmmTable 75 's3000_topo_port' => 's3EnetTopNmmPort', 76 's3000_topo_mac' => 's3EnetTopNmmMacAddr', 77); 78 79%MUNGE = ( 80 %SNMP::Info::Layer2::MUNGE, 's3000_topo_mac' => \&SNMP::Info::munge_mac 81); 82 83sub layers { 84 return '00000011'; 85} 86 87sub os { 88 return 'synoptics'; 89} 90 91sub vendor { 92 return 'nortel'; 93} 94 95sub model { 96 my $s3000 = shift; 97 my $id = $s3000->id(); 98 return unless defined $id; 99 my $model = &SNMP::translateObj($id); 100 return $id unless defined $model; 101 $model =~ s/^s3reg-//i; 102 103 return $1 if ( $model =~ /((\d+){3}[\dX])/ ); 104 return $model; 105} 106 107sub os_ver { 108 my $s3000 = shift; 109 my $major_ver = $s3000->s3000_major_ver() || 0; 110 my $minor_ver = $s3000->s3000_minor_ver() || 0; 111 my $maint_ver = $s3000->s3000_maint_ver() || 0; 112 113 my $ver = "$major_ver.$minor_ver.$maint_ver"; 114 return $ver; 115} 116 117sub mac { 118 my $s3000 = shift; 119 my $topo_port = $s3000->s3000_topo_port(); 120 my $topo_mac = $s3000->s3000_topo_mac(); 121 122 foreach my $entry ( keys %$topo_port ) { 123 my $port = $topo_port->{$entry}; 124 next unless $port == 0; 125 my $mac = $topo_mac->{$entry}; 126 return $mac; 127 } 128 129 # Topology turned off, not supported. 130 return; 131} 132 133# Hubs do not support ifMIB requirements for get MAC 134# and port status 135 136sub i_index { 137 my $s3000 = shift; 138 my $partial = shift; 139 140 my $b_index = $s3000->s3000_pb_index($partial) || {}; 141 my $p_index = $s3000->s3000_pp_index($partial) || {}; 142 143 my %i_index; 144 foreach my $iid ( keys %$b_index ) { 145 my $board = $b_index->{$iid}; 146 next unless defined $board; 147 my $port = $p_index->{$iid} || 0; 148 149 # We need to make up an index for multiple board instances. 150 my $index = ( $board * 256 ) + $port; 151 152 $i_index{$iid} = $index; 153 } 154 return \%i_index; 155} 156 157# Partials don't really help in this class, but implemented 158# for consistency 159 160sub interfaces { 161 my $s3000 = shift; 162 my $partial = shift; 163 164 my $i_index = $s3000->i_index() || {}; 165 166 my %if; 167 foreach my $iid ( keys %$i_index ) { 168 my $index = $i_index->{$iid}; 169 next unless defined $index; 170 next if ( defined $partial and $index !~ /^$partial$/ ); 171 172 # Index numbers are deterministic slot * 256 + port - see i_index() 173 my $port = $index % 256; 174 my $slot = int( $index / 256 ); 175 176 my $slotport = "$slot.$port"; 177 178 $if{$index} = $slotport; 179 } 180 181 return \%if; 182} 183 184sub i_duplex { 185 my $s3000 = shift; 186 my $partial = shift; 187 188 my $port_index = $s3000->i_index() || {}; 189 190 my %i_duplex; 191 foreach my $iid ( keys %$port_index ) { 192 my $index = $port_index->{$iid}; 193 next unless defined $index; 194 next if ( defined $partial and $index !~ /^$partial$/ ); 195 196 # Hubs only function half duplex 197 my $duplex = 'half'; 198 $i_duplex{$index} = $duplex; 199 } 200 return \%i_duplex; 201} 202 203sub i_duplex_admin { 204 my $s3000 = shift; 205 my $partial = shift; 206 207 my $port_index = $s3000->i_index() || {}; 208 209 my %i_duplex_admin; 210 foreach my $iid ( keys %$port_index ) { 211 my $index = $port_index->{$iid}; 212 next unless defined $index; 213 next if ( defined $partial and $index !~ /^$partial$/ ); 214 215 # Hubs only function half duplex 216 my $duplex = 'half'; 217 $i_duplex_admin{$index} = $duplex; 218 } 219 return \%i_duplex_admin; 220} 221 222sub i_speed { 223 my $s3000 = shift; 224 my $partial = shift; 225 226 my $port_index = $s3000->i_index() || {}; 227 228 my %i_speed; 229 foreach my $iid ( keys %$port_index ) { 230 my $index = $port_index->{$iid}; 231 next unless defined $index; 232 next if ( defined $partial and $index !~ /^$partial$/ ); 233 234 # These hubs only support 10 Mbs 235 my $speed = '10000000'; 236 $i_speed{$index} = $speed; 237 } 238 return \%i_speed; 239} 240 241sub i_up { 242 my $s3000 = shift; 243 my $partial = shift; 244 245 my $port_index = $s3000->i_index() || {}; 246 my $link_stat = $s3000->s3000_up() || {}; 247 248 my %i_up; 249 foreach my $iid ( keys %$port_index ) { 250 my $index = $port_index->{$iid}; 251 next unless defined $index; 252 next if ( defined $partial and $index !~ /^$partial$/ ); 253 my $link_stat = $link_stat->{$iid}; 254 next unless defined $link_stat; 255 256 $link_stat = 'up' if $link_stat =~ /on/i; 257 $link_stat = 'down' if $link_stat =~ /off/i; 258 259 $i_up{$index} = $link_stat; 260 } 261 return \%i_up; 262} 263 264sub i_up_admin { 265 my $s3000 = shift; 266 my $partial = shift; 267 268 my $i_index = $s3000->i_index() || {}; 269 my $link_stat = $s3000->s3000_up_admin() || {}; 270 271 my %i_up_admin; 272 foreach my $iid ( keys %$i_index ) { 273 my $index = $i_index->{$iid}; 274 next unless defined $index; 275 next if ( defined $partial and $index !~ /^$partial$/ ); 276 my $link_stat = $link_stat->{$iid}; 277 next unless defined $link_stat; 278 279 $i_up_admin{$index} = $link_stat; 280 } 281 return \%i_up_admin; 282} 283 284sub set_i_up_admin { 285 286 # map setting to those the hub will understand 287 my %setting = qw/up 2 down 3/; 288 289 my $s3000 = shift; 290 my ( $setting, $iid ) = @_; 291 292 my $i_index = $s3000->i_index() || {}; 293 my %reverse_i_index = reverse %$i_index; 294 295 $setting = lc($setting); 296 297 return 0 unless defined $setting{$setting}; 298 299 $iid = $reverse_i_index{$iid}; 300 301 return $s3000->set_s3000_up_admin( $setting{$setting}, $iid ); 302} 303 304# Hubs do not support the standard Bridge MIB 305sub bp_index { 306 my $s3000 = shift; 307 my $partial = shift; 308 309 my $b_index = $s3000->s3000_nb_index() || {}; 310 my $p_index = $s3000->s3000_np_index() || {}; 311 my $model = $s3000->model(); 312 313 my %bp_index; 314 foreach my $iid ( keys %$b_index ) { 315 my $board = $b_index->{$iid}; 316 next unless defined $board; 317 my $port = $p_index->{$iid} || 0; 318 319 my $index = ( $board * 256 ) + $port; 320 next if ( defined $partial and $index !~ /^$partial$/ ); 321 322 $bp_index{$index} = $index; 323 } 324 return \%bp_index; 325} 326 327sub fw_mac { 328 my $s3000 = shift; 329 my $partial = shift; 330 331 return $s3000->SUPER::fw_mac($partial); 332} 333 334sub fw_port { 335 my $s3000 = shift; 336 my $partial = shift; 337 338 my $b_index = $s3000->s3000_nb_index($partial) || {}; 339 my $p_index = $s3000->s3000_np_index($partial) || {}; 340 my $model = $s3000->model(); 341 342 my %fw_port; 343 foreach my $iid ( keys %$b_index ) { 344 my $board = $b_index->{$iid}; 345 next unless defined $board; 346 my $port = $p_index->{$iid} || 0; 347 348 my $index = ( $board * 256 ) + $port; 349 350 $fw_port{$iid} = $index; 351 } 352 return \%fw_port; 353} 354 3551; 356__END__ 357 358=head1 NAME 359 360SNMP::Info::Layer1::S3000 - SNMP Interface to Synoptics / Nortel Hubs 361 362=head1 AUTHOR 363 364Eric Miller 365 366=head1 SYNOPSIS 367 368 #Let SNMP::Info determine the correct subclass for you. 369 370 my $s3000 = new SNMP::Info( 371 AutoSpecify => 1, 372 Debug => 1, 373 DestHost => 'myswitch', 374 Community => 'public', 375 Version => 2 376 ) 377 378 or die "Can't connect to DestHost.\n"; 379 380 my $class = $s3000->class(); 381 print "SNMP::Info determined this device to fall under subclass : $class\n"; 382 383=head1 DESCRIPTION 384 385Provides abstraction to the configuration information obtainable from a 386Bay hub device through SNMP. Also provides device MAC to port mapping through 387the proprietary MIB. 388 389=head2 Inherited Classes 390 391=over 392 393=item SNMP::Info::Layer2 394 395=back 396 397=head2 Required MIBs 398 399=over 400 401=item F<SYNOPTICS-COMMON-MIB> 402 403=item F<SYNOPTICS-ETHERNET-MIB> 404 405=back 406 407=head2 Inherited MIBs 408 409See L<SNMP::Info::Layer2/"Required MIBs"> for its MIB requirements. 410 411=head1 GLOBALS 412 413These are methods that return scalar value from SNMP 414 415=over 416 417=item $s3000->vendor() 418 419Returns 'nortel' 420 421=item $s3000->os() 422 423Returns 'synoptics' 424 425=item $s3000->model() 426 427Cross references $s3000->id() to the F<SYNOPTICS-MIB> and returns 428the results. 429 430Removes C<sreg-> from the model name and returns only the numeric model 431identifier. 432 433=item $stack->os_ver() 434 435Returns the software version specified as major.minor.maint. 436 437(C<s3AgentSwMajorVer>).(C<s3AgentSwMinorVer>).(C<s3AgentSwMaintVer>) 438 439=item $stack->os_bin() 440 441Returns the firmware version. (C<s3AgentFwVer>) 442 443=item $s3000->mac() 444 445Returns MAC of the advertised IP address of the device. 446 447=back 448 449=head2 Overrides 450 451=over 452 453=item $s3000->layers() 454 455Returns 00000011. Class emulates Layer 2 functionality through proprietary 456MIBs. 457 458=back 459 460=head2 Globals imported from SNMP::Info::Layer2 461 462See L<SNMP::Info::Layer2/"GLOBALS"> for details. 463 464=head1 TABLE METHODS 465 466These are methods that return tables of information in the form of a reference 467to a hash. 468 469=head2 Overrides 470 471=over 472 473=item $s3000->i_index() 474 475Returns reference to map of IIDs to Interface index. 476 477Since hubs do not support C<ifIndex>, the interface index is created using the 478formula (board * 256 + port). This is required to support devices with more 479than one module. 480 481=item $s3000->interfaces() 482 483Returns reference to map of IIDs to physical ports. 484 485=item $s3000->i_duplex() 486 487Returns half, hubs do not support full duplex. 488 489=item $s3000->i_duplex_admin() 490 491Returns half, hubs do not support full duplex. 492 493=item $s3000->i_speed() 494 495Returns 10000000. The hubs only support 10 Mbs Ethernet. 496 497=item $s3000->i_up() 498 499Returns (C<s3EnetPortLinkStatus>) for each port. Translates on/off to 500up/down. 501 502=item $s3000->i_up_admin() 503 504Returns (C<s3EnetPortPartStatus>) for each port. 505 506=item $s3000->set_i_up_admin(state, ifIndex) 507 508Sets port state, must be supplied with state and port C<ifIndex> 509 510State choices are 'up' or 'down' 511 512Example: 513 my %if_map = reverse %{$s3000->interfaces()}; 514 $s3000->set_i_up_admin('down', $if_map{'1.1'}) 515 or die "Couldn't change port state. ",$s3000->error(1); 516 517=item $s3000->bp_index() 518 519Simulates bridge MIB by returning reference to a hash containing the index for 520both the keys and values. 521 522=item $s3000->fw_port() 523 524Returns reference to map of IIDs of the 525C<SYNOPTICS-ETHERNET-MIB::s3EnetShowNodesTable> to the Interface index. 526 527=item $s3000->fw_mac() 528 529(C<s3EnetShowNodesMacAddress>) 530 531=item $s3000->s3000_topo_port() 532 533Returns reference to hash. Key: Table entry, Value:Port Number 534(interface iid) 535 536(C<s3EnetTopNmmPort>) 537 538=item $s3000->s3000_topo_mac() 539 540(C<s3EnetTopNmmMacAddr>) 541 542Returns reference to hash. Key: Table entry, Value:Remote MAC address 543 544=back 545 546=head2 Table Methods imported from SNMP::Info::Layer2 547 548See L<SNMP::Info::Layer2/"TABLE METHODS"> for details. 549 550=cut 551