summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author陆秋文 <[email protected]>2016-12-07 19:28:57 +0800
committer陆秋文 <[email protected]>2016-12-07 19:28:57 +0800
commita924438a3e3d1926e03a46edc2f04d857244adf6 (patch)
tree089b76bf2fcd1199638c888aecfa96a8b9fab3f8
parente8e0c94bc5e52eefb5f71775986e89e4d775faf7 (diff)
parente7312311de94cc2c99ea44631d73dcd87ba1adbf (diff)
Merge branch 'dev-4.X.X' into 'rel-4.X.X' v4.0.6-20161207
v4.0.6-20161207发版 v4.0.6-20161207发版 See merge request !10
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt28
-rw-r--r--app/CMakeLists.txt19
-rw-r--r--app/include/mrapp.h52
-rw-r--r--app/src/marsio.c303
-rw-r--r--app/src/rawio.c181
-rw-r--r--app/src/version.map47
-rw-r--r--autorevision.sh1268
-rw-r--r--cmake/Package.cmake14
-rw-r--r--cmake/Version.cmake59
-rw-r--r--core/CMakeLists.txt9
-rw-r--r--core/include/mr_buffer.h47
-rw-r--r--core/include/mr_core.h20
-rw-r--r--core/include/mr_device.h96
-rw-r--r--core/include/mr_mrbuf.h73
-rw-r--r--core/include/mr_rtdev.h87
-rw-r--r--core/include/mr_vnode.h38
-rw-r--r--core/src/buffer.c419
-rw-r--r--core/src/core.c69
-rw-r--r--core/src/device.c490
-rw-r--r--core/src/mrbuf.c256
-rw-r--r--core/src/rtdev.c576
-rw-r--r--core/src/stat.c47
-rw-r--r--core/src/vman.c28
-rw-r--r--core/src/vnode.c108
-rw-r--r--include/CMakeLists.txt6
-rw-r--r--include/external/marsio.h86
-rw-r--r--include/external/marsio_buffer_user_api.h69
-rw-r--r--include/external/marsio_rawio_user_api.h22
-rw-r--r--include/external/marsio_udp_user_api.h32
-rw-r--r--include/internal/mr_common.h (renamed from include/mr_common.h)5
-rw-r--r--include/internal/mr_config.h.in (renamed from include/mr_config.h.in)0
-rw-r--r--include/internal/mr_mask.h (renamed from include/mr_mask.h)0
-rw-r--r--include/internal/mr_version.h.in15
-rw-r--r--include/mr_buffer.h47
-rw-r--r--include/mr_rawio.h27
-rw-r--r--pag/CMakeLists.txt4
-rw-r--r--pag/libpag.c218
-rw-r--r--runtime/include/mr_runtime.h1
-rw-r--r--runtime/src/app.c23
-rw-r--r--service/CMakeLists.txt7
-rw-r--r--service/include/sc_common.h120
-rw-r--r--service/src/cJSON.c2233
-rw-r--r--service/src/cJSON.h165
-rw-r--r--service/src/config.c271
-rw-r--r--service/src/core.c78
-rw-r--r--service/src/ldbc.c222
-rw-r--r--service/src/monit.c164
-rw-r--r--service/src/register.c186
-rw-r--r--service/src/runtime.c104
-rw-r--r--service/src/rxtx.c168
-rw-r--r--slave/CMakeLists.txt12
-rw-r--r--slave/include/mrlib.h17
-rw-r--r--slave/include/mrlib_common.h20
-rw-r--r--slave/src/marsio.c125
-rw-r--r--slave/src/rawio.c216
-rw-r--r--stack/CMakeLists.txt10
-rw-r--r--stack/include/sk_arp.h10
-rw-r--r--stack/include/sk_common.h18
-rw-r--r--stack/include/sk_device.h131
-rw-r--r--stack/include/sk_icmp.h6
-rw-r--r--stack/include/sk_interface.h (renamed from slave/include/mrlib_rtdev.h)0
-rw-r--r--stack/include/sk_ip.h9
-rw-r--r--stack/include/sk_neigh.h128
-rw-r--r--stack/include/sk_pcom.h14
-rw-r--r--stack/include/sk_protocol_arp.h22
-rw-r--r--stack/include/sk_protocol_icmp.h6
-rw-r--r--stack/include/sk_protocol_tcp.h4
-rw-r--r--stack/include/sk_protocol_udp.h4
-rw-r--r--stack/include/sk_route.h46
-rw-r--r--stack/include/sk_stack.h93
-rw-r--r--stack/include/sk_tcp.h7
-rw-r--r--stack/include/sk_ucb.h18
-rw-r--r--stack/include/sk_udp.h14
-rw-r--r--stack/src/arp.c171
-rw-r--r--stack/src/common.c3
-rw-r--r--stack/src/dest.c0
-rw-r--r--stack/src/device.c311
-rw-r--r--stack/src/feedback.c16
-rw-r--r--stack/src/icmp.c80
-rw-r--r--stack/src/interface.c210
-rw-r--r--stack/src/ip.c61
-rw-r--r--stack/src/neigh.c362
-rw-r--r--stack/src/pcom.c58
-rw-r--r--stack/src/protocol-arp.c66
-rw-r--r--stack/src/protocol-icmp.c9
-rw-r--r--stack/src/protocol-udp.c9
-rw-r--r--stack/src/route.c185
-rw-r--r--stack/src/rxtx.c85
-rw-r--r--stack/src/stack.c117
-rw-r--r--stack/src/tcp.c (renamed from stack/src/protocol-tcp.c)4
-rw-r--r--stack/src/ucb.c158
-rw-r--r--stack/src/udp.c92
m---------support/MESA_prof_load0
-rw-r--r--support/MESA_prof_load/.gitignore8
-rw-r--r--support/MESA_prof_load/CMakeLists.txt37
-rw-r--r--support/MESA_prof_load/Makefile13
-rw-r--r--support/MESA_prof_load/README39
-rw-r--r--support/MESA_prof_load/demo/Makefile34
-rw-r--r--support/MESA_prof_load/demo/config.ini11
-rw-r--r--support/MESA_prof_load/demo/demo.c65
-rw-r--r--support/MESA_prof_load/inc/MESA_prof_load.h179
-rw-r--r--support/MESA_prof_load/lib/.gitignore8
-rw-r--r--support/MESA_prof_load/lib/libMESA_prof_load.abin38224 -> 0 bytes
-rw-r--r--support/MESA_prof_load/lib/libMESA_prof_load.sobin32645 -> 0 bytes
-rw-r--r--support/MESA_prof_load/src/MESA_prof_load.abin27984 -> 0 bytes
-rw-r--r--support/MESA_prof_load/src/MESA_prof_load.c806
-rw-r--r--support/MESA_prof_load/src/Makefile46
-rw-r--r--test/CMakeLists.txt8
-rw-r--r--test/TestMrbuf.cc26
-rw-r--r--test/TestStackNeigh.cc93
-rw-r--r--test/TestVMan.cc114
-rw-r--r--test/TestVNode.cc24
-rw-r--r--tools/CMakeLists.txt15
-rw-r--r--tools/stat/dev_stat.c10
115 files changed, 8741 insertions, 4332 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..5d4e99a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "support/MESA_prof_load"]
+ path = support/MESA_prof_load
+ url = [email protected]:luqiuwen/MESA_prof_load.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b6117f2..45729ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,25 +1,12 @@
cmake_minimum_required(VERSION 2.6)
project(marsio)
-# Additive Path
-set(RTE_PREFIX ${RTE_PREFIX} /opt/iiesoft/dpdk)
-set(RTE_PREFIX ${RTE_PREFIX} /opt/iiesoft/)
-
# Include Modules
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
find_package(DPDK REQUIRED)
-include(GetGitRevisionDescription)
-
-# Project Version
-set(MARSIO_MAJOR_VERSION 4)
-set(MARSIO_MINOR_VERSION 0)
-set(MARSIO_PATCH_VERSION 0)
-set(MARSIO_VERSION ${MARSIO_MAJOR_VERSION}.${MARSIO_MINOR_VERSION}.${MARSIO_PATCH_VERSION})
-git_describe(MARSIO_GIT_VERSION)
-set(MARSIO_VERSION "${MARSIO_VERSION},${MARSIO_GIT_VERSION}")
-set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -DGITVER=\\\"${MARSIO_VERSION}\\\"")
-set(EXTRA_CXX_FLAGS "${EXTRA_CXX_FLAGS} -DGITVER=\\\"${MARSIO_VERSION}\\\"")
+# version
+include(Version)
# EXTRA Flags
# GNU99 and C++11 Support
@@ -32,8 +19,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXX_FLAGS}")
# set(CMAKE_INSTALL_PREFIX /opt/iiesoft/marsio)
add_definitions(-fPIC -Wall)
add_definitions(-D_GNU_SOURCE -D__STDC_LIMIT_MACROS)
-include_directories(include)
+include_directories(include/external)
+include_directories(include/internal)
# Install Dirs
set(MR_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
@@ -41,7 +29,7 @@ set(MR_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib)
set(MR_INSTALL_SYSCONFDIR ${CMAKE_INSTALL_PREFIX}/etc)
set(MR_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX}/include)
set(MR_INSTALL_BINDIR ${CMAKE_INSTALL_PREFIX}/bin)
-set(MR_INSTALL_LDCONFDIR /etc/ld.conf.d/)
+set(MR_INSTALL_LDCONFDIR /etc/ld.so.conf.d/)
set(MR_INSTALL_SYSUNITCONFDIR /etc/sysconfig/)
exec_program(pkg-config ARGS systemd --variable=systemdsystemconfdir
@@ -53,11 +41,11 @@ add_subdirectory(${CMAKE_SOURCE_DIR}/runtime)
add_subdirectory(${CMAKE_SOURCE_DIR}/core)
add_subdirectory(${CMAKE_SOURCE_DIR}/stack)
add_subdirectory(${CMAKE_SOURCE_DIR}/service)
-add_subdirectory(${CMAKE_SOURCE_DIR}/slave)
+add_subdirectory(${CMAKE_SOURCE_DIR}/app)
add_subdirectory(${CMAKE_SOURCE_DIR}/pag)
#add_subdirectory(${CMAKE_SOURCE_DIR}/examples)
-add_subdirectory(${CMAKE_SOURCE_DIR}/tools)
-add_subdirectory(${CMAKE_SOURCE_DIR}/test)
+#add_subdirectory(${CMAKE_SOURCE_DIR}/tools)
+#add_subdirectory(${CMAKE_SOURCE_DIR}/test)
add_subdirectory(${CMAKE_SOURCE_DIR}/conf)
if(BUILD_TESTS)
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
new file mode 100644
index 0000000..ab00f78
--- /dev/null
+++ b/app/CMakeLists.txt
@@ -0,0 +1,19 @@
+find_package(DPDK REQUIRED)
+include_directories(${CMAKE_SOURCE_DIR}/include)
+include_directories(${CMAKE_SOURCE_DIR}/include/extern)
+include_directories(${CMAKE_SOURCE_DIR}/include/internal)
+include_directories(${DPDK_INCLUDE_DIR})
+
+include_directories(include)
+add_definitions(${DPDK_C_PREDEFINED})
+add_library(marsio SHARED src/marsio.c src/rawio.c)
+
+set_target_properties(marsio PROPERTIES VERSION ${MARSIO_VERSION_MAJOR}.${MARSIO_VERSION_MINOR})
+set_target_properties(marsio PROPERTIES SOVERSION ${MARSIO_VERSION_MAJOR})
+set_target_properties(marsio PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/src/version.map")
+target_link_libraries(marsio PRIVATE -Wl,--whole-archive mruntime core stack -Wl,--no-whole-archive)
+target_link_libraries(marsio PRIVATE ${DPDK_LIBRARY} rt pthread dl)
+target_include_directories(marsio INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/")
+
+install(TARGETS marsio LIBRARY DESTINATION lib COMPONENT Program)
+#install(FILES libpag.h DESTINATION include COMPONENT Program) \ No newline at end of file
diff --git a/app/include/mrapp.h b/app/include/mrapp.h
new file mode 100644
index 0000000..60134ea
--- /dev/null
+++ b/app/include/mrapp.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <mr_common.h>
+#include <mr_device.h>
+#include <unistd.h>
+
+struct raw_socket;
+TAILQ_HEAD(raw_socket_list, __raw_socket);
+
+struct __devinfo
+{
+ unsigned int dev_id;
+ char devsym[MR_SYMBOL_MAX];
+};
+
+struct raw_socket;
+
+struct mrapp_config
+{
+ FILE * logstream;
+ cpu_mask_t coremask;
+ unsigned int nr_thread;
+ unsigned int autoexit;
+ unsigned int nr_raw_rxstream;
+ unsigned int nr_raw_txstream;
+ unsigned int nr_stack_rxstream;
+ unsigned int nr_stack_txstream;
+ unsigned int nr_raw_device;
+ unsigned int nr_stack_device;
+
+ struct __devinfo raw_open_device[MR_DEVICE_MAX];
+ struct __devinfo stack_open_device[MR_DEVICE_MAX];
+};
+
+struct mrapp_instance
+{
+ /* Ӧ������ */
+ char appsym[MR_SYMBOL_MAX];
+ /* ����� */
+ struct mrapp_config config;
+ /* Coreȫ�־�� */
+ struct mr_core_instance * core_instance;
+ /* StackӦ�þ�� */
+ struct sk_app_instance * sk_app_instance;
+ /* Raw�豸��� */
+ struct raw_socket * raw_socket[MR_DEVICE_MAX];
+};
+
+/* ��־λ���Ƿ��Ѿ������˳�ʼ��*/
+extern int mrapp_inited;
+/* ��־λ�����߳��Ƿ��Ѿ������˳�ʼ�� */
+extern int __thread mrapp_thread_inited; \ No newline at end of file
diff --git a/app/src/marsio.c b/app/src/marsio.c
new file mode 100644
index 0000000..7ee1e43
--- /dev/null
+++ b/app/src/marsio.c
@@ -0,0 +1,303 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <rte_log.h>
+#include <mr_common.h>
+#include <mr_core.h>
+#include <rte_malloc.h>
+#include <mr_runtime.h>
+#include <sk_stack.h>
+#include <mrapp.h>
+#include <marsio.h>
+#include "mr_mask.h"
+
+/* ��־λ���Ƿ��Ѿ������˳�ʼ��*/
+int mrapp_inited = 0;
+/* ��־λ�����߳��Ƿ��Ѿ������˳�ʼ�� */
+int __thread mrapp_thread_inited = 0;
+/* ���������Ľṹ */
+struct mrapp_instance * instance = NULL;
+/* ������Ϣ */
+struct mrapp_config mrapp_config;
+
+#define MR_LIB_MAX_EAL_ARGC 128
+
+/* �Command���� */
+static void __write_arg(char * eal_argv[], unsigned int * eal_argc,
+ unsigned int max_argc, const char * value)
+{
+ assert(max_argc >= *eal_argc);
+ char * mem = (char *)malloc(MR_STRING_MAX * sizeof(char));
+ assert(mem != NULL);
+
+ snprintf(mem, MR_STRING_MAX * sizeof(char), "%s", value);
+ eal_argv[(*eal_argc)++] = mem;
+ return;
+}
+
+#define WRITE_ARG(x) \
+ do {__write_arg(eal_argv, &eal_argc, MR_LIB_MAX_EAL_ARGC, x);} \
+ while(0)
+
+extern int mrapp_init_open_raw_device(struct mrapp_instance * instance);
+extern void mrapp_destory_close_raw_device(struct mrapp_instance * instance);
+
+/* EAL������ʼ�� */
+static void mrapp_eal_init(struct mrapp_config * config)
+{
+ if (config->logstream == NULL) config->logstream = stderr;
+ rte_openlog_stream(config->logstream);
+
+ char * eal_argv[MR_LIB_MAX_EAL_ARGC];
+ unsigned int eal_argc = 0;
+
+ WRITE_ARG("mrlib");
+ WRITE_ARG("-c");
+ WRITE_ARG("0x1");
+ WRITE_ARG("--proc-type=secondary");
+
+ int ret = rte_eal_init(eal_argc, eal_argv);
+ MR_CHECK(ret >= 0, "Cannot init EAL Enviorment, Failed");
+ return;
+}
+
+struct mrapp_instance * mrapp_instance_create(const char * appsym, struct mrapp_config * config)
+{
+ struct mrapp_instance * _instance = rte_zmalloc(NULL, sizeof(struct mrapp_instance), 0);
+ MR_CHECK(_instance != NULL, "Cannot alloc memory for mrapp instance");
+
+ snprintf(_instance->appsym, sizeof(instance->appsym), "%s", appsym);
+ _instance->config = *config;
+ return _instance;
+}
+
+void mrapp_instance_destory(struct mrapp_instance * instance)
+{
+ rte_free(instance);
+ return;
+}
+
+static int mrapp_config_check(const char * appsym, struct mrapp_config * config)
+{
+ // �û�û��ָ���߳������Ӻ����������
+ if (config->nr_thread == 0) config->nr_thread = mask_popcnt(config->coremask);
+
+ // û��ָ���ա����������շ��������߳���һ��
+ config->nr_raw_rxstream = config->nr_raw_rxstream == 0 ?
+ config->nr_thread : config->nr_raw_rxstream;
+ config->nr_raw_txstream = config->nr_raw_txstream == 0 ?
+ config->nr_thread : config->nr_raw_txstream;
+ config->nr_stack_rxstream = config->nr_stack_rxstream == 0 ?
+ config->nr_thread : config->nr_stack_rxstream;
+ config->nr_stack_txstream = config->nr_stack_txstream == 0 ?
+ config->nr_thread : config->nr_stack_txstream;
+
+ // �������
+ if(config->nr_thread <= 0)
+ {
+ MR_LOG(ERR, MRLIB, "Invalid thread number or coremask(thread number<=0). \n");
+ return -EINVAL;
+ }
+
+ if(config->nr_raw_rxstream > config->nr_thread)
+ {
+ MR_LOG(ERR, MRLIB, "Invalid raw rxstream number(>thread number). \n");
+ return -EINVAL;
+ }
+
+ if(config->nr_raw_txstream > config->nr_thread)
+ {
+ MR_LOG(ERR, MRLIB, "Invalid raw txstream number(>thread number). \n");
+ return -EINVAL;
+ }
+
+ if (config->nr_stack_rxstream > config->nr_thread)
+ {
+ MR_LOG(ERR, MRLIB, "Invalid stack rxstream number(>thread number). \n");
+ return -EINVAL;
+ }
+
+ if (config->nr_stack_txstream > config->nr_thread)
+ {
+ MR_LOG(ERR, MRLIB, "Invalid stack txstream number(>thread number). \n");
+ return -EINVAL;
+ }
+
+ // ��ӡ����
+ MR_LOG(INFO, MRLIB, "Marsio Config: \n");
+ MR_LOG(INFO, MRLIB, " Dataplane Thread Count: %d\n", config->nr_thread);
+ MR_LOG(INFO, MRLIB, " Raw rxstream: %d\n", config->nr_raw_rxstream);
+ MR_LOG(INFO, MRLIB, " Raw txstream: %d\n", config->nr_raw_txstream);
+ MR_LOG(INFO, MRLIB, " Stack rxstream: %d\n", config->nr_stack_rxstream);
+ MR_LOG(INFO, MRLIB, " Stack txstream: %d\n", config->nr_stack_txstream);
+ return 0;
+}
+
+static int mrapp_init(const char * appsym, struct mrapp_config * config)
+{
+ // �����
+ int ret = mrapp_config_check(appsym, config);
+ if(ret < 0)
+ {
+ MR_LOG(ERR, MRLIB, "Marsio config check failed. \n");
+ return ret;
+ }
+
+ // Ӧ��ע��
+ ret = mr_app_register(appsym, config->coremask, config->autoexit);
+ if (ret < 0)
+ {
+ MR_LOG(ERR, MRLIB, "Cannot register application %s. \n", appsym);
+ return -1;
+ }
+
+ MR_LOG(INFO, MRLIB, "Application %s register success. \n", appsym);
+
+ // ������̵�Privָ�벻Ϊ�գ�˵����ǰ���й����ָ�������
+ if ((instance = mr_app_priv_get()) != NULL)
+ mrapp_instance_destory(instance);
+
+ instance = mrapp_instance_create(appsym, config);
+ assert(instance != NULL);
+
+ // ��ȫ��Core���
+ struct mr_global_ctx * g_ctx = mr_global_ctx_get();
+ mr_core_default_instance_set(g_ctx->ctx_core);
+ instance->core_instance = g_ctx->ctx_core;
+
+ // ע��Э��ջ���
+ struct sk_app_instance * sk_app_instance = sk_app_instance_create(
+ g_ctx->ctx_stack, instance->appsym);
+
+ if (sk_app_instance == NULL)
+ {
+ MR_LOG(ERR, MRLIB, "Cannot create stack app instance for app %s. \n",
+ instance->appsym);
+ return -1;
+ }
+
+ sk_default_instance_set(g_ctx->ctx_stack, sk_app_instance);
+ instance->sk_app_instance = sk_app_instance;
+
+ ret = mrapp_init_open_raw_device(instance);
+ if (ret < 0)
+ {
+ MR_LOG(ERR, MRLIB, "Open raw devices failed. \n");
+ return ret;
+ }
+
+ return 0;
+}
+
+int __option_set_raw_device(struct mrapp_config * config, const char * devsym)
+{
+ if (config->nr_raw_device >= MR_DEVICE_MAX)
+ return -ENOMEM;
+
+ struct __devinfo * p_devinfo = &config->raw_open_device[config->nr_raw_device];
+ snprintf(p_devinfo->devsym, sizeof(p_devinfo->devsym), "%s", devsym);
+ p_devinfo->dev_id = config->nr_raw_device;
+ config->nr_raw_device++;
+ return p_devinfo->dev_id;
+}
+
+int __option_set_stack_device(struct mrapp_config * config, const char * devsym)
+{
+ if (config->nr_stack_device >= MR_DEVICE_MAX)
+ return -ENOMEM;
+
+ struct __devinfo * p_devinfo = &config->stack_open_device[config->nr_stack_device];
+ snprintf(p_devinfo->devsym, sizeof(p_devinfo->devsym), "%s", devsym);
+ p_devinfo->dev_id = config->nr_raw_device;
+ config->nr_stack_device++;
+ return p_devinfo->dev_id;
+}
+
+int marsio_option_set(const char * appsym, marsio_opt_type_t opt_type, void * opt, size_t sz_opt)
+{
+
+#define __CHECK_USER_PARAM(expect_type) do { \
+ if(sz_opt < sizeof(expect_type)) { return -EINVAL; } \
+} while(0)
+
+ struct mrapp_config * config = &mrapp_config;
+ int ret = 0;
+
+ switch(opt_type)
+ {
+ case MARSIO_OPT_THREAD_NUM:
+ __CHECK_USER_PARAM(unsigned int);
+ config->nr_thread = *(unsigned int *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_THREAD_MASK:
+ __CHECK_USER_PARAM(uint64_t);
+ config->coremask = *(uint64_t *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_AUTOEXIT:
+ __CHECK_USER_PARAM(unsigned int);
+ config->autoexit = *(unsigned int *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_FILE_LOG:
+ __CHECK_USER_PARAM(FILE *);
+ config->logstream = (FILE *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_RAW_RX_STREAM_NUM:
+ __CHECK_USER_PARAM(unsigned int);
+ config->nr_raw_rxstream = *(unsigned int *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_RAW_TX_STREAM_NUM:
+ __CHECK_USER_PARAM(unsigned int);
+ config->nr_raw_txstream = *(unsigned int *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_STACK_RX_STREAM_NUM:
+ __CHECK_USER_PARAM(unsigned int);
+ config->nr_stack_rxstream = *(unsigned int *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_STACK_TX_STREAM_NUM:
+ __CHECK_USER_PARAM(unsigned int);
+ config->nr_stack_txstream = *(unsigned int *)opt;
+ ret = 0; break;
+ case MARSIO_OPT_RAW_DEVICE:
+ __CHECK_USER_PARAM(char *);
+ ret = __option_set_raw_device(config, (const char *)opt);
+ break;
+ case MARSIO_OPT_STACK_DEVICE:
+ __CHECK_USER_PARAM(char *);
+ ret = __option_set_stack_device(config, (const char *)opt);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+int marsio_option_get(const char * appsym, int opt_type, void * out_opt, size_t out_opt_buffer)
+{
+ return 0;
+}
+
+int marsio_init(const char * appsym)
+{
+ mrapp_eal_init(&mrapp_config);
+ return mrapp_init(appsym, &mrapp_config);
+}
+
+int marsio_thread_init()
+{
+ mr_thread_register();
+ return 0;
+}
+
+int marsio_destory()
+{
+ mrapp_destory_close_raw_device(instance);
+ return 0;
+}
+
+void marsio_on_exit_register(void(*exit_fn)(void * arg), void * arg)
+{
+ mr_on_exit_register(exit_fn, arg);
+} \ No newline at end of file
diff --git a/app/src/rawio.c b/app/src/rawio.c
new file mode 100644
index 0000000..5328627
--- /dev/null
+++ b/app/src/rawio.c
@@ -0,0 +1,181 @@
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+
+#include <mrapp.h>
+#include <mr_vnode.h>
+#include <mr_stat.h>
+#include <mr_rtdev.h>
+#include <mr_runtime.h>
+#include <mr_device.h>
+
+#include <marsio.h>
+
+extern struct mrapp_instance * instance;
+extern int __option_set_raw_device(struct mrapp_config * config, const char * devsym);
+extern int __option_set_stack_device(struct mrapp_config * config, const char * devsym);
+
+struct raw_socket
+{
+ // ������
+ TAILQ_ENTRY(__raw_socket) next;
+ // �豸������
+ char devsym[MR_SYMBOL_MAX];
+ // Raw�ӿڶ������߳���
+ unsigned int nr_rxstream;
+ // Raw�ӿ�д�����߳���
+ unsigned int nr_txstream;
+ // Raw�ӿھ��
+ struct rtdev_app_desc * rtdev_desc;
+};
+
+// �򿪵�Socket��¼����ɾ����������Ѿ��򿪵�Socket��¼�����������û��ظ�����ɴ���
+
+int raw_socket_close(struct raw_socket * socket)
+{
+ struct raw_socket * _socket = (struct raw_socket *)socket;
+ mr_rt_device_close(_socket->rtdev_desc);
+ return 0;
+}
+
+struct raw_socket * raw_socket_open(const char * devsym,
+ unsigned int nr_rx_stream, unsigned int nr_tx_stream, unsigned int flags)
+{
+ struct mr_global_ctx * g_ctx = mr_global_ctx_get();
+ struct raw_socket * socket = rte_zmalloc(NULL, sizeof(struct raw_socket), 0);
+ if(unlikely(socket == NULL))
+ {
+ MR_LOG(ERR, MRLIB, "Cannot alloc memory for RawSocket"
+ "(devsym=%s, nr_rx_stream=%d, nr_tx_stream=%d, flags=%x)\n",
+ devsym, nr_rx_stream, nr_tx_stream, flags);
+ goto errout;
+ }
+
+ snprintf(socket->devsym, sizeof(socket->devsym), "%s", devsym);
+ socket->nr_rxstream = nr_rx_stream;
+ socket->nr_txstream = nr_tx_stream;
+
+ // ������ʱ�豸
+ struct rtdev_app_desc * _rtdev_desc = NULL;
+ _rtdev_desc = mr_rt_device_open(g_ctx->ctx_core, devsym, instance->appsym,
+ nr_rx_stream, nr_tx_stream);
+
+ if(unlikely(_rtdev_desc == NULL))
+ {
+ MR_LOG(ERR, MRLIB, "MarsioRawSocket: Open rt-device %s"
+ "(nr_rx_stream=%d, nr_tx_stream=%d, flags=%x) failed. \n",
+ devsym, nr_rx_stream, nr_tx_stream, flags);
+ goto errout;
+ }
+
+ socket->rtdev_desc = _rtdev_desc;
+ return socket;
+
+errout:
+ if (socket != NULL) rte_free(socket);
+ return NULL;
+}
+
+static int __set_all_raw_device_open(struct mrapp_instance * instance,
+ struct mrapp_config * config)
+{
+ struct mr_dev * dev_list[MR_DEVICE_MAX];
+ int nr_dev_list = 0;
+
+ // ��õ�ǰ���õ����������豸
+ nr_dev_list = mr_device_list(instance->core_instance, dev_list, MR_DEVICE_MAX, 0);
+ if (nr_dev_list < 0) return nr_dev_list;
+
+ // �������е������豸
+ for(int i = 0; i < nr_dev_list; i++)
+ __option_set_raw_device(config, dev_list[i]->symbol);
+
+ return 0;
+}
+
+int mrapp_init_open_raw_device(struct mrapp_instance * instance)
+{
+ struct mrapp_config * config = &instance->config;
+
+ // û���������õ��豸��Ӧ��ʹ��ȫ���豸
+ if (config->nr_raw_device == 0)
+ __set_all_raw_device_open(instance, config);
+
+ for(int i = 0; i < config->nr_raw_device; i++)
+ {
+ struct __devinfo * devinfo = &config->raw_open_device[i];
+ struct raw_socket * socket = raw_socket_open(devinfo->devsym,
+ config->nr_raw_rxstream, config->nr_raw_txstream, 0);
+
+ if(socket == NULL)
+ {
+ MR_LOG(INFO, MRLIB, "Raw device %s(device_id=%d) open failed. \n",
+ devinfo->devsym, devinfo->dev_id);
+ continue;
+ }
+
+ instance->raw_socket[devinfo->dev_id] = socket;
+ MR_LOG(INFO, MRLIB, "Raw device %s(device_id=%d) open successfully. \n",
+ devinfo->devsym, devinfo->dev_id);
+ }
+
+ return 0;
+}
+
+
+void mrapp_destory_close_raw_device(struct mrapp_instance * instance)
+{
+ for(int i = 0; i < MR_DEVICE_MAX; i++)
+ {
+ if (instance->raw_socket[i] == NULL) continue;
+ raw_socket_close(instance->raw_socket[i]);
+ }
+
+ return;
+}
+
+int marsio_raw_recv_burst(device_id_t dev_id, thread_id_t sid,
+ marsio_buff_t * mbufs[], int nr_max_mbufs)
+{
+ struct raw_socket * _socket = instance->raw_socket[dev_id];
+ if (unlikely(_socket == NULL))
+ {
+ MR_LOG(DEBUG, MRLIB, "%s: Invalid Parameters - dev_id=%d is invalid.\n",
+ __FUNCTION__, dev_id); return -EINVAL;
+ }
+
+ if (unlikely(sid >= _socket->nr_rxstream))
+ {
+ MR_LOG(DEBUG, MRLIB, "%s: Invalid Parameters - sid=%d is invalid.\n",
+ __FUNCTION__, sid); return -EINVAL;
+ }
+
+ mr_thread_hook();
+
+ int ret = vnode_dequeue_burst(_socket->rtdev_desc->vnode_cons_rx,
+ &_socket->rtdev_desc->ops, sid, (void **)mbufs, nr_max_mbufs);
+ return ret;
+}
+
+static inline hash_t __raw_send_pkt_hash(struct rte_mbuf * mbuf)
+{
+ return mbuf->hash.rss;
+}
+
+int marsio_raw_send_burst(device_id_t dev_id, thread_id_t sid,
+ marsio_buff_t * mbufs[], int nr_mbufs)
+{
+ struct raw_socket * _socket = instance->raw_socket[dev_id];
+ if (unlikely(_socket == NULL))
+ {
+ MR_LOG(DEBUG, MRLIB, "%s: Invalid Parameters - dev_id=%d is invalid.\n",
+ __FUNCTION__, dev_id); return -EINVAL;
+ }
+
+ if (unlikely(sid >= _socket->nr_txstream))
+ {
+ MR_LOG(DEBUG, MRLIB, "%s: Invalid Parameters - sid=%d is invalid.\n",
+ __FUNCTION__, dev_id); return -EINVAL;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/app/src/version.map b/app/src/version.map
new file mode 100644
index 0000000..bbfa69c
--- /dev/null
+++ b/app/src/version.map
@@ -0,0 +1,47 @@
+LIBPAG {
+global:
+ marsio_init;
+ marsio_thread_init;
+ marsio_destory;
+ marsio_on_exit_register;
+ marsio_option_set;
+ marsio_option_get;
+
+ marsio_raw_recv_burst;
+ marsio_raw_send_burst;
+
+ marsio_buff_malloc;
+ marsio_buff_free;
+ marsio_buff_ctrlzone;
+ marsio_buff_ctrlzone_data;
+ marsio_buff_ctrlzone_set;
+ marsio_buff_reset;
+ marsio_buff_getnext_seg;
+ marsio_buff_getnext_pkt;
+ marsio_buff_append_pkt;
+ marsio_buff_append_seg;
+ marsio_buff_headroom;
+ marsio_buff_tailroom;
+ marsio_buff_getnext_seg;
+ marsio_buff_getnext_pkt;
+ marsio_buff_mtod;
+ marsio_buff_buflen;
+ marsio_buff_datalen;
+ marsio_buff_prepend;
+ marsio_buff_append;
+ marsio_buff_adj;
+ marsio_buff_trim;
+ marsio_buff_headroom;
+ marsio_buff_tailroom;
+ marsio_get_pkt_type;
+ marsio_buff_dup;
+
+ marsio_socket;
+ marsio_connect;
+ marsio_bind;
+ marsio_udp_alloc;
+ marsio_udp_free;
+ marsio_udp_sendto_chain;
+
+local: *;
+}; \ No newline at end of file
diff --git a/autorevision.sh b/autorevision.sh
new file mode 100644
index 0000000..3baa179
--- /dev/null
+++ b/autorevision.sh
@@ -0,0 +1,1268 @@
+#!/bin/sh
+
+# Copyright (c) 2012 - 2016 dak180 and contributors. See
+# https://opensource.org/licenses/mit-license.php or the included
+# COPYING.md for licence terms.
+#
+# autorevision - extracts metadata about the head version from your
+# repository.
+
+# Usage message.
+arUsage() {
+ cat > "/dev/stderr" << EOF
+usage: autorevision {-t output-type | -s symbol} [-o cache-file [-f] ] [-V]
+ Options include:
+ -t output-type = specify output type
+ -s symbol = specify symbol output
+ -o cache-file = specify cache file location
+ -f = force the use of cache data
+ -U = check for untracked files in svn
+ -V = emit version and exit
+ -? = help message
+
+The following are valid output types:
+ clojure = clojure file
+ c = C/C++ file
+ h = Header for use with c/c++
+ hpp = Alternate C++ header strings with namespace
+ ini = INI file
+ java = Java file
+ javaprop = Java properties file
+ js = javascript file
+ json = JSON file
+ lua = Lua file
+ m4 = m4 file
+ matlab = matlab file
+ octave = octave file
+ php = PHP file
+ pl = Perl file
+ py = Python file
+ rpm = rpm file
+ scheme = scheme file
+ sh = Bash sytax
+ swift = Swift file
+ tex = (La)TeX file
+ xcode = Header useful for populating info.plist files
+ cmake = CMake file
+
+
+The following are valid symbols:
+ VCS_TYPE
+ VCS_BASENAME
+ VCS_UUID
+ VCS_NUM
+ VCS_DATE
+ VCS_BRANCH
+ VCS_TAG
+ VCS_TICK
+ VCS_EXTRA
+ VCS_FULL_HASH
+ VCS_SHORT_HASH
+ VCS_WC_MODIFIED
+ VCS_ACTION_STAMP
+EOF
+ exit 1
+}
+
+# Config
+ARVERSION="&&ARVERSION&&"
+TARGETFILE="/dev/stdout"
+while getopts ":t:o:s:VfU" OPTION; do
+ case "${OPTION}" in
+ t)
+ AFILETYPE="${OPTARG}"
+ ;;
+ o)
+ CACHEFILE="${OPTARG}"
+ ;;
+ f)
+ CACHEFORCE="1"
+ ;;
+ s)
+ VAROUT="${OPTARG}"
+ ;;
+ U)
+ UNTRACKEDFILES="1"
+ ;;
+ V)
+ echo "autorevision ${ARVERSION}"
+ exit 0
+ ;;
+ ?)
+ # If an unknown flag is used (or -?):
+ arUsage
+ ;;
+ esac
+done
+
+if [ ! -z "${VAROUT}" ] && [ ! -z "${AFILETYPE}" ]; then
+ # If both -s and -t are specified:
+ echo "error: Improper argument combination." 1>&2
+ exit 1
+elif [ -z "${VAROUT}" ] && [ -z "${AFILETYPE}" ]; then
+ # If neither -s or -t are specified:
+ arUsage
+elif [ -z "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then
+ # If -f is specified without -o:
+ arUsage
+elif [ ! -f "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then
+ # If we are forced to use the cache but it does not exist.
+ echo "error: Cache forced but no cache found." 1>&2
+ exit 1
+fi
+
+# Make sure that the path we are given is one we can source
+# (dash, we are looking at you).
+if [ ! -z "${CACHEFILE}" ] && ! echo "${CACHEFILE}" | grep -q '^\.*/'; then
+ CACHEFILE="./${CACHEFILE}"
+fi
+
+GENERATED_HEADER="Generated by autorevision - do not hand-hack!"
+
+# Functions to extract data from different repo types.
+# For git repos
+# shellcheck disable=SC2039,SC2164,SC2155
+gitRepo() {
+ local oldPath="${PWD}"
+
+ cd "$(git rev-parse --show-toplevel)"
+
+ VCS_TYPE="git"
+
+ VCS_BASENAME="$(basename "${PWD}")"
+
+ VCS_UUID="$(git rev-list --max-parents=0 --date-order --reverse HEAD 2>/dev/null | sed -n 1p)"
+ if [ -z "${VCS_UUID}" ]; then
+ VCS_UUID="$(git rev-list --topo-order HEAD | tail -n 1)"
+ fi
+
+ # Is the working copy clean?
+ test -z "$(git status --untracked-files=normal --porcelain)"
+ VCS_WC_MODIFIED="${?}"
+
+ # Enumeration of changesets
+ VCS_NUM="$(git rev-list --count HEAD 2>/dev/null)"
+ if [ -z "${VCS_NUM}" ]; then
+ echo "warning: Counting the number of revisions may be slower due to an outdated git version less than 1.7.2.3. If something breaks, please update it." 1>&2
+ VCS_NUM="$(git rev-list HEAD | wc -l)"
+ fi
+
+ # This may be a git-svn remote. If so, report the Subversion revision.
+ if [ -z "$(git config svn-remote.svn.url 2>/dev/null)" ]; then
+ # The full revision hash
+ VCS_FULL_HASH="$(git rev-parse HEAD)"
+
+ # The short hash
+ VCS_SHORT_HASH="$(echo "${VCS_FULL_HASH}" | cut -b 1-7)"
+ else
+ # The git-svn revision number
+ VCS_FULL_HASH="$(git svn find-rev HEAD)"
+ VCS_SHORT_HASH="${VCS_FULL_HASH}"
+ fi
+
+ # Current branch
+ VCS_BRANCH="$(git rev-parse --symbolic-full-name --verify "$(git name-rev --name-only --no-undefined HEAD 2>/dev/null)" 2>/dev/null | sed -e 's:refs/heads/::' | sed -e 's:refs/::')"
+
+ # Cache the description
+ local DESCRIPTION="$(git describe --long --tags 2>/dev/null)"
+
+ # Current or last tag ancestor (empty if no tags)
+ VCS_TAG="$(echo "${DESCRIPTION}" | sed -e "s:-g${VCS_SHORT_HASH}\$::" -e 's:-[0-9]*$::')"
+
+ # Distance to last tag or an alias of VCS_NUM if there is no tag
+ if [ ! -z "${DESCRIPTION}" ]; then
+ VCS_TICK="$(echo "${DESCRIPTION}" | sed -e "s:${VCS_TAG}-::" -e "s:-g${VCS_SHORT_HASH}::")"
+ else
+ VCS_TICK="${VCS_NUM}"
+ fi
+
+ # Date of the current commit
+ VCS_DATE="$(TZ=UTC git show -s --date=iso-strict-local --pretty=format:%ad | sed -e 's|+00:00|Z|')"
+ if [ -z "${VCS_DATE}" ]; then
+ echo "warning: Action stamps require git version 2.7+." 1>&2
+ VCS_DATE="$(git log -1 --pretty=format:%ci | sed -e 's: :T:' -e 's: ::' -e 's|+00:00|Z|')"
+ local ASdis="1"
+ fi
+
+ # Action Stamp
+ if [ -z "${ASdis}" ]; then
+ VCS_ACTION_STAMP="${VCS_DATE}!$(git show -s --pretty=format:%cE)"
+ else
+ VCS_ACTION_STAMP=""
+ fi
+
+ cd "${oldPath}"
+}
+
+# For hg repos
+# shellcheck disable=SC2039,SC2164
+hgRepo() {
+ local oldPath="${PWD}"
+
+ cd "$(hg root)"
+
+ VCS_TYPE="hg"
+
+ VCS_BASENAME="$(basename "${PWD}")"
+
+ VCS_UUID="$(hg log -r "0" -l 1 --template '{node}\n')"
+
+ # Is the working copy clean?
+ test -z "$(hg status -duram)"
+ VCS_WC_MODIFIED="${?}"
+
+ # Enumeration of changesets
+ VCS_NUM="$(hg id -n | tr -d '+')"
+
+ # The full revision hash
+ VCS_FULL_HASH="$(hg log -r "${VCS_NUM}" -l 1 --template '{node}\n')"
+
+ # The short hash
+ VCS_SHORT_HASH="$(hg id -i | tr -d '+')"
+
+ # Current bookmark (bookmarks are roughly equivalent to git's branches)
+ # or branch if no bookmark
+ VCS_BRANCH="$(hg id -B | cut -d ' ' -f 1)"
+ # Fall back to the branch if there are no bookmarks
+ if [ -z "${VCS_BRANCH}" ]; then
+ VCS_BRANCH="$(hg id -b)"
+ fi
+
+ # Current or last tag ancestor (excluding auto tags, empty if no tags)
+ VCS_TAG="$(hg log -r "${VCS_NUM}" -l 1 --template '{latesttag}\n' 2>/dev/null | sed -e 's:qtip::' -e 's:tip::' -e 's:qbase::' -e 's:qparent::' -e "s:$(hg --config 'extensions.color=' --config 'extensions.mq=' --color never qtop 2>/dev/null)::" | cut -d ' ' -f 1)"
+
+ # Distance to last tag or an alias of VCS_NUM if there is no tag
+ if [ ! -z "${VCS_TAG}" ]; then
+ VCS_TICK="$(hg log -r "${VCS_NUM}" -l 1 --template '{latesttagdistance}\n' 2>/dev/null)"
+ else
+ VCS_TICK="${VCS_NUM}"
+ fi
+
+ # Date of the current commit
+ VCS_DATE="$(hg log -r "${VCS_NUM}" -l 1 --template '{date|isodatesec}\n' 2>/dev/null | sed -e 's: :T:' -e 's: ::' -e 's|+00:00|Z|')"
+
+ # Action Stamp
+ VCS_ACTION_STAMP="$(TZ=UTC hg log -r "${VCS_NUM}" -l 1 --template '{date|localdate|rfc3339date}\n' 2>/dev/null | sed -e 's|+00:00|Z|')!$(hg log -r "${VCS_NUM}" -l 1 --template '{author|email}\n' 2>/dev/null)"
+
+ cd "${oldPath}"
+}
+
+# For bzr repos
+# shellcheck disable=SC2039,SC2164
+bzrRepo() {
+ local oldPath="${PWD}"
+
+ cd "$(bzr root)"
+
+ VCS_TYPE="bzr"
+
+ VCS_BASENAME="$(basename "${PWD}")"
+
+ # Currently unimplemented because more investigation is needed.
+ VCS_UUID=""
+
+ # Is the working copy clean?
+ bzr version-info --custom --template='{clean}\n' | grep -q '1'
+ VCS_WC_MODIFIED="${?}"
+
+ # Enumeration of changesets
+ VCS_NUM="$(bzr revno)"
+
+ # The full revision hash
+ VCS_FULL_HASH="$(bzr version-info --custom --template='{revision_id}\n')"
+
+ # The short hash
+ VCS_SHORT_HASH="${VCS_NUM}"
+
+ # Nick of the current branch
+ VCS_BRANCH="$(bzr nick)"
+
+ # Current or last tag ancestor (excluding auto tags, empty if no tags)
+ VCS_TAG="$(bzr tags --sort=time | sed '/?$/d' | tail -n1 | cut -d ' ' -f1)"
+
+ # Distance to last tag or an alias of VCS_NUM if there is no tag
+ if [ ! -z "${VCS_TAG}" ]; then
+ VCS_TICK="$(bzr log --line -r "tag:${VCS_TAG}.." | tail -n +2 | wc -l | sed -e 's:^ *::')"
+ else
+ VCS_TICK="${VCS_NUM}"
+ fi
+
+ # Date of the current commit
+ VCS_DATE="$(bzr version-info --custom --template='{date}\n' | sed -e 's: :T:' -e 's: ::')"
+
+ # Action Stamp
+ # Currently unimplemented because more investigation is needed.
+ VCS_ACTION_STAMP=""
+
+ cd "${oldPath}"
+}
+
+# For svn repos
+# shellcheck disable=SC2039,SC2164,SC2155
+svnRepo() {
+ local oldPath="${PWD}"
+
+ VCS_TYPE="svn"
+
+ case "${PWD}" in
+ /*trunk*|/*branches*|/*tags*)
+ local fn="${PWD}"
+ while [ "$(basename "${fn}")" != 'trunk' ] && [ "$(basename "${fn}")" != 'branches' ] && [ "$(basename "${fn}")" != 'tags' ] && [ "$(basename "${fn}")" != '/' ]; do
+ local fn="$(dirname "${fn}")"
+ done
+ local fn="$(dirname "${fn}")"
+ if [ "${fn}" = '/' ]; then
+ VCS_BASENAME="$(basename "${PWD}")"
+ else
+ VCS_BASENAME="$(basename "${fn}")"
+ fi
+ ;;
+ *) VCS_BASENAME="$(basename "${PWD}")" ;;
+ esac
+
+ VCS_UUID="$(svn info --xml | sed -n -e 's:<uuid>::' -e 's:</uuid>::p')"
+
+ # Cache svnversion output
+ local SVNVERSION="$(svnversion)"
+
+ # Is the working copy clean?
+ echo "${SVNVERSION}" | grep -q "M"
+ case "${?}" in
+ 0)
+ VCS_WC_MODIFIED="1"
+ ;;
+ 1)
+ if [ ! -z "${UNTRACKEDFILES}" ]; then
+ # `svnversion` does not detect untracked files and `svn status` is really slow, so only run it if we really have to.
+ if [ -z "$(svn status)" ]; then
+ VCS_WC_MODIFIED="0"
+ else
+ VCS_WC_MODIFIED="1"
+ fi
+ else
+ VCS_WC_MODIFIED="0"
+ fi
+ ;;
+ esac
+
+ # Enumeration of changesets
+ VCS_NUM="$(echo "${SVNVERSION}" | cut -d : -f 1 | sed -e 's:M::' -e 's:S::' -e 's:P::')"
+
+ # The full revision hash
+ VCS_FULL_HASH="${SVNVERSION}"
+
+ # The short hash
+ VCS_SHORT_HASH="${VCS_NUM}"
+
+ # Current branch
+ case "${PWD}" in
+ /*trunk*|/*branches*|/*tags*)
+ local lastbase=""
+ local fn="${PWD}"
+ while :
+ do
+ base="$(basename "${fn}")"
+ if [ "${base}" = 'trunk' ]; then
+ VCS_BRANCH='trunk'
+ break
+ elif [ "${base}" = 'branches' ] || [ "${base}" = 'tags' ]; then
+ VCS_BRANCH="${lastbase}"
+ break
+ elif [ "${base}" = '/' ]; then
+ VCS_BRANCH=""
+ break
+ fi
+ local lastbase="${base}"
+ local fn="$(dirname "${fn}")"
+ done
+ ;;
+ *) VCS_BRANCH="" ;;
+ esac
+
+ # Current or last tag ancestor (empty if no tags). But "current
+ # tag" can't be extracted reliably because Subversion doesn't
+ # have tags the way other VCSes do.
+ VCS_TAG=""
+ VCS_TICK=""
+
+ # Date of the current commit
+ VCS_DATE="$(svn info --xml | sed -n -e 's:<date>::' -e 's:</date>::p')"
+
+ # Action Stamp
+ VCS_ACTION_STAMP="${VCS_DATE}!$(svn log --xml -l 1 -r "${VCS_SHORT_HASH}" | sed -n -e 's:<author>::' -e 's:</author>::p')"
+
+ cd "${oldPath}"
+}
+
+
+# Functions to output data in different formats.
+# For bash output
+shOutput() {
+ cat > "${TARGETFILE}" << EOF
+# ${GENERATED_HEADER}
+
+VCS_TYPE="${VCS_TYPE}"
+VCS_BASENAME="${VCS_BASENAME}"
+VCS_UUID="${VCS_UUID}"
+VCS_NUM="${VCS_NUM}"
+VCS_DATE="${VCS_DATE}"
+VCS_BRANCH="${VCS_BRANCH}"
+VCS_TAG="${VCS_TAG}"
+VCS_TICK="${VCS_TICK}"
+VCS_EXTRA="${VCS_EXTRA}"
+
+VCS_ACTION_STAMP="${VCS_ACTION_STAMP}"
+VCS_FULL_HASH="${VCS_FULL_HASH}"
+VCS_SHORT_HASH="${VCS_SHORT_HASH}"
+
+VCS_WC_MODIFIED="${VCS_WC_MODIFIED}"
+
+# end
+EOF
+}
+
+# For source C output
+cOutput() {
+ cat > "${TARGETFILE}" << EOF
+/* ${GENERATED_HEADER} */
+
+const char *VCS_TYPE = "${VCS_TYPE}";
+const char *VCS_BASENAME = "${VCS_BASENAME}";
+const char *VCS_UUID = "${VCS_UUID}";
+const int VCS_NUM = ${VCS_NUM};
+const char *VCS_DATE = "${VCS_DATE}";
+const char *VCS_BRANCH = "${VCS_BRANCH}";
+const char *VCS_TAG = "${VCS_TAG}";
+const int VCS_TICK = ${VCS_TICK};
+const char *VCS_EXTRA = "${VCS_EXTRA}";
+
+const char *VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}";
+const char *VCS_FULL_HASH = "${VCS_FULL_HASH}";
+const char *VCS_SHORT_HASH = "${VCS_SHORT_HASH}";
+
+const int VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};
+
+/* end */
+EOF
+}
+
+# For header output
+hOutput() {
+ cat > "${TARGETFILE}" << EOF
+/* ${GENERATED_HEADER} */
+#ifndef AUTOREVISION_H
+#define AUTOREVISION_H
+
+#define VCS_TYPE "${VCS_TYPE}"
+#define VCS_BASENAME "${VCS_BASENAME}"
+#define VCS_UUID "${VCS_UUID}"
+#define VCS_NUM ${VCS_NUM}
+#define VCS_DATE "${VCS_DATE}"
+#define VCS_BRANCH "${VCS_BRANCH}"
+#define VCS_TAG "${VCS_TAG}"
+#define VCS_TICK ${VCS_TICK}
+#define VCS_EXTRA "${VCS_EXTRA}"
+
+#define VCS_ACTION_STAMP "${VCS_ACTION_STAMP}"
+#define VCS_FULL_HASH "${VCS_FULL_HASH}"
+#define VCS_SHORT_HASH "${VCS_SHORT_HASH}"
+
+#define VCS_WC_MODIFIED ${VCS_WC_MODIFIED}
+
+#endif
+
+/* end */
+EOF
+}
+
+# A header output for use with xcode to populate info.plist strings
+xcodeOutput() {
+ cat > "${TARGETFILE}" << EOF
+/* ${GENERATED_HEADER} */
+#ifndef AUTOREVISION_H
+#define AUTOREVISION_H
+
+#define VCS_TYPE ${VCS_TYPE}
+#define VCS_BASENAME ${VCS_BASENAME}
+#define VCS_UUID ${VCS_UUID}
+#define VCS_NUM ${VCS_NUM}
+#define VCS_DATE ${VCS_DATE}
+#define VCS_BRANCH ${VCS_BRANCH}
+#define VCS_TAG ${VCS_TAG}
+#define VCS_TICK ${VCS_TICK}
+#define VCS_EXTRA ${VCS_EXTRA}
+
+#define VCS_ACTION_STAMP ${VCS_ACTION_STAMP}
+#define VCS_FULL_HASH ${VCS_FULL_HASH}
+#define VCS_SHORT_HASH ${VCS_SHORT_HASH}
+
+#define VCS_WC_MODIFIED ${VCS_WC_MODIFIED}
+
+#endif
+
+/* end */
+EOF
+}
+
+# For Swift output
+swiftOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="false" ;;
+ 1) VCS_WC_MODIFIED="true" ;;
+ esac
+ # For values that may not exist depending on the type of repo we
+ # have read from, set them to `nil` when they are empty.
+ if [ -z "${VCS_UUID}" ]; then
+ VCS_UUID="nil"
+ else
+ VCS_UUID="\"${VCS_UUID}\""
+ fi
+ if [ -z "${VCS_TAG}" ]; then
+ VCS_TAG="nil"
+ else
+ VCS_TAG="\"${VCS_TAG}\""
+ fi
+ : "${VCS_TICK:="nil"}"
+ if [ -z "${VCS_EXTRA}" ]; then
+ VCS_EXTRA="nil"
+ else
+ VCS_EXTRA="\"${VCS_EXTRA}\""
+ fi
+ if [ -z "${VCS_ACTION_STAMP}" ]; then
+ VCS_ACTION_STAMP="nil"
+ else
+ VCS_ACTION_STAMP="\"${VCS_ACTION_STAMP}\""
+ fi
+ cat > "${TARGETFILE}" << EOF
+/* ${GENERATED_HEADER} */
+
+let VCS_TYPE = "${VCS_TYPE}"
+let VCS_BASENAME = "${VCS_BASENAME}"
+let VCS_UUID: String? = ${VCS_UUID}
+let VCS_NUM: Int = ${VCS_NUM}
+let VCS_DATE = "${VCS_DATE}"
+let VCS_BRANCH: String = "${VCS_BRANCH}"
+let VCS_TAG: String? = ${VCS_TAG}
+let VCS_TICK: Int? = ${VCS_TICK}
+let VCS_EXTRA: String? = ${VCS_EXTRA}
+
+let VCS_ACTION_STAMP: String? = ${VCS_ACTION_STAMP}
+let VCS_FULL_HASH: String = "${VCS_FULL_HASH}"
+let VCS_SHORT_HASH: String = "${VCS_SHORT_HASH}"
+
+let VCS_WC_MODIFIED: Bool = ${VCS_WC_MODIFIED}
+
+/* end */
+EOF
+}
+
+# For Python output
+pyOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="False" ;;
+ 1) VCS_WC_MODIFIED="True" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+# ${GENERATED_HEADER}
+
+VCS_TYPE = "${VCS_TYPE}"
+VCS_BASENAME = "${VCS_BASENAME}"
+VCS_UUID = "${VCS_UUID}"
+VCS_NUM = ${VCS_NUM}
+VCS_DATE = "${VCS_DATE}"
+VCS_BRANCH = "${VCS_BRANCH}"
+VCS_TAG = "${VCS_TAG}"
+VCS_TICK = ${VCS_TICK}
+VCS_EXTRA = "${VCS_EXTRA}"
+
+VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}"
+VCS_FULL_HASH = "${VCS_FULL_HASH}"
+VCS_SHORT_HASH = "${VCS_SHORT_HASH}"
+
+VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}
+
+# end
+EOF
+}
+
+# For Perl output
+plOutput() {
+ cat << EOF
+# ${GENERATED_HEADER}
+
+\$VCS_TYPE = '${VCS_TYPE}';
+\$VCS_BASENAME = '${VCS_BASENAME}';
+\$VCS_UUID = '${VCS_UUID}';
+\$VCS_NUM = ${VCS_NUM};
+\$VCS_DATE = '${VCS_DATE}';
+\$VCS_BRANCH = '${VCS_BRANCH}';
+\$VCS_TAG = '${VCS_TAG}';
+\$VCS_TICK = ${VCS_TICK};
+\$VCS_EXTRA = '${VCS_EXTRA}';
+
+\$VCS_ACTION_STAMP = '${VCS_ACTION_STAMP}';
+\$VCS_FULL_HASH = '${VCS_FULL_HASH}';
+\$VCS_SHORT_HASH = '${VCS_SHORT_HASH}';
+
+\$VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};
+
+# end
+1;
+EOF
+}
+
+# For lua output
+luaOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="false" ;;
+ 1) VCS_WC_MODIFIED="true" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+-- ${GENERATED_HEADER}
+
+VCS_TYPE = "${VCS_TYPE}"
+VCS_BASENAME = "${VCS_BASENAME}"
+VCS_UUID = "${VCS_UUID}"
+VCS_NUM = ${VCS_NUM}
+VCS_DATE = "${VCS_DATE}"
+VCS_BRANCH = "${VCS_BRANCH}"
+VCS_TAG = "${VCS_TAG}"
+VCS_TICK = ${VCS_TICK}
+VCS_EXTRA = "${VCS_EXTRA}"
+
+VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}"
+VCS_FULL_HASH = "${VCS_FULL_HASH}"
+VCS_SHORT_HASH = "${VCS_SHORT_HASH}"
+
+VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}
+
+-- end
+EOF
+}
+
+# For php output
+phpOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="false" ;;
+ 1) VCS_WC_MODIFIED="true" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+<?php
+# ${GENERATED_HEADER}
+
+return array(
+ "VCS_TYPE" => "${VCS_TYPE}",
+ "VCS_BASENAME" => "${VCS_BASENAME}",
+ "VCS_UUID" => "${VCS_UUID}",
+ "VCS_NUM" => ${VCS_NUM},
+ "VCS_DATE" => "${VCS_DATE}",
+ "VCS_BRANCH" => "${VCS_BRANCH}",
+ "VCS_TAG" => "${VCS_TAG}",
+ "VCS_TICK" => ${VCS_TICK},
+ "VCS_EXTRA" => "${VCS_EXTRA}",
+ "VCS_ACTION_STAMP" => "${VCS_ACTION_STAMP}",
+ "VCS_FULL_HASH" => "${VCS_FULL_HASH}",
+ "VCS_SHORT_HASH" => "${VCS_SHORT_HASH}",
+ "VCS_WC_MODIFIED" => ${VCS_WC_MODIFIED}
+);
+
+# end
+?>
+EOF
+}
+
+# For ini output
+iniOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="false" ;;
+ 1) VCS_WC_MODIFIED="true" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+; ${GENERATED_HEADER}
+[VCS]
+VCS_TYPE = "${VCS_TYPE}"
+VCS_BASENAME = "${VCS_BASENAME}"
+VCS_UUID = "${VCS_UUID}"
+VCS_NUM = ${VCS_NUM}
+VCS_DATE = "${VCS_DATE}"
+VCS_BRANCH = "${VCS_BRANCH}"
+VCS_TAG = "${VCS_TAG}"
+VCS_TICK = ${VCS_TICK}
+VCS_EXTRA = "${VCS_EXTRA}"
+VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}"
+VCS_FULL_HASH = "${VCS_FULL_HASH}"
+VCS_SHORT_HASH = "${VCS_SHORT_HASH}"
+VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}
+; end
+EOF
+}
+
+# For javascript output
+jsOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 1) VCS_WC_MODIFIED="true" ;;
+ 0) VCS_WC_MODIFIED="false" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+/** ${GENERATED_HEADER} */
+
+var autorevision = {
+ VCS_TYPE: "${VCS_TYPE}",
+ VCS_BASENAME: "${VCS_BASENAME}",
+ VCS_UUID: "${VCS_UUID}",
+ VCS_NUM: ${VCS_NUM},
+ VCS_DATE: "${VCS_DATE}",
+ VCS_BRANCH: "${VCS_BRANCH}",
+ VCS_TAG: "${VCS_TAG}",
+ VCS_TICK: ${VCS_TICK},
+ VCS_EXTRA: "${VCS_EXTRA}",
+
+ VCS_ACTION_STAMP: "${VCS_ACTION_STAMP}",
+ VCS_FULL_HASH: "${VCS_FULL_HASH}",
+ VCS_SHORT_HASH: "${VCS_SHORT_HASH}",
+
+ VCS_WC_MODIFIED: ${VCS_WC_MODIFIED}
+};
+
+/** Node.js compatibility */
+if (typeof module !== 'undefined') {
+ module.exports = autorevision;
+}
+
+/** end */
+EOF
+}
+
+# For JSON output
+jsonOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 1) VCS_WC_MODIFIED="true" ;;
+ 0) VCS_WC_MODIFIED="false" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+{
+ "_comment": "${GENERATED_HEADER}",
+ "VCS_TYPE": "${VCS_TYPE}",
+ "VCS_BASENAME": "${VCS_BASENAME}",
+ "VCS_UUID": "${VCS_UUID}",
+ "VCS_NUM": ${VCS_NUM},
+ "VCS_DATE": "${VCS_DATE}",
+ "VCS_BRANCH":"${VCS_BRANCH}",
+ "VCS_TAG": "${VCS_TAG}",
+ "VCS_TICK": ${VCS_TICK},
+ "VCS_EXTRA": "${VCS_EXTRA}",
+
+ "VCS_ACTION_STAMP": "${VCS_ACTION_STAMP}",
+ "VCS_FULL_HASH": "${VCS_FULL_HASH}",
+ "VCS_SHORT_HASH": "${VCS_SHORT_HASH}",
+
+ "VCS_WC_MODIFIED": ${VCS_WC_MODIFIED}
+}
+EOF
+}
+
+# For Java output
+javaOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 1) VCS_WC_MODIFIED="true" ;;
+ 0) VCS_WC_MODIFIED="false" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+/* ${GENERATED_HEADER} */
+
+public class autorevision {
+ public static final String VCS_TYPE = "${VCS_TYPE}";
+ public static final String VCS_BASENAME = "${VCS_BASENAME}";
+ public static final String VCS_UUID = "${VCS_UUID}";
+ public static final long VCS_NUM = ${VCS_NUM};
+ public static final String VCS_DATE = "${VCS_DATE}";
+ public static final String VCS_BRANCH = "${VCS_BRANCH}";
+ public static final String VCS_TAG = "${VCS_TAG}";
+ public static final long VCS_TICK = ${VCS_TICK};
+ public static final String VCS_EXTRA = "${VCS_EXTRA}";
+
+ public static final String VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}";
+ public static final String VCS_FULL_HASH = "${VCS_FULL_HASH}";
+ public static final String VCS_SHORT_HASH = "${VCS_SHORT_HASH}";
+
+ public static final boolean VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};
+}
+EOF
+}
+
+# For Java properties output
+javapropOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 1) VCS_WC_MODIFIED="true" ;;
+ 0) VCS_WC_MODIFIED="false" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+# ${GENERATED_HEADER}
+
+VCS_TYPE=${VCS_TYPE}
+VCS_BASENAME=${VCS_BASENAME}
+VCS_UUID=${VCS_UUID}
+VCS_NUM=${VCS_NUM}
+VCS_DATE=${VCS_DATE}
+VCS_BRANCH=${VCS_BRANCH}
+VCS_TAG=${VCS_TAG}
+VCS_TICK=${VCS_TICK}
+VCS_EXTRA=${VCS_EXTRA}
+
+VCS_ACTION_STAMP=${VCS_ACTION_STAMP}
+VCS_FULL_HASH=${VCS_FULL_HASH}
+VCS_SHORT_HASH=${VCS_SHORT_HASH}
+
+VCS_WC_MODIFIED=${VCS_WC_MODIFIED}
+EOF
+}
+
+# For m4 output
+m4Output() {
+ cat > "${TARGETFILE}" << EOF
+dnl ${GENERATED_HEADER}
+define(\`VCS_TYPE', \`${VCS_TYPE}')dnl
+define(\`VCS_BASENAME', \`${VCS_BASENAME}')dnl
+define(\`VCS_UUID', \`${VCS_UUID}')dnl
+define(\`VCS_NUM', \`${VCS_NUM}')dnl
+define(\`VCS_DATE', \`${VCS_DATE}')dnl
+define(\`VCS_BRANCH', \`${VCS_BRANCH}')dnl
+define(\`VCS_TAG', \`${VCS_TAG}')dnl
+define(\`VCS_TICK', \`${VCS_TICK}')dnl
+define(\`VCS_EXTRA', \`${VCS_EXTRA}')dnl
+define(\`VCS_ACTIONSTAMP', \`${VCS_ACTION_STAMP}')dnl
+define(\`VCS_FULLHASH', \`${VCS_FULL_HASH}')dnl
+define(\`VCS_SHORTHASH', \`${VCS_SHORT_HASH}')dnl
+define(\`VCS_WC_MODIFIED', \`${VCS_WC_MODIFIED}')dnl
+EOF
+}
+
+# For (La)TeX output
+texOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="false" ;;
+ 1) VCS_WC_MODIFIED="true" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+% ${GENERATED_HEADER}
+\def \vcsType {${VCS_TYPE}}
+\def \vcsBasename {${VCS_BASENAME}}
+\def \vcsUUID {${VCS_UUID}}
+\def \vcsNum {${VCS_NUM}}
+\def \vcsDate {${VCS_DATE}}
+\def \vcsBranch {${VCS_BRANCH}}
+\def \vcsTag {${VCS_TAG}}
+\def \vcsTick {${VCS_TICK}}
+\def \vcsExtra {${VCS_EXTRA}}
+\def \vcsACTIONSTAMP {${VCS_ACTION_STAMP}}
+\def \vcsFullHash {${VCS_FULL_HASH}}
+\def \vcsShortHash {${VCS_SHORT_HASH}}
+\def \vcsWCModified {${VCS_WC_MODIFIED}}
+\endinput
+EOF
+}
+
+# For scheme output
+schemeOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="#f" ;;
+ 1) VCS_WC_MODIFIED="#t" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+;; ${GENERATED_HEADER}
+(define VCS_TYPE "${VCS_TYPE}")
+(define VCS_BASENAME "${VCS_BASENAME}")
+(define VCS_UUID "${VCS_UUID}")
+(define VCS_NUM ${VCS_NUM})
+(define VCS_DATE "${VCS_DATE}")
+(define VCS_BRANCH "${VCS_BRANCH}")
+(define VCS_TAG "${VCS_TAG}")
+(define VCS_TICK ${VCS_TICK})
+(define VCS_EXTRA "${VCS_EXTRA}")
+
+(define VCS_ACTION_STAMP "${VCS_ACTION_STAMP}")
+(define VCS_FULL_HASH "${VCS_FULL_HASH}")
+(define VCS_SHORT_HASH "${VCS_SHORT_HASH}")
+
+(define VCS_WC_MODIFIED ${VCS_WC_MODIFIED})
+;; end
+EOF
+}
+
+# For clojure output
+clojureOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="false" ;;
+ 1) VCS_WC_MODIFIED="true" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+;; ${GENERATED_HEADER}
+(def VCS_TYPE "${VCS_TYPE}")
+(def VCS_BASENAME "${VCS_BASENAME}")
+(def VCS_UUID "${VCS_UUID}")
+(def VCS_NUM ${VCS_NUM})
+(def VCS_DATE "${VCS_DATE}")
+(def VCS_BRANCH "${VCS_BRANCH}")
+(def VCS_TAG "${VCS_TAG}")
+(def VCS_TICK ${VCS_TICK})
+(def VCS_EXTRA "${VCS_EXTRA}")
+
+(def VCS_ACTION_STAMP "${VCS_ACTION_STAMP}")
+(def VCS_FULL_HASH "${VCS_FULL_HASH}")
+(def VCS_SHORT_HASH "${VCS_SHORT_HASH}")
+
+(def VCS_WC_MODIFIED ${VCS_WC_MODIFIED})
+;; end
+EOF
+}
+
+# For rpm spec file output
+rpmOutput() {
+ cat > "${TARGETFILE}" << EOF
+# ${GENERATED_HEADER}
+$([ "${VCS_TYPE}" ] && echo "%define vcs_type ${VCS_TYPE}")
+$([ "${VCS_BASENAME}" ] && echo "%define vcs_basename ${VCS_BASENAME}")
+$([ "${VCS_UUID}" ] && echo "%define vcs_uuid ${VCS_UUID}")
+$([ "${VCS_NUM}" ] && echo "%define vcs_num ${VCS_NUM}")
+$([ "${VCS_DATE}" ] && echo "%define vcs_date ${VCS_DATE}")
+$([ "${VCS_BRANCH}" ] && echo "%define vcs_branch ${VCS_BRANCH}")
+$([ "${VCS_TAG}" ] && echo "%define vcs_tag ${VCS_TAG}")
+$([ "${VCS_TICK}" ] && echo "%define vcs_tick ${VCS_TICK}")
+$([ "${VCS_EXTRA}" ] && echo "%define vcs_extra ${VCS_EXTRA}")
+
+$([ "${VCS_ACTION_STAMP}" ] && echo "%define vcs_action_stamp ${VCS_ACTION_STAMP}")
+$([ "${VCS_FULL_HASH}" ] && echo "%define vcs_full_hash ${VCS_FULL_HASH}")
+$([ "${VCS_SHORT_HASH}" ] && echo "%define vcs_short_hash ${VCS_SHORT_HASH}")
+
+$([ "${VCS_WC_MODIFIED}" ] && echo "%define vcs_wc_modified ${VCS_WC_MODIFIED}")
+# end
+EOF
+}
+
+# shellcheck disable=SC2155,SC2039
+hppOutput() {
+ local NAMESPACE="$(echo "${VCS_BASENAME}" | sed -e 's:_::g' | tr '[:lower:]' '[:upper:]')"
+ cat > "${TARGETFILE}" << EOF
+/* ${GENERATED_HEADER} */
+
+#ifndef ${NAMESPACE}_AUTOREVISION_H
+#define ${NAMESPACE}_AUTOREVISION_H
+
+#include <string>
+
+namespace $(echo "${NAMESPACE}" | tr '[:upper:]' '[:lower:]')
+{
+ const std::string VCS_TYPE = "${VCS_TYPE}";
+ const std::string VCS_BASENAME = "${VCS_BASENAME}";
+ const std::string VCS_UUID = "${VCS_UUID}";
+ const int VCS_NUM = ${VCS_NUM};
+ const std::string VCS_DATE = "${VCS_DATE}";
+ const std::string VCS_BRANCH = "${VCS_BRANCH}";
+ const std::string VCS_TAG = "${VCS_TAG}";
+ const int VCS_TICK = ${VCS_TICK};
+ const std::string VCS_EXTRA = "${VCS_EXTRA}";
+
+ const std::string VCS_ACTION_STAMP = "${VCS_ACTION_STAMP}";
+ const std::string VCS_FULL_HASH = "${VCS_FULL_HASH}";
+ const std::string VCS_SHORT_HASH = "${VCS_SHORT_HASH}";
+
+ const int VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};
+}
+
+#endif
+
+/* end */
+EOF
+}
+
+matlabOutput() {
+ case "${VCS_WC_MODIFIED}" in
+ 0) VCS_WC_MODIFIED="FALSE" ;;
+ 1) VCS_WC_MODIFIED="TRUE" ;;
+ esac
+ cat > "${TARGETFILE}" << EOF
+% ${GENERATED_HEADER}
+
+VCS_TYPE = '${VCS_TYPE}';
+VCS_BASENAME = '${VCS_BASENAME}';
+VCS_UUID = '${VCS_UUID}';
+VCS_NUM = ${VCS_NUM};
+VCS_DATE = '${VCS_DATE}';
+VCS_BRANCH = '${VCS_BRANCH}';
+VCS_TAG = '${VCS_TAG}';
+VCS_TICK = ${VCS_TICK};
+VCS_EXTRA = '${VCS_EXTRA}';
+
+VCS_ACTION_STAMP = '${VCS_ACTION_STAMP}';
+VCS_FULL_HASH = '${VCS_FULL_HASH}';
+VCS_SHORT_HASH = '${VCS_SHORT_HASH}';
+
+VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};
+
+% end
+EOF
+}
+
+octaveOutput() {
+ cat > "${TARGETFILE}" << EOF
+% ${GENERATED_HEADER}
+
+VCS_TYPE = '${VCS_TYPE}';
+VCS_BASENAME = '${VCS_BASENAME}';
+VCS_UUID = '${VCS_UUID}';
+VCS_NUM = ${VCS_NUM};
+VCS_DATE = '${VCS_DATE}';
+VCS_BRANCH = '${VCS_BRANCH}';
+VCS_TAG = '${VCS_TAG}';
+VCS_TICK = ${VCS_TICK};
+VCS_EXTRA = '${VCS_EXTRA}';
+
+VCS_ACTION_STAMP = '${VCS_ACTION_STAMP}';
+VCS_FULL_HASH = '${VCS_FULL_HASH}';
+VCS_SHORT_HASH = '${VCS_SHORT_HASH}';
+
+VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};
+
+% end
+EOF
+}
+
+cmakeOutput() {
+ cat > "${TARGETFILE}" << EOF
+# ${GENERATED_HEADER}
+
+set(VCS_TYPE ${VCS_TYPE})
+set(VCS_BASENAME ${VCS_BASENAME})
+set(VCS_UUID ${VCS_UUID})
+set(VCS_NUM ${VCS_NUM})
+set(VCS_DATE ${VCS_DATE})
+set(VCS_BRANCH ${VCS_BRANCH})
+set(VCS_TAG ${VCS_TAG})
+set(VCS_TICK ${VCS_TICK})
+set(VCS_EXTRA ${VCS_EXTRA})
+
+set(VCS_ACTION_STAMP ${VCS_ACTION_STAMP})
+set(VCS_FULL_HASH ${VCS_FULL_HASH})
+set(VCS_SHORT_HASH ${VCS_SHORT_HASH})
+
+set(VCS_WC_MODIFIED ${VCS_WC_MODIFIED})
+
+# end
+EOF
+}
+
+
+# Helper functions
+# Count path segments
+# shellcheck disable=SC2039
+pathSegment() {
+ local pathz="${1}"
+ local depth="0"
+
+ if [ ! -z "${pathz}" ]; then
+ # Continue until we are at / or there are no path separators left.
+ while [ ! "${pathz}" = "/" ] && [ ! "${pathz}" = "$(echo "${pathz}" | sed -e 's:/::')" ]; do
+ pathz="$(dirname "${pathz}")"
+ depth="$((depth+1))"
+ done
+ fi
+ echo "${depth}"
+}
+
+# Largest of four numbers
+# shellcheck disable=SC2039
+multiCompare() {
+ local larger="${1}"
+ local numA="${2}"
+ local numB="${3}"
+ local numC="${4}"
+
+ [ "${numA}" -gt "${larger}" ] && larger="${numA}"
+ [ "${numB}" -gt "${larger}" ] && larger="${numB}"
+ [ "${numC}" -gt "${larger}" ] && larger="${numC}"
+ echo "${larger}"
+}
+
+# Test for repositories
+# shellcheck disable=SC2155,SC2039
+repoTest() {
+ REPONUM="0"
+ if [ ! -z "$(git rev-parse HEAD 2>/dev/null)" ]; then
+ local gitPath="$(git rev-parse --show-toplevel)"
+ local gitDepth="$(pathSegment "${gitPath}")"
+ REPONUM="$((REPONUM+1))"
+ else
+ local gitDepth="0"
+ fi
+ if [ ! -z "$(hg root 2>/dev/null)" ]; then
+ local hgPath="$(hg root 2>/dev/null)"
+ local hgDepth="$(pathSegment "${hgPath}")"
+ REPONUM="$((REPONUM+1))"
+ else
+ local hgDepth="0"
+ fi
+ if [ ! -z "$(bzr root 2>/dev/null)" ]; then
+ local bzrPath="$(bzr root 2>/dev/null)"
+ local bzrDepth="$(pathSegment "${bzrPath}")"
+ REPONUM="$((REPONUM+1))"
+ else
+ local bzrDepth="0"
+ fi
+ if [ ! -z "$(svn info 2>/dev/null)" ]; then
+ local stringz="<wcroot-abspath>"
+ local stringx="</wcroot-abspath>"
+ local svnPath="$(svn info --xml | sed -n -e "s:${stringz}::" -e "s:${stringx}::p")"
+ # An old enough svn will not be able give us a path; default
+ # to 1 for that case.
+ if [ -z "${svnPath}" ]; then
+ local svnDepth="1"
+ else
+ local svnDepth="$(pathSegment "${svnPath}")"
+ fi
+ REPONUM="$((REPONUM+1))"
+ else
+ local svnDepth="0"
+ fi
+
+ # Do not do more work then we have to.
+ if [ "${REPONUM}" = "0" ]; then
+ return
+ fi
+
+ # Figure out which repo is the deepest and use it.
+ local wonRepo="$(multiCompare "${gitDepth}" "${hgDepth}" "${bzrDepth}" "${svnDepth}")"
+ if [ "${wonRepo}" = "${gitDepth}" ]; then
+ gitRepo
+ elif [ "${wonRepo}" = "${hgDepth}" ]; then
+ hgRepo
+ elif [ "${wonRepo}" = "${bzrDepth}" ]; then
+ bzrRepo
+ elif [ "${wonRepo}" = "${svnDepth}" ]; then
+ svnRepo
+ fi
+}
+
+
+
+# Detect which repos we are in and gather data.
+# shellcheck source=/dev/null
+if [ -f "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then
+ # When requested only read from the cache to populate our symbols.
+ . "${CACHEFILE}"
+else
+ # If a value is not set through the environment set VCS_EXTRA to nothing.
+ : "${VCS_EXTRA:=""}"
+ repoTest
+
+ if [ -f "${CACHEFILE}" ] && [ "${REPONUM}" = "0" ]; then
+ # We are not in a repo; try to use a previously generated cache to populate our symbols.
+ . "${CACHEFILE}"
+ # Do not overwrite the cache if we know we are not going to write anything new.
+ CACHEFORCE="1"
+ elif [ "${REPONUM}" = "0" ]; then
+ echo "error: No repo or cache detected." 1>&2
+ exit 1
+ fi
+fi
+
+
+# -s output is handled here.
+if [ ! -z "${VAROUT}" ]; then
+ if [ "${VAROUT}" = "VCS_TYPE" ]; then
+ echo "${VCS_TYPE}"
+ elif [ "${VAROUT}" = "VCS_BASENAME" ]; then
+ echo "${VCS_BASENAME}"
+ elif [ "${VAROUT}" = "VCS_NUM" ]; then
+ echo "${VCS_NUM}"
+ elif [ "${VAROUT}" = "VCS_DATE" ]; then
+ echo "${VCS_DATE}"
+ elif [ "${VAROUT}" = "VCS_BRANCH" ]; then
+ echo "${VCS_BRANCH}"
+ elif [ "${VAROUT}" = "VCS_TAG" ]; then
+ echo "${VCS_TAG}"
+ elif [ "${VAROUT}" = "VCS_TICK" ]; then
+ echo "${VCS_TICK}"
+ elif [ "${VAROUT}" = "VCS_FULL_HASH" ]; then
+ echo "${VCS_FULL_HASH}"
+ elif [ "${VAROUT}" = "VCS_SHORT_HASH" ]; then
+ echo "${VCS_SHORT_HASH}"
+ elif [ "${VAROUT}" = "VCS_WC_MODIFIED" ]; then
+ echo "${VCS_WC_MODIFIED}"
+ elif [ "${VAROUT}" = "VCS_ACTION_STAMP" ]; then
+ echo "${VCS_ACTION_STAMP}"
+ else
+ echo "error: Not a valid output symbol." 1>&2
+ exit 1
+ fi
+fi
+
+
+# Detect requested output type and use it.
+if [ ! -z "${AFILETYPE}" ]; then
+ if [ "${AFILETYPE}" = "c" ]; then
+ cOutput
+ elif [ "${AFILETYPE}" = "h" ]; then
+ hOutput
+ elif [ "${AFILETYPE}" = "xcode" ]; then
+ xcodeOutput
+ elif [ "${AFILETYPE}" = "swift" ]; then
+ swiftOutput
+ elif [ "${AFILETYPE}" = "sh" ]; then
+ shOutput
+ elif [ "${AFILETYPE}" = "py" ] || [ "${AFILETYPE}" = "python" ]; then
+ pyOutput
+ elif [ "${AFILETYPE}" = "pl" ] || [ "${AFILETYPE}" = "perl" ]; then
+ plOutput
+ elif [ "${AFILETYPE}" = "lua" ]; then
+ luaOutput
+ elif [ "${AFILETYPE}" = "php" ]; then
+ phpOutput
+ elif [ "${AFILETYPE}" = "ini" ]; then
+ iniOutput
+ elif [ "${AFILETYPE}" = "js" ]; then
+ jsOutput
+ elif [ "${AFILETYPE}" = "json" ]; then
+ jsonOutput
+ elif [ "${AFILETYPE}" = "java" ]; then
+ javaOutput
+ elif [ "${AFILETYPE}" = "javaprop" ]; then
+ javapropOutput
+ elif [ "${AFILETYPE}" = "tex" ]; then
+ texOutput
+ elif [ "${AFILETYPE}" = "m4" ]; then
+ m4Output
+ elif [ "${AFILETYPE}" = "scheme" ]; then
+ schemeOutput
+ elif [ "${AFILETYPE}" = "clojure" ]; then
+ clojureOutput
+ elif [ "${AFILETYPE}" = "rpm" ]; then
+ rpmOutput
+ elif [ "${AFILETYPE}" = "hpp" ]; then
+ hppOutput
+ elif [ "${AFILETYPE}" = "matlab" ]; then
+ matlabOutput
+ elif [ "${AFILETYPE}" = "octave" ]; then
+ octaveOutput
+ elif [ "${AFILETYPE}" = "cmake" ]; then
+ cmakeOutput
+ else
+ echo "error: Not a valid output type." 1>&2
+ exit 1
+ fi
+fi
+
+
+# If requested, make a cache file.
+if [ ! -z "${CACHEFILE}" ] && [ ! "${CACHEFORCE}" = "1" ]; then
+ TARGETFILE="${CACHEFILE}.tmp"
+ shOutput
+
+ # Check to see if there have been any actual changes.
+ if [ ! -f "${CACHEFILE}" ]; then
+ mv -f "${CACHEFILE}.tmp" "${CACHEFILE}"
+ elif cmp -s "${CACHEFILE}.tmp" "${CACHEFILE}"; then
+ rm -f "${CACHEFILE}.tmp"
+ else
+ mv -f "${CACHEFILE}.tmp" "${CACHEFILE}"
+ fi
+fi
diff --git a/cmake/Package.cmake b/cmake/Package.cmake
index 57cb8e8..0c2684b 100644
--- a/cmake/Package.cmake
+++ b/cmake/Package.cmake
@@ -1,18 +1,16 @@
set(CPACK_PACKAGE_NAME "mrzcpd")
set(CPACK_PACKAGE_VECDOR "Mesasoft@IIE")
-set(CPACK_PACKAGE_VERSION_MAJOR ${MARSIO_MAJOR_VERSION})
-set(CPACK_PACKAGE_VERSION_MINOR ${MARSIO_MINOR_VERSION})
-set(CPACK_PACKAGE_VERSION_PATCH ${MARSIO_PATCH_VERSION})
+set(CPACK_PACKAGE_VERSION_MAJOR "${MARSIO_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${MARSIO_VERSION_MINOR}")
+set(CPACK_PACKAGE_VERSION_PATCH "${MARSIO_VERSION_PATCH}.${MARSIO_VERSION_BUILD}")
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
set(CPACK_STRIP_FILES TRUE)
-set(CPACK_SET_DESTDIR TRUE)
# RPM Build
set(CPACK_GENERATOR "RPM")
set(CPACK_RPM_PACKAGE_VENDOR "Mesasoft@IIE")
set(CPACK_RPM_PACKAGE_AUTOREQPROV "no")
-set(CPACK_RPM_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
-set(CPACK_RPM_PACKAGE_RELEASE "${CPACK_RPM_PACKAGE_VERSION}%{?dist}")
-set(CPACK_RPM_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}.rpm")
-set(CPACK_RPM_DEBUGINFO_PACKAGE "${CPACK_PACKAGE_NAME}-${CPACK_RPM_PACKAGE_RELEASE}.debuginfo.rpm")
+set(CPACK_RPM_PACKAGE_REQUIRES "/boot/vmlinuz-${MARSIO_VERSION_KERNEL}")
+set(CPACK_RPM_PACKAGE_RELEASE_DIST on)
+set(CPACK_RPM_DEBUGINFO_PACKAGE on)
include(CPack) \ No newline at end of file
diff --git a/cmake/Version.cmake b/cmake/Version.cmake
index 45dd488..cf4452d 100644
--- a/cmake/Version.cmake
+++ b/cmake/Version.cmake
@@ -1,12 +1,49 @@
-include(GetGitRevisionDescription)
-# Project Version
-set(MARSIO_MAJOR_VERSION 4)
-set(MARSIO_MINOR_VERSION 0)
-set(MARSIO_PATCH_VERSION 0)
-set(MARSIO_VERSION ${MARSIO_MAJOR_VERSION}.${MARSIO_MINOR_VERSION}.${MARSIO_PATCH_VERSION})
-
-git_describe(MARSIO_GIT_VERSION)
-set(MARSIO_VERSION "${MARSIO_VERSION},${MARSIO_GIT_VERSION}")
-set(EXTRA_C_FLAGS "${EXTRA_C_FLAGS} -DGITVER=\\\"${MARSIO_VERSION}\\\"")
-set(EXTRA_CXX_FLAGS "${EXTRA_CXX_FLAGS} -DGITVER=\\\"${MARSIO_VERSION}\\\"") \ No newline at end of file
+# Using autorevision.sh to generate version information
+
+set(__SOURCE_AUTORESIVISION ${CMAKE_SOURCE_DIR}/autorevision.sh)
+set(__AUTORESIVISION ${CMAKE_BINARY_DIR}/autorevision.sh)
+set(__VERSION_CACHE ${CMAKE_SOURCE_DIR}/version.txt)
+set(__VERSION_CONFIG ${CMAKE_BINARY_DIR}/version.cmake)
+set(__VERSION_CONFIG_C_IN ${CMAKE_SOURCE_DIR}/include/internal/mr_version.h.in)
+set(__VERSION_CONFIG_C_OUT ${CMAKE_BINARY_DIR}/include/internal/mr_version.h)
+
+file(COPY ${__SOURCE_AUTORESIVISION} DESTINATION ${CMAKE_BINARY_DIR}
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE
+ WORLD_READ WORLD_EXECUTE)
+
+# execute autorevision.sh to generate version information
+execute_process(COMMAND ${__AUTORESIVISION} -t cmake -o ${__VERSION_CACHE}
+ OUTPUT_FILE ${__VERSION_CONFIG} ERROR_QUIET)
+include(${__VERSION_CONFIG})
+
+# generate c header file
+configure_file(${__VERSION_CONFIG_C_IN} ${__VERSION_CONFIG_C_OUT} @ONLY)
+add_definitions(-include ${__VERSION_CONFIG_C_OUT})
+
+# extract major, minor, patch version from git tag
+string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" MARSIO_VERSION_MAJOR "${VCS_TAG}")
+string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" MARSIO_VERSION_MINOR "${VCS_TAG}")
+string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" MARSIO_VERSION_PATCH "${VCS_TAG}")
+
+if(NOT MARSIO_VERSION_MAJOR)
+ set(MARSIO_VERSION_MAJOR 4)
+endif()
+
+if(NOT MARSIO_VERSION_MINOR)
+ set(MARSIO_VERSION_MINOR 0)
+endif()
+
+if(NOT MARSIO_VERSION_PATCH)
+ set(MARSIO_VERSION_PATCH 0)
+endif()
+
+set(MARSIO_VERSION "${MARSIO_VERSION_MAJOR}.${MARSIO_VERSION_MINOR}.${MARSIO_VERSION_PATCH}")
+set(MARSIO_VERSION_BUILD "${VCS_SHORT_HASH}")
+
+# system information
+execute_process(COMMAND uname -r OUTPUT_VARIABLE MARSIO_VERSION_KERNEL)
+
+# print information
+message(STATUS "Marsio Version: ${MARSIO_VERSION}-${MARSIO_VERSION_BUILD}")
+message(STATUS "Kernel Version: ${MARSIO_VERSION_KERNEL}") \ No newline at end of file
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 3a64c8c..6c099bd 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -1,12 +1,9 @@
find_package(DPDK REQUIRED)
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_SOURCE_DIR}/include/extern)
-include_directories(${CMAKE_SOURCE_DIR}/include/internal)
include_directories(${DPDK_INCLUDE_DIR})
-
add_definitions(${DPDK_C_PREDEFINED})
+
include_directories(include)
-add_library(core src/core.c src/device.c src/vnode.c src/mrbuf.c src/vman.c src/stat.c src/rtdev.c)
-target_link_libraries(core MESA_prof_load_static mruntime)
+add_library(core src/core.c src/buffer.c src/device.c src/vnode.c src/stat.c src/rtdev.c)
+target_link_libraries(core mruntime)
target_link_libraries(core rt pthread dl)
target_include_directories(core INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/") \ No newline at end of file
diff --git a/core/include/mr_buffer.h b/core/include/mr_buffer.h
new file mode 100644
index 0000000..3e136cc
--- /dev/null
+++ b/core/include/mr_buffer.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+#include <mr_core.h>
+#include <mr_common.h>
+
+#ifndef MRB_MAX_CTRLZONE_NUM
+#define MRB_MAX_CTRLZONE_NUM 16
+#endif
+
+struct mrb_pool_t
+{
+ unsigned int pool_num;
+ unsigned int total_ctrl_zone_size;
+ struct rte_mempool ** mr_pkt_pool;
+ struct rte_mempool ** mr_indirect_pool;
+};
+
+struct mrb_pool_t * MRB_pool_handle_create();
+
+int mr_buffer_user_pool_produce(struct mr_core_instance* instance, unsigned int socket_id, unsigned int data_size,
+ unsigned int pool_size, unsigned int cache_size);
+
+struct rte_mempool * mr_buffer_user_direct_pool_get(struct mr_core_instance* instance, socket_id_t socket);
+
+struct rte_mempool * mr_buffer_user_indirect_pool_get(struct mr_core_instance* instance, socket_id_t socket);
+
+int mr_buffer_pool_produce(struct mr_core_instance* instance, unsigned int socket_id, unsigned int data_size,
+ unsigned int pool_size, unsigned int cache_size);
+
+int mr_buffer_ctrlzone_register(struct mr_core_instance* instance, const char* cz_sym,
+ uint8_t id, uint8_t size);
+
+int mr_buffer_ctrlzone_lookup(struct mr_core_instance* instance, const char* cz_sym,
+ uint8_t * id, uint8_t * size);
+
+void * mr_buffer_ctrlzone(struct rte_mbuf * mr_buff, uint8_t id);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/core/include/mr_core.h b/core/include/mr_core.h
index f39c901..7d96417 100644
--- a/core/include/mr_core.h
+++ b/core/include/mr_core.h
@@ -5,7 +5,8 @@ struct mr_global_config;
struct devman_ctx;
struct stat_ctx;
struct vnodeman_ctx;
-struct mrbuf_ctx;
+struct mrb_pool_t;
+struct rtdev_desc_list;
// Core��ʵ���ṹ�壨ȫ�֣�
struct mr_core_instance
@@ -14,19 +15,26 @@ struct mr_core_instance
struct devman_ctx * devman_ctx;
struct stat_ctx * stat_ctx;
struct vnodeman_ctx * vnodeman_ctx;
- struct mrbuf_ctx * mrbuf_ctx;
+ struct mrb_pool_t * mrb_pool_handle;
+
+ /* ����ʱ�豸�б� */
+ struct rtdev_desc_list * rtdev_list;
+ unsigned int nr_rtdev;
+};
+
+struct mr_core_config
+{
+ void * _reserved;
};
+
// Core��ʵ���ṹ�壨���̼���
struct mr_core_slave_instance
{
void * _reserved;
};
-struct mr_core_instance * mr_core_instance_create(struct mr_global_config * g_cfg);
+struct mr_core_instance * mr_core_instance_create(struct mr_core_config * config);
void mr_core_instance_destory(struct mr_core_instance * object);
-void mr_core_instance_config(struct mr_core_instance * object);
-void mr_core_instance_init(struct mr_core_instance * object);
-struct mr_core_slave_instance * mr_core_instance_slave_init(struct mr_core_instance * core_ctx);
void mr_core_default_instance_set(struct mr_core_instance * object);
struct mr_core_instance * mr_core_default_instance_get(); \ No newline at end of file
diff --git a/core/include/mr_device.h b/core/include/mr_device.h
index fb1578f..90679fd 100644
--- a/core/include/mr_device.h
+++ b/core/include/mr_device.h
@@ -10,6 +10,21 @@ extern "C" {
#include <rte_ether.h>
#include <rte_pci.h>
#include <rte_config.h>
+#include <rte_spinlock.h>
+#include <assert.h>
+#include "mr_core.h"
+
+#ifndef MR_DEVICE_DEFAULT_NR_PKTMBUF
+#define MR_DEVICE_DEFAULT_NR_PKTMBUF 8192
+#endif
+
+#ifndef MR_DEVICE_DEFAULT_SZ_PKTMBUF
+#define MR_DEVICE_DEFAULT_SZ_PKTMBUF RTE_MBUF_DEFAULT_DATAROOM
+#endif
+
+#ifndef MR_DEVICE_DEFAULT_NR_PKTMBUF_CACHE
+#define MR_DEVICE_DEFAULT_NR_PKTMBUF_CACHE 256
+#endif
// RSSģʽ
enum rssmode
@@ -20,7 +35,6 @@ enum rssmode
MR_DEV_RSSMODE_4TUPLE_ASYM = 3
};
-
struct mr_dev_info
{
/* ����MAC��ַ*/
@@ -41,8 +55,6 @@ struct mr_dev_param
char symbol[MR_SYMBOL_MAX];
/* �û�MAC��ַ*/
struct ether_addr usr_ether_addr;
- /* ������ */
- unsigned int nr_queues;
/* MTU */
unsigned short mtu;
/* ����ģʽ */
@@ -59,6 +71,51 @@ struct mr_dev_param
unsigned int nr_rxdesc;
/* TX������������ */
unsigned int nr_txdesc;
+ /* ����������ͨRSS��RX�ࣩ */
+ unsigned int nr_rss_rxq;
+ /* ����������ͨRSS��TX�ࣩ*/
+ unsigned int nr_rss_txq;
+ /* ���ijػ��������� */
+ unsigned int nr_direct_pktmbuf;
+ /* ��ӱ��ijػ��������� */
+ unsigned int nr_indirect_pktmbuf;
+ /* ���Ļ�������С */
+ unsigned int sz_pktmbuf;
+ /* ������������������ */
+ unsigned int nr_pktmbuf_cache;
+};
+
+enum dev_q_type
+{
+ /* ����RSS���У��ձ��IJ� */
+ DEVQ_TYPE_RSS_RX = 0,
+ /* ����RSS���������IJ� */
+ DEVQ_TYPE_RSS_TX = 1,
+ /* ����� */
+ DEVQ_TYPE_RSS_MAX
+};
+
+static inline const char * __str_dev_q_type(enum dev_q_type type)
+{
+ switch(type)
+ {
+ case DEVQ_TYPE_RSS_RX: return "RSS_RX";
+ case DEVQ_TYPE_RSS_TX: return "RSS_TX";
+ default: assert(0);
+ }
+
+ assert(0);
+ return NULL;
+}
+
+struct mr_dev_q
+{
+ /* �����Ƿ�ʹ�� */
+ unsigned short in_use;
+ /* ����������� */
+ port_id_t port_id;
+ /* ����������� */
+ queue_id_t queue_id;
};
struct mr_dev
@@ -80,21 +137,21 @@ struct mr_dev
unsigned short mtu;
/* ����ʱMAC��ַ*/
struct ether_addr ether_addr;
-
/* �Ƿ����� */
unsigned int enable;
/* �豸�Ƿ��ѳ�ʼ�� */
unsigned int inited;
/* �Ƿ���Ҫ���³�ʼ�� */
unsigned int need_reinit;
+
+ /* �������� */
+ struct rte_mempool * direct_pool;
+ struct rte_mempool * indirect_pool;
+
/* �������������� */
- struct mr_devq * devq[RTE_MAX_QUEUES_PER_PORT];
- /* ������������������ */
- unsigned int nr_devq;
- /* ���������������Ѿ���attach������*/
- unsigned int nr_devq_attach;
- /* KNI��� */
- void * kni;
+ rte_spinlock_t qlock;
+ unsigned int nr_devq[DEVQ_TYPE_RSS_MAX];
+ struct mr_dev_q devq[DEVQ_TYPE_RSS_MAX][RTE_MAX_QUEUES_PER_PORT];
};
struct mr_devq
@@ -106,14 +163,17 @@ struct mr_devq
unsigned int enable;
};
-typedef struct mr_devq mr_devq_t;
-typedef struct mr_dev mr_dev_t;
-
-mr_dev_t * mr_device_open(struct mr_dev_param * param);
-int mr_device_close(mr_devq_t * devq);
-mr_devq_t * mr_device_attach(const char * devsym);
-int mr_device_list(mr_dev_t * devs[], int nr_max_devs, flags_t flags);
+int mr_device_list(struct mr_core_instance* instance, struct mr_dev * devs[], int nr_max_devs, flags_t flags);
struct mr_device_stat * mr_device_stat_get();
+struct mr_dev * mr_device_open(struct mr_core_instance* instance, struct mr_dev_param * param);
+struct mr_dev * mr_device_lookup(struct mr_core_instance* instance, const char * devsym);
+int mr_device_list(struct mr_core_instance* instance, struct mr_dev * devs[], int nr_max_devs, flags_t flags);
+int mr_device_close(struct mr_dev_q * devq);
+struct mr_dev_q * mr_device_attach(struct mr_dev * dev, enum dev_q_type q_type);
+void mr_device_deattach(struct mr_dev_q * dev_q);
+
+struct rte_mempool * mr_device_direct_pool_get(struct mr_dev * dev);
+struct rte_mempool * mr_device_indirect_pool_get(struct mr_dev * dev);
#define MR_DEVICE_FLAGS_PROMISC (1UL << 0)
diff --git a/core/include/mr_mrbuf.h b/core/include/mr_mrbuf.h
deleted file mode 100644
index 01c3595..0000000
--- a/core/include/mr_mrbuf.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef _MARSIO_BUF_INTERNAL_H_
-#define _MARSIO_BUF_INTERNAL_H_ 1
-
-/*
- marsio mbuf internal definition.
-*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <stdint.h>
-#include "mr_common.h"
-
-#define MR_BASE_ON_DPDK 1
-
-#ifdef MR_BASE_ON_DPDK /* ����Intel-DPDK rte_mbuf��װ */
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_atomic.h>
-#endif
-
-#define MAX_CZ_NUM (8)
-
-struct marsio_pri_t{
- struct rte_mbuf *pkt_next; /* ���mbuf�ṹ����, ��ʾ��ͬ���ݰ�������, ����ͬ��mbuf��next, ��һ�����Ķ��segment */
- void *ctrlzone[MAX_CZ_NUM];
-};
-
-
-struct mrbuf_ctx
-{
- uint32_t mempool_block_num;
- uint32_t mempool_dataroom_size;
- uint32_t mempool_priv_size;
-
- rte_atomic32_t mr_ctrl_zone_id;
- int32_t mr_buf_pool_num;
- struct rte_mempool **mr_buf_pool;
-};
-
-typedef struct{
- uint32_t lcore_id;
- uint32_t __pad1;
- uint64_t alloc_mbuf_num;
- uint64_t __pad2[6];
-}mr_buf_stat_t; /* 64Byte cache alignment */
-
-#define MRBUF_PROC_MAGIC (0xA1B2C3D4E5F65AA5)
-typedef struct{
- uint64_t magic;
- mr_buf_stat_t mr_buf_stat;
-}mr_process_ctx_t;
-
-struct rte_mempool * mrbuf_get_mempool(socket_id_t socket_id);
-
-#ifdef MR_BASE_ON_PCAP
-
-/* TODO others */
-
-typedef struct{
- void *baseaddr;
-}marsio_buf_t;
-
-#endif
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/core/include/mr_rtdev.h b/core/include/mr_rtdev.h
index 0dda88c..f70cd32 100644
--- a/core/include/mr_rtdev.h
+++ b/core/include/mr_rtdev.h
@@ -8,40 +8,83 @@
*/
+#include <rte_mempool.h>
+#include <mr_core.h>
+#include <mr_vnode.h>
#include <mr_vman.h>
#include <mr_common.h>
+#include <sys/queue.h>
-struct mr_rtdev_stream
+struct rtdev_app_desc
{
+ TAILQ_ENTRY(rtdev_app_desc) next;
+ struct rtdev_desc * dev_desc;
+ struct vnode_ops ops;
+
char symbol[MR_SYMBOL_MAX];
- struct vnodeman_attach_desc * rxd;
- struct vnodeman_attach_desc * txd;
- struct vnodeman_attach_desc * fasttxd;
+ unsigned int nr_rx_stream;
+ unsigned int nr_tx_stream;
+
+ struct vnode_cons * vnode_cons_rx;
+ struct vnode_prod * vnode_prod_tx;
+ struct vnode_prod * vnode_prod_ftx;
+};
+
+TAILQ_HEAD(rtdev_app_desc_list, rtdev_app_desc);
+
+struct rtdev_desc
+{
+ TAILQ_ENTRY(rtdev_desc) next;
+
+ char symbol[MR_SYMBOL_MAX];
+ unsigned int nr_serv_stream;
+
+ struct vnode_ops ops;
+
+ struct vnode * vnode_rx;
+ struct vnode * vnode_tx;
+ struct vnode * vnode_ftx;
+
+ struct vnode_prod * vnode_prod_rx;
+ struct vnode_cons * vnode_cons_tx;
+ struct vnode_cons * vnode_cons_ftx;
+
+ rte_rwlock_t app_desc_lock;
+ struct rtdev_app_desc_list app_desc_list;
};
+struct rtdev_stat_info
+{
+ /* RX: from service to app */
+ uint64_t rx_on_line[MR_SID_MAX];
+ uint64_t rx_deliver[MR_SID_MAX];
+ uint64_t rx_missed[MR_SID_MAX];
+
+ /* TX: from app to service */
+ uint64_t tx_on_line[MR_SID_MAX];
+ uint64_t tx_deliver[MR_SID_MAX];
+ uint64_t tx_missed[MR_SID_MAX];
+
+ /* FTX: fast tunnel from app to serivce */
+ uint64_t ftx_on_line[MR_SID_MAX];
+ uint64_t ftx_deliver[MR_SID_MAX];
+ uint64_t ftx_missed[MR_SID_MAX];
+};
+
+TAILQ_HEAD(rtdev_desc_list, rtdev_desc);
+
// ����һ������ʱ�����豸
-int rt_device_serv_create(const char * devsym, const char * servsym, unsigned int nr_serv_thread,
- unsigned int sz_tunnel, unsigned int sz_buffer);
+struct rtdev_desc * mr_rtdev_create(struct mr_core_instance * instance, const char * devsym,
+ struct rte_mempool * pool, unsigned int nr_serv_thread, unsigned int sz_tunnel, unsigned int sz_buffer);
// ����һ������ʱ�����豸
-int rt_device_serv_destory(const char * devsym);
+int mr_rt_device_destory(struct rtdev_desc * desc);
// ���豸��ͨ����Slave������ʹ��
-int rt_device_open(const char * devsym, const char * appsym,
+struct rtdev_app_desc * mr_rt_device_open(struct mr_core_instance * instance, const char * devsym, const char * appsym,
unsigned int nr_rxstream, unsigned int nr_txstream);
-// ���豸����ÿ���̵߳���һ�Σ���ȡ��ǰ�̵߳������������������ʹ�ã�
-struct mr_rtdev_stream * rt_dev_serv_open_stream(const char * devsym,
- const char * servsym);
-
-#define RTDEV_FLAGS_OPEN_STREAM_RX ( 1UL << 0 )
-#define RTDEV_FLAGS_OPEN_STREAM_TX ( 1UL << 1 )
-#define RTDEV_FLAGS_OPEN_STREAM_ALL ( RTDEV_FLAGS_OPEN_STREAM_RX | RTDEV_FLAGS_OPEN_STREAM_TX )
-
-// ���豸����ÿ���̵߳���һ�Σ���ȡ��ǰ�̵߳���������
-struct mr_rtdev_stream * rt_dev_open_stream(const char * devsym,
- const char * appsym, flags_t flags);
-
-int rt_dev_stream_close(struct mr_rtdev_stream * stream);
+int mr_rt_device_close(struct rtdev_app_desc * desc);
-int rt_device_close(const char * devsym, const char * appsym); \ No newline at end of file
+// ����ʱ�豸��Ϣͳ��
+int mr_rtdev_stats_get(struct rtdev_desc * dev_desc, struct rtdev_stat_info * stat_info); \ No newline at end of file
diff --git a/core/include/mr_vnode.h b/core/include/mr_vnode.h
index e787df8..f650102 100644
--- a/core/include/mr_vnode.h
+++ b/core/include/mr_vnode.h
@@ -6,6 +6,7 @@ extern "C" {
#include <mr_common.h>
#include <sys/queue.h>
+#include <rte_memory.h>
#if MR_LIBVNODE_OPT_THREAD_SAFE
#include <rte_rwlock.h>
@@ -13,9 +14,17 @@ extern "C" {
struct tunnel_block
{
+ /* should be deleted */
unsigned int deleted;
+ /* Prod Queue Count */
unsigned int nr_prodq;
+ /* Cons Queue Count */
unsigned int nr_consq;
+ /* Tunnel's Producer */
+ struct vnode_prod * prod;
+ /* Tunnel's Consumer */
+ struct vnode_cons * cons;
+ /* Tunnel Descs */
struct tunnel_desc * descs[0];
};
@@ -27,6 +36,20 @@ struct tunnel_block_list_item
TAILQ_HEAD(tunnel_block_list, tunnel_block_list_item);
+struct vnode_cons_stat
+{
+ rte_atomic64_t on_line;
+ rte_atomic64_t recieved;
+ rte_atomic64_t missed;
+} __rte_cache_aligned;
+
+struct vnode_prod_stat
+{
+ rte_atomic64_t on_line;
+ rte_atomic64_t sent;
+ rte_atomic64_t missed;
+} __rte_cache_aligned;
+
/* Virtual Data-Node Consumer Structure */
struct vnode_cons
{
@@ -38,6 +61,7 @@ struct vnode_cons
struct tunnel_block_list block_list;
unsigned int nr_block;
unsigned int cur_attach;
+ struct vnode_cons_stat stat[MR_SID_MAX];
};
/* Virtual Data-Node Producer Structure */
@@ -51,6 +75,7 @@ struct vnode_prod
struct tunnel_block_list block_list;
unsigned int nr_block;
unsigned int cur_attach;
+ struct vnode_prod_stat stat[MR_SID_MAX];
};
/* Virtual Data-Node Consumer Queue Structure */
@@ -98,10 +123,15 @@ struct vnode
struct vnode_ops
{
+ /* Pool */
+ void * pool_new_object;
+ /* Pool */
+ void * pool_dup_object;
+
/* Object Operation Functions */
- void *(*op_object_new)();
+ void *(*op_object_new)(void * pool);
void(*op_object_delete)(void * object);
- void *(*op_object_dup)(void * object);
+ void *(*op_object_dup)(void * object, void * pool);
};
struct vnode * vnode_create(const char * sym, struct vnode_ops * ops,
@@ -128,6 +158,10 @@ unsigned int prodq, void * objects[], uint32_t hash[], int nr_objects);
int vnode_dequeue_burst(struct vnode_cons * cons, struct vnode_ops * ops,
unsigned int consq, void * objects[], int nr_max_objects);
+struct vnode_prod_stat * vnode_prod_stat_get(struct vnode_prod * prod);
+
+struct vnode_cons_stat * vnode_cons_stat_get(struct vnode_cons * cons);
+
/**
* \brief Attach Operation for Vnode's Coumser
* \param node VNode Structure
diff --git a/core/src/buffer.c b/core/src/buffer.c
new file mode 100644
index 0000000..3038e6c
--- /dev/null
+++ b/core/src/buffer.c
@@ -0,0 +1,419 @@
+/******************************************************************
+ * DPDK rte_mbuf wrap.
+ * Author: [email protected]
+ * Date: 2016-11-18
+ ******************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <mr_buffer.h>
+#include <mr_runtime.h>
+#include <mr_core.h>
+
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_common.h>
+#include <marsio_buffer_user_api.h>
+
+struct mrb_zone_idx_t
+{
+ uint8_t offset;
+ uint8_t size;
+};
+
+struct mrb_priv_zone_t
+{
+ struct rte_mbuf * next;
+ uint8_t cz_num;
+ struct mrb_zone_idx_t idx[0];
+}__rte_packed;
+
+struct mrb_zone_info_t
+{
+ char symbol[MR_SYMBOL_MAX];
+ unsigned int cz_id;
+ unsigned int size;
+ unsigned int in_use;
+};
+
+struct whole_mrb_pool_t
+{
+ struct mrb_pool_t external; //"external" must be the first member of this struct
+ struct rte_mempool * user_direct_pool;
+ struct rte_mempool * user_indirect_pool;
+
+ unsigned int total_ctrl_zone_size;
+ uint8_t ctrlzone_num;
+ struct mrb_zone_info_t ctrlzone_info[MRB_MAX_CTRLZONE_NUM];
+ struct mrb_zone_idx_t ctrlzone[MRB_MAX_CTRLZONE_NUM];
+};
+
+#define mrbuf_priv(m) ((struct mrb_priv_zone_t*)((char*)m+sizeof(struct rte_mbuf)))
+#define mrbuf_cz(m,k) (&(mrbuf_priv(m)->idx[k]))
+#define mrbuf_cz_data(m,k) ((void*)((char*)mrbuf_priv(m)+mrbuf_cz(m,k)->offset))
+#define mrbuf_cz_num(m) (mrbuf_priv(m)->cz_num)
+
+static void set_element_ctrlzone(__attribute__((unused))struct rte_mempool *mp,
+ void *opaque, void *obj, __attribute__((unused)) unsigned obj_idx)
+{
+ struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)opaque;
+ struct mrb_priv_zone_t* private = mrbuf_priv(obj);
+ private->cz_num = _handle->ctrlzone_num;
+ private->next = NULL;
+
+ assert(mp->private_data_size >= sizeof(struct mrb_zone_idx_t)*_handle->ctrlzone_num);
+ memcpy(private->idx, _handle->ctrlzone, sizeof(struct mrb_zone_idx_t)*_handle->ctrlzone_num);
+ return;
+}
+
+struct mrb_pool_t * MRB_pool_handle_create()
+{
+ struct whole_mrb_pool_t *handle = rte_zmalloc(NULL, sizeof(struct whole_mrb_pool_t), 0);
+ MR_CHECK(handle != NULL, "Cannot alloc memory for MRB Pool handle. ");
+
+ handle->external.pool_num = 0;
+ handle->total_ctrl_zone_size = sizeof(struct mrb_priv_zone_t);
+ return (struct mrb_pool_t *)handle;
+}
+
+struct rte_mempool * mr_buffer_user_direct_pool_get(struct mr_core_instance* instance, socket_id_t socket)
+{
+ struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle;
+ return _handle->user_direct_pool;
+}
+
+struct rte_mempool * mr_buffer_user_indirect_pool_get(struct mr_core_instance* instance, socket_id_t socket)
+{
+ struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle;
+ return _handle->user_indirect_pool;
+}
+
+int mr_buffer_user_pool_produce(struct mr_core_instance* instance, unsigned int socket_id, unsigned int data_size,
+ unsigned int pool_size, unsigned int cache_size)
+{
+ struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle;
+ char str_pool_sym[MR_SYMBOL_MAX];
+ int ret = 0;
+
+ unsigned int priv_size = RTE_ALIGN(_handle->total_ctrl_zone_size, RTE_MBUF_PRIV_ALIGN);
+
+ if (_handle->user_direct_pool == NULL)
+ {
+ snprintf(str_pool_sym, sizeof(str_pool_sym), "mrb_usr_pkt_pool_%d", socket_id);
+ _handle->user_direct_pool = rte_pktmbuf_pool_create(str_pool_sym, pool_size, cache_size,
+ priv_size, data_size, socket_id);
+ }
+
+ if (_handle->user_direct_pool == NULL)
+ {
+ MR_LOG(WARNING, BASE, "Creating user direct pktmbuf pool(symbol=%s, size=%d, cache=%d, "
+ "ctrlzone=%d, datasize=%d) : failed - %s)\n", str_pool_sym, pool_size, cache_size,
+ priv_size, data_size, __str_errno());
+
+ ret = -1; goto errout;
+ }
+
+ if (_handle->user_indirect_pool == NULL)
+ {
+ snprintf(str_pool_sym, sizeof(str_pool_sym), "mrb_usr_indirect_pool_%d", socket_id);
+ _handle->user_indirect_pool = rte_pktmbuf_pool_create(str_pool_sym, pool_size, cache_size,
+ priv_size, 0, socket_id);
+ }
+
+ if (_handle->user_indirect_pool == NULL)
+ {
+ MR_LOG(WARNING, BASE, "Creating user indirect pktmbuf pool(symbol=%s, size=%d, cache=%d, "
+ "ctrlzone=%d, datasize=%d) : failed - %s)\n", str_pool_sym, pool_size, cache_size,
+ priv_size, 0, __str_errno());
+
+ ret = -2; goto errout;
+ }
+
+ ret = rte_mempool_obj_iter(_handle->user_direct_pool, set_element_ctrlzone, _handle);
+ assert(ret == pool_size);
+
+ ret = rte_mempool_obj_iter(_handle->user_indirect_pool, set_element_ctrlzone, _handle);
+ assert(ret == pool_size);
+
+ return 0;
+
+errout:
+ if (_handle->user_direct_pool != NULL) rte_mempool_free(_handle->user_direct_pool);
+ if (_handle->user_indirect_pool != NULL) rte_mempool_free(_handle->user_indirect_pool);
+ return ret;
+}
+
+
+int mr_buffer_pool_produce(struct mr_core_instance* instance, unsigned int socket_id, unsigned int data_size,
+ unsigned int pool_size, unsigned int cache_size)
+{
+ struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle;
+ struct mrb_pool_t * handle = instance->mrb_pool_handle;
+
+ char str_pool_sym[MR_SYMBOL_MAX];
+
+ unsigned int priv_size = RTE_ALIGN(_handle->total_ctrl_zone_size, RTE_MBUF_PRIV_ALIGN);
+ int i = _handle->external.pool_num;
+
+ handle->mr_pkt_pool = (struct rte_mempool **)rte_realloc(handle->mr_pkt_pool,
+ sizeof(struct rte_mempool*)*(i + 1), 0);
+
+ handle->mr_indirect_pool = (struct rte_mempool **)rte_realloc(handle->mr_indirect_pool,
+ sizeof(struct rte_mempool*)*(i + 1), 0);
+
+ snprintf(str_pool_sym, sizeof(str_pool_sym), "mrb_pkt_pool_%d", i);
+ handle->mr_pkt_pool[i] = rte_pktmbuf_pool_create(str_pool_sym, pool_size, cache_size,
+ priv_size, data_size, socket_id);
+
+ if (handle->mr_pkt_pool[i] == NULL)
+ {
+ MR_LOG(WARNING, BASE, "Creating dataplane pktmbuf pool(symbol=%s, size=%d, cache=%d, "
+ "ctrlzone=%d, datasize=%d) : failed - %s)\n", str_pool_sym, pool_size, cache_size,
+ priv_size, data_size, __str_errno());
+ return -3;
+ }
+
+ rte_mempool_obj_iter(handle->mr_pkt_pool[i], set_element_ctrlzone, _handle);
+
+ MR_LOG(DEBUG, BASE, "Creating dataplane pktmbuf pool(symbol=%s, size=%d, cache=%d, "
+ "ctrlzone=%d, datasize=%d) : Success\n", str_pool_sym, pool_size, cache_size,
+ priv_size, data_size);
+
+ snprintf(str_pool_sym, sizeof(str_pool_sym), "mrb_indirect_pool_%d", i);
+ handle->mr_indirect_pool[i] = rte_pktmbuf_pool_create(str_pool_sym, pool_size, cache_size,
+ priv_size, 0, socket_id);
+
+ if (handle->mr_indirect_pool[i] == NULL)
+ {
+ MR_LOG(WARNING, BASE, "Creating dataplane indirect pktmbuf pool(symbol=%s, size=%d, cache=%d, "
+ "ctrlzone=%d, datasize=%d) : failed - %s)", str_pool_sym, pool_size, cache_size,
+ priv_size, 0, __str_errno());
+ return -4;
+ }
+
+ int ret __rte_unused = rte_mempool_obj_iter(handle->mr_indirect_pool[i], set_element_ctrlzone, _handle);
+ assert(ret == pool_size);
+ handle->pool_num++;
+
+ MR_LOG(DEBUG, BASE, "Creating dataplane indirect pktmbuf pool(symbol=%s, size=%d, cache=%d, "
+ "ctrlzone=%d, datasize=%d) : Success\n", str_pool_sym, pool_size, cache_size,
+ priv_size, data_size);
+
+ return i;
+}
+
+int mr_buffer_ctrlzone_register(struct mr_core_instance* instance, const char* cz_sym,
+ uint8_t id, uint8_t size)
+{
+ struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle;
+
+ if (_handle->ctrlzone_num >= MRB_MAX_CTRLZONE_NUM)
+ {
+ return -EOVERFLOW;
+ }
+
+ if (_handle->ctrlzone[id].size != 0)
+ {
+ return -EEXIST;
+ }
+
+ if(_handle->ctrlzone_info[id].in_use)
+ {
+ return -EEXIST;
+ }
+
+ snprintf(_handle->ctrlzone_info[id].symbol, sizeof(_handle->ctrlzone_info[id].symbol), "%s", cz_sym);
+ _handle->ctrlzone_info[id].size = size;
+ _handle->ctrlzone_info[id].cz_id = id;
+ _handle->ctrlzone_info[id].in_use = 1;
+
+ _handle->ctrlzone[id].size = size;
+ _handle->ctrlzone[id].offset = _handle->total_ctrl_zone_size;
+ _handle->total_ctrl_zone_size += (size + sizeof(struct mrb_zone_idx_t));
+ _handle->ctrlzone_num++;
+ return 0;
+}
+
+int mr_buffer_ctrlzone_lookup(struct mr_core_instance* instance, const char* cz_sym,
+ uint8_t * id, uint8_t * size)
+{
+ struct whole_mrb_pool_t *_handle = (struct whole_mrb_pool_t *)instance->mrb_pool_handle;
+ for(int i = 0; i < _handle->ctrlzone_num; i++)
+ {
+ struct mrb_zone_idx_t * cz __rte_unused = &_handle->ctrlzone[i];
+ struct mrb_zone_info_t * czinfo = &_handle->ctrlzone_info[i];
+ if (strcmp(czinfo->symbol, cz_sym) != 0) continue;
+
+ assert(cz->size != 0);
+ assert(czinfo->in_use > 0);
+ assert(czinfo->size > 0);
+ assert(czinfo->cz_id == i);
+
+ *id = czinfo->cz_id;
+ *size = czinfo->size;
+ return 0;
+ }
+
+ return -1;
+}
+
+void * marsio_buff_ctrlzone(marsio_buff_t *mr_buff, uint8_t id)
+{
+ assert(id < mrbuf_cz_num(mr_buff));
+ return mrbuf_cz_data(mr_buff, id);
+}
+
+void * marsio_buff_ctrlzone_data(marsio_buff_t *mr_buff, uint8_t id, uint8_t *size)
+{
+ struct mrb_zone_idx_t* cz = mrbuf_cz(mr_buff, id);
+ assert(id < mrbuf_cz_num(mr_buff));
+ *size = cz->size;
+ return mrbuf_cz_data(mr_buff, id);
+}
+
+void marsio_buff_ctrlzone_set(marsio_buff_t *mr_buff, uint8_t id, void* ptr_data, uint8_t size)
+{
+ struct mrb_zone_idx_t* cz = mrbuf_cz(mr_buff, id);
+ assert(id < mrbuf_cz_num(mr_buff));
+ assert(size <= cz->size);
+ memcpy(mrbuf_cz_data(mr_buff, id), ptr_data, size);
+ return;
+}
+
+void * mr_buffer_ctrlzone(struct rte_mbuf * mr_buff, uint8_t id)
+{
+ assert(id < mrbuf_cz_num(mr_buff));
+ return mrbuf_cz_data(mr_buff, id);
+}
+
+
+int marsio_buff_malloc(marsio_buff_t *marsio_buff[], unsigned int nb_buff,
+ __attribute__((unused))unsigned int flags,
+ __attribute__((unused))int thread_seq)
+{
+ struct mr_core_instance * this_core = NULL;
+ struct whole_mrb_pool_t * _handle = NULL;
+
+ this_core = mr_core_default_instance_get();
+ _handle = (struct whole_mrb_pool_t *)this_core->mrb_pool_handle;
+
+ for (int i = 0; i < nb_buff; i++)
+ {
+ marsio_buff[i] = rte_pktmbuf_alloc(_handle->user_direct_pool);
+ if (marsio_buff[i] == NULL) return i;
+ }
+
+ return nb_buff;
+}
+
+void marsio_buff_free(marsio_buff_t *marsio_buff[], unsigned int nb_buff)
+{
+ for (int i = 0; i < nb_buff; i++)
+ {
+ mrbuf_priv(marsio_buff[i])->next = NULL;
+ rte_pktmbuf_free((struct rte_mbuf *)marsio_buff[i]);
+ }
+
+ return;
+}
+
+void marsio_buff_append_pkt(marsio_buff_t *head, marsio_buff_t *next)
+{
+ marsio_buff_t *p = head;
+ while (mrbuf_priv(p)->next != NULL)
+ {
+ p = mrbuf_priv(p)->next;
+ }
+ mrbuf_priv(p)->next = next;
+}
+
+void marsio_buff_append_seg(marsio_buff_t *head, marsio_buff_t *next)
+{
+ rte_pktmbuf_chain((struct rte_mbuf *)head, (struct rte_mbuf *)next);
+}
+
+marsio_buff_t *marsio_buff_getnext_seg(marsio_buff_t *m)
+{
+ return (marsio_buff_t *)(((struct rte_mbuf*)m)->next);
+}
+
+marsio_buff_t *marsio_buff_getnext_pkt(marsio_buff_t *m)
+{
+ return mrbuf_priv(m)->next;
+}
+
+void marsio_buff_reset(marsio_buff_t *m)
+{
+ struct mrb_priv_zone_t* priv_zone = mrbuf_priv(m);
+ struct mrb_zone_idx_t* cz_first = NULL, *cz_last = NULL;
+
+ rte_pktmbuf_reset((struct rte_mbuf *)m);
+ priv_zone->next = NULL;
+ if (mrbuf_cz_num(m) > 0)
+ {
+ cz_first = mrbuf_cz(m, 0);
+ cz_last = mrbuf_cz(m, mrbuf_cz_num(m) - 1);
+ memset(mrbuf_cz_data(m, 0), 0, cz_last->offset + cz_last->size - cz_first->offset);
+ }
+ return;
+}
+
+char *marsio_buff_mtod(marsio_buff_t *m)
+{
+ return rte_pktmbuf_mtod((struct rte_mbuf *)m, char *);
+}
+
+uint32_t marsio_buff_buflen(marsio_buff_t *m)
+{
+ return rte_pktmbuf_pkt_len((struct rte_mbuf *)m);
+}
+
+uint32_t marsio_buff_datalen(marsio_buff_t *m)
+{
+ return rte_pktmbuf_data_len((struct rte_mbuf *)m);
+}
+
+char *marsio_buff_prepend(marsio_buff_t *m, uint16_t len)
+{
+ return rte_pktmbuf_prepend((struct rte_mbuf *)m, len);
+}
+
+char *marsio_buff_append(marsio_buff_t *m, uint16_t len)
+{
+ return rte_pktmbuf_append((struct rte_mbuf *)m, len);
+}
+
+char *marsio_buff_adj(marsio_buff_t *m, uint16_t len)
+{
+ return rte_pktmbuf_adj((struct rte_mbuf *)m, len);
+}
+
+int marsio_buff_trim(marsio_buff_t *m, uint16_t len)
+{
+ return rte_pktmbuf_trim((struct rte_mbuf *)m, len);
+}
+
+uint16_t marsio_buff_headroom(const marsio_buff_t *m)
+{
+ return rte_pktmbuf_headroom((const struct rte_mbuf *)m);
+}
+
+uint16_t marsio_buff_tailroom(const marsio_buff_t *m)
+{
+ return rte_pktmbuf_tailroom((const struct rte_mbuf *)m);
+}
+
+uint32_t marsio_get_pkt_type(marsio_buff_t *m)
+{
+ return ((struct rte_mbuf *)m)->packet_type;
+}
+
+marsio_buff_t *marsio_buff_dup(marsio_buff_t *m)
+{
+ assert(0);
+ return NULL;
+} \ No newline at end of file
diff --git a/core/src/core.c b/core/src/core.c
index 105370d..20e7dde 100644
--- a/core/src/core.c
+++ b/core/src/core.c
@@ -9,17 +9,14 @@
#include <mr_runtime.h>
#include <rte_ip_frag.h>
#include <mr_core.h>
+#include "mr_buffer.h"
// �ⲿ�����������豸������
-extern int devman_ctx_init(struct mr_core_instance * core_instance);
-extern int devman_config(struct mr_core_instance * core_instance);
extern int devman_init(struct mr_core_instance * core_instance);
extern int devman_destory(struct mr_core_instance * core_instance);
-extern int devman_slave_init(struct mr_core_instance * core_instance,
- struct mr_core_slave_instance * slave_instance);
// �ⲿ����������ͳ��
-extern int stat_ctx_init(struct mr_core_instance * core_instance);
+extern int stat_init(struct mr_core_instance * core_instance);
extern int stat_config(struct mr_core_instance * core_instance);
extern int stat_init(struct mr_core_instance * core_instance);
extern int stat_slave_init(struct mr_core_instance * core_instance,
@@ -35,64 +32,35 @@ extern int mrbuf_slave_init(struct mr_core_instance * core_instance,
struct mr_core_slave_instance * slave_instance);
// �ⲿ�����������������ݽڵ������
-extern int vnodeman_ctx_init(struct mr_core_instance * core_instance);
-extern int vnodeman_config(struct mr_core_instance * core_instance);
extern int vnodeman_init(struct mr_core_instance * core_instance);
-extern int vnodeman_slave_init(struct mr_core_instance * core_instance,
- struct mr_core_slave_instance * slave_instance);
extern int vnodeman_destory(struct mr_core_instance * core_instance);
// Ĭ�ϵ�CoreInstance
static struct mr_core_instance * default_core_instance = NULL;
-struct mr_core_instance * mr_core_instance_create(struct mr_global_config * g_cfg)
+struct mr_core_instance * mr_core_instance_create(struct mr_core_config* config)
{
struct mr_core_instance * instance;
instance = rte_zmalloc("CoreInstance", sizeof(struct mr_core_instance), 0);
MR_CHECK(instance != NULL, "Cannot alloc memory for CoreInstance. ");
int ret = 0;
- instance->g_cfg = g_cfg;
- ret = mrbuf_ctx_init(instance);
- MR_CHECK(ret >= 0, "Failed at CoreMrbuf Preinit stage.");
-
- ret = devman_ctx_init(instance);
+ ret = devman_init(instance);
MR_CHECK(ret >= 0, "Failed at CoreDevice Preinit stage.");
- ret = vnodeman_ctx_init(instance);
- MR_CHECK(ret >= 0, "Failed at CoreVNodeMan Preinit stage.");
-
- ret = stat_ctx_init(instance);
+ ret = stat_init(instance);
MR_CHECK(ret >= 0, "Failed at CoreStat Preinit stage.");
- return instance;
-}
-void mr_core_instance_destory(struct mr_core_instance * object)
-{
- return;
-}
+ struct mrb_pool_t * pool = MRB_pool_handle_create();
+ MR_CHECK(pool != NULL, "Failed at MRB Pool create. ");
-void mr_core_instance_config(struct mr_core_instance * object)
-{
- int ret = mrbuf_config(object);
- MR_CHECK(ret >= 0, "Failed at CoreMrbuf Config stage.");
-
- ret = devman_config(object);
- MR_CHECK(ret >= 0, "Failed at CoreDevice Config stage.");
-
- ret = stat_config(object);
- MR_CHECK(ret >= 0, "Failed at CoreStat Config stage.");
- return;
+ instance->mrb_pool_handle = pool;
+ return instance;
}
-void mr_core_instance_init(struct mr_core_instance * object)
+void mr_core_instance_destory(struct mr_core_instance * object)
{
- int ret = mrbuf_init(object);
- MR_CHECK(ret >= 0, "Failed at CoreMrbuf Init stage.");
-
- ret = devman_init(object);
- MR_CHECK(ret >= 0, "Failed at CoreDevice Init stage.");
return;
}
@@ -117,21 +85,4 @@ struct mr_core_instance * mr_core_default_instance_get()
{
assert(default_core_instance != NULL);
return default_core_instance;
-}
-
-struct mr_core_slave_instance * mr_core_instance_slave_init(struct mr_core_instance * object)
-{
- struct mr_core_slave_instance * slave_instance;
- slave_instance = rte_zmalloc("CoreSlaveInstance", sizeof(struct mr_core_slave_instance), 0);
- MR_CHECK(slave_instance != NULL, "Cannot alloc memory for CoreSlaveInstance. ");
-
- int ret = mrbuf_slave_init(object, slave_instance);
- MR_CHECK(ret >= 0, "Failed at CoreMrbuf slaveinit stage.");
- ret = devman_slave_init(object, slave_instance);
- MR_CHECK(ret >= 0, "Failed at CoreDevice slaveinit stage.");
- ret = vnodeman_slave_init(object, slave_instance);
- MR_CHECK(ret >= 0, "Failed at CoreVNodeMan slaveinit stage.");
- ret = stat_slave_init(object, slave_instance);
- MR_CHECK(ret >= 0, "Failed at CoreStat slaveinit stage.");
- return slave_instance;
} \ No newline at end of file
diff --git a/core/src/device.c b/core/src/device.c
index 2bf25e5..eca3aef 100644
--- a/core/src/device.c
+++ b/core/src/device.c
@@ -13,16 +13,13 @@
#include <rte_kni.h>
#include <rte_ethdev.h>
-#include <MESA_prof_load.h>
-
#include <mr_common.h>
-#include <mr_mrbuf.h>
#include <mr_device.h>
#include <mr_core.h>
-#include <mr_runtime.h>
+#include "mr_buffer.h"
#ifndef MR_DEVICE_DEFAULT_NR_RX_DESC
-#define MR_DEVICE_DEFAULT_NR_RX_DESC 512
+#define MR_DEVICE_DEFAULT_NR_RX_DESC 128
#endif
#ifndef MR_DEVICE_DEFAULT_NR_TX_DESC
@@ -68,185 +65,12 @@ TAILQ_HEAD(mr_deivce_list, mr_dev);
struct devman_ctx
{
- unsigned int default_nr_rx_desc;
- unsigned int default_nr_tx_desc;
- struct rte_eth_conf * default_eth_conf;
-
struct mr_deivce_list device_list;
struct mr_dev * rte_device[RTE_MAX_ETHPORTS];
};
-#if 0
-
-static int kni_change_mtu(__attribute__((unused)) uint8_t port_id,
- __attribute__((unused)) unsigned new_mtu)
-{
- return 1;
-}
-static int kni_config_network_interface(__attribute__((unused)) uint8_t port_id,
- __attribute__((unused)) uint8_t if_up)
-{
- return 1;
-}
-
-static struct rte_kni * __rte_unused kni_alloc(const char * sym,
- uint8_t port_id, struct rte_mempool * pktmbuf_pool)
-{
- struct rte_kni *kni;
- struct rte_kni_conf conf;
-
- snprintf(conf.name, sizeof(conf.name), "%s", sym);
- conf.group_id = (uint16_t)port_id;
- conf.mbuf_size = 1500;
-
- struct rte_kni_ops ops;
- struct rte_eth_dev_info dev_info;
-
- memset(&dev_info, 0, sizeof(dev_info));
- rte_eth_dev_info_get(port_id, &dev_info);
- conf.addr = dev_info.pci_dev->addr;
- conf.id = dev_info.pci_dev->id;
-
- ops.port_id = port_id;
- ops.change_mtu = kni_change_mtu;
- ops.config_network_if = kni_config_network_interface;
-
- kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops);
- return kni;
-}
-
-static void __rte_unused kni_free(struct rte_kni * kni)
-{
- rte_kni_release(kni);
-}
-
-#endif
-
-// 设备预打开,真正的初始化过程在设备初始化时进行。
-struct mr_devq * __device_open_devq(struct mr_dev * dev)
-{
- // 越界检测
- struct mr_dev_info * dev_info = &dev->info;
- assert(dev->nr_devq <= RTE_DIM(dev->devq));
- assert(dev->nr_rxq <= dev_info->nr_rxq_max);
- assert(dev->nr_txq <= dev_info->nr_txq_max);
-
- // 检查队列数量,超过队列数申请即失败
- if (dev->nr_devq >= RTE_DIM(dev->devq))
- {
- MR_LOG(INFO, BASE, "DeviceManager, DeviceOpen, Device %s, "
- "Too many open request\n", dev->symbol);
- return NULL;
- }
-
- if (dev->nr_rxq >= dev_info->nr_rxq_max)
- {
- MR_LOG(INFO, BASE, "DeviceManager, DeviceOpen, Device %s, "
- "Too many recieve queues\n", dev->symbol);
- return NULL;
- }
-
- if (dev->nr_txq >= dev_info->nr_txq_max)
- {
- MR_LOG(INFO, BASE, "DeviceManager, DeviceOpen, Device %s, "
- "Too many xmit queues\n", dev->symbol);
- return NULL;
- }
-
- // 申请队列描述符空间
- dev->devq[dev->nr_devq] = rte_zmalloc("DEVICE_DESC", sizeof(struct mr_devq), 0);
- MR_CHECK(dev->devq[dev->nr_devq] != NULL, "DeviceManager, DeviceOpen, Device %s"
- "Cannot alloc memory for mr_devq", dev->symbol);
-
- // 初始化队列描述符
- struct mr_devq * devq = dev->devq[dev->nr_devq];
- devq->enable = 1;
- devq->device = dev;
- devq->port_id = dev->port_id;
- devq->rx_queue_id = dev->nr_rxq;
- devq->tx_queue_id = dev->nr_txq;
-
- // 增加队列计数
- dev->enable = 1;
- dev->nr_rxq++;
- dev->nr_txq++;
- dev->nr_devq++;
- return devq;
-}
-
-// 设备预打开,一次打开多个队列
-int __device_open_multidevq(struct mr_dev * dev, int count)
-{
- for(int i = 0; i < count; i++)
- {
- struct mr_devq * devq = __device_open_devq(dev);
- if (devq == NULL) return -1;
- }
-
- return 0;
-}
-
-static struct mr_dev * __device_lookup(struct devman_ctx * ctx,
- const char * devsym)
-{
- struct mr_dev * dev_iter = NULL;
- struct mr_dev * dev_ret = NULL;
- TAILQ_FOREACH(dev_iter, &ctx->device_list, next)
- {
- if (strncmp(dev_iter->symbol, devsym, sizeof(dev_iter->symbol)) != 0)
- continue;
-
- dev_ret = dev_iter;
- break;
- }
- return dev_ret;
-}
-
-static struct mr_dev * __device_open(struct devman_ctx * ctx,
- struct mr_dev_param * param)
-{
- struct mr_dev * dev = __device_lookup(ctx, param->symbol);
-
- if (dev == NULL)
- {
- MR_LOG(INFO, BASE, "DeviceManager, DeviceOpen, "
- "Cannot found device %s\n", param->symbol);
- return NULL;
- }
-
- dev->param = *param;
- int ret = __device_open_multidevq(dev, param->nr_queues);
-
- if (ret < 0)
- {
- MR_LOG(INFO, BASE, "DeviceManager, DeviceOpen, "
- "Cannot open device %s\n", param->symbol);
- return NULL;
- }
-
- return dev;
-}
-
-static struct mr_devq * __device_attach(struct devman_ctx * ctx, struct mr_dev * dev)
-{
- if(dev->nr_devq_attach >= dev->nr_devq)
- {
- MR_LOG(INFO, BASE, "DeviceManager, DeviceAttach, "
- "Too many attach queues for device %s (nr_devq=%d, nr_devq_attach=%d)\n",
- dev->symbol, dev->nr_devq, dev->nr_devq_attach);
- return NULL;
- }
- return dev->devq[dev->nr_devq_attach++];
-}
-
-static int __device_close(struct devman_ctx * ctx, mr_devq_t * devq)
-{
- return 0;
-}
-
-
// 扫描DPDK加载的网卡,初始化描述符空间,以便收集配置信息
-static int __device_scan(struct devman_ctx * ctx)
+static int device_scan(struct devman_ctx * ctx)
{
unsigned int eth_dev_counts = rte_eth_dev_count();
@@ -280,7 +104,7 @@ static int __device_scan(struct devman_ctx * ctx)
const char * __str_rssmode(unsigned int rssmode)
{
- switch(rssmode)
+ switch (rssmode)
{
case MR_DEV_RSSMODE_DEFAULT: return "Default";
case MR_DEV_RSSMODE_2TUPLE_SYM: return "SAddr/DAddr(Sym)";
@@ -305,7 +129,7 @@ static int device_info_dump(struct mr_dev * dev)
&dev->info.phy_ether_addr);
ether_format_addr(str_usr_addr, sizeof(str_phy_addr),
&dev->ether_addr);
-
+
MR_LOG(INFO, BASE,
"Physical Device %s: PortID=%d\n"
"=====================================================\n"
@@ -339,7 +163,7 @@ static int device_usrset_qconf(struct mr_dev * dev, struct rte_eth_rxconf * rxco
struct mr_dev_param * param = &dev->param;
struct rte_eth_dev_info rte_dev_info;
rte_eth_dev_info_get(dev->port_id, &rte_dev_info);
-
+
// 复制默认配置
*rxconf = rte_dev_info.default_rxconf;
*txconf = rte_dev_info.default_txconf;
@@ -348,6 +172,9 @@ static int device_usrset_qconf(struct mr_dev * dev, struct rte_eth_rxconf * rxco
rxconf->rx_drop_en = param->en_drop ? 1 : 0;
*nr_rxdesc = param->nr_rxdesc > 0 ? param->nr_rxdesc : MR_DEVICE_DEFAULT_NR_RX_DESC;
*nr_txdesc = param->nr_txdesc > 0 ? param->nr_txdesc : MR_DEVICE_DEFAULT_NR_TX_DESC;
+
+ // 清空txconf中的标志位
+ txconf->txq_flags = 0;
return 0;
}
@@ -398,7 +225,7 @@ static int device_usrset_misc(struct mr_dev * dev)
}
rte_eth_dev_get_mtu(dev->port_id, &dev->mtu);
-
+
// 配置以太网地址
if (!is_zero_ether_addr(&param->usr_ether_addr))
{
@@ -413,98 +240,145 @@ static int device_usrset_misc(struct mr_dev * dev)
return 0;
}
-static int __device_init(struct devman_ctx * ctx)
+static int device_usrset_queue(struct mr_dev * dev, unsigned int * out_rxq,
+ unsigned int * out_txq)
+{
+ struct mr_dev_param * param = &dev->param;
+ unsigned int rxq_use = 0;
+ unsigned int txq_use = 0;
+
+ rte_spinlock_init(&dev->qlock);
+
+ // 计算各队列描述符对应的物理队列序号
+ for(int i = 0; i < param->nr_rss_rxq; i++)
+ {
+ dev->devq[DEVQ_TYPE_RSS_RX][i].port_id = dev->port_id;
+ dev->devq[DEVQ_TYPE_RSS_RX][i].queue_id = rxq_use++;
+ }
+
+ dev->nr_devq[DEVQ_TYPE_RSS_RX] = rxq_use;
+
+ for(int i = 0; i < param->nr_rss_txq; i++)
+ {
+ dev->devq[DEVQ_TYPE_RSS_TX][i].port_id = dev->port_id;
+ dev->devq[DEVQ_TYPE_RSS_TX][i].queue_id = txq_use++;
+ }
+
+ dev->nr_devq[DEVQ_TYPE_RSS_TX] = txq_use;
+
+ // 后面可以继续添加别的类型的队列,物理队列序号顺序排布
+ // 至少要有一个收、发队列,否则无法通过初始化
+ *out_rxq = rxq_use > 0 ? rxq_use : 1;
+ *out_txq = txq_use > 0 ? txq_use : 1;
+ return 0;
+}
+
+static int device_init(struct mr_core_instance* instance,
+ struct devman_ctx * ctx, struct mr_dev * dev)
{
- // 对设备链上的所有设备初始化,计算队列数量。
- struct mr_dev * dev;
- TAILQ_FOREACH(dev, &ctx->device_list, next)
+ int retval = 0;
+ socket_id_t socket_id = rte_eth_dev_socket_id(dev->port_id);
+
+ struct rte_mempool * direct_pool = NULL;
+ struct rte_mempool * indirect_pool = NULL;
+
+ int pool_id = mr_buffer_pool_produce(instance, SOCKET_ID_ANY, dev->param.sz_pktmbuf,
+ dev->param.nr_direct_pktmbuf, dev->param.nr_pktmbuf_cache);
+ if(pool_id < 0)
{
- if (dev->enable == 0)
- {
- MR_LOG(INFO, BASE, "DeviceManager, DeviceInit, "
- "Device %s is disable, skip\n", dev->symbol);
- continue;
- }
+ MR_LOG(ERR, BASE, "DeviceInit : Cannot create pktmbuf pool(device=%s, "
+ "n=%d, cache=%d, size=%d): %s\n", dev->symbol, dev->param.nr_direct_pktmbuf,
+ dev->param.nr_pktmbuf_cache, dev->param.sz_pktmbuf, __str_errno());
+ return -1;
+ }
+
+ direct_pool = instance->mrb_pool_handle->mr_pkt_pool[pool_id];
+ indirect_pool = instance->mrb_pool_handle->mr_indirect_pool[pool_id];
+
+ assert(direct_pool != NULL && indirect_pool != NULL);
+ MR_LOG(INFO, BASE, "device %s pktmbuf pool(nr=%d, cache=%d, dataroom=%d) created. \n",
+ dev->symbol, dev->param.nr_direct_pktmbuf, dev->param.nr_pktmbuf_cache, dev->param.sz_pktmbuf);
+
+ dev->direct_pool = direct_pool;
+ dev->indirect_pool = indirect_pool;
+
+ // 配置端口信息
+ struct rte_eth_conf local_eth_conf;
+ device_usrset_ethconf(dev, &local_eth_conf);
- int retval = 0;
- unsigned int nr_rxq_use = dev->nr_rxq > 1 ? dev->nr_rxq : 1;
- unsigned int nr_txq_use = dev->nr_txq > 1 ? dev->nr_rxq : 1;
- socket_id_t socket_id = rte_eth_dev_socket_id(dev->port_id);
+ unsigned nr_rxq_use = 0;
+ unsigned nr_txq_use = 0;
- // 配置端口信息
- struct rte_eth_conf local_eth_conf;
- device_usrset_ethconf(dev, &local_eth_conf);
-
- retval = rte_eth_dev_configure(dev->port_id, nr_rxq_use,
- nr_txq_use, &eth_conf_default);
+ // 计算队列数
+ device_usrset_queue(dev, &nr_rxq_use, &nr_txq_use);
+
+ retval = rte_eth_dev_configure(dev->port_id, nr_rxq_use,
+ nr_txq_use, &local_eth_conf);
+
+ if (retval != 0)
+ {
+ MR_LOG(ERR, BASE, "DeviceInit : Device %s Configure Error, Errno = %d\n",
+ dev->symbol, retval);
+ return retval;
+ }
+
+ // 配置队列信息
+ unsigned int nr_rxdesc;
+ unsigned int nr_txdesc;
+ struct rte_eth_rxconf rxconf;
+ struct rte_eth_txconf txconf;
+ device_usrset_qconf(dev, &rxconf, &txconf, &nr_rxdesc, &nr_txdesc);
+
+ for (int rxq = 0; rxq < nr_rxq_use; rxq++)
+ {
+ retval = rte_eth_rx_queue_setup(dev->port_id, rxq,
+ nr_rxdesc, socket_id, &rxconf, direct_pool);
- if (retval != 0)
+ if (retval < 0)
{
MR_LOG(ERR, BASE, "DeviceManager, DeviceInit, "
- "Device %s Configure Error, Errno = %d\n",
- dev->symbol, retval);
+ "Device %s RXQ %d Setup Error, Errno = %d\n",
+ dev->symbol, rxq, retval);
return retval;
}
+ }
- // 配置队列信息
- unsigned int nr_rxdesc;
- unsigned int nr_txdesc;
- struct rte_eth_rxconf rxconf;
- struct rte_eth_txconf txconf;
- device_usrset_qconf(dev, &rxconf, &txconf, &nr_rxdesc, &nr_txdesc);
-
- for (int rxq = 0; rxq < nr_rxq_use; rxq++)
- {
- retval = rte_eth_rx_queue_setup(dev->port_id, rxq,
- nr_rxdesc, socket_id, &rxconf, mrbuf_get_mempool(socket_id));
-
- if (retval < 0)
- {
- MR_LOG(ERR, BASE, "DeviceManager, DeviceInit, "
- "Device %s RXQ %d Setup Error, Errno = %d\n",
- dev->symbol, rxq, retval);
- return retval;
- }
- }
-
- for (int txq = 0; txq < nr_txq_use; txq++)
- {
- retval = rte_eth_tx_queue_setup(dev->port_id, txq,
- nr_txdesc,socket_id, &txconf);
-
- if (retval < 0)
- {
- MR_LOG(ERR, BASE, "DeviceManager, DeviceInit, "
- "Device %s TXQ %d Setup Error, Errno = %d\n",
- dev->symbol, txq, retval);
- return retval;
- }
- }
+ for (int txq = 0; txq < nr_txq_use; txq++)
+ {
+ retval = rte_eth_tx_queue_setup(dev->port_id, txq,
+ nr_txdesc, socket_id, &txconf);
- retval = rte_eth_dev_start(dev->port_id);
if (retval < 0)
{
MR_LOG(ERR, BASE, "DeviceManager, DeviceInit, "
- "Device %s Start Error, Errno = %d(%s)\n",
- dev->symbol, retval, strerror(-retval));
+ "Device %s TXQ %d Setup Error, Errno = %d\n",
+ dev->symbol, txq, retval);
return retval;
}
+ }
- dev->nr_rxq = nr_rxq_use;
- dev->nr_txq = nr_txq_use;
-
- // 其他项目配置
- device_usrset_misc(dev);
- device_info_dump(dev);
- dev->inited = 1;
- dev->enable = 1;
+ retval = rte_eth_dev_start(dev->port_id);
+ if (retval < 0)
+ {
+ MR_LOG(ERR, BASE, "DeviceManager, DeviceInit, "
+ "Device %s Start Error, Errno = %d(%s)\n",
+ dev->symbol, retval, strerror(-retval));
+ return retval;
}
+ dev->nr_rxq = nr_rxq_use;
+ dev->nr_txq = nr_txq_use;
+
+ // 其他项目配置
+ device_usrset_misc(dev);
+ device_info_dump(dev);
+ dev->inited = 1;
+ dev->enable = 1;
return 0;
}
-static int __device_list(struct devman_ctx * ctx, mr_dev_t * devs[],
+static int __device_list(struct devman_ctx * ctx, struct mr_dev * devs[],
int nr_max_devs, flags_t flags)
{
struct mr_dev * dev_iter;
@@ -519,75 +393,107 @@ static int __device_list(struct devman_ctx * ctx, mr_dev_t * devs[],
return nr_in_use;
}
-mr_dev_t * mr_device_open(struct mr_dev_param * param)
-{
- struct devman_ctx * module_ctx;
- module_ctx = mr_core_default_instance_get()->devman_ctx;
- return (mr_dev_t *)__device_open(module_ctx, param);
-}
-
-mr_dev_t * mr_device_lookup(const char * devsym)
+static struct mr_dev * device_lookup(struct devman_ctx * ctx, const char * devsym)
{
- struct devman_ctx * module_ctx;
- module_ctx = mr_core_default_instance_get()->devman_ctx;
- return (mr_dev_t *)__device_lookup(module_ctx, devsym);
-}
+ struct mr_dev * dev_iter = NULL;
+ struct mr_dev * dev_ret = NULL;
+ TAILQ_FOREACH(dev_iter, &ctx->device_list, next)
+ {
+ if (strncmp(dev_iter->symbol, devsym, sizeof(dev_iter->symbol)) != 0)
+ continue;
-int mr_device_list(mr_dev_t * devs[], int nr_max_devs, flags_t flags)
-{
- struct devman_ctx * module_ctx;
- module_ctx = mr_core_default_instance_get()->devman_ctx;
- return __device_list(module_ctx, devs, nr_max_devs, flags);
+ dev_ret = dev_iter;
+ break;
+ }
+ return dev_ret;
}
-mr_devq_t * mr_device_attach(const char * devsym)
+static struct mr_dev * device_open(struct mr_core_instance* instance,
+ struct devman_ctx * ctx, struct mr_dev_param * param)
{
- struct devman_ctx * module_ctx;
- module_ctx = mr_core_default_instance_get()->devman_ctx;
+ struct mr_dev * dev = device_lookup(ctx, param->symbol);
- struct mr_dev * dev = __device_lookup(module_ctx, devsym);
if (dev == NULL)
{
- MR_LOG(INFO, BASE, "DeviceManager, DeviceAttach, "
- "Cannot found device %s\n", devsym);
+ MR_LOG(INFO, BASE, "DeviceOpen: Cannot found device %s\n", param->symbol);
+ return NULL;
+ }
+
+ dev->param = *param;
+ int ret = device_init(instance, ctx, dev);
+
+ if (ret < 0)
+ {
+ MR_LOG(INFO, BASE, "DeviceOpen: Cannot open device %s\n", param->symbol);
return NULL;
}
- return (mr_devq_t*)__device_attach(module_ctx, dev);
+ return dev;
}
-int mr_device_close(mr_devq_t * devq)
+struct mr_dev * mr_device_open(struct mr_core_instance* instance, struct mr_dev_param * param)
{
- return 0;
+ return device_open(instance, instance->devman_ctx, param);
}
-int devman_ctx_init(struct mr_core_instance * core_instance)
+struct mr_dev * mr_device_lookup(struct mr_core_instance* instance, const char * devsym)
{
- core_instance->devman_ctx = rte_zmalloc("DEVMAN_CTX", sizeof(struct devman_ctx), 0);
- MR_CHECK(core_instance->devman_ctx != NULL, "Cannot alloc memory for devman context");
+ return device_lookup(instance->devman_ctx, devsym);
+}
- TAILQ_INIT(&core_instance->devman_ctx->device_list);
- return __device_scan(core_instance->devman_ctx);
+int mr_device_list(struct mr_core_instance* instance, struct mr_dev * devs[], int nr_max_devs, flags_t flags)
+{
+ return __device_list(instance->devman_ctx, devs, nr_max_devs, flags);
}
-int devman_config(struct mr_core_instance * core_instance)
+struct mr_dev_q * mr_device_attach(struct mr_dev * dev, enum dev_q_type q_type)
{
- return 0;
+ rte_spinlock_lock(&dev->qlock);
+ struct mr_dev_q * dev_q = NULL;
+
+ for(int i = 0; i < dev->nr_devq[q_type]; i++)
+ {
+ dev_q = &dev->devq[q_type][i];
+ if (dev_q->in_use) continue;
+ dev_q->in_use = 1;
+ break;
+ }
+
+ if (dev_q == NULL)
+ {
+ MR_LOG(ERR, BASE, "Device %s out of free queues(type = %s, total = %d), attach failed.\n",
+ dev->symbol, __str_dev_q_type(q_type), dev->nr_devq[q_type]);
+ }
+
+ rte_spinlock_unlock(&dev->qlock);
+ return dev_q;
}
-int devman_init(struct mr_core_instance * core_instance)
+void mr_device_deattach(struct mr_dev_q * dev_q)
{
- struct devman_ctx * ctx = core_instance->devman_ctx;
- return __device_init(ctx);
+ dev_q->in_use = 0;
}
-int devman_destory(struct mr_core_instance * core_instance)
+struct rte_mempool * mr_device_direct_pool_get(struct mr_dev * dev)
{
- return 0;
+ return dev->direct_pool;
}
-int devman_slave_init(struct mr_core_instance * core_instance,
- struct mr_core_slave_instance * slave_instance)
+struct rte_mempool * mr_device_indirect_pool_get(struct mr_dev * dev)
+{
+ return dev->indirect_pool;
+}
+
+int mr_device_close(struct mr_dev_q * devq)
{
return 0;
+}
+
+int devman_init(struct mr_core_instance * core_instance)
+{
+ core_instance->devman_ctx = rte_zmalloc("DEVMAN_CTX", sizeof(struct devman_ctx), 0);
+ MR_CHECK(core_instance->devman_ctx != NULL, "Cannot alloc memory for devman context");
+
+ TAILQ_INIT(&core_instance->devman_ctx->device_list);
+ return device_scan(core_instance->devman_ctx);
} \ No newline at end of file
diff --git a/core/src/mrbuf.c b/core/src/mrbuf.c
deleted file mode 100644
index 5acfe60..0000000
--- a/core/src/mrbuf.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- NOTE:
-
- mr_ctx.h, 将全局变量存入global_ctx中, 做了内存映射, 保证全部应用可见.
-
- alloc时, 为了保证尽量不跨NUMA, 判断一下当前应用绑定的CPU处于哪个socket,
- 在对应的socket中的mempool获取mbuf内存.
-
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <assert.h>
-#include <MESA_prof_load.h>
-
-#include <mr_mrbuf.h>
-#include <mr_buffer.h>
-#include <mr_runtime.h>
-#include <mr_core.h>
-
-#include <rte_malloc.h>
-#include <rte_mbuf.h>
-
-#ifndef MR_MRBUF_DEFAULT_BLOCK_NUM
-#define MR_MRBUF_DEFAULT_BLOCK_NUM 8192
-#endif
-
-#ifndef MR_MRBUF_DEFAULT_DATAROOM_SIZE
-#define MR_MRBUF_DEFAULT_DATAROOM_SIZE 2048
-#endif
-
-#ifndef MR_MRBUF_DEFAULT_PRIV_SIZE
-#define MR_MRBUF_DEFAULT_PRIV_SIZE 128
-#endif
-
-static int __mr_ctrl_zone_index = 0; /* 纪录私有数据结构CTRLZONE的序号 */
-
-int marsio_buf_ctrlzone_alloc_id(void)
-{
- assert(0);
- return 0;
-}
-
-void marsio_buf_set_ctrlzone(marsio_buf_t *m, int ctrlzone_id, void *ctrl_ptr)
-{
- assert(0);
- struct marsio_pri_t *mpr;
-
- assert((ctrlzone_id >= 0) && (ctrlzone_id < MAX_CZ_NUM));
-
- mpr = (struct marsio_pri_t *)((char *)m + sizeof(struct rte_mbuf));
-
- mpr->ctrlzone[ctrlzone_id] = ctrl_ptr;
-}
-
-void *marsio_buf_get_ctrlzone(marsio_buf_t *m, int ctrlzone_id)
-{
- assert(0);
- struct marsio_pri_t *mpr;
-
- assert((ctrlzone_id >= 0) && (ctrlzone_id < MAX_CZ_NUM));
-
- mpr = (struct marsio_pri_t *)((char *)m + sizeof(struct rte_mbuf));
-
- return mpr->ctrlzone[ctrlzone_id];
-}
-
-/* 将next作为previous的下一个包, 注意不是append下一个数据段 */
-void marsio_buf_append_pkt(marsio_buf_t *previous, marsio_buf_t *next)
-{
- assert(0);
- struct marsio_pri_t *mpr_previous;
-
- mpr_previous = (struct marsio_pri_t *)((char *)previous + sizeof(struct rte_mbuf));
-
- mpr_previous->pkt_next = (struct rte_mbuf *)next;
-}
-
-marsio_buf_t *marsio_buf_get_nextpkt(marsio_buf_t *m)
-{
- assert(0);
- struct marsio_pri_t *mpr;
-
- mpr = (struct marsio_pri_t *)((char *)m + sizeof(struct rte_mbuf));
-
- return (marsio_buf_t *)(mpr->pkt_next);
-}
-
-void marsio_buf_reset(marsio_buf_t *m)
-{
- assert(0);
- struct rte_mbuf *rtem = (struct rte_mbuf *)m;
- struct marsio_pri_t *mpr;
-
- rte_pktmbuf_reset(rtem);
-
- mpr = (struct marsio_pri_t *)((char *)m + sizeof(struct rte_mbuf));
- memset(mpr, 0, sizeof(struct marsio_pri_t));
-
- /* 私有数据长度 + 头部空间预留长度 <= 数据起始地址 - 缓冲区起始地址 */
- assert((int)(sizeof(struct marsio_pri_t) + RTE_PKTMBUF_HEADROOM)
- <= (int)((char *)rtem->buf_addr - (char *)rtem));
-}
-
-struct rte_mempool * mrbuf_get_mempool(socket_id_t socket_id)
-{
- struct mrbuf_ctx * module_ctx;
- module_ctx = mr_core_default_instance_get()->mrbuf_ctx;
-
- assert(socket_id < module_ctx->mr_buf_pool_num);
- if (MR_SOCKET_ANY == socket_id) socket_id = 0;
- return module_ctx->mr_buf_pool[socket_id];
-}
-
-marsio_buf_t *marsio_buf_alloc(void)
-{
- assert(0);
- return NULL;
-}
-
-void marsio_buf_free(marsio_buf_t *m)
-{
- assert(0);
- rte_pktmbuf_free((struct rte_mbuf *)m);
-}
-
-int marsio_buf_batch_alloc(marsio_buf_t *m[], int num)
-{
- return 0;
-}
-
-void marsio_buf_batch_free(marsio_buf_t *m[], int num)
-{
-}
-
-char *marsio_buf_mtod(marsio_buf_t *m)
-{
- return rte_pktmbuf_mtod((struct rte_mbuf *)m, char *);
-}
-
-uint32_t marsio_buf_pkt_len(marsio_buf_t *m)
-{
- return rte_pktmbuf_pkt_len((struct rte_mbuf *)m);
-}
-
-char *marsio_buf_prepend(marsio_buf_t *m, uint16_t len)
-{
- return rte_pktmbuf_prepend((struct rte_mbuf *)m, len);
-}
-
-char *marsio_buf_append(marsio_buf_t *m, uint16_t len)
-{
- return rte_pktmbuf_append((struct rte_mbuf *)m, len);
-}
-
-char *marsio_buf_adj(marsio_buf_t *m, uint16_t len)
-{
- return rte_pktmbuf_adj((struct rte_mbuf *)m, len);
-}
-
-int marsio_buf_trim(marsio_buf_t *m, uint16_t len)
-{
- return rte_pktmbuf_trim((struct rte_mbuf *)m, len);
-}
-
-uint16_t marsio_buf_headroom(const marsio_buf_t *m)
-{
- return rte_pktmbuf_headroom((const struct rte_mbuf *)m);
-}
-
-uint16_t marsio_buf_tailroom(const marsio_buf_t *m)
-{
- return rte_pktmbuf_tailroom((const struct rte_mbuf *)m);
-}
-
-marsio_buf_t *marsio_buf_dup(marsio_buf_t *m)
-{
- mr_process_ctx_t *proc_ctx;
- rte_mbuf_refcnt_update((struct rte_mbuf *)m, 1);
- return m;
-}
-
-int mrbuf_ctx_init(struct mr_core_instance * core_instance)
-{
- core_instance->mrbuf_ctx = rte_zmalloc("MRBUF_CTX", sizeof(struct mrbuf_ctx), 0);
- MR_CHECK(core_instance->mrbuf_ctx != NULL, "Cannot alloc memory for mrbuf context. ");
- return 0;
-}
-
-int mrbuf_config(struct mr_core_instance * core_instance)
-{
- struct mr_global_config * g_cfg = core_instance->g_cfg;
- struct mrbuf_ctx * ctx = core_instance->mrbuf_ctx;
-
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "buffer", "block_num",
- &ctx->mempool_block_num, MR_MRBUF_DEFAULT_BLOCK_NUM);
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "buffer", "dataroom_size",
- &ctx->mempool_dataroom_size, MR_MRBUF_DEFAULT_DATAROOM_SIZE);
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "buffer", "priv_size",
- &ctx->mempool_priv_size, MR_MRBUF_DEFAULT_PRIV_SIZE);
-
- MR_LOG(INFO, BASE, "MRBUF Config, "
- "block_num = %d, dataroom_size = %d, priv_size = %d\n",
- ctx->mempool_block_num, ctx->mempool_dataroom_size, ctx->mempool_priv_size);
-
- return 0;
-}
-
-int mrbuf_init(struct mr_core_instance * core_instance)
-{
- struct mr_global_config * g_cfg = core_instance->g_cfg;
- struct mrbuf_ctx * ctx = core_instance->mrbuf_ctx;
-
- ctx->mr_buf_pool_num = mr_hwinfo_nr_sockets();
- MR_CHECK(ctx->mr_buf_pool_num > 0, "MRBUF, ModuleInit, "
- "Get socket number error(socket_nr = %d)", ctx->mr_buf_pool_num);
-
- ctx->mr_buf_pool = (struct rte_mempool **)
- rte_zmalloc("MRBUF_MANAGER_CTX", sizeof(void *) *ctx->mr_buf_pool_num, 0);
-
- for (int socket_id = 0; socket_id < ctx->mr_buf_pool_num; socket_id++)
- {
- char sym[MR_SYMBOL_MAX];
- snprintf(sym, sizeof(sym), "mbuf_pool_%d", socket_id);
-
- ctx->mr_buf_pool[socket_id] = rte_pktmbuf_pool_create(sym,
- ctx->mempool_block_num, 256, ctx->mempool_priv_size,
- ctx->mempool_dataroom_size, socket_id);
-
- MR_CHECK(ctx->mr_buf_pool[socket_id] != NULL, "MRBUF, ModuleInit, "
- "Call rte_pktmbuf_pool_create() failed");
-
- MR_LOG(INFO, BASE, "MRBUF, ModuleInit, "
- "Pktmbuf Pool %s(block_num=%d, priv_size=%d, dataroom_size=%d) created.\n",
- sym, ctx->mempool_block_num, ctx->mempool_priv_size, ctx->mempool_dataroom_size);
-
- struct rte_mbuf *test_mbuf = rte_pktmbuf_alloc(ctx->mr_buf_pool[socket_id]);
- assert(test_mbuf != NULL);
- rte_pktmbuf_free(test_mbuf);
- }
-
- rte_atomic32_set(&ctx->mr_ctrl_zone_id, 0);
- return 0;
-}
-
-int mrbuf_destory(struct mr_core_instance * core_instance)
-{
- return 0;
-}
-
-int mrbuf_slave_init(struct mr_core_instance * core_instance,
- struct mr_core_slave_instance * slave_instance)
-{
- return 0;
-} \ No newline at end of file
diff --git a/core/src/rtdev.c b/core/src/rtdev.c
index bed0c37..be008e6 100644
--- a/core/src/rtdev.c
+++ b/core/src/rtdev.c
@@ -7,9 +7,10 @@
#include <rte_malloc.h>
#include <mr_device.h>
-#include <mr_vman.h>
#include <mr_common.h>
#include <mr_rtdev.h>
+#include <mr_core.h>
+#include <mr_vnode.h>
#define __PATTERN_DEV_RX "%s-RX"
#define __PATTERN_DEV_TX "%s-TX"
@@ -19,457 +20,248 @@
#define __PATTERN_PROD_APP "%s"
#define __PATTERN_CONS_APP "%s"
-static int __unregister_app_for_rxvnode(const char * devsym, const char * appsym)
+static void __wrap_object_delete(void * object)
{
- char vnodesym[MR_SYMBOL_MAX];
- char conssym[MR_SYMBOL_MAX];
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_RX, devsym);
- snprintf(conssym, sizeof(conssym), __PATTERN_CONS_APP, appsym);
-
- int ret = mr_vnodeman_unregister_consumer(vnodesym, conssym);
- if (ret < 0)
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceClose, "
- "Cannot unregister consumer %s for vnode %s. \n",
- conssym, vnodesym);
- return ret;
- }
-
- return 0;
+ return rte_pktmbuf_free(object);
}
-static int __unregister_app_for_txvnode(const char * devsym, const char * appsym)
+static void * __wrap_object_new(void * pool)
{
- char vnodesym[MR_SYMBOL_MAX];
- char prodsym[MR_SYMBOL_MAX];
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_TX, devsym);
- snprintf(prodsym, sizeof(prodsym), __PATTERN_PROD_APP, appsym);
-
- int ret = mr_vnodeman_unregister_producer(vnodesym, prodsym);
- if (ret < 0)
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceClose, "
- "Cannot unregister consumer %s for vnode %s. \n",
- prodsym, vnodesym);
- return ret;
- }
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_FTX, devsym);
- snprintf(prodsym, sizeof(prodsym), __PATTERN_PROD_APP, appsym);
-
- ret = mr_vnodeman_unregister_producer(vnodesym, prodsym);
- if (ret < 0)
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceClose, "
- "Cannot unregister consumer %s for vnode %s. \n",
- prodsym, vnodesym);
- return ret;
- }
-
- return 0;
+ return rte_pktmbuf_alloc(pool);
}
-static int __register_app_for_rxvnode(const char * devsym, const char * appsym,
- unsigned int nr_queues)
+static void * __wrap_object_dup(void * object, void * pool)
{
- char vnodesym[MR_SYMBOL_MAX];
- char conssym[MR_SYMBOL_MAX];
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_RX, devsym);
- snprintf(conssym, sizeof(conssym), __PATTERN_CONS_APP, appsym);
-
- int ret = mr_vnodeman_register_consumer(vnodesym, conssym, nr_queues);
- if (ret < 0)
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot register consumer %s(nr_queues=%d) for vnode %s. \n",
- conssym, nr_queues, vnodesym);
- return ret;
- }
-
- return 0;
+ return rte_pktmbuf_clone(object, pool);
}
-static int __register_app_for_txvnode(const char * devsym, const char * appsym,
- unsigned int nr_queues)
+struct vnode_ops _rtdev_vnode_ops =
{
- char vnodesym[MR_SYMBOL_MAX];
- char prodsym[MR_SYMBOL_MAX];
+ .op_object_new = __wrap_object_new,
+ .op_object_dup = __wrap_object_dup,
+ .op_object_delete = __wrap_object_delete
+};
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_TX, devsym);
- snprintf(prodsym, sizeof(prodsym), __PATTERN_PROD_APP, appsym);
-
- int ret = mr_vnodeman_register_producer(vnodesym, prodsym, nr_queues);
- if (ret < 0)
+static struct rtdev_desc * __rtdev_lookup_unsafe(struct mr_core_instance * instance, const char * devsym)
+{
+ struct rtdev_desc * desc_iter;
+ TAILQ_FOREACH(desc_iter, instance->rtdev_list, next)
{
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot register consumer %s(nr_queues=%d) for vnode %s. \n",
- prodsym, nr_queues, vnodesym);
- return ret;
+ if (strcmp(desc_iter->symbol, devsym) != 0) continue;
+ return desc_iter;
}
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_FTX, devsym);
- snprintf(prodsym, sizeof(prodsym), __PATTERN_PROD_APP, appsym);
+ return NULL;
+}
- ret = mr_vnodeman_register_producer(vnodesym, prodsym, nr_queues);
- if (ret < 0)
+static struct rtdev_app_desc * __rtdev_app_lookup_unsafe(struct rtdev_desc * dev_desc, const char * appsym)
+{
+ struct rtdev_app_desc * app_desc_iter;
+ TAILQ_FOREACH(app_desc_iter, &dev_desc->app_desc_list, next)
{
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot register consumer %s(nr_queues=%d) for vnode %s. \n",
- prodsym, nr_queues, vnodesym);
- return ret;
+ if (strcmp(app_desc_iter->symbol, appsym) != 0) continue;
+ return app_desc_iter;
}
- return 0;
+ return NULL;
}
-static int __register_service_for_rxvnode(const char * devsym, const char * servsym,
- unsigned int nr_queues)
+struct rtdev_desc * mr_rtdev_lookup(struct mr_core_instance * instance, const char * devsym)
{
- char vnodesym[MR_STRING_MAX];
- char prodsym[MR_STRING_MAX];
-
- // ����VNode������
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_RX, devsym);
- snprintf(prodsym, sizeof(prodsym), __PATTERN_PROD_SERVICE, servsym);
-
- // ע�������ߣ������ߵĶ��������������߳���һ��
- int ret = mr_vnodeman_register_producer(vnodesym, prodsym, nr_queues);
-
- if (ret < 0)
- {
- MR_LOG(WARNING, SERVICE, "Rtdevice, RtdeviceCreate, "
- "Cannot register producer %s(nr_queues=%d) for vnode %s. \n",
- prodsym, nr_queues, vnodesym);
- return ret;
- }
-
- return 0;
+ return __rtdev_lookup_unsafe(instance, devsym);
}
-static int __register_service_for_txvnode(const char * devsym, const char * servsym,
- unsigned int nr_queues)
+struct rtdev_app_desc * mr_rtdev_app_lookup(struct rtdev_desc * dev_desc, const char * appsym)
{
- char vnodesym[MR_SYMBOL_MAX];
- char conssym[MR_SYMBOL_MAX];
-
- // ����VNode�����֣���ͨ����·��
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_TX, devsym);
- snprintf(conssym, sizeof(conssym), __PATTERN_CONS_SERVICE, servsym);
-
- // ע��������
- int ret = mr_vnodeman_register_consumer(vnodesym, conssym, nr_queues);
+ return __rtdev_app_lookup_unsafe(dev_desc, appsym);
+}
- if (ret < 0)
+int mr_rtdev_stats_get(struct rtdev_desc * dev_desc, struct rtdev_stat_info * stat_info)
+{
+ struct vnode_prod_stat * st_prod_rx = vnode_prod_stat_get(dev_desc->vnode_prod_rx);
+ struct vnode_cons_stat * st_cons_tx = vnode_cons_stat_get(dev_desc->vnode_cons_tx);
+ struct vnode_cons_stat * st_cons_ftx = vnode_cons_stat_get(dev_desc->vnode_cons_ftx);
+
+ for(int i = 0; i < dev_desc->nr_serv_stream; i++)
{
- MR_LOG(WARNING, SERVICE, "Rtdevice, RtdeviceCreate, "
- "Cannot register consumer %s(nr_queues=%d) for vnode %s. \n",
- conssym, nr_queues, vnodesym);
- return ret;
- }
+ stat_info->rx_on_line[i] = rte_atomic64_read(&st_prod_rx[i].on_line);
+ stat_info->rx_deliver[i] = rte_atomic64_read(&st_prod_rx[i].sent);
+ stat_info->rx_missed[i] = rte_atomic64_read(&st_prod_rx[i].missed);
- // ����VNode�����֣����ٷ���·��
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_FTX, devsym);
- snprintf(conssym, sizeof(conssym), __PATTERN_CONS_SERVICE, servsym);
+ stat_info->tx_on_line[i] = rte_atomic64_read(&st_cons_tx[i].on_line);
+ stat_info->tx_deliver[i] = rte_atomic64_read(&st_cons_tx[i].recieved);
+ stat_info->tx_missed[i] = rte_atomic64_read(&st_cons_tx[i].missed);
- // ע��������
- ret = mr_vnodeman_register_consumer(vnodesym, conssym, nr_queues);
-
- if (ret < 0)
- {
- MR_LOG(WARNING, SERVICE, "Rtdevice, RtdeviceCreate, "
- "Cannot register consumer %s(nr_queues=%d) for vnode %s. \n",
- conssym, nr_queues, vnodesym);
- return ret;
+ stat_info->ftx_on_line[i] = rte_atomic64_read(&st_cons_ftx[i].on_line);
+ stat_info->ftx_deliver[i] = rte_atomic64_read(&st_cons_ftx[i].recieved);
+ stat_info->ftx_missed[i] = rte_atomic64_read(&st_cons_ftx[i].missed);
}
-
+
return 0;
}
-// ΪRtdevice����VNode�ڵ�
-static int __create_device_vnode(const char * symbol, unsigned int sz_tunnel, unsigned int sz_buffer)
+ // ����һ������ʱ�����豸
+struct rtdev_desc * mr_rtdev_create(struct mr_core_instance * instance, const char * devsym,
+ struct rte_mempool * pool, unsigned int nr_serv_thread, unsigned int sz_tunnel, unsigned int sz_buffer)
{
- char vnodesym[MR_SYMBOL_MAX];
- int ret = 0;
-
- // Ϊ�ձ�·��ע���µ�VNode�ڵ�
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_RX, symbol);
- ret = mr_vnodeman_create(vnodesym, sz_tunnel, sz_buffer, 0);
-
- if (ret < 0)
+ // �б���û�г�ʼ������������ʱ�б���ʼ��
+ if(instance->rtdev_list == NULL)
{
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceCreate, "
- "Cannot create vnode %s(sz_tunnel=%d, sz_buffer=%d) for rt-device %s\n",
- vnodesym, sz_tunnel, sz_buffer, symbol);
- return ret;
+ instance->rtdev_list = rte_zmalloc(NULL, sizeof(struct rtdev_desc_list), 0);
+ TAILQ_INIT(instance->rtdev_list);
}
- // Ϊ����·��ע���µ�VNode�ڵ�
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_TX, symbol);
- ret = mr_vnodeman_create(vnodesym, sz_tunnel, sz_buffer, 0);
+ // �����������ڴ�
+ struct rtdev_desc * desc = rte_zmalloc(NULL, sizeof(struct rtdev_desc), 0);
+ MR_CHECK(desc != NULL, "Cannot alloc memory for rtdev-desc %s", devsym);
- if (ret < 0)
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceCreate, "
- "Cannot create vnode %s(sz_tunnel=%d, sz_buffer=%d) for rt-device %s\n",
- vnodesym, sz_tunnel, sz_buffer, symbol);
- return ret;
- }
+ snprintf(desc->symbol, sizeof(desc->symbol), "%s", devsym);
+ desc->nr_serv_stream = nr_serv_thread;
- // Ϊ���ٱ��ķ���·��ע���µ�VNode�ڵ�
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_FTX, symbol);
- ret = mr_vnodeman_create(vnodesym, sz_tunnel, sz_buffer, 0);
+ desc->ops = _rtdev_vnode_ops;
+ desc->ops.pool_dup_object = pool;
+ desc->ops.pool_new_object = pool;
+ TAILQ_INIT(&desc->app_desc_list);
+ rte_rwlock_init(&desc->app_desc_lock);
+
+ // ����VNode
+ char vnodesym[MR_SYMBOL_MAX];
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_RX, desc->symbol);
- if(ret < 0)
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceCreate, "
- "Cannot create vnode %s(sz_tunnel=%d, sz_buffer=%d) for rt-device %s\n",
- vnodesym, sz_tunnel, sz_buffer, symbol);
- return ret;
- }
+ desc->vnode_rx = vnode_create(vnodesym, &desc->ops, sz_tunnel, sz_buffer);
+ if (desc->vnode_rx == NULL) goto vnode_create_failed;
+
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_TX, desc->symbol);
+ desc->vnode_tx = vnode_create(vnodesym, &desc->ops, sz_tunnel, sz_buffer);
+ if (desc->vnode_tx == NULL) goto vnode_create_failed;
- MR_LOG(DEBUG, BASE, "Rtdevice, RtdeviceCreate, "
- "Create vnodes for rt-device %s successful. \n", symbol);
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_FTX, desc->symbol);
+ desc->vnode_ftx = vnode_create(vnodesym, &desc->ops, sz_tunnel, 0);
+ if (desc->vnode_ftx == NULL) goto vnode_create_failed;
- return 0;
-}
+ // ע��������
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_PROD_SERVICE, "service");
+ desc->vnode_prod_rx = vnode_create_prod(desc->vnode_rx, &desc->ops, vnodesym, nr_serv_thread);
+ if (desc->vnode_prod_rx == NULL) goto prod_cons_create_failed;
-// ����һ������ʱ�����豸
-int rt_device_serv_create(const char * devsym,
- const char * servsym, unsigned int nr_serv_thread,
- unsigned int sz_tunnel, unsigned int sz_buffer)
-{
- // ����VNode�ڵ�
- int ret = __create_device_vnode(devsym, sz_tunnel, sz_buffer);
- if(unlikely(ret < 0))
- {
- MR_LOG(ERR, BASE, "Rtdevice, RtdeviceCreate, "
- "Cannot create vnodes for rt-device %s\n", devsym);
- return ret;
- }
+ // ע��������
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_CONS_SERVICE, "service");
+ desc->vnode_cons_tx = vnode_create_cons(desc->vnode_tx, &desc->ops, vnodesym, nr_serv_thread);
+ if (desc->vnode_cons_tx == NULL) goto prod_cons_create_failed;
- // ע��Service���ձ���������
- ret = __register_service_for_rxvnode(devsym, servsym, nr_serv_thread);
- if(unlikely(ret < 0))
- {
- MR_LOG(ERR, BASE, "Rtdevice, RtdeviceCreate, "
- "Cannot register rxvnodes for rt-device %s\n", devsym);
- return ret;
- }
+ // ע��������
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_CONS_SERVICE, "service");
+ desc->vnode_cons_ftx = vnode_create_cons(desc->vnode_ftx, &desc->ops, vnodesym, nr_serv_thread);
+ if (desc->vnode_cons_ftx == NULL) goto prod_cons_create_failed;
- // ע��Service�ķ�����������
- ret = __register_service_for_txvnode(devsym, servsym, nr_serv_thread);
- if(unlikely(ret < 0))
- {
- MR_LOG(ERR, BASE, "Rtdevice, RtdeviceCreate, "
- "Cannot register txvnodes for rt-device %s\n", devsym);
- return ret;
- }
+ // ����ע���б�
+ TAILQ_INSERT_TAIL(instance->rtdev_list, desc, next);
+ instance->nr_rtdev++;
- return 0;
+ MR_LOG(INFO, BASE, "RT-device %s(nr_serv_thread=%u, sz_tunnel=%u, sz_buffer=%u) created. \n",
+ desc->symbol, nr_serv_thread, sz_tunnel, sz_buffer);
+
+ return desc;
+
+prod_cons_create_failed:
+ MR_LOG(WARNING, BASE, "Creating prod/cons %s (nr_queues=%d) of rtdev %s failed. \n",
+ vnodesym, nr_serv_thread, desc->symbol);
+ goto clean;
+
+vnode_create_failed:
+ MR_LOG(WARNING, BASE, "Creating vnode %s(sz_tunnel=%d, sz_buffer=%d)"
+ "of rtdev %s failed. \n", vnodesym, sz_tunnel, sz_buffer, desc->symbol);
+ goto clean;
+
+clean:
+ if (desc->vnode_prod_rx != NULL) vnode_delete_prod(desc->vnode_prod_rx, &desc->ops);
+ if (desc->vnode_cons_tx != NULL) vnode_delete_cons(desc->vnode_cons_tx, &desc->ops);
+ if (desc->vnode_cons_ftx != NULL) vnode_delete_cons(desc->vnode_cons_ftx, &desc->ops);
+ if (desc->vnode_rx != NULL) vnode_delete(desc->vnode_rx, &desc->ops);
+ if (desc->vnode_tx != NULL) vnode_delete(desc->vnode_tx, &desc->ops);
+ if (desc->vnode_ftx != NULL) vnode_delete(desc->vnode_ftx, &desc->ops);
+ if (desc) rte_free(desc);
+ return NULL;
}
// ����һ������ʱ�����豸
-int rt_device_serv_destory(const char * devsym)
-{
- return 0;
-}
-
-// ���豸��ͨ����Slave������ʹ��
-int rt_device_open(const char * devsym, const char * appsym,
- unsigned int nr_rxstream, unsigned int nr_txstream)
+int mr_rt_device_destory(struct rtdev_desc * desc)
{
- // ע��App���ձ���������
- int ret = __register_app_for_rxvnode(devsym, appsym, nr_rxstream);
- if(unlikely(ret < 0))
- {
- MR_LOG(ERR, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot register rxvnodes for rt-device %s\n", devsym);
- return ret;
- }
-
- // ע��App�ķ�����������
- ret = __register_app_for_txvnode(devsym, appsym, nr_txstream);
- if(unlikely(ret < 0))
- {
- MR_LOG(ERR, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot register txvnodes for rt-device %s\n", devsym);
- return ret;
- }
-
- return 0;
-}
-
-int rt_device_close(const char * devsym, const char * appsym)
-{
- int ret = __unregister_app_for_rxvnode(devsym, appsym);
- if (unlikely(ret < 0))
- {
- MR_LOG(ERR, BASE, "Rtdevice, RtdeviceClose, "
- "Cannot unregister rxvnodes for rt-device %s\n", devsym);
- return ret;
- }
-
- ret = __unregister_app_for_txvnode(devsym, appsym);
- if (unlikely(ret < 0))
- {
- MR_LOG(ERR, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot register txvnodes for rt-device %s\n", devsym);
- return ret;
- }
-
return 0;
}
-struct mr_rtdev_stream * rt_dev_serv_open_stream(const char * devsym,
- const char * servsym)
+// ���豸
+struct rtdev_app_desc * mr_rt_device_open(struct mr_core_instance * instance,
+ const char * devsym, const char * appsym, unsigned int nr_rx_stream, unsigned int nr_tx_stream)
{
- char vnodesym[MR_STRING_MAX];
- char prod_or_cons_sym[MR_STRING_MAX];
-
- struct mr_rtdev_stream * rtdev_stream;
- rtdev_stream = rte_zmalloc(NULL, sizeof(struct mr_rtdev_stream), 0);
- if (unlikely(rtdev_stream == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceServOpen, "
- "Cannot alloc rtdev_stream for rtdevice %s", devsym);
- goto errout;
- }
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_RX, devsym);
- snprintf(prod_or_cons_sym, sizeof(prod_or_cons_sym), __PATTERN_PROD_SERVICE, servsym);
-
- struct vnodeman_attach_desc * attach_rxd;
- attach_rxd = mr_vnodeman_producer_attach(vnodesym, prod_or_cons_sym);
- if (unlikely(attach_rxd == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceServOpen, "
- "Cannot attach vnode(sym=%s) producer=(%s). \n",
- vnodesym, prod_or_cons_sym);
- goto errout;
- }
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_TX, devsym);
- snprintf(prod_or_cons_sym, sizeof(prod_or_cons_sym), __PATTERN_CONS_SERVICE, servsym);
-
- struct vnodeman_attach_desc * attach_txd;
- attach_txd = mr_vnodeman_consumer_attach(vnodesym, prod_or_cons_sym);
- if (unlikely(attach_txd == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceServOpen, "
- "Cannot attach vnode(sym=%s) consumer=(%s). \n",
- vnodesym, prod_or_cons_sym);
- goto errout;
- }
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_FTX, devsym);
- snprintf(prod_or_cons_sym, sizeof(prod_or_cons_sym), __PATTERN_CONS_SERVICE, servsym);
+ // ��������ʱ�豸
+ struct rtdev_desc * dev_desc = mr_rtdev_lookup(instance, devsym);
+ RETURN_IF_ERROR(WARNING, BASE , dev_desc == NULL, NULL, "Rtdevice %s does not existed. \n", devsym);
+
+ // �����������ڴ�
+ struct rtdev_app_desc * desc = rte_zmalloc(NULL, sizeof(struct rtdev_app_desc), 0);
+ RETURN_IF_ERROR(WARNING, BASE, desc == NULL, NULL, "Cannot alloc memory for rtdev-app-desc %s", devsym);
+
+ snprintf(desc->symbol, sizeof(desc->symbol), "%s", appsym);
+ desc->nr_rx_stream = nr_rx_stream;
+ desc->nr_tx_stream = nr_tx_stream;
+ desc->dev_desc = dev_desc;
+
+ // ���Ʋ�������ָ�룬��ͬ���̵ĺ�����ַ���ܲ�ͬ��������Դ��ַ��ͬ
+ desc->ops = _rtdev_vnode_ops;
+ desc->ops.pool_dup_object = dev_desc->ops.pool_dup_object;
+ desc->ops.pool_new_object = dev_desc->ops.pool_new_object;
+
+ // ΪRX����ע��������
+ char vnodesym[MR_SYMBOL_MAX];
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_CONS_APP, appsym);
+ desc->vnode_cons_rx = vnode_create_cons(dev_desc->vnode_rx, &desc->ops, vnodesym, nr_rx_stream);
+ if (desc->vnode_cons_rx == NULL) goto prod_cons_create_failed;
+
+ // ΪTXע��������
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_CONS_APP, appsym);
+ desc->vnode_prod_tx = vnode_create_prod(dev_desc->vnode_tx, &desc->ops, vnodesym, nr_tx_stream);
+ if (desc->vnode_prod_tx == NULL) goto prod_cons_create_failed;
+
+ // ΪFTXע��������
+ snprintf(vnodesym, sizeof(vnodesym), __PATTERN_CONS_APP, appsym);
+ desc->vnode_prod_ftx = vnode_create_prod(dev_desc->vnode_ftx, &desc->ops, vnodesym, nr_tx_stream);
+ if (desc->vnode_prod_ftx == NULL) goto prod_cons_create_failed;
+
+ // ����ע���б�
+ rte_rwlock_write_lock(&dev_desc->app_desc_lock);
+ TAILQ_INSERT_TAIL(&dev_desc->app_desc_list, desc, next);
+ rte_rwlock_write_unlock(&dev_desc->app_desc_lock);
+
+ MR_LOG(INFO, BASE, "RT-device %s(appsym=%s, nr_rx_stream=%d, nr_tx_stream=%d) opened. \n",
+ dev_desc->symbol, desc->symbol, nr_rx_stream, nr_tx_stream);
- struct vnodeman_attach_desc * attach_ftxd;
- attach_ftxd = mr_vnodeman_consumer_attach(vnodesym, prod_or_cons_sym);
- if (unlikely(attach_ftxd == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceServOpen, "
- "Cannot attach vnode(sym=%s) consumer=(%s). \n",
- vnodesym, prod_or_cons_sym);
- goto errout;
- }
+ return desc;
- rtdev_stream->rxd = attach_rxd;
- rtdev_stream->txd = attach_txd;
- rtdev_stream->fasttxd = attach_ftxd;
- snprintf(rtdev_stream->symbol, sizeof(rtdev_stream->symbol), "%s", devsym);
- return rtdev_stream;
+prod_cons_create_failed:
+ MR_LOG(WARNING, BASE, "Creating prod/cons %s (nr_rx_stream=%d, nr_tx_stream=%d) of rtdev %s failed. \n",
+ appsym, nr_rx_stream, nr_tx_stream, dev_desc->symbol);
+ goto clean;
-errout:
- //TODO: ��׼ȷ���ͷš�
- if (rtdev_stream != NULL) rte_free(rtdev_stream);
+clean:
+ if (desc->vnode_cons_rx != NULL) vnode_delete_cons(desc->vnode_cons_rx, &desc->ops);
+ if (desc->vnode_prod_tx != NULL) vnode_delete_prod(desc->vnode_prod_tx, &desc->ops);
+ if (desc->vnode_prod_ftx != NULL) vnode_delete_prod(desc->vnode_prod_ftx, &desc->ops);
return NULL;
}
-// �ر��豸����û��ʵ���Ե��߼������򿪺�Ͳ��ܹرգ�����Ҫ�ر�����
-// Ӧ���ر������豸Ȼ�����´򿪡�
-int rt_dev_stream_close(struct mr_rtdev_stream * stream)
+// �ر��豸
+int mr_rt_device_close(struct rtdev_app_desc * desc)
{
- rte_free(stream);
- return 0;
-}
-
-// ���豸����ÿ���̵߳���һ�Σ���ȡ��ǰ�̵߳���������
-struct mr_rtdev_stream * rt_dev_open_stream(const char * devsym,
- const char * appsym, flags_t flags)
-{
- char vnodesym[MR_STRING_MAX];
- char prod_or_cons_sym[MR_STRING_MAX];
-
- struct vnodeman_attach_desc * attach_rxd = NULL;
- struct vnodeman_attach_desc * attach_txd = NULL;
- struct vnodeman_attach_desc * attach_ftxd = NULL;
-
- // �����������ռ�
- struct mr_rtdev_stream * rtdev_stream;
- rtdev_stream = rte_zmalloc(NULL, sizeof(struct mr_rtdev_stream), 0);
- if(unlikely(rtdev_stream == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot alloc rtdev_stream for rtdevice %s", devsym);
- goto errout;
- }
+ struct rtdev_desc * dev_desc = desc->dev_desc;
+ if (desc->vnode_cons_rx != NULL) vnode_delete_cons(desc->vnode_cons_rx, &desc->ops);
+ if (desc->vnode_prod_tx != NULL) vnode_delete_prod(desc->vnode_prod_tx, &desc->ops);
+ if (desc->vnode_prod_ftx != NULL) vnode_delete_prod(desc->vnode_prod_ftx, &desc->ops);
- // �����򿪣����ձ���
- if (flags & RTDEV_FLAGS_OPEN_STREAM_RX)
- {
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_RX, devsym);
- snprintf(prod_or_cons_sym, sizeof(prod_or_cons_sym), __PATTERN_CONS_APP, appsym);
-
- attach_rxd = mr_vnodeman_consumer_attach(vnodesym, prod_or_cons_sym);
- if (unlikely(attach_rxd == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot attach vnode(sym=%s) consumer=(%s). \n",
- vnodesym, prod_or_cons_sym);
- goto errout;
- }
- }
+ rte_rwlock_write_lock(&dev_desc->app_desc_lock);
+ TAILQ_REMOVE(&dev_desc->app_desc_list, desc, next);
+ rte_rwlock_write_unlock(&dev_desc->app_desc_lock);
- // �����򿪣���������
- if (flags & RTDEV_FLAGS_OPEN_STREAM_TX)
- {
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_TX, devsym);
- snprintf(prod_or_cons_sym, sizeof(prod_or_cons_sym), __PATTERN_PROD_APP, appsym);
-
- attach_txd = mr_vnodeman_producer_attach(vnodesym, prod_or_cons_sym);
- if (unlikely(attach_txd == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot attach vnode(sym=%s) producer=(%s). \n",
- vnodesym, prod_or_cons_sym);
- goto errout;
- }
-
- snprintf(vnodesym, sizeof(vnodesym), __PATTERN_DEV_FTX, devsym);
- snprintf(prod_or_cons_sym, sizeof(prod_or_cons_sym), __PATTERN_PROD_APP, appsym);
-
- attach_ftxd = mr_vnodeman_producer_attach(vnodesym, prod_or_cons_sym);
- if (unlikely(attach_ftxd == NULL))
- {
- MR_LOG(WARNING, BASE, "Rtdevice, RtdeviceOpen, "
- "Cannot attach vnode(sym=%s) producer=(%s). \n",
- vnodesym, prod_or_cons_sym);
- goto errout;
- }
- }
-
- rtdev_stream->rxd = attach_rxd;
- rtdev_stream->txd = attach_txd;
- rtdev_stream->fasttxd = attach_ftxd;
- snprintf(rtdev_stream->symbol, sizeof(rtdev_stream->symbol), "%s", devsym);
- return rtdev_stream;
-
-errout:
- //TODO: ��׼ȷ���ͷš�
- if (rtdev_stream != NULL) rte_free(rtdev_stream);
- return NULL;
+ rte_free(desc);
+ return 0;
} \ No newline at end of file
diff --git a/core/src/stat.c b/core/src/stat.c
index 486f20e..f81361d 100644
--- a/core/src/stat.c
+++ b/core/src/stat.c
@@ -11,27 +11,6 @@
#include <mr_stat.h>
#include <mr_core.h>
#include <mr_runtime.h>
-#include "MESA_prof_load.h"
-
-#ifndef MR_STAT_OPT_DEFAULT_DEV_STAT_ENABLE
-#define MR_STAT_OPT_DEFAULT_DEV_STAT_ENABLE 1
-#endif
-
-#ifndef MR_STAT_OPT_DEFAULT_VNODE_STAT_ENABLE
-#define MR_STAT_OPT_DEFAULT_VNODE_STAT_ENABLE 1
-#endif
-
-#ifndef MR_STAT_OPT_DEFAULT_PERF_STAT_ENABLE
-#define MR_STAT_OPT_DEFAULT_PERF_STAT_ENABLE 1
-#endif
-
-#ifndef MR_STAT_OPT_DEFAULT_APP_STAT_ENABLE
-#define MR_STAT_OPT_DEFAULT_APP_STAT_ENABLE 1
-#endif
-
-#ifndef MR_STAT_OPT_DEFAULT_EVENT_STAT_ENABLE
-#define MR_STAT_OPT_DEFAULT_EVENT_STAT_ENABLE 1
-#endif
struct stat_ctx
{
@@ -83,7 +62,7 @@ struct mr_event_stat * mr_event_stat_get()
return NULL;
}
-int stat_ctx_init(struct mr_core_instance * core_instance)
+int stat_init(struct mr_core_instance * core_instance)
{
core_instance->stat_ctx = rte_zmalloc("STAT_CTX", sizeof(struct stat_ctx), 0);
MR_CHECK(core_instance->stat_ctx != NULL, "Cannot alloc memory for stat context");
@@ -92,30 +71,6 @@ int stat_ctx_init(struct mr_core_instance * core_instance)
int stat_config(struct mr_core_instance * core_instance)
{
- struct mr_global_config * g_cfg = core_instance->g_cfg;
- struct stat_ctx * module_ctx = mr_core_default_instance_get()->stat_ctx;
-
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "device_stat_enable",
- &module_ctx->device_stat_enable, MR_STAT_OPT_DEFAULT_DEV_STAT_ENABLE);
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "vnode_stat_enable",
- &module_ctx->vnode_stat_enable, MR_STAT_OPT_DEFAULT_VNODE_STAT_ENABLE);
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "perf_stat_enable",
- &module_ctx->perf_stat_enable, MR_STAT_OPT_DEFAULT_PERF_STAT_ENABLE);
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "app_stat_enable",
- &module_ctx->app_stat_enable, MR_STAT_OPT_DEFAULT_APP_STAT_ENABLE);
- MESA_load_profile_uint_def(g_cfg->glob_cfg_file, "stat", "event_stat_enable",
- &module_ctx->event_stat_enable, MR_STAT_OPT_DEFAULT_EVENT_STAT_ENABLE);
- return 0;
-}
-
-int stat_init(struct mr_core_instance * core_instance)
-{
- return 0;
-}
-
-int stat_slave_init(struct mr_core_instance * core_instance,
- struct mr_core_slave_instance * slave_instance)
-{
return 0;
}
diff --git a/core/src/vman.c b/core/src/vman.c
index 4d0ea4b..243727b 100644
--- a/core/src/vman.c
+++ b/core/src/vman.c
@@ -14,12 +14,11 @@
#include <string.h>
#include <rte_log.h>
#include <rte_malloc.h>
+#include <rte_mbuf.h>
#include <mr_common.h>
#include <mr_vnode.h>
#include <mr_vman.h>
-#include <mr_mrbuf.h>
-#include <mr_runtime.h>
#include <mr_core.h>
struct vnode_record
@@ -255,7 +254,7 @@ const char * vnode_sym, const char * prod_sym, unsigned int nr_prod_queue)
if (prod == NULL)
{
MR_LOG(INFO, BASE, "VNodeMan, VNodeManRegisterProducer, "
- "Cannot create consumer %s for vnode %s", prod_sym, vnode_sym);
+ "Cannot create consumer %s for vnode %s. \n", prod_sym, vnode_sym);
return -2;
}
@@ -459,7 +458,7 @@ struct vnodeman_attach_desc * mr_vnodeman_producer_attach(const char * vnode_sym
return desc;
}
-int vnodeman_ctx_init(struct mr_core_instance * core_instance)
+int vnodeman_init(struct mr_core_instance * core_instance)
{
core_instance->vnodeman_ctx = rte_zmalloc("VNODEMAN_CTX",
sizeof(struct vnodeman_ctx), 0);
@@ -470,25 +469,4 @@ int vnodeman_ctx_init(struct mr_core_instance * core_instance)
TAILQ_INIT(&ctx->vnode_list);
mr_spin_init(&ctx->lock);
return 0;
-}
-
-int vnodeman_config(struct mr_core_instance * core_instance)
-{
- return 0;
-}
-
-int vnodeman_init(struct mr_core_instance * core_instance)
-{
- return 0;
-}
-
-int vnodeman_slave_init(struct mr_core_instance * core_instance,
- struct mr_core_slave_instance * slave_instance)
-{
- return 0;
-}
-
-int vnodeman_destory(struct mr_core_instance * core_instance)
-{
- return 0;
} \ No newline at end of file
diff --git a/core/src/vnode.c b/core/src/vnode.c
index 5fda579..402d043 100644
--- a/core/src/vnode.c
+++ b/core/src/vnode.c
@@ -22,7 +22,6 @@
#include <mr_common.h>
#include <mr_vnode.h>
#include <rte_ring.h>
-#include <mr_stat.h>
#ifndef MR_LIBVNODE_OPT_THREAD_SAFE
#define MR_LIBVNODE_OPT_THREAD_SAFE 1
@@ -48,6 +47,12 @@
#define __write_unlock(x)
#endif
+
+#define VNODE_STAT_UPDATE(desc, queue, item, value) \
+do { \
+ rte_atomic64_add(&desc->stat[queue].item,value); \
+} while(0) \
+
/* Tunnel Description Structure */
struct tunnel_desc
{
@@ -93,8 +98,8 @@ struct tunnel_desc * tunnel_new(const char * symbol, unsigned int size,
snprintf(desc->symbol, sizeof(desc->symbol), "%s", symbol);
desc->tunnel_size = size;
- // disable tunnel enqueue buffer
- if (sz_buffer == 0) return desc;
+ // 禁用buffer,就是让buffer为1,写入一个后立即发出
+ if (sz_buffer == 0) sz_buffer = 1;
desc->en_buffer = rte_zmalloc(NULL, sizeof(void *) * sz_buffer, 0);
desc->sz_en_buffer = sz_buffer;
@@ -127,19 +132,10 @@ static inline void tunnel_enqueue_without_buffer(struct tunnel_desc * desc,
return;
}
-static inline void tunnel_enqueue(struct tunnel_desc * desc, struct vnode_ops * ops,
- void * obj)
+static inline void tunnel_enqueue(struct vnode_prod * prod, struct vnode_cons * cons,
+ unsigned int prodq, unsigned int consq, struct tunnel_desc * desc,
+ struct vnode_ops * ops, void * obj)
{
- // disable sz_buffer, enqueue object directly.
- // TODO: 优化无缓冲队列
-#if 0
- if(desc->en_buffer == NULL)
- {
- tunnel_enqueue_without_buffer(desc, ops, obj);
- return;
- }
-#endif
-
// append the object at the tail of enqueue buffer.
unsigned int pos;
pos = desc->sz_en_buffer_used;
@@ -157,22 +153,28 @@ static inline void tunnel_enqueue(struct tunnel_desc * desc, struct vnode_ops *
int n_to_send = desc->sz_en_buffer;
int n_send = rte_ring_sp_enqueue_burst(desc->tunnel_object,
desc->en_buffer, n_to_send);
+
+ if (likely(n_send == n_to_send)) goto out;
- UPDATE_VNODE_STAT(tunnel_enqueue, n_send);
-
// release all the objects which not send successfully.
- if(unlikely(n_send < n_to_send))
+ for (unsigned int k = n_send; k < n_to_send; k++)
{
- for (unsigned int k = n_send; k < n_to_send; k++)
- {
- void * object_to_be_free = desc->en_buffer[k];
- ops->op_object_delete(object_to_be_free);
- }
-
- UPDATE_VNODE_STAT(tunnel_enqueue_fail, n_to_send - n_send);
- UPDATE_EVENT_STAT(ev_rx_entunnel_failed, n_to_send - n_send);
+ void * object_to_be_free = desc->en_buffer[k];
+ ops->op_object_delete(object_to_be_free);
}
+out:
+ // 更新生产者统计计数
+ VNODE_STAT_UPDATE(prod, prodq, on_line, n_to_send);
+ VNODE_STAT_UPDATE(prod, prodq, sent, n_send);
+ VNODE_STAT_UPDATE(prod, prodq, missed, n_to_send - n_send);
+
+ // 更新消费者统计计数
+ VNODE_STAT_UPDATE(cons, consq, on_line, n_to_send);
+ VNODE_STAT_UPDATE(cons, consq, recieved, n_send);
+ VNODE_STAT_UPDATE(cons, consq, missed, n_to_send - n_send);
+
+ // 清空缓冲区
desc->sz_en_buffer_used = 0;
return;
}
@@ -192,8 +194,7 @@ static inline int tunnel_dequeue(struct tunnel_desc * desc, struct vnode_ops * o
*/
-//TODO: change name, tunnel_///locate,index
-static inline struct tunnel_desc ** tunnel_block_index(struct tunnel_block * block,
+static inline struct tunnel_desc ** tunnel_block_locate(struct tunnel_block * block,
unsigned int prodq_id, unsigned int consq_id)
{
assert(prodq_id < block->nr_prodq && consq_id < block->nr_consq);
@@ -207,8 +208,8 @@ int tunnel_block_delete(struct tunnel_block * block, struct vnode_ops * ops)
{
for (int consq_id = 0; consq_id < block->nr_consq; consq_id++)
{
- if (*tunnel_block_index(block, prodq_id, consq_id) != NULL)
- tunnel_delete(*tunnel_block_index(block, prodq_id, consq_id));
+ if (*tunnel_block_locate(block, prodq_id, consq_id) != NULL)
+ tunnel_delete(*tunnel_block_locate(block, prodq_id, consq_id));
}
}
@@ -238,9 +239,13 @@ int tunnel_block_try_gc(struct tunnel_block * block, struct vnode_ops * ops)
}
/* Alloc a block of tunnels, and init all the tunnels */
-struct tunnel_block * tunnel_block_new(struct vnode_ops * ops, const char * symbol,
- unsigned int nr_prodq, unsigned int nr_consq, unsigned int tunnel_size, unsigned int tun_sz_buffer)
+struct tunnel_block * tunnel_block_new(struct vnode_ops * ops, const char * symbol,
+ struct vnode_prod * prod, struct vnode_cons * cons,
+ unsigned int tunnel_size, unsigned int tun_sz_buffer)
{
+ unsigned int nr_prodq = prod->nr_prodq;
+ unsigned int nr_consq = cons->nr_consq;
+
unsigned int block_size = sizeof(struct tunnel_block) +
sizeof(struct tunnel_desc *) * (nr_prodq * nr_consq);
@@ -257,6 +262,8 @@ struct tunnel_block * tunnel_block_new(struct vnode_ops * ops, const char * symb
return NULL;
}
+ block->cons = cons;
+ block->prod = prod;
block->nr_consq = nr_consq;
block->nr_prodq = nr_prodq;
block->deleted = 0;
@@ -283,7 +290,7 @@ struct tunnel_block * tunnel_block_new(struct vnode_ops * ops, const char * symb
"Tunnel %s(object=%p, sz_tunnel=%d, sz_buffer=%d) created.\n",
tunnel_sym, tdesc->tunnel_object, tunnel_size, tun_sz_buffer);
- *tunnel_block_index(block, prodq_id, consq_id) = tdesc;
+ *tunnel_block_locate(block, prodq_id, consq_id) = tdesc;
}
}
@@ -306,16 +313,14 @@ err:
static inline void tunnel_block_enqueue_with_hash(struct tunnel_block * block, struct vnode_ops * ops,
int prodq, void * obj[], uint32_t hash[], int nr_obj)
{
- unsigned int consq;
struct tunnel_desc * tunnel;
- UPDATE_VNODE_STAT(block_enqueue, nr_obj);
-
+
for (unsigned int i = 0; i < nr_obj; i++)
{
assert(obj[i] != NULL);
- consq = hash[i] % block->nr_consq;
- tunnel = *tunnel_block_index(block, prodq, consq);
- tunnel_enqueue(tunnel, ops, obj[i]);
+ unsigned int consq = hash[i] % block->nr_consq;
+ tunnel = *tunnel_block_locate(block, prodq, consq);
+ tunnel_enqueue(block->prod, block->cons, prodq, consq, tunnel, ops, obj[i]);
}
}
@@ -330,7 +335,7 @@ static inline int tunnel_block_dequeue(struct tunnel_block * block, struct vnode
for (int prodq = 0; prodq < block->nr_prodq; prodq++)
{
- struct tunnel_desc * tunnel = *tunnel_block_index(block, prodq, consq);
+ struct tunnel_desc * tunnel = *tunnel_block_locate(block, prodq, consq);
nr_obj_recv = tunnel_dequeue(tunnel, ops, &obj[nr_obj], nr_obj_left);
nr_obj += nr_obj_recv;
nr_obj_left -= nr_obj_recv;
@@ -400,7 +405,7 @@ int vnode_prod_increase_unsafe(struct vnode * vnode, struct vnode_ops * ops,
nr_consq = cons->nr_consq;
// create commucation tunnel for each cons and prods
- block = tunnel_block_new(ops, block_sym, nr_prodq, nr_consq,
+ block = tunnel_block_new(ops, block_sym, prod, cons,
vnode->sz_tunnel, vnode->sz_tunnel_buffer);
if (block == NULL)
{
@@ -459,7 +464,7 @@ struct vnode_cons * cons)
nr_prodq = prod->nr_prodq;
// create commucation tunnel for each cons and prods
- block = tunnel_block_new(ops, block_sym, nr_prodq, nr_consq,
+ block = tunnel_block_new(ops, block_sym, prod, cons,
vnode->sz_tunnel, vnode->sz_tunnel_buffer);
if (block == NULL)
{
@@ -703,6 +708,16 @@ int vnode_prod_attach(struct vnode * node, struct vnode_prod* prod)
return ret;
}
+struct vnode_prod_stat * vnode_prod_stat_get(struct vnode_prod * prod)
+{
+ return prod->stat;
+}
+
+struct vnode_cons_stat * vnode_cons_stat_get(struct vnode_cons * cons)
+{
+ return cons->stat;
+}
+
int vnode_delete_prod(struct vnode_prod * prod, struct vnode_ops * ops)
{
assert(prod != NULL && prod->vnode != NULL && ops != NULL);
@@ -797,7 +812,6 @@ int vnode_enqueue_burst_with_hash(struct vnode_prod * prod, struct vnode_ops * o
assert(nr_objects <= MR_LIBVNODE_MAX_SZ_BURST);
__read_lock(&prod->vnode->rwlock);
- UPDATE_VNODE_STAT(object_enqueue, nr_objects);
// get the last block, this block are enqueued with the original objects.
struct tunnel_block_list_item * tblist_item_last;
@@ -823,16 +837,10 @@ int vnode_enqueue_burst_with_hash(struct vnode_prod * prod, struct vnode_ops * o
for (int i = 0; i < nr_objects; i++)
{
assert(i < RTE_DIM(dup_objects));
- dup_objects[nr_dup_objects] = ops->op_object_dup(objects[i]);
+ dup_objects[nr_dup_objects] = ops->op_object_dup(objects[i], ops->pool_dup_object);
if (likely(dup_objects[nr_dup_objects] != NULL))
{
nr_dup_objects++;
- UPDATE_VNODE_STAT(object_dup_success, 1);
- }
- else
- {
- UPDATE_VNODE_STAT(object_dup_fail, 1);
- UPDATE_EVENT_STAT(ev_rx_dup_failed, 1);
}
}
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 9271b1b..b803589 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -1,2 +1,4 @@
-#install(FILES extern/mr_rawio.h DESTINATION include COMPONENT Program)
-#install(FILES extern/mr_buf.h DESTINATION include COMPONENT Program) \ No newline at end of file
+install(FILES external/marsio.h DESTINATION include COMPONENT Program)
+install(FILES external/marsio_buffer_user_api.h DESTINATION include COMPONENT Program)
+install(FILES external/marsio_rawio_user_api.h DESTINATION include COMPONENT Program)
+install(FILES external/marsio_udp_user_api.h DESTINATION include COMPONENT Program) \ No newline at end of file
diff --git a/include/external/marsio.h b/include/external/marsio.h
new file mode 100644
index 0000000..bf78869
--- /dev/null
+++ b/include/external/marsio.h
@@ -0,0 +1,86 @@
+/*
+ * \brief MARSIO Userspace ZeroCopy Driver Version 4
+ *
+ * This is the user api header file of MARSIOv4 ZeroCopy Driver
+ *
+ * \author Qiuwen Lu<[email protected]>
+ * Institute of Information Engineering, Chinese Academy of Sciences
+ *
+ * \date 2016-12-01
+ */
+
+#pragma once
+
+typedef enum
+{
+ /* 数据面线程数,没有缺省值 */
+ MARSIO_OPT_THREAD_NUM,
+ /* 数据面线程绑定掩码,没有缺省值
+ * 设置该掩码后,数据面线程数选项将被忽略。
+ */
+ MARSIO_OPT_THREAD_MASK,
+ /* 日志句柄(FILE *),类型:FILE *,缺省值:stderr
+ * 不设置该选项将使日志向stderr输出
+ */
+ MARSIO_OPT_FILE_LOG,
+ /* 配置文件路径,类型:char *, 缺省值:NULL
+ * 设置该路径后,将到这一路径读取配置参数,SET_OPT的其他属性无效。
+ */
+ MARSIO_OPT_FILE_CONF_PATH,
+ /* 处理SIG信号,缺省值:类型:uint32_t,关闭(0)
+ * 启用该选项后,将自动处理SIGINT、SIGTERM信号
+ */
+ MARSIO_OPT_AUTOEXIT,
+ /* 原始报文收发:收报文环数,类型:uint32_t,
+ * 缺省值:与数据面线程数一致
+ */
+ MARSIO_OPT_RAW_RX_STREAM_NUM,
+ /* 原始报文收发:发报文环数,
+ * 类型:uint32_t,缺省值:与数据面线程数一致
+ */
+ MARSIO_OPT_RAW_TX_STREAM_NUM,
+ /* 协议栈报文收发:收报文环数,
+ * 类型:uint32_t,缺省值:与数据面线程数一致
+ */
+ MARSIO_OPT_STACK_RX_STREAM_NUM,
+ /* 协议栈报文收发:发报文环数,
+ * 类型:uint32_t,缺省值:与数据面线程数一致
+ */
+ MARSIO_OPT_STACK_TX_STREAM_NUM,
+ /* 原始报文收发:注册启用设备,类型:const char *,返回值:device_id_t
+ * 不设置启用设备将启用所有可能启用的设备
+ */
+ MARSIO_OPT_RAW_DEVICE,
+ /* 协议栈设备收发:注册启用设备,类型:const char *,返回值:device_id_t
+ * 不设置启用设备将启用所有可能启用的设备
+ */
+ MARSIO_OPT_STACK_DEVICE,
+ /* 原始报文收发:查询设备数量
+ * 查询选项,返回值:启用的原始报文收发设备数量。
+ */
+ MARSIO_OPT_RAW_DEVICE_NUM,
+ /* 协议栈报文收发:查询设备数量
+ * 查询选项,返回值:启用的协议栈设备收发设备数量
+ */
+ MARSIO_OPT_STACK_DEVICE_NUM,
+
+} marsio_opt_type_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void marsio_on_exit_register(void(*exit_fn)(void * arg), void * arg);
+int marsio_option_set(const char * appsym, marsio_opt_type_t opt_type, void * opt, size_t sz_opt);
+int marsio_option_get(const char * appsym, int opt_type, void * out_opt, size_t out_opt_buffer);
+int marsio_init(const char * appsym);
+int marsio_thread_init();
+int marsio_destory();
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <marsio_buffer_user_api.h>
+#include <marsio_rawio_user_api.h>
+#include <marsio_udp_user_api.h> \ No newline at end of file
diff --git a/include/external/marsio_buffer_user_api.h b/include/external/marsio_buffer_user_api.h
new file mode 100644
index 0000000..1aabae1
--- /dev/null
+++ b/include/external/marsio_buffer_user_api.h
@@ -0,0 +1,69 @@
+#ifndef _MARSIO_BUFF_USER_API_H_
+#define _MARSIO_BUFF_USER_API_H_
+
+/*
+ marsio mbuf definition.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+typedef void marsio_buff_t;
+
+int marsio_buff_malloc(marsio_buff_t *m[], unsigned int nb_buff,unsigned int flags,int thread_seq);
+void marsio_buff_free(marsio_buff_t *m[], unsigned int nb_buff);
+
+//simply get control zone data ptr.
+void *marsio_buff_ctrlzone(marsio_buff_t *m,uint8_t id);
+
+//a safe way to read control zone data.
+void *marsio_buff_ctrlzone_data(marsio_buff_t *m,uint8_t id,uint8_t *size);
+
+//a safe way to set control zone data.
+void marsio_buff_ctrlzone_set(marsio_buff_t *m,uint8_t id,void* ptr_data,uint8_t size);
+
+void marsio_buff_reset(marsio_buff_t *m);
+
+marsio_buff_t *marsio_buff_getnext_seg(marsio_buff_t *m);
+marsio_buff_t *marsio_buff_getnext_pkt(marsio_buff_t *m);
+
+void marsio_buff_append_pkt(marsio_buff_t *head, marsio_buff_t *next);
+void marsio_buff_append_seg(marsio_buff_t *head, marsio_buff_t *next);
+
+uint16_t marsio_buff_headroom(const marsio_buff_t *m);
+uint16_t marsio_buff_tailroom(const marsio_buff_t *m);
+
+marsio_buff_t *marsio_buff_getnext_seg(marsio_buff_t *m);
+marsio_buff_t *marsio_buff_getnext_pkt(marsio_buff_t *m);
+
+char *marsio_buff_mtod(marsio_buff_t *m);
+
+uint32_t marsio_buff_buflen(marsio_buff_t *m);
+
+uint32_t marsio_buff_datalen(marsio_buff_t *m);
+
+char *marsio_buff_prepend(marsio_buff_t *m, uint16_t len);
+
+char *marsio_buff_append(marsio_buff_t *m, uint16_t len);
+
+char *marsio_buff_adj(marsio_buff_t *m, uint16_t len);
+
+int marsio_buff_trim(marsio_buff_t *m, uint16_t len);
+
+uint16_t marsio_buff_headroom(const marsio_buff_t *m);
+
+uint16_t marsio_buff_tailroom(const marsio_buff_t *m);
+
+uint32_t marsio_get_pkt_type(marsio_buff_t *m);
+
+marsio_buff_t *marsio_buff_dup(marsio_buff_t *m);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/external/marsio_rawio_user_api.h b/include/external/marsio_rawio_user_api.h
new file mode 100644
index 0000000..6d48286
--- /dev/null
+++ b/include/external/marsio_rawio_user_api.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "marsio_buffer_user_api.h"
+
+typedef void * raw_socket_t;
+typedef uint32_t thread_id_t;
+typedef uint32_t device_id_t;
+
+int marsio_raw_recv_burst(device_id_t dev_id, thread_id_t sid,
+ marsio_buff_t * mbufs[], int nr_max_mbufs);
+
+int marsio_raw_send_burst(device_id_t dev_id, thread_id_t sid,
+ marsio_buff_t * mbufs[], int nr_mbufs);
+
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/include/external/marsio_udp_user_api.h b/include/external/marsio_udp_user_api.h
new file mode 100644
index 0000000..a2332ec
--- /dev/null
+++ b/include/external/marsio_udp_user_api.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <sys/socket.h>
+#include <unistd.h>
+
+int marsio_socket(int family, int type, int protocol);
+
+int marsio_connect(int fd, const struct sockaddr * addr, socklen_t addrlen);
+
+int marsio_bind(int fd, const struct sockaddr * addr, socklen_t addrlen);
+
+/* UDP���Ļ�������ͬһ�����ϵĻ�������ʾͬһ��UDP���� */
+/* ����MARSIO-3�汾���¹��ܲ�Ҫʹ�� */
+struct marsio_udp_buff
+{
+ /* ��������ʼ��ַ */
+ void * start;
+ /* ���������� */
+ unsigned int len;
+ /* ��һ�黺������ַ */
+ struct marsio_udp_buff * next;
+ /* ��һ������ʼ��ַ */
+ struct marsio_udp_buff * next_pkt;
+};
+
+struct marsio_udp_buff * marsio_udp_alloc() __attribute__((__deprecated__));
+
+void marsio_udp_free(struct marsio_udp_buff * udp_buff) __attribute__((__deprecated__));
+
+ssize_t marsio_udp_sendto_chain(int marsio_fd, struct marsio_udp_buff * chain_head,
+ int nb_buff, int flags, struct sockaddr * to[], socklen_t addrlen[], int nb_sockaddrs)
+ __attribute__((__deprecated__)); \ No newline at end of file
diff --git a/include/mr_common.h b/include/internal/mr_common.h
index 88a2140..3911a26 100644
--- a/include/mr_common.h
+++ b/include/internal/mr_common.h
@@ -83,6 +83,10 @@ typedef uint32_t hash_t;
#define MR_LOG(level, module, ...) \
RTE_LOG(level, module, ##__VA_ARGS__)
+#define RETURN_IF_ERROR(module, level, cond, rtv, ...) do { \
+ if(cond) { MR_LOG(module, level, ##__VA_ARGS__); return rtv; } \
+} while(0)
+
/* TODO: support pthread read/write lock */
typedef rte_rwlock_t mr_spin_rwlock_t;
#define mr_spin_rwlock_read_lock(x) rte_rwlock_read_lock(x)
@@ -99,6 +103,7 @@ typedef rte_spinlock_t mr_spinlock_t;
/* Only use in Visual Studio, to avoid IDE errors */
#ifdef _MSC_VER
#define rte_cpu_to_be_16(x) htons(x)
+#define rte_cpu_to_be_32(x) htonl(x)
#define rte_be_to_cpu_32(x) ntohl(x)
#define likely(x) x
#define unlikely(x) x
diff --git a/include/mr_config.h.in b/include/internal/mr_config.h.in
index 009cf7b..009cf7b 100644
--- a/include/mr_config.h.in
+++ b/include/internal/mr_config.h.in
diff --git a/include/mr_mask.h b/include/internal/mr_mask.h
index f3b85ec..f3b85ec 100644
--- a/include/mr_mask.h
+++ b/include/internal/mr_mask.h
diff --git a/include/internal/mr_version.h.in b/include/internal/mr_version.h.in
new file mode 100644
index 0000000..f721e88
--- /dev/null
+++ b/include/internal/mr_version.h.in
@@ -0,0 +1,15 @@
+#pragma once
+
+#define MR_VCS_TYPE "@VCS_TYPE@"
+#define MR_VCS_BASENAME "@VCS_BASENAME@"
+#define MR_VCS_UUID "@VCS_UUID@"
+#define MR_VCS_NUM "@VCS_NUM@"
+#define MR_VCS_DATE "@VCS_DATE@"
+#define MR_VCS_BRANCH "@VCS_BRANCH@"
+#define MR_VCS_TAG "@VCS_TAG@"
+#define MR_VCS_TICK "@VCS_TICK@"
+#define MR_VCS_EXTRA "@VCS_EXTRA@"
+#define MR_VCS_ACTION_STAMP "@VCS_ACTION_STAMP@"
+#define MR_VCS_FULL_HASH "@VCS_FULL_HASH@"
+#define MR_VCS_SHORT_HASH "@VCS_SHORT_HASH@"
+#define MR_VCS_WC_MODIFIED "@VCS_WC_MODIFIED@" \ No newline at end of file
diff --git a/include/mr_buffer.h b/include/mr_buffer.h
deleted file mode 100644
index c859f48..0000000
--- a/include/mr_buffer.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef _MARSIO_BUF_H_
-#define _MARSIO_BUF_H_ 1
-
-/*
- marsio mbuf definition.
-*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-typedef void marsio_buf_t;
-
-marsio_buf_t *marsio_buf_alloc(void);
-void marsio_buf_free(marsio_buf_t *m);
-int marsio_buf_batch_alloc(marsio_buf_t *m[], int num);
-void marsio_buf_batch_free(marsio_buf_t *m[], int num);
-
-void marsio_buf_reset(marsio_buf_t *m);
-
-marsio_buf_t *marsio_buf_dup(marsio_buf_t *m);
-
-char *marsio_buf_mtod(marsio_buf_t *m);
-uint32_t marsio_buf_pkt_len(marsio_buf_t *m);
-char *marsio_buf_prepend(marsio_buf_t *m, uint16_t len);
-char *marsio_buf_append(marsio_buf_t *m, uint16_t len);
-char *marsio_buf_adj(marsio_buf_t *m, uint16_t len);
-int marsio_buf_trim(marsio_buf_t *m, uint16_t len);
-uint16_t marsio_buf_headroom(const marsio_buf_t *m);
-uint16_t marsio_buf_tailroom(const marsio_buf_t *m);
-
-
-int marsio_buf_ctrlzone_alloc_id(void);
-void *marsio_buf_get_ctrlzone(marsio_buf_t *m, int ctrlzone_id);
-void marsio_buf_set_ctrlzone(marsio_buf_t *m, int ctrlzone_id, void *ctrl_ptr);
-
-void marsio_buf_append_pkt(marsio_buf_t *previous, marsio_buf_t *next);
-marsio_buf_t *marsio_buf_get_nextpkt(marsio_buf_t *m);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/include/mr_rawio.h b/include/mr_rawio.h
deleted file mode 100644
index 11b806e..0000000
--- a/include/mr_rawio.h
+++ /dev/null
@@ -1,27 +0,0 @@
-
-/* Packet I/O Middleware for START/SAPP/PAPP
- * Autuor : Lu Qiuwen
- * Date : 2014-03-04
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_mbuf.h>
-
-/* Basic Raw Packet I/O Interface */
-typedef void * raw_socket_t;
-raw_socket_t * marsio_raw_socket(const char * devsym, unsigned int nr_rx_stream,
- unsigned int nr_tx_stream, unsigned int flags);
-int marsio_raw_close(raw_socket_t * socket);
-int marsio_raw_recv(raw_socket_t * socket, struct rte_mbuf * mbufs[], int nr_max_mbufs);
-int marsio_raw_send(raw_socket_t * socket, struct rte_mbuf * mbufs[], int nr_mbufs);
-
-
-#ifdef __cplusplus
-}
-#endif \ No newline at end of file
diff --git a/pag/CMakeLists.txt b/pag/CMakeLists.txt
index 5911903..46e1bc8 100644
--- a/pag/CMakeLists.txt
+++ b/pag/CMakeLists.txt
@@ -6,8 +6,8 @@ include_directories(${DPDK_INCLUDE_DIR})
add_definitions(${DPDK_C_PREDEFINED})
add_library(pag SHARED libpag.c)
-target_link_libraries(pag MESA_prof_load_static marsio core)
-target_link_libraries(pag rt pthread dl core)
+target_link_libraries(pag MESA_prof_load_static marsio)
+target_link_libraries(pag rt pthread dl)
set_target_properties(pag PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/version.map")
target_include_directories(pag INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
diff --git a/pag/libpag.c b/pag/libpag.c
index f1066ee..8031b43 100644
--- a/pag/libpag.c
+++ b/pag/libpag.c
@@ -4,48 +4,54 @@
* Date : 2016-09-12
*/
+#include <stdio.h>
#include <unistd.h>
+#include <stdlib.h>
#include <assert.h>
#include <netinet/in.h>
-#include <rte_string_fns.h>
-#include <rte_ether.h>
#include <MESA_prof_load.h>
+
+#include <rte_ether.h>
#include <mr_common.h>
-#include <mr_rawio.h>
-#include <mr_stat.h>
-#include <mrlib.h>
-#include <mr_mask.h>
+#include <marsio.h>
+
#include "libpag.h"
+#define PAG_SYMBOL_MAX 64
+#define PAG_STRING_MAX 1024
+#define PAG_BURST_MAX 64
+#define PAG_DEVICE_MAX 16
+#define PAG_CPU_ID_MAX 64
+
struct pag_instance
{
- char app_name[MR_SYMBOL_MAX];
- char dev_name[MR_STRING_MAX];
- raw_socket_t * raw_sockets[MR_DEVICE_MAX];
- unsigned int nr_raw_sockets;
+ char app_name[PAG_SYMBOL_MAX];
+ char dev_name[PAG_STRING_MAX];
+ unsigned int nr_devices;
unsigned int nr_rx_stream;
unsigned int nr_tx_stream;
unsigned int burst_rx;
unsigned int burst_tx;
unsigned int autoexit;
+ unsigned int looptimes;
uint64_t coremask;
};
struct pag_thread_instance
{
int thread_inited;
- struct rte_mbuf * rxmbuf[MR_BURST_MAX];
- struct rte_mbuf * txmbuf[MR_BURST_MAX];
+ marsio_buff_t * rxmbuf[PAG_BURST_MAX];
+ marsio_buff_t * txmbuf[PAG_BURST_MAX];
unsigned int rxmbuf_max;
unsigned int txmbuf_max;
unsigned int rxmbuf_used;
unsigned int txmbuf_used;
unsigned int rxmbuf_cur;
unsigned int txmbuf_cur;
- unsigned int cur_socket;
+ unsigned int cur_device;
// ���������
- struct rte_mbuf * rxmbuf_ctx;
+ marsio_buff_t * rxmbuf_ctx;
};
static int __pag_inited = 0;
@@ -62,6 +68,34 @@ do { \
#define PAG_DEFAULT_RX_BURST 32
#define PAG_DEFAULT_TX_BURST 32
#define PAG_DEFAULT_AUTOEXIT 0
+#define PAG_DEFAULT_LOOP 0
+
+int __strsplit(char *string, int stringlen, char **tokens, int maxtokens, char delim)
+{
+ int i, tok = 0;
+ int tokstart = 1; /* first token is right at start of string */
+
+ if (string == NULL || tokens == NULL)
+ goto einval_error;
+
+ for (i = 0; i < stringlen; i++) {
+ if (string[i] == '\0' || tok >= maxtokens)
+ break;
+ if (tokstart) {
+ tokstart = 0;
+ tokens[tok++] = &string[i];
+ }
+ if (string[i] == delim) {
+ string[i] = '\0';
+ tokstart = 1;
+ }
+ }
+ return tok;
+
+einval_error:
+ errno = EINVAL;
+ return -1;
+}
static int pag_config_load_app_info(struct pag_instance * instance)
{
@@ -79,46 +113,51 @@ static int pag_config_load_app_info(struct pag_instance * instance)
static int pag_config_load_stream_info(struct pag_instance * instance)
{
- uint64_t coremask = 0;
- char * str_coremask_ptr = NULL;
- char str_coremask[MR_STRING_MAX];
-
- // ��CPU��������
- int ret = MESA_load_profile_string_nodef(PAG_CFGFILE, "pag", "coremask",
- str_coremask, sizeof(str_coremask));
-
- if(ret < 0)
+ unsigned int cpu_id_range[PAG_CPU_ID_MAX] = { 0 };
+
+ // ��CPU�����
+ int cpu_id_count = MESA_load_profile_uint_range(PAG_CFGFILE, "pag", "cpu_id",
+ PAG_CPU_ID_MAX, cpu_id_range);
+
+ if (cpu_id_count < 0)
{
- PAG_LOG("coremask is missing, please recheck %s", PAG_CFGFILE);
+ PAG_LOG("cpu_id is missing, please recheck %s", PAG_CFGFILE);
return -1;
}
-
- coremask = strtoull(str_coremask, &str_coremask_ptr, 0);
- if(coremask == 0 && str_coremask_ptr == NULL)
+
+ uint64_t coremask = 0;
+ for(int i = 0; i < cpu_id_count; i++)
{
- PAG_LOG("coremask is invalid, please recheck %s", PAG_CFGFILE);
- return -2;
+ coremask |= 1ULL << cpu_id_range[i];
}
-
+
// ��Ĭ���豸������û��ָ��ʹ���߳���
unsigned int nr_rx_stream;
unsigned int nr_tx_stream;
- unsigned int nr_stream_default = mask_popcnt(coremask);
+ unsigned int nr_stream_default = cpu_id_count;
MESA_load_profile_uint_def(PAG_CFGFILE, "pag", "rxstream",
&nr_rx_stream, nr_stream_default);
MESA_load_profile_uint_def(PAG_CFGFILE, "pag", "txstream",
&nr_tx_stream, nr_stream_default);
+ MESA_load_profile_uint_def(PAG_CFGFILE, "pag", "autoexit",
+ &instance->autoexit, PAG_DEFAULT_AUTOEXIT);
instance->coremask = coremask;
instance->nr_rx_stream = nr_rx_stream;
instance->nr_tx_stream = nr_tx_stream;
- MESA_load_profile_uint_def(PAG_CFGFILE, "pag", "autoexit",
- &instance->autoexit, PAG_DEFAULT_AUTOEXIT);
-
- PAG_LOG("coremask=%"PRIx64", rxstream=%u, txstream=%u, autoexit=%d",
- instance->coremask, instance->nr_rx_stream, instance->nr_tx_stream,
+ marsio_option_set(instance->app_name, MARSIO_OPT_THREAD_MASK,
+ &instance->coremask, sizeof(instance->coremask));
+ marsio_option_set(instance->app_name, MARSIO_OPT_AUTOEXIT,
+ &instance->autoexit, sizeof(instance->autoexit));
+ marsio_option_set(instance->app_name, MARSIO_OPT_RAW_RX_STREAM_NUM,
+ &instance->nr_rx_stream, sizeof(instance->nr_rx_stream));
+ marsio_option_set(instance->app_name, MARSIO_OPT_RAW_TX_STREAM_NUM,
+ &instance->nr_tx_stream, sizeof(instance->nr_tx_stream));
+
+ PAG_LOG("coremask=%"PRIx64", rxstream=%u, txstream=%u, autoexit=%d",
+ instance->coremask, instance->nr_rx_stream, instance->nr_tx_stream,
instance->autoexit);
return 0;
@@ -130,18 +169,20 @@ static int pag_config_load_burst_info(struct pag_instance * instance)
PAG_DEFAULT_RX_BURST);
MESA_load_profile_uint_def(PAG_CFGFILE, "pag", "burst_tx", &instance->burst_tx,
PAG_DEFAULT_TX_BURST);
+ MESA_load_profile_uint_def(PAG_CFGFILE, "pag", "loop", &instance->looptimes,
+ PAG_DEFAULT_LOOP);
- if(instance->burst_rx > MR_BURST_MAX)
+ if(instance->burst_rx > PAG_BURST_MAX)
{
PAG_LOG("burst_rx=%d is larger than limit(limit=%d), please recheck %s",
- instance->burst_rx, MR_BURST_MAX, PAG_CFGFILE);
+ instance->burst_rx, PAG_BURST_MAX, PAG_CFGFILE);
return -1;
}
- if(instance->burst_tx > MR_BURST_MAX)
+ if(instance->burst_tx > PAG_BURST_MAX)
{
PAG_LOG("burst_tx=%d is larger than limit(limit=%d), please recheck %s",
- instance->burst_tx, MR_BURST_MAX, PAG_CFGFILE);
+ instance->burst_tx, PAG_BURST_MAX, PAG_CFGFILE);
return -2;
}
@@ -149,7 +190,7 @@ static int pag_config_load_burst_info(struct pag_instance * instance)
return 0;
}
-static int __open_all_device(struct pag_instance * instance)
+static int pag_config_load_device_info(struct pag_instance * instance)
{
int ret = MESA_load_profile_string_nodef(PAG_CFGFILE, "pag", "dev_name",
instance->dev_name, sizeof(instance->dev_name));
@@ -160,11 +201,11 @@ static int __open_all_device(struct pag_instance * instance)
return -1;
}
- char * str_devices[MR_DEVICE_MAX];
+ char * str_devices[PAG_DEVICE_MAX];
int nr_devices;
- nr_devices = rte_strsplit(instance->dev_name, sizeof(instance->dev_name),
- str_devices, MR_DEVICE_MAX, ',');
+ nr_devices = __strsplit(instance->dev_name, sizeof(instance->dev_name),
+ str_devices, PAG_DEVICE_MAX, ',');
if (nr_devices <= 0)
{
@@ -174,22 +215,10 @@ static int __open_all_device(struct pag_instance * instance)
}
for (int i = 0; i < nr_devices; i++)
- {
- raw_socket_t * socket = marsio_raw_socket(str_devices[i],
- instance->nr_rx_stream, instance->nr_tx_stream, 0);
-
- if (socket == NULL)
- {
- PAG_LOG("cannot open device %s.\n", str_devices[i]);
- return -3;
- }
-
- instance->raw_sockets[instance->nr_raw_sockets] = socket;
- instance->nr_raw_sockets++;
-
- PAG_LOG("device opened: %s", str_devices[i]);
- }
+ marsio_option_set(instance->app_name, MARSIO_OPT_RAW_DEVICE,
+ str_devices[i], sizeof(str_devices[i]));
+ instance->nr_devices = nr_devices;
return 0;
}
@@ -220,6 +249,8 @@ static int pag_config(struct pag_instance * instance)
if (ret < 0) return ret;
ret = pag_config_load_stream_info(instance);
if (ret < 0) return ret;
+ ret = pag_config_load_device_info(instance);
+ if (ret < 0) return ret;
return 0;
}
@@ -241,24 +272,16 @@ int pag_open()
return -1;
}
- ret = marsio_init(instance->app_name, instance->coremask,
- instance->autoexit, stderr);
-
+ ret = marsio_init(instance->app_name);
+
if(ret < 0)
{
PAG_LOG("marsio library init failed(ret=%d).", ret);
return -3;
}
- ret = __open_all_device(instance);
- if(ret < 0)
- {
- PAG_LOG("device open error(ret=%d)", ret);
- return -4;
- }
-
if (instance->autoexit)
- mr_on_exit_register(__on_exit_pag_close, NULL);
+ marsio_on_exit_register(__on_exit_pag_close, NULL);
__pag_inited = 1;
return 0;
@@ -266,68 +289,65 @@ int pag_open()
static void inline __free_frames(struct pag_thread_instance * tinstance)
{
- for (int i = 0; i < tinstance->rxmbuf_used; i++)
- {
- rte_pktmbuf_free(tinstance->rxmbuf[i]);
- }
+ marsio_buff_free(tinstance->rxmbuf, tinstance->rxmbuf_used);
return;
}
// �������豸��ȡ���ݰ����ڱ��̻߳�����Ϊ��ʱ����
static int inline __get_frames_from_rtdevice(struct pag_instance * instance,
- struct pag_thread_instance * tinstance)
+ struct pag_thread_instance * tinstance, int sid)
{
// �α���ڵ����ϴ��ձ�����ʱ��˵����һ���ձ��ı���ȫ������
assert((tinstance->rxmbuf_cur >= tinstance->rxmbuf_used));
// һ����rxmbuf_max����������һ��������
- unsigned int cur_socket = tinstance->cur_socket;
- int ret = marsio_raw_recv(instance->raw_sockets[cur_socket],
- tinstance->rxmbuf, tinstance->rxmbuf_max);
+ unsigned int cur_device = tinstance->cur_device;
+ int ret = marsio_raw_recv_burst(cur_device, sid, tinstance->rxmbuf,
+ tinstance->rxmbuf_max);
+
+ if (ret < 0) return ret;
// ���û��������л��ձ��豸
- tinstance->cur_socket = (cur_socket + 1) % instance->nr_raw_sockets;
+ tinstance->cur_device = (cur_device + 1) % instance->nr_devices;
tinstance->rxmbuf_cur = 0;
tinstance->rxmbuf_used = ret;
-
-#ifndef NDEBUG
- for (int i = 0; i < tinstance->rxmbuf_used; i++)
- rte_mbuf_sanity_check(tinstance->rxmbuf[i], 1);
-#endif
assert(tinstance->rxmbuf_used <= tinstance->rxmbuf_max);
return ret;
}
-void * pag_get_frame(int sid __rte_unused)
+#define __PAG_LOOP_TIMES 5
+
+void * pag_get_frame(int sid)
{
struct pag_thread_instance * tinstance = &thread_instance_;
struct pag_instance * instance = &pag_config_;
pag_thread_init(instance, tinstance);
-
- PERF_BEGIN(pag_get_frame);
// �����������ݰ������꣬���ͷţ�Ȼ���ٴ�����ȡ
if (unlikely((tinstance->rxmbuf_cur >= tinstance->rxmbuf_used)))
{
__free_frames(tinstance);
- __get_frames_from_rtdevice(instance, tinstance);
+ __get_frames_from_rtdevice(instance, tinstance, sid);
}
- // ������������ǿյģ�����
- if (unlikely((tinstance->rxmbuf_used == 0)))
- return NULL;
-
+ int loop_times = 0;
+ while (tinstance->rxmbuf_used == 0 && loop_times < instance->looptimes)
+ {
+ __get_frames_from_rtdevice(instance, tinstance, sid);
+ loop_times++;
+ }
+
+ if (unlikely(tinstance->rxmbuf_used == 0)) return NULL;
tinstance->rxmbuf_ctx = tinstance->rxmbuf[tinstance->rxmbuf_cur++];
- PERF_END(pag_get_frame);
- return rte_pktmbuf_mtod(tinstance->rxmbuf_ctx, void *);
+ return (void *)marsio_buff_mtod(tinstance->rxmbuf_ctx);
}
-int pag_get_frame_length(int sid __rte_unused)
+int pag_get_frame_length(int sid)
{
struct pag_thread_instance * tinstance = &thread_instance_;
if (unlikely(tinstance->rxmbuf_ctx == NULL)) return 0;
- return rte_pktmbuf_pkt_len(tinstance->rxmbuf_ctx);
+ return marsio_buff_datalen(tinstance->rxmbuf_ctx);
}
void * pag_get_frame_with_len(int sid, unsigned int * len)
@@ -337,7 +357,7 @@ void * pag_get_frame_with_len(int sid, unsigned int * len)
return frame;
}
-void * pag_get(int sid __rte_unused)
+void * pag_get(int sid)
{
void * frame = pag_get_frame(sid);
if (frame == NULL) return NULL;
@@ -355,9 +375,7 @@ void * pag_get(int sid __rte_unused)
int pag_close()
{
- struct pag_instance * instance = &pag_config_;
- for (int i = 0; i < instance->nr_raw_sockets; i++)
- marsio_raw_close(instance->raw_sockets[i]);
+ marsio_destory();
return 0;
}
diff --git a/runtime/include/mr_runtime.h b/runtime/include/mr_runtime.h
index 098d0a0..94e27f6 100644
--- a/runtime/include/mr_runtime.h
+++ b/runtime/include/mr_runtime.h
@@ -47,6 +47,7 @@ void mr_on_exit_register(void(*exit_fn)(void * arg), void * arg);
void mr_thread_hook();
thread_id_t mr_thread_id();
+thread_id_t mr_gsid_id();
socket_id_t mr_socket_id();
cpu_id_t mr_cpu_id();
app_id_t mr_app_id();
diff --git a/runtime/src/app.c b/runtime/src/app.c
index 9533066..e598966 100644
--- a/runtime/src/app.c
+++ b/runtime/src/app.c
@@ -312,7 +312,7 @@ int __thread_set_affinity(struct appinfo * pinfo,
socket_id_t socket_id = mr_hwinfo_socket_id(cpu_id);
assert(socket_id >= 0 && socket_id < mr_hwinfo_nr_sockets());
- cpu_mask_t thread_cpu_mask = 1 << cpu_id;
+ cpu_mask_t thread_cpu_mask = 1L << cpu_id;
if(__set_affinity(thread_cpu_mask) < 0)
{
MR_LOG(INFO, BASE, "AppInfo, ThreadSetAffinity, "
@@ -336,14 +336,12 @@ int __thread_register_unsafe(struct appinfo * pinfo, thread_id_t suppose_sid)
// 没有注册过,注册一个新的线程
if (tinfo != NULL)
{
- MR_LOG(INFO, BASE, "AppInfo, ThreadRegister"
- "Thread %d in Process %s existed, recover it.\n",
+ MR_LOG(INFO, BASE, "Thread %d in Application %s existed, recoverd.\n",
suppose_sid, pinfo->symbol);
}
else
{
- MR_LOG(INFO, BASE, "AppInfo, ThreadRegister, "
- "Thread %d in Process %s, create new thread.\n",
+ MR_LOG(INFO, BASE, "Thread %d in Application %s registed as a new thread. \n",
suppose_sid, pinfo->symbol);
tinfo = __thread_new_unsafe(pinfo);
}
@@ -351,8 +349,7 @@ int __thread_register_unsafe(struct appinfo * pinfo, thread_id_t suppose_sid)
// 检测tinfo是否为空,此时为空就是异常情况了
if(unlikely(tinfo == NULL))
{
- MR_LOG(WARNING, BASE, "AppInfo, ThreadRegister, "
- "Thread %d in Process %s Info Structure is NULL, failed.\n",
+ MR_LOG(WARNING, BASE, "Thread %d in Application %s Info Structure is NULL, failed.\n",
suppose_sid, pinfo->symbol);
return -1;
}
@@ -363,14 +360,12 @@ int __thread_register_unsafe(struct appinfo * pinfo, thread_id_t suppose_sid)
if(__thread_set_affinity(pinfo, tinfo) < 0)
{
- MR_LOG(WARNING, BASE, "AppInfo, ThreadRegister, "
- "Thread %d in Process %s, SetThreadAffinity failed.\n",
+ MR_LOG(WARNING, BASE, "Thread %d in Application %s, SetThreadAffinity failed.\n",
tinfo->sid, pinfo->symbol);
return -2;
}
- MR_LOG(DEBUG, BASE, "AppInfo, ThreadRegister, "
- "ThreadID=%d, GThreadID=%d, App=%s, thread registered. \n",
+ MR_LOG(DEBUG, BASE, "Thread Registered (ThreadID=%d, GThreadID=%d, App=%s). \n",
tinfo->sid, tinfo->gsid, pinfo->symbol);
return 0;
@@ -539,6 +534,12 @@ thread_id_t mr_thread_id()
return currect_thread_info->sid;
}
+thread_id_t mr_gsid_id()
+{
+ assert(currect_thread_info != NULL);
+ return currect_thread_info->gsid;
+}
+
socket_id_t mr_socket_id()
{
assert(currect_thread_info != NULL);
diff --git a/service/CMakeLists.txt b/service/CMakeLists.txt
index 4a00981..dafd1da 100644
--- a/service/CMakeLists.txt
+++ b/service/CMakeLists.txt
@@ -1,14 +1,11 @@
find_package(DPDK REQUIRED)
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_SOURCE_DIR}/include/extern)
-include_directories(${CMAKE_SOURCE_DIR}/include/internal)
include_directories(${DPDK_INCLUDE_DIR})
include_directories(include)
add_definitions(${DPDK_C_PREDEFINED})
-add_executable(zcpd src/core.c src/runtime.c src/config.c src/register.c src/rxtx.c src/ldbc.c)
-target_link_libraries(zcpd ${DPDK_LIBRARY} MESA_prof_load_static)
+add_executable(zcpd src/cJSON.c src/core.c src/config.c src/register.c src/rxtx.c src/ldbc.c src/monit.c)
+target_link_libraries(zcpd MESA_prof_load_static ${DPDK_LIBRARY})
target_link_libraries(zcpd rt pthread dl core stack)
target_include_directories(zcpd INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/")
diff --git a/service/include/sc_common.h b/service/include/sc_common.h
index 394aaee..d2254f3 100644
--- a/service/include/sc_common.h
+++ b/service/include/sc_common.h
@@ -16,41 +16,35 @@ struct sc_device
/* �������� */
char symbol[MR_STRING_MAX];
/* ������� */
- mr_dev_t * dev;
- /* ����ʹ�� */
- unsigned int en_mr_dev;
+ struct mr_dev * dev;
+ /* Э��ջ�豸��� */
+ struct sk_dev_desc * sk_dev;
+ /* ����ʱ�豸������ */
+ struct rtdev_desc * rt_dev;
/* �������� */
struct mr_dev_param mr_dev_param;
- /* Э��ջ�豸ʹ�� */
- unsigned int en_sk_dev;
/* Э��ջ�豸���� */
struct sk_dev_param sk_dev_param;
+ /* Э��ջ�豸ʹ�� */
+ unsigned int en_sk_dev;
+ /* ����ʹ�� */
+ unsigned int en_mr_dev;
+ /* ����ʱ�豸ʹ�� */
+ unsigned int en_rt_dev;
+ /* ����ʱ����������Դ */
+ struct mr_dev_q * rx_devq[MR_SID_MAX];
+ struct mr_dev_q * tx_devq[MR_SID_MAX];
};
TAILQ_HEAD(sc_device_list, sc_device);
-struct sc_app
-{
- TAILQ_ENTRY(sc_app) next;
- char symbol[MR_STRING_MAX];
- cpu_mask_t cpu_mask;
- unsigned int rxstream;
- unsigned int txstream;
-
- //TODO: ÿ��Ӧ�ÿ��Է��ʲ�ͬ���豸
- //TODO: ��κ�Socket���
- struct sc_device_list device_list;
-};
-
-TAILQ_HEAD(sc_app_list, sc_app);
-
// ���طֵ���ʽ
enum _e_dist_mode
{
/* ������Ԫ���ϣ */
- LDBC_DIST_SIMPLE_TUPLE2 = 0,
+ LDBC_DIST_OUTER_TUPLE2 = 0,
/* ������Ԫ���ϣ */
- LDBC_DIST_SIMPLE_TUPLE4 = 1,
+ LDBC_DIST_OUTER_TUPLE4 = 1,
/* ʹ��Ӳ�������� */
LDBC_DIST_HARDWARE = 2
};
@@ -67,6 +61,40 @@ static inline const char * str_dist_mode(unsigned int distmode)
return NULL;
}
+struct sc_param
+{
+ /* SC���������߳����� */
+ unsigned int nr_serv_thread;
+ /* ���Ĵ���·����С */
+ unsigned int sz_tunnel;
+ /* ���Ĵ��ݻ�������С */
+ unsigned int sz_buffer;
+ /* �������Ĵ������� */
+ unsigned int sz_burst;
+ /* �û����ijش�С */
+ unsigned int nr_user_direct_pktmbuf;
+ /* �û����ijش�С */
+ unsigned int nr_user_indirect_pktmbuf;
+ /* �û����ij�Cache��С */
+ unsigned int sz_user_pktmbuf_cache;
+ /* �û����ij����ݴ�С */
+ unsigned int sz_user_pktmbuf;
+ /* ���طֵ���ʽ */
+ unsigned int distmode;
+ /* Ӳ��RSS��ʽ */
+ unsigned int rssmode;
+};
+
+struct sc_ctrlzone
+{
+ TAILQ_ENTRY(sc_ctrlzone) next;
+ char symbol[MR_SYMBOL_MAX];
+ unsigned int id;
+ unsigned int size;
+};
+
+TAILQ_HEAD(sc_ctrlzone_list, sc_ctrlzone);
+
/* Service Instance */
struct sc_instance
{
@@ -76,52 +104,24 @@ struct sc_instance
char local_cfgfile[MR_STRING_MAX];
/* ������־�ļ�λ�� */
char local_logfile[MR_STRING_MAX];
+ /* ״̬����ļ� */
+ char local_monitfile[MR_STRING_MAX];
/* CPU���룬�����������CPU������ */
cpu_mask_t cpu_mask;
/* ���õ��豸�б� */
struct sc_device_list device_list;
+ /* ������ע����Ϣ */
+ struct sc_ctrlzone_list ctrlzone_list;
/* ���õ��豸���� */
unsigned int nr_devs;
- /* Ӧ���б� */
- struct sc_app_list app_list;
- /* �ձ���·��VNode����С */
- unsigned int sz_rxvnode_ring;
- /* ������·��VNode����С */
- unsigned int sz_txvnode_ring;
- /* �ձ���·��VNode��������С */
- unsigned int sz_rxvnode_buffer;
- /* ������·��VNode��������С */
- unsigned int sz_txvnode_buffer;
- /* �ձ���·��Burst��С*/
- unsigned int sz_rx_burst;
- /* ������·��Burst��С*/
- unsigned int sz_tx_burst;
- /* ���طֵ���ʽ */
- unsigned int distmode;
- /* Ӳ��RSS��ʽ */
- unsigned int rssmode;
+ /* ������� */
+ struct sc_param sc_param;
/* Э��ջ���� */
- struct mr_stack_param sk_param;
-
+ struct sk_param sk_param;
/* ���Ŀ�ȫ�־�� */
struct mr_core_instance * core_instance;
/* Э��ջȫ�־�� */
- struct mr_stack_instance * sk_instance;
-};
-
-// �й��豸������ʱ��Դ��ÿ���̣߳�ÿ���豸һ���ṹ��
-struct sc_rt_device
-{
- /* ��ʵ�豸������ */
- mr_devq_t * devq;
- /* ��Ӧ������ʱ�豸������ */
- struct mr_rtdev_stream * rtstream;
- /* ��Ӧ��Э��ջ�豸������ */
- struct sk_dev_desc * sk_dev;
-};
-
-struct sc_thread_instance
-{
- unsigned int nr_devices;
- struct sc_rt_device * rt_dev;
+ struct sk_instance * sk_instance;
+ /* Э��ջ����Ӧ�þ�� */
+ struct sk_app_instance * sk_serv_instance;
}; \ No newline at end of file
diff --git a/service/src/cJSON.c b/service/src/cJSON.c
new file mode 100644
index 0000000..766e558
--- /dev/null
+++ b/service/src/cJSON.c
@@ -0,0 +1,2233 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cJSON.h"
+
+/* Determine the number of bits that an integer has using the preprocessor */
+#if INT_MAX == 32767
+ /* 16 bits */
+ #define INTEGER_SIZE 0x0010
+#elif INT_MAX == 2147483647
+ /* 32 bits */
+ #define INTEGER_SIZE 0x0100
+#elif INT_MAX == 9223372036854775807
+ /* 64 bits */
+ #define INTEGER_SIZE 0x1000
+#else
+ #error "Failed to determine the size of an integer"
+#endif
+
+/* define our own boolean type */
+typedef int cjbool;
+#define true ((cjbool)1)
+#define false ((cjbool)0)
+
+static const char *global_ep = NULL;
+
+const char *cJSON_GetErrorPtr(void)
+{
+ return global_ep;
+}
+
+/* case insensitive strcmp */
+static int cJSON_strcasecmp(const char *s1, const char *s2)
+{
+ if (!s1)
+ {
+ return (s1 == s2) ? 0 : 1; /* both NULL? */
+ }
+ if (!s2)
+ {
+ return 1;
+ }
+ for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2)
+ {
+ if (*s1 == '\0')
+ {
+ return 0;
+ }
+ }
+
+ return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+}
+
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static char* cJSON_strdup(const char* str)
+{
+ size_t len = 0;
+ char *copy = NULL;
+
+ len = strlen(str) + 1;
+ if (!(copy = (char*)cJSON_malloc(len)))
+ {
+ return NULL;
+ }
+ memcpy(copy, str, len);
+
+ return copy;
+}
+
+void cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (!hooks)
+ {
+ /* Reset hooks */
+ cJSON_malloc = malloc;
+ cJSON_free = free;
+ return;
+ }
+
+ cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
+ cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(void)
+{
+ cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
+ if (node)
+ {
+ memset(node, '\0', sizeof(cJSON));
+ }
+
+ return node;
+}
+
+/* Delete a cJSON structure. */
+void cJSON_Delete(cJSON *c)
+{
+ cJSON *next = NULL;
+ while (c)
+ {
+ next = c->next;
+ if (!(c->type & cJSON_IsReference) && c->child)
+ {
+ cJSON_Delete(c->child);
+ }
+ if (!(c->type & cJSON_IsReference) && c->valuestring)
+ {
+ cJSON_free(c->valuestring);
+ }
+ if (!(c->type & cJSON_StringIsConst) && c->string)
+ {
+ cJSON_free(c->string);
+ }
+ cJSON_free(c);
+ c = next;
+ }
+}
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static const char *parse_number(cJSON *item, const char *num)
+{
+ double n = 0;
+ double sign = 1;
+ double scale = 0;
+ int subscale = 0;
+ int signsubscale = 1;
+
+ /* Has sign? */
+ if (*num == '-')
+ {
+ sign = -1;
+ num++;
+ }
+ /* is zero */
+ if (*num == '0')
+ {
+ num++;
+ }
+ /* Number? */
+ if ((*num >= '1') && (*num <= '9'))
+ {
+ do
+ {
+ n = (n * 10.0) + (*num++ - '0');
+ }
+ while ((*num >= '0') && (*num<='9'));
+ }
+ /* Fractional part? */
+ if ((*num == '.') && (num[1] >= '0') && (num[1] <= '9'))
+ {
+ num++;
+ do
+ {
+ n = (n *10.0) + (*num++ - '0');
+ scale--;
+ } while ((*num >= '0') && (*num <= '9'));
+ }
+ /* Exponent? */
+ if ((*num == 'e') || (*num == 'E'))
+ {
+ num++;
+ /* With sign? */
+ if (*num == '+')
+ {
+ num++;
+ }
+ else if (*num == '-')
+ {
+ signsubscale = -1;
+ num++;
+ }
+ /* Number? */
+ while ((*num>='0') && (*num<='9'))
+ {
+ subscale = (subscale * 10) + (*num++ - '0');
+ }
+ }
+
+ /* number = +/- number.fraction * 10^+/- exponent */
+ n = sign * n * pow(10.0, (scale + subscale * signsubscale));
+
+ item->valuedouble = n;
+ item->valueint = (int)n;
+ item->type = cJSON_Number;
+
+ return num;
+}
+
+/* calculate the next largest power of 2 */
+static int pow2gt (int x)
+{
+ --x;
+
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+#if INTEGER_SIZE & 0x1110 /* at least 16 bit */
+ x |= x >> 8;
+#endif
+#if INTEGER_SIZE & 0x1100 /* at least 32 bit */
+ x |= x >> 16;
+#endif
+#if INT_SIZE & 0x1000 /* 64 bit */
+ x |= x >> 32;
+#endif
+
+ return x + 1;
+}
+
+typedef struct
+{
+ char *buffer;
+ int length;
+ int offset;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static char* ensure(printbuffer *p, int needed)
+{
+ char *newbuffer = NULL;
+ int newsize = 0;
+ if (!p || !p->buffer)
+ {
+ return NULL;
+ }
+ needed += p->offset;
+ if (needed <= p->length)
+ {
+ return p->buffer + p->offset;
+ }
+
+ newsize = pow2gt(needed);
+ newbuffer = (char*)cJSON_malloc(newsize);
+ if (!newbuffer)
+ {
+ cJSON_free(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ if (newbuffer)
+ {
+ memcpy(newbuffer, p->buffer, p->length);
+ }
+ cJSON_free(p->buffer);
+ p->length = newsize;
+ p->buffer = newbuffer;
+
+ return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer */
+static int update(const printbuffer *p)
+{
+ char *str = NULL;
+ if (!p || !p->buffer)
+ {
+ return 0;
+ }
+ str = p->buffer + p->offset;
+
+ return p->offset + strlen(str);
+}
+
+/* Render the number nicely from the given item into a string. */
+static char *print_number(const cJSON *item, printbuffer *p)
+{
+ char *str = NULL;
+ double d = item->valuedouble;
+ /* special case for 0. */
+ if (d == 0)
+ {
+ if (p)
+ {
+ str = ensure(p, 2);
+ }
+ else
+ {
+ str = (char*)cJSON_malloc(2);
+ }
+ if (str)
+ {
+ strcpy(str,"0");
+ }
+ }
+ /* value is an int */
+ else if ((fabs(((double)item->valueint) - d) <= DBL_EPSILON) && (d <= INT_MAX) && (d >= INT_MIN))
+ {
+ if (p)
+ {
+ str = ensure(p, 21);
+ }
+ else
+ {
+ /* 2^64+1 can be represented in 21 chars. */
+ str = (char*)cJSON_malloc(21);
+ }
+ if (str)
+ {
+ sprintf(str, "%d", item->valueint);
+ }
+ }
+ /* value is a floating point number */
+ else
+ {
+ if (p)
+ {
+ /* This is a nice tradeoff. */
+ str = ensure(p, 64);
+ }
+ else
+ {
+ /* This is a nice tradeoff. */
+ str=(char*)cJSON_malloc(64);
+ }
+ if (str)
+ {
+ /* This checks for NaN and Infinity */
+ if ((d * 0) != 0)
+ {
+ sprintf(str, "null");
+ }
+ else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60))
+ {
+ sprintf(str, "%.0f", d);
+ }
+ else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9))
+ {
+ sprintf(str, "%e", d);
+ }
+ else
+ {
+ sprintf(str, "%f", d);
+ }
+ }
+ }
+ return str;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const char *str)
+{
+ unsigned h = 0;
+ /* first digit */
+ if ((*str >= '0') && (*str <= '9'))
+ {
+ h += (*str) - '0';
+ }
+ else if ((*str >= 'A') && (*str <= 'F'))
+ {
+ h += 10 + (*str) - 'A';
+ }
+ else if ((*str >= 'a') && (*str <= 'f'))
+ {
+ h += 10 + (*str) - 'a';
+ }
+ else /* invalid */
+ {
+ return 0;
+ }
+
+
+ /* second digit */
+ h = h << 4;
+ str++;
+ if ((*str >= '0') && (*str <= '9'))
+ {
+ h += (*str) - '0';
+ }
+ else if ((*str >= 'A') && (*str <= 'F'))
+ {
+ h += 10 + (*str) - 'A';
+ }
+ else if ((*str >= 'a') && (*str <= 'f'))
+ {
+ h += 10 + (*str) - 'a';
+ }
+ else /* invalid */
+ {
+ return 0;
+ }
+
+ /* third digit */
+ h = h << 4;
+ str++;
+ if ((*str >= '0') && (*str <= '9'))
+ {
+ h += (*str) - '0';
+ }
+ else if ((*str >= 'A') && (*str <= 'F'))
+ {
+ h += 10 + (*str) - 'A';
+ }
+ else if ((*str >= 'a') && (*str <= 'f'))
+ {
+ h += 10 + (*str) - 'a';
+ }
+ else /* invalid */
+ {
+ return 0;
+ }
+
+ /* fourth digit */
+ h = h << 4;
+ str++;
+ if ((*str >= '0') && (*str <= '9'))
+ {
+ h += (*str) - '0';
+ }
+ else if ((*str >= 'A') && (*str <= 'F'))
+ {
+ h += 10 + (*str) - 'A';
+ }
+ else if ((*str >= 'a') && (*str <= 'f'))
+ {
+ h += 10 + (*str) - 'a';
+ }
+ else /* invalid */
+ {
+ return 0;
+ }
+
+ return h;
+}
+
+/* first bytes of UTF8 encoding for a given length in bytes */
+static const unsigned char firstByteMark[7] =
+{
+ 0x00, /* should never happen */
+ 0x00, /* 0xxxxxxx */
+ 0xC0, /* 110xxxxx */
+ 0xE0, /* 1110xxxx */
+ 0xF0, /* 11110xxx */
+ 0xF8,
+ 0xFC
+};
+
+/* Parse the input text into an unescaped cstring, and populate item. */
+static const char *parse_string(cJSON *item, const char *str, const char **ep)
+{
+ const char *ptr = str + 1;
+ const char *end_ptr =str + 1;
+ char *ptr2 = NULL;
+ char *out = NULL;
+ int len = 0;
+ unsigned uc = 0;
+ unsigned uc2 = 0;
+
+ /* not a string! */
+ if (*str != '\"')
+ {
+ *ep = str;
+ return NULL;
+ }
+
+ while ((*end_ptr != '\"') && *end_ptr && ++len)
+ {
+ if (*end_ptr++ == '\\')
+ {
+ if (*end_ptr == '\0')
+ {
+ /* prevent buffer overflow when last input character is a backslash */
+ return NULL;
+ }
+ /* Skip escaped quotes. */
+ end_ptr++;
+ }
+ }
+
+ /* This is at most how long we need for the string, roughly. */
+ out = (char*)cJSON_malloc(len + 1);
+ if (!out)
+ {
+ return NULL;
+ }
+ item->valuestring = out; /* assign here so out will be deleted during cJSON_Delete() later */
+ item->type = cJSON_String;
+
+ ptr = str + 1;
+ ptr2 = out;
+ /* loop through the string literal */
+ while (ptr < end_ptr)
+ {
+ if (*ptr != '\\')
+ {
+ *ptr2++ = *ptr++;
+ }
+ /* escape sequence */
+ else
+ {
+ ptr++;
+ switch (*ptr)
+ {
+ case 'b':
+ *ptr2++ = '\b';
+ break;
+ case 'f':
+ *ptr2++ = '\f';
+ break;
+ case 'n':
+ *ptr2++ = '\n';
+ break;
+ case 'r':
+ *ptr2++ = '\r';
+ break;
+ case 't':
+ *ptr2++ = '\t';
+ break;
+ case '\"':
+ case '\\':
+ case '/':
+ *ptr2++ = *ptr;
+ break;
+ case 'u':
+ /* transcode utf16 to utf8. See RFC2781 and RFC3629. */
+ uc = parse_hex4(ptr + 1); /* get the unicode char. */
+ ptr += 4;
+ if (ptr >= end_ptr)
+ {
+ /* invalid */
+ *ep = str;
+ return NULL;
+ }
+ /* check for invalid. */
+ if (((uc >= 0xDC00) && (uc <= 0xDFFF)) || (uc == 0))
+ {
+ *ep = str;
+ return NULL;
+ }
+
+ /* UTF16 surrogate pairs. */
+ if ((uc >= 0xD800) && (uc<=0xDBFF))
+ {
+ if ((ptr + 6) > end_ptr)
+ {
+ /* invalid */
+ *ep = str;
+ return NULL;
+ }
+ if ((ptr[1] != '\\') || (ptr[2] != 'u'))
+ {
+ /* missing second-half of surrogate. */
+ *ep = str;
+ return NULL;
+ }
+ uc2 = parse_hex4(ptr + 3);
+ ptr += 6; /* \uXXXX */
+ if ((uc2 < 0xDC00) || (uc2 > 0xDFFF))
+ {
+ /* invalid second-half of surrogate. */
+ *ep = str;
+ return NULL;
+ }
+ /* calculate unicode codepoint from the surrogate pair */
+ uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
+ }
+
+ /* encode as UTF8
+ * takes at maximum 4 bytes to encode:
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ len = 4;
+ if (uc < 0x80)
+ {
+ /* normal ascii, encoding 0xxxxxxx */
+ len = 1;
+ }
+ else if (uc < 0x800)
+ {
+ /* two bytes, encoding 110xxxxx 10xxxxxx */
+ len = 2;
+ }
+ else if (uc < 0x10000)
+ {
+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+ len = 3;
+ }
+ ptr2 += len;
+
+ switch (len) {
+ case 4:
+ /* 10xxxxxx */
+ *--ptr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ case 3:
+ /* 10xxxxxx */
+ *--ptr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ case 2:
+ /* 10xxxxxx */
+ *--ptr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ case 1:
+ /* depending on the length in bytes this determines the
+ * encoding ofthe first UTF8 byte */
+ *--ptr2 = (uc | firstByteMark[len]);
+ }
+ ptr2 += len;
+ break;
+ default:
+ *ep = str;
+ return NULL;
+ }
+ ptr++;
+ }
+ }
+ *ptr2 = '\0';
+ if (*ptr == '\"')
+ {
+ ptr++;
+ }
+
+ return ptr;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static char *print_string_ptr(const char *str, printbuffer *p)
+{
+ const char *ptr = NULL;
+ char *ptr2 = NULL;
+ char *out = NULL;
+ int len = 0;
+ cjbool flag = false;
+ unsigned char token = '\0';
+
+ /* empty string */
+ if (!str)
+ {
+ if (p)
+ {
+ out = ensure(p, 3);
+ }
+ else
+ {
+ out = (char*)cJSON_malloc(3);
+ }
+ if (!out)
+ {
+ return NULL;
+ }
+ strcpy(out, "\"\"");
+
+ return out;
+ }
+
+ /* set "flag" to 1 if something needs to be escaped */
+ for (ptr = str; *ptr; ptr++)
+ {
+ flag |= (((*ptr > 0) && (*ptr < 32)) /* unprintable characters */
+ || (*ptr == '\"') /* double quote */
+ || (*ptr == '\\')) /* backslash */
+ ? 1
+ : 0;
+ }
+ /* no characters have to be escaped */
+ if (!flag)
+ {
+ len = ptr - str;
+ if (p)
+ {
+ out = ensure(p, len + 3);
+ }
+ else
+ {
+ out = (char*)cJSON_malloc(len + 3);
+ }
+ if (!out)
+ {
+ return NULL;
+ }
+
+ ptr2 = out;
+ *ptr2++ = '\"';
+ strcpy(ptr2, str);
+ ptr2[len] = '\"';
+ ptr2[len + 1] = '\0';
+
+ return out;
+ }
+
+ ptr = str;
+ /* calculate additional space that is needed for escaping */
+ while ((token = *ptr) && ++len)
+ {
+ if (strchr("\"\\\b\f\n\r\t", token))
+ {
+ len++; /* +1 for the backslash */
+ }
+ else if (token < 32)
+ {
+ len += 5; /* +5 for \uXXXX */
+ }
+ ptr++;
+ }
+
+ if (p)
+ {
+ out = ensure(p, len + 3);
+ }
+ else
+ {
+ out = (char*)cJSON_malloc(len + 3);
+ }
+ if (!out)
+ {
+ return NULL;
+ }
+
+ ptr2 = out;
+ ptr = str;
+ *ptr2++ = '\"';
+ /* copy the string */
+ while (*ptr)
+ {
+ if (((unsigned char)*ptr > 31) && (*ptr != '\"') && (*ptr != '\\'))
+ {
+ /* normal character, copy */
+ *ptr2++ = *ptr++;
+ }
+ else
+ {
+ /* character needs to be escaped */
+ *ptr2++ = '\\';
+ switch (token = *ptr++)
+ {
+ case '\\':
+ *ptr2++ = '\\';
+ break;
+ case '\"':
+ *ptr2++ = '\"';
+ break;
+ case '\b':
+ *ptr2++ = 'b';
+ break;
+ case '\f':
+ *ptr2++ = 'f';
+ break;
+ case '\n':
+ *ptr2++ = 'n';
+ break;
+ case '\r':
+ *ptr2++ = 'r';
+ break;
+ case '\t':
+ *ptr2++ = 't';
+ break;
+ default:
+ /* escape and print as unicode codepoint */
+ sprintf(ptr2, "u%04x", token);
+ ptr2 += 5;
+ break;
+ }
+ }
+ }
+ *ptr2++ = '\"';
+ *ptr2++ = '\0';
+
+ return out;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static char *print_string(const cJSON *item, printbuffer *p)
+{
+ return print_string_ptr(item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static const char *parse_value(cJSON *item, const char *value, const char **ep);
+static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p);
+static const char *parse_array(cJSON *item, const char *value, const char **ep);
+static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p);
+static const char *parse_object(cJSON *item, const char *value, const char **ep);
+static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p);
+
+/* Utility to jump whitespace and cr/lf */
+static const char *skip(const char *in)
+{
+ while (in && *in && ((unsigned char)*in<=32))
+ {
+ in++;
+ }
+
+ return in;
+}
+
+/* Parse an object - create a new root, and populate. */
+cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjbool require_null_terminated)
+{
+ const char *end = NULL;
+ /* use global error pointer if no specific one was given */
+ const char **ep = return_parse_end ? return_parse_end : &global_ep;
+ cJSON *c = cJSON_New_Item();
+ *ep = NULL;
+ if (!c) /* memory fail */
+ {
+ return NULL;
+ }
+
+ end = parse_value(c, skip(value), ep);
+ if (!end)
+ {
+ /* parse failure. ep is set. */
+ cJSON_Delete(c);
+ return NULL;
+ }
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated)
+ {
+ end = skip(end);
+ if (*end)
+ {
+ cJSON_Delete(c);
+ *ep = end;
+ return NULL;
+ }
+ }
+ if (return_parse_end)
+ {
+ *return_parse_end = end;
+ }
+
+ return c;
+}
+
+/* Default options for cJSON_Parse */
+cJSON *cJSON_Parse(const char *value)
+{
+ return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+/* Render a cJSON item/entity/structure to text. */
+char *cJSON_Print(const cJSON *item)
+{
+ return print_value(item, 0, 1, 0);
+}
+
+char *cJSON_PrintUnformatted(const cJSON *item)
+{
+ return print_value(item, 0, 0, 0);
+}
+
+char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt)
+{
+ printbuffer p;
+ p.buffer = (char*)cJSON_malloc(prebuffer);
+ if (!p.buffer)
+ {
+ return NULL;
+ }
+ p.length = prebuffer;
+ p.offset = 0;
+
+ return print_value(item, 0, fmt, &p);
+}
+
+
+/* Parser core - when encountering text, process appropriately. */
+static const char *parse_value(cJSON *item, const char *value, const char **ep)
+{
+ if (!value)
+ {
+ /* Fail on null. */
+ return NULL;
+ }
+
+ /* parse the different types of values */
+ if (!strncmp(value, "null", 4))
+ {
+ item->type = cJSON_NULL;
+ return value + 4;
+ }
+ if (!strncmp(value, "false", 5))
+ {
+ item->type = cJSON_False;
+ return value + 5;
+ }
+ if (!strncmp(value, "true", 4))
+ {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ return value + 4;
+ }
+ if (*value == '\"')
+ {
+ return parse_string(item, value, ep);
+ }
+ if ((*value == '-') || ((*value >= '0') && (*value <= '9')))
+ {
+ return parse_number(item, value);
+ }
+ if (*value == '[')
+ {
+ return parse_array(item, value, ep);
+ }
+ if (*value == '{')
+ {
+ return parse_object(item, value, ep);
+ }
+
+ /* failure. */
+ *ep = value;
+ return NULL;
+}
+
+/* Render a value to text. */
+static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
+{
+ char *out = NULL;
+
+ if (!item)
+ {
+ return NULL;
+ }
+ if (p)
+ {
+ switch ((item->type) & 0xFF)
+ {
+ case cJSON_NULL:
+ out = ensure(p, 5);
+ if (out)
+ {
+ strcpy(out, "null");
+ }
+ break;
+ case cJSON_False:
+ out = ensure(p, 6);
+ if (out)
+ {
+ strcpy(out, "false");
+ }
+ break;
+ case cJSON_True:
+ out = ensure(p, 5);
+ if (out)
+ {
+ strcpy(out, "true");
+ }
+ break;
+ case cJSON_Number:
+ out = print_number(item, p);
+ break;
+ case cJSON_String:
+ out = print_string(item, p);
+ break;
+ case cJSON_Array:
+ out = print_array(item, depth, fmt, p);
+ break;
+ case cJSON_Object:
+ out = print_object(item, depth, fmt, p);
+ break;
+ }
+ }
+ else
+ {
+ switch ((item->type) & 0xFF)
+ {
+ case cJSON_NULL:
+ out = cJSON_strdup("null");
+ break;
+ case cJSON_False:
+ out = cJSON_strdup("false");
+ break;
+ case cJSON_True:
+ out = cJSON_strdup("true");
+ break;
+ case cJSON_Number:
+ out = print_number(item, 0);
+ break;
+ case cJSON_String:
+ out = print_string(item, 0);
+ break;
+ case cJSON_Array:
+ out = print_array(item, depth, fmt, 0);
+ break;
+ case cJSON_Object:
+ out = print_object(item, depth, fmt, 0);
+ break;
+ }
+ }
+
+ return out;
+}
+
+/* Build an array from input text. */
+static const char *parse_array(cJSON *item,const char *value,const char **ep)
+{
+ cJSON *child = NULL;
+ if (*value != '[')
+ {
+ /* not an array! */
+ *ep = value;
+ return NULL;
+ }
+
+ item->type = cJSON_Array;
+ value = skip(value + 1);
+ if (*value == ']')
+ {
+ /* empty array. */
+ return value + 1;
+ }
+
+ item->child = child = cJSON_New_Item();
+ if (!item->child)
+ {
+ /* memory fail */
+ return NULL;
+ }
+ /* skip any spacing, get the value. */
+ value = skip(parse_value(child, skip(value), ep));
+ if (!value)
+ {
+ return NULL;
+ }
+
+ /* loop through the comma separated array elements */
+ while (*value == ',')
+ {
+ cJSON *new_item = NULL;
+ if (!(new_item = cJSON_New_Item()))
+ {
+ /* memory fail */
+ return NULL;
+ }
+ /* add new item to end of the linked list */
+ child->next = new_item;
+ new_item->prev = child;
+ child = new_item;
+
+ /* go to the next comma */
+ value = skip(parse_value(child, skip(value + 1), ep));
+ if (!value)
+ {
+ /* memory fail */
+ return NULL;
+ }
+ }
+
+ if (*value == ']')
+ {
+ /* end of array */
+ return value + 1;
+ }
+
+ /* malformed. */
+ *ep = value;
+
+ return NULL;
+}
+
+/* Render an array to text */
+static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
+{
+ char **entries;
+ char *out = NULL;
+ char *ptr = NULL;
+ char *ret = NULL;
+ int len = 5;
+ cJSON *child = item->child;
+ int numentries = 0;
+ int i = 0;
+ cjbool fail = false;
+ size_t tmplen = 0;
+
+ /* How many entries in the array? */
+ while (child)
+ {
+ numentries++;
+ child = child->next;
+ }
+
+ /* Explicitly handle numentries == 0 */
+ if (!numentries)
+ {
+ if (p)
+ {
+ out = ensure(p, 3);
+ }
+ else
+ {
+ out = (char*)cJSON_malloc(3);
+ }
+ if (out)
+ {
+ strcpy(out,"[]");
+ }
+
+ return out;
+ }
+
+ if (p)
+ {
+ /* Compose the output array. */
+ /* opening square bracket */
+ i = p->offset;
+ ptr = ensure(p, 1);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ *ptr = '[';
+ p->offset++;
+
+ child = item->child;
+ while (child && !fail)
+ {
+ print_value(child, depth + 1, fmt, p);
+ p->offset = update(p);
+ if (child->next)
+ {
+ len = fmt ? 2 : 1;
+ ptr = ensure(p, len + 1);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ *ptr++ = ',';
+ if(fmt)
+ {
+ *ptr++ = ' ';
+ }
+ *ptr = '\0';
+ p->offset += len;
+ }
+ child = child->next;
+ }
+ ptr = ensure(p, 2);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ *ptr++ = ']';
+ *ptr = '\0';
+ out = (p->buffer) + i;
+ }
+ else
+ {
+ /* Allocate an array to hold the pointers to all printed values */
+ entries = (char**)cJSON_malloc(numentries * sizeof(char*));
+ if (!entries)
+ {
+ return NULL;
+ }
+ memset(entries, '\0', numentries * sizeof(char*));
+
+ /* Retrieve all the results: */
+ child = item->child;
+ while (child && !fail)
+ {
+ ret = print_value(child, depth + 1, fmt, 0);
+ entries[i++] = ret;
+ if (ret)
+ {
+ len += strlen(ret) + 2 + (fmt ? 1 : 0);
+ }
+ else
+ {
+ fail = true;
+ }
+ child = child->next;
+ }
+
+ /* If we didn't fail, try to malloc the output string */
+ if (!fail)
+ {
+ out = (char*)cJSON_malloc(len);
+ }
+ /* If that fails, we fail. */
+ if (!out)
+ {
+ fail = true;
+ }
+
+ /* Handle failure. */
+ if (fail)
+ {
+ /* free all the entries in the array */
+ for (i = 0; i < numentries; i++)
+ {
+ if (entries[i])
+ {
+ cJSON_free(entries[i]);
+ }
+ }
+ cJSON_free(entries);
+ return NULL;
+ }
+
+ /* Compose the output array. */
+ *out='[';
+ ptr = out + 1;
+ *ptr = '\0';
+ for (i = 0; i < numentries; i++)
+ {
+ tmplen = strlen(entries[i]);
+ memcpy(ptr, entries[i], tmplen);
+ ptr += tmplen;
+ if (i != (numentries - 1))
+ {
+ *ptr++ = ',';
+ if(fmt)
+ {
+ *ptr++ = ' ';
+ }
+ *ptr = '\0';
+ }
+ cJSON_free(entries[i]);
+ }
+ cJSON_free(entries);
+ *ptr++ = ']';
+ *ptr++ = '\0';
+ }
+
+ return out;
+}
+
+/* Build an object from the text. */
+static const char *parse_object(cJSON *item, const char *value, const char **ep)
+{
+ cJSON *child = NULL;
+ if (*value != '{')
+ {
+ /* not an object! */
+ *ep = value;
+ return NULL;
+ }
+
+ item->type = cJSON_Object;
+ value = skip(value + 1);
+ if (*value == '}')
+ {
+ /* empty object. */
+ return value + 1;
+ }
+
+ child = cJSON_New_Item();
+ item->child = child;
+ if (!item->child)
+ {
+ return NULL;
+ }
+ /* parse first key */
+ value = skip(parse_string(child, skip(value), ep));
+ if (!value)
+ {
+ return NULL;
+ }
+ /* use string as key, not value */
+ child->string = child->valuestring;
+ child->valuestring = NULL;
+
+ if (*value != ':')
+ {
+ /* invalid object. */
+ *ep = value;
+ return NULL;
+ }
+ /* skip any spacing, get the value. */
+ value = skip(parse_value(child, skip(value + 1), ep));
+ if (!value)
+ {
+ return NULL;
+ }
+
+ while (*value == ',')
+ {
+ cJSON *new_item = NULL;
+ if (!(new_item = cJSON_New_Item()))
+ {
+ /* memory fail */
+ return NULL;
+ }
+ /* add to linked list */
+ child->next = new_item;
+ new_item->prev = child;
+
+ child = new_item;
+ value = skip(parse_string(child, skip(value + 1), ep));
+ if (!value)
+ {
+ return NULL;
+ }
+
+ /* use string as key, not value */
+ child->string = child->valuestring;
+ child->valuestring = NULL;
+
+ if (*value != ':')
+ {
+ /* invalid object. */
+ *ep = value;
+ return NULL;
+ }
+ /* skip any spacing, get the value. */
+ value = skip(parse_value(child, skip(value + 1), ep));
+ if (!value)
+ {
+ return NULL;
+ }
+ }
+ /* end of object */
+ if (*value == '}')
+ {
+ return value + 1;
+ }
+
+ /* malformed */
+ *ep = value;
+ return NULL;
+}
+
+/* Render an object to text. */
+static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p)
+{
+ char **entries = NULL;
+ char **names = NULL;
+ char *out = NULL;
+ char *ptr = NULL;
+ char *ret = NULL;
+ char *str = NULL;
+ int len = 7;
+ int i = 0;
+ int j = 0;
+ cJSON *child = item->child;
+ int numentries = 0;
+ cjbool fail = false;
+ size_t tmplen = 0;
+
+ /* Count the number of entries. */
+ while (child)
+ {
+ numentries++;
+ child = child->next;
+ }
+
+ /* Explicitly handle empty object case */
+ if (!numentries)
+ {
+ if (p)
+ {
+ out = ensure(p, fmt ? depth + 4 : 3);
+ }
+ else
+ {
+ out = (char*)cJSON_malloc(fmt ? depth + 4 : 3);
+ }
+ if (!out)
+ {
+ return NULL;
+ }
+ ptr = out;
+ *ptr++ = '{';
+ if (fmt) {
+ *ptr++ = '\n';
+ for (i = 0; i < depth; i++)
+ {
+ *ptr++ = '\t';
+ }
+ }
+ *ptr++ = '}';
+ *ptr++ = '\0';
+
+ return out;
+ }
+
+ if (p)
+ {
+ /* Compose the output: */
+ i = p->offset;
+ len = fmt ? 2 : 1; /* fmt: {\n */
+ ptr = ensure(p, len + 1);
+ if (!ptr)
+ {
+ return NULL;
+ }
+
+ *ptr++ = '{';
+ if (fmt)
+ {
+ *ptr++ = '\n';
+ }
+ *ptr = '\0';
+ p->offset += len;
+
+ child = item->child;
+ depth++;
+ while (child)
+ {
+ if (fmt)
+ {
+ ptr = ensure(p, depth);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ for (j = 0; j < depth; j++)
+ {
+ *ptr++ = '\t';
+ }
+ p->offset += depth;
+ }
+
+ /* print key */
+ print_string_ptr(child->string, p);
+ p->offset = update(p);
+
+ len = fmt ? 2 : 1;
+ ptr = ensure(p, len);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ *ptr++ = ':';
+ if (fmt)
+ {
+ *ptr++ = '\t';
+ }
+ p->offset+=len;
+
+ /* print value */
+ print_value(child, depth, fmt, p);
+ p->offset = update(p);
+
+ /* print comma if not last */
+ len = (fmt ? 1 : 0) + (child->next ? 1 : 0);
+ ptr = ensure(p, len + 1);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ if (child->next)
+ {
+ *ptr++ = ',';
+ }
+
+ if (fmt)
+ {
+ *ptr++ = '\n';
+ }
+ *ptr = '\0';
+ p->offset += len;
+
+ child = child->next;
+ }
+
+ ptr = ensure(p, fmt ? (depth + 1) : 2);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ if (fmt)
+ {
+ for (i = 0; i < (depth - 1); i++)
+ {
+ *ptr++ = '\t';
+ }
+ }
+ *ptr++ = '}';
+ *ptr = '\0';
+ out = (p->buffer) + i;
+ }
+ else
+ {
+ /* Allocate space for the names and the objects */
+ entries = (char**)cJSON_malloc(numentries * sizeof(char*));
+ if (!entries)
+ {
+ return NULL;
+ }
+ names = (char**)cJSON_malloc(numentries * sizeof(char*));
+ if (!names)
+ {
+ cJSON_free(entries);
+ return NULL;
+ }
+ memset(entries, '\0', sizeof(char*) * numentries);
+ memset(names, '\0', sizeof(char*) * numentries);
+
+ /* Collect all the results into our arrays: */
+ child = item->child;
+ depth++;
+ if (fmt)
+ {
+ len += depth;
+ }
+ while (child && !fail)
+ {
+ names[i] = str = print_string_ptr(child->string, 0); /* print key */
+ entries[i++] = ret = print_value(child, depth, fmt, 0);
+ if (str && ret)
+ {
+ len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
+ }
+ else
+ {
+ fail = true;
+ }
+ child = child->next;
+ }
+
+ /* Try to allocate the output string */
+ if (!fail)
+ {
+ out = (char*)cJSON_malloc(len);
+ }
+ if (!out)
+ {
+ fail = true;
+ }
+
+ /* Handle failure */
+ if (fail)
+ {
+ /* free all the printed keys and values */
+ for (i = 0; i < numentries; i++)
+ {
+ if (names[i])
+ {
+ cJSON_free(names[i]);
+ }
+ if (entries[i])
+ {
+ cJSON_free(entries[i]);
+ }
+ }
+ cJSON_free(names);
+ cJSON_free(entries);
+ return NULL;
+ }
+
+ /* Compose the output: */
+ *out = '{';
+ ptr = out + 1;
+ if (fmt)
+ {
+ *ptr++ = '\n';
+ }
+ *ptr = '\0';
+ for (i = 0; i < numentries; i++)
+ {
+ if (fmt)
+ {
+ for (j = 0; j < depth; j++)
+ {
+ *ptr++='\t';
+ }
+ }
+ tmplen = strlen(names[i]);
+ memcpy(ptr, names[i], tmplen);
+ ptr += tmplen;
+ *ptr++ = ':';
+ if (fmt)
+ {
+ *ptr++ = '\t';
+ }
+ strcpy(ptr, entries[i]);
+ ptr += strlen(entries[i]);
+ if (i != (numentries - 1))
+ {
+ *ptr++ = ',';
+ }
+ if (fmt)
+ {
+ *ptr++ = '\n';
+ }
+ *ptr = '\0';
+ cJSON_free(names[i]);
+ cJSON_free(entries[i]);
+ }
+
+ cJSON_free(names);
+ cJSON_free(entries);
+ if (fmt)
+ {
+ for (i = 0; i < (depth - 1); i++)
+ {
+ *ptr++ = '\t';
+ }
+ }
+ *ptr++ = '}';
+ *ptr++ = '\0';
+ }
+
+ return out;
+}
+
+/* Get Array size/item / object item. */
+int cJSON_GetArraySize(const cJSON *array)
+{
+ cJSON *c = array->child;
+ int i = 0;
+ while(c)
+ {
+ i++;
+ c = c->next;
+ }
+ return i;
+}
+
+cJSON *cJSON_GetArrayItem(const cJSON *array, int item)
+{
+ cJSON *c = array ? array->child : NULL;
+ while (c && item > 0)
+ {
+ item--;
+ c = c->next;
+ }
+
+ return c;
+}
+
+cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string)
+{
+ cJSON *c = object ? object->child : NULL;
+ while (c && cJSON_strcasecmp(c->string, string))
+ {
+ c = c->next;
+ }
+ return c;
+}
+
+cjbool cJSON_HasObjectItem(const cJSON *object,const char *string)
+{
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item)
+{
+ cJSON *ref = cJSON_New_Item();
+ if (!ref)
+ {
+ return NULL;
+ }
+ memcpy(ref, item, sizeof(cJSON));
+ ref->string = NULL;
+ ref->type |= cJSON_IsReference;
+ ref->next = ref->prev = NULL;
+ return ref;
+}
+
+/* Add item to array/object. */
+void cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+ cJSON *c = array->child;
+ if (!item)
+ {
+ return;
+ }
+ if (!c)
+ {
+ /* list is empty, start new one */
+ array->child = item;
+ }
+ else
+ {
+ /* append to the end */
+ while (c->next)
+ {
+ c = c->next;
+ }
+ suffix_object(c, item);
+ }
+}
+
+void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ if (!item)
+ {
+ return;
+ }
+
+ /* free old key and set new one */
+ if (item->string)
+ {
+ cJSON_free(item->string);
+ }
+ item->string = cJSON_strdup(string);
+
+ cJSON_AddItemToArray(object,item);
+}
+
+/* Add an item to an object with constant string as key */
+void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+{
+ if (!item)
+ {
+ return;
+ }
+ if (!(item->type & cJSON_StringIsConst) && item->string)
+ {
+ cJSON_free(item->string);
+ }
+ item->string = (char*)string;
+ item->type |= cJSON_StringIsConst;
+ cJSON_AddItemToArray(object, item);
+}
+
+void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ cJSON_AddItemToArray(array, create_reference(item));
+}
+
+void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+ cJSON_AddItemToObject(object, string, create_reference(item));
+}
+
+cJSON *cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+ cJSON *c = array->child;
+ while (c && (which > 0))
+ {
+ c = c->next;
+ which--;
+ }
+ if (!c)
+ {
+ /* item doesn't exist */
+ return NULL;
+ }
+ if (c->prev)
+ {
+ /* not the first element */
+ c->prev->next = c->next;
+ }
+ if (c->next)
+ {
+ c->next->prev = c->prev;
+ }
+ if (c==array->child)
+ {
+ array->child = c->next;
+ }
+ /* make sure the detached item doesn't point anywhere anymore */
+ c->prev = c->next = NULL;
+
+ return c;
+}
+
+void cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+ int i = 0;
+ cJSON *c = object->child;
+ while (c && cJSON_strcasecmp(c->string,string))
+ {
+ i++;
+ c = c->next;
+ }
+ if (c)
+ {
+ return cJSON_DetachItemFromArray(object, i);
+ }
+
+ return NULL;
+}
+
+void cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+/* Replace array/object items with new ones. */
+void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *c = array->child;
+ while (c && (which > 0))
+ {
+ c = c->next;
+ which--;
+ }
+ if (!c)
+ {
+ cJSON_AddItemToArray(array, newitem);
+ return;
+ }
+ newitem->next = c;
+ newitem->prev = c->prev;
+ c->prev = newitem;
+ if (c == array->child)
+ {
+ array->child = newitem;
+ }
+ else
+ {
+ newitem->prev->next = newitem;
+ }
+}
+
+void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *c = array->child;
+ while (c && (which > 0))
+ {
+ c = c->next;
+ which--;
+ }
+ if (!c)
+ {
+ return;
+ }
+ newitem->next = c->next;
+ newitem->prev = c->prev;
+ if (newitem->next)
+ {
+ newitem->next->prev = newitem;
+ }
+ if (c == array->child)
+ {
+ array->child = newitem;
+ }
+ else
+ {
+ newitem->prev->next = newitem;
+ }
+ c->next = c->prev = NULL;
+ cJSON_Delete(c);
+}
+
+void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+ int i = 0;
+ cJSON *c = object->child;
+ while(c && cJSON_strcasecmp(c->string, string))
+ {
+ i++;
+ c = c->next;
+ }
+ if(c)
+ {
+ /* free the old string if not const */
+ if (!(newitem->type & cJSON_StringIsConst) && newitem->string)
+ {
+ cJSON_free(newitem->string);
+ }
+
+ newitem->string = cJSON_strdup(string);
+ cJSON_ReplaceItemInArray(object, i, newitem);
+ }
+}
+
+/* Create basic types: */
+cJSON *cJSON_CreateNull(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if(item)
+ {
+ item->type = cJSON_NULL;
+ }
+
+ return item;
+}
+
+cJSON *cJSON_CreateTrue(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if(item)
+ {
+ item->type = cJSON_True;
+ }
+
+ return item;
+}
+
+cJSON *cJSON_CreateFalse(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if(item)
+ {
+ item->type = cJSON_False;
+ }
+
+ return item;
+}
+
+cJSON *cJSON_CreateBool(cjbool b)
+{
+ cJSON *item = cJSON_New_Item();
+ if(item)
+ {
+ item->type = b ? cJSON_True : cJSON_False;
+ }
+
+ return item;
+}
+
+cJSON *cJSON_CreateNumber(double num)
+{
+ cJSON *item = cJSON_New_Item();
+ if(item)
+ {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+ item->valueint = (int)num;
+ }
+
+ return item;
+}
+
+cJSON *cJSON_CreateString(const char *string)
+{
+ cJSON *item = cJSON_New_Item();
+ if(item)
+ {
+ item->type = cJSON_String;
+ item->valuestring = cJSON_strdup(string);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+cJSON *cJSON_CreateArray(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if(item)
+ {
+ item->type=cJSON_Array;
+ }
+
+ return item;
+}
+
+cJSON *cJSON_CreateObject(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item)
+ {
+ item->type = cJSON_Object;
+ }
+
+ return item;
+}
+
+/* Create Arrays: */
+cJSON *cJSON_CreateIntArray(const int *numbers, int count)
+{
+ int i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = cJSON_CreateArray();
+ for(i = 0; a && (i < count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+cJSON *cJSON_CreateFloatArray(const float *numbers, int count)
+{
+ int i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = cJSON_CreateArray();
+ for(i = 0; a && (i < count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+cJSON *cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+ int i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = cJSON_CreateArray();
+ for(i = 0;a && (i < count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+cJSON *cJSON_CreateStringArray(const char **strings, int count)
+{
+ int i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = cJSON_CreateArray();
+ for (i = 0; a && (i < count); i++)
+ {
+ n = cJSON_CreateString(strings[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p,n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+/* Duplication */
+cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse)
+{
+ cJSON *newitem = NULL;
+ cJSON *cptr = NULL;
+ cJSON *nptr = NULL;
+ cJSON *newchild = NULL;
+
+ /* Bail on bad ptr */
+ if (!item)
+ {
+ return NULL;
+ }
+ /* Create new item */
+ newitem = cJSON_New_Item();
+ if (!newitem)
+ {
+ return NULL;
+ }
+ /* Copy over all vars */
+ newitem->type = item->type & (~cJSON_IsReference);
+ newitem->valueint = item->valueint;
+ newitem->valuedouble = item->valuedouble;
+ if (item->valuestring)
+ {
+ newitem->valuestring = cJSON_strdup(item->valuestring);
+ if (!newitem->valuestring)
+ {
+ cJSON_Delete(newitem);
+ return NULL;
+ }
+ }
+ if (item->string)
+ {
+ newitem->string = cJSON_strdup(item->string);
+ if (!newitem->string)
+ {
+ cJSON_Delete(newitem);
+ return NULL;
+ }
+ }
+ /* If non-recursive, then we're done! */
+ if (!recurse)
+ {
+ return newitem;
+ }
+ /* Walk the ->next chain for the child. */
+ cptr = item->child;
+ while (cptr)
+ {
+ newchild = cJSON_Duplicate(cptr, 1); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild)
+ {
+ cJSON_Delete(newitem);
+ return NULL;
+ }
+ if (nptr)
+ {
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ nptr->next = newchild;
+ newchild->prev = nptr;
+ nptr = newchild;
+ }
+ else
+ {
+ /* Set newitem->child and move to it */
+ newitem->child = newchild; nptr = newchild;
+ }
+ cptr = cptr->next;
+ }
+
+ return newitem;
+}
+
+void cJSON_Minify(char *json)
+{
+ char *into = json;
+ while (*json)
+ {
+ if (*json == ' ')
+ {
+ json++;
+ }
+ else if (*json == '\t')
+ {
+ /* Whitespace characters. */
+ json++;
+ }
+ else if (*json == '\r')
+ {
+ json++;
+ }
+ else if (*json=='\n')
+ {
+ json++;
+ }
+ else if ((*json == '/') && (json[1] == '/'))
+ {
+ /* double-slash comments, to end of line. */
+ while (*json && (*json != '\n'))
+ {
+ json++;
+ }
+ }
+ else if ((*json == '/') && (json[1] == '*'))
+ {
+ /* multiline comments. */
+ while (*json && !((*json == '*') && (json[1] == '/')))
+ {
+ json++;
+ }
+ json += 2;
+ }
+ else if (*json == '\"')
+ {
+ /* string literals, which are \" sensitive. */
+ *into++ = *json++;
+ while (*json && (*json != '\"'))
+ {
+ if (*json == '\\')
+ {
+ *into++=*json++;
+ }
+ *into++ = *json++;
+ }
+ *into++ = *json++;
+ }
+ else
+ {
+ /* All other characters. */
+ *into++ = *json++;
+ }
+ }
+
+ /* and null-terminate. */
+ *into = '\0';
+}
diff --git a/service/src/cJSON.h b/service/src/cJSON.h
new file mode 100644
index 0000000..dbbb739
--- /dev/null
+++ b/service/src/cJSON.h
@@ -0,0 +1,165 @@
+/*
+ Copyright (c) 2009 Dave Gamble
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stddef.h>
+
+/* cJSON Types: */
+#define cJSON_False (1 << 0)
+#define cJSON_True (1 << 1)
+#define cJSON_NULL (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array (1 << 5)
+#define cJSON_Object (1 << 6)
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON
+{
+ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *next;
+ struct cJSON *prev;
+ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+ struct cJSON *child;
+
+ /* The type of the item, as above. */
+ int type;
+
+ /* The item's string, if type==cJSON_String */
+ char *valuestring;
+ /* The item's number, if type==cJSON_Number */
+ int valueint;
+ /* The item's number, if type==cJSON_Number */
+ double valuedouble;
+
+ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+ char *string;
+} cJSON;
+
+typedef struct cJSON_Hooks
+{
+ void *(*malloc_fn)(size_t sz);
+ void (*free_fn)(void *ptr);
+} cJSON_Hooks;
+
+/* Supply malloc, realloc and free functions to cJSON */
+extern void cJSON_InitHooks(cJSON_Hooks* hooks);
+
+
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
+extern cJSON *cJSON_Parse(const char *value);
+/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
+extern char *cJSON_Print(const cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
+extern char *cJSON_PrintUnformatted(const cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+extern char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, int fmt);
+/* Delete a cJSON entity and all subentities. */
+extern void cJSON_Delete(cJSON *c);
+
+/* Returns the number of items in an array (or object). */
+extern int cJSON_GetArraySize(const cJSON *array);
+/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+extern cJSON *cJSON_GetArrayItem(const cJSON *array, int item);
+/* Get item "string" from object. Case insensitive. */
+extern cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string);
+extern int cJSON_HasObjectItem(const cJSON *object, const char *string);
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+extern const char *cJSON_GetErrorPtr(void);
+
+/* These calls create a cJSON item of the appropriate type. */
+extern cJSON *cJSON_CreateNull(void);
+extern cJSON *cJSON_CreateTrue(void);
+extern cJSON *cJSON_CreateFalse(void);
+extern cJSON *cJSON_CreateBool(int b);
+extern cJSON *cJSON_CreateNumber(double num);
+extern cJSON *cJSON_CreateString(const char *string);
+extern cJSON *cJSON_CreateArray(void);
+extern cJSON *cJSON_CreateObject(void);
+
+/* These utilities create an Array of count items. */
+extern cJSON *cJSON_CreateIntArray(const int *numbers, int count);
+extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count);
+extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count);
+extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
+
+/* Append item to the specified array/object. */
+extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+extern void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detatch items from Arrays/Objects. */
+extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
+extern void cJSON_DeleteItemFromArray(cJSON *array, int which);
+extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
+extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+
+/* Update array items. */
+extern void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+extern cJSON *cJSON_Duplicate(const cJSON *item, int recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+need to be released. With recurse!=0, it will duplicate any children connected to the item.
+The item->next and ->prev pointers are always zero on return from Duplicate. */
+
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
+extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated);
+
+extern void cJSON_Minify(char *json);
+
+/* Macros for creating things quickly. */
+#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
+#define cJSON_SetNumberValue(object,val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
+
+/* Macro for iterating over an array */
+#define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/service/src/config.c b/service/src/config.c
index f3ce748..6ae17fe 100644
--- a/service/src/config.c
+++ b/service/src/config.c
@@ -13,44 +13,28 @@
#include <mr_mask.h>
#include <mr_runtime.h>
#include <arpa/inet.h>
+#include "mr_buffer.h"
-#ifndef MR_SERVICE_DEFAULT_SZ_RXVNODE_RING
-#define MR_SERVICE_DEFAULT_SZ_RXVNODE_RING 1024
+#ifndef MR_SERVICE_DEFAULT_SZ_BUFFER
+#define MR_SERVICE_DEFAULT_SZ_BUFFER 32
#endif
-#ifndef MR_SERVICE_DEFAULT_SZ_TXVNODE_RING
-#define MR_SERVICE_DEFAULT_SZ_TXVNODE_RING 1024
-#endif
-
-#ifndef MR_SERVICE_DEFAULT_SZ_RXVNODE_BUFFER
-#define MR_SERVICE_DEFAULT_SZ_RXVNODE_BUFFER 128
-#endif
-
-#ifndef MR_SERVICE_DEFAULT_SZ_TXVNODE_BUFFER
-#define MR_SERVICE_DEFAULT_SZ_TXVNODE_BUFFER 128
-#endif
-
-#ifndef MR_SERVICE_DEFAULT_SZ_RX_BURST
-#define MR_SERVICE_DEFAULT_SZ_RX_BURST 128
-#endif
-
-#ifndef MR_SERVICE_DEFAULT_SZ_TX_BURST
-#define MR_SERVICE_DEFAULT_SZ_TX_BURST 128
+#ifndef MR_SERVICE_DEFAULT_SZ_TUNNEL
+#define MR_SERVICE_DEFAULT_SZ_TUNNEL 512
#endif
#ifndef MR_SERVICE_DEFAULT_DIST_MODE
-#define MR_SERVICE_DEFAULT_DIST_MODE LDBC_DIST_SIMPLE_TUPLE2
+#define MR_SERVICE_DEFAULT_DIST_MODE LDBC_DIST_OUTER_TUPLE2
#endif
-#if MR_SERVICE_DEFAULT_SZ_RX_BURST > MR_BURST_MAX
-#error("MR_SERVICE_DEFAULT_SZ_BURST is large than MR_BURST_MAX")
+#ifndef MR_SERVICE_DEFAULT_SZ_BURST
+#define MR_SERVICE_DEFAULT_SZ_BURST 32
#endif
-#if MR_SERVICE_DEFAULT_SZ_TX_BURST > MR_BURST_MAX
-#error("MR_SERVICE_DEFAULT_TX_BURST is large than MR_BURST_MAX")
+#if MR_SERVICE_DEFAULT_SZ_BURST > MR_BURST_MAX
+#error("MR_SERVICE_DEFAULT_SZ_BURST is large than MR_BURST_MAX")
#endif
-
static int __parser_uint(const char * str)
{
char * strptr;
@@ -108,116 +92,114 @@ static int __parser_str_core(char * str_core, int sz_buffer,
return 0;
}
-int sc_config_thread_info(const char * cfg, struct sc_instance * instance)
-{
- char str_thread_info[MR_STRING_MAX];
-
- int ret = MESA_load_profile_string_nodef(cfg, "service", "iocore",
- str_thread_info, sizeof(str_thread_info));
- if (ret < 0)
- return __errlog_lost_key("LoadThreadInfo","service", "iocore");
- ret = __parser_str_core(str_thread_info, sizeof(str_thread_info),
- &instance->cpu_mask, ',');
- if(ret < 0)
- return __errlog_invaild_format("LoadThreadInfo", "service", "iocore");
+void __ctrlzone_list_join(struct sc_instance * instance, const char * ctrlzone,
+ unsigned int ctrlzone_id, unsigned int sz_ctrlzone)
+{
+ struct sc_ctrlzone * sc_ctrlzone = rte_zmalloc(NULL, sizeof(sc_ctrlzone), 0);
+ MR_CHECK(sc_ctrlzone != NULL, "Cannot alloc memory for sc_ctrlzone");
- return 0;
+ snprintf(sc_ctrlzone->symbol, sizeof(sc_ctrlzone->symbol), "%s", ctrlzone);
+ sc_ctrlzone->id = ctrlzone_id;
+ sc_ctrlzone->size = sz_ctrlzone;
+
+ TAILQ_INSERT_TAIL(&instance->ctrlzone_list, sc_ctrlzone, next);
+ return;
}
-#if 0
-static int __parse_app_info(const char * cfg, const char * appsym,
- struct sc_instance * instance)
+int sc_config_ctrlzone(const char * cfg, struct sc_instance * instance)
{
+ char str_ctrlzone_key[MR_SYMBOL_MAX];
+ char str_ctrlzone_info[MR_STRING_MAX];
+ char str_ctrlzone_name[MR_STRING_MAX];
+ int sz_ctrlzone = 0;
int ret = 0;
- char str_section[MR_STRING_MAX];
- snprintf(str_section, sizeof(str_section), "app:%s", appsym);
+
+ for(int ctrlzone_id = 0; ctrlzone_id < MRB_MAX_CTRLZONE_NUM; ctrlzone_id++)
+ {
+ snprintf(str_ctrlzone_key, sizeof(str_ctrlzone_key), "ctrlzone%d", ctrlzone_id);
+ ret = MESA_load_profile_string_nodef(cfg, "ctrlzone", str_ctrlzone_key,
+ str_ctrlzone_info, sizeof(str_ctrlzone_info));
+ if (ret < 0) continue;
- // 读核心掩码
- char str_core[MR_STRING_MAX];
- ret = MESA_load_profile_string_nodef(cfg, str_section, "core",
- str_core, sizeof(str_core));
+ char * tokens[MR_TOKENS_MAX];
+ ret = rte_strsplit(str_ctrlzone_info, sizeof(str_ctrlzone_info), tokens,
+ MR_TOKENS_MAX, ',');
- if (ret < 0)
- return __errlog_lost_key("LoadAppInfo", str_section, "core");
+ if (ret != 2)
+ return __errlog_invaild_format("LoadCtrlZone", "ctrlzone", str_ctrlzone_key);
+
+ snprintf(str_ctrlzone_name, sizeof(str_ctrlzone_name), "%s", tokens[0]);
+ sz_ctrlzone = __parser_uint(tokens[1]);
+
+ if(sz_ctrlzone < 0)
+ return __errlog_invaild_format("LoadCtrlZone", "ctrlzone", str_ctrlzone_key);
+
+ __ctrlzone_list_join(instance, str_ctrlzone_name, ctrlzone_id, sz_ctrlzone);
+ }
- // 解析核心掩码
- cpu_mask_t coremask;
- ret = __parser_str_core(str_core, sizeof(str_core), &coremask, ',');
- if (ret < 0)
- return __errlog_invaild_format("LoadAppInfo", str_section, "core");
-
- // 读RX队列数
- unsigned int rxstream;
- ret = MESA_load_profile_uint_nodef(cfg, str_section, "rxstream", &rxstream);
- if (ret < 0) return __errlog_invaild_format("LoadAppInfo", str_section, "rxstream");
-
- // 读TX队列数
- unsigned int txstream;
- ret = MESA_load_profile_uint_nodef(cfg, str_section, "txstream", &txstream);
- if (ret < 0) return __errlog_invaild_format("LoadAppInfo", str_section, "txstream");
-
- // 生成App结构体,插入到链表中
- struct sc_app * appinfo;
- appinfo = rte_zmalloc(NULL, sizeof(struct sc_app), 0);
- assert(appinfo != NULL);
-
- snprintf(appinfo->symbol, sizeof(appinfo->symbol), "%s", appsym);
- appinfo->cpu_mask = coremask;
- appinfo->rxstream = rxstream;
- appinfo->txstream = txstream;
- TAILQ_INSERT_TAIL(&instance->app_list, appinfo, next);
return 0;
}
-int sc_config_app_info(const char * cfg, struct sc_instance * instance)
+int sc_config_thread_info(const char * cfg, struct sc_instance * instance)
{
- char str_app_info[MR_STRING_MAX];
+ char str_thread_info[MR_STRING_MAX];
+
+ int ret = MESA_load_profile_string_nodef(cfg, "service", "iocore",
+ str_thread_info, sizeof(str_thread_info));
+ if (ret < 0)
+ return __errlog_lost_key("LoadThreadInfo","service", "iocore");
- // 读APP汇总信息:[app]symbols=XXX,YYY,ZZZ
- int ret = MESA_load_profile_string_nodef(cfg, "app", "symbols",
- str_app_info, sizeof(str_app_info));
+ ret = __parser_str_core(str_thread_info, sizeof(str_thread_info),
+ &instance->cpu_mask, ',');
- if (ret < 0) return __errlog_lost_key("LoadAppInfo", "app","symbols");
-
- // 切分APP汇总信息
- char * app_info_tokens[MR_TOKENS_MAX];
- int nr_app_info_tokens = rte_strsplit(str_app_info, sizeof(str_app_info),
- app_info_tokens, MR_TOKENS_MAX, ',');
+ if(ret < 0)
+ return __errlog_invaild_format("LoadThreadInfo", "service", "iocore");
- if (nr_app_info_tokens < 0)
- return __errlog_invaild_format("LoadAppInfo", "app","symbols");
-
- TAILQ_INIT(&instance->app_list);
- for(int i = 0; i < nr_app_info_tokens; i++)
- {
- // 生成section的名字
- const char * appsym = app_info_tokens[i];
- ret = __parse_app_info(cfg, appsym, instance);
- if (ret < 0) return ret;
- }
-
+ instance->sc_param.nr_serv_thread = mask_popcnt(instance->cpu_mask);
return 0;
}
-#endif
-
// 读协议栈运行参数
static int sc_config_stack_info(const char * cfg, struct sc_instance * instance)
{
- struct mr_stack_param * sk_param = &instance->sk_param;
+ struct sk_param * sk_param = &instance->sk_param;
snprintf(sk_param->servsym, sizeof(sk_param->servsym), "%s", instance->procsym);
-
+
+ int nr_serv_thread = mask_popcnt(instance->cpu_mask);
+ sk_param->nr_serv_thread = nr_serv_thread;
+
MESA_load_profile_uint_def(cfg, "stack", "sz_deliver_ring",
&sk_param->sz_deliver_ring, MR_STACK_DEFAULT_SZ_DELIVER_RING);
MESA_load_profile_uint_def(cfg, "stack", "sz_deliver_buffer",
&sk_param->sz_deliver_buffer, MR_STACK_DEFAULT_SZ_DELIVER_BUFFER);
MESA_load_profile_uint_def(cfg, "stack", "sz_loop_ring",
&sk_param->sz_loop_ring, MR_STACK_DEFAULT_SZ_LOOP_RING);
+ MESA_load_profile_uint_def(cfg, "stack", "neigh_max_neighbours",
+ &sk_param->nr_neigh_max_neigh, MR_STACK_DEFAULT_NEIGH_NR_MAX_NEIGH);
+ MESA_load_profile_uint_def(cfg, "stack", "neigh_timeout",
+ &sk_param->t_neigh_timeout, MR_STACK_DEFAULT_NEIGH_T_TIMEOUT);
+ MESA_load_profile_uint_def(cfg, "stack", "neigh_time_ack_send",
+ &sk_param->t_neigh_arp_send, MR_STACK_DEFAULT_NEIGH_T_ARP_SEND);
+
+ return 0;
+}
+
+static int sc_config_user_pool_info(const char * cfg, struct sc_instance * instance)
+{
+ MESA_load_profile_uint_def(cfg, "userpool", "nr_direct_pktmbuf",
+ &instance->sc_param.nr_user_direct_pktmbuf, MR_DEVICE_DEFAULT_NR_PKTMBUF);
+ MESA_load_profile_uint_def(cfg, "userpool", "nr_indirect_pktmbuf",
+ &instance->sc_param.nr_user_indirect_pktmbuf, MR_DEVICE_DEFAULT_NR_PKTMBUF);
+ MESA_load_profile_uint_def(cfg, "userpool", "sz_pktmbuf",
+ &instance->sc_param.sz_user_pktmbuf, MR_DEVICE_DEFAULT_SZ_PKTMBUF);
+ MESA_load_profile_uint_def(cfg, "userpool", "nr_pktmbuf_cache",
+ &instance->sc_param.sz_user_pktmbuf_cache, MR_DEVICE_DEFAULT_NR_PKTMBUF_CACHE);
return 0;
}
+
static int __load_device_runtime_info(const char * cfg, struct sc_instance * instance,
struct sc_device * sc_dev)
{
@@ -244,6 +226,16 @@ static int __load_device_runtime_info(const char * cfg, struct sc_instance * ins
// TX描述符数量
MESA_load_profile_uint_def(cfg, str_section, "nr_txdesc", &dev_param->nr_txdesc, 0);
+ // 报文缓冲区参数
+ MESA_load_profile_uint_def(cfg, str_section, "nr_direct_pktmbuf", &dev_param->nr_direct_pktmbuf,
+ MR_DEVICE_DEFAULT_NR_PKTMBUF);
+ MESA_load_profile_uint_def(cfg, str_section, "nr_indirect_pktmbuf", &dev_param->nr_indirect_pktmbuf,
+ MR_DEVICE_DEFAULT_NR_PKTMBUF);
+ MESA_load_profile_uint_def(cfg, str_section, "sz_pktmbuf", &dev_param->sz_pktmbuf,
+ MR_DEVICE_DEFAULT_SZ_PKTMBUF);
+ MESA_load_profile_uint_def(cfg, str_section, "nr_pktmbuf_cache", &dev_param->nr_pktmbuf_cache,
+ MR_DEVICE_DEFAULT_NR_PKTMBUF_CACHE);
+
// 读用户MAC地址
struct ether_addr hwaddr;
char str_hwaddr[MR_STRING_MAX];
@@ -350,73 +342,46 @@ _err_fmt:
return __errlog_invaild_format("LoadDeviceInfo", "device", "device");
}
-int sc_config_vnode_info(const char * cfg, struct sc_instance * instance)
-{
- MESA_load_profile_uint_def(cfg, "vnode", "sz_rxvnode_ring",
- &instance->sz_rxvnode_ring, MR_SERVICE_DEFAULT_SZ_RXVNODE_RING);
- MESA_load_profile_uint_def(cfg, "vnode", "sz_txvnode_ring",
- &instance->sz_txvnode_ring, MR_SERVICE_DEFAULT_SZ_TXVNODE_RING);
- MESA_load_profile_uint_def(cfg, "vnode", "sz_rxvnode_buffer",
- &instance->sz_rxvnode_buffer, MR_SERVICE_DEFAULT_SZ_RXVNODE_BUFFER);
- MESA_load_profile_uint_def(cfg, "vnode", "sz_txvnode_buffer",
- &instance->sz_txvnode_buffer, MR_SERVICE_DEFAULT_SZ_TXVNODE_BUFFER);
-
- MR_LOG(INFO, SERVICE, "ServiceConfig, LoadVnodeInfo, "
- "sz_rxvnode_ring=%d, sz_txvnode_ring=%d, "
- "sz_rxvnode_buffer=%d, sz_txvnode_buffer=%d \n",
- instance->sz_rxvnode_ring, instance->sz_txvnode_ring,
- instance->sz_rxvnode_buffer, instance->sz_txvnode_buffer);
-
- return 0;
-}
-
int sc_config_burst_info(const char * cfg, struct sc_instance * instance)
{
- MESA_load_profile_uint_def(cfg, "burst", "sz_rx_burst",
- &instance->sz_rx_burst, MR_SERVICE_DEFAULT_SZ_RX_BURST);
- MESA_load_profile_uint_def(cfg, "burst", "sz_tx_burst",
- &instance->sz_tx_burst, MR_SERVICE_DEFAULT_SZ_TX_BURST);
+ struct sc_param * sc_param = &instance->sc_param;
+
+ MESA_load_profile_uint_def(cfg, "tunnel", "sz_tunnel",
+ &sc_param->sz_tunnel, MR_SERVICE_DEFAULT_SZ_TUNNEL);
+ MESA_load_profile_uint_def(cfg, "tunnel", "sz_buffer",
+ &sc_param->sz_buffer, MR_SERVICE_DEFAULT_SZ_BUFFER);
+ MESA_load_profile_uint_def(cfg, "tunnel", "sz_burst",
+ &sc_param->sz_burst, MR_SERVICE_DEFAULT_SZ_BURST);
//参数校验,不能大于MR_BURST_MAX
- if(instance->sz_rx_burst > MR_BURST_MAX)
+ if(sc_param->sz_burst > MR_BURST_MAX)
{
- MR_LOG(WARNING, SERVICE, "ServiceConfig, LoadBurstInfo, "
- "Configure File Error, Invalid value(in key [%s]%s), "
- "should be less than MR_BURST_MAX=%d.\n", "burst", "sz_rx_burst",
+ MR_LOG(WARNING, SERVICE, "Configure File Error, Invalid value(in key [%s]%s), "
+ "should be less than MR_BURST_MAX=%d.\n", "burst", "sz_burst",
MR_BURST_MAX);
return -1;
}
- if(instance->sz_tx_burst > MR_BURST_MAX)
- {
- MR_LOG(WARNING, SERVICE, "ServiceConfig, LoadBurstInfo, "
- "Configure File Error, Invalid value(in key [%s]%s), "
- "should be less than MR_BURST_MAX=%d.\n", "burst", "sz_tx_burst",
- MR_BURST_MAX);
- return -1;
- }
-
- MR_LOG(INFO, SERVICE, "ServiceConfig, LoadBurstInfo, "
- "sz_rx_burst=%d, sz_tx_burst=%d. \n", instance->sz_rx_burst, instance->sz_tx_burst);
-
+ MR_LOG(INFO, SERVICE, "TunnelBurstInfo: sz_tunnel=%d, sz_buffer=%d, sz_burst=%d. \n",
+ sc_param->sz_tunnel, sc_param->sz_buffer, sc_param->sz_burst);
+
return 0;
}
int sc_config_ldbc_dist_mode(const char * cfgfile, struct sc_instance * instance)
{
+ struct sc_param * sc_param = &instance->sc_param;
MESA_load_profile_uint_def(cfgfile, "service","distmode",
- &instance->distmode, MR_SERVICE_DEFAULT_DIST_MODE);
-
- MR_LOG(INFO, SERVICE, "ServiceConfig, LoadDistMode"
- "DistMode=(%d)%s\n", instance->distmode, str_dist_mode(instance->distmode));
+ &sc_param->distmode, MR_SERVICE_DEFAULT_DIST_MODE);
+
+ MR_LOG(INFO, SERVICE, "LoadDistMode : %s\n", str_dist_mode(sc_param->distmode));
return 0;
}
int sc_config_check_cfgfile(const char * cfg, struct sc_instance * instance)
{
if (access(cfg, R_OK) == 0) return 0;
- MR_LOG(WARNING, SERVICE, "ServiceConfig, CheckConfigFile, "
- "Configure file %s cannot be read. \n", cfg);
+ MR_LOG(WARNING, SERVICE, "Configure file %s cannot be read. \n", cfg);
return -1;
}
@@ -430,9 +395,9 @@ void sc_stage_config(struct sc_instance * instance)
"Please check configure file %s, Failed", cfgfile);
MR_CHECK(sc_config_thread_info(cfgfile, instance) >= 0,
"Please check configure file %s, Failed. ", cfgfile);
- MR_CHECK(sc_config_device_info(cfgfile, instance) >= 0,
+ MR_CHECK(sc_config_user_pool_info(cfgfile, instance) >= 0,
"Please check configure file %s, Failed. ", cfgfile);
- MR_CHECK(sc_config_vnode_info(cfgfile, instance) >= 0,
+ MR_CHECK(sc_config_device_info(cfgfile, instance) >= 0,
"Please check configure file %s, Failed. ", cfgfile);
MR_CHECK(sc_config_burst_info(cfgfile, instance) >= 0,
"Please check configure file %s, Failed. ", cfgfile);
@@ -440,6 +405,8 @@ void sc_stage_config(struct sc_instance * instance)
"Please check configure file %s, Failed. ", cfgfile);
MR_CHECK(sc_config_stack_info(cfgfile, instance) >= 0,
"Please check configure file %s, Failed. ", cfgfile);
-
+ MR_CHECK(sc_config_ctrlzone(cfgfile, instance) >= 0,
+ "Please check configure file %s, Failed. ", cfgfile);
+
return;
} \ No newline at end of file
diff --git a/service/src/core.c b/service/src/core.c
index 3c7cd45..f477ec2 100644
--- a/service/src/core.c
+++ b/service/src/core.c
@@ -13,6 +13,14 @@
#include <MESA_prof_load.h>
#include <mr_runtime.h>
+const char * mr_logo =
+" __ ___ _ _____ ______\n"
+" / |/ /___ ___________(_)__/__ / ___ _________ / ____/___ ____ __ __\n"
+" / /|_/ / __ `/ ___/ ___/ / __ \\/ / / _ \\/ ___/ __ \\/ / / __ \\/ __ \\/ / / /\n"
+" / / / / /_/ / / (__ ) / /_/ / /__/ __/ / / /_/ / /___/ /_/ / /_/ / /_/ /\n"
+" /_/ /_/\\__,_/_/ /____/_/\\____/____/\\___/_/ \\____/\\____/\\____/ .___/\\__, /\n"
+" /_/ /____/\n";
+
#ifdef GITVER
const char service_git_version[] = GITVER;
#else
@@ -23,28 +31,26 @@ const char service_git_version[] = "";
#define MR_SERVICE_MAX_EAL_ARGC 512
#endif
+#ifndef MR_SERVICE_DEFAULT_MONIT_FILE
+#define MR_SERVICE_DEFAULT_MONIT_FILE "/tmp/.mrzcpd.moint"
+#endif
+
#ifndef MR_SERVICE_DEFAULT_GLOB_CFG
-#define MR_SERVICE_GLOB_CFG "/etc/mrglobal.conf"
+#define MR_SERVICE_DEFAULT_GLOB_CFG "/etc/mrglobal.conf"
#endif
#ifndef MR_SERVICE_DEFAULT_PROCSYM
-#define MR_SERVICE_DEFAULT_PROCSYM "serv"
+#define MR_SERVICE_DEFAULT_PROCSYM "serv"
#endif
#ifndef MR_LOGREADER_DEFAULT_PROCSYM
-#define MR_LOGREADER_DEFAULT_PROCSYM "logreader"
+#define MR_LOGREADER_DEFAULT_PROCSYM "logreader"
#endif
-
extern void * sc_runtime_thread(void * args);
extern void sc_stage_config(struct sc_instance * instance);
extern void sc_stage_register(struct sc_instance * instance);
-extern struct mr_module module_desc_hwinfo;
-extern struct mr_module module_desc_procman;
-extern struct mr_module module_desc_device;
-extern struct mr_module module_desc_mrbuf;
-
/* 写入Command参数 */
static void __write_arg(char * eal_argv[], unsigned int * eal_argc,
unsigned int max_argc, const char * value)
@@ -82,8 +88,18 @@ static void sc_stage_eal_init(struct sc_instance * instance)
WRITE_ARG(str_virtaddr);
}
+ unsigned int loglevel;
+ ret = MESA_load_profile_uint_nodef(instance->local_cfgfile, "eal",
+ "loglevel", &loglevel);
+
+ if (ret >= 0)
+ {
+ rte_set_log_level(loglevel);
+ }
+
ret = rte_eal_init(eal_argc, eal_argv);
MR_CHECK(ret >= 0, "Cannot init EAL Enviorment, Failed");
+
return;
}
@@ -138,6 +154,14 @@ struct sc_instance * sc_instance_new()
return instance;
}
+void sc_instance_init_monitfile(struct sc_instance * instance)
+{
+ snprintf(instance->local_monitfile, sizeof(instance->local_monitfile), "%s",
+ MR_SERVICE_DEFAULT_MONIT_FILE);
+ return;
+}
+
+
void sc_instance_init_log(struct sc_instance * instance)
{
// 如果没有设置,使用默认的日志流(到屏幕上)
@@ -161,10 +185,11 @@ void sc_instance_init_cfg(struct sc_instance * instance)
int ret = strncmp(instance->local_cfgfile, "", sizeof(instance->local_cfgfile));
if (ret == 0) goto default_cfgfile;
if (access(instance->local_cfgfile, R_OK) != 0) goto default_cfgfile;
+ return;
default_cfgfile:
snprintf(instance->local_cfgfile, sizeof(instance->local_logfile), "%s",
- MR_SERVICE_GLOB_CFG);
+ MR_SERVICE_DEFAULT_GLOB_CFG);
MR_LOG(INFO, SERVICE, "Global Configure File: %s\n", instance->local_cfgfile);
}
@@ -177,11 +202,19 @@ void sc_instance_init_progsym(struct sc_instance * instance)
return;
}
+void sc_instance_init_ctrlzone_list(struct sc_instance * instance)
+{
+ TAILQ_INIT(&instance->ctrlzone_list);
+ return;
+}
+
void sc_instance_init(struct sc_instance * instance)
{
sc_instance_init_log(instance);
sc_instance_init_cfg(instance);
+ sc_instance_init_monitfile(instance);
sc_instance_init_progsym(instance);
+ sc_instance_init_ctrlzone_list(instance);
}
void sc_instance_ctx_init(struct sc_instance * instance)
@@ -193,15 +226,32 @@ void sc_instance_ctx_init(struct sc_instance * instance)
void sc_stage_init(struct sc_instance * instance)
{
- mr_core_instance_init(instance->core_instance);
return;
}
+extern int sc_monit_loop(struct sc_instance * sc_instance);
+
+void * sc_loop_thread(void * args)
+{
+ struct sc_instance * instance = (struct sc_instance *)args;
+ pthread_detach(pthread_self());
+
+ while(1)
+ {
+ sc_monit_loop(instance);
+ sleep(1);
+ }
+}
+
+
void sc_launch_thread(struct sc_instance * instance)
{
int nr_thread = mask_popcnt(instance->cpu_mask);
MR_CHECK(nr_thread >= 0, "Invailed CPU Mask");
-
+
+ pthread_t pid_loop;
+ pthread_create(&pid_loop, NULL, sc_loop_thread, instance);
+
pthread_t * pids = (pthread_t *)malloc(sizeof(pthread_t) * nr_thread);
MR_CHECK(pids != NULL, "Cannot alloc memory for pthread_t structures");
@@ -221,18 +271,18 @@ void sc_launch_thread(struct sc_instance * instance)
int main(int argc, char * argv[])
{
+ fprintf(stdout, "%s", mr_logo);
struct sc_instance * instance = sc_instance_new();
sc_stage_parse_cmd(instance, argc, argv);
sc_instance_init(instance);
sc_stage_eal_init(instance);
sc_instance_ctx_init(instance);
-
+
MR_LOG(INFO, SERVICE, "Starting IIE MARSIO I/O Service...\n");
MR_LOG(INFO, SERVICE, "Version : %s, Using %s\n", service_git_version, rte_version());
sc_stage_config(instance);
sc_stage_register(instance);
- mr_core_instance_config(instance->core_instance);
sc_stage_init(instance);
sc_launch_thread(instance);
assert(0);
diff --git a/service/src/ldbc.c b/service/src/ldbc.c
index 8e9f016..754e7af 100644
--- a/service/src/ldbc.c
+++ b/service/src/ldbc.c
@@ -18,46 +18,6 @@
#include <assert.h>
#include <linux/if_ether.h>
-#if RTE_VERSION <= RTE_VERSION_NUM(16,04,0,0) // CRC32 2byte is not defined in DPDK 2.1, Port from 16.04
-
-#define CRC32_UPD(crc, n) \
- (crc32c_tables[(n)][(crc) & 0xFF] ^ \
- crc32c_tables[(n)-1][((crc) >> 8) & 0xFF])
-
-// CRC32 2Bytes in SSE
-static inline uint32_t crc32c_sse42_u16(uint16_t data, uint32_t init_val)
-{
- __asm__ volatile(
- "crc32w %[data], %[init_val];"
- : [init_val] "+r" (init_val)
- : [data] "rm" (data));
- return init_val;
-}
-
-static inline uint32_t crc32c_2bytes(uint16_t data, uint32_t init_val)
-{
- uint32_t crc;
- crc = init_val;
- crc ^= data;
-
- crc = CRC32_UPD(crc, 1) ^ (crc >> 16);
-
- return crc;
-}
-
-// CRC32 2Bytes
-static inline uint32_t rte_hash_crc_2byte(uint16_t data, uint32_t init_val)
-{
-#if defined RTE_ARCH_I686 || defined RTE_ARCH_X86_64
- if (likely(crc32_alg & CRC32_SSE42))
- return crc32c_sse42_u16(data, init_val);
-#endif
-
- return crc32c_2bytes(data, init_val);
-}
-
-#endif
-
enum
{
/* 以太网头 */
@@ -108,8 +68,8 @@ static void * __complex_parser_pppoe_ses(void * data, int this_layer_type,
return data;
}
-#define PPPOE_TYPE_IPV4 0x0021
-#define PPPOE_TYPE_IPV6 0x0057
+#define PPPOE_TYPE_IPV4 0x2100
+#define PPPOE_TYPE_IPV6 0x5700
uint16_t pppoe_type = *((uint16_t *)data + 3);
void * data_next_layer = (uint8_t *)data + 8;
@@ -170,7 +130,7 @@ static void * __complex_parser_mpls_uc(void * data, int this_layer_type,
}
}
-static void * __complex_parser_vlan8021q(void * data, int this_layer_type,
+static const void * __complex_parser_vlan8021q(const void * data, int this_layer_type,
int expect_layer_type, int * layer_type_out)
{
if (expect_layer_type == LAYER_TYPE_VLAN || expect_layer_type == LAYER_TYPE_L2TUN)
@@ -211,7 +171,7 @@ static void * __complex_parser_vlan8021q(void * data, int this_layer_type,
return NULL;
}
-static void * __complex_parser_ether(void * data, int this_layer_type,
+static const void * __complex_parser_ether(const void * data, int this_layer_type,
int expect_layer_type, int * layer_type_out)
{
if (expect_layer_type == LAYER_TYPE_ETHER)
@@ -252,128 +212,128 @@ static void * __complex_parser_ether(void * data, int this_layer_type,
return NULL;
}
-static void * complex_parser_ether(void * data, int this_layer_type,
+static const void * complex_parser_ether(const void * data, int this_layer_type,
int expect_layer_type, int * layer_type_out)
{
return __complex_parser_ether(data, this_layer_type, expect_layer_type, layer_type_out);
}
-static uint32_t __hash_simple_tuple2(struct rte_mbuf * mbuf, uint32_t orin_hash __rte_unused)
+static inline uint32_t hash_l4_layer(const void * data, int layer_type, uint32_t orin_hash)
{
- const char * data = NULL;
- const char * p_str_ip = NULL;
- const char * p_dst_ip = NULL;
+ const char * p_src_port;
+ const char * p_dst_port;
+ uint8_t port_len = 0;
- uint8_t ip_len = 0;
- uint32_t src_hash = 0;
- uint32_t dst_hash = 0;
+ if (data == NULL) return 0;
- // IPv4 Header
- if (RTE_ETH_IS_IPV4_HDR(mbuf->packet_type))
+ if (layer_type == LAYER_TYPE_TCP)
{
- data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
- const struct ipv4_hdr * ether_hdr = (const struct ipv4_hdr *)data;
- p_str_ip = (const char *)&(ether_hdr->src_addr);
- p_dst_ip = (const char *)&(ether_hdr->dst_addr);
- ip_len = 4;
- }
-
- // IPv6 Header
- else if (RTE_ETH_IS_IPV4_HDR(mbuf->packet_type))
- {
- data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
- const struct ipv6_hdr * ipv6_hdr = (const struct ipv6_hdr *)data;
- p_str_ip = (const char *)&(ipv6_hdr->src_addr);
- p_dst_ip = (const char *)&(ipv6_hdr->dst_addr);
- ip_len = 16;
+ const struct tcp_hdr * tcp_hdr = (const struct tcp_hdr *)data;
+ p_src_port = (const char *)&tcp_hdr->src_port;
+ p_dst_port = (const char *)&tcp_hdr->dst_port;
+ port_len = sizeof(struct tcp_hdr);
}
- else
+ else if(layer_type == LAYER_TYPE_UDP)
{
- return 0;
+ const struct udp_hdr * udp_hdr = (const struct udp_hdr *)data;
+ p_src_port = (const char *)&udp_hdr->src_port;
+ p_dst_port = (const char *)&udp_hdr->dst_port;
+ port_len = sizeof(struct tcp_hdr);
}
+ else return 0;
- src_hash = rte_hash_crc(p_str_ip, ip_len, src_hash);
- dst_hash = rte_hash_crc(p_dst_ip, ip_len, dst_hash);
+ uint32_t src_hash = rte_hash_crc(p_src_port, port_len, orin_hash);
+ uint32_t dst_hash = rte_hash_crc(p_dst_port, port_len, orin_hash);
return src_hash ^ dst_hash;
}
-static uint32_t __hash_simple_tuple4(struct rte_mbuf * mbuf, uint32_t orin_hash __rte_unused)
+static inline uint32_t hash_ip_layer(const void * data, int layer_type, uint32_t orin_hash)
{
- const char * data = NULL;
- const char * p_str_ip = NULL;
- const char * p_dst_ip = NULL;
- const char * p_src_port = NULL;
- const char * p_dst_port = NULL;
- const char * p_proto = NULL;
-
+ const char * p_str_ip;
+ const char * p_dst_ip;
uint8_t ip_len = 0;
- uint8_t port_len = 2;
- uint32_t src_hash = 0;
- uint32_t dst_hash = 0;
- if (RTE_ETH_IS_IPV4_HDR(mbuf->packet_type))
+ if (data == NULL) return 0;
+
+ if(layer_type == LAYER_TYPE_IPV4)
{
- data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
const struct ipv4_hdr * ether_hdr = (const struct ipv4_hdr *)data;
p_str_ip = (const char *)&(ether_hdr->src_addr);
p_dst_ip = (const char *)&(ether_hdr->dst_addr);
- p_proto = (const char *)&(ether_hdr->next_proto_id);
ip_len = 4;
-
- data += sizeof(struct ipv4_hdr);
}
-
- else if (RTE_ETH_IS_IPV6_HDR(mbuf->packet_type))
+ else if(layer_type == LAYER_TYPE_IPV6)
{
- data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
const struct ipv6_hdr * ipv6_hdr = (const struct ipv6_hdr *)data;
p_str_ip = (const char *)&(ipv6_hdr->src_addr);
p_dst_ip = (const char *)&(ipv6_hdr->dst_addr);
- p_proto = (const char *)&(ipv6_hdr->proto);
ip_len = 16;
-
- data += sizeof(struct ipv6_hdr);
}
+ else return 0;
- // Not IPv4 or IPv6, cannot parse.
- else
- {
- return 0;
- }
+ uint32_t src_hash = rte_hash_crc(p_str_ip, ip_len, orin_hash);
+ uint32_t dst_hash = rte_hash_crc(p_dst_ip, ip_len, orin_hash);
+ return src_hash ^ dst_hash;
+}
- // Now Data is jumped from ether header and ip header;
- // Try to parse transport layer.
- // TCP Packets
- if (mbuf->packet_type & RTE_PTYPE_L4_TCP)
+static inline uint32_t __distributer_outer_tuple2(struct rte_mbuf * mbuf, uint32_t orin_hash)
+{
+ const char * data;
+ int layer_type;
+
+ if(RTE_ETH_IS_IPV4_HDR(mbuf->packet_type))
{
- const struct tcp_hdr * tcp_hdr = (const struct tcp_hdr *)data;
- p_src_port = (const char *)&tcp_hdr->src_port;
- p_dst_port = (const char *)&tcp_hdr->dst_port;
- data += sizeof(struct tcp_hdr);
+ data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
+ return hash_ip_layer(data, LAYER_TYPE_IPV4, orin_hash);
}
- // UDP Packets
- else if (mbuf->packet_type & RTE_PTYPE_L4_UDP)
+ else if(RTE_ETH_IS_IPV6_HDR(mbuf->packet_type))
{
- const struct udp_hdr * udp_hdr = (const struct udp_hdr *)data;
- p_src_port = (const char *)&udp_hdr->src_port;
- p_dst_port = (const char *)&udp_hdr->dst_port;
- data += sizeof(struct tcp_hdr);
+ data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
+ return hash_ip_layer(data, LAYER_TYPE_IPV6, orin_hash);
}
- // Not TCP or UDP Packets
else
{
- return 0;
+ data = complex_parser_ether(rte_pktmbuf_mtod(mbuf, const void *), LAYER_TYPE_ETHER,
+ LAYER_TYPE_IP, &layer_type);
+ return hash_ip_layer(data, layer_type, orin_hash);
}
+}
- // We have the address of necessory information,
- // caculate the hash value;
- src_hash = rte_hash_crc(p_str_ip, ip_len, src_hash);
- src_hash = rte_hash_crc(p_src_port, port_len, src_hash);
- dst_hash = rte_hash_crc(p_dst_ip, ip_len, dst_hash);
- dst_hash = rte_hash_crc(p_dst_port, port_len, dst_hash);
+static inline uint32_t __distributer_outer_tuple4(struct rte_mbuf * mbuf, uint32_t orin_hash)
+{
+ const char * data = NULL;
+ int layer_type = 0;
+ int layer_len = 0;
+
+ if (RTE_ETH_IS_IPV4_HDR(mbuf->packet_type))
+ {
+ data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
+ layer_type = LAYER_TYPE_IPV4;
+ }
+ else if (RTE_ETH_IS_IPV6_HDR(mbuf->packet_type))
+ {
+ data = rte_pktmbuf_mtod_offset(mbuf, const char *, sizeof(struct ether_hdr));
+ layer_type = LAYER_TYPE_IPV6;
+ }
- return src_hash ^ dst_hash;
+ if (layer_type == LAYER_TYPE_IPV4) layer_len = sizeof(struct ipv4_hdr);
+ else if (layer_type == LAYER_TYPE_IPV6) layer_len = sizeof(struct ipv6_hdr);
+ else return 0;
+
+ uint32_t ip_hash = hash_ip_layer(data, layer_type, orin_hash);
+ if (ip_hash == 0) return 0;
+
+ if(mbuf->packet_type & RTE_PTYPE_L4_TCP)
+ {
+ return hash_l4_layer(data + layer_len, LAYER_TYPE_TCP, ip_hash);
+ }
+ else if(mbuf->packet_type & RTE_PTYPE_L4_TCP)
+ {
+ return hash_l4_layer(data + layer_len, LAYER_TYPE_UDP, ip_hash);
+ }
+
+ return ip_hash;
}
//TODO: SSE/SSE2/AVX/AVX2加速
@@ -381,19 +341,19 @@ static uint32_t __hash_simple_tuple4(struct rte_mbuf * mbuf, uint32_t orin_hash
//TODO: 为0,也许有更好的处理方法。
//TODO: 缓存预取
-static inline int distributer_simple_tuple2(struct rte_mbuf * mbufs[],
+static inline int distributer_outer_tuple2(struct rte_mbuf * mbufs[],
unsigned int nr_mbufs, hash_t result[])
{
for (int i = 0; i < nr_mbufs; i++)
- result[i] = __hash_simple_tuple2(mbufs[i], 0);
+ result[i] = __distributer_outer_tuple2(mbufs[i], 0);
return 0;
}
-static inline int distributer_simple_tuple4(struct rte_mbuf * mbufs[],
+static inline int distributer_outer_tuple4(struct rte_mbuf * mbufs[],
unsigned int nr_mbufs, hash_t result[])
{
for (int i = 0; i < nr_mbufs; i++)
- result[i] = __hash_simple_tuple4(mbufs[i], 0);
+ result[i] = __distributer_outer_tuple2(mbufs[i], 0);
return 0;
}
@@ -423,10 +383,10 @@ int distributer_hash_caculate(unsigned int distmode, struct rte_mbuf * mbufs[],
{
switch (distmode)
{
- case LDBC_DIST_SIMPLE_TUPLE2:
- return distributer_simple_tuple2(mbufs, nr_mbufs, result);
- case LDBC_DIST_SIMPLE_TUPLE4:
- return distributer_simple_tuple4(mbufs, nr_mbufs, result);
+ case LDBC_DIST_OUTER_TUPLE2:
+ return distributer_outer_tuple2(mbufs, nr_mbufs, result);
+ case LDBC_DIST_OUTER_TUPLE4:
+ return distributer_outer_tuple4(mbufs, nr_mbufs, result);
case LDBC_DIST_HARDWARE:
return distributer_hardware(mbufs, nr_mbufs, result);
default:
diff --git a/service/src/monit.c b/service/src/monit.c
new file mode 100644
index 0000000..4de0cc7
--- /dev/null
+++ b/service/src/monit.c
@@ -0,0 +1,164 @@
+/* \brief ״̬����������
+ *
+ * \author Lu Qiuwen<[email protected]>
+ * \date 2016-11-30
+ */
+
+#include <sc_common.h>
+#include <mr_device.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "cJSON.h"
+
+static cJSON * __create_uint64_array(const uint64_t * value, int nr_value)
+{
+ struct cJSON * uint64_array = cJSON_CreateArray();
+ for (int i = 0; i < nr_value; i++)
+ cJSON_AddItemToArray(uint64_array, cJSON_CreateNumber(value[i]));
+ return uint64_array;
+}
+
+static cJSON * __create_raw_device_stats(struct rtdev_desc * dev_desc)
+{
+ struct rtdev_stat_info _stat_info;
+ mr_rtdev_stats_get(dev_desc, &_stat_info);
+
+ struct cJSON * j_raw_device_stats = cJSON_CreateObject();
+ unsigned int nr_serv_thread = dev_desc->nr_serv_stream;
+
+#define __JOIN_RAW_DEVICE_STATS_ITEM(item) do { \
+ cJSON_AddItemToObject(j_raw_device_stats, #item, \
+ __create_uint64_array(_stat_info.item, nr_serv_thread)); \
+} while(0)
+
+ __JOIN_RAW_DEVICE_STATS_ITEM(rx_on_line);
+ __JOIN_RAW_DEVICE_STATS_ITEM(rx_deliver);
+ __JOIN_RAW_DEVICE_STATS_ITEM(rx_missed);
+ __JOIN_RAW_DEVICE_STATS_ITEM(tx_on_line);
+ __JOIN_RAW_DEVICE_STATS_ITEM(tx_deliver);
+ __JOIN_RAW_DEVICE_STATS_ITEM(tx_missed);
+ __JOIN_RAW_DEVICE_STATS_ITEM(ftx_on_line);
+ __JOIN_RAW_DEVICE_STATS_ITEM(ftx_deliver);
+ __JOIN_RAW_DEVICE_STATS_ITEM(ftx_missed);
+
+ return j_raw_device_stats;
+}
+
+
+// ����ʱԭʼ�����豸ͳ�Ƽ���
+static cJSON * monit_raw_device(struct sc_instance * instance)
+{
+ struct cJSON * j_raw_device_array = cJSON_CreateArray();
+ struct sc_device * sc_device_iter = NULL;
+
+ TAILQ_FOREACH(sc_device_iter, &instance->device_list, next)
+ {
+ cJSON * j_raw_device = cJSON_CreateObject();
+ struct rtdev_desc * dev_desc = sc_device_iter->rt_dev;
+ if (dev_desc == NULL) continue;
+
+ cJSON_AddStringToObject(j_raw_device, "symbol", dev_desc->symbol);
+ cJSON_AddNumberToObject(j_raw_device, "streams", dev_desc->nr_serv_stream);
+ cJSON_AddItemToObject(j_raw_device, "stats", __create_raw_device_stats(dev_desc));
+ cJSON_AddItemToArray(j_raw_device_array, j_raw_device);
+ }
+
+ return j_raw_device_array;
+}
+
+// ��������ͳ�Ƽ���
+static cJSON * __create_device_stats(struct mr_dev * dev)
+{
+ struct cJSON * j_device_stats = cJSON_CreateObject();
+ struct rte_eth_stats _eth_stat;
+ rte_eth_stats_get(dev->port_id, &_eth_stat);
+
+ cJSON_AddNumberToObject(j_device_stats, "ipackets", _eth_stat.ipackets);
+ cJSON_AddNumberToObject(j_device_stats, "opackets", _eth_stat.opackets);
+ cJSON_AddNumberToObject(j_device_stats, "ibytes", _eth_stat.ibytes);
+ cJSON_AddNumberToObject(j_device_stats, "obytes", _eth_stat.obytes);
+ cJSON_AddNumberToObject(j_device_stats, "imissed", _eth_stat.imissed);
+ cJSON_AddNumberToObject(j_device_stats, "ierrors", _eth_stat.ierrors);
+ cJSON_AddNumberToObject(j_device_stats, "oerrors", _eth_stat.oerrors);
+ cJSON_AddNumberToObject(j_device_stats, "rxnombuf", _eth_stat.rx_nombuf);
+ return j_device_stats;
+}
+
+// ����������·��Ϣ���
+static cJSON * __create_device_link(struct mr_dev * dev)
+{
+ struct cJSON * j_device_link = cJSON_CreateObject();
+ struct rte_eth_link _eth_link;
+
+ rte_eth_link_get_nowait(dev->port_id, &_eth_link);
+ cJSON_AddNumberToObject(j_device_link, "LinkSpeed", _eth_link.link_speed);
+ cJSON_AddBoolToObject(j_device_link, "LinkDuplex", _eth_link.link_duplex);
+ cJSON_AddBoolToObject(j_device_link, "LinkAutoNeg", _eth_link.link_autoneg);
+ cJSON_AddBoolToObject(j_device_link, "LinkStatus", _eth_link.link_status);
+ return j_device_link;
+}
+
+// ��������������Ϣ���
+static cJSON * __create_device_info(struct mr_dev * dev)
+{
+ struct cJSON * j_device_info = cJSON_CreateObject();
+
+ char str_ether_addr[MR_STRING_MAX];
+ ether_format_addr(str_ether_addr, sizeof(str_ether_addr), &dev->ether_addr);
+
+ struct rte_pci_addr * pci_addr = &dev->info.pci_addr;
+ char str_pci_addr[MR_STRING_MAX];
+ snprintf(str_pci_addr, sizeof(str_pci_addr), PCI_PRI_FMT, pci_addr->bus,
+ pci_addr->devid, pci_addr->domain, pci_addr->function);
+
+ cJSON_AddStringToObject(j_device_info, "EtherAddr", str_ether_addr);
+ cJSON_AddStringToObject(j_device_info, "PCIAddr", str_pci_addr);
+ cJSON_AddNumberToObject(j_device_info, "PortID", dev->port_id);
+ cJSON_AddNumberToObject(j_device_info, "RxQueueCount", dev->nr_rxq);
+ cJSON_AddNumberToObject(j_device_info, "TxQueueCount", dev->nr_txq);
+ cJSON_AddNumberToObject(j_device_info, "MTU", dev->mtu);
+
+ return j_device_info;
+}
+
+// ���������豸���
+static cJSON * monit_device_info(struct sc_instance * sc_instance)
+{
+ struct cJSON * j_device_array = cJSON_CreateArray();
+
+ int nr_devices = 0;
+ struct mr_dev * mr_dev_info[MR_DEVICE_MAX];
+ nr_devices = mr_device_list(sc_instance->core_instance, mr_dev_info, MR_DEVICE_MAX, 0);
+
+ for(int i = 0; i < nr_devices; i++)
+ {
+ struct cJSON * j_device = cJSON_CreateObject();
+ cJSON_AddStringToObject(j_device, "symbol", mr_dev_info[i]->symbol);
+ cJSON_AddItemToObject(j_device, "information", __create_device_info(mr_dev_info[i]));
+ cJSON_AddItemToObject(j_device, "link", __create_device_link(mr_dev_info[i]));
+ cJSON_AddItemToObject(j_device, "stats", __create_device_stats(mr_dev_info[i]));
+ cJSON_AddItemToArray(j_device_array, j_device);
+ }
+
+ return j_device_array;
+}
+
+static cJSON * monit_root(struct sc_instance * sc_instance)
+{
+ struct cJSON * j_root = cJSON_CreateObject();
+ cJSON_AddItemToObject(j_root, "device", monit_device_info(sc_instance));
+ cJSON_AddItemToObject(j_root, "raw", monit_raw_device(sc_instance));
+ return j_root;
+}
+
+int sc_monit_loop(struct sc_instance * sc_instance)
+{
+ FILE * fp_monit = fopen(sc_instance->local_monitfile, "w");
+ cJSON * j_root = monit_root(sc_instance);
+ char * str_json_print = cJSON_Print(j_root);
+ fprintf(fp_monit, "%s", str_json_print);
+ free(j_root);
+ fclose(fp_monit);
+ return 0;
+} \ No newline at end of file
diff --git a/service/src/register.c b/service/src/register.c
index afb0322..c0d48b9 100644
--- a/service/src/register.c
+++ b/service/src/register.c
@@ -16,11 +16,13 @@
#include <mr_common.h>
#include <sc_common.h>
#include <mr_device.h>
-#include <mr_vman.h>
#include <mr_mask.h>
+#include <mr_rtdev.h>
#include <assert.h>
#include <mr_runtime.h>
#include <mr_rtdev.h>
+#include <MESA_prof_load.h>
+#include <mr_buffer.h>
static int sc_core_instance_register(struct sc_instance * instance)
{
@@ -34,37 +36,93 @@ static int sc_core_instance_register(struct sc_instance * instance)
"%s", instance->local_cfgfile);
// 初始化核心库句柄
- instance->core_instance = mr_core_instance_create(g_cfg);
+ instance->core_instance = mr_core_instance_create(NULL);
mr_core_default_instance_set(instance->core_instance);
g_ctx->ctx_core = instance->core_instance;
return 0;
}
+static int sc_core_ctrlzone_register(struct sc_instance * instance)
+{
+ struct sc_ctrlzone * ctrlzone_iter;
+ TAILQ_FOREACH(ctrlzone_iter, &instance->ctrlzone_list, next)
+ {
+ int ret = mr_buffer_ctrlzone_register(instance->core_instance,
+ ctrlzone_iter->symbol, ctrlzone_iter->id, ctrlzone_iter->size);
+
+ if(ret < 0)
+ {
+ MR_LOG(ERR, SERVICE, "Register ctrlzone %s(size=%d, id=%d) failed. ",
+ ctrlzone_iter->symbol, ctrlzone_iter->size, ctrlzone_iter->id);
+ return -1;
+ }
+
+ MR_LOG(INFO, SERVICE, "Register ctrlzone %s(size=%d, id=%d) successfully. \n",
+ ctrlzone_iter->symbol, ctrlzone_iter->size, ctrlzone_iter->id);
+ }
+
+ return 0;
+}
+
+static int sc_core_user_pktmbuf_pool_register(struct sc_instance * instance)
+{
+ int ret = mr_buffer_user_pool_produce(instance->core_instance, SOCKET_ID_ANY,
+ instance->sc_param.sz_user_pktmbuf, instance->sc_param.nr_user_direct_pktmbuf,
+ instance->sc_param.sz_user_pktmbuf_cache);
+
+ if(ret < 0)
+ {
+ MR_LOG(ERR, SERVICE, "Produce user pktmbuf pool(nr_pktmbuf=%d, sz_pktmbuf=%d, sz_cache=%d) failed. \n",
+ instance->sc_param.sz_user_pktmbuf, instance->sc_param.nr_user_direct_pktmbuf,
+ instance->sc_param.sz_user_pktmbuf_cache);
+ }
+ else
+ {
+ MR_LOG(ERR, SERVICE, "User pktmbuf pool(nr_pktmbuf=%d, sz_pktmbuf=%d, sz_cache=%d) created. \n",
+ instance->sc_param.sz_user_pktmbuf, instance->sc_param.nr_user_direct_pktmbuf,
+ instance->sc_param.sz_user_pktmbuf_cache);
+ }
+
+ return ret;
+}
+
static int sc_stack_instance_register(struct sc_instance * instance)
{
// 获取全局配置句柄和全局运行时句柄
- struct mr_global_config * g_cfg = mr_global_config_get();
struct mr_global_ctx * g_ctx = mr_global_ctx_get();
- assert(g_cfg != NULL && g_ctx != NULL);
+ assert(g_ctx != NULL);
+
+ // 取默认内存池地址
+ instance->sk_param.def_direct_pktmbuf_pool = mr_buffer_user_direct_pool_get(
+ instance->core_instance, SOCKET_ID_ANY);
+
+ instance->sk_param.def_indirect_pktmbuf_pool = mr_buffer_user_indirect_pool_get(
+ instance->core_instance, SOCKET_ID_ANY);
// 初始化协议栈全局句柄
- instance->sk_instance = mr_stack_instance_create(&instance->sk_param);
+ instance->sk_instance = sk_instance_create(instance->core_instance, &instance->sk_param);
g_ctx->ctx_stack = instance->sk_instance;
+
+ // 初始化服务进程句柄
+ instance->sk_serv_instance = sk_app_instance_create(instance->sk_instance, instance->procsym);
return 0;
}
static int __mr_dev_register(struct sc_instance * instance,
struct sc_device * sc_dev)
{
- // 计算默认队列数,队列数等于IO核心数
- int nr_queues = mask_popcnt(instance->cpu_mask);
+ struct sc_param * sc_param = &instance->sc_param;
// 没有指定队列数,采用默认的队列数
- if (sc_dev->mr_dev_param.nr_queues == 0)
- sc_dev->mr_dev_param.nr_queues = nr_queues;
+ if (sc_dev->mr_dev_param.nr_rss_rxq == 0)
+ sc_dev->mr_dev_param.nr_rss_rxq = sc_param->nr_serv_thread;
+
+ if (sc_dev->mr_dev_param.nr_rss_txq == 0)
+ sc_dev->mr_dev_param.nr_rss_txq = sc_param->nr_serv_thread;
// 打开设备
- mr_dev_t * dev = mr_device_open(&sc_dev->mr_dev_param);
+ struct mr_dev * dev = mr_device_open(instance->core_instance,
+ &sc_dev->mr_dev_param);
// 失败
if (unlikely(dev == NULL))
@@ -75,33 +133,45 @@ static int __mr_dev_register(struct sc_instance * instance,
return -1;
}
+ // 打开设备队列
+ for (int i = 0; i < sc_param->nr_serv_thread; i++)
+ {
+ sc_dev->rx_devq[i] = mr_device_attach(dev, DEVQ_TYPE_RSS_RX);
+ sc_dev->tx_devq[i] = mr_device_attach(dev, DEVQ_TYPE_RSS_TX);
+ assert(sc_dev->rx_devq[i] != NULL && sc_dev->tx_devq[i] != NULL);
+ }
+
sc_dev->dev = dev;
+ sc_dev->en_mr_dev = 1;
return 0;
}
static int __rt_dev_register(struct sc_instance * instance,
struct sc_device * sc_dev)
{
- // 计算默认队列数,队列数等于IO核心数
- int nr_queues = mask_popcnt(instance->cpu_mask);
-
+ struct sc_param * sc_param = &instance->sc_param;
+
+ // 获取mempool指针
+ struct rte_mempool * direct_pool = mr_device_direct_pool_get(sc_dev->dev);
+ assert(direct_pool != NULL);
+
// 创建运行时设备
- int ret = rt_device_serv_create(sc_dev->symbol, instance->procsym,
- nr_queues, instance->sz_rxvnode_ring, instance->sz_rxvnode_buffer);
-
- if (unlikely(ret < 0))
+ struct rtdev_desc * rtdev = mr_rtdev_create(instance->core_instance, sc_dev->symbol,
+ direct_pool, sc_param->nr_serv_thread, sc_param->sz_tunnel,
+ sc_param->sz_buffer);
+
+ if (unlikely(rtdev == NULL))
{
- MR_LOG(WARNING, SERVICE, "Service, RtdeviceRegister, "
- "Rtdevice %s(nr_queue=%d, sz_tunnel=%d, sz_buffer=%d) create failed. \n",
- sc_dev->symbol, nr_queues, instance->sz_rxvnode_ring,
- instance->sz_rxvnode_buffer);
- return ret;
+ MR_LOG(ERR, SERVICE, "Rtdevice %s(nr_queue=%d, sz_tunnel=%d, sz_buffer=%d) create failed. \n",
+ sc_dev->symbol, sc_param->nr_serv_thread, sc_param->sz_tunnel, sc_param->sz_buffer);
+ return -1;
}
- MR_LOG(INFO, SERVICE, "Service, RtdeviceRegister, "
- "Rtdevice %s(nr_queue=%d, sz_tunnel=%d, sz_buffer=%d) created. \n",
- sc_dev->symbol, nr_queues, instance->sz_rxvnode_ring,
- instance->sz_rxvnode_buffer);
+ sc_dev->rt_dev = rtdev;
+ sc_dev->en_rt_dev = 1;
+
+ MR_LOG(INFO, SERVICE, "Rtdevice %s(nr_queue=%d, sz_tunnel=%d, sz_buffer=%d) created. \n",
+ sc_dev->symbol, sc_param->nr_serv_thread, sc_param->sz_tunnel, sc_param->sz_buffer);
return 0;
}
@@ -112,24 +182,55 @@ static int __sk_dev_register(struct sc_instance * instance,
// 跳过没有启用协议栈的设备
if(!(sc_dev->en_mr_dev && sc_dev->en_sk_dev))
{
- MR_LOG(INFO, SERVICE, "Service, StackDeviceRegister, "
- "StackDevice %s is disable, ignore. \n", sc_dev->symbol);
+ MR_LOG(INFO, SERVICE, "Device %s user-mode stack is disable, ignore. \n", sc_dev->symbol);
return 0;
}
- // 创建协议栈设备
- int ret = mr_stack_device_create(instance->sk_instance,
- &sc_dev->sk_dev_param);
+ // 从真实设备中,填充MAC地址等信息
+ struct mr_dev * dev = mr_device_lookup(instance->core_instance, sc_dev->mr_dev_param.symbol);
+ assert(dev != NULL);
+
+ sc_dev->sk_dev_param.mtu = dev->mtu;
+ ether_addr_copy(&dev->ether_addr, &sc_dev->sk_dev_param.mac_addr);
+
+ struct sc_param * sc_param = &instance->sc_param;
+ struct rte_mempool * direct_pool = mr_device_direct_pool_get(sc_dev->dev);
+ struct rte_mempool * indirect_pool = mr_device_direct_pool_get(sc_dev->dev);
+ assert(direct_pool != NULL && indirect_pool != NULL);
+ sc_dev->sk_dev_param.direct_pktmbuf_pool = direct_pool;
+ sc_dev->sk_dev_param.indirect_pktmbuf_pool = indirect_pool;
+
+ // 创建设备
+ int ret = sk_device_create(instance->sk_instance, &sc_dev->sk_dev_param);
+
if(unlikely(ret < 0))
{
- MR_LOG(WARNING, SERVICE, "Service, StackDeviceRegister, "
- "StackDevice %s create failed. \n", sc_dev->sk_dev_param.symbol);
- return ret;
+ MR_LOG(WARNING, SERVICE, "StackDevice %s create failed. \n", sc_dev->sk_dev_param.symbol);
+ return -1;
}
- MR_LOG(WARNING, SERVICE, "Service, StackDeviceRegister, "
- "StackDevice %s created. \n", sc_dev->sk_dev_param.symbol);
+ // 打开设备,主应用只启用自循环收发队列,不启用TCP/UDP队列
+ struct sk_dev_open_param dev_open_param;
+ snprintf(dev_open_param.symbol, sizeof(dev_open_param.symbol), "%s", sc_dev->symbol);
+ dev_open_param.mode = SK_DEV_MODE_SERV;
+ dev_open_param.nr_loop_rxstream = sc_param->nr_serv_thread;
+ dev_open_param.nr_loop_txstream = sc_param->nr_serv_thread;
+ dev_open_param.nr_tcp_rxstream = 0;
+ dev_open_param.nr_tcp_txstream = 0;
+ dev_open_param.nr_udp_rxstream = 0;
+ dev_open_param.nr_udp_txstream = 0;
+
+ struct sk_dev_desc * dev_desc = sk_device_open(instance->sk_serv_instance, &dev_open_param);
+ if (unlikely(dev_desc == NULL))
+ {
+ MR_LOG(WARNING, SERVICE, "StackDevice %s open failed. \n", sc_dev->sk_dev_param.symbol);
+ return -2;
+ }
+
+ sc_dev->sk_dev = dev_desc;
+ sc_dev->en_sk_dev = 1;
+ MR_LOG(INFO, SERVICE, "StackDevice %s created. \n", sc_dev->sk_dev_param.symbol);
return 0;
}
@@ -155,8 +256,7 @@ static int sc_device_register(struct sc_instance * instance)
// 打开失败,移除设备链表
device_open_fail:
- MR_LOG(ERR, SERVICE, "ServiceDeviceRegister, "
- "Device %s register failed. Disabled. \n", device_iter->symbol);
+ MR_LOG(ERR, SERVICE, "Device %s register failed. Disabled. \n", device_iter->symbol);
TAILQ_REMOVE(&instance->device_list, device_iter, next);
}
@@ -169,14 +269,12 @@ int sc_app_register(struct sc_instance * instance)
int ret = mr_app_manager_appinfo_register(instance->procsym, instance->cpu_mask);
if(ret < 0)
{
- MR_LOG(ERR, SERVICE, "Service, AppRegister, "
- "Cannot register service application(sym=%s, cpu_mask=%"PRIx64")",
+ MR_LOG(ERR, SERVICE, "Cannot register service application(sym=%s, cpu_mask=%"PRIx64")",
instance->procsym, instance->cpu_mask);
return ret;
}
- MR_LOG(INFO, SERVICE, "Service, AppRegister, "
- "App(symbol=%s) Process(cpu_mask=%"PRIx64") registered.\n",
+ MR_LOG(INFO, SERVICE, "App(symbol=%s) Process(cpu_mask=%"PRIx64") registered.\n",
instance->procsym, instance->cpu_mask);
return 0;
@@ -186,6 +284,10 @@ void sc_stage_register(struct sc_instance * instance)
{
MR_CHECK(sc_core_instance_register(instance) >= 0,
"Cannot register core instance, Failed. Please recheck runtime log. ");
+ MR_CHECK(sc_core_ctrlzone_register(instance) >= 0,
+ "Cannot register control zone, Failed. Please recheck runtime log.");
+ MR_CHECK(sc_core_user_pktmbuf_pool_register(instance) >= 0,
+ "Cannot register control zone, Failed. Please recheck runtime log.");
MR_CHECK(sc_stack_instance_register(instance) >= 0,
"Cannot register stack instance, Failed. Please recheck runtime log. ");
MR_CHECK(sc_app_register(instance) >= 0,
diff --git a/service/src/runtime.c b/service/src/runtime.c
deleted file mode 100644
index ddb3574..0000000
--- a/service/src/runtime.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <assert.h>
-#include <rte_malloc.h>
-#include <rte_log.h>
-#include <mr_common.h>
-#include <mr_runtime.h>
-#include <mr_device.h>
-#include <sc_common.h>
-
-
-void sc_thread_instance_init(struct sc_instance * instance,
- struct sc_thread_instance * tinstance)
-{
- tinstance->rt_dev = rte_zmalloc(NULL, sizeof(struct sc_rt_device) * instance->nr_devs, 0);
- tinstance->nr_devices = 0;
- assert(tinstance->rt_dev != NULL);
- return;
-}
-
-void sc_thread_device_attach(struct sc_instance * instance,
- struct sc_thread_instance * tinstance)
-{
- struct sc_device * sc_dev_iter;
- int nr_devices = 0;
-
- TAILQ_FOREACH(sc_dev_iter, &instance->device_list, next)
- {
- // 附着设备,取出队列描述符
- mr_devq_t * devq = mr_device_attach(sc_dev_iter->symbol);
- if (devq == NULL)
- {
- MR_LOG(WARNING, SERVICE, "Service, RuntimeThread, "
- "Cannot attach device %s for thread %d, Ignore the device.\n",
- sc_dev_iter->symbol, mr_thread_id());
- continue;
- }
-
- // 附着运行时设备
- struct mr_rtdev_stream * rtstream;
- rtstream = rt_dev_serv_open_stream(sc_dev_iter->symbol,
- instance->procsym);
-
- if (rtstream == NULL)
- {
- MR_LOG(WARNING, SERVICE, "Service, RuntimeThread, "
- "Cannot attach rtdevice %s for thread %d, Ignore the device.\n",
- sc_dev_iter->symbol, mr_thread_id());
- continue;
- }
-
- MR_LOG(INFO, SERVICE, "Service, RuntimeThread, "
- "Attach Device %s for thread %d success.\n",
- sc_dev_iter->symbol, mr_thread_id());
-
- // 存储句柄到私有存储空间,下面收发包时使用
- tinstance->rt_dev[nr_devices].devq = devq;
- tinstance->rt_dev[nr_devices].rtstream = rtstream;
- nr_devices++;
- }
-
- tinstance->nr_devices = nr_devices;
- return;
-}
-
-extern void sc_thread_rx_loop(struct sc_instance * instance,
- struct sc_thread_instance * tinstance);
-
-extern void sc_thread_tx_loop(struct sc_instance * instance,
- struct sc_thread_instance * tinstance);
-
-extern void sc_thread_timer_loop(struct sc_instance * instance,
- struct sc_thread_instance * tinstance);
-
-void * sc_runtime_thread(void * args)
-{
- mr_app_manager_thread_register();
- struct sc_instance * instance = (struct sc_instance *)args;
-
- MR_LOG(INFO, SERVICE, "Service, RuntimeThread, "
- "Thread ID %d Running, CPU_ID=%d, Socket_ID=%d\n",
- mr_thread_id(), mr_cpu_id(), mr_socket_id());
-
- /* 分配线程私有存储空间 */
- struct sc_thread_instance * tinstance;
- tinstance = rte_zmalloc(NULL, sizeof(struct sc_thread_instance), 0);
- MR_CHECK(tinstance != NULL, "Service, RuntimeThread, "
- "Cannot alloc memory for thread private instance, Failed.\n");
-
- /* 初始化线程私有存储空间 */
- sc_thread_instance_init(instance, tinstance);
- /* 线程Attach设备操作 */
- sc_thread_device_attach(instance, tinstance);
-
- while(1)
- {
- sc_thread_rx_loop(instance, tinstance);
- sc_thread_tx_loop(instance, tinstance);
- sc_thread_timer_loop(instance, tinstance);
- }
-
- return NULL;
-} \ No newline at end of file
diff --git a/service/src/rxtx.c b/service/src/rxtx.c
index cd6fc13..d52df25 100644
--- a/service/src/rxtx.c
+++ b/service/src/rxtx.c
@@ -1,9 +1,9 @@
#include <rte_ethdev.h>
#include <sc_common.h>
#include <mr_common.h>
-#include <mr_vman.h>
#include <mr_stat.h>
#include <mr_vnode.h>
+#include <unistd.h>
extern int distributer_hash_caculate(unsigned int distmode, struct rte_mbuf * mbufs[],
unsigned int nr_mbufs, hash_t result[]);
@@ -15,73 +15,159 @@ void __free_mbufs(struct rte_mbuf * bufs[], int nr_bufs)
return;
}
-static inline void __rx_loop_one_device(struct sc_instance * instance,
- struct sc_thread_instance * tinstance, struct sc_rt_device * rtdev,
- unsigned int nr_rx_burst)
+int rt_serv_device_rx_bulk(struct rtdev_desc * dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbufs_in[], int nr_mbufs_in)
{
- struct rte_mbuf * rx_bufs[MR_BURST_MAX];
- hash_t hash_result[MR_BURST_MAX];
+ hash_t hash[MR_BURST_MAX];
+
+ for (int i = 0; i < nr_mbufs_in; i++)
+ hash[i] = mbufs_in[i]->hash.usr;
+
+ int ret = vnode_enqueue_burst_with_hash(dev_desc->vnode_prod_rx,
+ &dev_desc->ops, sid, (void **)mbufs_in, hash, nr_mbufs_in);
+
+ if (likely(ret < 0)) return 0;
+ for (int i = 0; i < nr_mbufs_in; i++) mbufs_in[i] = NULL;
+ return nr_mbufs_in;
+}
+
+int rt_serv_device_tx_bulk(struct rtdev_desc * dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbufs_out[], int nr_mbufs)
+{
+ int __nr_mbufs_out = 0;
+ int __nr_mbufs_left = nr_mbufs;
+
+ // ��FTXͨ��ȡ��
+ int ret = vnode_dequeue_burst(dev_desc->vnode_cons_ftx, &dev_desc->ops, sid,
+ (void **)&mbufs_out[__nr_mbufs_out], __nr_mbufs_left);
+
+ __nr_mbufs_out += ret;
+ __nr_mbufs_left -= ret;
+ assert(__nr_mbufs_left >= 0);
+
+ // ʣ�����������TXͨ��ȡ
+ ret = vnode_dequeue_burst(dev_desc->vnode_cons_tx, &dev_desc->ops, sid,
+ (void **)&mbufs_out[__nr_mbufs_out], __nr_mbufs_left);
+
+ __nr_mbufs_out += ret;
+ __nr_mbufs_left -= ret;
+ assert(__nr_mbufs_left >= 0);
+
+ return __nr_mbufs_out;
+}
+
+static inline void __tx_loop_one_device(struct sc_instance * instance, thread_id_t tid,
+ struct sc_device * sc_dev, unsigned int nr_tx_burst)
+{
+ struct rte_mbuf * tx_bufs[MR_BURST_MAX];
+ int nr_tx_bufs = 0;
+ int nr_tx_bufs_left = nr_tx_burst;
int ret;
- mr_devq_t * devq = rtdev->devq;
- struct mr_rtdev_stream * rtstream = rtdev->rtstream;
+ struct mr_dev_q * devq = sc_dev->rx_devq[tid];
+ assert(devq != NULL);
+
+ // ����Э��ջ���豸��ȫ���͵�Э��ջ
+ if (sc_dev->en_sk_dev)
+ {
+ ret = sk_serv_device_tx_bulk(sc_dev->sk_dev, tid, &tx_bufs[nr_tx_bufs], nr_tx_bufs_left);
+ nr_tx_bufs += ret;
+ nr_tx_bufs_left -= ret;
+ }
+ else
+ {
+ ret = rt_serv_device_tx_bulk(sc_dev->rt_dev, tid, &tx_bufs[nr_tx_bufs], nr_tx_bufs_left);
+ nr_tx_bufs += ret;
+ nr_tx_bufs_left -= ret;
+ }
+
+ ret = rte_eth_tx_burst(devq->port_id, devq->queue_id, tx_bufs, nr_tx_bufs);
+ if(unlikely(ret < nr_tx_bufs))
+ {
+ for (int i = ret; i < nr_tx_bufs; i++) rte_pktmbuf_free(tx_bufs[i]);
+ }
+
+ return;
+}
- uint16_t nr_rx_bufs = rte_eth_rx_burst(devq->port_id,
- devq->rx_queue_id, rx_bufs, nr_rx_burst);
+static inline void __rx_loop_one_device(struct sc_instance * instance, thread_id_t tid,
+ struct sc_device * sc_dev, unsigned int nr_rx_burst)
+{
+ struct rte_mbuf * rx_bufs_in[MR_BURST_MAX];
+ hash_t hash_result[MR_BURST_MAX];
- // û�����ݰ�ֱ������
- if (unlikely(nr_rx_bufs == 0)) return;
+ int nr_rx_bufs_in;
+ struct mr_dev_q * devq = sc_dev->rx_devq[tid];
+ assert(devq != NULL);
+
+ nr_rx_bufs_in = rte_eth_rx_burst(devq->port_id, devq->queue_id, rx_bufs_in, nr_rx_burst);
+ if (unlikely(nr_rx_bufs_in == 0)) return;
- int nr_rx_bufs_len = pktslen(rx_bufs, nr_rx_bufs);
- UPDATE_DEV_STAT(dev_rx_frame, devq->port_id, nr_rx_bufs);
+ int nr_rx_bufs_len = pktslen(rx_bufs_in, nr_rx_bufs_in);
+ UPDATE_DEV_STAT(dev_rx_frame, devq->port_id, nr_rx_bufs_in);
UPDATE_DEV_STAT(dev_rx_bit, devq->port_id, nr_rx_bufs_len);
- UPDATE_APP_STAT(rx_frame, nr_rx_bufs);
+ UPDATE_APP_STAT(rx_frame, nr_rx_bufs_in);
UPDATE_APP_STAT(rx_byte, nr_rx_bufs_len);
- // �������ݰ����طֵ�ʹ�õ�Hashֵ
- ret = distributer_hash_caculate(instance->distmode,
- rx_bufs, nr_rx_bufs, hash_result);
- if (unlikely(ret < 0)) goto err_free_mbufs;
-
- // ����VNode�У��ַ�����Ӧ��
- struct vnodeman_attach_desc * attach_desc = rtstream->rxd;
- ret = vnode_enqueue_burst_with_hash(attach_desc->prod, &vnodeman_ops,
- attach_desc->queue_id, (void **)rx_bufs, hash_result, nr_rx_bufs);
- if (unlikely(ret < 0)) goto err_free_mbufs;
- return;
+ int ret = distributer_hash_caculate(instance->sc_param.distmode,
+ rx_bufs_in, nr_rx_bufs_in, hash_result);
-err_free_mbufs:
- for (int i = 0; i < nr_rx_bufs; i++)
- rte_pktmbuf_free(rx_bufs[i]);
+ if (unlikely(ret < 0)) goto clean;
+ for (int i = 0; i < nr_rx_bufs_in; i++) rx_bufs_in[i]->hash.usr = hash_result[i];
- UPDATE_APP_STAT(drop_frame, nr_rx_bufs);
+ // ����Э��ջ���豸��ȫ���͵�Э��ջ
+ if (sc_dev->en_sk_dev)
+ {
+ sk_serv_device_rx_bulk(sc_dev->sk_dev, tid, rx_bufs_in, nr_rx_bufs_in);
+ }
+ else
+ {
+ rt_serv_device_rx_bulk(sc_dev->rt_dev, tid, rx_bufs_in, nr_rx_bufs_in);
+ }
+
+clean:
+ for (int i = 0; i < nr_rx_bufs_in; i++)
+ {
+ if (rx_bufs_in[i] != NULL) rte_pktmbuf_free(rx_bufs_in[i]);
+ }
+
return;
}
-
-void sc_thread_rx_loop(struct sc_instance * instance,
- struct sc_thread_instance * tinstance)
+void sc_thread_rxtx_loop(struct sc_instance * instance, thread_id_t tid)
{
PERF_BEGIN(sc_rx_loop_all);
+ unsigned int sz_burst = instance->sc_param.sz_burst;
- for (unsigned int i = 0; i < tinstance->nr_devices; i++)
+ struct sc_device * device_iter;
+ TAILQ_FOREACH(device_iter, &instance->device_list, next)
{
- __rx_loop_one_device(instance, tinstance,
- &tinstance->rt_dev[i], instance->sz_rx_burst);
+ __rx_loop_one_device(instance, tid, device_iter, sz_burst);
+ __tx_loop_one_device(instance, tid, device_iter, sz_burst);
}
PERF_END(sc_rx_loop_all);
return;
}
-void sc_thread_tx_loop(struct sc_instance * instance,
- struct sc_thread_instance * tinstance)
+void sc_thread_timer_loop(struct sc_instance * instance, thread_id_t tid)
{
return;
}
-void sc_thread_timer_loop(struct sc_instance * instance,
- struct sc_thread_instance * tinstance)
+void * sc_runtime_thread(void * args)
{
- return;
+ mr_app_manager_thread_register();
+ struct sc_instance * instance = (struct sc_instance *)args;
+ thread_id_t tid = mr_thread_id();
+
+ MR_LOG(INFO, SERVICE, "Thread %d Running...\n", mr_thread_id());
+
+ while (1)
+ {
+ sc_thread_rxtx_loop(instance, tid);
+ sc_thread_timer_loop(instance, tid);
+ }
+
+ return NULL;
} \ No newline at end of file
diff --git a/slave/CMakeLists.txt b/slave/CMakeLists.txt
deleted file mode 100644
index 3684199..0000000
--- a/slave/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-find_package(DPDK REQUIRED)
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_SOURCE_DIR}/include/extern)
-include_directories(${CMAKE_SOURCE_DIR}/include/internal)
-include_directories(${DPDK_INCLUDE_DIR})
-
-include_directories(include)
-add_definitions(${DPDK_C_PREDEFINED})
-add_library(marsio src/marsio.c src/rawio.c)
-target_link_libraries(marsio ${DPDK_LIBRARY} MESA_prof_load_static)
-target_link_libraries(marsio rt pthread dl core)
-target_include_directories(marsio INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/") \ No newline at end of file
diff --git a/slave/include/mrlib.h b/slave/include/mrlib.h
deleted file mode 100644
index 105f25b..0000000
--- a/slave/include/mrlib.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-
-int marsio_init(const char * appsym, uint64_t coremask, unsigned autoexit, FILE * logstream);
-int marsio_thread_init();
-int marsio_destory();
-
-extern struct mrlib_instance * instance;
-
-#ifdef __cplusplus
-}
-#endif \ No newline at end of file
diff --git a/slave/include/mrlib_common.h b/slave/include/mrlib_common.h
deleted file mode 100644
index 0bc8a7a..0000000
--- a/slave/include/mrlib_common.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <mr_common.h>
-#include <mr_device.h>
-
-struct __raw_socket;
-TAILQ_HEAD(raw_socket_list, __raw_socket);
-
-struct mrlib_instance
-{
- /* Ӧ������ */
- char appsym[MR_SYMBOL_MAX];
- /* �򿪵�ԭʼ�׽��־�� */
- struct raw_socket_list raw_socket_list;
-};
-
-/* ��־λ���Ƿ��Ѿ������˳�ʼ��*/
-extern int __mrlib_inited;
-/* ��־λ�����߳��Ƿ��Ѿ������˳�ʼ�� */
-extern int __thread __mrlib_thread_inited; \ No newline at end of file
diff --git a/slave/src/marsio.c b/slave/src/marsio.c
deleted file mode 100644
index 6fd019e..0000000
--- a/slave/src/marsio.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <rte_log.h>
-#include <mr_common.h>
-#include <mr_core.h>
-#include <mrlib.h>
-#include <mrlib_common.h>
-#include <rte_malloc.h>
-#include <mr_runtime.h>
-
-/* ��־λ���Ƿ��Ѿ������˳�ʼ��*/
-int __mrlib_inited = 0;
-/* ��־λ�����߳��Ƿ��Ѿ������˳�ʼ�� */
-int __thread __mrlib_thread_inited = 0;
-/* ���������Ľṹ */
-struct mrlib_instance * instance = NULL;
-
-#define MR_LIB_MAX_EAL_ARGC 128
-
-/* �Command���� */
-static void __write_arg(char * eal_argv[], unsigned int * eal_argc,
- unsigned int max_argc, const char * value)
-{
- assert(max_argc >= *eal_argc);
- char * mem = (char *)malloc(MR_STRING_MAX * sizeof(char));
- assert(mem != NULL);
-
- snprintf(mem, MR_STRING_MAX * sizeof(char), "%s", value);
- eal_argv[(*eal_argc)++] = mem;
- return;
-}
-
-#define WRITE_ARG(x) \
- do {__write_arg(eal_argv, &eal_argc, MR_LIB_MAX_EAL_ARGC, x);} \
- while(0)
-
-/* EAL������ʼ�� */
-static void mrlib_stage_eal_init()
-{
- char * eal_argv[MR_LIB_MAX_EAL_ARGC];
- unsigned int eal_argc = 0;
-
- WRITE_ARG("mrlib");
- WRITE_ARG("--proc-type=secondary");
-
- int ret = rte_eal_init(eal_argc, eal_argv);
- MR_CHECK(ret >= 0, "Cannot init EAL Enviorment, Failed");
- return;
-}
-
-static void mrlib_slave_log_ready(FILE * logstream)
-{
- if (logstream == NULL) logstream = stderr;
- rte_openlog_stream(logstream);
-}
-
-static int mrlib_slave_appinfo_register(const char * progsym,
- uint64_t coremask, unsigned autoexit)
-{
- // ע��Ӧ��
- int ret = mr_app_register(progsym, coremask, autoexit);
- if(ret < 0)
- {
- MR_LOG(ERR, MRLIB, "Mrlib, SlaveProcInfoReady, "
- "Cannot register local process %s. \n", progsym);
- return -1;
- }
-
- MR_LOG(INFO, MRLIB, "Mrlib, SlaveProcInfoReady, "
- "Process %s register success. \n", progsym);
-
- // ע����Ŀ��Slave���
- struct mr_global_ctx * g_ctx = mr_global_ctx_get();
- mr_core_default_instance_set(g_ctx->ctx_core);
- return 0;
-}
-
-static int mrlib_slave_instance_init(const char * progsym)
-{
- // ������̵�Privָ�벻Ϊ�գ�˵����ǰ���й����ָ�������
- if (mr_app_priv_get() != NULL)
- {
- instance = mr_app_priv_get();
- return 0;
- }
-
- // ����û���й������������Ŀռ�
- struct mrlib_instance * _instance;
- _instance = rte_zmalloc(NULL, sizeof(struct mrlib_instance), 0);
- MR_CHECK(_instance != NULL, "Cannot alloc memory for mrlib instance");
-
- snprintf(_instance->appsym, sizeof(instance->appsym), "%s", progsym);
- TAILQ_INIT(&_instance->raw_socket_list);
- instance = _instance;
- mr_app_priv_set(instance);
- return 0;
-}
-
-int marsio_init(const char * appsym, uint64_t coremask,
- unsigned autoexit, FILE * logstream)
-{
- int ret = 0;
- mrlib_stage_eal_init();
- mrlib_slave_log_ready(logstream);
-
- ret = mrlib_slave_appinfo_register(appsym, coremask, autoexit);
- if (ret < 0) return ret;
- ret = mrlib_slave_instance_init(appsym);
- if (ret < 0) return ret;
-
- __mrlib_inited = 1;
- return 0;
-}
-
-int marsio_thread_init()
-{
- mr_thread_register();
- return 0;
-}
-
-int marsio_destory()
-{
- return 0;
-} \ No newline at end of file
diff --git a/slave/src/rawio.c b/slave/src/rawio.c
deleted file mode 100644
index 395ddf9..0000000
--- a/slave/src/rawio.c
+++ /dev/null
@@ -1,216 +0,0 @@
-#include <rte_mbuf.h>
-#include <mr_rawio.h>
-#include <mr_vnode.h>
-#include <mr_vman.h>
-#include <mr_stat.h>
-#include <mr_rtdev.h>
-#include <rte_malloc.h>
-#include <mrlib_common.h>
-#include <mr_rtdev.h>
-#include <mr_runtime.h>
-
-extern struct mrlib_instance * instance;
-
-struct __raw_socket
-{
- // ������
- TAILQ_ENTRY(__raw_socket) next;
- // �豸������
- char devsym[MR_SYMBOL_MAX];
- // Raw�ӿڶ������߳���
- unsigned int nr_rxstream;
- // Raw�ӿ�д�����߳���
- unsigned int nr_txstream;
- // ����ʱ�豸�����������ձ��IJࣩ
- struct mr_rtdev_stream * rx_rt_streams[MR_SID_MAX];
- // ����ʱ�豸���������������IJࣩ
- struct mr_rtdev_stream * tx_rt_streams[MR_SID_MAX];
-};
-
-// �򿪵�Socket��¼����ɾ����������Ѿ��򿪵�Socket��¼�����������û��ظ�����ɴ���
-static struct __raw_socket * raw_socket_list_query(struct mrlib_instance * instance,
- const char * devsym)
-{
- struct __raw_socket * raw_socket_iter;
- TAILQ_FOREACH(raw_socket_iter, &instance->raw_socket_list, next)
- {
- if (strncmp(raw_socket_iter->devsym, devsym, sizeof(raw_socket_iter->devsym)) == 0)
- return raw_socket_iter;
- }
- return NULL;
-}
-
-static void raw_socket_list_join(struct mrlib_instance * instance, struct __raw_socket * socket)
-{
- TAILQ_INSERT_TAIL(&instance->raw_socket_list, socket, next);
- return;
-}
-
-static void raw_socket_list_remove(struct mrlib_instance * instance, struct __raw_socket * socket)
-{
- TAILQ_REMOVE(&instance->raw_socket_list, socket, next);
- return;
-}
-
-int marsio_raw_close(raw_socket_t * socket)
-{
- struct __raw_socket * _socket = (struct __raw_socket *)socket;
- raw_socket_list_remove(instance, (struct __raw_socket *)socket);
-
- for (int i = 0; i < RTE_DIM(_socket->rx_rt_streams); i++)
- {
- if (_socket->rx_rt_streams[i] != NULL)
- rt_dev_stream_close(_socket->rx_rt_streams[i]);
- }
-
- for(int i =0; i < RTE_DIM(_socket->tx_rt_streams); i++)
- {
- if (_socket->tx_rt_streams[i] != NULL)
- rt_dev_stream_close(_socket->tx_rt_streams[i]);
- }
-
- rt_device_close(_socket->devsym, instance->appsym);
- return 0;
-}
-
-raw_socket_t * marsio_raw_socket(const char * devsym, unsigned int nr_rx_stream,
- unsigned int nr_tx_stream, unsigned int flags __rte_unused)
-{
- struct __raw_socket * socket_before;
- struct __raw_socket * socket;
-
- // �����ǰ�Ƿ��Ѿ���Socket
- socket_before = raw_socket_list_query(instance, devsym);
-
- // ���Socket�Ѿ���
- if (socket_before != NULL)
- {
- // �����ǰ�򿪵IJ��������ڵ��Ƿ�һ��
- if (socket_before->nr_rxstream != nr_rx_stream)
- goto release_before_socket;
- if (socket_before->nr_txstream != nr_tx_stream)
- goto release_before_socket;
-
- // ���ͨ���������Ѿ��򿪵�Socket���
- return (raw_socket_t *)socket_before;
- }
- else
- {
- goto new_socket;
- }
-
- // �ͷ��Ѿ��򿪵�Socket
-release_before_socket:
- marsio_raw_close((raw_socket_t *)socket_before);
-
-new_socket:
- socket = rte_zmalloc(NULL, sizeof(struct __raw_socket), 0);
- if(unlikely(socket == NULL))
- {
- MR_LOG(ERR, MRLIB, "MarsioRawSocket, Cannot alloc memory for socket"
- "(devsym=%s, nr_rx_stream=%d, nr_tx_stream=%d, flags=%x)\n",
- devsym, nr_rx_stream, nr_tx_stream, flags);
- goto errout;
- }
-
- snprintf(socket->devsym, sizeof(socket->devsym), "%s", devsym);
- socket->nr_rxstream = nr_rx_stream;
- socket->nr_txstream = nr_tx_stream;
-
- // ������ʱ�豸
- int ret = rt_device_open(devsym, instance->appsym, nr_rx_stream, nr_tx_stream);
- if(unlikely(ret < 0))
- {
- MR_LOG(ERR, MRLIB, "MarsioRawSocket, Open rt-device %s"
- "(nr_rx_stream=%d, nr_tx_stream=%d, flags=%x) failed. \n",
- devsym, nr_rx_stream, nr_tx_stream, flags);
- goto errout;
- }
-
- raw_socket_list_join(instance, socket);
- return (raw_socket_t *)socket;
-
-errout:
- if (socket != NULL) rte_free(socket);
- return NULL;
-}
-
-int marsio_raw_recv(raw_socket_t * socket, struct rte_mbuf * mbufs[], int nr_max_mbufs)
-{
- unsigned int sid = mr_thread_id();
- struct __raw_socket * _socket = (struct __raw_socket *)socket;
- mr_thread_hook();
-
- // �жϵ�ǰ�̶߳�Ӧ���ձ����豸���Ƿ�򿪣����û����Ҫ��
- if(unlikely(_socket->rx_rt_streams[sid] == NULL))
- {
- // ������ʱ�豸���ձ�����
- struct mr_rtdev_stream * stream = rt_dev_open_stream(_socket->devsym,
- instance->appsym, RTDEV_FLAGS_OPEN_STREAM_RX);
-
- // ��ʧ��
- if(unlikely(stream == NULL))
- {
- MR_LOG(ERR, MRLIB, "MarsioRawRecv, Cannot open rt-device %s rxstream. \n",
- _socket->devsym);
- return -1;
- }
-
- _socket->rx_rt_streams[sid] = stream;
- }
-
- struct vnodeman_attach_desc * attach_desc;
- attach_desc = _socket->rx_rt_streams[sid]->rxd;
-
- // ��Vnode����ȡ����
- int ret = vnode_dequeue_burst(attach_desc->cons, &vnodeman_ops,
- attach_desc->queue_id, (void **)mbufs, nr_max_mbufs);
-
- UPDATE_APP_STAT(rx_frame, ret);
- UPDATE_APP_STAT(rx_byte, pktslen(mbufs, ret));
- return ret;
-}
-
-static inline hash_t __raw_send_pkt_hash(struct rte_mbuf * mbuf)
-{
- return mbuf->hash.rss;
-}
-
-int marsio_raw_send(raw_socket_t * socket, struct rte_mbuf * mbufs[], int nr_mbufs)
-{
- unsigned int sid = mr_thread_id();
- struct __raw_socket * _socket = (struct __raw_socket *)socket;
- mr_thread_hook();
-
- // �жϵ�ǰ�̶߳�Ӧ���ձ����豸���Ƿ�򿪣����û����Ҫ��
- if (unlikely(_socket->tx_rt_streams[sid] == NULL))
- {
- struct mr_rtdev_stream * stream = rt_dev_open_stream(_socket->devsym,
- instance->appsym, RTDEV_FLAGS_OPEN_STREAM_TX);
-
- if (unlikely(stream == NULL))
- {
- MR_LOG(ERR, MRLIB, "MarsioRawSend, Cannot open rt-device %s rxstream. \n",
- _socket->devsym);
- return -1;
- }
-
- _socket->tx_rt_streams[sid] = stream;
- }
-
- // ���㷢�͹�ϣֵ
- hash_t mbufs_hash[MR_BURST_MAX];
- for (int i = 0; i < nr_mbufs; i++)
- mbufs_hash[i] = __raw_send_pkt_hash(mbufs[i]);
-
- struct vnodeman_attach_desc * attach_desc;
- attach_desc = _socket->tx_rt_streams[sid]->txd;
-
- //TODO: ������
- int ret = vnode_enqueue_burst_with_hash(attach_desc->prod, &vnodeman_ops,
- attach_desc->queue_id, (void **)mbufs, mbufs_hash, nr_mbufs);
-
- UPDATE_APP_STAT(tx_frame, nr_mbufs);
- UPDATE_APP_STAT(tx_byte, pktslen(mbufs, ret));
- return ret;
-} \ No newline at end of file
diff --git a/stack/CMakeLists.txt b/stack/CMakeLists.txt
index 575ab3a..29c38b4 100644
--- a/stack/CMakeLists.txt
+++ b/stack/CMakeLists.txt
@@ -1,12 +1,10 @@
find_package(DPDK REQUIRED)
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_SOURCE_DIR}/include/extern)
-include_directories(${CMAKE_SOURCE_DIR}/include/internal)
include_directories(${DPDK_INCLUDE_DIR})
-
add_definitions(${DPDK_C_PREDEFINED})
+
include_directories(include)
-add_library(stack src/stack.c src/device.c src/neigh.c)
-target_link_libraries(stack MESA_prof_load_static mruntime core)
+add_library(stack src/stack.c src/device.c src/neigh.c src/rxtx.c src/route.c src/ip.c
+ src/pcom.c src/arp.c src/icmp.c src/tcp.c src/udp.c src/interface.c src/ucb.c)
+target_link_libraries(stack mruntime core)
target_link_libraries(stack rt pthread dl)
target_include_directories(stack INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include/") \ No newline at end of file
diff --git a/stack/include/sk_arp.h b/stack/include/sk_arp.h
new file mode 100644
index 0000000..6a1daf3
--- /dev/null
+++ b/stack/include/sk_arp.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <rte_mbuf.h>
+#include <sk_device.h>
+
+int protocol_serv_arp_entry(struct sk_dev_desc* dev_desc,
+ thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in);
+
+int protocol_serv_arp_request_send(struct sk_dev_desc* dev_desc, thread_id_t sid,
+ struct in_addr in_addr); \ No newline at end of file
diff --git a/stack/include/sk_common.h b/stack/include/sk_common.h
new file mode 100644
index 0000000..91cbe73
--- /dev/null
+++ b/stack/include/sk_common.h
@@ -0,0 +1,18 @@
+#pragma once
+
+enum _drop_location
+{
+ SK_FREE_ARP_UNDEFINED_TYPE,
+ SK_FREE_ARP_REPLY_DONE,
+ SK_FREE_ARP_REPLY_NOT_LOCAL,
+ SK_FREE_ARP_REQUEST_DONE,
+ SK_FREE_ARP_REQUEST_REPLY_FAILED,
+ SK_FREE_ICMP_UNDEFINED_TYPE,
+ SK_FREE_ICMP_CANNOT_HANDLE_TYPE,
+ SK_FREE_ICMP_REPLY_NO_DESTINFO
+};
+
+static inline void sk_packet_free(struct rte_mbuf * mbuf, thread_id_t sid, unsigned drop_location)
+{
+ rte_pktmbuf_free(mbuf);
+} \ No newline at end of file
diff --git a/stack/include/sk_device.h b/stack/include/sk_device.h
index 0af22e7..b0e13b4 100644
--- a/stack/include/sk_device.h
+++ b/stack/include/sk_device.h
@@ -38,13 +38,37 @@ struct sk_dev_param
unsigned int sz_rx_loop_buffer;
// ��ѭ����������С
unsigned int sz_tx_loop_buffer;
+
+ // �����ڴ����Դ
+ struct rte_mempool * direct_pktmbuf_pool;
+ struct rte_mempool * indirect_pktmbuf_pool;
+};
+
+struct sk_dev_open_param
+{
+ // �豸����
+ char symbol[MR_SYMBOL_MAX];
+ // ����ģʽ�������̻�ӽ��̣�
+ unsigned int mode;
+ // TCPЭ�����߳���
+ unsigned int nr_tcp_rxstream;
+ // TCPЭ�鷢�߳���
+ unsigned int nr_tcp_txstream;
+ // UDPЭ�����߳���
+ unsigned int nr_udp_rxstream;
+ // UDPЭ�鷢�߳���
+ unsigned int nr_udp_txstream;
+ // ��ѭ������������
+ unsigned int nr_loop_rxstream;
+ // ��ѭ������������
+ unsigned int nr_loop_txstream;
};
// �豸������Ϣ
struct sk_dev_info
{
// Э��ջCTX
- struct mr_stack_instance * instance_;
+ struct sk_instance * instance_;
// �豸������һ��
TAILQ_ENTRY(sk_dev_info) next;
// �豸����
@@ -61,63 +85,132 @@ struct sk_dev_info
struct in_addr in_addr;
// ��������
struct in_addr in_mask;
+ // ����
+ struct in_addr in_gateway;
// ����MAC��ַ
struct ether_addr mac_addr;
};
+enum sk_dev_sid_type
+{
+ SK_DEVQ_TYPE_SERV,
+ SK_DEVQ_TYPE_RAW_RX,
+ SK_DEVQ_TYPE_RAW_TX,
+ SK_DEVQ_TYPE_TCP_RX,
+ SK_DEVQ_TYPE_TCP_TX,
+ SK_DEVQ_TYPE_UDP_RX,
+ SK_DEVQ_TYPE_UDP_TX,
+ SK_DEVQ_TYPE_MAX
+};
+
// �豸��������ӽ���ͨ�ã�
struct sk_dev_desc
{
-#define SK_DEV_MODE_SERV 0
-#define SK_DEV_MODE_APP 1
+#define SK_DEV_MODE_SERV 0
+#define SK_DEV_MODE_APP 1
// ������һ��
TAILQ_ENTRY(sk_dev_desc) next;
+ // ������Ӧ�þ��
+ struct sk_app_instance * app_instance_;
// ģʽ�������̻�ӽ��̣�
unsigned int mode;
+ // �򿪲���
+ struct sk_dev_open_param open_param;
// �豸��Ϣ���
struct sk_dev_info * dev_info;
- // ��ѭ�����Ļ��������ڷ����������д�����
- struct rte_ring * rx_loop_buffer[MR_SID_MAX];
+ // �豸�ڴ��
+ struct rte_mempool * direct_pool;
+ // �豸�ڴ��
+ struct rte_mempool * indirect_pool;
+
// ��ѭ�����Ļ����������ձ��������д�����
+ struct rte_ring * rx_loop_buffer[MR_SID_MAX];
+ // ��ѭ�����Ļ��������ڷ����������д�����
struct rte_ring * tx_loop_buffer[MR_SID_MAX];
- // TCP�� Rt-Device Stream
- struct mr_rtdev_stream * tcp_rtdev_stream[MR_SID_MAX];
- // UDP�� Rt-Device Stream
- struct mr_rtdev_stream * udp_rtdev_stream[MR_SID_MAX];
+ // tcpЭ�����豸
+ struct rtdev_desc * tcp_device;
+ // udpЭ�����豸
+ struct rtdev_desc * udp_device;
+ // tcpЭ��Ӧ�����豸
+ struct rtdev_app_desc * tcp_app_device;
+ // udpЭ��Ӧ�����豸
+ struct rtdev_app_desc * udp_app_device;
+
+ // SID��������
+ rte_spinlock_t sid_alloc_lock;
+ // SID������
+ uint8_t sid_alloc_record[SK_DEVQ_TYPE_MAX][MR_SID_MAX];
+ // SID������¼
+ uint8_t nr_sid[SK_DEVQ_TYPE_MAX];
};
TAILQ_HEAD(sk_dev_info_list, sk_dev_info);
TAILQ_HEAD(sk_dev_desc_list, sk_dev_desc);
-struct sk_dev_info * mr_stack_device_lookup(struct mr_stack_instance * instance, const char * symbol);
+struct sk_instance;
+struct sk_app_instance;
+
+struct sk_dev_info * sk_device_lookup(struct sk_instance * instance, const char * symbol);
+
+struct sk_dev_desc * sk_device_desc_lookup(struct sk_app_instance* app_instance, const char * symbol);
// �豸��Ϣ������
-int mr_stack_device_iterate(struct mr_stack_instance * instance, struct sk_dev_info ** dev_info);
+int sk_device_iterate(struct sk_instance * instance, struct sk_dev_info ** dev_info);
// ����һ��Э��ջ�豸
-int mr_stack_device_create(struct mr_stack_instance * instance, struct sk_dev_param * param);
+int sk_device_create(struct sk_instance* instance, struct sk_dev_param* param);
// ����Э��ջ�豸
-int mr_stack_device_destory(struct sk_dev_info * devinfo);
+int sk_device_destory(struct sk_dev_info * devinfo);
+
+int sk_device_attach(struct sk_dev_desc * dev_desc, enum sk_dev_sid_type type,
+ thread_id_t * out_sid);
+
+void sk_device_deattach(struct sk_dev_desc * dev_desc, enum sk_dev_sid_type type,
+ thread_id_t sid);
+
+struct sk_dev_desc * sk_device_open(struct sk_app_instance * app_instance,
+ struct sk_dev_open_param * open_param);
// ����Э��ջ��IP��ַ
-int mr_stack_device_set_inaddr(struct sk_dev_info * dev_info, struct in_addr in_addr,
+int sk_device_set_inaddr(struct sk_dev_info * dev_info, struct in_addr in_addr,
struct in_addr in_mask);
// ��ȡЭ��ջ�豸��IP��ַ
-int mr_stack_device_get_inaddr(struct sk_dev_info * devinfo,
+int sk_device_get_inaddr(struct sk_dev_info * devinfo,
struct in_addr * in_addr, struct in_addr * in_mask);
// ����Э��ջ�豸��MTU
-int mr_stack_device_set_mtu(struct sk_dev_info * devinfo, unsigned int mtu);
+int sk_device_set_mtu(struct sk_dev_info * devinfo, unsigned int mtu);
// ��ȡЭ��ջ�豸��MTU
-int mr_stack_device_get_mtu(struct sk_dev_info * devinfo);
+int sk_device_get_mtu(struct sk_dev_info * devinfo);
// �����豸
-int mr_stack_device_enable(struct sk_dev_info * devinfo);
+int sk_device_enable(struct sk_dev_info * devinfo);
// �����豸
-int mr_stack_device_disable(struct sk_dev_info * devinfo);
+int sk_device_disable(struct sk_dev_info * devinfo);
+
+// ���ķ��ͣ�ͨ����ѭ�����У�
+static inline int sk_device_loop_packet_send(struct sk_dev_desc * dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbufs[], int nr_mbufs)
+{
+ return rte_ring_enqueue_burst(dev_desc->tx_loop_buffer[sid], (void **)mbufs, nr_mbufs);
+}
+
+// ���ر��Ĺ����������㣩
+static inline int sk_device_local_frame_filter(struct sk_dev_info * dev_info, struct ether_addr * ether_addr)
+{
+ if (is_broadcast_ether_addr(ether_addr)) return 1;
+ if (is_same_ether_addr(&dev_info->mac_addr, ether_addr)) return 1;
+ return 0;
+}
+
+// ���ر��Ĺ����������㣩
+static inline int sk_device_local_inaddr_filter(struct sk_dev_info * dev_info, struct in_addr * in_addr)
+{
+ return (dev_info->in_addr.s_addr == in_addr->s_addr);
+}
#ifdef __cplusplus
}
diff --git a/stack/include/sk_icmp.h b/stack/include/sk_icmp.h
new file mode 100644
index 0000000..46e8a73
--- /dev/null
+++ b/stack/include/sk_icmp.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <mr_common.h>
+
+int protocol_serv_icmp_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
+ struct rte_mbuf* mbufs_in[], int nr_mbufs_in);
diff --git a/slave/include/mrlib_rtdev.h b/stack/include/sk_interface.h
index 50e9667..50e9667 100644
--- a/slave/include/mrlib_rtdev.h
+++ b/stack/include/sk_interface.h
diff --git a/stack/include/sk_ip.h b/stack/include/sk_ip.h
new file mode 100644
index 0000000..1d3ca29
--- /dev/null
+++ b/stack/include/sk_ip.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <rte_mbuf.h>
+#include <rte_ip.h>
+#include <sk_stack.h>
+#include <stdint.h>
+
+void sk_ip_packet_construct(struct sk_app_instance * app_instance, struct rte_mbuf * mbuf,
+ struct sk_destinfo * destinfo, uint8_t l4_proto); \ No newline at end of file
diff --git a/stack/include/sk_neigh.h b/stack/include/sk_neigh.h
index 934ac9e..90e9caf 100644
--- a/stack/include/sk_neigh.h
+++ b/stack/include/sk_neigh.h
@@ -1,82 +1,48 @@
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <rte_rwlock.h>
-#include <rte_atomic.h>
-#include <rte_timer.h>
-#include <rte_ether.h>
-
-#define SK_NEIGH_MAX_HDR 0x60
-
-struct sk_neigh_table
-{
- struct rte_timer * event_timer;
- struct rte_hash * neigh_tbl;
- rte_rwlock_t neigh_tbl_lock;
-};
-
-struct sk_dest_info
-{
- uint16_t mtu;
- uint8_t l2_len;
- uint8_t l3_len;
- uint8_t hdr[SK_NEIGH_MAX_HDR];
-};
-
-#define NUD_INCOMPLETE 0x01
-#define NUD_REACHABLE 0x02
-#define NUD_STALE 0x04
-#define NUD_DELAY 0x08
-#define NUD_PROBE 0x10
-#define NUD_FAILED 0x20
-#define NUD_NOARP 0x40
-#define NUD_PERMANENT 0x80
-#define NUD_NONE 0x00
-
-#define NUD_IN_TIMER ( NUD_INCOMPLETE | NUD_REACHABLE | NUD_DELAY | NUD_PROBE )
-#define NUD_VALID ( NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE | NUD_DELAY )
-#define NUD_CONNECTED ( NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE )
-
-struct sk_neighbour
-{
- // ���ü���
- rte_atomic16_t refcnt;
- // ������
- rte_rwlock_t rwlock;
- // ��ʱ��
- struct rte_timer timer;
- // ״̬
- unsigned int state;
- // ��Ч��־λ
- unsigned int dead;
- // ������ʱ��
- unsigned int update;
- // �����豸
- struct sk_dev_desc * dev;
- // ��ѯ����
- struct in_addr in_addr;
- // ��ѯ���
- struct ether_addr ether_addr;
- // ���������Ϣ
- struct sk_dest_info dest_info;
-};
-
-int neigh_update(struct sk_neighbour * neigh, const struct ether_addr * lladdr,
- uint8_t state, uint32_t flags);
-
-int neigh_event_send(struct sk_neighbour * neigh, struct rte_mbuf * mbuf);
-
-struct sk_neighbour * neigh_create(struct sk_neigh_table * tbl,
- struct in_addr in_addr, struct sk_dev_desc * dev);
-
-struct sk_neighbour * neigh_lookup(struct sk_neigh_table * tbl,
- const void * pkey, int hold);
-
-int neigh_tbl_init(struct sk_neigh_table * tbl, const char * symbol, unsigned int nr_entries);
-
-#ifdef __cplusplus
-}
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_atomic.h>
+#include <sk_device.h>
+
+struct neighbour;
+TAILQ_HEAD(neighbour_list, neighbour);
+
+struct neighbour_manager
+{
+ /* ��� */
+ rte_rwlock_t rwlock;
+ /* ��ѯ��ϣ�� */
+ struct rte_hash * table;
+ /* ����ѯ������� */
+ struct neighbour_list in_none_list;
+ /* ����ѯ������г��ȣ�����rwlock�ı����� */
+ rte_atomic16_t in_none_list_len;
+ /* ���������� */
+ unsigned int max_entries;
+ /* ������ѯ������ */
+ unsigned int max_queue_entries;
+ /* �����ϻ�ʱ�� */
+ unsigned short t_timeout;
+ /* ARP����Ƶ�� */
+ unsigned short t_arp_send;
+};
+
+int neighbour_mamanger_init(struct neighbour_manager * object,
+ const char * symbol, unsigned int max_entries, unsigned short t_timeout, unsigned int t_arp_send);
+
+int neighbour_mamanger_deinit(struct neighbour_manager * object);
+
+int neigh_create_or_update(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * eth_addr, struct sk_dev_info * devinfo, unsigned short en_permanent);
+
+int neigh_delete(struct neighbour_manager * object, struct in_addr in_addr);
+
+int neigh_query(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * out_ether_addr, struct sk_dev_info ** out_dev_info);
+
+#ifdef __cplusplus
+}
#endif \ No newline at end of file
diff --git a/stack/include/sk_pcom.h b/stack/include/sk_pcom.h
new file mode 100644
index 0000000..9a0c59e
--- /dev/null
+++ b/stack/include/sk_pcom.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <mr_rtdev.h>
+#include <sk_device.h>
+
+int protocol_common_dev_desc_init(struct sk_instance * instance,
+ struct sk_dev_desc * dev_desc, const char * protosym, struct rtdev_desc ** rtdev_desc);
+
+int protocol_common_dev_desc_slave_init(struct sk_app_instance * slave_instance,
+ struct sk_dev_desc * dev_desc, const char * protosym, struct rtdev_app_desc ** rtdev_app_desc,
+ unsigned int nr_rxstream, unsigned int nr_txstream);
+
+#define PROTOCOL_ENTRY_RET_IS_MINE 0
+#define PROTOCOL_ENTRY_RET_NOT_MINE 1 \ No newline at end of file
diff --git a/stack/include/sk_protocol_arp.h b/stack/include/sk_protocol_arp.h
deleted file mode 100644
index fd20284..0000000
--- a/stack/include/sk_protocol_arp.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-int protocol_arp_init(struct mr_stack_instance * instance);
-
-int protocol_arp_deinit(struct mr_stack_instance * instance);
-
-int protocol_arp_slave_init(struct mr_stack_instance * instance,
- struct mr_stack_slave_instance * slave_instance);
-
-int protocol_arp_slave_deinit(struct mr_stack_instance * instance,
- struct mr_stack_slave_instance * slave_instance);
-
-int protocol_arp_dev_init(struct sk_dev_desc * dev);
-
-int protocol_arp_dev_deinit(struct sk_dev_desc * dev);
-
-int protocol_arp_slave_dev_init(struct sk_dev_desc * dev);
-
-int protocol_arp_slave_dev_deinit(struct sk_dev_desc * dev);
-
-void protocol_serv_arp_entry(struct sk_dev_desc* dev_desc,
- thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in); \ No newline at end of file
diff --git a/stack/include/sk_protocol_icmp.h b/stack/include/sk_protocol_icmp.h
deleted file mode 100644
index 11790ca..0000000
--- a/stack/include/sk_protocol_icmp.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#pragma once
-
-#include <mr_common.h>
-
-void protocol_serv_icmp_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
- struct rte_mbuf* mbufs_in[], int nr_mbufs_in);
diff --git a/stack/include/sk_protocol_tcp.h b/stack/include/sk_protocol_tcp.h
deleted file mode 100644
index fb24bb2..0000000
--- a/stack/include/sk_protocol_tcp.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-void protocol_serv_tcp_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
- struct rte_mbuf* mbufs_in[], int nr_mbufs_in); \ No newline at end of file
diff --git a/stack/include/sk_protocol_udp.h b/stack/include/sk_protocol_udp.h
deleted file mode 100644
index c416278..0000000
--- a/stack/include/sk_protocol_udp.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-void protocol_serv_udp_entry(struct sk_dev_desc* dev_desc,
- thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in); \ No newline at end of file
diff --git a/stack/include/sk_route.h b/stack/include/sk_route.h
new file mode 100644
index 0000000..560da38
--- /dev/null
+++ b/stack/include/sk_route.h
@@ -0,0 +1,46 @@
+#pragma once
+
+
+#include <netinet/in.h>
+#include <sk_device.h>
+#include <rte_ether.h>
+
+struct sk_route_tbl;
+
+struct sk_route_tbl * route_tbl_create(const char * symbol, unsigned max_rules);
+
+void route_tbl_set_default_hop(struct sk_route_tbl * tbl_object, struct sk_dev_info * dev_info);
+
+struct sk_dev_info * route_tbl_get_default_hop(struct sk_route_tbl * tbl_object);
+
+int route_tbl_insert(struct sk_route_tbl * tbl_object, struct in_addr in_addr,
+ struct in_addr in_mask, struct sk_dev_info * dev_info);
+
+struct sk_dev_info * route_tbl_lookup(struct sk_route_tbl * tbl_object, struct in_addr in_addr,
+ char * result_is_gateway);
+
+/* Ŀ����Ϣ���� */
+struct sk_destinfo
+{
+ /* Դ�˿ں� */
+ in_port_t s_trans_port;
+ /* Ŀ�Ķ˿ں� */
+ in_port_t d_trans_port;
+ /* ԴIP��ַ */
+ struct in_addr s_in_addr;
+ /* Ŀ��IP��ַ */
+ struct in_addr d_in_addr;
+ /* ԴMAC��ַ */
+ struct ether_addr s_eth_addr;
+ /* Ŀ��MAC��ַ */
+ struct ether_addr d_eth_addr;
+ /* Ŀ���豸��Ϣ������ */
+ struct sk_dev_info * d_dev_info;
+ /* Ŀ���豸����ʱ������ */
+ struct sk_dev_desc * d_dev_desc;
+};
+
+void sk_destinfo_destory(struct sk_destinfo * destinfo);
+
+struct sk_destinfo * sk_destinfo_create_by_route(struct sk_app_instance * app_instance,
+ struct in_addr d_in_addr); \ No newline at end of file
diff --git a/stack/include/sk_stack.h b/stack/include/sk_stack.h
index 8297502..e60ec19 100644
--- a/stack/include/sk_stack.h
+++ b/stack/include/sk_stack.h
@@ -1,5 +1,8 @@
#pragma once
#include <sk_device.h>
+#include <sk_neigh.h>
+#include <sk_route.h>
+#include <port_bitmap.h>
#ifndef MR_STACK_DEFAULT_SZ_DELIVER_RING
#define MR_STACK_DEFAULT_SZ_DELIVER_RING 1024
@@ -13,7 +16,24 @@
#define MR_STACK_DEFAULT_SZ_LOOP_RING 1024
#endif
-struct mr_stack_param
+#ifndef MR_STACK_DEFAULT_NEIGH_NR_MAX_NEIGH
+#define MR_STACK_DEFAULT_NEIGH_NR_MAX_NEIGH 2048
+#endif
+
+#ifndef MR_STACK_DEFAULT_NEIGH_T_ARP_SEND
+#define MR_STACK_DEFAULT_NEIGH_T_ARP_SEND 1
+#endif
+
+#ifndef MR_STACK_DEFAULT_NEIGH_T_TIMEOUT
+#define MR_STACK_DEFAULT_NEIGH_T_TIMEOUT 3600
+#endif
+
+#define LPORT_START 0x8000
+#define LPORT_END MAX_PORT_NUM
+#define LPORT_START_BLK PORT_BLK(LPORT_START)
+#define LPORT_END_BLCK PORT_BLK(LPORT_END)
+
+struct sk_param
{
// ��������
char servsym[MR_SYMBOL_MAX];
@@ -25,24 +45,81 @@ struct mr_stack_param
unsigned int sz_deliver_buffer;
// ��ѭ�����д�С
unsigned int sz_loop_ring;
+ // �ھ���ϵͳ����ʱʱ��
+ unsigned int t_neigh_timeout;
+ // �ھ���ϵͳ��ARP���ͼ��
+ unsigned int t_neigh_arp_send;
+ // �ھ���ϵͳ������ھ�����
+ unsigned int nr_neigh_max_neigh;
+
+ // �ڴ�أ�ȱʡ�����ڴ��
+ struct rte_mempool * def_direct_pktmbuf_pool;
+ // �ڴ�أ�ȱʡ���������ڴ��
+ struct rte_mempool * def_indirect_pktmbuf_pool;
};
-struct mr_stack_instance
+struct sk_instance
{
// Э��ջ���в���
- struct mr_stack_param param;
+ struct sk_param param;
+ // Coreָ��
+ struct mr_core_instance * core_instance;
// Э��ջ�豸��Ϣ
struct sk_dev_info_list dev_info_list;
- // Э��ջ�豸���
- struct sk_dev_desc_list dev_desc_list;
+ // �ھ���ϵͳ���
+ struct neighbour_manager * neigh_manager;
+ // Ĭ��·�ɱ�
+ struct sk_route_tbl * default_route;
+ // IP�����
+ rte_atomic16_t ip_counter;
+
+ // Packet Info ������ID
+ uint8_t ctrlzone_id_pktinfo;
+ // SOQ Info ������ID��MR3���ݣ�
+ uint8_t ctrlzone_id_soqinfo;
+};
+
+#define SK_CTRLZONE_PKTINFO_SYMBOL "sk_pktinfo"
+#define SK_CTRLZONE_SOQINFO_SYMBOL "sk_soqinfo"
+#define SK_CTRLZONE_PKTINFO_SIZE 32
+#define SK_CTRLZONE_SOQINFO_SIZE 32
+
+struct sk_ucb;
+
+struct sk_stack_udp_ctx
+{
+ struct sk_app_instance * app_instance_;
+ rte_rwlock_t rwlock;
+ struct portmap pbm_local;
+ struct sk_ucb * ucbs_local[MAX_PORT_NUM];
};
-struct mr_stack_slave_instance
+struct sk_app_instance
{
+ // Ӧ������
+ char appsym[MR_SYMBOL_MAX];
+ // instanceָ��
+ struct sk_instance * instance;
// Э��ջ�豸���
struct sk_dev_desc_list dev_desc_list;
+ // UDP����ʱ�����Ļ���
+ struct sk_stack_udp_ctx udp_ctx;
+
+ // �ڴ�أ�ȱʡ�����ڴ��
+ struct rte_mempool * def_direct_pktmbuf_pool;
+ // �ڴ�أ�ȱʡ���������ڴ��
+ struct rte_mempool * def_indirect_pktmbuf_pool;
};
-struct mr_stack_instance * mr_stack_instance_create(struct mr_stack_param * param);
+struct sk_instance * sk_instance_create(struct mr_core_instance * core_instance, struct sk_param * param);
+
+struct sk_app_instance * sk_app_instance_create(struct sk_instance * instance, const char* appsym);
+
+int sk_serv_device_rx_bulk(struct sk_dev_desc * dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbufs_in[], int nr_mbufs_in);
+
+int sk_serv_device_tx_bulk(struct sk_dev_desc * dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbufs_out[], int nr_mbufs_max);
-struct mr_stack_slave_instance * mr_stack_slave_create(); \ No newline at end of file
+void sk_default_instance_set(struct sk_instance * instance,
+ struct sk_app_instance * app_instance); \ No newline at end of file
diff --git a/stack/include/sk_tcp.h b/stack/include/sk_tcp.h
new file mode 100644
index 0000000..9db4f2b
--- /dev/null
+++ b/stack/include/sk_tcp.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <rte_mbuf.h>
+#include <sk_device.h>
+
+void protocol_serv_tcp_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
+ struct rte_mbuf* mbufs_in[], int nr_mbufs_in); \ No newline at end of file
diff --git a/stack/include/sk_ucb.h b/stack/include/sk_ucb.h
new file mode 100644
index 0000000..7eef1e1
--- /dev/null
+++ b/stack/include/sk_ucb.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <sk_stack.h>
+
+struct sk_ucb;
+
+int sk_ucb_bind(struct sk_ucb * ucb, struct sockaddr_in * addr);
+
+int sk_ucb_connect(struct sk_ucb * ucb, struct sockaddr_in * addr);
+
+int sk_ucb_get_index(struct sk_ucb * ucb);
+
+struct sk_ucb * sk_ucb_lookup_by_index(struct sk_app_instance * app_instance,
+ int index);
+
+struct sk_ucb * sk_ucb_create(struct sk_app_instance * app_instance);
+
+struct sk_destinfo * sk_ucb_destinfo_get(struct sk_ucb * ucb); \ No newline at end of file
diff --git a/stack/include/sk_udp.h b/stack/include/sk_udp.h
new file mode 100644
index 0000000..61690f3
--- /dev/null
+++ b/stack/include/sk_udp.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <rte_mbuf.h>
+#include <sk_device.h>
+
+int protocol_serv_udp_entry(struct sk_dev_desc* dev_desc,
+ thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in);
+
+int protocol_serv_udp_drain(struct sk_dev_desc * dev_desc,
+ thread_id_t sid, struct rte_mbuf * mbuf_out[], int nr_mbufs_max);
+
+int sk_udp_send_burst(struct sk_app_instance * app_instance, thread_id_t sid,
+ struct sk_destinfo * destinfo, struct rte_mbuf * mbuf[], unsigned int nr_mbuf,
+ unsigned char is_fast); \ No newline at end of file
diff --git a/stack/src/arp.c b/stack/src/arp.c
new file mode 100644
index 0000000..74e9379
--- /dev/null
+++ b/stack/src/arp.c
@@ -0,0 +1,171 @@
+/* \brief 简单协议栈ARP/RARP协议处理模块
+*
+* 处理ARP/RARP协议报文数据
+*
+* \author Lu Qiuwen<[email protected]>
+* \date 2016-10-21
+*/
+
+#include <mr_rtdev.h>
+#include <sk_stack.h>
+#include <sk_device.h>
+#include <rte_malloc.h>
+#include <rte_arp.h>
+#include <sk_common.h>
+#include <sk_neigh.h>
+
+static struct ether_addr broadcast_hwaddr = { { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF } };
+
+static void arp_reply_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbuf, struct arp_hdr * arp_header)
+{
+ struct in_addr * s_in_addr = (struct in_addr *)&arp_header->arp_data.arp_sip;
+ struct in_addr * d_in_addr = (struct in_addr *)&arp_header->arp_data.arp_tip;
+ struct ether_addr * s_eth_addr = (struct ether_addr *)&arp_header->arp_data.arp_sha;
+ struct ether_addr * d_eth_addr = (struct ether_addr *)&arp_header->arp_data.arp_tha;
+
+ // 检测目的IP地址、MAC地址是否是本机的
+ if (!sk_device_local_frame_filter(dev_desc->dev_info, d_eth_addr))
+ goto invalid_frame;
+ if (!sk_device_local_inaddr_filter(dev_desc->dev_info, d_in_addr))
+ goto invalid_frame;
+
+ // TODO: 错误处理
+ struct neighbour_manager * neigh_manager = dev_desc->dev_info->instance_->neigh_manager;
+ neigh_create_or_update(neigh_manager, *s_in_addr, s_eth_addr, dev_desc->dev_info, 0);
+
+ sk_packet_free(mbuf, sid, SK_FREE_ARP_REPLY_DONE);
+ return;
+
+invalid_frame:
+ sk_packet_free(mbuf, sid, SK_FREE_ARP_REPLY_NOT_LOCAL);
+ return;
+}
+
+static void arp_request_entry(struct sk_dev_desc * dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbuf, struct arp_hdr * arp_header)
+{
+ struct in_addr * s_in_addr = (struct in_addr *)&arp_header->arp_data.arp_sip;
+ struct in_addr * d_in_addr = (struct in_addr *)&arp_header->arp_data.arp_tip;
+ struct ether_addr * s_eth_addr = (struct ether_addr *)&arp_header->arp_data.arp_sha;
+ struct ether_addr * d_eth_addr = (struct ether_addr *)&arp_header->arp_data.arp_tha;
+
+ // 过滤非广播报文,请求报文应全部填零
+ if (!is_zero_ether_addr(d_eth_addr))
+ goto done;
+
+ // 根据广播的ARP报文,更新邻居表
+ struct neighbour_manager * neigh_manager = dev_desc->dev_info->instance_->neigh_manager;
+ neigh_create_or_update(neigh_manager, *s_in_addr, s_eth_addr, dev_desc->dev_info, 0);
+
+ // 对请求是本机的,进行响应
+ if (!sk_device_local_inaddr_filter(dev_desc->dev_info, d_in_addr))
+ goto done;
+
+ struct rte_mbuf * reply_mbuf = rte_pktmbuf_alloc(dev_desc->direct_pool);
+ if (unlikely(reply_mbuf == NULL)) goto reply_err;
+
+ // 构造以太网头
+ struct ether_hdr * ether_hdr = (struct ether_hdr *)rte_pktmbuf_append(
+ reply_mbuf, sizeof(struct ether_hdr));
+
+ ether_addr_copy(&dev_desc->dev_info->mac_addr, &ether_hdr->s_addr);
+ ether_addr_copy(&arp_header->arp_data.arp_sha, &ether_hdr->d_addr);
+ ether_hdr->ether_type = ntohs(ETHER_TYPE_ARP);
+
+ // 构造ARP应答
+ struct arp_hdr * reply_arp_hdr = (struct arp_hdr *)rte_pktmbuf_append(
+ reply_mbuf, sizeof(struct arp_hdr));
+
+ rte_memcpy(reply_arp_hdr, arp_header, sizeof(struct arp_hdr));
+ reply_arp_hdr->arp_op = ntohs(ARP_OP_REPLY);
+ ether_addr_copy(&ether_hdr->s_addr, &reply_arp_hdr->arp_data.arp_sha);
+ ether_addr_copy(&ether_hdr->d_addr, &reply_arp_hdr->arp_data.arp_tha);
+ reply_arp_hdr->arp_data.arp_sip = dev_desc->dev_info->in_addr.s_addr;
+ reply_arp_hdr->arp_data.arp_tip = s_in_addr->s_addr;
+
+ // 写应答包到线路
+ int ret = sk_device_loop_packet_send(dev_desc, sid, &reply_mbuf, 1);
+ if (ret != 1) sk_packet_free(reply_mbuf, sid, SK_FREE_ARP_REQUEST_REPLY_FAILED);
+
+ goto done;
+
+reply_err:
+ sk_packet_free(mbuf, sid, SK_FREE_ARP_REQUEST_REPLY_FAILED);
+ return;
+
+done:
+ sk_packet_free(mbuf, sid, SK_FREE_ARP_REQUEST_DONE);
+ return;
+}
+
+int protocol_serv_arp_entry(struct sk_dev_desc* dev_desc,
+ thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
+{
+ int handled_packets = 0;
+
+ for (int i = 0; i < nr_mbufs_in; i++)
+ {
+ struct rte_mbuf * mbuf = mbufs_in[i];
+ if (unlikely(mbuf == NULL)) continue;
+
+ struct ether_hdr * eth_hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
+ if (eth_hdr->ether_type != ntohs(ETHER_TYPE_ARP)) continue;
+
+ struct arp_hdr * arp_hdr = rte_pktmbuf_mtod_offset(
+ mbuf, struct arp_hdr *, sizeof(struct ether_hdr));
+
+ if (arp_hdr->arp_op == ntohs(ARP_OP_REQUEST))
+ arp_request_entry(dev_desc, sid, mbuf, arp_hdr);
+ else if (arp_hdr->arp_op == ntohs(ARP_OP_REPLY))
+ arp_reply_entry(dev_desc, sid, mbuf, arp_hdr);
+ else
+ sk_packet_free(mbuf, sid, SK_FREE_ARP_UNDEFINED_TYPE);
+
+ handled_packets++;
+ mbufs_in[i] = NULL;
+ }
+
+ return handled_packets;
+}
+
+int protocol_serv_arp_request_send(struct sk_dev_desc* dev_desc, thread_id_t sid,
+ struct in_addr in_addr)
+{
+ struct sk_dev_info * dev_info = dev_desc->dev_info;
+ if (dev_info->enable == 0) return -EINVAL;
+
+ struct ether_addr * src_hwaddr = &dev_info->mac_addr;
+ struct ether_addr * dst_hwaddr = &broadcast_hwaddr;
+
+ struct in_addr in_addr_src = dev_info->in_addr;
+ struct rte_mbuf * req_mbuf = rte_pktmbuf_alloc(dev_desc->direct_pool);
+ if (unlikely(req_mbuf == NULL)) return -ENOBUFS;
+
+ // 构造以太网头
+ struct ether_hdr * ether_hdr = (struct ether_hdr *)rte_pktmbuf_append(
+ req_mbuf, sizeof(struct ether_hdr));
+
+ ether_addr_copy(src_hwaddr, &ether_hdr->s_addr);
+ ether_addr_copy(dst_hwaddr, &ether_hdr->d_addr);
+ ether_hdr->ether_type = htons(ETHER_TYPE_ARP);
+
+ // 构造ARP请求报文
+ struct arp_hdr * arp_hdr = (struct arp_hdr *)rte_pktmbuf_append(
+ req_mbuf, sizeof(struct arp_hdr));
+
+ arp_hdr->arp_hrd = htons(ARP_HRD_ETHER);
+ arp_hdr->arp_pro = htons(ETHER_TYPE_IPv4);
+ arp_hdr->arp_hln = 6;
+ arp_hdr->arp_pln = 4;
+ arp_hdr->arp_op = htons(ARP_OP_REQUEST);
+ arp_hdr->arp_data.arp_sip = in_addr_src.s_addr;
+ arp_hdr->arp_data.arp_tip = in_addr.s_addr;
+ ether_addr_copy(src_hwaddr, &arp_hdr->arp_data.arp_sha);
+ memset(&arp_hdr->arp_data.arp_tha, 0, sizeof(arp_hdr->arp_data.arp_tha));
+
+ // 写数据包到线路
+ int ret = sk_device_loop_packet_send(dev_desc, sid, &req_mbuf, 1);
+ if (unlikely(ret != 1)) rte_pktmbuf_free(req_mbuf);
+ return 0;
+} \ No newline at end of file
diff --git a/stack/src/common.c b/stack/src/common.c
new file mode 100644
index 0000000..00e61e2
--- /dev/null
+++ b/stack/src/common.c
@@ -0,0 +1,3 @@
+
+#include <rte_mbuf.h>
+#include <mr_common.h>
diff --git a/stack/src/dest.c b/stack/src/dest.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stack/src/dest.c
diff --git a/stack/src/device.c b/stack/src/device.c
index bff5a05..e219b0c 100644
--- a/stack/src/device.c
+++ b/stack/src/device.c
@@ -9,22 +9,41 @@
*/
#include <sys/queue.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
#include <rte_ether.h>
#include <mr_rtdev.h>
-#include <mr_rawio.h>
#include <rte_malloc.h>
#include <sk_stack.h>
#include <sk_device.h>
#include <assert.h>
+struct sk_dev_info * sk_device_lookup(struct sk_instance * instance, const char * symbol)
+{
+ struct sk_dev_info * dev_info_iter;
+ TAILQ_FOREACH(dev_info_iter, &instance->dev_info_list, next)
+ {
+ if (strcmp(dev_info_iter->symbol, symbol) == 0)
+ return dev_info_iter;
+ }
-struct sk_dev_info * mr_stack_device_lookup(struct mr_stack_instance * instance, const char * symbol)
+ return NULL;
+}
+
+struct sk_dev_desc * sk_device_desc_lookup(struct sk_app_instance* app_instance, const char * symbol)
{
+ struct sk_dev_desc * dev_desc_iter;
+ TAILQ_FOREACH(dev_desc_iter, &app_instance->dev_desc_list, next)
+ {
+ if (strcmp(dev_desc_iter->dev_info->symbol, symbol) == 0)
+ return dev_desc_iter;
+ }
+
return NULL;
}
-int mr_stack_device_iterate(struct mr_stack_instance * instance, struct sk_dev_info ** dev_info)
+int sk_device_iterate(struct sk_instance * instance, struct sk_dev_info ** dev_info)
{
// 迭代器为空,从头开始迭代,否则查找迭代器下一个对象
if(*dev_info == NULL)
@@ -42,50 +61,218 @@ int mr_stack_device_iterate(struct mr_stack_instance * instance, struct sk_dev_i
return 0;
}
+
+static void __rte_unused sk_dev_desc_delete(struct sk_dev_desc * dev_desc)
+{
+ // 释放RX侧自循环缓冲区
+ for (int i = 0; i < RTE_DIM(dev_desc->rx_loop_buffer); i++)
+ {
+ if (dev_desc->rx_loop_buffer[i] != NULL)
+ rte_ring_free(dev_desc->rx_loop_buffer[i]);
+ }
+
+ // 释放TX侧自循环缓冲区
+ for (int i = 0; i < RTE_DIM(dev_desc->tx_loop_buffer); i++)
+ {
+ if (dev_desc->tx_loop_buffer[i] != NULL)
+ rte_ring_free(dev_desc->tx_loop_buffer[i]);
+ }
+
+ rte_free(dev_desc);
+ return;
+}
+
+static int __sk_device_create_loop_buffer(const char * prefix, const char * devsym,
+ unsigned int nr_stream, unsigned int sz_tunnel, struct rte_ring * object[])
+{
+ for (int i = 0; i < nr_stream; i++)
+ {
+ char str_loop_buffer[MR_SYMBOL_MAX];
+ snprintf(str_loop_buffer, sizeof(str_loop_buffer), "%s-%s-%d", prefix, devsym, i);
+
+ object[i] = rte_ring_create(str_loop_buffer, sz_tunnel, SOCKET_ID_ANY,
+ RING_F_SC_DEQ | RING_F_SP_ENQ);
+
+ if (object[i] == NULL)
+ {
+ MR_LOG(WARNING, STACK, "Create loop buffer for sk-dev %s(sym=%s, size=%d) failed. : %s\n",
+ devsym, str_loop_buffer, sz_tunnel, __str_errno());
+ goto err_out;
+ }
+ }
+
+ return 0;
+
+err_out:
+ for (int i = 0; i < nr_stream; i++) if (object[i] != NULL) rte_ring_free(object[i]);
+ return -1;
+}
+
+
// 创建一个协议栈设备
-int mr_stack_device_create(struct mr_stack_instance * instance, struct sk_dev_param * param)
+int sk_device_create(struct sk_instance* instance, struct sk_dev_param* param)
{
// 检查设备是否已经存在,不允许重复创建
- struct sk_dev_info * devinfo = mr_stack_device_lookup(instance, param->symbol);
- if(devinfo != NULL)
+ struct sk_dev_info * dev_info = sk_device_lookup(instance, param->symbol);
+ if(dev_info != NULL)
{
MR_LOG(INFO, STACK, "StackCreateDevice, StackDevice %s has been created. failed. \n",
param->symbol);
- return -EEXIST;
+ goto err_out;
}
// 申请Info结构体的空间
- devinfo = rte_zmalloc(NULL, sizeof(struct sk_dev_info), 0);
- if(unlikely(devinfo == NULL))
+ dev_info = rte_zmalloc(NULL, sizeof(struct sk_dev_info), 0);
+ if(unlikely(dev_info == NULL))
{
MR_LOG(WARNING, STACK, "StackCreateDevice, Cannot alloc memory for device info.\n");
- return -ENOMEM;
+ goto err_out;
}
- // 写参数
- snprintf(devinfo->symbol, sizeof(devinfo->symbol), "%s", param->symbol);
- devinfo->param = *param;
- devinfo->instance_ = instance;
- devinfo->in_addr = param->in_addr;
- devinfo->in_mask = param->in_mask;
- devinfo->mac_addr = param->mac_addr;
- devinfo->mtu = param->mtu;
- devinfo->promisc = 0;
+ snprintf(dev_info->symbol, sizeof(dev_info->symbol), "%s", param->symbol);
+ dev_info->param = *param;
+ dev_info->instance_ = instance;
+ dev_info->in_addr = param->in_addr;
+ dev_info->in_mask = param->in_mask;
+ dev_info->in_gateway = param->in_gateway;
+ dev_info->mac_addr = param->mac_addr;
+ dev_info->mtu = param->mtu;
+ dev_info->promisc = 0;
+
+ int ret = route_tbl_insert(instance->default_route, dev_info->in_addr,
+ dev_info->in_mask, dev_info);
+
+ if (unlikely(ret < 0)) goto err_out;
- // 加入到协议栈设备链表中
- TAILQ_INSERT_TAIL(&instance->dev_info_list, devinfo, next);
+ // 设置默认网关,默认网关只能有一个。若以前设置过,此处不生效
+ if (dev_info->in_gateway.s_addr != 0 &&
+ route_tbl_get_default_hop(instance->default_route) != NULL)
+ {
+ MR_LOG(WARNING, STACK, "Duplicated default gateway setting, "
+ "not available(see at device %s setting)\n", dev_info->symbol);
+ }
+
+ if (dev_info->in_gateway.s_addr != 0 &&
+ route_tbl_get_default_hop(instance->default_route) == NULL)
+ {
+ route_tbl_set_default_hop(instance->default_route, dev_info);
+ }
+
+ char str_in_addr[INET_ADDRSTRLEN];
+ char str_in_mask[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &dev_info->in_addr, str_in_addr, sizeof(str_in_addr));
+ inet_ntop(AF_INET, &dev_info->in_mask, str_in_mask, sizeof(str_in_mask));
+ MR_LOG(NOTICE, STACK, "Stack device %s(in_addr=%s, in_mask=%s) created. \n",
+ dev_info->symbol, str_in_addr, str_in_mask);
+
+ TAILQ_INSERT_TAIL(&instance->dev_info_list, dev_info, next);
return 0;
+
+err_out:
+ MR_LOG(ERR, STACK, "Sk-device %s create failed. \n", dev_info->symbol);
+ if (dev_info) rte_free(dev_info);
+ return ret;
+}
+
+// 打开一个协议栈设备
+struct sk_dev_desc * sk_device_open(struct sk_app_instance * app_instance,
+ struct sk_dev_open_param * open_param)
+{
+ struct sk_instance * instance = app_instance->instance;
+ struct sk_param * instance_param = &instance->param;
+
+ struct sk_dev_info * dev_info = sk_device_lookup(instance, open_param->symbol);
+
+ if (unlikely(dev_info == NULL))
+ {
+ MR_LOG(ERR, STACK, "Stack Device %s does not existed. failed. \n",
+ open_param->symbol);
+ return NULL;
+ }
+
+ struct sk_dev_desc * dev_desc = rte_zmalloc(NULL, sizeof(struct sk_dev_desc), 0);
+ if (unlikely(dev_desc == NULL))
+ {
+ MR_LOG(WARNING, STACK, "Cannot alloc memory for sk-dev %s desc. Failed. \n",
+ dev_info->symbol);
+ goto err_out;
+ }
+
+ dev_desc->dev_info = dev_info;
+ dev_desc->direct_pool = dev_info->param.direct_pktmbuf_pool;
+ dev_desc->indirect_pool = dev_info->param.indirect_pktmbuf_pool;
+ dev_desc->app_instance_ = app_instance;
+ assert(dev_desc->direct_pool != NULL && dev_desc->indirect_pool != NULL);
+
+ int ret = 0;
+
+ if(open_param->nr_loop_rxstream)
+ {
+ ret = __sk_device_create_loop_buffer("skd-rx", dev_info->symbol,
+ open_param->nr_loop_rxstream, instance_param->sz_loop_ring, dev_desc->rx_loop_buffer);
+ if (ret < 0) goto err_out;
+ }
+
+ if(open_param->nr_loop_txstream)
+ {
+ ret = __sk_device_create_loop_buffer("skd-tx", dev_info->symbol,
+ open_param->nr_loop_txstream, instance_param->sz_loop_ring, dev_desc->tx_loop_buffer);
+ if (ret < 0) goto err_out;
+ }
+
+ TAILQ_INSERT_TAIL(&app_instance->dev_desc_list, dev_desc, next);
+ MR_LOG(ERR, STACK, "Sk-device %s opened. \n", dev_info->symbol);
+ return dev_desc;
+
+err_out:
+ MR_LOG(ERR, STACK, "Sk-device %s open failed. \n", dev_info->symbol);
+ if (dev_desc != NULL) rte_free(dev_desc);
+ return NULL;
+}
+
+int sk_device_attach(struct sk_dev_desc * dev_desc, enum sk_dev_sid_type type,
+ thread_id_t * out_sid)
+{
+ rte_spinlock_lock(&dev_desc->sid_alloc_lock);
+ int ret = -1;
+ for(int i = 0; i < dev_desc->nr_sid[type]; i++)
+ {
+ if (dev_desc->sid_alloc_record[type][i]) continue;
+ dev_desc->sid_alloc_record[type][i] = 1;
+ *out_sid = i;
+ ret = 0; break;
+ }
+ rte_spinlock_lock(&dev_desc->sid_alloc_lock);
+ return ret;
+}
+
+void sk_device_deattach(struct sk_dev_desc * dev_desc, enum sk_dev_sid_type type,
+ thread_id_t sid)
+{
+ rte_spinlock_lock(&dev_desc->sid_alloc_lock);
+ dev_desc->sid_alloc_record[type][sid] = 0;
+ rte_spinlock_lock(&dev_desc->sid_alloc_lock);
+}
+
+struct rte_mempool * sk_device_direct_pktmbuf_pool(struct sk_dev_desc * dev_desc)
+{
+ return dev_desc->direct_pool;
+}
+
+struct rte_mempool * sk_device_indirect_pktmbuf_pool(struct sk_dev_desc * dev_desc)
+{
+ return dev_desc->indirect_pool;
}
// 销毁协议栈设备
-int mr_stack_device_destory(struct sk_dev_info * devinfo)
+int sk_device_destory(struct sk_dev_info * devinfo)
{
assert(0);
return 0;
}
// 设置协议栈的IP地址
-int mr_stack_device_set_inaddr(struct sk_dev_info * dev_info, struct in_addr in_addr,
+int sk_device_set_inaddr(struct sk_dev_info * dev_info, struct in_addr in_addr,
struct in_addr in_mask)
{
dev_info->in_addr = in_addr;
@@ -94,7 +281,7 @@ int mr_stack_device_set_inaddr(struct sk_dev_info * dev_info, struct in_addr in_
}
// 读取协议栈设备的IP地址
-int mr_stack_device_get_inaddr(struct sk_dev_info * devinfo,
+int sk_device_get_inaddr(struct sk_dev_info * devinfo,
struct in_addr * in_addr, struct in_addr * in_mask)
{
*in_addr = devinfo->in_addr;
@@ -103,94 +290,26 @@ int mr_stack_device_get_inaddr(struct sk_dev_info * devinfo,
}
// 设置协议栈设备的MTU
-int mr_stack_device_set_mtu(struct sk_dev_info * devinfo, unsigned int mtu)
+int sk_device_set_mtu(struct sk_dev_info * devinfo, unsigned int mtu)
{
devinfo->mtu = mtu;
return 0;
}
// 读取协议栈设备的MTU
-int mr_stack_device_get_mtu(struct sk_dev_info * devinfo)
+int sk_device_get_mtu(struct sk_dev_info * devinfo)
{
return devinfo->mtu;
}
// 启动设备
-int mr_stack_device_enable(struct sk_dev_info * devinfo)
+int sk_device_enable(struct sk_dev_info * devinfo)
{
return 0;
}
// 禁用设备
-int mr_stack_device_disable(struct sk_dev_info * devinfo)
-{
- return 0;
-}
-
-static struct sk_dev_desc * sk_dev_desc_new(struct sk_dev_info * dev_info, unsigned int mode)
-{
- // 申请内存空间
- struct sk_dev_desc * dev_desc = rte_zmalloc(NULL, sizeof(struct sk_dev_desc), 0);
- if(unlikely(dev_desc == NULL))
- {
- MR_LOG(WARNING, STACK, "StackDevice, StackDeviceDescCreate, "
- "Cannot alloc memory for device %s desc. Failed. \n", dev_info->symbol);
- return NULL;
- }
-
- // 各线程使用的资源放在线程初始化流程中进行,这里不进行。
- dev_desc->dev_info = dev_info;
- return dev_desc;
-}
-
-static void sk_dev_desc_delete(struct sk_dev_desc * dev_desc)
-{
- // TODO:stream的释放
-
- // 释放RX侧自循环缓冲区
- for(int i = 0; i < RTE_DIM(dev_desc->rx_loop_buffer); i++)
- {
- if (dev_desc->rx_loop_buffer[i] != NULL)
- rte_ring_free(dev_desc->rx_loop_buffer[i]);
- }
-
- // 释放TX侧自循环缓冲区
- for(int i = 0; i < RTE_DIM(dev_desc->tx_loop_buffer); i++)
- {
- if (dev_desc->tx_loop_buffer[i] != NULL)
- rte_ring_free(dev_desc->tx_loop_buffer[i]);
- }
-
- rte_free(dev_desc);
- return;
-}
-
-/* 以下为内部初始化、注销处理流程。*/
-int stack_device_init(struct mr_stack_instance * instance)
-{
- // 创建主应用设备句柄,插入到句柄链表中
- struct sk_dev_info * dev_info_iter;
- struct sk_dev_desc * dev_desc_iter;
-
- TAILQ_FOREACH(dev_info_iter, &instance->dev_info_list, next)
- {
- struct sk_dev_desc * dev_desc = sk_dev_desc_new(dev_info_iter, SK_DEV_MODE_SERV);
- if (unlikely(dev_desc == NULL)) goto errout;
- TAILQ_INSERT_TAIL(&instance->dev_desc_list, dev_desc, next);
- }
-
- return 0;
-
-errout:
- TAILQ_FOREACH(dev_desc_iter, &instance->dev_desc_list, next)
- {
- sk_dev_desc_delete(dev_desc_iter);
- }
- return -1;
-}
-
-int stack_device_slave_init(struct mr_stack_instance * instance,
- struct mr_stack_slave_instance * slave_instance)
+int sk_device_disable(struct sk_dev_info * devinfo)
{
return 0;
} \ No newline at end of file
diff --git a/stack/src/feedback.c b/stack/src/feedback.c
new file mode 100644
index 0000000..ac0c0b2
--- /dev/null
+++ b/stack/src/feedback.c
@@ -0,0 +1,16 @@
+/* T1/T2 UDP���ݻش�ר�ýӿ�
+ */
+
+#include <marsio_buffer_user_api.h>
+
+int marsio_feedback_send_burst(struct sk_destinfo * destinfo, uint32_t hash,
+ marsio_buff_t * buffer[], int nr_buffer, uint64_t flags)
+{
+ return 0;
+}
+
+int marsio_feedback_send_chain(struct sk_destinfo * destinfo, uint32_t hash,
+ marsio_buff_t * chain, uint64_t flags)
+{
+ return 0;
+} \ No newline at end of file
diff --git a/stack/src/icmp.c b/stack/src/icmp.c
new file mode 100644
index 0000000..630e70c
--- /dev/null
+++ b/stack/src/icmp.c
@@ -0,0 +1,80 @@
+
+
+#include <rte_icmp.h>
+#include <mr_common.h>
+#include <sk_device.h>
+#include <sk_stack.h>
+#include <sk_common.h>
+#include <sk_route.h>
+#include <sk_ip.h>
+
+static void icmp_echo_request_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
+ struct rte_mbuf * mbuf, struct in_addr s_in_addr, struct in_addr d_in_addr)
+{
+ struct icmp_hdr * icmp_hdr = rte_pktmbuf_mtod(mbuf, struct icmp_hdr *);
+
+ uint32_t cksum;
+ icmp_hdr->icmp_type = IP_ICMP_ECHO_REPLY;
+ cksum = ~icmp_hdr->icmp_cksum & 0xffff;
+ cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
+ cksum += htons(IP_ICMP_ECHO_REPLY << 8);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ cksum = (cksum & 0xffff) + (cksum >> 16);
+ icmp_hdr->icmp_cksum = cksum;
+
+ struct sk_app_instance * app_instance = dev_desc->app_instance_;
+ struct sk_destinfo * destinfo = sk_destinfo_create_by_route(app_instance, s_in_addr);
+ if(unlikely(destinfo == NULL))
+ {
+ sk_packet_free(mbuf, sid, SK_FREE_ICMP_REPLY_NO_DESTINFO);
+ return;
+ }
+
+ sk_ip_packet_construct(app_instance, mbuf, destinfo, IPPROTO_ICMP);
+ sk_device_loop_packet_send(destinfo->d_dev_desc, sid, &mbuf, 1);
+ return;
+}
+
+int protocol_serv_icmp_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
+ struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
+{
+ int handled_packets = 0;
+ struct in_addr s_in_addr;
+ struct in_addr d_in_addr;
+
+ for (int i = 0; i < nr_mbufs_in; i++)
+ {
+ struct rte_mbuf * mbuf = mbufs_in[i];
+ if (unlikely(mbuf == NULL)) continue;
+
+ // ������IPv4����
+ if (!RTE_ETH_IS_IPV4_HDR(mbuf->packet_type)) continue;
+
+ // ��IPv4��������
+ struct ipv4_hdr * ip_hdr = rte_pktmbuf_mtod_offset(mbuf, struct ipv4_hdr *,
+ sizeof(struct ether_hdr));
+
+ if (ip_hdr->next_proto_id != IPPROTO_ICMP) continue;
+
+ s_in_addr.s_addr = ip_hdr->src_addr;
+ d_in_addr.s_addr = ip_hdr->dst_addr;
+
+ rte_pktmbuf_adj(mbuf, sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr));
+ struct icmp_hdr * icmp_hdr = rte_pktmbuf_mtod(mbuf, struct icmp_hdr *);
+
+ // ICMP��������
+ if (icmp_hdr->icmp_type == IP_ICMP_ECHO_REQUEST)
+ {
+ icmp_echo_request_entry(dev_desc, sid, mbuf, s_in_addr, d_in_addr);
+ }
+ else // �������Ͳ�����
+ {
+ sk_packet_free(mbuf, sid, SK_FREE_ICMP_CANNOT_HANDLE_TYPE);
+ }
+
+ mbufs_in[i] = NULL;
+ handled_packets++;
+ }
+
+ return handled_packets;
+} \ No newline at end of file
diff --git a/stack/src/interface.c b/stack/src/interface.c
new file mode 100644
index 0000000..d0a2334
--- /dev/null
+++ b/stack/src/interface.c
@@ -0,0 +1,210 @@
+#include <sk_stack.h>
+#include <sk_ucb.h>
+#include <mr_common.h>
+#include <unistd.h>
+#include <mr_buffer.h>
+#include "sk_udp.h"
+
+static struct sk_app_instance * sk_default_app_instance;
+static struct sk_instance * sk_default_instance;
+
+void sk_default_instance_set(struct sk_instance * instance,
+ struct sk_app_instance * app_instance)
+{
+ sk_default_instance = instance;
+ sk_default_app_instance = app_instance;
+}
+
+
+int marsio_socket(int family, int type, int protocol)
+{
+ if (unlikely(family != AF_INET && family != AF_INET6))
+ return -EINVAL;
+ if (unlikely(type != SOCK_DGRAM))
+ return -EINVAL;
+
+ assert(sk_default_app_instance != NULL);
+ struct sk_ucb * ucb = sk_ucb_create(sk_default_app_instance);
+ if (unlikely(ucb == NULL)) return -1;
+ return sk_ucb_get_index(ucb);
+}
+
+int marsio_connect(int fd, const struct sockaddr * addr, socklen_t addrlen)
+{
+ if (addr->sa_family != AF_INET) return -EINVAL;
+ struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)addr;
+
+ assert(sk_default_app_instance != NULL);
+ struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, fd);
+ if (unlikely(ucb == NULL)) return -EINVAL;
+
+ return sk_ucb_connect(ucb, sockaddr_in);
+}
+
+int marsio_bind(int fd, const struct sockaddr * addr, socklen_t addrlen)
+{
+ if (addr->sa_family != AF_INET) return -EINVAL;
+ struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)addr;
+
+ assert(sk_default_app_instance != NULL);
+ struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, fd);
+ if (unlikely(ucb == NULL)) return -EINVAL;
+ return sk_ucb_bind(ucb, sockaddr_in);
+}
+
+#define SK_UDP_MAGIC_CHECK 0
+
+#ifdef __GNUC__
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *)0)->member) *__mptr = (ptr); \
+ (type *)((char *)__mptr - offsetof(type,member));})
+#else
+#define container_of(ptr, type,member) \
+ ((type *)((char *)(ptr) - offsetof(type, member)))
+#endif
+
+/* UDP���Ļ�������ͬһ�����ϵĻ�������ʾͬһ��UDP���� */
+struct marsio_udp_buff
+{
+ /* ��������ʼ��ַ */
+ void * start;
+ /* ���������� */
+ unsigned int len;
+ /* ��һ�黺������ַ */
+ struct marsio_udp_buff * next;
+ /* ��һ������ʼ��ַ */
+ struct marsio_udp_buff * next_pkt;
+};
+
+struct internal_udp_buff
+{
+#if SK_UDP_MAGIC_CHECK
+ char magic_0[2];
+#endif
+ struct rte_mbuf * mbuf;
+#if SK_UDP_MAGIC_CHECK
+ char magic_1[2];
+#endif
+ struct marsio_udp_buff buff;
+};
+
+
+/* ���º���Ϊ����MARSIO-3�汾��ʵ�֣��¹���Ӧ��ʹ�����º��� */
+/* BUFF�ṹ����ת������ */
+static inline struct marsio_udp_buff * __buff_from_internal_buff(struct internal_udp_buff * in_buff)
+{
+ return &(in_buff->buff);
+}
+
+static inline struct internal_udp_buff * __internal_buff_from_buff(struct marsio_udp_buff * buff)
+{
+ return container_of(buff, struct internal_udp_buff, buff);
+}
+
+static inline struct rte_mbuf * __mbuf_from_buff(struct marsio_udp_buff * buff)
+{
+ return __internal_buff_from_buff(buff)->mbuf;
+}
+
+struct marsio_udp_buff * marsio_udp_alloc()
+{
+ struct rte_mbuf * mbuf = rte_pktmbuf_alloc(sk_default_app_instance->def_direct_pktmbuf_pool);
+ if (unlikely(mbuf == NULL)) return NULL;
+
+ uint8_t ctrlzone_id = sk_default_app_instance->instance->ctrlzone_id_soqinfo;
+ struct internal_udp_buff * in_buff = (struct internal_udp_buff *)mr_buffer_ctrlzone(mbuf, ctrlzone_id);
+ assert(in_buff != NULL);
+
+ in_buff->mbuf = mbuf;
+ in_buff->buff.start = rte_pktmbuf_mtod(mbuf, void *);
+ in_buff->buff.len = mbuf->buf_len - mbuf->data_off;
+ in_buff->buff.next = NULL;
+ in_buff->buff.next_pkt = NULL;
+ return __buff_from_internal_buff(in_buff);
+}
+
+void marsio_udp_free(struct marsio_udp_buff * udp_buff)
+{
+ struct rte_mbuf * mbuf = __mbuf_from_buff(udp_buff);
+ rte_pktmbuf_free(mbuf);
+ return;
+}
+
+/* ����UDP Buff�ṹ�������ӵ�MBUF�ṹ*/
+static inline struct rte_mbuf * update_rte_mbuf(struct marsio_udp_buff * buff_head)
+{
+ struct marsio_udp_buff * now_buff_head = buff_head;
+ struct rte_mbuf * mbuf_chain_head = __mbuf_from_buff(buff_head);
+
+ // ��һ������ʼ��
+ mbuf_chain_head->pkt_len = buff_head->len;
+ mbuf_chain_head->data_len = buff_head->len;
+ mbuf_chain_head->nb_segs = 1;
+
+ // ����BUFF�ṹ����MBUF����
+ while (now_buff_head != NULL)
+ {
+
+#if SK_UDP_MAGIC_CHECK
+ struct internal_udp_buff * __check_in_buff = __internal_buff_from_buff(now_buff_head);
+ __magic_check(__check_in_buff);
+#endif
+
+ struct rte_mbuf * mbuf_now = __mbuf_from_buff(now_buff_head);
+ if (mbuf_now != mbuf_chain_head) rte_pktmbuf_chain(mbuf_chain_head, mbuf_now);
+ now_buff_head = now_buff_head->next;
+ }
+
+ return mbuf_chain_head;
+}
+
+static ssize_t __udp_sendto_burst(int marsio_fd, struct marsio_udp_buff * buff[],
+ unsigned int nr_buff, int flags, struct sockaddr * to, socklen_t addrlen)
+{
+ // ���ҵ�ǰ��FD��Ӧ��UCB
+ struct sk_ucb * ucb = sk_ucb_lookup_by_index(sk_default_app_instance, marsio_fd);
+ if (unlikely(ucb == NULL)) return -EINVAL;
+
+ // ��ַת����MBUFת��
+ struct sockaddr_in * sockaddr_in = (struct sockaddr_in *)to;
+ if (unlikely(sockaddr_in->sin_family != AF_INET)) return -EINVAL;
+
+ struct rte_mbuf * mbufs[MR_BURST_MAX];
+ for(int i = 0; i < nr_buff; i++)
+ {
+ mbufs[i] = update_rte_mbuf(buff[i]);
+ }
+
+ // ��ѯĿ��Destinfo
+ struct sk_destinfo * destinfo = sk_ucb_destinfo_get(ucb);
+ if (destinfo != NULL) goto send;
+
+ destinfo = sk_destinfo_create_by_route(sk_default_app_instance, sockaddr_in->sin_addr);
+ if (unlikely(destinfo == NULL)) goto errout;
+
+send:
+ return sk_udp_send_burst(sk_default_app_instance, flags, destinfo, mbufs,
+ nr_buff, 0);
+
+errout:
+
+
+ return 0;
+}
+
+ssize_t marsio_udp_sendto_chain(int marsio_fd, struct marsio_udp_buff * chain_head, int nb_buff,
+ int flags, struct sockaddr * to[], socklen_t addrlen[], int nb_sockaddrs)
+{
+ int nb_chain_pkts = 0;
+ struct marsio_udp_buff * buff_array[MR_BURST_MAX];
+
+ if (unlikely(nb_buff > RTE_DIM(buff_array))) return -ENOBUFS;
+ for (struct marsio_udp_buff * __head = chain_head; __head != NULL; __head = __head->next_pkt)
+ {
+ buff_array[nb_chain_pkts++] = __head;
+ }
+
+ // ��֧�ִ���1��Ŀ���ַ
+ if (nb_sockaddrs > 1) return -EINVAL;
+ return __udp_sendto_burst(marsio_fd, buff_array, nb_chain_pkts, flags, to[0], addrlen[0]);
+} \ No newline at end of file
diff --git a/stack/src/ip.c b/stack/src/ip.c
new file mode 100644
index 0000000..73c8455
--- /dev/null
+++ b/stack/src/ip.c
@@ -0,0 +1,61 @@
+/* \brief Э��ջIP�㱨�Ĵ���
+ *
+ * \author Lu Qiuwen<[email protected]>
+ * \date 2016-11-28
+ */
+
+#include <rte_ip.h>
+#include <mr_common.h>
+#include <sk_stack.h>
+#include <sk_device.h>
+
+#define __IP_VERSION_IHL(version, len) (version << 4 | len << 0)
+#define __IP_TTL 75
+
+uint16_t __get_ip_counter(struct sk_app_instance * app_instance, struct sk_destinfo * destinfo)
+{
+ return rte_atomic16_add_return(&app_instance->instance->ip_counter, 1);
+}
+
+struct sk_packet_info
+{
+ struct ether_addr s_ether_addr;
+ struct ether_addr d_ether_addr;
+ struct in_addr s_in_addr;
+ struct in_addr d_in_addr;
+ in_port_t s_in_port;
+ in_port_t d_in_port;
+};
+
+
+int sk_ip_packet_construct(struct sk_app_instance * app_instance, struct rte_mbuf * mbuf,
+ struct sk_destinfo * destinfo, uint8_t l4_proto)
+{
+ struct ipv4_hdr * ip_hdr = (struct ipv4_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(struct ipv4_hdr));
+ uint16_t datalen = rte_pktmbuf_pkt_len(mbuf);
+ assert(ip_hdr != NULL);
+
+ uint16_t ip_counter = __get_ip_counter(app_instance, destinfo);
+ ip_hdr->version_ihl = __IP_VERSION_IHL(4, sizeof(struct ipv4_hdr) / 4);
+ ip_hdr->type_of_service = 0;
+ ip_hdr->total_length = rte_cpu_to_be_16(datalen);
+ ip_hdr->packet_id = rte_cpu_to_be_16(ip_counter);
+ ip_hdr->fragment_offset = 0;
+ ip_hdr->time_to_live = __IP_TTL;
+ ip_hdr->next_proto_id = l4_proto;
+ ip_hdr->hdr_checksum = 0;
+ ip_hdr->src_addr = destinfo->s_in_addr.s_addr;
+ ip_hdr->dst_addr = destinfo->d_in_addr.s_addr;
+
+ mbuf->l3_len = sizeof(struct ipv4_hdr);
+ mbuf->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM;
+
+ struct ether_hdr * ether_hdr = (struct ether_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(struct ether_hdr));
+ assert(ether_hdr != NULL);
+
+ mbuf->l2_len = sizeof(struct ether_hdr);
+ ether_addr_copy(&destinfo->s_eth_addr, &ether_hdr->s_addr);
+ ether_addr_copy(&destinfo->d_eth_addr, &ether_hdr->d_addr);
+ ether_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ return 0;
+} \ No newline at end of file
diff --git a/stack/src/neigh.c b/stack/src/neigh.c
index ac2ef3c..a7ab285 100644
--- a/stack/src/neigh.c
+++ b/stack/src/neigh.c
@@ -11,220 +11,276 @@
#include <rte_rwlock.h>
#include <rte_atomic.h>
#include <rte_ether.h>
-#include <rte_ip.h>
#include <rte_ip_frag.h>
#include <rte_timer.h>
-
+#include <mr_common.h>
+#include <sk_stack.h>
#include <sk_device.h>
-#include <sk_protocol_arp.h>
-#include <sk_neigh.h>
-#include <rte_cycles.h>
#include <rte_hash_crc.h>
+#include <rte_errno.h>
+#include <errno.h>
+#include <assert.h>
+#include <sk_neigh.h>
+#include <sk_arp.h>
-#define __IP_VERSION_IHL(version, len) (version << 4 | len << 0)
-#define __IP_TTL 75
+enum neigh_state
+{
+ NEIGH_IN_NONE = 0,
+ NEIGH_IN_COMPLETE = 1,
+ NEIGH_IN_USE = 2,
+ NEIGH_IN_TIMEOUT = 3,
+ NEIGH_IN_DEAD = 4
+};
-// �����㱨��ͷ
-static inline size_t __neigh_fill_ether_hdr(uint8_t * hdr, const struct ether_addr * src_addr,
- const struct ether_addr * dst_addr, const uint16_t next_layer_type)
+/* Neighbour Table Object Rule */
+struct neighbour
{
- struct ether_hdr * ether_hdr = (struct ether_hdr *)hdr;
- ether_addr_copy(src_addr, &ether_hdr->s_addr);
- ether_addr_copy(dst_addr, &ether_hdr->d_addr);
- ether_hdr->ether_type = htons(next_layer_type);
- return sizeof(struct ether_hdr);
-}
+ /* ������ */
+ TAILQ_ENTRY(neighbour) next;
+ /* IP��ַ */
+ struct in_addr in_addr;
+ /* Ŀ��MAC��ַ */
+ struct ether_addr eth_addr;
+ /* �豸������ */
+ struct sk_dev_info * dev_info;
+ /* ����״̬ */
+ enum neigh_state state;
+ /* ת�뵱ǰ״̬��ʱ�� */
+ time_t t_start_state;
+ /* �ϴη���ARP�����ʱ�� */
+ time_t t_last_request;
+ /* �ϴ��յ�ARPӦ���ʱ�� */
+ time_t t_last_update;
+ /* ���ñ�־λ */
+ unsigned short en_permanent;
+};
-// ������㱨��ͷ
-static inline size_t __neigh_fill_ipv4_hdr(uint8_t * hdr, const struct in_addr * src_addr,
- const struct in_addr * dst_addr, uint16_t total_len, uint16_t pid, uint8_t next_proto)
+int neighbour_mamanger_init(struct neighbour_manager * object,
+ const char * symbol, unsigned int max_entries, unsigned short t_timeout, unsigned int t_arp_send)
{
- struct ipv4_hdr * ip_hdr = (struct ipv4_hdr *)hdr;
-
- ip_hdr->version_ihl = __IP_VERSION_IHL(4, sizeof(struct ipv4_hdr) / 4);
- ip_hdr->type_of_service = 0;
- ip_hdr->total_length = htons(total_len);
- ip_hdr->packet_id = htons(pid);
- ip_hdr->fragment_offset = 0;
- ip_hdr->time_to_live = __IP_TTL;
- ip_hdr->next_proto_id = next_proto;
- ip_hdr->hdr_checksum = 0;
-
- ip_hdr->src_addr = src_addr->s_addr;
- ip_hdr->dst_addr = dst_addr->s_addr;
- return sizeof(struct ipv4_hdr);
-}
+ int ret = 0;
-static inline void neigh_fill_destinfo(struct sk_neighbour * neigh)
-{
- struct sk_dest_info * dest_info = &neigh->dest_info;
- size_t ret;
-
- ret = __neigh_fill_ether_hdr(dest_info->hdr,
- &neigh->dev->dev_info->mac_addr, &neigh->ether_addr,
- ETHER_TYPE_IPv4);
- neigh->dest_info.l2_len = ret;
-
- ret = __neigh_fill_ipv4_hdr(dest_info->hdr + ret,
- &neigh->dev->dev_info->in_addr,
- &neigh->in_addr, 0, 0, 0);
- neigh->dest_info.l3_len = ret;
- return;
-}
+ char tbsymbol[MR_SYMBOL_MAX];
+ snprintf(tbsymbol, sizeof(tbsymbol), "NEIGH_%s", symbol);
-static void neigh_destory(struct sk_neighbour * neigh)
-{
- return;
-}
+ struct rte_hash_parameters hash_params =
+ {
+ .name = tbsymbol,
+ .entries = max_entries,
+ .key_len = sizeof(struct in_addr),
+ .hash_func = NULL,
+ .hash_func_init_val = 0,
+ };
-static void neigh_probe(struct sk_neighbour * neigh)
-{
- protocol_arp_request_send(neigh->dev, neigh->in_addr);
+ object->table = rte_hash_create(&hash_params);
+ if (unlikely(object->table == NULL))
+ {
+ MR_LOG(WARNING, STACK, "NeighbourManagerInit,"
+ "Cannot create hash table for %s : %s", symbol, __str_errno());
+ ret = -1; goto errout;
+ }
+
+ TAILQ_INIT(&object->in_none_list);
+ rte_atomic16_init(&object->in_none_list_len);
+ rte_rwlock_init(&object->rwlock);
+ return 0;
+
+errout:
+ if (object->table != NULL) rte_hash_free(object->table);
+ return ret;
}
-static inline void neigh_hold(struct sk_neighbour * neigh)
+int neighbour_mamanger_deinit(struct neighbour_manager * object)
{
- rte_atomic16_add(&neigh->refcnt, 1);
- return;
+ rte_hash_free(object->table);
+ return 0;
}
-static inline void neigh_release(struct sk_neighbour * neigh)
+static void __change_neigh_state(struct neighbour * neigh, enum neigh_state target_state)
{
- if (rte_atomic16_dec_and_test(&neigh->refcnt))
- neigh_destory(neigh);
- return;
+ if (target_state != neigh->state)
+ {
+ neigh->state = target_state;
+ neigh->t_start_state = time(NULL);
+ }
}
-static struct sk_neighbour * neigh_alloc(struct sk_neigh_table * tbl, struct sk_dev_desc * dev)
+static struct neighbour * __neigh_create_and_join_hash(struct neighbour_manager * object,
+ struct in_addr in_addr, struct ether_addr * eth_addr,
+ struct sk_dev_info * devinfo, unsigned short en_permanent)
{
- struct sk_neighbour * neigh = rte_zmalloc(NULL, sizeof(struct sk_neighbour), 0);
+ struct neighbour * neigh = rte_zmalloc(NULL, sizeof(struct neighbour), 0);
if (unlikely(neigh == NULL))
{
- MR_LOG(INFO, STACK, "NeighSystem, NeighCreate, "
- "Cannot alloc memory for neighbor structure. \n");
+ MR_LOG(WARNING, STACK, "Neighbour, Cannot create neigh structure : %s", __str_errno());
return NULL;
}
- rte_rwlock_init(&neigh->rwlock);
- rte_atomic16_init(&neigh->refcnt);
- neigh->state = NUD_NONE;
- neigh->dead = 1;
- neigh->update = rte_rdtsc();
- neigh->dev = dev;
+ neigh->in_addr = in_addr;
+ neigh->dev_info = devinfo;
+ neigh->en_permanent = en_permanent;
+ neigh->t_last_update = 0;
+ neigh->t_last_request = 0;
+ neigh->state = NEIGH_IN_NONE;
+
+ if(eth_addr != NULL)
+ {
+ ether_addr_copy(eth_addr, &neigh->eth_addr);
+ __change_neigh_state(neigh, NEIGH_IN_USE);
+ }
+
+ if(en_permanent)
+ {
+ neigh->en_permanent = 1;
+ }
+
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
+ int ret = rte_hash_add_key_with_hash_data(object->table, &in_addr, hash, neigh);
+ if (unlikely(ret < 0))
+ {
+ MR_LOG(WARNING, STACK, "Neighbour, Insert neigh to hash table failed : %s",
+ __str_errno());
+ goto errout;
+ }
+
return neigh;
+
+errout:
+ if (neigh) rte_free(neigh);
+ return NULL;
}
+static void __neigh_update(struct neighbour * neigh, struct in_addr in_addr,
+ struct ether_addr * eth_addr, struct sk_dev_info * devinfo, unsigned short en_permanent)
+{
+ assert(neigh != NULL);
+ neigh->in_addr = in_addr;
+ neigh->en_permanent = en_permanent;
+ neigh->dev_info = devinfo;
+
+ if(eth_addr != NULL)
+ {
+ ether_addr_copy(eth_addr, &neigh->eth_addr);
+ __change_neigh_state(neigh, NEIGH_IN_USE);
+ }
-int neigh_update(struct sk_neighbour * neigh, const struct ether_addr * lladdr,
- uint8_t state, uint32_t flags)
+ return;
+}
+
+int neigh_create_or_update(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * eth_addr, struct sk_dev_info * devinfo, unsigned short en_permanent)
{
- rte_rwlock_write_lock(&neigh->rwlock);
- struct sk_dev_desc * dev = neigh->dev;
- uint8_t old_state = neigh->state;
+ rte_rwlock_write_lock(&object->rwlock);
+ struct neighbour * neigh = NULL;
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
- if((old_state & NUD_REACHABLE) && (state & NUD_REACHABLE))
+ int ret = rte_hash_lookup_with_hash_data(object->table, &in_addr, hash, (void **)&neigh);
+ if (ret < 0)
{
- ether_addr_copy(lladdr, &neigh->ether_addr);
- neigh_fill_destinfo(neigh);
- neigh->dead = 0;
- neigh->state = state;
+ neigh = __neigh_create_and_join_hash(object, in_addr, eth_addr, devinfo, en_permanent);
}
-
- if((old_state & NUD_INCOMPLETE ) && (state & NUD_REACHABLE))
+ else
+ {
+ __neigh_update(neigh, in_addr, eth_addr, devinfo, en_permanent);
+ }
+
+ if (unlikely(neigh == NULL)) return -1;
+ if (neigh->state == NEIGH_IN_NONE)
{
- ether_addr_copy(lladdr, &neigh->ether_addr);
- neigh_fill_destinfo(neigh);
- neigh->dead = 0;
- neigh->state = state;
+ TAILQ_INSERT_TAIL(&object->in_none_list, neigh, next);
+ rte_atomic16_inc(&object->in_none_list_len);
}
+
+ ret = 0; goto exit;
- rte_rwlock_write_unlock(&neigh->rwlock);
- return 0;
+exit:
+ rte_rwlock_write_unlock(&object->rwlock);
+ return ret;
}
-int neigh_event_send(struct sk_neighbour * neigh, struct rte_mbuf * mbuf)
+int neigh_delete(struct neighbour_manager * object, struct in_addr in_addr)
{
- rte_rwlock_write_lock(&neigh->rwlock);
+ rte_rwlock_write_lock(&object->rwlock);
+ struct neighbour * neigh = NULL;
- if (neigh->state & (NUD_REACHABLE))
- goto out_unblock;
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
+ int ret = rte_hash_lookup_with_hash_data(object->table, &in_addr, hash, (void **)&neigh);
+ if (ret < 0) goto exit;
- if(neigh->state & NUD_NONE)
+ // ������IN_NONE״̬ʱ����IN_NONE�б����Ƴ�
+ if (neigh->state == NEIGH_IN_NONE)
{
- neigh_probe(neigh);
- goto out_unblock;
+ TAILQ_REMOVE(&object->in_none_list,neigh, next);
+ rte_atomic16_dec(&object->in_none_list_len);
}
- //TODO: ����״̬������
+ rte_hash_del_key_with_hash(object->table, &in_addr, hash);
+ rte_free(neigh);
+ ret = 0; goto exit;
-out_unblock:
- rte_rwlock_write_unlock(&neigh->rwlock);
- return 0;
+exit:
+ rte_rwlock_write_unlock(&object->rwlock);
+ return ret;
}
-struct sk_neighbour * neigh_create(struct sk_neigh_table * tbl,
- struct in_addr in_addr, struct sk_dev_desc * dev)
+int neigh_query(struct neighbour_manager * object, struct in_addr in_addr,
+ struct ether_addr * out_ether_addr, struct sk_dev_info ** out_dev_info)
{
- struct sk_neighbour * neigh = neigh_alloc(tbl, dev);
- if (unlikely(neigh == NULL)) return NULL;
-
- // Hashֵ��ΪIP��ַ������ֵ�����뵽Hash����
- hash_t hash = in_addr.s_addr;
- rte_rwlock_write_lock(&tbl->neigh_tbl_lock);
- rte_hash_add_key_with_hash(tbl->neigh_tbl, &hash, hash);
- rte_rwlock_write_unlock(&tbl->neigh_tbl_lock);
-
- // ���������¼�������ARP����
- neigh_event_send(neigh, NULL);
- neigh_hold(neigh);
- return neigh;
-}
+ struct neighbour * neigh = NULL;
-struct sk_neighbour * neigh_lookup(struct sk_neigh_table * tbl,
- const void * pkey, int hold)
-{
- hash_t hash = *(uint32_t *)pkey;
- struct sk_neighbour * neigh;
+ rte_rwlock_read_lock(&object->rwlock);
+ hash_sig_t hash = rte_hash_crc(&in_addr, sizeof(in_addr), 0);
+ int ret = rte_hash_lookup_with_hash_data(object->table, &in_addr, hash, (void **)&neigh);
+
+ // û�鵽
+ if (ret < 0) goto exit;
- rte_rwlock_read_lock(&tbl->neigh_tbl_lock);
- rte_hash_lookup_with_hash_data(tbl->neigh_tbl, &hash, hash, (void **)&neigh);
- rte_rwlock_read_unlock(&tbl->neigh_tbl_lock);
+ // ����״̬��Ϣ��ȫ���޷������ṩ��ѯ
+ if (neigh->state == NEIGH_IN_NONE ||
+ neigh->state == NEIGH_IN_COMPLETE ||
+ neigh->state == NEIGH_IN_DEAD)
+ {
+ ret = -EFAULT; goto exit;
+ }
- if (neigh == NULL) return NULL;
+ ether_addr_copy(&neigh->eth_addr, out_ether_addr);
+ *out_dev_info = neigh->dev_info;
+ ret = 0; goto exit;
- if (hold) neigh_hold(neigh);
- return neigh;
+exit:
+ rte_rwlock_read_unlock(&object->rwlock);
+ return ret;
}
-int neigh_tbl_init(struct sk_neigh_table * tbl, const char * symbol, unsigned int nr_entries)
+static void __neigh_handle_in_no_queue(struct sk_app_instance * app_instance,
+ thread_id_t sid, struct neighbour_manager * object)
{
- char hash_tbl_symbol[MR_SYMBOL_MAX];
- snprintf(hash_tbl_symbol, sizeof(hash_tbl_symbol), "NTB-%s", symbol);
-
- struct rte_hash_parameters hash_params =
- {
- .name = hash_tbl_symbol,
- .entries = nr_entries,
- .key_len = sizeof(uint32_t),
- .hash_func = rte_hash_crc,
- .hash_func_init_val = 0,
- };
+ if (rte_atomic16_read(&object->in_none_list_len) == 0) return;
+
+ rte_rwlock_write_lock(&object->rwlock);
+ struct neighbour * neigh_iter;
+ struct sk_dev_desc * dev_desc;
- tbl->neigh_tbl = rte_hash_create(&hash_params);
- if (unlikely(tbl == NULL))
+ // ��ÿһ����In-None�б��е�Neigh����ARP����
+ TAILQ_FOREACH(neigh_iter, &object->in_none_list, next)
{
- MR_LOG(WARNING, STACK, "NeighSystem, NeighTblInit, "
- "Create hash table %s failed(for NeighTable %s): %s. \n",
- hash_tbl_symbol, symbol, rte_strerror(rte_errno));
- return -1;
+ dev_desc = sk_device_desc_lookup(app_instance, neigh_iter->dev_info->symbol);
+
+ assert(dev_desc != NULL);
+ protocol_serv_arp_request_send(dev_desc, sid, neigh_iter->in_addr);
+
+ // ������ϣ��Ƴ���һ����ϣ���л������ã����ͷſռ�
+ TAILQ_REMOVE(&object->in_none_list, neigh_iter, next);
+ rte_atomic16_dec(&object->in_none_list_len);
}
- rte_rwlock_init(&tbl->neigh_tbl_lock);
- return 0;
+ // In-None�б�Ӧ��Ϊ�գ���������Ӧ��Ϊ0
+ assert(rte_atomic16_read(&object->in_none_list_len) == 0);
+ rte_rwlock_write_unlock(&object->rwlock);
}
-int neigh_tbl_deinit(struct sk_neigh_table * tbl)
+void neighbour_manager_loop_entry(struct sk_app_instance * app_instance,
+ thread_id_t sid, struct neighbour_manager * object)
{
- rte_hash_reset(tbl->neigh_tbl);
- return 0;
+ __neigh_handle_in_no_queue(app_instance, sid, object);
} \ No newline at end of file
diff --git a/stack/src/pcom.c b/stack/src/pcom.c
new file mode 100644
index 0000000..0683822
--- /dev/null
+++ b/stack/src/pcom.c
@@ -0,0 +1,58 @@
+
+#include <mr_rtdev.h>
+#include <sk_device.h>
+#include <sk_stack.h>
+#include <sk_pcom.h>
+
+// ����Э���ʼ��������������Ӧ������ʱ�豸��
+int protocol_common_dev_desc_init(struct sk_instance * instance,
+ struct sk_dev_desc * dev_desc, const char * protosym, struct rtdev_desc ** rtdev_desc)
+{
+ struct sk_param * param = &instance->param;
+ struct rtdev_desc * _rtdev_desc;
+
+ char rtdevsym[MR_SYMBOL_MAX];
+ snprintf(rtdevsym, sizeof(rtdevsym), "%s-%s", dev_desc->dev_info->symbol, protosym);
+
+ // ��������ʱ�豸
+ _rtdev_desc = mr_rtdev_create(instance->core_instance, rtdevsym,
+ dev_desc->direct_pool, param->nr_serv_thread, param->sz_deliver_ring, param->sz_deliver_buffer);
+
+ // ����ʧ��
+ if (_rtdev_desc == NULL)
+ {
+ MR_LOG(WARNING, STACK, "Create rt-device(protosym=%s) for sk-dev %s"
+ "(serv_sym=%s, nr_thread=%d, sz_ring=%d, sz_buffer=%d) failed. \n",
+ protosym, dev_desc->dev_info->symbol, param->servsym, param->nr_serv_thread,
+ param->sz_deliver_ring, param->sz_deliver_buffer);
+ return -1;
+ }
+
+ *rtdev_desc = _rtdev_desc;
+ return 0;
+}
+
+int protocol_common_dev_desc_slave_init(struct sk_app_instance * app_instance,
+ struct sk_dev_desc * dev_desc, const char * protosym, struct rtdev_app_desc ** rtdev_app_desc,
+ unsigned int nr_rxstream, unsigned int nr_txstream)
+{
+ char rtdevsym[MR_SYMBOL_MAX];
+ snprintf(rtdevsym, sizeof(rtdevsym), "%s-%s", dev_desc->dev_info->symbol, protosym);
+ struct rtdev_app_desc * _rtdev_app_desc;
+
+ // ��������ʱ�豸
+ _rtdev_app_desc = mr_rt_device_open(app_instance->instance->core_instance,
+ dev_desc->dev_info->symbol, app_instance->appsym, nr_rxstream, nr_txstream);
+
+ // ����ʧ��
+ if (_rtdev_app_desc == NULL)
+ {
+ MR_LOG(WARNING, STACK, "Open rt-device(protosym=%s) for sk-dev %s"
+ "(nr_rxstream=%d, nr_txstream=%d) failed. \n", protosym,
+ dev_desc->dev_info->symbol, nr_rxstream, nr_txstream);
+ return -1;
+ }
+
+ *rtdev_app_desc = _rtdev_app_desc;
+ return 0;
+} \ No newline at end of file
diff --git a/stack/src/protocol-arp.c b/stack/src/protocol-arp.c
deleted file mode 100644
index 8c4c046..0000000
--- a/stack/src/protocol-arp.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* \brief ��Э��ջARP/RARPЭ�鴦��ģ��
-*
-* ����ARP/RARPЭ�鱨������
-*
-* \author Lu Qiuwen<[email protected]>
-* \date 2016-10-21
-*/
-
-#include <mr_rtdev.h>
-#include <sk_stack.h>
-#include <sk_device.h>
-#include <rte_malloc.h>
-
-int protocol_arp_init(struct mr_stack_instance * instance)
-{
- return 0;
-}
-
-int protocol_arp_deinit(struct mr_stack_instance * instance)
-{
- return 0;
-}
-
-int protocol_arp_slave_init(struct mr_stack_instance * instance,
- struct mr_stack_slave_instance * slave_instance)
-{
- return 0;
-}
-
-int protocol_arp_slave_deinit(struct mr_stack_instance * instance,
- struct mr_stack_slave_instance * slave_instance)
-{
- return 0;
-}
-
-int protocol_arp_dev_init(struct sk_dev_desc * dev)
-{
- return 0;
-}
-
-int protocol_arp_dev_deinit(struct sk_dev_desc * dev)
-{
- return 0;
-}
-
-int protocol_arp_slave_dev_init(struct sk_dev_desc * dev)
-{
- return 0;
-}
-
-int protocol_arp_slave_dev_deinit(struct sk_dev_desc * dev)
-{
- return 0;
-}
-
-// ARP���Ĵ�����ں�����������̴�����
-void protocol_serv_arp_entry(struct sk_dev_desc* dev_desc,
- thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
-{
- return;
-}
-
-int protocol_arp_request_send(struct sk_dev_desc * dev, struct in_addr in_addr)
-{
- return 0;
-} \ No newline at end of file
diff --git a/stack/src/protocol-icmp.c b/stack/src/protocol-icmp.c
deleted file mode 100644
index e1d80ef..0000000
--- a/stack/src/protocol-icmp.c
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#include <sk_device.h>
-#include <sk_stack.h>
-
-void protocol_serv_icmp_entry(struct sk_dev_desc* dev_desc, thread_id_t sid,
- struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
-{
- return;
-} \ No newline at end of file
diff --git a/stack/src/protocol-udp.c b/stack/src/protocol-udp.c
deleted file mode 100644
index adf2c12..0000000
--- a/stack/src/protocol-udp.c
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#include <sk_device.h>
-#include <sk_stack.h>
-
-void protocol_serv_udp_entry(struct sk_dev_desc* dev_desc,
- thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
-{
- return;
-} \ No newline at end of file
diff --git a/stack/src/route.c b/stack/src/route.c
new file mode 100644
index 0000000..d62aa1d
--- /dev/null
+++ b/stack/src/route.c
@@ -0,0 +1,185 @@
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sk_device.h>
+#include <rte_lpm.h>
+#include <rte_malloc.h>
+#include <sk_stack.h>
+#include <sk_route.h>
+
+struct sk_route_tbl
+{
+ struct rte_lpm * lpm;
+ unsigned int nr_next_device;
+ struct sk_dev_info * next_device[MR_DEVICE_MAX];
+ struct sk_dev_info * default_device;
+};
+
+struct sk_route_tbl * route_tbl_create(const char * symbol, unsigned max_rules)
+{
+ struct sk_route_tbl * tbl_object = rte_zmalloc(symbol, sizeof(struct sk_route_tbl), 0);
+ if(unlikely(tbl_object == NULL))
+ {
+ MR_LOG(WARNING, STACK, "Cannot alloc memory for route table. \n");
+ return NULL;
+ }
+
+ struct rte_lpm_config _lpm_config;
+ _lpm_config.max_rules = max_rules;
+ _lpm_config.number_tbl8s = max_rules / 8;
+ _lpm_config.flags = 0;
+
+ tbl_object->lpm = rte_lpm_create(symbol, SOCKET_ID_ANY, &_lpm_config);
+ if(unlikely(tbl_object->lpm == NULL))
+ {
+ MR_LOG(ERR, STACK, "Unable to create the LPM table(symbol=%s, max_rules=%d). \n",
+ symbol, max_rules);
+ goto error;
+ }
+
+ return tbl_object;
+
+error:
+ if (tbl_object != NULL) rte_free(tbl_object);
+ return NULL;
+}
+
+void route_tbl_set_default_hop(struct sk_route_tbl * tbl_object, struct sk_dev_info * dev_info)
+{
+ assert(tbl_object != NULL);
+ tbl_object->default_device = dev_info;
+}
+
+struct sk_dev_info * route_tbl_get_default_hop(struct sk_route_tbl * tbl_object)
+{
+ assert(tbl_object != NULL);
+ return tbl_object->default_device;
+}
+
+static inline int __mask_to_depth(uint32_t mask)
+{
+ int count = 0;
+ while (mask)
+ {
+ ++count;
+ mask = (mask - 1)&mask;
+ }
+ return count;
+}
+
+int route_tbl_insert(struct sk_route_tbl * tbl_object, struct in_addr in_addr,
+ struct in_addr in_mask, struct sk_dev_info * dev_info)
+{
+ int next_hop_id = -1;
+
+ for(int i = 0; i < tbl_object->nr_next_device; i++)
+ {
+ if (tbl_object->next_device[i] != dev_info) continue;
+ next_hop_id = i;
+ }
+
+ if(next_hop_id < 0)
+ {
+ tbl_object->next_device[tbl_object->nr_next_device] = dev_info;
+ next_hop_id = tbl_object->nr_next_device;
+ tbl_object->nr_next_device++;
+ }
+
+ assert(next_hop_id < RTE_DIM(tbl_object->next_device));
+ int ret = rte_lpm_add(tbl_object->lpm, in_addr.s_addr, __mask_to_depth(
+ in_mask.s_addr), next_hop_id);
+
+ char str_in_addr[INET_ADDRSTRLEN];
+ char str_in_mask[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &in_addr, str_in_addr, sizeof(str_in_addr));
+ inet_ntop(AF_INET, &in_mask, str_in_mask, sizeof(str_in_mask));
+
+ if(unlikely(ret < 0))
+ {
+ MR_LOG(WARNING, STACK, "Insert route tbl rules(in_addr=%s, "
+ "in_mask=%s, next_hop=%s) failed: %s\n", str_in_addr, str_in_mask,
+ tbl_object->next_device[next_hop_id]->symbol, __str_errno());
+ return ret;
+ }
+
+ MR_LOG(INFO, STACK, "RouteTableRule(in_addr=%s, in_mask=%s, next_hop=%s) inserted. \n",
+ str_in_addr, str_in_mask, tbl_object->next_device[next_hop_id]->symbol);
+
+ return 0;
+}
+
+struct sk_dev_info * route_tbl_lookup(struct sk_route_tbl * tbl_object, struct in_addr in_addr,
+ char * result_is_gateway)
+{
+ uint32_t next_hop;
+ int ret = rte_lpm_lookup(tbl_object->lpm, in_addr.s_addr, &next_hop);
+ if (ret == -EINVAL) return NULL;
+ if (ret == -ENOENT) return tbl_object->default_device;
+ if (ret == 0) return tbl_object->next_device[next_hop];
+ return NULL;
+}
+
+void sk_destinfo_destory(struct sk_destinfo * destinfo)
+{
+ rte_free(destinfo);
+}
+
+struct sk_destinfo * sk_destinfo_create_by_route(struct sk_app_instance * app_instance,
+ struct in_addr d_in_addr)
+{
+ struct sk_instance * instance = app_instance->instance;
+ struct sk_destinfo * destinfo = rte_zmalloc(NULL, sizeof(struct sk_destinfo), 0);
+ if (destinfo == NULL) return destinfo;
+
+ char str_in_addr[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &d_in_addr, str_in_addr, sizeof(str_in_addr));
+
+ struct in_addr query_in_addr = d_in_addr;
+ struct ether_addr d_eth_addr = { {0} };
+ struct sk_dev_info * dev_info = NULL;
+ struct sk_dev_desc * dev_desc = NULL;
+
+ char is_gateway = 0;
+ dev_info = route_tbl_lookup(instance->default_route, d_in_addr, &is_gateway);
+ if (dev_info == NULL)
+ {
+ MR_LOG(ERR, STACK, "No route to host %s. \n", str_in_addr);
+ goto errout;
+ }
+
+ // ��ѯ�����豸�Ƿ��
+ dev_desc = sk_device_desc_lookup(app_instance, dev_info->symbol);
+ if(dev_desc == NULL)
+ {
+ MR_LOG(ERR, STACK, "Stack Device %s is not open. \n", dev_info->symbol);
+ goto errout;
+ }
+
+ // �Ƿ������أ�����·�ɲ�ѯ���ص�MAC��ַ
+ if (is_gateway) query_in_addr = dev_info->in_gateway;
+ int ret = neigh_query(instance->neigh_manager, query_in_addr, &d_eth_addr, &dev_info);
+ if (ret == 0) goto success;
+
+ // û���ھӽڵ㻺�棬����һ���µĽڵ㣬���β�ѯʧ��
+ ret = neigh_create_or_update(instance->neigh_manager, query_in_addr, NULL, dev_info, 0);
+ if(ret < 0)
+ {
+ MR_LOG(ERR, STACK, "Request neighbour for host %s failed. \n", str_in_addr);
+ goto errout;
+ }
+
+ goto errout;
+
+success:
+ destinfo->d_in_addr = d_in_addr;
+ destinfo->s_in_addr = dev_info->in_addr;
+ destinfo->s_eth_addr = dev_info->mac_addr;
+ destinfo->d_eth_addr = d_eth_addr;
+ destinfo->d_dev_info = dev_info;
+ destinfo->d_dev_desc = dev_desc;
+ return destinfo;
+
+errout:
+ if (destinfo != NULL) rte_free(destinfo);
+ return NULL;
+} \ No newline at end of file
diff --git a/stack/src/rxtx.c b/stack/src/rxtx.c
index 92fed52..ded77d0 100644
--- a/stack/src/rxtx.c
+++ b/stack/src/rxtx.c
@@ -6,83 +6,40 @@
* \date 2016-10-21
*/
+#include <unistd.h>
#include <assert.h>
#include <sk_device.h>
#include <sk_stack.h>
-#include <sk_protocol_udp.h>
-#include <sk_protocol_arp.h>
-#include <sk_protocol_tcp.h>
-#include <sk_protocol_icmp.h>
-
-
-struct packet_holder
-{
- struct rte_mbuf * packets[MR_BURST_MAX];
- unsigned int nr_packets;
-};
-
-enum sk_packet_type
-{
- __PACKET_TYPE_ARP = 0,
- __PACKET_TYPE_ICMP = 1,
- __PACKET_TYPE_TCP = 2,
- __PACKET_TYPE_UDP = 3,
- __PACKET_TYPE_FRAG = 4,
- __PACKET_TYPE_ELSE = 5,
- __PACKET_TYPE_MAX
-};
-
-static inline enum sk_packet_type __get_packet_type(struct rte_mbuf * mbuf)
-{
- if (mbuf->packet_type & RTE_PTYPE_L2_ETHER_ARP) return __PACKET_TYPE_ARP;
- if (mbuf->packet_type & RTE_PTYPE_L4_ICMP) return __PACKET_TYPE_ICMP;
- if (mbuf->packet_type & RTE_PTYPE_L4_TCP) return __PACKET_TYPE_TCP;
- if (mbuf->packet_type & RTE_PTYPE_L4_UDP) return __PACKET_TYPE_UDP;
- if (mbuf->packet_type & RTE_PTYPE_L4_FRAG) return __PACKET_TYPE_FRAG;
- return __PACKET_TYPE_ELSE;
-}
+#include <sk_udp.h>
+#include <sk_arp.h>
+#include <sk_tcp.h>
+#include <sk_icmp.h>
int sk_serv_device_tx_bulk(struct sk_dev_desc * dev_desc, thread_id_t sid,
struct rte_mbuf * mbufs_out[], int nr_mbufs_max)
{
- return 0;
+ int nr_mbufs_out = 0;
+ int nr_mbufs_left = nr_mbufs_max;
+
+ // ��ѭ�����Ļ�����
+ nr_mbufs_out += rte_ring_sc_dequeue_burst(dev_desc->tx_loop_buffer[sid],
+ (void **)&mbufs_out[nr_mbufs_out], nr_mbufs_left);
+
+ return nr_mbufs_out;
}
int sk_serv_device_rx_bulk(struct sk_dev_desc * dev_desc, thread_id_t sid,
- struct rte_mbuf * mbufs_in[], struct rte_mbuf * mbufs_out[], int nr_mbufs_in, int * nr_mbufs_out)
+ struct rte_mbuf * mbufs_in[], int nr_mbufs_in)
{
- struct packet_holder packets[__PACKET_TYPE_MAX];
- for (int i = 0; i < __PACKET_TYPE_MAX; i++) packets[i].nr_packets = 0;
-
- // ���ķ��࣬���ݱ���Э���ǩ
- for(int i = 0; i < nr_mbufs_in; i++)
- {
- enum sk_packet_type index = __get_packet_type(mbufs_in[i]);
- packets[index].packets[packets[index].nr_packets++] = mbufs_in[i];
- }
-
// ARP���Ĵ���
- protocol_serv_arp_entry(dev_desc, sid, packets[__PACKET_TYPE_ARP].packets,
- packets[__PACKET_TYPE_ARP].nr_packets);
-
- // ICMP���Ĵ���
- protocol_serv_icmp_entry(dev_desc, sid, packets[__PACKET_TYPE_ICMP].packets,
- packets[__PACKET_TYPE_TCP].nr_packets);
-
- // TCP���Ĵ���
- protocol_serv_tcp_entry(dev_desc, sid, packets[__PACKET_TYPE_TCP].packets,
- packets[__PACKET_TYPE_TCP].nr_packets);
+ int nr_handled = 0;
+ nr_handled += protocol_serv_arp_entry(dev_desc, sid, mbufs_in, nr_mbufs_in);
+ // ICMP���Ĵ���
+ nr_handled += protocol_serv_icmp_entry(dev_desc, sid, mbufs_in, nr_mbufs_in);
+
// UDP���Ĵ���
- protocol_serv_udp_entry(dev_desc, sid, packets[__PACKET_TYPE_UDP].packets,
- packets[__PACKET_TYPE_UDP].nr_packets);
+ nr_handled += protocol_serv_udp_entry(dev_desc, sid, mbufs_in, nr_mbufs_in);
- // �޷������ı��ģ����ظ��ϲ�
- for(int i = 0; i < packets[__PACKET_TYPE_ELSE].nr_packets; i++)
- {
- mbufs_out[i] = packets[__PACKET_TYPE_ELSE].packets[i];
- assert(i <= nr_mbufs_in);
- }
-
- return 0;
+ return nr_handled;
} \ No newline at end of file
diff --git a/stack/src/stack.c b/stack/src/stack.c
index 1197167..d13f284 100644
--- a/stack/src/stack.c
+++ b/stack/src/stack.c
@@ -4,30 +4,129 @@
* \date 2016-10-18
*/
+#include <mr_common.h>
#include <sk_stack.h>
#include <rte_ip_frag.h>
+#include <sk_neigh.h>
+#include <sk_device.h>
+#include <mr_buffer.h>
-struct mr_stack_instance * mr_stack_instance_create(struct mr_stack_param * param)
+int __instance_setup_ctrlzone(struct mr_core_instance * core_instance,
+ const char * symbol, uint8_t size, uint8_t * id)
{
- struct mr_stack_instance * instance;
+ uint8_t _id = 0;
+ uint8_t _size = 0;
+
+ int ret = mr_buffer_ctrlzone_lookup(core_instance, symbol, &_id, &_size);
+ if (ret < 0)
+ {
+ MR_LOG(WARNING, STACK, "Lookup ctrlzone %s failed. "
+ "Please setup the ctrlzone as size %d.", symbol, size);
+ return -1;
+ }
+
+ if (_size < size)
+ {
+ MR_LOG(WARNING, STACK, "Ctrlzone %s's size is not enough, "
+ "at least %d. Failed. ", symbol, size);
+ return -2;
+ }
+
+ *id = _id;
+ return 0;
+}
+
+struct sk_instance * sk_instance_create(struct mr_core_instance * core_instance,
+ struct sk_param * param)
+{
+ struct sk_instance * instance;
// 分配空间
- instance = rte_zmalloc(NULL, sizeof(struct mr_stack_instance), 0);
+ instance = rte_zmalloc(NULL, sizeof(struct sk_instance), 0);
if(unlikely(instance == NULL))
{
- MR_LOG(INFO, STACK, "StackInstanceCreate, "
- "Cannot alloc memory for stack instance. \n");
- return NULL;
+ MR_LOG(WARNING, STACK, "Cannot alloc memory for stack instance. \n");
+ goto errout;
}
// 初始化参数
instance->param = *param;
+ instance->core_instance = core_instance;
TAILQ_INIT(&instance->dev_info_list);
- TAILQ_INIT(&instance->dev_desc_list);
+
+ // 初始化邻居管理器
+ struct neighbour_manager * neigh_manager;
+ neigh_manager = rte_zmalloc(NULL, sizeof(struct neighbour_manager), 0);
+
+ if(unlikely(neigh_manager == NULL))
+ {
+ MR_LOG(WARNING, STACK, "Cannot alloc memory for neighbour manager. \n");
+ goto errout;
+ }
+
+ instance->neigh_manager = neigh_manager;
+
+ int ret = neighbour_mamanger_init(instance->neigh_manager, param->servsym,
+ param->nr_neigh_max_neigh, param->t_neigh_timeout, param->t_neigh_arp_send);
+
+ if (unlikely(ret < 0))
+ {
+ MR_LOG(WARNING, STACK, "Neighbour manager init failed. \n");
+ goto errout;
+ }
+
+ // 初始化默认路由表
+ instance->default_route = route_tbl_create("StackDefaultR", 4096);
+ if(unlikely(instance->default_route == NULL))
+ {
+ MR_LOG(WARNING, STACK, "Cannot create default route table. \n");
+ goto errout;
+ }
+
+ // 初始化报文控制域ID
+ ret = __instance_setup_ctrlzone(core_instance, SK_CTRLZONE_PKTINFO_SYMBOL,
+ SK_CTRLZONE_PKTINFO_SIZE, &instance->ctrlzone_id_pktinfo);
+
+ if (ret < 0) goto errout;
+
+ ret = __instance_setup_ctrlzone(core_instance, SK_CTRLZONE_SOQINFO_SYMBOL,
+ SK_CTRLZONE_SOQINFO_SIZE, &instance->ctrlzone_id_soqinfo);
+
+ if (ret < 0) goto errout;
return instance;
+
+errout:
+ if (instance->neigh_manager) rte_free(instance->neigh_manager);
+ if (instance) rte_free(instance);
+ return NULL;
}
-struct mr_stack_slave_instance * mr_stack_slave_create()
+struct sk_app_instance * sk_app_instance_create(struct sk_instance * instance, const char* appsym)
{
- return NULL;
+ struct sk_app_instance * app_instance;
+
+ app_instance = rte_zmalloc(NULL, sizeof(struct sk_instance), 0);
+ if (unlikely(app_instance == NULL))
+ {
+ MR_LOG(WARNING, STACK, "Cannot alloc memory for stack slave instance. \n");
+ return NULL;
+ }
+
+ // 初始化内部句柄
+ app_instance->instance = instance;
+ snprintf(app_instance->appsym, sizeof(app_instance->appsym), "%s", appsym);
+ TAILQ_INIT(&app_instance->dev_desc_list);
+
+ // 内存池
+ app_instance->def_direct_pktmbuf_pool = instance->param.def_direct_pktmbuf_pool;
+ app_instance->def_indirect_pktmbuf_pool = instance->param.def_indirect_pktmbuf_pool;
+
+ assert(app_instance->def_direct_pktmbuf_pool != NULL
+ && app_instance->def_indirect_pktmbuf_pool != NULL);
+
+ // 初始化UDP CTX
+ rte_rwlock_init(&app_instance->udp_ctx.rwlock);
+ portmap_init(&app_instance->udp_ctx.pbm_local, LPORT_START_BLK);
+ app_instance->udp_ctx.app_instance_ = app_instance;
+ return app_instance;
} \ No newline at end of file
diff --git a/stack/src/protocol-tcp.c b/stack/src/tcp.c
index 0af46d8..57ebebf 100644
--- a/stack/src/protocol-tcp.c
+++ b/stack/src/tcp.c
@@ -1,8 +1,8 @@
#include <mr_common.h>
-#include <sk_protocol_tcp.h>
+#include <sk_tcp.h>
void protocol_serv_tcp_entry(struct sk_dev_desc* dev_desc,
thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
{
return;
-}
+} \ No newline at end of file
diff --git a/stack/src/ucb.c b/stack/src/ucb.c
new file mode 100644
index 0000000..86e323e
--- /dev/null
+++ b/stack/src/ucb.c
@@ -0,0 +1,158 @@
+/* \brief MARSIO UDP控制与流表结构
+ * \author Qiuwen Lu<[email protected]>
+ * \date 2016-11-29
+ */
+
+/* UDP控制块,每个UDP控制块代表一个UDP流 */
+#include <rte_malloc.h>
+#include <port_bitmap.h>
+#include <sk_stack.h>
+#include <sk_ucb.h>
+
+union in_addrs
+{
+ uint64_t raw;
+ struct
+ {
+ struct in_addr local_in_addr;
+ struct in_addr remote_in_addr;
+ };
+};
+
+union in_ports
+{
+ uint32_t raw;
+ struct
+ {
+ in_port_t local_in_port;
+ in_port_t remote_in_port;
+ };
+};
+
+struct sk_ucb
+{
+ struct sk_stack_udp_ctx * udp_ctx;
+ TAILQ_ENTRY(sk_ucb) next;
+
+ unsigned int index;
+ union in_ports port;
+ union in_ports pmask;
+
+ union in_addrs in_addr;
+ union in_addrs in_mask;
+
+ unsigned int is_connected;
+ struct sk_destinfo * conn_destinfo;
+ struct rte_hash * cache_destinfo;
+};
+
+int sk_ucb_bind(struct sk_ucb * ucb, struct sockaddr_in * addr)
+{
+ struct sk_stack_udp_ctx * udp_ctx = ucb->udp_ctx;
+ int ret = 0;
+
+ rte_rwlock_write_lock(&udp_ctx->rwlock);
+
+ uint16_t l_port = ntohs(addr->sin_port);
+ if (portmap_check(&udp_ctx->pbm_local, l_port) != 0)
+ {
+ ret = -EEXIST;
+ goto out;
+ }
+
+ assert(udp_ctx->ucbs_local[l_port] == NULL);
+ ucb->in_addr.local_in_addr = addr->sin_addr;
+ ucb->in_mask.local_in_addr.s_addr = 0xffffffff;
+ ucb->port.local_in_port = addr->sin_port;
+ ucb->pmask.local_in_port = 0xffff;
+ ret = 0;
+
+out:
+ rte_rwlock_write_lock(&udp_ctx->rwlock);
+ return ret;
+}
+
+struct sk_destinfo * sk_ucb_destinfo_get(struct sk_ucb * ucb)
+{
+ // 没有设置连接,返回空,外面自己查询
+ if (!ucb->is_connected) return NULL;
+
+ // 已连接,有DestInfo,直接返回
+ if (ucb->conn_destinfo != NULL) return ucb->conn_destinfo;
+
+ // 已连接,没有DestInfo,查询并返回结果
+ ucb->conn_destinfo = sk_destinfo_create_by_route(ucb->udp_ctx->app_instance_,
+ ucb->in_addr.remote_in_addr);
+ return ucb->conn_destinfo;
+}
+
+int sk_ucb_connect(struct sk_ucb * ucb, struct sockaddr_in * addr)
+{
+ ucb->in_addr.remote_in_addr = addr->sin_addr;
+ ucb->in_mask.remote_in_addr.s_addr = 0xffffffff;
+ ucb->port.remote_in_port = addr->sin_port;
+ ucb->pmask.remote_in_port = 0xffff;
+ sk_ucb_destinfo_get(ucb);
+
+ return 0;
+}
+
+int sk_ucb_get_index(struct sk_ucb * ucb)
+{
+ return ucb->index;
+}
+
+struct sk_ucb * sk_ucb_lookup_by_index(struct sk_app_instance * app_instance,
+ int index)
+{
+ struct sk_stack_udp_ctx * udp_ctx = &app_instance->udp_ctx;
+ return udp_ctx->ucbs_local[index];
+}
+
+struct sk_ucb * sk_ucb_create(struct sk_app_instance * app_instance)
+{
+ struct sk_stack_udp_ctx * udp_ctx = &app_instance->udp_ctx;
+ struct sk_ucb * ucb = rte_zmalloc(NULL, sizeof(struct sk_ucb), 0);
+ MR_CHECK(ucb != NULL, "Cannot alloc memory for udp control block. ");
+
+ rte_rwlock_write_lock(&udp_ctx->rwlock);
+ ucb->udp_ctx = udp_ctx;
+
+ // 获得一个临时的本地端口
+ uint16_t l_port = portmap_find_range(&udp_ctx->pbm_local,
+ udp_ctx->pbm_local.blk, LPORT_END_BLCK);
+
+ if (l_port == 0 && udp_ctx->pbm_local.blk > LPORT_START_BLK)
+ {
+ l_port = portmap_find_range(&udp_ctx->pbm_local, LPORT_START_BLK,
+ udp_ctx->pbm_local.blk);
+ }
+
+ if(l_port == 0)
+ {
+ MR_LOG(WARNING, STACK, "Creating UDP Control Failed: No avilable local port. \n");
+ goto err_out;
+ }
+
+ // 临时本地端口使能
+ assert(portmap_check(&udp_ctx->pbm_local, l_port) == 0);
+ portmap_set(&udp_ctx->pbm_local, l_port);
+
+ assert(udp_ctx->ucbs_local[l_port] == NULL);
+ udp_ctx->ucbs_local[l_port] = ucb;
+
+ ucb->index = l_port;
+ ucb->port.local_in_port = htons(l_port);
+ ucb->pmask.local_in_port = 0xffff;
+ ucb->port.remote_in_port = 0;
+ ucb->pmask.remote_in_port = 0;
+ goto out;
+
+err_out:
+ if (ucb != NULL) { rte_free(ucb); ucb = NULL; }
+ goto out;
+
+out:
+ rte_rwlock_write_unlock(&udp_ctx->rwlock);
+ return ucb;
+} \ No newline at end of file
diff --git a/stack/src/udp.c b/stack/src/udp.c
new file mode 100644
index 0000000..07c6a4b
--- /dev/null
+++ b/stack/src/udp.c
@@ -0,0 +1,92 @@
+
+#include <mr_rtdev.h>
+#include <mr_vnode.h>
+#include <sk_device.h>
+#include <sk_stack.h>
+#include <rte_udp.h>
+#include <mr_common.h>
+#include <rte_ip.h>
+#include <sk_ip.h>
+
+int protocol_serv_udp_entry(struct sk_dev_desc * dev_desc,
+ thread_id_t sid, struct rte_mbuf* mbufs_in[], int nr_mbufs_in)
+{
+ return 0;
+}
+
+int protocol_serv_udp_drain(struct sk_dev_desc * dev_desc,
+ thread_id_t sid, struct rte_mbuf * mbuf_out[], int nr_mbufs_max)
+{
+ int nr_drain = 0;
+ struct rtdev_desc * rtdev_desc = dev_desc->udp_device;
+ assert(dev_desc != NULL);
+
+ nr_drain += vnode_dequeue_burst(rtdev_desc->vnode_cons_ftx, &rtdev_desc->ops,
+ sid, (void **)&mbuf_out[nr_drain], nr_mbufs_max - nr_drain);
+
+ nr_drain += vnode_dequeue_burst(rtdev_desc->vnode_cons_tx, &rtdev_desc->ops,
+ sid, (void **)&mbuf_out[nr_drain], nr_mbufs_max - nr_drain);
+
+ assert(nr_mbufs_max >= nr_drain);
+ return nr_drain;
+}
+
+int sk_udp_segment_construct(struct sk_destinfo * destinfo, struct rte_mbuf * mbuf)
+{
+ struct udp_hdr * udp_hdr = (struct udp_hdr *)rte_pktmbuf_prepend(mbuf, sizeof(struct udp_hdr));
+ assert(udp_hdr != NULL);
+
+ unsigned int l4_len = rte_pktmbuf_pkt_len(mbuf);
+ udp_hdr->src_port = destinfo->s_trans_port;
+ udp_hdr->dst_port = destinfo->d_trans_port;
+ udp_hdr->dgram_len = htonl(l4_len);
+ udp_hdr->dgram_cksum = 0;
+
+ // Ӳ��У���Offload��־
+ mbuf->tx_offload = 0;
+ mbuf->l4_len = sizeof(struct udp_hdr);
+ mbuf->ol_flags |= PKT_TX_UDP_CKSUM;
+
+ // ����αͷ��У��ͣ�Ӳ��Offload��Ҫαͷ��У���
+ struct ipv4_psd_header {
+ uint32_t src_addr; /* IP address of source host. */
+ uint32_t dst_addr; /* IP address of destination host. */
+ uint8_t zero; /* zero. */
+ uint8_t proto; /* L4 protocol type. */
+ uint16_t len; /* L4 length. */
+ } psd_hdr;
+
+ psd_hdr.src_addr = destinfo->s_in_addr.s_addr;
+ psd_hdr.dst_addr = destinfo->d_in_addr.s_addr;
+ psd_hdr.proto = IPPROTO_UDP;
+ psd_hdr.len = htons(l4_len);
+ udp_hdr->dgram_cksum = rte_raw_cksum(&psd_hdr, sizeof(psd_hdr));
+ return 0;
+}
+
+int sk_udp_send_burst(struct sk_app_instance * app_instance, thread_id_t sid,
+ struct sk_destinfo * destinfo, struct rte_mbuf * mbuf[], unsigned int nr_mbuf,
+ unsigned char is_fast)
+{
+ struct sk_dev_desc * dev_desc = destinfo->d_dev_desc;
+ hash_t hash[MR_BURST_MAX];
+
+ assert(nr_mbuf <= MR_BURST_MAX);
+
+ for (int i = 0; i < nr_mbuf; i++)
+ {
+ sk_udp_segment_construct(destinfo, mbuf[i]);
+ sk_ip_packet_construct(app_instance, mbuf[i], destinfo, IPPROTO_UDP);
+ }
+
+ struct vnode_prod * prod;
+ if (is_fast) prod = dev_desc->udp_app_device->vnode_prod_ftx;
+ else prod = dev_desc->udp_app_device->vnode_prod_tx;
+
+ // TODO: ��ϣ�㷨�Ľ�
+ hash_t _hash = destinfo->s_trans_port ^ destinfo->d_trans_port;
+ for (int i = 0; i < nr_mbuf; i++) hash[i] = _hash;
+
+ return vnode_enqueue_burst_with_hash(prod, &dev_desc->udp_app_device->ops, sid,
+ (void **)mbuf, hash, nr_mbuf);
+} \ No newline at end of file
diff --git a/support/MESA_prof_load b/support/MESA_prof_load
new file mode 160000
+Subproject 6f08e0554cf82a2d22581729cbe0aa58fd83d46
diff --git a/support/MESA_prof_load/.gitignore b/support/MESA_prof_load/.gitignore
deleted file mode 100644
index 75fb413..0000000
--- a/support/MESA_prof_load/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-*.o
-*.ko
-*.swp
-*.tmp
-*.log
-tags
-.tags
-
diff --git a/support/MESA_prof_load/CMakeLists.txt b/support/MESA_prof_load/CMakeLists.txt
deleted file mode 100644
index d51d9cf..0000000
--- a/support/MESA_prof_load/CMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-cmake_minimum_required(VERSION 2.6)
-#project(MESA_prof_load)
-
-set(MESA_PROF_LOAD_MAJOR_VERSION 1)
-set(MESA_PROF_LOAD_MINOR_VERSION 0)
-set(MESA_PROF_LOAD_PATCH_VERSION 0)
-set(MESA_PROF_LOAD_VERSION ${MESA_PROF_LOAD_MAJOR_VERSION}.${MESA_PROF_LOAD_MINOR_VERSION}.${MESA_PROF_LOAD_PATCH_VERSION})
-
-message(STATUS "MESA Profile Loader, Version: ${MESA_PROF_LOAD_VERSION}")
-
-add_definitions(-fPIC)
-set(SRCLIST src/MESA_prof_load.c)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc/)
-
-# Static Library Output
-add_library(MESA_prof_load_static STATIC ${SRCLIST})
-set_target_properties(MESA_prof_load_static PROPERTIES OUTPUT_NAME MESA_prof_load)
-set_target_properties(MESA_prof_load_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
-target_include_directories(MESA_prof_load_static INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/inc/")
-
-# Shared Library Output
-add_library(MESA_prof_load_shared SHARED ${SRCLIST})
-set_target_properties(MESA_prof_load_shared PROPERTIES OUTPUT_NAME MESA_prof_load)
-set_target_properties(MESA_prof_load_shared PROPERTIES CLEAN_DIRECT_OUTPUT 1)
-set_target_properties(MESA_prof_load_shared PROPERTIES VERSION ${MESA_PROF_LOAD_MAJOR_VERSION}.${MESA_PROF_LOAD_MINOR_VERSION})
-set_target_properties(MESA_prof_load_shared PROPERTIES SOVERSION ${MESA_PROF_LOAD_MAJOR_VERSION})
-target_include_directories(MESA_prof_load_shared INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/inc/")
-
-
-# Demo Output
-set(DEMO_SRC_LIST demo/demo.c)
-add_executable(MESA_prof_load_demo EXCLUDE_FROM_ALL ${DEMO_SRC_LIST})
-add_dependencies(MESA_prof_load_demo MESA_prof_load_static MESA_prof_load_shared)
-target_link_libraries(MESA_prof_load_demo MESA_prof_load_static)
-
-# Export
-export(TARGETS MESA_prof_load_shared MESA_prof_load_static FILE mesa_prof_load-config.cmake) \ No newline at end of file
diff --git a/support/MESA_prof_load/Makefile b/support/MESA_prof_load/Makefile
deleted file mode 100644
index e7ac1c2..0000000
--- a/support/MESA_prof_load/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-#opt: OPTFLAGS = -O2
-#export OPTFLAGS
-
-.PHONY: all clean opt
-
-all:
- $(MAKE) -C src
- mkdir -p $(APP_ROOT)/lib
- install -D lib/* $(APP_ROOT)/lib/
-clean:
- $(MAKE) -C src
-opt:
- $(MAKE) all
diff --git a/support/MESA_prof_load/README b/support/MESA_prof_load/README
deleted file mode 100644
index 9db1906..0000000
--- a/support/MESA_prof_load/README
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *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
deleted file mode 100644
index 2df4458..0000000
--- a/support/MESA_prof_load/demo/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-#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
deleted file mode 100644
index cf6d895..0000000
--- a/support/MESA_prof_load/demo/config.ini
+++ /dev/null
@@ -1,11 +0,0 @@
-[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
deleted file mode 100644
index 4bebaad..0000000
--- a/support/MESA_prof_load/demo/demo.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#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
deleted file mode 100644
index 8d8c202..0000000
--- a/support/MESA_prof_load/inc/MESA_prof_load.h
+++ /dev/null
@@ -1,179 +0,0 @@
-#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/.gitignore b/support/MESA_prof_load/lib/.gitignore
deleted file mode 100644
index 75fb413..0000000
--- a/support/MESA_prof_load/lib/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-*.o
-*.ko
-*.swp
-*.tmp
-*.log
-tags
-.tags
-
diff --git a/support/MESA_prof_load/lib/libMESA_prof_load.a b/support/MESA_prof_load/lib/libMESA_prof_load.a
deleted file mode 100644
index 385e9f1..0000000
--- a/support/MESA_prof_load/lib/libMESA_prof_load.a
+++ /dev/null
Binary files differ
diff --git a/support/MESA_prof_load/lib/libMESA_prof_load.so b/support/MESA_prof_load/lib/libMESA_prof_load.so
deleted file mode 100644
index 51b7b3c..0000000
--- a/support/MESA_prof_load/lib/libMESA_prof_load.so
+++ /dev/null
Binary files differ
diff --git a/support/MESA_prof_load/src/MESA_prof_load.a b/support/MESA_prof_load/src/MESA_prof_load.a
deleted file mode 100644
index 8d77dc2..0000000
--- a/support/MESA_prof_load/src/MESA_prof_load.a
+++ /dev/null
Binary files differ
diff --git a/support/MESA_prof_load/src/MESA_prof_load.c b/support/MESA_prof_load/src/MESA_prof_load.c
deleted file mode 100644
index f316a03..0000000
--- a/support/MESA_prof_load/src/MESA_prof_load.c
+++ /dev/null
@@ -1,806 +0,0 @@
-// 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
deleted file mode 100644
index 89a9155..0000000
--- a/support/MESA_prof_load/src/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-#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/test/CMakeLists.txt b/test/CMakeLists.txt
index 03898c5..55df185 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -19,8 +19,8 @@ set(TEST_LINK_LIBRARIES ${DPDK_LIBRARY} gtest)
#target_link_libraries(TestHwInfo ${TEST_LINK_LIBRARIES} core)
# TestCase 3
-# add_executable(TestVNode TestVNode.cc Unittest.cc)
-# target_link_libraries(TestVNode ${TEST_LINK_LIBRARIES} core)
+add_executable(TestVNode TestVNode.cc Unittest.cc)
+target_link_libraries(TestVNode ${TEST_LINK_LIBRARIES} core)
# TestCase 4
# add_executable(TestMask TestMask.cc Unittest.cc)
@@ -30,5 +30,5 @@ set(TEST_LINK_LIBRARIES ${DPDK_LIBRARY} gtest)
# add_executable(TestVMan TestVMan.cc Unittest.cc)
# target_link_libraries(TestVMan ${TEST_LINK_LIBRARIES} core)
-# add_executable(TestNeigh TestStackNeigh.cc Unittest.cc)
-# target_link_libraries(TestNeigh ${TEST_LINK_LIBRARIES} stack) \ No newline at end of file
+add_executable(TestNeigh TestStackNeigh.cc Unittest.cc)
+target_link_libraries(TestNeigh ${TEST_LINK_LIBRARIES} stack) \ No newline at end of file
diff --git a/test/TestMrbuf.cc b/test/TestMrbuf.cc
index 1336b30..2616d94 100644
--- a/test/TestMrbuf.cc
+++ b/test/TestMrbuf.cc
@@ -7,19 +7,19 @@ static struct rte_mempool * g_pktmbuf_pool = NULL;
static void marsio_mbuf_test(void)
{
#define BATCH_TEST_NUM (32)
- marsio_buf_t *mbuf, *mnext;
+ marsio_buff_t *mbuf, *mnext;
struct rte_mbuf *rbuf;
char *data;
char *pri_data = (char *)"test ctrlzone";
uint32_t pkt_len;
int ctrl_id = -1, i;
- marsio_buf_t *batch_mbuf[BATCH_TEST_NUM];
+ marsio_buff_t *batch_mbuf[BATCH_TEST_NUM];
ctrl_id = marsio_buf_ctrlzone_alloc_id();
while (1) {
printf("ctrl_id = %u\n", ctrl_id);
- mbuf = marsio_buf_alloc();
+ mbuf = marsio_buff_alloc();
rbuf = (struct rte_mbuf *)mbuf;
marsio_buf_batch_alloc(batch_mbuf, BATCH_TEST_NUM);
@@ -28,25 +28,25 @@ static void marsio_mbuf_test(void)
printf("tailroom = %u\n", marsio_buf_tailroom(mbuf));
printf("bufaddr-buf = %ld\n", (char *)rbuf->buf_addr - (char *)rbuf);
- data = marsio_buf_mtod(mbuf);
- pkt_len = marsio_buf_pkt_len(mbuf);
+ data = marsio_buff_mtod(mbuf);
+ pkt_len = marsio_buff_pkt_len(mbuf);
printf("init pkt_len = %u\n", pkt_len);
- marsio_buf_prepend(mbuf, 20);
- pkt_len = marsio_buf_pkt_len(mbuf);
+ marsio_buff_prepend(mbuf, 20);
+ pkt_len = marsio_buff_pkt_len(mbuf);
printf("after prepend, pkt_len = %u\n", pkt_len);
marsio_buf_append(mbuf, 100);
- pkt_len = marsio_buf_pkt_len(mbuf);
+ pkt_len = marsio_buff_pkt_len(mbuf);
printf("after append, pkt_len = %u\n", pkt_len);
marsio_buf_trim(mbuf, 60);
- pkt_len = marsio_buf_pkt_len(mbuf);
+ pkt_len = marsio_buff_pkt_len(mbuf);
printf("after trim, pkt_len = %u\n", pkt_len);
printf("tailroom = %u\n", marsio_buf_tailroom(mbuf));
- mnext = marsio_buf_alloc();
+ mnext = marsio_buff_alloc();
marsio_buf_append_pkt(mbuf, mnext);
printf("next is :%p\n", marsio_buf_get_nextpkt(mbuf));
@@ -70,11 +70,11 @@ static void marsio_mbuf_test(void)
#endif
marsio_buf_batch_free(batch_mbuf, BATCH_TEST_NUM);
- marsio_buf_free(mnext);
+ marsio_buff_free(mnext);
marsio_buf_dup(mbuf);
- marsio_buf_free(mbuf);
- marsio_buf_free(mbuf);
+ marsio_buff_free(mbuf);
+ marsio_buff_free(mbuf);
sleep(1);
printf("\n ---------------------------------------------------- \n");
diff --git a/test/TestStackNeigh.cc b/test/TestStackNeigh.cc
index 36fab6d..43bd9ae 100644
--- a/test/TestStackNeigh.cc
+++ b/test/TestStackNeigh.cc
@@ -1,30 +1,107 @@
#include <gtest/gtest.h>
#include <sk_device.h>
-#include <sk_neigh.h>
#include <netinet/in.h>
+#include <sk_neigh.h>
+#include <arpa/inet.h>
class TCStackNeigh : public ::testing::Test
{
protected:
- struct sk_neigh_table neigh_tbl_;
- struct sk_dev_desc neigh_dev_desc_;
+ struct neighbour_manager nbl_object_;
+ struct sk_dev_info dev_info_;
virtual void SetUp()
{
- int ret = neigh_tbl_init(&neigh_tbl_, "TestNeigh", 10000);
- neigh_dev_desc_.dev_info = new sk_dev_info;
+ int ret = neighbour_mamanger_init(&nbl_object_, "TestNeighbour",
+ 1024, 8, 0);
ASSERT_EQ(ret, 0);
}
virtual void TearDown()
{
+ int ret = neighbour_mamanger_deinit(&nbl_object_);
+ ASSERT_EQ(ret, 0);
}
};
-TEST_F(TCStackNeigh, TestNeighCreate)
+TEST_F(TCStackNeigh, CreateAndQuery)
{
+ int ret = 0;
struct in_addr _in_addr;
- _in_addr.s_addr = 1000000;
- neigh_create(&neigh_tbl_, _in_addr, &neigh_dev_desc_);
+ inet_pton(AF_INET, "192.168.11.101", &_in_addr);
+ struct ether_addr _ether_addr = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+ ret = neigh_create_or_update(&nbl_object_,
+ _in_addr, &_ether_addr, &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ struct ether_addr _ether_addr_query;
+ struct sk_dev_info * _dev_info_query;
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query,
+ &_dev_info_query);
+
+ ASSERT_EQ(ret, 0);
+ EXPECT_EQ(is_same_ether_addr(&_ether_addr_query, &_ether_addr), 1);
+ EXPECT_EQ(_dev_info_query, &dev_info_);
+}
+
+TEST_F(TCStackNeigh, CreateAndUpdate)
+{
+ int ret = 0;
+ struct in_addr _in_addr;
+ inet_pton(AF_INET, "192.168.11.101", &_in_addr);
+ struct ether_addr _ether_addr = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+ ret = neigh_create_or_update(&nbl_object_,
+ _in_addr, &_ether_addr, &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ struct ether_addr _ether_addr_query;
+ struct sk_dev_info * _dev_info_query;
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query,
+ &_dev_info_query);
+
+ ASSERT_EQ(ret, 0);
+ EXPECT_EQ(is_same_ether_addr(&_ether_addr_query, &_ether_addr), 1);
+ EXPECT_EQ(_dev_info_query, &dev_info_);
+
+ struct ether_addr _ether_addr_update = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+ ret = neigh_create_or_update(&nbl_object_, _in_addr, &_ether_addr_update,
+ &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query, &_dev_info_query);
+ ASSERT_EQ(ret, 0);
+ EXPECT_EQ(is_same_ether_addr(&_ether_addr_query, &_ether_addr_update), 1);
+ EXPECT_EQ(_dev_info_query, &dev_info_);
+}
+
+TEST_F(TCStackNeigh, CreateAndDelete)
+{
+ int ret = 0;
+ struct in_addr _in_addr;
+ inet_pton(AF_INET, "192.168.11.101", &_in_addr);
+ struct ether_addr _ether_addr = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+ ret = neigh_create_or_update(&nbl_object_,
+ _in_addr, &_ether_addr, &dev_info_, 1);
+
+ ASSERT_EQ(ret, 0);
+
+ ret = neigh_delete(&nbl_object_, _in_addr);
+ ASSERT_EQ(ret, 0);
+
+ struct ether_addr _ether_addr_query;
+ struct sk_dev_info * _dev_info_query;
+
+ ret = neigh_query(&nbl_object_, _in_addr, &_ether_addr_query,
+ &_dev_info_query);
+
+ ASSERT_LE(ret, 0);
} \ No newline at end of file
diff --git a/test/TestVMan.cc b/test/TestVMan.cc
index ca8ed11..3e30bad 100644
--- a/test/TestVMan.cc
+++ b/test/TestVMan.cc
@@ -1,59 +1,59 @@
-
-/* \brief ����ڵ��������Ԫ���Դ���
- * \author Qiuwen Lu<[email protected]>
- * \date 2016-09-02
- */
-
-#include <gtest/gtest.h>
-#include <mr_ctx.h>
-#include <mr_common.h>
-#include <mr_vman.h>
-
-extern struct mr_module module_desc_vnodeman;
-
-class TestCaseVNodeMan : public ::testing::Test
-{
-protected:
-
- TestCaseVNodeMan()
- {
- }
-
- ~TestCaseVNodeMan()
- {
- }
-
- static void SetUpTestCase()
- {
- mr_global_cfg_init();
- mr_global_ctx_init();
-
+
+/* \brief ����ڵ��������Ԫ���Դ���
+ * \author Qiuwen Lu<[email protected]>
+ * \date 2016-09-02
+ */
+
+#include <gtest/gtest.h>
+#include <mr_ctx.h>
+#include <mr_common.h>
+#include <mr_vman.h>
+
+extern struct mr_module module_desc_vnodeman;
+
+class TestCaseVNodeMan : public ::testing::Test
+{
+protected:
+
+ TestCaseVNodeMan()
+ {
+ }
+
+ ~TestCaseVNodeMan()
+ {
+ }
+
+ static void SetUpTestCase()
+ {
+ mr_global_cfg_init();
+ mr_global_ctx_init();
+
struct mr_global_ctx * g_ctx = mr_global_ctx_get();
- struct mr_config * g_cfg = mr_global_config_get();
-
- int ret = module_desc_vnodeman.preinit(
- &module_desc_vnodeman, g_cfg, g_ctx);
- ASSERT_EQ(ret, 0);
- }
-};
-
-TEST_F(TestCaseVNodeMan, TestRegisterAndAttach)
-{
- int ret = 0;
- ret = mr_vnodeman_create("TN", 1024, 128, 0);
- ASSERT_EQ(ret, 0);
- ret = mr_vnodeman_register_consumer("TN", "TNS",4);
- ASSERT_EQ(ret, 0);
- ret = mr_vnodeman_register_producer("TN", "TNP", 4);
- ASSERT_EQ(ret, 0);
-
- struct vnodeman_attach_desc * cons_desc[4];
- struct vnodeman_attach_desc * prod_desc[4];
- for (int i = 0; i < 4; i++)
- {
- cons_desc[i] = mr_vnodeman_consumer_attach("TN", "TNS");
- ASSERT_TRUE(cons_desc[i] != NULL);
- EXPECT_EQ(cons_desc[i]->desc_type, VNODEMAN_ATTACH_CONSUMER);
- EXPECT_EQ(cons_desc[i]->queue_id, i);
- }
+ struct mr_config * g_cfg = mr_global_config_get();
+
+ int ret = module_desc_vnodeman.preinit(
+ &module_desc_vnodeman, g_cfg, g_ctx);
+ ASSERT_EQ(ret, 0);
+ }
+};
+
+TEST_F(TestCaseVNodeMan, TestRegisterAndAttach)
+{
+ int ret = 0;
+ ret = mr_vnodeman_create("TN", 1024, 128, 0);
+ ASSERT_EQ(ret, 0);
+ ret = mr_vnodeman_register_consumer("TN", "TNS",4);
+ ASSERT_EQ(ret, 0);
+ ret = mr_vnodeman_register_producer("TN", "TNP", 4);
+ ASSERT_EQ(ret, 0);
+
+ struct vnodeman_attach_desc * cons_desc[4];
+ struct vnodeman_attach_desc * prod_desc[4];
+ for (int i = 0; i < 4; i++)
+ {
+ cons_desc[i] = mr_vnodeman_consumer_attach("TN", "TNS");
+ ASSERT_TRUE(cons_desc[i] != NULL);
+ EXPECT_EQ(cons_desc[i]->desc_type, VNODEMAN_ATTACH_CONSUMER);
+ EXPECT_EQ(cons_desc[i]->queue_id, i);
+ }
} \ No newline at end of file
diff --git a/test/TestVNode.cc b/test/TestVNode.cc
index 33d7570..325da58 100644
--- a/test/TestVNode.cc
+++ b/test/TestVNode.cc
@@ -50,7 +50,7 @@ protected:
/// 测试用例,测试VNode节点的创建和初始化
TEST_F(TestCaseVNodeBase, TestVNodeCreate)
{
- std::string strVNodeSym = "TestVNodeCreate";
+ std::string strVNodeSym = "TVNCreate";
struct vnode* node = vnode_create(strVNodeSym.c_str(), vnode_ops_, 512, 8);
ASSERT_TRUE(node != NULL);
@@ -62,7 +62,7 @@ TEST_F(TestCaseVNodeBase, TestVNodeCreate)
/// 测试用例,测试VNode的销毁过程
TEST_F(TestCaseVNodeBase, TestVNodeDelete)
{
- std::string strVNodeSym = "TestVNodeDelete";
+ std::string strVNodeSym = "TVNDelete";
struct vnode* node = vnode_create(strVNodeSym.c_str(), vnode_ops_, 512, 8);
ASSERT_TRUE(node != NULL);
EXPECT_STREQ(node->symbol, strVNodeSym.c_str());
@@ -85,7 +85,7 @@ protected:
virtual void SetUp()
{
- node_ = vnode_create("TestVNodeOps", vnode_ops_, 512, 8);
+ node_ = vnode_create("TVNOps", vnode_ops_, 512, 8);
ASSERT_TRUE(node_ != NULL);
}
@@ -100,7 +100,7 @@ protected:
TEST_F(TestCaseVNodeOps, TestVNodeCreateDeleteProd)
{
struct vnode_prod* prod;
- std::string strProdSym = "VNodeProd1";
+ std::string strProdSym = "VProd1";
prod = vnode_create_prod(node_, vnode_ops_, strProdSym.c_str(), 10);
ASSERT_TRUE(prod != NULL);
@@ -112,7 +112,7 @@ TEST_F(TestCaseVNodeOps, TestVNodeCreateDeleteProd)
TEST_F(TestCaseVNodeOps, TestVNodeCreateDeleteCons)
{
struct vnode_cons* cons;
- std::string strConsSym = "VNodeCons2";
+ std::string strConsSym = "VCons2";
cons = vnode_create_cons(node_, vnode_ops_, strConsSym.c_str(), 10);
ASSERT_TRUE(cons != NULL);
@@ -124,11 +124,11 @@ TEST_F(TestCaseVNodeOps, TestVNodeCreateDeleteCons)
TEST_F(TestCaseVNodeOps, TestVNodeProdConsCreate)
{
struct vnode_prod* prod;
- std::string strProdSym = "VNodeProd3";
+ std::string strProdSym = "VProd3";
prod = vnode_create_prod(node_, vnode_ops_, strProdSym.c_str(), 10);
struct vnode_cons* cons;
- std::string strConsSym = "VNodeCons4";
+ std::string strConsSym = "VCons4";
cons = vnode_create_cons(node_, vnode_ops_, strConsSym.c_str(), 10);
ASSERT_TRUE(prod != NULL);
@@ -143,11 +143,11 @@ TEST_F(TestCaseVNodeOps, TestVNodeProdConsCreate)
TEST_F(TestCaseVNodeOps, TestVNodeProdConsLookup)
{
struct vnode_prod* prod;
- std::string strProdSym = "VNodeProd5";
+ std::string strProdSym = "VProd5";
prod = vnode_create_prod(node_, vnode_ops_, strProdSym.c_str(), 10);
struct vnode_cons* cons;
- std::string strConsSym = "VNodeCons6";
+ std::string strConsSym = "VCons6";
cons = vnode_create_cons(node_, vnode_ops_, strConsSym.c_str(), 10);
struct vnode_prod* prod_lookup;
@@ -190,7 +190,7 @@ protected:
static void SetUpTestCase()
{
TestCaseVNodeOps::SetUpTestCase();
- pool_ = rte_pktmbuf_pool_create("TestCaseVNodeDataOpsPool", 8192, 512, 0, 512, SOCKET_ID_ANY);
+ pool_ = rte_pktmbuf_pool_create("TCVNDataOpsPool", 8192, 512, 0, 512, SOCKET_ID_ANY);
ASSERT_TRUE(pool_ != NULL);
}
@@ -202,7 +202,7 @@ protected:
virtual void VNodeCreate()
{
- node_ = vnode_create("TestVNodeOps", vnode_ops_, 512, 0);
+ node_ = vnode_create("TVNOps", vnode_ops_, 512, 0);
ASSERT_TRUE(node_ != NULL);
}
@@ -290,7 +290,7 @@ protected:
static void SetUpTestCase()
{
- pool_ = rte_pktmbuf_pool_create("TestCaseVNodeDataMultiQPool", 8192, 512, 0, 512, SOCKET_ID_ANY);
+ pool_ = rte_pktmbuf_pool_create("TCVNDataMultiQPool", 8192, 512, 0, 512, SOCKET_ID_ANY);
ASSERT_TRUE(pool_ != NULL);
}
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 3afd427..b64a3fe 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -8,24 +8,9 @@ include_directories(${DPDK_INCLUDE_DIR})
include_directories(include)
add_definitions(${DPDK_C_PREDEFINED})
-# add_executable(dev_stat stat/dev_stat_log.c)
-# target_link_libraries(dev_stat ${DPDK_LIBRARY} MESA_prof_load_static MESA_fs2)
-# target_link_libraries(dev_stat rt pthread dl core)
-
-add_executable(zcp_app_stat stat/libstat.c stat/app_stat.c)
-target_link_libraries(zcp_app_stat ${DPDK_LIBRARY} MESA_prof_load_static MESA_fs2)
-target_link_libraries(zcp_app_stat rt pthread dl core)
-
-add_executable(zcp_event_stat stat/libstat.c stat/event_stat.c)
-target_link_libraries(zcp_event_stat ${DPDK_LIBRARY} MESA_prof_load_static MESA_fs2)
-target_link_libraries(zcp_event_stat rt pthread dl core)
-
add_executable(zcp_rx_tcpdump tcpdump/rx_tcpdump.c)
target_include_directories(zcp_rx_tcpdump PRIVATE ${PCAP_INCLUDE_DIR})
target_link_libraries(zcp_rx_tcpdump pag ${PCAP_LIBRARY})
-
-install(TARGETS zcp_app_stat RUNTIME DESTINATION bin COMPONENT Program)
-install(TARGETS zcp_event_stat RUNTIME DESTINATION bin COMPONENT Program)
install(TARGETS zcp_rx_tcpdump RUNTIME DESTINATION bin COMPONENT Program)
#install(FILES script/mrstart DESTINATION bin PERMISSIONS WORLD_EXECUTE COMPONENT Program)
diff --git a/tools/stat/dev_stat.c b/tools/stat/dev_stat.c
index b9ff0b1..247a68e 100644
--- a/tools/stat/dev_stat.c
+++ b/tools/stat/dev_stat.c
@@ -147,7 +147,7 @@ void dev_stat_output(struct dev_stat_statics* g_dev_stat_statics,mr_dev_t * devi
}
-static void mrlib_stage_eal_init()
+static void mrapp_eal_init()
{
char * eal_argv[8];
unsigned int eal_argc = 0;
@@ -161,7 +161,7 @@ static void mrlib_stage_eal_init()
MR_CHECK(ret >= 0, "Cannot init EAL Enviorment, Failed");
return;
}
-static void mrlib_slave_log_ready(FILE * logstream)
+static void mrapp_slave_log_ready(FILE * logstream)
{
if (logstream == NULL) logstream = stderr;
rte_openlog_stream(stderr);
@@ -170,8 +170,8 @@ static void mrlib_slave_log_ready(FILE * logstream)
int mr_lib_init()
{
int ret = 0;
- mrlib_stage_eal_init();
- mrlib_slave_log_ready(NULL);
+ mrapp_eal_init();
+ mrapp_slave_log_ready(NULL);
mr_global_ctx_slave_init();
mr_global_cfg_slave_init();
@@ -184,7 +184,7 @@ int main(int argc,char *argv[])
{
mr_lib_init();
mr_dev_t * device_list[MR_DEVICE_MAX];
- int device_list_count=mr_device_list(device_list,MR_DEVICE_MAX,0);
+ int device_list_count=mr_device_list(, device_list,MR_DEVICE_MAX), 0;
struct dev_stat_statics *g_dev_stat_statics=dev_stat_init(device_list,device_list_count);
while(1)
{