summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/src
diff options
context:
space:
mode:
authorsatish.karunanithi <satish.fdio@gmail.com>2018-08-13 19:39:55 +0530
committersatish.karunanithi <satish.fdio@gmail.com>2018-08-14 10:22:59 +0530
commit54f5a270c74c405d3bb0e15d5b69d6d0e1e96c49 (patch)
treea855ebf120dd46c50784c30a53a1bdf9aedea632 /stacks/lwip_stack/src
parentbd6e75c243db1b384ba0882ecaf9063ec4cd70bd (diff)
Feat : LWIP integration part3
Change-Id: I62998963da110827a410287eed90a22da7ae4222 Signed-off-by: satish.karunanithi <satish.fdio@gmail.com>
Diffstat (limited to 'stacks/lwip_stack/src')
-rw-r--r--stacks/lwip_stack/src/CMakeLists.txt62
-rw-r--r--stacks/lwip_stack/src/alarm/CMakeLists.txt34
-rw-r--r--stacks/lwip_stack/src/alarm/alarm.c863
-rw-r--r--stacks/lwip_stack/src/alarm/alarm.h80
-rw-r--r--stacks/lwip_stack/src/alarm/alarm_api.h107
-rw-r--r--stacks/lwip_stack/src/include/nsfw_msg.h203
-rw-r--r--stacks/lwip_stack/src/include/nsfw_msg_api.h309
-rw-r--r--stacks/lwip_stack/src/include/nsfw_mt_config.h292
-rw-r--r--stacks/lwip_stack/src/include/nsfw_rti.h66
-rw-r--r--stacks/lwip_stack/src/io_adpt/CMakeLists.txt31
-rw-r--r--stacks/lwip_stack/src/io_adpt/dpdk.c2315
-rw-r--r--stacks/lwip_stack/src/maintain/CMakeLists.txt44
-rw-r--r--stacks/lwip_stack/src/maintain/fw_mt_config.c843
-rw-r--r--stacks/lwip_stack/src/maintain/nsfw_msg.c23
-rw-r--r--stacks/lwip_stack/src/maintain/nsfw_rti.c92
-rw-r--r--stacks/lwip_stack/src/nStackMain/CMakeLists.txt60
-rw-r--r--stacks/lwip_stack/src/nStackMain/main.c427
-rw-r--r--stacks/lwip_stack/src/sbr/CMakeLists.txt30
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_err.h191
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_index_ring.c212
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_index_ring.h61
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_protocol_api.h99
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_res_mgr.c88
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_res_mgr.h128
-rw-r--r--stacks/lwip_stack/src/sbr/sbr_socket.c1231
-rw-r--r--stacks/lwip_stack/src/tools/CMakeLists.txt22
-rw-r--r--stacks/lwip_stack/src/tools/dump_tool.c622
-rw-r--r--stacks/lwip_stack/src/tools/dump_tool.h81
28 files changed, 8616 insertions, 0 deletions
diff --git a/stacks/lwip_stack/src/CMakeLists.txt b/stacks/lwip_stack/src/CMakeLists.txt
new file mode 100644
index 0000000..6aacf07
--- /dev/null
+++ b/stacks/lwip_stack/src/CMakeLists.txt
@@ -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.
+#########################################################################
+
+SET(RTP_DIRECTORIES "${PROJECT_SOURCE_DIR}/src/include/")
+
+INCLUDE_DIRECTORIES(
+ framework/log/
+ framework/include/
+ framework/common/include/
+ framework/common/base/include/
+ ${RTP_DIRECTORIES}
+ ${RTP_DIRECTORIES}/generic
+ ../../SecureC/include/
+ ../../../thirdparty/glog/glog-0.3.4/src/
+)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fPIC -m64 -mssse3 -std=gnu89")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wshadow -Wfloat-equal -Wformat=2")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector -fstack-protector-all")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,relro,-z,now -Wl,--disable-new-dtags,--rpath,../lib64")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium")
+
+if(WITH_HAL_LIB)
+SET(RTP_CONFIG ${PROJECT_SOURCE_DIR}/src/include/rtp_config.h)
+else()
+ SET(RTP_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/common/base/include/common/common_sys_config.h)
+endif()
+SET(COMPLE_CONFIG ${PROJECT_SOURCE_DIR}/src/include/compile_config.h)
+ADD_DEFINITIONS(-include ${RTP_CONFIG})
+ADD_DEFINITIONS(-include ${COMPLE_CONFIG})
+ADD_DEFINITIONS(-D_GNU_SOURCE)
+ADD_DEFINITIONS(-DDPDK_MODULE=0)
+#ADD_DEFINITIONS(-DNSTACK_RSRDMA)
+LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC})
+
+if(WITH_SECUREC_LIB)
+LINK_LIBRARIES(pthread dl securec)
+else()
+LINK_LIBRARIES(pthread dl)
+endif()
+
+ADD_SUBDIRECTORY(maintain)
+ADD_SUBDIRECTORY(io_adpt)
+ADD_SUBDIRECTORY(sbr)
+#ADD_SUBDIRECTORY(nStackCtrl)
+ADD_SUBDIRECTORY(nStackMain)
+ADD_SUBDIRECTORY(tools)
+ADD_SUBDIRECTORY(alarm)
+#ADD_SUBDIRECTORY(nstackcmd)
diff --git a/stacks/lwip_stack/src/alarm/CMakeLists.txt b/stacks/lwip_stack/src/alarm/CMakeLists.txt
new file mode 100644
index 0000000..3de07b0
--- /dev/null
+++ b/stacks/lwip_stack/src/alarm/CMakeLists.txt
@@ -0,0 +1,34 @@
+#########################################################################
+#
+# 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.
+#########################################################################
+
+FILE(GLOB_RECURSE ALARM *.c)
+
+LINK_LIBRARIES(m dl rt dmm_api)
+if(WITH_SECUREC_LIB)
+INCLUDE_DIRECTORIES(
+ ./
+ ${JSON_C_SRC}
+ ${SECUREC_SRC}
+ ${CMAKE_CURRENT_LIST_DIR}/../include/
+)
+else()
+INCLUDE_DIRECTORIES(
+ ./
+ ${JSON_C_SRC}
+ ${CMAKE_CURRENT_LIST_DIR}/../include/
+)
+endif()
+ADD_LIBRARY(nStackAlarm STATIC ${ALARM})
diff --git a/stacks/lwip_stack/src/alarm/alarm.c b/stacks/lwip_stack/src/alarm/alarm.c
new file mode 100644
index 0000000..5f89cdd
--- /dev/null
+++ b/stacks/lwip_stack/src/alarm/alarm.c
@@ -0,0 +1,863 @@
+/*
+*
+* 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 "types.h"
+#include "nsfw_mgr_com_api.h"
+#include "nsfw_fd_timer_api.h"
+#include "alarm.h"
+#include "alarm_api.h"
+#include<time.h>
+#include<sys/time.h>
+#include "nsfw_init.h"
+#include "nstack_log.h"
+#include "json.h"
+#include "nstack_securec.h"
+#include <stdlib.h>
+#include "nstack_dmm_adpt.h"
+
+char g_vmid[MAX_VMID_LEN + 1] = "agent-node-x";
+
+extern nsfw_timer_info *nsfw_timer_reg_timer (u32 timer_type, void *data,
+ nsfw_timer_proc_fun fun,
+ struct timespec time_left);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif /* __cplusplus */
+
+// note:the first element is reserved
+alarm_data g_alarm_data[ALARM_EVENT_MAX] = { };
+
+alarm_result
+ms_alarm_check_func (void *para)
+{
+ alarm_result ret_alarm;
+ int para_value = (long) para;
+
+ ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_MAIN_ABNORMAL;
+
+ if (para_value == ALARM_PRODUCT)
+ {
+ ret_alarm.alarm_flag_get = ALARM_PRODUCT;
+ }
+ else if (para_value == ALARM_CLEAN)
+ {
+ ret_alarm.alarm_flag_get = ALARM_CLEAN;
+ }
+ else
+ {
+ ret_alarm.alarm_id_get = ALARM_EVENT_MAX;
+ }
+
+ ret_alarm.alarm_reason_get = ALARM_REASON_NSMAIN;
+
+ return ret_alarm;
+
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : period check alarm expire handle function
+********************************************************************/
+
+int
+ns_alarm_timer_resend_fun (u32 timer_type, void *argv)
+{
+ int i;
+ struct timespec time_left;
+ alarm_data *alarm_value;
+
+ for (i = ALARM_EVENT_BASE; i < ALARM_EVENT_MAX; i++)
+ {
+ alarm_value = &g_alarm_data[i];
+
+ if ((alarm_value->valid_flag == 1)
+ && (alarm_value->send_succ_flag == ALARM_SEND_FAIL))
+ {
+ /* nStack only send nsMain normal alarm */
+ ns_send_alarm_inner (alarm_value->_alarm_id,
+ (void *) (alarm_value->_alarm_flag), 1, 0);
+ }
+ }
+
+ time_left.tv_sec = ALARM_RESEND_TIMER_LENGTH;
+ time_left.tv_nsec = 0;
+ nsfw_timer_info *timer_info =
+ nsfw_timer_reg_timer (0, NULL, ns_alarm_timer_resend_fun, time_left);
+ if (NULL == timer_info)
+ {
+ NSAM_LOGERR ("nsfw_timer_reg_timer fail");
+ }
+
+ return 0;
+}
+
+void
+ns_alarm_set_sendFlag (enum_alarm_id alarmId, int flag)
+{
+ if ((alarmId <= 0) || (alarmId >= ALARM_EVENT_MAX)
+ || (0 == g_alarm_data[alarmId].valid_flag) || ((flag != ALARM_SEND_FAIL)
+ && (flag !=
+ ALARM_SEND_SUCC)))
+ {
+ NSAM_LOGERR ("alarm_id is invalid or not reg or flag invalid");
+ return;
+ }
+ g_alarm_data[alarmId].send_succ_flag = flag;
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : alarm module init
+********************************************************************/
+int
+ns_alarm_module_init (void *param)
+{
+ u32 proc_type = (u32) ((long long) param);
+ enum_alarm_id i = ALARM_EVENT_BASE;
+ alarm_reason j = ALARM_REASON_BEGIN;
+ const char *pst_vm_id = NULL;
+ alarm_para tcp_alarm_para;
+ struct timespec time_left;
+
+ for (i = ALARM_EVENT_BASE; i < ALARM_EVENT_MAX; i++)
+ {
+ g_alarm_data[i]._alarm_type = ALARM_SEND_ONCE;
+
+ for (j = ALARM_REASON_BEGIN; j < ALARM_REASON_MAX; j++)
+ {
+ g_alarm_data[i]._alarm_para.func_alarm_check[j] = NULL;
+ g_alarm_data[i]._alarm_para.alarm_reason_set[j] = ALARM_REASON_MAX;
+ g_alarm_data[i].alarm_time_laps[j] = 0;
+ }
+ g_alarm_data[i]._alarm_para.period_alarm.time_length = 0;
+ g_alarm_data[i]._alarm_id = i;
+ g_alarm_data[i].valid_flag = 0;
+ g_alarm_data[i]._alarm_flag = ALARM_CLEAN;
+ g_alarm_data[i].alarm_reason_cnt = 0;
+ g_alarm_data[i].send_succ_flag = ALARM_SEND_SUCC;
+ }
+
+ switch (proc_type)
+ {
+ case NSFW_PROC_MAIN:
+
+ case NSFW_PROC_MASTER:
+ case NSFW_PROC_CTRL:
+
+ /* [S138713][p00329905][20171219]modify ip address to vm id */
+ pst_vm_id = getenv ("VM_ID");
+
+ if (INVALID_STR_LEN (pst_vm_id, MIN_VM_ID_LEN, MAX_VM_ID_LEN))
+ {
+ NSAM_LOGWAR
+ ("invalid VM_ID,please check env VM_ID]vm_id=%s, proc_type=%u",
+ pst_vm_id, proc_type);
+ }
+ else
+ {
+ int retVal = STRNCPY_S (g_vmid, MAX_VMID_LEN + 1, pst_vm_id,
+ strlen (pst_vm_id));
+
+ if (EOK != retVal)
+ {
+ NSAM_LOGERR ("STRNCPY_S failed]ret=%d", retVal);
+ }
+ }
+
+ tcp_alarm_para.period_alarm.time_length = 0; /* 5 second period */
+ tcp_alarm_para.alarm_reason_count = 1; /*both resource */
+
+ tcp_alarm_para.func_alarm_check[0] = ms_alarm_check_func;
+ tcp_alarm_para.alarm_reason_set[0] = ALARM_REASON_NSMAIN;
+ (void) ns_reg_alarm (ALARM_EVENT_NSTACK_MAIN_ABNORMAL, ALARM_SEND_ONCE,
+ &tcp_alarm_para);
+
+ time_left.tv_sec = ALARM_INIT_RESEND_TIMER_LENGTH;
+ time_left.tv_nsec = 0;
+ nsfw_timer_info *timer_info =
+ nsfw_timer_reg_timer (0, NULL, ns_alarm_timer_resend_fun, time_left);
+ if (NULL == timer_info)
+ {
+ NSAM_LOGERR ("nsfw_timer_reg_timer fail");
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+#define JSON_NEW_OBJ(obj, cb, para1, para2)\
+ {\
+ obj = json_object_new_object();\
+ if (obj == NULL)\
+ {\
+ (void)cb(para1);\
+ (void)cb(para2);\
+ return -1;\
+ }\
+ }
+
+#define JSON_NEW_STRING_OBJ(str, obj, cb, para1, para2)\
+ {\
+ obj = json_object_new_string((str));\
+ if (obj == NULL)\
+ {\
+ (void)cb(para1);\
+ (void)cb(para2);\
+ return -1;\
+ }\
+ }
+
+#define JSON_NEW_STRING_OBJ_1(val, obj, cb, para1, para2,para3)\
+ {\
+ obj = json_object_new_string((val));\
+ if (obj == NULL)\
+ {\
+ (void)cb(para1);\
+ (void)cb(para2);\
+ (void)cb(para3);\
+ return -1;\
+ }\
+ }
+
+#define JSON_NEW_INT_OBJ(val, obj, cb, para1, para2)\
+ {\
+ obj = json_object_new_int((val));\
+ if (obj == NULL)\
+ {\
+ (void)cb(para1);\
+ (void)cb(para2);\
+ return -1;\
+ }\
+ }
+
+/*****************************************************************************
+* Prototype : ns_get_alarm_body
+* Description : get body by alarm parameter
+* Input : char *buf
+* int buf_len
+* alarm_result alarm_res
+* Output : None
+* Return Value : int
+*****************************************************************************/
+int
+ns_get_alarm_body (char *buf, int buf_len, alarm_result alarm_res)
+{
+#define ALARM_NAME_LENGTH 100
+#define COMPONENT_NAME "nStack"
+ int retVal;
+ size_t str_len;
+ int alarm_id = alarm_res.alarm_id_get + 27000;
+ struct timeval t_val;
+ struct tm now_time;
+ char *alarm_string = NULL, *alarm_reason_info = NULL, *alarm_desc = NULL;
+ json_object *temp_jso = NULL, *alarm_info = NULL;
+ alarm_info_s_out *alarmpara_out = NULL;
+ int perceivedSeverity_value = 0;
+ char *action_string = NULL;
+ if (buf == NULL || (buf_len < (int) sizeof (alarm_info_s_out)))
+ {
+ NSAM_LOGERR ("input para invalid");
+ return -1;
+ }
+ alarmpara_out = (alarm_info_s_out *) buf;
+
+ /*use sizeof(alarmpara_out->alarmId) instead of devil figure 16 */
+ retVal =
+ SPRINTF_S (alarmpara_out->alarmId, sizeof (alarmpara_out->alarmId), "%d",
+ alarm_id);
+ if (-1 == retVal)
+ {
+ NSAM_LOGERR ("SPRINTF_S failed]ret=%d", retVal);
+ return -1;
+ }
+
+ (void) gettimeofday (&t_val, NULL);
+ time_t t_sec = (time_t) t_val.tv_sec;
+ /*return value check */
+ if (NULL == localtime_r (&t_sec, &now_time))
+ {
+ NSAM_LOGERR ("localtime_r failed]");
+ return -1;
+ }
+
+ /*use sizeof(alarmpara_out->alarmtime) instead of devil figure 32 */
+ retVal =
+ SPRINTF_S (alarmpara_out->alarmtime, sizeof (alarmpara_out->alarmtime),
+ "%4d%02d%02d%02d%02d%02d%06ld", now_time.tm_year + 1900,
+ now_time.tm_mon + 1, now_time.tm_mday, now_time.tm_hour,
+ now_time.tm_min, now_time.tm_sec, (long) t_val.tv_usec);
+ if (-1 == retVal)
+ {
+ NSAM_LOGERR ("SPRINTF_S failed]ret=%d", retVal);
+ return -1;
+ }
+
+ retVal =
+ STRNCPY_S (alarmpara_out->comptentname,
+ sizeof (alarmpara_out->comptentname), COMPONENT_NAME,
+ strlen (COMPONENT_NAME));
+ if (EOK != retVal)
+ {
+ NSAM_LOGERR ("STRNCPY_S failed]ret=%d", retVal);
+ return -1;
+ }
+
+ switch (alarm_res.alarm_reason_get)
+ {
+ case ALARM_REASON_SOCKET:
+ /* alarmName and reason info is incorrect */
+ alarm_reason_info = "socketResource";
+ if (alarm_res.alarm_flag_get == ALARM_PRODUCT)
+ {
+ alarm_string = "networkResourceOverload";
+ alarm_desc = "more than 80 percent used";
+ perceivedSeverity_value = 2;
+ action_string = "alarm";
+ }
+ else
+ {
+ alarm_string = "networkResourceNormal";
+ alarm_desc = "less than 60 percent used";
+ perceivedSeverity_value = 5;
+ action_string = "clear";
+ }
+
+ break;
+ case ALARM_REASON_MSG_BUF:
+ alarm_reason_info = "SendBufResource";
+ if (alarm_res.alarm_flag_get == ALARM_PRODUCT)
+ {
+ alarm_string = "networkResourceOverload";
+ alarm_desc = "more than 80 percent used";
+ perceivedSeverity_value = 2;
+ action_string = "alarm";
+ }
+ else
+ {
+ alarm_string = "networkResourceNormal";
+ alarm_desc = "less than 60 percent used";
+ perceivedSeverity_value = 5;
+ action_string = "clear";
+ }
+
+ break;
+ case ALARM_REASON_NSMAIN:
+ /* process status alarm change from event to alarm/clear */
+ alarm_reason_info = "networkProcStatus";
+ if (alarm_res.alarm_flag_get == ALARM_PRODUCT)
+ {
+ alarm_string = "network-data-down";
+ alarm_desc = "networkProcDown";
+ perceivedSeverity_value = 2;
+ action_string = "alarm";
+ }
+ else
+ {
+ alarm_string = "network-data-up";
+ alarm_desc = "networkProcUp";
+ perceivedSeverity_value = 5;
+ action_string = "clear";
+ }
+
+ break;
+ default:
+ NSAM_LOGERR ("alarm_reason incorrect]ret=%d",
+ alarm_res.alarm_reason_get);
+ return -1;
+ }
+
+ str_len = 0;
+
+ json_object *alarmlist = json_object_new_object ();
+ if (NULL == alarmlist)
+ {
+ NSAM_LOGERR ("alarmlist is NULL");
+ return -1;
+ }
+
+ json_object *alarmItem = json_object_new_object ();
+
+ if (NULL == alarmItem)
+ {
+ NSAM_LOGERR ("alarmItem is NULL");
+ (void) json_object_put (alarmlist);
+ return -1;
+ }
+
+ JSON_NEW_STRING_OBJ ("ICTS_BASE=1", temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "neDN", temp_jso);
+ JSON_NEW_STRING_OBJ ("service", temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "neType", temp_jso);
+ JSON_NEW_STRING_OBJ ("ICTS_BASE", temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "neName", temp_jso);
+ JSON_NEW_STRING_OBJ ("service", temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "objectClass", temp_jso);
+ JSON_NEW_STRING_OBJ ("nStack", temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "moDN", temp_jso);
+ JSON_NEW_STRING_OBJ ("nStack", temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "moName", temp_jso);
+ JSON_NEW_STRING_OBJ ("default", temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "userId", temp_jso);
+
+ JSON_NEW_INT_OBJ (alarm_id, temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "alarmId", temp_jso);
+
+ JSON_NEW_INT_OBJ (10001, temp_jso, json_object_put, alarmlist, alarmItem);
+ json_object_object_add (alarmItem, "groupId", temp_jso);
+
+ JSON_NEW_STRING_OBJ (g_vmid, temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "objectInstance", temp_jso);
+ JSON_NEW_INT_OBJ (8, temp_jso, json_object_put, alarmlist, alarmItem);
+ json_object_object_add (alarmItem, "eventType", temp_jso);
+
+ JSON_NEW_STRING_OBJ (alarm_string, temp_jso, json_object_put, alarmlist,
+ alarmItem);
+ json_object_object_add (alarmItem, "alarmName", temp_jso);
+
+ JSON_NEW_INT_OBJ (perceivedSeverity_value, temp_jso, json_object_put,
+ alarmlist, alarmItem);
+
+ json_object_object_add (alarmItem, "perceivedSeverity", temp_jso);
+
+ JSON_NEW_OBJ (alarm_info, json_object_put, alarmlist, alarmItem);
+ JSON_NEW_STRING_OBJ_1 (alarm_reason_info, temp_jso, json_object_put,
+ alarmlist, alarmItem, alarm_info);
+ json_object_object_add (alarm_info, "reason", temp_jso);
+ JSON_NEW_STRING_OBJ_1 (alarm_desc, temp_jso, json_object_put, alarmlist,
+ alarmItem, alarm_info);
+ json_object_object_add (alarm_info, "desc", temp_jso);
+ json_object_object_add (alarmItem, "alarmInfo", alarm_info);
+
+ JSON_NEW_STRING_OBJ (action_string, temp_jso, json_object_put, alarmlist,
+ alarmItem);
+
+ json_object_object_add (alarmlist, "data", alarmItem);
+
+ json_object_object_add (alarmlist, "action", temp_jso);
+
+ const char *str = json_object_to_json_string (alarmlist);
+ if (str == NULL)
+ {
+ NSMON_LOGERR ("json_object_to_json_string fail");
+ (void) json_object_put (alarmlist);
+ return -1;
+ }
+
+ str_len = strlen (str);
+
+ if (str_len >= ALARM_PARA_LENGTH_OUTER)
+ {
+ NSAM_LOGERR ("str_len >= ALARM_PARA_LENGTH_OUTER");
+ (void) json_object_put (alarmlist);
+ return -1;
+ }
+
+ retVal =
+ STRNCPY_S (alarmpara_out->alarmcontent, ALARM_PARA_LENGTH_OUTER, str,
+ str_len + 1);
+
+ if (EOK != retVal)
+ {
+ NSAM_LOGERR ("STRNCPY_S failed]ret=%d", retVal);
+ (void) json_object_put (alarmlist);
+ return -1;
+ }
+
+ (void) json_object_put (alarmlist);
+
+ return 0;
+
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : send alarm to thirdparty alarm module, now only log
+********************************************************************/
+int
+ns_send_alarm_to_alarm_module (alarm_result alarm_res)
+{
+ int retVal = -1;
+
+ nsfw_mgr_msg *req_msg =
+ nsfw_mgr_msg_alloc (MGR_MSG_LARGE_ALARM_RSP, NSFW_PROC_ALARM);
+
+ if (NULL == req_msg)
+ {
+ NSAM_LOGERR ("mgr_msg_alloc fail]alarm_id=%d", alarm_res.alarm_id_get);
+ return -1;
+ }
+
+ if (req_msg->msg_len < (NSFW_MGR_MSG_HDR_LEN + sizeof (alarm_info_s_out)))
+ {
+ NSAM_LOGERR ("mgr_msg_alloc length fail]alarm_id=%d",
+ alarm_res.alarm_id_get);
+ nsfw_mgr_msg_free (req_msg);
+ return -1;
+ }
+ /* husky agent receive alarm info using fixed length */
+ req_msg->msg_len = (NSFW_MGR_MSG_HDR_LEN + sizeof (alarm_info_s_out));
+
+ retVal =
+ ns_get_alarm_body ((char *) req_msg->msg_body,
+ NSFW_MGR_LARGE_MSG_BODY_LEN, alarm_res);
+
+ if (-1 == retVal)
+ {
+ NSAM_LOGERR ("ns_get_alarm_body fail]alarm_id=%d",
+ alarm_res.alarm_id_get);
+ nsfw_mgr_msg_free (req_msg);
+ return -1;
+ }
+
+ u8 ret = nsfw_mgr_send_msg (req_msg);
+
+ if (FALSE == ret)
+ {
+ NSAM_LOGERR ("nsfw_mgr_send_msg fail]alarm_id=%d,reason=%d,flag=%d",
+ alarm_res.alarm_id_get, alarm_res.alarm_reason_get,
+ alarm_res.alarm_flag_get);
+ ns_alarm_set_sendFlag (alarm_res.alarm_id_get, ALARM_SEND_FAIL);
+ nsfw_mgr_msg_free (req_msg);
+ return -1;
+ }
+
+ NSAM_LOGINF ("nsfw_mgr_send_msg succ]alarm_id=%d,reason=%d,flag=%d",
+ alarm_res.alarm_id_get, alarm_res.alarm_reason_get,
+ alarm_res.alarm_flag_get);
+ ns_alarm_set_sendFlag (alarm_res.alarm_id_get, ALARM_SEND_SUCC);
+
+ nsfw_mgr_msg_free (req_msg);
+
+ return 0;
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : alarm product common func
+********************************************************************/
+void
+ns_send_alarm_inner (enum_alarm_id alarm_id, void *para, int check_times,
+ int check_state_flag)
+{
+ alarm_data *alarm_value = NULL;
+ alarm_result alarm_id_report;
+ int alarm_idx;
+ int alarm_loop;
+ int temp_alarm_time_laps;
+ int abnormal_alarm_flag = 0, normal_alarm_flag =
+ 0, total_abnormal_alarm_flag = 0;
+ int need_check_flag = check_state_flag;
+ int ret = 0;
+
+ if ((alarm_id <= 0) || (alarm_id >= ALARM_EVENT_MAX)
+ || (0 == g_alarm_data[alarm_id].valid_flag))
+ {
+ NSAM_LOGERR ("alarm_id is invalid or not reg");
+ return;
+ }
+
+ alarm_id_report.alarm_id_get = ALARM_EVENT_MAX;
+
+ alarm_idx = alarm_id;
+
+ alarm_value = &g_alarm_data[alarm_idx];
+
+ for (alarm_loop = 0; alarm_loop < alarm_value->alarm_reason_cnt;
+ alarm_loop++)
+ {
+ abnormal_alarm_flag = 0;
+ if (ALARM_PERIOD_CHECK == alarm_value->_alarm_type)
+ {
+ if (NULL ==
+ alarm_value->_alarm_para.func_alarm_check_period[alarm_loop])
+ {
+ NSAM_LOGERR ("alarm id func_alarm_check is invalid]alarm_id=%d",
+ alarm_id);
+ return;
+ }
+ alarm_id_report =
+ alarm_value->_alarm_para.func_alarm_check_period[alarm_loop] ();
+ }
+ else if (ALARM_SEND_ONCE == alarm_value->_alarm_type)
+ {
+ if (NULL == alarm_value->_alarm_para.func_alarm_check[alarm_loop])
+ {
+ NSAM_LOGERR ("alarm id func_alarm_check is invalid]alarm_id=%d",
+ alarm_id);
+ return;
+ }
+ alarm_id_report =
+ alarm_value->_alarm_para.func_alarm_check[alarm_loop] (para);
+ }
+
+ if ((alarm_id_report.alarm_id_get <= ALARM_EVENT_BASE)
+ || alarm_id_report.alarm_id_get >= ALARM_EVENT_MAX)
+ {
+ NSAM_LOGDBG ("don't satisfy alarm condition");
+ return;
+ }
+
+ alarm_idx = alarm_id_report.alarm_id_get;
+
+ if (ALARM_EVENT_NSTACK_MAIN_ABNORMAL == alarm_idx)
+ {
+ need_check_flag = 0;
+ }
+ /* for send current status alarm, needn't check count also status. */
+ /* for sending current state alarm, needn't check current state */
+ if ((alarm_id_report.alarm_flag_get == ALARM_PRODUCT)
+ && (((alarm_value->alarm_time_laps[alarm_loop] < check_times)
+ && (alarm_value->_alarm_flag != ALARM_PRODUCT))
+ || (need_check_flag == 0)))
+ {
+ if ((0 == check_state_flag)
+ || ++(alarm_value->alarm_time_laps[alarm_loop]) >= check_times)
+ {
+ alarm_value->_alarm_flag = ALARM_PRODUCT;
+ abnormal_alarm_flag = 1;
+ total_abnormal_alarm_flag++;
+ }
+
+ }
+ else if ((alarm_id_report.alarm_flag_get == ALARM_CLEAN)
+ && ((alarm_value->_alarm_flag == ALARM_PRODUCT)
+ || (need_check_flag == 0)))
+ {
+ if ((1 == check_state_flag)
+ && (alarm_value->alarm_time_laps[alarm_loop] > 0))
+ {
+ --alarm_value->alarm_time_laps[alarm_loop];
+ }
+ if ((alarm_value->alarm_time_laps[alarm_loop] <= 0)
+ || (0 == check_state_flag))
+ {
+ normal_alarm_flag++;
+ }
+ }
+
+ temp_alarm_time_laps = alarm_value->alarm_time_laps[alarm_loop];
+
+ /* can't product same alarm multi times */
+ /* only overload alarm can send */
+ if (abnormal_alarm_flag != 1)
+ {
+ NSAM_LOGDBG
+ ("don't satisfy alarm condition]alarm_idx=%d,alarm_time_laps=%d",
+ alarm_idx, temp_alarm_time_laps);
+ continue;
+ }
+
+ ret = ns_send_alarm_to_alarm_module (alarm_id_report);
+
+ if (-1 == ret)
+ {
+ ns_alarm_set_sendFlag (alarm_id, ALARM_SEND_FAIL);
+ }
+ else
+ {
+ ns_alarm_set_sendFlag (alarm_id, ALARM_SEND_SUCC);
+ }
+ /* for alarm current status, only can send one */
+ /* if it have multi-scearo, only can send a overload alarm */
+ if (0 == need_check_flag)
+ {
+ break;
+ }
+
+ }
+
+ if ((total_abnormal_alarm_flag == 0)
+ && (alarm_value->alarm_reason_cnt == normal_alarm_flag))
+ {
+ alarm_value->_alarm_flag = ALARM_CLEAN;
+ ret = ns_send_alarm_to_alarm_module (alarm_id_report);
+ if (-1 == ret)
+ {
+ ns_alarm_set_sendFlag (alarm_id, ALARM_SEND_FAIL);
+ }
+ else
+ {
+ ns_alarm_set_sendFlag (alarm_id, ALARM_SEND_SUCC);
+ }
+ }
+
+ return;
+
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : API, any app want to product alarm,need call this function
+********************************************************************/
+void
+ns_send_alarm (enum_alarm_id alarm_id, void *para)
+{
+ ns_send_alarm_inner (alarm_id, para, 1, 1);
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : period check alarm expire handle function
+********************************************************************/
+int
+ns_alarm_timer_proc_fun (u32 timer_type, void *argv)
+{
+ struct timespec time_left;
+ if (NULL == argv)
+ {
+ NSAM_LOGERR ("abnormal: argv is NULL ");
+ return -1;
+ }
+
+ alarm_data *alarm_value = (alarm_data *) argv;
+
+ if (alarm_value->_alarm_type == ALARM_PERIOD_CHECK)
+ {
+ ns_send_alarm_inner (alarm_value->_alarm_id, NULL,
+ ALARM_PERIOD_CHECK_TIMES, 1);
+ time_left.tv_sec = alarm_value->_alarm_para.period_alarm.time_length;
+ time_left.tv_nsec = 0;
+ nsfw_timer_info *timer_info =
+ nsfw_timer_reg_timer (0, (void *) (u64) alarm_value,
+ ns_alarm_timer_proc_fun, time_left);
+ if (NULL == timer_info)
+ {
+ NSAM_LOGERR ("nsfw_timer_reg_timer fail");
+ return -1;
+ }
+ }
+ NSAM_LOGDBG ("abnormal: alarm is not period ");
+
+ return 0;
+
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : app reg alarm info to alarm module
+********************************************************************/
+int
+ns_reg_alarm (enum_alarm_id alarm_id, alarm_type alarmType,
+ alarm_para * alarmPara)
+{
+ alarm_data *alarm_value = NULL;
+ alarm_reason loop = ALARM_REASON_BEGIN;
+ struct timespec time_left;
+
+ if ((alarm_id <= ALARM_EVENT_BASE) || (alarm_id >= ALARM_EVENT_MAX)
+ || (NULL == alarmPara)
+ || (alarmPara->alarm_reason_count > ALARM_REASON_MAX))
+ {
+ NSAM_LOGERR ("para invalid]alarm_id=%d ", alarm_id);
+ return -1;
+ }
+
+ for (loop = ALARM_REASON_BEGIN; loop < alarmPara->alarm_reason_count;
+ loop++)
+ {
+ if (NULL == alarmPara->func_alarm_check[loop])
+ {
+ NSAM_LOGERR ("para invalid]func_alarm_check=NULL,loop=%d", loop);
+ return -1;
+ }
+ }
+
+ alarm_value = &g_alarm_data[alarm_id];
+ alarm_value->_alarm_type = alarmType;
+ alarm_value->_alarm_para.period_alarm.time_length =
+ alarmPara->period_alarm.time_length;
+ alarm_value->_alarm_id = alarm_id;
+ alarm_value->alarm_reason_cnt = alarmPara->alarm_reason_count;
+ alarm_value->_alarm_flag = ALARM_CLEAN;
+
+ for (loop = ALARM_REASON_BEGIN; loop < alarmPara->alarm_reason_count;
+ loop++)
+ {
+ alarm_value->alarm_time_laps[loop] = alarmPara->alarm_reason_set[loop];
+ alarm_value->_alarm_para.func_alarm_check[loop] =
+ alarmPara->func_alarm_check[loop];
+ alarm_value->_alarm_para.func_alarm_check_period[loop] =
+ alarmPara->func_alarm_check_period[loop];
+ alarm_value->alarm_time_laps[loop] = 0;
+ }
+
+ alarm_value->valid_flag = 1;
+
+ if (ALARM_PERIOD_CHECK == alarmType)
+ {
+ time_left.tv_sec = alarm_value->_alarm_para.period_alarm.time_length;
+ time_left.tv_nsec = 0;
+ nsfw_timer_info *timer_info =
+ nsfw_timer_reg_timer (0, (void *) (u64) alarm_value,
+ ns_alarm_timer_proc_fun, time_left);
+ if (NULL == timer_info)
+ {
+ NSAM_LOGERR ("nsfw_timer_reg_timer fail");
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************
+* Copyright 2017, Huawei Tech. Co., Ltd.
+* ALL RIGHTS RESERVED
+*Description : send alarm as per current state
+********************************************************************/
+void
+ns_send_init_alarm (enum_alarm_id alarm_id)
+{
+ if ((alarm_id <= 0) || (alarm_id >= ALARM_EVENT_MAX))
+ {
+ NSAM_LOGDBG ("alarm_id is invalid");
+ return;
+ }
+ ns_send_alarm_inner (alarm_id,
+ (void *) (g_alarm_data[alarm_id]._alarm_flag), 1, 0);
+}
+
+NSFW_MODULE_NAME (NSFW_ALARM_MODULE)
+NSFW_MODULE_PRIORITY (10)
+NSFW_MODULE_DEPENDS (NSTACK_DMM_MODULE)
+NSFW_MODULE_INIT (ns_alarm_module_init)
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif /* __cplusplus */
diff --git a/stacks/lwip_stack/src/alarm/alarm.h b/stacks/lwip_stack/src/alarm/alarm.h
new file mode 100644
index 0000000..4c5f692
--- /dev/null
+++ b/stacks/lwip_stack/src/alarm/alarm.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 _ALARM_H_
+#define _ALARM_H_
+
+#include <stdint.h>
+#include "alarm_api.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/* alarm clean time = 1*3 */
+
+#define ALARM_RESEND_TIMER_LENGTH 60
+#define ALARM_INIT_RESEND_TIMER_LENGTH 40
+
+#define ALARM_SEND_SUCC 1
+#define ALARM_SEND_FAIL 0
+
+#define ALARM_PARA_LENGTH_OUTER 2048
+
+#define ALARM_PERIOD_CHECK_TIMES 3
+
+#define MAX_VMID_LEN 256
+
+#define MIN_VM_ID_LEN 1
+#define MAX_VM_ID_LEN 256
+
+#define INVALID_STR_LEN(_str, _min_len, _maxlen) (NULL == _str || strlen(_str) < _min_len || strlen(_str) > _maxlen)
+
+typedef struct _alarm_data
+{
+ alarm_para _alarm_para;
+ alarm_type _alarm_type;
+ enum_alarm_id _alarm_id;
+ int alarm_time_laps[ALARM_REASON_MAX];
+ alarm_flag _alarm_flag;
+ int alarm_reason_cnt;
+ int valid_flag;
+ int send_succ_flag;
+
+} alarm_data;
+
+typedef struct _alarm_info_s_out
+{
+ char alarmId[16];
+ char comptentname[32];
+ char alarmtime[32];
+ char alarmcontent[ALARM_PARA_LENGTH_OUTER];
+} alarm_info_s_out;
+
+int ns_send_alarm_to_alarm_module (alarm_result alarm_res);
+
+void ns_send_alarm_inner (enum_alarm_id alarm_id, void *para, int check_times,
+ int check_state_flag);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/alarm/alarm_api.h b/stacks/lwip_stack/src/alarm/alarm_api.h
new file mode 100644
index 0000000..8c7aca1
--- /dev/null
+++ b/stacks/lwip_stack/src/alarm/alarm_api.h
@@ -0,0 +1,107 @@
+/*
+*
+* 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 _ALARM_API_H_
+#define _ALARM_API_H_
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define NSFW_ALARM_MODULE "nstack_alarm"
+
+/* alarm ID for every event, when need add new alarm, here add a alarm_id define */
+typedef enum _alarm_id
+{
+ ALARM_EVENT_BASE,
+ ALARM_EVENT_NSTACK_RESOURCE_ALARM,
+ ALARM_EVENT_NSTACK_NO_USE,
+ ALARM_EVENT_NSTACK_MAIN_ABNORMAL,
+ ALARM_EVENT_MAX
+} enum_alarm_id;
+
+/* support both type alarm:
+ 1. support other module call func:ns_send_alarm to product alarm;
+ 2. alarm module call function periodly to check whether need product alarm */
+typedef enum _alarm_type
+{
+ ALARM_PERIOD_CHECK,
+ ALARM_SEND_ONCE
+} alarm_type;
+
+typedef enum _alarm_flag
+{
+ ALARM_PRODUCT,
+ ALARM_CLEAN,
+ ALARM_MAX
+} alarm_flag;
+
+typedef enum _alarm_reason
+{
+ ALARM_REASON_BEGIN,
+ ALARM_REASON_SOCKET = 0,
+ ALARM_REASON_MSG_BUF,
+ ALARM_REASON_NSMAIN,
+ ALARM_REASON_MAX
+} alarm_reason;
+
+typedef struct _alarm_result
+{
+ enum_alarm_id alarm_id_get;
+ alarm_reason alarm_reason_get;
+ alarm_flag alarm_flag_get;
+} alarm_result;
+
+/* check whether need product alarm,if return 0, then product alarm */
+typedef alarm_result (*alarm_check_func) (void *para);
+typedef alarm_result (*alarm_check_func_period) (void);
+
+typedef struct _alarm_para
+{
+ union
+ {
+ int time_length;
+ } period_alarm;
+ union
+ {
+ alarm_check_func func_alarm_check[ALARM_REASON_MAX];
+ alarm_check_func_period func_alarm_check_period[ALARM_REASON_MAX];
+ };
+
+ alarm_reason alarm_reason_set[ALARM_REASON_MAX];
+ int alarm_reason_count;
+
+} alarm_para;
+
+/* for any alarm added, firstly call following function to reg */
+int ns_reg_alarm (enum_alarm_id alarm_id, alarm_type _alarm_type,
+ alarm_para * _alarm_para);
+
+void ns_send_init_alarm (enum_alarm_id alarm_id);
+
+/* other module call this func to product alarm, here para is same as alarm_check_func's para */
+void ns_send_alarm (enum_alarm_id alarm_id, void *para);
+int ns_alarm_module_init (void *param);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/include/nsfw_msg.h b/stacks/lwip_stack/src/include/nsfw_msg.h
new file mode 100644
index 0000000..e5254d3
--- /dev/null
+++ b/stacks/lwip_stack/src/include/nsfw_msg.h
@@ -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.
+*/
+
+#ifndef MSG_H
+#define MSG_H
+#include "types.h"
+#include "common_mem_api.h"
+#include "nsfw_rti.h"
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define MAX_MSG_SIZE 512
+COMPAT_PROTECT (MAX_MSG_SIZE, 512);
+#define MAX_MSG_PARAM_SIZE 128
+COMPAT_PROTECT (MAX_MSG_PARAM_SIZE, 128);
+
+#define MSG_ASYN_POST 0
+#define MSG_SYN_POST 1
+
+typedef struct
+{
+ u16 module_type;
+ u16 major_type;
+ u16 minor_type;
+ u16 op_type; /* MSG_SYN_POST or MSG_ASYN_POST */
+ sys_sem_st op_completed;
+ i32 err;
+ PRIMARY_ADDR void *msg_from; /* use it to free msg */
+ i64 receiver;
+ i64 comm_receiver;
+ nsfw_res res_chk;
+ u32 src_pid;
+ u32 recycle_pid; /* use it in recycle */
+ u64 span_pid;
+ i64 extend_member_bit;
+} msg_param;
+
+typedef struct msg_t
+{
+ msg_param param;
+ i8 msg_param_pad[MAX_MSG_PARAM_SIZE - sizeof (msg_param)]; /* sizeof(msg_param) + sizeof(msg_param_pad) = MAX_MSG_PARAM_SIZE */
+ i64 buffer[(MAX_MSG_SIZE - MAX_MSG_PARAM_SIZE) / 8];
+}
+data_com_msg;
+
+#define MAX_MODULE_TYPE 64
+#define MAX_MAJOR_TYPE 256
+#define MAX_MINOR_TYPE 256
+
+struct rti_queue
+{
+ /* corresponding to enum spl_tcpip_msg_type */
+ volatile u64 tcpip_msg_enq[MAX_MAJOR_TYPE];
+ volatile u64 tcpip_msg_enq_fail[MAX_MAJOR_TYPE];
+ u64 tcpip_msg_deq[MAX_MAJOR_TYPE];
+
+ /* corresponding to enum api_msg_type, this is sub-type of SPL_TCPIP_NEW_MSG_API */
+ volatile u64 api_msg_enq[MAX_MINOR_TYPE];
+ volatile u64 api_msg_enq_fail[MAX_MINOR_TYPE];
+ u64 api_msg_deq[MAX_MINOR_TYPE];
+
+ u64 extend_member_bit;
+};
+
+enum MSG_MODULE_TYPE
+{
+ MSG_MODULE_IP,
+ MSG_MODULE_SBR,
+ MSG_MODULE_HAL,
+ MSG_MODULE_SPL,
+ MSG_MODULE_TIMER,
+ MSG_MODULE_MT,
+ MSG_MODULE_DFX,
+ MSG_MODULE_MAX = MAX_MODULE_TYPE
+};
+
+typedef int (*msg_fun) (data_com_msg * m);
+
+/* *INDENT-OFF* */
+extern msg_fun g_msg_module_fun_array[MAX_MODULE_TYPE];
+extern msg_fun g_msg_module_major_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE];
+extern msg_fun g_msg_module_major_minor_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE][MAX_MINOR_TYPE];
+extern msg_fun g_msg_unsupport_fun;
+/* *INDENT-ON* */
+
+#define REGIST_MSG_MODULE_FUN(module, fun) \
+ static void regist_ ## module ## _function (void) \
+ __attribute__((__constructor__)); \
+ static void regist_ ## module ## _function (void) \
+ { \
+ g_msg_module_fun_array[module] = fun; \
+ } \
+
+#define REGIST_MSG_MODULE_MAJOR_FUN(module, major, fun) \
+ static void regist_ ## module ## major ## _function (void) \
+ __attribute__((__constructor__)); \
+ static void regist_ ## module ## major ## _function (void) \
+ { \
+ g_msg_module_major_fun_array[module][major] = fun; \
+ } \
+
+#define REGIST_MSG_MODULE_MAJOR_MINOR_FUN(module, major, minor, fun) \
+ static void regist_ ## module ## major ## minor ## _function (void) \
+ __attribute__((__constructor__)); \
+ static void regist_ ## module ## major ## minor ## _function (void) \
+ { \
+ g_msg_module_major_minor_fun_array[module][major][minor] = fun; \
+ } \
+
+#define REGIST_MSG_UNSUPPORT_FUN(fun) \
+ static void regist_msg_unsupport_function (void) \
+ __attribute__((__constructor__)); \
+ static void regist_msg_unsupport_function (void) \
+ { \
+ g_msg_unsupport_fun = fun; \
+ }
+
+static inline int
+unsupport_msg (data_com_msg * m)
+{
+ if (g_msg_unsupport_fun)
+ {
+ return g_msg_unsupport_fun (m);
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : call_msg_fun
+* Description : call msg fun
+* Input : data_com_msg* m
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+call_msg_fun (data_com_msg * m)
+{
+ u16 module = m->param.module_type;
+ u16 major = m->param.major_type;
+ u16 minor = m->param.minor_type;
+
+ if ((module >= MAX_MODULE_TYPE) || (major >= MAX_MAJOR_TYPE)
+ || (minor >= MAX_MINOR_TYPE))
+ {
+ return unsupport_msg (m);
+ }
+
+ nsfw_rti_stat_macro (NSFW_STAT_PRIMARY_DEQ, m);
+
+ if (g_msg_module_fun_array[module]
+ && (g_msg_module_fun_array[module] (m) != 0))
+ {
+ return -1;
+ }
+
+ if (g_msg_module_major_fun_array[module][major]
+ && (g_msg_module_major_fun_array[module][major] (m) != 0))
+ {
+ return -1;
+ }
+
+ if (g_msg_module_major_minor_fun_array[module][major][minor])
+ {
+ return g_msg_module_major_minor_fun_array[module][major][minor] (m);
+ }
+
+ if (!g_msg_module_fun_array[module]
+ && !g_msg_module_major_fun_array[module][major]
+ && !g_msg_module_major_minor_fun_array[module][major][minor])
+ {
+ return unsupport_msg (m);
+ }
+
+ return 0;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/include/nsfw_msg_api.h b/stacks/lwip_stack/src/include/nsfw_msg_api.h
new file mode 100644
index 0000000..85dca49
--- /dev/null
+++ b/stacks/lwip_stack/src/include/nsfw_msg_api.h
@@ -0,0 +1,309 @@
+/*
+*
+* 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 MSG_API_H
+#define MSG_API_H
+#include "nsfw_msg.h"
+#include "nsfw_mem_api.h"
+#include "nstack_log.h"
+#include "nsfw_rti.h"
+#include "common_mem_api.h"
+#include "nsfw_recycle_api.h"
+#include "common_pal_bitwide_adjust.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define SET_MSG_ERR(m, error) ((m)->param.err = (error))
+#define GET_MSG_ERR(m) ((m)->param.err)
+
+/* for sync message from sbr we should signal sem */
+#define SYNC_MSG_ACK(m) sys_sem_s_signal(&((m)->param.op_completed))
+
+/* for async message from sbr we should free the message */
+#define ASYNC_MSG_FREE(m) msg_free(m)
+
+#define MSG_ENTRY(_ptr, _type, _member) container_of((void *)_ptr, _type, _member)
+
+#ifndef NSTACK_STATIC_CHECK
+/*****************************************************************************
+* Prototype : msg_malloc
+* Description : malloc msg
+* Input : mring_handle mhandle
+* Output : None
+* Return Value : static inline data_com_msg*
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline data_com_msg *
+msg_malloc (mring_handle mhandle)
+{
+ if (!mhandle)
+ {
+ NSFW_LOGERR ("mhandle is null");
+ return NULL;
+ }
+
+ data_com_msg *m = NULL;
+ if (nsfw_mem_ring_dequeue (mhandle, (void **) &m) != 1)
+ {
+ return NULL;
+ }
+
+ m->param.recycle_pid = get_sys_pid ();
+ res_alloc (&m->param.res_chk);
+ return m;
+}
+
+/*****************************************************************************
+* Prototype : msg_free
+* Description : free msg
+* Input : data_com_msg* m
+* mring_handle mhandle
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline void
+msg_free (data_com_msg * m)
+{
+ if (!m)
+ {
+ NSFW_LOGERR ("m is NULL");
+ return;
+ }
+
+ mring_handle mhandle = ADDR_SHTOL (m->param.msg_from);
+ if (!mhandle)
+ {
+ return;
+ }
+
+ if (res_free (&m->param.res_chk))
+ {
+ NSFW_LOGERR ("m refree!]m=%p", m);
+ return;
+ }
+
+ m->param.recycle_pid = 0;
+
+ if (nsfw_mem_ring_enqueue (mhandle, (void *) m) != 1)
+ {
+ NSFW_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ }
+}
+
+/*****************************************************************************
+* Prototype : msg_post
+* Description : post msg
+* Input : data_com_msg* m
+* mring_handle mhandle
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline int
+msg_post (data_com_msg * m, mring_handle mhandle)
+{
+ int ret;
+ if (!m || !mhandle)
+ {
+ NSFW_LOGERR ("param is not ok]m=%p,mhandle=%p", m, mhandle);
+ return -1;
+ }
+
+ while (1)
+ {
+ ret = nsfw_mem_ring_enqueue (mhandle, (void *) m);
+ switch (ret)
+ {
+ case 1:
+ if (MSG_SYN_POST == m->param.op_type)
+ {
+ sys_arch_sem_s_wait (&m->param.op_completed, 0);
+ }
+
+ return 0;
+ case 0:
+ continue;
+ default:
+ nsfw_rti_stat_macro (NSFW_STAT_PRIMARY_ENQ_FAIL, m);
+ return -1;
+ }
+ }
+}
+
+#define MSG_POST_FAILED 50
+/*****************************************************************************
+* Prototype : msg_post_with_lock_rel
+* Description : post msg to tcpip thread in mgrcom thread
+* Input : data_com_msg* m
+* mring_handle mhandle
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline int
+msg_post_with_lock_rel (data_com_msg * m, mring_handle mhandle)
+{
+ int ret;
+ int try_count = 0;
+ if (!m || !mhandle)
+ {
+ NSFW_LOGERR ("param is not ok]m=%p,mhandle=%p", m, mhandle);
+ return -1;
+ }
+
+ while (1)
+ {
+ ret = nsfw_mem_ring_enqueue (mhandle, (void *) m);
+ switch (ret)
+ {
+ case 1:
+ if (MSG_SYN_POST == m->param.op_type)
+ {
+ sys_arch_sem_s_wait (&m->param.op_completed, 0);
+ }
+
+ return 0;
+ case 0:
+ try_count++;
+ if (try_count > MSG_POST_FAILED)
+ {
+ try_count = 0;
+ nsfw_recycle_rechk_lock ();
+ }
+ sys_sleep_ns (0, 1000000);
+ continue;
+ default:
+ nsfw_rti_stat_macro (NSFW_STAT_PRIMARY_ENQ_FAIL, m);
+ return -1;
+ }
+ }
+}
+
+/*****************************************************************************
+* Prototype : msg_try_post
+* Description : try post msg
+* Input : data_com_msg* m
+* mring_handle mhandle
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline int
+msg_try_post (data_com_msg * m, mring_handle mhandle)
+{
+ if (!m || !mhandle)
+ {
+ NSFW_LOGERR ("param is not ok]m=%p,mhandle=%p", m, mhandle);
+ return -1;
+ }
+
+ int ret = nsfw_mem_ring_enqueue (mhandle, (void *) m);
+ if (1 == ret)
+ {
+ if (MSG_SYN_POST == m->param.op_type)
+ {
+ sys_arch_sem_s_wait (&m->param.op_completed, 0);
+ }
+
+ return 0;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : msg_fetch
+* Description : fetch msg
+* Input : mring_handle mhandle
+* data_com_msg** m
+* u32 num
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline int
+msg_fetch (mring_handle mhandle, data_com_msg ** m, u32 num)
+{
+ if (!m || !mhandle)
+ {
+ NSFW_LOGERR ("param is not ok]m=%p,mhandle=%p", m, mhandle);
+ return -1;
+ }
+
+ int ret;
+ while (1)
+ {
+ ret = nsfw_mem_ring_dequeuev (mhandle, (void *) m, num);
+ if (ret > 0)
+ {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : msg_try_fetch
+* Description : try fetch msg
+* Input : mring_handle mhandle
+* data_com_msg** m
+* u32 num
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*****************************************************************************/
+static inline int
+msg_try_fetch (mring_handle mhandle, data_com_msg ** m, u32 num)
+{
+ if (!m || !mhandle)
+ {
+ NSFW_LOGERR ("param is not ok]m=%p,mhandle=%p", m, mhandle);
+ return -1;
+ }
+
+ return nsfw_mem_ring_dequeuev (mhandle, (void *) m, num);
+}
+
+#else
+data_com_msg *msg_malloc (mring_handle mhandle);
+void msg_free (data_com_msg * m);
+int msg_post (data_com_msg * m, mring_handle mhandle);
+int msg_try_post (data_com_msg * m, mring_handle mhandle);
+int msg_fetch (mring_handle mhandle, data_com_msg ** m, u32 num);
+int msg_try_fetch (mring_handle mhandle, data_com_msg ** m, u32 num);
+int msg_post_with_lock_rel (data_com_msg * m, mring_handle mhandle);
+#endif
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/include/nsfw_mt_config.h b/stacks/lwip_stack/src/include/nsfw_mt_config.h
new file mode 100644
index 0000000..e1a7899
--- /dev/null
+++ b/stacks/lwip_stack/src/include/nsfw_mt_config.h
@@ -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.
+*/
+
+#ifndef _FW_MT_CONFIG_H
+#define _FW_MT_CONFIG_H
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define NSFW_CONFIG_MODULE "nsfw_config"
+#define NSTACK_SHARE_CONFIG "nstack_share_config"
+
+#define CFG_PATH "NSTACK_CONFIG_PATH"
+#define CFG_FILE_NAME "nStackConfig.json"
+#define MAX_FILE_NAME_LEN 512
+#define CFG_BUFFER_LEN 2048
+#define MAX_CFG_ITEM 128
+#define CFG_ITEM_LENGTH 64
+
+enum NSTACK_BASE_CFG
+{
+ CFG_BASE_SOCKET_NUM = 0,
+ CFG_BASE_RING_SIZE,
+ CFG_BASE_HAL_PORT_NUM,
+ CFG_BASE_ARP_STALE_TIME,
+ CFG_BASE_ARP_BC_RETRANS_NUM,
+ MAX_BASE_CFG
+};
+COMPAT_PROTECT (MAX_BASE_CFG, 5);
+
+enum NSTACK_CUSTOM_CFG
+{
+ /* mBuf config */
+ CFG_MBUF_DATA_SIZE,
+ CFG_TX_MBUF_NUM,
+ CFG_RX_MBUF_NUM,
+
+ /* memory pool config */
+ CFG_MP_TCPSEG_NUM,
+ CFG_MP_MSG_NUM,
+
+ /* RING config */
+ CFG_HAL_TX_RING_SIZE,
+ CFG_HAL_RX_RING_SIZE,
+ CFG_MBOX_RING_SIZE,
+ CFG_SPL_MAX_RING_SIZE,
+
+ /* PCB config */
+ CFG_TCP_PCB_NUM,
+ CFG_UDP_PCB_NUM,
+ CFG_RAW_PCB_NUM,
+
+ CFG_ARP_QUEUE_NUM,
+
+ MAX_CUSTOM_CFG
+};
+COMPAT_PROTECT (CFG_SPL_MAX_RING_SIZE, 8);
+
+enum EN_CFG_SEG
+{
+ CFG_SEG_BASE = 0,
+ CFG_SEG_LOG,
+ CFG_SEG_PATH,
+ CFG_SEG_PRI,
+ CFG_SEG_MAX
+};
+
+enum EN_CFG_ITEM_TYPE
+{
+ CFG_ITEM_TYPE_INT = 0,
+ CFG_ITEM_TYPE_STRING
+};
+
+enum EN_SEG_BASE_ITEM
+{
+ CFG_SEG_BASE_SOCKET_NUM = 0,
+ CFG_SEG_BASE_ARP_STALE_TIME,
+ CFG_SEG_BASE_ARP_BC_RETRANS_NUM,
+ CFG_SEG_BASE_MAX
+};
+
+enum EN_SEG_THREAD_PRI_ITEM
+{
+ CFG_SEG_THREAD_PRI_POLICY = 0,
+ CFG_SEG_THREAD_PRI_PRI,
+ CFG_SEG_THREAD_PRI_MAX
+};
+
+typedef void (*custom_check_fn) (void *pitem);
+
+// pack size?
+struct cfg_item_info
+{
+ char *name;
+ int type;
+ int min_value;
+ int max_value;
+ int default_value;
+ char *default_str;
+ custom_check_fn custom_check;
+ union
+ {
+ int value;
+ char *pvalue;
+ };
+};
+
+typedef struct _cfg_module_param
+{
+ u32 proc_type;
+ i32 argc;
+ u8 **argv;
+} cfg_module_param;
+
+extern u32 g_custom_cfg_items[MAX_CUSTOM_CFG];
+extern u32 g_base_cfg_items[MAX_BASE_CFG];
+
+#define get_base_cfg(tag) g_base_cfg_items[(tag)]
+#define get_custom_cfg(tag) g_custom_cfg_items[(tag)]
+#define set_custom_cfg_item(tag, value) g_custom_cfg_items[(tag)] = (value)
+
+/* stackx config data definition */
+
+/* app socket num */
+#define DEF_APP_SOCKET_NUM 1024
+
+/* socket num config */
+#define SOCKET_NUM_PER_THREAD 1024 /* socket number per thread */
+COMPAT_PROTECT (SOCKET_NUM_PER_THREAD, 1024);
+
+/*
+ MAX_SOCKET_NUM: max socket fd number one app can use, it should equal the max socket
+ number nstack support(CUR_CFG_SOCKET_NUM)
+*/
+
+#define DEF_SOCKET_NUM 1024 /* default socket number */
+COMPAT_PROTECT (DEF_SOCKET_NUM, 1024);
+#define MIN_SOCKET_NUM 1024 /* min socket number */
+
+#define MAX_SOCKET_NUM 8192 /* default: 8K sockets */
+
+#define CUR_CFG_SOCKET_NUM get_base_cfg(CFG_BASE_SOCKET_NUM) /* max socket numbere nstack support */
+
+#define DEF_ARP_STACLE_TIME 300 /* default arp stale time: second */
+#define MIN_ARP_STACLE_TIME 30 /* min arp stale time: second */
+#define MAX_ARP_STACLE_TIME 1200 /* max arp stale time: second */
+#define ARP_STALE_TIME get_base_cfg(CFG_BASE_ARP_STALE_TIME)
+
+#define DEF_ARP_BC_RETRANS_NUM 5 /* default arp broadcast retransmission times */
+#define MIN_ARP_BC_RETRANS_NUM 1 /* min arp broadcast retransmission times */
+#define MAX_ARP_BC_RETRANS_NUM 20 /* max arp broadcast retransmission times */
+#define ARP_BC_RETRANS_NUM get_base_cfg(CFG_BASE_ARP_BC_RETRANS_NUM)
+
+/* application mumber config */
+#define APP_POOL_NUM 32 /* max application number */
+COMPAT_PROTECT (APP_POOL_NUM, 32);
+
+/* thread number config */
+#define DEF_THREAD_NUM 1 /* default stackx thread number */
+#define MIN_THREAD_NUM 1 /* min thread number */
+#define MAX_THREAD_NUM 1 /* max thread number */
+COMPAT_PROTECT (MAX_THREAD_NUM, 1);
+
+/* hash size */
+#define MAX_TCP_HASH_SIZE 4096
+
+/* hal port number config */
+#define DEF_HAL_PORT_NUM 20 /* port number */
+COMPAT_PROTECT (DEF_HAL_PORT_NUM, 20);
+#define MIN_HAL_PORT_NUM 1
+#define MAX_HAL_PORT_NUM 255
+#define CUR_CFG_HAL_PORT_NUM get_base_cfg(CFG_BASE_HAL_PORT_NUM)
+
+/* vm number config */
+#define MAX_VF_NUM 4 /* max vf number */
+COMPAT_PROTECT (MAX_VF_NUM, 4);
+
+/* base ring size config */
+#define DEF_RING_BASE_SIZE 2048 /* base ring size */
+COMPAT_PROTECT (DEF_RING_BASE_SIZE, 2048);
+#define MIN_RING_BASE_SIZE 1024
+#define MAX_RING_BASE_SIZE 4096
+#define POOL_RING_BASE_SIZE get_base_cfg(CFG_BASE_RING_SIZE)
+
+/* mbuf data size config */
+#define DEF_MBUF_DATA_SIZE 2048 /* mbuf data size */
+COMPAT_PROTECT (DEF_MBUF_DATA_SIZE, 2048);
+#define TX_MBUF_MAX_LEN get_custom_cfg(CFG_MBUF_DATA_SIZE)
+
+/* tx mbuf pool size config */
+#define DEF_TX_MBUF_POOL_SIZE (4*POOL_RING_BASE_SIZE) /* tx mbuf pool size */
+
+#define TX_MBUF_POOL_SIZE get_custom_cfg(CFG_TX_MBUF_NUM)
+
+/* rx mbuf pool size config */
+#define DEF_RX_MBUF_POOL_SIZE (8*POOL_RING_BASE_SIZE) /* rx mbuf pool size */
+
+#define RX_MBUF_POOL_SIZE get_custom_cfg(CFG_RX_MBUF_NUM)
+
+/* hal netif rx/tx ring size config */
+#define DEF_HAL_RX_RING_SIZE 2048 /* hal rx ring size */
+
+#define DEF_HAL_TX_RING_SIZE 2048 /* hal tx ring size */
+#define HAL_RX_RING_SIZE get_custom_cfg(CFG_HAL_RX_RING_SIZE)
+#define HAL_TX_RING_SIZE get_custom_cfg(CFG_HAL_TX_RING_SIZE)
+
+/* stackx recv ring size config */
+#define DEF_SPL_MAX_RING_SIZE 1024
+COMPAT_PROTECT (DEF_SPL_MAX_RING_SIZE, 1024);
+
+#define SPL_MAX_RING_SIZE get_custom_cfg(CFG_SPL_MAX_RING_SIZE) /* ring size config, used in recv ring(per socket) */
+
+/* pcb number config */
+#define DEF_TCP_PCB_NUM 4096 /* tcp pcb number, per thread */
+COMPAT_PROTECT (DEF_TCP_PCB_NUM, 4096);
+#define DEF_UDP_PCB_NUM 512 /* udp pcb number, per thread */
+COMPAT_PROTECT (DEF_UDP_PCB_NUM, 512);
+#define DEF_RAW_PCB_NUM 600 /* raw pcb number, per thread */
+COMPAT_PROTECT (DEF_RAW_PCB_NUM, 600);
+
+#define DEF_ARP_QUEUE_NUM 300
+#define LARGE_ARP_QUEUE_NUM (512*1024)
+
+#define SPL_MEMP_NUM_TCP_PCB get_custom_cfg(CFG_TCP_PCB_NUM)
+
+#define SPL_MEMP_NUM_UDP_PCB get_custom_cfg(CFG_UDP_PCB_NUM)
+#define SPL_MEMP_NUM_RAW_PCB get_custom_cfg(CFG_RAW_PCB_NUM)
+
+#define SPL_MEMP_NUM_ARP_QUEUE get_custom_cfg(CFG_ARP_QUEUE_NUM)
+
+/* tcp seg number config */
+#define DEF_MEMP_NUM_TCP_SEG (2*APP_POOL_NUM*DEF_TX_MBUF_POOL_SIZE)
+#define SPL_MEMP_NUM_TCP_SEG get_custom_cfg(CFG_MP_TCPSEG_NUM) /* tcp segment number, per thread */
+
+/* stackx internal msg number config */
+#define DEF_TX_MSG_POOL_SIZE (DEF_TX_MBUF_POOL_SIZE*APP_POOL_NUM + MAX_VF_NUM*DEF_RX_MBUF_POOL_SIZE + DEF_RING_BASE_SIZE)
+
+#define TX_MSG_POOL_SIZE get_custom_cfg(CFG_MP_MSG_NUM) /* msg number, used by stackx internal, per thread */
+
+/* mbox ring size config */
+#define DEF_MBOX_RING_SIZE (DEF_RING_BASE_SIZE/4)
+COMPAT_PROTECT (DEF_MBOX_RING_SIZE, 512);
+
+#define MBOX_RING_SIZE get_custom_cfg(CFG_MBOX_RING_SIZE) /* mbox ring size config, per thread */
+
+/*some probem if CUSOTM_RECV_RING_SIZE more than 4096*/
+#define CUSOTM_RECV_RING_SIZE 4096
+COMPAT_PROTECT (CUSOTM_RECV_RING_SIZE, 4096);
+
+/*==============================================*
+ * constants or macros define *
+ *----------------------------------------------*/
+#define set_cfg_info(tag, item, min, max, def) { \
+ g_cfg_item_info[tag][item].min_value = (min); \
+ g_cfg_item_info[tag][item].max_value = (max); \
+ g_cfg_item_info[tag][item].default_value = (def);\
+ g_cfg_item_info[tag][item].value = (def);\
+}
+
+#define get_cfg_info(tag, item) g_cfg_item_info[tag][item].value
+
+u32 get_cfg_share_mem_size ();
+
+int get_share_cfg_from_mem (void *mem);
+
+int set_share_cfg_to_mem (void *mem);
+
+void config_module_init (cfg_module_param * param);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/include/nsfw_rti.h b/stacks/lwip_stack/src/include/nsfw_rti.h
new file mode 100644
index 0000000..6b81942
--- /dev/null
+++ b/stacks/lwip_stack/src/include/nsfw_rti.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 RTI_H
+#define RTI_H
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define nsfw_rti_stat_macro(type, m) if (1 == g_dfx_switch) { nsfw_rti_stat(type, m); }
+
+typedef enum nsfw_rti_stat_type
+{
+ NSFW_STAT_PRIMARY_ENQ,
+ NSFW_STAT_PRIMARY_ENQ_FAIL,
+ NSFW_STAT_PRIMARY_DEQ,
+} nsfw_rti_stat_type_t;
+
+typedef struct nsfw_app_info
+{
+ int nsocket_fd;
+ int sbr_fd;
+
+ int hostpid;
+ int pid;
+ int ppid;
+
+ u64 reserve1;
+ u64 reserve2;
+ u64 reserve3;
+ u64 reserve4;
+
+ u64 extend_member_bit;
+} nsfw_app_info_t;
+
+struct rti_queue;
+struct msg_t;
+
+extern char g_dfx_switch;
+extern struct rti_queue *g_nsfw_rti_primary_stat;
+
+void nsfw_rti_stat (nsfw_rti_stat_type_t statType, const struct msg_t *m);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/io_adpt/CMakeLists.txt b/stacks/lwip_stack/src/io_adpt/CMakeLists.txt
new file mode 100644
index 0000000..ae18116
--- /dev/null
+++ b/stacks/lwip_stack/src/io_adpt/CMakeLists.txt
@@ -0,0 +1,31 @@
+#########################################################################
+#
+# 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.
+#########################################################################
+
+FILE(GLOB_RECURSE HAL *.c)
+
+if(WITH_HAL_LIB)
+else()
+endif()
+
+
+INCLUDE_DIRECTORIES(
+ ./
+ ${PROJECT_SOURCE_DIR}/src/include/
+ ${PROJECT_SOURCE_DIR}/src/include/generic/
+ /usr/include/dpdk/
+)
+LINK_LIBRARIES(m dl rt dmm_api)
+ADD_LIBRARY(nStackHal STATIC ${HAL})
diff --git a/stacks/lwip_stack/src/io_adpt/dpdk.c b/stacks/lwip_stack/src/io_adpt/dpdk.c
new file mode 100644
index 0000000..63ffde1
--- /dev/null
+++ b/stacks/lwip_stack/src/io_adpt/dpdk.c
@@ -0,0 +1,2315 @@
+/*
+*
+* 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 <sched.h>
+#include <dlfcn.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <pwd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fnmatch.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+
+#include <rte_config.h>
+#include <rte_ethdev.h>
+#include <rte_mbuf.h>
+#include <rte_eth_bond.h>
+#include "nsfw_init.h"
+#include "hal.h"
+#include "nstack_securec.h"
+#include <rte_ethdev_driver.h>
+
+#define DPDK_NON_ROOT_USER_NAME "paas"
+#define DPDK_TOOL_ENV "DPDK_TOOL_DIR"
+#define DPDK_NIC_LIST_FILE "%s/ip_module/.nstack_dpdk_nic_list"
+#define SOCKET_ID_0 0
+
+NSTACK_STATIC struct passwd *dpdk_non_root_user;
+NSTACK_STATIC char dpdk_tool_path[HAL_MAX_PATH_LEN] = { 0 };
+
+/* Default configuration for rx and tx thresholds etc. */
+NSTACK_STATIC const struct rte_eth_rxconf rx_conf_default_igb = {
+ .rx_thresh = {
+ .pthresh = 8,
+ .hthresh = 8,
+ .wthresh = 1, //not bigger than 1
+ },
+};
+
+/*
+ * These default values are optimized for use with the Intel(R) 82576 1 GbE
+ * Controller and the DPDK e1000 PMD. Consider using other values for other
+ * network controllers and/or network drivers.
+ */
+NSTACK_STATIC const struct rte_eth_txconf tx_conf_default_igb = {
+ .tx_thresh = {
+ .pthresh = 8,
+ .hthresh = 1,
+ .wthresh = 16,
+ },
+ .tx_free_thresh = 0, /* Use PMD default values */
+ .tx_rs_thresh = 0, /* Use PMD default values */
+};
+
+/*
+ * RX and TX Prefetch, Host, and Write-back threshold values should be
+ * carefully set for optimal performance. Consult the network
+ * controller's datasheet and supporting DPDK documentation for guidance
+ * on how these parameters should be set.
+ */
+
+/* Default configuration for rx and tx thresholds etc. */
+NSTACK_STATIC const struct rte_eth_rxconf rx_conf_default_ixgbe = {
+ .rx_thresh = {
+ .pthresh = 8,
+ .hthresh = 8,
+ .wthresh = 4,
+ },
+ .rx_free_thresh = 0,
+};
+
+/*
+ * These default values are optimized for use with the Intel(R) 82599 10 GbE
+ * Controller and the DPDK ixgbe PMD. Consider using other values for other
+ * network controllers and/or network drivers.
+ */
+NSTACK_STATIC const struct rte_eth_txconf tx_conf_default_ixgbe = {
+ .tx_thresh = {
+ .pthresh = 36,
+ .hthresh = 0,
+ .wthresh = 0,
+ },
+ .tx_free_thresh = 0, /* Use PMD default values */
+ .tx_rs_thresh = 0, /* Use PMD default values */
+ .txq_flags = 0,
+};
+
+/* the port configuration of normal port */
+NSTACK_STATIC struct rte_eth_conf port_conf_default_normal = {
+ .rxmode = {
+ .mq_mode = ETH_RSS,
+ .max_rx_pkt_len = ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ .header_split = 0,
+ .hw_ip_checksum = 1,
+ .hw_vlan_filter = 1,
+ .hw_vlan_strip = 1,
+ .jumbo_frame = 0,
+ .hw_strip_crc = 0,
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = (ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP), //rss hash key
+ },
+ },
+ .txmode = {
+ .mq_mode = ETH_DCB_NONE,
+ },
+ .intr_conf = {
+ .lsc = 0,
+ },
+};
+
+/* the port configuration of virtio port */
+NSTACK_STATIC struct rte_eth_conf port_conf_default_virtio = {
+ .rxmode = {
+ .mq_mode = ETH_RSS,
+ .max_rx_pkt_len = ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ .header_split = 0,
+ .hw_ip_checksum = 0, /* Virtio NIC doesn't support HW IP CheckSUM */
+ .hw_vlan_filter = 1,
+ .hw_vlan_strip = 1,
+ .jumbo_frame = 0,
+ .hw_strip_crc = 0,
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = (ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP), //rss hash key
+ },
+ },
+ .txmode = {
+ .mq_mode = ETH_DCB_NONE,
+ },
+ .intr_conf = {
+ .lsc = 0,
+ },
+};
+
+/* the port configuration of bond port */
+NSTACK_STATIC struct rte_eth_conf port_conf_default_bond = {
+ .rxmode = {
+ .mq_mode = ETH_MQ_RX_NONE,
+ .max_rx_pkt_len = ETHER_MAX_LEN,
+ .split_hdr_size = 0,
+ .header_split = 0,
+ /**< Header Split disabled */
+ .hw_ip_checksum = 0,
+ /**< IP checksum offload enabled */
+ .hw_vlan_filter = 1,
+ /**< VLAN filtering enabled */
+ .hw_vlan_strip = 1,
+ .jumbo_frame = 0,
+ /**< Jumbo Frame Support disabled */
+ .hw_strip_crc = 0,
+ /**< CRC stripped by hardware */
+ },
+ .rx_adv_conf = {
+ .rss_conf = {
+ .rss_key = NULL,
+ .rss_hf = ETH_RSS_IP,
+ },
+ },
+ .txmode = {
+ .mq_mode = ETH_MQ_TX_NONE,
+ },
+};
+
+/*****************************************************************************
+* Prototype : hal_rte_eth_rx_burst
+* Description : a copy of rte_eth_rx_burst, because this function invokes
+ a global(rte_eth_devices), which cannt be access by dlsym
+ symbols
+* Input : uint8_t port_id
+* uint16_t queue_id
+* struct rte_mbuf **rx_pkts
+* const uint16_t nb_pkts
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC inline uint16_t
+hal_rte_eth_rx_burst (uint8_t port_id, uint16_t queue_id,
+ struct rte_mbuf **rx_pkts, const uint16_t nb_pkts)
+{
+#ifdef RTE_ETHDEV_RXTX_CALLBACKS
+ struct rte_eth_rxtx_callback *cb;
+#endif
+ int16_t nb_rx;
+
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+
+ if (NULL == dev->rx_pkt_burst)
+ {
+ NSHAL_LOGERR ("dev->rx_pkt_burst is NULL,dev=%p", dev);
+ return 0;
+ }
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ RTE_ETH_VALID_PORTID_OR_ERR_RET (port_id, 0);
+ RTE_FUNC_PTR_OR_ERR_RET (*dev->rx_pkt_burst, 0);
+
+ if (queue_id >= dev->data->nb_rx_queues)
+ {
+ RTE_PMD_DEBUG_TRACE ("Invalid RX queue_id=%d\n", queue_id);
+ return 0;
+ }
+#endif
+ nb_rx = (*dev->rx_pkt_burst) (dev->data->rx_queues[queue_id],
+ rx_pkts, nb_pkts);
+
+#ifdef RTE_ETHDEV_RXTX_CALLBACKS
+ cb = dev->post_rx_burst_cbs[queue_id];
+
+ if (unlikely (cb != NULL))
+ {
+ do
+ {
+ nb_rx = cb->fn.rx (port_id, queue_id, rx_pkts, nb_rx,
+ nb_pkts, cb->param);
+ cb = cb->next;
+ }
+ while (cb != NULL);
+ }
+#endif
+
+ return (uint16_t) nb_rx;
+}
+
+/*****************************************************************************
+* Prototype : hal_rte_eth_tx_burst
+* Description : a copy of rte_eth_tx_burst, because this function invokes
+
+* Input : uint8_t port_id
+* uint16_t queue_id
+* struct rte_mbuf **tx_pkts
+* uint16_t nb_pkts
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC inline uint16_t
+hal_rte_eth_tx_burst (uint8_t port_id, uint16_t queue_id,
+ struct rte_mbuf ** tx_pkts, uint16_t nb_pkts)
+{
+#ifdef RTE_ETHDEV_RXTX_CALLBACKS
+ struct rte_eth_rxtx_callback *cb;
+#endif
+
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+
+ if (NULL == dev->tx_pkt_burst)
+ {
+ NSHAL_LOGERR ("dev->tx_pkt_burst is NULL");
+ return 0;
+ }
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ RTE_ETH_VALID_PORTID_OR_ERR_RET (port_id, 0);
+ RTE_FUNC_PTR_OR_ERR_RET (*dev->tx_pkt_burst, 0);
+
+ if (queue_id >= dev->data->nb_tx_queues)
+ {
+ RTE_PMD_DEBUG_TRACE ("Invalid TX queue_id=%d\n", queue_id);
+ return 0;
+ }
+#endif
+
+#ifdef RTE_ETHDEV_RXTX_CALLBACKS
+ cb = dev->pre_tx_burst_cbs[queue_id];
+
+ if (unlikely (cb != NULL))
+ {
+ do
+ {
+ nb_pkts = cb->fn.tx (port_id, queue_id, tx_pkts, nb_pkts,
+ cb->param);
+ cb = cb->next;
+ }
+ while (cb != NULL);
+ }
+#endif
+
+ return (*dev->tx_pkt_burst) (dev->data->tx_queues[queue_id], tx_pkts,
+ nb_pkts);
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_hugepage_size
+ Description : get the free hugepage size
+ Input : the dir of the nstack hugepage
+ Output : free hugepage size
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+int
+dpdk_read_hugepage_size (int *freehuge)
+{
+ int fd_huge;
+ int len;
+ char buf[5] = { '\0' };
+ fd_huge =
+ open ("/sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages",
+ O_RDONLY);
+ if (fd_huge < 0)
+ {
+ NSHAL_LOGERR ("errno=%d", errno);
+ return -1;
+ }
+
+ len = read (fd_huge, buf, sizeof (buf));
+ if (len < 0)
+ {
+ NSHAL_LOGERR ("errno=%d", errno);
+ close (fd_huge); //fix codeDEX 124547
+ return -1;
+ }
+ *freehuge = buf[0] - '0';
+ NSHAL_LOGINF ("hugepage size=%d", *freehuge);
+ close (fd_huge);
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_clear_hugedir
+ Description : clear the hugepage which is used by dpdk
+ Input : the dir of the nstack hugepage
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_clear_hugedir (const char *hugedir)
+{
+ DIR *dir;
+ struct dirent *dirent_dpdk;
+ int dir_fd, fd, lck_result, lk_result;
+ const char filter[] = "*mapns*"; /* matches hugepage files */
+
+ /* open directory */
+ dir = opendir (hugedir);
+ if (!dir)
+ {
+ NSHAL_LOGERR ("the path %s is not exist, errno = %d", hugedir, errno);
+ goto error;
+ }
+ dir_fd = dirfd (dir);
+
+ dirent_dpdk = readdir (dir);
+ if (!dirent_dpdk)
+ {
+ NSHAL_LOGERR ("the dir %s can not read, errno = %d", hugedir, errno);
+ goto error;
+ }
+
+ while (dirent_dpdk != NULL)
+ {
+ /* skip files that don't match the hugepage pattern */
+ if (fnmatch (filter, dirent_dpdk->d_name, 0) > 0)
+ {
+ NSHAL_LOGWAR ("the file name %s is not match mapns, errno = %d",
+ dirent_dpdk->d_name, errno);
+ dirent_dpdk = readdir (dir);
+ continue;
+ }
+
+ /* try and lock the file */
+ fd = openat (dir_fd, dirent_dpdk->d_name, O_RDONLY);
+
+ /* skip to next file */
+ if (fd == -1)
+ {
+ NSHAL_LOGERR ("the file name %s can not be lock, errno = %d",
+ dirent_dpdk->d_name, errno);
+ dirent_dpdk = readdir (dir);
+ continue;
+ }
+
+ /* non-blocking lock */
+ lck_result = flock (fd, LOCK_EX | LOCK_NB);
+
+ /* if lock succeeds, unlock and remove the file */
+ if (lck_result != -1)
+ {
+ NSHAL_LOGWAR
+ ("the file name %s can be lock and will delete, errno = %d",
+ dirent_dpdk->d_name, errno);
+ lck_result = flock (fd, LOCK_UN);
+ if (-1 == lck_result)
+ NSHAL_LOGERR ("the file name %s unlock fail, errno = %d",
+ dirent_dpdk->d_name, errno);
+ lk_result = unlinkat (dir_fd, dirent_dpdk->d_name, 0);
+ if (-1 == lk_result)
+ NSHAL_LOGERR ("the file name %s is unlinkat fail, errno = %d",
+ dirent_dpdk->d_name, errno);
+ }
+ close (fd);
+ dirent_dpdk = readdir (dir);
+ }
+
+ (void) closedir (dir);
+ return 0;
+
+error:
+ if (dir)
+ (void) closedir (dir);
+
+ return -1;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_init_global
+ Description : DPDK global init
+ Input : int argc
+ char** argv
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_init_global (int argc, char **argv)
+{
+ //int ret;
+ const char hugepath[] = "/mnt/nstackhuge";
+ //int freeHuge = 0;
+ //int retryCount = 10;
+
+ if (-1 == dpdk_clear_hugedir (hugepath))
+ {
+ NSHAL_LOGERR ("clear hugedir fail, try again!");
+ sys_sleep_ns (0, 100000000);
+ (void) dpdk_clear_hugedir (hugepath);
+ }
+ NSHAL_LOGINF ("init global succ");
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_init_env
+ Description : init dpdk run env
+ Input : void
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_init_env (void)
+{
+ int ret;
+ size_t len_size;
+ char *dpdk_env;
+ char *dpdk_path;
+
+ /* Get dpdk_tool_path */
+ dpdk_env = getenv (DPDK_TOOL_ENV);
+ if (NULL == dpdk_env)
+ {
+ NSHAL_LOGERR ("please set enviroment:%s before start this stack"
+ "\nthe value of the %s must be the path of dpdk tools",
+ DPDK_TOOL_ENV, DPDK_TOOL_ENV);
+ return -1;
+ }
+
+ /* modify ugly len_size judgement and strcpy */
+ /* check len_size for malloc */
+ len_size = strlen (dpdk_env);
+ if (0 == len_size || len_size >= HAL_MAX_PATH_LEN)
+ {
+ NSHAL_LOGERR ("fail to dpdk_env strlen(DPDK_TOOL_ENV)");
+ return -1;
+ }
+
+ /* DPDK_TOOL_ENV's value will be use as popen's paramter,we need check's validity */
+ dpdk_path = realpath (dpdk_env, NULL);
+ if (NULL == dpdk_path)
+ {
+ NSHAL_LOGERR ("env:%s value incorrect]value=%s,errno=%d", DPDK_TOOL_ENV,
+ dpdk_env, errno);
+ return -1;
+ }
+
+ len_size = strlen (dpdk_path);
+ if (0 == len_size || len_size >= HAL_MAX_PATH_LEN)
+ {
+ NSHAL_LOGERR ("fail to dpdk_path strlen(DPDK_TOOL_ENV)");
+ return -1;
+ }
+
+ ret = STRCPY_S (dpdk_tool_path, HAL_MAX_PATH_LEN, dpdk_path);
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("STRCPY_S failed]ret=%d", ret);
+ return -1;
+ }
+
+ if (!hal_is_script_valid (dpdk_tool_path))
+ {
+ NSHAL_LOGERR ("dpdk_tool_path is invalid]dpdk_tool_path=%s",
+ dpdk_tool_path);
+ return -1;
+ }
+
+ /* get non-root user's id */
+ dpdk_non_root_user = getpwnam (DPDK_NON_ROOT_USER_NAME);
+ if (dpdk_non_root_user)
+ {
+ NSHAL_LOGINF ("non-root]name=%s,uid=%u,gid=%u,errno=%d",
+ dpdk_non_root_user->pw_name, dpdk_non_root_user->pw_uid,
+ dpdk_non_root_user->pw_gid, errno);
+ }
+ else
+ {
+ NSHAL_LOGERR ("non-root]cannot find user %s", DPDK_NON_ROOT_USER_NAME);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_init_local
+ Description : DPDK local init
+ Input : void
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_init_local (void)
+{
+ int ret;
+
+ ret = dpdk_init_env ();
+
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("dpdk_init_env failed");
+ return -1;
+ }
+
+ NSHAL_LOGINF ("init local succ");
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_set_port
+ Description : check and save the port num
+ Input : netif_inst_t* inst
+ int port
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_set_port (netif_inst_t * inst, uint8_t port)
+{
+ if (port >= rte_eth_dev_count ())
+ {
+ NSHAL_LOGERR ("the number of port=%d is more than rte_eth_dev_count=%d",
+ port, rte_eth_dev_count ());
+ return -1;
+ }
+
+ inst->data.dpdk_if.port_id = port;
+
+ return 0;
+
+}
+
+/*****************************************************************************
+ Prototype : dpdk_set_nic_name
+ Description : check and save nic name
+ Input : netif_inst_t* inst
+ const char* name
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_set_nic_name (netif_inst_t * inst, const char *name)
+{
+ int ret;
+
+ /* sizeof(pointer) always = 8 in 64 bit system */
+ ret =
+ STRCPY_S (inst->data.dpdk_if.nic_name,
+ sizeof (inst->data.dpdk_if.nic_name), name);
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("STRCPY_S set nic_name failed]ret=%d", ret);
+ return -1;
+ }
+
+ if (!hal_is_script_valid (inst->data.dpdk_if.nic_name))
+ {
+ NSHAL_LOGERR ("nic_name is invalid");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_driver_name
+ Description : get and save driver name
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_get_driver_name (netif_inst_t * inst)
+{
+ int ret_len, ret;
+ char script_cmmd[HAL_SCRIPT_LENGTH];
+ char driver_name[HAL_SCRIPT_LENGTH] = { 0 };
+
+ ret = hal_snprintf (script_cmmd, sizeof (script_cmmd),
+ "readlink -f /sys/class/net/" "%s"
+ "/device/driver| awk -F'/' '{print $6}'",
+ inst->data.dpdk_if.nic_name);
+ if (-1 == ret)
+ {
+ NSHAL_LOGERR ("hal_snprintf failed");
+ return -1;
+ }
+
+ ret_len =
+ hal_run_script (script_cmmd, driver_name, sizeof (driver_name) - 1);
+
+ if (ret_len > HAL_MAX_DRIVER_NAME_LEN)
+ {
+ ret_len = HAL_MAX_DRIVER_NAME_LEN;
+ }
+
+ if (ret_len <= 0)
+ {
+ NSHAL_LOGERR ("%s does't have a driver", driver_name);
+
+ ret =
+ STRNCPY_S (inst->data.dpdk_if.driver_name,
+ sizeof (inst->data.dpdk_if.driver_name), "NULL",
+ sizeof ("NULL"));
+
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("STRNCPY_S failed]ret=%d.", ret);
+ return -1;
+ }
+
+ return -1;
+ }
+ else
+ {
+ ret =
+ STRNCPY_S (inst->data.dpdk_if.driver_name,
+ sizeof (inst->data.dpdk_if.driver_name), driver_name,
+ ret_len);
+
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("STRNCPY_S failed]ret=%d.", ret);
+ return -1;
+ }
+
+ inst->data.dpdk_if.driver_name[(ret_len - 1)] = '\0';
+
+ return 0;
+ }
+}
+
+/*****************************************************************************
+ Prototype : dpdk_set_pci_permission
+ Description : set pci permission
+ Input : char *pci_addr
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_set_pci_permission (char *pci_addr)
+{
+ DIR *dir_desc;
+ char file_path[HAL_SCRIPT_LENGTH] = { 0 }, dir_path[HAL_SCRIPT_LENGTH] =
+ {
+ 0};
+ struct dirent *ent;
+ struct stat statbuf;
+ int ret;
+
+ ret =
+ SNPRINTF_S (dir_path, sizeof (dir_path), sizeof (dir_path) - 1,
+ "/sys/bus/pci/devices/%s", pci_addr);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("SNPRINTF_S fail");
+ return -1;
+ }
+
+ if ((dir_desc = opendir (dir_path)) == NULL)
+ {
+ NSHAL_LOGERR ("opendir fail:errno=%d", errno);
+ return -1;
+ }
+
+ while ((ent = readdir (dir_desc)) != NULL)
+ {
+ if (strstr (ent->d_name, "resource"))
+ {
+ ret =
+ SNPRINTF_S (file_path, sizeof (file_path), sizeof (file_path) - 1,
+ "%s/%s", dir_path, ent->d_name);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("SNPRINTF_S fail");
+ (void) closedir (dir_desc);
+ return -1;
+ }
+
+ if (!lstat (file_path, &statbuf) && !S_ISDIR (statbuf.st_mode))
+ {
+ ret =
+ chown (file_path, dpdk_non_root_user->pw_uid,
+ dpdk_non_root_user->pw_gid);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("chown fail]file_path=%s,ret=%d,errno=%d",
+ file_path, ret, errno);
+ (void) closedir (dir_desc);
+ return -1;
+ }
+ NSHAL_LOGWAR ("chown succ]file_path=%s,ret=%d", file_path, ret);
+ ret = chmod (file_path, 0640);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("chmod fail]file_path=%s,ret=%d,errno=%d",
+ file_path, ret, errno);
+ (void) closedir (dir_desc);
+ return -1;
+ }
+ NSHAL_LOGWAR ("chmod succ]file_path=%s,ret=%d", file_path, ret);
+ }
+ }
+ }
+
+ (void) closedir (dir_desc);
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_pci_addr
+ Description : get and save pci addr
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_get_pci_addr (netif_inst_t * inst)
+{
+ int ret, pci_len;
+ struct ethtool_drvinfo edata = { 0 };
+ struct ifreq ifr;
+ int fd = -1;
+
+ /* use ioctl to get pci address instead of call dpdk-devbind.py to reduce time cost */
+ ret = MEMSET_S (&ifr, sizeof (ifr), 0, sizeof (ifr));
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("MEMSET_S fail");
+ return -1;
+ }
+ edata.cmd = ETHTOOL_GDRVINFO;
+ ret =
+ STRCPY_S (ifr.ifr_name, sizeof (ifr.ifr_name),
+ inst->data.dpdk_if.nic_name);
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("STRCPY_S fail");
+ return -1;
+ }
+
+ ifr.ifr_data = (char *) (&edata);
+ if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ NSHAL_LOGERR ("cannot init socket, errno=%d", errno);
+ return -1;
+ }
+ if (ioctl (fd, SIOCETHTOOL, &ifr) < 0)
+ {
+ NSHAL_LOGERR ("ioctl to the device %s err, errno=%d",
+ inst->data.dpdk_if.nic_name, errno);
+ close (fd);
+ return -1;
+ }
+ close (fd);
+
+ pci_len = strlen (edata.bus_info);
+ if (pci_len == 0
+ || pci_len > (int) sizeof (inst->data.dpdk_if.pci_addr) - 1)
+ {
+ NSHAL_LOGERR ("does't have a pci_addr");
+ inst->data.dpdk_if.pci_addr[0] = '\0';
+ return -1;
+ }
+
+ NSHAL_LOGINF ("nic_name=%s,nic_pci_addr=%s", inst->data.dpdk_if.nic_name,
+ edata.bus_info);
+
+ ret =
+ STRNCPY_S (inst->data.dpdk_if.pci_addr,
+ sizeof (inst->data.dpdk_if.pci_addr), edata.bus_info, pci_len);
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("STRNCPY_S failed]ret=%d.", ret);
+ return -1;
+ }
+
+ if (!hal_is_script_valid (inst->data.dpdk_if.pci_addr))
+ {
+ NSHAL_LOGERR ("pci_addr is invalid]pci_addr=%s",
+ inst->data.dpdk_if.pci_addr);
+ return -1;
+ }
+
+ if (dpdk_non_root_user && getuid ())
+ {
+ ret = dpdk_set_pci_permission (inst->data.dpdk_if.pci_addr);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("dpdk_set_pci_permission fail");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_mlx_linkup
+ Description : linkup the port for mlx
+ In bonding mode, mlx4 NICs should be set up manually,
+ in order to make bond port up
+ Input : char* name
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_mlx_linkup (char *name)
+{
+ struct ifreq st_ifreq;
+ int sock;
+ int retVal;
+
+ if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ NSHAL_LOGERR ("socket fail]errno=%d", errno);
+ return 2;
+ }
+
+ retVal = STRCPY_S (st_ifreq.ifr_name, sizeof (st_ifreq.ifr_name), name);
+
+ if (EOK != retVal)
+ {
+ NSHAL_LOGERR ("STRCPY_S fail]");
+ close (sock);
+ return 1;
+ }
+
+ if (ioctl (sock, (uint64_t) SIOCGIFFLAGS, &st_ifreq) < 0)
+ {
+ NSHAL_LOGERR ("ioctl SIOCGIFFLAGS fail]errno=%d", errno);
+ close (sock);
+ return 3;
+ }
+
+ st_ifreq.ifr_flags |= IFF_UP;
+ st_ifreq.ifr_flags |= IFF_RUNNING;
+
+ if (ioctl (sock, (uint64_t) SIOCSIFFLAGS, &st_ifreq) < 0)
+ {
+ NSHAL_LOGERR ("ioctl SIOCSIFFLAGS fail]errno=%d", errno);
+ close (sock);
+ return 3;
+ }
+
+ close (sock);
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_nonmlx_linkdown
+ Description : linkdown the port for nonmlx
+ Input : char* name
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_nonmlx_linkdown (char *name)
+{
+ int ret, ret_len;
+ char script_cmmd[HAL_SCRIPT_LENGTH];
+ char result_buf[HAL_SCRIPT_LENGTH];
+
+ ret =
+ hal_snprintf (script_cmmd, sizeof (script_cmmd), "sudo ifconfig %s down",
+ name);
+ if (-1 == ret)
+ {
+ NSHAL_LOGERR ("spl_snprintf failed]");
+ return -1;
+ }
+
+ ret_len = hal_run_script (script_cmmd, result_buf, sizeof (result_buf));
+ NSHAL_LOGINF ("ifconfig]script_cmmd=%s,ret_len=%d", script_cmmd, ret_len);
+ if (0 > ret_len)
+ {
+ NSHAL_LOGERR ("cannot able to ifconfig %s down", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_uio_by_pci_addr
+ Description : get uio
+ Input : char *pci_addr
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_get_uio_by_pci_addr (char *pci_addr)
+{
+ int i, ret, ret_len;
+ char script_cmmd[HAL_SCRIPT_LENGTH];
+ char result_buf[HAL_SCRIPT_LENGTH];
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++)
+ {
+ ret = hal_snprintf (script_cmmd, sizeof (script_cmmd),
+ "readlink ls /sys/class/uio/uio%d/device | awk -F '/' '{print $4}'",
+ i);
+ if (-1 == ret)
+ {
+ NSHAL_LOGERR ("hal_snprintf fail]pci=%s,i=%d", pci_addr, i);
+ return -1;
+ }
+
+ ret_len = hal_run_script (script_cmmd, result_buf, sizeof (result_buf));
+ if (0 > ret_len)
+ {
+ NSHAL_LOGERR ("hal_run_script fail]pci=%s,i=%d", pci_addr, i);
+ return -1;
+ }
+ if (strcmp (result_buf, pci_addr) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_set_uio_permission
+ Description : set uio permission
+ Input : char *pci_addr
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_set_uio_permission (char *pci_addr)
+{
+ int ret, uio_idx;
+ char file_path[HAL_SCRIPT_LENGTH / 2] = { 0 };
+
+ /* get /dev/uio by pci addr */
+ uio_idx = dpdk_get_uio_by_pci_addr (pci_addr);
+ if (uio_idx < 0)
+ {
+ NSHAL_LOGERR ("dpdk_get_uio_by_pci_addr fail]pci_addr=%s", pci_addr);
+ return -1;
+ }
+
+ NSHAL_LOGINF ("uio_idx]pci=%s,uio%d", pci_addr, uio_idx);
+
+ /* change /dev/uio%u permission */
+ if (SNPRINTF_S
+ (file_path, sizeof (file_path), sizeof (file_path) - 1, "/dev/uio%d",
+ uio_idx) < 0)
+ {
+ NSHAL_LOGERR ("SNPRINTF_S failed]uio%d", uio_idx);
+ return -1;
+ }
+ sys_sleep_ns (0, 500000000);
+ ret =
+ chown (file_path, dpdk_non_root_user->pw_uid, dpdk_non_root_user->pw_gid);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("chown fail]file_path=%s,ret=%d,errno=%d", file_path, ret,
+ errno);
+ return -1;
+ }
+ NSHAL_LOGWAR ("chown succ]file_path=%s,ret=%d", file_path, ret);
+
+ ret = chmod (file_path, 0640);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("chmod fail]file_path=%s,ret=%d,errno=%d", file_path, ret,
+ errno);
+ return -1;
+ }
+ NSHAL_LOGWAR ("chmod succ]file_path=%s,ret=%d", file_path, ret);
+
+ /* change /sys/class/uio/uio%u/device/config permission */
+ if (SNPRINTF_S
+ (file_path, sizeof (file_path), sizeof (file_path) - 1,
+ "/sys/class/uio/uio%d/device/config", uio_idx) < 0)
+ {
+ NSHAL_LOGERR ("SNPRINTF_S failed]uio%d", uio_idx);
+ return -1;
+ }
+
+ ret =
+ chown (file_path, dpdk_non_root_user->pw_uid, dpdk_non_root_user->pw_gid);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("chown fail]file_path=%s,ret=%d,errno=%d", file_path, ret,
+ errno);
+ return -1;
+ }
+ NSHAL_LOGWAR ("chown succ]file_path=%s,ret=%d", file_path, ret);
+
+ ret = chmod (file_path, 0640);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("chmod fail]file_path=%s,ret=%d,errno=%d", file_path, ret,
+ errno);
+ return -1;
+ }
+ NSHAL_LOGWAR ("chmod succ]file_path=%s,ret=%d", file_path, ret);
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_nic_list_file
+ Description : get dpdk bind nic list file
+ Input : void
+ Output : char*
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC char *
+dpdk_get_nic_list_file (void)
+{
+ int ret;
+ static char buffer[HAL_MAX_PATH_LEN]; /* static so auto-zeroed */
+ const char *directory = "/var/run";
+ const char *home_dir = getenv ("HOME");
+
+ if (getuid () != 0 && home_dir != NULL)
+ directory = home_dir;
+
+ ret =
+ SNPRINTF_S (buffer, sizeof (buffer), sizeof (buffer) - 1,
+ DPDK_NIC_LIST_FILE, directory);
+ if (-1 == ret)
+ {
+ NSCOMM_LOGERR ("SNPRINTF_S failed]ret=%d", ret);
+ return NULL;
+ }
+
+ return buffer;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_bind_uio
+ Description : bind uio
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_bind_uio (netif_inst_t * inst)
+{
+ char script_cmmd[HAL_SCRIPT_LENGTH];
+ char result_buf[HAL_SCRIPT_LENGTH];
+ int ret, ret_len;
+
+ result_buf[0] = '\0';
+
+ if (strncmp ("mlx4_co", inst->data.dpdk_if.driver_name, (size_t) 7) == 0)
+ {
+ /*For MLX4: NIC should be set link up before rte_eth_dev_start() is called. */
+ ret = dpdk_mlx_linkup (inst->data.dpdk_if.nic_name);
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("set mlx linkup fail]nic_name=%s,ret=%d",
+ inst->data.dpdk_if.nic_name, ret);
+
+ return -1;
+ }
+ }
+ else
+ {
+ /*For other drivers: NIC should be set link down before bind uio. */
+ ret = dpdk_nonmlx_linkdown (inst->data.dpdk_if.nic_name);
+ if (-1 == ret)
+ {
+ NSHAL_LOGERR ("dpdk_nonmlx_linkdown fail]nic_name=%s",
+ inst->data.dpdk_if.nic_name);
+ return -1;
+ }
+
+ /* save binded VF list to file /var/run/ip_module/.nstack_dpdk_nic_list */
+ ret = hal_snprintf (script_cmmd, sizeof (script_cmmd),
+ "sudo %s"
+ "/dpdk-devbind.py -s | grep `ethtool -i %s| grep bus-info |awk '{print $2}'` >> %s 2>&1",
+ dpdk_tool_path, inst->data.dpdk_if.nic_name,
+ dpdk_get_nic_list_file ());
+
+ if (-1 == ret)
+ {
+ NSHAL_LOGERR ("hal_snprintf fail]nic_name=%s",
+ inst->data.dpdk_if.nic_name);
+ return -1;
+ }
+
+ ret_len =
+ hal_run_script (script_cmmd, result_buf, sizeof (result_buf) - 1);
+ NSHAL_LOGINF ("bind]script_cmmd=%s,ret_len=%d", script_cmmd, ret_len);
+ if (0 > ret_len)
+ {
+ NSHAL_LOGERR ("hal_run_script fail]script_cmmd=%s", script_cmmd);
+ return -1;
+ }
+
+ if (strncmp ("virtio", inst->data.dpdk_if.driver_name, (size_t) 6) == 0)
+ {
+ /* For Virtio NIC, should call "./devbind.sh ethX" to bind the VF */
+ ret = hal_snprintf (script_cmmd, sizeof (script_cmmd),
+ "sudo %s"
+ "/dpdk-devbind.py --bind=igb_uio `ethtool -i %s| grep bus-info |awk '{print $2}'`",
+ dpdk_tool_path, inst->data.dpdk_if.nic_name);
+ //"sudo %s" "/devbind.sh " "%s", dpdk_tool_path, inst->data.dpdk_if.nic_name);
+
+ }
+ else
+ {
+ ret = hal_snprintf (script_cmmd, sizeof (script_cmmd),
+ "sudo %s" "/dpdk-devbind.py --bind=igb_uio "
+ "%s", dpdk_tool_path,
+ inst->data.dpdk_if.nic_name);
+ }
+
+ if (-1 == ret)
+ {
+ NSHAL_LOGERR ("hal_snprintf failed");
+ return -1;
+ }
+
+ ret_len =
+ hal_run_script (script_cmmd, result_buf, sizeof (result_buf) - 1);
+ NSHAL_LOGINF ("bind]script_cmmd=%s,retlen=%d", script_cmmd, ret_len);
+ if (0 > ret_len)
+ {
+ NSHAL_LOGERR ("hal_run_script fail]script_cmmd=%s", script_cmmd);
+ return -1;
+ }
+
+ if (dpdk_non_root_user && getuid ())
+ {
+ ret = dpdk_set_uio_permission (inst->data.dpdk_if.pci_addr);
+
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("set_uio_permission fail]nic_name=%s",
+ inst->data.dpdk_if.nic_name);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_probe_pci
+ Description : probe pci
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_probe_pci (netif_inst_t * inst)
+{
+ int ret;
+ uint16_t port_id;
+ struct rte_eth_dev *eth_dev;
+ char *pci_addr = inst->data.dpdk_if.pci_addr;
+
+ ret = rte_eal_iopl_init ();
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("rte_eal_iopl_init fail]pci_addr=%s,ret=%d", pci_addr,
+ ret);
+ return -1;
+ }
+
+ ret = rte_eth_dev_attach (pci_addr, &port_id);
+ if (0 != ret)
+ {
+ NSHAL_LOGWAR
+ ("pci attach to DPDK fail, the pci may have attached, try to get port id]pci_addr=%s,ret=%d",
+ pci_addr, ret);
+
+ eth_dev = rte_eth_dev_allocated (inst->data.dpdk_if.nic_name);
+ if (NULL != eth_dev && NULL != eth_dev->data)
+ {
+ port_id = eth_dev->data->port_id;
+ ret = 0;
+ }
+ }
+
+ if (!ret)
+ {
+ ret = dpdk_set_port (inst, port_id);
+
+ if (0 == ret)
+ {
+ NSHAL_LOGINF ("set port success]pci_addr=%s,port_id=%u", pci_addr,
+ port_id);
+ }
+ else
+ {
+ NSHAL_LOGERR ("set port fail]pci_addr=%s,port_id=%u", pci_addr,
+ port_id);
+ return -1;
+ }
+ }
+ else
+ {
+ NSHAL_LOGERR ("get port fail]pci_addr=%s,ret=%d", pci_addr, ret);
+ return -1;
+ }
+
+ /*[TA33635][2017-04-24][l00408818] Start: support bond mode */
+ ret = rte_eal_devargs_add (RTE_DEVTYPE_WHITELISTED_PCI, pci_addr);
+ if (!ret)
+ {
+ NSHAL_LOGINF ("pci attach to whitelist success]pci_addr=%s", pci_addr);
+ }
+ else
+ {
+ NSHAL_LOGERR ("pci attach to whitelist fail]pci_addr=%s", pci_addr);
+ return -1;
+ }
+ /*[TA33635][2017-04-24][l00408818] End */
+
+ return 0;
+}
+
+/*nic_name->driver_name->pci_addr->get port*/
+/*****************************************************************************
+ Prototype : dpdk_open
+ Description : open the port
+ Input : netif_inst_t* inst
+ const char* name
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_open (netif_inst_t * inst, const char *name)
+{
+ int ret;
+
+ ret = dpdk_set_nic_name (inst, name);
+
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("dpdk_set_nic_name fail]nic_name=%s, ret=%d", name, ret);
+ return -1;
+ }
+
+ ret = dpdk_get_driver_name (inst);
+
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("dpdk_get_driver_name fail]nic_name=%s, ret=%d", name,
+ ret);
+ return -1;
+ }
+
+ ret = dpdk_get_pci_addr (inst);
+
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("dpdk_get_pci_addr fail]nic_name=%s, ret=%d", name, ret);
+ return -1;
+ }
+
+ ret = dpdk_bind_uio (inst);
+
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("dpdk_bind_uio fail]nic_name=%s, ret=%d", name, ret);
+ return -1;
+ }
+
+ ret = dpdk_probe_pci (inst);
+
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("dpdk_probe_pci fail]nic_name=%s, ret=%d", name, ret);
+ return -1;
+ }
+
+ NSHAL_LOGINF ("open port succ]port_id=%u, nic_name=%s",
+ inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name);
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_close
+ Description : close the port
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_close (netif_inst_t * inst)
+{
+ int i;
+
+ /* close slave NIC first */
+ for (i = 0; i < inst->data.dpdk_if.slave_num; i++)
+ {
+ rte_eth_dev_close (inst->data.dpdk_if.slave_port[i]);
+ NSHAL_LOGINF ("close slave port succ]port_id=%u, nic_name=%s",
+ inst->data.dpdk_if.slave_port[i],
+ inst->data.dpdk_if.nic_name);
+ }
+
+ rte_eth_dev_close (inst->data.dpdk_if.port_id);
+ NSHAL_LOGINF ("close port succ]port_id=%u, nic_name=%s",
+ inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name);
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_queue_conf
+ Description : get the port queue configure
+ Input : netif_inst_t* inst
+ struct rte_eth_rxconf** rx_conf
+ struct rte_eth_txconf** tx_conf
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_get_queue_conf (netif_inst_t * inst,
+ struct rte_eth_rxconf **rx_conf,
+ struct rte_eth_txconf **tx_conf)
+{
+ static struct rte_eth_dev_info slave_dev_info;
+
+ if (strncmp ("igb", inst->data.dpdk_if.driver_name, (size_t) 3) == 0)
+ {
+ *rx_conf = (struct rte_eth_rxconf *) &rx_conf_default_igb;
+ *tx_conf = (struct rte_eth_txconf *) &tx_conf_default_igb;
+ NSHAL_LOGINF ("igb config is enable]port_id=%u",
+ inst->data.dpdk_if.port_id);
+ }
+ else if (strncmp ("ixgbe", inst->data.dpdk_if.driver_name, (size_t) 5) == 0)
+ {
+ *rx_conf = (struct rte_eth_rxconf *) &rx_conf_default_ixgbe;
+ *tx_conf = (struct rte_eth_txconf *) &tx_conf_default_ixgbe;
+ NSHAL_LOGINF ("igxbe config is enable]port_id=%u",
+ inst->data.dpdk_if.port_id);
+ }
+ else if (strncmp ("bond", inst->data.dpdk_if.driver_name, (size_t) 4) == 0)
+ {
+ *rx_conf = NULL;
+ rte_eth_dev_info_get (inst->data.dpdk_if.slave_port[0],
+ &slave_dev_info);
+ *tx_conf = &(slave_dev_info.default_txconf);
+ NSHAL_LOGINF ("bond config is enable]port_id=%u",
+ inst->data.dpdk_if.port_id);
+ }
+ else
+ {
+ *rx_conf = NULL;
+ *tx_conf = NULL;
+ NSHAL_LOGINF ("default config is enable]port_id=%u",
+ inst->data.dpdk_if.port_id);
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_port_conf
+ Description : get the port configure
+ Input : netif_inst_t* inst
+ struct rte_eth_conf** port_conf
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC void
+dpdk_get_port_conf (netif_inst_t * inst, struct rte_eth_conf **port_conf)
+{
+ if (strncmp ("virtio", inst->data.dpdk_if.driver_name, (size_t) 6) == 0)
+ {
+ *port_conf = &port_conf_default_virtio;
+ }
+ else if (strncmp ("bond", inst->data.dpdk_if.driver_name, (size_t) 4) == 0)
+ {
+ *port_conf = &port_conf_default_bond;
+ }
+ else
+ {
+ *port_conf = &port_conf_default_normal;
+ }
+
+ (*port_conf)->rxmode.hw_vlan_filter = inst->data.dpdk_if.hw_vlan_filter;
+ (*port_conf)->rxmode.hw_vlan_strip = inst->data.dpdk_if.hw_vlan_strip;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_setup_port
+ Description : setup the port
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_setup_port (netif_inst_t * inst)
+{
+ int ret;
+ uint32_t i;
+ struct rte_eth_conf *port_conf;
+ struct rte_eth_rxconf *rx_conf;
+ struct rte_eth_txconf *tx_conf;
+
+ uint8_t port_id = inst->data.dpdk_if.port_id;
+ struct rte_mempool **mp = inst->data.dpdk_if.rx_pool;
+ uint32_t *rx_ring_size = inst->data.dpdk_if.rx_ring_size;
+ uint32_t *tx_ring_size = inst->data.dpdk_if.tx_ring_size;
+ uint32_t rx_queue_num = inst->data.dpdk_if.rx_queue_num;
+ uint32_t tx_queue_num = inst->data.dpdk_if.tx_queue_num;
+
+ dpdk_get_port_conf (inst, &port_conf);
+
+ ret =
+ rte_eth_dev_configure (port_id, rx_queue_num, tx_queue_num, port_conf);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("rte_eth_dev_configure]port_id=%u,ret=%d", port_id, ret);
+ return ret;
+ }
+
+ if (dpdk_get_queue_conf (inst, &rx_conf, &tx_conf) < 0)
+ {
+ NSHAL_LOGERR ("dpdk_get_queue_conf failed]inst=%p,rx_conf=%p", inst,
+ rx_conf);
+ return -1;
+ }
+ /* fix "FORTIFY.Out-of-Bounds_Read" type codedex issue CID 33436 */
+ if (rx_queue_num > HAL_ETH_MAX_QUEUE_NUM
+ || tx_queue_num > HAL_ETH_MAX_QUEUE_NUM)
+ {
+ NSHAL_LOGERR
+ ("queue num error]rx_queue_num=%u, tx_queue_num=%u, HAL_ETH_MAX_QUEUE_NUM=%d",
+ rx_queue_num, tx_queue_num, HAL_ETH_MAX_QUEUE_NUM);
+
+ return -1;
+ }
+
+ for (i = 0; i < rx_queue_num; i++)
+ {
+ ret =
+ rte_eth_rx_queue_setup (port_id, i, rx_ring_size[i], SOCKET_ID_ANY,
+ rx_conf, mp[i]);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("rx queue setup fail]index=%u,port_id=%u,ret=%d", i,
+ port_id, ret);
+ return ret;
+ }
+ }
+
+ for (i = 0; i < tx_queue_num; i++)
+ {
+ ret =
+ rte_eth_tx_queue_setup (port_id, i, tx_ring_size[i], SOCKET_ID_ANY,
+ tx_conf);
+
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("tx queue setup fail]q=%u,ret=%d", i, ret);
+ return ret;
+ }
+ }
+
+ rte_eth_promiscuous_enable (port_id);
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_start
+ Description : start the port
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_start (netif_inst_t * inst)
+{
+ int ret;
+ struct ether_addr eth_addr;
+
+ ret = dpdk_setup_port (inst);
+
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("call dpdk_setup_port fail]ret=%d", ret);
+ return ret;
+ }
+
+ ret = rte_eth_dev_start (inst->data.dpdk_if.port_id);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("rte_eth_dev_start fail]ret=%d", ret);
+ return ret;
+ }
+
+ rte_eth_macaddr_get (inst->data.dpdk_if.port_id, &eth_addr);
+ NSHAL_LOGINF ("port_id=%u,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X",
+ inst->data.dpdk_if.port_id,
+ inst->data.dpdk_if.nic_name,
+ eth_addr.addr_bytes[0],
+ eth_addr.addr_bytes[1],
+ eth_addr.addr_bytes[2],
+ eth_addr.addr_bytes[3],
+ eth_addr.addr_bytes[4], eth_addr.addr_bytes[5]);
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_stop
+ Description : stop the port
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_stop (netif_inst_t * inst)
+{
+ int i;
+
+ /* stop slave NIC first */
+ for (i = 0; i < inst->data.dpdk_if.slave_num; i++)
+ {
+ rte_eth_dev_stop (inst->data.dpdk_if.slave_port[i]);
+ NSHAL_LOGINF ("stop slave port succ]port_id=%u, nic_name=%s",
+ inst->data.dpdk_if.slave_port[i],
+ inst->data.dpdk_if.nic_name);
+ }
+ rte_eth_dev_stop (inst->data.dpdk_if.port_id);
+
+ NSHAL_LOGINF ("stop port succ]port_id=%u, nic_name=%s",
+ inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name);
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_mtu
+ Description : get the port mtu
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC uint32_t
+dpdk_get_mtu (netif_inst_t * inst)
+{
+ uint32_t mtu;
+
+ if (rte_eth_dev_get_mtu (inst->data.dpdk_if.port_id, (uint16_t *) & mtu))
+ {
+ return 0;
+ }
+
+ return mtu;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_macaddr
+ Description : get the port mac addr
+ Input : netif_inst_t* inst
+ void* mac_addr
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_get_macaddr (netif_inst_t * inst, void *mac_addr)
+{
+ /*bond port */
+ int primary_port = rte_eth_bond_primary_get (inst->data.dpdk_if.port_id);
+ if (0 <= primary_port)
+ {
+ rte_eth_macaddr_get ((uint8_t) primary_port,
+ (struct ether_addr *) mac_addr);
+
+ NSHAL_LOGDBG
+ ("primary_port_id=%u,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X",
+ primary_port, inst->data.dpdk_if.nic_name,
+ ((struct ether_addr *) mac_addr)->addr_bytes[0],
+ ((struct ether_addr *) mac_addr)->addr_bytes[1],
+ ((struct ether_addr *) mac_addr)->addr_bytes[2],
+ ((struct ether_addr *) mac_addr)->addr_bytes[3],
+ ((struct ether_addr *) mac_addr)->addr_bytes[4],
+ ((struct ether_addr *) mac_addr)->addr_bytes[5]);
+ }
+ /*normal port */
+ else
+ {
+ rte_eth_macaddr_get (inst->data.dpdk_if.port_id,
+ (struct ether_addr *) mac_addr);
+
+ NSHAL_LOGDBG
+ ("normal_port_id=%u,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X",
+ inst->data.dpdk_if.port_id, inst->data.dpdk_if.nic_name,
+ ((struct ether_addr *) mac_addr)->addr_bytes[0],
+ ((struct ether_addr *) mac_addr)->addr_bytes[1],
+ ((struct ether_addr *) mac_addr)->addr_bytes[2],
+ ((struct ether_addr *) mac_addr)->addr_bytes[3],
+ ((struct ether_addr *) mac_addr)->addr_bytes[4],
+ ((struct ether_addr *) mac_addr)->addr_bytes[5]);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_capa_convert
+ Description : convert format from dpdk to hal
+ Input : const struct rte_eth_dev_info* dev_info
+ hal_netif_capa_t* capa
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC inline void
+dpdk_capa_convert (const struct rte_eth_dev_info *dev_info,
+ hal_netif_capa_t * capa)
+{
+ int retVal =
+ MEMSET_S (capa, sizeof (hal_netif_capa_t), 0, sizeof (hal_netif_capa_t));
+ if (EOK != retVal)
+ {
+ NSHAL_LOGERR ("MEMSET_S fail]retVal=%d", retVal);
+ }
+
+ capa->tx_offload_capa = dev_info->tx_offload_capa;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_get_capability
+ Description : get the port capability
+ Input : netif_inst_t* inst
+ hal_netif_capa_t* capa
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_get_capability (netif_inst_t * inst, hal_netif_capa_t * capa)
+{
+ struct rte_eth_dev_info dev_info;
+
+ rte_eth_dev_info_get (inst->data.dpdk_if.port_id, &dev_info);
+ dpdk_capa_convert (&dev_info, capa);
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_recv
+ Description : recv packet from the port
+ Input : netif_inst_t* inst
+ uint16_t queue_id
+ struct common_mem_mbuf** rx_pkts
+ uint16_t nb_pkts
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC uint16_t
+dpdk_recv (netif_inst_t * inst, uint16_t queue_id,
+ struct common_mem_mbuf ** rx_pkts, uint16_t nb_pkts)
+{
+ return hal_rte_eth_rx_burst (inst->data.dpdk_if.port_id, queue_id,
+ (struct rte_mbuf **) rx_pkts, nb_pkts);
+}
+
+/*****************************************************************************
+ Prototype : dpdk_send
+ Description : send packet to the port
+ Input : netif_inst_t* inst
+ uint16_t queue_id
+ struct common_mem_mbuf** tx_pkts
+ uint16_t nb_pkts
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC uint16_t
+dpdk_send (netif_inst_t * inst, uint16_t queue_id,
+ struct common_mem_mbuf **tx_pkts, uint16_t nb_pkts)
+{
+ return hal_rte_eth_tx_burst (inst->data.dpdk_if.port_id, queue_id,
+ (struct rte_mbuf **) tx_pkts, nb_pkts);
+}
+
+/*****************************************************************************
+ Prototype : dpdk_link_status
+ Description : get link status form the port
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC uint32_t
+dpdk_link_status (netif_inst_t * inst)
+{
+ struct rte_eth_link eth_link;
+
+ /* add log output when failed */
+ int retVal = MEMSET_S (&eth_link, sizeof (struct rte_eth_link), 0,
+ sizeof (struct rte_eth_link));
+ if (EOK != retVal)
+ {
+ NSHAL_LOGERR ("MEMSET_S fail]retVal=%d", retVal);
+ }
+
+ rte_eth_link_get (inst->data.dpdk_if.port_id, &eth_link);
+
+ return eth_link.link_status;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_stats_convert
+ Description : convert format from dpdk to hal
+ Input : const struct rte_eth_stats* rte_stats
+ hal_netif_stats_t* stats
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC inline void
+dpdk_stats_convert (const struct rte_eth_stats *rte_stats,
+ hal_netif_stats_t * stats)
+{
+ int i;
+
+ /* give fail error number when failed */
+ int retVal = MEMSET_S (stats, sizeof (hal_netif_stats_t), 0,
+ sizeof (hal_netif_stats_t));
+ if (EOK != retVal)
+ {
+ NSHAL_LOGERR ("MEMSET_S fail]retVal=%d", retVal);
+ }
+
+ stats->ipackets = rte_stats->ipackets;
+ stats->opackets = rte_stats->opackets;
+ stats->ibytes = rte_stats->ibytes;
+ stats->obytes = rte_stats->obytes;
+ stats->imissed = rte_stats->imissed;
+ stats->ierrors = rte_stats->ierrors;
+ stats->oerrors = rte_stats->oerrors;
+ stats->rx_nombuf = rte_stats->rx_nombuf;
+
+ for (i = 0; i < HAL_ETH_QUEUE_STAT_CNTRS; i++)
+ {
+ stats->q_ipackets[i] = rte_stats->q_ipackets[i];
+ stats->q_opackets[i] = rte_stats->q_opackets[i];
+ stats->q_ibytes[i] = rte_stats->q_ibytes[i];
+ stats->q_obytes[i] = rte_stats->q_obytes[i];
+ stats->q_errors[i] = rte_stats->q_errors[i];
+ }
+}
+
+/*****************************************************************************
+ Prototype : dpdk_stats
+ Description : get stats form the port
+ Input : netif_inst_t* inst
+ hal_netif_stats_t* stats
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_stats (netif_inst_t * inst, hal_netif_stats_t * stats)
+{
+ int ret;
+ struct rte_eth_stats rte_stats;
+
+ ret = rte_eth_stats_get (inst->data.dpdk_if.port_id, &rte_stats);
+ if (ret == 0)
+ {
+ dpdk_stats_convert (&rte_stats, stats);
+ return 0;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_stats_reset
+ Description : reset stats to the port
+ Input : netif_inst_t* inst
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_stats_reset (netif_inst_t * inst)
+{
+ rte_eth_stats_reset (inst->data.dpdk_if.port_id);
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_config
+ Description : config the port queue and ring
+ Input : netif_inst_t* inst
+ hal_netif_config_t* conf
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_config (netif_inst_t * inst, hal_netif_config_t * conf)
+{
+ uint32_t i;
+
+ inst->data.dpdk_if.hw_vlan_filter = conf->bit.hw_vlan_filter;
+ inst->data.dpdk_if.hw_vlan_strip = conf->bit.hw_vlan_strip;
+
+ inst->data.dpdk_if.rx_queue_num = conf->rx.queue_num;
+ /* fix Buffer Overflow type code-dex issue */
+ if (inst->data.dpdk_if.rx_queue_num > HAL_ETH_MAX_QUEUE_NUM)
+ {
+ NSHAL_LOGERR
+ ("rx queue num error]rx_queue_num=%u, HAL_ETH_MAX_QUEUE_NUM=%d",
+ inst->data.dpdk_if.rx_queue_num, HAL_ETH_MAX_QUEUE_NUM);
+
+ return -1;
+ }
+
+ for (i = 0; i < inst->data.dpdk_if.rx_queue_num; i++)
+ {
+ inst->data.dpdk_if.rx_ring_size[i] = conf->rx.ring_size[i];
+ inst->data.dpdk_if.rx_pool[i] =
+ (struct rte_mempool *) conf->rx.ring_pool[i];
+ }
+
+ inst->data.dpdk_if.tx_queue_num = conf->tx.queue_num;
+ /* fix "FORTIFY.Out-of-Bounds_Read--Off-by-One" type codedex issue */
+ if (inst->data.dpdk_if.tx_queue_num > HAL_ETH_MAX_QUEUE_NUM)
+ {
+ NSHAL_LOGERR
+ ("tx queue num error]rx_queue_num=%u, HAL_ETH_MAX_QUEUE_NUM=%d",
+ inst->data.dpdk_if.tx_queue_num, HAL_ETH_MAX_QUEUE_NUM);
+
+ return -1;
+ }
+ for (i = 0; i < inst->data.dpdk_if.tx_queue_num; i++)
+ {
+ inst->data.dpdk_if.tx_ring_size[i] = conf->tx.ring_size[i];
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_bond_config
+ Description : config the port for bond mode
+ Input : netif_inst_t* inst
+ uint8_t slave_num
+ netif_inst_t* slave_inst[]
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_bond_config (netif_inst_t * inst, uint8_t slave_num,
+ netif_inst_t * slave_inst[])
+{
+ int ret;
+ uint32_t i, queue;
+
+ inst->data.dpdk_if.slave_num = slave_num;
+
+ for (i = 0; i < slave_num; i++)
+ {
+ inst->data.dpdk_if.slave_port[i] = slave_inst[i]->data.dpdk_if.port_id;
+
+ if (0 == i)
+ {
+ inst->data.dpdk_if.hw_vlan_filter =
+ slave_inst[i]->data.dpdk_if.hw_vlan_filter;
+ inst->data.dpdk_if.hw_vlan_strip =
+ slave_inst[i]->data.dpdk_if.hw_vlan_strip;
+ inst->data.dpdk_if.rx_queue_num =
+ slave_inst[i]->data.dpdk_if.rx_queue_num;
+ inst->data.dpdk_if.tx_queue_num =
+ slave_inst[i]->data.dpdk_if.tx_queue_num;
+
+ /*will be used in function dpdk_get_queue_conf and dpdk_get_port_conf */
+ ret =
+ STRCPY_S (inst->data.dpdk_if.driver_name,
+ sizeof (inst->data.dpdk_if.driver_name), "bond");
+
+ if (EOK != ret)
+ {
+ NSHAL_LOGERR ("STRCPY_S failed]ret=%d.", ret);
+ return -1;
+ }
+
+ for (queue = 0; queue < HAL_ETH_MAX_QUEUE_NUM; queue++)
+ {
+ inst->data.dpdk_if.rx_pool[queue] =
+ slave_inst[i]->data.dpdk_if.rx_pool[queue];
+ inst->data.dpdk_if.rx_ring_size[queue] =
+ slave_inst[i]->data.dpdk_if.rx_ring_size[queue];
+ inst->data.dpdk_if.tx_ring_size[queue] =
+ slave_inst[i]->data.dpdk_if.tx_ring_size[queue];
+ }
+ }
+ }
+
+ return 0;
+
+}
+
+/*****************************************************************************
+ Prototype : dpdk_bond
+ Description : bond port
+ Input : netif_inst_t* inst
+ const char* bond_name
+ uint8_t slave_num
+ netif_inst_t* slave_inst[]
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_bond (netif_inst_t * inst, const char *bond_name, uint8_t slave_num,
+ netif_inst_t * slave_inst[])
+{
+ int i, ret;
+ int port;
+ struct ether_addr eth_addr;
+
+ /* check if all the slaves' drivers are same, not support different drivers */
+ for (i = 1; i < slave_num; i++)
+ {
+ if (strncmp
+ (slave_inst[0]->data.dpdk_if.driver_name,
+ slave_inst[i]->data.dpdk_if.driver_name,
+ strlen (slave_inst[0]->data.dpdk_if.driver_name)))
+ {
+ NSHAL_LOGERR
+ ("dpdk does not support different types of network card]slave[0]=%s, slave[%i]=%s",
+ slave_inst[0]->data.dpdk_if.driver_name, i,
+ slave_inst[i]->data.dpdk_if.driver_name);
+ return -1;
+ }
+ }
+
+ ret = dpdk_set_nic_name (inst, bond_name);
+
+ if (0 != ret)
+ {
+ NSHAL_LOGERR ("dpdk_set_nic_name fail]ret=%d", ret);
+ return -1;
+ }
+
+ port =
+ rte_eth_bond_create (bond_name, BONDING_MODE_ACTIVE_BACKUP, SOCKET_ID_0);
+ if (port < 0)
+ {
+ NSHAL_LOGERR ("rte_eth_bond_create fail]ret=%i", ret);
+ return -1;
+ }
+
+ ret = dpdk_set_port (inst, (uint8_t) port);
+
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("dpdk_set_port fail]ret=%i", ret);
+ return ret;
+ }
+
+ ret = dpdk_bond_config (inst, slave_num, slave_inst);
+
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("dpdk_bond_config fail]ret=%i", ret);
+ return ret;
+ }
+
+ ret = dpdk_setup_port (inst);
+
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("dpdk_setup_port fail]ret=%i", ret);
+ return ret;
+ }
+
+ for (i = 0; i < slave_num; i++)
+ {
+ NSHAL_LOGINF ("add slave port_id=%u, nic_name=%s",
+ slave_inst[i]->data.dpdk_if.port_id,
+ slave_inst[i]->data.dpdk_if.nic_name);
+
+ if (rte_eth_bond_slave_add
+ ((uint8_t) port, slave_inst[i]->data.dpdk_if.port_id) == -1)
+ {
+ NSHAL_LOGERR ("adding slave (%u) to bond (%u) failed]",
+ slave_inst[i]->data.dpdk_if.port_id, port);
+ return -1;
+ }
+ }
+
+ rte_eth_macaddr_get (slave_inst[0]->data.dpdk_if.port_id, &eth_addr);
+
+ ret = rte_eth_bond_mac_address_set ((uint8_t) port, &eth_addr);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("rte_eth_bond_mac_address_set fail]ret=%i", ret);
+ return ret;
+ }
+
+ ret = rte_eth_dev_start (inst->data.dpdk_if.port_id);
+ if (ret < 0)
+ {
+ NSHAL_LOGERR ("rte_eth_dev_start fail]ret=%i, port_id=%d", ret,
+ inst->data.dpdk_if.port_id);
+ return ret;
+ }
+
+ NSHAL_LOGINF ("port_id=%d,nic_name=%s,mac=%02X:%02X:%02X:%02X:%02X:%02X",
+ port,
+ inst->data.dpdk_if.nic_name,
+ eth_addr.addr_bytes[0],
+ eth_addr.addr_bytes[1],
+ eth_addr.addr_bytes[2],
+ eth_addr.addr_bytes[3],
+ eth_addr.addr_bytes[4], eth_addr.addr_bytes[5]);
+ return 0;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_add_mcastaddr
+ Description : add mcastaddr to the port
+ Input : netif_inst_t* inst
+ void* mc_addr_set
+ void* mc_addr
+ uint32_t nb_mc_addr
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_set_mcastaddr (netif_inst_t * inst, void *mc_addr_set,
+ void *mc_addr, uint32_t nb_mc_addr)
+{
+ uint8_t port = inst->data.dpdk_if.port_id;
+ int iRetVal;
+
+ NSHAL_LOGINF ("mc_addr_set number=%u", nb_mc_addr);
+ iRetVal = rte_eth_dev_set_mc_addr_list (port, mc_addr_set, nb_mc_addr);
+ if (iRetVal != 0)
+ {
+ NSHAL_LOGWAR ("fail to set_mc_addr_list]port=%u,ret=%d", port, iRetVal);
+ }
+
+ return iRetVal;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_add_mac_addr
+ Description : add mcastaddr to the port
+ Input : netif_inst_t* inst
+ void* mc_addr
+ Output : None
+ Return Value : NSTACK_STATIC int
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_add_mac_addr (netif_inst_t * inst, void *mc_addr)
+{
+ uint8_t port = inst->data.dpdk_if.port_id;
+ int iRetVal;
+
+ /* for MLX: set_mc_addr_list() is not callback, so call mac_addr_add() instead */
+ iRetVal = rte_eth_dev_mac_addr_add (port, mc_addr, 0);
+ if (0 != iRetVal)
+ {
+ NSHAL_LOGWAR ("fail to add_mac_addr]port=%u,ret=%d", port, iRetVal);
+ }
+
+ return iRetVal;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_rmv_mac_addr
+ Description : remove mcastaddr to the port
+ Input : netif_inst_t* inst
+ void* mc_addr
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_rmv_mac_addr (netif_inst_t * inst, void *mc_addr)
+{
+ uint8_t port = inst->data.dpdk_if.port_id;
+ int iRetVal;
+
+ /* for MLX: set_mc_addr_list() is not callback, so call mac_addr_remove() instead */
+ iRetVal = rte_eth_dev_mac_addr_remove (port, mc_addr);
+ if (0 != iRetVal)
+ {
+ NSHAL_LOGWAR ("fail to rmv_mac_addr]port=%u,ret=%d", port, iRetVal);
+ }
+
+ return iRetVal;
+}
+
+/*****************************************************************************
+ Prototype : dpdk_allmcast
+ Description : set allmcast mode to the port
+ Input : netif_inst_t* inst
+ uint8_t enable
+ Output : None
+ Return Value : NSTACK_STATIC
+ Calls :
+ Called By :
+
+*****************************************************************************/
+NSTACK_STATIC int
+dpdk_allmcast (netif_inst_t * inst, uint8_t enable)
+{
+ if (enable)
+ {
+ rte_eth_allmulticast_enable (inst->data.dpdk_if.port_id);
+ }
+ else
+ {
+ rte_eth_allmulticast_disable (inst->data.dpdk_if.port_id);
+ }
+
+ return 0;
+}
+
+const netif_ops_t dpdk_netif_ops = {
+ .name = "dpdk",
+ .init_global = dpdk_init_global,
+ .init_local = dpdk_init_local,
+ .open = dpdk_open,
+ .close = dpdk_close,
+ .start = dpdk_start,
+ .stop = dpdk_stop,
+ .bond = dpdk_bond,
+ .mtu = dpdk_get_mtu,
+ .macaddr = dpdk_get_macaddr,
+ .capability = dpdk_get_capability,
+ .recv = dpdk_recv,
+ .send = dpdk_send,
+ .link_status = dpdk_link_status,
+ .stats = dpdk_stats,
+ .stats_reset = dpdk_stats_reset,
+ .config = dpdk_config,
+ .mcastaddr = dpdk_set_mcastaddr,
+ .add_mac = dpdk_add_mac_addr,
+ .rmv_mac = dpdk_rmv_mac_addr,
+ .allmcast = dpdk_allmcast
+};
+
+HAL_IO_REGISTER (dpdk, &dpdk_netif_ops);
diff --git a/stacks/lwip_stack/src/maintain/CMakeLists.txt b/stacks/lwip_stack/src/maintain/CMakeLists.txt
new file mode 100644
index 0000000..05c5117
--- /dev/null
+++ b/stacks/lwip_stack/src/maintain/CMakeLists.txt
@@ -0,0 +1,44 @@
+#########################################################################
+#
+# 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 "/usr/include/dpdk/")
+ SET(PAL_BITWIDE_ADJUST ${PROJECT_SOURCE_DIR}/../../src/framework/common/base/include/common_pal_bitwide_adjust.h)
+ ADD_DEFINITIONS(-include ${PAL_BITWIDE_ADJUST})
+ INCLUDE_DIRECTORIES(
+ ${PAL_H_DIRECTORIES}
+ )
+endif()
+
+FILE(GLOB_RECURSE NSTACKMAINTAIN *.c)
+
+LINK_LIBRARIES(m dl rt dmm_api)
+if(WITH_SECUREC_LIB)
+INCLUDE_DIRECTORIES(
+ ./
+ ${JSON_C_SRC}
+ ${SECUREC_SRC}
+ ${CMAKE_CURRENT_LIST_DIR}/../include/
+)
+else()
+INCLUDE_DIRECTORIES(
+ ./
+ ${JSON_C_SRC}
+ ${CMAKE_CURRENT_LIST_DIR}/../include/
+)
+endif()
+ADD_LIBRARY(nStackMaintain STATIC ${NSTACKMAINTAIN})
diff --git a/stacks/lwip_stack/src/maintain/fw_mt_config.c b/stacks/lwip_stack/src/maintain/fw_mt_config.c
new file mode 100644
index 0000000..400eaa0
--- /dev/null
+++ b/stacks/lwip_stack/src/maintain/fw_mt_config.c
@@ -0,0 +1,843 @@
+/*
+*
+* 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 "nsfw_mt_config.h"
+#include <stdlib.h>
+#include <pthread.h>
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "json.h"
+#include "nsfw_init.h"
+#include "nsfw_mgr_com_api.h"
+
+/*==============================================*
+ * project-wide global variables *
+ *----------------------------------------------*/
+
+// can be read from config file
+u32 g_base_cfg_items[MAX_BASE_CFG] = { 0 };
+
+// calculated according to base config
+u32 g_custom_cfg_items[MAX_CUSTOM_CFG] = { 0 };
+
+// note: if seg number greater than 16, such buffer should use malloc
+// or it will be exceed 2K
+struct cfg_item_info g_cfg_item_info[CFG_SEG_MAX][MAX_CFG_ITEM];
+
+NSTACK_STATIC int g_cfg_item_count[CFG_SEG_MAX] = { 0 };
+
+NSTACK_STATIC char *g_cfg_seg_name[CFG_SEG_MAX];
+
+/*==============================================*
+ * routines' or functions' implementations *
+ *----------------------------------------------*/
+
+/* nStackCtrl cannot get the env path info, no start by shell script, need get
+ the path info ,and legal check , add a input parameter proc_type*/
+
+NSTACK_STATIC int
+get_ctrl_dir_info (char *current_path, unsigned path_len)
+{
+ char ctrl_dir[MAX_FILE_NAME_LEN] = { 0 };
+ int count = 0;
+ unsigned int dir_len = 0;
+
+ //nStackCtrl cannot get the path from the env, so need get from current pwd.
+ count = readlink ("/proc/self/exe", ctrl_dir, MAX_FILE_NAME_LEN);
+ if ((count < 0) || (count >= MAX_FILE_NAME_LEN))
+ {
+ save_pre_init_log (NSLOG_ERR,
+ "readlink get nStackCtrl path failed, write nothing!");
+ return -1;
+ }
+ ctrl_dir[count] = '\0';
+
+ dir_len = strlen (ctrl_dir);
+ if ((dir_len > strlen ("nStackCtrl")) && (dir_len < MAX_FILE_NAME_LEN))
+ {
+ ctrl_dir[dir_len - strlen ("nStackCtrl")] = '\0';
+ }
+ else
+ {
+ save_pre_init_log (NSLOG_ERR, "path strlen is illegal, write nothing!");
+ return -1;
+ }
+
+ if (NULL == strstr (ctrl_dir, "bin"))
+ {
+ /* Exit before nstack_log_init, use printf */
+ printf
+ ("the nStackServer content change, plz keep same with nStack release, exit!\n");
+#ifdef FOR_NSTACK_UT
+ return -1;
+#else
+ exit (1);
+#endif
+ }
+ if (EOK !=
+ STRNCAT_S (ctrl_dir, sizeof (ctrl_dir), "/../configure",
+ strlen ("/../configure")))
+ {
+ save_pre_init_log (NSLOG_ERR, "STRNCAT_S failed, current_dir = %s",
+ ctrl_dir);
+ return -1;
+ }
+
+ if (-1 == SNPRINTF_S (current_path, path_len, path_len - 1, "%s", ctrl_dir))
+ {
+ save_pre_init_log (NSLOG_ERR,
+ "SNPRINTF_S path name failed, ctrl_dir %s.",
+ ctrl_dir);
+ return -1;
+ }
+
+ return 0;
+
+}
+
+NSTACK_STATIC int
+get_cfg_buf (u32 proc_type, char *cfg_buf, unsigned buf_size)
+{
+ char current_dir[MAX_FILE_NAME_LEN] = { 0 };
+ char cfg_file_name[MAX_FILE_NAME_LEN] = { 0 };
+ char *cfg_resolved_path = NULL;
+ char *cfg_path = NULL;
+ FILE *fp = NULL;
+ int cfg_buf_len = 0;
+
+ cfg_path = getenv (CFG_PATH);
+ if ((NULL == cfg_path) && (NSFW_PROC_CTRL == proc_type))
+ {
+ if (-1 == get_ctrl_dir_info (current_dir, sizeof (current_dir)))
+ {
+ save_pre_init_log (NSLOG_ERR, "get_ctrl_dir_info failed.");
+ return -1;
+ }
+ cfg_path = current_dir;
+ }
+ else if ((NULL == cfg_path) && (NSFW_PROC_CTRL != proc_type))
+ {
+ save_pre_init_log (NSLOG_ERR,
+ "main or master process get nstack config path failed, will use default config!");
+ return -1;
+ }
+
+ if (-1 ==
+ SPRINTF_S (cfg_file_name, sizeof (cfg_file_name), "%s/%s", cfg_path,
+ CFG_FILE_NAME))
+ {
+ save_pre_init_log (NSLOG_ERR,
+ "format config file name failed, path %s, name %s.",
+ cfg_path, CFG_FILE_NAME);
+ return -1;
+ }
+
+ cfg_resolved_path = realpath (cfg_file_name, NULL);
+ if (NULL == cfg_resolved_path)
+ {
+ save_pre_init_log (NSLOG_ERR, "config file path invalid, cfg name %s.",
+ cfg_file_name);
+ return -1;
+ }
+
+ fp = fopen (cfg_resolved_path, "r");
+ if (NULL == fp)
+ {
+ free (cfg_resolved_path);
+ save_pre_init_log (NSLOG_ERR, "config file path invalid, cfg name %s.",
+ cfg_file_name);
+ return -1;
+ }
+
+ free (cfg_resolved_path);
+ // read config file to json buffer
+ cfg_buf_len = fread (cfg_buf, 1, buf_size, fp);
+
+ fclose (fp);
+
+ return cfg_buf_len;
+}
+
+NSTACK_STATIC inline int
+get_value_from_json_obj (struct json_object *obj, struct cfg_item_info *pitem)
+{
+ switch (pitem->type)
+ {
+ case CFG_ITEM_TYPE_INT:
+ pitem->value = json_object_get_int (obj);
+ break;
+ case CFG_ITEM_TYPE_STRING:
+ pitem->pvalue = (char *) json_object_get_string (obj);
+ break;
+ default:
+ // print log here?
+ return -1;
+ }
+ return 0;
+}
+
+NSTACK_STATIC inline void
+get_cfg_item (struct json_object *obj, int seg_index)
+{
+ struct json_object *cfg_seg_obj = NULL;
+ struct json_object *cfg_seg = NULL;
+ struct json_object *cfg_item_obj[MAX_CFG_ITEM] = { 0 };
+ int i = 0;
+ int cfg_num = 0;
+
+ (void) json_object_object_get_ex (obj, g_cfg_seg_name[seg_index],
+ &cfg_seg_obj);
+ if (NULL == cfg_seg_obj)
+ {
+ save_pre_init_log (NSLOG_ERR, "get config segment obj failed, seg:%s.",
+ g_cfg_seg_name[seg_index]);
+ return;
+ }
+
+ cfg_num = json_object_array_length (cfg_seg_obj);
+ if (cfg_num < 1)
+ {
+ save_pre_init_log (NSLOG_ERR,
+ "config segment count invalid, config segment %s, count %d.",
+ g_cfg_seg_name[seg_index], cfg_num);
+ return;
+ }
+
+ // each config segment just has 1 array element
+ cfg_seg = (struct json_object *) json_object_array_get_idx (cfg_seg_obj, 0);
+ if (NULL == cfg_seg)
+ {
+ save_pre_init_log (NSLOG_ERR, "no config item in seg %s.",
+ g_cfg_seg_name[seg_index]);
+ return;
+ }
+
+ for (; i < g_cfg_item_count[seg_index]; i++)
+ {
+ (void) json_object_object_get_ex (cfg_seg,
+ g_cfg_item_info[seg_index][i].name,
+ &cfg_item_obj[i]);
+
+ if (NULL == cfg_item_obj[i])
+ {
+ save_pre_init_log (NSLOG_ERR,
+ "get config item failed, config item %s.",
+ g_cfg_item_info[seg_index][i].name);
+ return;
+ }
+
+ // note: should specify the config item type if not only int item exist
+ if (get_value_from_json_obj
+ (cfg_item_obj[i], &g_cfg_item_info[seg_index][i]) != 0)
+ {
+ return;
+ }
+ }
+
+ return;
+}
+
+NSTACK_STATIC inline void
+parse_cfg (char *cfg_buf)
+{
+ if (NULL == cfg_buf)
+ {
+ return;
+ }
+
+ struct json_object *obj =
+ (struct json_object *) json_tokener_parse (cfg_buf);
+ int i = 0;
+
+ for (; i < CFG_SEG_MAX; i++)
+ {
+ if (0 == g_cfg_item_count[i])
+ {
+ continue;
+ }
+
+ get_cfg_item (obj, i);
+ }
+}
+
+NSTACK_STATIC inline int
+is_valid (int value, int min_value, int max_value)
+{
+ if ((value < min_value) || (value > max_value))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+NSTACK_STATIC inline void
+check_cfg_item_int (struct cfg_item_info *pitem)
+{
+ if (!is_valid (pitem->value, pitem->min_value, pitem->max_value))
+ {
+ pitem->value = pitem->default_value;
+ }
+}
+
+NSTACK_STATIC inline void
+check_cfg_item_string (struct cfg_item_info *pitem)
+{
+ if ((NULL == pitem->pvalue) || ((pitem->pvalue) && (0 == pitem->pvalue[0])))
+ {
+ pitem->pvalue = pitem->default_str;
+ }
+}
+
+NSTACK_STATIC inline void
+check_cfg_item (struct cfg_item_info *pitem)
+{
+ switch (pitem->type)
+ {
+ case CFG_ITEM_TYPE_INT:
+ check_cfg_item_int (pitem);
+ if (pitem->custom_check)
+ pitem->custom_check (pitem);
+ break;
+ case CFG_ITEM_TYPE_STRING:
+ check_cfg_item_string (pitem);
+ if (pitem->custom_check)
+ pitem->custom_check (pitem);
+ break;
+ default:
+ break;
+ }
+}
+
+NSTACK_STATIC inline void
+check_cfg ()
+{
+ int i = 0;
+ int j = 0;
+ for (i = 0; i < CFG_SEG_MAX; i++)
+ {
+ for (j = 0; j < g_cfg_item_count[i]; j++)
+ {
+ check_cfg_item (&g_cfg_item_info[i][j]);
+ }
+ }
+}
+
+NSTACK_STATIC inline void
+print_item_info (char *seg_name, struct cfg_item_info *pitem)
+{
+ switch (pitem->type)
+ {
+ case CFG_ITEM_TYPE_INT:
+ save_pre_init_log (NSLOG_INF, "config read seg:%s, name:%s, value:%d.",
+ seg_name, pitem->name, pitem->value);
+ break;
+ case CFG_ITEM_TYPE_STRING:
+ save_pre_init_log (NSLOG_INF, "config read seg:%s, name:%s, pvalue:%s.",
+ seg_name, pitem->name, pitem->pvalue);
+ break;
+ default:
+ break;
+ }
+}
+
+NSTACK_STATIC inline void
+print_config_item_info ()
+{
+ int i = 0;
+ int j = 0;
+ for (; i < CFG_SEG_MAX; i++)
+ {
+ for (j = 0; j < g_cfg_item_count[i]; j++)
+ {
+ print_item_info (g_cfg_seg_name[i], &g_cfg_item_info[i][j]);
+ }
+ }
+}
+
+void
+check_socket_config (void *pitem)
+{
+ struct cfg_item_info *item = (struct cfg_item_info *) pitem;
+ if (item->value > 0 && !(item->value & (item->value - 1)))
+ return;
+ save_pre_init_log (NSLOG_WAR,
+ "warning: config socket_num (%u) is not 2^n, will use the default value:%u",
+ item->value, item->default_value);
+ item->value = item->default_value;
+}
+
+/* thread schedule mode and thread priority should be matched */
+void
+check_thread_config (void *pitem)
+{
+ struct cfg_item_info *pri_cfg = (struct cfg_item_info *) pitem;
+ struct cfg_item_info *policy_cfg =
+ &g_cfg_item_info[CFG_SEG_PRI][CFG_SEG_THREAD_PRI_POLICY];
+
+ int max_pri = sched_get_priority_max (policy_cfg->value);
+ int min_pri = sched_get_priority_min (policy_cfg->value);
+ if ((pri_cfg->value > max_pri) || (pri_cfg->value < min_pri))
+ {
+ save_pre_init_log (NSLOG_INF,
+ "detect invalid thread priority configuration, use default value] policy=%d, pri=%d, def policy=%d, def pri=%d",
+ policy_cfg->value, pri_cfg->value,
+ policy_cfg->default_value, pri_cfg->default_value);
+
+ policy_cfg->value = policy_cfg->default_value;
+ pri_cfg->value = pri_cfg->default_value;
+ }
+}
+
+#define SET_CFG_ITEM(seg, item, field, value) g_cfg_item_info[seg][item].field = (value)
+#define SET_THREAD_CFG_ITEM(item, field, value) SET_CFG_ITEM(CFG_SEG_PRI, item, field, value)
+
+NSTACK_STATIC void
+init_main_def_config_items ()
+{
+ /* base config */
+ g_cfg_seg_name[CFG_SEG_BASE] = "cfg_seg_socket";
+ g_cfg_item_count[CFG_SEG_BASE] = CFG_SEG_BASE_MAX;
+ /* -- socket number */
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_SOCKET_NUM].name = "socket_num";
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_SOCKET_NUM].type =
+ CFG_ITEM_TYPE_INT;
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_SOCKET_NUM].custom_check =
+ check_socket_config;
+ set_cfg_info (CFG_SEG_BASE, CFG_SEG_BASE_SOCKET_NUM, MIN_SOCKET_NUM,
+ MAX_SOCKET_NUM, DEF_SOCKET_NUM);
+ /* -- arp stale time */
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_ARP_STALE_TIME].name =
+ "arp_stale_time";
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_ARP_STALE_TIME].type =
+ CFG_ITEM_TYPE_INT;
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_ARP_STALE_TIME].custom_check =
+ NULL;
+ set_cfg_info (CFG_SEG_BASE, CFG_SEG_BASE_ARP_STALE_TIME,
+ MIN_ARP_STACLE_TIME, MAX_ARP_STACLE_TIME,
+ DEF_ARP_STACLE_TIME);
+ /* -- arp braodcast retransmission times */
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_ARP_BC_RETRANS_NUM].name =
+ "arp_bc_retrans_num";
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_ARP_BC_RETRANS_NUM].type =
+ CFG_ITEM_TYPE_INT;
+ g_cfg_item_info[CFG_SEG_BASE][CFG_SEG_BASE_ARP_BC_RETRANS_NUM].custom_check
+ = NULL;
+ set_cfg_info (CFG_SEG_BASE, CFG_SEG_BASE_ARP_BC_RETRANS_NUM,
+ MIN_ARP_BC_RETRANS_NUM, MAX_ARP_BC_RETRANS_NUM,
+ DEF_ARP_BC_RETRANS_NUM);
+
+ /* support thread priority configuration */
+ g_cfg_seg_name[CFG_SEG_PRI] = "cfg_seg_thread_pri";
+ g_cfg_item_count[CFG_SEG_PRI] = CFG_SEG_THREAD_PRI_MAX;
+ SET_THREAD_CFG_ITEM (CFG_SEG_THREAD_PRI_POLICY, name, "sched_policy");
+ SET_THREAD_CFG_ITEM (CFG_SEG_THREAD_PRI_POLICY, type, CFG_ITEM_TYPE_INT);
+ SET_THREAD_CFG_ITEM (CFG_SEG_THREAD_PRI_POLICY, custom_check, NULL);
+ set_cfg_info (CFG_SEG_PRI, CFG_SEG_THREAD_PRI_POLICY, 0, 2, 0);
+
+ SET_THREAD_CFG_ITEM (CFG_SEG_THREAD_PRI_PRI, name, "thread_pri");
+ SET_THREAD_CFG_ITEM (CFG_SEG_THREAD_PRI_PRI, type, CFG_ITEM_TYPE_INT);
+ SET_THREAD_CFG_ITEM (CFG_SEG_THREAD_PRI_PRI, custom_check,
+ check_thread_config);
+ set_cfg_info (CFG_SEG_PRI, CFG_SEG_THREAD_PRI_PRI, 0, 99, 0);
+
+ /* remove unsed operation config set */
+ /* log config */
+ g_cfg_seg_name[CFG_SEG_LOG] = "cfg_seg_log";
+ g_cfg_item_count[CFG_SEG_LOG] = 2;
+ g_cfg_item_info[CFG_SEG_LOG][0].name = "run_log_size";
+ g_cfg_item_info[CFG_SEG_LOG][0].type = CFG_ITEM_TYPE_INT;
+ g_cfg_item_info[CFG_SEG_LOG][0].custom_check = NULL;
+ g_cfg_item_info[CFG_SEG_LOG][1].name = "run_log_count";
+ g_cfg_item_info[CFG_SEG_LOG][1].type = CFG_ITEM_TYPE_INT;
+ g_cfg_item_info[CFG_SEG_LOG][1].custom_check = NULL;
+ set_cfg_info (CFG_SEG_LOG, 0, 10, 100, 50);
+ set_cfg_info (CFG_SEG_LOG, 1, 2, 20, 10);
+
+ /* path config */
+ /* set the path string and default str */
+ g_cfg_seg_name[CFG_SEG_PATH] = "cfg_seg_path";
+ g_cfg_item_count[CFG_SEG_PATH] = 1;
+ g_cfg_item_info[CFG_SEG_PATH][0].name = "stackx_log_path";
+ g_cfg_item_info[CFG_SEG_PATH][0].type = CFG_ITEM_TYPE_STRING;
+ g_cfg_item_info[CFG_SEG_PATH][0].default_str = NSTACK_LOG_NAME;
+ g_cfg_item_info[CFG_SEG_PATH][0].custom_check = NULL;
+}
+
+/* master and ctrl both use the function to reduce the redundancy,
+* as the parameter and operation all same.
+*/
+NSTACK_STATIC void
+init_master_def_config_items ()
+{
+ int i = 0;
+ for (; i < CFG_SEG_MAX; i++)
+ {
+ if (i != CFG_SEG_LOG)
+ {
+ g_cfg_item_count[i] = 0;
+ }
+ }
+
+ g_cfg_seg_name[CFG_SEG_LOG] = "cfg_seg_log";
+ g_cfg_item_count[CFG_SEG_LOG] = 2;
+ g_cfg_item_info[CFG_SEG_LOG][0].name = "mon_log_size";
+ g_cfg_item_info[CFG_SEG_LOG][0].type = CFG_ITEM_TYPE_INT;
+ g_cfg_item_info[CFG_SEG_LOG][0].custom_check = NULL;
+ g_cfg_item_info[CFG_SEG_LOG][1].name = "mon_log_count";
+ g_cfg_item_info[CFG_SEG_LOG][1].type = CFG_ITEM_TYPE_INT;
+ g_cfg_item_info[CFG_SEG_LOG][1].custom_check = NULL;
+
+ set_cfg_info (CFG_SEG_LOG, 0, 2, 20, 10);
+ set_cfg_info (CFG_SEG_LOG, 1, 2, 20, 10);
+
+ g_cfg_seg_name[CFG_SEG_PATH] = "cfg_seg_path";
+ g_cfg_item_count[CFG_SEG_PATH] = 1;
+ g_cfg_item_info[CFG_SEG_PATH][0].name = "master_log_path";
+ g_cfg_item_info[CFG_SEG_PATH][0].type = CFG_ITEM_TYPE_STRING;
+ g_cfg_item_info[CFG_SEG_PATH][0].default_str = NSTACK_LOG_NAME;
+ g_cfg_item_info[CFG_SEG_PATH][0].custom_check = NULL;
+}
+
+NSTACK_STATIC void
+read_init_config (u32 proc_type)
+{
+ int cfg_buf_len = 0;
+ char cfg_json_buf[CFG_BUFFER_LEN] = { 0 };
+
+ cfg_buf_len = get_cfg_buf (proc_type, cfg_json_buf, sizeof (cfg_json_buf));
+ if (cfg_buf_len < 0)
+ {
+ save_pre_init_log (NSLOG_WAR,
+ "warning:file not exist, use default config.");
+ return;
+ }
+ else
+ {
+ /* parse json buffer */
+ parse_cfg (cfg_json_buf);
+ }
+ save_pre_init_log (NSLOG_INF, "read configuration finished.");
+}
+
+/* =========== set config items ========= */
+NSTACK_STATIC inline void
+set_base_config ()
+{
+ g_base_cfg_items[CFG_BASE_RING_SIZE] = DEF_RING_BASE_SIZE;
+ g_base_cfg_items[CFG_BASE_HAL_PORT_NUM] = DEF_HAL_PORT_NUM;
+
+ g_base_cfg_items[CFG_BASE_SOCKET_NUM] =
+ (u32) get_cfg_info (CFG_SEG_BASE, CFG_SEG_BASE_SOCKET_NUM);
+ g_base_cfg_items[CFG_BASE_ARP_STALE_TIME] =
+ (u32) get_cfg_info (CFG_SEG_BASE, CFG_SEG_BASE_ARP_STALE_TIME);
+ g_base_cfg_items[CFG_BASE_ARP_BC_RETRANS_NUM] =
+ (u32) get_cfg_info (CFG_SEG_BASE, CFG_SEG_BASE_ARP_BC_RETRANS_NUM);
+}
+
+NSTACK_STATIC void
+init_base_config (cfg_module_param * param)
+{
+ /* initial default config */
+ /* omc_ctrl single log file should be 10M */
+ if (param->proc_type == NSFW_PROC_MASTER
+ || param->proc_type == NSFW_PROC_CTRL)
+ {
+ init_master_def_config_items ();
+ }
+ else
+ {
+ init_main_def_config_items ();
+ }
+
+ /* read base config from file */
+ read_init_config (param->proc_type);
+ /* check config and reset value */
+ check_cfg ();
+
+ /* print config info */
+ print_config_item_info ();
+
+ set_base_config ();
+}
+
+NSTACK_STATIC void
+init_stackx_config ()
+{
+ u32 socket_num_per_thread = CUR_CFG_SOCKET_NUM;
+ u32 factor = socket_num_per_thread / SOCKET_NUM_PER_THREAD;
+
+ if (factor == 0 || socket_num_per_thread % SOCKET_NUM_PER_THREAD > 0)
+ {
+ factor += 1;
+ }
+
+ save_pre_init_log (NSLOG_INF, "socket num:%d, factor:%d",
+ CUR_CFG_SOCKET_NUM, factor);
+
+ /* MBUF config */
+ set_custom_cfg_item (CFG_MBUF_DATA_SIZE, DEF_MBUF_DATA_SIZE);
+ set_custom_cfg_item (CFG_TX_MBUF_NUM, DEF_TX_MBUF_POOL_SIZE);
+ set_custom_cfg_item (CFG_RX_MBUF_NUM, DEF_RX_MBUF_POOL_SIZE);
+ set_custom_cfg_item (CFG_MP_TCPSEG_NUM, DEF_MEMP_NUM_TCP_SEG); /* tcp segment number */
+ set_custom_cfg_item (CFG_MP_MSG_NUM, DEF_TX_MSG_POOL_SIZE); /* msg number */
+
+ /* ring config */
+ set_custom_cfg_item (CFG_HAL_RX_RING_SIZE, DEF_HAL_RX_RING_SIZE); /* netif ring size not changed */
+ set_custom_cfg_item (CFG_HAL_TX_RING_SIZE, DEF_HAL_TX_RING_SIZE); /* netif ring size not changed */
+ set_custom_cfg_item (CFG_MBOX_RING_SIZE, DEF_MBOX_RING_SIZE);
+ set_custom_cfg_item (CFG_SPL_MAX_RING_SIZE, DEF_SPL_MAX_RING_SIZE); /* stackx ring size */
+
+ /* pcb config */
+ set_custom_cfg_item (CFG_TCP_PCB_NUM, DEF_TCP_PCB_NUM * factor);
+ set_custom_cfg_item (CFG_UDP_PCB_NUM, DEF_UDP_PCB_NUM * factor);
+ set_custom_cfg_item (CFG_RAW_PCB_NUM, DEF_RAW_PCB_NUM * factor);
+ set_custom_cfg_item (CFG_ARP_QUEUE_NUM,
+ CUR_CFG_SOCKET_NUM >
+ DEF_SOCKET_NUM ? LARGE_ARP_QUEUE_NUM :
+ DEF_ARP_QUEUE_NUM);
+}
+
+void
+print_final_config_para ()
+{
+ save_pre_init_log (NSLOG_INF, "socket_num :%u",
+ get_base_cfg (CFG_BASE_SOCKET_NUM));
+ save_pre_init_log (NSLOG_INF, "base_ring_size :%u",
+ get_base_cfg (CFG_BASE_RING_SIZE));
+ save_pre_init_log (NSLOG_INF, "hal_port_num :%u",
+ get_base_cfg (CFG_BASE_HAL_PORT_NUM));
+ save_pre_init_log (NSLOG_INF, "arp_stale_num :%u",
+ get_base_cfg (CFG_BASE_ARP_STALE_TIME));
+ save_pre_init_log (NSLOG_INF, "arp_bc_retrans_num :%u",
+ get_base_cfg (CFG_BASE_ARP_BC_RETRANS_NUM));
+
+ save_pre_init_log (NSLOG_INF, "mbuf_data_size :%u",
+ get_custom_cfg (CFG_MBUF_DATA_SIZE));
+ save_pre_init_log (NSLOG_INF, "tx_mbuf_num :%u",
+ get_custom_cfg (CFG_TX_MBUF_NUM));
+ save_pre_init_log (NSLOG_INF, "rx_mbuf_num :%u",
+ get_custom_cfg (CFG_RX_MBUF_NUM));
+ save_pre_init_log (NSLOG_INF, "tcp_seg_mp_num :%u",
+ get_custom_cfg (CFG_MP_TCPSEG_NUM));
+ save_pre_init_log (NSLOG_INF, "msg_mp_num :%u",
+ get_custom_cfg (CFG_MP_MSG_NUM));
+ save_pre_init_log (NSLOG_INF, "hal_tx_ring_size :%u",
+ get_custom_cfg (CFG_HAL_TX_RING_SIZE));
+ save_pre_init_log (NSLOG_INF, "hal_rx_ring_size :%u",
+ get_custom_cfg (CFG_HAL_RX_RING_SIZE));
+ save_pre_init_log (NSLOG_INF, "mbox_ring_size :%u",
+ get_custom_cfg (CFG_MBOX_RING_SIZE));
+ save_pre_init_log (NSLOG_INF, "spl_ring_size :%u",
+ get_custom_cfg (CFG_SPL_MAX_RING_SIZE));
+ save_pre_init_log (NSLOG_INF, "tcp_pcb_num :%u",
+ get_custom_cfg (CFG_TCP_PCB_NUM));
+ save_pre_init_log (NSLOG_INF, "udp_pcb_num :%u",
+ get_custom_cfg (CFG_UDP_PCB_NUM));
+ save_pre_init_log (NSLOG_INF, "raw_pcb_num :%u",
+ get_custom_cfg (CFG_RAW_PCB_NUM));
+}
+
+NSTACK_STATIC void
+init_module_cfg_default ()
+{
+ init_stackx_config ();
+
+ print_final_config_para ();
+}
+
+NSTACK_STATIC void
+init_main_log_cfg_para ()
+{
+ struct log_init_para log_para;
+ log_para.run_log_size = g_cfg_item_info[CFG_SEG_LOG][0].value;
+ log_para.run_log_count = g_cfg_item_info[CFG_SEG_LOG][1].value;
+
+ /* log path valid check */
+ if (0 == access (g_cfg_item_info[CFG_SEG_PATH][0].pvalue, W_OK))
+ {
+ log_para.run_log_path = g_cfg_item_info[CFG_SEG_PATH][0].pvalue;
+ }
+ else
+ {
+ log_para.run_log_path = g_cfg_item_info[CFG_SEG_PATH][0].default_str;
+ }
+
+ set_log_init_para (&log_para);
+}
+
+NSTACK_STATIC void
+init_master_log_cfg_para ()
+{
+ struct log_init_para log_para;
+ log_para.mon_log_size = g_cfg_item_info[CFG_SEG_LOG][0].value;
+ log_para.mon_log_count = g_cfg_item_info[CFG_SEG_LOG][1].value;
+
+ /* log path valid check */
+ if (0 == access (g_cfg_item_info[CFG_SEG_PATH][0].pvalue, W_OK))
+ {
+ log_para.mon_log_path = g_cfg_item_info[CFG_SEG_PATH][0].pvalue;
+ }
+ else
+ {
+ log_para.mon_log_path = g_cfg_item_info[CFG_SEG_PATH][0].default_str;
+ }
+
+ set_log_init_para (&log_para);
+}
+
+/* nStackCtrl is the diff process with main, cannot use main process info,
+ need get the configure info respectively */
+/* omc_ctrl single log file should be 10M */
+NSTACK_STATIC void
+init_ctrl_log_cfg_para ()
+{
+ struct log_init_para log_para;
+ log_para.mon_log_size = g_cfg_item_info[CFG_SEG_LOG][0].value;
+ log_para.mon_log_count = g_cfg_item_info[CFG_SEG_LOG][1].value;
+
+ /* log path valid check */
+ if (0 == access (g_cfg_item_info[CFG_SEG_PATH][0].pvalue, W_OK))
+ {
+ log_para.mon_log_path = g_cfg_item_info[CFG_SEG_PATH][0].pvalue;
+ }
+ else
+ {
+ log_para.mon_log_path = g_cfg_item_info[CFG_SEG_PATH][0].default_str;
+ }
+
+ set_log_init_para (&log_para);
+}
+
+/*===========config init for nstack main=============*/
+
+NSTACK_STATIC void
+init_module_cfg_nstackmain ()
+{
+ /* init config data */
+ init_module_cfg_default ();
+
+ /* init log para */
+ init_main_log_cfg_para ();
+}
+
+/*===========config init for nstack master=============*/
+
+NSTACK_STATIC void
+init_module_cfg_nstackmaster ()
+{
+ /* init config data */
+ init_module_cfg_default ();
+
+ init_master_log_cfg_para ();
+}
+
+/*===========config init for nstack ctrl=============*/
+
+/* nStackCtrl is the diff process with main,
+ cannot use main process info, need get the configure info respectively */
+
+NSTACK_STATIC void
+init_module_cfg_nstackctrl ()
+{
+ init_ctrl_log_cfg_para ();
+}
+
+/*===========init config module=============*/
+void
+config_module_init (cfg_module_param * param)
+{
+ save_pre_init_log (NSLOG_INF, "config module init begin] proc type=%d",
+ param->proc_type);
+
+ init_base_config (param);
+
+ switch (param->proc_type)
+ {
+ case NSFW_PROC_MAIN:
+ init_module_cfg_nstackmain ();
+ break;
+
+ case NSFW_PROC_MASTER:
+ init_module_cfg_nstackmaster ();
+ break;
+
+ case NSFW_PROC_CTRL:
+ init_module_cfg_nstackctrl ();
+ break;
+
+ default:
+ init_module_cfg_default ();
+ break;
+ }
+
+ save_pre_init_log (NSLOG_INF, "config module init end.");
+}
+
+u32
+get_cfg_share_mem_size ()
+{
+ return sizeof (g_base_cfg_items) + sizeof (g_custom_cfg_items);
+}
+
+int
+get_share_cfg_from_mem (void *mem)
+{
+ if (EOK !=
+ MEMCPY_S (g_base_cfg_items, sizeof (g_base_cfg_items), mem,
+ sizeof (g_base_cfg_items)))
+ {
+ return -1;
+ }
+
+ char *custom_cfg_mem = (char *) mem + sizeof (g_base_cfg_items);
+
+ if (EOK !=
+ MEMCPY_S (g_custom_cfg_items, sizeof (g_custom_cfg_items),
+ custom_cfg_mem, sizeof (g_custom_cfg_items)))
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+set_share_cfg_to_mem (void *mem)
+{
+ if (EOK !=
+ MEMCPY_S (mem, sizeof (g_base_cfg_items), g_base_cfg_items,
+ sizeof (g_base_cfg_items)))
+ {
+ return -1;
+ }
+
+ char *custom_cfg_mem = (char *) mem + sizeof (g_base_cfg_items);
+
+ if (EOK !=
+ MEMCPY_S (custom_cfg_mem, sizeof (g_custom_cfg_items),
+ g_custom_cfg_items, sizeof (g_custom_cfg_items)))
+ {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/stacks/lwip_stack/src/maintain/nsfw_msg.c b/stacks/lwip_stack/src/maintain/nsfw_msg.c
new file mode 100644
index 0000000..338f803
--- /dev/null
+++ b/stacks/lwip_stack/src/maintain/nsfw_msg.c
@@ -0,0 +1,23 @@
+/*
+*
+* 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_msg.h"
+/* *INDENT-OFF* */
+msg_fun g_msg_module_fun_array[MAX_MODULE_TYPE] = {NULL};
+msg_fun g_msg_module_major_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE] = {{NULL}};
+msg_fun g_msg_module_major_minor_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE][MAX_MINOR_TYPE] = {{{NULL}}};
+msg_fun g_msg_unsupport_fun = NULL;
+/* *INDENT-ON* */
diff --git a/stacks/lwip_stack/src/maintain/nsfw_rti.c b/stacks/lwip_stack/src/maintain/nsfw_rti.c
new file mode 100644
index 0000000..e5a1d3c
--- /dev/null
+++ b/stacks/lwip_stack/src/maintain/nsfw_rti.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 <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"
+#include "nsfw_rti.h"
+#include "nsfw_msg.h"
+#ifdef HAL_LIB
+#else
+#include "common_pal_bitwide_adjust.h"
+#endif
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C"{
+/* *INDENT-ON* */
+#endif /* __cplusplus */
+
+char g_dfx_switch = 1;
+
+struct rti_queue *g_nsfw_rti_primary_stat = NULL;
+
+void
+nsfw_rti_stat (nsfw_rti_stat_type_t statType, const data_com_msg * m)
+{
+ if (!g_nsfw_rti_primary_stat || !m)
+ {
+ return;
+ }
+
+ struct rti_queue *primary_stat = ADDR_SHTOL (g_nsfw_rti_primary_stat);
+
+ switch (statType)
+ {
+ case NSFW_STAT_PRIMARY_DEQ:
+ if ((m->param.major_type >= MAX_MAJOR_TYPE)
+ || (m->param.minor_type >= MAX_MINOR_TYPE))
+ {
+ return;
+ }
+ /*call_msg_fun() is only called in nStackMain, no reentrance risk, ++ operation is ok */
+ primary_stat->tcpip_msg_deq[m->param.major_type]++;
+ if (0 == m->param.major_type) //SPL_TCPIP_NEW_MSG_API
+ {
+ primary_stat->api_msg_deq[m->param.minor_type]++;
+ }
+ break;
+ case NSFW_STAT_PRIMARY_ENQ_FAIL:
+ if ((m->param.major_type >= MAX_MAJOR_TYPE)
+ || (m->param.minor_type >= MAX_MINOR_TYPE))
+ {
+ return;
+ }
+ __sync_fetch_and_add (&primary_stat->tcpip_msg_enq_fail
+ [m->param.major_type], 1);
+ if (0 == m->param.major_type) //SPL_TCPIP_NEW_MSG_API
+ {
+ __sync_fetch_and_add (&primary_stat->api_msg_enq_fail
+ [m->param.minor_type], 1);
+ }
+ break;
+ case NSFW_STAT_PRIMARY_ENQ:
+ //not use
+ break;
+ default:
+ break;
+ }
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif /* __cplusplus */
diff --git a/stacks/lwip_stack/src/nStackMain/CMakeLists.txt b/stacks/lwip_stack/src/nStackMain/CMakeLists.txt
new file mode 100644
index 0000000..24f6c9d
--- /dev/null
+++ b/stacks/lwip_stack/src/nStackMain/CMakeLists.txt
@@ -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.
+#########################################################################
+
+FILE(GLOB_RECURSE MAIN *.c)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE -pie")
+
+ADD_DEFINITIONS(-rdynamic -D__NSTACK_MAIN__)
+ADD_EXECUTABLE(nStackMain ${MAIN})
+TARGET_LINK_LIBRARIES(
+ nStackMain
+ -Wl,--whole-archive
+ ${LIB_PATH_STATIC}/libjson-c.a
+ ${LIB_PATH_STATIC}/libglog.a
+ dmm_api
+ nStackMaintain
+ stacklwip
+ nStackHal
+ nStackAlarm
+ nTcpdump
+ -Wl,--no-whole-archive,-lstdc++ -ldl
+ -Wl,--no-as-needed
+ rte_eal
+ rte_ethdev
+ rte_mempool
+ rte_ring
+ rte_mbuf
+ rte_pmd_ixgbe
+ rte_pmd_virtio
+ rte_pmd_e1000
+ rte_pmd_vmxnet3_uio
+ rte_pmd_bond
+ rte_kvargs
+ rte_cmdline
+)
+
+if(WITH_SECUREC_LIB)
+ADD_DEPENDENCIES(nStackMain nStackHal nStackMaintain nStackAlarm stacklwip SECUREC)
+else()
+ADD_DEPENDENCIES(nStackMain nStackHal nStackMaintain nStackAlarm stacklwip)
+endif()
+
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_LIST_DIR}/../alarm/
+ ${CMAKE_CURRENT_LIST_DIR}/../maintain/
+ ${CMAKE_CURRENT_LIST_DIR}/../include/
+)
diff --git a/stacks/lwip_stack/src/nStackMain/main.c b/stacks/lwip_stack/src/nStackMain/main.c
new file mode 100644
index 0000000..ce05068
--- /dev/null
+++ b/stacks/lwip_stack/src/nStackMain/main.c
@@ -0,0 +1,427 @@
+/*
+*
+* 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 <signal.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include "nstack_securec.h"
+#include "nstack_log.h"
+#include "types.h"
+#include "nsfw_init.h"
+#include "alarm_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_dmm_adpt.h"
+
+#include "nsfw_mem_api.h"
+#include "nsfw_mt_config.h"
+
+#define GLOBAL_Stack_ARG "stack"
+#define GlOBAL_HELP "--help"
+#define GLOBAL_Dpdk_ARG "dpdk"
+#define GLOBAL_STACK_PORT "-port"
+#define NSTACK_MAIN_MAX_PARA 19
+#define NSTACK_MAIN_MIN_PARA 1
+
+#define MAX_MASTER_OPEN_FD 1024
+
+extern int uStackArgIndex;
+extern void spl_tcpip_thread (void *arg);
+extern int globalArgc;
+extern char **gArgv;
+extern int g_dpdk_argc;
+extern char **g_dpdk_argv;
+extern void print_call_stack ();
+extern int adjust_mem_arg (int argc, char *argv[]);
+extern struct cfg_item_info g_cfg_item_info[CFG_SEG_MAX][MAX_CFG_ITEM];
+extern int get_network_json_data ();
+extern int get_ip_json_data ();
+
+#ifdef SYS_MEM_RES_STAT
+extern void get_resource_stat ();
+#endif
+
+extern alarm_result ms_alarm_check_func (void *para);
+int g_tcpip_thread_stat = 0; //this variable will be used at health check feature
+
+#if (DPDK_MODULE)
+extern void pal_common_usage (void);
+#endif
+
+typedef void (*pSignalFunc) (int);
+int app_init (void);
+
+void
+helpInfo ()
+{
+ NSPOL_LOGERR
+ ("-----------------------------------------------------------------"
+ "\nThe format of arg" "\nbash:./nStackMain RTE-ARGS stack STACK-ARGS"
+ "\n RTE-ARGS=-c COREMASK -n NUM [-b <domain:bus:devid.func>] [--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] [--proc-type <primary|secondary|auto>] [-- xen-dom0]"
+ "\n STACK-ARGS=-port PORTMASK [-c COREMASK] [-thread NUM]"
+ "\nUser examples:"
+ "\nTo make the DPDK run on core mask:0xf,Number of memory channels per processor socket in DPDK is 3 "
+ "\nTo make the stack run on eth coremask:f"
+ "\nbash: ./nStackMain -c 0xf -n 3 stack -port f"
+ "\nTo get more help info for stack:" "\n ./nStackMain --help stack"
+ "\nTo get more help info for dpdk:" "\n ./nStackMain --help dpdk"
+ "\n-----------------------------------------------------------------");
+
+#ifndef FOR_NSTACK_UT
+ exit (0);
+#endif
+
+}
+
+#define SIG_PTRACE __SIGRTMIN + 5
+
+void
+signal_handler (int s)
+{
+ NSPOL_LOGERR ("Received signal exiting.]s=%d", s);
+ if (s == SIGSEGV) /* add for gdb attach work */
+ {
+ print_call_stack ();
+ }
+
+ nstack_segment_error (s);
+ if ((SIG_PTRACE != s) && (SIG_PTRACE + 2 != s))
+ {
+#ifndef FOR_NSTACK_UT
+ exit (0);
+#endif
+ }
+
+ int i;
+ for (i = 0; i < MAX_THREAD; i++)
+ {
+ if (g_all_thread[i] != pthread_self () && 0 != g_all_thread[i])
+ {
+ NSFW_LOGERR ("send sig thread %d", g_all_thread[i]);
+ if (0 == pthread_kill (g_all_thread[i], SIG_PTRACE + 2))
+ {
+ return;
+ }
+ }
+ g_all_thread[i] = 0;
+ }
+
+ for (i = 0; i < MAX_THREAD; i++)
+ {
+ if (0 != g_all_thread[i])
+ {
+ return;
+ }
+ }
+
+#ifndef FOR_NSTACK_UT
+ exit (0);
+#endif
+
+ //dpdk_signal_handler();
+}
+
+void
+register_signal_handler ()
+{
+/* donot catch SIGHUP SIGTERM */
+ static const int s_need_handle_signals[] = {
+ SIGABRT,
+ SIGBUS,
+ SIGFPE,
+ SIGILL,
+ SIGIOT,
+ SIGQUIT,
+ SIGSEGV,
+ //SIGTRAP,
+ SIGXCPU,
+ SIGXFSZ,
+ //SIGALRM,
+ //SIGHUP,
+ SIGINT,
+ //SIGKILL,
+ SIGPIPE,
+ SIGPROF,
+ SIGSYS,
+ //SIGTERM,
+ SIGUSR1,
+ SIGUSR2,
+ //SIGVTALRM,
+ //SIGSTOP,
+ //SIGTSTP,
+ //SIGTTIN,
+ //SIGTTOU
+ };
+
+ /* here mask signal that will use in sigwait() */
+ sigset_t waitset, oset;
+
+ if (0 != sigemptyset (&waitset))
+ {
+ NSPOL_LOGERR ("sigemptyset failed.");
+ }
+ sigaddset (&waitset, SIGRTMIN); /* for timer */
+ sigaddset (&waitset, SIGRTMIN + 2);
+ pthread_sigmask (SIG_BLOCK, &waitset, &oset);
+ unsigned int i = 0;
+
+ struct sigaction s;
+ s.sa_handler = signal_handler;
+ if (0 != sigemptyset (&s.sa_mask))
+ {
+ NSPOL_LOGERR ("sigemptyset failed.");
+ }
+
+ s.sa_flags = (int) SA_RESETHAND;
+
+ /* register sig handler for more signals */
+ for (i = 0; i < sizeof (s_need_handle_signals) / sizeof (int); i++)
+ {
+ if (sigaction (s_need_handle_signals[i], &s, NULL) != 0)
+ {
+ NSPOL_LOGERR ("Could not register %d signal handler.",
+ s_need_handle_signals[i]);
+ }
+
+ }
+
+}
+
+void
+checkArgs (int argc, char **argv)
+{
+ int uStackArg = 0; //mark the status whether need helpinfo and return
+ int i;
+ const unsigned int global_para_length = 5; //GLOBAL_Stack_ARG "stack" and GLOBAL_STACK_PORT "-port" string length, both are 5
+ const unsigned int global_help_length = 6; //GlOBAL_HELP "--help" string length is 6
+ const unsigned int global_dpdk_length = 4; //GLOBAL_Dpdk_ARG "dpdk" string length is 4
+
+ for (i = 0; i < argc; i++)
+ {
+ if (argc > 1)
+ {
+ if (strncmp (argv[i], GLOBAL_Stack_ARG, global_para_length) == 0)
+ {
+ if (i < 5)
+ {
+ NSPOL_LOGERR ("Too less args");
+ helpInfo ();
+ return;
+ }
+
+ uStackArg = 1;
+ uStackArgIndex = i;
+ continue;
+ }
+
+ if (strncmp (argv[i], GLOBAL_STACK_PORT, global_para_length) == 0)
+ {
+ continue;
+ }
+
+ if (strncmp (argv[i], GlOBAL_HELP, global_help_length) == 0)
+ {
+ if (i == (argc - 1))
+ {
+ helpInfo ();
+ return;
+ }
+ else if ((++i < argc)
+ &&
+ (strncmp (argv[i], GLOBAL_Dpdk_ARG, global_dpdk_length)
+ == 0))
+ {
+#if (DPDK_MODULE != 1)
+ //eal_common_usage();
+#else
+ pal_common_usage ();
+#endif
+ return;
+ }
+ else
+ {
+ helpInfo ();
+ return;
+ }
+ }
+ }
+ else
+ {
+ NSPOL_LOGERR ("Too less args");
+ helpInfo ();
+ return;
+ }
+ }
+
+ if (!uStackArg)
+ {
+ helpInfo ();
+ return;
+ }
+}
+
+extern u64 timer_get_threadid ();
+
+#ifdef FOR_NSTACK_UT
+int
+nstack_main (void)
+{
+ int argc;
+
+ char *argv[NSTACK_MAIN_MAX_PARA];
+ argv[0] = "nStackMain";
+ argv[1] = "-c";;
+ argv[2] = "0xffffffff";
+ argv[3] = "-n";
+ argv[4] = "3";
+ argv[5] = "stack";
+ argv[6] = "-port";
+ argv[7] = "288";
+ argv[8] = "-c";
+ argv[9] = "2";
+ argc = 10;
+
+#else
+int
+main (int argc, char *argv[])
+{
+#endif
+ fw_poc_type proc_type = NSFW_PROC_MAIN;
+
+ /* although nStackMaster has set close on exec, here can't be removed.
+ * in upgrade senario, if Master is old which has not set close on exec, here,
+ * if new version Main not close, problem will reappear. Add Begin*/
+ int i;
+ for (i = 4; i < MAX_MASTER_OPEN_FD; i++)
+ {
+ close (i);
+ }
+
+ cfg_module_param config_para;
+ config_para.proc_type = proc_type;
+ config_para.argc = argc;
+ config_para.argv = (unsigned char **) argv;
+ config_module_init (&config_para);
+
+ set_log_proc_type (LOG_PRO_NSTACK);
+ (void) nstack_log_init ();
+
+// nstack_tracing_enable();
+ if (0 != nsfw_proc_start_with_lock (NSFW_PROC_MAIN))
+ {
+ NSFW_LOGERR ("another process is running!!");
+ return 0;
+ }
+
+ if (1 != mallopt (M_ARENA_MAX, 1))
+ {
+ NSPOL_LOGERR ("Error: mallopt fail, continue init");
+ }
+
+ /* Set different mem args to PAL and EAL */
+ INITPOL_LOGINF ("main_thread", "adjust_mem_arg init", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_START);
+ if (adjust_mem_arg (argc, argv))
+ {
+ INITPOL_LOGERR ("main_thread", "adjust_mem_arg init", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_FAIL);
+ return -1;
+ }
+ INITPOL_LOGINF ("main_thread", "adjust_mem_arg init", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_SUCCESS);
+
+ checkArgs (globalArgc, gArgv);
+ register_signal_handler ();
+
+ (void) signal (SIG_PTRACE, signal_handler);
+ (void) signal (SIG_PTRACE + 2, signal_handler);
+
+ if (nsfw_mgr_comm_fd_init (NSFW_PROC_MAIN) < 0)
+ {
+ NSFW_LOGERR ("nsfw_mgr_comm_fd_init failed");
+ }
+
+ (void) nsfw_reg_trace_thread (pthread_self ());
+
+ (void) nstack_framework_setModuleParam (NSFW_ALARM_MODULE,
+ (void *) ((u64) proc_type));
+ (void) nstack_framework_setModuleParam (TCPDUMP_MODULE,
+ (void *) ((u64) proc_type));
+
+ nstack_dmm_para stpara;
+ stpara.argc = uStackArgIndex;
+ stpara.argv = gArgv;
+ stpara.deploy_type = NSTACK_MODEL_TYPE3;
+ stpara.proc_type = NSFW_PROC_MAIN;
+ stpara.attr.policy = get_cfg_info (CFG_SEG_PRI, CFG_SEG_THREAD_PRI_POLICY);
+ stpara.attr.pri = get_cfg_info (CFG_SEG_PRI, CFG_SEG_THREAD_PRI_PRI);
+
+ if (nstack_adpt_init (&stpara) != 0)
+ {
+ NSFW_LOGERR ("nstack adpt init fail");
+ return -1;
+ }
+
+ ns_send_init_alarm (ALARM_EVENT_NSTACK_MAIN_ABNORMAL);
+
+ while (!timer_get_threadid ())
+ {
+ (void) nsfw_thread_chk ();
+ sys_sleep_ns (0, 500000000);
+ }
+ (void) nsfw_thread_chk_unreg ();
+ NSFW_LOGINF ("tcpip thread start!");
+ (void) sleep (2);
+
+ NSFW_LOGINF ("read configuration!");
+ if (0 != get_network_json_data ())
+ {
+ NSFW_LOGINF ("get_network_json_data error");
+ }
+
+ if (0 != get_ip_json_data ())
+ {
+ NSFW_LOGINF ("get_ip_json_data error");
+ }
+
+ int ep_thread = 0;
+ while (1)
+ {
+#ifdef SYS_MEM_RES_STAT
+ get_resource_stat ();
+#endif
+ (void) sleep (3);
+ ep_thread = nsfw_mgr_com_chk_hbt (1);
+ if (ep_thread > 0)
+ {
+ NSFW_LOGINF ("force release lock");
+ (void) nsfw_recycle_rechk_lock ();
+ }
+#ifdef FOR_NSTACK_UT
+ return 0;
+#endif
+
+ }
+}
diff --git a/stacks/lwip_stack/src/sbr/CMakeLists.txt b/stacks/lwip_stack/src/sbr/CMakeLists.txt
new file mode 100644
index 0000000..42ab4a4
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/CMakeLists.txt
@@ -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.
+#########################################################################
+
+if(WITH_HAL_LIB)
+else()
+ SET(PAL_H_DIRECTORIES "/usr/include/dpdk/")
+endif()
+
+
+FILE(GLOB SBR *.c)
+ADD_LIBRARY(nstack SHARED ${SBR})
+TARGET_LINK_LIBRARIES(nstack -Wl,--whole-archive socket -Wl,--no-whole-archive dmm_api nStackMaintain)
+ADD_DEPENDENCIES(nstack socket DPDK)
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_LIST_DIR}/../include
+ ${PAL_H_DIRECTORIES}
+)
diff --git a/stacks/lwip_stack/src/sbr/sbr_err.h b/stacks/lwip_stack/src/sbr/sbr_err.h
new file mode 100644
index 0000000..be3bc3b
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/sbr_err.h
@@ -0,0 +1,191 @@
+/*
+*
+* 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 SBR_ERR_H
+#define SBR_ERR_H
+#include <errno.h>
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#ifdef SBR_PROVIDE_ERRNO
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Arg list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No stored locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+
+#define ENSROK 0
+#define ENSRNODATA 160
+#define ENSRFORMERR 161
+#define ENSRSERVFAIL 162
+#define ENSRNOTFOUND 163
+#define ENSRNOTIMP 164
+#define ENSRREFUSED 165
+#define ENSRBADQUERY 166
+#define ENSRBADNAME 167
+#define ENSRBADFAMILY 168
+#define ENSRBADRESP 169
+#define ENSRCONNREFUSED 170
+#define ENSRTIMEOUT 171
+#define ENSROF 172
+#define ENSRFILE 173
+#define ENSRNOMEM 174
+#define ENSRDESTRUCTION 175
+#define ENSRQUERYDOMAINTOOLONG 176
+#define ENSRCNAMELOOP 177
+#define OPTION_DEG 200
+
+#endif
+
+static inline void
+sbr_set_errno (int err)
+{
+ errno = err;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/sbr/sbr_index_ring.c b/stacks/lwip_stack/src/sbr/sbr_index_ring.c
new file mode 100644
index 0000000..0daa465
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/sbr_index_ring.c
@@ -0,0 +1,212 @@
+/*
+*
+* 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 "sbr_index_ring.h"
+#include "nstack_securec.h"
+#include "common_mem_common.h"
+#include "common_func.h"
+
+/*****************************************************************************
+* Prototype : sbr_init_index_ring
+* Description : init index ring
+* Input : sbr_index_ring* ring
+* u32 num
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+sbr_init_index_ring (sbr_index_ring * ring, u32 num)
+{
+ u32 loop;
+
+ ring->head = 0;
+ ring->tail = 0;
+ ring->num = num;
+ ring->mask = num - 1;
+
+ for (loop = 0; loop < num; loop++)
+ {
+ ring->nodes[loop].ver = (loop - num);
+ ring->nodes[loop].val = 0;
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_create_index_ring
+* Description : create index ring
+* Input : u32 num
+* Output : None
+* Return Value : sbr_index_ring*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+sbr_index_ring *
+sbr_create_index_ring (u32 num)
+{
+ num = common_mem_align32pow2 (num + 1);
+ sbr_index_ring *ring =
+ (sbr_index_ring *) malloc (sizeof (sbr_index_ring) +
+ num * sizeof (sbr_index_node));
+ if (!ring)
+ {
+ return NULL;
+ }
+
+ sbr_init_index_ring (ring, num);
+ return ring;
+}
+
+/*****************************************************************************
+* Prototype : sbr_index_ring_enqueue
+* Description : enqueue data,val != 0
+* Input : sbr_index_ring* ring
+* i32 val
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_index_ring_enqueue (sbr_index_ring * ring, i32 val)
+{
+ if (0 == val)
+ {
+ return -1;
+ }
+
+ sbr_index_node expect_node;
+ sbr_index_node cur_node;
+ u32 tmp_head;
+ u32 tmp_tail;
+ u32 cur_head = ring->head;
+ u32 mask = ring->mask;
+ u32 size = ring->num;
+
+ do
+ {
+ tmp_tail = ring->tail;
+ if (tmp_tail + size - cur_head == 0)
+ {
+ if (ring->nodes[tmp_tail & mask].val == 0)
+ {
+ (void) __sync_bool_compare_and_swap (&ring->tail, tmp_tail,
+ tmp_tail + 1);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ expect_node.ver = cur_head - size;
+ expect_node.val = 0;
+
+ cur_node.ver = cur_head;
+ cur_node.val = val;
+
+ if ((ring->nodes[cur_head & mask].ver == expect_node.ver)
+ && __sync_bool_compare_and_swap (&ring->nodes[cur_head & mask].data,
+ expect_node.data, cur_node.data))
+ {
+ tmp_head = ring->head;
+ if ((tmp_head - cur_head > 0x80000000) && (0 == (cur_head & 0x11)))
+ {
+ (void) __sync_bool_compare_and_swap (&ring->head, tmp_head,
+ cur_head);
+ }
+
+ break;
+ }
+
+ tmp_head = ring->head;
+ cur_head = cur_head - tmp_head < mask - 1 ? cur_head + 1 : tmp_head;
+ }
+ while (1);
+
+ return 1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_index_ring_dequeue
+* Description : dequeue
+* Input : sbr_index_ring* ring
+* i32* val
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_index_ring_dequeue (sbr_index_ring * ring, i32 * val)
+{
+ u32 cur_tail;
+ u32 tmp_tail;
+ u32 tmp_head;
+ u32 mask = ring->mask;
+ sbr_index_node null_node;
+ sbr_index_node expect_node;
+
+ cur_tail = ring->tail;
+ do
+ {
+ tmp_head = ring->head;
+ if (cur_tail == tmp_head)
+ {
+ if (0 != (ring->nodes[tmp_head & mask].val))
+ {
+ (void) __sync_bool_compare_and_swap (&ring->head, tmp_head,
+ tmp_head + 1);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ null_node.ver = cur_tail;
+ null_node.val = 0;
+ expect_node = ring->nodes[cur_tail & mask];
+
+ if ((null_node.ver == expect_node.ver) && (expect_node.val)
+ && __sync_bool_compare_and_swap (&ring->nodes[cur_tail & mask].data,
+ expect_node.data, null_node.data))
+
+ {
+ *val = expect_node.val;
+ tmp_tail = ring->tail;
+ if ((tmp_tail - cur_tail > 0x80000000) && (0 == (cur_tail & 0x11)))
+ {
+ (void) __sync_bool_compare_and_swap (&ring->tail, tmp_tail,
+ cur_tail);
+ }
+
+ break;
+ }
+
+ tmp_tail = ring->tail;
+ cur_tail = cur_tail - tmp_tail < mask - 1 ? cur_tail + 1 : tmp_tail;
+ }
+ while (1);
+
+ return 1;
+}
diff --git a/stacks/lwip_stack/src/sbr/sbr_index_ring.h b/stacks/lwip_stack/src/sbr/sbr_index_ring.h
new file mode 100644
index 0000000..86e8345
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/sbr_index_ring.h
@@ -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.
+*/
+
+#ifndef _SBR_INDEX_RING_H_
+#define _SBR_INDEX_RING_H_
+
+#include "types.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef struct
+{
+ union
+ {
+ struct
+ {
+ volatile u32 ver;
+ volatile u32 val;
+ };
+ u64 data;
+ };
+} sbr_index_node;
+
+typedef struct
+{
+ volatile u32 head;
+ i8 cache_space[124];
+ volatile u32 tail;
+ u32 num;
+ u32 mask;
+ sbr_index_node nodes[0];
+} sbr_index_ring;
+
+sbr_index_ring *sbr_create_index_ring (u32 num);
+int sbr_index_ring_enqueue (sbr_index_ring * ring, i32 val);
+int sbr_index_ring_dequeue (sbr_index_ring * ring, i32 * val);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/sbr/sbr_protocol_api.h b/stacks/lwip_stack/src/sbr/sbr_protocol_api.h
new file mode 100644
index 0000000..1c0fb1e
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/sbr_protocol_api.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 SBR_PROTOCOL_API_H
+#define SBR_PROTOCOL_API_H
+#include <sys/uio.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include "sbr_err.h"
+#include "nsfw_msg_api.h"
+#include "nsfw_mt_config.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#ifndef SBR_MAX_INTEGER
+#define SBR_MAX_INTEGER 0x7FFFFFFF
+#endif
+
+#ifndef socklen_t
+#define socklen_t u32
+#endif
+
+#define SBR_MAX_FD_NUM MAX_SOCKET_NUM
+
+typedef struct sbr_socket_s sbr_socket_t;
+typedef struct
+{
+ int (*socket) (sbr_socket_t *, int, int, int);
+ int (*bind) (sbr_socket_t *, const struct sockaddr *, socklen_t);
+ int (*listen) (sbr_socket_t *, int);
+ int (*accept) (sbr_socket_t *, sbr_socket_t *, struct sockaddr *,
+ socklen_t *);
+ int (*accept4) (sbr_socket_t *, sbr_socket_t *, struct sockaddr *,
+ socklen_t *, int);
+ int (*connect) (sbr_socket_t *, const struct sockaddr *, socklen_t);
+ int (*shutdown) (sbr_socket_t *, int);
+ int (*getsockname) (sbr_socket_t *, struct sockaddr *, socklen_t *);
+ int (*getpeername) (sbr_socket_t *, struct sockaddr *, socklen_t *);
+ int (*getsockopt) (sbr_socket_t *, int, int, void *, socklen_t *);
+ int (*setsockopt) (sbr_socket_t *, int, int, const void *, socklen_t);
+ int (*recvfrom) (sbr_socket_t *, void *, size_t, int, struct sockaddr *,
+ socklen_t *);
+ int (*readv) (sbr_socket_t *, const struct iovec *, int);
+ int (*recvmsg) (sbr_socket_t *, struct msghdr *, int);
+ int (*send) (sbr_socket_t *, const void *, size_t, int);
+ int (*sendto) (sbr_socket_t *, const void *, size_t, int,
+ const struct sockaddr *, socklen_t);
+ int (*sendmsg) (sbr_socket_t *, const struct msghdr *, int);
+ int (*writev) (sbr_socket_t *, const struct iovec *, int);
+ int (*fcntl) (sbr_socket_t *, int, long);
+ int (*ioctl) (sbr_socket_t *, unsigned long, void *);
+ int (*close) (sbr_socket_t *);
+ int (*peak) (sbr_socket_t *);
+ void (*lock_common) (sbr_socket_t *);
+ void (*unlock_common) (sbr_socket_t *);
+ unsigned int (*ep_ctl) (sbr_socket_t *, int triggle_ops,
+ struct epoll_event * event, void *pdata);
+ unsigned int (*ep_getevt) (sbr_socket_t *, unsigned int events);
+ void (*set_app_info) (sbr_socket_t *, void *appinfo);
+ void (*set_close_stat) (sbr_socket_t *, int flag);
+} sbr_fdopt;
+
+struct sbr_socket_s
+{
+ int fd;
+ sbr_fdopt *fdopt;
+ void *stack_obj;
+ void *sk_obj;
+};
+
+int sbr_init_protocol ();
+
+sbr_fdopt *sbr_get_fdopt (int domain, int type, int protocol);
+void sbr_app_touch_in (void); /*app send its version info to nStackMain */
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/sbr/sbr_res_mgr.c b/stacks/lwip_stack/src/sbr/sbr_res_mgr.c
new file mode 100644
index 0000000..f40f101
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/sbr_res_mgr.c
@@ -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.
+*/
+
+#include "nstack_securec.h"
+#include "sbr_res_mgr.h"
+
+sbr_res_group g_res_group = { };
+
+/*****************************************************************************
+* Prototype : sbr_init_sk
+* Description : init sock pool
+* Input : None
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int
+sbr_init_sk ()
+{
+ sbr_index_ring *ring = sbr_create_index_ring (SBR_MAX_FD_NUM - 1);
+
+ if (!ring)
+ {
+ NSSBR_LOGERR ("init ring failed");
+ return -1;
+ }
+
+ int i;
+ /*the queue can't accept value=0, so i begin with 1 */
+ for (i = 1; i <= SBR_MAX_FD_NUM; ++i)
+ {
+ g_res_group.sk[i].fd = i;
+ if (sbr_index_ring_enqueue (ring, i) != 1)
+ {
+ NSSBR_LOGERR ("sbr_index_ring_enqueue failed, this can not happen");
+ free (ring);
+ return -1;
+ }
+ }
+
+ g_res_group.sk_ring = ring;
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_res
+* Description : init sbr res
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_init_res ()
+{
+ if (sbr_init_sk () != 0)
+ {
+ return -1;
+ }
+
+ NSSBR_LOGDBG ("init socket ok");
+
+ if (sbr_init_protocol () != 0)
+ {
+ return -1;
+ }
+
+ NSSBR_LOGDBG ("init protocol ok");
+
+ return 0;
+}
diff --git a/stacks/lwip_stack/src/sbr/sbr_res_mgr.h b/stacks/lwip_stack/src/sbr/sbr_res_mgr.h
new file mode 100644
index 0000000..54729d4
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/sbr_res_mgr.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 SBR_RES_MGR_H
+#define SBR_RES_MGR_H
+#include "sbr_protocol_api.h"
+#include "sbr_index_ring.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef struct
+{
+ sbr_index_ring *sk_ring;
+ sbr_socket_t sk[SBR_MAX_FD_NUM + 1]; /* unuse index 0 */
+} sbr_res_group;
+
+extern sbr_res_group g_res_group;
+
+/*****************************************************************************
+* Prototype : sbr_malloc_sk
+* Description : malloc sock
+* Input : None
+* Output : None
+* Return Value : static inline sbr_socket_t *
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline sbr_socket_t *
+sbr_malloc_sk ()
+{
+ int fd;
+
+ if (sbr_index_ring_dequeue (g_res_group.sk_ring, &fd) != 1)
+ {
+ NSSBR_LOGERR ("malloc sk failed]");
+ sbr_set_errno (EMFILE);
+ return NULL;
+ }
+
+ NSSBR_LOGDBG ("malloc sk ok]fd=%d", fd);
+ return &g_res_group.sk[fd];
+}
+
+/*****************************************************************************
+* Prototype : sbr_free_sk
+* Description : free sock
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+sbr_free_sk (sbr_socket_t * sk)
+{
+ sk->fdopt = NULL;
+ sk->sk_obj = NULL;
+ sk->stack_obj = NULL;
+
+ if (sbr_index_ring_enqueue (g_res_group.sk_ring, sk->fd) != 1)
+ {
+ NSSBR_LOGERR ("sbr_index_ring_enqueue failed, this can not happen");
+ }
+
+ NSSBR_LOGDBG ("free sk ok]fd=%d", sk->fd);
+}
+
+/*****************************************************************************
+* Prototype : sbr_lookup_sk
+* Description : lookup socket
+* Input : int fd
+* Output : None
+* Return Value : static inline sbr_socket_t *
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline sbr_socket_t *
+sbr_lookup_sk (int fd)
+{
+ if ((fd < 1) || (fd > SBR_MAX_FD_NUM))
+ {
+ NSSBR_LOGERR ("fd is not ok]fd=%d", fd);
+ sbr_set_errno (EBADF);
+ return NULL;
+ }
+
+ sbr_socket_t *sk = &g_res_group.sk[fd];
+ if (!sk->sk_obj || !sk->stack_obj)
+ {
+ NSSBR_LOGERR
+ ("data in sk is error, this can not happen]fd=%d,sk_obj=%p,stack_obj=%p",
+ fd, sk->sk_obj, sk->stack_obj);
+ sbr_set_errno (EBADF);
+ return NULL;
+ }
+
+ return sk;
+}
+
+int sbr_init_res ();
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/src/sbr/sbr_socket.c b/stacks/lwip_stack/src/sbr/sbr_socket.c
new file mode 100644
index 0000000..47aefda
--- /dev/null
+++ b/stacks/lwip_stack/src/sbr/sbr_socket.c
@@ -0,0 +1,1231 @@
+/*
+*
+* 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 <dlfcn.h>
+#include "sbr_protocol_api.h"
+#include "sbr_res_mgr.h"
+#include "nstack_log.h"
+#include "nstack_dmm_api.h"
+
+#define SBR_INTERCEPT(ret, name, args) ret sbr_ ## name args
+#define CALL_SBR_INTERCEPT(name, args) sbr_ ## name args
+#define GET_SBR_INTERCEPT(name) sbr_ ## name
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : create socket
+* Input : int
+* socket
+* (int domain
+* int type
+* int protocol)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, socket, (int domain, int type, int protocol))
+{
+ NSSBR_LOGDBG ("socket]domain=%d,type=%d,protocol=%d", domain, type,
+ protocol);
+ sbr_fdopt *fdopt = sbr_get_fdopt (domain, type, protocol);
+
+ if (!fdopt)
+ {
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_malloc_sk ();
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sk->fdopt = fdopt;
+
+ int ret = sk->fdopt->socket (sk, domain, type, protocol);
+
+ if (ret != 0)
+ {
+ sbr_free_sk (sk);
+ return ret;
+ }
+
+ return sk->fd;
+}
+
+/*****************************************************************************
+* Prototype : sbr_check_addr
+* Description : check addr
+* Input : int s
+* struct sockaddr * addr
+* socklen_t * addrlen
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_check_addr (int s, struct sockaddr *addr, socklen_t * addrlen)
+{
+ if (addr)
+ {
+ if (!addrlen)
+ {
+ NSSBR_LOGERR ("addrlen is null]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ if (0 > (int) (*addrlen))
+ {
+ NSSBR_LOGERR ("addrlen is negative]fd=%d,addrlen=%d", s, *addrlen);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : accept4
+* Input : int
+* accept4
+* (int s
+* struct sockaddr * addr
+* socklen_t * addrlen
+* int flags)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, accept4,
+ (int s, struct sockaddr * addr, socklen_t * addrlen,
+ int flags))
+{
+ NSSBR_LOGDBG ("accept4]fd=%d,addr=%p,addrlen=%p,flags=%d", s, addr, addrlen,
+ flags);
+ int ret = sbr_check_addr (s, addr, addrlen);
+
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sbr_socket_t *new_sk = sbr_malloc_sk ();
+ if (!new_sk)
+ {
+ return -1;
+ }
+
+ new_sk->fdopt = sk->fdopt;
+
+ ret = sk->fdopt->accept4 (sk, new_sk, addr, addrlen, flags);
+ if (-1 == ret)
+ {
+ sbr_free_sk (new_sk);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : accept
+* Input : int
+* accept
+* (int s
+* struct sockaddr * addr
+* socklen_t * addrlen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, accept,
+ (int s, struct sockaddr * addr, socklen_t * addrlen))
+{
+ NSSBR_LOGDBG ("accept]fd=%d,addr=%p,addrlen=%p", s, addr, addrlen);
+ int ret = sbr_check_addr (s, addr, addrlen);
+
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sbr_socket_t *new_sk = sbr_malloc_sk ();
+ if (!new_sk)
+ {
+ return -1;
+ }
+
+ new_sk->fdopt = sk->fdopt;
+
+ ret = sk->fdopt->accept (sk, new_sk, addr, addrlen);
+ if (-1 == ret)
+ {
+ sbr_free_sk (new_sk);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : bind
+* Input : int
+* bind
+* (int s
+* const struct sockaddr * name
+* socklen_t namelen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, bind,
+ (int s, const struct sockaddr * name, socklen_t namelen))
+{
+ NSSBR_LOGDBG ("bind]fd=%d,name=%p,namelen=%d", s, name, namelen);
+ if (!name)
+ {
+ NSSBR_LOGERR ("name is not ok]fd=%d,name=%p", s, name);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ if ((name->sa_family) != AF_INET)
+ {
+ NSSBR_LOGERR ("domain is not AF_INET]fd=%d,name->sa_family=%u", s,
+ name->sa_family);
+ sbr_set_errno (EAFNOSUPPORT);
+ return -1;
+ }
+
+ if (namelen != sizeof (struct sockaddr_in))
+ {
+ NSSBR_LOGERR ("namelen is invalid]fd=%d,namelen=%d", s, namelen);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->bind (sk, name, namelen);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : listen
+* Input : int
+* listen
+* (int s
+* int backlog)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, listen, (int s, int backlog))
+{
+ NSSBR_LOGDBG ("listen]fd=%d,backlog=%d", s, backlog);
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ /* limit the "backlog" parameter to fit in an u8_t */
+ if (backlog < 0)
+ {
+ backlog = 0;
+ }
+
+ if (backlog > 0xff)
+ {
+ backlog = 0xff;
+ }
+
+ return sk->fdopt->listen (sk, backlog);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : connect
+* Input : int
+* connect
+* (int s
+* const struct sockaddr * name
+* socklen_t namelen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, connect,
+ (int s, const struct sockaddr * name, socklen_t namelen))
+{
+ NSSBR_LOGDBG ("connect]fd=%d,name=%p,namelen=%d", s, name, namelen);
+ if (!name)
+ {
+ NSSBR_LOGERR ("name is null]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ if (!
+ (namelen == sizeof (struct sockaddr_in)
+ && (name->sa_family == AF_INET)))
+ {
+ NSSBR_LOGERR ("parameter invalid]fd=%d,domain=%u,namelen=%d", s,
+ name->sa_family, namelen);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ NSSBR_LOGERR ("get socket failed]fd=%d", s);
+ return -1;
+ }
+
+ return sk->fdopt->connect (sk, name, namelen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_check_sock_name
+* Description : check name
+* Input : int s
+* struct sockaddr * name
+* socklen_t * namelen
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_check_sock_name (int s, struct sockaddr *name, socklen_t * namelen)
+{
+ if (!name || !namelen)
+ {
+ NSSBR_LOGERR ("name or namelen is null]fd=%d", s);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ if (*namelen & 0x80000000)
+ {
+ NSSBR_LOGERR ("namelen is not ok]fd=%d,namelen=%d", s, *namelen);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : getpeername
+* Input : int
+* getpeername
+* (int s
+* struct sockaddr * name
+* socklen_t * namelen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, getpeername,
+ (int s, struct sockaddr * name, socklen_t * namelen))
+{
+ NSSBR_LOGDBG ("getpeername]fd=%d", s);
+ int ret = sbr_check_sock_name (s, name, namelen);
+
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sk->fdopt->lock_common (sk);
+ ret = sk->fdopt->getpeername (sk, name, namelen);
+ sk->fdopt->unlock_common (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : getsockname
+* Input : int
+* getsockname
+* (int s
+* struct sockaddr * name
+* socklen_t * namelen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, getsockname,
+ (int s, struct sockaddr * name, socklen_t * namelen))
+{
+ NSSBR_LOGDBG ("getsockname]fd=%d", s);
+ int ret = sbr_check_sock_name (s, name, namelen);
+
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sk->fdopt->lock_common (sk);
+ ret = sk->fdopt->getsockname (sk, name, namelen);
+ sk->fdopt->unlock_common (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : setsockopt
+* Input : int
+* setsockopt
+* (int s
+* int level
+* int optname
+* const void * optval
+* socklen_t optlen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, setsockopt,
+ (int s, int level, int optname, const void *optval,
+ socklen_t optlen))
+{
+ NSSBR_LOGDBG ("setsockopt]fd=%d,level=%d,optname=%d,optval=%p,optlen=%d", s,
+ level, optname, optval, optlen);
+ if (!optval)
+ {
+ NSSBR_LOGERR ("optval is null]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sk->fdopt->lock_common (sk);
+ int ret = sk->fdopt->setsockopt (sk, level, optname, optval, optlen);
+ sk->fdopt->unlock_common (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : getsockopt
+* Input : int
+* getsockopt
+* (int s
+* int level
+* int optname
+* void * optval
+* socklen_t * optlen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, getsockopt,
+ (int s, int level, int optname, void *optval,
+ socklen_t * optlen))
+{
+ NSSBR_LOGDBG ("getsockopt]fd=%d,level=%d,optname=%d,optval=%p,optlen=%p", s,
+ level, optname, optval, optlen);
+ if (!optval || !optlen)
+ {
+ NSSBR_LOGERR ("optval or optlen is NULL]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sk->fdopt->lock_common (sk);
+ int ret = sk->fdopt->getsockopt (sk, level, optname, optval, optlen);
+ sk->fdopt->unlock_common (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : ioctl
+* Input : int
+* ioctl
+* (int s
+* unsigned long cmd
+* ...)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, ioctl, (int s, unsigned long cmd, ...))
+{
+ NSSBR_LOGDBG ("ioctl]fd=%d,cmd=%lu", s, cmd);
+ va_list va;
+ va_start (va, cmd);
+ void *arg = va_arg (va, void *);
+ va_end (va);
+
+ if (!arg)
+ {
+ NSSBR_LOGERR ("parameter is not ok]fd=%d", s);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sk->fdopt->lock_common (sk);
+ int ret = sk->fdopt->ioctl (sk, cmd, arg);
+ sk->fdopt->unlock_common (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : fcntl
+* Input : int
+* fcntl
+* (int s
+* int cmd
+* ...)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, fcntl, (int s, int cmd, ...))
+{
+ NSSBR_LOGDBG ("fcntl]fd=%d,cmd=%d", s, cmd);
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ va_list va;
+ va_start (va, cmd);
+ long arg = va_arg (va, long);
+ va_end (va);
+
+ sk->fdopt->lock_common (sk);
+ int ret = sk->fdopt->fcntl (sk, cmd, arg);
+ sk->fdopt->unlock_common (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : recvfrom
+* Input : int
+* recvfrom
+* (int s
+* void * mem
+* size_t len
+* int flags
+* struct sockaddr * from
+* socklen_t * fromlen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, recvfrom,
+ (int s, void *mem, size_t len, int flags,
+ struct sockaddr * from, socklen_t * fromlen))
+{
+ NSSBR_LOGDBG ("recvfrom]fd=%d,mem=%p,len=%d,flags=%d,from=%p,fromlen=%p", s,
+ mem, len, flags, from, fromlen);
+
+ if (0 == len)
+ {
+ NSSBR_LOGDBG ("len is zero]fd=%d,len=%u", s, (u32) len);
+ return 0; //return directly, don't change the last errno.
+ }
+
+ if (!mem)
+ {
+ NSSBR_LOGERR ("mem is NULL]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ if (fromlen && (*((int *) fromlen) < 0))
+ {
+ NSSBR_LOGERR ("fromlen is not ok]fd=%d,fromlen=%d", s, *fromlen);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->recvfrom (sk, mem, len, flags, from, fromlen);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : read
+* Input : int
+* read
+* (int s
+* void * mem
+* size_t len)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, read, (int s, void *mem, size_t len))
+{
+ NSSBR_LOGDBG ("read]fd=%d,mem=%p,len=%d", s, mem, len);
+ return CALL_SBR_INTERCEPT (recvfrom, (s, mem, len, 0, NULL, NULL));
+}
+
+/*****************************************************************************
+* Prototype : sbr_check_iov
+* Description : check iov
+* Input : int s
+* const struct iovec * iov
+* int iovcnt
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_check_iov (int s, const struct iovec *iov, int iovcnt)
+{
+ if ((!iov) || (iovcnt <= 0))
+ {
+ NSSBR_LOGERR ("iov is NULL or iovcn <=0]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ int i;
+ for (i = 0; i < iovcnt; ++i)
+ {
+ if (!iov[i].iov_base && (iov[i].iov_len != 0))
+ {
+ NSSBR_LOGERR ("iov is not ok]fd=%d,iov_base=%p,iov_len=%d", s,
+ iov[i].iov_base, iov[i].iov_len);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : readv
+* Input : int
+* readv
+* (int s
+* const struct iovec * iov
+* int iovcnt)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, readv, (int s, const struct iovec * iov, int iovcnt))
+{
+ NSSBR_LOGDBG ("readv]fd=%d,iov=%p,iovcnt=%d", s, iov, iovcnt);
+
+ if (sbr_check_iov (s, iov, iovcnt) != 0)
+ {
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->readv (sk, iov, iovcnt);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : recv
+* Input : int
+* recv
+* (int s
+* void * mem
+* size_t len
+* int flags)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, recv, (int s, void *mem, size_t len, int flags))
+{
+ NSSBR_LOGDBG ("recv]fd=%d,mem=%p,len=%d,flags=%d", s, mem, len, flags);
+ return CALL_SBR_INTERCEPT (recvfrom, (s, mem, len, flags, NULL, NULL));
+}
+
+/*****************************************************************************
+* Prototype : sbr_check_msg
+* Description : check msg
+* Input : int s
+* const struct msghdr * msg
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_check_msg (int s, const struct msghdr *msg)
+{
+ if (!msg)
+ {
+ NSSBR_LOGERR ("msg is NULL]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ if (msg->msg_name && ((int) msg->msg_namelen < 0))
+ {
+ NSSBR_LOGERR ("msg_namelen is not ok]fd=%d,msg_namelen=%d", s,
+ msg->msg_namelen);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ return sbr_check_iov (s, msg->msg_iov, msg->msg_iovlen);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : recvmsg
+* Input : int
+* recvmsg
+* (int s
+* struct msghdr * msg
+* int flags)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, recvmsg, (int s, struct msghdr * msg, int flags))
+{
+ NSSBR_LOGDBG ("recvmsg]fd=%d,msg=%p,flags=%d", s, msg, flags);
+
+ if (sbr_check_msg (s, msg) != 0)
+ {
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->recvmsg (sk, msg, flags);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : send
+* Input : int
+* send
+* (int s
+* const void * data
+* size_t size
+* int flags)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, send, (int s, const void *data, size_t size, int flags))
+{
+ NSSBR_LOGDBG ("send]fd=%d,data=%p,size=%zu,flags=%d", s, data, size, flags);
+ if (!data)
+ {
+ NSSBR_LOGERR ("data is NULL]fd=%d", s);
+ sbr_set_errno (EFAULT);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->send (sk, data, size, flags);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : sendmsg
+* Input : int
+* sendmsg
+* (int s
+* const struct msghdr * msg
+* int flags)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, sendmsg, (int s, const struct msghdr * msg, int flags))
+{
+ NSSBR_LOGDBG ("sendmsg]fd=%d,msg=%p,flags=%d", s, msg, flags);
+
+ if (sbr_check_msg (s, msg) != 0)
+ {
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->sendmsg (sk, msg, flags);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : sendto
+* Input : int
+* sendto
+* (int s
+* const void * data
+* size_t size
+* int flags
+* const struct sockaddr * to
+* socklen_t tolen)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, sendto,
+ (int s, const void *data, size_t size, int flags,
+ const struct sockaddr * to, socklen_t tolen))
+{
+ NSSBR_LOGDBG ("sendto]fd=%d,data=%p,size=%zu,flags=%d,to=%p,tolen=%d", s,
+ data, size, flags, to, tolen);
+ if ((data == NULL) || (flags < 0))
+ {
+ NSSBR_LOGERR ("parameter is not ok]fd=%d,data=%p,size=%zu,flags=%d", s,
+ data, size, flags);
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->sendto (sk, data, size, flags, to, tolen);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : write
+* Input : int
+* write
+* (int s
+* const void * data
+* size_t size)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, write, (int s, const void *data, size_t size))
+{
+ NSSBR_LOGDBG ("write]fd=%d,data=%p,size=%zu", s, data, size);
+ return CALL_SBR_INTERCEPT (send, (s, data, size, 0));
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : writev
+* Input : int
+* writev
+* (int s
+* const struct iovec * iov
+* int iovcnt)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, writev, (int s, const struct iovec * iov, int iovcnt))
+{
+ NSSBR_LOGDBG ("writev]fd=%d,iov=%p,iovcnt=%d", s, iov, iovcnt);
+
+ if (sbr_check_iov (s, iov, iovcnt) != 0)
+ {
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->writev (sk, iov, iovcnt);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : shutdown
+* Input : int
+* shutdown
+* (int s
+* int how)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, shutdown, (int s, int how))
+{
+ NSSBR_LOGDBG ("shutdown]fd=%d,how=%d", s, how);
+ if ((how != SHUT_RD) && (how != SHUT_WR) && (how != SHUT_RDWR))
+ {
+ sbr_set_errno (EINVAL);
+ return -1;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ sk->fdopt->lock_common (sk);
+ int ret = sk->fdopt->shutdown (sk, how);
+ sk->fdopt->unlock_common (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : close
+* Input : int
+* close
+* (int s)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (int, close, (int s))
+{
+ NSSBR_LOGDBG ("close]fd=%d", s);
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ int ret = sk->fdopt->close (sk);
+ sbr_free_sk (sk);
+ return ret;
+}
+
+SBR_INTERCEPT (int, select,
+ (int nfds, fd_set * readfd, fd_set * writefd,
+ fd_set * exceptfd, struct timeval * timeout))
+{
+ return -1;
+}
+
+SBR_INTERCEPT (unsigned int, ep_getevt,
+ (int epfd, int profd, unsigned int events))
+{
+ NSSBR_LOGDBG ("epfd= %d, proFD=%d,epi=0x%x", epfd, profd, events);
+ sbr_socket_t *sk = sbr_lookup_sk (profd);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->ep_getevt (sk, events);
+}
+
+SBR_INTERCEPT (unsigned int, ep_ctl,
+ (int epfd, int profd, int triggle_ops,
+ struct epoll_event * event, void *pdata))
+{
+ NSSBR_LOGDBG ("epfd = %d, proFD=%d,triggle_ops=%d,pdata=%p", epfd, profd,
+ triggle_ops, pdata);
+ sbr_socket_t *sk = sbr_lookup_sk (profd);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->ep_ctl (sk, triggle_ops, event, pdata);
+}
+
+SBR_INTERCEPT (int, peak, (int s))
+{
+ NSSBR_LOGDBG ("]fd=%d", s);
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return -1;
+ }
+
+ return sk->fdopt->peak (sk);
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : set_app_info
+* Input : int
+* set_app_info
+* (int s
+* void* app_info)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (void, set_app_info, (int s, void *app_info))
+{
+ NSSBR_LOGDBG ("set_app_info]fd=%d", s);
+
+ if (!app_info)
+ {
+ NSSBR_LOGERR ("invalid param, app_info is NULL]");
+ return;
+ }
+
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+ if (!sk)
+ {
+ return;
+ }
+
+ sk->fdopt->set_app_info (sk, app_info);
+}
+
+/* app send its version info to nStackMain */
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : sbr_app_touch
+* Input : int
+* sbr_app_touch
+* ()
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (void, app_touch, (void))
+{
+ NSSBR_LOGDBG ("sbr_app_touch() is called]");
+
+ sbr_app_touch_in ();
+}
+
+/*****************************************************************************
+* Prototype : SBR_INTERCEPT
+* Description : set_close_status
+* Input : void
+* set_close_stat
+* (int s
+* int flag)
+* Output : None
+* Return Value :
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+SBR_INTERCEPT (void, set_close_stat, (int s, int flag))
+{
+ NSSBR_LOGDBG ("]fd=%d", s);
+ sbr_socket_t *sk = sbr_lookup_sk (s);
+
+ if (!sk)
+ {
+ return;
+ }
+ if (sk->fdopt->set_close_stat)
+ {
+ sk->fdopt->set_close_stat (sk, flag);
+ }
+
+}
+
+SBR_INTERCEPT (int, fd_alloc, ())
+{
+ return sbr_socket (AF_INET, SOCK_STREAM, 0);
+}
+
+/*****************************************************************************
+* Prototype : nstack_stack_register
+* Description : reg api to nsocket
+* Input : nstack_socket_ops* ops
+* nstack_event_ops *val
+* nstack_proc_ops *deal
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+nstack_stack_register (nstack_proc_cb * ops, nstack_event_cb * val)
+{
+ if (!ops || !val || !val->handle)
+ {
+ return -1;
+ }
+
+#undef NSTACK_MK_DECL
+#define NSTACK_MK_DECL(ret, fn, args) \
+ (ops->socket_ops).pf ## fn = (typeof(((nstack_socket_ops*)0)->pf ## fn))dlsym(val->handle, "sbr_" # fn);
+#include "declare_syscalls.h"
+
+ (ops->extern_ops).module_init = sbr_init_res;
+ (ops->extern_ops).ep_getevt = GET_SBR_INTERCEPT (ep_getevt);
+ (ops->extern_ops).ep_ctl = GET_SBR_INTERCEPT (ep_ctl);
+ (ops->extern_ops).peak = GET_SBR_INTERCEPT (peak);
+ (ops->extern_ops).stack_alloc_fd = GET_SBR_INTERCEPT (fd_alloc); /*alloc a fd id for epoll */
+ return 0;
+}
diff --git a/stacks/lwip_stack/src/tools/CMakeLists.txt b/stacks/lwip_stack/src/tools/CMakeLists.txt
new file mode 100644
index 0000000..bd485b8
--- /dev/null
+++ b/stacks/lwip_stack/src/tools/CMakeLists.txt
@@ -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.
+#########################################################################
+
+FILE(GLOB_RECURSE Tcpdump *.c)
+ADD_LIBRARY(nTcpdump STATIC ${Tcpdump})
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_LIST_DIR}/../include
+)
+TARGET_LINK_LIBRARIES(nTcpdump dmm_api) \ No newline at end of file
diff --git a/stacks/lwip_stack/src/tools/dump_tool.c b/stacks/lwip_stack/src/tools/dump_tool.c
new file mode 100644
index 0000000..53f0e44
--- /dev/null
+++ b/stacks/lwip_stack/src/tools/dump_tool.c
@@ -0,0 +1,622 @@
+/*
+*
+* 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 <arpa/inet.h>
+
+#include "nsfw_init.h"
+#include "nsfw_maintain_api.h"
+#include "nsfw_mem_api.h"
+#include "nsfw_fd_timer_api.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+
+#include "dump_tool.h"
+#include "nstack_dmm_adpt.h"
+
+NSTACK_STATIC u32 g_dump_task_mask = 0;
+NSTACK_STATIC dump_task_info g_dump_task[MAX_DUMP_TASK];
+static dump_timer_info g_dump_timer;
+
+static nsfw_mem_name g_dump_mem_ring_info =
+ { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_RIGN_NAME };
+static nsfw_mem_name g_dump_mem_pool_info =
+ { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_POOL_NAME };
+
+NSTACK_STATIC inline void
+dump_task_init (dump_task_info * task)
+{
+ task->task_state = 0;
+ task->task_id = -1;
+ task->task_keep_time = 0;
+ task->task_pool = NULL;
+ task->task_queue = NULL;
+}
+
+NSTACK_STATIC inline void
+clear_dump_task ()
+{
+ int i = 0;
+ for (; i < MAX_DUMP_TASK; i++)
+ {
+ dump_task_init (&g_dump_task[i]);
+ }
+}
+
+NSTACK_STATIC i16
+get_dump_task (nsfw_tool_dump_msg * req)
+{
+ // base version just support 1 dump task
+ if (req->task_keep_time > MAX_DUMP_TIME
+ || req->task_keep_time < MIN_DUMP_TIME)
+ {
+ NSPOL_DUMP_LOGERR ("task keep time invalid] time=%u.",
+ req->task_keep_time);
+ return -1;
+ }
+
+ if (1 == g_dump_task[0].task_state)
+ {
+ NSPOL_DUMP_LOGERR
+ ("start tcpdump task failed, task still in work state] task id=%d.",
+ 0);
+ return -1;
+ }
+
+ struct timespec cur_time;
+ GET_CUR_TIME (&cur_time); /*do not need return value */
+ g_dump_task[0].task_start_sec = cur_time.tv_sec;
+ g_dump_task[0].last_hbt_sec = cur_time.tv_sec;
+
+ g_dump_task[0].task_state = 1;
+ g_dump_task[0].task_id = 0;
+ g_dump_task[0].task_keep_time = req->task_keep_time;
+
+ g_dump_task_mask |= (1 << g_dump_task[0].task_id);
+ NSPOL_DUMP_LOGINF ("start tcpdump task success] task id=%d.", 0);
+ return 0;
+}
+
+NSTACK_STATIC i16
+close_dump_task (i16 task_id)
+{
+ if (task_id < 0 || task_id >= MAX_DUMP_TASK)
+ {
+ NSPOL_DUMP_LOGERR
+ ("receive invalid task id in close dump task req] task id=%d.",
+ task_id);
+ return -1;
+ }
+
+ g_dump_task[task_id].task_state = 0;
+
+ g_dump_task_mask &= ~(1 << task_id);
+
+ NSPOL_DUMP_LOGINF ("stop tcpdump task success] task id=%d.", 0);
+
+ return task_id;
+}
+
+NSTACK_STATIC void
+stop_expired_task (int idx, u32 now_sec)
+{
+ dump_task_info *ptask = &g_dump_task[idx];
+ if (0 == ptask->task_state)
+ {
+ return;
+ }
+
+ if (now_sec - ptask->task_start_sec > ptask->task_keep_time)
+ {
+ NSPOL_DUMP_LOGERR
+ ("stop dump task because task time expired] task id=%d, now_sec=%u, task start time=%u, dump time=%u.",
+ ptask->task_id, now_sec, ptask->task_start_sec,
+ ptask->task_keep_time);
+ close_dump_task (ptask->task_id);
+ return;
+ }
+
+ if (now_sec - ptask->last_hbt_sec > DUMP_TASK_HBT_TIME_OUT)
+ {
+ NSPOL_DUMP_LOGERR
+ ("stop dump task because heart beat time out] task id=%d, now_sec=%u, last hbt time=%u, hbt timeout=%u.",
+ ptask->task_id, now_sec, ptask->last_hbt_sec,
+ DUMP_TASK_HBT_TIME_OUT);
+ close_dump_task (ptask->task_id);
+ }
+
+ return;
+}
+
+NSTACK_STATIC inline bool
+check_dump_alive (u32 timer_type, void *data)
+{
+ dump_timer_info *ptimer_info = (dump_timer_info *) data;
+
+ struct timespec cur_time;
+ GET_CUR_TIME (&cur_time); /*do not need return value */
+
+ int i = 0;
+ for (; i < MAX_DUMP_TASK; i++)
+ {
+ stop_expired_task (i, cur_time.tv_sec);
+ }
+
+ ptimer_info->ptimer =
+ nsfw_timer_reg_timer (1, ptimer_info, check_dump_alive,
+ *(struct timespec *) (ptimer_info->interval));
+
+ return true;
+}
+
+NSTACK_STATIC bool
+dump_init_timer (dump_timer_info * ptimer_info)
+{
+ struct timespec *trigger_time =
+ (struct timespec *) malloc (sizeof (struct timespec));
+ if (NULL == trigger_time)
+ {
+ NSPOL_DUMP_LOGERR ("alloc memory for timer failed.");
+ return false;
+ }
+
+ trigger_time->tv_sec = DUMP_HBT_CHK_INTERVAL;
+ trigger_time->tv_nsec = 0;
+
+ ptimer_info->interval = trigger_time;
+ ptimer_info->ptimer =
+ nsfw_timer_reg_timer (1, ptimer_info, check_dump_alive, *trigger_time);
+ return true;
+}
+
+NSTACK_STATIC inline u32
+copy_limit_buf (char *dst_buf, int dst_buf_len, char *src_buf,
+ u32 src_buf_len, u32 limit_len)
+{
+ if (src_buf_len < limit_len)
+ {
+ NSPOL_DUMP_LOGERR ("message too short] len=%d", src_buf_len);
+ return 0;
+ }
+
+ if (EOK != MEMCPY_S (dst_buf, dst_buf_len, src_buf, limit_len))
+ {
+ NSPOL_DUMP_LOGERR ("MEMCPY_S failed");
+ return 0;
+ }
+
+ return limit_len;
+}
+
+NSTACK_STATIC inline u32
+get_packet_buf (char *dst_buf, int dst_buf_len, char *src_buf,
+ u32 src_buf_len, u32 eth_head_len)
+{
+#define TCP_BUF_LEN (eth_head_len + IP_HEAD_LEN + TCP_HEAD_LEN)
+#define UDP_BUF_LEN (eth_head_len + IP_HEAD_LEN + UDP_HEAD_LEN)
+#define ICMP_BUF_LEN (eth_head_len + IP_HEAD_LEN + ICMP_HEAD_LEN)
+
+ if (NULL == dst_buf || NULL == src_buf)
+ {
+ return 0;
+ }
+
+ struct ip_hdr *ip_head = (struct ip_hdr *) (src_buf + eth_head_len);
+ if (ip_head->_proto == IP_PROTO_TCP)
+ {
+ return copy_limit_buf (dst_buf, dst_buf_len, src_buf, src_buf_len,
+ TCP_BUF_LEN);
+ }
+
+ if (ip_head->_proto == IP_PROTO_UDP)
+ {
+ return copy_limit_buf (dst_buf, dst_buf_len, src_buf, src_buf_len,
+ UDP_BUF_LEN);
+ }
+
+ if (ip_head->_proto == IP_PROTO_ICMP)
+ {
+ return copy_limit_buf (dst_buf, dst_buf_len, src_buf, src_buf_len,
+ ICMP_BUF_LEN);
+ }
+
+ if (EOK != MEMCPY_S (dst_buf, dst_buf_len, src_buf, src_buf_len))
+ {
+ NSPOL_DUMP_LOGERR ("MEMCPY_S failed");
+ return 0;
+ }
+
+ return src_buf_len;
+}
+
+NSTACK_STATIC int
+pack_msg_inout (void *dump_buf, char *msg_buf, u32 len, u16 direction,
+ void *para)
+{
+ (void) para;
+ dump_msg_info *pmsg = (dump_msg_info *) dump_buf;
+ if (!pmsg)
+ {
+ return 0;
+ }
+
+ pmsg->direction = direction;
+ struct timeval cur_time;
+ gettimeofday (&cur_time, NULL);
+ pmsg->dump_sec = cur_time.tv_sec;
+ pmsg->dump_usec = cur_time.tv_usec;
+
+ /* msg content can not be captured */
+ u32 real_len =
+ get_packet_buf (pmsg->buf, DUMP_MSG_SIZE, msg_buf, len, ETH_HEAD_LEN);
+ if (0 == real_len)
+ {
+ return 0;
+ }
+
+ pmsg->len = real_len;
+
+ return 1;
+}
+
+NSTACK_STATIC int
+pack_msg_loop (void *dump_buf, char *msg_buf, u32 len, u16 direction,
+ void *para)
+{
+ dump_msg_info *pmsg = (dump_msg_info *) dump_buf;
+ if (!pmsg)
+ {
+ return 0;
+ }
+ pmsg->direction = direction;
+ struct timeval cur_time;
+ gettimeofday (&cur_time, NULL);
+ pmsg->dump_sec = cur_time.tv_sec;
+ pmsg->dump_usec = cur_time.tv_usec;
+
+ eth_head pack_eth_head;
+ int retVal =
+ MEMCPY_S (pack_eth_head.dest_mac, MAC_ADDR_LEN, para, MAC_ADDR_LEN);
+ if (EOK != retVal)
+ {
+ NSPOL_DUMP_LOGERR ("MEMCPY_S failed]retVal=%d", retVal);
+ return 0;
+ }
+ retVal = MEMCPY_S (pack_eth_head.src_mac, MAC_ADDR_LEN, para, MAC_ADDR_LEN);
+ if (EOK != retVal)
+ {
+ NSPOL_DUMP_LOGERR ("MEMCPY_S failed]retVal=%d", retVal);
+ return 0;
+ }
+ pack_eth_head.eth_type = htons (PROTOCOL_IP);
+
+ retVal =
+ MEMCPY_S (pmsg->buf, DUMP_MSG_SIZE, &pack_eth_head, sizeof (eth_head));
+ if (EOK != retVal)
+ {
+ NSPOL_DUMP_LOGERR ("MEMCPY_S failed]retVal=%d", retVal);
+ return 0;
+ }
+
+ u32 buf_len = DUMP_MSG_SIZE - ETH_HEAD_LEN;
+
+ /* msg content can not be captured- Begin */
+ u32 real_len =
+ get_packet_buf (pmsg->buf + ETH_HEAD_LEN, buf_len, msg_buf, len, 0);
+ if (0 == real_len)
+ {
+ return 0;
+ }
+
+ pmsg->len = real_len + ETH_HEAD_LEN;
+
+ return 1;
+}
+
+NSTACK_STATIC void
+dump_enqueue (int task_idx, void *buf, u32 len, u16 direction,
+ pack_msg_fun pack_msg, void *para)
+{
+ mring_handle queue = (mring_handle *) g_dump_task[task_idx].task_queue;
+ mring_handle pool = (mring_handle *) g_dump_task[task_idx].task_pool;
+
+ void *msg = NULL;
+
+ if (nsfw_mem_ring_dequeue (pool, &msg) <= 0)
+ {
+ // such log may be too much if queue is empty
+ NSPOL_DUMP_LOGDBG ("get msg node from mem pool failed] pool=%p.", pool);
+ return;
+ }
+
+ if (NULL == msg)
+ {
+ NSPOL_DUMP_LOGWAR ("get NULL msg node from mem pool] pool=%p.", pool);
+ return;
+ }
+
+ if (!pack_msg (msg, buf, len, direction, para))
+ {
+ NSPOL_DUMP_LOGWAR ("get dump msg failed");
+ return;
+ }
+
+ if (nsfw_mem_ring_enqueue (queue, msg) < 0)
+ {
+ NSPOL_DUMP_LOGWAR ("dump mem ring enqueue failed] ring=%p.", queue);
+ }
+
+ return;
+}
+
+NSTACK_STATIC inline bool
+dump_enabled ()
+{
+ return (0 != g_dump_task_mask);
+}
+
+void
+ntcpdump (void *buf, u32 buf_len, u16 direction)
+{
+ u32 i;
+ if (!dump_enabled ())
+ {
+ return;
+ }
+
+ /* fix Dead-code type Codedex issue here */
+ for (i = 0; i < MAX_DUMP_TASK; i++)
+ {
+ if (g_dump_task[i].task_state)
+ {
+ dump_enqueue (i, buf, buf_len, direction, pack_msg_inout, NULL);
+ }
+ }
+}
+
+void
+ntcpdump_loop (void *buf, u32 buf_len, u16 direction, void *eth_addr)
+{
+ u32 i;
+
+ if (!dump_enabled ())
+ {
+ return;
+ }
+
+ /* fix Dead-code type Codedex issue here */
+ for (i = 0; i < MAX_DUMP_TASK; i++)
+ {
+ if (g_dump_task[i].task_state)
+ {
+ dump_enqueue (i, buf, buf_len, direction, pack_msg_loop, eth_addr);
+ }
+ }
+}
+
+// called by nStackMain
+bool
+dump_create_pool ()
+{
+ nsfw_mem_sppool pool_info;
+ if (EOK !=
+ MEMCPY_S (&pool_info.stname, sizeof (nsfw_mem_name),
+ &g_dump_mem_pool_info, sizeof (nsfw_mem_name)))
+ {
+ NSPOL_DUMP_LOGERR ("create dump mem pool failed, MEMCPY_S failed.");
+ return false;
+ }
+
+ pool_info.usnum = DUMP_MSG_NUM;
+ pool_info.useltsize = DUMP_MSG_SIZE + sizeof (dump_msg_info);
+ pool_info.isocket_id = NSFW_SOCKET_ANY;
+ pool_info.enmptype = NSFW_MRING_MPSC;
+
+ mring_handle pool = nsfw_mem_sp_create (&pool_info);
+ if (NULL == pool)
+ {
+ NSPOL_DUMP_LOGERR ("create dump mem pool failed, pool create failed.");
+ return false;
+ }
+
+ g_dump_task[0].task_pool = pool;
+
+ NSPOL_DUMP_LOGINF ("dump pool create success] pool=%p.", pool);
+
+ return true;
+}
+
+bool
+dump_create_ring ()
+{
+ nsfw_mem_mring ring_info;
+ if (EOK !=
+ MEMCPY_S (&ring_info.stname, sizeof (nsfw_mem_name),
+ &g_dump_mem_ring_info, sizeof (nsfw_mem_name)))
+ {
+ NSPOL_DUMP_LOGERR ("create dump mem ring failed, MEMCPY_S failed.");
+ return false;
+ }
+
+ ring_info.usnum = DUMP_MSG_NUM;
+ ring_info.isocket_id = NSFW_SOCKET_ANY;
+ ring_info.enmptype = NSFW_MRING_MPSC;
+
+ mring_handle ring = nsfw_mem_ring_create (&ring_info);
+ if (NULL == ring)
+ {
+ NSPOL_DUMP_LOGERR ("create dump mem ring failed, ring create failed.");
+ return false;
+ }
+
+ g_dump_task[0].task_queue = ring;
+
+ NSPOL_DUMP_LOGINF ("dump ring create success] ring=%p.", ring);
+
+ return true;
+}
+
+NSTACK_STATIC int
+on_dump_tool_req (nsfw_mgr_msg * req)
+{
+ i16 task_id = 0;
+ if (!req)
+ {
+ return -1;
+ }
+ if (req->src_proc_type != NSFW_PROC_TOOLS)
+ {
+ NSPOL_DUMP_LOGDBG
+ ("dump module receive invaild message] module type=%u.",
+ req->src_proc_type);
+ return -1;
+ }
+
+ if (req->msg_type != MGR_MSG_TOOL_TCPDUMP_REQ)
+ {
+ NSPOL_DUMP_LOGDBG ("dump module receive invaild message] msg type=%u.",
+ req->msg_type);
+ return -1;
+ }
+
+ nsfw_tool_dump_msg *dump_msg_req = GET_USER_MSG (nsfw_tool_dump_msg, req);
+
+ switch (dump_msg_req->op_type)
+ {
+ case START_DUMP_REQ:
+ task_id = get_dump_task (dump_msg_req);
+ break;
+
+ case STOP_DUMP_REQ:
+ task_id = close_dump_task (dump_msg_req->task_id);
+ break;
+
+ default:
+ task_id = -1;
+ }
+
+ nsfw_mgr_msg *rsp = nsfw_mgr_rsp_msg_alloc (req);
+ if (NULL == rsp)
+ {
+ NSPOL_DUMP_LOGDBG ("alloc response for dump request failed.");
+ return -1;
+ }
+
+ nsfw_tool_dump_msg *dump_msg_rsp = GET_USER_MSG (nsfw_tool_dump_msg, rsp);
+ dump_msg_rsp->op_type = dump_msg_req->op_type + DUMP_MSG_TYPE_RSP;
+ dump_msg_rsp->task_id = task_id;
+
+ nsfw_mgr_send_msg (rsp);
+ nsfw_mgr_msg_free (rsp);
+ return 0;
+
+}
+
+NSTACK_STATIC int
+on_dump_hbt_req (nsfw_mgr_msg * req)
+{
+ if (!req)
+ {
+ return -1;
+ }
+ if (req->src_proc_type != NSFW_PROC_TOOLS)
+ {
+ NSPOL_DUMP_LOGDBG
+ ("dump module receive invaild message] module type=%u.",
+ req->src_proc_type);
+ return -1;
+ }
+
+ if (req->msg_type != MGR_MSG_TOOL_HEART_BEAT)
+ {
+ NSPOL_DUMP_LOGDBG ("dump module receive invaild message] msg type=%u.",
+ req->msg_type);
+ return -1;
+ }
+
+ nsfw_tool_hbt *dump_hbt_req = GET_USER_MSG (nsfw_tool_hbt, req);
+
+ i16 task_id = dump_hbt_req->task_id;
+ if (task_id < 0 || task_id >= MAX_DUMP_TASK)
+ {
+ NSPOL_DUMP_LOGERR ("dump heart beat with invalid task id] task id=%d.",
+ task_id);
+ return -1;
+ }
+
+ if (0 == g_dump_task[task_id].task_state)
+ {
+ NSPOL_DUMP_LOGDBG
+ ("dump module receive heart beat but task not enabled] task id=%d.",
+ task_id);
+ return 0;
+ }
+
+ struct timespec cur_time;
+ GET_CUR_TIME (&cur_time); /*no need return value */
+
+ // update task alive time
+ g_dump_task[task_id].last_hbt_seq = dump_hbt_req->seq;
+ g_dump_task[task_id].last_hbt_sec = cur_time.tv_sec;
+
+ return 0;
+}
+
+NSTACK_STATIC int dump_tool_init (void *param);
+NSTACK_STATIC int
+dump_tool_init (void *param)
+{
+ u32 proc_type = (u32) ((long long) param);
+ NSPOL_DUMP_LOGINF ("dump module init] proc type=%d", proc_type);
+
+ switch (proc_type)
+ {
+ case NSFW_PROC_MAIN:
+ nsfw_mgr_reg_msg_fun (MGR_MSG_TOOL_TCPDUMP_REQ, on_dump_tool_req);
+ nsfw_mgr_reg_msg_fun (MGR_MSG_TOOL_HEART_BEAT, on_dump_hbt_req);
+ break;
+ default:
+ NSPOL_DUMP_LOGERR ("dump init with unknow module] proc type=%d",
+ proc_type);
+ return -1;
+ }
+
+ clear_dump_task ();
+
+ if (!dump_create_ring ())
+ {
+ return -1;
+ }
+
+ if (!dump_create_pool ())
+ {
+ return -1;
+ }
+
+ if (!dump_init_timer (&g_dump_timer))
+ {
+ return -1;
+ }
+
+ NSPOL_DUMP_LOGINF ("dump module init success.");
+ return 0;
+}
+
+/* *INDENT-OFF* */
+NSFW_MODULE_NAME (TCPDUMP_MODULE)
+NSFW_MODULE_PRIORITY (10)
+NSFW_MODULE_DEPENDS (NSTACK_DMM_MODULE)
+NSFW_MODULE_INIT (dump_tool_init)
+/* *INDENT-ON* */
diff --git a/stacks/lwip_stack/src/tools/dump_tool.h b/stacks/lwip_stack/src/tools/dump_tool.h
new file mode 100644
index 0000000..8c32523
--- /dev/null
+++ b/stacks/lwip_stack/src/tools/dump_tool.h
@@ -0,0 +1,81 @@
+/*
+*
+* 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 _DUMP_TOOL_H_
+#define _DUMP_TOOL_H_
+
+#define IP_PROTO_ICMP 1
+#define IP_PROTO_IGMP 2
+#define IP_PROTO_UDP 17
+#define IP_PROTO_UDPLITE 136
+#define IP_PROTO_TCP 6
+
+#ifndef MAC_ADDR_LEN
+#define MAC_ADDR_LEN 6
+#endif
+
+#ifndef IP_HEAD_LEN
+#define IP_HEAD_LEN 20
+#endif
+#ifndef TCP_HEAD_LEN
+#define TCP_HEAD_LEN 20
+#endif
+#ifndef UDP_HEAD_LEN
+#define UDP_HEAD_LEN 8
+#endif
+
+#ifndef ICMP_HEAD_LEN
+#define ICMP_HEAD_LEN 8
+#endif
+
+typedef struct _dump_task_info
+{
+ u16 task_state; // 0:off, 1:on
+ i16 task_id;
+ u32 task_keep_time;
+ u32 task_start_sec;
+ u32 last_hbt_seq;
+ u32 last_hbt_sec;
+ void *task_queue;
+ void *task_pool;
+} dump_task_info;
+
+typedef struct _dump_eth_head
+{
+ u8 dest_mac[MAC_ADDR_LEN];
+ u8 src_mac[MAC_ADDR_LEN];
+ u16 eth_type;
+} eth_head;
+
+#define ETH_HEAD_LEN sizeof(eth_head)
+
+struct ip_hdr
+{
+ u16 _v_hl_tos;
+ u16 _len;
+ u16 _id;
+ u16 _offset;
+ u8 _ttl;
+ u8 _proto;
+ u16 _chksum;
+ u32 src;
+ u32 dest;
+};
+
+typedef int (*pack_msg_fun) (void *dump_buf, char *msg_buf, u32 len,
+ u16 direction, void *para);
+
+#endif