Open lyubomirtraykov opened 4 years ago
This lacks a lot of details.
Also, implementing CDP/LLDP discovery works on a per-vendor basis with often multiple SNMP calls to figure it out. It will be hard to allow this configuration in the switch templates. The best we could probably do is to create some pre-built Perl templates for the different vendors that we could then apply on the switch template. But you'd be limited to the ones the Inverse team coded since its almost impossible to get the CDP/LLDP logic implemented through configuration
I disagree. This code is generic. It uses LLDP-MIB.
my $oid_lldpRemPortId = '1.0.8802.1.1.2.1.4.1.1.7';
my $oid_lldpRemSysCapEnabled = '1.0.8802.1.1.2.1.4.1.1.12';
if ( !$self->connectRead() ) {
return @phones;
}
$logger->trace(
"SNMP get_next_request for lldpRemSysCapEnabled: $oid_lldpRemSysCapEnabled");
my $result = $self->{_sessionRead}
->get_table( -baseoid => $oid_lldpRemSysCapEnabled );
foreach my $oid ( keys %{$result} ) {
if ( $oid =~ /^$oid_lldpRemSysCapEnabled\.([0-9]+)\.([0-9]+)\.([0-9]+)$/ ) {
if ( $ifIndex eq $2 ) {
my $cache_lldpRemTimeMark = $1;
my $cache_lldpRemLocalPortNum = $2;
my $cache_lldpRemIndex = $3;
if ( $self->getBitAtPosition($result->{$oid}, $SNMP::LLDP::TELEPHONE) ) {
$logger->trace(
"SNMP get_request for lldpRemPortId: $oid_lldpRemPortId.$cache_lldpRemTimeMark.$cache_lldpRemLocalPortNum.$cache_lldpRemIndex"
);
my $MACresult = $self->{_sessionRead}->get_request(
-varbindlist => [
"$oid_lldpRemPortId.$cache_lldpRemTimeMark.$cache_lldpRemLocalPortNum.$cache_lldpRemIndex"
]
);
if ($MACresult
&& ($MACresult->{
"$oid_lldpRemPortId.$cache_lldpRemTimeMark.$cache_lldpRemLocalPortNum.$cache_lldpRemIndex"
}
=~ /^([0-9A-Z]{2})([0-9A-Z]{2})([0-9A-Z]{2})([0-9A-Z]{2})([0-9A-Z]{2})([0-9A-Z]{2})/i
)
)
{
push @phones, lc("$1:$2:$3:$4:$5:$6");
}
}
}
}
}
return @phones;
We will only need Var for $position in getBitAtPosition and maybe one more Var for the regex in $MACresult
I see at least 2 different implementation in the code by looking at it quickly
Avaya != Cisco
And Procurve (which your example looks to be taken of) doesn't use the same regex for lldpRemIndex
I doubt we can get a one size fits all piece of code but if you find something that can work with all vendors using a handful of configuration variables, we can definitely get that in through a pull request
This regex
^(?:0x)?([0-9A-Z]{2})[\s-\,\.]?([0-9A-Z]{2})[\s-\,\.]?([0-9A-Z]{2})[\s-\,\.]?([0-9A-Z]{2})[\s-\,\.]?([0-9A-Z]{2})[\s-\,\.]?([0-9A-Z]{2})(?:.*)?(?::..)?$
should work for all vendors that you support now.
This getBitAtPosition is universal:
sub getBitAtPosition {
my ($bitStream, $position) = @_;
my $bin ='';
if ($bitStream =~ /^0x/) {
$bitStream =~ s/^0x//i;
$bin = join('',map { unpack("B4",pack("H",$_)) } (split //, $bitStream));
} else {
$bin = unpack('B*', $bitStream);
}
if (substr($bin,0,8) ne '00000000') {return substr($bin, $position, 1);}
else {return substr($bin, $position -8, 1);}
}
The only var that i can think of now is $ifIndexOffset. For example: If $ifIndex = 501 and the $lldpRemLocalPortNum = 502, $ifIndexOffset should be 1 If $ifIndex = 501 and the $lldpRemLocalPortNum = 11502, $ifIndexOffset should be 11001 If $ifIndex = 501 and the $lldpRemLocalPortNum = 500, $ifIndexOffset should be -1 If $ifIndex = 501 and the $lldpRemLocalPortNum = 501, $ifIndexOffset should be 0
This way the code above gets universal. I did a test with Cisco, Brocade and Juniper and it works.
Still need other variables for Avaya/Nortel because they don't use the same MIB, not sure if they also use a different way to handle the data in the SNMP table
Ok we can have $uselldpRemSysDesc BOOL and $regexRemSysDesc regex.
This is an example code:
sub getPhonesLLDPAtIfIndex {
my ( $self, $ifIndex ) = @_;
my $logger = $self->logger;
my @phones;
if ( !$self->isVoIPEnabled() ) {
$logger->debug( "VoIP not enabled on switch "
. $self->{_ip}
. ". getPhonesLLDPAtIfIndex will return empty list." );
return @phones;
}
my $oid_lldpRemPortId = '1.0.8802.1.1.2.1.4.1.1.7';
my $oid_lldpRemSysDesc = '1.0.8802.1.1.2.1.4.1.1.10';
my $oid_lldpRemSysCapEnabled = '1.0.8802.1.1.2.1.4.1.1.12';
if ( !$self->connectRead() ) {
return @phones;
}
$logger->trace(
"SNMP get_next_request for lldpRemSysCapEnabled: $oid_lldpRemSysCapEnabled");
my $result;
if(isenabled($self->{_template}->{uselldpRemSysDesc})){
$result = $self->{_sessionRead}
->get_table( -baseoid => $oid_lldpRemSysDesc );
}
else{
my $result = $self->{_sessionRead}
->get_table( -baseoid => $oid_lldpRemSysCapEnabled );
}
foreach my $oid ( keys %{$result} ) {
if ( $oid =~ /^$oid_lldpRemSysCapEnabled\.([0-9]+)\.([0-9]+)\.([0-9]+)$/ ||
$oid =~ /^$oid_lldpRemSysDesc\.([0-9]+)\.([0-9]+)\.([0-9]+)$/ ) {
if ( ($ifIndex + $ifIndexOffset) eq $2 ) {
my $cache_lldpRemTimeMark = $1;
my $cache_lldpRemLocalPortNum = $2;
my $cache_lldpRemIndex = $3;
if ( $self->getBitAtPosition($result->{$oid}, $SNMP::LLDP::TELEPHONE) ||
($result->{$oid} =~ /$regexRemSysDesc/i and isenabled($self->{_template}->{uselldpRemSysDesc})) ) {
$logger->trace(
"SNMP get_request for lldpRemPortId: $oid_lldpRemPortId.$cache_lldpRemTimeMark.$cache_lldpRemLocalPortNum.$cache_lldpRemIndex"
);
my $MACresult = $self->{_sessionRead}->get_request(
-varbindlist => [
"$oid_lldpRemPortId.$cache_lldpRemTimeMark.$cache_lldpRemLocalPortNum.$cache_lldpRemIndex"
]
);
if ($MACresult
&& ($MACresult->{
"$oid_lldpRemPortId.$cache_lldpRemTimeMark.$cache_lldpRemLocalPortNum.$cache_lldpRemIndex"
}
=~ /^(?:0x)?([0-9A-Z]{2})[\s\-\,\.]?([0-9A-Z]{2})[\-\,\.\s]?([0-9A-Z]{2})[\s\-\,\.]?([0-9A-Z]{2})[\s\-\,\.]?([0-9A-Z]{2})[\s\-\,\.]?([0-9A-Z]{2})(?:.*)?(?::..)?$/i
)
)
{
push @phones, lc("$1:$2:$3:$4:$5:$6");
}
}
}
}
}
return @phones;
}
Hi,
Since you've done quite a bit of work around it, I think it would be good if you submit a pull request.
This way we can test it with the switches we have available in our lab and continue the conversation there.
Thanks,
Add LDDP and CDP config in the templates.