ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FastPing/FPing.pm
Revision: 1.2
Committed: Fri May 4 07:36:45 2007 UTC (17 years, 1 month ago) by root
Branch: MAIN
Changes since 1.1: +28 -14 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.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 root 1.2 =item Net::FPing::ipv4_supported
65    
66     Returns true if IPv4 is supported in this module and on this system.
67    
68     =item Net::FPing::ipv6_supported
69    
70     Returns true if IPv6 is supported in this module and on this system.
71    
72     =item Net::FPing::ipv4_pktsize
73    
74     Returns the number of bytes each IPv4 ping packet has.
75    
76     =item Net::FPing::ipv6_pktsize
77    
78     Returns the number of bytes each IPv4 ping packet has.
79    
80     =item Net::FPing::icmp_ping [ranges...], $send_interval, $payload, \&callback
81 root 1.1
82     Ping the given IPv4 address ranges. Each range is an arrayref of the
83     form C<[lo, hi, interval]>, where C<lo> and C<hi> are octet strings with
84     either 4 octets (for IPv4 addresses) or 16 octets (for IPV6 addresses),
85     representing the lowest and highest address to ping (you can convert a
86     dotted-quad IPv4 address to this format by using C<inet_aton $address>. The
87     range C<interval> is the minimum time in seconds between pings to the
88     given range. If omitted, defaults to C<$send_interval>.
89    
90     The C<$send_interval> is the minimum interval between sending any two
91     packets and is a way to make an overall rate limit. If omitted, pings will
92     be send as fast as possible.
93    
94     The C<$payload> is a 32 bit integer given as the ICMP ECHO REQUEST ident
95     and sequence numbers (in unspecified order :).
96    
97     The request will be queued and all requests will be served by a background
98     thread in order. When all ranges have been pinged, the C<callback> will be
99     called.
100    
101     Algorithm: Each range has an associated "next time to send packet"
102     time. The algorithm loops as long as there are ranges with hosts to be
103     pinged and always serves the range with the most urgent packet send
104     time. It will at most send one packet every C<$send_interval> seconds. The
105     algorithm to send each packet is O(log n) on the number of ranges, so even
106 root 1.2 a large number of ranges (many thousands) is managable. No storage is
107     allocated per address.
108 root 1.1
109     Performance: On my 2 GHZ Opteron system with a pretty average nvidia
110     gigabit network card I can ping around 60k to 200k adresses per second,
111     depending on routing decisions.
112    
113     Example: ping 10.0.0.1-10.0.0.15 with at most 100 packets/s, and
114     11.0.0.1-11.0.255.255 with at most 1000 packets/s. Do not, however, exceed
115 root 1.2 1000 packets/s overall:
116 root 1.1
117 root 1.2 Net::FPing::icmp_ping
118 root 1.1 [v10.0.0.1, v10.0.0.15, .01],
119     [v11.0.0.1, v11.0.255.255, .001],
120     .001, 0x12345678,
121     sub {
122     warn "all ranges pinged\n";
123     }
124     ;
125    
126     =cut
127    
128 root 1.2 sub icmp_ping($$$&) {
129     _send_req _req_icmp_ping @_;
130 root 1.1 }
131    
132     our $ICMP4_FH;
133     our $ICMP4_W = (open $ICMP4_FH, "<&=$ICMP4_FD") && AnyEvent->io (fh => $ICMP4_FH, poll => 'r', cb => \&_recv_icmp4);
134     our $ICMP6_FH;
135     our $ICMP6_W = (open $ICMP6_FH, "<&=$ICMP6_FD") && AnyEvent->io (fh => $ICMP6_FH, poll => 'r', cb => \&_recv_icmp6);
136    
137 root 1.2 1;
138 root 1.1
139 root 1.2 =back
140 root 1.1
141 root 1.2 =head1 BUGS AND SHORTCOMINGS
142 root 1.1
143 root 1.2 - replies are not yet accessible.
144     - ipv6 support has never ever been tested.
145 root 1.1
146     =head1 AUTHOR
147    
148     Marc Lehmann <schmorp@schmorp.de>
149     http://home.schmorp.de/
150    
151     =head1 AUTHOR
152    
153     This software is distributed under the GENERAL PUBLIC LICENSE,
154     version 2 or any later.
155    
156     =cut
157