summaryrefslogtreecommitdiff
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
create new project.
-rw-r--r--Makefile44
-rw-r--r--bin/conf/flowood.conf62
-rw-r--r--bin/conf/maat_tableinfo.conf16
-rw-r--r--bin/conf/maat_test.json89
-rw-r--r--bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local2
-rw-r--r--bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local3
-rw-r--r--bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local3
-rw-r--r--bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local3
-rw-r--r--bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local3
-rw-r--r--bin/conf/maat_test.json_iris_tmp/index/full_config_index.00000000015
-rw-r--r--bin/conf/network_access.cfg4
-rw-r--r--bin/conf/network_connect.cfg6
-rw-r--r--bin/conf/network_forward.cfg6
-rw-r--r--bin/conf/network_gdev.cfg6
-rw-r--r--bin/flowood_keepalive.py19
-rw-r--r--bin/flwd_r23
-rw-r--r--bin/flwd_r317
-rw-r--r--bin/io_lib/flwd_io_pcap.sobin0 -> 30411 bytes
-rw-r--r--bin/io_lib/flwd_io_socket.sobin0 -> 26649 bytes
-rw-r--r--bin/memchk.sh2
-rw-r--r--bin/rulescan_tmp/rulescan_iie.log0
-rw-r--r--deploy.txt13
-rw-r--r--deploy/ethtool3
-rw-r--r--deploy/ip_forward1
-rw-r--r--deploy/iptable_drop_rst1
-rw-r--r--deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpmbin0 -> 91900 bytes
-rw-r--r--deploy/pptpd/pptpd_install/auth-down7
-rw-r--r--deploy/pptpd/pptpd_install/auth-up19
-rw-r--r--deploy/pptpd/pptpd_install/chap-secrets58
-rw-r--r--deploy/pptpd/pptpd_install/options.pptpd134
-rw-r--r--deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpmbin0 -> 81428 bytes
-rw-r--r--deploy/pptpd/pptpd_install/pptpd.conf106
-rw-r--r--deploy/pptpd/pptpd_install/pptpd.install.sh16
-rw-r--r--deploy/problem2
-rw-r--r--deploy/user_pass8
-rw-r--r--inc/flowood.h491
-rw-r--r--inc/flowood_fun.h92
-rw-r--r--inc/flwd_net.h389
-rw-r--r--inc/ltsm.h117
-rw-r--r--lib/libltsm.abin0 -> 5968 bytes
-rw-r--r--src/Makefile59
-rw-r--r--src/access/Makefile26
-rw-r--r--src/access/flowood_access.c1656
-rw-r--r--src/access/flwd_access_active_ip_manage.c616
-rw-r--r--src/access/flwd_access_idle_call.c66
-rw-r--r--src/access/flwd_access_ip_layer.c6
-rw-r--r--src/access/flwd_access_l2tp_layer.c22
-rw-r--r--src/access/flwd_access_maat.c582
-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
-rw-r--r--src/flowood_main.c155
-rw-r--r--src/forward/Makefile27
-rw-r--r--src/forward/flowood_forward.c1044
-rw-r--r--src/forward/flwd_fwd_idle_call.c5
-rw-r--r--src/forward/flwd_fwd_maat.c40
-rw-r--r--src/packet_io/Makefile34
-rw-r--r--src/packet_io/flwd_io_pcap.sobin0 -> 30411 bytes
-rw-r--r--src/packet_io/flwd_io_socket.sobin0 -> 26649 bytes
-rw-r--r--src/packet_io/flwd_packet_io.c193
-rw-r--r--src/packet_io/flwd_packet_io_pcap.c428
-rw-r--r--src/packet_io/flwd_packet_io_socket.c376
-rw-r--r--src/packet_io/nf-queue.c213
-rw-r--r--src/packet_io/nfq_test.c270
-rw-r--r--support/include/MESA_atomic_for_view.h38
-rw-r--r--support/include/MESA_handle_logger_for_view.h68
-rw-r--r--support/include/MESA_htable_for_view.h393
-rw-r--r--support/include/MESA_list_count_for_view.h31
-rw-r--r--support/include/MESA_list_for_view.h34
-rw-r--r--support/include/MESA_list_queue_for_view.h115
-rw-r--r--support/include/MESA_prof_load_for_view.h179
-rw-r--r--support/include/MESA_ring_queue_for_view.h107
-rw-r--r--support/include/Maat_command_for_view.h154
-rw-r--r--support/include/Maat_rule_for_view.h228
-rw-r--r--support/include/field_stat2_for_view.h66
-rw-r--r--support/include/本文件夹中的文件仅用于查看_不编译.txt0
-rw-r--r--support/ltsm/Makefile14
-rw-r--r--support/ltsm/ltsm.c485
-rw-r--r--support/ltsm/ltsm.h117
-rw-r--r--support/ltsm/ltsm_with_hash.h81
-rw-r--r--support/ltsm/test_ltsm.c59
-rw-r--r--test/mutex_vs_rdlock.c138
-rw-r--r--test/sport_usable.c45
91 files changed, 12891 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..27ce0e6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,44 @@
+__YES=1
+__NO=0
+TYPE_ACCESS=access
+TYPE_FORWARD=forward
+type=
+__MAKE_CHECK=$(__NO)
+CFLAGS=
+
+ifeq ($(type), $(TYPE_ACCESS))
+ __MAKE_CHECK = $(__YES)
+ CFLAGS += -DCOMPILE_ACCESS=1
+endif
+
+ifeq ($(type), $(TYPE_FORWARD))
+ __MAKE_CHECK = $(__YES)
+ CFLAGS += -DCOMPILE_FORWARD=1
+endif
+
+ifeq ($(__MAKE_CHECK), $(__NO))
+ $(error must assign type use make type=[access|forward]!)
+ exit
+endif
+
+export CFLAGS
+export type
+export TYPE_ACCESS
+export TYPE_FORWARD
+
+all:
+ cd support/ltsm; $(MAKE);
+ cd src/access; $(MAKE);
+ cd src/common; $(MAKE);
+ cd src/packet_io; $(MAKE);
+ cd src/forward; $(MAKE);
+ cd src; $(MAKE);
+
+clean:
+ cd src/access; $(MAKE) clean;
+ cd src/common; $(MAKE) clean;
+ cd src/packet_io; $(MAKE) clean;
+ cd src/forward; $(MAKE) clean;
+ cd src; $(MAKE) clean;
+ cd support/ltsm; $(MAKE) clean;
+ rm -f bin/flowood_access bin/flowood_forward
diff --git a/bin/conf/flowood.conf b/bin/conf/flowood.conf
new file mode 100644
index 0000000..d270e7e
--- /dev/null
+++ b/bin/conf/flowood.conf
@@ -0,0 +1,62 @@
+[main]
+thread_num=1
+nat_htable_timeout=180
+nat_htable_max_num=10000
+global_access_gateway_num = 5
+#id start with natural number, 1
+current_access_gateway_id = 2
+
+use_static_pool_ip_if_no_dynamic=0
+use_dynamic_pool_ip_if_no_static=0
+
+[log]
+log_level=10
+
+[maat]
+json_switch=1
+json_cfg_file=./conf/maat_test.json
+table_info=./conf/maat_tableinfo.conf
+inc_dir=./soqrule/inc/index/
+full_dir=./soqrule/full/index/
+
+
+#cap_mode: (0:pag,1:pcap,2:socket,3:pfring,4:DPDK,5:ppf,6:NPacket,7:qnf,8:N95,9:pcap-dumpfile-list,10:topsec
+# 11:ipfile, 12:marsio4, 13:agent_smith, 14:dpdk_vxlan, 15:marsio_vxlan, 16:pag_marsio)
+# for flowood, only support mode1, mode2, mode12!
+
+[TOPO_ACC_LINK_USER]
+cap_mode=1
+device_name=em1
+addr_para=172.18.1.229
+addr_mask=255.255.0.0
+gateway_ip=172.18.1.254
+pkt_filter=net 172.18.0.0/16
+
+
+[TOPO_ACC_LINK_FWD]
+cap_mode=2
+device_name=em2
+addr_para=64789
+#addr_para=172.16.1.229
+#addr_mask=255.255.255.0
+gateway_ip=192.168.10.1
+pkt_filter=
+
+[TOPO_FWD_LINK_ACC]
+cap_mode=2
+device_name=em1sdf
+addr_para=64789
+#addr_para=172.16.1.201
+#addr_mask=255.255.0.0
+gateway_ip=172.16.1.201
+pkt_filter=net 172.16.0.0/16
+
+
+[TOPO_FWD_LINK_GDEV]
+cap_mode=1
+device_name=em1
+addr_para=172.17.1.203
+addr_mask=255.255.0.0
+gateway_ip=172.17.1.1
+pkt_filter=net 172.17.0.0/16
+
diff --git a/bin/conf/maat_tableinfo.conf b/bin/conf/maat_tableinfo.conf
new file mode 100644
index 0000000..6d935bd
--- /dev/null
+++ b/bin/conf/maat_tableinfo.conf
@@ -0,0 +1,16 @@
+#each collumn seperate with '\t'
+#id (0~65535)
+#name string
+#type one of ip,expr,expr_plus,digest,intval,compile or plugin
+#src_charset one of GBK,BIG5,UNICODE,UTF8
+#dst_charset combined by GBK,BIG5,UNICODE,UTF8,seperate with '/'
+#do_merege yes or no
+#cross cache 0~max
+#quickswitch quickon or quick off
+#id name type src_charset dst_charset do_merge cross_cache quickswitch
+0 IR_POLICY_COMPILE compile UTF8 UTF8 no 0
+1 IR_POLICY_GROUP group UTF8 UTF8 no 0
+2 IR_POLICY_IP ip UTF8 UTF8 no 0
+3 IR_STATIC_IP_POOL_CB plugin UTF8 UTF8 no 0
+4 IR_DYN_SIFT_IP_CB plugin UTF8 UTF8 no 0
+5 IR_DYN_CONN_IP ip --
diff --git a/bin/conf/maat_test.json b/bin/conf/maat_test.json
new file mode 100644
index 0000000..9be798c
--- /dev/null
+++ b/bin/conf/maat_test.json
@@ -0,0 +1,89 @@
+{
+ "compile_table": "IR_POLICY_COMPILE",
+ "group_table": "IR_POLICY_GROUP",
+ "rules": [
+ {
+ "compile_id": 1,
+ "service": 1,
+ "action": 2,
+ "do_blacklist": 1,
+ "do_log": 1,
+ "effective_rage": 0,
+ "user_region": "IR_STRATEGY:10001",
+ "is_valid": "yes",
+ "groups": [
+ {
+ "group_name": "group_1",
+ "regions": [
+ {
+ "table_name": "IR_POLICY_IP",
+ "table_type": "ip",
+ "table_content": {
+ "addr_type": "ipv4",
+ "src_ip": "172.18.1.13",
+ "mask_src_ip": "255.255.255.255",
+ "src_port": "0",
+ "mask_src_port": "65535",
+ "dst_ip": "0.0.0.0",
+ "mask_dst_ip": "255.255.255.255",
+ "dst_port": "0",
+ "mask_dst_port": "65535",
+ "protocol": 0,
+ "direction": "double"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "compile_id": 2,
+ "service": 1,
+ "action": 2,
+ "do_blacklist": 1,
+ "do_log": 1,
+ "effective_rage": 0,
+ "user_region": "IR_STRATEGY:10002",
+ "is_valid": "yes",
+ "groups": [
+ {
+ "group_name": "group_2",
+ "regions": [
+ {
+ "table_name": "IR_POLICY_IP",
+ "table_type": "ip",
+ "table_content": {
+ "addr_type": "ipv4",
+ "src_ip": "172.18.1.222",
+ "mask_src_ip": "255.255.255.255",
+ "src_port": "0",
+ "mask_src_port": "65535",
+ "dst_ip": "0.0.0.0",
+ "mask_dst_ip": "255.255.255.255",
+ "dst_port": "0",
+ "mask_dst_port": "65535",
+ "protocol": 0,
+ "direction": "double"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "plugin_table": [
+ {
+ "table_name": "IR_DYN_SIFT_IP_CB",
+ "table_content": [
+ "1\t4\t0\t192.168.10.222\t0\t2\tgdev_ip=10.0.6.195;\t0\t1\t2018-07-15"
+ ]
+ },
+ {
+ "table_name": "IR_STATIC_IP_POOL_CB",
+ "table_content": [
+ "1\t4\t0\t47.74.128.220\t0\t2\tgdev_ip=10.0.6.195;\t0\t1\t1\t1\t10001\t2018-07-15",
+ "2\t4\t0\t192.168.10.222\t0\t2\tgdev_ip=10.0.6.195;\t0\t1\t1\t1\t10002\t2018-07-15"
+ ]
+ }
+ ]
+}
diff --git a/bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local b/bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local
new file mode 100644
index 0000000..2fc8e5f
--- /dev/null
+++ b/bin/conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local
@@ -0,0 +1,2 @@
+0000000001
+1 4 0 192.168.10.222 0 2 gdev_ip=10.0.6.195; 0 1 2018-07-15
diff --git a/bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local
new file mode 100644
index 0000000..f0d8445
--- /dev/null
+++ b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local
@@ -0,0 +1,3 @@
+0000000002
+1 1 2 1 1 0 IR_STRATEGY:10001 1
+2 1 2 1 1 0 IR_STRATEGY:10002 1
diff --git a/bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local
new file mode 100644
index 0000000..86bfaf1
--- /dev/null
+++ b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local
@@ -0,0 +1,3 @@
+0000000002
+0 1 1
+1 2 1
diff --git a/bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local
new file mode 100644
index 0000000..57f5ad9
--- /dev/null
+++ b/bin/conf/maat_test.json_iris_tmp/IR_POLICY_IP.local
@@ -0,0 +1,3 @@
+0000000002
+0 0 4 172.18.1.13 255.255.255.255 0 65535 0.0.0.0 255.255.255.255 0 65535 0 0 1
+1 1 4 172.18.1.222 255.255.255.255 0 65535 0.0.0.0 255.255.255.255 0 65535 0 0 1
diff --git a/bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local b/bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local
new file mode 100644
index 0000000..874147d
--- /dev/null
+++ b/bin/conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local
@@ -0,0 +1,3 @@
+0000000002
+1 4 0 47.74.128.220 0 2 gdev_ip=10.0.6.195; 0 1 1 1 10001 2018-07-15
+2 4 0 192.168.10.222 0 2 gdev_ip=10.0.6.195; 0 1 1 1 10002 2018-07-15
diff --git a/bin/conf/maat_test.json_iris_tmp/index/full_config_index.0000000001 b/bin/conf/maat_test.json_iris_tmp/index/full_config_index.0000000001
new file mode 100644
index 0000000..ba4e23c
--- /dev/null
+++ b/bin/conf/maat_test.json_iris_tmp/index/full_config_index.0000000001
@@ -0,0 +1,5 @@
+IR_POLICY_COMPILE 2 ./conf/maat_test.json_iris_tmp/IR_POLICY_COMPILE.local
+IR_POLICY_GROUP 2 ./conf/maat_test.json_iris_tmp/IR_POLICY_GROUP.local
+IR_DYN_SIFT_IP_CB 1 ./conf/maat_test.json_iris_tmp/IR_DYN_SIFT_IP_CB.local
+IR_STATIC_IP_POOL_CB 2 ./conf/maat_test.json_iris_tmp/IR_STATIC_IP_POOL_CB.local
+IR_POLICY_IP 2 ./conf/maat_test.json_iris_tmp/IR_POLICY_IP.local
diff --git a/bin/conf/network_access.cfg b/bin/conf/network_access.cfg
new file mode 100644
index 0000000..f88daa0
--- /dev/null
+++ b/bin/conf/network_access.cfg
@@ -0,0 +1,4 @@
+#global_id access_manage_ip access_feedback_ip
+#for example:
+1 10.0.6.229 172.16.0.229
+1 10.0.6.203 172.16.0.203
diff --git a/bin/conf/network_connect.cfg b/bin/conf/network_connect.cfg
new file mode 100644
index 0000000..23f5b9c
--- /dev/null
+++ b/bin/conf/network_connect.cfg
@@ -0,0 +1,6 @@
+#region vlan_id gdev_redirect_ip forward_manage_ip forward_feedback_ip
+#for example:
+#beijing 1 10.0.0.1 10.0.0.101 172.16.0.1
+#shanghai 1 10.0.1.1 10.0.1.103 172.16.1.3
+#guangzhou 1 10.0.2.3 10.0.2.101 172.16.2.1
+alamutu 1 10.0.6.201 10.0.6.201 10.0.6.201
diff --git a/bin/conf/network_forward.cfg b/bin/conf/network_forward.cfg
new file mode 100644
index 0000000..e41d4a5
--- /dev/null
+++ b/bin/conf/network_forward.cfg
@@ -0,0 +1,6 @@
+#region vlan_id forward_ip
+#for example:
+#beijing 1 10.0.0.101
+#shanghai 1 10.0.1.103
+#guangzhou 1 10.0.2.101
+huayan 1 10.0.6.201
diff --git a/bin/conf/network_gdev.cfg b/bin/conf/network_gdev.cfg
new file mode 100644
index 0000000..f57988d
--- /dev/null
+++ b/bin/conf/network_gdev.cfg
@@ -0,0 +1,6 @@
+#region vlan_id gdev_redirect_ip
+#for example:
+#beijing 1 10.0.0.1
+#shanghai 1 10.0.1.1
+#guangzhou 1 10.0.2.3
+huayan 1 10.0.6.195
diff --git a/bin/flowood_keepalive.py b/bin/flowood_keepalive.py
new file mode 100644
index 0000000..9fbf312
--- /dev/null
+++ b/bin/flowood_keepalive.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# 因某些NAT, 外网出口源端口会变化, 即便绑定了客户端的源端口也不行
+# 所以使用一个脚本, 让数据包源源不断的发送, 就可以维持住NAT的连接表,
+#
+from scapy import *
+from scapy.all import *
+import random
+
+while 1:
+ ip_pkt = IP(dst='47.75.205.197',src='192.168.10.214')
+ udp_pkt = UDP(dport=64789,sport=64789)
+ #dns_pkt = DNS(id=1,qr=0,opcode=0,tc=0,rd=1,qdcount=1,ancount=0,nscount=0,arcount=0)
+ #dns_pkt.qd=DNSQR(qname='www.keepalive.com',qtype=255,qclass=1)
+ #send_pkt = ip_pkt/udp_pkt/dns_pkt
+ payload = 'test';
+ send_pkt = ip_pkt/udp_pkt/payload
+ send(send_pkt)
+ time.sleep(0.33)
+pass \ No newline at end of file
diff --git a/bin/flwd_r2 b/bin/flwd_r2
new file mode 100644
index 0000000..dcdcbb8
--- /dev/null
+++ b/bin/flwd_r2
@@ -0,0 +1,3 @@
+killall flwd_r3 flowood_access
+./flwd_r3 &> /dev/null &
+#./kill_sapp_by_mem.sh &> /dev/null &
diff --git a/bin/flwd_r3 b/bin/flwd_r3
new file mode 100644
index 0000000..45b7d54
--- /dev/null
+++ b/bin/flwd_r3
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+while [ 1 ]; do
+ count=`ls -l core.* |wc -l`
+ echo $count
+ if [ $count -lt 5 ]
+ then
+ echo "set unlimited"
+ ulimit -c unlimited
+ else
+ ulimit -c 0
+ fi
+
+ ./flowood_access > /dev/null
+ echo program crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log
+ sleep 10
+done
diff --git a/bin/io_lib/flwd_io_pcap.so b/bin/io_lib/flwd_io_pcap.so
new file mode 100644
index 0000000..7af3822
--- /dev/null
+++ b/bin/io_lib/flwd_io_pcap.so
Binary files differ
diff --git a/bin/io_lib/flwd_io_socket.so b/bin/io_lib/flwd_io_socket.so
new file mode 100644
index 0000000..7db273b
--- /dev/null
+++ b/bin/io_lib/flwd_io_socket.so
Binary files differ
diff --git a/bin/memchk.sh b/bin/memchk.sh
new file mode 100644
index 0000000..5ce6bfb
--- /dev/null
+++ b/bin/memchk.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+valgrind --tool=memcheck --leak-check=full --leak-resolution=high --error-limit=no --undef-value-errors=yes --log-file=valgrind.log $1
diff --git a/bin/rulescan_tmp/rulescan_iie.log b/bin/rulescan_tmp/rulescan_iie.log
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/rulescan_tmp/rulescan_iie.log
diff --git a/deploy.txt b/deploy.txt
new file mode 100644
index 0000000..66a32fe
--- /dev/null
+++ b/deploy.txt
@@ -0,0 +1,13 @@
+#if 0
+1)���ڲ�������IR
+ ��Ϊ���Ի����ڵ�C�ζ��ǺϷ����õ�, ͨ���ֹ������ļ�, ģ��maat_cb,
+ ����dynamic_ip_pool_cb, �������ļ��е�IP��������̬���ֵ�IP��
+
+
+2)������IR
+ �������õĵ�ַ��IP�����Dz��Ի�����C��IP,
+ ͨ��maat_redis�ɻ�ȡ������Ŀǰû���Զ�������־����SMAC=xxx�ֶΣ���ȡ����GDEV�����Ϣ��
+ ֻ��ͨ�����ֳ�������Ȼ���Լ���static_ip_pool_cb��������һ��SMAC=xxxx��.
+
+#endif
+
diff --git a/deploy/ethtool b/deploy/ethtool
new file mode 100644
index 0000000..f16b4bb
--- /dev/null
+++ b/deploy/ethtool
@@ -0,0 +1,3 @@
+ethtool -K eth0 gso off
+ethtool -K eth0 gro off
+ethtool -K eth0 tso off
diff --git a/deploy/ip_forward b/deploy/ip_forward
new file mode 100644
index 0000000..3f15c3b
--- /dev/null
+++ b/deploy/ip_forward
@@ -0,0 +1 @@
+echo "1" > /proc/sys/net/ipv4/ip_forward
diff --git a/deploy/iptable_drop_rst b/deploy/iptable_drop_rst
new file mode 100644
index 0000000..30b6224
--- /dev/null
+++ b/deploy/iptable_drop_rst
@@ -0,0 +1 @@
+iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
diff --git a/deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm b/deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm
new file mode 100644
index 0000000..a3b67b9
--- /dev/null
+++ b/deploy/l2tp/xl2tpd-1.3.8-8.fc29.x86_64.rpm
Binary files differ
diff --git a/deploy/pptpd/pptpd_install/auth-down b/deploy/pptpd/pptpd_install/auth-down
new file mode 100644
index 0000000..81e2228
--- /dev/null
+++ b/deploy/pptpd/pptpd_install/auth-down
@@ -0,0 +1,7 @@
+#!/bin/bash
+# get the username from the parameters
+USER=$2
+# if there is a session already for this user, terminate the old one
+rm -f /var/run/ppp/current_user/$USER
+echo $2 link down ! >> /var/run/ppp/user_access.log
+
diff --git a/deploy/pptpd/pptpd_install/auth-up b/deploy/pptpd/pptpd_install/auth-up
new file mode 100644
index 0000000..d8a2c75
--- /dev/null
+++ b/deploy/pptpd/pptpd_install/auth-up
@@ -0,0 +1,19 @@
+#!/bin/bash
+# get the username from the parameters
+USER=$2
+# if there is a session already for this user, terminate the old one
+
+mkdir -p /var/run/ppp/current_user/
+
+PPID=`awk '/PPid/ { print $2; }' /proc/$$/status`
+
+if [ -f /var/run/ppp/current_user/$USER ]; then
+ echo $2 already access success, exit, pid:$$, ppid:$PPID >> /var/run/ppp/user_access.log
+ kill -9 $PPID
+else
+ echo $2 > /var/run/ppp/current_user/$USER
+ echo $2 dial up success! >> /var/run/ppp/user_access.log
+fi
+
+
+
diff --git a/deploy/pptpd/pptpd_install/chap-secrets b/deploy/pptpd/pptpd_install/chap-secrets
new file mode 100644
index 0000000..d27529d
--- /dev/null
+++ b/deploy/pptpd/pptpd_install/chap-secrets
@@ -0,0 +1,58 @@
+# Secrets for authentication using CHAP
+# client server secret IP addresses
+mesa pptpd 111111 *
+liuqingyun_hk pptpd 111111 172.18.1.101
+zhengchao_hk pptpd 111111 172.18.1.102
+yangrong_hk pptpd 111111 172.18.1.103
+zhouzhou_hk pptpd 111111 172.18.1.104
+lijia_hk pptpd 111111 172.18.1.105
+doufenghu_hk pptpd 111111 172.18.1.106
+dumeijie_hk pptpd 111111 172.18.1.107
+fengweihao_hk pptpd 111111 172.18.1.108
+guofu_hk pptpd 111111 172.18.1.109
+jixinyi_hk pptpd 111111 172.18.1.110
+lishu_hk pptpd 111111 172.18.1.111
+lizhao_hk pptpd 111111 172.18.1.111
+liujunpeng_hk pptpd 111111 172.18.1.112
+liuxueli_hk pptpd 111111 172.18.1.113
+liuyang_hk pptpd 111111 172.18.1.114
+luqiuwen_hk pptpd 111111 172.18.1.115
+qidaijie_hk pptpd 111111 172.18.1.116
+wangfengmei_hk pptpd 111111 172.18.1.117
+wangkuan_hk pptpd 111111 172.18.1.118
+wangyouzhan_hk pptpd 111111 172.18.1.119
+yangwei_hk pptpd 111111 172.18.1.120
+yulingjing_hk pptpd 111111 172.18.1.121
+zhangchengwei_hk pptpd 111111 172.18.1.122
+zhanglei_hk pptpd 111111 172.18.1.123
+zhangpeng_hk pptpd 111111 172.18.1.124
+jiamengdie_hk pptpd 111111 172.18.1.125
+zhuyujia_hk pptpd 111111 172.18.1.126
+
+liuqingyun_de pptpd 111111 172.18.1.131
+zhengchao_de pptpd 111111 172.18.1.132
+yangrong_de pptpd 111111 172.18.1.133
+zhouzhou_de pptpd 111111 172.18.1.134
+lijia_de pptpd 111111 172.18.1.135
+doufenghu_de pptpd 111111 172.18.1.136
+dumeijie_de pptpd 111111 172.18.1.137
+fengweihao_de pptpd 111111 172.18.1.138
+guofu_de pptpd 111111 172.18.1.139
+jixinyi_de pptpd 111111 172.18.1.140
+lishu_de pptpd 111111 172.18.1.141
+lizhao_de pptpd 111111 172.18.1.142
+liujunpeng_de pptpd 111111 172.18.1.143
+liuxueli_de pptpd 111111 172.18.1.144
+liuyang_de pptpd 111111 172.18.1.145
+luqiuwen_de pptpd 111111 172.18.1.146
+qidaijie_de pptpd 111111 172.18.1.147
+wangfengmei_de pptpd 111111 172.18.1.148
+wangkuan_de pptpd 111111 172.18.1.149
+wangyouzhan_de pptpd 111111 172.18.1.150
+yangwei_de pptpd 111111 172.18.1.151
+yulingjing_de pptpd 111111 172.18.1.152
+zhangchengwei_de pptpd 111111 172.18.1.153
+zhanglei_de pptpd 111111 172.18.1.154
+zhangpeng_de pptpd 111111 172.18.1.155
+jiamengdie_de pptpd 111111 172.18.1.156
+zhuyujia_de pptpd 111111 172.18.1.157
diff --git a/deploy/pptpd/pptpd_install/options.pptpd b/deploy/pptpd/pptpd_install/options.pptpd
new file mode 100644
index 0000000..738c10f
--- /dev/null
+++ b/deploy/pptpd/pptpd_install/options.pptpd
@@ -0,0 +1,134 @@
+###############################################################################
+# $Id: options.pptpd,v 1.11 2005/12/29 01:21:09 quozl Exp $
+#
+# Sample Poptop PPP options file /etc/ppp/options.pptpd
+# Options used by PPP when a connection arrives from a client.
+# This file is pointed to by /etc/pptpd.conf option keyword.
+# Changes are effective on the next connection. See "man pppd".
+#
+# You are expected to change this file to suit your system. As
+# packaged, it requires PPP 2.4.2 and the kernel MPPE module.
+###############################################################################
+
+
+# Authentication
+
+# Name of the local system for authentication purposes
+# (must match the second field in /etc/ppp/chap-secrets entries)
+name pptpd
+
+# Strip the domain prefix from the username before authentication.
+# (applies if you use pppd with chapms-strip-domain patch)
+#chapms-strip-domain
+
+
+# Encryption
+# (There have been multiple versions of PPP with encryption support,
+# choose with of the following sections you will use.)
+
+
+# BSD licensed ppp-2.4.2 upstream with MPPE only, kernel module ppp_mppe.o
+# {{{
+refuse-pap
+refuse-chap
+refuse-mschap
+# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft
+# Challenge Handshake Authentication Protocol, Version 2] authentication.
+require-mschap-v2
+# Require MPPE 128-bit encryption
+# (note that MPPE requires the use of MSCHAP-V2 during authentication)
+require-mppe-128
+# }}}
+
+
+# OpenSSL licensed ppp-2.4.1 fork with MPPE only, kernel module mppe.o
+# {{{
+#-chap
+#-chapms
+# Require the peer to authenticate itself using MS-CHAPv2 [Microsoft
+# Challenge Handshake Authentication Protocol, Version 2] authentication.
+#+chapms-v2
+# Require MPPE encryption
+# (note that MPPE requires the use of MSCHAP-V2 during authentication)
+#mppe-40 # enable either 40-bit or 128-bit, not both
+#mppe-128
+#mppe-stateless
+# }}}
+
+
+# Network and Routing
+
+# If pppd is acting as a server for Microsoft Windows clients, this
+# option allows pppd to supply one or two DNS (Domain Name Server)
+# addresses to the clients. The first instance of this option
+# specifies the primary DNS address; the second instance (if given)
+# specifies the secondary DNS address.
+#ms-dns 10.0.0.1
+#ms-dns 10.0.0.2
+ms-dns 8.8.8.8
+
+# If pppd is acting as a server for Microsoft Windows or "Samba"
+# clients, this option allows pppd to supply one or two WINS (Windows
+# Internet Name Services) server addresses to the clients. The first
+# instance of this option specifies the primary WINS address; the
+# second instance (if given) specifies the secondary WINS address.
+#ms-wins 10.0.0.3
+#ms-wins 10.0.0.4
+
+# Add an entry to this system's ARP [Address Resolution Protocol]
+# table with the IP address of the peer and the Ethernet address of this
+# system. This will have the effect of making the peer appear to other
+# systems to be on the local ethernet.
+# (you do not need this if your PPTP server is responsible for routing
+# packets to the clients -- James Cameron)
+proxyarp
+
+# Normally pptpd passes the IP address to pppd, but if pptpd has been
+# given the delegate option in pptpd.conf or the --delegate command line
+# option, then pppd will use chap-secrets or radius to allocate the
+# client IP address. The default local IP address used at the server
+# end is often the same as the address of the server. To override this,
+# specify the local IP address here.
+# (you must not use this unless you have used the delegate option)
+#10.8.0.100
+
+
+# Logging
+
+# Enable connection debugging facilities.
+# (see your syslog configuration for where pppd sends to)
+#debug
+
+# Print out all the option values which have been set.
+# (often requested by mailing list to verify options)
+#dump
+
+
+# Miscellaneous
+
+# Create a UUCP-style lock file for the pseudo-tty to ensure exclusive
+# access.
+lock
+
+# Disable BSD-Compress compression
+nobsdcomp
+
+# Disable Van Jacobson compression
+# (needed on some networks with Windows 9x/ME/XP clients, see posting to
+# poptop-server on 14th April 2005 by Pawel Pokrywka and followups,
+# http://marc.theaimsgroup.com/?t=111343175400006&r=1&w=2 )
+novj
+novjccomp
+
+# turn off logging to stderr, since this may be redirected to pptpd,
+# which may trigger a loopback
+nologfd
+
+# put plugins here
+# (putting them higher up may cause them to sent messages to the pty)
+
+mru 1380
+mtu 1380
+holdoff 10
+idle 60
+
diff --git a/deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm b/deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm
new file mode 100644
index 0000000..48c8946
--- /dev/null
+++ b/deploy/pptpd/pptpd_install/pptpd-1.4.0-2.el7.x86_64.rpm
Binary files differ
diff --git a/deploy/pptpd/pptpd_install/pptpd.conf b/deploy/pptpd/pptpd_install/pptpd.conf
new file mode 100644
index 0000000..6ebc63c
--- /dev/null
+++ b/deploy/pptpd/pptpd_install/pptpd.conf
@@ -0,0 +1,106 @@
+###############################################################################
+# $Id: pptpd.conf,v 1.11 2011/05/19 00:02:50 quozl Exp $
+#
+# Sample Poptop configuration file /etc/pptpd.conf
+#
+# Changes are effective when pptpd is restarted.
+###############################################################################
+
+# TAG: ppp
+# Path to the pppd program, default '/usr/sbin/pppd' on Linux
+#
+#ppp /usr/sbin/pppd
+
+# TAG: option
+# Specifies the location of the PPP options file.
+# By default PPP looks in '/etc/ppp/options'
+#
+option /etc/ppp/options.pptpd
+
+# TAG: debug
+# Turns on (more) debugging to syslog
+#
+#debug
+
+# TAG: stimeout
+# Specifies timeout (in seconds) on starting ctrl connection
+#
+# stimeout 10
+
+# TAG: noipparam
+# Suppress the passing of the client's IP address to PPP, which is
+# done by default otherwise.
+#
+#noipparam
+
+# TAG: logwtmp
+# Use wtmp(5) to record client connections and disconnections.
+#
+logwtmp
+
+# TAG: vrf <vrfname>
+# Switches PPTP & GRE sockets to the specified VRF, which must exist
+# Only available if VRF support was compiled into pptpd.
+#
+#vrf test
+
+# TAG: bcrelay <if>
+# Turns on broadcast relay to clients from interface <if>
+#
+#bcrelay eth1
+
+# TAG: delegate
+# Delegates the allocation of client IP addresses to pppd.
+#
+# Without this option, which is the default, pptpd manages the list of
+# IP addresses for clients and passes the next free address to pppd.
+# With this option, pptpd does not pass an address, and so pppd may use
+# radius or chap-secrets to allocate an address.
+#
+#delegate
+
+# TAG: connections
+# Limits the number of client connections that may be accepted.
+#
+# If pptpd is allocating IP addresses (e.g. delegate is not
+# used) then the number of connections is also limited by the
+# remoteip option. The default is 100.
+#connections 100
+
+# TAG: localip
+# TAG: remoteip
+# Specifies the local and remote IP address ranges.
+#
+# These options are ignored if delegate option is set.
+#
+# Any addresses work as long as the local machine takes care of the
+# routing. But if you want to use MS-Windows networking, you should
+# use IP addresses out of the LAN address space and use the proxyarp
+# option in the pppd options file, or run bcrelay.
+#
+# You can specify single IP addresses seperated by commas or you can
+# specify ranges, or both. For example:
+#
+# 192.168.0.234,192.168.0.245-249,192.168.0.254
+#
+# IMPORTANT RESTRICTIONS:
+#
+# 1. No spaces are permitted between commas or within addresses.
+#
+# 2. If you give more IP addresses than the value of connections,
+# it will start at the beginning of the list and go until it
+# gets connections IPs. Others will be ignored.
+#
+# 3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
+# you must type 234-238 if you mean this.
+#
+# 4. If you give a single localIP, that's ok - all local IPs will
+# be set to the given one. You MUST still give at least one remote
+# IP for each simultaneous client.
+#
+# (Recommended)
+localip 172.18.1.254
+#remoteip 192.168.0.234-238,192.168.0.245
+# or
+#localip 192.168.0.234-238,192.168.0.245
+remoteip 172.18.1.100-200
diff --git a/deploy/pptpd/pptpd_install/pptpd.install.sh b/deploy/pptpd/pptpd_install/pptpd.install.sh
new file mode 100644
index 0000000..365939c
--- /dev/null
+++ b/deploy/pptpd/pptpd_install/pptpd.install.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+rpm -ivh ./pptpd-1.4.0-2.el7.x86_64.rpm
+
+cp pptpd.conf /etc
+cp options.pptpd /etc/ppp/
+cp chap-secrets /etc/ppp/
+cp auth-down /etc/ppp
+cp auth-up /etc/ppp
+
+service pptpd restart
+
+
+
+
+
+
diff --git a/deploy/problem b/deploy/problem
new file mode 100644
index 0000000..0132ad8
--- /dev/null
+++ b/deploy/problem
@@ -0,0 +1,2 @@
+1-YiZhuang NAT use PNAT, modiyf source port per link;
+2-maybe the WIFI don't allow GRE packet, so PPTP can't established!
diff --git a/deploy/user_pass b/deploy/user_pass
new file mode 100644
index 0000000..83796f8
--- /dev/null
+++ b/deploy/user_pass
@@ -0,0 +1,8 @@
+Ali_IP:47.91.74.214:22
+user: mesa
+pass:mesalab2018@AV
+
+
+Ali_IP: 47.75.205.197
+user: root
+pass: MESA@LiJia#20170808
diff --git a/inc/flowood.h b/inc/flowood.h
new file mode 100644
index 0000000..74f77c4
--- /dev/null
+++ b/inc/flowood.h
@@ -0,0 +1,491 @@
+#ifndef _FLOWOOD_H_
+#define _FLOWOOD_H_ 1
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <netinet/ip6.h>
+#include "MESA_htable.h"
+#include "MESA_list_queue.h"
+#include "MESA_atomic.h"
+#include "MESA_handle_logger.h"
+#include "MESA_prof_load.h"
+#include "MESA_list_count.h"
+#include "MESA_list.h"
+#include "stream.h"
+
+
+#define FLWD_RUN_AS_SAPP_PLUG (1) /* ת��������sapp�IJ����ʽ���� */
+#define FLWD_NO_ACTIVE_IP_DISCOVER (0) /* û�л�ԾIP������ϵͳ������, �ֹ�ָ��һЩ����ip, �Բ��� */
+#define FLWD_NO_GDEV_ENV (0) /* û��GDEV�Ļ�����, ת������ģ��·��ģʽ, ��͸��ת����, ��ʵ��Ҫ���ڲ��Խ������ع��� */
+#define FLWD_NO_ACTIVE_ARP_QUERY (0) /* û������ARP��ѯ�������, ����Э��ջģ��, ��raw_socket, marsioԭʼ�ӿ�, Ҫ�ֶ�ָ��MAC��ַ */
+#define FLWD_NO_MAAT (0)
+#define FLWD_SUPPORT_DNAT (0) /* DNAT�Ȳ�ʵ��! */
+#define FLWD_ASYNC_LOCK_FREE (0) /* �첽����ģʽ���̸߳��� */
+#define FLWD_IP_REGION_BY_LIB (0) /* 1:IP�ĵ���λ����Ϣ��������IP��ַ���ѯ�õ�; 0:IP����λ����Ϣ�����ֹ����úͶ�̬����ϵͳ, ����˵ɶ����ɶ */
+#define FLWD_USE_LTSM_FOR_QUICK_CLOSE (0) /* ʹ��LTSM������ǿ���ʱ��̭, �Ծ������TCP����, �Ի��տ��ö˿� */
+
+#define FLWD_NAT_SPORT_VOLATILE (0) /* access����NAT�ڲ�ʱ, ����Դ�˿ڻ�仯, ����access����Դ�˿�Ҳ����, ��ʱ��ҪforwardҲ��¼�յ���ʱ��Դ�˿�, ������޷����� */
+
+#define FLWD_RUN_IN_CEIEC_TEST (1) /* ��ceiec���Ի�����ʱд���IJ��� */
+
+#define FLWD_USE_SPORT_HASH_AS_MARK (1) /* ʹ��Դ�˿ڵ�ijЩbitλ, ���ڱ�ʶacc-gateway, hashֵ, fwd-gateway����ȷ���ش�����̨acc-gateway */
+/*
+ ������ʹ��������ʱ��bit�ֲ�λ:
+ |15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+ |accid| hash | sport |
+
+ ���2bit ��������id;
+ �м�6bit HASHֵ;
+ ���8bit �����Ŀ��ö˿�;
+*/
+#if FLWD_USE_SPORT_HASH_AS_MARK
+#define FLWD_SPORT_ACC_ID_MASK (0xC000) /* ������, acc-gateway ID, ���λ����bit, ͬһ�ֵ�֧��4̨acc-gateway�豸 */
+#define FLWD_SPORT_ACC_ID_SHIFT_NUM (14) /* MASK�ƶ�14λ, ���������, ��ǰ�ֵ�ID */
+
+#define FLWD_UDP_SPORT_HASH_MASK (0x3F00) /* ������, hashֵ,���ڸ���ʵ��������, 6bit, ��Ԫ���ͻʶ��׼ȷ��: 98.4%, ���Ǹ��ÿͻ��˺���ʵ�ͻ���ͬʱ����һ����������ʶ���� */
+#define FLWD_UDP_SPORT_ACTUAL_PORT_MASK (0x00FF) /* ������, ��ʵ���ö˿ڵ�ֵ, 8bit. ��ʵҲ��������10bit, �ټ���acc-gateway id */
+#define FLWD_TCP_SPORT_ACTUAL_PORT_MASK (FLWD_UDP_SPORT_ACTUAL_PORT_MASK) /* TODO, �Ժ����, TCP�ɲ�ʹ�ö˿�HASH��Ϊ����, ��ISN���±�������,���ӿ��ö˿ڷ�Χ */
+#else
+
+#endif
+
+
+#define FLWD_LINK_MTU (2048)
+#define FLWD_MAX_THREAD_NUM (64)
+#define FLWD_REGION_STR_LEN_MAX (32) /* ��������ֵ */
+#define FLWD_NETWORK_NxM_MAX (16) /* GDEV��ת������֮�� NxM �������豸���ֵ */
+
+#define TRAFFIC_STAT_STR_LEN (32)
+
+#define FLWD_CONFIG_FILE "./conf/ip_reuse/flowood.conf"
+
+#define FLWD_MACRO_TO_STRING(x) (#x)
+
+
+/* �����֧ѡ���Ż�, ��������еķ�֧�ж�, ʹ��flwd_likely()���� */
+#ifndef flwd_likely
+#define flwd_likely(x) __builtin_expect(!!(x), 1)
+#endif
+
+#ifndef flwd_unlikely
+#define flwd_unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+
+typedef enum{
+ FLWD_DROP = 0,
+ FLWD_PASS = 1,
+}flwd_pkt_action_t;
+
+
+/* ��ֵ�����ÿ����Ҫ��Ӧ, ��ֹ�����޸� */
+typedef enum {
+ FLWD_NAT_TYPE_SNAT = 1,
+ FLWD_NAT_TYPE_DNAT = 2,
+}flwd_nat_type_t;
+
+
+typedef enum {
+ FLWD_IP_REGION_INLAND = 0, /* ����, �˶���Ҫ��pangu���ݿ������һ��!!! */
+ FLWD_IP_REGION_OUTLAND = 1, /* ����, �˶���Ҫ��pangu���ݿ������һ��!!! */
+ FLWD_IP_REGION_MAX = 2,
+}flwd_ip_region_type_t;
+
+
+typedef enum {
+ FLWD_ACT_IP_DYNAMIC = 1, /* �Զ����ֵĶ�̬��ԾIP */
+ FLWD_ACT_IP_STATIC = 2, /* �û�ͨ�������·��ľ�̬IP��ַ�� */
+}flwd_active_ip_type_t;
+
+/* NOTE: Ϊ�˳�����ʹ�������±�����v4, v6, �˴�������4,6�������õ�������ʵ��ֵ */
+typedef enum{
+ FLWD_IP_ADDR_TYPE_V4 = 0,
+ FLWD_IP_ADDR_TYPE_V6 = 1,
+}flwd_ip_addr_type_t;
+
+
+typedef enum{
+ FLWD_MAAT_SRC_JSON = 1,
+ FLWD_MAAT_SRC_LOCAL_FILE = 2,
+ FLWD_MAAT_SRC_REDIS = 3,
+}flwd_maat_cfg_source_t;
+
+
+typedef struct{
+ unsigned char addr_type;
+ unsigned char addr_len;
+ unsigned short dport; /* NOTE: ��������ṹҲ������, �˴��Ŀ�϶����һ��port����, ������DNAT */
+ union{
+ unsigned int addr_ipv4;
+ struct in6_addr addr_ipv6;
+ unsigned char addr_value[16];
+ };
+}flwd_ip_t;
+
+
+typedef struct{
+ unsigned int sip_net_order;
+ unsigned int dip_net_order;
+}flwd_ippair_v4_t;
+
+typedef struct{
+ struct in6_addr sip_net_order;
+ struct in6_addr dip_net_order;
+}flwd_ippair_v6_t;
+
+
+typedef struct{
+ unsigned char addr_type; /* flwd_ip_addr_type_t, ÿ����Ԫ��ʹ�ö����ĵ�ַ����, Ԥ��v4_over_v6, v6_over_v4�ĵ�ַת������ */
+ unsigned char protocol; /* TCP��UDP��Ԫ����Ҫ����, ����Э���ֶ�, ʵ����5Ԫ�� */
+ unsigned char dir_reverse; /* natת��֮ǰ��key��Ԫ����ʵ����, �Ƿ���ݴ��ַ��ΪԴ��HASH�淶, ���˵�ַ��ת, ��: TCP_SYN��, �����ֵΪ1, ˵��key->dip����������SYN�����ͷ�, д��־ʱ����ע�� */
+ unsigned char __pad; /* �ֽڶ��� */
+ unsigned short sport_net_order;
+ unsigned short dport_net_order;
+ union{
+ flwd_ippair_v6_t *ippair_v6; /* �˴�ʹ��ָ��, ��IPv6��ַ̫��, V6������Խ���, �˽ṹ���ɺ�flwd_ippair_v4_tһ����, union���Խ�Լ�ڴ�. ע��free!! */
+ flwd_ippair_v4_t ippair_v4;
+ };
+}flwd_tuple5_t; /* NAT��Ԫ�� */
+
+
+/* ��ʵ������IP�Ͷ˿� */
+typedef struct{
+ unsigned int actual_server_ip_net_order;
+ unsigned short actual_server_port_net_order;
+}flwd_actual_ip_port_t;
+
+
+
+/* ���ݰ���Դ, �������� or ת������,
+ ���н���������ת������֮��, Ԥ������socketͨ��ģʽ, ��Ϊ�������̿��Բ�����һ̨����
+*/
+typedef enum {
+ TOPO_ACC_LINK_USER = 0, /* ��������--�û��ն� */
+ TOPO_ACC_LINK_FWD = 1, /* ��������--ת������ */
+ TOPO_FWD_LINK_ACC = 2, /* ת������--�������� */
+ TOPO_FWD_LINK_GDEV = 3, /* ת������--ר���豸 */
+ __TOPO_MODE_MAX = 4,
+}flwd_topology_t;
+
+/* �û������ն�Э������ */
+typedef enum {
+ FLWD_TERMINAL_IP_LAYER,
+ FLWD_TERMINAL_IP_L2TP,
+ FLWD_TERMINAL_IP_PPTP,
+}flwd_terminal_proto_t;
+
+typedef enum {
+ CAP_MODEL_PAG = 0,
+ CAP_MODEL_PCAP_ONLINE = 1,
+ CAP_MODEL_SOCKET = 2, /* ����ƽ̨������, ��Ϊflowoodϵͳ�϶������ö���ģʽ, ��������ʵʱ��������, ��dumpfile��Ϊsocketģʽ */
+ CAP_MODEL_PFRING = 3,
+ CAP_MODEL_DPDK = 4,
+ CAP_MODEL_PPF = 5,
+ CAP_MODEL_NPACKET = 6,
+ CAP_MODEL_QNF = 7, /* for ��߿Ƽ�Zhuanyong���� */
+ CAP_MODEL_N95 = 8, /* to do: for xx9 UDP�½ӿ� */
+ CAP_MODEL_PCAP_DUMPLIST = 9, /* 2014-11-19 lijia add */
+ CAP_MODEL_TOPSEC = 10, /* 2015-09-29 lijia add, for trojan detect */
+ CAP_MODEL_IPFILE = 11,
+ CAP_MODEL_MARSIOV4 = 12, /* 2016-10-26 lijia add, for DPDK-marsio-V4.0 */
+ CAP_MODEL_AGENT_SMITH = 13, /* 2016-10-27 lijia add, for ��Դ���빲���ڴ� */
+ CAP_MODEL_DPDK_VXLAN = 14, /* 2016-11-01 lijia add, for DPDK-3.0, vxlan������� */
+ CAP_MODEL_MARSIOV4_VXLAN= 15, /* 2016-11-01 lijia add, for MARSIO-4.0, vxlan������� */
+ CAP_MODEL_PAG_MARSIO = 16, /* 2017-04-07 lijia add, for marsio compat pag */
+ __CAP_MODEL_MAX = 17,
+}flwd_cap_mode_t;
+
+
+typedef enum{
+ FLWD_OUTOPT_FIRST_PKT = 0x1, /* һ�������װ�, ��Ҫ����ָ������, accessͨ��vxlan�����ֶθ�֮fwd�˰����װ�, fwdҪ����session�� */
+
+}flwd_output_opt_t;
+
+
+typedef struct{
+ void *low_level_mbuff; /* �ײ�IO����ذ��ṹ, ��: struct pfring_pkthdr, marsio_buff_t */
+ char *inner_pkt_data; /* �ڲ�MAC�㿪ʼ�����ݲ��� */
+ char *outer_pkt_data; /* ���MAC�㿪ʼ�����ݲ��� */
+ int inner_pkt_len; /* �ڲ�MACͷ��ʼ�����ݳ��� */
+ int outer_pkt_len; /* ���MACͷ��ʼ�����ݳ��� */
+ flwd_terminal_proto_t terminal_proto;
+ const char *inner_ip_layer_hdr; /* Vxlan(����)�ڲ�IP��ͷ��ʼ��ַ, v4 or v6 */
+}flwd_raw_pkt_t;
+
+typedef struct{
+ const char *device_name;
+ const char *pkt_filter; /* ����ijЩ������֧�� */
+ flwd_cap_mode_t cap_mode;
+ flwd_topology_t topo_mode;
+ unsigned int device_ip_net_order; /* �����豸IP��ַ */
+ unsigned int device_ip_mask_net_order; /* �����豸IP���� */
+ unsigned int gateway_ip_net_order; /* Ĭ������IP��ַ */
+// unsigned int *device_slave_ip_net_order; /* ������˫IPģʽ, ������������������, ����ģʽ����һ��������, ͬʱ����ת�����غͽ����ն˵Ļ�����, ����ͬIP���������� */
+// unsigned char device_slave_ip_num; /* ��Ҫ����DNAT�Ľ������غ���ʵ������ͨ��, ���ֻ��һ��IP, ��󲢷�������ֻ��65411��, ����ʹ�ö������ip��ַ, ���ܱ�֤�߲����� */
+ unsigned short socket_port_net_order; /* lo���ػػ�socketͨ�Ŷ˿�ģʽ */
+ unsigned char local_mac_addr[6];
+}flwd_io_para_t;
+
+typedef struct __flwd_device_handle{
+ int tot_thread_count;
+ int sapp_send_thread_seq; /* �Բ����ʽ���ص�sappʱ, �ǰ������̵߳ķ����߳�ID */
+ flwd_io_para_t io_para; /* ������������, ������, ����ģʽ, �ӿ�IP,MAC��ַ�ȵ� */
+ void *low_level_io_handle;
+ int (*low_level_io_init)(struct __flwd_device_handle *h);
+ void (*low_level_io_run)(struct __flwd_device_handle *h);
+ int (*low_level_pkt_recv)(struct __flwd_device_handle *h, int tid, void **mbuff);
+ void (*low_level_pkt_free)(struct __flwd_device_handle *h, int tid, void *mbuff);
+ void *(* low_level_mbuff_malloc)(struct __flwd_device_handle *h, int tid, int len);
+ void (* low_level_mbuff_free)(struct __flwd_device_handle *h, int tid, void *mbuff);
+ void (* low_level_mbuff_free_after_send)(struct __flwd_device_handle *h, int tid, void *mbuff); /* ��marsioģʽ���ͺ��Զ�free, ijЩ���ֲ��Զ�free, ������ôһ�������ӿ� */
+ void (* low_level_mbuff_send_back)(struct __flwd_device_handle *h, int tid, void *mbuff); /* GDEVģʽ��, fwd���ػ�ע���ݰ� */
+ char * (* low_level_mbuff_mtod)(void *mbuff);
+ char * (*low_level_mbuff_data_append)(void *mbuff, const char *user_data, int user_data_len);
+ char * (*low_level_mbuff_data_forward)(void *mbuff, int n); /* ����ָ����ǰ�ƶ�N���ֽ�, ���ݳ����Զ�����N */
+ char * (*low_level_mbuff_data_rearward)(void *mbuff, int n); /* ����ָ������ƶ�N���ֽ�, ���ݳ����Զ�����N */
+ int (*low_level_mbuff_get_pkt_len)(void *mbuff);
+ void (*low_level_mbuff_set_pkt_len)(void *mbuff, int pkt_len);
+ int (*low_level_send)(struct __flwd_device_handle *h, int tid, void *mbuff); /* ����֮ǰ����low_level_mbuff_malloc(), ��������Զ�free, ������������low_level_mbuff_free() */
+}flwd_device_handle_t;
+
+
+/* Ϊ���������, �ڲ�Ϊÿ�������, ��maat���ص�table_id��ͬ */
+typedef enum{
+ FLWD_MAAT_TB_IR_POLICY_COMPILE = 0,
+ FLWD_MAAT_TB_IR_POLICY_GROUP,
+ FLWD_MAAT_TB_IR_POLICY_IP,
+ FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB, /* �û��˹�����IP */
+ FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB, /* �Զ�����IP */
+ FLWD_MAAT_TB_IR_DYN_CONN_IP, /* ��ɢIP���õ���Ԫ��, ��֮������ϵͳ, ����ϵͳ�ڳ�ͻ���� */
+ FLWD_MAAT_TB_MAX,
+}flwd_inner_maat_table_id_t;
+
+typedef struct{
+ const char *table_name;
+ int table_id;
+}flwd_maat_table_info_t;
+
+typedef struct{
+ void *flwd_log_handle; /* MESA-handle_logger��־��� */
+ void *maat_log_handle;
+ void *maat_static_handle; /* redis�������÷���, maatҲҪ��ʼ��������ͬ��� */
+ void *maat_dynamic_handle; /* redis�������÷���, maatҲҪ��ʼ��������ͬ��� */
+ void *flwd_network_conn_table; /* gdev��forward����֮��Ļ�����ϵ */
+ void *flwd_arp_table; /* ARP HASH��, ip��Ϊkey, mac_addrΪdata */
+ pthread_rwlock_t flwd_arp_htable_rwlock; /* arp��Ҫ��̬����, ��htableֻ�л�����, ����󲿷����Ƕ�����, ��Ҫ��д��, ����߶��߳����� */
+ time_t cur_time;
+ struct in6_addr zero_ipv6_addr; /* ��ʾȫ0��IPv6��ַ */
+ unsigned char zero_mac_addr[6]; /* ��ʾȫ0��MAC��ַ */
+ unsigned long long cur_time_usec; /* ��1970-01-01 ��ʼ����ǰʱ��ľ���΢���� */
+ flwd_device_handle_t global_io_handle[__TOPO_MODE_MAX];
+ flwd_maat_table_info_t maat_table_info[FLWD_MAAT_TB_MAX];
+}flwd_global_val_t; /* ȫ�ֱ��� */
+
+
+typedef struct{
+ unsigned long long eth_pkt_num;
+ unsigned long long ip_pkt_num;
+ unsigned long long tcp_pkt_num;
+ unsigned long long udp_pkt_num;
+
+ unsigned long long eth_pkt_byte;
+ unsigned long long ip_pkt_byte;
+ unsigned long long tcp_pkt_byte;
+ unsigned long long udp_pkt_byte;
+
+}flwd_pkt_stat_t; /* ���ݰ�����ͳ����Ϣ */
+
+
+/* Դ��Ŀ�ķ����Ե�ǰ����Ϊ׼ */
+struct __flwd_tuple4{
+ unsigned char addr_type; /* �ѵ�ַ���ͷ�ֹ�ṹ����ǰ, ����v4, v6����ʶ�� */
+ unsigned char protocol; /* TCP��UDP��Ԫ����Ҫ����, ����Э���ֶ� */
+ unsigned short sport_net_order;
+ unsigned short dport_net_order;
+ unsigned int sip_net_order;
+ unsigned int dip_net_order;
+}__attribute__((packed));
+typedef struct __flwd_tuple4 flwd_tuple4v4_t;
+
+/* Դ��Ŀ�ķ����Ե�ǰ����Ϊ׼ */
+struct __flwd_tuple6{
+ unsigned char addr_type; /* �ѵ�ַ���ͷ�ֹ�ṹ����ǰ, ����v4, v6����ʶ�� */
+ unsigned char protocol; /* TCP��UDP��Ԫ����Ҫ����, ����Э���ֶ� */
+ unsigned short sport_net_order;
+ unsigned short dport_net_order;
+ struct in6_addr sip_net_order;
+ struct in6_addr dip_net_order;
+}__attribute__((packed));
+typedef struct __flwd_tuple6 flwd_tuple4v6_t;
+
+
+typedef struct{
+ unsigned int gdev_ip_net_order; /* ��¼�����������IP��GDEV IP, ʵ�ʾ��DZ�ҵ���loopback ip, ����region_id, dev_idͨ������õ� */
+ unsigned char region_id; /* ���ڱ�� */
+ unsigned char dev_id; /* �豸��� */
+ unsigned char link_id; /* ��ǰIP������ʱ����·�� */
+ unsigned char this_ip_as_sip_route_dir; /* �˻�ԾIP��ΪԴIPʱ, ��INLINE�豸�ķ���λ, һ��Ҫ��TCP��SYN�����ӵ�����, udp���ܻύ��sip��dip, ��Ϊ������ΪԴ��ַ, ͨ����ֵ����� */
+ unsigned char inner_raw_smac[6];
+ unsigned char inner_raw_dmac[6];
+}flwd_gdev_associated_args_t;
+
+
+/* �洢��ת�������еĵײ�·����Ϣ, ����ÿ�ζ���̬��·�ɱ�, ARP��, �ÿռ任ʱ��!!!
+ SNAT:
+ access����:
+ ���տͻ������ݰ�, ��¼�ͻ���ԴMAC;
+ ����ѡ��Ļ�ԾIP����λ��, ��̬��ѯ��һ��fwd����, ��¼fwd_ip, fwd_mac;
+
+ fwd����:
+ ��������access�İ�, ����hash��, ��¼access_ip, access_mac;
+ ���յ�����gdev�Ļظ���, ֱ��ȡ��nat_info�е�access_ip, access_mac, ֱ��ת��(�������Ĵ��Ļ�ȥ).
+
+ DNAT:
+ fwd����:
+ ���յ�����gdev���װ�, ��̬��ѯdip������̨access���ؿ��Ե���, ��¼access_ip, access_mac;
+
+ access����:
+ ���յ�����fwd���װ�, ��¼fwd_ip, fwd_mac, ���յ���ʵ������Ӧ��ʱ, ȡ���洢��ip,macֱ��ת��(�������Ĵ��Ļ�ȥ).
+*/
+typedef struct{
+ flwd_gdev_associated_args_t gdev_args;
+ unsigned char inner_terminal_mac[6]; /* ��Ҫ����access_gateway, �ͻ��˻���ʵ��������MAC, SNAT��Ӧ������ò�ARP��; DNAT���װ���Ҫ��ѯARP��һ�� */
+ unsigned int next_gateway_ip_net; /* ��Ҫ����access_gateway��fwd_gateway, ��һ�����ص�IP, ʵ�ʾ���vxlan���IP��ַ, ������v4,v6, �϶�����IPv4��ַ */
+ unsigned char next_gateway_mac[6]; /* ��Ҫ����access_gateway��fwd_gateway, ��һ�����ص�MAC */
+}flwd_route_info_t;
+
+
+typedef struct{
+ unsigned char tid; /* ��Ҫ����htable�ص������ڲ���tid�������� */
+ unsigned char reference; /* �˽ṹ��htable�б�������ͬ��key����, �������ü���, ��ֹdouble free */
+ unsigned char act_ip_region; /* flwd_ip_region_type_t, ��¼��ԾIP���ڵ���λ��, �����ӽ�����, ���ն˿�ʱʹ�� */
+ unsigned char act_ip_origin; /* flwd_active_ip_type_t, ��̬���� or �û��������� */
+ flwd_nat_type_t nat_type;
+ flwd_tuple5_t inner_nat_tuple5; /* ����SNAT, ���Ǿ������ڲ���ʵ�ͻ��˵İ�; */
+ flwd_tuple5_t outer_nat_tuple5; /* ����SNAT, ���dz�����, Internet�ϵİ�; */
+ signed long long signature_param; /* ���ݰ�ָ��Э������ض�����, ����TCP��˵, ��SYN-ISNƫ����; ����DNS��˵, ��transidƫ����; ��ֵ��after-nat�IJ���תΪ64bit long long �ͼ�ȥԭʼpre-nat(64bit)��IJ���֮�� */
+ flwd_route_info_t flwd_route_info;
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ void *ltsm_stat_handle;
+#endif
+}flwd_nat_info_t;
+
+
+typedef struct{
+ unsigned char tid; /* ��Ҫ����htable�ص������ڲ���tid�������� */
+ flwd_route_info_t flwd_route_info;
+}flwd_fwd_nat_info_t;
+
+
+typedef struct{
+ flwd_pkt_stat_t pkt_stat;
+ /* IP��ַ��htable */
+ void *flwd_ip_pool_dynamic_htable[2][2]; /* ʹ��һ����ά����, ����ά�ȷֱ���: [v4_or_v6][inland_or_outland], ��dynamic��static�洢��key��һ��, �ֿ��������� */
+ void *flwd_ip_pool_static_htable[2][2]; /* ʹ��һ����ά����, ����ά�ȷֱ���: [v4_or_v6][inland_or_outland], ��dynamic��static�洢��key��һ��, �ֿ��������� */
+ pthread_rwlock_t flwd_ip_pool_dynamic_rwlock;
+ pthread_rwlock_t flwd_ip_pool_static_rwlock;
+ void *nat_info_table; /* access��fwd���ظ���ͬһ������, TCP��UDPͬ��һ��htable, protocolҲ��Ϊkey��һ���� */
+ flwd_ippair_v6_t nat_key_ipv6_buf; /* ���캯��ջ�ڵ�nat_keyʱ, ��flwd_tuple5_t��ipv6��ַ������ָ��, ����ÿ�ζ�̬malloc/free, �˴�Ϊÿ���̷߳���һ����ʱ��ipv6��ַ������ */
+ struct stream_tuple4_v4 addrv4_convert_buf; /* flwd_tuple5_to_stream_addr()�����õ��ڴ滺���� */
+ struct stream_tuple4_v6 addrv6_convert_buf; /* flwd_tuple5_to_stream_addr()�����õ��ڴ滺���� */
+ char __pad[56];
+}flwd_global_thread_t; /* ���߳�ȫ�ֱ���, ע��64�ֽڻ������ */
+
+
+
+typedef struct{
+ int tot_thread_count;
+ int flwd_log_level;
+ int nat_htable_max_num;
+ int nat_htable_timeout;
+ int global_access_gateway_num; /* ȫ��һ���ж��ٸ���������, ��������ʹ�û�ԾIP��Դ�˿� */
+ int current_access_gateway_id; /* ��ǰ�������ص�ΨһID, ��1��ʼ */
+ int use_static_pool_ip_if_no_dynamic; /* ������, �����ǰû�п��ö�̬IP, ��Ӿ�̬���������ѡһ�� */
+ int use_dynamic_pool_ip_if_no_static; /* ������, ��������˲���, ����static_pool��ǰû�п���IP, ��Ӷ�̬�������ѡһ�� */
+ const char *maat_json_cfg_file;
+ const char* table_info_path; /* maat_cfg */
+ const char* full_cfg_dir; /* maat_cfg */
+ const char* inc_cfg_dir; /* maat_cfg */
+}flwd_global_cfg_t; /* ȫ�������ļ����� */
+
+
+typedef struct{
+ flwd_topology_t topo_mode;
+ const char *cfg_file_section;
+ char addr_para[64];
+}flwd_packet_io_cfg_para_t;
+
+
+
+typedef struct {
+ unsigned char is_valid;
+ unsigned int policy_group_id; /* ��̬IPΪ0 */
+ flwd_ip_region_type_t ip_region_type; /* ���ڡ����� */
+ flwd_active_ip_type_t ip_origin_type; /* ��̬, ��̬ */
+ flwd_ip_t active_ip_net_order;
+ flwd_gdev_associated_args_t gdev_args;
+ MESA_list_t active_ip_list_node; /* ��̬IP��group_idΪkey, ��ͬ��group_id��IPʹ����������; Ϊ�˷��㴦��, quiddityָ�򱾽ṹ��ͷ��, ʹ��get_entry_of̫�鷳; headͷ�ڵ������� */
+ MESA_list_count_t usable_tcp_sport_list_head; /* TCP���ö˿�����, ��ʼ��ʱ, ����ȫ�������ö˿�, ����һ���ʹ��������Ƴ�һ��, ���ӽ����ͷ�ʱ, �ٲ�������, ʹ��MESA_list_count_t, ���ڼ��� */
+ MESA_list_count_t usable_udp_sport_list_head; /* UDP���ö˿�����, ��ʼ��ʱ, ����ȫ�������ö˿�, ����һ���ʹ��������Ƴ�һ��, ���ӽ����ͷ�ʱ, �ٲ�������, ʹ��MESA_list_count_t, ���ڼ��� */
+}flwd_active_ip_t;
+
+
+
+/* ѡ���ԾIP��ͬʱ, ���ݵ�ǰIP�����м�¼, ͬʱѡ��һ������Դ�˿� */
+typedef struct{
+ int tid;
+ flwd_ip_region_type_t dip_region_type; /* ��ǰ��Ԫ����ʵĿ��IP���ڵ���λ�� */
+ flwd_tuple5_t *nat_key; /* ԭʼ����Ԫ����Ϣ, ����SNAT����inner_tuple5, ����DNAT����outer_tuple5 */
+ flwd_ip_t act_sip_net_order; /* ���õĻ�ԾIP��ַ */
+ flwd_gdev_associated_args_t gdev_args;
+ unsigned short act_sport_net_order;
+ unsigned char protocol; /* ��ֵ������htable�ص��������ݲ�����, ����ʱ���������� */
+}flwd_active_ip_port_args_t;
+
+
+
+
+/* ��Ϊ��ԾIP��MAAT�ص���, �����Ƕ����ڰ������߳�, Ϊ�˲���ͬһ��htable��������, ʹ��һ��Сtrick:
+
+
+ op_flag�������bit����:
+ 0λ:
+ 0:callback�߳��Ѿ�������, �������߳̿��Զ�ȡ�����뱾�̵߳�htable;
+ 1:�������߳��Ѿ�������, ��ʱΪNULL, callback�߳̿��Լ�������������.
+ 1λ:
+ 1:���������߳�ռ��;
+ 0:�������߳��ͷ�;
+ 2λ:
+ 1:��callback�߳�ռ��;
+ 0:callback�߳��ͷ�;
+
+ ��1bit ��0bit ��0bit
+ --------|--------|--------|
+ cb proc valid
+
+ �յ����º�, �����ݿ��ת����flwd_active_ip_t�����Ƹ�ʽ, ���ݲ�ͬ���߳����ò�ͬ�Ķ˿�,
+ Ȼ�����ÿ���̵߳�flwd_temp_active_ip_op_flag=1,
+*/
+
+//#define FLWD_ACT_IP_OP_MASK_DATA_VALID (0x1)
+#define FLWD_ACT_IP_OP_OR_MASK_BY_PROC (0x1) /* ���ӱ��λ */
+#define FLWD_ACT_IP_OP_OR_MASK_BY_CALLBACK (0x2) /* ���ӱ��λ */
+
+#define FLWD_ACT_IP_OP_AND_MASK_BY_PROC (0xFFFE) /* ��ձ��λ */
+#define FLWD_ACT_IP_OP_AND_MASK_BY_CALLBACK (0xFFFD) /* ��ձ��λ */
+
+
+
+extern flwd_global_cfg_t flwd_cfg_val;
+extern flwd_global_val_t flwd_global_val;
+extern flwd_global_thread_t flwd_thread_val[FLWD_MAX_THREAD_NUM];
+extern const flwd_packet_io_cfg_para_t g_packet_io_cfg_para[__TOPO_MODE_MAX];
+extern MESA_ATOMIC_T flwd_temp_active_ip_op_flag[FLWD_MAX_THREAD_NUM];
+extern MESA_lqueue_head flwd_temp_active_ip_to_deal[FLWD_MAX_THREAD_NUM];
+
+#define flwd_log(level, fmt, args...) do{ if(level >= flwd_cfg_val.flwd_log_level){MESA_handle_runtime_log(flwd_global_val.flwd_log_handle, level, "flowood", fmt, ##args);}}while(0)
+
+#endif
+
+
diff --git a/inc/flowood_fun.h b/inc/flowood_fun.h
new file mode 100644
index 0000000..ec66a73
--- /dev/null
+++ b/inc/flowood_fun.h
@@ -0,0 +1,92 @@
+#ifndef _FLOWOOD_FUN_H_
+#define _FLOWOOD_FUN_H_ 1
+#include <stdint.h>
+#include <sys/types.h>
+#include "flowood.h"
+#include "flwd_net.h"
+
+int flwd_gateway_init(void);
+int flwd_packet_io_init(flwd_topology_t first_top_mode, flwd_topology_t second_top_mode);
+int flwd_access_maat_init(void);
+void flwd_packet_io_run(void);
+int flwd_access_ip_layer_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt);
+int flwd_rubbish_pkt_identify(flwd_device_handle_t *device_handle, flwd_raw_pkt_t *raw_pkt, int check_dip);
+void *flwd_stat_thread(void *arg);
+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);
+int flwd_sendpacket_build_ethernet(u_int16_t eth_type_host_order, const unsigned char *src_mac, const unsigned char *dst_mac, char *buf);
+int flwd_sendpacket_build_icmpv4_echo(u_int8_t type, u_int8_t code, u_int16_t sum,
+ u_int16_t id, u_int16_t seq, char *payload, u_int32_t payload_s, char *buf);
+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);
+
+int flwd_sendpacket_do_checksum(char *ip_buf, int protocol, int len);
+int flwd_sendpacket_build_arp(u_short hrd_net, u_short pro_net, u_char hln, u_char pln, u_short op_net,
+ u_char *sha, u_char *spa, u_char *tha, u_char *tpa, char *buf);
+int flwd_packet_io_low_level_init(flwd_device_handle_t *g_io_handle);
+void *flwd_packet_io_work_thread(void *arg);
+int flwd_access_kernal_pkt_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt);
+int flwd_protocol_stack_process(flwd_device_handle_t *io_handle, int tid, flwd_raw_pkt_t *raw_pkt);
+int flwd_access_l2tp_layer_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt);
+const char *flwd_tuple5_ntop(int tid, const flwd_tuple5_t *tuple5);
+const char *flwd_tuple5_ntop_r(const flwd_tuple5_t *tuple5, char *str_mbuf, int mbuf_len);
+const char *flwd_ipt_ntop_r(const flwd_ip_t *ipbin, char *str_mbuf, int mbuf_len);
+int flwd_idle_call(int tid);
+int flwd_access_active_ip_init(void);
+flwd_ip_region_type_t flwd_dstip_location(const flwd_tuple5_t *tuple5);
+int flwd_pkt_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt);
+void *flwd_malloc(int tid, size_t size);
+void flwd_free(int tid, void *ptr);
+void *flwd_calloc(int tid, size_t nmemb, size_t size);
+unsigned int flwd_tuple5_hash(const flwd_tuple5_t *tuple5, int);
+flwd_tuple5_t *flwd_tuple5_dup_to_stack(int tid, flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5);
+flwd_tuple5_t *flwd_tuple5_dup_to_heap(flwd_tuple5_t *dst_tuple5, const flwd_tuple5_t *src_tuple5);
+void flwd_tuple5_adjust_dir(flwd_tuple5_t *tuple5);
+unsigned int compat_marsio_tuple4_hash(const flwd_tuple5_t *nat_key);
+int flwd_act_ip_hash_proc(int tid, flwd_active_ip_t *act_ip_stack);
+int flwd_nat_htable_key_cmp(const uchar * key1, uint size1, const uchar * key2, uint size2);
+uint flwd_nat_htable_key2index(const MESA_htable_handle table, const uchar * key, uint size);
+uchar * flwd_nat_htable_key_dup(const uchar *key, uint key_size);
+void flwd_nat_htable_key_free(uchar *key, uint key_size);
+void flwd_adapt_sleep(int success_work_times_in_recent_100);
+int flwd_build_tuple4_key(int tid, flwd_tuple5_t *nat_key, const flwd_raw_pkt_t *raw_pkt);
+int flwd_pre_process_pkt_input(flwd_device_handle_t *rcv_device_handle, flwd_raw_pkt_t *raw_pkt);
+int flwd_maat_talbe_name_init(void);
+int flwd_maat_table_register(void *handle, int inner_table_index);
+unsigned int flwd_access_maat_scan_rule(int tid, const flwd_tuple5_t *tuple5);
+flwd_active_ip_t *flwd_ip_pool_search(unsigned char act_ip_origin, const MESA_htable_handle table, const uchar * key, uint size);
+void flwd_ip_dyn_sift_pool_cb(int table_id,const char* table_line,void* u_para);
+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);
+
+int flwd_maat_talbe_name_init(void);
+flwd_ip_region_type_t flwd_ipv4_location(unsigned int ip4addr);
+flwd_ip_region_type_t flwd_ipv6_location(const struct in6_addr *ip6addr);
+void flwd_act_ip_update(const flwd_active_ip_t *stack_act_ip);
+void * flwd_maat_summon(const char *cfg_file, const char *cfg_section);
+int flwd_ipt_equal(const flwd_ip_t *ip1, const flwd_ip_t *ip2);
+
+const char *flwd_ip_region_ntop(int ip_region_type);
+int flwd_arp_table_init(void);
+int flwd_arp_table_query(int tid, flwd_ip_t *ip_union, flwd_device_handle_t *io_handle, unsigned char result_mac[6]);
+void flwd_arp_response_update(const flwd_arp_hdr_t *arp_hdr);
+int flwd_tuple5_to_stream_addr(int tid, const flwd_tuple5_t *tuple5, struct ipaddr *stream_addr);
+unsigned int flwd_search_fwd_ip_by_gdev_ip(unsigned int active_ip_net_order);
+void flwd_del_last_rn(char *data, int max_len);
+int flwd_network_conn_init(void);
+unsigned char *flwd_policy_group_id_key_gen(unsigned int policy_group_id, unsigned char *out_key, int *out_key_len);
+const char *flwd_debug_print_tuple4(const void *a_packet, int tid);
+const char *flwd_debug_print_tuple4_r(const void *a_packet, char *buf, int buf_max_len);
+const char *flwd_debug_print_tuple4_detail(const void *a_packet, int tid);
+const char *flwd_debug_print_tuple4_detail_r(const void *a_packet, char *buf, int buf_max_len);
+
+unsigned short flwd_act_ip_get_usable_tcp_sport_num(void);
+unsigned short flwd_act_ip_get_usable_udp_sport_num(void);
+
+
+
+
+#endif
+
diff --git a/inc/flwd_net.h b/inc/flwd_net.h
new file mode 100644
index 0000000..2651021
--- /dev/null
+++ b/inc/flwd_net.h
@@ -0,0 +1,389 @@
+#ifndef _FLWD_NET_H_
+#define _FLWD_NET_H_ 1
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <linux/if_ether.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip6.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/in_systm.h>
+#include <linux/ppp_defs.h>
+
+/* ����һ��flwdģ�����õ�ͷ�ļ�, ��linux BSD������һ�� */
+
+struct flwd_eth_hdr{
+ unsigned char h_dest[ETH_ALEN]; /* destination ethernet address */
+ unsigned char h_source[ETH_ALEN]; /* source ethernet address */
+ unsigned short h_proto; /* packet type ID */
+}__attribute__((packed));
+typedef struct flwd_eth_hdr flwd_eth_hdr_t;
+
+typedef struct {
+ u_short ar_hrd; /* format of hardware address */
+
+ u_short ar_pro; /* format of protocol address */
+ u_char ar_hln; /* length of hardware address */
+ u_char ar_pln; /* length of protocol addres */
+ u_short ar_op; /* operation type */
+
+ /*
+ * These should implementation defined but I've hardcoded eth/IP.
+ */
+ u_char ar_sha[6]; /* sender hardware address */
+ u_char ar_spa[4]; /* sender protocol address */
+ u_char ar_tha[6]; /* target hardware address */
+ u_char ar_tpa[4]; /* target protocol address */
+}flwd_arp_hdr_t;
+
+/*
+ * Structure of an internet header, naked of options.
+ */
+typedef struct
+ {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int ip_hl:4; /* header length */
+ unsigned int ip_v:4; /* version */
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int ip_v:4; /* version */
+ unsigned int ip_hl:4; /* header length */
+#endif
+ u_int8_t ip_tos; /* type of service */
+ u_short ip_len; /* total length */
+ u_short ip_id; /* identification */
+ u_short ip_off; /* fragment offset field */
+#define IP_RF 0x8000 /* reserved fragment flag */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_int8_t ip_ttl; /* time to live */
+ u_int8_t ip_p; /* protocol */
+ u_short ip_sum; /* checksum */
+ struct in_addr ip_src, ip_dst; /* source and dest address */
+}flwd_ipv4_hdr_t;
+
+/*
+ * IPv6 packet header prototype, add by LiJia 2012-03-19.
+ */
+typedef struct{
+ u_int8_t ip6_flags[4]; /* version, traffic-class, flow-label */
+ u_int16_t ip6_payload_len; /* payload length, not contain header */
+ u_int8_t ip6_nxt_hdr; /* next header, same as protocol in IPv4 */
+ u_int8_t ip6_hop; /* hop limit, same as TTL in IPv4 */
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* dest address */
+}flwd_ipv6_hdr_t;
+
+#define FLWD_IPV4_MULTICAST_ADDR(addr) (((addr&0xF0000000)==0xE0000000)?1:0)
+
+/*
+ * ICMP packet header prototype. // from libnet-headers.h
+ */
+typedef struct
+{
+ u_char icmp_type;
+/*
+ * ICMP types.
+ */
+#ifndef ICMP_ECHOREPLY
+#define ICMP_ECHOREPLY 0
+#endif
+#ifndef ICMP_UNREACH
+#define ICMP_UNREACH 3
+#endif
+#ifndef ICMP_SOURCEQUENCH
+#define ICMP_SOURCEQUENCH 4
+#endif
+#ifndef ICMP_REDIRECT
+#define ICMP_REDIRECT 5
+#endif
+#ifndef ICMP_ECHO
+#define ICMP_ECHO 8
+#endif
+#ifndef ICMP_ROUTERADVERT
+#define ICMP_ROUTERADVERT 9
+#endif
+#ifndef ICMP_ROUTERSOLICIT
+#define ICMP_ROUTERSOLICIT 10
+#endif
+#ifndef ICMP_TIMXCEED
+#define ICMP_TIMXCEED 11
+#endif
+#ifndef ICMP_PARAMPROB
+#define ICMP_PARAMPROB 12
+#endif
+#ifndef ICMP_TSTAMP
+#define ICMP_TSTAMP 13
+#endif
+#ifndef ICMP_TSTAMPREPLY
+#define ICMP_TSTAMPREPLY 14
+#endif
+#ifndef ICMP_IREQ
+#define ICMP_IREQ 15
+#endif
+#ifndef ICMP_IREQREPLY
+#define ICMP_IREQREPLY 16
+#endif
+#ifndef ICMP_MASKREQ
+#define ICMP_MASKREQ 17
+#endif
+#ifndef ICMP_MASKREPLY
+#define ICMP_MASKREPLY 18
+#endif
+ u_char icmp_code;
+/*
+ * ICMP codes.
+ */
+#ifndef ICMP_UNREACH_NET
+#define ICMP_UNREACH_NET 0
+#endif
+#ifndef ICMP_UNREACH_HOST
+#define ICMP_UNREACH_HOST 1
+#endif
+#ifndef ICMP_UNREACH_PROTOCOL
+#define ICMP_UNREACH_PROTOCOL 2
+#endif
+#ifndef ICMP_UNREACH_PORT
+#define ICMP_UNREACH_PORT 3
+#endif
+#ifndef ICMP_UNREACH_NEEDFRAG
+#define ICMP_UNREACH_NEEDFRAG 4
+#endif
+#ifndef ICMP_UNREACH_SRCFAIL
+#define ICMP_UNREACH_SRCFAIL 5
+#endif
+#ifndef ICMP_UNREACH_NET_UNKNOWN
+#define ICMP_UNREACH_NET_UNKNOWN 6
+#endif
+#ifndef ICMP_UNREACH_HOST_UNKNOWN
+#define ICMP_UNREACH_HOST_UNKNOWN 7
+#endif
+#ifndef ICMP_UNREACH_ISOLATED
+#define ICMP_UNREACH_ISOLATED 8
+#endif
+#ifndef ICMP_UNREACH_NET_PROHIB
+#define ICMP_UNREACH_NET_PROHIB 9
+#endif
+#ifndef ICMP_UNREACH_HOST_PROHIB
+#define ICMP_UNREACH_HOST_PROHIB 10
+#endif
+#ifndef ICMP_UNREACH_TOSNET
+#define ICMP_UNREACH_TOSNET 11
+#endif
+#ifndef ICMP_UNREACH_TOSHOST
+#define ICMP_UNREACH_TOSHOST 12
+#endif
+#ifndef ICMP_UNREACH_FILTER_PROHIB
+#define ICMP_UNREACH_FILTER_PROHIB 13
+#endif
+#ifndef ICMP_UNREACH_HOST_PRECEDENCE
+#define ICMP_UNREACH_HOST_PRECEDENCE 14
+#endif
+#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
+#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
+#endif
+#ifndef ICMP_REDIRECT_NET
+#define ICMP_REDIRECT_NET 0
+#endif
+#ifndef ICMP_REDIRECT_HOST
+#define ICMP_REDIRECT_HOST 1
+#endif
+#ifndef ICMP_REDIRECT_TOSNET
+#define ICMP_REDIRECT_TOSNET 2
+#endif
+#ifndef ICMP_REDIRECT_TOSHOST
+#define ICMP_REDIRECT_TOSHOST 3
+#endif
+#ifndef ICMP_TIMXCEED_INTRANS
+#define ICMP_TIMXCEED_INTRANS 0
+#endif
+#ifndef ICMP_TIMXCEED_REASS
+#define ICMP_TIMXCEED_REASS 1
+#endif
+#ifndef ICMP_PARAMPROB_OPTABSENT
+#define ICMP_PARAMPROB_OPTABSENT 1
+#endif
+
+ u_short icmp_sum;
+
+ union
+ {
+ struct
+ {
+ u_short id;
+ u_short seq;
+ }echo;
+
+#undef icmp_id
+#undef icmp_seq
+#define icmp_id hun.echo.id
+#define icmp_seq hun.echo.seq
+
+ u_long gateway;
+ struct
+ {
+ u_short pad;
+ u_short mtu;
+ }frag;
+ }hun;
+ union
+ {
+ struct
+ {
+ n_time its_otime;
+ n_time its_rtime;
+ n_time its_ttime;
+ }ts;
+ struct
+ {
+ struct ip idi_ip;
+ /* options and then 64 bits of data */
+ }ip;
+ u_long mask;
+ char data[1];
+
+#undef icmp_mask
+#define icmp_mask dun.mask
+#undef icmp_data
+#define icmp_data dun.data
+
+#undef icmp_otime
+#define icmp_otime dun.ts.its_otime
+#undef icmp_rtime
+#define icmp_rtime dun.ts.its_rtime
+#undef icmp_ttime
+#define icmp_ttime dun.ts.its_ttime
+ }dun;
+
+}flwd_icmp_hdr_t;
+
+/* 2012-04-10 LiJia add,
+ ��׼ICMPͷ��������ڸ��ӣ�
+ ��ICMPЭ��ͷ���������������ECHO_REQUEST��ECHO_REPLAY.
+*/
+typedef struct{
+ unsigned char icmp_type;
+ unsigned char icmp_code;
+ unsigned short icmp_cksum;
+ unsigned short icd_id;
+ unsigned short icd_seq;
+ //char echo_data[......];
+}flwd_simple_icmp_hdr_t;
+
+
+#ifndef TH_FIN
+#define TH_FIN 0x01
+#endif
+
+#ifndef TH_SYN
+#define TH_SYN 0x02
+#endif
+
+#ifndef TH_RST
+#define TH_RST 0x04
+#endif
+
+#ifndef TH_PUSH
+#define TH_PUSH 0x08
+#endif
+
+#ifndef TH_ACK
+#define TH_ACK 0x10
+#endif
+
+#ifndef TH_URG
+#define TH_URG 0x20
+#endif
+
+typedef struct{
+ u_int16_t th_sport; /* source port */
+ u_int16_t th_dport; /* destination port */
+ u_int32_t th_seq; /* sequence number */
+ u_int32_t th_ack; /* acknowledgement number */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t th_x2:4, /* (unused) */
+ th_off:4; /* data offset */
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t th_off:4, /* data offset */
+ th_x2:4; /* (unused) */
+#else
+#error "Please check <endian.h>"
+#endif
+ u_int8_t th_flags; /* control flags */
+ u_int16_t th_win; /* window */
+ u_int16_t th_sum; /* checksum */
+ u_int16_t th_urp; /* urgent pointer */
+}flwd_tcp_hdr_t;
+
+
+/*
+ * UDP packet header prototype.
+ */
+typedef struct{
+ u_int16_t uh_sport; /* soure port */
+ u_int16_t uh_dport; /* destination port */
+ u_int16_t uh_ulen; /* length */
+ u_int16_t uh_sum; /* checksum */
+}flwd_udp_hdr_t;
+
+
+/* ��׼vxlan���� */
+typedef struct{
+ unsigned char flags;
+ /*------------byte delim -------*/
+ unsigned char reserved[3];
+
+ /*--------int delim -------*/
+ unsigned char vlan_id_half_high;
+ unsigned char link_layer_type : 4; /* ���㱨�ķ�װ��ʽ */
+ unsigned char vlan_id_half_low : 4;
+ unsigned int online_test : 1;
+ unsigned int link_id : 6;
+ unsigned int dir : 1;
+
+ unsigned int r7 : 1;
+ unsigned int r6 : 1;
+ unsigned int r5 : 1;
+ unsigned int r4 : 1;
+ unsigned int vni_flag : 1;
+ unsigned int r2 : 1;
+ unsigned int r1 : 1;
+ unsigned int r0 : 1;
+}__vxlan_standard_hdr_t;
+
+/*
+ �˽ṹ�������׼vxlan(RFC7348) __vxlan_standard_hdr_t ��ͬ, ʹ����ijЩԤ���ֶ�,
+ ������access��forward����֮���ڲ�ͨѶ, ����������gdev���, ����ijЩֵ��������ʹ��.
+*/
+typedef struct{
+ unsigned char flags;
+
+ /*------------byte delim -------*/
+ unsigned char reserved[3];
+
+ /*--------int delim -------*/
+ unsigned char vlan_id_half_high;
+ unsigned char link_layer_type : 4; /* ���㱨�ķ�װ��ʽ */
+ unsigned char vlan_id_half_low : 4;
+ unsigned int online_test : 1;
+ unsigned int link_id : 6;
+ unsigned int dir : 1;
+
+ unsigned int r7 : 1;
+ unsigned int r6 : 1;
+ unsigned int r5 : 1;
+ unsigned int r4 : 1;
+ unsigned int vni_flag : 1;
+ unsigned int r2 : 1;
+ unsigned int r1 : 1;
+ unsigned int first_pkt_per_stream : 1; /* �˱�������, ��ʾ��һ�������װ�, ����access֪ͨfwd���� */
+
+}flwd_vxlan_hdr_t;
+
+#define FLWD_VXLAN_OUTER_PACKET_LEN (sizeof(flwd_eth_hdr_t)+sizeof(flwd_ipv4_hdr_t)+sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t))
+#endif
+
diff --git a/inc/ltsm.h b/inc/ltsm.h
new file mode 100644
index 0000000..340aa2f
--- /dev/null
+++ b/inc/ltsm.h
@@ -0,0 +1,117 @@
+#ifndef __LTSM_H_
+#define __LTSM_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+ LTSM : Light TCP State Machine.
+ Version : 2018-01-16
+*/
+
+/* RFC��׼TCPЭ��ջ״̬������ */
+enum full_tcp_state{
+ FTSM_VOID, /* ���һ�����ĵ�һ��������SYN��, ���ش�ֵ */
+ FTSM_SYN_SENT,
+ FTSM_SYN_RCVD,
+ FTSM_ESTABLISHED,
+ FTSM_FIN_WAIT,
+ FTSM_CLOSE_WAIT,
+ FTSM_LAST_ACK,
+ FTSM_TIME_WAIT,
+ FTSM_CLOSED,
+ FTSM_LISTEN,
+ __FTSM_MAX,
+};
+
+/*
+ ����TCP״̬������,
+ ʵ��ֻ������״̬:�½�����, ��������, ��������,
+ ÿ�����ض�����1��START��1��CLOSE״̬, ���ܰ���0�����ɸ�DATA״̬.
+
+ VOID״̬���ڵ����߿����ж��Ƿ���Ҫ��������.
+*/
+enum light_tcp_state{
+ LTSM_VOID, /* ���һ�����ĵ�һ��������SYN��, ���ش�ֵ */
+ LTSM_START,
+ LTSM_DATA,
+ LTSM_CLOSE,
+};
+
+struct ltsm_iphdr
+ {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int ip_hl:4; /* header length */
+ unsigned int ip_v:4; /* version */
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int ip_v:4; /* version */
+ unsigned int ip_hl:4; /* header length */
+#endif
+ u_int8_t ip_tos; /* type of service */
+ u_short ip_len; /* total length */
+ u_short ip_id; /* identification */
+ u_short ip_off; /* fragment offset field */
+#define IP_RF 0x8000 /* reserved fragment flag */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_int8_t ip_ttl; /* time to live */
+ u_int8_t ip_p; /* protocol */
+ u_short ip_sum; /* checksum */
+ struct in_addr ip_src, ip_dst; /* source and dest address */
+ };
+
+struct ltsm_tcphdr
+ {
+ u_int16_t th_sport; /* source port */
+ u_int16_t th_dport; /* destination port */
+ u_int32_t th_seq; /* sequence number */
+ u_int32_t th_ack; /* acknowledgement number */
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t th_x2:4; /* (unused) */
+ u_int8_t th_off:4; /* data offset */
+# endif
+# if __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t th_off:4; /* data offset */
+ u_int8_t th_x2:4; /* (unused) */
+# endif
+ u_int8_t th_flags;
+# define TH_FIN 0x01
+# define TH_SYN 0x02
+# define TH_RST 0x04
+# define TH_PUSH 0x08
+# define TH_ACK 0x10
+# define TH_URG 0x20
+ u_int16_t th_win; /* window */
+ u_int16_t th_sum; /* checksum */
+ u_int16_t th_urp; /* urgent pointer */
+};
+
+struct ltsm_result{
+ enum full_tcp_state fstate;
+ enum light_tcp_state lstate;
+};
+
+typedef void * ltsm_stream_handle;
+
+ltsm_stream_handle ltsm_create_handle(void);
+
+#define LTSM_DIR_C2S 0
+#define LTSM_DIR_S2C 1
+
+struct ltsm_result ltsm_get_current_state(ltsm_stream_handle pltsm, uint8_t tcp_flags, uint8_t dir);
+
+const char *ltsm_fstate_ntop(enum full_tcp_state fstate);
+const char *ltsm_lstate_ntop(enum light_tcp_state lstate);
+
+void ltsm_destroy_handle(ltsm_stream_handle pltsm);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/lib/libltsm.a b/lib/libltsm.a
new file mode 100644
index 0000000..93538db
--- /dev/null
+++ b/lib/libltsm.a
Binary files differ
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..c244e92
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,59 @@
+#CC=gcc
+CC=g++
+CCC=g++
+
+ifeq ($(type), $(TYPE_ACCESS))
+TARGET=flowood_access
+else
+TARGET=flowood_forward.so
+endif
+
+CFLAGS += -g -fPIC -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 -ldl -lMESA_handle_logger -lMESA_htable -lMESA_prof_load
+
+COMMON_OBJS=flowood_main.o common/flwd_common_stack.o common/flwd_sendpacket.o common/flwd_status.o
+COMMON_OBJS += common/flwd_common_tool.o
+COMMON_OBJS += common/flwd_compat_marsio_hash.o
+COMMON_OBJS += common/linux_jhash_algo.o
+COMMON_OBJS += common/flwd_arp.o
+COMMON_OBJS += common/flwd_common_hash.o
+COMMON_OBJS += packet_io/flwd_packet_io.o
+
+ACC_OBJS = access/flowood_access.o
+ACC_OBJS += access/flwd_access_ip_layer.o
+ACC_OBJS += access/flwd_access_active_ip_manage.o
+ACC_OBJS += access/flwd_access_idle_call.o
+ACC_OBJS += access/flwd_access_maat.o
+ACC_OBJS += common/flwd_common_maat.o
+ACC_OBJS += common/flwd_network_connect.o
+ACC_OBJS += ../lib/libltsm.a
+
+FWD_OBJS = forward/flowood_forward.o
+FWD_OBJS += forward/flwd_fwd_idle_call.o
+
+all:$(TARGET)
+
+.c.o:
+ $(CCC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+.cpp.o:
+ $(CCC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+flowood_access: $(COMMON_OBJS) $(ACC_OBJS)
+ (rm -f $@; $(CC) -o $@ -Wl,--export-dynamic $(CFLAGS) $^ $(LIB) -lmaatframe ; cp $@ ../bin;)
+
+#flowood_forward: $(COMMON_OBJS) $(FWD_OBJS)
+ #(rm -f $@; $(CC) -o $@ -Wl,--export-dynamic $(CFLAGS) $^ $(LIB); cp $@ ../bin;)
+
+flowood_forward.so: $(COMMON_OBJS) $(FWD_OBJS)
+ (rm -f $@; $(CC) -o $@ -shared $(CFLAGS) $^ $(LIB); cp $@ /opt/MESA/lib)
+
+
+clean:
+ rm -f *.o access/*.o common/*.o packet_io/*.o forward/*.o $(TARGET)
diff --git a/src/access/Makefile b/src/access/Makefile
new file mode 100644
index 0000000..be17825
--- /dev/null
+++ b/src/access/Makefile
@@ -0,0 +1,26 @@
+#CC=gcc
+CC=g++
+CCC=g++
+
+TARGET=flowood_access.o flwd_access_ip_layer.o flwd_access_active_ip_manage.o flwd_access_idle_call.o flwd_access_maat.o
+
+CFLAGS=-g -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)
+
+.c.o:
+ $(CC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+.cpp.o:
+ $(CCC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+clean:
+ rm -f *.o
diff --git a/src/access/flowood_access.c b/src/access/flowood_access.c
new file mode 100644
index 0000000..6af4866
--- /dev/null
+++ b/src/access/flowood_access.c
@@ -0,0 +1,1656 @@
+#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 "ltsm.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>
+
+/*
+ IP����ϵͳ��������, ��������ն˵�����, ���ݲ���ѡ���ض�IP��, ��NATת��,
+ ���͸�ת������,
+ �Զ������̷�ʽ����.
+*/
+
+static int flwd_access_fetch_usable_ipport_by_single_ip(
+ flwd_active_ip_t *flwd_active_ip, flwd_active_ip_port_args_t *usable_active_ipport_args)
+{
+ int ret;
+ int try_times;
+ MESA_list_count_t *usable_sport_queue_head, *sport_list_node;
+ unsigned short sport;
+ long buf_len;
+ flwd_tuple5_t seek_nat_key;
+ unsigned int compat_io_hash;
+ char ip_str[64];
+ int usable_sport_num;
+
+ if(IPPROTO_TCP == usable_active_ipport_args->protocol){
+ usable_sport_queue_head = &flwd_active_ip->usable_tcp_sport_list_head;
+ }else{
+ usable_sport_queue_head = &flwd_active_ip->usable_udp_sport_list_head;
+ }
+
+ usable_sport_num = MESA_list_count_get_count(usable_sport_queue_head);
+ if(usable_sport_num <= 0){
+ /* ��ǰIP���ö˿���ȫ�������� */
+ flwd_log(20, "ip_pool: %s, all usable sport is in used!\n",
+ flwd_ipt_ntop_r(&flwd_active_ip->active_ip_net_order, ip_str, 64));
+ return ITERATE_CB_RET_CONTINUE_FLAG;
+ }
+
+ flwd_tuple5_dup_to_stack(usable_active_ipport_args->tid, &seek_nat_key, usable_active_ipport_args->nat_key);
+
+ flwd_tuple5_adjust_dir(&seek_nat_key);
+
+ if(FLWD_IP_ADDR_TYPE_V4 == flwd_active_ip->active_ip_net_order.addr_type){
+ seek_nat_key.ippair_v4.sip_net_order = flwd_active_ip->active_ip_net_order.addr_ipv4;
+ }else{
+ memcpy(&seek_nat_key.ippair_v6->sip_net_order,
+ &flwd_active_ip->active_ip_net_order.addr_ipv6,
+ sizeof(struct in6_addr));
+ }
+
+ /*
+ TODO,
+ �˴�ѡ����ԴIP, ��Ҫѡ����ʵ�Դ�˿�, ʹ�ظ��������ܷ�������ǰ���͵��߳�,
+ ����ʹ��ring_queue, ��Ҫ��ͣ�ı������Կ��ö˿�, ֱ��hashֵ���Ϸ�������.
+ */
+ sport_list_node = usable_sport_queue_head->nextele;
+
+ for(try_times = 0;
+ (try_times < usable_sport_num) && (sport_list_node != usable_sport_queue_head);
+ try_times++, sport_list_node = sport_list_node->nextele){
+ /* �������ж˿�, �鿴�ĸ����ɵ���Ԫ��HASH���ɷ��ϵ�ǰ�߳�id */
+ memcpy(&seek_nat_key.sport_net_order, &sport_list_node->quiddity, sizeof(short));
+ compat_io_hash = compat_marsio_tuple4_hash(&seek_nat_key);
+ if((compat_io_hash % flwd_cfg_val.tot_thread_count) == usable_active_ipport_args->tid){
+ MESA_list_count_del(usable_sport_queue_head, sport_list_node); /* �ӿ��ö˿��������Ƴ� */
+ free(sport_list_node); /* �˿��Ѿ���ȡ��, ������������ṹ */
+ goto bingo;
+ }
+ }
+
+ /* ��Ȼ�п��ö˿�, ���ǵ�ǰIPû�ҵ��ʺϵ�ǰ�߳�, �Թ�����ʵ�HASHֵ����Ѷ˿�, ����������һ��IP */
+ flwd_log(20, "ip_pool: %s,has %d usable sport, but unfortunately no match hash value sport for current thread!\n",
+ usable_sport_num,
+ flwd_ipt_ntop_r(&flwd_active_ip->active_ip_net_order, ip_str, 64), usable_sport_num);
+ return ITERATE_CB_RET_CONTINUE_FLAG ;
+
+bingo:
+ usable_active_ipport_args->act_sip_net_order = flwd_active_ip->active_ip_net_order;
+ usable_active_ipport_args->act_sport_net_order = seek_nat_key.sport_net_order;
+
+ memcpy(&usable_active_ipport_args->gdev_args, &flwd_active_ip->gdev_args, sizeof(flwd_gdev_associated_args_t));
+
+ return ITERATE_CB_RET_BREAK_FLAG | ITERATE_CB_RET_REVERSE_FLAG;
+}
+
+/*
+ NOTE:
+ Ϊ��ͬʱ��Ӧstatic_pool��dynamic_pool, ����һ������,
+ ��ͬ����static_poolΪһ��flwd_active_ip_t�ṹ������, ��Ҫ�ڴ˺�����ѭ������.
+*/
+static int flwd_access_fetch_usable_ipport_by_ip_list_cb(
+ const uchar * key, uint size, void * data, void *user)
+{
+ int ret;
+ flwd_active_ip_t *flwd_active_ip_list_head = (flwd_active_ip_t *)data;
+ flwd_active_ip_t *tmp_node;
+ flwd_active_ip_port_args_t *usable_active_ipport_args = (flwd_active_ip_port_args_t *)user;
+
+ tmp_node = flwd_active_ip_list_head;
+ do{
+ ret = flwd_access_fetch_usable_ipport_by_single_ip(tmp_node, usable_active_ipport_args);
+ if(ITERATE_CB_RET_BREAK_FLAG == ret){
+ break;
+ }
+
+ tmp_node = (flwd_active_ip_t *)tmp_node->active_ip_list_node.nextele->quiddity;
+ }while(flwd_active_ip_list_head != tmp_node);
+
+ return ret|ITERATE_CB_RET_REVERSE_FLAG /* �޸�item˳��, ÿ�����Ӹ�����ַ���ﲻͬ��IP */;
+}
+
+/*
+ ����: ��ʵ�ͻ��˵���Ԫ��;
+ ���: ���õ�Դ��ԾIP;
+
+ ����ֵ:
+ 1 : ���в�������, �����ҵ����ŵ�ǰ���ԵĿ���Դip;
+ 0 : �޲���;
+ -1 : �����˲���, ��û�п���IP;
+
+ service_defined��ʽ:
+ "IR_STRATEGY:123"
+*/
+static int flwd_access_snat_search_policy(int tid,
+ flwd_tuple5_t *tuple5, flwd_active_ip_port_args_t *usable_active_ipport_net_order)
+{
+ unsigned int usable_active_ip = 0;
+ int ret;
+ int found_usable_policy_ip = -1;
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+ return 0; /* ��ʱ����, �޲��� */
+#else
+ unsigned int policy_id;
+ MESA_list_t *list_node;
+ flwd_active_ip_t *ip_static_pool_list_head, *list_node_item;
+ flwd_ip_region_type_t ip_pool_retion;
+ unsigned char static_ip_group_key[64];
+ int static_ip_group_key_len = 64;
+
+ policy_id = flwd_access_maat_scan_rule(tid, tuple5);
+ if(0 == policy_id){
+ return 0;
+ }
+
+ flwd_log(10, "tuple4 %s hit policy id:%u\n", flwd_tuple5_ntop(tid, tuple5), policy_id);
+
+ /* ���õ�IPΪ��ǰĿ��IP�ķ��� */
+ if(FLWD_IP_REGION_INLAND == usable_active_ipport_net_order->dip_region_type){
+ ip_pool_retion = FLWD_IP_REGION_OUTLAND;
+ }else{
+ ip_pool_retion = FLWD_IP_REGION_INLAND;
+ }
+
+ flwd_policy_group_id_key_gen(policy_id, static_ip_group_key, &static_ip_group_key_len);
+
+ ip_static_pool_list_head = flwd_ip_pool_search(FLWD_ACT_IP_STATIC,
+ flwd_thread_val[tid].flwd_ip_pool_static_htable[tuple5->addr_type][ip_pool_retion],
+ static_ip_group_key,
+ static_ip_group_key_len);
+ if(NULL == ip_static_pool_list_head){
+ flwd_log(30, "tuple4 %s hit policy id:%u, but no valid ip in static ip_pool!\n",
+ flwd_tuple5_ntop(tid, tuple5), policy_id);
+ return 0;
+ }
+
+ list_node = &ip_static_pool_list_head->active_ip_list_node;
+ do{
+ list_node_item = (flwd_active_ip_t *)list_node->quiddity;
+ /* ����htable_cb����, �˴���key, size�ɲ��� */
+ ret = flwd_access_fetch_usable_ipport_by_single_ip(list_node_item, usable_active_ipport_net_order);
+ if(ITERATE_CB_RET_BREAK_FLAG == ret){
+ found_usable_policy_ip = 1;
+ break;
+ }
+ list_node = list_node->nextele;
+ }while(list_node != &ip_static_pool_list_head->active_ip_list_node);
+
+#endif
+
+ return found_usable_policy_ip;
+}
+
+
+/*
+ �ӵ�ַ����, ���ѡ��һ�����û�ԾIP.
+
+ TODO:
+ �����ͬ�ͻ���, ʹ���˲�ͬ����, ��ͬһ��ԴIP���ڲ�ͬ�ľ�̬��ַ����,
+ ������1.2.3.4��Ϊ����IP, �˿ڷ�Χ�ǰ�access_gateway�������ֵ�,
+ ����ͬһ��access_gateway, ������һ���Ķ˿�, ��ͻ��ô��?
+ ��ô�����ͻ����??!!
+
+ �����ý��汣֤, һ��IP��ַֻ������һ����̬��ַ��.
+*/
+static int flwd_access_snat_fetch_usable_ip_from_pool(
+ MESA_htable_handle table, pthread_rwlock_t *flwd_ip_pool_rwlock, int tid,
+ flwd_tuple5_t *nat_key, flwd_active_ip_port_args_t *usable_active_ipport_args)
+{
+
+ pthread_rwlock_wrlock(flwd_ip_pool_rwlock);
+
+ /* ����htable�İ�ʱ�����ȱ�������, ��ѡ���µ�IP, ����dip�ĵ���, ѡ���෴��Դ��Ծip */
+ MESA_htable_iterate_bytime(table,
+ ITERATE_TYPE_NEWEST_FIRST,
+ flwd_access_fetch_usable_ipport_by_ip_list_cb,
+ usable_active_ipport_args);
+
+ if((0 == usable_active_ipport_args->act_sip_net_order.addr_ipv4)
+ || (0 == memcmp(&usable_active_ipport_args->act_sip_net_order.addr_ipv6,
+ &flwd_global_val.zero_ipv6_addr, sizeof(struct in6_addr)))){
+ pthread_rwlock_unlock(flwd_ip_pool_rwlock);
+ return -1;
+ }
+
+ pthread_rwlock_unlock(flwd_ip_pool_rwlock);
+ return 0;
+}
+
+#if FLWD_SUPPORT_DNAT
+static void * flwd_search_access_dnat_lb_policy(int tid,
+ flwd_tuple4v4_t *nat_key, flwd_actual_ip_port_t *actual_ipport_net_order)
+{
+ /* ����dip, dport�ҵ���ʵ��������dip, dport, �滻�������ݰ�, Ȼ��洢��nat-htable */
+ return 0;
+}
+#endif
+
+
+
+/* TODO:
+ ��ֹ������, �ǶԳ�·������, ����S2C�����������C2S������ͬһ̨ת������,
+
+ Ҫ�����ӱ���ɢ��ȫ����ת������,
+
+ ��Ԫ��, dip+dport+sip, ��Ԫ����̫����,
+
+ sport����һ������ָ���㷨, ɨ����Ԫ������ж�sport.
+*/
+static int flwd_link_table_broadcast(int tid, flwd_nat_info_t *nat_info)
+{
+ /* TODO:
+ ��ֹ������, �ǶԳ�·������, ����S2C�����������C2S������ͬһ̨ת������,
+
+ Ҫ�����ӱ���ɢ��ȫ����ת������.
+ */
+ return 0;
+}
+
+
+/* ��ָ����Ϣ�洢��Դ�˿ڵ��ض��ֶ�, ��������IR�İ�����ʵ�ͻ��˵İ� */
+static void flwd_pkt_signature_hide_to_sport(
+ unsigned short pkt_signature, flwd_nat_info_t *nat_info)
+{
+ unsigned short sport_host_order;
+
+ pkt_signature &= (FLWD_UDP_SPORT_HASH_MASK >> 8);
+
+ if(0 == nat_info->outer_nat_tuple5.dir_reverse){
+ sport_host_order = ntohs(nat_info->outer_nat_tuple5.sport_net_order);
+ sport_host_order &= (~FLWD_UDP_SPORT_HASH_MASK); /* �����hash�ֶ� */
+ sport_host_order |= (pkt_signature << 8); /* hash�ֶ�������sport�� */
+ nat_info->outer_nat_tuple5.sport_net_order = htons(sport_host_order);
+ }else{
+ sport_host_order = ntohs(nat_info->outer_nat_tuple5.dport_net_order);
+ sport_host_order &= (~FLWD_UDP_SPORT_HASH_MASK); /* �����hash�ֶ� */
+ sport_host_order |= (pkt_signature << 8); /* hash�ֶ�������sport�� */
+ nat_info->outer_nat_tuple5.dport_net_order = htons(sport_host_order);
+ }
+
+ return;
+}
+
+
+/*
+ ѡ��Դ�˿���Ҫ��֤����ȥ���߳�id, ��Ӧ�������֮��, ���ܱ�����������ͬһ���߳�,
+ ������Ҫ���Զ��, �ҵ�һ�����ʵ�sport, ���ɷ��������ķ����㷨.
+
+ ��Ϊdip, dport�Dz��ܱ��, sipҲ�����ѡ�����ܱ�, ֻ����Դ�˿�����һЩtrick,
+ ���Ҷ����ͬ��������֮��, �������صIJ�ͬ�߳�֮���Ѿ�Ԥ�ȷ����˶˿ڷ�Χ,
+ ����һ����ԾIP��˵, �˿������������trick�ķ�Χ��С, ����׼ȷ�Ⱥܵ�!
+
+ ��ȡһ���²���:
+ 1,TCPЭ��, ʹ��SYN-ISNת������, ͨ��32bit��ISN����hash, ��Ϊָ��;
+ 2,DNSЭ��, ʹ��DNS-TRANSIDת������, ͨ��16bit��TRANSID��Ϊָ��, ��ͻ�ʱ�TCP_ISN���һЩ;
+ 3,����UDPЭ��, ѡ�����Ԫ��ʹ��maat_redisȫ����ɢ, ����Э����ܴ�����ʱ���⵼���װ���ʧ!
+*/
+static int flwd_acc_user_generate_pkt_signature(
+ int tid, flwd_nat_info_t *nat_info, flwd_raw_pkt_t *raw_pkt)
+{
+ const flwd_ipv4_hdr_t *flwd_iphdr = (flwd_ipv4_hdr_t *)raw_pkt->inner_ip_layer_hdr;
+ const flwd_udp_hdr_t *flwd_udphdr;
+ const flwd_tcp_hdr_t *flwd_tcphdr;
+ int canot_convert_pro;
+ unsigned int hash_val;
+ unsigned short pkt_signature;
+
+ if(FLWD_NAT_TYPE_SNAT != nat_info->nat_type){
+ return 0;
+ }
+
+ if(IPPROTO_TCP == flwd_iphdr->ip_p){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_iphdr + flwd_iphdr->ip_hl * 4);
+ assert(TH_SYN == flwd_tcphdr->th_flags);
+ canot_convert_pro = 0;
+ /* �˴�Ҫʹ��nat֮�����Ԫ��, ָ����Ϣ��Ҫ����ת������ʶ������internet�����ݰ� */
+ hash_val = flwd_tuple5_hash(&nat_info->outer_nat_tuple5, 1);
+ /*
+ TODO:
+ ����TCPЭ��, ʹ�ö˿�HASH�����ʽ��ͻ�ʽϸ�, �����޸�ISN�ķ�ʽ,
+ */
+#if 0
+ nat_info->signature_param = (long long)hash_val - (long long)ntohl(flwd_tcphdr->th_seq);
+#else
+ pkt_signature = hash_val % (FLWD_UDP_SPORT_HASH_MASK >> 8);
+#endif
+
+ }else if(IPPROTO_UDP == flwd_iphdr->ip_p){
+ /*
+ TODO,
+ ����UDPЭ��, ���ö˿�HASH����, ��ͻ��Ҳ�ϸ�, ������redisȫ����ɢ��Ԫ�鹦��,
+ IP���ú���ʵ�ͻ��˷���ͬһ��������, ���Ҷ˿ڻ����ɳ�ͻ�ļ��ʼ�С.
+ */
+ hash_val = flwd_tuple5_hash(&nat_info->outer_nat_tuple5, 1);
+ pkt_signature = hash_val % (FLWD_UDP_SPORT_HASH_MASK >> 8);
+ canot_convert_pro = 0;
+ }else{
+ canot_convert_pro = 1;
+ }
+
+ if(1 == canot_convert_pro){
+ /* TODO: ��ͨUDPЭ�鿿redisʵʱ��ɢ��Ԫ��, ʶ��Ӧ��� */
+ //flwd_link_table_broadcast(tid, nat_info);
+ }else{
+ flwd_pkt_signature_hide_to_sport(pkt_signature, nat_info);
+ }
+
+ return 0;
+}
+
+static flwd_terminal_proto_t flwd_access_proto_identify(flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_terminal_proto_t flwd_pro = FLWD_TERMINAL_IP_LAYER;
+
+ /*
+ TODO:
+ ʶ��L2TP, PPTP���뷽ʽ�����ݰ�.
+
+ ���߿�������ʽ�ս�VPN, תΪ��IP��, ��ͬ��IP�������.
+ */
+
+ return flwd_pro;
+}
+
+
+
+/* �������شӿͻ��˷����հ�, ����ײ�ԭʼ���ݰ���ں��� */
+static int flwd_acc_user_pkt_input(flwd_device_handle_t *device_handle,
+ int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ raw_pkt->terminal_proto = flwd_access_proto_identify(raw_pkt);
+ switch(raw_pkt->terminal_proto){
+ case FLWD_TERMINAL_IP_LAYER:
+ flwd_access_kernal_pkt_input(device_handle, tid, raw_pkt);
+ break;
+
+ case FLWD_TERMINAL_IP_L2TP:
+ /* TODO */
+ assert(0);
+ break;
+
+ case FLWD_TERMINAL_IP_PPTP:
+ /* TODO */
+ assert(0);
+ break;
+
+ default:
+ assert(0);
+ }
+
+ return 0;
+}
+
+/*
+ NAT��ַת��,
+ ����nat_info��, ����������Ԫ��, �滻���ݰ��е�IP�Ͷ˿�,
+ �����¼���У���.
+*/
+static int flwd_nat_set_new_addr_v4(flwd_topology_t topo_mode,
+ flwd_nat_type_t nat_type, const flwd_nat_info_t *nat_info, flwd_ipv4_hdr_t *flwd_ip4hdr)
+{
+ flwd_tcp_hdr_t *flwd_tcp_hdr;
+ flwd_udp_hdr_t *flwd_udp_hdr;
+ const flwd_tuple5_t *after_nat_addr;
+ struct ltsm_result ltsm_res;
+ unsigned int *tobe_modify_ip;
+ unsigned short *tobe_modify_port;
+ unsigned char tcp_flags = 0;
+
+ if(TOPO_ACC_LINK_USER == topo_mode){
+ /* C2I����, ��outer�ĵ�ַ, �滻��ǰ����Դip��Դ�˿� */
+ after_nat_addr = &nat_info->outer_nat_tuple5;
+ tobe_modify_ip = &flwd_ip4hdr->ip_src.s_addr;
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcp_hdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tcp_flags = flwd_tcp_hdr->th_flags;
+ tobe_modify_port = &flwd_tcp_hdr->th_sport;
+ }else{
+ flwd_udp_hdr = (flwd_udp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tobe_modify_port = &flwd_udp_hdr->uh_sport;
+ }
+ }else{
+ /* I2C����, ��inner�ĵ�ַ, �滻��ǰ����Ŀ��ip��Ŀ��˿� */
+ after_nat_addr = &nat_info->inner_nat_tuple5;
+ tobe_modify_ip = &flwd_ip4hdr->ip_dst.s_addr;
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcp_hdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tcp_flags = flwd_tcp_hdr->th_flags;
+ tobe_modify_port = &flwd_tcp_hdr->th_dport;
+ }else{
+ flwd_udp_hdr = (flwd_udp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ tobe_modify_port = &flwd_udp_hdr->uh_dport;
+ }
+ }
+
+ /* Ϊ��hashֻ����һ��, key�ĵ�ַ�洢���Ǹ���sip>dip�Ľ������, Ҫ���ݴ洢��key�ĵ�ַ����, ѡ��������ԭʼ��ַ */
+ if(0 == after_nat_addr->dir_reverse){
+ *tobe_modify_ip = after_nat_addr->ippair_v4.sip_net_order;
+ *tobe_modify_port = after_nat_addr->sport_net_order;
+ }else{
+ *tobe_modify_ip = after_nat_addr->ippair_v4.dip_net_order;
+ *tobe_modify_port = after_nat_addr->dport_net_order;
+ }
+
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_sendpacket_do_checksum((char *)flwd_ip4hdr,
+ IPPROTO_TCP,
+ ntohs(flwd_ip4hdr->ip_len) - flwd_ip4hdr->ip_hl * 4); /* �Ӵ����ͷ����ʼ����ĩβ�ij��� */
+ }else{
+ flwd_sendpacket_do_checksum((char *)flwd_ip4hdr,
+ IPPROTO_UDP,
+ ntohs(flwd_ip4hdr->ip_len) - flwd_ip4hdr->ip_hl * 4); /* �Ӵ����ͷ����ʼ����ĩβ�ij��� */
+ }
+
+ flwd_sendpacket_do_checksum((char *)flwd_ip4hdr,
+ IPPROTO_IP,
+ sizeof(flwd_ipv4_hdr_t));
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ unsigned char dir;
+ if(tcp_flags != 0){
+ if(FLWD_NAT_TYPE_SNAT == nat_info->nat_type){
+ if(TOPO_ACC_LINK_USER == topo_mode){
+ dir = LTSM_DIR_C2S; /* SNATģʽ, ��user���յ��Ŀ϶���client�˵İ� */
+ }else{
+ dir = LTSM_DIR_S2C;
+ }
+ }else{
+ if(TOPO_ACC_LINK_USER == topo_mode){
+ dir = LTSM_DIR_S2C;
+ }else{
+ dir = LTSM_DIR_C2S;
+ }
+ }
+
+ ltsm_res = ltsm_get_current_state(nat_info->ltsm_stat_handle, tcp_flags, dir);
+ }
+#endif
+
+ return (int)ltsm_res.fstate;
+}
+
+
+static int flwd_nat_set_new_addr_v6(flwd_topology_t topo_mode,
+ flwd_nat_type_t nat_type, const flwd_nat_info_t *nat_info,flwd_ipv6_hdr_t *flwd_ip6hdr)
+{
+ /* TODO, IPv6 NAT */
+ return -1;
+}
+
+
+/*
+ ����֮ǰ�Ѿ��洢��ת����, ��natת��
+ Ŀǰ���õIJ�����ֱ���޸�ԭʼ����IP��ַ�Ͷ˿�, �������, ����ÿ�ζ�malloc/memcpy/free����.
+*/
+static int flwd_do_nat(flwd_device_handle_t *device_handle,
+ flwd_nat_info_t *nat_info, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ if(FLWD_IP_ADDR_TYPE_V4 == nat_info->outer_nat_tuple5.addr_type){
+ ret = flwd_nat_set_new_addr_v4(device_handle->io_para.topo_mode,
+ nat_info->nat_type, nat_info,
+ (flwd_ipv4_hdr_t *)raw_pkt->inner_ip_layer_hdr);
+ }else{
+ ret = flwd_nat_set_new_addr_v6(device_handle->io_para.topo_mode,
+ nat_info->nat_type, nat_info,
+ (flwd_ipv6_hdr_t *)raw_pkt->inner_ip_layer_hdr);
+ }
+
+ return ret;
+}
+
+static void *flwd_nat_table_search(void)
+{
+ /*
+ ת���������к�, �ὫSNAT��DNAT���ʹ洢��vxlan��ij���ֶΣ�
+
+ ����SNAT, C2S����Ĵ洢NAT�����Ԫ��, ��S2C����Ļ�����, �ٴβ���htable��ͬ��key�� �ָ�֮ǰ��ʵ�ͻ���IP��PORT����;
+
+ ����DNAT, ��һ��SYN��ɨ��IP���ò��Ա�, �ҵ�һ�����õ�RIP��RPORT, Ȼ��Ҳ�洢��htable,
+ ����������������İ�, ֱ�Ӻ�SNAT�ɸ���һ��htable, ����һ�μ��ɡ�
+ */
+ return 0;
+}
+
+
+static void * flwd_acc_to_fwd_pre_output(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_nat_info_t *nat_info,
+ flwd_raw_pkt_t *raw_pkt, unsigned int out_opt)
+{
+ flwd_vxlan_hdr_t *outer_vxlan_hdr;
+ unsigned char *local_acc_gateway_mac = NULL ;
+ int ret;
+ flwd_ip_t ip_union;
+ char ip_str[64];
+ flwd_eth_hdr_t *inner_eth_hdr;
+
+ char *unsend_raw_data_ptr = rcv_device_handle->low_level_mbuff_mtod(raw_pkt->low_level_mbuff);
+ int unsend_raw_data_len = rcv_device_handle->low_level_mbuff_get_pkt_len(raw_pkt->low_level_mbuff);
+ void *send_mbuff = send_device_handle->low_level_mbuff_malloc(send_device_handle, tid, unsend_raw_data_len+FLWD_VXLAN_OUTER_PACKET_LEN);
+ char *send_buf_data_ptr;
+
+ /* �����վ���Ļ�����copy�������;���Ļ�����, �����߲���ģʽ���ܲ�һ��,
+ ����accessʹ��Э��ջģʽ, ��forwardʹ��marsioģʽ,
+ mbuff����ֱ�Ӹ���, ������һ��malloc/memcpy/free�Ĺ���.
+ */
+ send_device_handle->low_level_mbuff_data_append(send_mbuff, unsend_raw_data_ptr, unsend_raw_data_len);
+
+ /* ָ����ǰ�ƶ�, Ԥ��vxlan���ռ� */
+ send_buf_data_ptr = (char *)send_device_handle->low_level_mbuff_data_forward(send_mbuff, FLWD_VXLAN_OUTER_PACKET_LEN);
+
+ /* ����ײ�vxlan��Ϣ, ���迼�Ƿ������, ��Ϊ�����ڲ���Ԫ��hash����, vxlan����ַ����·��Ѱַ���� */
+
+#if FLWD_NO_ACTIVE_ARP_QUERY
+ local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ unsigned char remote_fwd_gateway_mac[6] = {0x0c, 0xc4,0x7a,0x14,0x6f,0x5a}; /* 10.0.6.203 */
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_fwd_gateway_mac, send_buf_data_ptr);
+#else
+ if(send_device_handle->io_para.cap_mode != CAP_MODEL_SOCKET){ /* ��socketģʽ����Ҫ����vxlan����ethernet�� */
+ local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+
+ ip_union.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ ip_union.addr_ipv4 = nat_info->flwd_route_info.next_gateway_ip_net;
+
+ if(memcmp(nat_info->flwd_route_info.next_gateway_mac, flwd_global_val.zero_mac_addr, 6) == 0){
+ /* �˴�������MAC���浽nat_info, ����ÿ�ζ���arp�� */
+ ret = flwd_arp_table_query(nat_info->tid, &ip_union, send_device_handle, nat_info->flwd_route_info.next_gateway_mac);
+ if(ret < 0){
+ send_device_handle->low_level_mbuff_free(send_device_handle, tid, send_mbuff);
+ flwd_log(30, "arp query %s, but not found!\n", flwd_ipt_ntop_r(&ip_union, ip_str, 64));
+ return NULL;
+ }
+ }
+
+ /* ���ݻ�ԾIP�IJ���ʱ��gdevIP, ��ѯGDEV��MAC, ����ethernet header */
+ unsigned char *remote_fwd_gateway_mac = nat_info->flwd_route_info.next_gateway_mac;
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_fwd_gateway_mac, send_buf_data_ptr);
+ }
+
+#endif
+
+ /* NOTE, ��ʹ��socketģʽ, ����Ҫ����ײ�vxlanԭʼ��, ��DIP, PORT���ܶ���һ��, ����Щֵ���Ƿ�װ�����ݰ���, ��dl_io_send�Ӱ���ȡ */
+#if FLWD_NO_GDEV_ENV
+ flwd_sendpacket_build_ipv4(unsend_raw_data_len + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t), /* �ڲ�ԭʼ�� + UDP��ͷ + vxlanͷ */
+ 0,
+ 0x1234,
+ 0,
+ 64,
+ IPPROTO_UDP,
+ send_device_handle->io_para.device_ip_net_order,
+ nat_info->flwd_route_info.next_gateway_ip_net,
+ NULL,
+ 0,
+ (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t));
+#else
+ flwd_sendpacket_build_ipv4(unsend_raw_data_len + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t), /* �ڲ�ԭʼ�� + UDP��ͷ + vxlanͷ */
+ 0,
+ 0x1234,
+ 0,
+ 64,
+ IPPROTO_UDP,
+ 0x0100007F, /* ����socket */
+ 0x0100007F, /* ����socket */
+ NULL,
+ 0,
+ (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t));
+#endif
+
+ flwd_sendpacket_build_udp(unsend_raw_data_len + sizeof(flwd_vxlan_hdr_t),
+ htons(50000 + tid), /* TODO, �˴���sport�����ڲ��sport, �ڲ�sport��ȫ��ʶ��ij���������ص�, vxlan��sport�������� */
+ htons(60000 + tid),
+ NULL,
+ 0,
+ send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t));
+
+ if(CAP_MODEL_SOCKET != send_device_handle->io_para.cap_mode){ /* socketģʽ�ײ���Э��ջ��װ, У�����Э��ջʵ�� */
+ flwd_sendpacket_do_checksum((char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t),
+ IPPROTO_IP,
+ sizeof(flwd_ipv4_hdr_t));
+ }
+
+ outer_vxlan_hdr = (flwd_vxlan_hdr_t *)(send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+ memset(outer_vxlan_hdr, 0, sizeof(flwd_vxlan_hdr_t));
+ outer_vxlan_hdr->link_id = nat_info->flwd_route_info.gdev_args.link_id;
+ outer_vxlan_hdr->link_layer_type = 0; /* 0:ethernet; */
+ outer_vxlan_hdr->dir = nat_info->flwd_route_info.gdev_args.this_ip_as_sip_route_dir;
+ if(FLWD_OUTOPT_FIRST_PKT == (out_opt & FLWD_OUTOPT_FIRST_PKT)){
+ outer_vxlan_hdr->first_pkt_per_stream = 1;
+ }
+
+ inner_eth_hdr = (flwd_eth_hdr_t *)(send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t));
+ memcpy(inner_eth_hdr->h_source, nat_info->flwd_route_info.gdev_args.inner_raw_smac, 6);
+ memcpy(inner_eth_hdr->h_dest , nat_info->flwd_route_info.gdev_args.inner_raw_dmac, 6);
+
+ if(FLWD_IP_ADDR_TYPE_V4 == nat_info->inner_nat_tuple5.addr_type){
+ inner_eth_hdr->h_proto = htons(ETH_P_IP);
+ }else{
+ inner_eth_hdr->h_proto = htons(ETH_P_IPV6);
+ }
+
+ return send_mbuff;
+}
+
+static void * flwd_acc_to_user_pre_output(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_nat_info_t *nat_info,
+ flwd_raw_pkt_t *raw_pkt, unsigned int out_opt)
+{
+ flwd_vxlan_hdr_t *outer_vxlan_dr;
+
+ const char *unsend_raw_data_ptr = raw_pkt->inner_pkt_data; /* ��ָ����flwd_acc_fwd_pkt_input()����, �Ѿ�ָ�����ڲ�ethernetͷ�� */
+ int unsend_raw_data_len = raw_pkt->inner_pkt_len;
+ void *send_mbuff = send_device_handle->low_level_mbuff_malloc(send_device_handle, tid, unsend_raw_data_len + FLWD_VXLAN_OUTER_PACKET_LEN);
+ char *send_buf_data_ptr;
+
+ /* �����վ���Ļ�����copy�������;���Ļ�����, �����߲���ģʽ���ܲ�һ��, ����ֱ�Ӹ���, ������һ��malloc/memcpy/free�Ĺ��� */
+ send_buf_data_ptr = send_device_handle->low_level_mbuff_data_append(send_mbuff, unsend_raw_data_ptr, unsend_raw_data_len);
+
+#if FLWD_NO_ACTIVE_ARP_QUERY
+ /* û��ARP��̬��ѯ�Ĺ���ʱ, �ֹ����²����ն˵�mac */
+ unsigned char *local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ unsigned char *remote_user_mac = nat_info->flwd_route_info.inner_terminal_mac;
+
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_user_mac, send_buf_data_ptr);
+#else
+ /* û��ARP��̬��ѯ�Ĺ���ʱ, �ֹ����²����ն˵�mac */
+ unsigned char *local_acc_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ unsigned char *remote_user_mac = nat_info->flwd_route_info.inner_terminal_mac;
+
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_acc_gateway_mac, remote_user_mac, send_buf_data_ptr);
+#endif
+
+ return send_mbuff;
+}
+
+
+/*
+ TODO:
+ ��ϵͳ����������������ʵ��L2TP, PPTP��������,
+ ��Iptables ��ppp�������һ������ָ��(�ض���)��һ��tap�豸,
+ ����, tap�豸�Ķ�ȡ��(��������), ���ܿ��������ڲ���ip��,
+ �յ�ip�����acc-userһ���Ĵ�������.
+
+ ����:
+ acc-userֻ��һ��io_handle, Ŀǰ��pcap, marsio, socket, ��tap,
+ ������pcap��tap�ľ�����Բ�һ��,
+
+ �����ʽ:
+ 1, һ��Flowood_IO���(�ĸ�����, acc-user, acc-fwd, fwd-acc, fwd-gdev), �ɶ�Ӧ�������IO���,
+ ��acc-user�����IO�����������������IO���, ��������ͬ�Ľ��뷽ʽ: pcap, l2tp_tap, pptp_tap,
+ �����������Ľ����ij�;
+
+ 2, ����Ǹ���һ������, ������������Ƕ��, ��ʵ�ʴ�һ����������;
+ ��acc-user, acc-fwd����һ���������ӵ�������,
+ Flowood���������, ��ʵ��������һ��, ��ʱӦ�ÿ���ͬ��IP��������,
+ ��һ���������IP��ַ, �����ݰ���dip�����ĸ���acc-user�İ�, �ĸ���acc-fwd�İ�.
+
+*/
+
+static int flwd_access_output(flwd_device_handle_t *rcv_device_handle, int tid,
+ flwd_nat_info_t *nat_info, flwd_raw_pkt_t *raw_pkt, unsigned int out_opt)
+{
+ int ret;
+ flwd_device_handle_t *send_device_handle;
+ void *send_mbuff ;
+ const char *send_actual_ptr;
+ char debug_outer_tuple4[128];
+
+ /*
+ TODO,
+
+ ACC��USERת������ʱ, �������ͨIPЭ��ջ, ����ͨ��low_level_io_send()ֱ�ӽ�������ȥ,
+ ���п��ܻ���PPTP����, ��ʱ�����ݰ������ڲ����һ����, ���PPP��װ��Ҫ��VPN�������,
+ ��Ҫע�����������, ������ͨ���ײ�IO�ӿ�ֱ�ӷ��ͳ�����.
+
+ Ӧ�������ֵײ������ӿ�, ���pcap, marsio, socket��ϵͳ��ʽ,
+ �߼��ӿ�, ��һ������������IP, ���������߼�����,
+ ������L2TP, PPTP������, ��ԭʼ�������յ�PPP�İ���, ���ջ�������ڲ�IP��,
+
+ ��������߼�����һ�Զ�Ĺ�ϵ, ��ʹ����һ���ӿ�, Ҳ���������һ���߼���,
+ flowood������߼������ͨ��, ����ֱ�Ӷ�������.
+ */
+
+ if(TOPO_ACC_LINK_USER == rcv_device_handle->io_para.topo_mode){
+ send_device_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_FWD];
+ send_mbuff = flwd_acc_to_fwd_pre_output(rcv_device_handle, send_device_handle, tid, nat_info, raw_pkt, out_opt);
+ if(NULL == send_mbuff){
+ return -1;
+ }
+ ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff);
+ if(ret < 0){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(30, "ACC: send pkt to forward gateway error! inner_tuple4 is:%s, outer_tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+FLWD_VXLAN_OUTER_PACKET_LEN+sizeof(flwd_eth_hdr_t), tid),
+ flwd_debug_print_tuple4_detail_r(send_actual_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128));
+ }else{
+ if(flwd_cfg_val.flwd_log_level <= 10){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(10, "ACC: send pkt to forward gateway succ, inner_tuple4 is:%s, outer_tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+FLWD_VXLAN_OUTER_PACKET_LEN+sizeof(flwd_eth_hdr_t), tid),
+ flwd_debug_print_tuple4_detail_r(send_actual_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128));
+ }
+ }
+
+ }else{
+ send_device_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_USER];
+ send_mbuff = flwd_acc_to_user_pre_output(rcv_device_handle, send_device_handle, tid, nat_info, raw_pkt, out_opt);
+ ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff);
+ if(ret < 0){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(30, "ACC: send pkt to user client error! tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+sizeof(flwd_eth_hdr_t), tid));
+ }else{
+ if(flwd_cfg_val.flwd_log_level <= 10){
+ send_actual_ptr = (char *)rcv_device_handle->low_level_mbuff_mtod(send_mbuff);
+ flwd_log(10, "ACC: send pkt to user client succ! tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(send_actual_ptr+sizeof(flwd_eth_hdr_t), tid));
+
+ }
+ }
+ }
+
+ send_device_handle->low_level_mbuff_free_after_send(send_device_handle, tid, send_mbuff);
+
+ return ret;
+}
+
+
+/*
+ ���ӽ�����, �ͷ�ռ�û�ԾIP��Դ�˿�.
+*/
+static void flwd_sport_recycle(flwd_nat_info_t *nat_info)
+{
+ /* ����nat����, snat����outer->tuple5��sip, ����ʵ����ԴIP;
+ dnatû�ж��������Դ, ֻ�Ǽ򵥵Ľ�virtual_dip:virtual_dport�ij���real_dip:real_dport.
+ */
+ MESA_list_count_t *usable_sport_queue_head;
+ MESA_list_count_t *recycle_node;
+ unsigned char *ip_key;
+ unsigned int ip_key_size;
+ MESA_htable_handle act_ip_htable;
+ int tid = nat_info->tid;
+ const flwd_tuple5_t *recycle_tuple5;
+ unsigned short recycle_sport;
+ char ip_str[64];
+
+ if(FLWD_NAT_TYPE_DNAT == nat_info->nat_type){
+ return; /* nothing to do */
+ }
+
+ if(FLWD_NAT_TYPE_SNAT == nat_info->nat_type){
+ recycle_tuple5 = &nat_info->outer_nat_tuple5;
+ }
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == nat_info->inner_nat_tuple5.addr_type)){
+ if(FLWD_ACT_IP_DYNAMIC == nat_info->act_ip_origin){
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_dynamic_htable[FLWD_IP_ADDR_TYPE_V4][nat_info->act_ip_region];
+ }else{
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_static_htable[FLWD_IP_ADDR_TYPE_V4][nat_info->act_ip_region];
+ }
+
+ if(recycle_tuple5->dir_reverse){
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v4.dip_net_order;
+ recycle_sport = recycle_tuple5->dport_net_order;
+ }else{
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v4.sip_net_order;
+ recycle_sport = recycle_tuple5->sport_net_order;
+ }
+ ip_key_size = sizeof(int);
+ }else{ /* IPv6 */
+ if(FLWD_ACT_IP_DYNAMIC == nat_info->act_ip_origin){
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_dynamic_htable[FLWD_IP_ADDR_TYPE_V6][nat_info->act_ip_region];
+ }else{
+ act_ip_htable = flwd_thread_val[tid].flwd_ip_pool_static_htable[FLWD_IP_ADDR_TYPE_V6][nat_info->act_ip_region];
+ }
+
+ if(recycle_tuple5->dir_reverse){
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v6->dip_net_order;
+ recycle_sport = recycle_tuple5->dport_net_order;
+ }else{
+ ip_key = (unsigned char *)&recycle_tuple5->ippair_v6->sip_net_order;
+ recycle_sport = recycle_tuple5->sport_net_order;
+ }
+ ip_key_size = sizeof(struct in6_addr);
+ }
+
+ if(sizeof(int) == ip_key_size){
+ inet_ntop(AF_INET, ip_key, ip_str, 64);
+ }else{
+ inet_ntop(AF_INET6, ip_key, ip_str, 64);
+ }
+
+ pthread_rwlock_wrlock(&flwd_thread_val[tid].flwd_ip_pool_static_rwlock);
+
+ flwd_active_ip_t *flwd_active_ip = (flwd_active_ip_t *)flwd_ip_pool_search(nat_info->act_ip_origin, act_ip_htable, ip_key, ip_key_size);
+ if(NULL == flwd_active_ip){
+ /* NOTE: �������ڼ�˻�ԾIP�Ѿ���ʱ��maat_callback�Ƴ�, Ҳ�Ͳ��ػ��ն˿�, ֱ�ӷ��ؼ��� */
+ flwd_log(20, "ACC:sport %u recycle, but active ip:%s is not exist!\n", recycle_sport, ip_str);
+ goto done;
+ }
+
+ if(IPPROTO_TCP == nat_info->inner_nat_tuple5.protocol){ /* TCP, UDP������ */
+ usable_sport_queue_head = &flwd_active_ip->usable_tcp_sport_list_head;
+ }else{
+ usable_sport_queue_head = &flwd_active_ip->usable_udp_sport_list_head;
+ }
+
+ /* NOTE: ȡ���ö˿�ʱ�ֳ�free��MESA_list_count_t�����ṹ, �˴�Ҳ���ֳ�malloc */
+ recycle_node = (MESA_list_count_t *)malloc(sizeof(MESA_list_count_t));
+ memcpy(&recycle_node->quiddity, &recycle_sport, sizeof(short));
+ /* �˴�ʹ��MESA_list_count_add_tail, ����head->pre, ���ʹ�� */
+ MESA_list_count_add_tail(usable_sport_queue_head, recycle_node);
+
+done:
+ pthread_rwlock_unlock(&flwd_thread_val[tid].flwd_ip_pool_static_rwlock);
+
+ flwd_log(10, "ACC:sport recycle, active_ip:%s, port:%u\n", ip_str, recycle_sport);
+
+ return;
+}
+
+
+static void flwd_access_nat_htable_data_free(void *data)
+{
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)data;
+
+ if(--nat_info->reference > 0){
+ /* ����key����ͬһ��nat_info, ɾ��ʱ����double free, ����reference���� */
+ return;
+ }
+
+ flwd_sport_recycle(nat_info);
+
+ if(FLWD_IP_ADDR_TYPE_V6 == nat_info->inner_nat_tuple5.addr_type ){
+ flwd_free(nat_info->tid, nat_info->inner_nat_tuple5.ippair_v6);
+ }
+
+ if(FLWD_IP_ADDR_TYPE_V6 == nat_info->outer_nat_tuple5.addr_type ){
+ flwd_free(nat_info->tid, nat_info->outer_nat_tuple5.ippair_v6);
+ }
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ ltsm_destroy_handle(nat_info->ltsm_stat_handle);
+#endif
+
+ flwd_free(nat_info->tid, data);
+}
+
+static int flwd_access_nat_htable_data_expire_notify(
+ void *data, int eliminate_type)
+{
+ char str_tmp[256];
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)data;
+
+ if(1 == nat_info->reference){ /* ��Ϊͬʱ������key����, ֻ���һ�μ�¼��־, �����д����һ������־ */
+ flwd_log(10, "pre-nat-tuple4 %s expire!\n",
+ flwd_tuple5_ntop_r(&nat_info->inner_nat_tuple5, str_tmp, 256));
+ }
+
+ return 1;
+}
+
+
+
+/*
+ natת����������, ��һ�δ���nat_infoʱ������,
+ �洢·��ת�������Ϣ, ����ÿ��ת��ʱ����ѯһ��.
+*/
+static int flwd_save_session_route_info(flwd_nat_info_t *nat_info,
+ flwd_raw_pkt_t *raw_pkt, flwd_active_ip_port_args_t *usable_active_ipport_args)
+{
+ const flwd_eth_hdr_t *ehdr = (flwd_eth_hdr_t *)raw_pkt->outer_pkt_data;
+ int ret;
+
+ if(FLWD_NAT_TYPE_SNAT == nat_info->nat_type){
+ /* user�ն˵�MAC���ò�ѯ, ֱ��ʹ�õ�ǰ������mac�洢�������� */
+ memcpy(nat_info->flwd_route_info.inner_terminal_mac, ehdr->h_source, ETH_ALEN);
+ /*
+ TODO:
+ ��εõ���һ��ת�����ص�IP, ��ת������IP?
+ ������ͬһ���ֵ�������豸������ͨ��, ��ѡһ���Ϳ���,
+ ��������ɵ�����,
+ �����֪��GDEV�ķ����㷨�����.
+ */
+#if 0
+ nat_info->flwd_route_info.next_gateway_ip_net = flwd_search_fwd_ip_by_gdev_ip(usable_active_ipport_args->gdev_args.gdev_ip_net_order);
+#else
+ /* TODO, ��̨����, ��д��, ʹ�ñ��ػػ� */
+ inet_pton(AF_INET, "127.0.0.1", &nat_info->flwd_route_info.next_gateway_ip_net);
+#endif
+
+ memcpy(&nat_info->flwd_route_info.gdev_args,
+ &usable_active_ipport_args->gdev_args,
+ sizeof(flwd_gdev_associated_args_t));
+ }else{
+ /* TODO, DNAT */
+ abort();
+ }
+
+ return 0;
+}
+
+
+/*
+ NOTE:
+
+ HASH����ʱ,
+ ��ΪSNAT->C2S����, SNAT->S2C����, DNAT->C2S����, DNAT->S2C����,
+ ��������ĵ�ַ��ͬ,
+ ����, ����һ�����ӵ��ڲ���ַ���ⲿ��ַ��˵, Ҫ��������key, ָ��ͬһ��nat_info.
+
+ hash����ʱ, ����ͬһ��nat_info, ʹ��������ͬ��key����.
+
+ ����:
+ 192.168.10.100:12345->8.8.8.8:53����һ��DNS��ѯ,
+ ��NAT���غ�����:
+ 202.43.148.189:34567->8.8.8.8:53,
+
+ Ҫ������������ͬ����Ԫ��ֱ���Ϊkey, �����ҵ�ͬһ��htable���data, ��nat_info.
+*/
+static int flwd_new_nat_session_sotre(int tid, flwd_nat_info_t *nat_info)
+{
+ int ret;
+ char inner_str[256], outer_str[256];
+
+ ret = MESA_htable_add(flwd_thread_val[tid].nat_info_table,
+ (unsigned char *)&nat_info->inner_nat_tuple5,
+ sizeof(flwd_tuple5_t),
+ nat_info);
+ if(ret < 0){
+ flwd_log(30, "save nat session error, %s!\n",
+ flwd_tuple5_ntop_r(&nat_info->inner_nat_tuple5, inner_str, 256));
+ nat_info->reference = 1;
+ flwd_access_nat_htable_data_free(nat_info);
+ return -1;
+ }
+ nat_info->reference++;
+
+ ret = MESA_htable_add(flwd_thread_val[tid].nat_info_table,
+ (unsigned char *)&nat_info->outer_nat_tuple5,
+ sizeof(flwd_tuple5_t),
+ nat_info);
+ if(ret < 0){
+ nat_info->reference = 1;
+ flwd_log(30, "save nat session error, %s!\n",
+ flwd_tuple5_ntop_r(&nat_info->outer_nat_tuple5, outer_str, 256));
+ /* NOTE: ����ʧ��, �˴�Ҫʹ��inner��key, ��Ϊouter����ʧ�� */
+ MESA_htable_del(flwd_thread_val[tid].nat_info_table,
+ (unsigned char *)&nat_info->inner_nat_tuple5,
+ sizeof(flwd_tuple5_t),
+ NULL);
+ return -1;
+ }
+ nat_info->reference++;
+
+ return 0;
+}
+
+
+static inline flwd_nat_info_t *flwd_create_new_nat_info_v4(int tid,
+ flwd_nat_type_t nat_type, flwd_tuple5_t *inner_nat_key,
+ flwd_active_ip_port_args_t *usable_active_ipport_args, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)flwd_calloc(tid, 1, sizeof(flwd_nat_info_t));
+ flwd_tuple5_t *opposite_tuple5;
+ int differ;
+ unsigned int outer_actual_dip_net_order; /* �ͻ���ȥ����ʵ��Ŀ��IP, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+ unsigned int outer_actual_dport_net_order; /* �ͻ���ȥ����ʵ��Ŀ��˿�, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+
+ nat_info->tid = tid; /* ��Ҫ����htable�ص������ڲ���tid�������� */
+ nat_info->nat_type = nat_type;
+
+ if(FLWD_NAT_TYPE_SNAT == nat_type){
+ /************************** ���� inner tuple5 **************************/
+ memcpy(&nat_info->inner_nat_tuple5, inner_nat_key, sizeof(flwd_tuple5_t)); /* snat��inner tuple5ֱ��copy */
+
+
+ /*************************** ����outer tuple5 **************************/
+ opposite_tuple5 = &nat_info->outer_nat_tuple5;
+
+ if(inner_nat_key->dir_reverse){
+ outer_actual_dip_net_order = inner_nat_key->ippair_v4.sip_net_order;
+ outer_actual_dport_net_order = inner_nat_key->sport_net_order;
+ }else{
+ outer_actual_dip_net_order = inner_nat_key->ippair_v4.dip_net_order;
+ outer_actual_dport_net_order = inner_nat_key->dport_net_order;
+ }
+
+ /* NOTE: �����޷��������Ƚϴ�С, һ��Ҫֱ�ӱȽ�, ������ c = a - b; if(c < 0)�ķ�ʽ!!! */
+ if(usable_active_ipport_args->act_sip_net_order.addr_ipv4 > outer_actual_dip_net_order){
+ /* �ⲿ��ַ����ʵԴIP�Ǹ�ѡ��Ļ�ԾIP, ��ʵĿ��IP���ǵ�ǰinner_key��Ŀ��ip */
+ opposite_tuple5->ippair_v4.sip_net_order = usable_active_ipport_args->act_sip_net_order.addr_ipv4;
+ opposite_tuple5->ippair_v4.dip_net_order = outer_actual_dip_net_order;
+ opposite_tuple5->sport_net_order = usable_active_ipport_args->act_sport_net_order;
+ opposite_tuple5->dport_net_order = outer_actual_dport_net_order;
+
+ opposite_tuple5->dir_reverse = 0; /* �洢��key����ʵ��Ԫ���ַ��һ���� */
+ }else if(usable_active_ipport_args->act_sip_net_order.addr_ipv4 < outer_actual_dip_net_order){
+ opposite_tuple5->ippair_v4.sip_net_order = outer_actual_dip_net_order;
+ opposite_tuple5->ippair_v4.dip_net_order = usable_active_ipport_args->act_sip_net_order.addr_ipv4;
+ opposite_tuple5->sport_net_order = outer_actual_dport_net_order;
+ opposite_tuple5->dport_net_order = usable_active_ipport_args->act_sport_net_order;
+
+ opposite_tuple5->dir_reverse = 1; /* �洢��key����ʵ��Ԫ���ַ���෴�� */
+ }else{
+ /* inner��outer��IP��ַ��ͬ, ��������IP����ϵͳ���Dz����ܵ�!!! */
+ abort();
+ }
+
+ opposite_tuple5->addr_type = inner_nat_key->addr_type; /* TODO, Ԥ��6to4��ַת������?? */
+ opposite_tuple5->protocol = inner_nat_key->protocol;
+
+ /* TODO, ����ѡ��Ļ�ԾIP, �������, ȷ��Ӧ�ô��ĸ�FWD���� */
+ ////nat_info->next_hop_ip_net_order = flwd_search_fwd_ip_by_gdev_ip(usable_active_ipport_args->related_gdev_ip_net_order);
+ }else{
+#if FLWD_SUPPORT_DNAT
+ /* TODO,
+ DNATֻ����滻dip, dport����, ���ÿ�����ô��ѡ�˿�, �˿ڸ�������,
+ ��Ϊ����һ���������, ��ʵԴIP,Դport�Ѿ�������������Э��ջ��֤�޳�ͻ��.
+ */
+ assert(0);
+#endif
+ }
+
+ flwd_save_session_route_info(nat_info, raw_pkt, usable_active_ipport_args);
+
+ return nat_info;
+}
+
+
+static inline flwd_nat_info_t *flwd_create_new_nat_info_v6(int tid,
+ flwd_nat_type_t nat_type, flwd_tuple5_t *inner_tuple5_v6,
+ flwd_active_ip_port_args_t *usable_active_ipport_args, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_nat_info_t *nat_info = (flwd_nat_info_t *)flwd_calloc(tid, 1, sizeof(flwd_nat_info_t));
+ flwd_tuple5_t *opposite_tuple5;
+ int differ;
+ struct in6_addr outer_actual_dip_net_order; /* �ͻ���ȥ����ʵ��Ŀ��IP, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+ unsigned int outer_actual_dport_net_order; /* �ͻ���ȥ����ʵ��Ŀ��˿�, inner��outer��һ����, ����key�Ĵ洢λ��, ��sip,dip�Ĵ�С��ϵ���ܲ�һ�� */
+
+ nat_info->tid = tid; /* ��Ҫ����htable�ص������ڲ���tid�������� */
+ nat_info->nat_type = nat_type;
+
+ nat_info->inner_nat_tuple5.ippair_v6 = (flwd_ippair_v6_t *)flwd_malloc(tid, sizeof(flwd_ippair_v6_t));
+ nat_info->outer_nat_tuple5.ippair_v6 = (flwd_ippair_v6_t *)flwd_malloc(tid, sizeof(flwd_ippair_v6_t));
+
+ if(FLWD_NAT_TYPE_SNAT == nat_type){
+ /********* ���� inner tuple5 ******/
+ memcpy(&nat_info->inner_nat_tuple5, inner_tuple5_v6, sizeof(flwd_tuple5_t)); /* snat��inner tuple5ֱ��copy */
+ memcpy(nat_info->inner_nat_tuple5.ippair_v6, inner_tuple5_v6->ippair_v6, sizeof(flwd_ippair_v6_t));
+
+ opposite_tuple5 = &nat_info->outer_nat_tuple5;
+ /********* ����outer tuple5 ******/
+
+ if(inner_tuple5_v6->dir_reverse){
+ outer_actual_dip_net_order = inner_tuple5_v6->ippair_v6->sip_net_order;
+ outer_actual_dport_net_order = inner_tuple5_v6->sport_net_order;
+ }else{
+ outer_actual_dip_net_order = inner_tuple5_v6->ippair_v6->dip_net_order;
+ outer_actual_dport_net_order = inner_tuple5_v6->dport_net_order;
+ }
+
+ differ = memcmp(&usable_active_ipport_args->act_sip_net_order.addr_ipv6, &outer_actual_dip_net_order, sizeof(struct in6_addr)) ;
+ if(differ > 0){ /* �ⲿ��ַ����ʵԴIP�Ǹ�ѡ��Ļ�ԾIP, ��ʵĿ��IP���ǵ�ǰinner_key��Ŀ��ip */
+ memcpy(&opposite_tuple5->ippair_v6->sip_net_order, &usable_active_ipport_args->act_sip_net_order.addr_ipv6, sizeof(struct in6_addr));
+ memcpy(&opposite_tuple5->ippair_v6->dip_net_order, &outer_actual_dip_net_order, sizeof(struct in6_addr));
+ opposite_tuple5->sport_net_order = usable_active_ipport_args->act_sport_net_order;
+ opposite_tuple5->dport_net_order = outer_actual_dport_net_order;
+
+ opposite_tuple5->dir_reverse = 0; /* �洢��key����ʵ��Ԫ���ַ��һ���� */
+ }else if(differ < 0){
+ memcpy(&opposite_tuple5->ippair_v6->sip_net_order, &outer_actual_dip_net_order, sizeof(struct in6_addr));
+ memcpy(&opposite_tuple5->ippair_v6->dip_net_order, &usable_active_ipport_args->act_sip_net_order.addr_ipv6, sizeof(struct in6_addr));
+ opposite_tuple5->sport_net_order = outer_actual_dport_net_order;
+ opposite_tuple5->dport_net_order = usable_active_ipport_args->act_sport_net_order;
+
+ opposite_tuple5->dir_reverse = 1; /* �洢��key����ʵ��Ԫ���ַ���෴�� */
+ }else{
+ /* inner��outer��IP��ַ��ͬ, ��������flowoodϵͳ���Dz����ܵ�!!! */
+ abort();
+ }
+
+ opposite_tuple5->addr_type = inner_tuple5_v6->addr_type; /* TODO, Ԥ��6to4��ַת������, �ⲿ��ַ�����Ǹ��ݲ��Եõ�, ��һ���ǹ̶���ipv4תipv4 */
+ opposite_tuple5->protocol = inner_tuple5_v6->protocol;
+
+ ////nat_info->next_hop_ip_net_order = flwd_search_fwd_ip_by_gdev_ip(usable_active_ipport_args->related_gdev_ip_net_order); /* TODO, ����ѡ��Ļ�ԾIP, �������, ȷ��Ӧ�ô��ĸ�FWD���� */
+
+ }else{
+#if FLWD_SUPPORT_DNAT
+ assert(0);
+#endif
+ }
+
+ flwd_save_session_route_info(nat_info, raw_pkt, usable_active_ipport_args);
+
+ return nat_info;
+}
+
+
+
+static flwd_nat_info_t *flwd_create_new_nat_info(int tid,
+ flwd_nat_type_t nat_type, flwd_tuple5_t *inner_nat_key,
+ flwd_active_ip_port_args_t *usable_active_ipport_args, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_nat_info_t *nat_info;
+
+ if(flwd_likely(FLWD_IP_ADDR_TYPE_V4 == inner_nat_key->addr_type)){
+ nat_info = flwd_create_new_nat_info_v4(tid, nat_type, inner_nat_key,
+ usable_active_ipport_args, raw_pkt);
+ }else{
+ nat_info = flwd_create_new_nat_info_v6(tid, nat_type, inner_nat_key,
+ usable_active_ipport_args, raw_pkt);
+ }
+
+ if(FLWD_IP_REGION_INLAND == usable_active_ipport_args->dip_region_type){
+ nat_info->act_ip_region = FLWD_IP_REGION_OUTLAND;
+ }else{
+ nat_info->act_ip_region = FLWD_IP_REGION_INLAND;
+ }
+
+ nat_info->nat_type = nat_type;
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ nat_info->ltsm_stat_handle = ltsm_create_handle();
+#endif
+ return nat_info;
+}
+
+
+
+static flwd_nat_info_t * flwd_new_nat_session(flwd_device_handle_t *device_handle,
+ int tid, flwd_tuple5_t *nat_key, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+ flwd_nat_info_t *nat_info = NULL;
+ flwd_active_ip_port_args_t usable_active_ipport_args;
+ flwd_actual_ip_port_t actual_ipport_net_order;
+
+ memset(&usable_active_ipport_args, 0, sizeof(flwd_active_ip_port_args_t));
+
+ usable_active_ipport_args.dip_region_type = flwd_dstip_location(nat_key); /* �鿴Ŀ��IP��������λ�� */
+ usable_active_ipport_args.tid = tid;
+ usable_active_ipport_args.nat_key = nat_key;
+ usable_active_ipport_args.protocol = nat_key->protocol;
+
+ if(TOPO_ACC_LINK_USER == device_handle->io_para.topo_mode){
+ /* ACC_LINK�ӿ�, NATת����������, �϶���SNAT���װ�, �Ȳ���NAT���ò��� */
+ ret = flwd_access_snat_search_policy(tid, nat_key, &usable_active_ipport_args);
+ if(0 == ret){
+ /* �޲���, ��dynamic-ip-pool�������ѡһ��IP */
+ ret = flwd_access_snat_fetch_usable_ip_from_pool(flwd_thread_val[tid].flwd_ip_pool_dynamic_htable[nat_key->addr_type][(int)usable_active_ipport_args.dip_region_type ^ 1],
+ &flwd_thread_val[tid].flwd_ip_pool_dynamic_rwlock,
+ tid, nat_key, &usable_active_ipport_args);
+ if(ret < 0){
+ flwd_log(RLOG_LV_INFO, "tuple4 %s not hit any policy, but no according usable active ip in %s dynamic pool !\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+
+ if(flwd_cfg_val.use_static_pool_ip_if_no_dynamic != 0){
+ ret = flwd_access_snat_fetch_usable_ip_from_pool(flwd_thread_val[tid].flwd_ip_pool_static_htable[nat_key->addr_type][(int)usable_active_ipport_args.dip_region_type ^ 1],
+ &flwd_thread_val[tid].flwd_ip_pool_static_rwlock,
+ tid, nat_key, &usable_active_ipport_args);
+ if(ret < 0){
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s not hit any policy, but no according usable ip in all %s static and dynamic pool!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }else{
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s not hit any policy, but no according usable active ip in %s dynamic pool, unfortunately 'use_static_pool_ip_if_no_dynamic' is disable!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }
+ }else if(-1 == ret){
+ if(flwd_cfg_val.use_dynamic_pool_ip_if_no_static != 0){
+ ret = flwd_access_snat_fetch_usable_ip_from_pool(flwd_thread_val[tid].flwd_ip_pool_static_htable[nat_key->addr_type][(int)usable_active_ipport_args.dip_region_type ^ 1],
+ &flwd_thread_val[tid].flwd_ip_pool_static_rwlock,
+ tid, nat_key, &usable_active_ipport_args);
+ if(ret < 0){
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s hit policy, but no according usable ip in all %s static and dynamic pool!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }else{
+ flwd_log(RLOG_LV_FATAL, "tuple4 %s hit policy, but no according usable ip in %s static pool, unfortunately 'use_dynamic_pool_ip_if_no_static' is disable!\n",
+ flwd_tuple5_ntop(tid, nat_key),
+ flwd_ip_region_ntop((int)usable_active_ipport_args.dip_region_type ^ 1));
+ return NULL;
+ }
+ }
+
+ nat_info = flwd_create_new_nat_info(tid, FLWD_NAT_TYPE_SNAT, nat_key,
+ &usable_active_ipport_args, raw_pkt);
+
+ flwd_log(RLOG_LV_DEBUG, "---before signature, tuple4:%s",
+ flwd_tuple5_ntop(tid, &nat_info->outer_nat_tuple5));
+ flwd_acc_user_generate_pkt_signature(tid, nat_info, raw_pkt);
+ flwd_log(RLOG_LV_DEBUG, "---after signature, tuple4:%s",
+ flwd_tuple5_ntop(tid, &nat_info->outer_nat_tuple5));
+
+ }else if(TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode){
+ /* FWD���������װ�, ˵����DNAT��һ����, ���ݸ��ؾ�����Բ���������ʵ������IP�Ͷ˿� */
+#if FLWD_SUPPORT_DNAT
+ flwd_search_access_dnat_lb_policy(tid, nat_key, &actual_ipport_net_order);
+
+ nat_info = flwd_create_new_nat_info(tid, FLWD_NAT_TYPE_DNAT, nat_key,
+ &usable_active_ipport_args, raw_pkt);
+#endif
+ }
+
+ if(NULL == nat_info){
+#if FLWD_SUPPORT_DNAT
+ assert(0);
+#endif
+ return NULL;
+ }
+
+ if(flwd_new_nat_session_sotre(tid, nat_info) < 0){
+ return NULL;
+ }
+
+ char inner_tuple5_str[256];
+ char outer_tuple5_str[256];
+
+ flwd_log(10, "ACC: create new nat session, inner_tuple4:%s, outer_tuple4:%s\n",
+ flwd_tuple5_ntop_r(&nat_info->inner_nat_tuple5, inner_tuple5_str, 256),
+ flwd_tuple5_ntop_r(&nat_info->outer_nat_tuple5, outer_tuple5_str, 256));
+
+ return nat_info;
+}
+
+/*
+ access����user�հ�, ���nat��������, Ҫ��֤�Ϸ����װ�,
+ ������TCP->SYN, ������UDP��.
+
+ return value:
+ 0 : valid;
+ -1: invalid;
+*/
+static int flwd_acc_user_first_pkt_verify(const char *raw_eth_data)
+{
+ const flwd_eth_hdr_t *flwd_ethhdr = (flwd_eth_hdr_t *)raw_eth_data;
+ const flwd_ipv4_hdr_t *flwd_ip4hdr;
+ const flwd_ipv6_hdr_t *flwd_ip6hdr;
+ unsigned short eth_type = ntohs(flwd_ethhdr->h_proto);
+ const flwd_tcp_hdr_t *flwd_tcphdr;
+ int ret = 0;
+
+ if(ETH_P_IP == eth_type){
+ flwd_ip4hdr = (flwd_ipv4_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ if(TH_SYN == flwd_tcphdr->th_flags){
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else if(ETH_P_IPV6 == eth_type){
+ flwd_ip6hdr = (flwd_ipv6_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip6hdr->ip6_nxt_hdr){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t));
+ if(TH_SYN == flwd_tcphdr->th_flags){
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else{
+ assert(0);
+ }
+
+ return ret;
+}
+
+/*
+ access���ش�fwd�����հ�, ���nat��������, Ҫ��֤�Ϸ����װ�,
+ ������IP���ò���DNAT�е�ip,port;
+ ͬʱ��������TCP->SYN, ������UDP��.
+
+ �����SNAT, �϶�Ӧ�����ҵ�nat����֮ǰ�洢��Ԫ��.
+
+ return value:
+ 0 : valid;
+ -1: invalid;
+*/
+static int flwd_acc_fwd_first_pkt_verify(char *inner_mac_hdr)
+{
+ const flwd_eth_hdr_t *flwd_ethhdr = (flwd_eth_hdr_t *)inner_mac_hdr;
+ const flwd_ipv4_hdr_t *flwd_ip4hdr;
+ const flwd_ipv6_hdr_t *flwd_ip6hdr;
+ unsigned short eth_type = ntohs(flwd_ethhdr->h_proto);
+ const flwd_tcp_hdr_t *flwd_tcphdr;
+ int ret = 0;
+
+ if(ETH_P_IP == eth_type){
+ flwd_ip4hdr = (flwd_ipv4_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip4hdr->ip_p){
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip4hdr + flwd_ip4hdr->ip_hl * 4);
+ if(TH_SYN == flwd_tcphdr->th_flags){ /* ����DNAT��˵ */
+ ret = 0;
+ }if((TH_SYN|TH_ACK) == flwd_tcphdr->th_flags){ /* ����SNAT��˵ */
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else if(ETH_P_IPV6 == eth_type){
+ flwd_ip6hdr = (flwd_ipv6_hdr_t *)((char *)flwd_ethhdr + sizeof(flwd_eth_hdr_t));
+ if(IPPROTO_TCP == flwd_ip6hdr->ip6_nxt_hdr){ /* TODO, IPv6���п��ܰ�������ͷ��, ��ʵ��Ӧ����ôֱ��ȡnext_hdr */
+ flwd_tcphdr = (flwd_tcp_hdr_t *)((char *)flwd_ip6hdr + sizeof(flwd_ipv6_hdr_t));
+ if(TH_SYN == flwd_tcphdr->th_flags){ /* ����DNAT��˵ */
+ ret = 0;
+ }if((TH_SYN|TH_ACK) == flwd_tcphdr->th_flags){ /* ����SNAT��˵ */
+ ret = 0;
+ }else{
+ ret = -1;
+ }
+ }else if(IPPROTO_UDP == flwd_ip4hdr->ip_p){
+ ret = 0;
+ }
+ }else{
+ assert(0);
+ }
+
+ return ret;
+}
+
+/* �ͻ��˽��뷽��IP��, ���߰�ȥ������(��L2TP, PPTP������װ)����ʵ�ͻ����ڲ����ݰ���ں��� */
+int flwd_access_kernal_pkt_input(flwd_device_handle_t *device_handle,
+ int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ void *ip_strategy;
+ flwd_nat_info_t *nat_info;
+ char nat_key_buf[sizeof(flwd_tuple4v6_t)]; /* v4, v6����, ʹ��v6�ռ����� */
+ flwd_tuple5_t nat_key;
+ unsigned char dir_reverse;
+ int ret;
+ int ltsm_stat;
+ unsigned int out_opt = 0;
+
+ ret = flwd_build_tuple4_key(tid, &nat_key, raw_pkt);
+ if(ret < 0){
+ return -1;
+ }
+
+ nat_info = (flwd_nat_info_t *)MESA_htable_search(flwd_thread_val[tid].nat_info_table,
+ (const uchar *)&nat_key, sizeof(flwd_tuple5_t));
+ if(NULL == nat_info){
+ if((TOPO_ACC_LINK_USER == device_handle->io_para.topo_mode)
+ && (flwd_acc_user_first_pkt_verify(raw_pkt->outer_pkt_data) < 0)){
+ return -1;
+ }else if((TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode)
+ && (flwd_acc_fwd_first_pkt_verify(raw_pkt->inner_pkt_data) < 0)){
+ return -1;
+ }
+
+ nat_info = flwd_new_nat_session(device_handle, tid, &nat_key, raw_pkt);
+ if(NULL == nat_info){
+ if(TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode){
+ flwd_log(30, "recv pkt from gdev, but not found nat_info:%s!",
+ flwd_tuple5_ntop(tid, &nat_key));
+ }
+ return -1;
+ }
+ out_opt |= FLWD_OUTOPT_FIRST_PKT;
+ }
+
+ ltsm_stat = flwd_do_nat(device_handle, nat_info, raw_pkt);
+
+ flwd_access_output(device_handle, tid, nat_info, raw_pkt, out_opt);
+
+#if FLWD_USE_LTSM_FOR_QUICK_CLOSE
+ if(FTSM_CLOSED == ltsm_stat){
+ flwd_log(10, "tuple4 %s state is CLOSED, quick destroy nat_info!\n",
+ flwd_tuple5_ntop(tid, &nat_key));
+ MESA_htable_del(flwd_thread_val[tid].nat_info_table,
+ (const uchar *)&nat_key, sizeof(flwd_tuple5_t), NULL);
+ }
+#endif
+
+ return 0;
+}
+
+static void *flwd_access_nat_table_create(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 * 256;
+ MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &flwd_cfg_val.nat_htable_max_num, sizeof(int));
+
+ /* TODO, Ŀǰ���ó�ʱ��̭, ����TCPӦ��������״̬��, TCP������������̭, �����ͷ��ڴ� */
+ MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &flwd_cfg_val.nat_htable_timeout, sizeof(int));
+
+ opt_int = HASH_ELIMINATE_ALGO_LRU;
+ MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_nat_htable_key_cmp, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_nat_htable_key2index, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_COMPLEX_KEY_DUP, (void *)flwd_nat_htable_key_dup, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_COMPLEX_KEY_FREE, (void *)flwd_nat_htable_key_free, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_access_nat_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 *)"./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;
+}
+
+
+/*
+ �������ش�ת�����ط����հ�, ����vxlan��.
+*/
+static int flwd_acc_fwd_pkt_input(flwd_device_handle_t *rcv_device_handle,
+ int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ 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;
+ ret = flwd_access_kernal_pkt_input(rcv_device_handle, tid, raw_pkt);
+
+ return ret;
+}
+
+int flwd_acc_pkt_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ flwd_thread_val[tid].pkt_stat.eth_pkt_num++;
+ flwd_thread_val[tid].pkt_stat.eth_pkt_byte += raw_pkt->outer_pkt_len;
+
+ if(TOPO_ACC_LINK_FWD == device_handle->io_para.topo_mode){
+ ret = flwd_rubbish_pkt_identify(device_handle, raw_pkt, 1);
+ }else{
+ ret = flwd_rubbish_pkt_identify(device_handle, raw_pkt, 0);
+ }
+ if(ret != 0){
+ return 0;
+ }
+
+ ret = flwd_protocol_stack_process(device_handle, tid, raw_pkt);
+ if(ret != 0){
+ return 0;
+ }
+
+ switch((int)device_handle->io_para.topo_mode){
+ case TOPO_ACC_LINK_USER:
+ flwd_log(10, "ACC: recv pkt from user client, tuple4:%s\n",
+ flwd_debug_print_tuple4_detail((char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t), tid));
+ flwd_acc_user_pkt_input(device_handle, tid, raw_pkt);
+ break;
+
+ case TOPO_ACC_LINK_FWD:
+ {
+ char inner_tuple4[128];
+ char outer_tuple4[128];
+ flwd_log(10, "ACC: recv pkt from forward gateway, inner_tuple4:%s, outer_tuple4:%s\n",
+ flwd_debug_print_tuple4_detail_r((char *)raw_pkt->outer_pkt_data + FLWD_VXLAN_OUTER_PACKET_LEN + sizeof(flwd_eth_hdr_t), inner_tuple4, 128),
+ flwd_debug_print_tuple4_detail_r((char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t), outer_tuple4, 128));
+
+ flwd_acc_fwd_pkt_input(device_handle, tid, raw_pkt);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+void *flwd_packet_io_work_thread(void *arg)
+{
+ int ret1, ret2, ret3;
+ int tseq = *((int *)arg);
+ flwd_raw_pkt_t raw_pkt;
+ unsigned long long last_idle_call_in_ms = 0;
+ flwd_device_handle_t *dev_handle;
+ int tot_work_times = 0; /* �ܽ��հ�, idle���� */
+ int success_work_times_in_recent_100 = 0; /* ���100�γɹ��Ĵ��� */
+
+ while(1){
+ dev_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_USER];
+ ret1 = dev_handle->low_level_pkt_recv(dev_handle, tseq, &raw_pkt.low_level_mbuff);
+ if(ret1 >= 0){
+ raw_pkt.outer_pkt_data = dev_handle->low_level_mbuff_mtod(raw_pkt.low_level_mbuff);
+ raw_pkt.outer_pkt_len = dev_handle->low_level_mbuff_get_pkt_len(raw_pkt.low_level_mbuff);
+ flwd_pre_process_pkt_input(dev_handle, &raw_pkt);
+ flwd_acc_pkt_input(dev_handle, tseq, &raw_pkt);
+ dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }
+
+ dev_handle = &flwd_global_val.global_io_handle[TOPO_ACC_LINK_FWD];
+ ret2 = dev_handle->low_level_pkt_recv(dev_handle, tseq, &raw_pkt.low_level_mbuff);
+ if(ret2 >= 0){
+ raw_pkt.outer_pkt_data = dev_handle->low_level_mbuff_mtod(raw_pkt.low_level_mbuff);
+ raw_pkt.outer_pkt_len = dev_handle->low_level_mbuff_get_pkt_len(raw_pkt.low_level_mbuff);
+ flwd_pre_process_pkt_input(dev_handle, &raw_pkt);
+ flwd_acc_pkt_input(dev_handle, tseq, &raw_pkt);
+ dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }
+
+ tot_work_times++;
+
+ if((ret1 < 0) && (ret2 < 0)){
+ ret3 = flwd_idle_call(tseq);
+ if(0 == ret3){
+ /* ����������������, idle_call()Ҳ���¿���, ����һ�� */
+ flwd_adapt_sleep(success_work_times_in_recent_100);
+ }else{
+ success_work_times_in_recent_100++;
+ }
+ }else{
+ success_work_times_in_recent_100++;
+ }
+
+ if(tot_work_times >= 100){
+ /////printf("%d/100\n", success_work_times_in_recent_100);
+ tot_work_times = 0;
+ success_work_times_in_recent_100 = 0;
+ }
+ }
+
+ return NULL;
+}
+
+/* �������س�ʼ������� */
+int flwd_gateway_init(void)
+{
+ int i, ret;
+ char str_tmp[256];
+
+#if FLWD_NO_ACTIVE_IP_DISCOVER
+ printf("\033[1;31;40m[Warning] TEST NO IP DISCOVER is enable!\033[0m\n" );
+ sleep(2);
+#endif
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "nat_htable_max_num", &flwd_cfg_val.nat_htable_max_num, 50000);
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "nat_htable_timeout", &flwd_cfg_val.nat_htable_timeout, 30);
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ flwd_thread_val[i].nat_info_table = flwd_access_nat_table_create();
+ }
+
+
+ /* TODO, PPTP, L2TP server ��ʼ�� */
+
+ /* TODO, IP��ַ��ȫ��, ip-hot-pool �ṹ��ʼ�� */
+
+ /* IP���ò��Խṹ��ʼ��, HASH��, ����SNAT, keyΪdip+dport, ����DNAT, keyΪRIP+RPORT */
+
+ ret = flwd_packet_io_init(TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWD);
+ if(ret < 0){
+ return -1;
+ }
+
+ ret = flwd_access_active_ip_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ ret = flwd_network_conn_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ /* NOTE: maat��÷���������, ��Ϊ��callback, ��ʼ����ر���������, ����������ݽṹ��û��ʼ�����, ����flwd_access_active_ip_init(), callback�����! */
+ ret = flwd_access_maat_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ return 0;
+}
+
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;
+}
+
diff --git a/src/access/flwd_access_idle_call.c b/src/access/flwd_access_idle_call.c
new file mode 100644
index 0000000..a842728
--- /dev/null
+++ b/src/access/flwd_access_idle_call.c
@@ -0,0 +1,66 @@
+/*
+ �����������ݰ�, CPU����ʱ, �ڰ������̵߳��������е��ô˽ӿ�,
+ ������htable��ʱ��̭,
+ ��ԾIP���ø���(ԭ�����޲��Ե�, �û�������һ������, ����в��Ե���; ��֮, ԭ�������в���, ��ɾ����),
+
+ ��˺����ӿ��ڰ������̵߳���������, ��ʵ�ְ������߳���������ʱ������, �������!!
+*/
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include "MESA_handle_logger.h"
+#include "MESA_atomic.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>
+
+extern MESA_ATOMIC_T flwd_temp_active_ip_op_flag[FLWD_MAX_THREAD_NUM];
+
+
+/* �ڰ������߳������Ĵ�����ԾIP�ĸ���, ����ģʽ */
+static int flwd_act_ip_update_in_process_thread_context(int tid)
+{
+#if FLWD_ASYNC_LOCK_FREE
+ int ret;
+ flwd_active_ip_t tmp_act_ip;
+ long buf_len;
+
+ if(0 == MESA_lqueue_get_count(flwd_temp_active_ip_to_deal[tid])){
+ /* û���µ����� */
+ return 0;
+ }
+
+ if(FLWD_ACT_IP_OP_OR_MASK_BY_CALLBACK & __sync_or_and_fetch(&flwd_temp_active_ip_op_flag[tid], FLWD_ACT_IP_OP_OR_MASK_BY_PROC)){
+ /* callback�̻߳��ڴ�����, �˴����ܵȴ�, ��ձ�־λ��, ֱ�ӷ��ص���һ�ε��� */
+ __sync_and_and_fetch(&flwd_temp_active_ip_op_flag[tid], FLWD_ACT_IP_OP_AND_MASK_BY_PROC);
+ return 0;
+ }
+
+ buf_len = sizeof(flwd_active_ip_t);
+ ret = MESA_lqueue_get_head(flwd_temp_active_ip_to_deal[tid], &tmp_act_ip, &buf_len);
+ assert(ret >= 0);
+
+ flwd_act_ip_hash_proc(tid, &tmp_act_ip);
+
+ /* �������, �����־λ */
+ __sync_and_and_fetch(&flwd_temp_active_ip_op_flag[tid], FLWD_ACT_IP_OP_AND_MASK_BY_PROC);
+
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+
+int flwd_idle_call(int tid)
+{
+ int ret;
+ ret = flwd_act_ip_update_in_process_thread_context(tid);
+
+ return ret;
+}
+
diff --git a/src/access/flwd_access_ip_layer.c b/src/access/flwd_access_ip_layer.c
new file mode 100644
index 0000000..1fcfb4a
--- /dev/null
+++ b/src/access/flwd_access_ip_layer.c
@@ -0,0 +1,6 @@
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+
+
+
diff --git a/src/access/flwd_access_l2tp_layer.c b/src/access/flwd_access_l2tp_layer.c
new file mode 100644
index 0000000..43c76af
--- /dev/null
+++ b/src/access/flwd_access_l2tp_layer.c
@@ -0,0 +1,22 @@
+#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_access_l2tp_layer_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ /* TODO, ����l2tpЭ��ջ����, �ҵ�l2tp���, ������Ϻ�, ����access���Ĵ���ģ�� */
+
+ flwd_access_kernal_pkt_input(device_handle, tid, raw_pkt);
+
+ return 0;
+}
+
diff --git a/src/access/flwd_access_maat.c b/src/access/flwd_access_maat.c
new file mode 100644
index 0000000..be30508
--- /dev/null
+++ b/src/access/flwd_access_maat.c
@@ -0,0 +1,582 @@
+#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 "Maat_rule.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 <ctype.h>
+
+
+static unsigned int flwd_fetch_policy_id_from_user_region(struct Maat_rule_t *maat_res)
+{
+ char *policy_section;
+
+ /* �������, �洢���Զ�����, ����ǰ���Ե�IP��ַ�ص���� */
+ policy_section = strcasestr(maat_res->service_defined, "IR_STRATEGY=");
+ if(NULL == policy_section){
+ return 0;
+ }
+
+ policy_section += strlen("IR_STRATEGY=");
+
+ return (unsigned int)atoi(policy_section);
+}
+
+
+/*
+ ���ݵ�ǰ�ͻ��˵�ԴIP, PORT, ɨ�������ĸ����ò���: policy_id.
+ return value:
+ > 0: success, policy id.
+ 0: not hit rule;
+*/
+unsigned int flwd_access_maat_scan_rule(int tid, const flwd_tuple5_t *tuple5)
+{
+ int ret;
+ struct Maat_rule_t maat_res[1]; /* ��̫���ܶ�����, �����Ƕ�����, ���Ҳֻ��Ҫһ�����, �˴�res��Ϊ1 */
+ struct ipaddr client_addr;
+ scan_status_t mid = NULL;
+ unsigned int hit_policy_id;
+
+ memset(&maat_res[0], 0, sizeof(maat_res));
+
+ flwd_tuple5_to_stream_addr(tid, tuple5, &client_addr);
+
+ ret = Maat_scan_addr(flwd_global_val.maat_static_handle,
+ flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_POLICY_IP].table_id, /* TODO, SNAT��DNAT���Էֿ�, table_id�ֳ�����!! */
+ &client_addr,
+ maat_res,
+ 1,
+ &mid,
+ tid);
+ if(ret <= 0){
+ return 0;
+ }
+
+ hit_policy_id = flwd_fetch_policy_id_from_user_region(&maat_res[0]);
+
+ return hit_policy_id;
+}
+
+static void nouse_maat_start_cb(int update_type,void* u_para)
+{
+ return;
+}
+
+static void nouse_maat_finish_cb(void* u_para)
+{
+ return;
+}
+
+
+struct layer_addr_mac_in_mac
+{
+ unsigned char outer_dst_mac[6]; /* �����mac��ַ, network order */
+ unsigned char outer_src_mac[6]; /* �����mac��ַ, network order */
+ unsigned char inner_dst_mac[6]; /* �ڲ�mac��ַ, network order */
+ unsigned char inner_src_mac[6]; /* �ڲ�mac��ַ, network order */
+};
+
+
+/* ascii�ַ�ת16���� */
+static char MESA_ascii_to_hex(char ascii)
+{
+ char c = 0;
+
+ switch(ascii)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c = ascii - 0x30;
+ break;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ c = 10 + ascii - 0x61;
+ break;
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ c = 10 + ascii - 0x41;
+ break;
+ }
+
+ return c;
+}
+
+/*
+ "000100032202-00e0fc030007,000100032202-00e0fc030007"
+ copy from sapp.
+*/
+static int flwd_mac_in_mac_pton(char *addr_str, struct layer_addr_mac_in_mac *minm)
+{
+ int i;
+ char *str_val = addr_str;
+ unsigned char tmp_bin_val;
+
+ memset(minm, 0, sizeof(struct layer_addr_mac_in_mac));
+
+ for(i = 0; i < 6; i++){
+ tmp_bin_val = 0; /* ������, ������ֵ��䶼�ǻ���� */
+ if(isxdigit(*str_val)==0){
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4;
+ str_val++;
+
+ if(isxdigit(*str_val)==0) {
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val);
+ str_val++;
+ minm->inner_src_mac[i] = tmp_bin_val;
+ }
+
+ if(*str_val != '-'){
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ str_val++;
+
+ for(i = 0; i < 6; i++){
+ tmp_bin_val = 0; /* ������, ������ֵ��䶼�ǻ���� */
+ if(isxdigit(*str_val)==0){
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4;
+ str_val++;
+
+ if(isxdigit(*str_val)==0) {
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val);
+ str_val++;
+ minm->inner_dst_mac[i] = tmp_bin_val;
+ }
+
+ if(*str_val != ','){
+ printf("MAC_IN_MAC string type error!\n");
+ return -1;
+ }
+ str_val++;
+
+ for(i = 0; i < 6; i++){
+ tmp_bin_val = 0; /* ������, ������ֵ��䶼�ǻ���� */
+ if(isxdigit(*str_val)==0){
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4;
+ str_val++;
+
+ if(isxdigit(*str_val)==0) {
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val);
+ str_val++;
+ minm->outer_src_mac[i] = tmp_bin_val;
+ }
+
+ if(*str_val != '-'){
+ printf("MAC_IN_MAC string type error!\n");
+ return -1;
+ }
+ str_val++;
+
+ for(i = 0; i < 6; i++){
+ tmp_bin_val = 0; /* ������, ������ֵ��䶼�ǻ���� */
+ if(isxdigit(*str_val)==0){
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val) << 4;
+ str_val++;
+
+ if(isxdigit(*str_val)==0) {
+ printf("MAC string type error!\n");
+ return -1;
+ }
+ tmp_bin_val |= MESA_ascii_to_hex(*str_val);
+ str_val++;
+ minm->outer_dst_mac[i] = tmp_bin_val;
+ }
+
+ return 0;
+}
+
+/*
+ region_id=1;dev_id=1;link_id=2;route_dir=0;smac=xxxxxx;dmac=xxxxx;
+
+ ����user_region��ʽʹ��MAC-IN-MAC��ʽ�������ڲ㣬���������.
+ inner_smac-inner-dmac, outer_smac-outer_dmat,
+ 000100032202-00e0fc030007,000100032202-00e0fc030007
+
+*/
+static int flwd_act_ip_user_region_parse(char *user_region, flwd_active_ip_t *act_ip)
+{
+ int ret;
+ struct layer_addr_mac_in_mac minm;
+
+
+ /* TODO
+ flwd_search_fwd_ip_by_gdev_ip(), ͨ��dev_id, region_id�Զ���ѯ.
+ */
+
+
+#if FLWD_RUN_IN_CEIEC_TEST
+ /* ��ʱ���ԣ��ֶ�д���ڲ�mac */
+ //char manual_inner_smac[6] = {0x3c, 0x97, 0x0e, 0x18, 0x18, 0x41};
+ //char manual_inner_smac[6] = {0xe4, 0x95, 0x6e, 0x20, 0x0d, 0x06};
+ char manual_inner_smac[6] = {0x28, 0xd2, 0x44, 0x43, 0x12, 0x34}; /* ��ԾIP��SMAC */
+ char manual_inner_dmac[6] = {0xe8, 0x61, 0x1f, 0x13, 0x70, 0x7a}; /* Ŀ�������MAC */
+
+ //inet_pton(AF_INET, "10.3.127.3", &act_ip->gdev_args.gdev_ip_net_order);
+ inet_pton(AF_INET, "10.1.1.1", &act_ip->gdev_args.gdev_ip_net_order);
+ act_ip->gdev_args.link_id = 1; /* TODO, ���ݻ�ԾIP������ȡ, ���ϲ���Ϊ1 */
+ act_ip->gdev_args.this_ip_as_sip_route_dir = 1; /* TODO, ���ݻ�ԾIP������ȡ,���ϲ���Ϊ1 */
+ memcpy(act_ip->gdev_args.inner_raw_smac, manual_inner_smac, 6);
+ memcpy(act_ip->gdev_args.inner_raw_dmac, manual_inner_dmac, 6);
+#else
+ ret = flwd_mac_in_mac_pton(user_region, &minm);
+ if(ret < 0){
+ return -1;
+ }
+
+ memcpy(act_ip->gdev_args.inner_raw_dmac, minm.inner_dst_mac, 6);
+ memcpy(act_ip->gdev_args.inner_raw_smac, minm.inner_src_mac, 6);
+
+#endif
+
+ return 0;
+}
+
+
+/*
+ �����ʽ:
+ ID,addr_type, protocol,ip,port,direction,user_region,location,is_valid,action,service,policy_group,op_time;
+
+ TODO:
+ ����user_region��ʽ��ǰ���Ƿ���mac-in-mac��ʽ, ����ԭʼMAC��ʽδ��, ��ʹ��gdev_ip=1.1.1.1��GDEVIP������.
+*/
+static void flwd_ip_static_pool_cb(int table_id, const char *table_line, void* u_para)
+{
+ char *stack_buf = strdup(table_line);
+ char *save_ptr;
+ char *section;
+ const char *delim = "\t ";
+ flwd_active_ip_t act_ip;
+ int tmp_int;
+ char for_log_ip_str[128];
+
+ memset(&act_ip, 0, sizeof(act_ip));
+
+ /* ID */
+ section = strtok_r(stack_buf, delim, &save_ptr);
+ assert(section);
+
+ /* addr_type */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ tmp_int = atoi(section);
+ if(4 == tmp_int){
+ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ act_ip.active_ip_net_order.addr_len = sizeof(int);
+ }else if(6 == tmp_int){
+ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V6;
+ act_ip.active_ip_net_order.addr_len = sizeof(struct in6_addr);
+ }else{
+ assert(0);
+ }
+
+ /* protocol, �ݲ����� */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+
+ /* ip */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){
+ inet_pton(AF_INET, section, &act_ip.active_ip_net_order.addr_ipv4);
+ }else{
+ inet_pton(AF_INET6, section, &act_ip.active_ip_net_order.addr_ipv6);
+ }
+ strncpy(for_log_ip_str, section, 128);
+
+ /* port */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ tmp_int = atoi(section);
+ if(tmp_int < 0 || tmp_int > 65535){
+ assert(0);
+ }
+ act_ip.active_ip_net_order.dport = (unsigned short)tmp_int;
+
+ /* direction, ��GDEV�µķ���Ӧ�ö���Ŀ��IP, 0��ʾԴIP��1��ʾĿ��IP��2��ʾ˫�� */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+
+ /* user region, �洢GDEV�����Ϣ */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ if(flwd_act_ip_user_region_parse(section, &act_ip) < 0){
+ goto done;
+ }
+
+ /* location, */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+
+#if FLWD_IP_REGION_BY_LIB
+ if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){
+ act_ip.ip_region_type = flwd_ipv4_location(ntohl(act_ip.active_ip_net_order.addr_ipv4));
+ }else{
+ act_ip.ip_region_type = flwd_ipv6_location(&act_ip.active_ip_net_order.addr_ipv6);
+ }
+#else
+ tmp_int = atoi(section);
+ if((tmp_int != FLWD_IP_REGION_INLAND) && (tmp_int != FLWD_IP_REGION_OUTLAND)){
+ assert(0);
+ }
+
+ act_ip.ip_region_type = (flwd_ip_region_type_t)tmp_int;
+#endif
+
+ /* is_valid */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ act_ip.is_valid = atoi(section);
+
+ /* action, TODO, 20180910, ���ֶ��Ѿ�ɾ��!!! */
+ //section = strtok_r(NULL, delim, &save_ptr);
+ //assert(section);
+
+ /* service */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+
+ /* policy group id */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ act_ip.policy_group_id = strtoul(section, NULL, 10);
+
+ /* op_time */
+ section = strtok_r(NULL, delim, &save_ptr);
+ //assert(section);
+
+ act_ip.ip_origin_type = FLWD_ACT_IP_STATIC;
+ flwd_act_ip_update(&act_ip);
+
+ flwd_log(10, "ip_static_pool update callback: recv ip %s, region:%d, policy_id:%u\n",
+ for_log_ip_str, act_ip.ip_region_type, act_ip.policy_group_id);
+
+done:
+ while(strtok_r(NULL, delim, &save_ptr));
+
+ free(stack_buf);
+
+ return;
+}
+
+
+/*
+ �����ʽ:
+ ID,addr_type, protocol,ip,port,direction,user_region,location,is_valid,op_time;
+
+ TODO:
+ ����user_region��ʽʹ��MAC-IN-MAC��ʽ�������ڲ㣬���������.
+ inner_smac-inner-dmac, outer_smac-outer_dmat,
+ 000100032202-00e0fc030007,000100032202-00e0fc030007
+*/
+void flwd_ip_dyn_sift_pool_cb(int table_id,const char* table_line,void* u_para)
+{
+ char *stack_buf = strdup(table_line);
+ char *save_ptr;
+ char *section;
+ const char *delim = "\t ";
+ flwd_active_ip_t act_ip;
+ int tmp_int;
+ char *for_log_ip_str;
+
+ memset(&act_ip, 0, sizeof(act_ip));
+
+ /* ID */
+ section = strtok_r(stack_buf, delim, &save_ptr);
+ assert(section);
+
+ /* addr_type */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ tmp_int = atoi(section);
+ if(4 == tmp_int){
+ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ act_ip.active_ip_net_order.addr_len = sizeof(int);
+ }else if(6 == tmp_int){
+ act_ip.active_ip_net_order.addr_type = FLWD_IP_ADDR_TYPE_V6;
+ act_ip.active_ip_net_order.addr_len = sizeof(struct in6_addr);
+ }else{
+ assert(0);
+ }
+
+ /* protocol, �ݲ����� */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+
+ /* ip */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){
+ inet_pton(AF_INET, section, &act_ip.active_ip_net_order.addr_ipv4);
+ }else{
+ inet_pton(AF_INET6, section, &act_ip.active_ip_net_order.addr_ipv6);
+ }
+ for_log_ip_str = section;
+
+ /* port, ��ַ�ص�PORT�ֶ������� */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ tmp_int = atoi(section);
+ if(tmp_int < 0 || tmp_int > 65535){
+ assert(0);
+ }
+ act_ip.active_ip_net_order.dport = (unsigned short)tmp_int;
+
+ /* direction, ��GDEV�µķ���Ӧ�ö���Ŀ��IP, 0��ʾԴIP��1��ʾĿ��IP��2��ʾ˫�� */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+
+ /* user region, �ݲ����� */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ if(flwd_act_ip_user_region_parse(section, &act_ip) < 0){
+ goto done;
+ }
+
+ /* location, */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+#if FLWD_IP_REGION_BY_LIB
+ if(FLWD_IP_ADDR_TYPE_V4 == act_ip.active_ip_net_order.addr_type){
+ act_ip.ip_region_type = flwd_ipv4_location(ntohl(act_ip.active_ip_net_order.addr_ipv4));
+ }else{
+ act_ip.ip_region_type = flwd_ipv6_location(&act_ip.active_ip_net_order.addr_ipv6);
+ }
+#else
+ tmp_int = atoi(section);
+ if((tmp_int != FLWD_IP_REGION_INLAND) && (tmp_int != FLWD_IP_REGION_OUTLAND)){
+ assert(0);
+ }
+
+ act_ip.ip_region_type = (flwd_ip_region_type_t)tmp_int;
+#endif
+
+ /* is_valid */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+ act_ip.is_valid = atoi(section);
+
+ /* op_time */
+ section = strtok_r(NULL, delim, &save_ptr);
+ assert(section);
+
+ act_ip.ip_origin_type = FLWD_ACT_IP_DYNAMIC;
+
+ flwd_act_ip_update(&act_ip);
+
+ flwd_log(10, "ip_dynamic_pool update callback: recv ip %s, region:%d\n",
+ for_log_ip_str, act_ip.ip_region_type);
+done:
+ while(strtok_r(NULL, delim, &save_ptr)); /* ���strtok���� */
+
+ free(stack_buf);
+
+ return;
+}
+
+
+int flwd_access_maat_init(void)
+{
+#if 0 == FLWD_NO_MAAT
+ int ret;
+
+ ret = flwd_maat_talbe_name_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ flwd_global_val.maat_static_handle = flwd_maat_summon(FLWD_CONFIG_FILE, "maat_static");
+ if(NULL == flwd_global_val.maat_static_handle){
+ return -1;
+ }
+
+ flwd_global_val.maat_dynamic_handle = flwd_maat_summon(FLWD_CONFIG_FILE, "maat_dynamic");
+ if(NULL == flwd_global_val.maat_dynamic_handle){
+ return -1;
+ }
+
+ flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_POLICY_COMPILE);
+ flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_POLICY_GROUP);
+ flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_POLICY_IP);
+ flwd_maat_table_register(flwd_global_val.maat_static_handle, (int)FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB);
+ flwd_maat_table_register(flwd_global_val.maat_dynamic_handle, (int)FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB);
+ flwd_maat_table_register(flwd_global_val.maat_dynamic_handle, (int)FLWD_MAAT_TB_IR_DYN_CONN_IP);
+
+ ret = Maat_table_callback_register(flwd_global_val.maat_static_handle,
+ flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB].table_id,
+ nouse_maat_start_cb,
+ flwd_ip_static_pool_cb,
+ nouse_maat_finish_cb,
+ flwd_global_val.maat_log_handle);
+ if(ret < 0){
+ flwd_log(30, "Maat_table_callback_register %s error!\n",
+ flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_STATIC_IP_POOL_CB].table_name);
+ return -1;
+ }
+
+ ret = Maat_table_callback_register(flwd_global_val.maat_dynamic_handle,
+ flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB].table_id,
+ nouse_maat_start_cb,
+ flwd_ip_dyn_sift_pool_cb,
+ nouse_maat_finish_cb,
+ flwd_global_val.maat_log_handle);
+ if(ret < 0){
+ flwd_log(30, "Maat_table_callback_register %s error!\n",
+ flwd_global_val.maat_table_info[FLWD_MAAT_TB_IR_DYN_SIFT_IP_CB].table_name);
+ return -1;
+ }
+
+#endif
+
+ return 0;
+}
+
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;
+}
+
diff --git a/src/flowood_main.c b/src/flowood_main.c
new file mode 100644
index 0000000..7deb452
--- /dev/null
+++ b/src/flowood_main.c
@@ -0,0 +1,155 @@
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "MESA_handle_logger.h"
+#include "MESA_prof_load.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+/*
+ IP����ϵͳ,
+ ģ�鿪������: flowood,
+ IP����ϵͳ�IJ�����Ϊ��Դ�ڳ���"�ƻ���ľ", flower->wood, ƴ�ճ�һ����: flowood.
+*/
+
+int flowood_version_VERSION_20181019;
+
+flwd_global_val_t flwd_global_val; /* ȫ�ֱ��� */
+flwd_global_cfg_t flwd_cfg_val; /* ���� */
+flwd_global_thread_t flwd_thread_val[FLWD_MAX_THREAD_NUM];
+
+/*
+ ���ֲ����ļ��, ��ֹ������������, ������д��!
+*/
+static int flwd_validity_check(void)
+{
+ if((sizeof(flwd_global_thread_t) % 64) != 0){
+ printf("sizeof(flwd_global_thread_t) size is %u, % 64 is %u\n", sizeof(flwd_global_thread_t) , sizeof(flwd_global_thread_t) % 64);
+ abort();
+ }
+
+ /* NOTE: �������껹���������±�, ����һ��trick, �����0��ʼ, �������ⶨ��, ���˾���! */
+ assert(FLWD_IP_ADDR_TYPE_V4 == 0);
+ assert(FLWD_IP_ADDR_TYPE_V6 == 1);
+
+ /* NOTE: �������껹���������±�, �����0��ʼ, �������ⶨ��, ���˾���! */
+ assert(FLWD_IP_REGION_INLAND == 0);
+ assert(FLWD_IP_REGION_OUTLAND == 1);
+
+ assert(flwd_cfg_val.current_access_gateway_id <= flwd_cfg_val.global_access_gateway_num);
+
+ assert(flwd_cfg_val.current_access_gateway_id <= 4); /* ���֧��4̨, ��FLWD_SPORT_ACC_ID_MASK���� */
+
+ return 0;
+}
+
+static void flwd_run(void)
+{
+ flwd_log(RLOG_LV_DEBUG, "flowood ready to run......");
+
+ flwd_packet_io_run();
+}
+
+static int flwd_init(void)
+{
+ int i, ret, int_tmp;
+ int log_level;
+ pthread_t pid;
+
+ flwd_validity_check();
+
+ memset((void *)&flwd_global_val.zero_ipv6_addr, 0, sizeof(struct in6_addr));
+ memset((void *)&flwd_global_val.zero_mac_addr, 0, 6);
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "log", "log_level", &flwd_cfg_val.flwd_log_level, 20);
+
+ flwd_global_val.flwd_log_handle = MESA_create_runtime_log_handle("./log/ip_reuse.log", log_level);
+ flwd_global_val.maat_log_handle = MESA_create_runtime_log_handle("./log/ip_reuse_maat.log", log_level);
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "thread_num", &int_tmp, 1);
+ if(int_tmp < 1 || int_tmp > FLWD_MAX_THREAD_NUM){
+ flwd_log(RLOG_LV_FATAL, "conf->thread_num invalid!");
+ return -1;
+ }
+ flwd_cfg_val.tot_thread_count = int_tmp;
+ for(i = 0; i < __TOPO_MODE_MAX; i++){
+ flwd_global_val.global_io_handle[i].tot_thread_count = int_tmp;
+ }
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "global_access_gateway_num", &flwd_cfg_val.global_access_gateway_num, 1);
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "current_access_gateway_id", &flwd_cfg_val.current_access_gateway_id, 1);
+ if(flwd_cfg_val.current_access_gateway_id <= 0 || flwd_cfg_val.current_access_gateway_id > flwd_cfg_val.global_access_gateway_num){
+ flwd_log(RLOG_LV_FATAL, "conf->current_access_gateway_id invalid!");
+ return -1;
+ }
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "use_static_pool_ip_if_no_dynamic", &flwd_cfg_val.use_static_pool_ip_if_no_dynamic, 0);
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "use_dynamic_pool_ip_if_no_static", &flwd_cfg_val.use_dynamic_pool_ip_if_no_static, 0);
+
+ ret = flwd_gateway_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ ret = flwd_arp_table_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ pthread_create(&pid, NULL, flwd_stat_thread, NULL);
+
+ return 0;
+}
+
+
+#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ת�������Բ����ʽ���ص�sapp */
+int IR_FWD_INIT(void)
+{
+ int ret;
+
+ ret = flwd_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ flwd_log(RLOG_LV_DEBUG, "flwd_init() success!");
+
+ flwd_run();
+
+ return 0;
+}
+#ifdef __cplusplus
+}
+#endif
+
+#else
+int main(void)
+{
+ int ret;
+
+ ret = flwd_init();
+ if(ret < 0){
+ return -1;
+ }
+
+ flwd_log(RLOG_LV_DEBUG, "flwd_init() success!");
+
+ flwd_run();
+
+ while(1){
+ pause();
+ }
+
+ return 0;
+}
+#endif
+
+
diff --git a/src/forward/Makefile b/src/forward/Makefile
new file mode 100644
index 0000000..99d476c
--- /dev/null
+++ b/src/forward/Makefile
@@ -0,0 +1,27 @@
+#CC=gcc
+CC=g++
+CCC=g++
+
+TARGET=flowood_forward.o flwd_fwd_idle_call.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
+H_DIR += -I/opt/mrzcpd/include
+
+LIBPATH=../lib
+LIB=-L/opt/MESA/lib -lpthread
+
+
+all:$(TARGET)
+
+.c.o:
+ $(CC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+.cpp.o:
+ $(CCC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+clean:
+ rm -f *.o
diff --git a/src/forward/flowood_forward.c b/src/forward/flowood_forward.c
new file mode 100644
index 0000000..f422067
--- /dev/null
+++ b/src/forward/flowood_forward.c
@@ -0,0 +1,1044 @@
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <assert.h>
+#include <arpa/inet.h>
+
+/*
+ IP����ϵͳת������, ��sapp�����ʽ����.
+ ��TCPALL��UDP�������, �ݲ�֧�ִ�IP��Э��, ��ICMP, GRE��IP��Э��.
+
+ �ͽ������ز�����ͨUDP-SOCKET��ʽ, �����߳��շ�,
+ ��GDEV�����ݽ�����IPREUSE_TCPALL_ENTRY()��IPREUSE_UDP_ENTRY(),
+ ��ת������֮�����ں���:flwd_packet_io_work_thread().
+*/
+
+
+/* NAT���Ը���, maat�ص���, ��maat���� */
+int flowood_forward_nat_strategy_update_cb()
+{
+ return 0;
+}
+
+void * flwd_fwd_to_gdev_pre_output(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ char *unsend_raw_data_ptr = rcv_device_handle->low_level_mbuff_mtod(raw_pkt->low_level_mbuff);
+ int unsend_raw_data_len = rcv_device_handle->low_level_mbuff_get_pkt_len(raw_pkt->low_level_mbuff);
+ void *send_mbuff = send_device_handle->low_level_mbuff_malloc(send_device_handle, tid, unsend_raw_data_len+FLWD_VXLAN_OUTER_PACKET_LEN);
+ char *send_buf_data_ptr;
+
+ unsend_raw_data_ptr += FLWD_VXLAN_OUTER_PACKET_LEN; /* ����vxlanͷ��, ָ���ڲ����ݰ�macͷ�� */
+ unsend_raw_data_len -= FLWD_VXLAN_OUTER_PACKET_LEN;
+
+ /* �����վ���Ļ�����copy�������;���Ļ�����, �����߲���ģʽ���ܲ�һ��, ����ֱ�Ӹ���, ������һ��malloc/memcpy/free�Ĺ��� */
+ send_buf_data_ptr = send_device_handle->low_level_mbuff_data_append(send_mbuff, unsend_raw_data_ptr, unsend_raw_data_len);
+ if(NULL == send_buf_data_ptr){
+ send_device_handle->low_level_mbuff_free(send_device_handle, tid, send_mbuff);
+ return NULL;
+ }
+#if FLWD_NO_GDEV_ENV
+ /* û��GDEV�Ļ�����, ���ֶ���������mac, ��marsio������, ��������, ��mrtunnat�Զ����� */
+
+#if FLWD_NO_ACTIVE_ARP_QUERY
+ /* �ֹ�����ʵ�ʶԶ˷�������mac */
+ unsigned char *local_fwd_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ ///unsigned char remote_gdev_mac[6] = {0x74, 0x86, 0x7a, 0xd0, 0x25, 0x18}; /* 10.0.6.240 */
+ unsigned char remote_gdev_mac[6] = {0xe8, 0x61, 0x1f, 0x13, 0x70, 0x7a}; /* 192.168.10.5 */
+
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_fwd_gateway_mac, remote_gdev_mac, send_buf_data_ptr);
+#else
+ /*
+ ���ȷ�������ĸ�gdev?
+
+ 1-���е�ת�������յ���������, ��������˻�Ծip, �ͽ�active_ip <---> gdev_ip�Ķ�Ӧ��ϵ�洢����, maat-redis��ɢ;
+ ��ת�������յ��������صĵ�һ������, ��ѯ�����ϵ��, ��֪�������ĸ�GDEV,
+
+ ���active_ip���˹����õ�, �ĸ�ת�����ض�û�յ�������, Ҳ��û��������ϵ��, ���ⷢ��һ��gdev.
+
+ Դ��Ծip��ַ, �ҵ��������񵽴����ݰ���gdevip
+ */
+ unsigned char remote_gdev_mac[6];
+ flwd_ip_t gdev_ip;
+ gdev_ip.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ gdev_ip.addr_ipv4 = send_device_handle->io_para.gateway_ip_net_order;
+ ret = flwd_arp_table_query(tid, &gdev_ip, send_device_handle, remote_gdev_mac);
+ if(ret < 0){
+ return NULL;
+ }
+
+ unsigned char *local_fwd_gateway_mac = send_device_handle->io_para.local_mac_addr;
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_fwd_gateway_mac, remote_gdev_mac, send_buf_data_ptr);
+#endif
+
+#else
+ /* marsio vxlan send */
+
+#endif
+
+ return send_mbuff;
+}
+
+
+
+#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻ��ת��������Ҫ��sappһ������ */
+#include "stream.h"
+#include "mrtunnat.h"
+#include "marsio.h"
+
+extern "C" int MESA_sendpacket_iplayer_options(int thread_index,const char *data, int data_len, u_int8_t dir, SAPP_TLV_T *options, int opt_num);
+extern "C" mr_instance *sapp_get_marsio_instance(void);
+extern "C" void *packet_io_alias_ref_get(int target_id);
+extern "C" int marsio_send_burst_with_options_for_tcpdumpmesa(struct mr_sendpath * sendpath, queue_id_t sid, marsio_buff_t * mbufs[], int nr_mbufs, uint16_t options);
+extern "C" int 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, u_int32_t dst, const char *payload,
+ int payload_s, unsigned char *buf);
+extern "C" int sendpacket_do_checksum(unsigned char *buf, int protocol, int len);
+static mr_instance *flwd_marsio_handle;
+
+
+/*
+ ֱ�ӵ���ԭʼ�����ͽӿ�.
+*/
+
+int flwd_fwd_to_gdev_in_sapp_raw_marsio_mode(
+ flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ const flwd_eth_hdr_t *inner_eth_hdr;
+ const flwd_vxlan_hdr_t *vxlan_hdr;
+
+ flwd_eth_hdr_t *outer_eth_hdr = (flwd_eth_hdr_t *)raw_pkt->outer_pkt_data;
+ flwd_ipv4_hdr_t *outer_ip4_hdr;
+ flwd_udp_hdr_t *outer_udp_hdr;
+
+ inner_eth_hdr = (flwd_eth_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t));
+ vxlan_hdr = (flwd_vxlan_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+
+
+ flwd_log(10, "FWD: recv pkt from access gateway, link_id:%d, innser_smac:%02x-%02x-%02x-%02x-%02x-%02x, innser_dmac:%02x-%02x-%02x-%02x-%02x-%02x, inner_tuple4:%s\n",
+ vxlan_hdr->link_id,
+ inner_eth_hdr->h_source[0], inner_eth_hdr->h_source[1], inner_eth_hdr->h_source[2], inner_eth_hdr->h_source[3], inner_eth_hdr->h_source[4], inner_eth_hdr->h_source[5],
+ inner_eth_hdr->h_dest[0], inner_eth_hdr->h_dest[1], inner_eth_hdr->h_dest[2], inner_eth_hdr->h_dest[3], inner_eth_hdr->h_dest[4], inner_eth_hdr->h_dest[5],
+ flwd_debug_print_tuple4_detail((char *)inner_eth_hdr + sizeof(flwd_eth_hdr_t), tid));
+
+#if FLWD_RUN_IN_CEIEC_TEST
+ unsigned char outer_smac[6] = {0xe4, 0x95, 0x6e, 0x20, 0x0d, 0x0a}; //������ע������ҵ���MAC
+ unsigned char outer_dmac[6] = {0x00, 0x1e, 0x73, 0x6c, 0xfa, 0x43}; //gdev��������, ����������vlan_ip��MAC
+#endif
+
+ outer_eth_hdr->h_proto = htons(ETH_P_IP);
+ memcpy(outer_eth_hdr->h_source, outer_smac, 6);
+ memcpy(outer_eth_hdr->h_dest, outer_dmac, 6);
+
+ /* build outer ipv4 header */
+ sendpacket_build_ipv4(raw_pkt->outer_pkt_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv4_hdr_t),
+ 0,
+ 0,
+ 0,
+ 64,
+ 17,
+ 0x0100007F,
+ 0x0100007F,
+ NULL,
+ 0,
+ (unsigned char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t));
+ outer_ip4_hdr = (flwd_ipv4_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t));
+
+#if FLWD_RUN_IN_CEIEC_TEST
+ inet_pton(AF_INET, "192.168.1.10", &outer_ip4_hdr->ip_src.s_addr);
+ inet_pton(AF_INET, "10.1.1.1", &outer_ip4_hdr->ip_dst.s_addr);
+#endif
+
+ sendpacket_do_checksum((unsigned char *)outer_ip4_hdr, IPPROTO_IP, sizeof(flwd_ipv4_hdr_t));
+
+ /* outer udp header */
+ outer_udp_hdr = (flwd_udp_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t));
+ outer_udp_hdr->uh_ulen = htons(raw_pkt->outer_pkt_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv4_hdr_t));
+ outer_udp_hdr->uh_dport = htons(4789);
+#if FLWD_RUN_IN_CEIEC_TEST
+ outer_udp_hdr->uh_sport = htons(50705);
+#else
+ outer_udp_hdr->uh_sport = htons(50705);
+#endif
+ outer_udp_hdr->uh_sum = 0;
+
+
+#if FLWD_RUN_IN_CEIEC_TEST
+ /* vxlan header */
+ //unsigned char capture_vxlan_data[8] = {0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00}; /* I2C, ��->�� */
+ unsigned char capture_vxlan_data[8] = {0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00}; /* C2I, ��->�� */
+ memcpy((void *)vxlan_hdr, capture_vxlan_data, 8);
+#endif
+
+/////////////////
+ int inner_ret;
+ marsio_buff_t *send_mbuf[1];
+ unsigned char *real_buf;
+ struct mr_tunnat_ctrlzone mr_ctrlzone;
+ int ret;
+
+ if(NULL == flwd_marsio_handle){
+ flwd_marsio_handle = sapp_get_marsio_instance();
+ }
+
+ inner_ret = marsio_buff_malloc_global(flwd_marsio_handle, send_mbuf, 1,
+ MARSIO_SOCKET_ID_ANY, send_device_handle->sapp_send_thread_seq);
+ if(inner_ret < 0){
+ return -1;
+ }
+
+ real_buf = (unsigned char *)marsio_buff_append(send_mbuf[0], raw_pkt->outer_pkt_len);
+ outer_eth_hdr = (flwd_eth_hdr_t *)real_buf;
+
+ memcpy(real_buf, raw_pkt->outer_pkt_data, raw_pkt->outer_pkt_len);
+ outer_eth_hdr->h_proto = ntohs(ETH_P_IP);/* ��ײ���ΪIPv4 */
+
+ mr_ctrlzone.action |= TUNNAT_CZ_ACTION_ENCAP_NO_SESSION;
+ mr_ctrlzone.route_dir = vxlan_hdr->dir;
+ marsio_buff_ctrlzone_set(send_mbuf[0], 0, &mr_ctrlzone, sizeof(struct mr_tunnat_ctrlzone));
+
+ struct mr_sendpath *snd_path_handle = (struct mr_sendpath * )packet_io_alias_ref_get(1); /* 0Ϊvxlan_user, 1Ϊԭʼ�������� */
+ ret = marsio_send_burst_with_options_for_tcpdumpmesa(snd_path_handle,
+ send_device_handle->sapp_send_thread_seq,
+ send_mbuf, 1, MARSIO_SEND_OPT_FAST);
+ if(flwd_cfg_val.flwd_log_level <= 10){
+ char outer_tuple4_str[128];
+ flwd_log(10, "FWD: send pkt to gdev, link_id:%d, innser_smac:%02x-%02x-%02x-%02x-%02x-%02x, innser_dmac:%02x-%02x-%02x-%02x-%02x-%02x, inner_tuple4:%s, outer_tuple4:%s,\n",
+ vxlan_hdr->link_id,
+ inner_eth_hdr->h_source[0], inner_eth_hdr->h_source[1], inner_eth_hdr->h_source[2], inner_eth_hdr->h_source[3], inner_eth_hdr->h_source[4], inner_eth_hdr->h_source[5],
+ inner_eth_hdr->h_dest[0], inner_eth_hdr->h_dest[1], inner_eth_hdr->h_dest[2], inner_eth_hdr->h_dest[3], inner_eth_hdr->h_dest[4], inner_eth_hdr->h_dest[5],
+ flwd_debug_print_tuple4_detail((char *)inner_eth_hdr + sizeof(flwd_eth_hdr_t), tid),
+ flwd_debug_print_tuple4_detail_r(outer_ip4_hdr, outer_tuple4_str, 128));
+ }
+ return ret;
+}
+
+
+int flwd_fwd_to_gdev_in_sapp_vxlan_mode(
+ flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ SAPP_TLV_T option[32];
+ int option_num = 0;
+ //int vxlan_link_id = 1;
+ const flwd_eth_hdr_t *inner_eth_hdr;
+ const flwd_vxlan_hdr_t *vxlan_hdr;
+
+ inner_eth_hdr = (flwd_eth_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t));
+ vxlan_hdr = (flwd_vxlan_hdr_t *)(raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+
+ unsigned char outer_smac[6] = {0xe4, 0x95, 0x6e, 0x02, 0x0d, 0x0a};
+ unsigned char outer_dmac[6] = {0x00, 0x1e, 0x73, 0x6c, 0xfa, 0x43};
+
+ option[option_num].type = SAPP_SEND_OPT_GDEV_SMAC;
+ option[option_num].length = 6;
+ memcpy(option[option_num].array_value, outer_smac, 6);
+ option_num++;////////
+ option[option_num].type = SAPP_SEND_OPT_GDEV_DMAC;
+ option[option_num].length = 6;
+ memcpy(option[option_num].array_value, outer_dmac, 6);
+ option_num++;///////
+
+ option[option_num].type = SAPP_SEND_OPT_GDEV_SIP;
+ option[option_num].length = 4;
+// option[option_num].int_value = g_wangyan_send_fake_pkt_para.vxlan_sip_net_order;
+ unsigned int gsip_net_order;
+ inet_pton(AF_INET, "192.168.1.10", &gsip_net_order); /* TODO, ����cong/gdev.conf��ȡ������GDEV�ı����עIP */
+ option[option_num].int_value = gsip_net_order;
+ option_num++;///////
+
+ option[option_num].type = SAPP_SEND_OPT_GDEV_DIP;
+ option[option_num].length = 4;
+ //option[option_num].int_value = g_wangyan_send_fake_pkt_para.vxlan_dip_net_order;;
+ unsigned int gdip_net_order;
+ inet_pton(AF_INET, "10.1.1.1", &gdip_net_order); /* TODO, ���ݻ�ԾIP�е�DEV_ID����õ� */
+ option[option_num].int_value = gdip_net_order;
+ option_num++;///////
+
+ option[option_num].type = SAPP_SEND_OPT_GDEV_UDP_SPORT;
+ option[option_num].length = 2;
+// option[option_num].short_value = ntohs(g_wangyan_send_fake_pkt_para.vxlan_sport_net_order);
+#if FLWD_RUN_IN_CEIEC_TEST
+ option[option_num].short_value = ntohs(50709); /* 12��ҵ��̶��˿ں� */
+#else
+ option[option_num].short_value = ntohs(51664); /* 27��ҵ��̶��˿ں� */
+#endif
+ option_num++;///////
+
+ option[option_num].type = SAPP_SEND_OPT_GDEV_UDP_DPORT;
+ option[option_num].length = 2;
+ option[option_num].short_value = ntohs(4789);
+ option_num++;///////
+
+
+ option[option_num].type = SAPP_SEND_OPT_VXLAN_VPN_ID;
+ option[option_num].length = 4;
+// option[option_num].int_value = htonl(g_wangyan_send_fake_pkt_para.vxlan_vlan_num);
+ option[option_num].int_value = 7; /* VPN������ */
+ option_num++;///////
+
+ option[option_num].type = SAPP_SEND_OPT_VXLAN_LINK_ID;
+ option[option_num].length = 4;
+ option[option_num].int_value = vxlan_hdr->link_id;
+ option_num++;///////
+
+ option[option_num].type = SAPP_SEND_OPT_VXLAN_LINK_ENCAP_TYPE;
+ option[option_num].length = 1;
+ option[option_num].char_value = TUNNAT_TUNNEL_TYPE_ETHER;
+ option_num++;///////
+
+ option[option_num].type = SAPP_SEND_OPT_VXLAN_LINK_DIR;
+ option[option_num].length = 1;
+ option[option_num].char_value = vxlan_hdr->dir;
+ option_num++;///////
+
+
+ option[option_num].type = SAPP_SEND_OPT_INNER_SMAC;
+ option[option_num].length = 6;
+ memcpy(option[option_num].array_value, inner_eth_hdr->h_source, 6);
+ option_num++;////////
+ option[option_num].type = SAPP_SEND_OPT_INNER_DMAC;
+ option[option_num].length = 6;
+ memcpy(option[option_num].array_value, inner_eth_hdr->h_dest, 6);
+ option_num++;///////
+
+
+ flwd_log(10, "recv pkt from access gateway, link_id:%d, innser_smac:%02x-%02x-%02x-%02x-%02x-%02x, innser_dmac:%02x-%02x-%02x-%02x-%02x-%02x!\n",
+ vxlan_hdr->link_id,
+ inner_eth_hdr->h_source[0], inner_eth_hdr->h_source[1], inner_eth_hdr->h_source[2], inner_eth_hdr->h_source[3], inner_eth_hdr->h_source[4], inner_eth_hdr->h_source[5],
+ inner_eth_hdr->h_dest[0], inner_eth_hdr->h_dest[1], inner_eth_hdr->h_dest[2], inner_eth_hdr->h_dest[3], inner_eth_hdr->h_dest[4], inner_eth_hdr->h_dest[5]);
+
+ if(flwd_cfg_val.flwd_log_level <= 10){
+ const flwd_ipv4_hdr_t *inner_ip4_hdr = (flwd_ipv4_hdr_t *)(raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t));
+ char ip_src_str[32], ip_dst_str[32];
+ inet_ntop(AF_INET, &inner_ip4_hdr->ip_src.s_addr, ip_src_str, 32);
+ inet_ntop(AF_INET, &inner_ip4_hdr->ip_dst.s_addr, ip_dst_str, 32);
+
+ flwd_log(10, "fwd sendto gdev, inner ip: %s->%s, len:%u, ipid:0x%x, proto:%u\n",
+ ip_src_str, ip_dst_str, ntohs(inner_ip4_hdr->ip_len),
+ inner_ip4_hdr->ip_id, inner_ip4_hdr->ip_p);
+ }
+
+ int ret = MESA_sendpacket_iplayer_options(send_device_handle->sapp_send_thread_seq,
+ raw_pkt->inner_pkt_data + sizeof(flwd_eth_hdr_t),
+ raw_pkt->inner_pkt_len - sizeof(flwd_eth_hdr_t),
+ vxlan_hdr->dir,
+ option, option_num);
+
+ return ret;
+}
+
+#endif
+
+
+static void * flwd_fwd_to_acc_pre_output(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+
+{
+ flwd_vxlan_hdr_t *outer_vxlan_dr;
+ int ret;
+ char *unsend_raw_data_ptr = rcv_device_handle->low_level_mbuff_mtod(raw_pkt->low_level_mbuff);
+ int unsend_raw_data_len = rcv_device_handle->low_level_mbuff_get_pkt_len(raw_pkt->low_level_mbuff);
+ void *send_mbuff = send_device_handle->low_level_mbuff_malloc(send_device_handle, tid, unsend_raw_data_len+FLWD_VXLAN_OUTER_PACKET_LEN);
+ char *send_buf_data_ptr;
+
+ /* �����վ���Ļ�����copy�������;���Ļ�����, �����߲���ģʽ���ܲ�һ��, device_handleҲ��һ��, mbuff����ֱ�Ӹ���, ������һ��malloc/memcpy/free�Ĺ��� */
+ send_device_handle->low_level_mbuff_data_append(send_mbuff, unsend_raw_data_ptr, unsend_raw_data_len);
+
+ /* ָ����ǰ�ƶ�, Ԥ��vxlan���ռ� */
+ send_buf_data_ptr = (char *)send_device_handle->low_level_mbuff_data_forward(send_mbuff, FLWD_VXLAN_OUTER_PACKET_LEN);
+
+ /* ����ײ�vxlan��Ϣ, ���迼�Ƿ������, ��Ϊ�����ڲ���Ԫ��hash����, vxlan����ַ����·��Ѱַ���� */
+
+#if FLWD_NO_ACTIVE_ARP_QUERY
+ unsigned char *local_fwd_to_acc_mac = send_device_handle->io_para.local_mac_addr;
+ unsigned char remote_acc_gateway_mac[6] = {0x74, 0x86, 0x7A, 0xD0, 0x1B, 0x30}; /* 10.0.6.229 */
+ flwd_sendpacket_build_ethernet(ETH_P_IP, local_fwd_to_acc_mac, remote_acc_gateway_mac, send_buf_data_ptr);
+#else
+ /* TODO: �����ڲ����ݰ���Դ�˿�, ���ݶ˿ڷ�Χ, ����ȫ�ֽ�������id��������, �ҵ��������ص�ip��ַ, ���Ҷ�Ӧip��mac��ַ */
+ if(CAP_MODEL_SOCKET != send_device_handle->io_para.cap_mode){ /* socketģʽ�ײ���Э��ջ��װ, flowoodֻ������һ��vxlan */
+ unsigned char acc_gateway_mac[6];
+ flwd_ip_t acc_gateway_ip;
+ acc_gateway_ip.addr_type = FLWD_IP_ADDR_TYPE_V4;
+ acc_gateway_ip.addr_ipv4 = send_device_handle->io_para.gateway_ip_net_order;
+ ret = flwd_arp_table_query(tid, &acc_gateway_ip, send_device_handle, acc_gateway_mac);
+ if(ret < 0){
+ return NULL;
+ }
+ }
+#endif
+
+ /* NOTE, ��ʹ��socketģʽ, ����Ҫ����ײ�vxlanԭʼ��, ��DIP, PORT���ܶ���һ��, ����Щֵ���Ƿ�װ�����ݰ���, ��dl_io_send�Ӱ���ȡ */
+#if FLWD_NO_GDEV_ENV
+ unsigned int local_fwd_gateway_ip = send_device_handle->io_para.device_ip_net_order;
+ unsigned int remote_acc_gateway_ip;
+// inet_pton(AF_INET, "172.16.1.229", &remote_acc_gateway_ip);
+// inet_pton(AF_INET, "10.0.6.229", &remote_acc_gateway_ip);
+ inet_pton(AF_INET, "202.43.148.188", &remote_acc_gateway_ip);
+ flwd_sendpacket_build_ipv4(unsend_raw_data_len + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t), /* �ڲ�ԭʼ�� + UDP��ͷ + vxlanͷ */
+ 0,
+ 0x1234,
+ 0,
+ 64,
+ IPPROTO_UDP,
+ local_fwd_gateway_ip,
+ remote_acc_gateway_ip,
+ NULL,
+ 0,
+ (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t));
+#else
+ abort();
+#endif
+
+ flwd_sendpacket_build_udp(unsend_raw_data_len + sizeof(flwd_vxlan_hdr_t),
+ htons(50704), /* TODO, �˴���sport�����ڲ��sport, �ڲ�sport��ȫ��ʶ��ij���������ص�, vxlan��sport�������� */
+ htons(64789),
+ NULL,
+ 0,
+ send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t));
+
+ if(CAP_MODEL_SOCKET != send_device_handle->io_para.cap_mode){ /* socketģʽ�ײ���Э��ջ��װ, flowoodֻ������һ��vxlan */
+
+ /* ������� */
+ flwd_sendpacket_do_checksum((char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t),
+ IPPROTO_IP,
+ sizeof(flwd_ipv4_hdr_t));
+ }
+
+ /* TODO, vxlan���ݰ����������Э��ջ����, �����Ȳ�����У����� */
+ outer_vxlan_dr = (flwd_vxlan_hdr_t *)(send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+ memset(outer_vxlan_dr, 0, sizeof(flwd_vxlan_hdr_t));
+ outer_vxlan_dr->link_id = 10;
+ outer_vxlan_dr->link_layer_type = 0; /* 0:ethernet; */
+
+ return send_mbuff;
+}
+
+
+/* ת���������ӽ������ص��豸, ����ײ�ԭʼ���ݰ���ں��� */
+static int flwd_fwd_acc_pkt_input(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ /* TODO:����active_ip <---> GDEVIP ӳ���, ���ݵ�ǰ�ڲ����ݰ���sip, �ҵ�gdev_ip */
+ int ret;
+
+#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻ��ת��������Ҫ��sappһ������ */
+ ///ret = flwd_fwd_to_gdev_in_sapp_vxlan_mode(send_device_handle, tid, raw_pkt);
+ ret = flwd_fwd_to_gdev_in_sapp_raw_marsio_mode(send_device_handle, tid, raw_pkt);
+#else
+ void *send_mbuff ;
+ send_mbuff = flwd_fwd_to_gdev_pre_output(rcv_device_handle, send_device_handle, tid, raw_pkt);
+ if(NULL == send_mbuff){
+ return -1;
+ }
+
+ ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff);
+
+ send_device_handle->low_level_mbuff_free_after_send(send_device_handle, tid, send_mbuff);
+#endif
+
+ return ret;
+}
+
+
+/* GDEV����, ����ײ�ԭʼ���ݰ���ں��� */
+static int flwd_fwd_gdev_pkt_input(flwd_device_handle_t *rcv_device_handle,
+ flwd_device_handle_t *send_device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+ void *send_mbuff ;
+
+ send_mbuff = flwd_fwd_to_acc_pre_output(rcv_device_handle, send_device_handle, tid, raw_pkt);
+ if(NULL == send_mbuff){
+ return -1;
+ }
+
+ ret = send_device_handle->low_level_send(send_device_handle, tid, send_mbuff);
+
+ send_device_handle->low_level_mbuff_free_after_send(send_device_handle, tid, send_mbuff);
+
+ return ret;
+}
+
+static void flwd_fwd_nat_htable_data_free(void *data)
+{
+ flwd_fwd_nat_info_t *fwd_nat_info = (flwd_fwd_nat_info_t *)data;
+
+ flwd_free(fwd_nat_info->tid, data);
+}
+
+/*
+ fwdת����, ��access���ظ���key������㷨�ͺ���, ��data��accessת������ͬ,
+
+ access��data��nat_info��, �洢��inner��outer����Ԫ��,
+
+ fwd��data������outer����Ԫ��, �Լ�DNAT�Ķ�Ԫ��, ֻҪ�������װ�����ָ������, ����Ϊ��flowood����.
+*/
+static void *flwd_fwd_nat_table_create(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 * 256;
+ MESA_htable_set_opt(htable, MHO_HASH_SLOT_SIZE, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_HASH_MAX_ELEMENT_NUM, &flwd_cfg_val.nat_htable_max_num, sizeof(int));
+
+ /* TODO, Ŀǰ���ó�ʱ��̭, �����ļ���ȡ��ʱ���; ����TCPӦ��������״̬��, TCP������������̭, �����ͷ��ڴ� */
+ MESA_htable_set_opt(htable, MHO_EXPIRE_TIME, &flwd_cfg_val.nat_htable_timeout, sizeof(int));
+
+ opt_int = HASH_ELIMINATE_ALGO_LRU;
+ MESA_htable_set_opt(htable, MHO_ELIMIMINATE_TYPE, &opt_int, sizeof(int));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_COMPARE, (void *)&flwd_nat_htable_key_cmp, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_KEY_TO_INDEX, (void *)&flwd_nat_htable_key2index, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_COMPLEX_KEY_DUP, (void *)flwd_nat_htable_key_dup, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_COMPLEX_KEY_FREE, (void *)flwd_nat_htable_key_free, sizeof(void *));
+
+ MESA_htable_set_opt(htable, MHO_CBFUN_DATA_FREE, (void *)&flwd_fwd_nat_htable_data_free, sizeof(void *));
+
+ ///MESA_htable_set_opt(htable, MHO_CBFUN_DATA_EXPIRE_NOTIFY, (void *)&flwd_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 *)"./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;
+}
+
+static void flwd_fwd_store_session_table(int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_vxlan_hdr_t *outer_vxlan_hdr;
+ const flwd_ipv4_hdr_t *outer_ip4_hdr;
+ const flwd_eth_hdr_t *outer_eth_hdr;
+ flwd_tuple5_t nat_key;
+ int ret;
+ flwd_fwd_nat_info_t *fwd_route_info;
+
+ outer_vxlan_hdr = (flwd_vxlan_hdr_t *)((char *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+
+ if(0 == outer_vxlan_hdr->first_pkt_per_stream){
+ /* ���װ� */
+ return;
+ }
+
+ flwd_build_tuple4_key(tid, &nat_key, raw_pkt);
+
+ outer_eth_hdr = (flwd_eth_hdr_t *)raw_pkt->outer_pkt_data;
+ outer_ip4_hdr = ((flwd_ipv4_hdr_t *)raw_pkt->outer_pkt_data + sizeof(flwd_eth_hdr_t));
+
+ fwd_route_info = (flwd_fwd_nat_info_t *)flwd_calloc(tid, 1, sizeof(flwd_fwd_nat_info_t));
+ fwd_route_info->tid = tid;
+ fwd_route_info->flwd_route_info.next_gateway_ip_net = outer_ip4_hdr->ip_src.s_addr;
+ memcpy(fwd_route_info->flwd_route_info.next_gateway_mac, outer_eth_hdr->h_source, 6);
+
+ ret = MESA_htable_add(flwd_thread_val[tid].nat_info_table, (uchar *)&nat_key,
+ sizeof(flwd_tuple5_t), (void *)fwd_route_info);
+ if(ret < 0){
+ flwd_log(30, "FWD: save session %s to htable error, htable ret = %d.",
+ flwd_tuple5_ntop(tid, &nat_key), ret);
+ flwd_free(tid, fwd_route_info);
+ }
+
+ flwd_log(10, "FWD: recv first pkt from acc gateway, save session %s to htable.",
+ flwd_tuple5_ntop(tid, &nat_key));
+
+ return;
+}
+
+/*
+ return value:
+ 1 : ����IRָ������;
+ 0 : ������IRָ������;
+*/
+
+static int flwd_pkt_signature_check(flwd_tuple5_t *tuple5)
+{
+ unsigned int hash_val;
+ unsigned short ir_expect_pkt_signature;
+ unsigned short actual_pkt_signature;
+
+ hash_val = flwd_tuple5_hash(tuple5, 1);
+ ir_expect_pkt_signature = hash_val % (FLWD_UDP_SPORT_HASH_MASK >> 8);
+
+ if(0 == tuple5->dir_reverse){
+ actual_pkt_signature = (ntohs(tuple5->sport_net_order) & FLWD_UDP_SPORT_HASH_MASK) >> 8;
+ }else{
+ actual_pkt_signature = (ntohs(tuple5->dport_net_order) & FLWD_UDP_SPORT_HASH_MASK) >> 8;
+ }
+ if(ir_expect_pkt_signature == actual_pkt_signature){
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/*
+ return value:
+ 1 : �DZ�ϵͳ���õ�����;
+ 0 : ���DZ�ϵͳ���õ�����;
+*/
+static int flwd_fwd_my_pkt_identify(int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ flwd_tuple5_t nat_key;
+ void *hdata;
+
+ flwd_build_tuple4_key(tid, &nat_key, raw_pkt);
+
+ /* ��������ӱ������, ˵���϶���IRϵͳ�İ� */
+ hdata = MESA_htable_search(flwd_thread_val[tid].nat_info_table, (uchar *)&nat_key, sizeof(flwd_tuple5_t));
+ if(hdata != NULL){
+ return 1;
+ }
+
+ /* �����ǰ��nat-session��������, Ҳ������HASHָ�Ƶ�, ���п�����DNAT���װ�, ɨ��һ��DNAT_POLICY */
+ /* TODO,
+ Maatɨ��IR_POLICY_COMPILE��, ���Ƿ�����DNAT����.
+ if(maat_scan() ){
+ return 1;
+ }
+ */
+
+
+ /* ���ӱ��������Ҳ���DNAT����, ������SNAT->S2C����ĵ�����, �ټ��˿��е�HASHֵ */
+
+ if(flwd_pkt_signature_check(&nat_key) == 0){
+ flwd_log(10, "recv tuple4: %s, but not in session_table, not found signature, must inject it back!\n",
+ flwd_tuple5_ntop(tid, &nat_key));
+ return 0;
+ }
+
+ /* TODO,
+ ��������session�����ҵ���, �����п�������Ԫ��������, ����ʶ���IR�İ���,
+ ��ʱ����TCP���а취��������:
+
+ client���ѽ������ӵ�TCP����SYN��, �������᷵����ȷ��ACK, ������client->seq + 1, ������֮�ͻ���, ��ԭ�������Ӳ����κ�Ӱ��.
+
+ Ϊ��̽�������ͻ, ����TCPЭ��, �����flowood�󷢵�SYN, �����ͨ����ظ���ȷ��ACK���, ���Ը�֪��;
+
+ �����flowood������ij���˿�, ����ʵ�ͻ�����ʹ��������˿ڷ���SYN, �������ظ���ACK������ACK����û����, �Ƚ��Ѳ��!!!
+
+ ��������Ԫ�����õ�UDP, ��ô��???
+ */
+
+ return 1;
+}
+
+static int flwd_fwd_pkt_input(flwd_device_handle_t *device_handle, int tid, flwd_raw_pkt_t *raw_pkt)
+{
+ int ret;
+
+ flwd_thread_val[tid].pkt_stat.eth_pkt_num++;
+ flwd_thread_val[tid].pkt_stat.eth_pkt_byte += raw_pkt->outer_pkt_len;
+
+ if(TOPO_FWD_LINK_ACC == device_handle->io_para.topo_mode){
+ ret = flwd_rubbish_pkt_identify(device_handle, raw_pkt, 1);
+ }else{
+ ret = flwd_rubbish_pkt_identify(device_handle, raw_pkt, 1);
+ }
+ if(ret != 0){
+ return FLWD_DROP;
+ }
+
+ ret = flwd_protocol_stack_process(device_handle, tid, raw_pkt);
+ if(ret != 0){
+ return FLWD_DROP;
+ }
+
+ switch((int)device_handle->io_para.topo_mode){
+ case TOPO_FWD_LINK_ACC:
+ /* ��ACC��������, ��Ϊ����flowoodϵͳ�İ�, �װ�Ҫ����session�� */
+ flwd_fwd_store_session_table(tid, raw_pkt);
+ flwd_fwd_acc_pkt_input(device_handle, &flwd_global_val.global_io_handle[TOPO_FWD_LINK_GDEV], tid, raw_pkt);
+ break;
+
+ case TOPO_FWD_LINK_GDEV:
+ if(flwd_fwd_my_pkt_identify(tid, raw_pkt) == 0){
+ /* ��Ϊ�µ���IP����, ����������ʵ�ͻ��˵İ�, �˴�Ҫ��ע */
+ return FLWD_PASS;
+ }
+
+ /* ��FWD��������, ��Ҫ����ʵ��������, �װ������ݰ���signature, ��������ѯsession�� */
+ flwd_fwd_gdev_pkt_input(device_handle, &flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC], tid, raw_pkt);
+ break;
+
+ default:
+ abort();
+ }
+
+ return FLWD_DROP; /* Ĭ����drop, ��Ϊ�󲿷��������Ҫ��ע */
+}
+
+#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻ��ת��������Ҫ��sappһ������ */
+#include "stream.h"
+
+static int flwd_get_sapp_thread_tid(void)
+{
+ int send_tid;
+ int opt_len;
+ int ret;
+
+ ret = sapp_get_platform_opt(SPO_INDEPENDENT_THREAD_ID, &send_tid, &opt_len);
+ if(ret < 0){
+ return -1;
+ }
+
+ return send_tid;
+}
+#endif
+
+
+void *flwd_packet_io_work_thread(void *arg)
+{
+ int ret1 = -1, ret2 = -1, ret3;
+ int action;
+ int tseq = *((int *)arg);
+ flwd_raw_pkt_t raw_pkt;
+ ////unsigned long long last_idle_call_in_ms = 0;
+ flwd_device_handle_t *dev_handle;
+ int tot_work_times = 0; /* ���հ��� */
+ int success_work_times_in_recent_100 = 0; /* ���100�γɹ��Ĵ��� */
+
+#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻ��ת��������Ҫ��sappһ������ */
+ int sapp_send_thread_id;
+ printf("flwd work thread waiting for packet_io init......\n");
+ sleep(10); /* ��Ϊ�˴����ڲ����ʼ������������, ƽ̨�ȵ��ò���ٵ���packet_io, ��ʱ����packet_io_lib��û��ʼ�����, ��ʱ����һ��!! */
+ sapp_send_thread_id = flwd_get_sapp_thread_tid();
+ if(sapp_send_thread_id < 0){
+ abort();
+ }
+
+ flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC].sapp_send_thread_seq = sapp_send_thread_id;
+ flwd_global_val.global_io_handle[TOPO_FWD_LINK_GDEV].sapp_send_thread_seq = sapp_send_thread_id;
+#endif
+
+ while(1){
+ dev_handle = &flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC];
+ ret1 = dev_handle->low_level_pkt_recv(dev_handle, tseq, &raw_pkt.low_level_mbuff);
+ if(ret1 >= 0){
+ raw_pkt.outer_pkt_data= dev_handle->low_level_mbuff_mtod(raw_pkt.low_level_mbuff);
+ raw_pkt.outer_pkt_len = dev_handle->low_level_mbuff_get_pkt_len(raw_pkt.low_level_mbuff);
+ flwd_pre_process_pkt_input(dev_handle, &raw_pkt);
+ action = flwd_fwd_pkt_input(dev_handle, tseq, &raw_pkt);
+ if(FLWD_PASS == action){
+ dev_handle->low_level_mbuff_free_after_send(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }else{
+ dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }
+ }
+
+#if (0 == FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD) /* ֻ��ת��������Ҫ��sappһ������ */
+ dev_handle = &flwd_global_val.global_io_handle[TOPO_FWD_LINK_GDEV];
+ ret2 = dev_handle->low_level_pkt_recv(dev_handle, tseq, &raw_pkt.low_level_mbuff);
+ if(ret2 >= 0){
+ raw_pkt.outer_pkt_data = dev_handle->low_level_mbuff_mtod(raw_pkt.low_level_mbuff);
+ raw_pkt.outer_pkt_len = dev_handle->low_level_mbuff_get_pkt_len(raw_pkt.low_level_mbuff);
+ flwd_pre_process_pkt_input(dev_handle, &raw_pkt);
+ action = flwd_fwd_pkt_input(dev_handle, tseq, &raw_pkt);
+ if(FLWD_PASS == action){
+ dev_handle->low_level_mbuff_free_after_send(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }else{
+ dev_handle->low_level_pkt_free(dev_handle, tseq, raw_pkt.low_level_mbuff);
+ }
+ }
+#endif
+ tot_work_times++;
+
+ if((ret1 < 0) && (ret2 < 0)){
+ ret3 = flwd_idle_call(tseq);
+ if(0 == ret3){
+ /* ����������������, idle_call()Ҳ���¿���, ����һ�� */
+ flwd_adapt_sleep(success_work_times_in_recent_100);
+ }else{
+ success_work_times_in_recent_100++;
+ }
+ }else{
+ success_work_times_in_recent_100++;
+ }
+
+ if(tot_work_times >= 100){
+ /////printf("%d/100\n", success_work_times_in_recent_100);
+ tot_work_times = 0;
+ success_work_times_in_recent_100 = 0;
+ }
+ }
+
+ return NULL;
+}
+
+
+/* ת�����س�ʼ������� */
+int flwd_gateway_init(void)
+{
+ int i, ret;
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "nat_htable_max_num", &flwd_cfg_val.nat_htable_max_num, 50000);
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, "main", "nat_htable_timeout", &flwd_cfg_val.nat_htable_timeout, 30);
+
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ flwd_thread_val[i].nat_info_table = flwd_fwd_nat_table_create();
+ }
+
+ ret = flwd_packet_io_init(TOPO_FWD_LINK_ACC, TOPO_FWD_LINK_GDEV);
+ if(ret < 0){
+ return -1;
+ }
+
+ return 0;
+}
+
+#if FLWD_RUN_AS_SAPP_PLUG && COMPILE_FORWARD /* ֻ��ת��������Ϊ���, ��Ҫ��sappһ������ */
+
+static int flwd_ptk_signature_identify(struct streaminfo *pstream)
+{
+#if FLWD_RUN_IN_CEIEC_TEST
+
+ if((STREAM_TYPE_UDP == pstream->type)
+ && ((3784 == ntohs(pstream->addr.tuple4_v4->source))
+ ||(3784 == ntohs(pstream->addr.tuple4_v4->dest)))){
+ /* TODO: �����g_keepalive����Ѿ�������DROP_PKT, ����Ȼû�б�ƽ̨DROP */
+ return 0;
+ }
+#endif
+
+ /* TODO: ���ݰ�ָ��ʶ�� */
+
+ return 1;
+}
+
+
+int flwd_fwd_to_access_gateway(struct streaminfo *a_tcp, int thread_seq, void *a_packet)
+{
+ flwd_device_handle_t *fwd_send_handle = &flwd_global_val.global_io_handle[TOPO_FWD_LINK_ACC];
+ const flwd_ipv4_hdr_t *ipv4_hdr;
+ const flwd_ipv6_hdr_t *ipv6_hdr;
+ int inner_raw_data_len = 0;
+ flwd_vxlan_hdr_t *outer_vxlan_dr;
+ int ret;
+ flwd_eth_hdr_t *inner_eth_hdr;
+
+ if(NULL == a_packet){ /* ������ƽ̨����ʱ����״̬,��û�а� */
+ return 0;
+ }
+
+ flwd_log(10, "FWD: recv pkt from gdev, inner_tuple4: %s!",
+ flwd_debug_print_tuple4_detail(a_packet, thread_seq));
+
+ if(ADDR_TYPE_IPV4 == a_tcp->addr.addrtype){
+ ipv4_hdr = (flwd_ipv4_hdr_t *)a_packet;
+ inner_raw_data_len = ntohs(ipv4_hdr->ip_len) + sizeof(flwd_eth_hdr_t);
+ }else{
+ ipv6_hdr = (flwd_ipv6_hdr_t *)a_packet;
+ inner_raw_data_len = ntohs(ipv6_hdr->ip6_payload_len) + sizeof(flwd_ipv6_hdr_t) + sizeof(flwd_eth_hdr_t);
+ }
+
+ void *send_mbuff = fwd_send_handle->low_level_mbuff_malloc(fwd_send_handle, thread_seq, inner_raw_data_len + FLWD_VXLAN_OUTER_PACKET_LEN);
+ char *send_buf_data_ptr = fwd_send_handle->low_level_mbuff_mtod(send_mbuff);
+
+ /* fwd�յ���ԭʼ��copy�������͵Ļ����� */
+ memcpy(send_buf_data_ptr+sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t)+sizeof(flwd_eth_hdr_t),
+ a_packet,
+ inner_raw_data_len);
+
+ /* ���ڲ�ethernet, �����eth����, TODO, �ڲ�MAC */
+ inner_eth_hdr = (flwd_eth_hdr_t *)(send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t));
+ if(ADDR_TYPE_IPV4 == a_tcp->addr.addrtype){
+ inner_eth_hdr->h_proto = htons(ETH_P_IP);
+ }else{
+ inner_eth_hdr->h_proto = htons(ETH_P_IPV6);
+ }
+
+ /* ָ����ǰ�ƶ�, Ԥ��vxlan���ռ� */
+
+ /* ����ײ�vxlan��Ϣ, ���迼�Ƿ������, ��Ϊ�����ڲ���Ԫ��hash����, vxlan����ַ����·��Ѱַ���� */
+
+ /* ��ײ�ethernet, ��Ϊʹ��socketģʽ����access, ����Ԥ���ռ�Ϳ���, ���ù��� */
+
+ /* TODO:
+ fwdҪ��Դ�˿��л�ȡaccess_id, ��������̨access, ӳ���access��IP��ַ,
+ ����ʱֻ��һ̨����, ���ñ���loopback.
+ */
+
+ /* ���ipv4ͷ�� */
+ flwd_sendpacket_build_ipv4(inner_raw_data_len + sizeof(flwd_udp_hdr_t) + sizeof(flwd_vxlan_hdr_t), /* �ڲ�ԭʼ�� + UDP��ͷ + vxlanͷ */
+ 0,
+ 0x1234,
+ 0,
+ 64,
+ IPPROTO_UDP,
+ 0x0100007f,
+ 0x0100007f,
+ NULL,
+ 0,
+ (char *)send_buf_data_ptr + sizeof(flwd_eth_hdr_t));
+ /* ���udpͷ�� */
+ flwd_sendpacket_build_udp(inner_raw_data_len + sizeof(flwd_vxlan_hdr_t),
+ htons(60000 + thread_seq), /* TODO, �˴���sport�����ڲ��sport, �ڲ�sport��ȫ��ʶ��ij���������ص�, vxlan��sport�������� */
+ htons(50000 + thread_seq),
+ NULL,
+ 0,
+ send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t));
+
+ /* ����vxlan, UDP��У��Ϳ������0 */
+
+ /* ���vxlanͷ�� */
+ outer_vxlan_dr = (flwd_vxlan_hdr_t *)(send_buf_data_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+ memset(outer_vxlan_dr, 0, sizeof(flwd_vxlan_hdr_t));
+
+ outer_vxlan_dr->link_id = 1; /* TODO, vxlan��Ϣ�����ݰ��л�ȡ */
+ outer_vxlan_dr->link_layer_type = 0; /* 0:ethernet; */
+
+ fwd_send_handle->low_level_mbuff_set_pkt_len(send_mbuff, inner_raw_data_len + FLWD_VXLAN_OUTER_PACKET_LEN);
+
+ char debug_outer_tuple4[128];
+ ret = fwd_send_handle->low_level_send(fwd_send_handle, thread_seq, send_mbuff);
+ if(ret < 0){
+ flwd_log(30, "FWD: send pkt to access gateway error! inner_tuple4 is:%s, outer_tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(a_packet, thread_seq),
+ flwd_debug_print_tuple4_detail_r(send_buf_data_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128));
+ }else{
+ flwd_log(10, "FWD: send pkt to access gateway succ! inner_tuple4 is:%s, outer_tuple4 is:%s\n",
+ flwd_debug_print_tuple4_detail(a_packet, thread_seq),
+ flwd_debug_print_tuple4_detail_r(send_buf_data_ptr + sizeof(flwd_eth_hdr_t), debug_outer_tuple4, 128));
+ }
+
+ return ret;
+}
+
+extern "C" char IPREUSE_TCPALL_ENTRY(struct streaminfo *a_tcp,void **pme, int thread_seq, void *a_packet)
+{
+ char ret = APP_STATE_GIVEME | APP_STATE_FAWPKT;
+ /*
+ NOTE:
+ ����DNAT, �װ�����֮��, ����DIP%access_num, ����һ���������ػش�.
+
+ ����SNAT, �ڶ������϶���SYN/ACK, ͨ�������ı�־����Ƿ�������������ʵ������
+ �����������ݵ�ǰ���Ķ˿ڷ�Χ, �õ����ĸ�access������, �ظ���̨access.
+ */
+
+ switch(a_tcp->pktstate){
+ case OP_STATE_PENDING:
+ if(flwd_ptk_signature_identify(a_tcp) == 0){
+ return APP_STATE_DROPME | APP_STATE_FAWPKT; /* ����IR�� */
+ }
+
+ flwd_fwd_to_access_gateway(a_tcp, thread_seq, a_packet);
+ break;
+
+ case OP_STATE_DATA:
+ flwd_fwd_to_access_gateway(a_tcp, thread_seq, a_packet);
+ ret = APP_STATE_GIVEME; /* ��IR�� */
+ break;
+
+ case OP_STATE_CLOSE:
+ flwd_fwd_to_access_gateway(a_tcp, thread_seq, a_packet);
+ ret = APP_STATE_DROPME;
+ break;
+
+ default:
+ ret = APP_STATE_DROPME | APP_STATE_FAWPKT;
+ break;
+ }
+
+
+ return ret;
+}
+
+extern "C" char IPREUSE_UDP_ENTRY(struct streaminfo *a_udp, void **pme, int thread_seq, void *a_packet)
+{
+ char ret = APP_STATE_GIVEME | APP_STATE_FAWPKT;
+ /*
+ NOTE:
+ ����DNAT, �װ�����֮��, ����DIP%access_num, ����һ���������ػش�.
+
+ ����SNAT, �ڶ������϶���SYN/ACK, ͨ�������ı�־����Ƿ�������������ʵ������
+ �����������ݵ�ǰ���Ķ˿ڷ�Χ, �õ����ĸ�access������, �ظ���̨access.
+ */
+
+ switch(a_udp->pktstate){
+ case OP_STATE_PENDING:
+ if(flwd_ptk_signature_identify(a_udp) == 0){
+ return APP_STATE_DROPME | APP_STATE_FAWPKT; /* ����IR�� */
+ }
+ flwd_fwd_to_access_gateway(a_udp, thread_seq, a_packet);
+ ret = APP_STATE_GIVEME | APP_STATE_FAWPKT;
+ break;
+
+
+ case OP_STATE_DATA:
+ flwd_fwd_to_access_gateway(a_udp, thread_seq, a_packet);
+ ret = APP_STATE_GIVEME;
+ break;
+
+ case OP_STATE_CLOSE:
+ flwd_fwd_to_access_gateway(a_udp, thread_seq, a_packet);
+ ret = APP_STATE_DROPME;
+ break;
+
+ default:
+ ret = APP_STATE_DROPME | APP_STATE_FAWPKT; /* ����IR�� */
+ break;
+ }
+
+
+ return ret;
+
+}
+
+extern "C" char IPREUSE_IPv4_ENTRY(struct streaminfo *pstream,unsigned char routedir,int thread_seq, const flwd_ipv4_hdr_t * ipv4_hdr)
+{
+ /*
+ TODO:
+ ��TCP, UDP��Э���ڴ˴���, ��Ϊ���������϶��������˹���,
+ ����ͨIPЭ��, �޷������ĸ��Ǹ����������ĸ�����ʵ����������ע.
+
+ TODO:
+ ICMP, IGMP, GRE, ���������ȵ�, ��AH, ESP.
+ */
+
+ return APP_STATE_DROPME | APP_STATE_FAWPKT;
+}
+
+extern "C" char IPREUSE_IPv6_ENTRY(const struct streaminfo *pstream,unsigned char routedir,int thread_seq, const flwd_ipv6_hdr_t *ipv6_hdr)
+{
+
+ /*
+ TODO:
+ ��TCP, UDP��Э���ڴ˴���, ��Ϊ���������϶��������˹���,
+ ����ͨIPЭ��, �޷������ĸ��Ǹ����������ĸ�����ʵ����������ע.
+
+ TODO:
+ ICMP, IGMP, GRE, ���������ȵ�, ��AH, ESP.
+ */
+
+ return APP_STATE_DROPME | APP_STATE_FAWPKT;
+}
+
+#endif
+
+
diff --git a/src/forward/flwd_fwd_idle_call.c b/src/forward/flwd_fwd_idle_call.c
new file mode 100644
index 0000000..27101d8
--- /dev/null
+++ b/src/forward/flwd_fwd_idle_call.c
@@ -0,0 +1,5 @@
+
+int flwd_idle_call(int tid)
+{
+ return 0;
+}
diff --git a/src/forward/flwd_fwd_maat.c b/src/forward/flwd_fwd_maat.c
new file mode 100644
index 0000000..9b6dda8
--- /dev/null
+++ b/src/forward/flwd_fwd_maat.c
@@ -0,0 +1,40 @@
+#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 "Maat_rule.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>
+
+int flwd_fwd_maat_init(void)
+{
+#if 0 == FLWD_NO_MAAT
+ int ret = flwd_maat_summon();
+ if(ret < 0){
+ return -1;
+ }
+
+ flwd_maat_table_register((int)FLWD_MAAT_TB_IR_POLICY_COMPILE);
+ flwd_maat_table_register((int)FLWD_MAAT_TB_IR_POLICY_GROUP);
+
+ /* SYN��ɨ���Ƿ�DNAT */
+ flwd_maat_table_register((int)FLWD_MAAT_TB_IR_POLICY_IP);
+
+ /* ��������SYN/ACK��, ɨ��IR_DYN_CONN_IP, ���߸��ݰ�ָ��ʶ�� */
+ flwd_maat_table_register((int)FLWD_MAAT_TB_IR_DYN_CONN_IP);
+
+#endif
+
+ return 0;
+}
+
diff --git a/src/packet_io/Makefile b/src/packet_io/Makefile
new file mode 100644
index 0000000..5a2d790
--- /dev/null
+++ b/src/packet_io/Makefile
@@ -0,0 +1,34 @@
+#CC=gcc
+CC=g++
+CCC=g++
+
+TARGET=flwd_io_pcap.so flwd_io_socket.so flwd_packet_io.o
+
+CFLAGS +=-g -Wall -fPIC -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= ../../bin/ip_reuse_io_lib/
+LIB=-L/opt/MESA/lib -lpthread
+
+
+all:$(TARGET)
+
+.c.o:
+ $(CC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+.cpp.o:
+ $(CCC) -c $(CFLAGS) -I. $(H_DIR) $<
+
+flwd_io_pcap.so:flwd_packet_io_pcap.o
+ $(CCC) -o $@ -shared -g -Wall $(CFLAGS) $(H_DIR) $^ -lpcap
+ cp $@ $(LIBPATH)
+
+flwd_io_socket.so:flwd_packet_io_socket.o
+ $(CCC) -o $@ -shared -g -Wall $(CFLAGS) $(H_DIR) $^
+ cp $@ $(LIBPATH)
+
+clean:
+ rm -f *.o
diff --git a/src/packet_io/flwd_io_pcap.so b/src/packet_io/flwd_io_pcap.so
new file mode 100644
index 0000000..7af3822
--- /dev/null
+++ b/src/packet_io/flwd_io_pcap.so
Binary files differ
diff --git a/src/packet_io/flwd_io_socket.so b/src/packet_io/flwd_io_socket.so
new file mode 100644
index 0000000..7db273b
--- /dev/null
+++ b/src/packet_io/flwd_io_socket.so
Binary files differ
diff --git a/src/packet_io/flwd_packet_io.c b/src/packet_io/flwd_packet_io.c
new file mode 100644
index 0000000..a6f8449
--- /dev/null
+++ b/src/packet_io/flwd_packet_io.c
@@ -0,0 +1,193 @@
+/*
+ ���������ĸ��ӿ�, ��������ģʽ,
+ ÿ���������ж����߳�, ������TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWDӦ�ù��ý���/�����߳�,
+ ��Ϊ�ڲ���NATת����, �շ���������ʹ��ͬһ��, ����Ƕ��߳�, ��Ҫ����.
+
+ ����, ֧��TOPO_ACC_LINK_USER, TOPO_ACC_LINK_FWDΪ��ͬ�IJ���ģʽ,
+ �������÷�����ģʽ����������֮�������л���ȡ���ݰ�.
+*/
+
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include "MESA_handle_logger.h"
+#include "MESA_prof_load.h"
+#include <linux/limits.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+
+
+typedef struct{
+ flwd_cap_mode_t cap_mode;
+ char *lib_name;
+}flwd_io_lib_name_type_t;
+
+
+static const flwd_io_lib_name_type_t g_packet_io_type_name_info[] =
+{
+ {CAP_MODEL_PAG , (char *)"flwd_io_pag.so" },
+ {CAP_MODEL_PCAP_ONLINE , (char *)"flwd_io_pcap.so" },
+ {CAP_MODEL_SOCKET , (char *)"flwd_io_socket.so" },
+ {CAP_MODEL_PFRING , (char *)"flwd_io_pfring.so" },
+ {CAP_MODEL_DPDK , (char *)"flwd_io_dpdk.so" },
+ {CAP_MODEL_PPF , (char *)"flwd_io_ppf.so" },
+ {CAP_MODEL_NPACKET , (char *)"flwd_io_npacket.so" },
+ {CAP_MODEL_QNF , (char *)"flwd_io_qnf.so" },
+ {CAP_MODEL_N95 , (char *)"flwd_io_n95.so" },
+ {CAP_MODEL_PCAP_DUMPLIST , (char *)"flwd_io_pcap.so"},
+ {CAP_MODEL_TOPSEC , (char *)"flwd_io_topsec.so"},
+ {CAP_MODEL_IPFILE , (char *)"flwd_io_ipfile.so"},
+ {CAP_MODEL_MARSIOV4 , (char *)"flwd_io_marsio.so"},
+ {CAP_MODEL_AGENT_SMITH , (char *)"flwd_io_agent_smith.so"},
+ {CAP_MODEL_DPDK_VXLAN , (char *)"flwd_io_dpdk_vxlan.so"},
+ {CAP_MODEL_MARSIOV4_VXLAN , (char *)"flwd_io_marsio_vxlan.so"},
+ {CAP_MODEL_PAG_MARSIO , (char *)"flwd_io_pag_marsio.so"},
+};
+
+const flwd_packet_io_cfg_para_t g_packet_io_cfg_para[__TOPO_MODE_MAX] =
+{
+ {TOPO_ACC_LINK_USER, FLWD_MACRO_TO_STRING(TOPO_ACC_LINK_USER), "#todo"},
+ {TOPO_ACC_LINK_FWD, FLWD_MACRO_TO_STRING(TOPO_ACC_LINK_FWD), "#todo"},
+ {TOPO_FWD_LINK_ACC, FLWD_MACRO_TO_STRING(TOPO_FWD_LINK_ACC), "#doto"},
+ {TOPO_FWD_LINK_GDEV, FLWD_MACRO_TO_STRING(TOPO_FWD_LINK_GDEV), "#doto"},
+};
+
+static int flwd_packet_io_lib_load(flwd_device_handle_t *global_dev_handle)
+{
+ char full_lib_path[PATH_MAX];
+ void *dlopen_handle;
+
+ switch((int)global_dev_handle->io_para.cap_mode){
+ case CAP_MODEL_PCAP_ONLINE:
+ case CAP_MODEL_SOCKET:
+ case CAP_MODEL_MARSIOV4:
+ break;
+
+ default:
+ flwd_log(RLOG_LV_FATAL, "not support cap_mode:%d\n", (int)global_dev_handle->io_para.cap_mode);
+ return -1;
+ break;
+ }
+
+ snprintf(full_lib_path, PATH_MAX, "%s/%s", "ip_reuse_io_lib", g_packet_io_type_name_info[(int)global_dev_handle->io_para.cap_mode].lib_name);
+
+ dlopen_handle = dlopen(full_lib_path, RTLD_LAZY | RTLD_LOCAL);
+ if(NULL == dlopen_handle){
+ flwd_log(RLOG_LV_FATAL, "dlopen %s error, %s", full_lib_path, dlerror());
+ return -1;
+ }
+ global_dev_handle->low_level_io_init = (int (*)(struct __flwd_device_handle *h))dlsym(dlopen_handle, "low_level_io_init");
+ global_dev_handle->low_level_io_run = (void (*)(struct __flwd_device_handle *h))dlsym(dlopen_handle, "low_level_io_run");
+ global_dev_handle->low_level_pkt_recv = (int (*)(struct __flwd_device_handle *h, int tid, void **mbuff))dlsym(dlopen_handle, "low_level_pkt_recv");
+ global_dev_handle->low_level_pkt_free = (void (*)(struct __flwd_device_handle *h, int tid, void *mbuff))dlsym(dlopen_handle, "low_level_pkt_free");
+ global_dev_handle->low_level_mbuff_malloc = (void * (* )(struct __flwd_device_handle *h, int tid, int len)) dlsym(dlopen_handle, "low_level_mbuff_malloc");
+ global_dev_handle->low_level_mbuff_free = (void (* )(struct __flwd_device_handle *h, int, void *mbuff)) dlsym(dlopen_handle, "low_level_mbuff_free");
+ global_dev_handle->low_level_mbuff_free_after_send = (void (* )(struct __flwd_device_handle *h, int, void *mbuff)) dlsym(dlopen_handle, "low_level_mbuff_free_after_send");
+ global_dev_handle->low_level_mbuff_mtod = (char * (* )(void *mbuff))dlsym(dlopen_handle, "low_level_mbuff_mtod");
+ global_dev_handle->low_level_mbuff_data_append = (char * (*)(void *mbuff, const char *user_data, int user_data_len))dlsym(dlopen_handle, "low_level_mbuff_data_append");
+ global_dev_handle->low_level_mbuff_data_forward = (char * (*)(void *mbuff, int n))dlsym(dlopen_handle, "low_level_mbuff_data_forward");
+ global_dev_handle->low_level_mbuff_data_rearward = (char * (*)(void *mbuff, int n))dlsym(dlopen_handle, "low_level_mbuff_data_rearward");
+ global_dev_handle->low_level_mbuff_get_pkt_len = (int (*)(void *mbuff))dlsym(dlopen_handle, "low_level_mbuff_get_pkt_len");
+ global_dev_handle->low_level_mbuff_set_pkt_len = (void (*)(void *mbuff, int pkt_len)) dlsym(dlopen_handle, "low_level_mbuff_set_pkt_len");
+ global_dev_handle->low_level_send = (int (*)(struct __flwd_device_handle *h, int tid, void *mbuff))dlsym(dlopen_handle, "low_level_send");
+
+ return 0;
+}
+
+static void *flwd_packet_io_run_thread(void *arg)
+{
+ flwd_device_handle_t *global_io_handle = (flwd_device_handle_t *)arg;
+
+ global_io_handle->low_level_io_run(global_io_handle);
+
+ while(1){
+ pause();
+ }
+
+ return NULL;
+}
+
+
+
+void flwd_packet_io_run(void)
+{
+ int i;
+ pthread_t recv_thread_pid[FLWD_MAX_THREAD_NUM];
+ pthread_t run_thread_pid[FLWD_MAX_THREAD_NUM];
+ static int thread_seq[FLWD_MAX_THREAD_NUM];
+
+ for(i = 0; i < flwd_cfg_val.tot_thread_count; i++){
+ thread_seq[i] = i;
+ pthread_create(&recv_thread_pid[i], NULL, flwd_packet_io_work_thread, (void *)&thread_seq[i]);
+ }
+
+ /* NOTE:
+ ��ijЩ�ײ�IO����Լ, ���ܵ�����io_run�����հ����̾���Ҳ�޷�������, ��pcap_loop()�Ⱥ���, ������Ҫ��̬�����հ��߳�,
+ ������marsio��IO��, �������հ���ѯģʽ, flwd_packet_io_run_thread�̴߳�����һֱ����, ʵ��������.
+ */
+ for(i = 0; i < __TOPO_MODE_MAX; i++){
+ if(flwd_global_val.global_io_handle[i].low_level_io_handle != NULL){
+ pthread_create(&run_thread_pid[i], NULL, flwd_packet_io_run_thread, (void *)&flwd_global_val.global_io_handle[i]);
+ }
+ }
+}
+
+/*
+ ÿ�����س�ʼ�������豸.
+*/
+int flwd_packet_io_init(flwd_topology_t first_top_mode, flwd_topology_t second_top_mode)
+{
+ char str_tmp[128];
+ int ret, int_tmp;
+ int i;
+
+ for(i = 0; i < (int)__TOPO_MODE_MAX; i++){
+ if((i != first_top_mode) && (i != second_top_mode)){
+ continue;
+ }
+ /* NOTE: ��ȡ�����ļ�, ��ȡ��������ز��� */
+ flwd_global_val.global_io_handle[i].io_para.topo_mode = (flwd_topology_t)i;
+
+ MESA_load_profile_int_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "cap_mode", &int_tmp, 0);
+ if(int_tmp <= 0 || int_tmp > CAP_MODEL_PAG_MARSIO){
+ flwd_log(RLOG_LV_FATAL, "get config %s->cap_mode error!", g_packet_io_cfg_para[i].cfg_file_section);
+ return -1;
+ }
+ flwd_global_val.global_io_handle[i].io_para.cap_mode = (flwd_cap_mode_t)int_tmp;
+
+ MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "device_name", str_tmp, 128, "#");
+ if('#' == str_tmp[0]){
+ flwd_log(RLOG_LV_FATAL, "get config %s->device_name error!", g_packet_io_cfg_para[i].cfg_file_section);
+ return -1;
+ }
+ flwd_global_val.global_io_handle[i].io_para.device_name = strdup(str_tmp);
+
+ MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[i].cfg_file_section, "pkt_filter", str_tmp, 128, "#");
+ if('#' == str_tmp[0]){
+ flwd_global_val.global_io_handle[i].io_para.pkt_filter = NULL;
+ }else{
+ flwd_global_val.global_io_handle[i].io_para.pkt_filter = strdup(str_tmp);
+ }
+
+ /* NOTE: dlopen�򿪵ײ�IO����, ��io_pcap.so, io_marsio.so��, ��ȡ��غ���ָ�� */
+ ret = flwd_packet_io_lib_load(&flwd_global_val.global_io_handle[i]);
+ if(ret < 0){
+ flwd_log(RLOG_LV_FATAL, "%s, flwd_packet_io_lib_load() error!", g_packet_io_cfg_para[i].cfg_file_section);
+ return -1;
+ }
+
+ ret = flwd_global_val.global_io_handle[i].low_level_io_init(&flwd_global_val.global_io_handle[i]);
+ if(ret < 0){
+ flwd_log(RLOG_LV_FATAL, "%s low_level_init() error!", g_packet_io_cfg_para[i].cfg_file_section);
+ return -1;
+ }
+ }
+
+ flwd_log(RLOG_LV_DEBUG, "flwd_packet_io_init success!");
+
+ return 0;
+}
+
diff --git a/src/packet_io/flwd_packet_io_pcap.c b/src/packet_io/flwd_packet_io_pcap.c
new file mode 100644
index 0000000..adb584e
--- /dev/null
+++ b/src/packet_io/flwd_packet_io_pcap.c
@@ -0,0 +1,428 @@
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include <pcap/pcap.h>
+#include "MESA_list_queue.h"
+#include "MESA_handle_logger.h"
+#include "MESA_prof_load.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+
+#ifdef __cplusplus
+/* ��Ҫ��̬dlopen��ȡ������, ʹ��C�淶 */
+extern "C" {
+#endif
+
+
+typedef struct {
+ pthread_t pid;
+ unsigned char thread_seq;
+ int sd_raw_eth; /* �ײ㷢��socket��� */
+ struct sockaddr sock_addr;
+ MESA_lqueue_head pkt_queue;
+}pcap_work_thread_t;
+
+typedef struct{
+ char *__data_buf; /* mbuff������ͷָ�� */
+ char *data_actual_ptr; /* ��ǰ����ʵ�ʴ洢������ָ�� */
+ int __data_buf_max_len; /* mbuff��󻺴泤��, ��FLWD_LINK_MTU */
+ int data_actual_len; /* ��ǰ������ʵ�ʴ洢�����ݳ��� */
+}pcap_mbuff_t;
+
+/* pcapģʽ�ڲ�����ṹ */
+typedef struct{
+ int tot_thread_count;
+ pcap_t *pcap_dev_handle;
+ pcap_work_thread_t pcap_io_thread_para[FLWD_MAX_THREAD_NUM];
+ pcap_mbuff_t pcap_send_buf[FLWD_MAX_THREAD_NUM]; /* ��������, ��ʼ��ʱ����, �Ժ󷢰�����ÿ�ζ�̬malloc/free */
+}flwd_device_handle_pcap_t;
+
+typedef struct{
+ char *pkt_data;
+ int pkt_len;
+}pcap_queue_item_t;
+
+/* 2012-04-10 LiJia add, ��ȡ����MAC��ַ
+����:
+ device: ��������
+ mac: �洢MAC��ַ������,���Ϊ������,
+ ������MAC��ַΪ11:22:33:44:55:66,��mac[0]Ϊ0x11,mac[5]Ϊ0x66.
+����ֵ:
+ 0: ����
+ -1:����
+*/
+static int MESA_get_dev_mac(const char *device, unsigned char mac[6])
+{
+ struct ifreq ifr;
+ int fd;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if(fd < 0)
+ {
+ return -1;
+ }
+
+ memset(ifr.ifr_ifrn.ifrn_name, 0, sizeof(ifr.ifr_ifrn.ifrn_name));
+ strncpy(ifr.ifr_ifrn.ifrn_name, device, sizeof(ifr.ifr_ifrn.ifrn_name));
+ if(ioctl(fd, SIOCGIFHWADDR, &ifr) == -1)
+ {
+ printf("Cann't get hwaddr of %s:%s\n", device, strerror(errno));
+ goto err_exit;
+ }
+
+ if(ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
+ {
+ printf("'%s' is not ethernet interface!\n", device);
+ goto err_exit;
+ }
+
+ memcpy(mac, ifr.ifr_ifru.ifru_addr.sa_data, 6);
+
+ close(fd);
+
+ return 0;
+
+err_exit:
+ close(fd);
+ return -1;
+}
+
+static inline int flwd_pcap_dispatch_thread(flwd_device_handle_pcap_t *pcap_io_handle, const u_char *data)
+{
+ int to_work_thread_seq;
+ const flwd_eth_hdr_t *flwd_eth_hdr = (flwd_eth_hdr_t *)data;
+ const flwd_ipv4_hdr_t *flwd_ip_hdr;
+
+ if(ETH_P_IP == ntohs(flwd_eth_hdr->h_proto)){
+ flwd_ip_hdr = (flwd_ipv4_hdr_t *)(data + sizeof(flwd_eth_hdr_t));
+ to_work_thread_seq = (flwd_ip_hdr->ip_src.s_addr ^ flwd_ip_hdr->ip_dst.s_addr) % pcap_io_handle->tot_thread_count;
+ }else{
+ to_work_thread_seq = 0;/* ����Э��Ĭ����0���� */
+ }
+
+ return to_work_thread_seq;
+}
+
+
+
+static pcap_mbuff_t *flwd_pcap_create_new_mbuff(u_char *data, int datalen)
+{
+ pcap_mbuff_t *pcap_mbuff;
+
+ pcap_mbuff = (pcap_mbuff_t *)calloc(1, sizeof(pcap_mbuff_t));
+
+ pcap_mbuff->__data_buf = (char *)malloc(datalen + FLWD_VXLAN_OUTER_PACKET_LEN); /* Ԥ��vxlanͷ�� */
+ pcap_mbuff->__data_buf_max_len = datalen + FLWD_VXLAN_OUTER_PACKET_LEN;
+
+
+ pcap_mbuff->data_actual_ptr = pcap_mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN;
+ pcap_mbuff->data_actual_len = datalen;
+
+ memcpy(pcap_mbuff->data_actual_ptr, data, datalen);
+
+ return pcap_mbuff;
+}
+
+
+static void flwd_pcap_pkt_handle(u_char *user, const struct pcap_pkthdr *hdr, const u_char *data)
+{
+ int to_work_thread_seq;
+ pcap_mbuff_t *pcap_mbuff;
+ flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)user;
+
+ to_work_thread_seq = flwd_pcap_dispatch_thread(pcap_io_handle, data);
+
+ pcap_mbuff = flwd_pcap_create_new_mbuff((u_char *)data, hdr->caplen);
+
+ /* NOTE: �˴������������ӿ�, ��Ϊpcap_loop�ڶ������߳������Ŀռ�, ��Ӱ���������� */
+ int ret = MESA_lqueue_join_tail(pcap_io_handle->pcap_io_thread_para[to_work_thread_seq].pkt_queue, &pcap_mbuff, sizeof(void *));
+ if(ret < 0){
+ free(pcap_mbuff->__data_buf);
+ free(pcap_mbuff);
+ printf("pcap io thread MESA_lqueue_join_tail() error, ret=%d\n", ret);
+ }
+
+}
+
+static int pcap_low_level_io_init(flwd_device_handle_t *global_dev_handle)
+{
+ int i;
+ char pcap_errbuf[PCAP_ERRBUF_SIZE];
+ char str_tmp[128];
+ struct bpf_program bpf_filter;
+
+ flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)calloc(1, sizeof(flwd_device_handle_pcap_t));
+
+ pcap_io_handle->pcap_dev_handle = pcap_open_live(global_dev_handle->io_para.device_name, 4096, 1, 1, pcap_errbuf);
+ if(NULL == pcap_io_handle->pcap_dev_handle){
+ flwd_log(RLOG_LV_FATAL, "pcap_open_live() error, %s\n", pcap_errbuf);
+ return -1;
+ }
+ /* TODO, set filter */
+ if(global_dev_handle->io_para.pkt_filter != NULL){
+ if(pcap_compile(pcap_io_handle->pcap_dev_handle, &bpf_filter, (char *)global_dev_handle->io_para.pkt_filter, 1, 0) < 0){
+ flwd_log(RLOG_LV_FATAL, "pcap_compile() error, invalid pkt_filter: %s\n", global_dev_handle->io_para.pkt_filter);
+ return -1;
+ }
+
+ pcap_setfilter(pcap_io_handle->pcap_dev_handle, &bpf_filter);
+ }
+
+ pcap_setdirection(pcap_io_handle->pcap_dev_handle, PCAP_D_IN); /* ֻ���հ� */
+
+ for(i = 0; i < global_dev_handle->tot_thread_count; i++){
+ pcap_io_handle->pcap_io_thread_para[i].thread_seq = i;
+ pcap_io_handle->pcap_send_buf[i].__data_buf = (char *)malloc(FLWD_LINK_MTU);
+ pcap_io_handle->pcap_send_buf[i].__data_buf_max_len = FLWD_LINK_MTU;
+ pcap_io_handle->pcap_io_thread_para[i].sd_raw_eth = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
+
+ snprintf(pcap_io_handle->pcap_io_thread_para[i].sock_addr.sa_data,
+ sizeof(pcap_io_handle->pcap_io_thread_para[i].sock_addr.sa_data),
+ "%s", global_dev_handle->io_para.device_name);
+
+ pcap_io_handle->pcap_io_thread_para[i].pkt_queue = MESA_lqueue_create(1, 50000);
+ }
+
+ MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "addr_para", str_tmp, 128, "#");
+ if('#' == str_tmp[0]){
+ flwd_log(RLOG_LV_FATAL, "get config %s->addr_para error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+ if(inet_pton(AF_INET, str_tmp, &global_dev_handle->io_para.device_ip_net_order) <= 0){
+ flwd_log(RLOG_LV_FATAL, "config %s->addr_para type invalid!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+
+ MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "addr_mask", str_tmp, 128, "#");
+ if('#' == str_tmp[0]){
+ flwd_log(RLOG_LV_FATAL, "get config %s->addr_mask error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+ if(inet_pton(AF_INET, str_tmp, &global_dev_handle->io_para.device_ip_mask_net_order) <= 0){
+ flwd_log(RLOG_LV_FATAL, "config %s->addr_mask type invalid!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+
+ MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "gateway_ip", str_tmp, 128, "#");
+ if('#' == str_tmp[0]){
+ flwd_log(RLOG_LV_FATAL, "get config %s->gateway_ip error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+ if(inet_pton(AF_INET, str_tmp, &global_dev_handle->io_para.gateway_ip_net_order) <= 0){
+ flwd_log(RLOG_LV_FATAL, "config %s->gateway_ip type invalid!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+
+
+ MESA_get_dev_mac(global_dev_handle->io_para.device_name, global_dev_handle->io_para.local_mac_addr);
+
+ pcap_io_handle->tot_thread_count = global_dev_handle->tot_thread_count;
+ global_dev_handle->low_level_io_handle = (void *)pcap_io_handle;
+
+ return 0;
+}
+
+static int pcap_low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff)
+{
+ int ret;
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+ flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)global_dev_handle->low_level_io_handle;
+
+ ret = sendto(pcap_io_handle->pcap_io_thread_para[tid].sd_raw_eth,
+ pcap_mbuff->data_actual_ptr,
+ pcap_mbuff->data_actual_len,
+ MSG_DONTWAIT,
+ (const struct sockaddr *)&pcap_io_handle->pcap_io_thread_para[tid].sock_addr,
+ sizeof(struct sockaddr));
+
+ return ret;
+}
+
+
+
+
+int low_level_pkt_recv(flwd_device_handle_t *g_dev_handle, int tid, void **mbuff)
+{
+ int ret, try_times;
+ pcap_mbuff_t *pcap_mbuff;
+ long recv_len;
+ flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)g_dev_handle->low_level_io_handle;
+
+ recv_len = sizeof(void *);
+
+ for(try_times = 0; try_times < 20; try_times++){
+ /* NOTE: ��Ϊ��trylock, �dz�����ʧ��, �����������Լ��� */
+ ret = MESA_lqueue_try_get_head(pcap_io_handle->pcap_io_thread_para[tid].pkt_queue, &pcap_mbuff, &recv_len);
+ switch(ret){
+ case 0: //OK
+ goto done;
+ break;
+
+ case -5: //empty, no packet
+ return -1;
+ }
+ }
+
+ if(ret < 0){
+ return -1;
+ }
+
+done:
+ *mbuff = (void *)pcap_mbuff;
+
+ return pcap_mbuff->data_actual_len;
+}
+
+void low_level_pkt_free(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff)
+{
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+
+ free(pcap_mbuff->__data_buf);
+ free(pcap_mbuff);
+
+ return;
+}
+
+
+void *low_level_mbuff_malloc(flwd_device_handle_t *g_dev_handle, int tid, int len)
+{
+ ///flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)g_dev_handle->low_level_io_handle;
+
+ pcap_mbuff_t *mbuff = (pcap_mbuff_t *)malloc(sizeof(pcap_mbuff_t));
+
+ mbuff->__data_buf = (char *)malloc(FLWD_LINK_MTU);
+ mbuff->data_actual_ptr = mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN;
+ mbuff->__data_buf_max_len = FLWD_LINK_MTU;
+ mbuff->data_actual_len = 0;
+
+ return (void *)mbuff;
+}
+
+char *low_level_mbuff_mtod(void *mbuff)
+{
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+
+ return (char *)pcap_mbuff->data_actual_ptr;
+}
+
+void low_level_mbuff_free(struct __flwd_device_handle *h, int tid, void *mbuff)
+{
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+
+ free(pcap_mbuff->__data_buf);
+ pcap_mbuff->data_actual_len = 0;
+ pcap_mbuff->__data_buf_max_len = 0;
+ free(mbuff);
+}
+
+void low_level_mbuff_free_after_send(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff)
+{
+ /* pcapģʽ�������Զ�free, �ٴε���������free���� */
+ low_level_mbuff_free(g_dev_handle, tid, mbuff);
+}
+
+
+void low_level_mbuff_send_back(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff)
+{
+ /* pcapģʽ��ʱ���û�עgdev���ݰ�, �պ��� */
+ return;
+}
+
+/*
+ ��mbuff��׷��user_data����.
+
+ return value:
+ ������ʼλ��;
+*/
+char * low_level_mbuff_data_append(void *mbuff, const char *user_data, int user_data_len)
+{
+ pcap_mbuff_t *pcap_mbuff= (pcap_mbuff_t *)mbuff;
+
+ assert(user_data_len <= pcap_mbuff->__data_buf_max_len - pcap_mbuff->data_actual_len);
+
+ memcpy(pcap_mbuff->data_actual_ptr, user_data, user_data_len);
+ pcap_mbuff->data_actual_len += user_data_len;
+
+ return (char *)pcap_mbuff->data_actual_ptr;
+}
+
+/* ����ָ����ǰ�ƶ�N���ֽ�, ���ݳ����Զ�����N, ���������������ݰ�֮ǰ���������ͷ, ��vxlan */
+char *low_level_mbuff_data_forward(void *mbuff, int n)
+{
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+
+ assert(n <= pcap_mbuff->data_actual_ptr - pcap_mbuff->__data_buf);
+
+ pcap_mbuff->data_actual_ptr -= n; /* ��ǰ�ƶ� */
+ pcap_mbuff->data_actual_len += n;
+
+ return (char *)pcap_mbuff->data_actual_ptr;
+}
+
+
+/* ����ָ������ƶ�N���ֽ�, ���ݳ����Զ�����N, �����ǰ��������ݰ���ijЩ��ͷ����, ���ȥvxlanͷ�� */
+char * low_level_mbuff_data_rearward(void *mbuff, int n)
+{
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+
+ assert(n <= pcap_mbuff->__data_buf_max_len - pcap_mbuff->data_actual_len);
+
+ pcap_mbuff->data_actual_ptr += n;
+ pcap_mbuff->data_actual_len -= n;
+
+ return pcap_mbuff->data_actual_ptr;
+}
+
+
+
+int low_level_mbuff_get_pkt_len(void *mbuff)
+{
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+
+ return pcap_mbuff->data_actual_len;
+}
+
+void low_level_mbuff_set_pkt_len(void *mbuff, int pkt_len)
+{
+ pcap_mbuff_t *pcap_mbuff = (pcap_mbuff_t *)mbuff;
+
+ pcap_mbuff->data_actual_len = pkt_len;
+}
+
+
+int low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff)
+{
+ return pcap_low_level_send(global_dev_handle, tid, mbuff);
+}
+
+/* �˺���������������ѭ��, һֱ������ */
+void low_level_io_run(flwd_device_handle_t *global_io_handle)
+{
+ ///int i;
+ ///pthread_t pid;
+
+ flwd_device_handle_pcap_t *pcap_io_handle = (flwd_device_handle_pcap_t *)global_io_handle->low_level_io_handle;
+
+ while(1){
+ pcap_loop(pcap_io_handle->pcap_dev_handle, -1, flwd_pcap_pkt_handle, (u_char *)pcap_io_handle);
+ }
+
+ return;
+}
+
+int low_level_io_init(flwd_device_handle_t *global_dev_handle)
+{
+ return pcap_low_level_io_init(global_dev_handle);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/packet_io/flwd_packet_io_socket.c b/src/packet_io/flwd_packet_io_socket.c
new file mode 100644
index 0000000..6dad448
--- /dev/null
+++ b/src/packet_io/flwd_packet_io_socket.c
@@ -0,0 +1,376 @@
+#include "flowood.h"
+#include "flowood_fun.h"
+#include "flwd_net.h"
+#include <pcap/pcap.h>
+#include "MESA_list_queue.h"
+#include "MESA_handle_logger.h"
+#include "MESA_prof_load.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+/* ��Ҫ��̬dlopen��ȡ������, ʹ��C�淶 */
+extern "C" {
+#endif
+
+
+typedef struct {
+ pthread_t pid;
+ unsigned char thread_seq;
+ int sd; /* socket���, UDP��, DGRAMģʽ */
+ struct sockaddr sock_addr;
+}socket_work_thread_t;
+
+typedef struct{
+ char *__data_buf; /* mbuff������ͷָ�� */
+ char *data_actual_ptr; /* ��ǰ����ʵ�ʴ洢������ָ��, ��MAC��ʼ��û��Ҳ��Ԥ���ռ�α��һ��, ����socketģʽ */
+ int __data_buf_max_len; /* mbuff��󻺴泤��, ��FLWD_LINK_MTU */
+ int data_actual_len; /* ��ǰ������ʵ�ʴ洢�����ݳ��� */
+}socket_mbuff_t;
+
+/* pcapģʽ�ڲ�����ṹ */
+typedef struct{
+ int tot_thread_count;
+ int *socket_dev_handle; /* sd�����ָ�� */
+ socket_work_thread_t socket_io_thread_para[FLWD_MAX_THREAD_NUM];
+ socket_mbuff_t socket_send_buf[FLWD_MAX_THREAD_NUM]; /* ��������, ��ʼ��ʱ����, �Ժ󷢰�����ÿ�ζ�̬malloc/free */
+}flwd_device_handle_socket_t;
+
+
+
+/* �˺���������������ѭ��, һֱ������ */
+void low_level_io_run(flwd_device_handle_t *global_io_handle)
+{
+ /* socketģʽ, init�ɹ���, ������������ӿ�, ֱ��recv, send���� */
+ (void )global_io_handle;
+
+ return;
+}
+
+
+static socket_mbuff_t *flwd_socket_create_new_mbuff(int datalen)
+{
+ socket_mbuff_t *sock_mbuff;
+
+ sock_mbuff = (socket_mbuff_t *)calloc(1, sizeof(socket_mbuff_t));
+
+ sock_mbuff->__data_buf = (char *)malloc(datalen + FLWD_VXLAN_OUTER_PACKET_LEN); /* Ԥ��vxlanͷ�� */
+ sock_mbuff->__data_buf_max_len = datalen + FLWD_VXLAN_OUTER_PACKET_LEN;
+
+
+ sock_mbuff->data_actual_ptr = sock_mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN;
+ sock_mbuff->data_actual_len = datalen;
+
+ return sock_mbuff;
+}
+
+/* socket addr_para: addr_para=127.0.0.1:50000 */
+int flwd_socket_addr_para_parse(char *cfg_line, unsigned int *sock_addr_ip_net_order, unsigned short *sock_addr_port_host_order)
+{
+ const char *delim = ": ";
+ char *save_ptr;
+ char *section;
+ int tmp;
+
+ section = strtok_r(cfg_line, delim, &save_ptr);
+ if(inet_pton(AF_INET, cfg_line, sock_addr_ip_net_order) <= 0){
+ return -1;
+ }
+
+ section = strtok_r(NULL, delim, &save_ptr);
+ if(NULL == section){
+ return -1;
+ }
+
+ tmp = atoi(section);
+ if(tmp <= 0 || tmp > 65535){
+ return -1;
+ }
+
+ *sock_addr_port_host_order = (unsigned short)tmp;
+
+ while(strtok_r(NULL, delim, &save_ptr));
+
+ return 0;
+}
+
+/* Ϊ��gdb��ϵ㷽��, ÿ��io_lib���Լ��ڲ����صĺ������� */
+static int socket_low_level_io_init(flwd_device_handle_t *global_dev_handle)
+{
+ int i, tmp_int;
+ char str_tmp[128];
+ unsigned int sock_addr_ip_net_order = 0; /* socketģʽ������IP */
+ unsigned short sock_addr_port_host_order; /* ��ʼ�˿�, һ���󶨴ӵ�ǰ�˿ڿ�ʼ��port + thread_count */
+ struct sockaddr_in sockadd;
+
+ flwd_device_handle_socket_t *socket_io_handle = (flwd_device_handle_socket_t *)calloc(1, sizeof(flwd_device_handle_socket_t));
+
+ /* socket addr_para: addr_para=60000, ��ʾ���ذ󶨵���ʼ�˿�, �Լ�������thread_num�������˿� */
+ MESA_load_profile_string_def(FLWD_CONFIG_FILE, g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, "addr_para", str_tmp, 128, "#");
+ if('#' == str_tmp[0]){
+ flwd_log(RLOG_LV_FATAL, "get config %s->addr_para error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+
+#if 0
+ ret = flwd_socket_addr_para_parse(str_tmp, &sock_addr_ip_net_order, &sock_addr_port_host_order);
+ if(ret < 0){
+ flwd_log(RLOG_LV_FATAL, "parse config %s->addr_para %s error!",
+ g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section, str_tmp);
+ return -1;
+ }
+#else
+ tmp_int = atoi(str_tmp);
+ if((tmp_int <= 0) || (tmp_int > 65535)){
+ flwd_log(RLOG_LV_FATAL, "%s config %s->addr_para error!", g_packet_io_cfg_para[(int)global_dev_handle->io_para.topo_mode].cfg_file_section);
+ return -1;
+ }
+#endif
+
+ sock_addr_port_host_order = (unsigned short)tmp_int;
+
+ for(i = 0; i < global_dev_handle->tot_thread_count; i++){
+ socket_io_handle->socket_io_thread_para[i].thread_seq = i;
+ socket_io_handle->socket_send_buf[i].__data_buf = (char *)malloc(FLWD_LINK_MTU);
+ socket_io_handle->socket_send_buf[i].__data_buf_max_len = FLWD_LINK_MTU;
+ socket_io_handle->socket_io_thread_para[i].sd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ bzero(&sockadd, sizeof(sockadd));
+ sockadd.sin_family = AF_INET;
+ sockadd.sin_addr.s_addr = sock_addr_ip_net_order;
+ sockadd.sin_port = htons(sock_addr_port_host_order + i);
+
+ if(bind(socket_io_handle->socket_io_thread_para[i].sd, (struct sockaddr *) &sockadd, sizeof(sockadd)) < 0){
+ flwd_log(RLOG_LV_FATAL, "Socket bind port %u error, %s!\n", sock_addr_port_host_order + i, strerror(errno));
+ return -1;
+ }
+ }
+
+ global_dev_handle->io_para.device_ip_net_order = sock_addr_ip_net_order;
+ global_dev_handle->io_para.socket_port_net_order = htons(sock_addr_port_host_order);
+
+ socket_io_handle->tot_thread_count = global_dev_handle->tot_thread_count;
+ global_dev_handle->low_level_io_handle = (void *)socket_io_handle;
+
+ return 0;
+}
+
+#if FLWD_NAT_SPORT_VOLATILE
+static struct sockaddr_in g_remote_addr;
+#endif
+
+
+static int socket_low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff)
+{
+ int ret;
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+ flwd_device_handle_socket_t *sock_io_handle = (flwd_device_handle_socket_t *)global_dev_handle->low_level_io_handle;
+ struct sockaddr_in sockadd;
+ const flwd_ipv4_hdr_t *ipv4_hdr = (flwd_ipv4_hdr_t *) (sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t));
+ const flwd_udp_hdr_t *udph = (flwd_udp_hdr_t *)(sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t));
+
+ sockadd.sin_family = AF_INET;
+
+#if FLWD_NAT_SPORT_VOLATILE
+ sockadd.sin_addr.s_addr = g_remote_addr.sin_addr.s_addr;
+ sockadd.sin_port = g_remote_addr.sin_port;
+#else
+ sockadd.sin_addr.s_addr = ipv4_hdr->ip_dst.s_addr;
+ sockadd.sin_port = udph->uh_dport;
+#endif
+
+ ret = sendto(sock_io_handle->socket_io_thread_para[tid].sd,
+ sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t), /* �ϲ�Ӧ�ö�Ĭ�ϴ�mac�㿪ʼ, �˴�ʹ��socketģʽ, ϵͳ���װMAC,IP,UDP, �����vxlan����MACͷ+ipͷ+udpͷ */
+ sock_mbuff->data_actual_len - sizeof(flwd_eth_hdr_t) - sizeof(flwd_ipv4_hdr_t) - sizeof(flwd_udp_hdr_t), /* �ϲ�Ӧ�ö�Ĭ�ϴ�mac�㿪ʼ, �˴�ʹ��socketģʽ, ϵͳ���װMAC,IP,UDP, ����vxlan����MACͷ+ipͷ+udpͷ */
+ MSG_DONTWAIT,
+ (const struct sockaddr *)&sockadd,
+ sizeof(struct sockaddr));
+
+ return ret;
+}
+
+int low_level_pkt_recv(flwd_device_handle_t *g_dev_handle, int tid, void **mbuff)
+{
+ int ret;
+ socket_mbuff_t *sock_mbuff;
+ char sock_rcv_buf[FLWD_LINK_MTU];
+ flwd_device_handle_socket_t *socket_io_handle = (flwd_device_handle_socket_t *)g_dev_handle->low_level_io_handle;
+ flwd_eth_hdr_t *ehdr;
+ flwd_ipv4_hdr_t *ipv4_hdr;
+ struct sockaddr_in local_remote_addr;
+ socklen_t addr_len = sizeof(local_remote_addr);
+
+ ret = recvfrom(socket_io_handle->socket_io_thread_para[tid].sd, sock_rcv_buf, FLWD_LINK_MTU, MSG_DONTWAIT, (struct sockaddr *)&local_remote_addr, &addr_len);
+
+ if(ret > 0){
+ sock_mbuff = flwd_socket_create_new_mbuff(ret + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t));
+
+ /* α��һ��mac��ʼ��ԭʼ��, ģ��vxlan���ethernet */
+ ehdr = (flwd_eth_hdr_t *)(sock_mbuff->data_actual_ptr);
+ ehdr->h_proto = htons(ETH_P_IP);
+
+ /* �vxlan���ipv4 */
+ ipv4_hdr = (flwd_ipv4_hdr_t *) (sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t));
+ ipv4_hdr->ip_v = 4;
+ ipv4_hdr->ip_hl = 5;
+ ipv4_hdr->ip_p = IPPROTO_UDP;
+
+ /* ��udp�յ�������Ԥ��ͷ���ռ�, �ٿ��� */
+ memcpy(sock_mbuff->data_actual_ptr + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t), sock_rcv_buf, ret);
+ sock_mbuff->data_actual_len = ret + sizeof(flwd_eth_hdr_t) + sizeof(flwd_ipv4_hdr_t) + sizeof(flwd_udp_hdr_t);
+
+
+#if FLWD_NAT_SPORT_VOLATILE
+ if(memcmp(&local_remote_addr, &g_remote_addr, sizeof(local_remote_addr)) != 0){
+ /* ��ΪNAT�ڲ���������������, ���³�NAT���Դ�˿ڱ��� */
+ memcpy(&g_remote_addr, &local_remote_addr,sizeof(local_remote_addr));
+ }
+#endif
+
+
+ }else{
+ *mbuff = NULL;
+ return -1;
+ }
+
+ *mbuff = (void *)sock_mbuff;
+
+ return ret;
+}
+
+void low_level_pkt_free(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ free(sock_mbuff->__data_buf);
+ free(sock_mbuff);
+
+ return;
+}
+
+void *low_level_mbuff_malloc(flwd_device_handle_t *g_dev_handle, int tid, int len)
+{
+ //flwd_device_handle_socket_t *socket_io_handle = (flwd_device_handle_socket_t *)g_dev_handle->low_level_io_handle;
+
+ socket_mbuff_t *mbuff = (socket_mbuff_t *)malloc(sizeof(socket_mbuff_t));
+
+ mbuff->__data_buf = (char *)malloc(FLWD_LINK_MTU);
+ mbuff->data_actual_ptr = mbuff->__data_buf + FLWD_VXLAN_OUTER_PACKET_LEN;
+ mbuff->__data_buf_max_len = FLWD_LINK_MTU;
+ mbuff->data_actual_len = 0;
+
+ return (void *)mbuff;
+}
+
+char *low_level_mbuff_mtod(void *mbuff)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ return (char *)sock_mbuff->data_actual_ptr;
+}
+
+void low_level_mbuff_free(struct __flwd_device_handle *h, int tid, void *mbuff)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ free(sock_mbuff->__data_buf);
+ sock_mbuff->data_actual_len = 0;
+ sock_mbuff->__data_buf_max_len = 0;
+ free(mbuff);
+}
+
+void low_level_mbuff_free_after_send(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff)
+{
+ /* pcapģʽ�������Զ�free, �ٴε���������free���� */
+ low_level_mbuff_free(g_dev_handle, tid, mbuff);
+}
+
+void low_level_mbuff_send_back(flwd_device_handle_t *g_dev_handle, int tid, void *mbuff)
+{
+ /* socketģʽ��ʱ���û�עgdev���ݰ�, �պ��� */
+ return;
+}
+
+/*
+ ��mbuff��׷��user_data����.
+ return value:
+ ������ʼλ��;
+*/
+char * low_level_mbuff_data_append(void *mbuff, const char *user_data, int user_data_len)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ assert(user_data_len <= sock_mbuff->__data_buf_max_len - sock_mbuff->data_actual_len);
+
+ memcpy(sock_mbuff->data_actual_ptr, user_data, user_data_len);
+ sock_mbuff->data_actual_len += user_data_len;
+
+ return (char *)sock_mbuff->data_actual_ptr;
+}
+
+/* ����ָ����ǰ�ƶ�N���ֽ�, ���ݳ����Զ�����N, ���������������ݰ�֮ǰ���������ͷ, Ԥ��һЩ�ռ�, ��vxlan */
+char * low_level_mbuff_data_forward(void *mbuff, int n)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ assert(n <= sock_mbuff->data_actual_ptr - sock_mbuff->__data_buf);
+
+ sock_mbuff->data_actual_ptr -= n;
+ sock_mbuff->data_actual_len += n;
+
+ return (char *)sock_mbuff->data_actual_ptr;
+}
+
+
+/* ����ָ������ƶ�N���ֽ�, ���ݳ����Զ�����N, �����ǰ��������ݰ���ijЩ��ͷ����, ���ȥvxlanͷ�� */
+char * low_level_mbuff_data_rearward(void *mbuff, int n)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ assert(n <= sock_mbuff->__data_buf_max_len - sock_mbuff->data_actual_len);
+
+ sock_mbuff->data_actual_ptr += n;
+ sock_mbuff->data_actual_len -= n;
+
+ return sock_mbuff->data_actual_ptr;
+}
+
+
+int low_level_mbuff_get_pkt_len(void *mbuff)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ return sock_mbuff->data_actual_len;
+}
+
+void low_level_mbuff_set_pkt_len(void *mbuff, int pkt_len)
+{
+ socket_mbuff_t *sock_mbuff = (socket_mbuff_t *)mbuff;
+
+ sock_mbuff->data_actual_len = pkt_len;
+}
+
+
+int low_level_send(flwd_device_handle_t *global_dev_handle, int tid, void *mbuff)
+{
+ return socket_low_level_send(global_dev_handle, tid, mbuff);
+}
+
+
+int low_level_io_init(flwd_device_handle_t *global_dev_handle)
+{
+ return socket_low_level_io_init(global_dev_handle);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/packet_io/nf-queue.c b/src/packet_io/nf-queue.c
new file mode 100644
index 0000000..c2bc6cc
--- /dev/null
+++ b/src/packet_io/nf-queue.c
@@ -0,0 +1,213 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <arpa/inet.h>
+
+#include <libmnl/libmnl.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+
+#include <linux/types.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+
+#include <libnetfilter_queue/libnetfilter_queue.h>
+
+/* only for NFQA_CT, not needed otherwise: */
+#include <linux/netfilter/nfnetlink_conntrack.h>
+
+static struct mnl_socket *nl;
+
+static struct nlmsghdr *
+nfq_hdr_put(char *buf, int type, uint32_t queue_num)
+{
+ struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf);
+ nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | type;
+ nlh->nlmsg_flags = NLM_F_REQUEST;
+
+ struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg));
+ nfg->nfgen_family = AF_UNSPEC;
+ nfg->version = NFNETLINK_V0;
+ nfg->res_id = htons(queue_num);
+
+ return nlh;
+}
+
+static void
+nfq_send_verdict(int queue_num, uint32_t id)
+{
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
+ struct nlattr *nest;
+
+ nlh = nfq_hdr_put(buf, NFQNL_MSG_VERDICT, queue_num);
+ nfq_nlmsg_verdict_put(nlh, id, NF_ACCEPT);
+
+ /* example to set the connmark. First, start NFQA_CT section: */
+ nest = mnl_attr_nest_start(nlh, NFQA_CT);
+
+ /* then, add the connmark attribute: */
+ mnl_attr_put_u32(nlh, CTA_MARK, htonl(42));
+ /* more conntrack attributes, e.g. CTA_LABEL, could be set here */
+
+ /* end conntrack section */
+ mnl_attr_nest_end(nlh, nest);
+
+ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
+ perror("mnl_socket_send");
+ exit(EXIT_FAILURE);
+ }
+}
+
+static int queue_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nfqnl_msg_packet_hdr *ph = NULL;
+ struct nlattr *attr[NFQA_MAX+1] = {};
+ uint32_t id = 0, skbinfo;
+ struct nfgenmsg *nfg;
+ uint16_t plen;
+
+ if (nfq_nlmsg_parse(nlh, attr) < 0) {
+ perror("problems parsing");
+ return MNL_CB_ERROR;
+ }
+
+ nfg = mnl_nlmsg_get_payload(nlh);
+
+ if (attr[NFQA_PACKET_HDR] == NULL) {
+ fputs("metaheader not set\n", stderr);
+ return MNL_CB_ERROR;
+ }
+
+ ph = mnl_attr_get_payload(attr[NFQA_PACKET_HDR]);
+
+ plen = mnl_attr_get_payload_len(attr[NFQA_PAYLOAD]);
+ /* void *payload = mnl_attr_get_payload(attr[NFQA_PAYLOAD]); */
+
+ skbinfo = attr[NFQA_SKB_INFO] ? ntohl(mnl_attr_get_u32(attr[NFQA_SKB_INFO])) : 0;
+
+ if (attr[NFQA_CAP_LEN]) {
+ uint32_t orig_len = ntohl(mnl_attr_get_u32(attr[NFQA_CAP_LEN]));
+ if (orig_len != plen)
+ printf("truncated ");
+ }
+
+ if (skbinfo & NFQA_SKB_GSO)
+ printf("GSO ");
+
+ id = ntohl(ph->packet_id);
+ printf("packet received (id=%u hw=0x%04x hook=%u, payload len %u",
+ id, ntohs(ph->hw_protocol), ph->hook, plen);
+
+ /*
+ * ip/tcp checksums are not yet valid, e.g. due to GRO/GSO.
+ * The application should behave as if the checksums are correct.
+ *
+ * If these packets are later forwarded/sent out, the checksums will
+ * be corrected by kernel/hardware.
+ */
+ if (skbinfo & NFQA_SKB_CSUMNOTREADY)
+ printf(", checksum not ready");
+ puts(")");
+
+ nfq_send_verdict(ntohs(nfg->res_id), id);
+
+ return MNL_CB_OK;
+}
+
+int main(int argc, char *argv[])
+{
+ char *buf;
+ /* largest possible packet payload, plus netlink data overhead: */
+ size_t sizeof_buf = 0xffff + (MNL_SOCKET_BUFFER_SIZE/2);
+ struct nlmsghdr *nlh;
+ int ret;
+ unsigned int portid, queue_num;
+
+ if (argc != 2) {
+ printf("Usage: %s [queue_num]\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ queue_num = atoi(argv[1]);
+
+ nl = mnl_socket_open(NETLINK_NETFILTER);
+ if (nl == NULL) {
+ perror("mnl_socket_open");
+ exit(EXIT_FAILURE);
+ }
+
+ if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+ perror("mnl_socket_bind");
+ exit(EXIT_FAILURE);
+ }
+ portid = mnl_socket_get_portid(nl);
+
+ buf = malloc(sizeof_buf);
+ if (!buf) {
+ perror("allocate receive buffer");
+ exit(EXIT_FAILURE);
+ }
+
+ /* PF_(UN)BIND is not needed with kernels 3.8 and later */
+ nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, 0);
+ nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_PF_UNBIND);
+
+ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
+ perror("mnl_socket_send");
+ exit(EXIT_FAILURE);
+ }
+
+ nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, 0);
+ nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_PF_BIND);
+
+ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
+ perror("mnl_socket_send");
+ exit(EXIT_FAILURE);
+ }
+
+ nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, queue_num);
+ nfq_nlmsg_cfg_put_cmd(nlh, AF_INET, NFQNL_CFG_CMD_BIND);
+
+ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
+ perror("mnl_socket_send");
+ exit(EXIT_FAILURE);
+ }
+
+ nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, queue_num);
+ nfq_nlmsg_cfg_put_params(nlh, NFQNL_COPY_PACKET, 0xffff);
+
+ mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQA_CFG_F_GSO));
+ mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(NFQA_CFG_F_GSO));
+
+ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
+ perror("mnl_socket_send");
+ exit(EXIT_FAILURE);
+ }
+
+ /* ENOBUFS is signalled to userspace when packets were lost
+ * on kernel side. In most cases, userspace isn't interested
+ * in this information, so turn it off.
+ */
+ ret = 1;
+ mnl_socket_setsockopt(nl, NETLINK_NO_ENOBUFS, &ret, sizeof(int));
+
+ for (;;) {
+ ret = mnl_socket_recvfrom(nl, buf, sizeof_buf);
+ if (ret == -1) {
+ perror("mnl_socket_recvfrom");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = mnl_cb_run(buf, ret, 0, portid, queue_cb, NULL);
+ if (ret < 0){
+ perror("mnl_cb_run");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ mnl_socket_close(nl);
+
+ return 0;
+}
diff --git a/src/packet_io/nfq_test.c b/src/packet_io/nfq_test.c
new file mode 100644
index 0000000..58e2ee3
--- /dev/null
+++ b/src/packet_io/nfq_test.c
@@ -0,0 +1,270 @@
+/*
+ * =====================================================================================
+ *
+ * Filename: nf_queue_test.c
+ *
+ * Description: ��netfilter_queue ���û�̬�޸��������ݰ������ӳ���
+ *
+ * Version: 1.0
+ * Created: 04/02/2010 09:49:48 AM
+ * Revision: none
+ * Compiler: gcc
+ *
+ * Author: LeiuX (xulei), [email protected]
+ * Company: HIT
+ *
+ * =====================================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <asm/byteorder.h>
+#include <linux/netfilter.h>
+#include <libnetfilter_queue/libnetfilter_queue.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+#ifdef __LITTLE_ENDIAN
+#define IPQUAD(addr) \
+((unsigned char *)&addr)[0], \
+((unsigned char *)&addr)[1], \
+((unsigned char *)&addr)[2], \
+((unsigned char *)&addr)[3]
+#else
+#define IPQUAD(addr) \
+((unsigned char *)&addr)[3], \
+((unsigned char *)&addr)[2], \
+((unsigned char *)&addr)[1], \
+((unsigned char *)&addr)[0]
+#endif
+
+struct tcp_pseudo /*the tcp pseudo header*/
+{
+ __u32 src_addr;
+ __u32 dst_addr;
+ __u8 zero;
+ __u8 proto;
+ __u16 length;
+} pseudohead;
+
+
+long checksum(unsigned short *addr, unsigned int count) {
+ /* Compute Internet Checksum for "count" bytes
+ * beginning at location "addr".
+ */
+ register long sum = 0;
+
+ while( count > 1 ) {
+ /* This is the inner loop */
+ sum += * addr++;
+ count -= 2;
+ }
+ /* Add left-over byte, if any */
+ if( count > 0 )
+ sum += * (unsigned char *) addr;
+
+ /* Fold 32-bit sum to 16 bits */
+ while (sum>>16)
+ sum = (sum & 0xffff) + (sum >> 16);
+
+ return ~sum;
+}
+
+
+/*************************tcp checksum**********************/
+long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
+
+ __u16 total_len = ntohs(myip->tot_len);
+
+ int tcpopt_len = mytcp->doff*4 - 20;
+ int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);
+
+ pseudohead.src_addr=myip->saddr;
+ pseudohead.dst_addr=myip->daddr;
+ pseudohead.zero=0;
+ pseudohead.proto=IPPROTO_TCP;
+ pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);
+
+ int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + tcpopt_len +tcpdatalen;
+ //unsigned short * tcp = new unsigned short[totaltcp_len];
+
+ unsigned short * tcp = malloc(totaltcp_len);
+
+
+ memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
+ memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned char*)mytcp,sizeof(struct tcphdr));
+ memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr),(unsigned char *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);
+ memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char *)mytcp+(mytcp->doff*4), tcpdatalen);
+
+ /* printf("pseud length: %d\n",pseudohead.length);
+ printf("tcp hdr length: %d\n",mytcp->doff*4);
+ printf("tcp hdr struct length: %d\n",sizeof(struct tcphdr));
+ printf("tcp opt length: %d\n",tcpopt_len);
+ printf("tcp total+psuedo length: %d\n",totaltcp_len);
+
+ fflush(stdout);
+
+ printf("tcp data len: %d, data start %u\n", tcpdatalen,mytcp + (mytcp->doff*4));
+ */
+
+
+ return checksum(tcp,totaltcp_len);
+
+}
+
+static u_int16_t tcp_checksum(struct iphdr* iphdrp){
+ struct tcphdr *tcphdrp =
+ (struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
+ return get_tcp_checksum(iphdrp, tcphdrp);
+}
+
+static void set_tcp_checksum(struct iphdr* iphdrp){
+ struct tcphdr *tcphdrp =
+ (struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
+ tcphdrp->check = 0;
+ tcphdrp->check = get_tcp_checksum(iphdrp, tcphdrp);
+}
+/****************************tcp checksum end****************************/
+
+
+/********************************Ip checksum*****************************/
+static u_int16_t ip_checksum(struct iphdr* iphdrp){
+ return checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);
+}
+
+static void set_ip_checksum(struct iphdr* iphdrp){
+ iphdrp->check = 0;
+ iphdrp->check = checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);
+}
+/****************************Ip checksum end******************************/
+
+static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
+ struct nfq_data *nfa, void *data){
+ (void)nfmsg;
+ (void)data;
+ u_int32_t id = 0;
+ struct nfqnl_msg_packet_hdr *ph;
+ unsigned char *pdata = NULL;
+ int pdata_len;
+
+ ph = nfq_get_msg_packet_hdr(nfa);
+ if (ph){
+ id = ntohl(ph->packet_id);
+ }
+
+ pdata_len = nfq_get_payload(nfa, &pdata);
+ if(pdata_len == -1){
+ pdata_len = 0;
+ }
+
+ struct iphdr *iphdrp = (struct iphdr *)pdata;
+
+ printf("len %d iphdr %d %u.%u.%u.%u ->",
+ pdata_len,
+ iphdrp->ihl<<2,
+ IPQUAD(iphdrp->saddr));
+ printf(" %u.%u.%u.%u %s",
+ IPQUAD(iphdrp->daddr),
+ getprotobynumber(iphdrp->protocol)->p_name);
+ printf(" ipsum %hu", ip_checksum(iphdrp));
+ if(iphdrp->protocol == IPPROTO_TCP){
+ printf(" tcpsum %hu", tcp_checksum(iphdrp));
+ }
+
+ iphdrp->saddr = 0x08080808;
+ iphdrp->daddr = iphdrp->saddr;
+
+#if 0
+#define TO "220.181.37.55"
+#define DNAT_TO "202.118.236.130"
+
+ if(iphdrp->daddr == inet_addr(TO)){
+ printf(" !hacked!");
+ iphdrp->daddr = inet_addr(DNAT_TO);
+ set_ip_checksum(iphdrp);
+ if(iphdrp->protocol == IPPROTO_TCP){
+ set_tcp_checksum(iphdrp);
+ printf(" ipsum+ %hu tcpsum+ %hu",
+ ip_checksum(iphdrp), tcp_checksum(iphdrp));
+ }
+ }
+
+ if(iphdrp->saddr == inet_addr(DNAT_TO)){
+ iphdrp->saddr = inet_addr(TO);
+ printf(" !hacked!");
+ set_ip_checksum(iphdrp);
+ if(iphdrp->protocol == IPPROTO_TCP){
+ set_tcp_checksum(iphdrp);
+ printf(" ipsum+ %hu tcpsum+ %hu",
+ ip_checksum(iphdrp), tcp_checksum(iphdrp));
+ }
+ }
+#endif
+ printf("\n");
+
+ return nfq_set_verdict_mark(qh, id, NF_REPEAT, 1, (u_int32_t)pdata_len, pdata);
+}
+
+int main(int argc, char **argv)
+{
+ struct nfq_handle *h;
+ struct nfq_q_handle *qh;
+ struct nfnl_handle *nh;
+ int fd;
+ int rv;
+ char buf[4096];
+
+ h = nfq_open();
+ if (!h) {
+ exit(1);
+ }
+
+ nfq_unbind_pf(h, AF_INET);
+
+ /*2.6.24 ���ں���BUG�� nfq_unbind_pf ����ֵ����ȷ��
+ ����http://article.gmane.org/gmane.c ... ilter.general/33573*/
+
+ /*
+ if (nfq_unbind_pf(h, AF_INET) < 0){
+ exit(1);
+ }
+ */
+
+ if (nfq_bind_pf(h, AF_INET) < 0) {
+ exit(1);
+ }
+
+ int qid = 0;
+ if(argc == 2){
+ qid = atoi(argv[1]);
+ }
+ printf("binding this socket to queue %d\n", qid);
+ qh = nfq_create_queue(h, qid, &cb, NULL);
+ if (!qh) {
+ exit(1);
+ }
+
+ if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
+ exit(1);
+ }
+
+ nh = nfq_nfnlh(h);
+ fd = nfnl_fd(nh);
+
+ while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {
+ nfq_handle_packet(h, buf, rv);
+ }
+
+ /* never reached */
+ nfq_destroy_queue(qh);
+
+ nfq_close(h);
+
+ exit(0);
+}
diff --git a/support/include/MESA_atomic_for_view.h b/support/include/MESA_atomic_for_view.h
new file mode 100644
index 0000000..6d8c6ef
--- /dev/null
+++ b/support/include/MESA_atomic_for_view.h
@@ -0,0 +1,38 @@
+#ifndef _MESA_ATOMIC_H_
+#define _MESA_ATOMIC_H_
+
+
+#if(__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__ >= 411)
+typedef unsigned long MESA_ATOMIC_T;
+#define MESA_ATOMIC_SET(v, i) __sync_lock_test_and_set((&v), i)
+#define MESA_ATOMIC_READ(v) __sync_or_and_fetch((&v), 0)
+#define MESA_ATOMIC_INC(v) __sync_add_and_fetch((&v),1)
+#define MESA_ATOMIC_DEC(v) __sync_sub_and_fetch((&v),1)
+#define MESA_ATOMIC_ADD(v,add) __sync_add_and_fetch((&v),(add))
+#define MESA_ATOMIC_SUB(v,sub) __sync_sub_and_fetch((&v),(sub))
+#else
+#include <alsa/iatomic.h>
+typedef atomic_t MESA_ATOMIC_T;
+#define MESA_ATOMIC_SET(v, i) atomic_set((&v), i)
+#define MESA_ATOMIC_READ(v) atomic_read((&v))
+#define MESA_ATOMIC_INC(v) atomic_inc((&v))
+#define MESA_ATOMIC_DEC(v) atomic_dec((&v))
+#define MESA_ATOMIC_ADD(v, add) atomic_add((add),(&v))
+#define MESA_ATOMIC_SUB(v, sub) atomic_sub((sub),(&v))
+#endif
+
+
+#ifdef __tilegx__
+#include <arch/atomic.h>
+typedef int MESA_ATOMIC_T;
+#define MESA_ATOMIC_SET(v, i) arch_atomic_exchange((&v), i)
+#define MESA_ATOMIC_READ(v) arch_atomic_or((&v), 0)
+#define MESA_ATOMIC_INC(v) arch_atomic_add((&v), 1)
+#define MESA_ATOMIC_DEC(v) arch_atomic_sub((&v), 1)
+#define MESA_ATOMIC_ADD(v, add) arch_atomic_add((&v), add)
+#define MESA_ATOMIC_SUB(v, sub) arch_atomic_sub((&v), sub)
+#endif
+
+
+#endif
+
diff --git a/support/include/MESA_handle_logger_for_view.h b/support/include/MESA_handle_logger_for_view.h
new file mode 100644
index 0000000..c615b53
--- /dev/null
+++ b/support/include/MESA_handle_logger_for_view.h
@@ -0,0 +1,68 @@
+#ifndef MESA_HANDLE__LOGGER_H
+#define MESA_HANDLE__LOGGER_H
+
+/*
+ * runtime_log with handle,
+ * based on runtime_log.
+ * yang wei
+ * create time:2014-03-24
+ * version:20140324
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define RLOG_LV_DEBUG 10
+#define RLOG_LV_INFO 20
+#define RLOG_LV_FATAL 30
+
+
+#define MESA_HANDLE_RUNTIME_LOG(handle, lv, mod, fmt, args...) \
+ MESA_handle_runtime_log((handle), (lv), (mod), "file %s, line %d, " fmt, \
+ __FILE__, __LINE__, ##args)
+
+/*
+ * name: MESA_create_runtime_log_handle
+ * functionality: get runtime_log handle;
+ * params:
+ * file_path: path of log file, like "./log/runtime_log";
+ * level: level of log;
+ * returns:
+ * not NULL, if succeeded;
+ * NULL, if file is not absolute path, or failed to create log file;
+ */
+void *MESA_create_runtime_log_handle(const char *file_path, int level);
+
+/*
+ * name: MESA_handle_runtime_log
+ * functionality: appends log message to runtime log file;
+ * params:
+ * handle:handle of runtime log, which is created by MESA_create_runtime_log_handle;
+ * level: log level, messages with level value smaller the global var
+ * "runtime_log_level" are ignored;
+ * module: name of loggin module;
+ * fmt: format string;
+ * returns:
+ * none;
+ */
+void MESA_handle_runtime_log(void *handle, int level, const char *module, const char *fmt, ...);
+
+/*
+ * name: MESA_destroy_runtime_log_handle
+ * functionality: release runtime log handle memory.
+ * params:
+ * handle: runtime log handle which is going to be released;
+ * returns:
+ * none;
+ */
+void MESA_destroy_runtime_log_handle(void *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/support/include/MESA_htable_for_view.h b/support/include/MESA_htable_for_view.h
new file mode 100644
index 0000000..76d7a2f
--- /dev/null
+++ b/support/include/MESA_htable_for_view.h
@@ -0,0 +1,393 @@
+#ifndef __MESA_HTABLE_H_
+#define __MESA_HTABLE_H_
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+
+/*
+ * general purpose hash table implementation.
+ *
+ * xiang hong
+ * 2002-07-28
+ *History:
+ * 2012-03-23 zhengchao add thread safe option and link expire feature;
+ * 2014-01-27 lijia add reentrant feature.
+ */
+#define MESA_HTABLE_VERSION_MACRO (20171114)
+extern const unsigned int MESA_HTABLE_VERSION_INT;
+
+#define MESA_HASH_DEBUG (0)
+
+#define COMPLEX_KEY_SWITCH (1)
+
+#define ELIMINATE_TYPE_NUM (1)
+#define ELIMINATE_TYPE_TIME (2)
+#define ELIMINATE_TYPE_MANUAL (3) /* delete oldest item by manual */
+
+typedef void * MESA_htable_handle;
+
+
+#define HASH_MALLOC(_n_) malloc(_n_)
+#define HASH_FREE(_p_) free(_p_)
+
+
+#ifndef uchar
+#define uchar unsigned char
+#endif
+#ifndef uint
+#define uint unsigned int
+#endif
+
+/* eliminate algorithm */
+#define HASH_ELIMINATE_ALGO_FIFO (0) /* by default */
+#define HASH_ELIMINATE_ALGO_LRU (1)
+
+/*
+ * hash key compare function prototype, see hash_key_comp().
+ * return value:
+ * 0:key1 and key2 are equal;
+ * other:key1 and key2 not equal.
+ */
+typedef int key_comp_fun_t(const uchar * key1, uint size1, const uchar * key2, uint size2);
+
+/*
+ * hash key->index computing function prototype, see hash_key2index().
+ */
+typedef uint key2index_fun_t(const MESA_htable_handle table, const uchar * key, uint size);
+
+/* MESA_htable built-in HASH algorithm, MESA_htable use BKDR_hash_algo as default, user can choose any one of the following */
+extern uint BKDR_hash_algo(MESA_htable_handle api_table, const uchar *key, uint size);
+extern uint APHash_algo(MESA_htable_handle api_table, const uchar *key, uint size);
+extern uint murmur3_32_algo(MESA_htable_handle api_table, const uchar* key, uint size) ;
+
+typedef void MESA_htable_data_free_cbfun_t(void *data);
+
+typedef int MESA_htable_expire_notify_cbfun_t(void *data, int eliminate_type);
+
+typedef uchar* MESA_htable_complex_key_dup_cbfun_t(const uchar *key, uint key_size);
+
+typedef void MESA_htable_complex_key_free_cbfun_t(uchar *key, uint key_size);
+
+typedef long hash_cb_fun_t(void *data, const uchar *key, uint size, void *user_arg);
+
+/*
+ * thread_safe: 0:create hash table without thread safe features;
+ * positive:the bigger number has more performance, less collide, but less timeout accuracy.
+ * max number is 1024.
+ * recursive: 0:can't recursive call MESA_htable_xxx series function
+ * 1:can recursive call MESA_htable_xxx series function.
+ * hash_slot_size: how big do you want the table to be, must be 2^N;
+ * max_elem_num: the maximum elements of the HASH-table,0 means infinite;
+ * key_comp: hash key compare function, use default function if NULL;
+ * suggest implement by yourself.
+ * key2index: hash key->index computing function, use default function if NULL;
+ * suggest use MESA_htable built-in function.
+ * data_free: release resources function;
+ * data_expire_with_condition:
+ * if expire_time > 0 and data_expire_with_condition != NULL,
+ * then call this function when an element expired, and give the reason by the 'type'
+ * if expire_time > 0 and data_expire_with_condition is NULL,
+ * eliminate the item immediately;
+ * args:
+ * data: pointer to attached data;
+ * type: item eliminate reason, ELIMINATE_TYPE_NUM or ELIMINATE_TYPE_TIME;
+ * return value of 'data_expire_with_condition':
+ * 1: the item can be eliminated;
+ * 0: the item can't be eliminated, renew the item.
+ * eliminate_type: the algorithm of elimanate a expired element, 0:FIFO; 1:LRU.
+ * expire_time: the element expire time in second, 0 means infinite.
+ */
+typedef struct{
+ unsigned int thread_safe;
+ int recursive;
+ unsigned int hash_slot_size;
+ unsigned int max_elem_num;
+ int eliminate_type;
+ int expire_time;
+ key_comp_fun_t * key_comp;
+ key2index_fun_t * key2index;
+ void (* data_free)(void *data);
+ int (*data_expire_with_condition)(void *data, int eliminate_type);
+#if COMPLEX_KEY_SWITCH
+ uchar* (*complex_key_dup)(const uchar *key, uint key_size);
+ void (* complex_key_free)(uchar *key, uint key_size);
+#endif
+}MESA_htable_create_args_t;
+
+
+/* All of the following functions return value */
+typedef enum{
+ MESA_HTABLE_RET_OK = 0, /* success */
+ MESA_HTABLE_RET_COMMON_ERR = -1, /* general��undefined errors */
+ MESA_HTABLE_RET_ARG_ERR = -2, /* invalid args */
+ MESA_HTABLE_RET_NUM_FULL = -3, /* htable number full */
+ MESA_HTABLE_RET_QEMPTY = -4, /* htable empty */
+ MESA_HTABLE_RET_DUP_ITEM = -5, /* duplicate item */
+ MESA_HTABLE_RET_NOT_FOUND = -6, /* not found item */
+ MESA_HTABLE_RET_LEN_ERR = -7, /* length error */
+ MESA_HTABLE_RET_CANT_GET_LOCK = -8, /* can't get lock in non-block mode */
+ MESA_HTABLE_RET_GET_LOCK_TMOUT = -9, /* get lock timeout */
+}MESA_htable_errno_t;
+
+/*
+ * You should never use this API to create a hash table, use MESA_htable_born() instead.
+ * name: MESA_htable_create
+ * functionality: allocats memory for hash slots, and initialize hash structure;
+ * param:
+ * args: argments set;
+ * args_len: length of argment set;
+ * returns:
+ * NULL : error;
+ * Non-NULL : success;
+ */
+MESA_htable_handle MESA_htable_create(const MESA_htable_create_args_t *args, int args_struct_len);
+
+/*
+ * get total number of HASH element.
+*/
+unsigned int MESA_htable_get_elem_num(const MESA_htable_handle table);
+
+/*
+ * name: MESA_htable_destroy
+ * functionality: cleans up hash structure, frees memory occupied;
+ * param:
+ * table: who is the victim;
+ * func: callback function to clean up data attached to hash items, has higher priority level than MESA_htable_data_free_cbfun_t in initialization.
+
+ * returns:
+ * always returns 0;
+ */
+int MESA_htable_destroy(MESA_htable_handle table, void (* func)(void *));
+
+/*
+ * name: MESA_htable_add
+ * functionality: adds item to table, call hash_expire() if elem_count gets
+ * bigger than threshold_hi, and adjust threshold;
+ * param:
+ * table: to which table do you want to add;
+ * key: what is the label;
+ * size: how long is the label;
+ * data: what data do you want to attach;
+ * returns:
+ * >0: success,return hash elems' linklist size;
+ * 0: success.
+ * <0: error, refer to MESA_htable_errno_t.
+ */
+int MESA_htable_add(MESA_htable_handle table, const uchar * key, uint size, const void *data);
+
+
+/*
+ * name: MESA_htable_del
+ * functionality: deletes item from table.
+ * param:
+ * table: from which table do you want to delete;
+ * key : what is the label;
+ * size : how long is the label;
+ * func : callback function to clean up data attached to hash items,
+ if this pointer is NULL will call "data_free" in MESA_hash_create(),
+ * returns:
+ * 0 : success;
+ * <0: error, refer to MESA_htable_errno_t.
+ */
+int MESA_htable_del(MESA_htable_handle table, const uchar * key, uint size,
+ void (* func)(void *));
+/*
+ TODO:
+ ����MESA_htable_del_with_hash(MESA_htable_handle table, const uchar * key, uint size, uint hash_value,
+ void (* func)(void *));
+ ɾ��ʱ����֮ǰ��hash_value, ����һ��hash���㿪��,
+*/
+
+
+/*
+ * name: MESA_htable_del_oldest_manual
+ * functionality: deletes oldest item from table.
+ * param:
+ * table: from which table do you want to delete;
+ * func : callback function to clean up data attached to hash items,
+ if this pointer is NULL will call "data_free" in MESA_hash_create(),
+ * batch_num: delete oldest items.
+ * returns:
+ * 0, do nothing ;
+ * >0, delete items;
+ */
+int MESA_htable_del_oldest_manual(MESA_htable_handle table, void (* func)(void *), int batch_num);
+
+/*
+ * name: MESA_htable_search
+ * functionality: selects item from table;
+ * param:
+ * table: from which table do you want to select;
+ * key : what is the label;
+ * size : how long is the label;
+ *
+ * return:
+ * not NULL :pointer to attached data;
+ * NULL :not found(thus be careful if you are attaching NULL data on purpose).
+ */
+void *MESA_htable_search(const MESA_htable_handle table, const uchar * key, uint size);
+
+/*
+ * name: MESA_htable_search_cb
+ * functionality: selects item from table, and then call 'cb', reentrant;
+ * in param:
+ * table: from which table do you want to select;
+ * key : what is the label;
+ * size : how long is the label;
+ * cb : call this function when found the attached data;
+ * arg : the argument of "cb" function.
+ * out param:
+ * cb_ret: the return value of the function "cb".
+ * return:
+ * not NULL :pointer to attached data;
+ * NULL :not found(thus be careful if you are attaching NULL data on purpose).
+ */
+void *MESA_htable_search_cb(const MESA_htable_handle table, const uchar * key, uint size,
+ hash_cb_fun_t *cb, void *arg, long *cb_ret);
+
+/*
+ * name: MESA_htable_iterate
+ * functionality: iterates each hash item;
+ * params:
+ * table: what table is to be iterated;
+ * func: what do you want to do to each attached data item;
+ * returns:
+ * 0: iterates all items;
+ * -1: error;
+ */
+int MESA_htable_iterate(MESA_htable_handle table,
+ void (* func)(const uchar * key, uint size, void * data, void *user), void * user);
+
+
+/*
+ * name: MESA_htable_iterate_bytime
+ * functionality: iterates each hash item by your demand;
+ * note:
+ * if 'thread_safe' more than one, this function is not correct.
+ * params:
+ * table: what table is to be iterated;
+ * iterate_type: 1: newest item first; 2: oldest item first;
+ * iterate_cb: what do you want to do to each attached data item;
+ * return value of iterate_cb:
+ * refer to ITERATE_CB_RET_xxx;
+ * returns:
+ * 0: iterates all items;
+ * -1: uncomplete break.
+ * -2: error;
+ */
+#define ITERATE_CB_RET_CONTINUE_FLAG (0) /* default, like MESA_htable_iterate() */
+#define ITERATE_CB_RET_BREAK_FLAG (1<<1) /* break iterate, return from MESA_htable_iterate_bytime() immediately */
+#define ITERATE_CB_RET_DEL_FLAG (1<<2) /* del this item, like but faster than call MESA_htable_del() */
+#define ITERATE_CB_RET_REVERSE_FLAG (1<<3) /* if the item is newest item, it will become the oldest item, and vice versa */
+#define ITERATE_CB_RET_REMOVE_BUT_NOT_FREE (1<<4) /* only remove the item from Hash table, but don't free the attached data, be careful */
+
+#define ITERATE_TYPE_NEWEST_FIRST (1)
+#define ITERATE_TYPE_OLDEST_FIRST (2)
+int MESA_htable_iterate_bytime(MESA_htable_handle table, int iterate_type,
+ int (*iterate_cb)(const uchar * key, uint size, void * data, void *user), void * user);
+
+/*
+ args:
+ print_switch:
+ 0: disable print message;
+ 1: enable print message;
+*/
+void MESA_htable_print_crtl(MESA_htable_handle table, int print_switch);
+
+
+/*
+ Create a htable handle and Alloc memory, and set default option,
+ but can't running before call MESA_htable_mature().
+
+ return value:
+ not NULL: success.
+ NULL : error.
+*/
+MESA_htable_handle MESA_htable_born(void);
+
+/*
+ MESA_htable option definition.
+*/
+enum MESA_htable_opt{
+ MHO_THREAD_SAFE = 0, /* must be int, 1:create hash table with thread safe features, default is 0 */
+ MHO_MUTEX_NUM, /* must be int, valid only if MHO_THREAD_SAFE is not zero, max value is 1024, defalut is 1. the bigger number has more performance and less mutex collide, but less timeout accuracy */
+ MHO_HASH_SLOT_SIZE, /* must be unsigned int, default is 1048576. */
+ MHO_HASH_MAX_ELEMENT_NUM, /* must be unsigned int, defalut is 0, means infinite */
+ MHO_EXPIRE_TIME, /* must be int, defalut is 0, means infinite */
+ MHO_ELIMIMINATE_TYPE, /* must be int, valid only if MHO_EXPIRE_TIME is not zero. HASH_ELIMINATE_ALGO_FIFO or HASH_ELIMINATE_ALGO_LRU, defalut HASH_ELIMINATE_ALGO_FIFO */
+ MHO_CBFUN_KEY_COMPARE, /* must be key_comp_fun_t, hash key compare function, use default function if NULL */
+ MHO_CBFUN_KEY_TO_INDEX, /* must be key2index_fun_t, hash key->index computing function, use default function if NULL */
+ MHO_CBFUN_DATA_FREE, /* must be MESA_htable_data_free_cbfun_t, release resources function */
+ /* data_expire_notify, must be MESA_htable_expire_notify_cbfun_t,
+ * if expire_time > 0 and data_expire_notify != NULL,
+ * then call this function when an element expired, and give the reason by the 'type'
+ * if expire_time > 0 and data_expire_notify is NULL,
+ * eliminate the item immediately;
+ * args:
+ * data: pointer to attached data;
+ * type: item eliminate reason, ELIMINATE_TYPE_NUM or ELIMINATE_TYPE_TIME;
+ * return value of 'data_expire_with_condition':
+ * 1: the item can be eliminated;
+ * 0: the item can't be eliminated, renew the item.
+ */
+ MHO_CBFUN_DATA_EXPIRE_NOTIFY,
+ MHO_CBFUN_COMPLEX_KEY_DUP, /* must be MESA_htable_complex_key_dup_cbfun_t, if key store in a complex struct, caller must be implement this duplicate function. */
+ MHO_CBFUN_COMPLEX_KEY_FREE, /* must be MESA_htable_complex_key_free_cbfun_t, if key store in a complex struct, caller must be implement this duplicate function. */
+ MHO_AUTO_UPDATE_TIME, /* must be int, create a background thread used to update current_time instead of time(NULL). 1:enable; 0:disable; default value is 0; */
+ MHO_SCREEN_PRINT_CTRL, /* must be int, 1:enable screen print; 0:disable screen print; default is 1. */
+ MHO_HASH_LIST_COLLIDE_THRESHOLD, /* must be int, write log when hash collide number more than this, default is 100, 0 means infinite. */
+ MHO_HASH_LOG_FILE, /* must be char * with EOF, default is "./log/htable_runtime_%p_%t.log", opt_len is strlen(optval) */
+ MHO_HASH_SEARCH_MAX_TIMES, /* must be int, max compare items in once MESA_htable_search() */
+ MHO_HASH_SEARCH_AVG_TIMES, /* must be double, average compare items in all previous MESA_htable_search() */
+ MHO_AUTO_EXPAND_MULTIPLE, /* must be int, default is 0, if this option value bigger than zero, user should set small SLOT_SIZE in initialization for economize memory, htable will auto expand SLOT_SIZE if hash collide item number more than MHO_HASH_LIST_COLLIDE_THRESHOLD. */
+ __MHO_MAX_VAL, /* caller can't use this definition, it's value maybe changed in next version!! */
+};
+
+
+/*
+ to set features of specified MESA_htable handle.
+ opt_type: option type, refer to enum MESA_htable_opt;
+ opt_val : option value, depend on opt type;
+ opt_len : opt_val size, depend on opt type;
+
+ return value:
+ 0 :success;
+ <0:error;
+*/
+int MESA_htable_set_opt(MESA_htable_handle table, enum MESA_htable_opt opt_type, void *opt_val, int opt_len);
+
+/*
+ to get features of specified MESA_htable handle.
+ opt_type: option type, refer to enum MESA_htable_opt;
+ opt_val : option value, depend on opt type;
+ opt_len : value-result argument, opt_val size, depend on opt type;
+
+ return value:
+ 0 :success;
+ <0:error;
+*/
+int MESA_htable_get_opt(MESA_htable_handle api_table, enum MESA_htable_opt opt_type, void *opt_val, int *opt_len);
+
+/*
+ Construct htable and ready to running.
+
+ return value:
+ 0 : success;
+ <0: error.
+*/
+int MESA_htable_mature(MESA_htable_handle table);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIB_HASH_H_INCLUDED_ */
+
+
diff --git a/support/include/MESA_list_count_for_view.h b/support/include/MESA_list_count_for_view.h
new file mode 100644
index 0000000..55523aa
--- /dev/null
+++ b/support/include/MESA_list_count_for_view.h
@@ -0,0 +1,31 @@
+#ifndef _MESA_LIST_COUNT_H_
+#define _MESA_LIST_COUNT_H_
+
+typedef struct MESA_list_count{
+ struct MESA_list_count *nextele;
+ struct MESA_list_count *preele;
+ void *quiddity;
+}MESA_list_count_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void MESA_list_count_init_head(struct MESA_list_count *head);
+long MESA_list_count_get_count(const struct MESA_list_count *head);
+int MESA_list_count_is_empty(const struct MESA_list_count *head);
+void MESA_list_count_add(struct MESA_list_count *head, struct MESA_list_count *new_list);
+void MESA_list_count_add_tail(struct MESA_list_count *head, struct MESA_list_count *new_list);
+void MESA_list_count_del(struct MESA_list_count *head, struct MESA_list_count *del_list);
+void MESA_list_count_move(struct MESA_list_count *head, struct MESA_list_count *list);
+void MESA_list_count_move_tail(struct MESA_list_count *head, struct MESA_list_count *list);
+struct MESA_list_count *MESA_list_count_join_n(struct MESA_list_count *head, struct MESA_list_count *op_place, struct MESA_list_count *new_obj);
+struct MESA_list_count *MESA_list_count_join_p(struct MESA_list_count *head, struct MESA_list_count *new_obj, struct MESA_list_count *op_place);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/support/include/MESA_list_for_view.h b/support/include/MESA_list_for_view.h
new file mode 100644
index 0000000..6d7cee8
--- /dev/null
+++ b/support/include/MESA_list_for_view.h
@@ -0,0 +1,34 @@
+#ifndef _MESA_LIST_H_
+#define _MESA_LIST_H_
+
+typedef struct MESA_list{
+ struct MESA_list *nextele;
+ struct MESA_list *preele;
+ void *quiddity;
+}MESA_list_t;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define MESA_LIST_VERSION_MACRO (20150529)
+extern const unsigned int MESA_LIST_VERSION_INT;
+
+void MESA_list_init_head(struct MESA_list *head);
+int MESA_list_is_empty(const struct MESA_list *head);
+void MESA_list_add(struct MESA_list *head, struct MESA_list *new_list);
+void MESA_list_add_tail(struct MESA_list *head, struct MESA_list *new_list);
+void MESA_list_del(struct MESA_list *head, struct MESA_list *del_list);
+void MESA_list_move(struct MESA_list *head, struct MESA_list *list);
+void MESA_list_move_tail(struct MESA_list *head, struct MESA_list *list);
+struct MESA_list *MESA_list_join_n(struct MESA_list *head, struct MESA_list *op_place, struct MESA_list *new_obj);
+struct MESA_list *MESA_list_join_p(struct MESA_list *head, struct MESA_list *new_obj, struct MESA_list *op_place);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/support/include/MESA_list_queue_for_view.h b/support/include/MESA_list_queue_for_view.h
new file mode 100644
index 0000000..6fdbdd7
--- /dev/null
+++ b/support/include/MESA_list_queue_for_view.h
@@ -0,0 +1,115 @@
+#ifndef _MESA_LIST_QUEUE_H_
+#define _MESA_LIST_QUEUE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+ MESA_list �����棬
+ 1-�����̰߳�ȫ����;
+ 2-�����ڲ��ṹ, ����ȫ���ӿڸ����;
+ 3-�������������й����ڵ�ṹ��ʹ�ø�����;
+*/
+
+#define MESA_LIST_QUEUE_VERSION_MACRO (20160308)
+extern const unsigned int MESA_LIST_QUEUE_VERSION_INT;
+
+#define MESA_LIST_OP_PLACE_HEAD (0x1)
+#define MESA_LIST_OP_PLACE_TAIL (0x2)
+
+#define MESA_list_GET (0x1)
+#define MESA_list_JOIN (0x2)
+
+#define MESA_list_BOLCK (0x4)
+#define MESA_list_NONBOLCK (0x8)
+
+#define MESA_list_JOIN_BLOCK (MESA_list_JOIN|MESA_list_BOLCK)
+#define MESA_list_JOIN_NONBLOCK (MESA_list_JOIN|MESA_list_NONBOLCK)
+#define MESA_list_GET_BLOCK (MESA_list_GET|MESA_list_BOLCK)
+#define MESA_list_GET_NONBLOCK (MESA_list_GET|MESA_list_NONBOLCK)
+
+typedef void * MESA_lqueue_head;
+typedef int (* MESA_lqueue_cb_t)(void *data, long data_len, void *arg);
+
+/* All of the following functions return value */
+typedef enum{
+ MESA_QUEUE_RET_OK = 0, /* success */
+ MESA_QUEUE_RET_COMMON_ERR = -1, /* general��undefined errors */
+ MESA_QUEUE_RET_ARG_ERR = -2, /* invalid args */
+ MESA_QUEUE_RET_NUM_FULL = -3, /* queue number full */
+ MESA_QUEUE_RET_MEM_FULL = -4, /* queue memory full */
+ MESA_QUEUE_RET_QEMPTY = -5, /* queue empty */
+ MESA_QUEUE_RET_LEN_ERR = -6, /* length error */
+ MESA_QUEUE_RET_CANT_GET_LOCK = -7, /* can't get lock in non-block mode */
+ MESA_QUEUE_RET_GET_LOCK_TMOUT = -8, /* get lock timeout */
+}MESA_queue_errno_t;
+
+/*
+ args description:
+ [IN]
+ thread_safe : 1:create thread safe queue; 0:without thread safe insurance.
+ max_item_num: maximum queue items of the queue, 0 means infinity.
+*/
+MESA_lqueue_head MESA_lqueue_create(int thread_safe, long max_item_num);
+
+/*
+ attention:
+ The follow two functions is get some value of queue in a moment,
+ however, the value you got is not exactly,
+ because it's maybe changed immediately by other thread when this functions is return.
+*/
+long MESA_lqueue_get_mem_used(MESA_lqueue_head head);
+long MESA_lqueue_get_count(MESA_lqueue_head head);
+
+
+/*
+ args description:
+ [IN]:
+ lq_head : the handler of MESA_lqueue.
+
+ [OUT]:
+ data : receive buffer.
+
+ [IN && OUT]:
+ data_len:
+ is value-result argument, like "addrlen of recvfrom(2)",
+ the caller should initialize the size of the 'data',
+ will modified on return to indicate the actual size of the queue item.
+
+*/
+int MESA_lqueue_read_head(MESA_lqueue_head lq_head, void *data, long *data_len);
+int MESA_lqueue_get_head(MESA_lqueue_head lqhead, void *data, long *data_len);
+
+/*
+ if return value of "cb" is 0, the behaviour is like MESA_lqueue_read_head(),
+ else if return value of "cb" is not 0, the behaviour is like MESA_lqueue_get_head().
+*/
+int MESA_lqueue_detect_get_head(MESA_lqueue_head lq_head, MESA_lqueue_cb_t cb, void *data, long *data_len, void *cb_arg);
+int MESA_lqueue_get_tail(MESA_lqueue_head lq_head, void *data, long *data_len);
+
+int MESA_lqueue_join_head(MESA_lqueue_head lq_head, const void *data, long data_len);
+int MESA_lqueue_join_tail(MESA_lqueue_head lq_head, const void *data, long data_len);
+
+
+/* these functions features same with above no "try",
+ except shall return immediately, in other word is "Non-block mode"!
+ */
+int MESA_lqueue_try_read_head(MESA_lqueue_head lq_head, void *data, long *data_len);
+int MESA_lqueue_try_get_head(MESA_lqueue_head lq_head, void *data, long *data_len);
+int MESA_lqueue_try_get_tail(MESA_lqueue_head lq_head, void *data, long *data_len);
+int MESA_lqueue_try_join_head(MESA_lqueue_head lq_head, const void *data, long data_len);
+int MESA_lqueue_try_join_tail(MESA_lqueue_head lq_head, const void *data, long data_len);
+
+
+void MESA_lqueue_destroy(MESA_lqueue_head head, MESA_lqueue_cb_t cb, void *cb_arg);
+
+const char *MESA_lqueue_strerror(MESA_queue_errno_t error_num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/support/include/MESA_prof_load_for_view.h b/support/include/MESA_prof_load_for_view.h
new file mode 100644
index 0000000..9ed5b40
--- /dev/null
+++ b/support/include/MESA_prof_load_for_view.h
@@ -0,0 +1,179 @@
+#ifndef SLIB_LOADPROF_H
+#define SLIB_LOADPROF_H
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_int_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val, // [OUT] returned value
+ const int dval); // [IN] default value
+
+
+
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_int_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val); // [OUT] returned value
+
+
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_uint_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val, // [OUT] returned value
+ const unsigned int dval); // [IN] default value
+
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_uint_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val); // [OUT] returned value
+
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_short_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val, // [OUT] returned value
+ const short dval); // [IN] default value
+
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_short_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val); // [OUT] returned value
+
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t' '\n' '\r'
+//
+// Return:
+// >= 0 : length of val
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+
+int MESA_load_profile_string_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size); // [IN] buffer size(bytes)
+
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t' '\n' '\r'
+//
+// Return:
+// >= 0 : length of val
+// < 0 : error, str is set to default
+int MESA_load_profile_string_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size, // [IN] buffer size(bytes)
+ const char *dstr); // [IN] default string
+
+
+
+//read ips from config file
+//return :
+// >=0 : success,return the number of ip read from file successfully
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error,invalid ip
+
+//if 0
+int MESA_load_profile_ipset(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const size_t size, // [IN] the size of memory ips point,it must equel or greater than ip_num*sizeof(unsigned int)
+ unsigned int *ipset); // [OUT] return ipset network bytes order
+
+// Write the a int into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_int(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const int value); // [IN] the integer need write
+
+// Write the a float into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_float(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const float value); // [IN] the float need write
+
+// Write the a string into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_string(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const char *value); // [IN] the string need write
+//endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef SLIB_LOADPROF_H */
diff --git a/support/include/MESA_ring_queue_for_view.h b/support/include/MESA_ring_queue_for_view.h
new file mode 100644
index 0000000..cc1efe8
--- /dev/null
+++ b/support/include/MESA_ring_queue_for_view.h
@@ -0,0 +1,107 @@
+#ifndef __MESA_RING_QUEUE_H_
+#define __MESA_RING_QUEUE_H_ 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef void * MESA_ring_queue_head;
+
+#define MESA_RING_QUEUE_VERSION_MACRO (20160708)
+extern const unsigned int MESA_RING_QUEUE_VERSION_INT;
+
+/* All of the following functions return value */
+typedef enum{
+ MESA_RQUEUE_RET_OK = 0, /* success */
+ MESA_RQUEUE_RET_COMMON_ERR = -1, /* general��undefined errors */
+ MESA_RQUEUE_RET_ARG_ERR = -2, /* invalid args */
+ MESA_RQUEUE_RET_NUM_FULL = -3, /* queue number full */
+ MESA_RQUEUE_RET_MEM_FULL = -4, /* queue memory full */
+ MESA_RQUEUE_RET_QEMPTY = -5, /* queue empty */
+ MESA_RQUEUE_RET_LEN_ERR = -6, /* length error */
+ MESA_RQUEUE_RET_CANT_GET_LOCK = -7, /* can't get lock in non-block mode */
+ MESA_RQUEUE_RET_GET_LOCK_TMOUT = -8, /* get lock timeout */
+}MESA_ring_queue_errno_t;
+
+
+/*
+ args description:
+ [IN]
+ thread_safe : 1:create thread safe queue; 0:without thread safe insurance.
+ max_item_num: maximum queue items of the queue, must more than zero.
+*/
+MESA_ring_queue_head MESA_ring_queue_born(void);
+
+
+enum MESA_rq_opt{
+ RQO_THREAD_SAFE = 0, /* must be int, 1:create ring qqueue with thread safe features, default is 1 */
+ RQO_RING_ELEMENT_NUM, /* must be unsigned int, defalut is 1000. */
+ RQO_PRE_ALLOC_BUF_LEN, /* must be unsigned int, Ԥ�ȷ���ÿ��item���ڴ�, �Ժ�ֻ��memcpy */
+ RQO_MULTI_THREAD_LOCK_FREE, /* must be int, default is 0, conflict with RQO_THREAD_SAFE */
+};
+
+/*
+ to set features of specified MESA_ring_queue_headhandle.
+ opt_type: option type, refer to enum MESA_htable_opt;
+ opt_val : option value, depend on opt type;
+ opt_len : opt_val size, depend on opt type;
+
+ return value:
+ 0 :success;
+ <0:error;
+*/
+int MESA_ring_queue_set_opt(MESA_ring_queue_head rq, enum MESA_rq_opt opt_type, void *opt_val, int opt_len);
+
+
+/*
+ Construct ring queue and ready to running.
+
+ return value:
+ 0 : success;
+ <0: error.
+*/
+int MESA_ring_queue_mature(MESA_ring_queue_head rq);
+
+
+
+int MESA_ring_queue_get_count(MESA_ring_queue_head head);
+
+/*
+ args description:
+ [IN]:
+ lq_head : the handler of MESA_ring_queue.
+
+ [OUT]:
+ data : receive buffer.
+
+ [IN && OUT]:
+ data_len:
+ is value-result argument, like "addrlen of recvfrom(2)",
+ the caller should initialize the size of the 'data',
+ will modified on return to indicate the actual size of the queue item.
+
+*/
+int MESA_ring_queue_read(MESA_ring_queue_head rq_head, void *data, int *data_len);
+int MESA_ring_queue_get(MESA_ring_queue_head rqhead, void *data, int *data_len);
+int MESA_ring_queue_join(MESA_ring_queue_head rq_head, const void *data, int data_len);
+
+
+/* these functions features same with above no "try",
+ except shall return immediately, in other word is "Non-block mode"!
+ */
+int MESA_ring_queue_try_read(MESA_ring_queue_head rq_head, void *data, int *data_len);
+int MESA_ring_queue_try_get(MESA_ring_queue_head rqhead, void *data, int *data_len);
+int MESA_ring_queue_try_join(MESA_ring_queue_head rq_head, const void *data, int data_len);
+
+
+typedef int (* MESA_rqueue_cb_t)(void *data, long data_len, void *arg);
+void MESA_ring_queue_destroy(MESA_ring_queue_head rq_head, MESA_rqueue_cb_t cb, void *cb_arg);
+const char *MESA_ring_queue_strerror(MESA_ring_queue_errno_t error_num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/support/include/Maat_command_for_view.h b/support/include/Maat_command_for_view.h
new file mode 100644
index 0000000..1d65383
--- /dev/null
+++ b/support/include/Maat_command_for_view.h
@@ -0,0 +1,154 @@
+#ifndef H_MAAT_COMMAND_H_INCLUDE
+#define H_MAAT_COMMAND_H_INCLUDE
+#ifndef __cplusplus
+#error("This file should be compiled with C++ compiler")
+#endif
+#include "Maat_rule.h"
+enum MAAT_OPERATION
+{
+ MAAT_OP_DEL=0,
+ MAAT_OP_ADD
+};
+
+enum MAAT_REGION_TYPE
+{
+ REGION_EXPR,
+ REGION_IP,
+ REGION_INTERVAL,
+ REGION_DIGEST,
+ REGION_SIMILARITY
+};
+enum MAAT_EXPR_TYPE
+{
+ EXPR_TYPE_STRING=0,
+ EXPR_TYPE_AND,
+ EXPR_TYPE_REGEX,
+ EXPR_TYPE_OFFSET
+};
+enum MAAT_MATCH_METHOD
+{
+ MATCH_METHOD_SUB=0,
+ MATCH_METHOD_RIGHT,
+ MATCH_METHOD_LEFT,
+ MATCH_METHOD_COMPLETE
+};
+
+enum MAAT_CASE_TYPE
+{
+ UNCASE_PLAIN=0,
+ CASE_HEXBIN,
+ CASE_PLAIN
+};
+enum MAAT_ADDR_TYPE
+{
+ ADDR_TYPE_IPv4=4,
+ ADDR_TYPE_IPv6=6
+};
+enum MAAT_ADDR_DIRECTION
+{
+ ADDR_DIR_DOUBLE=0,
+ ADDR_DIR_SINGLE=1
+};
+struct Maat_rgn_str_t
+{
+ const char *keywords;
+ const char *district;// optional for expr_plus, otherwise set to NULL.
+ enum MAAT_EXPR_TYPE expr_type;
+ enum MAAT_MATCH_METHOD match_method;
+ enum MAAT_CASE_TYPE hex_bin;
+};
+struct Maat_rgn_addr_t
+{
+ enum MAAT_ADDR_TYPE addr_type;
+ const char* src_ip;
+ const char* mask_src_ip;
+ const char* dst_ip;
+ const char* mask_dst_ip;
+ unsigned short src_port;
+ unsigned short mask_src_port;
+ unsigned short dst_port;
+ unsigned short mask_dst_port;
+ unsigned short protocol;
+ enum MAAT_ADDR_DIRECTION direction;
+};
+struct Maat_rgn_intv_t
+{
+ unsigned int low_boundary;
+ unsigned int up_boundary;
+};
+struct Maat_rgn_digest_t
+{
+ unsigned long long orgin_len;
+ const char* digest_string;
+ short confidence_degree;
+};
+struct Maat_rgn_sim_t
+{
+ char* target;
+ short threshold;// 1~100
+};
+struct Maat_region_t
+{
+ const char* table_name;
+ int region_id; //If MAAT_OPT_CMD_AUTO_NUMBERING==1, maat will assigned one. Or users must appoint a unique number.
+ enum MAAT_REGION_TYPE region_type;
+ union
+ {
+ struct Maat_rgn_str_t expr_rule;
+ struct Maat_rgn_addr_t ip_rule;
+ struct Maat_rgn_intv_t interval_rule;
+ struct Maat_rgn_digest_t digest_rule;
+ struct Maat_rgn_sim_t similarity_rule;
+ };
+};
+struct Maat_group_t
+{
+ int region_num;
+ int group_id; //If MAAT_OPT_CMD_AUTO_NUMBERING==1, maat will assigned one. Or users must assign a unique number.
+ struct Maat_region_t *regions;
+};
+struct Maat_cmd_t
+{
+ struct Maat_rule_t compile; // for MAAT_OP_DEL, only compile.config_id is necessary.
+ int group_num; // for MAAT_OP_DEL, set to 0.
+ int expire_after; //expired after $expire_after$ seconds, set to 0 for never timeout.
+ int label_id; //>0, to be indexed and quried by Maat_cmd_select; =0 not index
+ struct Maat_group_t* groups;// Add regions with Maat_add_region2cmd
+};
+struct Maat_line_t
+{
+ const char* table_name;
+ const char* table_line;
+ int rule_id; // for MAAT_OP_DEL, only rule_id is necessary.
+ int label_id;
+ int expire_after; //expired after $timeout$ seconds, set to 0 for never timeout.
+};
+struct Maat_cmd_t* Maat_create_cmd(const struct Maat_rule_t* rule, int group_num);
+//input: which_group 0~group_num
+//input: region can be freed after added.
+void Maat_add_region2cmd(struct Maat_cmd_t* cmd,int which_group,const struct Maat_region_t* region);
+
+void Maat_free_cmd(struct Maat_cmd_t* cmd);
+int Maat_format_cmd(struct Maat_cmd_t* cmd, char* buffer, int size);
+// REGION_EXPR and REGION_SIMILARITY need to escape input string.
+char* Maat_str_escape(char* dst,int size,const char*src);
+
+//Deletion failed due to not complete synchronize with Redis.
+//To make sure the delete command is excecuted, user should try again after MAAT_OPT_SCANDIR_INTERVAL_MS ms.
+// The following functions are NOT thread safe.
+int Maat_cmd(Maat_feather_t feather,struct Maat_cmd_t* cmd,enum MAAT_OPERATION op);
+
+//pipeline model
+int Maat_cmd_append(Maat_feather_t feather,struct Maat_cmd_t* cmd,enum MAAT_OPERATION op);
+int Maat_cmd_commit(Maat_feather_t feather);
+
+
+int Maat_cmd_set_group(Maat_feather_t feather, int group_id, const struct Maat_region_t* region, enum MAAT_OPERATION op);
+int Maat_cmd_set_line(Maat_feather_t feather,const struct Maat_line_t* line_rule, enum MAAT_OPERATION op);
+
+//Return the value of key after the increment.
+//If the key does not exist, it is set to 0 before performing the operation.
+long long Maat_cmd_incrby(Maat_feather_t feather,const char* key, int increment);
+int Maat_cmd_select(Maat_feather_t feather, int label_id, int * output_ids, unsigned int size);
+#endif
+
diff --git a/support/include/Maat_rule_for_view.h b/support/include/Maat_rule_for_view.h
new file mode 100644
index 0000000..e160a4a
--- /dev/null
+++ b/support/include/Maat_rule_for_view.h
@@ -0,0 +1,228 @@
+
+/*
+*****************Maat Network Flow Rule Manage Framework********
+* Maat is the Goddess of truth and justice in ancient Egyptian concept.
+* Her feather was the measure that determined whether the souls (considered
+* to reside in the heart) of the departed would reach the paradise of afterlife
+* successfully.
+* Author: [email protected],MESA
+* Version 2015-11-09 digest scan
+* NOTE: MUST compile with G++
+* All right reserved by Institute of Infomation Engineering,Chinese Academic of Science 2014~2018
+*********************************************************
+*/
+#ifndef H_MAAT_RULE_H_INCLUDE
+#define H_MAAT_RULE_H_INCLUDE
+#ifndef __cplusplus
+#error("This file should be compiled with C++ compiler")
+#endif
+#include "stream.h"
+enum MAAT_CHARSET
+{
+ CHARSET_NONE=0,
+ CHARSET_GBK,
+ CHARSET_BIG5,
+ CHARSET_UNICODE,
+ CHARSET_UTF8, // 4
+ CHARSET_BIN, //5
+ CHARSET_UNICODE_ASCII_ESC, // Unicode Escape format, prefix backslash-u hex, e.g. "\u627;"
+ CHARSET_UNICODE_ASCII_ALIGNED,//Unicode Escape format, prefix backslash-u with 4 bytes aligned, e.g. "\u0627"
+ CHARSET_UNICODE_NCR_DEC, //SGML Numeric character reference,decimal base, e.g. "&#1575;"
+ CHARSET_UNICODE_NCR_HEX, //SGML Numeric character reference,hexdecimal base, e.g. "&#x627;"
+ CHARSET_URL_ENCODE_GB2312, //URL encode with GB2312, e.g. the chinese word "china" was encoded to %D6%D0%B9%FA
+ CHARSET_URL_ENCODE_UTF8 //11, URL encode with UTF8,e.g. the chinese word "china" was encoded to %E4%B8%AD%E5%9B%BD
+};
+enum MAAT_ACTION
+{
+ MAAT_ACTION_BLOCK=0,
+ MAAT_ACTION_MONIT,
+ MAAT_ACTION_WHITE
+};
+enum MAAT_POS_TYPE
+{
+ MAAT_POSTYPE_EXPR=0,
+ MAAT_POSTYPE_REGEX
+};
+typedef void* scan_status_t;
+typedef void* stream_para_t;
+typedef void* Maat_feather_t;
+
+
+#define MAX_SERVICE_DEFINE_LEN 128
+struct Maat_rule_t
+{
+ int config_id;
+ int service_id;
+ char do_log;
+ char do_blacklist;
+ char action;
+ char resevered;
+ int serv_def_len;
+ char service_defined[MAX_SERVICE_DEFINE_LEN];
+};
+#define MAAT_RULE_UPDATE_TYPE_FULL 1
+#define MAAT_RULE_UPDATE_TYPE_INC 2
+typedef void Maat_start_callback_t(int update_type,void* u_para);
+typedef void Maat_update_callback_t(int table_id,const char* table_line,void* u_para);
+typedef void Maat_finish_callback_t(void* u_para);
+
+
+
+
+
+//--------------------HITTING DETAIL DESCRIPTION BEGIN
+
+#define MAAT_MAX_HIT_RULE_NUM 8
+#define MAAT_MAX_EXPR_ITEM_NUM 8
+#define MAAT_MAX_HIT_POS_NUM 8
+#define MAAT_MAX_REGEX_GROUP_NUM 8
+
+//NOTE position buffer as hitting_regex_pos and hit_pos,are ONLY valid before next scan or Maat_stream_scan_string_end
+struct regex_pos_t
+{
+ int group_num;
+ int hitting_regex_len;
+ const char* hitting_regex_pos;
+ int grouping_len[MAAT_MAX_REGEX_GROUP_NUM];
+ const char* grouping_pos[MAAT_MAX_REGEX_GROUP_NUM];
+};
+struct str_pos_t
+{
+ int hit_len;
+ const char* hit_pos;
+};
+struct sub_item_pos_t
+{
+ enum MAAT_POS_TYPE ruletype;
+ int hit_cnt;
+ union
+ {
+ struct regex_pos_t regex_pos[MAAT_MAX_HIT_POS_NUM];
+ struct str_pos_t substr_pos[MAAT_MAX_HIT_POS_NUM];
+ };
+};
+
+struct Maat_region_pos_t
+{
+
+ int region_id;
+ int sub_item_num;
+ struct sub_item_pos_t sub_item_pos[MAAT_MAX_EXPR_ITEM_NUM];
+};
+
+struct Maat_hit_detail_t
+{
+ int config_id;//set <0 if half hit;
+ int hit_region_cnt;
+ struct Maat_region_pos_t region_pos[MAAT_MAX_HIT_RULE_NUM];
+};
+//--------------------HITTING DETAIL DESCRIPTION END
+
+//Abondon interface ,left for compatible.
+Maat_feather_t Maat_summon_feather(int max_thread_num,
+ const char* table_info_path,
+ const char* ful_cfg_dir,
+ const char* inc_cfg_dir,
+ void*logger);//MESA_handle_logger
+//Abondon interface ,left for compatible.
+Maat_feather_t Maat_summon_feather_json(int max_thread_num,
+ const char* table_info_path,
+ const char* json_rule,
+ void* logger);
+
+Maat_feather_t Maat_feather(int max_thread_num,const char* table_info_path,void* logger);
+int Maat_initiate_feather(Maat_feather_t feather);
+
+enum MAAT_INIT_OPT
+{
+ MAAT_OPT_SCANDIR_INTERVAL_MS=1, //VALUE is interger, SIZE=sizeof(int). DEFAULT:1,000 milliseconds.
+ MAAT_OPT_EFFECT_INVERVAL_MS, //VALUE is interger, SIZE=sizeof(int). DEFAULT:60,000 milliseconds.
+ MAAT_OPT_FULL_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default.
+ MAAT_OPT_INC_CFG_DIR, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default.
+ MAAT_OPT_JSON_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1.DEFAULT: no default.
+ MAAT_OPT_STAT_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF.
+ MAAT_OPT_PERF_ON, //VALUE is NULL,SIZE is 0. MAAT_OPT_STAT_FILE_PATH must be set. Default: stat OFF.
+ MAAT_OPT_STAT_FILE_PATH, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT: no default.
+ MAAT_OPT_SCAN_DETAIL, //VALUE is interger *, SIZE=sizeof(int). 0: not return any detail;1: return hit pos, not include regex grouping;
+ // 2 return hit pos and regex grouping pos;DEFAULT:0
+ MAAT_OPT_INSTANCE_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1, no more than 11 bytes.DEFAULT: MAAT_$tableinfo_path$.
+ MAAT_OPT_DECRYPT_KEY, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT.
+ MAAT_OPT_REDIS_IP, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT.
+ MAAT_OPT_REDIS_PORT, //VALUE is a unsigned short, host order, SIZE= sizeof(unsigned short). No DEFAULT.
+ MAAT_OPT_REDIS_INDEX, //VALUE is interger *, 0~15, SIZE=sizeof(int). DEFAULT: 0.
+ MAAT_OPT_CMD_AUTO_NUMBERING, //VALUE is interger *, 1 or 0, SIZE=sizeof(int). DEFAULT: 1.
+ MAAT_OPT_DEFERRED_LOAD //VALUE is NULL,SIZE is 0. Default: Deffered initialization OFF.
+};
+//return -1 if failed, return 0 on success;
+int Maat_set_feather_opt(Maat_feather_t feather,enum MAAT_INIT_OPT type,const void* value,int size);
+void Maat_burn_feather(Maat_feather_t feather);
+
+//return table_id(>=0) if success,otherwise return -1;
+int Maat_table_register(Maat_feather_t feather,const char* table_name);
+//return 1 if success,otherwise return -1 incase invalid table_id or registed function number exceed 32;
+int Maat_table_callback_register(Maat_feather_t feather,short table_id,
+ Maat_start_callback_t *start,//MAAT_RULE_UPDATE_TYPE_*,u_para
+ Maat_update_callback_t *update,//table line ,u_para
+ Maat_finish_callback_t *finish,//u_para
+ void* u_para);
+
+enum MAAT_SCAN_OPT
+{
+ MAAT_SET_SCAN_DISTRICT=1, //VALUE is a const char*,SIZE= strlen(string).DEFAULT: no default.
+ MAAT_SET_SCAN_LAST_REGION //VALUE is NULL, SIZE=0. This option indicates that the follow scan is the last region of current scan cobination.
+};
+//return 0 if success, return -1 when failed;
+int Maat_set_scan_status(Maat_feather_t feather,scan_status_t* mid,enum MAAT_SCAN_OPT type,const void* value,int size);
+
+//Return hit rule number, return -1 when error occurs,return -2 when hit current region
+//mid MUST set NULL before fist call
+int Maat_scan_intval(Maat_feather_t feather,int table_id
+ ,unsigned int intval
+ ,struct Maat_rule_t*result,int rule_num
+ ,scan_status_t *mid,int thread_num);
+int Maat_scan_addr(Maat_feather_t feather,int table_id
+ ,struct ipaddr* addr
+ ,struct Maat_rule_t*result,int rule_num
+ ,scan_status_t *mid,int thread_num);
+int Maat_scan_proto_addr(Maat_feather_t feather,int table_id
+ ,struct ipaddr* addr,unsigned short int proto
+ ,struct Maat_rule_t*result,int rule_num
+ ,scan_status_t *mid,int thread_num);
+int Maat_full_scan_string(Maat_feather_t feather,int table_id
+ ,enum MAAT_CHARSET charset,const char* data,int data_len
+ ,struct Maat_rule_t*result,int* found_pos,int rule_num
+ ,scan_status_t* mid,int thread_num);
+//hite_detail could be NULL if unconcern
+int Maat_full_scan_string_detail(Maat_feather_t feather,int table_id
+ ,enum MAAT_CHARSET charset,const char* data,int data_len
+ ,struct Maat_rule_t*result,int rule_num,struct Maat_hit_detail_t *hit_detail,int detail_num
+ ,int* detail_ret,scan_status_t* mid,int thread_num);
+
+stream_para_t Maat_stream_scan_string_start(Maat_feather_t feather,int table_id,int thread_num);
+int Maat_stream_scan_string(stream_para_t* stream_para
+ ,enum MAAT_CHARSET charset,const char* data,int data_len
+ ,struct Maat_rule_t*result,int* found_pos,int rule_num
+ ,scan_status_t* mid);
+//hited_detail could be NULL if unconcern
+int Maat_stream_scan_string_detail(stream_para_t* stream_para
+ ,enum MAAT_CHARSET charset,const char* data,int data_len
+ ,struct Maat_rule_t*result,int rule_num,struct Maat_hit_detail_t *hit_detail,int detail_num
+ ,int* detail_ret,scan_status_t* mid);
+void Maat_stream_scan_string_end(stream_para_t* stream_para);
+
+stream_para_t Maat_stream_scan_digest_start(Maat_feather_t feather,int table_id,unsigned long long total_len,int thread_num);
+int Maat_stream_scan_digest(stream_para_t* stream_para
+ ,const char* data,int data_len,unsigned long long offset
+ ,struct Maat_rule_t*result,int rule_num
+ ,scan_status_t* mid);
+void Maat_stream_scan_digest_end(stream_para_t* stream_para);
+
+int Maat_similar_scan_string(Maat_feather_t feather,int table_id
+ ,const char* data,int data_len
+ ,struct Maat_rule_t*result,int rule_num
+ ,scan_status_t* mid,int thread_num);
+
+void Maat_clean_status(scan_status_t* mid);
+
+#endif // H_MAAT_RULE_H_INCLUDE
+
diff --git a/support/include/field_stat2_for_view.h b/support/include/field_stat2_for_view.h
new file mode 100644
index 0000000..7dbf5a5
--- /dev/null
+++ b/support/include/field_stat2_for_view.h
@@ -0,0 +1,66 @@
+#ifndef H_SCREEN_STAT2_H_INCLUDE
+#define H_SCREEN_STAT2_H_INCLUDE
+#include <stdio.h>
+
+#ifndef __cplusplus
+#error("This file should be compiled with C++ compiler")
+#endif
+
+enum field_dsp_style_t
+{
+ FS_STYLE_FIELD=0,
+ FS_STYLE_COLUMN,
+ FS_STYLE_LINE,
+ FS_STYLE_STATUS
+};
+enum field_calc_algo
+{
+ FS_CALC_CURRENT=0,
+ FS_CALC_SPEED
+};
+enum field_op
+{
+ FS_OP_ADD=1,
+ FS_OP_SET
+};
+
+
+typedef void* screen_stat_handle_t;
+
+enum FS_option
+{
+ OUTPUT_DEVICE, //VALUE is a const char*, indicate a file path string, SIZE = strlen(string+'\0')+1.DEFAULT:output to stdout.
+ PRINT_MODE, //VALUE is an interger,1:Rewrite ,2: Append. SIZE=4,DEFALUT:REWRITE.
+ STAT_CYCLE, //VALUE is an interger idicate interval seconds of every output, SIZE=4 ,DEFUALT:2 seconds.
+ PRINT_TRIGGER, //VALUE is an interger,1:Do print,0: Don't print.SIZE=4.DEFAULT:1.
+ CREATE_THREAD, //VALUE is an interger,1: Create a print thread,0:not create,output by call passive_output function,
+ //and the STAT_CYCLE is meaningless.SIZE=4,DEFAULT:0.
+ ID_INVISBLE, //value is field_id/status_id/column_id, not output this string, SIZE=4,DEFAULT: shutdown NO one.
+ FLUSH_BY_DATE, //value is 1(ture) or 0(false),SIZE=4,DEFAULT: Do not flush by date.
+ APP_NAME, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. DEFAULT is "?".
+ STATS_SERVER_IP, //VALUE is a const char*, MUST end with '\0', SIZE= strlen(string+'\0')+1. No DEFAULT.
+ STATS_SERVER_PORT, //VALUE is a unsigned short, host order, SIZE= sizeof(unsigned short). No DEFAULT.
+};
+
+//Always success.
+screen_stat_handle_t FS_create_handle(void);
+
+int FS_set_para(screen_stat_handle_t handle, enum FS_option type,const void* value,int size);
+void FS_start(screen_stat_handle_t handle);
+void FS_stop(screen_stat_handle_t* handle);
+
+//return field_id/line_id/column_id greater than zero if success,return an interger less than zero if failed.
+//should NOT include '\n','|' or ':' in the parameter name.
+int FS_register(screen_stat_handle_t handle,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name);
+
+//numerator_id and denominator_id must be column/field/status style.
+//scaling: negative value: zoom in; positive value: zoom out;
+int FS_register_ratio(screen_stat_handle_t handle,int numerator_id,int denominator_id,int scaling,enum field_dsp_style_t style,enum field_calc_algo calc_type,const char* name);
+
+//id: when id's type is FIELD , column_id is ignore.
+int FS_operate(screen_stat_handle_t handle,int id,int column_id,enum field_op op,long long value);
+
+void FS_passive_output(screen_stat_handle_t handle);
+
+#endif
+
diff --git a/support/include/本文件夹中的文件仅用于查看_不编译.txt b/support/include/本文件夹中的文件仅用于查看_不编译.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/support/include/本文件夹中的文件仅用于查看_不编译.txt
diff --git a/support/ltsm/Makefile b/support/ltsm/Makefile
new file mode 100644
index 0000000..1cb32b7
--- /dev/null
+++ b/support/ltsm/Makefile
@@ -0,0 +1,14 @@
+all:test_ltsm.so libltsm.a
+
+libltsm.a:ltsm.o
+ ar -r $@ $^;
+ cp $@ ../../lib
+
+test_ltsm.so:test_ltsm.o ltsm.o
+ gcc -fPIC -shared -o $@ $^ -I/opt/MESA/include/MESA
+
+test_ltsm.o:test_ltsm.c
+ gcc -fPIC -c -D__USE_MISC -D_BSD_SOURCE -o $@ $^ -I/opt/MESA/include/MESA
+
+ltsm.o:ltsm.c
+ gcc -fPIC -c -D__USE_MISC -D_BSD_SOURCE -o $@ $^ -I/opt/MESA/include/MESA
diff --git a/support/ltsm/ltsm.c b/support/ltsm/ltsm.c
new file mode 100644
index 0000000..c8af056
--- /dev/null
+++ b/support/ltsm/ltsm.c
@@ -0,0 +1,485 @@
+
+
+#include <netinet/ip.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+
+/*
+ * The TCP state transition table needs a few words...
+ *
+ * We are the man in the middle. All the packets go through us
+ * but might get lost in transit to the destination.
+ * It is assumed that the destinations can't receive segments
+ * we haven't seen.
+ *
+ * The checked segment is in window, but our windows are *not*
+ * equivalent with the ones of the sender/receiver. We always
+ * try to guess the state of the current sender.
+ *
+ * The meaning of the states are:
+ *
+ * NONE: initial state
+ * SYN_SENT: SYN-only packet seen
+ * SYN_SENT2: SYN-only packet seen from reply dir, simultaneous open
+ * SYN_RECV: SYN-ACK packet seen
+ * ESTABLISHED: ACK packet seen
+ * FIN_WAIT: FIN packet seen
+ * CLOSE_WAIT: ACK seen (after FIN)
+ * LAST_ACK: FIN seen (after FIN)
+ * TIME_WAIT: last ACK seen
+ * CLOSE: closed connection (RST)
+ *
+ * Packets marked as IGNORED (sIG):
+ * if they may be either invalid or valid
+ * and the receiver may send back a connection
+ * closing RST or a SYN/ACK.
+ *
+ * Packets marked as INVALID (sIV):
+ * if we regard them as truly invalid packets
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/ip.h>
+#include <assert.h>
+#include <time.h>
+#include <arpa/inet.h>
+#include "ltsm.h"
+
+
+
+enum tcp_conntrack {
+ TCP_CONNTRACK_NONE,
+ TCP_CONNTRACK_SYN_SENT,
+ TCP_CONNTRACK_SYN_RECV,
+ TCP_CONNTRACK_ESTABLISHED,
+ TCP_CONNTRACK_FIN_WAIT,
+ TCP_CONNTRACK_CLOSE_WAIT,
+ TCP_CONNTRACK_LAST_ACK,
+ TCP_CONNTRACK_TIME_WAIT,
+ TCP_CONNTRACK_CLOSE,
+ TCP_CONNTRACK_LISTEN, /* obsolete */
+#define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN
+ TCP_CONNTRACK_MAX,
+ TCP_CONNTRACK_IGNORE
+};
+
+
+/* What TCP flags are set from RST/SYN/FIN/ACK. */
+enum tcp_bit_set {
+ TCP_SYN_SET,
+ TCP_SYNACK_SET,
+ TCP_FIN_SET,
+ TCP_ACK_SET,
+ TCP_RST_SET,
+ TCP_NONE_SET,
+};
+
+#define TCP_URG_FLAG 0x20
+#define TCP_ACK_FLAG 0x10
+#define TCP_PSH_FLAG 0x08
+#define TCP_RST_FLAG 0x04
+#define TCP_SYN_FLAG 0x02
+#define TCP_FIN_FLAG 0x01
+#define TCP_FLAG_ALL 0x3F
+
+
+#define sNO TCP_CONNTRACK_NONE
+#define sSS TCP_CONNTRACK_SYN_SENT
+#define sSR TCP_CONNTRACK_SYN_RECV
+#define sES TCP_CONNTRACK_ESTABLISHED
+#define sFW TCP_CONNTRACK_FIN_WAIT
+#define sCW TCP_CONNTRACK_CLOSE_WAIT
+#define sLA TCP_CONNTRACK_LAST_ACK
+#define sTW TCP_CONNTRACK_TIME_WAIT
+#define sCL TCP_CONNTRACK_CLOSE
+#define sS2 TCP_CONNTRACK_SYN_SENT2
+#define sIV TCP_CONNTRACK_MAX
+#define sIG TCP_CONNTRACK_IGNORE
+
+static const struct ltsm_result g_tsm_first_void = {FTSM_VOID, LTSM_VOID}; /* ��SYN��, ��������״̬, ����void */
+static const struct ltsm_result g_tsm_first_start = {TCP_CONNTRACK_SYN_SENT, LTSM_START};
+
+
+static const char *g_ftsm_string[] =
+{
+ "VOID",
+ "FTSM_SYN_SENT",
+ "FTSM_SYN_RCVD",
+ "FTSM_ESTABLISHED",
+ "FTSM_FIN_WAIT",
+ "FTSM_CLOSE_WAIT",
+ "FTSM_LAST_ACK",
+ "FTSM_TIME_WAIT",
+ "FTSM_CLOSED",
+ "FTSM_LISTEN",
+ "__FTSM_MAX",
+};
+
+static const char *g_ltsm_string[] =
+{
+ "LTSM_VOID",
+ "LTSM_START",
+ "LTSM_DATA",
+ "LTSM_CLOSE",
+};
+
+
+
+static const enum light_tcp_state g_ltsm_full2light_table[12] =
+{
+ LTSM_VOID, /* TCP_CONNTRACK_NONE, */
+ LTSM_START, /* TCP_CONNTRACK_SYN_SENT, */
+ LTSM_DATA, /* TCP_CONNTRACK_SYN_RECV, */
+ LTSM_DATA, /* TCP_CONNTRACK_ESTABLISHED, */
+ LTSM_DATA, /* TCP_CONNTRACK_FIN_WAIT, */
+ LTSM_DATA, /* TCP_CONNTRACK_CLOSE_WAIT, */
+ LTSM_DATA, /* TCP_CONNTRACK_LAST_ACK, */
+ LTSM_CLOSE, /* TCP_CONNTRACK_TIME_WAIT, */
+ LTSM_CLOSE, /* TCP_CONNTRACK_CLOSE, */
+ LTSM_VOID, /* TCP_CONNTRACK_LISTEN, */
+ LTSM_VOID, /* TCP_CONNTRACK_MAX, */
+ LTSM_VOID, /* TCP_CONNTRACK_IGNORE */
+};
+
+/*
+ if dir == 0, packet from client; if dir == 1, packet from service.
+
+ new_tcp_state = tcp_conntracks[dir][new_tcp_flag][old_tcp_state];
+*/
+static const uint8_t tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
+ {/* ORIGINAL */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*syn*/ {sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sS2},
+ /*
+ * sNO -> sSS Initialize a new connection
+ * sSS -> sSS Retransmitted SYN
+ * sS2 -> sS2 Late retransmitted SYN
+ * sSR -> sIG
+ * sES -> sIG Error: SYNs in window outside the SYN_SENT state
+ * are errors. Receiver will reply with RST
+ * and close the connection.
+ * Or we are not in sync and hold a dead connection.
+ * sFW -> sIG
+ * sCW -> sIG
+ * sLA -> sIG
+ * sTW -> sSS Reopened connection (RFC 1122).
+ * sCL -> sSS
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*synack*/ {sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR},
+ /*
+ * sNO -> sIV Too late and no reason to do anything
+ * sSS -> sIV Client can't send SYN and then SYN/ACK
+ * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open
+ * sSR -> sIG
+ * sES -> sIG Error: SYNs in window outside the SYN_SENT state
+ * are errors. Receiver will reply with RST
+ * and close the connection.
+ * Or we are not in sync and hold a dead connection.
+ * sFW -> sIG
+ * sCW -> sIG
+ * sLA -> sIG
+ * sTW -> sIG
+ * sCL -> sIG
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*fin*/ {sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV},
+ /*
+ * sNO -> sIV Too late and no reason to do anything...
+ * sSS -> sIV Client migth not send FIN in this state:
+ * we enforce waiting for a SYN/ACK reply first.
+ * sS2 -> sIV
+ * sSR -> sFW Close started.
+ * sES -> sFW
+ * sFW -> sLA FIN seen in both directions, waiting for
+ * the last ACK.
+ * Migth be a retransmitted FIN as well...
+ * sCW -> sLA
+ * sLA -> sLA Retransmitted FIN. Remain in the same state.
+ * sTW -> sTW
+ * sCL -> sCL
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*ack*/ {sES, sIV, sES, sES, sCW, sCW, sTW, sTW, sCL, sIV},
+ /*
+ * sNO -> sES Assumed.
+ * sSS -> sIV ACK is invalid: we haven't seen a SYN/ACK yet.
+ * sS2 -> sIV
+ * sSR -> sES Established state is reached.
+ * sES -> sES :-)
+ * sFW -> sCW Normal close request answered by ACK.
+ * sCW -> sCW
+ * sLA -> sTW Last ACK detected.
+ * sTW -> sTW Retransmitted last ACK. Remain in the same state.
+ * sCL -> sCL
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*rst*/ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+ /*none*/ {sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV}},
+
+ {/******************************** REPLY *******************************/
+
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*syn*/ {sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2},
+ /*
+ * sNO -> sIV Never reached.
+ * sSS -> sS2 Simultaneous open
+ * sS2 -> sS2 Retransmitted simultaneous SYN
+ * sSR -> sIV Invalid SYN packets sent by the server
+ * sES -> sIV
+ * sFW -> sIV
+ * sCW -> sIV
+ * sLA -> sIV
+ * sTW -> sIV Reopened connection, but server may not do it.
+ * sCL -> sIV
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*synack*/ {sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sSR},
+ /*
+ * sSS -> sSR Standard open.
+ * sS2 -> sSR Simultaneous open
+ * sSR -> sSR Retransmitted SYN/ACK.
+ * sES -> sIG Late retransmitted SYN/ACK?
+ * sFW -> sIG Might be SYN/ACK answering ignored SYN
+ * sCW -> sIG
+ * sLA -> sIG
+ * sTW -> sIG
+ * sCL -> sIG
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*fin*/ {sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV},
+ /*
+ * sSS -> sIV Server might not send FIN in this state.
+ * sS2 -> sIV
+ * sSR -> sFW Close started.
+ * sES -> sFW
+ * sFW -> sLA FIN seen in both directions.
+ * sCW -> sLA
+ * sLA -> sLA Retransmitted FIN.
+ * sTW -> sTW
+ * sCL -> sCL
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*ack*/ {sIV, sIG, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIG},
+ /*
+ * sSS -> sIG Might be a half-open connection.
+ * sS2 -> sIG
+ * sSR -> sSR Might answer late resent SYN.
+ * sES -> sES :-)
+ * sFW -> sCW Normal close request answered by ACK.
+ * sCW -> sCW
+ * sLA -> sTW Last ACK detected.
+ * sTW -> sTW Retransmitted last ACK.
+ * sCL -> sCL
+ */
+ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2
+ */
+ /*rst*/ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
+ /*none*/ {sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV}}
+ };
+
+typedef struct{
+ uint32_t sip_net_order;
+ uint32_t dip_net_order;
+ uint16_t sport_net_order;
+ uint16_t dport_net_order;
+ uint8_t old_state;
+ uint8_t cur_state;
+ uint8_t create_dir;
+}ltsm_inner_t;
+
+
+const char *ltsm_fstate_ntop(enum full_tcp_state fstate)
+{
+ if((int)fstate < 0 || (int)fstate >= __FTSM_MAX){
+ return "Invalid";
+ }
+
+ return g_ftsm_string[fstate];
+}
+
+
+const char *ltsm_lstate_ntop(enum light_tcp_state lstate)
+{
+ if((int)lstate < 0 || (int)lstate > LTSM_CLOSE){
+ return "Invalid";
+ }
+
+ return g_ltsm_string[lstate];
+}
+
+
+
+static inline uint32_t ltsm_get_tcpflags(const struct ltsm_tcphdr *th) {
+ if (th->th_flags & TCP_RST_FLAG)
+ return TCP_RST_SET;
+ else if (th->th_flags & TCP_SYN_FLAG)
+ return ((th->th_flags & TCP_ACK_FLAG) ? TCP_SYNACK_SET : TCP_SYN_SET);
+ else if (th->th_flags & TCP_FIN_FLAG)
+ return TCP_FIN_SET;
+ else if (th->th_flags & TCP_ACK_FLAG)
+ return TCP_ACK_SET;
+ else
+ return TCP_NONE_SET;
+}
+
+
+static inline uint32_t ltsm_convert_tcpflags(uint8_t th_flags) {
+ if (th_flags & TCP_RST_FLAG)
+ return TCP_RST_SET;
+ else if (th_flags & TCP_SYN_FLAG)
+ return ((th_flags & TCP_ACK_FLAG) ? TCP_SYNACK_SET : TCP_SYN_SET);
+ else if (th_flags & TCP_FIN_FLAG)
+ return TCP_FIN_SET;
+ else if (th_flags & TCP_ACK_FLAG)
+ return TCP_ACK_SET;
+ else
+ return TCP_NONE_SET;
+}
+
+
+ltsm_stream_handle ltsm_create_handle(void)
+{
+ ltsm_inner_t *ltsm_inner;
+
+ ltsm_inner = calloc(1, sizeof(ltsm_inner_t));
+
+ ltsm_inner->old_state = TCP_CONNTRACK_SYN_SENT;
+
+ return ltsm_inner;
+}
+
+
+
+ltsm_stream_handle ltsm_create_stream_handle(const struct ltsm_iphdr * iphdr)
+{
+ const struct ltsm_tcphdr *tcp_hdr;
+ ltsm_inner_t *ltsm_inner;
+ int dir = 0;
+ uint32_t tcp_flags_set;
+
+ if(IPPROTO_TCP != iphdr->ip_p){
+ return NULL;
+ }
+
+ tcp_hdr = (const struct ltsm_tcphdr *)((char *)iphdr + iphdr->ip_hl*4);
+ if(TH_SYN == tcp_hdr->th_flags){
+ dir = 0;
+ }else if(TH_SYN|TH_ACK == tcp_hdr->th_flags){
+ dir = 1;
+ }else{
+ return NULL;
+ }
+
+ ltsm_inner = calloc(1, sizeof(ltsm_inner_t));
+ ltsm_inner->old_state = TCP_CONNTRACK_NONE;
+ ltsm_inner->sip_net_order = iphdr->ip_src.s_addr;
+ ltsm_inner->dip_net_order = iphdr->ip_dst.s_addr;
+ ltsm_inner->sport_net_order = tcp_hdr->th_sport;
+ ltsm_inner->dport_net_order = tcp_hdr->th_dport;
+
+ tcp_flags_set = ltsm_get_tcpflags(tcp_hdr);
+
+ ltsm_inner->cur_state = tcp_conntracks[dir][tcp_flags_set][ltsm_inner->old_state];
+ ltsm_inner->create_dir = dir;
+
+ return ltsm_inner;
+}
+
+
+uint8_t ltsm_proc_ipv4tcppkt(ltsm_stream_handle s_ltsm, const struct ltsm_iphdr *iphdr)
+{
+ uint8_t tcpstate;
+ ltsm_inner_t *ltsm_inner = (ltsm_inner_t *)s_ltsm;
+ int dir = 0;
+ uint32_t tcp_flags_set;
+ const struct ltsm_tcphdr *tcp_hdr;
+
+ if(IPPROTO_TCP != iphdr->ip_p){
+ return LTSM_VOID;
+ }
+
+ tcp_hdr = (const struct ltsm_tcphdr *)((char *)iphdr + iphdr->ip_hl*4);
+ tcp_flags_set = ltsm_get_tcpflags(tcp_hdr);
+
+ if((ltsm_inner->sip_net_order == iphdr->ip_src.s_addr)
+ && (ltsm_inner->dip_net_order == iphdr->ip_dst.s_addr)
+ && (ltsm_inner->sport_net_order == tcp_hdr->th_sport)
+ && (ltsm_inner->dport_net_order == tcp_hdr->th_dport)){
+ dir = ltsm_inner->create_dir;
+ }else{
+ dir = ltsm_inner->create_dir ^ 1;
+ }
+
+ tcpstate = tcp_conntracks[dir][tcp_flags_set][ltsm_inner->old_state];
+
+ if(tcpstate < TCP_CONNTRACK_MAX){
+ ltsm_inner->old_state = tcpstate;
+ }
+
+ return tcpstate;
+}
+
+void ltsm_destroy_stream_handle(ltsm_stream_handle pltsm)
+{
+ free(pltsm);
+}
+
+void ltsm_destroy_handle(ltsm_stream_handle pltsm)
+{
+ free(pltsm);
+}
+
+
+
+struct ltsm_result ltsm_get_current_state(ltsm_stream_handle pltsm, uint8_t tcp_flags, uint8_t dir)
+{
+ uint8_t tcp_fstate;
+ uint32_t tcp_flags_set;
+ struct ltsm_result res;
+
+ if(NULL == pltsm){
+ if(TH_SYN != tcp_flags){
+ return g_tsm_first_void;
+ }
+
+ return g_tsm_first_start;
+ }
+
+ ltsm_inner_t *ltsm_inner = (ltsm_inner_t *)pltsm;
+
+ tcp_flags_set = ltsm_convert_tcpflags(tcp_flags);
+ tcp_fstate = tcp_conntracks[dir][tcp_flags_set][ltsm_inner->old_state];
+
+ ltsm_inner->old_state = tcp_fstate;
+
+ res.fstate = tcp_fstate;
+ res.lstate = g_ltsm_full2light_table[tcp_fstate];
+
+ return res;
+}
+
+
+uint32_t ltsm_tcp_key_generate(uint32_t sip_net_order, uint32_t dip_net_order, uint16_t sport_net_order, uint16_t dport_net_order)
+{
+
+}
+
+int ltsm_tcp_key_verify(const struct ip * iphdr)
+{
+
+}
+
diff --git a/support/ltsm/ltsm.h b/support/ltsm/ltsm.h
new file mode 100644
index 0000000..340aa2f
--- /dev/null
+++ b/support/ltsm/ltsm.h
@@ -0,0 +1,117 @@
+#ifndef __LTSM_H_
+#define __LTSM_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+ LTSM : Light TCP State Machine.
+ Version : 2018-01-16
+*/
+
+/* RFC��׼TCPЭ��ջ״̬������ */
+enum full_tcp_state{
+ FTSM_VOID, /* ���һ�����ĵ�һ��������SYN��, ���ش�ֵ */
+ FTSM_SYN_SENT,
+ FTSM_SYN_RCVD,
+ FTSM_ESTABLISHED,
+ FTSM_FIN_WAIT,
+ FTSM_CLOSE_WAIT,
+ FTSM_LAST_ACK,
+ FTSM_TIME_WAIT,
+ FTSM_CLOSED,
+ FTSM_LISTEN,
+ __FTSM_MAX,
+};
+
+/*
+ ����TCP״̬������,
+ ʵ��ֻ������״̬:�½�����, ��������, ��������,
+ ÿ�����ض�����1��START��1��CLOSE״̬, ���ܰ���0�����ɸ�DATA״̬.
+
+ VOID״̬���ڵ����߿����ж��Ƿ���Ҫ��������.
+*/
+enum light_tcp_state{
+ LTSM_VOID, /* ���һ�����ĵ�һ��������SYN��, ���ش�ֵ */
+ LTSM_START,
+ LTSM_DATA,
+ LTSM_CLOSE,
+};
+
+struct ltsm_iphdr
+ {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned int ip_hl:4; /* header length */
+ unsigned int ip_v:4; /* version */
+#endif
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int ip_v:4; /* version */
+ unsigned int ip_hl:4; /* header length */
+#endif
+ u_int8_t ip_tos; /* type of service */
+ u_short ip_len; /* total length */
+ u_short ip_id; /* identification */
+ u_short ip_off; /* fragment offset field */
+#define IP_RF 0x8000 /* reserved fragment flag */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_int8_t ip_ttl; /* time to live */
+ u_int8_t ip_p; /* protocol */
+ u_short ip_sum; /* checksum */
+ struct in_addr ip_src, ip_dst; /* source and dest address */
+ };
+
+struct ltsm_tcphdr
+ {
+ u_int16_t th_sport; /* source port */
+ u_int16_t th_dport; /* destination port */
+ u_int32_t th_seq; /* sequence number */
+ u_int32_t th_ack; /* acknowledgement number */
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+ u_int8_t th_x2:4; /* (unused) */
+ u_int8_t th_off:4; /* data offset */
+# endif
+# if __BYTE_ORDER == __BIG_ENDIAN
+ u_int8_t th_off:4; /* data offset */
+ u_int8_t th_x2:4; /* (unused) */
+# endif
+ u_int8_t th_flags;
+# define TH_FIN 0x01
+# define TH_SYN 0x02
+# define TH_RST 0x04
+# define TH_PUSH 0x08
+# define TH_ACK 0x10
+# define TH_URG 0x20
+ u_int16_t th_win; /* window */
+ u_int16_t th_sum; /* checksum */
+ u_int16_t th_urp; /* urgent pointer */
+};
+
+struct ltsm_result{
+ enum full_tcp_state fstate;
+ enum light_tcp_state lstate;
+};
+
+typedef void * ltsm_stream_handle;
+
+ltsm_stream_handle ltsm_create_handle(void);
+
+#define LTSM_DIR_C2S 0
+#define LTSM_DIR_S2C 1
+
+struct ltsm_result ltsm_get_current_state(ltsm_stream_handle pltsm, uint8_t tcp_flags, uint8_t dir);
+
+const char *ltsm_fstate_ntop(enum full_tcp_state fstate);
+const char *ltsm_lstate_ntop(enum light_tcp_state lstate);
+
+void ltsm_destroy_handle(ltsm_stream_handle pltsm);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/support/ltsm/ltsm_with_hash.h b/support/ltsm/ltsm_with_hash.h
new file mode 100644
index 0000000..0404f3d
--- /dev/null
+++ b/support/ltsm/ltsm_with_hash.h
@@ -0,0 +1,81 @@
+#ifndef LTSM_H_
+#define LTSM_H_
+
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include "mesa_net.h"
+/*
+ LTSM : Light TCP State Machine.
+
+*/
+
+/* RFC��׼TCPЭ��ջ״̬������ */
+enum full_tcp_state{
+ FTSM_CLOSED,
+ FTSM_LISTEN,
+ FTSM_SYN_SENT,
+ FTSM_SYN_RCVD,
+ FTSM_ESTABLISHED,
+ FTSM_CLOSE_WAIT,
+ FTSM_LAST_ACK,
+ FTSM_FIN_WAIT1,
+ FTSM_FIN_WAIT2,
+ FTSM_CLOSING,
+ FTSM_TIME_WAIT,
+};
+
+/*
+ ����TCP״̬������,
+ ֻ������״̬:�½�����, ��������, ��������,
+ ÿ�����ض�����1��START��1��CLOSE״̬, ���ܰ���0�����ɸ�DATA״̬.
+*/
+enum light_tcp_state{
+ LTSM_START,
+ LTSM_DATA,
+ LTSM_CLOSE,
+ LTSM_INVALID,
+};
+
+
+enum light_tsm_opt{
+ LTSMO_THREAD_NUM, /* �߳�����, ѡ������:uint32 */
+ LTSMO_CREATE_MODE, /* ������ģʽ, 1:�������SYN; 2:�������ݰ��ɴ���, ѡ������:uint32 */
+ LTSMO_MAX_STREAM_NUM, /* TCP��󲢷�������, forÿ���߳�, ѡ������:uint32 */
+ LTSMO_STREAM_TIMEOUT, /* ����ʱ��̭ʱ��, ��λ:��, 0��ʾ����ʱ. ѡ������:uint32 */
+};
+
+struct ltsm_result{
+ enum full_tcp_state fstate;
+ enum light_tcp_state lstate;
+ void *pme;
+};
+
+typedef void * ltsm_global_handle;
+typedef void * ltsm_stream_handle;
+
+/* ltsmȫ�־����ʼ�� */
+void *ltsm_init(void);
+
+/* ltsm������ز��� */
+int ltsm_set_opt(ltsm_global_handle pltsm, enum light_tsm_opt opt, void *value, int value_len);
+
+/* ltsm���� */
+int ltsm_run(ltsm_global_handle pltsm);
+
+/* IPv4������, ���ص�ǰ��������ltsm״̬�����, pme�����ⲿ�����ߴ洢�Զ�������, �ڴ�������������ͷ� */
+struct ltsm_result *ltsm_proc_ip4pkt(ltsm_global_handle pltsm, int tseq, const struct ip *ip4hdr);
+
+/* IPv4��ͷ+TCP��ͷ����, ���ص�ǰ��������ltsm״̬�����, pme�����ⲿ�����ߴ洢�Զ�������, �ڴ�������������ͷ� */
+struct ltsm_result *ltsm_proc_ip4tcppkt(ltsm_global_handle pltsm, int tseq, const struct ip *ip4hdr, const struct tcphdr *tcp_hdr);
+
+/* IPv6������, ���ص�ǰ��������ltsm״̬�����, pme�����ⲿ�����ߴ洢�Զ�������, �ڴ�������������ͷ� */
+struct ltsm_result *ltsm_proc_ip6pkt(ltsm_global_handle pltsm, int tseq, const struct ip6_hdr *ip6hdr);
+
+/* IPv6��ͷ+TCP��ͷ����, ���ص�ǰ��������ltsm״̬�����, pme�����ⲿ�����ߴ洢�Զ�������, �ڴ�������������ͷ� */
+struct ltsm_result *ltsm_proc_ip6tcppkt(ltsm_global_handle pltsm, int tseq, const struct ip6_hdr *ip6hdr, const struct tcphdr *tcp_hdr);
+
+uint8_t ltsm_proc_ipv4tcppkt(ltsm_stream_handle s_ltsm, const struct mesa_ip4_hdr *iphdr);
+
+void ltsm_destroy_stream_handle(ltsm_stream_handle s_ltsm);
+#endif \ No newline at end of file
diff --git a/support/ltsm/test_ltsm.c b/support/ltsm/test_ltsm.c
new file mode 100644
index 0000000..01935a9
--- /dev/null
+++ b/support/ltsm/test_ltsm.c
@@ -0,0 +1,59 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <assert.h>
+#include <time.h>
+#include <arpa/inet.h>
+
+#include "stream.h"
+#include "ltsm.h"
+
+
+
+
+char LTSM_TCPALL_ENTRY(struct streaminfo *pstream, void **pme, int thread_seq,void *apacket)
+{
+ void *ltsm_handle;
+ struct ltsm_result tcpstate;
+ const struct ltsm_tcphdr *tcp_hdr;
+ const struct ip *iphdr = (const struct ip *)apacket;
+
+ if(apacket != NULL){
+ tcp_hdr = (const struct ltsm_tcphdr *)((char *)iphdr + iphdr->ip_hl*4);
+ }
+
+ if(OP_STATE_PENDING == pstream->pktstate){
+ tcpstate = ltsm_get_current_state(NULL, tcp_hdr->th_flags, pstream->curdir);
+ if(LTSM_START == tcpstate.lstate ){
+ ltsm_handle = ltsm_create_handle();
+ *pme = ltsm_handle;
+ }else{
+ return APP_STATE_DROPME;
+ }
+ }else{
+ ltsm_handle = *pme;
+ if(OP_STATE_CLOSE == pstream->pktstate){
+ ltsm_destroy_handle(ltsm_handle);
+ return APP_STATE_DROPME;
+ }
+ }
+
+
+ tcpstate = ltsm_get_current_state(ltsm_handle, tcp_hdr->th_flags, pstream->curdir - 1);
+
+ printf("stream: %s, flags:0x%x, fstate: %s,\t lstate:%s\n", printaddr(&pstream->addr, thread_seq), tcp_hdr->th_flags, ltsm_fstate_ntop(tcpstate.fstate), ltsm_lstate_ntop(tcpstate.lstate));
+
+ return APP_STATE_GIVEME;
+}
+
+
+int LTSM_INIT(void)
+{
+ return 1;
+}
+
+
+
diff --git a/test/mutex_vs_rdlock.c b/test/mutex_vs_rdlock.c
new file mode 100644
index 0000000..e05ee65
--- /dev/null
+++ b/test/mutex_vs_rdlock.c
@@ -0,0 +1,138 @@
+#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>
+
+
+
+#define LOCK_TYPE (2) /* 1:mutex; 2:rwlock; 3:atomic */
+
+#if LOCK_TYPE==1
+pthread_rwlock_t test_rwlock;
+#elif LOCK_TYPE==2
+pthread_mutex_t test_mlock;
+#elif LOCK_TYPE==3
+long atomic_lock = 0;
+#endif
+
+unsigned long long g_val;
+
+unsigned long long g_producer_op_times = 0, g_customer_op_times;
+
+
+static inline void test_lock(long lock_val)
+{
+#if LOCK_TYPE==1
+ pthread_rwlock_wrlock(&test_rwlock);
+#elif LOCK_TYPE==2
+ pthread_mutex_lock(&test_mlock);
+#elif LOCK_TYPE==3
+ while((__sync_or_and_fetch(&atomic_lock, lock_val) & 0xF) == lock_val){
+ ;
+ }
+#endif
+
+}
+
+static inline void test_rlock(long lock_val)
+{
+#if LOCK_TYPE==1
+ pthread_rwlock_rdlock(&test_rwlock);
+#elif LOCK_TYPE==2
+ pthread_mutex_lock(&test_mlock);
+#elif LOCK_TYPE==3
+ while((__sync_or_and_fetch(&atomic_lock, lock_val) & 0xF) == lock_val){
+ ;
+ }
+#endif
+
+}
+
+static inline void test_unlock(long lock_mask)
+{
+#if LOCK_TYPE==1
+ pthread_rwlock_unlock(&test_rwlock);
+#elif LOCK_TYPE==2
+ pthread_mutex_unlock(&test_mlock);
+#elif LOCK_TYPE==3
+ __sync_and_and_fetch(&atomic_lock, lock_mask);
+#endif
+}
+
+/*
+ ���bit: producer;
+ ��2bit : customer;
+*/
+
+static void *producer_thread(void *arg)
+{
+ int i;
+
+ //for(i = 0; i < 9999999; i++){
+ while(1){
+ test_lock(0x01);
+ g_val++;
+ test_unlock(0xFE);
+ g_producer_op_times++;
+ }
+
+ return NULL;
+}
+
+static void *customer_thread(void *arg)
+{
+ unsigned long long tmp;
+ int i;
+
+ //for(i = 0; i < 9999999; i++){
+ while(1){
+ test_rlock(0x02);
+ tmp = g_val;
+ test_unlock(0xFD);
+ g_customer_op_times++;
+ }
+
+ return NULL;
+}
+
+static void *stat_thread(void *arg)
+{
+ unsigned long long last_op_times = 0;
+
+ while(1){
+ printf("op PPS: %llu\n", g_customer_op_times + g_producer_op_times - last_op_times);
+ last_op_times = g_customer_op_times + g_producer_op_times;
+ sleep(1);
+ }
+
+ return NULL;
+}
+
+int main(void)
+{
+#if LOCK_TYPE==1
+ pthread_rwlock_init(&test_rwlock, NULL);
+#elif LOCK_TYPE==2
+ pthread_mutex_init(&test_mlock, NULL);
+#endif
+
+ pthread_t stat_pid, producer_pid, customer_pid;
+
+ pthread_create(&stat_pid, NULL, stat_thread, NULL);
+
+ pthread_create(&producer_pid, NULL, producer_thread, NULL);
+ pthread_create(&customer_pid, NULL, customer_thread, NULL);
+
+ pthread_join(producer_pid, NULL);
+ pthread_join(customer_pid, NULL);
+
+ printf("%llu\n", g_val);
+
+ return 0;
+}
+
diff --git a/test/sport_usable.c b/test/sport_usable.c
new file mode 100644
index 0000000..1f9ec6b
--- /dev/null
+++ b/test/sport_usable.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+
+#define TOT_ACC_GW_NUM (10)
+#define THIS_ACC_GW_ID (5)
+#define THREAD_NUM (8)
+
+/* for test */
+static int flwd_act_ip_get_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 =
+ 64511 / TOT_ACC_GW_NUM;
+
+ this_gateway_begin_port =
+ this_gateway_usable_tot_count * (THIS_ACC_GW_ID-1) + 1025;
+
+ this_thread_usable_tot_count =
+ this_gateway_usable_tot_count / THREAD_NUM;
+
+ *usable_count =
+ this_gateway_usable_tot_count / THREAD_NUM;
+
+ *begin_port = this_gateway_begin_port + (*usable_count) * tid;
+
+ return 0;
+}
+
+int main(void)
+{
+ int i;
+ unsigned short begin_port;
+ unsigned short usable_count;
+
+ for(i =0; i < THREAD_NUM; i++){
+ flwd_act_ip_get_usable_sport(i, &begin_port, &usable_count);
+ printf("thread:%d, begin:%u, count:%u\n", i, begin_port, usable_count);
+ }
+ return 0;
+}
+
+