=head1 NAME Net::FPing - quickly ping a large number of hosts =head1 SYNOPSIS use Net::FPing; =head1 DESCRIPTION This module was written for a signle purpose only: sendinf ICMP EHCO REQUEST packets as quickly as possible to a large number of hosts (thousands to millions). It employs a sending thread and is fully event-driven (using AnyEvent), so you have to run an event model supported by AnyEvent to use this module. Receiving and processing reply packets is not currently supported by this module. =over 4 =cut package Net::FPing; use AnyEvent; BEGIN { $VERSION = '0.01'; @ISA = qw(Exporter); require Exporter; Exporter::export_ok_tags(keys %EXPORT_TAGS); require XSLoader; XSLoader::load __PACKAGE__, $VERSION; } our $THR_REQ_FH; open $THR_REQ_FH, ">&=$THR_REQ_FD" or die "FATAL: cannot fdopen"; our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen"; our $THR_REQ_W; our $THR_RES_W = AnyEvent->io (fh => $THR_RES_FH, poll => 'r', cb => sub { my $sv = _read_res or return; $sv->(); }); our @THR_REQ_BUF; sub _send_req($) { $THR_REQ_BUF .= $_[0]; $THR_REQ_W ||= AnyEvent->io (fh => $THR_REQ_FH, poll => 'w', cb => sub { my $len = syswrite $THR_REQ_FH, $THR_REQ_BUF; substr $THR_REQ_BUF, 0, $len, ""; undef $THR_REQ_W unless length $THR_REQ_BUF; }); } =item Net::FPing::ipv4_supported Returns true if IPv4 is supported in this module and on this system. =item Net::FPing::ipv6_supported Returns true if IPv6 is supported in this module and on this system. =item Net::FPing::ipv4_pktsize Returns the number of bytes each IPv4 ping packet has. =item Net::FPing::ipv6_pktsize Returns the number of bytes each IPv4 ping packet has. =item Net::FPing::icmp_ping [ranges...], $send_interval, $payload, \&callback Ping the given IPv4 address ranges. Each range is an arrayref of the form C<[lo, hi, interval]>, where C and C are octet strings with either 4 octets (for IPv4 addresses) or 16 octets (for IPV6 addresses), representing the lowest and highest address to ping (you can convert a dotted-quad IPv4 address to this format by using C. The range C is the minimum time in seconds between pings to the given range. If omitted, defaults to C<$send_interval>. The C<$send_interval> is the minimum interval between sending any two packets and is a way to make an overall rate limit. If omitted, pings will be send as fast as possible. The C<$payload> is a 32 bit integer given as the ICMP ECHO REQUEST ident and sequence numbers (in unspecified order :). The request will be queued and all requests will be served by a background thread in order. When all ranges have been pinged, the C will be called. Algorithm: Each range has an associated "next time to send packet" time. The algorithm loops as long as there are ranges with hosts to be pinged and always serves the range with the most urgent packet send time. It will at most send one packet every C<$send_interval> seconds. The algorithm to send each packet is O(log n) on the number of ranges, so even a large number of ranges (many thousands) is managable. No storage is allocated per address. Performance: On my 2 GHZ Opteron system with a pretty average nvidia gigabit network card I can ping around 60k to 200k adresses per second, depending on routing decisions. Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and 11.0.0.1-11.0.255.255 with at most 1000 packets/s. Do not, however, exceed 1000 packets/s overall: Net::FPing::icmp_ping [v10.0.0.1, v10.0.0.15, .01], [v11.0.0.1, v11.0.255.255, .001], .001, 0x12345678, sub { warn "all ranges pinged\n"; } ; =cut sub icmp_ping($$$&) { _send_req _req_icmp_ping @_; } our $ICMP4_FH; our $ICMP4_W = (open $ICMP4_FH, "<&=$ICMP4_FD") && AnyEvent->io (fh => $ICMP4_FH, poll => 'r', cb => \&_recv_icmp4); our $ICMP6_FH; our $ICMP6_W = (open $ICMP6_FH, "<&=$ICMP6_FD") && AnyEvent->io (fh => $ICMP6_FH, poll => 'r', cb => \&_recv_icmp6); 1; =back =head1 BUGS AND SHORTCOMINGS - replies are not yet accessible. - ipv6 support has never ever been tested. =head1 AUTHOR Marc Lehmann http://home.schmorp.de/ =head1 AUTHOR This software is distributed under the GENERAL PUBLIC LICENSE, version 2 or any later. =cut