diff options
Diffstat (limited to 'ot_stats.c')
| -rw-r--r-- | ot_stats.c | 111 |
1 files changed, 110 insertions, 1 deletions
| @@ -43,6 +43,110 @@ static unsigned long long ot_failed_request_counts[CODE_HTTPERROR_COUNT]; | |||
| 43 | 43 | ||
| 44 | static time_t ot_start_time; | 44 | static time_t ot_start_time; |
| 45 | 45 | ||
| 46 | #ifdef WANT_LOG_NETWORKS | ||
| 47 | #define STATS_NETWORK_NODE_BITWIDTH 8 | ||
| 48 | #define STATS_NETWORK_NODE_MAXDEPTH 3 | ||
| 49 | |||
| 50 | #define STATS_NETWORK_NODE_BITMASK ((1<<STATS_NETWORK_NODE_BITWIDTH)-1) | ||
| 51 | #define STATS_NETWORK_NODE_COUNT (1<<STATS_NETWORK_NODE_BITWIDTH) | ||
| 52 | |||
| 53 | typedef union stats_network_node stats_network_node; | ||
| 54 | union stats_network_node { | ||
| 55 | int counters[STATS_NETWORK_NODE_COUNT]; | ||
| 56 | stats_network_node *children[STATS_NETWORK_NODE_COUNT]; | ||
| 57 | }; | ||
| 58 | |||
| 59 | static stats_network_node *stats_network_counters_root = NULL; | ||
| 60 | |||
| 61 | static int stat_increase_network_count( stats_network_node **node, int depth, uint32_t ip ) { | ||
| 62 | int foo = ( ip >> ( 32 - STATS_NETWORK_NODE_BITWIDTH * ( ++depth ) ) ) & STATS_NETWORK_NODE_BITMASK; | ||
| 63 | |||
| 64 | if( !*node ) { | ||
| 65 | *node = malloc( sizeof( stats_network_node ) ); | ||
| 66 | if( !*node ) | ||
| 67 | return -1; | ||
| 68 | memset( *node, 0, sizeof( stats_network_node ) ); | ||
| 69 | } | ||
| 70 | |||
| 71 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) | ||
| 72 | return stat_increase_network_count( &(*node)->children[ foo ], depth, ip ); | ||
| 73 | |||
| 74 | (*node)->counters[ foo ]++; | ||
| 75 | return 0; | ||
| 76 | } | ||
| 77 | |||
| 78 | static int stats_shift_down_network_count( stats_network_node **node, int depth, int shift ) { | ||
| 79 | int i, rest = 0; | ||
| 80 | if( !*node ) return 0; | ||
| 81 | |||
| 82 | if( ++depth == STATS_NETWORK_NODE_MAXDEPTH ) | ||
| 83 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | ||
| 84 | rest += ((*node)->counters[i]>>=shift); | ||
| 85 | return rest; | ||
| 86 | } | ||
| 87 | |||
| 88 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | ||
| 89 | stats_network_node **childnode = &(*node)->children[i]; | ||
| 90 | int rest_val; | ||
| 91 | |||
| 92 | if( !*childnode ) continue; | ||
| 93 | |||
| 94 | rest += rest_val = stats_shift_down_network_count( childnode, depth, shift ); | ||
| 95 | |||
| 96 | if( rest_val ) continue; | ||
| 97 | |||
| 98 | free( (*node)->children[i] ); | ||
| 99 | (*node)->children[i] = NULL; | ||
| 100 | } | ||
| 101 | |||
| 102 | return rest; | ||
| 103 | } | ||
| 104 | |||
| 105 | static void stats_get_highscore_networks( stats_network_node *node, int depth, uint32_t node_value, int *scores, uint32_t *networks, int network_count ) { | ||
| 106 | int i; | ||
| 107 | |||
| 108 | if( !node ) return; | ||
| 109 | |||
| 110 | if( !depth++ ) { | ||
| 111 | memset( scores, 0, sizeof( *scores ) * network_count ); | ||
| 112 | memset( networks, 0, sizeof( *networks ) * network_count ); | ||
| 113 | } | ||
| 114 | |||
| 115 | if( depth < STATS_NETWORK_NODE_MAXDEPTH ) { | ||
| 116 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) | ||
| 117 | if( node->children[i] ) | ||
| 118 | stats_get_highscore_networks( node->children[i], depth, node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ), scores, networks, network_count ); | ||
| 119 | } else | ||
| 120 | for( i=0; i<STATS_NETWORK_NODE_COUNT; ++i ) { | ||
| 121 | int j=1; | ||
| 122 | if( node->counters[i] <= scores[0] ) continue; | ||
| 123 | |||
| 124 | while( (j<network_count) && (node->counters[i]>scores[j] ) ) ++j; | ||
| 125 | --j; | ||
| 126 | |||
| 127 | memmove( scores, scores + 1, j * sizeof( *scores ) ); | ||
| 128 | memmove( networks, networks + 1, j * sizeof( *networks ) ); | ||
| 129 | scores[ j ] = node->counters[ i ]; | ||
| 130 | networks[ j ] = node_value | ( i << ( 32 - depth * STATS_NETWORK_NODE_BITWIDTH ) ); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | static size_t stats_return_busy_networks( char * reply ) { | ||
| 135 | uint32_t networks[16]; | ||
| 136 | int scores[16]; | ||
| 137 | int i; | ||
| 138 | char * r = reply; | ||
| 139 | |||
| 140 | stats_get_highscore_networks( stats_network_counters_root, 0, 0, scores, networks, 16 ); | ||
| 141 | |||
| 142 | for( i=15; i>=0; ++i) | ||
| 143 | r += sprintf( r, "%08i: %d.%d.%d.0/24\n", scores[i], (networks[i]>>24)&0xff, (networks[i]>>16)&0xff, (networks[i]>>8)&0xff ); | ||
| 144 | |||
| 145 | return r - reply; | ||
| 146 | } | ||
| 147 | |||
| 148 | #endif | ||
| 149 | |||
| 46 | /* Converter function from memory to human readable hex strings */ | 150 | /* Converter function from memory to human readable hex strings */ |
| 47 | static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} | 151 | static char*to_hex(char*d,uint8_t*s){char*m="0123456789ABCDEF";char *t=d;char*e=d+40;while(d<e){*d++=m[*s>>4];*d++=m[*s++&15];}*d=0;return t;} |
| 48 | 152 | ||
| @@ -377,15 +481,20 @@ size_t return_stats_for_tracker( char *reply, int mode, int format ) { | |||
| 377 | return stats_httperrors_txt( reply ); | 481 | return stats_httperrors_txt( reply ); |
| 378 | case TASK_STATS_VERSION: | 482 | case TASK_STATS_VERSION: |
| 379 | return stats_return_tracker_version( reply ); | 483 | return stats_return_tracker_version( reply ); |
| 484 | case TASK_STATS_BUSY_NETWORKS: | ||
| 485 | return stats_return_busy_networks( reply ); | ||
| 380 | default: | 486 | default: |
| 381 | return 0; | 487 | return 0; |
| 382 | } | 488 | } |
| 383 | } | 489 | } |
| 384 | 490 | ||
| 385 | void stats_issue_event( ot_status_event event, int is_tcp, size_t event_data ) { | 491 | void stats_issue_event( ot_status_event event, int is_tcp, uint32_t event_data ) { |
| 386 | switch( event ) { | 492 | switch( event ) { |
| 387 | case EVENT_ACCEPT: | 493 | case EVENT_ACCEPT: |
| 388 | if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; | 494 | if( is_tcp ) ot_overall_tcp_connections++; else ot_overall_udp_connections++; |
| 495 | #ifdef WANT_LOG_NETWORKS | ||
| 496 | stat_increase_network_count( &stats_network_counters_root, 0, event_data ); | ||
| 497 | #endif | ||
| 389 | break; | 498 | break; |
| 390 | case EVENT_ANNOUNCE: | 499 | case EVENT_ANNOUNCE: |
| 391 | if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; | 500 | if( is_tcp ) ot_overall_tcp_successfulannounces++; else ot_overall_udp_successfulannounces++; |
