File Coverage

blib/lib/Net/SNMP/Mixin/IfInfo.pm
Criterion Covered Total %
statement 59 82 71.9
branch 18 32 56.2
condition 3 6 50.0
subroutine 14 14 100.0
pod 1 1 100.0
total 95 135 70.3


line stmt bran cond sub pod time code
1             package Net::SNMP::Mixin::IfInfo;
2              
3 4     4   243081 use strict;
  4         6  
  4         98  
4 4     4   16 use warnings;
  4         5  
  4         130  
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   14 use Carp ();
  4         9  
  4         75  
17 4     4   437 use Net::SNMP::Mixin::Util qw/idx2val push_error get_init_slot/;
  4         57364  
  4         33  
18              
19             #
20             # this module export config
21             #
22             my @mixin_methods;
23              
24             BEGIN {
25 4     4   1270 @mixin_methods = ( qw/ get_if_entries /);
26             }
27              
28 4         38 use Sub::Exporter -setup => {
29             exports => [@mixin_methods],
30             groups => { default => [@mixin_methods], },
31 4     4   18 };
  4         5  
32              
33             #
34             # SNMP oid constants used in this module
35             #
36             use constant {
37 4         880 IF_DESCR => '1.3.6.1.2.1.2.2.1.2',
38             IF_TYPE => '1.3.6.1.2.1.2.2.1.3',
39             IF_ADMIN_STATUS => '1.3.6.1.2.1.2.2.1.7',
40             IF_OPER_STATUS => '1.3.6.1.2.1.2.2.1.8',
41             IF_X_NAME => '1.3.6.1.2.1.31.1.1.1.1',
42             IF_X_ALIAS => '1.3.6.1.2.1.31.1.1.1.18',
43 4     4   1139 };
  4         5  
44              
45             =head1 NAME
46              
47             Net::SNMP::Mixin::IfInfo - mixin class for interface related infos
48              
49             =head1 VERSION
50              
51             Version 0.07
52              
53             =cut
54              
55             our $VERSION = '0.07';
56              
57             =head1 SYNOPSIS
58              
59             use Net::SNMP;
60             use Net::SNMP::Mixin;
61              
62             my $session = Net::SNMP->session( -hostname => 'foo.bar.com' );
63              
64             $session->mixer('Net::SNMP::Mixin::IfInfo');
65             $session->init_mixins;
66             snmp_dispatcher();
67             $session->init_ok();
68             die $session->errors if $session->errors;
69              
70             my $if_entries = $session->get_if_entries;
71             foreach my $if_index ( sort { $a <=> $b } keys %$if_entries ) {
72             my $ifAdminStatus = $if_entries->{$if_index}->{ifAdminStatus} || 0;
73             my $ifOperStatus = $if_entries->{$if_index}->{ifOperStatus} || 0;
74             my $ifType = $if_entries->{$if_index}->{ifType} || 0;
75             my $ifName = $if_entries->{$if_index}->{ifName} || '';
76             my $ifDescr = $if_entries->{$if_index}->{ifDescr} || '';
77             my $ifAlias = $if_entries->{$if_index}->{ifAlias} || '';
78              
79             printf "%5d %1d/%1d %-10.10s %-25.25s %-26.26s\n",
80             $if_index, $ifAdminStatus, $ifOperStatus,
81             $ifName, $ifDescr, $ifAlias;
82             }
83              
84             =head1 DESCRIPTION
85              
86             A mixin class for basic interface related infos from the ifTable and ifXTable.
87              
88             This mixin supports the quasi static information from both tables together in one hash, see below.
89              
90             =head1 MIXIN METHODS
91              
92             =head2 B<< OBJ->get_if_entries >>
93              
94             Returns parts ot the ifTable and ifXTable as a hash reference. The key is the common ifIndex into the ifTable and ifXtable:
95              
96             {
97             INTEGER => { # ifIndex as key
98              
99             ifName => DisplayString, # an ifXTable entry
100             ifAlias => DisplayString, # an ifXTable entry
101              
102             ifDescr => DisplayString, # an ifTable entry
103             ifType => IANAifType, # an ifTable entry
104             ifAdminStatus => INTEGER, # an ifTable entry
105             ifOperStatus => INTEGER, # an ifTable entry
106             }
107              
108             ... ,
109             }
110              
111             =cut
112              
113             sub get_if_entries {
114 1     1 1 19532 my $session = shift;
115 1         5 my $agent = $session->hostname;
116              
117 1 50       6 Carp::croak "$agent: '$prefix' not initialized,"
118             unless $session->init_ok($prefix);
119              
120             # stash for return values
121 0         0 my $result = {};
122              
123             # the MIB tables are stored in {column}{row}{value} order
124             # but we return {row}{column}{value}
125             #
126             # grab all rows from one random choosen column
127 0         0 my @rows = keys %{ $session->{$prefix}{ifInfo}{ifDescr} };
  0         0  
128              
129 0         0 foreach my $row (@rows) {
130              
131             # loop over all columns
132 0         0 foreach my $column ( keys %{ $session->{$prefix}{ifInfo} } ) {
  0         0  
133              
134             # rebuild in reverse order: result(row,column) = stash(column,row)
135             # side effect: make a shallow copy for shallow values
136              
137             $result->{$row}{$column} =
138 0         0 $session->{$prefix}{ifInfo}{$column}{$row};
139             }
140              
141             }
142              
143 0         0 return $result;
144              
145             }
146              
147             =head1 INITIALIZATION
148              
149             =head2 B<< OBJ->_init($reload) >>
150              
151             Fetch basic interface related snmp values from the host. Don't call this method direct!
152              
153             =cut
154              
155             #
156             # due to the asynchron nature, we don't know what init job is really the last, we decrement
157             # the value after each callback
158             #
159 4     4   15 use constant THIS_INIT_JOBS => 2;
  4         5  
  4         2126  
160              
161             sub _init {
162 4     4   7208 my ( $session, $reload ) = @_;
163 4         11 my $agent = $session->hostname;
164              
165             die "$agent: $prefix already initialized and reload not forced.\n"
166             if exists get_init_slot($session)->{$prefix}
167 4 50 66     20 && get_init_slot($session)->{$prefix} == 0
      33        
168             && not $reload;
169              
170             # set number of async init jobs for proper initialization
171 4         88 get_init_slot($session)->{$prefix} = THIS_INIT_JOBS;
172              
173             # populate the object with needed mib values
174             #
175             # map between ifIndexes -> ifDescr, ...
176 4         29 _fetch_if_table_entries($session);
177 4 100       32 return if $session->error;
178              
179             # map between ifIndexes -> ifAlias, ...
180 2         13 _fetch_if_x_table_entries($session);
181 2 50       12 return if $session->error;
182              
183 2         16 return 1;
184             }
185              
186             =head1 PRIVATE METHODS
187              
188             Only for developers or maintainers.
189              
190             =head2 B<< _fetch_if_table_entries($session) >>
191              
192             Get some MIB values from the ifTable needed by all other modules.
193              
194             =cut
195              
196             sub _fetch_if_table_entries {
197 4     4   5 my $session = shift;
198 4         4 my $result;
199              
200             # fetch all some entries from ifTable
201 4 100       33 $result = $session->get_entries(
202             -columns => [
203             IF_DESCR, IF_TYPE, IF_ADMIN_STATUS, IF_OPER_STATUS,
204             # IF_X_NAME, IF_X_ALIAS,
205             ],
206              
207             # define callback if in nonblocking mode
208             $session->nonblocking ? ( -callback => \&_if_table_entries_cb ) : (),
209             );
210              
211 4 100       2008401 unless (defined $result) {
212             # Net::SNMP looses sometimes error messages in nonblocking
213             # mode, so we save them in an extra buffer
214 2         11 my $err_msg = $session->error;
215 2 50       24 push_error($session, "$prefix: $err_msg") if $err_msg;
216 2         61 return;
217             }
218              
219             # in nonblocking mode the callback will be called asynchronously
220 2 50       8 return 1 if $session->nonblocking;
221              
222             # ok we are in synchronous mode, call the result mangling function
223             # by hand
224 0         0 _if_table_entries_cb($session);
225              
226             }
227              
228             =head2 B<< _if_table_entries_cb($session) >>
229              
230             The callback for _fetch_if_table_entries
231              
232             =cut
233              
234             sub _if_table_entries_cb {
235 2     2   2003520 my $session = shift;
236 2         8 my $vbl = $session->var_bind_list;
237              
238 2 50       26 unless (defined $vbl) {
239             # Net::SNMP looses sometimes error messages in nonblocking
240             # mode, so we save them in an extra buffer
241 2         10 my $err_msg = $session->error;
242 2 50       34 push_error($session, "$prefix: $err_msg") if $err_msg;
243 2         61 return;
244             }
245              
246             # mangle result table to get plain idx->value
247 0         0 $session->{$prefix}{ifInfo}{ifDescr} = idx2val( $vbl, IF_DESCR );
248              
249 0         0 $session->{$prefix}{ifInfo}{ifType} = idx2val( $vbl, IF_TYPE );
250              
251             $session->{$prefix}{ifInfo}{ifAdminStatus} =
252 0         0 idx2val( $vbl, IF_ADMIN_STATUS );
253              
254             $session->{$prefix}{ifInfo}{ifOperStatus} =
255 0         0 idx2val( $vbl, IF_OPER_STATUS );
256              
257             # this init job is finished
258 0         0 get_init_slot($session)->{$prefix}--;
259              
260 0         0 return 1;
261             }
262              
263             =head2 B<< _fetch_if_x_table_entries($session) >>
264              
265             Get some MIB values from the ifXTable needed by all other modules.
266              
267             =cut
268              
269             sub _fetch_if_x_table_entries {
270 2     2   4 my $session = shift;
271 2         2 my $result;
272              
273             # fetch all some entries from ifXTable
274 2 50       13 $result = $session->get_entries(
275             -columns => [ IF_X_NAME, IF_X_ALIAS, ],
276              
277             # define callback if in nonblocking mode
278             $session->nonblocking ? ( -callback => \&_if_x_table_entries_cb ) : (),
279             );
280              
281 2 50       1544 unless (defined $result) {
282             # Net::SNMP looses sometimes error messages in nonblocking
283             # mode, so we save them in an extra buffer
284 0         0 my $err_msg = $session->error;
285 0 0       0 push_error($session, "$prefix: $err_msg") if $err_msg;
286 0         0 return;
287             }
288              
289             # in nonblocking mode the callback will be called asynchronously
290 2 50       6 return 1 if $session->nonblocking;
291              
292             # ok we are in synchronous mode, call the result mangling function
293             # by hand
294 0         0 _if_x_table_entries_cb($session);
295              
296             }
297              
298             =head2 B<< _if_x_table_entries_cb($session) >>
299              
300             The callback for _fetch_if_x_table_entries
301              
302             =cut
303              
304             sub _if_x_table_entries_cb {
305 2     2   669 my $session = shift;
306 2         18 my $vbl = $session->var_bind_list;
307              
308 2 50       22 unless (defined $vbl) {
309             # Net::SNMP looses sometimes error messages in nonblocking
310             # mode, so we save them in an extra buffer
311 2         39 my $err_msg = $session->error;
312 2 50       22 push_error($session, "$prefix: $err_msg") if $err_msg;
313 2         47 return;
314             }
315              
316             # mangle result table to get plain idx->value
317              
318 0           $session->{$prefix}{ifInfo}{ifName} = idx2val( $vbl, IF_X_NAME );
319              
320 0           $session->{$prefix}{ifInfo}{ifAlias} = idx2val( $vbl, IF_X_ALIAS );
321              
322             # this init job is finished
323 0           get_init_slot($session)->{$prefix}--;
324              
325 0           return 1;
326             }
327              
328             =head1 SEE ALSO
329              
330             L<< Net::SNMP::Mixin::Dot1dBase >> for a mapping between ifIndexes and dot1dBasePorts.
331              
332             =head1 REQUIREMENTS
333              
334             L<< Net::SNMP >>, L<< Net::SNMP::Mixin >>
335              
336             =head1 BUGS, PATCHES & FIXES
337              
338             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.
339              
340             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 .
341              
342             RT: http://rt.cpan.org/Public/Dist/Display.html?Name=Net-SNMP-Mixin-IfInfo
343              
344             =head1 AUTHOR
345              
346             Karl Gaissmaier
347              
348             =head1 COPYRIGHT & LICENSE
349              
350             Copyright 2008-2016 Karl Gaissmaier, all rights reserved.
351              
352             This program is free software; you can redistribute it and/or modify it
353             under the same terms as Perl itself.
354              
355             =cut
356              
357             unless ( caller() ) {
358             print __PACKAGE__ . " compiles and initializes successful.\n";
359             }
360              
361             1;
362              
363             # vim: sw=2