#!/usr/bin/perl -w # $Id$ $DevMatrix = '../DeviceMatrix.txt'; $DevHTML = 'DeviceMatrix.html'; $DevPNG = 'DeviceMatrix.png'; $Attributes= {}; # Parse Data File $matrix = parse_data($DevMatrix); # Graph it for fun eval "use GraphViz::Data::Structure;"; if ($@) { print "GraphViz::Data::Structure not installed. $@\n"; } else { my %graph = (); foreach my $vendor (sort sort_nocase keys %$matrix){ $graph{$vendor} = {}; foreach my $family (sort sort_nocase keys %{$matrix->{$vendor}->{families}} ){ my @models; foreach my $mod (keys %{$matrix->{$vendor}->{families}->{$family}->{models}}){ push(@models,split(/\s*,\s*/,$mod)); } if (scalar @models){ $graph{$vendor}->{$family}=\@models; } else { $graph{$vendor}->{$family}=[]; } } } my $now = scalar localtime; my $gvds = GraphViz::Data::Structure->new(\%graph,Orientation=>'vertical', Colors=> 'Deep', graph => {label=>"SNMP::Info and Netdisco Supported Devices \n $now",'fontpath'=>'/usr/local/netdisco','fontname'=>'lucon',concentrate=>'true','overlap'=>'false',spline=>'true',bgcolor=>'wheat'}, node => {fontname=>'lucon'}, ); $gvds->graph()->as_png($DevPNG); } print "Creating $DevHTML\n"; open (HTML, "> $DevHTML") or die "Can't open $DevHTML. $!\n"; $old_fh = select(HTML); &html_head; print_vendors($matrix); foreach my $vendor (sort sort_nocase keys %$matrix){ print "$vendor\n"; print "
\n"; my $vendor_defaults = $matrix->{$vendor}->{defaults}; print_notes($vendor_defaults,1); my $families = $matrix->{$vendor}->{families}; foreach my $family (sort sort_nocase keys %$families ) { print "
$family Family\n"; my $family_defaults = $families->{$family}->{defaults}; print_notes($family_defaults,2); my $models = $families->{$family}->{models}; foreach my $model (sort sort_nocase keys %$models ){ my $model_defaults = $models->{$model}->{defaults}; print "
$model\n"; print "
\n"; print_notes($model_defaults,3); print "
\n"; print_headers(); print "\n"; foreach my $a (sort sort_nocase keys %$Attributes) { my $val; next if $a eq 'note'; $val = ['-']; $class = 'none'; if (defined $model_defaults->{$a}) { $val = $model_defaults->{$a}; $class = 'model'; } elsif (defined $family_defaults->{$a}){ $val = $family_defaults->{$a}; $class = 'family'; } elsif (defined $vendor_defaults->{$a}){ $val = $vendor_defaults->{$a}; $class = 'vendor'; } print " \n"; } print "
",join("
\n",@$val),"
\n"; print "
\n"; } } print "
\n"; } &html_tail; select ($old_fh); close (HTML) or die "Can't write $DevHTML. $!\n"; # Data Structures # Matrix = # ( vendor => { families => { family => family_hash }, # defaults => { cmd => [values] }, # } # ) # Family Hash # ( models => { model => model_hash }, # defaults => { cmd => [values] } # ) # Model Hash # ( defaults => { cmd => [values] } ) sub parse_data { my $file = shift; my %ignore = map { $_ => 1 } @_; my $Matrix; my @Lines; open (DM, "< $file") or die "Can't open $file. $!\n"; { @Lines = ; } close (DM); my ($device,$family,$vendor,$class); foreach my $line (@Lines){ chomp($line); # Comments $line =~ s/#.*//; # Blank Lines next if $line =~ /^\s*$/; # Trim whitespace $line =~ s/^\s+//; $line =~ s/\s+$//; my ($cmd,$value); if ($line =~ /^([a-z-_]+)\s*:\s*(.*)$/) { $cmd = $1; $value = $2; } else { print "What do i do with this line : $line \n"; next; } if (exists $ignore{$cmd}){ print "Ignoring $cmd\n"; } # Set Class {vendor,family,device} if ($cmd eq 'device-vendor'){ $vendor = $value; $family = $model = undef; $Matrix->{$vendor} = {} unless defined $Matrix->{$vendor}; $class = $Matrix->{$vendor}; $class->{defaults}->{type}='vendor'; next; } if ($cmd eq 'device-family'){ $family = $value; $model = undef; print "$family has no vendor.\n" unless defined $vendor; $Matrix->{$vendor}->{families}->{$family} = {} unless defined $Matrix->{$vendor}->{families}->{$family}; $class = $Matrix->{$vendor}->{families}->{$family}; $class->{defaults}->{type}='family'; next; } if ($cmd eq 'device') { $model = $value; print "$model has no family.\n" unless defined $family; print "$model has no vendor.\n" unless defined $vendor; $Matrix->{$vendor}->{families}->{$family}->{models}->{$model} = {} unless defined $Matrix->{$vendor}->{families}->{$family}->{models}->{$model}; $class = $Matrix->{$vendor}->{families}->{$family}->{models}->{$model}; $class->{defaults}->{type}='device'; next; } # Store attribute push (@{$class->{defaults}->{$cmd}} , $value); $Attributes->{$cmd}++; } return $Matrix; } sub sort_nocase { return lc($a) cmp lc($b); } sub print_notes { my $defaults = shift; my $level = shift; my $notes = $defaults->{note} || []; foreach my $note (@$notes){ if ($note =~ s/^!//){ $note = '' . $note . ''; } } if (scalar @$notes){ print "
\n"; my $print_note = join("\n
  • ",@$notes); print "
    • $print_note
    \n"; } } sub print_vendors { my $matrix=shift; print "

    Device Vendors

    \n"; foreach my $vendor (sort sort_nocase keys %$matrix){ print "[$vendor]\n"; } print "
    \n"; } sub html_head { print <<"end_head"; SNMP::Info - Device Compatibility Matrix

    SNMP::Info - Device Compatibility Matrix

    end_head } sub html_tail { print <<'end_tail';


    Color Key

    [Model Attribute] [Family Attribute] [Vendor Attribute]

    Attribute Key

    A value of - signifies the information is not specified and can not be assumed working.
    Arpnip Ability to collect ARP tables for MAC to IP translation.
    Class SNMP::Info Class the the device currently uses. Devices using more generic interfaces like Layer2 or Layer3 may eventually get their own subclass.
    Duplex Ability to cull duplex settings from device.
    • no - Can't recover current or admin setting.
    • link - Can get current setting only.
    • both - Can get admin and link setting.
    • write - Can get admin and link setting and perform sets.
    Macsuck Ability to get CAM tables for MAC to switch port mapping.
    • no - Have not found an SNMP method to get data yet.
    • yes - Can get through normal SWITCH-MIB method.
    • vlan - Have to re-connect to each VLAN and then fetch with normal method.
    Modules Ability to gather hardware module information.
    Portmac Whether the device will list the MAC address of the switch port on each switch port when doing a Macsuck.
    Topo Ability to get Layer 2 Topology Information from device if the protocol is enabled. SNMP::Info supports querying Link Layer Discovery Protocol (LLDP), Cisco Discovery Protocol (CDP), SynOptics/Bay/Nortel/Avaya Network Management Protocol (SONMP), Foundry/Brocade Discovery Protocol (FDP), Extreme Discovery Protocol (EDP), and Alcatel Mapping Adjacency Protocol (AMAP).
    Ver SNMP Protocol Version the device has to use.
    Vlan Ability to get VLAN port assignments.
    • no - Have not found an SNMP method to get data yet.
    • yes - Can read information.
    • write - Can read and write (set).
    end_tail } sub print_headers { print "\n"; foreach my $a (sort sort_nocase keys %$Attributes) { next if $a eq 'note'; print " $a\n"; } print "\n"; }