ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FastPing/FPing.pm
Revision: 1.1
Committed: Fri May 4 07:02:19 2007 UTC (17 years ago) by root
Branch: MAIN
Log Message:
initial check-in

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     Net::FPing - quickly ping a large number of hosts
4    
5     =head1 SYNOPSIS
6    
7     use Net::FPing;
8    
9     =head1 DESCRIPTION
10    
11     This module was written for a signle purpose only: sendinf ICMP EHCO
12     REQUEST packets as quickly as possible to a large number of hosts
13     (thousands to millions).
14    
15     It employs a sending thread and is fully event-driven (using AnyEvent), so
16     you have to run an event model supported by AnyEvent to use this module.
17    
18     Receiving and processing reply packets is not currently supported by this
19     module.
20    
21     =over 4
22    
23     =cut
24    
25     package Net::FPing;
26    
27     use AnyEvent;
28    
29     BEGIN {
30     $VERSION = '0.01';
31     @ISA = qw(Exporter);
32    
33     require Exporter;
34     Exporter::export_ok_tags(keys %EXPORT_TAGS);
35    
36     require XSLoader;
37     XSLoader::load __PACKAGE__, $VERSION;
38     }
39    
40     our $THR_REQ_FH; open $THR_REQ_FH, ">&=$THR_REQ_FD" or die "FATAL: cannot fdopen";
41     our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen";
42    
43     our $THR_REQ_W;
44     our $THR_RES_W = AnyEvent->io (fh => $THR_RES_FH, poll => 'r', cb => sub {
45     my $sv = _read_res
46     or return;
47    
48     $sv->();
49     });
50    
51     our @THR_REQ_BUF;
52    
53     sub _send_req($) {
54     $THR_REQ_BUF .= $_[0];
55    
56     $THR_REQ_W ||= AnyEvent->io (fh => $THR_REQ_FH, poll => 'w', cb => sub {
57     my $len = syswrite $THR_REQ_FH, $THR_REQ_BUF;
58     substr $THR_REQ_BUF, 0, $len, "";
59    
60     undef $THR_REQ_W unless length $THR_REQ_BUF;
61     });
62     }
63    
64     =item Net::FPing::ping_ipv4_ranges [ranges...], $send_interval, $payload, \&callback
65    
66     Ping the given IPv4 address ranges. Each range is an arrayref of the
67     form C<[lo, hi, interval]>, where C<lo> and C<hi> are octet strings with
68     either 4 octets (for IPv4 addresses) or 16 octets (for IPV6 addresses),
69     representing the lowest and highest address to ping (you can convert a
70     dotted-quad IPv4 address to this format by using C<inet_aton $address>. The
71     range C<interval> is the minimum time in seconds between pings to the
72     given range. If omitted, defaults to C<$send_interval>.
73    
74     The C<$send_interval> is the minimum interval between sending any two
75     packets and is a way to make an overall rate limit. If omitted, pings will
76     be send as fast as possible.
77    
78     The C<$payload> is a 32 bit integer given as the ICMP ECHO REQUEST ident
79     and sequence numbers (in unspecified order :).
80    
81     The request will be queued and all requests will be served by a background
82     thread in order. When all ranges have been pinged, the C<callback> will be
83     called.
84    
85     Algorithm: Each range has an associated "next time to send packet"
86     time. The algorithm loops as long as there are ranges with hosts to be
87     pinged and always serves the range with the most urgent packet send
88     time. It will at most send one packet every C<$send_interval> seconds. The
89     algorithm to send each packet is O(log n) on the number of ranges, so even
90     a large number of ranges (many thousands) is managable.
91    
92     Performance: On my 2 GHZ Opteron system with a pretty average nvidia
93     gigabit network card I can ping around 60k to 200k adresses per second,
94     depending on routing decisions.
95    
96     Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and
97     11.0.0.1-11.0.255.255 with at most 1000 packets/s. Do not, however, exceed
98     1000 packets/s:
99    
100     Net::FPing::ping_ipv4_ranges
101     [v10.0.0.1, v10.0.0.15, .01],
102     [v11.0.0.1, v11.0.255.255, .001],
103     .001, 0x12345678,
104     sub {
105     warn "all ranges pinged\n";
106     }
107     ;
108    
109     =cut
110    
111     sub ping_ipv4_ranges($$$&) {
112     _send_req _req_ranges4 @_;
113     }
114    
115     our $ICMP4_FH;
116     our $ICMP4_W = (open $ICMP4_FH, "<&=$ICMP4_FD") && AnyEvent->io (fh => $ICMP4_FH, poll => 'r', cb => \&_recv_icmp4);
117     our $ICMP6_FH;
118     our $ICMP6_W = (open $ICMP6_FH, "<&=$ICMP6_FD") && AnyEvent->io (fh => $ICMP6_FH, poll => 'r', cb => \&_recv_icmp6);
119    
120     #my $t1 = Event::time;
121     #my @ranges = map [v127.0.0.1, v127.0.255.255, .000001], 0..0;
122     #ping_ipv4_ranges [@ranges, [v11.0.0.2, v11.0.0.15, 1]], 0, 0x12345678, sub { warn "done"; warn +(Event::time - $t1) / 0x100000};
123     #
124     #AnyEvent->condvar->wait;#d#
125    
126     =cut
127    
128     1;
129    
130     =back
131    
132     =head1 AUTHOR
133    
134     Marc Lehmann <schmorp@schmorp.de>
135     http://home.schmorp.de/
136    
137     =head1 AUTHOR
138    
139     This software is distributed under the GENERAL PUBLIC LICENSE,
140     version 2 or any later.
141    
142     =cut
143