ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FastPing/FastPing.pm
Revision: 1.18
Committed: Fri Nov 11 01:18:56 2016 UTC (7 years, 6 months ago) by root
Branch: MAIN
CVS Tags: rel-2_03
Changes since 1.17: +21 -14 lines
Log Message:
rel-2_03

File Contents

# Content
1 =head1 NAME
2
3 AnyEvent::FastPing - quickly ping a large number of hosts
4
5 =head1 SYNOPSIS
6
7 use AnyEvent::FastPing;
8
9 =head1 DESCRIPTION
10
11 This module was written for a single purpose only: sending ICMP ECHO
12 REQUEST packets as quickly as possible to a large number of hosts
13 (thousands to millions).
14
15 It employs a separate thread and is fully event-driven (using AnyEvent),
16 so you have to run an event model supported by AnyEvent to use this
17 module.
18
19 =head1 FUNCTIONS
20
21 =over 4
22
23 =cut
24
25 package AnyEvent::FastPing;
26
27 use common::sense;
28
29 use AnyEvent;
30
31 BEGIN {
32 our $VERSION = 2.03;
33 our @ISA = qw(Exporter);
34
35 require Exporter;
36 #Exporter::export_ok_tags (keys %EXPORT_TAGS);
37
38 require XSLoader;
39 XSLoader::load (__PACKAGE__, $VERSION);
40 }
41
42 our ($THR_RES_FD, $ICMP4_FD, $ICMP6_FD);
43
44 our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen";
45
46 our $ICMP4_FH;
47 our $ICMP6_FH;
48
49 our @IDLE_CB;
50
51 AnyEvent::post_detect {
52 our $ICMP4_W = $ICMP4_FD >= 0 && (open $ICMP4_FH, "<&=$ICMP4_FD") && AE::io $ICMP4_FH, 0, \&_recv_icmp4;
53 our $ICMP6_W = $ICMP6_FD >= 0 && (open $ICMP6_FH, "<&=$ICMP6_FD") && AE::io $ICMP6_FH, 0, \&_recv_icmp6;
54
55 our $THR_RES_W = AE::io $THR_RES_FH, 0, sub {
56 sysread $THR_RES_FH, my $buf, 8;
57
58 for my $id (unpack "S*", $buf) {
59 _stop_id $id;
60 ($IDLE_CB[$id] || sub { })->();
61 }
62 };
63 };
64
65 =item AnyEvent::FastPing::ipv4_supported
66
67 Returns true iff IPv4 is supported in this module and on this system.
68
69 =item AnyEvent::FastPing::ipv6_supported
70
71 Returns true iff IPv6 is supported in this module and on this system.
72
73 =item AnyEvent::FastPing::icmp4_pktsize
74
75 Returns the number of octets per IPv4 ping packet (the whole IP packet
76 including headers, excluding lower-level headers or trailers such as
77 Ethernet).
78
79 Can be used to calculate e.g. octets/s from rate ...
80
81 my $octets_per_second = $packets_per_second * AnyEvent::FastPing::icmp4_pktsize;
82
83 ... or convert kilobit/second to packet rate ...
84
85 my $packets_per_second = $kilobit_per_second
86 * (1000 / 8 / AnyEvent::FastPing::icmp4_pktsize);
87
88 etc.
89
90 =item AnyEvent::FastPing::icmp6_pktsize
91
92 Like AnyEvent::FastPing::icmp4_pktsize, but for IPv6.
93
94 =back
95
96 =head1 THE AnyEvent::FastPing CLASS
97
98 The AnyEvent::FastPing class represents a single "pinger". A "pinger"
99 comes with its own thread to send packets in the background, a rate-limit
100 machinery and separate idle/receive callbacks.
101
102 The recommended workflow (there are others) is this: 1. create a new
103 AnyEvent::FastPing object 2. configure the address lists and ranges to
104 ping, also configure an idle callback and optionally a receive callback
105 3. C<start> the pinger.
106
107 When the pinger has finished pinging all the configured addresses it will
108 call the idle callback.
109
110 The pinging process works like this: every range has a minimum interval
111 between sends, which is used to limit the rate at which hosts in that
112 range are being pinged. Distinct ranges are independent of each other,
113 which is why there is a per-pinger "global" minimum interval as well.
114
115 The pinger sends pings as fats as possible, while both obeying the pinger
116 rate limit as well as range limits.
117
118 When a range is exhausted, it is removed. When all ranges are exhausted,
119 the pinger waits another C<max_rtt> seconds and then exits, causing the
120 idle callback to trigger.
121
122 Performance: On my 2 GHz Opteron system with a pretty average nvidia
123 gigabit network card I can ping around 60k to 200k addresses per second,
124 depending on routing decisions.
125
126 Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and
127 11.0.0.1-11.0.255.255 with at most 1000 packets/s. Also ping the IPv6
128 loopback address 5 times as fast as possible. Do not, however, exceed 1000
129 packets/s overall. Also dump each received reply.
130
131 use AnyEvent::Socket;
132 use AnyEvent::FastPing;
133
134 my $done = AnyEvent->condvar;
135
136 my $pinger = new AnyEvent::FastPing;
137
138 $pinger->interval (1/1000);
139 $pinger->max_rtt (0.1); # reasonably fast/reliable network
140
141 $pinger->add_range (v10.0.0.1, v10.0.0.15, 1/100);
142 $pinger->add_range (v11.0.0.1, v11.0.255.255, 1/1000);
143 $pinger->add_hosts ([ (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1) x 5 ]);
144
145 $pinger->on_recv (sub {
146 for (@{ $_[0] }) {
147 printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1];
148 }
149 });
150
151 $pinger->on_idle (sub {
152 print "done\n";
153 undef $pinger;
154 });
155
156 $pinger->start;
157 $done->wait;
158
159 =head2 METHODS
160
161 =over 4
162
163 =item $pinger = new AnyEvent::FastPing
164
165 Creates a new pinger - right now there can be at most C<65536> pingers in
166 a process, although that limit might change to something drastically lower
167 - you should be stingy with your pinger objects.
168
169 =cut
170
171 sub new {
172 my ($klass) = @_;
173
174 AnyEvent::detect unless defined $AnyEvent::MODEL;
175
176 _new $klass, (rand 65536), (rand 65536), (rand 65536)
177 }
178
179 sub DESTROY {
180 undef $IDLE_CB[ &id ];
181 &_free;
182 }
183
184 =item $pinger->on_recv ($callback->([[$host, $rtt], ...]))
185
186 Registers a callback to be called for ping replies. If no callback has
187 been registered than ping replies will be ignored, otherwise this module
188 calculates the round trip time, in seconds, for each reply and calls this
189 callback.
190
191 The callback receives a single argument, which is an array reference
192 with an entry for each reply packet (the replies will be batched for
193 efficiency). Each member in the array reference is again an array
194 reference with exactly two members: the binary host address (4 octets for
195 IPv4, 16 for IPv6) and the approximate round trip time, in seconds.
196
197 The replies will be passed to the callback as soon as they arrive, and
198 this callback can be called many times with batches of replies.
199
200 The receive callback will be called whenever a suitable reply arrives,
201 whether generated by this pinger or not, whether this pinger is started
202 or not. The packets will have a unique 64 bit ID to distinguish them from
203 other pinger objects and other generators, but this doesn't help against
204 malicious replies.
205
206 Note that very high packet rates can overwhelm your process, causing
207 replies to be dropped (configure your kernel with long receive queues for
208 raw sockets if this is a problem).
209
210 Example: register a callback which simply dumps the received data.
211
212 use AnyEvent::Socket;
213
214 $pinger->on_recv (sub {
215 for (@{ $_[0] }) {
216 printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1];
217 }
218 });
219
220 Example: a single ping reply with payload of 1 from C<::1> gets passed
221 like this:
222
223 [
224 [ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 0.000280141830444336 ]
225 ]
226
227 Example: ping replies for C<127.0.0.1> and C<127.0.0.2>:
228
229 [
230 [ "\177\0\0\1", 0.00015711784362793 ],
231 [ "\177\0\0\2", 0.00090184211731 ]
232 ]
233
234 =item $pinger->on_idle ($callback->())
235
236 Registers a callback to be called when the pinger becomes I<idle>, that
237 is, it has been started, has exhausted all ping ranges and waited for
238 the C<max_rtt> time. An idle pinger is also stopped, so the callback can
239 instantly add new ranges, if it so desires.
240
241 =cut
242
243 sub on_idle {
244 $IDLE_CB[ &id ] = $_[1];
245 }
246
247 =item $pinger->interval ($seconds)
248
249 Configures the minimum interval between packet sends for this pinger - the
250 pinger will not send packets faster than this rate (or actually 1 / rate),
251 even if individual ranges have a lower interval.
252
253 A value of C<0> selects the fastest possible speed (currently no faster
254 than 1_000_000 packets/s).
255
256 =item $pinger->max_rtt ($seconds)
257
258 If your idle callback were called instantly after all ranges were
259 exhausted and you destroyed the object inside (which is common), then
260 there would be no chance to receive some replies, as there would be no
261 time of the packet to travel over the network.
262
263 This can be fixed by starting a timer in the idle callback, or more simply
264 by selecting a suitable C<max_rtt> value, which should be the maximum time
265 you allow a ping packet to travel to its destination and back.
266
267 The pinger thread automatically waits for this amount of time before becoming idle.
268
269 The default is currently C<0.5> seconds, which is usually plenty.
270
271 =item $pinger->add_range ($lo, $hi[, $interval])
272
273 Ping the IPv4 (or IPv6, but see below) address range, starting at binary
274 address C<$lo> and ending at C<$hi> (both C<$lo> and C<$hi> will be
275 pinged), generating no more than one ping per C<$interval> seconds (or as
276 fast as possible if omitted).
277
278 You can convert IP addresses from text to binary form by
279 using C<AnyEvent::Util::parse_address>, C<Socket::inet_aton>,
280 C<Socket6::inet_pton> or any other method that you like :)
281
282 The algorithm to select the next address is O(log n) on the number of
283 ranges, so even a large number of ranges (many thousands) is manageable.
284
285 No storage is allocated per address.
286
287 Note that, while IPv6 addresses are currently supported, the usefulness of
288 this option is extremely limited and might be gone in future versions - if
289 you want to ping a number of IPv6 hosts, better specify them individually
290 using the C<add_hosts> method.
291
292 =item $pinger->add_hosts ([$host...], $interval, $interleave)
293
294 Similar to C<add_range>, but uses a list of single addresses instead. The
295 list is specified as an array reference as first argument. Each entry in
296 the array should be a binary host address, either IPv4 or IPv6. If all
297 addresses are IPv4 addresses, then a compact IPv4-only format will be used
298 to store the list internally.
299
300 Minimum C<$interval> is the same as for C<add_range> and can be left out.
301
302 C<$interlave> specifies an increment between addresses: often address
303 lists are generated in a way that results in clustering - first all
304 addresses from one subnet, then from the next, and so on. To avoid this,
305 you can specify an interleave factor. If it is C<1> (the default), then
306 every address is pinged in the order specified. If it is C<2>, then only
307 every second address will be pinged in the first round, followed by a
308 second round with the others. Higher factors will create C<$interleave>
309 runs of addresses spaced C<$interleave> indices in the list.
310
311 The special value C<0> selects a (hopefully) suitable interleave factor
312 automatically - currently C<256> for lists with less than 65536 addresses,
313 and the square root of the list length otherwise.
314
315 =item $pinger->start
316
317 Start the pinger, unless it is running already. While a pinger is running
318 you must not modify the pinger. If you want to change a parameter, you
319 have to C<stop> the pinger first.
320
321 The pinger will automatically stop when destroyed.
322
323 =item $pinger->stop
324
325 Stop the pinger, if it is running. A pinger can be stopped at any time,
326 after which it's current state is preserved - starting it again will
327 continue where it left off.
328
329 =cut
330
331 1;
332
333 =back
334
335 =head1 AUTHOR
336
337 Marc Lehmann <schmorp@schmorp.de>
338 http://home.schmorp.de/
339
340 =head1 LICENSE
341
342 This software is distributed under the GENERAL PUBLIC LICENSE, version 2
343 or any later version or, at your option, the Artistic License.
344
345 =cut
346