… | |
… | |
10 | |
10 | |
11 | This module was written for a single purpose only: sending ICMP ECHO |
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 |
12 | REQUEST packets as quickly as possible to a large number of hosts |
13 | (thousands to millions). |
13 | (thousands to millions). |
14 | |
14 | |
15 | It employs a sending thread and is fully event-driven (using AnyEvent), so |
15 | It employs a separate thread and is fully event-driven (using AnyEvent), |
16 | you have to run an event model supported by AnyEvent to use this module. |
16 | so you have to run an event model supported by AnyEvent to use this |
|
|
17 | module. |
17 | |
18 | |
18 | =head1 FUNCTIONS |
19 | =head1 FUNCTIONS |
19 | |
20 | |
20 | =over 4 |
21 | =over 4 |
21 | |
22 | |
… | |
… | |
26 | use common::sense; |
27 | use common::sense; |
27 | |
28 | |
28 | use AnyEvent; |
29 | use AnyEvent; |
29 | |
30 | |
30 | BEGIN { |
31 | BEGIN { |
31 | our $VERSION = '2.0'; |
32 | our $VERSION = 2.03; |
32 | our @ISA = qw(Exporter); |
33 | our @ISA = qw(Exporter); |
33 | |
34 | |
34 | require Exporter; |
35 | require Exporter; |
35 | #Exporter::export_ok_tags (keys %EXPORT_TAGS); |
36 | #Exporter::export_ok_tags (keys %EXPORT_TAGS); |
36 | |
37 | |
… | |
… | |
40 | |
41 | |
41 | our ($THR_RES_FD, $ICMP4_FD, $ICMP6_FD); |
42 | our ($THR_RES_FD, $ICMP4_FD, $ICMP6_FD); |
42 | |
43 | |
43 | our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen"; |
44 | our $THR_RES_FH; open $THR_RES_FH, "<&=$THR_RES_FD" or die "FATAL: cannot fdopen"; |
44 | |
45 | |
|
|
46 | our $ICMP4_FH; |
|
|
47 | our $ICMP6_FH; |
|
|
48 | |
|
|
49 | our @IDLE_CB; |
|
|
50 | |
|
|
51 | AnyEvent::post_detect { |
45 | our $ICMP4_FH; our $ICMP4_W = $ICMP4_FD >= 0 && (open $ICMP4_FH, "<&=$ICMP4_FD") && AE::io $ICMP4_FH, 0, \&_recv_icmp4; |
52 | our $ICMP4_W = $ICMP4_FD >= 0 && (open $ICMP4_FH, "<&=$ICMP4_FD") && AE::io $ICMP4_FH, 0, \&_recv_icmp4; |
46 | our $ICMP6_FH; our $ICMP6_W = $ICMP6_FD >= 0 && (open $ICMP6_FH, "<&=$ICMP6_FD") && AE::io $ICMP6_FH, 0, \&_recv_icmp6; |
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 | }; |
47 | |
64 | |
48 | =item AnyEvent::FastPing::ipv4_supported |
65 | =item AnyEvent::FastPing::ipv4_supported |
49 | |
66 | |
50 | Returns true iff IPv4 is supported in this module and on this system. |
67 | Returns true iff IPv4 is supported in this module and on this system. |
51 | |
68 | |
… | |
… | |
101 | When a range is exhausted, it is removed. When all ranges are exhausted, |
118 | When a range is exhausted, it is removed. When all ranges are exhausted, |
102 | the pinger waits another C<max_rtt> seconds and then exits, causing the |
119 | the pinger waits another C<max_rtt> seconds and then exits, causing the |
103 | idle callback to trigger. |
120 | idle callback to trigger. |
104 | |
121 | |
105 | Performance: On my 2 GHz Opteron system with a pretty average nvidia |
122 | Performance: On my 2 GHz Opteron system with a pretty average nvidia |
106 | gigabit network card I can ping around 60k to 200k adresses per second, |
123 | gigabit network card I can ping around 60k to 200k addresses per second, |
107 | depending on routing decisions. |
124 | depending on routing decisions. |
108 | |
125 | |
109 | Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and |
126 | Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and |
110 | 11.0.0.1-11.0.255.255 with at most 1000 packets/s. Also ping the IPv6 |
127 | 11.0.0.1-11.0.255.255 with at most 1000 packets/s. Also ping the IPv6 |
111 | loopback address 5 times as fast as possible. Do not, however, exceed 1000 |
128 | loopback address 5 times as fast as possible. Do not, however, exceed 1000 |
112 | packets/s overall. Dump each received reply: |
129 | packets/s overall. Also dump each received reply. |
113 | |
130 | |
114 | use AnyEvent::Socket; |
131 | use AnyEvent::Socket; |
115 | use AnyEvent::FastPing; |
132 | use AnyEvent::FastPing; |
116 | |
133 | |
117 | my $done = AnyEvent->condvar; |
134 | my $done = AnyEvent->condvar; |
… | |
… | |
144 | =over 4 |
161 | =over 4 |
145 | |
162 | |
146 | =item $pinger = new AnyEvent::FastPing |
163 | =item $pinger = new AnyEvent::FastPing |
147 | |
164 | |
148 | Creates a new pinger - right now there can be at most C<65536> pingers in |
165 | Creates a new pinger - right now there can be at most C<65536> pingers in |
149 | a process, although that limit might change to somethind drastically lower |
166 | a process, although that limit might change to something drastically lower |
150 | - you should be stringy with your pinger objects. |
167 | - you should be stingy with your pinger objects. |
151 | |
168 | |
152 | =cut |
169 | =cut |
153 | |
170 | |
154 | sub new { |
171 | sub new { |
155 | my ($klass) = @_; |
172 | my ($klass) = @_; |
156 | |
173 | |
|
|
174 | AnyEvent::detect unless defined $AnyEvent::MODEL; |
|
|
175 | |
157 | _new $klass, (rand 65536), (rand 65536), (rand 65536) |
176 | _new $klass, (rand 65536), (rand 65536), (rand 65536) |
158 | } |
177 | } |
159 | |
|
|
160 | our @IDLE_CB; |
|
|
161 | |
178 | |
162 | sub DESTROY { |
179 | sub DESTROY { |
163 | undef $IDLE_CB[ &id ]; |
180 | undef $IDLE_CB[ &id ]; |
164 | &_free; |
181 | &_free; |
165 | } |
182 | } |
166 | |
183 | |
167 | =item $pinger->on_recv ($callback->([[$host, $rtt], ...])) |
184 | =item $pinger->on_recv ($callback->([[$host, $rtt], ...])) |
168 | |
185 | |
169 | Registeres a callback to be called for ping replies. If no callback has |
186 | Registers a callback to be called for ping replies. If no callback has |
170 | been registered than ping replies will be ignored, otherwise this module |
187 | been registered than ping replies will be ignored, otherwise this module |
171 | calculates the round trip time, in seconds, for each reply and calls this |
188 | calculates the round trip time, in seconds, for each reply and calls this |
172 | callback. |
189 | callback. |
173 | |
190 | |
174 | The callback receives a single argument, which is an array reference |
191 | The callback receives a single argument, which is an array reference |
175 | with an entry for each reply packet (the replies will be batched for |
192 | with an entry for each reply packet (the replies will be batched for |
176 | efficiency). Each member in the array reference is again an array |
193 | efficiency). Each member in the array reference is again an array |
177 | reference with exactly two members: the binary host addresss (4 octets for |
194 | reference with exactly two members: the binary host address (4 octets for |
178 | IPv4, 16 for IPv6) and the approximate round trip time, in seconds. |
195 | IPv4, 16 for IPv6) and the approximate round trip time, in seconds. |
179 | |
196 | |
180 | The replies will be passed to the callback as soon as they arrive, and |
197 | The replies will be passed to the callback as soon as they arrive, and |
181 | this callback can be called many times with batches of replies. |
198 | this callback can be called many times with batches of replies. |
182 | |
199 | |
… | |
… | |
196 | |
213 | |
197 | $pinger->on_recv (sub { |
214 | $pinger->on_recv (sub { |
198 | for (@{ $_[0] }) { |
215 | for (@{ $_[0] }) { |
199 | printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1]; |
216 | printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1]; |
200 | } |
217 | } |
201 | }; |
218 | }); |
202 | |
219 | |
203 | Example: a single ping reply with payload of 1 from C<::1> gets passed |
220 | Example: a single ping reply with payload of 1 from C<::1> gets passed |
204 | like this: |
221 | like this: |
205 | |
222 | |
206 | [ |
223 | [ |
… | |
… | |
225 | |
242 | |
226 | sub on_idle { |
243 | sub on_idle { |
227 | $IDLE_CB[ &id ] = $_[1]; |
244 | $IDLE_CB[ &id ] = $_[1]; |
228 | } |
245 | } |
229 | |
246 | |
230 | our $THR_RES_W = AE::io $THR_RES_FH, 0, sub { |
|
|
231 | sysread $THR_RES_FH, my $buf, 8; |
|
|
232 | |
|
|
233 | for my $id (unpack "S*", $buf) { |
|
|
234 | _stop_id $id; |
|
|
235 | ($IDLE_CB[$id] || sub { })->(); |
|
|
236 | } |
|
|
237 | }; |
|
|
238 | |
|
|
239 | =item $pinger->interval ($seconds) |
247 | =item $pinger->interval ($seconds) |
240 | |
248 | |
241 | Configures the minimum interval between packet sends for this pinger - the |
249 | Configures the minimum interval between packet sends for this pinger - the |
242 | pinger will not send packets faster than this rate (or atcually 1 / rate), |
250 | pinger will not send packets faster than this rate (or actually 1 / rate), |
243 | even if individual ranges have a lower interval. |
251 | even if individual ranges have a lower interval. |
244 | |
252 | |
245 | A value of C<0> selects the fastests possible speed (currently no faster |
253 | A value of C<0> selects the fastest possible speed (currently no faster |
246 | than 1_000_000 packets/s). |
254 | than 1_000_000 packets/s). |
247 | |
255 | |
248 | =item $pinger->max_rtt ($seconds) |
256 | =item $pinger->max_rtt ($seconds) |
249 | |
257 | |
250 | If your idle callback were called instantly after all ranges were |
258 | If your idle callback were called instantly after all ranges were |
251 | exhausted and you destroyed the object inside (which is common), then |
259 | exhausted and you destroyed the object inside (which is common), then |
252 | there would be no chance to receive some replies, as there would be no |
260 | there would be no chance to receive some replies, as there would be no |
253 | time fo the packet to travel over the network. |
261 | time of the packet to travel over the network. |
254 | |
262 | |
255 | This can be fixed by starting a timer in the idle callback, or more simply |
263 | This can be fixed by starting a timer in the idle callback, or more simply |
256 | by selecting a suitable C<max_rtt> value, which should be the maximum time |
264 | by selecting a suitable C<max_rtt> value, which should be the maximum time |
257 | you allow a ping packet to travel to its destinazion and back. |
265 | you allow a ping packet to travel to its destination and back. |
258 | |
266 | |
259 | The pinger thread automatically waits for this amount of time before becoming idle. |
267 | The pinger thread automatically waits for this amount of time before becoming idle. |
260 | |
268 | |
261 | The default is currently C<0.5> seconds, which is usually plenty. |
269 | The default is currently C<0.5> seconds, which is usually plenty. |
262 | |
270 | |
… | |
… | |
270 | You can convert IP addresses from text to binary form by |
278 | You can convert IP addresses from text to binary form by |
271 | using C<AnyEvent::Util::parse_address>, C<Socket::inet_aton>, |
279 | using C<AnyEvent::Util::parse_address>, C<Socket::inet_aton>, |
272 | C<Socket6::inet_pton> or any other method that you like :) |
280 | C<Socket6::inet_pton> or any other method that you like :) |
273 | |
281 | |
274 | The algorithm to select the next address is O(log n) on the number of |
282 | The algorithm to select the next address is O(log n) on the number of |
275 | ranges, so even a large number of ranges (many thousands) is managable. |
283 | ranges, so even a large number of ranges (many thousands) is manageable. |
276 | |
284 | |
277 | No storage is allocated per address. |
285 | No storage is allocated per address. |
278 | |
286 | |
279 | Note that, while IPv6 addresses are currently supported, the usefulness of |
287 | Note that, while IPv6 addresses are currently supported, the usefulness of |
280 | this option is extremely limited and might be gone in future versions - if |
288 | this option is extremely limited and might be gone in future versions - if |
… | |
… | |
283 | |
291 | |
284 | =item $pinger->add_hosts ([$host...], $interval, $interleave) |
292 | =item $pinger->add_hosts ([$host...], $interval, $interleave) |
285 | |
293 | |
286 | Similar to C<add_range>, but uses a list of single addresses instead. The |
294 | Similar to C<add_range>, but uses a list of single addresses instead. The |
287 | list is specified as an array reference as first argument. Each entry in |
295 | list is specified as an array reference as first argument. Each entry in |
288 | the array should be a binary host address, either IPv4 or IPv6. Currently, |
296 | the array should be a binary host address, either IPv4 or IPv6. If all |
289 | all entries in the list must be either IPv4 B<OR> IPv6, so you have to |
297 | addresses are IPv4 addresses, then a compact IPv4-only format will be used |
290 | create two host ranges if you have mixed addresses. |
298 | to store the list internally. |
291 | |
299 | |
292 | Minimum C<$interval> is the same as for C<add_range> and can be left out. |
300 | Minimum C<$interval> is the same as for C<add_range> and can be left out. |
293 | |
301 | |
294 | C<$interlave> specifies an increment between addresses: often address |
302 | C<$interlave> specifies an increment between addresses: often address |
295 | lists are generated in a way that results in clustering - first all |
303 | lists are generated in a way that results in clustering - first all |