From be01c3937a117a897af21d6cbdbb8b3c06c600c2 Mon Sep 17 00:00:00 2001 From: "Eric A. Miller" Date: Sat, 27 Dec 2014 14:27:15 -0500 Subject: [PATCH] Move snmp_comm_reindex and _get_vlan_list from Core::Macsuck to Util::SNMP to support gathering per vlan stp instances in discover --- Netdisco/lib/App/Netdisco/Core/Macsuck.pm | 115 +--------------------- Netdisco/lib/App/Netdisco/Util/SNMP.pm | 113 ++++++++++++++++++++- 2 files changed, 114 insertions(+), 114 deletions(-) diff --git a/Netdisco/lib/App/Netdisco/Core/Macsuck.pm b/Netdisco/lib/App/Netdisco/Core/Macsuck.pm index 1cde1cc4..a1c2bdf8 100644 --- a/Netdisco/lib/App/Netdisco/Core/Macsuck.pm +++ b/Netdisco/lib/App/Netdisco/Core/Macsuck.pm @@ -5,7 +5,7 @@ use Dancer::Plugin::DBIC 'schema'; use App::Netdisco::Util::PortMAC 'get_port_macs'; use App::Netdisco::Util::Node 'check_mac'; -use App::Netdisco::Util::SNMP 'snmp_comm_reindex'; +use App::Netdisco::Util::SNMP qw/snmp_comm_reindex get_comm_reindex_vlan_list/; use Time::HiRes 'gettimeofday'; use base 'Exporter'; @@ -75,7 +75,7 @@ sub do_macsuck { my $fwtable = _walk_fwtable($device, $snmp, $interfaces, $port_macs, $device_ports); # ...then per-vlan if supported - my @vlan_list = _get_vlan_list($device, $snmp); + my @vlan_list = get_comm_reindex_vlan_list($device, $snmp); foreach my $vlan (@vlan_list) { snmp_comm_reindex($snmp, $device, $vlan); my $pv_fwtable = _walk_fwtable($device, $snmp, $interfaces, $port_macs, $device_ports, $vlan); @@ -179,117 +179,6 @@ sub store_node { }); } -# return a list of vlan numbers which are OK to macsuck on this device -sub _get_vlan_list { - my ($device, $snmp) = @_; - - return () unless $snmp->cisco_comm_indexing; - - my (%vlans, %vlan_names); - my $i_vlan = $snmp->i_vlan || {}; - my $trunks = $snmp->i_vlan_membership || {}; - my $i_type = $snmp->i_type || {}; - - # get list of vlans in use - while (my ($idx, $vlan) = each %$i_vlan) { - # hack: if vlan id comes as 1.142 instead of 142 - $vlan =~ s/^\d+\.//; - - # VLANs are ports interfaces capture VLAN, but don't count as in use - # Port channels are also 'propVirtual', but capture while checking - # trunk VLANs below - if (exists $i_type->{$idx} and $i_type->{$idx} eq 'propVirtual') { - $vlans{$vlan} ||= 0; - } - else { - ++$vlans{$vlan}; - } - foreach my $t_vlan (@{$trunks->{$idx}}) { - ++$vlans{$t_vlan}; - } - } - - unless (scalar keys %vlans) { - debug sprintf ' [%s] macsuck - no VLANs found.', $device->ip; - return (); - } - - my $v_name = $snmp->v_name || {}; - - # get vlan names (required for config which filters by name) - while (my ($idx, $name) = each %$v_name) { - # hack: if vlan id comes as 1.142 instead of 142 - (my $vlan = $idx) =~ s/^\d+\.//; - - # just in case i_vlan is different to v_name set - # capture the VLAN, but it's not in use on a port - $vlans{$vlan} ||= 0; - - $vlan_names{$vlan} = $name; - } - - debug sprintf ' [%s] macsuck - VLANs: %s', $device->ip, - (join ',', sort keys %vlans); - - my @ok_vlans = (); - foreach my $vlan (sort keys %vlans) { - my $name = $vlan_names{$vlan} || '(unnamed)'; - - if (ref [] eq ref setting('macsuck_no_vlan')) { - my $ignore = setting('macsuck_no_vlan'); - - if ((scalar grep {$_ eq $vlan} @$ignore) or - (scalar grep {$_ eq $name} @$ignore)) { - - debug sprintf - ' [%s] macsuck VLAN %s - skipped by macsuck_no_vlan config', - $device->ip, $vlan; - next; - } - } - - if (ref [] eq ref setting('macsuck_no_devicevlan')) { - my $ignore = setting('macsuck_no_devicevlan'); - my $ip = $device->ip; - - if ((scalar grep {$_ eq "$ip:$vlan"} @$ignore) or - (scalar grep {$_ eq "$ip:$name"} @$ignore)) { - - debug sprintf - ' [%s] macsuck VLAN %s - skipped by macsuck_no_devicevlan config', - $device->ip, $vlan; - next; - } - } - - if (setting('macsuck_no_unnamed') and $name eq '(unnamed)') { - debug sprintf - ' [%s] macsuck VLAN %s - skipped by macsuck_no_unnamed config', - $device->ip, $vlan; - next; - } - - if ($vlan == 0 or $vlan > 4094) { - debug sprintf ' [%s] macsuck - invalid VLAN number %s', - $device->ip, $vlan; - next; - } - - # check in use by a port on this device - if (!$vlans{$vlan} && !setting('macsuck_all_vlans')) { - - debug sprintf - ' [%s] macsuck VLAN %s/%s - not in use by any port - skipping.', - $device->ip, $vlan, $name; - next; - } - - push @ok_vlans, $vlan; - } - - return @ok_vlans; -} - # walks the forwarding table (BRIDGE-MIB) for the device and returns a # table of node entries. sub _walk_fwtable { diff --git a/Netdisco/lib/App/Netdisco/Util/SNMP.pm b/Netdisco/lib/App/Netdisco/Util/SNMP.pm index ab659bc2..5ad7def7 100644 --- a/Netdisco/lib/App/Netdisco/Util/SNMP.pm +++ b/Netdisco/lib/App/Netdisco/Util/SNMP.pm @@ -12,7 +12,7 @@ use Path::Class 'dir'; use base 'Exporter'; our @EXPORT = (); our @EXPORT_OK = qw/ - snmp_connect snmp_connect_rw snmp_comm_reindex + snmp_connect snmp_connect_rw snmp_comm_reindex get_comm_reindex_vlan_list /; our %EXPORT_TAGS = (all => \@EXPORT_OK); @@ -400,4 +400,115 @@ sub snmp_comm_reindex { } } +# return a list of vlan numbers which are OK to macsuck on this device +sub get_comm_reindex_vlan_list { + my ($device, $snmp) = @_; + + return () unless $snmp->cisco_comm_indexing; + + my (%vlans, %vlan_names); + my $i_vlan = $snmp->i_vlan || {}; + my $trunks = $snmp->i_vlan_membership || {}; + my $i_type = $snmp->i_type || {}; + + # get list of vlans in use + while (my ($idx, $vlan) = each %$i_vlan) { + # hack: if vlan id comes as 1.142 instead of 142 + $vlan =~ s/^\d+\.//; + + # VLANs are ports interfaces capture VLAN, but don't count as in use + # Port channels are also 'propVirtual', but capture while checking + # trunk VLANs below + if (exists $i_type->{$idx} and $i_type->{$idx} eq 'propVirtual') { + $vlans{$vlan} ||= 0; + } + else { + ++$vlans{$vlan}; + } + foreach my $t_vlan (@{$trunks->{$idx}}) { + ++$vlans{$t_vlan}; + } + } + + unless (scalar keys %vlans) { + debug sprintf ' [%s] macsuck - no VLANs found.', $device->ip; + return (); + } + + my $v_name = $snmp->v_name || {}; + + # get vlan names (required for config which filters by name) + while (my ($idx, $name) = each %$v_name) { + # hack: if vlan id comes as 1.142 instead of 142 + (my $vlan = $idx) =~ s/^\d+\.//; + + # just in case i_vlan is different to v_name set + # capture the VLAN, but it's not in use on a port + $vlans{$vlan} ||= 0; + + $vlan_names{$vlan} = $name; + } + + debug sprintf ' [%s] macsuck - VLANs: %s', $device->ip, + (join ',', sort keys %vlans); + + my @ok_vlans = (); + foreach my $vlan (sort keys %vlans) { + my $name = $vlan_names{$vlan} || '(unnamed)'; + + if (ref [] eq ref setting('macsuck_no_vlan')) { + my $ignore = setting('macsuck_no_vlan'); + + if ((scalar grep {$_ eq $vlan} @$ignore) or + (scalar grep {$_ eq $name} @$ignore)) { + + debug sprintf + ' [%s] macsuck VLAN %s - skipped by macsuck_no_vlan config', + $device->ip, $vlan; + next; + } + } + + if (ref [] eq ref setting('macsuck_no_devicevlan')) { + my $ignore = setting('macsuck_no_devicevlan'); + my $ip = $device->ip; + + if ((scalar grep {$_ eq "$ip:$vlan"} @$ignore) or + (scalar grep {$_ eq "$ip:$name"} @$ignore)) { + + debug sprintf + ' [%s] macsuck VLAN %s - skipped by macsuck_no_devicevlan config', + $device->ip, $vlan; + next; + } + } + + if (setting('macsuck_no_unnamed') and $name eq '(unnamed)') { + debug sprintf + ' [%s] macsuck VLAN %s - skipped by macsuck_no_unnamed config', + $device->ip, $vlan; + next; + } + + if ($vlan == 0 or $vlan > 4094) { + debug sprintf ' [%s] macsuck - invalid VLAN number %s', + $device->ip, $vlan; + next; + } + + # check in use by a port on this device + if (!$vlans{$vlan} && !setting('macsuck_all_vlans')) { + + debug sprintf + ' [%s] macsuck VLAN %s/%s - not in use by any port - skipping.', + $device->ip, $vlan, $name; + next; + } + + push @ok_vlans, $vlan; + } + + return @ok_vlans; +} + 1;