diff --git a/Changes b/Changes index f6c71eb2..411d683d 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,8 @@ Version 3.61 [BUG FIXES] * #261 EIGRP Peer Neighbor Formatting / Munge + * #252 Unpack binary MAC if present in cdp_port + * Fix SNMPv1 cdp_run check Version 3.60 (2018-05-06) diff --git a/lib/SNMP/Info/CDP.pm b/lib/SNMP/Info/CDP.pm index e239c610..2b9546f3 100644 --- a/lib/SNMP/Info/CDP.pm +++ b/lib/SNMP/Info/CDP.pm @@ -54,7 +54,7 @@ $VERSION = '3.60'; 'cdp_run' => 'cdpGlobalRun', 'cdp_interval' => 'cdpGlobalMessageInterval', 'cdp_holdtime' => 'cdpGlobalHoldTime', - 'cdp_gid' => 'cdpGlobalDeviceId', + 'cdp_gid' => 'cdpGlobalDeviceId', ); %FUNCS = ( @@ -62,7 +62,7 @@ $VERSION = '3.60'; 'cdp_addr' => 'cdpCacheAddress', 'cdp_ver' => 'cdpCacheVersion', 'cdp_dev_id' => 'cdpCacheDeviceId', - 'cdp_port' => 'cdpCacheDevicePort', + 'cdp_dev_port' => 'cdpCacheDevicePort', 'cdp_platform' => 'cdpCachePlatform', 'cdp_capabilities' => 'cdpCacheCapabilities', 'cdp_domain' => 'cdpCacheVTPMgmtDomain', @@ -79,7 +79,6 @@ $VERSION = '3.60'; 'cdp_capabilities' => \&SNMP::Info::munge_bits, 'cdp_platform' => \&SNMP::Info::munge_null, 'cdp_domain' => \&SNMP::Info::munge_null, - 'cdp_port' => \&SNMP::Info::munge_null, 'cdp_ver' => \&SNMP::Info::munge_null, 'cdp_ip' => \&SNMP::Info::munge_ip, 'cdp_power' => \&munge_power, @@ -110,18 +109,16 @@ sub munge_power { sub hasCDP { my $cdp = shift; - my $ver = $cdp->{_version}; + # Check the global that is supposed to indicate CDP is running + my $cdp_run = $cdp->cdp_run(); + return 1 if $cdp_run; - # SNMP v1 clients dont have the globals - if ( defined $ver and $ver == 1 ) { - my $cdp_ip = $cdp->cdp_ip(); + # SNMP v1 clients don't have the globals, fallback + # by checking if it would report neighbors + my $cdp_ip = $cdp->cdp_ip() || {}; + return 1 if scalar keys %$cdp_ip; - # See if anything in cdp cache, if so we have cdp - return 1 if ( defined $cdp_ip and scalar( keys %$cdp_ip ) ); - return; - } - - return $cdp->cdp_run(); + return; } sub cdp_if { @@ -219,6 +216,22 @@ sub cdp_id { return \%cdp_id; } +sub cdp_port { + my $cdp = shift; + my $partial = shift; + + my $ch = $cdp->cdp_dev_port($partial) || {}; + + my %cdp_port; + foreach my $key ( sort keys %$ch ) { + my $port = $ch->{$key}; + next unless $port; + $port = SNMP::Info::munge_mac($port) || SNMP::Info::munge_null($port); + $cdp_port{$key} = $port; + } + return \%cdp_port; +} + 1; __END__ diff --git a/xt/lib/Test/SNMP/Info/CDP.pm b/xt/lib/Test/SNMP/Info/CDP.pm index 11101aeb..52a978ae 100644 --- a/xt/lib/Test/SNMP/Info/CDP.pm +++ b/xt/lib/Test/SNMP/Info/CDP.pm @@ -33,23 +33,139 @@ use Test::Class::Most parent => 'My::Test::Class'; use SNMP::Info::CDP; -# Remove this startup override once we have full method coverage -sub startup : Tests(startup => 1) { - my $test = shift; - $test->SUPER::startup(); - - $test->todo_methods(1); -} - sub setup : Tests(setup) { my $test = shift; $test->SUPER::setup; # Start with a common cache that will serve most tests my $cache_data = { - 'store' => {}, + '_cdp_run' => 'true', + '_cdp_ip' => 1, + '_cdp_addr' => 1, + '_cdp_proto' => 1, + '_cdp_capabilities' => 1, + '_cdp_dev_id' => 1, + '_cdp_dev_port' => 1, + 'store' => { + 'cdp_addr' => {'2.1' => pack("H*", '0A141E28'), '3.1' => 'xyz'}, + 'cdp_proto' => {'2.1' => 'ip', '3.1' => 'chaos'}, + 'cdp_capabilities' => {'2.1' => pack("H*", '00000228')}, + 'cdp_dev_id' => {'2.1' => pack("H*", 'ABCD12345678')}, + 'cdp_dev_port' => {'2.1' => pack("H*", 'ABCD12345678')}, + } }; $test->{info}->cache($cache_data); } -1; \ No newline at end of file +sub hasCDP : Tests(4) { + my $test = shift; + + can_ok($test->{info}, 'hasCDP'); + is($test->{info}->hasCDP(), 1, q(Has 'cdpGlobalRun' has CDP)); + + delete $test->{info}{_cdp_run}; + is($test->{info}->hasCDP(), + 1, q(No 'cdpGlobalRun', but has neighbors, has CDP)); + + $test->{info}->clear_cache(); + is($test->{info}->hasCDP(), + undef, q(No 'cdpGlobalRun' and no neighbors, no CDP)); +} + +sub cdp_if : Tests(3) { + my $test = shift; + + can_ok($test->{info}, 'cdp_if'); + + my $expected = {'2.1' => 2}; + + cmp_deeply($test->{info}->cdp_if(), + $expected, q(Mapping of CDP interface has expected value)); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->cdp_if(), {}, q(No data returns empty hash)); +} + +sub cdp_ip : Tests(3) { + my $test = shift; + + can_ok($test->{info}, 'cdp_ip'); + + my $expected = {'2.1' => '10.20.30.40'}; + + cmp_deeply($test->{info}->cdp_ip(), + $expected, q(Remote CDP IPv4 has expected value)); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->cdp_ip(), {}, q(No data returns empty hash)); +} + +sub cdp_cap : Tests(4) { + my $test = shift; + + can_ok($test->{info}, 'cdp_cap'); + + my $expected = ['IGMP', 'Supports-STP-Dispute', 'Switch']; + + my $caps = $test->{info}->cdp_cap(); + + cmp_set($caps->{'2.1'}, $expected, q(Caps emumerated correctly)); + + $test->{info}{store}{cdp_capabilities} = {'2.1' => pack("H*", '00000000')}; + + cmp_deeply($test->{info}->cdp_cap(), {}, q(Cap of zeros return empty hash)); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->cdp_cap(), {}, q(No data returns empty hash)); +} + +sub cdp_id : Tests(4) { + my $test = shift; + + can_ok($test->{info}, 'cdp_id'); + + my $expected = {'2.1' => 'ab:cd:12:34:56:78'}; + + cmp_deeply($test->{info}->cdp_id(), + $expected, q(Remote ID packed MAC has expected value)); + + $test->{info}{store}{cdp_dev_id} = {'2.1' => 'My-Device-Name'}; + $expected = {'2.1' => 'My-Device-Name'}; + + cmp_deeply($test->{info}->cdp_id(), + $expected, q(Remote ID text has expected value)); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->cdp_id(), {}, q(No data returns empty hash)); +} + +sub cdp_port : Tests(4) { + my $test = shift; + + can_ok($test->{info}, 'cdp_port'); + + my $expected = {'2.1' => 'ab:cd:12:34:56:78'}; + + cmp_deeply($test->{info}->cdp_port(), + $expected, q(Remote ID packed MAC has expected value)); + + $test->{info}{store}{cdp_dev_port} = {'2.1' => 'My-Port-Name'}; + $expected = {'2.1' => 'My-Port-Name'}; + + cmp_deeply($test->{info}->cdp_port(), + $expected, q(Remote ID text has expected value)); + + $test->{info}->clear_cache(); + cmp_deeply($test->{info}->cdp_port(), {}, q(No data returns empty hash)); +} + +sub munge_power : Tests(2) { + my $test = shift; + + can_ok($test->{info}, 'munge_power'); + + is(SNMP::Info::CDP::munge_power(123456), + '123.456', q(... munges millwatts to watts)); +} + +1;