summaryrefslogtreecommitdiff
path: root/src/forward
diff options
context:
space:
mode:
Diffstat (limited to 'src/forward')
-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
4 files changed, 1116 insertions, 0 deletions
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;
+}
+