Attached is my first try at an OSPF monitoring script meant for use in Mon. It's loosely based on bgp.monitor.
The script walks through your OSPF interface table, and lists all enabled OSPF interfaces and whether you have adjacencies on them. It complains if it finds any interfaces that OSPF has enabled but hasn't been able to form an adjacency. Usage is as follows: ospf.monitor [--exclude regexp] [--community blah] router1 router2 ... Where "router1", "router2", etc. are the routers you are polling, "blah" is the SNMP community, and "regexp" is either a single IP address of an interface to ignore, or a regexp in the form "ip1|ip2|ip3" if you want to ignore multiple interfaces. I was rather surprised when I ran this script on my routers - a few of my routers were trying to start adjacencies on dead interfaces or in other places that they shouldn't have been. Here's a sample output: $ ./ospf.monitor router1 router1 router1 (ID 10.99.99.99) router1: Interface 10.99.37.8.0 state : down [NO ADJACENCY] router1: Interface 10.99.37.9.0 state : pointToPoint router1: Interface 10.99.37.10.0 state : pointToPoint router1: Interface 10.99.37.11.0 state : pointToPoint router1: Interface 10.99.37.12.0 state : down [NO ADJACENCY] router1: Interface 10.99.38.88.0 state : designatedRouter router1: Interface 10.99.38.89.0 state : loopback [NO ADJACENCY] router1: Interface 10.99.38.90.0 state : designatedRouter router1: Interface 10.99.38.91.0 state : designatedRouter For this router, the two "down" links are lines that have been disconnected and I forgot to tell OSPF not to listen on them anymore, and the "loopback" line is a loopback interface that I've incorrectly told OSFP to listen on. The script will also tell you about addressless interfaces that have OSPF enabled - I need to put a bit more code in the script to identify them (currently you just see an ifIndex without explanation). This script is fresh out of the oven, so consider it beta quality or worse - but I'd be pleased if folks with the right environment (Perl and the SNMP_Session module from http://www.switch.ch/misc/leinen/snmp/perl) could give it a spin and let me know what they think of it. It sticks to the RFC1253 OSPF MIB, so it should work on any router, not just Cisco. -- Ed
#!/usr/bin/perl # # Router ospf (Open Shortest Path First) monitor # Look at each router and get the status of all OSPF neighbors. # Issue alarm if any interfaces configured for neighbors do not # have a full adjacencies # Detail log shows status of all enabled OSPF interfaces. # Usage: # ospf.monitor [--exclude pattern] [--community str] router1 [...] # # --exclude - don't alarm for IP addresses that match <pattern>. Periods # in the IP address will be escaped so that they only match periods. Use # [0-9] or the like if you need character class matching. Use 'ip|ip|ip' # to exclude multiple peers. # # --community - SNMPv1 community name to use. But it's more secure # to pass the community in via the environment variable COMMUNITY. # # Edit history below # Version 0.1 # # By Ed Ravin <[EMAIL PROTECTED]> This code is made available courtesy of # PANIX http://www.panix.com. # Copyright 2005, by Ed Ravin # # License: GNU GPL v2, see http://www.gnu.org/copyleft/gpl.html # # Loosely based on bgp.monitor which is: # Copyright 2002, by Marc Hauswirth, Safe Host SA <[EMAIL PROTECTED]> # # Some inspiration is taked from others mon monitors and from # routerinfo.pl by Ben Buxton ([EMAIL PROTECTED]), also under GPL, see http://www.zipworld.com.au/~bb/linux/ # and from routerint.monitor by P. Strauss ([EMAIL PROTECTED]) and me self ([EMAIL PROTECTED]). # # This script need the SNMP Session module from Simon Leinen <[EMAIL PROTECTED]> # Wich you could found under http://www.switch.ch/misc/leinen/snmp/perl/ # It is also part of MRTG (http://people.ee.ethz.ch/~oetiker/webtools/mrtg/) use SNMP; use SNMP_Session; use Getopt::Long; use strict; my %opt; $opt{'community'}= undef; $opt{'exclude'}= ""; $opt{'debug'}= undef; my $usage="Usage: [COMMUNITY=str] ospf.monitor [--exclude regexp] [--community str] router [...]\n"; GetOptions(\%opt, "exclude=s", "community=s", "debug") or die $usage; # It's highly unlikely someone wants dots in an IP address to be treated # as a regexp pattern, so we'll escape them to make behavior more predictable. # If you really want to use pattern matching, use a character class like # [0-9] instead. $opt{'exclude'} =~ s/\./\\./g; $opt{'exclude'}= '^(' . $opt{exclude} . ')'; ## -- my $community = $opt{'community'} || $ENV{'COMMUNITY'} || "public"; ## -- my @failures; my @details; $ENV{'MIBS'}= ""; # all OIDs needed are specified in script # OID's to the SNMP elements that I want to show... # From Cisco's MIB and RFC's # http://sunsite.cnlab-switch.ch/ftp/doc/standard/rfc/16xx/1657 # http://www.telecomm.uh.edu/stats/rfc/BGP4-MIB.html my %oids = ( "SysUptime" => "1.3.6.1.2.1.1.3.0", "ospfRouterId" => "1.3.6.1.2.1.14.1.1" , "ospfIfIpAddress" => "1.3.6.1.2.1.14.7.1.1" , "ospfAddressLessIf" => "1.3.6.1.2.1.14.7.1.2" , "ospfIfAdminStat" => "1.3.6.1.2.1.14.7.1.5" , "ospfIfState" => "1.3.6.1.2.1.14.7.1.12" , ); my %ospfIfStates = ( 1 => "down", 2 => "loopback", 3 => "waiting", 4 => "pointToPoint", 5 => "designatedRouter", 6 => "backupDesignatedRouter", 7 => "otherDesignatedRouter", ); my %ospfAdminStatus = ( 1 => "enabled", 2 => "disabled", ); my %state; my $router; sub snmpget1 # session, oid-hashstr, instance { my $session= shift; my $oidstr= shift; my $instance = shift; my $result= $session->get(".$oids{$oidstr}.$instance"); if ($session->{ErrorNum}) { push @failures, $router; push @details, "$router: error on SNMP get of $oidstr: $session->{ErrorStr}"; return 0; } return $result; } foreach $router (@ARGV) { # Get some infos about this router my $sess = new SNMP::Session ( DestHost => $router, Community => $community ); if (!defined($sess)) { push @failures, $router; push @details, "$router: cannot create SNMP session"; next; } my $ospfRouterID = snmpget1($sess, "ospfRouterId", "0") || next; push @details, "$router (ID $ospfRouterID)"; # Find the indexes of the interfaces with OSPF enabled my @ospfinterfaces; my $vars = new SNMP::VarList([$oids{ospfIfAdminStat}]); for (my @vals = $sess->getnext($vars); $vars->[0]->tag =~ /1\.3\.6\.1\.2\.1\.14\.7\.1\.5/ # still in table (Did you have a cleaner solutions ?) and not $sess->{ErrorStr}; # and not end of mib or other error @vals = $sess->getnext($vars)) { my $textIfAdminStatus = $ospfAdminStatus{$vals[0]}; push @ospfinterfaces, $vars->[0]->tag if $textIfAdminStatus eq "enabled"; } # trim down OID to keep just the interface part, which we will use # shortly as an instance ID map {s/^\.$oids{ospfIfAdminStat}\.//} @ospfinterfaces; foreach my $int (@ospfinterfaces) { my $ifstate = snmpget1($sess, "ospfIfState", "$int"); push @details, sprintf("$router: Interface %-16s state : %-15s",$int, $ospfIfStates{$ifstate}); # if ospfIfState not in [4..7] (OSPF full adjacency states) if ($ifstate < 4 or $ifstate > 7) { push @failures, $router unless $int =~ $opt{exclude} or grep(/$router/, @failures); $details[$#details] .= " [NO ADJACENCY]"; } } } if (@failures) { print join(' ', @failures), "\n"; }; if (@details) { print "\n"; print join("\n", @details), "\n"; } if (@failures) { # Error state exit exit 1; } else { # Correct exit exit 0; };
_______________________________________________ mon mailing list mon@linux.kernel.org http://linux.kernel.org/mailman/listinfo/mon