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

# 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 =head1 FUNCTIONS
22
23 =over 4
24
25 =cut
26
27 package Net::FPing;
28
29 use strict;
30 no warnings;
31
32 use AnyEvent;
33
34 BEGIN {
35 our $VERSION = '0.01';
36 our @ISA = qw(Exporter);
37
38 require Exporter;
39 #Exporter::export_ok_tags (keys %EXPORT_TAGS);
40
41 require XSLoader;
42 XSLoader::load (__PACKAGE__, $VERSION);
43 }
44
45 our ($THR_REQ_FD, $THR_RES_FD, $ICMP4_FD, $ICMP6_FD);
46
47 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 our $THR_REQ_BUF;
59
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 =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
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 a large number of ranges (many thousands) is managable. No storage is
114 allocated per address.
115
116 Performance: On my 2 GHz Opteron system with a pretty average nvidia
117 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 1000 packets/s overall:
123
124 my $done = AnyEvent->condvar;
125
126 Net::FPing::icmp_ping
127 [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 $done->broadcast;
133 }
134 ;
135
136 $done->wait;
137
138 =cut
139
140 sub icmp_ping($$$&) {
141 _send_req _req_icmp_ping @_;
142 }
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 1;
150
151 =back
152
153 =head1 BUGS AND SHORTCOMINGS
154
155 - replies are not yet accessible.
156 - ipv6 support has never ever been tested.
157
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