]> git.ipfire.org Git - thirdparty/squid.git/blame - src/peer_select.cc
update
[thirdparty/squid.git] / src / peer_select.cc
CommitLineData
641941c0 1
062e2281 2/*
d46a87a8 3 * $Id: peer_select.cc,v 1.85 1998/09/19 17:06:08 wessels Exp $
062e2281 4 *
5 * DEBUG: section 44 Peer Selection Algorithm
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 9 * ----------------------------------------------------------
062e2281 10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
e25c139f 13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
062e2281 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
062e2281 34 */
35
36#include "squid.h"
37
429fdbec 38const char *hier_strings[] =
39{
40 "NONE",
41 "DIRECT",
42 "SIBLING_HIT",
43 "PARENT_HIT",
44 "DEFAULT_PARENT",
45 "SINGLE_PARENT",
46 "FIRST_UP_PARENT",
47 "NO_PARENT_DIRECT",
48 "FIRST_PARENT_MISS",
49 "CLOSEST_PARENT_MISS",
69c95dd3 50 "CLOSEST_PARENT",
429fdbec 51 "CLOSEST_DIRECT",
52 "NO_DIRECT_FAIL",
53 "SOURCE_FASTEST",
429fdbec 54 "ROUNDROBIN_PARENT",
6cfa8966 55#if USE_CACHE_DIGESTS
c127134a 56 "CACHE_DIGEST_HIT",
285f75ea 57 "NO_CACHE_DIGEST_DIRECT",
afd88fbe 58#endif
59#if USE_CARP
60 "CARP",
c127134a 61#endif
429fdbec 62 "INVALID CODE"
63};
64
85034133 65static struct {
75e88d56 66 int timeouts;
85034133 67} PeerStats;
062e2281 68
f9e5a344 69static char *DirectStr[] =
70{
71 "DIRECT_NO",
72 "DIRECT_MAYBE",
73 "DIRECT_YES"
7b665aeb 74};
75e88d56 75
f5b8bbc4 76static void peerSelectFoo(ps_state *);
77static void peerPingTimeout(void *data);
78static void peerSelectCallbackFail(ps_state * psstate);
86aebcda 79static IRCB peerHandlePingReply;
f5b8bbc4 80static void peerSelectStateFree(ps_state * psstate);
81static void peerIcpParentMiss(peer *, icp_common_t *, ps_state *);
44e237d0 82#if USE_HTCP
83static void peerHtcpParentMiss(peer *, htcpReplyData *, ps_state *);
84static void peerHandleHtcpReply(peer *, peer_t, htcpReplyData *, void *);
85#endif
f5b8bbc4 86static int peerCheckNetdbDirect(ps_state * psstate);
348b2031 87
88static void
89peerSelectStateFree(ps_state * psstate)
90{
91 if (psstate->acl_checklist) {
51fdcbd5 92 debug(44, 1) ("calling aclChecklistFree() from peerSelectStateFree\n");
348b2031 93 aclChecklistFree(psstate->acl_checklist);
94 }
95 requestUnlink(psstate->request);
8407afee 96 psstate->request = NULL;
73a201f8 97 if (psstate->entry) {
6898e7b0 98 assert(psstate->entry->ping_status != PING_WAITING);
0cdcddb9 99 storeUnlockObject(psstate->entry);
100 psstate->entry = NULL;
73a201f8 101 }
8407afee 102 cbdataFree(psstate);
348b2031 103}
062e2281 104
105int
106peerSelectIcpPing(request_t * request, int direct, StoreEntry * entry)
107{
7b665aeb 108 int n;
93775f90 109 if (entry == NULL)
110 return 0;
9fb13bb6 111 debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry));
062e2281 112 if (entry->ping_status != PING_NONE)
113 return 0;
9bd6a36d 114 assert(direct != DIRECT_YES);
92695e5e 115 if (!request->flags.hierarchical && direct != DIRECT_NO)
062e2281 116 return 0;
d46a87a8 117 if (EBIT_TEST(entry->flags, KEY_PRIVATE) && !neighbors_do_private_keys)
062e2281 118 if (direct != DIRECT_NO)
119 return 0;
7b665aeb 120 n = neighborsCount(request);
f9e5a344 121 debug(44, 3) ("peerSelectIcpPing: counted %d neighbors\n", n);
7b665aeb 122 return n;
062e2281 123}
124
125
126peer *
127peerGetSomeParent(request_t * request, hier_code * code)
128{
129 peer *p;
669fefd4 130 debug(44, 3) ("peerGetSomeParent: %s %s\n",
131 RequestMethodStr[request->method],
132 request->host);
062e2281 133 if ((p = getDefaultParent(request))) {
429fdbec 134 *code = DEFAULT_PARENT;
062e2281 135 return p;
136 }
062e2281 137 if ((p = getRoundRobinParent(request))) {
429fdbec 138 *code = ROUNDROBIN_PARENT;
062e2281 139 return p;
140 }
141 if ((p = getFirstUpParent(request))) {
429fdbec 142 *code = FIRSTUP_PARENT;
062e2281 143 return p;
144 }
145 return NULL;
146}
147
148void
93775f90 149peerSelect(request_t * request,
b6c0e933 150 StoreEntry * entry,
582b6456 151 PSC * callback,
152 PSC * fail_callback,
b6c0e933 153 void *callback_data)
75e88d56 154{
b6c0e933 155 ps_state *psstate = xcalloc(1, sizeof(ps_state));
86b389fc 156 if (entry)
9fb13bb6 157 debug(44, 3) ("peerSelect: %s\n", storeUrl(entry));
86b389fc 158 else
f9e5a344 159 debug(44, 3) ("peerSelect: %s\n", RequestMethodStr[request->method]);
3f6c0fb2 160 cbdataAdd(psstate, MEM_NONE);
b6c0e933 161 psstate->request = requestLink(request);
162 psstate->entry = entry;
163 psstate->callback = callback;
164 psstate->fail_callback = fail_callback;
165 psstate->callback_data = callback_data;
6cfa8966 166#if USE_CACHE_DIGESTS
39edba21 167 request->hier.peer_select_start = current_time;
168#endif
2395cb21 169 if (psstate->entry)
0cdcddb9 170 storeLockObject(psstate->entry);
395b813e 171 cbdataLock(callback_data);
b6c0e933 172 peerSelectFoo(psstate);
75e88d56 173}
174
175static void
176peerCheckNeverDirectDone(int answer, void *data)
177{
b6c0e933 178 ps_state *psstate = data;
348b2031 179 psstate->acl_checklist = NULL;
a3d5953d 180 debug(44, 3) ("peerCheckNeverDirectDone: %d\n", answer);
b6c0e933 181 psstate->never_direct = answer ? 1 : -1;
182 peerSelectFoo(psstate);
75e88d56 183}
184
185static void
186peerCheckAlwaysDirectDone(int answer, void *data)
187{
b6c0e933 188 ps_state *psstate = data;
348b2031 189 psstate->acl_checklist = NULL;
a3d5953d 190 debug(44, 3) ("peerCheckAlwaysDirectDone: %d\n", answer);
7b665aeb 191 psstate->always_direct = answer ? 1 : -1;
b6c0e933 192 peerSelectFoo(psstate);
75e88d56 193}
194
93775f90 195static void
b6c0e933 196peerSelectCallback(ps_state * psstate, peer * p)
93775f90 197{
b6c0e933 198 StoreEntry *entry = psstate->entry;
8407afee 199 void *data = psstate->callback_data;
b6c0e933 200 if (entry) {
9fb13bb6 201 debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry));
b6c0e933 202 if (entry->ping_status == PING_WAITING)
203 eventDelete(peerPingTimeout, psstate);
204 entry->ping_status = PING_DONE;
205 }
44e237d0 206 psstate->ping.stop = current_time;
8407afee 207 if (cbdataValid(data))
365e5b34 208 psstate->callback(p, data);
8407afee 209 cbdataUnlock(data);
348b2031 210 peerSelectStateFree(psstate);
93775f90 211}
212
213static void
b6c0e933 214peerSelectCallbackFail(ps_state * psstate)
93775f90 215{
b6c0e933 216 request_t *request = psstate->request;
8407afee 217 void *data = psstate->callback_data;
9b5d1d21 218 const char *url = psstate->entry ? storeUrl(psstate->entry) : urlCanonical(request);
6898e7b0 219 if (psstate->entry)
220 psstate->entry->ping_status = PING_DONE;
a3d5953d 221 debug(44, 1) ("Failed to select source for '%s'\n", url);
222 debug(44, 1) (" always_direct = %d\n", psstate->always_direct);
223 debug(44, 1) (" never_direct = %d\n", psstate->never_direct);
44e237d0 224 debug(44, 1) (" timedout = %d\n", psstate->ping.timedout);
8407afee 225 if (cbdataValid(data))
365e5b34 226 psstate->fail_callback(NULL, data);
8407afee 227 cbdataUnlock(data);
348b2031 228 peerSelectStateFree(psstate);
93775f90 229}
230
b3264694 231static int
232peerCheckNetdbDirect(ps_state * psstate)
233{
85223cd7 234 peer *p = whichPeer(&psstate->closest_parent_miss);
b3264694 235 int myrtt;
236 int myhops;
237 if (p == NULL)
238 return 0;
239 myrtt = netdbHostRtt(psstate->request->host);
0f8df3b0 240 debug(44, 3) ("peerCheckNetdbDirect: MY RTT = %d msec\n", myrtt);
241 debug(44, 3) ("peerCheckNetdbDirect: closest_parent_miss RTT = %d msec\n",
44e237d0 242 psstate->ping.p_rtt);
243 if (myrtt && myrtt < psstate->ping.p_rtt)
b3264694 244 return 1;
245 myhops = netdbHostHops(psstate->request->host);
437e2060 246 debug(44, 3) ("peerCheckNetdbDirect: MY hops = %d\n", myhops);
247 debug(44, 3) ("peerCheckNetdbDirect: minimum_direct_hops = %d\n",
b3264694 248 Config.minDirectHops);
249 if (myhops && myhops <= Config.minDirectHops)
250 return 1;
251 return 0;
252}
253
93775f90 254static void
b6c0e933 255peerSelectFoo(ps_state * psstate)
062e2281 256{
257 peer *p;
258 hier_code code;
b6c0e933 259 StoreEntry *entry = psstate->entry;
260 request_t *request = psstate->request;
75e88d56 261 int direct;
7b665aeb 262 debug(44, 3) ("peerSelectFoo: '%s %s'\n",
b6c0e933 263 RequestMethodStr[request->method],
264 request->host);
3445a83a 265 if (psstate->always_direct == 0 && Config.accessList.AlwaysDirect) {
348b2031 266 psstate->acl_checklist = aclChecklistCreate(
3445a83a 267 Config.accessList.AlwaysDirect,
75e88d56 268 request,
269 request->client_addr,
270 NULL, /* user agent */
348b2031 271 NULL); /* ident */
272 aclNBCheck(psstate->acl_checklist,
3445a83a 273 peerCheckAlwaysDirectDone,
b6c0e933 274 psstate);
75e88d56 275 return;
3445a83a 276 } else if (psstate->always_direct > 0) {
277 direct = DIRECT_YES;
278 } else if (psstate->never_direct == 0 && Config.accessList.NeverDirect) {
348b2031 279 psstate->acl_checklist = aclChecklistCreate(
3445a83a 280 Config.accessList.NeverDirect,
75e88d56 281 request,
282 request->client_addr,
283 NULL, /* user agent */
348b2031 284 NULL); /* ident */
285 aclNBCheck(psstate->acl_checklist,
3445a83a 286 peerCheckNeverDirectDone,
b6c0e933 287 psstate);
75e88d56 288 return;
3445a83a 289 } else if (psstate->never_direct > 0) {
290 direct = DIRECT_NO;
92695e5e 291 } else if (request->flags.loopdetect) {
9945ba2e 292 direct = DIRECT_YES;
75e88d56 293 } else {
294 direct = DIRECT_MAYBE;
295 }
7b665aeb 296 debug(44, 3) ("peerSelectFoo: direct = %s\n", DirectStr[direct]);
062e2281 297 if (direct == DIRECT_YES) {
7b665aeb 298 debug(44, 3) ("peerSelectFoo: DIRECT\n");
44e237d0 299 hierarchyNote(&request->hier, DIRECT, &psstate->ping, request->host);
b6c0e933 300 peerSelectCallback(psstate, NULL);
062e2281 301 return;
302 }
85223cd7 303 if ((p = getSingleParent(request))) {
e82d6d21 304 psstate->single_parent = p->in_addr;
a369131d 305 debug(44, 3) ("peerSelect: found single parent, skipping ICP query\n");
85223cd7 306 }
6cfa8966 307#if USE_CACHE_DIGESTS
85223cd7 308 else if ((p = neighborsDigestSelect(request, entry))) {
69c95dd3 309 debug(44, 2) ("peerSelect: Using Cache Digest\n");
310 request->hier.alg = PEER_SA_DIGEST;
311 code = CACHE_DIGEST_HIT;
312 debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
44e237d0 313 hierarchyNote(&request->hier, code, &psstate->ping, p->host);
69c95dd3 314 peerSelectCallback(psstate, p);
315 return;
85223cd7 316 }
afd88fbe 317#endif
318#if USE_CARP
85223cd7 319 else if ((p = carpSelectParent(request))) {
44e237d0 320 hierarchyNote(&request->hier, CARP, &psstate->ping, p->host);
0cdcddb9 321 peerSelectCallback(psstate, p);
322 return;
85223cd7 323 }
c127134a 324#endif
85223cd7 325 else if ((p = netdbClosestParent(request))) {
69c95dd3 326 request->hier.alg = PEER_SA_NETDB;
327 code = CLOSEST_PARENT;
328 debug(44, 2) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
44e237d0 329 hierarchyNote(&request->hier, code, &psstate->ping, p->host);
52040193 330 peerSelectCallback(psstate, p);
331 return;
69c95dd3 332 } else if (peerSelectIcpPing(request, direct, entry)) {
333 assert(entry->ping_status == PING_NONE);
334 request->hier.alg = PEER_SA_ICP;
335 debug(44, 3) ("peerSelect: Doing ICP pings\n");
44e237d0 336 psstate->ping.start = current_time;
337 psstate->ping.n_sent = neighborsUdpPing(request,
69c95dd3 338 entry,
86aebcda 339 peerHandlePingReply,
69c95dd3 340 psstate,
44e237d0 341 &psstate->ping.n_replies_expected,
342 &psstate->ping.timeout);
343 if (psstate->ping.n_sent == 0)
69c95dd3 344 debug(44, 0) ("WARNING: neighborsUdpPing returned 0\n");
70b768cd 345 debug(44, 3) ("peerSelectFoo: %d ICP replies expected, RTT %d msec\n",
44e237d0 346 psstate->ping.n_replies_expected, psstate->ping.timeout);
347 if (psstate->ping.n_replies_expected > 0) {
69c95dd3 348 entry->ping_status = PING_WAITING;
349 eventAdd("peerPingTimeout",
350 peerPingTimeout,
b6c0e933 351 psstate,
44e237d0 352 0.001 * psstate->ping.timeout,
52040193 353 0);
69c95dd3 354 return;
062e2281 355 }
062e2281 356 }
de7ba689 357 debug(44, 3) ("peerSelectFoo: After peerSelectIcpPing.\n");
b3264694 358 if (peerCheckNetdbDirect(psstate)) {
359 code = CLOSEST_DIRECT;
360 debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host);
44e237d0 361 hierarchyNote(&request->hier, code, &psstate->ping, request->host);
b3264694 362 peerSelectCallback(psstate, NULL);
85223cd7 363 } else if ((p = whichPeer(&psstate->closest_parent_miss))) {
b3264694 364 code = CLOSEST_PARENT_MISS;
365 debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
44e237d0 366 hierarchyNote(&request->hier, code, &psstate->ping, p->host);
b3264694 367 peerSelectCallback(psstate, p);
85223cd7 368 } else if ((p = whichPeer(&psstate->first_parent_miss))) {
429fdbec 369 code = FIRST_PARENT_MISS;
a3d5953d 370 debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
44e237d0 371 hierarchyNote(&request->hier, code, &psstate->ping, p->host);
b6c0e933 372 peerSelectCallback(psstate, p);
85223cd7 373 } else if ((p = whichPeer(&psstate->single_parent))) {
a369131d 374 code = SINGLE_PARENT;
375 debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
44e237d0 376 hierarchyNote(&request->hier, code, &psstate->ping, p->host);
a369131d 377 peerSelectCallback(psstate, p);
93775f90 378 } else if (direct != DIRECT_NO) {
429fdbec 379 code = DIRECT;
a3d5953d 380 debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], request->host);
44e237d0 381 hierarchyNote(&request->hier, code, &psstate->ping, request->host);
b6c0e933 382 peerSelectCallback(psstate, NULL);
93775f90 383 } else if ((p = peerGetSomeParent(request, &code))) {
a3d5953d 384 debug(44, 3) ("peerSelect: %s/%s\n", hier_strings[code], p->host);
44e237d0 385 hierarchyNote(&request->hier, code, &psstate->ping, p->host);
b6c0e933 386 peerSelectCallback(psstate, p);
93775f90 387 } else {
429fdbec 388 code = NO_DIRECT_FAIL;
44e237d0 389 hierarchyNote(&request->hier, code, &psstate->ping, NULL);
b6c0e933 390 peerSelectCallbackFail(psstate);
062e2281 391 }
392}
393
d9586c3c 394static void
93775f90 395peerPingTimeout(void *data)
062e2281 396{
b6c0e933 397 ps_state *psstate = data;
398 StoreEntry *entry = psstate->entry;
fefb0227 399 if (entry)
400 debug(44, 3) ("peerPingTimeout: '%s'\n", storeUrl(entry));
401 entry->ping_status = PING_TIMEOUT;
73a201f8 402 if (!cbdataValid(psstate->callback_data)) {
403 /* request aborted */
404 cbdataUnlock(psstate->callback_data);
0cdcddb9 405 peerSelectStateFree(psstate);
73a201f8 406 return;
407 }
75e88d56 408 PeerStats.timeouts++;
44e237d0 409 psstate->ping.timedout = 1;
b6c0e933 410 peerSelectFoo(psstate);
85034133 411}
412
413void
414peerSelectInit(void)
415{
75e88d56 416 memset(&PeerStats, '\0', sizeof(PeerStats));
9bdbfe33 417 assert(sizeof(hier_strings) == (HIER_MAX + 1) * sizeof(char *));
062e2281 418}
93775f90 419
b3264694 420static void
421peerIcpParentMiss(peer * p, icp_common_t * header, ps_state * ps)
422{
423 int rtt;
424 int hops;
425 if (Config.onoff.query_icmp) {
79a15e0a 426 if (header->flags & ICP_FLAG_SRC_RTT) {
b3264694 427 rtt = header->pad & 0xFFFF;
428 hops = (header->pad >> 16) & 0xFFFF;
429 if (rtt > 0 && rtt < 0xFFFF)
430 netdbUpdatePeer(ps->request, p, rtt, hops);
44e237d0 431 if (rtt && (ps->ping.p_rtt == 0 || rtt < ps->ping.p_rtt)) {
85223cd7 432 ps->closest_parent_miss = p->in_addr;
44e237d0 433 ps->ping.p_rtt = rtt;
b3264694 434 }
435 }
436 }
18ec72b2 437 /* if closest-only is set, then don't allow FIRST_PARENT_MISS */
cd196bc8 438 if (p->options.closest_only)
b3264694 439 return;
85223cd7 440 /* set FIRST_MISS if there is no CLOSEST parent */
441 if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr)
b3264694 442 return;
44e237d0 443 rtt = tvSubMsec(ps->ping.start, current_time) / p->weight;
444 if (ps->ping.w_rtt == 0 || rtt < ps->ping.w_rtt) {
85223cd7 445 ps->first_parent_miss = p->in_addr;
44e237d0 446 ps->ping.w_rtt = rtt;
b3264694 447 }
448}
93775f90 449
b6c0e933 450static void
b3264694 451peerHandleIcpReply(peer * p, peer_t type, icp_common_t * header, void *data)
93775f90 452{
b6c0e933 453 ps_state *psstate = data;
b3264694 454 icp_opcode op = header->opcode;
b6c0e933 455 request_t *request = psstate->request;
f9e5a344 456 debug(44, 3) ("peerHandleIcpReply: %s %s\n",
27cd7235 457 icp_opcode_str[op],
9fb13bb6 458 storeUrl(psstate->entry));
69c95dd3 459#if USE_CACHE_DIGESTS && 0
26b164ac 460 /* do cd lookup to count false misses */
3ab66981 461 if (p && request)
4b4cd312 462 peerNoteDigestLookup(request, p,
3ab66981 463 peerDigestLookup(p, request, psstate->entry));
26b164ac 464#endif
44e237d0 465 psstate->ping.n_recv++;
27cd7235 466 if (op == ICP_MISS || op == ICP_DECHO) {
b3264694 467 if (type == PEER_PARENT)
468 peerIcpParentMiss(p, header, psstate);
a7c05555 469 } else if (op == ICP_HIT) {
a4394ebd 470 hierarchyNote(&request->hier,
429fdbec 471 type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT,
44e237d0 472 &psstate->ping,
93775f90 473 p->host);
b6c0e933 474 peerSelectCallback(psstate, p);
93775f90 475 return;
27cd7235 476 } else if (op == ICP_SECHO) {
a4394ebd 477 hierarchyNote(&request->hier,
429fdbec 478 SOURCE_FASTEST,
44e237d0 479 &psstate->ping,
b6c0e933 480 request->host);
4f92c80c 481 peerSelectCallback(psstate, NULL);
93775f90 482 return;
483 }
44e237d0 484 if (psstate->ping.n_recv < psstate->ping.n_replies_expected)
93775f90 485 return;
b6c0e933 486 peerSelectFoo(psstate);
93775f90 487}
86aebcda 488
489#if USE_HTCP
490static void
44e237d0 491peerHandleHtcpReply(peer * p, peer_t type, htcpReplyData * htcp, void *data)
86aebcda 492{
493 ps_state *psstate = data;
44e237d0 494 request_t *request = psstate->request;
495 debug(44, 3) ("peerHandleIcpReply: %s %s\n",
496 htcp->hit ? "HIT" : "MISS",
497 storeUrl(psstate->entry));
498 psstate->ping.n_recv++;
499 if (htcp->hit) {
500 hierarchyNote(&request->hier,
501 type == PEER_PARENT ? PARENT_HIT : SIBLING_HIT,
502 &psstate->ping,
503 p->host);
504 peerSelectCallback(psstate, p);
505 return;
506 }
507 if (type == PEER_PARENT)
508 peerHtcpParentMiss(p, htcp, psstate);
509 if (psstate->ping.n_recv < psstate->ping.n_replies_expected)
510 return;
511 peerSelectFoo(psstate);
512}
513
514static void
515peerHtcpParentMiss(peer * p, htcpReplyData * htcp, ps_state * ps)
516{
517 int rtt;
518 int hops;
519 if (Config.onoff.query_icmp) {
520 if (htcp->cto.rtt > 0) {
521 rtt = (int) htcp->cto.rtt * 1000;
522 hops = (int) htcp->cto.hops * 1000;
523 netdbUpdatePeer(ps->request, p, rtt, hops);
524 if (rtt && (ps->ping.p_rtt == 0 || rtt < ps->ping.p_rtt)) {
525 ps->closest_parent_miss = p->in_addr;
526 ps->ping.p_rtt = rtt;
527 }
528 }
529 }
530 /* if closest-only is set, then don't allow FIRST_PARENT_MISS */
cd196bc8 531 if (p->options.closest_only)
44e237d0 532 return;
533 /* set FIRST_MISS if there is no CLOSEST parent */
534 if (ps->closest_parent_miss.sin_addr.s_addr != any_addr.s_addr)
535 return;
536 rtt = tvSubMsec(ps->ping.start, current_time) / p->weight;
537 if (ps->ping.w_rtt == 0 || rtt < ps->ping.w_rtt) {
538 ps->first_parent_miss = p->in_addr;
539 ps->ping.w_rtt = rtt;
540 }
86aebcda 541}
542#endif
543
544static void
545peerHandlePingReply(peer * p, peer_t type, protocol_t proto, void *ping_data, void *data)
546{
547 if (proto == PROTO_ICP)
548 peerHandleIcpReply(p, type, ping_data, data);
549#if USE_HTCP
550 else if (proto == PROTO_HTCP)
551 peerHandleHtcpReply(p, type, ping_data, data);
552#endif
553 else
554 debug(44, 1) ("peerHandlePingReply: unknown protocol_t %d\n", (int) proto);
555}