… | |
… | |
7 | DESCRIPTION |
7 | DESCRIPTION |
8 | This module was written for a single purpose only: sending ICMP ECHO |
8 | This module was written for a single purpose only: sending ICMP ECHO |
9 | REQUEST packets as quickly as possible to a large number of hosts |
9 | REQUEST packets as quickly as possible to a large number of hosts |
10 | (thousands to millions). |
10 | (thousands to millions). |
11 | |
11 | |
12 | It employs a sending thread and is fully event-driven (using AnyEvent), |
12 | It employs a separate thread and is fully event-driven (using AnyEvent), |
13 | so you have to run an event model supported by AnyEvent to use this |
13 | so you have to run an event model supported by AnyEvent to use this |
14 | module. |
14 | module. |
15 | |
15 | |
16 | FUNCTIONS |
16 | FUNCTIONS |
17 | AnyEvent::FastPing::ipv4_supported |
17 | AnyEvent::FastPing::ipv4_supported |
18 | Returns true if IPv4 is supported in this module and on this system. |
18 | Returns true iff IPv4 is supported in this module and on this |
|
|
19 | system. |
19 | |
20 | |
20 | AnyEvent::FastPing::ipv6_supported |
21 | AnyEvent::FastPing::ipv6_supported |
21 | Returns true if IPv6 is supported in this module and on this system. |
22 | Returns true iff IPv6 is supported in this module and on this |
|
|
23 | system. |
22 | |
24 | |
23 | AnyEvent::FastPing::icmp4_pktsize |
25 | AnyEvent::FastPing::icmp4_pktsize |
24 | Returns the number of bytes each IPv4 ping packet has. |
26 | Returns the number of octets per IPv4 ping packet (the whole IP |
|
|
27 | packet including headers, excluding lower-level headers or trailers |
|
|
28 | such as Ethernet). |
|
|
29 | |
|
|
30 | Can be used to calculate e.g. octets/s from rate ... |
|
|
31 | |
|
|
32 | my $octets_per_second = $packets_per_second * AnyEvent::FastPing::icmp4_pktsize; |
|
|
33 | |
|
|
34 | ... or convert kilobit/second to packet rate ... |
|
|
35 | |
|
|
36 | my $packets_per_second = $kilobit_per_second |
|
|
37 | * (1000 / 8 / AnyEvent::FastPing::icmp4_pktsize); |
|
|
38 | |
|
|
39 | etc. |
25 | |
40 | |
26 | AnyEvent::FastPing::icmp6_pktsize |
41 | AnyEvent::FastPing::icmp6_pktsize |
27 | Returns the number of bytes each IPv4 ping packet has. |
42 | Like AnyEvent::FastPing::icmp4_pktsize, but for IPv6. |
28 | |
43 | |
29 | AnyEvent::FastPing::icmp_ping [ranges...], $send_interval, $payload, |
44 | THE AnyEvent::FastPing CLASS |
30 | \&callback |
45 | The AnyEvent::FastPing class represents a single "pinger". A "pinger" |
31 | Ping the given IPv4 address ranges. Each range is an arrayref of the |
46 | comes with its own thread to send packets in the background, a |
32 | form "[lo, hi, interval]", where "lo" and "hi" are octet strings |
47 | rate-limit machinery and separate idle/receive callbacks. |
33 | with either 4 octets (for IPv4 addresses) or 16 octets (for IPV6 |
|
|
34 | addresses), representing the lowest and highest address to ping (you |
|
|
35 | can convert a dotted-quad IPv4 address to this format by using |
|
|
36 | "inet_aton $address". The range "interval" is the minimum time in |
|
|
37 | seconds between pings to the given range. If omitted, defaults to |
|
|
38 | $send_interval. |
|
|
39 | |
48 | |
40 | The $send_interval is the minimum interval between sending any two |
49 | The recommended workflow (there are others) is this: 1. create a new |
41 | packets and is a way to make an overall rate limit. If omitted, |
50 | AnyEvent::FastPing object 2. configure the address lists and ranges to |
42 | pings will be sent as fast as possible. |
51 | ping, also configure an idle callback and optionally a receive callback |
|
|
52 | 3. "start" the pinger. |
43 | |
53 | |
44 | The $payload is a 32 bit unsigned integer given as the ICMP ECHO |
54 | When the pinger has finished pinging all the configured addresses it |
45 | REQUEST ident and sequence numbers (in unspecified order :). |
55 | will call the idle callback. |
46 | |
56 | |
47 | The request will be queued and all requests will be served by a |
57 | The pinging process works like this: every range has a minimum interval |
48 | background thread in order. When all ranges have been pinged, the |
58 | between sends, which is used to limit the rate at which hosts in that |
49 | "callback" will be called. |
59 | range are being pinged. Distinct ranges are independent of each other, |
|
|
60 | which is why there is a per-pinger "global" minimum interval as well. |
50 | |
61 | |
51 | Algorithm: Each range has an associated "next time to send packet" |
62 | The pinger sends pings as fats as possible, while both obeying the |
52 | time. The algorithm loops as long as there are ranges with hosts to |
63 | pinger rate limit as well as range limits. |
53 | be pinged and always serves the range with the most urgent packet |
|
|
54 | send time. It will at most send one packet every $send_interval |
|
|
55 | seconds. |
|
|
56 | |
64 | |
57 | This will ensure that pings to the same range are nicely interleaved |
65 | When a range is exhausted, it is removed. When all ranges are exhausted, |
58 | with other ranges - this can help reduce per-subnet bandwidth while |
66 | the pinger waits another "max_rtt" seconds and then exits, causing the |
59 | maintaining an overall high packet rate. |
67 | idle callback to trigger. |
60 | |
68 | |
61 | The algorithm to send each packet is O(log n) on the number of |
|
|
62 | ranges, so even a large number of ranges (many thousands) is |
|
|
63 | managable. |
|
|
64 | |
|
|
65 | No storage is allocated per address. |
|
|
66 | |
|
|
67 | Performance: On my 2 GHz Opteron system with a pretty average nvidia |
69 | Performance: On my 2 GHz Opteron system with a pretty average nvidia |
68 | gigabit network card I can ping around 60k to 200k adresses per |
70 | gigabit network card I can ping around 60k to 200k addresses per second, |
69 | second, depending on routing decisions. |
71 | depending on routing decisions. |
70 | |
72 | |
71 | Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and |
73 | Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and |
72 | 11.0.0.1-11.0.255.255 with at most 1000 packets/s. Do not, however, |
74 | 11.0.0.1-11.0.255.255 with at most 1000 packets/s. Also ping the IPv6 |
73 | exceed 1000 packets/s overall: |
75 | loopback address 5 times as fast as possible. Do not, however, exceed |
|
|
76 | 1000 packets/s overall. Also dump each received reply. |
74 | |
77 | |
|
|
78 | use AnyEvent::Socket; |
|
|
79 | use AnyEvent::FastPing; |
|
|
80 | |
75 | my $done = AnyEvent->condvar; |
81 | my $done = AnyEvent->condvar; |
76 | |
82 | |
77 | AnyEvent::FastPing::icmp_ping |
83 | my $pinger = new AnyEvent::FastPing; |
|
|
84 | |
|
|
85 | $pinger->interval (1/1000); |
|
|
86 | $pinger->max_rtt (0.1); # reasonably fast/reliable network |
|
|
87 | |
|
|
88 | $pinger->add_range (v10.0.0.1, v10.0.0.15, 1/100); |
|
|
89 | $pinger->add_range (v11.0.0.1, v11.0.255.255, 1/1000); |
|
|
90 | $pinger->add_hosts ([ (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1) x 5 ]); |
|
|
91 | |
|
|
92 | $pinger->on_recv (sub { |
|
|
93 | for (@{ $_[0] }) { |
|
|
94 | printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1]; |
78 | [ |
95 | } |
79 | [v10.0.0.1, v10.0.0.15, .01], |
96 | }); |
80 | [v11.0.0.1, v11.0.255.255, .001], |
97 | |
81 | ], |
98 | $pinger->on_idle (sub { |
82 | .001, 0x12345678, |
99 | print "done\n"; |
83 | sub { |
100 | undef $pinger; |
84 | warn "all ranges pinged\n"; |
101 | }); |
85 | $done->broadcast; |
102 | |
|
|
103 | $pinger->start; |
|
|
104 | $done->wait; |
|
|
105 | |
|
|
106 | METHODS |
|
|
107 | $pinger = new AnyEvent::FastPing |
|
|
108 | Creates a new pinger - right now there can be at most 65536 pingers |
|
|
109 | in a process, although that limit might change to something |
|
|
110 | drastically lower - you should be stingy with your pinger objects. |
|
|
111 | |
|
|
112 | $pinger->on_recv ($callback->([[$host, $rtt], ...])) |
|
|
113 | Registers a callback to be called for ping replies. If no callback |
|
|
114 | has been registered than ping replies will be ignored, otherwise |
|
|
115 | this module calculates the round trip time, in seconds, for each |
|
|
116 | reply and calls this callback. |
|
|
117 | |
|
|
118 | The callback receives a single argument, which is an array reference |
|
|
119 | with an entry for each reply packet (the replies will be batched for |
|
|
120 | efficiency). Each member in the array reference is again an array |
|
|
121 | reference with exactly two members: the binary host address (4 |
|
|
122 | octets for IPv4, 16 for IPv6) and the approximate round trip time, |
|
|
123 | in seconds. |
|
|
124 | |
|
|
125 | The replies will be passed to the callback as soon as they arrive, |
|
|
126 | and this callback can be called many times with batches of replies. |
|
|
127 | |
|
|
128 | The receive callback will be called whenever a suitable reply |
|
|
129 | arrives, whether generated by this pinger or not, whether this |
|
|
130 | pinger is started or not. The packets will have a unique 64 bit ID |
|
|
131 | to distinguish them from other pinger objects and other generators, |
|
|
132 | but this doesn't help against malicious replies. |
|
|
133 | |
|
|
134 | Note that very high packet rates can overwhelm your process, causing |
|
|
135 | replies to be dropped (configure your kernel with long receive |
|
|
136 | queues for raw sockets if this is a problem). |
|
|
137 | |
|
|
138 | Example: register a callback which simply dumps the received data. |
|
|
139 | |
|
|
140 | use AnyEvent::Socket; |
|
|
141 | |
|
|
142 | $pinger->on_recv (sub { |
|
|
143 | for (@{ $_[0] }) { |
|
|
144 | printf "%s %g\n", (AnyEvent::Socket::format_address $_->[0]), $_->[1]; |
86 | } |
145 | } |
87 | ; |
146 | }); |
88 | |
|
|
89 | $done->wait; |
|
|
90 | |
|
|
91 | AnyEvent::FastPing::register_cb \&cb |
|
|
92 | Register a callback that is called for every received ping reply |
|
|
93 | (regardless of whether a ping is still in process or not and |
|
|
94 | regardless of whether the reply is actually a reply to a ping sent |
|
|
95 | earlier). |
|
|
96 | |
|
|
97 | The code reference gets a single parameter - an arrayref with an |
|
|
98 | entry for each received packet (replies are being batched for |
|
|
99 | greater efficiency). Each packet is represented by an arrayref with |
|
|
100 | three members: the source address (an octet string of either 4 |
|
|
101 | (IPv4) or 16 (IPv6) octets length), the payload as passed to |
|
|
102 | "icmp_ping" and the round trip time in seconds. |
|
|
103 | |
147 | |
104 | Example: a single ping reply with payload of 1 from "::1" gets |
148 | Example: a single ping reply with payload of 1 from "::1" gets |
105 | passed like this: |
149 | passed like this: |
106 | |
150 | |
107 | [ [ |
|
|
108 | "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", |
|
|
109 | "0.000280141830444336", |
|
|
110 | 1 |
|
|
111 | ] ] |
|
|
112 | |
|
|
113 | Example: ping replies for 127.0.0.1 and 127.0.0.2, with a payload of |
|
|
114 | 0x12345678: |
|
|
115 | |
|
|
116 | [ |
151 | [ |
117 | [ |
152 | [ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 0.000280141830444336 ] |
118 | "\177\0\0\1", |
|
|
119 | "0.00015711784362793", |
|
|
120 | 305419896 |
|
|
121 | ], |
|
|
122 | [ |
|
|
123 | "\177\0\0\2", |
|
|
124 | "0.00090184211731", |
|
|
125 | 305419896 |
|
|
126 | ] |
|
|
127 | ] |
153 | ] |
128 | |
154 | |
129 | AnyEvent::FastPing::unregister_cb \&cb |
155 | Example: ping replies for 127.0.0.1 and 127.0.0.2: |
130 | Unregister the callback again (make sure you pass the same |
156 | |
131 | codereference as to "register_cb"). |
157 | [ |
|
|
158 | [ "\177\0\0\1", 0.00015711784362793 ], |
|
|
159 | [ "\177\0\0\2", 0.00090184211731 ] |
|
|
160 | ] |
|
|
161 | |
|
|
162 | $pinger->on_idle ($callback->()) |
|
|
163 | Registers a callback to be called when the pinger becomes *idle*, |
|
|
164 | that is, it has been started, has exhausted all ping ranges and |
|
|
165 | waited for the "max_rtt" time. An idle pinger is also stopped, so |
|
|
166 | the callback can instantly add new ranges, if it so desires. |
|
|
167 | |
|
|
168 | $pinger->interval ($seconds) |
|
|
169 | Configures the minimum interval between packet sends for this pinger |
|
|
170 | - the pinger will not send packets faster than this rate (or |
|
|
171 | actually 1 / rate), even if individual ranges have a lower interval. |
|
|
172 | |
|
|
173 | A value of 0 selects the fastest possible speed (currently no faster |
|
|
174 | than 1_000_000 packets/s). |
|
|
175 | |
|
|
176 | $pinger->max_rtt ($seconds) |
|
|
177 | If your idle callback were called instantly after all ranges were |
|
|
178 | exhausted and you destroyed the object inside (which is common), |
|
|
179 | then there would be no chance to receive some replies, as there |
|
|
180 | would be no time of the packet to travel over the network. |
|
|
181 | |
|
|
182 | This can be fixed by starting a timer in the idle callback, or more |
|
|
183 | simply by selecting a suitable "max_rtt" value, which should be the |
|
|
184 | maximum time you allow a ping packet to travel to its destination |
|
|
185 | and back. |
|
|
186 | |
|
|
187 | The pinger thread automatically waits for this amount of time before |
|
|
188 | becoming idle. |
|
|
189 | |
|
|
190 | The default is currently 0.5 seconds, which is usually plenty. |
|
|
191 | |
|
|
192 | $pinger->add_range ($lo, $hi[, $interval]) |
|
|
193 | Ping the IPv4 (or IPv6, but see below) address range, starting at |
|
|
194 | binary address $lo and ending at $hi (both $lo and $hi will be |
|
|
195 | pinged), generating no more than one ping per $interval seconds (or |
|
|
196 | as fast as possible if omitted). |
|
|
197 | |
|
|
198 | You can convert IP addresses from text to binary form by using |
|
|
199 | "AnyEvent::Util::parse_address", "Socket::inet_aton", |
|
|
200 | "Socket6::inet_pton" or any other method that you like :) |
|
|
201 | |
|
|
202 | The algorithm to select the next address is O(log n) on the number |
|
|
203 | of ranges, so even a large number of ranges (many thousands) is |
|
|
204 | manageable. |
|
|
205 | |
|
|
206 | No storage is allocated per address. |
|
|
207 | |
|
|
208 | Note that, while IPv6 addresses are currently supported, the |
|
|
209 | usefulness of this option is extremely limited and might be gone in |
|
|
210 | future versions - if you want to ping a number of IPv6 hosts, better |
|
|
211 | specify them individually using the "add_hosts" method. |
|
|
212 | |
|
|
213 | $pinger->add_hosts ([$host...], $interval, $interleave) |
|
|
214 | Similar to "add_range", but uses a list of single addresses instead. |
|
|
215 | The list is specified as an array reference as first argument. Each |
|
|
216 | entry in the array should be a binary host address, either IPv4 or |
|
|
217 | IPv6. If all addresses are IPv4 addresses, then a compact IPv4-only |
|
|
218 | format will be used to store the list internally. |
|
|
219 | |
|
|
220 | Minimum $interval is the same as for "add_range" and can be left |
|
|
221 | out. |
|
|
222 | |
|
|
223 | $interlave specifies an increment between addresses: often address |
|
|
224 | lists are generated in a way that results in clustering - first all |
|
|
225 | addresses from one subnet, then from the next, and so on. To avoid |
|
|
226 | this, you can specify an interleave factor. If it is 1 (the |
|
|
227 | default), then every address is pinged in the order specified. If it |
|
|
228 | is 2, then only every second address will be pinged in the first |
|
|
229 | round, followed by a second round with the others. Higher factors |
|
|
230 | will create $interleave runs of addresses spaced $interleave indices |
|
|
231 | in the list. |
|
|
232 | |
|
|
233 | The special value 0 selects a (hopefully) suitable interleave factor |
|
|
234 | automatically - currently 256 for lists with less than 65536 |
|
|
235 | addresses, and the square root of the list length otherwise. |
|
|
236 | |
|
|
237 | $pinger->start |
|
|
238 | Start the pinger, unless it is running already. While a pinger is |
|
|
239 | running you must not modify the pinger. If you want to change a |
|
|
240 | parameter, you have to "stop" the pinger first. |
|
|
241 | |
|
|
242 | The pinger will automatically stop when destroyed. |
|
|
243 | |
|
|
244 | $pinger->stop |
|
|
245 | Stop the pinger, if it is running. A pinger can be stopped at any |
|
|
246 | time, after which it's current state is preserved - starting it |
|
|
247 | again will continue where it left off. |
132 | |
248 | |
133 | AUTHOR |
249 | AUTHOR |
134 | Marc Lehmann <schmorp@schmorp.de> |
250 | Marc Lehmann <schmorp@schmorp.de> |
135 | http://home.schmorp.de/ |
251 | http://home.schmorp.de/ |
136 | |
252 | |