File Coverage

blib/lib/Net/SNMP/Mixin/Dot1dStp.pm
Criterion Covered Total %
statement 55 131 41.9
branch 19 42 45.2
condition 1 3 33.3
subroutine 14 16 87.5
pod 2 2 100.0
total 91 194 46.9


line stmt bran cond sub pod time code
1             package Net::SNMP::Mixin::Dot1dStp;
2              
3 4     4   399115 use strict;
  4         13  
  4         171  
4 4     4   25 use warnings;
  4         7  
  4         179  
5              
6             #
7             # store this package name in a handy variable,
8             # used for unambiguous prefix of mixin attributes
9             # storage in object hash
10             #
11             my $prefix = __PACKAGE__;
12              
13             #
14             # this module import config
15             #
16 4     4   23 use Carp ();
  4         11  
  4         112  
17 4     4   4186 use Net::SNMP::Mixin::Util qw/idx2val hex2octet normalize_mac push_error/;
  4         107484  
  4         40  
18              
19             #
20             # this module export config
21             #
22             my @mixin_methods;
23              
24             BEGIN {
25 4     4   2109 @mixin_methods = (
26             qw/
27             get_dot1d_stp_group
28             get_dot1d_stp_port_table
29             /
30             );
31             }
32              
33 4         36 use Sub::Exporter -setup => {
34             exports => [@mixin_methods],
35             groups => { default => [@mixin_methods], },
36 4     4   33 };
  4         9  
37              
38             #
39             # SNMP oid constants used in this module
40             #
41             use constant {
42 4         8619 DOT1D_STP_GROUP => '1.3.6.1.2.1.17.2',
43              
44             DOT1D_STP_PROTO => '1.3.6.1.2.1.17.2.1.0',
45             DOT1D_STP_PRIO => '1.3.6.1.2.1.17.2.2.0',
46             DOT1D_STP_TIME_SINCE_TOPO_CHANGE => '1.3.6.1.2.1.17.2.3.0',
47             DOT1D_STP_TOPO_CHANGES => '1.3.6.1.2.1.17.2.4.0',
48             DOT1D_STP_DESIGNATED_ROOT => '1.3.6.1.2.1.17.2.5.0',
49             DOT1D_STP_ROOT_COST => '1.3.6.1.2.1.17.2.6.0',
50             DOT1D_STP_ROOT_PORT => '1.3.6.1.2.1.17.2.7.0',
51             DOT1D_STP_MAX_AGE => '1.3.6.1.2.1.17.2.8.0',
52             DOT1D_STP_HELLO_TIME => '1.3.6.1.2.1.17.2.9.0',
53             DOT1D_STP_HOLD_TIME => '1.3.6.1.2.1.17.2.10.0',
54             DOT1D_STP_FWD_DELAY => '1.3.6.1.2.1.17.2.11.0',
55             DOT1D_STP_BRIDGE_MAX_AGE => '1.3.6.1.2.1.17.2.12.0',
56             DOT1D_STP_BRIDGE_HELLO_TIME => '1.3.6.1.2.1.17.2.13.0',
57             DOT1D_STP_BRIDGE_FWD_DELAY => '1.3.6.1.2.1.17.2.14.0',
58              
59             DOT1D_STP_PORT_TABLE => '1.3.6.1.2.1.17.2.15',
60              
61             DOT1D_STP_PORT_PRIO => '1.3.6.1.2.1.17.2.15.1.2',
62             DOT1D_STP_PORT_STATE => '1.3.6.1.2.1.17.2.15.1.3',
63             DOT1D_STP_PORT_ENABLE => '1.3.6.1.2.1.17.2.15.1.4',
64             DOT1D_STP_PORT_PATH_COST => '1.3.6.1.2.1.17.2.15.1.5',
65             DOT1D_STP_PORT_DESIGNATED_ROOT => '1.3.6.1.2.1.17.2.15.1.6',
66             DOT1D_STP_PORT_DESIGNATED_COST => '1.3.6.1.2.1.17.2.15.1.7',
67             DOT1D_STP_PORT_DESIGNATED_BRIDGE => '1.3.6.1.2.1.17.2.15.1.8',
68             DOT1D_STP_PORT_DESIGNATED_PORT => '1.3.6.1.2.1.17.2.15.1.9',
69             DOT1D_STP_PORT_FORWARD_TRANSITIONS => '1.3.6.1.2.1.17.2.15.1.10',
70 4     4   1874 };
  4         9  
71              
72             =head1 NAME
73              
74             Net::SNMP::Mixin::Dot1dStp - mixin class for 802.1D spanning tree information
75              
76             =head1 VERSION
77              
78             Version 0.03
79              
80             =cut
81              
82             our $VERSION = '0.03';
83              
84             =head1 SYNOPSIS
85              
86             use Net::SNMP;
87             use Net::SNMP::Mixin;
88              
89             my $session = Net::SNMP->session( -hostname => 'foo.bar.com' );
90             $session->mixer('Net::SNMP::Mixin::Dot1dStp');
91             $session->init_mixins;
92              
93             snmp_dispatcher();
94             die $session->errors if $session->errors;
95              
96             my $stp_group = $session->get_dot1d_stp_group;
97              
98             printf "TopoChanges: %d\n", $stp_group->{dot1dStpTopChanges};
99             printf "ThisRootPort: %d\n", $stp_group->{dot1dStpRootPort};
100             printf "ThisRootCost: %d\n", $stp_group->{dot1dStpRootCost};
101             printf "ThisStpPrio: %d\n", $stp_group->{dot1dStpPriority};
102             printf "RootBridgeMAC: %s\n",
103             $stp_group->{dot1dStpDesignatedRootAddress};
104             printf "RootBridgePrio: %d\n",
105             $stp_group->{dot1dStpDesignatedRootPriority};
106              
107             my $stp_ports = $session->get_dot1d_stp_port_table;
108             foreach my $port ( sort { $a <=> $b } keys %$stp_ports ) {
109             my $enabled = $stp_ports->{$port}{dot1dStpPortEnable};
110             next unless defined $enabled && $enabled == 1;
111              
112             printf "----------- STP Port: %d ---------\n", $port;
113             printf "PState: %d\n", $stp_ports->{$port}{dot1dStpPortState};
114             printf "PStateStr: %d\n",
115             $stp_ports->{$port}{dot1dStpPortStateString};
116             printf "PPrio: %d\n",
117             $stp_ports->{$port}{dot1dStpPortPriority};
118             printf "PCost: %d\n",
119             $stp_ports->{$port}{dot1dStpPortPathCost};
120             printf "PDesigCost: %d\n",
121             $stp_ports->{$port}{dot1dStpPortDesignatedCost};
122             printf "DBridgePrio: %d\n",
123             $stp_ports->{$port}{dot1dStpPortDesignatedBridgePriority};
124             printf "DBridgeMAC: %d\n",
125             $stp_ports->{$port}{dot1dStpPortDesignatedBridgeAddress};
126             printf "DPortPrio: %d\n",
127             $stp_ports->{$port}{dot1dStpPortDesignatedPortPriority};
128             printf "DPortNr: %d\n",
129             $stp_ports->{$port}{dot1dStpPortDesignatedPortNumber};
130             }
131              
132             =head1 DESCRIPTION
133              
134             This mixin reads data from the B<< dot1dStp >> group out of the BRIDGE-MIB. Normally it's implemented by those bridges that support the Spanning Tree Protocol.
135              
136             =head1 MIXIN METHODS
137              
138             =cut
139              
140             =head2 B<< OBJ->get_dot1d_stp_group() >>
141              
142             Returns the dot1dStp group as a hash reference:
143              
144             {
145             dot1dStpProtocolSpecification => INTEGER,
146             dot1dStpPriority => INTEGER,
147             dot1dStpTimeSinceTopologyChange => TIME_TICKS,
148             dot1dStpTopChanges => COUNTER,
149             dot1dStpRootCost => INTEGER,
150             dot1dStpRootPort => INTEGER,
151             dot1dStpMaxAge => TIMEOUT,
152             dot1dStpHelloTime => TIMEOUT,
153             dot1dStpHoldTime => INTEGER,
154             dot1dStpForwardDelay => TIMEOUT,
155             dot1dStpBridgeMaxAge => TIMEOUT,
156             dot1dStpBridgeHelloTime => TIMEOUT,
157             dot1dStpBridgeForwardDelay => TIMEOUT,
158             dot1dStpDesignatedRoot => BridgeId,
159             dot1dStpDesignatedRootPriority => INTEGER,
160             dot1dStpDesignatedRootAddress => MacAddress,
161             }
162              
163              
164             The dot1dStpDesignatedRoot is a BridgeId struct of priority and MacAddress. The mixin method splits this already into dot1dStpDesignatedRootPriority and dot1dStpDesignatedRootAddress for your convenience.
165              
166             =cut
167              
168             sub get_dot1d_stp_group {
169 1     1 1 44385 my $session = shift;
170 1 50       133 Carp::croak "'$prefix' not initialized,"
171             unless $session->{$prefix}{__initialized};
172              
173             # just a shallow copy for shallow values
174 0         0 my $result = { %{ $session->{$prefix}{dot1dStpGroup} } };
  0         0  
175              
176             # split BridgeId in priority and address
177 0         0 my ( $root_bridge_prio, $root_bridge_address ) =
178             _unpack_bridge_id( $result->{dot1dStpDesignatedRoot} );
179              
180 0         0 $result->{dot1dStpDesignatedRootPriority} = $root_bridge_prio;
181 0         0 $result->{dot1dStpDesignatedRootAddress} = $root_bridge_address;
182              
183 0         0 return $result;
184             }
185              
186             =head2 B<< OBJ->get_dot1d_stp_port_table() >>
187              
188             Returns the dot1dStpPortTable as a hash reference. The keys are the dot1d STP port numbers for which this entry contains Spanning Tree Protocol management information:
189              
190             {
191             INTEGER => { # dot1dStpPort
192              
193             dot1dStpPortPriority => INTEGER,
194             dot1dStpPortState => INTEGER,
195             dot1dStpPortStateString => String,
196             dot1dStpPortEnable => INTEGER,
197             dot1dStpPortPathCost => INTEGER,
198             dot1dStpPortDesignatedRootId => BridgeId,
199             dot1dStpPortDesignatedCost => INTEGER,
200             dot1dStpPortDesignatedBridgeId => BridgeId,
201             dot1dStpPortDesignatedPort => PortId,
202             dot1dStpPortForwardTransitions => COUNTER,
203              
204             # dot1dStpPortDesignatedRootId is a struct (BridgeId) of
205             # priority and MacAddress
206             #
207             dot1dStpPortDesignatedRootPriority => INTEGER,
208             dot1dStpPortDesignatedRootAddress => MacAddress,
209              
210             # dot1dStpPortDesignatedBridgeId is a struct (BridgeId) of
211             # priority and MacAddress
212             #
213             dot1dStpPortDesignatedBridgePriority => INTEGER,
214             dot1dStpPortDesignatedBridgeAddress => MacAddress,
215              
216             # dot1dStpPortDesignatedPort is a struct (PortId) of
217             # priority and bridge port number
218             #
219             dot1dStpPortDesignatedPortPriority => INTEGER,
220             dot1dStpPortDesignatedPortNumber => INTEGER,
221              
222             },
223              
224             ... ,
225             }
226              
227             The structs BridgeId and PortId are already splitted by this mixin method into the relevant values for your convenience.
228              
229             The dot1dStpPort has the same value as the dot1dBasePort and isn't necessarily the ifIndex of the switch.
230              
231             See also the L<< Net::SNMP::Mixin::Dot1dBase >> for a mixin to get the mapping between the ifIndexes and the dot1dBasePorts if needed.
232              
233             =cut
234              
235             sub get_dot1d_stp_port_table {
236 1     1 1 536 my $session = shift;
237 1 50       130 Carp::croak "'$prefix' not initialized,"
238             unless $session->{$prefix}{__initialized};
239              
240             # stash for return values
241 0         0 my $result = {};
242              
243             #
244             # the port's current state translation table
245             #
246 0         0 my %port_state_enum = (
247             1 => 'disabled',
248             2 => 'blocking',
249             3 => 'listening',
250             4 => 'learning',
251             5 => 'forwarding',
252             6 => 'broken',
253             );
254              
255             # the MIB tables are stored in {column}{row}{value} order
256             # but we return {row}{column}{value}
257             #
258             # grab all rows from one random choosen column
259 0         0 my @rows = keys %{ $session->{$prefix}{dot1dStpPortTbl}{dot1dStpPortPriority} };
  0         0  
260              
261 0         0 foreach my $row (@rows) {
262              
263             # loop over all columns
264 0         0 foreach my $column ( keys %{ $session->{$prefix}{dot1dStpPortTbl} } ) {
  0         0  
265              
266             # rebuild in reverse order: result(row,column) = stash(column,row)
267             # side effect: make a shallow copy for shallow values
268              
269 0         0 $result->{$row}{$column} =
270             $session->{$prefix}{dot1dStpPortTbl}{$column}{$row};
271             }
272              
273             #
274             # additonal calculated values from the structs
275             #
276             #
277             # resolve enum
278             #
279 0         0 $result->{$row}{dot1dStpPortStateString} =
280             $port_state_enum{ $result->{$row}{dot1dStpPortState} };
281              
282 0         0 my ( $bridge_prio, $bridge_address);
283              
284             #
285             # split dot1dStpPortDesignatedRoot
286             #
287 0         0 ( $bridge_prio, $bridge_address ) =
288             _unpack_bridge_id( $result->{$row}{dot1dStpPortDesignatedRoot} );
289              
290 0         0 $result->{$row}{dot1dStpPortDesignatedRootPriority} = $bridge_prio;
291 0         0 $result->{$row}{dot1dStpPortDesignatedRootAddress} = $bridge_address;
292              
293             #
294             # split dot1dStpPortDesignatedBridge
295             #
296 0         0 ( $bridge_prio, $bridge_address ) =
297             _unpack_bridge_id( $result->{$row}{dot1dStpPortDesignatedBridge} );
298              
299 0         0 $result->{$row}{dot1dStpPortDesignatedBridgePriority} = $bridge_prio;
300 0         0 $result->{$row}{dot1dStpPortDesignatedBridgeAddress} = $bridge_address;
301              
302 0         0 my ( $portPrio, $portNumber );
303             #
304             # split dot1dStpPortDesignatedPort
305             #
306 0         0 ( $portPrio, $portNumber ) =
307             _unpack_bridge_port_id( $result->{$row}{dot1dStpPortDesignatedPort} );
308              
309 0         0 $result->{$row}{dot1dStpPortDesignatedPortPriority} = $portPrio;
310 0         0 $result->{$row}{dot1dStpPortDesignatedPortNumber} = $portNumber;
311             }
312              
313 0         0 return $result;
314             }
315              
316             =head1 INITIALIZATION
317              
318             =head2 B<< OBJ->_init($reload) >>
319              
320             Fetch the dot1dSTP related snmp values from the host. Don't call this method direct!
321              
322             =cut
323              
324             sub _init {
325 4     4   15331 my ( $session, $reload ) = @_;
326              
327 4 50 33     38 die "$prefix already initalized and reload not forced.\n"
328             if $session->{$prefix}{__initialized} && not $reload;
329              
330             # populate the object with needed mib values
331             #
332             # initialize the object for STP infos
333 4         16 _fetch_dot1d_stp_group($session);
334 4 100       30 return if $session->error;
335              
336 2         17 _fetch_dot1d_stp_port_tbl($session);
337 2 50       16 return if $session->error;
338              
339 2         19 return 1;
340             }
341              
342             =head1 PRIVATE SUBROUTINES
343              
344             =head2 B<< _fetch_dot1d_stp_group($session) >>
345              
346             Fetch the local system data from the dot1dStp tree once during object initialization.
347              
348             =cut
349              
350             sub _fetch_dot1d_stp_group {
351 4     4   10 my $session = shift;
352 4         5 my $result;
353              
354 4 100       46 $result = $session->get_entries(
355             -columns => [ DOT1D_STP_GROUP, ],
356             -endindex => '14.0',
357              
358             # define callback if in nonblocking mode
359             $session->nonblocking
360             ? ( -callback => \&_dot1d_stp_group_cb )
361             : (),
362              
363             );
364              
365 4 100       2018873 unless (defined $result) {
366             # Net::SNMP looses sometimes error messages in nonblocking
367             # mode, so we save them in an extra buffer
368 2         34 my $err_msg = $session->error;
369 2 50       29 push_error($session, "$prefix: $err_msg") if $err_msg;
370 2         43 return;
371             }
372              
373             # in nonblocking mode the callback will be called asynchronously
374 2 50       10 return 1 if $session->nonblocking;
375              
376             # ok we are in synchronous mode, call the result mangling function
377             # by hand
378 0         0 _dot1d_stp_group_cb($session);
379              
380             }
381              
382             =head2 B<< _dot1d_stp_group_cb($session) >>
383              
384             The callback for _fetch_dot1d_stp_group.
385              
386             =cut
387              
388             sub _dot1d_stp_group_cb {
389 2     2   2005534 my $session = shift;
390 2         8 my $vbl = $session->var_bind_list;
391              
392 2 50       26 unless (defined $vbl) {
393             # Net::SNMP looses sometimes error messages in nonblocking
394             # mode, so we save them in an extra buffer
395 2         31 my $err_msg = $session->error;
396 2 50       33 push_error($session, "$prefix: $err_msg") if $err_msg;
397 2         46 return;
398             }
399              
400 0 0       0 unless ( defined $vbl->{ DOT1D_STP_PROTO() } ) {
401 0         0 my $err_msg = "No Spanning Tree Protocol running";
402 0 0       0 push_error( $session, "$prefix: $err_msg" ) if $err_msg;
403 0         0 return;
404             }
405              
406 0         0 my $stash_ptr = $session->{$prefix}{dot1dStpGroup} = {};
407              
408 0         0 $stash_ptr->{dot1dStpProtocolSpecification} = $vbl->{ DOT1D_STP_PROTO() };
409              
410 0         0 $stash_ptr->{dot1dStpPriority} = $vbl->{ DOT1D_STP_PRIO() };
411              
412 0         0 $stash_ptr->{dot1dStpTimeSinceTopologyChange} =
413             $vbl->{ DOT1D_STP_TIME_SINCE_TOPO_CHANGE() };
414              
415 0         0 $stash_ptr->{dot1dStpTopChanges} = $vbl->{ DOT1D_STP_TOPO_CHANGES() };
416              
417 0         0 $stash_ptr->{dot1dStpDesignatedRoot} =
418             $vbl->{ DOT1D_STP_DESIGNATED_ROOT() };
419              
420 0         0 $stash_ptr->{dot1dStpRootCost} = $vbl->{ DOT1D_STP_ROOT_COST() };
421              
422 0         0 $stash_ptr->{dot1dStpRootPort} = $vbl->{ DOT1D_STP_ROOT_PORT() };
423              
424 0         0 $stash_ptr->{dot1dStpMaxAge} = $vbl->{ DOT1D_STP_MAX_AGE() };
425              
426 0         0 $stash_ptr->{dot1dStpHelloTime} = $vbl->{ DOT1D_STP_HELLO_TIME() };
427              
428 0         0 $stash_ptr->{dot1dStpHoldTime} = $vbl->{ DOT1D_STP_HOLD_TIME() };
429              
430 0         0 $stash_ptr->{dot1dStpForwardDelay} = $vbl->{ DOT1D_STP_FWD_DELAY() };
431              
432 0         0 $stash_ptr->{dot1dStpBridgeMaxAge} = $vbl->{ DOT1D_STP_BRIDGE_MAX_AGE() };
433              
434 0         0 $stash_ptr->{dot1dStpBridgeHelloTime} =
435             $vbl->{ DOT1D_STP_BRIDGE_HELLO_TIME() };
436              
437 0         0 $stash_ptr->{dot1dStpBridgeForwardDelay} =
438             $vbl->{ DOT1D_STP_BRIDGE_FWD_DELAY() };
439              
440 0         0 $session->{$prefix}{__initialized}++;
441             }
442              
443             =head2 B<< _fetch_dot1d_stp_port_tbl($session) >>
444              
445             Fetch the dot1dStpPortTable once during object initialization.
446              
447             =cut
448              
449             sub _fetch_dot1d_stp_port_tbl {
450 2     2   4 my $session = shift;
451 2         5 my $result;
452              
453             # fetch the dot1dStpPortTable
454 2 50       19 $result = $session->get_entries(
455             -columns => [
456             DOT1D_STP_PORT_PRIO, DOT1D_STP_PORT_STATE,
457             DOT1D_STP_PORT_ENABLE, DOT1D_STP_PORT_PATH_COST,
458             DOT1D_STP_PORT_DESIGNATED_ROOT, DOT1D_STP_PORT_DESIGNATED_COST,
459             DOT1D_STP_PORT_DESIGNATED_BRIDGE, DOT1D_STP_PORT_DESIGNATED_PORT,
460             DOT1D_STP_PORT_FORWARD_TRANSITIONS,
461             ],
462              
463             # define callback if in nonblocking mode
464             $session->nonblocking
465             ? ( -callback => \&_dot1d_stp_port_tbl_cb )
466             : (),
467             );
468              
469 2 50       4185 unless (defined $result) {
470             # Net::SNMP looses sometimes error messages in nonblocking
471             # mode, so we save them in an extra buffer
472 0         0 my $err_msg = $session->error;
473 0 0       0 push_error($session, "$prefix: $err_msg") if $err_msg;
474 0         0 return;
475             }
476              
477             # in nonblocking mode the callback will be called asynchronously
478 2 50       7 return 1 if $session->nonblocking;
479              
480             # ok we are in synchronous mode, call the result mangling function
481             # by hand
482 0         0 _dot1d_stp_port_tbl_cb($session);
483              
484             }
485              
486             =head2 B<< _dot1d_stp_port_tbl_cb($session) >>
487              
488             The callback for _fetch_dot1d_stp_port_tbl().
489              
490             =cut
491              
492             sub _dot1d_stp_port_tbl_cb {
493 2     2   697 my $session = shift;
494 2         8 my $vbl = $session->var_bind_list;
495              
496 2 50       23 unless (defined $vbl) {
497             # Net::SNMP looses sometimes error messages in nonblocking
498             # mode, so we save them in an extra buffer
499 2         8 my $err_msg = $session->error;
500 2 50       21 push_error($session, "$prefix: $err_msg") if $err_msg;
501 2         26 return;
502             }
503              
504 0           my $stash_ptr = $session->{$prefix}{dot1dStpPortTbl} = {};
505              
506 0           $stash_ptr->{dot1dStpPortPriority} = idx2val( $vbl, DOT1D_STP_PORT_PRIO );
507              
508 0           $stash_ptr->{dot1dStpPortState} = idx2val( $vbl, DOT1D_STP_PORT_STATE );
509              
510 0           $stash_ptr->{dot1dStpPortEnable} = idx2val( $vbl, DOT1D_STP_PORT_ENABLE );
511              
512 0           $stash_ptr->{dot1dStpPortPathCost} =
513             idx2val( $vbl, DOT1D_STP_PORT_PATH_COST );
514              
515 0           $stash_ptr->{dot1dStpPortDesignatedRoot} =
516             idx2val( $vbl, DOT1D_STP_PORT_DESIGNATED_ROOT );
517              
518 0           $stash_ptr->{dot1dStpPortDesignatedCost} =
519             idx2val( $vbl, DOT1D_STP_PORT_DESIGNATED_COST );
520              
521 0           $stash_ptr->{dot1dStpPortDesignatedBridge} =
522             idx2val( $vbl, DOT1D_STP_PORT_DESIGNATED_BRIDGE );
523              
524 0           $stash_ptr->{dot1dStpPortDesignatedPort} =
525             idx2val( $vbl, DOT1D_STP_PORT_DESIGNATED_PORT );
526              
527 0           $stash_ptr->{dot1dStpPortForwardTransitions} =
528             idx2val( $vbl, DOT1D_STP_PORT_FORWARD_TRANSITIONS );
529              
530 0           $session->{$prefix}{__initialized}++;
531             }
532              
533             =head2 B<< _unpack_bridge_id($bridgeId) >>
534              
535             Split a bridge id in priority and MAC address. Returns a list of (bridgePrio, bridgeMac).
536              
537             =cut
538              
539             sub _unpack_bridge_id {
540 0     0     my $bridgeId = shift;
541 0 0         return unless $bridgeId;
542              
543             # convert to untranslated OCTET_STRING in case it's
544             # already translated by Net::SNMP
545 0           $bridgeId = hex2octet($bridgeId);
546              
547             # the bridgeId struct is the concatenation of:
548             # dot1dStpPriority and dot1dStpBridgeMAC
549             #
550             # unpack the struct
551 0           my ( $bridgePrio, $bridgeMac ) = unpack 'nH*', $bridgeId;
552              
553             # convert to a normalized adress format
554 0           $bridgeMac = normalize_mac($bridgeMac);
555              
556 0           return ( $bridgePrio, $bridgeMac );
557             }
558              
559             =head2 B<< _unpack_bridge_port_id($bridgePortId) >>
560              
561             Split a bridge port id in priority and bridge port number. Returns a list of (portPrio, portNumber).
562              
563             =cut
564              
565             sub _unpack_bridge_port_id {
566 0     0     my $portId = shift;
567 0 0         return unless $portId;
568              
569             # convert to untranslated OCTET_STRING in case it's
570             # already translated by Net::SNMP
571 0           $portId = hex2octet($portId);
572              
573             # the portId is the concatenation of:
574             # portPriority(4bit) and dot1dBasePort(12bit)
575             #
576 0           my $portPrio = ( unpack 'n', $portId ) >> 12;
577 0           my $dot1dBasePort = ( unpack 'n', $portId ) & 0x0FFF;
578              
579             # priority <0-15> (default: 8 ) - The range of 0-240 is
580             # divided into 16 steps. These steps are numbered from
581             # 0 to 15. It is multiplied by 16 to calculate the
582             # priority value used by the STP protocol.
583              
584 0           $portPrio *= 16;
585              
586 0           return ( $portPrio, $dot1dBasePort );
587             }
588              
589             =head1 SEE ALSO
590              
591             L<< Net::SNMP::Mixin::Dot1dBase >>
592              
593             =head1 REQUIREMENTS
594              
595             L<< Net::SNMP >>, L<< Net::SNMP::Mixin >>
596              
597             =head1 BUGS, PATCHES & FIXES
598              
599             There are no known bugs at the time of this release. However, if you spot a bug or are experiencing difficulties that are not explained within the POD documentation, please submit a bug to the RT system (see link below). However, it would help greatly if you are able to pinpoint problems or even supply a patch.
600              
601             Fixes are dependant upon their severity and my availablity. Should a fix not be forthcoming, please feel free to (politely) remind me by sending an email to gaissmai@cpan.org .
602              
603             RT: http://rt.cpan.org/Public/Dist/Display.html?Name=Net-SNMP-Mixin-Dot1dStp
604              
605             =head1 AUTHOR
606              
607             Karl Gaissmaier
608              
609             =head1 COPYRIGHT & LICENSE
610              
611             Copyright 2008 Karl Gaissmaier, all rights reserved.
612              
613             This program is free software; you can redistribute it and/or modify it
614             under the same terms as Perl itself.
615              
616             =cut
617              
618             unless ( caller() ) {
619             print "$prefix compiles and initializes successful.\n";
620             }
621              
622             1;
623              
624             # vim: sw=2