1: ###########################
   2: ##Ping Stress Test
   3: ##desertfoxps@earthlink.net
   4: ##
   5: ## This is my first script, so it isn't as good as it could be,
   6: ## but its still pretty solid.
   7: ##
   8: ## The purpose is simply to ping a host with larger and larger
   9: ## pings until it fails.  It can be used to stress test any device
  10: ## that accepts ICMP, for fragment DOS.  Relevant information is
  11: ## dumped into a log file named after the host.
  12: ##
  13: ## An unmodified PING.EXE is required for Windows users (as Microsoft
  14: ## modified PING.EXE so that it cannot send large buffers), I don't know
  15: ## if *nix's PING.EXE will work /shrug.
  16: 
  17: use strict;
  18: my ($size,$RAW,@INFO,$TIME,$host,$fails);
  19: 
  20: $fails = 0; #Zero the var
  21: $size = 0; #Zero the var, of change to resume tests
  22: $host = '10.10.10.1'; #IP address of test subject
  23: 
  24: 
  25: while ($size = $size + 1) { #Increment buffer size
  26: open (DATA,"ssping -n 1 -l $size -w 1000 $host |"); #Call ping (I use SSPING.EXE
  27: @INFO = <DATA>;
  28: $RAW = join "", @INFO;
  29: $RAW =~ /time[<|=](.....)/gm; #Grab latency
  30: $TIME = $1;
  31:  if ($RAW =~ /Request/gs) { #Search for Request (as in Request timed out)
  32: 
  33:  open (DATA,"ssping -n 1 -l $size -w 2000 $host |"); #Double check the host
  34:  @INFO = <DATA>;
  35: 	$RAW = join "", @INFO;
  36:   if ($RAW =~ /Request/gs) { #Yup, it bit off to much
  37:   print "$host Failed at $size\n";
  38:   open LOG, ">>$host.log" or die $!;
  39:   print LOG "$host Failed at $size\n";
  40:   close LOG;
  41:   $fails = $fails + 1; #Increment fails
  42: 
  43:    if ($fails>=20) { #If to many consecutive fails...
  44:    print "Encountered Maximum amount of consecutive fails.\n";
  45:    exit;
  46:    }
  47:    goto END;
  48: 			
  49:   }
  50:   $fails = 0; #Zero the fails, as this was only a hiccup in traffic
  51:   print "$size    $TIME *Hiccup*\n"; #Host responded to second attempt
  52:   goto END;
  53: 		
  54:  }
  55:  print "$size    $TIME\n"; #Print good reply to screen
  56:  END:
  57: }

Replies are listed 'Best First'.
Re: Ping Stress Test
by Aristotle (Chancellor) on Oct 13, 2002 at 09:44 UTC

    Yuck, please don't use goto. Perl has next and last, which means you nearly never need the evil goto. Also, you could have saved a couple temporary variables in various places; f.ex $RAW = join "", <DATA>; would have let you get away without @INFO. (Even better would have been to write $RAW = do { local $/; <DATA> }; .) print ".."; exit; is nearly always better written as die "..";.

    Update { I forgot to mention: you should really check out Mark-Jason Dominus' excellent Program Repair Shop and Red Flags article series on Perl.com }

    That said, I would have used Net::Ping (as already suggested), and I'd also use one of the Getopt::* modules to make the script more flexible. Here's one possible rendition:

    #!/usr/bin/perl -w use strict; use Net::Ping 2.13; # earlier versions do not return ping time use Getopt::Std; my %opt = ( i => 1, m => 65536, p => "udp", r => 20, t => 1, ); getopts("a:i:m:p:t:r:", \%opt) and $opt{a} or die << "USAGE"; usage: $0 -a addr [-i minsize] [-m maxsize] [-p proto] [-r retr] [-t t +imeout] -a destination address -i initial ping size in bytes [default: 1] -m max ping size in bytes [default: 63536] -p protocol: tcp, udp, icmp [default: udp] -r maximum nr. or retries [default: 20] -t timeout in seconds [default: 1] USAGE my ($addr, $bytes, $maxsize, $proto, $timeout, $retries) = @opt{qw(a i m p t r)}; $Net::Ping::max_datasize = 65536; # we want to send huge packets until($bytes > $maxsize) { my $p = Net::Ping->new($proto, $timeout, $bytes); $p->hires(1); # precise ping times my ($success, $time); my $retry = 0; ($success, $time) = $p->ping($addr) until $success or (++$retry > $retries); die "Sorry, host $addr not found or network problem.\n" if not defined $success; die "Host $addr seems to have died at $bytes bytes packet size.\n" if $success == 0; printf "%3.2f msec for $bytes bytes packet size", $time; print " (traffic hiccuped, $retry tries)" if $retry > 1; print "\n"; ++$bytes; };
    Update: now tested. I also just noticed that the documentation of Net::Ping says you can only set the data size to 1024 bytes at most. There's a constant for that limit in the module however; I added a line to remove that limit.

    Makeshifts last the longest.

Re: Ping Stress Test
by jjdraco (Scribe) on Oct 12, 2002 at 22:51 UTC
    I've never messed around with any of the Net modules before, but you should take a look at Net::Ping.
    I think that would work better for you. But I could be wrong.

    jjdraco
    learning Perl one statement at a time.
      Last time I tested Net::Ping it crashed on me sometimes, so I had to roll my own.

      Update: This node is causing me some --, so perhaps I should explain myself. I used the Net::Ping in a script that built a tree of DNSinformation to make sure a DNS server was alive before I fetched data from it (this was an internal network), and I experienced problems with the Net::Ping module, that caused the program to abort and/or fail to report correctly if the server responded or not. I don't remember anything more, this was 2 years ago, and I didn't file a bug report on it. Perhaps it's better now.

Re: Ping Stress Test
by TStanley (Canon) on Oct 13, 2002 at 01:29 UTC
    As jjdraco mentions above, the Net::Ping module is a good one to use for this, and would greatly simplify your script. One thing to note however, is that you might need to be the root user on some *nix systems, if you are sending ICMP packets. Otherwise, you can use UDP by default.

    TStanley
    --------
    It is God's job to forgive Osama Bin Laden. It is our job to arrange the meeting -- General Norman Schwartzkopf
Re: Ping Stress Test
by foxops (Monk) on Oct 13, 2002 at 15:51 UTC
    Thanks everyone, I had a feeling that net::ping had a limit set on it - and I didn't feel like searching through the code to find it :)