summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorlijia <[email protected]>2018-10-24 09:36:45 +0800
committerlijia <[email protected]>2018-10-24 09:36:45 +0800
commit86a43b4d325ddc850fa9dc4711670880f35b11e8 (patch)
tree8356a056ac9bfb8cf14fcf57f113dd306b4277d1 /src/common
create new project.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile42
-rw-r--r--src/common/flwd_arp.c252
-rw-r--r--src/common/flwd_common_hash.c98
-rw-r--r--src/common/flwd_common_maat.c153
-rw-r--r--src/common/flwd_common_stack.c449
-rw-r--r--src/common/flwd_common_tool.c911
-rw-r--r--src/common/flwd_compat_marsio_hash.c23
-rw-r--r--src/common/flwd_network_connect.c363
-rw-r--r--src/common/flwd_sendpacket.c138
-rw-r--r--src/common/flwd_status.c275
-rw-r--r--src/common/linux_jhash_algo.c267
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;
+}
+