diff options
| author | 陆秋文 <[email protected]> | 2016-12-07 19:28:57 +0800 |
|---|---|---|
| committer | 陆秋文 <[email protected]> | 2016-12-07 19:28:57 +0800 |
| commit | a924438a3e3d1926e03a46edc2f04d857244adf6 (patch) | |
| tree | 089b76bf2fcd1199638c888aecfa96a8b9fab3f8 | |
| parent | e8e0c94bc5e52eefb5f71775986e89e4d775faf7 (diff) | |
| parent | e7312311de94cc2c99ea44631d73dcd87ba1adbf (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
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(¶m->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, ð_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, ðer_hdr->s_addr); + ether_addr_copy(&arp_header->arp_data.arp_sha, ðer_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(ðer_hdr->s_addr, &reply_arp_hdr->arp_data.arp_sha); + ether_addr_copy(ðer_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, ðer_hdr->s_addr); + ether_addr_copy(dst_hwaddr, ðer_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, ðer_hdr->s_addr); + ether_addr_copy(&destinfo->d_eth_addr, ðer_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, ðer_hdr->s_addr); - ether_addr_copy(dst_addr, ðer_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 Binary files differdeleted file mode 100644 index 385e9f1..0000000 --- a/support/MESA_prof_load/lib/libMESA_prof_load.a +++ /dev/null diff --git a/support/MESA_prof_load/lib/libMESA_prof_load.so b/support/MESA_prof_load/lib/libMESA_prof_load.so Binary files differdeleted file mode 100644 index 51b7b3c..0000000 --- a/support/MESA_prof_load/lib/libMESA_prof_load.so +++ /dev/null diff --git a/support/MESA_prof_load/src/MESA_prof_load.a b/support/MESA_prof_load/src/MESA_prof_load.a Binary files differdeleted file mode 100644 index 8d77dc2..0000000 --- a/support/MESA_prof_load/src/MESA_prof_load.a +++ /dev/null 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) { |
