diff options
| author | lijia <[email protected]> | 2018-10-24 09:36:45 +0800 |
|---|---|---|
| committer | lijia <[email protected]> | 2018-10-24 09:36:45 +0800 |
| commit | 86a43b4d325ddc850fa9dc4711670880f35b11e8 (patch) | |
| tree | 8356a056ac9bfb8cf14fcf57f113dd306b4277d1 /src/common | |
create new project.
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/Makefile | 42 | ||||
| -rw-r--r-- | src/common/flwd_arp.c | 252 | ||||
| -rw-r--r-- | src/common/flwd_common_hash.c | 98 | ||||
| -rw-r--r-- | src/common/flwd_common_maat.c | 153 | ||||
| -rw-r--r-- | src/common/flwd_common_stack.c | 449 | ||||
| -rw-r--r-- | src/common/flwd_common_tool.c | 911 | ||||
| -rw-r--r-- | src/common/flwd_compat_marsio_hash.c | 23 | ||||
| -rw-r--r-- | src/common/flwd_network_connect.c | 363 | ||||
| -rw-r--r-- | src/common/flwd_sendpacket.c | 138 | ||||
| -rw-r--r-- | src/common/flwd_status.c | 275 | ||||
| -rw-r--r-- | src/common/linux_jhash_algo.c | 267 |
11 files changed, 2971 insertions, 0 deletions
diff --git a/src/common/Makefile b/src/common/Makefile new file mode 100644 index 0000000..ebc5d73 --- /dev/null +++ b/src/common/Makefile @@ -0,0 +1,42 @@ +#CC=gcc +CC=g++ +CCC=g++ + +TARGET=flwd_common_stack.o flwd_sendpacket.o flwd_status.o flwd_common_tool.o linux_jhash_algo.o +TARGET += flwd_compat_marsio_hash.o +TARGET += flwd_arp.o +TARGET += flwd_common_hash.o +TARGET += flwd_common_maat.o +TARGET += flwd_network_connect.o + + +CFLAGS +=-g -Wall -fPIC -shared -D_GNU_SOURCE=1 -D_BSD_SOURCE=1 -D__USE_MISC=1 -D__FAVOR_BSD=1 -D__USE_BSD=1 + +H_DIR=-I../../inc +H_DIR+=-I/opt/MESA/include +H_DIR+=-I/opt/MESA/include/MESA + +LIBPATH=../../lib +LIB=-L/opt/MESA/lib -lpthread + + +all:$(TARGET) + +flwd_common_hash.o:flwd_common_hash.c + $(CC) -c -O3 $(CFLAGS) -O3 -I. $(H_DIR) $< + +linux_jhash_algo.o:linux_jhash_algo.c + $(CC) -c -O3 $(CFLAGS) -O3 -I. $(H_DIR) $< + +flwd_common_stack.o:flwd_common_stack.c + $(CC) -c -O3 $(CFLAGS) -O3 -I. $(H_DIR) $< + + +.c.o: + $(CC) -c $(CFLAGS) -I. $(H_DIR) $< + +.cpp.o: + $(CCC) -c $(CFLAGS) -I. $(H_DIR) $< + +clean: + rm -f *.o diff --git a/src/common/flwd_arp.c b/src/common/flwd_arp.c new file mode 100644 index 0000000..b593f09 --- /dev/null +++ b/src/common/flwd_arp.c @@ -0,0 +1,252 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_htable.h" +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_list_count.h" +#include <assert.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> +#include <linux/if_arp.h> + +/* + ����SNAT, �װ��϶��ǿͻ��˷���, access���ؼ�¼�¿ͻ��˵�mac, ����ÿ�η�������ѯARP, �ÿռ任ʱ��. + + ����DNAT, �װ����ⲿ��������, �����ڲ�������, ����Ŀ������MAC��û��, ��Ҫ��������ARP��ѯ, + ARP�����첽ģʽ, ��һ�β�ѯ�϶�û���, �Ȱѵ�ǰ������, ���õ�ARPӦ���, �洢��nat_info, �����İ��Ͳ����ٲ�. +*/ + +static const unsigned char G_BROADCAST_MAC_ADDR[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; /* �㲥MAC */ + +static void flwd_arp_query_ipv4(int tid, unsigned int dip_net, flwd_device_handle_t *io_handle) +{ + int ret; + void *send_mbuff = io_handle->low_level_mbuff_malloc(io_handle, tid, sizeof(flwd_eth_hdr_t) + sizeof(flwd_arp_hdr_t)); + char *unsend_data_ptr = io_handle->low_level_mbuff_mtod(send_mbuff); + + flwd_eth_hdr_t *ehdr = (flwd_eth_hdr_t *)unsend_data_ptr; + + memcpy(ehdr->h_source, io_handle->io_para.local_mac_addr, ETH_ALEN); + memcpy(ehdr->h_dest, G_BROADCAST_MAC_ADDR, ETH_ALEN); + ehdr->h_proto = htons(ETH_P_ARP); + + flwd_arp_hdr_t *arphdr = (flwd_arp_hdr_t *)(unsend_data_ptr + sizeof(flwd_eth_hdr_t)); + + arphdr->ar_hrd = htons(ARPHRD_ETHER); + arphdr->ar_pro = htons(ETH_P_IP); + arphdr->ar_hln = ETH_ALEN; + arphdr->ar_pln = sizeof(int); + arphdr->ar_op = htons(ARPOP_REQUEST); + + memcpy(arphdr->ar_sha, io_handle->io_para.local_mac_addr, ETH_ALEN); + memcpy(arphdr->ar_spa, &io_handle->io_para.device_ip_net_order, sizeof(int)); + memset(arphdr->ar_tha, 0, ETH_ALEN); + memcpy(arphdr->ar_tpa, &dip_net, sizeof(int)); + + io_handle->low_level_mbuff_set_pkt_len(send_mbuff, sizeof(flwd_eth_hdr_t) + sizeof(flwd_arp_hdr_t)); + + ret = io_handle->low_level_send(io_handle, tid, send_mbuff); + if(ret < 0){ + flwd_log(30, "send arp query packet error! ret = %d.\n", ret); + }else{ + char ip_str[16]; + inet_ntop(AF_INET, &dip_net, ip_str, 16); + flwd_log(10, "send arp query dip:%s.\n", ip_str); + } +} + + +static void flwd_arp_net_query(int tid, const flwd_ip_t *dip_union, flwd_device_handle_t *io_handle) +{ + if(FLWD_IP_ADDR_TYPE_V4 == dip_union->addr_type){ + flwd_arp_query_ipv4(tid, dip_union->addr_ipv4, io_handle); + }else{ + /* TODO, IPv6 <---> ARP, IPv6�ھӷ���Э�� */ + assert(0); + } + +} + +/* + ���ݵ�ǰ���ݰ�����ʵĿ��IP, �ͱ��ص�ַ, + �ж϶���ethernetMAC��ַ, Ӧ��ʹ���ĸ�IP? +*/ +static unsigned int flwd_judge_layer2_dipv4(unsigned int real_target_ip_net, flwd_device_handle_t *io_handle) +{ + unsigned int real_target_ip_host = ntohl(real_target_ip_net); + unsigned int local_ip_mask_host = ntohl(io_handle->io_para.device_ip_mask_net_order); + unsigned int local_ip_host = ntohl(io_handle->io_para.device_ip_net_order); + + if((real_target_ip_host & local_ip_mask_host) == (local_ip_host & local_ip_mask_host)){ + /* Ŀ��IP��ͬһ������, ֱ��ʹ��Ŀ��IP, ��ѯARP�� */ + return real_target_ip_net; + } + + /* Ŀ��IP����ͬһ������, ��Ҫ��Խ�����豸, ʹ�����ص�IP��ѯARP�� */ + return io_handle->io_para.gateway_ip_net_order; +} + + +static struct in6_addr * flwd_judge_layer2_dipv6(struct in6_addr *real_target_ip_net, + flwd_device_handle_t *io_handle) +{ + /* TODO, IPv6 */ + return real_target_ip_net; +} + +int flwd_arp_table_query(int tid, flwd_ip_t *target_ip, + flwd_device_handle_t *io_handle, unsigned char result_mac[6]) +{ + unsigned char *res; + +#if FLWD_NO_ACTIVE_ARP_QUERY + /* 172.16.1.201, 10.0.6.201 */ + static unsigned char acc_to_fwd_gateway_mac[6] = {0x74, 0x86,0x7a,0xd0,0x12,0xfc}; + + /* 172.16.1.229, 10.0.6.229 */ + static unsigned char fwd_to_acc_gateway_mac[6] = {0x74, 0x86, 0x7A, 0xD0, 0x1B, 0x30}; + + if(0xC90110AC == target_ip->addr_ipv4){ + memcpy(result_mac, acc_to_fwd_gateway_mac, 6); + return 0; + }else if(0xE50110AC == target_ip->addr_ipv4){ + memcpy(result_mac, fwd_to_acc_gateway_mac, 6); + return 0; + }else{ + abort(); + } +#else + unsigned char *hkey; + unsigned int hkey_size; + unsigned int local_net_dipv4; + + if(FLWD_IP_ADDR_TYPE_V4 == target_ip->addr_type){ + local_net_dipv4 = flwd_judge_layer2_dipv4(target_ip->addr_ipv4, io_handle); + hkey = (unsigned char *)&local_net_dipv4; + hkey_size = sizeof(int); + + target_ip->addr_ipv4 = local_net_dipv4; + }else{ + struct in6_addr *local_net_dip6 = flwd_judge_layer2_dipv6(&target_ip->addr_ipv6, io_handle); + hkey = (unsigned char *)local_net_dip6; + hkey_size = sizeof(struct in6_addr); + } + + pthread_rwlock_rdlock(&flwd_global_val.flwd_arp_htable_rwlock); + res = (unsigned char *)MESA_htable_search(flwd_global_val.flwd_arp_table, hkey, hkey_size); + if(res != NULL){ + memcpy(result_mac, res, 6); /* ��������������, �Ƚ��鵽�Ľ����������, �������̾ͱ������̸߳���, ���߳�ʱ��̭��! */ + } + pthread_rwlock_unlock(&flwd_global_val.flwd_arp_htable_rwlock); + + if(NULL == res){ + flwd_arp_net_query(tid, target_ip, io_handle); /* ����鲻��, ����������Ŀ�귢��һ�β�ѯ�� */ + return -1; + } +#endif + + return 0; +} + +void flwd_arp_response_update(const flwd_arp_hdr_t *arp_hdr) +{ + unsigned char *res_mac = (unsigned char *)malloc(ETH_ALEN); + int ret; + + memcpy(res_mac, arp_hdr->ar_sha, ETH_ALEN); + + pthread_rwlock_wrlock(&flwd_global_val.flwd_arp_htable_rwlock); + ret = MESA_htable_add(flwd_global_val.flwd_arp_table, arp_hdr->ar_spa, sizeof(int), res_mac); + pthread_rwlock_unlock(&flwd_global_val.flwd_arp_htable_rwlock); + + if(ret < 0){ + free(res_mac); + } +} + +static int flwd_arp_htable_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2) +{ + if(size1 != size2){ + return (int)size1 - (int)size2; + } + + return memcmp(key1, key2, size1); +} + + +static uint flwd_arp_htable_key2index(const MESA_htable_handle table, const uchar * key, uint size) +{ + uint i; + uint seed = 13131; // 31 131 1313 13131 131313 etc.. + uint hash = 31; + + for(i = 0; i < size; i++){ + hash = hash * seed + (*key++); + } + + return hash; +} + +static void flwd_arp_htable_data_free(void *data) +{ + free(data); +} + +int flwd_arp_table_init(void) +{ + int opt_int; + + MESA_htable_handle htable = MESA_htable_born(); + + opt_int = 0; /* �ⲿʹ�ö�д������, htable������ģʽ */ + MESA_htable_set_opt(htable, MHO_THREAD_SAFE, &opt_int, sizeof(int)); + + opt_int = 1024; + MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int)); + + opt_int = 10000; + MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &opt_int, sizeof(int)); + + opt_int = 120; + MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &opt_int, sizeof(int)); + + opt_int = HASH_ELIMINATE_ALGO_FIFO; + MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_arp_htable_key_cmp, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_arp_htable_key2index, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_arp_htable_data_free, sizeof(void *)); + + ////MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, (void *)&flwd_access_nat_htable_data_expire_notify, sizeof(void *)); + + opt_int = 1; + MESA_htable_set_opt(htable, MHO_AUTO_UPDATE_TIME, &opt_int, sizeof(int)); + + opt_int = 0; + MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, &opt_int, sizeof(int)); + + opt_int = 100; + MESA_htable_set_opt(htable, MHO_HASH_LIST_COLLIDE_THRESHOLD, &opt_int, sizeof(int)); + + char *err_log = (char *)"./log/flwd_arp_hash_collide.log"; + MESA_htable_set_opt(htable, MHO_HASH_LOG_FILE, (void *)err_log, strlen(err_log)); + + int ret = MESA_htable_mature(htable); + assert(ret >= 0); + + flwd_global_val.flwd_arp_table = htable; + + pthread_rwlock_init(&flwd_global_val.flwd_arp_htable_rwlock, NULL); + + return 0; +} + diff --git a/src/common/flwd_common_hash.c b/src/common/flwd_common_hash.c new file mode 100644 index 0000000..563c111 --- /dev/null +++ b/src/common/flwd_common_hash.c @@ -0,0 +1,98 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_htable.h" +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_list_count.h" +#include <assert.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> + +uchar * flwd_nat_htable_key_dup(const uchar *key, uint key_size) +{ + const flwd_tuple5_t *stack_tuple5 = (flwd_tuple5_t *)key; + flwd_tuple5_t *heap_tuple5 = (flwd_tuple5_t *)malloc(sizeof(flwd_tuple5_t)); + + memcpy(heap_tuple5, stack_tuple5, sizeof(flwd_tuple5_t)); + + if(FLWD_IP_ADDR_TYPE_V6 == stack_tuple5->addr_type){ + /* �����v6, ��Ҫ����mallo, memcpyIP��ַ, ע��free!! */ + heap_tuple5->ippair_v6 = (flwd_ippair_v6_t *)malloc(sizeof(flwd_ippair_v6_t)); + memcpy(&heap_tuple5->ippair_v6->sip_net_order, &stack_tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + memcpy(&heap_tuple5->ippair_v6->dip_net_order, &stack_tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + } + + return (uchar *)heap_tuple5; +} + +void flwd_nat_htable_key_free(uchar *key, uint key_size) +{ + flwd_tuple5_t *raw_tuple5 = (flwd_tuple5_t *)key; + + if(FLWD_IP_ADDR_TYPE_V6 == raw_tuple5->addr_type){ + free(raw_tuple5->ippair_v6); + } + + free(key); + + return; +} + +uint flwd_nat_htable_key2index(const MESA_htable_handle table, const uchar * key, uint size) +{ + const flwd_tuple5_t *tuple5 = (flwd_tuple5_t *)key; + + return flwd_tuple5_hash(tuple5, 0); +} + + +int flwd_nat_htable_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2) +{ + const flwd_tuple5_t *tp1; + const flwd_tuple5_t *tp2; + + tp1 = (flwd_tuple5_t *)key1; + tp2 = (flwd_tuple5_t *)key2; + + if(tp1->addr_type != tp2->addr_type){ + return -1; + } + + if(tp1->protocol != tp2->protocol){ + return -1; + } + + if(tp1->sport_net_order != tp2->sport_net_order){ + return -1; + } + + if(tp1->dport_net_order != tp2->dport_net_order){ + return -1; + } + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tp1->addr_type)){ + if(tp1->ippair_v4.sip_net_order != tp2->ippair_v4.sip_net_order){ + return -1; + } + if(tp1->ippair_v4.dip_net_order != tp2->ippair_v4.dip_net_order){ + return -1; + } + }else{ + if(memcmp(&tp1->ippair_v6->sip_net_order, &tp2->ippair_v6->sip_net_order, sizeof(struct in6_addr))){ + return -1; + } + if(memcmp(&tp1->ippair_v6->dip_net_order, &tp2->ippair_v6->dip_net_order, sizeof(struct in6_addr))){ + return -1; + } + } + + return 0; +} + diff --git a/src/common/flwd_common_maat.c b/src/common/flwd_common_maat.c new file mode 100644 index 0000000..b18671c --- /dev/null +++ b/src/common/flwd_common_maat.c @@ -0,0 +1,153 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include "MESA_htable.h" +#include "Maat_rule.h" +#include <linux/if_ether.h> +#include <linux/if_arp.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> + + +void * flwd_maat_summon(const char *cfg_file, const char *cfg_section) +{ + char cfg_ip[32]; + char str_tmp[256]; + int ret, tmp_int; + int maat_cfg_src_type; + unsigned short redis_port; + void *maat_handle; + + MESA_load_profile_string_def(FLWD_CONFIG_FILE, cfg_section, "table_info", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->table_info invalid!"); + return NULL; + } + flwd_cfg_val.table_info_path = strdup(str_tmp); + + MESA_load_profile_int_def(cfg_file, cfg_section, "maat_cfg_source", &maat_cfg_src_type, FLWD_MAAT_SRC_JSON); + + if(FLWD_MAAT_SRC_LOCAL_FILE == maat_cfg_src_type){ + MESA_load_profile_string_def(cfg_file, cfg_section, "inc_dir", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->inc_dir invalid!"); + return NULL; + } + flwd_cfg_val.inc_cfg_dir = strdup(str_tmp); + + MESA_load_profile_string_def(cfg_file, cfg_section, "full_dir", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->full_dir invalid!"); + return NULL; + } + flwd_cfg_val.full_cfg_dir = strdup(str_tmp); + + maat_handle = Maat_summon_feather( + FLWD_MAX_THREAD_NUM, + flwd_cfg_val.table_info_path, + flwd_cfg_val.full_cfg_dir, + flwd_cfg_val.inc_cfg_dir, + flwd_global_val.maat_log_handle); + + }else if(FLWD_MAAT_SRC_JSON == maat_cfg_src_type){ + MESA_load_profile_string_def(FLWD_CONFIG_FILE, cfg_section, "json_cfg_file", str_tmp, 256, "$"); + if('$' == str_tmp[0]){ + flwd_log(RLOG_LV_FATAL, "conf->json_cfg_file invalid!"); + return NULL; + } + flwd_cfg_val.maat_json_cfg_file = strdup(str_tmp); + + maat_handle = Maat_summon_feather_json( + FLWD_MAX_THREAD_NUM, + flwd_cfg_val.table_info_path, + flwd_cfg_val.maat_json_cfg_file, + flwd_global_val.maat_log_handle); + }else if(FLWD_MAAT_SRC_REDIS == maat_cfg_src_type){ + MESA_load_profile_string_def(cfg_file, cfg_section, "redis_server_ip", cfg_ip, 32, "$"); + if('$' == cfg_ip[0]){ + flwd_log(30, "Invalid config 'redis_server_ip'!\n"); + exit(1); + } + MESA_load_profile_int_def(cfg_file, cfg_section, "redis_server_port", &tmp_int, 0); + if(tmp_int <= 0 || tmp_int > 65535){ + flwd_log(30, "Invalid config 'redis_server_port'!\n"); + exit(1); + } + redis_port = (unsigned short)tmp_int; + + maat_handle = Maat_feather(FLWD_MAX_THREAD_NUM, flwd_cfg_val.table_info_path, flwd_global_val.maat_log_handle); + tmp_int = 1000; + Maat_set_feather_opt(maat_handle, MAAT_OPT_EFFECT_INVERVAL_MS, &tmp_int, sizeof(int)); + Maat_set_feather_opt(maat_handle, MAAT_OPT_STAT_ON, NULL, 0); + Maat_set_feather_opt(maat_handle, MAAT_OPT_STAT_FILE_PATH, "./log/maat_stat.log", strlen("./log/maat_stat.log") + 2); + ret = Maat_set_feather_opt(maat_handle, MAAT_OPT_REDIS_IP, cfg_ip, strlen(cfg_ip) + 2); + if(ret < 0){ + flwd_log(30, "Maat_set_feather_opt 'MAAT_OPT_REDIS_IP' error, value: %s!\n", cfg_ip); + exit(1); + } + ret = Maat_set_feather_opt(maat_handle, MAAT_OPT_REDIS_PORT, &redis_port, sizeof(short)); + if(ret < 0){ + flwd_log(30, "Maat_set_feather_opt 'MAAT_OPT_REDIS_PORT' error, value: %u!\n", redis_port); + exit(1); + } + + MESA_load_profile_int_def(cfg_file, cfg_section, "redis_index", &tmp_int, -1); + if(-1 == tmp_int){ + flwd_log(30, "Invalid config 'redis_index'!\n"); + exit(1); + } + + ret = Maat_set_feather_opt(maat_handle, MAAT_OPT_REDIS_INDEX, &tmp_int, sizeof(int)); + if(ret < 0){ + flwd_log(30, "Maat_set_feather_opt 'MAAT_OPT_REDIS_INDEX' error, value: %d!\n", tmp_int); + exit(1); + } + + Maat_initiate_feather(maat_handle); + }else{ + flwd_log(30, "Invalid config 'maat_cfg_source'! [1:json; 2:file; 3:redis]\n"); + exit(1); + } + + if(NULL == maat_handle){ + flwd_log(30, "maat init error!\n"); + return NULL; + } + + + + return maat_handle; +} + + +int flwd_maat_table_register(void *maat_handle, int inner_table_index) +{ + assert(inner_table_index < FLWD_MAAT_TB_MAX); + flwd_global_val.maat_table_info[inner_table_index].table_id = + Maat_table_register(maat_handle, flwd_global_val.maat_table_info[inner_table_index].table_name); + + assert(flwd_global_val.maat_table_info[inner_table_index].table_id >= 0); + return flwd_global_val.maat_table_info[inner_table_index].table_id; +} + +/* + NOTE: + ��Щ�������ƶ����ĵ��涨, ���������, ��ʱд����������. +*/ +int flwd_maat_talbe_name_init(void) +{ + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_COMPILE].table_name = strdup("IR_POLICY_COMPILE"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_GROUP].table_name = strdup("IR_POLICY_GROUP"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_IP].table_name = strdup("IR_POLICY_IP"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB].table_name = strdup("IR_STATIC_IP_POOL_CB"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB].table_name = strdup("IR_DYN_SIFT_IP_CB"); + flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_CONN_IP].table_name = strdup("IR_DYN_CONN_IP"); + + return 0; +} + + diff --git a/src/common/flwd_common_stack.c b/src/common/flwd_common_stack.c new file mode 100644 index 0000000..9dfc09b --- /dev/null +++ b/src/common/flwd_common_stack.c @@ -0,0 +1,449 @@ +/* + ͨ��Э��ջģ��, ������ARP, ICMPЭ��Ĵ���. +*/ + +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include <linux/if_ether.h> +#include <linux/if_arp.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> +#include <arpa/inet.h> + +const unsigned char G_FLWD_BROADCAST_ADDR[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + +/* + TODO: + �����ӿ�����IP�����Ĭ��·��, ʵ��������IPЭ��ջ, + ��Ŀ���������ܲ���һ������(��·������VLAN), + ��Ҫ��������arp����һ������. +*/ + + +static inline int sendpacket_in_cksum(u_int16_t *addr, int len) +{ + int sum; + int nleft; + u_int16_t ans; + u_int16_t *w; + + sum = 0; + ans = 0; + nleft = len; + w = addr; + + while (nleft > 1) + { + sum += *w++; + nleft -= 2; + } + if (nleft == 1) + { + *(char *)(&ans) = *(char *)w; + sum += ans; + } + return (sum); +} + +/* + * Checksum stuff + */ +#define SENDPACKET_CKSUM_CARRY(x) \ + (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff)) + +int flwd_sendpacket_do_checksum(char *buf, int protocol, int len) +{ + flwd_ipv4_hdr_t *iph_p; + flwd_ipv6_hdr_t *ip6h_p; + int ip_hl; + int sum; + int is_ipv6 = 0; + + sum = 0; + iph_p = (flwd_ipv4_hdr_t *)buf; + + if(4 == iph_p->ip_v) /* IP�汾���ֶΣ�IPv4��IPv6��ʽ����ͬ�� */ + { + ip_hl = iph_p->ip_hl << 2; + ip6h_p = NULL; + } + else if(6 == iph_p->ip_v) + { + ip6h_p = (flwd_ipv6_hdr_t *)buf; + iph_p = NULL; + ip_hl = sizeof(flwd_ipv6_hdr_t); + is_ipv6 = 1; + } + else + { + return (-1); + } + + /* + * Dug Song came up with this very cool checksuming implementation + * eliminating the need for explicit psuedoheader use. Check it out. + */ + switch (protocol) + { + /* + * Style note: normally I don't advocate declaring variables inside + * blocks of control, but it makes good sense here. -- MDS + */ + case IPPROTO_TCP: + { + flwd_tcp_hdr_t *tcph_p = + (flwd_tcp_hdr_t *)(buf + ip_hl); + +#if (STUPID_SOLARIS_CHECKSUM_BUG) + tcph_p->th_sum = tcph_p->th_off << 2; + return (1); +#endif /* STUPID_SOLARIS_CHECKSUM_BUG */ + + tcph_p->th_sum = 0; + /* 2012-03-19 LiJia add, for IPv6 */ + if(is_ipv6) + { + sum = sendpacket_in_cksum((u_int16_t *)&ip6h_p->ip6_src, 32); + } + else + { + sum = sendpacket_in_cksum((u_int16_t *)&iph_p->ip_src, 8); + } + sum += ntohs(IPPROTO_TCP + len); + sum += sendpacket_in_cksum((u_int16_t *)tcph_p, len); + tcph_p->th_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + case IPPROTO_UDP: + { + flwd_udp_hdr_t *udph_p = + (flwd_udp_hdr_t *)(buf + ip_hl); + + udph_p->uh_sum = 0; + /* 2012-03-19 LiJia add, for IPv6 */ + if(is_ipv6) + { + sum = sendpacket_in_cksum((u_int16_t *)&ip6h_p->ip6_src, 32); + } + else + { + sum = sendpacket_in_cksum((u_int16_t *)&iph_p->ip_src, 8); + } + sum += ntohs(IPPROTO_UDP + len); + sum += sendpacket_in_cksum((u_int16_t *)udph_p, len); + udph_p->uh_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + case IPPROTO_IP: /* Dummy protocol for TCP. */ + { + iph_p->ip_sum = 0; + sum = sendpacket_in_cksum((u_int16_t *)iph_p, len); + iph_p->ip_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + case IPPROTO_ICMP: + { + flwd_icmp_hdr_t *icmph_p = + (flwd_icmp_hdr_t *)(buf + ip_hl); + + icmph_p->icmp_sum = 0; + sum = sendpacket_in_cksum((u_short *)icmph_p, len); + icmph_p->icmp_sum = SENDPACKET_CKSUM_CARRY(sum); + break; + } + + default: + { + return (-1); + } + } + + return (1); +} + + + +/* + �����������߰���İ�(�㲥���鲥, �DZ���IP,MAC�İ�)ʶ����. + + args: + check_dip_expect_cmp_res: ���Ŀ��IP�ͱ�������IP�Ĺ�ϵ, + user->acc_gateway���ܼ��, ��Ϊdip�϶���������IP; + acc_gateway->fwd_gateway, fwd_gateway->acc_gateway������, ��Ϊ�Ǿ�������ͨ��; + gdev->fwd_gateway������, ���ʹ��marsio����, ��������ʵ��. +*/ +int flwd_rubbish_pkt_identify(flwd_device_handle_t *device_handle, + flwd_raw_pkt_t *raw_pkt, int check_dip_expect_cmp_res) +{ + const flwd_eth_hdr_t *eth_hdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + flwd_ipv4_hdr_t *ip4hdr; + flwd_ipv6_hdr_t *ip6hdr; + unsigned eth_pro_type = ntohs(eth_hdr->h_proto); + + if(CAP_MODEL_SOCKET == device_handle->io_para.cap_mode){ + flwd_eth_hdr_t *inner_eth_hdr; + if((unsigned int)raw_pkt->inner_pkt_len < sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_vxlan_hdr_t)){ + return 1; + } + + inner_eth_hdr = (flwd_eth_hdr_t *)raw_pkt->inner_pkt_data; + if(ETH_P_IP == ntohs(inner_eth_hdr->h_proto)){ + ip4hdr = (flwd_ipv4_hdr_t *)(raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t)); + if(ip4hdr->ip_v != 4){ + return 1; + } + if(ip4hdr->ip_hl < 5){ + return 1; + } + if(ntohs(ip4hdr->ip_len) != (raw_pkt->inner_pkt_len - sizeof(flwd_eth_hdr_t))){ + return 1; + } + }else if(ETH_P_IPV6 != ntohs(inner_eth_hdr->h_proto)){ + ip6hdr = (flwd_ipv6_hdr_t *)(flwd_ipv6_hdr_t *)(raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t)); + if((ip6hdr->ip6_flags[0] & 0xF0) != 6){ + return 1; + } + if(ntohs(ip6hdr->ip6_payload_len) != (raw_pkt->inner_pkt_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv6_hdr_t))){ + return 1; + } + }else{ + return 1; + } + } + + if(device_handle->io_para.cap_mode != CAP_MODEL_SOCKET){ /* �ڻ��Ӳ���ģʽ�¼�� */ + if(memcmp(G_FLWD_BROADCAST_ADDR, eth_hdr->h_dest, ETH_ALEN) == 0){ + if(ETH_P_ARP != eth_pro_type){ /* ����ǹ㲥������ARP, ������϶���Ӧ�ó�NAT����, ֱ�Ӷ��� */ + return 1; + } + }else if(memcmp(device_handle->io_para.local_mac_addr, eth_hdr->h_dest, ETH_ALEN) != 0){ + /* ���ǹ㲥, Ŀ��MACҲ���DZ���, ���� */ + return 1; + } + +#if 0 /* IPv6���ھӷ��ְ�ʹ���鲥��ַʵ��, ����IPv4��ARP, ��Ҫ����, ���ܶ��� */ + else if((eth_hdr->h_dest[0] & 0x01) == 0x01){ + /* �鲥MAC��ַ, ͨ��Ϊ�������ڿ��������ݰ�, ��LLMNR, SPT��Э��, һ�����账�� */ + return 1; + } +#endif + + if(ETH_P_IP == eth_pro_type){ + ip4hdr = (flwd_ipv4_hdr_t *)((char *)eth_hdr + sizeof(flwd_eth_hdr_t)); + + if(FLWD_IPV4_MULTICAST_ADDR(ntohl(ip4hdr->ip_dst.s_addr)) != 0){ + return 1; /* �鲥IP��ַ, ������ */ + } + + if(check_dip_expect_cmp_res != (ip4hdr->ip_dst.s_addr == device_handle->io_para.device_ip_net_order)){ + return 1; + } + } + } + + return 0; +} + +static int flwd_protocol_stack_icmp_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, + flwd_ipv4_hdr_t *raw_ip_hdr, const flwd_simple_icmp_hdr_t *raw_icmp_hdr) +{ + int ret; + void *io_mbuff; + char *send_user_buf; + int raw_ip_tot_len = ntohs(raw_ip_hdr->ip_len); + int icmp_payload_len = raw_ip_tot_len - raw_ip_hdr->ip_hl * 4 - sizeof(flwd_simple_icmp_hdr_t); + + ///flwd_eth_hdr_t *snd_eth_hdr; + const flwd_eth_hdr_t *raw_eth_hdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + + /* Ϊ��Ӧ��ͬ�ײ�����, �������ڴ�, ����ICMP_REPLY���ٷ���, ������ֱ����ԭʼ���� */ + io_mbuff = io_handle->low_level_mbuff_malloc(io_handle, tid, raw_pkt->outer_pkt_len); + assert(io_mbuff != NULL); + + send_user_buf = (char *)io_handle->low_level_mbuff_mtod(io_mbuff); + + flwd_sendpacket_build_icmpv4_echo(ICMP_ECHOREPLY, 0, 0, + raw_icmp_hdr->icd_id, + raw_icmp_hdr->icd_seq, + (char *)raw_icmp_hdr + sizeof(flwd_simple_icmp_hdr_t), + icmp_payload_len, + send_user_buf + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t)); + + flwd_sendpacket_build_ipv4(raw_ip_tot_len - sizeof(flwd_ipv4_hdr_t), + 0, + 0x1234, + 0, + 64, + IPPROTO_ICMP, + raw_ip_hdr->ip_dst.s_addr, /* ��ַȡ�� */ + raw_ip_hdr->ip_src.s_addr, /* ��ַȡ�� */ + NULL, + 0, + send_user_buf + sizeof(flwd_eth_hdr_t)); + + /* ����У��� */ + flwd_sendpacket_do_checksum(send_user_buf + sizeof(flwd_eth_hdr_t), + IPPROTO_IP, + sizeof(flwd_ipv4_hdr_t)); + + flwd_sendpacket_do_checksum(send_user_buf + sizeof(flwd_eth_hdr_t), + IPPROTO_ICMP, + icmp_payload_len + sizeof(flwd_simple_icmp_hdr_t)); + + flwd_sendpacket_build_ethernet(ETH_P_IP, raw_eth_hdr->h_dest, raw_eth_hdr->h_source, send_user_buf); + + io_handle->low_level_mbuff_set_pkt_len(io_mbuff, raw_pkt->outer_pkt_len); + + ret = io_handle->low_level_send(io_handle, tid, io_mbuff); + if(ret < 0){ + flwd_log(RLOG_LV_FATAL, "send icmp reply error!"); + }else{ + char icmp_dip_str[16]; + inet_ntop(AF_INET, &raw_ip_hdr->ip_dst.s_addr, icmp_dip_str, 16); + flwd_log(RLOG_LV_DEBUG, "ICMP: recv icmp request to %s, send icmp reply!\n", icmp_dip_str); + } + + io_handle->low_level_mbuff_free_after_send(io_handle, tid, io_mbuff); + + return ret; +} + + +static int flwd_protocol_stack_ipv4_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, flwd_ipv4_hdr_t *iphdr) +{ + const flwd_simple_icmp_hdr_t *flwd_simple_icmp_hdr; + + if(io_handle->io_para.device_ip_net_order != iphdr->ip_dst.s_addr){ + return 0; + } + + if(iphdr->ip_p != IPPROTO_ICMP){ + return 0; + } + + flwd_simple_icmp_hdr = (flwd_simple_icmp_hdr_t *)((char *)iphdr + iphdr->ip_hl * 4); + if(flwd_simple_icmp_hdr->icmp_type != ICMP_ECHO){ + return 0; + } + + flwd_protocol_stack_icmp_layer_process(io_handle, tid, raw_pkt, iphdr, flwd_simple_icmp_hdr); + + return 1; +} + + +static int flwd_protocol_stack_ipv6_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, flwd_ipv6_hdr_t *ip6hdr) +{ + if(IPPROTO_ICMPV6 == ip6hdr->ip6_nxt_hdr){ + /* TODO, + ��ICMPv6���п������Ƿ���Netighbor ����Э��, + ȡ��IP��ַ, �鿴�Ƿ��DZ���, + Ȼ��ظ�Ӧ���. + */ + } + + return 0; +} + +static int flwd_protocol_stack_arp_layer_process( + flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt, flwd_arp_hdr_t *arp_hdr) +{ + int ret; + void *io_mbuff; + char *send_user_buf; + const flwd_eth_hdr_t *raw_eth_hdr; + + if(memcmp(arp_hdr->ar_tpa, &io_handle->io_para.device_ip_net_order, sizeof(int)) != 0){ + return 1; /* �DZ���ARP, ����Ҳ����1, ���ⲿ�����߲��ٴ��������ݰ�, ��������Ҳ���ظ�ARPӦ�� */ + } + + if(arp_hdr->ar_op == htons(ARPOP_REPLY)){ + flwd_arp_response_update(arp_hdr); + return 1; + } + + if(arp_hdr->ar_op != htons(ARPOP_REQUEST)){ + /* ֻ����REQUEST��REPLY, �������Ͳ����� */ + return 1; + } + + /* Ϊ��Ӧ��ͬ�ײ�����, �������ڴ�, ����ICMP_REPLY���ٷ���, ������ֱ����ԭʼ���� */ + io_mbuff = io_handle->low_level_mbuff_malloc(io_handle, tid, raw_pkt->outer_pkt_len); + assert(io_mbuff != NULL); + + send_user_buf = (char *)io_handle->low_level_mbuff_mtod(io_mbuff); + + flwd_sendpacket_build_arp(ARPHRD_ETHER, ETH_P_IP, arp_hdr->ar_hln, arp_hdr->ar_pln, + ARPOP_REPLY, + io_handle->io_para.local_mac_addr, + arp_hdr->ar_tpa, + arp_hdr->ar_sha, + arp_hdr->ar_spa, + send_user_buf + sizeof(flwd_eth_hdr_t)); + + raw_eth_hdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + flwd_sendpacket_build_ethernet(ETH_P_ARP, io_handle->io_para.local_mac_addr, + raw_eth_hdr->h_source, send_user_buf); + + io_handle->low_level_mbuff_set_pkt_len(io_mbuff, raw_pkt->outer_pkt_len); + + ret = io_handle->low_level_send(io_handle, tid, io_mbuff); + if(ret < 0){ + flwd_log(RLOG_LV_FATAL, "send arp reply error!"); + }else{ + char arp_dip_str[16]; + inet_ntop(AF_INET, arp_hdr->ar_tpa, arp_dip_str, 16); + flwd_log(RLOG_LV_DEBUG, "ARP: recv arp request to %s, send arp reply!\n", arp_dip_str); + } + + io_handle->low_level_mbuff_free_after_send(io_handle, tid, io_mbuff); + + return 1; /* ARPЭ��϶�����flowoodģ��Ҫ������, �����Dz��DZ�����, ���̶�����1 */ +} + +/* + IP��Э��ջ�����������, ����arp����, icmp�����. + return value: + 1: ��Э��ջ����, ����flowoodģ���������; + 0: ����Э��ջ����, ��IP��������. +*/ +int flwd_protocol_stack_process(flwd_device_handle_t *io_handle, + int tid, flwd_raw_pkt_t *raw_pkt) +{ + int is_stack = 0; + + const flwd_eth_hdr_t *flwd_ethhdr = (const flwd_eth_hdr_t *)raw_pkt->outer_pkt_data; + + switch(ntohs(flwd_ethhdr->h_proto)){ + case ETH_P_IP: + is_stack = flwd_protocol_stack_ipv4_layer_process(io_handle, tid, raw_pkt, (flwd_ipv4_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t))); + flwd_thread_val[tid].pkt_stat.ip_pkt_num++; + flwd_thread_val[tid].pkt_stat.ip_pkt_byte += raw_pkt->outer_pkt_len; + break; + + case ETH_P_IPV6: + is_stack = flwd_protocol_stack_ipv6_layer_process(io_handle, tid, raw_pkt, (flwd_ipv6_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t))); + break; + + case ETH_P_ARP: + is_stack = flwd_protocol_stack_arp_layer_process(io_handle, tid, raw_pkt, (flwd_arp_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t))); + break; + + default: + break; + } + + return is_stack; +} + diff --git a/src/common/flwd_common_tool.c b/src/common/flwd_common_tool.c new file mode 100644 index 0000000..e2e1b36 --- /dev/null +++ b/src/common/flwd_common_tool.c @@ -0,0 +1,911 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include "stream.h" +#include <linux/if_ether.h> +#include <linux/if_arp.h> +#include <arpa/inet.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> + + +static const unsigned char flwd_adapt_sleep_time_table[100] = +{ + 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ��Ϊ������pollģʽ, ����ɹ��ɹ��հ�����30%����, ˵��ϵͳ���رȽ�����, �Ͳ���usleep */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + + +void flwd_adapt_sleep(int success_work_times_in_recent_100) +{ + assert(success_work_times_in_recent_100 < 100); + + if(flwd_adapt_sleep_time_table[success_work_times_in_recent_100] > 0){ + usleep(flwd_adapt_sleep_time_table[success_work_times_in_recent_100]); + } +} + + +flwd_ip_region_type_t flwd_ipv4_location(unsigned int ip4addr_host_order) +{ + +#if FLWD_RUN_IN_CEIEC_TEST + /* �ڲ����Ե�ַ�����ж�!!! */ + if((ip4addr_host_order & 0xFFFFFF00) == 0xAC100A00){ /* 172.16.10.5Ϊ���������, ��λ���� */ + return FLWD_IP_REGION_OUTLAND; + } + if((ip4addr_host_order & 0xFFFFFF00) == 0xAC100B00){/* 172.16.11.xxΪ�ͻ���IP, ��λ���� */ + return FLWD_IP_REGION_INLAND; + } +#endif + /* TODO, ����IP��ַ���жϵ���λ��, �˴���д���������ڲ�IP */ + if(((ip4addr_host_order & 0xFF000000) == 0x0a000000) /* 10/8 */ + ||((ip4addr_host_order & 0xFFF00000) == 0xAC100000 ) /* 172.16/12 */ + ||((ip4addr_host_order & 0xFFFF0000) == 0xC0A80000)){ /* 192.168/16 */ + return FLWD_IP_REGION_INLAND; + } + + return FLWD_IP_REGION_OUTLAND; +} + +flwd_ip_region_type_t flwd_ipv6_location(const struct in6_addr *ip6addr_net) +{ + /* TODO, IP��ַ�� */ + + return FLWD_IP_REGION_INLAND; +} + + +/* ͨ��IP��ַ��λ��, �õ���ǰ���ʵ�Ŀ��IP���ڵ���λ�� */ +flwd_ip_region_type_t flwd_dstip_location(const flwd_tuple5_t *tuple5) +{ + unsigned int actual_dip_v4_host; + + if(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type){ + if(tuple5->dir_reverse != 0){ + actual_dip_v4_host = ntohl(tuple5->ippair_v4.sip_net_order); + }else{ + actual_dip_v4_host = ntohl(tuple5->ippair_v4.dip_net_order); + } + + return flwd_ipv4_location(actual_dip_v4_host); + }else{ + /* TODO, IPv6 */ + flwd_log(30, "recv ipv6 packet, but not support ipv6 addr location yet!\n"); + return FLWD_IP_REGION_INLAND; + } + + return FLWD_IP_REGION_INLAND; +} + + +const char *flwd_ip_region_ntop(int ip_region_type) +{ + if((int)FLWD_IP_REGION_INLAND == ip_region_type){ + return "inland"; + } + + return "outland"; +} + + +const char *flwd_tuple5_ntop(int tid, const flwd_tuple5_t *tuple5) +{ + static char str_mbuf[FLWD_MAX_THREAD_NUM][256]; + char ip_src_str[64], ip_dst_str[64]; + unsigned short actual_sport, actual_dport; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + }else{ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + } + + snprintf(str_mbuf[tid], 256, "%s.%u > %s.%u", ip_src_str, actual_sport, + ip_dst_str, actual_dport); + + return str_mbuf[tid]; +} + + +const char *flwd_tuple5_ntop_r(const flwd_tuple5_t *tuple5, char *str_mbuf, int mbuf_len) +{ + char ip_src_str[64], ip_dst_str[64]; + unsigned short actual_sport, actual_dport; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET, &tuple5->ippair_v4.sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET, &tuple5->ippair_v4.dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + }else{ + if(tuple5->dir_reverse){ + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->dport_net_order); + actual_dport = ntohs(tuple5->sport_net_order); + }else{ + inet_ntop(AF_INET6, &tuple5->ippair_v6->sip_net_order, ip_src_str, 64); + inet_ntop(AF_INET6, &tuple5->ippair_v6->dip_net_order, ip_dst_str, 64); + actual_sport = ntohs(tuple5->sport_net_order); + actual_dport = ntohs(tuple5->dport_net_order); + } + } + + snprintf(str_mbuf, mbuf_len, "%s.%u > %s.%u", + ip_src_str, actual_sport, + ip_dst_str, actual_dport); + + return str_mbuf; +} + +/* + �ж�flwd_ip_t��ַ�Ƿ����. + 1:��ͬ; + 0:��ͬ; +*/ +int flwd_ipt_equal(const flwd_ip_t *ip1, const flwd_ip_t *ip2) +{ + int diff = 0; + if(ip1->addr_type != ip2->addr_type){ + return 0; + } + + if(FLWD_IP_ADDR_TYPE_V4 == ip1->addr_type){ + if(ip1->addr_ipv4 == ip2->addr_ipv4){ + diff = 1; + }else{ + diff = 0; + } + }else{ + if(memcmp(&ip1->addr_ipv6, &ip2->addr_ipv6, sizeof(struct in6_addr)) == 0){ + diff = 1; + }else{ + diff = 0; + } + } + + return diff; +} + + +const char *flwd_ipt_ntop_r(const flwd_ip_t *ipbin, char *str_mbuf, int mbuf_len) +{ + ///char ip_str[64]; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == ipbin->addr_type)){ + inet_ntop(AF_INET, &ipbin->addr_ipv4, str_mbuf, mbuf_len); + }else{ + inet_ntop(AF_INET6, &ipbin->addr_ipv6, str_mbuf, mbuf_len); + } + + return str_mbuf; +} + +/* + ��ַmemcpy, + ��ַ��ָ��ָ��ǰ�̵߳�ȫ�ֱ���, ֻ���ڵ�ǰ��������ջ��ʹ��, ���غ��ַ��ʧЧ. +*/ +flwd_tuple5_t *flwd_tuple5_dup_to_stack(int tid, flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5) +{ + memcpy(dst_tuple5, src_tuple5, sizeof(flwd_tuple5_t)); + + if(FLWD_IP_ADDR_TYPE_V6 == src_tuple5->addr_type){ + memcpy(&flwd_thread_val[tid].nat_key_ipv6_buf, src_tuple5->ippair_v6, sizeof(flwd_ippair_v6_t)); + dst_tuple5->ippair_v6 = &flwd_thread_val[tid].nat_key_ipv6_buf; + } + + return dst_tuple5; +} + +/* + ��ַmemcpy, + ��ַ��ָ��ָ��malloc��ȫ���ڴ�, ʹ�ú�ע��free. +*/ +flwd_tuple5_t *flwd_tuple5_dup_to_heap(flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5) +{ + memcpy(dst_tuple5, src_tuple5, sizeof(flwd_tuple5_t)); + + if(FLWD_IP_ADDR_TYPE_V6 == src_tuple5->addr_type){ + dst_tuple5->ippair_v6 = (flwd_ippair_v6_t *)malloc(sizeof(flwd_ippair_v6_t)); + memcpy(dst_tuple5->ippair_v6, src_tuple5->ippair_v6, sizeof(flwd_ippair_v6_t)); + } + + return dst_tuple5; +} + +/* + ��Ϊtuple5�Ĵ洢Ϊ�˷���hash����, ʹ�ô��ַ��ΪԴ��Ĭ�Ϲ���, �����ܵߵ�����ʵ��Ԫ��ķ�������, + �˺�������dir�ķ���, �ָ�������ԭʼ��Ԫ��, ��sip�϶���ԭʼ����������ԴIP! +*/ +void flwd_tuple5_adjust_dir(flwd_tuple5_t *tuple5) +{ + unsigned short tshort; + unsigned int tint; + struct in6_addr tin6; + + if(0 == tuple5->dir_reverse){ + return; + } + + tshort = tuple5->sport_net_order; + tuple5->sport_net_order = tuple5->dport_net_order; + tuple5->dport_net_order = tshort; + + if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){ + tint = tuple5->ippair_v4.sip_net_order; + tuple5->ippair_v4.sip_net_order = tuple5->ippair_v4.dip_net_order; + tuple5->ippair_v4.dip_net_order = tint; + }else{ + memcpy(&tin6, &tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + memcpy(&tuple5->ippair_v6->sip_net_order, &tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + memcpy(&tuple5->ippair_v6->dip_net_order, &tin6, sizeof(struct in6_addr)); + } + + return; +} + + +void *flwd_calloc(int tid, size_t nmemb, size_t size) +{ + /* todo: dictator */ + return calloc(nmemb, size); +} + + +void *flwd_malloc(int tid, size_t size) +{ + /* todo: dictator */ + return malloc(size); +} + + +void flwd_free(int tid, void *ptr) +{ + /* todo: dictator */ + free(ptr); +} + +static int inline flwd_build_tuple4v4_key(flwd_tuple5_t *nat_key_v4, const flwd_raw_pkt_t *raw_pkt) +{ + const flwd_ipv4_hdr_t *flwd_iphdr = (flwd_ipv4_hdr_t *)raw_pkt->inner_ip_layer_hdr; + unsigned short raw_sport, raw_dport; + const flwd_tcp_hdr_t *flwd_tcphdr; + const flwd_udp_hdr_t *flwd_udphdr; + + nat_key_v4->addr_type = FLWD_IP_ADDR_TYPE_V4; + + if(IPPROTO_TCP == flwd_iphdr->ip_p){ + flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_iphdr + flwd_iphdr->ip_hl * 4); + raw_sport = flwd_tcphdr->th_sport; + raw_dport = flwd_tcphdr->th_dport; + nat_key_v4->protocol = IPPROTO_TCP; + }else if(IPPROTO_UDP == flwd_iphdr->ip_p){ + flwd_udphdr = (flwd_udp_hdr_t *)((char *)flwd_iphdr + flwd_iphdr->ip_hl * 4); + raw_sport = flwd_udphdr->uh_sport; + raw_dport = flwd_udphdr->uh_dport; + nat_key_v4->protocol = IPPROTO_UDP; + }else{ + flwd_log(30, "ip protocol is:%d, not support yet!\n", flwd_iphdr->ip_p); + return -1; + } + + /* key�Ķ������: + IP��ַ�����ΪԴ, �����ַһ��, �˿ڴ����ΪԴ, + ����Ǹ����Դ��涨, ����ν˭�����С, + Ϊ��Ч��, ֱ��ʹ�������ַ�����ֵ�Ƚϴ�С, ����ÿ�ζ���ntoh�任; + */ + if(flwd_iphdr->ip_src.s_addr > flwd_iphdr->ip_dst.s_addr){ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->sport_net_order = raw_sport; + nat_key_v4->dport_net_order = raw_dport; + nat_key_v4->dir_reverse = 0; + }else if(flwd_iphdr->ip_src.s_addr < flwd_iphdr->ip_dst.s_addr){ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->sport_net_order = raw_dport; + nat_key_v4->dport_net_order = raw_sport; + nat_key_v4->dir_reverse = 1; + }else{ + if(raw_sport > raw_dport){ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->sport_net_order = raw_sport; + nat_key_v4->dport_net_order = raw_dport; + nat_key_v4->dir_reverse = 0; + }else{ + nat_key_v4->ippair_v4.sip_net_order = flwd_iphdr->ip_dst.s_addr; + nat_key_v4->ippair_v4.dip_net_order = flwd_iphdr->ip_src.s_addr; + nat_key_v4->sport_net_order = raw_dport; + nat_key_v4->dport_net_order = raw_sport; + nat_key_v4->dir_reverse = 1; + } + } + + return nat_key_v4->dir_reverse; +} + +static inline int flwd_build_tuple4v6_key(int tid, flwd_tuple5_t *nat_key_v6, const flwd_raw_pkt_t *raw_pkt) +{ + const flwd_ipv6_hdr_t *flwd_ip6hdr = (flwd_ipv6_hdr_t *)raw_pkt->inner_ip_layer_hdr; + unsigned short raw_sport, raw_dport; + const flwd_tcp_hdr_t *flwd_tcphdr; + const flwd_udp_hdr_t *flwd_udphdr; + flwd_ippair_v6_t *nat_key_ipv6_buf = &flwd_thread_val[tid].nat_key_ipv6_buf; /* ����ջ����ʱ��ַ, ʹ��ȫ�ֱ����Ļ�����, ����malloc/free */ + int diff; + + nat_key_v6->addr_type = FLWD_IP_ADDR_TYPE_V6; + + if(IPPROTO_TCP == flwd_ip6hdr->ip6_nxt_hdr){ + flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t)); + raw_sport = flwd_tcphdr->th_sport; + raw_dport = flwd_tcphdr->th_dport; + nat_key_v6->protocol = IPPROTO_TCP; + }if(IPPROTO_UDP == flwd_ip6hdr->ip6_nxt_hdr){ + flwd_udphdr = (flwd_udp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t)); + raw_sport = flwd_udphdr->uh_sport; + raw_dport = flwd_udphdr->uh_dport; + nat_key_v6->protocol = IPPROTO_UDP; + }else{ + /* ����Э���ݲ�֧�� */ + return -1; + } + + nat_key_v6->ippair_v6 = nat_key_ipv6_buf; + + /* key�Ķ������: + IP��ַ�����ΪԴ, �����ַһ��, �˿ڴ����ΪԴ, + ��Ϊ���Ǹ����Դ��涨, ����ν˭�����С, + Ϊ��Ч��, ֱ��ʹ�������ַ�����ֵ�Ƚϴ�С, ����ÿ�ζ���ntoh�任; + */ + diff = memcmp(&flwd_ip6hdr->ip6_src, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + if(diff > 0){ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_sport; + nat_key_v6->dport_net_order = raw_dport; + nat_key_v6->dir_reverse = 0; + }else if(diff < 0){ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_dport; + nat_key_v6->dport_net_order = raw_sport; + nat_key_v6->dir_reverse = 1; + }else{ + if(raw_sport > raw_dport){ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_sport; + nat_key_v6->dport_net_order = raw_dport; + nat_key_v6->dir_reverse = 0; + }else{ + memcpy(&nat_key_ipv6_buf->sip_net_order, &flwd_ip6hdr->ip6_dst, sizeof( struct in6_addr)); + memcpy(&nat_key_ipv6_buf->dip_net_order, &flwd_ip6hdr->ip6_src, sizeof( struct in6_addr)); + nat_key_v6->sport_net_order = raw_dport; + nat_key_v6->dport_net_order = raw_sport; + nat_key_v6->dir_reverse = 1; + } + } + + return 0; +} + +/* + TODO: + IP��Ƭ��ô��? ��DNS��Ӧ���, ���ж��additionl-records, �ͳ�����MTU,Ҫ��Ƭ. + NAT��key����Ԫ��, IP��Ƭֻ�е�һƬ����Я���˿�, (��������������Ƭ��С��20�ֽ�, TCP��ͷҲ��ȫ, �װ�Ҳû�ж˿�), + + ���ȡ����: ���������Ƚ���������IP��Ƭ��, ������ɺ�, ����NATת��, ����ʱ��������Ƭ. + + HASH����ʱ, + ��ΪSNAT->C2S����, SNAT->S2C����, DNAT->C2S����, DNAT->S2C����, + ��������ĵ�ַ��ͬ, + ����, ����һ�����ӵ��ڲ���ַ���ⲿ��ַ��˵, Ҫ��������key, ָ��ͬһ��nat_info. + + return value: + 1: key�ĵ�ַ��ԭ��ʵ��Ԫ�����˷�ת; + 0: key�ĵ�ַ����ʵ��Ԫ���ַ; +*/ +int flwd_build_tuple4_key(int tid, flwd_tuple5_t *nat_key, const flwd_raw_pkt_t *raw_pkt) +{ + int ret; + const flwd_eth_hdr_t *flwd_ethhdr = (flwd_eth_hdr_t *)raw_pkt->inner_pkt_data; + unsigned short eth_type = ntohs(flwd_ethhdr->h_proto); + + if(ETH_P_IP == eth_type){ + ret = flwd_build_tuple4v4_key(nat_key, raw_pkt); + }else if(ETH_P_IPV6 == eth_type){ + ret = flwd_build_tuple4v6_key(tid, nat_key, raw_pkt); + }else{ + /* unsuport or unknown protocol */ + //flwd_log(20, "unsupport ethernet protocol, 0x%x", eth_type); + ret = -1; + } + + return ret; +} + +/* + IP����ϵͳ�ڲ���ַ��ƽ̨, Maat��ַ�ṹ��һ��, ɨ��֮ǰҪ��ת��. +*/ +int flwd_tuple5_to_stream_addr(int tid, const flwd_tuple5_t *tuple5, struct ipaddr *stream_addr) +{ + if(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type){ + stream_addr->addrtype = ADDR_TYPE_IPV4; + stream_addr->addrlen = sizeof(int); + if(0 == tuple5->dir_reverse){ + flwd_thread_val[tid].addrv4_convert_buf.saddr = tuple5->ippair_v4.sip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.daddr = tuple5->ippair_v4.dip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.source = tuple5->sport_net_order; + flwd_thread_val[tid].addrv4_convert_buf.dest = tuple5->dport_net_order; + }else{ + flwd_thread_val[tid].addrv4_convert_buf.saddr = tuple5->ippair_v4.dip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.daddr = tuple5->ippair_v4.sip_net_order; + flwd_thread_val[tid].addrv4_convert_buf.source = tuple5->dport_net_order; + flwd_thread_val[tid].addrv4_convert_buf.dest = tuple5->sport_net_order; + } + + stream_addr->v4 = &flwd_thread_val[tid].addrv4_convert_buf; + }else{ + stream_addr->addrtype = ADDR_TYPE_IPV6; + stream_addr->addrlen = sizeof(sizeof(struct in6_addr)); + if(0 == tuple5->dir_reverse){ + memcpy(flwd_thread_val[tid].addrv6_convert_buf.saddr, &tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + memcpy(flwd_thread_val[tid].addrv6_convert_buf.daddr, &tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + flwd_thread_val[tid].addrv6_convert_buf.source = tuple5->sport_net_order; + flwd_thread_val[tid].addrv6_convert_buf.dest = tuple5->dport_net_order; + }else{ + memcpy(flwd_thread_val[tid].addrv6_convert_buf.saddr, &tuple5->ippair_v6->dip_net_order, sizeof(struct in6_addr)); + memcpy(flwd_thread_val[tid].addrv6_convert_buf.daddr, &tuple5->ippair_v6->sip_net_order, sizeof(struct in6_addr)); + flwd_thread_val[tid].addrv6_convert_buf.source = tuple5->dport_net_order; + flwd_thread_val[tid].addrv6_convert_buf.dest = tuple5->sport_net_order; + } + + stream_addr->v6 = &flwd_thread_val[tid].addrv6_convert_buf; + } + + return 0; +} + +/* + �յ�ԭʼ����, Ԥ����, ���ݲ���ģʽ, topģʽ��ͬ, ���ò�ͬ���ָ���ַ. + +*/ +int flwd_pre_process_pkt_input(flwd_device_handle_t *rcv_device_handle, flwd_raw_pkt_t *raw_pkt) +{ + if((TOPO_ACC_LINK_FWD == rcv_device_handle->io_para.topo_mode) + || (TOPO_FWD_LINK_ACC == rcv_device_handle->io_para.topo_mode)){ + /* �������ش�ת�����ط����հ�, ����vxlan��. */ + raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data+ FLWD_VXLAN_OUTER_PACKET_LEN + sizeof(flwd_eth_hdr_t); /* �����������vxlanͷ�����ڲ�ethernetͷ�� */ + raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data + FLWD_VXLAN_OUTER_PACKET_LEN; /* ָ���ڲ�ethernet��ʼ��ַ */ + raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len - FLWD_VXLAN_OUTER_PACKET_LEN; + }else if(TOPO_ACC_LINK_USER == rcv_device_handle->io_para.topo_mode){ + /* �û��˽��붼����ͨEthernet��, TODO, �����tap�豸��??? */ + raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t); + raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data; + raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len; + }else if(TOPO_FWD_LINK_GDEV == rcv_device_handle->io_para.topo_mode){ +#if FLWD_NO_GDEV_ENV + raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t); + raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data; + raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len; +#else + /* mrtunnat�����Ѿ�ж����vxlanͷ�� */ + raw_pkt->inner_ip_layer_hdr = (const char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t); + raw_pkt->inner_pkt_data = (char *)raw_pkt->outer_pkt_data; + raw_pkt->inner_pkt_len = raw_pkt->outer_pkt_len; +#endif + } + + return 0; +} + + +/* + dynamic, static����, htable�������ݵķ�ʽ��һ��, ��Ҫ�����. +*/ +flwd_active_ip_t *flwd_ip_pool_search(unsigned char act_ip_origin, const MESA_htable_handle table, const uchar * key, uint size) +{ + flwd_active_ip_t *act_ip_list_head; + + if(FLWD_ACT_IP_DYNAMIC == act_ip_origin){ + return (flwd_active_ip_t *)MESA_htable_search(table, key, size); + } + + /* ��̬IP����group_idΪkey, IP_listΪdata */ + act_ip_list_head = (flwd_active_ip_t *)MESA_htable_search(table, key, size); +#if 1 + return act_ip_list_head; +#else + if(NULL == act_ip_list_head){ + return NULL; + } + + tmp_ip = act_ip_list_head; + do{ + /* ʹ������֮��Ƚϳ���ipv6�ı�����ַ���бȽ� */ + if(memcmp(key, &tmp_ip->active_ip_net_order.addr_ipv6, size) == 0){ + break; + } + if(tmp_ip->active_ip_list_node.nextele){ + tmp_ip = (flwd_active_ip_t *)tmp_ip->active_ip_list_node.nextele->quiddity; + }else{ + tmp_ip = NULL; + break; + } + }while(tmp_ip != act_ip_list_head); + + return tmp_ip; +#endif +} + + +static void __phony_del_cb(void *arg) +{ + return; /* ֻɾ��htable�����ṹ��key, ��ɾ��data */ +} + +/* + TODO: dynamic, static����, htable�������ݵķ�ʽ��һ��, ��Ҫ�����. +*/ +void flwd_ip_pool_del(unsigned char act_ip_origin, MESA_htable_handle table, unsigned int policy_group_id, + void (* del_cb)(void *), const flwd_active_ip_t *maat_cb_tobe_del_ip) +{ + flwd_active_ip_t *act_ip_list_head, *tmp_ip; + MESA_list_t *list_node; + ///flwd_active_ip_t *in_htable_tobe_del_ip; + const unsigned char *hkey; + unsigned int hsize; + unsigned char static_ip_group_key[64]; + int static_ip_group_key_len = 64; + int found = 0; + int to_be_free_group_id_key = 0; + char ip_str[64]; + + /* ��̬IPֱ��ɾ�� */ + if(FLWD_ACT_IP_DYNAMIC == act_ip_origin){ + MESA_htable_del(table, (unsigned char *)&maat_cb_tobe_del_ip->active_ip_net_order.addr_value, maat_cb_tobe_del_ip->active_ip_net_order.addr_len, del_cb); + return; + } + + flwd_policy_group_id_key_gen(policy_group_id, static_ip_group_key, &static_ip_group_key_len); + + act_ip_list_head = (flwd_active_ip_t *)MESA_htable_search(table, static_ip_group_key, static_ip_group_key_len); + if(NULL == act_ip_list_head){ + flwd_log(30, "del static ip pool, but '%s' not in htable!\n", flwd_ipt_ntop_r(&maat_cb_tobe_del_ip->active_ip_net_order, ip_str, 64)); + return; + } + + if(FLWD_IP_ADDR_TYPE_V4 == maat_cb_tobe_del_ip->active_ip_net_order.addr_type){ + hkey = (unsigned char *)&maat_cb_tobe_del_ip->active_ip_net_order.addr_ipv4; + hsize = sizeof(int); + }else{ + hkey = (unsigned char *)&maat_cb_tobe_del_ip->active_ip_net_order.addr_ipv6; + hsize = sizeof(struct in6_addr); + } + + list_node = &act_ip_list_head->active_ip_list_node; + + do{ + tmp_ip = (flwd_active_ip_t *)list_node->quiddity; + if(memcmp(hkey, &tmp_ip->active_ip_net_order.addr_value, hsize) == 0){ + found = 1; + break; + } + list_node = list_node->nextele; + }while(list_node != &act_ip_list_head->active_ip_list_node); + + if(found != 0){ + if(MESA_list_is_empty(&act_ip_list_head->active_ip_list_node)){ + /* �˴���empty��ʾֻ��һ��ͷ�ڵ�, ������IRϵͳ��˵, ͷ�ڵ�Ҳ�洢������, ������������empty! */ + to_be_free_group_id_key = 1; + } + + MESA_list_del(&act_ip_list_head->active_ip_list_node, &tmp_ip->active_ip_list_node); + + /* �˴�ֻ��htableɾ����ip_key���������ݽṹ, ʵ�ʵ�data��act_ip_list_head, ��ɾ��, ������IP����ɾ�����ɾ����ip_list */ + MESA_htable_del(table, hkey, hsize, __phony_del_cb); + + del_cb((void *)tmp_ip); /* ɾ������IP */ + + if(to_be_free_group_id_key != 0){ + /* static_pool��ǰpolicy_idɾ�����һ��IP, �Ѿ�����, ��Ҫ��HASH����ɾ����policy_idΪkey�Ľṹ */ + MESA_htable_del(table, static_ip_group_key, strlen((const char *)static_ip_group_key), __phony_del_cb); + } + } + + return; +} + + +void flwd_del_last_rn(char *data, int max_len) +{ + int i; + for(i = 0; i < max_len; i++){ + if(('\r' == data[i]) || ('\n' == data[i])){ + data[i] = '\0'; + return; + } + } + + return; +} + + +unsigned char *flwd_policy_group_id_key_gen(unsigned int policy_group_id, unsigned char *out_key, int *out_key_len) +{ + int actual_key_len; + + if(NULL == out_key_len || *out_key_len < 16){ + return (unsigned char *)"ERROR"; + } + + actual_key_len = snprintf((char *)out_key, *out_key_len, "GPID%u", policy_group_id); + + *out_key_len = actual_key_len; + + return out_key; +} + + +/* + ����sapp�������, ��ӡ��ǰ������Ԫ��, ����ֱ��ʹ��printadd, ��Ϊ������ʱ���ܻ�ߵ�Դ��Ŀ���ַ. +*/ +const char *flwd_debug_print_tuple4(const void *a_packet, int tid) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + static char tuple4_str[FLWD_MAX_THREAD_NUM][128]; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + + if(tid >= FLWD_MAX_THREAD_NUM){ + assert(0); + } + + if(NULL == a_packet){ + return "NULL"; + } + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* sapp������IP��ͷ, ���Ի�ȡraw_pkt, ���߿�IPͷ����һ����IPV4����IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(tuple4_str[tid], 128, "%s,%u ---> %s,%u", debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport); + + return tuple4_str[tid]; +} + + +/* + ����sapp�������, ��ӡ��ǰ������Ԫ��, IPID, UDP_CHECKSUM����Ψһ��ʶһ��������Ϣ, + ������������DEBUG��λ����. +*/ +const char *flwd_debug_print_tuple4_detail(const void *a_packet, int tid) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + static char tuple4_str[FLWD_MAX_THREAD_NUM][256]; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + unsigned short ip_id; + unsigned short tu_checksum; + + if(tid >= FLWD_MAX_THREAD_NUM){ + assert(0); + } + + if(NULL == a_packet){ + return "NULL"; + } + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* sapp������IP��ͷ, ���Ի�ȡraw_pkt, ���߿�IPͷ����һ����IPV4����IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + ip_id = ntohs(ipv4_hdr->ip_id); + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + ip_id = 0; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + tu_checksum = ntohs(thdr->th_sum); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + tu_checksum = ntohs(uhdr->uh_sum); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(tuple4_str[tid], 256, "%s,%u ---> %s,%u, pro:%u, ipid:0x%04x, checksum:0x%04x", + debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport, + protocol, + ip_id, + tu_checksum); + + return tuple4_str[tid]; +} + + +/* + ����sapp�������, ��ӡ��ǰ������Ԫ��, IPID, UDP_CHECKSUM����Ψһ��ʶһ��������Ϣ, + ������������DEBUG��λ����. +*/ +const char *flwd_debug_print_tuple4_detail_r(const void *a_packet, char *buf, int buf_max_len) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + unsigned short ip_id; + unsigned short tu_checksum; + + if(NULL == a_packet){ + return "NULL"; + } + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* sapp������IP��ͷ, ���Ի�ȡraw_pkt, ���߿�IPͷ����һ����IPV4����IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + ip_id = ntohs(ipv4_hdr->ip_id); + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + ip_id = 0; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + tu_checksum = ntohs(thdr->th_sum); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + tu_checksum = ntohs(uhdr->uh_sum); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(buf, buf_max_len, "%s,%u ---> %s,%u, pro:%u, ipid:0x%04x, checksum:0x%04x", + debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport, + protocol, + ip_id, + tu_checksum); + + return buf; +} + + +const char *flwd_debug_print_tuple4_r(const void *a_packet, char *buf, int buf_max_len) +{ + char debug_ip_src_str[64], debug_ip_dst_str[64]; + unsigned short debug_sport, debug_dport; + const flwd_ipv4_hdr_t *ipv4_hdr; + const flwd_ipv6_hdr_t *ipv6_hdr; + const flwd_tcp_hdr_t *thdr; + const flwd_udp_hdr_t *uhdr; + unsigned char *ip_hdr = (unsigned char *)a_packet; + unsigned char protocol; + + if(flwd_cfg_val.flwd_log_level <= 10){ + if(0x40 == (ip_hdr[0] & 0xF0)){ /* ��һ����IPV4����IPV6 */ + ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet; + protocol = ipv4_hdr->ip_p; + }else{ + ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet; + protocol = ipv6_hdr->ip6_nxt_hdr; + } + + inet_ntop(AF_INET, &ipv4_hdr->ip_src.s_addr, debug_ip_src_str, 64); + inet_ntop(AF_INET, &ipv4_hdr->ip_dst.s_addr, debug_ip_dst_str, 64); + if(6 == protocol){ + thdr = (flwd_tcp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(thdr->th_sport); + debug_dport = ntohs(thdr->th_dport); + }else if (17 == protocol){ + uhdr = (flwd_udp_hdr_t *)((char *)a_packet + ipv4_hdr->ip_hl * 4); + debug_sport = ntohs(uhdr->uh_sport); + debug_dport = ntohs(uhdr->uh_dport); + }else{ + debug_sport = 0; + debug_dport = 0; + } + } + + snprintf(buf, buf_max_len, "%s,%u ---> %s,%u", debug_ip_src_str, debug_sport, debug_ip_dst_str, debug_dport); + + return buf; +} + + diff --git a/src/common/flwd_compat_marsio_hash.c b/src/common/flwd_compat_marsio_hash.c new file mode 100644 index 0000000..dee143a --- /dev/null +++ b/src/common/flwd_compat_marsio_hash.c @@ -0,0 +1,23 @@ + +#include "flowood.h" +#include "flowood_fun.h" +#include <arpa/inet.h> +#include <linux/if_ether.h> +#include <linux/if_arp.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> +/* + ����������Ҫ��֤�����İ�����Ԫ��, ����marsio�ķ����㷨��, + ����ʱ���ܱ��ֵ�ͬһ���߳���, ��֤���ҵ�ԭ����nat_session. +*/ + +unsigned int compat_marsio_tuple4_hash(const flwd_tuple5_t *nat_key) +{ + /* TODO, ���marsio���������㷨, ��֤ͬԴͬ�� */ + + return 0; +} + diff --git a/src/common/flwd_network_connect.c b/src/common/flwd_network_connect.c new file mode 100644 index 0000000..e875e87 --- /dev/null +++ b/src/common/flwd_network_connect.c @@ -0,0 +1,363 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_htable.h" +#include "MESA_list_queue.h" +#include "MESA_handle_logger.h" +#include "MESA_list_count.h" +#include <assert.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> + + +typedef struct{ + char region_str[FLWD_REGION_STR_LEN_MAX]; + unsigned int vlan_id; + unsigned int conn_forward_gateway_array[FLWD_NETWORK_NxM_MAX]; /* ����������ת������IP, ������ */ + int conn_forward_gateway_array_num; +}flwd_network_gdev_data_t; + +/* + NOTE: + GDEV��FWD֮����NxM��ϵ, ͨ�������ñ�, ��֮access����, ����һ��ѡ���˵Ļ�ԾIP, Ӧ�ý����ĸ�FWD����ͨ���ĸ�GDEV����ȥ. + + active_IP: access---->forwad---->gdev---->INTERNET. + + + config: + region vlan gdev_redirect_ip forward_manage_ip forward_feedback_ip + + + region: �������, ��ʡ����; + vlan : ��ֹһ���ֵ��ڵ�GDEV��froward���ܲ�ͨ, �������������VLAN�ȵ�, ���������ʶ; + gdev_redirect_ip: GDEV�Ļ�����IP + forward_manage_ip: ת�����ع�����IP + forward_feedback_ip: ת�����ص������ݻش���IP + + ������ȫ��һ��, ��access�����зֶ˿ڵ�����, Ҫȫ��ͬ��, ����������������!!!! +*/ + + + + + +static int flwd_network_gdev_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2) +{ + if(size1 != size2){ + return -1; + } + + return memcmp(key1, key2, size1); +} + +static uint flwd_network_gdev_key2index(const MESA_htable_handle table, const uchar * key, uint size) +{ + unsigned int hash = 131; + unsigned seed = 13131; + unsigned int i; + + for(i = 0; i < size; i++){ + hash = hash * seed + *key++; + } + + return hash; +} + +static void flwd_network_gdev_data_free(void *data) +{ + assert(0); /* ��������ʱ��Զ����free, �Ͳ����ߵ�����, ����!!! */ +} + +/* + NOTE: + ��htable��gdev_ip��Ϊkey, + flwd_network_gdev_data_t�ṹΪdata, + ��������ȥ���ĸ�gdev, ����ͨ����Щforward. +*/ +static MESA_htable_handle flwd_create_network_gdev_table(void) +{ + int opt_int; + MESA_htable_handle htable; + + htable = MESA_htable_born(); + assert(htable != NULL); + + opt_int = 0; /* ��ʼ�����ٸĶ�, ����ģʽ */ + MESA_htable_set_opt(htable, MHO_THREAD_SAFE, &opt_int, sizeof(int)); + + opt_int = 1024; + MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int)); + + opt_int = 1000; + MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &opt_int, sizeof(int)); + + opt_int = 0; + MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &opt_int, sizeof(int)); /* ����̭ */ + + opt_int = HASH_ELIMINATE_ALGO_FIFO; /* ���߳�����ģʽ����FIFO */ + MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_network_gdev_key_cmp, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_network_gdev_key2index, sizeof(void *)); + + MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_network_gdev_data_free, sizeof(void *)); + + opt_int = 0; + MESA_htable_set_opt(htable, MHO_AUTO_UPDATE_TIME, &opt_int, sizeof(int)); + + opt_int = 0; + MESA_htable_set_opt(htable, MHO_SCREEN_PRINT_CTRL, &opt_int, sizeof(int)); + + opt_int = 100; + MESA_htable_set_opt(htable, MHO_HASH_LIST_COLLIDE_THRESHOLD, &opt_int, sizeof(int)); + + char *err_log = (char *)"./flwd_hash_collide.log"; + MESA_htable_set_opt(htable, MHO_HASH_LOG_FILE, (void *)err_log, strlen(err_log)); + + int ret = MESA_htable_mature(htable); + assert(ret >= 0); + + return htable; +} + +/* + pattern: + #region vlan_id gdev_redirect_ip +*/ +static int flwd_network_gdev_cfg_parse(void) +{ + FILE *fp; + char __raw_line_buf[1024]; + char line_buf[1024]; + const char *delim = "\t "; + char *save_ptr; + flwd_network_gdev_data_t *tmp_data; + char *section, *region_str, *gdev_ip_str; + unsigned int hkey; + int ret; + + fp = fopen("./conf/ip_reuse/network_gdev.cfg", "r"); + if(NULL == fp){ + return -1; + } + + while(fgets(__raw_line_buf, 1024, fp)){ + if('#' ==__raw_line_buf[0]){ + continue; + } + memcpy(line_buf, __raw_line_buf, 1024); + flwd_del_last_rn(line_buf, 1024); + tmp_data = (flwd_network_gdev_data_t *)calloc(1, sizeof(flwd_network_gdev_data_t)); + + /* region */ + section = strtok_r(line_buf, delim, &save_ptr); + if(NULL == section){ + return -1; + } + strncpy(tmp_data->region_str, section, FLWD_REGION_STR_LEN_MAX-1); + region_str = section; + + /* vlan_id */ + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + tmp_data->vlan_id = (unsigned int)atoi(section); + + /* gdev_redirect_ip */ + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + if(inet_pton(AF_INET, section, &hkey) <= 0){ + return -1; + } + gdev_ip_str = section; + + ret = MESA_htable_add(flwd_global_val.flwd_network_conn_table, (const uchar *)&hkey, sizeof(int), tmp_data); + if(ret >= 0){ + flwd_log(10, "parse network_gdev.cfg, %s\t%u\t%s\n", region_str, tmp_data->vlan_id, gdev_ip_str); + }else{ + flwd_log(30, "parse network_gdev.cfg error, %s\n", __raw_line_buf); + } + + while(strtok_r(NULL, delim, &save_ptr)); + } + + fclose(fp); + + return 0; +} + + +static int flwd_network_gdev_fwd_relate_cb(const uchar * key, uint size, void * data, void * user) +{ + flwd_network_gdev_data_t *hdata = (flwd_network_gdev_data_t *)data; + flwd_network_gdev_data_t *tmp_fwd_data = (flwd_network_gdev_data_t *)user; + + if(strlen(hdata->region_str) != strlen(tmp_fwd_data->region_str)){ + return ITERATE_CB_RET_CONTINUE_FLAG; /* MESA_htable_iterate_bytime�����ػص�������ֵ, �����ø�trick, ��conn_forward_gateway_array_num=2�����ҵ���, ������1 */ + } + + if(strncmp(hdata->region_str, tmp_fwd_data->region_str,strlen(hdata->region_str)) != 0){ + return ITERATE_CB_RET_CONTINUE_FLAG; + } + + if(hdata->vlan_id != tmp_fwd_data->vlan_id){ + return ITERATE_CB_RET_CONTINUE_FLAG; + } + + tmp_fwd_data->conn_forward_gateway_array_num = 2; /* bingo! */ + + if(hdata->conn_forward_gateway_array_num >= FLWD_NETWORK_NxM_MAX){ + assert(0); + } + + hdata->conn_forward_gateway_array[hdata->conn_forward_gateway_array_num] = tmp_fwd_data->conn_forward_gateway_array[0]; + hdata->conn_forward_gateway_array_num++; + + /* NOTE: �м�!!! �����ҵ�����һ�������е�GDEV, �˴�Ҳ�����ж�callback, ��Ϊһ�������ڻ�����������������GDEV, Ҫȫ����һ�� */ + return ITERATE_CB_RET_CONTINUE_FLAG; +} + +static void flwd_network_gdev_fwd_relate(flwd_network_gdev_data_t *tmp_data) +{ + /* �������� */ + MESA_htable_iterate_bytime(flwd_global_val.flwd_network_conn_table, ITERATE_TYPE_OLDEST_FIRST, + flwd_network_gdev_fwd_relate_cb, tmp_data); + + return ; +} + + +/* + #region vlan_id forward_ip +*/ +static int flwd_network_forward_cfg_parse(void) +{ + FILE *fp; + char line_buf[1024]; + const char *delim = "\t "; + char *save_ptr; + flwd_network_gdev_data_t tmp_data; + char *section; + char *forward_ip; + + fp = fopen("./conf/ip_reuse/network_forward.cfg", "r"); + if(NULL == fp){ + return -1; + } + + while(fgets(line_buf, 1024, fp)){ + if('#' ==line_buf[0]){ + continue; + } + flwd_del_last_rn(line_buf, 1024); + memset(&tmp_data, 0, sizeof(flwd_network_gdev_data_t)); + + section = strtok_r(line_buf, delim, &save_ptr); + if(NULL == section){ + return -1; + } + strncpy(tmp_data.region_str, section, FLWD_REGION_STR_LEN_MAX-1); + + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + tmp_data.vlan_id = (unsigned int)atoi(section); + + section = strtok_r(NULL, delim, &save_ptr); + if(NULL == section){ + return -1; + } + if(inet_pton(AF_INET, section, &tmp_data.conn_forward_gateway_array[0]) <= 0){ /* ����һ������0, ��ʱ�洢 forward_ip */ + return -1; + } + forward_ip = section; + tmp_data.conn_forward_gateway_array_num = 1; + + flwd_network_gdev_fwd_relate(&tmp_data); + /* MESA_htable_iterate_bytime�����ػص�������ֵ, �����ø�trick, ��conn_forward_gateway_array_num=2�����ҵ���, ������1 */ + if(2 != tmp_data.conn_forward_gateway_array_num){ + flwd_log(30, "can't found related gdev ip in network_gdev.cfg, network_forward.cfg->forward ip:%s\n", forward_ip); + return -1; + }else{ + flwd_log(10, "parse network_gdev.cfg->%s\n", forward_ip); + } + + while(strtok_r(NULL, delim, &save_ptr)); + } + + fclose(fp); + + return 0; +} + +/* TODO, + + ///����ѡ��Ļ�ԾIP���ڵ�GDEV_IP��ID, �������, ȷ��Ӧ�ô��ĸ�FWD���� + + ��һ���ֵ���˵, �������ظ�����һ��ת������, ����ͨ�����е�INLINE-DEVICE, + + �����IP��ַ������������. + +*/ +unsigned int flwd_search_fwd_ip_by_gdev_ip(unsigned int gdev_ip_net_order) +{ + flwd_network_gdev_data_t *hdata; + char ip_str[16]; + int rnd_num; + + hdata = (flwd_network_gdev_data_t *)MESA_htable_search(flwd_global_val.flwd_network_conn_table, (unsigned char *)&gdev_ip_net_order, sizeof(int)); + if(NULL == hdata){ + inet_ntop(AF_INET, &gdev_ip_net_order, ip_str, 16); + flwd_log(30, "not found gdev ip %s in network_gdev.cfg\n", ip_str); + return -1; + } + + /* NxM���˹�ϵ, ��������, �����ѡһ��ת������ */ + rnd_num = rand() % hdata->conn_forward_gateway_array_num; + + return hdata->conn_forward_gateway_array[rnd_num]; + /* + TODO: + дһ��gdev_ip��FWD���ݿ�IP�ľ�̬������, + + ���߿���һ��rip·��Э��, �Զ��㲥, �Զ�����. + + ����ʱ���ֶ�д��, ʵ�ʾ���10.0.6.201��em1����IP��ַ: 172.16.1.201. + */ + + //inet_pton(AF_INET, "10.0.6.201", &gdev_ip_net_order); + //inet_pton(AF_INET, "172.16.1.201", &gdev_ip_net_order); + //inet_pton(AF_INET, "47.74.128.220", &gdev_ip_net_order); + //return gdev_ip_net_order; +} + +int flwd_network_conn_init(void) +{ + flwd_global_val.flwd_network_conn_table = flwd_create_network_gdev_table(); + + /* NOTE, �����ȵ���flwd_network_gdev_cfg_parse, ���ӵ�htable��, �����ٵ���flwd_network_forward_cfg_parse */ + if(flwd_network_gdev_cfg_parse() < 0){ + flwd_log(30, "flwd_network_gdev_cfg_parse error!\n"); + return -1; + } + + /* NOTE, �����ȵ���flwd_network_gdev_cfg_parse, ���ӵ�htable��, �����ٵ���flwd_network_forward_cfg_parse */ + if(flwd_network_forward_cfg_parse() < 0){ + flwd_log(30, "flwd_network_forward_cfg_parse error!\n"); + return -1; + } + return 0; +} + + diff --git a/src/common/flwd_sendpacket.c b/src/common/flwd_sendpacket.c new file mode 100644 index 0000000..701a447 --- /dev/null +++ b/src/common/flwd_sendpacket.c @@ -0,0 +1,138 @@ + +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include "MESA_handle_logger.h" +#include <linux/if_ether.h> +#include <linux/if_arp.h> +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include <assert.h> + +int flwd_sendpacket_build_ethernet(u_int16_t eth_type_host_order, + const unsigned char *src_mac, const unsigned char *dst_mac, char *buf) +{ + flwd_eth_hdr_t *snd_eth_hdr = (flwd_eth_hdr_t *)buf; + + memcpy(snd_eth_hdr->h_dest, dst_mac, ETH_ALEN); + memcpy(snd_eth_hdr->h_source, src_mac, ETH_ALEN); + + snd_eth_hdr->h_proto = htons(eth_type_host_order); + + return 0; +} + + +int flwd_sendpacket_build_arp(u_short hrd_host, u_short pro_host, + u_char hln, u_char pln, u_short op_host, u_char *sha, u_char *spa, + u_char *tha, u_char *tpa, char *buf) +{ + flwd_arp_hdr_t *arp_hdr = (flwd_arp_hdr_t *)buf; + + if (!buf){ + return (-1); + } + + arp_hdr->ar_hrd = htons(hrd_host); /* hardware address type */ + arp_hdr->ar_pro = htons(pro_host); /* protocol address type */ + arp_hdr->ar_hln = hln; /* hardware address length */ + arp_hdr->ar_pln = pln; /* protocol address length */ + arp_hdr->ar_op = htons(op_host); /* opcode command */ + memcpy(arp_hdr->ar_sha, sha, hln); /* sender hardware address */ + memcpy(arp_hdr->ar_spa, spa, pln); /* sender protocol (IP) address */ + memcpy(arp_hdr->ar_tha, tha, hln); /* target hardware address */ + memcpy(arp_hdr->ar_tpa, tpa, pln); /* target protocol (IP) address */ + + return (0); +} + +int flwd_sendpacket_build_ipv4(u_int16_t carry_layer_len, u_int8_t tos, + u_int16_t id, u_int16_t frag, u_int8_t ttl, u_int8_t prot, u_int32_t src_net_order, + u_int32_t dst_net_order, const char *payload, int payload_s, char *buf) +{ + flwd_ipv4_hdr_t *ip_hdr; + + if (!buf){ + return (-1); + } + + ip_hdr = (flwd_ipv4_hdr_t *)buf; + + ip_hdr->ip_v = 4; /* version 4 */ + ip_hdr->ip_hl = 5; /* 20 byte header */ + ip_hdr->ip_tos = tos; /* IP tos */ + ip_hdr->ip_len = htons(sizeof(flwd_ipv4_hdr_t) + carry_layer_len); /* total length */ + ip_hdr->ip_id = htons(id); /* IP ID */ + ip_hdr->ip_off = htons(frag); /* fragmentation flags */ + ip_hdr->ip_ttl = ttl; /* time to live */ + ip_hdr->ip_p = prot; /* transport protocol */ + ip_hdr->ip_sum = 0; /* do this later */ + ip_hdr->ip_src.s_addr = src_net_order; + ip_hdr->ip_dst.s_addr = dst_net_order; + if (payload && payload_s){ + /* + * Unchecked runtime error for buf + IP_H + payload to be greater than + * the allocated heap memory. + */ + memcpy(buf + sizeof(flwd_ipv4_hdr_t), payload, payload_s); + } + + return (0); +} + + +/* ���ڹ��������: ICMP-ECHO-REQUEST, ICMP-ECHO-REPLAY�� */ +int flwd_sendpacket_build_icmpv4_echo(u_int8_t type, u_int8_t code, + u_int16_t sum, u_int16_t id_net_order, u_int16_t seq_net_order, char *payload, + u_int32_t payload_s, char *buf) +{ + flwd_simple_icmp_hdr_t *icmp_hdr = (flwd_simple_icmp_hdr_t *)buf; + + icmp_hdr->icmp_type = type; + icmp_hdr->icmp_code = code; + icmp_hdr->icmp_cksum = 0; /* checksum done in userland */ + icmp_hdr->icd_id = id_net_order; + icmp_hdr->icd_seq = seq_net_order; + + if(payload && payload_s){ + /* + * Unchecked runtime error for buf + IP_H + payload to be greater than + * the allocated heap memory. + */ + memcpy(buf + sizeof(flwd_simple_icmp_hdr_t), payload, payload_s); + } + + return 0; +} + +int flwd_sendpacket_build_udp(u_int16_t carry_layer_len, + u_int16_t sport_net_order, u_int16_t dport_net_order, + const char *payload, int payload_s, char *buf) +{ + flwd_udp_hdr_t udp_hdr; + + if (!buf) + { + return (-1); + } + + udp_hdr.uh_sport = sport_net_order; /* source port */ + udp_hdr.uh_dport = dport_net_order; /* destination port */ + udp_hdr.uh_ulen = htons(sizeof(flwd_udp_hdr_t) + carry_layer_len); /* total length */ + udp_hdr.uh_sum = 0; /* checksum */ + + if (payload && payload_s) + { + /* + * Unchecked runtime error for buf + UDP_H + payload to be greater + * than the allocated heap memory. + */ + memcpy(buf + sizeof(flwd_udp_hdr_t), payload, payload_s); + } + memcpy(buf, &udp_hdr, sizeof(udp_hdr)); + return (1); +} + + diff --git a/src/common/flwd_status.c b/src/common/flwd_status.c new file mode 100644 index 0000000..fe01d2b --- /dev/null +++ b/src/common/flwd_status.c @@ -0,0 +1,275 @@ +#include "flowood.h" +#include "flowood_fun.h" +#include "flwd_net.h" +#include <assert.h> +#include <time.h> +#include <errno.h> +#include <sys/time.h> + +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; +} + + diff --git a/src/common/linux_jhash_algo.c b/src/common/linux_jhash_algo.c new file mode 100644 index 0000000..31fa7ec --- /dev/null +++ b/src/common/linux_jhash_algo.c @@ -0,0 +1,267 @@ +
+/* jhash.h: Jenkins hash support.
+ *
+ * Copyright (C) 2006. Bob Jenkins ([email protected])
+ *
+ * http://burtleburtle.net/bob/hash/
+ *
+ * These are the credits from Bob's sources:
+ *
+ * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+ *
+ * These are functions for producing 32-bit hashes for hash table lookup.
+ * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
+ * are externally useful functions. Routines to test the hash are included
+ * if SELF_TEST is defined. You can use this free for any purpose. It's in
+ * the public domain. It has no warranty.
+ *
+ * Copyright (C) 2009-2010 Jozsef Kadlecsik ([email protected])
+ *
+ * I've modified Bob's hash to be useful in the Linux kernel, and
+ * any bugs present are my fault.
+ * Jozsef
+ */
+
+#include "flowood.h"
+
+/* An arbitrary initial parameter */
+#define JHASH_INITVAL (0x20180601) /* flowood��Ŀ������������������ */
+
+
+#ifndef u32
+typedef unsigned int u32;
+#endif
+
+#ifndef __u32
+typedef unsigned int __u32;
+#endif
+
+/* Best hash sizes are of power of two */
+#define jhash_size(n) ((u32)1<<(n))
+/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */
+#define jhash_mask(n) (jhash_size(n)-1)
+
+
+/**
+ * rol32 - rotate a 32-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 rol32(__u32 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (32 - shift));
+}
+
+/* __jhash_mix -- mix 3 32-bit values reversibly. */
+#define __jhash_mix(a, b, c) \
+{ \
+ a -= c; a ^= rol32(c, 4); c += b; \
+ b -= a; b ^= rol32(a, 6); a += c; \
+ c -= b; c ^= rol32(b, 8); b += a; \
+ a -= c; a ^= rol32(c, 16); c += b; \
+ b -= a; b ^= rol32(a, 19); a += c; \
+ c -= b; c ^= rol32(b, 4); b += a; \
+}
+
+/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
+#define __jhash_final(a, b, c) \
+{ \
+ c ^= b; c -= rol32(b, 14); \
+ a ^= c; a -= rol32(c, 11); \
+ b ^= a; b -= rol32(a, 25); \
+ c ^= b; c -= rol32(b, 16); \
+ a ^= c; a -= rol32(c, 4); \
+ b ^= a; b -= rol32(a, 14); \
+ c ^= b; c -= rol32(b, 24); \
+}
+
+#if 0
+/* jhash - hash an arbitrary key
+ * @k: sequence of bytes as key
+ * @length: the length of the key
+ * @initval: the previous hash, or an arbitray value
+ *
+ * The generic version, hashes an arbitrary sequence of bytes.
+ * No alignment or length assumptions are made about the input key.
+ *
+ * Returns the hash value of the key. The result depends on endianness.
+ */
+static inline u32 jhash(const void *key, u32 length, u32 initval)
+{
+ u32 a, b, c;
+ const u8 *k = key;
+
+ /* Set up the internal state */
+ a = b = c = JHASH_INITVAL + length + initval;
+
+ /* All but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12) {
+ a += __get_unaligned_cpu32(k);
+ b += __get_unaligned_cpu32(k + 4);
+ c += __get_unaligned_cpu32(k + 8);
+ __jhash_mix(a, b, c);
+ length -= 12;
+ k += 12;
+ }
+ /* Last block: affect all 32 bits of (c) */
+ /* All the case statements fall through */
+ switch (length) {
+ case 12: c += (u32)k[11]<<24;
+ case 11: c += (u32)k[10]<<16;
+ case 10: c += (u32)k[9]<<8;
+ case 9: c += k[8];
+ case 8: b += (u32)k[7]<<24;
+ case 7: b += (u32)k[6]<<16;
+ case 6: b += (u32)k[5]<<8;
+ case 5: b += k[4];
+ case 4: a += (u32)k[3]<<24;
+ case 3: a += (u32)k[2]<<16;
+ case 2: a += (u32)k[1]<<8;
+ case 1: a += k[0];
+ __jhash_final(a, b, c);
+ case 0: /* Nothing left to add */
+ break;
+ }
+
+ return c;
+}
+#endif
+
+/* jhash2 - hash an array of u32's
+ * @k: the key which must be an array of u32's
+ * @length: the number of u32's in the key
+ * @initval: the previous hash, or an arbitray value
+ *
+ * Returns the hash value of the key.
+ */
+static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
+{
+ u32 a, b, c;
+
+ /* Set up the internal state */
+ a = b = c = JHASH_INITVAL + (length<<2) + initval;
+
+ /* Handle most of the key */
+ while (length > 3) {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ __jhash_mix(a, b, c);
+ length -= 3;
+ k += 3;
+ }
+
+ /* Handle the last 3 u32's: all the case statements fall through */
+ switch (length) {
+ case 3: c += k[2];
+ case 2: b += k[1];
+ case 1: a += k[0];
+ __jhash_final(a, b, c);
+ case 0: /* Nothing left to add */
+ break;
+ }
+
+ return c;
+}
+
+
+/* jhash_3words - hash exactly 3, 2 or 1 word(s) */
+static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
+{
+ a += JHASH_INITVAL;
+ b += JHASH_INITVAL;
+ c += initval;
+
+ __jhash_final(a, b, c);
+
+ return c;
+}
+
+/*
+ NATת�����ͼ������ݰ�ָ�Ƹ���һ������, ������sport_with_no_id_hash����:
+ sport_with_no_id_hash=0: ���ڼ�����Ԫ��HASH,
+ sport_with_no_id_hash=1: ���ڼ������ݰ�ָ��;
+
+ NOTE:
+ ����Ԫ��hash����ʱ, ����Ҫ��dir_reverse,
+ ��ΪC2S�����S2C�������ɵ�key����Ԫ��ʵ�ʶ�������һ����,
+ ����ѭ���ַ��ΪԴ�Ĺ���, ֻ��dir_reverse��ͬ,
+ C2S��S2C����������һ��, dir_reverse�϶����෴��.
+*/
+unsigned int flwd_tuple5_hash(const flwd_tuple5_t *tuple5, int sport_with_no_id_hash)
+{
+ unsigned int sip;
+ unsigned int dip;
+ unsigned int hash_val = 0;
+ unsigned short sport; /* ������Ԫ��HASHʱ, ��ȫ����bit; ����ָ����Ϣʱ, ֻ��sport�����8bit�˿�ֵ, ����������id, hash */
+ unsigned short dport;
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){
+ sip = tuple5->ippair_v4.sip_net_order;
+ dip = tuple5->ippair_v4.dip_net_order;
+ }else{
+ sip = tuple5->ippair_v6->sip_net_order.s6_addr32[0]; /* ʹ�����4�ֽ� */
+ dip = tuple5->ippair_v6->dip_net_order.s6_addr32[0]; /* ʹ�����4�ֽ� */
+ }
+
+ if(sport_with_no_id_hash){
+ sport = ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; /* ֻ�������Ķ˿�ֵ, ����id��hash�ֶ� */
+ }else{
+ sport = tuple5->sport_net_order;
+ }
+ dport = tuple5->dport_net_order;
+
+ hash_val = (unsigned int)sport;
+ hash_val |= ((unsigned int)dport << 16);
+ hash_val += JHASH_INITVAL;
+
+ __jhash_final(sip, dip, hash_val);
+
+ return hash_val;
+}
+
+
+
+unsigned int __flwd_tuple5_hash(const flwd_tuple5_t *tuple5)
+{
+ unsigned int sip;
+ unsigned int dip;
+ unsigned int port_union;
+ unsigned short sport_no_id_hash; /* ������Ԫ��HASHʱ, ֻ��sport�����8bit�˿�ֵ, ��������id, hash */
+ unsigned short dport;
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == tuple5->addr_type)){
+ if(0 == tuple5->dir_reverse){
+ sip = tuple5->ippair_v4.sip_net_order;
+ dip = tuple5->ippair_v4.dip_net_order;
+ sport_no_id_hash = ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; /* ֻ�������Ķ˿�ֵ, ����id��hash�ֶ� */
+ dport = tuple5->dport_net_order;
+ }else{
+ sip = tuple5->ippair_v4.dip_net_order;
+ dip = tuple5->ippair_v4.sip_net_order;
+ sport_no_id_hash = ntohs(tuple5->dport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK; /* ֻ�������Ķ˿�ֵ, ����id��hash�ֶ� */
+ dport = tuple5->sport_net_order;
+ }
+ }else{
+ if(0 == tuple5->dir_reverse){
+ sip = tuple5->ippair_v6->sip_net_order.s6_addr32[0]; /* ʹ�����4�ֽ� */
+ dip = tuple5->ippair_v6->dip_net_order.s6_addr32[0]; /* ʹ�����4�ֽ� */
+ sport_no_id_hash = ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK;
+ dport = tuple5->dport_net_order;
+ }else{
+ sip = tuple5->ippair_v6->dip_net_order.s6_addr32[0]; /* ʹ�����4�ֽ� */
+ dip = tuple5->ippair_v6->sip_net_order.s6_addr32[0]; /* ʹ�����4�ֽ� */
+ sport_no_id_hash = ntohs(tuple5->dport_net_order) & FLWD_UDP_SPORT_ACTUAL_PORT_MASK;
+ dport = tuple5->sport_net_order;
+ }
+ }
+
+ port_union = (unsigned int)sport_no_id_hash;
+ port_union |= ((unsigned int)dport << 16);
+ port_union += JHASH_INITVAL;
+
+ __jhash_final(sip, dip, port_union);
+
+ return port_union;
+}
+
|
