summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes3
-rw-r--r--.gitignore8
-rw-r--r--Makefile73
-rw-r--r--README75
-rw-r--r--conf/.gitignore8
-rw-r--r--conf/nl2fwd.conf62
-rw-r--r--driver/.gitignore8
-rw-r--r--driver/Makefile44
-rw-r--r--driver/apt.c284
-rw-r--r--driver/apt.h11
-rw-r--r--driver/config.c752
-rw-r--r--driver/init.c598
-rw-r--r--driver/layer.c267
-rw-r--r--driver/layer.h39
-rw-r--r--driver/main.c228
-rw-r--r--driver/nl2fwd.h19
-rw-r--r--driver/nstat.c270
-rw-r--r--driver/nstat.h72
-rw-r--r--driver/runtime.c531
-rw-r--r--driver/version.c5
-rw-r--r--driver/version.h9
-rw-r--r--include/.gitignore8
-rw-r--r--include/MESA/MESA_prof_load.h197
-rw-r--r--include/pcap/bluetooth.h48
-rw-r--r--include/pcap/bpf.h1303
-rw-r--r--include/pcap/ipnet.h43
-rw-r--r--include/pcap/namedb.h89
-rw-r--r--include/pcap/pcap.h463
-rw-r--r--include/pcap/sll.h129
-rw-r--r--include/pcap/usb.h143
-rw-r--r--include/pcap/vlan.h46
-rw-r--r--include/serial/main.h625
-rw-r--r--include/serial/nstat_common.h58
-rw-r--r--lib/.gitignore8
-rw-r--r--lib/libMESA_prof_load.abin0 -> 28264 bytes
-rw-r--r--lib/libMESA_prof_load.sobin0 -> 25314 bytes
-rw-r--r--logreader/.gitignore8
-rw-r--r--logreader/Makefile44
-rw-r--r--logreader/config.c746
-rwxr-xr-xlogreader/dlogreaderbin0 -> 477573 bytes
-rw-r--r--logreader/main.c22
-rw-r--r--logreader/nstat.c208
-rw-r--r--logreader/nstat.h72
-rw-r--r--support/MESA_prof_load/.gitignore8
-rw-r--r--support/MESA_prof_load/Makefile13
-rw-r--r--support/MESA_prof_load/README39
-rw-r--r--support/MESA_prof_load/demo/Makefile34
-rw-r--r--support/MESA_prof_load/demo/config.ini11
-rw-r--r--support/MESA_prof_load/demo/demo.c65
-rw-r--r--support/MESA_prof_load/inc/MESA_prof_load.h179
-rw-r--r--support/MESA_prof_load/lib/libMESA_prof_load.abin0 -> 28264 bytes
-rw-r--r--support/MESA_prof_load/lib/libMESA_prof_load.sobin0 -> 25314 bytes
-rw-r--r--support/MESA_prof_load/src/MESA_prof_load.abin0 -> 27984 bytes
-rw-r--r--support/MESA_prof_load/src/MESA_prof_load.c806
-rw-r--r--support/MESA_prof_load/src/Makefile46
-rw-r--r--support/Makefile19
-rw-r--r--test/.gitignore8
-rw-r--r--test/Makefile10
-rw-r--r--test/conf/nl2fwd.conf.bak54
-rw-r--r--test/nl2fwd.h19
-rw-r--r--test/r21
-rw-r--r--test/r313
-rw-r--r--test/test.c24
-rw-r--r--tools/.gitignore8
-rw-r--r--tools/Makefile6
-rwxr-xr-xtools/dpdk_mlx4171
-rwxr-xr-xtools/drv_monitor.sh35
-rwxr-xr-xtools/drv_start.sh28
-rw-r--r--worker/.gitignore8
-rw-r--r--worker/Makefile51
-rw-r--r--worker/apt.c201
-rw-r--r--worker/apt.h11
-rw-r--r--worker/config.c777
-rw-r--r--worker/init.c584
-rw-r--r--worker/nl2fwd.c275
-rw-r--r--worker/nl2fwd.h19
-rw-r--r--worker/nstat.c42
-rw-r--r--worker/nstat.h45
-rw-r--r--worker/olpnet.c212
-rw-r--r--worker/olpnet.h9
-rw-r--r--worker/runtime.c626
-rw-r--r--worker/version.c2
-rw-r--r--worker/vlan.c93
-rw-r--r--worker/vlan.h11
-rw-r--r--worker/watchdog.c241
-rw-r--r--worker/watchdog.h39
86 files changed, 12469 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..04d8752
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+*.a binary
+*.so binary
+*.o binary
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a3f5912
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,73 @@
+#######################################################
+# Project: Serial-Multiprocess Project
+# Version: 1.1.0
+# Author: Lu Qiuwen<[email protected]>
+# Date: 2014-12-11
+#######################################################
+
+OPTFLAGS =
+QUITE = 1
+MODULES_VLAN_DMAC = 0
+MODULES_ENERGY = 1
+MODULES_STATS = 1
+MODULES_WATCHDOG = 1
+
+#######################################################
+
+DPDK_ROOT = $(RTE_SDK)
+DPDK_TARGET = $(RTE_TARGET)
+APP_ROOT = $(CURDIR)
+INSTALL = $(CURDIR)/test
+LIB_INSTALL = /usr/lib
+
+export OPTFLAGS
+export QUITE
+export MODULES_VLAN_DMAC
+export MODULES_ENERGY
+export MODULES_STATS
+export MODULES_WATCHDOG
+
+export DPDK_ROOT
+export DPDK_TARGET
+export APP_ROOT
+export INSTALL
+export LIB_INSTALL
+
+WORKER = worker
+DRIVER = driver
+SUPPORT = support
+TOOLS = tools
+LOGREADER = logreader
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+ifeq ($(RTE_TARGET),)
+$(error "Please define RTE_TARGET environment variable")
+endif
+
+.PHONY: install clean
+
+all:
+ cd $(SUPPORT) && $(MAKE)
+ cd $(WORKER) && $(MAKE)
+ cd $(DRIVER) && $(MAKE)
+ cd $(LOGREADER) && $(MAKE)
+
+clean:
+ cd $(SUPPORT) && $(MAKE) clean
+ cd $(WORKER) && $(MAKE) clean
+ cd $(DRIVER) && $(MAKE) clean
+ cd $(LOGREADER) && $(MAKE) clean
+
+install:
+ cd $(WORKER) && $(MAKE) install
+ cd $(DRIVER) && $(MAKE) install
+ cd $(TOOLS) && $(MAKE) install
+ cd $(LOGREADER) && $(MAKE) install
+distclean:
+ cd $(WORKER) && $(MAKE) distclean
+ cd $(DRIVER) && $(MAKE) distclean
+dpdk:
+ export EXTRA_CFLAGS="-g -fPIC" && cd $(DPDK_ROOT) && $(MAKE) install T=$(DPDK_TARGET)
diff --git a/README b/README
new file mode 100644
index 0000000..519bf33
--- /dev/null
+++ b/README
@@ -0,0 +1,75 @@
+
+Serial-Multiprocess README VERSION 0.2.0
+===============================================================
+Changlog
+ 2014-03-18 Done.
+ 2014-05-09 Version 0.1.0
+ + Read the configure file instead of reading
+ the paras from command line.
+ + Reorganize the source structure for the MESA
+ standard.
+ + New Makefile to replace the buildso.sh
+ + Other improvement.
+ 2014-05-13 Version 0.1.1
+ + Add the test application source and header file
+ to path ./test
+ 2014-05-13 Version 0.1.2
+ + Fix some bugs in Makefile, and we don't need to
+ link a lot of libs while complete with our .so
+ file.
+ 2014-07-03 Version 0.2.0
+ + Add the module APT,which to adapt the run envoriment by itself,
+ now can support the EAL paras.
+ 2014-12-11 Version 1.1.0
+ + Support Multiprocess Mode and Complete Load-Balance Model.
+
+Author
+ Lu Qiuwen <[email protected]>
+
+Interface and Paras.
+=====================
+
+We provide two kinds of interface. One of them provide the stream id for users,and the other provide the
+port number in physical.
+
+**Note** What is a stream id?
+ As you know, the pkts from Port A to Port B which in physical can consist of a stream, we call it
+ a stream, and it have an stream id, which maybe 0.
+
+At <nl2fwd.h>
+ <1> int dpdk_send_packet_dst(unsigned char *data, int datalen, int dst);
+ Send packets made by yourself to the tx port in stream <dst>
+ <2> int dpdk_send_packet_port(const unsigned char *data, int datalen, int port);\
+ Send packets made by yourself to port <port>
+ <3> int dpdk_init(int argc, char **argv);
+ Init the Intel DPDK envoriment.
+ <4> int dpdk_run();
+ Start and run the worker and I/O thread created by Intel DPDK.
+ <5> int dpdk_register_callfunc(int (*func)(const unsigned char *data,int datalen,int port_in,int lcore));
+ Register the function handle which provided by user, and the function will be called by packet process
+ function in worker thread.
+ * You can recieve the physical port number.
+ <6> int dpdk_register_callfunc_dst(int (*func)(const unsigned char *data,int datalen,int dst,int lcore));
+ Register the function handle which provided by user, and the function will be called by packet process
+ function in worker thread.
+ * You can recieve the stream(destration) number.
+
+ Note: You cannot use dpdk_register_callfunc() and dpdk_register_callfunc_dst together.
+
+
+Complete and Install
+==============================
+ # make
+ # make install
+
+ It is so easy.
+
+Rebuild DPDK
+==============================
+ If need to rebuild DPDK libs, type:
+ # make dpdk
+ It will use -fPIC and -g symbol to rebuild DPDK libs.
+
+Link to your Application
+==============================
+ $gcc -o test test.c -lnl2fwd
diff --git a/conf/.gitignore b/conf/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/conf/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/conf/nl2fwd.conf b/conf/nl2fwd.conf
new file mode 100644
index 0000000..5b44d7f
--- /dev/null
+++ b/conf/nl2fwd.conf
@@ -0,0 +1,62 @@
+[common]
+nic_rx_ring_size=4096
+nic_tx_ring_size=4096
+ring_rx_size=65536
+ring_tx_size=65536
+burst_size_io_rx_read=1
+burst_size_io_rx_write=1
+burst_size_io_tx_read=1
+burst_size_io_tx_write=1
+burst_size_worker_read=1
+burst_size_worker_write=1
+[rx_common]
+rx_count=2
+[rx_0]
+port=1
+queue=0
+lcore=14
+[rx_1]
+port=3
+queue=0
+lcore=14
+[tx_common]
+tx_count=2
+[tx_0]
+port=1
+lcore=14
+nqueue=8
+[tx_1]
+port=3
+lcore=14
+nqueue=8
+[worker]
+lcore=0,1,2,3,4,5,6,7,8,9,10,11,12
+[map]
+n_map=2
+map_0=1,3
+map_1=3,1
+[watchdog]
+enable=1
+localip=192.168.0.198
+dev=eth7
+threshold_bypass_lostpkt=20000
+threshold_alert_lostpkt=10000
+threshold_bypass_do=10
+threshold_alert_do=10
+threshold_normal_do=10
+[stat]
+enable=1
+print=1
+sample_time=1
+[mempool]
+mempool_buffers=4194304
+#mempool_mbuf_size=
+#mempool_cache_size=4096
+[energy]
+enable=1
+min_zero_pull_count=5
+sleep_gear1_threshold=50
+sleep_gear2_threshold=500
+[virtaddr]
+enable=1
+virtaddr=0x7f40c4a00000
diff --git a/driver/.gitignore b/driver/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/driver/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/driver/Makefile b/driver/Makefile
new file mode 100644
index 0000000..2c80601
--- /dev/null
+++ b/driver/Makefile
@@ -0,0 +1,44 @@
+
+ifeq ($(MODULES_STATS),0)
+ MODULES_CFAGS += -DAPP_STAT=0
+endif
+
+TARGET = driver
+MAJOR_VERSION = 1
+SUB_VERSION = 1
+
+DPDK_INCLUDE = $(DPDK_ROOT)/$(DPDK_TARGET)/include
+DPDK_LIB_DIR = $(DPDK_ROOT)/$(DPDK_TARGET)/lib
+DPDK_LIB = $(wildcard ${DPDK_LIB_DIR}/*.a)
+DPDK_CONFIG = $(DPDK_INCLUDE)/rte_config.h
+
+DIR_INC = -I$(DPDK_INCLUDE) -I$(APP_ROOT)/include/MESA -I$(APP_ROOT)/include/serial
+DIR_SRC = ./
+DIR_OBJ = ./
+DIR_BIN = ./
+DIR_LIB = $(APP_ROOT)/lib/
+
+MODULES = -Wl,--start-group $(DPDK_LIB) -Wl,--end-group
+MODULES += $(APP_ROOT)/lib/libMESA_prof_load.a
+
+CC = gcc
+SRC = $(wildcard ${DIR_SRC}/*.c)
+OBJ = $(patsubst %.c,${DIR_OBJ}/%.o,$(notdir ${SRC}))
+LDFLAG += -lrt -lpthread
+CFLAGS += -g -fPIC ${OPTFLAGS} ${DIR_INC} -L${DIR_LIB} -std=gnu99 -include ${DPDK_CONFIG} $(MODULES_CFAGS)
+
+${TARGET}:${OBJ}
+ ${CC} ${LDFLAG} -o $@ ${OBJ} ${MODULES}
+${DIR_OBJ}/%.o:${DIR_SRC}/%.c
+ ${CC} ${CFLAGS} -c $< -o $@
+
+.PHONY:install clean
+
+all: $(TARGET)
+
+clean:
+ rm -f *.o
+install:
+ cp -f ${TARGET} ${INSTALL}
+distclean: clean
+ rm -f ${TARGET}
diff --git a/driver/apt.c b/driver/apt.c
new file mode 100644
index 0000000..55aa284
--- /dev/null
+++ b/driver/apt.c
@@ -0,0 +1,284 @@
+
+///////////////////////////////////////////////////////////////////
+/// Copyright(C) Institude of Information Engineering,CAS 2014
+///
+/// @brief 自动运行参数模块
+///
+/// 用于自动获取运行参数的模块,尽量减少用户需要配置的参数。
+///
+/// @author 陆秋文<[email protected]>
+/// @date 2014-07-03
+///
+///
+///////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include <unistd.h>
+#include <dirent.h>
+
+#include "apt.h"
+#include <MESA_prof_load.h>
+
+#ifndef STRING_MAX
+#define STRING_MAX 2048
+#endif
+
+#ifndef APP_MAX_STRING
+#define APP_MAX_STRING 4096
+#endif
+
+#define APT_PCAPDEVICE_TYPE_NONE 0
+#define APT_PCAPDEVICE_TYPE_FILE 1
+#define APT_PCAPDEVICE_TYPE_ETH 2
+#define APT_PCAPDEVICE_TYPE_FILE_RXTX_SPLIT 3
+#define APT_PCAPDEVICE_TYPE_ETH_RXTX_SPLIT 4
+
+extern const char * conf_path[];
+extern const int n_conf_path;
+
+static const char * apt_find_conffile()
+{
+ for(int i = 0; i < n_conf_path; i++)
+ if(access(conf_path[i],R_OK) == 0)
+ return conf_path[i];
+ return NULL;
+}
+
+/* 基于PCAP的虚拟设备参数配置 */
+static int apt_paras_eal_veth(int argc_max,__out__ int * argc,__out__ char * argv[])
+{
+ const char * conffile = apt_find_conffile();
+ if(conffile == NULL)
+ return -2;
+
+ int n_eth = 0;
+ MESA_load_profile_int_def(conffile,"pcap_compatibility","n_device",&n_eth,0);
+
+ if(n_eth <= 0)
+ return 0;
+
+ for(int i = 0; i < n_eth; i++)
+ {
+ char eth_section_name[APP_MAX_STRING];
+ char command_line[APP_MAX_STRING];
+
+ memset(command_line,0,APP_MAX_STRING);
+ memset(eth_section_name,0,APP_MAX_STRING);
+
+ sprintf(eth_section_name,"pcap_device_%d",i);
+ sprintf(command_line,"eth_pcap%d,",i);
+
+ char rx_pcap[APP_MAX_STRING];
+ char tx_pcap[APP_MAX_STRING];
+ char rx_iface[APP_MAX_STRING];
+ char tx_iface[APP_MAX_STRING];
+ char iface[APP_MAX_STRING];
+
+ MESA_load_profile_string_def(conffile,eth_section_name,"rx_pcap",rx_pcap,APP_MAX_STRING,"");
+ MESA_load_profile_string_def(conffile,eth_section_name,"tx_pcap",tx_pcap,APP_MAX_STRING,"");
+ MESA_load_profile_string_def(conffile,eth_section_name,"rx_iface",rx_iface,APP_MAX_STRING,"");
+ MESA_load_profile_string_def(conffile,eth_section_name,"tx_iface",tx_iface,APP_MAX_STRING,"");
+ MESA_load_profile_string_def(conffile,eth_section_name,"iface",iface,APP_MAX_STRING,"");
+
+ if(strnlen(rx_pcap,APP_MAX_STRING) != 0)
+ {
+ strncat(command_line,"rx_pcap=",APP_MAX_STRING);
+ strncat(command_line,rx_pcap,APP_MAX_STRING);
+ strncat(command_line,",",APP_MAX_STRING);
+ }
+
+ if(strnlen(tx_pcap,APP_MAX_STRING) != 0)
+ {
+ strncat(command_line,"tx_pcap=",APP_MAX_STRING);
+ strncat(command_line,tx_pcap,APP_MAX_STRING);
+ strncat(command_line,",",APP_MAX_STRING);
+ }
+
+ if(strnlen(tx_pcap,APP_MAX_STRING) != 0)
+ {
+ strncat(command_line,"rx_iface=",APP_MAX_STRING);
+ strncat(command_line,rx_iface,APP_MAX_STRING);
+ strncat(command_line,",",APP_MAX_STRING);
+ }
+
+ if(strnlen(tx_pcap,APP_MAX_STRING) != 0)
+ {
+ strncat(command_line,"tx_iface=",APP_MAX_STRING);
+ strncat(command_line,tx_iface,APP_MAX_STRING);
+ strncat(command_line,",",APP_MAX_STRING);
+ }
+
+ if(strnlen(tx_pcap,APP_MAX_STRING) != 0)
+ {
+ strncat(command_line,"iface",APP_MAX_STRING);
+ strncat(command_line,iface,APP_MAX_STRING);
+ }
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"--vdev",STRING_MAX);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],command_line,STRING_MAX);
+ }
+
+ return 0;
+}
+
+static int apt_paras_eal_ccpu(int argc_max,__out__ int * argc,__out__ char * argv[])
+{
+ const char * conffile = apt_find_conffile();
+ if(conffile == NULL)
+ return -2;
+
+ int n_arg_rx = 0;
+ uint64_t core_ret = 0;
+
+ MESA_load_profile_int_def(conffile,"rx_common","rx_count",&n_arg_rx,0);
+
+ if(n_arg_rx <= 0)
+ return -2;
+
+ for(int i = 0; i < n_arg_rx; i++)
+ {
+
+ char rx_section_name[STRING_MAX];
+ sprintf(rx_section_name,"rx_%d",i);
+
+ int lcore;
+ MESA_load_profile_int_def(conffile,rx_section_name,"lcore",&lcore,0);
+ core_ret |= 1 << lcore;
+ }
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"-c",STRING_MAX);
+
+ char core_hex[STRING_MAX];
+ sprintf(core_hex,"0x%x",(unsigned int)core_ret);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+
+ strncpy(argv[(*argc)++],core_hex,STRING_MAX);
+ return 0;
+}
+
+static int apt_paras_eal_bpci(int argc_max,__out__ int * argc,__out__ char * argv[])
+{
+ struct dirent * device_dir_p;
+ DIR * device_dir;
+
+ if((device_dir = opendir("/sys/class/net/")) == NULL)
+ return -1;
+
+
+ while((device_dir_p = readdir(device_dir)) != NULL)
+ {
+ if(strcmp(device_dir_p->d_name,".") == 0 ||
+ strcmp(device_dir_p->d_name,"..") == 0 ||
+ strcmp(device_dir_p->d_name,"lo") == 0)
+ continue;
+
+ char devsym_dir[STRING_MAX];
+ strncpy(devsym_dir,"/sys/class/net/",STRING_MAX);
+ strncat(devsym_dir,device_dir_p->d_name,STRING_MAX);
+ strncat(devsym_dir,"/device",STRING_MAX);
+
+ char devsym_info[STRING_MAX];
+ readlink(devsym_dir,devsym_info,STRING_MAX);
+
+ char devsym_pci[STRING_MAX];
+ strncpy(devsym_pci,devsym_info + 11 ,STRING_MAX);
+
+ if(strcmp(devsym_pci,"") == 0)
+ continue;
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"-b",STRING_MAX);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],devsym_pci,STRING_MAX);
+ }
+
+ closedir(device_dir);
+
+ return 0;
+}
+
+/* get the -n paras from configure file. */
+
+int apt_paras_eal_memchannals(int argc_max,__out__ int * argc,__out__ char * argv[])
+{
+ int isenable_m = 0;
+ int n_memchal = 0;
+
+ //Read it from configure file
+ for(int i = 0; i < n_conf_path; i++)
+ {
+ if(access(conf_path[i],R_OK) == 0)
+ {
+ MESA_load_profile_int_def(conf_path[i],"eal","enable_spec_memc",&(isenable_m),0);
+ MESA_load_profile_int_def(conf_path[i],"eal","n_mem_channel",&(n_memchal),0);
+ break;
+ }
+ }
+
+ if(isenable_m <= 0)
+ return 0;
+
+ char n_memchal_string[STRING_MAX];
+ sprintf(n_memchal_string,"%d",n_memchal);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"-n",STRING_MAX);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],n_memchal_string,STRING_MAX);
+
+ return 0;
+}
+
+int apt_paras_eal_virtaddr(int argc_max, __out__ int * argc, __out__ char * argv[])
+{
+ int enable = 0;
+ char virtaddr[APP_MAX_STRING];
+
+ const char * fcfg_path = apt_find_conffile();
+ MESA_load_profile_int_def(fcfg_path,"virtaddr","enable",&(enable),0);
+ MESA_load_profile_string_def(fcfg_path,"virtaddr","virtaddr",virtaddr,APP_MAX_STRING,"");
+
+ if(enable > 0)
+ {
+ strncpy(argv[(*argc)++],"--base-virtaddr",STRING_MAX);
+ strncpy(argv[(*argc)++],virtaddr,STRING_MAX);
+ }
+
+ return 0;
+}
+
+int apt_paras_eal(int argc_max,__out__ int * argc,__out__ char * argv[])
+{
+ if(apt_paras_eal_bpci(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_eal_ccpu(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_eal_memchannals(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_eal_veth(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_eal_virtaddr(argc_max,argc,argv) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/driver/apt.h b/driver/apt.h
new file mode 100644
index 0000000..bdfaf86
--- /dev/null
+++ b/driver/apt.h
@@ -0,0 +1,11 @@
+
+#ifndef __APT_INCLUDE_H__
+#define __APT_INCLUDE_H__
+
+#ifndef __out__
+#define __out__
+#endif
+
+int apt_paras_eal(int argc_max,__out__ int * argc,__out__ char * argv[]);
+
+#endif
diff --git a/driver/config.c b/driver/config.c
new file mode 100644
index 0000000..4b60997
--- /dev/null
+++ b/driver/config.c
@@ -0,0 +1,752 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_string_fns.h>
+
+#include <assert.h>
+
+#include "main.h"
+#include "MESA_prof_load.h"
+
+struct app_params app;
+const char *conf_path[] = {
+ "conf/nl2fwd.conf",
+ ".nl2fwd.conf",
+ "~/.nl2fwd.conf",
+ "/etc/nl2fwd.conf",
+ "/usr/local/etc/nl2fwd.conf"};
+
+const int n_conf_path = 5;
+
+#ifndef APP_MAX_STRING
+#define APP_MAX_STRING 4096
+#endif
+
+void app_print_usage(void)
+{
+ printf("usages\n");
+}
+
+static int app_parse_conffile_rx(char * fcfg_path)
+{
+ int n_arg_rx = 0;
+ MESA_load_profile_int_def(fcfg_path,"rx_common","rx_count",&n_arg_rx,0);
+
+ if(n_arg_rx <= 0)
+ return -1;
+
+ for(int i = 0; i < n_arg_rx; i++)
+ {
+ struct app_lcore_params *lp;
+
+ char rx_section_name[APP_MAX_STRING];
+ sprintf(rx_section_name,"rx_%d",i);
+
+ int port,queue,lcore;
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"port",&port,0);
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"queue",&queue,0);
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"lcore",&lcore,0);
+
+ /* Enable port and queue for later initialization */
+ if ((port >= APP_MAX_NIC_PORTS) || (queue >= APP_MAX_RX_QUEUES_PER_NIC_PORT)) {
+ return -3;
+ }
+ if (app.nic_rx_queue_mask[port][queue] != 0) {
+ return -4;
+ }
+ app.enabled_port_mask |= 1 << port;
+ app.nic_rx_queue_mask[port][queue] = 1;
+
+ /* Check and assign (port, queue) to I/O lcore */
+ if (rte_lcore_is_enabled(lcore) == 0) {
+ return -5;
+ }
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -6;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_WORKER) {
+ return -7;
+ }
+ lp->type = e_APP_LCORE_IO;
+ for (int j = 0; j < lp->io.rx.n_nic_queues; j++) {
+ if ((lp->io.rx.nic_queues[j].port == port) &&
+ (lp->io.rx.nic_queues[j].queue == queue)) {
+ return -8;
+ }
+ }
+ if (lp->io.rx.n_nic_queues >= APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE) {
+ return -9;
+ }
+ lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].port = (uint8_t) port;
+ lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].queue = (uint8_t) queue;
+ lp->io.rx.n_nic_queues ++;
+
+#if 0
+ int tx_port_existed = 0;
+ for(int j = 0; j < lp->io.tx.n_nic_ports; j++) {
+ if (lp->io.tx.nic_ports[j] == (uint8_t) port) {
+ tx_port_existed = 1;
+ break;
+ }
+ }
+
+ if(!tx_port_existed) {
+ lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = port;
+ lp->io.tx.n_nic_ports ++;
+ app.enabled_port_mask |= 1 << (uint8_t)port;
+ app.nic_tx_port_mask[(uint8_t)port] = 1;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+#if 0
+static int app_parse_conffile_tx(char *fcfg_path)
+{
+
+ char tx_strbuf[APP_MAX_STRING];
+ char * parse_arg = tx_strbuf;
+ int tx_enable;
+
+ MESA_load_profile_int_def(fcfg_path,"tx","tx_enable",&tx_enable,0);
+ MESA_load_profile_string_def(fcfg_path,"tx","tx_port",parse_arg,
+ sizeof(char) * APP_MAX_STRING,"");
+ if(!tx_enable)
+ return 0;
+
+ for(parse_arg = strtok(parse_arg,",");
+ parse_arg != NULL; parse_arg = strtok(NULL,","))
+ {
+ int port = 0;
+ int ret = sscanf(parse_arg,"%d",&port);
+ if(ret <= 0)
+ return -1; //Parse Error.
+ if(port > APP_MAX_NIC_PORTS|| port < 0)
+ return -2; // Wrong Port number.
+
+ //Set TX Mask and Port Mask.
+ app.enabled_port_mask |= 1 << (uint8_t)port;
+ app.nic_tx_port_mask[(uint8_t)port] = 1;
+ }
+
+ return 0;
+}
+#endif
+
+static int app_parse_conffile_tx(char * fcfg_path)
+{
+ int n_arg_tx = 0;
+ MESA_load_profile_int_def(fcfg_path,"tx_common","tx_count",&n_arg_tx,0);
+
+ if(n_arg_tx <= 0)
+ return -1;
+
+ for(int i = 0; i < n_arg_tx; i++)
+ {
+ struct app_lcore_params *lp;
+ char tx_section_name[APP_MAX_STRING];
+ sprintf(tx_section_name,"tx_%d",i);
+
+ int port,lcore,nb_queues;
+ MESA_load_profile_int_def(fcfg_path,tx_section_name,"port",&port,0);
+ MESA_load_profile_int_def(fcfg_path,tx_section_name,"lcore",&lcore,0);
+ MESA_load_profile_int_def(fcfg_path,tx_section_name,"nqueue",&nb_queues,0);
+
+ /* Enable port and queue for later initialization */
+ if (port >= APP_MAX_NIC_PORTS) {
+ return -3;
+ }
+
+ if (nb_queues <= 0 || port >= APP_MAX_TX_QUEUES_PER_NIC_PORT)
+ return -4;
+
+ if (app.nic_tx_port_mask[port] != 0) {
+ return -5;
+ }
+
+ app.nic_tx_port_mask[port] = nb_queues;
+
+ /* Check and assign (port, queue) to I/O lcore */
+ if (rte_lcore_is_enabled(lcore) == 0) {
+ return -6;
+ }
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -7;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_WORKER) {
+ return -8;
+ }
+ lp->type = e_APP_LCORE_IO;
+ for (int j = 0; j < lp->io.tx.n_nic_ports; j++) {
+ if (lp->io.tx.nic_ports[j] == port) {
+ return -9;
+ }
+ }
+ if (lp->io.tx.n_nic_ports >= APP_MAX_NIC_TX_PORTS_PER_IO_LCORE) {
+ return -10;
+ }
+ lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = (uint8_t) port;
+ lp->io.tx.nic_n_queues[lp->io.tx.n_nic_ports] = (uint8_t) nb_queues;
+ lp->io.tx.n_nic_ports ++;
+ }
+
+ return 0;
+}
+
+static int app_parse_conffile_w(char *fcfg_path)
+{
+
+ char worker_buf[APP_MAX_STRING];
+ MESA_load_profile_string_def(fcfg_path,"worker","lcore",worker_buf,
+ sizeof(char) * APP_MAX_STRING,"");
+
+ char *p = worker_buf;
+
+ while (*p != 0) {
+ struct app_lcore_params *lp;
+ uint32_t lcore;
+
+
+ errno = 0;
+ lcore = strtoul(p, NULL, 0);
+ if ((errno != 0)) {
+ return -2;
+ }
+
+ /* Check and enable worker lcore */
+#if 0
+ if (rte_lcore_is_enabled(lcore) == 0) {
+ return -3;
+ }
+#endif
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -4;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_IO) {
+ return -5;
+ }
+ lp->type = e_APP_LCORE_WORKER;
+
+ p = strchr(p, ',');
+ if (p == NULL) {
+ break;
+ }
+ p++;
+ }
+
+ return 0;
+}
+
+
+
+static int app_parse_conffile_rxtx_paras(char * fcfg_path)
+{
+ MESA_load_profile_int_def(fcfg_path,"common","nic_rx_ring_size",
+ &app.nic_rx_ring_size,APP_DEFAULT_NIC_RX_RING_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","nic_tx_ring_size",
+ &app.nic_tx_ring_size,APP_DEFAULT_NIC_TX_RING_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","ring_rx_size",
+ &app.ring_rx_size, APP_DEFAULT_RING_RX_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","ring_tx_size",
+ &app.ring_tx_size, APP_DEFAULT_RING_TX_SIZE);
+
+
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_rx_read",
+ &app.burst_size_io_rx_read,APP_DEFAULT_BURST_SIZE_IO_RX_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_rx_write",
+ &app.burst_size_io_rx_write,APP_DEFAULT_BURST_SIZE_IO_RX_WRITE);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_tx_read",
+ &app.burst_size_io_tx_read,APP_DEFAULT_BURST_SIZE_IO_TX_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_tx_write",
+ &app.burst_size_io_tx_write,APP_DEFAULT_BURST_SIZE_IO_TX_WRITE);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_worker_read",
+ &app.burst_size_worker_read,APP_DEFAULT_BURST_SIZE_WORKER_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_worker_write",
+ &app.burst_size_worker_write,APP_DEFAULT_BURST_SIZE_WORKER_WRITE);
+
+
+ return 0;
+}
+
+
+
+static int app_parse_conffile_map(char * fcfg_path)
+{
+ int rx_port,tx_port;
+ int n_record = 0;
+
+ MESA_load_profile_int_def(fcfg_path,"map","n_map",&n_record,0);
+
+ if(n_record <= 0)
+ return 0;
+
+ char map_strbuf[APP_MAX_STRING];
+
+ for(int i = 0; i < n_record; i++)
+ {
+ char map_key[APP_MAX_STRING];
+
+ char * map_strbuf_p = map_strbuf;
+ char * port_str = NULL;
+
+ sprintf(map_key,"map_%d",i);
+
+ int ret = MESA_load_profile_string_def(fcfg_path,"map",map_key,map_strbuf,
+ sizeof(char) * APP_MAX_STRING,"");
+ if(ret < 0)
+ return -1;
+
+ port_str = strtok(map_strbuf_p, ",");
+ ret = sscanf(port_str,"%d",&rx_port);
+
+ if(ret <= 0)
+ return -1;
+
+ // Add Map Record for RX Port.
+ app.rxtx_port_map[i].rx_port = rx_port;
+
+ int j = 1;
+ for(j = 1,port_str = strtok(NULL, ",");
+ port_str != NULL;
+ port_str = strtok(NULL, ","))
+ {
+ if(sscanf(port_str,"%d",&tx_port) < 0)
+ return -1;
+ if(tx_port > APP_MAX_NIC_PORTS || tx_port < 0)
+ return -1;
+ if(app.nic_tx_port_mask[tx_port] == 0)
+ return -1;
+
+ // Add Map Record for TX Report
+ app.rxtx_port_map[i].tx_port[j-1] = tx_port;
+
+ }
+ app.rxtx_port_map[i].n_tx_port = (uint32_t)j;
+ (app.n_rxtx_port_map)++;
+
+ app.rxtx_stream_record[(uint8_t)app.n_rxtx_stream].rx_port = rx_port;
+ app.rxtx_stream_record[(uint8_t)app.n_rxtx_stream].tx_port = tx_port;
+ (app.n_rxtx_stream)++;
+
+ app.map_type = e_APP_MAP_TYPE_PORTMAP;
+
+ }
+
+ assert(app.n_rxtx_port_map == n_record);
+
+ return n_record;
+}
+
+static int app_parse_conffile_stat(char *fcfg_path)
+{
+ MESA_load_profile_int_def(fcfg_path,"stat","enable",&(app.statistics.enable),1);
+ MESA_load_profile_int_def(fcfg_path,"stat","print", &(app.statistics.is_printmsg),1);
+ MESA_load_profile_int_def(fcfg_path,"stat","sample_time", &(app.statistics.sample_time),1);
+
+ if(app.watchdog_paras.enable)
+ app.statistics.enable = 1;
+
+ return 0;
+}
+
+
+static int app_parse_conffile_mempool(char *fcfg_path)
+{
+
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_buffers",
+ &(app.mempool.mempool_buffers),APP_DEFAULT_MEMPOOL_BUFFERS);
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_mbuf_size",
+ &(app.mempool.mempool_mbuf_size),APP_DEFAULT_MBUF_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_cache_size",
+ &(app.mempool.mempool_cache_size),APP_DEFAULT_MEMPOOL_CACHE_SIZE);
+
+ return 0;
+}
+
+
+int app_parse_args(int argc, char **argv)
+{
+
+
+ app.enabled_port_mask = 0;
+ app.key_type = KEY_TYPE_IS_IP;
+
+ for(int i = 0; i < n_conf_path ; i++)
+ {
+ if(access(conf_path[i],R_OK) == 0) {
+
+ char * path = (char *)conf_path[i];
+
+ if(app_parse_conffile_rx(path) < 0)
+ return -1;
+ if(app_parse_conffile_tx(path) < 0)
+ return -2;
+ if(app_parse_conffile_w(path) < 0)
+ return -3;
+ if(app_parse_conffile_rxtx_paras(path) < 0)
+ return -4;
+ if(app_parse_conffile_stat(path) < 0)
+ return -5;
+ if(app_parse_conffile_map(path) < 0)
+ return -6;
+ if(app_parse_conffile_mempool(path) < 0)
+ return -7;
+ return 0;
+ }
+ }
+ return -9;
+}
+
+int
+app_get_nic_rx_queues_per_port(uint8_t port)
+{
+ uint32_t i, count;
+
+ if (port >= APP_MAX_NIC_PORTS) {
+ return -1;
+ }
+
+ count = 0;
+ for (i = 0; i < APP_MAX_RX_QUEUES_PER_NIC_PORT; i ++) {
+ if (app.nic_rx_queue_mask[port][i] == 1) {
+ count ++;
+ }
+ }
+
+ return count;
+}
+
+int
+app_get_lcore_for_nic_rx(uint8_t port, uint8_t queue, uint32_t *lcore_out)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t i;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_IO) {
+ continue;
+ }
+
+ for (i = 0; i < lp->rx.n_nic_queues; i ++) {
+ if ((lp->rx.nic_queues[i].port == port) &&
+ (lp->rx.nic_queues[i].queue == queue)) {
+ *lcore_out = lcore;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+app_get_lcore_for_nic_tx(uint8_t port, uint32_t *lcore_out)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t i;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_IO) {
+ continue;
+ }
+
+ for (i = 0; i < lp->tx.n_nic_ports; i ++) {
+ if (lp->tx.nic_ports[i] == port) {
+ *lcore_out = lcore;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+app_is_socket_used(uint32_t socket)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) {
+ continue;
+ }
+
+ if (socket == rte_lcore_to_socket_id(lcore)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+uint32_t
+app_get_lcores_io_rx(void)
+{
+ uint32_t lcore, count;
+
+ count = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->rx.n_nic_queues == 0)) {
+ continue;
+ }
+ count ++;
+ }
+ return count;
+}
+
+uint32_t
+app_get_lcores_worker(void)
+{
+ uint32_t lcore, count;
+
+ count = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ count ++;
+ }
+
+ if (count > APP_MAX_WORKER_LCORES) {
+ rte_panic("Algorithmic error (too many worker lcores)\n");
+ return 0;
+ }
+
+ return count;
+}
+
+void
+app_print_params(void)
+{
+ unsigned port, queue, lcore, i, j;
+
+ /* Print NIC RX configuration */
+ printf("NIC RX ports: ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ uint32_t n_rx_queues = app_get_nic_rx_queues_per_port((uint8_t) port);
+
+ if (n_rx_queues == 0) {
+ continue;
+ }
+
+ printf("%u (", port);
+ for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) {
+ if (app.nic_rx_queue_mask[port][queue] == 1) {
+ printf("%u ", queue);
+ }
+ }
+ printf(") ");
+ }
+ printf(";\n");
+
+ /* Print I/O lcore RX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp->rx.n_nic_queues == 0)) {
+ continue;
+ }
+
+ printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore));
+
+ printf("RX ports ");
+ for (i = 0; i < lp->rx.n_nic_queues; i ++) {
+ printf("(%u, %u) ",
+ (unsigned) lp->rx.nic_queues[i].port,
+ (unsigned) lp->rx.nic_queues[i].queue);
+ }
+ printf("; ");
+
+ printf("Output rings ");
+ for (i = 0; i < lp->rx.n_rings; i ++) {
+ printf("%p ", lp->rx.rings[i]);
+ }
+ printf(";\n");
+ }
+
+ /* Print worker lcore RX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Worker lcore %u (socket %u) ID %u: ",
+ lcore,
+ rte_lcore_to_socket_id(lcore),
+ (unsigned)lp->worker_id);
+
+ printf("Input rings ");
+ for (i = 0; i < lp->n_rings_in; i ++) {
+ printf("%p ", lp->rings_in[i]);
+ }
+
+ printf(";\n");
+ }
+
+ printf("\n");
+
+ /* Print NIC TX configuration */
+ printf("NIC TX ports: ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ if (app.nic_tx_port_mask[port] == 1) {
+ printf("%u ", port);
+ }
+ }
+ printf(";\n");
+
+ /* Print I/O TX lcore params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t n_workers = app_get_lcores_worker();
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp->tx.n_nic_ports == 0)) {
+ continue;
+ }
+
+ printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore));
+
+ printf("Input rings per TX port ");
+ for (i = 0; i < lp->tx.n_nic_ports; i ++) {
+ port = lp->tx.nic_ports[i];
+
+ printf("%u (", port);
+ for (j = 0; j < n_workers; j ++) {
+ printf("%p ", lp->tx.rings[port][j]);
+ }
+ printf(") ");
+
+ }
+
+ printf(";\n");
+ }
+
+ /* Print worker lcore TX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Worker lcore %u (socket %u) ID %u: \n",
+ lcore,
+ rte_lcore_to_socket_id(lcore),
+ (unsigned)lp->worker_id);
+
+ printf("Output rings per TX port ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ if (lp->rings_out[port] != NULL) {
+ printf("%u (%p) ", port, lp->rings_out[port]);
+ }
+ }
+
+ printf(";\n");
+ }
+
+ /* Rings */
+ printf("Ring sizes: NIC RX = %u; Worker in = %u; Worker out = %u; NIC TX = %u;\n",
+ (unsigned) app.nic_rx_ring_size,
+ (unsigned) app.ring_rx_size,
+ (unsigned) app.ring_tx_size,
+ (unsigned) app.nic_tx_ring_size);
+
+ /* Bursts */
+ printf("Burst sizes: I/O RX (rd = %u, wr = %u); Worker (rd = %u, wr = %u); I/O TX (rd = %u, wr = %u)\n",
+ (unsigned) app.burst_size_io_rx_read,
+ (unsigned) app.burst_size_io_rx_write,
+ (unsigned) app.burst_size_worker_read,
+ (unsigned) app.burst_size_worker_write,
+ (unsigned) app.burst_size_io_tx_read,
+ (unsigned) app.burst_size_io_tx_write);
+}
diff --git a/driver/init.c b/driver/init.c
new file mode 100644
index 0000000..51df8d2
--- /dev/null
+++ b/driver/init.c
@@ -0,0 +1,598 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_string_fns.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_version.h>
+
+#include "main.h"
+#include "nstat.h"
+
+static struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .split_hdr_size = 0,
+ .header_split = 0, /**< Header Split disabled */
+ .hw_ip_checksum = 0, /**< IP checksum offload enabled */
+ .hw_vlan_filter = 0, /**< VLAN filtering disabled */
+ .hw_vlan_strip = 0,
+ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */
+ .hw_strip_crc = 0, /**< CRC stripped by hardware */
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6,
+ },
+ },
+ .txmode = {
+ //.mq_mode = ETH_MQ_TX_NONE,
+ .mq_mode = ETH_DCB_NONE,
+ },
+};
+
+static struct rte_eth_rxconf rx_conf = {
+ .rx_thresh = {
+ .pthresh = APP_DEFAULT_NIC_RX_PTHRESH,
+ .hthresh = APP_DEFAULT_NIC_RX_HTHRESH,
+ .wthresh = APP_DEFAULT_NIC_RX_WTHRESH,
+ },
+ .rx_free_thresh = APP_DEFAULT_NIC_RX_FREE_THRESH,
+ .rx_drop_en = APP_DEFAULT_NIC_RX_DROP_EN,
+};
+
+static struct rte_eth_txconf tx_conf = {
+ .tx_thresh = {
+ .pthresh = APP_DEFAULT_NIC_TX_PTHRESH,
+ .hthresh = APP_DEFAULT_NIC_TX_HTHRESH,
+ .wthresh = APP_DEFAULT_NIC_TX_WTHRESH,
+ },
+ .tx_free_thresh = APP_DEFAULT_NIC_TX_FREE_THRESH,
+ .tx_rs_thresh = APP_DEFAULT_NIC_TX_RS_THRESH,
+};
+
+static int
+app_get_worker_core_number(void)
+{
+ unsigned lcore;
+ int count = 0;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+ count++;
+ }
+ return count;
+}
+
+static void
+app_assign_worker_ids(void)
+{
+ uint32_t lcore, worker_id;
+
+ /* Assign ID for each worker */
+ worker_id = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ lp_worker->worker_id = worker_id;
+ worker_id ++;
+ }
+}
+
+static void
+app_init_mbuf_pools(void)
+{
+ unsigned socket, lcore;
+
+ /* Init the buffer pools */
+ for (socket = 0; socket < APP_MAX_SOCKETS; socket ++) {
+ char name[32];
+ if (app_is_socket_used(socket) == 0) {
+ continue;
+ }
+
+ snprintf(name, sizeof(name), "mbuf_pool_%u", socket);
+ printf("Creating the mbuf pool for socket %u ...\n", socket);
+
+#if 0
+ app.pools[socket] = rte_mempool_create(
+ name,
+ APP_DEFAULT_MEMPOOL_BUFFERS,
+ APP_DEFAULT_MBUF_SIZE,
+ APP_DEFAULT_MEMPOOL_CACHE_SIZE,
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ rte_pktmbuf_init, NULL,
+ socket,
+ 0);
+#endif
+ app.pools[socket] = rte_mempool_create(
+ name,
+ app.mempool.mempool_buffers,
+ app.mempool.mempool_mbuf_size,
+ app.mempool.mempool_cache_size,
+ sizeof(struct rte_pktmbuf_pool_private),
+ rte_pktmbuf_pool_init, NULL,
+ rte_pktmbuf_init, NULL,
+ socket,
+ 0);
+ if (app.pools[socket] == NULL) {
+ rte_panic("Cannot create mbuf pool on socket %u\n", socket);
+ }
+ }
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) {
+ continue;
+ }
+
+ socket = rte_lcore_to_socket_id(lcore);
+ app.lcore_params[lcore].pool = app.pools[socket];
+ }
+}
+
+
+static void
+app_init_rings_rx(void)
+{
+ unsigned lcore;
+
+ /* Initialize the rings for the RX side */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+ unsigned socket_io, lcore_worker;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->rx.n_nic_queues == 0)) {
+ continue;
+ }
+
+ socket_io = rte_lcore_to_socket_id(lcore);
+
+ for (lcore_worker = 0; lcore_worker < APP_MAX_LCORES; lcore_worker ++) {
+ char name[32];
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore_worker].worker;
+ struct rte_ring *ring = NULL;
+
+ if (app.lcore_params[lcore_worker].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Creating ring to connect I/O lcore %u (socket %u) with worker lcore %u ...\n",
+ lcore,
+ socket_io,
+ lcore_worker);
+ snprintf(name, sizeof(name), "app_ring_rx_io%u_w%u",
+ lcore,
+ lcore_worker);
+ ring = rte_ring_create(
+ name,
+ app.ring_rx_size,
+ socket_io,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (ring == NULL) {
+ rte_panic("Cannot create ring to connect I/O core %u with worker core %u\n",
+ lcore,
+ lcore_worker);
+ }
+
+ lp_io->rx.rings[lp_io->rx.n_rings] = ring;
+ lp_io->rx.n_rings ++;
+
+ lp_worker->rings_in[lp_worker->n_rings_in] = ring;
+ lp_worker->n_rings_in ++;
+ }
+ }
+
+
+#if 0
+ /* Init the rings for the TX side */
+ /* Add by Lu Qiuwen <[email protected]> at 2014-12-04 */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker;
+ unsigned socket_io, port;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ if (lp_worker->n_rings_in != app_get_lcores_io_rx()) {
+ rte_panic("Algorithmic error (worker input rings)\n");
+ }
+
+ socket_io = rte_lcore_to_socket_id(lcore);
+ for (port = 0; port < APP_MAX_NIC_PORTS; port++) {
+ char name[32];
+ struct rte_ring * ring = NULL;
+
+ if(app.nic_tx_port_mask[port] != 1)
+ continue;
+
+ printf("Creating ring to connect NIC %u (socket %u) in worker lcore %u ... \n",
+ port,
+ socket_io,
+ lcore);
+ rte_snprintf(name, sizeof(name), "app_ring_tx_s%u_p%u_w_%u",
+ socket_io,
+ port,
+ lcore);
+ ring = rte_ring_create(
+ name,
+ app.ring_tx_size,
+ socket_io,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (ring == NULL) {
+ rte_panic("Cannot create ring NIC %u in worker lcore %u\n",
+ port,
+ lcore);
+ }
+
+ lp_worker->rings_out[port] = ring;
+ }
+ }
+
+ /* Connect I/O TX to working tx rings, by Lu Qiuwen at 2014-12-04 */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+ unsigned lcore_worker, port_id;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->rx.n_nic_queues == 0)) {
+ continue;
+ }
+
+ for(lcore_worker = 0; lcore < APP_MAX_LCORES; lcore++) {
+ struct app_lcore_params_worker * lp_worker = &app.lcore_params[lcore].worker;
+ struct rte_ring * ring = NULL;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ for(int i = 0; i < lp_io->tx.n_nic_ports; i++) {
+ port_id = lp_io->tx.nic_ports[i];
+ ring = lp_worker->rings_out[port_id];
+
+ lp_io->tx.rings[port_id][lcore_worker] = ring;
+
+ printf("Link rings between worker %u(port %u) with I/O core %u\n",
+ lcore_worker,
+ port_id,
+ lcore);
+ }
+ }
+ }
+#endif
+}
+
+static void
+app_init_rings_tx(void)
+{
+ unsigned lcore;
+
+ /* Initialize the rings for the TX side */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker;
+ unsigned port;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ char name[32];
+ struct app_lcore_params_io *lp_io = NULL;
+ struct rte_ring *ring;
+ uint32_t socket_io, lcore_io;
+
+ if (app.nic_tx_port_mask[port] == 0) {
+ continue;
+ }
+
+ if (app_get_lcore_for_nic_tx((uint8_t) port, &lcore_io) < 0) {
+ rte_panic("Algorithmic error (no I/O core to handle TX of port %u)\n",
+ port);
+ }
+
+ lp_io = &app.lcore_params[lcore_io].io;
+ socket_io = rte_lcore_to_socket_id(lcore_io);
+
+ printf("Creating ring to connect worker lcore %u with TX port %u (through I/O lcore %u) (socket %u) ...\n",
+ lcore, port, (unsigned)lcore_io, (unsigned)socket_io);
+ snprintf(name, sizeof(name), "app_ring_tx_w%u_p%u", lcore, port);
+ printf("%s\n",name);
+
+ ring = rte_ring_create(
+ name,
+ app.ring_tx_size,
+ socket_io,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (ring == NULL) {
+ rte_panic("Cannot create ring to connect worker core %u with TX port %u\n",
+ lcore,
+ port);
+ }
+
+ lp_worker->rings_out[port] = ring;
+ lp_io->tx.rings[port][lp_worker->worker_id] = ring;
+ }
+ }
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+ unsigned i;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->tx.n_nic_ports == 0)) {
+ continue;
+ }
+
+ for (i = 0; i < lp_io->tx.n_nic_ports; i ++){
+ unsigned port, j;
+
+ port = lp_io->tx.nic_ports[i];
+ for (j = 0; j < app_get_lcores_worker(); j ++) {
+ if (lp_io->tx.rings[port][j] == NULL) {
+ rte_panic("Algorithmic error (I/O TX rings)\n");
+ }
+ }
+ }
+ }
+}
+
+
+
+
+/* Check the link status of all ports in up to 9s, and print them finally */
+static void
+check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
+{
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
+ uint8_t portid, count, all_ports_up, print_flag = 0;
+ struct rte_eth_link link;
+ uint32_t n_rx_queues, n_tx_queues;
+
+ printf("\nChecking link status");
+ fflush(stdout);
+ for (count = 0; count <= MAX_CHECK_TIME; count++) {
+ all_ports_up = 1;
+ for (portid = 0; portid < port_num; portid++) {
+ if ((port_mask & (1 << portid)) == 0)
+ continue;
+ n_rx_queues = app_get_nic_rx_queues_per_port(portid);
+ n_tx_queues = app.nic_tx_port_mask[portid];
+ if ((n_rx_queues == 0) && (n_tx_queues == 0))
+ continue;
+ memset(&link, 0, sizeof(link));
+ rte_eth_link_get_nowait(portid, &link);
+ /* print link status if flag set */
+ if (print_flag == 1) {
+ if (link.link_status)
+ printf("Port %d Link Up - speed %u "
+ "Mbps - %s\n", (uint8_t)portid,
+ (unsigned)link.link_speed,
+ (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ ("full-duplex") : ("half-duplex\n"));
+ else
+ printf("Port %d Link Down\n",
+ (uint8_t)portid);
+ continue;
+ }
+ /* clear all_ports_up flag if any link down */
+ if (link.link_status == 0) {
+ all_ports_up = 0;
+ break;
+ }
+ }
+ /* after finally printing all link status, get out */
+ if (print_flag == 1)
+ break;
+
+ if (all_ports_up == 0) {
+ printf(".");
+ fflush(stdout);
+ rte_delay_ms(CHECK_INTERVAL);
+ }
+
+ /* set the print_flag if all ports up or timeout */
+ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
+ print_flag = 1;
+ printf("done\n");
+ }
+ }
+}
+
+static void
+app_init_nics(void)
+{
+ unsigned socket;
+ uint32_t lcore;
+ uint8_t port, queue;
+ int ret;
+ uint32_t n_rx_queues, n_tx_queues;
+
+ /* Init driver */
+ printf("Initializing the PMD driver ...\n");
+
+#if RTE_VER_MAJOR >=1 && RTE_VER_MINOR <= 6
+ if (rte_pmd_init_all() < 0) {
+ rte_panic("Cannot init PMD\n");
+ }
+#endif
+
+ if (rte_eal_pci_probe() < 0) {
+ rte_panic("Cannot probe PCI\n");
+ }
+
+ app.worker_core_num = app_get_worker_core_number();
+
+ /* Init NIC ports and queues, then start the ports */
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ struct rte_mempool *pool;
+
+ n_rx_queues = app_get_nic_rx_queues_per_port(port);
+ n_tx_queues = app.nic_tx_port_mask[port];
+
+ if ((n_rx_queues == 0) && (n_tx_queues == 0)) {
+ continue;
+ }
+
+ /* Init port */
+ printf("Initializing NIC port %u ...\n", (unsigned) port);
+ ret = rte_eth_dev_configure(
+ port,
+ (uint8_t) n_rx_queues,
+ (uint8_t) n_tx_queues,
+ &port_conf);
+ if (ret < 0) {
+ rte_panic("Cannot init NIC port %u (%d)\n", (unsigned) port, ret);
+ }
+ rte_eth_promiscuous_enable(port);
+
+ /* Init RX queues */
+ for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) {
+ if (app.nic_rx_queue_mask[port][queue] == 0) {
+ continue;
+ }
+
+ app_get_lcore_for_nic_rx(port, queue, &lcore);
+ socket = rte_lcore_to_socket_id(lcore);
+ pool = app.lcore_params[lcore].pool;
+
+ printf("Initializing NIC port %u RX queue %u ...\n",
+ (unsigned) port,
+ (unsigned) queue);
+ ret = rte_eth_rx_queue_setup(
+ port,
+ queue,
+ (uint16_t) app.nic_rx_ring_size,
+ socket,
+ &rx_conf,
+ pool);
+ if (ret < 0) {
+ rte_panic("Cannot init RX queue %u for port %u (%d)\n",
+ (unsigned) queue,
+ (unsigned) port,
+ ret);
+ }
+ }
+
+ /* Init TX queues */
+ //RSYS if (app.nic_tx_port_mask[port] == 1) {
+ for (queue = 0; queue < n_tx_queues; queue ++) {
+ app_get_lcore_for_nic_tx(port, &lcore);
+ socket = rte_lcore_to_socket_id(lcore);
+ printf("Initializing NIC port %u TX queue %u ...\n",
+ (unsigned) port, (unsigned) queue);
+ ret = rte_eth_tx_queue_setup(
+ port,
+ queue, //0,
+ (uint16_t) app.nic_tx_ring_size,
+ socket,
+ &tx_conf);
+ if (ret < 0) {
+ rte_panic("Cannot init TX queue %u for port %d (%d)\n",
+ queue,
+ port,
+ ret);
+ }
+ }
+
+ /* Start port */
+ ret = rte_eth_dev_start(port);
+ if (ret < 0) {
+ rte_panic("Cannot start port %d (%d)\n", port, ret);
+ }
+ }
+
+ check_all_ports_link_status(APP_MAX_NIC_PORTS, (~0x0));
+}
+
+
+void
+app_init(void)
+{
+ app_assign_worker_ids();
+ app_init_mbuf_pools();
+ app_init_rings_rx();
+ app_init_rings_tx();
+ app_init_nics();
+
+ nstat_init();
+ printf("Initialization completed.\n");
+}
diff --git a/driver/layer.c b/driver/layer.c
new file mode 100644
index 0000000..0e3a219
--- /dev/null
+++ b/driver/layer.c
@@ -0,0 +1,267 @@
+/* Network Layer Jumper Functions
+ *
+ * Author : Lu Qiuwen <[email protected]>
+ * Date : 2014-12-19
+ * Last : 2014-12-19
+ *
+ * The code is ported from SAPP Platform <dealpkt/net_common.c, sapp_20141219>
+ * writted by Li Jia.
+ *
+ * Changelog.
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "layer.h"
+
+#include <linux/if_ether.h>
+#include <net/if_arp.h>
+#include <netinet/ip6.h>
+#include <netinet/ip.h>
+#include <netinet/in.h>
+
+#define PPPOE_TYPE_IPV4 0x0021
+#define PPPOE_TYPE_IPV6 0x0057
+
+static int eth_jump_to_layer(int skip_len,const char *raw_data, int raw_layer_type, int expect_layer_type);
+static int vlan8021q_jump_to_layer(int skip_len,const char *raw_data, int raw_layer_type, int expect_layer_type);
+static int pppoe_jump_to_layer(int skip_len,const char *raw_data, int raw_layer_type, int expect_layer_type);
+static int __common_eth_type_dispatch(int skip_len, uint16_t eth_type, const char *next_layer_data, int raw_layer_type, int expect_layer_type);
+static int __common_pppoe_type_dispatch(int skip_len, uint16_t eth_type, const char * next_layer_data, int raw_layer_type, int expect_layer_type);
+
+static inline int check_layer_type(int layer_type)
+{
+ switch(layer_type){
+ case ADDR_TYPE_IPV4:
+ case ADDR_TYPE_IPV6:
+ case ADDR_TYPE_VLAN:
+ case ADDR_TYPE_MAC:
+ case ADDR_TYPE_ARP:
+ case ADDR_TYPE_GRE:
+ case ADDR_TYPE_MPLS:
+ case ADDR_TYPE_PPPOE_SES:
+ case ADDR_TYPE_TCP:
+ case ADDR_TYPE_UDP:
+ case ADDR_TYPE_L2TP:
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int arp_jump_to_layer(int skip_len,const char * raw_data, int raw_layer_type, int except_layer_type)
+{
+ /* arp协议不承载任何上层其他协议 */
+ return -1;
+}
+
+
+static int ipv4_jump_to_layer(int skip_len,const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ struct ip *p_ip_hdr = (struct ip *)raw_data;
+ int ip_hdr_len = p_ip_hdr->ip_hl * 4;
+ //const char *next_layer_data = raw_data + ip_hdr_len;
+
+ switch(p_ip_hdr->ip_p){
+ case IPPROTO_TCP:
+ if(ADDR_TYPE_TCP == expect_layer_type){
+ skip_len += ip_hdr_len;
+ }else{
+ skip_len = -1; /* tcp 层之上不承载其他协议 */
+ }
+ break;
+
+ case IPPROTO_UDP:
+ if(ADDR_TYPE_UDP == expect_layer_type){
+ skip_len += ip_hdr_len;
+ }else{
+ skip_len = -1; /* tcp 层之上不承载其他协议, teredo隧道模式不支持此类跳转 */
+ }
+ break;
+
+ default:
+ skip_len = -1;
+ break;
+ }
+
+ if(skip_len < 0){
+ return -1;
+ }
+
+ return skip_len;
+}
+
+static int ipv6_jump_to_layer(int skip_len,const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ // to do !!!
+ return -1;
+}
+
+static int pppoe_ses_jump_to_layer(int skip_len,const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ uint16_t * eth_type = (uint16_t *) raw_data + 3;
+ skip_len += 8;
+
+ return __common_pppoe_type_dispatch(skip_len,ntohs(*eth_type), raw_data + 8, raw_layer_type, expect_layer_type);
+}
+
+/* PPPoE层协议跳转 */
+static int __common_pppoe_type_dispatch(int skip_len, uint16_t eth_type, const char * next_layer_data, int raw_layer_type, int expect_layer_type)
+{
+ switch(eth_type)
+ {
+ case PPPOE_TYPE_IPV4:
+ if(ADDR_TYPE_IPV4 != expect_layer_type){
+ skip_len = ipv4_jump_to_layer(skip_len,next_layer_data, ADDR_TYPE_IPV4, expect_layer_type);
+ }
+ break;
+
+ case PPPOE_TYPE_IPV6:
+ if(ADDR_TYPE_IPV6 != expect_layer_type){
+ skip_len = ipv6_jump_to_layer(skip_len,next_layer_data, ADDR_TYPE_IPV6, expect_layer_type);
+ }
+ break;
+
+ default:
+ skip_len = -1;
+ break;
+ }
+
+ return skip_len;
+}
+
+/* 以太网、VLAN层跳转 */
+static int __common_eth_type_dispatch(int skip_len, uint16_t eth_type, const char *next_layer_data, int raw_layer_type, int expect_layer_type)
+{
+ switch(eth_type){
+ case ETH_P_ARP:
+ if(ADDR_TYPE_ARP != expect_layer_type){
+ skip_len = arp_jump_to_layer(skip_len,next_layer_data, ADDR_TYPE_ARP, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_8021Q:
+ if(ADDR_TYPE_VLAN != expect_layer_type){
+ skip_len = vlan8021q_jump_to_layer(skip_len,next_layer_data, ADDR_TYPE_VLAN, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_IP:
+ if(ADDR_TYPE_IPV4 != expect_layer_type){
+ skip_len = ipv4_jump_to_layer(skip_len,next_layer_data, ADDR_TYPE_IPV4, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_IPV6:
+ if(ADDR_TYPE_IPV6 != expect_layer_type){
+ skip_len = ipv6_jump_to_layer(skip_len,next_layer_data, ADDR_TYPE_IPV6, expect_layer_type);
+ }
+ break;
+
+ case ETH_P_PPP_SES:
+ if(ADDR_TYPE_PPPOE_SES != expect_layer_type){
+ skip_len = pppoe_ses_jump_to_layer(skip_len,next_layer_data, ADDR_TYPE_PPPOE_SES, expect_layer_type);
+ }
+ break;
+
+ default:
+ skip_len = -1;
+ break;
+ }
+
+ return skip_len;
+}
+
+static int vlan8021q_jump_to_layer(int skip_len, const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ uint16_t * eth_type = (uint16_t *) raw_data + 1;
+ skip_len += 4;
+
+ return __common_eth_type_dispatch(skip_len,ntohs(*eth_type), raw_data + 4, raw_layer_type, expect_layer_type);
+}
+
+static int eth_jump_to_layer(int skip_len, const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ struct ethhdr *p_eth_hdr = (struct ethhdr *)raw_data;
+ unsigned short eth_type = ntohs(p_eth_hdr->h_proto);
+ skip_len += sizeof(struct ethhdr);
+ const char *next_layer_data = raw_data + sizeof(struct ethhdr);
+
+ return __common_eth_type_dispatch(skip_len, eth_type, next_layer_data, raw_layer_type, expect_layer_type);
+}
+
+const void * network_data_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type)
+{
+ int ret = 0;
+
+ if(check_layer_type(raw_layer_type) < 0){
+ return NULL;
+ }
+
+ if(check_layer_type(expect_layer_type) < 0){
+ return NULL;
+ }
+
+ switch(raw_layer_type){
+ case ADDR_TYPE_MAC:
+ ret = eth_jump_to_layer(ret,raw_data, raw_layer_type, expect_layer_type);
+ break;
+
+ case ADDR_TYPE_ARP:
+ ret = arp_jump_to_layer(ret,raw_data, raw_layer_type, expect_layer_type);
+ break;
+ case ADDR_TYPE_VLAN:
+ ret = vlan8021q_jump_to_layer(ret,raw_data, raw_layer_type, expect_layer_type);
+ break;
+ case ADDR_TYPE_PPPOE_SES:
+ case ADDR_TYPE_MPLS:
+ case ADDR_TYPE_IPV4:
+ ret = ipv4_jump_to_layer(ret,raw_data, raw_layer_type, expect_layer_type);
+ break;
+ case ADDR_TYPE_IPV6:
+ case ADDR_TYPE_GRE:
+ /* to do */
+ break;
+
+ default:
+ return NULL;
+ }
+
+ if(ret < 0)
+ return NULL;
+
+ return (raw_data + ret);
+}
+
+const void * network_data_jump_to_layer_ip(const char * data, uint16_t * layer_type)
+{
+ void * dataret_ipv4 = NULL;
+ void * dataret_ipv6 = NULL;
+
+ dataret_ipv4 = network_data_jump_to_layer(data,ADDR_TYPE_MAC,ADDR_TYPE_IPV4);
+
+ if(dataret_ipv4 != NULL)
+ {
+ * layer_type = ADDR_TYPE_IPV4;
+ return dataret_ipv4;
+ }
+
+ dataret_ipv6 = network_data_jump_to_layer(data,ADDR_TYPE_MAC,ADDR_TYPE_IPV6);
+
+ if(dataret_ipv6 != NULL)
+ {
+ * layer_type = ADDR_TYPE_IPV6;
+ return dataret_ipv6;
+ }
+
+ return NULL;
+}
+
+
+
diff --git a/driver/layer.h b/driver/layer.h
new file mode 100644
index 0000000..67f96ab
--- /dev/null
+++ b/driver/layer.h
@@ -0,0 +1,39 @@
+/* Network Layer Jumper Functions
+ *
+ * Author : Lu Qiuwen <[email protected]>
+ * Date : 2014-12-19
+ * Last : 2014-12-19
+ *
+ * Changelog.
+ *
+ */
+
+#ifndef __SERIAL_MULTIPROCESS_LAYER_JMP_INCLUDE_H__
+#define __SERIAL_MULTIPROCESS_LAYER_JMP_INCLUDE_H__
+
+#include <stdint.h>
+
+
+//地址类型定义
+enum addr_type_t{
+ __ADDR_TYPE_INIT = 0,
+ ADDR_TYPE_IPV4, /* 1 */
+ ADDR_TYPE_IPV6, /* 2 */
+ ADDR_TYPE_VLAN, /* 3 */
+ ADDR_TYPE_MAC, /* 4 */
+ ADDR_TYPE_ARP, /* 5 */
+ ADDR_TYPE_GRE, /* 6 */
+ ADDR_TYPE_MPLS, /* 7 */
+ ADDR_TYPE_PPPOE_SES, /* 8 */
+ ADDR_TYPE_TCP, /* 9 */
+ ADDR_TYPE_UDP, /* 10 */
+ ADDR_TYPE_L2TP, /* 11 */
+ ADDR_TYPE_STREAM_TUPLE4_V4, /* 12, 混合地址类型, 基于IPv4地址的四元组信息 */
+ ADDR_TYPE_STREAM_TUPLE4_V6, /* 13, 混合地址类型, 基于IPv6地址的四元组信息 */
+ __ADDR_TYPE_MAX, /* 14 */
+};
+
+const void * network_data_jump_to_layer(const char *raw_data, int raw_layer_type, int expect_layer_type);
+const void * network_data_jump_to_layer_ip(const char * data, uint16_t * layer_type);
+
+#endif
diff --git a/driver/main.c b/driver/main.c
new file mode 100644
index 0000000..34bffb4
--- /dev/null
+++ b/driver/main.c
@@ -0,0 +1,228 @@
+
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_memcpy.h>
+
+#include "nl2fwd.h"
+#include "main.h"
+#include "apt.h"
+#include "nstat.h"
+
+
+FILE *warn_output_stream = NULL;
+FILE *err_output_stream = NULL;
+
+#if 0
+static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp)
+{
+ struct rte_mbuf *m;
+ m = __rte_mbuf_raw_alloc(mp);
+ __rte_mbuf_sanity_check_raw(m,RTE_MBUF_PKT,0);
+
+ return (m);
+}
+
+int dpdk_register_callfunc(int (*func)(const unsigned char *data,int datalen,int port_in,int lcore))
+{
+ app.pkt_callback_f.rx_pkt_process = func;
+ app.pkt_callback_f.rx_pkt_process_dst = NULL;
+ return 0;
+}
+
+int dpdk_register_callfunc_dst(int (*func)(const unsigned char *data,int datalen,int dst,int lcore))
+{
+ app.pkt_callback_f.rx_pkt_process_dst = func;
+ app.pkt_callback_f.rx_pkt_process = NULL;
+ return 0;
+}
+
+int dpdk_send_packet_dst(unsigned char *data, int datalen, int dst)
+{
+ if(dst <0 || dst >= (int)app.n_rxtx_stream)
+ return -1;
+ uint32_t port = app.rxtx_stream_record[dst].tx_port;
+
+ return dpdk_send_packet_port(data,datalen,port);
+}
+
+int app_lcore_worker_tx_buffer_to_send (struct rte_mbuf *pkt, uint8_t port);
+#endif
+#if 0
+int dpdk_send_packet_port(const unsigned char *data, int datalen, int port)
+{
+ struct rte_mbuf * pkt_burst = NULL;
+
+ int lcore_id = rte_lcore_id();
+
+ if(data == NULL) {
+ fprintf(warn_output_stream,"WARNING(core_id=%d,datalen=%d): Invalid TX packet info, ignore the pkt.\n",
+ lcore_id,datalen);
+ return -1;
+ }
+
+ pkt_burst = rte_rxmbuf_alloc(app.lcore_params[lcore_id].pool);
+
+ if(pkt_burst == NULL) {
+ fprintf(warn_output_stream,"WARNING(core_id=%d),Alloc mbuf failed,ignore the pkt\n",
+ lcore_id);
+ return -1;
+ }
+
+ pkt_burst->pkt.nb_segs = 1;
+ pkt_burst->pkt.next = NULL;
+ pkt_burst->pkt.in_port = port;
+ pkt_burst->pkt.pkt_len = datalen;
+ pkt_burst->pkt.data_len = datalen;
+
+ rte_memcpy(pkt_burst->pkt.data, data, datalen);
+ pkt_burst->ol_flags |= PKT_TX_IP_CKSUM;
+
+ app_lcore_worker_tx_buffer_to_send(pkt_burst,port);
+
+ return 0;
+}
+#endif
+
+void sigint_handler(int signo)
+{
+ uint8_t portid;
+ uint8_t nb_ports = rte_eth_dev_count();
+
+ signo = 0;
+
+ for (portid = 0; portid < nb_ports; portid++) {
+ rte_eth_dev_stop((uint8_t) portid);
+ printf(" stop ethernet device %d \n", portid);
+ }
+
+ exit(0);
+}
+
+
+#ifndef NL2FWD_APT_MAXPARAS
+#define NL2FWD_APT_MAXPARAS 2048
+#endif
+
+#ifndef NL2FWD_APT_STRING_MAX
+#define NL2FWD_APT_STRING_MAX 2048
+#endif
+
+#ifndef NL2FWD_APT_ENABLE
+#define NL2FWD_APT_ENABLE 1
+#endif
+
+int dpdk_init_apt();
+int dpdk_init_t(int argc, char **argv);
+
+int main(int argc,char **argv)
+{
+#if NL2FWD_APT_ENABLE
+ dpdk_init_apt();
+#else
+ dpdk_init_t(argc,argv);
+#endif
+}
+
+int dpdk_init_apt()
+{
+ char * argv_t[NL2FWD_APT_MAXPARAS];
+ int argc_t = 0;
+
+ for(int i = 0; i < NL2FWD_APT_MAXPARAS; i++)
+ {
+ argv_t[i] = (char *)malloc(sizeof(char) * NL2FWD_APT_STRING_MAX);
+ }
+ strncpy(argv_t[argc_t++],"./nl2fwd",NL2FWD_APT_STRING_MAX);
+
+ apt_paras_eal(NL2FWD_APT_MAXPARAS,&argc_t,argv_t);
+ dpdk_init_t(argc_t,argv_t);
+
+ return 0;
+}
+
+int dpdk_init_t(int argc, char **argv)
+{
+ int ret;
+
+ warn_output_stream = stderr;
+ err_output_stream = stderr;
+
+ /* Init EAL */
+ ret = rte_eal_init(argc,argv);
+ if (ret < 0)
+ return -1;
+
+ /* Parse application arguments (after the EAL ones) */
+ ret = app_parse_args(argc, argv);
+ if (ret < 0) {
+ app_print_usage();
+ return -1;
+ }
+
+ /* Init */
+ app_init();
+ app_print_params();
+
+ /* Install the signal handlers */
+ signal(SIGHUP, sigint_handler);
+ signal(SIGINT, sigint_handler);
+ signal(SIGQUIT, sigint_handler);
+ signal(SIGABRT, sigint_handler);
+ signal(SIGTERM, sigint_handler);
+
+
+ dpdk_run();
+
+ return 0;
+}
+
+
+int dpdk_run()
+{
+ uint32_t lcore;
+#if APP_STATS
+ pthread_t ntid;
+ pthread_create(&ntid, NULL,nstat_thread_entry,NULL);
+#endif
+
+ /* Launch per-lcore init on every lcore */
+ rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, CALL_MASTER);
+ RTE_LCORE_FOREACH_SLAVE(lcore) {
+ if (rte_eal_wait_lcore(lcore) < 0)
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/driver/nl2fwd.h b/driver/nl2fwd.h
new file mode 100644
index 0000000..5277de0
--- /dev/null
+++ b/driver/nl2fwd.h
@@ -0,0 +1,19 @@
+
+/* Header file of new_l2fwd_lib in Load Balance Model.
+ * Autuor : Lu Qiuwen
+ * Date : 2014-03-04
+ */
+
+
+#ifndef __L2FWD_LIB_INCLUDE__
+#define __L2FWD_LIB_INCLUDE__
+
+int dpdk_send_packet_dst(unsigned char *data, int datalen, int dst);
+int dpdk_send_packet_port(const unsigned char *data, int datalen, int port);
+int dpdk_init(int argc, char **argv);
+int dpdk_run();
+int dpdk_register_callfunc(int (*func)(const unsigned char *data,int datalen,int port_in,int lcore));
+int dpdk_register_callfunc_dst(int (*func)(const unsigned char *data,int datalen,int dst,int lcore));
+
+
+#endif
diff --git a/driver/nstat.c b/driver/nstat.c
new file mode 100644
index 0000000..14e01ab
--- /dev/null
+++ b/driver/nstat.c
@@ -0,0 +1,270 @@
+
+
+/* Stat Module in Serial-Multiprocess
+ Author : Lu Qiuwen <[email protected]>
+ Date : 2014-12-07
+
+*/
+
+
+#include <sys/mman.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <rte_memory.h>
+#include <rte_debug.h>
+#include <rte_memcpy.h>
+#include <rte_cycles.h>
+#include <rte_common.h>
+#include <rte_atomic.h>
+
+#include "nstat.h"
+#include <main.h>
+
+#define SHM_FILEMODE 00777
+
+struct nstat_handle * nstat_common_handle = NULL;
+struct nstat_handle * nstat_handle_last = NULL;
+struct stat_summerize_t * nstat_summerize = NULL;
+
+void nstat_summerize_loop(struct nstat_handle * handle_now, struct nstat_handle * handle_past);
+void nstat_print_loop(struct nstat_handle * handle_now, struct nstat_handle * handle_past, FILE * fstream);
+
+#define TBPS (1ull * 1000 * 1000 * 1000 * 1000)
+#define GBPS (1ull * 1000 * 1000 * 1000)
+#define MBPS (1ull * 1000 * 1000)
+#define KBPS (1ull * 1000)
+
+static void unit_translate(uint64_t number, float * f_number, char * unit)
+{
+ if(number > TBPS)
+ {
+ *f_number = number * 1.0 / TBPS;
+ *unit = 'T';
+ }
+ else if(number > GBPS)
+ {
+ *f_number = number * 1.0 / GBPS;
+ *unit = 'G';
+ }
+ else if(number > MBPS)
+ {
+ *f_number = number * 1.0 / MBPS;
+ *unit = 'M';
+ }
+ else if(number > KBPS)
+ {
+ *f_number = number * 1.0 / KBPS;
+ *unit = 'K';
+ }
+ else
+ {
+ *f_number = number * 1.0;
+ *unit = ' ';
+ }
+}
+
+int nstat_init()
+{
+ int shm_fd = shm_open(NSTAT_SHAREDMEMORY_SYMBOL, O_RDWR|O_CREAT, SHM_FILEMODE);
+ ftruncate(shm_fd, sizeof(struct nstat_handle));
+
+ void * shm_ptr = mmap(NULL, sizeof(struct nstat_handle), PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_fd, 0);
+ if(shm_ptr == NULL)
+ rte_panic("cannot create nstat shared memory");
+
+ int shm_fd_sum = shm_open(NSTAT_SHAREMEMORY_SUMMERIZE_SYMBOL, O_RDWR|O_CREAT, SHM_FILEMODE);
+ ftruncate(shm_fd_sum, sizeof(struct stat_summerize_t));
+
+ void * shm_ptr_sum = mmap(NULL, sizeof(struct stat_summerize_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_fd_sum, 0);
+ if(shm_ptr_sum == NULL)
+ rte_panic("cannot create nstat shared memory");
+
+ nstat_common_handle = (struct nstat_handle *) shm_ptr;
+ nstat_handle_last = (struct nstat_handle *)malloc(sizeof(struct nstat_handle));
+ nstat_summerize = (struct stat_summerize_t *) shm_ptr_sum;
+
+ memset(nstat_common_handle,0,sizeof(struct nstat_handle));
+ memset(nstat_handle_last,0,sizeof(struct nstat_handle));
+ memset(nstat_summerize,0,sizeof(struct stat_summerize_t));
+
+ nstat_common_handle->stat_interval = app.statistics.sample_time;
+ nstat_handle_last->stat_interval = app.statistics.sample_time;
+
+ rte_rwlock_init(&nstat_summerize->rwlock);
+
+ return 0;
+}
+
+int nstat_destroy()
+{
+ free(nstat_handle_last);
+ free(nstat_summerize);
+ return shm_unlink(NSTAT_SHAREDMEMORY_SYMBOL);
+}
+
+void * nstat_thread_entry()
+{
+ if(!app.statistics.enable)
+ return (void *)0;
+
+ while(1)
+ {
+ sleep(app.statistics.sample_time);
+ nstat_summerize_loop(nstat_common_handle,nstat_handle_last);
+
+ if(app.statistics.is_printmsg)
+ nstat_print_loop(nstat_common_handle,nstat_handle_last,stdout);
+
+ rte_memcpy(nstat_handle_last,nstat_common_handle,sizeof(struct nstat_handle));
+ }
+
+}
+
+void nstat_summerize_loop(struct nstat_handle * handle_now, struct nstat_handle * handle_past)
+{
+ rte_rwlock_write_lock(&nstat_summerize->rwlock);
+
+ nstat_summerize->dropped = 0;
+
+ for(int port_id = 0; port_id < APP_MAX_NIC_PORTS; port_id ++)
+ {
+ if(app.enabled_port_mask & (1 << port_id) == 0)
+ continue;
+ nstat_summerize->dropped += handle_now->port[port_id].rx_drop_packets;
+ nstat_summerize->dropped += handle_now->port[port_id].tx_drop_packets;
+ }
+
+ for(int lcore_id = 0; lcore_id < APP_MAX_LCORES; lcore_id++)
+ {
+ if(app.lcore_params[lcore_id].type == e_APP_LCORE_WORKER)
+ {
+ nstat_summerize->dropped += handle_now->worker_stat[lcore_id].dropped;
+ }
+ if(app.lcore_params[lcore_id].type == e_APP_LCORE_IO)
+ {
+ nstat_summerize->dropped += handle_now->io_rx[lcore_id].dropped;
+ nstat_summerize->dropped += handle_now->io_tx[lcore_id].dropped;
+ }
+ }
+
+ rte_rwlock_write_unlock(&nstat_summerize->rwlock);
+
+ return;
+}
+
+void nstat_print_loop(struct nstat_handle * handle_now, struct nstat_handle * handle_past, FILE * fstream)
+{
+ uint64_t calibration;
+ static uint64_t hpet_last = 0, hpet_cur = 0;
+
+ hpet_cur = rte_get_timer_cycles();
+ if(hpet_last != 0)
+ calibration = (hpet_cur - hpet_last) * 1.0 / rte_get_timer_hz();
+ else
+ calibration = handle_now->stat_interval;
+
+ hpet_last = hpet_cur;
+
+ const char clr[] = {27,'[','2','J','\0'};
+ const char topleft[] = {27,'[','1',';','1','H','\0'};
+
+ fprintf(fstream,"%s%s",clr,topleft);
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ fprintf(fstream," Network Ports Statistics \n");
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+
+
+ for(int port_id = 0; port_id < APP_MAX_NIC_PORTS; port_id ++)
+ {
+ if((app.enabled_port_mask & (1 << port_id)) == 0)
+ continue;
+
+ uint64_t nic_rx_burst = (handle_now->port[port_id].rx_packets - handle_past->port[port_id].rx_packets) / calibration;
+ uint64_t nic_tx_burst = (handle_now->port[port_id].tx_packets - handle_past->port[port_id].tx_packets) / calibration;
+ uint64_t nic_rx_bytes = (handle_now->port[port_id].rx_bytes - handle_past->port[port_id].rx_bytes) / calibration;
+ uint64_t nic_tx_bytes = (handle_now->port[port_id].tx_bytes - handle_past->port[port_id].tx_bytes) / calibration;
+
+ float fps_rx,bps_rx,fps_tx,bps_tx;
+ char fps_rx_unit,bps_rx_unit,fps_tx_unit,bps_tx_unit;
+
+ unit_translate(nic_rx_burst, &fps_rx, &fps_rx_unit);
+ unit_translate(nic_tx_burst, &fps_tx, &fps_tx_unit);
+ unit_translate(nic_rx_bytes * 8, &bps_rx, &bps_rx_unit);
+ unit_translate(nic_tx_bytes * 8, &bps_tx, &bps_tx_unit);
+
+ fprintf(fstream,"Port %d\n",port_id);
+ fprintf(fstream,"RX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->port[port_id].rx_packets, handle_now->port[port_id].rx_bytes,
+ handle_now->port[port_id].rx_drop_packets, fps_rx,fps_rx_unit,bps_rx,bps_rx_unit);
+ fprintf(fstream,"TX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->port[port_id].tx_packets, handle_now->port[port_id].tx_bytes,
+ handle_now->port[port_id].tx_drop_packets, fps_tx, fps_tx_unit, bps_tx, bps_tx_unit);
+ }
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ fprintf(fstream," Input/Output(I/O) Statistics \n");
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+
+ for(int lcore_id = 0; lcore_id < APP_MAX_LCORES; lcore_id++)
+ {
+ if(app.lcore_params[lcore_id].type == e_APP_LCORE_IO)
+ {
+ uint64_t io_rx_burst = (handle_now->io_rx[lcore_id].packets - handle_past->io_rx[lcore_id].packets) / calibration;
+ uint64_t io_tx_burst = (handle_now->io_tx[lcore_id].packets - handle_past->io_tx[lcore_id].packets) / calibration;
+ uint64_t io_rx_bytes = (handle_now->io_rx[lcore_id].bytes - handle_past->io_rx[lcore_id].bytes) /calibration;
+ uint64_t io_tx_bytes = (handle_now->io_tx[lcore_id].bytes - handle_past->io_tx[lcore_id].bytes) /calibration;
+
+ float fps_rx,bps_rx,fps_tx,bps_tx;
+ char fps_rx_unit,bps_rx_unit,fps_tx_unit,bps_tx_unit;
+
+ unit_translate(io_rx_burst, &fps_rx, &fps_rx_unit);
+ unit_translate(io_tx_burst, &fps_tx, &fps_tx_unit);
+ unit_translate(io_rx_bytes * 8, &bps_rx, &bps_rx_unit);
+ unit_translate(io_tx_bytes * 8, &bps_tx, &bps_tx_unit);
+
+ fprintf(fstream,"Core %d\n",lcore_id);
+ fprintf(fstream,"RX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->io_rx[lcore_id].packets , handle_now->io_rx[lcore_id].bytes,
+ handle_now->io_rx[lcore_id].dropped, fps_rx,fps_rx_unit,bps_rx,bps_rx_unit);
+ fprintf(fstream,"TX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->io_tx[lcore_id].packets , handle_now->io_tx[lcore_id].bytes,
+ handle_now->io_tx[lcore_id].dropped, fps_tx,fps_tx_unit,bps_tx,bps_tx_unit);
+ }
+ }
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ fprintf(fstream," Worker(Client Process) Statistics \n");
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+
+ for(int lcore_id = 0; lcore_id < APP_MAX_LCORES; lcore_id++)
+ {
+ if(app.lcore_params[lcore_id].type == e_APP_LCORE_WORKER)
+ {
+ uint64_t runtime_delta = handle_now->worker_stat[lcore_id].app_runtime - handle_past->worker_stat[lcore_id].app_runtime;
+ uint64_t cycle_delta = handle_now->worker_stat[lcore_id].app_cycles - handle_past->worker_stat[lcore_id].app_cycles;
+ float runtime_per_cycle = 0;
+
+ if(likely(cycle_delta != 0))
+ runtime_per_cycle = (float)runtime_delta / cycle_delta;
+ else
+ runtime_per_cycle = 0;
+
+ fprintf(fstream,"WORKER %2d | packets %20lu | bytes: %20lu | dropped %10lu | runtime %7.2f\n",
+ lcore_id,
+ handle_now->worker_stat[lcore_id].packets,
+ handle_now->worker_stat[lcore_id].bytes,
+ handle_now->worker_stat[lcore_id].dropped,
+ runtime_per_cycle);
+ }
+ }
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ return;
+}
diff --git a/driver/nstat.h b/driver/nstat.h
new file mode 100644
index 0000000..6611495
--- /dev/null
+++ b/driver/nstat.h
@@ -0,0 +1,72 @@
+
+#ifndef __SERIAL_MULTIPROCESS_NSTAT_SERVER_INCLUDE_H__
+#define __SERIAL_MULTIPROCESS_NSTAT_SERVER_INCLUDE_H__
+
+#include <rte_mbuf.h>
+#include <nstat_common.h>
+
+// Get the Pkts total length.
+static inline uint64_t nstat_pktslen(struct rte_mbuf ** mbufs, unsigned nb_mbufs)
+{
+ uint64_t datalen = 0;
+ for(int i = 0; i < nb_mbufs; i++)
+ {
+ datalen += mbufs[i]->pkt.pkt_len + APP_PKT_OVERHEAD;
+ }
+
+ return datalen;
+}
+
+static inline void nstat_port_count_rx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t port_id)
+{
+ handle->port[port_id].rx_packets += nb_mbufs;
+ handle->port[port_id].rx_bytes += nstat_pktslen(mbufs, nb_mbufs);
+ return;
+}
+
+static inline void nstat_port_count_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t port_id)
+{
+ handle->port[port_id].tx_packets += nb_mbufs;
+ handle->port[port_id].tx_bytes += nstat_pktslen(mbufs, nb_mbufs);
+ return;
+}
+
+static inline void nstat_port_count_remove_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t port_id)
+{
+ handle->port[port_id].tx_packets -= nb_mbufs;
+ handle->port[port_id].tx_bytes -= nstat_pktslen(mbufs, nb_mbufs);
+ handle->port[port_id].tx_drop_packets += nb_mbufs;
+ return;
+}
+
+static inline void nstat_io_count_rx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_rx[lcore_id].packets += nb_mbufs;
+ handle->io_rx[lcore_id].bytes += nstat_pktslen(mbufs,nb_mbufs);
+ return;
+}
+
+static inline void nstat_io_count_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_tx[lcore_id].packets += nb_mbufs;
+ handle->io_tx[lcore_id].bytes += nstat_pktslen(mbufs,nb_mbufs);
+ return;
+}
+
+static inline void nstat_io_drop_rx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_rx[lcore_id].dropped += nb_mbufs;
+ return;
+}
+
+static inline void nstat_io_drop_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_tx[lcore_id].dropped += nb_mbufs;
+ return;
+}
+
+int nstat_init();
+int nstat_destroy();
+void * nstat_thread_entry();
+
+#endif
diff --git a/driver/runtime.c b/driver/runtime.c
new file mode 100644
index 0000000..5f47736
--- /dev/null
+++ b/driver/runtime.c
@@ -0,0 +1,531 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_spinlock.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+
+#include "main.h"
+#include "nstat.h"
+#include "layer.h"
+
+union hashkey_un
+{
+ uint64_t key[2];
+ struct hashkey
+ {
+ uint32_t src_ip;
+ uint32_t dst_ip;
+
+ uint16_t src_port;
+ uint16_t dst_port;
+ uint8_t ip_prot;
+ uint8_t rsv0;
+ uint16_t rsv1;
+ }hashkey_st;
+};
+
+static inline int get_hash_result(uint8_t *data, uint32_t *hash_value)
+{
+ uint16_t protrol_type = 0;
+ data = (uint8_t *) network_data_jump_to_layer_ip(data,&protrol_type);
+
+ switch(protrol_type)
+ {
+ case ADDR_TYPE_IPV4:
+ {
+ struct ipv4_hdr * ipv4hdr = (struct ipv4_hdr *) data;
+ uint32_t key_ipv4 = 0;
+
+ uint8_t *src_addr = (uint8_t *)&(ipv4hdr->src_addr);
+ uint8_t *dst_addr = (uint8_t *)&(ipv4hdr->dst_addr);
+
+ key_ipv4 += src_addr[0] + dst_addr[0];
+ key_ipv4 += src_addr[1] + dst_addr[1];
+ key_ipv4 += src_addr[2] + dst_addr[2];
+ key_ipv4 += src_addr[3] + dst_addr[3];
+
+ * hash_value = key_ipv4;
+ break;
+ }
+ case ADDR_TYPE_IPV6:
+ {
+ struct ipv6_hdr * ipv6hdr = (struct ipv6_hdr *)data;
+ uint32_t key_ipv6;
+ int i = 0;
+ for(i = 0; i < 16; i++)
+ key_ipv6 += (ipv6hdr->src_addr[i])+(ipv6hdr->dst_addr[i]);
+
+ *hash_value = key_ipv6;
+ break;
+ }
+
+ default:
+ {
+ * hash_value = rte_rand();
+ }
+ }
+
+ return 0;
+}
+
+static inline void
+app_lcore_io_rx_buffer_to_send (
+ struct app_lcore_params_io *lp,
+ uint32_t worker,
+ struct rte_mbuf *mbuf,
+ uint32_t bsz)
+{
+ uint32_t pos;
+ int ret;
+ unsigned lcore_id = rte_lcore_id();
+
+ pos = lp->rx.mbuf_out[worker].n_mbufs;
+ lp->rx.mbuf_out[worker].array[pos ++] = mbuf;
+
+ if (likely(pos < bsz)) {
+ lp->rx.mbuf_out[worker].n_mbufs = pos;
+ return;
+ }
+
+ ret = rte_ring_enqueue_bulk(
+ lp->rx.rings[worker],
+ (void **) lp->rx.mbuf_out[worker].array,
+ bsz);
+
+ if (unlikely(ret == -ENOBUFS)) {
+ uint32_t k;
+ nstat_io_drop_rx(nstat_common_handle,lp->rx.mbuf_out[worker].array,bsz,lcore_id);
+
+ for (k = 0; k < bsz; k ++) {
+ struct rte_mbuf *m = lp->rx.mbuf_out[worker].array[k];
+ rte_pktmbuf_free(m);
+ }
+ }
+
+ lp->rx.mbuf_out[worker].n_mbufs = 0;
+ lp->rx.mbuf_out_flush[worker] = 0;
+}
+
+static inline void
+app_lcore_io_rx(
+ struct app_lcore_params_io *lp,
+ uint32_t n_workers,
+ uint32_t bsz_rd,
+ uint32_t bsz_wr)
+{
+ struct rte_mbuf *mbuf_1_0, *mbuf_1_1, *mbuf_2_0, *mbuf_2_1;
+ uint8_t *data_1_0, *data_1_1 = NULL;
+ uint32_t i;
+ uint32_t hash_value;
+ unsigned lcore_id = rte_lcore_id();
+
+ for (i = 0; i < lp->rx.n_nic_queues; i ++) {
+ uint8_t port = lp->rx.nic_queues[i].port;
+ uint8_t queue = lp->rx.nic_queues[i].queue;
+ uint32_t n_mbufs, j;
+
+ n_mbufs = rte_eth_rx_burst(port, queue, lp->rx.mbuf_in.array, (uint16_t) bsz_rd);
+
+ if(unlikely(n_mbufs == 0))
+ continue;
+
+ nstat_port_count_rx(nstat_common_handle, lp->rx.mbuf_in.array, n_mbufs, port);
+ nstat_io_count_rx(nstat_common_handle, lp->rx.mbuf_in.array, n_mbufs, lcore_id);
+
+#if APP_IO_RX_DROP_ALL_PACKETS
+ for (j = 0; j < n_mbufs; j ++) {
+ struct rte_mbuf *pkt = lp->rx.mbuf_in.array[j];
+ rte_pktmbuf_free(pkt);
+ }
+
+ continue;
+#endif
+ uint32_t lcore = rte_lcore_id();
+
+ mbuf_1_0 = lp->rx.mbuf_in.array[0];
+ mbuf_1_1 = lp->rx.mbuf_in.array[1];
+ data_1_0 = rte_pktmbuf_mtod(mbuf_1_0, uint8_t *);
+ if (likely(n_mbufs > 1)) {
+ data_1_1 = rte_pktmbuf_mtod(mbuf_1_1, uint8_t *);
+ }
+
+ mbuf_2_0 = lp->rx.mbuf_in.array[2];
+ mbuf_2_1 = lp->rx.mbuf_in.array[3];
+ APP_IO_RX_PREFETCH0(mbuf_2_0);
+ APP_IO_RX_PREFETCH0(mbuf_2_1);
+
+ for (j = 0; j + 3 < n_mbufs; j += 2) {
+ struct rte_mbuf *mbuf_0_0, *mbuf_0_1;
+ uint8_t *data_0_0, *data_0_1;
+ uint32_t worker_0, worker_1;
+
+ mbuf_0_0 = mbuf_1_0;
+ mbuf_0_1 = mbuf_1_1;
+ data_0_0 = data_1_0;
+ data_0_1 = data_1_1;
+
+ mbuf_1_0 = mbuf_2_0;
+ mbuf_1_1 = mbuf_2_1;
+ data_1_0 = rte_pktmbuf_mtod(mbuf_2_0, uint8_t *);
+ data_1_1 = rte_pktmbuf_mtod(mbuf_2_1, uint8_t *);
+ APP_IO_RX_PREFETCH0(data_1_0);
+ APP_IO_RX_PREFETCH0(data_1_1);
+
+ mbuf_2_0 = lp->rx.mbuf_in.array[j+4];
+ mbuf_2_1 = lp->rx.mbuf_in.array[j+5];
+ APP_IO_RX_PREFETCH0(mbuf_2_0);
+ APP_IO_RX_PREFETCH0(mbuf_2_1);
+
+ if(get_hash_result(data_0_0, &hash_value))
+ {
+ rte_pktmbuf_free(mbuf_0_0);
+ }
+ else
+ {
+ worker_0 = hash_value % n_workers;
+ app_lcore_io_rx_buffer_to_send(lp, worker_0, mbuf_0_0, bsz_wr);
+ }
+
+ if(get_hash_result(data_0_1, &hash_value))
+ {
+ rte_pktmbuf_free(mbuf_0_1);
+ }
+ else
+ {
+ worker_1 = hash_value % n_workers;
+ app_lcore_io_rx_buffer_to_send(lp, worker_1, mbuf_0_1, bsz_wr);
+ }
+ }
+
+ /* Handle the last 1, 2 (when n_mbufs is even) or 3 (when n_mbufs is odd) packets */
+ for ( ; j < n_mbufs; j += 1) {
+ struct rte_mbuf *mbuf;
+ uint8_t *data;
+ uint32_t worker;
+
+ mbuf = mbuf_1_0;
+ mbuf_1_0 = mbuf_1_1;
+ mbuf_1_1 = mbuf_2_0;
+ mbuf_2_0 = mbuf_2_1;
+
+ data = rte_pktmbuf_mtod(mbuf, uint8_t *);
+
+ APP_IO_RX_PREFETCH0(mbuf_1_0);
+
+ if(get_hash_result(data, &hash_value))
+ {
+ rte_pktmbuf_free(mbuf);
+ }
+ else
+ {
+ worker = hash_value % n_workers;
+ app_lcore_io_rx_buffer_to_send(lp, worker, mbuf, bsz_wr);
+ }
+ }
+ }
+}
+
+static inline void
+app_lcore_io_rx_flush(struct app_lcore_params_io *lp, uint32_t n_workers)
+{
+ uint32_t worker;
+ unsigned lcore_id = rte_lcore_id();
+
+ for (worker = 0; worker < n_workers; worker ++) {
+ int ret;
+
+ if (likely((lp->rx.mbuf_out_flush[worker] == 0) ||
+ (lp->rx.mbuf_out[worker].n_mbufs == 0))) {
+ lp->rx.mbuf_out_flush[worker] = 1;
+ continue;
+ }
+
+ ret = rte_ring_sp_enqueue_bulk(lp->rx.rings[worker],(void **) lp->rx.mbuf_out[worker].array,
+ lp->rx.mbuf_out[worker].n_mbufs);
+
+ //TODO: STAT Handle
+
+ if (unlikely(ret < 0)) {
+ uint32_t k;
+ nstat_io_drop_rx(nstat_common_handle,lp->rx.mbuf_out[worker].array,lp->rx.mbuf_out[worker].n_mbufs,lcore_id);
+
+ for (k = 0; k < lp->rx.mbuf_out[worker].n_mbufs; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->rx.mbuf_out[worker].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+
+ lp->rx.mbuf_out[worker].n_mbufs = 0;
+ lp->rx.mbuf_out_flush[worker] = 1;
+ }
+}
+
+
+/* Lu Qiuwen<[email protected]>, at 2014-12-04 */
+/* Modified from DPDK 1.7.1 examples/load_balancer/runtime.c */
+
+static inline void
+app_lcore_io_tx(
+ struct app_lcore_params_io *lp,
+ uint32_t n_workers,
+ uint32_t bsz_rd,
+ uint32_t bsz_wr)
+{
+ uint32_t worker;
+ unsigned lcore_id = rte_lcore_id();
+
+ for (worker = 0; worker < n_workers; worker ++) {
+ uint32_t i;
+
+ for (i = 0; i < lp->tx.n_nic_ports; i ++) {
+ uint8_t port = lp->tx.nic_ports[i];
+ uint8_t nqueue = lp->tx.nic_n_queues[i];
+ struct rte_ring *ring = lp->tx.rings[port][worker];
+ uint32_t n_mbufs, n_pkts;
+ int ret;
+
+ n_mbufs = lp->tx.mbuf_out[port].n_mbufs;
+ ret = rte_ring_sc_dequeue_bulk(
+ ring,
+ (void **) &lp->tx.mbuf_out[port].array[n_mbufs],
+ bsz_rd);
+
+ if (unlikely(ret == -ENOENT)) {
+ continue;
+ }
+
+ nstat_io_count_tx(nstat_common_handle, &lp->tx.mbuf_out[port].array[n_mbufs],bsz_rd, lcore_id);
+ n_mbufs += bsz_rd;
+
+#if APP_IO_TX_DROP_ALL_PACKETS
+ {
+ uint32_t j;
+ APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[0]);
+ APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[1]);
+
+ for (j = 0; j < n_mbufs; j ++) {
+ if (likely(j < n_mbufs - 2)) {
+ APP_IO_TX_PREFETCH0(lp->tx.mbuf_out[port].array[j + 2]);
+ }
+
+ rte_pktmbuf_free(lp->tx.mbuf_out[port].array[j]);
+ }
+
+ lp->tx.mbuf_out[port].n_mbufs = 0;
+ continue;
+ }
+#endif
+
+ if (unlikely(n_mbufs < bsz_wr)) {
+ lp->tx.mbuf_out[port].n_mbufs = n_mbufs;
+ continue;
+ }
+
+ n_pkts = rte_eth_tx_burst(
+ port,
+ worker % nqueue,
+ lp->tx.mbuf_out[port].array,
+ (uint16_t) n_mbufs);
+
+ // NSTAT Handle
+ nstat_port_count_tx(nstat_common_handle, lp->tx.mbuf_out[port].array,
+ n_mbufs, port);
+
+ if (unlikely(n_pkts < n_mbufs)) {
+ uint32_t k;
+
+ nstat_port_count_remove_tx(nstat_common_handle, &(lp->tx.mbuf_out[port].array[n_pkts]),
+ n_mbufs - n_pkts, port);
+ nstat_io_drop_tx(nstat_common_handle, &(lp->tx.mbuf_out[port].array[n_pkts]),
+ n_mbufs - n_pkts, lcore_id);
+
+ for (k = n_pkts; k < n_mbufs; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->tx.mbuf_out[port].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+ lp->tx.mbuf_out[port].n_mbufs = 0;
+ lp->tx.mbuf_out_flush[port] = 0;
+ }
+ }
+}
+
+static inline void
+app_lcore_io_tx_flush(struct app_lcore_params_io *lp)
+{
+ uint8_t port;
+ unsigned lcore_id = rte_lcore_id();
+
+ for (port = 0; port < lp->tx.n_nic_ports; port ++) {
+ uint32_t n_pkts;
+
+ if (likely((lp->tx.mbuf_out_flush[port] == 0) ||
+ (lp->tx.mbuf_out[port].n_mbufs == 0))) {
+ lp->tx.mbuf_out_flush[port] = 1;
+ continue;
+ }
+
+ n_pkts = rte_eth_tx_burst(
+ port,
+ 0,
+ lp->tx.mbuf_out[port].array,
+ (uint16_t) lp->tx.mbuf_out[port].n_mbufs);
+
+ nstat_port_count_tx(nstat_common_handle, lp->tx.mbuf_out[port].array,
+ lp->tx.mbuf_out[port].n_mbufs, port);
+
+ if (unlikely(n_pkts < lp->tx.mbuf_out[port].n_mbufs)) {
+ uint32_t k;
+
+ nstat_port_count_remove_tx(nstat_common_handle, &(lp->tx.mbuf_out[port].array[n_pkts]),
+ lp->tx.mbuf_out[port].n_mbufs - n_pkts, port);
+ nstat_io_drop_tx(nstat_common_handle, &(lp->tx.mbuf_out[port].array[n_pkts]),
+ lp->tx.mbuf_out[port].n_mbufs - n_pkts, lcore_id);
+
+ for (k = n_pkts; k < lp->tx.mbuf_out[port].n_mbufs; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->tx.mbuf_out[port].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+
+ lp->tx.mbuf_out[port].n_mbufs = 0;
+ lp->tx.mbuf_out_flush[port] = 1;
+ }
+}
+
+/* end ---------- at 2014-12-04 ------- */
+
+static void
+app_lcore_main_loop_io(void)
+{
+ uint32_t lcore = rte_lcore_id();
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t n_workers = app_get_lcores_worker();
+ uint32_t n_io_cores = app_get_lcores_io_rx();
+ uint64_t i = 0;
+
+ uint32_t bsz_rx_rd = app.burst_size_io_rx_read;
+ uint32_t bsz_rx_wr = app.burst_size_io_rx_write;
+ uint32_t bsz_tx_rd = app.burst_size_io_tx_read;
+ uint32_t bsz_tx_wr = app.burst_size_io_tx_write;
+
+ for ( ; ; ) {
+ if (APP_LCORE_IO_FLUSH && (unlikely(i == APP_LCORE_IO_FLUSH))) {
+ if (likely(lp->rx.n_nic_queues > 0)) {
+ app_lcore_io_rx_flush(lp, n_workers);
+ }
+ i = 0;
+ }
+
+ if (likely(lp->rx.n_nic_queues > 0)) {
+ app_lcore_io_rx(lp, n_workers, bsz_rx_rd, bsz_rx_wr);
+ }
+ i ++;
+
+ if(APP_LCORE_IO_FLUSH && (unlikely(i == APP_LCORE_IO_FLUSH))) {
+ if(likely(lp->tx.n_nic_ports > 0)) {
+ app_lcore_io_tx_flush(lp);
+ }
+ i = 0;
+ }
+
+ if (likely(lp->tx.n_nic_ports> 0)) {
+ app_lcore_io_tx(lp, n_workers, bsz_rx_rd, bsz_rx_wr);
+ }
+ i ++;
+ }
+}
+
+int
+app_lcore_main_loop(__attribute__((unused)) void *arg)
+{
+ struct app_lcore_params *lp;
+ unsigned lcore;
+
+ lcore = rte_lcore_id();
+ lp = &app.lcore_params[lcore];
+
+ if (lp->type == e_APP_LCORE_IO) {
+ printf("Logical core %u (I/O) main loop.\n", lcore);
+ app_lcore_main_loop_io();
+ }
+
+ return 0;
+}
diff --git a/driver/version.c b/driver/version.c
new file mode 100644
index 0000000..1cd1c45
--- /dev/null
+++ b/driver/version.c
@@ -0,0 +1,5 @@
+
+#include "version.h"
+
+const char __serial_driver_version_20141219__[] __attribute__((used)) = "__SERIAL_DRIVER_VERSION_20141219__";
+const char __SERIAL_DRIVER_VERSION_20141219__[] __attribute__((used)) = "__serial_driver_version_20141219__";
diff --git a/driver/version.h b/driver/version.h
new file mode 100644
index 0000000..5c421b1
--- /dev/null
+++ b/driver/version.h
@@ -0,0 +1,9 @@
+
+#ifndef __VERSION_LIB_INCLUDE_H__
+#define __VERSION_LIB_INCLUDE_H__
+
+extern const char __serial_version_info__[];
+extern const char __serial_version_platform__[];
+
+#endif
+
diff --git a/include/.gitignore b/include/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/include/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/include/MESA/MESA_prof_load.h b/include/MESA/MESA_prof_load.h
new file mode 100644
index 0000000..a08bb23
--- /dev/null
+++ b/include/MESA/MESA_prof_load.h
@@ -0,0 +1,197 @@
+#ifndef SLIB_LOADPROF_H
+#define SLIB_LOADPROF_H
+#include <sys/types.h>
+
+#ifdef WIN32
+#define strncasecmp(x,y,z) memicmp(x,y,z)
+#endif
+#ifdef WIN32
+#define LINE_BREAK_TAG "\r\n"
+#else
+#define LINE_BREAK_TAG "\n"
+#endif
+
+#define MAX_PROF_LINE 1024 /* MAX bytes in a single line */
+#define MAX_IP_SIZE 16 /* MAX bytes in a single ip string*/
+#define COMMENT_CHAR '#' /* comments line prefix */
+#define SECTION_PRE '[' /* section name prefix */
+#define SECTION_POST ']' /* section name postfix */
+#define VALUE_SET '=' /* set key value operator */
+#define HYPHEN '-'
+#define TYPE_INT 1
+#define TYPE_FLOAT 2
+#define TYPE_STRING 3
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_int_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val, // [OUT] returned value
+ const int dval); // [IN] default value
+
+
+
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_int_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val); // [OUT] returned value
+
+
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_uint_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val, // [OUT] returned value
+ const unsigned int dval); // [IN] default value
+
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_uint_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val); // [OUT] returned value
+
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_short_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val, // [OUT] returned value
+ const short dval); // [IN] default value
+
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_short_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val); // [OUT] returned value
+
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t' '\n' '\r'
+//
+// Return:
+// >= 0 : length of val
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+
+int MESA_load_profile_string_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size); // [IN] buffer size(bytes)
+
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t' '\n' '\r'
+//
+// Return:
+// >= 0 : length of val
+// < 0 : error, str is set to default
+int MESA_load_profile_string_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size, // [IN] buffer size(bytes)
+ const char *dstr); // [IN] default string
+
+
+
+//read ips from config file
+//return :
+// >=0 : success,return the number of ip read from file successfully
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error,invalid ip
+
+
+int MESA_load_profile_ipset(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const size_t size, // [IN] the size of memory ips point,it must equel or greater than ip_num*sizeof(unsigned int)
+ unsigned int *ipset); // [OUT] return ipset network bytes order
+
+// Write the a int into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_int(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const int value); // [IN] the integer need write
+
+// Write the a float into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_float(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const float value); // [IN] the float need write
+
+// Write the a string into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_string(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const char *value); // [IN] the string need write
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef SLIB_LOADPROF_H */
diff --git a/include/pcap/bluetooth.h b/include/pcap/bluetooth.h
new file mode 100644
index 0000000..813bea3
--- /dev/null
+++ b/include/pcap/bluetooth.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * bluetooth data struct
+ * By Paolo Abeni <[email protected]>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007-09-22 02:10:17 guy Exp $
+ */
+
+#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
+#define _PCAP_BLUETOOTH_STRUCTS_H__
+
+/*
+ * Header prepended libpcap to each bluetooth h:4 frame.
+ * fields are in network byte order
+ */
+typedef struct _pcap_bluetooth_h4_header {
+ u_int32_t direction; /* if first bit is set direction is incoming */
+} pcap_bluetooth_h4_header;
+
+
+#endif
diff --git a/include/pcap/bpf.h b/include/pcap/bpf.h
new file mode 100644
index 0000000..8576bbd
--- /dev/null
+++ b/include/pcap/bpf.h
@@ -0,0 +1,1303 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.32 2008-12-23 20:13:29 guy Exp $ (LBL)
+ */
+
+/*
+ * This is libpcap's cut-down version of bpf.h; it includes only
+ * the stuff needed for the code generator and the userland BPF
+ * interpreter, and the libpcap APIs for setting filters, etc..
+ *
+ * "pcap-bpf.c" will include the native OS version, as it deals with
+ * the OS's BPF implementation.
+ *
+ * At least two programs found by Google Code Search explicitly includes
+ * <pcap/bpf.h> (even though <pcap.h>/<pcap/pcap.h> includes it for you),
+ * so moving that stuff to <pcap/pcap.h> would break the build for some
+ * programs.
+ */
+
+/*
+ * If we've already included <net/bpf.h>, don't re-define this stuff.
+ * We assume BSD-style multiple-include protection in <net/bpf.h>,
+ * which is true of all but the oldest versions of FreeBSD and NetBSD,
+ * or Tru64 UNIX-style multiple-include protection (or, at least,
+ * Tru64 UNIX 5.x-style; I don't have earlier versions available to check),
+ * or AIX-style multiple-include protection (or, at least, AIX 5.x-style;
+ * I don't have earlier versions available to check).
+ *
+ * We do not check for BPF_MAJOR_VERSION, as that's defined by
+ * <linux/filter.h>, which is directly or indirectly included in some
+ * programs that also include pcap.h, and <linux/filter.h> doesn't
+ * define stuff we need.
+ *
+ * This also provides our own multiple-include protection.
+ */
+#if !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h)
+#define lib_pcap_bpf_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef MSDOS /* must be 32-bit */
+typedef long bpf_int32;
+typedef unsigned long bpf_u_int32;
+#else
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+/*
+ * Alignment macros. BPF_WORDALIGN rounds up to the next
+ * even multiple of BPF_ALIGNMENT.
+ *
+ * Tcpdump's print-pflog.c uses this, so we define it here.
+ */
+#ifndef __NetBSD__
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#else
+#define BPF_ALIGNMENT sizeof(long)
+#endif
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+/*
+ * Structure for "pcap_compile()", "pcap_setfilter()", etc..
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Link-layer header type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "[email protected]" for a value. Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ *
+ * See
+ *
+ * http://www.tcpdump.org/linktypes.html
+ *
+ * for detailed descriptions of some of these link-layer header types.
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL 0 /* BSD loopback encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* 802.5 Token Ring */
+#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages. We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW 14 /* raw IP */
+#else
+#define DLT_RAW 12 /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't. So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
+ *
+ * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
+ * as 117 so that pflog captures would use a link-layer header type
+ * value that didn't collide with any other values. On all
+ * platforms other than OpenBSD, we defined DLT_PFLOG as 117,
+ * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG.
+ *
+ * OpenBSD eventually switched to using 117 for DLT_PFLOG as well.
+ *
+ * Don't use 17 for anything else.
+ */
+
+/*
+ * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and
+ * Mac OS X; don't use it for anything else. (FreeBSD uses 121,
+ * which collides with DLT_HHDLC, even though it doesn't use 18
+ * for anything and doesn't appear to have ever used it for anything.)
+ *
+ * We define it as 18 on those platforms; it is, unfortunately, used
+ * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC
+ * in general. As the packet format for it, like that for
+ * DLT_PFLOG, is not only OS-dependent but OS-version-dependent,
+ * we don't support printing it in tcpdump except on OSes that
+ * have the relevant header files, so it's not that useful on
+ * other platforms.
+ */
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#define DLT_PFSYNC 18
+#endif
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800. I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE 32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies. The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL 99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer header type LINKTYPE_ values corresponding to DLT_ types
+ * that differ between platforms; don't use those values for new DLT_
+ * new types.
+ */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
+ * the highest such value.
+ */
+#define DLT_MATCHING_MIN 104
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't. (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY 107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP 12
+#else
+#define DLT_LOOP 108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC 13
+#else
+#define DLT_ENC 109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK 114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET 115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER 116
+
+/*
+ * OpenBSD DLT_PFLOG.
+ */
+#define DLT_PFLOG 117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS 118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER 119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER 120
+
+/*
+ * Sigh.
+ *
+ * This was reserved for Siemens HiPath HDLC on 2002-01-25, as
+ * requested by Tomas Kukosa.
+ *
+ * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
+ * assigned 121 as DLT_PFSYNC. Its libpcap does DLT_ <-> LINKTYPE_
+ * mapping, so it probably supports capturing on the pfsync device
+ * but not saving the captured data to a pcap file.
+ *
+ * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
+ * their libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
+ * use 18 in pcap files as well.
+ *
+ * NetBSD and DragonFly BSD also use 18 for DLT_PFSYNC; their
+ * libpcaps do DLT_ <-> LINKTYPE_ mapping, and neither has an entry
+ * for DLT_PFSYNC, so it might not be able to write out dump files
+ * with 18 as the link-layer header type. (Earlier versions might
+ * not have done mapping, in which case they'd work the same way
+ * OpenBSD does.)
+ *
+ * Mac OS X defines it as 18, but doesn't appear to use it as of
+ * Mac OS X 10.7.3. Its libpcap does DLT_ <-> LINKTYPE_ mapping.
+ *
+ * We'll define DLT_PFSYNC as 121 on FreeBSD and define it as 18 on
+ * all other platforms. We'll define DLT_HHDLC as 121 on everything
+ * except for FreeBSD; anybody who wants to compile, on FreeBSD, code
+ * that uses DLT_HHDLC is out of luck.
+ *
+ * We'll define LINKTYPE_PFSYNC as 18, *even on FreeBSD*, and map
+ * it, so that savefiles won't use 121 for PFSYNC - they'll all
+ * use 18. Code that uses pcap_datalink() to determine the link-layer
+ * header type of a savefile won't, when built and run on FreeBSD,
+ * be able to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC
+ * capture files; code that doesn't, such as the code in Wireshark,
+ * will be able to distinguish between them.
+ */
+#ifdef __FreeBSD__
+#define DLT_PFSYNC 121
+#else
+#define DLT_HHDLC 121
+#endif
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC 122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM 123 /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <[email protected]>
+ * for private use.
+ */
+#define DLT_RIO 124 /* RapidIO */
+#define DLT_PCI_EXP 125 /* PCI Express */
+#define DLT_AURORA 126 /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <[email protected]>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX 129 /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <[email protected]>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP 130
+#define DLT_JUNIPER_MLFR 131
+#define DLT_JUNIPER_ES 132
+#define DLT_JUNIPER_GGSN 133
+#define DLT_JUNIPER_MFR 134
+#define DLT_JUNIPER_ATM2 135
+#define DLT_JUNIPER_SERVICES 136
+#define DLT_JUNIPER_ATM1 137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <[email protected]>. The header that's presented is an Ethernet-like
+ * header:
+ *
+ * #define FIREWIRE_EUI64_LEN 8
+ * struct firewire_header {
+ * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
+ * u_char firewire_shost[FIREWIRE_EUI64_LEN];
+ * u_short firewire_type;
+ * };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394 138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2 140 /* MTP2, without pseudo-header */
+#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS 143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA 144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP 145
+#define DLT_IBM_SN 146
+
+/*
+ * Reserved for private use. If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "[email protected]" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0 147
+#define DLT_USER1 148
+#define DLT_USER2 149
+#define DLT_USER3 150
+#define DLT_USER4 151
+#define DLT_USER5 152
+#define DLT_USER6 153
+#define DLT_USER7 154
+#define DLT_USER8 155
+#define DLT_USER9 156
+#define DLT_USER10 157
+#define DLT_USER11 158
+#define DLT_USER12 159
+#define DLT_USER13 160
+#define DLT_USER14 161
+#define DLT_USER15 162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR 164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define DLT_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <[email protected]>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD 166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE 167
+#define DLT_JUNIPER_PPPOE_ATM 168
+
+#define DLT_GPRS_LLC 169 /* GPRS LLC */
+#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <[email protected]> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1 172
+#define DLT_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <[email protected]> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH 175 /* Ethernet */
+#define DLT_ERF_POS 176 /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <[email protected]> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD 177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>.
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER 178
+#define DLT_JUNIPER_PPP 179
+#define DLT_JUNIPER_FRELAY 180
+#define DLT_JUNIPER_CHDLC 181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>.
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP 183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <[email protected]>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429 184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <[email protected]>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM 185
+
+/*
+ * USB packets, beginning with a USB setup header; requested by
+ * Paolo Abeni <[email protected]>.
+ */
+#define DLT_USB 186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4 187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ */
+#define DLT_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <[email protected]>.
+ */
+#define DLT_USB_LINUX 189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <[email protected]>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B 190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <[email protected]>.
+ */
+#define DLT_PPI 192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO 193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>.
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM 194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <[email protected]>.
+ * For this one, we expect the FCS to be present at the end of the frame;
+ * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
+ */
+#define DLT_IEEE802_15_4 195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew ([email protected]).
+ */
+#define DLT_SITA 196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records. Requested by Stephen Donnelly
+ */
+#define DLT_ERF 197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board. Requested by Phil Mulholland
+ */
+#define DLT_RAIF1 198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc.. Requested by Chanthy Toeung
+ */
+#define DLT_IPMB 199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST 200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <[email protected]>.
+ */
+#define DLT_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <[email protected]>.
+ */
+#define DLT_LAPD 203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <[email protected]>.
+ */
+#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
+#define DLT_LAPB_WITH_DIR 207 /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ */
+#define DLT_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <[email protected]>.
+ */
+#define DLT_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <[email protected]>.
+ */
+#define DLT_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ */
+#define DLT_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <[email protected]>.
+ */
+#define DLT_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <[email protected]>.
+ */
+#define DLT_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <[email protected]>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY 215
+
+/*
+ * David Gibson <[email protected]> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg.
+ */
+#define DLT_LINUX_EVDEV 216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <[email protected]>.
+ */
+#define DLT_GSMTAP_UM 217
+#define DLT_GSMTAP_ABIS 218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <[email protected]> on behalf
+ * of OpenBSD.
+ */
+#define DLT_MPLS 219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define DLT_USB_LINUX_MMAPPED 220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <[email protected]>.
+ */
+#define DLT_DECT 221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <[email protected]>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ * I have already written dissectors for but need an OK from
+ * legal before I can submit a patch.
+ *
+ */
+#define DLT_AOS 222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <[email protected]>.
+ */
+#define DLT_WIHART 223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <[email protected]>.
+ */
+#define DLT_FC_2 224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <[email protected]>.
+ */
+#define DLT_FC_2_WITH_FRAME_DELIMS 225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <[email protected]>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ * u_int8_t dli_version;
+ * u_int8_t dli_family;
+ * u_int16_t dli_htype;
+ * u_int32_t dli_pktlen;
+ * u_int32_t dli_ifindex;
+ * u_int32_t dli_grifindex;
+ * u_int32_t dli_zsrc;
+ * u_int32_t dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define DLT_IPNET 226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN. See Documentation/networking/can.txt in the Linux
+ * source.
+ *
+ * Requested by Felix Obenhuber <[email protected]>.
+ */
+#define DLT_CAN_SOCKETCAN 227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6. Requested by Darren Reed <[email protected]>.
+ */
+#define DLT_IPV4 228
+#define DLT_IPV6 229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <[email protected]>.
+ */
+#define DLT_IEEE802_15_4_NOFCS 230
+
+/*
+ * Raw D-Bus:
+ *
+ * http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <[email protected]>.
+ */
+#define DLT_DBUS 231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>.
+ */
+#define DLT_JUNIPER_VS 232
+#define DLT_JUNIPER_SRX_E2E 233
+#define DLT_JUNIPER_FIBRECHANNEL 234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver). See
+ *
+ * http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <[email protected]>.
+ */
+#define DLT_DVB_CI 235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
+ * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel
+ */
+#define DLT_MUX27010 236
+
+/*
+ * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
+ */
+#define DLT_STANAG_5066_D_PDU 237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <[email protected]>.
+ */
+#define DLT_JUNIPER_ATM_CEMIC 238
+
+/*
+ * NetFilter LOG messages
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <[email protected]>
+ */
+#define DLT_NFLOG 239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <[email protected]>
+ */
+#define DLT_NETANALYZER 240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * with the Ethernet header preceded by 7 bytes of preamble and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <[email protected]>
+ */
+#define DLT_NETANALYZER_TRANSPARENT 241
+
+/*
+ * IP-over-InfiniBand, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <[email protected]>.
+ */
+#define DLT_IPOIB 242
+
+/*
+ * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
+ *
+ * Requested by Guy Martin <[email protected]>.
+ */
+#define DLT_MPEG_2_TS 243
+
+/*
+ * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
+ * used by their ng40 protocol tester.
+ *
+ * Requested by Jens Grimmer <[email protected]>.
+ */
+#define DLT_NG40 244
+
+/*
+ * Pseudo-header giving adapter number and flags, followed by an NFC
+ * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
+ * as specified by NFC Forum Logical Link Control Protocol Technical
+ * Specification LLCP 1.1.
+ *
+ * Requested by Mike Wakerly <[email protected]>.
+ */
+#define DLT_NFC_LLCP 245
+
+/*
+ * 245 is used as LINKTYPE_PFSYNC; do not use it for any other purpose.
+ *
+ * DLT_PFSYNC has different values on different platforms, and all of
+ * them collide with something used elsewhere. On platforms that
+ * don't already define it, define it as 245.
+ */
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)
+#define DLT_PFSYNC 246
+#endif
+
+/*
+ * Raw InfiniBand packets, starting with the Local Routing Header.
+ *
+ * Requested by Oren Kladnitsky <[email protected]>.
+ */
+#define DLT_INFINIBAND 247
+
+/*
+ * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
+ *
+ * Requested by Michael Tuexen <[email protected]>.
+ */
+#define DLT_SCTP 248
+
+#define DLT_MATCHING_MAX 248 /* highest value in the "matching" range */
+
+/*
+ * DLT and savefile link type values are split into a class and
+ * a member of that class. A class value of 0 indicates a regular
+ * DLT_/LINKTYPE_ value.
+ */
+#define DLT_CLASS(x) ((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type. The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with. Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define DLT_CLASS_NETBSD_RAWAF 0x02240000
+#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
+#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
+#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_u_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+#if __STDC__ || defined(__cplusplus)
+extern int bpf_validate(const struct bpf_insn *, int);
+extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+#else
+extern int bpf_validate();
+extern u_int bpf_filter();
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) */
diff --git a/include/pcap/ipnet.h b/include/pcap/ipnet.h
new file mode 100644
index 0000000..5330847
--- /dev/null
+++ b/include/pcap/ipnet.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define IPH_AF_INET 2 /* Matches Solaris's AF_INET */
+#define IPH_AF_INET6 26 /* Matches Solaris's AF_INET6 */
+
+#define IPNET_OUTBOUND 1
+#define IPNET_INBOUND 2
diff --git a/include/pcap/namedb.h b/include/pcap/namedb.h
new file mode 100644
index 0000000..e314557
--- /dev/null
+++ b/include/pcap/namedb.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006-10-04 18:09:22 guy Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_namedb_h
+#define lib_pcap_namedb_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * As returned by the pcap_next_etherent()
+ * XXX this stuff doesn't belong in this interface, but this
+ * library already must do name to address translation, so
+ * on systems that don't have support for /etc/ethers, we
+ * export these hooks since they'll
+ */
+struct pcap_etherent {
+ u_char addr[6];
+ char name[122];
+};
+#ifndef PCAP_ETHERS_FILE
+#define PCAP_ETHERS_FILE "/etc/ethers"
+#endif
+struct pcap_etherent *pcap_next_etherent(FILE *);
+u_char *pcap_ether_hostton(const char*);
+u_char *pcap_ether_aton(const char *);
+
+bpf_u_int32 **pcap_nametoaddr(const char *);
+#ifdef INET6
+struct addrinfo *pcap_nametoaddrinfo(const char *);
+#endif
+bpf_u_int32 pcap_nametonetaddr(const char *);
+
+int pcap_nametoport(const char *, int *, int *);
+int pcap_nametoportrange(const char *, int *, int *, int *);
+int pcap_nametoproto(const char *);
+int pcap_nametoeproto(const char *);
+int pcap_nametollc(const char *);
+/*
+ * If a protocol is unknown, PROTO_UNDEF is returned.
+ * Also, pcap_nametoport() returns the protocol along with the port number.
+ * If there are ambiguous entried in /etc/services (i.e. domain
+ * can be either tcp or udp) PROTO_UNDEF is returned.
+ */
+#define PROTO_UNDEF -1
+
+/* XXX move these to pcap-int.h? */
+int __pcap_atodn(const char *, bpf_u_int32 *);
+int __pcap_atoin(const char *, bpf_u_int32 *);
+u_short __pcap_nametodnaddr(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/pcap/pcap.h b/include/pcap/pcap.h
new file mode 100644
index 0000000..7be36b1
--- /dev/null
+++ b/include/pcap/pcap.h
@@ -0,0 +1,463 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.15 2008-10-06 15:27:32 gianluca Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_pcap_h
+#define lib_pcap_pcap_h
+
+#if defined(WIN32)
+ #include <pcap-stdinc.h>
+#elif defined(MSDOS)
+ #include <sys/types.h>
+ #include <sys/socket.h> /* u_int, u_char etc. */
+#else /* UN*X */
+ #include <sys/types.h>
+ #include <sys/time.h>
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <pcap/bpf.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Version number of the current version of the pcap file format.
+ *
+ * NOTE: this is *NOT* the version number of the libpcap library.
+ * To fetch the version information for the version of libpcap
+ * you're using, use pcap_lib_version().
+ */
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+#define PCAP_ERRBUF_SIZE 256
+
+/*
+ * Compatibility for systems that have a bpf.h that
+ * predates the bpf typedefs for 64-bit support.
+ */
+#if BPF_RELEASE - 0 < 199406
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+typedef struct pcap pcap_t;
+typedef struct pcap_dumper pcap_dumper_t;
+typedef struct pcap_if pcap_if_t;
+typedef struct pcap_addr pcap_addr_t;
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are 32 bit ints so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ *
+ * Do not change the layout of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ *
+ * Also, do not change the interpretation of any of the members of this
+ * structure, in any way (this includes using values other than
+ * LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
+ * field).
+ *
+ * Instead:
+ *
+ * introduce a new structure for the new format, if the layout
+ * of the structure changed;
+ *
+ * send mail to "[email protected]", requesting
+ * a new magic number for your new capture file format, and, when
+ * you get the new magic number, put it in "savefile.c";
+ *
+ * use that magic number for save files with the changed file
+ * header;
+ *
+ * make the code in "savefile.c" capable of reading files with
+ * the old file header as well as files with the new file header
+ * (using the magic number to determine the header format).
+ *
+ * Then supply the changes by forking the branch at
+ *
+ * https://github.com/mcr/libpcap/issues
+ *
+ * and issuing a pull request, so that future versions of libpcap and
+ * programs that use it (such as tcpdump) will be able to read your new
+ * capture file format.
+ */
+struct pcap_file_header {
+ bpf_u_int32 magic;
+ u_short version_major;
+ u_short version_minor;
+ bpf_int32 thiszone; /* gmt to local correction */
+ bpf_u_int32 sigfigs; /* accuracy of timestamps */
+ bpf_u_int32 snaplen; /* max length saved portion of each pkt */
+ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
+};
+
+/*
+ * Macros for the value returned by pcap_datalink_ext().
+ *
+ * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro
+ * gives the FCS length of packets in the capture.
+ */
+#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000)
+#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28)
+#define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000)
+
+typedef enum {
+ PCAP_D_INOUT = 0,
+ PCAP_D_IN,
+ PCAP_D_OUT
+} pcap_direction_t;
+
+/*
+ * Generic per-packet information, as supplied by libpcap.
+ *
+ * The time stamp can and should be a "struct timeval", regardless of
+ * whether your system supports 32-bit tv_sec in "struct timeval",
+ * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
+ * and 64-bit applications. The on-disk format of savefiles uses 32-bit
+ * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit
+ * and 64-bit versions of libpcap, even if they're on the same platform,
+ * should supply the appropriate version of "struct timeval", even if
+ * that's not what the underlying packet capture mechanism supplies.
+ */
+struct pcap_pkthdr {
+ struct timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+};
+
+/*
+ * As returned by the pcap_stats()
+ */
+struct pcap_stat {
+ u_int ps_recv; /* number of packets received */
+ u_int ps_drop; /* number of packets dropped */
+ u_int ps_ifdrop; /* drops by interface -- only supported on some platforms */
+#ifdef WIN32
+ u_int bs_capt; /* number of packets that reach the application */
+#endif /* WIN32 */
+};
+
+#ifdef MSDOS
+/*
+ * As returned by the pcap_stats_ex()
+ */
+struct pcap_stat_ex {
+ u_long rx_packets; /* total packets received */
+ u_long tx_packets; /* total packets transmitted */
+ u_long rx_bytes; /* total bytes received */
+ u_long tx_bytes; /* total bytes transmitted */
+ u_long rx_errors; /* bad packets received */
+ u_long tx_errors; /* packet transmit problems */
+ u_long rx_dropped; /* no space in Rx buffers */
+ u_long tx_dropped; /* no space available for Tx */
+ u_long multicast; /* multicast packets received */
+ u_long collisions;
+
+ /* detailed rx_errors: */
+ u_long rx_length_errors;
+ u_long rx_over_errors; /* receiver ring buff overflow */
+ u_long rx_crc_errors; /* recv'd pkt with crc error */
+ u_long rx_frame_errors; /* recv'd frame alignment error */
+ u_long rx_fifo_errors; /* recv'r fifo overrun */
+ u_long rx_missed_errors; /* recv'r missed packet */
+
+ /* detailed tx_errors */
+ u_long tx_aborted_errors;
+ u_long tx_carrier_errors;
+ u_long tx_fifo_errors;
+ u_long tx_heartbeat_errors;
+ u_long tx_window_errors;
+ };
+#endif
+
+/*
+ * Item in a list of interfaces.
+ */
+struct pcap_if {
+ struct pcap_if *next;
+ char *name; /* name to hand to "pcap_open_live()" */
+ char *description; /* textual description of interface, or NULL */
+ struct pcap_addr *addresses;
+ bpf_u_int32 flags; /* PCAP_IF_ interface flags */
+};
+
+#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
+
+/*
+ * Representation of an interface address.
+ */
+struct pcap_addr {
+ struct pcap_addr *next;
+ struct sockaddr *addr; /* address */
+ struct sockaddr *netmask; /* netmask for that address */
+ struct sockaddr *broadaddr; /* broadcast address for that address */
+ struct sockaddr *dstaddr; /* P2P destination address for that address */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+ const u_char *);
+
+/*
+ * Error codes for the pcap API.
+ * These will all be negative, so you can check for the success or
+ * failure of a call that returns these codes by checking for a
+ * negative value.
+ */
+#define PCAP_ERROR -1 /* generic error code */
+#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */
+#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */
+#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */
+#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */
+#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */
+#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */
+#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
+#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
+#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
+#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
+
+/*
+ * Warning codes for the pcap API.
+ * These will all be positive and non-zero, so they won't look like
+ * errors.
+ */
+#define PCAP_WARNING 1 /* generic warning code */
+#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */
+#define PCAP_WARNING_TSTAMP_TYPE_NOTSUP 3 /* the requested time stamp type is not supported */
+
+/*
+ * Value to pass to pcap_compile() as the netmask if you don't know what
+ * the netmask is.
+ */
+#define PCAP_NETMASK_UNKNOWN 0xffffffff
+
+char *pcap_lookupdev(char *);
+int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+
+pcap_t *pcap_create(const char *, char *);
+int pcap_set_snaplen(pcap_t *, int);
+int pcap_set_promisc(pcap_t *, int);
+int pcap_can_set_rfmon(pcap_t *);
+int pcap_set_rfmon(pcap_t *, int);
+int pcap_set_timeout(pcap_t *, int);
+int pcap_set_tstamp_type(pcap_t *, int);
+int pcap_set_buffer_size(pcap_t *, int);
+int pcap_activate(pcap_t *);
+
+int pcap_list_tstamp_types(pcap_t *, int **);
+void pcap_free_tstamp_types(int *);
+int pcap_tstamp_type_name_to_val(const char *);
+const char *pcap_tstamp_type_val_to_name(int);
+const char *pcap_tstamp_type_val_to_description(int);
+
+/*
+ * Time stamp types.
+ * Not all systems and interfaces will necessarily support all of these.
+ *
+ * A system that supports PCAP_TSTAMP_HOST is offering time stamps
+ * provided by the host machine, rather than by the capture device,
+ * but not committing to any characteristics of the time stamp;
+ * it will not offer any of the PCAP_TSTAMP_HOST_ subtypes.
+ *
+ * PCAP_TSTAMP_HOST_LOWPREC is a time stamp, provided by the host machine,
+ * that's low-precision but relatively cheap to fetch; it's normally done
+ * using the system clock, so it's normally synchronized with times you'd
+ * fetch from system calls.
+ *
+ * PCAP_TSTAMP_HOST_HIPREC is a time stamp, provided by the host machine,
+ * that's high-precision; it might be more expensive to fetch. It might
+ * or might not be synchronized with the system clock, and might have
+ * problems with time stamps for packets received on different CPUs,
+ * depending on the platform.
+ *
+ * PCAP_TSTAMP_ADAPTER is a high-precision time stamp supplied by the
+ * capture device; it's synchronized with the system clock.
+ *
+ * PCAP_TSTAMP_ADAPTER_UNSYNCED is a high-precision time stamp supplied by
+ * the capture device; it's not synchronized with the system clock.
+ *
+ * Note that time stamps synchronized with the system clock can go
+ * backwards, as the system clock can go backwards. If a clock is
+ * not in sync with the system clock, that could be because the
+ * system clock isn't keeping accurate time, because the other
+ * clock isn't keeping accurate time, or both.
+ *
+ * Note that host-provided time stamps generally correspond to the
+ * time when the time-stamping code sees the packet; this could
+ * be some unknown amount of time after the first or last bit of
+ * the packet is received by the network adapter, due to batching
+ * of interrupts for packet arrival, queueing delays, etc..
+ */
+#define PCAP_TSTAMP_HOST 0 /* host-provided, unknown characteristics */
+#define PCAP_TSTAMP_HOST_LOWPREC 1 /* host-provided, low precision */
+#define PCAP_TSTAMP_HOST_HIPREC 2 /* host-provided, high precision */
+#define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */
+#define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */
+
+pcap_t *pcap_open_live(const char *, int, int, int, char *);
+pcap_t *pcap_open_dead(int, int);
+pcap_t *pcap_open_offline(const char *, char *);
+#if defined(WIN32)
+pcap_t *pcap_hopen_offline(intptr_t, char *);
+#if !defined(LIBPCAP_EXPORTS)
+#define pcap_fopen_offline(f,b) \
+ pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
+#else /*LIBPCAP_EXPORTS*/
+static pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif
+#else /*WIN32*/
+pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif /*WIN32*/
+
+void pcap_close(pcap_t *);
+int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+const u_char*
+ pcap_next(pcap_t *, struct pcap_pkthdr *);
+int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+void pcap_breakloop(pcap_t *);
+int pcap_stats(pcap_t *, struct pcap_stat *);
+int pcap_setfilter(pcap_t *, struct bpf_program *);
+int pcap_setdirection(pcap_t *, pcap_direction_t);
+int pcap_getnonblock(pcap_t *, char *);
+int pcap_setnonblock(pcap_t *, int, char *);
+int pcap_inject(pcap_t *, const void *, size_t);
+int pcap_sendpacket(pcap_t *, const u_char *, int);
+const char *pcap_statustostr(int);
+const char *pcap_strerror(int);
+char *pcap_geterr(pcap_t *);
+void pcap_perror(pcap_t *, char *);
+int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
+ bpf_u_int32);
+int pcap_compile_nopcap(int, int, struct bpf_program *,
+ const char *, int, bpf_u_int32);
+void pcap_freecode(struct bpf_program *);
+int pcap_offline_filter(const struct bpf_program *,
+ const struct pcap_pkthdr *, const u_char *);
+int pcap_datalink(pcap_t *);
+int pcap_datalink_ext(pcap_t *);
+int pcap_list_datalinks(pcap_t *, int **);
+int pcap_set_datalink(pcap_t *, int);
+void pcap_free_datalinks(int *);
+int pcap_datalink_name_to_val(const char *);
+const char *pcap_datalink_val_to_name(int);
+const char *pcap_datalink_val_to_description(int);
+int pcap_snapshot(pcap_t *);
+int pcap_is_swapped(pcap_t *);
+int pcap_major_version(pcap_t *);
+int pcap_minor_version(pcap_t *);
+
+/* XXX */
+FILE *pcap_file(pcap_t *);
+int pcap_fileno(pcap_t *);
+
+pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+FILE *pcap_dump_file(pcap_dumper_t *);
+long pcap_dump_ftell(pcap_dumper_t *);
+int pcap_dump_flush(pcap_dumper_t *);
+void pcap_dump_close(pcap_dumper_t *);
+void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+int pcap_findalldevs(pcap_if_t **, char *);
+void pcap_freealldevs(pcap_if_t *);
+
+const char *pcap_lib_version(void);
+
+/*
+ * On at least some versions of NetBSD, we don't want to declare
+ * bpf_filter() here, as it's also be declared in <net/bpf.h>, with a
+ * different signature, but, on other BSD-flavored UN*Xes, it's not
+ * declared in <net/bpf.h>, so we *do* want to declare it here, so it's
+ * declared when we build pcap-bpf.c.
+ */
+#ifndef __NetBSD__
+u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+#endif
+int bpf_validate(const struct bpf_insn *f, int len);
+char *bpf_image(const struct bpf_insn *, int);
+void bpf_dump(const struct bpf_program *, int);
+
+#if defined(WIN32)
+
+/*
+ * Win32 definitions
+ */
+
+int pcap_setbuff(pcap_t *p, int dim);
+int pcap_setmode(pcap_t *p, int mode);
+int pcap_setmintocopy(pcap_t *p, int size);
+
+#ifdef WPCAP
+/* Include file with the wpcap-specific extensions */
+#include <Win32-Extensions.h>
+#endif /* WPCAP */
+
+#define MODE_CAPT 0
+#define MODE_STAT 1
+#define MODE_MON 2
+
+#elif defined(MSDOS)
+
+/*
+ * MS-DOS definitions
+ */
+
+int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+u_long pcap_mac_packets (void);
+
+#else /* UN*X */
+
+/*
+ * UN*X definitions
+ */
+
+int pcap_get_selectable_fd(pcap_t *);
+
+#endif /* WIN32/MSDOS/UN*X */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* lib_pcap_pcap_h */
diff --git a/include/pcap/sll.h b/include/pcap/sll.h
new file mode 100644
index 0000000..7ad811d
--- /dev/null
+++ b/include/pcap/sll.h
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/sll.h,v 1.3 2008-05-30 01:35:33 guy Exp $ (LBL)
+ */
+
+/*
+ * For captures on Linux cooked sockets, we construct a fake header
+ * that includes:
+ *
+ * a 2-byte "packet type" which is one of:
+ *
+ * LINUX_SLL_HOST packet was sent to us
+ * LINUX_SLL_BROADCAST packet was broadcast
+ * LINUX_SLL_MULTICAST packet was multicast
+ * LINUX_SLL_OTHERHOST packet was sent to somebody else
+ * LINUX_SLL_OUTGOING packet was sent *by* us;
+ *
+ * a 2-byte Ethernet protocol field;
+ *
+ * a 2-byte link-layer type;
+ *
+ * a 2-byte link-layer address length;
+ *
+ * an 8-byte source link-layer address, whose actual length is
+ * specified by the previous value.
+ *
+ * All fields except for the link-layer address are in network byte order.
+ *
+ * DO NOT change the layout of this structure, or change any of the
+ * LINUX_SLL_ values below. If you must change the link-layer header
+ * for a "cooked" Linux capture, introduce a new DLT_ type (ask
+ * "[email protected]" for one, so that you don't give it
+ * a value that collides with a value already being used), and use the
+ * new header in captures of that type, so that programs that can
+ * handle DLT_LINUX_SLL captures will continue to handle them correctly
+ * without any change, and so that capture files with different headers
+ * can be told apart and programs that read them can dissect the
+ * packets in them.
+ */
+
+#ifndef lib_pcap_sll_h
+#define lib_pcap_sll_h
+
+/*
+ * A DLT_LINUX_SLL fake link-layer header.
+ */
+#define SLL_HDR_LEN 16 /* total header length */
+#define SLL_ADDRLEN 8 /* length of address field */
+
+struct sll_header {
+ u_int16_t sll_pkttype; /* packet type */
+ u_int16_t sll_hatype; /* link-layer address type */
+ u_int16_t sll_halen; /* link-layer address length */
+ u_int8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
+ u_int16_t sll_protocol; /* protocol */
+};
+
+/*
+ * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
+ * PACKET_ values on Linux, but are defined here so that they're
+ * available even on systems other than Linux, and so that they
+ * don't change even if the PACKET_ values change.
+ */
+#define LINUX_SLL_HOST 0
+#define LINUX_SLL_BROADCAST 1
+#define LINUX_SLL_MULTICAST 2
+#define LINUX_SLL_OTHERHOST 3
+#define LINUX_SLL_OUTGOING 4
+
+/*
+ * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
+ * ETH_P_ values on Linux, but are defined here so that they're
+ * available even on systems other than Linux. We assume, for now,
+ * that the ETH_P_ values won't change in Linux; if they do, then:
+ *
+ * if we don't translate them in "pcap-linux.c", capture files
+ * won't necessarily be readable if captured on a system that
+ * defines ETH_P_ values that don't match these values;
+ *
+ * if we do translate them in "pcap-linux.c", that makes life
+ * unpleasant for the BPF code generator, as the values you test
+ * for in the kernel aren't the values that you test for when
+ * reading a capture file, so the fixup code run on BPF programs
+ * handed to the kernel ends up having to do more work.
+ *
+ * Add other values here as necessary, for handling packet types that
+ * might show up on non-Ethernet, non-802.x networks. (Not all the ones
+ * in the Linux "if_ether.h" will, I suspect, actually show up in
+ * captures.)
+ */
+#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
+#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
+
+#endif
diff --git a/include/pcap/usb.h b/include/pcap/usb.h
new file mode 100644
index 0000000..aa35122
--- /dev/null
+++ b/include/pcap/usb.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Basic USB data struct
+ * By Paolo Abeni <[email protected]>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.9 2008-12-23 20:13:29 guy Exp $
+ */
+
+#ifndef _PCAP_USB_STRUCTS_H__
+#define _PCAP_USB_STRUCTS_H__
+
+/*
+ * possible transfer mode
+ */
+#define URB_TRANSFER_IN 0x80
+#define URB_ISOCHRONOUS 0x0
+#define URB_INTERRUPT 0x1
+#define URB_CONTROL 0x2
+#define URB_BULK 0x3
+
+/*
+ * possible event type
+ */
+#define URB_SUBMIT 'S'
+#define URB_COMPLETE 'C'
+#define URB_ERROR 'E'
+
+/*
+ * USB setup header as defined in USB specification.
+ * Appears at the front of each Control S-type packet in DLT_USB captures.
+ */
+typedef struct _usb_setup {
+ u_int8_t bmRequestType;
+ u_int8_t bRequest;
+ u_int16_t wValue;
+ u_int16_t wIndex;
+ u_int16_t wLength;
+} pcap_usb_setup;
+
+/*
+ * Information from the URB for Isochronous transfers.
+ */
+typedef struct _iso_rec {
+ int32_t error_count;
+ int32_t numdesc;
+} iso_rec;
+
+/*
+ * Header prepended by linux kernel to each event.
+ * Appears at the front of each packet in DLT_USB_LINUX captures.
+ */
+typedef struct _usb_header {
+ u_int64_t id;
+ u_int8_t event_type;
+ u_int8_t transfer_type;
+ u_int8_t endpoint_number;
+ u_int8_t device_address;
+ u_int16_t bus_id;
+ char setup_flag;/*if !=0 the urb setup header is not present*/
+ char data_flag; /*if !=0 no urb data is present*/
+ int64_t ts_sec;
+ int32_t ts_usec;
+ int32_t status;
+ u_int32_t urb_len;
+ u_int32_t data_len; /* amount of urb data really present in this event*/
+ pcap_usb_setup setup;
+} pcap_usb_header;
+
+/*
+ * Header prepended by linux kernel to each event for the 2.6.31
+ * and later kernels; for the 2.6.21 through 2.6.30 kernels, the
+ * "iso_rec" information, and the fields starting with "interval"
+ * are zeroed-out padding fields.
+ *
+ * Appears at the front of each packet in DLT_USB_LINUX_MMAPPED captures.
+ */
+typedef struct _usb_header_mmapped {
+ u_int64_t id;
+ u_int8_t event_type;
+ u_int8_t transfer_type;
+ u_int8_t endpoint_number;
+ u_int8_t device_address;
+ u_int16_t bus_id;
+ char setup_flag;/*if !=0 the urb setup header is not present*/
+ char data_flag; /*if !=0 no urb data is present*/
+ int64_t ts_sec;
+ int32_t ts_usec;
+ int32_t status;
+ u_int32_t urb_len;
+ u_int32_t data_len; /* amount of urb data really present in this event*/
+ union {
+ pcap_usb_setup setup;
+ iso_rec iso;
+ } s;
+ int32_t interval; /* for Interrupt and Isochronous events */
+ int32_t start_frame; /* for Isochronous events */
+ u_int32_t xfer_flags; /* copy of URB's transfer flags */
+ u_int32_t ndesc; /* number of isochronous descriptors */
+} pcap_usb_header_mmapped;
+
+/*
+ * Isochronous descriptors; for isochronous transfers there might be
+ * one or more of these at the beginning of the packet data. The
+ * number of descriptors is given by the "ndesc" field in the header;
+ * as indicated, in older kernels that don't put the descriptors at
+ * the beginning of the packet, that field is zeroed out, so that field
+ * can be trusted even in captures from older kernels.
+ */
+typedef struct _usb_isodesc {
+ int32_t status;
+ u_int32_t offset;
+ u_int32_t len;
+ u_int8_t pad[4];
+} usb_isodesc;
+
+#endif
diff --git a/include/pcap/vlan.h b/include/pcap/vlan.h
new file mode 100644
index 0000000..41aa8c7
--- /dev/null
+++ b/include/pcap/vlan.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1 2008-08-06 07:45:00 guy Exp $
+ */
+
+#ifndef lib_pcap_vlan_h
+#define lib_pcap_vlan_h
+
+struct vlan_tag {
+ u_int16_t vlan_tpid; /* ETH_P_8021Q */
+ u_int16_t vlan_tci; /* VLAN TCI */
+};
+
+#define VLAN_TAG_LEN 4
+
+#endif
diff --git a/include/serial/main.h b/include/serial/main.h
new file mode 100644
index 0000000..3c7c2be
--- /dev/null
+++ b/include/serial/main.h
@@ -0,0 +1,625 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Modifed By Lu Qiuwen <[email protected]>
+ * Date: 2014-03-05
+ */
+
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#ifndef APP_STATS
+#define APP_STATS 1
+#endif
+
+#ifndef APP_STATS_PRINT
+#define APP_STATS_PRINT 1
+#endif
+
+#ifndef APP_WATCHDOG
+#define APP_WATCHDOG 1
+#define APP_STATS 1
+#endif
+
+/* Logical cores */
+#ifndef APP_MAX_SOCKETS
+#define APP_MAX_SOCKETS 2
+#endif
+
+#ifndef APP_MAX_STREAM_RECORD
+#define APP_MAX_STREAM_RECORD 1024
+#endif
+
+#ifndef APP_MAX_LCORES
+#define APP_MAX_LCORES RTE_MAX_LCORE
+#endif
+
+#ifndef APP_MAX_NIC_PORTS
+#define APP_MAX_NIC_PORTS RTE_MAX_ETHPORTS
+#endif
+
+#ifndef APP_MAX_RX_QUEUES_PER_NIC_PORT
+#define APP_MAX_RX_QUEUES_PER_NIC_PORT 128
+#endif
+
+#ifndef APP_MAX_TX_QUEUES_PER_NIC_PORT
+#define APP_MAX_TX_QUEUES_PER_NIC_PORT 128
+#endif
+
+#ifndef APP_MAX_IO_LCORES
+#define APP_MAX_IO_LCORES 16
+#endif
+#if (APP_MAX_IO_LCORES > APP_MAX_LCORES)
+#error "APP_MAX_IO_LCORES is too big"
+#endif
+
+#ifndef APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE
+#define APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE 16
+#endif
+
+#ifndef APP_MAX_NIC_TX_PORTS_PER_IO_LCORE
+#define APP_MAX_NIC_TX_PORTS_PER_IO_LCORE 16
+#endif
+#if (APP_MAX_NIC_TX_PORTS_PER_IO_LCORE > APP_MAX_NIC_PORTS)
+#error "APP_MAX_NIC_TX_PORTS_PER_IO_LCORE too big"
+#endif
+
+#ifndef APP_MAX_WORKER_LCORES
+#define APP_MAX_WORKER_LCORES 16
+#endif
+#if (APP_MAX_WORKER_LCORES > APP_MAX_LCORES)
+#error "APP_MAX_WORKER_LCORES is too big"
+#endif
+
+
+/* Mempools */
+#ifndef APP_DEFAULT_MBUF_SIZE
+//#define APP_DEFAULT_MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
+#define APP_DEFAULT_MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
+#endif
+
+#ifndef APP_DEFAULT_MEMPOOL_BUFFERS
+#define APP_DEFAULT_MEMPOOL_BUFFERS 8192 * 4
+#endif
+
+#ifndef APP_DEFAULT_MEMPOOL_CACHE_SIZE
+#define APP_DEFAULT_MEMPOOL_CACHE_SIZE 256
+#endif
+
+/* LPM Tables */
+#ifndef APP_MAX_LPM_RULES
+#define APP_MAX_LPM_RULES 1024
+#endif
+
+/* NIC RX */
+#ifndef APP_DEFAULT_NIC_RX_RING_SIZE
+#define APP_DEFAULT_NIC_RX_RING_SIZE 1024
+#endif
+
+/*
+ * RX and TX Prefetch, Host, and Write-back threshold values should be
+ * carefully set for optimal performance. Consult the network
+ * controller's datasheet and supporting DPDK documentation for guidance
+ * on how these parameters should be set.
+ */
+#ifndef APP_DEFAULT_NIC_RX_PTHRESH
+#define APP_DEFAULT_NIC_RX_PTHRESH 8
+#endif
+
+#ifndef APP_DEFAULT_NIC_RX_HTHRESH
+#define APP_DEFAULT_NIC_RX_HTHRESH 8
+#endif
+
+#ifndef APP_DEFAULT_NIC_RX_WTHRESH
+#define APP_DEFAULT_NIC_RX_WTHRESH 4
+#endif
+
+#ifndef APP_DEFAULT_NIC_RX_FREE_THRESH
+#define APP_DEFAULT_NIC_RX_FREE_THRESH 64
+#endif
+
+#ifndef APP_DEFAULT_NIC_RX_DROP_EN
+#define APP_DEFAULT_NIC_RX_DROP_EN 0
+#endif
+
+/* NIC TX */
+#ifndef APP_DEFAULT_NIC_TX_RING_SIZE
+#define APP_DEFAULT_NIC_TX_RING_SIZE 1024
+#endif
+
+/*
+ * These default values are optimized for use with the Intel(R) 82599 10 GbE
+ * Controller and the DPDK ixgbe PMD. Consider using other values for other
+ * network controllers and/or network drivers.
+ */
+#ifndef APP_DEFAULT_NIC_TX_PTHRESH
+#define APP_DEFAULT_NIC_TX_PTHRESH 36
+#endif
+
+#ifndef APP_DEFAULT_NIC_TX_HTHRESH
+#define APP_DEFAULT_NIC_TX_HTHRESH 0
+#endif
+
+#ifndef APP_DEFAULT_NIC_TX_WTHRESH
+#define APP_DEFAULT_NIC_TX_WTHRESH 0
+#endif
+
+#ifndef APP_DEFAULT_NIC_TX_FREE_THRESH
+#define APP_DEFAULT_NIC_TX_FREE_THRESH 0
+#endif
+
+#ifndef APP_DEFAULT_NIC_TX_RS_THRESH
+#define APP_DEFAULT_NIC_TX_RS_THRESH 0
+#endif
+
+/* Software Rings */
+#ifndef APP_DEFAULT_RING_RX_SIZE
+#define APP_DEFAULT_RING_RX_SIZE 1024
+#endif
+
+#ifndef APP_DEFAULT_RING_TX_SIZE
+#define APP_DEFAULT_RING_TX_SIZE 1024
+#endif
+
+/* Bursts */
+#ifndef APP_MBUF_ARRAY_SIZE
+#define APP_MBUF_ARRAY_SIZE 512
+#endif
+
+#ifndef APP_DEFAULT_BURST_SIZE_IO_RX_READ
+#define APP_DEFAULT_BURST_SIZE_IO_RX_READ 144
+#endif
+#if (APP_DEFAULT_BURST_SIZE_IO_RX_READ > APP_MBUF_ARRAY_SIZE)
+#error "APP_DEFAULT_BURST_SIZE_IO_RX_READ is too big"
+#endif
+
+#ifndef APP_DEFAULT_BURST_SIZE_IO_RX_WRITE
+#define APP_DEFAULT_BURST_SIZE_IO_RX_WRITE 144
+#endif
+#if (APP_DEFAULT_BURST_SIZE_IO_RX_WRITE > APP_MBUF_ARRAY_SIZE)
+#error "APP_DEFAULT_BURST_SIZE_IO_RX_WRITE is too big"
+#endif
+
+#ifndef APP_DEFAULT_BURST_SIZE_IO_TX_READ
+#define APP_DEFAULT_BURST_SIZE_IO_TX_READ 144
+#endif
+#if (APP_DEFAULT_BURST_SIZE_IO_TX_READ > APP_MBUF_ARRAY_SIZE)
+#error "APP_DEFAULT_BURST_SIZE_IO_TX_READ is too big"
+#endif
+
+#ifndef APP_DEFAULT_BURST_SIZE_IO_TX_WRITE
+#define APP_DEFAULT_BURST_SIZE_IO_TX_WRITE 144
+#endif
+#if (APP_DEFAULT_BURST_SIZE_IO_TX_WRITE > APP_MBUF_ARRAY_SIZE)
+#error "APP_DEFAULT_BURST_SIZE_IO_TX_WRITE is too big"
+#endif
+
+#ifndef APP_DEFAULT_BURST_SIZE_WORKER_READ
+#define APP_DEFAULT_BURST_SIZE_WORKER_READ 144
+#endif
+#if ((2 * APP_DEFAULT_BURST_SIZE_WORKER_READ) > APP_MBUF_ARRAY_SIZE)
+#error "APP_DEFAULT_BURST_SIZE_WORKER_READ is too big"
+#endif
+
+#ifndef APP_DEFAULT_BURST_SIZE_WORKER_WRITE
+#define APP_DEFAULT_BURST_SIZE_WORKER_WRITE 144
+#endif
+#if (APP_DEFAULT_BURST_SIZE_WORKER_WRITE > APP_MBUF_ARRAY_SIZE)
+#error "APP_DEFAULT_BURST_SIZE_WORKER_WRITE is too big"
+#endif
+
+/* Load balancing logic */
+#ifndef APP_DEFAULT_IO_RX_LB_POS
+#define APP_DEFAULT_IO_RX_LB_POS 29
+#endif
+#if (APP_DEFAULT_IO_RX_LB_POS >= 64)
+#error "APP_DEFAULT_IO_RX_LB_POS is too big"
+#endif
+
+
+/* From runtime.c */
+#ifndef APP_LCORE_IO_FLUSH
+#define APP_LCORE_IO_FLUSH 1000000
+#endif
+
+#ifndef APP_LCORE_WORKER_FLUSH
+#define APP_LCORE_WORKER_FLUSH 1000000
+#endif
+
+#define APP_IO_RX_DROP_ALL_PACKETS 0
+#define APP_WORKER_DROP_ALL_PACKETS 0
+#define APP_IO_TX_DROP_ALL_PACKETS 0
+
+#define APP_MAX_PORTS 32
+#define APP_MAX_QUEUE_PER_PORT 128
+
+#define APP_PKT_OVERHEAD (24) // preamble + SOF + IFG + CRC
+
+#ifdef RTE_LIBRTE_MLX4_PMD
+#define MAX_RX_QUEUE_PER_LCORE RTE_LIBRTE_MLX4_RX_RING_NUM
+#define MAX_TX_QUEUE_PER_PORT RTE_LIBRTE_MLX4_TX_RING_NUM
+#define MAX_QUEUE_PER_LCORE RTE_LIBRTE_MLX4_TX_RING_NUM
+#else
+#define MAX_RX_QUEUE_PER_LCORE 16
+#define MAX_TX_QUEUE_PER_PORT 16
+#define MAX_QUEUE_PER_LCORE 16
+#endif
+
+
+
+#ifndef APP_IO_RX_PREFETCH_ENABLE
+#define APP_IO_RX_PREFETCH_ENABLE 1
+#endif
+
+#ifndef APP_WORKER_PREFETCH_ENABLE
+#define APP_WORKER_PREFETCH_ENABLE 1
+#endif
+
+#ifndef APP_IO_TX_PREFETCH_ENABLE
+#define APP_IO_TX_PREFETCH_ENABLE 1
+#endif
+
+#if APP_IO_RX_PREFETCH_ENABLE
+#define APP_IO_RX_PREFETCH0(p) rte_prefetch0(p)
+#define APP_IO_RX_PREFETCH1(p) rte_prefetch1(p)
+#else
+#define APP_IO_RX_PREFETCH0(p)
+#define APP_IO_RX_PREFETCH1(p)
+#endif
+
+#if APP_WORKER_PREFETCH_ENABLE
+#define APP_WORKER_PREFETCH0(p) rte_prefetch0(p)
+#define APP_WORKER_PREFETCH1(p) rte_prefetch1(p)
+#else
+#define APP_WORKER_PREFETCH0(p)
+#define APP_WORKER_PREFETCH1(p)
+#endif
+
+#if APP_IO_TX_PREFETCH_ENABLE
+#define APP_IO_TX_PREFETCH0(p) rte_prefetch0(p)
+#define APP_IO_TX_PREFETCH1(p) rte_prefetch1(p)
+#else
+#define APP_IO_TX_PREFETCH0(p)
+#define APP_IO_TX_PREFETCH1(p)
+#endif
+
+#ifndef APP_PACKET_MODIFY_SMAC
+#define APP_PACKET_MODIFY_SMAC 0
+#endif
+
+#ifndef APP_PACKET_MODIFY_DMAC
+#define APP_PACKET_MODIFY_DMAC 0
+#endif
+
+#ifndef ENERGY_SLEEP_GEAR1_THRESHOLD
+#define ENERGY_SLEEP_GEAR1_THRESHOLD 100
+#endif
+
+#ifndef ENERGY_SLEEP_GEAR2_THRESHOLD
+#define ENERGY_SLEEP_GEAR2_THRESHOLD 1000
+#endif
+
+#ifndef ENERGY_MIN_ZERO_POLL_COUNT
+#define ENERGY_MIN_ZERO_POLL_COUNT 5
+#endif
+
+/************ END ***************/
+
+
+struct app_mbuf_array {
+ struct rte_mbuf *array[APP_MBUF_ARRAY_SIZE];
+ uint32_t n_mbufs;
+};
+
+enum app_lcore_type {
+ e_APP_LCORE_DISABLED = 0,
+ e_APP_LCORE_IO,
+ e_APP_LCORE_WORKER
+};
+
+enum app_map_type {
+ e_APP_MAP_TYPE_PORTMAP = 0,
+ e_APP_MAP_TYPE_IP
+};
+
+
+struct app_lcore_params_io {
+ /* I/O RX */
+ struct {
+ /* NIC */
+ struct {
+ uint8_t port;
+ uint8_t queue;
+ } nic_queues[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE];
+ uint32_t n_nic_queues;
+
+ /* Rings */
+ struct rte_ring *rings[APP_MAX_WORKER_LCORES];
+ uint32_t n_rings;
+
+ /* Internal buffers */
+ struct app_mbuf_array mbuf_in;
+ struct app_mbuf_array mbuf_out[APP_MAX_WORKER_LCORES];
+ uint8_t mbuf_out_flush[APP_MAX_WORKER_LCORES];
+
+ /* Stats */
+ uint32_t nic_queues_count[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE];
+ uint32_t nic_queues_iters[APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE];
+ uint32_t rings_count[APP_MAX_WORKER_LCORES];
+ uint32_t rings_iters[APP_MAX_WORKER_LCORES];
+ } rx;
+
+ /* I/O TX */
+ struct {
+ /* Rings */
+ struct rte_ring *rings[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES];
+
+ /* NIC */
+ uint8_t nic_ports[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE];
+ uint8_t nic_n_queues[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE];
+ uint32_t n_nic_ports;
+
+ /* Internal buffers */
+ struct app_mbuf_array mbuf_out[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE];
+ uint8_t mbuf_out_flush[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE];
+
+ /* Stats */
+ uint32_t rings_count[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES];
+ uint32_t rings_iters[APP_MAX_NIC_PORTS][APP_MAX_WORKER_LCORES];
+ uint32_t nic_ports_count[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE];
+ uint32_t nic_ports_iters[APP_MAX_NIC_TX_PORTS_PER_IO_LCORE];
+ } tx;
+};
+
+struct app_lcore_params_worker {
+ /* Rings */
+ struct rte_ring *rings_in[APP_MAX_IO_LCORES];
+ uint32_t n_rings_in;
+ struct rte_ring *rings_out[APP_MAX_NIC_PORTS];
+
+ /* LPM table */
+ struct rte_lpm *lpm_table;
+ uint32_t worker_id;
+
+ /* Internal buffers */
+ struct app_mbuf_array mbuf_in;
+ struct app_mbuf_array mbuf_out[APP_MAX_NIC_PORTS];
+ uint8_t mbuf_out_flush[APP_MAX_NIC_PORTS];
+
+ /* Stats */
+ uint32_t rings_in_count[APP_MAX_IO_LCORES];
+ uint32_t rings_in_iters[APP_MAX_IO_LCORES];
+ uint32_t rings_out_count[APP_MAX_NIC_PORTS];
+ uint32_t rings_out_iters[APP_MAX_NIC_PORTS];
+};
+
+struct app_lcore_params {
+ union {
+ struct app_lcore_params_io io;
+ struct app_lcore_params_worker worker;
+ };
+ enum app_lcore_type type;
+ struct rte_mempool *pool;
+} __rte_cache_aligned;
+
+struct app_lpm_rule {
+ uint32_t ip;
+ uint8_t depth;
+ uint8_t if_out;
+};
+
+// Callback func's pointer in pkt process.
+// **Modified By Luqiuwen<[email protected]>,At 2014-03-05 **
+
+struct app_pkt_callback_f {
+ int (*rx_pkt_process)(const unsigned char *data,int datalen,int port_in,int lcore);
+ int (*rx_pkt_process_dst)(const unsigned char *data,int datalen,int dst,int lcore);
+};
+
+
+// Forward Map
+struct app_rxtx_port_map {
+ uint32_t rx_port;
+ uint32_t tx_port[APP_MAX_NIC_PORTS];
+ uint32_t n_tx_port;
+};
+
+struct app_rxtx_stream {
+ uint32_t rx_port;
+ uint32_t tx_port;
+};
+
+struct app_watchdog_paras {
+
+ char * dev;
+ char * localip;
+ uint64_t threshold_bypass_pktloss;
+ uint64_t threshold_alert_pktloss;
+ uint64_t threshold_bypass_do;
+ uint64_t threshold_alert_do;
+ uint64_t threshold_normal_do;
+
+ int enable;
+};
+
+struct app_energy_paras {
+ int enable;
+ int min_zero_pull_count;
+ int sleep_gear1_threshold;
+ int sleep_gear2_threshold;
+
+ uint32_t wk_zero_rx_packet_count[APP_MAX_LCORES][APP_MAX_IO_LCORES];
+ uint32_t wk_idle_hint[APP_MAX_LCORES][APP_MAX_IO_LCORES];
+};
+
+struct app_statistics_paras {
+ int enable;
+ int sample_time;
+ int is_printmsg;
+};
+
+
+struct app_mempool_paras {
+ int mempool_buffers;
+ int mempool_mbuf_size;
+ int mempool_cache_size;
+};
+
+struct app_eal_paras {
+ int argc;
+ char **argv;
+};
+
+
+
+// **Done**
+
+enum hash_key_type
+{
+ KEY_TYPE_IS_IP, /* IP 5 tuples */
+ KEY_TYPE_IS_VLAN, /* L2 VLAN */
+};
+
+struct app_params {
+ /* lcore */
+ struct app_lcore_params lcore_params[APP_MAX_LCORES];
+
+ /* NIC */
+ uint8_t nic_rx_queue_mask[APP_MAX_NIC_PORTS][APP_MAX_RX_QUEUES_PER_NIC_PORT];
+ uint8_t nic_tx_port_mask[APP_MAX_NIC_PORTS];
+
+ /* mbuf pools */
+ struct rte_mempool *pools[APP_MAX_SOCKETS];
+
+ /* LPM tables */
+ struct rte_lpm *lpm_tables[APP_MAX_SOCKETS];
+ struct app_lpm_rule lpm_rules[APP_MAX_LPM_RULES];
+ uint32_t n_lpm_rules;
+
+ /* Port Forward Map Rules */
+ struct app_rxtx_port_map rxtx_port_map[APP_MAX_NIC_PORTS];
+ uint32_t n_rxtx_port_map;
+
+ /* Default Stream Record */
+
+ struct app_rxtx_stream rxtx_stream_record[APP_MAX_STREAM_RECORD];
+ uint32_t n_rxtx_stream;
+
+ /* Energy Management */
+ struct app_energy_paras energy;
+
+ /* Map Type: IP Forward or Port Map */
+ enum app_map_type map_type;
+
+ /* rings */
+ uint32_t nic_rx_ring_size;
+ uint32_t nic_tx_ring_size;
+ uint32_t ring_rx_size;
+ uint32_t ring_tx_size;
+
+ /* burst size */
+ uint32_t burst_size_io_rx_read;
+ uint32_t burst_size_io_rx_write;
+ uint32_t burst_size_io_tx_read;
+ uint32_t burst_size_io_tx_write;
+ uint32_t burst_size_worker_read;
+ uint32_t burst_size_worker_write;
+
+ /* load balancing */
+ uint8_t pos_lb;
+
+ /*I/O Core Number*/
+ uint8_t io_core_num;
+
+ /*Worker Core Number*/
+ uint8_t worker_core_num;
+
+ /* Hash key type(VLAN or 5 tuples)*/
+ uint8_t key_type;
+
+ /* mask of enabled ports */
+ uint32_t enabled_port_mask;
+
+ /* packet process function */
+ struct app_pkt_callback_f pkt_callback_f;
+
+ /* Watchlog */
+ struct app_watchdog_paras watchdog_paras;
+
+ /*stat*/
+ struct app_statistics_paras statistics;
+
+ /* mempool paras*/
+ struct app_mempool_paras mempool;
+
+ struct app_eal_paras eal;
+
+} __rte_cache_aligned;
+
+extern struct app_params app;
+
+//DEBUG:
+extern long pktprocess_pkt;
+extern long pktprocess_drop;
+
+int app_parse_args(int argc, char **argv);
+void app_print_usage(void);
+void app_init(void);
+int app_lcore_main_loop(void *arg);
+
+int app_get_nic_rx_queues_per_port(uint8_t port);
+int app_get_lcore_for_nic_rx(uint8_t port, uint8_t queue, uint32_t *lcore_out);
+int app_get_lcore_for_nic_tx(uint8_t port, uint32_t *lcore_out);
+int app_is_socket_used(uint32_t socket);
+uint32_t app_get_lcores_io_rx(void);
+uint32_t app_get_lcores_worker(void);
+void app_print_params(void);
+
+int app_launch_stats_print(void);
+void* app_statistics_print_loop();
+
+
+// Find the stream number by rx port and tx port.
+static inline int app_port2stream(uint32_t rx_port, uint32_t tx_port)
+{
+ int i = 0;
+ for(i = 0; i < (int)app.n_rxtx_stream ; i++) {
+ if(app.rxtx_stream_record[i].rx_port == rx_port &&
+ app.rxtx_stream_record[i].tx_port == tx_port)
+ return i;
+ }
+ return 0;
+}
+
+#endif
diff --git a/include/serial/nstat_common.h b/include/serial/nstat_common.h
new file mode 100644
index 0000000..98d4348
--- /dev/null
+++ b/include/serial/nstat_common.h
@@ -0,0 +1,58 @@
+
+#ifndef __SERIAL_MULTIPROCESS_NSTAT_COMMON_INCLUDE_H__
+#define __SERIAL_MULTIPROCESS_NSTAT_COMMON_INCLUDE_H__
+
+#include <rte_mbuf.h>
+#include <rte_common.h>
+#include <rte_atomic.h>
+#include <rte_rwlock.h>
+#include "main.h"
+
+#ifndef NSTAT_SHAREDMEMORY_SYMBOL
+#define NSTAT_SHAREDMEMORY_SYMBOL "serial_multiprocess_nstat_shdmem_sym_20141207"
+#endif
+
+#ifndef NSTAT_SHAREMEMORY_SUMMERIZE_SYMBOL
+#define NSTAT_SHAREMEMORY_SUMMERIZE_SYMBOL "serial_multiprocess_nstat_summerize_sym_20141207"
+#endif
+
+struct port_stat_t
+{
+ uint64_t rx_packets;
+ uint64_t rx_bytes;
+ uint64_t tx_packets;
+ uint64_t tx_bytes;
+
+ uint64_t rx_drop_packets;
+ uint64_t tx_drop_packets;
+};
+
+
+struct lcore_stat_t
+{
+ uint64_t packets;
+ uint64_t bytes;
+ uint64_t dropped;
+
+ uint64_t app_runtime;
+ uint64_t app_cycles;
+};
+
+struct stat_summerize_t
+{
+ rte_rwlock_t rwlock;
+ uint64_t dropped;
+};
+
+struct nstat_handle
+{
+ struct port_stat_t port[APP_MAX_NIC_PORTS];
+ struct lcore_stat_t worker_stat[APP_MAX_LCORES];
+ struct lcore_stat_t io_rx[APP_MAX_LCORES];
+ struct lcore_stat_t io_tx[APP_MAX_LCORES];
+
+ uint64_t stat_interval;
+};
+
+extern struct nstat_handle * nstat_common_handle;
+#endif
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/lib/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/lib/libMESA_prof_load.a b/lib/libMESA_prof_load.a
new file mode 100644
index 0000000..ee678ba
--- /dev/null
+++ b/lib/libMESA_prof_load.a
Binary files differ
diff --git a/lib/libMESA_prof_load.so b/lib/libMESA_prof_load.so
new file mode 100644
index 0000000..c640506
--- /dev/null
+++ b/lib/libMESA_prof_load.so
Binary files differ
diff --git a/logreader/.gitignore b/logreader/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/logreader/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/logreader/Makefile b/logreader/Makefile
new file mode 100644
index 0000000..8c2dc09
--- /dev/null
+++ b/logreader/Makefile
@@ -0,0 +1,44 @@
+
+ifeq ($(MODULES_STATS),0)
+ MODULES_CFAGS += -DAPP_STAT=0
+endif
+
+TARGET = dlogreader
+MAJOR_VERSION = 1
+SUB_VERSION = 1
+
+DPDK_INCLUDE = $(DPDK_ROOT)/$(DPDK_TARGET)/include
+DPDK_LIB_DIR = $(DPDK_ROOT)/$(DPDK_TARGET)/lib
+DPDK_LIB = $(wildcard ${DPDK_LIB_DIR}/*.a)
+DPDK_CONFIG = $(DPDK_INCLUDE)/rte_config.h
+
+DIR_INC = -I$(DPDK_INCLUDE) -I$(APP_ROOT)/include/MESA -I$(APP_ROOT)/include/serial
+DIR_SRC = ./
+DIR_OBJ = ./
+DIR_BIN = ./
+DIR_LIB = $(APP_ROOT)/lib/
+
+MODULES = -Wl,--start-group $(DPDK_LIB) -Wl,--end-group
+MODULES += $(APP_ROOT)/lib/libMESA_prof_load.a
+
+CC = gcc
+SRC = $(wildcard ${DIR_SRC}/*.c)
+OBJ = $(patsubst %.c,${DIR_OBJ}/%.o,$(notdir ${SRC}))
+LDFLAG += -lrt -lpthread
+CFLAGS += -g -fPIC ${OPTFLAGS} ${DIR_INC} -L${DIR_LIB} -std=gnu99 -include ${DPDK_CONFIG} $(MODULES_CFAGS)
+
+${TARGET}:${OBJ}
+ ${CC} ${LDFLAG} -o $@ ${OBJ} ${MODULES}
+${DIR_OBJ}/%.o:${DIR_SRC}/%.c
+ ${CC} ${CFLAGS} -c $< -o $@
+
+.PHONY:install clean
+
+all: $(TARGET)
+
+clean:
+ rm -f *.o
+install:
+ cp -f ${TARGET} ${INSTALL}
+distclean: clean
+ rm -f ${TARGET}
diff --git a/logreader/config.c b/logreader/config.c
new file mode 100644
index 0000000..9a9ac4e
--- /dev/null
+++ b/logreader/config.c
@@ -0,0 +1,746 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_string_fns.h>
+
+#include <assert.h>
+
+#include "main.h"
+#include "MESA_prof_load.h"
+
+struct app_params app;
+const char *conf_path[] = {
+ "conf/nl2fwd.conf",
+ ".nl2fwd.conf",
+ "~/.nl2fwd.conf",
+ "/etc/nl2fwd.conf",
+ "/usr/local/etc/nl2fwd.conf"};
+
+const int n_conf_path = 5;
+
+#ifndef APP_MAX_STRING
+#define APP_MAX_STRING 4096
+#endif
+
+void app_print_usage(void)
+{
+ printf("usages\n");
+}
+
+static int app_parse_conffile_rx(char * fcfg_path)
+{
+ int n_arg_rx = 0;
+ MESA_load_profile_int_def(fcfg_path,"rx_common","rx_count",&n_arg_rx,0);
+
+ if(n_arg_rx <= 0)
+ return -1;
+
+ for(int i = 0; i < n_arg_rx; i++)
+ {
+ struct app_lcore_params *lp;
+
+ char rx_section_name[APP_MAX_STRING];
+ sprintf(rx_section_name,"rx_%d",i);
+
+ int port,queue,lcore;
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"port",&port,0);
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"queue",&queue,0);
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"lcore",&lcore,0);
+
+ /* Enable port and queue for later initialization */
+ if ((port >= APP_MAX_NIC_PORTS) || (queue >= APP_MAX_RX_QUEUES_PER_NIC_PORT)) {
+ return -3;
+ }
+ if (app.nic_rx_queue_mask[port][queue] != 0) {
+ return -4;
+ }
+ app.enabled_port_mask |= 1 << port;
+ app.nic_rx_queue_mask[port][queue] = 1;
+
+ /* Check and assign (port, queue) to I/O lcore */
+ if (rte_lcore_is_enabled(lcore) == 0) {
+ return -5;
+ }
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -6;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_WORKER) {
+ return -7;
+ }
+ lp->type = e_APP_LCORE_IO;
+ for (int j = 0; j < lp->io.rx.n_nic_queues; j++) {
+ if ((lp->io.rx.nic_queues[j].port == port) &&
+ (lp->io.rx.nic_queues[j].queue == queue)) {
+ return -8;
+ }
+ }
+ if (lp->io.rx.n_nic_queues >= APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE) {
+ return -9;
+ }
+ lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].port = (uint8_t) port;
+ lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].queue = (uint8_t) queue;
+ lp->io.rx.n_nic_queues ++;
+
+#if 0
+ int tx_port_existed = 0;
+ for(int j = 0; j < lp->io.tx.n_nic_ports; j++) {
+ if (lp->io.tx.nic_ports[j] == (uint8_t) port) {
+ tx_port_existed = 1;
+ break;
+ }
+ }
+
+ if(!tx_port_existed) {
+ lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = port;
+ lp->io.tx.n_nic_ports ++;
+ app.enabled_port_mask |= 1 << (uint8_t)port;
+ app.nic_tx_port_mask[(uint8_t)port] = 1;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+#if 0
+static int app_parse_conffile_tx(char *fcfg_path)
+{
+
+ char tx_strbuf[APP_MAX_STRING];
+ char * parse_arg = tx_strbuf;
+ int tx_enable;
+
+ MESA_load_profile_int_def(fcfg_path,"tx","tx_enable",&tx_enable,0);
+ MESA_load_profile_string_def(fcfg_path,"tx","tx_port",parse_arg,
+ sizeof(char) * APP_MAX_STRING,"");
+ if(!tx_enable)
+ return 0;
+
+ for(parse_arg = strtok(parse_arg,",");
+ parse_arg != NULL; parse_arg = strtok(NULL,","))
+ {
+ int port = 0;
+ int ret = sscanf(parse_arg,"%d",&port);
+ if(ret <= 0)
+ return -1; //Parse Error.
+ if(port > APP_MAX_NIC_PORTS|| port < 0)
+ return -2; // Wrong Port number.
+
+ //Set TX Mask and Port Mask.
+ app.enabled_port_mask |= 1 << (uint8_t)port;
+ app.nic_tx_port_mask[(uint8_t)port] = 1;
+ }
+
+ return 0;
+}
+#endif
+
+static int app_parse_conffile_tx(char * fcfg_path)
+{
+ int n_arg_tx = 0;
+ MESA_load_profile_int_def(fcfg_path,"tx_common","tx_count",&n_arg_tx,0);
+
+ if(n_arg_tx <= 0)
+ return -1;
+
+ for(int i = 0; i < n_arg_tx; i++)
+ {
+ struct app_lcore_params *lp;
+ char tx_section_name[APP_MAX_STRING];
+ sprintf(tx_section_name,"tx_%d",i);
+
+ int port,lcore;
+ MESA_load_profile_int_def(fcfg_path,tx_section_name,"port",&port,0);
+ MESA_load_profile_int_def(fcfg_path,tx_section_name,"lcore",&lcore,0);
+
+ /* Enable port and queue for later initialization */
+ if (port >= APP_MAX_NIC_PORTS) {
+ return -3;
+ }
+ if (app.nic_tx_port_mask[port] != 0) {
+ return -4;
+ }
+ app.nic_tx_port_mask[port] = 1;
+
+ /* Check and assign (port, queue) to I/O lcore */
+ if (rte_lcore_is_enabled(lcore) == 0) {
+ return -5;
+ }
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -6;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_WORKER) {
+ return -7;
+ }
+ lp->type = e_APP_LCORE_IO;
+ for (int j = 0; j < lp->io.tx.n_nic_ports; j++) {
+ if (lp->io.tx.nic_ports[j] == port) {
+ return -8;
+ }
+ }
+ if (lp->io.tx.n_nic_ports >= APP_MAX_NIC_TX_PORTS_PER_IO_LCORE) {
+ return -9;
+ }
+ lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = (uint8_t) port;
+ lp->io.tx.n_nic_ports ++;
+
+ }
+
+ return 0;
+}
+
+static int app_parse_conffile_w(char *fcfg_path)
+{
+
+ char worker_buf[APP_MAX_STRING];
+ MESA_load_profile_string_def(fcfg_path,"worker","lcore",worker_buf,
+ sizeof(char) * APP_MAX_STRING,"");
+
+ char *p = worker_buf;
+
+ while (*p != 0) {
+ struct app_lcore_params *lp;
+ uint32_t lcore;
+
+
+ errno = 0;
+ lcore = strtoul(p, NULL, 0);
+ if ((errno != 0)) {
+ return -2;
+ }
+
+ /* Check and enable worker lcore */
+#if 0
+ if (rte_lcore_is_enabled(lcore) == 0) {
+ return -3;
+ }
+#endif
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -4;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_IO) {
+ return -5;
+ }
+ lp->type = e_APP_LCORE_WORKER;
+
+ p = strchr(p, ',');
+ if (p == NULL) {
+ break;
+ }
+ p++;
+ }
+
+ return 0;
+}
+
+
+
+static int app_parse_conffile_rxtx_paras(char * fcfg_path)
+{
+ MESA_load_profile_int_def(fcfg_path,"common","nic_rx_ring_size",
+ &app.nic_rx_ring_size,APP_DEFAULT_NIC_RX_RING_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","nic_tx_ring_size",
+ &app.nic_tx_ring_size,APP_DEFAULT_NIC_TX_RING_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","ring_rx_size",
+ &app.ring_rx_size, APP_DEFAULT_RING_RX_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","ring_tx_size",
+ &app.ring_tx_size, APP_DEFAULT_RING_TX_SIZE);
+
+
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_rx_read",
+ &app.burst_size_io_rx_read,APP_DEFAULT_BURST_SIZE_IO_RX_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_rx_write",
+ &app.burst_size_io_rx_write,APP_DEFAULT_BURST_SIZE_IO_RX_WRITE);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_tx_read",
+ &app.burst_size_io_tx_read,APP_DEFAULT_BURST_SIZE_IO_TX_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_tx_write",
+ &app.burst_size_io_tx_write,APP_DEFAULT_BURST_SIZE_IO_TX_WRITE);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_worker_read",
+ &app.burst_size_worker_read,APP_DEFAULT_BURST_SIZE_WORKER_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_worker_write",
+ &app.burst_size_worker_write,APP_DEFAULT_BURST_SIZE_WORKER_WRITE);
+
+
+ return 0;
+}
+
+
+
+static int app_parse_conffile_map(char * fcfg_path)
+{
+ int rx_port,tx_port;
+ int n_record = 0;
+
+ MESA_load_profile_int_def(fcfg_path,"map","n_map",&n_record,0);
+
+ if(n_record <= 0)
+ return 0;
+
+ char map_strbuf[APP_MAX_STRING];
+
+ for(int i = 0; i < n_record; i++)
+ {
+ char map_key[APP_MAX_STRING];
+
+ char * map_strbuf_p = map_strbuf;
+ char * port_str = NULL;
+
+ sprintf(map_key,"map_%d",i);
+
+ int ret = MESA_load_profile_string_def(fcfg_path,"map",map_key,map_strbuf,
+ sizeof(char) * APP_MAX_STRING,"");
+ if(ret < 0)
+ return -i;
+
+ port_str = strtok(map_strbuf_p, ",");
+ ret = sscanf(port_str,"%d",&rx_port);
+
+ if(ret <= 0)
+ return -i;
+
+ // Add Map Record for RX Port.
+ app.rxtx_port_map[i].rx_port = rx_port;
+
+ int j = 1;
+ for(j = 1,port_str = strtok(NULL, ",");
+ port_str != NULL;
+ port_str = strtok(NULL, ","))
+ {
+ if(sscanf(port_str,"%d",&tx_port) < 0)
+ return -i;
+ if(tx_port > APP_MAX_NIC_PORTS || tx_port < 0)
+ return -i;
+ if(app.nic_tx_port_mask[tx_port] != 1)
+ return -i;
+
+ // Add Map Record for TX Report
+ app.rxtx_port_map[i].tx_port[j-1] = tx_port;
+
+ }
+ app.rxtx_port_map[i].n_tx_port = (uint32_t)j;
+ (app.n_rxtx_port_map)++;
+
+ app.rxtx_stream_record[(uint8_t)app.n_rxtx_stream].rx_port = rx_port;
+ app.rxtx_stream_record[(uint8_t)app.n_rxtx_stream].tx_port = tx_port;
+ (app.n_rxtx_stream)++;
+
+ app.map_type = e_APP_MAP_TYPE_PORTMAP;
+
+ }
+
+ assert(app.n_rxtx_port_map == n_record);
+
+ return n_record;
+}
+
+static int app_parse_conffile_stat(char *fcfg_path)
+{
+ MESA_load_profile_int_def(fcfg_path,"stat","enable",&(app.statistics.enable),1);
+ MESA_load_profile_int_def(fcfg_path,"stat","print", &(app.statistics.is_printmsg),1);
+ MESA_load_profile_int_def(fcfg_path,"stat","sample_time", &(app.statistics.sample_time),1);
+
+ if(app.watchdog_paras.enable)
+ app.statistics.enable = 1;
+
+ return 0;
+}
+
+
+static int app_parse_conffile_mempool(char *fcfg_path)
+{
+
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_buffers",
+ &(app.mempool.mempool_buffers),APP_DEFAULT_MEMPOOL_BUFFERS);
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_mbuf_size",
+ &(app.mempool.mempool_mbuf_size),APP_DEFAULT_MBUF_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_cache_size",
+ &(app.mempool.mempool_cache_size),APP_DEFAULT_MEMPOOL_CACHE_SIZE);
+
+ return 0;
+}
+
+
+int app_parse_args(int argc, char **argv)
+{
+
+
+ app.enabled_port_mask = 0;
+ app.key_type = KEY_TYPE_IS_IP;
+
+ for(int i = 0; i < n_conf_path ; i++)
+ {
+ if(access(conf_path[i],R_OK) == 0) {
+
+ char * path = (char *)conf_path[i];
+
+ if(app_parse_conffile_rx(path) < 0)
+ return -1;
+ if(app_parse_conffile_tx(path) < 0)
+ return -2;
+ if(app_parse_conffile_w(path) < 0)
+ return -3;
+ if(app_parse_conffile_rxtx_paras(path) < 0)
+ return -4;
+ if(app_parse_conffile_stat(path) < 0)
+ return -5;
+ if(app_parse_conffile_map(path) < 0)
+ return -6;
+ if(app_parse_conffile_mempool(path) < 0)
+ return -7;
+ return 0;
+ }
+ }
+ return -9;
+}
+
+int
+app_get_nic_rx_queues_per_port(uint8_t port)
+{
+ uint32_t i, count;
+
+ if (port >= APP_MAX_NIC_PORTS) {
+ return -1;
+ }
+
+ count = 0;
+ for (i = 0; i < APP_MAX_RX_QUEUES_PER_NIC_PORT; i ++) {
+ if (app.nic_rx_queue_mask[port][i] == 1) {
+ count ++;
+ }
+ }
+
+ return count;
+}
+
+int
+app_get_lcore_for_nic_rx(uint8_t port, uint8_t queue, uint32_t *lcore_out)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t i;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_IO) {
+ continue;
+ }
+
+ for (i = 0; i < lp->rx.n_nic_queues; i ++) {
+ if ((lp->rx.nic_queues[i].port == port) &&
+ (lp->rx.nic_queues[i].queue == queue)) {
+ *lcore_out = lcore;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+app_get_lcore_for_nic_tx(uint8_t port, uint32_t *lcore_out)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t i;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_IO) {
+ continue;
+ }
+
+ for (i = 0; i < lp->tx.n_nic_ports; i ++) {
+ if (lp->tx.nic_ports[i] == port) {
+ *lcore_out = lcore;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+app_is_socket_used(uint32_t socket)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) {
+ continue;
+ }
+
+ if (socket == rte_lcore_to_socket_id(lcore)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+uint32_t
+app_get_lcores_io_rx(void)
+{
+ uint32_t lcore, count;
+
+ count = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->rx.n_nic_queues == 0)) {
+ continue;
+ }
+ count ++;
+ }
+ return count;
+}
+
+uint32_t
+app_get_lcores_worker(void)
+{
+ uint32_t lcore, count;
+
+ count = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ count ++;
+ }
+
+ if (count > APP_MAX_WORKER_LCORES) {
+ rte_panic("Algorithmic error (too many worker lcores)\n");
+ return 0;
+ }
+
+ return count;
+}
+
+void
+app_print_params(void)
+{
+ unsigned port, queue, lcore, i, j;
+
+ /* Print NIC RX configuration */
+ printf("NIC RX ports: ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ uint32_t n_rx_queues = app_get_nic_rx_queues_per_port((uint8_t) port);
+
+ if (n_rx_queues == 0) {
+ continue;
+ }
+
+ printf("%u (", port);
+ for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) {
+ if (app.nic_rx_queue_mask[port][queue] == 1) {
+ printf("%u ", queue);
+ }
+ }
+ printf(") ");
+ }
+ printf(";\n");
+
+ /* Print I/O lcore RX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp->rx.n_nic_queues == 0)) {
+ continue;
+ }
+
+ printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore));
+
+ printf("RX ports ");
+ for (i = 0; i < lp->rx.n_nic_queues; i ++) {
+ printf("(%u, %u) ",
+ (unsigned) lp->rx.nic_queues[i].port,
+ (unsigned) lp->rx.nic_queues[i].queue);
+ }
+ printf("; ");
+
+ printf("Output rings ");
+ for (i = 0; i < lp->rx.n_rings; i ++) {
+ printf("%p ", lp->rx.rings[i]);
+ }
+ printf(";\n");
+ }
+
+ /* Print worker lcore RX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Worker lcore %u (socket %u) ID %u: ",
+ lcore,
+ rte_lcore_to_socket_id(lcore),
+ (unsigned)lp->worker_id);
+
+ printf("Input rings ");
+ for (i = 0; i < lp->n_rings_in; i ++) {
+ printf("%p ", lp->rings_in[i]);
+ }
+
+ printf(";\n");
+ }
+
+ printf("\n");
+
+ /* Print NIC TX configuration */
+ printf("NIC TX ports: ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ if (app.nic_tx_port_mask[port] == 1) {
+ printf("%u ", port);
+ }
+ }
+ printf(";\n");
+
+ /* Print I/O TX lcore params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t n_workers = app_get_lcores_worker();
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp->tx.n_nic_ports == 0)) {
+ continue;
+ }
+
+ printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore));
+
+ printf("Input rings per TX port ");
+ for (i = 0; i < lp->tx.n_nic_ports; i ++) {
+ port = lp->tx.nic_ports[i];
+
+ printf("%u (", port);
+ for (j = 0; j < n_workers; j ++) {
+ printf("%p ", lp->tx.rings[port][j]);
+ }
+ printf(") ");
+
+ }
+
+ printf(";\n");
+ }
+
+ /* Print worker lcore TX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Worker lcore %u (socket %u) ID %u: \n",
+ lcore,
+ rte_lcore_to_socket_id(lcore),
+ (unsigned)lp->worker_id);
+
+ printf("Output rings per TX port ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ if (lp->rings_out[port] != NULL) {
+ printf("%u (%p) ", port, lp->rings_out[port]);
+ }
+ }
+
+ printf(";\n");
+ }
+
+ /* Rings */
+ printf("Ring sizes: NIC RX = %u; Worker in = %u; Worker out = %u; NIC TX = %u;\n",
+ (unsigned) app.nic_rx_ring_size,
+ (unsigned) app.ring_rx_size,
+ (unsigned) app.ring_tx_size,
+ (unsigned) app.nic_tx_ring_size);
+
+ /* Bursts */
+ printf("Burst sizes: I/O RX (rd = %u, wr = %u); Worker (rd = %u, wr = %u); I/O TX (rd = %u, wr = %u)\n",
+ (unsigned) app.burst_size_io_rx_read,
+ (unsigned) app.burst_size_io_rx_write,
+ (unsigned) app.burst_size_worker_read,
+ (unsigned) app.burst_size_worker_write,
+ (unsigned) app.burst_size_io_tx_read,
+ (unsigned) app.burst_size_io_tx_write);
+}
diff --git a/logreader/dlogreader b/logreader/dlogreader
new file mode 100755
index 0000000..e447e21
--- /dev/null
+++ b/logreader/dlogreader
Binary files differ
diff --git a/logreader/main.c b/logreader/main.c
new file mode 100644
index 0000000..17d99e1
--- /dev/null
+++ b/logreader/main.c
@@ -0,0 +1,22 @@
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nstat.h"
+
+const int __SERIAL_MULTIPROCESS_LOGREADER_VERSION_20141215__ = 0;
+
+extern int app_parse_args(int argc, char **argv);
+
+int main(int argc,char * argv[])
+{
+ app_parse_args(argc,argv);
+ nstat_init();
+ nstat_thread_entry();
+
+ nstat_destroy();
+ return 0;
+}
+
diff --git a/logreader/nstat.c b/logreader/nstat.c
new file mode 100644
index 0000000..a3e50f8
--- /dev/null
+++ b/logreader/nstat.c
@@ -0,0 +1,208 @@
+
+
+/* Stat Module in Serial-Multiprocess LogReader
+ Author : Lu Qiuwen <[email protected]>
+ Date : 2014-12-07
+
+*/
+
+
+#include <sys/mman.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "nstat.h"
+#include <main.h>
+
+#define SHM_FILEMODE 00777
+
+struct nstat_handle * nstat_common_handle = NULL;
+struct nstat_handle * nstat_handle_last = NULL;
+struct stat_summerize_t * nstat_summerize = NULL;
+
+void nstat_summerize_loop(struct nstat_handle * handle_now, struct nstat_handle * handle_past);
+void nstat_print_loop(struct nstat_handle * handle_now, struct nstat_handle * handle_past, FILE * fstream);
+
+#define TBPS (1ull * 1000 * 1000 * 1000 * 1000)
+#define GBPS (1ull * 1000 * 1000 * 1000)
+#define MBPS (1ull * 1000 * 1000)
+#define KBPS (1ull * 1000)
+
+static void unit_translate(uint64_t number, float * f_number, char * unit)
+{
+ if(number > TBPS)
+ {
+ *f_number = number * 1.0 / TBPS;
+ *unit = 'T';
+ }
+ else if(number > GBPS)
+ {
+ *f_number = number * 1.0 / GBPS;
+ *unit = 'G';
+ }
+ else if(number > MBPS)
+ {
+ *f_number = number * 1.0 / MBPS;
+ *unit = 'M';
+ }
+ else if(number > KBPS)
+ {
+ *f_number = number * 1.0 / KBPS;
+ *unit = 'K';
+ }
+ else
+ {
+ *f_number = number * 1.0;
+ *unit = ' ';
+ }
+}
+
+int nstat_init()
+{
+ int shm_fd = shm_open(NSTAT_SHAREDMEMORY_SYMBOL, O_RDWR, SHM_FILEMODE);
+ ftruncate(shm_fd, sizeof(struct nstat_handle));
+
+ void * shm_ptr = mmap(NULL, sizeof(struct nstat_handle), PROT_READ,
+ MAP_SHARED, shm_fd, 0);
+ if(shm_ptr == NULL)
+ {
+ printf("cannot create nstat shared memory");
+ exit(1);
+ }
+
+ nstat_common_handle = (struct nstat_handle *) shm_ptr;
+ nstat_handle_last = (struct nstat_handle *)malloc(sizeof(struct nstat_handle));
+
+ memset(nstat_handle_last,0,sizeof(struct nstat_handle));
+ nstat_handle_last->stat_interval = app.statistics.sample_time;
+
+ return 0;
+}
+
+int nstat_destroy()
+{
+ free(nstat_handle_last);
+ free(nstat_summerize);
+ return shm_unlink(NSTAT_SHAREDMEMORY_SYMBOL);
+}
+
+void * nstat_thread_entry()
+{
+ if(!app.statistics.enable)
+ return (void *)0;
+
+ while(1)
+ {
+ sleep(app.statistics.sample_time);
+ nstat_print_loop(nstat_common_handle,nstat_handle_last,stdout);
+ memcpy(nstat_handle_last,nstat_common_handle,sizeof(struct nstat_handle));
+ }
+
+}
+
+void nstat_print_loop(struct nstat_handle * handle_now, struct nstat_handle * handle_past, FILE * fstream)
+{
+ uint64_t calibration;
+
+ calibration = handle_now->stat_interval;
+
+ const char clr[] = {27,'[','2','J','\0'};
+ const char topleft[] = {27,'[','1',';','1','H','\0'};
+
+ fprintf(fstream,"%s%s",clr,topleft);
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ fprintf(fstream," Network Ports Statistics(LOGREADER) \n");
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+
+
+ for(int port_id = 0; port_id < APP_MAX_NIC_PORTS; port_id ++)
+ {
+ if((app.enabled_port_mask & (1 << port_id)) == 0)
+ continue;
+
+ uint64_t nic_rx_burst = (handle_now->port[port_id].rx_packets - handle_past->port[port_id].rx_packets) / calibration;
+ uint64_t nic_tx_burst = (handle_now->port[port_id].tx_packets - handle_past->port[port_id].tx_packets) / calibration;
+ uint64_t nic_rx_bytes = (handle_now->port[port_id].rx_bytes - handle_past->port[port_id].rx_bytes) / calibration;
+ uint64_t nic_tx_bytes = (handle_now->port[port_id].tx_bytes - handle_past->port[port_id].tx_bytes) / calibration;
+
+ float fps_rx,bps_rx,fps_tx,bps_tx;
+ char fps_rx_unit,bps_rx_unit,fps_tx_unit,bps_tx_unit;
+
+ unit_translate(nic_rx_burst, &fps_rx, &fps_rx_unit);
+ unit_translate(nic_tx_burst, &fps_tx, &fps_tx_unit);
+ unit_translate(nic_rx_bytes * 8, &bps_rx, &bps_rx_unit);
+ unit_translate(nic_tx_bytes * 8, &bps_tx, &bps_tx_unit);
+
+ fprintf(fstream,"Port %d\n",port_id);
+ fprintf(fstream,"RX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->port[port_id].rx_packets, handle_now->port[port_id].rx_bytes,
+ handle_now->port[port_id].rx_drop_packets, fps_rx,fps_rx_unit,bps_rx,bps_rx_unit);
+ fprintf(fstream,"TX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->port[port_id].tx_packets, handle_now->port[port_id].tx_packets,
+ handle_now->port[port_id].tx_drop_packets, fps_tx, fps_tx_unit, bps_tx, bps_tx_unit);
+ }
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ fprintf(fstream," Input/Output(I/O) Statistics \n");
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+
+ for(int lcore_id = 0; lcore_id < APP_MAX_LCORES; lcore_id++)
+ {
+ if(app.lcore_params[lcore_id].type == e_APP_LCORE_IO)
+ {
+ uint64_t io_rx_burst = (handle_now->io_rx[lcore_id].packets - handle_past->io_rx[lcore_id].packets) / calibration;
+ uint64_t io_tx_burst = (handle_now->io_tx[lcore_id].packets - handle_past->io_tx[lcore_id].packets) / calibration;
+ uint64_t io_rx_bytes = (handle_now->io_rx[lcore_id].bytes - handle_past->io_rx[lcore_id].bytes) /calibration;
+ uint64_t io_tx_bytes = (handle_now->io_tx[lcore_id].bytes - handle_past->io_tx[lcore_id].bytes) /calibration;
+
+ float fps_rx,bps_rx,fps_tx,bps_tx;
+ char fps_rx_unit,bps_rx_unit,fps_tx_unit,bps_tx_unit;
+
+ unit_translate(io_rx_burst, &fps_rx, &fps_rx_unit);
+ unit_translate(io_tx_burst, &fps_tx, &fps_tx_unit);
+ unit_translate(io_rx_bytes * 8, &bps_rx, &bps_rx_unit);
+ unit_translate(io_tx_bytes * 8, &bps_tx, &bps_tx_unit);
+
+ fprintf(fstream,"Core %d\n",lcore_id);
+ fprintf(fstream,"RX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->io_rx[lcore_id].packets , handle_now->io_rx[lcore_id].bytes,
+ handle_now->io_rx[lcore_id].dropped, fps_rx,fps_rx_unit,bps_rx,bps_rx_unit);
+ fprintf(fstream,"TX: packets%20lu | bytes:%20lu | dropped %10lu | fps:%7.2f%c | bps: %7.2f%c\n",
+ handle_now->io_tx[lcore_id].packets , handle_now->io_tx[lcore_id].bytes,
+ handle_now->io_tx[lcore_id].dropped, fps_tx,fps_tx_unit,bps_tx,bps_tx_unit);
+ }
+ }
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ fprintf(fstream," Worker(Client Process) Statistics \n");
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+
+ for(int lcore_id = 0; lcore_id < APP_MAX_LCORES; lcore_id++)
+ {
+ if(app.lcore_params[lcore_id].type == e_APP_LCORE_WORKER)
+ {
+ uint64_t runtime_delta = handle_now->worker_stat[lcore_id].app_runtime - handle_past->worker_stat[lcore_id].app_runtime;
+ uint64_t cycle_delta = handle_now->worker_stat[lcore_id].app_cycles - handle_past->worker_stat[lcore_id].app_cycles;
+ float runtime_per_cycle = 0;
+
+ if(likely(cycle_delta != 0))
+ runtime_per_cycle = (float)runtime_delta / cycle_delta;
+ else
+ runtime_per_cycle = 0;
+
+ fprintf(fstream,"WORKER %2d | packets %20lu | bytes: %20lu | dropped %10lu | runtime %7.2f\n",
+ lcore_id,
+ handle_now->worker_stat[lcore_id].packets,
+ handle_now->worker_stat[lcore_id].bytes,
+ handle_now->worker_stat[lcore_id].dropped,
+ runtime_per_cycle);
+ }
+ }
+
+ fprintf(fstream,"--------------------------------------------------------------------------------------------------------------------------------------\n");
+ return;
+}
diff --git a/logreader/nstat.h b/logreader/nstat.h
new file mode 100644
index 0000000..6611495
--- /dev/null
+++ b/logreader/nstat.h
@@ -0,0 +1,72 @@
+
+#ifndef __SERIAL_MULTIPROCESS_NSTAT_SERVER_INCLUDE_H__
+#define __SERIAL_MULTIPROCESS_NSTAT_SERVER_INCLUDE_H__
+
+#include <rte_mbuf.h>
+#include <nstat_common.h>
+
+// Get the Pkts total length.
+static inline uint64_t nstat_pktslen(struct rte_mbuf ** mbufs, unsigned nb_mbufs)
+{
+ uint64_t datalen = 0;
+ for(int i = 0; i < nb_mbufs; i++)
+ {
+ datalen += mbufs[i]->pkt.pkt_len + APP_PKT_OVERHEAD;
+ }
+
+ return datalen;
+}
+
+static inline void nstat_port_count_rx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t port_id)
+{
+ handle->port[port_id].rx_packets += nb_mbufs;
+ handle->port[port_id].rx_bytes += nstat_pktslen(mbufs, nb_mbufs);
+ return;
+}
+
+static inline void nstat_port_count_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t port_id)
+{
+ handle->port[port_id].tx_packets += nb_mbufs;
+ handle->port[port_id].tx_bytes += nstat_pktslen(mbufs, nb_mbufs);
+ return;
+}
+
+static inline void nstat_port_count_remove_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t port_id)
+{
+ handle->port[port_id].tx_packets -= nb_mbufs;
+ handle->port[port_id].tx_bytes -= nstat_pktslen(mbufs, nb_mbufs);
+ handle->port[port_id].tx_drop_packets += nb_mbufs;
+ return;
+}
+
+static inline void nstat_io_count_rx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_rx[lcore_id].packets += nb_mbufs;
+ handle->io_rx[lcore_id].bytes += nstat_pktslen(mbufs,nb_mbufs);
+ return;
+}
+
+static inline void nstat_io_count_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_tx[lcore_id].packets += nb_mbufs;
+ handle->io_tx[lcore_id].bytes += nstat_pktslen(mbufs,nb_mbufs);
+ return;
+}
+
+static inline void nstat_io_drop_rx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_rx[lcore_id].dropped += nb_mbufs;
+ return;
+}
+
+static inline void nstat_io_drop_tx(struct nstat_handle * handle, struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ handle->io_tx[lcore_id].dropped += nb_mbufs;
+ return;
+}
+
+int nstat_init();
+int nstat_destroy();
+void * nstat_thread_entry();
+
+#endif
diff --git a/support/MESA_prof_load/.gitignore b/support/MESA_prof_load/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/support/MESA_prof_load/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/support/MESA_prof_load/Makefile b/support/MESA_prof_load/Makefile
new file mode 100644
index 0000000..92de0be
--- /dev/null
+++ b/support/MESA_prof_load/Makefile
@@ -0,0 +1,13 @@
+#opt: OPTFLAGS = -O2
+#export OPTFLAGS
+
+.PHONY: all clean opt
+
+all:
+ cd src && $(MAKE)
+ cp lib/* $(APP_ROOT)/lib/
+clean:
+ cd src && $(MAKE) clean
+
+opt:
+ $(MAKE) all
diff --git a/support/MESA_prof_load/README b/support/MESA_prof_load/README
new file mode 100644
index 0000000..9db1906
--- /dev/null
+++ b/support/MESA_prof_load/README
@@ -0,0 +1,39 @@
+/*
+ *NAME:MESA_prof_load
+ *INTRODUCTION:general routines to read in profile.
+ *MAINTENANCED by [email protected]
+ -------------------------------------------------------------------------------------
+ *History:
+ CREATED by Song Xinbo, 2003-06-23
+
+ MODIFIED by tjx,2012-06-09
+
+ MODIFIED by tjx, 2013-05-23:
+ 1)add the write function
+ 2)strcpy and strncpy are replaced with memmove,because the strcpy and strncpy is not safe, they is not able to be used in overlap memory
+
+ MODIFIED by tjx,2013-06-19
+ 1)fixed the bug that get error string when nothing behind the '=' int the fucntion seek_key
+
+ MAINTENANCED by yw, 2014-03-24
+
+ MODIFIED by yw 2014-04-16
+ 1)strict inspection parameters, compatible with g++ 4.4.4
+
+ MODIFIED by yw 2014-08-11
+ 1)support the profile string which contained blank or tab character, for example, "pcap_rule= tcp port 80" will load to "tcp port 80"
+-------------------------------------------------------------------------------------
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/support/MESA_prof_load/demo/Makefile b/support/MESA_prof_load/demo/Makefile
new file mode 100644
index 0000000..2df4458
--- /dev/null
+++ b/support/MESA_prof_load/demo/Makefile
@@ -0,0 +1,34 @@
+#demo:MESA_prof_load.o demo.o
+# gcc -g MESA_prof_load.o demo.o -o demo -W
+#demo.o: demo.c
+# gcc -g -c demo.c -o demo.o -W
+
+#MESA_prof_load.o:MESA_prof_load.c
+# gcc -g -c MESA_prof_load.c -o MESA_prof_load.o -W
+#clean:
+# rm *.o demo
+VPATH=../inc/:../lib
+opt: OPTFLAGS = -O
+export OPTFLAGS
+
+CC = gcc
+CFLAGS = -Wall -Wstrict-prototypes
+CFLAGS += -g -fPIC
+CFLAGS += $(OPTFLAGS)
+LIB =-L../lib/
+INC = -I../inc/
+SOURCES = demo.c
+TEST_TARGETS = demo
+
+.PHONY: all clean opt
+
+all: $(TEST_TARGETS)
+
+opt:
+ $(MAKE) all
+
+$(TEST_TARGETS): demo.c MESA_prof_load.h libMESA_prof_load.a
+ $(CC) -o $@ $(CFLAGS) $(LIB) $(INC) $< -static -lMESA_prof_load
+
+clean:
+ rm -f $(TEST_TARGETS)
diff --git a/support/MESA_prof_load/demo/config.ini b/support/MESA_prof_load/demo/config.ini
new file mode 100644
index 0000000..cf6d895
--- /dev/null
+++ b/support/MESA_prof_load/demo/config.ini
@@ -0,0 +1,11 @@
+[CONFIG]
+port = 12345
+users= 4294967295
+#log_path=/home/taojianxi/
+log_path= tcp port 80
+#ips=10.0.6.1-99;
+#salaries = 8888.799805
+[DB_CONFIG]
+#username=ashi
+#maxpasswd_len = 4
+#salaries = 12983.099609
diff --git a/support/MESA_prof_load/demo/demo.c b/support/MESA_prof_load/demo/demo.c
new file mode 100644
index 0000000..4bebaad
--- /dev/null
+++ b/support/MESA_prof_load/demo/demo.c
@@ -0,0 +1,65 @@
+#include "MESA_prof_load.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int main(void)
+{
+ short int g_port;
+ unsigned int user_amount;
+ int ret;
+ //unsigned int ips[10]={0};
+ char path[256]={0};
+ if(MESA_load_profile_short_nodef("config.ini","CONFIG","port",&g_port)<0)
+ return -1;
+ else
+ printf("g_port:%d\n",g_port);
+ if((ret = MESA_load_profile_short_def("config.ini","CONFIG","port",&g_port,999))<0)
+ printf("g_port:%d,ret:%d\n",g_port,ret);
+
+ if(MESA_load_profile_uint_nodef("config.ini","CONFIG","users",&user_amount)<0)
+ return -1;
+ else
+ printf("user_amount:%u\n",user_amount);
+ MESA_load_profile_uint_def("config.ini","CONFIG","users",&user_amount,0);
+ printf("user_amount:%u\n",user_amount);
+ if((ret=MESA_load_profile_string_nodef("config.ini","CONFIG","log_path",path,256))<0)
+ return -1;
+ else
+ printf("path:%s,ret:%d\n",path,ret);
+ memset(path,0,256);
+ if((ret=MESA_load_profile_string_def("config.ini","CONFIG","log_path",path,256,"./logger"))>0)
+ printf("path:%s,ret:%d\n",path,ret);
+
+#if 0
+ if((ret=MESA_load_profile_ipset("config.ini","CONFIG","ips",10,ips))>0)
+ printf("ret:%d\n",ret);
+
+ if((ret = MESA_write_profile_int("./config.ini","CONFIG","port",12345))<0)
+ {
+ printf("write int failed!!\n");
+ }
+ if((ret = MESA_write_profile_string("./config.ini","CONFIG","log_path","/home/taojianxi/"))<0)
+ {
+ printf("write int failed!!\n");
+ }
+ if((ret = MESA_write_profile_float("./config.ini","CONFIG","salaries",8888.8))<0)
+ {
+ printf("write int failed!!\n");
+ }
+ if((ret = MESA_write_profile_string("./config.ini","DB_CONFIG","username","ashi"))<0)
+ {
+ printf("write int failed!!\n");
+ }
+ if((ret = MESA_write_profile_int("./config.ini","DB_CONFIG","maxpasswd_len",4))<0)
+ {
+ printf("write int failed!!\n");
+ }
+ if((ret = MESA_write_profile_float("./config.ini","DB_CONFIG","salaries",12983.10))<0)
+ {
+ printf("write int failed!!\n");
+ }
+
+#endif
+ return 0;
+}
diff --git a/support/MESA_prof_load/inc/MESA_prof_load.h b/support/MESA_prof_load/inc/MESA_prof_load.h
new file mode 100644
index 0000000..8d8c202
--- /dev/null
+++ b/support/MESA_prof_load/inc/MESA_prof_load.h
@@ -0,0 +1,179 @@
+#ifndef SLIB_LOADPROF_H
+#define SLIB_LOADPROF_H
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_int_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val, // [OUT] returned value
+ const int dval); // [IN] default value
+
+
+
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_int_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val); // [OUT] returned value
+
+
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_uint_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val, // [OUT] returned value
+ const unsigned int dval); // [IN] default value
+
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_uint_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val); // [OUT] returned value
+
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_short_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val, // [OUT] returned value
+ const short dval); // [IN] default value
+
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_short_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val); // [OUT] returned value
+
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t' '\n' '\r'
+//
+// Return:
+// >= 0 : length of val
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+
+int MESA_load_profile_string_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size); // [IN] buffer size(bytes)
+
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t' '\n' '\r'
+//
+// Return:
+// >= 0 : length of val
+// < 0 : error, str is set to default
+int MESA_load_profile_string_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size, // [IN] buffer size(bytes)
+ const char *dstr); // [IN] default string
+
+
+
+//read ips from config file
+//return :
+// >=0 : success,return the number of ip read from file successfully
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error,invalid ip
+
+#if 0
+int MESA_load_profile_ipset(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const size_t size, // [IN] the size of memory ips point,it must equel or greater than ip_num*sizeof(unsigned int)
+ unsigned int *ipset); // [OUT] return ipset network bytes order
+
+// Write the a int into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_int(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const int value); // [IN] the integer need write
+
+// Write the a float into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_float(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const float value); // [IN] the float need write
+
+// Write the a string into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_string(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const char *value); // [IN] the string need write
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifndef SLIB_LOADPROF_H */
diff --git a/support/MESA_prof_load/lib/libMESA_prof_load.a b/support/MESA_prof_load/lib/libMESA_prof_load.a
new file mode 100644
index 0000000..ee678ba
--- /dev/null
+++ b/support/MESA_prof_load/lib/libMESA_prof_load.a
Binary files differ
diff --git a/support/MESA_prof_load/lib/libMESA_prof_load.so b/support/MESA_prof_load/lib/libMESA_prof_load.so
new file mode 100644
index 0000000..c640506
--- /dev/null
+++ b/support/MESA_prof_load/lib/libMESA_prof_load.so
Binary files differ
diff --git a/support/MESA_prof_load/src/MESA_prof_load.a b/support/MESA_prof_load/src/MESA_prof_load.a
new file mode 100644
index 0000000..8d77dc2
--- /dev/null
+++ b/support/MESA_prof_load/src/MESA_prof_load.a
Binary files differ
diff --git a/support/MESA_prof_load/src/MESA_prof_load.c b/support/MESA_prof_load/src/MESA_prof_load.c
new file mode 100644
index 0000000..f316a03
--- /dev/null
+++ b/support/MESA_prof_load/src/MESA_prof_load.c
@@ -0,0 +1,806 @@
+// loadprof.c
+//
+// general routines to read in profile
+//
+// CREATED by Song Xinbo, 2003-06-23
+// MODIFIED by tjx,2012-06-09
+// MODIFIED by tjx, 2013-05-23:
+// add the write function
+// strcpy and strncpy are replaced with memmove,because the strcpy and strncpy is not safe, they is not able to be used in overlap memory
+// MODIFUED by tjx,2013-06-19
+// fixed the bug that get error string when nothing behind the '=' int the fucntion seek_key
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include "MESA_prof_load.h"
+
+#ifdef WIN32
+#define strncasecmp(x,y,z) memicmp(x,y,z)
+#endif
+#ifdef WIN32
+#define LINE_BREAK_TAG "\r\n"
+#else
+#define LINE_BREAK_TAG "\n"
+#endif
+
+#define MAX_PROF_LINE 1024 /* MAX bytes in a single line */
+#define MAX_IP_SIZE 16 /* MAX bytes in a single ip string*/
+#define COMMENT_CHAR '#' /* comments line prefix */
+#define SECTION_PRE '[' /* section name prefix */
+#define SECTION_POST ']' /* section name postfix */
+#define VALUE_SET '=' /* set key value operator */
+#define HYPHEN '-'
+#define TYPE_INT 1
+#define TYPE_FLOAT 2
+#define TYPE_STRING 3
+
+const char *PROF_LOAD_VERSION_20140811 = "1.0.20140811";
+//convert string to int
+//return :
+// 0,success
+// -1,failed
+static int str2int(const char *str, //[IN] the string need to convert
+ int *val)//[OUT] convert result
+{
+ int tmpval;
+ char *tmp_str=(char*)str;
+ char check_str[16]={0};
+ if(tmp_str==NULL||strlen(tmp_str)<=0||strlen(tmp_str)>11)
+ return -1;
+ tmpval=atoi(tmp_str);
+ sprintf(check_str,"%d",tmpval);
+ if(*tmp_str=='+')
+ tmp_str++;
+ if(strncasecmp(tmp_str,check_str,strlen(tmp_str))==0)
+ {
+ *val=tmpval;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+
+}
+//convert string to unsigned int
+//return :
+// 0,success
+// -1,failed
+static int str2uint(const char *str, //[IN] the string need to convert
+ unsigned int *val)//[OUT] convert result
+{
+ unsigned int tmpval;
+ char *tmp_str=(char *)str;
+ char check_str[16]={0};
+ if(tmp_str==NULL||strlen(tmp_str)<=0||strlen(tmp_str)>11||*tmp_str=='-')
+ return -1;
+ tmpval=(unsigned int)strtoul(str,NULL,0);
+ //tmpval=(unsigned int)atoi(tmp_str);
+ sprintf(check_str,"%u",tmpval);
+ if(*str=='+')
+ tmp_str++;
+ if(strncasecmp(tmp_str,check_str,strlen(tmp_str))==0)
+ {
+ *val=tmpval;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+
+}
+
+//cut off left and right space characters
+//include ' ', '\n', '\t', '\r'
+
+static void filter_lr_space(const char *str)
+{
+ char *ptr1,*ptr2;
+ int len = 0;
+ ptr1=ptr2=(char*)str;
+ if(str==NULL)
+ return;
+ while((*ptr2==' ')||(*ptr2=='\n')||(*ptr2=='\t')||(*ptr2=='\r'))
+ ptr2++;
+ len = strlen(ptr2); //
+ if(ptr1 != ptr2)
+ //strncpy(ptr1,ptr2,len);
+ //strcpy(ptr1,ptr2);
+ memmove(ptr1,ptr2,len+1);
+// ptr1[len] = '\0';
+ if(!(*ptr1))
+ return;
+ ptr2=(char*)ptr1+strlen(ptr1)-1;
+ while((*ptr2==' ')||(*ptr2=='\n')||(*ptr2=='\t')||(*ptr2=='\r'))
+ {
+ *ptr2='\0';
+ ptr2--;
+ }
+}
+
+
+//cut off all space characters
+//include ' ', '\n', '\t', '\r'
+static void filter_all_space(const char *str)
+{
+ char *ptr1,*ptr2;
+ if(str==NULL)
+ return;
+ ptr2=ptr1=(char*)str;
+ while(*ptr2)
+ {
+ if ((*ptr2==' ')||(*ptr2=='\t')||(*ptr2=='\r')||(*ptr2=='\n'))
+ {
+ ptr2++;
+ continue;
+ }
+ *ptr1++=*ptr2++;
+ }
+ *ptr1='\0';
+}
+
+
+// seek specified section in initialization file,
+// file read pointer at beginning of next line
+//
+// Return:
+// >= 0 : success
+// < 0 : error
+static int seek_section(
+ FILE *fp, // [IN] initialization file descriptor
+ const char *section) // [IN] section name in initialization file
+{
+ char line[MAX_PROF_LINE];
+ unsigned int i, j;
+ char *pc;
+
+ i = strlen(section);
+ while (NULL != fgets(line, MAX_PROF_LINE, fp)) {
+ pc = line;
+
+ filter_all_space(pc);
+ if(COMMENT_CHAR == *pc)
+ continue;
+ if (SECTION_PRE != *pc)
+ continue;
+ pc ++;
+ j = strlen(pc);
+ if (j < (i + 1) || SECTION_POST != pc[i])
+ continue;
+ if (strncasecmp(section, pc, i))
+ continue;
+ return 0;
+ }
+ return -1;
+}
+
+
+
+// seek specified key in initialization file
+//
+// Return:
+// >= 0 : success
+// < 0 : error
+static int seek_key(
+ FILE *fp, // [IN] initialization file descriptor
+ const char *key, // [IN] key name in initialization file
+ char *line) // [OUT] key value string
+{
+ unsigned int i, j;
+ char *pc;
+
+ i = strlen(key);
+ *line = '\0';
+ while (NULL != fgets(line, MAX_PROF_LINE, fp)) {
+ pc = line;
+// filter_all_space(pc);
+ filter_lr_space(pc);//add by yw 20140811
+ if (SECTION_PRE == *pc) // next section
+ return -1;
+ if(COMMENT_CHAR == *pc)
+ continue;
+ j = strlen(pc);
+ if (j < i)
+ continue;
+ if (strncasecmp(key, pc, i))
+ continue;
+ pc += i;
+ filter_lr_space(pc);//add by yw 20140811
+ if (VALUE_SET != *pc)
+ continue;
+ pc++;
+ filter_lr_space(pc);//add by yw 20140811
+ j = strlen(pc);
+// if (j < 1)
+// return 0;
+ memmove(line, pc, j);
+ line[j] = '\0';
+ return 0;
+ }
+ return -1;
+}
+
+//to get the corresponding value string which decided by section and key
+//Return:
+// =0,succuss
+// -1 file is null
+// -2 fopen file failed
+// -3 have no this section
+// -4 have this section, but have no this key
+static int get_key_str(const char *file, // [IN] initialization file path
+ const char * section, // [IN] section name in initialization file
+ const char* key, // [IN] keyword name in initialization file
+ char* ret_str) // [OUT] return the string matched to key
+{
+ FILE* fp;
+ if(file==NULL)
+ return -1;
+ if((fp = fopen(file,"r"))==NULL)
+ return -2;
+
+ if (seek_section(fp, section) < 0) {
+ fclose(fp);
+ return -3;
+ }
+ if (seek_key(fp, key, ret_str) <0) {
+ fclose(fp);
+ return -4;
+ }
+ fclose(fp);
+ return 0;
+}
+
+
+//split ip groups
+//return:
+// >=0,success
+// <0,failed
+static int split_ipgroups(
+ const char *ipgroups, // [IN] ipgroups string,eg 10.0.6.201-241
+ char*prep_part, // [OUT] the prep part,eg,10.0.6
+ unsigned int *min,// [OUT] eg,201
+ unsigned int *max)// [OUT] eg,241
+{
+ char max_str[4]={0};
+ char min_str[4]={0};
+ char *temp1=NULL;
+ char *temp2=NULL;
+ if(ipgroups==NULL||strlen(ipgroups)>19)
+ return -1;
+
+ temp1 = strrchr(ipgroups,'.');
+ if(temp1==NULL)
+ return -1;
+ temp1++;
+ memcpy(prep_part,ipgroups,(strlen(ipgroups)-strlen(temp1)));
+ if(strlen(prep_part)>12)
+ return -1;
+ temp2=strrchr(temp1,'-');
+ if(temp2==NULL)
+ {
+ if(strlen(temp1)>3)
+ return -1;
+ else
+ {
+ memcpy(min_str,temp1,strlen(temp1));
+ memcpy(max_str,temp1,strlen(temp1));
+ }
+ }
+ else
+ {
+ memcpy(min_str,temp1,(strlen(temp1)-strlen(temp2)));
+ if(strlen(min_str)>=4)
+ return -1;
+ temp2++;
+ if(strlen(temp2)>=4)
+ return -1;
+ memcpy(max_str,temp2,strlen(temp2));
+ }
+ if(str2uint(min_str,min)<0 || str2uint(max_str,max)<0)
+ return -1;
+ if(*min>*max)
+ {
+ *min = *min ^ *max;
+ *max = *min ^ *max;
+ *min = *min ^ *max;
+ }
+
+ if(*max>=255||*min>=255||*min<=0)
+ return -1;
+ return 0;
+
+}
+// get the length of file stream
+//Return:
+// >=0 length of file stream
+// <0 failed to get the length becase call fopen failed
+static int get_file_stream_len(const char *file)
+{
+ FILE *fp = NULL;
+ int len = 0;
+ if((fp = fopen(file,"a+b"))==NULL)
+ return -1;
+ fseek(fp,0L,SEEK_END);
+ len = (int)ftell(fp);
+ fclose(fp);
+ return len;
+}
+
+static void get_update_line(char *line,int line_size,const char *key,const void *val,int type)
+{
+ memset(line,0,line_size);
+ char *temp = NULL;
+ switch(type)
+ {
+ case TYPE_INT:
+ sprintf(line,"%s = %d%s",key,*(int*)val,LINE_BREAK_TAG);
+ break;
+ case TYPE_FLOAT:
+ sprintf(line,"%s = %f%s",key,*(float*)val,LINE_BREAK_TAG);
+ break;
+ case TYPE_STRING:
+ if(strlen(key)+strlen("=")+strlen(LINE_BREAK_TAG)+strlen((char *)val)+sizeof('\0')<(size_t)line_size )
+ sprintf(line,"%s=%s%s",key,(char*)val,LINE_BREAK_TAG);
+ else
+ {
+ temp = (char*)malloc(line_size - (strlen(key)+strlen("=")+strlen(LINE_BREAK_TAG)+strlen((char *)val)+sizeof('\0')) + 1);
+ memset(temp,0, line_size - (strlen(key)+strlen("=")+strlen(LINE_BREAK_TAG)+strlen((char *)val)+sizeof('\0')) + 1);
+ memcpy(temp,val,line_size - (strlen(key)+strlen("=")+strlen(LINE_BREAK_TAG)+strlen((char *)val)+sizeof('\0')));
+ sprintf("%s=%s%s",key,temp,LINE_BREAK_TAG);
+ }
+ free(temp);
+ temp = NULL;
+ break;
+ default:
+ break;
+ }
+}
+// Write the value in to specified position of the cofig file,
+// Return:
+// >= 0 : length of val
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+static int write_profile(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const void *value, // [IN] s pointer which point the value need write
+ const int value_type) // the type of value
+{
+ char *text = NULL;
+ char line[MAX_PROF_LINE] = {0};
+ char tmpline[MAX_PROF_LINE] = {0};
+ FILE *fp = NULL;
+ char *tmp = NULL;
+ int file_len = 0;
+ int line_len = 0;
+ int section_len = strlen(section);
+ int key_len = strlen(key);
+ int section_exist = 0;
+ int cur_text_offset = 0;
+ int finish = 0;//if update the value complete, finish is 1, or is 0
+ if(!key) return -1;
+ /*get the length of the file stream and alloc enough memory for update file stream*/
+ file_len = get_file_stream_len(file);
+ if((text = (char *)malloc(file_len + 2*MAX_PROF_LINE+ 1)) == NULL) return -1;
+ memset(text, 0 ,file_len + 2*MAX_PROF_LINE + 1);
+
+ /*get new file content, and fill into the memory pointed by text
+ *the new file content have three possibility:
+ * have no section, add section and key
+ * have section, but have no key, add key
+ * have section and key, modify the value
+ */
+ if((fp = fopen(file,"rb")) == NULL) {free(text);text=NULL;return -1;}
+ tmp = (char *)malloc(MAX_PROF_LINE);
+ while(NULL != fgets(line,MAX_PROF_LINE,fp))
+ {
+ line_len = strlen(line);
+ memcpy(tmp,line,line_len+1);
+ filter_all_space(tmp);
+ if(finish)// content update finished, thr rest of content would be memcpy directly
+ {
+ memcpy(text + cur_text_offset,line,line_len);
+ cur_text_offset += line_len;
+ continue;
+ }
+ if(*tmp == COMMENT_CHAR)// if this line is comment, memcpy directly
+ {
+ memcpy(text + cur_text_offset,line,line_len);
+ cur_text_offset += line_len;
+ continue;
+ }
+ if(*tmp == SECTION_PRE)// this is a section
+ {
+ if(section_exist == 0)//section is not exist, check this section is equle the section argument
+ {
+ if(memcmp(tmp+1,section,section_len)==0)
+ section_exist = 1;// the section haved be found in this file
+ }
+ else // the section had be found before, the key is not in this section, so add it in this section
+ {
+ get_update_line(tmpline,MAX_PROF_LINE,key,value,value_type);
+ memcpy(text+cur_text_offset,tmpline,strlen(tmpline));
+ cur_text_offset +=strlen(tmpline);
+ finish = 1;
+ }
+ memcpy(text + cur_text_offset,line,line_len);
+ cur_text_offset += line_len;
+ continue;
+ }
+ if(section_exist == 1)// only when section exist, compare the key
+ {
+ if(memcmp(tmp,key,key_len)==0)// have section and key, modigy the value
+ {
+ get_update_line(tmpline,MAX_PROF_LINE,key,value,value_type);
+ memcpy(text+cur_text_offset,tmpline,strlen(tmpline));
+ cur_text_offset +=strlen(tmpline);
+ finish = 1;
+ continue;
+ }
+ }
+#if 0
+ if(memcmp(tmp,key,key_len)==0)
+ {
+ if(section_exist != 1)
+ {
+ memcpy(text + cur_text_offset,line,line_len);
+ cur_text_offset += line_len;
+ }
+ else
+ {
+ get_update_line(tmpline,MAX_PROF_LINE,key,value,value_type);
+ memcpy(text+cur_text_offset,tmpline,strlen(tmpline));
+ cur_text_offset +=strlen(tmpline);
+ finish = 1;
+ }
+ continue;
+ }
+#endif
+
+ memcpy(text + cur_text_offset,line,line_len);
+ cur_text_offset += line_len;
+ }
+ free(tmp);
+ tmp = NULL;
+ fclose(fp);
+ /*reached the file end, but no finish, have two possibility:
+ * hanve no section
+ * have section, but have no key, and this section must be the last section in this file*/
+ if(!finish)
+ {
+ if(section_exist ==0)//have no section
+ {
+ /*add section*/
+ sprintf(tmpline,"[%s]%s",section,LINE_BREAK_TAG);
+ memcpy(text+cur_text_offset,tmpline,strlen(tmpline));
+ cur_text_offset +=strlen(tmpline);
+ }
+ /*add key*/
+ get_update_line(tmpline,MAX_PROF_LINE,key,value,value_type);
+ memcpy(text+cur_text_offset,tmpline,strlen(tmpline));
+ cur_text_offset += strlen(tmpline);
+ }
+ /*write a new file,the file name is not change*/
+ if((fp = fopen(file,"wb"))==NULL)
+ {
+ free(text);
+ text = NULL;
+ return -1;
+ }
+ fwrite(text,cur_text_offset,1,fp);
+ fclose(fp);
+ free(text);
+ text = NULL;
+ return 0;
+}
+
+
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_int_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val) // [OUT] returned value
+{
+ char line[MAX_PROF_LINE] = {0};
+// char *pc;
+ if(get_key_str(file,section,key,line)<0)
+ {
+ return -1;
+ }
+// pc = line;
+ if(str2int(line,val)<0)
+ return -2;
+ else
+ return 0;
+}
+// Read in specified integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_int_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ int *val, // [OUT] returned value
+ const int dval) // [IN] default value
+{
+ *val=dval;
+ return MESA_load_profile_int_nodef(file,section,key,val);
+
+}
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_uint_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val) // [OUT] returned value
+{
+ char line[MAX_PROF_LINE] = {0};
+// char *pc;
+
+ if(get_key_str(file,section,key,line)<0)
+ {
+ return -1;
+ }
+// pc = line;
+ if(str2uint(line,val)<0)
+ return -2;
+ else
+ return 0;
+}
+
+
+// Read in specified unsigned integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_uint_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ unsigned int *val, // [OUT] returned value
+ const unsigned int dval) // [IN] default value
+{
+ *val=dval;
+ return MESA_load_profile_uint_nodef(file,section,key,val);
+}
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error ,the val if out of range
+int MESA_load_profile_short_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val) // [OUT] returned value
+{
+ char line[MAX_PROF_LINE] = {0};
+// char *pc;
+ int temp;
+
+ if(get_key_str(file,section,key,line)<0)
+ {
+ return -1;
+ }
+// pc = line;
+
+ if(str2int(line,&temp)<0)
+ return -2;
+ if(temp>32767||temp<-32768)
+ return -2;
+ *val=(int)temp;
+ return 0;
+}
+
+
+
+// Read in specified short integer value
+//
+// Return:
+// 0 : success
+// < 0 : error, val is set to default
+int MESA_load_profile_short_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ short *val, // [OUT] returned value
+ const short dval) // [IN] default value
+{
+ *val=dval;
+ return MESA_load_profile_short_nodef(file,section,key,val);
+}
+
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t', '\r','\n'
+//
+// Return:
+// >= 0 : length of val
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+int MESA_load_profile_string_nodef(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size) // [IN] buffer size(bytes)
+{
+ char line[MAX_PROF_LINE] = {0};
+ int i;
+ char *pc;
+
+ if (0 == size) {
+ *str = '\0';
+ return 0;
+ }
+
+ if(get_key_str(file,section,key,line)<0)
+ {
+ return -1;
+ }
+ pc = line;
+
+ i = strlen(pc);
+ if( i == 0)
+ return 0;
+ if (i > size - 1)
+ i = size - 1; // truncate extra chars
+ memcpy(str, pc, i);
+ str[i] = '\0';
+ return i;
+}
+
+
+// Read in specified string value,
+// if value string is too long to return, extra chars truncated.
+// prefix/postfix space chars cutted,
+// space chars: ' ', '\t' '\n' '\r'
+//
+// Return:
+// >= 0 : length of val
+// < 0 : error, str is set to default
+int MESA_load_profile_string_def(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ char *str, // [OUT] returned string
+ const size_t size, // [IN] buffer size(bytes)
+ const char *dstr) // [IN] default string
+{
+ int len, t_len;
+ if (dstr == NULL)
+ {
+ *str = '\0';
+ }
+ else
+ {
+ t_len = strlen(dstr);
+ len = ((size-1)<t_len)?(size-1):t_len;
+ memcpy(str, dstr, len);
+ }
+ return MESA_load_profile_string_nodef(file,section,key,str,size);
+}
+
+
+
+//read ips from config file
+//return :
+// >=0 : success,return the number of ip read from file successfully
+// -1 : failed to get the key,may be have no thie section, key or the val which the key pointed error
+// -2 : error,invalid ip
+int MESA_load_profile_ipset(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const size_t size, // [IN] the number of unit memory ips pointed,a unit ha sizeof(unsigned int) bytes,(it means a unit has 4 bytes),
+ unsigned int *ipset) // [OUT] return ipset network bytes order
+{
+ char line[MAX_PROF_LINE];
+ char *ip_seg;
+ char ip[MAX_IP_SIZE];
+ char *saveptr;
+ char *pc;
+ char prep_part[MAX_IP_SIZE]={0};
+ unsigned int max_ip_suffix;
+ unsigned int min_ip_suffix;
+ unsigned int real_ip_num=0;
+
+ if(get_key_str(file,section,key,line)<0)
+ return -1;
+ pc = line;
+ memset(ipset,0,size);
+ while(1)
+ {
+ ip_seg=strtok_r(pc,";",&saveptr);
+ if(ip_seg==NULL)
+ break;
+ if(split_ipgroups(ip_seg,prep_part,&min_ip_suffix,&max_ip_suffix)<0)
+ {
+ return -2;
+ }
+ while(real_ip_num<(unsigned int)size && ((int)max_ip_suffix-(int)min_ip_suffix)>=0)
+ {
+ memset(ip,0,MAX_IP_SIZE);
+ sprintf(ip,"%s%u",prep_part,min_ip_suffix);
+ ipset[real_ip_num]=inet_addr(ip);
+ min_ip_suffix++;
+ real_ip_num++;
+ }
+ if(real_ip_num==(unsigned int)size)
+ {
+ break;
+ }
+
+
+ pc=NULL;
+ }
+ return real_ip_num;
+}
+// Write the a int into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_int(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const int value // [IN] the integer need write
+)
+{
+ int temp = value;
+ return write_profile(file,section,key,&temp,TYPE_INT);
+}
+
+// Write the a float into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_float(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const float value // [IN] the float need write
+)
+{
+ float temp = value;
+ return write_profile(file,section,key,&temp,TYPE_FLOAT);
+}
+// Write the a string into specified position of the config file,the position is decided by section and key
+// Return:
+// >= 0 : success
+// -1 : failed to write profile,maybe fopen failed, or malloc failed
+int MESA_write_profile_string(
+ const char *file, // [IN] initialization file path
+ const char *section, // [IN] section name in initialization file
+ const char *key, // [IN] keyword name in initialization file
+ const char *value // [IN] the string need write
+)
+{
+ const char *temp = value;
+ return write_profile(file,section,key,temp,TYPE_STRING);
+}
diff --git a/support/MESA_prof_load/src/Makefile b/support/MESA_prof_load/src/Makefile
new file mode 100644
index 0000000..89a9155
--- /dev/null
+++ b/support/MESA_prof_load/src/Makefile
@@ -0,0 +1,46 @@
+#demo:MESA_prof_load.o demo.o
+# gcc -g MESA_prof_load.o demo.o -o demo -W
+#demo.o: demo.c
+# gcc -g -c demo.c -o demo.o -W
+
+#MESA_prof_load.o:MESA_prof_load.c
+# gcc -g -c MESA_prof_load.c -o MESA_prof_load.o -W
+#clean:
+# rm *.o demo
+VPATH=../inc/
+opt: OPTFLAGS = -O
+export OPTFLAGS
+
+CC = gcc
+CFLAGS = -Wall -Wstrict-prototypes
+CFLAGS += -g -fPIC
+CFLAGS += $(OPTFLAGS)
+CFLAGS += $(INC)
+LIB =-L./
+INC = -I../inc/
+SOURCES = MESA_prof_load.c
+OBJS = $(SOURCES:.c=.o)
+TARGETSLIB = libMESA_prof_load.a
+TARGETSO = libMESA_prof_load.so
+
+.PHONY: all clean deps test opt
+
+all: $(TARGETSLIB) $(TARGETSO)
+
+opt:
+ $(MAKE) all
+
+clean:
+ rm -f $(TARGETSLIB) $(TARGETSO) *.o core core.*
+
+deps:
+ @$(CC) -MM $(SOURCES)
+
+$(TARGETSLIB): MESA_prof_load.o
+ ar -r $@ $^
+ cp $@ ../lib
+$(TARGETSO): MESA_prof_load.o
+ $(CC) -o $(TARGETSO) $(CFLAGS) MESA_prof_load.o -shared
+ cp $@ ../lib
+
+MESA_prof_load.o: MESA_prof_load.c MESA_prof_load.h
diff --git a/support/Makefile b/support/Makefile
new file mode 100644
index 0000000..655a87e
--- /dev/null
+++ b/support/Makefile
@@ -0,0 +1,19 @@
+export OPTFLAGS
+export QUITE
+export MODULES_VLAN_DMAC
+export MODULES_ENERGY
+export MODULES_STATS
+export MODULES_WATCHDOG
+
+export DPDK_ROOT
+export DPDK_TARGET
+export APP_ROOT
+export INSTALL
+export LIB_INSTALL
+
+.PHONY:all install clean
+
+all:
+ cd MESA_prof_load && $(MAKE)
+clean:
+ cd MESA_prof_load && $(MAKE) clean
diff --git a/test/.gitignore b/test/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/test/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..30100c1
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,10 @@
+
+.PHONY: all clean distclean
+
+all:
+ gcc -o test test.c -lnl2fwd
+clean:
+ rm -f *.o
+distclean:
+ rm -f test
+
diff --git a/test/conf/nl2fwd.conf.bak b/test/conf/nl2fwd.conf.bak
new file mode 100644
index 0000000..4b00a4f
--- /dev/null
+++ b/test/conf/nl2fwd.conf.bak
@@ -0,0 +1,54 @@
+[eal]
+enable_spec_memc=0
+n_mem_channel=4
+[common]
+nic_rx_ring_size=4096
+nic_tx_ring_size=4096
+ring_rx_size=65536
+ring_tx_size=65536
+burst_size_io_rx_read=144
+burst_size_io_rx_write=144
+burst_size_io_tx_read=144
+burst_size_io_tx_write=144
+burst_size_worker_read=144
+burst_size_worker_write=144
+[rx_common]
+rx_count=2
+[rx_0]
+port=0
+queue=0
+lcore=1
+[rx_1]
+port=3
+queue=0
+lcore=2
+[tx]
+tx_enable=1
+tx_port=0,3
+[worker]
+lcore=0
+[map]
+n_map=2
+map_0=0,3
+map_1=3,0
+[watchdog]
+enable=1
+localip=192.168.0.198
+dev=eth5
+threshold_bypass_lostpkt=20000
+threshold_alert_lostpkt=10000
+threshold_bypass_do=10
+threshold_alert_do=10
+threshold_normal_do=10
+[stat]
+enable=1
+print=1
+sample_time=1
+[mempool]
+mempool_buffers=524288
+#mempool_mbuf_size=
+#mempool_cache_size=4096
+[vlan]
+n_rules=1
+0_port=0
+0_mac=FF:FF:FF:FF:FF:FF
diff --git a/test/nl2fwd.h b/test/nl2fwd.h
new file mode 100644
index 0000000..5277de0
--- /dev/null
+++ b/test/nl2fwd.h
@@ -0,0 +1,19 @@
+
+/* Header file of new_l2fwd_lib in Load Balance Model.
+ * Autuor : Lu Qiuwen
+ * Date : 2014-03-04
+ */
+
+
+#ifndef __L2FWD_LIB_INCLUDE__
+#define __L2FWD_LIB_INCLUDE__
+
+int dpdk_send_packet_dst(unsigned char *data, int datalen, int dst);
+int dpdk_send_packet_port(const unsigned char *data, int datalen, int port);
+int dpdk_init(int argc, char **argv);
+int dpdk_run();
+int dpdk_register_callfunc(int (*func)(const unsigned char *data,int datalen,int port_in,int lcore));
+int dpdk_register_callfunc_dst(int (*func)(const unsigned char *data,int datalen,int dst,int lcore));
+
+
+#endif
diff --git a/test/r2 b/test/r2
new file mode 100644
index 0000000..4c15a9b
--- /dev/null
+++ b/test/r2
@@ -0,0 +1 @@
+./r3 &> /dev/null &
diff --git a/test/r3 b/test/r3
new file mode 100644
index 0000000..8f4b5d5
--- /dev/null
+++ b/test/r3
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+while [ 1 ]; do
+ papp_num=`ps -ef|grep ./test|grep -v grep | wc -l`
+ if [ $papp_num -lt 1 ]
+ then
+ ulimit -c unlimited
+ #./jz -c 0x7 -b 00:04:00.1 -b 00:04:00.2 -b 00:04:00.3 -b 00:04:00.4 &>/dev/null
+ ./test -c 0x7 -b 00:04:00.1 -b 00:04:00.2 -b 00:04:00.3 -b 00:04:00.4 &> log.txt
+ echo program crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log
+ fi
+ sleep 35
+done
diff --git a/test/test.c b/test/test.c
new file mode 100644
index 0000000..bff0a80
--- /dev/null
+++ b/test/test.c
@@ -0,0 +1,24 @@
+#include "nl2fwd.h"
+
+#include <stdio.h>
+
+
+int l2fwd_data(const unsigned char *data,int datalen,int dst,int lcore)
+{
+ data = 0;
+ datalen = 0;
+
+ dst = 0;
+ lcore = 0;
+
+ return 1;
+}
+
+int main(int argc,char **argv)
+{
+ dpdk_register_callfunc_dst(l2fwd_data);
+ dpdk_init(argc,argv);
+ dpdk_run();
+
+ return 0;
+}
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/tools/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..3341143
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,6 @@
+
+.PHONY: install
+
+install:
+ cp dpdk_mlx4 /etc/init.d/
+ cp *.sh $(APP_ROOT)/test/
diff --git a/tools/dpdk_mlx4 b/tools/dpdk_mlx4
new file mode 100755
index 0000000..4da72e3
--- /dev/null
+++ b/tools/dpdk_mlx4
@@ -0,0 +1,171 @@
+#!/bin/bash
+#
+# dpdk-kernel Start up the DPDK configuration and insert kernel model
+#
+### END INIT INFO
+
+prog=dpdk_mlx4
+
+export RTE_SDK=/root/DPDK
+export RTE_TARGET=x86_64-default-linuxapp-gcc
+
+HUGEPAGE_MEM=25000
+
+load_mlx4_core_module()
+{
+ /sbin/insmod /lib/modules/$(uname -r)/kernel/drivers/net/mlx4/mlx4_core.ko
+ /sbin/insmod /lib/modules/$(uname -r)/kernel/drivers/net/mlx4/mlx4_en.ko
+}
+
+remove_mlx4_uio_module()
+{
+ echo "Unloading any existing DPDK UIO module"
+ /sbin/lsmod | grep -s mlx4_uio > /dev/null
+ if [ $? -eq 0 ] ; then
+ sudo /sbin/rmmod mlx4_uio
+ fi
+}
+
+remove_mlx4_en_module()
+{
+ echo "Unloading any existing MLX4 EN module"
+ /sbin/lsmod | grep -s mlx4_en > /dev/null
+ if [ $? -eq 0 ] ; then
+ sudo /sbin/rmmod mlx4_en
+ fi
+}
+
+remove_mlx4_core_module()
+{
+ echo "Unloading any existing MLX4 CORE module"
+ /sbin/lsmod | grep -s mlx4_core > /dev/null
+ if [ $? -eq 0 ] ; then
+ sudo /sbin/rmmod mlx4_core
+ fi
+}
+
+load_mlx4_uio_module()
+{
+ if [ ! -f $RTE_SDK/$RTE_TARGET/kmod/mlx4_uio.ko ];then
+ echo "## ERROR: Target does not have the DPDK UIO Kernel Module."
+ echo " To fix, please try to rebuild target."
+ return
+ fi
+
+ remove_mlx4_uio_module
+ remove_mlx4_en_module
+ remove_mlx4_core_module
+
+ /sbin/lsmod | grep -s uio > /dev/null
+ if [ $? -ne 0 ] ; then
+ if [ -f /lib/modules/$(uname -r)/kernel/drivers/uio/uio.ko ] ; then
+ echo "Loading uio module"
+ sudo /sbin/modprobe uio
+ fi
+ fi
+
+ # UIO may be compiled into kernel, so it may not be an error if it can't
+ # be loaded.
+
+ echo "Loading DPDK UIO module"
+ sudo /sbin/insmod $RTE_SDK/$RTE_TARGET/kmod/mlx4_uio.ko intr_mode="msix"
+ if [ $? -ne 0 ] ; then
+ echo "## ERROR: Could not load kmod/mlx4_uio.ko."
+ quit
+ fi
+}
+
+remove_mnt_huge()
+{
+ echo "Unmounting /mnt/huge and removing directory"
+ grep -s '/mnt/huge' /proc/mounts > /dev/null
+ if [ $? -eq 0 ] ; then
+ sudo umount /mnt/huge
+ fi
+
+ if [ -d /mnt/huge ] ; then
+ sudo rm -R /mnt/huge
+ fi
+}
+
+create_mnt_huge()
+{
+ echo "Creating /mnt/huge and mounting as hugetlbfs"
+ sudo mkdir -p /mnt/huge
+
+ grep -s '/mnt/huge' /proc/mounts > /dev/null
+ if [ $? -ne 0 ] ; then
+ sudo mount -t hugetlbfs nodev /mnt/huge
+ fi
+}
+
+clear_huge_pages()
+{
+ echo > .echo_tmp
+ for d in /sys/devices/system/node/node? ; do
+ echo "echo 0 > $d/hugepages/hugepages-2048kB/nr_hugepages" >> .echo_tmp
+ done
+ echo "Removing currently reserved hugepages"
+ sudo sh .echo_tmp
+ rm -f .echo_tmp
+
+ remove_mnt_huge
+}
+
+#
+# Creates hugepages.
+#
+set_non_numa_pages()
+{
+ clear_huge_pages
+
+ echo "echo $HUGEPAGE_MEM > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages" > .echo_tmp
+ echo "Reserving hugepages"
+ sudo sh .echo_tmp
+ rm -f .echo_tmp
+ create_mnt_huge
+}
+
+
+
+
+start()
+{
+ echo -n $"Starting $prog: "
+
+ load_mlx4_uio_module
+ set_non_numa_pages
+
+ return 0
+}
+
+stop()
+{
+ echo -n $"Stopping $prog: "
+ remove_mlx4_uio_module
+ clear_huge_pages
+ load_mlx4_core_module
+
+ return 0
+}
+
+restart() {
+ stop
+ start
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ restart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|restart}"
+ RETVAL=2
+esac
+exit $RETVAL
diff --git a/tools/drv_monitor.sh b/tools/drv_monitor.sh
new file mode 100755
index 0000000..728c877
--- /dev/null
+++ b/tools/drv_monitor.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+sleep_period=1
+worker_proc_name="start"
+driver_proc_name="driver"
+log_path="./MONITOR.log"
+
+get_worker_proc_num()
+{
+ num=`ps -ef | grep $worker_proc_name | grep -v grep | wc -l`
+ return $num
+}
+
+get_driver_proc_num()
+{
+ num=`ps -ef | grep $driver_proc_name | grep -v grep | wc -l`
+ return $num
+}
+
+while true
+do
+ sleep $sleep_period
+
+ get_worker_proc_num
+ nb_worker=$?
+ get_driver_proc_num
+ nb_driver=$?
+
+ if [ $nb_worker -ge 1 ] && [ $nb_driver -eq 0 ]
+ then
+ pid=$(ps -ef | grep $worker_proc_name | grep -v grep | awk '{print $2}')
+ kill $pid
+ fi
+done
+
diff --git a/tools/drv_start.sh b/tools/drv_start.sh
new file mode 100755
index 0000000..723118a
--- /dev/null
+++ b/tools/drv_start.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+DRV_PROG=./driver
+DRV_MONITOR=./drv_monitor.sh
+
+sh $DRV_MONITOR &
+
+while [ 1 ]; do
+ count=`ls -l core.* |wc -l`
+ echo $count
+ if [ $count -lt 6 ]
+ then
+ echo "set unlimited"
+ ulimit -c unlimited
+ else
+ ulimit -c 0
+ fi
+
+ $DRV_PROG
+
+# ./start >> start.`date +"%Y-%m-%d_%H-%M"`.log
+ echo $DRV_PROG crashed, restart at `date +"%w %Y/%m/%d, %H:%M:%S"` >> RESTART.log
+ sleep 5
+done
+
+#./start
+#echo program crashed, reboot at `date +"%w %Y/%m/%d, %H:%M:%S"` >> REBOOT.log
+#reboot
diff --git a/worker/.gitignore b/worker/.gitignore
new file mode 100644
index 0000000..75fb413
--- /dev/null
+++ b/worker/.gitignore
@@ -0,0 +1,8 @@
+*.o
+*.ko
+*.swp
+*.tmp
+*.log
+tags
+.tags
+
diff --git a/worker/Makefile b/worker/Makefile
new file mode 100644
index 0000000..db56360
--- /dev/null
+++ b/worker/Makefile
@@ -0,0 +1,51 @@
+APP_MODULES_VLAN_DMAC = 0
+
+ifeq ($(APP_MODULES_VLAN_DMAC),1)
+ MODULES_CFLAG += -DAPP_PACKET_MODIFY_DMAC=1
+endif
+
+MAJOR_VERSION = 1
+SUB_VERSION = 1
+
+DPDK_INCLUDE = $(DPDK_ROOT)/$(DPDK_TARGET)/include
+DPDK_LIB_DIR = $(DPDK_ROOT)/$(DPDK_TARGET)/lib
+DPDK_LIB = $(wildcard ${DPDK_LIB_DIR}/*.a)
+DPDK_CONFIG = $(DPDK_INCLUDE)/rte_config.h
+
+DIR_INC = -I$(DPDK_INCLUDE) -I$(APP_ROOT)/include/MESA -I$(APP_ROOT)/include/serial
+DIR_SRC = ./
+DIR_OBJ = ./
+DIR_BIN = ./
+DIR_LIB = $(APP_ROOT)/lib/
+
+MODULES = $(DPDK_LIB)
+MODULES += $(APP_ROOT)/lib/libMESA_prof_load.a
+
+SRC = $(wildcard ${DIR_SRC}/*.c)
+OBJ = $(patsubst %.c,%.o,$(notdir ${SRC}))
+
+BSNAME = libnl2fwd.so
+TARGET = libnl2fwd.so.${MAJOR_VERSION}.${SUB_VERSION}
+SONAME = libnl2fwd.so.${MAJOR_VERSION}
+SOFILE = ${DIR_BIN}/${TARGET}
+LDFLAG = -lpthread -lrt -lm -lpcap -lnet
+
+CC = gcc
+CFLAGS = -g -fPIC ${OPTFLAGS} ${DIR_INC} -L${DIR_LIB} -std=gnu99 -include ${DPDK_CONFIG} ${MODULES_CFLAG}
+
+${SOFILE}:${OBJ}
+ ${CC} --shared --fPIC -Wl,-soname,${SONAME} ${ATT_LIB} ${LDFLAG} -o $@ -Wl,--whole-archive ${OBJ} ${MODULES} -Wl,--no-whole-archive
+${DIR_OBJ}/%.o:${DIR_SRC}/%.c
+ ${CC} ${CFLAGS} -c $< -o $@
+
+.PHONY:install clean
+
+install:
+ cp -f ${TARGET} ${LIB_INSTALL}
+ -ln -s -f ${LIB_INSTALL}/${TARGET} ${LIB_INSTALL}/${SONAME}
+ -ln -s -f ${LIB_INSTALL}/${SONAME} ${LIB_INSTALL}/${BSNAME}
+ -ldconfig
+clean:
+ rm -f *.o
+distclean: clean
+ rm -f $(TARGET)
diff --git a/worker/apt.c b/worker/apt.c
new file mode 100644
index 0000000..c3e58f7
--- /dev/null
+++ b/worker/apt.c
@@ -0,0 +1,201 @@
+
+///////////////////////////////////////////////////////////////////
+/// Copyright(C) Institude of Information Engineering,CAS 2014
+///
+/// @brief 自动运行参数模块
+///
+/// 用于自动获取运行参数的模块,尽量减少用户需要配置的参数。
+///
+/// @author 陆秋文<[email protected]>
+/// @date 2014-07-03
+///
+///
+///////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <unistd.h>
+#include <dirent.h>
+
+#include "apt.h"
+#include "MESA_prof_load.h"
+
+#ifndef STRING_MAX
+#define STRING_MAX 2048
+#endif
+
+extern const char * conf_path[];
+extern const int n_conf_path;
+
+static const char * apt_find_conffile()
+{
+ for(int i = 0; i < n_conf_path; i++)
+ if(access(conf_path[i],R_OK) == 0)
+ return conf_path[i];
+ return NULL;
+}
+
+static int apt_paras_eal_ccpu(int argc_max,__out__ int * argc,__out__ const char * argv[])
+{
+ uint64_t core_ret = 0;
+ const char * conffile = apt_find_conffile();
+ if(conffile == NULL)
+ return -2;
+
+ char worker_buf[STRING_MAX];
+ MESA_load_profile_string_def(conffile,"worker","lcore",
+ worker_buf,sizeof(char) * STRING_MAX,"");
+ char *p = worker_buf;
+ while (*p != 0) {
+ uint32_t lcore;
+ errno = 0;
+ lcore = strtoul(p, NULL, 0);
+ if ((errno != 0)) {
+ return -2;
+ }
+
+ core_ret |= 1 << lcore;
+
+ p = strchr(p, ',');
+ if (p == NULL) {
+ break;
+ }
+ p++;
+ }
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"-c",STRING_MAX);
+
+ char core_hex[STRING_MAX];
+ sprintf(core_hex,"0x%x",core_ret);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],core_hex,STRING_MAX);
+ return 0;
+}
+
+static int apt_paras_eal_bpci(int argc_max,__out__ int * argc,__out__ const char * argv[])
+{
+ struct dirent * device_dir_p;
+ DIR * device_dir;
+
+ if((device_dir = opendir("/sys/class/net/")) == NULL)
+ return -1;
+
+
+ while((device_dir_p = readdir(device_dir)) != NULL)
+ {
+ if(strcmp(device_dir_p->d_name,".") == 0 ||
+ strcmp(device_dir_p->d_name,"..") == 0 ||
+ strcmp(device_dir_p->d_name,"lo") == 0)
+ continue;
+
+ char devsym_dir[STRING_MAX];
+ strncpy(devsym_dir,"/sys/class/net/",STRING_MAX);
+ strncat(devsym_dir,device_dir_p->d_name,STRING_MAX);
+ strncat(devsym_dir,"/device",STRING_MAX);
+
+ char devsym_info[STRING_MAX];
+ readlink(devsym_dir,devsym_info,STRING_MAX);
+
+ char devsym_pci[STRING_MAX];
+ strncpy(devsym_pci,devsym_info + 11 ,STRING_MAX);
+
+ if(strcmp(devsym_pci,"") == 0)
+ continue;
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"-b",STRING_MAX);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],devsym_pci,STRING_MAX);
+ }
+
+ closedir(device_dir);
+
+ return 0;
+}
+
+int apt_paras_eal_memchannals(int argc_max,__out__ int * argc,__out__ const char * argv[])
+{
+ int isenable_m = 0;
+ int n_memchal = 0;
+
+ //Read it from configure file
+ for(int i = 0; i < n_conf_path; i++)
+ {
+ if(access(conf_path[i],R_OK) == 0)
+ {
+ MESA_load_profile_int_def(conf_path[i],"eal","enable_spec_memc",&(isenable_m),0);
+ MESA_load_profile_int_def(conf_path[i],"eal","n_mem_channel",&(n_memchal),0);
+ break;
+ }
+ }
+
+ if(isenable_m <= 0)
+ return 0;
+
+ char n_memchal_string[STRING_MAX];
+ sprintf(n_memchal_string,"%d",n_memchal);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"-n",STRING_MAX);
+
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],n_memchal_string,STRING_MAX);
+
+ return 0;
+}
+
+int apt_paras_proc_type(int argc_max, __out__ int * argc, __out__ const char * argv[])
+{
+ if(*argc > (argc_max - 1))
+ return -2;
+ strncpy(argv[(*argc)++],"--proc-type=secondary",STRING_MAX);
+
+ return 0;
+}
+
+int apt_paras_eal_virtaddr(int argc_max, __out__ int * argc, __out__ char * argv[])
+{
+ int enable = 0;
+ char virtaddr[STRING_MAX];
+
+ const char * fcfg_path = apt_find_conffile();
+ MESA_load_profile_int_def(fcfg_path,"virtaddr","enable",&(enable),0);
+ MESA_load_profile_string_def(fcfg_path,"virtaddr","virtaddr",virtaddr,STRING_MAX,"");
+
+ if(enable > 0)
+ {
+ strncpy(argv[(*argc)++],"--base-virtaddr",STRING_MAX);
+ strncpy(argv[(*argc)++],virtaddr,STRING_MAX);
+ }
+
+ return 0;
+}
+
+int apt_paras_eal(int argc_max,__out__ int * argc,__out__ const char * argv[])
+{
+ if(apt_paras_eal_bpci(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_eal_ccpu(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_eal_memchannals(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_proc_type(argc_max,argc,argv) < 0)
+ return -1;
+ if(apt_paras_eal_virtaddr(argc_max,argc,argv) < 0)
+ return -1;
+ return 0;
+}
diff --git a/worker/apt.h b/worker/apt.h
new file mode 100644
index 0000000..34e1ecb
--- /dev/null
+++ b/worker/apt.h
@@ -0,0 +1,11 @@
+
+#ifndef __APT_INCLUDE_H__
+#define __APT_INCLUDE_H__
+
+#ifndef __out__
+#define __out__
+#endif
+
+int apt_paras_eal(int argc_max,__out__ int * argc,__out__ const char * argv[]);
+
+#endif
diff --git a/worker/config.c b/worker/config.c
new file mode 100644
index 0000000..199d897
--- /dev/null
+++ b/worker/config.c
@@ -0,0 +1,777 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <unistd.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_string_fns.h>
+
+#include <assert.h>
+
+#include "main.h"
+#include "MESA_prof_load.h"
+#include "watchdog.h"
+
+struct app_params app;
+const char *conf_path[] = {
+ "conf/nl2fwd.conf",
+ ".nl2fwd.conf",
+ "~/.nl2fwd.conf",
+ "/etc/nl2fwd.conf",
+ "/usr/local/etc/nl2fwd.conf"};
+
+const int n_conf_path = 5;
+
+#ifndef APP_MAX_STRING
+#define APP_MAX_STRING 4096
+#endif
+
+void app_print_usage(void)
+{
+ printf("usages\n");
+}
+
+static int app_parse_conffile_rx(char * fcfg_path)
+{
+ int n_arg_rx = 0;
+ MESA_load_profile_int_def(fcfg_path,"rx_common","rx_count",&n_arg_rx,0);
+
+ if(n_arg_rx <= 0)
+ return -1;
+
+ for(int i = 0; i < n_arg_rx; i++)
+ {
+ struct app_lcore_params *lp;
+
+ char rx_section_name[APP_MAX_STRING];
+ sprintf(rx_section_name,"rx_%d",i);
+
+ int port,queue,lcore;
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"port",&port,0);
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"queue",&queue,0);
+ MESA_load_profile_int_def(fcfg_path,rx_section_name,"lcore",&lcore,0);
+
+ /* Enable port and queue for later initialization */
+ if ((port >= APP_MAX_NIC_PORTS) || (queue >= APP_MAX_RX_QUEUES_PER_NIC_PORT)) {
+ return -3;
+ }
+ if (app.nic_rx_queue_mask[port][queue] != 0) {
+ return -4;
+ }
+ app.enabled_port_mask |= 1 << port;
+ app.nic_rx_queue_mask[port][queue] = 1;
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -6;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_WORKER) {
+ return -7;
+ }
+ lp->type = e_APP_LCORE_IO;
+ for (int j = 0; j < lp->io.rx.n_nic_queues; j++) {
+ if ((lp->io.rx.nic_queues[j].port == port) &&
+ (lp->io.rx.nic_queues[j].queue == queue)) {
+ return -8;
+ }
+ }
+ if (lp->io.rx.n_nic_queues >= APP_MAX_NIC_RX_QUEUES_PER_IO_LCORE) {
+ return -9;
+ }
+ lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].port = (uint8_t) port;
+ lp->io.rx.nic_queues[lp->io.rx.n_nic_queues].queue = (uint8_t) queue;
+ lp->io.rx.n_nic_queues ++;
+
+#if 0
+ int tx_port_existed = 0;
+ for(int j = 0; j < lp->io.tx.n_nic_ports; j++) {
+ if (lp->io.tx.nic_ports[j] == (uint8_t) port) {
+ tx_port_existed = 1;
+ break;
+ }
+ }
+
+ if(!tx_port_existed) {
+ lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = port;
+ lp->io.tx.n_nic_ports ++;
+ app.enabled_port_mask |= 1 << (uint8_t)port;
+ app.nic_tx_port_mask[(uint8_t)port] = 1;
+ }
+#endif
+ }
+
+ return 0;
+}
+
+#if 0
+static int app_parse_conffile_tx(char *fcfg_path)
+{
+
+ char tx_strbuf[APP_MAX_STRING];
+ char * parse_arg = tx_strbuf;
+ int tx_enable;
+
+ MESA_load_profile_int_def(fcfg_path,"tx","tx_enable",&tx_enable,0);
+ MESA_load_profile_string_def(fcfg_path,"tx","tx_port",parse_arg,
+ sizeof(char) * APP_MAX_STRING,"");
+ if(!tx_enable)
+ return 0;
+
+ for(parse_arg = strtok(parse_arg,",");
+ parse_arg != NULL; parse_arg = strtok(NULL,","))
+ {
+ int port = 0;
+ int ret = sscanf(parse_arg,"%d",&port);
+ if(ret <= 0)
+ return -1; //Parse Error.
+ if(port > APP_MAX_NIC_PORTS|| port < 0)
+ return -2; // Wrong Port number.
+
+ //Set TX Mask and Port Mask.
+ app.enabled_port_mask |= 1 << (uint8_t)port;
+ app.nic_tx_port_mask[(uint8_t)port] = 1;
+ }
+
+ return 0;
+}
+#endif
+
+static int app_parse_conffile_tx(char * fcfg_path)
+{
+ int n_arg_tx = 0;
+ MESA_load_profile_int_def(fcfg_path,"tx_common","tx_count",&n_arg_tx,0);
+
+ if(n_arg_tx <= 0)
+ return -1;
+
+ for(int i = 0; i < n_arg_tx; i++)
+ {
+ struct app_lcore_params *lp;
+ char tx_section_name[APP_MAX_STRING];
+ sprintf(tx_section_name,"tx_%d",i);
+
+ int port,lcore;
+ MESA_load_profile_int_def(fcfg_path,tx_section_name,"port",&port,0);
+ MESA_load_profile_int_def(fcfg_path,tx_section_name,"lcore",&lcore,0);
+
+ /* Enable port and queue for later initialization */
+ if (port >= APP_MAX_NIC_PORTS) {
+ return -3;
+ }
+ if (app.nic_tx_port_mask[port] != 0) {
+ return -4;
+ }
+ app.nic_tx_port_mask[port] = 1;
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -6;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_WORKER) {
+ return -7;
+ }
+ lp->type = e_APP_LCORE_IO;
+ for (int j = 0; j < lp->io.tx.n_nic_ports; j++) {
+ if (lp->io.tx.nic_ports[j] == port) {
+ return -8;
+ }
+ }
+ if (lp->io.tx.n_nic_ports >= APP_MAX_NIC_TX_PORTS_PER_IO_LCORE) {
+ return -9;
+ }
+ lp->io.tx.nic_ports[lp->io.tx.n_nic_ports] = (uint8_t) port;
+ lp->io.tx.n_nic_ports ++;
+
+ }
+
+ return 0;
+}
+
+static int app_parse_conffile_w(char *fcfg_path)
+{
+
+ char worker_buf[APP_MAX_STRING];
+ MESA_load_profile_string_def(fcfg_path,"worker","lcore",worker_buf,
+ sizeof(char) * APP_MAX_STRING,"");
+
+ char *p = worker_buf;
+
+ while (*p != 0) {
+ struct app_lcore_params *lp;
+ uint32_t lcore;
+
+
+ errno = 0;
+ lcore = strtoul(p, NULL, 0);
+ if ((errno != 0)) {
+ return -2;
+ }
+
+ /* Check and enable worker lcore */
+#if 0
+ if (rte_lcore_is_enabled(lcore) == 0) {
+ return -3;
+ }
+#endif
+
+ if (lcore >= APP_MAX_LCORES) {
+ return -4;
+ }
+ lp = &app.lcore_params[lcore];
+ if (lp->type == e_APP_LCORE_IO) {
+ return -5;
+ }
+ lp->type = e_APP_LCORE_WORKER;
+
+ p = strchr(p, ',');
+ if (p == NULL) {
+ break;
+ }
+ p++;
+ }
+
+ return 0;
+}
+
+static int app_parse_conffile_energy_paras(char * fcfg_path)
+{
+ MESA_load_profile_int_def(fcfg_path,"energy","enable",&app.energy.enable,0);
+ MESA_load_profile_int_def(fcfg_path,"energy","min_zero_pull_count",&app.energy.min_zero_pull_count,ENERGY_MIN_ZERO_POLL_COUNT);
+ MESA_load_profile_int_def(fcfg_path,"energy","sleep_gear1_threshold",&app.energy.sleep_gear1_threshold,ENERGY_SLEEP_GEAR1_THRESHOLD);
+ MESA_load_profile_int_def(fcfg_path,"energy","sleep_gear2_threshold",&app.energy.sleep_gear2_threshold,ENERGY_SLEEP_GEAR2_THRESHOLD);
+
+ return 0;
+}
+
+static int app_parse_conffile_rxtx_paras(char * fcfg_path)
+{
+ MESA_load_profile_int_def(fcfg_path,"common","nic_rx_ring_size",
+ &app.nic_rx_ring_size,APP_DEFAULT_NIC_RX_RING_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","nic_tx_ring_size",
+ &app.nic_tx_ring_size,APP_DEFAULT_NIC_TX_RING_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","ring_rx_size",
+ &app.ring_rx_size,APP_DEFAULT_RING_RX_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"common","ring_tx_size",
+ &app.ring_tx_size,APP_DEFAULT_RING_TX_SIZE);
+
+
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_rx_read",
+ &app.burst_size_io_rx_read,APP_DEFAULT_BURST_SIZE_IO_RX_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_rx_write",
+ &app.burst_size_io_rx_write,APP_DEFAULT_BURST_SIZE_IO_RX_WRITE);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_tx_read",
+ &app.burst_size_io_tx_read,APP_DEFAULT_BURST_SIZE_IO_TX_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_io_tx_write",
+ &app.burst_size_io_tx_write,APP_DEFAULT_BURST_SIZE_IO_TX_WRITE);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_worker_read",
+ &app.burst_size_worker_read,APP_DEFAULT_BURST_SIZE_WORKER_READ);
+ MESA_load_profile_int_def(fcfg_path,"common","burst_size_worker_write",
+ &app.burst_size_worker_write,APP_DEFAULT_BURST_SIZE_WORKER_WRITE);
+
+
+ return 0;
+}
+
+
+
+static int app_parse_conffile_map(char * fcfg_path)
+{
+ int rx_port,tx_port;
+ int n_record = 0;
+
+ MESA_load_profile_int_def(fcfg_path,"map","n_map",&n_record,0);
+
+ if(n_record <= 0)
+ return 0;
+
+ char map_strbuf[APP_MAX_STRING];
+
+ for(int i = 0; i < n_record; i++)
+ {
+ char map_key[APP_MAX_STRING];
+
+ char * map_strbuf_p = map_strbuf;
+ char * port_str = NULL;
+
+ sprintf(map_key,"map_%d",i);
+
+ int ret = MESA_load_profile_string_def(fcfg_path,"map",map_key,map_strbuf,
+ sizeof(char) * APP_MAX_STRING,"");
+ if(ret < 0)
+ return -1;
+
+ port_str = strtok(map_strbuf_p, ",");
+ ret = sscanf(port_str,"%d",&rx_port);
+
+ if(ret <= 0)
+ return -1;
+
+ // Add Map Record for RX Port.
+ app.rxtx_port_map[i].rx_port = rx_port;
+
+ int j = 1;
+ for(j = 1,port_str = strtok(NULL, ",");
+ port_str != NULL;
+ port_str = strtok(NULL, ","))
+ {
+ if(sscanf(port_str,"%d",&tx_port) < 0)
+ return -1;
+ if(tx_port > APP_MAX_NIC_PORTS || tx_port < 0)
+ return -1;
+ if(app.nic_tx_port_mask[tx_port] != 1)
+ return -1;
+
+ // Add Map Record for TX Report
+ app.rxtx_port_map[i].tx_port[j-1] = tx_port;
+
+ }
+ app.rxtx_port_map[i].n_tx_port = (uint32_t)j;
+ (app.n_rxtx_port_map)++;
+
+ app.rxtx_stream_record[(uint8_t)app.n_rxtx_stream].rx_port = rx_port;
+ app.rxtx_stream_record[(uint8_t)app.n_rxtx_stream].tx_port = tx_port;
+ (app.n_rxtx_stream)++;
+
+ app.map_type = e_APP_MAP_TYPE_PORTMAP;
+
+ }
+
+ assert(app.n_rxtx_port_map == n_record);
+
+ return n_record;
+}
+
+static int app_parse_conffile_stat(char *fcfg_path)
+{
+ MESA_load_profile_int_def(fcfg_path,"stat","enable",&(app.statistics.enable),1);
+ MESA_load_profile_int_def(fcfg_path,"stat","print", &(app.statistics.is_printmsg),1);
+ MESA_load_profile_int_def(fcfg_path,"stat","sample_time", &(app.statistics.sample_time),1);
+
+ if(app.watchdog_paras.enable)
+ app.statistics.enable = 1;
+
+ return 0;
+}
+
+static int app_parse_conffile_watchdog(char * fcfg_path)
+{
+
+ app.watchdog_paras.localip = (char *)malloc(sizeof(char) * APP_MAX_STRING);
+ app.watchdog_paras.dev = (char *)malloc(sizeof(char) * APP_MAX_STRING);
+
+ MESA_load_profile_int_def(fcfg_path,"watchdog","enable",
+ &(app.watchdog_paras.enable),APP_DEFAULT_WATCHDOG_ENABLE);
+ MESA_load_profile_int_def(fcfg_path,"watchdog","threshold_bypass_lostpkt",
+ &(app.watchdog_paras.threshold_bypass_pktloss),APP_DEFAULT_WATCHDOG_THS_BYPASS_LOSSPKT);
+ MESA_load_profile_int_def(fcfg_path,"watchdog","threshold_alert_lostpkt",
+ &(app.watchdog_paras.threshold_alert_pktloss),APP_DEFAULT_WATCHDOG_THS_ALERT_LOSSPKT);
+ MESA_load_profile_int_def(fcfg_path,"watchdog","threshold_bypass_do",
+ &(app.watchdog_paras.threshold_bypass_do),APP_DEFAULT_WATCHDOG_THS_BYPASS_DO);
+ MESA_load_profile_int_def(fcfg_path,"watchdog","threshold_alert_do",
+ &(app.watchdog_paras.threshold_alert_do),APP_DEFAULT_WATCHDOG_THS_ALERT_DO);
+ MESA_load_profile_int_def(fcfg_path,"watchdog","threshold_normal_do",
+ &(app.watchdog_paras.threshold_normal_do),APP_DEFAULT_WATCHDOG_THS_NORMAL_DO);
+
+ MESA_load_profile_string_def(fcfg_path,"watchdog","localip",app.watchdog_paras.localip,
+ sizeof(char) * APP_MAX_STRING, "192.168.0.178");
+ MESA_load_profile_string_def(fcfg_path,"watchdog","dev",app.watchdog_paras.dev,
+ sizeof(char) * APP_MAX_STRING, "eth5");
+
+ return 0;
+}
+
+
+static int app_parse_conffile_mempool(char *fcfg_path)
+{
+
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_buffers",
+ &(app.mempool.mempool_buffers),APP_DEFAULT_MEMPOOL_BUFFERS);
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_mbuf_size",
+ &(app.mempool.mempool_mbuf_size),APP_DEFAULT_MBUF_SIZE);
+ MESA_load_profile_int_def(fcfg_path,"mempool","mempool_cache_size",
+ &(app.mempool.mempool_cache_size),APP_DEFAULT_MEMPOOL_CACHE_SIZE);
+
+ return 0;
+}
+
+
+int app_parse_args(int argc, char **argv)
+{
+
+
+ app.enabled_port_mask = 0;
+ app.key_type = KEY_TYPE_IS_IP;
+
+ for(int i = 0; i < n_conf_path ; i++)
+ {
+ if(access(conf_path[i],R_OK) == 0) {
+
+ char * path = (char *)conf_path[i];
+
+ if(app_parse_conffile_rx(path) < 0)
+ return -1;
+ if(app_parse_conffile_tx(path) < 0)
+ return -2;
+ if(app_parse_conffile_w(path) < 0)
+ return -3;
+ if(app_parse_conffile_rxtx_paras(path) < 0)
+ return -4;
+ if(app_parse_conffile_stat(path) < 0)
+ return -5;
+ if(app_parse_conffile_watchdog(path) < 0)
+ return -6;
+ if(app_parse_conffile_map(path) < 0)
+ return -7;
+ if(app_parse_conffile_mempool(path) < 0)
+ return -8;
+ if(app_parse_conffile_energy_paras(path) < 0)
+ return -9;
+
+ return 0;
+ }
+ }
+ return -9;
+}
+
+int
+app_get_nic_rx_queues_per_port(uint8_t port)
+{
+ uint32_t i, count;
+
+ if (port >= APP_MAX_NIC_PORTS) {
+ return -1;
+ }
+
+ count = 0;
+ for (i = 0; i < APP_MAX_RX_QUEUES_PER_NIC_PORT; i ++) {
+ if (app.nic_rx_queue_mask[port][i] == 1) {
+ count ++;
+ }
+ }
+
+ return count;
+}
+
+int
+app_get_lcore_for_nic_rx(uint8_t port, uint8_t queue, uint32_t *lcore_out)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t i;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_IO) {
+ continue;
+ }
+
+ for (i = 0; i < lp->rx.n_nic_queues; i ++) {
+ if ((lp->rx.nic_queues[i].port == port) &&
+ (lp->rx.nic_queues[i].queue == queue)) {
+ *lcore_out = lcore;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+app_get_lcore_for_nic_tx(uint8_t port, uint32_t *lcore_out)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t i;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_IO) {
+ continue;
+ }
+
+ for (i = 0; i < lp->tx.n_nic_ports; i ++) {
+ if (lp->tx.nic_ports[i] == port) {
+ *lcore_out = lcore;
+ return 0;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int
+app_is_socket_used(uint32_t socket)
+{
+ uint32_t lcore;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) {
+ continue;
+ }
+
+ if (socket == rte_lcore_to_socket_id(lcore)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+uint32_t
+app_get_lcores_io_rx(void)
+{
+ uint32_t lcore, count;
+
+ count = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->rx.n_nic_queues == 0)) {
+ continue;
+ }
+ count ++;
+ }
+ return count;
+}
+
+uint32_t
+app_get_lcores_worker(void)
+{
+ uint32_t lcore, count;
+
+ count = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ count ++;
+ }
+
+ if (count > APP_MAX_WORKER_LCORES) {
+ rte_panic("Algorithmic error (too many worker lcores)\n");
+ return 0;
+ }
+
+ return count;
+}
+
+void
+app_print_params(void)
+{
+ unsigned port, queue, lcore, i, j;
+
+ /* Print NIC RX configuration */
+ printf("NIC RX ports: ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ uint32_t n_rx_queues = app_get_nic_rx_queues_per_port((uint8_t) port);
+
+ if (n_rx_queues == 0) {
+ continue;
+ }
+
+ printf("%u (", port);
+ for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) {
+ if (app.nic_rx_queue_mask[port][queue] == 1) {
+ printf("%u ", queue);
+ }
+ }
+ printf(") ");
+ }
+ printf(";\n");
+
+ /* Print I/O lcore RX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp->rx.n_nic_queues == 0)) {
+ continue;
+ }
+
+ printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore));
+
+ printf("RX ports ");
+ for (i = 0; i < lp->rx.n_nic_queues; i ++) {
+ printf("(%u, %u) ",
+ (unsigned) lp->rx.nic_queues[i].port,
+ (unsigned) lp->rx.nic_queues[i].queue);
+ }
+ printf("; ");
+
+ printf("Output rings ");
+ for (i = 0; i < lp->rx.n_rings; i ++) {
+ printf("%p ", lp->rx.rings[i]);
+ }
+ printf(";\n");
+ }
+
+ /* Print worker lcore RX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Worker lcore %u (socket %u) ID %u: ",
+ lcore,
+ rte_lcore_to_socket_id(lcore),
+ (unsigned)lp->worker_id);
+
+ printf("Input rings ");
+ for (i = 0; i < lp->n_rings_in; i ++) {
+ printf("%p ", lp->rings_in[i]);
+ }
+
+ printf(";\n");
+ }
+
+ printf("\n");
+
+ /* Print NIC TX configuration */
+ printf("NIC TX ports: ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ if (app.nic_tx_port_mask[port] == 1) {
+ printf("%u ", port);
+ }
+ }
+ printf(";\n");
+
+ /* Print I/O TX lcore params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp = &app.lcore_params[lcore].io;
+ uint32_t n_workers = app_get_lcores_worker();
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp->tx.n_nic_ports == 0)) {
+ continue;
+ }
+
+ printf("I/O lcore %u (socket %u): ", lcore, rte_lcore_to_socket_id(lcore));
+
+ printf("Input rings per TX port ");
+ for (i = 0; i < lp->tx.n_nic_ports; i ++) {
+ port = lp->tx.nic_ports[i];
+
+ printf("%u (", port);
+ for (j = 0; j < n_workers; j ++) {
+ printf("%p ", lp->tx.rings[port][j]);
+ }
+ printf(") ");
+
+ }
+
+ printf(";\n");
+ }
+
+ /* Print worker lcore TX params */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Worker lcore %u (socket %u) ID %u: \n",
+ lcore,
+ rte_lcore_to_socket_id(lcore),
+ (unsigned)lp->worker_id);
+
+ printf("Output rings per TX port ");
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ if (lp->rings_out[port] != NULL) {
+ printf("%u (%p) ", port, lp->rings_out[port]);
+ }
+ }
+
+ printf(";\n");
+ }
+
+ /* Rings */
+ printf("Ring sizes: NIC RX = %u; Worker in = %u; Worker out = %u; NIC TX = %u;\n",
+ (unsigned) app.nic_rx_ring_size,
+ (unsigned) app.ring_rx_size,
+ (unsigned) app.ring_tx_size,
+ (unsigned) app.nic_tx_ring_size);
+
+ /* Bursts */
+ printf("Burst sizes: I/O RX (rd = %u, wr = %u); Worker (rd = %u, wr = %u); I/O TX (rd = %u, wr = %u)\n",
+ (unsigned) app.burst_size_io_rx_read,
+ (unsigned) app.burst_size_io_rx_write,
+ (unsigned) app.burst_size_worker_read,
+ (unsigned) app.burst_size_worker_write,
+ (unsigned) app.burst_size_io_tx_read,
+ (unsigned) app.burst_size_io_tx_write);
+}
diff --git a/worker/init.c b/worker/init.c
new file mode 100644
index 0000000..1c162b6
--- /dev/null
+++ b/worker/init.c
@@ -0,0 +1,584 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_string_fns.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_version.h>
+
+#include "main.h"
+#include "nstat.h"
+
+static struct rte_eth_conf port_conf = {
+ .rxmode = {
+ .split_hdr_size = 0,
+ .header_split = 0, /**< Header Split disabled */
+ .hw_ip_checksum = 0, /**< IP checksum offload enabled */
+ .hw_vlan_filter = 1, /**< VLAN filtering disabled */
+ .hw_vlan_strip = 1,
+ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */
+ .hw_strip_crc = 0, /**< CRC stripped by hardware */
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6,
+ },
+ },
+ .txmode = {
+ //.mq_mode = ETH_MQ_TX_NONE,
+ .mq_mode = ETH_DCB_NONE,
+ },
+};
+
+static struct rte_eth_rxconf rx_conf = {
+ .rx_thresh = {
+ .pthresh = APP_DEFAULT_NIC_RX_PTHRESH,
+ .hthresh = APP_DEFAULT_NIC_RX_HTHRESH,
+ .wthresh = APP_DEFAULT_NIC_RX_WTHRESH,
+ },
+ .rx_free_thresh = APP_DEFAULT_NIC_RX_FREE_THRESH,
+ .rx_drop_en = APP_DEFAULT_NIC_RX_DROP_EN,
+};
+
+static struct rte_eth_txconf tx_conf = {
+ .tx_thresh = {
+ .pthresh = APP_DEFAULT_NIC_TX_PTHRESH,
+ .hthresh = APP_DEFAULT_NIC_TX_HTHRESH,
+ .wthresh = APP_DEFAULT_NIC_TX_WTHRESH,
+ },
+ .tx_free_thresh = APP_DEFAULT_NIC_TX_FREE_THRESH,
+ .tx_rs_thresh = APP_DEFAULT_NIC_TX_RS_THRESH,
+};
+
+static int
+app_get_worker_core_number(void)
+{
+ unsigned lcore;
+ int count = 0;
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+ count++;
+ }
+ return count;
+}
+
+static void
+app_assign_worker_ids(void)
+{
+ uint32_t lcore, worker_id;
+
+ /* Assign ID for each worker */
+ worker_id = 0;
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ lp_worker->worker_id = worker_id;
+ worker_id ++;
+ }
+}
+
+static void
+app_init_mbuf_pools(void)
+{
+ unsigned socket, lcore;
+
+ /* Init the buffer pools */
+ for (socket = 0; socket < APP_MAX_SOCKETS; socket ++) {
+ char name[32];
+ if (app_is_socket_used(socket) == 0) {
+ continue;
+ }
+
+ rte_snprintf(name, sizeof(name), "mbuf_pool_%u", socket);
+ printf("Creating the mbuf pool for socket %u ...\n", socket);
+
+ app.pools[socket] = rte_mempool_lookup(name);
+
+ if (app.pools[socket] == NULL) {
+ rte_panic("Cannot create mbuf pool on socket %u\n", socket);
+ }
+ }
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ if (app.lcore_params[lcore].type == e_APP_LCORE_DISABLED) {
+ continue;
+ }
+
+ socket = rte_lcore_to_socket_id(lcore);
+ app.lcore_params[lcore].pool = app.pools[socket];
+ }
+}
+
+
+static void
+app_init_rings_rx(void)
+{
+ unsigned lcore;
+
+ /* Initialize the rings for the RX side */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+ unsigned socket_io, lcore_worker;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->rx.n_nic_queues == 0)) {
+ continue;
+ }
+
+ socket_io = rte_lcore_to_socket_id(lcore);
+
+ for (lcore_worker = 0; lcore_worker < APP_MAX_LCORES; lcore_worker ++) {
+ char name[32];
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore_worker].worker;
+ struct rte_ring *ring = NULL;
+
+ if (app.lcore_params[lcore_worker].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ printf("Creating ring to connect I/O lcore %u (socket %u) with worker lcore %u ...\n",
+ lcore,
+ socket_io,
+ lcore_worker);
+ rte_snprintf(name, sizeof(name), "app_ring_rx_io%u_w%u",
+ lcore,
+ lcore_worker);
+ ring = rte_ring_lookup(name);
+
+ if (ring == NULL) {
+ rte_panic("Cannot create ring to connect I/O core %u with worker core %u\n",
+ lcore,
+ lcore_worker);
+ }
+
+ lp_io->rx.rings[lp_io->rx.n_rings] = ring;
+ lp_io->rx.n_rings ++;
+
+ lp_worker->rings_in[lp_worker->n_rings_in] = ring;
+ lp_worker->n_rings_in ++;
+ }
+ }
+
+
+#if 0
+ /* Init the rings for the TX side */
+ /* Add by Lu Qiuwen <[email protected]> at 2014-12-04 */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker;
+ unsigned socket_io, port;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ if (lp_worker->n_rings_in != app_get_lcores_io_rx()) {
+ rte_panic("Algorithmic error (worker input rings)\n");
+ }
+
+ socket_io = rte_lcore_to_socket_id(lcore);
+ for (port = 0; port < APP_MAX_NIC_PORTS; port++) {
+ char name[32];
+ struct rte_ring * ring = NULL;
+
+ if(app.nic_tx_port_mask[port] != 1)
+ continue;
+
+ printf("Creating ring to connect NIC %u (socket %u) in worker lcore %u ... \n",
+ port,
+ socket_io,
+ lcore);
+ rte_snprintf(name, sizeof(name), "app_ring_tx_s%u_p%u_w_%u",
+ socket_io,
+ port,
+ lcore);
+ ring = rte_ring_create(
+ name,
+ app.ring_tx_size,
+ socket_io,
+ RING_F_SP_ENQ | RING_F_SC_DEQ);
+ if (ring == NULL) {
+ rte_panic("Cannot create ring NIC %u in worker lcore %u\n",
+ port,
+ lcore);
+ }
+
+ lp_worker->rings_out[port] = ring;
+ }
+ }
+
+ /* Connect I/O TX to working tx rings, by Lu Qiuwen at 2014-12-04 */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+ unsigned lcore_worker, port_id;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->rx.n_nic_queues == 0)) {
+ continue;
+ }
+
+ for(lcore_worker = 0; lcore < APP_MAX_LCORES; lcore++) {
+ struct app_lcore_params_worker * lp_worker = &app.lcore_params[lcore].worker;
+ struct rte_ring * ring = NULL;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ for(int i = 0; i < lp_io->tx.n_nic_ports; i++) {
+ port_id = lp_io->tx.nic_ports[i];
+ ring = lp_worker->rings_out[port_id];
+
+ lp_io->tx.rings[port_id][lcore_worker] = ring;
+
+ printf("Link rings between worker %u(port %u) with I/O core %u\n",
+ lcore_worker,
+ port_id,
+ lcore);
+ }
+ }
+ }
+#endif
+}
+
+static void
+app_init_rings_tx(void)
+{
+ unsigned lcore;
+
+ /* Initialize the rings for the TX side */
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_worker *lp_worker = &app.lcore_params[lcore].worker;
+ unsigned port;
+
+ if (app.lcore_params[lcore].type != e_APP_LCORE_WORKER) {
+ continue;
+ }
+
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ char name[32];
+ struct app_lcore_params_io *lp_io = NULL;
+ struct rte_ring *ring;
+ uint32_t socket_io, lcore_io;
+
+ if (app.nic_tx_port_mask[port] == 0) {
+ continue;
+ }
+
+ if (app_get_lcore_for_nic_tx((uint8_t) port, &lcore_io) < 0) {
+ rte_panic("Algorithmic error (no I/O core to handle TX of port %u)\n",
+ port);
+ }
+
+ lp_io = &app.lcore_params[lcore_io].io;
+ socket_io = rte_lcore_to_socket_id(lcore_io);
+
+ printf("Creating ring to connect worker lcore %u with TX port %u (through I/O lcore %u) (socket %u) ...\n",
+ lcore, port, (unsigned)lcore_io, (unsigned)socket_io);
+ snprintf(name, sizeof(name), "app_ring_tx_w%u_p%u", lcore, port);
+ printf("%s\n",name);
+
+ ring = rte_ring_lookup(name);
+ if (ring == NULL) {
+ rte_panic("Cannot create ring to connect worker core %u with TX port %u\n",
+ lcore,
+ port);
+ }
+
+ lp_worker->rings_out[port] = ring;
+ lp_io->tx.rings[port][lp_worker->worker_id] = ring;
+ }
+ }
+
+ for (lcore = 0; lcore < APP_MAX_LCORES; lcore ++) {
+ struct app_lcore_params_io *lp_io = &app.lcore_params[lcore].io;
+ unsigned i;
+
+ if ((app.lcore_params[lcore].type != e_APP_LCORE_IO) ||
+ (lp_io->tx.n_nic_ports == 0)) {
+ continue;
+ }
+
+ for (i = 0; i < lp_io->tx.n_nic_ports; i ++){
+ unsigned port, j;
+
+ port = lp_io->tx.nic_ports[i];
+ for (j = 0; j < app_get_lcores_worker(); j ++) {
+ if (lp_io->tx.rings[port][j] == NULL) {
+ rte_panic("Algorithmic error (I/O TX rings)\n");
+ }
+ }
+ }
+ }
+}
+
+
+
+
+/* Check the link status of all ports in up to 9s, and print them finally */
+static void
+check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
+{
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
+ uint8_t portid, count, all_ports_up, print_flag = 0;
+ struct rte_eth_link link;
+ uint32_t n_rx_queues, n_tx_queues;
+
+ printf("\nChecking link status");
+ fflush(stdout);
+ for (count = 0; count <= MAX_CHECK_TIME; count++) {
+ all_ports_up = 1;
+ for (portid = 0; portid < port_num; portid++) {
+ if ((port_mask & (1 << portid)) == 0)
+ continue;
+ n_rx_queues = app_get_nic_rx_queues_per_port(portid);
+ n_tx_queues = app.nic_tx_port_mask[portid];
+ if ((n_rx_queues == 0) && (n_tx_queues == 0))
+ continue;
+ memset(&link, 0, sizeof(link));
+ rte_eth_link_get_nowait(portid, &link);
+ /* print link status if flag set */
+ if (print_flag == 1) {
+ if (link.link_status)
+ printf("Port %d Link Up - speed %u "
+ "Mbps - %s\n", (uint8_t)portid,
+ (unsigned)link.link_speed,
+ (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
+ ("full-duplex") : ("half-duplex\n"));
+ else
+ printf("Port %d Link Down\n",
+ (uint8_t)portid);
+ continue;
+ }
+ /* clear all_ports_up flag if any link down */
+ if (link.link_status == 0) {
+ all_ports_up = 0;
+ break;
+ }
+ }
+ /* after finally printing all link status, get out */
+ if (print_flag == 1)
+ break;
+
+ if (all_ports_up == 0) {
+ printf(".");
+ fflush(stdout);
+ rte_delay_ms(CHECK_INTERVAL);
+ }
+
+ /* set the print_flag if all ports up or timeout */
+ if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
+ print_flag = 1;
+ printf("done\n");
+ }
+ }
+}
+
+static void
+app_init_nics(void)
+{
+ unsigned socket;
+ uint32_t lcore;
+ uint8_t port, queue;
+ int ret;
+ uint32_t n_rx_queues, n_tx_queues;
+
+ /* Init driver */
+ printf("Initializing the PMD driver ...\n");
+
+#if 0
+#if RTE_VER_MAJOR >=1 && RTE_VER_MINOR <= 6
+ if (rte_pmd_init_all() < 0) {
+ rte_panic("Cannot init PMD\n");
+ }
+#endif
+
+ if (rte_eal_pci_probe() < 0) {
+ rte_panic("Cannot probe PCI\n");
+ }
+#endif
+
+ app.worker_core_num = app_get_worker_core_number();
+
+#if 0
+ /* Init NIC ports and queues, then start the ports */
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ struct rte_mempool *pool;
+
+ n_rx_queues = app_get_nic_rx_queues_per_port(port);
+
+ if(app.nic_tx_port_mask[port])
+ {
+ app.nic_tx_port_mask[port] = app.worker_core_num;
+ }
+ n_tx_queues = app.nic_tx_port_mask[port];
+
+ if ((n_rx_queues == 0) && (n_tx_queues == 0)) {
+ continue;
+ }
+
+ /* Init port */
+ printf("Initializing NIC port %u ...\n", (unsigned) port);
+ ret = rte_eth_dev_configure(
+ port,
+ (uint8_t) n_rx_queues,
+ (uint8_t) n_tx_queues,
+ &port_conf);
+ if (ret < 0) {
+ rte_panic("Cannot init NIC port %u (%d)\n", (unsigned) port, ret);
+ }
+ rte_eth_promiscuous_enable(port);
+
+ /* Init RX queues */
+ for (queue = 0; queue < APP_MAX_RX_QUEUES_PER_NIC_PORT; queue ++) {
+ if (app.nic_rx_queue_mask[port][queue] == 0) {
+ continue;
+ }
+
+ app_get_lcore_for_nic_rx(port, queue, &lcore);
+ socket = rte_lcore_to_socket_id(lcore);
+ pool = app.lcore_params[lcore].pool;
+
+ printf("Initializing NIC port %u RX queue %u ...\n",
+ (unsigned) port,
+ (unsigned) queue);
+ ret = rte_eth_rx_queue_setup(
+ port,
+ queue,
+ (uint16_t) app.nic_rx_ring_size,
+ socket,
+ &rx_conf,
+ pool);
+ if (ret < 0) {
+ rte_panic("Cannot init RX queue %u for port %u (%d)\n",
+ (unsigned) queue,
+ (unsigned) port,
+ ret);
+ }
+ }
+
+ /* Init TX queues */
+ //RSYS if (app.nic_tx_port_mask[port] == 1) {
+ for (queue = 0; queue < n_tx_queues; queue ++) {
+ app_get_lcore_for_nic_tx(port, &lcore);
+ socket = rte_lcore_to_socket_id(lcore);
+ printf("Initializing NIC port %u TX queue 0 ...\n",
+ (unsigned) port);
+ ret = rte_eth_tx_queue_setup(
+ port,
+ queue, //0,
+ (uint16_t) app.nic_tx_ring_size,
+ socket,
+ &tx_conf);
+ if (ret < 0) {
+ rte_panic("Cannot init TX queue 0 for port %d (%d)\n",
+ port,
+ ret);
+ }
+ }
+
+ /* Start port */
+ ret = rte_eth_dev_start(port);
+ if (ret < 0) {
+ rte_panic("Cannot start port %d (%d)\n", port, ret);
+ }
+ }
+
+ check_all_ports_link_status(APP_MAX_NIC_PORTS, (~0x0));
+#endif
+}
+
+
+void
+app_init(void)
+{
+ if (rte_eal_process_type() != RTE_PROC_SECONDARY)
+ rte_panic("Cannot run in primary mode!");
+
+ app_assign_worker_ids();
+ app_init_mbuf_pools();
+ app_init_rings_rx();
+ app_init_rings_tx();
+ app_init_nics();
+
+ nstat_client_init();
+ watchdog_init();
+
+ printf("Initialization completed.\n");
+}
diff --git a/worker/nl2fwd.c b/worker/nl2fwd.c
new file mode 100644
index 0000000..e21461c
--- /dev/null
+++ b/worker/nl2fwd.c
@@ -0,0 +1,275 @@
+
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_memcpy.h>
+#include <rte_hash.h>
+
+#include "nl2fwd.h"
+#include "main.h"
+#include "watchdog.h"
+#include "nstat.h"
+#include "apt.h"
+
+#ifndef APP_MKPKT_IP_CHECKSUM
+#define APP_MKPKT_IP_CHECKSUM 0
+#endif
+
+#ifndef APP_MKPKT_ETHERNET_CRC
+#define APP_MKPKT_ETHERNET_CRC 0
+#endif
+
+FILE *warn_output_stream = NULL;
+FILE *err_output_stream = NULL;
+
+static inline struct rte_mbuf * rte_rxmbuf_alloc(struct rte_mempool *mp)
+{
+ struct rte_mbuf *m;
+ m = __rte_mbuf_raw_alloc(mp);
+ __rte_mbuf_sanity_check_raw(m,RTE_MBUF_PKT,0);
+
+ return (m);
+}
+
+int dpdk_register_callfunc(int (*func)(const unsigned char *data,int datalen,int port_in,int lcore))
+{
+ app.pkt_callback_f.rx_pkt_process = func;
+ app.pkt_callback_f.rx_pkt_process_dst = NULL;
+ return 0;
+}
+
+int dpdk_register_callfunc_dst(int (*func)(const unsigned char *data,int datalen,int dst,int lcore))
+{
+ app.pkt_callback_f.rx_pkt_process_dst = func;
+ app.pkt_callback_f.rx_pkt_process = NULL;
+ return 0;
+}
+
+int dpdk_send_packet_dst(unsigned char *data, int datalen, int dst)
+{
+ if(dst <0 || dst >= (int)app.n_rxtx_stream)
+ return -1;
+ uint32_t port = app.rxtx_stream_record[dst].tx_port;
+
+ return dpdk_send_packet_port(data,datalen,port);
+}
+
+int app_lcore_worker_tx_buffer_to_send (struct rte_mbuf *pkt, uint8_t port);
+int dpdk_send_packet_port(const unsigned char *data, int datalen, int port)
+{
+ struct rte_mbuf * pkt_burst = NULL;
+ unsigned lcore_id = rte_lcore_id();
+ struct app_lcore_params_worker * lp = &app.lcore_params[lcore_id].worker;
+ uint32_t bsz_wr = app.burst_size_worker_write;
+ uint64_t pos;
+
+ if(unlikely(data == NULL)) {
+ fprintf(warn_output_stream,"WARNING(core_id=%d,datalen=%d): Invalid TX packet info, ignore the pkt.\n",
+ lcore_id,datalen);
+ return -1;
+ }
+
+ pkt_burst = rte_rxmbuf_alloc(app.lcore_params[lcore_id].pool);
+
+ if(pkt_burst == NULL) {
+ fprintf(warn_output_stream,"WARNING(core_id=%d),Alloc mbuf failed,ignore the pkt\n",
+ lcore_id);
+ return -1;
+ }
+
+ pkt_burst->pkt.nb_segs = 1;
+ pkt_burst->pkt.next = NULL;
+ pkt_burst->pkt.in_port = port;
+ pkt_burst->pkt.pkt_len = datalen;
+ pkt_burst->pkt.data_len = datalen;
+
+ rte_memcpy(pkt_burst->pkt.data, data, datalen);
+
+#if APP_MKPKT_IP_CHECKSUM
+ pkt_burst->ol_flags |= PKT_TX_IP_CKSUM;
+ pkt_burst->pkt.vlan_macip.f.l2_len = sizeof(struct ether_hdr);
+ pkt_burst->pkt.vlan_macip.f.l3_len = sizeof(struct ipv4_hdr);
+#endif
+
+#if APP_MKPKT_ETHERNET_CRC
+ uint32_t ethernet_crc = rte_hash_crc(pkt_burst->pkt.data,datalen - ETHER_CRC_LEN ,0);
+ uint8_t * crc_start = (uint8_t *)pkt_burst->pkt.data + datalen - ETHER_CRC_LEN;
+ rte_cpu_to_be_32(ethernet_crc);
+ rte_memcpy(crc_start,&ethernet_crc,ETHER_CRC_LEN);
+#endif
+
+ pos = lp->mbuf_out[port].n_mbufs;
+ lp->mbuf_out[port].array[pos++] = pkt_burst;
+
+ if (likely(pos < bsz_wr)) {
+ lp->mbuf_out[port].n_mbufs = pos;
+ return 0;
+ }
+
+ int ret = rte_ring_sp_enqueue_bulk(lp->rings_out[port],(void **) lp->mbuf_out[port].array, bsz_wr);
+
+ if (unlikely(ret == -ENOBUFS)) {
+ uint32_t k;
+ nstat_client_count_wk_drop(lp->mbuf_out[port].array, bsz_wr,lcore_id);
+ for (int k = 0; k < bsz_wr; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+
+ lp->mbuf_out[port].n_mbufs = 0;
+ lp->mbuf_out_flush[port] = 0;
+
+ return 0;
+}
+
+void sigint_handler(int signo)
+{
+
+#if 0
+ uint8_t portid;
+ uint8_t nb_ports = rte_eth_dev_count();
+
+ signo = 0;
+
+ for (portid = 0; portid < nb_ports; portid++) {
+ rte_eth_dev_stop((uint8_t) portid);
+ printf(" stop ethernet device %d \n", portid);
+ }
+#endif
+ exit(0);
+}
+
+
+#ifndef NL2FWD_APT_MAXPARAS
+#define NL2FWD_APT_MAXPARAS 2048
+#endif
+
+#ifndef NL2FWD_APT_STRING_MAX
+#define NL2FWD_APT_STRING_MAX 2048
+#endif
+
+#ifndef NL2FWD_APT_ENABLE
+#define NL2FWD_APT_ENABLE 1
+#endif
+
+int dpdk_init(int argc,char **argv)
+{
+ static inited_flag = 0;
+ if(inited_flag != 0)
+ {
+ return 0;
+ }
+ else
+ {
+
+#if NL2FWD_APT_ENABLE
+ dpdk_init_apt();
+#else
+ dpdk_init_t(argc,argv);
+#endif
+ inited_flag = 1;
+
+ }
+}
+
+int dpdk_init_apt()
+{
+ char * argv_t[NL2FWD_APT_MAXPARAS];
+ int argc_t = 0;
+
+ for(int i = 0; i < NL2FWD_APT_MAXPARAS; i++)
+ {
+ argv_t[i] = (char *)malloc(sizeof(char) * NL2FWD_APT_STRING_MAX);
+ }
+ strncpy(argv_t[argc_t++],"./nl2fwd",NL2FWD_APT_STRING_MAX);
+
+ apt_paras_eal(NL2FWD_APT_MAXPARAS,&argc_t,argv_t);
+ dpdk_init_t(argc_t,argv_t);
+
+ return 0;
+}
+
+int dpdk_init_t(int argc, char **argv)
+{
+ int ret;
+
+ warn_output_stream = stderr;
+ err_output_stream = stderr;
+
+ /* Init EAL */
+ ret = rte_eal_init(argc,argv);
+ if (ret < 0)
+ return -1;
+
+ /* Parse application arguments (after the EAL ones) */
+ ret = app_parse_args(argc, argv);
+ if (ret < 0) {
+ app_print_usage();
+ return -1;
+ }
+
+ /* Init */
+ app_init();
+ app_print_params();
+
+ /* Install the signal handlers */
+ signal(SIGHUP, sigint_handler);
+ signal(SIGINT, sigint_handler);
+ signal(SIGQUIT, sigint_handler);
+ signal(SIGABRT, sigint_handler);
+ signal(SIGTERM, sigint_handler);
+ return 0;
+}
+
+
+int dpdk_run()
+{
+ uint32_t lcore;
+
+#if APP_WATCHDOG
+ pthread_t watchdog_loop_tid, watchdog_olpnet_tid;
+ pthread_create(&watchdog_loop_tid,NULL,watchdog_loop_thread_entry,NULL);
+ pthread_create(&watchdog_olpnet_tid,NULL,app_olp_watchdog_thread_start,NULL);
+#endif
+ /* Launch per-lcore init on every lcore */
+ rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, CALL_MASTER);
+ //rte_eal_mp_remote_launch(app_lcore_main_loop, NULL, SKIP_MASTER);
+
+ RTE_LCORE_FOREACH_SLAVE(lcore) {
+ if (rte_eal_wait_lcore(lcore) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/worker/nl2fwd.h b/worker/nl2fwd.h
new file mode 100644
index 0000000..5277de0
--- /dev/null
+++ b/worker/nl2fwd.h
@@ -0,0 +1,19 @@
+
+/* Header file of new_l2fwd_lib in Load Balance Model.
+ * Autuor : Lu Qiuwen
+ * Date : 2014-03-04
+ */
+
+
+#ifndef __L2FWD_LIB_INCLUDE__
+#define __L2FWD_LIB_INCLUDE__
+
+int dpdk_send_packet_dst(unsigned char *data, int datalen, int dst);
+int dpdk_send_packet_port(const unsigned char *data, int datalen, int port);
+int dpdk_init(int argc, char **argv);
+int dpdk_run();
+int dpdk_register_callfunc(int (*func)(const unsigned char *data,int datalen,int port_in,int lcore));
+int dpdk_register_callfunc_dst(int (*func)(const unsigned char *data,int datalen,int dst,int lcore));
+
+
+#endif
diff --git a/worker/nstat.c b/worker/nstat.c
new file mode 100644
index 0000000..fb37e71
--- /dev/null
+++ b/worker/nstat.c
@@ -0,0 +1,42 @@
+/* Stat Module in Serial-Multiprocess(Client)
+ Author : Lu Qiuwen <[email protected]>
+ Date : 2014-12-07
+*/
+
+#include <sys/mman.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <rte_memory.h>
+#include <rte_debug.h>
+#include <rte_memcpy.h>
+#include <rte_cycles.h>
+
+#include "nstat.h"
+#include "main.h"
+
+#define SHM_FILEMODE 00777
+
+struct nstat_handle * nstat_common_handle = NULL;
+
+int nstat_client_init()
+{
+ int shm_fd = shm_open(NSTAT_SHAREDMEMORY_SYMBOL, O_RDWR, SHM_FILEMODE);
+ ftruncate(shm_fd, sizeof(struct nstat_handle));
+
+ void * shm_ptr = mmap(NULL, sizeof(struct nstat_handle), PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_fd, 0);
+ if(shm_ptr == NULL)
+ rte_panic("cannot connect nstat shared memory");
+
+ nstat_common_handle = (struct nstat_handle *) shm_ptr;
+ return 0;
+}
+
+int nstat_client_destroy()
+{
+ return shm_unlink(NSTAT_SHAREDMEMORY_SYMBOL);
+}
diff --git a/worker/nstat.h b/worker/nstat.h
new file mode 100644
index 0000000..dafbd8f
--- /dev/null
+++ b/worker/nstat.h
@@ -0,0 +1,45 @@
+
+#ifndef __SERIAL_MULTIPROCESS_NSTAT_CLIENT_INCLUDE_H__
+#define __SERIAL_MULTIPROCESS_NSTAT_CLIENT_INCLUDE_H__
+
+#include <rte_mbuf.h>
+#include <nstat_common.h>
+#include "main.h"
+
+// Get the Pkts total length.
+static inline uint64_t nstat_pktslen(struct rte_mbuf ** mbufs, unsigned nb_mbufs)
+{
+ uint64_t datalen = 0;
+ for(int i = 0; i < nb_mbufs; i++)
+ {
+ datalen += mbufs[i]->pkt.pkt_len + APP_PKT_OVERHEAD;
+ }
+
+ return datalen;
+}
+
+static inline void nstat_client_count_wk_pkts(struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ nstat_common_handle->worker_stat[lcore_id].packets += nb_mbufs;
+ nstat_common_handle->worker_stat[lcore_id].bytes += nstat_pktslen(mbufs,nb_mbufs);
+
+ return;
+}
+
+static inline void nstat_client_count_wk_drop(struct rte_mbuf ** mbufs, unsigned nb_mbufs, uint8_t lcore_id)
+{
+ nstat_common_handle->worker_stat[lcore_id].dropped += nb_mbufs;
+ return;
+}
+
+static inline void nstat_client_count_wk_runtime(uint8_t lcore_id, uint64_t runtime)
+{
+ nstat_common_handle->worker_stat[lcore_id].app_runtime += runtime;
+ nstat_common_handle->worker_stat[lcore_id].app_cycles ++;
+ return;
+}
+
+int nstat_client_init();
+int nstat_client_destroy();
+
+#endif
diff --git a/worker/olpnet.c b/worker/olpnet.c
new file mode 100644
index 0000000..03a8686
--- /dev/null
+++ b/worker/olpnet.c
@@ -0,0 +1,212 @@
+/* Watchdong Supply Functions
+ Author. Lu Qiuwen<[email protected]>
+ Date. 2014-05-04
+ */
+
+#include <pcap/pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <libnet.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <arpa/inet.h>
+
+#ifndef OLP_PCAP_ERRBUF_SIZE
+#define OLP_PCAP_ERRBUF_SIZE 512
+#endif
+
+#ifndef OLP_PCAP_SNAPLEN
+#define OLP_PCAP_SNAPLEN 65536
+#endif
+
+typedef uint8_t u_char;
+
+static libnet_t * net_send_dev = NULL;
+static u_char local_mac[6] = {0x30,0xff,0xff,0xff,0xff,0xff};
+static struct in_addr local_ip_addr;
+
+static int bypass_sig = 0;
+static void olp_pktprocess_arp(int request_pkt_len,const u_char *request_pkt)
+{
+ // Filter the arp packet.
+
+ libnet_clear_packet(net_send_dev);
+ struct ether_arp * arp_pkthdr_p = (struct ether_arp *)(request_pkt + sizeof(struct ether_header));
+
+ if(arp_pkthdr_p->arp_op != htons(ARPOP_REQUEST))
+ return;
+
+ u_char src_mac[6];
+ u_char dst_mac[6];
+
+ struct in_addr src_ip;
+ struct in_addr dst_ip;
+ struct in_addr req_ip;
+
+ memcpy(&(req_ip.s_addr),arp_pkthdr_p->arp_tpa,sizeof(u_char) * 4);
+ memcpy(dst_mac,arp_pkthdr_p->arp_sha,sizeof(u_char) * 6);
+ memcpy(&(dst_ip.s_addr),arp_pkthdr_p->arp_spa,sizeof(u_char) * 4);
+ memcpy(src_mac,local_mac,sizeof(u_char) * 6);
+
+ src_ip = local_ip_addr;
+
+ if(req_ip.s_addr != local_ip_addr.s_addr)
+ return;
+
+ libnet_autobuild_arp(ARPOP_REPLY,
+ src_mac,
+ (u_char *)&(src_ip.s_addr),
+ dst_mac,
+ (u_char *)&(dst_ip.s_addr),
+ net_send_dev);
+
+ libnet_autobuild_ethernet(dst_mac,
+ ETHERTYPE_ARP,
+ net_send_dev);
+
+ int result = libnet_write(net_send_dev);
+
+ request_pkt_len = 0;
+
+ return;
+}
+
+static void olp_pktprocess_ip(int request_pkt_len,const u_char *request_pkt)
+{
+ struct ip * ip_hdr = (struct ip *)(request_pkt + sizeof(struct ether_header));
+ struct icmp *icmp_hdr = (struct icmp *)((u_char *)ip_hdr + ip_hdr->ip_hl * 4);
+
+ struct in_addr src_ip;
+ struct in_addr dst_ip;
+
+ libnet_clear_packet(net_send_dev);
+
+ if(ip_hdr->ip_dst.s_addr != local_ip_addr.s_addr)
+ return;
+
+ if(icmp_hdr->icmp_type != ICMP_ECHO)
+ return;
+
+ src_ip = ip_hdr->ip_dst;
+ dst_ip = ip_hdr->ip_src;
+
+ libnet_build_icmpv4_echo(ICMP_ECHOREPLY,
+ 0,0,
+ ntohs(icmp_hdr->icmp_id),
+ ntohs(icmp_hdr->icmp_seq),
+ NULL,
+ 0,net_send_dev,0);
+
+ uint32_t dst_h = (uint32_t)dst_ip.s_addr;
+ uint32_t src_h = (uint32_t)src_ip.s_addr;
+
+ libnet_build_ipv4(sizeof(struct icmp),
+ 0,
+ 0,
+ 0,
+ 64,
+ IPPROTO_ICMP,
+ 0,
+ src_h,
+ dst_h,
+ NULL,
+ 0,
+ net_send_dev,0);
+
+ libnet_autobuild_ethernet(((struct ether_header *)request_pkt)
+ ->ether_shost,
+ ETHERTYPE_IP,
+ net_send_dev);
+
+ libnet_write(net_send_dev);
+ request_pkt_len = 0;
+
+ return;
+}
+
+static void olp_pcap_pkt_callback(u_char *userarg,const struct pcap_pkthdr * pkthdr,const u_char *packet)
+{
+
+ if(bypass_sig)
+ return;
+
+ int * id = (int *)userarg;
+
+ struct ether_header * eth_header_p = (struct ether_header *)packet; // Get the ether head.
+
+ if(eth_header_p->ether_type == htons(ETHERTYPE_ARP))
+ olp_pktprocess_arp(pkthdr->len,packet);
+ if(eth_header_p->ether_type == htons(ETHERTYPE_IP))
+ olp_pktprocess_ip(pkthdr->len,packet);
+
+ id = 0;
+ return;
+}
+
+
+static int olp_init(char *dev)
+{
+ char *errbuf = (char *)malloc(sizeof(char) * OLP_PCAP_ERRBUF_SIZE);
+
+ net_send_dev = libnet_init(LIBNET_LINK,dev,errbuf);
+ if(!net_send_dev) {
+ printf("error:libnet_init:%s",errbuf);
+ return -1;
+ }
+
+ pcap_t * device = pcap_open_live(dev,OLP_PCAP_SNAPLEN,0,0,errbuf);
+ if(!device) {
+ printf("error:pcap_open_live():%s\n",errbuf);
+ return -1;
+ }
+
+ struct bpf_program filter;
+ pcap_compile(device,&filter,"arp or icmp",1,0);
+ pcap_setfilter(device,&filter);
+
+ int id = 0;
+ pcap_loop(device,-1,olp_pcap_pkt_callback,(u_char *)&id);
+ pcap_close(device);
+
+ libnet_destroy(net_send_dev);
+
+ free(errbuf);
+ return 0;
+}
+
+
+int olp_start(char *dev,char *ip)
+{
+ inet_aton(ip,&local_ip_addr);
+ struct ifreq ifreq;
+ int sock;
+
+ //Get the MAC Address
+ if((sock = socket(AF_INET,SOCK_STREAM,0))<0)
+ return -1;
+ strcpy(ifreq.ifr_name,dev);
+ if(ioctl(sock,SIOCGIFHWADDR,&ifreq) < 0)
+ return -1;
+ memcpy(local_mac,&(ifreq.ifr_hwaddr.sa_data),sizeof(u_char) * 6);
+ close(sock);
+
+ olp_init(dev);
+ return 0;
+}
+
+int olp_enable()
+{
+ bypass_sig = 0;
+ return 0;
+}
+
+int olp_disable()
+{
+ bypass_sig = 1;
+ return 0;
+}
diff --git a/worker/olpnet.h b/worker/olpnet.h
new file mode 100644
index 0000000..64d0a7c
--- /dev/null
+++ b/worker/olpnet.h
@@ -0,0 +1,9 @@
+
+#ifndef __INCLUDE_OLPNET_H__
+#define __INCLUDE_OLPNET_H__
+
+int olp_start(char *dev,char *ip);
+int olp_enable();
+int olp_disable();
+
+#endif
diff --git a/worker/runtime.c b/worker/runtime.c
new file mode 100644
index 0000000..6c1ee47
--- /dev/null
+++ b/worker/runtime.c
@@ -0,0 +1,626 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_spinlock.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+
+#include "main.h"
+#include "watchdog.h"
+#include "nstat.h"
+
+#if APP_PACKET_MODIFY_DMAC || APP_PACKET_MODIFY_SMAC
+#include "vlan.h"
+#endif
+
+#ifndef APP_ENERGY_PAUSE
+#define APP_ENERGY_PAUSE 0
+#endif
+
+
+/* Implement by Lu Qiuwen <[email protected]> */
+/* Need to profiled */
+
+//#include <sys/time.h>
+//extern FILE *warn_output_stream;
+//extern FILE *err_output_stream;
+
+
+static inline uint32_t
+power_idle_heuristic(uint32_t zero_rx_packet_count)
+{
+ /* If zero count is less than 100, use it as the sleep time in us */
+ if (zero_rx_packet_count < app.energy.sleep_gear1_threshold)
+ return zero_rx_packet_count;
+ /* If zero count is less than 1000, sleep time should be 100 us */
+ else if ((zero_rx_packet_count >= app.energy.sleep_gear1_threshold) &&
+ (zero_rx_packet_count < app.energy.sleep_gear2_threshold))
+ return app.energy.sleep_gear1_threshold;
+ /* If zero count is greater than 1000, sleep time should be 1000 us */
+ else if (zero_rx_packet_count >= app.energy.sleep_gear2_threshold)
+ return app.energy.sleep_gear2_threshold;
+
+ return 0;
+}
+
+static inline int
+app_pkt_map_call_extern_func(struct rte_mbuf *pkt, uint32_t rx_port, uint32_t tx_port)
+{
+ uint32_t lcore = rte_lcore_id();
+ uint64_t tsc_start,tsc_end;
+ int ret;
+
+ unsigned char * pkt_data = rte_pktmbuf_mtod(pkt,void *);
+ int pkt_len = rte_pktmbuf_data_len(pkt);
+
+#if RTE_VER_MAJOR >= 1 && RTE_VER_MINOR >= 8
+ int in_port = pkt->port;
+#else
+ int in_port = pkt->pkt.in_port;
+#endif
+
+#if APP_STATS
+ tsc_start = rte_rdtsc();
+#endif
+
+ if(app.pkt_callback_f.rx_pkt_process != NULL)
+ {
+ ret = (*app.pkt_callback_f.rx_pkt_process)(pkt_data,pkt_len,in_port,lcore);
+ }
+ else if(app.pkt_callback_f.rx_pkt_process_dst != NULL)
+ {
+
+ int dst = app_port2stream(rx_port,tx_port);
+ ret = (*app.pkt_callback_f.rx_pkt_process_dst)(pkt_data,pkt_len,dst,lcore);
+ }
+
+#if APP_STATS
+ tsc_end = rte_rdtsc();
+ nstat_client_count_wk_runtime(lcore,tsc_end - tsc_start);
+#endif
+
+ return ret;
+}
+
+int app_pkt_process(struct rte_mbuf *pkt, uint8_t *port)
+{
+
+ if(app.map_type == e_APP_MAP_TYPE_PORTMAP) {
+ uint32_t i = 0;
+ for(i = 0; i < app.n_rxtx_port_map ; i++) {
+ if(app.rxtx_port_map[i].rx_port == pkt->pkt.in_port) {
+ uint32_t j = 0;
+ for(j = 0; j < app.rxtx_port_map[i].n_tx_port ; j++) {
+ int rx_port = app.rxtx_port_map[i].rx_port;
+ int tx_port = app.rxtx_port_map[i].tx_port[j];
+ *port = tx_port;
+ //DEBUG:
+ if(app_pkt_map_call_extern_func(pkt,rx_port,tx_port)) {
+ //TODO:Debug,Send to multi-stream will be crash
+ //Because if we send the pkt, the pkt will be released.
+ //After that, what we send again will be unused pointer.
+#if APP_PACKET_MODIFY_DMAC
+ vlan_tag_pkt(pkt,0);
+#endif
+ return 0;
+ }
+ else
+ {
+ return -1; //Drop packets.
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ return -1;
+}
+
+
+/* End */
+
+/* Port from DPDK 1.7.1 examples/load_balancer/runtime.c */
+/* By Lu Qiuwen <[email protected]> at 2014-12-05 */
+
+static inline void
+app_lcore_worker(
+ struct app_lcore_params_worker *lp,
+ uint32_t bsz_rd,
+ uint32_t bsz_wr)
+{
+ uint32_t i;
+ uint64_t lcore_id = rte_lcore_id();
+
+ // Save energy
+ uint32_t lcore_rx_idle_count = 0;
+ uint32_t lcore_idle_hint = 0;
+
+ uint32_t * zero_rx_packet_count = app.energy.wk_zero_rx_packet_count[lcore_id];
+ uint32_t * zero_idle_hint = app.energy.wk_idle_hint[lcore_id];
+
+ for (i = 0; i < lp->n_rings_in; i ++) {
+ struct rte_ring *ring_in = lp->rings_in[i];
+ uint32_t j;
+ uint32_t pos;
+ int ret;
+
+ ret = rte_ring_sc_dequeue_bulk(
+ ring_in,
+ (void **) lp->mbuf_in.array,
+ bsz_rd);
+
+ if (unlikely(ret == -ENOENT)) {
+ zero_rx_packet_count[i]++;
+ if(zero_rx_packet_count[i] < app.energy.min_zero_pull_count)
+ continue;
+ zero_idle_hint[i] = power_idle_heuristic(zero_rx_packet_count[i]);
+ lcore_rx_idle_count++;
+
+ continue;
+ }
+ else {
+ zero_rx_packet_count[i] = zero_rx_packet_count[i] == 0 ? 0 : zero_rx_packet_count[i]--;
+ nstat_client_count_wk_pkts(lp->mbuf_in.array, bsz_rd, lcore_id);
+ }
+
+
+#if APP_WORKER_DROP_ALL_PACKETS
+ for (j = 0; j < bsz_rd; j ++) {
+ struct rte_mbuf *pkt = lp->mbuf_in.array[j];
+ rte_pktmbuf_free(pkt);
+ }
+
+ continue;
+#endif
+
+ APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[0], unsigned char *));
+ APP_WORKER_PREFETCH0(lp->mbuf_in.array[1]);
+
+ for (j = 0; j < bsz_rd; j ++) {
+ struct rte_mbuf *pkt;
+ uint8_t port;
+
+ if (likely(j < bsz_rd - 1)) {
+ APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[j+1], unsigned char *));
+ }
+ if (likely(j < bsz_rd - 2)) {
+ APP_WORKER_PREFETCH0(lp->mbuf_in.array[j+2]);
+ }
+
+ pkt = lp->mbuf_in.array[j];
+
+#if 0
+ if(unlikely(app_portmap_lookup(pkt->pkt.in_port,&port) != 0)) {
+ port = pkt->pkt.in_port;
+ }
+#endif
+
+#if 0
+ if (unlikely(rte_lpm_lookup(lp->lpm_table, ipv4_dst, &port) != 0)) {
+ port = pkt->pkt.in_port;
+ }
+#endif
+
+ if(unlikely(app_pkt_process(pkt, &port))) {
+ //Drop Packet
+ rte_pktmbuf_free(pkt);
+ }
+ else
+ {
+ //Forward Packet
+ pos = lp->mbuf_out[port].n_mbufs;
+ lp->mbuf_out[port].array[pos ++] = pkt;
+ }
+ if (likely(pos < bsz_wr)) {
+ lp->mbuf_out[port].n_mbufs = pos;
+ continue;
+ }
+
+ ret = rte_ring_sp_enqueue_bulk(
+ lp->rings_out[port],
+ (void **) lp->mbuf_out[port].array,
+ bsz_wr);
+
+
+ if (unlikely(ret == -ENOBUFS)) {
+ uint32_t k;
+ nstat_client_count_wk_drop(lp->mbuf_out[port].array, bsz_wr,lcore_id);
+ for (k = 0; k < bsz_wr; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+
+ lp->mbuf_out[port].n_mbufs = 0;
+ lp->mbuf_out_flush[port] = 0;
+ }
+ }
+
+ if(unlikely(lcore_rx_idle_count == lp->n_rings_in))
+ {
+ for(i = 0, lcore_idle_hint = zero_idle_hint[0]; i < lp->n_rings_in; i++)
+ {
+ lcore_idle_hint = lcore_idle_hint > zero_idle_hint[i] ? zero_idle_hint[i] : lcore_idle_hint;
+ }
+ }
+
+ if(app.energy.enable)
+ {
+ if(lcore_idle_hint < app.energy.sleep_gear1_threshold)
+ rte_delay_us(lcore_idle_hint);
+ else
+ usleep(lcore_idle_hint);
+ }
+
+ return;
+}
+
+static inline void
+app_lcore_worker_flush(struct app_lcore_params_worker *lp)
+{
+ uint32_t port;
+ uint8_t lcore_id = rte_lcore_id();
+
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ int ret;
+
+ if (unlikely(lp->rings_out[port] == NULL)) {
+ continue;
+ }
+
+ if (likely((lp->mbuf_out_flush[port] == 0) ||
+ (lp->mbuf_out[port].n_mbufs == 0))) {
+ lp->mbuf_out_flush[port] = 1;
+ continue;
+ }
+
+ ret = rte_ring_sp_enqueue_bulk(
+ lp->rings_out[port],
+ (void **) lp->mbuf_out[port].array,
+ lp->mbuf_out[port].n_mbufs);
+
+ if (unlikely(ret < 0)) {
+ nstat_client_count_wk_drop(lp->mbuf_out[port].array,lp->mbuf_out[port].n_mbufs,lcore_id);
+ uint32_t k;
+ for (k = 0; k < lp->mbuf_out[port].n_mbufs; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+
+ lp->mbuf_out[port].n_mbufs = 0;
+ lp->mbuf_out_flush[port] = 1;
+ }
+}
+
+
+#if 0
+int app_lcore_worker_tx_buffer_to_send (struct rte_mbuf *pkt, uint8_t port)
+{
+ uint32_t lcore = rte_lcore_id();
+ uint32_t bsz_wr = app.burst_size_worker_write;
+ uint32_t n_pkts;
+ uint16_t tx_queueid = lcore % app.worker_core_num;
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+ uint32_t pos;
+#if APP_STATS
+ uint64_t tsc_start, tsc_end;
+#endif
+
+
+ pos = lp->mbuf_out[port].n_mbufs;
+
+ lp->mbuf_out[port].array[pos ++] = pkt;
+ if (likely(pos < bsz_wr)) {
+ lp->mbuf_out[port].n_mbufs = pos;
+ return 0;
+ }
+#if APP_STATS
+ get_stats(lp->mbuf_out[port].array, bsz_wr, lcore, port, tx_queueid, RSYS_TX);
+ tsc_start = rte_rdtsc();
+ get_lcores_stats(lcore, tsc_start, RSYS_LCORE_TX);
+
+#endif
+
+
+ n_pkts = rte_eth_tx_burst(
+ port,
+ tx_queueid,
+ lp->mbuf_out[port].array,
+ (uint16_t) bsz_wr);
+#ifdef APP_DEBUG
+ int debugi;
+ for(debugi = 0; debugi < (int)n_pkts; debugi++)
+ fprintf(stderr,"ETH_TX_BURST/WK:%d(%d)\n",
+ lp->mbuf_out[port].array[debugi]->pkt.data_len,
+ lcore);
+#endif
+
+
+#if APP_STATS
+ tsc_end = rte_rdtsc();
+ get_lcores_stats(lcore, tsc_end, RSYS_LCORE_APP);
+ app_stats[lcore][port][tx_queueid][RSYS_TX].core_cycles[current_index] += (tsc_end - tsc_start);
+
+#endif
+
+ if (unlikely(n_pkts < bsz_wr)) {
+ uint32_t k;
+#if APP_STATS
+ remove_stats(lp->mbuf_out[port].array, bsz_wr - n_pkts, lcore, port, tx_queueid, RSYS_TX);
+#endif
+
+ for (k = n_pkts; k < bsz_wr; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+
+ lp->mbuf_out[port].n_mbufs = 0;
+ lp->mbuf_out_flush[port] = 0;
+
+ return 0;
+}
+
+
+
+#endif
+
+
+#if 0
+
+static inline void
+app_lcore_worker(
+ struct app_lcore_params_worker *lp,
+ uint32_t bsz_rd)
+{
+ uint32_t i,n;
+#if APP_STATS
+ unsigned lcore_id = rte_lcore_id();
+ uint64_t tsc_start, tsc_end;
+#endif
+
+ for (i = 0; i < lp->n_rings_in; i ++)
+ {
+ struct rte_ring *ring_in = lp->rings_in[i];
+ uint32_t j;
+
+#if APP_STATS
+ tsc_start = rte_rdtsc();
+ get_lcores_stats(lcore_id, tsc_start, RSYS_LCORE_RX);
+
+#endif
+
+ n = rte_ring_sc_dequeue_burst(
+ ring_in,
+ (void **) lp->mbuf_in.array,
+ bsz_rd);
+
+ if (unlikely( n == 0)) {
+ continue;
+ }
+#if APP_STATS
+ tsc_end = rte_rdtsc();
+ get_lcores_stats(lcore_id, tsc_end, RSYS_LCORE_APP);
+ app_stats[lcore_id][lcore_conf[lcore_id][i].port_id][lcore_conf[lcore_id][i].queue_id][RSYS_RX].core_cycles[current_index] += (tsc_end - tsc_start);
+ get_stats(lp->mbuf_in.array, n, lcore_id, 0, 0, RSYS_RX);
+#endif
+ //usleep(5000);
+
+#if APP_WORKER_DROP_ALL_PACKETS
+ for (j = 0; j < n; j ++) {
+ struct rte_mbuf *pkt = lp->mbuf_in.array[j];
+ rte_pktmbuf_free(pkt);
+ }
+
+ continue;
+#endif
+
+ APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[0], unsigned char *));
+ APP_WORKER_PREFETCH0(lp->mbuf_in.array[1]);
+
+ for (j = 0; j < n; j ++) {
+ struct rte_mbuf *pkt;
+ uint8_t port;
+
+ if (likely(j < n - 1)) {
+ APP_WORKER_PREFETCH1(rte_pktmbuf_mtod(lp->mbuf_in.array[j+1], unsigned char *));
+ }
+ if (likely(j < n - 2)) {
+ APP_WORKER_PREFETCH0(lp->mbuf_in.array[j+2]);
+ }
+
+ pkt = lp->mbuf_in.array[j];
+
+ if(app_pkt_process(pkt, &port)) {
+ struct rte_mbuf *pkt = lp->mbuf_in.array[j];
+ rte_pktmbuf_free(pkt);
+ }
+
+ }
+ }
+}
+
+static inline void
+app_lcore_worker_flush(struct app_lcore_params_worker *lp)
+{
+ uint32_t port;
+ uint32_t lcore = rte_lcore_id();
+ uint16_t tx_queueid = lcore % app.worker_core_num;
+
+ uint32_t n_pkts;
+#if APP_STATS
+ uint64_t tsc_start, tsc_end;
+#endif
+
+
+ for (port = 0; port < APP_MAX_NIC_PORTS; port ++) {
+ if (likely((lp->mbuf_out_flush[port] == 0) ||
+ (lp->mbuf_out[port].n_mbufs == 0))) {
+ lp->mbuf_out_flush[port] = 1;
+ continue;
+ }
+
+#if APP_STATS
+ get_stats(lp->mbuf_out[port].array, lp->mbuf_out[port].n_mbufs, lcore, port, tx_queueid, RSYS_TX);
+ tsc_start = rte_rdtsc();
+ get_lcores_stats(lcore, tsc_start, RSYS_LCORE_TX);
+
+#endif
+ n_pkts = rte_eth_tx_burst(
+ port,
+ tx_queueid,
+ lp->mbuf_out[port].array,
+ lp->mbuf_out[port].n_mbufs);
+
+#ifdef APP_DEBUG
+ //DEBUG:
+ int debugi;
+ fprintf(stderr,"ETH_TX_BURST/WK_FL-n_mbufs:%d\n",n_pkts);
+ for(debugi = 0; debugi < (int)n_pkts; debugi++)
+ fprintf(stderr,"ETH_TX_BURST/WK_FL:%d(%d)\n",
+ lp->mbuf_out[port].array[debugi]->pkt.data_len,
+ lcore);
+#endif
+
+#if APP_STATS
+ tsc_end = rte_rdtsc();
+ get_lcores_stats(lcore, tsc_end, RSYS_LCORE_APP);
+ app_stats[lcore][port][tx_queueid][RSYS_TX].core_cycles[current_index] += (tsc_end - tsc_start);
+
+#endif
+
+ if (unlikely(n_pkts < lp->mbuf_out[port].n_mbufs)) {
+ uint32_t k;
+#if APP_STATS
+ remove_stats(lp->mbuf_out[port].array, lp->mbuf_out[port].n_mbufs - n_pkts, lcore, port, tx_queueid, RSYS_TX);
+#endif
+
+ for (k = n_pkts; k < lp->mbuf_out[port].n_mbufs; k ++) {
+ struct rte_mbuf *pkt_to_free = lp->mbuf_out[port].array[k];
+ rte_pktmbuf_free(pkt_to_free);
+ }
+ }
+ lp->mbuf_out[port].n_mbufs = 0;
+ lp->mbuf_out_flush[port] = 1;
+ }
+}
+
+
+#endif
+
+static void
+app_lcore_main_loop_worker(void) {
+ uint32_t lcore = rte_lcore_id();
+ struct app_lcore_params_worker *lp = &app.lcore_params[lcore].worker;
+ uint64_t i = 0;
+
+ uint32_t bsz_rd = app.burst_size_worker_read;
+ uint32_t bsz_wr = app.burst_size_worker_write;
+
+ for ( ; ; ) {
+ if (APP_LCORE_WORKER_FLUSH && (unlikely(i == APP_LCORE_WORKER_FLUSH))) {
+ app_lcore_worker_flush(lp);
+ i = 0;
+ }
+
+ app_lcore_worker(lp, bsz_rd, bsz_wr);
+ i ++;
+ }
+}
+
+int
+app_lcore_main_loop(__attribute__((unused)) void *arg)
+{
+ struct app_lcore_params *lp;
+ unsigned lcore;
+
+ lcore = rte_lcore_id();
+ lp = &app.lcore_params[lcore];
+
+ if (lp->type == e_APP_LCORE_WORKER) {
+ printf("Logical core %u (worker %u) main loop.\n",
+ lcore,
+ (unsigned) lp->worker.worker_id);
+ app_lcore_main_loop_worker();
+ }
+
+ return 0;
+}
diff --git a/worker/version.c b/worker/version.c
new file mode 100644
index 0000000..a46723e
--- /dev/null
+++ b/worker/version.c
@@ -0,0 +1,2 @@
+const char __serial_worker_version_20141208__[] __attribute__((used)) = "__SERIAL_WORKER_VERSION_20141208__";
+const char __SERIAL_WORKER_VERSION_20141208__[] __attribute__((used)) = "__SERIAL_WORKER_VERSION_20141208__";
diff --git a/worker/vlan.c b/worker/vlan.c
new file mode 100644
index 0000000..df68a98
--- /dev/null
+++ b/worker/vlan.c
@@ -0,0 +1,93 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <MESA_prof_load.h>
+
+#ifndef VLAN_TAG_MAX_RULES
+#define VLAN_TAG_MAX_RULES 1024
+#endif
+
+#ifndef VLAN_TAG_MAX_STRING
+#define VLAN_TAG_MAX_STRING 1024
+#endif
+
+
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_mbuf.h>
+
+
+#include "main.h"
+
+
+struct port_mac_rule_t
+{
+ uint8_t mac[6];
+ uint32_t port;
+};
+
+struct vlan_tag_paras_t
+{
+ struct port_mac_rule_t rule[VLAN_TAG_MAX_RULES];
+ int n_rules;
+};
+
+static struct vlan_tag_paras_t vlan_tag_paras;
+
+int vlan_tag_rd_paras(char * cfg_path)
+{
+ MESA_load_profile_int_def(cfg_path,"vlan","n_rules",&(vlan_tag_paras.n_rules),0);
+
+ for(int i = 0; i < vlan_tag_paras.n_rules; i++)
+ {
+ char mac_tag[VLAN_TAG_MAX_STRING];
+ char port_tag[VLAN_TAG_MAX_STRING];
+ char mac_value[VLAN_TAG_MAX_STRING];
+ int port_value;
+
+ sprintf(mac_tag,"%d_mac",i);
+ sprintf(port_tag,"%d_port",i);
+
+ if(MESA_load_profile_string_nodef(cfg_path,"vlan",mac_tag,mac_value,VLAN_TAG_MAX_STRING) < 0)
+ return -1;
+ if(MESA_load_profile_int_nodef(cfg_path,"vlan",port_tag,&port_value) < 0)
+ return -2;
+
+ sscanf(mac_value,"%02x:%02x:%02x:%02x:%02x:%02x",&(vlan_tag_paras.rule[i].mac[0]),
+ &(vlan_tag_paras.rule[i].mac[1]),
+ &(vlan_tag_paras.rule[i].mac[2]),
+ &(vlan_tag_paras.rule[i].mac[3]),
+ &(vlan_tag_paras.rule[i].mac[4]),
+ &(vlan_tag_paras.rule[i].mac[5]));
+
+ //For Debug:
+
+ for(int j = 0; j < 6; j++)
+ fprintf(stderr,"%x ",vlan_tag_paras.rule[i].mac[j]);
+
+ fprintf(stderr,"\n");
+
+ vlan_tag_paras.rule[i].port = port_value;
+ }
+
+ return 0;
+}
+
+int vlan_tag_pkt(struct rte_mbuf * pkt,int port)
+{
+ uint8_t * data = pkt->pkt.data;
+ struct ether_hdr * hdr = (struct ether_hdr *)(data);
+
+ for(int i = 0; i < vlan_tag_paras.n_rules; i++)
+ {
+ if(vlan_tag_paras.rule[i].port == port)
+ {
+ memcpy(&(hdr->d_addr),vlan_tag_paras.rule[i].mac,sizeof(uint8_t) * 6);
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/worker/vlan.h b/worker/vlan.h
new file mode 100644
index 0000000..dfc5921
--- /dev/null
+++ b/worker/vlan.h
@@ -0,0 +1,11 @@
+
+#ifndef __VLAN_TAG_INCLUDE_H__
+#define __VLAN_TAG_INCLUDE_H__
+
+
+#include <rte_mbuf.h>
+
+int vlan_tag_rd_paras(char *cfg_path);
+int vlan_tag_pkt(struct rte_mbuf *pkt, int port);
+
+#endif
diff --git a/worker/watchdog.c b/worker/watchdog.c
new file mode 100644
index 0000000..015b543
--- /dev/null
+++ b/worker/watchdog.c
@@ -0,0 +1,241 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <sys/time.h>
+
+
+#include <rte_common.h>
+#include <rte_byteorder.h>
+#include <rte_log.h>
+#include <rte_memory.h>
+#include <rte_memcpy.h>
+#include <rte_memzone.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_launch.h>
+#include <rte_atomic.h>
+#include <rte_cycles.h>
+#include <rte_prefetch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_interrupts.h>
+#include <rte_pci.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ether.h>
+#include <rte_ethdev.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_lpm.h>
+#include <rte_spinlock.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+
+#include "nstat.h"
+#include "main.h"
+#include "olpnet.h"
+
+#define SHM_FILEMODE 00777
+
+struct stat_summerize_t * stat_summerize;
+
+static uint64_t pkt_loss_last = 0;
+static uint64_t pkt_loss_now = 0;
+
+enum watchdog_status_t {
+ WATCHDOG_NORMAL,
+ WATCHDOG_BYPASS
+};
+
+static enum watchdog_status_t watchdog_status;
+
+//Threshold: Lost Packet on Application
+static uint64_t threshold_total_lost_alert = 5000;
+static uint64_t threshold_total_lost_bypass = 20000;
+
+//Threshold: Lost Packet on NIC
+//static uint64_t threshold_buf_last_alert = 6000;
+//static uint64_t threshold_buf_last_bypass = 5000;
+
+//Paras
+static uint64_t sample_time = 1;
+
+//Do para
+static uint64_t threshold_do_count_bypass = 10;
+static uint64_t threshold_do_count_normal = 60;
+static uint64_t threshold_do_count_alert = 0;
+static uint64_t do_bypass_count = 0;
+static uint64_t do_normal_count = 0;
+static uint64_t do_alert_count = 0;
+
+#define ALERT -1
+#define BYPASS -2
+
+static inline uint64_t get_total_lost()
+{
+ return pkt_loss_now - pkt_loss_last;
+}
+
+int app_watchdog_do_bypass()
+{
+ if(do_bypass_count >= threshold_do_count_bypass)
+ {
+ olp_disable();
+ watchdog_status = WATCHDOG_BYPASS;
+ do_bypass_count = 0;
+ }
+ else
+ do_bypass_count++;
+
+ return 0;
+}
+
+int app_watchdog_do_normal()
+{
+ if(do_normal_count >= threshold_do_count_normal)
+ {
+ olp_enable();
+ watchdog_status = WATCHDOG_NORMAL;
+ do_normal_count = 0;
+ }
+ else
+ do_normal_count++;
+
+ return 0;
+}
+
+int app_watchdog_do_alert()
+{
+ if(do_alert_count >= threshold_do_count_alert)
+ {
+ //TODO:
+ }
+ else
+ do_alert_count++;
+
+ return 0;
+}
+
+//状态机:正常情况
+int app_watchdog_check_normal()
+{
+ uint64_t delta_lost = get_total_lost();
+ uint64_t delta_lost_per_sec = delta_lost / sample_time;
+
+ //DEBUG:
+ //printf("watchdog:normal\n");
+
+ if(delta_lost_per_sec >= threshold_total_lost_bypass)
+ {
+ app_watchdog_do_bypass();
+ }
+ else if(delta_lost_per_sec >= threshold_total_lost_alert)
+ {
+ app_watchdog_do_alert();
+ }
+ else
+ {
+ do_bypass_count = 0;
+ do_alert_count = 0;
+ }
+
+ return 0;
+}
+
+int app_watchdog_check_bypass()
+{
+ uint64_t delta_lost = get_total_lost();
+ uint64_t delta_lost_per_sec = delta_lost / sample_time;
+
+ if(delta_lost_per_sec <= threshold_total_lost_bypass)
+ {
+ app_watchdog_do_normal();
+ }
+ else if(delta_lost_per_sec <= threshold_total_lost_alert)
+ {
+ app_watchdog_do_normal();
+ }
+ else
+ {
+ do_bypass_count = 0;
+ do_alert_count = 0;
+ }
+
+ return 0;
+}
+
+void watchdog_init()
+{
+ int shm_fd_sum = shm_open(NSTAT_SHAREMEMORY_SUMMERIZE_SYMBOL, O_RDWR, SHM_FILEMODE);
+ ftruncate(shm_fd_sum, sizeof(struct stat_summerize_t));
+ void * shm_ptr_sum = mmap(NULL, sizeof(struct stat_summerize_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_fd_sum, 0);
+ if(shm_ptr_sum == NULL)
+ rte_panic("cannot create nstat shared memory");
+
+ stat_summerize = shm_ptr_sum;
+ watchdog_status = WATCHDOG_NORMAL;
+
+ return;
+}
+
+void * watchdog_loop_thread_entry()
+{
+ if(!app.watchdog_paras.enable)
+ return (void *)0;
+
+ while(1)
+ {
+ sleep(app.statistics.sample_time);
+
+ pkt_loss_last = pkt_loss_now;
+ rte_rwlock_read_lock(&stat_summerize->rwlock);
+ pkt_loss_now = stat_summerize->dropped;
+ rte_rwlock_read_unlock(&stat_summerize->rwlock);
+
+ if(watchdog_status == WATCHDOG_NORMAL)
+ app_watchdog_check_normal();
+ if(watchdog_status == WATCHDOG_BYPASS)
+ app_watchdog_check_bypass();
+ }
+
+ return (void *)0;
+}
+
+void * app_olp_watchdog_thread_start()
+{
+
+ threshold_total_lost_alert = app.watchdog_paras.threshold_alert_pktloss;
+ threshold_total_lost_bypass = app.watchdog_paras.threshold_bypass_pktloss;
+ sample_time = app.statistics.sample_time;
+
+ threshold_do_count_bypass = app.watchdog_paras.threshold_bypass_do;
+ threshold_do_count_normal = app.watchdog_paras.threshold_normal_do;
+ threshold_do_count_alert = app.watchdog_paras.threshold_alert_do;
+
+ char * watchdog_olp_dev = app.watchdog_paras.dev;
+ char * watchdog_olp_ip = app.watchdog_paras.localip;
+
+ if(app.watchdog_paras.enable)
+ olp_start(watchdog_olp_dev,watchdog_olp_ip);
+
+ return (void *)0;
+}
diff --git a/worker/watchdog.h b/worker/watchdog.h
new file mode 100644
index 0000000..c337ba7
--- /dev/null
+++ b/worker/watchdog.h
@@ -0,0 +1,39 @@
+#ifndef __WATCHLOG_INCLUDE__
+#define __WATCHLOG_INCLUDE__
+
+
+#ifndef APP_DEFAULT_WATCHDOG_ENABLE
+#define APP_DEFAULT_WATCHDOG_ENABLE 1
+#endif
+
+#ifndef APP_DEFAULT_WATCHDOG_THS_BYPASS_LOSSPKT
+#define APP_DEFAULT_WATCHDOG_THS_BYPASS_LOSSPKT 20000
+#endif
+
+#ifndef APP_DEFAULT_WATCHDOG_THS_ALERT_LOSSPKT
+#define APP_DEFAULT_WATCHDOG_THS_ALERT_LOSSPKT 5000
+#endif
+
+#ifndef APP_DEFAULT_WATCHDOG_THS_BYPASS_DO
+#define APP_DEFAULT_WATCHDOG_THS_BYPASS_DO 10
+#endif
+
+#ifndef APP_DEFAULT_WATCHDOG_THS_ALERT_DO
+#define APP_DEFAULT_WATCHDOG_THS_ALERT_DO 10
+#endif
+
+#ifndef APP_DEFAULT_WATCHDOG_THS_NORMAL_DO
+#define APP_DEFAULT_WATCHDOG_THS_NORMAL_DO 50
+#endif
+
+
+int app_watchdog_check_drop();
+int app_watchdog_check_mempool();
+int app_watchdog_do_normal();
+int app_watchdog_do_alert();
+int app_watchdog_do_bypass();
+
+void watchdog_init();
+void * watchdog_loop_thread_entry();
+void * app_olp_watchdog_thread_start();
+#endif