diff options
128 files changed, 30598 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..590a5a5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,145 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11) +PROJECT(nStack) +SET(CMAKE_C_COMPILER "gcc") +SET(EXECUTABLE_PATH ${CMAKE_CURRENT_LIST_DIR}/release/bin) +SET(LIB_PATH_STATIC ${PROJECT_BINARY_DIR}) +SET(LIB_PATH_SHARED ${CMAKE_CURRENT_LIST_DIR}/release/lib64) +SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIB_PATH_STATIC}) +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_PATH}) +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIB_PATH_SHARED}) +SET(DMM_DPDK_INSTALL_DIR "" CACHE STRING "to get the dpdk install path by cmd") + +MESSAGE(STATUS "Top dir is: " ${CMAKE_CURRENT_LIST_DIR}) +MESSAGE(STATUS "Static library dir: " ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) +MESSAGE(STATUS "Executable binary dir: " ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) +MESSAGE(STATUS "Shared library dir: " ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + + +add_custom_target(clean-cmake-files + COMMAND ${CMAKE_COMMAND} -P clean-all.cmake +) + +option(WITH_SECUREC_LIB "Option description" OFF) +option(WITH_HAL_LIB "Option description" OFF) + +if(WITH_SECUREC_LIB) + add_definitions(-DSECUREC_LIB) +endif() + +if(WITH_HAL_LIB) + add_definitions(-DHAL_LIB) +endif() + +SET(post_compile "${PROJECT_BINARY_DIR}/post_compile.sh") +FILE(WRITE ${post_compile} "#!/bin/bash\n") +if(WITH_HAL_LIB) +else() +FILE(APPEND ${post_compile} +" + +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/nSocket/include/nstack_dmm_api.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/adapt/nstack_dmm_adpt.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/adapt/nstack_share_res.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/adapt/nstack_rd_mng.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/nSocket/include/declare_syscalls.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/framework/include/* ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -rf ${CMAKE_CURRENT_LIST_DIR}/src/framework/common/base/include/*.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -rf ${CMAKE_CURRENT_LIST_DIR}/src/framework/common/base/include/common/* ${CMAKE_CURRENT_LIST_DIR}/release/include/ + +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/framework/common/include/* ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/framework/ipc/mgr_com/mgr_com.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/src/framework/hal/hal.h ${CMAKE_CURRENT_LIST_DIR}/release/include/ +cp -f ${CMAKE_CURRENT_LIST_DIR}/build/libdmm_api.a ${CMAKE_CURRENT_LIST_DIR}/release/lib64/ +echo post compile process success. +" +) +endif() + +SET(clean_compile "${PROJECT_BINARY_DIR}/clean_compile.sh") +FILE(WRITE ${clean_compile} "#!/bin/bash\n") +FILE(APPEND ${clean_compile} +" + +rm -rf ${CMAKE_CURRENT_LIST_DIR}/release/include/*.h +rm -rf ${CMAKE_CURRENT_LIST_DIR}/release/include/generic +rm -rf ${CMAKE_CURRENT_LIST_DIR}/release/lib64/libdmm_api.a + +echo post clean process success. +" +) + +ADD_CUSTOM_TARGET(DPDK ALL COMMAND sh post_compile.sh) +ADD_DEPENDENCIES(DPDK dmm_api) + +ADD_CUSTOM_TARGET(clean-all + COMMAND ${CMAKE_BUILD_TOOL} clean + COMMAND sh clean_compile.sh) + +SET(JSON_C_URL https://github.com/json-c/json-c/archive/json-c-0.12.1-20160607.tar.gz) +SET(JSON_C_DOWNLOAD_DIR ${CMAKE_CURRENT_LIST_DIR}/thirdparty/json/) +SET(JSON_C_SRC ${CMAKE_CURRENT_LIST_DIR}/thirdparty/json/json-c-0.12.1) +if(EXISTS "${JSON_C_DOWNLOAD_DIR}/json-c-0.12.1.tar.gz") + SET(JSON_DOWNLOAD_CMD tar -xvf ${JSON_C_DOWNLOAD_DIR}/json-c-0.12.1.tar.gz -C ${JSON_C_DOWNLOAD_DIR}/json-c-0.12.1 --strip-components 1) +else() + SET(JSON_DOWNLOAD_CMD wget --no-check-certificate -O json-c-0.12.1.tar.gz ${JSON_C_URL} && tar -xvf ${JSON_C_DOWNLOAD_DIR}/json-c-0.12.1.tar.gz -C ${JSON_C_DOWNLOAD_DIR}/json-c-0.12.1 --strip-components 1) +endif() +INCLUDE(ExternalProject) +ExternalProject_Add( + JSON + DOWNLOAD_DIR ${JSON_C_DOWNLOAD_DIR} + DOWNLOAD_COMMAND ${JSON_DOWNLOAD_CMD} + BUILD_IN_SOURCE 1 + SOURCE_DIR ${JSON_C_SRC} + CONFIGURE_COMMAND sh autogen.sh COMMAND sh ./configure --enable-static --with-pic + BUILD_COMMAND make -j 8 + INSTALL_COMMAND cp -f .libs/libjson-c.a ${LIB_PATH_STATIC}/ +) + +SET(SECUREC_SRC ${CMAKE_CURRENT_LIST_DIR}/thirdparty/SecureC/src) +SET(SECUREC_SRC_H ${CMAKE_CURRENT_LIST_DIR}/thirdparty/SecureC/include) + +if(WITH_SECUREC_LIB) +INCLUDE(ExternalProject) +ExternalProject_Add( + SECUREC + SOURCE_DIR ${SECUREC_SRC} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND COMMAND make -j 8 + INSTALL_COMMAND cp -f ${SECUREC_SRC}/../lib/libsecurec.so ${LIB_PATH_SHARED}/ +) +endif() + +SET(GLOG_SRC ${CMAKE_CURRENT_LIST_DIR}/thirdparty/glog/glog-0.3.4) +INCLUDE(ExternalProject) +ExternalProject_Add( + GLOG + SOURCE_DIR ${GLOG_SRC} + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND autoreconf COMMAND sh configure CFLAGS=-fPIC CXXFLAGS=-fPIC + BUILD_COMMAND COMMAND make -j 8 + INSTALL_COMMAND cp -f ${GLOG_SRC}/.libs/libglog.a ${LIB_PATH_STATIC}/ +) + +ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(app_example) + +#ADD_SUBDIRECTORY(thirdparty/rsrdma) +ADD_SUBDIRECTORY(thirdparty/apps) @@ -0,0 +1,68 @@ +一、DMM compile + +1.compile all module: +cd build +cmake -D DMM_DPDK_INSTALL_DIR=$DPDK_INSTALL_PATH .. +make -j 8 + +Note: DPDK_INSTALL_PATH - the path in which DPDK has been installed + +libnStackAdpt.so, libnStackAPI.so, libsecurec.so will be copyed to release\lib64 folder. +declare_syscalls.h, nsocket_dmm_api.h will be copyed to release\include folder + +configure files : + release\configure + module_config.json is the stack module config file. + rd_config.json is the rd config file. + the content of these two configure files just a simple. + +2. run DMM +nStack DMM is just a library linked by APP, no need run any other. + +for example: + gcc -g -o sendmsg sendmsg.c -L./DMM/release/lib64 -lnStackAPI + sendmsg.c is a APP that create a socket and connect to the service. + run app:./sendmsg 192.168.1.10 1024 1 + + module_config.json rd_config.json should be put together with sendmsg + + module_config.json for example: + { + "default_stack_name": "kernel", /*when rd can't not be find maybe choose the defualt one*/ + "module_list": [ + { + "stack_name": "kernel", + "function_name": "kernel_stack_register", + "libname": "", /*library name, if loadtype is static, this maybe null, else must give a library name*/ + "loadtype": "static", /*library load type: static or dynamic*/ + "deploytype": "1", + "maxfd": "1024", + "minfd": "0", + "priorty": "1", + "stackid": "0", /*must be ordered and not be repeated*/ + } + ] + } + + rd_config.json for example: + { + "ip_route": [ + { + "subnet": "192.165.1.1/16", + "type": "nstack-kernel", /*output interface type, nstack-kernel: indicate that this ip should go through linux protocol, nstack-dpdk: go through stackx protocol*/ + }, + { + "subnet": "192.167.1.1/16", + "type": "nstack-kernel", + } + ] + "prot_route": [ + { + "proto_type": "11", + "type": "nstack-kernel", + }, + } + + + +
\ No newline at end of file diff --git a/app_example/CMakeLists.txt b/app_example/CMakeLists.txt new file mode 100644 index 0000000..0c88a4f --- /dev/null +++ b/app_example/CMakeLists.txt @@ -0,0 +1,18 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +ADD_SUBDIRECTORY(perf-test) + diff --git a/app_example/perf-test/CMakeLists.txt b/app_example/perf-test/CMakeLists.txt new file mode 100644 index 0000000..a22f071 --- /dev/null +++ b/app_example/perf-test/CMakeLists.txt @@ -0,0 +1,39 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) + +ADD_EXECUTABLE(vc_epoll multi_tcp_epoll_app_Cli.c) +ADD_DEPENDENCIES(vc_epoll nStackAPI) +TARGET_LINK_LIBRARIES(vc_epoll libnStackAPI.so -Wl,-rpath=. -lpthread -lrt) + +ADD_EXECUTABLE(vs_epoll multi_tcp_epoll_app_Ser.c) +ADD_DEPENDENCIES(vs_epoll nStackAPI) +TARGET_LINK_LIBRARIES(vs_epoll libnStackAPI.so -Wl,-rpath=. -lpthread -lrt) + +ADD_EXECUTABLE(kc_epoll multi_tcp_epoll_app_Cli.c) +TARGET_LINK_LIBRARIES(kc_epoll pthread) + +ADD_EXECUTABLE(ks_epoll multi_tcp_epoll_app_Ser.c) +TARGET_LINK_LIBRARIES(ks_epoll pthread) + +#ADD_EXECUTABLE(vs_no_epoll multi_tcp_no_epoll_Ser.c) +#ADD_DEPENDENCIES(vs_no_epoll nStackAPI) +#TARGET_LINK_LIBRARIES(vs_no_epoll libnStackAPI.so -Wl,-rpath=. -lpthread -lrt) + +#ADD_EXECUTABLE(ks_no_epoll multi_tcp_no_epoll_Ser.c) +#TARGET_LINK_LIBRARIES(ks_no_epoll pthread) + diff --git a/app_example/perf-test/multi_tcp_epoll_app_Cli.c b/app_example/perf-test/multi_tcp_epoll_app_Cli.c new file mode 100644 index 0000000..c09d422 --- /dev/null +++ b/app_example/perf-test/multi_tcp_epoll_app_Cli.c @@ -0,0 +1,628 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define _GNU_SOURCE +#include <sys/socket.h> +#include <fcntl.h> +#include <memory.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <time.h> +#include <linux/tcp.h> +#include <sched.h> +#include <pthread.h> +#include <arpa/inet.h> +#include <sys/epoll.h> +#include <errno.h> + +#define _BIND bind +#define _LISTEN listen +#define _SOCKET socket +#define _ACCEPT accept +#define _SEND send +#define _RECV recv +#define _CLOSE close +#define _CONNECT connect +#define _PROTOCOL IPPROTO_TCP + +#define MAX_TEST_TIME 1000 +#define MSG_LENGTH 256 +#define CORE_NUM 8 +#define START_CPU_ID 2 +#define MAX_CONN_LIMIT 256 +#define MAX_PORT_NUM 65535 +//1:A-B ;0:A-B-A +#define SEND_RECV_MODE 1 +#define MAX_EVENTS 1000 +#define Default_PortID 12345 +#define Default_SleepCnt 10000 +#define Default_SleepTime 1000000 +#define Flag_Print 1 +#define Fd_Number 1 + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +static struct sockaddr_in g_recv; + +int times = MAX_TEST_TIME; +int msg_length = MSG_LENGTH; +int coreNum = CORE_NUM; +int startCPUId = START_CPU_ID; +int connectNum = MAX_CONN_LIMIT; +int msgMode = SEND_RECV_MODE; +int sleepCnt = Default_SleepCnt; +int sleepTime = Default_SleepTime; //us +int fdNumber = Fd_Number; +int flagPrint = Flag_Print; +int unitPrint = 0; +int waitTime = 0; + +int srcPort = Default_PortID; +int destPort = 0; +int recvPort = 0; +char sendarr[256] = ""; +char recvarr[256] = ""; +char destarr[256] = ""; + +static void +setArgsDefault () +{ + + memset (&g_dest, 0, sizeof (g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr ("127.0.0.1"); + g_dest.sin_port = htons (12345); + bzero (&(g_dest.sin_zero), 8); + + memset (&g_src, 0, sizeof (g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr ("0.0.0.0"); + g_src.sin_port = htons (7895); + bzero (&(g_src.sin_zero), 8); + + memset (&g_recv, 0, sizeof (g_recv)); + g_recv.sin_family = AF_INET; + g_recv.sin_addr.s_addr = inet_addr ("0.0.0.0"); + g_recv.sin_port = htons (7895); + bzero (&(g_recv.sin_zero), 8); + +} + +static int +process_arg (int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; + int rw_mark = 0; + + if (argc < 4) + { + printf + ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); + printf + ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); + return 0; + } + while ((opt = getopt (argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + destPort = atoi (optarg); + g_dest.sin_port = htons (atoi (optarg)); + break; + case 'd': + stpcpy (destarr, optarg); + g_dest.sin_addr.s_addr = inet_addr (optarg); + break; + case 's': + stpcpy (sendarr, optarg); + g_src.sin_addr.s_addr = inet_addr (optarg); + g_recv.sin_addr.s_addr = inet_addr (optarg); + break; + case 'a': + //g_src.sin_port = htons(atoi(optarg)); + srcPort = atoi (optarg); + break; + case 'l': + msg_length = atoi (optarg); + break; + case 't': + times = atoi (optarg); + break; + case 'e': + sleepCnt = atoi (optarg); + break; + case 'i': + sleepTime = atoi (optarg); + break; + case 'f': + fdNumber = atoi (optarg); + break; + case 'r': + recvPort = atoi (optarg); + g_recv.sin_port = htons (atoi (optarg)); + break; + case 'n': + connectNum = atoi (optarg); + break; + case 'w': + waitTime = atoi (optarg); + break; + case 'u': + unitPrint = atoi (optarg); + break; + case 'x': + flagPrint = atoi (optarg); + break; + + } + } + return 1; +} + +void +process_client (void) +{ + int sendLen = 0; + int i = 0, t = 0, p = 0, optval = 0, ret = 0; + char send_buf[1000] = ""; + char recv_buf[1000] = ""; + int c_socketfd[100] = { 0 }; + int errbind[1000] = { 0 }; + int errconn[1000] = { 0 }; + + int send_count[1000] = { 0 }; + int pps = 0; + long pps_time = 0; + + struct timespec startTime, endTime; + struct timespec countStart; + struct timespec countEnd; + memset (&countStart, 0, sizeof (countStart)); + memset (&countEnd, 0, sizeof (countEnd)); + + for (i = 0; i < fdNumber; i++) + { + c_socketfd[i] = _SOCKET (PF_INET, SOCK_STREAM, _PROTOCOL); + if (0 > c_socketfd[i]) + { + printf ("client %d failed,err %d\n", i, errno); + } + else + { + printf ("client %d created success\n", i); + } + } + + for (i = 0; i < fdNumber; i++) + { + optval = 1; + ret = + setsockopt (c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof (optval)); + if (ret == -1) + { + printf ("Couldn't setsockopt(SO_REUSEADDR)\n"); + break; + } + } + + for (i = 0; i < fdNumber; i++) + { + g_src.sin_port = htons (srcPort + i); + errbind[i] = + _BIND (c_socketfd[i], (struct sockaddr *) &g_src, sizeof (g_src)); + if (errbind[i] < 0) + { + printf ("client %d bind Failed %d\n", i, errno); + _CLOSE (c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf ("client %d bind Success port:%d IP:%s\n", i, + ntohs (g_src.sin_port), + inet_ntoa (*((struct in_addr *) &(g_src.sin_addr.s_addr)))); + } + } + for (i = 0; i < fdNumber; i++) + { + if (errbind[i] >= 0) + { + errconn[i] = + _CONNECT (c_socketfd[i], (struct sockaddr *) &g_dest, + sizeof (g_dest)); + if (errconn[i] < 0) + { + printf ("client %d Connect Failed %d\n", i, errno); + _CLOSE (c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf ("client %d Connect Success port:%d, IP:%s\n", i, + ntohs (g_dest.sin_port), + inet_ntoa (* + ((struct in_addr *) + &(g_dest.sin_addr.s_addr)))); + } + } + } + + sleep (1); + + clock_gettime (CLOCK_MONOTONIC, &startTime); + clock_gettime (CLOCK_MONOTONIC, &countStart); + + int recvLen2, recvLen; + for (t = 0; t < times; t++) + { + for (i = 0; i < fdNumber; i++) + { + if (c_socketfd[i] < 0) + { + continue; + } + do + { + sendLen = _SEND (c_socketfd[i], send_buf, msg_length, 0); + } + while (sendLen <= 0); + send_count[i]++; + recvLen = 0; + do + { + recvLen2 = + recv (c_socketfd[i], recv_buf + recvLen, msg_length - recvLen, + 0); + if (recvLen2 <= 0) + { + continue; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + break; + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + } + while (1); + } + + if (0 != sleepTime) + { + if ((t % sleepCnt) == 0) + { + usleep (sleepTime); + } + } + + if ((send_count[0] % unitPrint) == 0 && send_count[0] > 0) + { + clock_gettime (CLOCK_MONOTONIC, &countEnd); + + pps_time = + (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + + countEnd.tv_nsec - countStart.tv_nsec; + pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; + if ((flagPrint != 0)) + { + printf (" sendcount %d, time: %ld ns\n", + send_count[0] * fdNumber, pps_time); + } + printf ("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); + clock_gettime (CLOCK_MONOTONIC, &countStart); + } + } + + clock_gettime (CLOCK_MONOTONIC, &endTime); + + for (i = 0; i < fdNumber; i++) + { + printf ("client %d send %d , sendtime :%ld s %ld ns\n", i, + send_count[i], endTime.tv_sec - startTime.tv_sec, + endTime.tv_nsec - startTime.tv_nsec); + } + + for (i = 0; i < fdNumber; i++) + { + printf ("client %d close!\n", i); + if (c_socketfd[i] > 0) + _CLOSE (c_socketfd[i]); + } + + pthread_exit (NULL); +} + +/* + using this thread to do recv msg; +*/ +void * +process_server_msg_thread (void *pArgv) +{ + int recvLen = 0, recvLen2 = 0; + char send_buf[1000]; + char recv_buf[1000]; + int recv_count = 0; + long recv_ppstime = 0; + int recv_pps = 0; + int ret; + + struct epoll_event eventList[MAX_EVENTS]; + + struct timespec recvStart; + struct timespec recvEnd; + memset (&recvStart, 0, sizeof (recvStart)); + memset (&recvEnd, 0, sizeof (recvEnd)); + + int msgEpFd = *(int *) pArgv; + + clock_gettime (CLOCK_MONOTONIC, &recvStart); + while (1) + { + int timeout = -1; + int m; + int sock; + ret = epoll_wait (msgEpFd, eventList, MAX_EVENTS, timeout); + if (ret == 0) + continue; + + for (m = 0; m < ret; m++) + { + if ((eventList[m].events & EPOLLERR) + || (eventList[m].events & EPOLLHUP) + || !(eventList[m].events & EPOLLIN)) + { + printf ("fd %d epoll error event:%d\n", eventList[m].data.fd, + eventList[m].events); + close (eventList[m].data.fd); + continue; + } + else + { + recvLen = 0; + recvLen2 = 0; + sock = eventList[m].data.fd; + + do + { + recvLen2 = + recv (sock, recv_buf + recvLen, msg_length - recvLen, 0); + if (recvLen2 <= 0) + { + break; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + recv_count++; + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) + { + clock_gettime (CLOCK_MONOTONIC, &recvEnd); + recv_ppstime = + (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + + recvEnd.tv_nsec - recvStart.tv_nsec; + recv_pps = + ((float) 1000000000 / recv_ppstime) * unitPrint; + printf ("receive count:%d, receive time: %ld ns\n", + recv_count, recv_ppstime); + printf ("receive pps = %d\n", recv_pps); + clock_gettime (CLOCK_MONOTONIC, &recvStart); + } + } + while (1); + } + + } + + if (recv_count == connectNum * times) + { + break; + } + } + + close (msgEpFd); +} + +/* + using this thread to do accept connect +*/ +void * +process_server_accept_thread (void *pArgv) +{ + int listenFd = 0; + int x, optval, ret, m = 0; + int acpt_socketfd[1000] = { 0 }; + int msgEpFd = *(int *) pArgv; + + listenFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (0 > listenFd) + { + printf ("ERROR:socket failed,errno [%d]\n", errno); + return NULL; + } + else + { + printf ("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); + } + + if (0 > fcntl (listenFd, F_SETFL, O_NONBLOCK)) + { + printf ("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); + close (listenFd); + } + + optval = 1; + ret = + setsockopt (listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof (optval)); + if (ret == -1) + { + printf ("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, + errno); + close (listenFd); + return NULL; + } + + if (0 != + bind (listenFd, (struct sockaddr *) &g_recv, sizeof (struct sockaddr))) + { + printf ("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); + printf ("Info Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port), + inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + close (listenFd); + return NULL; + } + else + { + printf ("Info Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port), + inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + } + + if (0 != listen (listenFd, 100)) + { + printf ("server socket listen failed. err %d\n", errno); + close (listenFd); + return NULL; + } + printf ("Listen Success\n"); + + int accEpFd; + struct epoll_event eventList[100]; + accEpFd = epoll_create (100); + struct epoll_event event; + event.events = EPOLLIN | EPOLLET; + event.data.fd = listenFd; + + if (epoll_ctl (accEpFd, EPOLL_CTL_ADD, listenFd, &event) < 0) + { + printf ("epoll_ctl add [%d] to epfd:%d failed\n", listenFd, accEpFd); + exit (-1); + } + + int timeout = -1; + int accpedNum = 0; + while (accpedNum < connectNum) + { + ret = epoll_wait (accEpFd, eventList, connectNum, timeout); + + if (ret < 0) + { + printf ("accept_thread epoll_wait error, epfd[%d], errno[%d]\n", + accEpFd, errno); + continue; + } + else if (ret == 0) + continue; + + /*loop done ever Event */ + for (x = 0; x < ret; x++) + { + printf ("event:%d; ret:%d\n", eventList[x].events, ret); + if ((eventList[x].events & EPOLLERR) + || !(eventList[x].events & EPOLLIN)) + { + printf ("epoll fd %d error\n", eventList[x].data.fd); + close (eventList[x].data.fd); + continue; + } + + while (1) + { + acpt_socketfd[accpedNum] = + accept4 (listenFd, NULL, NULL, SOCK_NONBLOCK); + if (acpt_socketfd[accpedNum] < 0) + { + perror ("epoll connect error\n"); + break; + } + /*add new accptFd to MsgEpFD */ + event.events = EPOLLIN | EPOLLET; + event.data.fd = acpt_socketfd[accpedNum]; + if (epoll_ctl + (msgEpFd, EPOLL_CTL_ADD, acpt_socketfd[accpedNum], + &event) < 0) + { + printf ("epoll add fd[%d] to msgEpfd:[%d] failed\n", + acpt_socketfd[accpedNum], msgEpFd); + continue; + } + printf ("accept cnt [%d], cur accept fd [%d]\n", accpedNum, + acpt_socketfd[accpedNum]); + accpedNum++; + } + } + } + + close (listenFd); + close (accEpFd); + pthread_exit (NULL); +} + +void +main (int argc, char *argv[]) +{ + socklen_t addrlen = sizeof (struct sockaddr); + int err = 0, result = 0, ret = 0; + int i = 0, j = 0, optval = 0, z = 0, x, listenfd; + cpu_set_t mask; + + setArgsDefault (); + ret = process_arg (argc, argv); + if (ret != 1) + { + printf ("The param error\n"); + return; + } + + int accEpFd = epoll_create (100); + + pthread_t client_thread_id; + + if (pthread_create + (&client_thread_id, NULL, (void *) (&process_client), NULL) == -1) + { + printf ("create client thread fail\n"); + return; + } + + printf ("create client thread success\n"); + + if (client_thread_id != 0) + { + printf ("Client Thread join\n"); + pthread_join (client_thread_id, NULL); + } + + return; +} diff --git a/app_example/perf-test/multi_tcp_epoll_app_Ser.c b/app_example/perf-test/multi_tcp_epoll_app_Ser.c new file mode 100644 index 0000000..972c395 --- /dev/null +++ b/app_example/perf-test/multi_tcp_epoll_app_Ser.c @@ -0,0 +1,631 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define _GNU_SOURCE +#include <sys/socket.h> +#include <fcntl.h> +#include <memory.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <time.h> +#include <linux/tcp.h> +#include <sched.h> +#include <pthread.h> +#include <arpa/inet.h> +#include <sys/epoll.h> +#include <errno.h> + +#define _BIND bind +#define _LISTEN listen +#define _SOCKET socket +#define _ACCEPT accept +#define _SEND send +#define _RECV recv +#define _CLOSE close +#define _CONNECT connect +#define _PROTOCOL IPPROTO_TCP + +#define MAX_TEST_TIME 1000 +#define MSG_LENGTH 256 +#define CORE_NUM 8 +#define START_CPU_ID 2 +#define MAX_CONN_LIMIT 256 +#define MAX_PORT_NUM 65535 +//1:A-B ;0:A-B-A +#define SEND_RECV_MODE 1 +#define MAX_EVENTS 1000 +#define Default_PortID 12345 +#define Default_SleepCnt 10000 +#define Default_SleepTime 1000000 +#define Flag_Print 1 +#define Fd_Number 1 + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +static struct sockaddr_in g_recv; + +int times = MAX_TEST_TIME; +int msg_length = MSG_LENGTH; +int coreNum = CORE_NUM; +int startCPUId = START_CPU_ID; +int connectNum = MAX_CONN_LIMIT; +int msgMode = SEND_RECV_MODE; +int sleepCnt = Default_SleepCnt; +int sleepTime = Default_SleepTime; //us +int fdNumber = Fd_Number; +int flagPrint = Flag_Print; +int unitPrint = 0; +int waitTime = 0; + +int srcPort = Default_PortID; +int destPort = 0; +int recvPort = 0; +char sendarr[256] = ""; +char recvarr[256] = ""; +char destarr[256] = ""; + +static void +setArgsDefault () +{ + + memset (&g_dest, 0, sizeof (g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr ("127.0.0.1"); + g_dest.sin_port = htons (12345); + bzero (&(g_dest.sin_zero), 8); + + memset (&g_src, 0, sizeof (g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr ("0.0.0.0"); + g_src.sin_port = htons (7895); + bzero (&(g_src.sin_zero), 8); + + memset (&g_recv, 0, sizeof (g_recv)); + g_recv.sin_family = AF_INET; + g_recv.sin_addr.s_addr = inet_addr ("0.0.0.0"); + g_recv.sin_port = htons (7895); + bzero (&(g_recv.sin_zero), 8); + +} + +static int +process_arg (int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; + int rw_mark = 0; + + if (argc < 4) + { + printf + ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); + printf + ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); + return 0; + } + while ((opt = getopt (argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + destPort = atoi (optarg); + g_dest.sin_port = htons (atoi (optarg)); + break; + case 'd': + stpcpy (destarr, optarg); + g_dest.sin_addr.s_addr = inet_addr (optarg); + break; + case 's': + stpcpy (sendarr, optarg); + g_src.sin_addr.s_addr = inet_addr (optarg); + g_recv.sin_addr.s_addr = inet_addr (optarg); + break; + case 'a': + //g_src.sin_port = htons(atoi(optarg)); + srcPort = atoi (optarg); + break; + case 'l': + msg_length = atoi (optarg); + break; + case 't': + times = atoi (optarg); + break; + case 'e': + sleepCnt = atoi (optarg); + break; + case 'i': + sleepTime = atoi (optarg); + break; + case 'f': + fdNumber = atoi (optarg); + break; + case 'r': + recvPort = atoi (optarg); + g_recv.sin_port = htons (atoi (optarg)); + break; + case 'n': + connectNum = atoi (optarg); + break; + case 'w': + waitTime = atoi (optarg); + break; + case 'u': + unitPrint = atoi (optarg); + break; + case 'x': + flagPrint = atoi (optarg); + break; + + } + } + return 1; +} + +void +process_client (void) +{ + int sendLen = 0; + int i = 0, t = 0, p = 0, optval = 0, ret = 0; + char send_buf[1000] = ""; + int c_socketfd[100] = { 0 }; + int errbind[1000] = { 0 }; + int errconn[1000] = { 0 }; + + int send_count[1000] = { 0 }; + int pps = 0; + long pps_time = 0; + + struct timespec startTime, endTime; + struct timespec countStart; + struct timespec countEnd; + memset (&countStart, 0, sizeof (countStart)); + memset (&countEnd, 0, sizeof (countEnd)); + + for (i = 0; i < fdNumber; i++) + { + c_socketfd[i] = _SOCKET (PF_INET, SOCK_STREAM, _PROTOCOL); + if (0 > c_socketfd[i]) + { + printf ("client %d failed,err %d\n", i, errno); + } + else + { + printf ("client %d created success\n", i); + } + } + + for (i = 0; i < fdNumber; i++) + { + optval = 1; + ret = + setsockopt (c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof (optval)); + if (ret == -1) + { + printf ("Couldn't setsockopt(SO_REUSEADDR)\n"); + break; + } + } + + for (i = 0; i < fdNumber; i++) + { + g_src.sin_port = htons (srcPort + i); + errbind[i] = + _BIND (c_socketfd[i], (struct sockaddr *) &g_src, sizeof (g_src)); + if (errbind[i] < 0) + { + printf ("client %d bind Failed %d\n", i, errno); + _CLOSE (c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf ("client %d bind Success port:%d IP:%s\n", i, + ntohs (g_src.sin_port), + inet_ntoa (*((struct in_addr *) &(g_src.sin_addr.s_addr)))); + } + } + for (i = 0; i < fdNumber; i++) + { + if (errbind[i] >= 0) + { + errconn[i] = + _CONNECT (c_socketfd[i], (struct sockaddr *) &g_dest, + sizeof (g_dest)); + if (errconn[i] < 0) + { + printf ("client %d Connect Failed %d\n", i, errno); + _CLOSE (c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf ("client %d Connect Success port:%d, IP:%s\n", i, + ntohs (g_dest.sin_port), + inet_ntoa (* + ((struct in_addr *) + &(g_dest.sin_addr.s_addr)))); + } + } + } + + sleep (1); + + clock_gettime (CLOCK_MONOTONIC, &startTime); + clock_gettime (CLOCK_MONOTONIC, &countStart); + + for (t = 0; t < times; t++) + { + for (i = 0; i < fdNumber; i++) + { + if (c_socketfd[i] < 0) + { + continue; + } + do + { + sendLen = _SEND (c_socketfd[i], send_buf, msg_length, 0); + } + while (sendLen <= 0); + send_count[i]++; + } + + if (0 != sleepTime) + { + if ((t % sleepCnt) == 0) + { + usleep (sleepTime); + } + } + + if ((send_count[0] % unitPrint) == 0) + { + clock_gettime (CLOCK_MONOTONIC, &countEnd); + + pps_time = + (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + + countEnd.tv_nsec - countStart.tv_nsec; + pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; + if ((flagPrint != 0)) + { + printf (" sendcount %d, time: %ld ns\n", + send_count[0] * fdNumber, pps_time); + } + printf ("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); + clock_gettime (CLOCK_MONOTONIC, &countStart); + } + + } + + clock_gettime (CLOCK_MONOTONIC, &endTime); + + for (i = 0; i < fdNumber; i++) + { + printf ("client %d send %d , sendtime :%ld s %ld ns\n", i, + send_count[i], endTime.tv_sec - startTime.tv_sec, + endTime.tv_nsec - startTime.tv_nsec); + } + + for (i = 0; i < fdNumber; i++) + { + printf ("client %d close!\n", i); + if (c_socketfd[i] > 0) + _CLOSE (c_socketfd[i]); + } + + pthread_exit (NULL); +} + +/* + using this thread to do recv msg; +*/ +void * +process_server_msg_thread (void *pArgv) +{ + int recvLen = 0, recvLen2 = 0; + char send_buf[1000]; + char recv_buf[1000]; + int recv_count = 0; + long recv_ppstime = 0; + int recv_pps = 0; + int ret; + struct epoll_event event; + + struct epoll_event eventList[MAX_EVENTS]; + + struct timespec recvStart; + struct timespec recvEnd; + memset (&recvStart, 0, sizeof (recvStart)); + memset (&recvEnd, 0, sizeof (recvEnd)); + + pthread_detach (pthread_self ()); + + int msgEpFd = epoll_create (100); + int msgFd = *(int *) pArgv; + + event.events = EPOLLIN | EPOLLET; + event.data.fd = msgFd; + if (epoll_ctl (msgEpFd, EPOLL_CTL_ADD, msgFd, &event) < 0) + { + printf ("epoll add fd[%d] to msgEpfd:[%d] failed\n", msgFd, msgEpFd); + close (msgEpFd); + close (msgFd); + return NULL; + } + + clock_gettime (CLOCK_MONOTONIC, &recvStart); + while (1) + { + int timeout = -1; + int m; + int sock; + ret = epoll_wait (msgEpFd, eventList, MAX_EVENTS, timeout); + if (ret == 0) + continue; + + for (m = 0; m < ret; m++) + { + if ((eventList[m].events & EPOLLERR) + || (eventList[m].events & EPOLLHUP) + || !(eventList[m].events & EPOLLIN)) + { + printf ("fd %d epoll error event:%d\n", eventList[m].data.fd, + eventList[m].events); + close (eventList[m].data.fd); + continue; + } + else + { + recvLen = 0; + recvLen2 = 0; + sock = eventList[m].data.fd; + + do + { + recvLen2 = + recv (sock, recv_buf + recvLen, msg_length - recvLen, 0); + if (recvLen2 <= 0) + { + break; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + recv_count++; + if (msg_length != send (sock, send_buf, msg_length, 0)) + { + printf ("send failed!====, need exit\n"); + } + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) + { + clock_gettime (CLOCK_MONOTONIC, &recvEnd); + recv_ppstime = + (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + + recvEnd.tv_nsec - recvStart.tv_nsec; + recv_pps = + ((float) 1000000000 / recv_ppstime) * unitPrint; + printf ("receive count:%d, receive time: %ld ns\n", + recv_count, recv_ppstime); + printf ("receive pps = %d\n", recv_pps); + clock_gettime (CLOCK_MONOTONIC, &recvStart); + } + } + while (1); + } + + } + + if (recv_count == times) + { + break; + } + } + close (msgFd); + close (msgEpFd); +} + +/* + using this thread to do accept connect +*/ +void * +process_server_accept_thread (void *pArgv) +{ + int listenFd = 0; + int x, optval, ret, m = 0; + int acpt_socketfd[1000] = { 0 }; + + listenFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (0 > listenFd) + { + printf ("ERROR:socket failed,errno [%d]\n", errno); + return NULL; + } + else + { + printf ("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); + } + + if (0 > fcntl (listenFd, F_SETFL, O_NONBLOCK)) + { + printf ("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); + close (listenFd); + } + + optval = 1; + ret = + setsockopt (listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof (optval)); + if (ret == -1) + { + printf ("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, + errno); + close (listenFd); + return NULL; + } + + if (0 != + bind (listenFd, (struct sockaddr *) &g_recv, sizeof (struct sockaddr))) + { + printf ("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); + printf ("Info Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port), + inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + close (listenFd); + return NULL; + } + else + { + printf ("Info Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port), + inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + } + + if (0 != listen (listenFd, 100)) + { + printf ("server socket listen failed. err %d\n", errno); + close (listenFd); + return NULL; + } + printf ("Listen Success\n"); + + int accEpFd; + struct epoll_event eventList[100]; + accEpFd = epoll_create (100); + struct epoll_event event; + event.events = EPOLLIN | EPOLLET; + event.data.fd = listenFd; + + if (epoll_ctl (accEpFd, EPOLL_CTL_ADD, listenFd, &event) < 0) + { + printf ("epoll_ctl add [%d] to epfd:%d failed\n", listenFd, accEpFd); + exit (-1); + } + + int timeout = -1; + int accpedNum = 0; + while (accpedNum < connectNum) + { + ret = epoll_wait (accEpFd, eventList, connectNum, timeout); + + if (ret < 0) + { + printf ("accept_thread epoll_wait error, epfd[%d], errno[%d]\n", + accEpFd, errno); + continue; + } + else if (ret == 0) + continue; + + /*loop done ever Event */ + for (x = 0; x < ret; x++) + { + printf ("event:%d; ret:%d\n", eventList[x].events, ret); + if ((eventList[x].events & EPOLLERR) + || !(eventList[x].events & EPOLLIN)) + { + printf ("epoll fd %d error\n", eventList[x].data.fd); + close (eventList[x].data.fd); + continue; + } + + while (1) + { + acpt_socketfd[accpedNum] = + accept4 (listenFd, NULL, NULL, SOCK_NONBLOCK); + if (acpt_socketfd[accpedNum] < 0) + { + perror ("epoll connect error\n"); + break; + } + /*add new accptFd to MsgEpFD */ + pthread_t ser_rcv_thread_id; + if (pthread_create + (&ser_rcv_thread_id, NULL, process_server_msg_thread, + (void *) &acpt_socketfd[accpedNum]) == -1) + { + printf ("create process_server_msg_thread fail\n"); + break; + } + + printf ("accept cnt [%d], cur accept fd [%d]\n", accpedNum, + acpt_socketfd[accpedNum]); + accpedNum++; + } + } + } + + close (listenFd); + close (accEpFd); + + while (1) + { + sleep (10); + } + + pthread_exit (NULL); +} + +void +main (int argc, char *argv[]) +{ + socklen_t addrlen = sizeof (struct sockaddr); + int err = 0, result = 0, ret = 0; + int i = 0, j = 0, optval = 0, z = 0, x, listenfd; + cpu_set_t mask; + + setArgsDefault (); + ret = process_arg (argc, argv); + if (ret != 1) + { + printf ("The param error\n"); + return; + } + + pthread_t server_thread_id; + + if (pthread_create + (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) + { + printf ("create process_server_accept_thread fail\n"); + return; + } + + printf ("create process_server_accept_thread success\n"); + + if (server_thread_id != 0) + { + printf ("Server Thread join\n"); + pthread_join (server_thread_id, NULL); + } + + while (1) + { + sleep (10); + } + + return; +} diff --git a/app_example/perf-test/multi_tcp_no_epoll_Ser.c b/app_example/perf-test/multi_tcp_no_epoll_Ser.c new file mode 100644 index 0000000..ec67b0c --- /dev/null +++ b/app_example/perf-test/multi_tcp_no_epoll_Ser.c @@ -0,0 +1,589 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <fcntl.h> +#include <memory.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <time.h> +#include <linux/tcp.h> +#define __USE_GNU +#include <sched.h> +#include <pthread.h> +#include <arpa/inet.h> +#include <sys/epoll.h> +#include <errno.h> + +#define _BIND bind +#define _LISTEN listen +#define _SOCKET socket +#define _ACCEPT accept +#define _SEND send +#define _RECV recv +#define _CLOSE close +#define _CONNECT connect +#define _PROTOCOL IPPROTO_TCP + +#define MAX_TEST_TIME 1000 +#define MSG_LENGTH 256 +#define CORE_NUM 8 +#define START_CPU_ID 2 +#define MAX_CONN_LIMIT 256 +#define MAX_PORT_NUM 65535 +//1:A-B ;0:A-B-A +#define SEND_RECV_MODE 1 +#define MAX_EVENTS 1000 +#define Default_PortID 12345 +#define Default_SleepCnt 10000 +#define Default_SleepTime 1000000 +#define Flag_Print 1 +#define Fd_Number 1 + +static struct sockaddr_in g_dest; +static struct sockaddr_in g_src; +static struct sockaddr_in g_recv; + +int times = MAX_TEST_TIME; +int msg_length = MSG_LENGTH; +int coreNum = CORE_NUM; +int startCPUId = START_CPU_ID; +int connectNum = MAX_CONN_LIMIT; +int msgMode = SEND_RECV_MODE; +int sleepCnt = Default_SleepCnt; +int sleepTime = Default_SleepTime; //us +int fdNumber = Fd_Number; +int flagPrint = Flag_Print; +int unitPrint = 0; +int waitTime = 0; + +int srcPort = Default_PortID; +int destPort = 0; +int recvPort = 0; +char sendarr[256] = ""; +char recvarr[256] = ""; +char destarr[256] = ""; + +static void +setArgsDefault () +{ + + memset (&g_dest, 0, sizeof (g_dest)); + g_dest.sin_family = AF_INET; + g_dest.sin_addr.s_addr = inet_addr ("127.0.0.1"); + g_dest.sin_port = htons (12345); + bzero (&(g_dest.sin_zero), 8); + + memset (&g_src, 0, sizeof (g_src)); + g_src.sin_family = AF_INET; + g_src.sin_addr.s_addr = inet_addr ("0.0.0.0"); + g_src.sin_port = htons (7895); + bzero (&(g_src.sin_zero), 8); + + memset (&g_recv, 0, sizeof (g_recv)); + g_recv.sin_family = AF_INET; + g_recv.sin_addr.s_addr = inet_addr ("0.0.0.0"); + g_recv.sin_port = htons (7895); + bzero (&(g_recv.sin_zero), 8); + +} + +static int +process_arg (int argc, char *argv[]) +{ + int opt = 0; + int error = 0; + const char *optstring = "p:d:s:a:l:t:e:i:f:r:n:w:u:x:"; + int rw_mark = 0; + + if (argc < 4) + { + printf + ("Param info :-p dest_portid; -d dest_serverIP; -a src_portid; -s src_clientIP; -l msg_length; \n"); + printf + ("\t-t MAX_TEST_TIME; -i msg_interval ; -f client fd number ; -r receive port; -n connectNum(one server vs n client)\n"); + return 0; + } + while ((opt = getopt (argc, argv, optstring)) != -1) + { + switch (opt) + { + case 'p': + destPort = atoi (optarg); + g_dest.sin_port = htons (atoi (optarg)); + break; + case 'd': + stpcpy (destarr, optarg); + g_dest.sin_addr.s_addr = inet_addr (optarg); + break; + case 's': + stpcpy (sendarr, optarg); + g_src.sin_addr.s_addr = inet_addr (optarg); + g_recv.sin_addr.s_addr = inet_addr (optarg); + break; + case 'a': + //g_src.sin_port = htons(atoi(optarg)); + srcPort = atoi (optarg); + break; + case 'l': + msg_length = atoi (optarg); + break; + case 't': + times = atoi (optarg); + break; + case 'e': + sleepCnt = atoi (optarg); + break; + case 'i': + sleepTime = atoi (optarg); + break; + case 'f': + fdNumber = atoi (optarg); + break; + case 'r': + recvPort = atoi (optarg); + g_recv.sin_port = htons (atoi (optarg)); + break; + case 'n': + connectNum = atoi (optarg); + break; + case 'w': + waitTime = atoi (optarg); + break; + case 'u': + unitPrint = atoi (optarg); + break; + case 'x': + flagPrint = atoi (optarg); + break; + + } + } + return 1; +} + +void +process_client (void) +{ + int sendLen = 0; + int i = 0, t = 0, p = 0, optval = 0, ret = 0; + char send_buf[1000] = ""; + int c_socketfd[100] = { 0 }; + int errbind[1000] = { 0 }; + int errconn[1000] = { 0 }; + + int send_count[1000] = { 0 }; + int pps = 0; + long pps_time = 0; + + struct timespec startTime, endTime; + struct timespec countStart; + struct timespec countEnd; + memset (&countStart, 0, sizeof (countStart)); + memset (&countEnd, 0, sizeof (countEnd)); + + for (i = 0; i < fdNumber; i++) + { + c_socketfd[i] = _SOCKET (PF_INET, SOCK_STREAM, _PROTOCOL); + if (0 > c_socketfd[i]) + { + printf ("client %d failed,err %d\n", i, errno); + } + else + { + printf ("client %d created success\n", i); + } + } + + for (i = 0; i < fdNumber; i++) + { + optval = 1; + ret = + setsockopt (c_socketfd[i], SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof (optval)); + if (ret == -1) + { + printf ("Couldn't setsockopt(SO_REUSEADDR)\n"); + break; + } + } + + for (i = 0; i < fdNumber; i++) + { + g_src.sin_port = htons (srcPort + i); + errbind[i] = + _BIND (c_socketfd[i], (struct sockaddr *) &g_src, sizeof (g_src)); + if (errbind[i] < 0) + { + printf ("client %d bind Failed %d\n", i, errno); + _CLOSE (c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf ("client %d bind Success port:%d IP:%s\n", i, + ntohs (g_src.sin_port), + inet_ntoa (*((struct in_addr *) &(g_src.sin_addr.s_addr)))); + } + } + for (i = 0; i < fdNumber; i++) + { + if (errbind[i] >= 0) + { + errconn[i] = + _CONNECT (c_socketfd[i], (struct sockaddr *) &g_dest, + sizeof (g_dest)); + if (errconn[i] < 0) + { + printf ("client %d Connect Failed %d\n", i, errno); + _CLOSE (c_socketfd[i]); + c_socketfd[i] = -1; + continue; + } + else + { + printf ("client %d Connect Success port:%d, IP:%s\n", i, + ntohs (g_dest.sin_port), + inet_ntoa (* + ((struct in_addr *) + &(g_dest.sin_addr.s_addr)))); + } + } + } + + sleep (1); + + clock_gettime (CLOCK_MONOTONIC, &startTime); + clock_gettime (CLOCK_MONOTONIC, &countStart); + + for (t = 0; t < times; t++) + { + for (i = 0; i < fdNumber; i++) + { + if (c_socketfd[i] < 0) + { + continue; + } + do + { + sendLen = _SEND (c_socketfd[i], send_buf, msg_length, 0); + } + while (sendLen <= 0); + send_count[i]++; + } + + if (0 != sleepTime) + { + if ((t % sleepCnt) == 0) + { + usleep (sleepTime); + } + } + + if ((send_count[0] % unitPrint) == 0) + { + clock_gettime (CLOCK_MONOTONIC, &countEnd); + + pps_time = + (countEnd.tv_sec - countStart.tv_sec) * 1000000000 + + countEnd.tv_nsec - countStart.tv_nsec; + pps = ((float) 1000000000 / pps_time) * unitPrint * fdNumber; + if ((flagPrint != 0)) + { + printf (" sendcount %d, time: %ld ns\n", + send_count[0] * fdNumber, pps_time); + } + printf ("sendcount %d , pps=%d\n", send_count[0] * fdNumber, pps); + clock_gettime (CLOCK_MONOTONIC, &countStart); + } + + } + + clock_gettime (CLOCK_MONOTONIC, &endTime); + + for (i = 0; i < fdNumber; i++) + { + printf ("client %d send %d , sendtime :%ld s %ld ns\n", i, + send_count[i], endTime.tv_sec - startTime.tv_sec, + endTime.tv_nsec - startTime.tv_nsec); + } + + for (i = 0; i < fdNumber; i++) + { + printf ("client %d close!\n", i); + if (c_socketfd[i] > 0) + _CLOSE (c_socketfd[i]); + } + + pthread_exit (NULL); +} + +/* + using this thread to do recv msg; +*/ +void * +process_server_msg_thread (void *pArgv) +{ + int recvLen = 0, recvLen2 = 0; + char send_buf[1000]; + char recv_buf[1000]; + int recv_count = 0; + long recv_ppstime = 0; + int recv_pps = 0; + int ret; + struct epoll_event event; + + struct epoll_event eventList[MAX_EVENTS]; + + struct timespec recvStart; + struct timespec recvEnd; + memset (&recvStart, 0, sizeof (recvStart)); + memset (&recvEnd, 0, sizeof (recvEnd)); + + pthread_detach (pthread_self ()); + + int msgFd = *(int *) pArgv; + clock_gettime (CLOCK_MONOTONIC, &recvStart); + while (recv_count < times) + { + recvLen = 0; + recvLen2 = 0; + while (1) + { + recvLen2 = + recv (msgFd, recv_buf + recvLen, msg_length - recvLen, 0); + if (recvLen2 <= 0) + { + break; + } + else if (recvLen2 == msg_length - recvLen) + { + recvLen = 0; + recv_count++; + if (msg_length != send (msgFd, send_buf, msg_length, 0)) + { + printf ("send failed!====, need exit\n"); + } + + } + else if (recvLen2 < msg_length - recvLen) + { + recvLen += recvLen2; + } + } + if ((flagPrint != 0) && ((recv_count % unitPrint) == 0)) + { + clock_gettime (CLOCK_MONOTONIC, &recvEnd); + recv_ppstime = + (recvEnd.tv_sec - recvStart.tv_sec) * 1000000000 + + recvEnd.tv_nsec - recvStart.tv_nsec; + recv_pps = ((float) 1000000000 / recv_ppstime) * unitPrint; + printf ("receive count:%d, receive time: %ld ns\n", recv_count, + recv_ppstime); + printf ("receive pps = %d\n", recv_pps); + clock_gettime (CLOCK_MONOTONIC, &recvStart); + } + } + close (msgFd); +} + +/* + using this thread to do accept connect +*/ +void * +process_server_accept_thread (void *pArgv) +{ + int listenFd = 0; + int x, optval, ret, m = 0; + int acpt_socketfd[1000] = { 0 }; + + listenFd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (0 > listenFd) + { + printf ("ERROR:socket failed,errno [%d]\n", errno); + return; + } + else + { + printf ("INFO:Create listen socket Success, listenFd[%d]\n", listenFd); + } + + if (0 > fcntl (listenFd, F_SETFL, O_NONBLOCK)) + { + printf ("ERROR:fcntl failed. fd[%d], errno[%d]/n", listenFd, errno); + close (listenFd); + } + + optval = 1; + ret = + setsockopt (listenFd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof (optval)); + if (ret == -1) + { + printf ("ERROR:setsockopt failed. fd[%d], errno[%d]\n", listenFd, + errno); + close (listenFd); + return; + } + + if (0 != + bind (listenFd, (struct sockaddr *) &g_recv, sizeof (struct sockaddr))) + { + printf ("ERROR:bind failed. fd[%d] errno [%d]\n", listenFd, errno); + printf ("Info Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port), + inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + close (listenFd); + return; + } + else + { + printf ("Info Bind Success, port %d IP:%s\n", ntohs (g_recv.sin_port), + inet_ntoa (*((struct in_addr *) &(g_recv.sin_addr.s_addr)))); + } + + if (0 != listen (listenFd, 100)) + { + printf ("server socket listen failed. err %d\n", errno); + close (listenFd); + return; + } + printf ("Listen Success\n"); + + int accEpFd; + struct epoll_event eventList[100]; + accEpFd = epoll_create (100); + struct epoll_event event; + event.events = EPOLLIN | EPOLLET; + event.data.fd = listenFd; + + if (epoll_ctl (accEpFd, EPOLL_CTL_ADD, listenFd, &event) < 0) + { + printf ("epoll_ctl add [%d] to epfd:%d failed\n", listenFd, accEpFd); + exit (-1); + } + + int timeout = -1; + int accpedNum = 0; + while (accpedNum < connectNum) + { + ret = epoll_wait (accEpFd, eventList, connectNum, timeout); + + if (ret < 0) + { + printf ("accept_thread epoll_wait error, epfd[%d], errno[%d]\n", + accEpFd, errno); + continue; + } + else if (ret == 0) + continue; + + /*loop done ever Event */ + for (x = 0; x < ret; x++) + { + printf ("event:%d; ret:%d\n", eventList[x].events, ret); + if ((eventList[x].events & EPOLLERR) + || !(eventList[x].events & EPOLLIN)) + { + printf ("epoll fd %d error\n", eventList[x].data.fd); + close (eventList[x].data.fd); + continue; + } + + while (1) + { + acpt_socketfd[accpedNum] = + accept4 (listenFd, NULL, NULL, SOCK_NONBLOCK); + if (acpt_socketfd[accpedNum] < 0) + { + perror ("epoll connect error\n"); + break; + } + + fcntl (acpt_socketfd[accpedNum], F_SETFL, 0); + + /*add new accptFd to MsgEpFD */ + pthread_t ser_rcv_thread_id; + if (pthread_create + (&ser_rcv_thread_id, NULL, process_server_msg_thread, + (void *) &acpt_socketfd[accpedNum]) == -1) + { + printf ("create process_server_msg_thread fail\n"); + break; + } + + printf ("accept cnt [%d], cur accept fd [%d]\n", accpedNum, + acpt_socketfd[accpedNum]); + accpedNum++; + } + } + } + + close (listenFd); + close (accEpFd); + + while (1) + { + sleep (10); + } + + pthread_exit (NULL); +} + +void +main (int argc, char *argv[]) +{ + socklen_t addrlen = sizeof (struct sockaddr); + int err = 0, result = 0, ret = 0; + int i = 0, j = 0, optval = 0, z = 0, x, listenfd; + cpu_set_t mask; + + setArgsDefault (); + ret = process_arg (argc, argv); + if (ret != 1) + { + printf ("The param error\n"); + return; + } + + pthread_t server_thread_id; + + if (pthread_create + (&server_thread_id, NULL, process_server_accept_thread, NULL) == -1) + { + printf ("create process_server_accept_thread fail\n"); + return; + } + + printf ("create process_server_accept_thread success\n"); + + if (server_thread_id != 0) + { + printf ("Server Thread join\n"); + pthread_join (server_thread_id, NULL); + } + + while (1) + { + sleep (10); + } + + return; +} diff --git a/build/.gitkeep b/build/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/build/.gitkeep diff --git a/doc/Build_DMM.md b/doc/Build_DMM.md new file mode 100644 index 0000000..12105de --- /dev/null +++ b/doc/Build_DMM.md @@ -0,0 +1,109 @@ +# 1. Introduction : + This document purpose is to build the DMM. + +# 2. Build DPDK: +DPDK need to be built for DMM RTE dependency. + +- Steps : + + download dpdk-16.04.tar.xz from DPDK release, you can get it from [http://static.dpdk.org/rel](http://static.dpdk.org/rel) +``` + #wget http://static.dpdk.org/rel/dpdk-16.04.tar.xz + #tar xvf dpdk-16.04.tar.xz + #vi dpdk-16.04/config/common_base #make CONFIG_RTE_BUILD_SHARED_LIB=y + #cd dpdk-16.04 + #make install T=x86_64-native-linuxapp-gcc DESTDIR=/root/dpdk_build/tmp2 + #cd x86_64-native-linuxapp-gcc + #make #to install the dpdk which will generate .so inside lib folder in the path. +``` +Make sure the path same as list up +``` + #mkdir -p /root/dpdk_build/tmp2/opt/uvp/evs/ + #cp /root/dpdk/dpdk-16.04/x86_64-native-linuxapp-gcc/kmod/igb_uio.ko /root/dpdk_build/tmp2/opt/uvp/evs/ +``` +Note: + + Environment: + Linux ubuntu 14.04 and above. + Make sure you have linux-headers-4.4.0-89 linux-headers-4.4.0-89-generic and check uname -a it should have 4.4.0-89-generic header + +- Hugepage setting: + +``` + #vi /etc/default/grub +``` +update GRUB\_CMDLINE\_LINUX\_DEFAULT="default\_hugepagesz=1G hugepagesz=1G hugepages=8" + +``` + #update-grub + #reboot +``` +Check hugepage info HugePages_ + +``` + #cat /proc/meminfo +``` +- Mount hugepages: + +``` + #mount -t hugetlbfs -o pagesize=1G none /mnt/nstackhuge/ +``` + +``` + #mkdir /var/run/ip_module ##if not exist + #export LD_LIBRARY_PATH=/root/xxxx/DMM/release/lib64/ +``` +Note: + + no need LD_PRELOAD, This macro is for the same purpose. + +- Enable detail log of nstack + +``` + #export NSTACK_LOG_ON=DBG +``` + + +# 3. Build DMM: + +``` + #cd DMM/build + #cmake -D DMM_DPDK_INSTALL_DIR=$DPDK_INSTALL_PATH .. + #Note: DPDK_INSTALL_PATH - the path in which DPDK has been installed +``` + after cmake all the makefiles and dependent .sh files will be copied under build directory. + +``` + #make -j 8 +``` + Note: + + Sometimes compilation fails due to GLOB lib dependency, to solve this problem by following steps. + +``` + #cd ../thirdparty/glog/glog-0.3.4 + #sudo autoreconf -ivf + #cd + #make -j 8 + #bash -x release_tar.sh +``` + +Note: + + Update path of DPDK install with /root/dpdk_build/tmp2 in below file +``` + #vim ./release/script/nstack_var.sh # you can change it +``` + +# 4. Bring up the nStackMain process: +``` + #rm -rf /product + #mkdir /product/ + #chmod 777 /product/ + #mkdir /mnt/nstackhuge -p + #goto /DMM/ + #tar zxvf nStackServer.tar.gz + #cd nStackServer + #./start_nstack.sh + #ps -ef | grep nStackMain +```
\ No newline at end of file diff --git a/doc/DMM_DeveloperManual.md b/doc/DMM_DeveloperManual.md new file mode 100644 index 0000000..cbed4f1 --- /dev/null +++ b/doc/DMM_DeveloperManual.md @@ -0,0 +1,1023 @@ +![logo fd.io](resources/logo_fdio-300x184.png) + +**DMM Developer Manual** + +[**1** **Introduction** 1](#section) + +[**2** **DMM Overall Architecture** 2](#dmm-overallarchitecture) + +[**3** **Core Components** 3](#core-components) + +[**3.1** **nSocket** 3a](#nsocket) + +[**3.2** **Framework** 3b](#framework) + +[**3.3** **Adaptor** 3c](#adaptor) + +[**3.4** **LRD** 3d](#lrd) + +[**3.5** **HAL** 3e](#hal) + +[**3.6** **OMC** 3f](#omc) + +[**4** **Plug-in Architectures** 4](#plug-in-architectures) + +[**4.1** **Overview** 4a](#overview) + +[**4.2** **Plug-in interface** 4b](#plug-in-interface) + +[**4.2.1** **Interface of protocol stack adapter APIs**4ba](#Interface-of-protocol-stack-adapter-APIs) + +[**4.2.1.1** **nStack\_module\_info**4baa](#nStack_module_info) + +[**4.2.1.2** **ep\_free\_ref**4bab](#ep_free_ref) + +[**4.2.1.3** **nstack\_stack\_register\_fn**4bac](#nstack_stack_register_fn) + +[**4.2.1.4** **nstack\_proc\_cb**4bad](#nstack_proc_cb) + +[**4.2.1.5** **DMM-adapter APIs**4bae](#DMM-adapter-APIs) + +[**4.2.1.6** **nstack\_adp\t_init**4baf](#nstack_adpt_init) + +[**4.2.2** **epoll architecture** 4bb](#epoll-architecture) + +[**4.2.2.1** **ep\_ctl** 4bba](#ep_ctl) + +[**4.2.2.2** **ep\_getevt** 4bbb](#ep_getevt) + +[**4.2.2.3** **nstack\_event\_callback ** 4bbc](#nstack_event_callback) + +[**4.2.2.4** **nsep\_force\_epinfo\_free** 4bbd](#nsep_force_epinfo_free) + +[**4.2.3** **select** 4bc](#select) + +[**4.2.3.1** **pfselect** 4bca](#pfselect) + +[**4.2.4** **fork** 4bd](#fork) + +[**4.2.4.1** **fork\_init\_child** 4bda](#fork_init_child) + +[**4.2.4.2** **fork\_parent\_fd**4bdb](#fork_parent_fd) + +[**4.2.4.3** **fork\_child\_fd** 4bdc](#fork_child_fd) + +[**4.2.4.4** **fork\_free\_fd** 4bdd](#fork_free_fd) + +[**4.2.5** **Multithreading** 4be](#multithreading) + +[**4.2.6** **Resource recovery** 4bf](#resource-recovery) + +[**4.2.6.1** **obj\_recycle\_reg** 4bfa](#obj_recycle_reg) + +[**4.2.6.2** **obj\_recycle\_fun** 4bfb](#obj_recycle_fun) + +[**4.2.7** **LRD**4bg](#LRD) + +[**4.2.7.1** **nstack\_rd\_init** 4bga](#nstack_rd_init) + +[**4.2.7.2** **nstack\_get\_route\_data** 4bgb](#nstack_get_route_data) + +[**4.2.7.3** **nstack\_rd\_get\_stackid** 4bgc](#nstack_rd_get_stackid) + +[**5** **Release file** 5](#release-file) + +[**5.1** **libs** 5a](#libs) + +[**5.2** **Posix API of nSocket** 5b](#posix-api-of-nsocket) + +**1. Introduction** +================ + +This document is used to guide the user-mode protocol stack developers to use +the DMM framework. The document defines the interface that need to be registered +to the DMM when the protocol stack is integrated into the DMM and the interface +that the DMM provides to the protocol stack. In the document as well as in the +code, DMM is also called nStack. The two names are interchangeable. + +**2. DMM Overall Architecture** +============================ + +![nstack architecture](resources/nStack_Architecture.png) + +Figure1. The nStack software architecture.HAL: Hardware Abstraction +Layer, and IO adaptor + +The DMM framework provides posix socket APIs to the application. A protocol +stack could be plugged into the DMM. DMM will choose the most suitable stack +according to the policy of nRD to application. + +nRD is a strategy system which is used to choose a protocol stack for +application based on certain rules, such as network information, SLA, security +and so on. + +**3. Core Components** +=================== + +Figure1 shows an overview of the architecture design for DMM. DMM can be divided +into six main components: nSocket, Framework (FW), adapters, RD, HAL and OMC +(orchestration\manage\control).. + +**3.1 nSocket** +----------- + +“nSocket” provides user-friendly POSIX Compatible API of nStack, it intercepts +the socket API calls from the user application via system call hijacking or +the LD_PRELOAD mechanism. + +**3.2 Framework** +------------- + +Framework is a public framework module that includes shared-memory management, +IPC-management, initialization framework, basic data structures and timer. + +**3.3 Adaptor** +----------- + +**nStack-adaptor:** Used by protocol stack and implemented by DMM. Provides +interfaces towards DMM. + +**Stack-x-adaptor:** Used by DMM and implemented by protocol stack. Provides +interfaces towards protocol stack. + +**Kernel-adaptor:** Used and implemented by DMM. Help interact with kernel +stack (if supported). + +**3.4 RD** +------- +![RD topology](resources/RD_Topo.PNG) + +Resource Discovery subsystem is responsible for “routing/rule” discovery, +negotiation and decision-making (decision to select protocol stack). + +**3.5 HAL** +------- + +HAL (Hardware Abstraction Layer) layer provides the following functions for +upper-layer protocol stack: + +A unified user plane IO interface, shields the lower-level driver implementation +differences. Mask the port implementation differences between IO layer and +Protocol stack. + +Initialize the network interface card. + +**3.6 OMC** +------- + +OMC (operation, Monitor and Control) is responsible for the whole protocol stack +configuration management, monitoring and control. + +It provides functionalities like query statistics, monitoring process status etc. + +**4 Plug-in Architectures** +========================= + +**4.1 Overview** +------------ + +DMM-Plug-in architecture is an attractive solution for developers seeking to +build protocol stacks that are multi-functional, customizable, and easily +extensible. +![integration scheme](resources/Integration.png) + +Figure3. The Integration scheme + +Figure 3 shows a typical deployment mode that protocol stack and application +process are deployed in a pipeline mode (DMM also support the run-to-completion +mode) across processes.IPC is used for communication between them. + +1. DMM need to integrate the protocol stack adapter-library. The library + should implement the interfaces defined in the list1. The protocol stack + adapter is used for communicating with protocol stack process. In addition + to the function of the protocol stack, this module must implement the + interfaces defined by DMM, including the socket APIs, the epoll APIs, the + fork APIs and the resource recycle APIs. + + Interface | detail + --------- | ------ + ep\_ctl | Section 4.2.2.1 + ep\_getevt | Section 4.2.2.2 + fork\_init\_child | Section 4.2.4.1 + fork\_parent\_fd | Section 4.2.4.2 + fork\_child\_fd | Section 4.2.4.3 + fork\_free\_fd | Section 4.2.4.4 + module\_init | Section 4.3.5.5 + +List1. The function provided by protocol adapter. + +2. Protocol stack needs to integrate the DMM adapter-library. The library which + is used to create and initialize shared-memory. The shared-memory is the + highest performance method of IPC between nSocket and protocol stack. + The library utilizes the plug-in interface to provide rich features to the + protocol stack, such as resource recycle and event management. + +a. Protocol stack needs to register the recycle object and functions + (See section 4.2.7 for details) to the DMM adapter. When the OMC receive + the process exit signal, DMM adapter processes the exit signal, and + trigger resource recovery action. Protocol stack does not need to focus + on the exit of the application. + +b. Protocol stack needs to call the nstack\_adpt\_init + (See section 4.2.1 for details) defined in the DMM adapter to create and + initialize the shared memory object used by DMM.The init function + returns the nStack\_adpt\_cb (See section 4.2.1.1 for details) object + to the protocol stack. The protocol stack calls the callback functions + when processing packet. + Then DMM adapt-library should implement the interface defined in the list2. + + Interface | detail + --------- | ------ + event\_notify | Section 4.2.2.3 + ep\_pdata\_free | Section 4.2.2.4 + obj\_recycle\_reg | Section 4.2.7.1 + mbuf\_alloc | Section 4.2.6.1 + +List2. The function provided by DMM-adaptor. This will be used by protocol stack + +c. In the pipeline mode, initialization of nSocket does not create shared + memory; instead it looks up and attaches the shared memory created by + the DMM adapterr. + +d. nRD reads the routing information from the configuration file to make a + decision as nSocket selects the protocol stack. + +With these modules, DMM provides a unified socket interface, and support epoll, +select, fork, zero copy, resource recovery features. + +**4.2 Plug-in interface** +--------------------- + +### **4.2.1 Interface of Stack adapter APIs** + +The following APIs must be implemented by the protocol stack adapter. +They are used by nSocket module to do its work. + +**4.2.1.1 nStack\_module\_info** + +When the protocol stack is integrated into DMM, the first step is adding new +protocol stack module information. + + +``` +typedef struct _ nstack_module_keys { + const ns_char* modName; /*stack name*/ + const ns_char* registe_fn_name; /*stack register func name*/ + const ns_char* libPath; /*if libtype is dynamic, it is the path of lib*/ + ns_char deploytype; /*depoly model type: model type1, model type2, model type3*/ + ns_char libtype; /*dynamic lib or static lib*/ + ns_char ep_free_ref; /*when epoll information free, need to wait that stack would not + notify event */ + ns_char default_stack; /*whether is default stack: when don't know how to choose stack, + just use default stack firstly*/ + ns_int32 priority; /*reserv*/ + ns_int32 maxfdid; /* the max fd id, just used to check*/ + ns_int32 minfdid; /* the min fd id, just used to check */ + ns_int32 modInx; /* This is alloced by nStack , not from configuration */ +} nstack_module_keys; + +nstack_module_keys g_nstack_module_desc[] ={}; + +typedef enum { + NSTACK_MODEL_TYPE1, /*nSocket and stack belong to the same process*/ + NSTACK_MODEL_TYPE2, /*nSocket and stack belong to different processes, + *and nStack don't take care the communication between stack and stack adpt*/ + NSTACK_MODEL_TYPE3, /*nSocket and stack belong to different processes, and stax-x-adapter was + spplied to communicate whit stack*/ + NSTACK_MODEL_INVALID, +} nstack_model_deploy_type; + +``` + +DMM uses g\_nstack\_module_desc to manage the stack initialization information, +e.g. registration function name, lib path, etc. + +When the nSocket calls the nstack\_stack\_registe_fn() (See section 4.2.1.3 for +details) , the information returned by the protocol stack adapter is stored in +nstack\_module\_info. + +``` +typedef struct __NSTACK_MODULE { + char modulename[NSTACK_PLUGIN_NAME_LEN]; + ns_int32 priority; + void* handle; + nstack_proc_cb mops; + ns_int32 ep_free_ref; //ep information need free with ref + ns_int32 modInx; // The index of module + ns_int32 maxfdid; //the max fd id + ns_int32 minfdid; //the min fd id +} nstack_module; + +typedef struct{ + ns_int32 modNum; // Number of modules registed + ns_int32 linuxmid; + ns_int32 spmid; /* Stackx module index. */ + nstack_module *defMod; // The default module + nstack_module modules[NSTACK_MAX_MODULE_NUM]; +} nstack_module_info; + +nstack_module_info g_nstack_modules = { + .modNum = 0, + .linuxmid = -1, + .modules = {{{0}}}, + .defMod = NULL, +} + +``` + +CS2. The information of nstack\_module\_info + + **4.2.1.2 ep\_free\_ref** + +This field in data structure nstack\_module\_keys is used in pipe-line mode. +When the application process exits, the socket resources in the application +process are released, but the resources in the protocol stack are not released. +At this time, the protocol stack needs to continue accessing the epoll shared +resource to send events. + +So, you cannot free the resources of epoll immediately after the application +exits. Only when the resources of the protocol stack are completely released, +the epoll share resource can be released and it is done by the interface +provided by the DMM adapter. + +This field marks whether the stack needs to release the epoll resources. If it +is 1, DMM will not release resources when close is called, and the stack must +calls the interface provided by DMM adapter to release after releasing its own +resources. If it is 0, DMM(nSocket) released the source directly directly. + +**4.2.1.3 nstack\_stack\_register\_fn** + +Function prototypes: + + `typedef int (*nstack_stack_register_fn) (nstack_proc_cb *proc_fun, nstack_event_cb *event_ops);` + + +CS3. The declaration of nstack\_stack\_register\_fn + +There are three parameters in this function. + +nstack\_socket\_ops: defined in declare\_syscalls.h.tmpl file and is +same is in Posix. + +nstack\_event\_ops: + +``` +typedef struct __nstack_event_cb +{ + void *handle; /*current so file handler */ + int type; /*nstack is assigned to the protocol stack and needs to be passed to nstack when the event is reported */ + int (*event_cb) (void *pdata, int events); +} nstack_event_cb; + +``` + +Detail in the Section 4.2.3 + +**4.2.1.4 nstack\_proc\_cb:** + +``` +typedef struct __nstack_proc_ops{ + nstack_socket_ops socket_ops; /*posix socket api*/ + nstack_extern_ops extern_ops; /*other proc callback*/ +} nstack_proc_cb; + +typedef struct __nstack_extern_ops { + int (*module_init) (void); /*stack module init */ + int (*fork_init_child) (pid_t p, pid_t c); /*after fork, stack child process init again if needed. */ + void (*fork_parent_fd) (int s, pid_t p); /*after fork, stack parent process proc again if needed. */ + void (*fork_child_fd) (int s, pid_t p, pid_t c); /*after fork, child record pid for recycle if needed. */ + void (*fork_free_fd) (int s, pid_t p, pid_t c); /*for SOCK_CLOEXEC when fork if needed. */ + unsigned int (*ep_ctl) (int epFD, int proFD, int ctl_ops, struct epoll_event * event, void *pdata); /*when fd add to epoll fd, triggle stack to proc if need */ + unsigned int (*ep_getevt) (int epFD, int profd, unsigned int events); /*check whether some events exist really */ + int (*ep_prewait_proc) (int epfd); + int (*stack_fd_check) (int s, int flag); /*check whether fd belong to stack, if belong, return 1, else return 0 */ + int (*stack_alloc_fd) (); /*alloc a fd id for epoll */ + int (*peak) (int s); /*used for stack-x , isource maybe no need */ +} nstack_extern_ops; + +``` + +### **4.2.1.5 DMM-adapter APIs** + +For the multi-process model, DMM provide a library with resource initialization, +resource recycling, event notification and other functions to the protocol stack. + +nstack_adpt_fun is the core object between protocol stack and DMM. +It defines some pointers which can be used by protocol stacks. + +``` +typedef struct nsfw_com_attr +{ + int policy; + int pri; +} nsfw_com_attr; + +typedef struct __nstack_dmm_para +{ + nstack_model_deploy_type deploy_type; + int proc_type; + nsfw_com_attr attr; + int argc; + char **argv; +} nstack_dmm_para; + +int nstack_adpt_init (nstack_dmm_para * para) + +``` + +### **4.2.1.5 nstack\_adpt\_init** + + `int nstack_adpt_init (nstack_dmm_para * para)` + + +**Description**: + +The protocol stack calls this function to initialize the DMM framework and get +the callback function from DMM. + +**Parameters:** + +*deploy\_type*: decides whether protocol stack is deployed in same process along +with DMM or in a separate process. +*flag*: reserved +*out\_ops*: DMM provides the interfaces to protocol Stack, defined in +nstack\_adpt\_fun(details in 4.2.1) +*in\_ops*: protocol stack callback function registered to DMM. + +### **4.2.2 epoll Architecture** + +The function of these data structures is similar to the one in linux. +``` +struct eventpoll { + sys_sem_st lock; /*eventpoll lock*/ + sys_sem_st sem; /* rdlist lock */ + sem_t waitSem; /*sem for epoll_wait */ + struct ep_hlist rdlist; /*ready epitem list*/ + struct ep_hlist txlist; /*pad*/ + struct ep_rb_root rbr; /* rbtree*/ + int epfd; /*epoll fd*/ + u32 pid; /* Pid of the process who creat the structure, the resources used to release */ + nsfw_res res_chk; /* Verify whether resources are repeatedly released */ +}; +``` + +``` +typedef struct{ + int iindex; + int iNext; + int fd; + i32 fdtype; /* 0: socket fd, 1: epoll fd */ + i32 rlfd; /* copy of fdInf->rlfd */ + i32 rmidx; /* copy of fdInf->rmidx */ + i32 protoFD[NSEP_SMOD_MAX]; + i32 epaddflag[NSEP_SMOD_MAX]; + struct eventpoll *ep; + sys_sem_st epiLock; + sys_sem_st freeLock; + struct ep_list epiList; /* This restore the epitem of this file descriptor */ + u32 sleepTime; /* add for NSTACK_SEM_SLEEP */ + nsep_pidinfo pidinfo; + nsfw_res res_chk; + void* private_data; + i32 reserv[4]; +} nsep_epollInfo_t; + +``` + +``` +struct epitem { + struct ep_rb_node rbn; + struct ep_hlist_node rdllink; + struct ep_hlist_node lkFDllink; + int nwait; + struct eventpoll *ep; + nsep_epollInfo_t *epInfo; + struct epoll_event event; + struct list_node fllink; + struct ep_hlist_node txlink; + unsigned int revents; + int fd; + u32 pid; + void* private_data; + nsfw_res res_chk; +}; + +``` + +When the application calls epoll\_create(), nSocket first creates socket or +epoll object in the data type of nsep\_epollInfo\_t, then creates an eventpoll +object. For the created nsep_epollInfo_t object, when the file descriptor is an +epoll socket, ep points to eventpoll and the eplist is not used. When the file +descriptor is a normal socket, the epiList restores the fd and the ep is not +used. + +When the application calls epoll\_ctl() to add a socket to the epoll, nSocket +allocates an epitem object. The epitem object is added to a rbtree pointed by +epList in nsep\_epollInfo\_t, which is the epoll created in the previous step. +In the epitem object just allocated, nSocket uses ep to point to eventpoll, +revents to store event that is produced by the protocol stack, epinfo to point+ +to the epoll object in the data type of nsep\_epollInfo\_t. This is how DMM +connects the epoll, event, and socket together. + +When the application calls epoll\_wait(), nSocket scans the rdlist in eventpoll +to get events and return them to the application. + +Figure 3 is Runtime Graphs of nSocket in epoll function: + +![ePoll flow chart](resources/Epoll_flwChart.png) + +Figure 4: flow chart of various epoll functions function: + +![event and ep_pData free flow](resources/EvntNotify_StackX.png) + +Figure5: flow chart of nstack_event_callback and nsep_force_epinfo_free in protocol Stack + +### **4.2.2.1 ep\_ctl** + + `int (*ep_ctl)(int proFD, int ctl_ops, struct epoll_event *event, void *pdata);` + + +**Description:** + +1\. Used by the application to inform protocol stack to add/modify/delete file +descriptor (FD) to/from epoll and monitor events. + +2\. When the application adds new events or modifies existing events, it gets +prompt notification。 + +3\. pdata stores the nsep_epollInfo_t corresponding to the FD. It is used to +pass the value to the protocol stack event notification API when an event occurs. + +**Parameters:** + +*proFD*: sock file descriptor created by the protocol stack. +*ctl\_ops*: 0 add, 1 modify, 2 delete。 +*event*: similar to Linux “struct epoll\_event”。 +*pdata*: Private data that DMM passes to the protocol stack. + +**Interface implemented by:** Protocol stack. + +### **4.2.2.2 ep\_getevt** + +**Interface Definition:** + +`void (*ep_getevt)(int epFD, int profd, unsigned int events);` + +**Description:** + +To check if an event in protocol stack exist. Due to multi-threading or other +reasons, it’s possible that protocol stack is busy and causes delay in event +notification. Or event may be cleared by some application operation. Application +may use the API to check whether the event still exists. + +**Parameters:** + +*epFD*: epoll FD. +*proFD*: sock file descriptor created by the protocol stack. +*event*: Events which need to check. + +**Interface implemented by:** Protocol stack. + +### **4.2.2.3 nstack\_event\_callback ** + +`int (*nstack_event_callback)(void *pdata, int events)` + +**Description:** + +Called by the protocol stack when there is an event occurs. + +**Parameters:** + +*pdata*: pdata is the private data passed in ep\_ctl().. +*events*: Whatever event occurred + +**Interface implemented by:** DMM + +### **4.2.2.4 nsep\_force\_epinfo\_free** + +`int (*nsep_force_epinfo_free)(void *pdata)` + +**Description:** + +When closes fd, the protocol stack frees the resources related to fd. This API +is called by the protocol stack to release private data. + +**Precautions for use:** + +This API should only be called when ep\_free\_ref is configured 1 in +nstack\_module\_keys. + +**Parameters:** + +*pdata*: pdata is the private data in ep\_ctl(). + +**Interface implemented by:** DMM + +### **4.2.3 select** + +Select requires the protocol stack adapter module to provide a select API in +order to query for existing events. When the application calls select(), +DMM starts a separate thread to fetch the select event for each stack and +sends it back to the application. + +![select flowchart](resources/SelectFunc.png) + +Figure 6: flow chart of select function + +### **4.2.3.1 pfselect** + +`int *pfselect(int s, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout)` + + +**Description:** + +Query whether there is a corresponding protocol stack event. + +**Parameters:** + +*s*: The maximum file descriptor value in the collection +*readfds*: file descriptor set will be watched for read event +*writefds*: file descriptor set will be watched for write event +*exceptfds*: file descriptor set will be watched for exception cases + +**Interface implemented by:** Protocol Stack + +### **4.2.4 fork** + +fork() creates a child process by making an exact duplicate of the calling +process in a separate address spaces. Each process, parent and child, has its +own process address space where memory segments, such as code segment, data +segment, stack segment, etc., are placed. + +There are few exceptions to this. + +1. The fork system call duplicates all the file descriptors of the parent into + the child, so that the file descriptors in the parent and child point to the + same files. + +2. The shared memory is still shared between parent and child process after + fork (). + +3. Child process clones only thread, which executed it. + +When parent process or child process releases the shared resources on process +quit or kill, it affects the other process. + +Also if the child process wants to inherit other threads in the parent process, +the child process needs to pull or create those threads after the fork. + +Both parent and child process can access the shared memory, it create conflicts. + +Because of these issues, DMM provides the fork APIs to take care of processing +before and after calling the Linux fork interface. It includes interface lock +and shared resource lock, reference count incrimination, saving the PID of the +subprocesses, reinitialization and SOCK\_CLOEXEC option in socket special +handlings. + +Each shared memory data structure in DMM contains a reference count and a list +of process pids, so that the shared memory can be managed between parent and +child processes. On each fork, the reference count is increased by 1 and the +child process id is added to the pid array. + +``` +struct xxx{ + xxx, + int ref; / * Reference count * / + pid_t pid_array[]; + / * for father and son after the process list * / +}; + +``` + +DMM needs assistance from protocol stack to release or hold the shared +resources. Protocol stack is to provide stack specific implementation on +these DMM APIs. + +The following flow chart shows how fork process is handled: + +![fork process handling](resources/ForkChild.png) + +#### **4.2.4.1 fork\_init\_child** + +`int (* fork_init_child) (s, pid_t p, pid_t c)` + +**Description:** + +After fork, the API is used to add child process pid into the pid list in the +share socket data structure. When the child process exits, only the resources +in the child process are released unless the shared resource reference count +reaches 0. + +**Parameters:** + +*s*: file descriptor of the socket to be operated +*p*: parent process pid +*c*: child process pid + + +**Interface Implemented by:** Protocol stack. + +#### **4.2.4.2 fork\_parent\_fd** + +`void (* fork_parent_fd)(int s, pid_t p)` + +**Description:** + +For the socket with the SOCK_CLOEXEC flag on, when it is closed after fork, +only the file descriptor is recycled, no other resource is released. +It is a special treatment for SOCK_CLOEXEC. + +**Parameters:** + +*s*: socket fd +*p*: parent process pid +*c*: Child process pid + + +**Interface Implemented by:** Protocol stack. + +#### **4.2.4.3 fork\_child\_fd** + +`void (* fork_child_fd) (int s, pid_t p, pid_t c);` + +**Description:** + +After fork, the API is used to add child process pid into the pid list in the +share socket data structure. When the child process exits, only the resources +in the child process are released unless the shared resource reference count +reaches 0. + +**Parameter Description:** + +*s*: file descriptor of the socket to be operated +*p*: parent process pid +*c*: child process pid + +**Interface Implemented by:** Protocol stack. + +#### **4.2.4.4 fork\_free\_fd** + +`void (* fork_free_fd) (int s, pid_t p, pid_t c);` + +**Description:** + +For the socket with the SOCK\_CLOEXEC flag on, when it is closed after fork, +only the file descriptor is recycled, no other resource is released. +It is a special treatment for SOCK\_CLOEXEC. + +**Parameters:** + +*s*: socket fd. +*p*: parent process pid. +*c*: child process pid. + +**Interface Implemented by:** Protocol stack + +### **4.2.5 Multithreading** + +nSocket supports multi-thread. nSocket uses a ref and state to support +the feature. + +### **4.2.6 Resource recovery** + +Protocol stack must implement resource recovery. When the application crashes +or exits, the resources allocated by protocol stack must be released. +Otherwise, it causes resources leaking and can crash the system. + +DMM provides the following mechanism to support the feature. + +There is certain relationship between resource recovery and fork. Each fork +increases the reference count by 1 and saves the child process PID to the +corresponding shared resource. On exiting of the process, decreases the +reference count by 1 if the exiting process PID equals to one of the saved +PIDs and releases the shared resource if the reference count is 0, do not +release the shared resource if the reference count in not zero. + +1. There are two kinds of resource recovery, normal exit and abnormal + process exit. Resources are freed on normal exit operation. But on the + abnormal process exits, there is no one to clean up the shared resources + or decrease the reference count, so we rely on the separate process to + monitor the processes and notify the stack process to release the resources. + +2. To support resource recovery, the protocol stack needs to define a resource + object type in responding to DMM request and registers the recycle function + at initialization time. + +#### **4.2.6.1 obj\_recycle\_reg** + +TO Do + +#### **4.2.6.2 obj\_recycle\_fun** + +TO DO + +### **4.2.7 LRD** + +LRD function is mainly the protocol stack routing function, the internal storage +of a protocol stack selection policy table. When multiple protocol stacks are +integrated, according to the incoming IP address, protocol stack type and other +information, you can select a suitable protocol stack from the protocol Stack +selection policy table. During nSocket module initialization, it invokes the +LRD module initialization API to register the protocol stack information and +the protocol stack selection policy gets the interface. + +The initialization function for the LRD module is defined as follows. + + + +``` + int nstack_rd_init(nstack_stack_info *pstack, int num, nstack_get_route_data pfun) + +typedef struct __nstack_stack_info { + char name[STACK_NAME_MAX]; /*stack name*/ + int stack_id; /*stack id*/ + /*when route info not found, high priority stack was chose, + same priority chose fist input one*/ + int priority; /*0: highest: route info not found choose first*/ +} nstack_stack_info; + +/*rd local data*/ +typedef struct __rd_local_data { + nstack_rd_stack_info *pstack_info; /* all stack info*/ + int stack_num; + nstack_rd_list route_list[RD_DATA_TYPE_MAX]; /*route table*/ + nstack_get_route_data sys_fun; +} rd_local_data; + +rd_local_data *g_rd_local_data = NULL; + +/*get rd info. if return ok, data callee alloc memory, caller free, else caller don't free*/ +int (*nstack_get_route_data)(rd_route_data **data, int *num); + +``` + +When a new protocol stack is integrated into DMM, the protocol stack selection +configuration file will not directly match with the protocol stack name, but +with the plane name, which is more descriptive about stack and other interface +technology, therefore the RD has a map between the protocols stack and plane +name. + +``` +typedef struct __rd_stack_plane_map{ + char stackname[STACK_NAME_MAX]; /* Stack name */ + char planename[RD_PLANE_NAMELEN]; /* Plane name */ + int stackid; /*stack id */ +} rd_stack_plane_map; + +rd_stack_plane_map g_nstack_plane_info[] = { + {{“stackx”}, {“nstack-dpdk”} , -1}, + {{“kernel”}, {“nstack-linux”} , -1}, +}; + +``` + +When application calls the DMM socket, connect, sendto, sendmsg APIS, it +triggers the nSocket module to invoke the nStack\_rd\_get\_stackid() API to get +the route information. The protocol stack is then selected based on the +returned protocol stack ID. + +#### **4.2.7.1 nstack\_rd\_init** + +`int nstack_rd_init (nstack_stack_info * pstack, int num, nstack_get_route_data *pfun, int fun_num)` + +**Description:** + +Initializes the RD module g\_rd\_local\_data to receive and save the protocol +stack information provided by nSocket. Also provides the API to get protocol +stack selection information. + +When initialized, nSocket passes all the integrated protocol stacks information +to the RD module. The information includes the protocol stack name, nSocket +assigned stack id after integration and selects priority + +**Parameters:** + +*pStack*: a list of the protocol stack info +*num*: the number of protocol stack info passed in. +*pfun*: function to get the protocol stack selection information. +*fun_num*: the number of pfun passed in + +**Interface implemented by:**DMM + +#### **4.2.7.2 nstack\_get\_route\_data** + +`typedef int (*nstack_get_route_data) (rd_route_data ** data, int *num);` + +**Description:** + +Obtain the protocol stack selection information according to the protocol +stack plane name.. + +**Parameters:** + +*planename*: description on stack and other interface technology. nSocket +provides the protocol stack name. The configuration file saves an +outbound interface type, which is corresponding to a protocol stack. +*data*: protocol stack selection information. + +``` +typedef enum __rd_data_type{ + RD_DATA_TYPE_IP, / * According to the ip address to select the protocol stack * / + RD_DATA_TYPE_PROTO, / * Select protocol stack by protocol type * / + RD_DATA_TYPE_MAX, +}rd_data_type; + +typedef struct __rd_route_data{ + rd_data_type type; / * Stored protocol stack selection type * / + char stack_name[RD_PLANE_NAMELEN]; / * Stack plane name */ + union { + rd_ip_data ipdata; / * Select the IP address of the protocol stack type * / + unsigned int proto_type; / * Select protocol information for this stack * / + }; +} rd_route_data; + +``` + +*num*: The number of routing information returned. + +**Interface implemented by:**DMM + +#### **4.2.7.3 nstack\_rd\_get\_stackid** + +`int nstack_rd_get_stackid(nstack_rd_key* pkey, int *stackid) ;` + +**Description:** + +Select parameters according to the protocol stack to obtain the protocol stack +id corresponding to the parameter. + +**Parameter:** + +*pkey*: protocol stack selection key. + +``` +typedef struct __nstack_rd_key{ + rd_data_type type; / * Select protocol type parameters * / + union { + unsigned int ip_addr; / * This field is valid if the type is RD_DATA_TYPE_IP, which is + the IP address of the connection to be initiated * / + unsigned int proto_type; / * This field is valid if the type is RD_DATA_TYPE_PROTO, which + is the protocol type of the socket created at the time * / + }; +} nstack_rd_key; + +``` + +*stackid*: output parameter; nSocket internal number of the protocol stack id. + +**Interface implemented by:** DMM + +**5 Release file** +================ + +**5.1 libs** +-------- + +**libnStackAPI.so:** The API library that DMM provides to the application. +-------------------------------------------------------------------------------- + +**libnStackAdapt.so:** DMM provides an adapter library for cross process +protocol stack connections. + +**5.2 Posix API of nSocket** +------------------------ + +DMM provides socket APIs and integrates various protocol stacks. DMM selects +and invokes a specific protocol stack based on the information, such as IP and +protocol type, from the application. The protocol stacks do not interact with +the application. After the selection, what features an API supports are +determined by the implementation provided by the protocol stack itself. + +The standard socket APIs defined by DMM are as follows: + + Interface definition | Interface Description + -------------------- | --------------------- + int socket(int, int, int) | same as corresponding POSIX apis + int bind(int, const struct sockaddr\*, socklen\_t) | same as corresponding POSIX apis + int listen(int, int) | same as corresponding POSIX apis + int shutdown(int, int) | same as corresponding POSIX apis + int getsockname(int, struct sockaddr\*, socklen\_t\*) | same as corresponding POSIX apis + int getpeername(int, struct sockaddr\*, socklen\_t\*) | same as corresponding POSIX apis + int getsockopt(int, int, int, void\*, socklen\_t\*) | same as corresponding POSIX apis + int setsockopt(int, int, int, const void\*, socklen\_t) | same as corresponding POSIX apis + int accept(int, struct sockaddr\*, socklen\_t\*) | same as corresponding POSIX apis + int accept4(int, struct sockaddr\*, socklen\_t\*, int flags) | same as corresponding POSIX apis + int connect(int, const struct sockaddr\*, socklen\_t) | same as corresponding POSIX apis + ssize\_t recv(int , void\*, size\_t, int) | same as corresponding POSIX apis + ssize\_t send(int, const void\*, size\_t, int) | same as corresponding POSIX apis + ssize\_t read(int, void\*, size\_t) | same as corresponding POSIX apis + ssize\_t write(int, const void\*, size\_t) | same as corresponding POSIX apis + ssize\_t writev(int, const struct iovec \*, int) | same as corresponding POSIX apis + ssize\_t readv(int, const struct iovec \*, int) | same as corresponding POSIX apis + ssize\_t sendto(int, const void \*, size\_t, int, const struct sockaddr \*, socklen\_t) | same as corresponding POSIX apis + ssize\_t recvfrom(int, void \*, size\_t, int, struct sockaddr \*, socklen\_t \*) | same as corresponding POSIX apis + ssize\_t sendmsg(int, const struct msghdr \*, int flags) | same as corresponding POSIX apis + ssize\_t recvmsg(int, struct msghdr \*, int flags) | same as corresponding POSIX apis + int close(int) | same as corresponding POSIX apis + int select(int, fd\_set\*, fd\_set\*, fd\_set\*, struct timeval\*) | same as corresponding POSIX apis + int ioctl(int, unsigned long, unsigned long) | same as corresponding POSIX apis + int fcntl(int, int, unsigned long) | same as corresponding POSIX apis + int epoll\_create(int) | same as corresponding POSIX apis + int epoll\_ctl(int, int, int, struct epoll\_event \*) | same as corresponding POSIX apis + int epoll\_wait(int, struct epoll\_event \*, int, int) | same as corresponding POSIX apis + pid\_t fork(void) | Before/after calling base fork() need to handle other processing like ref\_count etc. diff --git a/doc/DMM_developer_manual_V1.23.docx b/doc/DMM_developer_manual_V1.23.docx Binary files differnew file mode 100644 index 0000000..d8aa3fa --- /dev/null +++ b/doc/DMM_developer_manual_V1.23.docx diff --git a/doc/TestAppUserGuide.md b/doc/TestAppUserGuide.md new file mode 100644 index 0000000..fc0d061 --- /dev/null +++ b/doc/TestAppUserGuide.md @@ -0,0 +1,158 @@ +# 1. Introduction: + +This document will help to test sample app with DMM. + +# 2. Configuration files: + +There are two configuration files need to modify for setting up the +topology. + +release\\configure + +**module\_config.json** is the stack module config file. + +**rd\_config.json** is the rd config file. + +<!-- --> + +# 3. JSON files configuration. + +We need to setup configuration as given below. + +# 3.1 module\_config.json for example: + +``` +{ + "default_stack_name": "kernel", /*when rd can't be find maybe + choose the defualt one*/ + "module_list": [ + { + "stack_name": "kernel", + "function_name": "kernel_stack_register", + "libname": "", /*library name, if loadtype is static, this maybe + null, */ /* else must give a library name*/ + "loadtype": "static", /*library load type: static or dynamic*/ + "deploytype": "1", + "maxfd": "1024", + "minfd": "0", + "priorty": "1", + "stackid": "0", /*must be ordered and not be repeated*/ + } + ] +} +``` + +# 3.2 rd\_config.json for example: + +``` +{ +"ip_route": [ + { + "subnet": "192.165.1.1/16", + "type": "nstack-kernel", /*output interface type, nstack-kernel: + indicate that this ip */ /* should go through linux protocol, + nstack-dpdk: go through stackx protocol*/ + }, + { + "subnet": "172.16.25.125/16", + "type": "nstack-kernel", + } +] +"prot_route": [ + { + "proto_type": "11", + "type": "nstack-kernel", + }, + ] +} +``` +# 4. Run sample APP: + +- **perf-test:** + + Add test code with kernel stack or userspace protocol stack + + +Usage: + +After building the DMM, inside the DMM/release directory below perf-test app will be generated. + +*kc_epoll, ks_epoll, vc_epoll, vs_epoll* + + +Examples : + +**With Kernel stack:** + +server: +``` + #./ks_epoll -p 20000 -d 172.16.25.125 -a 10000 -s 172.16.25.126 -l 200 -t 5000000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 10000 -e 10 -x 1 +``` +client: +``` + #./kc_epoll -p 20000 -d 172.16.25.126 -a 10000 -s 172.16.25.125 -l 200 -t 5000000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 10000 -e 10 -x 1 +``` + +**With DMM nStack:** + +server: +``` + #./vs_epoll -p 20000 -d 172.16.25.125 -a 10000 -s 172.16.25.126 -l 200 -t 5000000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 10000 -e 10 -x 1 +``` +client: +``` + #./vc_epoll -p 20000 -d 172.16.25.126 -a 10000 -s 172.16.25.125 -l 200 -t 5000000 -i 0 -f 1 -r 20000 -n 1 -w 10 -u 10000 -e 10 -x 1 +``` + +- **NGNIX**: + +Nginx build process: + +*step 1: Compile nginx code* + +``` + #wget "http://hg.nginx.org/nginx" + #cd nginx-1.1.15 + #./configure --with-ld-opt="-L /root/Work/xxx/release/lib64/ -lnStackAPI" + #make + #make install +``` +Note: + + a. ./configure **--with-ld-opt="-L /root/xxx/DMM/release/lib64/ -lnStackAPI"** can be done if you want to use nStack otherwise just give the ./configure. + b. Make sure before building edit the configurtaion if you want specific server IP. + For Ex: + Server: ifconfig eth3 172.16.25.125 netmask 255.255.255.224 up + Client: ifconfig eth3 172.16.25.126 netmask 255.255.255.224 up + + nginx.conf file modifiecations: + listen 172.16.25.125:80 + +*step 2: run the nginx code* + +``` + #cd /usr/local/nginx/sbin + #cp -r * ../../sbin + #cd ../../sbin + #./nginx +``` +Note: + + if you want to run ./nginx with nStack then perform following before run + a. export LD_LIBRARY_PATH=/root/xxx/DMM/release/lib64/ + b. export NSTACK_LOG_ON=DBG ##to display nStack consol logs. + +*step 3: Check whether ngnix service is running.* + +``` + #ps -ax | grep nginx +``` +*step 4: Test the nginx server is up or not!* + +At client board, perform below command and check the output: +``` + #curl http://172.16.25.125:80/ +``` +Note: + + curl is the tool need to be installed to browse the html page in linux without GUI. diff --git a/license/LICENSE b/license/LICENSE new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/license/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
\ No newline at end of file diff --git a/license/Third_Party_Open_Source_Software_Notice b/license/Third_Party_Open_Source_Software_Notice new file mode 100644 index 0000000..4595c7f --- /dev/null +++ b/license/Third_Party_Open_Source_Software_Notice @@ -0,0 +1,105 @@ +THIRD PARTY OPEN SOURCE SOFTWARE NOTICE + +Please note we provide an open source software notice for the third party open source software along with this software and/or this software component contributed by Huawei (in the following just "this SOFTWARE"). The open source software licenses are granted by the respective right holders. + + + +Warranty Disclaimer +THE OPEN SOURCE SOFTWARE IN THIS SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + + + +Copyright Notice and License Texts + +Software: glog 0.3.4 +Copyright notice: + +This software has been modified by Huawei Technologies Co.,Ltd. +Copyright (C) 2018, Huawei. + +Copyright (c) 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +A function gettimeofday in utilities.cc is based on + +http://www.google.com/codesearch/p?hl=en#dR3YEbitojA/COPYING&q=GetSystemTimeAsFileTime%20license:bsd + +The license of this code is: + +Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> and contributors +All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name(s) of the above-listed copyright holder(s) nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +License: Apache License, Version 2.0 + Copyright 2018 Huawei Technologies Co.,Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + + diff --git a/release/configure/module_config.json b/release/configure/module_config.json new file mode 100644 index 0000000..c9bae26 --- /dev/null +++ b/release/configure/module_config.json @@ -0,0 +1,27 @@ +{ + "default_stack_name": "kernel", + "module_list": [ + { + "stack_name": "kernel", + "function_name": "kernel_stack_register", + "libname": "./", + "loadtype": "static", + "deploytype": "1", + "maxfd": "1024", + "minfd": "0", + "priorty": "1", + "stackid": "0", + }, + { + "stack_name": "stackpool", + "function_name": "nstack_stack_register", + "libname": "libnstack.so", + "loadtype": "dynmic", + "deploytype": "3", + "maxfd": "1024", + "minfd": "0", + "priorty": "1", + "stackid": "1", + }, + ] +} diff --git a/release/configure/rd_config.json b/release/configure/rd_config.json new file mode 100644 index 0000000..d005569 --- /dev/null +++ b/release/configure/rd_config.json @@ -0,0 +1,26 @@ +{ + "ip_route": [ + { + "subnet": "192.168.1.1/24", + "type": "nstack-kernel", + }, + { + "subnet": "192.167.1.1/24", + "type": "nstack-kernel", + }, + { + "subnet": "192.166.1.1/24", + "type": "nstack-kernel", + } + ], + "prot_route": [ + { + "proto_type": "1", + "type": "nstack-kernel", + }, + { + "proto_type": "2", + "type": "nstack-kernel", + } + ], +} diff --git a/release/include/declare_syscalls.h b/release/include/declare_syscalls.h new file mode 100644 index 0000000..c4810f5 --- /dev/null +++ b/release/include/declare_syscalls.h @@ -0,0 +1,51 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +NSTACK_MK_DECL (int, socket, (int, int, int)); +NSTACK_MK_DECL (int, bind, (int, const struct sockaddr *, socklen_t)); +NSTACK_MK_DECL (int, listen, (int, int)); +NSTACK_MK_DECL (int, shutdown, (int, int)); +NSTACK_MK_DECL (int, getsockname, (int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (int, getpeername, (int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (int, getsockopt, (int, int, int, void *, socklen_t *)); +NSTACK_MK_DECL (int, setsockopt, (int, int, int, const void *, socklen_t)); +NSTACK_MK_DECL (int, accept, (int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (int, accept4, + (int, struct sockaddr *, socklen_t *, int flags)); +NSTACK_MK_DECL (int, connect, (int, const struct sockaddr *, socklen_t)); +NSTACK_MK_DECL (ssize_t, recv, (int, void *, size_t, int)); +NSTACK_MK_DECL (ssize_t, send, (int, const void *, size_t, int)); +NSTACK_MK_DECL (ssize_t, read, (int, void *, size_t)); +NSTACK_MK_DECL (ssize_t, write, (int, const void *, size_t)); +NSTACK_MK_DECL (ssize_t, writev, (int, const struct iovec *, int)); +NSTACK_MK_DECL (ssize_t, readv, (int, const struct iovec *, int)); +NSTACK_MK_DECL (ssize_t, sendto, + (int, const void *, size_t, int, const struct sockaddr *, + socklen_t)); +NSTACK_MK_DECL (ssize_t, recvfrom, + (int, void *, size_t, int, struct sockaddr *, socklen_t *)); +NSTACK_MK_DECL (ssize_t, sendmsg, (int, const struct msghdr *, int flags)); +NSTACK_MK_DECL (ssize_t, recvmsg, (int, struct msghdr *, int flags)); +NSTACK_MK_DECL (int, close, (int)); +NSTACK_MK_DECL (int, select, + (int, fd_set *, fd_set *, fd_set *, struct timeval *)); +NSTACK_MK_DECL (int, ioctl, (int, unsigned long, unsigned long)); +NSTACK_MK_DECL (int, fcntl, (int, int, unsigned long)); +NSTACK_MK_DECL (int, epoll_create, (int)); +NSTACK_MK_DECL (int, epoll_ctl, (int, int, int, struct epoll_event *)); +NSTACK_MK_DECL (int, epoll_wait, (int, struct epoll_event *, int, int)); +NSTACK_MK_DECL (pid_t, fork, (void)); +#undef NSTACK_MK_DECL diff --git a/release/include/nsocket_dmm_api.h b/release/include/nsocket_dmm_api.h new file mode 100644 index 0000000..ffdb709 --- /dev/null +++ b/release/include/nsocket_dmm_api.h @@ -0,0 +1,128 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __NSOCKET_DMM_API_H__ +#define __NSOCKET_DMM_API_H__ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/epoll.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +typedef enum +{ + NSTACK_MODEL_TYPE1 = 1, /*nSocket and stack belong to the same process */ + NSTACK_MODEL_TYPE2 = 2, /*nSocket and stack belong to different processes, + *and nStack don't take care the communication between stack and stack adpt + */ + NSTACK_MODEL_TYPE3 = 3, /*nSocket and stack belong to different processes, and sbr was spplied to communicate whit stack */ + NSTACK_MODEL_INVALID, +} nstack_model_deploy_type; + +typedef enum +{ + MBUF_TRANSPORT, + MBUF_UDP, + MBUF_IP, + MBUF_LINK, + MBUF_RAW, + MBUF_MAX_LAYER, +} mbuf_layer; + +/* + *Standard api interface definition. + *these interface is provided by Protocol stack to nStack + */ +typedef struct __nstack_socket_ops +{ +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) ret (*pf##fn) args +#include "declare_syscalls.h" +} nstack_socket_ops; + +/* + *Interactive interface for Protocol stack and nStack defined here + *these interface is provided by Protocol stack to nStack + */ +typedef struct __nstack_extern_ops +{ + int (*module_init) (void); /*stack module init */ + int (*fork_init_child) (pid_t p, pid_t c); /*after fork, stack child process init again if needed. */ + void (*fork_parent_fd) (int s, pid_t p); /*after fork, stack parent process proc again if needed. */ + void (*fork_child_fd) (int s, pid_t p, pid_t c); /*after fork, child record pid for recycle if needed. */ + void (*fork_free_fd) (int s, pid_t p, pid_t c); /*for SOCK_CLOEXEC when fork if needed. */ + unsigned int (*ep_ctl) (int epFD, int proFD, int ctl_ops, struct epoll_event * event, void *pdata); /*when fd add to epoll fd, triggle stack to proc if need */ + unsigned int (*ep_getevt) (int epFD, int profd, unsigned int events); /*check whether some events exist really */ + int (*peak) (int s); /*used for stack-x , isource maybe no need */ +} nstack_extern_ops; + +/* + *The event notify interface provided to the protocol stack by nStack + *these interface is provided by nStack to Protocol stack + */ +typedef struct __nstack_event_cb +{ + void *handle; /*current so file handler */ + int type; /*nstack is assigned to the protocol stack and needs to be passed to nstack when the event is reported */ + int (*event_cb) (void *pdata, int events); +} nstack_event_cb; + +typedef struct __nstack_proc_cb +{ + nstack_socket_ops socket_ops; /*posix socket api */ + nstack_extern_ops extern_ops; /*other proc callback */ +} nstack_proc_cb; + +/* + *Module registration interface. + *ouput param:posix_ps,proc_ops + *input param:event_ops + */ +typedef int (*nstack_stack_registe_fn) (nstack_proc_cb * proc_fun, + nstack_event_cb * event_ops); +typedef void (*io_send_fn) (void *pbuf, void *pargs); +typedef void (*io_recv_cb) (void **pbuf, void *pargs); +typedef int (*recycle_fun) (unsigned int exit_pid, void *pdata, + unsigned short rec_type); + +/*structure type of mbuf*/ +typedef enum +{ + MBUF_TYPE_DPDK, /*mbuf structure type of DPDK */ + MBUF_TYPE_STACKPOOL, /*mbuf structure type of stack-x */ + MBUF_TYPE_INVALID, +} mbuf_type; + +typedef struct +{ + int (*event_notify) (void *pdata, int events); /*event notify */ + int (*ep_pdata_free) (void *pdata); /*pdata free */ + void (*obj_recycle_reg) (unsigned char priority, unsigned short rec_type, void *data, recycle_fun cb_fun); /*source recycle */ + void *(*mbuf_alloc) (mbuf_layer layer, unsigned short length, mbuf_type Type, unsigned short thread_index); /*zero copy memory alloc */ + void (*mbuf_free) (void *p, mbuf_type Type); /*zero copy memory free */ + void (*pkt_send_cb) (void *pbuf, mbuf_type inType, mbuf_type outType, + void *pargs, io_send_fn io_send); + void (*pkt_recv_cb) (void **pbuf, mbuf_type inType, mbuf_type outType, + void *pargs, io_recv_cb io_recv); +} nStack_adpt_fun; + +extern int nstack_adpt_init (nstack_model_deploy_type deploy_type, + nStack_adpt_fun * out_ops, int flag); + +#endif diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..d6c2bdc --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,14 @@ +To run checkstyle : +./checkstyle.sh [-options] + +To modify license: +./lic.sh + +from + CPUB(lwip_writev) + NSTACK_CAL_FUN(fdInf->ops, writev, (fdInf->rlfd, iov, iovcnt), size); + CPUE(lwip_writev) +to + CPUB(writev) + NSTACK_CAL_FUN(fdInf->ops, writev, (fdInf->rlfd, iov, iovcnt), size); + CPUE(writev)
\ No newline at end of file diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100644 index 0000000..07bbe0c --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,120 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +#!/bin/bash + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BUILD_DIR=${DIR}/../build +LIB_PATH=${DIR}/../release/lib64 + +#DPDK download path +DPDK_DOWNLOAD_PATH=/root/dpdk + +#dpdk installation path +DPDK_INSTALL_PATH=/root/dpdk_install/tmp + +#set and check the environment for Ubuntu +#set env +apt-get install git cmake gcc g++ automake libtool wget lsof lshw pciutils net-tools tcpdump + +#check env +isInFile=$(cat /etc/default/grub | grep -c "default_hugepagesz=1G hugepagesz=1G hugepages=8") +if [ $isInFile -eq 0 ]; then + echo "hugepage need to be set, set it by doing" + echo "1. vi /etc/default/grub " + echo "2. add the line GRUB_CMDLINE_LINUX_DEFAULT="default_hugepagesz=1G hugepagesz=1G hugepages=8" " + echo "3. perform " update-grub " " + echo "4. reboot" + exit +else + echo "hugepage has been set already....." +fi + +#DPDK will be having dependancy on linux headers +apt-get install git build-essential linux-headers-`uname -r` + +hugepageTotal=$(cat /proc/meminfo | grep -c "HugePages_Total: 0") +if [ $hugepageTotal -ne 0 ]; then + echo "HugePages_Total is zero" + exit +fi + +hugepageFree=$(cat /proc/meminfo | grep -c "HugePages_Free: 0") +if [ $hugepageFree -ne 0 ]; then + echo "HugePages_Free is zero" + exit +fi + +hugepageSize=$(cat /proc/meminfo | grep -c "Hugepagesize: 0 kB") +if [ $hugepageSize -ne 0 ]; then + echo "Hugepagesize is zero" + exit +fi + +pdpe1gbFlag=$(cat /proc/cpuinfo | grep -c "pdpe1gb") +if [ $pdpe1gbFlag -eq 0 ]; then + echo "/proc/cpuinfo doesn't include pdpe1gb to make hugepage work" + exit +fi + +mkdir /mnt/nstackhuge -p +mount -t hugetlbfs -o pagesize=1G none /mnt/nstackhuge/ + +mkdir -p /var/run/ip_module/ + +#===========build DPDK================ +if [ -d $DPDK_INSTALL_PATH ]; then + rm -rf $DPDK_INSTALL_PATH +fi + +mkdir -p $DPDK_DOWNLOAD_PATH + +cd $DPDK_DOWNLOAD_PATH +rm -rf dpdk-16.04/ +wget https://fast.dpdk.org/rel/dpdk-16.04.tar.xz +tar xvf dpdk-16.04.tar.xz +cd dpdk-16.04/ + +sed -i 's!CONFIG_RTE_EXEC_ENV=.*!CONFIG_RTE_EXEC_ENV=y!1' config/common_base +sed -i 's!CONFIG_RTE_BUILD_SHARED_LIB=.*!CONFIG_RTE_BUILD_SHARED_LIB=y!1' config/common_base +sed -i 's!CONFIG_RTE_LIBRTE_EAL=.*!CONFIG_RTE_LIBRTE_EAL=y!1' config/common_base + +make install T=x86_64-native-linuxapp-gcc DESTDIR=${DPDK_INSTALL_PATH} +cd x86_64-native-linuxapp-gcc +make + +mkdir ${DPDK_INSTALL_PATH}/lib64/ +cp -r ${DPDK_INSTALL_PATH}/lib/* ${DPDK_INSTALL_PATH}/lib64/ + +export LD_LIBRARY_PATH=$LIB_PATH +export NSTACK_LOG_ON=DBG + +#===========build DMM================= +echo "DMM build started....." + +cd $LIB_PATH +rm -rf * + +cd ../../thirdparty/glog/glog-0.3.4/ +sudo autoreconf -ivf + +cd $BUILD_DIR +rm -rf * +cmake -D DMM_DPDK_INSTALL_DIR=$DPDK_INSTALL_PATH .. +make -j 8 + +#DPDK install path need to be updated below if it is changed +sed -i 's!export DPDK_INSTALL_PATH.*!export DPDK_INSTALL_PATH="/root/dpdk_install/tmp/"!1' ../thirdparty/stackpool/release/script/nstack_var.sh +echo "DMM build finished....."
\ No newline at end of file diff --git a/scripts/checkstyle.sh b/scripts/checkstyle.sh new file mode 100644 index 0000000..55f4f73 --- /dev/null +++ b/scripts/checkstyle.sh @@ -0,0 +1,203 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +#!/bin/bash + +CURR_DIR=`dirname $0` +DMM_DIR=${CURR_DIR}/.. +EXIT_CODE=0 +FIX="0" +FULL="0" +CHECKSTYLED_FILES="" +UNCHECKSTYLED_FILES="" +UNCHECK_LIST="" + +SHOW_HELP="1" +FIX="0" +FULL="0" +CHECK="0" + +# user options.... -a, -c, -f + +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -f|--fixstyle) + FIX="1" + SHOW_HELP="0" + shift # past argument + ;; + -c|--checkstyle) + CHECK="1" + SHOW_HELP="0" + shift # past argument + ;; + -a|--all) + FULL="1" + FIX="1" + SHOW_HELP="0" + shift # past argument + ;; + -h|--help) + shift # past argument + ;; + *) # unknown option + shift # past argument + ;; +esac +done + +if [ "${SHOW_HELP}" == "1" ] ; then + echo "help option:" + echo " -f, --fixstyle - fix coding style" + echo " -c, --checkstyle - check coding style" + echo " -a, --all - fix style including dos2unix" + exit +fi +cd ${DMM_DIR} + + +if [ "${FULL}" == "1" ]; then + FILELIST=$(git ls-tree -r HEAD --name-only) +else + FILELIST=$((git diff HEAD~1.. --name-only; git ls-files -m ) | sort -u) +fi + +# Check to make sure we have indent. Exit if we don't with an error message, but +# don't *fail*. +command -v indent > /dev/null +if [ $? != 0 ]; then + echo "Cound not find required command \"indent\". Checkstyle aborted" + exit ${EXIT_CODE} +fi +indent --version + +# Check to make sure we have clang-format. Exit if we don't with an error message, but +# don't *fail*. +HAVE_CLANG_FORMAT=0 +#command -v clang-format > /dev/null +#if [ $? != 0 ]; then +# echo "Could not find command \"clang-format\". Checking C++ files will cause abort" +#else +# clang-format --version +# x=$(echo "" | clang-format 2>&1) +# if [[ "$x" == "" ]]; then +# HAVE_CLANG_FORMAT=1 +# else +# echo "Output produced while formatting empty file (expected empty string):" +# echo "$x" +# echo "Could not find working \"clang-format\". Checking C++ files will cause abort" +# fi +#fi + +for i in ${FILELIST}; do + if [ -f ${i} ] && ( [ ${i: -2} == ".c" ] || [ ${i: -2} == ".h" ] ) && [[ ${i} != *"thirdparty"* ]] && [[ ${i} != *"testcode"* ]] ; then + #grep -q "fd.io coding-style-patch-verification: ON" ${i} + if [ $? == 0 ]; then + EXTENSION=`basename ${i} | sed 's/^\w\+.//'` + case ${EXTENSION} in + hpp|cpp|cc|hh) + CMD="clang-format" + if [ ${HAVE_CLANG_FORMAT} == 0 ]; then + echo "C++ file detected. Abort. (missing clang-format)" + exit ${EXIT_CODE} + fi + ;; + *) + CMD="indent" + ;; + esac + CHECKSTYLED_FILES="${CHECKSTYLED_FILES} ${i}" + if [ ${FIX} == 0 ]; then + if [ "${CMD}" == "clang-format" ] + then + clang-format ${i} > ${i}.out2 + else + indent -gnu -nut ${i} -o ${i}.out1 > /dev/null 2>&1 + indent -gnu -nut ${i}.out1 -o ${i}.out2 > /dev/null 2>&1 + fi + # Remove trailing whitespace + sed -i -e 's/[[:space:]]*$//' ${i}.out2 + diff -q ${i} ${i}.out2 + else + if [ "${CMD}" == "clang-format" ]; then + clang-format -i ${i} > /dev/null 2>&1 + else + indent -nut -sob ${i} + indent -nut -sob ${i} + fi + # Remove trailing whitespace + sed -i -e 's/[[:space:]]*$//' ${i} + fi + if [ $? != 0 ]; then + EXIT_CODE=1 + echo + echo "Checkstyle failed for ${i}." + if [ "${CMD}" == "clang-format" ]; then + echo "Run clang-format as shown to fix the problem:" + echo "clang-format -i ${DMM_DIR}${i}" + else + echo "Run indent (twice!) as shown to fix the problem:" + echo "indent ${DMM_DIR}${i}" + echo "indent ${DMM_DIR}${i}" + fi + fi + if [ -f ${i}.out1 ]; then + rm ${i}.out1 + fi + if [ -f ${i}.out2 ]; then + rm ${i}.out2 + fi + else + UNCHECKSTYLED_FILES="${UNCHECKSTYLED_FILES} ${i}" + fi + else + UNCHECKSTYLED_FILES="${UNCHECKSTYLED_FILES} ${i}" + fi +done + +if [ ${FULL} == "1" ] && [ ${FULL} == "1" ] ; then + for i in ${FILELIST}; do + #egrep -qlr $'\r'\$ ${i} + if [ $? == 0 ] && [[ ${i} != *"thirdparty"* ]] && [[ ${i} != *"testcode"* ]] && [[ ${i} != *"resources"* ]] && [[ ${i} != *"build"* ]] && ( [ ${i: -2} == ".c" ] || [ ${i: -2} == ".h" ] || [ ${i: -3} == ".sh" ] ); then + sed -e 's/\r//g' ${i} > ${i}.tmp + echo "dos2unix conoversion happened for ${i}" + mv ${i}.tmp ${i} + fi + done +fi + +#delete temp files +echo "deleting temp files generated by ${CMD}" + +find . -name "*~" -type f -delete + +if [ ${EXIT_CODE} == 0 ]; then + git status + echo "*******************************************************************" + echo "* DMM CHECKSTYLE SUCCESSFULLY COMPLETED" + echo "*******************************************************************" +else + echo "*******************************************************************" + echo "* DMM CHECKSTYLE FAILED" + echo "* CONSULT FAILURE LOG ABOVE" + echo "* NOTE: Running 'checkstyle.sh -f' *MAY* fix the issue" + echo "*******************************************************************" +fi +cd ${CURR_DIR} +exit ${EXIT_CODE} diff --git a/scripts/header.template b/scripts/header.template new file mode 100644 index 0000000..d3fe9f2 --- /dev/null +++ b/scripts/header.template @@ -0,0 +1,16 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + diff --git a/scripts/header2.template b/scripts/header2.template new file mode 100644 index 0000000..edf38d0 --- /dev/null +++ b/scripts/header2.template @@ -0,0 +1,16 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + diff --git a/scripts/lic.sh b/scripts/lic.sh new file mode 100644 index 0000000..a3c95e2 --- /dev/null +++ b/scripts/lic.sh @@ -0,0 +1,88 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +function remove_copyright_a { + printf "%s\n" 1,14d w q | ed "$1" +} + +function remove_copyright_b { + printf "%s\n" 1,14d w q | ed "$1" +} + +function add_copyright { + if [[ $1 == Makefile ]]; then + ed "$1" <<END +0i +/* + * Copyright (c) 2015 Huawei and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +. +w +q +END + else + ed "$1" <<END +0i +/* + * Copyright (c) 2015 HUAWEI and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +. +w +q +END + fi +} + +shopt -s nullglob globstar +#for file in **/*.[ch]; do + # ./replace_header.sh "$file" +#done + +for i in $(find ./../ -type f) +do + if [[ ${i} != *"thirdparty"* ]] && [[ ${i} != *"testcode"* ]] && [[ ${i} != *"resources"* ]] && [[ ${i} != *"build"* ]] ; then + if [ "${i: -2}" == ".c" ] || [ "${i: -2}" == ".h" ] ; then + ./replace_header.sh "$i" "header.template" + elif [[ "${i}" == *"Makefile" ]] || [ "${i: -4}" == ".txt" ] || [ "${i: -3}" == ".sh" ] ; then + grep -q "Apache License" ${i} + if [ $? != 0 ]; then + ./replace_header.sh "$i" "header2.template" + fi + fi + fi +done diff --git a/scripts/remove_header.awk b/scripts/remove_header.awk new file mode 100644 index 0000000..9e83877 --- /dev/null +++ b/scripts/remove_header.awk @@ -0,0 +1,63 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### +# This script removes ANSI C file header comments +BEGIN { start = 0; incomment = 0;} + +{ + if (start == 0) + { + if (incomment == 0) + { + # C++ single line comment + if (/^\/\//) + { + # print "single line" + } + # single line comment + else if (/^\/\*[^\/]*\*\/$/) + { + # print "single line" + } + # multi line comment + else if (/^\/\*/) + { + #print "start comment" + # start multi line comment + incomment = 1 + } + else + { + # first line that is not a comment, start normal output + print $0; + start = 1; + } + } + else + { + # search for comment end + if (/\*\//) + { + #print "end comment" + incomment = 0; + } + } + } + else + { + # print the complete line for the rest of the file + print $0 + } +} diff --git a/scripts/replace_header.sh b/scripts/replace_header.sh new file mode 100644 index 0000000..3339533 --- /dev/null +++ b/scripts/replace_header.sh @@ -0,0 +1,27 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +#!/bin/bash +SOURCE_DIR=`dirname $0` +if [ $# != 2 ]; then + echo "Usage: replace_header.sh <file> <header.template>" + exit 1 +fi + +cat $SOURCE_DIR/$2 > $SOURCE_DIR/tmp +cat $1 | awk -f $SOURCE_DIR/remove_header.awk >> $SOURCE_DIR/tmp +mv $SOURCE_DIR/tmp $1 + diff --git a/src/adapt/nstack_dmm_adpt.c b/src/adapt/nstack_dmm_adpt.c new file mode 100644 index 0000000..eea2bf1 --- /dev/null +++ b/src/adapt/nstack_dmm_adpt.c @@ -0,0 +1,250 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#include "nsfw_init.h" +#include "nsfw_mem_api.h" +#include "nsfw_recycle_api.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_ps_mem_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_recycle_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" +#include "nstack_eventpoll.h" +#include "nstack_dmm_api.h" +#include "nstack_dmm_adpt.h" +#include "nstack_rd_mng.h" +#include "mgr_com.h" + +int g_same_process = 1; + +extern int nsep_adpt_attach_memory (); +extern int nstack_init_share_res (); +extern int nstack_attach_share_res (); +extern int nsep_adpt_reg_res_mgr (); + +/** + * This just for linux kernel epoll thread + */ +int +nstack_event_callback (void *pdata, int events) +{ + nsep_epollInfo_t *epInfo = (nsep_epollInfo_t *) pdata; + + if (!epInfo) + { + NSSOC_LOGWAR ("!!!!!!!err pdata=%p,get null epInfo", pdata); + return -1; + } +#if 0 + if (epInfo->rmidx >= 0 && epInfo->rmidx != modInx) + { + NSSOC_LOGDBG ("This fd should not issue events"); + return -1; + } +#endif + + NSSOC_LOGDBG ("Got one event]fd=%d,events=%u", epInfo->fd, events); + + sys_arch_lock_with_pid (&epInfo->epiLock); + struct list_node *fdEpiHead = + (struct list_node *) ADDR_SHTOL (epInfo->epiList.head); + struct list_node *node = (struct list_node *) ADDR_SHTOL (fdEpiHead->next); + struct epitem *epi = NULL; + struct eventpoll *ep = NULL; + while (node) + { + + epi = (struct epitem *) ep_list_entry (node, struct epitem, fllink); + + node = (struct list_node *) ADDR_SHTOL (node->next); + ep = (struct eventpoll *) ADDR_SHTOL (epi->ep); + if (!(epi->event.events & events)) + continue; + + /*event should not notice other process */ + if ((ep->pid != get_sys_pid ()) && g_same_process) + { + continue; + } + + sys_arch_lock_with_pid (&ep->lock); + + if (unlikely (ep->ovflist != NSEP_EP_UNACTIVE_PTR)) + { + if (epi->next == NSEP_EP_UNACTIVE_PTR) + { + epi->next = ep->ovflist; + ep->ovflist = (struct epitem *) ADDR_LTOSH (epi); + } + epi->ovf_revents |= events; + NSSOC_LOGDBG ("Add to ovflist]protoFD=%d,event=%d", epInfo->fd, + events); + goto out_unlock; + } + if (!EP_HLIST_NODE_LINKED (&epi->rdllink)) + { + ep_hlist_add_tail (&ep->rdlist, &epi->rdllink); + sem_post (&ep->waitSem); + } + epi->revents |= events; + out_unlock: + sys_sem_s_signal (&ep->lock); + } + sys_sem_s_signal (&epInfo->epiLock); + /* [Remove fdInf->event_sem post] */ + return 0; +} + +int +nstack_adpt_init (nstack_dmm_para * para) +{ + nsfw_mem_para stinfo = { 0 }; + i32 init_ret = 0; + + if (!para) + { + return -1; + } + stinfo.iargsnum = para->argc; + stinfo.pargs = para->argv; + stinfo.enflag = para->proc_type; + if (para->deploy_type >= NSTACK_MODEL_TYPE1) + { + g_same_process = 0; + } + + nsfw_com_attr_set (para->attr.policy, para->attr.pri); + + (void) nstack_framework_setModuleParam (NSFW_MEM_MGR_MODULE, &stinfo); + (void) nstack_framework_setModuleParam (NSFW_MGR_COM_MODULE, + (void *) ((u64) para->proc_type)); + (void) nstack_framework_setModuleParam (NSFW_TIMER_MODULE, + (void *) ((u64) para->proc_type)); + (void) nstack_framework_setModuleParam (NSFW_PS_MODULE, + (void *) ((u64) para->proc_type)); + (void) nstack_framework_setModuleParam (NSFW_PS_MEM_MODULE, + (void *) ((u64) para->proc_type)); + (void) nstack_framework_setModuleParam (NSFW_RECYCLE_MODULE, + (void *) ((u64) para->proc_type)); + (void) nstack_framework_setModuleParam (NSFW_RES_MGR_MODULE, + (void *) ((u64) para->proc_type)); + (void) nstack_framework_setModuleParam (NSFW_SOFT_PARAM_MODULE, + (void *) ((u64) para->proc_type)); + (void) nstack_framework_setModuleParam (NSFW_LOG_CFG_MODULE, + (void *) ((u64) para->proc_type)); + + init_ret = nstack_framework_init (); + if (init_ret < 0) + { + NSFW_LOGERR + ("######################init failed!!!!######################"); + return -1; + } + + if ((para->proc_type != NSFW_PROC_APP) + && (para->proc_type != NSFW_PROC_MAIN)) + { + return 0; + } + + if (para->proc_type == NSFW_PROC_MAIN) + { + if (nstack_init_share_res () != 0) + { + NSFW_LOGERR ("nstack_init_share_res failed"); + return -1; + } + if (nsep_create_memory () != 0) + { + NSFW_LOGERR ("nsep_create_memory failed"); + return -1; + } + + if (nstack_rd_mng_int (0) != 0) + { + NSFW_LOGERR ("nstack_rd_mng_int failed"); + return -1; + } + } + else + { + if (nstack_attach_share_res () != 0) + { + NSFW_LOGERR ("nstack_attach_share_res failed"); + return -1; + } + + /** + * the share memory for epoll is created and usedy be app, don't clear + * it in fault case. + */ + if (0 != nsep_adpt_attach_memory ()) + { + NSFW_LOGERR ("nsep_adpt_attach_memory failed"); + return -1; + } + + if (nstack_rd_mng_int (1) != 0) + { + NSFW_LOGERR ("nstack_rd_mng_int failed"); + return -1; + } + } + + void *pret = + nsfw_recycle_reg_obj (NSFW_REC_PRO_LOWEST, NSFW_REC_NSOCKET_EPOLL, + NULL); + if (!pret) + { + NSFW_LOGERR ("regist recycle failed"); + return -1; + } + (void) nsep_adpt_reg_res_mgr (); + + return 0; +} + +/*just to used to dependence by other module*/ +int +nstack_init_module (void *para) +{ + return 0; +} + +NSFW_MODULE_NAME (NSTACK_DMM_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_MEM_MGR_MODULE) +NSFW_MODULE_DEPENDS (NSFW_MGR_COM_MODULE) +NSFW_MODULE_DEPENDS (NSFW_TIMER_MODULE) +NSFW_MODULE_DEPENDS (NSFW_PS_MODULE) +NSFW_MODULE_DEPENDS (NSFW_PS_MEM_MODULE) +NSFW_MODULE_DEPENDS (NSFW_RECYCLE_MODULE) +NSFW_MODULE_DEPENDS (NSFW_LOG_CFG_MODULE) +NSFW_MODULE_DEPENDS (NSFW_RES_MGR_MODULE) +NSFW_MODULE_DEPENDS (NSFW_SOFT_PARAM_MODULE) +NSFW_MODULE_INIT (nstack_init_module) +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/adapt/nstack_dmm_adpt.h b/src/adapt/nstack_dmm_adpt.h new file mode 100644 index 0000000..e71dce3 --- /dev/null +++ b/src/adapt/nstack_dmm_adpt.h @@ -0,0 +1,62 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#ifndef __NSTACK_DMM_ADPT_H__ +#define __NSTACK_DMM_ADPT_H__ + +typedef enum +{ + NSTACK_MODEL_TYPE1 = 1, /*nSocket and stack belong to the same process */ + NSTACK_MODEL_TYPE2 = 2, /*nSocket and stack belong to different processes, + *and nStack don't take care the communication between stack and stack adpt + */ + NSTACK_MODEL_TYPE3 = 3, /*nSocket and stack belong to different processes, and sbr was spplied to communicate whit stack */ + NSTACK_MODEL_INVALID, +} nstack_model_deploy_type; + +#define NSTACK_DMM_MODULE "nstack_dmm_module" + +typedef struct nsfw_com_attr +{ + int policy; + int pri; +} nsfw_com_attr; + +typedef struct __nstack_dmm_para +{ + nstack_model_deploy_type deploy_type; + int proc_type; + nsfw_com_attr attr; + int argc; + char **argv; +} nstack_dmm_para; + +extern int nstack_adpt_init (nstack_dmm_para * para); +extern int nstack_event_callback (void *pdata, int events); + +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/adapt/nstack_epoll_comm.c b/src/adapt/nstack_epoll_comm.c new file mode 100644 index 0000000..1f3fd02 --- /dev/null +++ b/src/adapt/nstack_epoll_comm.c @@ -0,0 +1,1077 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nstack_eventpoll.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nsfw_recycle_api.h" +#include "nsfw_maintain_api.h" +#include <stdio.h> +#include <stdlib.h> + +nsep_epollManager_t g_epollMng = { + .infoSockMap = NULL, +}; + +/* + * This function will find the epitem of fd in eventpool ep + * This is only used in epoll_ctl add + */ +struct epitem * +nsep_find_ep (struct eventpoll *ep, int fd) +{ + struct ep_rb_node *rbp; + struct epitem *epi, *epir = NULL; + u32_t loopCnt = 0; + for (rbp = ADDR_SHTOL (ep->rbr.rb_node); rbp;) + { + ++loopCnt; + if (loopCnt > NSTACK_MAX_EPITEM_NUM) + break; + + epi = (struct epitem *) ep_rb_entry (rbp, struct epitem, rbn); + if (fd > epi->fd) + { + rbp = (struct ep_rb_node *) ADDR_SHTOL (rbp->rb_right); + } + else if (fd < epi->fd) + { + rbp = (struct ep_rb_node *) ADDR_SHTOL (rbp->rb_left); + } + else + { + epir = epi; + break; + } + } + + if (loopCnt > NSTACK_MAX_EPITEM_NUM) + { + NSSOC_LOGERR ("Loop out of range!!!!"); + } + + return epir; +} + +int +nstack_ep_unlink (struct eventpoll *ep, struct epitem *epi) +{ + int error = ENOENT; + + if (ep_rb_parent (&epi->rbn) == + (struct ep_rb_node *) ADDR_LTOSH_EXT (&epi->rbn)) + { + NSSOC_LOGWAR ("ep_rb_parent == epi->rbn"); + return error; + } + + epi->event.events = 0; + + ep_rb_erase (&epi->rbn, &ep->rbr); + ep_rb_set_parent (&epi->rbn, &epi->rbn); + + if (EP_HLIST_NODE_LINKED (&epi->rdllink)) + { + ep_hlist_del (&ep->rdlist, &epi->rdllink); + } + + return 0; +} + +/** + * @Function nsep_free_epitem + * @Description free nstack epitem + * @param in data - the epitem to be free + * @return 0 on success, -1 on error + */ +int +nsep_free_epitem (struct epitem *data) +{ + struct epitem *epiEntry = (struct epitem *) data; + struct epitem_pool *pool = &nsep_getManager ()->epitemPool; + epiEntry->pid = 0; + NSSOC_LOGDBG ("nsep_free_epitem data:%p", data); + if (res_free (&epiEntry->res_chk)) + { + NSFW_LOGERR ("epitem refree!]epitem=%p", epiEntry); + return 0; + } + + if (nsfw_mem_ring_enqueue (pool->ring, (void *) epiEntry) != 1) + { + NSSOC_LOGERR ("Error to free epitem"); + } + return 0; +} + +NSTACK_STATIC void +nsep_initEpInfo (nsep_epollInfo_t * info) +{ + int iindex = 0; + EP_LIST_INIT (&info->epiList); + NSTACK_SEM_MALLOC (info->epiLock, 1); + NSTACK_SEM_MALLOC (info->freeLock, 1); + + info->rlfd = -1; + info->rmidx = -1; + info->fd = -1; + info->ep = NULL; + info->fdtype = 0; + info->private_data = NULL; + info->epaddflag = 0; + for (iindex = 0; iindex < NSEP_SMOD_MAX; iindex++) + { + info->protoFD[iindex] = -1; + } + (void) nsep_for_pidinfo_init (&(info->pidinfo)); +} + +NSTACK_STATIC void +nsep_destroy_epinfo (nsep_epollInfo_t * info) +{ + // TODO: Here we need to free the semaphore + return; +} + +/** + * @Function nstack_eventpoll_allocShareInfo + * @Description alloc nstack share info + * @param out data - the return value alloced + * @return 0 on success, -1 on error + */ +int +nsep_alloc_epinfo (nsep_epollInfo_t ** data) +{ + nsep_epollInfo_t *head_info = NULL; + + if (NULL == data) + return -1; + NSSOC_LOGDBG ("epinfo alloc begin"); + + nsep_infoPool_t *pool = &nsep_getManager ()->infoPool; + if (0 == nsfw_mem_ring_dequeue (pool->ring, (void *) &head_info) + || NULL == head_info) + { + NSSOC_LOGERR ("epinfo ring alloc failed]pool->ring=%p", pool->ring); + return -1; + } + + res_alloc (&head_info->res_chk); + + nsep_initEpInfo (head_info); + if (0 != nsep_add_pid (&head_info->pidinfo, get_sys_pid ())) + { + NSSOC_LOGERR ("epinfo pid add to headinfo failed]pid=%d,headinfo=%p", + get_sys_pid (), head_info); + } + NSSOC_LOGDBG ("epinfo ring:%p alloc epinfo:%p end", pool->ring, head_info); + *data = head_info; + return 0; +} + +/** + * @Function nstack_eventpoll_freeShareInfo + * @Description free nstack share info + * @param in info - the info to be free + * @return 0 on success, -1 on error + */ +int +nsep_free_epinfo (nsep_epollInfo_t * info) +{ + + if (NULL == info) + return -1; + + nsep_infoPool_t *pool = &nsep_getManager ()->infoPool; + NSSOC_LOGDBG ("nsep_free_epinfo info:%p, pool->ring:%p", info, pool->ring); + nsep_destroy_epinfo (info); + + (void) nsep_for_pidinfo_init (&(info->pidinfo)); + if (res_free (&info->res_chk)) + { + NSFW_LOGERR ("epinfo refree!]epitem=%p", info); + return 0; + } + + if (nsfw_mem_ring_enqueue (pool->ring, (void *) info) != 1) + { + NSSOC_LOGERR ("Errot to free epinfo"); + } + + return 0; +} + +int +nsep_force_epinfo_free (void *data) +{ + nsep_epollInfo_t *info = data; + if (NULL == info) + { + return FALSE; + } + + if (!nsep_is_pid_array_empty (&info->pidinfo)) + { + return FALSE; + } + + res_alloc (&info->res_chk); + (void) nsep_free_epinfo (info); + NSFW_LOGINF ("free epinfo]%p", data); + return TRUE; +} + +int +nsep_force_epitem_free (void *data) +{ + struct epitem *item = data; + if (NULL == item) + { + return FALSE; + } + + if (0 != item->pid) + { + return FALSE; + } + + res_alloc (&item->res_chk); + (void) nsep_free_epitem (item); + NSFW_LOGINF ("free epitem]%p", data); + return TRUE; +} + +int +nsep_force_epevent_free (void *data) +{ + struct eventpoll *epevent = data; + if (NULL == epevent) + { + return FALSE; + } + + if (0 != epevent->pid) + { + return FALSE; + } + + res_alloc (&epevent->res_chk); + (void) nsep_free_eventpoll (epevent); + NSFW_LOGINF ("free event pool]%p", data); + return TRUE; +} + +NSTACK_STATIC int +nsep_init_eventpoll (struct eventpoll *ep) +{ + if (0 != sem_init (&ep->waitSem, 1, 0)) + { + return -1; + } + + NSTACK_SEM_MALLOC (ep->lock, 1); + NSTACK_SEM_MALLOC (ep->sem, 1); + + EP_HLIST_INIT (&ep->rdlist); + ep->ovflist = NSEP_EP_UNACTIVE_PTR; + ep->rbr.rb_node = NULL; + ep->epfd = -1; + return 0; +} + +NSTACK_STATIC void +nsep_destroy_eventpoll (struct eventpoll *ep) +{ + (void) sem_destroy (&ep->waitSem); +} + +/** + * @Function nsep_free_eventpoll + * @Description free nstack eventpoll + * @param in ep - the eventpoll to be free + * @return 0 on success, -1 on error + */ +int +nsep_free_eventpoll (struct eventpoll *ep) +{ + if (!ep) + return -1; + struct eventpoll *epEntry = (struct eventpoll *) ep; + struct eventpoll_pool *pool = &nsep_getManager ()->epollPool; + NSSOC_LOGDBG ("nsep_free_eventpoll ep:%p, epollPool:%p", ep, pool); + nsep_destroy_eventpoll (ep); + ep->pid = 0; + NSSOC_LOGDBG ("Free eventpool"); + if (res_free (&ep->res_chk)) + { + NSFW_LOGERR ("ep refree!]epitem=%p", epEntry); + return 0; + } + + if (nsfw_mem_ring_enqueue (pool->ring, epEntry) != 1) + { + NSSOC_LOGERR ("Errot to free eventpoll"); + } + + return 0; +} + +/** + * @Function nsep_alloc_eventpoll + * @Description alloc nstack eventpoll + * @param out data - the eventpoll alloced + * @return 0 on success, -1 on error + */ +int +nsep_alloc_eventpoll (struct eventpoll **data) +{ + struct eventpoll *p_head = NULL; + struct eventpoll_pool *pool = &nsep_getManager ()->epollPool; + + NSSOC_LOGDBG ("ring:%p alloc eventpool begin", pool->ring); + if (0 == nsfw_mem_ring_dequeue (pool->ring, (void *) &p_head) + || NULL == p_head) + { + NSSOC_LOGERR ("ring alloc eventpool failed]ring=%p", pool->ring); + return -1; + } + + NSSOC_LOGDBG ("alloc eventpool, pid=%u", get_sys_pid ()); + res_alloc (&p_head->res_chk); + p_head->pid = get_sys_pid (); + + if (0 != nsep_init_eventpoll ((struct eventpoll *) p_head)) + { + NSSOC_LOGERR ("p_head init pid alloc failed]p_head=%p,pid=%d", p_head, + get_sys_pid ()); + (void) nsep_free_eventpoll ((struct eventpoll *) p_head); + return -1; + } + + NSSOC_LOGDBG ("ring:%p eventpoll:%p alloc eventpool end", pool->ring, + p_head); + *data = p_head; + return 0; +} + +NSTACK_STATIC int +nsep_init_epitem (struct epitem *epi) +{ + int retVal; + epi->rbn.rb_parent = (struct ep_rb_node *) ADDR_LTOSH_EXT (&epi->rbn); + EP_HLIST_INIT_NODE (&epi->rdllink); + EP_HLIST_INIT_NODE (&epi->lkFDllink); + epi->nwait = 0; + epi->ep = NULL; + epi->next = NSEP_EP_UNACTIVE_PTR; + retVal = + MEMSET_S (&epi->event, sizeof (epi->event), 0, sizeof (epi->event)); + if (EOK != retVal) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", retVal); + return -1; + } + + EP_LIST_INIT_NODE (&epi->fllink); + epi->revents = 0; + epi->ovf_revents = 0; + epi->fd = -1; + epi->private_data = NULL; + + return 0; +} + +/** + * @Function nsep_alloc_epitem + * @Description alloc nstack epitem + * @param out data - the epitem alloced + * @return 0 on success, -1 on error + */ +int +nsep_alloc_epitem (struct epitem **data) +{ + struct epitem *p_head_entry = NULL; + struct epitem_pool *pool = &nsep_getManager ()->epitemPool; + + NSSOC_LOGDBG ("epitem alloc begin.."); + + if (0 == nsfw_mem_ring_dequeue (pool->ring, (void *) &p_head_entry) + || NULL == p_head_entry) + { + NSSOC_LOGERR ("epitem ring alloc failed]ring=%p", pool->ring); + return -1; + } + + res_alloc (&p_head_entry->res_chk); + p_head_entry->pid = get_sys_pid (); + + if (nsep_init_epitem ((struct epitem *) p_head_entry)) + { + (void) nsep_free_epitem ((struct epitem *) p_head_entry); + p_head_entry = NULL; + NSSOC_LOGERR ("ring epitem init failed]ring=%p,epitem=%p", pool->ring, + p_head_entry); + return -1; + } + + NSSOC_LOGDBG ("epitem alloc success..ring:%p head:%p", pool->ring, + p_head_entry); + *data = p_head_entry; + return 0; +} + +typedef int (*nsep_shem_initFn_t) (void *, size_t); + +NSTACK_STATIC int +nsep_epPoolInit (void *addr, size_t lenth) +{ + u32_t pos; + int ret; + + NSSOC_LOGDBG ("Start to init eventpoll pool"); + + ret = MEMSET_S (addr, lenth, 0, lenth); + if (EOK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", ret); + return -1; + } + struct eventpoll *pool = (struct eventpoll *) addr; + nsep_epollManager_t *manager = nsep_getManager (); + manager->epollPool.pool = pool; + + /* init g_nStackInfo.sockPool->nstack_block_array */ + for (pos = 0; pos < NSTACK_MAX_EPOLL_INFO_NUM; pos++) + { + pool[pos].pid = 0; + if (-1 == nsfw_mem_ring_enqueue (manager->epollPool.ring, &pool[pos])) + { + NSSOC_LOGERR ("init fail to enqueue epitem]pos=%u", pos); + return -1; + } + } + return 0; +} + +NSTACK_STATIC int +nsep_epitemPoolInit (void *addr, size_t lenth) +{ + u32_t pos; + int ret; + + NSSOC_LOGDBG ("Start to init epitem pool"); + + ret = MEMSET_S (addr, lenth, 0, lenth); + if (EOK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", ret); + return -1; + } + struct epitem *pool = (struct epitem *) addr; + nsep_epollManager_t *manager = nsep_getManager (); + manager->epitemPool.pool = pool; + + /* init g_nStackInfo.sockPool->nstack_block_array */ + for (pos = 0; pos < NSTACK_MAX_EPITEM_NUM; pos++) + { + pool[pos].pid = 0; + if (-1 == nsfw_mem_ring_enqueue (manager->epitemPool.ring, &pool[pos])) + { + NSSOC_LOGERR ("init fail to enqueue epitem]pos=%u", pos); + return -1; + } + } + return 0; +} + +NSTACK_STATIC int +nsep_epInfoPoolInit (void *addr, size_t lenth) +{ + u32_t pos; + int ret; + + NSSOC_LOGDBG ("shmem info init start"); + + ret = MEMSET_S (addr, lenth, 0, lenth); + if (EOK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", ret); + return -1; + } + nsep_epollInfo_t *pool = (nsep_epollInfo_t *) addr; + nsep_epollManager_t *manager = nsep_getManager (); + manager->infoPool.pool = pool; + + /* init g_nStackInfo.sockPool->nstack_block_array */ + for (pos = 0; pos < NSTACK_MAX_EPOLL_INFO_NUM; pos++) + { + if (nsep_for_pidinfo_init (&(pool[pos].pidinfo))) + { + NSSOC_LOGERR ("pid info init failed]pos=%u", pos); + return -1; + } + + if (-1 == nsfw_mem_ring_enqueue (manager->infoPool.ring, &pool[pos])) + { + NSSOC_LOGERR ("init fail to enqueue epInfo]pos=%u", pos); + return -1; + } + } + + NSSOC_LOGDBG ("nstack_shmen_info_init success"); + return 0; +} + +NSTACK_STATIC int +nsep_create_shmem (size_t length, char *name, nsep_shem_initFn_t initFn) +{ + nsfw_mem_zone pmeminfo; + mzone_handle phandle; + int ret; + + pmeminfo.ireserv = 0; + pmeminfo.isocket_id = NSFW_SOCKET_ANY; + pmeminfo.lenth = length; + ret = + STRCPY_S (pmeminfo.stname.aname, sizeof (pmeminfo.stname.aname), name); + if (EOK != ret) + { + NSSOC_LOGERR ("STRCPY_S failed]name=%s,ret=%d", name, ret); + return -1; + } + pmeminfo.stname.entype = NSFW_SHMEM; + + phandle = nsfw_mem_zone_create (&pmeminfo); + if (NULL == phandle) + { + NSSOC_LOGERR ("create nstack epoll memory failed]name=%s", name); + return -1; + } + + if (0 != initFn ((void *) phandle, length)) + { + NSSOC_LOGERR ("Fail to init memory]name=%s", name); + return -1; + } + + return 0; +} + +NSTACK_STATIC int +nsep_create_epInfoMem () +{ + nsfw_mem_mring pringinfo; + pringinfo.enmptype = NSFW_MRING_MPMC; + pringinfo.isocket_id = NSFW_SOCKET_ANY; + pringinfo.stname.entype = NSFW_SHMEM; + pringinfo.usnum = NSTACK_MAX_EPOLL_INFO_NUM; + + if (-1 == + SPRINTF_S (pringinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EPINFO_RING_NAME)) + { + NSSOC_LOGERR ("Error to create ring]name=%s", pringinfo.stname.aname); + return -1; + } + + mring_handle ring_handle = nsfw_mem_ring_create (&pringinfo); + + if (NULL == ring_handle) + { + NSSOC_LOGERR ("Error to create ring]name=%s", pringinfo.stname.aname); + return -1; + } + + nsep_epollManager_t *manager = nsep_getManager (); + manager->infoPool.ring = ring_handle; + + return nsep_create_shmem (sizeof (nsep_epollInfo_t) * + NSTACK_MAX_EPOLL_INFO_NUM, + MP_NSTACK_EPOLL_INFO_NAME, nsep_epInfoPoolInit); +} + +NSTACK_STATIC int +nsep_adpt_attach_epInfoMem () +{ + nsfw_mem_name name; + name.entype = NSFW_SHMEM; + name.enowner = NSFW_PROC_MAIN; + + if (-1 == + SPRINTF_S (name.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EPINFO_RING_NAME)) + { + NSSOC_LOGERR ("Error to attach ring]name=%s", name.aname); + return -1; + } + mring_handle ring_handle = nsfw_mem_ring_lookup (&name); + + if (NULL == ring_handle) + { + NSSOC_LOGERR ("Error to attach ring]name=%s", name.aname); + return -1; + } + + nsep_epollManager_t *manager = nsep_getManager (); + manager->infoPool.ring = ring_handle; + + if (-1 == + SPRINTF_S (name.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EPOLL_INFO_NAME)) + { + NSSOC_LOGERR ("SPRINTF_S failed]"); + return -1; + } + manager->infoPool.pool = nsfw_mem_zone_lookup (&name); + if (NULL == manager->infoPool.pool) + { + NSSOC_LOGERR ("Error to attach memzone]name=%s", + MP_NSTACK_EPOLL_INFO_NAME); + return -1; + } + return 0; +} + +NSTACK_STATIC int +nsep_create_epItemMem () +{ + nsfw_mem_mring pringinfo; + pringinfo.enmptype = NSFW_MRING_MPMC; + pringinfo.isocket_id = NSFW_SOCKET_ANY; + pringinfo.stname.entype = NSFW_SHMEM; + pringinfo.usnum = NSTACK_MAX_EPITEM_NUM; + + if (-1 == + SPRINTF_S (pringinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EPITEM_RING_NAME)) + { + NSSOC_LOGERR ("Error to create ring]name=%s", pringinfo.stname.aname); + return -1; + } + + mring_handle ring_handle = nsfw_mem_ring_create (&pringinfo); + + if (NULL == ring_handle) + { + NSSOC_LOGERR ("Error to create ring]name=%s", pringinfo.stname.aname); + return -1; + } + + nsep_epollManager_t *manager = nsep_getManager (); + manager->epitemPool.ring = ring_handle; + + return nsep_create_shmem (sizeof (struct epitem) * NSTACK_MAX_EPITEM_NUM, + MP_NSTACK_EPITEM_POOL, nsep_epitemPoolInit); +} + +NSTACK_STATIC int +nsep_adpt_attach_epItemMem () +{ + nsfw_mem_name name; + name.entype = NSFW_SHMEM; + name.enowner = NSFW_PROC_MAIN; + + if (-1 == + SPRINTF_S (name.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EPITEM_RING_NAME)) + { + NSSOC_LOGERR ("Error to attach epItemMem]name=%s", name.aname); + return -1; + } + + mring_handle ring_handle = nsfw_mem_ring_lookup (&name); + + if (NULL == ring_handle) + { + NSSOC_LOGERR ("Error to attach ring]name=%s", name.aname); + return -1; + } + + nsep_epollManager_t *manager = nsep_getManager (); + manager->epitemPool.ring = ring_handle; + + if (-1 == + SPRINTF_S (name.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EPITEM_POOL)) + { + NSSOC_LOGERR ("SPRINTF_S failed]"); + return -1; + } + manager->epitemPool.pool = nsfw_mem_zone_lookup (&name); + if (NULL == manager->epitemPool.pool) + { + NSSOC_LOGERR ("Error to attach memzone]name=%s", MP_NSTACK_EPITEM_POOL); + return -1; + } + return 0; +} + +NSTACK_STATIC int +nsep_create_eventpollMem () +{ + nsfw_mem_mring pringinfo; + pringinfo.enmptype = NSFW_MRING_MPMC; + pringinfo.isocket_id = NSFW_SOCKET_ANY; + pringinfo.stname.entype = NSFW_SHMEM; + pringinfo.usnum = NSTACK_MAX_EPOLL_NUM; + + if (-1 == + SPRINTF_S (pringinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EVENTPOOL_RING_NAME)) + { + NSSOC_LOGERR ("Error to create ring]name=%s", pringinfo.stname.aname); + return -1; + } + + mring_handle ring_handle = nsfw_mem_ring_create (&pringinfo); + + if (NULL == ring_handle) + { + NSSOC_LOGERR ("Error to create ring]name=%s", pringinfo.stname.aname); + return -1; + } + + nsep_epollManager_t *manager = nsep_getManager (); + manager->epollPool.ring = ring_handle; + + return nsep_create_shmem (sizeof (struct eventpoll) * NSTACK_MAX_EPOLL_NUM, + MP_NSTACK_EVENTPOLL_POOL, nsep_epPoolInit); +} + +NSTACK_STATIC int +nsep_adpt_attach_eventpollMem () +{ + nsfw_mem_name name; + name.entype = NSFW_SHMEM; + name.enowner = NSFW_PROC_MAIN; + + if (-1 == + SPRINTF_S (name.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EVENTPOOL_RING_NAME)) + { + NSSOC_LOGERR ("Error to attach ring]name=%s", name.aname); + return -1; + } + + mring_handle ring_handle = nsfw_mem_ring_lookup (&name); + + if (NULL == ring_handle) + { + NSSOC_LOGERR ("Error to create ring]name=%s", name.aname); + return -1; + } + + nsep_epollManager_t *manager = nsep_getManager (); + manager->epollPool.ring = ring_handle; + + int retVal = SPRINTF_S (name.aname, NSFW_MEM_NAME_LENTH, "%s", + MP_NSTACK_EVENTPOLL_POOL); + if (-1 == retVal) + { + NSSOC_LOGERR ("SPRINTF_S faild]ret=%d", retVal); + return -1; + } + manager->epollPool.pool = nsfw_mem_zone_lookup (&name); + if (NULL == manager->epollPool.pool) + { + NSSOC_LOGERR ("Error to attach memzone]name=%s", + MP_NSTACK_EVENTPOLL_POOL); + return -1; + } + + return 0; +} + +int +nsep_create_memory () +{ + typedef int (*nsep_createMemFunc_t) (void); + nsep_createMemFunc_t createFuncs[] = { nsep_create_epInfoMem, + nsep_create_epItemMem, + nsep_create_eventpollMem + }; + + int i = 0; + for (i = 0; + i < (int) (sizeof (createFuncs) / sizeof (nsep_createMemFunc_t)); i++) + { + if (-1 == createFuncs[i] ()) + return -1; + } + + return 0; +} + +int +nsep_adpt_attach_memory () +{ + typedef int (*nsep_attachMemFunc_t) (void); + nsep_attachMemFunc_t attachFuncs[] = { nsep_adpt_attach_epInfoMem, + nsep_adpt_attach_epItemMem, + nsep_adpt_attach_eventpollMem + }; + + int i = 0; + for (i = 0; + i < (int) (sizeof (attachFuncs) / sizeof (nsep_attachMemFunc_t)); i++) + { + if (-1 == attachFuncs[i] ()) + { + NSSOC_LOGERR ("mem attach fail]idx=%d", i); + return -1; + } + } + + return 0; +} + +int +nsep_adpt_reg_res_mgr () +{ + + nsep_epollManager_t *manager = nsep_getManager (); + + nsfw_res_scn_cfg scn_cfg_info = { NSFW_RES_SCAN_ARRAY, 90, 3, 16, + NSTACK_MAX_EPOLL_INFO_NUM / 128, NSTACK_MAX_EPOLL_INFO_NUM, + sizeof (nsep_epollInfo_t), + offsetof (nsep_epollInfo_t, res_chk), + manager->infoPool.pool, + manager->infoPool.ring, + nsep_force_epinfo_free + }; + + nsfw_res_scn_cfg scn_cfg_item = { NSFW_RES_SCAN_ARRAY, 90, 3, 16, + NSTACK_MAX_EPITEM_NUM / 128, NSTACK_MAX_EPITEM_NUM, + sizeof (struct epitem), + offsetof (struct epitem, res_chk), + manager->epitemPool.pool, + manager->epitemPool.ring, + nsep_force_epitem_free + }; + + nsfw_res_scn_cfg scn_cfg_event = { NSFW_RES_SCAN_ARRAY, 90, 3, 16, + NSTACK_MAX_EPOLL_NUM / 128, NSTACK_MAX_EPOLL_NUM, + sizeof (struct eventpoll), + offsetof (struct eventpoll, res_chk), + manager->epollPool.pool, + manager->epollPool.ring, + nsep_force_epevent_free + }; + + (void) nsfw_res_mgr_reg (&scn_cfg_info); + (void) nsfw_res_mgr_reg (&scn_cfg_item); + (void) nsfw_res_mgr_reg (&scn_cfg_event); + return 0; +} + +int +nsep_epitem_remove (nsep_epollInfo_t * pinfo, u32 pid) +{ + struct list_node *prenode = NULL; + struct list_node *nextnode = NULL; + struct epitem *epi = NULL; + u32_t i = 0; + int icnt = 0; + (void) sys_arch_lock_with_pid (&pinfo->epiLock); + /*list head must be not null */ + prenode = (struct list_node *) ADDR_SHTOL (pinfo->epiList.head); + nextnode = (struct list_node *) ADDR_SHTOL (prenode->next); + while ((nextnode) && (i++ <= NSTACK_MAX_EPOLL_INFO_NUM)) + { + epi = ep_list_entry (nextnode, struct epitem, fllink); + if (pid == epi->pid) + { + /*shmem equal to shmem */ + prenode->next = nextnode->next; + nextnode->next = NULL; + (void) nsep_free_epitem (epi); + nextnode = ADDR_SHTOL (prenode->next); + icnt++; + continue; + } + prenode = nextnode; + nextnode = ADDR_SHTOL (nextnode->next); + } + sys_sem_s_signal (&pinfo->epiLock); + if (i >= NSTACK_MAX_EPOLL_INFO_NUM) + { + NSSOC_LOGERR ("free pinfo:%p pid:%u, error maybe happen", pinfo, pid); + } + return icnt; +} + +void +nsep_recycle_epfd (void *epinfo, u32 pid) +{ + struct eventpoll *ep = NULL; + nsep_epollInfo_t *info = (nsep_epollInfo_t *) epinfo; + int ret = 0; + int ileftcnt = 0; + if (!epinfo) + { + NSSOC_LOGDBG ("input null, pid:%u", pid); + return; + } + (void) sys_arch_lock_with_pid (&info->freeLock); + ileftcnt = nsep_del_last_pid (&info->pidinfo, pid); + sys_sem_s_signal (&info->freeLock); + /*no pid exist */ + if (-1 == ileftcnt) + { + return; + } + if (NSTACK_EPOL_FD == info->fdtype) + { + NSSOC_LOGDBG ("recycle epfd:%d epinfo pid:%u begin...", info->fd, pid); + if (0 == ileftcnt) + { + ep = ADDR_SHTOL (info->ep); + info->ep = NULL; + (void) nsep_free_eventpoll (ep); + (void) nsep_free_epinfo (info); + } + return; + } + + NSSOC_LOGDBG ("recycle fd:%d epinfo pid:%u begin...", info->fd, pid); + + ret = nsep_epitem_remove (info, pid); + if (0 != ret) + { + NSSOC_LOGINF ("info:%p, fd:%d pid:%u, %d items was left", info, + info->fd, pid, ret); + } + + if (0 == ileftcnt) + { + NSSOC_LOGINF ("info:%p, fd:%d pid:%u was finally freed", info, info->fd, + pid); + (void) nsep_free_epinfo (info); + } + return; +} + +int +nsep_recyle_ep (u32 pid) +{ + nsep_epollManager_t *manager = nsep_getManager (); + nsep_epollInfo_t *pool = manager->infoPool.pool; + + u32_t pos; + for (pos = 0; pos < NSTACK_MAX_EPOLL_INFO_NUM; pos++) + { + (void) nsep_recycle_epfd (&pool[pos], pid); + } + return 0; +} + +NSTACK_STATIC int +nsep_recyle_epItem (u32 pid) +{ + nsep_epollManager_t *manager = nsep_getManager (); + struct epitem *pool = manager->epitemPool.pool; + + u32_t pos; + for (pos = 0; pos < NSTACK_MAX_EPITEM_NUM; pos++) + { + if (pool[pos].pid != pid) + continue; + + if (-1 == nsep_free_epitem (&pool[pos])) + return -1; + } + + return 0; +} + +NSTACK_STATIC int +nsep_recyle_eventpoll (u32 pid) +{ + nsep_epollManager_t *manager = nsep_getManager (); + struct eventpoll *pool = manager->epollPool.pool; + + u32_t pos; + for (pos = 0; pos < NSTACK_MAX_EPOLL_INFO_NUM; pos++) + { + if (pool[pos].pid != pid) + continue; + + if (-1 == nsep_free_eventpoll (&pool[pos])) + return -1; + } + + return 0; +} + +NSTACK_STATIC + nsfw_rcc_stat nsep_recycle_resource (u32 exit_pid, void *pdata, + u16 rec_type) +{ + NSSOC_LOGINF ("pid:%u recycle", exit_pid); + (void) nsep_recyle_epItem (exit_pid); + (void) nsep_recyle_eventpoll (exit_pid); + return NSFW_RCC_CONTINUE; +} + +NSTACK_STATIC + nsfw_rcc_stat nsep_recyle_lock (u32 pid, void *pdata, u16 rec_type) +{ + nsep_epollManager_t *manager = nsep_getManager (); + nsep_epollInfo_t *pool = manager->infoPool.pool; + u32_t pos; + if (NULL != pool) + { + for (pos = 0; pos < NSTACK_MAX_EPOLL_INFO_NUM; pos++) + { + if (pid == pool[pos].epiLock.locked) + { + pool[pos].epiLock.locked = 0; + NSFW_LOGWAR ("epiLock locked]pos=%u,pid=%u", pos, pid); + } + if (pid == pool[pos].freeLock.locked) + { + pool[pos].freeLock.locked = 0; + NSFW_LOGWAR ("freelock locked]pos=%u,pid=%u", pos, pid); + } + } + } + + struct eventpoll *ev_pool = manager->epollPool.pool; + if (NULL != ev_pool) + { + for (pos = 0; pos < NSTACK_MAX_EPOLL_NUM; pos++) + { + if (pid == ev_pool[pos].lock.locked) + { + ev_pool[pos].lock.locked = 0; + NSFW_LOGWAR ("event_pollLock locked]pos=%u,pid=%u", pos, pid); + } + + if (pid == ev_pool[pos].sem.locked) + { + ev_pool[pos].sem.locked = 0; + NSFW_LOGWAR ("event_pollLock sem]pos=%u,pid=%u", pos, pid); + } + } + } + + return NSFW_RCC_CONTINUE; +} + +REGIST_RECYCLE_OBJ_FUN (NSFW_REC_NSOCKET_EPOLL, + nsep_recycle_resource) +REGIST_RECYCLE_LOCK_REL (nsep_recyle_lock, NULL, NSFW_PROC_NULL) diff --git a/src/adapt/nstack_rd_mng.c b/src/adapt/nstack_rd_mng.c new file mode 100644 index 0000000..64c54a8 --- /dev/null +++ b/src/adapt/nstack_rd_mng.c @@ -0,0 +1,317 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "nstack_rd_data.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nstack_securec.h" + +#define RD_SHMEM_NAME "rd_table" + +#define RD_AGE_MAX_TIME 3 + +rd_route_table *g_rd_table_handle = NULL; + +#define RD_IP_ROUTE_CPY(pnode, name, data) { \ + if (EOK != STRCPY_S((pnode)->data.stack_name, RD_PLANE_NAMELEN, (name))) \ + { \ + NSSOC_LOGERR("STRCPY_S failed]copy_name=%s", name); \ + } \ + (pnode)->data.type = RD_DATA_TYPE_IP; \ + (pnode)->agetime = 0; \ + (pnode)->data.ipdata.addr = (data)->addr; \ + (pnode)->data.ipdata.masklen = (data)->masklen; \ + (pnode)->data.ipdata.resev[0] = 0; \ + (pnode)->data.ipdata.resev[1] = 0; \ +} + +/***************************************************************************** +* Prototype : nstack_rd_mng_int +* Description : rd mng moudule init, create a block memory +* Input : int flag +* Output : None +* Return Value : int +* Calls : +* Called By : nStackMain +*****************************************************************************/ +int +nstack_rd_mng_int (int flag) +{ + int ret; + nsfw_mem_zone zname = { + {NSFW_SHMEM, NSFW_PROC_MAIN, RD_SHMEM_NAME}, + sizeof (rd_route_table), + NSFW_SOCKET_ANY, + 0 + }; + NSSOC_LOGINF ("nstack rd mng init begin]flag=%d", flag); + /*nstack main create, app lookup */ + if (0 == flag) + { + g_rd_table_handle = (rd_route_table *) nsfw_mem_zone_create (&zname); + if (!g_rd_table_handle) + { + NSSOC_LOGERR ("mem create fail]mem name=%s", RD_SHMEM_NAME); + return -1; + } + ret = + MEMSET_S (&(g_rd_table_handle->node[0]), sizeof (rd_route_node), 0, + sizeof (rd_route_node)); + if (EOK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", ret); + return -1; + } + g_rd_table_handle->size = NSTACK_RD_DATA_MAX; + g_rd_table_handle->icnt = 0; + } + else /* static data will not be erased in fault case */ + { + g_rd_table_handle = + (rd_route_table *) nsfw_mem_zone_lookup (&(zname.stname)); + if (!g_rd_table_handle) + { + NSSOC_LOGERR ("mem lookup fail]mem name=%s", RD_SHMEM_NAME); + return -1; + } + } + NSSOC_LOGINF ("nstack rd mng init end flag"); + return 0; +} + +/***************************************************************************** +* Prototype : nstack_rd_ip_node_insert +* Description : insert a rd_ip_data into list +* Input : char *name +* rd_ip_data *data +* Output : None +* Return Value : int +* Calls : +* Called By : nStackMain +*****************************************************************************/ +int +nstack_rd_ip_node_insert (char *name, rd_ip_data * data) +{ + if (!g_rd_table_handle) + { + NSSOC_LOGERR ("nstack rd mng not inited"); + return -1; + } + int iindex = 0; + rd_route_node *pnode = NULL; + int agetime = 0; + int ageindex = -1; + int freeindex = -1; + int repeatflag = 0; + + for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++) + { + pnode = &(g_rd_table_handle->node[iindex]); + /*record the index of first free element */ + if (RD_NODE_USELESS == pnode->flag) + { + if (-1 == freeindex) + { + freeindex = iindex; + NSSOC_LOGINF ("nstack rd ip free element index:%d was found", + iindex); + } + continue; + } + + /*if is using, and repeat just set flag */ + if (RD_NODE_USING == pnode->flag) + { + if (MASK_V (pnode->data.ipdata.addr, pnode->data.ipdata.masklen) == + MASK_V (data->addr, data->masklen)) + { + NSSOC_LOGWAR + ("nstack:%s, old_addr:0x%x index:%d new_addr:0x%x, masklen:%u was repeat", + name, pnode->data.ipdata.addr, iindex, data->addr, + data->masklen); + repeatflag = 1; + } + continue; + } + + /*if flag is deleting, just update the age time, if agetime is on, just set flag to free */ + if (RD_NODE_DELETING == pnode->flag) + { + pnode->agetime++; + if (pnode->agetime >= RD_AGE_MAX_TIME) + { + pnode->flag = RD_NODE_USELESS; + NSSOC_LOGINF + ("nstack rd ip element index:%d addr:0x%x, masklen:%u was delete and set to free", + iindex, pnode->data.ipdata.addr, pnode->data.ipdata.masklen); + } + /*record delete time */ + if (agetime < pnode->agetime) + { + agetime = pnode->agetime; + ageindex = iindex; + } + continue; + } + } + + /*if repeat, just return */ + if (1 == repeatflag) + { + return 0; + } + if (-1 == freeindex) + { + if (-1 != ageindex) + { + freeindex = ageindex; + } + else + { + NSSOC_LOGERR + ("the rd table is full,nstack:%s, rd addr:0x%x, masklen:%u can't be inserted", + name, data->addr, data->masklen); + return -1; + } + } + pnode = &(g_rd_table_handle->node[freeindex]); + /*if no free found, just reuse the big agetime */ + RD_IP_ROUTE_CPY (pnode, name, data); + pnode->flag = RD_NODE_USING; /*last set */ + g_rd_table_handle->icnt++; + NSSOC_LOGINF ("nstack:%s, rd addr:0x%x, masklen:%u index was inserted", + name, data->addr, data->masklen); + return 0; +} + +/***************************************************************************** +* Prototype : nstack_rd_ip_node_delete +* Description : rd data delete +* Input : rd_ip_data *data +* Output : None +* Return Value : int +* Calls : +* Called By : nStackMain +* just set delete flag, becuase +*****************************************************************************/ +int +nstack_rd_ip_node_delete (rd_ip_data * data) +{ + int iindex = 0; + rd_route_node *pnode = NULL; + + if (!g_rd_table_handle) + { + NSSOC_LOGERR ("nstack rd mng not inited"); + return -1; + } + + for (iindex = 0; iindex < NSTACK_RD_DATA_MAX; iindex++) + { + pnode = &(g_rd_table_handle->node[iindex]); + if ((RD_NODE_USING == pnode->flag) + && (MASK_V (pnode->data.ipdata.addr, pnode->data.ipdata.masklen) == + MASK_V (data->addr, data->masklen))) + { + pnode->flag = RD_NODE_DELETING; /*just set deleting state */ + pnode->agetime = 0; + g_rd_table_handle->icnt--; + NSSOC_LOGINF + ("nstack rd delete:%s, addr:0x%x, masklen:%u index:%d was delete", + pnode->data.stack_name, data->addr, data->masklen, iindex); + return 0; + } + } + NSSOC_LOGINF ("nstack rd delete, addr:0x%x, masklen:%u index was not found", + data->addr, data->masklen); + return 0; +} + +/***************************************************************************** +* Prototype : nstack_rd_ip_get +* Description : get rd data from rd table +* Input : char *planename +* rd_route_data **data +* int *num +* Output : None +* Return Value : int +* Calls : +* Called By : +* Note : a block memory was alloc and return by data, +* this need free by caller if return 0, otherwise no need +*****************************************************************************/ +int +nstack_rd_ip_get (rd_route_data ** data, int *num) +{ + rd_route_data *pdata = NULL; + rd_route_node *pnode = NULL; + int size = 0; + int icnt = 0; + int idex = 0; + int ret; + + if (!g_rd_table_handle || !data || !num) + { + NSSOC_LOGERR ("nstack rd mng not inited or input err"); + return -1; + } + size = sizeof (rd_route_data) * g_rd_table_handle->size; + pdata = (rd_route_data *) malloc (size); + if (!pdata) + { + NSSOC_LOGERR ("rd route data malloc fail"); + return -1; + } + ret = MEMSET_S (pdata, size, 0, size); + if (EOK != ret) + { + NSSOC_LOGERR ("MEMSET_S failed]ret=%d", ret); + free (pdata); + return -1; + } + for (icnt = 0; icnt < g_rd_table_handle->size; icnt++) + { + pnode = &(g_rd_table_handle->node[icnt]); + if (RD_NODE_USING == pnode->flag) + { + pdata[idex].type = pnode->data.type; + pdata[idex].ipdata.addr = pnode->data.ipdata.addr; + pdata[idex].ipdata.masklen = pnode->data.ipdata.masklen; + pdata[idex].ipdata.resev[0] = pnode->data.ipdata.resev[0]; + pdata[idex].ipdata.resev[1] = pnode->data.ipdata.resev[1]; + ret = + STRCPY_S (pdata[idex].stack_name, RD_PLANE_NAMELEN, + pnode->data.stack_name); + if (EOK != ret) + { + NSSOC_LOGERR ("STRCPY_S failed]ret=%d", ret); + free (pdata); + return -1; + } + idex++; + } + } + /*if no data fetched , just return fail */ + if (idex == 0) + { + free (pdata); + return -1; + } + *data = pdata; + *num = idex; + return 0; +} diff --git a/src/adapt/nstack_rd_mng.h b/src/adapt/nstack_rd_mng.h new file mode 100644 index 0000000..f1fe7a3 --- /dev/null +++ b/src/adapt/nstack_rd_mng.h @@ -0,0 +1,27 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __NSTACK_RD_MNG_H +#define __NSTACK_RD_MNG_H +#include <stdlib.h> +#include "nstack_rd_data.h" + +int nstack_rd_mng_int (int flag); +int nstack_rd_ip_node_insert (char *name, rd_ip_data * data); +int nstack_rd_ip_node_delete (rd_ip_data * data); +int nstack_rd_ip_get (rd_route_data ** data, int *num); + +#endif diff --git a/src/adapt/nstack_share_res.c b/src/adapt/nstack_share_res.c new file mode 100644 index 0000000..421b5ed --- /dev/null +++ b/src/adapt/nstack_share_res.c @@ -0,0 +1,176 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nstack_share_res.h" +#include "nsfw_mem_api.h" +#include "types.h" +#include "nsfw_recycle_api.h" +#include "nstack_securec.h" +#include "nstack_log.h" +#include "nsfw_maintain_api.h" +#include "nstack_types.h" + +#define NSTACK_SHARE_FORK_LOCK "share_fork_lock" + +typedef struct +{ + common_mem_spinlock_t *fork_share_lock; +} nstack_share_res; + +NSTACK_STATIC nstack_share_res g_nstack_share_res; + +/** global timer tick */ +nstack_tick_info_t g_nstack_timer_tick; + +NSTACK_STATIC int +nstack_create_share_fork_lock () +{ + mzone_handle zone; + nsfw_mem_zone param; + int ret; + + param.isocket_id = -1; + param.lenth = sizeof (common_mem_spinlock_t); + param.stname.entype = NSFW_SHMEM; + + ret = + STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, + NSTACK_SHARE_FORK_LOCK); + if (EOK != ret) + { + NSSOC_LOGERR ("STRCPY_S failed]name=%s,ret=%d", NSTACK_SHARE_FORK_LOCK, + ret); + return -1; + } + + zone = nsfw_mem_zone_create (¶m); + if (!zone) + { + NSSOC_LOGERR ("nsfw_mem_zone_create failed]name=%s", + NSTACK_SHARE_FORK_LOCK); + return -1; + } + + g_nstack_share_res.fork_share_lock = (common_mem_spinlock_t *) zone; + common_mem_spinlock_init (g_nstack_share_res.fork_share_lock); + + NSSOC_LOGDBG ("ok"); + return 0; +} + +NSTACK_STATIC int +nstack_lookup_share_fork_lock () +{ + mzone_handle zone; + nsfw_mem_name param; + + param.entype = NSFW_SHMEM; + param.enowner = NSFW_PROC_MAIN; + if (STRCPY_S (param.aname, NSFW_MEM_NAME_LENTH, NSTACK_SHARE_FORK_LOCK) != + 0) + { + NSSOC_LOGERR ("STRCPY_S failed]name=%s", NSTACK_SHARE_FORK_LOCK); + return -1; + } + + zone = nsfw_mem_zone_lookup (¶m); + if (!zone) + { + NSSOC_LOGERR ("nsfw_mem_zone_lookup failed]name=%s", + NSTACK_SHARE_FORK_LOCK); + return -1; + } + + g_nstack_share_res.fork_share_lock = (common_mem_spinlock_t *) zone; + + NSSOC_LOGDBG ("ok"); + + return 0; +} + +NSTACK_STATIC int +nstack_lookup_share_global_tick () +{ + int ret; + nsfw_mem_name name = {.entype = NSFW_SHMEM,.enowner = NSFW_PROC_MAIN }; + + ret = STRCPY_S (name.aname, NSFW_MEM_NAME_LENTH, NSTACK_GLOBAL_TICK_SHM); + if (EOK != ret) + { + NSSOC_LOGERR ("STRCPY_S failed]name=%s,ret=%d", NSTACK_GLOBAL_TICK_SHM, + ret); + return -1; + } + + g_nstack_timer_tick.tick_ptr = (u64_t *) nsfw_mem_zone_lookup (&name); + if (NULL == g_nstack_timer_tick.tick_ptr) + { + NSPOL_LOGERR ("Failed to lookup global timer tick memory"); + return -1; + } + + NSSOC_LOGDBG ("ok"); + return 0; +} + +int +nstack_init_share_res () +{ + if (nstack_create_share_fork_lock () != 0) + { + return -1; + } + + return 0; +} + +int +nstack_attach_share_res () +{ + if (nstack_lookup_share_fork_lock () != 0) + { + return -1; + } + + if (nstack_lookup_share_global_tick () != 0) + { + return -1; + } + + return 0; +} + +common_mem_spinlock_t * +nstack_get_fork_share_lock () +{ + return g_nstack_share_res.fork_share_lock; +} + +NSTACK_STATIC nsfw_rcc_stat +nstack_recycle_fork_share_lock (u32 exit_pid, void *pdata, u16 rec_type) +{ + NSSOC_LOGDBG ("recycle]pid=%u", exit_pid); + + if (g_nstack_share_res.fork_share_lock + && (g_nstack_share_res.fork_share_lock->locked == exit_pid)) + { + common_mem_spinlock_unlock (g_nstack_share_res.fork_share_lock); + } + + return NSFW_RCC_CONTINUE; +} + +REGIST_RECYCLE_LOCK_REL (nstack_recycle_fork_share_lock, NULL, NSFW_PROC_APP) diff --git a/src/adapt/nstack_share_res.h b/src/adapt/nstack_share_res.h new file mode 100644 index 0000000..5025482 --- /dev/null +++ b/src/adapt/nstack_share_res.h @@ -0,0 +1,66 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef NSTACK_SHARE_RES_H +#define NSTACK_SHARE_RES_H + +#include <stdint.h> +#include "common_mem_spinlock.h" +#include "nstack_log.h" +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NSTACK_VERSION_SHM "nstack_version" +#define NSTACK_VERSION_LEN 128 +COMPAT_PROTECT (NSTACK_VERSION_LEN, 128); +#define MAX_UNMATCH_VER_CNT 32 +COMPAT_PROTECT (MAX_UNMATCH_VER_CNT, 32); + +#define NSTACK_GLOBAL_TICK_SHM "nstack_global_tick" + +typedef struct unmatch_ver_info +{ + int unmatch_count; + char lib_version[NSTACK_VERSION_LEN]; + char first_time_stamp[LOG_TIME_STAMP_LEN]; +} unmatch_ver_info_t; + +#define DFX_TMR_INTERVAL 60000 /*60 seconds */ +typedef struct nstack_tick_info +{ + uint64_t *tick_ptr; // tick from shared memory + uint64_t interval; // tick interval, only used in stack process + /* tick refference, updated periodically and read in tcpip_thread only */ + struct timeval ref_time; // ref tick time + uint64_t ref_tick; // ref tick +} nstack_tick_info_t; + +int nstack_init_share_res (); +int nstack_attach_share_res (); +common_mem_spinlock_t *nstack_get_fork_share_lock (); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt new file mode 100644 index 0000000..78c5a45 --- /dev/null +++ b/src/framework/CMakeLists.txt @@ -0,0 +1,61 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +if(WITH_HAL_LIB) +else() + SET(PAL_H_DIRECTORIES "${DMM_DPDK_INSTALL_DIR}/include/dpdk/") + FILE(GLOB_RECURSE LIBCOMM lib_common_mem/*.c) +endif() + +FILE(GLOB_RECURSE COMMON common/*.c) +FILE(GLOB INIT init/*.c) +FILE(GLOB_RECURSE IPC ipc/*.c) +FILE(GLOB LOG log/*.c) +FILE(GLOB SNAPSHOT snapshot/*.c) +FILE(GLOB STARTUP startup/*.c) +FILE(GLOB MAINTAIN maintain/*.c) +FILE(GLOB TRACEING tracing/*.c) +FILE(GLOB HAL hal/*.c) +FILE(GLOB DMM_ADPT ../adapt/*.c) + + + +ADD_LIBRARY(dmm_api STATIC ${COMMON} ${INIT} ${IPC} ${LOG} ${SNAPSHOT} ${STARTUP} ${MAINTAIN} ${TRACEING} ${HAL} ${DMM_ADPT} ${LIBCOMM}) +if(WITH_SECUREC_LIB) +ADD_DEPENDENCIES(dmm_api SECUREC JSON GLOG) +else() +ADD_DEPENDENCIES(dmm_api JSON GLOG) +endif() +INCLUDE_DIRECTORIES( + dmm_api + PRIVATE + ${JSON_C_SRC} + ${GLOG_SRC} + ${SECUREC_SRC_H} + ipc/mgr_com/ + hal/ + include/ + common/base/include/generic + common/base/include/ + ${PAL_H_DIRECTORIES} + common/base/liblinuxapi/ + common/mem_mgr/include + common/mem_mgr/nsfw_shmem/ + common/mem_mgr/nsfw_nshmem/ + ${CMAKE_CURRENT_LIST_DIR}/../nSocket/nstack/event/ + ${CMAKE_CURRENT_LIST_DIR}/../nSocket/nstack/event/epoll + ${CMAKE_CURRENT_LIST_DIR}/../nSocket/include +)
\ No newline at end of file diff --git a/src/framework/common/base/include/common/common_func.h b/src/framework/common/base/include/common/common_func.h new file mode 100644 index 0000000..fdf2802 --- /dev/null +++ b/src/framework/common/base/include/common/common_func.h @@ -0,0 +1,98 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _RTE_COMM_FUNC_H_ +#define _RTE_COMM_FUNC_H_ + +#ifdef HAL_LIB + +#else + +#define common_mem_rwlock_t rte_rwlock_t +#define common_mem_spinlock_t rte_spinlock_t + //typedef rte_rwlock_t common_mem_rwlock_t; + +#define nsfw_write_lock(plock) rte_rwlock_write_lock(plock) +#define nsfw_write_unlock(plock) rte_rwlock_write_unlock(plock) +#define nsfw_read_lock(plock) rte_rwlock_read_lock(plock) +#define nsfw_read_unlock(plock) rte_rwlock_read_unlock(plock) + +#define common_mem_align32pow2 rte_align32pow2 + +#define common_mem_atomic32_cmpset rte_atomic32_cmpset +#define common_mem_pause rte_pause + +#define COMMON_MEM_MAX_MEMZONE RTE_MAX_MEMZONE + +#define common_mem_atomic32_t rte_atomic32_t + +#define common_mem_memseg rte_memseg +#define common_mem_mem_config rte_mem_config + +#define common_mem_pal_get_configuration rte_eal_get_configuration + + //#define commem_mem_pal_module_info rte_eal_module_info + // +#define common_mem_pal_init rte_eal_init + +#define COMMON_MEM_MEMPOOL_NAMESIZE RTE_MEMPOOL_NAMESIZE + +#define common_mem_memzone_lookup rte_memzone_lookup +#define common_mem_memzone rte_memzone +#define common_mem_atomic32_add_return rte_atomic32_add_return + +#define common_mem_spinlock_init rte_spinlock_init +#define common_mem_spinlock_lock rte_spinlock_lock +#define common_mem_spinlock_unlock rte_spinlock_unlock + +#define common_mem_memzone_free rte_memzone_free +#define common_mem_pktmbuf_pool_create rte_pktmbuf_pool_create + +#define common_mem_pktmbuf_alloc rte_pktmbuf_alloc + +#define common_mem_mempool rte_mempool + +#define common_mem_pktmbuf_free rte_pktmbuf_free +#define common_mem_mbuf rte_mbuf + +#define common_mem_mempool_lookup rte_mempool_lookup + +#define common_mem_ring_get_memsize rte_ring_get_memsize +#define common_mem_ring rte_ring + +#define COMMON_MEM_MAX_MEMSEG RTE_MAX_MEMSEG + +#define common_mem_memzone_reserve rte_memzone_reserve +#define common_mem_rwlock_read_lock rte_rwlock_read_lock +#define common_mem_rwlock_read_unlock rte_rwlock_read_unlock + +#define common_mem_rwlock_write_lock rte_rwlock_write_lock +#define common_mem_rwlock_write_unlock rte_rwlock_write_unlock +#define common_mem_spinlock_trylock rte_spinlock_trylock + +#define common_mem_socket_id rte_socket_id +#define common_mem_malloc_socket_stats rte_malloc_socket_stats + +#define COMMON_MEM_MIN RTE_MIN + +#define common_pal_module_init nscomm_pal_module_init +#define common_memzone_data_reserve_name nscomm_memzone_data_reserve_name +#define common_memzone_data_lookup_name nscomm_memzone_data_lookup_name + +#define common_dump_stack rte_dump_stack +#endif + +#endif // _RTE_COMM_FUNC_H_ diff --git a/src/framework/common/base/include/common/common_mem_api.h b/src/framework/common/base/include/common/common_mem_api.h new file mode 100644 index 0000000..9eb4344 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_api.h @@ -0,0 +1,144 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __COMMON_MEM_API_H__ +#define __COMMON_MEM_API_H__ + +#ifdef HAL_LIB +#else + +#include "rte_atomic.h" +#include "common_mem_spinlock.h" +#include <sys/types.h> +#include <unistd.h> +#include <semaphore.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef NSTACK_LINT_CODE_DISABLE +#define NSTACK_LINT_CODE_DISABLE(code) /*lint -e#code */ +#endif + +#ifndef NSTACK_LINT_CODE_ENABLE +#define NSTACK_LINT_CODE_ENABLE(code) /*lint +e#code */ +#endif + +#define SYS_MBOX_NULL (sys_mbox_t)0 + +typedef sem_t *sys_sem_t_v1; +typedef sem_t sys_sem_st_v1; +typedef struct queue *sys_mbox_t; + +typedef rte_spinlock_t *sys_sem_t_v2; +typedef rte_spinlock_t sys_sem_st_v2; + +#ifndef u32_t +typedef uint32_t u32_t; +#endif + +#ifndef u8_t +typedef uint8_t u8_t; +#endif + +#ifndef s8_t +typedef int8_t s8_t; +#endif + +#ifndef err_t +typedef s8_t err_t; +#endif + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +void sys_sem_signal_s_v2 (sys_sem_t_v2 sem); +void sys_sem_init_v2 (sys_sem_t_v2 sem); + +u32_t sys_arch_sem_wait_s_v2 (sys_sem_t_v2 sem); + +#define SYS_HOST_INITIAL_PID 1 +extern volatile pid_t g_sys_host_pid; +pid_t sys_get_hostpid_from_file (pid_t pid); +static inline pid_t +get_sys_pid () +{ + if (SYS_HOST_INITIAL_PID == g_sys_host_pid) + (void) sys_get_hostpid_from_file (getpid ()); + return g_sys_host_pid; +} + +pid_t updata_sys_pid (); +long sys_now (void); + +#define sys_sem_t sys_sem_t_v2 +#define sys_sem_st sys_sem_st_v2 +#define sys_sem_new(sem, count) sys_sem_new_v2(sem, count) +#define sys_sem_free(sem) sys_sem_free_v2(sem) +#define sys_sem_signal(sem) sys_sem_signal_v2(sem) +#define sys_arch_sem_wait(sem, timeout) sys_arch_sem_wait_v2(sem) +#define sys_arch_sem_trywait(sem) sys_arch_sem_trywait_v2(sem) + +#define sys_sem_init(sem) sys_sem_init_v2(sem) +#define sys_sem_s_signal(sem) sys_sem_signal_s_v2(sem) +#define sys_arch_sem_s_wait(sem, timeout) sys_arch_sem_wait_s_v2(sem) +#define sys_arch_lock_with_pid(sem) (void)sys_arch_lock_with_pid_v2(sem) + +#define BUF_SIZE_FILEPATH 256 +#define STR_PID "pid:" +#define READ_FILE_BUFLEN 512 + +extern pid_t sys_get_hostpid_from_file (pid_t pid); +extern pid_t get_hostpid_from_file (u32_t pid); +extern void get_exec_name_by_pid (pid_t pid, char *task_name, + int task_name_len); + +static inline u32_t +sys_arch_lock_with_pid_v2 (sys_sem_t_v2 sem) +{ + if (SYS_HOST_INITIAL_PID == g_sys_host_pid) + (void) sys_get_hostpid_from_file (getpid ()); + dmm_spinlock_lock_with_pid (sem, g_sys_host_pid); + return 0; +} + +#define NSTACK_SEM_MALLOC(sys_sem,count) \ +{ \ + rte_spinlock_init(&(sys_sem)); \ + /*lint -e506*/\ + if (!(count)) \ + /*lint +e506*/\ + { \ + rte_spinlock_lock(&(sys_sem)); \ + } \ +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif + +#endif /* __COMMON_MEM_API_H__ */ diff --git a/src/framework/common/base/include/common/common_mem_base_type.h b/src/framework/common/base/include/common/common_mem_base_type.h new file mode 100644 index 0000000..01707d9 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_base_type.h @@ -0,0 +1,85 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_BASE_TYPE_H_ +#define _COMMON_MEM_BASE_TYPE_H_ + +#ifdef HAL_LIB + +#else + +#define ALIGN_TYPE uint64_t +#define PTR_ALIGN_TYPE uint64_t + +/*alignment define*/ +#define ALIGNMENT_DEF(name, type, aligntype) \ + union { \ + type name; \ + aligntype name##_align; \ + } + +#define PTR_ALIGNMENT_DEF(name, type) ALIGNMENT_DEF(name, type, PTR_ALIGN_TYPE) + +#define OTHER_ALIGNMENT_DEF(name, type) ALIGNMENT_DEF(name, type, ALIGN_TYPE) + +/* + * * List definitions. + * */ +#define DMM_LIST_HEAD(name, type) \ +struct name { \ + PTR_ALIGNMENT_DEF(lh_first, struct type *); /* first element */ \ +} + +#define DMM_LIST_ENTRY(type) \ +struct { \ + PTR_ALIGNMENT_DEF(le_next, struct type *); /* next element */\ + PTR_ALIGNMENT_DEF(le_prev, struct type **); /* address of previous next element */ \ +} + +/* + * * Tail queue definitions. + * */ +#define _DMM_TAILQ_HEAD(name, type, qual) \ +struct name { \ + PTR_ALIGNMENT_DEF(tqh_first, qual type *); /* first element */ \ + PTR_ALIGNMENT_DEF(tqh_last, qual type * qual *); /* addr of last next element */ \ +} + +#define DMM_TAILQ_HEAD(name, type) _DMM_TAILQ_HEAD(name, struct type,) + +#define _DMM_TAILQ_ENTRY(type, qual) \ +struct { \ + PTR_ALIGNMENT_DEF(tqe_next, qual type *); /* next element */\ + PTR_ALIGNMENT_DEF(tqe_prev, qual type * qual*); /* address of previous next element */\ +} +#define DMM_TAILQ_ENTRY(type) _DMM_TAILQ_ENTRY(struct type,) + +/* + * * Singly-linked Tail queue declarations. + * */ +#define DMM_STAILQ_HEAD(name, type) \ + struct name { \ + PTR_ALIGNMENT_DEF(stqh_first, struct type *); /* first element */ \ + PTR_ALIGNMENT_DEF(stqh_last, struct type **); /* addr of last next element */ \ + } + +#define DMM_STAILQ_ENTRY(type) \ + struct { \ + PTR_ALIGNMENT_DEF(stqe_next, struct type *); /* next element */ \ + } +#endif + +#endif diff --git a/src/framework/common/base/include/common/common_mem_buf.h b/src/framework/common/base/include/common/common_mem_buf.h new file mode 100644 index 0000000..d0d3588 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_buf.h @@ -0,0 +1,75 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_BUF_H_ +#define _COMMON_MEM_BUF_H_ + +#ifdef HAL_LIB +#else + +#include "common_mem_base_type.h" + +typedef enum __DMM_PROC_TYPE +{ + DMM_PROC_T_AUTO = 0, /*auto detect */ + DMM_PROC_T_PRIMARY = 1, /* set to primary */ + DMM_PROC_T_SECONDARY = 2, /* set to seconday */ + DMM_PROC_T_INVALID +} DMM_PROC_TYPE; + +#define DMM_MBUF_RET_OK 0 +#define DMM_MBUF_RET_ERR 1 + +#define LCORE_MAX 128 +#define LCORE_MASK_PER (sizeof(int) * 8) +#define LCORE_MASK_MAX (LCORE_MAX/LCORE_MASK_PER) + +#define LCORE_MASK_SET(ilcoremask, value) \ + if (value < LCORE_MAX) \ + { \ + ilcoremask[(value/LCORE_MASK_PER)] = (int) ( (ilcoremask[(value/LCORE_MASK_PER)]) | (1< (value%LCORE_MASK_PER))); \ + } \ + +#define DMM_HUGTBL_ENABLE 0 +#define DMM_HUGTBL_DISABLE 1 + +typedef struct __common_pal_module_info +{ + int ishare_mem_size; /*shared memory size */ + int ilcoremask[LCORE_MASK_MAX]; + /**/ unsigned char uchugeflag; + unsigned char ucproctype; + unsigned char ucinstance; + unsigned char ucresrv2; +} common_mem_pal_module_info; + +/** + * rte pal module init. + * + * + * @param name + * The name of the buf pool. + */ +int nscomm_pal_module_init (common_mem_pal_module_info * pinfo); + +void *nscomm_memzone_data_reserve_name (const char *name, size_t len, + int socket_id); + +void *nscomm_memzone_data_lookup_name (const char *name); + +#endif + +#endif /* _COMMON_MEM_BUF_H_ */ diff --git a/src/framework/common/base/include/common/common_mem_common.h b/src/framework/common/base/include/common/common_mem_common.h new file mode 100644 index 0000000..1e4cf56 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_common.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_COMMON_H_ +#define _COMMON_MEM_COMMON_H_ + +#ifdef HAL_LIB +#else +#include "rte_common.h" +#endif + +#endif diff --git a/src/framework/common/base/include/common/common_mem_malloc.h b/src/framework/common/base/include/common/common_mem_malloc.h new file mode 100644 index 0000000..68721cd --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_malloc.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_MALLOC_H_ +#define _COMMON_MEM_MALLOC_H_ + +#ifdef HAL_LIB +#else +#include "rte_malloc.h" +#endif + +#endif /* _COMMON_MEM_MALLOC_H_ */ diff --git a/src/framework/common/base/include/common/common_mem_mbuf.h b/src/framework/common/base/include/common/common_mem_mbuf.h new file mode 100644 index 0000000..0bb7696 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_mbuf.h @@ -0,0 +1,40 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/******************************************************************* + Copyright 2017 - 2047, Huawei Tech. Co., Ltd. + ALL RIGHTS RESERVED + +Filename : common_mem_mbuf.h +Description : +Version : 1.1 +********************************************************************/ + +#ifndef _COMMON_MEM_MBUF_H_ +#define _COMMON_MEM_MBUF_H_ + +#ifdef HAL_LIB +#else +#include "rte_mbuf.h" +#include "common_func.h" + +typedef uint32_t (*dmm_mbuf_item_fun) (void *data, void *argv); +int32_t dmm_pktmbuf_pool_iterator (struct common_mem_mempool *mp, + uint32_t start, uint32_t end, + dmm_mbuf_item_fun fun, void *argv); +#endif + +#endif /* _COMMON_MEM_MBUF_H_ */ diff --git a/src/framework/common/base/include/common/common_mem_mempool.h b/src/framework/common/base/include/common/common_mem_mempool.h new file mode 100644 index 0000000..58a8e82 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_mempool.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_MEMPOOL_H_ +#define _COMMON_MEM_MEMPOOL_H_ + +#ifdef HAL_LIB +#else +#include "rte_mempool.h" +#endif + +#endif /* _COMMON_MEM_MEMPOOL_H_ */ diff --git a/src/framework/common/base/include/common/common_mem_memzone.h b/src/framework/common/base/include/common/common_mem_memzone.h new file mode 100644 index 0000000..20e18c2 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_memzone.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_MEMZONE_H_ +#define _COMMON_MEM_MEMZONE_H_ + +#ifdef HAL_LIB +#else +#include "rte_memzone.h" +#endif + +#endif /* _COMMON_MEM_MEMZONE_H_ */ diff --git a/src/framework/common/base/include/common/common_mem_pal.h b/src/framework/common/base/include/common/common_mem_pal.h new file mode 100644 index 0000000..209b8bd --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_pal.h @@ -0,0 +1,30 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_PAL_H_ +#define _COMMON_MEM_PAL_H_ + +#ifdef HAL_LIB +#else + +#include "nsfw_base_linux_api.h" + +/*print the map address*/ +void dmm_addr_print (void); + +#endif + +#endif /* _COMMON_MEM_PAL_H_ */ diff --git a/src/framework/common/base/include/common/common_mem_pal_memconfig.h b/src/framework/common/base/include/common/common_mem_pal_memconfig.h new file mode 100644 index 0000000..65b6e04 --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_pal_memconfig.h @@ -0,0 +1,26 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_PAL_MEMCONFIG_H_ +#define _COMMON_MEM_PAL_MEMCONFIG_H_ + +#ifdef HAL_LIB +#else +#include "rte_eal_memconfig.h" + +#endif + +#endif diff --git a/src/framework/common/base/include/common/common_mem_spinlock.h b/src/framework/common/base/include/common/common_mem_spinlock.h new file mode 100644 index 0000000..23f6b1e --- /dev/null +++ b/src/framework/common/base/include/common/common_mem_spinlock.h @@ -0,0 +1,40 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_SPINLOCK_X86_64_H_ +#define _COMMON_MEM_SPINLOCK_X86_64_H_ + +#ifdef HAL_LIB +#else +#include "rte_spinlock.h" + +static inline void +dmm_spinlock_lock_with_pid (rte_spinlock_t * sl, int pid) +{ + while (!__sync_bool_compare_and_swap (&sl->locked, 0, pid)) + while (sl->locked) + rte_pause (); +} + +static inline int +dmm_spinlock_try_lock_with_pid (rte_spinlock_t * sl, int pid) +{ + return __sync_bool_compare_and_swap (&sl->locked, 0, pid); +} + +#endif + +#endif /* _COMMON_MEM_SPINLOCK_X86_64_H_ */ diff --git a/src/framework/common/base/include/common/common_sys_config.h b/src/framework/common/base/include/common/common_sys_config.h new file mode 100644 index 0000000..552cae3 --- /dev/null +++ b/src/framework/common/base/include/common/common_sys_config.h @@ -0,0 +1,46 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __COMMON_SYS_CONFIG_H_ +#define __COMMON_SYS_CONFIG_H_ + +/* Below compile macro is used only in UT makefile */ +#if (HAL_LIB) +#else +#undef RTE_CACHE_LINE_SIZE +#define RTE_CACHE_LINE_SIZE 64 +#undef RTE_MAX_LCORE +#define RTE_MAX_LCORE 128 +#undef RTE_MAX_NUMA_NODES +#define RTE_MAX_NUMA_NODES 8 +#undef RTE_MAX_MEMSEG +#define RTE_MAX_MEMSEG 256 +#undef RTE_MAX_MEMZONE +#define RTE_MAX_MEMZONE 2560 +#undef RTE_MAX_TAILQ +#define RTE_MAX_TAILQ 32 +#undef RTE_ARCH_X86 +#define RTE_ARCH_X86 1 +#undef RTE_ARCH_64 +#define RTE_ARCH_64 1 +#undef RTE_PKTMBUF_HEADROOM +#define RTE_PKTMBUF_HEADROOM 128 +#undef RTE_MEMPOOL_CACHE_MAX_SIZE +#define RTE_MEMPOOL_CACHE_MAX_SIZE 512 + +#endif + +#endif // __COMMON_SYS_CONFIG_H_ diff --git a/src/framework/common/base/include/common/generic/common_mem_rwlock.h b/src/framework/common/base/include/common/generic/common_mem_rwlock.h new file mode 100644 index 0000000..2eed259 --- /dev/null +++ b/src/framework/common/base/include/common/generic/common_mem_rwlock.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_RWLOCK_H_ +#define _COMMON_MEM_RWLOCK_H_ + +#ifdef HAL_LIB +#else +#include "rte_rwlock.h" +#endif + +#endif /* _COMMON_MEM_RWLOCK_H_ */ diff --git a/src/framework/common/base/include/common_pal_bitwide_adjust.h b/src/framework/common/base/include/common_pal_bitwide_adjust.h new file mode 100644 index 0000000..850742b --- /dev/null +++ b/src/framework/common/base/include/common_pal_bitwide_adjust.h @@ -0,0 +1,222 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_PAL_BITWIDE_ADJUST_H_ +#define _COMMON_PAL_BITWIDE_ADJUST_H_ + +#ifdef HAL_LIB +#include "pal_bitwide_adjust.h" +#else +#define MODULE(name) (1) + +#include "common_mem_common.h" + +#include "common_func.h" + +#ifndef _UT_FUN_DISABLE_ +/*define struct for UT restore global variant*/ +struct ut_adjust_global +{ + void **ut_PrimAddr2LocalMap; + uint64_t *ut_LocalAddr2PrimMap; + void *ut_LocalBaseAddr; + void *ut_LocalMaxAddr; + void *ut_LocalCfgAddrBase; + uint64_t ut_PrimBaseAddr; + uint64_t ut_PrimMaxAddr; + uint64_t ut_PrimCfgAddrBase; + int ut_PrimSameFlg; + uint64_t ut_LBitMask; + int ut_LBitMaskLen; + struct common_mem_memseg *ut_PMemSegArry; + void **ut_LMegAddrArry; +}; +#endif + +#define ALIGN_SIZET(size) ((uint64_t)(size)) +#define ALIGN_PTR(PTR) ((uint64_t)(PTR)) + +extern struct common_mem_memseg *g_PMemSegArry; +extern void **g_LMegAddrArry; + +/*get Local Seg addr by segIdx*/ +#define HMEM_SEG_LVADDR(segid) (g_LMegAddrArry[segid]) +/*get SegIDX by PrimSegAddr, just get the arry Idx of g_PMemSegArry*/ +#define HMEM_SEGID(segaddr) ((struct common_mem_memseg*)segaddr - &(g_PMemSegArry[0])) + +/***************************************************************** +Parameters : LMegAddrArry[] Loacol common_mem_memseg addr Arry + SegNum common_mem_memseg Num. +Return : +Description : init g_PrimAddr2LocalMap g_LocalAddr2PrimMap while the process start +*****************************************************************/ +void *pal_shddr_to_laddr (uint64_t shaddr); +uint64_t pal_laddr_to_shddr (void *laddr); +int dmm_pal_addr_align (); + +extern int g_PrimSameFlg; + +/* if __NSTACK_MAIN__ is defined, no need do addr trans*/ +#ifndef __NSTACK_MAIN__ +/* g_PrimSameFlg check should be done before calling cast functions */ + +/*share memory address to local virtual address*/ +#define ADDR_SHTOL(addr) (g_PrimSameFlg ? ((void*) (addr)) : pal_shddr_to_laddr((uint64_t)(addr))) + +/*local virtual address to share memory address according to memseg*/ +#define ADDR_LTOSH(addr) (g_PrimSameFlg ? ((uint64_t)(addr)) : pal_laddr_to_shddr((void*)(addr))) + +#define PTR_SHTOL(type, addr) ((type)ADDR_SHTOL(addr)) + +/*local virtual address to share memory address; for compatible, not delete ADDR_LTOSH_EXT*/ +#define ADDR_LTOSH_EXT(addr) ADDR_LTOSH(addr) +#else +/*share memory address to local virtual address*/ +#define ADDR_SHTOL(addr) ((void*)(addr)) + +/*local virtual address to share memory address according to memseg*/ +#define ADDR_LTOSH(addr) ((uint64_t)(addr)) + +#define PTR_SHTOL(type, addr) ((type)(addr)) + +/*local virtual address to share memory address; for compatible, not delete ADDR_LTOSH_EXT*/ +#define ADDR_LTOSH_EXT(addr) ADDR_LTOSH(addr) +#endif + +#if MODULE("list") +#define COMMON_LIST_INSERT_HEAD(lhead, lelm, field) do { \ + if (((lelm)->field.le_next_align = (lhead)->lh_first_align) != ((typeof((lhead)->lh_first_align))(long)NULL)) \ + ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align))->field.le_prev_align = \ + ADDR_LTOSH(&(lelm)->field.le_next); \ + (lhead)->lh_first_align = ADDR_LTOSH(lelm); \ + (lelm)->field.le_prev_align = ADDR_LTOSH(&(lhead)->lh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_LIST_REMOVE(lelm, field) do { \ + if ((lelm)->field.le_next_align != ((typeof((lelm)->field.le_next_align))ALIGN_PTR(NULL))) \ + ((typeof((lelm)->field.le_next))ADDR_SHTOL((lelm)->field.le_next_align))->field.le_prev_align = \ + (lelm)->field.le_prev_align; \ + if (EOK != (MEMCPY_S((typeof((lelm)->field.le_prev))ADDR_SHTOL((lelm)->field.le_prev_align), \ + sizeof((lelm)->field.le_next_align), \ + &((lelm)->field.le_next_align), \ + sizeof((lelm)->field.le_next_align)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + return;\ + }\ +} while (/*CONSTCOND*/0) + +#define COMMON_LIST_EMPTY(lhead) ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align) == NULL) +#define COMMON_LIST_FIRST(lhead) ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align)) +#define COMMON_LIST_NEXT(lelm, field) ((typeof((lelm)->field.le_next))ADDR_SHTOL((lelm)->field.le_next_align)) + +#endif + +#if MODULE("tailq") + +#define COMMON_TAILQ_INSERT_TAIL(lhead, lelm, field) do { \ + (lelm)->field.tqe_next_align = (typeof((lelm)->field.tqe_next_align))NULL; \ + (lelm)->field.tqe_prev_align = (lhead)->tqh_last_align; \ + typeof((lhead)->tqh_last_align) tempelm = ADDR_LTOSH(lelm);\ + if (EOK != (MEMCPY_S(ADDR_SHTOL((lhead)->tqh_last_align), sizeof(tempelm), &tempelm, sizeof(tempelm)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + (lhead)->tqh_last_align = ADDR_LTOSH(&(lelm)->field.tqe_next); \ +} while (/*CONSTCOND*/0) + +#define COMMON_TAILQ_FOREACH(lvar, lhead, field) \ + for ((lvar) = (typeof(lvar))ADDR_SHTOL((lhead)->tqh_first_align); \ + (lvar); \ + (lvar) = (typeof(lvar))ADDR_SHTOL((lvar)->field.tqe_next_align)) + +#define COMMON_TAILQ_REMOVE(lhead, lelm, field) do { \ + if (((lelm)->field.tqe_next_align) != (typeof((lelm)->field.tqe_next_align))NULL) \ + ((typeof((lelm)->field.tqe_next))ADDR_SHTOL((lelm)->field.tqe_next_align))->field.tqe_prev_align = \ + (lelm)->field.tqe_prev_align; \ + else \ + (lhead)->tqh_last_align = (lelm)->field.tqe_prev_align; \ + if (EOK != (MEMCPY_S(ADDR_SHTOL((lelm)->field.tqe_prev_align), \ + sizeof((lelm)->field.tqe_next_align), \ + &((lelm)->field.tqe_next_align), \ + sizeof((lelm)->field.tqe_next_align)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + } while (/*CONSTCOND*/0) + +/* + * Tail queue functions. + */ +#define COMMON_TAILQ_INIT(head) do { \ + (head)->tqh_first_align = (typeof((head)->tqh_first_align))NULL; \ + (head)->tqh_last_align = ADDR_LTOSH(&(head)->tqh_first); \ + } while (/*CONSTCOND*/0) + +/* + * Tail queue access methods. + */ +#define COMMON_TAILQ_EMPTY(head) ((head)->tqh_first_align == (typeof((head)->tqh_first_align))NULL) +#define COMMON_TAILQ_FIRST(head) ((typeof((head)->tqh_first))ADDR_SHTOL((head)->tqh_first_align)) +#define COMMON_TAILQ_NEXT(elm, field) ((typeof((elm)->field.tqe_next))ADDR_SHTOL((elm)->field.tqe_next_align)) + +#endif + +#if MODULE("stailq") +/* +* Singly-linked Tail queue functions. +*/ +#define COMMON_STAILQ_INIT(head) do { \ + (head)->stqh_first_align = ALIGN_PTR(NULL); \ + (head)->stqh_last_align = ADDR_LTOSH(&(head)->stqh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next_align = ALIGN_PTR(NULL); \ + typeof((head)->stqh_last_align) telm = ADDR_LTOSH(elm);\ + if (EOK != (MEMCPY_S(ADDR_SHTOL((head)->stqh_last_align), sizeof(telm), &telm, sizeof(telm))))\ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + (head)->stqh_last_align = ADDR_LTOSH(&(elm)->field.stqe_next); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first_align = \ + ((typeof((head)->stqh_first))ADDR_SHTOL((head)->stqh_first_align))->field.stqe_next_align) == \ + (PTR_ALIGN_TYPE)NULL) \ + (head)->stqh_last_align = ADDR_LTOSH(&(head)->stqh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_FOREACH(var, head, field) \ + for ((var) = ADDR_SHTOL((head)->stqh_first_align); \ + (var); \ + (var) = ADDR_SHTOL((var)->field.stqe_next_align)) + +/* +* Singly-linked Tail queue access methods. +*/ + +#define COMMON_STAILQ_EMPTY(head) ((head)->stqh_first_align == (PTR_ALIGN_TYPE)NULL) + +#define COMMON_STAILQ_FIRST(head) (ADDR_SHTOL((head)->stqh_first_align)) + +#define COMMON_STAILQ_NEXT(elm, field) (ADDR_SHTOL((elm)->field.stqe_next_align)) +#endif + +#endif + +#endif diff --git a/src/framework/common/base/include/nsfw_base_linux_api.h b/src/framework/common/base/include/nsfw_base_linux_api.h new file mode 100644 index 0000000..83b5a32 --- /dev/null +++ b/src/framework/common/base/include/nsfw_base_linux_api.h @@ -0,0 +1,58 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_BASE_LINUX_API_H_ +#define _NSFW_BASE_LINUX_API_H_ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/epoll.h> +#include <unistd.h> + +int nsfw_base_socket (int, int, int); +int nsfw_base_bind (int, const struct sockaddr *, socklen_t); +int nsfw_base_listen (int, int); +int nsfw_base_shutdown (int, int); +int nsfw_base_getsockname (int, struct sockaddr *, socklen_t *); +int nsfw_base_getpeername (int, struct sockaddr *, socklen_t *); +int nsfw_base_getsockopt (int, int, int, void *, socklen_t *); +int nsfw_base_setsockopt (int, int, int, const void *, socklen_t); +int nsfw_base_accept (int, struct sockaddr *, socklen_t *); +int nsfw_base_accept4 (int, struct sockaddr *, socklen_t *, int flags); +int nsfw_base_connect (int, const struct sockaddr *, socklen_t); +ssize_t nsfw_base_recv (int, void *, size_t, int); +ssize_t nsfw_base_send (int, const void *, size_t, int); +ssize_t nsfw_base_read (int, void *, size_t); +ssize_t nsfw_base_write (int, const void *, size_t); +ssize_t nsfw_base_writev (int, const struct iovec *, int); +ssize_t nsfw_base_readv (int, const struct iovec *, int); +ssize_t nsfw_base_sendto (int, const void *, size_t, int, + const struct sockaddr *, socklen_t); +ssize_t nsfw_base_recvfrom (int, void *, size_t, int, struct sockaddr *, + socklen_t *); +ssize_t nsfw_base_sendmsg (int, const struct msghdr *, int flags); +ssize_t nsfw_base_recvmsg (int, struct msghdr *, int flags); +int nsfw_base_close (int); +int nsfw_base_select (int, fd_set *, fd_set *, fd_set *, struct timeval *); +int nsfw_base_ioctl (int, unsigned long, unsigned long); +int nsfw_base_fcntl (int, int, unsigned long); +int nsfw_base_epoll_create (int); +int nsfw_base_epoll_create1 (int); +int nsfw_base_epoll_ctl (int, int, int, struct epoll_event *); +int nsfw_base_epoll_wait (int, struct epoll_event *, int, int); +pid_t nsfw_base_fork (void); + +#endif diff --git a/src/framework/common/base/include/nsfw_getopt.h b/src/framework/common/base/include/nsfw_getopt.h new file mode 100644 index 0000000..f1394cf --- /dev/null +++ b/src/framework/common/base/include/nsfw_getopt.h @@ -0,0 +1,50 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef NSFW_GETOPT_H +#define NSFW_GETOPT_H 1 + +#if defined(__cplusplus) +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define nsfw_no_argument 0 +#define nsfw_required_argument 1 +#define nsfw_optional_argument 2 + +struct option +{ + const char *name; + int has_arg; + int *flag; + int val; +}; + +int nsfw_getopt_long (int argc, char *const argv[], const char *optstring, + const struct option *longopts, int *longindex); + +extern char *nsfw_optarg; +extern int nsfw_optind, nsfw_opterr, nsfw_optopt; + +#if defined(__cplusplus) +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/framework/common/base/liblinuxapi/base_linux_api_declare.h b/src/framework/common/base/liblinuxapi/base_linux_api_declare.h new file mode 100644 index 0000000..943ae04 --- /dev/null +++ b/src/framework/common/base/liblinuxapi/base_linux_api_declare.h @@ -0,0 +1,51 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +BASE_MK_DECL (int, socket, (int, int, int)); +BASE_MK_DECL (int, bind, (int, const struct sockaddr *, socklen_t)); +BASE_MK_DECL (int, listen, (int, int)); +BASE_MK_DECL (int, shutdown, (int, int)); +BASE_MK_DECL (int, getsockname, (int, struct sockaddr *, socklen_t *)); +BASE_MK_DECL (int, getpeername, (int, struct sockaddr *, socklen_t *)); +BASE_MK_DECL (int, getsockopt, (int, int, int, void *, socklen_t *)); +BASE_MK_DECL (int, setsockopt, (int, int, int, const void *, socklen_t)); +BASE_MK_DECL (int, accept, (int, struct sockaddr *, socklen_t *)); +BASE_MK_DECL (int, accept4, (int, struct sockaddr *, socklen_t *, int flags)); +BASE_MK_DECL (int, connect, (int, const struct sockaddr *, socklen_t)); +BASE_MK_DECL (ssize_t, recv, (int, void *, size_t, int)); +BASE_MK_DECL (ssize_t, send, (int, const void *, size_t, int)); +BASE_MK_DECL (ssize_t, read, (int, void *, size_t)); +BASE_MK_DECL (ssize_t, write, (int, const void *, size_t)); +BASE_MK_DECL (ssize_t, writev, (int, const struct iovec *, int)); +BASE_MK_DECL (ssize_t, readv, (int, const struct iovec *, int)); +BASE_MK_DECL (ssize_t, sendto, + (int, const void *, size_t, int, const struct sockaddr *, + socklen_t)); +BASE_MK_DECL (ssize_t, recvfrom, + (int, void *, size_t, int, struct sockaddr *, socklen_t *)); +BASE_MK_DECL (ssize_t, sendmsg, (int, const struct msghdr *, int flags)); +BASE_MK_DECL (ssize_t, recvmsg, (int, struct msghdr *, int flags)); +BASE_MK_DECL (int, close, (int)); +BASE_MK_DECL (int, select, + (int, fd_set *, fd_set *, fd_set *, struct timeval *)); +BASE_MK_DECL (int, ioctl, (int, unsigned long, unsigned long)); +BASE_MK_DECL (int, fcntl, (int, int, unsigned long)); +BASE_MK_DECL (int, epoll_create, (int)); +BASE_MK_DECL (int, epoll_create1, (int)); +BASE_MK_DECL (int, epoll_ctl, (int, int, int, struct epoll_event *)); +BASE_MK_DECL (int, epoll_wait, (int, struct epoll_event *, int, int)); +BASE_MK_DECL (pid_t, fork, (void)); +#undef BASE_MK_DECL diff --git a/src/framework/common/base/liblinuxapi/nsfw_base_linux_api.c b/src/framework/common/base/liblinuxapi/nsfw_base_linux_api.c new file mode 100644 index 0000000..de98877 --- /dev/null +++ b/src/framework/common/base/liblinuxapi/nsfw_base_linux_api.c @@ -0,0 +1,628 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_base_linux_api.h" +#include "nstack_log.h" +#include <pthread.h> +#include <stdio.h> +#include <errno.h> +#include <dlfcn.h> + +#define NSFW_BASE_OK 0 +#define NSFW_BASE_FAIL (-1) + +#define nsfw_call_ret(symbol, para){ \ + if (NSFW_BASE_OK != nsfw_posix_api_init()) \ + { \ + return NSFW_BASE_FAIL; \ + } \ + if (g_nsfw_posix_api.pf##symbol) \ + { \ + return g_nsfw_posix_api.pf##symbol para;\ + } \ + errno = ENOSYS; \ + return NSFW_BASE_FAIL; \ +} + +typedef enum +{ + BASE_STATE_INIT, + BASE_STATE_SUCCESS, + BASE_STATE_FAIL +} nsfw_base_state; + +typedef struct __base_linux_api +{ +#define BASE_MK_DECL(ret, fn, args) ret (*pf##fn) args; +#include "base_linux_api_declare.h" +} base_linux_api; + +nsfw_base_state g_nsfw_mudule_state = BASE_STATE_INIT; +pthread_mutex_t g_nsfw_init_mutex = PTHREAD_MUTEX_INITIALIZER; +base_linux_api g_nsfw_posix_api = { 0 }; + +void *g_linux_lib_handle = (void *) 0; + +int +nsfw_posix_symbol_load () +{ + g_linux_lib_handle = dlopen ("libc.so.6", RTLD_NOW | RTLD_GLOBAL); + if ((void *) 0 == g_linux_lib_handle) + { + /* optimize dlopen err print */ + NSSOC_LOGERR ("cannot dlopen libc.so.6] err_string=%s", dlerror ()); + return NSFW_BASE_FAIL; + } +#define BASE_MK_DECL(ret, fn, args) \ + g_nsfw_posix_api.pf##fn = (typeof(g_nsfw_posix_api.pf##fn))dlsym(g_linux_lib_handle, #fn); +#include <base_linux_api_declare.h> + + return NSFW_BASE_OK; +} + +/***************************************************************** +Parameters : void +Return : +Description : linux posix api init with threadonce +*****************************************************************/ +static inline int +nsfw_posix_api_init () +{ + int iret = NSFW_BASE_OK; + + /*if init already, just return success, if init fail before, just return err */ + if (BASE_STATE_INIT != g_nsfw_mudule_state) + { + return (BASE_STATE_SUCCESS == + g_nsfw_mudule_state ? NSFW_BASE_OK : NSFW_BASE_FAIL); + } + + (void) pthread_mutex_lock (&g_nsfw_init_mutex); + + /*if init already, just return success, if init fail before, just return err */ + if (BASE_STATE_INIT != g_nsfw_mudule_state) + { + (void) pthread_mutex_unlock (&g_nsfw_init_mutex); + return (BASE_STATE_SUCCESS == + g_nsfw_mudule_state ? NSFW_BASE_OK : NSFW_BASE_FAIL); + } + + iret = nsfw_posix_symbol_load (); + if (NSFW_BASE_OK == iret) + { + g_nsfw_mudule_state = BASE_STATE_SUCCESS; + } + else + { + g_nsfw_mudule_state = BASE_STATE_FAIL; + } + + (void) pthread_mutex_unlock (&g_nsfw_init_mutex); + return iret; +} +/* *INDENT-OFF* */ +/***************************************************************************** +* Prototype : nsfw_base_socket +* Description : linux socket api +* Input : int a +* int b +* int c +* Output : None +* Return Value : int +* Calls : +* Called By : + +* +*****************************************************************************/ +int nsfw_base_socket(int a, int b, int c) +{ + nsfw_call_ret(socket, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_bind +* Description : linux fd bind api +* Input : int a +* const struct sockaddr* b +* socklen_t c +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_bind(int a, const struct sockaddr* b, socklen_t c) +{ + nsfw_call_ret(bind, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_listen +* Description : linux fd listen api +* Input : int a +* int b +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_listen(int a, int b) +{ + nsfw_call_ret(listen, (a, b)) +} + +/***************************************************************************** +* Prototype : nsfw_base_shutdown +* Description : linux shutdown api +* Input : int a +* int b +* Output : None +* Return Value : int +* Calls : +* Called By : +* +* +*****************************************************************************/ +int nsfw_base_shutdown(int a, int b) +{ + nsfw_call_ret(shutdown, (a, b)) +} + +/***************************************************************************** +* Prototype : nsfw_base_getsockname +* Description : linux getsockname api +* Input : int a +* struct sockaddr* b +* socklen_t* c +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_getsockname(int a, struct sockaddr* b, socklen_t* c) +{ + nsfw_call_ret(getsockname, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_getpeername +* Description : linux getpername api +* Input : int a +* struct sockaddr* b +* socklen_t* c +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_getpeername(int a, struct sockaddr* b, socklen_t* c) +{ + nsfw_call_ret(getpeername, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_getsockopt +* Description : linux getsockopt api +* Input : int a +* int b +* int c +* void* d +* socklen_t* e +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_getsockopt(int a, int b, int c, void* d, socklen_t* e) +{ + nsfw_call_ret(getsockopt, (a, b, c, d, e)) +} + +/***************************************************************************** +* Prototype : nsfw_base_setsockopt +* Description : linux setsockopt api +* Input : int a +* int b +* int c +* const void* d +* socklen_t e +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int nsfw_base_setsockopt(int a, int b, int c, const void* d, socklen_t e) +{ + nsfw_call_ret(setsockopt, (a, b, c, d, e)) +} + +/***************************************************************************** +* Prototype : nsfw_base_accept +* Description : linux accept api +* Input : int a +* struct sockaddr* b +* socklen_t* c +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int nsfw_base_accept(int a, struct sockaddr* b, socklen_t* c) +{ + nsfw_call_ret(accept, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_accept4 +* Description : linux accept4 api +* Input : int a +* struct sockaddr* b +* socklen_t* c +* int flags +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int nsfw_base_accept4(int a, struct sockaddr* b, socklen_t* c, int flags) +{ + nsfw_call_ret(accept4, (a, b, c, flags)) +} + +/***************************************************************************** +* Prototype : nsfw_base_connect +* Description : linux connect api +* Input : int a +* const struct sockaddr* b +* socklen_t c +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_connect(int a, const struct sockaddr* b, socklen_t c) +{ + nsfw_call_ret(connect, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_recv +* Description : linux recv api +* Input : int a +* void* b +* size_t c +* int d +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_base_recv(int a, void* b, size_t c, int d) +{ + nsfw_call_ret(recv, (a, b, c, d)) +} + +/***************************************************************************** +* Prototype : nsfw_base_send +* Description : linux send api +* Input : int a +* const void* b +* size_t c +* int d +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_base_send(int a, const void* b, size_t c, int d) +{ + nsfw_call_ret(send, (a, b, c, d)) +} + +/***************************************************************************** +* Prototype : nsfw_base_read +* Description : linux read api +* Input : int a +* void* b +* size_t c +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_base_read(int a, void* b, size_t c) +{ + nsfw_call_ret(read, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_write +* Description : linux write api +* Input : int a +* const void* b +* size_t c +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_base_write(int a, const void* b, size_t c) +{ + nsfw_call_ret(write, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_writev +* Description : linux writev api +* Input : int a +* const struct iovec * b +* int c +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +*****************************************************************************/ +ssize_t nsfw_base_writev(int a, const struct iovec * b, int c) +{ + nsfw_call_ret(writev, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_readv +* Description : linux readv api +* Input : int a +* const struct iovec * b +* int c +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_base_readv(int a, const struct iovec * b, int c) +{ + nsfw_call_ret(readv, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_sendto +* Description : linux sendto api +* Input : int a +* const void * b +* size_t c +* int d +* const struct sockaddr *e +* socklen_t f +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +*****************************************************************************/ +ssize_t nsfw_base_sendto(int a, const void * b, size_t c, int d, const struct sockaddr *e, socklen_t f) +{ + nsfw_call_ret(sendto, (a, b, c, d, e, f)) +} + +/***************************************************************************** +* Prototype : nsfw_base_recvfrom +* Description : linux recvfrom api +* Input : int a +* void *b +* size_t c +* int d +* struct sockaddr *e +* socklen_t *f +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +*****************************************************************************/ +ssize_t nsfw_base_recvfrom(int a, void *b, size_t c, int d,struct sockaddr *e, socklen_t *f) +{ + nsfw_call_ret(recvfrom, (a, b, c, d, e, f)) +} + +/***************************************************************************** +* Prototype : nsfw_base_sendmsg +* Description : linux sendmsg api +* Input : int a +* const struct msghdr *b +* int flags +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_base_sendmsg(int a, const struct msghdr *b, int flags) +{ + nsfw_call_ret(sendmsg, (a, b, flags)) +} + +/***************************************************************************** +* Prototype : nsfw_base_recvmsg +* Description : linux recvmsg api +* Input : int a +* struct msghdr *b +* int flags +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_base_recvmsg(int a, struct msghdr *b, int flags) +{ + nsfw_call_ret(recvmsg, (a, b, flags)) +} + +/***************************************************************************** +* Prototype : nsfw_base_close +* Description : linux close api +* Input : int a +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_close(int a) +{ + nsfw_call_ret(close, (a)) +} + +/***************************************************************************** +* Prototype : nsfw_base_select +* Description : linux select api +* Input : int a +* fd_set *b +* fd_set *c +* fd_set *d +* struct timeval *e +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int nsfw_base_select(int a, fd_set *b, fd_set *c, fd_set *d, struct timeval *e) +{ + nsfw_call_ret(select, (a, b, c, d, e)) +} + +/***************************************************************************** +* Prototype : nsfw_base_ioctl +* Description : linux ioctl api +* Input : int a +* unsigned long b +* unsigned long c +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_ioctl(int a, unsigned long b, unsigned long c) +{ + nsfw_call_ret(ioctl, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_fcntl +* Description : linux fcntl api +* Input : int a +* int b +* unsigned long c +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_fcntl(int a, int b, unsigned long c) +{ + nsfw_call_ret(fcntl, (a, b, c)) +} + +/***************************************************************************** +* Prototype : nsfw_base_epoll_create +* Description : linux epoll_create api +* Input : int a +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_epoll_create(int a) +{ + nsfw_call_ret(epoll_create, (a)) +} + +/***************************************************************************** +* Prototype : nsfw_base_epoll_create1 +* Description : linux epoll_create1 api +* Input : int a +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_epoll_create1(int a) +{ + nsfw_call_ret(epoll_create1, (a)) +} + +/***************************************************************************** +* Prototype : nsfw_base_epoll_ctl +* Description : linux epoll_ctl api +* Input : int a +* int b +* int c +* struct epoll_event *d +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_epoll_ctl(int a, int b, int c, struct epoll_event *d) +{ + nsfw_call_ret(epoll_ctl, (a, b, c, d)) +} + +/***************************************************************************** +* Prototype : nsfw_base_epoll_wait +* Description : linux epoll_wait api +* Input : int a +* struct epoll_event *b +* int c +* int d +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int nsfw_base_epoll_wait(int a, struct epoll_event *b, int c, int d) +{ + nsfw_call_ret(epoll_wait, (a, b, c, d)) +} + +/***************************************************************************** +* Prototype : nsfw_base_fork +* Description : linux fork api +* Input : void +* Output : None +* Return Value : pid_t +* Calls : +* Called By : +* +*****************************************************************************/ +pid_t nsfw_base_fork(void) +{ + nsfw_call_ret(fork, ()) +} +/* *INDENT-ON* */ diff --git a/src/framework/common/base/liblinuxapi/nsfw_getopt.c b/src/framework/common/base/liblinuxapi/nsfw_getopt.c new file mode 100644 index 0000000..ac7d6bf --- /dev/null +++ b/src/framework/common/base/liblinuxapi/nsfw_getopt.c @@ -0,0 +1,455 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include "nsfw_getopt.h" +#include "nstack_log.h" + +char *nsfw_optarg = NULL; +int nsfw_optind = 1; +int nsfw_opterr = 1; +int nsfw_optopt = '?'; +NSTACK_STATIC char *nsfw_optnext = NULL; +NSTACK_STATIC int posixly_correct = -1; +NSTACK_STATIC int handle_nonopt_argv = 0; +NSTACK_STATIC int start = 0; +NSTACK_STATIC int end = 0; + +NSTACK_STATIC void check_gnu_extension (const char *optstring); +NSTACK_STATIC int nsfw_getopt_internal (int argc, char *const argv[], + const char *optstring, + const struct option *longopts, + int *longindex, int long_only); +NSTACK_STATIC int nsfw_getopt_shortopts (int argc, char *const argv[], + const char *optstring, + int long_only); +NSTACK_STATIC int nsfw_getopt_longopts (int argc, char *const argv[], + char *arg, const char *optstring, + const struct option *longopts, + int *longindex, int *long_only_flag); +NSTACK_STATIC inline int nsfw_getopt_internal_check_opts (const char + *optstring); +NSTACK_STATIC inline int nsfw_getopt_check_optind (); +NSTACK_STATIC inline int nsfw_getopt_internal_init (char *const argv[]); +NSTACK_STATIC inline int nsfw_getopt_longopts_check_longonly (int + *long_only_flag, + const char + *optstring, + char *const + argv[]); + +NSTACK_STATIC void +check_gnu_extension (const char *optstring) +{ + if (optstring[0] == '+' || getenv ("POSIXLY_CORRECT") != NULL) + { + posixly_correct = 1; + } + else + { + posixly_correct = 0; + } + if (optstring[0] == '-') + { + handle_nonopt_argv = 1; + } + else + { + handle_nonopt_argv = 0; + } +} + +int +nsfw_getopt_long (int argc, char *const argv[], const char *optstring, + const struct option *longopts, int *longindex) +{ + return nsfw_getopt_internal (argc, argv, optstring, longopts, longindex, 0); +} + +NSTACK_STATIC inline int +nsfw_getopt_internal_check_opts (const char *optstring) +{ + if (NULL == optstring) + { + return -1; + } + + if (nsfw_optopt == '?') + { + nsfw_optopt = 0; + } + + if (posixly_correct == -1) + { + check_gnu_extension (optstring); + } + + if (nsfw_optind == 0) + { + check_gnu_extension (optstring); + nsfw_optind = 1; + nsfw_optnext = NULL; + } + + switch (optstring[0]) + { + case '+': + case '-': + optstring++; + break; + default: + break; + } + return 0; +} + +NSTACK_STATIC inline int +nsfw_getopt_check_optind () +{ + if (nsfw_optind <= 0) + nsfw_optind = 1; + return 0; +} + +NSTACK_STATIC inline int +nsfw_getopt_internal_init (char *const argv[]) +{ + if (nsfw_optnext == NULL && start != 0) + { + int last_pos = nsfw_optind - 1; + + nsfw_optind -= end - start; + (void) nsfw_getopt_check_optind (); + + while (start < end--) + { + int i; + char *arg = argv[end]; + + for (i = end; i < last_pos; i++) + { + int j = i + 1; + ((char **) argv)[i] = argv[j]; + } + ((char const **) argv)[i] = arg; + last_pos--; + } + start = 0; + } + return 0; +} + +NSTACK_STATIC int +nsfw_getopt_internal (int argc, char *const argv[], const char *optstring, + const struct option *longopts, int *longindex, + int long_only) +{ + + (void) nsfw_getopt_internal_check_opts (optstring); + + (void) nsfw_getopt_internal_init (argv); + + if (nsfw_optind >= argc) + { + nsfw_optarg = NULL; + return -1; + } + if (nsfw_optnext == NULL) + { + const char *arg = argv[nsfw_optind]; + if (*arg != '-') + { + if (handle_nonopt_argv) + { + nsfw_optarg = argv[nsfw_optind++]; + start = 0; + return 1; + } + else if (posixly_correct) + { + nsfw_optarg = NULL; + return -1; + } + else + { + int i; + + start = nsfw_optind; + for (i = nsfw_optind + 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + end = i; + break; + } + } + if (i == argc) + { + nsfw_optarg = NULL; + return -1; + } + nsfw_optind = i; + arg = argv[nsfw_optind]; + } + } + if (strcmp (arg, "--") == 0) + { + nsfw_optind++; + return -1; + } + if (longopts != NULL && arg[1] == '-') + { + return nsfw_getopt_longopts (argc, argv, argv[nsfw_optind] + 2, + optstring, longopts, longindex, NULL); + } + } + + if (nsfw_optnext == NULL) + { + nsfw_optnext = argv[nsfw_optind] + 1; + } + if (long_only) + { + int long_only_flag = 0; + int rv = + nsfw_getopt_longopts (argc, argv, nsfw_optnext, optstring, longopts, + longindex, &long_only_flag); + if (!long_only_flag) + { + nsfw_optnext = NULL; + return rv; + } + } + + return nsfw_getopt_shortopts (argc, argv, optstring, long_only); +} + +NSTACK_STATIC int +nsfw_getopt_shortopts (int argc, char *const argv[], const char *optstring, + int long_only) +{ + int opt = *nsfw_optnext; + const char *os; + if (optstring != NULL) + { + os = strchr (optstring, opt); + } + else + { + /* here try to keep same with below behavior */ + return '?'; + } + + if (os == NULL) + { + nsfw_optarg = NULL; + if (long_only) + { + if (':' != optstring[0]) + { + NSFW_LOGERR ("unrecognized option] argv_0=%s, netopt=%s", + argv[0], nsfw_optnext); + } + nsfw_optind++; + nsfw_optnext = NULL; + } + else + { + nsfw_optopt = opt; + if (':' != optstring[0]) + { + NSFW_LOGERR ("invalid option] argv_0=%s, opt=%c", argv[0], opt); + } + if (*(++nsfw_optnext) == 0) + { + nsfw_optind++; + nsfw_optnext = NULL; + } + } + return '?'; + } + if (os[1] == ':') + { + if (nsfw_optnext[1] == 0) + { + nsfw_optind++; + if (os[2] == ':') + { + nsfw_optarg = NULL; + } + else + { + if (nsfw_optind == argc) + { + nsfw_optarg = NULL; + nsfw_optopt = opt; + if (':' != optstring[0]) + { + NSFW_LOGERR + ("option requires an argument] argv_0=%s, opt=%c", + argv[0], opt); + } + return optstring[0] == ':' ? ':' : '?'; + } + nsfw_optarg = argv[nsfw_optind]; + nsfw_optind++; + } + } + else + { + nsfw_optarg = nsfw_optnext + 1; + nsfw_optind++; + } + nsfw_optnext = NULL; + } + else + { + nsfw_optarg = NULL; + if (nsfw_optnext[1] == 0) + { + nsfw_optnext = NULL; + nsfw_optind++; + } + else + { + nsfw_optnext++; + } + } + return opt; +} + +NSTACK_STATIC inline int +nsfw_getopt_longopts_check_longonly (int *long_only_flag, + const char *optstring, + char *const argv[]) +{ + if (long_only_flag) + { + *long_only_flag = 1; + } + else + { + if (':' != optstring[0]) + { + NSFW_LOGERR ("unrecognized option] argv_0=%s, option=%s", argv[0], + argv[nsfw_optind]); + } + nsfw_optind++; + } + return 0; +} + +NSTACK_STATIC int +nsfw_getopt_longopts (int argc, char *const argv[], char *arg, + const char *optstring, const struct option *longopts, + int *longindex, int *long_only_flag) +{ + char *val = NULL; + const struct option *opt; + size_t namelen; + int idx; + + if ((longopts == NULL) || (arg == NULL)) + { + return -1; + } + + for (idx = 0; longopts[idx].name != NULL; idx++) + { + opt = &longopts[idx]; + namelen = strlen (opt->name); + + if (strncmp (arg, opt->name, namelen) == 0) + { + switch (arg[namelen]) + { + case '\0': + switch (opt->has_arg) + { + case nsfw_required_argument: + nsfw_optind++; + + if (nsfw_optind == argc) + { + nsfw_optarg = NULL; + nsfw_optopt = opt->val; + if (':' != optstring[0]) + { + NSFW_LOGERR + ("requires an argument] argv_0=%s, opt name=%s", + argv[0], opt->name); + } + return optstring[0] == ':' ? ':' : '?'; + } + + val = argv[nsfw_optind]; + break; + + default: + break; + } + + goto found; + + case '=': + if (opt->has_arg == nsfw_no_argument) + { + const char *hyphens = + (argv[nsfw_optind][1] == '-') ? "--" : "-"; + nsfw_optind++; + nsfw_optarg = NULL; + nsfw_optopt = opt->val; + if (':' != optstring[0]) + { + NSFW_LOGERR + ("doesn't allow an argument] argv_0=%s, hyphens=%s, opt name=%s", + argv[0], hyphens, opt->name); + } + return '?'; + } + + val = arg + namelen + 1; + goto found; + + default: + break; + } + } + } + + (void) nsfw_getopt_longopts_check_longonly (long_only_flag, optstring, + argv); + return '?'; + +found: + nsfw_optarg = val; + nsfw_optind++; + + if (opt->flag) + { + *opt->flag = opt->val; + } + + if (longindex) + { + *longindex = idx; + } + + return opt->flag ? 0 : opt->val; +} diff --git a/src/framework/common/base/liblinuxapi/nsfw_lock_file.c b/src/framework/common/base/liblinuxapi/nsfw_lock_file.c new file mode 100644 index 0000000..0ec196f --- /dev/null +++ b/src/framework/common/base/liblinuxapi/nsfw_lock_file.c @@ -0,0 +1,174 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "common_mem_api.h" + +#include "nstack_log.h" +#include "nsfw_maintain_api.h" +#include "nsfw_mgr_com_api.h" + +#include "nsfw_base_linux_api.h" +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_FILE_PATH_LEN 128 +#define LOCK_FOLDER "/ip_module/" +#define LOCK_SUFFIX ".pid" + +#define read_lock(fd, offset, whence, len) nsfw_lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len)) +#define readw_lock(fd, offset, whence, len) nsfw_lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len)) +#define write_lock(fd, offset, whence, len) nsfw_lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len)) +#define writew_lock(fd, offset, whence, len) nsfw_lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len)) +#define un_lock(fd, offset, whence, len) nsfw_lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len)) + +i32 +nsfw_lock_reg (i32 fd, i32 cmd, i32 type, off_t offset, i32 whence, off_t len) +{ + struct flock lock_file; + lock_file.l_type = type; + lock_file.l_start = offset; + lock_file.l_whence = whence; + lock_file.l_len = len; + return (fcntl (fd, cmd, &lock_file)); +} + +/***************************************************************************** +* Prototype : nsfw_proc_start_with_lock +* Description : lock file start +* Input : u8 proc_type +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_proc_start_with_lock (u8 proc_type) +{ + NSFW_LOGINF ("lock_file init]type=%u", proc_type); + char *module_name = nsfw_get_proc_name (proc_type); + if (NULL == module_name) + { + NSFW_LOGERR ("proc type error]proc_type=%u", proc_type); + return 0; + } + + const char *directory = NSFW_DOMAIN_DIR; + const char *home_dir = getenv ("HOME"); + + if (getuid () != 0 && home_dir != NULL) + { + directory = home_dir; + } + + int ret; + char lock_fpath[NSFW_FILE_PATH_LEN] = { 0 }; + ret = STRCPY_S (lock_fpath, NSFW_FILE_PATH_LEN, directory); + if (EOK != ret) + { + NSFW_LOGERR ("lock init STRCPY_S failed]ret=%d", ret); + return -1; + } + + ret = STRCAT_S (lock_fpath, NSFW_FILE_PATH_LEN, LOCK_FOLDER); + if (EOK != ret) + { + NSFW_LOGERR ("lock init STRCAT_S failed]ret=%d", ret); + return -1; + } + + ret = STRCAT_S (lock_fpath, NSFW_FILE_PATH_LEN, module_name); + if (EOK != ret) + { + NSFW_LOGERR ("lock init STRCAT_S failed]ret=%d", ret); + return -1; + } + + ret = STRCAT_S (lock_fpath, NSFW_FILE_PATH_LEN, LOCK_SUFFIX); + if (EOK != ret) + { + NSFW_LOGERR ("lock init STRCAT_S failed]ret=%d", ret); + return -1; + } + + i32 fd; + if ((fd = open (lock_fpath, O_RDWR | O_CREAT, 0640)) == -1) + { /* file permission no large than 0640 */ + NSFW_LOGERR ("open lock file error!]path=%s,error = %d", lock_fpath, + errno); + return -1; + } + + int rc = nsfw_set_close_on_exec (fd); + if (rc == -1) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", fd, errno); + return -1; + } + + if (write_lock (fd, 0, SEEK_SET, 0) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("get lock file error!]path=%s,error = %d", lock_fpath, + errno); + return -1; + } + + char buf[32] = { 0 }; + if (ftruncate (fd, 0) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("ftruncate file error!]path=%s,error = %d", lock_fpath, + errno); + return -1; + } + + ret = + SNPRINTF_S (buf, sizeof (buf), sizeof (buf) - 1, "%ld", (long) getpid ()); + if (-1 == ret) + { + NSTCP_LOGERR ("SNPRINTF_S failed]ret=%d", ret); + (void) nsfw_base_close (fd); + return -1; + } + + if (write (fd, buf, strlen (buf) + 1) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("write file error!]path=%s,error = %d", lock_fpath, errno); + return -1; + } + + return 0; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/common/data_struct/eprb_tree.c b/src/framework/common/data_struct/eprb_tree.c new file mode 100644 index 0000000..c8af17c --- /dev/null +++ b/src/framework/common/data_struct/eprb_tree.c @@ -0,0 +1,492 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "eprb_tree.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* + * This function returns the first node (in sort order) of the tree. + */ +struct ep_rb_node * +ep_rb_first (const struct ep_rb_root *root) +{ + if (NULL == root) + return NULL; + + struct ep_rb_node *n; + n = (struct ep_rb_node *) ADDR_SHTOL (root->rb_node); + + if (!n) + { + return NULL; + } + + while (n->rb_left) + { + n = (struct ep_rb_node *) ADDR_SHTOL (n->rb_left); + } + + return n; +} + +void +__ep_rb_rotate_left (struct ep_rb_node *X, struct ep_rb_root *root) +{ + /************************** + * rotate Node X to left * + **************************/ + struct ep_rb_node *Y = (struct ep_rb_node *) ADDR_SHTOL (X->rb_right); + + /* estblish X->Right link */ + X->rb_right = Y->rb_left; + + if (Y->rb_left != NULL) + { + ((struct ep_rb_node *) ADDR_SHTOL (Y->rb_left))->rb_parent = + (struct ep_rb_node *) ADDR_LTOSH_EXT (X); + } + + /* estblish Y->Parent link */ + Y->rb_parent = X->rb_parent; + + if (X->rb_parent) + { + struct ep_rb_node *xParent = + (struct ep_rb_node *) ADDR_SHTOL (X->rb_parent); + + if (X == ADDR_SHTOL (xParent->rb_left)) + { + xParent->rb_left = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + } + else + { + xParent->rb_right = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + } + } + else + { + root->rb_node = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + } + + /* link X and Y */ + Y->rb_left = (struct ep_rb_node *) ADDR_LTOSH_EXT (X); + X->rb_parent = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + + return; +} + +void +__ep_rb_rotate_right (struct ep_rb_node *X, struct ep_rb_root *root) +{ + /**************************** + * rotate Node X to right * + ****************************/ + struct ep_rb_node *Y = (struct ep_rb_node *) ADDR_SHTOL (X->rb_left); + + /* estblish X->Left link */ + X->rb_left = Y->rb_right; + + if (Y->rb_right != NULL) + { + ((struct ep_rb_node *) ADDR_SHTOL (Y->rb_right))->rb_parent = + (struct ep_rb_node *) ADDR_LTOSH_EXT (X); + } + + /* estblish Y->Parent link */ + Y->rb_parent = X->rb_parent; + + if (X->rb_parent) + { + struct ep_rb_node *xParent = + (struct ep_rb_node *) ADDR_SHTOL (X->rb_parent); + + if (X == (struct ep_rb_node *) ADDR_SHTOL (xParent->rb_right)) + { + xParent->rb_right = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + } + else + { + xParent->rb_left = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + } + } + else + { + root->rb_node = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + } + + /* link X and Y */ + Y->rb_right = (struct ep_rb_node *) ADDR_LTOSH_EXT (X); + X->rb_parent = (struct ep_rb_node *) ADDR_LTOSH_EXT (Y); + + return; +} + +#define EP_RBTREE_PARENT(X) ((struct ep_rb_node*) ADDR_SHTOL((X)->rb_parent)) +#define EP_RBTREE_GRANDF(X) EP_RBTREE_PARENT(EP_RBTREE_PARENT(X)) + +/* X, Y are for application */ +void +ep_rb_insert_color (struct ep_rb_node *X, struct ep_rb_root *root) +{ + /************************************* + * maintain red-black tree balance * + * after inserting node X * + *************************************/ + /* check red-black properties */ + while (X != (struct ep_rb_node *) ADDR_SHTOL (root->rb_node) + && EP_RBTREE_PARENT (X)->color == EP_RB_RED) + { + /* we have a violation */ + if (X->rb_parent == EP_RBTREE_GRANDF (X)->rb_left) + { + struct ep_rb_node *Y = + (struct ep_rb_node *) ADDR_SHTOL (EP_RBTREE_GRANDF (X)->rb_right); + + if (Y && Y->color == EP_RB_RED) + { + + /* uncle is red */ + EP_RBTREE_PARENT (X)->color = EP_RB_BLACK; + Y->color = EP_RB_BLACK; + EP_RBTREE_GRANDF (X)->color = EP_RB_RED; + X = EP_RBTREE_GRANDF (X); + } + else + { + + /* uncle is black */ + if (X == + (struct ep_rb_node *) + ADDR_SHTOL (EP_RBTREE_PARENT (X)->rb_right)) + { + /* make X a left child */ + X = EP_RBTREE_PARENT (X); + __ep_rb_rotate_left (X, root); + } + + /* recolor and rotate */ + EP_RBTREE_PARENT (X)->color = EP_RB_BLACK; + EP_RBTREE_GRANDF (X)->color = EP_RB_RED; + __ep_rb_rotate_right (EP_RBTREE_GRANDF (X), root); + } + } + else + { + /* miror image of above code */ + struct ep_rb_node *Y = + (struct ep_rb_node *) ADDR_SHTOL (EP_RBTREE_GRANDF (X)->rb_left); + + if (Y && (Y->color == EP_RB_RED)) + { + + /* uncle is red */ + EP_RBTREE_PARENT (X)->color = EP_RB_BLACK; + Y->color = EP_RB_BLACK; + EP_RBTREE_GRANDF (X)->color = EP_RB_RED; + X = EP_RBTREE_GRANDF (X); + } + else + { + + /* uncle is black */ + if (X == + (struct ep_rb_node *) + ADDR_SHTOL (EP_RBTREE_PARENT (X)->rb_left)) + { + X = EP_RBTREE_PARENT (X); + __ep_rb_rotate_right (X, root); + } + + EP_RBTREE_PARENT (X)->color = EP_RB_BLACK; + EP_RBTREE_GRANDF (X)->color = EP_RB_RED; + __ep_rb_rotate_left (EP_RBTREE_GRANDF (X), root); + } + } + } + + ((struct ep_rb_node *) ADDR_SHTOL (root->rb_node))->color = EP_RB_BLACK; + + return; +} + +void +__ep_rb_erase_color (struct ep_rb_node *X, struct ep_rb_node *Parent, + struct ep_rb_root *root) +{ + /************************************* + * maintain red-black tree balance * + * after deleting node X * + *************************************/ + while (X != (struct ep_rb_node *) ADDR_SHTOL (root->rb_node) + && (!X || X->color == EP_RB_BLACK)) + { + + if (Parent == NULL) + { + break; + } + + if (X == (struct ep_rb_node *) ADDR_SHTOL (Parent->rb_left)) + { + struct ep_rb_node *W = + (struct ep_rb_node *) ADDR_SHTOL (Parent->rb_right); + + if (W->color == EP_RB_RED) + { + W->color = EP_RB_BLACK; + Parent->color = EP_RB_RED; /* Parent != NIL? */ + __ep_rb_rotate_left (Parent, root); + W = (struct ep_rb_node *) ADDR_SHTOL (Parent->rb_right); + } + + if ((!W->rb_left + || ((struct ep_rb_node *) ADDR_SHTOL (W->rb_left))->color == + EP_RB_BLACK) && (!W->rb_right + || ((struct ep_rb_node *) + ADDR_SHTOL (W->rb_right))->color == + EP_RB_BLACK)) + { + W->color = EP_RB_RED; + X = Parent; + Parent = (struct ep_rb_node *) ADDR_SHTOL (X->rb_parent); + } + else + { + if (!W->rb_right + || ((struct ep_rb_node *) ADDR_SHTOL (W->rb_right))->color + == EP_RB_BLACK) + { + if (W->rb_left != NULL) + { + ((struct ep_rb_node *) ADDR_SHTOL (W->rb_left))->color + = EP_RB_BLACK; + } + + W->color = EP_RB_RED; + __ep_rb_rotate_right (W, root); + W = (struct ep_rb_node *) ADDR_SHTOL (Parent->rb_right); + } + + W->color = Parent->color; + Parent->color = EP_RB_BLACK; + + if (((struct ep_rb_node *) ADDR_SHTOL (W->rb_right))->color != + EP_RB_BLACK) + { + ((struct ep_rb_node *) ADDR_SHTOL (W->rb_right))->color = + EP_RB_BLACK; + } + + __ep_rb_rotate_left (Parent, root); + X = (struct ep_rb_node *) ADDR_SHTOL (root->rb_node); + break; + } + } + else + { + + struct ep_rb_node *W = + (struct ep_rb_node *) ADDR_SHTOL (Parent->rb_left); + + if (W->color == EP_RB_RED) + { + W->color = EP_RB_BLACK; + Parent->color = EP_RB_RED; /* Parent != NIL? */ + __ep_rb_rotate_right (Parent, root); + W = (struct ep_rb_node *) ADDR_SHTOL (Parent->rb_left); + } + + if ((!W->rb_left + || (((struct ep_rb_node *) ADDR_SHTOL (W->rb_left))->color == + EP_RB_BLACK)) && (!W->rb_right + || + (((struct ep_rb_node *) + ADDR_SHTOL (W->rb_right))->color == + EP_RB_BLACK))) + { + W->color = EP_RB_RED; + X = Parent; + Parent = (struct ep_rb_node *) ADDR_SHTOL (X->rb_parent); + } + else + { + if (!W->rb_left + || ((struct ep_rb_node *) ADDR_SHTOL (W->rb_left))->color + == EP_RB_BLACK) + { + if (W->rb_right != NULL) + { + ((struct ep_rb_node *) + ADDR_SHTOL (W->rb_right))->color = EP_RB_BLACK; + } + + W->color = EP_RB_RED; + __ep_rb_rotate_left (W, root); + W = (struct ep_rb_node *) ADDR_SHTOL (Parent->rb_left); + } + + W->color = Parent->color; + Parent->color = EP_RB_BLACK; + + if (((struct ep_rb_node *) ADDR_SHTOL (W->rb_left))->color != + EP_RB_BLACK) + { + ((struct ep_rb_node *) ADDR_SHTOL (W->rb_left))->color = + EP_RB_BLACK; + } + + __ep_rb_rotate_right (Parent, root); + X = (struct ep_rb_node *) ADDR_SHTOL (root->rb_node); + break; + } + } + } + + if (X) + { + X->color = EP_RB_BLACK; + } + + return; +} + +void +ep_rb_erase (struct ep_rb_node *node, struct ep_rb_root *root) +{ + struct ep_rb_node *child, *parent; + int color; + + if (!node->rb_left) + { + child = (struct ep_rb_node *) ADDR_SHTOL (node->rb_right); + } + else if (!node->rb_right) + { + child = (struct ep_rb_node *) ADDR_SHTOL (node->rb_left); + } + else + { + struct ep_rb_node *old = node, *left; + + node = (struct ep_rb_node *) ADDR_SHTOL (node->rb_right); + + while ((left = + (struct ep_rb_node *) ADDR_SHTOL (node->rb_left)) != NULL) + { + node = left; + } + + if (old->rb_parent) + { + struct ep_rb_node *oldParent = + (struct ep_rb_node *) ADDR_SHTOL (old->rb_parent); + + if (oldParent->rb_left == + (struct ep_rb_node *) ADDR_LTOSH_EXT (old)) + { + oldParent->rb_left = + (struct ep_rb_node *) ADDR_LTOSH_EXT (node); + } + else + { + oldParent->rb_right = + (struct ep_rb_node *) ADDR_LTOSH_EXT (node); + } + } + else + { + root->rb_node = (struct ep_rb_node *) ADDR_LTOSH_EXT (node); + } + + child = (struct ep_rb_node *) ADDR_SHTOL (node->rb_right); + parent = (struct ep_rb_node *) ADDR_SHTOL (node->rb_parent); + color = node->color; + + if (parent == old) + { + parent = node; + } + else + { + if (child) + { + child->rb_parent = + (struct ep_rb_node *) ADDR_LTOSH_EXT (parent); + } + + parent->rb_left = (struct ep_rb_node *) ADDR_LTOSH_EXT (child); + + node->rb_right = old->rb_right; + ((struct ep_rb_node *) ADDR_SHTOL (old->rb_right))->rb_parent = + (struct ep_rb_node *) ADDR_LTOSH_EXT (node); + } + + node->color = old->color; + node->rb_parent = old->rb_parent; + node->rb_left = old->rb_left; + ((struct ep_rb_node *) ADDR_SHTOL (old->rb_left))->rb_parent = + (struct ep_rb_node *) ADDR_LTOSH_EXT (node); + + if (color == EP_RB_BLACK) + { + __ep_rb_erase_color (child, parent, root); + } + + return; + + } + + parent = (struct ep_rb_node *) ADDR_SHTOL (node->rb_parent); + color = node->color; + + if (child) + { + child->rb_parent = (struct ep_rb_node *) ADDR_LTOSH_EXT (parent); + } + + if (parent) + { + if (parent->rb_left == (struct ep_rb_node *) ADDR_LTOSH_EXT (node)) + { + parent->rb_left = (struct ep_rb_node *) ADDR_LTOSH_EXT (child); + } + else + { + parent->rb_right = (struct ep_rb_node *) ADDR_LTOSH_EXT (child); + } + } + else + { + root->rb_node = (struct ep_rb_node *) ADDR_LTOSH_EXT (child); + } + + if (color == EP_RB_BLACK) + { + __ep_rb_erase_color (child, parent, root); + } + return; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif diff --git a/src/framework/common/data_struct/list.c b/src/framework/common/data_struct/list.c new file mode 100644 index 0000000..7645640 --- /dev/null +++ b/src/framework/common/data_struct/list.c @@ -0,0 +1,163 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "list.h" + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +inline int +list_empty (const struct list_head *head) +{ + return head->next == head; +} + +inline void +list_del (struct list_head *entry) +{ + if (entry->prev == NULL || entry->next == NULL) + { + return; + } + entry->next->prev = entry->prev; + entry->prev->next = entry->next; + entry->next = NULL; + entry->prev = NULL; +} + +/*get the first element of the list, need to check if list empty or not before calling this.*/ +inline struct list_head * +list_get_first (struct list_head *head) +{ + return head->next; +} + +inline void +list_add (struct list_head *newp, struct list_head *head) +{ + head->next->prev = newp; + newp->next = head->next; + newp->prev = head; + head->next = newp; +} + +inline void +list_link (struct list_head *newhead, struct list_head *head) +{ + struct list_head *tmp; + + newhead->prev->next = head; + head->prev->next = newhead; + + tmp = newhead->prev; + newhead->prev = head->prev; + head->prev = tmp; +} + +inline void +list_add_tail (struct list_head *newp, struct list_head *head) +{ + list_add (newp, head->prev); +} + +inline void +hlist_del_init (struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + + if (pprev == NULL && next == NULL) + { + return; + } + + if (pprev) + { + *pprev = next; + } + + if (next) + { + next->pprev = pprev; + } + + n->next = NULL; + n->pprev = NULL; +} + +/** + * next must be != NULL + * add n node before next node + * + * @n: new node + * @next: node in the hlist + */ +inline void +hlist_add_before (struct hlist_node *n, struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +/** + * next must be != NULL + * add n node after next node + * actual behavior is add after n + * @n: node in the hlist + * @next: new node + */ +inline void +hlist_add_after (struct hlist_node *n, struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + if (next->next) + { + next->next->pprev = &next->next; + } +} + +/* add after the head */ +inline void +hlist_add_head (struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + + n->next = first; + if (first) + { + first->pprev = &n->next; + } + + h->first = n; + n->pprev = &h->first; +} + +inline int +hlist_unhashed (const struct hlist_node *h) +{ + return !h->pprev; +} + +inline int +hlist_empty (const struct hlist_head *h) +{ + return !h->first; +} diff --git a/src/framework/common/data_struct/pidinfo.c b/src/framework/common/data_struct/pidinfo.c new file mode 100644 index 0000000..08e551f --- /dev/null +++ b/src/framework/common/data_struct/pidinfo.c @@ -0,0 +1,125 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "pidinfo.h" +#include "nstack_securec.h" + +inline i32 +nsfw_pidinfo_init (nsfw_pidinfo * pidinfo) +{ + int retVal = + MEMSET_S (pidinfo, sizeof (nsfw_pidinfo), 0, sizeof (nsfw_pidinfo)); + if (EOK != retVal) + { + return -1; + } + + return 0; +} + +inline int +nsfw_add_pid (nsfw_pidinfo * pidinfo, u32 pid) +{ + u32 i; + + for (i = 0; i < NSFW_MAX_FORK_NUM; i++) + { + if ((0 == pidinfo->apid[i]) + && (__sync_bool_compare_and_swap (&pidinfo->apid[i], 0, pid))) + { + if (pidinfo->used_size < i + 1) + { + pidinfo->used_size = i + 1; + } + return 0; + } + } + return -1; +} + +inline int +nsfw_del_pid (nsfw_pidinfo * pidinfo, u32 pid) +{ + u32 i; + + for (i = 0; i < pidinfo->used_size && i < NSFW_MAX_FORK_NUM; i++) + { + if (pid == pidinfo->apid[i]) + { + pidinfo->apid[i] = 0; + return 0; + } + } + return -1; +} + +inline int +nsfw_del_last_pid (nsfw_pidinfo * pidinfo, u32 pid) +{ + u32 i; + int count = 0; + int deleted = 0; + for (i = 0; i < pidinfo->used_size && i < NSFW_MAX_FORK_NUM; i++) + { + if (pid == pidinfo->apid[i]) + { + pidinfo->apid[i] = 0; + deleted = 1; + continue; + } + + if (pidinfo->apid[i] != 0) + { + ++count; + } + } + + if (!deleted) + { + return -1; + } + + return count; +} + +inline int +nsfw_pid_exist (nsfw_pidinfo * pidinfo, u32 pid) +{ + u32 i; + + for (i = 0; i < pidinfo->used_size && i < NSFW_MAX_FORK_NUM; i++) + { + if (pid == pidinfo->apid[i]) + { + return 1; + } + } + return 0; +} + +inline int +nsfw_pidinfo_empty (nsfw_pidinfo * pidinfo) +{ + u32 i; + for (i = 0; i < pidinfo->used_size && i < NSFW_MAX_FORK_NUM; i++) + { + if (pidinfo->apid[i] != 0) + { + return 0; + } + } + return 1; +} diff --git a/src/framework/common/data_struct/sha256.c b/src/framework/common/data_struct/sha256.c new file mode 100644 index 0000000..504b365 --- /dev/null +++ b/src/framework/common/data_struct/sha256.c @@ -0,0 +1,397 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*Possible access of out-of-bounds pointer: + The algorithms has been tested on purify. So no + out of bounds access possible.*/ + +/*Possible creation of out-of-bounds pointer + No Out of bounds pointers are created.- false positive.*/ + +#include <string.h> /* for mem copy function etc. */ +#include "sha256.h" +#include "nstack_securec.h" +#include "types.h" +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define rotl32(x,n) (((x) << n) | ((x) >> (32 - n))) +#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n))) + +#if !defined(bswap_32) +#define bswap_32(x) ((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00)) +#endif + +#ifdef LITTLE_ENDIAN +#define SWAP_BYTES +#else +#undef SWAP_BYTES +#endif + +#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y)))) + + /* round transforms for SHA256 and SHA512 compression functions */ + +#define vf(n,i) v[(n - i) & 7] + +#define hf(i) (p[i & 15] += \ + g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15])) + +#define v_cycle(i,j) \ +{ \ + vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \ + + s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \ + vf(3,i) += vf(7,i); \ + vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i)); \ +} + +#define SHA256_MASK (SHA256_BLOCK_SIZE - 1) + +#if defined(SWAP_BYTES) +#define bsw_32(p,n) \ +{ \ + u32 _i = (n); \ + while (_i--) \ + { \ + ((u32*)p)[_i] = bswap_32(((u32*)p)[_i]); \ + } \ +} + +#else +#define bsw_32(p,n) +#endif + +#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22)) +#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25)) +#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3)) +#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10)) +#define k_0 k256 + +/* rotated SHA256 round definition. Rather than swapping variables as in */ +/* FIPS-180, different variables are 'rotated' on each round, returning */ +/* to their starting positions every eight rounds */ + +#define q(n) v##n + +#define one_cycle(a,b,c,d,e,f,g,h,k,w) \ + q(h) += s_1(q(e)) + ch(q(e), q(f), q(g)) + k + w; \ + q(d) += q(h); q(h) += s_0(q(a)) + maj(q(a), q(b), q(c)) + +/* +Description: SHA256 mixing data +Value Range: None +Access: Used to mix with data to create SHA256 key. +Remarks: +*/ +static const u32 k256[64] = { + 010242427630, 016115642221, 026560175717, 035155355645, + 07125541133, 013174210761, 022217701244, 025307057325, + 033001725230, 02240655401, 04414302676, 012503076703, + 016257456564, 020067530776, 023367003247, 030146770564, + 034446664701, 035757443606, 01760316706, 04403120714, + 05572226157, 011235102252, 013454124734, 016676304332, + 023017450522, 025014343155, 026000623710, 027726277707, + 030670005763, 032551710507, 0662461521, 02412224547, + 04755605205, 05606620470, 011513066774, 012316006423, + 014502471524, 016632405273, 020160544456, 022234426205, + 024257764241, 025006463113, 030222705560, 030733050643, + 032144564031, 032646203044, 036403432605, 02032520160, + 03151140426, 03615666010, 04722073514, 06454136265, + 07107006263, 011666125112, 013347145117, 015013467763, + 016443701356, 017051261557, 020462074024, 021461601010, + 022057577772, 024424066353, 027676321767, 030634274362, +}; + +/* Compile 64 bytes of hash data into SHA256 digest value */ +/* NOTE: this routine assumes that the byte order in the */ +/* ctx->wbuf[] at this point is such that low address bytes */ +/* in the ORIGINAL byte stream will go into the high end of */ +/* words on BOTH big and little endian systems */ + +#define v_ v +#define ptr p + +/*===========================================================================*\ + Function :Sha256_compile__ + Description : This function generates the digest value for SHA256. + Compile 64 bytes of hash data into SHA256 digest value + Calls : mem copy - Secure mem copy function. + Called by : + Return : This is a static internal function which doesn't return any value. + Parameters : + SHA256_CTX ctx[1] - + Note : this routine assumes that the byte order in the + ctx->wbuf[] at this point is such that low address bytes in + the ORIGINAL byte stream will go into the high end of + words on BOTH big and little endian systems. +\*===========================================================================*/ +NSTACK_STATIC void +Sha256_compile__ (SHA256_CTX ctx[1]) +{ + + /* macros defined above to this function i.e. v_ and ptr should not be removed */ + /* v_cycle - for 0 to 15 */ + u32 j; + u32 *ptr = ctx->wbuf; + u32 v_[8]; + + int ret = MEMCPY_S (v_, 8 * sizeof (u32), ctx->hash, 8 * sizeof (u32)); + if (EOK != ret) + { + NSPOL_LOGERR ("MEMCPY_S failed"); + return; + } + + for (j = 0; j < 64; j += 16) + { + /*v_cycle operations from 0 to 15 */ + v_cycle (0, j); + v_cycle (1, j); + v_cycle (2, j); + v_cycle (3, j); + v_cycle (4, j); + v_cycle (5, j); + v_cycle (6, j); + v_cycle (7, j); + v_cycle (8, j); + v_cycle (9, j); + v_cycle (10, j); + v_cycle (11, j); + v_cycle (12, j); + v_cycle (13, j); + v_cycle (14, j); + v_cycle (15, j); + } + + /* update the context */ + ctx->hash[0] += v_[0]; + ctx->hash[1] += v_[1]; + ctx->hash[2] += v_[2]; + ctx->hash[3] += v_[3]; + ctx->hash[4] += v_[4]; + ctx->hash[5] += v_[5]; + ctx->hash[6] += v_[6]; + ctx->hash[7] += v_[7]; + + return; +} + +#undef v_ +#undef ptr + +/* SHA256 hash data in an array of bytes into hash buffer */ +/* and call the hash_compile function as required. */ + +/*===========================================================================*\ + Function :Sha256_upd + Description : + Calls : + Called by : + Return :void - + Parameters : + SHA256_CTX ctx[1] - + const unsigned char data[] - + size_t len - + Note : +\*===========================================================================*/ +void +Sha256_upd (SHA256_CTX ctx[1], const u8 data[], size_t len) +{ + u32 pos = (u32) (ctx->count[0] & SHA256_MASK); + u32 space = SHA256_BLOCK_SIZE - pos; + const u8 *sp = data; + int ret; + + if ((ctx->count[0] += (u32) len) < len) + { + ++(ctx->count[1]); + } + + while (len >= space) + { + + /* tranfer whole blocks while possible */ + ret = MEMCPY_S (((u8 *) ctx->wbuf) + pos, space, sp, space); + if (EOK != ret) + { + NSPOL_LOGERR ("MEMCPY_S failed"); + return; + } + + sp += space; + len -= space; + space = SHA256_BLOCK_SIZE; + pos = 0; + bsw_32 (ctx->wbuf, SHA256_BLOCK_SIZE >> 2); + Sha256_compile__ (ctx); + } + + if (len != 0) + { + ret = MEMCPY_S (((u8 *) ctx->wbuf) + pos, (u32) len, sp, (u32) len); + if (EOK != ret) + { + NSPOL_LOGERR ("MEMCPY_S failed"); + return; + } + } + + return; +} + +/* SHA256 Final padding and digest calculation */ + +/*===========================================================================*\ + Function :SHA_fin1 + Description : + Calls : + Called by : + Return :void - + Parameters : + unsigned char hval[] - + SHA256_CTX ctx[1] - + const unsigned int hlen - + Note : +\*===========================================================================*/ +NSTACK_STATIC void +SHA_fin1 (u8 hval[], SHA256_CTX ctx[1], const unsigned int hlen) +{ + u32 i = (u32) (ctx->count[0] & SHA256_MASK); + + /* Not unusal shift operation. Checked with purify. */ + + /*put bytes in the buffer in an order in which references to */ + /*32-bit words will put bytes with lower addresses into the */ + /*top of 32 bit words on BOTH big and little endian machines */ + bsw_32 (ctx->wbuf, (i + 3) >> 2); + + /*we now need to mask valid bytes and add the padding which is */ + /*a single 1 bit and as many zero bits as necessary. Note that */ + /*we can always add the first padding byte here because the */ + /*buffer always has at least one empty slot */ + ctx->wbuf[i >> 2] &= (u32) 0xffffff80 << 8 * (~i & 3); + ctx->wbuf[i >> 2] |= (u32) 0x00000080 << 8 * (~i & 3); + + /* we need 9 or more empty positions, one for the padding byte */ + /* (above) and eight for the length count. If there is not */ + /* enough space pad and empty the buffer */ + if (i > SHA256_BLOCK_SIZE - 9) + { + if (i < 60) + { + ctx->wbuf[15] = 0; + } + + Sha256_compile__ (ctx); + i = 0; + } + else + { + /* compute a word index for the empty buffer positions */ + i = (i >> 2) + 1; + } + + while (i < 14) + { + /* and zero pad all but last two positions */ + ctx->wbuf[i++] = 0; + } + + /* the following 32-bit length fields are assembled in the */ + /* wrong byte order on little endian machines but this is */ + /* corrected later since they are only ever used as 32-bit */ + /* word values. */ + ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29); + ctx->wbuf[15] = ctx->count[0] << 3; + Sha256_compile__ (ctx); + + /* extract the hash value as bytes in case the hash buffer is */ + /* mislaigned for 32-bit words */ + for (i = 0; i < hlen; ++i) + { + hval[i] = (u8) (ctx->hash[i >> 2] >> (8 * (~i & 3))); + } + + return; +} + +/* +Description: Internal data for SHA256 digest calculation +Value Range: None +Access: Used to store internal data for SHA256 digest calculation +Remarks: +*/ +static const u32 g_i256[] = { + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +}; + +/*===========================================================================*\ + Function :Sha256_set + Description : + Calls : + Called by : + Return :void - + Parameters : + SHA256_CTX ctx[1] - + Note : +\*===========================================================================*/ +void +Sha256_set (SHA256_CTX ctx[1]) +{ + int ret; + ctx->count[0] = ctx->count[1] = 0; + + ret = MEMCPY_S (ctx->hash, sizeof (ctx->hash), g_i256, sizeof (g_i256)); + if (EOK != ret) + { + NSPOL_LOGERR ("MEMCPY_S failed"); + return; + } + + return; +} + +/*===========================================================================*\ + Function :Sha256_fin + Description : + Calls : + Called by : + Return :void - + Parameters : + SHA256_CTX ctx[1] - + unsigned char hval[] - + Note : +\*===========================================================================*/ +void +Sha256_fin (SHA256_CTX ctx[1], u8 hval[]) +{ + SHA_fin1 (hval, ctx, SHA256_DIGEST_SIZE); + + return; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif diff --git a/src/framework/common/include/compile_config.h b/src/framework/common/include/compile_config.h new file mode 100644 index 0000000..2ec5373 --- /dev/null +++ b/src/framework/common/include/compile_config.h @@ -0,0 +1,30 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef COMPILE_CONFIG_H +#define COMPILE_CONFIG_H + +#ifndef NSTACK_STATIC +#ifndef NSTACK_STATIC_CHECK +#define NSTACK_STATIC static +#else +#define NSTACK_STATIC +#endif +#endif + +#include "compiling_check.h" + +#endif /*compile_config.h */ diff --git a/src/framework/common/include/compiling_check.h b/src/framework/common/include/compiling_check.h new file mode 100644 index 0000000..e4a7538 --- /dev/null +++ b/src/framework/common/include/compiling_check.h @@ -0,0 +1,106 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef COMPILING_CHECK_H +#define COMPILING_CHECK_H + +/* protect the value of macro whose value impacts the version + * compatibility, can't be changed!!! */ +#define COMPAT_PROTECT(name, value) \ +static inline char value_of_##name##_equal_to() \ +{ \ + char __dummy1[(name) - (value)]; \ + char __dummy2[(value) - (name)]; \ + return __dummy1[-1] + __dummy2[-1]; \ +} + +/* check whether struct size is equal to a special value */ +#define SIZE_OF_TYPE_EQUAL_TO(type, size) \ +static inline char size_of_##type##_equal_to_##size() \ +{ \ + char __dummy1[sizeof(type) - size]; \ + char __dummy2[size - sizeof(type)]; \ + return __dummy1[-1] + __dummy2[-1]; \ +} + +/* check whether struct size is not equal to a special value */ +#define SIZE_OF_TYPE_UNEQUAL_TO(type, size) \ +static inline char size_of_##type##_unequal_to_##size() \ +{ \ + char __dummy1[0==(10/(sizeof(type)-size))]; \ + return __dummy1[-1]; \ +} + +/* check whether struct size is not larger than a special value */ +#define SIZE_OF_TYPE_NOT_LARGER_THAN(type, size) \ +static inline char size_of_##type##_not_larger_than_##size() \ +{ \ + char __dummy1[size - sizeof(type)]; \ + return __dummy1[-1]; \ +} + +/* check whether struct size + sizeof(void*) is not larger than a special value */ +/* reserve 8 bytes for 64 bits pointers */ +#define SIZE_OF_TYPE_PLUS8_NOT_LARGER_THAN(type, size) \ +static inline char size_of_##type##_not_larger_than_##size() \ +{ \ + char __dummy1[size - sizeof(type) - sizeof(void*)]; \ + return __dummy1[-1]; \ +} + +/* check whether struct size is not smaller than a special value */ +#define SIZE_OF_TYPE_NOT_SMALLER_THAN(type, size) \ +static inline char size_of_##type##_not_smaller_than_##size() \ +{ \ + char __dummy1[sizeof(type) - size]; \ + return __dummy1[-1]; \ +} + +/* check whether struct size is smaller than a special value */ +#define SIZE_OF_TYPE_SMALLER_THAN(type, size) \ + SIZE_OF_TYPE_NOT_LARGER_THAN(type, size) \ + SIZE_OF_TYPE_UNEQUAL_TO(type, size) + +/* check whether struct size is larger than a special value */ +#define SIZE_OF_TYPE_LARGER_THAN(type, size) \ + SIZE_OF_TYPE_NOT_SMALLER_THAN(type, size) \ + SIZE_OF_TYPE_UNEQUAL_TO(type, size) + +/* check whether struct size is smaller than a special value, version 2 */ +#define SIZE_OF_TYPE_SMALLER_THAN2(type, size) \ +static inline char size_of_##type##_smaller_than2_##size() \ +{ \ + char __dummy1[size - sizeof(type) - 1]; \ + return __dummy1[-1]; \ +} + +/* check whether struct size is larger than a special value, version 2 */ +#define SIZE_OF_TYPE_LARGER_THAN2(type, size) \ +static inline char size_of_##type##_larger_than2_##size() \ +{ \ + char __dummy1[sizeof(type) - size - 1]; \ + return __dummy1[-1]; \ +} + +/* check whether struct size is equal to an integer multiple of a special value */ +#define SIZE_OF_TYPE_IS_MULTIPLE_OF(type, size) \ +static inline char size_of_##type##_is_multiple_of_##size() \ +{ \ + char __dummy1[0 - (sizeof(type) % size)]; \ + return __dummy1[-1]; \ +} + +#endif /*compiling_check.h */ diff --git a/src/framework/common/include/ephlist.h b/src/framework/common/include/ephlist.h new file mode 100644 index 0000000..90491b0 --- /dev/null +++ b/src/framework/common/include/ephlist.h @@ -0,0 +1,199 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _EPHLIST_H_ +#define _EPHLIST_H_ + +#include <stdio.h> +#include "types.h" +#include "common_mem_pal.h" +#include "common_mem_buf.h" +#include "common_pal_bitwide_adjust.h" +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +struct ep_hlist_node +{ + struct ep_hlist_node *next, **pprev; +}; + +struct ep_node_list +{ + struct ep_hlist_node *head; + struct ep_hlist_node *tail; +}; + +struct ep_hlist +{ + struct ep_hlist_node node; + struct ep_hlist_node *head; + struct ep_hlist_node *tail; +}; + +#define ep_hlist_entry(ptr, type, member) container_of(ptr, type, member) + +#define EP_HLIST_INIT_NODE(node) {\ + (node)->next = NULL;\ + (node)->pprev = NULL; \ + } + +#define EP_HLIST_INIT(ptr) {\ + EP_HLIST_INIT_NODE(&((ptr)->node)); \ + (ptr)->head = (struct ep_hlist_node*)ADDR_LTOSH_EXT(&((ptr)->node)); \ + (ptr)->tail = (struct ep_hlist_node*)ADDR_LTOSH_EXT(&((ptr)->node)); \ + } + +#define EP_HLIST_PREV(ptr) ((struct ep_hlist_node*)(ADDR_SHTOL((ptr)->pprev))) +/* list check may below zero check header, because if app crash before + do list->size++, it will lead problem */ +#define EP_HLIST_EMPTY(list) (NULL == ((struct ep_hlist_node*)ADDR_SHTOL((list)->head))->next) +#define EP_HLIST_NODE_LINKED(node) (!(!(node)->pprev)) + +static __inline void ep_hlist_del (struct ep_hlist *list, + struct ep_hlist_node *n); +static __inline void ep_hlist_add_tail (struct ep_hlist *list, + struct ep_hlist_node *node); + +/* + * list , n are local pointer, don't need to cast + */ +static __inline void +ep_hlist_del (struct ep_hlist *list, struct ep_hlist_node *n) +{ + if (!EP_HLIST_NODE_LINKED (n)) + return; + EP_HLIST_PREV (n)->next = n->next; + if (n->next) + { + ((struct ep_hlist_node *) ADDR_SHTOL (n->next))->pprev = n->pprev; + } + else + { + list->tail = (struct ep_hlist_node *) (n->pprev); + } + EP_HLIST_INIT_NODE (n); +} + +/** + * list, node are local pointer , don't need to case + */ +static __inline void +ep_hlist_add_tail (struct ep_hlist *list, struct ep_hlist_node *node) +{ + struct ep_hlist_node *tail = + (struct ep_hlist_node *) ADDR_SHTOL (list->tail); + EP_HLIST_INIT_NODE (node); + node->pprev = (struct ep_hlist_node **) ADDR_LTOSH_EXT (&tail->next); + tail->next = (struct ep_hlist_node *) ADDR_LTOSH_EXT (node); + list->tail = (struct ep_hlist_node *) ADDR_LTOSH_EXT (node); +} + +/*#########################################################*/ +struct list_node +{ + struct list_node *next; +}; + +struct ep_list +{ + struct list_node node; + struct list_node *head; +}; + +#define ep_list_entry(ptr, type, member) container_of(ptr, type, member) + +#define EP_LIST_INIT_NODE(node) {\ + (node)->next = NULL;\ + } + +#define EP_LIST_INIT(ptr) {\ + EP_LIST_INIT_NODE(&((ptr)->node)); \ + (ptr)->head = (struct list_node*)ADDR_LTOSH_EXT(&((ptr)->node)); \ + } + +#define EP_LIST_EMPTY(list) (NULL == ((struct list_node*)ADDR_SHTOL((list)->head))->next) + +static __inline void ep_list_del (struct ep_list *list, struct list_node *n); +static __inline void ep_list_add_tail (struct ep_list *list, + struct list_node *node); + +/* + * list , n are local pointer, don't need to cast + */ +static __inline void +ep_list_del (struct ep_list *list, struct list_node *n) +{ + if (NULL == n) + { + return; + } + + struct list_node *p_node; + struct list_node *p_prev = NULL; + p_node = ((struct list_node *) ADDR_SHTOL (list->head)); + while (NULL != p_node && p_node != n) + { + p_prev = p_node; + p_node = ((struct list_node *) ADDR_SHTOL (p_node->next)); + } + + if (p_node != n || p_prev == NULL) + { + return; + } + + p_prev->next = n->next; + + EP_LIST_INIT_NODE (n); + return; +} + +/** + * list, node are local pointer , don't need to case + */ +static __inline void +ep_list_add_tail (struct ep_list *list, struct list_node *node) +{ + + struct list_node *p_node; + struct list_node *p_prev = NULL; + p_node = ((struct list_node *) ADDR_SHTOL (list->head)); + while (NULL != p_node) + { + p_prev = p_node; + p_node = ((struct list_node *) ADDR_SHTOL (p_node->next)); + } + + if (NULL == p_prev) + { + return; + } + + EP_LIST_INIT_NODE (node); + p_prev->next = (struct list_node *) ADDR_LTOSH_EXT (node); + return; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* _HLIST_H_ */ diff --git a/src/framework/common/include/eprb_tree.h b/src/framework/common/include/eprb_tree.h new file mode 100644 index 0000000..558ab2d --- /dev/null +++ b/src/framework/common/include/eprb_tree.h @@ -0,0 +1,84 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _EPRB_TREE_H_ +#define _EPRB_TREE_H_ + +#include <stdio.h> +#include <stdlib.h> +#include "types.h" +#include "common_mem_pal.h" +#include "common_mem_buf.h" +#include "common_pal_bitwide_adjust.h" +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define EP_RB_RED 0 +#define EP_RB_BLACK 1 + +struct ep_rb_node +{ + int color; + + struct ep_rb_node *rb_parent; + struct ep_rb_node *rb_right; + struct ep_rb_node *rb_left; +}; + +/* The alignment might seem pointless, but allegedly CRIS needs it */ + +struct ep_rb_root +{ + struct ep_rb_node *rb_node; +}; + +#define ep_rb_parent(r) ((struct ep_rb_node *)((r)->rb_parent)) + +static inline void +ep_rb_set_parent (struct ep_rb_node *rb, struct ep_rb_node *p) +{ + rb->rb_parent = (struct ep_rb_node *) ADDR_LTOSH_EXT (p); +} + +#define ep_rb_entry(ptr, type, member) container_of(ptr, type, member) + +extern void ep_rb_insert_color (struct ep_rb_node *, struct ep_rb_root *); +extern void ep_rb_erase (struct ep_rb_node *, struct ep_rb_root *); +struct ep_rb_node *ep_rb_first (const struct ep_rb_root *); + +static inline void +ep_rb_link_node (struct ep_rb_node *node, + struct ep_rb_node *parent, struct ep_rb_node **rb_link) +{ + + node->rb_parent = (struct ep_rb_node *) ADDR_LTOSH_EXT (parent); + node->rb_left = node->rb_right = NULL; + + *rb_link = (struct ep_rb_node *) ADDR_LTOSH_EXT (node); + node->color = EP_RB_RED; + +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/framework/common/include/list.h b/src/framework/common/include/list.h new file mode 100644 index 0000000..01860bc --- /dev/null +++ b/src/framework/common/include/list.h @@ -0,0 +1,181 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef LIST_H_ +#define LIST_H_ + +#include <signal.h> +#include <stdio.h> +#include <pthread.h> +#include <unistd.h> + +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +struct list_head +{ + union + { + struct list_head *next; + }; + + union + { + struct list_head *prev; + }; +}; + +struct hlist_node +{ + /** + * @pprev: point the previous node's next pointer + */ + union + { + struct hlist_node *next; + }; + + union + { + struct hlist_node **pprev; + }; +}; + +struct hlist_head +{ + struct hlist_node *first; +}; + +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +#define list_for_each_entry_type(tpos, typeof_tpos,pos, head, member) \ + for (pos = ((head)->next); \ + pos && pos != (head) && ({tpos = list_entry(pos, typeof_tpos, member); 1;}); \ + pos = ((pos)->next)) + +#define LINT_LIST() + +#define list_for_each_entry(tpos, pos, head, member) \ + for (pos = ((head)->next); \ + pos && pos != (head) && ({tpos = list_entry(pos, typeof(*tpos), member); 1;}); \ + pos = ((pos)->next)) + +#define list_for_each_entry_list_head(tpos, pos, head, member) \ + for (pos = (struct list_head *)((head)->next); \ + pos && pos != (struct list_head *)(head) && ({tpos = list_entry(pos, typeof(*tpos), member); 1;}); \ + pos = (pos)->next) +#define list_for_each_safe_entry(tpos, pos, n, head, member) \ + for (pos = (head)->next,n = pos->next; \ + pos && pos != (head) && ({tpos = list_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n,n = (pos)->next) + +#define INIT_LIST_HEAD(list) {(list)->next = (list); (list)->prev = (list);} + +/* + * @head: the list to test. + */ +inline void list_add (struct list_head *newp, struct list_head *head); +inline void list_link (struct list_head *newhead, struct list_head *head); +inline void list_add_tail (struct list_head *newp, struct list_head *head); +inline int list_empty (const struct list_head *head); +inline void list_del (struct list_head *entry); +inline struct list_head *list_get_first (struct list_head *head); +inline void hlist_del_init (struct hlist_node *n); + +struct hlist_tail +{ + struct hlist_node *end; +}; + +struct hlist_ctl +{ + struct hlist_head head; + struct hlist_tail tail; +}; +#define INIT_HLIST_CTRL(ptr) {(ptr)->head.first = NULL; (ptr)->tail.end = NULL;} + +inline int hlist_empty (const struct hlist_head *h); +inline void hlist_add_head (struct hlist_node *n, struct hlist_head *h); + +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_HLIST_NODE(ptr) {(ptr)->next = NULL; (ptr)->pprev = NULL;} +#define hlist_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/*** + * hlist_for_each_entry - iterate over list of given type + * @member: the name of the hlist_node within the struct. + * @head: the head for your list. + * @pos: the &struct hlist_node to use as a loop cursor. + * @tpos: the type * to use as a loop cursor. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_type - iterate over list of given type + * @member: the name of the hlist_node within the struct. + * @head: the head for your list. + * @pos: the &struct hlist_node to use as a loop cursor. + * @tpos: the type * to use as a loop cursor. + */ +#define hlist_for_each_entry_type(tpos, typeof_tpos,pos, head, member) \ + for (pos = (head)->first; \ + pos && ({tpos = hlist_entry(pos, typeof_tpos, member); 1;}); \ + pos = pos->next) + +inline void hlist_del_init (struct hlist_node *n); + +/** + * next must be != NULL + * add n node before next node + * + * @n: new node + * @next: node in the hlist + */ +inline void hlist_add_before (struct hlist_node *n, struct hlist_node *next); + +/** + * next must be != NULL + * add n node after next node + * actual behavior is add after n + * @n: node in the hlist + * @next: new node + */ +inline void hlist_add_after (struct hlist_node *n, struct hlist_node *next); + +/* add after the head */ +inline void hlist_add_head (struct hlist_node *n, struct hlist_head *h); + +inline int hlist_unhashed (const struct hlist_node *h); + +inline int hlist_empty (const struct hlist_head *h); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +}; +/* *INDENT-ON* */ +#endif + +#endif /* HASH_H_ */ diff --git a/src/framework/common/include/pidinfo.h b/src/framework/common/include/pidinfo.h new file mode 100644 index 0000000..7438756 --- /dev/null +++ b/src/framework/common/include/pidinfo.h @@ -0,0 +1,48 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _PIDINFO_H_ +#define _PIDINFO_H_ + +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define NSFW_MAX_FORK_NUM 32 +typedef struct +{ + u32 used_size; + u32 apid[NSFW_MAX_FORK_NUM]; +} nsfw_pidinfo; + +inline i32 nsfw_pidinfo_init (nsfw_pidinfo * pidinfo); +inline int nsfw_add_pid (nsfw_pidinfo * pidinfo, u32 pid); +inline int nsfw_del_pid (nsfw_pidinfo * pidinfo, u32 pid); +inline int nsfw_del_last_pid (nsfw_pidinfo * pidinfo, u32 pid); +inline int nsfw_pid_exist (nsfw_pidinfo * pidinfo, u32 pid); +inline int nsfw_pidinfo_empty (nsfw_pidinfo * pidinfo); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +}; +/* *INDENT-ON* */ +#endif + +#endif /* _PIDINFO_H_ */ diff --git a/src/framework/common/include/sha256.h b/src/framework/common/include/sha256.h new file mode 100644 index 0000000..b1c7f3c --- /dev/null +++ b/src/framework/common/include/sha256.h @@ -0,0 +1,94 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _SHA256_H_ +#define _SHA256_H_ +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* Note that the following function prototypes are the same */ +/* for both the bit and byte oriented implementations. But */ +/* the length fields are in bytes or bits as is appropriate */ +/* for the version used. Bit sequences are arrays of bytes */ +/* in which bit sequence indexes increase from the most to */ +/* the least significant end of each byte */ + +#define SHA256_DIGEST_SIZE 32 /* in bytes */ +#define SHA256_BLOCK_SIZE 64 /* in bytes */ + +typedef struct +{ + u32 count[2]; + u32 hash[8]; + u32 wbuf[16]; +} SHA256_CTX; + +/* SHA256 hash data in an array of bytes into hash buffer */ +/* and call the hash_compile function as required. */ + +/*===========================================================================*\ + Function :Sha256_upd + Description : + Calls : + Called by : + Return :void - + Parameters : + SHA256_CTX ctx[1] - + const unsigned char data[] - + size_t len - + Note : +\*===========================================================================*/ +void Sha256_upd (SHA256_CTX ctx[1], const u8 data[], size_t len); + +/* SHA256 Final padding and digest calculation */ + +/*===========================================================================*\ + Function :Sha256_set + Description : + Calls : + Called by : + Return :void - + Parameters : + SHA256_CTX ctx[1] - + Note : +\*===========================================================================*/ +void Sha256_set (SHA256_CTX ctx[1]); + +/*===========================================================================*\ + Function :Sha256_fin + Description : + Calls : + Called by : + Return :void - + Parameters : + SHA256_CTX ctx[1] - + unsigned char hval[] - + Note : +\*===========================================================================*/ +void Sha256_fin (SHA256_CTX ctx[1], u8 hval[]); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif /* _SHA256_H_ */ diff --git a/src/framework/common/include/types.h b/src/framework/common/include/types.h new file mode 100644 index 0000000..c7d013c --- /dev/null +++ b/src/framework/common/include/types.h @@ -0,0 +1,97 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef clib_types_h +#define clib_types_h +#include <stddef.h> + +/* Standard CLIB types. */ + +/* Define signed and unsigned 8, 16, 32, and 64 bit types + and machine signed/unsigned word for all architectures. */ +typedef char i8; +typedef short i16; + +typedef unsigned char u8; +typedef unsigned short u16; + +typedef int i32; +typedef long long i64; + +typedef unsigned int u32; +typedef unsigned long long u64; + +#ifndef bool +#define bool int +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef false +#define false 0 +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define container_of(ptr, type, member) ( \ + (type *)((char *)(ptr) - offsetof(type,member)) \ + ) + +#define PRIMARY_ADDR + +typedef struct _nsfw_res +{ + u8 alloc_flag; + u8 u8Reserve; + u16 chk_count; + u32 data; +} nsfw_res; + +static inline void +res_alloc (nsfw_res * res) +{ + res->alloc_flag = TRUE; + res->chk_count = 0; + res->u8Reserve = 0; +} + +static inline int +res_free (nsfw_res * res) +{ + if (TRUE != res->alloc_flag) + { + return -1; + } + res->chk_count = 0; + res->alloc_flag = FALSE; + return 0; +} + +#define NSFW_THREAD __thread + +#endif /*clib_types_h */ diff --git a/src/framework/common/mem_mgr/include/nsfw_mem_desc.h b/src/framework/common/mem_mgr/include/nsfw_mem_desc.h new file mode 100644 index 0000000..1e959d9 --- /dev/null +++ b/src/framework/common/mem_mgr/include/nsfw_mem_desc.h @@ -0,0 +1,172 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_MEM_DESC_H +#define _NSFW_MEM_DESC_H +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include "nsfw_mem_api.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_ring_data.h" + +#define NSFW_MEM_NOT_INIT (0) +#define NSFW_MEM_INIT_ERR (1) +#define NSFW_MEM_INIT_OK (2) + +#define NSFW_NAME_LENCHECK_RET(name, desc) \ + { \ + i32 inamelen = strlen(name); \ + if (inamelen >= NSFW_MEM_APPNAME_LENTH) \ + { \ + NSCOMM_LOGERR("name length check fail] desc=%s, name len=%d, expected max=%d", \ + #desc, inamelen, NSFW_MEM_APPNAME_LENTH); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_NAME_LENCHECK_RET_NULL(name, desc) \ + { \ + i32 inamelen = strlen(name); \ + if (inamelen >= NSFW_MEM_APPNAME_LENTH) \ + { \ + NSCOMM_LOGERR("name length check fail] desc=%s, name len=%d, expected max=%d", \ + #desc, inamelen, NSFW_MEM_APPNAME_LENTH); \ + return NULL; \ + } \ + } + +#define NSFW_MEM_PARA_CHECK_RET(handle, pdata, desc, num) {\ + if ((NULL == (handle)) || (NULL == (pdata)) || (num <= 0)\ + || (((struct nsfw_mem_ring*)(handle))->memtype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] desc=%s,mhandle=%p, pdata=%p, inum=%d", desc, (handle), (pdata), num); \ + return 0; \ + } \ + } + +#define NSFW_MEM_ENQ_PARA_CHECK_RET(handle, desc) {\ + if ((NULL == (handle)) \ + || (((struct nsfw_mem_ring*)(handle))->memtype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] desc=%s,mhandle=%p", desc, (handle)); \ + return 0; \ + } \ + } + +#define NSFW_MEM_NAME_CHECK_RET_ERR(pname, desc) {\ + if ((NULL == (pname)) || ((pname)->entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] desc=%s, pname=%p, mtype=%d", desc, pname, (pname) ? (pname)->entype:-1); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_MEM_NAME_CHECK_RET_NULL(pname, desc) {\ + if ((NULL == (pname)) || ((pname)->entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] desc=%s, pname=%p, mtype=%d", desc, pname, (pname) ? (pname)->entype:-1); \ + return NULL; \ + } \ + } + +#define NSFW_MEM_RING_CHECK_RET(pringinfo, pringhandle_array, iringnum) {\ + if ((NULL == pringinfo) || (NULL == pringhandle_array) || (pringinfo[0].stname.entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] pringinfo=%p, iringnum=%d, pringhandle_array=%p, mtype=%d", \ + pringinfo, iringnum, pringhandle_array, pringinfo ? pringinfo[0].stname.entype : (-1)); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_MEM_RINGV_CHECK_RET(pmpinfo, inum, pringhandle_array, iarray_num) { \ + if ((NULL == pmpinfo) || (NULL == pringhandle_array) \ + || (inum != iarray_num) || (inum <= 0) || (pmpinfo[0].stname.entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] pmpinfo=%p, inum=%d, pringhandle_array=%p, iarray_num=%d", \ + pmpinfo, inum, pringhandle_array, iarray_num, pmpinfo ? pmpinfo[0].stname.entype : (-1)); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_MEM_MBUF_CHECK_RET_ERR(mhandle, entype, desc) {\ + if ((NULL == mhandle) || (entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] desc=%s, mhandle=%p, mtype=%d", desc, mhandle, entype); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_MEM_MBUF_CHECK_RET_NULL(mhandle, entype, desc) {\ + if ((NULL == mhandle) || (entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSCOMM_LOGERR("input para error] desc=%s, mhandle=%p, mtype=%d", desc, mhandle, entype); \ + return NULL; \ + } \ + } + +/*memory access inferface define*/ +typedef struct +{ + i32 (*mem_ops_init) (nsfw_mem_para * para); + void (*mem_ops_destroy) (void); + mzone_handle (*mem_ops_zone_creae) (nsfw_mem_zone * pinfo); + i32 (*mem_ops_zone_createv) (nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num); + mzone_handle (*mem_ops_zone_lookup) (nsfw_mem_name * pname); + i32 (*mem_ops_mzone_release) (nsfw_mem_name * pname); + mpool_handle (*mem_ops_mbfmp_create) (nsfw_mem_mbfpool * pbufinfo); + i32 (*mem_ops_mbfmp_createv) (nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, + i32 iarray_num); + mbuf_handle (*mem_ops_mbf_alloc) (mpool_handle mhandle); + i32 (*mem_ops_mbf_free) (mbuf_handle mhandle); + mpool_handle (*mem_ops_mbfmp_lookup) (nsfw_mem_name * pmbfname); + i32 (*mem_ops_mbfmp_release) (nsfw_mem_name * pname); + mring_handle (*mem_ops_sp_create) (nsfw_mem_sppool * pmpinfo); + i32 (*mem_ops_sp_createv) (nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, + i32 iarray_num); + i32 (*mem_ops_spring_create) (nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, + i32 iringnum); + i32 (*mem_ops_sp_release) (nsfw_mem_name * pname); + mring_handle (*mem_ops_sp_lookup) (nsfw_mem_name * pname); + mring_handle (*mem_ops_ring_create) (nsfw_mem_mring * pringinfo); + mring_handle (*mem_ops_ring_lookup) (nsfw_mem_name * pname); + i32 (*mem_ops_ring_release) (nsfw_mem_name * pname); + ssize_t (*mem_ops_mem_statics) (void *handle, nsfw_mem_struct_type type); + i32 (*mem_ops_mbuf_recycle) (mpool_handle handle); + i32 (*mem_ops_sp_iterator) (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); + i32 (*mem_ops_mbuf_iterator) (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); +} nsfw_mem_ops; + +typedef struct +{ + nsfw_mem_type entype; + nsfw_mem_ops *stmemop; +} nsfw_mem_attr; + +typedef struct +{ + fw_poc_type enflag; /*app, nStackMain, Master */ +} nsfw_mem_localdata; + +extern nsfw_mem_attr g_nsfw_mem_ops[]; +extern i32 g_mem_type_num; +#endif diff --git a/src/framework/common/mem_mgr/include/nsfw_ring_data.h b/src/framework/common/mem_mgr/include/nsfw_ring_data.h new file mode 100644 index 0000000..99ec0ed --- /dev/null +++ b/src/framework/common/mem_mgr/include/nsfw_ring_data.h @@ -0,0 +1,95 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RING_DATA_H_ +#define _NSFW_RING_DATA_H_ + +#include <stdint.h> +#include "types.h" +#include "common_mem_api.h" + +#define VALUE_LEN 40 + +/* +Ring Data has two part; Ver&Data +val is a pointer offset base on rte_perf_ring::Addrbase, this struct support 1TB, it's enough now; +future __int128 maybe used, this type can perfectly solve the version & address rang problem. +*/ +union RingData_U +{ + struct RingData_S + { + /* + value of data, indeed it's a pointer offset base on rte_perf_ring::Addrbase;40bit is enough for user space addr + ver must using 24bit, so val using 40bit; a CAS now just support 64bit; in future, we may using __int128,now __int128 not support well. + */ + volatile unsigned long long val:VALUE_LEN; + /* + version of data, using 16b store version flg is more suitable for Address save, but using 16b version is too short, it's value range is [0-65535]; + between two cpu schedule time (TM-SPACE) of one process/thread, other processes/threads do N times queue oper. if N > 65535, still have a chance of ABA. + if using a 24bit save version flg, if ABA happened, 16777216 times queue oper need done in one TM-SPACE, it's impossible for today cpu. + */ + volatile unsigned long long ver:(64 - VALUE_LEN); + } data_s; + u64 data_l; +}; + +/* + this high perf Ring rely on the init value of Ring Slot; + Ring Must init using PerfRingInit, Pool Must init using PerfPoolInit + + the addrbase is base addr for all element; now we support 1024G offset; + for nstack the Ring element is from hugepage, and the addr is in stack space. + + 1. not support a ring who's element space range bigger than 1024GB + [if one element from heep, one from stack, range will bigger than 1024GB, we not support] + 2. one more thing addr from mmap is in stack + 3. rte_perf_ring must create by rte_perf_ring_create/rte_perf_pool_create +*/ +struct nsfw_mem_ring +{ + u8 memtype; //shared, no shared + u8 ringflag; //scmp, scsp, mcsp,mcmp + u16 reserv; //reserv data + u32 size; //size of the Ring, must 2^n + u32 eltsize; //for sppool, it is the size of per buf, if is ring, eltsize is zero. + u32 mask; //mask of the Ring, used mask mod Head/Tail to get real pos, must 2^n-1 + void *Addrbase; /*Cause the Addr we support just 40b(1024G), we using a basAddr+offset to get the real addr; ring[x].data_s.val just store offset; + * not used when no shared mode + */ + volatile u32_t prodhflag; //for nshmem fork recover + volatile u32_t prodtflag; //for nshmem fork recover + volatile u32_t conshflag; //for nshmem fork recover + volatile u32_t constflag; //for nshmem fork recover + nsfw_res res_chk; + + struct + { + volatile u32 head; //Head of the Ring, used to indicat pos where to pull a val + volatile u32 tail; //for nshmem, shmem not used. + } prod; + struct + { + volatile u32 head; //for nshmem, shmem not used. + volatile u32 tail; //Tail of the Ring, used to indicat pos where to push a val + } cons; + u32 uireserv[4]; //reserved for update + union RingData_U ring[0]; //Value of Ring +}; + +#define PERFRING_ADDR_RANGE (0xFFFFFFFFFFL) + +#endif /*_NSFW_RING_DATA_H_*/ diff --git a/src/framework/common/mem_mgr/include/nsfw_ring_fun.h b/src/framework/common/mem_mgr/include/nsfw_ring_fun.h new file mode 100644 index 0000000..57a7bf3 --- /dev/null +++ b/src/framework/common/mem_mgr/include/nsfw_ring_fun.h @@ -0,0 +1,110 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RING_FUN_H_ +#define _NSFW_RING_FUN_H_ + +#include <stdint.h> +#include "common_pal_bitwide_adjust.h" +#include "nsfw_mem_api.h" +#include "nsfw_ring_data.h" + +/* + for nstack I advise addrbase set to lowest of mmaped hugepage Addr. + to simple: + 1. ring element is from mmaped mem, set Addrbase to 0x7fffffffffff - 0xffffffffff is OK; + 1. ring element is from heap, set Addrbase to NULL is ok; +*/ +static inline void +nsfw_mem_ring_init (struct nsfw_mem_ring *ring, unsigned int size, + void *addrbase, unsigned char memtype, unsigned char flag) +{ + unsigned int loop = 0; + + if (!ring) + { + return; + } + + ring->prod.head = 0; + ring->prod.tail = 0; + ring->cons.head = 0; + ring->cons.tail = 0; + ring->size = size; + ring->eltsize = 0; + ring->mask = size - 1; + ring->memtype = memtype; + ring->ringflag = flag; + ring->prodtflag = ring->prodhflag = get_sys_pid (); + ring->conshflag = ring->constflag = get_sys_pid (); + /*if shmem, addrbase already changed to primary memory address */ + ring->Addrbase = addrbase; + ring->uireserv[0] = 0; + ring->uireserv[1] = 0; + ring->uireserv[2] = 0; + ring->uireserv[3] = 0; + + /*init Ring */ + for (loop = 0; loop < size; loop++) + { + /* + for a empty ring, version is the mapping head val - size + so the empty ring's ver is loop-size; + */ + ring->ring[loop].data_s.ver = (loop - size); + ring->ring[loop].data_s.val = 0; + } +} + +/* +another way to init Pool while no continuous space +1. init a empt rte_perf_ring +2. add element to PerRing. +*/ +static inline void +nsfw_mem_pool_head_init (struct nsfw_mem_ring *ring, unsigned int size, + unsigned int eltsize, void *addrbase, + nsfw_mem_type memtype, nsfw_mpool_type flag) +{ + ring->prod.head = size; + ring->prod.tail = size; + ring->cons.head = 0; + ring->cons.tail = 0; + ring->size = size; + ring->eltsize = eltsize; + ring->mask = size - 1; + ring->memtype = memtype; + ring->ringflag = flag; + ring->prodtflag = ring->prodhflag = get_sys_pid (); + ring->conshflag = ring->constflag = get_sys_pid (); + /*if shmem, addrbase already changed to primary memory address */ + ring->Addrbase = addrbase; + ring->uireserv[0] = 0; + ring->uireserv[1] = 0; + ring->uireserv[2] = 0; + ring->uireserv[3] = 0; + return; +} + +#define NSFW_RING_FLAG_CHECK_RET(handle, desc) {\ + if (((struct nsfw_mem_ring*)mhandle)->ringflag >= NSFW_MPOOL_TYPEMAX) \ + { \ + NSCOMM_LOGERR("invalid ring] desc=%s, ringflag=%d", desc, ((struct nsfw_mem_ring*)mhandle)->ringflag); \ + return 0; \ + } \ + } + +#endif /*_NSFW_RING_FUN_H_*/ diff --git a/src/framework/common/mem_mgr/nsfw_mem_api.c b/src/framework/common/mem_mgr/nsfw_mem_api.c new file mode 100644 index 0000000..b795921 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_mem_api.c @@ -0,0 +1,879 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <sys/types.h> +#include <unistd.h> +#include "nsfw_mem_desc.h" +#include "nstack_securec.h" + +#ifdef SYS_MEM_RES_STAT +#include "common_mem_ring.h" +#include "common_mem_mempool.h" +#endif + +#define MEM_OP_CALL_OK_RET(mtype, fun, para) { \ + if (g_nsfw_mem_ops[mtype].stmemop->fun) \ + { \ + return g_nsfw_mem_ops[mtype].stmemop->fun para; \ + } \ + } + +/***************************************************************************** +* Prototype : nsfw_mem_init +* Description : memory mgr module init +* Input : point to nstak_fwmem_para +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_init (void *para) +{ + nsfw_mem_para *ptempara = NULL; + i32 iret = NSFW_MEM_OK; + i32 icount = 0; + i32 iindex = 0; + + if (NULL == para) + { + NSCOMM_LOGERR ("ns mem init input error"); + return NSFW_MEM_ERR; + } + + ptempara = (nsfw_mem_para *) para; + + if (ptempara->enflag >= NSFW_PROC_MAX) + { + NSCOMM_LOGERR ("ns mem init input enflag invalid] enflag=%d", + ptempara->enflag); + return NSFW_MEM_ERR; + } + + NSCOMM_LOGINF ("ns mem init begin] enflag=%d, iargsnum=%d", + ptempara->enflag, ptempara->iargsnum); + + for (iindex = 0; iindex < ptempara->iargsnum; iindex++) + { + NSCOMM_LOGINF ("%s", ptempara->pargs[iindex]); + } + + for (icount = 0; icount < g_mem_type_num; icount++) + { + if ((NULL != g_nsfw_mem_ops[icount].stmemop) + && (NULL != g_nsfw_mem_ops[icount].stmemop->mem_ops_init)) + { + iret = g_nsfw_mem_ops[icount].stmemop->mem_ops_init (ptempara); + + if (NSFW_MEM_OK != iret) + { + NSCOMM_LOGERR ("mem init failed]index=%d, memtype=%d", icount, + g_nsfw_mem_ops[icount].entype); + break; + } + } + } + + /*if some module init fail, destory the moudles that success */ + if (icount < g_mem_type_num) + { + for (iindex = 0; iindex < icount; iindex++) + { + if (g_nsfw_mem_ops[icount].stmemop->mem_ops_destroy) + { + g_nsfw_mem_ops[icount].stmemop->mem_ops_destroy (); + } + } + + return NSFW_MEM_ERR; + } + + NSCOMM_LOGINF ("ns mem init end"); + return NSFW_MEM_OK; +} + +/***************************************************************************** +* Prototype : nsfw_mem_zone_create +* Description : create a block memory with name +* nsfw_mem_zone::stname +* nsfw_mem_zone::isize +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_zone* pinfo +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle +nsfw_mem_zone_create (nsfw_mem_zone * pinfo) +{ + + if ((NULL == pinfo) || (pinfo->stname.entype >= NSFW_MEM_TYPEMAX)) + { + NSCOMM_LOGERR ("zone create input para error] pinfo=%p, mtype=%d", + pinfo, pinfo ? pinfo->stname.entype : (-1)); + return NULL; + } + + MEM_OP_CALL_OK_RET (pinfo->stname.entype, mem_ops_zone_creae, (pinfo)); + NSCOMM_LOGINF ("mem create fail] memtype=%d, name=%s, size=%zu", + pinfo->stname.entype, pinfo->stname.aname, pinfo->lenth); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_zone_createv +* Description : create some memory blocks +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_zone* pmeminfo +* i32 inum +* mzone_handle* paddr_array +* i32 iarray_num +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_zone_createv (nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num) +{ + if ((NULL == pmeminfo) || (NULL == paddr_array) + || (inum != iarray_num) || (inum <= 0) + || (pmeminfo[0].stname.entype >= NSFW_MEM_TYPEMAX)) + { + NSCOMM_LOGERR + ("input para error] pmeminfo=%p, inum=%d, paddr_array=%p, iarray_num=%d, mtype=%d", + pmeminfo, inum, paddr_array, iarray_num, + pmeminfo ? pmeminfo[0].stname.entype : (-1)); + return NSFW_MEM_ERR; + } + + MEM_OP_CALL_OK_RET (pmeminfo[0].stname.entype, mem_ops_zone_createv, + (pmeminfo, inum, paddr_array, iarray_num)); + NSCOMM_LOGINF ("mem create fail] memtype=%d", pmeminfo[0].stname.entype); + return NSFW_MEM_ERR; +} + +/***************************************************************************** +* Prototype : nsfw_mem_zone_lookup +* Description : look up a memory +* 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* 2. if the memory is shared, pname->enowner indicate that who create this memory. +* note : 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, +* end with none created by nStackMaster, and end with _<pid> created by other. +* 2. pname->enowner is available only when call look up shared memory. +* 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, +* the name must be full name. +* for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, +* must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add +* _(pid) at the end of name, nstack_123. +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle +nsfw_mem_zone_lookup (nsfw_mem_name * pname) +{ + NSFW_MEM_NAME_CHECK_RET_NULL (pname, "mem zone look up"); + MEM_OP_CALL_OK_RET (pname->entype, mem_ops_zone_lookup, (pname)); + NSCOMM_LOGERR ("mem lookup fail] memtype=%d, name=%s ", pname->entype, + pname->aname); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_zone_release +* Description : release a memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_zone_release (nsfw_mem_name * pname) +{ + NSFW_MEM_NAME_CHECK_RET_ERR (pname, "mem zone release"); + MEM_OP_CALL_OK_RET (pname->entype, mem_ops_mzone_release, (pname)); + NSCOMM_LOGERR ("mem release fail] memtype=%d, name=%s", pname->entype, + pname->aname); + return NSFW_MEM_ERR; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbfmp_create +* Description : create a mbuf pool +* Input : nsfw_mem_mbfpool* pbufinfo +* Output : None +* Return Value : mpool_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mpool_handle +nsfw_mem_mbfmp_create (nsfw_mem_mbfpool * pbufinfo) +{ + if ((NULL == pbufinfo) || (pbufinfo->stname.entype >= NSFW_MEM_TYPEMAX)) + { + NSCOMM_LOGERR ("input para error] pbufinfo=%p, mtype=%d", pbufinfo, + pbufinfo ? pbufinfo->stname.entype : (-1)); + return NULL; + } + + MEM_OP_CALL_OK_RET (pbufinfo->stname.entype, mem_ops_mbfmp_create, + (pbufinfo)); + NSCOMM_LOGERR ("mbufmp create fail] memtype=%d, name=%s ", + pbufinfo->stname.entype, pbufinfo->stname.aname); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbfmp_createv +* Description : create some mbuf pools +* 1. the name of lenth must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_mbfpool* pmbfname +* i32 inum +* mpool_handle* phandle_array +* i32 iarray_num +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_mbfmp_createv (nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num) +{ + if ((NULL == pmbfname) || (NULL == phandle_array) + || (inum != iarray_num) || (inum <= 0) + || (pmbfname[0].stname.entype >= NSFW_MEM_TYPEMAX)) + { + NSCOMM_LOGERR + ("input para error] pmbfname=%p, inum=%d, phandle_array=%p, iarray_num=%d", + pmbfname, inum, phandle_array, iarray_num, + pmbfname ? pmbfname[0].stname.entype : (-1)); + return NSFW_MEM_ERR; + } + + MEM_OP_CALL_OK_RET (pmbfname[0].stname.entype, mem_ops_mbfmp_createv, + (pmbfname, inum, phandle_array, iarray_num)); + NSCOMM_LOGERR ("mbufmp createv fail] memtype=%d", + pmbfname[0].stname.entype); + return NSFW_MEM_ERR; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbf_alloc +* Description : alloc a mbuf from mbuf pool +* Input : mpool_handle mhandle +* nsfw_mem_type entype +* Output : None +* Return Value : mbuf_handle +* Calls : +* Called By : +*****************************************************************************/ +mbuf_handle +nsfw_mem_mbf_alloc (mpool_handle mhandle, nsfw_mem_type entype) +{ + NSFW_MEM_MBUF_CHECK_RET_NULL (mhandle, entype, "mbf alloc"); + MEM_OP_CALL_OK_RET (entype, mem_ops_mbf_alloc, (mhandle)); + NSCOMM_LOGERR ("mbf alloc fail] handle=%p, type=%d", mhandle, entype); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbf_free +* Description : put a mbuf backintp mbuf pool +* Input : mbuf_handle mhandle +* nsfw_mem_type entype +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_mbf_free (mbuf_handle mhandle, nsfw_mem_type entype) +{ + NSFW_MEM_MBUF_CHECK_RET_ERR (mhandle, entype, "mbuf free"); + MEM_OP_CALL_OK_RET (entype, mem_ops_mbf_free, (mhandle)); + NSCOMM_LOGERR ("mbf free fail] handle=%p, type=%d", mhandle, entype); + return NSFW_MEM_ERR; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbfmp_lookup +* Description : look up mbuf mpool +* 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* 2. if the memory is shared, pname->enowner indicate that who create this memory. +* note : 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, +* end with none created by nStackMaster, and end with _<pid> created by other. +* 2. pname->enowner is available only when call look up shared memory. +* 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, +* the name must be full name. +* for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, +* must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add +* _(pid) at the end of name, nstack_123. +* Input : nsfw_mem_name* pmbfname +* Output : None +* Return Value : mpool_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mpool_handle +nsfw_mem_mbfmp_lookup (nsfw_mem_name * pmbfname) +{ + NSFW_MEM_NAME_CHECK_RET_NULL (pmbfname, "mbuf pool look up"); + MEM_OP_CALL_OK_RET (pmbfname->entype, mem_ops_mbfmp_lookup, (pmbfname)); + NSCOMM_LOGERR ("mbufmp lookup fail] memtype=%d, name=%s ", pmbfname->entype, + pmbfname->aname); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbfmp_release +* Description : release mbuf pool +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_mbfmp_release (nsfw_mem_name * pname) +{ + NSFW_MEM_NAME_CHECK_RET_ERR (pname, "mbuf mp release"); + MEM_OP_CALL_OK_RET (pname->entype, mem_ops_mbfmp_release, (pname)); + NSCOMM_LOGERR ("mbfmp release fail] memtype=%d, name=%s", pname->entype, + pname->aname); + return NSFW_MEM_ERR; +} + +/***************************************************************************** +* Prototype : nsfw_mem_sp_create +* Description : create a simple pool +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_sppool* pmpinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +nsfw_mem_sp_create (nsfw_mem_sppool * pmpinfo) +{ + if ((NULL == pmpinfo) || (pmpinfo->stname.entype >= NSFW_MEM_TYPEMAX)) + { + NSCOMM_LOGERR ("input para error] pmpinfo=%p, mtype=%d", pmpinfo, + pmpinfo ? pmpinfo->stname.entype : (-1)); + return NULL; + } + + MEM_OP_CALL_OK_RET (pmpinfo->stname.entype, mem_ops_sp_create, (pmpinfo)); + NSCOMM_LOGERR ("sp create fail] memtype=%d, name=%s ", + pmpinfo->stname.entype, pmpinfo->stname.aname); + return NULL; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_sp_createv +* Description : create some simple pools one time +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_sppool* pmpinfo +* i32 inum +* mring_handle* pringhandle_array +* i32 iarray_num +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_sp_createv (nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num) +{ + NSFW_MEM_RINGV_CHECK_RET (pmpinfo, inum, pringhandle_array, iarray_num); + MEM_OP_CALL_OK_RET (pmpinfo[0].stname.entype, mem_ops_sp_createv, + (pmpinfo, inum, pringhandle_array, iarray_num)); + NSCOMM_LOGERR ("sp createv fail] memtype=%d", pmpinfo[0].stname.entype); + return NSFW_MEM_ERR; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_sp_ring_create +* Description : create a simple pool with many rings +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_mring* pringinfo +* mring_handle* pringhandle_array +* i32 iringnum +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_sp_ring_create (nsfw_mem_mring * pringinfo, + mring_handle * pringhandle_array, i32 iringnum) +{ + NSFW_MEM_RING_CHECK_RET (pringinfo, pringhandle_array, iringnum); + MEM_OP_CALL_OK_RET (pringinfo[0].stname.entype, mem_ops_spring_create, + (pringinfo, pringhandle_array, iringnum)); + NSCOMM_LOGERR ("mppool spring creat fail] memtype=%d", + pringinfo[0].stname.entype); + return NSFW_MEM_ERR; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_sp_release +* Description : release a simple mempool +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mem_sp_release (nsfw_mem_name * pname) +{ + NSFW_MEM_NAME_CHECK_RET_ERR (pname, "sp release"); + MEM_OP_CALL_OK_RET (pname->entype, mem_ops_sp_release, (pname)); + NSCOMM_LOGERR ("sp release fail] memtype=%d, name=%s ", pname->entype, + pname->aname); + return NSFW_MEM_ERR; +} + +/***************************************************************************** +* Prototype : nsfw_mem_sp_lookup +* Description : look up a simpile ring +* 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* 2. if the memory is shared, pname->enowner indicate that who create this memory. +* note : 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, +* end with none created by nStackMaster, and end with _<pid> created by other. +* 2. pname->enowner is available only when call look up shared memory. +* 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, +* the name must be full name. +* for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, +* must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add +* _(pid) at the end of name, nstack_123. +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +nsfw_mem_sp_lookup (nsfw_mem_name * pname) +{ + NSFW_MEM_NAME_CHECK_RET_NULL (pname, "sp look up"); + MEM_OP_CALL_OK_RET (pname->entype, mem_ops_sp_lookup, (pname)); + NSCOMM_LOGERR ("sp lookup fail] memtype=%d, name=%s", pname->entype, + pname->aname); + return NULL; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_create +* Description : create a ring +* note : 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* 2. shared memory ring (NSFW_SHMEM) just can put a pointor into the queue, the queue also point to a shared block memory. +* no shared memory ring(NSFW_NSHMEM) is other wise. +* Input : nsfw_mem_mring* pringinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +nsfw_mem_ring_create (nsfw_mem_mring * pringinfo) +{ + if ((NULL == pringinfo) || (pringinfo->stname.entype >= NSFW_MEM_TYPEMAX)) + { + NSCOMM_LOGERR ("input para error] pmpinfo=%p, mtype=%d", pringinfo, + pringinfo ? pringinfo->stname.entype : (-1)); + return NULL; + } + + MEM_OP_CALL_OK_RET (pringinfo->stname.entype, mem_ops_ring_create, + (pringinfo)); + NSCOMM_LOGERR ("ring create fail] memtype=%d, name=%s ", + pringinfo->stname.entype, pringinfo->stname.aname); + return NULL; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_lookup +* Description : look up a ring by name +* 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. +* 2. if the memory is shared, pname->enowner indicate that who create this memory. +* note: +* 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, +* end with none created by nStackMaster, and end with _<pid> created by other. +* 2. pname->enowner is available only when call look up shared memory. +* 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, +* the name must be full name. +* for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, +* must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add +* _(pid) at the end of name, nstack_123. +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +* +*****************************************************************************/ +mring_handle +nsfw_mem_ring_lookup (nsfw_mem_name * pname) +{ + NSFW_MEM_NAME_CHECK_RET_NULL (pname, "ring lookup"); + MEM_OP_CALL_OK_RET (pname->entype, mem_ops_ring_lookup, (pname)); + NSCOMM_LOGERR ("ring lookup fail] memtype=%d, name=%s", pname->entype, + pname->aname); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_reset +* Description : reset the number of producer and consumer, also, the +* state of ring reset to empty +* notes : must be called before doing any operations base on the ring +* Input : mring_handle mhandle +* nsfw_mpool_type entype +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_mem_ring_reset (mring_handle mhandle, nsfw_mpool_type entype) +{ + u32 loop = 0; + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) mhandle; + + if (!ring) + { + return; + } + + ring->prod.head = 0; + ring->cons.tail = 0; + ring->ringflag = (u8) entype; + + /*init Ring */ + for (loop = 0; loop < ring->size; loop++) + { + /* + for a empty ring, version is the mapping head val - size + so the empty ring's ver is loop-size; + */ + ring->ring[loop].data_s.ver = (loop - ring->size); + ring->ring[loop].data_s.val = 0; + } + + return; +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_free_count +* Description : get the free number of ring +* Input : mring_handle mhandle +* Output : None +* Return Value : u32 +* Calls : +* Called By : +* +*****************************************************************************/ +u32 +nsfw_mem_ring_free_count (mring_handle mhandle) +{ + struct nsfw_mem_ring *temp = NULL; + u32 thead = 0; + u32 ttail = 0; + if (NULL == mhandle) + { + NSCOMM_LOGERR ("input para error] mhandle=%p", mhandle); + return 0; + } + + temp = (struct nsfw_mem_ring *) mhandle; + thead = temp->prod.head; + ttail = temp->cons.tail; + return ttail + temp->size - thead; +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_using_count +* Description : get the in using number of ring +* Input : mring_handle mhandle +* Output : None +* Return Value : u32 +* Calls : +* Called By : +* +*****************************************************************************/ +u32 +nsfw_mem_ring_using_count (mring_handle mhandle) +{ + struct nsfw_mem_ring *temp = NULL; + u32 thead = 0; + u32 ttail = 0; + if (NULL == mhandle) + { + NSCOMM_LOGERR ("input para error] mhandle=%p", mhandle); + return 0; + } + + temp = (struct nsfw_mem_ring *) mhandle; + thead = temp->prod.head; + ttail = temp->cons.tail; + return thead - ttail; +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_size +* Description : get size of ring +* Input : mring_handle mhandle +* Output : None +* Return Value : u32 +* Calls : +* Called By : +*****************************************************************************/ +u32 +nsfw_mem_ring_size (mring_handle mhandle) +{ + struct nsfw_mem_ring *temp = NULL; + + if (NULL == mhandle) + { + NSCOMM_LOGERR ("input para error] mhandle=%p", mhandle); + return 0; + } + + temp = (struct nsfw_mem_ring *) mhandle; + + return temp->size; +} + +#ifdef SYS_MEM_RES_STAT +/***************************************************************************** +* Prototype : nsfw_mem_mbfpool_free_count +* Description : get the free mbuf count of a mbuf pool +* Input : mpool_handle mhandle +* Output : None +* Return Value : u32 +* Calls : +* Called By : +* +*****************************************************************************/ +u32 +nsfw_mem_mbfpool_free_count (mpool_handle mhandle) +{ + if (!mhandle) + { + NSCOMM_LOGERR ("input para error] mhandle=%p", mhandle); + return 0; + } + struct common_mem_mempool *mp = (struct common_mem_mempool *) mhandle; + struct common_mem_ring *mp_ring = + (struct common_mem_ring *) (mp->ring_align); + if (!mp_ring) + { + NSCOMM_LOGERR ("ring is null"); + return 0; + } + u32 p_head = mp_ring->prod.head; + u32 c_tail = mp_ring->cons.tail; + + return p_head - c_tail; +} +#endif /* SYS_MEM_RES_STAT */ + +/***************************************************************************** +* Prototype : nsfw_mem_ring_release +* Description : release a ring memory +* notes : the lenth of name must be less than NSFW_MEM_APPNAME_LENTH +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mem_ring_release (nsfw_mem_name * pname) +{ + NSFW_MEM_NAME_CHECK_RET_ERR (pname, "ring release"); + MEM_OP_CALL_OK_RET (pname->entype, mem_ops_ring_release, (pname)); + NSCOMM_LOGERR ("ring release fail] name=%s, type=%d", pname->aname, + pname->entype); + return NSFW_MEM_ERR; + +} + +/***************************************************************************** +* Prototype : nsfw_mem_get_len +* Description : statics mbufpool, sppool, ring mem size. +* return: <=0, err happen, >0 mem size +* NSFW_MEM_MZONE: not surport because you already know the lenth when create +* Input : void * handle +* nsfw_mem_struct_type type +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +*****************************************************************************/ +ssize_t +nsfw_mem_get_len (void *handle, nsfw_mem_struct_type type) +{ + if (NULL == handle) + { + NSCOMM_LOGERR ("input para error] handle=%p", handle); + return -1; + } + if ((NSFW_MEM_SPOOL == type) || (NSFW_MEM_RING == type)) + { + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) handle; + if (ring->memtype >= NSFW_MEM_TYPEMAX) + { + NSCOMM_LOGERR ("invalid ring] ring type=%u ,handle=%p", + ring->memtype, handle); + return -1; + } + MEM_OP_CALL_OK_RET (ring->memtype, mem_ops_mem_statics, (handle, type)); + } + else + { + MEM_OP_CALL_OK_RET (NSFW_SHMEM, mem_ops_mem_statics, (handle, type)); + } + return -1; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbuf_pool_recycle +* Description : recycle mbuf +* Input : mpool_handle handle +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mem_mbuf_pool_recycle (mpool_handle handle) +{ + MEM_OP_CALL_OK_RET (NSFW_SHMEM, mem_ops_mbuf_recycle, (handle)); + return -1; +} + +/***************************************************************************** +* Prototype : nsfw_mem_sp_iterator +* Description : spool iterator +* Input : mpool_handle handle +* u32 start +* u32 end +* nsfw_mem_item_fun fun +* void *argv +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_sp_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + MEM_OP_CALL_OK_RET (NSFW_SHMEM, mem_ops_sp_iterator, + (handle, start, end, fun, argv)); + return -1; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbuf_iterator +* Description : mbuf iterator +* Input : mpool_handle handle +* u32 start +* u32 end +* nsfw_mem_item_fun fun +* void *argv +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_mem_mbuf_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + MEM_OP_CALL_OK_RET (NSFW_SHMEM, mem_ops_mbuf_iterator, + (handle, start, end, fun, argv)); + return -1; +} + +/***************************************************************************** +* Prototype : nsfw_mem_dfx_ring_print +* Description : print ring info +* Input : mring_handle mhandle +* Output : None +* Return Value : if no err happen, return the lenth of string print, 0 or -1 maybe err happen +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mem_dfx_ring_print (mring_handle mhandle, char *pbuf, int lenth) +{ + struct nsfw_mem_ring *temp = (struct nsfw_mem_ring *) mhandle; + u32 head = 0; + u32 tail = 0; + int ret = 0; + if ((!temp) || (!pbuf) || (lenth <= 0)) + { + return 0; + } + head = temp->prod.head; + tail = temp->cons.tail; + ret = + SPRINTF_S (pbuf, lenth, + "[.Head=%u,\n .Tail=%u,\n .(|Tail-Head|)=%u,\n .size=%u,\n .mask=%u]\n", + head, tail, (tail >= head) ? (tail - head) : (head - tail), + temp->size, temp->mask); + return ret; +} diff --git a/src/framework/common/mem_mgr/nsfw_mem_construct.c b/src/framework/common/mem_mgr/nsfw_mem_construct.c new file mode 100644 index 0000000..ed6fe27 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_mem_construct.c @@ -0,0 +1,21 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_init.h" +#include "nsfw_mem_api.h" + +NSFW_MODULE_NAME (NSFW_MEM_MGR_MODULE) +NSFW_MODULE_PRIORITY (10) NSFW_MODULE_INIT (nsfw_mem_init) diff --git a/src/framework/common/mem_mgr/nsfw_mem_desc.c b/src/framework/common/mem_mgr/nsfw_mem_desc.c new file mode 100644 index 0000000..d0fbfd3 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_mem_desc.c @@ -0,0 +1,92 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <sys/types.h> +#include <unistd.h> +#include "nsfw_mem_desc.h" +#include "nsfw_shmem_mdesc.h" +#include "nsfw_nshmem_mdesc.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_nshmem_ring.h" + +/* *INDENT-OFF* */ +/*the order you add must be NSFW_SHMEM, NSFW_NSHMEM*/ +nsfw_mem_attr g_nsfw_mem_ops[] = +{ + {NSFW_SHMEM, &g_shmem_ops}, + {NSFW_NSHMEM, &g_nshmem_ops}, +}; + +i32 g_mem_type_num = sizeof(g_nsfw_mem_ops) / sizeof(nsfw_mem_attr); + + +nsfw_ring_ops g_ring_ops_arry[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX] = { + { + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_singlethread_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_singlethread_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_singlethread_dequeuev + } + }, + { + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_singlethread_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_singlethread_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_singlethread_dequeuev + } + } +}; +/* *INDENT-ON* */ diff --git a/src/framework/common/mem_mgr/nsfw_mem_stat.c b/src/framework/common/mem_mgr/nsfw_mem_stat.c new file mode 100644 index 0000000..f7a1f41 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_mem_stat.c @@ -0,0 +1,292 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nstack_log.h" +#include "nsfw_maintain_api.h" +#include "nsfw_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_MEM_STAT_NUM 512 + +#define NSFW_MEM_STAT_MODULE "nsfw_mem_stat_module" + +typedef struct _nsfw_mem_stat +{ + u8 mem_type; + u8 alloc_flag; + char module[NSFW_MEM_MODULE_LEN]; + char mem_name[NSFW_MEM_NAME_LEN]; + u32 mem_size; +} nsfw_mem_stat_t; + +nsfw_mem_stat_t g_mem_stat[NSFW_MEM_STAT_NUM]; + +#ifdef SYS_MEM_RES_STAT +#define MAX_STAT_ITEM_NUM 20 +typedef struct _mem_stat_item_t +{ + char name[32]; + u64 size; +} mem_stat_item_t; + +typedef struct _mem_stat_mgr_t +{ + u32 item_num; + mem_stat_item_t item[MAX_STAT_ITEM_NUM]; +} mem_stat_mgr; + +mem_stat_mgr g_max_mem_list; +#endif + +/***************************************************************************** +* Prototype : nsfw_mem_stat +* Description : add memory stat +* Input : char *module +* char *mem_name +* u8 mem_type +* u32 mem_size +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_mem_stat (char *module, char *mem_name, u8 mem_type, u32 mem_size) +{ + if (NULL == module || NULL == mem_name) + { + NSFW_LOGERR ("argv err]module=%p,mem_name=%p", module, mem_name); + return; + } + + int i; + nsfw_mem_stat_t *mem_stat_item = NULL; + for (i = 0; i < NSFW_MEM_STAT_NUM; i++) + { + if (FALSE == g_mem_stat[i].alloc_flag) + { + g_mem_stat[i].alloc_flag = TRUE; + mem_stat_item = &g_mem_stat[i]; + break; + } + } + + if (NULL == mem_stat_item) + { + NSFW_LOGERR ("mem stat full]module=%s,type=%u,name=%s,size=%u", + module, mem_type, mem_name, mem_size); + return; + } + + mem_stat_item->mem_type = mem_type; + mem_stat_item->mem_size = mem_size; + + if (EOK != STRCPY_S (mem_stat_item->module, NSFW_MEM_MODULE_LEN, module)) + { + NSFW_LOGERR ("STRNCPY_S failed"); + return; + } + if (EOK != STRCPY_S (mem_stat_item->mem_name, NSFW_MEM_NAME_LEN, mem_name)) + { + NSFW_LOGERR ("STRNCPY_S failed"); + return; + } + + return; +} + +/***************************************************************************** +* Prototype : nsfw_mem_stat_print +* Description : print all memory info +* Input : None +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_mem_stat_print () +{ + int i; + for (i = 0; i < NSFW_MEM_STAT_NUM; i++) + { + if (TRUE == g_mem_stat[i].alloc_flag) + { + NSFW_LOGINF ("mem_module=%s,name=%s,type=%u,size=%u", + g_mem_stat[i].module, g_mem_stat[i].mem_name, + g_mem_stat[i].mem_type, g_mem_stat[i].mem_size); + } + } + +} + +#ifdef SYS_MEM_RES_STAT +void +clear_mem_stat_item () +{ + if (EOK != MEMSET_S ((char *) &g_max_mem_list, sizeof (mem_stat_mgr), + 0, sizeof (mem_stat_mgr))) + { + NSFW_LOGERR ("MEMSET_S failed"); + } +} + +void +insert_mem_stat_item (char *name, u64 len) +{ + int j, temp; + + if (g_max_mem_list.item_num == 0) + { + if (EOK != + STRCPY_S (g_max_mem_list.item[0].name, + sizeof (g_max_mem_list.item[0].name), name)) + { + NSFW_LOGERR ("STRCPY_S failed"); + } + g_max_mem_list.item[0].size = len; + g_max_mem_list.item_num++; + return; + } + else if (g_max_mem_list.item_num < MAX_STAT_ITEM_NUM) + { + if (len <= g_max_mem_list.item[g_max_mem_list.item_num - 1].size) + { + if (EOK != + STRCPY_S (g_max_mem_list.item[g_max_mem_list.item_num].name, + sizeof (g_max_mem_list.item + [g_max_mem_list.item_num].name), name)) + { + NSFW_LOGERR ("STRCPY_S failed"); + } + g_max_mem_list.item[g_max_mem_list.item_num].size = len; + g_max_mem_list.item_num++; + return; + } + j = 0; + temp = g_max_mem_list.item_num; + while (j < temp) + { + if (len >= g_max_mem_list.item[j].size) + { + goto insert_it; + } + j++; + } + if (j == temp) + { + if (EOK != + STRCPY_S (g_max_mem_list.item[j].name, + sizeof (g_max_mem_list.item[j].name), name)) + { + NSFW_LOGERR ("STRCPY_S failed"); + } + g_max_mem_list.item[j].size = len; + g_max_mem_list.item_num++; + return; + } + } + else + { + j = 0; + temp = MAX_STAT_ITEM_NUM - 1; + while (j < MAX_STAT_ITEM_NUM) + { + if (len >= g_max_mem_list.item[j].size) + { + goto insert_it; + } + j++; + } + } + + return; + +insert_it: + while (temp - 1 >= j) + { + if (EOK != + STRCPY_S (g_max_mem_list.item[temp].name, + sizeof (g_max_mem_list.item[temp].name), + g_max_mem_list.item[temp - 1].name)) + { + NSFW_LOGERR ("STRCPY_S failed"); + } + g_max_mem_list.item[temp].size = g_max_mem_list.item[temp - 1].size; + temp--; + } + if (EOK != + STRCPY_S (g_max_mem_list.item[j].name, + sizeof (g_max_mem_list.item[j].name), name)) + { + NSFW_LOGERR ("STRCPY_S failed"); + } + g_max_mem_list.item[j].size = len; + g_max_mem_list.item_num++; + return; +} + +int +get_mem_stat_item (int idx, char **name, u64 * len) +{ + if (idx < 0 || idx >= MAX_STAT_ITEM_NUM) + { + return -1; + } + + *name = g_max_mem_list.item[idx].name; + *len = g_max_mem_list.item[idx].size; + + return 0; +} +#endif + +static int nsfw_mem_stat_init (void *param); +static int +nsfw_mem_stat_init (void *param) +{ + MEM_STAT (NSFW_MEM_STAT_MODULE, "g_mem_stat", NSFW_NSHMEM, + sizeof (g_mem_stat)); + nsfw_mem_stat_print (); +#ifdef SYS_MEM_RES_STAT + clear_mem_stat_item (); +#endif + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_MEM_STAT_MODULE) +NSFW_MODULE_PRIORITY (99) +NSFW_MODULE_INIT (nsfw_mem_stat_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mdesc.c b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mdesc.c new file mode 100644 index 0000000..c78c27e --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mdesc.c @@ -0,0 +1,47 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_mem_desc.h" +#include "nsfw_nshmem_mng.h" +#include "nsfw_nshmem_mdesc.h" + +/*no share memory access inferface*/ +nsfw_mem_ops g_nshmem_ops = { + nsfw_nshmem_init, + nsfw_nshmem_destory, + nsfw_nshmem_create, + NULL, + nsfw_nshmem_lookup, + nsfw_nshmem_release, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + nsfw_nshmem_spcreate, + NULL, + NULL, + nsfw_nshmem_sprelease, + nsfw_nshmem_sp_lookup, + nsfw_nshmem_ringcreate, + NULL, + nsfw_nshmem_ringrelease, + nsfw_nshmem_stactic, + NULL, + NULL, /*mem_ops_sp_iterator */ + NULL, /*mem_ops_mbuf_iterator */ +}; diff --git a/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mdesc.h b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mdesc.h new file mode 100644 index 0000000..1b63520 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mdesc.h @@ -0,0 +1,22 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_MDESC_H +#define _NSFW_NSHMEM_MDESC_H + +extern nsfw_mem_ops g_nshmem_ops; + +#endif diff --git a/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mng.c b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mng.c new file mode 100644 index 0000000..d5661fd --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mng.c @@ -0,0 +1,544 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nsfw_mem_desc.h" +#include "nsfw_ring_fun.h" +#include "nsfw_nshmem_ring.h" +#include "nsfw_nshmem_mng.h" + +#include "common_func.h" + +#define nsfw_get_glb_lock() (&g_nshmem_internal_cfg->mlock) + +#define NSFW_NSHMEM_INIT_CHK_RET_NULL() \ + if ((!g_nshmem_internal_cfg) || (!g_nshmem_localdata)) \ + { \ + NSCOMM_LOGDBG("Error] g_nshmem_internal_cfg=%p, g_nshmem_localdata=%p", g_nshmem_internal_cfg, g_nshmem_localdata); \ + return NULL; \ + } + +#define NSFW_NSHMEM_INIT_CHK_RET() \ + if ((!g_nshmem_internal_cfg) || (!g_nshmem_localdata)) \ + { \ + NSCOMM_LOGDBG("Error] g_nshmem_internal_cfg=%p, g_nshmem_localdata=%p", g_nshmem_internal_cfg, g_nshmem_localdata); \ + return NSFW_MEM_ERR; \ + } + +nsfw_mem_localdata *g_nshmem_localdata = NULL; +nsfw_nshmem_cfg *g_nshmem_internal_cfg = NULL; + +/*look up a mem zone*/ +NSTACK_STATIC inline nsfw_nshmem_mzone * +nsfw_nshmem_get_free_zone (void) +{ + int icnt = 0; + + /*g_nshmem_internal_cfg must not be null if come here */ + for (icnt = 0; icnt < COMMON_MEM_MAX_MEMZONE; icnt++) + { + if (g_nshmem_internal_cfg->amemzone[icnt].addr == NULL) + { + return &g_nshmem_internal_cfg->amemzone[icnt]; + } + } + + return NULL; +} + +NSTACK_STATIC inline void +nsfw_nshmem_free_zone (nsfw_nshmem_mzone * pzone) +{ + nsfw_nshmem_mzone *pzonebase = &g_nshmem_internal_cfg->amemzone[0]; + nsfw_nshmem_mzone *pzoneend = + &g_nshmem_internal_cfg->amemzone[NSFW_NSHMEM_ZONE_MAX - 1]; + + if ((((int) ((char *) pzone - (char *) pzonebase) < 0) + || ((int) ((char *) pzone - (char *) pzoneend) > 0)) + && ((unsigned int) ((char *) pzone - (char *) pzonebase) % + sizeof (nsfw_nshmem_mzone) != 0)) + { + NSCOMM_LOGERR ("nshmem free fail] mem=%p", pzone); + return; + } + if (pzone->addr) + { + free (pzone->addr); + } + pzone->addr = NULL; + + int ret = MEMSET_S ((void *) pzone, sizeof (nsfw_nshmem_mzone), 0, + sizeof (nsfw_nshmem_mzone)); + if (EOK != ret) + { + NSCOMM_LOGERR ("MEMSET_S failed] mem=%p, ret=%d", pzone, ret); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_init +* Description : nsh module init +* Input : nsfw_mem_para* para +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_nshmem_init (nsfw_mem_para * para) +{ + i32 iret = NSFW_MEM_OK; + NSCOMM_LOGINF ("nsfw nshmem init begin"); + g_nshmem_localdata = + (nsfw_mem_localdata *) malloc (sizeof (nsfw_mem_localdata)); + + if (NULL == g_nshmem_localdata) + { + NSCOMM_LOGERR ("nshmem init g_nshmem_localdata malloc fail"); + return NSFW_MEM_ERR; + } + + iret = + MEMSET_S (g_nshmem_localdata, sizeof (nsfw_mem_localdata), 0, + sizeof (nsfw_mem_localdata)); + + if (EOK != iret) + { + NSCOMM_LOGERR ("nshmem init g_nshmem_localdata MEMSET_S fail"); + goto ERROR; + } + + g_nshmem_internal_cfg = + (nsfw_nshmem_cfg *) malloc (sizeof (nsfw_nshmem_cfg)); + + if (NULL == g_nshmem_internal_cfg) + { + NSCOMM_LOGERR ("nshmem init g_nshmem_internal_cfg malloc fail"); + goto ERROR; + } + + iret = + MEMSET_S (g_nshmem_internal_cfg, sizeof (nsfw_nshmem_cfg), 0, + sizeof (nsfw_nshmem_cfg)); + + if (EOK != iret) + { + NSCOMM_LOGERR ("nshmem init g_nshmem_internal_cfg MEMSET_S fail"); + goto ERROR; + } + + g_nshmem_localdata->enflag = para->enflag; + NSCOMM_LOGINF ("nsfw nshmem init end"); + goto OK; + +ERROR: + iret = NSFW_MEM_ERR; + nsfw_nshmem_destory (); + return iret; +OK: + iret = NSFW_MEM_OK; + return iret; +} + +/* + * memory destory + */ +void +nsfw_nshmem_destory (void) +{ + if (g_nshmem_localdata) + { + free (g_nshmem_localdata); + g_nshmem_localdata = NULL; + } + + if (g_nshmem_internal_cfg) + { + free (g_nshmem_internal_cfg); + g_nshmem_internal_cfg = NULL; + } + + return; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_reserv_safe +* Description : malloc a memory and save to memzone +* Input : const char* name +* size_t lenth +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle +nsfw_nshmem_reserv_safe (const char *name, size_t lenth) +{ + void *addr = NULL; + i32 iret = NSFW_MEM_OK; + nsfw_nshmem_mzone *pmemzone = NULL; + + if (lenth <= 0) + { + return NULL; + } + + nsfw_write_lock (nsfw_get_glb_lock ()); + + addr = malloc (lenth); + if (!addr) + { + NSCOMM_LOGERR ("nshmem malloc addr fail] addr=%p", addr); + nsfw_write_unlock (nsfw_get_glb_lock ()); + return NULL; + } + + iret = MEMSET_S (addr, lenth, 0, lenth); + if (EOK != iret) + { + NSCOMM_LOGERR ("nshmem malloc addr MEMSET_S fail] addr=%p", addr); + free (addr); + nsfw_write_unlock (nsfw_get_glb_lock ()); + return NULL; + } + + pmemzone = nsfw_nshmem_get_free_zone (); + + if (!pmemzone) + { + NSCOMM_LOGERR ("nshmem get free zone fail"); + free (addr); + nsfw_write_unlock (nsfw_get_glb_lock ()); + return NULL; + } + + pmemzone->addr = addr; + pmemzone->lenth = lenth; + /*name must be less than NSFW_MEM_APPNAME_LENTH */ + if (EOK != + STRCPY_S ((char *) pmemzone->aname, sizeof (pmemzone->aname), name)) + { + NSCOMM_LOGERR ("STRCPY_S failed]name=%s", name); + free (addr); + nsfw_write_unlock (nsfw_get_glb_lock ()); + return NULL; + } + + nsfw_write_unlock (nsfw_get_glb_lock ()); + return addr; +} + +/* + * create no shared memory + * nsfw_mem_zone::stname no shared memory name + * nsfw_mem_zone::isize memory size + */ +mzone_handle +nsfw_nshmem_create (nsfw_mem_zone * pinfo) +{ + + NSFW_NAME_LENCHECK_RET_NULL (pinfo->stname.aname, "nshmem create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL (); + return nsfw_nshmem_reserv_safe (pinfo->stname.aname, pinfo->lenth); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_lookup +* Description : find a block memory by name +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle +nsfw_nshmem_lookup (nsfw_mem_name * pname) +{ + int icnt = 0; + nsfw_nshmem_mzone *mz = NULL; + + NSFW_NAME_LENCHECK_RET_NULL (pname->aname, "nshmem lookup"); + NSFW_NSHMEM_INIT_CHK_RET_NULL (); + nsfw_read_lock (nsfw_get_glb_lock ()); + + for (icnt = 0; icnt < NSFW_NSHMEM_ZONE_MAX; icnt++) + { + mz = &g_nshmem_internal_cfg->amemzone[icnt]; + + if (mz->addr != NULL + && !strncmp (pname->aname, mz->aname, NSFW_MEM_NAME_LENTH)) + { + nsfw_read_unlock (nsfw_get_glb_lock ()); + return mz->addr; + } + } + + nsfw_read_unlock (nsfw_get_glb_lock ()); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_release +* Description : free a block memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_nshmem_release (nsfw_mem_name * pname) +{ + int icnt = 0; + nsfw_nshmem_mzone *mz = NULL; + + NSFW_NAME_LENCHECK_RET (pname->aname, "nshmem release"); + NSFW_NSHMEM_INIT_CHK_RET (); + nsfw_read_lock (nsfw_get_glb_lock ()); + + for (icnt = 0; icnt < NSFW_NSHMEM_ZONE_MAX; icnt++) + { + mz = &g_nshmem_internal_cfg->amemzone[icnt]; + + if (mz->addr != NULL + && !strncmp (pname->aname, mz->aname, NSFW_MEM_NAME_LENTH)) + { + nsfw_nshmem_free_zone (mz); + nsfw_read_unlock (nsfw_get_glb_lock ()); + return NSFW_MEM_OK; + } + } + + nsfw_read_unlock (nsfw_get_glb_lock ()); + return NSFW_MEM_OK; + +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_spcreate +* Description : create a memory pool by ring +* Input : nsfw_mem_sppool* pmpinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +*****************************************************************************/ +mring_handle +nsfw_nshmem_spcreate (nsfw_mem_sppool * pmpinfo) +{ + size_t len = 0; + unsigned int usnum = common_mem_align32pow2 (pmpinfo->usnum + 1); + unsigned int uselt_size = pmpinfo->useltsize; + struct nsfw_mem_ring *pringhead = NULL; + unsigned int uscnt = 0; + char *pmz = NULL; + NSFW_NAME_LENCHECK_RET_NULL (pmpinfo->stname.aname, "nshmem sp create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL (); + + len = + sizeof (struct nsfw_mem_ring) + + (size_t) usnum *sizeof (union RingData_U) + (size_t) usnum *uselt_size; + pringhead = + (struct nsfw_mem_ring *) nsfw_nshmem_reserv_safe (pmpinfo->stname.aname, + len); + + if (!pringhead) + { + NSCOMM_LOGERR ("nshmem sp create mzone reserv fail"); + return NULL; + } + + nsfw_mem_ring_init (pringhead, usnum, pringhead, NSFW_NSHMEM, + pmpinfo->enmptype); + pmz = + ((char *) pringhead + sizeof (struct nsfw_mem_ring) + + usnum * sizeof (union RingData_U)); + + for (uscnt = 0; uscnt < usnum; uscnt++) + { + if (0 == + g_ring_ops_arry[pringhead->memtype][pringhead-> + ringflag].ring_ops_enqueue + (pringhead, (void *) pmz)) + { + NSCOMM_LOGERR ("nsfw_nshmem_ringenqueue enque fail] uscnt=%u", + uscnt); + } + + pmz = pmz + uselt_size; + } + + return pringhead; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sp_lookup +* Description : look up a sppool memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +*****************************************************************************/ +mring_handle +nsfw_nshmem_sp_lookup (nsfw_mem_name * pname) +{ + return nsfw_nshmem_lookup (pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sprelease +* Description : release a sp pool +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_nshmem_sprelease (nsfw_mem_name * pname) +{ + NSFW_NAME_LENCHECK_RET (pname->aname, "nshmem sp mempool release"); + NSFW_NSHMEM_INIT_CHK_RET (); + return nsfw_nshmem_release (pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ringcreate +* Description : create a ring +* Input : nsfw_mem_mring* pringinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle +nsfw_nshmem_ringcreate (nsfw_mem_mring * pringinfo) +{ + size_t len = 0; + unsigned int usnum = common_mem_align32pow2 (pringinfo->usnum + 1); + struct nsfw_mem_ring *pringhead = NULL; + NSFW_NAME_LENCHECK_RET_NULL (pringinfo->stname.aname, "nshmem ring create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL (); + + len = sizeof (struct nsfw_mem_ring) + usnum * sizeof (union RingData_U); + pringhead = + (struct nsfw_mem_ring *) nsfw_nshmem_reserv_safe (pringinfo->stname.aname, + len); + + if (!pringhead) + { + NSCOMM_LOGERR ("nshmem ring create mzone reserv fail"); + return NULL; + } + + nsfw_mem_ring_init (pringhead, usnum, (void *) pringhead, NSFW_NSHMEM, + pringinfo->enmptype); + return pringhead; + +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ringrelease +* Description : release a nsh ring memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 +nsfw_nshmem_ringrelease (nsfw_mem_name * pname) +{ + NSFW_NAME_LENCHECK_RET (pname->aname, "nshmem ring mempool release"); + NSFW_NSHMEM_INIT_CHK_RET (); + return nsfw_nshmem_release (pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sppool_statics +* Description : static the memory size of sppool +* Input : mring_handle sppool +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t +nsfw_nshmem_sppool_statics (mring_handle sppool) +{ + struct nsfw_mem_ring *phead = (struct nsfw_mem_ring *) sppool; + + return sizeof (struct nsfw_mem_ring) + + (ssize_t) phead->size * sizeof (union RingData_U) + + (ssize_t) phead->size * phead->eltsize; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ring_statics +* Description : static the memory size of ring +* Input : mring_handle handle +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t +nsfw_nshmem_ring_statics (mring_handle handle) +{ + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) handle; + return ring->size * sizeof (union RingData_U) + + sizeof (struct nsfw_mem_ring); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_stactic +* Description : static the memory size according to mem type +* Input : void* handle +* nsfw_mem_struct_type type +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t +nsfw_nshmem_stactic (void *handle, nsfw_mem_struct_type type) +{ + switch (type) + { + case NSFW_MEM_MBUF: + return -1; + case NSFW_MEM_SPOOL: + return nsfw_nshmem_sppool_statics (handle); + case NSFW_MEM_RING: + return nsfw_nshmem_ring_statics (handle); + default: + break; + } + return -1; +} diff --git a/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mng.h b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mng.h new file mode 100644 index 0000000..3f5b1b9 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_mng.h @@ -0,0 +1,70 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_MNG_H_ +#define _NSFW_NSHMEM_MNG_H_ + +#include "generic/common_mem_rwlock.h" + +#include "common_func.h" + +#define NSFW_NSHMEM_ZONE_MAX 2560 + +typedef struct +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + void *addr; + int lenth; +} nsfw_nshmem_mzone; + +typedef struct +{ + nsfw_nshmem_mzone amemzone[NSFW_NSHMEM_ZONE_MAX]; + common_mem_rwlock_t mlock; +} nsfw_nshmem_cfg; + +/* + * no share memory module init + */ +i32 nsfw_nshmem_init (nsfw_mem_para * para); + +/* + * no share memory moudle destory + */ +void nsfw_nshmem_destory (void); + +/* + * create a no shared memory + */ +mzone_handle nsfw_nshmem_create (nsfw_mem_zone * pinfo); + +mzone_handle nsfw_nshmem_lookup (nsfw_mem_name * pname); + +i32 nsfw_nshmem_release (nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_spcreate (nsfw_mem_sppool * pmpinfo); + +i32 nsfw_nshmem_sprelease (nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_sp_lookup (nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_ringcreate (nsfw_mem_mring * pringinfo); + +i32 nsfw_nshmem_ringrelease (nsfw_mem_name * pname); + +ssize_t nsfw_nshmem_stactic (void *handle, nsfw_mem_struct_type type); + +#endif diff --git a/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_ring.c b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_ring.c new file mode 100644 index 0000000..64e7d57 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_ring.c @@ -0,0 +1,436 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include <sched.h> +#include "nstack_securec.h" + +#include "nsfw_mem_desc.h" +#include "nsfw_nshmem_ring.h" +#include "nsfw_ring_fun.h" +#include "common_func.h" + +/*copy the data to obj*/ +NSTACK_STATIC inline void +nsfw_nshmem_ring_obj_copy (struct nsfw_mem_ring *r, uint32_t cons_head, + void **obj_table, unsigned n) +{ + uint32_t idx = cons_head & r->mask; + unsigned i = 0; + const uint32_t size = r->size; + + if (likely (idx + n < size)) + { + for (i = 0; i < (n & (~(unsigned) 0x3)); i += 4, idx += 4) + { + obj_table[i] = (void *) r->ring[idx].data_l; + obj_table[i + 1] = (void *) r->ring[idx + 1].data_l; + obj_table[i + 2] = (void *) r->ring[idx + 2].data_l; + obj_table[i + 3] = (void *) r->ring[idx + 3].data_l; + } + switch (n & 0x3) + { + case 3: + obj_table[i++] = (void *) r->ring[idx++].data_l; + + case 2: + obj_table[i++] = (void *) r->ring[idx++].data_l; + + case 1: + obj_table[i++] = (void *) r->ring[idx++].data_l; + } + } + else + { + for (i = 0; idx < size; i++, idx++) + { + obj_table[i] = (void *) r->ring[idx].data_l; + } + + for (idx = 0; i < n; i++, idx++) + { + obj_table[i] = (void *) r->ring[idx].data_l; + } + } +} + +/*fork recover*/ +NSTACK_STATIC inline void +nsfw_nshmem_enqueue_fork_recov (struct nsfw_mem_ring *r) +{ + u32_t pidflag = 0; + u32_t curpid = get_sys_pid (); + int success = 0; + /*if pid is not the same, maybe mult thread fork happen */ + pidflag = r->prodhflag; + + if (unlikely (pidflag != curpid)) + { + success = common_mem_atomic32_cmpset (&r->prodhflag, pidflag, curpid); + + if (unlikely (success != 0)) + { + /*recover it */ + if (r->prod.tail != r->prod.head) + { + r->prod.head = r->prod.tail; + } + + r->prodtflag = curpid; + } + } + + return; +} + +NSTACK_STATIC inline void +nsfw_nshmem_dequeue_fork_recov (struct nsfw_mem_ring *r) +{ + u32_t pidflag = 0; + u32_t curpid = get_sys_pid (); + int success = 0; + /*if pid is not the same, maybe mult thread fork happen */ + pidflag = r->conshflag; + + if (unlikely (pidflag != curpid)) + { + success = common_mem_atomic32_cmpset (&r->conshflag, pidflag, curpid); + + if (unlikely (success != 0)) + { + /*recover it */ + if (r->cons.tail != r->cons.head) + { + r->cons.head = r->cons.tail; + } + + r->constflag = curpid; + } + } + + return; +} + +/* +this is a multi thread/process enqueue function, please pay attention to the bellow point +1. while Enqueue corrupt, we may lose one element; because no one to add the Head +*/ +int +nsfw_nshmem_ring_mp_enqueue (struct nsfw_mem_ring *mem_ring, void *obj_table) +{ + uint32_t prod_head, prod_next; + uint32_t cons_tail, free_entries; + int success; + unsigned rep = 0; + uint32_t mask = mem_ring->mask; + uint32_t size = mem_ring->size; + uint32_t n = 1; + + /* move prod.head atomically */ + do + { + + prod_head = mem_ring->prod.head; + cons_tail = mem_ring->cons.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * prod_head > cons_tail). So 'free_entries' is always between 0 + * and size(ring)-1. */ + free_entries = (size + cons_tail - prod_head); + + /* check that we have enough room in ring */ + if (unlikely (n > free_entries)) + { + return 0; + /* Below code is commented currenlty as its a dead code. */ + } + + /*if pid is not the same, maybe mult thread fork happen */ + nsfw_nshmem_enqueue_fork_recov (mem_ring); + + while (unlikely + ((mem_ring->prod.tail != mem_ring->prod.head) + || (mem_ring->prodtflag != mem_ring->prodhflag))) + { + common_mem_pause (); + } + + prod_next = prod_head + n; + success = + common_mem_atomic32_cmpset (&mem_ring->prod.head, prod_head, + prod_next); + } + while (unlikely (success == 0)); + + mem_ring->ring[prod_head & mask].data_l = (u64) obj_table; + + /* + * If there are other enqueues in progress that preceded us, + * we need to wait for them to complete + */ + while (unlikely (mem_ring->prod.tail != prod_head)) + { + common_mem_pause (); + + /* Set COMMON_RING_PAUSE_REP_COUNT to avoid spin too long waiting + * for other thread finish. It gives pre-empted thread a chance + * to proceed and finish with ring dequeue operation. */ + /* check the queue can be operate */ + if (++rep == 5) + { + rep = 0; + (void) sched_yield (); + } + } + + mem_ring->prod.tail = prod_next; + return (int) n; +} + +/* + this is a single thread/process enqueue function + */ +int +nsfw_nshmem_ring_sp_enqueue (struct nsfw_mem_ring *r, void *obj_table) +{ + uint32_t prod_head, cons_tail; + uint32_t prod_next, free_entries; + uint32_t mask = r->mask; + uint32_t n = 1; + uint32_t size = r->size; + + prod_head = r->prod.head; + cons_tail = r->cons.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * prod_head > cons_tail). So 'free_entries' is always between 0 + * and size(ring)-1. */ + free_entries = size + cons_tail - prod_head; + + /* check that we have enough room in ring */ + if (unlikely (n > free_entries)) + { + return 0; + } + + nsfw_nshmem_enqueue_fork_recov (r); + + prod_next = prod_head + n; + r->prod.head = prod_next; + + r->ring[prod_head & mask].data_l = (u64) obj_table; + + r->prod.tail = prod_next; + return (int) n; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_nshmem_ring_mc_dequeuev (struct nsfw_mem_ring *r, void **obj_table, + unsigned int n) +{ + uint32_t cons_head, prod_tail; + uint32_t cons_next, entries; + int success; + unsigned rep = 0; + uint32_t num = n; + + /* Avoid the unnecessary cmpset operation below, which is also + * potentially harmful when n equals 0. */ + if (unlikely (num == 0)) + { + return 0; + } + + nsfw_nshmem_dequeue_fork_recov (r); + + /* move cons.head atomically */ + do + { + num = n; + cons_head = r->cons.head; + prod_tail = r->prod.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * cons_head > prod_tail). So 'entries' is always between 0 + * and size(ring)-1. */ + entries = (prod_tail - cons_head); + + /* Set the actual entries for dequeue */ + if (unlikely (num > entries)) + { + if (likely (entries > 0)) + { + num = entries; + } + else + { + return 0; + } + } + + /* check the queue can be operate */ + while (unlikely + ((r->cons.tail != r->cons.head) + || (r->conshflag != r->constflag))) + { + common_mem_pause (); + } + + cons_next = cons_head + num; + + success = + common_mem_atomic32_cmpset (&r->cons.head, cons_head, cons_next); + } + while (unlikely (success == 0)); + + nsfw_nshmem_ring_obj_copy (r, cons_head, obj_table, num); + + /* + * If there are other dequeues in progress that preceded us, + * we need to wait for them to complete + */ + while (unlikely (r->cons.tail != cons_head)) + { + common_mem_pause (); + + /* Set COMMON_RING_PAUSE_REP_COUNT to avoid spin too long waiting + * for other thread finish. It gives pre-empted thread a chance + * to proceed and finish with ring dequeue operation. */ + /* check the queue can be operate */ + if (++rep == 5) + { + rep = 0; + (void) sched_yield (); + } + } + + r->cons.tail = cons_next; + + return (int) num; +} + +/*this is a multi thread/process dequeue function, please pay attention to the bellow point +1. while dequeue corrupt, the tail no one added, may multy the try times. +*/ +int +nsfw_nshmem_ring_mc_dequeue (struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_mc_dequeuev (ring, box, 1); +} + +/* + this is a single thread/process dequeue function +*/ +int +nsfw_nshmem_ring_sc_dequeuev (struct nsfw_mem_ring *r, void **obj_table, + unsigned int n) +{ + uint32_t cons_head, prod_tail; + uint32_t cons_next, entries; + uint32_t inum = n; + cons_head = r->cons.head; + prod_tail = r->prod.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * cons_head > prod_tail). So 'entries' is always between 0 + * and size(ring)-1. */ + entries = prod_tail - cons_head; + + if (unlikely (inum > entries)) + { + if (likely (entries > 0)) + { + inum = entries; + } + else + { + return 0; + } + } + + nsfw_nshmem_dequeue_fork_recov (r); + + cons_next = cons_head + inum; + r->cons.head = cons_next; + + nsfw_nshmem_ring_obj_copy (r, cons_head, obj_table, inum); + + r->cons.tail = cons_next; + return (int) inum; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_nshmem_ring_sc_dequeue (struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_sc_dequeuev (ring, box, 1); +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_enqueue (struct nsfw_mem_ring *ring, void *box) +{ + u32 head = 0; + + /*if queue is full, just return 0 */ + if (unlikely (ring->prod.head >= (ring->size + ring->cons.tail))) + { + return 0; + } + + head = ring->prod.head; + ring->ring[head & ring->mask].data_l = (u64) box; + ring->prod.head++; + return 1; +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_dequeue (struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_singlethread_dequeuev (ring, box, 1); +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_dequeuev (struct nsfw_mem_ring *ring, + void **box, unsigned int n) +{ + u32 tail = 0; + u32 num = 0; + + while (num < n) + { + tail = ring->cons.tail; + + /* if all entries are dequed return 0 */ + if (unlikely (ring->prod.head == ring->cons.tail)) + { + return num; + } + + box[num] = (void *) ring->ring[tail & ring->mask].data_l; + ring->cons.tail++; + num++; + } + + return num; +} diff --git a/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_ring.h b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_ring.h new file mode 100644 index 0000000..93a4d4a --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_nshmem/nsfw_nshmem_ring.h @@ -0,0 +1,37 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_RING_H_ +#define _NSFW_NSHMEM_RING_H_ + +#include <stdint.h> + +int nsfw_nshmem_ring_mp_enqueue (struct nsfw_mem_ring *ring, void *box); +int nsfw_nshmem_ring_sp_enqueue (struct nsfw_mem_ring *ring, void *box); +int nsfw_nshmem_ring_mc_dequeue (struct nsfw_mem_ring *ring, void **box); +int nsfw_nshmem_ring_mc_dequeuev (struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_nshmem_ring_sc_dequeue (struct nsfw_mem_ring *ring, void **box); +int nsfw_nshmem_ring_sc_dequeuev (struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_nshmem_ring_singlethread_enqueue (struct nsfw_mem_ring *ring, + void *box); +int nsfw_nshmem_ring_singlethread_dequeue (struct nsfw_mem_ring *ring, + void **box); +int nsfw_nshmem_ring_singlethread_dequeuev (struct nsfw_mem_ring *ring, + void **box, unsigned int n); + +#endif /*_NSFW_NSHMEM_RING_H_*/ diff --git a/src/framework/common/mem_mgr/nsfw_res_mgr.c b/src/framework/common/mem_mgr/nsfw_res_mgr.c new file mode 100644 index 0000000..2f676c9 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_res_mgr.c @@ -0,0 +1,429 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "common_mem_mbuf.h" + +#include "nstack_log.h" +#include "nsfw_maintain_api.h" + +#include "nsfw_mem_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_ring_data.h" + +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +nsfw_res_mgr_item_cfg g_all_res_can[NSFW_MAX_RES_SCAN_COUNT]; + +#define NSFW_RES_SCAN_TVLAUE_DEF 60 +#define NSFW_RES_SCAN_TVLAUE (g_scan_cfg.scan_tvalue) + +typedef struct _nsfw_res_scan_init_cfg +{ + nsfw_timer_info *scan_timer; + u16 scan_tvalue; +} nsfw_res_scan_init_cfg; +nsfw_res_scan_init_cfg g_scan_cfg; + +u8 +nsfw_res_mgr_reg (nsfw_res_scn_cfg * cfg) +{ + if (NULL == cfg) + { + NSFW_LOGERR ("argv err!"); + return FALSE; + } + + u32 i; + for (i = 0; i < NSFW_MAX_RES_SCAN_COUNT; i++) + { + if ((NULL == g_all_res_can[i].scn_cfg.free_fun) + && + (__sync_bool_compare_and_swap + (&g_all_res_can[i].scn_cfg.free_fun, 0, cfg->free_fun))) + { + g_all_res_can[i].scn_cfg = *cfg; + NSFW_LOGINF ("reg res_mgr fun suc]fun=%p,data=%p", cfg->free_fun, + cfg->data); + return TRUE; + } + } + + NSFW_LOGERR + ("reg]type=%u,per=%u,chk=%u,cyc=%u,total=%u,size=%u,offset=%u,fun=%p,data=%p", + cfg->type, cfg->force_free_percent, cfg->force_free_chk_num, + cfg->num_per_cyc, cfg->total_num, cfg->elm_size, cfg->res_mem_offset, + cfg->res_mem_offset, cfg->free_fun, cfg->data); + return FALSE; +} + +static inline u32 +nsfw_get_alloc_count (u32 head, u32 tail) +{ + if (head >= tail) + { + return head - tail; + } + + return head + (0xFFFFFFFF - tail); +} + +int +nsfw_res_sp_item_chk (void *data, void *argv) +{ + nsfw_res_mgr_item_cfg *res_scn_item = (nsfw_res_mgr_item_cfg *) argv; + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + char *elm = (char *) data; + + if (NULL == scn_cfg || NULL == elm) + { + return FALSE; + } + + nsfw_res *res_item = NULL; + res_item = (nsfw_res *) (elm + scn_cfg->res_mem_offset); + if (0 == res_item->chk_count) + { + res_item->data = res_scn_item->cons_head; + } + res_item->chk_count++; + + if (res_item->chk_count < scn_cfg->force_free_chk_num) + { + return FALSE; + } + + if (res_scn_item->free_percent > scn_cfg->force_free_percent) + { + return FALSE; + } + + if (scn_cfg->total_num * scn_cfg->alloc_speed_factor > + nsfw_get_alloc_count (res_scn_item->cons_head, res_item->data)) + { + return FALSE; + } + + if (NULL == scn_cfg->free_fun) + { + return FALSE; + } + + if (TRUE == scn_cfg->free_fun ((void *) elm)) + { + res_scn_item->force_count++; + } + + res_item->chk_count = 0; + return TRUE; +} + +int +nsfw_res_flash_data (nsfw_res_mgr_item_cfg * res_scn_item) +{ + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + + u32 cur_head = 0; + u32 cur_tail = 0; + u32 elm_num = 0; + u32 free_count = 0; + + switch (scn_cfg->type) + { + case NSFW_RES_SCAN_MBUF: + { + struct common_mem_ring *ring = + (struct common_mem_ring *) scn_cfg->mgr_ring; + struct common_mem_mempool *mp = + (struct common_mem_mempool *) scn_cfg->data; + if (NULL == ring) + { + ring = mp->ring; + if (NULL == ring) + return FALSE; + } + cur_head = ring->prod.head; + cur_tail = ring->cons.head; + elm_num = mp->size; + } + break; + case NSFW_RES_SCAN_SPOOL: + { + struct nsfw_mem_ring *mem_ring = + (struct nsfw_mem_ring *) scn_cfg->mgr_ring; + if (NULL == mem_ring) + { + mem_ring = (struct nsfw_mem_ring *) scn_cfg->data; + if (NULL == mem_ring) + return FALSE; + } + + cur_head = mem_ring->prod.head; + cur_tail = mem_ring->cons.tail; + elm_num = mem_ring->size; + } + break; + case NSFW_RES_SCAN_ARRAY: + { + struct nsfw_mem_ring *mem_ring = + (struct nsfw_mem_ring *) scn_cfg->mgr_ring; + if (NULL == mem_ring) + { + return FALSE; + } + + cur_head = mem_ring->prod.head; + cur_tail = mem_ring->cons.tail; + elm_num = scn_cfg->total_num; + } + break; + default: + return FALSE; + } + + free_count = nsfw_get_alloc_count (cur_head, cur_tail); + + res_scn_item->cons_head = cur_head; + res_scn_item->prod_head = cur_tail; + if (0 != elm_num) + { + res_scn_item->free_percent = free_count * 100 / elm_num; + } + else + { + res_scn_item->free_percent = 100; + } + + scn_cfg->total_num = elm_num; + return TRUE; +} + +void +nsfw_res_scan_mem (nsfw_res_mgr_item_cfg * res_scn_item) +{ + if (NULL == res_scn_item) + { + return; + } + + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + if (NULL == scn_cfg->data) + { + return; + } + + u32 start = res_scn_item->last_scn_idx; + u32 end = start + scn_cfg->num_per_cyc; + int res_chk_number = 0; + if (NSFW_RES_SCAN_SPOOL == scn_cfg->type) + { + res_chk_number = + nsfw_mem_sp_iterator (scn_cfg->data, start, end, + nsfw_res_sp_item_chk, (void *) res_scn_item); + } + else + { + res_chk_number = + nsfw_mem_mbuf_iterator (scn_cfg->data, start, end, + nsfw_res_sp_item_chk, (void *) res_scn_item); + } + + if (0 == res_chk_number) + { + res_scn_item->last_scn_idx = 0; + start = res_scn_item->last_scn_idx; + end = start + scn_cfg->num_per_cyc; + if (NSFW_RES_SCAN_SPOOL == scn_cfg->type) + { + res_chk_number = + nsfw_mem_sp_iterator (scn_cfg->data, start, end, + nsfw_res_sp_item_chk, + (void *) res_scn_item); + } + else + { + res_chk_number = + nsfw_mem_mbuf_iterator (scn_cfg->data, start, end, + nsfw_res_sp_item_chk, + (void *) res_scn_item); + } + } + + if (res_chk_number + start < end) + { + res_scn_item->last_scn_idx = 0; + } + else + { + res_scn_item->last_scn_idx += res_chk_number; + } + + return; +} + +void +nsfw_res_scan_array (nsfw_res_mgr_item_cfg * res_scn_item) +{ + if (NULL == res_scn_item) + { + return; + } + + nsfw_res_scn_cfg *scn_cfg = &res_scn_item->scn_cfg; + if (NULL == scn_cfg->data) + { + return; + } + + u32 i; + char *elm = + (char *) scn_cfg->data + (res_scn_item->last_scn_idx * scn_cfg->elm_size); + for (i = res_scn_item->last_scn_idx; i < scn_cfg->total_num; i++) + { + if (i >= res_scn_item->last_scn_idx + scn_cfg->num_per_cyc) + { + break; + } + + if (TRUE == nsfw_res_sp_item_chk (elm, (void *) res_scn_item)) + { + NSFW_LOGINF ("force free item]data=%p,cfg=%p", elm, res_scn_item); + } + + elm += scn_cfg->elm_size; + } + + if (i >= scn_cfg->total_num) + { + res_scn_item->last_scn_idx = 0; + } + else + { + res_scn_item->last_scn_idx = i; + } + + return; +} + +void +nsfw_res_scan_proc (nsfw_res_mgr_item_cfg * res_scn_item) +{ + (void) nsfw_res_flash_data (res_scn_item); + switch (res_scn_item->scn_cfg.type) + { + case NSFW_RES_SCAN_ARRAY: + nsfw_res_scan_array (res_scn_item); + break; + case NSFW_RES_SCAN_SPOOL: + case NSFW_RES_SCAN_MBUF: + nsfw_res_scan_mem (res_scn_item); + break; + default: + break; + } +} + +int +nsfw_res_scan_all (u32 timer_type, void *data) +{ + NSFW_LOGDBG ("scan start!"); + struct timespec time_left = { NSFW_RES_SCAN_TVLAUE, 0 }; + g_scan_cfg.scan_timer = + nsfw_timer_reg_timer (0, NULL, nsfw_res_scan_all, time_left); + + if (g_hbt_switch) + { + return TRUE; + } + + int i; + for (i = 0; i < NSFW_MAX_RES_SCAN_COUNT; i++) + { + /*last fun */ + if (NULL == g_all_res_can[i].scn_cfg.data) + { + break; + } + + nsfw_res_scan_proc (&g_all_res_can[i]); + } + + return TRUE; +} + +static int nsfw_resmgr_module_init (void *param); +static int +nsfw_resmgr_module_init (void *param) +{ + u8 proc_type = (u8) ((long long) param); + NSFW_LOGINF ("res mgr module init]type=%u", proc_type); + g_scan_cfg.scan_tvalue = NSFW_RES_SCAN_TVLAUE_DEF; + switch (proc_type) + { + case NSFW_PROC_MAIN: + { + struct timespec time_left = { NSFW_RES_SCAN_TVLAUE, 0 }; + g_scan_cfg.scan_timer = + nsfw_timer_reg_timer (0, NULL, nsfw_res_scan_all, time_left); + return 0; + } + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME(NSFW_RES_MGR_MODULE) +NSFW_MODULE_PRIORITY(99) +NSFW_MODULE_INIT(nsfw_resmgr_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_rshmem_mng.c b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_rshmem_mng.c new file mode 100644 index 0000000..dc3400d --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_rshmem_mng.c @@ -0,0 +1,987 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdint.h> +#include "nstack_securec.h" +#include "nstack_log.h" +#include "nsfw_ring_fun.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_shmem_mng.h" +#include "common_mem_buf.h" +#include "common_mem_common.h" + +#include "common_func.h" + +/*get the base address of msg data */ +#define NSFW_SHMEM_GET_DATA(pmsg, type) (type *)&((pmsg)->aidata[0]) + +/*if input point is nun, just return null*/ +#define NSFW_POINT_CHK_RET_NULL(p, desc) \ + if (NULL == (p)) \ + { \ + NSCOMM_LOGERR("point check fail] desc_para=%s", desc); \ + return NULL; \ + } + +/*if input point is nun, just return err num*/ +#define NSFW_POINT_CHK_RET_ERR(p, desc) \ + if (NULL == (p)) \ + { \ + NSCOMM_LOGDBG("point check fail] desc_para=%s", desc); \ + return NSFW_MEM_ERR; \ + } + +/*if input point is nun, goto flag*/ +#define NSFW_POINT_CHK_RET_GOTO(p, gotoflag, desc) \ + if (NULL == (p)) \ + { \ + NSCOMM_LOGERR("point check fail] desc_para=%s", desc); \ + goto gotoflag; \ + } + +/*init the msg head*/ +#define NSFW_SHMEM_MSG_HEAD_INIT(pmsg, type, lenth) { \ + (pmsg)->usmsg_type = (type); \ + (pmsg)->uslenth = (lenth); \ + } + +/*rsp msg head check, and if err goto*/ +#define NSFW_SHMEM_MSGHEAD_CHK_GOTO(pmsg, type, lenth, gotoflag) { \ + if (((type) != pmsg->usmsg_type) && ((lenth) != pmsg->uslenth)) \ + { \ + NSCOMM_LOGERR("check fail] msgtype=%d, type_para=%d, len=%d", (pmsg->usmsg_type), (type), (lenth)); \ + goto gotoflag; \ + } \ + } + +/*rsp check the state*/ +#define NSFW_SHMEM_ACKSTATE_CHK_GOTO(expret, ret, expseg, seg, gotoflag) { \ + if (((ret) != (expret)) || ((expseg) != (seg))) \ + { \ + NSCOMM_LOGERR("ackstate check fail]msgack exp=%d, real=%d,eseg=%d, rseg=%d", (expret), (ret), (expseg), (seg)); \ + goto gotoflag; \ + } \ + } + +/*mzone msg init*/ +#define NSFW_SHMEM_MZONE_DATA_INIT(pdata, slenth, seg, socketid) { \ + (pdata)->isocket_id = (socketid); \ + (pdata)->lenth = (slenth); \ + (pdata)->usseq = (seg); \ + (pdata)->ireserv = 0; \ + } + +/*mbuf msg init*/ +#define NSFW_SHMEM_MBUF_DATA_INIT(pdata, seg, num, cashsize, priv_size, data_room, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->uscash_size = (cashsize); \ + (pdata)->uspriv_size = (priv_size); \ + (pdata)->usdata_room = (data_room); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +/*mpool msg init*/ +#define NSFW_SHMEM_MPOOL_DATA_INIT(pdata, seg, num, eltsize, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->useltsize = (eltsize); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +/*mring msg init*/ +#define NSFW_SHMEM_MRING_DATA_INIT(pdata, seg, num, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +#define NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg) {\ + if (pmsg) \ + { \ + nsfw_mgr_msg_free(pmsg); \ + } \ + if (prsp_msg) \ + { \ + nsfw_mgr_msg_free(prsp_msg); \ + } \ +} + +/* + * create a block memory by send a msg + * + */ +mzone_handle +nsfw_memzone_remote_reserv (const i8 * name, size_t mlen, i32 socket_id) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head point define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data point define */ + nsfw_shmem_reserv_req *pdata = NULL; + nsfw_shmem_msg_head *pack_head = NULL; + + /*ack msg define */ + nsfw_shmem_ack *pack_data = NULL; + + mzone_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL (pmsg, "remote reserv pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, release, "remote reserv rspmsg alloc"); + + /*msg head init */ + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_RESERV_REQ_MSG, + sizeof (nsfw_shmem_reserv_req)); + + /*msg data init */ + pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_reserv_req); + iretval = STRCPY_S (pdata->aname, sizeof (pdata->aname), name); + if (EOK != iretval) + { + NSCOMM_LOGERR ("reserv mem copy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MZONE_DATA_INIT (pdata, mlen, (u16) 0, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("reserv mem req rsp fail] ret=%u", ucret); + goto release; + } + + /*interrupt msg head */ + pack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (pack_head, NSFW_RESERV_ACK_MSG, + sizeof (nsfw_shmem_ack), release); + + pack_data = NSFW_SHMEM_GET_DATA (pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, pack_data->cstate, 0, + pack_data->usseq, release); + + hhandle = (mzone_handle) ADDR_SHTOL (pack_data->pbase_addr); + NSCOMM_LOGDBG ("mem reserve] name=%s, handle=%p, seg=%u", name, hhandle, + pack_data->usseq); +release: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return hhandle; +} + +/* + *create some memorys by send a msg + */ +i32 +nsfw_memzone_remote_reserv_v (nsfw_mem_zone * pmeminfo, + mzone_handle * paddr_array, i32 inum, pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_reserv_req *pdata = NULL; + nsfw_shmem_reserv_req *ptempdata = NULL; + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + u16 ussegbase = 0; + u16 ustempv = 0; + i32 ieltnum = 0; + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof (nsfw_shmem_msg_head)) / sizeof (nsfw_shmem_reserv_req); + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO (pmsg, err, "remote reserv_v msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, err, "remote reserv_v rspmsg alloc"); + + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + + ptempdata = pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_reserv_req); + + do + { + icount++; + ieltnum++; + + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_RESERV_REQ_MSG, + ieltnum * sizeof (nsfw_shmem_reserv_req)); + + itindex = icount - 1; + int retVal = + SPRINTF_S (ptempdata->aname, sizeof (ptempdata->aname), "%s_%x", + pmeminfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S faild]ret=%d", retVal); + } + NSFW_SHMEM_MZONE_DATA_INIT (ptempdata, pmeminfo[itindex].lenth, + (u16) itindex, + pmeminfo[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("reserv v mem req rsp fail] ret=%u", ucret); + goto err; + } + + pack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (pack_head, NSFW_RESERV_ACK_MSG, + ieltnum * sizeof (nsfw_shmem_ack), + err); + + pack_data = NSFW_SHMEM_GET_DATA (pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + ustempv = ussegbase + iindex; + + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, ustempv, + (u16) pack_data->usseq, err); + + paddr_array[ustempv] = ADDR_SHTOL (pack_data->pbase_addr); + NSCOMM_LOGDBG ("remote reserve]index=%u, seg=%u, handle=%p", + ustempv, pack_data->usseq, paddr_array[ustempv]); + pack_data++; + } + + ussegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + int retVal = + SPRINTF_S (ptempdata->aname, sizeof (ptempdata->aname), "%s_%x", + pmeminfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S faild]ret=%d", retVal); + } + NSFW_SHMEM_MZONE_DATA_INIT (ptempdata, pmeminfo[itindex].lenth, + (u16) itindex, + pmeminfo[itindex].isocket_id); + ptempdata++; + } + } + while (icount < inum); + + iretval = NSFW_MEM_OK; + goto free; + +err: + iretval = NSFW_MEM_ERR; +free: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return iretval; +} + +/* + *release a block memory with name by send msg + */ +i32 +nsfw_remote_free (const i8 * name, nsfw_mem_struct_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + nsfw_shmem_msg_head *pdata_head = NULL; + + nsfw_shmem_free_req *pdata = NULL; + + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *pack_data = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_ERR (pmsg, "remote free msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, terr, "remote free rspmsg alloc"); + + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_RELEASE_REQ_MSG, + sizeof (nsfw_shmem_free_req)); + + pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_free_req); + if (EOK != STRCPY_S (pdata->aname, sizeof (pdata->aname), name)) + { + NSCOMM_LOGERR ("STRCPY_S failed]name=%s", name); + } + pdata->usseq = 0; + pdata->ustype = entype; + pdata->ireserv = 0; + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("free mem req rsp fail] ret=%u", ucret); + goto release; + } + + pack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (pack_head, NSFW_RELEASE_ACK_MSG, + sizeof (nsfw_shmem_ack), terr); + + pack_data = NSFW_SHMEM_GET_DATA (pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, pack_data->cstate, 0, + pack_data->usseq, terr); + + iretval = NSFW_MEM_OK; + goto release; +terr: + iretval = NSFW_MEM_ERR; +release: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return iretval; +} + +/* + *create a mbuf pool by send a msg + */ +mpool_handle +nsfw_remote_shmem_mbf_create (const i8 * name, unsigned n, + unsigned cache_size, unsigned priv_size, + unsigned data_room_size, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_mbuf_req *pdata = NULL; + nsfw_shmem_msg_head *tpack_head = NULL; + nsfw_shmem_ack *tpack_data = NULL; + mpool_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL (pmsg, "remote mbf create pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, release, "remote mbf create msg alloc"); + + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_MBUF_REQ_MSG, + sizeof (nsfw_shmem_mbuf_req)); + + pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_mbuf_req); + iretval = STRCPY_S (pdata->aname, sizeof (pdata->aname), name); + if (EOK != iretval) + { + NSCOMM_LOGERR ("mbf create name cpy fail] ret=%d", iretval); + goto release; + } + + NSFW_SHMEM_MBUF_DATA_INIT (pdata, 0, n, cache_size, priv_size, + data_room_size, (u16) entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("mbf create mem req rsp fail] ret=%u", ucret); + goto release; + } + + tpack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (tpack_head, NSFW_MBUF_ACK_MSG, + sizeof (nsfw_shmem_ack), release); + + tpack_data = NSFW_SHMEM_GET_DATA (tpack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, tpack_data->cstate, 0, + tpack_data->usseq, release); + + hhandle = ADDR_SHTOL (tpack_data->pbase_addr); + NSCOMM_LOGDBG ("mbf create] name=%s, handle=%p, seg=%u", name, hhandle, + tpack_data->usseq); +release: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return hhandle; +} + +/* + *create some mbuf pools + */ +i32 +nsfw_remote_shmem_mbf_createv (nsfw_mem_mbfpool * pmbfname, + mpool_handle * phandle_array, i32 inum, + pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *mbpmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + + nsfw_shmem_mbuf_req *pdata = NULL; + nsfw_shmem_mbuf_req *ptempdata = NULL; + + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + mpool_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + i32 isegbase = 0; + i32 ieltnum = 0; + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof (nsfw_shmem_msg_head)) / sizeof (nsfw_shmem_mbuf_req); + + mbpmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO (mbpmsg, lerr, "remote mbf createv msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, lerr, "remote mbf createv rspmsg alloc"); + + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, mbpmsg); + + ptempdata = pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_mbuf_req); + + do + { + icount++; + ieltnum++; + + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_MBUF_REQ_MSG, + ieltnum * sizeof (nsfw_shmem_mbuf_req)); + + /*fill msg data */ + itindex = icount - 1; + if (-1 == + SPRINTF_S (ptempdata->aname, sizeof (ptempdata->aname), "%s_%x", + pmbfname[itindex].stname.aname, pid)) + { + NSCOMM_LOGERR ("SPRINTF_S failed]"); + goto lerr; + } + NSFW_SHMEM_MBUF_DATA_INIT (ptempdata, (u16) itindex, + pmbfname[itindex].usnum, + pmbfname[itindex].uscash_size, + pmbfname[itindex].uspriv_size, + pmbfname[itindex].usdata_room, + pmbfname[itindex].enmptype, + pmbfname[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp (mbpmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("mbf createv mem req rsp fail] ret=%d", ucret); + goto lerr; + } + + /*interrup msg head */ + pack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (pack_head, NSFW_MBUF_ACK_MSG, + ieltnum * sizeof (nsfw_shmem_ack), + lerr); + + pack_data = NSFW_SHMEM_GET_DATA (pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, + (isegbase + iindex), + (u16) pack_data->usseq, lerr); + phandle_array[isegbase + iindex] = + ADDR_SHTOL (pack_data->pbase_addr); + NSCOMM_LOGDBG ("mbf createv] seg=%d, handle=%p", + pack_data->usseq, hhandle); + pack_data++; + } + + isegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + if (-1 == + SPRINTF_S (ptempdata->aname, sizeof (ptempdata->aname), "%s_%x", + pmbfname[itindex].stname.aname, pid)) + { + NSCOMM_LOGERR ("SPRINTF_S failed]"); + goto lerr; + } + NSFW_SHMEM_MBUF_DATA_INIT (ptempdata, (u16) itindex, + pmbfname[itindex].usnum, + pmbfname[itindex].uscash_size, + pmbfname[itindex].uspriv_size, + pmbfname[itindex].usdata_room, + pmbfname[itindex].enmptype, + pmbfname[itindex].isocket_id); + ptempdata++; + } + } + while (icount < inum); + + /*release memory */ + iretval = NSFW_MEM_OK; + goto release; + +lerr: + iretval = NSFW_MEM_ERR; +release: + NSFW_SHMEM_MSG_FREE (mbpmsg, prsp_msg); + return iretval; +} + +/* + *create a simpile pool + */ +mring_handle +nsfw_remote_shmem_mpcreate (const char *name, unsigned int n, + unsigned int elt_size, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_sppool_req *pdata = NULL; + nsfw_shmem_msg_head *mppack_head = NULL; + nsfw_shmem_ack *mppack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL (pmsg, "remote mbf mpcreate pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, release, "remote mpcreate rspmsg alloc"); + + /*init msg head */ + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_SPPOOL_REQ_MSG, + sizeof (nsfw_shmem_sppool_req)); + + /*fill msg data */ + pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_sppool_req); + iretval = STRCPY_S (pdata->aname, sizeof (pdata->aname), name); + if (EOK != iretval) + { + NSCOMM_LOGERR ("mp create copy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MPOOL_DATA_INIT (pdata, 0, n, elt_size, entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("mp create rsp fail] ret=%d", ucret); + goto release; + } + + /*get msg head */ + mppack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (mppack_head, NSFW_SPPOOL_ACK_MSG, + sizeof (nsfw_shmem_ack), release); + + mppack_data = NSFW_SHMEM_GET_DATA (mppack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, mppack_data->cstate, 0, + mppack_data->usseq, release); + + hhandle = ADDR_SHTOL (mppack_data->pbase_addr); + NSCOMM_LOGDBG ("mpcreate] name=%s, handle=%p, seg=%d", name, hhandle, + mppack_data->usseq); +release: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return hhandle; +} + +/* + *create some simpile pools by send a msg + */ +i32 +nsfw_remote_shmem_mpcreatev (nsfw_mem_sppool * pmpinfo, + mring_handle * pringhandle_array, i32 inum, + pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_sppool_req *pdata = NULL; + nsfw_shmem_sppool_req *ptempdata = NULL; + + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + i32 isegbase = 0; + i32 ieltnum = 0; + /*the max members that a msg can take */ + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof (nsfw_shmem_msg_head)) / sizeof (nsfw_shmem_sppool_req); + + /*alloc a msg */ + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO (pmsg, mperr, "remote mpcreatev pmsg alloc"); + + /*alloc rsp msg */ + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, mperr, "remote mpcreatev rspmsg alloc"); + + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + + ptempdata = pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_sppool_req); + + do + { + icount++; + ieltnum++; + + /*if the element num reach the bigest, or already send all, just deal */ + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + /*init msg header */ + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_SPPOOL_REQ_MSG, + ieltnum * sizeof (nsfw_shmem_sppool_req)); + + /*fill the msg data */ + itindex = icount - 1; + + int retVal = + SPRINTF_S (ptempdata->aname, sizeof (ptempdata->aname), "%s_%x", + pmpinfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S fail]ret=%d", retVal); + goto mperr; + } + NSFW_SHMEM_MPOOL_DATA_INIT (ptempdata, itindex, + pmpinfo[itindex].usnum, + pmpinfo[itindex].useltsize, + pmpinfo[itindex].enmptype, + pmpinfo[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("mpcreatev create fail] ret=%u", ucret); + goto mperr; + } + + /*interrup mgs head */ + pack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (pack_head, NSFW_SPPOOL_ACK_MSG, + ieltnum * sizeof (nsfw_shmem_ack), + mperr); + + pack_data = NSFW_SHMEM_GET_DATA (pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, + (isegbase + iindex), + (u16) pack_data->usseq, mperr); + pringhandle_array[isegbase + iindex] = + ADDR_SHTOL (pack_data->pbase_addr); + NSCOMM_LOGDBG ("mpcreatev] seg=%u, handle=%p", pack_data->usseq, + hhandle); + pack_data++; + } + + isegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + int retVal = + SPRINTF_S (ptempdata->aname, sizeof (ptempdata->aname), "%s_%x", + pmpinfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S fail]ret=%d", retVal); + goto mperr; + } + NSFW_SHMEM_MPOOL_DATA_INIT (ptempdata, itindex, + pmpinfo[itindex].usnum, + pmpinfo[itindex].useltsize, + pmpinfo[itindex].enmptype, + pmpinfo[itindex].isocket_id); + + ptempdata++; + } + } + while (icount < inum); + + /*release the memory */ + iretval = NSFW_MEM_OK; + goto release; + +mperr: + iretval = NSFW_MEM_ERR; +release: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return iretval; +} + +/* + *create a ring + */ +mring_handle +nsfw_remote_shmem_ringcreate (const char *name, unsigned int n, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_ring_req *pdata = NULL; + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *ppack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL (pmsg, "remote ringcreate pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, release, + "remote ringcreate rspmsg alloc"); + + /*fill msg head */ + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_RING_REQ_MSG, + sizeof (nsfw_shmem_ring_req)); + + /*fill msg data */ + pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_ring_req); + iretval = STRCPY_S (pdata->aname, sizeof (pdata->aname), name); + if (EOK != iretval) + { + NSCOMM_LOGERR ("ring create cpy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MRING_DATA_INIT (pdata, 0, n, entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("ring create rsp fail] ret=%d", ucret); + goto release; + } + + /*interrup mgs head */ + pack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (pack_head, NSFW_RING_ACK_MSG, + sizeof (nsfw_shmem_ack), release); + + ppack_data = NSFW_SHMEM_GET_DATA (pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, ppack_data->cstate, 0, + ppack_data->usseq, release); + + hhandle = ADDR_SHTOL (ppack_data->pbase_addr); + NSCOMM_LOGDBG ("ring create] name=%s, handle=%p, seg=%u", name, hhandle, + ppack_data->usseq); +release: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return hhandle; +} + +/* + *create a mem pool that the members are rings by send a msg + *ieltnum:the num of ring member + *iringnum:the num of ring in simple mem pook + *entype:the defualt the of ring + */ +i32 +nsfw_remote_shmem_ringcreatev (const char *name, i32 ieltnum, + mring_handle * pringhandle_array, i32 iringnum, + i32 socket_id, nsfw_mpool_type entype) +{ + unsigned int useltsize = 0; + mring_handle nhandle = NULL; + i32 icount = 0; + i32 n = 0; + uint64_t baseaddr = 0; + uint64_t endaddr = 0; + /*the num of ring member must be power of 2 */ + unsigned int usnum = common_mem_align32pow2 (ieltnum + 1); + + useltsize = + sizeof (struct nsfw_mem_ring) + usnum * sizeof (union RingData_U); + nhandle = + nsfw_remote_shmem_mpcreate (name, iringnum, useltsize, socket_id, + NSFW_MRING_SPSC); + NSFW_POINT_CHK_RET_ERR (nhandle, "remote ringcreatev msg alloc"); + + n = + nsfw_shmem_ring_sc_dequeuev (nhandle, (void **) pringhandle_array, + iringnum); + + if (n != iringnum) + { + NSCOMM_LOGERR ("ring dequeue fail] ringnum=%d, retnum=%d", iringnum, n); + return NSFW_MEM_ERR; + } + + nsfw_shmem_ring_baseaddr_query (&baseaddr, &endaddr); + + for (icount = 0; icount < iringnum; icount++) + { + nsfw_mem_ring_init (pringhandle_array[icount], usnum, (void *) baseaddr, + NSFW_SHMEM, entype); + } + + return NSFW_MEM_OK; +} + +/* + *look up a msg by send a msg + */ +void * +nsfw_remote_shmem_lookup (const i8 * name, nsfw_mem_struct_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + void *addr = NULL; + /*msg head data define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_lookup_req *pdata = NULL; + + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *lpack_data = NULL; + u8 ucret = TRUE; + + pmsg = nsfw_mgr_msg_alloc (MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL (pmsg, "remote lookup pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc (); + NSFW_POINT_CHK_RET_GOTO (prsp_msg, perr, "remote lookup rspmsg alloc"); + + /*msg head init */ + pdata_head = GET_USER_MSG (nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT (pdata_head, NSFW_MEM_LOOKUP_REQ_MSG, + sizeof (nsfw_shmem_lookup_req)); + + pdata = NSFW_SHMEM_GET_DATA (pdata_head, nsfw_shmem_lookup_req); + if (EOK != STRCPY_S (pdata->aname, sizeof (pdata->aname), name)) + { + NSCOMM_LOGERR ("STRCPY_S faild]name=%s", name); + } + pdata->usseq = 0; + pdata->ustype = entype; + pdata->ireserv = 0; + + ucret = nsfw_mgr_send_req_wait_rsp (pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSCOMM_LOGERR ("mem lookup fail] ret=%u", ucret); + goto release; + } + + /*interrup mgs head */ + pack_head = GET_USER_MSG (nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO (pack_head, NSFW_MEM_LOOKUP_ACK_MSG, + sizeof (nsfw_shmem_ack), perr); + + lpack_data = NSFW_SHMEM_GET_DATA (pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO (NSFW_MEM_ALLOC_SUCC, lpack_data->cstate, 0, + lpack_data->usseq, perr); + + addr = ADDR_SHTOL (lpack_data->pbase_addr); + NSCOMM_LOGDBG ("shmem lookup] name=%s, handle=%p, seg=%u", name, addr, + lpack_data->usseq); + goto release; +perr: + addr = NULL; + +release: + NSFW_SHMEM_MSG_FREE (pmsg, prsp_msg); + return addr; +} diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_rshmem_mng.h b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_rshmem_mng.h new file mode 100644 index 0000000..60c4115 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_rshmem_mng.h @@ -0,0 +1,51 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RSHMEM_MNG_H +#define _NSFW_RSHMEM_MNG_H + +mzone_handle nsfw_memzone_remote_reserv (const i8 * name, size_t mlen, + i32 socket_id); +i32 nsfw_memzone_remote_reserv_v (nsfw_mem_zone * pmeminfo, + mzone_handle * paddr_array, i32 inum, + pid_t pid); +i32 nsfw_remote_free (const i8 * name, nsfw_mem_struct_type entype); +mpool_handle nsfw_remote_shmem_mbf_create (const i8 * name, unsigned int n, + unsigned cache_size, + unsigned priv_size, + unsigned data_room_size, + i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_mbf_createv (nsfw_mem_mbfpool * pmbfname, + mpool_handle * phandle_array, i32 inum, + pid_t pid); +mring_handle nsfw_remote_shmem_mpcreate (const char *name, unsigned int n, + unsigned int elt_size, i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_mpcreatev (nsfw_mem_sppool * pmpinfo, + mring_handle * pringhandle_array, i32 inum, + pid_t pid); +mring_handle nsfw_remote_shmem_ringcreate (const char *name, unsigned int n, + i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_ringcreatev (const char *name, i32 ieltnum, + mring_handle * pringhandle_array, + i32 iringnum, i32 socket_id, + nsfw_mpool_type entype); + +void *nsfw_remote_shmem_lookup (const i8 * name, nsfw_mem_struct_type entype); + +#endif diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mdesc.c b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mdesc.c new file mode 100644 index 0000000..e7a11ad --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mdesc.c @@ -0,0 +1,47 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_mem_desc.h" +#include "nsfw_shmem_mng.h" +#include "nsfw_shmem_mdesc.h" + +/*the inferaces accessing memory*/ +nsfw_mem_ops g_shmem_ops = { + nsfw_shmem_init, + nsfw_shmem_destroy, + nsfw_shmem_create, + nsfw_shmem_createv, + nsfw_shmem_lookup, + nsfw_shmem_release, + nsfw_shmem_mbfmpcreate, + nsfw_shmem_mbfmpcreatev, + nsfw_shmem_mbfalloc, + nsfw_shmem_mbffree, + nsfw_shmem_mbfmplookup, + nsfw_shmem_mbfmprelease, + nsfw_shmem_spcreate, + nsfw_shmem_spcreatev, + nswf_shmem_sp_ringcreate, + nsfw_shmem_sprelease, + nsfw_shmem_sp_lookup, + nsfw_shmem_ringcreate, + nsfw_shmem_ring_lookup, + nsfw_shmem_ringrelease, + nsfw_shmem_stactic, + nsfw_shmem_mbuf_recycle, + nsfw_shmem_sp_iterator, + nsfw_shmem_mbuf_iterator +}; diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mdesc.h b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mdesc.h new file mode 100644 index 0000000..afd9e29 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mdesc.h @@ -0,0 +1,22 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_MDESC_H_ +#define _NSFW_SHMEM_MDESC_H_ + +extern nsfw_mem_ops g_shmem_ops; + +#endif diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mng.c b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mng.c new file mode 100644 index 0000000..f85e70d --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mng.c @@ -0,0 +1,880 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nstack_securec.h" +#include "nstack_log.h" +#include "nsfw_mem_desc.h" +#include "nsfw_ring_fun.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_shmem_mng.h" +#include "common_mem_mempool.h" +#include "common_mem_memzone.h" +#include "common_mem_buf.h" +#include "common_mem_mbuf.h" +#include "nsfw_rshmem_mng.h" +#include "common_mem_api.h" +#include "common_sys_config.h" +#include "nsfw_maintain_api.h" +#include "common_pal_bitwide_adjust.h" + +#include "common_mem_pal.h" + +#include "common_func.h" + +#define NSFW_SHMEM_PID (get_sys_pid()) +#define NSFW_SHMEM_FLAG (g_shmem_localdata->enflag) + +nsfw_mem_localdata *g_shmem_localdata = NULL; + +/*check g_mem_localdata*/ +#define NSFW_INIT_CHK_RET() \ + if (!g_shmem_localdata) \ + { \ + return NSFW_MEM_ERR; \ + } + +#define NSFW_INIT_CHK_RET_NULL() \ + if (!g_shmem_localdata) \ + { \ + return NULL; \ + } + +/* + *share memory mng module init + * + */ +i32 +nsfw_shmem_init (nsfw_mem_para * para) +{ + common_mem_pal_module_info rteinfo = { 0 }; + i32 iret = NSFW_MEM_ERR; + int flag = 0; + if (!para) + { + return NSFW_MEM_ERR; + } + + NSCOMM_LOGINF ("nsfw shmem init begin"); + + if (NSFW_PROC_MASTER == para->enflag) + { + iret = common_mem_pal_init (para->iargsnum, para->pargs); + } + else if (NSFW_PROC_MAIN == para->enflag) + { + iret = common_pal_module_init (NULL); + } + else + { + LCORE_MASK_SET (rteinfo.ilcoremask, 1); + rteinfo.ucproctype = DMM_PROC_T_SECONDARY; + iret = common_pal_module_init (&rteinfo); + } + + if (NSFW_MEM_OK != iret) + { + NSCOMM_LOGERR ("rte init fail] ret=0x%x", iret); + return NSFW_MEM_ERR; + } + + flag = dmm_pal_addr_align (); + if ((0 == flag) && (NSFW_PROC_MAIN == para->enflag)) + { + dmm_addr_print (); + NSCOMM_LOGERR + ("rte init addr is not the same with primary] nstackmain flag=%d", + flag); + return NSFW_MEM_ERR; + } + + g_shmem_localdata = + (nsfw_mem_localdata *) malloc (sizeof (nsfw_mem_localdata)); + + if (NULL == g_shmem_localdata) + { + NSCOMM_LOGERR ("g_shmem_localdata malloc fail"); + return NSFW_MEM_ERR; + } + + iret = + MEMSET_S (g_shmem_localdata, sizeof (nsfw_mem_localdata), 0, + sizeof (nsfw_mem_localdata)); + if (EOK != iret) + { + NSCOMM_LOGERR ("memset fail] g_shmem_localdata=%p ", g_shmem_localdata); + free (g_shmem_localdata); + g_shmem_localdata = NULL; + return NSFW_MEM_ERR; + } + + g_shmem_localdata->enflag = para->enflag; + + NSCOMM_LOGINF ("nsfw shmem init end] enflag=%d", para->enflag); + return NSFW_MEM_OK; + +} + +/* + *module destroy + */ +void +nsfw_shmem_destroy (void) +{ + if (g_shmem_localdata) + { + free (g_shmem_localdata); + g_shmem_localdata = NULL; + } + + return; +} + +/* + * create a shared memory + * nsfw_mem_zone::stname memory name + * nsfw_mem_zone::isize + */ +mzone_handle +nsfw_shmem_create (nsfw_mem_zone * pinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL ()if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_memzone_data_reserve_name (pinfo->stname.aname, + pinfo->lenth, + pinfo->isocket_id); + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENTH */ + NSFW_NAME_LENCHECK_RET_NULL (pinfo->stname.aname, "shmem create") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + return NULL; + } + } + + return nsfw_memzone_remote_reserv ((char *) &aname[0], pinfo->lenth, + SOCKET_ID_ANY); +} + +/* + *create some memory + *inum must be equal iarray_num + */ +i32 +nsfw_shmem_createv (nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET (); + + if (NSFW_PROC_MASTER == NSFW_SHMEM_FLAG) + { + return NSFW_MEM_ERR; + } + else if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_memzone_remote_reserv_v (pmeminfo, paddr_array, iarray_num, + 0); + } + else + { + return nsfw_memzone_remote_reserv_v (pmeminfo, paddr_array, iarray_num, + NSFW_SHMEM_PID); + } + return NSFW_MEM_ERR; +} + +mzone_handle +nsfw_shmem_lookup (nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + NSFW_INIT_CHK_RET_NULL (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_memzone_data_lookup_name (pname->aname); + } + + if ((NSFW_PROC_NULL == pname->enowner) + || (NSFW_PROC_MAIN == pname->enowner)) + { + int retVal = + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", pname->aname); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S faild"); + return NULL; + } + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENTH */ + NSFW_NAME_LENCHECK_RET_NULL (pname->aname, "shmem lookup") + int retVal = + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", pname->aname, + NSFW_SHMEM_PID); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S faild"); + return NULL; + } + } + + return nsfw_remote_shmem_lookup (aname, NSFW_MEM_MZONE); +} + +i32 +nsfw_shmem_release (nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + const struct common_mem_memzone *pmzone = NULL; + NSFW_INIT_CHK_RET (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + pmzone = common_mem_memzone_lookup (pname->aname); + + if (pmzone) + { + common_mem_memzone_free (pmzone); + } + return NSFW_MEM_OK; + } + else + { + NSFW_NAME_LENCHECK_RET (pname->aname, "shmem free") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild"); + return NSFW_MEM_ERR; + } + } + + return nsfw_remote_free (aname, NSFW_MEM_MZONE); +} + +mpool_handle +nsfw_shmem_mbfmpcreate (nsfw_mem_mbfpool * pbufinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_mem_pktmbuf_pool_create (pbufinfo->stname.aname, + pbufinfo->usnum, + pbufinfo->uscash_size, + pbufinfo->uspriv_size, + pbufinfo->usdata_room, + pbufinfo->isocket_id); + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENTH */ + NSFW_NAME_LENCHECK_RET_NULL (pbufinfo->stname.aname, "mbufpool create") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pbufinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + + return nsfw_remote_shmem_mbf_create (aname, pbufinfo->usnum, + pbufinfo->uscash_size, + pbufinfo->uspriv_size, + pbufinfo->usdata_room, SOCKET_ID_ANY, + pbufinfo->enmptype); +} + +/* + *create some mbuf pools + */ +i32 +nsfw_shmem_mbfmpcreatev (nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET (); + + if (NSFW_PROC_MASTER == NSFW_SHMEM_FLAG) + { + return NSFW_MEM_ERR; + } + else if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_remote_shmem_mbf_createv (pmbfname, phandle_array, + iarray_num, 0); + } + else + { + return nsfw_remote_shmem_mbf_createv (pmbfname, phandle_array, + iarray_num, NSFW_SHMEM_PID); + } + + return NSFW_MEM_ERR; +} + +mbuf_handle +nsfw_shmem_mbfalloc (mpool_handle mhandle) +{ + return (mbuf_handle) common_mem_pktmbuf_alloc ((struct common_mem_mempool *) + mhandle); +} + +i32 +nsfw_shmem_mbffree (mbuf_handle mhandle) +{ + common_mem_pktmbuf_free ((struct common_mem_mbuf *) mhandle); + return NSFW_MEM_OK; +} + +i32 +nsfw_shmem_mbfmprelease (nsfw_mem_name * pname) +{ + return NSFW_MEM_OK; +} + +mpool_handle +nsfw_shmem_mbfmplookup (nsfw_mem_name * pmbfname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_mem_mempool_lookup (pmbfname->aname); + } + + if ((NSFW_PROC_NULL == pmbfname->enowner) + || (NSFW_PROC_MAIN == pmbfname->enowner)) + { + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", + pmbfname->aname)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENTH */ + NSFW_NAME_LENCHECK_RET_NULL (pmbfname->aname, "shmem lookup") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pmbfname->aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + + return nsfw_remote_shmem_lookup (aname, NSFW_MEM_MBUF); +} + +mring_handle +nsfw_shmem_spcreate (nsfw_mem_sppool * pmpinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_shmem_pool_create (pmpinfo->stname.aname, pmpinfo->usnum, + pmpinfo->useltsize, pmpinfo->isocket_id, + pmpinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET_NULL (pmpinfo->stname.aname, "mpool create") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pmpinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + + return nsfw_remote_shmem_mpcreate (aname, pmpinfo->usnum, + pmpinfo->useltsize, SOCKET_ID_ANY, + pmpinfo->enmptype); +} + +i32 +nsfw_shmem_spcreatev (nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET (); + + if (NSFW_PROC_MASTER == NSFW_SHMEM_FLAG) + { + return NSFW_MEM_ERR; + } + else if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_remote_shmem_mpcreatev (pmpinfo, pringhandle_array, inum, + 0); + } + else + { + return nsfw_remote_shmem_mpcreatev (pmpinfo, pringhandle_array, inum, + NSFW_SHMEM_PID); + } + return NSFW_MEM_ERR; +} + +i32 +nsfw_lshmem_ringcreatev (const char *name, i32 ieltnum, + mring_handle * pringhandle_array, i32 iringnum, + i32 socket_id, nsfw_mpool_type entype) +{ + i32 useltsize = 0; + mring_handle nhandle = NULL; + i32 icount = 0; + i32 n = 0; + uint64_t baseaddr = 0; + uint64_t endaddr = 0; + i32 usnum = common_mem_align32pow2 (ieltnum + 1); + + useltsize = + sizeof (struct nsfw_mem_ring) + usnum * sizeof (union RingData_U); + nhandle = + nsfw_shmem_pool_create (name, iringnum, useltsize, socket_id, + NSFW_MRING_SPSC); + if (NULL == (nhandle)) + { + return NSFW_MEM_ERR; + } + + n = + nsfw_shmem_ring_sc_dequeuev (nhandle, (void **) pringhandle_array, + iringnum); + + if (n != iringnum) + { + NSCOMM_LOGERR + ("ring dequeuev failed] ring=%p, dequeue num=%d, expect num=%d", + nhandle, n, iringnum); + return NSFW_MEM_ERR; + } + + nsfw_shmem_ring_baseaddr_query (&baseaddr, &endaddr); + + for (icount = 0; icount < iringnum; icount++) + { + nsfw_mem_ring_init (pringhandle_array[icount], usnum, (void *) baseaddr, + NSFW_SHMEM, entype); + } + + return NSFW_MEM_OK; +} + +i32 +nswf_shmem_sp_ringcreate (nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, i32 iringnum) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_lshmem_ringcreatev (prpoolinfo->stname.aname, + prpoolinfo->usnum, pringhandle_array, + iringnum, SOCKET_ID_ANY, + prpoolinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET (prpoolinfo->stname.aname, "ring pool") + int retVal = SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + prpoolinfo->stname.aname, NSFW_SHMEM_PID); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + + return nsfw_remote_shmem_ringcreatev (aname, prpoolinfo->usnum, + pringhandle_array, iringnum, + SOCKET_ID_ANY, prpoolinfo->enmptype); +} + +i32 +nsfw_shmem_sprelease (nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + void *mz_mem = NULL; + struct nsfw_mem_ring *ring_ptr = NULL; + NSFW_INIT_CHK_RET (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + mz_mem = common_memzone_data_lookup_name (pname->aname); + + if (mz_mem) + { + ring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof (struct nsfw_shmem_ring_head)); + nsfw_shmem_pool_free (ring_ptr); + } + return NSFW_MEM_OK; + } + else + { + NSFW_NAME_LENCHECK_RET (pname->aname, "shmem free") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + + return nsfw_remote_free (aname, NSFW_MEM_SPOOL); +} + +mring_handle +nsfw_shmem_sp_lookup (nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + void *mz_mem = NULL; + struct nsfw_mem_ring *ring_ptr = NULL; + NSFW_INIT_CHK_RET_NULL (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + mz_mem = common_memzone_data_lookup_name (pname->aname); + + if (mz_mem) + { + ring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof (struct nsfw_shmem_ring_head)); + return ring_ptr; + } + return mz_mem; + } + + if ((NSFW_PROC_NULL == pname->enowner) + || (NSFW_PROC_MAIN == pname->enowner)) + { + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", pname->aname)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + else + { + /*app's name can not over NSFW_MEM_APPNAME_LENTH */ + NSFW_NAME_LENCHECK_RET_NULL (pname->aname, "shmem lookup") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + + return nsfw_remote_shmem_lookup (aname, NSFW_MEM_SPOOL); +} + +mring_handle +nsfw_shmem_ringcreate (nsfw_mem_mring * pringinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL (); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_shmem_ring_create (pringinfo->stname.aname, + pringinfo->usnum, pringinfo->isocket_id, + pringinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET_NULL (pringinfo->stname.aname, "ring create") + if (-1 == + SPRINTF_S (aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pringinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSCOMM_LOGERR ("SPRINTF_S faild]"); + } + } + + return nsfw_remote_shmem_ringcreate (aname, pringinfo->usnum, SOCKET_ID_ANY, + pringinfo->enmptype); +} + +mring_handle +nsfw_shmem_ring_lookup (nsfw_mem_name * pname) +{ + return nsfw_shmem_lookup (pname); +} + +i32 +nsfw_shmem_ringrelease (nsfw_mem_name * pname) +{ + return nsfw_shmem_release (pname); +} + +size_t +nsfw_shmem_mbufpool_statics (mpool_handle mbufpool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) mbufpool; + return (size_t) mp->size * (mp->header_size + mp->elt_size + + mp->trailer_size) + + (size_t) mp->private_data_size + + (size_t) + common_mem_ring_get_memsize (common_mem_align32pow2 (mp->size + 1)); +} + +size_t +nsfw_shmem_sppool_statics (mring_handle sppool) +{ + struct nsfw_shmem_ring_head *temp = NULL; + size_t lent = 0; + temp = + (struct nsfw_shmem_ring_head *) ((char *) sppool - + sizeof (struct nsfw_shmem_ring_head)); + + while (temp) + { + lent += temp->mem_zone->len; + temp = temp->next; + } + + return lent; +} + +size_t +nsfw_shmem_ring_statics (mring_handle handle) +{ + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) handle; + return ring->size * sizeof (union RingData_U) + + sizeof (struct nsfw_mem_ring); +} + +ssize_t +nsfw_shmem_stactic (void *handle, nsfw_mem_struct_type type) +{ + switch (type) + { + case NSFW_MEM_MBUF: + return nsfw_shmem_mbufpool_statics (handle); + case NSFW_MEM_SPOOL: + return nsfw_shmem_sppool_statics (handle); + case NSFW_MEM_RING: + return nsfw_shmem_ring_statics (handle); + default: + break; + } + return -1; +} + +i32 +nsfw_shmem_mbuf_recycle (mpool_handle handle) +{ +#if 0 + const struct common_mem_mempool *mp = (struct common_mem_mempool *) handle; + struct common_mem_ring *rteRing = NULL; + struct common_mem_mbuf *m_buf = NULL; + uint32_t item; + u32_t *recycle_flg; + uint32_t size = mp->size; + uint32_t threadsize = (size >> 2) * 3; + rteRing = (struct common_mem_ring *) ADDR_SHTOL (mp->ring); + + if (rteRing->prod.tail - rteRing->cons.head < threadsize) + { + for (item = 0; item < size - 1; item++) + { + m_buf = (struct common_mem_mbuf *) ADDR_SHTOL (mp->elt_va_start + item * (mp->header_size + mp->elt_size + mp->trailer_size) + mp->header_size); /*lint !e647 */ + recycle_flg = + (uint32_t *) ((char *) (ADDR_SHTOL (m_buf->buf_addr_align)) + + RTE_PKTMBUF_HEADROOM - sizeof (uint32_t)); + + if (m_buf->refcnt > 0 && *recycle_flg == MBUF_HLD_BY_APP) + { + NSCOMM_LOGINF ("free mbuf hold by app]ring=%p, mbuf=%p", handle, + m_buf); + *recycle_flg = MBUF_UNUSED; + common_mem_pktmbuf_free (m_buf); + } + } + } + + NSCOMM_LOGINF ("To recycle app_tx_pool now]ring=%p,prod.head=%u," + "prod.tail=%u,cons.head=%u,cons.tail=%u.", handle, + rteRing->prod.head, rteRing->prod.tail, + rteRing->cons.head, rteRing->cons.tail); + + /*we Must check and recorrect the Queue if Queue is not correct + 1.if proc.head != proc.tail set proc.head to proc.tail [may lost some buf,but the queue still can use] + App May not putIn Data , just done head++, we can't set proc.tail to proc.head. + 2.if cons.head != cons.tail set cons.tail to cons.head [may lost some buf,but the queue still can use] + App May alread finish deque,just not tail++, we can't set cons.head to cons.tail. + */ + if ((rteRing->prod.head != rteRing->prod.tail) + || (rteRing->cons.head != rteRing->cons.tail)) + { + rteRing->prod.head = rteRing->prod.tail; + rteRing->cons.tail = rteRing->cons.head; + } +#endif + return NSFW_MEM_OK; +} + +/***************************************************************************** +* Prototype : nsfw_shmem_sp_iterator +* Description : sp pool iterator +* Input : mpool_handle handle +* u32 start +* u32 end +* nsfw_mem_item_fun fun +* void *argv +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_shmem_sp_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + struct nsfw_mem_ring *perfring_ptr = (struct nsfw_mem_ring *) handle; + if (NULL == perfring_ptr || NULL == fun) + { + return 0; + } + + if (0 == perfring_ptr->eltsize) + { + return 0; + } + + int num = perfring_ptr->size; + if (start >= (u32) num || end <= start) + { + return 0; + } + + struct nsfw_shmem_ring_head *ring_head = + (struct nsfw_shmem_ring_head *) ((char *) handle - + sizeof (struct nsfw_shmem_ring_head)); + void *mz = + (void *) ((char *) perfring_ptr + sizeof (struct nsfw_mem_ring) + + num * sizeof (union RingData_U)); + + if (ring_head->mem_zone->len < + sizeof (struct nsfw_shmem_ring_head) + sizeof (struct nsfw_mem_ring) + + num * sizeof (union RingData_U)) + { + return 0; + } + + u32 mz_len = + ring_head->mem_zone->len - sizeof (struct nsfw_shmem_ring_head) - + sizeof (struct nsfw_mem_ring) - num * sizeof (union RingData_U); + + u32 start_idx = 0; + u32 elm_num = 0; + elm_num = mz_len / perfring_ptr->eltsize; + while (start > start_idx + elm_num) + { + if (NULL == ring_head->next || NULL == ring_head->next->mem_zone + || 0 == elm_num) + { + return 0; + } + + ring_head = + (struct nsfw_shmem_ring_head *) ring_head->next->mem_zone->addr_64; + mz_len = + ring_head->mem_zone->len - sizeof (struct nsfw_shmem_ring_head); + + elm_num = mz_len / perfring_ptr->eltsize; + mz = + (void *) ((char *) ring_head + sizeof (struct nsfw_shmem_ring_head)); + start_idx += elm_num; + } + + u32 cur_idx = start - start_idx; + char *cur_elm = NULL; + int proc_count = 0; + while (cur_idx + start_idx < end && cur_idx + start_idx < (u32) num) + { + if (cur_idx >= elm_num) + { + if (NULL == ring_head->next || NULL == ring_head->next->mem_zone + || 0 == elm_num) + { + break; + } + + ring_head = + (struct nsfw_shmem_ring_head *) ring_head->next-> + mem_zone->addr_64; + mz_len = + ring_head->mem_zone->len - sizeof (struct nsfw_shmem_ring_head); + + elm_num = mz_len / perfring_ptr->eltsize; + mz = + (void *) ((char *) ring_head + + sizeof (struct nsfw_shmem_ring_head)); + start_idx += elm_num; + + cur_idx = 0; + cur_elm = NULL; + continue; + } + + if (NULL == cur_elm) + { + cur_elm = ((char *) mz + cur_idx * perfring_ptr->eltsize); + } + else + { + cur_elm += perfring_ptr->eltsize; + } + + cur_idx++; + proc_count++; + (void) fun (cur_elm, argv); + } + + return proc_count; +} + +i32 +nsfw_shmem_mbuf_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + return dmm_pktmbuf_pool_iterator ((struct common_mem_mempool *) handle, + start, end, (dmm_mbuf_item_fun) fun, + argv); +} diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mng.h b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mng.h new file mode 100644 index 0000000..f81b34a --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_mng.h @@ -0,0 +1,133 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_MNG_H +#define _NSFW_SHMEM_MNG_H + +/* + * mem mgr module init + * para:point to nstak_fwmem_para + */ +i32 nsfw_shmem_init (nsfw_mem_para * para); + +/* + * mem mgr module destory + * + */ +void nsfw_shmem_destroy (void); + +/* + * create a block memory with name + * fw_mem_zone::stname name of memory + * fw_mem_zone::isize memory size + */ +mzone_handle nsfw_shmem_create (nsfw_mem_zone * pinfo); + +/* + *create some blocks memeory + */ +i32 nsfw_shmem_createv (nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num); + +/* + *lookup a memory + */ +mzone_handle nsfw_shmem_lookup (nsfw_mem_name * pname); + +/*release the memory*/ +i32 nsfw_shmem_release (nsfw_mem_name * pname); + +/* + *create mbuf pool + */ +mpool_handle nsfw_shmem_mbfmpcreate (nsfw_mem_mbfpool * pbufinfo); + +/* + *create some mbuf pool + */ +i32 nsfw_shmem_mbfmpcreatev (nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num); + +/* + *alloc a mbuf from mbuf pool + */ +mbuf_handle nsfw_shmem_mbfalloc (mpool_handle mhandle); + +/* + *release a mbuf pool + */ +i32 nsfw_shmem_mbffree (mbuf_handle mhandle); + +/* + *put mbuf backto mbuf pool + */ +i32 nsfw_shmem_mbfmprelease (nsfw_mem_name * pname); + +/*look up mbuf mpool*/ +mpool_handle nsfw_shmem_mbfmplookup (nsfw_mem_name * pmbfname); + +/* + *create simple pool + */ +mring_handle nsfw_shmem_spcreate (nsfw_mem_sppool * pmpinfo); + +/* + *create some simple pools + */ +i32 nsfw_shmem_spcreatev (nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num); + +/* + *create a simple pool that members are rings + */ +i32 nswf_shmem_sp_ringcreate (nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, i32 iringnum); + +/* + *release a simple pool + */ +i32 nsfw_shmem_sprelease (nsfw_mem_name * pname); + +/* + *look up a simple pool + */ +mring_handle nsfw_shmem_sp_lookup (nsfw_mem_name * pname); + +/* + *create a ring with name + */ +mring_handle nsfw_shmem_ringcreate (nsfw_mem_mring * pringinfo); + +/* + *look up a ring with name + */ +mring_handle nsfw_shmem_ring_lookup (nsfw_mem_name * pname); + +/* + *release ring + */ +i32 nsfw_shmem_ringrelease (nsfw_mem_name * pname); + +ssize_t nsfw_shmem_stactic (void *handle, nsfw_mem_struct_type type); + +i32 nsfw_shmem_mbuf_recycle (mpool_handle handle); + +i32 nsfw_shmem_sp_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); +i32 nsfw_shmem_mbuf_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); + +#endif diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_ring.c b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_ring.c new file mode 100644 index 0000000..af46e18 --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_ring.c @@ -0,0 +1,839 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include <common_sys_config.h> + +#include "common_mem_pal.h" +#include "common_mem_pal_memconfig.h" +#include "nstack_securec.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_ring_fun.h" +#include "common_mem_buf.h" +#include "common_func.h" + +void +nsfw_shmem_ring_baseaddr_query (uint64_t * rte_lowest_addr, + uint64_t * rte_highest_addr) +{ + struct common_mem_mem_config *pMemCfg = + common_mem_pal_get_configuration ()->mem_config; + struct common_mem_memseg *PMemSegArry = pMemCfg->memseg; + + *rte_lowest_addr = PMemSegArry[0].addr_64; + *rte_highest_addr = PMemSegArry[0].addr_64 + PMemSegArry[0].len; + + int s = 1; + + while (s < COMMON_MEM_MAX_MEMSEG && PMemSegArry[s].len > 0) + { + if (*rte_lowest_addr > PMemSegArry[s].addr_64) + { + *rte_lowest_addr = PMemSegArry[s].addr_64; + } + + if (*rte_highest_addr < PMemSegArry[s].addr_64 + PMemSegArry[s].len) + { + *rte_highest_addr = PMemSegArry[s].addr_64 + PMemSegArry[s].len; + } + + s++; + } + +} + +static unsigned +nsfw_shmem_pool_node_alloc (struct nsfw_mem_ring *perfring_ptr, + unsigned alloc_index, unsigned max_index, + void *mz, size_t mz_len, unsigned elt_size) +{ + size_t alloc_size = 0; + unsigned offset_idx = 0; + NSTCP_LOGINF ("mz(%p), mz_len = 0x%x", mz, mz_len); + + while (alloc_size + elt_size <= mz_len) + { + perfring_ptr->ring[alloc_index + offset_idx].data_s.ver = + alloc_index + offset_idx; + perfring_ptr->ring[alloc_index + offset_idx].data_s.val = + ADDR_LTOSH_EXT (mz) - ((uint64_t) perfring_ptr->Addrbase); + mz = (char *) mz + elt_size; + alloc_size += elt_size; + offset_idx++; + + if (alloc_index + offset_idx == max_index) + { + break; + } + } + + return offset_idx; +} + +void +nsfw_shmem_pool_free (struct nsfw_mem_ring *perfring_ptr) +{ + struct nsfw_shmem_ring_head *ptemp; + + if (NULL == perfring_ptr) + { + return; + } + + struct nsfw_shmem_ring_head *pnode = + (struct nsfw_shmem_ring_head *) ((char *) perfring_ptr - + sizeof (struct nsfw_shmem_ring_head)); + + while (pnode) + { + // phead is involved in phead->mem_zone + ptemp = pnode->next; + common_mem_memzone_free (pnode->mem_zone); + pnode = ptemp; + } +} + +struct nsfw_mem_ring * +nsfw_shmem_pool_create (const char *name, unsigned int n, + unsigned int elt_size, int socket_id, + unsigned char flag) +{ + struct nsfw_mem_ring *perfring_ptr = NULL; + struct common_mem_memzone *mz_mem; + void *mz = NULL; + + /*get pool size, pool size must pow of 2 */ + unsigned int num = common_mem_align32pow2 (n + 1); + + struct nsfw_shmem_ring_head *pcur = NULL; + /*calculat the empty rte_perf_ring Size */ + size_t len = + sizeof (struct nsfw_shmem_ring_head) + sizeof (struct nsfw_mem_ring) + + (size_t) num * sizeof (union RingData_U) + (size_t) num * elt_size; + size_t alloc_len = len; + unsigned int alloc_num = 0; + unsigned int alloc_index = 0; + + size_t mz_len = 0; + + unsigned int mz_index = 1; + char mz_name[128] = { 0 }; + int retVal; + /*we'd better use `strlen(src)` or `sizeof(dst)` to explain copying length of src string. + it's meaningless using `sizeof(dst) - 1` to reserve 1 byte for '\0'. + if copying length equals to or bigger than dst length, just let STRNCPY_S() returns failure. */ + retVal = STRNCPY_S (mz_name, sizeof (mz_name), name, sizeof (mz_name)); + + if (EOK != retVal) + { + NSTCP_LOGERR ("STRNCPY_S failed]ret=%d", retVal); + return NULL; + } + + mz_mem = common_memzone_data_lookup_name (name); + NSTCP_LOGINF ("memzone data look up] n=%u,num=%u,len=%zu", n, num, len); + + if (mz_mem) + { + perfring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof (struct nsfw_shmem_ring_head)); + return perfring_ptr; + } + + while (alloc_len > 0) + { + if (NULL != perfring_ptr) + { + retVal = + SPRINTF_S (mz_name, sizeof (mz_name), "%s_%03d", name, mz_index); + + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + nsfw_shmem_pool_free (perfring_ptr); + return NULL; + } + } + + mz_mem = + (struct common_mem_memzone *) common_mem_memzone_reserve (mz_name, + alloc_len, + socket_id, + 0); + + if (mz_mem == NULL) + { + mz_mem = + (struct common_mem_memzone *) common_mem_memzone_reserve (mz_name, + 0, + socket_id, + 0); + } + + if (mz_mem == NULL) + { + nsfw_shmem_pool_free (perfring_ptr); + return NULL; + } + + if (NULL == perfring_ptr + && (mz_mem->len < + sizeof (struct nsfw_shmem_ring_head) + + sizeof (struct nsfw_mem_ring) + + num * sizeof (union RingData_U))) + { + common_mem_memzone_free (mz_mem); + return NULL; + } + + if (NULL == perfring_ptr) + { + pcur = (struct nsfw_shmem_ring_head *) ADDR_SHTOL (mz_mem->addr_64); + pcur->mem_zone = mz_mem; + pcur->next = NULL; + + perfring_ptr = + (struct nsfw_mem_ring *) ((char *) pcur + + sizeof (struct nsfw_shmem_ring_head)); + + mz = + (void *) ((char *) perfring_ptr + sizeof (struct nsfw_mem_ring) + + num * sizeof (union RingData_U)); + mz_len = + mz_mem->len - sizeof (struct nsfw_shmem_ring_head) - + sizeof (struct nsfw_mem_ring) - num * sizeof (union RingData_U); + + uint64_t rte_base_addr; + uint64_t rte_highest_addr; + nsfw_shmem_ring_baseaddr_query (&rte_base_addr, &rte_highest_addr); + nsfw_mem_pool_head_init (perfring_ptr, num, elt_size, + (void *) rte_base_addr, NSFW_SHMEM, + (nsfw_mpool_type) flag); + } + else + { + if (pcur) + { + pcur->next = + (struct nsfw_shmem_ring_head *) ADDR_SHTOL (mz_mem->addr_64); + pcur = pcur->next; + pcur->mem_zone = mz_mem; + pcur->next = NULL; + + if (mz_mem->len < sizeof (struct nsfw_shmem_ring_head)) + { + NSCOMM_LOGERR ("mz_len error %d", mz_mem->len); + nsfw_shmem_pool_free (perfring_ptr); + return NULL; + } + + mz = + (void *) ((char *) pcur + + sizeof (struct nsfw_shmem_ring_head)); + mz_len = mz_mem->len - sizeof (struct nsfw_shmem_ring_head); + } + } + + alloc_num = + nsfw_shmem_pool_node_alloc (perfring_ptr, alloc_index, num, mz, + mz_len, elt_size); + alloc_index += alloc_num; + + if (alloc_index >= num) + { + break; + } + + // second time allocate should not containd all ring head + alloc_len = + (size_t) (num - alloc_index) * elt_size + + sizeof (struct nsfw_shmem_ring_head); + mz_index++; + } + + return perfring_ptr; +} + +/*ring create*/ +struct nsfw_mem_ring * +nsfw_shmem_ring_create (const char *name, unsigned int n, int socket_id, + unsigned char flag) +{ + struct nsfw_mem_ring *perfring_ptr; + struct common_mem_memzone *mz; + uint64_t rte_base_addr; + uint64_t rte_highest_addr; + + unsigned int num = common_mem_align32pow2 (n); + + mz = + (struct common_mem_memzone *) common_mem_memzone_reserve (name, + sizeof (struct + nsfw_mem_ring) + + + num * + sizeof (union + RingData_U), + socket_id, 0); + + if (mz == NULL) + { + return NULL; + } + + perfring_ptr = mz->addr; + + nsfw_shmem_ring_baseaddr_query (&rte_base_addr, &rte_highest_addr); + nsfw_mem_ring_init (perfring_ptr, num, (void *) rte_base_addr, NSFW_SHMEM, + flag); + + return perfring_ptr; +} + +/* +this is a multi thread/process enqueue function, please pay attention to the bellow point +1. while Enqueue corrupt, we may lose one element; because no one to add the Head +*/ +int +nsfw_shmem_ring_mp_enqueue (struct nsfw_mem_ring *ring, void *box) +{ + union RingData_U expectPostVal; + union RingData_U curVal; + unsigned int tmpHead; + unsigned int tmpTail; + unsigned int CurHead = ring->prod.head; + unsigned int mask = ring->mask; + unsigned int size = ring->size; + void *prmBox = NULL; + + prmBox = (void *) ADDR_LTOSH_EXT (box); + + /*do box range check */ + if ((char *) prmBox <= (char *) ring->Addrbase + || (char *) prmBox > (char *) ring->Addrbase + PERFRING_ADDR_RANGE) + { + /*invalid addr of box, can't put in rte_perf_ring, maybe should set a errno here */ + return -1; + } + + do + { + /* + if the ring is Full return directly; this not a exact check, cause we made tail++ after dequeue success. + the thing we could make sure is ring[ring->Tail&mask] already dequeue + */ + tmpTail = ring->cons.tail; + + if (tmpTail + size - CurHead == 0) + { + /* + here we give enque a chance to recorrect the Tail, if tail not has Data let tail++ + */ + if (ring->ring[tmpTail & mask].data_s.val == 0) + { + (void) __sync_bool_compare_and_swap (&ring->cons.tail, tmpTail, + tmpTail + 1); + } + else + { + return 0; + } + } + + /* + the old version of ring->ring[CurHead&mask] must CurHead - size, which enqueue set to this pos lasttime + & the val must already dequeue. otherwise this pos can't enqueue; + */ + expectPostVal.data_l = + (((unsigned long long) (CurHead - size)) << VALUE_LEN); + + /* + the new version of ring->ring[CurHead&mask] must CurHead, which enqueue set to this pos this time. + */ + curVal.data_l = + ((((unsigned long long) CurHead) << VALUE_LEN) | + ((char *) prmBox - (char *) ring->Addrbase)); + if (ring->ring[CurHead & mask].data_s.ver == expectPostVal.data_s.ver + && __sync_bool_compare_and_swap (&ring->ring[CurHead & mask].data_l, + expectPostVal.data_l, + curVal.data_l)) + { + /* + enqueue success, add Head Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Head, 1) to assume that, if one process enque sucess && been killed before + add Head, other process can recorrect the Head Value; + one more thing the direction of Tail must been add-direction, so we using the condition (ring->Head - CurHead >0x80000000); + while many thread do enque at same time, Head may not correct,exp: + thread A get old head 10, thread A want set head to 11 + thread B get old head 10, thread B want set head to 12 + thread A do CAS && thread B do CAS at same time, thread A do CAS success; + the result of head is 11, but the correct Value should be 12; + + then thread C get old head 11, thread C will set head to 13[cause pos 12 already has value, thread C will skill 12], + the head will be recorrect by thread C. + if no thread C, thread A& B are the last enque thread; the head must recorrect by the deque function. + */ + tmpHead = ring->prod.head; + + if (0 == (CurHead & 0x03) && tmpHead - CurHead > 0x80000000) + { + (void) __sync_bool_compare_and_swap (&ring->prod.head, tmpHead, + CurHead + 1); + } + + break; + } + + /* + CurHead++ here; + may be cpu slice is end here; while re-sched CurHead < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurHead++ instead CurHead++ directly. + if using CurHead++ will amplify the probability of ABA problem + */ + /*CurHead++; */ + tmpHead = ring->prod.head; + CurHead = CurHead - tmpHead < mask - 1 ? CurHead + 1 : tmpHead; + } + while (1); + + return 1; +} + +/* + this is a single thread/process enqueue function + */ +int +nsfw_shmem_ring_sp_enqueue (struct nsfw_mem_ring *ring, void *box) +{ + union RingData_U texpectPostVal; + union RingData_U curVal; + unsigned int tmpTail; + unsigned int CurHead = ring->prod.head; + unsigned int mask = ring->mask; + unsigned int uisize = ring->size; + void *prmBox = NULL; + + prmBox = (void *) ADDR_LTOSH_EXT (box); + + if ((char *) prmBox <= (char *) ring->Addrbase + || (char *) prmBox > (char *) ring->Addrbase + PERFRING_ADDR_RANGE) + { + return -1; + } + + do + { + tmpTail = ring->cons.tail; + if (tmpTail + uisize - CurHead == 0) + { + /* + *here we give enque a chance to recorrect the Tail, if tail not has Data let tail++ + */ + if (ring->ring[tmpTail & mask].data_s.val == 0) + { + (void) __sync_bool_compare_and_swap (&ring->cons.tail, tmpTail, + tmpTail + 1); + } + else + { + return 0; + } + } + texpectPostVal.data_l = + (((unsigned long long) (CurHead - uisize)) << VALUE_LEN); + + curVal.data_l = + ((((unsigned long long) CurHead) << VALUE_LEN) | + ((char *) prmBox - (char *) ring->Addrbase)); + + if (ring->ring[CurHead & mask].data_l == texpectPostVal.data_l) + { + ring->ring[CurHead & mask].data_l = curVal.data_l; + ring->prod.head = CurHead + 1; + break; + } + + CurHead++; + } + while (1); + return 1; +} + +/*this is a multi thread/process dequeue function, please pay attention to the bellow point +*/ +int +nsfw_shmem_ring_mc_dequeue (struct nsfw_mem_ring *ring, void **box) +{ + unsigned int CurTail; + unsigned int tmpTail; + unsigned int tmpHead; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + + CurTail = ring->cons.tail; + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + + if (CurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++ + */ + if (ring->ring[tmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap (&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return 0; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + /* + *the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val) + && __sync_bool_compare_and_swap (&ring->ring[CurTail & mask].data_l, + ExcpRingVal.data_l, + curNullVal.data_l)) + { + + *box = + ADDR_SHTOL (((char *) ring->Addrbase + ExcpRingVal.data_s.val)); + + /* + enqueue success, add Tail Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Tail, 1) to assume that, if one process dequeue sucess && been killed before + add Tail, other process can recorrect the Tail Value; + one more thing the direction of Tail must been add-direction, so we using the condition (rlTail - CurTail >0x80000000); + while multi CAS done the result value of CurTail may not correct, but we don't care, it will be recorrect while next deque done. + + avg CAS cost 200-300 Cycles, so we using cache loop to instead some CAS;[head&tail not exact guide, so no need Do CAS evertime] + here we using 0 == (CurTail&0x11) means we only do CAS while head/tail low bit is 0x11; four times do one CAS. + */ + tmpTail = ring->cons.tail; + + if (0 == (CurTail & 0x03) && tmpTail - CurTail > 0x80000000) + { + (void) __sync_bool_compare_and_swap (&ring->cons.tail, tmpTail, + CurTail + 1); + } + break; + } + + /* + CurTail++ here; + may be cpu slice is end here; while re-sched CurTail < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurTail++ instead CurTail++ directly. + if using CurTail++ will amplify the probability of ABA problem + */ + /*CurTail++; */ + tmpTail = ring->cons.tail; + CurTail = CurTail - tmpTail < mask - 1 ? CurTail + 1 : tmpTail; + } + while (1); + + return 1; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_shmem_ring_mc_dequeuev (struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + unsigned int uiCurTail; + unsigned int tmpTail; + unsigned int tmpHead; + unsigned int uimask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int deqNum = 0; + uiCurTail = ring->cons.tail; + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + if (uiCurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++; + here must done to avoid some msg can't deque. + */ + if (deqNum == 0 && ring->ring[tmpHead & uimask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap (&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return deqNum; + } + } + + curNullVal.data_l = (((unsigned long long) uiCurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[uiCurTail & uimask]; + + /* + *the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val) + && __sync_bool_compare_and_swap (&ring-> + ring[uiCurTail & uimask].data_l, + ExcpRingVal.data_l, + curNullVal.data_l)) + { + + box[deqNum] = + ADDR_SHTOL (((char *) ring->Addrbase + ExcpRingVal.data_s.val)); + + /* + enqueue success, add Tail Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Tail, 1) to assume that, if one process dequeue sucess && been killed before + add Tail, other process can recorrect the Tail Value; + one more thing the direction of Tail must been add-direction, so we using the condition (rlTail - CurTail >0x80000000); + + avg CAS cost 200-300 Cycles, so we using cache loop to instead some CAS;[head&tail not exact guide, so no need Do CAS evertime] + here we using 0 == (CurTail&0x11) means we only do CAS while head/tail low bit is 0x11; four times do one CAS. + */ + tmpTail = ring->cons.tail; + + if (0 == (uiCurTail & 0x03) && tmpTail - uiCurTail > 0x80000000) + { + (void) __sync_bool_compare_and_swap (&ring->cons.tail, tmpTail, + uiCurTail + 1); + } + + deqNum++; + } + + /* + CurTail++ here; + may be cpu slice is end here; while re-sched CurTail < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurTail++ instead CurTail++ directly. + if using CurTail++ will amplify the probability of ABA problem + */ + /*CurTail++; */ + tmpTail = ring->cons.tail; + uiCurTail = uiCurTail - tmpTail < uimask - 1 ? uiCurTail + 1 : tmpTail; + + } + while (n > deqNum); + + return deqNum; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_shmem_ring_sc_dequeue (struct nsfw_mem_ring *ring, void **box) +{ + unsigned int CurTail; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int uitmpHead; + + CurTail = ring->cons.tail; + + do + { + /*if ring is empty return directly */ + uitmpHead = ring->prod.head; + if (CurTail == uitmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++ + */ + if (ring->ring[uitmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap (&ring->prod.head, + uitmpHead, uitmpHead + 1); + } + else + { + return 0; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val)) + { + ring->ring[CurTail & mask].data_l = curNullVal.data_l; + + *box = + ADDR_SHTOL (((char *) ring->Addrbase + ExcpRingVal.data_s.val)); + + ring->cons.tail = CurTail + 1; + break; + } + + CurTail++; + } + while (1); + + return 1; +} + +/* + this is a single thread/process dequeue function +*/ +int +nsfw_shmem_ring_sc_dequeuev (struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + unsigned int CurTail; + unsigned int tmpHead; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int usdeqNum = 0; + + CurTail = ring->cons.tail; + + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + if (CurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++; + here must done to avoid some msg can't deque. + */ + if (usdeqNum == 0 && ring->ring[tmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap (&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return usdeqNum; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + + /* + the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val)) + { + ring->ring[CurTail & mask].data_l = curNullVal.data_l; + + box[usdeqNum] = + ADDR_SHTOL (((char *) ring->Addrbase + ExcpRingVal.data_s.val)); + + ring->cons.tail = CurTail + 1; + usdeqNum++; + } + + CurTail++; + } + while (n > usdeqNum); + + return usdeqNum; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_enqueue (struct nsfw_mem_ring *ring, void *box) +{ + u32 head = 0; + void *prmBox = NULL; + + /*if queue is full, just return 0 */ + if (ring->prod.head >= (ring->size + ring->cons.tail)) + { + return 0; + } + + prmBox = (void *) ADDR_LTOSH_EXT (box); + + head = ring->prod.head; + ring->prod.head = head + 1; + ring->ring[head & ring->mask].data_s.ver = head; + ring->ring[head & ring->mask].data_s.val = + (char *) prmBox - (char *) ring->Addrbase; + return 1; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_dequeue (struct nsfw_mem_ring *ring, void **box) +{ + u32 tail = 0; + + /* if all entries are dequed return 0 */ + if (unlikely (ring->prod.head == ring->cons.tail)) + { + return 0; + } + + tail = ring->cons.tail; + *box = + ADDR_SHTOL ((char *) ring->Addrbase + + ring->ring[tail & ring->mask].data_s.val); + ring->ring[tail & ring->mask].data_s.val = 0; + ring->ring[tail & ring->mask].data_s.ver = tail; + ring->cons.tail++; + return 1; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_dequeuev (struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + u32 tail = 0; + u32 num = 0; + + while (num < n) + { + tail = ring->cons.tail; + + /* if all entries are dequed return 0 */ + if (unlikely (ring->prod.head == ring->cons.tail)) + { + return num; + } + + ring->cons.tail = tail + 1; + + box[num] = + ADDR_SHTOL ((char *) ring->Addrbase + + ring->ring[tail & ring->mask].data_s.val); + + ring->ring[tail & ring->mask].data_s.val = 0; + ring->ring[tail & ring->mask].data_s.ver = tail; + num++; + } + + return num; +} diff --git a/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_ring.h b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_ring.h new file mode 100644 index 0000000..15cd1dd --- /dev/null +++ b/src/framework/common/mem_mgr/nsfw_shmem/nsfw_shmem_ring.h @@ -0,0 +1,60 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_RING_H_ +#define _NSFW_SHMEM_RING_H_ + +#include <stdint.h> + +#include "common_func.h" + +struct nsfw_shmem_ring_head +{ + struct common_mem_memzone *mem_zone; + struct nsfw_shmem_ring_head *next; + unsigned int uireserv[4]; +}; + +void nsfw_shmem_ring_baseaddr_query (uint64_t * rte_lowest_addr, + uint64_t * rte_highest_addr); +struct nsfw_mem_ring *nsfw_shmem_pool_create (const char *name, + unsigned int n, + unsigned int elt_size, + int socket_id, + unsigned char flag); +struct nsfw_mem_ring *nsfw_shmem_ring_create (const char *name, + unsigned int n, int socket_id, + unsigned char flag); + +void nsfw_shmem_pool_free (struct nsfw_mem_ring *perfring_ptr); + +void nsfw_shmem_ring_reset (struct nsfw_mem_ring *ring, unsigned char flag); +int nsfw_shmem_ring_mp_enqueue (struct nsfw_mem_ring *ring, void *box); +int nsfw_shmem_ring_sp_enqueue (struct nsfw_mem_ring *ring, void *box); +int nsfw_shmem_ring_mc_dequeue (struct nsfw_mem_ring *ring, void **box); +int nsfw_shmem_ring_mc_dequeuev (struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_shmem_ring_sc_dequeue (struct nsfw_mem_ring *ring, void **box); +int nsfw_shmem_ring_sc_dequeuev (struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_shmem_ring_singlethread_enqueue (struct nsfw_mem_ring *ring, + void *box); +int nsfw_shmem_ring_singlethread_dequeue (struct nsfw_mem_ring *ring, + void **box); +int nsfw_shmem_ring_singlethread_dequeuev (struct nsfw_mem_ring *ring, + void **box, unsigned int n); + +#endif /*_NSFW_SHMEM_RING_H_*/ diff --git a/src/framework/hal/hal.c b/src/framework/hal/hal.c new file mode 100644 index 0000000..1adf274 --- /dev/null +++ b/src/framework/hal/hal.c @@ -0,0 +1,865 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "common_sys_config.h" +#include "common_mem_mbuf.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "hal.h" +#include "hal_api.h" + +#define HAL_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +/* *INDENT-OFF* */ +static char hal_invalid_char_script[] = {'|', ';', '&', '$', '>', '<', '`', '\\', '\"', '\'', + '(', ')', '[', ']', '~', '?', '*' + }; + +static char* hal_invalid_str_script[] = {"&&", "||", ">>", "${", ";;", "/./", "/../"}; + +static char* hal_invalid_str_script_begin[] = {"./", "../"}; + +extern const netif_ops_t dpdk_netif_ops; + +static hal_hdl_t hal_invaldi_hdl = {.id = -1}; + +static const netif_ops_t* netif_ops_table[HAL_DRV_MAX]; +static int netif_ops_init_flag = 0; + +netif_inst_t netif_tbl[HAL_MAX_NIC_NUM]; +/* *INDENT-ON* */ + +void +hal_io_adpt_register (const netif_ops_t * ops) +{ + int icnt = 0; + if (netif_ops_init_flag == 0) + { + (void) MEMSET_S (&netif_ops_table[0], sizeof (netif_ops_table), 0, + sizeof (netif_ops_table)); + netif_ops_init_flag = 1; + } + + for (icnt = 0; icnt < HAL_DRV_MAX; icnt++) + { + if (netif_ops_table[icnt] == 0) + { + netif_ops_table[icnt] = ops; + break; + } + } + return; +} + +/***************************************************************************** + Prototype : hal_snprintf + Description : create shell script + Input : char* buffer + size_t buflen + const char* format + ... + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_snprintf (char *buffer, size_t buflen, const char *format, ...) +{ + int len; + va_list ap; + + /* check buffer validity */ + if (NULL == buffer || 0 == buflen) + { + goto einval_error; + } + + if (format == NULL) + { + buffer[0] = '\0'; + + goto einval_error; + } + + (void) va_start (ap, format); + len = VSNPRINTF_S (buffer, buflen, buflen - 1, format, ap); + + if (-1 == len) + { + va_end (ap); + goto einval_error; + } + + va_end (ap); + + buffer[buflen - 1] = '\0'; + + return len; + +einval_error: + errno = EINVAL; + return -1; +} + +/***************************************************************************** + Prototype : hal_is_script_valid + Description : Check External Injection of Shell script Validation + Input : const char* cmd + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_is_script_valid (const char *cmd) +{ + unsigned int i; + + if (cmd) + { + char *cmd_str = (char *) cmd; + + /* skip space */ + while (*cmd_str == ' ' || *cmd_str == '\t') + { + cmd_str++; + } + + /* cmd can not start with ./ and ../ */ + for (i = 0; i < HAL_ARRAY_SIZE (hal_invalid_str_script_begin); i++) + { + if (strstr (cmd_str, hal_invalid_str_script_begin[i]) == cmd_str) + { + return 0; + } + } + + /* cmd can not include | ; $ and so on */ + for (i = 0; i < HAL_ARRAY_SIZE (hal_invalid_char_script); i++) + { + if (strchr (cmd, hal_invalid_char_script[i])) + { + return 0; + } + } + + /* cmd can not include && || >> and so on */ + for (i = 0; i < HAL_ARRAY_SIZE (hal_invalid_str_script); i++) + { + if (strstr (cmd, hal_invalid_str_script[i])) + { + return 0; + } + } + + return 1; + } + + return 0; +} + +/***************************************************************************** + Prototype : hal_run_script + Description : run shell script + Input : const char* cmd + char* result_buf + size_t max_result_len + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_run_script (const char *cmd, char *result_buf, size_t max_result_len) +{ + size_t n; + if (!cmd || !result_buf || max_result_len <= 1) + { + return -1; + } + + FILE *fd = popen (cmd, "r"); + + if (fd != NULL) + { + n = fread (result_buf, sizeof (char), max_result_len - 1, fd); + + if (n == 0) + { + result_buf[0] = '\0'; + } + else if ('\n' == result_buf[n - 1]) + { + result_buf[n - 1] = '\0'; + } + /* make it null terminated */ + else + { + result_buf[n] = '\0'; + } + + (void) pclose (fd); + return n; + } + + return -1; +} + +/***************************************************************************** + Prototype : hal_init_global + Description : init hal when proccess start + Input : int argc + char** argv + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_init_global (int argc, char **argv) +{ + int ret; + int netif_type; + + ret = + MEMSET_S (netif_tbl, HAL_MAX_NIC_NUM * sizeof (netif_inst_t), 0, + HAL_MAX_NIC_NUM * sizeof (netif_inst_t)); + if (EOK != ret) + { + NSHAL_LOGERR ("MEMSET_S failed"); + return -1; + } + + for (netif_type = 0; netif_ops_table[netif_type]; ++netif_type) + { + if (netif_ops_table[netif_type]->init_global) + { + if (netif_ops_table[netif_type]->init_global (argc, argv)) + { + NSHAL_LOGERR ("failed to init global]netif type=%d", + netif_type); + return -1; + } + } + } + + return 0; +} + +/***************************************************************************** + Prototype : hal_init_local + Description : init hal when process or thread start + Input : None + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_init_local () +{ + int netif_type; + + for (netif_type = 0; netif_ops_table[netif_type]; ++netif_type) + { + if (netif_ops_table[netif_type]->init_local) + { + if (netif_ops_table[netif_type]->init_local ()) + { + NSHAL_LOGERR ("failed to init local]netif type=%d", netif_type); + return -1; + } + } + } + + return 0; +} + +/***************************************************************************** + Prototype : hal_get_invalid_hdl + Description : get the invalid object + Input : None + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +hal_hdl_t +hal_get_invalid_hdl () +{ + return hal_invaldi_hdl; +} + +/***************************************************************************** + Prototype : hal_create + Description : create hal object + Input : const char* name + hal_netif_config_t* conf + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +hal_hdl_t +hal_create (const char *name, hal_netif_config_t * conf) +{ + int ret = -1; + uint32_t netif_type; + netif_inst_t *inst; + + if ((NULL == name) || (NULL == conf)) + { + NSHAL_LOGERR ("invalid para]name=%p,conf=%p", name, conf); + return hal_get_invalid_hdl (); + } + + inst = alloc_netif_inst (); + + if (NULL == inst) + { + NSHAL_LOGERR ("failed to alloc netif inst]netif name=%s", name); + + return hal_get_invalid_hdl (); + } + + /*open */ + for (netif_type = 0; NULL != netif_ops_table[netif_type]; ++netif_type) + { + ret = netif_ops_table[netif_type]->open (inst, name); + + if (0 == ret) + { + inst->ops = netif_ops_table[netif_type]; + + NSHAL_LOGINF ("netif ops]netif type=%u, netif name=%s", netif_type, + inst->ops->name); + + break; + } + } + + if (ret != 0) + { + inst->state = NETIF_STATE_FREE; + + inst->ops = NULL; + + NSHAL_LOGERR ("open fail]netif name=%s", name); + + return hal_get_invalid_hdl (); + } + + /*config */ + ret = inst->ops->config (inst, conf); + + if (ret != 0) + { + inst->state = NETIF_STATE_FREE; + + NSHAL_LOGERR ("config fail]netif name=%s", name); + + return hal_get_invalid_hdl (); + } + + /*start */ + ret = inst->ops->start (inst); + + if (ret != 0) + { + inst->state = NETIF_STATE_FREE; + + NSHAL_LOGERR ("start fail]netif name=%s", name); + + return hal_get_invalid_hdl (); + } + + return inst->hdl; +} + +/***************************************************************************** + Prototype : hal_bond + Description : create hal object for bond mode + Input : const char* bond_name + uint8_t slave_num + hal_hdl_t slave_hdl[] + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +hal_hdl_t +hal_bond (const char *bond_name, uint8_t slave_num, hal_hdl_t slave_hdl[]) +{ + int i, ret; + netif_inst_t *inst; + netif_inst_t *slave_inst[HAL_MAX_SLAVES_PER_BOND]; + + if ((0 == slave_num) || (HAL_MAX_SLAVES_PER_BOND < slave_num) + || (NULL == bond_name) || (NULL == slave_hdl)) + { + NSHAL_LOGERR ("invalid para]bond_name=%p,slave_num=%u,slave_hdl=%p,", + bond_name, slave_num, slave_hdl); + + return hal_get_invalid_hdl (); + } + + for (i = 0; i < slave_num; i++) + { + slave_inst[i] = get_netif_inst (slave_hdl[i]); + + if (NULL == slave_inst[i]) + { + NSHAL_LOGERR ("invalid para slave_hdl]index=%d, slave_inst=%d", i, + slave_hdl[i].id); + return hal_get_invalid_hdl (); + } + } + + inst = alloc_netif_inst (); + + if (NULL == inst) + { + NSHAL_LOGERR ("failed to alloc nic inst]bond_name=%s", bond_name); + return hal_get_invalid_hdl (); + } + + inst->ops = slave_inst[0]->ops; + + ret = inst->ops->bond (inst, bond_name, slave_num, slave_inst); + + if (0 != ret) + { + inst->state = NETIF_STATE_FREE; + + inst->ops = NULL; + + NSHAL_LOGERR ("bond netif fail]bond_name=%s", bond_name); + + return hal_get_invalid_hdl (); + } + + return inst->hdl; +} + +/***************************************************************************** + Prototype : hal_close + Description : destroy hal object + Input : hal_hdl_t hdl + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_close (hal_hdl_t hdl) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return -1; + } + + inst->state = NETIF_STATE_FREE; + + return inst->ops->close (inst); +} + +/***************************************************************************** + Prototype : hal_stop + Description : stop recv packet + Input : hal_hdl_t hdl + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_stop (hal_hdl_t hdl) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return -1; + } + + return inst->ops->stop (inst); +} + +/***************************************************************************** + Prototype : hal_get_mtu + Description : get the mtu from nic + Input : hal_hdl_t hdl + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +uint32_t +hal_get_mtu (hal_hdl_t hdl) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return 0; + } + + return inst->ops->mtu (inst); +} + +/***************************************************************************** + Prototype : hal_get_macaddr + Description : in normal mode, get the mac addr from nic + in bond mode1, get the mac addr from primary nic + Input : hal_hdl_t hdl + void* mac_addr + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +void +hal_get_macaddr (hal_hdl_t hdl, void *mac_addr) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return; + } + + (void) inst->ops->macaddr (inst, mac_addr); +} + +/***************************************************************************** + Prototype : hal_get_capability + Description : get offload capability from nic + Input : hal_hdl_t hdl + hal_netif_capa_t* info + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +void +hal_get_capability (hal_hdl_t hdl, hal_netif_capa_t * info) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return; + } + + (void) inst->ops->capability (inst, info); +} + +/***************************************************************************** + Prototype : hal_recv_packet + Description : recv packet from nic + Input : hal_hdl_t hdl + uint16_t queue_id + struct common_mem_mbuf** rx_pkts + uint16_t nb_pkts + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +uint16_t +hal_recv_packet (hal_hdl_t hdl, uint16_t queue_id, + struct common_mem_mbuf **rx_pkts, uint16_t nb_pkts) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return 0; + } + + return inst->ops->recv (inst, queue_id, rx_pkts, nb_pkts); +} + +/***************************************************************************** + Prototype : hal_send_packet + Description : send packet to nic + Input : hal_hdl_t hdl + uint16_t queue_id + struct common_mem_mbuf** tx_pkts + uint16_t nb_pkts + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +uint16_t +hal_send_packet (hal_hdl_t hdl, uint16_t queue_id, + struct common_mem_mbuf ** tx_pkts, uint16_t nb_pkts) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return 0; + } + + return inst->ops->send (inst, queue_id, tx_pkts, nb_pkts); +} + +/***************************************************************************** + Prototype : hal_link_status + Description : get link status form nic + Input : hal_hdl_t hdl + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +uint32_t +hal_link_status (hal_hdl_t hdl) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return 0; + } + + return inst->ops->link_status (inst); +} + +/***************************************************************************** + Prototype : hal_stats + Description : get link statistics form nic + Input : hal_hdl_t hdl + hal_netif_stats_t* stats + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_stats (hal_hdl_t hdl, hal_netif_stats_t * stats) +{ + netif_inst_t *inst; + + if (NULL == stats) + { + NSHAL_LOGERR ("invalid para"); + return -1; + } + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return -1; + } + + return inst->ops->stats (inst, stats); +} + +/***************************************************************************** + Prototype : hal_stats_reset + Description : reset link statistics to nic + Input : hal_hdl_t hdl + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +void +hal_stats_reset (hal_hdl_t hdl) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return; + } + + (void) inst->ops->stats_reset (inst); +} + +/***************************************************************************** + Prototype : hal_add_mcastaddr + Description : set multicast addrs to nic + Input : hal_hdl_t hdl + void* mc_addr_set + void* mc_addr + uint32_t nb_mc_addr + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_add_mcastaddr (hal_hdl_t hdl, void *mc_addr_set, + void *mc_addr, uint32_t nb_mc_addr) +{ + int ret; + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return -1; + } + + ret = inst->ops->mcastaddr (inst, mc_addr_set, mc_addr, nb_mc_addr); + /* if set mcast addr failed, we have to manually add the mac addr to nic. */ + if (ret < 0) + { + ret = inst->ops->add_mac (inst, mc_addr); + } + return ret; +} + +/***************************************************************************** + Prototype : hal_del_mcastaddr + Description : delete multicast addrs to nic + Input : hal_hdl_t hdl + void* mc_addr_set + void* mc_addr + uint32_t nb_mc_addr + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +int +hal_del_mcastaddr (hal_hdl_t hdl, void *mc_addr_set, + void *mc_addr, uint32_t nb_mc_addr) +{ + int ret; + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return -1; + } + + ret = inst->ops->mcastaddr (inst, mc_addr_set, mc_addr, nb_mc_addr); + /* if set mcast addr failed, we have to manually delete the mac addr from nic. */ + if (ret < 0) + { + ret = inst->ops->rmv_mac (inst, mc_addr); + } + return ret; +} + +/***************************************************************************** + Prototype : hal_set_allmulti_mode + Description : set all multicast mode + Input : hal_hdl_t hdl + uint8_t enable + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +void +hal_set_allmulti_mode (hal_hdl_t hdl, uint8_t enable) +{ + netif_inst_t *inst; + + inst = get_netif_inst (hdl); + + if (inst == NULL) + { + NSHAL_LOGERR ("netif does not exist]inst=%i", HAL_HDL_TO_ID (hdl)); + return; + } + + (void) inst->ops->allmcast (inst, enable); +} + +/***************************************************************************** + Prototype : hal_is_nic_exist + Description : check nic is exist + Input : const char *name + Output : None + Return Value : + Calls : + Called By : +*****************************************************************************/ +uint32_t +hal_is_nic_exist (const char *name) +{ + char script_cmmd[HAL_SCRIPT_LENGTH]; + char result_buf[HAL_SCRIPT_LENGTH]; + int len_out; + int retval; + + if (!hal_is_script_valid (name)) + { + NSHAL_LOGERR ("nic name is not valid"); + return 0; + } + + retval = + hal_snprintf (script_cmmd, sizeof (script_cmmd), + "sudo ifconfig -a | grep -w \"%s[ :]\"", name); + if (-1 == retval) + { + NSHAL_LOGERR ("rte_snprintf failed]retval=%d", retval); + return 0; + } + + len_out = hal_run_script (script_cmmd, result_buf, sizeof (result_buf) - 1); + /* buffer not initialized, should take length as decision */ + if (0 != len_out) + { + return 1; + } + + return 0; +} diff --git a/src/framework/hal/hal.h b/src/framework/hal/hal.h new file mode 100644 index 0000000..2f66914 --- /dev/null +++ b/src/framework/hal/hal.h @@ -0,0 +1,182 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _HAL_H_ +#define _HAL_H_ + +#include <stdint.h> +#include "hal_api.h" +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define HAL_DRV_MAX 32 + +#define HAL_IO_REGISTER(name, ops) \ + static __attribute__((__constructor__)) void __hal_register##name(void) \ + {\ + hal_io_adpt_register(ops); \ + } \ + + +#define HAL_MAX_PCI_ADDR_LEN 16 + +#define HAL_MAX_DRIVER_NAME_LEN 128 + +#define HAL_MAX_PATH_LEN 4096 //max path length on linux is 4096 + +#define HAL_SCRIPT_LENGTH 256 + +#define HAL_HDL_TO_ID(hdl) (hdl.id) + +/* IO using DPDK interface */ +typedef struct dpdk_if +{ + uint8_t port_id; /**< DPDK port identifier */ + uint8_t slave_num; + uint8_t slave_port[HAL_MAX_SLAVES_PER_BOND]; + + uint32_t hw_vlan_filter:1; + uint32_t hw_vlan_strip:1; + uint32_t rsv30:30; + + uint32_t rx_queue_num; + uint32_t rx_ring_size[HAL_ETH_MAX_QUEUE_NUM]; + struct rte_mempool *rx_pool[HAL_ETH_MAX_QUEUE_NUM]; + + uint32_t tx_queue_num; + uint32_t tx_ring_size[HAL_ETH_MAX_QUEUE_NUM]; + + char pci_addr[HAL_MAX_PCI_ADDR_LEN]; + char nic_name[HAL_MAX_NIC_NAME_LEN]; + char driver_name[HAL_MAX_DRIVER_NAME_LEN]; +} dpdk_if_t; + +typedef struct netif_inst +{ + enum + { + NETIF_STATE_FREE = 0, + NETIF_STATE_ACTIVE + } state; + + hal_hdl_t hdl; + + const struct netif_ops *ops; /**< Implementation specific methods */ + + union + { + dpdk_if_t dpdk_if; /**< using DPDK for IO */ + } data; + +} netif_inst_t; + +typedef struct netif_ops +{ + const char *name; + int (*init_global) (int argc, char **argv); + int (*init_local) (void); + int (*open) (netif_inst_t * inst, const char *name); + int (*close) (netif_inst_t * inst); + int (*start) (netif_inst_t * inst); + int (*stop) (netif_inst_t * inst); + int (*bond) (netif_inst_t * inst, const char *bond_name, + uint8_t slave_num, netif_inst_t * slave[]); + uint32_t (*mtu) (netif_inst_t * inst); + int (*macaddr) (netif_inst_t * inst, void *mac_addr); + int (*capability) (netif_inst_t * inst, hal_netif_capa_t * info); + uint16_t (*recv) (netif_inst_t * inst, uint16_t queue_id, + struct common_mem_mbuf ** rx_pkts, uint16_t nb_pkts); + uint16_t (*send) (netif_inst_t * inst, uint16_t queue_id, + struct common_mem_mbuf ** tx_pkts, uint16_t nb_pkts); + uint32_t (*link_status) (netif_inst_t * inst); + int (*stats) (netif_inst_t * inst, hal_netif_stats_t * stats); + int (*stats_reset) (netif_inst_t * inst); + int (*config) (netif_inst_t * inst, hal_netif_config_t * conf); + int (*mcastaddr) (netif_inst_t * inst, void *mc_addr_set, + void *mc_addr, uint32_t nb_mc_addr); + int (*add_mac) (netif_inst_t * inst, void *mc_addr); + int (*rmv_mac) (netif_inst_t * inst, void *mc_addr); + int (*allmcast) (netif_inst_t * inst, uint8_t enable); +} netif_ops_t; + +extern netif_inst_t netif_tbl[HAL_MAX_NIC_NUM]; + +static inline netif_inst_t * +alloc_netif_inst () +{ + int i; + netif_inst_t *inst; + + for (i = 0; i < HAL_MAX_NIC_NUM; ++i) + { + inst = &netif_tbl[i]; + + if (NETIF_STATE_FREE == inst->state) + { + inst->state = NETIF_STATE_ACTIVE; + + inst->hdl.id = i; + + return inst; + } + } + + return NULL; + +} + +static inline netif_inst_t * +get_netif_inst (hal_hdl_t hdl) +{ + netif_inst_t *inst; + + if (unlikely (!hal_is_valid (hdl))) + { + NSHAL_LOGERR ("inst id is not valid]inst=%i, HAL_MAX_NIC_NUM=%d", + HAL_HDL_TO_ID (hdl), HAL_MAX_NIC_NUM); + + return NULL; + } + + inst = &netif_tbl[HAL_HDL_TO_ID (hdl)]; + + if (unlikely ((NETIF_STATE_ACTIVE != inst->state) || (NULL == inst->ops))) + { + NSHAL_LOGERR ("netif is not active]inst=%i", HAL_HDL_TO_ID (hdl)); + + return NULL; + } + + return inst; +} + +int hal_snprintf (char *buffer, size_t buflen, const char *format, ...); +int hal_is_script_valid (const char *cmd); +int hal_run_script (const char *cmd, char *result_buf, size_t max_result_len); +void hal_io_adpt_register (const netif_ops_t * ops); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/framework/include/hal_api.h b/src/framework/include/hal_api.h new file mode 100644 index 0000000..24ed779 --- /dev/null +++ b/src/framework/include/hal_api.h @@ -0,0 +1,148 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _HAL_API_H_ +#define _HAL_API_H_ + +#include "common_mem_mbuf.h" +#include "common_mem_mempool.h" +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define HAL_ETH_MAX_QUEUE_NUM 4 + +#define HAL_ETH_QUEUE_STAT_CNTRS 16 + +#define HAL_MAX_NIC_NUM 4096 +COMPAT_PROTECT (HAL_MAX_NIC_NUM, 4096); + +#define HAL_MAX_SLAVES_PER_BOND 2 + +#define HAL_MAX_NIC_NAME_LEN 256 + +/** + * TX offload capabilities of a device. + */ +#define HAL_ETH_TX_OFFLOAD_IPV4_CKSUM 0x00000002 +#define HAL_ETH_TX_OFFLOAD_UDP_CKSUM 0x00000004 +#define HAL_ETH_TX_OFFLOAD_TCP_CKSUM 0x00000008 + +/** + * Hal Instance Handler + */ +typedef struct hal_hdl +{ + int id; +} hal_hdl_t; + +/** + * Ethernet device capability + */ +typedef struct hal_netif_capa +{ + uint32_t tx_offload_capa; /**< Device TX offload capabilities. */ +} hal_netif_capa_t; + +/** + * A structure used to retrieve statistics for an Ethernet port. + */ +typedef struct hal_netif_stats +{ + uint64_t ipackets; /**< Total no.of packets that are successfully received . */ + uint64_t opackets; /**< Total no.of packets that are successfully transmitted .*/ + uint64_t ibytes; /**< Total no.of bytes that are successfully received . */ + uint64_t obytes; /**< Total no.of bytes that are successfully transmitted . */ + uint64_t imissed; /**< Total no.of RX packets that are dropped by the HW. */ + uint64_t ierrors; /**< Total no.of packets that are received as erroneous. */ + uint64_t oerrors; /**< Total no.of failed transmitted packets. */ + uint64_t rx_nombuf; /**< Total no.of RX mbuf allocation failures. */ + + uint64_t q_ipackets[HAL_ETH_QUEUE_STAT_CNTRS]; /**< Total no.of queue RX packets. */ + uint64_t q_opackets[HAL_ETH_QUEUE_STAT_CNTRS]; /**< Total no.of queue TX packets. */ + uint64_t q_ibytes[HAL_ETH_QUEUE_STAT_CNTRS]; /**< Total no.of successfully received queue bytes. */ + uint64_t q_obytes[HAL_ETH_QUEUE_STAT_CNTRS]; /**< Total no.of successfully transmitted queue bytes. */ + uint64_t q_errors[HAL_ETH_QUEUE_STAT_CNTRS]; /**< Total no.of queue packets received that are dropped. */ +} hal_netif_stats_t; + +/** + * Ethernet device config + */ +typedef struct hal_netif_config +{ + struct + { + uint32_t hw_vlan_filter:1; + uint32_t hw_vlan_strip:1; + uint32_t rsv30:30; + } bit; + + struct + { + uint32_t queue_num; + uint32_t ring_size[HAL_ETH_MAX_QUEUE_NUM]; + struct common_mem_mempool *ring_pool[HAL_ETH_MAX_QUEUE_NUM]; + } rx; + + struct + { + uint32_t queue_num; + uint32_t ring_size[HAL_ETH_MAX_QUEUE_NUM]; + } tx; + +} hal_netif_config_t; + +int hal_init_global (int argc, char **argv); +int hal_init_local (); +hal_hdl_t hal_create (const char *name, hal_netif_config_t * conf); +hal_hdl_t hal_bond (const char *bond_name, uint8_t slave_num, + hal_hdl_t slave_hdl[]); + +#define hal_is_valid(hdl) ((hdl.id >= 0) && (hdl.id < HAL_MAX_NIC_NUM)) + +#define hal_is_equal(hdl_left, hdl_right) (hdl_left.id == hdl_right.id) + +int hal_close (hal_hdl_t hdl); +int hal_stop (hal_hdl_t hdl); +uint32_t hal_get_mtu (hal_hdl_t hdl); +void hal_get_macaddr (hal_hdl_t hdl, void *mac_addr); +void hal_get_capability (hal_hdl_t hdl, hal_netif_capa_t * info); +uint16_t hal_recv_packet (hal_hdl_t hdl, uint16_t queue_id, + struct common_mem_mbuf **rx_pkts, uint16_t nb_pkts); +uint16_t hal_send_packet (hal_hdl_t hdl, uint16_t queue_id, + struct common_mem_mbuf **tx_pkts, uint16_t nb_pkts); +uint32_t hal_link_status (hal_hdl_t hdl); +int hal_stats (hal_hdl_t hdl, hal_netif_stats_t * stats); +void hal_stats_reset (hal_hdl_t hdl); +int hal_add_mcastaddr (hal_hdl_t hdl, void *mc_addr_set, + void *mc_addr, uint32_t nb_mc_addr); +int hal_del_mcastaddr (hal_hdl_t hdl, void *mc_addr_set, + void *mc_addr, uint32_t nb_mc_addr); +void hal_set_allmulti_mode (hal_hdl_t hdl, uint8_t enable); +uint32_t hal_is_nic_exist (const char *name); +hal_hdl_t hal_get_invalid_hdl (); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/framework/include/nsfw_fd_timer_api.h b/src/framework/include/nsfw_fd_timer_api.h new file mode 100644 index 0000000..0b42fe0 --- /dev/null +++ b/src/framework/include/nsfw_fd_timer_api.h @@ -0,0 +1,64 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_FD_TIMER_API_H +#define _NSFW_FD_TIMER_API_H + +#include "list.h" +#include <time.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_TIMER_MODULE "nsfw_timer" + +typedef struct _nsfw_timer_init_cfg +{ + u32 timer_info_size; + void *timer_info_pool; + struct list_head timer_head; + struct list_head exp_timer_head; +} nsfw_timer_init_cfg; + +typedef int (*nsfw_timer_proc_fun) (u32 timer_type, void *argv); +typedef struct _nsfw_timer_info +{ + struct list_head node; + nsfw_timer_proc_fun fun; + void *argv; + struct timespec time_left; + u32 timer_type; + u8 alloc_flag; +} nsfw_timer_info; + +extern nsfw_timer_info *nsfw_timer_reg_timer (u32 timer_type, void *data, + nsfw_timer_proc_fun fun, + struct timespec time_left); +extern void nsfw_timer_rmv_timer (nsfw_timer_info * tm_info); + +extern u8 g_hbt_switch; +extern int nsfw_timer_module_init (void *param); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_FD_TIMER_API_H */ diff --git a/src/framework/include/nsfw_init.h b/src/framework/include/nsfw_init.h new file mode 100644 index 0000000..def97b2 --- /dev/null +++ b/src/framework/include/nsfw_init.h @@ -0,0 +1,148 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _FW_INIT_H +#define _FW_INIT_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_INIT_PRIORITY_ROOT 101 +#define NSFW_INIT_PRIORITY_BASE 102 +#define NSFW_INIT_PRIORITY_INITFN 103 + +#define NSFW_INIT_MODULE_PRIORITY_BASE 1 +#define NSFW_INIT_MODULE_PRIORITY(x) (NSFW_INIT_MODULE_PRIORITY_BASE + x) + +#define NSFW_SET_INSTANCE_VALUE(_attr, _inst, _value) \ + nsfw_module_set_instance_##_attr(_inst, _value) + +#define NSFW_INIT_CRAETE_LOCAL_INSTANCE() \ + if (!nsfwLocalInitInst) {\ + nsfwLocalInitInst = nsfw_module_create_instance(); \ + nsfw_module_add_instance(nsfwLocalInitInst);\ + } + +#define _NSFW_MODULE_ATTRIBUTE_DEFINE_SURFIX(_attr, _value, _priority, _surfix) \ + static __attribute__((__constructor__(_priority))) void nsfw_module_attribute_##_attr##_surfix(void){\ + NSFW_INIT_CRAETE_LOCAL_INSTANCE(); \ + NSFW_SET_INSTANCE_VALUE(_attr, nsfwLocalInitInst, _value);\ + } \ + +#define NSFW_MODULE_ATTRIBUTE_DEFINE_SURFIX(_attr, _value, _priority, _surfix) \ + _NSFW_MODULE_ATTRIBUTE_DEFINE_SURFIX(_attr, _value, _priority, _surfix) + +#define NSFW_MODULE_ATTRIBUTE_DEFINE_UNIQUE(_attr, _value, _priority) \ + NSFW_MODULE_ATTRIBUTE_DEFINE_SURFIX(_attr, _value, _priority, __LINE__) + +#define NSFW_MODULE_ATTRIBUTE_DEFINE(_attr, _value, _priority) \ + NSFW_MODULE_ATTRIBUTE_DEFINE_UNIQUE(_attr, _value, _priority) + +#define NSFW_MODULE_NAME(_name) \ + NSFW_MODULE_ATTRIBUTE_DEFINE(name, _name, NSFW_INIT_PRIORITY_BASE) + +#define NSFW_MODULE_FATHER(_father) \ + NSFW_MODULE_ATTRIBUTE_DEFINE(father, _father, NSFW_INIT_PRIORITY_BASE) + +#define NSFW_MODULE_PRIORITY(_priority) \ + NSFW_MODULE_ATTRIBUTE_DEFINE(priority, _priority, NSFW_INIT_PRIORITY_BASE) + +#define NSFW_MODULE_DEPENDS(_depends) \ + NSFW_MODULE_ATTRIBUTE_DEFINE(depends, _depends, NSFW_INIT_PRIORITY_BASE) + +#define NSFW_MODULE_INIT(_initfn) \ + NSFW_MODULE_ATTRIBUTE_DEFINE(initfn, _initfn, NSFW_INIT_PRIORITY_INITFN) + +#define NSFW_MAX_STRING_LENGTH 128 + +#define NSFW_DEPENDS_SIZE 8 +typedef struct _nsfw_module_depends +{ + char name[NSFW_MAX_STRING_LENGTH]; + int isReady; + struct _nsfw_module_depends *next; /* It is a list, not just only one */ +} nsfw_module_depends_t; + +typedef enum +{ + NSFW_INST_STAT_CHECKING, /* Not check yet */ + NSFW_INST_STAT_DEPENDING, /* Blocked, waiting for other module instances */ + NSFW_INST_STAT_DONE, /* Check done */ + NSFW_INST_STAT_FAIL /* Check Fail */ +} nsfw_module_instance_stat_t; + +typedef int (*nsfw_module_init_fn) (void *); + +typedef struct _nsfw_module_instance +{ + nsfw_module_init_fn fnInit; + char name[NSFW_MAX_STRING_LENGTH]; + char fatherName[NSFW_MAX_STRING_LENGTH]; + int priority; + nsfw_module_depends_t *depends; + nsfw_module_instance_stat_t stat; + void *param; + struct _nsfw_module_instance *next; + struct _nsfw_module_instance *child; + struct _nsfw_module_instance *father; +} nsfw_module_instance_t; + +static nsfw_module_instance_t *nsfwLocalInitInst __attribute__ ((unused)) = + (void *) 0; + +extern nsfw_module_instance_t *nsfw_module_create_instance (); +extern nsfw_module_instance_t *nsfw_module_getModuleByName (char *); +extern void nsfw_module_add_instance (nsfw_module_instance_t * inst); +extern void nsfw_module_del_instance (nsfw_module_instance_t * inst); +extern void nsfw_module_set_instance_name (nsfw_module_instance_t * inst, + char *name); +extern void nsfw_module_set_instance_father (nsfw_module_instance_t * inst, + char *father); +extern void nsfw_module_set_instance_priority (nsfw_module_instance_t * + inst, int priority); +extern void nsfw_module_set_instance_initfn (nsfw_module_instance_t * inst, + nsfw_module_init_fn fn); +extern void nsfw_module_set_instance_depends (nsfw_module_instance_t * inst, + char *name); + +/** + * @Function nstack_framework_init + * @Description This function will do framework initial work, it will involk all initial functions + * registed using macro NSFW_MODULE_INIT before + * @param none + * @return 0 on success, -1 on error + */ +extern int nstack_framework_init (void); + +/** + * @Function nstack_framework_setModuleParam + * @Description This function set parameter of module initial function parameter + * @param module - name of module + * @param param - parameter to set + * @return 0 on success, -1 on error + */ +extern int nstack_framework_setModuleParam (char *module, void *param); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _FW_INIT_H */ diff --git a/src/framework/include/nsfw_maintain_api.h b/src/framework/include/nsfw_maintain_api.h new file mode 100644 index 0000000..74cedf6 --- /dev/null +++ b/src/framework/include/nsfw_maintain_api.h @@ -0,0 +1,320 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_MEM_STAT_API_H +#define _NSFW_MEM_STAT_API_H + +#include "types.h" +#include "nsfw_mgr_com_api.h" +#include "compiling_check.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/*################MEM_STAT######################*/ +#define NSFW_MEM_MODULE_LEN 32 +#define NSFW_MEM_NAME_LEN 64 + +#define OMC_PROC_MM "omc_proc_maintain" + +#define MEM_STAT(module, mem_name, mem_type, mem_size)\ + nsfw_mem_stat(module, mem_name, mem_type, mem_size) + +extern void nsfw_mem_stat (char *module, char *mem_name, u8 mem_type, + u32 mem_size); +extern void nsfw_mem_stat_print (); +/*##############################################*/ + +/*################SRV_CTRL######################*/ +typedef enum _nsfw_srv_ctrl_state +{ + NSFW_SRV_CTRL_RESUME = 1, + NSFW_SRV_CTRL_SUSPEND = 2 +} nsfw_srv_ctrl_state; + +typedef struct _nsfw_srv_ctrl_msg +{ + nsfw_srv_ctrl_state srv_state; + u16 rsp_code; +} nsfw_srv_ctrl_msg; +extern u8 nsfw_srv_ctrl_send (nsfw_srv_ctrl_state state, u8 rsp_flag); +/*#############################################*/ + +/*#################RES_MGR######################*/ +#define NSFW_RES_MGR_MODULE "nsfw_res_mgr" + +typedef enum _nsfw_res_scan_type +{ + NSFW_RES_SCAN_ARRAY = 0, + NSFW_RES_SCAN_SPOOL, + NSFW_RES_SCAN_MBUF, + NSFW_RES_SCAN_MAX +} nsfw_res_scan_type; + +typedef int (*nsfw_res_free_fun) (void *pdata); + +typedef struct _nsfw_res_scn_cfg +{ + u8 type; /*nsfw_res_scan_type */ + u8 force_free_percent; /*if the resource free percent below this vlaue, begin to force free the element */ + u16 force_free_chk_num; /*if the check count beyone this vlaue, call free fun release this element */ + u16 alloc_speed_factor; /*alloc fast with higher value */ + + u32 num_per_cyc; /*define the element number in one scan cycle process and increase chk_count of every element */ + u32 total_num; /*total number of elements */ + u32 elm_size; /*element size */ + u32 res_mem_offset; /*the nsfw_res offset from the element start */ + + void *data; /*the array addr or spool addr */ + void *mgr_ring; + + nsfw_res_free_fun free_fun; +} nsfw_res_scn_cfg; + +typedef struct _nsfw_res_mgr_item_cfg +{ + nsfw_res_scn_cfg scn_cfg; + u32 cons_head; + u32 prod_head; + u32 free_percent; + u32 last_scn_idx; + u64 force_count; +} nsfw_res_mgr_item_cfg; + +#define NSFW_MAX_RES_SCAN_COUNT 256 + +extern u8 nsfw_res_mgr_reg (nsfw_res_scn_cfg * cfg); +extern i32 nsfw_proc_start_with_lock (u8 proc_type); +/*#############################################*/ + +typedef enum _nsfw_exit_code +{ + NSFW_EXIT_SUCCESS = 0, + NSFW_EXIT_FAILED = 1, + NSFW_EXIT_DST_ERROR = 2, + NSFW_EXIT_TIME_OUT = 3, + + NSFW_EXIT_MAX_COM_ERR = 31, +} nsfw_exit_code; + +/*#############################################*/ + +/*#################SOFT_PARAM##################*/ +#define NSFW_SOFT_PARAM_MODULE "nsfw_soft_param" + +typedef struct _nsfw_soft_param_msg +{ + u32 param_name; + u32 rsp_code; + u8 param_value[NSFW_MGR_MSG_BODY_LEN - sizeof (u32) - sizeof (u32)]; +} +nsfw_soft_param_msg; + +typedef enum _nsfw_soft_param +{ + NSFW_DBG_MODE_PARAM = 1, + NSFW_HBT_TIMER = 2, + NSFW_HBT_COUNT_PARAM = 3, + NSFW_APP_EXIT_TIMER = 4, + NSFW_SRV_RESTORE_TIMER = 5, + NSFW_APP_RESEND_TIMER = 6, + NSFW_APP_SEND_PER_TIME = 7, + + NSFW_MAX_SOFT_PARAM = 1024 +} nsfw_soft_param; + +typedef int (*nsfw_set_soft_fun) (u32 param, char *buf, u32 buf_len); +extern u8 nsfw_soft_param_reg_fun (u32 param_name, nsfw_set_soft_fun fun); +extern u8 nsfw_soft_param_reg_int (u32 param_name, u32 size, u32 min, + u32 max, u64 * data); + +extern void nsfw_set_soft_para (fw_poc_type proc_type, u32 para_name, + void *value, u32 size); + +extern int nsfw_isdigitstr (const char *str); +#define NSFW_REG_SOFT_INT(_param,_data,_min, _max) nsfw_soft_param_reg_int(_param,sizeof(_data),_min,_max,(u64*)&_data) +/*#############################################*/ + +/*#################LOG_CONFIG##################*/ +#define NSFW_LOG_CFG_MODULE "nsfw_log_cfg" + +#define NSFW_MODULE_NAME_LEN 20 +#define NSFW_LOG_LEVEL_LEN 10 +#define NSFW_LOG_VALUE_LEN 256 + +typedef struct _nsfw_set_log_msg +{ + u16 rsp_code; + char module[NSFW_MODULE_NAME_LEN]; + char log_level[NSFW_LOG_VALUE_LEN]; +} nsfw_set_log_msg; +/*#############################################*/ + +/*################## DFX ######################*/ +#define MAX_DFX_QRY_RES_LEN 28 + +#define SPL_DFX_RES_ALL "all" +#define SPL_DFX_RES_QUEUE "queue" +#define SPL_DFX_RES_CONN "conn" +#define SPL_DFX_RES_L2TO4 "l2to4" +#define SPL_DFX_RES_UNMATCH "version" +#define SPL_DFX_RES_SOCKT_CB "socketcb" +#define SPL_DFX_RES_COMM_MEMPOOL "mbufpool" +#define SPL_DFX_RES_PCBLIST "pcblist" +#define SPL_DFX_RES_ARPLIST "arplist" + +typedef enum +{ + DFX_ACTION_SNAPSHOT, + DFX_ACTION_RST_STATS, + DFX_ACTION_SWITCH, + DFX_ACTION_MAX +} dfx_module_action; + +typedef struct _nsfw_dfx_qry_msg +{ + dfx_module_action action; + char resource[MAX_DFX_QRY_RES_LEN]; + char flag; //for snapshot print "all" +} nsfw_dfx_qry_msg; + +typedef enum +{ + QUERY_ACTION_GET, + QUERY_ACTION_MAX +} query_action; + +typedef struct _nsfw_qry_msg +{ + query_action action; + char resource[MAX_DFX_QRY_RES_LEN]; +} nsfw_get_qry_msg; + +/*##################DFX#########################*/ + +/*#################for tcpdump#####################*/ + +#ifndef nstack_min +#define nstack_min(a, b) (a) < (b) ? (a) : (b) +#endif + +#define GET_CUR_TIME(ptime) \ + (void)clock_gettime(CLOCK_MONOTONIC, ptime); + +#define TCPDUMP_MODULE "tcpdump_tool" + +#define DUMP_MSG_NUM (64 * 1024) +COMPAT_PROTECT (DUMP_MSG_NUM, 64 * 1024); +#define DUMP_MSG_SIZE 128 // can not be less than 14 +COMPAT_PROTECT (DUMP_MSG_SIZE, 128); + +#define DEFAULT_DUMP_TIME 600 +#define MAX_DUMP_TIME 86400 +#define MIN_DUMP_TIME 1 + +#define MAX_DUMP_TASK 16 +#define DUMP_HBT_INTERVAL 2 +#define DUMP_HBT_CHK_INTERVAL 4 +#define DUMP_TASK_HBT_TIME_OUT 30 + +#define DUMP_SHMEM_RIGN_NAME "tcpdump_ring" +#define DUMP_SHMEM_POOL_NAME "tcpdump_pool" + +enum L2_PROTOCOL +{ + PROTOCOL_IP = 0x0800, + PROTOCOL_ARP = 0x0806, + PROTOCOL_RARP = 0x8035, + PROTOCOL_OAM_LACP = 0x8809, + INVALID_L2_PROTOCOL = 0xFFFF +}; + +enum L3_PROTOCOL +{ + PROTOCOL_ICMP = 1, + PROTOCOL_TCP = 6, + PROTOCOL_UDP = 17, + INVALID_L3_PROTOCOL = 0xFF +}; + +enum DUMP_MSG_DIRECTION +{ + DUMP_SEND = 1, + DUMP_RECV = 2, + DUMP_SEND_RECV = 3 +}; + +enum DUMP_MSG_TYPE +{ + START_DUMP_REQ, + STOP_DUMP_REQ, + TOOL_COM_HBT_REQ, + + DUMP_MSG_TYPE_RSP = 0x00010000, + + START_DUMP_RSP = START_DUMP_REQ + DUMP_MSG_TYPE_RSP, + STOP_DUMP_RSP = STOP_DUMP_REQ + DUMP_MSG_TYPE_RSP, + + DUMP_MSG_TYPE_INVALID +}; + +typedef struct _nsfw_tool_hbt +{ + u32 seq; + i16 task_id; +} nsfw_tool_hbt; + +typedef struct _nsfw_tool_dump_msg +{ + u16 op_type; + i16 task_id; + u32 task_keep_time; +} nsfw_tool_dump_msg; + +typedef struct _dump_msg_info +{ + u32 len; + u16 direction; // 1:SEND, 2:RECV + u32 dump_sec; + u32 dump_usec; + nsfw_res res_chk; + char buf[1]; +} dump_msg_info; + +typedef struct _dump_timer_info +{ + u32 seq; + i16 task_id; + void *interval; + void *ptimer; +} dump_timer_info; + +extern void ntcpdump_loop (void *buf, u32 buf_len, u16 direction, + void *eth_addr); +extern void ntcpdump (void *buf, u32 buf_len, u16 direction); + +/*##############for tcpdump######################*/ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_MEM_STAT_API_H */ diff --git a/src/framework/include/nsfw_mem_api.h b/src/framework/include/nsfw_mem_api.h new file mode 100644 index 0000000..ec78692 --- /dev/null +++ b/src/framework/include/nsfw_mem_api.h @@ -0,0 +1,546 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_MEM_API_H +#define _NSFW_MEM_API_H +#include <stdint.h> +#include <sys/types.h> + +#include "types.h" +#include "nsfw_mgr_com_api.h" +#include "nstack_log.h" + +#define NSFW_MEM_MGR_MODULE "nsfw_mem_mgr" + +/* + *the max len of memory name is 32bytes, but app just can use max 22bytes, left 10bytes to memory manager module + */ +#define NSFW_MEM_NAME_LENTH (32) +#define NSFW_MEM_APPNAME_LENTH (22) + +#define NSFW_SOCKET_ANY (-1) +#define NSFW_MEM_OK (0) +#define NSFW_MEM_ERR (-1) + +/* + *type of memory: + *NSFW_SHMEM:shared memory + *NSFW_NSHMEM:allocated by calling malloc + */ +typedef enum +{ + NSFW_SHMEM, + NSFW_NSHMEM, + NSFW_MEM_TYPEMAX, +} nsfw_mem_type; + +/*type of ring operation*/ +typedef enum +{ + NSFW_MRING_SPSC, /*sigle producer sigle consumer ring */ + NSFW_MRING_MPSC, /*multi producer sigle consumer ring */ + NSFW_MRING_SPMC, /*sigle producer multi consumer ring */ + NSFW_MRING_MPMC, /*multi producer multi consumer ring */ + NSFW_MRING_SPSC_ST, /*single producer single consumer and belong to one thread ring */ + NSFW_MPOOL_TYPEMAX, +} nsfw_mpool_type; + +typedef void *mpool_handle; +typedef void *mzone_handle; +typedef void *mbuf_handle; +typedef void *mring_handle; + +/*initial of param*/ +typedef struct +{ + i32 iargsnum; + i8 **pargs; + fw_poc_type enflag; /*app, nStackMain, Master */ +} nsfw_mem_para; + +typedef struct +{ + nsfw_mem_type entype; + fw_poc_type enowner; /*notes: 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, + * end with null created by nStackMaster, and end with _<pid> created by other. + * 2. pname->enowner is available only when call look up shared memory. + * 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, + * the name must be full name. + * for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, + * must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add + * _(pid) at the end of name, nstack_123. + */ + i8 aname[NSFW_MEM_NAME_LENTH]; /*the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. */ +} nsfw_mem_name; + +typedef struct +{ + nsfw_mem_name stname; + size_t lenth; + i32 isocket_id; + i32 ireserv; +} nsfw_mem_zone; + +typedef struct +{ + nsfw_mem_name stname; + unsigned usnum; /*the really created mbfpool num is (num+1) power of 2 */ + unsigned uscash_size; + unsigned uspriv_size; + unsigned usdata_room; + i32 isocket_id; + nsfw_mpool_type enmptype; +} nsfw_mem_mbfpool; + +typedef struct +{ + nsfw_mem_name stname; + u32 usnum; /*the really created sppool num is (num+1) power of 2 */ + u32 useltsize; + i32 isocket_id; + nsfw_mpool_type enmptype; +} nsfw_mem_sppool; + +typedef struct +{ + nsfw_mem_name stname; + u32 usnum; /*the really created ring num is (num+1) power of 2 */ + i32 isocket_id; + nsfw_mpool_type enmptype; +} nsfw_mem_mring; + +typedef enum +{ + NSFW_MEM_ALLOC_SUCC = 1, + NSFW_MEM_ALLOC_FAIL = 2, +} nsfw_mem_alloc_state; + +typedef enum +{ + NSFW_MEM_MZONE, + NSFW_MEM_MBUF, + NSFW_MEM_SPOOL, + NSFW_MEM_RING +} nsfw_mem_struct_type; + +typedef enum +{ + NSFW_RESERV_REQ_MSG, + NSFW_RESERV_ACK_MSG, + NSFW_MBUF_REQ_MSG, + NSFW_MBUF_ACK_MSG, + NSFW_SPPOOL_REQ_MSG, + NSFW_SPPOOL_ACK_MSG, + NSFW_RING_REQ_MSG, + NSFW_RING_ACK_MSG, + NSFW_RELEASE_REQ_MSG, + NSFW_RELEASE_ACK_MSG, + NSFW_MEM_LOOKUP_REQ_MSG, + NSFW_MEM_LOOKUP_ACK_MSG, + NSFW_MEM_MAX_MSG +} nsfw_remote_msg; + +typedef struct __nsfw_shmem_msg_head +{ + unsigned usmsg_type; + unsigned uslenth; + i32 aidata[0]; +} nsfw_shmem_msg_head; + +typedef struct __nsfw_shmem_ack +{ + void *pbase_addr; + u16 usseq; + i8 cstate; + i8 creserv; + i32 ireserv; +} nsfw_shmem_ack; + +typedef struct __nsfw_shmem_reserv_req +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + u16 usseq; + u16 usreserv; + i32 isocket_id; + size_t lenth; + i32 ireserv; +} nsfw_shmem_reserv_req; + +typedef struct __nsfw_shmem_mbuf_req +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + u16 usseq; + u16 enmptype; + unsigned usnum; + unsigned uscash_size; + unsigned uspriv_size; + unsigned usdata_room; + i32 isocket_id; + i32 ireserv; +} nsfw_shmem_mbuf_req; + +typedef struct __nsfw_shmem_sppool_req +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + u16 usseq; + u16 enmptype; + u32 usnum; + u32 useltsize; + i32 isocket_id; + i32 ireserv; +} nsfw_shmem_sppool_req; + +typedef struct __nsfw_shmem_ring_req +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + u16 usseq; + u16 enmptype; + u32 usnum; + i32 isocket_id; + i32 ireserv; +} nsfw_shmem_ring_req; + +typedef struct __nsfw_shmem_free_req +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + u16 usseq; + u16 ustype; /*structure of memory(memzone,mbuf,mpool,ring) */ + i32 ireserv; +} nsfw_shmem_free_req; + +typedef struct __nsfw_shmem_lookup_req +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + u16 usseq; + u16 ustype; /*structure of memory(memzone,mbuf,mpool,ring) */ + i32 ireserv; +} nsfw_shmem_lookup_req; + +typedef int (*nsfw_mem_ring_enqueue_fun) (mring_handle ring, void *box); +typedef int (*nsfw_mem_ring_dequeue_fun) (mring_handle ring, void **box); +typedef int (*nsfw_mem_ring_dequeuev_fun) (mring_handle ring, void **box, + unsigned int n); + +typedef struct +{ + nsfw_mem_ring_enqueue_fun ring_ops_enqueue; + nsfw_mem_ring_dequeue_fun ring_ops_dequeue; + nsfw_mem_ring_dequeuev_fun ring_ops_dequeuev; +} nsfw_ring_ops; + +/* + * memory module init + * para:point to nstak_fwmem_para + */ +i32 nsfw_mem_init (void *para); + +/* + * create a block memory with name + * nsfw_mem_zone::stname + * nsfw_mem_zone::isize + * note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +mzone_handle nsfw_mem_zone_create (nsfw_mem_zone * pinfo); + +/* + *create some memory blocks + * note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +i32 nsfw_mem_zone_createv (nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num); + +/* + *look up a memory + * note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + * 2. if the memory is shared, pname->enowner indicate that who create this memory, + * note: + * 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, + * end with none created by nStackMaster, and end with _<pid> created by other. + * 2. pname->enowner is available only when call look up shared memory. + * 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, + * the name must be full name. + * for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, + * must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add + * _(pid) at the end of name, nstack_123. + */ +mzone_handle nsfw_mem_zone_lookup (nsfw_mem_name * pname); + +/*release a memory*/ +i32 nsfw_mem_zone_release (nsfw_mem_name * pname); + +/* + *create a mbuf pool + */ +mpool_handle nsfw_mem_mbfmp_create (nsfw_mem_mbfpool * pbufinfo); + +/* + *create some mbuf pools + * note: 1. the name of lenth must be less than NSFW_MEM_APPNAME_LENTH. + */ +i32 nsfw_mem_mbfmp_createv (nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num); + +/* + *alloc a mbuf from mbuf pool + */ +mbuf_handle nsfw_mem_mbf_alloc (mpool_handle mhandle, nsfw_mem_type entype); + +/* + *put a mbuf backintp mbuf pool + */ +i32 nsfw_mem_mbf_free (mbuf_handle mhandle, nsfw_mem_type entype); + +/* + *look up mbuf mpool + * note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + * 2. if the memory is shared, pname->enowner indicate that who create this memory. + * note: + * 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, + * end with none created by nStackMaster, and end with _<pid> created by other. + * 2. pname->enowner is available only when call look up shared memory. + * 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, + * the name must be full name. + * for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, + * must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add + * _(pid) at the end of name, nstack_123. + */ +mpool_handle nsfw_mem_mbfmp_lookup (nsfw_mem_name * pmbfname); + +/* + *release mbuf pool + * note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +i32 nsfw_mem_mbfmp_release (nsfw_mem_name * pname); + +/* + *create a simple pool + *note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +mring_handle nsfw_mem_sp_create (nsfw_mem_sppool * pmpinfo); + +/* + *create some simple pools one time + *note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +i32 nsfw_mem_sp_createv (nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num); + +/* + *create a simple pool with many rings + *note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +i32 nsfw_mem_sp_ring_create (nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, i32 iringnum); + +/* + *release a simple mempool + *note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +i32 nsfw_mem_sp_release (nsfw_mem_name * pname); + +/* + *look up a simpile ring + * note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + * 2. if the memory is shared, pname->enowner indicate that who create this memory, + * note: + * 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, + * end with none created by nStackMaster, and end with _<pid> created by other. + * 2. pname->enowner is available only when call look up shared memory. + * 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, + * the name must be full name. + * for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, + * must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add + * _(pid) at the end of name, nstack_123. + */ +mring_handle nsfw_mem_sp_lookup (nsfw_mem_name * pname); + +/* + *create a ring + *note: 1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + * 2. shared memory ring (NSFW_SHMEM) just can put a pointor into the queue, the queue also point to a shared block memory. + * no shared memory ring(NSFW_NSHMEM) is other wise. + */ +mring_handle nsfw_mem_ring_create (nsfw_mem_mring * pringinfo); + +/* + *look up a ring by name + * note:1. the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + * 2. if the memory is shared, pname->enowner indicate that who create this memory, + * note: + * 1. when calling any shared memory create inferface, the name of memory end with _0 created by nStackMain, + * end with none created by nStackMaster, and end with _<pid> created by other. + * 2. pname->enowner is available only when call look up shared memory. + * 3. if the roles of process is NSFW_PROC_MASTER but the memory was created by others, or pname->enowner is NSFW_PROC_NULL, + * the name must be full name. + * for examles if the memory was created by nStackMain and pname->enowner is NSFW_PROC_NULL, + * must add '_0' at the end of name, if the memory was created by app and the role of process is NSFW_PROC_MASTER, must add + * _(pid) at the end of name, nstack_123. + */ +mring_handle nsfw_mem_ring_lookup (nsfw_mem_name * pname); + +/* + * reset the number of producer and consumer, also, the state of ring reset to empty + * notes: must be called before doing any operations base on the ring + */ +void nsfw_mem_ring_reset (mring_handle mhandle, nsfw_mpool_type entype); + +extern nsfw_ring_ops g_ring_ops_arry[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX]; + +/***************************************************************************** +* Prototype : nsfw_mem_ring_dequeue +* Description : get a member from a ring +* note : if NSFW_SHMEM ring, pdata returned alread a local address +* Input : mring_handle mhandle +* void** pdata +* Output : None +* Return Value : the num of elment get from the queue, =0: get null, <0: err happen, >0: return num. +* Calls : +* Called By : +* +*****************************************************************************/ +static inline i32 +nsfw_mem_ring_dequeue (mring_handle mhandle, void **pdata) +{ + if (NULL == mhandle || *((u8 *) mhandle) >= NSFW_MEM_TYPEMAX + || *((u8 *) mhandle + 1) >= NSFW_MPOOL_TYPEMAX) + { + NSCOMM_LOGERR ("input para error] mhandle=%p", mhandle); + return -1; + } + + return + g_ring_ops_arry[*((u8 *) mhandle)][*((u8 *) mhandle + 1)].ring_ops_dequeue + (mhandle, pdata); +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_dequeuev +* Description : get some members from a ring +* note : if NSFW_SHMEM ring, pdata returned alread a local address +* Input : mring_handle mhandle +* void** pdata +* unsigned inum +* Output : None +* Return Value : the num of elment get from the queue, =0: get null, <0: err happen, >0: return num. +* Calls : +* Called By : +* +*****************************************************************************/ +static inline i32 +nsfw_mem_ring_dequeuev (mring_handle mhandle, void **pdata, unsigned int inum) +{ + if (NULL == mhandle || *((u8 *) mhandle) >= NSFW_MEM_TYPEMAX + || *((u8 *) mhandle + 1) >= NSFW_MPOOL_TYPEMAX) + { + NSCOMM_LOGERR ("input para error] mhandle=%p", mhandle); + return -1; + } + + return + g_ring_ops_arry[*((u8 *) mhandle)][* + ((u8 *) mhandle + + 1)].ring_ops_dequeuev (mhandle, pdata, + inum); +} + +/***************************************************************************** +* Prototype : nsfw_mem_ring_enqueue +* Description : put a member back into a ring +* note : pdata must point to a shared block memory when put into the NSFW_SHMEM type memory ring, and the +* value of pdata must be local address +* Input : mring_handle mhandle +* void* pdata +* Output : None +* Return Value : the num of elment put into the queue, =0: put null, <0: err happen, >0: return num. +* Calls : +* Called By : +* +*****************************************************************************/ +static inline i32 +nsfw_mem_ring_enqueue (mring_handle mhandle, void *pdata) +{ + if (NULL == mhandle || *((u8 *) mhandle) >= NSFW_MEM_TYPEMAX + || *((u8 *) mhandle + 1) >= NSFW_MPOOL_TYPEMAX) + { + NSCOMM_LOGERR ("input para error] mhandle=%p", mhandle); + return -1; + } + + return + g_ring_ops_arry[*((u8 *) mhandle)][*((u8 *) mhandle + 1)].ring_ops_enqueue + (mhandle, pdata); +} + +/* + *get the free number of ring + */ +u32 nsfw_mem_ring_free_count (mring_handle mhandle); + +/* + *get the in using number of ring + */ +u32 nsfw_mem_ring_using_count (mring_handle mhandle); + +/* + *get size of ring + */ +u32 nsfw_mem_ring_size (mring_handle mhandle); + +/* + *release a ring memory + *note: the lenth of name must be less than NSFW_MEM_APPNAME_LENTH. + */ +i32 nsfw_mem_ring_release (nsfw_mem_name * pname); + +/* + *statics mbufpool, sppool, ring mem size + *return: <=0, err happen, >0 mem size + * NSFW_MEM_MZONE: not surport because you already know the lenth when create + */ +ssize_t nsfw_mem_get_len (void *handle, nsfw_mem_struct_type type); + +/* + *recycle mbuf + * + */ +i32 nsfw_mem_mbuf_pool_recycle (mpool_handle handle); + +typedef int (*nsfw_mem_item_fun) (void *data, void *argv); + +i32 nsfw_mem_sp_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); +i32 nsfw_mem_mbuf_iterator (mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); + +/***************************************************************************** +* Prototype : nsfw_mem_dfx_ring_print +* Description : print ring info +* Input : mring_handle mhandle +* char *pbuf +* int lenth +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_mem_dfx_ring_print (mring_handle mhandle, char *pbuf, int lenth); + +#ifdef SYS_MEM_RES_STAT +u32 nsfw_mem_mbfpool_free_count (mpool_handle mhandle); +#endif + +#endif diff --git a/src/framework/include/nsfw_mgr_com_api.h b/src/framework/include/nsfw_mgr_com_api.h new file mode 100644 index 0000000..2499fee --- /dev/null +++ b/src/framework/include/nsfw_mgr_com_api.h @@ -0,0 +1,198 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ +#ifndef _NSFW_MGRCOM_API_H +#define _NSFW_MGRCOM_API_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_MGR_COM_MODULE "nsfw_mgr_com" + +#define MRG_RSP(_req_msg) (_req_msg + MGR_MSG_RSP_BASE) + +typedef enum _mgr_msg_type +{ + MGR_MSG_NULL = 0, + /*#############common msg type################# */ + MGR_MSG_CHK_INIT_REQ = 1, + MGR_MSG_INIT_NTY_REQ, + MGR_MSG_CHK_HBT_REQ, + MGR_MSG_APP_EXIT_REQ, + MGR_MSG_SRV_CTL_REQ, + MGR_MSG_VER_MGR_REQ, + MGR_MSG_SOF_PAR_REQ, + + /*############################################# */ + MGR_MSG_MEM_ALLOC_REQ = 64, /* memory msg type */ + + /*############################################# */ + MGR_MSG_DFX_QRY_REQ = 96, /* nStackCtrl maitain msg */ + MGR_MSG_SET_LOG_REQ, + + /*############################################# */ + MGR_MSG_RCC_END_REQ = 128, /* service msg type */ + + /*############################################# */ + MGR_MSG_TOOL_TCPDUMP_REQ = 256, /* for tools */ + MGR_MSG_TOOL_HEART_BEAT, + + /*###query message with large rsp message begin## */ + MGR_MSG_LARGE_QRY_REQ_BEGIN = 384, + MGR_MSG_LARGE_STA_QRY_REQ = MGR_MSG_LARGE_QRY_REQ_BEGIN, + MGR_MSG_LARGE_MT_QRY_REQ, /* nStackCtrl maitain msg */ + + /*############################################# */ + MGR_MSG_LARGE_ALARM_REQ = 500, /* alarm msg type */ + + MGR_MSG_RSP_BASE = 512, + /*#############common msg type################# */ + MGR_MSG_CHK_INIT_RSP = MRG_RSP (MGR_MSG_CHK_INIT_REQ), + MGR_MSG_INIT_NTY_RSP = MRG_RSP (MGR_MSG_INIT_NTY_REQ), + MGR_MSG_CHK_HBT_RSP = MRG_RSP (MGR_MSG_CHK_HBT_REQ), + MGR_MSG_APP_EXIT_RSP = MRG_RSP (MGR_MSG_APP_EXIT_REQ), + MGR_MSG_SRV_CTL_RSP = MRG_RSP (MGR_MSG_SRV_CTL_REQ), + MGR_MSG_VER_MGR_RSP = MRG_RSP (MGR_MSG_VER_MGR_REQ), + MGR_MSG_SOF_PAR_RSP = MRG_RSP (MGR_MSG_SOF_PAR_REQ), + /*############################################# */ + + MGR_MSG_MEM_ALLOC_RSP = MRG_RSP (MGR_MSG_MEM_ALLOC_REQ), + + MGR_MSG_DFX_QRY_RSP = MRG_RSP (MGR_MSG_DFX_QRY_REQ), + + MGR_MSG_SET_LOG_RSP = MRG_RSP (MGR_MSG_SET_LOG_REQ), + + MGR_MSG_RCC_END_RSP = MRG_RSP (MGR_MSG_RCC_END_REQ), + + /*############################################# */ + MGR_MSG_TOOL_TCPDUMP_RSP = MRG_RSP (MGR_MSG_TOOL_TCPDUMP_REQ), + MGR_MSG_TOOL_HEART_BEAT_RSP = MRG_RSP (MGR_MSG_TOOL_HEART_BEAT), + + /*##############LARGE RSP MESSAGE################## */ + MGR_MSG_LAG_QRY_RSP_BEGIN = MRG_RSP (MGR_MSG_LARGE_QRY_REQ_BEGIN), + MGR_MSG_LAG_STA_QRY_RSP = MRG_RSP (MGR_MSG_LARGE_STA_QRY_REQ), + MGR_MSG_LAG_MT_QRY_RSP = MRG_RSP (MGR_MSG_LARGE_MT_QRY_REQ), + MGR_MSG_LARGE_ALARM_RSP = MRG_RSP (MGR_MSG_LARGE_ALARM_REQ), + MGR_MSG_MAX = 1024 +} mgr_msg_type; + +typedef enum _fw_poc_type +{ + NSFW_PROC_NULL = 0, + NSFW_PROC_MAIN, + NSFW_PROC_MASTER, + NSFW_PROC_APP, + NSFW_PROC_CTRL, + NSFW_PROC_TOOLS, + NSFW_PROC_ALARM, + NSFW_PROC_MAX = 16 +} fw_poc_type; + +#define NSFW_DOMAIN_DIR "/var/run" +#define NSTACK_MAX_PROC_NAME_LEN 20 + +typedef enum _nsfw_mgr_msg_rsp_code +{ + NSFW_MGR_SUCESS, + NSFW_MGR_MSG_TYPE_ERROR, +} mgr_msg_rsp_code; + +extern char *nsfw_get_proc_name (u8 proc_type); + +#define GET_USER_MSG(_stu, _msg) ((_stu *)(&(_msg)->msg_body[0])) + +/*for log print*/ +#define MSGINFO "msg=%p,len=%d,t=%d,sq=%d,st=%d,sp=%d,dt=%d,dp=%d" +#define PRTMSG(msg) (msg), (msg)->msg_len,(msg)->msg_type,(msg)->seq, (msg)->src_proc_type,(msg)->src_pid,(msg)->dst_proc_type,(msg)->dst_pid + +#define NSFW_MGR_MSG_LEN 512 +#define NSFW_MGR_MSG_HDR_LEN 32 +#define NSFW_MGR_MSG_BODY_LEN (NSFW_MGR_MSG_LEN - NSFW_MGR_MSG_HDR_LEN) + +#define NSFW_MGR_LARGE_MSG_LEN (256*1024) +#define NSFW_MGR_LARGE_MSG_BODY_LEN (NSFW_MGR_LARGE_MSG_LEN - NSFW_MGR_MSG_HDR_LEN) + +typedef struct _nsfw_mgr_msg +{ + u16 msg_type; /* mgr_msg_type */ + u16 u16Reserve; + u32 msg_len; + + u8 alloc_flag:1; + u8 fw_flag:1; + u8 from_mem:1; + u8 more_msg_flag:1; + u8 reserve_flag:4; + u8 resp_code; + u8 src_proc_type; /* fw_poc_type */ + u8 dst_proc_type; + i32 seq; + + u32 src_pid; + u32 dst_pid; + + u64 traceid; + + u8 msg_body[NSFW_MGR_MSG_BODY_LEN]; +} nsfw_mgr_msg; + +extern nsfw_mgr_msg *nsfw_mgr_msg_alloc (u16 msg_type, u8 dst_proc_type); +extern void nsfw_mgr_msg_free (nsfw_mgr_msg * msg); + +/* for rsp msg alloc*/ +extern nsfw_mgr_msg *nsfw_mgr_null_rspmsg_alloc (); +extern nsfw_mgr_msg *nsfw_mgr_rsp_msg_alloc (nsfw_mgr_msg * req_msg); + +/* for msg proc fun reg*/ +typedef int (*nsfw_mgr_msg_fun) (nsfw_mgr_msg * msg); +extern u8 nsfw_mgr_reg_msg_fun (u16 msg_type, nsfw_mgr_msg_fun fun); + +extern u8 nsfw_mgr_send_msg (nsfw_mgr_msg * msg); +extern u8 nsfw_mgr_send_req_wait_rsp (nsfw_mgr_msg * req_msg, + nsfw_mgr_msg * rsp_msg); + +/* for fork clear parent resource*/ +extern void nsfw_mgr_close_dst_proc (u8 proc_type, u32 dst_pid); +extern u8 nsfw_mgr_clr_fd_lock (); + +/* for epoll thread reg other sock proc fun*/ +typedef int (*nsfw_mgr_sock_fun) (i32 epfd, i32 socket, u32 events); +extern u8 nsfw_mgr_reg_sock_fun (i32 socket, nsfw_mgr_sock_fun fun); +extern void nsfw_mgr_unreg_sock_fun (i32 socket); +extern int nsfw_mgr_com_socket_error (i32 fd, nsfw_mgr_sock_fun fun, + i32 timer); +extern u8 nsfw_mgr_ep_start (); +extern int nsfw_mgr_com_module_init (void *param); +extern int nsfw_mgr_run_script (const char *cmd, char *result, + int result_buf_len); + +extern int nsfw_mgr_com_chk_hbt (int v_add); +extern i32 nsfw_set_close_on_exec (i32 sock); +extern int nsfw_mgr_comm_fd_init (u32 proc_type); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_MGRCOM_API_H */ diff --git a/src/framework/include/nsfw_ps_api.h b/src/framework/include/nsfw_ps_api.h new file mode 100644 index 0000000..69fa992 --- /dev/null +++ b/src/framework/include/nsfw_ps_api.h @@ -0,0 +1,134 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_PS_API_H +#define _NSFW_PS_API_H + +#include "list.h" +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_PS_MODULE "nsfw_ps" + +#define NSFW_PS_MAX_CALLBACK 16 + +#define NSFW_MAX_HBT_CHK_COUNT_DEF 60 + +typedef enum _nsfw_ps_state +{ + NSFW_PS_NULL = 0, + NSFW_PS_START, + NSFW_PS_RUNNING, + NSFW_PS_PARENT_FORK, + NSFW_PS_CHILD_FORK, + NSFW_PS_HBT_FAILED, + NSFW_PS_EXITING, + NSFW_PS_EXIT, + NSFW_PS_MAX +} nsfw_ps_state; + +/* for state change call back proc*/ +typedef int (*nsfw_ps_proc_fun) (void *pps_info, void *argv); +typedef struct _nsfw_ps_callback +{ + u8 state; + nsfw_ps_proc_fun fun; + void *argv; +} nsfw_ps_callback; + +/* for value in ps_info get/set*/ +typedef enum _nsfw_ps_user_value +{ + NSFW_REC_IDX = 1, + NSFW_REC_TIMER = 2, + NSFW_PS_UV_MAX = 16 +} nsfw_ps_user_value; +#define nsfw_ps_set_uv(_pps_info, _type, _value) (_pps_info)->value[(_type)] = (_value) +#define nsfw_ps_get_uv(_pps_info, _type) ((_pps_info)->value[(_type)]) + +typedef struct _nsfw_ps_info +{ + struct list_head node; + u8 alloc_flag; + u8 state; /*nsfw_ps_state */ + u8 proc_type; /*fw_poc_type */ + u8 rechk_flg; + u32 host_pid; + u32 parent_pid; /* only use for fork */ + u32 cur_child_pid; /* only use for fork */ + void *exit_timer_ptr; + void *resend_timer_ptr; + void *hbt_timer_ptr; + u32 hbt_failed_count; + nsfw_ps_callback callback[NSFW_PS_MAX_CALLBACK]; + void *value[NSFW_PS_UV_MAX]; +} nsfw_ps_info; + +typedef struct _nsfw_thread_dogs +{ + u8 alloc_flag; + i32 count; + u32 thread_id; +} nsfw_thread_dogs; + +extern nsfw_ps_info *nsfw_ps_info_alloc (u32 pid, u8 proc_type); +extern nsfw_ps_info *nsfw_ps_info_get (u32 pid); +extern void nsfw_ps_info_free (nsfw_ps_info * ps_info); + +extern u8 nsfw_ps_reg_fun (nsfw_ps_info * pps_info, u8 ps_state, + nsfw_ps_proc_fun fun, void *argv); + +/* will auto reg after ps_info alloc*/ +extern u8 nsfw_ps_reg_global_fun (u8 proc_type, u8 ps_state, + nsfw_ps_proc_fun fun, void *argv); + +typedef struct _nsfw_ps_info_msg +{ + u32 host_pid; + u32 parent_pid; + u64 reserve; +} nsfw_ps_info_msg; +extern u8 nsfw_ps_exit_end_notify (u32 pid); + +/*for heartbeat check*/ +extern u8 nsfw_ps_check_dst_init (u8 dst_proc_type); +extern u8 nsfw_thread_chk (); +extern nsfw_thread_dogs *nsfw_thread_getDog (); +extern u8 nsfw_thread_chk_unreg (); +extern u8 nsfw_ps_hbt_start (nsfw_ps_info * ps_info); +extern u8 nsfw_ps_hbt_stop (nsfw_ps_info * ps_info); + +extern u32 nsfw_ps_iterator (nsfw_ps_proc_fun fun, void *argv); + +#define MAX_THREAD 16 +extern pthread_t g_all_thread[]; +extern u8 nsfw_reg_trace_thread (pthread_t tid); + +typedef int (*nsfw_ps_pid_fun) (u32 pid, u8 proc_type, void *argv); +extern int nsfw_ps_rechk_pid_exit (nsfw_ps_pid_fun fun, void *argv); +extern nsfw_ps_info *nsfw_share_ps_info_get (u32 pid); +extern void nsfw_ps_cfg_set_chk_count (u16 count); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_PS_API_H */ diff --git a/src/framework/include/nsfw_ps_mem_api.h b/src/framework/include/nsfw_ps_mem_api.h new file mode 100644 index 0000000..01f9cd3 --- /dev/null +++ b/src/framework/include/nsfw_ps_mem_api.h @@ -0,0 +1,36 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_PS_MEM_API_H +#define _NSFW_PS_MEM_API_H + +#include "nsfw_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_PS_MEM_MODULE "nsfw_ps_mem" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_PS_MEM_API_H */ diff --git a/src/framework/include/nsfw_recycle_api.h b/src/framework/include/nsfw_recycle_api.h new file mode 100644 index 0000000..fd2bd8f --- /dev/null +++ b/src/framework/include/nsfw_recycle_api.h @@ -0,0 +1,92 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RECYCLE_API_H +#define _NSFW_RECYCLE_API_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_RECYCLE_MODULE "nsfw_recycle" + +typedef enum _nsfw_recycle_item_type +{ + NSFW_REC_TYPE_NULL = 0, + NSFW_REC_SBR_START = 1, + NSFW_REC_SBR_SOCKET, + NSFW_REC_SBR_END = NSFW_REC_SBR_START + 63, + NSFW_REC_NSOCKET_START, + NSFW_REC_NSOCKET_EPOLL, + NSFW_REC_NSOCKET_END = NSFW_REC_NSOCKET_START + 63, + NSFW_REC_TYPE_MAX = 512 +} nsfw_recycle_item_type; + +typedef enum _nsfw_recycle_priority +{ + NSFW_REC_PRO_HIGHTEST = 0, + NSFW_REC_PRO_NORMAL = 1, + NSFW_REC_PRO_DEFALUT = 2, + NSFW_REC_PRO_LOWEST = 3, + NSFW_REC_PRO_MAX = 4 +} nsfw_recycle_priority; + +typedef enum _nsfw_rcc_stat +{ + NSFW_RCC_CONTINUE = 0, + NSFW_RCC_SUSPEND = 1, + NSFW_RCC_FAILED = 2, +} nsfw_rcc_stat; + +/*work on nStackMain*/ +typedef nsfw_rcc_stat (*nsfw_recycle_fun) (u32 exit_pid, void *pdata, + u16 rec_type); +extern u8 nsfw_recycle_reg_fun (u16 obj_type, nsfw_recycle_fun fun); +extern u8 nsfw_recycle_obj_end (u32 pid); +extern u8 nsfw_recycle_lock_rel_fun (nsfw_recycle_fun fun, void *data, + u8 proc_type); +extern int nsfw_recycle_exit_pid_lock (u32 pid, u8 proc_type, void *argv); + +#define REGIST_RECYCLE_OBJ_FUN(_obj_type, _fun) \ + NSTACK_STATIC void regist_ ## _obj_type ## _fun (void) \ + __attribute__((__constructor__)); \ + NSTACK_STATIC void regist_ ## _obj_type ## _fun (void) \ + { \ + (void)nsfw_recycle_reg_fun(_obj_type, _fun); \ + } + +#define REGIST_RECYCLE_LOCK_REL(_fun, _data, _proc) \ + NSTACK_STATIC void regist_lock ## _fun (void) \ + __attribute__((__constructor__)); \ + NSTACK_STATIC void regist_lock ## _fun (void) \ + { \ + (void)nsfw_recycle_lock_rel_fun(_fun, _data,_proc); \ + } + +/*work on nStackApp*/ +extern void *nsfw_recycle_reg_obj (u8 priority, u16 rec_type, void *data); +extern u8 nsfw_recycle_fork_init (); +extern int nsfw_recycle_rechk_lock (); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_RECYCLE_API_H */ diff --git a/src/framework/include/nsfw_snapshot.h b/src/framework/include/nsfw_snapshot.h new file mode 100644 index 0000000..8958c64 --- /dev/null +++ b/src/framework/include/nsfw_snapshot.h @@ -0,0 +1,144 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _FW_SNAPSHOT_H +#define _FW_SNAPSHOT_H + +#include <stdlib.h> +#include "types.h" +#include "../snapshot/fw_ss_tlv.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +// object type(7 bits) | member type (7 bits) | is object(1 bit) | is array(1 bit) +// member type is the type in object structure , it only effects the own object +/** + * type - object , type object of array, type base item + */ + +#define NSFW_SS_TYPE_OBJ(_objType) (0xfe00 & ((_objType) << 9)) +#define NSFW_SS_TYPE_GETOBJ(_objType) ((0xfe00 & (_objType)) >> 9) + +#define NSFW_SS_TYPE_MEMBER(_memType) (0x01fc & ((_memType) << 2)) +#define NSFW_SS_TYPE_GET_MEMBER(_memType) ((0x01fc & (_memType)) >> 2) + +#define NSFW_SS_TYPE_SET_MEMBER_ITEM(_memType) (NSFW_SS_TYPE_MEMBER((_memType))) +#define NSFW_SS_TYPE_SET_MEMBER_OBJ(_objType, _memType) \ + (NSFW_SS_TYPE_OBJ((_objType)) | NSFW_SS_TYPE_SET_MEMBER_ITEM((_memType)) | 0x02) +#define NSFW_SS_TYPE_SET_MEMBER_OBJ_ARRAY(_objType, _memType) \ + (NSFW_SS_TYPE_SET_MEMBER_OBJ((_objType), (_memType)) | 0x01) + +#define NSFW_SS_TYPE_IS_MEMBER_OBJ(_memType) ((_memType) & 0x02) +#define NSFW_SS_TYPE_IS_MEMBER_ARRAY(_memType) ((_memType) & 0x01) + +/* + * This structure tells how to describe one object and its members + */ +typedef struct _nsfw_ss_objMemDesc +{ + u16 type; // object type(7 bits) | member type (7 bits) | is object(1 bit) | is array(1 bit) + u32 length; + u8 offset; +} nsfw_ss_objMemDesc_t; + +typedef struct _nsfw_ss_objDesc +{ + u16 objType; /* Type number of object */ + u8 memNum; /* Nubmer of object members */ + u32 objSize; + nsfw_ss_objMemDesc_t *memDesc; /* Member descripe */ +} nsfw_ss_objDesc_t; + +#define NSFW_SS_MAX_OBJDESC_NUM 256 + +/* Traversal, you can save the current value to start the search, do not need to start from the beginning of the search, because the value is generally a sequential */ + +typedef struct _nsfw_ss_objDescManager +{ + nsfw_ss_objDesc_t *g_nsfw_ss_objDescs[NSFW_SS_MAX_OBJDESC_NUM]; + int g_nsfw_ss_objDesNum; +} nsfw_ss_objDescManager_t; + +extern nsfw_ss_objDescManager_t g_nsfw_ss_objDescManager; + +#define nsfw_ss_getObjDescManagerInst() (&g_nsfw_ss_objDescManager) + +/** + * @Function nsfw_ss_registe_ObjDesc + * @Description Registe object description to snapshot + * @param objDesc - description of object + * @return void + */ +extern void nsfw_ss_register_ObjDesc (nsfw_ss_objDesc_t * objDesc); + +/** + * @Function nsfw_ss_store + * @Description store object to memory + * @param (in) objType - type of object + * @param (in) obj - adderss of object memory + * @param (in) storeMem - address of memory to store object data + * @param (in) storeMemLen - maximal length of storage memory + * @return positive integer means length of memory cost on success. return -1 if error + */ +extern int nsfw_ss_store (u16 objType, void *obj, void *storeMem, + u32 storeMemLen); + +/** + * @Function nsfw_ss_restore + * @Description restore object from memory + * @param (in) objMem - memory of object + * @param (in) mem - memory of storage + * @param (in) storeMemLen - maximal length of storage memory + * @return positive integer stands on object type, -1 on error + */ +extern int nsfw_ss_restore (void *objMem, void *mem, u32 storeMemLen); + +/** + * @Function nsfw_ss_getObjStoreMemLen + * @Description Get the maximal memory it needs + * @param (in) objType - type of object + * @return length of memory needs, -1 if error + */ +extern int nsfw_ss_getObjStoreMemLen (int objType); + +#define _NSFW_SNAPSHOT_OBJDESC_REGISTER_SURFIX(_value, _surfix) \ + static __attribute__((__constructor__(121))) void nsfw_snapshot_objdesc_register_constructor##_surfix(void){\ + nsfw_ss_register_ObjDesc((_value));\ + } + +#define NSFW_SNAPSHOT_OBJDESC_REGISTER_SURFIX(_value, _surfix) \ + _NSFW_SNAPSHOT_OBJDESC_REGISTER_SURFIX(_value, _surfix) + +#define NSFW_SNAPSHOT_OBJDESC_REGISTER_UNIQUE(_value) \ + NSFW_SNAPSHOT_OBJDESC_REGISTER_SURFIX(_value, __LINE__) + +/** + * Using this marcro to register object description + */ +#define NSFW_SS_REGSITER_OBJDESC(_value) \ + NSFW_SNAPSHOT_OBJDESC_REGISTER_UNIQUE(_value) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _FW_SNAPSHOT_H */ diff --git a/src/framework/include/nsfw_upgrade.h b/src/framework/include/nsfw_upgrade.h new file mode 100644 index 0000000..a4e809c --- /dev/null +++ b/src/framework/include/nsfw_upgrade.h @@ -0,0 +1,51 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef NSFW_UPGRADE_H +#define NSFW_UPGRADE_H +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#define ENUM_STRUCT(struct) enum enum_upgrade_ ## struct + +#define ENUM_MEM(struct, mem) struct ## _ ## mem + +#define GET_MEM_BIT(mem_bit, struct, mem) (mem_bit & ((i64)1 << struct ## _ ## mem)) + +#define USE_MEM_BIT(mem_bit, struct, mem) (mem_bit |= ((i64)1 << struct ## _ ## mem)) + +#define UPGRADE_MEM_VAL(mem_bit, struct, mem, obj, defalut) { \ + if (!GET_MEM_BIT(mem_bit, struct, mem)){ \ + obj->mem = defalut; \ + } \ + } + +#define CONSTRUCT_UPGRADE_FUN(struct, obj) void upgrade_ ## struct (struct* obj) + +#define CALL_UPGRADE_FUN(struct, obj) upgrade_ ## struct (obj) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/framework/include/nstack_log.h b/src/framework/include/nstack_log.h new file mode 100644 index 0000000..bb90ec8 --- /dev/null +++ b/src/framework/include/nstack_log.h @@ -0,0 +1,580 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSTACK_LOG_H_ +#define _NSTACK_LOG_H_ +/*==============================================* + * include header files * + *----------------------------------------------*/ +#pragma GCC diagnostic ignored "-Wcpp" +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdarg.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +#include <unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <signal.h> +#include "types.h" +#include "nstack_trace.h" + +#include "glog/nstack_glog.ph" +#include "glog/nstack_glog_in.h" + +#define NSTACK_GETVER_MODULE "nStack" +#define NSTACK_GETVER_VERSION "VPP2.0 V100R002C10B053" +#define NSTACK_GETVER_BUILDTIME "[" __DATE__ "]" "[" __TIME__ "]" +#define NSTACK_VERSION NSTACK_GETVER_VERSION " (" NSTACK_GETVER_MODULE ") " NSTACK_GETVER_BUILDTIME + +#define LOG_TIME_STAMP_LEN 17 // "YYYYMMDDHHMMSS"; + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ +typedef enum _LOG_MODULE +{ + NSOCKET = 1, + STACKX, + OPERATION, + MASTER, + LOGTCP, + LOGUDP, + LOGIP, + LOGCMP, + LOGARP, + LOGRTE, + LOGHAL, + LOGDFX, + LOGFW, + LOGSBR, + MAX_LOG_MODULE +} LOG_MODULE; + +enum _LOG_TYPE +{ + LOG_TYPE_NSTACK = 0, + LOG_TYPE_OPERATION, + LOG_TYPE_MASTER, + LOG_TYPE_APP, + MAX_LOG_TYPE +}; + +enum _LOG_PROCESS +{ + LOG_PRO_NSTACK = 0, + LOG_PRO_MASTER, + LOG_PRO_APP, + LOG_PRO_OMC_CTRL, + LOG_PRO_INVALID +}; + +#define LOG_INVALID_VALUE 0xFFFF + +#define NSLOG_DBG 0x10 +#define NSLOG_INF 0x08 +#define NSLOG_WAR 0x04 +#define NSLOG_ERR 0x02 +#define NSLOG_EMG 0x01 +#define NSLOG_OFF 0x00 + +#define LOG_LEVEL_EMG "emg" +#define LOG_LEVEL_ERR "err" +#define LOG_LEVEL_WAR "war" +#define LOG_LEVEL_DBG "dbg" +#define LOG_LEVEL_INF "inf" + +#define GET_FILE_NAME(name_have_path) strrchr(name_have_path,'/')?strrchr(name_have_path,'/')+1:name_have_path + +#define NSTACK_LOG_NAME "/product/gpaas/log/nStack" + +#define STACKX_LOG_NAME "running.log" + +#define OPERATION_LOG_NAME "operation.log" + +#define MASTER_LOG_NAME "master.log" + +#define OMC_CTRL_LOG_NAME "omc_ctrl.log" + +#define FAILURE_LOG_NAME "fail_dump.log" + +#define FLUSH_TIME 30 + +#define APP_LOG_SIZE 30 +#define APP_LOG_COUNT 10 +#define APP_LOG_PATH "/var/log" +#define APP_LOG_NAME "nStack_nSocket.log" + +#define NS_LOG_STACKX_ON 0x80U +#define NS_LOG_STACKX_TRACE 0x40U +#define NS_LOG_STACKX_STATE 0x20U +#define NS_LOG_STACKX_FRESH 0x10U +#define NS_LOG_STACKX_HALT 0x08U +#define NS_LOG_STACKX_OFF 0x00U + +#define NULL_STRING "" +#define MODULE_INIT_FORMAT_STRING "module %s]name=[%s]%s" +#define MODULE_INIT_START "init" +#define MODULE_INIT_FAIL "start failed" +#define MODULE_INIT_SUCCESS "start success" + +#define PRE_INIT_LOG_LENGTH 128 + +struct nstack_logs +{ + uint32_t level; /**< Log level. */ + int pad64; + int inited; + int file_type; +}; + +struct log_init_para +{ + uint32_t run_log_size; + uint32_t run_log_count; + char *run_log_path; + uint32_t mon_log_size; //master and ctrl both use the parameter to reduce the redundancy + uint32_t mon_log_count; //master and ctrl both use the parameter to reduce the redundancy + char *mon_log_path; //master and ctrl both use the parameter to reduce the redundancy +}; + +enum LOG_CTRL_ID +{ + // for socket api + LOG_CTRL_SEND = 0, + LOG_CTRL_RECV, + LOG_CTRL_SENDMSG, + LOG_CTRL_RECVMSG, + LOG_CTRL_READ, + LOG_CTRL_WRITE, + LOG_CTRL_READV, + LOG_CTRL_WRITEV, + LOG_CTRL_GETSOCKNAME, + LOG_CTRL_GETPEERNAME, + LOG_CTRL_GETSOCKOPT, + + // for nstack service + LOG_CTRL_RECV_QUEUE_FULL, + LOG_CTRL_L4_RECV_QUEUE_FULL, + LOG_CTRL_HUGEPAGE_ALLOC_FAIL, + LOG_CTRL_TCP_MEM_NOT_ENOUGH, + LOG_CTRL_IPREASS_OVERFLOW, + LOG_CTRL_ID_MAX +}; + +struct log_ctrl_info +{ + u32 expire_time; + u32 unprint_count; + struct timespec last_log_time; +}; + +struct pre_init_info +{ + uint32_t level; /**< Log level. */ + char log_buffer[PRE_INIT_LOG_LENGTH]; +}; + +#define NS_LOG_STACKX(dbug,_module,_prestr,_level,fmt, ...) \ +{\ + if ((dbug) & NS_LOG_STACKX_ON)\ + {\ + NS_LOGPID(_module,_prestr,_level,fmt,##__VA_ARGS__);\ + }\ +}\ + + +/***************************************************************************** +* Prototype : nstack_get_log_level +* Description : get log level +* Input : int module +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +extern struct nstack_logs g_nstack_logs[MAX_LOG_MODULE]; +static inline int +nstack_get_log_level (int module) +{ + /* validity check for path */ + if ((MAX_LOG_MODULE <= module) || (module < 0)) + { + return -1; + } + + return g_nstack_logs[module].level; +} + +/***************************************************************************** +* Prototype : level_stoa +* Description : convert stack log level to app log level +* Input : unsigned int nstack_level +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +static inline unsigned int +level_stoa (unsigned int level) +{ + unsigned int golg_level; + switch (level) + { + case NSLOG_DBG: + golg_level = GLOG_LEVEL_DEBUG; + break; + case NSLOG_INF: + golg_level = GLOG_LEVEL_INFO; + break; + case NSLOG_WAR: + golg_level = GLOG_LEVEL_WARNING; + break; + case NSLOG_ERR: + golg_level = GLOG_LEVEL_ERROR; + break; + case NSLOG_EMG: + golg_level = GLOG_LEVEL_FATAL; + break; + default: + golg_level = GLOG_LEVEL_BUTT; + break; + } + return golg_level; +} + +/* use the glog function to replace old nstack log module */ + +/* segregate the dump info */ +#define LOG_TYPE(_module, _level) \ + (((STACKX == _module) && (NSLOG_EMG == _level)) ? GLOG_LEVEL_ERROR : ((OPERATION == _module) ? GLOG_LEVEL_WARNING : GLOG_LEVEL_INFO)) + +#define log_shooting(_module,_level) \ + ((NULL == g_log_hook_tag.log_hook) ? (nstack_get_log_level(_module) >= _level) : (level_stoa(_level) >= g_log_hook_tag.level)) + +/* add the non reentry protection */ +extern __thread unsigned int nstack_log_nonreentry; + +/* hanging up version check log need restrain */ +extern int ctrl_log_switch; + +#if defined MPTCP_UT +#define NS_LOGPID(_module,_prestr,_level,fmt, ...) +#elif !defined FOR_NSTACK_UT +#define NS_LOGPID(_module,_prestr,_level,fmt, ...) \ +{\ + if (log_shooting(_module, _level) && (0 == nstack_log_nonreentry) && (0 == ctrl_log_switch))\ + {\ + nstack_log_nonreentry = 1;\ + NSTACK_TRACING(_level, _prestr, fmt,##__VA_ARGS__);\ + if(nstack_log_info_check(_module, _level))\ + glog_print(LOG_TYPE(_module,_level),_prestr,level_stoa(_level),-1,GET_FILE_NAME(__FILE__),\ + __LINE__,__func__,fmt, ##__VA_ARGS__);\ + nstack_log_nonreentry = 0;\ + }\ +} +#else +static inline void +ut_log_info (const char *file_name, int line_no, const char *func_name, + int _module, const char *_prestr, unsigned int _level, char *fmt, + ...) +{ + va_list ap; + + if (log_shooting (_module, _level) && (0 == nstack_log_nonreentry) + && (0 == ctrl_log_switch)) + { + + nstack_log_nonreentry = 1; + if (nstack_log_info_check (_module, _level)) + { + char pMsgBuf[MAX_LOG_TRANSITIONAL_LEN] = "\0"; + va_start (ap, fmt); + VSNPRINTF_S (pMsgBuf, + MAX_LOG_TRANSITIONAL_LEN, + MAX_LOG_TRANSITIONAL_LEN - 1, fmt, ap); + glog_print (LOG_TYPE (_module, _level), _prestr, + level_stoa (_level), -1, GET_FILE_NAME (file_name), + line_no, func_name, "%s", pMsgBuf); + va_end (ap); + } + nstack_log_nonreentry = 0; + + } +} + +#define NS_LOGPID(_module,_prestr,_level,fmt, ...) \ +{\ + ut_log_info(__FILE__,__LINE__, __func__, _module,_prestr,_level,fmt, ##__VA_ARGS__); \ +} + +#endif + +#ifndef FOR_NSTACK_UT +#define NS_LOG_CTRL(_id, _module, _prestr, _level, fmt, ...) \ +{\ + if (log_shooting(_module, _level) && (0 == nstack_log_nonreentry) && check_log_prt_time(_id))\ + {\ + nstack_log_nonreentry = 1;\ + NSTACK_TRACING(_level, _prestr, fmt,##__VA_ARGS__);\ + if(nstack_log_info_check(_module, _level))\ + glog_print(LOG_TYPE(_module,_level),_prestr,level_stoa(_level),get_unprt_log_count(_id),\ + GET_FILE_NAME(__FILE__),__LINE__,__func__,fmt, ##__VA_ARGS__);\ + clr_unprt_log_count(_id);\ + nstack_log_nonreentry = 0;\ + }\ +} + +#else +static inline void +ut_ctrl_log_info (char *file_name, int line_no, char *func_name, int _id, + int _module, char *_prestr, unsigned int _level, char *fmt, + ...) +{ + va_list ap; + if (log_shooting (_module, _level) && (0 == nstack_log_nonreentry) + && check_log_prt_time (_id)) + { + nstack_log_nonreentry = 1; + if (nstack_log_info_check (_module, _level)) + { + char pMsgBuf[MAX_LOG_TRANSITIONAL_LEN] = "\0"; + va_start (ap, fmt); + VSNPRINTF_S (pMsgBuf, + MAX_LOG_TRANSITIONAL_LEN, + MAX_LOG_TRANSITIONAL_LEN - 1, fmt, ap); + glog_print (LOG_TYPE (_module, _level), _prestr, + level_stoa (_level), get_unprt_log_count (_id), + GET_FILE_NAME (file_name), line_no, func_name, "%s", + pMsgBuf); + va_end (ap); + } + clr_unprt_log_count (_id); + nstack_log_nonreentry = 0; + + } +} + +#define NS_LOG_CTRL(_id, _module, _prestr, _level, fmt, ...) \ +{\ + ut_ctrl_log_info(__FILE__,__LINE__, __func__, _id, _module,_prestr,_level,fmt, ##__VA_ARGS__); \ +} + +#endif + +#define NS_LOG_CTRL_STACKX(_id, dbug,_module,_prestr,_level,fmt, ...) \ +{\ + if ((dbug) & NS_LOG_STACKX_ON)\ + {\ + NS_LOG_CTRL(_id, _module,_prestr,_level,fmt,##__VA_ARGS__);\ + }\ +}\ + + +/*for every log modules should def marcos below use a sort module name, just like MON means Monitor*/ +#define NSMON_LOGINF(fmt, ...) NS_LOGPID(MASTER,"NSMON",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSMON_LOGDBG(fmt, ...) NS_LOGPID(MASTER,"NSMON",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSMON_LOGWAR(fmt, ...) NS_LOGPID(MASTER,"NSMON",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSMON_LOGERR(fmt, ...) NS_LOGPID(MASTER,"NSMON",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSPOL_LOGINF(debug,fmt, ...)NS_LOG_STACKX(debug,STACKX,"NSPOL",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSPOL_LOGDBG(debug,fmt, ...) NS_LOG_STACKX(debug,STACKX,"NSPOL",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSPOL_LOGWAR(debug,fmt, ...) NS_LOG_STACKX(debug,STACKX,"NSPOL",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSPOL_LOGERR(fmt, ...) NS_LOGPID(STACKX,"NSPOL",NSLOG_ERR,fmt,##__VA_ARGS__) +#define NSPOL_LOGEMG(fmt, ...) NS_LOGPID(STACKX,"NSPOL",NSLOG_EMG,fmt,##__VA_ARGS__) + +#define NSOPR_LOGINF(fmt, ...) NS_LOGPID(OPERATION,"NSOPR",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSOPR_LOGDBG(fmt, ...) NS_LOGPID(OPERATION,"NSOPR",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSOPR_LOGWAR(fmt, ...) NS_LOGPID(OPERATION,"NSOPR",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSOPR_LOGERR(fmt, ...) NS_LOGPID(OPERATION,"orchestration",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSSOC_LOGINF(fmt, ...) NS_LOGPID(NSOCKET,"NSSOC",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSSOC_LOGDBG(fmt, ...) NS_LOGPID(NSOCKET,"NSSOC",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSSOC_LOGWAR(fmt, ...) NS_LOGPID(NSOCKET,"NSSOC",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSSOC_LOGERR(fmt, ...) NS_LOGPID(NSOCKET,"NSSOC",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSSBR_LOGINF(fmt, ...) NS_LOGPID(LOGSBR,"NSSBR",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSSBR_LOGDBG(fmt, ...) NS_LOGPID(LOGSBR,"NSSBR",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSSBR_LOGWAR(fmt, ...) NS_LOGPID(LOGSBR,"NSSBR",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSSBR_LOGERR(fmt, ...) NS_LOGPID(LOGSBR,"NSSBR",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSCOMM_LOGINF(fmt, ...) NS_LOGPID(LOGRTE, "NSRTE",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSCOMM_LOGDBG(fmt, ...) NS_LOGPID(LOGRTE, "NSRTE",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSCOMM_LOGWAR(fmt, ...) NS_LOGPID(LOGRTE, "NSRTE",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSCOMM_LOGERR(fmt, ...) NS_LOGPID(LOGRTE, "NSRTE",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSTCP_LOGINF(fmt, ...) NS_LOGPID(LOGTCP,"NSTCP",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSTCP_LOGDBG(fmt, ...) NS_LOGPID(LOGTCP,"NSTCP",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSTCP_LOGWAR(fmt, ...) NS_LOGPID(LOGTCP,"NSTCP",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSTCP_LOGERR(fmt, ...) NS_LOGPID(LOGTCP,"NSTCP",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSIP_LOGINF(fmt, ...) NS_LOGPID(LOGIP,"NSIP",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSIP_LOGDBG(fmt, ...) NS_LOGPID(LOGIP,"NSIP",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSIP_LOGWAR(fmt, ...) NS_LOGPID(LOGIP,"NSIP",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSIP_LOGERR(fmt, ...) NS_LOGPID(LOGIP,"NSIP",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSUDP_LOGINF(fmt, ...) NS_LOGPID(LOGUDP,"NSUDP",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSUDP_LOGDBG(fmt, ...) NS_LOGPID(LOGUDP,"NSUDP",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSUDP_LOGWAR(fmt, ...) NS_LOGPID(LOGUDP,"NSUDP",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSUDP_LOGERR(fmt, ...) NS_LOGPID(LOGUDP,"NSUDP",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSHAL_LOGINF(fmt, ...) NS_LOGPID(LOGHAL,"NSHAL",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSHAL_LOGDBG(fmt, ...) NS_LOGPID(LOGHAL,"NSHAL",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSHAL_LOGWAR(fmt, ...) NS_LOGPID(LOGHAL,"NSHAL",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSHAL_LOGERR(fmt, ...) NS_LOGPID(LOGHAL,"NSHAL",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSARP_LOGINF(fmt, ...) NS_LOGPID(LOGARP,"NSARP",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSARP_LOGDBG(fmt, ...) NS_LOGPID(LOGARP,"NSARP",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSARP_LOGWAR(fmt, ...) NS_LOGPID(LOGARP,"NSARP",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSARP_LOGERR(fmt, ...) NS_LOGPID(LOGARP,"NSARP",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSDFX_LOGINF(fmt, ...) NS_LOGPID(LOGDFX,"NSDFX",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSDFX_LOGDBG(fmt, ...) NS_LOGPID(LOGDFX,"NSDFX",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSDFX_LOGWAR(fmt, ...) NS_LOGPID(LOGDFX,"NSDFX",NSLOG_WAR,fmt,##__VA_ARGS__) +#define NSDFX_LOGERR(fmt, ...) NS_LOGPID(LOGDFX,"NSDFX",NSLOG_ERR,fmt,##__VA_ARGS__) + +#define NSFW_LOGINF(fmt, ...) NS_LOGPID(LOGFW,"NSFW",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSFW_LOGDBG(fmt, ...) NS_LOGPID(LOGFW,"NSFW",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSFW_LOGERR(fmt, ...) NS_LOGPID(LOGFW,"NSFW",NSLOG_ERR,fmt,##__VA_ARGS__) +#define NSFW_LOGWAR(fmt, ...) NS_LOGPID(LOGFW,"NSFW",NSLOG_WAR,fmt,##__VA_ARGS__) + +#define NSAM_LOGINF(fmt, ...) NS_LOGPID(LOGFW,"NSAM",NSLOG_INF,fmt,##__VA_ARGS__) +#define NSAM_LOGDBG(fmt, ...) NS_LOGPID(LOGFW,"NSAM",NSLOG_DBG,fmt,##__VA_ARGS__) +#define NSAM_LOGERR(fmt, ...) NS_LOGPID(LOGFW,"NSAM",NSLOG_ERR,fmt,##__VA_ARGS__) +#define NSAM_LOGWAR(fmt, ...) NS_LOGPID(LOGFW,"NSAM",NSLOG_WAR,fmt,##__VA_ARGS__) + +#define INIT_LOG_ASSEM(log_module,_prestr,_level, init_module , function, errString, errValue, status) \ + if ((LOG_INVALID_VALUE <= errValue) && (1 == sizeof(errString))) \ + { \ + NS_LOGPID(log_module,_prestr, _level,MODULE_INIT_FORMAT_STRING, (char*)status, init_module, function ); \ + } \ + else if (LOG_INVALID_VALUE <= errValue)\ + { \ + NS_LOGPID(log_module,_prestr, _level,MODULE_INIT_FORMAT_STRING",err_string=%s", (char*)status, init_module, function, errString ); \ + } \ + else if (1 == sizeof(errString))\ + { \ + NS_LOGPID(log_module,_prestr, _level,MODULE_INIT_FORMAT_STRING",err_value=%d", (char*)status, init_module, function, errValue ); \ + } \ + else \ + { \ + NS_LOGPID(log_module,_prestr, _level,MODULE_INIT_FORMAT_STRING",err_string=%s,err_value=%d", (char*)status, init_module, function, errString, errValue ); \ + } \ + +#define INITPOL_LOGINF(init_module_name, function, err_string, err_value, status) \ + INIT_LOG_ASSEM(STACKX,"NSPOL",NSLOG_INF,init_module_name , function, err_string, err_value, status)\ + +#define INITPOL_LOGERR(init_module_name, function, err_string, err_value, status) \ + INIT_LOG_ASSEM(STACKX,"NSPOL",NSLOG_ERR,init_module_name , function, err_string, err_value, status)\ + +#define INITTCP_LOGINF(init_module_name , function, err_string, err_value, status) \ + INIT_LOG_ASSEM(LOGTCP,"NSTCP",NSLOG_INF,init_module_name , function, err_string, err_value, status)\ + +#define INITTCP_LOGERR(init_module_name , function, err_string, err_value, status) \ + INIT_LOG_ASSEM(LOGTCP,"NSTCP",NSLOG_ERR,init_module_name , function, err_string, err_value, status)\ + +#define INITMON_LOGERR(init_module_name , function, err_string, err_value, status) \ + INIT_LOG_ASSEM(MASTER,"NSMON",NSLOG_ERR,init_module_name , function, err_string, err_value, status)\ + +#define INITSOC_LOGERR(init_module_name , function, err_string, err_value, status) \ + INIT_LOG_ASSEM(NSOCKET,"NSSOC",NSLOG_ERR,init_module_name , function, err_string, err_value, status) + +#define NSPOL_DUMP_LOGINF(fmt, ...) NSPOL_LOGINF(0x80, fmt, ##__VA_ARGS__) +#define NSPOL_DUMP_LOGDBG(fmt, ...) NSPOL_LOGDBG(0x80, fmt, ##__VA_ARGS__) +#define NSPOL_DUMP_LOGERR(fmt, ...) NSPOL_LOGERR(fmt, ##__VA_ARGS__) +#define NSPOL_DUMP_LOGWAR(fmt, ...) NSPOL_LOGWAR(0x80, fmt, ##__VA_ARGS__) + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +void save_pre_init_log (uint32_t level, char *fmt, ...); +void write_pre_init_log (); + +void set_log_init_para (struct log_init_para *para); + +void nstack_setlog_level (int module, uint32_t level); +bool nstack_log_info_check (uint32_t module, uint32_t level); +int nstack_log_init (); +void nstack_log_init_app (); +int get_app_env_log_path (char *app_file_path, unsigned int app_file_size); +void set_log_proc_type (int log_proc_type); + +int setlog_level_value (const char *param, const char *value); +int get_str_value (const char *arg); +int check_log_dir_valid (const char *path); +void nstack_segment_error (int s); +void init_log_ctrl_info (); +void set_log_ctrl_time (int id, int ctrl_time); + +int cmp_log_path (const char *path); + +#ifndef sys_sleep_ns +#define sys_sleep_ns(_s, _ns)\ + {\ + if ((_s) >= 0 && (_ns) >= 0){\ + struct timespec delay, remain;\ + delay.tv_sec=(_s);\ + delay.tv_nsec=(_ns);\ + while (nanosleep (&delay, &remain) < 0)\ + {\ + delay = remain;\ + }\ + }\ + } +#endif /* sys_sleep_ns */ + +int check_log_prt_time (int id); +int get_unprt_log_count (int id); +void clr_unprt_log_count (int id); + +void get_current_time (char *buf, const int len); + +#ifdef CPU_CYCLES +static __inline__ unsigned long long +nstack_rdtsc (void) +{ + unsigned hi, lo; + __asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi)); + return ((unsigned long long) lo) | (((unsigned long long) hi) << 32); +} + +#define CPUB(name) \ +unsigned long long start##name = 0;\ +unsigned long long stop##name = 0;\ +static unsigned long long total##name = 0;\ +static unsigned long long total_cout##name = 0;\ +start##name = nstack_rdtsc(); + +#define CPUE(name) \ +stop##name = nstack_rdtsc();\ +total##name += (stop##name - start##name);\ +if(++total_cout##name == 1000000)\ +{\ + NSSOC_LOGINF(#name" cpu %llu-------\n", total##name / total_cout##name);\ + total##name = 0;\ + total_cout##name = 0;\ +} +#else +#define CPUB(name) +#define CPUE(name) +#endif + +#endif diff --git a/src/framework/include/nstack_rd_data.h b/src/framework/include/nstack_rd_data.h new file mode 100644 index 0000000..3924680 --- /dev/null +++ b/src/framework/include/nstack_rd_data.h @@ -0,0 +1,80 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __NSTACK_RD_DATA_H +#define __NSTACK_RD_DATA_H + +/*choose router base on ip seg*/ +#define STACK_NAME_MAX 32 +#define RD_PLANE_NAMELEN (32) +#define NSTACK_IP_BIT_MAX (32) +#define NSTACK_RD_DATA_MAX (2048) +#define RD_IP_STR_MAX_LEN (32) + +typedef enum __rd_data_type +{ + RD_DATA_TYPE_IP, + RD_DATA_TYPE_PROTO, + RD_DATA_TYPE_MAX, +} rd_data_type; + +typedef enum __rd_node_state +{ + RD_NODE_USELESS, + RD_NODE_USING, + RD_NODE_DELETING, + RD_NODE_MAX, +} rd_node_state; + +/*route info base on ip*/ +typedef struct __rd_route_ip_data +{ + unsigned int addr; + unsigned int masklen; + unsigned int resev[2]; +} rd_ip_data; + +/*route data*/ +typedef struct __rd_route_data +{ + /*route info type , for example base on ip */ + rd_data_type type; + char stack_name[RD_PLANE_NAMELEN]; + union + { + rd_ip_data ipdata; + unsigned int proto_type; + /*:::other type to be add */ + }; +} rd_route_data; + +typedef struct __rd_route_node +{ + rd_node_state flag; + int agetime; + rd_route_data data; +} rd_route_node; + +typedef struct __rd_route_table +{ + int size; + int icnt; + rd_route_node node[NSTACK_RD_DATA_MAX]; +} rd_route_table; + +#define MASK_V(ipaddr, masklen) ((ipaddr) & (~0 << (NSTACK_IP_BIT_MAX - (masklen)))) + +#endif diff --git a/src/framework/include/nstack_securec.h b/src/framework/include/nstack_securec.h new file mode 100644 index 0000000..c9efb4f --- /dev/null +++ b/src/framework/include/nstack_securec.h @@ -0,0 +1,145 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __NSTACK_SECUREC_H__ +#define __NSTACK_SECUREC_H__ + +/*if you need export the function of this library in Win32 dll, use __declspec(dllexport) */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ + +#endif /* */ +#ifndef SECUREC_LIB +#include <stdio.h> +#include <stdarg.h> +#include <wchar.h> +#include <string.h> + +#ifndef NULL +#define NULL ((void *)0) +#endif /* + */ + +/*define error code*/ +#ifndef errno_t +typedef int errno_t; + +#endif /* + */ + +/* success */ +#define EOK (0) + +/* invalid parameter */ +#ifndef EINVAL +#define EINVAL (22) +#endif /* + */ + +#define EINVAL_AND_RESET (22 | 0X80) +#define ERANGE_AND_RESET (34 | 0X80) + +#define SCANF_S scanf +#define WSCANF_S wscanf +#define VSCANF_S vscanf +#define VWSCANF_S vwscanf +#define FSCANF_S fscanf +#define FWSCANF_S fwscanf +#define VFSCANF_S vfscanf +#define VFWSCANF_S vfwscanf +#define SSCANF_S sscanf +#define SWSCANF_S swscanf +#define VSSCANF_S vsscanf +#define VSWSCANF_S vswscanf + +#define SPRINTF_S(a, b, ...) sprintf(a, ##__VA_ARGS__) +#define SWPRINTF_S(a, b, c, ...) swprintf(a, b, c, ##__VA_ARGS__) +#define VSPRINTF_S(a, b, c, d) vsprintf(a, c, d) +#define VSWPRINTF_S(a, b, c, d) vswprintf(a, b, c, d) +#define VSNPRINTF_S(a, b, c, d, e) vsnprintf(a, c, d, e) +#define SNPRINTF_S(a, b, c, d, ...) snprintf(a, c, d, ##__VA_ARGS__) + +#define WMEMCPY_S(a, b, c, d) ((NULL == wmemcpy(a, c, d)) ? EINVAL : EOK) +#define MEMMOVE_S(a, b, c, d) ((NULL == memmove(a, c, d)) ? EINVAL : EOK) +#define WMEMMOVE_S(a, b, c, d) ((NULL == wmemmove(a, c, d)) ? EINVAL : EOK) +#define WCSCPY_S(a, b, c) ((NULL == wcscpy(a, c)) ? EINVAL : EOK) +#define WCSNCPY_S(a, b, c, d) ((NULL == wcsncpy(a, c, d)) ? EINVAL : EOK) +#define WCSCAT_S(a, b, c) ((NULL == wcscat(a, c)) ? EINVAL : EOK) +#define WCSNCAT_S(a, b, c, d) ((NULL == wcsncat(a, c, d)) ? EINVAL : EOK) + +#define MEMSET_S(a, b, c, d) ((NULL == memset(a, c, d)) ? EINVAL : EOK) +#define MEMCPY_S(a, b, c, d) ((NULL == memcpy(a, c, d)) ? EINVAL : EOK) +#define STRCPY_S(a, b, c) ((NULL == strcpy(a, c )) ? EINVAL : EOK) +#define STRNCPY_S(a, b, c, d) ((NULL == strncpy(a, c, d)) ? EINVAL : EOK) +#define STRCAT_S(a, b, c) ((NULL == strcat(a, c)) ? EINVAL : EOK) +#define STRNCAT_S(a, b, c, d) ((NULL == strncat(a, c, d)) ? EINVAL : EOK) + +#define STRTOK_S(a, b, c) strtok(a, b) +#define WCSTOK_S(a, b, c) wcstok(a, b) +#define GETS_S(a, b) gets(a) + +#else /* */ +#include "securec.h" + +#define SCANF_S scanf_s +#define WSCANF_S wscanf_s +#define VSCANF_S vscanf_s +#define VWSCANF_S vwscanf_s +#define FSCANF_S fscanf_s +#define FWSCANF_S fwscanf_s +#define VFSCANF_S vfscanf_s +#define VFWSCANF_S vfwscanf_s +#define SSCANF_S sscanf_s +#define SWSCANF_S swscanf_s +#define VSSCANF_S vsscanf_s +#define VSWSCANF_S vswscanf_s + +#define SPRINTF_S(a, b, ...) sprintf_s (a, b, ##__VA_ARGS__) +#define SWPRINTF_S(a, b, c, ...) swprintf_s(a, b, c, ##__VA_ARGS__) +#define VSPRINTF_S(a, b, c, d) vsprintf_s(a, b, c, d) +#define VSWPRINTF_S(a, b, c, d) vswprintf_s(a, b, c, d) +#define VSNPRINTF_S(a, b, c, d, e) vsnprintf_s(a, b, c, d, e) +#define SNPRINTF_S(a, b, c, d, ...) snprintf_s(a, b, c, d, ##__VA_ARGS__) + +#define WMEMCPY_S(a, b, c, d) wmemcpy_s(a, b, c, d) +#define MEMMOVE_S(a, b, c, d) memmove_s(a, b, c, d) +#define WMEMMOVE_S(a, b, c, d) wmemmove_s(a, b, c, d) +#define WCSCPY_S(a, b, c) wcscpy_s(a, b, c) +#define WCSNCPY_S(a, b, c, d) wcsncpy_s(a, b, c, d) +#define WCSCAT_S(a, b, c) wcscat_s(a, b, c) +#define WCSNCAT_S(a, b, c, d) wcsncat_s(a, b, c, d) + +#define MEMSET_S(a, b, c, d) memset_s(a, b, c, d) +#define MEMCPY_S(a, b, c, d) memcpy_s(a, b, c, d) +#define STRCPY_S(a, b, c) strcpy_s(a, b, c) +#define STRNCPY_S(a, b, c, d) strncpy_s(a, b, c, d) +#define STRCAT_S(a, b, c) strcat_s(a, b, c) +#define STRNCAT_S(a, b, c, d) strncat_s(a, b, c, d) + +#define STRTOK_S(a, b, c) strtok_s(a, b, c) +#define WCSTOK_S(a, b, c) wcstok_s(a, b, c) +#define GETS_S(a, b) gets_s(a, b) +#endif /* */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* __NSTACK_SECUREC_H__ */ diff --git a/src/framework/include/nstack_trace.h b/src/framework/include/nstack_trace.h new file mode 100644 index 0000000..0f4f640 --- /dev/null +++ b/src/framework/include/nstack_trace.h @@ -0,0 +1,76 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __NSTACK_TRACE_H__ +#define __NSTACK_TRACE_H__ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +/*==============================================* + * include header files * + *----------------------------------------------*/ +#include "types.h" +#include "nstack_log.h" +#include <time.h> +#define SPAN_NAME_MAX 64 +#define TRACE_NULL 0 +#define NSTACK_TRACE_ON 0 +#define NSTACK_TRACE_OFF 1 + +typedef struct nst_trace_header +{ + u64 trace_id; + u64 span_pid; + u64 span_id; /*now us */ + int fd; + int thread_id; +} trace_hread_t; + +typedef struct nst_trace_fun +{ + u64 (*current_traceid) (); + void (*span_raw) (char *msg); + void (*tracing_enable) (int enable); + void (*tracing_simpling) (int frequency); + void (*tracing_cleanup) (); + void (*tracing_setup) (u32 process); + u64 (*tracing_string_to_traceid) (const char *input, size_t length); +} trace_fun_t; + +extern __thread struct nst_trace_header strace_header; + +#define get_trace_header() (&strace_header) + +//For Tracing define own tracing feature. +#define nstack_trace_init( a ) +#define nstack_set_tracing_contex( a,b,c) +#define nstack_get_tracing_contex(traceid,spanid,spanpid,fd) +#define nstack_clear_tracing_contex( ) +#define NSTACK_TRACING(level, module_name,famt,...) +#define nstack_tracing_enalbe() +#define nstack_get_traceid() (NULL) + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/src/framework/init/CMakeLists.txt b/src/framework/init/CMakeLists.txt new file mode 100644 index 0000000..ff8d4d2 --- /dev/null +++ b/src/framework/init/CMakeLists.txt @@ -0,0 +1,24 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +SET(LIBSBR_SRC fw_init.c fw_module.c) + +SET(COMM_CONFIG ${PROJECT_SOURCE_DIR}/src/framework/common/base/include/common_sys_config.h) +ADD_DEFINITIONS(-fPIC -mssse3) +ADD_DEFINITIONS(-include ${COMM_CONFIG}) + +ADD_LIBRARY(nStackfwinit static ${LIBSBR_SRC}) + diff --git a/src/framework/init/fw_init.c b/src/framework/init/fw_init.c new file mode 100644 index 0000000..6337b67 --- /dev/null +++ b/src/framework/init/fw_init.c @@ -0,0 +1,320 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "nstack_securec.h" +#include "fw_module.h" +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +NSTACK_STATIC int +nsfw_module_instance_isIndepend (nsfw_module_instance_t * inst) +{ + nsfw_module_depends_t *dep = inst->depends; + while (dep) + { + if (!dep->isReady) + return 1; + dep = dep->next; + } + + return 0; +} + +NSTACK_STATIC void +nsfw_module_instance_depend_check (nsfw_module_instance_t * inst) +{ + nsfw_module_instance_t *curInst = nsfw_module_getManager ()->inst; + while (curInst) + { + if (curInst == inst) + goto nextLoop; + if (NSFW_INST_STAT_CHECKING == curInst->stat + || NSFW_INST_STAT_DEPENDING == curInst->stat) + { + nsfw_module_depends_t *dep = curInst->depends; + while (dep) + { + if (0 == dep->isReady && 0 == strcmp (dep->name, inst->name)) + { + dep->isReady = 1; /* Don't break for case that duplicate name exist, though I think it should + not happen */ + } + dep = dep->next; + } + } + nextLoop: + curInst = curInst->next; + } + +} + +/** + * @Function nstack_framework_init + * @Description Init child modules + * @param father instance , NULL means root + * @return 0 on success, -1 on error + */ +NSTACK_STATIC int +nstack_framework_initChild_unsafe (nsfw_module_instance_t * father) +{ + NSFW_LOGDBG ("init framework module] name=%s", + father ? father->name : "NULL"); + + nsfw_module_instance_t *inst = nsfw_module_getManager ()->inst; + + while (inst) + { + NSFW_LOGDBG + ("init child] inst=%s, inst->father=%s, inst->depends=%s, inst->state=%d", + inst->name, inst->father ? inst->father->name : "NULL", + inst->depends ? inst->depends->name : "NULL", inst->stat); + + if (father != inst->father) + { + NSFW_LOGDBG ("inst->father not match] inst=%s, ", inst->name); + + inst = inst->next; + continue; + } + + switch (inst->stat) + { + case NSFW_INST_STAT_CHECKING: + /* First, check if any depends, then check if other instance depends on it */ + if (nsfw_module_instance_isIndepend (inst)) + { + inst->stat = NSFW_INST_STAT_DEPENDING; + NSFW_LOGDBG ("inst is still depending] name=%s", inst->name); + inst = inst->next; + break; + } + + NSFW_LOGINF ("Going to init module] name=%s, init fun=%p", + inst->name, inst->fnInit); + if (NULL != inst->fnInit && 0 != inst->fnInit (inst->param)) + { + NSFW_LOGERR ("initial fail!!!] inst=%s", inst->name); + inst->stat = NSFW_INST_STAT_FAIL; + return -1; + } + + inst->stat = NSFW_INST_STAT_DONE; + nsfw_module_instance_depend_check (inst); + + if (-1 == nsfw_module_addDoneNode (inst)) + { + NSFW_LOGERR ("add done node fail"); + } + + inst = nsfw_module_getManager ()->inst; /* check from begining */ + break; + case NSFW_INST_STAT_DEPENDING: + /* check if depending stat is still there */ + if (!nsfw_module_instance_isIndepend (inst)) + { + inst->stat = NSFW_INST_STAT_CHECKING; + break; + } + case NSFW_INST_STAT_FAIL: + case NSFW_INST_STAT_DONE: + default: + inst = inst->next; + break; + } + } + + return 0; +} + +NSTACK_STATIC void +nstack_framework_printInstanceInfo (nsfw_module_instance_t * inst) +{ + + if (NULL == inst) + { + NSFW_LOGERR ("param error,inst==NULL"); + return; + } + + char info[1024] = ""; + int plen = 0; + + int ret = SPRINTF_S (info, sizeof (info), "Inst:%s,father:%s,depends:", + inst->name, + inst->father ? inst->father->name : "NULL"); + + if (ret <= 0) + { + NSFW_LOGERR ("Sprintf Error] module=%s,state=%d, ret=%d", inst->name, + inst->stat, ret); + return; + } + else + { + plen += ret; + } + + if (NULL == inst->depends) + { + ret = SPRINTF_S (info + plen, sizeof (info) - plen, "NULL"); + if (ret <= 0) + { + NSFW_LOGERR ("Sprintf Error] module=%s,state=%d, ret=%d", + inst->name, inst->stat, ret); + return; + } + NSFW_LOGINF ("] inst info=%s", info); + return; + } + + nsfw_module_depends_t *dep = inst->depends; + while (dep) + { + ret = SPRINTF_S (info + plen, sizeof (info) - plen, "%s ", dep->name); + if (ret <= 0) + { + NSFW_LOGERR ("Sprintf Error] module=%s,state=%d, ret=%d", + inst->name, inst->stat, ret); + return; + } + plen += ret; + dep = dep->next; + } + + NSFW_LOGINF ("] inst info=%s", info); +} + +NSTACK_STATIC void +nstack_framework_printInitialResult () +{ + nsfw_module_manager_t *manager = nsfw_module_getManager (); + + if (manager->doneHead) + { + NSFW_LOGINF ("Here is the initial done modules: "); + + nsfw_module_doneNode_t *curNode = manager->doneHead; + while (curNode) + { + nstack_framework_printInstanceInfo (curNode->inst); + curNode = curNode->next; + } + } + else + { + NSFW_LOGERR ("No initial done modules"); + } + + nsfw_module_instance_t *curInst = manager->inst; + int unDoneNum = 0; + while (curInst) + { + if (curInst->stat != NSFW_INST_STAT_DONE) + { + if (0 == unDoneNum) + { + NSFW_LOGINF ("Here is the unInited modules:"); + } + unDoneNum++; + nstack_framework_printInstanceInfo (curInst); + } + curInst = curInst->next; + } + if (0 == unDoneNum) + NSFW_LOGINF ("All modules are inited"); +} + +/** + * @Function nstack_framework_init + * @Description This function will do framework initial work, it will involk all initial functions + * registed using macro NSFW_MODULE_INIT before + * @param none + * @return 0 on success, -1 on error + */ +int +nstack_framework_init (void) +{ + int ret = -1; + if (nsfw_module_getManager ()->done) + { + goto init_finished; + } + + if (pthread_mutex_lock (&nsfw_module_getManager ()->initMutex)) + { + return -1; + } + + if (nsfw_module_getManager ()->done) + { + goto done; + } + + ret = nstack_framework_initChild_unsafe (NULL); + + if (0 == ret) + { + nsfw_module_getManager ()->done = 1; + } + else + { + nsfw_module_getManager ()->done = -1; + } + + // Going to print done modules and undone modules + nstack_framework_printInitialResult (); + +done: + if (pthread_mutex_unlock (&nsfw_module_getManager ()->initMutex)) + { + return -1; + } +init_finished: + ret = nsfw_module_getManager ()->done == 1 ? 0 : -1; + return ret; +} + +/** + * @Function nstack_framework_setModuleParam + * @Description This function set parameter of module initial function parameter + * @param module - name of module + * @param param - parameter to set + * @return 0 on success, -1 on error + */ +int +nstack_framework_setModuleParam (char *module, void *param) +{ + nsfw_module_instance_t *inst = nsfw_module_getModuleByName (module); + if (!inst) + return -1; + + inst->param = param; + return 0; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/init/fw_module.c b/src/framework/init/fw_module.c new file mode 100644 index 0000000..65bbb0a --- /dev/null +++ b/src/framework/init/fw_module.c @@ -0,0 +1,331 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <memory.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include "nstack_securec.h" +#include "fw_module.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +COMPAT_PROTECT (NSFW_MOUDLE_INSTANCE_POOL_SIZE, 64); +COMPAT_PROTECT (NSFW_MOUDLE_DEPENDS_POOL_SIZE, 128); + +nsfw_module_instance_pool_t g_nsfw_module_inst_pool; +nsfw_module_depends_pool_t g_nsfw_module_deps_pool; + +/* +* WARNING!!!: +* This function is only used in constructor progress. Multi-thread concurrent is not supported! +*/ +NSTACK_STATIC nsfw_module_instance_t * +nsfw_module_malloc_instance () +{ + if (g_nsfw_module_inst_pool.last_idx >= NSFW_MOUDLE_INSTANCE_POOL_SIZE) + { + return NULL; + } + return + &g_nsfw_module_inst_pool.module_instance_pool[g_nsfw_module_inst_pool. + last_idx++]; +} + +/* +* WARNING!!!: +* This function is only used in constructor progress. Multi-thread concurrent is not supported! +*/ +NSTACK_STATIC nsfw_module_depends_t * +nsfw_module_malloc_depends () +{ + if (g_nsfw_module_deps_pool.last_idx >= NSFW_MOUDLE_DEPENDS_POOL_SIZE) + { + return NULL; + } + return + &g_nsfw_module_deps_pool.module_depends_pool[g_nsfw_module_deps_pool. + last_idx++]; +} + +NSTACK_STATIC void +nsfw_module_setChildInstance (nsfw_module_instance_t * + father, nsfw_module_instance_t * child) +{ + if (NULL == father || NULL == child) + return; + child->father = father; +} + +nsfw_module_depends_t * +nsfw_module_create_depends (char *name) +{ + if (NULL == name) + return NULL; + + /*Change module malloc to pool array */ + nsfw_module_depends_t *dep = nsfw_module_malloc_depends (); + + if (NULL == dep) + return NULL; + + if (EOK != + MEMSET_S (dep, sizeof (nsfw_module_depends_t), 0, + sizeof (nsfw_module_depends_t))) + { + goto fail; + } + + /*change destMax from nameSize - 1 to sizeof(dep->name) */ + if (EOK != STRCPY_S (dep->name, sizeof (dep->name), name)) + { + goto fail; + } + dep->isReady = 0; + + return dep; + +fail: + // NOTE: if dep is not null, we do not free it and just leave it there. + return NULL; +} + +nsfw_module_instance_t * +nsfw_module_create_instance (void) +{ + /*Change module malloc to pool array */ + nsfw_module_instance_t *inst = nsfw_module_malloc_instance (); + if (NULL == inst) + return NULL; + + if (EOK != + MEMSET_S (inst, sizeof (nsfw_module_instance_t), 0, + sizeof (nsfw_module_instance_t))) + { + // NOTE: if inst is not null, we do not free it and just leave it there. + return NULL; + } + + inst->stat = NSFW_INST_STAT_CHECKING; + return inst; +} + +void +nsfw_module_set_instance_name (nsfw_module_instance_t * inst, char *name) +{ + if (NULL == inst || NULL == name || inst->name[0] != '\0') + { + return; + } + + /*change destMax from nameSize - 1 to sizeof(inst->name) */ + if (EOK != STRCPY_S (inst->name, sizeof (inst->name), name)) + { + return; + } + + // Now we need to search if it's any instance's father + nsfw_module_instance_t *curInst = nsfw_module_getManager ()->inst; + while (curInst) + { + if (curInst == inst) + goto next_loop; + + if (0 == strcmp (curInst->fatherName, inst->name) + && NULL == curInst->father) + { + nsfw_module_setChildInstance (inst, curInst); + } + next_loop: + curInst = curInst->next; + } + return; +} + +void +nsfw_module_set_instance_father (nsfw_module_instance_t * inst, + char *fatherName) +{ + if (NULL == inst || NULL == fatherName) + { + return; + } + + if (EOK != + STRCPY_S (inst->fatherName, sizeof (inst->fatherName), fatherName)) + { + return; + } + + nsfw_module_instance_t *fatherInst = + nsfw_module_getModuleByName (fatherName); + if (fatherInst) + { + nsfw_module_setChildInstance (fatherInst, inst); + } + return; +} + +void +nsfw_module_set_instance_priority (nsfw_module_instance_t * inst, + int priority) +{ + if (NULL == inst) + return; + inst->priority = priority; + + nsfw_module_del_instance (inst); + nsfw_module_add_instance (inst); + return; +} + +void +nsfw_module_set_instance_initfn (nsfw_module_instance_t * inst, + nsfw_module_init_fn fn) +{ + if (NULL == inst) + return; + inst->fnInit = fn; + return; +} + +void +nsfw_module_set_instance_depends (nsfw_module_instance_t * inst, char *name) +{ + if (NULL == inst || name == NULL) + return; + + // Check if depends already set + nsfw_module_depends_t *dep = inst->depends; + while (dep) + { + if (0 == strcmp (dep->name, name)) + return; + dep = dep->next; + } + + dep = nsfw_module_create_depends (name); + if (NULL == dep) + return; + + if (NULL == inst->depends) + inst->depends = dep; + else + inst->depends->next = dep; +} + +/* *INDENT-OFF* */ +nsfw_module_manager_t g_nsfw_module_manager = {.inst = NULL, .initMutex = + PTHREAD_MUTEX_INITIALIZER, .done = 0}; +/* *INDENT-ON* */ + +void +nsfw_module_add_instance (nsfw_module_instance_t * inst) +{ + nsfw_module_instance_t *curInst = nsfw_module_getManager ()->inst; + + if (NULL == curInst || curInst->priority > inst->priority) + { + inst->next = curInst; + nsfw_module_getManager ()->inst = inst; + } + else + { + while (curInst->next && curInst->next->priority <= inst->priority) + { + curInst = curInst->next; + } + inst->next = curInst->next; + curInst->next = inst; + } +} + +void +nsfw_module_del_instance (nsfw_module_instance_t * inst) +{ + if (nsfw_module_getManager ()->inst == inst) + { + nsfw_module_getManager ()->inst = inst->next; + return; + } + + nsfw_module_instance_t *curInst = nsfw_module_getManager ()->inst; + + while (curInst->next && curInst->next != inst) + curInst = curInst->next; + + if (!curInst->next) + return; + curInst->next = inst->next; +} + +nsfw_module_instance_t * +nsfw_module_getModuleByName (char *name) +{ + if (NULL == name) + return NULL; + + nsfw_module_instance_t *curInst = nsfw_module_getManager ()->inst; + while (curInst) + { + if (0 == strcmp (curInst->name, name)) + { + return curInst; + } + curInst = curInst->next; + } + + return NULL; +} + +int +nsfw_module_addDoneNode (nsfw_module_instance_t * inst) +{ + nsfw_module_doneNode_t *node = + (nsfw_module_doneNode_t *) malloc (sizeof (nsfw_module_doneNode_t)); + if (NULL == node) + return -1; + node->inst = inst; + node->next = NULL; + + nsfw_module_manager_t *manager = nsfw_module_getManager (); + if (NULL == manager->doneHead) + { + manager->doneHead = node; + } + else + { + nsfw_module_doneNode_t *tail = manager->doneHead; + while (tail->next) + { + tail = tail->next; + } + + tail->next = node; + } + + return 0; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/init/fw_module.h b/src/framework/init/fw_module.h new file mode 100644 index 0000000..1cfc95f --- /dev/null +++ b/src/framework/init/fw_module.h @@ -0,0 +1,85 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _FW_MODULE +#define _FW_MODULE +#include <pthread.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* _cplusplus */ + +#include "nsfw_init.h" + +/* Unique name declare */ +#define NSFW__STRINGIFY(x) #x +#define NSFW_STRINGIFY(x) NSFW__STRINGIFY(x) + +#define NSFW__PASTE(a,b) a##b +#define NSFW_PASTE(a,b) NSFW__PASTE(a,b) + +#define NSFW_UNIQUE_ID(prefix) NSFW_PASTE(NSFW_PASTE(__LINE__, prefix), __COUNTER__) + +#define NSFW_MODULE_INITFN(_fn) \ + static int _fn(void* param) +extern nsfw_module_depends_t *nsfw_module_create_depends (char *name); + +#define NSFW_MODULE_SET_STATE(inst, state) ((inst)->stat = (state)) + +typedef struct _nsfw_module_doneNode +{ + nsfw_module_instance_t *inst; + struct _nsfw_module_doneNode *next; +} nsfw_module_doneNode_t; + +typedef struct _nsfw_module_manager +{ + pthread_mutex_t initMutex; + int done; // 0 - not finished, 1 - finished, -1 - error + nsfw_module_instance_t *inst; + nsfw_module_doneNode_t *doneHead; +} nsfw_module_manager_t; + +extern int nsfw_module_addDoneNode (nsfw_module_instance_t * inst); + +extern nsfw_module_manager_t g_nsfw_module_manager; +#define nsfw_module_getManager() (&g_nsfw_module_manager) + +#define NSFW_MOUDLE_INSTANCE_POOL_SIZE 64 +#define NSFW_MOUDLE_DEPENDS_POOL_SIZE 128 + +typedef struct _nsfw_module_instance_pool +{ + int last_idx; + nsfw_module_instance_t + module_instance_pool[NSFW_MOUDLE_INSTANCE_POOL_SIZE]; +} nsfw_module_instance_pool_t; + +typedef struct _nsfw_module_depends_pool +{ + int last_idx; + nsfw_module_depends_t module_depends_pool[NSFW_MOUDLE_DEPENDS_POOL_SIZE]; +} nsfw_module_depends_pool_t; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* _cplusplus */ + +#endif /* _FW_MODULE */ diff --git a/src/framework/ipc/mgr_com/mgr_com.c b/src/framework/ipc/mgr_com/mgr_com.c new file mode 100644 index 0000000..4a57d6a --- /dev/null +++ b/src/framework/ipc/mgr_com/mgr_com.c @@ -0,0 +1,2037 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "common_mem_api.h" + +#include "nsfw_mgr_com_api.h" +#include "mgr_com.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" + +#include <sys/un.h> +#include <stddef.h> +#include <sys/epoll.h> +#include <fcntl.h> + +#include "nsfw_maintain_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_fd_timer_api.h" + +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/* *INDENT-OFF* */ + +/* *INDENT-OFF* */ +nsfw_mgr_msg_fun g_mgr_fun[MGR_MSG_MAX][NSFW_MGRCOM_MAX_PROC_FUN]; +nsfw_mgr_init_cfg g_mgr_com_cfg; +nsfw_mgr_sock_map g_mgr_sockt_map = {{0}, NULL}; +nsfw_mgrcom_stat g_mgr_stat; +nsfw_mgrcom_proc g_ep_proc = { 0 }; +/* *INDENT-ON* */ + +u32 g_mgr_sockfdmax = NSFW_MGRCOM_MAX_SOCKET; + +char g_proc_info[NSFW_PROC_MAX][NSTACK_MAX_PROC_NAME_LEN] = { + "", "nStackMain", "nStackMaster", "nStackLib", "nStackTools", "nStackCtrl", + "", "", "", "", "", "", "", "", "", "" +}; + +/* *INDENT-ON* */ + +int g_thread_policy = 0; +int g_thread_pri = 0; + +void +nsfw_com_attr_set (int policy, int pri) +{ + g_thread_policy = policy; + g_thread_pri = pri; +} + +char * +nsfw_get_proc_name (u8 proc_type) +{ + if (proc_type >= NSFW_PROC_MAX || NSFW_PROC_NULL == proc_type) + { + return NULL; + } + + return g_proc_info[proc_type]; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_reg_msg_fun +* Description : reg the callback funciton when receive new message +* Input : u16 msg_type +* nsfw_mgr_msg_fun fun +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_reg_msg_fun (u16 msg_type, nsfw_mgr_msg_fun fun) +{ + u32 i; + if (MGR_MSG_MAX <= msg_type) + { + NSFW_LOGERR ("reg mgr_msg]msg_type=%u,fun=%p", msg_type, fun); + return FALSE; + } + + for (i = 0; i < NSFW_MGRCOM_MAX_PROC_FUN; i++) + { + if (NULL == g_mgr_fun[msg_type][i]) + { + /*TODO should use cas */ + g_mgr_fun[msg_type][i] = fun; + NSFW_LOGINF ("reg mgr_msg fun suc]msg_type=%u,fun=%p", msg_type, + fun); + return TRUE; + } + } + + NSFW_LOGERR ("reg mgr_msg type full]msg_type=%u,fun=%p", msg_type, fun); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_null_rspmsg_alloc +* Description : alloc null response msg for receive message buffer +* Input : None +* Output : None +* Return Value : nsfw_mgr_msg* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_mgr_msg * +nsfw_mgr_null_rspmsg_alloc () +{ + return nsfw_mgr_msg_alloc (MGR_MSG_NULL, NSFW_PROC_NULL); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_msg_alloc +* Description : alloc new request message to send +* Input : u16 msg_type +* u8 dst_proc_type +* Output : None +* Return Value : nsfw_mgr_msg* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_mgr_msg * +nsfw_mgr_msg_alloc (u16 msg_type, u8 dst_proc_type) +{ + nsfw_mgr_msg *p_msg = NULL; + u8 from_mem_flag = FALSE; + u32 alloc_len = sizeof (nsfw_mgr_msg); + + if (MGR_MSG_LAG_QRY_RSP_BEGIN <= msg_type) + { + from_mem_flag = TRUE; + alloc_len = NSFW_MGR_LARGE_MSG_LEN; + } + + if ((NULL == g_mgr_com_cfg.msg_pool) + && (MGR_MSG_INIT_NTY_REQ == msg_type + || MGR_MSG_INIT_NTY_RSP == msg_type)) + { + from_mem_flag = TRUE; + } + + if (FALSE == from_mem_flag) + { + if (0 == + nsfw_mem_ring_dequeue (g_mgr_com_cfg.msg_pool, (void *) &p_msg)) + { + NSFW_LOGERR ("alloc msg full]type=%u,dst=%u", msg_type, + dst_proc_type); + return NULL; + } + alloc_len = sizeof (nsfw_mgr_msg); + } + else + { + p_msg = (nsfw_mgr_msg *) malloc (alloc_len); + } + + if (NULL == p_msg) + { + NSFW_LOGERR ("alloc msg nul]type=%u,dst=%u", msg_type, dst_proc_type); + return NULL; + } + + if (EOK != MEMSET_S (p_msg, alloc_len, 0, alloc_len)) + { + p_msg->from_mem = from_mem_flag; + nsfw_mgr_msg_free (p_msg); + NSFW_LOGERR ("alloc msg MEMSET_S failed]type=%u,dst=%u", msg_type, + dst_proc_type); + return NULL; + } + p_msg->from_mem = from_mem_flag; + + if (msg_type < MGR_MSG_RSP_BASE && msg_type > 0) + { + p_msg->seq = common_mem_atomic32_add_return (&g_mgr_com_cfg.cur_idx, 1); + } + + p_msg->from_mem = from_mem_flag; + p_msg->msg_type = msg_type; + p_msg->src_pid = get_sys_pid (); + p_msg->src_proc_type = g_mgr_com_cfg.proc_type; + p_msg->msg_len = alloc_len; + p_msg->dst_proc_type = dst_proc_type; + p_msg->alloc_flag = TRUE; + p_msg->more_msg_flag = 0; + + g_mgr_stat.msg_alloc++; + return p_msg; +} + +static inline void +lint_lock_1 () +{ + return; +} + +static inline void +lint_unlock_1 () +{ + return; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_rsp_msg_alloc +* Description : alloc response message from request message +* Input : nsfw_mgr_msg* req_msg +* Output : None +* Return Value : nsfw_mgr_msg* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_mgr_msg * +nsfw_mgr_rsp_msg_alloc (nsfw_mgr_msg * req_msg) +{ + nsfw_mgr_msg *p_msg = NULL; + if (NULL == req_msg) + { + NSFW_LOGERR ("req msg nul!"); + return NULL; + } + + p_msg = + nsfw_mgr_msg_alloc (req_msg->msg_type + MGR_MSG_RSP_BASE, + req_msg->src_proc_type); + if (NULL == p_msg) + { + return NULL; + } + + p_msg->dst_pid = req_msg->src_pid; + p_msg->seq = req_msg->seq; + return p_msg; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_msg_free +* Description : message free +* Input : nsfw_mgr_msg *msg +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_msg_free (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + return; + } + + if (FALSE == msg->alloc_flag) + { + NSFW_LOGERR ("msg refree]msg=%p, type=%u", msg, msg->msg_type); + return; + } + + msg->alloc_flag = FALSE; + + if (TRUE == msg->from_mem) + { + if ((MGR_MSG_INIT_NTY_REQ == msg->msg_type + || MGR_MSG_INIT_NTY_RSP == msg->msg_type) + || (MGR_MSG_LAG_QRY_RSP_BEGIN <= msg->msg_type)) + { + free (msg); + g_mgr_stat.msg_free++; + return; + } + NSFW_LOGERR ("msg err free]type=%u", msg->msg_type); + } + + if (0 == nsfw_mem_ring_enqueue (g_mgr_com_cfg.msg_pool, msg)) + { + NSFW_LOGERR ("msg free failed pool full]msg=%p, type=%u", msg, + msg->msg_type); + return; + } + + g_mgr_stat.msg_free++; + return; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_listen_socket +* Description : get domain socket listen fd +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mgr_get_listen_socket () +{ + i32 fd, len; + struct sockaddr_un un; + + if ((fd = nsfw_base_socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + NSFW_LOGERR ("create sock failed!"); + return -1; + } + + if (-1 == unlink ((char *) g_mgr_com_cfg.domain_path)) + { + NSFW_LOGWAR ("unlink failed]error=%d", errno); + } + if (EOK != MEMSET_S (&un, sizeof (un), 0, sizeof (un))) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock MEMSET_S failed!] error=%d", errno); + return -1; + } + + un.sun_family = AF_UNIX; + int retVal = STRCPY_S ((char *) un.sun_path, sizeof (un.sun_path), + (char *) g_mgr_com_cfg.domain_path); + if (EOK != retVal) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock STRCPY_S failed!] error=%d", errno); + return -1; + } + + int rc = nsfw_set_close_on_exec (fd); + if (rc == -1) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", fd, errno); + return -1; + } + + len = + offsetof (struct sockaddr_un, + sun_path) +strlen ((char *) g_mgr_com_cfg.domain_path); + + if (nsfw_base_bind (fd, (struct sockaddr *) &un, len) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("bind failed!]mgr_fd=%d,error=%d", fd, errno); + return -1; + } + + if (nsfw_base_listen (fd, 10) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("listen failed!]mgr_fd=%d,error=%d", fd, errno); + return -1; + } + + NSFW_LOGINF ("mgr com start with]mgr_fd=%d", fd); + return fd; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_connect_socket +* Description : get new connect fd to destination procedure +* Input : u8 proc_type +* u32 host_pid +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mgr_get_connect_socket (u8 proc_type, u32 host_pid) +{ + i32 fd, len; + char *name; + struct sockaddr_un un; + const char *directory = NSFW_DOMAIN_DIR; + const char *home_dir = getenv ("HOME"); + + if (getuid () != 0 && home_dir != NULL) + directory = home_dir; + + switch (proc_type) + { + case NSFW_PROC_MAIN: + name = NSFW_MAIN_FILE; + break; + case NSFW_PROC_MASTER: + name = NSFW_MASTER_FILE; + break; + case NSFW_PROC_ALARM: + directory = "/tmp"; + name = NSFW_ALARM_FILE; + break; + default: + NSFW_LOGERR ("get dst socket err]type=%u,pid=%u", proc_type, host_pid); + return -1; + } + + if ((fd = nsfw_base_socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + NSFW_LOGERR ("create socket err]type=%u,pid=%u,errno=%d", proc_type, + host_pid, errno); + return -1; + } + + if (EOK != MEMSET_S (&un, sizeof (un), 0, sizeof (un))) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("get dst socket err]mgr_fd=%d,type=%u,pid=%u", fd, + proc_type, host_pid); + return -1; + } + + struct timeval tv; + tv.tv_sec = MGR_COM_RECV_TIMEOUT; + tv.tv_usec = 0; + if (nsfw_base_setsockopt + (fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof tv)) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("setsockopt socket err]mgr_fd=%d,type=%u,pid=%u", fd, + proc_type, host_pid); + return -1; + } + + int rc = nsfw_set_close_on_exec (fd); + if (rc == -1) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", fd, errno); + return -1; + } + + int size, size_len; + size = MAX_RECV_BUF_DEF; + size_len = sizeof (size); + if (0 > + nsfw_base_setsockopt (fd, SOL_SOCKET, SO_RCVBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + if (0 > + nsfw_base_setsockopt (fd, SOL_SOCKET, SO_SNDBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + un.sun_family = AF_UNIX;; + int retVal = STRCPY_S ((char *) un.sun_path, sizeof (un.sun_path), + (char *) directory); + if (EOK != retVal) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock STRCPY_S failed!] error=%d", errno); + return -1; + } + + retVal = STRCAT_S (un.sun_path, sizeof (un.sun_path), name); + if (EOK != retVal) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR ("create sock STRCAT_S failed!] error=%d", errno); + return -1; + } + + len = offsetof (struct sockaddr_un, sun_path) +strlen (un.sun_path); + if (nsfw_base_connect (fd, (struct sockaddr *) &un, len) < 0) + { + (void) nsfw_base_close (fd); + NSFW_LOGERR + ("create socket err]mgr_fd=%d,type=%u,pid=%u,errno=%d,path=%s", fd, + proc_type, host_pid, errno, un.sun_path); + return -1; + } + + NSFW_LOGINF ("get dst socket]mgr_fd=%d,type=%u,pid=%u", fd, proc_type, + host_pid); + return (fd); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_new_socket +* Description : management the new fd to cache +* Input : u32 fd +* u8 proc_type +* u32 host_pid +* Output : None +* Return Value : static inline u8 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline u8 +nsfw_mgr_new_socket (i32 fd, u8 proc_type, u32 host_pid) +{ + nsfw_mgr_sock_info *sock_info = NULL; + if (((i32) NSFW_MGR_FD_MAX <= fd) || (fd < 0) || (!g_mgr_sockt_map.sock)) + { + NSFW_LOGERR ("fd err]mgr_fd=%d, sock=%p", fd, g_mgr_sockt_map.sock); + return FALSE; + } + + sock_info = &g_mgr_sockt_map.sock[fd]; + if (host_pid != sock_info->host_pid) + { + NSFW_LOGDBG + ("update sock info]mgr_fd=%d,old_pid=%u,new_pid=%u,type=%u", fd, + sock_info->host_pid, host_pid, proc_type); + } + + sock_info->host_pid = host_pid; + sock_info->proc_type = proc_type; + + if (proc_type < NSFW_PROC_MAX) + { + g_mgr_sockt_map.proc_cache[proc_type] = fd; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_del_socket +* Description : delete the fd from cache when fd close +* Input : u32 fd +* Output : None +* Return Value : static inline u8 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline u8 +nsfw_mgr_del_socket (u32 fd) +{ + nsfw_mgr_sock_info *sock_info = NULL; + if ((NSFW_MGR_FD_MAX <= fd) || (!g_mgr_sockt_map.sock)) + { + NSFW_LOGERR ("fd err]mgr_fd=%u, sock=%p", fd, g_mgr_sockt_map.sock); + return FALSE; + } + + sock_info = &g_mgr_sockt_map.sock[fd]; + + if (sock_info->proc_type < NSFW_PROC_MAX + && fd == g_mgr_sockt_map.proc_cache[sock_info->proc_type]) + { + g_mgr_sockt_map.proc_cache[sock_info->proc_type] = 0; + } + + NSFW_LOGDBG ("del sock]mgr_fd=%u,type=%u,pid=%u", fd, + sock_info->proc_type, sock_info->host_pid); + sock_info->host_pid = 0; + sock_info->proc_type = 0; + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_dst_socket +* Description : get the fd to send message to destination procedure +* Input : u8 proc_type +* u32 dst_pid +* Output : None +* Return Value : static inline i32 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline i32 +nsfw_mgr_get_dst_socket (u8 proc_type, u32 dst_pid) +{ + i32 fd = -1; + + nsfw_mgr_sock_info *sock_info = NULL; + + if (proc_type < NSFW_PROC_MAX) + { + fd = g_mgr_sockt_map.proc_cache[proc_type]; + } + + if (!g_mgr_sockt_map.sock) + { + return -1; + } + + if (fd > 0 && fd < (i32) NSFW_MGR_FD_MAX) + { + sock_info = &g_mgr_sockt_map.sock[fd]; + if (sock_info->host_pid != 0) + { + if (0 == dst_pid || dst_pid == sock_info->host_pid) + { + return fd; + } + } + else if (proc_type == sock_info->proc_type) + { + return fd; + } + } + + i32 i; + for (i = 0; i < (i32) NSFW_MGR_FD_MAX; i++) + { + sock_info = &g_mgr_sockt_map.sock[i]; + if (sock_info->host_pid != 0 && proc_type == sock_info->proc_type) + { + if (0 == dst_pid || dst_pid == sock_info->host_pid) + { + return i; + } + } + } + + return -1; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_get_new_socket +* Description : get new connect +* Input : u8 proc_type +* u32 dst_pid +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_mgr_get_new_socket (u8 proc_type, u32 dst_pid) +{ + i32 fd = 0; + fd = nsfw_mgr_get_connect_socket (proc_type, dst_pid); + if (fd > 0) + { + (void) nsfw_mgr_new_socket (fd, proc_type, dst_pid); + (void) nsfw_mgr_reg_sock_fun (fd, nsfw_mgr_new_msg); + } + return fd; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_clr_fd_lock +* Description : clear the fd lock when fork in child proc +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_clr_fd_lock () +{ + i32 i; + if (!g_mgr_sockt_map.sock) + { + NSFW_LOGERR ("clr fd lock fail, sock is null"); + return FALSE; + } + for (i = 0; i < (i32) NSFW_MGR_FD_MAX; i++) + { + common_mem_spinlock_init (&(g_mgr_sockt_map.sock[i].opr_lock)); + } + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_close_dst_proc +* Description : close the remote connect +* Input : u8 proc_type +* u32 dst_pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_close_dst_proc (u8 proc_type, u32 dst_pid) +{ + i32 fd = nsfw_mgr_get_dst_socket (proc_type, dst_pid); + if (fd > 0) + { + (void) nsfw_mgr_del_socket (fd); + (void) nsfw_mgr_unreg_sock_fun (fd); + (void) nsfw_base_close (fd); + } +} + +/***************************************************************************** +* Prototype : nsfw_mgr_send_msg_socket +* Description : send message to dst fd +* Input : u32 fd +* nsfw_mgr_msg* msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_send_msg_socket (u32 fd, nsfw_mgr_msg * msg) +{ + i32 send_len = 0; + i32 off_set = 0; + + if (NULL == msg) + { + NSFW_LOGERR ("msg nul]mgr_fd=%u", fd); + return FALSE; + } + + if (msg->msg_len < sizeof (nsfw_mgr_msg)) + { + msg->msg_len = sizeof (nsfw_mgr_msg); + } + + if (msg->msg_type == MGR_MSG_LARGE_ALARM_RSP) + { + off_set = NSFW_MGR_MSG_HDR_LEN; + } + + /*TODO if closed by peer, may send failed, should close this fd */ + do + { + off_set += send_len; + send_len = + nsfw_base_send (fd, (char *) msg + off_set, msg->msg_len - off_set, + MSG_NOSIGNAL); + if (send_len <= 0) + { + NSFW_LOGERR + ("send error]mgr_fd=%u,send_len=%d,off_set=%d,errno=%d" MSGINFO, + fd, send_len, off_set, errno, PRTMSG (msg)); + return FALSE; + } + } + while ((send_len + off_set) < (i32) msg->msg_len); + NSFW_LOGDBG ("send mgr_msg suc]mgr_fd=%u," MSGINFO, fd, PRTMSG (msg)); + g_mgr_stat.msg_send[msg->msg_type]++; + return TRUE; +} + +#define MAX_RECV_COUNT 100 + +/***************************************************************************** +* Prototype : nsfw_mgr_recv_msg_socket +* Description : receive new message from fd +* Input : u32 fd +* nsfw_mgr_msg* msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_recv_msg_socket (u32 fd, nsfw_mgr_msg * msg, + nsfw_mgr_msg ** large_msg) +{ + i32 recv_len = 0; + i32 off_set = 0; + u32 msg_len = 0; + i32 max_count = 0; + if (NULL == msg) + { + return FALSE; + } + + u8 from_flag = msg->from_mem; + msg_len = msg->msg_len; + do + { + off_set += recv_len; + recv_len = + nsfw_base_recv (fd, (char *) msg + off_set, msg_len - off_set, 0); + if (recv_len <= 0) + { + if ((EINTR == errno || EAGAIN == errno) + && (max_count < MAX_RECV_COUNT)) + { + recv_len = 0; + max_count++; + continue; + } + + NSFW_LOGERR + ("recv error]mgr_fd=%u,recv_len=%d,off_set=%d,errno=%d," + MSGINFO, fd, recv_len, off_set, errno, PRTMSG (msg)); + msg->from_mem = from_flag; + return FALSE; + } + } + while (recv_len + off_set < (i32) msg_len); + + msg->from_mem = from_flag; + + g_mgr_stat.msg_recv[msg->msg_type]++; + + if (msg->msg_len <= msg_len) + { + NSFW_LOGDBG ("recv mgr_msg suc]mgr_fd=%u," MSGINFO, fd, PRTMSG (msg)); + return TRUE; + } + + if (large_msg == NULL) + { + return TRUE; + } + + nsfw_mgr_msg *l_msg = + nsfw_mgr_msg_alloc (msg->msg_type, msg->dst_proc_type); + if (NULL == l_msg) + { + return TRUE; + } + + if (l_msg->msg_len <= msg_len) + { + NSFW_LOGWAR ("alloc new msg error!]len=%u,org_len=%u,type=%u", + l_msg->msg_len, msg->msg_len, msg->msg_type); + nsfw_mgr_msg_free (l_msg); + return TRUE; + } + + max_count = 0; + (void) nsfw_set_sock_block (fd, FALSE); + from_flag = l_msg->from_mem; + u32 l_msg_len = l_msg->msg_len; + do + { + off_set += recv_len; + recv_len = + nsfw_base_recv (fd, (char *) l_msg + off_set, l_msg_len - off_set, 0); + if (recv_len <= 0) + { + if ((EINTR == errno || EAGAIN == errno) + && (max_count < MAX_RECV_COUNT)) + { + recv_len = 0; + max_count++; + continue; + } + + NSFW_LOGERR + ("recv error]mgr_fd=%u,recv_len=%d,off_set=%d,errno=%d," + MSGINFO, fd, recv_len, off_set, errno, PRTMSG (msg)); + l_msg->from_mem = from_flag; + nsfw_mgr_msg_free (l_msg); + return FALSE; + } + } + while (recv_len + off_set < (i32) l_msg_len); + (void) nsfw_set_sock_block (fd, TRUE); + int retVal = MEMCPY_S (l_msg, msg_len, msg, msg_len); + if (EOK != retVal) + { + NSFW_LOGERR ("MEMCPY_S failed] ret=%d", retVal); + l_msg->from_mem = from_flag; + nsfw_mgr_msg_free (l_msg); + return TRUE; + } + l_msg->from_mem = from_flag; + l_msg->msg_len = l_msg_len; + + *large_msg = l_msg; + NSFW_LOGDBG ("recv large mgr_msg suc]mgr_fd=%u," MSGINFO, fd, + PRTMSG (l_msg)); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_send_req_wait_rsp +* Description : send request message and block waiting for it's response + within MGR_COM_RECV_TIMEOUT +* Input : nsfw_mgr_msg* req_msg +* nsfw_mgr_msg* rsp_msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_send_req_wait_rsp (nsfw_mgr_msg * req_msg, nsfw_mgr_msg * rsp_msg) +{ + if (NULL == req_msg) + { + NSFW_LOGERR ("req msg nul!"); + return FALSE; + } + + i32 dst_socket = + nsfw_mgr_get_dst_socket (req_msg->dst_proc_type, req_msg->dst_pid); + if (dst_socket <= 0) + { + dst_socket = + nsfw_mgr_get_new_socket (req_msg->dst_proc_type, req_msg->dst_pid); + if (dst_socket <= 0) + { + NSFW_LOGERR ("send msg get dst_socket_error]" MSGINFO, + PRTMSG (req_msg)); + return FALSE; + } + } + + if ((NULL == rsp_msg) && (req_msg->msg_len == sizeof (nsfw_mgr_msg))) + { + LOCK_MGR_FD (dst_socket) + if (FALSE == nsfw_mgr_send_msg_socket (dst_socket, req_msg)) + { + NSFW_LOGERR ("send msg error]" MSGINFO, PRTMSG (req_msg)); + g_mgr_stat.msg_send_failed++; + UNLOCK_MGR_FD (dst_socket) return FALSE; + } + UNLOCK_MGR_FD (dst_socket) return TRUE; + } + + LOCK_MGR_FD (dst_socket); + (void) nsfw_mgr_unreg_sock_fun (dst_socket); + if (FALSE == nsfw_mgr_send_msg_socket (dst_socket, req_msg)) + { + NSFW_LOGERR ("send msg error]" MSGINFO, PRTMSG (req_msg)); + g_mgr_stat.msg_send_failed++; + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + UNLOCK_MGR_FD (dst_socket); + return FALSE; + } + + if (NULL == rsp_msg) + { + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + UNLOCK_MGR_FD (dst_socket) return TRUE; + } + + u16 i; + for (i = 0; i < MGR_COM_MAX_DROP_MSG; i++) + { + if (FALSE == nsfw_mgr_recv_msg_socket (dst_socket, rsp_msg, NULL)) + { + NSFW_LOGERR ("recv msg error]" MSGINFO, PRTMSG (req_msg)); + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + UNLOCK_MGR_FD (dst_socket) return FALSE; + } + + if ((rsp_msg->seq == req_msg->seq) + && (rsp_msg->msg_type == req_msg->msg_type + MGR_MSG_RSP_BASE)) + { + break; + } + + NSFW_LOGINF ("recv msg forward]" MSGINFO, PRTMSG (rsp_msg)); + rsp_msg->fw_flag = TRUE; + (void) nsfw_mgr_send_msg (rsp_msg); + } + + (void) nsfw_mgr_reg_sock_fun (dst_socket, nsfw_mgr_new_msg); + if (0 == req_msg->dst_pid) + { + (void) nsfw_mgr_new_socket (dst_socket, rsp_msg->src_proc_type, + rsp_msg->src_pid); + } + UNLOCK_MGR_FD (dst_socket) return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_send_msg +* Description : send message to peer +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_send_msg (nsfw_mgr_msg * msg) +{ + return nsfw_mgr_send_req_wait_rsp (msg, NULL); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_msg_in +* Description : when new domain socket mgr message receive, this function will be call +* Input : i32 fd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_msg_in (i32 fd) +{ + u32 i = 0; + u8 ret = FALSE; + u8 msg_match = FALSE; + nsfw_mgr_msg *msg = nsfw_mgr_null_rspmsg_alloc (); + nsfw_mgr_msg *large_msg = NULL; + + LOCK_MGR_FD (fd) ret = nsfw_mgr_recv_msg_socket (fd, msg, &large_msg); + UNLOCK_MGR_FD (fd) if (large_msg != NULL) + { + nsfw_mgr_msg_free (msg); + msg = large_msg; + } + + if (FALSE == ret) + { + nsfw_mgr_msg_free (msg); + return FALSE; + } + nstack_get_tracing_contex (msg->traceid, 0, 0, -1); + if (msg->fw_flag != TRUE) + { + (void) nsfw_mgr_new_socket (fd, msg->src_proc_type, msg->src_pid); + } + + if (msg->msg_type < MGR_MSG_MAX) + { + for (i = 0; i < NSFW_MGRCOM_MAX_PROC_FUN; i++) + { + if (NULL == g_mgr_fun[msg->msg_type][i]) + { + break; + } + + (void) g_mgr_fun[msg->msg_type][i] (msg); + msg_match = TRUE; + } + } + + if (FALSE != msg_match) + { + nsfw_mgr_msg_free (msg); + nstack_clear_tracing_contex (); + return TRUE; + } + + if (msg->msg_type < MGR_MSG_RSP_BASE) + { + NSFW_LOGERR ("msg match failed! auto rsp]" MSGINFO, PRTMSG (msg)); + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL != rsp_msg) + { + rsp_msg->resp_code = NSFW_MGR_MSG_TYPE_ERROR; + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + } + } + + NSFW_LOGERR ("drop msg]" MSGINFO, PRTMSG (msg)); + /* fix "Out-of-bounds write" type codedex issue */ + if (msg->msg_type < MGR_MSG_MAX) + { + g_mgr_stat.recv_drop[msg->msg_type]++; + } + nsfw_mgr_msg_free (msg); + nstack_clear_tracing_contex (); + return FALSE; + +} + +/***************************************************************************** +* Prototype : nsfw_mgr_new_msg +* Description : when new mgr message recive from socket, this funciton + will call back +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_new_msg (i32 epfd, i32 fd, u32 events) +{ + lint_lock_1 (); + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_mgr_del_socket (fd); + (void) nsfw_mgr_unreg_sock_fun (fd); + (void) nsfw_base_close (fd); + lint_unlock_1 (); + return TRUE; + } + + (void) nsfw_mgr_msg_in (fd); + lint_unlock_1 (); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_rereg_fun +* Description : rereg the error socket +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_com_rereg_fun (u32 timer_type, void *data) +{ + (void) nsfw_mgr_reg_sock_fun (timer_type, (nsfw_mgr_sock_fun) data); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_socket_error +* Description : remove the error fd from ep +* Input : i32 fd +* nsfw_mgr_sock_fun fun +* i32 timer +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_com_socket_error (i32 fd, nsfw_mgr_sock_fun fun, i32 timer) +{ + struct timespec time_left = { timer, 0 }; + nsfw_mgr_unreg_sock_fun (fd); + nsfw_timer_reg_timer (fd, (void *) fun, nsfw_mgr_com_rereg_fun, time_left); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_new_connection +* Description : when new mgr connection in, this funciton will call back +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_new_connection (i32 epfd, i32 fd, u32 events) +{ + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_base_close (fd); + NSFW_LOGWAR ("listen disconnect!]epfd=%d,listen=%d,event=0x%x", epfd, + fd, events); + (void) nsfw_mgr_unreg_sock_fun (fd); + i32 listen_fd = nsfw_mgr_get_listen_socket (); + if (listen_fd < 0) + { + NSFW_LOGERR + ("get listen_fd faied!]epfd=%d,listen_fd=%d,event=0x%x", epfd, + fd, events); + return FALSE; + } + + (void) nsfw_mgr_reg_sock_fun (listen_fd, nsfw_mgr_new_connection); + return TRUE; + } + + struct sockaddr in_addr; + socklen_t in_len; + int infd; + in_len = sizeof in_addr; + + int size, size_len; + u8 accept_flag = FALSE; + while (1) + { + infd = nsfw_base_accept (fd, &in_addr, &in_len); + if (infd == -1) + { + if (FALSE == accept_flag) + { + nsfw_mgr_com_socket_error (fd, nsfw_mgr_new_connection, 1); + } + break; + } + + if (-1 == nsfw_set_close_on_exec (infd)) + { + (void) nsfw_base_close (infd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", infd, errno); + break; + } + + size = MAX_RECV_BUF_DEF; + size_len = sizeof (size); + if (0 > + nsfw_base_setsockopt (infd, SOL_SOCKET, SO_RCVBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + if (0 > + nsfw_base_setsockopt (infd, SOL_SOCKET, SO_SNDBUF, (void *) &size, + (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + (void) nsfw_mgr_reg_sock_fun (infd, nsfw_mgr_new_msg); + NSFW_LOGDBG ("accept_flag new fd]new_mgr_fd=%d", infd); + accept_flag = TRUE; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_set_sock_block +* Description : set fd blok or not for epoll thread +* Input : i32 sock +* u8 flag +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_set_sock_block (i32 sock, u8 flag) +{ + i32 flags; + flags = nsfw_base_fcntl (sock, F_GETFL, 0); + if (flags < 0) + { + NSFW_LOGERR ("fcntl err]new_mgr_fd=%d,errno=%d", sock, errno); + return -1; + } + + if (TRUE == flag) + { + flags = flags | O_NONBLOCK; + } + else + { + flags = flags & (~O_NONBLOCK); + struct timeval tv; + tv.tv_sec = MGR_COM_RECV_TIMEOUT; + tv.tv_usec = 0; + if (nsfw_base_setsockopt + (sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof tv)) + { + NSFW_LOGERR ("setsockopt socket err]mgr_fd=%d", sock); + return -1; + } + } + + if (nsfw_base_fcntl (sock, F_SETFL, flags) < 0) + { + NSFW_LOGERR ("fcntl err]new_mgr_fd=%d,errno=%d,flags=%d", sock, errno, + flags); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_set_close_on_exec +* Description : close on exec set +* Input : i32 sock +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_set_close_on_exec (i32 sock) +{ + i32 flags; + flags = nsfw_base_fcntl (sock, F_GETFD, 0); + if (flags < 0) + { + NSFW_LOGERR ("fcntl err]fd=%d,errno=%d", sock, errno); + return -1; + } + + flags |= FD_CLOEXEC; + + if (nsfw_base_fcntl (sock, F_SETFD, flags) < 0) + { + NSFW_LOGERR ("fcntl err]fd=%d,errno=%d,flags=%d", sock, errno, flags); + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_add_sock_to_ep +* Description : add fd to epoll wait thread +* Input : i32 fd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_add_sock_to_ep (i32 fd) +{ + struct epoll_event event; + event.data.fd = fd; + event.events = EPOLLIN; + if (g_ep_proc.epfd == 0) + { + return TRUE; + } + + (void) nsfw_set_sock_block (fd, TRUE); + + if (0 > nsfw_base_epoll_ctl (g_ep_proc.epfd, EPOLL_CTL_ADD, fd, &event)) + { + NSFW_LOGINF + ("add sock to ep thread failed]mgr_fd=%d,errno=%d,epfd=%d", fd, + errno, g_ep_proc.epfd); + return FALSE; + } + + NSFW_LOGDBG ("add sock to ep thread]mgr_fd=%d,epfd=%d", fd, + g_ep_proc.epfd) return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_rmv_sock_from_ep +* Description : remove fd from epoll thread +* Input : i32 fd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_rmv_sock_from_ep (i32 fd) +{ + struct epoll_event event; + event.data.fd = fd; + event.events = EPOLLIN; + if (g_ep_proc.epfd == 0) + { + return TRUE; + } + + (void) nsfw_set_sock_block (fd, FALSE); + + if (0 > nsfw_base_epoll_ctl (g_ep_proc.epfd, EPOLL_CTL_DEL, fd, &event)) + { + NSFW_LOGINF + ("rmv sock to ep thread failed] mgr_fd=%d,errno=%d,epfd=%d", fd, + errno, g_ep_proc.epfd); + return FALSE; + } + + NSFW_LOGDBG ("rmv sock to ep thread] mgr_fd=%d,epfd=%d", fd, + g_ep_proc.epfd) return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_reg_sock_fun +* Description : reg fd process function to call back when epoll thread + recvice new event of the reg fd +* Input : i32 fd +* nsfw_mgr_sock_fun fun +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_reg_sock_fun (i32 fd, nsfw_mgr_sock_fun fun) +{ + lint_lock_1 (); + if ((fd >= (i32) NSFW_MGR_FD_MAX) || (fd < 0) || NULL == fun) + { + NSFW_LOGINF ("reg sock fun error!] mgr_fd=%d,fun=%p", fd, fun); + lint_unlock_1 (); + return FALSE; + } + + if ((g_ep_proc.ep_fun) && (NULL == g_ep_proc.ep_fun[fd])) + { + g_ep_proc.ep_fun[fd] = fun; + if (FALSE == nsfw_add_sock_to_ep (fd)) + { + g_ep_proc.ep_fun[fd] = NULL; + lint_unlock_1 (); + return FALSE; + } + + NSFW_LOGDBG ("reg sock fun] mgr_fd=%d,fun=%p", fd, fun); + lint_unlock_1 (); + return TRUE; + } + lint_unlock_1 (); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_unreg_sock_fun +* Description : unreg the fd event function +* Input : i32 fd +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_unreg_sock_fun (i32 fd) +{ + lint_lock_1 (); + if (fd >= (i32) NSFW_MGR_FD_MAX) + { + NSFW_LOGINF ("unreg sock fun failed!] mgr_fd=%d", fd); + lint_unlock_1 (); + return; + } + + if ((g_ep_proc.ep_fun) && (NULL != g_ep_proc.ep_fun[fd])) + { + g_ep_proc.ep_fun[fd] = NULL; + (void) nsfw_rmv_sock_from_ep (fd); + NSFW_LOGDBG ("unreg sock fun] mgr_fd=%d", fd); + lint_unlock_1 (); + return; + } + + lint_unlock_1 (); + return; +} + +/***************************************************************************** +* Prototype : nsfw_sock_fun_callback +* Description : call back the event process function +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : static inline u8 +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC inline u8 +nsfw_sock_fun_callback (i32 epfd, i32 fd, u32 events) +{ + if ((fd < (i32) NSFW_MGR_FD_MAX) + && (g_ep_proc.ep_fun) && (NULL != g_ep_proc.ep_fun[fd])) + { + (void) g_ep_proc.ep_fun[fd] (epfd, fd, events); + return TRUE; + } + + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_sock_add_to_ep +* Description : add all event process function has ben reg to the epoll + thread when thread start +* Input : i32 epfd +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_sock_add_to_ep (i32 epfd) +{ + u32 i; + + for (i = 0; i < NSFW_MGR_FD_MAX; i++) + { + if ((g_ep_proc.ep_fun) && (NULL == g_ep_proc.ep_fun[i])) + { + continue; + } + (void) nsfw_add_sock_to_ep (i); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_start +* Description : start mgr com module +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_com_start () +{ + i32 listern_fd = nsfw_mgr_get_listen_socket (); + if (listern_fd < 0) + { + NSFW_LOGERR ("get listern_fd failed!"); + return FALSE; + } + + NSFW_LOGINF ("start mgr_com module!] listern_fd=%d", listern_fd); + (void) nsfw_mgr_reg_sock_fun (listern_fd, nsfw_mgr_new_connection); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_start_local +* Description : start_local_msg_com +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_com_start_local (u8 proc_type) +{ + int fd[2]; + if ((socketpair (AF_UNIX, SOCK_STREAM, 0, fd)) < 0) + { + NSFW_LOGERR ("create socket err] type=%u,errno=%d", proc_type, errno); + return FALSE; + } + + (void) nsfw_mgr_new_socket (fd[0], proc_type, get_sys_pid ()); + (void) nsfw_mgr_new_socket (fd[1], proc_type, get_sys_pid ()); + (void) nsfw_mgr_reg_sock_fun (fd[0], nsfw_mgr_new_msg); + (void) nsfw_mgr_reg_sock_fun (fd[1], nsfw_mgr_new_msg); + NSFW_LOGINF ("create local socket] fd0=%d,fd1=%d", fd[0], fd[1]); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_listen_thread +* Description : epoll thread function +* Input : void* arg +* Output : None +* Return Value : void * +* Calls : +* Called By : +*****************************************************************************/ +void * +nsfw_mgr_listen_thread (void *arg) +{ + i32 epfd = 0; + //i32 listen_socket = 0; + + lint_lock_1 (); +#define MAXEVENTS 10 + epfd = nsfw_base_epoll_create (10); + + struct epoll_event events[MAXEVENTS]; + if (EOK != MEMSET_S (events, sizeof (events), 0, sizeof (events))) + { + NSFW_LOGERR ("MEMSET_S failed!]epfd=%d", epfd); + lint_unlock_1 (); + return NULL; + } + + g_ep_proc.epfd = epfd; + g_ep_proc.hbt_count = 0; + (void) nsfw_sock_add_to_ep (epfd); + lint_unlock_1 (); + while (1) + { + lint_lock_1 (); + int n, i; + n = nsfw_base_epoll_wait (epfd, events, MAXEVENTS, -1); + for (i = 0; i < n; i++) + { + if (TRUE == + nsfw_sock_fun_callback (epfd, events[i].data.fd, + events[i].events)) + { + g_ep_proc.hbt_count = 0; + continue; + } + + NSFW_LOGERR ("error event recv] fd=%d,event=%d", + events[i].data.fd, events[i].events); + } + lint_unlock_1 (); + } + +} + +NSTACK_STATIC inline void +get_thread_policy (pthread_attr_t * attr) +{ + int policy; + int rs = pthread_attr_getschedpolicy (attr, &policy); + if (rs != 0) + { + NSFW_LOGERR ("pthread_attr_getschedpolicy failed"); + return; + } + switch (policy) + { + case SCHED_FIFO: + NSFW_LOGINF ("policy= SCHED_FIFO"); + break; + case SCHED_RR: + NSFW_LOGINF ("policy= SCHED_RR"); + break; + case SCHED_OTHER: + NSFW_LOGINF ("policy=SCHED_OTHER"); + break; + default: + NSFW_LOGINF ("policy=UNKNOWN"); + break; + } + + return; +} + +NSTACK_STATIC inline void +get_thread_priority (pthread_attr_t * attr) +{ + struct sched_param param; + int rs = pthread_attr_getschedparam (attr, ¶m); + if (rs != 0) + { + NSFW_LOGERR ("pthread_attr_getschedparam failed"); + return; + } + + NSFW_LOGINF ("get thread priority] pri=%d", param.sched_priority); +} + +/* support thread priority configuration */ +void +set_thread_attr (pthread_attr_t * pattr, int stacksize, int pri, int policy) +{ + struct sched_param param; + (void) pthread_attr_init (pattr); + + if (stacksize > 0) + { + (void) pthread_attr_setstacksize (pattr, stacksize); + } + + param.sched_priority = pri; + if (SCHED_OTHER != policy) + { + (void) pthread_attr_setschedpolicy (pattr, policy); + (void) pthread_attr_setschedparam (pattr, ¶m); + (void) pthread_attr_setinheritsched (pattr, PTHREAD_EXPLICIT_SCHED); + } + get_thread_policy (pattr); + get_thread_priority (pattr); +} + +/***************************************************************************** +* Prototype : nsfw_mgr_ep_start +* Description : start epoll thread +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_mgr_ep_start () +{ + /* heart beat thread should have the same priority with the tcpip thread */ + pthread_attr_t attr; + pthread_attr_t *pattr = NULL; + + if (g_thread_policy != SCHED_OTHER) + { + set_thread_attr (&attr, 0, g_thread_pri, g_thread_policy); + pattr = &attr; + } + + if (pthread_create + (&g_ep_proc.ep_thread, pattr, nsfw_mgr_listen_thread, NULL)) + { + return FALSE; + } + + NSFW_LOGINF ("start thread] id=%d", g_ep_proc.ep_thread); + + if (pthread_setname_np (g_ep_proc.ep_thread, NSFW_MGRCOM_THREAD)) + { + return TRUE; + } + (void) nsfw_reg_trace_thread (g_ep_proc.ep_thread); + return TRUE; +} + +int +nsfw_mgr_com_chk_hbt (int v_add) +{ + int ret = g_ep_proc.hbt_count; + g_ep_proc.hbt_count += v_add; + return ret; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_comm_fd_destroy +* Description : free the memeory +* Input : +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_mgr_comm_fd_destroy () +{ + if (g_ep_proc.ep_fun) + { + free (g_ep_proc.ep_fun); + g_ep_proc.ep_fun = NULL; + } + if (g_mgr_sockt_map.sock) + { + free (g_mgr_sockt_map.sock); + g_mgr_sockt_map.sock = NULL; + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_comm_fd_init +* Description : fd map and socket info init +* Input : u32 proc_type +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mgr_comm_fd_init (u32 proc_type) +{ + /*only app need to do this */ + if ((g_mgr_sockt_map.sock) && (g_ep_proc.ep_fun)) + { + return 0; + } + if (NSFW_PROC_APP == proc_type) + { + long sysfdmax = 0; + sysfdmax = sysconf (_SC_OPEN_MAX); + NSFW_LOGINF ("] sys max open files=%d", sysfdmax); + if (sysfdmax > 0) + { + NSFW_MGR_FD_MAX = + (int) ((sysfdmax <= + NSFW_MGRCOM_MAX_SOCKET * + 60) ? sysfdmax : NSFW_MGRCOM_MAX_SOCKET * 60); + } + else + { + NSFW_LOGERR ("get sys max open file fail"); + NSFW_MGR_FD_MAX = NSFW_MGRCOM_MAX_SOCKET; + } + } + NSFW_LOGINF ("] final max fd=%d", NSFW_MGR_FD_MAX); + if (!g_mgr_sockt_map.sock) + { + g_mgr_sockt_map.sock = + (nsfw_mgr_sock_info *) malloc (sizeof (nsfw_mgr_sock_info) * + NSFW_MGR_FD_MAX); + if (NULL == g_mgr_sockt_map.sock) + { + NSFW_LOGERR ("malloc fail] length=%d", + sizeof (nsfw_mgr_sock_info) * NSFW_MGR_FD_MAX); + return -1; + } + (void) MEMSET_S (g_mgr_sockt_map.sock, + sizeof (nsfw_mgr_sock_info) * NSFW_MGR_FD_MAX, 0, + sizeof (nsfw_mgr_sock_info) * NSFW_MGR_FD_MAX); + } + if (!g_ep_proc.ep_fun) + { + g_ep_proc.ep_fun = + (nsfw_mgr_sock_fun *) malloc (sizeof (nsfw_mgr_sock_fun) * + NSFW_MGR_FD_MAX); + if (NULL == g_ep_proc.ep_fun) + { + NSFW_LOGERR ("malloc fail] length=%d ", + sizeof (nsfw_mgr_sock_fun) * NSFW_MGR_FD_MAX); + return -1; + } + (void) MEMSET_S (g_ep_proc.ep_fun, + sizeof (nsfw_mgr_sock_fun) * NSFW_MGR_FD_MAX, 0, + sizeof (nsfw_mgr_sock_fun) * NSFW_MGR_FD_MAX); + } + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_com_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int nsfw_mgr_com_module_init (void *param); +int +nsfw_mgr_com_module_init (void *param) +{ + lint_lock_1 (); + u32 proc_type = (u32) ((long long) param); + nsfw_mgr_init_cfg *mgr_cfg = &g_mgr_com_cfg; + const char *directory = NSFW_DOMAIN_DIR; + const char *home_dir = getenv ("HOME"); + + NSFW_LOGINF ("module mgr init] type=%u", proc_type); + + if (getuid () != 0 && home_dir != NULL) + directory = home_dir; + + if (0 != nsfw_mgr_comm_fd_init (proc_type)) + { + NSFW_LOGERR ("fd init fail] proc_type=%u", proc_type); + lint_unlock_1 (); + return -1; + } + + switch (proc_type) + { + case NSFW_PROC_MAIN: + /* modify destMax, remove "-1" */ + if (EOK != + STRCPY_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, directory)) + { + NSFW_LOGERR ("module mgr init STRCPY_S failed!"); + lint_unlock_1 (); + return -1; + } + + /* modify destMax, remove "-1" */ + if (EOK != + STRCAT_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, + NSFW_MAIN_FILE)) + { + NSFW_LOGERR ("module mgr init STRCAT_S failed!"); + lint_unlock_1 (); + return -1; + } + + NSFW_LOGINF ("module mgr init]NSFW_PROC_MAIN domain_path=%s", + mgr_cfg->domain_path); + + if (TRUE != nsfw_mgr_com_start ()) + { + NSFW_LOGERR ("module mgr nsfw_mgr_com_start failed!"); + lint_unlock_1 (); + return -1; + } + + break; + case NSFW_PROC_MASTER: + /* modify destMax, remove "-1" */ + if (EOK != + STRCPY_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, directory)) + { + NSFW_LOGERR ("module mgr init STRCPY_S failed!"); + lint_unlock_1 (); + return -1; + } + + /* modify destMax, remove "-1" */ + if (EOK != + STRCAT_S (mgr_cfg->domain_path, NSFW_MGRCOM_PATH_LEN, + NSFW_MASTER_FILE)) + { + NSFW_LOGERR ("module mgr init STRCAT_S failed!"); + lint_unlock_1 (); + return -1; + } + + NSFW_LOGINF ("module mgr init]NSFW_PROC_MASTER domain_path=%s", + mgr_cfg->domain_path); + + if (TRUE != nsfw_mgr_com_start ()) + { + NSFW_LOGERR ("module mgr nsfw_mgr_com_start failed!"); + lint_unlock_1 (); + return -1; + } + + break; + case NSFW_PROC_TOOLS: + break; + case NSFW_PROC_CTRL: + if (TRUE != nsfw_mgr_com_start_local (proc_type)) + { + NSFW_LOGERR ("module mgr nsfw_mgr_com_start_local failed!"); + lint_unlock_1 (); + return -1; + } + break; + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + lint_unlock_1 (); + return -1; + } + + mgr_cfg->msg_size = MGR_COM_MSG_COUNT_DEF; + mgr_cfg->max_recv_timeout = MGR_COM_RECV_TIMEOUT_DEF; + mgr_cfg->max_recv_drop_msg = MGR_COM_MAX_DROP_MSG_DEF; + + mgr_cfg->proc_type = proc_type; + + nsfw_mem_sppool pmpinfo; + if (EOK != MEMSET_S (&pmpinfo, sizeof (pmpinfo), 0, sizeof (pmpinfo))) + { + NSFW_LOGERR ("Error to memset!!!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + + pmpinfo.enmptype = NSFW_MRING_MPMC; + pmpinfo.usnum = mgr_cfg->msg_size; + pmpinfo.useltsize = sizeof (nsfw_mgr_msg); + pmpinfo.isocket_id = NSFW_SOCKET_ANY; + pmpinfo.stname.entype = NSFW_NSHMEM; + if (-1 == + SPRINTF_S (pmpinfo.stname.aname, sizeof (pmpinfo.stname.aname), "%s", + "MS_MGR_MSGPOOL")) + { + NSFW_LOGERR ("Error to SPRINTF_S!!!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + + mgr_cfg->msg_pool = nsfw_mem_sp_create (&pmpinfo); + + if (!mgr_cfg->msg_pool) + { + NSFW_LOGERR ("module mgr init msg_pool alloc failed!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + + (void) MEM_STAT (NSFW_MGR_COM_MODULE, pmpinfo.stname.aname, NSFW_NSHMEM, + nsfw_mem_get_len (mgr_cfg->msg_pool, NSFW_MEM_SPOOL)); + + if ((NSFW_PROC_TOOLS == proc_type) + || (NSFW_PROC_CTRL == proc_type) || (NSFW_PROC_MAIN == proc_type)) + { + if (TRUE != nsfw_mgr_ep_start ()) + { + NSFW_LOGERR ("module mgr nsfw_mgr_ep_start failed!"); + nsfw_mgr_comm_fd_destroy (); + lint_unlock_1 (); + return -1; + } + } + lint_unlock_1 (); + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_mgr_run_script +* Description : run a linux shell script +* Input : const char *cmd, char *result, int result_buf_len +* Output : result length +* Return Value : int +* Calls : +* Called By : + *****************************************************************************/ +int +nsfw_mgr_run_script (const char *cmd, char *result, int result_buf_len) +{ + if (!cmd || !result || result_buf_len <= 1) + { + return -1; + } + + FILE *fp = popen (cmd, "r"); + if (fp != NULL) + { + size_t n = fread (result, sizeof (char), result_buf_len - 1, fp); + if (n == 0) + { + result[0] = '\0'; + } + else if ('\n' == result[n - 1]) + { + result[n - 1] = '\0'; + } + else + { + result[n] = '\0'; + } + + pclose (fp); + return n; + } + + return -1; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME(NSFW_MGR_COM_MODULE) +NSFW_MODULE_PRIORITY(10) +NSFW_MODULE_DEPENDS(NSFW_MEM_MGR_MODULE) +NSFW_MODULE_INIT(nsfw_mgr_com_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/mgr_com/mgr_com.h b/src/framework/ipc/mgr_com/mgr_com.h new file mode 100644 index 0000000..c4333a1 --- /dev/null +++ b/src/framework/ipc/mgr_com/mgr_com.h @@ -0,0 +1,150 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/***************************************************************************** +* Prototype : ifndef _NSFW_MGRCOM_MODULE_H +* Description : mgr com module definition +* Input : None +* Output : None +* Return Value : # +* Calls : +* Called By : + *****************************************************************************/ +#ifndef _NSFW_MGRCOM_MODULE_H +#define _NSFW_MGRCOM_MODULE_H + +#include "pthread.h" +#include "nsfw_mem_api.h" +#include "common_mem_api.h" + +#include "common_func.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_MGRCOM_PATH_LEN 128 +#define NSFW_MGRCOM_MAX_SOCKET 1024 +#define NSFW_MGRCOM_MAX_PROC_FUN 8 + +#define MAX_RECV_BUF_DEF 0x34000*2 + +#define MGR_COM_MSG_COUNT_DEF 1023 /*g_mgr_com_cfg */ +#define MGR_COM_RECV_TIMEOUT_DEF 5 +#define MGR_COM_MAX_DROP_MSG_DEF 1024 + +#define MGR_COM_MSG_COUNT (g_mgr_com_cfg.msg_size) +#define MGR_COM_RECV_TIMEOUT (g_mgr_com_cfg.max_recv_timeout) +#define MGR_COM_MAX_DROP_MSG (g_mgr_com_cfg.max_recv_drop_msg) + +#define NSFW_MAIN_FILE "/ip_module/nStackMainMgr" +#define NSFW_MASTER_FILE "/ip_module/nStackMasterMgr" +#define NSFW_ALARM_FILE "/HuskyAlarm.domain" + +#define NSFW_MGRCOM_THREAD "nStackMgrCom" + +typedef struct _nsfw_mgr_init_cfg +{ + u8 proc_type; /*fw_poc_type */ + u8 max_recv_timeout; + u16 max_recv_drop_msg; + u32 msg_size; + common_mem_atomic32_t cur_idx; + u64 u64reserve; + mring_handle msg_pool; + char domain_path[NSFW_MGRCOM_PATH_LEN]; +} nsfw_mgr_init_cfg; + +typedef struct _nsfw_mgrcom_stat +{ + u64 msg_send[MGR_MSG_MAX]; + u64 msg_recv[MGR_MSG_MAX]; + u64 recv_drop[MGR_MSG_MAX]; + u64 msg_alloc; + u64 msg_free; + u64 msg_send_failed; + u64 reconnect_count; +} nsfw_mgrcom_stat; + +typedef struct _nsfw_mgr_sock_info +{ + u8 proc_type; /*_ns_poc_type*/ + u32 host_pid; + common_mem_spinlock_t opr_lock; +} nsfw_mgr_sock_info; + +typedef struct _nsfw_mgr_sock_map +{ + i32 proc_cache[NSFW_PROC_MAX]; + nsfw_mgr_sock_info *sock; +} nsfw_mgr_sock_map; + +#define NSFW_SOCK_MAX_PROC_FUN 4 + +typedef struct _nsfw_mgrcom_proc_fun +{ + i32 fd; + nsfw_mgr_sock_fun fun; +} nsfw_mgrcom_proc_fun; + +typedef struct _nsfw_mgrcom_proc +{ + i32 epfd; + u32 hbt_count; + pthread_t ep_thread; + nsfw_mgr_sock_fun *ep_fun; +} nsfw_mgrcom_proc; + +i32 nsfw_set_sock_block (i32 sock, u8 flag); + +u8 nsfw_rmv_sock_from_ep (i32 fd); +u8 nsfw_add_sock_to_ep (i32 fd); + +int nsfw_mgr_new_msg (i32 epfd, i32 socket, u32 events); + +u8 nsfw_mgr_ep_start (); +u8 nsfw_mgr_stop (); + +#define LOCK_MGR_FD(_fd){\ + if ((i32)NSFW_MGR_FD_MAX > _fd)\ + {\ + common_mem_spinlock_lock(&g_mgr_sockt_map.sock[_fd].opr_lock);\ + }\ +} + +#define UNLOCK_MGR_FD(_fd){\ + if ((i32)NSFW_MGR_FD_MAX > _fd)\ + {\ + common_mem_spinlock_unlock(&g_mgr_sockt_map.sock[_fd].opr_lock);\ + }\ +} + +#define NSFW_MGR_FD_MAX g_mgr_sockfdmax + +extern void set_thread_attr (pthread_attr_t * pattr, int stacksize, int pri, + int policy); + +extern void nsfw_com_attr_set (int policy, int pri); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_MGRCOM_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_fd_timer.c b/src/framework/ipc/ps/nsfw_fd_timer.c new file mode 100644 index 0000000..57535a3 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_fd_timer.c @@ -0,0 +1,378 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <sys/timerfd.h> + +#include "types.h" +#include "list.h" + +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_TIMER_CYCLE 1 +#define NSFW_TIMER_INFO_MAX_COUNT_DEF 8191 +#define NSFW_TIMER_INFO_MAX_COUNT (g_timer_cfg.timer_info_size) +/* *INDENT-OFF* */ +nsfw_timer_init_cfg g_timer_cfg; + +u8 g_hbt_switch = FALSE; +/* *INDENT-ON* */ + +/***************************************************************************** +* Prototype : nsfw_timer_reg_timer +* Description : reg timer with callback function when timeout +* Input : u32 timer_type +* void* data +* nsfw_timer_proc_fun fun +* struct timespec time_left +* Output : None +* Return Value : nsfw_timer_info* +* Calls : +* Called By : +* +*****************************************************************************/ +nsfw_timer_info * +nsfw_timer_reg_timer (u32 timer_type, void *data, + nsfw_timer_proc_fun fun, struct timespec time_left) +{ + nsfw_timer_info *tm_info = NULL; + if (0 == + nsfw_mem_ring_dequeue (g_timer_cfg.timer_info_pool, (void *) &tm_info)) + { + NSFW_LOGERR ("dequeue error]data=%p,fun=%p", data, fun); + return NULL; + } + + if (EOK != MEMSET_S (tm_info, sizeof (*tm_info), 0, sizeof (*tm_info))) + { + if (0 == nsfw_mem_ring_enqueue (g_timer_cfg.timer_info_pool, tm_info)) + { + NSFW_LOGERR ("enqueue error]data=%p,fun=%p", data, fun); + } + NSFW_LOGERR ("mem set error]data=%p,fun=%p", data, fun); + return NULL; + } + + tm_info->fun = fun; + tm_info->argv = data; + tm_info->time_left = time_left; + //tm_info->time_left.tv_sec += NSFW_TIMER_CYCLE; + tm_info->timer_type = timer_type; + list_add_tail (&tm_info->node, &g_timer_cfg.timer_head); + tm_info->alloc_flag = TRUE; + return tm_info; +} + +/***************************************************************************** +* Prototype : nsfw_timer_rmv_timer +* Description : stop timer +* Input : nsfw_timer_info* tm_info +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_timer_rmv_timer (nsfw_timer_info * tm_info) +{ + if (NULL == tm_info) + { + NSFW_LOGWAR ("tm_info nul"); + return; + } + + if (FALSE == tm_info->alloc_flag) + { + NSFW_LOGERR ("tm_info refree]tm_info=%p,argv=%p,fun=%p", tm_info, + tm_info->argv, tm_info->fun); + return; + } + + tm_info->alloc_flag = FALSE; + list_del (&tm_info->node); + if (0 == nsfw_mem_ring_enqueue (g_timer_cfg.timer_info_pool, tm_info)) + { + NSFW_LOGERR ("tm_info free failed]tm_info=%p,argv=%p,fun=%p", tm_info, + tm_info->argv, tm_info->fun); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_timer_exp +* Description : timer expire +* Input : u64 count +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_timer_exp (u64 count) +{ + nsfw_timer_info *tm_info = NULL; + struct list_head *tNode; + struct list_head *tPretNode; + + LINT_LIST ()list_for_each_entry (tm_info, tNode, (&g_timer_cfg.timer_head), + node) + { + tPretNode = tm_info->node.prev; + if (tm_info->time_left.tv_sec > (long) count * NSFW_TIMER_CYCLE) + { + tm_info->time_left.tv_sec -= count * NSFW_TIMER_CYCLE; + continue; + } + + list_del (&tm_info->node); + list_add_tail (&tm_info->node, &g_timer_cfg.exp_timer_head); + tNode = tPretNode; + } + + u32 i = 0; + while (!list_empty (&g_timer_cfg.exp_timer_head) + && i++ < NSFW_TIMER_INFO_MAX_COUNT) + { + tm_info = + (nsfw_timer_info *) list_get_first (&g_timer_cfg.exp_timer_head); + if (NULL != tm_info->fun) + { + (void) tm_info->fun (tm_info->timer_type, tm_info->argv); + } + nsfw_timer_rmv_timer (tm_info); + } + +} + +/***************************************************************************** +* Prototype : nsfw_get_timer_socket +* Description : get timer socket from kernel +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_get_timer_socket () +{ + i32 tfd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK); + if (tfd == -1) + { + NSFW_LOGERR ("timerfd_create failed!]errno=%d\n", errno); + return -1; + } + + /* close on exe */ + if (-1 == nsfw_set_close_on_exec (tfd)) + { + (void) nsfw_base_close (tfd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", tfd, errno); + return -1; + } + + struct itimerspec ts; + ts.it_interval.tv_sec = NSFW_TIMER_CYCLE; + ts.it_interval.tv_nsec = 0; + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = NSFW_TIMER_CYCLE; + + if (timerfd_settime (tfd, 0, &ts, NULL) < 0) + { + NSFW_LOGERR ("timerfd_settime failed] errno=%d", errno); + close (tfd); + return -1; + } + + return tfd; +} + +/***************************************************************************** +* Prototype : nsfw_timer_notify_fun +* Description : receive timer event from kernel +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_timer_notify_fun (i32 epfd, i32 fd, u32 events) +{ + i32 rc; + + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_base_close (fd); + NSFW_LOGWAR ("timer disconnect!]epfd=%d,timer=%d,event=0x%x", epfd, + fd, events); + + (void) nsfw_mgr_unreg_sock_fun (fd); + i32 timer_fd = nsfw_get_timer_socket (); + if (timer_fd < 0) + { + NSFW_LOGERR ("get timer_fd faied!]epfd=%d,timer_fd=%d,event=0x%x", + epfd, fd, events); + return FALSE; + } + + (void) nsfw_mgr_reg_sock_fun (timer_fd, nsfw_timer_notify_fun); + return TRUE; + } + + u64 data; + while (1) + { + rc = nsfw_base_read (fd, &data, sizeof (data)); + if (rc == 0) + { + NSFW_LOGERR ("timer_fd recv 0]timer_fd=%d,errno=%d", fd, errno); + break; + } + else if (rc == -1) + { + if (errno == EINTR || errno == EAGAIN) + { + break; + } + NSMON_LOGERR ("timer_fd recv]timer_fd=%d,errno=%d", fd, errno); + break; + } + + nsfw_timer_exp (data); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_timer_start +* Description : reg the timer module to epoll thread +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +u8 +nsfw_timer_start () +{ + i32 timer_fd = nsfw_get_timer_socket (); + if (timer_fd < 0) + { + NSFW_LOGERR ("get timer_fd failed!"); + return FALSE; + } + + NSFW_LOGINF ("start timer_fd module!]timer_fd=%d", timer_fd); + (void) nsfw_mgr_reg_sock_fun (timer_fd, nsfw_timer_notify_fun); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_timer_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +nsfw_timer_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + nsfw_timer_init_cfg *timer_cfg = &g_timer_cfg; + NSFW_LOGINF ("ps module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MASTER: + case NSFW_PROC_MAIN: + (void) NSFW_REG_SOFT_INT (NSFW_DBG_MODE_PARAM, g_hbt_switch, 0, 1); + break; + case NSFW_PROC_TOOLS: + case NSFW_PROC_CTRL: + break; + default: + return 0; + } + + timer_cfg->timer_info_size = NSFW_TIMER_INFO_MAX_COUNT_DEF; + + nsfw_mem_sppool pmpinfo; + pmpinfo.enmptype = NSFW_MRING_MPMC; + pmpinfo.usnum = timer_cfg->timer_info_size; + pmpinfo.useltsize = sizeof (nsfw_timer_info); + pmpinfo.isocket_id = NSFW_SOCKET_ANY; + pmpinfo.stname.entype = NSFW_NSHMEM; + if (-1 == + SPRINTF_S (pmpinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + "MS_TM_INFOPOOL")) + { + NSFW_LOGERR ("SPRINTF_S failed"); + return -1; + } + timer_cfg->timer_info_pool = nsfw_mem_sp_create (&pmpinfo); + + if (!timer_cfg->timer_info_pool) + { + NSFW_LOGERR ("alloc timer info pool_err"); + return -1; + } + + MEM_STAT (NSFW_TIMER_MODULE, pmpinfo.stname.aname, NSFW_NSHMEM, + nsfw_mem_get_len (timer_cfg->timer_info_pool, NSFW_MEM_SPOOL)); + + INIT_LIST_HEAD (&(timer_cfg->timer_head)); + INIT_LIST_HEAD (&(timer_cfg->exp_timer_head)); + + (void) nsfw_timer_start (); + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_TIMER_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_MGR_COM_MODULE) +NSFW_MODULE_INIT (nsfw_timer_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_ps_mem_module.c b/src/framework/ipc/ps/nsfw_ps_mem_module.c new file mode 100644 index 0000000..9cda6b3 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_mem_module.c @@ -0,0 +1,924 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nsfw_ps_module.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_ps_mem_api.h" +#include "nsfw_ps_mem_module.h" +#include "nsfw_ps_api.h" +#include "nsfw_maintain_api.h" +#include "nsfw_fd_timer_api.h" + +#include "nstack_log.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +ns_mem_mng_init_cfg g_mem_cfg; + +int mem_ps_exiting (void *pps_info, void *argv); + +int +nsfw_mem_ps_exit_resend_timeout (u32 timer_type, void *data) +{ + nsfw_ps_info *ps_info = data; + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (NSFW_PROC_APP != ps_info->proc_type) + { + return FALSE; + } + + if (NSFW_PS_EXITING != ps_info->state) + { + return FALSE; + } + + ps_info->resend_timer_ptr = NULL; + (void) mem_ps_exiting (ps_info, NULL); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_ps_exiting +* Description : send exiting message when ps_info exiting +* Input : void *pps_info +* void* argv +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_ps_exiting (void *pps_info, void *argv) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (TRUE == NSFW_SRV_STATE_SUSPEND) + { + NSFW_LOGERR ("main suspend]ps_info=%d,pid=%u", pps_info, + ((nsfw_ps_info *) pps_info)->host_pid); + return FALSE; + } + + nsfw_mgr_msg *msg = + nsfw_mgr_msg_alloc (MGR_MSG_APP_EXIT_REQ, NSFW_PROC_MAIN); + if (NULL == msg) + { + NSFW_LOGERR ("ps_exit alloc msg failed]ps_info=%p,pid=%u", pps_info, + ((nsfw_ps_info *) pps_info)->host_pid); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + ps_msg->host_pid = ((nsfw_ps_info *) pps_info)->host_pid; + + (void) nsfw_mgr_send_msg (msg); + NSFW_LOGINF ("ps_exiting send msg]ps_info=%p,pid=%u", pps_info, + ps_msg->host_pid); + nsfw_mgr_msg_free (msg); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_alloc_ps_info +* Description : alloc ps_info +* Input : u32 pid +* u8 proc_type +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_alloc_ps_info (u32 pid, u8 proc_type) +{ + nsfw_ps_info *pps_info = NULL; + pps_info = nsfw_ps_info_get (pid); + if (NULL != pps_info) + { + return TRUE; + } + + pps_info = nsfw_ps_info_alloc (pid, proc_type); + if (NULL == pps_info) + { + NSFW_LOGERR ("alloc ps_info falied!]pid=%u,proc_type=%u", pid, + proc_type); + return FALSE; + } + + NSFW_LOGINF ("alloc new ps_info]pps_info=%p,pid=%u", pps_info, pid); + return TRUE; +} + +/*mem alloc by msg begin*/ +void * +mem_item_zone_create (void *mem_info) +{ + return (void *) nsfw_mem_zone_create ((nsfw_mem_zone *) mem_info); +} + +void * +mem_item_mbfmp_create (void *mem_info) +{ + return (void *) nsfw_mem_mbfmp_create ((nsfw_mem_mbfpool *) mem_info); +} + +void * +mem_item_sp_create (void *mem_info) +{ + return (void *) nsfw_mem_sp_create ((nsfw_mem_sppool *) mem_info); +} + +void * +mem_item_ring_create (void *mem_info) +{ + return (void *) nsfw_mem_ring_create ((nsfw_mem_mring *) mem_info); +} + +nsfw_ps_mem_item_cfg g_ps_mem_map[] = { + { + NSFW_RESERV_REQ_MSG, + sizeof (nsfw_shmem_reserv_req), + NSFW_MEM_MZONE, + mem_item_zone_create, + mem_item_get_callargv} + , + + { + NSFW_MBUF_REQ_MSG, + sizeof (nsfw_shmem_mbuf_req), + NSFW_MEM_MBUF, + mem_item_mbfmp_create, + mem_item_get_callargv} + , + { + NSFW_SPPOOL_REQ_MSG, + sizeof (nsfw_shmem_sppool_req), + NSFW_MEM_SPOOL, + mem_item_sp_create, + mem_item_get_callargv} + , + { + NSFW_RING_REQ_MSG, + sizeof (nsfw_shmem_ring_req), + NSFW_MEM_RING, + mem_item_ring_create, + mem_item_get_callargv} + , + { + NSFW_RELEASE_REQ_MSG, + sizeof (nsfw_shmem_free_req), + 0xFFFF, + mem_item_free, + mem_item_get_callargv, + } + , + { + NSFW_MEM_LOOKUP_REQ_MSG, + sizeof (nsfw_shmem_lookup_req), + 0xFFFF, + mem_item_lookup, + mem_item_get_callargv, + } +}; + +/***************************************************************************** +* Prototype : mem_item_get_cfg_from_msg +* Description : get memory config +* Input : u16 msg_type +* Output : None +* Return Value : nsfw_ps_mem_item_cfg * +* Calls : +* Called By : +*****************************************************************************/ +nsfw_ps_mem_item_cfg * +mem_item_get_cfg_from_msg (u16 msg_type) +{ + int idx; + int map_count = sizeof (g_ps_mem_map) / sizeof (nsfw_ps_mem_item_cfg); + for (idx = 0; idx < map_count; idx++) + { + if (g_ps_mem_map[idx].usmsg_type == msg_type) + { + return &g_ps_mem_map[idx]; + } + } + + return NULL; +} + +/***************************************************************************** +* Prototype : mem_item_get_callargv +* Description : change the message value to structur value +* Input : u16 msg_type +* char* msg_body +* char *memstr_buf +* i32 buf_len +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_item_get_callargv (u16 msg_type, char *msg_body, char *memstr_buf, + i32 buf_len) +{ + switch (msg_type) + { + case NSFW_RESERV_REQ_MSG: + MEM_GET_CALLARGV (lenth, lenth, nsfw_mem_zone, nsfw_shmem_reserv_req, + memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_zone, + nsfw_shmem_reserv_req, memstr_buf, msg_body); + break; + case NSFW_MBUF_REQ_MSG: + MEM_GET_CALLARGV (usnum, usnum, nsfw_mem_mbfpool, nsfw_shmem_mbuf_req, + memstr_buf, msg_body); + MEM_GET_CALLARGV (uscash_size, uscash_size, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (uspriv_size, uspriv_size, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (usdata_room, usdata_room, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (enmptype, enmptype, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_mbfpool, + nsfw_shmem_mbuf_req, memstr_buf, msg_body); + break; + case NSFW_SPPOOL_REQ_MSG: + MEM_GET_CALLARGV (usnum, usnum, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (useltsize, useltsize, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (enmptype, enmptype, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_sppool, + nsfw_shmem_sppool_req, memstr_buf, msg_body); + break; + case NSFW_RING_REQ_MSG: + MEM_GET_CALLARGV (usnum, usnum, nsfw_mem_mring, nsfw_shmem_ring_req, + memstr_buf, msg_body); + MEM_GET_CALLARGV (enmptype, enmptype, nsfw_mem_mring, + nsfw_shmem_ring_req, memstr_buf, msg_body); + MEM_GET_CALLARGV (isocket_id, isocket_id, nsfw_mem_mring, + nsfw_shmem_ring_req, memstr_buf, msg_body); + break; + case NSFW_RELEASE_REQ_MSG: + MEM_GET_CALLARGV (ustype, ustype, nsfw_mem_type_info, + nsfw_shmem_free_req, memstr_buf, msg_body); + break; + case NSFW_MEM_LOOKUP_REQ_MSG: + MEM_GET_CALLARGV (ustype, ustype, nsfw_mem_type_info, + nsfw_shmem_lookup_req, memstr_buf, msg_body); + break; + default: + NSFW_LOGERR ("error msg]type=%u", msg_type); + return FALSE; + } + if (EOK != + STRCPY_S (((nsfw_mem_zone *) memstr_buf)->stname.aname, + NSFW_MEM_NAME_LENTH, + ((nsfw_shmem_reserv_req *) msg_body)->aname)) + { + NSFW_LOGERR ("STRCPY_S failed]msg_type=%u", msg_type); + return FALSE; + } + + ((nsfw_mem_zone *) memstr_buf)->stname.entype = NSFW_SHMEM; + + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_item_free +* Description : free memory item +* Input : void *pdata +* Output : None +* Return Value : void* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_item_free (void *pdata) +{ + nsfw_mem_type_info *mem_free = (nsfw_mem_type_info *) pdata; + i32 ret; + NSFW_LOGINF ("free mem]type=%u,name=%s", mem_free->ustype, + mem_free->stname.aname); + switch (mem_free->ustype) + { + case NSFW_MEM_MZONE: + ret = nsfw_mem_zone_release (&mem_free->stname); + break; + case NSFW_MEM_MBUF: + ret = nsfw_mem_mbfmp_release (&mem_free->stname); + break; + case NSFW_MEM_SPOOL: + ret = nsfw_mem_sp_release (&mem_free->stname); + break; + case NSFW_MEM_RING: + ret = nsfw_mem_ring_release (&mem_free->stname); + break; + default: + NSFW_LOGERR ("free mem err type]type=%u", mem_free->ustype); + return NULL; + } + + if (NSFW_MEM_OK != ret) + { + NSFW_LOGERR ("mem free failed!]ret=%d", ret); + return NULL; + } + + return pdata; +} + +/***************************************************************************** +* Prototype : mem_item_lookup +* Description : lookup memory item +* Input : void *pdata +* Output : None +* Return Value : void* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_item_lookup (void *pdata) +{ + nsfw_mem_type_info *mem_lookup = (nsfw_mem_type_info *) pdata; + void *ret; + NSFW_LOGDBG ("lookup mem]type=%u,name=%s", mem_lookup->ustype, + mem_lookup->stname.aname); + switch (mem_lookup->ustype) + { + case NSFW_MEM_MZONE: + ret = nsfw_mem_zone_lookup (&mem_lookup->stname); + break; + case NSFW_MEM_MBUF: + ret = nsfw_mem_mbfmp_lookup (&mem_lookup->stname); + break; + case NSFW_MEM_SPOOL: + ret = nsfw_mem_sp_lookup (&mem_lookup->stname); + break; + case NSFW_MEM_RING: + ret = nsfw_mem_ring_lookup (&mem_lookup->stname); + break; + default: + NSFW_LOGERR ("lookup mem err type]type=%d", mem_lookup->ustype); + return NULL; + } + + if (NULL == ret) + { + NSFW_LOGERR ("mem lookup failed!]ret=%p,name=%s", ret, + mem_lookup->stname.aname); + return NULL; + } + + return ret; +} + +/***************************************************************************** +* Prototype : mem_item_proc_by_msg +* Description : call memory item process function +* Input : void *pdata +* nsfw_ps_mem_item_cfg* item_cfg +* Output : None +* Return Value : void* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_item_proc_by_msg (void *pdata, nsfw_ps_mem_item_cfg * item_cfg) +{ + char argv_buf[NSFW_MEM_CALL_ARG_BUF] = { 0 }; + + if ((NULL == item_cfg->change_fun) || (NULL == item_cfg->create_fun)) + { + NSFW_LOGERR ("item error]change_fun=%p,create_fun=%p", + item_cfg->change_fun, item_cfg->create_fun); + return NULL; + } + + if (FALSE == + item_cfg->change_fun (item_cfg->usmsg_type, pdata, argv_buf, + NSFW_MEM_CALL_ARG_BUF)) + { + NSFW_LOGERR ("call change_fun failed!]type=%u", item_cfg->usmsg_type); + return NULL; + } + + void *pdataret = NULL; + pdataret = (item_cfg->create_fun) ((void *) argv_buf); + return pdataret; +} + +/***************************************************************************** +* Prototype : mem_init_rsp_msg +* Description : init the rsp message +* Input : nsfw_shmem_msg_head* msg +* nsfw_shmem_msg_head *rsp +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +u8 +mem_init_rsp_msg (nsfw_shmem_msg_head * msg, nsfw_shmem_msg_head * rsp) +{ + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", msg->usmsg_type); + return FALSE; + } + + int idx; + int mem_count = msg->uslenth / item_cfg->item_size; + + rsp->usmsg_type = msg->usmsg_type + 1; + rsp->uslenth = mem_count * sizeof (nsfw_shmem_ack); + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + char *pdata = NULL; + for (idx = 0; idx < mem_count; idx++) + { + pdata = (char *) msg->aidata + idx * item_cfg->item_size; + pack->pbase_addr = NULL; + pack->usseq = ((nsfw_shmem_reserv_req *) pdata)->usseq; + pack->cstate = NSFW_MEM_ALLOC_FAIL; + pack++; + } + + NSFW_LOGDBG ("init all rsp ack]mem_count=%d,msg_type=%u", mem_count, + msg->usmsg_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_rel_mem_by_msg +* Description : release memory by message +* Input : nsfw_shmem_msg_head* req_msg +* nsfw_shmem_msg_head *rsp +* u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_rel_mem_by_msg (nsfw_shmem_msg_head * req_msg, + nsfw_shmem_msg_head * rsp, u32 pid) +{ + u32 i; + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (req_msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", req_msg->usmsg_type); + return FALSE; + } + + unsigned int mem_count = req_msg->uslenth / item_cfg->item_size; + char *pdata = NULL; + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + for (i = 0; i < mem_count; i++) + { + pdata = (char *) req_msg->aidata + i * item_cfg->item_size; + if (NULL != mem_item_proc_by_msg ((void *) pdata, item_cfg)) + { + pack->cstate = NSFW_MEM_ALLOC_SUCC; + pack->pbase_addr = NULL; + } + pack++; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_lookup_mem_by_msg +* Description : lookup memory by message +* Input : nsfw_shmem_msg_head* mgr_msg +* nsfw_shmem_msg_head *rsp +* u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_lookup_mem_by_msg (nsfw_shmem_msg_head * mgr_msg, + nsfw_shmem_msg_head * rsp, u32 pid) +{ + i32 idx; + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (mgr_msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", mgr_msg->usmsg_type); + return FALSE; + } + + int mem_count = mgr_msg->uslenth / item_cfg->item_size; + char *pdata = NULL; + void *paddr = NULL; + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + + for (idx = 0; idx < mem_count; idx++) + { + pdata = (char *) mgr_msg->aidata + idx * item_cfg->item_size; + paddr = mem_item_proc_by_msg ((void *) pdata, item_cfg); + if (NULL != paddr) + { + pack->cstate = NSFW_MEM_ALLOC_SUCC; + pack->pbase_addr = paddr; + } + pack++; + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_alloc_mem_by_msg +* Description : alloc memory by message +* Input : nsfw_shmem_msg_head* mem_msg +* nsfw_shmem_msg_head *rsp +* Output : None +* Return Value : ns_mem_info* +* Calls : +* Called By : +*****************************************************************************/ +void * +mem_alloc_mem_by_msg (nsfw_shmem_msg_head * mem_msg, + nsfw_shmem_msg_head * rsp) +{ + nsfw_ps_mem_item_cfg *item_cfg = + mem_item_get_cfg_from_msg (mem_msg->usmsg_type); + if (NULL == item_cfg) + { + NSFW_LOGERR ("get item cfg failed!]msg_type=%u", mem_msg->usmsg_type); + return NULL; + } + + int i; + int j; + nsfw_mem_type_info mem_free; + char *pdata = NULL; + void *p_addr = NULL; + + int mem_count = mem_msg->uslenth / item_cfg->item_size; + nsfw_shmem_ack *pack = (nsfw_shmem_ack *) & (rsp->aidata[0]); + for (i = 0; i < mem_count; i++) + { + pdata = (char *) mem_msg->aidata + i * item_cfg->item_size; + p_addr = mem_item_proc_by_msg ((void *) pdata, item_cfg); + if (NULL == p_addr) + { + NSFW_LOGERR + ("alloc mem failed!]type=%u,mem_count=%d,item=%d,name=%s", + mem_msg->usmsg_type, mem_count, i, + ((nsfw_shmem_reserv_req *) pdata)->aname); + goto fail_free_mem; + } + + pack->cstate = NSFW_MEM_ALLOC_SUCC; + pack->pbase_addr = p_addr; + NSFW_LOGINF + ("alloc mem suc!]addr=%p,type=%u,mem_count=%d,item=%d,name=%s", + p_addr, mem_msg->usmsg_type, mem_count, i, + ((nsfw_shmem_reserv_req *) pdata)->aname); + pack++; + } + return p_addr; + +fail_free_mem: + for (j = 0; j < i; j++) + { + pdata = (char *) mem_msg->aidata + j * item_cfg->item_size; + if (EOK != + STRCPY_S (mem_free.stname.aname, NSFW_MEM_NAME_LENTH, + ((nsfw_shmem_reserv_req *) pdata)->aname)) + { + NSFW_LOGERR ("STRCPY_S failed]j=%d", j); + continue; + } + + mem_free.ustype = item_cfg->mem_type; + mem_free.stname.entype = NSFW_SHMEM; + (void) mem_item_free (&mem_free); + NSFW_LOGINF ("free mem]addr=%p,type=%u,mem_count=%d,item=%d,name=%s", + p_addr, mem_msg->usmsg_type, mem_count, j, + ((nsfw_shmem_reserv_req *) pdata)->aname); + pack++; + } + + return NULL; + +} + +/***************************************************************************** +* Prototype : mem_alloc_req_proc +* Description : memory message +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_alloc_req_proc (nsfw_mgr_msg * msg) +{ + void *mem_addr = NULL; + + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_shmem_msg_head *mem_msg = GET_USER_MSG (nsfw_shmem_msg_head, msg); + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]msg_type=%u", mem_msg->usmsg_type); + return FALSE; + } + + nsfw_shmem_msg_head *mem_rsp_msg = + GET_USER_MSG (nsfw_shmem_msg_head, rsp_msg); + + if (!mem_init_rsp_msg (mem_msg, mem_rsp_msg)) + { + NSFW_LOGERR ("init rsp msg failed]msg_type=%u", mem_msg->usmsg_type); + nsfw_mgr_msg_free (rsp_msg); + return FALSE; + } + + switch (mem_msg->usmsg_type) + { + case NSFW_MEM_LOOKUP_REQ_MSG: + if (!mem_lookup_mem_by_msg (mem_msg, mem_rsp_msg, msg->src_pid)) + { + NSFW_LOGERR ("lookup mem msg failed]msg_type=%u", + mem_msg->usmsg_type); + goto sendrspmsg; + } + (void) mem_alloc_ps_info (msg->src_pid, msg->src_proc_type); + break; + case NSFW_RESERV_REQ_MSG: + case NSFW_MBUF_REQ_MSG: + case NSFW_SPPOOL_REQ_MSG: + case NSFW_RING_REQ_MSG: + mem_addr = mem_alloc_mem_by_msg (mem_msg, mem_rsp_msg); + if (NULL == mem_addr) + { + NSFW_LOGERR ("alloc mem msg failed]msg_type=%u", + mem_msg->usmsg_type); + (void) mem_init_rsp_msg (mem_msg, mem_rsp_msg); + goto sendrspmsg; + } + (void) mem_alloc_ps_info (msg->src_pid, msg->src_proc_type); + break; + case NSFW_RELEASE_REQ_MSG: + if (!mem_rel_mem_by_msg (mem_msg, mem_rsp_msg, msg->src_pid)) + { + NSFW_LOGERR ("rel mem msg failed]msg_type=%u", mem_msg->usmsg_type); + goto sendrspmsg; + } + break; + default: + break; + } + +sendrspmsg: + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_ps_exiting_resend +* Description : send the exiting message again +* Input : void *pps_info +* void* argv +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_ps_exiting_resend (void *pps_info, void *argv) +{ + u32 *count = argv; + nsfw_ps_info *ps_info = pps_info; + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (NSFW_PROC_APP != ps_info->proc_type) + { + return FALSE; + } + + if (NSFW_PS_EXITING != ps_info->state) + { + return FALSE; + } + + if (NULL != count) + { + NSFW_LOGINF ("send count]count=%u,pid=%u", *count, ps_info->host_pid); + if (NSFW_PS_SEND_PER_TIME < (*count)++) + { + struct timespec time_left = + { NSFW_PS_MEM_RESEND_TVLAUE + +((*count) / NSFW_PS_SEND_PER_TIME), 0 + }; + ps_info->resend_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_PS_MEM_RESEND_TIMER, + pps_info, + nsfw_mem_ps_exit_resend_timeout, + time_left); + return TRUE; + } + } + + (void) mem_ps_exiting (ps_info, NULL); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_mem_srv_restore_timeout +* Description : service waiting resume timeout +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_mem_srv_restore_timeout (u32 timer_type, void *data) +{ + u32 max_count = 0; + + g_mem_cfg.p_restore_timer = NULL; + if (TRUE == NSFW_SRV_STATE_SUSPEND) + { + NSFW_SRV_STATE_SUSPEND = FALSE; + (void) nsfw_ps_iterator (mem_ps_exiting_resend, &max_count); + } + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_srv_ctrl_proc +* Description : service control message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_srv_ctrl_proc (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_srv_ctrl_msg *ctrl_msg = GET_USER_MSG (nsfw_srv_ctrl_msg, msg); + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]msg=%p", msg); + return FALSE; + } + nsfw_srv_ctrl_msg *ctrl_rsp_msg = GET_USER_MSG (nsfw_srv_ctrl_msg, rsp_msg); + NSFW_LOGINF ("get srv ctrl state] state=%d", ctrl_msg->srv_state); + + ctrl_rsp_msg->rsp_code = NSFW_MGR_SUCESS; + + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + + if (NSFW_SRV_CTRL_RESUME == ctrl_msg->srv_state) + { + if (TRUE == NSFW_SRV_STATE_SUSPEND) + { + NSFW_SRV_STATE_SUSPEND = FALSE; + } + u32 max_count = 0; + (void) nsfw_ps_iterator (mem_ps_exiting_resend, &max_count); + if (NULL != g_mem_cfg.p_restore_timer) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) + g_mem_cfg.p_restore_timer); + g_mem_cfg.p_restore_timer = NULL; + } + } + else + { + NSFW_SRV_STATE_SUSPEND = TRUE; + struct timespec time_left = { NSFW_SRV_RESTORE_TVALUE, 0 }; + g_mem_cfg.p_restore_timer = + (void *) nsfw_timer_reg_timer (0, NULL, + nsfw_mem_srv_restore_timeout, + time_left); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_mem_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_mem_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + NSFW_LOGINF ("ps_mem module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MAIN: + (void) nsfw_ps_reg_global_fun (NSFW_PROC_APP, NSFW_PS_EXITING, + mem_ps_exiting, NULL); + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_MEM_ALLOC_REQ, mem_alloc_req_proc); + (void) NSFW_REG_SOFT_INT (NSFW_SRV_RESTORE_TIMER, + NSFW_SRV_RESTORE_TVALUE, 1, 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_APP_RESEND_TIMER, + NSFW_PS_MEM_RESEND_TVLAUE, 1, 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_APP_SEND_PER_TIME, + NSFW_PS_SEND_PER_TIME, 1, 0xFFFF); + break; + default: + if (proc_type < NSFW_PROC_MAX) + { + return 0; + } + return -1; + } + + g_mem_cfg.srv_restore_tvalue = NSFW_SRV_RESTORE_TVALUE_DEF; + g_mem_cfg.ps_exit_resend_tvalue = NSFW_PS_MEM_RESEND_TVLAUE_DEF; + g_mem_cfg.ps_send_per_time = NSFW_PS_SEND_PER_TIME_DEF; + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_PS_MEM_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_PS_MODULE) +NSFW_MODULE_INIT (nsfw_ps_mem_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_ps_mem_module.h b/src/framework/ipc/ps/nsfw_ps_mem_module.h new file mode 100644 index 0000000..6b2b3c9 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_mem_module.h @@ -0,0 +1,87 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_PS_MEM_MODULE_H +#define _NSFW_PS_MEM_MODULE_H + +#include "list.h" +#include "pidinfo.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define MEMZONE_MAX_NAME 32 +#define NS_MAX_FORK_NUM 32 +#define NSFW_PS_MEM_MAX_FILTER 4 + +#define NSFW_SRV_RESTORE_TVALUE_DEF 120 +#define NSFW_SRV_RESTORE_TVALUE g_mem_cfg.srv_restore_tvalue +#define NSFW_SRV_STATE_SUSPEND g_mem_cfg.srv_suspend + +#define NSFW_PS_MEM_RESEND_TIMER 1 +#define NSFW_PS_MEM_RESEND_TVLAUE_DEF 2 +#define NSFW_PS_SEND_PER_TIME_DEF 150 +#define NSFW_PS_SEND_PER_TIME (g_mem_cfg.ps_send_per_time) +#define NSFW_PS_MEM_RESEND_TVLAUE (g_mem_cfg.ps_exit_resend_tvalue) + +typedef struct _ns_mem_mng_init_cfg +{ + u16 srv_restore_tvalue; + u16 ps_exit_resend_tvalue; + u16 ps_send_per_time; + u16 srv_suspend; + void *p_restore_timer; +} ns_mem_mng_init_cfg; + +/*mem alloc by msg begin*/ +typedef struct +{ + nsfw_mem_name stname; + u16 ustype; +} nsfw_mem_type_info; + +#define NSFW_MEM_CALL_ARG_BUF 256 +#define MEM_GET_CALLARGV(_dst_member,_src_member, _dst_type,_srctype,_dst_buf, _src_buf) \ + ((_dst_type*)(void*)_dst_buf)->_dst_member = ((_srctype*)(void*)_src_buf)->_src_member + +typedef void *(*nsfw_ps_mem_create_fun) (void *memstr); +typedef u8 (*nsfw_ps_mem_msg_to_memstr) (u16 msg_type, char *msg_body, + char *memstr_buf, i32 buf_len); + +typedef struct __nsfw_ps_mem_item_cfg +{ + u16 usmsg_type; + u16 item_size; + u16 mem_type; + nsfw_ps_mem_create_fun create_fun; + nsfw_ps_mem_msg_to_memstr change_fun; +} nsfw_ps_mem_item_cfg; + +void *mem_item_free (void *pdata); +void *mem_item_lookup (void *pdata); +u8 mem_item_get_callargv (u16 msg_type, char *msg_body, char *memstr_buf, + i32 buf_len); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_PS_MEM_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_ps_module.c b/src/framework/ipc/ps/nsfw_ps_module.c new file mode 100644 index 0000000..e532c31 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_module.c @@ -0,0 +1,1725 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nsfw_mgr_com_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_ps_module.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" + +#include <errno.h> +#include <sys/un.h> +#include <stddef.h> +#include <sys/epoll.h> +#include <fcntl.h> + +#include <linux/cn_proc.h> +#include <linux/connector.h> +#include <linux/netlink.h> +#include <dirent.h> +#include <fnmatch.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +nsfw_ps_init_cfg g_ps_cfg; + +nsfw_pid_item *g_ps_info = NULL; + +nsfw_pid_item *g_master_ps_info = NULL; + +struct list_head g_ps_runing_list; +nsfw_ps_callback g_ps_init_callback[NSFW_PROC_MAX][NSFW_PS_MAX_CALLBACK]; +nsfw_ps_info g_main_ps_info; + +void *g_ps_chk_timer = NULL; + +/***************************************************************************** +* Prototype : nsfw_ps_reg_fun +* Description : reg the callback fun when process state change +* Input : nsfw_ps_info *pps_info +* u8 ps_state +* nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_reg_fun (nsfw_ps_info * pps_info, u8 ps_state, + nsfw_ps_proc_fun fun, void *argv) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("reg pps_info nul]state=%d,fun=%p", ps_state, fun); + return FALSE; + } + + u32 i; + for (i = 0; i < NSFW_PS_MAX_CALLBACK; i++) + { + if (NULL == pps_info->callback[i].fun) + { + pps_info->callback[i].fun = fun; + pps_info->callback[i].argv = argv; + pps_info->callback[i].state = ps_state; + NSFW_LOGDBG + ("reg fun suc]ps_info=%p,state=%d,fun=%p,argv=%p,i=%d", + pps_info, ps_state, fun, argv, i); + return TRUE; + } + } + + NSFW_LOGERR ("reg fun failed]ps_info=%p,state=%d,fun=%p,argv=%p,i=%d", + pps_info, ps_state, fun, argv, i); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_reg_global_fun +* Description : reg the callback function of the specify proc_type state + change +* Input : u8 proc_type +* u8 ps_state +* nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_reg_global_fun (u8 proc_type, u8 ps_state, nsfw_ps_proc_fun fun, + void *argv) +{ + if (NSFW_PROC_MAX <= proc_type) + { + NSFW_LOGERR ("proc_type err]state=%u,fun=%p,type=%u", ps_state, fun, + proc_type); + return FALSE; + } + + nsfw_ps_callback *cb_fun = g_ps_init_callback[proc_type]; + u32 i; + for (i = 0; i < NSFW_PS_MAX_CALLBACK; i++) + { + if (NULL == cb_fun[i].fun) + { + cb_fun[i].fun = fun; + cb_fun[i].argv = argv; + cb_fun[i].state = ps_state; + NSFW_LOGINF ("reg fun suc]type=%u,state=%u,fun=%p,argv=%p,i=%u", + proc_type, ps_state, fun, argv, i); + return TRUE; + } + } + + NSFW_LOGERR ("reg fun ful failed]type=%u,state=%u,fun=%p,argv=%p,i=%u", + proc_type, ps_state, fun, argv, i); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_exit +* Description : when recvive the process exit finish message ,change + to exit state +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_exit (nsfw_mgr_msg * msg) +{ + nsfw_ps_info *pps_info; + if (NULL == msg) + { + NSFW_LOGERR ("msg nul!"); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + pps_info = nsfw_ps_info_get (ps_msg->host_pid); + NSFW_LOGINF ("recv ps exit]host_pid=%d,ps_info=%p", ps_msg->host_pid, + pps_info); + + if (NULL == pps_info) + { + NSFW_LOGERR ("error msg pps_info nul]host_pid=%d", ps_msg->host_pid); + return true; + } + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXIT); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_fork_alloc +* Description : alloc fork ps_info +* Input : u32 parent_pid +* u32 child_pid +* Output : None +* Return Value : nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_ps_info * +nsfw_ps_info_fork_alloc (u32 parent_pid, u32 child_pid) +{ + nsfw_ps_info *pps_info = NULL; + nsfw_ps_info *pps_info_parent = NULL; + pps_info_parent = nsfw_ps_info_get (parent_pid); + if (NULL == pps_info_parent) + { + NSFW_LOGERR ("pps_info_parent nul"); + return NULL; + } + + pps_info = nsfw_ps_info_get (child_pid); + if (NULL == pps_info) + { + pps_info = nsfw_ps_info_alloc (child_pid, pps_info_parent->proc_type); + if (NULL == pps_info) + { + NSFW_LOGERR + ("alloc ps_info failed!]ps_info=%p,host_pid=%u,child_pid=%u", + pps_info_parent, pps_info_parent->host_pid, child_pid); + return NULL; + } + } + else + { + NSFW_LOGWAR + ("fork alloc mem before!]ps_info=%p,host_pid=%u,child_pid=%u", + pps_info_parent, pps_info_parent->host_pid, child_pid); + } + + NSFW_LOGWAR ("ps_info fork]ps_info=%p,host_pid=%u,child_pid=%u", + pps_info_parent, pps_info_parent->host_pid, child_pid); + pps_info->parent_pid = parent_pid; + if (EOK != + MEMCPY_S (pps_info->callback, sizeof (pps_info->callback), + pps_info_parent->callback, + sizeof (pps_info_parent->callback))) + { + nsfw_ps_info_free (pps_info); + NSFW_LOGERR ("ps_info set_failed"); + return NULL; + } + + if (EOK != + MEMCPY_S (pps_info->value, sizeof (pps_info->value), + pps_info_parent->value, sizeof (pps_info_parent->value))) + { + nsfw_ps_info_free (pps_info); + NSFW_LOGERR ("ps_info cpy_failed"); + return NULL; + } + + return pps_info; +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_alloc +* Description : alloc ps_info +* Input : u32 pid +* u8 proc_type +* Output : None +* Return Value : nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +nsfw_ps_info * +nsfw_ps_info_alloc (u32 pid, u8 proc_type) +{ + nsfw_ps_info *pps_info = NULL; + if (0 == nsfw_mem_ring_dequeue (g_ps_cfg.ps_info_pool, (void *) &pps_info)) + { + NSFW_LOGERR ("alloc ps_info falied]pid=%u,type=%u", pid, proc_type); + return NULL; + } + + if (NULL == pps_info) + { + if (NSFW_PROC_MAIN != proc_type || TRUE == g_main_ps_info.alloc_flag) + { + NSFW_LOGERR ("alloc ps_info nul]pid=%u,type=%u", pid, proc_type); + return NULL; + } + pps_info = &g_main_ps_info; + } + + if (EOK != + MEMSET_S (pps_info, sizeof (nsfw_ps_info), 0, sizeof (nsfw_ps_info))) + { + nsfw_ps_info_free (pps_info); + NSFW_LOGERR ("set failed"); + return NULL; + } + + pps_info->proc_type = proc_type; + pps_info->host_pid = pid; + + if (proc_type < NSFW_PROC_MAX) + { + int retval; + retval = + MEMCPY_S (pps_info->callback, sizeof (pps_info->callback), + g_ps_init_callback[proc_type], sizeof (pps_info->callback)); + if (EOK != retval) + { + NSFW_LOGERR ("Failed to MEMCPY_S]retval=%d", retval); + nsfw_ps_info_free (pps_info); + return NULL; + } + } + list_add_tail (&pps_info->node, &g_ps_runing_list); + pps_info->alloc_flag = TRUE; + + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_RUNNING); + if (pid < NSFW_MAX_PID) + { + g_ps_info[pid].ps_info = pps_info; + g_ps_info[pid].proc_type = proc_type; + } + + NSFW_LOGINF ("ps_info alloc]ps_info=%p,pid=%u,type=%u", pps_info, pid, + proc_type); + return pps_info; + +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_get +* Description : get ps_info by pid +* Input : u32 pid +* Output : None +* Return Value : inline nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +inline nsfw_ps_info * +nsfw_ps_info_get (u32 pid) +{ + if (pid < NSFW_MAX_PID) + { + return g_ps_info[pid].ps_info; + } + + return NULL; +} + +nsfw_ps_info * +nsfw_share_ps_info_get (u32 pid) +{ + if (pid < NSFW_MAX_PID) + { + return g_master_ps_info[pid].ps_info; + } + + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_ps_info_free +* Description : free ps_info +* Input : nsfw_ps_info *ps_info +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_ps_info_free (nsfw_ps_info * ps_info) +{ + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul"); + return; + } + + if (FALSE == ps_info->alloc_flag) + { + NSFW_LOGERR ("ps_info refree]ps_info=%p,pid=%u,state=%u", ps_info, + ps_info->host_pid, ps_info->state); + return; + } + + if (NULL != ps_info->exit_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) ps_info->exit_timer_ptr); + ps_info->exit_timer_ptr = NULL; + } + + if (NULL != ps_info->resend_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) ps_info->resend_timer_ptr); + ps_info->resend_timer_ptr = NULL; + } + + if (NULL != ps_info->hbt_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) ps_info->hbt_timer_ptr); + ps_info->hbt_timer_ptr = NULL; + } + + list_del (&ps_info->node); + + ps_info->alloc_flag = FALSE; + + NSFW_LOGINF ("ps_info free]ps_info=%p,pid=%u,state=%u", ps_info, + ps_info->host_pid, ps_info->state); + if (ps_info != &g_main_ps_info) + { + if (0 == nsfw_mem_ring_enqueue (g_ps_cfg.ps_info_pool, ps_info)) + { + NSFW_LOGERR ("ps_info free failed]ps_info=%p,pid=%u,state=%u", + ps_info, ps_info->host_pid, ps_info->state); + return; + } + } + + if (ps_info->host_pid < NSFW_MAX_PID) + { + g_ps_info[ps_info->host_pid].proc_type = 0; + g_ps_info[ps_info->host_pid].ps_info = NULL; + } + + return; +} + +/***************************************************************************** +* Prototype : nsfw_ps_exiting_timeout +* Description : waiting for remove ps_info timeout +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_exiting_timeout (u32 timer_type, void *data) +{ + nsfw_ps_info *pps_info = (nsfw_ps_info *) data; + NSFW_LOGINF ("ps_info timerout]pps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + if (NULL == pps_info) + { + return TRUE; + } + + pps_info->exit_timer_ptr = NULL; + + if (TRUE == g_hbt_switch) + { + NSFW_LOGINF ("hbt off"); + struct timespec time_left = { NSFW_PS_WEXIT_TVLAUE, 0 }; + pps_info->exit_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_PS_WEXIT_TIMER, pps_info, + nsfw_ps_exiting_timeout, time_left); + return TRUE; + } + + if (NSFW_PS_EXITING == pps_info->state) + { + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXIT); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_exit_end_notify +* Description : send exitting state process finished +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_exit_end_notify (u32 pid) +{ + nsfw_mgr_msg *rsp_msg = + nsfw_mgr_msg_alloc (MGR_MSG_APP_EXIT_RSP, NSFW_PROC_MASTER); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]pid=%u", pid); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, rsp_msg); + ps_msg->host_pid = pid; + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + NSFW_LOGINF ("send exit rsp msg]pid=%u", pid); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_sw_ps_state +* Description : switch ps_info state +* Input : nsfw_ps_info* pps_info +* u8 new_state +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_sw_ps_state (nsfw_ps_info * pps_info, u8 new_state) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("pps_info nul!"); + return FALSE; + } + + NSFW_LOGINF ("sw]ps_info=%p,pid=%u,type=%u,old_state=%u,newstate=%u", + pps_info, pps_info->host_pid, pps_info->proc_type, + pps_info->state, new_state); + + i32 i, ret; + for (i = 0; i < NSFW_PS_MAX_CALLBACK; i++) + { + if (NULL == pps_info->callback[i].fun) + { + /* NULL should be the last fun */ + break; + } + + if (new_state == pps_info->callback[i].state) + { + ret = + pps_info->callback[i].fun (pps_info, pps_info->callback[i].argv); + NSFW_LOGINF ("callback fun]ps_info=%p,i=%d,fun=%p,argv=%p,ret=%d", + pps_info, i, pps_info->callback[i].fun, + pps_info->callback[i].argv, ret); + } + } + + if (NSFW_PS_HBT_FAILED != new_state) + { + pps_info->state = new_state; + } + + if (NSFW_PS_EXIT == new_state) + { + nsfw_ps_info_free (pps_info); + } + + if (NSFW_PS_EXITING == new_state) + { + struct timespec time_left = { NSFW_PS_WEXIT_TVLAUE, 0 }; + pps_info->exit_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_PS_WEXIT_TIMER, pps_info, + nsfw_ps_exiting_timeout, time_left); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_get_netlink_socket +* Description : get netlink socket to kernel +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_ps_get_netlink_socket () +{ + int rc; + int nl_sock; + int size, size_len; + struct sockaddr_nl sa_nl; + + nl_sock = nsfw_base_socket (PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + if (nl_sock == -1) + { + NSFW_LOGERR ("get netlink socket err]errno=%d", errno); + return -1; + } + + rc = nsfw_set_close_on_exec (nl_sock); + if (rc == -1) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", nl_sock, errno); + return -1; + } + + sa_nl.nl_family = AF_NETLINK; + sa_nl.nl_groups = CN_IDX_PROC; + sa_nl.nl_pid = getpid (); + + rc = nsfw_base_bind (nl_sock, (struct sockaddr *) &sa_nl, sizeof (sa_nl)); + if (rc == -1) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("netlink bind err]netlink_fd=%d, errno=%d", nl_sock, + errno); + return -1; + } + + struct __attribute__ ((aligned (NLMSG_ALIGNTO))) + { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) + { + struct cn_msg cn_msg; + enum proc_cn_mcast_op cn_mcast; + }; + } nlcn_msg; + if (EOK != MEMSET_S (&nlcn_msg, sizeof (nlcn_msg), 0, sizeof (nlcn_msg))) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("netlink set failed]netlink_fd=%d", nl_sock); + return -1; + } + nlcn_msg.nl_hdr.nlmsg_len = sizeof (nlcn_msg); + nlcn_msg.nl_hdr.nlmsg_pid = getpid (); + nlcn_msg.nl_hdr.nlmsg_type = NLMSG_DONE; + + nlcn_msg.cn_msg.id.idx = CN_IDX_PROC; + nlcn_msg.cn_msg.id.val = CN_VAL_PROC; + nlcn_msg.cn_msg.len = sizeof (enum proc_cn_mcast_op); + + nlcn_msg.cn_mcast = PROC_CN_MCAST_LISTEN; + rc = nsfw_base_send (nl_sock, &nlcn_msg, sizeof (nlcn_msg), 0); + if (rc == -1) + { + (void) nsfw_base_close (nl_sock); + NSFW_LOGERR ("netlink send err]netlink_fd=%d, errno=%d", nl_sock, + errno); + return -1; + } + + NSFW_LOGINF ("netlink connect]netlink_fd=%d", nl_sock); + int val, len; + len = sizeof (val); + if (0 > + nsfw_base_getsockopt (nl_sock, SOL_SOCKET, SO_RCVBUF, &val, + (socklen_t *) & len)) + { + NSFW_LOGERR ("get socket opt err!]error=%d", errno); + } + else + { + NSFW_LOGINF ("] SO_RCVBUF=0x%x", val); + } + + size = MAX_NET_LINK_BUF; + size_len = sizeof (size); + if (0 > + nsfw_base_setsockopt (nl_sock, SOL_SOCKET, SO_RCVBUFFORCE, + (void *) &size, (socklen_t) size_len)) + { + NSFW_LOGERR ("set socket opt err!]error=%d", errno); + } + + size_len = sizeof (size); + if (0 > + nsfw_base_getsockopt (nl_sock, SOL_SOCKET, SO_RCVBUF, (void *) &size, + (socklen_t *) & size_len)) + { + NSFW_LOGERR ("get socket opt err!]error=%d", errno); + } + + NSFW_LOGINF ("] SO_RCVBUF=0x%x", size); + return nl_sock; +} + +/***************************************************************************** +* Prototype : nsfw_ps_change_fun +* Description : proc change when receive event from kernel +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_change_fun (i32 epfd, i32 fd, u32 events) +{ + i32 rc; + u32 host_pid; + nsfw_ps_info *pps_info = NULL; + + struct __attribute__ ((aligned (NLMSG_ALIGNTO))) + { + struct nlmsghdr nl_hdr; + struct __attribute__ ((__packed__)) + { + struct cn_msg cn_msg; + struct proc_event proc_ev; + }; + } nlcn_msg; + + if (!(events & EPOLLIN)) + { + return TRUE; + } + + while (1) + { + rc = nsfw_base_recv (fd, &nlcn_msg, sizeof (nlcn_msg), 0); + if (rc == 0) + { + NSFW_LOGWAR ("netlink recv 0]netlink_fd=%d,errno=%d", fd, errno); + break; + } + else if (rc == -1) + { + if (errno == EINTR || errno == EAGAIN) + { + break; + } + NSMON_LOGERR ("netlink recv]netlink_fd=%d,errno=%d", fd, errno); + if (errno == ENOBUFS) + { + struct timespec time_left = { NSFW_PS_FIRST_CHK_TVLAUE, 0 }; + g_ps_chk_timer = + (void *) nsfw_timer_reg_timer (NSFW_PS_CHK_TIMER, + (void *) FALSE, + nsfw_ps_chk_timeout, + time_left); + } + break; + } + + switch (nlcn_msg.proc_ev.what) + { + case PROC_EVENT_EXIT: + host_pid = nlcn_msg.proc_ev.event_data.exit.process_pid; + pps_info = nsfw_ps_info_get (host_pid); + if (NULL == pps_info) + { + NSFW_LOGDBG ("pps info is null]host pid=%d", host_pid); + break; + } + + if (NSFW_PS_EXITING == pps_info->state) + { + NSFW_LOGERR ("double pid info]ps_info=%p,pid=%d", pps_info, + host_pid); + break; + } + + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXITING); + break; + default: + break; + } + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_start_netlink +* Description : reg ps_module to epoll thread +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +u8 +nsfw_ps_start_netlink () +{ + i32 netlink_fd = nsfw_ps_get_netlink_socket (); + if (netlink_fd < 0) + { + NSFW_LOGERR ("get netlink failed!"); + return FALSE; + } + + NSFW_LOGINF ("start ps_info module!]netlink_fd=%d", netlink_fd); + (void) nsfw_mgr_reg_sock_fun (netlink_fd, nsfw_ps_change_fun); + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_APP_EXIT_RSP, nsfw_ps_exit); + return TRUE; +} + +/* for heartbeat check*/ + +NSTACK_STATIC __thread i32 t_val_idx = 0; +nsfw_thread_dogs g_thread_dogs[NSFW_MAX_THREAD_DOGS_COUNT]; +/***************************************************************************** +* Prototype : nsfw_all_thread_chk +* Description : get all thread check state +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_all_thread_chk () +{ + i32 count = -1; + u32 i; + for (i = 0; i < NSFW_MAX_THREAD_DOGS_COUNT; i++) + { + if (FALSE == g_thread_dogs[i].alloc_flag) + { + continue; + } + + if (count < g_thread_dogs[i].count) + { + count = g_thread_dogs[i].count; + } + + g_thread_dogs[i].count++; + } + return count; +} + +/***************************************************************************** +* Prototype : nsfw_thread_chk_unreg +* Description : cancel the thread check +* Input : None +* Output : None +* Return Value : inline u8 +* Calls : +* Called By : +*****************************************************************************/ +inline u8 +nsfw_thread_chk_unreg () +{ + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].alloc_flag = FALSE; + g_thread_dogs[t_val_idx].count = 0; + g_thread_dogs[t_val_idx].thread_id = 0; + t_val_idx = 0; + } + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_thread_chk +* Description : add the thread to check, and should be call in every + process cycle +* Input : None +* Output : None +* Return Value : inline u8 +* Calls : +* Called By : +*****************************************************************************/ +inline u8 +nsfw_thread_chk () +{ + u32 i; + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].count = 0; + return TRUE; + } + + for (i = 1; i < NSFW_MAX_THREAD_DOGS_COUNT; i++) + { + if ((FALSE == g_thread_dogs[i].alloc_flag) + && __sync_bool_compare_and_swap (&g_thread_dogs[i].alloc_flag, + FALSE, TRUE)) + { + t_val_idx = i; + break; + } + } + + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].count = 0; + g_thread_dogs[t_val_idx].thread_id = syscall (SYS_gettid); + } + + return TRUE; +} + +/***************************************************************** +Parameters : None +Return : +Description : +*****************************************************************/ +nsfw_thread_dogs * +nsfw_thread_getDog () +{ + u32 i; + nsfw_thread_dogs *retPtr = NULL; + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + return &g_thread_dogs[t_val_idx]; + } + + for (i = 1; i < NSFW_MAX_THREAD_DOGS_COUNT; i++) + { + if ((FALSE == g_thread_dogs[i].alloc_flag) + && __sync_bool_compare_and_swap (&g_thread_dogs[i].alloc_flag, + FALSE, TRUE)) + { + t_val_idx = i; + break; + } + } + + if (t_val_idx > 0 && t_val_idx < NSFW_MAX_THREAD_DOGS_COUNT) + { + g_thread_dogs[t_val_idx].count = 0; + g_thread_dogs[t_val_idx].thread_id = syscall (SYS_gettid); + retPtr = &g_thread_dogs[t_val_idx]; + } + return retPtr; +} + +pthread_t g_all_thread[MAX_THREAD] = { 0 }; + +u8 +nsfw_reg_trace_thread (pthread_t tid) +{ + int i; + for (i = 0; i < MAX_THREAD; i++) + { + if ((0 == g_all_thread[i]) + && __sync_bool_compare_and_swap (&g_all_thread[i], 0, tid)) + { + return TRUE; + } + } + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_check_dst_init +* Description : send check msg check the dst process is listening +* Input : u8 dst_proc_type +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_check_dst_init (u8 dst_proc_type) +{ + u8 ps_state = FALSE; + nsfw_mgr_msg *msg = + nsfw_mgr_msg_alloc (MGR_MSG_CHK_INIT_REQ, dst_proc_type); + if (NULL == msg) + { + NSFW_LOGERR ("alloc msg failed]dst_typ=%d", dst_proc_type); + return FALSE; + } + + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, msg); + ps_msg->ps_state = TRUE; + + nsfw_mgr_msg *rsp_msg = nsfw_mgr_null_rspmsg_alloc (); + if (NULL == rsp_msg) + { + nsfw_mgr_msg_free (msg); + NSFW_LOGERR ("alloc rsp msg failed]dst_typ=%d", dst_proc_type); + return FALSE; + } + + (void) nsfw_mgr_send_req_wait_rsp (msg, rsp_msg); + + ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, rsp_msg); + ps_state = ps_msg->ps_state; + + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp_msg); + NSFW_LOGINF ("get peer state]dst_type=%d,state=%d", dst_proc_type, + ps_state); + return ps_state; +} + +/***************************************************************************** +* Prototype : nsfw_ps_send_hbt +* Description : seng heart beat message to peer +* Input : nsfw_ps_info* pps_info +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_send_hbt (nsfw_ps_info * pps_info) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + nsfw_mgr_msg *req_msg = + nsfw_mgr_msg_alloc (MGR_MSG_CHK_HBT_REQ, pps_info->proc_type); + if (NULL == req_msg) + { + NSFW_LOGERR ("alloc req msg failed]pps_info=%p", pps_info); + return FALSE; + } + + req_msg->dst_pid = pps_info->host_pid; + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, req_msg); + ps_msg->ps_state = TRUE; + u8 ret = nsfw_mgr_send_msg (req_msg); + nsfw_mgr_msg_free (req_msg); + NSFW_LOGDBG ("send hbt msg]ret=%d,pps_info=%p,pid=%d,type=%d", ret, + pps_info, pps_info->host_pid, pps_info->proc_type); + return ret; +} + +/***************************************************************************** +* Prototype : nsfw_ps_recv_hbt +* Description : recv heart beat message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_recv_hbt (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("error msg nul!"); + return FALSE; + } + + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp failed,drop msg!" MSGINFO, PRTMSG (msg)); + return FALSE; + } + + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, rsp_msg); + ps_msg->ps_state = TRUE; + ps_msg->thread_chk_count = nsfw_all_thread_chk (); + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_recv_hbt_rsp +* Description : recv heart beat response message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_recv_hbt_rsp (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("error msg nul!"); + return FALSE; + } + + nsfw_ps_chk_msg *ps_msg = GET_USER_MSG (nsfw_ps_chk_msg, msg); + if (TRUE != ps_msg->ps_state) + { + NSFW_LOGERR ("Heartbeat failed]pid=%u,type=%u", msg->src_pid, + msg->src_proc_type); + return FALSE; + } + + nsfw_ps_info *pps_info = nsfw_ps_info_get (msg->src_pid); + if (NULL == pps_info) + { + NSFW_LOGERR ("get ps_info failed]pid=%u,type=%u,count=%d", + msg->src_pid, msg->src_proc_type, + ps_msg->thread_chk_count); + return FALSE; + } + + if (0 == ps_msg->thread_chk_count) + { + pps_info->hbt_failed_count = 0; + return TRUE; + } + + if (pps_info->hbt_failed_count > (u32) ps_msg->thread_chk_count) + { + pps_info->hbt_failed_count = (u32) ps_msg->thread_chk_count; + } + + NSFW_LOGERR ("Heartbeat failed]pid=%u,type=%u,count=%d,ps_count=%u", + msg->src_pid, msg->src_proc_type, ps_msg->thread_chk_count, + pps_info->hbt_failed_count); + return FALSE; +} + +int +nsfw_ps_reset_hbt (void *pps_info, void *argv) +{ + nsfw_ps_info *ps_info = pps_info; + if (NULL == ps_info) + { + NSFW_LOGERR ("ps_info nul!"); + return FALSE; + } + + if (NSFW_PROC_MAIN != ps_info->proc_type) + { + return FALSE; + } + + ps_info->hbt_failed_count = *(u32 *) argv; + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_hbt_timeout +* Description : heart beat time out +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_hbt_timeout (u32 timer_type, void *data) +{ + nsfw_ps_info *pps_info = (nsfw_ps_info *) data; + + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + if (NULL == pps_info->hbt_timer_ptr) + { + NSFW_LOGERR ("hbt has stop]pps_info=%p", pps_info); + pps_info->hbt_failed_count = 0; + return TRUE; + } + + if (TRUE == g_hbt_switch) + { + struct timespec time_left = { NSFW_CHK_HBT_TVLAUE, 0 }; + pps_info->hbt_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_CHK_HBT_TIMER, data, + nsfw_ps_hbt_timeout, time_left); + return TRUE; + } + + /* nic init may cost a few seconds, master will restart main if heartbeat timeout */ + if (NSFW_SOFT_HBT_CHK_COUNT != NSFW_MAX_HBT_CHK_COUNT) + { + if (NSFW_SOFT_HBT_CHK_COUNT < NSFW_MAX_HBT_CHK_COUNT) + { + u32 new_hbt_count = 0; + (void) nsfw_ps_iterator (nsfw_ps_reset_hbt, &new_hbt_count); + } + + NSFW_MAX_HBT_CHK_COUNT = NSFW_SOFT_HBT_CHK_COUNT; + } + + if (NSFW_MAX_HBT_CHK_COUNT <= pps_info->hbt_failed_count) + { + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_HBT_FAILED); + /*reset counter */ + pps_info->hbt_failed_count = 0; + } + + if (TRUE != nsfw_ps_send_hbt (pps_info)) + { + } + + if (pps_info->hbt_failed_count > 0) + { + NSFW_LOGWAR ("Heartbeat failed]pid=%u,ps_count=%u, max_count=%d", + pps_info->host_pid, pps_info->hbt_failed_count, + NSFW_MAX_HBT_CHK_COUNT); + } + + pps_info->hbt_failed_count++; + struct timespec time_left = { NSFW_CHK_HBT_TVLAUE, 0 }; + pps_info->hbt_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_CHK_HBT_TIMER, data, + nsfw_ps_hbt_timeout, time_left); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_hbt_start +* Description : start ps_info heart beat +* Input : nsfw_ps_info* pps_info +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_hbt_start (nsfw_ps_info * pps_info) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + if (NULL != pps_info->hbt_timer_ptr) + { + NSFW_LOGERR ("hbt start before!]ps_info=%p,pid=%u,type=%u", pps_info, + pps_info->host_pid, pps_info->proc_type); + return FALSE; + } + + struct timespec time_left = { NSFW_CHK_HBT_TVLAUE, 0 }; + pps_info->hbt_timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_CHK_HBT_TIMER, (void *) pps_info, + nsfw_ps_hbt_timeout, time_left); + NSFW_LOGINF ("hbt start!]ps_info=%p,pid=%u,type=%u", pps_info, + pps_info->host_pid, pps_info->proc_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_hbt_stop +* Description : stop ps_info heart beat +* Input : nsfw_ps_info* pps_info +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_ps_hbt_stop (nsfw_ps_info * pps_info) +{ + if (NULL == pps_info) + { + NSFW_LOGERR ("null ps_info!"); + return FALSE; + } + + if (NULL != pps_info->hbt_timer_ptr) + { + nsfw_timer_rmv_timer ((nsfw_timer_info *) pps_info->hbt_timer_ptr); + pps_info->hbt_timer_ptr = NULL; + } + + NSFW_LOGINF ("hbt stop!]ps_info=%p,pid=%d,type=%d", pps_info, + pps_info->host_pid, pps_info->proc_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_iterator +* Description : get all ps_info process by fun +* Input : nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : u32 +* Calls : +* Called By : +*****************************************************************************/ +u32 +nsfw_ps_iterator (nsfw_ps_proc_fun fun, void *argv) +{ + u32 count = 0; + nsfw_ps_info *pps_info = NULL; + struct list_head *tNode; + + if (NULL == fun) + { + NSFW_LOGERR ("fun null!"); + return count; + } + + LINT_LIST ()list_for_each_entry (pps_info, tNode, (&g_ps_runing_list), node) + { + (void) fun (pps_info, argv); + count++; + } + + NSFW_LOGINF ("proc pid]count=%u", count); + return count; +} + +int +filter (const struct dirent *dir) +{ + return !fnmatch ("[1-9]*", dir->d_name, 0); +} + +/***************************************************************************** +* Prototype : nsfw_ps_realloc_pid +* Description : realloc pid +* Input : u32 pid +* Output : None +* Return Value : inline nsfw_ps_info* +* Calls : +* Called By : +*****************************************************************************/ +inline nsfw_ps_info * +nsfw_ps_realloc_pid (u32 pid, u8 realloc_flg) +{ + nsfw_ps_info *pps_info = NULL; + if (pid >= NSFW_MAX_PID) + { + return NULL; + } + + if (g_ps_info[pid].ps_info == NULL) + { + return NULL; + } + + if (TRUE == realloc_flg) + { + pps_info = nsfw_ps_info_alloc (pid, g_ps_info[pid].proc_type); + if (NULL == pps_info) + { + NSFW_LOGERR ("alloc ps_info failed!]pid=%u,type=%u", pid, + g_ps_info[pid].proc_type); + return NULL; + } + } + else + { + pps_info = g_ps_info[pid].ps_info; + } + + pps_info->rechk_flg = TRUE; + return pps_info; +} + +/***************************************************************************** +* Prototype : nsfw_ps_reload_pid +* Description : reload pid +* Input : None +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_ps_reload_pid () +{ + struct dirent **namelist; + i32 n; + u32 host_pid; + nsfw_ps_info *pps_info = NULL; + + n = scandir ("/proc", &namelist, filter, 0); + if (n < 0) + { + NSFW_LOGERR ("buf null"); + } + else + { + while (n--) + { + host_pid = strtol (namelist[n]->d_name, NULL, 10); + pps_info = nsfw_ps_info_get (host_pid); + if (NULL != pps_info) + { + pps_info->rechk_flg = FALSE; + } + free (namelist[n]); + } + free (namelist); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_ps_realloc_all_pid +* Description : realloc all pid +* Input : u32 *main_pid +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nsfw_ps_realloc_all_pid (u32 * main_pid, u8 realloc_flg) +{ + u32 i; + nsfw_ps_info *pps_info = NULL; + for (i = 0; i < NSFW_MAX_PID; i++) + { + pps_info = nsfw_ps_realloc_pid (i, realloc_flg); + if (NULL != main_pid) + { + if (NULL != pps_info && NSFW_PROC_MAIN == pps_info->proc_type) + { + (*main_pid) = i; + } + } + } +} + +/***************************************************************************** +* Prototype : nsfw_ps_chk_exit_timeout +* Description : chk ps info +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_chk_exit_timeout (u32 timer_type, void *data) +{ + u32 i; + nsfw_ps_info *pps_info = NULL; + u32 pid = (u64) data; + + /*main pid exit first */ + if (NULL != data) + { + pps_info = nsfw_ps_info_get (pid); + if (NULL != pps_info && TRUE == pps_info->rechk_flg) + { + if (NSFW_PS_EXITING != pps_info->state) + { + NSFW_LOGWAR ("rechk pid exit]ps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXITING); + pps_info->rechk_flg = FALSE; + } + } + } + + for (i = 0; i < NSFW_MAX_PID; i++) + { + pps_info = nsfw_ps_info_get (i); + if (NULL != pps_info && TRUE == pps_info->rechk_flg) + { + if (NSFW_PS_EXITING == pps_info->state) + { + NSFW_LOGWAR ("double pid info]ps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + continue; + } + + NSFW_LOGWAR ("rechk pid exit]ps_info=%p,pid=%u", pps_info, + pps_info->host_pid); + (void) nsfw_sw_ps_state (pps_info, NSFW_PS_EXITING); + pps_info->rechk_flg = FALSE; + } + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_chk_timeout +* Description : load all running pid +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +****************************************************************************/ +int +nsfw_ps_chk_timeout (u32 timer_type, void *data) +{ + u32 main_pid = 0; + u8 realloc_flg = (u8) (u64) data; + + nsfw_ps_realloc_all_pid (&main_pid, realloc_flg); + nsfw_ps_reload_pid (); + + struct timespec time_left = { NSFW_PS_CHK_EXIT_TVLAUE, 0 }; + g_ps_chk_timer = + (void *) nsfw_timer_reg_timer (NSFW_PS_CHK_EXIT_TVLAUE, + (void *) (u64) main_pid, + nsfw_ps_chk_exit_timeout, time_left); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_ps_rechk_pid_exit +* Description : rechck pid exit +* Input : nsfw_ps_proc_fun fun +* void* argv +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_rechk_pid_exit (nsfw_ps_pid_fun fun, void *argv) +{ + u32 ulI = 0; + if (NULL == fun) + { + NSFW_LOGERR ("input err! fun null"); + return -1; + } + + u8 *ps_pid = malloc (NSFW_MAX_PID); + if (NULL == ps_pid) + { + NSFW_LOGERR ("malloc failed"); + return -1; + } + + int retval = MEMSET_S (ps_pid, NSFW_MAX_PID, 0, NSFW_MAX_PID); + if (EOK != retval) + { + NSFW_LOGERR ("MEMSET_S failed]retval=%d", retval); + free (ps_pid); + return -1; + } + + struct dirent **namelist; + i32 n; + u32 host_pid; + n = scandir ("/proc", &namelist, filter, 0); + if (n < 0) + { + NSFW_LOGERR ("buf null"); + free (ps_pid); + return -1; + } + + while (n--) + { + host_pid = strtol (namelist[n]->d_name, NULL, 10); + if (host_pid < NSFW_MAX_PID) + { + ps_pid[ulI] = TRUE; + } + free (namelist[n]); + } + free (namelist); + + int count = 0; + for (ulI = 0; ulI < NSFW_MAX_PID; ulI++) + { + if ((NULL != g_master_ps_info[ulI].ps_info) && (FALSE == ps_pid[ulI])) + { + (void) fun (ulI, g_master_ps_info[ulI].proc_type, argv); + NSFW_LOGWAR ("rechk pid exit]pid=%d,type=%d", ulI, + g_master_ps_info[ulI].proc_type); + count++; + continue; + } + } + + free (ps_pid); + return count; +} + +void +nsfw_ps_cfg_set_chk_count (u16 count) +{ + g_ps_cfg.ps_chk_hbt_count = count; +} + +/***************************************************************************** +* Prototype : nsfw_ps_module_init +* Description : ps_module init +* Input : void* param +* Output : None +* Return Value : static int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_ps_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + nsfw_ps_init_cfg *ps_cfg = &g_ps_cfg; + int retval; + nsfw_pid_item *pid_info = NULL; + NSFW_LOGINF ("ps module init]type=%u", proc_type); + + ps_cfg->ps_chk_hbt_count = NSFW_MAX_HBT_CHK_COUNT_DEF; + ps_cfg->ps_chk_hbt_tvalue = NSFW_CHK_HBT_TVLAUE_DEF; + ps_cfg->ps_chk_hbt_soft_count = ps_cfg->ps_chk_hbt_count; + + nsfw_mem_zone pzoneinfo; + pzoneinfo.isocket_id = NSFW_SOCKET_ANY; + pzoneinfo.stname.entype = NSFW_SHMEM; + pzoneinfo.lenth = sizeof (nsfw_pid_item) * NSFW_MAX_PID; + if (-1 == + SPRINTF_S (pzoneinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + "MAS_PS_INFO")) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return -1; + } + + switch (proc_type) + { + case NSFW_PROC_MASTER: + { + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_CHK_HBT_RSP, + nsfw_ps_recv_hbt_rsp); + (void) NSFW_REG_SOFT_INT (NSFW_HBT_TIMER, NSFW_CHK_HBT_TVLAUE, 1, + 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_HBT_COUNT_PARAM, + NSFW_SOFT_HBT_CHK_COUNT, 1, 0xFFFF); + (void) NSFW_REG_SOFT_INT (NSFW_APP_EXIT_TIMER, NSFW_PS_WEXIT_TVLAUE, + 1, 0xFFFF); + + pid_info = nsfw_mem_zone_lookup (&pzoneinfo.stname); + if (NULL == pid_info) + { + pid_info = nsfw_mem_zone_create (&pzoneinfo); + if (NULL == pid_info) + { + NSFW_LOGERR ("alloc rec nul!"); + return -1; + } + + retval = + MEMSET_S (pid_info, (sizeof (nsfw_pid_item) * NSFW_MAX_PID), + 0, (sizeof (nsfw_pid_item) * NSFW_MAX_PID)); + if (EOK != retval) + { + NSFW_LOGERR ("MEMSET_S failed]retval=%d.\n", retval); + return -1; + } + } + + MEM_STAT (NSFW_PS_MODULE, pzoneinfo.stname.aname, NSFW_SHMEM, + pzoneinfo.lenth); + g_ps_info = pid_info; + break; + } + case NSFW_PROC_MAIN: + { + pid_info = malloc (sizeof (nsfw_pid_item) * NSFW_MAX_PID); + if (NULL == pid_info) + { + NSFW_LOGERR ("malloc mem failed!"); + return -1; + } + + retval = + MEMSET_S (pid_info, (sizeof (nsfw_pid_item) * NSFW_MAX_PID), 0, + (sizeof (nsfw_pid_item) * NSFW_MAX_PID)); + if (EOK != retval) + { + NSFW_LOGERR ("MEMSET_S failed]retval=%d.\n", retval); + free (pid_info); + return -1; + } + + g_ps_info = pid_info; + + pzoneinfo.stname.enowner = NSFW_PROC_MAIN; + pid_info = nsfw_mem_zone_create (&pzoneinfo); + if (NULL == pid_info) + { + NSFW_LOGERR ("create pid_info failed!"); + return -1; + } + + g_master_ps_info = pid_info; + break; + } + default: + return 0; + } + + ps_cfg->ps_info_size = NSFW_PS_INFO_MAX_COUNT; + ps_cfg->ps_waite_exit_tvalue = NSFW_PS_WEXIT_TVLAUE_DEF; + ps_cfg->net_link_buf = MAX_NET_LINK_BUF_DEF; + + INIT_LIST_HEAD (&(g_ps_runing_list)); + + nsfw_mem_sppool pmpinfo; + pmpinfo.enmptype = NSFW_MRING_MPMC; + pmpinfo.usnum = ps_cfg->ps_info_size; + pmpinfo.useltsize = sizeof (nsfw_ps_info); + pmpinfo.isocket_id = NSFW_SOCKET_ANY; + pmpinfo.stname.entype = NSFW_NSHMEM; + if (-1 == + SPRINTF_S (pmpinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + "MAS_PS_INFOPOOL")) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return -1; + } + + ps_cfg->ps_info_pool = nsfw_mem_sp_create (&pmpinfo); + + if (!ps_cfg->ps_info_pool) + { + NSFW_LOGERR ("alloc ps info pool_err"); + return -1; + } + + MEM_STAT (NSFW_PS_MODULE, pmpinfo.stname.aname, NSFW_NSHMEM, + nsfw_mem_get_len (ps_cfg->ps_info_pool, NSFW_MEM_SPOOL)); + + if (NSFW_PROC_MASTER != proc_type) + { + return 0; + } + + struct timespec time_left = { NSFW_PS_FIRST_CHK_TVLAUE, 0 }; + g_ps_chk_timer = + (void *) nsfw_timer_reg_timer (NSFW_PS_CHK_TIMER, (void *) TRUE, + nsfw_ps_chk_timeout, time_left); + + if (TRUE != nsfw_ps_start_netlink ()) + { + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_PS_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_MGR_COM_MODULE) +NSFW_MODULE_DEPENDS (NSFW_TIMER_MODULE) +NSFW_MODULE_INIT (nsfw_ps_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_ps_module.h b/src/framework/ipc/ps/nsfw_ps_module.h new file mode 100644 index 0000000..b754cea --- /dev/null +++ b/src/framework/ipc/ps/nsfw_ps_module.h @@ -0,0 +1,99 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_PS_MODULE_H +#define _NSFW_PS_MODULE_H + +#include "nsfw_ps_api.h" +#include "nsfw_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +#define NSFW_MAX_PID 65535 +COMPAT_PROTECT (NSFW_MAX_PID, 65535); + +#define NSFW_PS_INFO_MAX_COUNT 4095 +#define MAX_NET_LINK_BUF_DEF 0x34000*32 + +#define NSFW_PS_WEXIT_TIMER 1 +#define NSFW_PS_WEXIT_TVLAUE_DEF 180 + +#define NSFW_PS_WEXIT_TVLAUE (g_ps_cfg.ps_waite_exit_tvalue) +#define MAX_NET_LINK_BUF (g_ps_cfg.net_link_buf) + +typedef struct _nsfw_ps_init_cfg +{ + u32 ps_info_size; + u32 net_link_buf; + + u16 ps_waite_exit_tvalue; + u16 ps_chk_hbt_count; + u16 ps_chk_hbt_soft_count; + u16 ps_chk_hbt_tvalue; + + mring_handle ps_info_pool; +} nsfw_ps_init_cfg; + +#define NSFW_PS_CHK_TIMER 1 +#define NSFW_PS_FIRST_CHK_TVLAUE 1 +#define NSFW_PS_CHK_EXIT_TVLAUE 1 + +typedef struct _nsfw_pid_item +{ + u8 proc_type; + u8 u8_reserve; + u16 u16_reserve; + u32 u32_reserve; + nsfw_ps_info *ps_info; +} nsfw_pid_item; + +int nsfw_ps_change_fun (i32 epfd, i32 socket, u32 events); +u8 nsfw_sw_ps_state (nsfw_ps_info * pps_info, u8 new_state); + +/* for heartbeat checking*/ +#define NSFW_MAX_THREAD_DOGS_COUNT 8 +#define NSFW_CHK_HBT_TIMER 1 +#define NSFW_MAX_HBT_PROC_FUN 4 + +#define NSFW_CHK_HBT_TVLAUE_DEF 1 + +#define NSFW_MAX_HBT_CHK_COUNT (g_ps_cfg.ps_chk_hbt_count) +#define NSFW_SOFT_HBT_CHK_COUNT (g_ps_cfg.ps_chk_hbt_soft_count) +#define NSFW_CHK_HBT_TVLAUE (g_ps_cfg.ps_chk_hbt_tvalue) + +typedef struct _nsfw_ps_chk_msg +{ + u32 ps_state; + i32 thread_chk_count; +} nsfw_ps_chk_msg; + +int nsfw_ps_chk_timeout (u32 timer_type, void *data); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_PS_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_recycle_module.c b/src/framework/ipc/ps/nsfw_recycle_module.c new file mode 100644 index 0000000..bb3844f --- /dev/null +++ b/src/framework/ipc/ps/nsfw_recycle_module.c @@ -0,0 +1,666 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nsfw_mgr_com_api.h" +#include "nsfw_mem_api.h" +#include "nsfw_ps_api.h" +#include "nsfw_ps_mem_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_recycle_module.h" +#include "nsfw_maintain_api.h" +#include "nstack_log.h" +#include "common_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/* only work on nStackMain*/ +nsfw_recycle_cfg g_rec_cfg; + +nsfw_recycle_fun g_rec_fun[NSFW_REC_TYPE_MAX] = { 0 }; + +nsfw_rec_fun_info g_rec_lock_fun[NSFW_REC_LOCK_REL_MAX_FUN]; + +/***************************************************************************** +* Prototype : nsfw_recycle_reg_fun +* Description : reg one recycle type recycle funciton +* Input : u16 rec_type +* nsfw_recycle_fun fun +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_reg_fun (u16 rec_type, nsfw_recycle_fun fun) +{ + if (NULL == fun || rec_type >= NSFW_REC_TYPE_MAX) + { + NSFW_LOGERR ("argv err]fun=%p,type=%u", fun, rec_type); + return FALSE; + } + + g_rec_fun[rec_type] = fun; + NSFW_LOGINF ("reg]fun=%d,type=%u", fun, rec_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_lock_rel_fun +* Description : reg lock release when app exit run +* Input : nsfw_recycle_fun fun +* void* data +* u8 proc_type: NULL as all +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_lock_rel_fun (nsfw_recycle_fun fun, void *data, u8 proc_type) +{ + if (NULL == fun) + { + NSFW_LOGERR ("argv err]fun=%p,data=%p", fun, data); + return FALSE; + } + + u32 i; + + for (i = 0; i < NSFW_REC_LOCK_REL_MAX_FUN; i++) + { + if (NULL == g_rec_lock_fun[i].rec_fun) + { + g_rec_lock_fun[i].rec_fun = fun; + g_rec_lock_fun[i].data = data; + g_rec_lock_fun[i].proc_type = proc_type; + NSFW_LOGINF ("reg mgr_msg fun suc]fun=%p,data=%p", fun, data); + return TRUE; + } + } + + NSFW_LOGINF ("reg]fun=%p,data=%p", fun, data); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_exit_pid_lock +* Description : release all lock fun +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_exit_pid_lock (u32 pid, u8 proc_type, void *argv) +{ + u32 i; + NSFW_LOGINF ("release lock]pid=%d,type=%d", pid, proc_type); + for (i = 0; i < NSFW_REC_LOCK_REL_MAX_FUN; i++) + { + if (NULL == g_rec_lock_fun[i].rec_fun) + { + break; + } + + if ((NSFW_PROC_NULL == g_rec_lock_fun[i].proc_type) + || (proc_type == g_rec_lock_fun[i].proc_type)) + { + (void) g_rec_lock_fun[i].rec_fun (pid, g_rec_lock_fun[i].data, 0); + } + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_obj_end +* Description : one recycle object process finished notify +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_obj_end (u32 pid) +{ + nsfw_mgr_msg *rsp_msg = + nsfw_mgr_msg_alloc (MGR_MSG_RCC_END_REQ, NSFW_PROC_MAIN); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp msg failed]pid=%u", pid); + return FALSE; + } + + nsfw_ps_info_msg *ps_msg = GET_USER_MSG (nsfw_ps_info_msg, rsp_msg); + ps_msg->host_pid = pid; + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + NSFW_LOGINF ("send obj end msg]pid=%d", pid); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_callback_all_obj +* Description : process all recycle object +* Input : u32 pid +* nsfw_recycle_pool *rec_pool +* Output : None +* Return Value : nsfw_rcc_stat +* Calls : +* Called By : +*****************************************************************************/ +nsfw_rcc_stat +nsfw_recycle_callback_all_obj (u32 pid, nsfw_recycle_pool * rec_pool) +{ + u32 match = 0; + nsfw_recycle_obj *obj = NULL; + if (NULL == rec_pool) + { + return NSFW_RCC_CONTINUE; + } + + nsfw_recycle_obj *p_start = rec_pool->obj; + u32 i; + u32 size = rec_pool->pool_size; + + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL == pps_info) + { + NSFW_LOGERR ("get ps_info falied!]pid=%d", pid); + return NSFW_RCC_CONTINUE; + } + + i32 cur_idx = (i32) (u64) nsfw_ps_get_uv (pps_info, NSFW_REC_IDX); + + if (-1 == cur_idx) + { + cur_idx = 0; + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (u64) cur_idx); + (void) nsfw_recycle_exit_pid_lock (pid, NSFW_PROC_APP, NULL); + } + else + { + cur_idx++; + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (u64) cur_idx); + } + + for (i = cur_idx; i < size; i++) + { + obj = &p_start[i]; + cur_idx = i; + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (u64) cur_idx); + if (FALSE == obj->alloc_flag) + { + continue; + } + + if ((obj->rec_type < NSFW_REC_TYPE_MAX) + && (NULL != g_rec_fun[obj->rec_type])) + { + match++; + if (NSFW_RCC_SUSPEND == + g_rec_fun[obj->rec_type] (pid, obj->data, obj->rec_type)) + { + NSFW_LOGINF + ("call suspend]type=%d,obj_pid=%d,pid=%d,count=%d", + obj->rec_type, obj->host_pid, pid, match); + return NSFW_RCC_SUSPEND; + } + } + else + { + NSFW_LOGERR ("obj_error!drop]type=%d,obj_pid=%d,pid=%d", + obj->rec_type, obj->host_pid, pid); + } + } + + NSFW_LOGWAR ("rec obj]pid=%d,count=%d,cur_idx=%d", pid, match, cur_idx); + return NSFW_RCC_CONTINUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_pid_obj +* Description : recycle object with pid +* Input : u32 pid +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_pid_obj (u32 pid) +{ + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL == pps_info) + { + NSFW_LOGERR ("get ps_info falied!]pid=%d", pid); + return FALSE; + } + + nsfw_recycle_pool *rec_pool = g_rec_cfg.mem_rec_obj_pool; + void *timer_ptr = nsfw_ps_get_uv (pps_info, NSFW_REC_TIMER); + if (NSFW_RCC_SUSPEND == nsfw_recycle_callback_all_obj (pid, rec_pool)) + { + if (NULL != timer_ptr) + { + nsfw_timer_rmv_timer (timer_ptr); + timer_ptr = NULL; + } + + struct timespec time_left = { NSFW_REC_WEND_TVLAUE, 0 }; + timer_ptr = + (void *) nsfw_timer_reg_timer (NSFW_REC_WEND_TIMER, + (void *) (u64) pid, + nsfw_recycle_obj_timeout, time_left); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, timer_ptr); + return TRUE; + } + + if (NULL != timer_ptr) + { + nsfw_timer_rmv_timer (timer_ptr); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, NULL); + } + + (void) nsfw_ps_exit_end_notify (pid); + nsfw_ps_info_free (pps_info); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_all_obj +* Description : +* Input : u32 pid +* nsfw_mem_addr_msg *addr_msg +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_all_obj (u32 pid) +{ + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL == pps_info) + { + pps_info = nsfw_ps_info_alloc (pid, NSFW_PROC_APP); + if (NULL == pps_info) + { + NSFW_LOGERR ("alloc ps_info falied!]pid=%u", pid); + return FALSE; + } + } + + nsfw_ps_set_uv (pps_info, NSFW_REC_IDX, (void *) (-1)); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, NULL); + return nsfw_recycle_pid_obj (pid); +} + +/***************************************************************************** +* Prototype : mem_app_exit_proc +* Description : exiting message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +mem_app_exit_proc (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_ps_info_msg *ps_info_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + + /* look up the app rec memzone and release all resource */ + /* no need to send rsp for it will be send after stack process over */ + if (TRUE == nsfw_recycle_all_obj (ps_info_msg->host_pid)) + { + NSFW_LOGINF ("obj found!]pid=%d", ps_info_msg->host_pid); + return TRUE; + } + + (void) nsfw_ps_exit_end_notify (ps_info_msg->host_pid); + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_obj_end_proc +* Description : obj recycle finished notify process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_obj_end_proc (nsfw_mgr_msg * msg) +{ + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_ps_info_msg *ps_info_msg = GET_USER_MSG (nsfw_ps_info_msg, msg); + + return nsfw_recycle_pid_obj (ps_info_msg->host_pid); +} + +/***************************************************************************** +* Prototype : nsfw_recycle_obj_timeout +* Description : recycle object timeout process +* Input : u32 timer_type +* void* data +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_obj_timeout (u32 timer_type, void *data) +{ + u32 pid = (u64) data; + void *timer_ptr = NULL; + NSFW_LOGINF ("ps_info timerout]pid=%u", pid); + + nsfw_ps_info *pps_info; + pps_info = nsfw_ps_info_get (pid); + if (NULL != pps_info) + { + nsfw_recycle_pool *rec_pool = g_rec_cfg.mem_rec_obj_pool; + if (NULL != rec_pool) + { + if (TRUE == g_hbt_switch) + { + struct timespec time_left = { NSFW_REC_WEND_TVLAUE, 0 }; + timer_ptr = + (void *) nsfw_timer_reg_timer (timer_type, data, + nsfw_recycle_obj_timeout, + time_left); + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, timer_ptr); + return TRUE; + } + } + nsfw_ps_set_uv (pps_info, NSFW_REC_TIMER, timer_ptr); + } + + (void) nsfw_recycle_pid_obj (pid); + return TRUE; +} + +/***************************************************************************** +* Prototype : mem_rec_zone_init +* Description : init recycle zone in app, only work on App +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +mem_rec_zone_init () +{ + nsfw_mem_mring pringinfo; + pringinfo.enmptype = NSFW_MRING_MPMC; + pringinfo.isocket_id = NSFW_SOCKET_ANY; + pringinfo.stname.entype = NSFW_NSHMEM; + pringinfo.usnum = MEM_RECYCLE_PER_PRO_QUE; + u32 i; + for (i = 0; i < NSFW_REC_PRO_MAX; i++) + { + if (-1 == + SPRINTF_S (pringinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s%d", + MEM_REC_QUEUE_NAME, i)) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return FALSE; + } + g_rec_cfg.mem_rec_pro[i] = nsfw_mem_ring_create (&pringinfo); + if (NULL == g_rec_cfg.mem_rec_pro[i]) + { + NSFW_LOGERR ("alloc rec ring nul!"); + return FALSE; + } + } + + MEM_STAT (NSFW_RECYCLE_MODULE, MEM_REC_QUEUE_NAME, NSFW_NSHMEM, + NSFW_REC_PRO_MAX * nsfw_mem_get_len (g_rec_cfg.mem_rec_pro[0], + NSFW_MEM_RING)); + + nsfw_mem_zone pzoneinfo; + pzoneinfo.isocket_id = NSFW_SOCKET_ANY; + pzoneinfo.stname.entype = NSFW_NSHMEM; + pzoneinfo.lenth = + MEM_RECYCLE_OBJ_MAX_NUM * sizeof (nsfw_recycle_obj) + + sizeof (nsfw_recycle_pool); + if (-1 == + SPRINTF_S (pzoneinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + MEM_REC_POOL_NAME)) + { + NSFW_LOGERR ("SPRINTF_S failed]"); + return FALSE; + } + + g_rec_cfg.mem_rec_obj_pool = nsfw_mem_zone_create (&pzoneinfo); + if (NULL == g_rec_cfg.mem_rec_obj_pool) + { + NSFW_LOGERR ("alloc rec pool nul!"); + return FALSE; + } + + MEM_STAT (NSFW_RECYCLE_MODULE, MEM_REC_POOL_NAME, NSFW_NSHMEM, + pzoneinfo.lenth); + + int retval; + retval = + MEMSET_S (g_rec_cfg.mem_rec_obj_pool, pzoneinfo.lenth, 0, + pzoneinfo.lenth); + if (EOK != retval) + { + NSFW_LOGERR ("mem set init failed!"); + return FALSE; + } + + i32 j; + nsfw_recycle_pool *rec_pool = + (nsfw_recycle_pool *) g_rec_cfg.mem_rec_obj_pool; + rec_pool->pool_size = MEM_RECYCLE_OBJ_MAX_NUM; + + nsfw_recycle_obj *p_start = rec_pool->obj; + for (i = 0; i < NSFW_REC_PRO_MAX; i++) + { + for (j = 0; j < MEM_RECYCLE_PER_PRO_QUE; j++) + { + if (FALSE == p_start[j].alloc_flag) + { + if (0 == + nsfw_mem_ring_enqueue (g_rec_cfg.mem_rec_pro[i], + &p_start[j])) + { + NSFW_LOGERR ("enqueue failed"); + break; + } + } + } + p_start = p_start + MEM_RECYCLE_PER_PRO_QUE; + } + + NSFW_LOGINF ("init rec pool and ring suc!"); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_reg_obj +* Description : reg one recycle object +* Input : u8 priority +* u16 rec_type +* void* data +* Output : None +* Return Value : void * +* Calls : +* Called By : +*****************************************************************************/ +void * +nsfw_recycle_reg_obj (u8 priority, u16 rec_type, void *data) +{ + if (NSFW_REC_PRO_MAX <= priority) + { + NSFW_LOGERR ("pro error]priority=%d,rec_type=%d,data=%p", priority, + rec_type, data); + return NULL; + } + + nsfw_recycle_obj *obj = NULL; + if (0 == + nsfw_mem_ring_dequeue (g_rec_cfg.mem_rec_pro[priority], (void *) &obj)) + { + NSFW_LOGERR ("dequeue error]priority=%d,rec_type=%d,data=%p", + priority, rec_type, data); + return NULL; + } + + if (EOK != MEMSET_S (obj, sizeof (*obj), 0, sizeof (*obj))) + { + if (0 == nsfw_mem_ring_enqueue (g_rec_cfg.mem_rec_pro[priority], obj)) + { + NSFW_LOGERR ("enqueue error]priority=%d,rec_type=%d,data=%p", + priority, rec_type, data); + } + + NSFW_LOGERR ("mem set error]priority=%d,rec_type=%d,data=%p", + priority, rec_type, data); + return NULL; + } + + obj->alloc_flag = TRUE; + obj->rec_type = rec_type; + obj->data = data; + obj->host_pid = get_sys_pid (); + obj->alloc_flag = TRUE; + NSFW_LOGINF ("en queue obj]priority=%d,rec_type=%d,data=%p", priority, + rec_type, data); + return obj; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_rechk_lock +* Description : add for rechk lock +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_recycle_rechk_lock () +{ + return nsfw_ps_rechk_pid_exit (nsfw_recycle_exit_pid_lock, NULL); +} + +/***************************************************************************** +* Prototype : nsfw_recycle_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : static int +* Calls : +* Called By : +*****************************************************************************/ +NSTACK_STATIC int nsfw_recycle_module_init (void *param); +NSTACK_STATIC int +nsfw_recycle_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + NSFW_LOGINF ("recycle module init]type=%d", proc_type); + g_rec_cfg.rec_waite_end_tvalue = NSFW_REC_WEND_TVLAUE_DEF; + switch (proc_type) + { + case NSFW_PROC_MASTER: + return 0; + case NSFW_PROC_MAIN: + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_APP_EXIT_REQ, mem_app_exit_proc); + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_RCC_END_REQ, + nsfw_recycle_obj_end_proc); + if (TRUE == mem_rec_zone_init ()) + { + return 0; + } + + return 0; + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + return -1; + } + + return 0; +} + +/***************************************************************************** +* Prototype : nsfw_recycle_fork_init +* Description : fork init +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_recycle_fork_init () +{ + /* reconnect to master after fork in child proc */ + nsfw_mgr_close_dst_proc (NSFW_PROC_MAIN, 0); + nsfw_mgr_close_dst_proc (NSFW_PROC_MASTER, 0); + if (0 == nsfw_recycle_module_init ((void *) ((long long) NSFW_PROC_APP))) + { + return TRUE; + } + return FALSE; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_RECYCLE_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_PS_MEM_MODULE) +NSFW_MODULE_INIT (nsfw_recycle_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/ipc/ps/nsfw_recycle_module.h b/src/framework/ipc/ps/nsfw_recycle_module.h new file mode 100644 index 0000000..694c1d2 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_recycle_module.h @@ -0,0 +1,84 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RECYCLE_MODULE_H +#define _NSFW_RECYCLE_MODULE_H + +#include "nsfw_recycle_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define MEM_RECYCLE_PER_PRO_QUE 128 +#define MEM_RECYCLE_OBJ_MAX_NUM (MEM_RECYCLE_PER_PRO_QUE*NSFW_REC_PRO_MAX) + +#define MEM_REC_POOL_NAME "APP_REC_POOL" +#define MEM_REC_QUEUE_NAME "APP_REC_RINGQ" + +#define REC_POOL_MAGIC_FLAG 0xDBFC01A600000000 + +#define NSFW_REC_WEND_TIMER 1 +#define NSFW_REC_WEND_TVLAUE_DEF 60 + +#define NSFW_REC_WEND_TVLAUE (g_rec_cfg.rec_waite_end_tvalue) + +typedef struct _nsfw_recycle_obj +{ + u8 alloc_flag; + u8 u8reserve; + u16 rec_type; + u32 host_pid; + void *data; + u64 u64reserve; +} nsfw_recycle_obj; + +#define NSFW_REC_LOCK_REL_MAX_FUN 32 + +typedef struct _nsfw_rec_fun_info +{ + nsfw_recycle_fun rec_fun; + void *data; + u8 proc_type; +} nsfw_rec_fun_info; + +typedef struct _nsfw_recycle_pool +{ + u32 pool_size; + nsfw_recycle_obj obj[0]; +} nsfw_recycle_pool; + +typedef struct _nsfw_recycle_cfg +{ + u16 rec_waite_end_tvalue; + mring_handle mem_rec_obj_pool; + mzone_handle mem_rec_pro[NSFW_REC_PRO_MAX]; +} nsfw_recycle_cfg; + +extern nsfw_rcc_stat nsfw_recycle_callback_all_obj (u32 pid, + nsfw_recycle_pool * + rec_pool); +extern int nsfw_recycle_obj_timeout (u32 timer_type, void *data); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _NSFW_RECYCLE_MODULE_H */ diff --git a/src/framework/ipc/ps/nsfw_soft_param.c b/src/framework/ipc/ps/nsfw_soft_param.c new file mode 100644 index 0000000..d458040 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_soft_param.c @@ -0,0 +1,296 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nstack_log.h" +#include "nsfw_maintain_api.h" + +#include "nsfw_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +typedef struct _nsfw_set_soft_item +{ + void *data; + u32 size; + u64 max; + u64 min; +} nsfw_set_soft_item; + +/* *INDENT-OFF* */ +nsfw_set_soft_fun g_soft_fun[NSFW_MAX_SOFT_PARAM] = { 0 }; +nsfw_set_soft_item g_soft_int_cfg[NSFW_MAX_SOFT_PARAM]; +/* *INDENT-ON* */ + +int +nsfw_isdigitstr (const char *str) +{ + if (NULL == str || '\0' == str[0]) + return 0; + + while (*str) + { + if (*str < '0' || *str > '9') + return 0; + str++; + } + return 1; +} + +u8 +nsfw_soft_param_reg_fun (u32 param_name, nsfw_set_soft_fun fun) +{ + if (NULL == fun || param_name >= NSFW_MAX_SOFT_PARAM) + { + NSFW_LOGERR ("argv err]fun=%p,type=%u", fun, param_name); + return FALSE; + } + + g_soft_fun[param_name] = fun; + NSFW_LOGINF ("reg]fun=%d,type=%u", fun, param_name); + return TRUE; +} + +int +nsfw_soft_set_int (u32 param, char *buf, u32 buf_len) +{ + u64 buf_value = 0; + if (NULL == buf || param >= NSFW_MAX_SOFT_PARAM) + { + NSFW_LOGERR ("argv err]buf=%p,param=%u", buf, param); + return FALSE; + } + + if (!nsfw_isdigitstr (buf)) + { + NSFW_LOGERR ("argv err]buf=%s,param=%u", buf, param); + return FALSE; + } + + char *parsing_end; + buf_value = (u64) strtol (buf, &parsing_end, 10); + nsfw_set_soft_item *int_item = &g_soft_int_cfg[param]; + if (NULL == int_item->data) + { + NSFW_LOGERR ("data err]buf=%s,param=%u,min=%llu,max=%llu", buf, param, int_item->min, int_item->max); //[DTS2017112402499][2017-11-24][z00316269] Issue #40, fix type dismatch + return FALSE; + } + + if (buf_value < int_item->min || buf_value > int_item->max) + { + NSFW_LOGERR ("argv err]buf=%s,param=%u,min=%llu,max=%llu", buf, param, int_item->min, int_item->max); //[DTS2017112402499][2017-11-24][z00316269] Issue #40, fix type dismatch + return FALSE; + } + + u32 size = int_item->size; + if (size >= sizeof (u64)) + { + size = sizeof (u64); + } + + if (EOK != MEMCPY_S (int_item->data, size, &buf_value, size)) + { + NSFW_LOGERR ("MEMCPY_S failed"); + return FALSE; + } + + NSFW_LOGINF ("set soft param ok]param=%u,value=%llu,size=%u", param, + buf_value, size); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_soft_param_reg_int +* Description : reg int param set +* Input : u32 param_name +* u32 size +* u32 min +* u32 max +* u64 *data +* Output : None +* Return Value : u8 +* Calls : +* Called By : +*****************************************************************************/ +u8 +nsfw_soft_param_reg_int (u32 param_name, u32 size, u32 min, u32 max, + u64 * data) +{ + if (NULL == data || param_name >= NSFW_MAX_SOFT_PARAM) + { + NSFW_LOGERR ("argv err]data=%p,type=%u", data, param_name); + return FALSE; + } + + g_soft_int_cfg[param_name].data = data; + g_soft_int_cfg[param_name].size = size; + g_soft_int_cfg[param_name].max = max; + g_soft_int_cfg[param_name].min = min; + return nsfw_soft_param_reg_fun (param_name, nsfw_soft_set_int); +} + +void +nsfw_set_soft_para (fw_poc_type proc_type, u32 para_name, void *value, + u32 size) +{ + nsfw_mgr_msg *msg = + (nsfw_mgr_msg *) nsfw_mgr_msg_alloc (MGR_MSG_SOF_PAR_REQ, proc_type); + if (NULL == msg) + { + NSFW_LOGERR + ("nsfw_mgr_msg_alloc failed] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + return; + } + + nsfw_soft_param_msg *soft_msg = GET_USER_MSG (nsfw_soft_param_msg, msg); + + soft_msg->param_name = para_name; + soft_msg->rsp_code = 0; + + if (EOK != + MEMCPY_S (soft_msg->param_value, sizeof (soft_msg->param_value), + value, size)) + { + NSFW_LOGERR + ("MEMCPY_S failed] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + nsfw_mgr_msg_free (msg); + return; + } + + nsfw_mgr_msg *rsp = nsfw_mgr_null_rspmsg_alloc (); + if (NULL == rsp) + { + NSFW_LOGERR + ("nsfw_mgr_null_rspmsg_alloc failed] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + nsfw_mgr_msg_free (msg); + return; + } + + if (!nsfw_mgr_send_req_wait_rsp (msg, rsp)) + { + NSFW_LOGERR + ("can not get response] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp); + return; + } + + nsfw_soft_param_msg *soft_rsp_msg = GET_USER_MSG (nsfw_soft_param_msg, rsp); + if (soft_rsp_msg->rsp_code != NSFW_EXIT_SUCCESS) + { + NSFW_LOGERR + ("set soft param failed] msg type=%d, proc type=%d, para_name=%u, rsp code=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name, soft_rsp_msg->rsp_code); + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp); + return; + } + + NSFW_LOGINF + ("set soft param success] msg type=%d, proc type=%d, para_name=%u", + MGR_MSG_SOF_PAR_REQ, proc_type, para_name); + + nsfw_mgr_msg_free (msg); + nsfw_mgr_msg_free (rsp); + return; +} + +int +nsfw_softparam_msg_proc (nsfw_mgr_msg * msg) +{ + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp failed,drop msg!" MSGINFO, PRTMSG (msg)); + return FALSE; + } + + nsfw_soft_param_msg *soft_msg = GET_USER_MSG (nsfw_soft_param_msg, msg); + nsfw_soft_param_msg *soft_rsp_msg = + GET_USER_MSG (nsfw_soft_param_msg, rsp_msg); + if ((soft_msg->param_name < NSFW_MAX_SOFT_PARAM) + && (NULL != g_soft_fun[soft_msg->param_name])) + { + soft_msg->param_value[sizeof (soft_msg->param_value) - 1] = 0; + (void) g_soft_fun[soft_msg->param_name] (soft_msg->param_name, + (char *) + soft_msg->param_value, + sizeof + (soft_msg->param_value)); + soft_rsp_msg->rsp_code = NSFW_EXIT_SUCCESS; + } + else + { + NSFW_LOGERR ("set soft failed!]soft=%u", soft_msg->param_name); + soft_rsp_msg->rsp_code = NSFW_EXIT_FAILED; + } + + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + return TRUE; +} + +int nsfw_softparam_module_init (void *param); +int +nsfw_softparam_module_init (void *param) +{ + u8 proc_type = (u8) ((long long) param); + NSFW_LOGINF ("softparam module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MAIN: + case NSFW_PROC_MASTER: + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_SOF_PAR_REQ, + nsfw_softparam_msg_proc); + return 0; + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_SOFT_PARAM_MODULE) +NSFW_MODULE_PRIORITY (99) +NSFW_MODULE_INIT (nsfw_softparam_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/lib_common_mem/common_api.c b/src/framework/lib_common_mem/common_api.c new file mode 100644 index 0000000..b535ee6 --- /dev/null +++ b/src/framework/lib_common_mem/common_api.c @@ -0,0 +1,325 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include "common_mem_api.h" +#include "common_mem_pal.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "common_func.h" + +void +sys_sem_init_v2 (sys_sem_t_v2 sem) +{ + sem->locked = 1; +} + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +long +sys_now (void) +{ + struct timespec now; + + if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &now))) + { + NSCOMM_LOGERR ("Failed to get time, errno = %d", errno); + } + + return 1000 * now.tv_sec + now.tv_nsec / 1000000; +} + +long +sys_jiffies (void) +{ + return sys_now (); +} + +err_t +sys_sem_new_v2 (sys_sem_t_v2 * sem, u8_t isUnLockd) +{ + int retVal; + if (!sem) + { + return -1; + } + *sem = malloc (sizeof (common_mem_spinlock_t)); + + if (NULL == *sem) + { + return -1; + } + else + { + retVal = + MEMSET_S (*sem, sizeof (common_mem_spinlock_t), 0, + sizeof (common_mem_spinlock_t)); + if (EOK != retVal) + { + NSCOMM_LOGERR ("MEMSET_S failed]ret=%d", retVal); + free (*sem); + *sem = NULL; + return -1; + } + common_mem_spinlock_init (*sem); + } + + if (!isUnLockd) + { + common_mem_spinlock_lock (*sem); + } + + return 0; +} + +void +sys_sem_free_v2 (sys_sem_t_v2 * sem) +{ + if ((sem != NULL) && (*sem != NULL)) + { + free (*sem); + *sem = NULL; + } + else + { + } +} + +void +sys_sem_signal_v2 (sys_sem_t_v2 * sem) +{ + common_mem_spinlock_unlock (*sem); +} + +void +sys_sem_signal_s_v2 (sys_sem_t_v2 sem) +{ + common_mem_spinlock_unlock (sem); +} + +u32_t +sys_arch_sem_trywait_v2 (sys_sem_t_v2 * sem) +{ + return (u32_t) common_mem_spinlock_trylock (*sem); +} + +u32_t +sys_arch_sem_wait_v2 (sys_sem_t_v2 * pstsem) +{ + common_mem_spinlock_lock (*pstsem); + return 0; +} + +u32_t +sys_arch_sem_wait_s_v2 (sys_sem_t_v2 sem) +{ + common_mem_spinlock_lock (sem); + return 0; +} + +volatile pid_t g_sys_host_pid = SYS_HOST_INITIAL_PID; + +/***************************************************************************** +* Prototype : get_exec_name_by_pid +* Description : get exec name by pid +* Input : pid_t pid +* char *task_name +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +get_exec_name_by_pid (pid_t pid, char *task_name, int task_name_len) +{ + int retVal; + char path[READ_FILE_BUFLEN] = { 0 }; + char buf[READ_FILE_BUFLEN] = { 0 }; + + retVal = SPRINTF_S (path, sizeof (path), "/proc/%d/status", pid); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + return; + } + + FILE *fp = fopen (path, "r"); + if (NULL != fp) + { + if (fgets (buf, READ_FILE_BUFLEN - 1, fp) == NULL) + { + fclose (fp); + return; + } + fclose (fp); + +#ifdef SECUREC_LIB + retVal = SSCANF_S (buf, "%*s %s", task_name, task_name_len); +#else + retVal = SSCANF_S (buf, "%*s %s", task_name); +#endif + + if (1 != retVal) + { + NSSOC_LOGERR ("SSCANF_S failed]ret=%d", retVal); + return; + } + } +} + +pid_t +get_hostpid_from_file_one_time (u32_t pid) +{ + int retVal; + char path[READ_FILE_BUFLEN] = { 0 }; + char buf[READ_FILE_BUFLEN] = { 0 }; + char fmt[READ_FILE_BUFLEN] = { 0 }; + char out[READ_FILE_BUFLEN] = { 0 }; + char task_name[BUF_SIZE_FILEPATH] = { 0 }; + pid_t hostpid = SYS_HOST_INITIAL_PID; + get_exec_name_by_pid (pid, task_name, BUF_SIZE_FILEPATH); + + retVal = SPRINTF_S (fmt, sizeof (fmt), "%s%s", task_name, " (%s"); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + return hostpid; + } + retVal = SPRINTF_S (path, sizeof (path), "/proc/%d/sched", pid); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + return hostpid; + } + FILE *fp = fopen (path, "r"); + if (NULL != fp) + { + if (fgets (buf, READ_FILE_BUFLEN - 1, fp) == NULL) + { + fclose (fp); + return hostpid; + } + fclose (fp); + /* Compiler needs "fmt" to be like "%s%s" to + understand. But we have "fmt" already prepared and used here. It can + be suppressed, not an issue + */ +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + retVal = SSCANF_S (buf, fmt, out, READ_FILE_BUFLEN); + if (-1 == retVal) + { + NSPOL_LOGERR ("SSCANF_S failed]ret=%d", retVal); + return hostpid; + } + } + + hostpid = (pid_t) strtol (out, NULL, 0); + if (hostpid == 0) + { + hostpid = 1; + } + + return hostpid; +} + +#define MAX_GET_PID_TIME 10 +pid_t +get_hostpid_from_file (u32_t pid) +{ + pid_t ret_pid = SYS_HOST_INITIAL_PID; + int i = 0; + ret_pid = get_hostpid_from_file_one_time (pid); + while (0 == ret_pid || ret_pid == SYS_HOST_INITIAL_PID) + { + i++; + if (i > MAX_GET_PID_TIME) + { + NSFW_LOGERR ("get pid failed]pid=%u,hostpid=%d", pid, ret_pid); + break; + } + sys_sleep_ns (0, 5000000); + ret_pid = get_hostpid_from_file_one_time (pid); + } + + return ret_pid; +} + +/***************************************************************************** +* Prototype : get_hostpid_from_file +* Description : get host pid by sub namespace pid in docker +* Input : uint32_t pid +* Output : None +* Return Value : uint32_t +* Calls : +* Called By : +*****************************************************************************/ +pid_t +sys_get_hostpid_from_file (pid_t pid) +{ + g_sys_host_pid = get_hostpid_from_file (pid); + NSCOMM_LOGDBG ("ok]cur pid=%d, input pid=%d", g_sys_host_pid, pid); + return g_sys_host_pid; +} + +pid_t +updata_sys_pid () +{ + g_sys_host_pid = SYS_HOST_INITIAL_PID; + return get_sys_pid (); +} + +/***************************************************************************** +* Prototype : get_pid_namespace +* Description : Get namespace of pid +* Input : uint32_t pid +* Output : None +* Return Value : uint64_t +* Calls : +* Called By : +*****************************************************************************/ +uint64_t +get_pid_namespace (pid_t pid) +{ + char buf[BUF_SIZE_FILEPATH] = { 0 }; + char path[BUF_SIZE_FILEPATH] = { 0 }; + const char *pstart; + int ret = 0; + if (!pid) + { + NSSOC_LOGERR ("Pid is zero!"); + return 0; + } + + ret = + SNPRINTF_S (path, sizeof (path), sizeof (path) - 1, "/proc/%d/ns/pid", + pid); + if (-1 == ret) + { + NSSOC_LOGERR ("SNPRINTF_S failed]ret=%d", ret); + return 0; + } + + ret = readlink (path, buf, sizeof (buf) - 1); + if (ret <= (int) sizeof (STR_PID)) + { + NSSOC_LOGERR ("readlink pid ns file error]ret=%d", ret); + return 0; + } + + buf[ret - 1] = 0; + pstart = &(buf[sizeof (STR_PID)]); + return strtoull (pstart, NULL, 10); +} diff --git a/src/framework/lib_common_mem/common_buf.c b/src/framework/lib_common_mem/common_buf.c new file mode 100644 index 0000000..523ce54 --- /dev/null +++ b/src/framework/lib_common_mem/common_buf.c @@ -0,0 +1,260 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdarg.h> +#include <inttypes.h> +#include <errno.h> +#include <ctype.h> +#include <sys/queue.h> + +#include "common_mem_base_type.h" + +#include "common_mem_common.h" + +#include "common_mem_memzone.h" + +#include "common_mem_pal.h" + +#include "common_mem_mempool.h" +#include "common_mem_buf.h" + +#include "nstack_log.h" +#include "nstack_securec.h" + +#include "common_func.h" +#include "common_pal_bitwide_adjust.h" + +#define LOG_ERR 0 +#define LOG_WARN 1 +#define LOG_INFO 2 +#define LOG_DEBUG 3 +#define LOG_MAX 4 + +#define COMMON_LOG_PRINT(leve, fmt, args...) \ + if (leve <= log_levl) NSCOMM_LOGERR("===>[COMMON]"fmt, ##args); \ + +#define COMMON_PANIC(fmt) \ + NSCOMM_LOGERR("==>[COMMON_PANIC]"fmt); \ + common_dump_stack(); \ + +#define PARA1_SET(argv, tempargv, Index, para1) do {\ + retVal = STRCPY_S(tempargv[Index], PATA_STRLENT, para1);\ + if (retVal != EOK)\ + {\ + NSCOMM_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index ++; } while (0) + +#define PARA2_SET(argv, tempargv, Index, para1, para2) do {\ + retVal = STRCPY_S(tempargv[Index], PATA_STRLENT, para1); \ + if (retVal != EOK)\ + {\ + NSCOMM_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index++; \ + retVal = STRCPY_S(tempargv[Index], PATA_STRLENT, para2); \ + if (retVal != EOK)\ + {\ + NSCOMM_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index ++; } while (0) + +#define PATA_STRLENT 64 +#define PATA_NUM_MAX 12 + +int log_levl = LOG_INFO; + +int +nscomm_pal_module_init (common_mem_pal_module_info * pinfo) +{ + char tempargv[PATA_NUM_MAX][PATA_STRLENT]; + char *argv[PATA_NUM_MAX]; + char tempbuf[PATA_STRLENT]; + unsigned int Index = 0; + int ioffset = 0; + int agindex = 0; + int intmask = 0; + int retVal; + retVal = MEMSET_S (tempargv, sizeof (tempargv), '\0', sizeof (tempargv)); + if (EOK != retVal) + { + NSCOMM_LOGERR ("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + retVal = MEMSET_S (argv, sizeof (argv), 0, sizeof (argv)); + if (EOK != retVal) + { + NSCOMM_LOGERR ("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + if (NULL == pinfo) + { + PARA1_SET (argv, tempargv, agindex, "nStackMain"); + PARA2_SET (argv, tempargv, agindex, "-c", "0x1"); + PARA2_SET (argv, tempargv, agindex, "-n", "4"); + PARA2_SET (argv, tempargv, agindex, "-m", "2048"); + PARA1_SET (argv, tempargv, agindex, "--huge-dir=/mnt/nstackhuge"); + PARA1_SET (argv, tempargv, agindex, "--proc-type=primary"); + } + else + { + PARA1_SET (argv, tempargv, agindex, "nStackMain"); + + /*[DTS2017032711606 ][2017-04-08][z00353090] There are some unsafe function ,need to be replace with safe function */ + retVal = SPRINTF_S (tempbuf, PATA_STRLENT, "0x"); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", ioffset); + return DMM_MBUF_RET_ERR; + } + ioffset = retVal; + for (Index = 0; Index < LCORE_MASK_MAX; Index++) + { + if (ioffset >= PATA_STRLENT) + { + NSCOMM_LOGERR ("SPRINTF_S tempbuf overflow]ioffset=%d", + ioffset); + return DMM_MBUF_RET_ERR; + } + retVal = + SPRINTF_S (&(tempbuf[ioffset]), PATA_STRLENT - ioffset, "%8u", + pinfo->ilcoremask[Index]); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", ioffset); + return DMM_MBUF_RET_ERR; + } + ioffset = ioffset + retVal; + intmask |= pinfo->ilcoremask[Index]; + } + if (0 == intmask) + { + PARA2_SET (argv, tempargv, agindex, "-c", "0x1"); + } + else + { + PARA2_SET (argv, tempargv, agindex, "-c", tempbuf); + } + if (pinfo->ishare_mem_size > 0) + { + retVal = MEMSET_S (tempbuf, PATA_STRLENT, 0, PATA_NUM_MAX); + if (EOK != retVal) + { + NSCOMM_LOGERR ("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + retVal = + SPRINTF_S (tempbuf, PATA_STRLENT, "%d", pinfo->ishare_mem_size); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + PARA2_SET (argv, tempargv, agindex, "-m", tempbuf); + } + + retVal = MEMSET_S (tempbuf, PATA_STRLENT, 0, PATA_NUM_MAX); + if (EOK != retVal) + { + NSCOMM_LOGERR ("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + + switch (pinfo->ucproctype) + { + case DMM_PROC_T_PRIMARY: + retVal = SPRINTF_S (tempbuf, PATA_STRLENT, "--proc-type=primary"); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + case DMM_PROC_T_SECONDARY: + retVal = SPRINTF_S (tempbuf, PATA_STRLENT, "--proc-type=secondary"); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + case DMM_PROC_T_AUTO: + default: + retVal = SPRINTF_S (tempbuf, PATA_STRLENT, "--proc-type=auto"); + if (-1 == retVal) + { + NSCOMM_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + } + PARA1_SET (argv, tempargv, agindex, tempbuf); + + if (DMM_HUGTBL_DISABLE == pinfo->uchugeflag) + { + PARA1_SET (argv, tempargv, agindex, "--no-huge"); + } + } + if (common_mem_pal_init (agindex, argv) < 0) + { + COMMON_LOG_PRINT (LOG_ERR, "Cannot init pal\r\n"); + return DMM_MBUF_RET_ERR; + } + return DMM_MBUF_RET_OK; +} + +void * +nscomm_memzone_data_reserve_name (const char *name, size_t len, int socket_id) +{ + const struct common_mem_memzone *mz = NULL; + /* + rte_memzone_reserve must Call first, cause rte_memzone_reserve has a globe lock. + while proc race happen, who(calls A) got lock first will create memzone success. + others create same memzone proc will got lock after A, and rte_memzone_reserve return NULL; + so while rte_memzone_reserve return NULL we need do rte_memzone_lookup; + */ + mz = common_mem_memzone_reserve (name, len, socket_id, 0); + if (mz == NULL) + { + mz = common_mem_memzone_lookup (name); + } + + return mz ? (void *) ADDR_SHTOL (mz->addr_64) : NULL; +} + +void * +nscomm_memzone_data_lookup_name (const char *name) +{ + void *addr = NULL; + const struct common_mem_memzone *mz = NULL; + mz = common_mem_memzone_lookup (name); + if (mz == NULL) + { + return NULL; + } + addr = (void *) ADDR_SHTOL (mz->addr_64); + return addr; +} diff --git a/src/framework/lib_common_mem/common_func.c b/src/framework/lib_common_mem/common_func.c new file mode 100644 index 0000000..f68380f --- /dev/null +++ b/src/framework/lib_common_mem/common_func.c @@ -0,0 +1,205 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "common_mem_pal_memconfig.h" +#include "common_mem_mbuf.h" +#include "common_mem_common.h" +#include "nstack_log.h" +#include "common_pal_bitwide_adjust.h" + +#include "common_func.h" + +#include "nstack_securec.h" + +#define COMMON_PROCESS_MAPS "/proc/self/maps" + +int g_PrimSameFlg = 1; + +NSTACK_STATIC void **g_PrimAddr2LocalMap = NULL; +NSTACK_STATIC void *g_LocalBaseAddr = NULL; +NSTACK_STATIC void *g_LocalMaxAddr = NULL; +NSTACK_STATIC void *g_LocalCfgAddrBase = NULL; + +NSTACK_STATIC uint64_t *g_LocalAddr2PrimMap = NULL; +NSTACK_STATIC uint64_t g_PrimBaseAddr = 0; +NSTACK_STATIC uint64_t g_PrimMaxAddr = 0; +NSTACK_STATIC uint64_t g_PrimCfgAddrBase = 0; + +NSTACK_STATIC uint64_t g_LBitMask = 0; +NSTACK_STATIC int g_LBitMaskLen = 0; + +uint64_t +pal_laddr_to_shddr (void *LAddr) +{ + size_t l2pIdx; + + if (g_PrimSameFlg || LAddr == NULL) + { + return (uint64_t) LAddr; + } + + /*calculate the IDX */ + l2pIdx = (ALIGN_PTR (LAddr) - ALIGN_PTR (g_LocalBaseAddr)) >> g_LBitMaskLen; + + /*check the Hugepage Addr Rang */ + if (LAddr <= g_LocalMaxAddr && LAddr >= g_LocalBaseAddr + && g_LocalAddr2PrimMap[l2pIdx]) + { + return g_LocalAddr2PrimMap[l2pIdx] + (ALIGN_PTR (LAddr) & g_LBitMask); + } + + /*check the Cfg Mapping Addr Rang */ + if (LAddr >= g_LocalCfgAddrBase + && LAddr <= + (void *) ((char *) g_LocalCfgAddrBase + + sizeof (struct common_mem_mem_config))) + { + return g_PrimCfgAddrBase + ((char *) LAddr - + (char *) g_LocalCfgAddrBase); + } + + NSCOMM_LOGWAR + ("WARNING!!! Input invalid LAddr]LAddr=%p, g_LocalBaseAddr=%p, g_LocalMaxAddr=%p, g_LocalCfgAddrBase=%p, g_LocalCfgAddrMax=%p.", + LAddr, g_LocalBaseAddr, g_LocalMaxAddr, g_LocalCfgAddrBase, + (char *) g_LocalCfgAddrBase + sizeof (struct common_mem_mem_config)); + + return (uint64_t) LAddr; +} + +void * +pal_shddr_to_laddr (uint64_t PAddr) +{ + size_t p2lIdx; + + if (g_PrimSameFlg || PAddr == ALIGN_PTR (NULL)) + { + return (void *) PAddr; + } + + p2lIdx = (PAddr - g_PrimBaseAddr) >> g_LBitMaskLen; + /*check the Hugepage Addr Rang */ + if (PAddr <= g_PrimMaxAddr && PAddr >= g_PrimBaseAddr + && g_PrimAddr2LocalMap[p2lIdx]) + { + return (void *) ((uint64_t) g_PrimAddr2LocalMap[p2lIdx] + + (PAddr & g_LBitMask)); + } + + /*check the Cfg Mapping Addr Rang */ + if (PAddr >= g_PrimCfgAddrBase + && PAddr <= g_PrimCfgAddrBase + sizeof (struct common_mem_mem_config)) + { + return (void *) ((uint64_t) g_LocalCfgAddrBase + PAddr - + g_PrimCfgAddrBase); + } + + NSCOMM_LOGWAR + ("WARNING!!! Input invalid PAddr]PAddr=%lx, g_PrimBaseAddr=%lx, g_PrimMaxAddr=%lx, g_PrimCfgAddrBase=%lx, g_PrimCfgAddrMax=%lx.", + PAddr, g_PrimBaseAddr, g_PrimMaxAddr, g_PrimCfgAddrBase, + g_PrimCfgAddrBase + sizeof (struct common_mem_mem_config)); + + return (void *) PAddr; +} + +/*lint +e539 */ + +int +dmm_pal_addr_align () +{ + return g_PrimSameFlg; +} + +int32_t +dmm_pktmbuf_pool_iterator (struct common_mem_mempool * mp, uint32_t start, + uint32_t end, dmm_mbuf_item_fun fun, void *argv) +{ + if (NULL == mp || fun == NULL) + { + return 0; + } + + if (start >= mp->size || end <= start) + { + return 0; + } + + int32_t elm_size = mp->elt_size + mp->header_size + mp->trailer_size; + struct common_mem_mbuf *elm_mbuf = (struct common_mem_mbuf *) (mp->elt_va_start + start * elm_size + mp->header_size); /*lint !e647 */ + + uint32_t i; + uint32_t mbuf_end = COMMON_MEM_MIN (end, mp->size) - start; + for (i = 0; i < mbuf_end; i++) + { + (void) fun (elm_mbuf, argv); + elm_mbuf = (struct common_mem_mbuf *) ((char *) elm_mbuf + elm_size); + } + + return mbuf_end; +} + +void +dmm_addr_print (void) +{ + const struct common_mem_mem_config *mcfg = + common_mem_pal_get_configuration ()->mem_config; + int s; + FILE *fd; + char *ptembuf = NULL; + if (!mcfg) + { + NSCOMM_LOGERR ("mcfg is null"); + return; + } + /*printf base address */ + NSCOMM_LOGINF ("********master baseaddr begin***************"); + for (s = 0; s < COMMON_MEM_MAX_MEMSEG; ++s) + { + if ((mcfg->memseg[s].len > 0) && (mcfg->memseg[s].addr != 0)) + { + NSCOMM_LOGINF ("addr:%p, len:%u", mcfg->memseg[s].addr, + mcfg->memseg[s].len); + } + } + NSCOMM_LOGINF ("********master baseaddr end***************"); + + fd = fopen (COMMON_PROCESS_MAPS, "r"); + if (!fd) + { + NSCOMM_LOGERR ("/proc/self/maps open fail, erro:%d", errno); + return; + } + + ptembuf = (char *) malloc (BUFSIZ); + if (!ptembuf) + { + NSCOMM_LOGERR ("malloc buff failed]buff_len=%d", BUFSIZ); + fclose (fd); + return; + } + if (EOK != MEMSET_S (ptembuf, BUFSIZ, 0, BUFSIZ)) + { + NSCOMM_LOGERR ("MEMSET_S failed] buff=%p", ptembuf); + } + NSCOMM_LOGINF ("********self process addr space begin***************"); + while (fgets (ptembuf, BUFSIZ, fd) != NULL) + { + NSCOMM_LOGERR ("%s", ptembuf); + } + NSCOMM_LOGINF ("********self process addr space end*****************"); + fclose (fd); + free (ptembuf); + return; +} diff --git a/src/framework/log/nsfw_set_log.c b/src/framework/log/nsfw_set_log.c new file mode 100644 index 0000000..a4b3b92 --- /dev/null +++ b/src/framework/log/nsfw_set_log.c @@ -0,0 +1,228 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "types.h" +#include "nstack_securec.h" +#include "nsfw_init.h" + +#include "nstack_log.h" +#include "nsfw_maintain_api.h" +#include "nsfw_mem_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +typedef struct _nsfw_log_cfg +{ + u8 proc_type; + char master_log_path[NSFW_LOG_VALUE_LEN]; + char runing_log_path[NSFW_LOG_VALUE_LEN]; + char opr_log_path[NSFW_LOG_VALUE_LEN]; +} nsfw_log_cfg; + +nsfw_log_cfg g_log_cfg; + +const char nsfw_mas_log[NSFW_LOG_VALUE_LEN] = "maspath"; +const char nsfw_flush_name[NSFW_LOG_VALUE_LEN] = "flush"; + +enum _set_log_type +{ + SET_LOG_LEVEL = 0, + SET_LOG_FLUSH, + SET_LOG_MASTER, + SET_LOG_MAIN, + + SET_LOG_INVALID +}; + +/***************************************************************************** +* Prototype : nsfw_set_log_path +* Description : set log path +* Input : const char *param +* const char *value +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_set_log_path (const char *param, const char *value) +{ + if (NULL == param || NULL == value) + { + NSFW_LOGERR ("log param error!]param=%p,value=%p", param, value); + return FALSE; + } + + if (cmp_log_path (value)) + { + if (check_log_dir_valid (value) < 0) + { + NSFW_LOGERR ("path is invalid]value=%s", value); + return FALSE; + } + if (EOK != + STRCPY_S (g_log_cfg.master_log_path, NSFW_LOG_VALUE_LEN, value)) + { + NSFW_LOGERR ("strcpy error!"); + return FALSE; + } + + NSFW_LOGINF ("renew log path]%s", g_log_cfg.master_log_path); + nstack_modify_log_dir (g_log_cfg.master_log_path); + NSFW_LOGINF ("set log sucess]newpath=%s!", g_log_cfg.master_log_path); + return TRUE; + } + return FALSE; +} + +/***************************************************************************** +* Prototype : nsfw_flush_log_info +* Description : flush the log info +* Input : const char *param +* u8 proc_type +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_flush_log_info (const char *param, u8 proc_type) +{ + if (NULL == param) + { + NSFW_LOGERR ("log param error!]param=%p", param); + return FALSE; + } + glogFlushLogFiles (GLOG_LEVEL_DEBUG); + NSFW_LOGINF ("flush log sucess]proc_type=%u", proc_type); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_set_log_msg_proc +* Description : set log message process +* Input : nsfw_mgr_msg* msg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_set_log_msg_proc (nsfw_mgr_msg * msg) +{ + int ret = -1; + int status = -1; + if (NULL == msg) + { + NSFW_LOGERR ("msg nul"); + return FALSE; + } + + nsfw_set_log_msg *set_log_msg = GET_USER_MSG (nsfw_set_log_msg, msg); + + if (0 == strcmp (set_log_msg->module, nsfw_mas_log)) + { + status = SET_LOG_MASTER; + } + else if (0 == strcmp (set_log_msg->module, nsfw_flush_name)) + { + status = SET_LOG_FLUSH; + } + else if (nsfw_isdigitstr (set_log_msg->module)) + { + status = SET_LOG_LEVEL; + } + + switch (status) + { + case SET_LOG_LEVEL: + ret = setlog_level_value (set_log_msg->module, set_log_msg->log_level); + break; + case SET_LOG_FLUSH: + ret = nsfw_flush_log_info (set_log_msg->module, msg->dst_proc_type); + break; + case SET_LOG_MASTER: + ret = nsfw_set_log_path (set_log_msg->module, set_log_msg->log_level); + break; + default: + NSFW_LOGERR ("default error]status=%d,set_log_msg->module=%s", status, + set_log_msg->module); + return FALSE; + } + + nsfw_mgr_msg *rsp_msg = nsfw_mgr_rsp_msg_alloc (msg); + if (NULL == rsp_msg) + { + NSFW_LOGERR ("alloc rsp failed,drop msg!" MSGINFO, PRTMSG (msg)); + return FALSE; + } + nsfw_set_log_msg *log_rsp_msg = GET_USER_MSG (nsfw_set_log_msg, rsp_msg); + log_rsp_msg->rsp_code = ret; + (void) nsfw_mgr_send_msg (rsp_msg); + nsfw_mgr_msg_free (rsp_msg); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_cfg_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : static int +* Calls : +* Called By : +*****************************************************************************/ +static int nsfw_cfg_module_init (void *param); +static int +nsfw_cfg_module_init (void *param) +{ + u8 proc_type = (u8) ((long long) param); + NSFW_LOGINF ("log cfg module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MAIN: + case NSFW_PROC_MASTER: + (void) nsfw_mgr_reg_msg_fun (MGR_MSG_SET_LOG_REQ, + nsfw_set_log_msg_proc); + g_log_cfg.proc_type = proc_type; + return 0; + default: + if (proc_type < NSFW_PROC_MAX) + { + break; + } + return -1; + } + + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_LOG_CFG_MODULE) +NSFW_MODULE_PRIORITY (99) +NSFW_MODULE_INIT (nsfw_cfg_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/log/nstack_log.c b/src/framework/log/nstack_log.c new file mode 100644 index 0000000..5e8ffd4 --- /dev/null +++ b/src/framework/log/nstack_log.c @@ -0,0 +1,825 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ + +#include "nstack_log.h" +#include <sys/stat.h> +#include <dirent.h> +#include <time.h> +#include <errno.h> +#include <execinfo.h> +#include <fcntl.h> +#include "nstack_securec.h" +#include <pthread.h> + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ + +#define FILE_NAME_LEN 256 +#define MAX_PRE_INIT_LOG_COUNT 256 +#define MAX_LOCK_RETRY_COUNT 50000 /* changed MAX_LOCK_RETRY_COUNT to 50000 to avoid function being blocked for too long */ +/* *INDENT-OFF* */ +int g_l4_dump_enable = 0; +static int pre_init_log_count = 0; +static struct pre_init_info pre_init_log[MAX_PRE_INIT_LOG_COUNT] = {{0, ""}}; +/* *INDENT-ON* */ +__thread unsigned int nstack_log_nonreentry = 0; +int ctrl_log_switch = 0; + +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ +struct nstack_logs g_nstack_logs[MAX_LOG_MODULE] = { {0, 0, 0, 0}, {0xFFFF, 0, 0, 0} }; /* Clear compile warning */ +struct log_init_para g_log_init_para = + { 50, 10, NSTACK_LOG_NAME, 10, 10, NSTACK_LOG_NAME }; +static int g_my_pro_type = LOG_PRO_INVALID; + +#define DEFAULT_LOG_CTR_TIME 5 +static struct log_ctrl_info g_log_ctrl_info[LOG_CTRL_ID_MAX]; + +/*==============================================* + * routines' or functions' implementations * + *----------------------------------------------*/ + +/* change the print level, not only has err, Begin.*/ +void +save_pre_init_log (uint32_t level, char *fmt, ...) +{ + va_list ap; + int ret = 0; + /* add pre_init_log_count rang check */ + if (level > NSLOG_DBG || pre_init_log_count >= MAX_PRE_INIT_LOG_COUNT + || pre_init_log_count < 0) + + { + return; + } + pre_init_log[pre_init_log_count].log_buffer[PRE_INIT_LOG_LENGTH - 1] = '\0'; + (void) va_start (ap, fmt); + ret = + VSNPRINTF_S (pre_init_log[pre_init_log_count].log_buffer, + PRE_INIT_LOG_LENGTH, PRE_INIT_LOG_LENGTH - 1, fmt, ap); + if (-1 == ret) + { + va_end (ap); + return; + } + va_end (ap); + pre_init_log[pre_init_log_count].level = level; + pre_init_log_count++; +} + +void +write_pre_init_log () +{ + int i = 0; + for (; i < pre_init_log_count; i++) + { + if (NSLOG_ERR == pre_init_log[i].level) + { + NSPOL_LOGERR ("pre init log: %s", pre_init_log[i].log_buffer); + } + else if (NSLOG_WAR == pre_init_log[i].level) + { + NSPOL_LOGWAR (NS_LOG_STACKX_ON, "pre init log: %s", + pre_init_log[i].log_buffer); + } + else if (NSLOG_INF == pre_init_log[i].level) + { + NSPOL_LOGINF (NS_LOG_STACKX_ON, "pre init log: %s", + pre_init_log[i].log_buffer); + } + } +} + +int +cmp_log_path (const char *path) +{ + if (NULL == path) + { + return 1; + } + + /* remove struct log_info g_nstack_log_info */ + if (NULL != g_log_init_para.mon_log_path) + { + if (strcmp (g_log_init_para.mon_log_path, path) == 0) + { + return 0; + } + } + return 1; +} + +void +get_current_time (char *buf, const int len) +{ + int retVal; + time_t cur_tick; + struct tm cur_time; + (void) time (&cur_tick); + /* add return value check, */ + if (NULL == localtime_r (&cur_tick, &cur_time)) + { + return; + } + + // from man page of localtime_r: + // tm_year The number of years since 1900. + // tm_mon The number of months since January, in the range 0 to 11. + retVal = + SNPRINTF_S (buf, len, len - 1, "%04d%02d%02d%02d%02d%02d", + cur_time.tm_year + 1900, cur_time.tm_mon + 1, + cur_time.tm_mday, cur_time.tm_hour, cur_time.tm_min, + cur_time.tm_sec); + if (-1 == retVal) + { + return; + } + buf[len - 1] = 0; +} + +/***************************************************************************** +* Prototype : nstack_setlog_level +* Description : Set global log level +* Input : int module +* uint32_t level +* Output : None +* Return Value : void +* Calls : +* Called By : +*****************************************************************************/ +void +nstack_setlog_level (int module, uint32_t level) +{ + if (MAX_LOG_MODULE <= module || module < 0) + { + return; + } + g_nstack_logs[module].level = level; +} + +/***************************************************************************** +* Prototype : nstack_log_info_check +* Description : log info check +* Input : uint32_t module +* uint32_t level +* ... +* Output : None +* Return Value : bool +* Calls : +* Called By : +*****************************************************************************/ +bool +nstack_log_info_check (uint32_t module, uint32_t level) +{ + if (MAX_LOG_MODULE <= module) + { + return false; + } + + /* no need compare module ,which is done ahead */ + if (LOG_PRO_INVALID == g_my_pro_type) + { + return false; + } + return true; +} + +/* *INDENT-OFF* */ +NSTACK_STATIC inline void init_operation_log_para() +{ + g_nstack_logs[OPERATION].file_type = LOG_TYPE_OPERATION; +} + +NSTACK_STATIC inline void init_nstack_log_para() +{ + int i = 0; + + (void)glogLevelSet(GLOG_LEVEL_DEBUG); + glogBufLevelSet(GLOG_LEVEL_WARNING); + for(; i<GLOG_LEVEL_BUTT; i++) + glogSetLogSymlink(i,""); + glogDir(g_log_init_para.run_log_path); + nstack_log_count_set(g_log_init_para.run_log_count); + glogMaxLogSizeSet(g_log_init_para.run_log_size); + glogSetLogFilenameExtension(STACKX_LOG_NAME); + glogFlushLogSecsSet(FLUSH_TIME); + + for (i = 0; i < MAX_LOG_MODULE ; i++ ) + { + if (i == OPERATION) + { + continue; + } + g_nstack_logs[i].file_type = LOG_TYPE_NSTACK; + } + init_operation_log_para(); +} + +NSTACK_STATIC inline void init_ctrl_log_para() +{ + int i = 0; + + (void)glogLevelSet(GLOG_LEVEL_DEBUG); + glogBufLevelSet(GLOG_LEVEL_WARNING); + for(; i<GLOG_LEVEL_BUTT; i++) + glogSetLogSymlink(i,""); + glogDir(g_log_init_para.mon_log_path); + nstack_log_count_set(g_log_init_para.mon_log_count); + glogMaxLogSizeSet(g_log_init_para.mon_log_size); + glogSetLogFilenameExtension(OMC_CTRL_LOG_NAME); + glogFlushLogSecsSet(FLUSH_TIME); +} + +NSTACK_STATIC inline void init_master_log_para() +{ + int i = 0; + + (void)glogLevelSet(GLOG_LEVEL_DEBUG); + glogBufLevelSet(GLOG_LEVEL_WARNING); + for(; i<GLOG_LEVEL_BUTT; i++) + glogSetLogSymlink(i,""); + glogDir(g_log_init_para.mon_log_path); + nstack_log_count_set(g_log_init_para.mon_log_count); + glogMaxLogSizeSet(g_log_init_para.mon_log_size); + glogSetLogFilenameExtension(MASTER_LOG_NAME); + glogFlushLogSecsSet(FLUSH_TIME); + for (i = 0; i < MAX_LOG_MODULE ; i++ ) + { + g_nstack_logs[i].file_type = LOG_TYPE_MASTER; + } +} +/* *INDENT-OFF* */ + +/***************************************************************************** +* Prototype : nstack_log_init +* Description : called by environment-specific log init function +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int nstack_log_init() +{ + char *pst_temp = NULL; + int log_level = NSLOG_INF; + pst_temp = getenv("NSTACK_LOG_ON"); + if (pst_temp) + { + if (strcmp (pst_temp, "INF") == 0) + { + log_level = NSLOG_INF; + } + else if (strcmp (pst_temp, "DBG") == 0) + { + log_level = NSLOG_DBG; + } + else if (strcmp (pst_temp, "WAR") == 0) + { + log_level = NSLOG_WAR; + } + else if (strcmp (pst_temp, "ERR") == 0) + { + log_level = NSLOG_ERR; + } + else if (strcmp (pst_temp, "EMG") == 0) + { + log_level = NSLOG_EMG; + } + else + { + log_level = NSLOG_ERR; + } + } + else + { + log_level = NSLOG_INF; + } + int i = 0; + for (i = 0; i < MAX_LOG_MODULE; i++) + { + nstack_setlog_level (i, log_level); + } + if (log_level <= NSLOG_WAR) + { + /*MONITR log level must set to larger than warning */ + nstack_setlog_level (MASTER, NSLOG_WAR); + } + + /* monitr and nstack write the same file, it will cause synchronize problem */ + switch (g_my_pro_type) + { + case LOG_PRO_NSTACK: + glogInit ("NSTACK"); + init_nstack_log_para (); + break; + case LOG_PRO_OMC_CTRL: + glogInit ("CTRL"); + init_ctrl_log_para (); + break; + case LOG_PRO_MASTER: + glogInit ("MASTER"); + init_master_log_para (); + break; + default: + return 0; + } + + init_log_ctrl_info(); + + // this is for monitr to check whether log has beed inited + g_nstack_logs[NSOCKET].inited = 1; + NSPOL_LOGERR ("nStackMain_version=%s", NSTACK_VERSION); + write_pre_init_log(); + return 0; +} + +/***************************************************************************** +* Prototype : get_str_value +* Description : get int value +* Input : const char *arg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +get_str_value (const char *arg) +{ + char *parsing_end; + int iValue = 0; + int oldErrno = errno; + if (arg == NULL) + { + return -1; + } + errno = 0; + iValue = (int) strtol (arg, &parsing_end, 0); + if (errno || (!parsing_end) || parsing_end[0] != 0) + { + iValue = -1; + } + errno = oldErrno; + return iValue; +} + + +/***************************************************************************** +* Prototype : setlog_level_value +* Description : proc log level config +* Input : const char *param +* const char *value +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +setlog_level_value (const char *param, const char *value) +{ + int i = 0; + int module = 0; + int logLevel = 0; + module = get_str_value (param); + if ((module < 0) || (MAX_LOG_MODULE <= module)) + { + NSOPR_LOGERR ("input module error]param=%s,module=%d", param, module); + return 1; + } + + if (strcmp (value, LOG_LEVEL_ERR) == 0) + { + logLevel = NSLOG_ERR; + } + else if (strcmp (value, LOG_LEVEL_WAR) == 0) + { + logLevel = NSLOG_WAR; + } + else if (strcmp (value, LOG_LEVEL_DBG) == 0) + { + logLevel = NSLOG_DBG; + } + else if (strcmp (value, LOG_LEVEL_INF) == 0) + { + logLevel = NSLOG_INF; + } + else if (strcmp (value, LOG_LEVEL_EMG) == 0) + { + logLevel = NSLOG_EMG; + } + else + { + NSOPR_LOGERR ("input log level error!"); + return 1; + } + NSOPR_LOGINF ("set module log with level]module=%d,logLevel=0x%x", + module, logLevel); + if (module > 0) + { + nstack_setlog_level (module, logLevel); + return 0; + } + if (0 == module) + { + for ( i = 0; i < MAX_LOG_MODULE ; i++ ) + { + nstack_setlog_level(i,logLevel); + } + } + return 0; +} + + +/***************************************************************************** +* Prototype : check_log_dir_valid +* Description : check the log dir valid or not +* Input : const char *arg +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +check_log_dir_valid (const char *path) +{ + size_t length; + struct stat statbuf; + if (NULL == path) + { + return -1; + } + length = strlen (path) + 1; + if ((length <= 1) || (length > FILE_NAME_LEN)) + { + return -1; + } + + /* only write permission is allowed */ + if ((0 != access (path, W_OK))) + { + /* if path can access, use env path */ + return -1; + } + + if ((0 == lstat (path, &statbuf)) && S_ISDIR (statbuf.st_mode)) + { + return 0; + } + else + { + return -1; + } +} + + +/***************************************************************************** +* Prototype : get_app_env_log_path +* Description : called by environment-specific log init function +* Input : app_file_path, a char pointer to store the log path +* Input : app_file_size, the app_file_path size +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +get_app_env_log_path (char *app_file_path, unsigned int app_file_size) +{ + char *pst_app_log_path_flag = NULL; + char *pst_app_log_path_string = NULL; + int log_to_file = 0; + int ret = -1; + char *app_dir = NULL; + + if ((NULL == app_file_path) || (0 == app_file_size)) + { + return 0; + } + pst_app_log_path_flag = getenv ("NSTACK_LOG_FILE_FLAG"); + if (pst_app_log_path_flag && strcmp (pst_app_log_path_flag, "1") == 0) + { + /* if set enviroment variable to 1,then output to file*/ + log_to_file = 1; + } + else + { + /* if enviroment variable is not equal 1 or + don't set this enviroment variable ,output to STDOUT */ + return 0; + } + + /* add the realpath and dir check */ + /* APP LOG can be set by user */ + pst_app_log_path_string = getenv("NSTACK_APP_LOG_PATH"); + + if ((NULL == pst_app_log_path_string) + ||(strlen (pst_app_log_path_string) > FILE_NAME_LEN - 1)) + { + goto app_default; + } + + app_dir = realpath (pst_app_log_path_string, NULL); + if (check_log_dir_valid (pst_app_log_path_string) < 0) + { + goto app_default; + } + ret = STRCPY_S (app_file_path, app_file_size, app_dir); + if(EOK != ret) + { + log_to_file = 0; + } + + free(app_dir); + return log_to_file; + +app_default: + + if ((0 == access (APP_LOG_PATH, W_OK))) + { + ret = STRCPY_S (app_file_path, app_file_size, APP_LOG_PATH); + if (EOK != ret) + { + log_to_file = 0; + } + } + else + { + log_to_file = 0; + } + + if (NULL != app_dir) + { + free (app_dir); + } + + return log_to_file; + +} + +/***************************************************************************** +* Prototype : nstack_log_init_app +* Description : called by environment-specific log init function +* Input : None +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +void +nstack_log_init_app () +{ + char *pc_temp = NULL; + int log_level = NSLOG_ERR; + int i = 0; + int file_flag = 0; + char app_log_path[FILE_NAME_LEN] = { 0 }; + + /* log alread initialized, just return */ + if (LOG_PRO_INVALID != g_my_pro_type) + { + return; + } + /* Add app log hook module init */ + nstack_log_hook_init (); + + if (0 != g_nstack_logs[NSOCKET].inited) + { + return; + } + glogInit ("APP"); + + pc_temp = getenv ("NSTACK_LOG_ON"); + if (pc_temp) + { + if (strcmp (pc_temp, "INF") == 0) + { + log_level = NSLOG_INF; + } + else if (strcmp (pc_temp, "DBG") == 0) + { + log_level = NSLOG_DBG; + } + else if (strcmp (pc_temp, "WAR") == 0) + { + log_level = NSLOG_WAR; + } + else if (strcmp (pc_temp, "ERR") == 0) + { + log_level = NSLOG_ERR; + } + else if (strcmp (pc_temp, "EMG") == 0) + { + log_level = NSLOG_EMG; + } + else + { + log_level = NSLOG_ERR; + } + + } + else + { + log_level = NSLOG_ERR; + } + + /* socket interface APP called include both stack-x and nstack module! */ + nstack_setlog_level (STACKX, log_level); + nstack_setlog_level (NSOCKET, log_level); + nstack_setlog_level (LOGRTE, log_level); + nstack_setlog_level (LOGDFX, log_level); + nstack_setlog_level (LOGFW, log_level); + nstack_setlog_level (LOGHAL, log_level); + nstack_setlog_level (LOGSBR, log_level); + + /* package the app env handle function, Begin */ + file_flag = get_app_env_log_path (app_log_path, FILE_NAME_LEN); + if ((1 == file_flag) && (strlen (app_log_path) > 0)) + { + glogDir (app_log_path); + glogBufLevelSet (GLOG_LEVEL_WARNING); + (void) glogLevelSet (GLOG_LEVEL_DEBUG); + for (i = 0; i < GLOG_LEVEL_BUTT; i++) + glogSetLogSymlink (i, ""); + nstack_log_count_set (APP_LOG_COUNT); + glogMaxLogSizeSet (APP_LOG_SIZE); + glogSetLogFilenameExtension (APP_LOG_NAME); + glogFlushLogSecsSet (FLUSH_TIME); + } + else + { + glogToStderrSet (1); + } + + for (i = 0; i < MAX_LOG_MODULE; i++) + { + g_nstack_logs[i].file_type = LOG_TYPE_APP; + } + init_log_ctrl_info (); + g_my_pro_type = LOG_PRO_APP; +#ifdef FOR_NSTACK_UT + +#else + SetGlogCtrlOpt (TRUE); +#endif + NSPOL_LOGERR ("app_nStack_version=%s", NSTACK_VERSION); + return; +} + +void +nstack_segment_error (int s) +{ + +#define BACKTRACE_SIZ 20 + void *array[BACKTRACE_SIZ]; + int size; + int i; + char **strings = NULL; + + /*if set, flush the log immediately */ + glogFlushLogFiles (GLOG_LEVEL_DEBUG); + + size = backtrace (array, BACKTRACE_SIZ); + NSPOL_LOGEMG + ("------------------DUMP_BACKTRACE[%d]--------------------------------\n", + size); + + /* easy to view signal in separate log file */ + NSPOL_LOGEMG ("Received signal s=%d", s); + + for (i = 0; i < size; i++) + { + NSPOL_LOGEMG ("[%d]:%p\n", i, array[i]); + } + strings = backtrace_symbols (array, size); + if (NULL == strings) + { + return; + } + for (i = 0; i < size; i++) + { + NSPOL_LOGEMG ("[%d]:%s\n", i, strings[i]); + } + NSPOL_LOGEMG + ("-------------------------------------------------------------------\n"); + free (strings); +} + +void +set_log_init_para (struct log_init_para *para) +{ + if (NULL == para) + + { + return; + } + if (EOK != + MEMCPY_S (&g_log_init_para, sizeof (struct log_init_para), para, + sizeof (struct log_init_para))) + + { + return; + } +} + +/* control log printed counts */ +static inline void +update_log_prt_time (struct timespec *cur_time, struct timespec *log_prt_time) +{ + log_prt_time->tv_sec = cur_time->tv_sec; + log_prt_time->tv_nsec = cur_time->tv_nsec; +} + +int +check_log_prt_time (int id) +{ + struct timespec cur_time; + struct timespec *log_prt_time = NULL; + if (id >= LOG_CTRL_ID_MAX || id < 0) + + { + return 0; + } + (void) clock_gettime (CLOCK_MONOTONIC, &cur_time); + log_prt_time = &g_log_ctrl_info[id].last_log_time; + if (cur_time.tv_sec - log_prt_time->tv_sec >= + g_log_ctrl_info[id].expire_time) + { + /* first log need print */ + set_log_ctrl_time (id, DEFAULT_LOG_CTR_TIME); + update_log_prt_time (&cur_time, log_prt_time); + return 1; + } + g_log_ctrl_info[id].unprint_count++; + return 0; +} + +int +get_unprt_log_count (int id) +{ + return g_log_ctrl_info[id].unprint_count; +} + +void +clr_unprt_log_count (int id) +{ + g_log_ctrl_info[id].unprint_count = 0; +} + +void +set_log_ctrl_time (int id, int ctrl_time) +{ + if (id >= LOG_CTRL_ID_MAX || id < 0) + { + return; + } + + if (ctrl_time <= 0) + { + return; + } + + g_log_ctrl_info[id].expire_time = ctrl_time; +} + +void +init_log_ctrl_info () +{ + int i = 0; + for (; i < LOG_CTRL_ID_MAX; i++) + { + /* first log need print */ + g_log_ctrl_info[i].expire_time = 0; + g_log_ctrl_info[i].unprint_count = 0; + g_log_ctrl_info[i].last_log_time.tv_sec = 0; + g_log_ctrl_info[i].last_log_time.tv_nsec = 0; + } + + // for every socket api, need different log id + + // for nstack inner +} + +void +set_log_proc_type (int log_proc_type) +{ + g_my_pro_type = log_proc_type; +} diff --git a/src/framework/snapshot/fw_snapshot.c b/src/framework/snapshot/fw_snapshot.c new file mode 100644 index 0000000..790ecbf --- /dev/null +++ b/src/framework/snapshot/fw_snapshot.c @@ -0,0 +1,483 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nstack_securec.h" +#include "nsfw_snapshot.h" +#include "nstack_log.h" +#include "fw_ss_tlv.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +/* *INDENT-OFF* */ +nsfw_ss_objDescManager_t g_nsfw_ss_objDescManager = +{ +.g_nsfw_ss_objDesNum = 0}; + +/* *INDENT-ON* */ + +void +nsfw_ss_register_ObjDesc (nsfw_ss_objDesc_t * objDesc) +{ + if (objDesc == NULL) + return; + nsfw_ss_objDescManager_t *manager = nsfw_ss_getObjDescManagerInst (); + if (manager->g_nsfw_ss_objDesNum >= NSFW_SS_MAX_OBJDESC_NUM) + return; + manager->g_nsfw_ss_objDescs[manager->g_nsfw_ss_objDesNum++] = objDesc; +} + +static nsfw_ss_objDesc_t * +nsfw_ss_getObjDescFromType (u16 objType) +{ + nsfw_ss_objDescManager_t *manager = nsfw_ss_getObjDescManagerInst (); + int i; + for (i = 0; i < manager->g_nsfw_ss_objDesNum && i < NSFW_SS_MAX_OBJDESC_NUM; + i++) + { + if (manager->g_nsfw_ss_objDescs[i]->objType == objType) + return manager->g_nsfw_ss_objDescs[i]; + } + return NULL; +} + +static nsfw_ss_objMemDesc_t * +nsfw_ss_getMemDescFromType (u16 objType, nsfw_ss_objDesc_t * objDesc) +{ + int i; + for (i = 0; i < objDesc->memNum; i++) + { + if (objDesc->memDesc[i].type == objType) + { + return &objDesc->memDesc[i]; + } + } + return NULL; +} + +/** + * @Function nsfw_ss_store + * @Description store object to memory + * @param (in) objType - type of object with member description + * @param (in) obj - adderss of object memory + * @param (in) storeMem - address of memory to store object data + * @param (in) storeMemLen - maximal length of storage memory + * @return positive integer means length of memory cost on success. return -1 if error + */ +int +nsfw_ss_storeObjMem (u16 objMemType, void *obj, void *storeMem, + u32 storeMemLen) +{ + if (NULL == obj || NULL == storeMem) + return -1; + + // example of object + /* struct A{ */ + /* int a1; */ + /* struct A2 a2; --> struct A2 {int a2} */ + /* struct A3 a3[2]; --> struct A3 [{int a3}, {int a3}] */ + /* } */ + + /* -------------------------------------------- */ + /* | type(object) | length | */ + /* | -------------------------------------- | */// -- + /* | | type(item) | length | | */// member a1 + /* | | item value (object->member) | | */// -- + /* | -------------------------------------- | */// object a2 + /* | | type(object) | length | | */// -- + /* | | ------------------------------- | | */// member a2 + /* | | | type(item) | length | | | */// -- + /* | | | item value (object->member) | | | */// -- + /* | | ------------------------------- | | */// + /* | -------------------------------------- | */// + /* | | type(object array) | length | | */// array member a3 + /* | | ------------------------------- | | */// -- + /* | | | type(object) | length | | | */// object a3_1 + /* | | | ----------------------------| | | */// -- + /* | | | type(item) | length | | | */// member a3_1_1 + /* | | | item value (object->member) | | | */ + /* | | | ----------------------------| | | */ + /* | | ------------------------------- | | */ + /* | | | type(object) | length | | | */ + /* | | | ----------------------------| | | */ + /* | | | type(item) | length | | | */ + /* | | | item value (object->member) | | | */ + /* | | | ----------------------------| | | */ + /* | | ------------------------------- | | */ + /* | |------------------------------------| | */ + /* -------------------------------------------- */ + nsfw_ss_objDesc_t *objDesc = + nsfw_ss_getObjDescFromType (NSFW_SS_TYPE_GETOBJ (objMemType)); + if (NULL == objDesc) + return -1; + + /* Get object header tlv */ + if (storeMemLen < tlv_header_length ()) + return -1; + nsfw_ss_tlv_t *tlv = (nsfw_ss_tlv_t *) storeMem; + tlv->type = objMemType; + tlv->length = 0; + tlv_header (storeMem); + storeMemLen -= tlv_header_length (); + + /* Search every object member */ + + /* For base item(including array of base item), it should start with a tlv header */ + /* For object array, it should start with one tlv header including array information */ + /* For object, it should call nsfw_ss_store recursively */ + int i; + for (i = 0; i < objDesc->memNum; i++) + { + nsfw_ss_objMemDesc_t *memDesc = &objDesc->memDesc[i]; + if (NSFW_SS_TYPE_IS_MEMBER_OBJ (memDesc->type)) + { + + if (NSFW_SS_TYPE_IS_MEMBER_ARRAY (memDesc->type)) + { + /* array object should includes one array tlv header, shows the array informations */ + if (storeMemLen < tlv_header_length ()) + return -1; + nsfw_ss_tlv_t *arrayTlv = (nsfw_ss_tlv_t *) storeMem; + arrayTlv->type = memDesc->type; + arrayTlv->length = 0; + tlv_header (storeMem); + storeMemLen -= tlv_header_length (); + nsfw_ss_objDesc_t *memObjDesc = + nsfw_ss_getObjDescFromType (NSFW_SS_TYPE_GETOBJ + (memDesc->type)); + if (NULL == memObjDesc) + return -1; + u32 arraySize = memDesc->length / memObjDesc->objSize; + u32 j; + for (j = 0; j < arraySize; j++) + { + int ret = + nsfw_ss_storeObjMem (NSFW_SS_TYPE_SET_MEMBER_OBJ + (NSFW_SS_TYPE_GETOBJ (memDesc->type), + 0), + (char *) obj + + (u64) (memDesc->offset) + + (u64) j * memObjDesc->objSize, + storeMem, storeMemLen); + if ((-1 == ret) || (storeMemLen < (u32) ret)) + return -1; + tlv_mem_forward (storeMem, ret); + storeMemLen -= (u32) ret; + arrayTlv->length += (u32) ret; + } + tlv->length += (arrayTlv->length + (u32) tlv_header_length ()); + } + else + { + int ret = nsfw_ss_storeObjMem (memDesc->type, + ((char *) obj + memDesc->offset), + storeMem, storeMemLen); + if (ret < 0 || (storeMemLen < (u32) ret)) + return -1; + storeMemLen -= (u32) ret; + tlv_mem_forward (storeMem, ret); + tlv->length += (u32) ret; + } + } + else + { + // Base Item + if (storeMemLen < tlv_header_length ()) + { + return -1; + } + nsfw_ss_tlv_t *curtlv = (nsfw_ss_tlv_t *) storeMem; // curTlv means next tlv elem + curtlv->type = memDesc->type; + curtlv->length = memDesc->length; + tlv_header (storeMem); + storeMemLen -= tlv_header_length (); + if (storeMemLen < curtlv->length) + return -1; + if (EOK != + MEMCPY_S (storeMem, (size_t) storeMemLen, + ((char *) obj + memDesc->offset), + (size_t) memDesc->length)) + { + return -1; + } + tlv_mem_forward (storeMem, memDesc->length); + storeMemLen -= memDesc->length; + tlv->length += (curtlv->length + (u32) tlv_header_length ()); + } + } + return (int) (tlv->length + tlv_header_length ()); +} + +/** + * @Function nsfw_ss_store + * @Description store object to memory + * @param (in) objType - type of object + * @param (in) obj - adderss of object memory + * @param (in) storeMem - address of memory to store object data + * @param (in) storeMemLen - maximal length of storage memory + * @return positive integer means length of memory cost on success. return -1 if error + */ +int +nsfw_ss_store (u16 objType, void *obj, void *storeMem, u32 storeMemLen) +{ + return nsfw_ss_storeObjMem (NSFW_SS_TYPE_SET_MEMBER_OBJ (objType, 0), + obj, storeMem, storeMemLen); +} + +/** + * @Function nsfw_ss_restoreObjArray + * @Description restore array of objects + * @param (in) objType - type of object + * @param (in) objMem - object memory to restore + * @param (in) mem - memory of storage + * @param (in) storeMemLength - maximal length of storage memroy + * @return 0 on succss , -1 on error + */ +NSTACK_STATIC int +nsfw_ss_restoreObjArray (int objType, void *objMem, void *mem, + u32 storeMemLength) +{ + if (storeMemLength < tlv_header_length ()) + return -1; + nsfw_ss_tlv_t *arrayTlv = (nsfw_ss_tlv_t *) mem; + storeMemLength -= tlv_header_length (); + tlv_header (mem); + if (0 == arrayTlv->length || storeMemLength < arrayTlv->length) + return -1; + storeMemLength = arrayTlv->length; // Only cares tlv->value + nsfw_ss_objDesc_t *objDesc = nsfw_ss_getObjDescFromType ((u16) objType); + if (NULL == objDesc) + return -1; + + /* Now we are going to iterate every object */ + u32 objCnt = 0; + while (storeMemLength) + { + if (storeMemLength < tlv_header_length ()) + return -1; // Format error + nsfw_ss_tlv_t *objTlv = (nsfw_ss_tlv_t *) mem; + if ((int) NSFW_SS_TYPE_GETOBJ (objTlv->type) != objType) + { + return -1; + } + int ret = + nsfw_ss_restore ((char *) objMem + (u64) objDesc->objSize * objCnt, + mem, storeMemLength); + if (-1 == ret) + return -1; + objCnt++; + tlv_mem_forward (mem, (objTlv->length + tlv_header_length ())); + storeMemLength -= (objTlv->length + tlv_header_length ()); + } + return 0; +} + +/** + * @Function nsfw_ss_restore + * @Description restore object from memory + * @param (in) objMem - memory of object + * @param (in) mem - memory of storage + * @param (in) storeMemLen - maximal length of storage memory + * @return positive integer stands on object type, -1 on error + */ +int +nsfw_ss_restore (void *objMem, void *mem, u32 storeMemLen) +{ + if (NULL == objMem || NULL == mem || 0 == storeMemLen) + return -1; + + // example of object + /* struct A{ */ + /* int a1; */ + /* struct A2 a2; --> struct A2 {int a2} */ + /* struct A3 a3[2]; --> struct A3 [{int a3}, {int a3}] */ + /* } */ + + /* -------------------------------------------- */// -- + /* | type(object) | length | */// type length + /* | -------------------------------------- | */// -- + /* | | type(item) | length | | */// member a1 + /* | | item value (object->member) | | */// -- + /* | -------------------------------------- | */// object a2 + /* | | type(object) | length | | */// -- + /* | | ------------------------------- | | */// member a2 + /* | | | type(item) | length | | | */// -- + /* | | | item value (object->member) | | | */// -- + /* | | ------------------------------- | | */// + /* | -------------------------------------- | */// + /* | | type(object array) | length | | */// array member a3 + /* | | ------------------------------- | | */// -- + /* | | | type(object) | length | | | */// object a3_1 + /* | | | ----------------------------| | | */// -- + /* | | | type(item) | length | | | */// member a3_1_1 + /* | | | item value (object->member) | | | */ + /* | | | ----------------------------| | | */ + /* | | ------------------------------- | | */ + /* | | | type(object) | length | | | */ + /* | | | ----------------------------| | | */ + /* | | | type(item) | length | | | */ + /* | | | item value (object->member) | | | */ + /* | | | ----------------------------| | | */ + /* | | ------------------------------- | | */ + /* | |------------------------------------| | */ + /* -------------------------------------------- */ + if (storeMemLen < tlv_header_length ()) + return -1; + nsfw_ss_tlv_t *tlv = (nsfw_ss_tlv_t *) mem; + storeMemLen -= tlv_header_length (); + tlv_header (mem); + nsfw_ss_objDesc_t *objDesc = + nsfw_ss_getObjDescFromType (NSFW_SS_TYPE_GETOBJ (tlv->type)); + if (NULL == objDesc) + { + return -1; + } + if (!NSFW_SS_TYPE_IS_MEMBER_OBJ (tlv->type)) + return -1; + if (0 == tlv->length || storeMemLen < tlv->length) + return -1; + + /* Now we go to inner of object */ + storeMemLen = tlv->length; /* Only care about tlv values */ + while (storeMemLen) + { + if (storeMemLen < tlv_header_length ()) + return -1; // Format error + nsfw_ss_tlv_t *curtlv = (nsfw_ss_tlv_t *) mem; + nsfw_ss_objMemDesc_t *memDesc = + nsfw_ss_getMemDescFromType (curtlv->type, objDesc); + if (NULL == memDesc) + { // This type not support + storeMemLen -= tlv_header_length (); + tlv_header (mem); + if (storeMemLen < curtlv->length) + return -1; + tlv_mem_forward (mem, curtlv->length); + storeMemLen -= curtlv->length; + continue; + } + if (NSFW_SS_TYPE_IS_MEMBER_OBJ (curtlv->type)) + { + if (NSFW_SS_TYPE_IS_MEMBER_ARRAY (curtlv->type)) + { + int ret = + nsfw_ss_restoreObjArray ((int) + NSFW_SS_TYPE_GETOBJ (curtlv->type), + (void *) ((char *) objMem + + memDesc->offset), mem, + storeMemLen); + if (-1 == ret) + return -1; + } + else + { + int ret = + nsfw_ss_restore ((void *) ((char *) objMem + + memDesc->offset), mem, + storeMemLen); + if (-1 == ret) + return -1; + } + tlv_mem_forward (mem, (curtlv->length + tlv_header_length ())); + storeMemLen -= (curtlv->length + tlv_header_length ()); + } + else + { + tlv_header (mem); + storeMemLen -= tlv_header_length (); + NSFW_LOGDBG + ("curtlv->type(%u), curtlv->length(%u), memDesc->offset(%u), memDesc->length(%u), mem(%u)", + curtlv->type, curtlv->length, memDesc->offset, memDesc->length, + *(u32 *) mem); + if (storeMemLen < curtlv->length) + return -1; + if (EOK != + MEMCPY_S ((void *) ((char *) objMem + memDesc->offset), + (size_t) memDesc->length, mem, + (size_t) curtlv->length)) + { + return -1; + } + tlv_mem_forward (mem, curtlv->length); + storeMemLen -= curtlv->length; + } + } + return (int) tlv->type; +} + +/** + * @Function nsfw_ss_getObjStoreMemLen + * @Description Get the maximal memory it needs + * @param (in) objType - type of object + * @return length of memory needs, -1 if error + */ +int +nsfw_ss_getObjStoreMemLen (int objType) +{ + u32 maxlength = tlv_header_length (); + u32 i; + nsfw_ss_objDesc_t *objDesc = nsfw_ss_getObjDescFromType ((u16) objType); + if (!objDesc) + return -1; + for (i = 0; i < objDesc->memNum; i++) + { + nsfw_ss_objMemDesc_t *memDesc = &objDesc->memDesc[i]; + int temp_len; + if (NSFW_SS_TYPE_IS_MEMBER_OBJ (memDesc->type)) + { + nsfw_ss_objDesc_t *curObjDesc = + nsfw_ss_getObjDescFromType (NSFW_SS_TYPE_GETOBJ (memDesc->type)); + if (NULL == curObjDesc) + return -1; + if (NSFW_SS_TYPE_IS_MEMBER_ARRAY (memDesc->type)) + { + maxlength += tlv_header_length (); // array length + u32 arrSize = memDesc->length / curObjDesc->objSize; + u32 j; + for (j = 0; j < arrSize; j++) + { + temp_len = + nsfw_ss_getObjStoreMemLen ((int) curObjDesc->objType); + if (temp_len < 0) + return -1; + maxlength += (u32) temp_len; + } + } + else + { + temp_len = + nsfw_ss_getObjStoreMemLen ((int) curObjDesc->objType); + if (temp_len < 0) + return -1; + maxlength += (u32) temp_len; + } + } + else + { + maxlength += ((u32) tlv_header_length () + memDesc->length); + } + } + return (int) maxlength; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/src/framework/snapshot/fw_ss_tlv.h b/src/framework/snapshot/fw_ss_tlv.h new file mode 100644 index 0000000..0bfbd91 --- /dev/null +++ b/src/framework/snapshot/fw_ss_tlv.h @@ -0,0 +1,47 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _FW_SS_TLV_H +#define _FW_SS_TLV_H + +#include <stdlib.h> +#include "types.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +typedef struct _nsfw_ss_tlv +{ + u16 type; + u32 length; + void *value; +} nsfw_ss_tlv_t; + +#define tlv_header_length() ((size_t)(&((nsfw_ss_tlv_t*)0)->value)) + +#define tlv_mem_forward(mem, step) ((mem) = (void*) ((char*)(mem) + (step))) +#define tlv_header(mem) tlv_mem_forward((mem), tlv_header_length()) // move header + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#endif /* _FW_SS_TLV_H */ diff --git a/src/framework/tracing/nstack_trace.c b/src/framework/tracing/nstack_trace.c new file mode 100644 index 0000000..88c8ffb --- /dev/null +++ b/src/framework/tracing/nstack_trace.c @@ -0,0 +1,52 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/*==============================================* + * include header files * + *----------------------------------------------*/ +#include "nstack_trace.h" +#include "nstack_securec.h" +#include <stdarg.h> +#include <dlfcn.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif + +/*==============================================* + * constants or macros define * + *----------------------------------------------*/ +#define EVENT_MAX 5 +#define NSTACK_TRACE_SWICH "NSTACK_TRACE_ON" +/*==============================================* + * project-wide global variables * + *----------------------------------------------*/ +trace_fun_t nstack_trace_fun; +__thread trace_hread_t strace_header = { + .thread_id = -1, + .trace_id = TRACE_NULL, +}; + +int tracing_inited = 0; +__thread char *cad_traceID_string = NULL; + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif |