X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=snmp-topology.pl;h=3db868a77df0168e4e06fbb554abd14c29db6504;hb=HEAD;hp=327177dc2a11af38ee721df7e12a14cf55b90e88;hpb=04fda611c3477b7b909a70f0506bcd224edeca40;p=dell-switch diff --git a/snmp-topology.pl b/snmp-topology.pl index 327177d..3db868a 100755 --- a/snmp-topology.pl +++ b/snmp-topology.pl @@ -22,10 +22,14 @@ sub macfmt { foreach my $file ( @dumps ) { + my $lines = 0; + my $ignored = 0; + open(my $fh, '<', $file); my $sw = $file; $sw =~ s/^.*\///; while(<$fh>) { chomp; + $lines++; if ( m/^SNMPv2-MIB::(sysName|sysDescr)\.0 = STRING: (.+)/ ) { $stat->{$sw}->{$1} = $2; =for xxx @@ -39,21 +43,33 @@ foreach my $file ( @dumps ) { #warn "# $sw ",dump($name,$oid,$i,$type,$value),$/; #$stat->{$sw}->{$name}->{$oid}->[$i] = $value; $stat->{_mac2sw}->{$value} = $sw; + $stat->{_sw_mac_count}->{$sw}++; } elsif ( m/^BRIDGE-MIB::dot1dTpFdbPort\[STRING: ([^\]]+)\] = INTEGER: (\d+)/ ) { my ( $mac, $port ) = ($1,$2); push @{ $stat->{_sw_mac_port_vlan}->{$sw}->{$mac}->{$port} }, ''; + #$stat->{_sw_port_vlan_count}->{$sw}->{$port}->{''}++; + $stat->{_sw_port_mac_count}->{$sw}->{$port}++; } elsif ( m/^Q-BRIDGE-MIB::dot1qTpFdbPort\[(\d+)\]\[STRING: ([^\]]+)\] = INTEGER: (\d+)/ ) { my ( $vlan, $mac, $port ) = ($1,$2,$3); push @{ $stat->{_sw_mac_port_vlan}->{$sw}->{$mac}->{$port} }, $vlan; + #$stat->{_sw_port_vlan_count}->{$sw}->{$port}->{$vlan}++; + $stat->{_sw_port_mac_count}->{$sw}->{$port}++; + } else { + $ignored++; } } #warn "# $sw ",dump( $stat->{$sw} ); + warn "## $file $lines / $ignored ignored"; } -#warn "# stat = ",dump($stat); +warn "# stat = ",dump($stat); +#warn "# _sw_port_vlan_count = ",dump($stat->{_sw_port_vlan_count}); +warn "# _sw_port_mac_count = ",dump($stat->{_sw_port_mac_count}); open(my $fh, '>', '/dev/shm/mac2sw'); +open(my $fh2, '>', '/dev/shm/mac2sw.snmp'); foreach my $mac ( keys %{ $stat->{_mac2sw} } ) { print $fh macfmt($mac), " ", $stat->{_mac2sw}->{$mac}, "\n"; + print $fh $mac, " ", $stat->{_mac2sw}->{$mac}, "\n"; }; # XXX inject additional mac in filter to include wap devices @@ -66,9 +82,12 @@ if ( -e $mac_include ) { 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; + $count++; } # warn "# $mac_include added to _mac2sw = ",dump($stat->{_mac2sw}),$/; warn "# $mac_include added to _mac2sw $count hosts\n"; +} else { + warn "MISSING $mac_include\n"; } my $s = $stat->{_sw_mac_port_vlan}; @@ -79,18 +98,51 @@ foreach my $sw ( keys %$s ) { foreach my $port ( keys %{ $s->{$sw}->{$mac} } ) { #$stat->{_sw_port_sw}->{$sw}->{$port}->{$mac_name} = $s->{$sw}->{$mac}->{$port}; push @{ $stat->{_sw_port_sw}->{$sw}->{$port} }, $mac_name; + push @{ $stat->{_sw_sw_port}->{$sw}->{$mac_name} }, $port; } } } } warn "# _sw_port_sw = ",dump($stat->{_sw_port_sw}); +warn "# _sw_sw_port = ",dump($stat->{_sw_sw_port}); my $s = $stat->{_sw_port_sw}; our $later; my $last_later; +our @single_sw_port_visible; +sub single_sw_port_visible { + @single_sw_port_visible = (); + my $s = {}; + foreach my $sw ( keys %$later ) { + if ( exists $stat->{_found}->{$sw} ) { + my @d = delete $later->{$sw}; + warn "REMOVED $sw from later it's _found! later was = ",dump( \@d ); + next; + } + my @ports = sort keys %{ $later->{$sw} }; + foreach my $port ( @ports ) { + my @visible = uniq_visible( @{ $later->{$sw}->{$port} } ); + if ( $#visible < 0 ) { + warn "REMOVED $sw $port from later it's empty"; + delete $later->{$sw}->{$port}; + next; + } + $s->{$sw}->{$port} = [ @visible ]; + push @single_sw_port_visible, [ $sw, $port, $visible[0] ] if $#visible == 0; # single + } + } + my $d_s = dump($s); + my $d_l = dump($later); + if ( $d_s ne $d_l ) { + $later = $s; + warn "# single_sw_port_visible = ",dump( \@single_sw_port_visible ); + warn "# reduced later = ",dump( $later ); + } +} + sub uniq { my @visible = @_; my $u; $u->{$_}++ foreach @visible; @@ -127,7 +179,7 @@ foreach my $sw ( sort keys %$s ) { if ( $#ports == 0 ) { my $port = $ports[0]; - #print "$sw $port TRUNK\n"; + print "$sw $port TRUNK\n"; push @{$stat->{_trunk}->{$sw}}, $port; # FIXME multiple trunks? #warn "## _trunk = ",dump( $stat->{_trunk} ).$/; @@ -144,11 +196,13 @@ foreach my $sw ( sort keys %$s ) { warn "++++ $sw $port $visible[0]\n"; #print "$sw $port $visible[0]\n"; $stat->{_found}->{$visible[0]} = "$sw $port"; - - } elsif ( @visible ) { + single_sw_port_visible(); + + } elsif ( $#visible > 0 ) { to_later( $sw, $port, @visible ); } else { - warn "#### $sw $port doesn't have anything visible\n"; + warn "#### $sw $port doesn't have anything visible, reseting visibility\n"; + to_later( $sw, $port, @{ $stat->{_sw_port_sw}->{$sw}->{$port} } ); } } @@ -156,51 +210,59 @@ foreach my $sw ( sort keys %$s ) { } warn "NEXT later = ",dump($later),$/; -#$s = $later; - -my @single_sw_port_visible; +single_sw_port_visible(); -UNIQUE_LATER: -# remove all found -$s = {}; - -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); +my $d = dump($later); if ( $d eq $last_later ) { 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 ) { + while ( @single_sw_port_visible ) { + my $single = shift @single_sw_port_visible; my ( $sw, $port, $visible ) = @$single; - foreach my $port ( keys %{ $s->{$visible} } ) { + warn "XXX $sw | $port | $visible\n"; + + foreach my $port ( keys %{ $later->{$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}; + + my @d = delete $later->{$visible}->{$port}; + warn "DELETED $visible $port ",dump(@d); $did_patch++; - $d = dump($s); - warn "PATCHED _found = ", dump($stat->{_found}); - warn "PATCHED s = $d\n"; - $later = $s; - goto UNIQUE_LATER; + + single_sw_port_visible(); } else { - die "fatal inconsistency - dungeon colapses, you die"; + warn "FATAL $visible $port NO $sw IN ",dump( \@visible ); } } + + if ( ! $did_patch ) { + # OK, we have link from trunk probably, which port was originally visible on? + + foreach my $port ( keys %{ $stat->{_sw_port_sw}->{$visible} } ) { + my @visible = grep /$sw/, @{ $stat->{_sw_port_sw}->{$visible}->{$port} }; + if ( scalar @visible ) { + warn "PATCH-2 $visible $port -> $sw\n"; + $stat->{_found}->{$sw} = "$visible $port"; + + my @d = delete $later->{$visible}->{$port}; + warn "DELETED $visible $port ",dump(@d); + $did_patch++; + + single_sw_port_visible(); + } else { + warn "FATAL $visible $port _sw_port_sw doesn't have $sw"; + } + } + } + } + warn "## applied $did_patch patches to unblock\n"; last if $d eq $last_later; @@ -239,6 +301,7 @@ foreach my $to_sw ( keys %{ $stat->{_found} } ) { my @to_port = uniq(@{ $stat->{_trunk}->{$to_sw} }); my $to_port = $to_port[0]; warn "ERROR: $to_sw has ",dump(\@to_port), " ports instead of just one!" if $#to_port > 0; + no warnings; printf "%s %s -> %s %s\n", $from_sw, $from_port, $to_sw, $to_port; push @edges, [ $from_sw, $to_sw, $from_port, $to_port ]; push @{ $node->{$from_sw} }, [ $from_port, $to_sw ]; @@ -250,6 +313,7 @@ warn "# node = ",dump($node); if ( $ports ) { foreach my $n ( keys %$node ) { + no warnings; my @port_sw = sort { $a->[0] <=> $b->[0] } @{ $node->{$n} }; @@ -262,6 +326,7 @@ foreach my $e ( @edges ) { if (! $ports) { print $dot sprintf qq{ "%s" -> "%s" [ taillabel="%s" ; headlabel="%s" ]\n}, @$e; } else { + no warnings; print $dot sprintf qq{ "%s":%d -> "%s":%d\n}, $e->[0], $e->[2], $e->[1], $e->[3]; } }