Files
netdisco/Netdisco/lib/App/Netdisco/Core/Macsuck.pm
Oliver Gorwits 4d0e2461f5 Merge of og-work branch, many new features.
Squashed commit of the following:

commit a43c98962a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jun 3 20:37:39 2013 +0100

    Missing mibdirs causes all MIBs to be loaded (with a warning)

commit 09829a25b8
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jun 3 20:07:31 2013 +0100

    local plugins site_plugins dir

commit b0e804e558
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jun 3 19:59:04 2013 +0100

    use send_error and redirect from Dancer

commit 3d1185261a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jun 3 19:13:40 2013 +0100

    support path config option

commit 31ca119f84
Merge: 9a79855 4d2b3a5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jun 3 00:06:17 2013 +0100

    Merge remote-tracking branch 'origin/og-work' into og-work
    g-work"

    This reverts commit 9a79855361, reversing
    changes made to 6fd6118354.

    Conflicts:
    	Netdisco/share/views/plugin/device_port_column/c_observiumsparklines.tt

commit 9a79855361
Merge: 6fd6118 c8c3b82
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Jun 3 00:03:32 2013 +0100

    Merge remote-tracking branch 'origin/master' into og-work

commit 6fd6118354
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Jun 2 15:47:45 2013 +0100

    extra note about behind proxy

commit 798086ca29
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Jun 2 15:30:26 2013 +0100

    complete the observium plugin

commit 66b3ced179
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun Jun 2 12:48:06 2013 +0100

    Plugins can have CSS and Javascript loaded within <head>

commit 4d2b3a5307
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 30 08:50:16 2013 +0100

    get device dns to port template

commit ed1bfa1ae7
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 30 08:17:02 2013 +0100

    observium sparklines plugin; support X:: namespace

commit 76b7636c74
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 30 06:30:06 2013 +0100

    rename private settings keys

commit fdac8f6c33
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 30 05:59:53 2013 +0100

    add macwalk and arpnip buttons to device details

commit 3d688c7d83
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 30 05:57:20 2013 +0100

    Revert "reduce refresh to 5sec"

    This reverts commit 8ea9ec7dd9.

commit dc62382112
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 30 05:50:34 2013 +0100

    support for arpwalk and macwalk and all jobs via web

commit 8bc7d83c98
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 30 05:35:41 2013 +0100

    simplify discover options to only discoverall and discover

commit 8ea9ec7dd9
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 20:23:08 2013 +0100

    reduce refresh to 5sec

commit 8c54e6c58b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 20:11:06 2013 +0100

    show undiscovered neighbor properly

commit e0ee25628f
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 19:54:09 2013 +0100

    avoid unecessary log for queueing

commit d5565423f2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 19:51:37 2013 +0100

    avoid warning on undefined remote type

commit 5d9b58a6b2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 19:48:22 2013 +0100

    avoid explosion when not admin

commit 377bb942e0
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 19:46:52 2013 +0100

    avoid undefined warning

commit 08806dcfa2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 19:46:42 2013 +0100

    get_db_version will be 0 at first deploy

commit 9511c17056
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 29 19:15:55 2013 +0100

    fix name of Template module

commit eb0288de35
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 28 07:17:07 2013 +0100

    initial config settings documentation

commit 7f2ea7f8dc
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 27 15:18:15 2013 +0100

    remove check_mac to own module, use in macsuck too

commit b995cf6398
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 27 15:01:29 2013 +0100

    show probable but undiscovered neighbor is ports display

commit dd8d461188
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 27 14:52:41 2013 +0100

    new schema version for is_uplink and is_uplink_admin

commit 3f6a7b5aa2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 27 14:47:59 2013 +0100

    make sure device_port is updated when manual_topo is set

commit 33bf9a6599
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 26 19:51:49 2013 +0100

    export store_arp and store_node

commit 0ed356d560
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat May 25 17:12:31 2013 +0100

    use row lock not table lock

commit f830bc3a3b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat May 25 16:38:33 2013 +0100

    move macsuck/arpnip/discover to ::Core namespace

commit be40788987
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri May 24 21:10:34 2013 +0100

    add maybe_uplink to device_port; more macsuck implementation

commit 88371026d5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri May 24 14:34:58 2013 +0100

    start on macsuck; tweak update locking

commit 6f7c87ac07
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri May 24 13:10:58 2013 +0100

    ORDER BY ... FOR UPDATE will allow us to avoid table lock

commit 7c438e01fc
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri May 24 12:12:46 2013 +0100

    yet more efficient arpnip

commit c74c56dc02
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Fri May 24 11:34:23 2013 +0100

    guard against race with *_or_* DBIC methods

commit d50c54972e
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 20 23:42:41 2013 +0100

    more efficient arpnip

commit 73c8979130
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 19 22:52:15 2013 +0100

    fix confusing name

commit bf78e82411
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 19 22:37:22 2013 +0100

    fix mistake in DBIx::Class schema

commit 6a5af95836
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 19 22:06:27 2013 +0100

    arpnip implementation

commit 594abd3f82
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 16 00:00:50 2013 +0100

    PostgreSQL explicit locking support.

    Squashed commit of the following:

    commit 76e1539102
    Author: Oliver Gorwits <oliver@cpan.org>
    Date:   Wed May 15 23:54:25 2013 +0100

        finished explicit locking module

    commit 369387258b
    Author: Oliver Gorwits <oliver@cpan.org>
    Date:   Tue May 14 23:50:42 2013 +0100

        initial implementation of locking from schema object

commit 55c6d4fe63
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 14 21:05:01 2013 +0100

    add discover button to device details page

commit 11fd8bf964
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 14 20:43:43 2013 +0100

    fix typo and clear port box on autocomplete dropdown

commit a00f9b5c2e
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 14 20:38:54 2013 +0100

    move admin tasks and remove JobControl package

commit 74bc0023df
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat May 11 18:25:04 2013 +0100

    complete job queue delete and kill running timers properly when reloading page

commit dd6947f38d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat May 11 16:51:28 2013 +0100

    fix improper use of bootstrap table class

commit cd5b83f71e
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat May 11 15:55:45 2013 +0100

    fix update view icon in sidebar

commit e9349f325d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat May 11 11:57:19 2013 +0100

    css audit

commit 201470275d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 9 23:48:05 2013 +0100

    add job queue to standard plugins list

commit a18a3c72a3
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 9 23:37:43 2013 +0100

    fix table headings and improve Action display in Job Queue

commit 70f5da8bb6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 9 23:30:32 2013 +0100

    implement "no devices" prompt for admin users to do first discover

commit 2e8ac83173
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 9 21:53:39 2013 +0100

    more js refactoring for report and search

commit 479ac0e55d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 9 21:50:29 2013 +0100

    refactor js for device tabs

commit 6a17fe5d6c
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Thu May 9 21:05:42 2013 +0100

    fix crazy races with javasacript by using global delegations

commit e94e3cef3b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Wed May 8 23:06:41 2013 +0100

    remove Try::Tiny from web runtime

commit c746e68b9b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 7 21:54:11 2013 +0100

    make topo autocomplete more responsive

commit 24c511786f
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 7 21:52:17 2013 +0100

    display name and IP for device typeahead

commit 52ab7d1266
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 7 21:47:05 2013 +0100

    add drop-down control for the topo form fields

commit 5744b6845f
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 7 21:25:30 2013 +0100

    complete the topology editor (add/delete)

commit b510fbe8c5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 7 00:59:11 2013 +0100

    add new admin tasks to default plugins list

commit 11d55e0129
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Tue May 7 00:56:19 2013 +0100

    Manual Device Topology

    Needed to add the 'autocomplete' jQuery UI component because
    it can do minLength=0 properly. Used the smoothness UI theme.

    Added typeahead AJAX calls to support the topology searching.

    Added new plugin and template for the topology editing page.

commit bf7a419d08
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 6 22:16:24 2013 +0100

    add a little colour to lone tab titles

commit 9690a31f19
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 6 22:01:13 2013 +0100

    complete Manage Pseudo Devices

commit 024f4d9a83
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 6 00:49:47 2013 +0100

    use bootstrap font colour instead of css

commit f75f1e5cbf
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon May 6 00:45:18 2013 +0100

    add frontend update/del forms, and display port count

commit f0899e16b3
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 23:53:20 2013 +0100

    add frontend pseudo device add form

commit 3271c01931
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 21:45:17 2013 +0100

    complete the code for admin tasks page loading

commit 38f70624f3
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 17:04:30 2013 +0100

    set up file paths consistently in all scripts

commit c761ca839b
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 17:00:30 2013 +0100

    Helper script to import the Netdisco 1.x Topology file to the database

commit f468b48049
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 16:20:39 2013 +0100

    Handle whitespace ahead of OUI data

commit 5c8a5754f6
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 16:16:20 2013 +0100

    also set neighbor info when discovering device interfaces

commit acb988b6af
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 15:34:20 2013 +0100

    try to avoid duplicate execution of scheduled jobs

commit c6bcaf66c5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 14:16:25 2013 +0100

    do not clobber manual topo when discovering neighbors

commit d9a6a1882a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sun May 5 13:02:45 2013 +0100

    User icon color indicates port_control/admin ability

commit 2cdcb9db7e
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Apr 29 23:34:27 2013 +0100

    add support for admin tasks as plugins

commit 075a770c9a
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Apr 29 22:23:20 2013 +0100

    skip pseudo devices (vendor netdisco)

commit 045c022d42
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Mon Apr 29 21:58:33 2013 +0100

    incorporate manual topo info from the topology db table

commit 09285d42b4
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 18:39:12 2013 +0100

    add unique constraints to topology table

commit 2780b72e49
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 15:38:05 2013 +0100

    muted help text in sidebar

commit 733d4f83fb
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:39:54 2013 +0100

    sorry, testing hook changes

commit 71e366e352
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:34:36 2013 +0100

    sorry, testing hook changes

commit 7f9eaa99f5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:33:44 2013 +0100

    sorry, testing hook changes

commit 5215fd632d
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:30:07 2013 +0100

    sorry, testing hook changes

commit be817d60c2
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:21:45 2013 +0100

    sorry, testing hook changes

commit 1fd3695358
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:18:57 2013 +0100

    sorry, testing hook changes

commit ac448c4a91
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:13:03 2013 +0100

    sorry, testing hook changes

commit c563b8d9af
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:08:54 2013 +0100

    sorry, testing hook changes

commit 3abcfb01d5
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:06:25 2013 +0100

    sorry, testing hook changes

commit 877a81facf
Author: Oliver Gorwits <oliver@cpan.org>
Date:   Sat Apr 27 14:05:25 2013 +0100

    sorry, testing hook changes
2013-06-03 20:38:33 +01:00

458 lines
13 KiB
Perl

package App::Netdisco::Core::Macsuck;
use Dancer qw/:syntax :script/;
use Dancer::Plugin::DBIC 'schema';
use App::Netdisco::Util::PortMAC 'get_port_macs';
use App::Netdisco::Util::SanityCheck 'check_mac';
use App::Netdisco::Util::SNMP 'snmp_comm_reindex';
use Time::HiRes 'gettimeofday';
use base 'Exporter';
our @EXPORT = ();
our @EXPORT_OK = qw/
do_macsuck
store_node
store_wireless_client_info
/;
our %EXPORT_TAGS = (all => \@EXPORT_OK);
=head1 NAME
App::Netdisco::Core::Macsuck
=head1 DESCRIPTION
Helper subroutines to support parts of the Netdisco application.
There are no default exports, however the C<:all> tag will export all
subroutines.
=head1 EXPORT_OK
=head2 do_macsuck( $device, $snmp )
Given a Device database object, and a working SNMP connection, connect to a
device and discover the MAC addresses listed against each physical port
without a neighbor.
If the device has VLANs, C<do_macsuck> will walk each VALN to get the MAC
addresses from there.
It will also gather wireless client information if C<store_wireless_client>
configuration setting is enabled.
=cut
sub do_macsuck {
my ($device, $snmp) = @_;
unless ($device->in_storage) {
debug sprintf
' [%s] macsuck - skipping device not yet discovered',
$device->ip;
return;
}
# would be possible just to use now() on updated records, but by using this
# same value for them all, we _can_ if we want add a job at the end to
# select and do something with the updated set (no reason to yet, though)
my $now = 'to_timestamp('. (join '.', gettimeofday) .')';
my $total_nodes = 0;
# do this before we start messing with the snmp community string
store_wireless_client_info($device, $snmp, $now);
# cache the device ports to save hitting the database for many single rows
my $device_ports = {map {($_->port => $_)} $device->ports->all};
my $port_macs = get_port_macs($device);
# get forwarding table data via basic snmp connection
my $fwtable = { 0 => _walk_fwtable($device, $snmp, $port_macs, $device_ports) };
# ...then per-vlan if supported
my @vlan_list = _get_vlan_list($device, $snmp);
foreach my $vlan (@vlan_list) {
snmp_comm_reindex($snmp, $vlan);
$fwtable->{$vlan} = _walk_fwtable($device, $snmp, $port_macs, $device_ports);
}
# now it's time to call store_node for every node discovered
# on every port on every vlan on this device.
# reverse sort allows vlan 0 entries to be included only as fallback
foreach my $vlan (reverse sort keys %$fwtable) {
foreach my $port (keys %{ $fwtable->{$vlan} }) {
if ($device_ports->{$port}->is_uplink) {
debug sprintf
' [%s] macsuck - port %s is uplink, topo broken - skipping.',
$device->ip, $port;
next;
}
debug sprintf ' [%s] macsuck - port %s vlan %s : %s nodes',
$device->ip, $port, $vlan, scalar keys %{ $fwtable->{$vlan}->{$port} };
foreach my $mac (keys %{ $fwtable->{$vlan}->{$port} }) {
# remove vlan 0 entry for this MAC addr
delete $fwtable->{0}->{$_}->{$mac}
for keys %{ $fwtable->{0} };
++$total_nodes;
store_node($device->ip, $vlan, $port, $mac, $now);
}
}
}
debug sprintf ' [%s] macsuck - %s forwarding table entries',
$device->ip, $total_nodes;
$device->update({last_macsuck => \$now});
}
=head2 store_node( $ip, $vlan, $port, $mac, $now? )
Writes a fresh entry to the Netdisco C<node> database table. Will mark old
entries for this data as no longer C<active>.
All four fields in the tuple are required. If you don't know the VLAN ID,
Netdisco supports using ID "0".
Optionally, a fifth argument can be the literal string passed to the time_last
field of the database record. If not provided, it defauls to C<now()>.
=cut
sub store_node {
my ($ip, $vlan, $port, $mac, $now) = @_;
$now ||= 'now()';
schema('netdisco')->txn_do(sub {
my $nodes = schema('netdisco')->resultset('Node');
# TODO: probably needs changing if we're to support VTP domains
my $old = $nodes->search(
{
mac => $mac,
vlan => $vlan,
-bool => 'active',
-not => {
switch => $ip,
port => $port,
},
});
# lock rows,
# and get the count so we know whether to set time_recent
my $old_count = scalar $old->search(undef,
{
columns => [qw/switch vlan port mac/],
order_by => [qw/switch vlan port mac/],
for => 'update',
})->all;
$old->update({ active => \'false' });
my $new = $nodes->search(
{
'me.switch' => $ip,
'me.port' => $port,
'me.mac' => $mac,
},
{
order_by => [qw/switch vlan port mac/],
for => 'update',
});
# lock rows
$new->search({vlan => [$vlan, 0, undef]})->first;
# upgrade old schema
$new->search({vlan => [$vlan, 0, undef]})
->update({vlan => $vlan});
$new->update_or_create({
vlan => $vlan,
active => \'true',
oui => substr($mac,0,8),
time_last => \$now,
($old_count ? (time_recent => \$now) : ()),
});
});
}
# 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 || {};
# 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{$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
++$vlans{$vlan};
$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)';
# FIXME: macsuck_no_vlan
# FIXME: macsuck_no_devicevlan
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 (scalar keys %$i_vlan and not exists $vlans{$vlan}
and not 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 {
my ($device, $snmp, $port_macs, $device_ports) = @_;
my $cache = {};
my $fw_mac = $snmp->fw_mac;
my $fw_port = $snmp->fw_port;
my $fw_vlan = $snmp->qb_fw_vlan;
my $bp_index = $snmp->bp_index;
my $interfaces = $snmp->interfaces;
# to map forwarding table port to device port we have
# fw_port -> bp_index -> interfaces
while (my ($idx, $mac) = each %$fw_mac) {
my $bp_id = $fw_port->{$idx};
next unless check_mac($device, $mac, $port_macs);
unless (defined $bp_id) {
debug sprintf
' [%s] macsuck %s - %s has no fw_port mapping - skipping.',
$device->ip, $mac, $idx;
next;
}
my $iid = $bp_index->{$bp_id};
unless (defined $iid) {
debug sprintf
' [%s] macsuck %s - port %s has no bp_index mapping - skipping.',
$device->ip, $mac, $bp_id;
next;
}
my $port = $interfaces->{$iid};
unless (defined $port) {
debug sprintf
' [%s] macsuck %s - iid %s has no port mapping - skipping.',
$device->ip, $mac, $iid;
next;
}
# TODO: add proper port channel support!
if ($port =~ m/port.channel/i) {
debug sprintf
' [%s] macsuck %s - port %s is LAG member - skipping.',
$device->ip, $mac, $port;
next;
}
# this uses the cached $ports resultset to limit hits on the db
my $device_port = $device_ports->{$port};
unless (defined $device_port) {
debug sprintf
' [%s] macsuck %s - port %s is not in database - skipping.',
$device->ip, $mac, $port;
next;
}
# check to see if the port is connected to another device
# and if we have that device in the database.
# we have several ways to detect "uplink" port status:
# * a neighbor was discovered using CDP/LLDP
# * a mac addr is seen which belongs to any device port/interface
# * (TODO) admin sets is_uplink_admin on the device_port
if ($device_port->is_uplink) {
if (my $neighbor = $device_port->neighbor) {
debug sprintf
' [%s] macsuck %s - port %s has neighbor %s - skipping.',
$device->ip, $mac, $port, $neighbor->ip;
next;
}
elsif (my $remote = $device_port->remote_ip) {
debug sprintf
' [%s] macsuck %s - port %s has undiscovered neighbor %s',
$device->ip, $mac, $port, $remote;
# continue!!
}
else {
debug sprintf
' [%s] macsuck %s - port %s is detected uplink - skipping.',
$device->ip, $mac, $port;
next;
}
}
if (exists $port_macs->{$mac}) {
my $switch_ip = $port_macs->{$mac};
if ($device->ip eq $switch_ip) {
debug sprintf
' [%s] macsuck %s - port %s connects to self - skipping.',
$device->ip, $mac, $port;
next;
}
debug sprintf ' [%s] macsuck %s - port %s is probably an uplink',
$device->ip, $mac, $port;
$device_port->update({is_uplink => \'true'});
# when there's no CDP/LLDP, we only want to gather macs at the
# topology edge, hence skip ports with known device macs.
next unless setting('macsuck_bleed');
}
++$cache->{$port}->{$mac};
}
return $cache;
}
=head2 store_wireless_client_info( $device, $snmp, $now? )
Given a Device database object, and a working SNMP connection, connect to a
device and discover 802.11 related information for all connected wireless
clients.
If the device doesn't support the 802.11 MIBs, then this will silently return.
If the device does support the 802.11 MIBs but Netdisco's configuration
does not permit polling (C<store_wireless_client> must be true) then a debug
message is logged and the subroutine returns.
Otherwise, client information is gathered and stored to the database.
Optionally, a third argument can be the literal string passed to the time_last
field of the database record. If not provided, it defauls to C<now()>.
=cut
sub store_wireless_client_info {
my ($device, $snmp, $now) = @_;
$now ||= 'now()';
my $cd11_txrate = $snmp->cd11_txrate;
return unless $cd11_txrate and scalar keys %$cd11_txrate;
if (setting('store_wireless_client')) {
debug sprintf ' [%s] macsuck - gathering wireless client info',
$device->ip;
}
else {
debug sprintf ' [%s] macsuck - dot11 info available but skipped due to config',
$device->ip;
return;
}
my $cd11_rateset = $snmp->cd11_rateset();
my $cd11_uptime = $snmp->cd11_uptime();
my $cd11_sigstrength = $snmp->cd11_sigstrength();
my $cd11_sigqual = $snmp->cd11_sigqual();
my $cd11_mac = $snmp->cd11_mac();
my $cd11_port = $snmp->cd11_port();
my $cd11_rxpkt = $snmp->cd11_rxpkt();
my $cd11_txpkt = $snmp->cd11_txpkt();
my $cd11_rxbyte = $snmp->cd11_rxbyte();
my $cd11_txbyte = $snmp->cd11_txbyte();
my $cd11_ssid = $snmp->cd11_ssid();
while (my ($idx, $txrates) = each %$cd11_txrate) {
my $rates = $cd11_rateset->{$idx};
my $mac = $cd11_mac->{$idx};
next unless defined $mac; # avoid null entries
# there can be more rows in txrate than other tables
my $txrate = defined $txrates->[$#$txrates]
? int($txrates->[$#$txrates])
: undef;
my $maxrate = defined $rates->[$#$rates]
? int($rates->[$#$rates])
: undef;
schema('netdisco')->txn_do(sub {
schema('netdisco')->resultset('NodeWireless')
->search({ 'me.mac' => $mac })
->update_or_create({
txrate => $txrate,
maxrate => $maxrate,
uptime => $cd11_uptime->{$idx},
rxpkt => $cd11_rxpkt->{$idx},
txpkt => $cd11_txpkt->{$idx},
rxbyte => $cd11_rxbyte->{$idx},
txbyte => $cd11_txbyte->{$idx},
sigqual => $cd11_sigqual->{$idx},
sigstrength => $cd11_sigstrength->{$idx},
ssid => ($cd11_ssid->{$idx} || 'unknown'),
time_last => \$now,
}, {
order_by => [qw/mac ssid/],
for => 'update',
});
});
}
}
1;