Exemple #1
0
void
gnet_stats_count_flowc(const void *head, bool head_only)
{
	uint t;
	uint16 size = gmsg_size(head) + GTA_HEADER_SIZE;
	uint8 function = gnutella_header_get_function(head);
	uint8 ttl = gnutella_header_get_ttl(head);
	uint8 hops = gnutella_header_get_hops(head);

	g_assert(thread_is_main());

	if (GNET_PROPERTY(node_debug) > 3)
		g_debug("FLOWC function=%d ttl=%d hops=%d", function, ttl, hops);

	/*
	 * Adjust for Kademlia messages.
	 */

	if (GTA_MSG_DHT == function && size >= KDA_HEADER_SIZE && !head_only) {
		uint8 opcode = kademlia_header_get_function(head);

		if (UNSIGNED(opcode + MSG_DHT_BASE) < G_N_ELEMENTS(stats_lut)) {
			t = stats_lut[opcode + MSG_DHT_BASE];
		} else {
			t = stats_lut[function];		/* Invalid opcode? */
		}
		hops = 0;
		ttl = 0;
	} else {
		t = stats_lut[function];
	}

	gnet_stats_flowc_internal(t, function, ttl, hops, size);
}
Exemple #2
0
void
gnet_stats_g2_count_flowc(const gnutella_node_t *n,
	const void *base, size_t len)
{
	uint t;
	uint8 f, ttl, hops;

	g_assert(thread_is_main());

	f = g2_msg_type(base, len);

	if (GNET_PROPERTY(node_debug) > 3)
		g_debug("FLOWC G2 %s", g2_msg_type_name(f));

	if (f != G2_MSG_MAX) {
		f += MSG_G2_BASE;
	} else {
		f = G_N_ELEMENTS(stats_lut) - 1;	/* Last, holds MSG_UNKNOWN */
	}

	ttl = NODE_USES_UDP(n) ? 1 : 2;		/* Purely made up, but cannot be 0 */
	hops = 0;		/* Locally generated, this is TX flowc */

	t = stats_lut[f];

	gnet_stats_flowc_internal(t, f, ttl, hops, len);
}
Exemple #3
0
void
gnet_stats_count_sent(const gnutella_node_t *n,
	uint8 type, const void *base, uint32 size)
{
	uint t = stats_lut[type];
	gnet_stats_t *stats;
	uint8 hops;

	g_assert(t != MSG_UNKNOWN);
	g_assert(thread_is_main());
	g_assert(!NODE_TALKS_G2(n));

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	/*
	 * Adjust for Kademlia messages.
	 */

	if (GTA_MSG_DHT == type && size >= KDA_HEADER_SIZE) {
		uint8 opcode = kademlia_header_get_function(base);

		if (UNSIGNED(opcode + MSG_DHT_BASE) < G_N_ELEMENTS(stats_lut)) {
			t = stats_lut[opcode + MSG_DHT_BASE];
		}
		hops = 0;
	} else {
		hops = gnutella_header_get_hops(base);
	}

	gnet_stats_count_sent_internal(n, t, hops, size, stats);
}
Exemple #4
0
void
gnet_stats_g2_count_queued(const gnutella_node_t *n,
	const void *base, size_t len)
{
	gnet_stats_t *stats;
	uint t;
	uint8 f;

	g_assert(thread_is_main());
	g_assert(NODE_TALKS_G2(n));

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	f = g2_msg_type(base, len);

	if (f != G2_MSG_MAX) {
		f += MSG_G2_BASE;
	} else {
		f = G_N_ELEMENTS(stats_lut) - 1;	/* Last, holds MSG_UNKNOWN */
	}

	t = stats_lut[f];

	/* Leaf mode => hops = 0 */
	gnet_stats_count_queued_internal(n, t, 0, len, stats);
}
Exemple #5
0
void
gnet_stats_udp_get(gnet_stats_t *s)
{
    g_assert(s != NULL);
	g_assert(thread_is_main());

    *s = gnet_udp_stats;
}
Exemple #6
0
void
gnet_stats_count_dropped(gnutella_node_t *n, msg_drop_reason_t reason)
{
	uint32 size;
	uint type;
	gnet_stats_t *stats;

	g_assert(UNSIGNED(reason) < MSG_DROP_REASON_COUNT);
	g_assert(thread_is_main());

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	if (NODE_TALKS_G2(n)) {
		int f = g2_msg_type(n->data, n->size);
		if (f != G2_MSG_MAX) {
			f += MSG_G2_BASE;
		} else {
			f = G_N_ELEMENTS(stats_lut) - 1;	/* Last, holds MSG_UNKNOWN */
		}
		type = stats_lut[f];
		size = n->size;
	} else {
		type = stats_lut[gnutella_header_get_function(&n->header)];
		size = n->size + sizeof(n->header);
	}

	entropy_harvest_small(
		VARLEN(n->addr), VARLEN(n->port), VARLEN(reason), VARLEN(type),
		VARLEN(size), NULL);

	DROP_STATS(stats, type, size);
	node_inc_rxdrop(n);

	switch (reason) {
	case MSG_DROP_HOSTILE_IP: n->n_hostile++; break;
	case MSG_DROP_SPAM: n->n_spam++; break;
	case MSG_DROP_EVIL: n->n_evil++; break;
	default: ;
	}

	if (NODE_TALKS_G2(n)) {
		if (GNET_PROPERTY(log_dropped_g2)) {
			g2_msg_log_dropped_data(n->data, n->size,
				"from %s: %s", node_infostr(n),
				gnet_stats_drop_reason_to_string(reason));
		}
	} else {
		if (GNET_PROPERTY(log_dropped_gnutella)) {
			gmsg_log_split_dropped(&n->header, n->data, n->size,
				"from %s: %s", node_infostr(n),
				gnet_stats_drop_reason_to_string(reason));
		}
	}
}
Exemple #7
0
/**
 * Called when Gnutella header has been read.
 */
void
gnet_stats_count_received_header(gnutella_node_t *n)
{
	uint t = stats_lut[gnutella_header_get_function(&n->header)];
	uint8 ttl, hops;

	g_assert(thread_is_main());
	g_assert(!NODE_TALKS_G2(n));

	ttl = gnutella_header_get_ttl(&n->header);
	hops = gnutella_header_get_hops(&n->header);

	gnet_stats_count_received_header_internal(n, GTA_HEADER_SIZE, t, ttl, hops);
}
Exemple #8
0
void
gnet_stats_g2_count_sent(const gnutella_node_t *n,
	enum g2_msg type, uint32 size)
{
	uint t;
	gnet_stats_t *stats;

	g_assert(thread_is_main());
	g_assert((uint) type < UNSIGNED(G2_MSG_MAX));
	g_assert(NODE_TALKS_G2(n));

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	t = stats_lut[MSG_G2_BASE + type];

	g_assert(t != MSG_UNKNOWN);

	/* Leaf mode => hops = 0 */
	gnet_stats_count_sent_internal(n, t, 0, size, stats);
}
Exemple #9
0
void
gnet_stats_count_expired(const gnutella_node_t *n)
{
    uint32 size = n->size + sizeof(n->header);
	uint t = stats_lut[gnutella_header_get_function(&n->header)];
	gnet_stats_t *stats;

	g_assert(thread_is_main());
	g_assert(!NODE_TALKS_G2(n));

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

    gnet_stats.pkg.expired[MSG_TOTAL]++;
    gnet_stats.pkg.expired[t]++;
    gnet_stats.byte.expired[MSG_TOTAL] += size;
    gnet_stats.byte.expired[t] += size;

    stats->pkg.expired[MSG_TOTAL]++;
    stats->pkg.expired[t]++;
    stats->byte.expired[MSG_TOTAL] += size;
    stats->byte.expired[t] += size;
}
Exemple #10
0
/**
 * Check which of qsort() or xqsort() is best for sorting aligned arrays with
 * a native item size of OPSIZ.
 */
void
vsort_init(int verbose)
{
	tm_t start, end;
	bool blockable = TRUE;

	STATIC_ASSERT(VSORT_HUGE_ITEMS > VSORT_ITEMS);
	STATIC_ASSERT(VSORT_ITEMS > VSORT_SMALL_ITEMS);

	if (verbose)
		s_info("benchmarking sort routines to select the best one...");

	/*
	 * Allow main thread to block during the duration of our tests.
	 * This is needed since tqsort() can create threads and block.
	 */

	if (thread_is_main() && !thread_main_is_blockable()) {
		thread_set_main(TRUE);
		blockable = FALSE;
	}

	tm_now_exact(&start);
	vsort_init_items(VSORT_HUGE_ITEMS, VSORT_HUGE, verbose, "huge");
	vsort_init_items(VSORT_ITEMS, VSORT_LARGE, verbose, "large");
	vsort_init_items(VSORT_SMALL_ITEMS, VSORT_SMALL, verbose, "small");
	tm_now_exact(&end);

	if (verbose)
		s_info("vsort() benchmarking took %F secs", tm_elapsed_f(&end, &start));

	/*
	 * Restore non-blockable main thread if needed.
	 */

	if (!blockable)
		thread_set_main(FALSE);
}
Exemple #11
0
/**
 * Called to transform Gnutella header counting into Kademlia header counting.
 *
 * @param n		the node receiving the message
 * @param kt
 */
static void
gnet_stats_count_kademlia_header(const gnutella_node_t *n, uint kt)
{
	uint t = stats_lut[gnutella_header_get_function(&n->header)];
	uint i;
	gnet_stats_t *stats;

	g_assert(thread_is_main());
	g_assert(!NODE_TALKS_G2(n));

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

    gnet_stats.pkg.received[t]--;
    gnet_stats.pkg.received[kt]++;
    gnet_stats.byte.received[t] -= GTA_HEADER_SIZE;
    gnet_stats.byte.received[kt] += GTA_HEADER_SIZE;

    stats->pkg.received[t]--;
    stats->pkg.received[kt]++;
    stats->byte.received[t] -= GTA_HEADER_SIZE;
    stats->byte.received[kt] += GTA_HEADER_SIZE;

	i = MIN(gnutella_header_get_ttl(&n->header), STATS_RECV_COLUMNS - 1);
    stats->pkg.received_ttl[i][MSG_TOTAL]--;
    stats->pkg.received_ttl[i][t]--;

	i = MIN(gnutella_header_get_hops(&n->header), STATS_RECV_COLUMNS - 1);
    stats->pkg.received_hops[i][MSG_TOTAL]--;
    stats->pkg.received_hops[i][t]--;

	/* DHT messages have no hops nor ttl, use 0 */

    stats->pkg.received_ttl[0][MSG_TOTAL]++;
    stats->pkg.received_ttl[0][kt]++;
    stats->pkg.received_hops[0][MSG_TOTAL]++;
    stats->pkg.received_hops[0][kt]++;
}
Exemple #12
0
void
gnet_stats_count_dropped_nosize(
	const gnutella_node_t *n, msg_drop_reason_t reason)
{
	uint type;
	gnet_stats_t *stats;

	g_assert(UNSIGNED(reason) < MSG_DROP_REASON_COUNT);
	g_assert(thread_is_main());
	g_assert(!NODE_TALKS_G2(n));

	type = stats_lut[gnutella_header_get_function(&n->header)];
	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	entropy_harvest_small(VARLEN(n->addr), VARLEN(n->port), NULL);

	/* Data part of message not read */
	DROP_STATS(stats, type, sizeof(n->header));

	if (GNET_PROPERTY(log_dropped_gnutella))
		gmsg_log_split_dropped(&n->header, n->data, 0,
			"from %s: %s", node_infostr(n),
			gnet_stats_drop_reason_to_string(reason));
}
Exemple #13
0
/**
 * Account for dropped Kademlia message of specified opcode from node ``n''.
 */
void
gnet_dht_stats_count_dropped(gnutella_node_t *n, kda_msg_t opcode,
	msg_drop_reason_t reason)
{
	uint32 size;
	uint type;
	gnet_stats_t *stats;

	g_assert(UNSIGNED(reason) < MSG_DROP_REASON_COUNT);
	g_assert(opcode <= KDA_MSG_MAX_ID);
	g_assert(UNSIGNED(opcode + MSG_DHT_BASE) < G_N_ELEMENTS(stats_lut));
	g_assert(thread_is_main());

    size = n->size + sizeof(n->header);
	type = stats_lut[opcode + MSG_DHT_BASE];
	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	entropy_harvest_small(
		VARLEN(n->addr), VARLEN(n->port), VARLEN(reason), VARLEN(type),
		VARLEN(size), NULL);

	DROP_STATS(stats, type, size);
	node_inc_rxdrop(n);
}
Exemple #14
0
/**
 * Called when Gnutella payload has been read, or when a G2 messsage is read.
 *
 * The actual payload size (effectively read) is expected to be found
 * in n->size for Gnutella messages and G2 messages.
 *
 * @param n			the node from which message was received
 * @param payload	start of Gnutella payload, or head of G2 frame
 */
void
gnet_stats_count_received_payload(const gnutella_node_t *n, const void *payload)
{
	uint8 f;
	uint t;
	uint i;
	gnet_stats_t *stats;
    uint32 size;
	uint8 hops, ttl;

	g_assert(thread_is_main());

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;
	size = n->size;

	/*
	 * Size is NOT read in the Gnutella header but in n->size, which
	 * reflects how much data we have in the payload, as opposed to the
	 * size in the header which may be wrong, or have highest bits set
	 * because they indicate flags.
	 *
	 * In particular, broken DHT messages often come with an invalid size in
	 * the header.
	 *		--RAM, 2010-10-30
	 */

	if (NODE_TALKS_G2(n)) {
		f = g2_msg_type(payload, size);
		if (f != G2_MSG_MAX) {
			f += MSG_G2_BASE;
		} else {
			f = G_N_ELEMENTS(stats_lut) - 1;	/* Last, holds MSG_UNKNOWN */
		}
		ttl = 1;
		hops = NODE_USES_UDP(n) ? 0 : 1;
		t = stats_lut[f];
		/*
		 * No header for G2, so count header reception now with a size of zero.
		 * This is required to update the other packet reception statistics.
		 */
		gnet_stats_count_received_header_internal(
			deconstify_pointer(n),
			0, t, ttl, hops);
	} else {
		f = gnutella_header_get_function(&n->header);
		hops = gnutella_header_get_hops(&n->header);
		ttl = gnutella_header_get_ttl(&n->header);
		t = stats_lut[f];
	}

	gnet_stats_randomness(n, f, size);

	/*
	 * If we're dealing with a Kademlia message, we need to do two things:
	 *
	 * We counted the Gnutella header for the GTA_MSG_DHT message, but we
	 * now need to undo that and count it as a Kademlia message.
	 *
	 * To access the proper entry in the array, we need to offset the
	 * Kademlia OpCode from the header with MSG_DHT_BASE to get the entry
	 * in the statistics that are associated with that particular message.
	 *		--RAM, 2010-11-01
	 */

	if (GTA_MSG_DHT == f && size + GTA_HEADER_SIZE >= KDA_HEADER_SIZE) {
		uint8 opcode = peek_u8(payload);	/* Kademlia Opcode */

		if (UNSIGNED(opcode + MSG_DHT_BASE) < G_N_ELEMENTS(stats_lut)) {
			t = stats_lut[opcode + MSG_DHT_BASE];
			gnet_stats_count_kademlia_header(n, t);
		}
	}

	g_assert(t < MSG_TOTAL);

    gnet_stats.byte.received[MSG_TOTAL] += size;
    gnet_stats.byte.received[t] += size;

    stats->byte.received[MSG_TOTAL] += size;
    stats->byte.received[t] += size;

	i = MIN(ttl, STATS_RECV_COLUMNS - 1);
    stats->byte.received_ttl[i][MSG_TOTAL] += size;
    stats->byte.received_ttl[i][t] += size;

	i = MIN(hops, STATS_RECV_COLUMNS - 1);
    stats->byte.received_hops[i][MSG_TOTAL] += size;
    stats->byte.received_hops[i][t] += size;
}