resolve first halting case
[dell-switch] / snmp-topology.pl
index 9973442..327177d 100755 (executable)
@@ -5,7 +5,7 @@ use autodie;
 
 use Data::Dump qw(dump);
 
-my $dir="/dev/shm/snmpbulkwalk";
+my $dir="/dev/shm/snmp-topology";
 
 my $stat;
 
@@ -56,6 +56,21 @@ foreach my $mac ( keys %{ $stat->{_mac2sw} } ) {
        print $fh macfmt($mac), " ", $stat->{_mac2sw}->{$mac}, "\n";
 };
 
+# XXX inject additional mac in filter to include wap devices
+my $mac_include = '/dev/shm/mac.wap';
+if ( -e $mac_include ) {
+       my $count = 0;
+       open(my $fh, '<', $mac_include);
+       while(<$fh>) {
+               chomp;
+               my ($mac,$host) = split(/\s+/,$_,2);
+               $mac =~ s/^0//; $mac =~ s/:0/:/g; # mungle mac to snmp format without leading zeros
+               $stat->{_mac2sw}->{$mac} = $host;
+       }
+#      warn "# $mac_include added to _mac2sw = ",dump($stat->{_mac2sw}),$/;
+       warn "# $mac_include added to _mac2sw $count hosts\n";
+}
+
 my $s = $stat->{_sw_mac_port_vlan};
 foreach my $sw ( keys %$s ) {
        foreach my $mac ( keys %{ $s->{$sw} } ) {
@@ -93,7 +108,7 @@ sub to_later {
        my $sw = shift;
        my $port = shift;
        my @visible = uniq_visible(@_);
-       warn "# to_later $sw $port visible = ", $#visible + 1, "\n";
+       warn "# to_later $sw $port visible = ",dump( \@visible ),"\n";
        $later->{$sw}->{$port} = [ @visible ];
        return @visible;
 }
@@ -109,6 +124,7 @@ foreach my $sw ( sort keys %$s ) {
        foreach my $port ( @ports ) {
                warn "## $sw $port => ",join(' ', @{$s->{$sw}->{$port}}),$/;
        }
+
        if ( $#ports == 0 ) {
                my $port = $ports[0];
                #print "$sw $port TRUNK\n";
@@ -140,12 +156,55 @@ foreach my $sw ( sort keys %$s ) {
 }
 
 warn "NEXT later = ",dump($later),$/;
-$s = $later;
+#$s = $later;
+
+
+my @single_sw_port_visible;
+
+UNIQUE_LATER:
+# remove all found
+$s = {};
 
-my $d = dump($later);
+foreach my $sw ( keys %$later ) {
+       my @ports = sort keys %{ $later->{$sw} };
+       foreach my $port ( @ports ) {
+               my @visible = uniq_visible( @{ $later->{$sw}->{$port} } );
+               $s->{$sw}->{$port} = [ @visible ];
+               push @single_sw_port_visible, [ $sw, $port, $visible[0] ] if $#visible == 0; # single
+       }
+}
+$later = $s;
+
+my $d = dump($s);
 if ( $d eq $last_later ) {
-       warn "FIXME later didn't change, last\n";
-       last;
+       warn "FIXME later didn't change single_sw_port_visible = ",dump( \@single_sw_port_visible ),$/;
+
+       my $did_patch = 0;
+
+       foreach my $single ( @single_sw_port_visible ) {
+               my ( $sw, $port, $visible ) = @$single;
+               foreach my $port ( keys %{ $s->{$visible} } ) {
+                       # check back in original full map to see if it was visible
+                       my @visible = @{ $stat->{_sw_port_sw}->{$visible}->{$port} };
+                       if ( scalar grep(/$sw/,@visible) ) {
+                               warn "PATCH $visible $port -> $sw ONLY";
+                               $stat->{_found}->{$sw} = "$visible $port";
+                               delete $s->{$visible}->{$port};
+                               $did_patch++;
+                               $d = dump($s);
+                               warn "PATCHED _found = ", dump($stat->{_found});
+                               warn "PATCHED s = $d\n";
+                               $later = $s;
+                               goto UNIQUE_LATER;
+                       } else {
+                               die "fatal inconsistency - dungeon colapses, you die";
+                       }
+               }
+       }
+       warn "## applied $did_patch patches to unblock\n";
+
+       last if $d eq $last_later;
+       
 }
 $last_later = $d;
 
@@ -155,18 +214,19 @@ $later = undef;
 
 warn "FINAL _found = ",dump( $stat->{_found} ),$/;
 warn "FINAL _trunk = ",dump( $stat->{_trunk} ),$/;
+warn "FINAL later  = ",dump( $later ),$/;
 
 
 my $node;
 my @edges;
 
-my $ports = $ENV{PORTS} || 0; # FIXME
+my $ports = $ENV{PORTS} || 1; # FIXME
 
 
 open(my $dot, '>', '/tmp/snmp-topology.dot');
 
 my $shape = $ports ? 'record' : 'ellipse';
-my $rankdir = $ports ? 'TB' : 'LR';
+my $rankdir = 'LR'; #$ports ? 'TB' : 'LR';
 print $dot <<"__DOT__";
 digraph topology {
 graph [ rankdir = $rankdir ]
@@ -191,10 +251,10 @@ warn "# node = ",dump($node);
 if ( $ports ) {
        foreach my $n ( keys %$node ) {
                my @port_sw =
-                       sort { $a->[0] <=> $b->[1] }
+                       sort { $a->[0] <=> $b->[0] }
                        @{ $node->{$n} };
-warn "XXX $n ",dump( \@port_sw );
-               print $dot qq!"$n" [ label="*$n*|! . join('|', map { sprintf "<%d>%2d %s", $_->[0], $_->[0], $_->[1] } @port_sw ) . qq!" ];\n!;
+#warn "XXX $n ",dump( \@port_sw );
+               print $dot qq!"$n" [ label="!.uc($n).'|' . join('|', map { sprintf "<%d>%2d %s", $_->[0], $_->[0], $_->[1] } @port_sw ) . qq!" ];\n!;
        }
 }