parse snmpbulkwalk and update local on-disk copy
authorDobrica Pavlinusic <dpavlin@rot13.org>
Wed, 6 Apr 2022 16:43:23 +0000 (18:43 +0200)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Wed, 6 Apr 2022 16:43:23 +0000 (18:43 +0200)
sbw-parse.pl [new file with mode: 0755]

diff --git a/sbw-parse.pl b/sbw-parse.pl
new file mode 100755 (executable)
index 0000000..6f75223
--- /dev/null
@@ -0,0 +1,140 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use autodie;
+
+# ./sw-name-mac.sh
+
+use Data::Dump qw(dump);
+
+my $debug = $ENV{DEBUG} || 0;
+
+my @cols = qw( ifName ifHighSpeed ifAdminStatus ifOperStatus ifType dot1dStpPortPathCost ifAlias );
+
+my $mac2name;
+
+open(my $f, '<'. '/dev/shm/sw-name-mac');
+while(<$f>) {
+       chomp;
+       #my ( $ip, $name, $mac ) = split(/ /,$_);
+       my ( $name, $mac ) = split(/ /,$_);
+       $mac = lc($mac);
+       $mac2name->{$mac} = $name;
+}
+
+sub mac2name {
+       my ( $mac, $name ) = @_;
+
+       $mac = lc($mac);
+
+       if ( exists $mac2name->{$mac} ) {
+               my $mac_name = $mac2name->{$mac};
+               warn "ERROR: name different $name != $mac_name" if $name && $name ne $mac_name;
+               return ( $mac, $mac_name );
+       }
+       return ( $mac, $name );
+}
+
+warn "# mac2name = ",dump($mac2name) if $debug;
+
+
+my $sw;
+
+sub fix_mac {
+       my $mac = shift;
+       $mac = lc($mac);
+       $mac =~ s/^([0-9a-f]):/0$1:/;
+       while ( $mac =~ s/:([0-9a-f]):/:0$1:/g ) {};
+       $mac =~ s/:([0-9a-f])$/:0$1/;
+#      warn "# $mac\n";
+       return $mac;
+}
+
+sub sw_name_mac_port {
+       my ( $name, $mac, $port ) = @_;
+       $mac = fix_mac($mac);
+       if ( exists $mac2name->{$mac} ) {
+               my $sw_name = $mac2name->{$mac};
+               $sw->{$name}->{port_for_switch}->{$port}->{ $sw_name }++;
+               #print "## $name $port $sw_name\n";
+       }
+}
+
+my @files = @ARGV;
+@files = glob('snmpbulkwalk/*') unless @files;
+
+foreach my $file ( @files ) {
+       my ( undef, $name ) = split(/\//, $file);
+       print "# $name $file\n" if $debug;
+
+       if ( -s "/dev/shm/$file" ) {
+               if ( -M $file < -M "/dev/shm/$file" ) {
+                       warn "UPDATE $file\n";
+                       system "cp -pv /dev/shm/$file $file";
+               }
+               $file="/dev/shm/$file";
+       } else {
+               warn "WARNING: using old file $file\n";
+       }
+
+       open(my $f, '<', $file);
+       while(<$f>) {
+               chomp;
+               if ( m/::(sysName|sysLocation|ipDefaultTTL|dot1dStpPriority|dot1dStpTopChanges|dot1dStpDesignatedRoot|dot1dStpRootCost|dot1dStpRootPort|dot1qNumVlans)\./ ) {
+                       my ( undef, $v ) = split(/ = \w+: /,$_,2);
+                       $sw->{$name}->{$1} = $v;
+               } elsif ( m/::(ifMtu|ifHighSpeed)\[(\d\d?)\] = (?:INTEGER|Gauge32): (\d+)/ ) {
+                       $sw->{$name}->{$1}->[$2] = $3;
+               } elsif ( m/::(ifPhysAddress)\[(\d\d?)\] = STRING: ([0-9a-f:]+)/ ) {
+                       $sw->{$name}->{$1}->[$2] = fix_mac($3);
+               } elsif ( m/::(ifName|ifAlias)\[(\d\d?)\] = STRING: (.+)/ ) {
+                       $sw->{$name}->{$1}->[$2] = $3;
+               } elsif ( m/::(ifAdminStatus|ifOperStatus|ifType|dot3StatsDuplexStatus)\[(\d\d?)\] = INTEGER: (\w+)\(/ ) {
+                       $sw->{$name}->{$1}->[$2] = $3;
+               } elsif ( m/::(dot1dStpPortPathCost)\[(\d\d?)\] = INTEGER: (\d+)/ ) {
+                       $sw->{$name}->{$1}->[$2] = $3;
+               } elsif ( m/::(dot1dTpFdbPort)\[STRING: ([0-9a-f:]+)\] = INTEGER: (\d+)/ ) {
+                       $sw->{$name}->{$1}->{ fix_mac($2) } = $3;
+                       sw_name_mac_port( $name, $2, $3 );
+               } elsif ( m/::(dot1qTpFdbPort)\[(\d+)\]\[STRING: ([0-9a-f:]+)\] = INTEGER: (\d+)/ ) {
+                       $sw->{$name}->{$1}->{ fix_mac($3) } = [ $4, $2 ]; # port, vlan
+                       sw_name_mac_port( $name, $3, $4 );
+               }
+
+               # dot1qVlanCurrentEgressPorts
+               # dot1qVlanCurrentUntaggedPorts
+               # dot1qVlanStaticName
+               # dot1qVlanStaticEgressPorts
+               # dot1qVlanStaticUntaggedPorts
+               # dot1qPvid
+
+               # entPhysicalDescr
+               # entPhysicalClass
+
+               #print "## $_<--\n";
+       }
+       warn "# sw $name = ",dump($sw->{$name}) if $debug;
+
+       foreach my $port ( 1 .. $#{ $sw->{$name}->{ifName} } ) {
+               print "$name $port";
+               foreach my $oid ( @cols ) {
+                       if ( $oid eq 'ifAlias' ) {
+                               if ( defined( $sw->{$name}->{$oid}->[$port] ) ) {
+                                       print " [",$sw->{$name}->{$oid}->[$port],"]";
+                               }
+                       } elsif ( defined $sw->{$name}->{$oid}->[$port] ) {
+                               print " ", $sw->{$name}->{$oid}->[$port];
+                       } else {
+                               print " ?";
+                               #warn "MISSING $name $oid $port\n";
+                       }
+
+               }
+               if ( exists( $sw->{$name}->{port_for_switch}->{ $port } ) ) {
+                       print " ",join(',', sort keys %{ $sw->{$name}->{port_for_switch}->{ $port } } );
+               }
+               print "\n";
+       }}
+
+# fix ifPhysAddress
+