#!/usr/bin/perl -w # # EMULAB-COPYRIGHT # Copyright (c) 2000-2002 University of Utah and the Flux Group. # All rights reserved. # use Getopt::Std; # # vlandiff - Show differences between switch state and vlan table, if any # # # Configure variables # $ENV{'PATH'} = '@prefix@/sbin:@prefix@/bin:/bin'; use lib '@prefix@/lib'; use libdb; my %opt = (); getopts('v',\%opt); my $debug = 0; if ($opt{v}) { $debug = 1; } if (@ARGV) { die "Usage: $0 [-v]\n"; } sub debug(@); my %table = (); my %switch= (); my %id = (); # Get all the vlans from the table my $result = DBQueryFatal("select id,members from vlans"); while (@row = $result->fetchrow_array()) { my ($vlan_id, $members) = @row; my @list = split(" ",$members); foreach $port (@list) { my ($node,$card) = split(":",$port); if ($card =~ /[a-zA-Z]/) { # specified ala ethX my $result2 = DBQueryFatal("select card from interfaces ". "where node_id='$node' and iface='$card'"); ($card) = $result2->fetchrow_array(); debug("Had '$port', changed to '$node:$card'\n"); $port = "$node:$card"; } } $table{$vlan_id} = \@list; debug("In table: vlan $vlan_id: $table{$vlan_id}\n"); } # Get all the vlans from the switch my $list; my $vlan=0; open(LIST,"snmpit -l |") || die ("vlandiff: couldn't run snmpit: $!\n"); while() { chop; # Skip heaer lines if (/(^VLAN)|(^--)/) { next; } # Ignore the pid/eid and vlan_name if ( /^(\S+)\s+\S*\s+\S*\s+(.*)$/ ) { my $vlan_id = $1; my $members = $2; debug("VLAN id $vlan_id has members $members\n"); $switch{$vlan_id} = [ split(" ",$members) ]; $vlan = $vlan_id; } elsif ( /^\s+(.*)?$/ ) { # These lines are continuations of multi-line meber lists my $members = $1; if (!defined $members) { $list = ""; } else { $list = $members; } push @{$switch{$vlan}}, split(" ",$list); debug("On switch: vlan $vlan: $switch{$vlan}\n"); } } close(LIST); # Compare all of them... foreach $key (sort keys %table) { if ( defined $switch{$key} ) { # Hacky 'one liner' list comparison if (join("\0",sort(@{$switch{$key}})) eq join("\0",sort(@{$table{$key}}))) { # If its in both lists, delete it from both debug("vlan table:$key ($table{$key}) matches switch:$key ($switch{$key})\n"); delete $switch{$key}; delete $table{$key}; } } } # Print out the difference my $rv = 0; if (keys %table) { print "In vlans table only:\n"; foreach $key(sort keys %table) { print "$key\t", join(" ",@{$table{$key}}), "\n"; } $rv++; } if (keys %switch) { print "On switch only:\n"; foreach $key(sort keys %switch) { print "$key\t", join(" ",@{$switch{$key}}), "\n"; } $rv++; } debug("Exiting with value $rv\n"); # Return 0 if same, 1 for a one-sided diff, 2 for a two-sided diff # (Could be changed to return total # of different vlans) exit($rv); sub debug(@) { if ($debug) { warn @_; } }