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); }
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); }
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); }
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); }
void gnet_stats_udp_get(gnet_stats_t *s) { g_assert(s != NULL); g_assert(thread_is_main()); *s = gnet_udp_stats; }
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)); } } }
/** * 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); }
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); }
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; }
/** * 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); }
/** * 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]++; }
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)); }
/** * 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); }
/** * 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; }