#include "flowood.h" #include "flowood_fun.h" #include "flwd_net.h" #include #include #include #include static unsigned long TO_KB = 1024; static unsigned long TO_MB = 1024 * 1024; static unsigned long TO_GB = 1024 * 1024 * 1024UL; static unsigned long TO_TB; /* 转换成人容易读的网络流量字符串, 如123bps, 34.5Mbps, 而不是一大串数字 */ static char *byte_convert_to_human(unsigned long long bytes, int interval, int multiple, char * byte_str) { if(0 == bytes){ return (char *)"0"; } bytes *= multiple; /* to network pattern, or human pattern */ bytes /= interval; /* per second */ if(bytes < TO_KB){ snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%llu", bytes); }else if(bytes < TO_MB){ snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fK", (float)bytes/TO_KB); }else if(bytes < TO_GB){ snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fM", (float)bytes/TO_MB); }else if(bytes < TO_TB){ snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fG", (float)bytes/TO_GB); }else{ snprintf(byte_str,TRAFFIC_STAT_STR_LEN,"%.2fT", (double)bytes/TO_TB); } return byte_str; } static void flwd_show_stream_stat(FILE *fp) { unsigned long long tot_stream_num = 0; int i; for(i = 0; i < FLWD_MAX_THREAD_NUM; i++){ if(flwd_thread_val[i].nat_info_table != NULL){ tot_stream_num += MESA_htable_get_elem_num(flwd_thread_val[i].nat_info_table); } } fprintf(fp,"Total stream number is:%llu\n", tot_stream_num); return; } static void flwd_pkt_flow_stat(FILE *fp) { int tseq; char human_byte_str[TRAFFIC_STAT_STR_LEN], human_bps_str[TRAFFIC_STAT_STR_LEN]; static unsigned long long history_eth_pkt_sum = 0, history_ip_pkt_sum = 0, history_tcp_pkt_sum = 0, history_udp_pkt_sum = 0; static unsigned long long history_eth_byte_sum = 0, history_ip_byte_sum = 0, history_tcp_byte_sum = 0, history_udp_byte_sum = 0; unsigned long long eth_pkt_sum = 0, ip_pkt_sum = 0, tcp_pkt_sum = 0, udp_pkt_sum = 0; unsigned long long eth_byte_sum = 0, ip_byte_sum = 0, tcp_byte_sum = 0, udp_byte_sum = 0; for(tseq = 0; tseq < flwd_cfg_val.tot_thread_count; tseq++){ eth_pkt_sum += flwd_thread_val[tseq].pkt_stat.eth_pkt_num; ip_pkt_sum += flwd_thread_val[tseq].pkt_stat.ip_pkt_num; tcp_pkt_sum += flwd_thread_val[tseq].pkt_stat.tcp_pkt_num; udp_pkt_sum += flwd_thread_val[tseq].pkt_stat.udp_pkt_num; eth_byte_sum += flwd_thread_val[tseq].pkt_stat.eth_pkt_byte; ip_byte_sum += flwd_thread_val[tseq].pkt_stat.ip_pkt_byte; tcp_byte_sum += flwd_thread_val[tseq].pkt_stat.tcp_pkt_byte; udp_byte_sum += flwd_thread_val[tseq].pkt_stat.udp_pkt_byte; } fprintf(fp,"%-10s %12s %12s %12s %12s\n","PKT-TYPE", "total_pkt", "total_len","pps", "bps"); fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "Ethernet", eth_pkt_sum, byte_convert_to_human(eth_byte_sum, 1, 1, human_byte_str), eth_pkt_sum-history_eth_pkt_sum, byte_convert_to_human(eth_byte_sum-history_eth_byte_sum, 1, 8, human_bps_str)); fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "IPv4", ip_pkt_sum, byte_convert_to_human(ip_byte_sum, 1, 1, human_byte_str), ip_pkt_sum-history_ip_pkt_sum, byte_convert_to_human(ip_byte_sum-history_ip_byte_sum, 1, 8, human_bps_str)); fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "TCP", tcp_pkt_sum, byte_convert_to_human(tcp_byte_sum, 1, 1, human_byte_str), history_tcp_pkt_sum-history_tcp_pkt_sum, byte_convert_to_human(tcp_byte_sum-history_tcp_byte_sum, 1, 8, human_bps_str)); fprintf(fp,"%-10s %12llu %12s %12llu %12s\n", "UDP", udp_pkt_sum, byte_convert_to_human(udp_byte_sum, 1, 1, human_byte_str), udp_pkt_sum-history_udp_pkt_sum, byte_convert_to_human(udp_byte_sum-history_udp_byte_sum, 1, 8, human_bps_str)); history_eth_pkt_sum = eth_pkt_sum; history_ip_pkt_sum = ip_pkt_sum; history_tcp_pkt_sum = tcp_pkt_sum; history_udp_pkt_sum = udp_pkt_sum; history_eth_byte_sum = eth_byte_sum; history_ip_byte_sum = ip_byte_sum; history_tcp_byte_sum = tcp_byte_sum; history_udp_byte_sum = udp_byte_sum; flwd_show_stream_stat(fp); } typedef struct{ unsigned long long tot_ip_pool_num; /* 总量无所谓, 协议无关 */ unsigned long long usable_ip_pool_tcp_num; /* 可用IP要根据TCP, UDP区别 */ unsigned long long usable_ip_pool_udp_num; /* 可用IP要根据TCP, UDP区别 */ }flwd_ip_pool_num_stat_t; typedef struct{ FILE *detail_log_fp; /* 为了区别度, static, dynamic分为两个文件 */ flwd_active_ip_type_t act_ip_type; /* static, dynamic */ int this_callback_location; /* inland, outland */ flwd_ip_pool_num_stat_t ip_pool_num[2]; }flwd_ip_pool_log_stat_t; static flwd_ip_pool_log_stat_t static_ip_pool_log_info; /* 0:inland; 1:outland */ static flwd_ip_pool_log_stat_t dynamic_ip_pool_log_info; /* 0:inland; 1:outland */ static int flwd_ip_pool_num_stat_cb(const uchar * key, uint size, void * data, void * user) { flwd_active_ip_t *act_ip_list_head = (flwd_active_ip_t *)data; flwd_active_ip_t *tmp_ip; MESA_list_t *list_node; flwd_ip_pool_log_stat_t *st_ip_pool_log_info = (flwd_ip_pool_log_stat_t *)user; char ip_str[64]; long usable_ip_tcpport_num, usable_ip_udpport_num; if((FLWD_ACT_IP_STATIC == act_ip_list_head->ip_origin_type) && (strncmp((const char*)"GPID", (const char*)key, 4) != 0)){ /* NOTE: htable中还有一批用ip为key, 为了让端口回收时可以找到对应的IP节点, 此hnode和以GPIDxxx为key的数据是一样的, 日志会写重复, 跳过即可 */ return ITERATE_CB_RET_CONTINUE_FLAG; } list_node = &act_ip_list_head->active_ip_list_node; /* dynamic和static一样, 第一个节点从act_ip_list_head自身开始遍历 */ do{ tmp_ip = (flwd_active_ip_t *)list_node->quiddity; st_ip_pool_log_info->ip_pool_num[st_ip_pool_log_info->this_callback_location].tot_ip_pool_num++; usable_ip_tcpport_num = MESA_list_count_get_count(&tmp_ip->usable_tcp_sport_list_head); if(usable_ip_tcpport_num > 0){ st_ip_pool_log_info->ip_pool_num[st_ip_pool_log_info->this_callback_location].usable_ip_pool_tcp_num++; } usable_ip_udpport_num = MESA_list_count_get_count(&tmp_ip->usable_udp_sport_list_head); if(usable_ip_udpport_num > 0){ st_ip_pool_log_info->ip_pool_num[st_ip_pool_log_info->this_callback_location].usable_ip_pool_udp_num++; } if(NULL != st_ip_pool_log_info->detail_log_fp){ flwd_ipt_ntop_r(&tmp_ip->active_ip_net_order, ip_str, 64); fprintf(st_ip_pool_log_info->detail_log_fp, "%s, %s ---> TCP: %6d, %6ld\n", flwd_ip_region_ntop(st_ip_pool_log_info->this_callback_location), ip_str, (int)flwd_act_ip_get_usable_tcp_sport_num(), usable_ip_tcpport_num); fprintf(st_ip_pool_log_info->detail_log_fp, "%s, %s ---> UDP: %6d, %6ld\n", flwd_ip_region_ntop(st_ip_pool_log_info->this_callback_location), ip_str, (int)flwd_act_ip_get_usable_udp_sport_num(), usable_ip_udpport_num); } list_node = list_node->nextele; }while(list_node != &act_ip_list_head->active_ip_list_node); return ITERATE_CB_RET_CONTINUE_FLAG; } static void flwd_ip_pool_num_stat(void *htable, flwd_ip_pool_log_stat_t *st_ip_pool_log_info) { MESA_htable_iterate_bytime(htable, ITERATE_TYPE_NEWEST_FIRST, flwd_ip_pool_num_stat_cb, (void *)st_ip_pool_log_info); } static void flwd_log_module_delimiter(FILE *fp_flwd_stat) { fprintf(fp_flwd_stat, "--------------------------------------------------------------\n"); } static void flwd_ip_pool_stat(FILE *fp_flwd_stat) { int tseq; int v4_or_v6; memset(&static_ip_pool_log_info, 0, sizeof(static_ip_pool_log_info)); memset(&dynamic_ip_pool_log_info, 0, sizeof(dynamic_ip_pool_log_info)); static_ip_pool_log_info.detail_log_fp = fopen("./log/static_ip_pool_detail.log", "w+"); if(static_ip_pool_log_info.detail_log_fp){ fprintf(static_ip_pool_log_info.detail_log_fp, "#location, ip_pool_addr --> protocol, total_port_num, usable_port_num\n"); } dynamic_ip_pool_log_info.detail_log_fp = fopen("./log/dynamic_ip_pool_detail.log", "w+"); if(dynamic_ip_pool_log_info.detail_log_fp){ fprintf(dynamic_ip_pool_log_info.detail_log_fp, "##location, ip_pool_addr --> protocol, total_port_num, usable_port_num\n"); } for(tseq = 0; tseq < flwd_cfg_val.tot_thread_count; tseq++){ /****** dynamic ****/ pthread_rwlock_rdlock(&flwd_thread_val[tseq].flwd_ip_pool_dynamic_rwlock); dynamic_ip_pool_log_info.act_ip_type = FLWD_ACT_IP_DYNAMIC; for(v4_or_v6 = 0; v4_or_v6 < 2; v4_or_v6++){ dynamic_ip_pool_log_info.this_callback_location = 0; flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_dynamic_htable[v4_or_v6][0], &dynamic_ip_pool_log_info); dynamic_ip_pool_log_info.this_callback_location = 1; flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_dynamic_htable[v4_or_v6][1], &dynamic_ip_pool_log_info); } pthread_rwlock_unlock(&flwd_thread_val[tseq].flwd_ip_pool_dynamic_rwlock); /****** static ****/ pthread_rwlock_rdlock(&flwd_thread_val[tseq].flwd_ip_pool_static_rwlock); static_ip_pool_log_info.act_ip_type = FLWD_ACT_IP_STATIC; for(v4_or_v6 = 0; v4_or_v6 < 2; v4_or_v6++){ static_ip_pool_log_info.this_callback_location = 0; flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_static_htable[v4_or_v6][0], &static_ip_pool_log_info); static_ip_pool_log_info.this_callback_location = 1; flwd_ip_pool_num_stat(flwd_thread_val[tseq].flwd_ip_pool_static_htable[v4_or_v6][1], &static_ip_pool_log_info); } pthread_rwlock_unlock(&flwd_thread_val[tseq].flwd_ip_pool_static_rwlock); } fprintf(fp_flwd_stat, "static_ip_pool_num:\n"); fprintf(fp_flwd_stat, "\tinland\n"); fprintf(fp_flwd_stat, "\t\ttotal \t: %llu\n", static_ip_pool_log_info.ip_pool_num[0].tot_ip_pool_num); fprintf(fp_flwd_stat, "\t\tusable\t: TCP:%llu \tUDP:%llu\n", static_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_tcp_num, static_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_udp_num); fprintf(fp_flwd_stat, "\toutland\n"); fprintf(fp_flwd_stat, "\t\ttotal \t: %llu\n", static_ip_pool_log_info.ip_pool_num[1].tot_ip_pool_num); fprintf(fp_flwd_stat, "\t\tusable\t: TCP:%llu \tUDP:%llu\n", static_ip_pool_log_info.ip_pool_num[1].usable_ip_pool_tcp_num, static_ip_pool_log_info.ip_pool_num[1].usable_ip_pool_udp_num); fprintf(fp_flwd_stat, "dynamic_ip_pool_num:\n"); fprintf(fp_flwd_stat, "\tinland\n"); fprintf(fp_flwd_stat, "\t\ttotal \t: %llu\n", dynamic_ip_pool_log_info.ip_pool_num[0].tot_ip_pool_num); fprintf(fp_flwd_stat, "\t\tusable\t: TCP:%llu \tUDP:%llu\n", dynamic_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_tcp_num, dynamic_ip_pool_log_info.ip_pool_num[0].usable_ip_pool_udp_num); fclose(static_ip_pool_log_info.detail_log_fp); fclose(dynamic_ip_pool_log_info.detail_log_fp); } void *flwd_stat_thread(void *arg) { time_t last_time = 0; struct timeval cur_time_val; FILE *fp_flwd_stat; TO_GB = 1024 * 1024 * 1024UL; TO_TB = (unsigned long long)1024 * 1024 * 1024 * 1024UL; while(1){ gettimeofday(&cur_time_val, NULL); flwd_global_val.cur_time = cur_time_val.tv_sec; flwd_global_val.cur_time_usec = cur_time_val.tv_sec * 1000000 + cur_time_val.tv_usec; if(last_time < flwd_global_val.cur_time){ /* NOTE: 很多不同模块需要同时写入flwd_stat.log, 函数外面打开文件句柄 */ fp_flwd_stat = fopen("./log/flwd_stat.log", "w+"); if(NULL == fp_flwd_stat){ printf("Can't open file:%s, %s\n", "./log/flwd_stat.log", strerror(errno)); continue; } flwd_pkt_flow_stat(fp_flwd_stat); flwd_log_module_delimiter(fp_flwd_stat); flwd_ip_pool_stat(fp_flwd_stat); last_time = flwd_global_val.cur_time; fclose(fp_flwd_stat); } usleep(50); } return NULL; }