Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Juniper full-mesh latency measurements (using DISMAN PING MIB)

by smullis (Pilgrim)
on Nov 08, 2004 at 11:10 UTC ( #406024=CUFP: print w/ replies, xml ) Need Help??

UPDATE

Found a couple of errors in the script (I had posted an old version...)




Below you'll find a small script that sets up / outputs latency information for a list of Juniper routers (although this will also work with Extreme Networks kit too (and maybe some Cisco kit)).

Using this provides full-mesh latency data... (Which is darned useful.)

Interestingly - or not! - this script is the reason I'm working on my Perl at the moment. I originally wrote it in BASH but found that the performance was appalling. It took around 30 seconds to complete. Now, in Perl it completes in less than a second.

Woohooo!

You need to make sure you do the following to allow remote SNMP RW access to the relevant OID subtrees.

view remote-view { oid .1.3.6.1.2.1.80 include; oid .1.3.6.1.4.1.2636.3.7 include; oid .1.3.6.1.2.1.81 include; oid .1.3.6.1.4.1.2636.3.8 include; } community COMMNUNITY_STRING { view remote-view; authorization read-write; clients { x.x.x.x/32; y.y.y.y/32; } }

And here it is:

As it's pretty implementation dependent I'll split it into the functional segments...

#!/usr/bin/perl -w #===================================================================== +========== # # FILE: ping_mib.pl # # USAGE: ./ping_mib.pl <source short_code> # # SYNOPSIS: If not present sets up DISMAN-PING MIB (RFC 2925) pro +bes # from source to all targets in hash. # DESCRIPTION: # AUTHOR: Simon Mullis (simon.mullis@equinoxsolutions.com) # OPTIONS: # REQUIREMENTS: Net::SNMP and well, Perl! # NOTES: --- # VERSION: 0.8 # CREATED: Aug 20 2004 12:25:43 GMTDT # REVISION: $Revision$ #===================================================================== +========== # # Set up pragmas use strict; # Set up external modules use Net::SNMP; # Set up all of the variables my ( $short_origin, $short_target, $origin_ip, $target_ip, $community +) = (); my %global_targets = (); $short_origin = $ARGV[0]; # Set up the community - make sure you've enabled the relevant RW OID +trees on the Juniper in question: # $community = 'CHANGE_ME'; # A list of source / target definitions %global_targets = ( juni1 => 'ip address 1', juni2 => 'ip address 2', juni3 => 'ip address 3', juni4 => 'ip address 4', ); sub usage { print "Usage: "; print "./ping_mib.pl <shortcode_origin> <shortcode_target>\n"; print "Please enter two of the following as origin and target:\n"; foreach my $short_target (sort(keys(%global_targets))) { print "$short_target "; } } # Check the command line arguments. if ($#ARGV != 2) { &usage; exit 0; } my $global_targets; if ( exists( $global_targets{$short_origin} ) ) { $origin_ip = $global_targets{$short_origin}; } else { print "Please check $short_origin"; } if ( exists( $global_targets{$short_target} ) ) { $target_ip = $global_targets{$short_target}; } else { print "Please check $short_target"; }

That's the boring bit done... Now let's set up the OID / Variables we'll need.

# Set up full target name encoded as BER OID. my @out = unpack( "C*", "$short_origin-to-$short_target" ); my $name = join( ".", @out ); my $num = $#out + 1; my $fulltargetname = "$num\.$name\.$num\.$name"; ### Default Values # All of the OIDs for the Results my $pingResultsMinRtt = '.1.3.6.1.2.1.80.1.3.1.4'; my $pingResultsMaxRtt = '.1.3.6.1.2.1.80.1.3.1.5'; my $pingResultsAveRtt = '.1.3.6.1.2.1.80.1.3.1.6'; my $pingProbeHistoryStatus = '.1.3.6.1.2.1.80.1.4.1.3'; # ### Default Values # Max Concurrent requests allowed for Juniper (suggest: 30) my $maxconn = '30'; # Target Address Type (suggest: 16) my $pingCtlTargetAddressType_val = '16'; # Number of polls per cycle (suggest: 5) my $pingCtlProbeCount_val = '5'; # Size of ICMP request in Octets (suggest: 128) my $pingCtlDataSize_val = '128'; # Polling frequency in seconds (suggest: 60) my $pingCtlFrequency_val = '60'; # Max number of historical rows kept in pingProbeHistoryTable (suggest +: 5 - needs to be >= to pingCtlProbeCount for this script) my $pingCtlMaxRows_val = '5'; # All of the required OIDs for the pingCtlTable my $pingCtlRowStatus = ".1.3.6.1.2.1.80.1.2.1.23\.$fulltarget +name"; my $pingCtlTargetAddress = ".1.3.6.1.2.1.80.1.2.1.4\.$fulltargetn +ame"; my $pingCtlTargetAddressType = ".1.3.6.1.2.1.80.1.2.1.3\.$fulltargetn +ame"; my $pingCtlProbeCount = ".1.3.6.1.2.1.80.1.2.1.7\.$fulltargetn +ame"; my $pingCtlDataSize = ".1.3.6.1.2.1.80.1.2.1.5\.$fulltargetn +ame"; my $pingCtlFrequency = ".1.3.6.1.2.1.80.1.2.1.10\.$fulltarget +name"; my $pingCtlMaxRows = ".1.3.6.1.2.1.80.1.2.1.11\.$fulltarget +name"; my $pingCtlAdminStatus = ".1.3.6.1.2.1.80.1.2.1.8\.$fulltargetn +ame"; my $pingMaxConcurrentRequests = ".1.3.6.1.2.1.80.1.1.0"; # The set OID array my @set_oids = (); @set_oids = ( $pingCtlRowStatus, INTEGER, 4, $pingCtlTargetAddressType, INTEGER, $pingCtlTargetAddres +sType_val, $pingCtlTargetAddress, OCTET_STRING, $target_ip, $pingCtlProbeCount, UNSIGNED32, $pingCtlProbeCount_val, $pingCtlDataSize, UNSIGNED32, $pingCtlDataSize_val, $pingCtlFrequency, UNSIGNED32, $pingCtlFrequency_val, + $pingCtlMaxRows, UNSIGNED32, $pingCtlMaxRows_val, $pingCtlAdminStatus, INTEGER, 1, ); # The OID array to retrieve data my @get_oids = (); @get_oids = ( "$pingResultsAveRtt\.$fulltargetname", "$pingResultsMinRtt\.$fulltargetname", "$pingResultsMaxRtt\.$fulltargetname", );

OK - At this point we're set to set up the Net::SNMP sessions

my ( $session, $error ) = (); ( $session, $error ) = Net::SNMP->session( -version => 'SNMPv2', -hostname => $origin_ip, -community => $community, -port => 161, -timeout => 3, -debug => 0, -retries => 2, ); # First we check if the PING-MIB instance is already set up. # Normally it should be. my $check_if_set_up = (); $check_if_set_up = $session->get_request( -varbindlist => [$pingCtlRow +Status] ); if ( !defined($check_if_set_up) ) { printf( "ERROR (Check_if_set_up): %s.\n", $error ); exit 1; } if ( $check_if_set_up->{$pingCtlRowStatus} ne 1 ) { # Let's make sure that the pingMaxConcurrentRequests is high enoug +h. my $setup_maxconcurr = (); $setup_maxconcurr = $session->set_request( -varbindlist => [ $ +pingMaxConcurrentRequests,INTEGER,30 ]); # If it is NOT set up then let's do that now. my $setup_probes_session = (); $setup_probes_session = $session->set_request( -varbindlist => [@set_oids] ); if ( !defined($setup_probes_session) ) { printf( "ERROR (Setup_probes_session): %s.\n", $error ); exit 1; } } else { # Otherwise we should just get the results. my $get_responses = $session->get_request( -varbindlist => [@get_o +ids] ); # if ( !defined($get_responses) ) { my $err = $session->error; print "ERROR: $err\n"; $session->close(); exit 1; } # Here we will get the History table for the last 5 ICMP requests and +see if any were not successfull. my $get_history = 0; $get_history = $session->get_entries( -columns => ["$pingProbeHistoryStatus\.$fulltarge +tname"] ); if ( !defined($get_history) ) { my $err = $session->error; print "$err\n"; $session->close(); exit 1; } # Here we calculate the number of bad responses. my $err = 0; while ( my ( $oid, $value ) = each %$get_history ) { # 1 is a plain old failure. 9 is when the max concurr +ency set above has been exceeded. # This is not an error so let's ignore that too... if ( $value !~ /1|9/ ) { $err++; } } # Set the ErrorCode and ErrorMessage my ( $errorcode, $errormessage ); if ( $err != 0 ) { $errorcode = "1"; $errormessage = "$err errors"; } else { $errorcode = "0"; $errormessage = "All OK"; }

Now we can print out the results. Here we use XML which another process chucks into a database

# And finally, print out the results print "<ErrorCode>$errorcode</ErrorCode><ErrorMessage>$errormessag +e</ErrorMessage>\n"; print "<Metric>Ave</Metric><MetricVal>$get_responses->{\"$pingResu +ltsAveRtt\.$fulltargetname\"}</MetricVal>\n"; print "<Metric>Min</Metric><MetricVal>$get_responses->{\"$pingResu +ltsMinRtt\.$fulltargetname\"}</MetricVal>\n"; print "<Metric>Max</Metric><MetricVal>$get_responses->{\"$pingResu +ltsMaxRtt\.$fulltargetname\"}</MetricVal>\n"; } $session->close; # If the instance is merely being set up then we will not output anyth +ing. We will # get results next time around. exit 0;

In some network configurations you'll want to specify the source interface to use - I've taken this code out for this example as it is Juniper specific. As it is above, it will test latency in inet.0

If anyone is interested I'll post the code I use to generate the funky colour-coded HTML matrix with date range so you can check what the latency across the network was for any specified time / date range...

Cheers

SM

Comment on Juniper full-mesh latency measurements (using DISMAN PING MIB)
Select or Download Code
Re: Juniper full-mesh latency measurements (using DISMAN PING MIB)
by howie (Sexton) on Nov 09, 2004 at 11:33 UTC
    Thanks for that - I'll be playing with it later today :-) I'd love to see the HTML report too...
      Well, I am trying to run this against some Extreme switches and failing. Has anyone gotten it to work with Extreme gear? Here is an error I got by just using snmpset
      snmpset -v2c -cprivate 10.1.1.20 pingCtlRowStatus.10.1.1.20 i 4 Error in packet. Reason: wrongValue (The set value is illegal or unsupported in some wa +y) Failed object: DISMAN-PING-MIB::pingCtlRowStatus.10.1.1.20

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://406024]
Approved by grinder
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2014-09-22 03:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (178 votes), past polls