]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/local/bin/perl | |
2 | # | |
3 | ## Copyright (C) 1996-2020 The Squid Software Foundation and contributors | |
4 | ## | |
5 | ## Squid software is distributed under GPLv2+ license and includes | |
6 | ## contributions from numerous individuals and organizations. | |
7 | ## Please see the COPYING and CONTRIBUTORS files for details. | |
8 | ## | |
9 | ||
10 | # udp-banger.pl | |
11 | # | |
12 | # Duane Wessels, Dec 1995 | |
13 | # | |
14 | # Usage: udp-banger.pl [host [port]] < url-list | |
15 | # | |
16 | # Sends a continuous stream of ICP queries to a cache. Stdin is a list of | |
17 | # URLs to request. Run N of these at the same time to simulate a heavy | |
18 | # neighbor cache load. | |
19 | ||
20 | use Fcntl; | |
21 | use Getopt::Std; | |
22 | use IO::Socket; | |
23 | ||
24 | $|=1; | |
25 | ||
26 | getopts('qlnr'); | |
27 | ||
28 | $host=(shift || 'localhost') ; | |
29 | $port=(shift || '3130') ; | |
30 | ||
31 | # just copy this from src/proto.c | |
32 | @CODES=( | |
33 | "ICP_INVALID", | |
34 | "ICP_QUERY", | |
35 | "UDP_HIT", | |
36 | "UDP_MISS", | |
37 | "ICP_ERR", | |
38 | "ICP_SEND", | |
39 | "ICP_SENDA", | |
40 | "ICP_DATABEG", | |
41 | "ICP_DATA", | |
42 | "ICP_DATAEND", | |
43 | "ICP_SECHO", | |
44 | "ICP_DECHO", | |
45 | "ICP_OP_UNUSED0", | |
46 | "ICP_OP_UNUSED1", | |
47 | "ICP_OP_UNUSED2", | |
48 | "ICP_OP_UNUSED3", | |
49 | "ICP_OP_UNUSED4", | |
50 | "ICP_OP_UNUSED5", | |
51 | "ICP_OP_UNUSED6", | |
52 | "ICP_OP_UNUSED7", | |
53 | "ICP_OP_UNUSED8", | |
54 | "UDP_RELOADING", | |
55 | "UDP_DENIED", | |
56 | "UDP_HIT_OBJ", | |
57 | "ICP_END" | |
58 | ); | |
59 | ||
60 | $sock = IO::Socket::INET->new(PeerAddr => "$host:$port", Proto => 'udp'); | |
61 | die "socket: $!\n" unless defined($sock); | |
62 | ||
63 | chop($me=`uname -a|cut -f2 -d' '`); | |
64 | $myip=(gethostbyname($me))[4]; | |
65 | ||
66 | $flags = fcntl ($sock, &F_GETFL, 0); | |
67 | $flags |= &O_NONBLOCK; | |
68 | die "fcntl O_NONBLOCK: $!\n" unless | |
69 | fcntl ($sock, &F_SETFL, $flags); | |
70 | ||
71 | $flags = 0; | |
72 | $flags |= 0x80000000; | |
73 | $flags |= 0x40000000 if ($opt_n); | |
74 | $flags = ~0; | |
75 | $rn = 0; | |
76 | ||
77 | $start = time; | |
78 | while (<>) { | |
79 | chop; | |
80 | ||
81 | if ($opt_l) { # it's a Squid log file | |
82 | @stuff = split(/\s+/, $_); | |
83 | $_ = $stuff[6]; | |
84 | } | |
85 | ||
86 | $len = length($_) + 1; | |
87 | $request_template = sprintf 'CCnNNa4a4x4a%d', $len; | |
88 | $request = pack($request_template, | |
89 | 1, # C opcode | |
90 | 2, # C version | |
91 | 24 + $len, # n length | |
92 | ++$rn, # N reqnum | |
93 | $flags, # N flags | |
94 | '', # a4 pad | |
95 | $myip, # a4 shostid | |
96 | $_); # a%d payload | |
97 | die "send: $!\n" unless | |
98 | send($sock, $request, 0); | |
99 | $nsent++; | |
100 | $rin = ''; | |
101 | vec($rin,fileno($sock),1) = 1; | |
102 | ($nfound,$timeleft) = select($rout=$rin, undef, undef, 2.0); | |
103 | next if ($nfound == 0); | |
104 | while (1) { | |
105 | last unless ($theiraddr = recv($sock, $reply, 1024, 0)); | |
106 | next if $opt_q; # quietly carry on | |
107 | $nrecv++; | |
108 | if ($opt_r) { | |
109 | # only print send/receive rates | |
110 | if (($nsent & 0xFF) == 0) { | |
111 | $dt = time - $start; | |
112 | printf "SENT %d %f/sec; RECV %d %f/sec\n", | |
113 | $nsent, | |
114 | $nsent / $dt, | |
115 | $nrecv, | |
116 | $nrecv / $dt; | |
117 | } | |
118 | } else { | |
119 | # print the whole reply | |
120 | ($junk, $junk, $sourceaddr, $junk) = unpack($sockaddr, $theiraddr); | |
121 | @theirip = unpack('C4', $sourceaddr); | |
122 | ($type,$ver,$len,$flag,$p1,$p2,$payload) = unpack('CCnx4Nnnx4A', $reply); | |
123 | print join('.', @theirip) . ' ' . $CODES[$type] . " $_"; | |
124 | print " hop=$p1" if ($opt_n); | |
125 | print " rtt=$p2" if ($opt_n); | |
126 | print "\n"; | |
127 | } | |
128 | } | |
129 | } | |
130 |