Esempio n. 1
0
static void
peerMonitorCompleted(PeerMonitor * pm)
{
    int state = PEER_ALIVE;
    peer *p = pm->peer;
    storeClientUnregister(pm->running.sc, pm->running.e, pm);
    storeUnlockObject(pm->running.e);
    requestUnlink(pm->running.req);
    memFree(pm->running.buf, MEM_4K_BUF);
    if (pm->running.timeout_set) {
	eventDelete(peerMonitorTimeout, pm);
	pm->running.timeout_set = 0;
    }
    if (!cbdataValid(pm->peer)) {
	cbdataFree(pm);
	return;
    }
    /* Figure out if the response was OK or not */
    if (pm->running.status != HTTP_OK) {
	debug(DBG, 1) ("peerMonitor %s: Failed, status != 200 (%d)\n",
	    p->name, pm->running.status);
	state = PEER_DEAD;
    } else if (pm->running.size < p->monitor.min) {
	debug(DBG, 1) ("peerMonitor %s: Failed, reply size %d < min %d\n",
	    p->name, pm->running.size, p->monitor.min);
	state = PEER_DEAD;
    } else if (pm->running.size > p->monitor.max && p->monitor.max > 0) {
	debug(DBG, 1) ("peerMonitor %s: Failed, reply size %d > max %d\n",
	    p->name, pm->running.size, p->monitor.max);
	state = PEER_DEAD;
    } else {
	debug(DBG, 2) ("peerMonitor %s: OK\n", p->name);
    }
    p->monitor.state = state;
    if (state != p->stats.logged_state) {
	switch (state) {
	case PEER_ALIVE:
	    debug(DBG, 1) ("Detected REVIVED %s: %s\n",
		neighborTypeStr(p), p->name);
	    peerClearRR();
	    break;
	case PEER_DEAD:
	    debug(DBG, 1) ("Detected DEAD %s: %s\n",
		neighborTypeStr(p), p->name);
	    break;
	}
	p->stats.logged_state = state;
    }
    memset(&pm->running, 0, sizeof(pm->running));
    eventAdd(pm->name, peerMonitorRequest, pm, (double) (pm->last_probe + pm->peer->monitor.interval - current_dtime), 1);
}
Esempio n. 2
0
void
neighbors_init(void)
{
    struct sockaddr_in name;
    socklen_t len = sizeof(struct sockaddr_in);
    struct servent *sep = NULL;
    const char *me = getMyHostname();
    peer *this;
    peer *next;
    int fd = theInIcpConnection;
    if (fd >= 0) {
	memset(&name, '\0', sizeof(struct sockaddr_in));
	if (getsockname(fd, (struct sockaddr *) &name, &len) < 0)
	    debug(15, 1) ("getsockname(%d,%p,%p) failed.\n", fd, &name, &len);
	for (this = Config.peers; this; this = next) {
	    http_port_list *s;
	    next = this->next;
	    if (0 != strcmp(this->host, me))
		continue;
	    for (s = Config.Sockaddr.http; s; s = s->next) {
		if (this->http_port != ntohs(s->s.sin_port))
		    continue;
		debug(15, 1) ("WARNING: Peer looks like this host\n");
		debug(15, 1) ("         Ignoring %s %s/%d/%d\n",
		    neighborTypeStr(this), this->host, this->http_port,
		    this->icp.port);
		neighborRemove(this);
	    }
	}
    }
    peerRefreshDNS((void *) 1);
    if (0 == echo_hdr.opcode) {
	echo_hdr.opcode = ICP_SECHO;
	echo_hdr.version = ICP_VERSION_CURRENT;
	echo_hdr.length = 0;
	echo_hdr.reqnum = 0;
	echo_hdr.flags = 0;
	echo_hdr.pad = 0;
	echo_hdr.shostid = name.sin_addr.s_addr;
	sep = getservbyname("echo", "udp");
	echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
    }
    first_ping = Config.peers;
    cachemgrRegister("server_list",
	"Peer Cache Statistics",
	neighborDumpPeers, 0, 1);
    if (theInIcpConnection >= 0) {
	cachemgrRegister("non_peers",
	    "List of Unknown sites sending ICP messages",
	    neighborDumpNonPeers, 0, 1);
    }
}
Esempio n. 3
0
static void
neighborAliveHtcp(peer * p, const MemObject * mem, const htcpReplyData * htcp)
{
    if (p->stats.logged_state == PEER_DEAD && p->tcp_up) {
	debug(15, 1) ("Detected REVIVED %s: %s\n",
	    neighborTypeStr(p), p->name);
	p->stats.logged_state = PEER_ALIVE;
	peerClearRR();
    }
    p->stats.last_reply = squid_curtime;
    p->stats.probe_start = 0;
    p->stats.pings_acked++;
    p->htcp.counts[htcp->hit ? 1 : 0]++;
    p->htcp.version = htcp->version;
}
Esempio n. 4
0
void
peerConnectSucceded(peer * p)
{
    if (!p->tcp_up) {
	debug(15, 2) ("TCP connection to %s (%s:%d) succeded\n", p->name, p->host, p->http_port);
	debug(15, 1) ("Detected REVIVED %s: %s\n",
	    neighborTypeStr(p), p->name);
	peerMonitorNow(p);
	p->stats.logged_state = PEER_ALIVE;
	peerClearRR();
	if (!p->n_addresses)
	    ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
    }
    p->tcp_up = p->connect_fail_limit;
}
Esempio n. 5
0
static void
peerConnectFailedSilent(peer * p)
{
    p->stats.last_connect_failure = squid_curtime;
    if (!p->tcp_up) {
	debug(15, 2) ("TCP connection to %s (%s:%d) dead\n", p->name, p->host, p->http_port);
	return;
    }
    p->tcp_up--;
    if (!p->tcp_up) {
	debug(15, 1) ("Detected DEAD %s: %s\n",
	    neighborTypeStr(p), p->name);
	p->stats.logged_state = PEER_DEAD;
    }
}
Esempio n. 6
0
static void
neighborAlive(peer * p, const MemObject * mem, const icp_common_t * header)
{
    if (p->stats.logged_state == PEER_DEAD && p->tcp_up) {
	debug(15, 1) ("Detected REVIVED %s: %s\n",
	    neighborTypeStr(p), p->name);
	p->stats.logged_state = PEER_ALIVE;
	peerClearRR();
    }
    p->stats.last_reply = squid_curtime;
    p->stats.probe_start = 0;
    p->stats.pings_acked++;
    if ((icp_opcode) header->opcode <= ICP_END)
	p->icp.counts[header->opcode]++;
    p->icp.version = (int) header->version;
}
Esempio n. 7
0
static void
peerDNSConfigure(const ipcache_addrs * ia, void *data)
{
    peer *p = data;
    struct sockaddr_in *ap;
    int j;
    if (p->n_addresses == 0) {
	debug(15, 1) ("Configuring %s %s %s/%d/%d\n", p->name, neighborTypeStr(p),
	    p->name, p->http_port, p->icp.port);
	if (p->type == PEER_MULTICAST)
	    debug(15, 1) ("    Multicast TTL = %d\n", p->mcast.ttl);
    }
    p->n_addresses = 0;
    if (ia == NULL) {
	debug(0, 0) ("WARNING: DNS lookup of '%s' failed!\n", p->host);
	return;
    }
    if ((int) ia->count < 1) {
	debug(0, 0) ("WARNING: No IP address found for '%s'!\n", p->host);
	return;
    }
    for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) {
	p->addresses[j] = ia->in_addrs[j];
	debug(15, 2) ("--> IP address #%d: %s\n", j, inet_ntoa(p->addresses[j]));
	p->n_addresses++;
    }
    if (!p->tcp_up)
	peerProbeConnect((peer *) p);
    ap = &p->in_addr;
    memset(ap, '\0', sizeof(struct sockaddr_in));
    ap->sin_family = AF_INET;
    ap->sin_addr = p->addresses[0];
    ap->sin_port = htons(p->icp.port);
    if (p->type == PEER_MULTICAST)
	peerCountMcastPeersSchedule(p, 10);
    if (p->type != PEER_MULTICAST)
	if (!p->options.no_netdb_exchange)
	    eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
}
Esempio n. 8
0
int
neighborsUdpPing(request_t * request,
    StoreEntry * entry,
    IRCB * callback,
    void *callback_data,
    int *exprep,
    int *timeout)
{
    const char *url = storeUrl(entry);
    MemObject *mem = entry->mem_obj;
    peer *p = NULL;
    int i;
    int reqnum = 0;
    int flags;
    icp_common_t *query;
    int queries_sent = 0;
    int peers_pinged = 0;
    int parent_timeout = 0, parent_exprep = 0;
    int sibling_timeout = 0, sibling_exprep = 0;
    int mcast_timeout = 0, mcast_exprep = 0;

    if (Config.peers == NULL)
	return 0;
    if (theOutIcpConnection < 0)
	fatal("neighborsUdpPing: There is no ICP socket!");
    assert(entry->swap_status == SWAPOUT_NONE);
    mem->start_ping = current_time;
    mem->ping_reply_callback = callback;
    mem->ircb_data = callback_data;
    reqnum = icpSetCacheKey(entry->hash.key);
    for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
	if (p == NULL)
	    p = Config.peers;
	debug(15, 5) ("neighborsUdpPing: Peer %s\n", p->name);
	if (!peerWouldBePinged(p, request))
	    continue;		/* next peer */
	peers_pinged++;
	debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n",
	    p->name, url);
	if (p->type == PEER_MULTICAST)
	    mcastSetTtl(theOutIcpConnection, p->mcast.ttl);
	debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->hash.key));
	debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);

#if USE_HTCP
	if (p->options.htcp && !p->options.htcp_only_clr) {
	    debug(15, 3) ("neighborsUdpPing: sending HTCP query\n");
	    htcpQuery(entry, request, p);
	} else
#endif
	if (p->icp.port == echo_port) {
	    debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n");
	    echo_hdr.reqnum = reqnum;
	    query = icpCreateMessage(ICP_DECHO, 0, url, reqnum, 0);
	    icpUdpSend(theOutIcpConnection,
		&p->in_addr,
		query,
		LOG_ICP_QUERY,
		0);
	} else {
	    flags = 0;
	    if (Config.onoff.query_icmp)
		if (p->icp.version == ICP_VERSION_2)
		    flags |= ICP_FLAG_SRC_RTT;
	    query = icpCreateMessage(ICP_QUERY, flags, url, reqnum, 0);
	    icpUdpSend(theOutIcpConnection,
		&p->in_addr,
		query,
		LOG_ICP_QUERY,
		0);
	}
	queries_sent++;

	p->stats.pings_sent++;
	if (p->type == PEER_MULTICAST) {
	    mcast_exprep += p->mcast.n_replies_expected;
	    mcast_timeout += (p->stats.rtt * p->mcast.n_replies_expected);
	} else if (neighborUp(p)) {
	    /* its alive, expect a reply from it */
	    if (neighborType(p, request) == PEER_PARENT) {
		parent_exprep++;
		parent_timeout += p->stats.rtt;
	    } else {
		sibling_exprep++;
		sibling_timeout += p->stats.rtt;
	    }
	} else {
	    /* Neighbor is dead; ping it anyway, but don't expect a reply */
	    /* log it once at the threshold */
	    if (p->stats.logged_state == PEER_ALIVE) {
		debug(15, 1) ("Detected DEAD %s: %s\n",
		    neighborTypeStr(p), p->name);
		p->stats.logged_state = PEER_DEAD;
	    }
	}
	p->stats.last_query = squid_curtime;
	/*
	 * keep probe_start == 0 for a multicast peer,
	 * so neighborUp() never says this peer is dead.
	 */
	if ((p->type != PEER_MULTICAST) && (p->stats.probe_start == 0))
	    p->stats.probe_start = squid_curtime;
    }
    if ((first_ping = first_ping->next) == NULL)
	first_ping = Config.peers;

#if ALLOW_SOURCE_PING
    /* only do source_ping if we have neighbors */
    if (Config.npeers) {
	const ipcache_addrs *ia = NULL;
	struct sockaddr_in to_addr;
	char *host = request->host;
	if (!Config.onoff.source_ping) {
	    debug(15, 6) ("neighborsUdpPing: Source Ping is disabled.\n");
	} else if ((ia = ipcache_gethostbyname(host, 0))) {
	    debug(15, 6) ("neighborsUdpPing: Source Ping: to %s for '%s'\n",
		host, url);
	    echo_hdr.reqnum = reqnum;
	    if (icmp_sock != -1) {
		icmpSourcePing(ia->in_addrs[ia->cur], &echo_hdr, url);
	    } else {
		to_addr.sin_family = AF_INET;
		to_addr.sin_addr = ia->in_addrs[ia->cur];
		to_addr.sin_port = htons(echo_port);
		query = icpCreateMessage(ICP_SECHO, 0, url, reqnum, 0);
		icpUdpSend(theOutIcpConnection,
		    &to_addr,
		    query,
		    LOG_ICP_QUERY,
		    0);
	    }
	} else {
	    debug(15, 6) ("neighborsUdpPing: Source Ping: unknown host: %s\n",
		host);
	}
    }
#endif
    /*
     * How many replies to expect?
     */
    *exprep = parent_exprep + sibling_exprep + mcast_exprep;

    /*
     * If there is a configured timeout, use it
     */
    if (Config.Timeout.icp_query)
	*timeout = Config.Timeout.icp_query;
    else {
	if (*exprep > 0) {
	    if (parent_exprep)
		*timeout = 2 * parent_timeout / parent_exprep;
	    else if (mcast_exprep)
		*timeout = 2 * mcast_timeout / mcast_exprep;
	    else
		*timeout = 2 * sibling_timeout / sibling_exprep;
	} else
	    *timeout = 2000;	/* 2 seconds */
	if (Config.Timeout.icp_query_max)
	    if (*timeout > Config.Timeout.icp_query_max)
		*timeout = Config.Timeout.icp_query_max;

	if (*timeout < Config.Timeout.icp_query_min)
	    *timeout = Config.Timeout.icp_query_min;
    }
    return peers_pinged;
}
Esempio n. 9
0
static void
dump_peers(StoreEntry * sentry, peer * peers)
{
    peer *e = NULL;
    struct _domain_ping *d = NULL;
    icp_opcode op;
    int i;
    if (peers == NULL)
	storeAppendPrintf(sentry, "There are no neighbors installed.\n");
    for (e = peers; e; e = e->next) {
	assert(e->host != NULL);
	storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
	    neighborTypeStr(e),
	    e->name);
	storeAppendPrintf(sentry, "Host       : %s/%d/%d\n",
	    e->host,
	    e->http_port,
	    e->icp.port);
	storeAppendPrintf(sentry, "Flags      :");
	dump_peer_options(sentry, e);
	for (i = 0; i < e->n_addresses; i++) {
	    storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
		inet_ntoa(e->addresses[i]));
	}
	storeAppendPrintf(sentry, "Status     : %s\n",
	    neighborUp(e) ? "Up" : "Down");
	storeAppendPrintf(sentry, "AVG RTT    : %d msec\n", e->stats.rtt);
	storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open);
	if (!e->options.no_query) {
	    storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n",
		(int) (squid_curtime - e->stats.last_query));
	    if (e->stats.last_reply > 0)
		storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n",
		    (int) (squid_curtime - e->stats.last_reply));
	    else
		storeAppendPrintf(sentry, "LAST REPLY : none received\n");
	    storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent);
	    storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
		e->stats.pings_acked,
		percent(e->stats.pings_acked, e->stats.pings_sent));
	}
	storeAppendPrintf(sentry, "FETCHES    : %8d %3d%%\n",
	    e->stats.fetches,
	    percent(e->stats.fetches, e->stats.pings_acked));
	storeAppendPrintf(sentry, "IGNORED    : %8d %3d%%\n",
	    e->stats.ignored_replies,
	    percent(e->stats.ignored_replies, e->stats.pings_acked));
	if (!e->options.no_query) {
	    storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
#if USE_HTCP
	    if (e->options.htcp) {
		storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
		    e->htcp.counts[0],
		    percent(e->htcp.counts[0], e->stats.pings_acked));
		storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
		    e->htcp.counts[1],
		    percent(e->htcp.counts[1], e->stats.pings_acked));
	    } else {
#endif
		for (op = ICP_INVALID; op < ICP_END; op++) {
		    if (e->icp.counts[op] == 0)
			continue;
		    storeAppendPrintf(sentry, "    %12.12s : %8d %3d%%\n",
			icp_opcode_str[op],
			e->icp.counts[op],
			percent(e->icp.counts[op], e->stats.pings_acked));
		}
#if USE_HTCP
	    }
#endif
	}
	if (e->stats.last_connect_failure) {
	    storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
		mkhttpdlogtime(&(e->stats.last_connect_failure)));
	}
	if (e->peer_domain != NULL) {
	    storeAppendPrintf(sentry, "DOMAIN LIST: ");
	    for (d = e->peer_domain; d; d = d->next) {
		storeAppendPrintf(sentry, "%s%s ",
		    d->do_ping ? null_string : "!", d->domain);
	    }
	    storeAppendPrintf(sentry, "\n");
	}
	storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n",
	    percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
    }
}