From bdf5a8086891433721f3c0816ec4c2410c7e1bb0 Mon Sep 17 00:00:00 2001 From: Carlos Vicente <> Date: Wed, 22 Sep 2010 21:45:08 +0000 Subject: [PATCH] Adding LLDP support for Juniper and C3550 classes --- Info/Layer3/C3550.pm | 212 +++++++++++++++++++++++++++++++++++++++-- Info/Layer3/Juniper.pm | 96 ++++++++++++++++++- 2 files changed, 298 insertions(+), 10 deletions(-) diff --git a/Info/Layer3/C3550.pm b/Info/Layer3/C3550.pm index 8017f0f6..bc814791 100644 --- a/Info/Layer3/C3550.pm +++ b/Info/Layer3/C3550.pm @@ -35,6 +35,7 @@ use strict; use Exporter; use SNMP::Info::CiscoVTP; use SNMP::Info::CiscoStack; +use SNMP::Info::LLDP; use SNMP::Info::CDP; use SNMP::Info::CiscoConfig; use SNMP::Info::CiscoStats; @@ -51,6 +52,7 @@ use vars qw/$VERSION %GLOBALS %MIBS %FUNCS %MUNGE/; SNMP::Info::CiscoVTP SNMP::Info::CiscoStpExtensions SNMP::Info::CiscoStack + SNMP::Info::LLDP SNMP::Info::CDP SNMP::Info::CiscoStats SNMP::Info::CiscoImage @@ -74,8 +76,9 @@ $VERSION = '2.01'; %SNMP::Info::Layer3::MIBS, %SNMP::Info::CiscoPower::MIBS, %SNMP::Info::CiscoConfig::MIBS, %SNMP::Info::CiscoPortSecurity::MIBS, %SNMP::Info::CiscoImage::MIBS, %SNMP::Info::CiscoStats::MIBS, - %SNMP::Info::CDP::MIBS, %SNMP::Info::CiscoStack::MIBS, - %SNMP::Info::CiscoStpExtensions::MIBS, %SNMP::Info::CiscoVTP::MIBS, + %SNMP::Info::LLDP::MIBS, %SNMP::Info::CDP::MIBS, + %SNMP::Info::CiscoStack::MIBS, %SNMP::Info::CiscoStpExtensions::MIBS, + %SNMP::Info::CiscoVTP::MIBS, ); @@ -86,6 +89,7 @@ $VERSION = '2.01'; %SNMP::Info::CiscoPortSecurity::GLOBALS, %SNMP::Info::CiscoImage::GLOBALS, %SNMP::Info::CiscoStats::GLOBALS, + %SNMP::Info::LLDP::GLOBALS, %SNMP::Info::CDP::GLOBALS, %SNMP::Info::CiscoStack::GLOBALS, %SNMP::Info::CiscoStpExtensions::GLOBALS, @@ -96,16 +100,18 @@ $VERSION = '2.01'; %SNMP::Info::Layer3::FUNCS, %SNMP::Info::CiscoPower::FUNCS, %SNMP::Info::CiscoConfig::FUNCS, %SNMP::Info::CiscoPortSecurity::FUNCS, %SNMP::Info::CiscoImage::FUNCS, %SNMP::Info::CiscoStats::FUNCS, - %SNMP::Info::CDP::FUNCS, %SNMP::Info::CiscoStack::FUNCS, - %SNMP::Info::CiscoStpExtensions::FUNCS, %SNMP::Info::CiscoVTP::FUNCS, + %SNMP::Info::LLDP::FUNCS, %SNMP::Info::CDP::FUNCS, + %SNMP::Info::CiscoStack::FUNCS, %SNMP::Info::CiscoStpExtensions::FUNCS, + %SNMP::Info::CiscoVTP::FUNCS, ); %MUNGE = ( %SNMP::Info::Layer3::MUNGE, %SNMP::Info::CiscoPower::MUNGE, %SNMP::Info::CiscoConfig::MUNGE, %SNMP::Info::CiscoPortSecurity::MUNGE, %SNMP::Info::CiscoImage::MUNGE, %SNMP::Info::CiscoStats::MUNGE, - %SNMP::Info::CDP::MUNGE, %SNMP::Info::CiscoStack::MUNGE, - %SNMP::Info::CiscoStpExtensions::MUNGE, %SNMP::Info::CiscoVTP::MUNGE, + %SNMP::Info::LLDP::MUNGE, %SNMP::Info::CDP::MUNGE, + %SNMP::Info::CiscoStack::MUNGE, %SNMP::Info::CiscoStpExtensions::MUNGE, + %SNMP::Info::CiscoVTP::MUNGE, ); sub vendor { @@ -230,6 +236,141 @@ sub cisco_comm_indexing { return 1; } +# Use CDP and/or LLDP +sub hasCDP { + my $c3550 = shift; + return $c3550->hasLLDP() || $c3550->SUPER::hasCDP(); +} + +sub c_ip { + my $c3550 = shift; + my $partial = shift; + + my $cdp = $c3550->SUPER::c_ip($partial) || {}; + my $lldp = $c3550->lldp_ip($partial) || {}; + + my %c_ip; + foreach my $iid ( keys %$cdp ) { + my $ip = $cdp->{$iid}; + next unless defined $ip; + + $c_ip{$iid} = $ip; + } + + foreach my $iid ( keys %$lldp ) { + my $ip = $lldp->{$iid}; + next unless defined $ip; + + $c_ip{$iid} = $ip; + } + return \%c_ip; +} + +sub c_if { + my $c3550 = shift; + my $partial = shift; + + my $cdp = $c3550->SUPER::c_if($partial) || {}; + + my %c_if; + foreach my $iid ( keys %$cdp ) { + my $if = $cdp->{$iid}; + next unless defined $if; + + $c_if{$iid} = $if; + } + + # We need to match the lldp key with the ifIndex + # via lldpLocPortId and ifName + my $i_name = $c3550->ifName($partial) || {}; + my $i_name_rev = {}; + while ( my($key,$val) = each %$i_name ){ + $i_name_rev->{$val} = $key; + } + my $loc_port_id = $c3550->lldpLocPortId($partial) || {}; + my $lldp = $c3550->lldp_if($partial) || {}; + + foreach my $iid ( keys %$lldp ) { + my $if = $lldp->{$iid} || next; + my $name = $loc_port_id->{$if} || next; + my $i_index = $i_name_rev->{$name} || next; + $c_if{$iid} = $i_index; + } + return \%c_if; +} + +sub c_port { + my $c3550 = shift; + my $partial = shift; + + my $lldp = $c3550->lldp_port($partial) || {}; + my $cdp = $c3550->SUPER::c_port($partial) || {}; + + my %c_port; + foreach my $iid ( keys %$cdp ) { + my $port = $cdp->{$iid}; + next unless defined $port; + + $c_port{$iid} = $port; + } + + foreach my $iid ( keys %$lldp ) { + my $port = $lldp->{$iid}; + next unless defined $port; + $c_port{$iid} = $port; + } + return \%c_port; +} + +sub c_id { + my $c3550 = shift; + my $partial = shift; + + my $lldp = $c3550->lldp_id($partial) || {}; + my $cdp = $c3550->SUPER::c_id($partial) || {}; + + my %c_id; + foreach my $iid ( keys %$cdp ) { + my $id = $cdp->{$iid}; + next unless defined $id; + + $c_id{$iid} = $id; + } + + foreach my $iid ( keys %$lldp ) { + my $id = $lldp->{$iid}; + next unless defined $id; + + $c_id{$iid} = $id; + } + return \%c_id; +} + +sub c_platform { + my $c3550 = shift; + my $partial = shift; + + my $lldp = $c3550->lldp_rem_sysdesc($partial) || {}; + my $cdp = $c3550->SUPER::c_platform($partial) || {}; + + my %c_platform; + foreach my $iid ( keys %$cdp ) { + my $platform = $cdp->{$iid}; + next unless defined $platform; + + $c_platform{$iid} = $platform; + } + + foreach my $iid ( keys %$lldp ) { + my $platform = $lldp->{$iid}; + next unless defined $platform; + + $c_platform{$iid} = $platform; + } + return \%c_platform; +} + + 1; __END__ @@ -289,6 +430,8 @@ after determining a more specific class using the method above. =item SNMP::Info::CDP +=item SNMP::Info::LLDP + =item SNMP::Info::CiscoStats =item SNMP::Info::CiscoImage @@ -320,6 +463,8 @@ See L for its own MIB requirements. See L for its own MIB requirements. +See L for its own MIB requirements. + =back =head1 GLOBALS @@ -349,6 +494,23 @@ Returns 1. Use vlan indexing. =back +=head2 Topology information + +Based upon the firmware version Cisco devices may support Link Layer Discovery +Protocol (LLDP) in addition to Cisco Discovery Protocol (CDP). These methods +will query both and return the combination of all information. As a result, +there may be identical topology information returned from the two protocols +causing duplicate entries. It is the calling program's responsibility to +identify any duplicate entries and remove duplicates if necessary. + +=over + +=item $c3550->hasCDP() + +Returns true if the device is running either CDP or LLDP. + +=back + =head2 Globals imported from SNMP::Info::Layer3 See documentation in L for details. @@ -377,6 +539,10 @@ See documentation in L for details. See documentation in L for details. +=head2 Globals imported from SNMP::Info::LLDP + +See documentation in L for details. + =head2 Globals imported from SNMP::Info::CiscoStats See documentation in L for details. @@ -390,6 +556,36 @@ See documentation in L for details. These are methods that return tables of information in the form of a reference to a hash. +=item $c3550->c_if() + +Returns reference to hash. Key: iid Value: local device port (interfaces) + +=item $c3550->c_ip() + +Returns reference to hash. Key: iid Value: remote IPv4 address + +If multiple entries exist with the same local port, c_if(), with the same IPv4 +address, c_ip(), it may be a duplicate entry. + +If multiple entries exist with the same local port, c_if(), with different +IPv4 addresses, c_ip(), there is either a non-CDP/LLDP device in between two +or more devices or multiple devices which are not directly connected. + +Use the data from the Layer2 Topology Table below to dig deeper. + +=item $c3550->c_port() + +Returns reference to hash. Key: iid Value: remote port (interfaces) + +=item $c3550->c_id() + +Returns reference to hash. Key: iid Value: string value used to identify the +chassis component associated with the remote system. + +=item $c3550->c_platform() + +Returns reference to hash. Key: iid Value: Remote Device Type + =head2 Overrides =over @@ -459,6 +655,10 @@ See documentation in L for details. See documentation in L for details. +=head2 Table Methods imported from SNMP::Info::LLDP + +See documentation in L for details. + =head2 Table Methods imported from SNMP::Info::CiscoStats See documentation in L for details. diff --git a/Info/Layer3/Juniper.pm b/Info/Layer3/Juniper.pm index 2a9cb1d6..3e83d498 100644 --- a/Info/Layer3/Juniper.pm +++ b/Info/Layer3/Juniper.pm @@ -33,8 +33,9 @@ package SNMP::Info::Layer3::Juniper; use strict; use Exporter; use SNMP::Info::Layer3; +use SNMP::Info::LLDP; -@SNMP::Info::Layer3::Juniper::ISA = qw/SNMP::Info::Layer3 Exporter/; +@SNMP::Info::Layer3::Juniper::ISA = qw/SNMP::Info::Layer3 SNMP::Info::LLDP Exporter/; @SNMP::Info::Layer3::Juniper::EXPORT_OK = qw//; use vars qw/$VERSION %GLOBALS %MIBS %FUNCS %MUNGE/; @@ -43,15 +44,22 @@ $VERSION = '2.01'; %MIBS = ( %SNMP::Info::Layer3::MIBS, + %SNMP::Info::LLDP::MIBS, 'JUNIPER-CHASSIS-DEFINES-MIB' => 'jnxChassisDefines', 'JUNIPER-MIB' => 'jnxBoxAnatomy', ); -%GLOBALS = ( %SNMP::Info::Layer3::GLOBALS, 'serial' => 'jnxBoxSerialNo.0', ); +%GLOBALS = ( %SNMP::Info::Layer3::GLOBALS, + %SNMP::Info::LLDP::GLOBALS, + 'serial' => 'jnxBoxSerialNo.0', ); -%FUNCS = ( %SNMP::Info::Layer3::FUNCS, ); +%FUNCS = ( %SNMP::Info::Layer3::FUNCS, + %SNMP::Info::LLDP::FUNCS, +); -%MUNGE = ( %SNMP::Info::Layer3::MUNGE, ); +%MUNGE = ( %SNMP::Info::Layer3::MUNGE, + %SNMP::Info::LLDP::MUNGE, +); sub vendor { return 'juniper'; @@ -130,6 +138,50 @@ sub fw_port { return $juniper->qb_fw_port($partial); } +# Use LLDP + +sub hasCDP { + my $juniper = shift; + + return $juniper->hasLLDP(); +} + +sub c_ip { + my $juniper = shift; + my $partial = shift; + + return $juniper->lldp_ip($partial); +} + +sub c_if { + my $juniper = shift; + my $partial = shift; + + return $juniper->lldp_if($partial); +} + +sub c_port { + my $juniper = shift; + my $partial = shift; + + return $juniper->lldp_port($partial); +} + +sub c_id { + my $juniper = shift; + my $partial = shift; + + return $juniper->lldp_id($partial); +} + +sub c_platform { + my $juniper = shift; + my $partial = shift; + + return $juniper->lldp_rem_sysdesc($partial); +} + + 1; __END__ @@ -166,6 +218,8 @@ Subclass for Generic Juniper Routers running JUNOS =item SNMP::Info::Layer3 +=item SNMP::Info::LLDP + =back =head2 Required MIBs @@ -176,6 +230,8 @@ Subclass for Generic Juniper Routers running JUNOS See L for its own MIB requirements. +See L for its own MIB requirements. + =back =head1 GLOBALS @@ -207,12 +263,20 @@ Returns serial number (C) +=item $juniper->hasCDP() + + Returns whether LLDP is enabled. + =back =head2 Globals imported from SNMP::Info::Layer3 See documentation in L for details. +=head2 Global Methods imported from SNMP::Info::LLDP + +See documentation in L for details. + =head1 TABLE METHODS These are methods that return tables of information in the form of a reference @@ -225,10 +289,34 @@ to a hash. Returns the list of interfaces whose C is l2vlan(135), and the VLAN ID extracted from the interface description. +=item $juniper->c_id() + +Returns LLDP information. + +=item $juniper->c_if() + +Returns LLDP information. + +=item $juniper->c_ip() + +Returns LLDP information. + +=item $juniper->c_platform() + +Returns LLDP information. + +=item $juniper->c_port() + +Returns LLDP information. + =back =head2 Table Methods imported from SNMP::Info::Layer3 See documentation in L for details. +=head2 Table Methods imported from SNMP::Info::LLDP + +See documentation in L for details. + =cut