File Coverage

blib/lib/Net/SNMP/Mixin/NXOSDot1dBase.pm
Criterion Covered Total %
statement 56 81 69.1
branch 17 28 60.7
condition 3 6 50.0
subroutine 16 16 100.0
pod 3 3 100.0
total 95 134 70.9


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