From 86a43b4d325ddc850fa9dc4711670880f35b11e8 Mon Sep 17 00:00:00 2001 From: lijia Date: Wed, 24 Oct 2018 09:36:45 +0800 Subject: create new project. --- src/forward/Makefile | 27 + src/forward/flowood_forward.c | 1044 ++++++++++++++++++++++++++++++++++++++ src/forward/flwd_fwd_idle_call.c | 5 + src/forward/flwd_fwd_maat.c | 40 ++ 4 files changed, 1116 insertions(+) create mode 100644 src/forward/Makefile create mode 100644 src/forward/flowood_forward.c create mode 100644 src/forward/flwd_fwd_idle_call.c create mode 100644 src/forward/flwd_fwd_maat.c (limited to 'src/forward') 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 +#include +#include +#include +#include +#include + +/* + 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是全局识别某个接入网关的, 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 : 是本系统复用的流量; + 0 : 不是本系统复用的流量; +*/ +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复用了某个端口, 而真实客户端又使用了这个端口发了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是全局识别某个接入网关的, 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} + -- cgit v1.2.3