ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FastPing/FPing.pm
Revision: 1.3
Committed: Fri May 4 12:50:44 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
Changes since 1.2: +18 -6 lines
Log Message:
*** empty log message ***

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 root 1.3 =head1 FUNCTIONS
22    
23 root 1.1 =over 4
24    
25     =cut
26    
27     package Net::FPing;
28    
29 root 1.3 use strict;
30     no warnings;
31    
32 root 1.1 use AnyEvent;
33    
34     BEGIN {
35 root 1.3 our $VERSION = '0.01';
36     our @ISA = qw(Exporter);
37 root 1.1
38     require Exporter;
39 root 1.3 #Exporter::export_ok_tags (keys %EXPORT_TAGS);
40 root 1.1
41     require XSLoader;
42 root 1.3 XSLoader::load (__PACKAGE__, $VERSION);
43 root 1.1 }
44    
45 root 1.3 our ($THR_REQ_FD, $THR_RES_FD, $ICMP4_FD, $ICMP6_FD);
46    
47 root 1.1 our $THR_REQ_FH; open $THR_REQ_FH, ">&=$THR_REQ_FD" or die "FATAL: cannot fdopen";
48     our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen";
49    
50     our $THR_REQ_W;
51     our $THR_RES_W = AnyEvent->io (fh => $THR_RES_FH, poll => 'r', cb => sub {
52     my $sv = _read_res
53     or return;
54    
55     $sv->();
56     });
57    
58 root 1.3 our $THR_REQ_BUF;
59 root 1.1
60     sub _send_req($) {
61     $THR_REQ_BUF .= $_[0];
62    
63     $THR_REQ_W ||= AnyEvent->io (fh => $THR_REQ_FH, poll => 'w', cb => sub {
64     my $len = syswrite $THR_REQ_FH, $THR_REQ_BUF;
65     substr $THR_REQ_BUF, 0, $len, "";
66    
67     undef $THR_REQ_W unless length $THR_REQ_BUF;
68     });
69     }
70    
71 root 1.2 =item Net::FPing::ipv4_supported
72    
73     Returns true if IPv4 is supported in this module and on this system.
74    
75     =item Net::FPing::ipv6_supported
76    
77     Returns true if IPv6 is supported in this module and on this system.
78    
79     =item Net::FPing::ipv4_pktsize
80    
81     Returns the number of bytes each IPv4 ping packet has.
82    
83     =item Net::FPing::ipv6_pktsize
84    
85     Returns the number of bytes each IPv4 ping packet has.
86    
87     =item Net::FPing::icmp_ping [ranges...], $send_interval, $payload, \&callback
88 root 1.1
89     Ping the given IPv4 address ranges. Each range is an arrayref of the
90     form C<[lo, hi, interval]>, where C<lo> and C<hi> are octet strings with
91     either 4 octets (for IPv4 addresses) or 16 octets (for IPV6 addresses),
92     representing the lowest and highest address to ping (you can convert a
93     dotted-quad IPv4 address to this format by using C<inet_aton $address>. The
94     range C<interval> is the minimum time in seconds between pings to the
95     given range. If omitted, defaults to C<$send_interval>.
96    
97     The C<$send_interval> is the minimum interval between sending any two
98     packets and is a way to make an overall rate limit. If omitted, pings will
99     be send as fast as possible.
100    
101     The C<$payload> is a 32 bit integer given as the ICMP ECHO REQUEST ident
102     and sequence numbers (in unspecified order :).
103    
104     The request will be queued and all requests will be served by a background
105     thread in order. When all ranges have been pinged, the C<callback> will be
106     called.
107    
108     Algorithm: Each range has an associated "next time to send packet"
109     time. The algorithm loops as long as there are ranges with hosts to be
110     pinged and always serves the range with the most urgent packet send
111     time. It will at most send one packet every C<$send_interval> seconds. The
112     algorithm to send each packet is O(log n) on the number of ranges, so even
113 root 1.2 a large number of ranges (many thousands) is managable. No storage is
114     allocated per address.
115 root 1.1
116 root 1.3 Performance: On my 2 GHz Opteron system with a pretty average nvidia
117 root 1.1 gigabit network card I can ping around 60k to 200k adresses per second,
118     depending on routing decisions.
119    
120     Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and
121     11.0.0.1-11.0.255.255 with at most 1000 packets/s. Do not, however, exceed
122 root 1.2 1000 packets/s overall:
123 root 1.1
124 root 1.3 my $done = AnyEvent->condvar;
125    
126 root 1.2 Net::FPing::icmp_ping
127 root 1.1 [v10.0.0.1, v10.0.0.15, .01],
128     [v11.0.0.1, v11.0.255.255, .001],
129     .001, 0x12345678,
130     sub {
131     warn "all ranges pinged\n";
132 root 1.3 $done->broadcast;
133 root 1.1 }
134     ;
135    
136 root 1.3 $done->wait;
137    
138 root 1.1 =cut
139    
140 root 1.2 sub icmp_ping($$$&) {
141     _send_req _req_icmp_ping @_;
142 root 1.1 }
143    
144     our $ICMP4_FH;
145     our $ICMP4_W = (open $ICMP4_FH, "<&=$ICMP4_FD") && AnyEvent->io (fh => $ICMP4_FH, poll => 'r', cb => \&_recv_icmp4);
146     our $ICMP6_FH;
147     our $ICMP6_W = (open $ICMP6_FH, "<&=$ICMP6_FD") && AnyEvent->io (fh => $ICMP6_FH, poll => 'r', cb => \&_recv_icmp6);
148    
149 root 1.2 1;
150 root 1.1
151 root 1.2 =back
152 root 1.1
153 root 1.2 =head1 BUGS AND SHORTCOMINGS
154 root 1.1
155 root 1.2 - replies are not yet accessible.
156     - ipv6 support has never ever been tested.
157 root 1.1
158     =head1 AUTHOR
159    
160     Marc Lehmann <schmorp@schmorp.de>
161     http://home.schmorp.de/
162    
163     =head1 AUTHOR
164    
165     This software is distributed under the GENERAL PUBLIC LICENSE,
166     version 2 or any later.
167    
168     =cut
169