File Coverage

blib/lib/Net/SNMP/Mixin/Dot1dBase.pm
Criterion Covered Total %
statement 56 80 70.0
branch 17 28 60.7
condition 3 6 50.0
subroutine 16 16 100.0
pod 3 3 100.0
total 95 133 71.4


line stmt bran cond sub pod time code
1             package Net::SNMP::Mixin::Dot1dBase;
2              
3 4     4   219807 use strict;
  4         6  
  4         97  
4 4     4   13 use warnings;
  4         4  
  4         125  
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   13 use Carp ();
  4         16  
  4         61  
17 4     4   474 use Net::SNMP::Mixin::Util qw/idx2val normalize_mac get_init_slot/;
  4         60489  
  4         28  
18              
19             #
20             # this module export config
21             #
22             my @mixin_methods;
23              
24             BEGIN {
25 4     4   1237 @mixin_methods = (
26             qw/
27             get_dot1d_base_group
28             map_bridge_ports2if_indexes
29             map_if_indexes2bridge_ports
30             /
31             );
32             }
33              
34 4         29 use Sub::Exporter -setup => {
35             exports => [@mixin_methods],
36             groups => { default => [@mixin_methods], },
37 4     4   20 };
  4         5  
38              
39             #
40             # SNMP oid constants used in this module
41             #
42             use constant {
43 4         1392 DOT1D_BASE_BRIDGE_ADDRESS => '1.3.6.1.2.1.17.1.1.0',
44             DOT1D_BASE_NUM_PORTS => '1.3.6.1.2.1.17.1.2.0',
45             DOT1D_BASE_TYPE => '1.3.6.1.2.1.17.1.3.0',
46              
47             DOT1D_BASE_PORT_IF_INDEX => '1.3.6.1.2.1.17.1.4.1.2',
48 4     4   1167 };
  4         4  
49              
50             =head1 NAME
51              
52             Net::SNMP::Mixin::Dot1dBase - mixin class for the switch dot1d base values
53              
54             =head1 VERSION
55              
56             Version 0.06
57              
58             =cut
59              
60             our $VERSION = '0.06';
61              
62             =head1 SYNOPSIS
63              
64             A Net::SNMP mixin class for Dot1d base info.
65              
66             use Net::SNMP;
67             use Net::SNMP::Mixin;
68              
69             # class based mixin
70             Net::SNMP->mixer('Net::SNMP::Mixin::Dot1dBase');
71              
72             # ...
73              
74             my $session = Net::SNMP->session( -hostname => 'foo.bar.com' );
75              
76             $session->mixer('Net::SNMP::Mixin::Dot1dBase');
77             $session->init_mixins;
78             snmp_dispatcher() if $session->nonblocking;
79             $session->init_ok;
80             die $session->errors if $session->errors;
81              
82             my $base_group = $session->get_dot1d_base_group;
83              
84             printf "BridgeAddr: %s NumPorts: %d Type: %d\n",
85             $base_group->{dot1dBaseBridgeAddress},
86             $base_group->{dot1dBaseNumPorts},
87             $base_group->{dot1dBaseType};
88              
89             my $map = $session->map_bridge_ports2if_indexes;
90              
91             foreach my $bridge_port ( sort {$a <=> $b} keys %$map ) {
92             my $if_index = $map->{$bridge_port};
93             printf "bridgePort: %4d -> ifIndex: %4\n", $bridge_port, $if_index;
94             }
95              
96              
97             =head1 DESCRIPTION
98              
99             A mixin class for basic switch information from the BRIDGE-MIB.
100              
101             Besides the bridge address and the number of bridge ports, it's primary use is the mapping between dot1dBasePorts and ifIndexes.
102              
103             =head1 MIXIN METHODS
104              
105             =head2 B<< OBJ->get_dot1d_base_group() >>
106              
107             Returns the dot1dBase group as a hash reference:
108              
109             {
110             dot1dBaseBridgeAddress => MacAddress,
111             dot1dBaseNumPorts => INTEGER,
112             dot1dBaseType => INTEGER,
113             }
114              
115             =cut
116              
117             sub get_dot1d_base_group {
118 1     1 1 20413 my $session = shift;
119 1         5 my $agent = $session->hostname;
120              
121 1 50       6 Carp::croak "$agent: '$prefix' not initialized,"
122             unless $session->init_ok($prefix);
123              
124 0         0 my $result = { %{ $session->{$prefix}{dot1dBase} } };
  0         0  
125              
126             # normalize the MAC address
127             $result->{dot1dBaseBridgeAddress} =
128 0         0 normalize_mac( $result->{dot1dBaseBridgeAddress} );
129              
130 0         0 return $result;
131             }
132              
133             =head2 B<< OBJ->map_bridge_ports2if_indexes() >>
134              
135             Returns a reference to a hash with the following entries:
136              
137             {
138             # INTEGER INTEGER
139             dot1dBasePort => dot1dBasePortIfIndex,
140             }
141              
142             =cut
143              
144             sub map_bridge_ports2if_indexes {
145 1     1 1 379 my ( $session, ) = @_;
146 1         4 my $agent = $session->hostname;
147              
148 1 50       4 Carp::croak "$agent: '$prefix' not initialized,"
149             unless $session->init_ok($prefix);
150              
151             # datastructure:
152             # $session->{$prefix}{dot1dBasePortIfIndex}{$dot1d_base_port} = ifIndex
153             #
154              
155 0         0 my $result = {};
156              
157 0         0 while ( my ( $bridge_port, $if_index ) =
158 0         0 each %{ $session->{$prefix}{dot1dBasePortIfIndex} } )
159             {
160 0         0 $result->{$bridge_port} = $if_index;
161             }
162              
163 0         0 return $result;
164             }
165              
166             =head2 B<< OBJ->map_if_indexes2bridge_ports() >>
167              
168             Returns a reference to a hash with the following entries:
169              
170             {
171             # INTEGER INTEGER
172             dot1dBasePortIfIndex => dot1dBasePort ,
173             }
174              
175             =cut
176              
177             sub map_if_indexes2bridge_ports {
178 1     1 1 422 my ( $session, ) = @_;
179 1         4 my $agent = $session->hostname;
180              
181 1 50       5 Carp::croak "$agent: '$prefix' not initialized,"
182             unless $session->init_ok($prefix);
183              
184             # datastructure:
185             # $session->{$prefix}{dot1dBasePortIfIndex}{$dot1d_base_port} = ifIndex
186             #
187              
188 0         0 my $result = {};
189              
190 0         0 while ( my ( $bridge_port, $if_index ) =
191 0         0 each %{ $session->{$prefix}{dot1dBasePortIfIndex} } )
192             {
193 0         0 $result->{$if_index} = $bridge_port;
194             }
195              
196 0         0 return $result;
197             }
198              
199             =head1 INITIALIZATION
200              
201             =cut
202              
203             =head2 B<< OBJ->_init($reload) >>
204              
205             Fetch the dot1d base related snmp values from the host. Don't call this method direct!
206              
207             =cut
208              
209             #
210             # due to the asynchron nature, we don't know what init job is really the last, we decrement
211             # the value after each callback
212             #
213 4     4   17 use constant THIS_INIT_JOBS => 2;
  4         62  
  4         1748  
214              
215             sub _init {
216 4     4   6805 my ( $session, $reload ) = @_;
217 4         9 my $agent = $session->hostname;
218              
219             die "$agent: $prefix already initialized and reload not forced.\n"
220             if exists get_init_slot($session)->{$prefix}
221 4 50 66     20 && get_init_slot($session)->{$prefix} == 0
      33        
222             && not $reload;
223              
224             # set number of async init jobs for proper initialization
225 4         77 get_init_slot($session)->{$prefix} = THIS_INIT_JOBS;
226              
227             # initialize the object for dot1dbase infos
228 4         25 _fetch_dot1d_base($session);
229 4 100       21 return if $session->error;
230              
231             # LLDP, Dot1Q, STP, LLDP, ... tables are indexed
232             # by dot1dbaseports and not ifIndexes
233             # table to map between dot1dBasePort <-> ifIndex
234              
235 2         11 _fetch_dot1d_base_ports($session);
236 2 50       9 return if $session->error;
237              
238 2         9 return 1;
239             }
240              
241             =head1 PRIVATE METHODS
242              
243             Only for developers or maintainers.
244              
245             =head2 B<< _fetch_dot1d_base($session) >>
246              
247             Fetch values from the dot1dBase group once during object initialization.
248              
249             =cut
250              
251             sub _fetch_dot1d_base {
252 4     4   4 my $session = shift;
253 4         4 my $result;
254              
255             # fetch the dot1dBase group
256 4 100       22 $result = $session->get_request(
257             -varbindlist => [
258              
259             DOT1D_BASE_BRIDGE_ADDRESS,
260             DOT1D_BASE_NUM_PORTS,
261             DOT1D_BASE_TYPE,
262             ],
263              
264             # define callback if in nonblocking mode
265             $session->nonblocking ? ( -callback => \&_dot1d_base_cb ) : (),
266             );
267              
268 4 100       2007063 return unless defined $result;
269 2 50       7 return 1 if $session->nonblocking;
270              
271             # call the callback function in blocking mode by hand
272 0         0 _dot1d_base_cb($session);
273              
274             }
275              
276             =head2 B<< _dot1d_base_cb($session) >>
277              
278             The callback for _fetch_dot1d_base.
279              
280             =cut
281              
282             sub _dot1d_base_cb {
283 2     2   2003563 my $session = shift;
284 2         11 my $vbl = $session->var_bind_list;
285              
286 2 50       29 return unless defined $vbl;
287              
288             $session->{$prefix}{dot1dBase}{dot1dBaseBridgeAddress} =
289 0         0 $vbl->{ DOT1D_BASE_BRIDGE_ADDRESS() };
290              
291             $session->{$prefix}{dot1dBase}{dot1dBaseNumPorts} =
292 0         0 $vbl->{ DOT1D_BASE_NUM_PORTS() };
293              
294 0         0 $session->{$prefix}{dot1dBase}{dot1dBaseType} = $vbl->{ DOT1D_BASE_TYPE() };
295              
296             # this init job is finished
297 0         0 get_init_slot($session)->{$prefix}--;
298              
299 0         0 return 1;
300             }
301              
302             =head2 B<< _fetch_dot1d_base_ports($session) >>
303              
304             Populate the object with the dot1dBasePorts.
305              
306             =cut
307              
308             sub _fetch_dot1d_base_ports {
309 2     2   2 my $session = shift;
310 2         3 my $result;
311              
312             # fetch the dot1dBasePorts, in blocking or nonblocking mode
313 2 50       10 $result = $session->get_entries(
314             -columns => [ DOT1D_BASE_PORT_IF_INDEX, ],
315              
316             # define callback if in nonblocking mode
317             $session->nonblocking ? ( -callback => \&_dot1d_base_ports_cb ) : (),
318             );
319              
320 2 50       1144 return unless defined $result;
321 2 50       7 return 1 if $session->nonblocking;
322              
323             # call the callback funktion in blocking mode by hand
324 0         0 _dot1d_base_ports_cb($session);
325              
326             }
327              
328             =head2 B<< _dot1d_base_ports_cb($session) >>
329              
330             The callback for _fetch_dot1d_base_ports.
331              
332             =cut
333              
334             sub _dot1d_base_ports_cb {
335 2     2   591 my $session = shift;
336 2         5 my $vbl = $session->var_bind_list;
337              
338 2 50       14 return unless defined $vbl;
339              
340             # mangle result table to get plain idx->value
341              
342             $session->{$prefix}{dot1dBasePortIfIndex} =
343 0           idx2val( $vbl, DOT1D_BASE_PORT_IF_INDEX );
344              
345             # this init job is finished
346 0           get_init_slot($session)->{$prefix}--;
347              
348 0           return 1;
349             }
350              
351             =head1 REQUIREMENTS
352              
353             L<< Net::SNMP >>, L<< Net::SNMP::Mixin >>
354              
355             =head1 BUGS, PATCHES & FIXES
356              
357             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.
358              
359             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 .
360              
361             RT: http://rt.cpan.org/Public/Dist/Display.html?Name=Net-SNMP-Mixin-Dot1dBase
362              
363             =head1 AUTHOR
364              
365             Karl Gaissmaier
366              
367             =head1 COPYRIGHT & LICENSE
368              
369             Copyright 2008-2016 Karl Gaissmaier, all rights reserved.
370              
371             This program is free software; you can redistribute it and/or modify it
372             under the same terms as Perl itself.
373              
374             =cut
375              
376             unless ( caller() ) {
377             print "$prefix compiles and initializes successful.\n";
378             }
379              
380             1;
381              
382             # vim: sw=2