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, 3 months ago) by root
Branch: MAIN
Log Message:
initial check-in

File Contents

# Content
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