Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
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 surveying the Monastery: (6)
As of 2015-07-03 00:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (47 votes), past polls