Skip to content

Commit

Permalink
Initial version of node_ip_l3device patch
Browse files Browse the repository at this point in the history
 * allows tracking of L3 device arp origin
 * new table and schema object for node_ip_l3device
 * Arpnip.pm and netdisco-sshcollector support
 * usage is enable through arpnip_track_l3device setting
 * more info in https://github.com/rc9000/nd2_private_patches/wiki
  • Loading branch information
rc9000 committed Nov 10, 2016
1 parent d311d1a commit f0b7bc8
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 8 deletions.
6 changes: 3 additions & 3 deletions Netdisco/bin/netdisco-sshcollector
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ sub main {
$stats{host}++;
info sprintf ' [%s] arpnip - retrieved %s entries',
$host->[0], scalar @{$host->[1]};
store_arpentries($host->[1]);
store_arpentries($host->[0], $host->[1]);
}

info sprintf 'arpnip - processed %s ARP Cache entries from %s devices',
Expand Down Expand Up @@ -140,15 +140,15 @@ sub process {
}

sub store_arpentries {
my ($arpentries) = @_;
my ($device_ip, $arpentries) = @_;

foreach my $arpentry ( @$arpentries ) {
# skip broadcast/vrrp/hsrp and other wierdos
next unless check_mac( undef, $arpentry->{mac} );

debug sprintf ' arpnip - stored entry: %s / %s',
$arpentry->{mac}, $arpentry->{ip};
store_arp({
store_arp($device_ip, {
node => $arpentry->{mac},
ip => $arpentry->{ip},
dns => $arpentry->{dns},
Expand Down
63 changes: 59 additions & 4 deletions Netdisco/lib/App/Netdisco/Core/Arpnip.pm
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@ sub do_arpnip {
my $now = 'to_timestamp('. (join '.', gettimeofday) .')';

# update node_ip with ARP and Neighbor Cache entries
store_arp(\%$_, $now) for @$v4;
store_arp($device->ip, \%$_, $now) for @$v4;
debug sprintf ' [%s] arpnip - processed %s ARP Cache entries',
$device->ip, scalar @$v4;

store_arp(\%$_, $now) for @$v6;
store_arp($device->ip, \%$_, $now) for @$v6;
debug sprintf ' [%s] arpnip - processed %s IPv6 Neighbor Cache entries',
$device->ip, scalar @$v6;

Expand Down Expand Up @@ -97,7 +97,7 @@ sub _get_arps {
return $resolved_ips;
}

=head2 store_arp( \%host, $now? )
=head2 store_arp($device_ip, \%host, $now? )
Stores a new entry to the C<node_ip> table with the given MAC, IP (v4 or v6)
and DNS host name. Host details are provided in a Hash ref:
Expand All @@ -116,13 +116,15 @@ C<time_last> timestamp, otherwise the current timestamp (C<now()>) is used.
=cut


sub store_arp {
my ($hash_ref, $now) = @_;
my ($device_ip, $hash_ref, $now) = @_;
$now ||= 'now()';
my $ip = $hash_ref->{'ip'};
my $mac = NetAddr::MAC->new($hash_ref->{'node'});
my $name = $hash_ref->{'dns'};


return if !defined $mac or $mac->errstr;

schema('netdisco')->txn_do(sub {
Expand All @@ -144,9 +146,62 @@ sub store_arp {
key => 'primary',
for => 'update',
});

if (setting('arpnip_track_l3device')){

# device_ip could actually be a hostname when passed from e.g. sshcollector
# so we try to resolve it and use this value if necessary
my $device_ip_resolved = ipv4_from_hostname($device_ip);

schema('netdisco')->resultset('NodeIpL3device')
->update_or_create(
{
node_mac => $mac->as_ieee,
node_ip => $ip,
device_ip => $device_ip_resolved ? $device_ip_resolved : $device_ip,
time_last => \$now,
},
{
key => 'primary',
for => 'update',
});

}
});
}


#sub store_arp {
# my ($hash_ref, $now) = @_;
# $now ||= 'now()';
# my $ip = $hash_ref->{'ip'};
# my $mac = NetAddr::MAC->new($hash_ref->{'node'});
# my $name = $hash_ref->{'dns'};
#
# return if !defined $mac or $mac->errstr;
#
# schema('netdisco')->txn_do(sub {
# my $current = schema('netdisco')->resultset('NodeIp')
# ->search(
# { ip => $ip, -bool => 'active'},
# { columns => [qw/mac ip/] })->update({active => \'false'});
#
# schema('netdisco')->resultset('NodeIp')
# ->update_or_create(
# {
# mac => $mac->as_ieee,
# ip => $ip,
# dns => $name,
# active => \'true',
# time_last => \$now,
# },
# {
# key => 'primary',
# for => 'update',
# });
# });
#}

# gathers device subnets
sub _gather_subnets {
my ($device, $snmp) = @_;
Expand Down
2 changes: 1 addition & 1 deletion Netdisco/lib/App/Netdisco/DB.pm
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ __PACKAGE__->load_namespaces(
);

our # try to hide from kwalitee
$VERSION = 41; # schema version used for upgrades, keep as integer
$VERSION = 42; # schema version used for upgrades, keep as integer

use Path::Class;
use File::Basename;
Expand Down
102 changes: 102 additions & 0 deletions Netdisco/lib/App/Netdisco/DB/Result/NodeIpL3device.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
use utf8;
package App::Netdisco::DB::Result::NodeIpL3device;

# Created by DBIx::Class::Schema::Loader
# DO NOT MODIFY THE FIRST PART OF THIS FILE

=head1 NAME
App::Netdisco::DB::Result::NodeIpL3device
=cut

use strict;
use warnings;

use base 'DBIx::Class::Core';

=head1 TABLE: C<node_ip_l3device>
=cut

__PACKAGE__->table("node_ip_l3device");

=head1 ACCESSORS
=head2 node_mac
data_type: 'macaddr'
is_nullable: 0
=head2 node_ip
data_type: 'inet'
is_nullable: 0
=head2 device_ip
data_type: 'inet'
is_nullable: 0
=head2 time_first
data_type: 'timestamp'
default_value: current_timestamp
is_nullable: 1
original: {default_value => \"now()"}
=head2 time_last
data_type: 'timestamp'
default_value: current_timestamp
is_nullable: 1
original: {default_value => \"now()"}
=cut

__PACKAGE__->add_columns(
"node_mac",
{ data_type => "macaddr", is_nullable => 0 },
"node_ip",
{ data_type => "inet", is_nullable => 0 },
"device_ip",
{ data_type => "inet", is_nullable => 0 },
"time_first",
{
data_type => "timestamp",
default_value => \"current_timestamp",
is_nullable => 1,
original => { default_value => \"now()" },
},
"time_last",
{
data_type => "timestamp",
default_value => \"current_timestamp",
is_nullable => 1,
original => { default_value => \"now()" },
},
);

=head1 PRIMARY KEY
=over 4
=item * L</node_mac>
=item * L</node_ip>
=item * L</device_ip>
=back
=cut

__PACKAGE__->set_primary_key("node_mac", "node_ip", "device_ip");


# Created by DBIx::Class::Schema::Loader v0.07046 @ 2016-11-09 23:03:08
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:eTQlbkByATRqTPO3W8Rosg


# You can replace this text with custom code or comments, and it will be preserved on regeneration
1;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
BEGIN;

CREATE TABLE node_ip_l3device
(
node_mac macaddr NOT NULL,
node_ip inet NOT NULL,
device_ip inet NOT NULL,
time_first timestamp without time zone DEFAULT now(),
time_last timestamp without time zone DEFAULT now(),
CONSTRAINT node_ip_l3device_pkey PRIMARY KEY (node_mac, node_ip, device_ip)
)
WITH (
OIDS=FALSE
);
ALTER TABLE node_ip_l3device
OWNER TO netdisco;

COMMIT;
8 changes: 8 additions & 0 deletions Netdisco/lib/App/Netdisco/Manual/Configuration.pod
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,14 @@ Value: Number. Default: 0.
Sets the minimum amount of time in seconds which must elapse between any two
arpnip jobs for a device.

=head3 C<arpnip_track_l3device>

Value: Boolean. Default: C<false>.

If true, arpnip and sshcollector arp discover will populate the table
C<node_ip_l3device> with the tupple C<device_ip, node_ip, node_mac>. This
allows to recreate where ARP entries come from.

=head3 C<nbtstat_no>

Value: List of Network Identifiers. Default: Empty List.
Expand Down

0 comments on commit f0b7bc8

Please sign in to comment.