File Coverage

blib/lib/Net/SNMP/Mixin/Dot1abLldp.pm
Criterion Covered Total %
statement 75 135 55.5
branch 25 54 46.3
condition 3 12 25.0
subroutine 17 18 94.4
pod 3 3 100.0
total 123 222 55.4


line stmt bran cond sub pod time code
1             package Net::SNMP::Mixin::Dot1abLldp;
2              
3 4     4   298874 use strict;
  4         9  
  4         101  
4 4     4   19 use warnings;
  4         16  
  4         135  
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   21 use Carp ();
  4         8  
  4         99  
17 4     4   436 use Net::SNMP::Mixin::Util qw/normalize_mac idx2val push_error get_init_slot/;
  4         73204  
  4         30  
18              
19             #
20             # this module export config
21             #
22             my @mixin_methods;
23              
24             BEGIN {
25 4     4   1805 @mixin_methods = (
26             qw/
27             get_lldp_local_system_data
28             get_lldp_loc_port_table
29             get_lldp_rem_table
30             /
31             );
32             }
33              
34 4         62 use Sub::Exporter -setup => {
35             exports => [@mixin_methods],
36             groups => { default => [@mixin_methods], },
37 4     4   23 };
  4         9  
38              
39             #
40             # SNMP oid constants used in this module
41             #
42             # from lldpMIB
43             use constant {
44 4         2724 LLDP_LOCAL_SYSTEM_DATA => '1.0.8802.1.1.2.1.3',
45             LLDP_LOCAL_CASSIS_ID_SUBTYPE => '1.0.8802.1.1.2.1.3.1.0',
46             LLDP_LOCAL_CASSIS_ID => '1.0.8802.1.1.2.1.3.2.0',
47             LLDP_LOCAL_SYS_NAME => '1.0.8802.1.1.2.1.3.3.0',
48             LLDP_LOCAL_SYS_DESC => '1.0.8802.1.1.2.1.3.4.0',
49             LLDP_LOCAL_SYS_CAPA_SUP => '1.0.8802.1.1.2.1.3.5.0',
50             LLDP_LOCAL_SYS_CAPA_ENA => '1.0.8802.1.1.2.1.3.6.0',
51              
52             LLDP_LOC_PORT_TABLE => '1.0.8802.1.1.2.1.3.7',
53             LLDP_LOC_PORT_NUM => '1.0.8802.1.1.2.1.3.7.1.1',
54             LLDP_LOC_PORT_ID_SUBTYPE => '1.0.8802.1.1.2.1.3.7.1.2',
55             LLDP_LOC_PORT_ID => '1.0.8802.1.1.2.1.3.7.1.3',
56             LLDP_LOC_PORT_DESC => '1.0.8802.1.1.2.1.3.7.1.4',
57              
58             LLDP_REM_TABLE => '1.0.8802.1.1.2.1.4.1',
59             LLDP_REM_LOCAL_PORT_NUM => '1.0.8802.1.1.2.1.4.1.1.2',
60             LLDP_REM_CASSIS_ID_SUBTYPE => '1.0.8802.1.1.2.1.4.1.1.4',
61             LLDP_REM_CASSIS_ID => '1.0.8802.1.1.2.1.4.1.1.5',
62             LLDP_REM_PORT_ID_SUBTYPE => '1.0.8802.1.1.2.1.4.1.1.6',
63             LLDP_REM_PORT_ID => '1.0.8802.1.1.2.1.4.1.1.7',
64             LLDP_REM_PORT_DESC => '1.0.8802.1.1.2.1.4.1.1.8',
65             LLDP_REM_SYS_NAME => '1.0.8802.1.1.2.1.4.1.1.9',
66             LLDP_REM_SYS_DESC => '1.0.8802.1.1.2.1.4.1.1.10',
67             LLDP_REM_SYS_CAPA_SUP => '1.0.8802.1.1.2.1.4.1.1.11',
68             LLDP_REM_SYS_CAPA_ENA => '1.0.8802.1.1.2.1.4.1.1.12',
69 4     4   1848 };
  4         10  
70              
71             =head1 NAME
72              
73             Net::SNMP::Mixin::Dot1abLldp - mixin class for the Link Layer Discovery Protocol
74              
75             =cut
76              
77             our $VERSION = '0.15';
78              
79             =head1 SYNOPSIS
80              
81             A Net::SNMP mixin class for LLDP (Link Layer Discovery Protocol) based info.
82              
83             use Net::SNMP;
84             use Net::SNMP::Mixin;
85              
86             #...
87              
88             my $session = Net::SNMP->session( -hostname => 'foo.bar.com' );
89              
90             $session->mixer('Net::SNMP::Mixin::Dot1abLldp');
91             $session->init_mixins;
92             snmp_dispatcher();
93             $session->init_ok();
94             die $session->errors if $session->errors;
95              
96             printf "Local ChassisID: %s\n",
97             $session->get_lldp_local_system_data->{lldpLocChassisId};
98              
99             $lldp_loc_port_tbl = $session->get_lldp_loc_port_table;
100             $lldp_rem_tbl = $session->get_lldp_rem_table;
101              
102             foreach $lport ( keys %$lldp_rem_tbl ) {
103             foreach $idx ( keys %{ $lldp_rem_tbl->{$lport} } ) {
104             my $lldpRemSysName = $lldp_rem_tbl->{$lport}{$idx}{lldpRemSysName};
105             my $lldpRemPortId = $lldp_rem_tbl->{$lport}{$idx}{lldpRemPortId};
106             my $lldpRemPortDesc = $lldp_rem_tbl->{$lport}{$idx}{lldpRemPortDesc};
107             my $lldpRemChassisId = $lldp_rem_tbl->{$lport}{$idx}{lldpRemChassisId};
108             my $ldesc = $lldp_loc_port_tbl->{$lport}{lldpLocPortDesc};
109              
110             printf "$lport:$ldesc => $lldpRemSysName:$lldpRemPortId:$lldpRemPortDesc:$lldpRemChassisId\n";
111             }
112             }
113              
114             =cut
115              
116             =head1 DESCRIPTION
117              
118             With this mixin it's simple to explore the Layer-2 topologie of the network.
119              
120             The LLDP (Link Layer Discovery Protocol) is an IEEE (Draft?) standard for vendor-independent Layer-2 discovery, similar to the proprietary CDP (Cisco Discovery Protocol) from Cisco. It's defined in the IEEE 802.1AB documents, therefore the name of this module.
121              
122             This mixin reads data from the B<< lldpLocalSystemData >>, B<< lldpLocPortTable >> and the B<< lldpRemTable >> out of the LLDP-MIB. At least these values are in the mandatory set of the LLDP-MIB.
123              
124             =head1 MIXIN METHODS
125              
126             =head2 B<< OBJ->get_lldp_local_system_data() >>
127              
128             Returns the LLDP lldpLocalSystemData group as a hash reference:
129              
130             {
131             lldpLocChassisIdSubtype => Integer,
132             lldpLocChassisId => OCTET_STRING,
133             lldpLocSysName => OCTET_STRING,
134             lldpLocSysDesc => OCTET_STRING,
135             lldpLocSysCapSupported => BITS,
136             lldpLocSysCapEnabled => BITS,
137             }
138              
139             =cut
140              
141             sub get_lldp_local_system_data {
142 1     1 1 30186 my $session = shift;
143 1         7 my $agent = $session->hostname;
144              
145 1 50       14 Carp::croak "$agent: '$prefix' not initialized,"
146             unless $session->init_ok($prefix);
147              
148             # just a shallow copy for shallow values
149 0         0 my $result = { %{ $session->{$prefix}{locSysData} } };
  0         0  
150              
151             # if the chassisIdSubtype has the enumeration 'macAddress(4)'
152             # we normalize the MacAddress
153             $result->{lldpLocChassisId} = normalize_mac( $result->{lldpLocChassisId} )
154 0 0 0     0 if defined $result->{lldpLocChassisIdSubtype} && $result->{lldpLocChassisIdSubtype} == 4;
155              
156 0         0 return $result;
157             }
158              
159             =head2 B<< OBJ->get_lldp_loc_port_table() >>
160              
161             Returns the LLDP lldp_loc_port_table as a hash reference. The table is indexed by the LLDP local port numbers:
162              
163             {
164             lldpLocPortNum => {
165             lldpLocPortIdSubtype => INTEGER,
166             lldpLocPortId => OCTET_STRING,
167             lldpLocPortDesc => OCTET_STRING,
168             }
169             }
170              
171             The LLDP portnumber isn't necessarily the ifIndex of the switch. See the TEXTUAL-CONVENTION from the LLDP-MIB:
172              
173             "A port number has no mandatory relationship to an
174             InterfaceIndex object (of the interfaces MIB, IETF RFC 2863).
175             If the LLDP agent is a IEEE 802.1D, IEEE 802.1Q bridge, the
176             LldpPortNumber will have the same value as the dot1dBasePort
177             object (defined in IETF RFC 1493) associated corresponding
178             bridge port. If the system hosting LLDP agent is not an
179             IEEE 802.1D or an IEEE 802.1Q bridge, the LldpPortNumber
180             will have the same value as the corresponding interface's
181             InterfaceIndex object."
182              
183             See also the L<< Net::SNMP::Mixin::Dot1dBase >> for a mixin to get the mapping between the ifIndexes and the dot1dBasePorts if needed.
184              
185             =cut
186              
187              
188             sub get_lldp_loc_port_table {
189 0     0 1 0 my $session = shift;
190 0         0 my $agent = $session->hostname;
191              
192 0 0       0 Carp::croak "$agent: '$prefix' not initialized,"
193             unless $session->init_ok($prefix);
194              
195             # stash for return values
196 0         0 my $result = {};
197              
198             #
199             # the MIB tables are stored in {column}{row}{value} order
200             # but we return {row}{column}{value}
201             #
202             # grab all rows from one choosen column
203 0         0 my @rows = keys %{ $session->{$prefix}{lldpLocPortTbl}{lldpLocPortId} };
  0         0  
204              
205 0         0 foreach my $row (@rows) {
206              
207             # loop over all columns
208 0         0 foreach my $column ( keys %{ $session->{$prefix}{lldpLocPortTbl} } ) {
  0         0  
209              
210             # rebuild in reverse order: result(row,column) = stash(column,row)
211             # side effect: make a shallow copy for shallow values
212              
213             $result->{$row}{$column} =
214 0         0 $session->{$prefix}{lldpLocPortTbl}{$column}{$row};
215             }
216              
217             }
218              
219 0         0 return $result;
220             }
221              
222             =head2 B<< OBJ->get_lldp_rem_table() >>
223              
224             Returns the LLDP lldp_rem_table as a hash reference. The table is indexed by the LLDP local port numbers on which the remote system information is received and an index for multiple neighbors on one port:
225              
226             {
227             lldpRemLocalPortNum => {
228             lldpRemIndex => {
229             lldpRemChassisIdSubtype => INTEGER,
230             lldpRemChassisId => OCTET_STRING,
231             lldpRemPortIdSubtype => INTEGER,
232             lldpRemPortId => OCTET_STRING,
233             lldpRemPortDesc => OCTET_STRING,
234             lldpRemSysName => OCTET_STRING,
235             lldpRemSysDesc => OCTET_STRING,
236             lldpRemSysCapSupported => BITS,
237             lldpRemSysCapEnabled => BITS,
238             }
239             }
240             }
241              
242             =cut
243              
244             sub get_lldp_rem_table {
245 1     1 1 1050 my $session = shift;
246 1         7 my $agent = $session->hostname;
247              
248 1 50       10 Carp::croak "$agent: '$prefix' not initialized,"
249             unless $session->init_ok($prefix);
250              
251             # stash for return values
252 0         0 my $result = {};
253              
254             # the MIB tables are stored in {column}{row}{value} order
255             # but we return {row}{column}{value}
256             #
257             # grab all rows from one random choosen column
258 0         0 my @rows = keys %{ $session->{$prefix}{lldpRemTbl}{lldpRemPortId} };
  0         0  
259              
260 0         0 foreach my $row (@rows) {
261              
262             # the rows are the concatenation of 'lldpRemLocalPortNum.lldpRemIndex'
263             # split them into separate values
264 0         0 my ( $lldpRemLocalPortNum, $lldpRemIndex ) = split /\./, $row;
265              
266             # loop over all columns
267 0         0 foreach my $column ( keys %{ $session->{$prefix}{lldpRemTbl} } ) {
  0         0  
268              
269             # rebuild in reverse order: result(row,column) = stash(column,row)
270             # side effect: make a shallow copy for shallow values
271             # side effect: entangle the row 'lldpRemLocalPortNum.lldpRemIndex'
272              
273             $result->{$lldpRemLocalPortNum}{$lldpRemIndex}{$column} =
274 0         0 $session->{$prefix}{lldpRemTbl}{$column}{$row};
275             }
276              
277             # if the chassisIdSubtype has the enumeration 'macAddress(4)'
278             # we normalize the MacAddress
279             my $chassisIdSubtype =
280 0         0 $result->{$lldpRemLocalPortNum}{$lldpRemIndex}{lldpRemChassisIdSubtype};
281              
282 0 0 0     0 if ( defined $chassisIdSubtype && $chassisIdSubtype == 4 ) {
283             $result->{$lldpRemLocalPortNum}{$lldpRemIndex}{lldpRemChassisId} =
284 0         0 normalize_mac( $result->{$lldpRemLocalPortNum}{$lldpRemIndex}{lldpRemChassisId} );
285             }
286              
287             }
288              
289 0         0 return $result;
290             }
291              
292             =head1 INITIALIZATION
293              
294             =head2 B<< OBJ->_init($reload) >>
295              
296             Fetch the LLDP related snmp values from the host. Don't call this method direct!
297              
298             =cut
299              
300             #
301             # due to the asynchron nature, we don't know what init job is really the last, we decrement
302             # the value after each callback
303             #
304 4     4   27 use constant THIS_INIT_JOBS => 3;
  4         8  
  4         3778  
305              
306             sub _init {
307 4     4   7273 my ($session, $reload) = @_;
308 4         10 my $agent = $session->hostname;
309              
310             die "$agent: $prefix already initialized and reload not forced.\n"
311             if exists get_init_slot($session)->{$prefix}
312 4 50 66     22 && get_init_slot($session)->{$prefix} == 0
      33        
313             && not $reload;
314              
315             # set number of async init jobs for proper initialization
316 4         85 get_init_slot($session)->{$prefix} = THIS_INIT_JOBS;
317              
318             # populate the object with needed mib values
319             #
320             # initialize the object for LLDP infos
321 4         36 _fetch_lldp_local_system_data($session);
322 4 100       17 return if $session->error;
323              
324 2         12 _fetch_lldp_loc_port_tbl($session);
325 2 50       10 return if $session->error;
326              
327 2         13 _fetch_lldp_rem_tbl($session);
328 2 50       10 return if $session->error;
329              
330 2         11 return 1;
331             }
332              
333             =head1 PRIVATE METHODS
334              
335             Only for developers or maintainers.
336              
337             =head2 B<< _fetch_lldp_local_system_data($session) >>
338              
339             Fetch the local system data from the lldpMIB once during object initialization.
340              
341             =cut
342              
343             sub _fetch_lldp_local_system_data {
344 4     4   9 my $session = shift;
345 4         14 my $result;
346              
347             # use get_entries instead of get_request since the
348             # result will be true in case of missing values
349             # the values are just noSuchObject
350             # with get_entries() we get error messages for free
351            
352 4 100       24 $result = $session->get_entries(
353             -columns => [ LLDP_LOCAL_SYSTEM_DATA, ],
354             -endindex => '6.0', # LLDP_LOCAL_SYS_CAPA_ENA
355              
356             # define callback if in nonblocking mode
357             $session->nonblocking ? ( -callback => \&_lldp_local_system_data_cb ) : (),
358              
359             );
360              
361 4 100       2008389 unless (defined $result) {
362 2 50       10 if (my $err_msg = $session->error) {
363 2         42 push_error($session, "$prefix: $err_msg");
364             };
365 2         66 return;
366             }
367              
368             # in nonblocking mode the callback will be called asynchronously
369 2 50       5 return 1 if $session->nonblocking;
370              
371             # ok we are in synchronous mode, call the result mangling function
372             # by hand
373 0         0 _lldp_local_system_data_cb($session);
374             }
375              
376             =head2 B<< _lldp_local_system_data_cb($session) >>
377              
378             The callback for _fetch_lldp_local_system_data.
379              
380             =cut
381              
382             sub _lldp_local_system_data_cb {
383 2     2   2003885 my $session = shift;
384 2         7 my $vbl = $session->var_bind_list;
385              
386 2 50       17 unless (defined $vbl) {
387 2 50       7 if (my $err_msg = $session->error) {
388 2         38 push_error($session, "$prefix: $err_msg");
389             };
390 2         50 return;
391             }
392              
393             $session->{$prefix}{locSysData}{lldpLocChassisIdSubtype} =
394 0         0 $vbl->{ LLDP_LOCAL_CASSIS_ID_SUBTYPE() };
395              
396             $session->{$prefix}{locSysData}{lldpLocChassisId} =
397 0         0 $vbl->{ LLDP_LOCAL_CASSIS_ID() };
398              
399             $session->{$prefix}{locSysData}{lldpLocSysName} =
400 0         0 $vbl->{ LLDP_LOCAL_SYS_NAME() };
401              
402             $session->{$prefix}{locSysData}{lldpLocSysDesc} =
403 0         0 $vbl->{ LLDP_LOCAL_SYS_DESC() };
404              
405             $session->{$prefix}{locSysData}{lldpLocSysCapSupported} =
406 0         0 $vbl->{ LLDP_LOCAL_SYS_CAPA_SUP() };
407              
408             $session->{$prefix}{locSysData}{lldpLocSysCapEnabled} =
409 0         0 $vbl->{ LLDP_LOCAL_SYS_CAPA_ENA() };
410              
411             # this init job is finished
412 0         0 get_init_slot($session)->{$prefix}--;
413              
414 0         0 return 1;
415             }
416              
417             =head2 B<< _fetch_lldp_loc_port_tbl($session) >>
418              
419             Fetch the lldpLocPortTable once during object initialization.
420              
421             =cut
422              
423             sub _fetch_lldp_loc_port_tbl {
424 2     2   6 my $session = shift;
425 2         3 my $result;
426              
427             # fetch the lldpLocPortTable
428 2 50       6 $result = $session->get_table(
429             -baseoid => LLDP_LOC_PORT_TABLE,
430              
431             # define callback if in nonblocking mode
432             $session->nonblocking ? ( -callback => \&_lldp_loc_port_tbl_cb ) : (),
433             );
434              
435 2 50       1478 unless (defined $result) {
436 0 0       0 if (my $err_msg = $session->error) {
437 0         0 push_error($session, "$prefix: $err_msg");
438             };
439 0         0 return;
440             }
441              
442             # in nonblocking mode the callback will be called asynchronously
443 2 50       9 return 1 if $session->nonblocking;
444              
445             # ok we are in synchronous mode, call the result mangling function
446             # by hand
447 0         0 _lldp_loc_port_tbl_cb($session);
448              
449             }
450              
451             =head2 B<< _lldp_loc_port_tbl_cb($session) >>
452              
453             The callback for _fetch_lldp_loc_port_tbl_cb().
454              
455             =cut
456              
457             sub _lldp_loc_port_tbl_cb {
458 2     2   640 my $session = shift;
459 2         6 my $vbl = $session->var_bind_list;
460              
461              
462 2 50       15 unless (defined $vbl) {
463 2 50       5 if (my $err_msg = $session->error) {
464 2         28 push_error($session, "$prefix: $err_msg");
465             };
466 2         38 return;
467             }
468              
469             # mangle result table to get plain idx->value
470              
471             $session->{$prefix}{lldpLocPortTbl}{lldpLocPortIdSubtype} =
472 0         0 idx2val( $vbl, LLDP_LOC_PORT_ID_SUBTYPE );
473              
474             $session->{$prefix}{lldpLocPortTbl}{lldpLocPortId} =
475 0         0 idx2val( $vbl, LLDP_LOC_PORT_ID );
476              
477             $session->{$prefix}{lldpLocPortTbl}{lldpLocPortDesc} =
478 0         0 idx2val( $vbl, LLDP_LOC_PORT_DESC );
479              
480             # this init job is finished
481 0         0 get_init_slot($session)->{$prefix}--;
482              
483 0         0 return 1;
484             }
485              
486             =head2 B<< _fetch_lldp_rem_tbl($session) >>
487              
488             Fetch the lldpRemTable once during object initialization.
489              
490             =cut
491              
492             sub _fetch_lldp_rem_tbl {
493 2     2   4 my $session = shift;
494 2         4 my $result;
495              
496             # fetch the lldpRemTable
497 2 50       5 $result = $session->get_table(
498             -baseoid => LLDP_REM_TABLE,
499              
500             # define callback if in nonblocking mode
501             $session->nonblocking ? ( -callback => \&_lldp_rem_tbl_cb ) : (),
502             );
503              
504 2 50       1469 unless (defined $result) {
505 0 0       0 if (my $err_msg = $session->error) {
506 0         0 push_error($session, "$prefix: $err_msg");
507             };
508 0         0 return;
509             }
510              
511             # in nonblocking mode the callback will be called asynchronously
512 2 50       7 return 1 if $session->nonblocking;
513              
514             # ok we are in synchronous mode, call the result mangling function
515             # by hand
516 0         0 _lldp_rem_tbl_cb($session);
517              
518             }
519              
520             =head2 B<< _lldp_rem_tbl_cb($session) >>
521              
522             The callback for _fetch_lldp_rem_tbl_cb().
523              
524             =cut
525              
526             sub _lldp_rem_tbl_cb {
527 2     2   586 my $session = shift;
528 2         7 my $vbl = $session->var_bind_list;
529              
530 2 50       14 unless (defined $vbl) {
531 2 50       6 if (my $err_msg = $session->error) {
532 2         14 push_error($session, "$prefix: $err_msg");
533             }
534 2         34 return;
535             }
536              
537             # mangle result table to get plain idx->value
538             #---------------------------------------------------------------
539             # the tableIndex is a little bit tricky, please see the LLDP-MIB
540             #---------------------------------------------------------------
541             #
542             # .1.0.8802.1.1.2.1.4.1.1.11[.0.20.1]
543             # ^ ^ ^
544             # | | |
545             # lldpRemTimeMark---/ | |
546             # | |
547             # lldpRemLocalPortNum--/ |
548             # |
549             # lldpRemIndex-----------/
550             #
551             #---------------------------------------------------------------
552             # lldpRemEntry OBJECT-TYPE
553             # SYNTAX LldpRemEntry
554             # MAX-ACCESS not-accessible
555             # STATUS current
556             # DESCRIPTION
557             # "Information about a particular physical network connection.
558             # Entries may be created and deleted in this table by the agent,
559             # if a physical topology discovery process is active."
560             # INDEX {
561             # lldpRemTimeMark,
562             # lldpRemLocalPortNum,
563             # lldpRemIndex
564             # }
565             # ::= { lldpRemTable 1 }
566             # -----------------------------------------------
567              
568             # mangle result table to get plain idx->value
569             # cut off the variable lldpRemTimeMark as pre
570             #
571             # result hashes: lldpRemLocalPortNum.lldpRemIndex => values
572             #
573              
574             $session->{$prefix}{lldpRemTbl}{lldpRemChassisIdSubtype} =
575 0           idx2val( $vbl, LLDP_REM_CASSIS_ID_SUBTYPE, 1, undef, );
576              
577             $session->{$prefix}{lldpRemTbl}{lldpRemChassisId} =
578 0           idx2val( $vbl, LLDP_REM_CASSIS_ID, 1, undef, );
579              
580             $session->{$prefix}{lldpRemTbl}{lldpRemPortIdSubtype} =
581 0           idx2val( $vbl, LLDP_REM_PORT_ID_SUBTYPE, 1, undef, );
582              
583             $session->{$prefix}{lldpRemTbl}{lldpRemPortId} =
584 0           idx2val( $vbl, LLDP_REM_PORT_ID, 1, undef, );
585              
586             $session->{$prefix}{lldpRemTbl}{lldpRemPortDesc} =
587 0           idx2val( $vbl, LLDP_REM_PORT_DESC, 1, undef, );
588              
589             $session->{$prefix}{lldpRemTbl}{lldpRemSysName} =
590 0           idx2val( $vbl, LLDP_REM_SYS_NAME, 1, undef, );
591              
592             $session->{$prefix}{lldpRemTbl}{lldpRemSysDesc} =
593 0           idx2val( $vbl, LLDP_REM_SYS_DESC, 1, undef, );
594              
595             $session->{$prefix}{lldpRemTbl}{lldpRemSysCapSupported} =
596 0           idx2val( $vbl, LLDP_REM_SYS_CAPA_SUP, 1, undef, );
597              
598             $session->{$prefix}{lldpRemTbl}{lldpRemSysCapEnabled} =
599 0           idx2val( $vbl, LLDP_REM_SYS_CAPA_ENA, 1, undef, );
600              
601             # this init job is finished
602 0           get_init_slot($session)->{$prefix}--;
603              
604 0           return 1;
605             }
606              
607             unless ( caller() ) {
608             print "$prefix compiles and initializes successful.\n";
609             }
610              
611             =head1 SEE ALSO
612              
613             L<< Net::SNMP::Mixin::Dot1dBase >>
614              
615             =head1 REQUIREMENTS
616              
617             L<< Net::SNMP >>, L<< Net::SNMP::Mixin >>
618              
619             =head1 BUGS, PATCHES & FIXES
620              
621             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.
622              
623             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 .
624              
625             RT: http://rt.cpan.org/Public/Dist/Display.html?Name=Net-SNMP-Mixin-Dot1abLldp
626              
627              
628             =head1 AUTHOR
629              
630             Karl Gaissmaier
631              
632             =head1 COPYRIGHT & LICENSE
633              
634             Copyright 2008-2016 Karl Gaissmaier, all rights reserved.
635              
636             This program is free software; you can redistribute it and/or modify it
637             under the same terms as Perl itself.
638              
639             =cut
640              
641             1;
642              
643             # vim: sw=2