Exemple #1
0
/* Return TRUE if it is okay to send an ICP request to this peer.   */
static int
peerWouldBePinged(const peer * p, request_t * request)
{
    if (!peerAllowedToUse(p, request))
	return 0;
    if (p->options.no_query)
	return 0;
    if (p->options.mcast_responder)
	return 0;
    if (p->n_addresses == 0)
	return 0;
    if (p->icp.port == 0)
	return 0;
    /* the case below seems strange, but can happen if the
     * URL host is on the other side of a firewall */
    if (p->type == PEER_SIBLING)
	if (!request->flags.hierarchical)
	    return 0;
    /* Ping dead peers every timeout interval */
    if (squid_curtime - p->stats.last_query > Config.Timeout.deadPeer)
	return 1;
    if (!neighborUp(p))
	return 0;
    return 1;
}
Exemple #2
0
/* Return TRUE if it is okay to send an HTTP request to this peer. */
int
peerHTTPOkay(const peer * p, request_t * request)
{
    if (!peerAllowedToUse(p, request))
	return 0;
    if (!neighborUp(p))
	return 0;
    if (p->max_conn)
	if (p->stats.conn_open >= p->max_conn)
	    return 0;
    return 1;
}
Exemple #3
0
peer *
getFirstUpParent(request_t * request)
{
    peer *p = NULL;
    for (p = Config.peers; p; p = p->next) {
	if (!neighborUp(p))
	    continue;
	if (neighborType(p, request) != PEER_PARENT)
	    continue;
	if (!peerHTTPOkay(p, request))
	    continue;
	break;
    }
    debug(15, 3) ("getFirstUpParent: returning %s\n", p ? p->name : "NULL");
    return p;
}
Exemple #4
0
peer *
carpSelectParent(request_t * request)
{
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> ((sizeof(u_long)*8)-(n))))
    const char *c;
    peer *p = NULL;
    peer *tp;
    unsigned long url_hash = 0;
    unsigned long combined_hash;
    unsigned long high_score = 0;
    const char *url = urlCanonical(request);
    /* calculate url hash */
    debug(39, 2) ("carpSelectParent: CARP Calculating hash for %s\n", url);
    for (c = url; *c != 0; c++)
	url_hash += ROTATE_LEFT(url_hash, 19) + *c;
    /* select peer */
    for (tp = Config.peers; tp; tp = tp->next) {
	if (0.0 == tp->carp.load_factor)
	    continue;
	if (tp->tcp_up != PEER_TCP_MAGIC_COUNT)
	    continue;
	assert(tp->type == PEER_PARENT);
	combined_hash = (url_hash ^ tp->carp.hash);
	combined_hash += combined_hash * 0x62531965;
	combined_hash = ROTATE_LEFT(combined_hash, 21);
	combined_hash = combined_hash * tp->carp.load_multiplier;
	debug(39, 3) ("carpSelectParent: %s combined_hash %d\n",
	    tp->host, combined_hash);
	if ((combined_hash > high_score) && neighborUp(tp)) {
	    p = tp;
	    high_score = combined_hash;
	}
    }
    if (p)
	debug(39, 3) ("carpSelectParent: selected CARP %s\n", p->host);
    return p;
}
Exemple #5
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;
}
Exemple #6
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));
    }
}
Exemple #7
0
variable_list *
snmp_meshPtblFn(variable_list * Var, snint * ErrP)
{
    variable_list *Answer = NULL;
    struct in_addr *laddr;
    char *cp = NULL;
    peer *p = NULL;
    int cnt = 0;
    debug(49, 5) ("snmp_meshPtblFn: peer %d requested!\n", Var->name[LEN_SQ_MESH + 3]);
    *ErrP = SNMP_ERR_NOERROR;
    laddr = oid2addr(&Var->name[LEN_SQ_MESH + 3]);
    for (p = Config.peers; p != NULL; p = p->next, cnt++)
	if (p->in_addr.sin_addr.s_addr == laddr->s_addr)
	    break;
    if (p == NULL) {
	*ErrP = SNMP_ERR_NOSUCHNAME;
	return NULL;
    }
    switch (Var->name[LEN_SQ_MESH + 2]) {
    case MESH_PTBL_NAME:
	cp = p->host;
	Answer = snmp_var_new(Var->name, Var->name_length);
	Answer->type = ASN_OCTET_STR;
	Answer->val_len = strlen(cp);
	Answer->val.string = (u_char *) xstrdup(cp);
	break;
    case MESH_PTBL_IP:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    (snint) p->in_addr.sin_addr.s_addr,
	    SMI_IPADDRESS);
	break;
    case MESH_PTBL_HTTP:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    (snint) p->http_port,
	    ASN_INTEGER);
	break;
    case MESH_PTBL_ICP:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    (snint) p->icp.port,
	    ASN_INTEGER);
	break;
    case MESH_PTBL_TYPE:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    (snint) p->type,
	    ASN_INTEGER);
	break;
    case MESH_PTBL_STATE:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    (snint) neighborUp(p),
	    ASN_INTEGER);
	break;
    case MESH_PTBL_SENT:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    p->stats.pings_sent,
	    SMI_COUNTER32);
	break;
    case MESH_PTBL_PACKED:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    p->stats.pings_acked,
	    SMI_COUNTER32);
	break;
    case MESH_PTBL_FETCHES:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    p->stats.fetches,
	    SMI_COUNTER32);
	break;
    case MESH_PTBL_RTT:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    p->stats.rtt,
	    ASN_INTEGER);
	break;
    case MESH_PTBL_IGN:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    p->stats.ignored_replies,
	    SMI_COUNTER32);
	break;
    case MESH_PTBL_KEEPAL_S:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    p->stats.n_keepalives_sent,
	    SMI_COUNTER32);
	break;
    case MESH_PTBL_KEEPAL_R:
	Answer = snmp_var_new_integer(Var->name, Var->name_length,
	    p->stats.n_keepalives_recv,
	    SMI_COUNTER32);
	break;
    default:
	*ErrP = SNMP_ERR_NOSUCHNAME;
	break;
    }
    return Answer;
}