diff options
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)
@@ -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 + * <[email protected]>. + */ +#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 + * <[email protected]>. + */ +#define DLT_ERF 197 + +/* + * Special header prepended to Ethernet packets when capturing from a + * u10 Networks board. Requested by Phil Mulholland + * <[email protected]>. + */ +#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 + * <[email protected]>. + */ +#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 + * <[email protected]>. + */ +#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 + * <[email protected]>. + */ +#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 + * <[email protected]>. + */ +#define DLT_MUX27010 236 + +/* + * STANAG 5066 D_PDUs. Requested by M. Baris Demiray + * <[email protected]>. + */ +#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 Binary files differnew file mode 100644 index 0000000..ee678ba --- /dev/null +++ b/lib/libMESA_prof_load.a diff --git a/lib/libMESA_prof_load.so b/lib/libMESA_prof_load.so Binary files differnew file mode 100644 index 0000000..c640506 --- /dev/null +++ b/lib/libMESA_prof_load.so 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 Binary files differnew file mode 100755 index 0000000..e447e21 --- /dev/null +++ b/logreader/dlogreader 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 Binary files differnew file mode 100644 index 0000000..ee678ba --- /dev/null +++ b/support/MESA_prof_load/lib/libMESA_prof_load.a diff --git a/support/MESA_prof_load/lib/libMESA_prof_load.so b/support/MESA_prof_load/lib/libMESA_prof_load.so Binary files differnew file mode 100644 index 0000000..c640506 --- /dev/null +++ b/support/MESA_prof_load/lib/libMESA_prof_load.so diff --git a/support/MESA_prof_load/src/MESA_prof_load.a b/support/MESA_prof_load/src/MESA_prof_load.a Binary files differnew file mode 100644 index 0000000..8d77dc2 --- /dev/null +++ b/support/MESA_prof_load/src/MESA_prof_load.a 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 @@ -0,0 +1 @@ +./r3 &> /dev/null & @@ -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,ðernet_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
|
