summaryrefslogtreecommitdiff
path: root/src/packet_io
diff options
context:
space:
mode:
authorlijia <[email protected]>2018-10-24 09:36:45 +0800
committerlijia <[email protected]>2018-10-24 09:36:45 +0800
commit86a43b4d325ddc850fa9dc4711670880f35b11e8 (patch)
tree8356a056ac9bfb8cf14fcf57f113dd306b4277d1 /src/packet_io
create new project.
Diffstat (limited to 'src/packet_io')
-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
8 files changed, 1514 insertions, 0 deletions
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);
+}