summaryrefslogtreecommitdiff
path: root/src/access/flwd_access_active_ip_manage.c
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/access/flwd_access_active_ip_manage.c
create new project.
Diffstat (limited to 'src/access/flwd_access_active_ip_manage.c')
-rw-r--r--src/access/flwd_access_active_ip_manage.c616
1 files changed, 616 insertions, 0 deletions
diff --git a/src/access/flwd_access_active_ip_manage.c b/src/access/flwd_access_active_ip_manage.c
new file mode 100644
index 0000000..8b3e876
--- /dev/null
+++ b/src/access/flwd_access_active_ip_manage.c
@@ -0,0 +1,616 @@
+/*
+ ��ԾIP��ַ����ģ��,
+ ����IP������ϵͳ��IP, ����MAAT-IP�ص���,
+*/
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include "MESA_handle_logger.h"
+#include "MESA_htable.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>
+
+
+/*
+ TODO:
+ ȫ�����н������ط���Ψһ��id, ����Ȼ��1��ʼ,
+ ��������N����ÿ����������ʹ�õ�Դ�˿ڷ�Χ, ������1ʹ��10001-20000, ����2ʹ��20001-30000�ȵ�,
+ IP��ȫ�ֹ���, ��ͬ��������֮��Ķ˿ڰ���Χ����, ��֤���֮�以����ͻ!
+
+ ÿ�����������ڲ��ٸ����߳�����, ���������ö˿ڷֳ�THREAD_NUM��,
+ ������1���߳�1ʹ��10001-12000, ����1���߳�2ʹ��12001-14000, �ȵ�.
+*/
+
+
+MESA_ATOMIC_T flwd_temp_active_ip_op_flag[FLWD_MAX_THREAD_NUM];
+MESA_lqueue_head flwd_temp_active_ip_to_deal[FLWD_MAX_THREAD_NUM]; /* �ṹ: flwd_temp_to_deal_act_ip_t */
+
+
+typedef struct{
+ flwd_ip_t active_ip_net_order;
+ char is_valid; /* 1:usabel, add; 0:disable, del */
+}flwd_temp_to_deal_act_ip_t;
+
+static void flwd_act_ip_htable_data_free(void *data);
+
+
+static unsigned short flwd_act_ip_mask_to_num(unsigned short mask_to_num)
+{
+ int i;
+
+ for(i = 0; i < 16; i++){
+ if(0 != (mask_to_num & 1)){ /* һֱ����, ֱ�����λ��Ϊ0Ϊֹ */
+ break;
+ }else{
+ mask_to_num = mask_to_num >> 1;
+ }
+ }
+
+ return mask_to_num;
+}
+
+
+static unsigned short flwd_act_ip_get_acc_gateway_num(void)
+{
+ return flwd_act_ip_mask_to_num(FLWD_SPORT_ACC_ID_MASK);
+}
+
+unsigned short flwd_act_ip_get_usable_udp_sport_num(void)
+{
+ return flwd_act_ip_mask_to_num(FLWD_UDP_SPORT_ACTUAL_PORT_MASK);
+}
+
+unsigned short flwd_act_ip_get_usable_tcp_sport_num(void)
+{
+ return flwd_act_ip_mask_to_num(FLWD_TCP_SPORT_ACTUAL_PORT_MASK);
+}
+
+static int flwd_act_ip_get_tcp_usable_sport(int tid,
+ unsigned short *begin_port, unsigned short *usable_count)
+{
+ unsigned short this_gateway_begin_port;
+ unsigned short this_thread_usable_tot_count;
+ unsigned short this_gateway_usable_tot_count;
+
+ this_gateway_usable_tot_count = flwd_act_ip_get_usable_tcp_sport_num();
+
+ /* NOTE: current_access_gateway_idΪ�˷�������, ����Ȼ��1��ʼ, �˴���Ҫ��1, ���߳�id��0��ʼ, �����1 */
+
+ /* gateway_id���Ƶ����λ */
+ this_gateway_begin_port = (((unsigned short)flwd_cfg_val.current_access_gateway_id - 1) << (FLWD_SPORT_ACC_ID_SHIFT_NUM));
+
+ this_thread_usable_tot_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *usable_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *begin_port = this_gateway_begin_port | (*usable_count) * tid;
+
+ return 0;
+}
+
+
+static int flwd_act_ip_get_udp_usable_sport(int tid,
+ unsigned short *begin_port, unsigned short *usable_count)
+{
+ unsigned short this_gateway_begin_port;
+ unsigned short this_thread_usable_tot_count;
+ unsigned short this_gateway_usable_tot_count;
+
+ this_gateway_usable_tot_count = flwd_act_ip_get_usable_udp_sport_num();
+
+ /* NOTE: current_access_gateway_idΪ�˷�������, ����Ȼ��1��ʼ, �˴���Ҫ��1, ���߳�id��0��ʼ, �����1 */
+
+ /* gateway_id���Ƶ����λ */
+ this_gateway_begin_port = (((unsigned short)flwd_cfg_val.current_access_gateway_id - 1) << (FLWD_SPORT_ACC_ID_SHIFT_NUM));
+
+ this_thread_usable_tot_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *usable_count = this_gateway_usable_tot_count/flwd_cfg_val.tot_thread_count;
+
+ *begin_port = this_gateway_begin_port | (*usable_count) * tid;
+
+ return 0;
+}
+
+/*
+ NOTE:
+ ���ݻص����������Ļ�ԾIP, ��Ϊkey����htable,
+ ���ݵ�ǰ�������ص�id, ������������, ���߳�ID, ���ɿ��õĶ˿��б�.
+*/
+static flwd_active_ip_t *flwd_act_ip_create_new_node(int tid, const flwd_active_ip_t *act_ip_stack)
+{
+ flwd_active_ip_t *act_ip_heap;
+ unsigned short udp_begin_port, tcp_begin_port, tport;
+ unsigned short udp_usable_count, tcp_usable_count;
+ unsigned short i;
+ MESA_list_count_t *list_node;
+
+ act_ip_heap = (flwd_active_ip_t *)malloc(sizeof(flwd_active_ip_t));
+ memcpy(act_ip_heap, act_ip_stack, sizeof(flwd_active_ip_t));
+
+ MESA_list_init_head(&act_ip_heap->active_ip_list_node);
+ act_ip_heap->active_ip_list_node.quiddity = act_ip_heap; /* Ϊ�˽�Լ�ڴ�, ����ͷҲ�洢����, ��������dynamic���ͺͽ���һ��IP��static������˵, �������¹���һ���ڵ�, quiddityִ�������ṹ��ͷ�� */
+
+ /* TCP��UDP�Ķ˿ڷֿ��洢ʹ��, ������չһ����ԾIP��ʵ�ʸ��÷�Χ */
+ MESA_list_count_init_head(&act_ip_heap->usable_tcp_sport_list_head);
+ MESA_list_count_init_head(&act_ip_heap->usable_udp_sport_list_head);
+
+ flwd_act_ip_get_udp_usable_sport(tid, &udp_begin_port, &udp_usable_count);
+
+ for(i = 0; i < udp_usable_count; i++){
+ list_node = (MESA_list_count_t *)calloc(1, sizeof(MESA_list_count_t));
+ tport = udp_begin_port + i;
+ tport |= (flwd_cfg_val.current_access_gateway_id << FLWD_SPORT_ACC_ID_SHIFT_NUM);
+ tport = htons(tport); /* convert to net_order */
+ memcpy(&list_node->quiddity, &tport, sizeof(short)); /* ԭ���˴�������ָ��, ֱ�Ӹ����ڴ��ַ, �洢2���ֽڵĶ˿�ֵ, net_order */
+ MESA_list_count_add(&act_ip_heap->usable_udp_sport_list_head, list_node);
+ }
+
+ flwd_act_ip_get_tcp_usable_sport(tid, &tcp_begin_port, &tcp_usable_count);
+
+ for(i = 0; i < tcp_usable_count; i++){
+ list_node = (MESA_list_count_t *)calloc(1, sizeof(MESA_list_count_t));
+ tport = tcp_begin_port + i;
+ tport |= (flwd_cfg_val.current_access_gateway_id << FLWD_SPORT_ACC_ID_SHIFT_NUM);
+ tport = htons(tport); /* convert to net_order */
+
+ memcpy(&list_node->quiddity, &tport, sizeof(short)); /* ԭ���˴�������ָ��, ֱ�Ӹ����ڴ��ַ, �洢2���ֽڵĶ˿�ֵ, net_order */
+ MESA_list_count_add(&act_ip_heap->usable_tcp_sport_list_head, list_node);
+ }
+
+ return act_ip_heap;
+}
+
+#if FLWD_ASYNC_LOCK_FREE
+/* NOTE: �˺����ڰ������߳���������, ����ģʽ�����µĻ�Ծip */
+int flwd_act_ip_hash_proc(int tid, flwd_active_ip_t *act_ip_stack)
+{
+ MESA_htable_handle flwd_act_htable;
+ unsigned char *ip_key;
+ unsigned int ip_key_size;
+ flwd_active_ip_t *act_ip_heap;
+ int ret;
+ char ip_str[64];
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == act_ip_stack->active_ip_net_order.addr_type)){
+ if(FLWD_IP_REGION_INLAND == act_ip_stack->ip_region_type){
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv4_pool_inland;
+ }else{
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv4_pool_outland;
+ }
+ ip_key = (unsigned char *)&act_ip_stack->active_ip_net_order.addr_ipv4;
+ ip_key_size = sizeof(int);
+ inet_ntop(AF_INET, &act_ip_stack->active_ip_net_order.addr_ipv4, ip_str, 64);
+ }else{
+ if(FLWD_IP_REGION_INLAND == act_ip_stack->ip_region_type){
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv6_pool_inland;
+ }else{
+ flwd_act_htable = flwd_thread_val[tid].flwd_active_ipv6_pool_outland;
+ }
+ ip_key = (unsigned char *)&act_ip_stack->active_ip_net_order.addr_ipv6;
+ ip_key_size = sizeof(struct in6_addr);
+ inet_ntop(AF_INET6, &act_ip_stack->active_ip_net_order.addr_ipv6, ip_str, 64);
+ }
+
+ if(act_ip_stack->is_valid){
+ if(MESA_htable_search(flwd_act_htable, ip_key, ip_key_size) == NULL){
+ act_ip_heap = flwd_act_ip_create_new_node(tid, act_ip_stack);
+ ret = MESA_htable_add(flwd_act_htable, ip_key, ip_key_size, act_ip_heap);
+ if(ret < 0){
+ flwd_act_ip_htable_data_free(act_ip_heap);
+ flwd_log(30, "add new active ip to htable fail, ret=%d\n", ret);
+ }else{
+ flwd_log(10, "add new active ip:%s\n", ip_str);
+ }
+ }else{
+ ; /* already exist, do nothing. */
+ }
+ }else{
+ /* */
+ MESA_htable_del(flwd_act_htable, ip_key, ip_key_size, NULL);
+ flwd_log(10, "del old active ip:%s\n", ip_str);
+ }
+
+ return 0;
+}
+#endif
+
+
+static void flwd_act_ip_dynamic_update(const flwd_active_ip_t *stack_act_ip)
+{
+ int i, ret;
+ flwd_active_ip_t *heap_act_ip;
+ unsigned int key_size;
+ unsigned char *key;
+ char ip_str[64];
+
+ if(FLWD_IP_ADDR_TYPE_V4 == stack_act_ip->active_ip_net_order.addr_type){
+ key = (unsigned char *)&stack_act_ip->active_ip_net_order.addr_ipv4;
+ key_size = sizeof(int);
+ }else{
+ key = (unsigned char *)&stack_act_ip->active_ip_net_order.addr_ipv6;
+ key_size = sizeof(struct in6_addr);
+ }
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ pthread_rwlock_wrlock(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock);
+
+ if(0 == stack_act_ip->is_valid){
+ MESA_htable_del(flwd_thread_val[i].flwd_ip_pool_dynamic_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type],
+ key, key_size, NULL);
+ }else{
+ /* ���������, ����һ��, htable���Ƿ��Ѿ����� */
+ heap_act_ip = (flwd_active_ip_t *)MESA_htable_search(flwd_thread_val[i].flwd_ip_pool_dynamic_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type],
+ key, key_size);
+ if(heap_act_ip != NULL){
+ /* ��ԾIP�ظ�, do nonthing !! */
+ pthread_rwlock_unlock(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock);
+ return;
+ }
+
+ heap_act_ip = flwd_act_ip_create_new_node(i, stack_act_ip);
+ ret = MESA_htable_add(flwd_thread_val[i].flwd_ip_pool_dynamic_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type],
+ key, key_size, heap_act_ip);
+ assert(ret >= 0);
+ flwd_log(10, "add dynamic ip pool addr:'%s'\n ", flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }
+
+ pthread_rwlock_unlock(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock);
+ }
+
+ return;
+}
+
+
+/* �ж�IP�Ƿ�����е��ظ�(�˹�����, ���������ظ�IP), ������ʱҲ���ܸ���һ����IP�Ͷ˿�, ������� */
+
+static int flwd_static_ip_pool_is_dup(const flwd_active_ip_t *act_ip_head,
+ const flwd_active_ip_t *stack_act_ip)
+{
+ const MESA_list_t *in_list_node = &act_ip_head->active_ip_list_node;
+ const flwd_active_ip_t *in_list_ipt;
+
+ do{
+ in_list_ipt = (flwd_active_ip_t *)in_list_node->quiddity;
+ if(flwd_ipt_equal(&in_list_ipt->active_ip_net_order, &stack_act_ip->active_ip_net_order) == 1){
+ return 1;
+ }
+ in_list_node = in_list_node->nextele;
+ }while(in_list_node != &act_ip_head->active_ip_list_node); /* ˫��ѭ������, ��ֹ��ѭ�� */
+
+ return 0;
+}
+
+
+/* ��̬IP����group_idΪkey, IP_listΪdata */
+static void flwd_act_ip_static_update(const flwd_active_ip_t *stack_act_ip)
+{
+ int i, ret;
+ flwd_active_ip_t *act_ip_head;/* htable�е�ip�ڵ� */
+ flwd_active_ip_t *heap_act_ip; /* ����������ip */
+ char ip_str[64];
+ void *ip_static_htable;
+
+ /* NOTE: ���Ӻ�ɾ��IPʱʹ��group_id����ip_list, Ȼ���ٱ���; �����ö˿ڻ���ʱ, ֻ��IP�Ͷ˿�, û��Group_id�ĸ���,
+ ��flwd_ip_pool_static_htable��, ʹ��������ͬ��key, ����ͬһ��data, ��ip_list.
+
+ update_cbʹ��group_id����ip_list;
+ sport_recycleʹ��ip��ַ����ip_list;
+
+ Ϊ�˷�ֹ��һgroup_id��ipv4��ַ��ͻ, ��groupתΪ�ַ���ģʽ, ǰ�����GPIDǰ׺, ������֤key�ij��ȶ���һ��, �϶�Ҳ�����ͻ.
+ */
+ unsigned char static_ip_group_key[64];
+ int static_ip_group_key_len = 64;
+ flwd_policy_group_id_key_gen(stack_act_ip->policy_group_id, static_ip_group_key, &static_ip_group_key_len);
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ /* NOTE: �˺�������maat�ص��߳�������, �����������̵߳����ݽṹ, ��Ҫ����! */
+ pthread_rwlock_wrlock(&flwd_thread_val[i].flwd_ip_pool_static_rwlock);
+
+ ip_static_htable = flwd_thread_val[i].flwd_ip_pool_static_htable[stack_act_ip->active_ip_net_order.addr_type][stack_act_ip->ip_region_type];
+
+ if(0 == stack_act_ip->is_valid){
+ flwd_ip_pool_del(FLWD_ACT_IP_STATIC,
+ ip_static_htable,
+ stack_act_ip->policy_group_id,
+ flwd_act_ip_htable_data_free,
+ stack_act_ip);
+ }else{
+ /* ���������, ����һ��htable���Ƿ��Ѿ����� */
+ act_ip_head = (flwd_active_ip_t *)flwd_ip_pool_search(FLWD_ACT_IP_STATIC,
+ ip_static_htable,
+ (unsigned char *)static_ip_group_key,
+ static_ip_group_key_len);
+ if(act_ip_head != NULL){
+ /* group-list�Ѵ���, �ж�IP�Ƿ�����е��ظ�(�˹�����, ���������ظ�IP), ������ʱҲ���ܸ���һ����IP�Ͷ˿�, ������� */
+ if(flwd_static_ip_pool_is_dup(act_ip_head, stack_act_ip) == 0){
+ heap_act_ip = flwd_act_ip_create_new_node(i, stack_act_ip);
+
+ MESA_list_add(&act_ip_head->active_ip_list_node, &heap_act_ip->active_ip_list_node);
+
+ /* ��ipΪkey, �ٲ���һ��hash��, ���ڶ˿ڻ���ʱ, û��group_id, Ҳ�ܿ�ip�ҵ���Ӧ��ip_list */
+ ret = MESA_htable_add(ip_static_htable,
+ stack_act_ip->active_ip_net_order.addr_value,
+ stack_act_ip->active_ip_net_order.addr_len,
+ heap_act_ip);
+ assert(ret >= 0);
+ flwd_log(10, "add static ip pool addr:'%s'\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }else{
+ flwd_log(20, "static ip pool %s is duplicated!\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }
+ }else{
+ /* ��ǰpolicy��û��IP, ��һ��, Ҳ����������ͷ�ڵ�, ֱ����MESA_htable_add����, */
+ heap_act_ip = flwd_act_ip_create_new_node(i, stack_act_ip);
+ ret = MESA_htable_add(ip_static_htable,
+ (unsigned char *)static_ip_group_key,
+ static_ip_group_key_len,
+ heap_act_ip);
+ assert(ret >= 0);
+ /* ��ipΪkey, �ٲ���һ��hash��, ���ڶ˿ڻ���ʱ, û��group_id, Ҳ�ܿ�ip�ҵ���Ӧ��ip_list */
+ ret = MESA_htable_add(ip_static_htable,
+ stack_act_ip->active_ip_net_order.addr_value,
+ stack_act_ip->active_ip_net_order.addr_len,
+ heap_act_ip);
+ if(ret < 0){
+ /* ������IP�ظ���! �����Dz�ͬ�������������ͬ��IP��ַ! */
+ /* TODO, ���������ô��?? ͬһ��IP���ڲ�ͬ����, �ɲ�����?? */
+ //flwd_act_ip_htable_data_free(heap_act_ip);
+ flwd_log(30, "add static ip pool addr:'%s' error, ret=%d\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64), ret);
+ }else{
+ flwd_log(10, "add static ip pool addr:'%s'\n ",
+ flwd_ipt_ntop_r(&stack_act_ip->active_ip_net_order, ip_str, 64));
+ }
+ }
+ }
+
+ pthread_rwlock_unlock(&flwd_thread_val[i].flwd_ip_pool_static_rwlock);
+ }
+
+ return;
+}
+
+/*
+ NOTE:
+ ��̬��ԾIP��IP��ַΪkey, dataΪflwd_active_ip_t, ֻ����һ���ڵ�, active_ip_list_nodeָ�붼�ǿ�;
+ ��̬IP��ַ�صĵ�ַ�Բ�����IDΪkey, dataΪflwd_active_ip_t������, ����������ͬpolicy_id��IP;
+*/
+void flwd_act_ip_update(const flwd_active_ip_t *stack_act_ip)
+{
+ if(FLWD_ACT_IP_DYNAMIC == stack_act_ip->ip_origin_type){
+ flwd_act_ip_dynamic_update(stack_act_ip);
+ }else{
+ flwd_act_ip_static_update(stack_act_ip);
+ }
+
+ return;
+}
+
+
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+/* ģ���ԾIP����ϵͳ, ��һЩ������ģ�� */
+
+/*
+ ���ݿ����ʽ:
+ "id addr_type ipaddr port user_region(GDEV_IP) location is_valid op_time"
+ "1 4 11.22.33.44 0 100 0 1 2018-06-03 11:11:11"
+*/
+static void flwd_phony_act_ipv4_gen(int is_valid, unsigned ip_addr, unsigned int group_id, flwd_ip_region_type_t region_type, flwd_active_ip_type_t origin_type)
+{
+ int rand_num;
+ flwd_active_ip_t stack_act_ip;
+
+ rand_num = rand();
+
+ stack_act_ip.is_valid = is_valid;
+ stack_act_ip.policy_group_id = group_id;
+
+ stack_act_ip.ip_region_type = region_type; /* ����ip���� */
+
+ stack_act_ip.ip_origin_type = origin_type;
+
+ stack_act_ip.active_ip_net_order.addr_ipv4 = ip_addr;
+ stack_act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ stack_act_ip.active_ip_net_order.addr_len = sizeof(int);
+
+ stack_act_ip.gdev_args.gdev_ip_net_order = 0x01010101;
+
+ flwd_act_ip_update(&stack_act_ip);
+
+}
+
+static void *flwd_act_ip_phony_discoverer(void *arg)
+{
+ int i = 0;
+ time_t tstart;
+
+ tstart = time(NULL);
+
+ while(1){
+ for(i = 0; i < 100; i++){
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_DYNAMIC);
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_DYNAMIC);
+
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_STATIC);
+ flwd_phony_act_ipv4_gen(1, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_STATIC);
+ }
+
+ usleep(10);
+#if 1
+ for(i = 0; i < 100; i++){
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_DYNAMIC);
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_INLAND, FLWD_ACT_IP_STATIC);
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_DYNAMIC);
+ flwd_phony_act_ipv4_gen(0, i, i, FLWD_IP_REGION_OUTLAND, FLWD_ACT_IP_STATIC);
+ }
+#endif
+
+ if(tstart + 60 < time(NULL)){
+ sleep(5);
+ exit(1);
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+static int flwd_act_ip_htable_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_act_ip_htable_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_act_ip_htable_data_free(void *data)
+{
+ flwd_active_ip_t *act_ip = (flwd_active_ip_t *)data;
+ MESA_list_count_t *list_node, *next_node;
+ char ip_str[64];
+
+ while((0 == MESA_list_count_is_empty(&act_ip->usable_tcp_sport_list_head))){
+ list_node = act_ip->usable_tcp_sport_list_head.nextele;
+ MESA_list_count_del(&act_ip->usable_tcp_sport_list_head, list_node);
+ free(list_node);
+ }
+
+ while((0 == MESA_list_count_is_empty(&act_ip->usable_udp_sport_list_head))){
+ list_node = act_ip->usable_udp_sport_list_head.nextele;
+ MESA_list_count_del(&act_ip->usable_udp_sport_list_head, list_node);
+ free(list_node);
+ }
+
+ flwd_log(10, "del ip pool addr:'%s'\n ", flwd_ipt_ntop_r(&act_ip->active_ip_net_order, ip_str, 64));
+
+ memset(act_ip, 0xFE, sizeof(flwd_active_ip_t));
+
+ free(data);
+}
+
+static MESA_htable_handle flwd_act_ip_htable_create(void)
+{
+ int opt_int;
+ MESA_htable_handle htable;
+
+ htable = MESA_htable_born();
+ assert(htable != NULL);
+
+ opt_int = 0; /* ���ⲿ��rwlock��д��ʵ�ֶ��̰߳�ȫ, ��htable�ڲ��Ļ��������ܸ���һЩ */
+ MESA_htable_set_opt(htable, MHO_THREAD_SAFE, &opt_int, sizeof(int));
+
+ opt_int = 1024 * 32;
+ MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int));
+
+ opt_int = 100000;
+ MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &opt_int, sizeof(int));
+
+ opt_int = 0; /* ��ԾIP�ص����г�ʱɾ������, ��redis�ص�ʵ��, ����htable������ʱ */
+ MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_act_ip_htable_key_cmp, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_act_ip_htable_key2index, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_act_ip_htable_data_free, 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));
+
+ /* searchʱ�ӵ��Ƕ���, ֻ����FIFOģʽ, LRUģʽ�ڲ���д���� */
+ opt_int = HASH_ELIMINATE_ALGO_FIFO;
+ MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &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;
+}
+
+
+/*
+ TODO:
+ ����SNAT��˵, act_ip����IP������ϵͳ�ش���IP, ��������;
+ ����DNAT��˵, act_ip�ǽ��������������ip, ��Ϊֻ��һ��ip����65535���˿ڿ���, �������ļ��������������⶯̬ip��ʼ��ַ������:
+
+ [TOPO_ACC_LINK_USER]
+ gateway_slave_ip_range = 10.0.9.100
+ gateway_slave_ip_num = 10
+
+ ��˼�Ǵ�10.0.9.100��ʼ, ��10.0.9.109���ǽ�����������������ʵ�ڲ���������ip,
+ Ҫ������ЩIP��arp����, �ظ�Ӧ���.
+*/
+
+
+int flwd_access_active_ip_init(void)
+{
+ int i;
+ int v4_or_v6, in_or_out;
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ flwd_temp_active_ip_to_deal[i] = MESA_lqueue_create(0, 1000); /* �첽������б�������, ��ԭ�ӱ������� */
+
+ MESA_ATOMIC_SET(flwd_temp_active_ip_op_flag[i], 0);
+#if 0
+ flwd_thread_val[i].flwd_active_ipv4_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_active_ipv4_pool_outland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_active_ipv6_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_active_ipv6_pool_outland = flwd_act_ip_htable_create();
+
+ flwd_thread_val[i].flwd_static_ipv4_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_static_ipv4_pool_outland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_static_ipv6_pool_inland = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_static_ipv6_pool_outland = flwd_act_ip_htable_create();
+#else
+ for(v4_or_v6 = 0; v4_or_v6 <= 1; v4_or_v6++){
+ for(in_or_out = 0; in_or_out <= 1; in_or_out++){
+ flwd_thread_val[i].flwd_ip_pool_dynamic_htable[v4_or_v6][in_or_out] = flwd_act_ip_htable_create();
+ flwd_thread_val[i].flwd_ip_pool_static_htable[v4_or_v6][in_or_out] = flwd_act_ip_htable_create();
+ }
+ }
+ pthread_rwlock_init(&flwd_thread_val[i].flwd_ip_pool_dynamic_rwlock, NULL);
+ pthread_rwlock_init(&flwd_thread_val[i].flwd_ip_pool_static_rwlock, NULL);
+#endif
+ }
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+ pthread_t pid;
+
+ pthread_create(&pid, NULL, flwd_act_ip_phony_discoverer, NULL);
+#endif
+
+ return 0;
+}
+