From 54f5a270c74c405d3bb0e15d5b69d6d0e1e96c49 Mon Sep 17 00:00:00 2001 From: "satish.karunanithi" Date: Mon, 13 Aug 2018 19:39:55 +0530 Subject: Feat : LWIP integration part3 Change-Id: I62998963da110827a410287eed90a22da7ae4222 Signed-off-by: satish.karunanithi --- stacks/lwip_stack/src/CMakeLists.txt | 62 + stacks/lwip_stack/src/alarm/CMakeLists.txt | 34 + stacks/lwip_stack/src/alarm/alarm.c | 863 +++++++++ stacks/lwip_stack/src/alarm/alarm.h | 80 + stacks/lwip_stack/src/alarm/alarm_api.h | 107 ++ stacks/lwip_stack/src/include/nsfw_msg.h | 203 ++ stacks/lwip_stack/src/include/nsfw_msg_api.h | 309 +++ stacks/lwip_stack/src/include/nsfw_mt_config.h | 292 +++ stacks/lwip_stack/src/include/nsfw_rti.h | 66 + stacks/lwip_stack/src/io_adpt/CMakeLists.txt | 31 + stacks/lwip_stack/src/io_adpt/dpdk.c | 2315 +++++++++++++++++++++++ stacks/lwip_stack/src/maintain/CMakeLists.txt | 44 + stacks/lwip_stack/src/maintain/fw_mt_config.c | 843 +++++++++ stacks/lwip_stack/src/maintain/nsfw_msg.c | 23 + stacks/lwip_stack/src/maintain/nsfw_rti.c | 92 + stacks/lwip_stack/src/nStackMain/CMakeLists.txt | 60 + stacks/lwip_stack/src/nStackMain/main.c | 427 +++++ stacks/lwip_stack/src/sbr/CMakeLists.txt | 30 + stacks/lwip_stack/src/sbr/sbr_err.h | 191 ++ stacks/lwip_stack/src/sbr/sbr_index_ring.c | 212 +++ stacks/lwip_stack/src/sbr/sbr_index_ring.h | 61 + stacks/lwip_stack/src/sbr/sbr_protocol_api.h | 99 + stacks/lwip_stack/src/sbr/sbr_res_mgr.c | 88 + stacks/lwip_stack/src/sbr/sbr_res_mgr.h | 128 ++ stacks/lwip_stack/src/sbr/sbr_socket.c | 1231 ++++++++++++ stacks/lwip_stack/src/tools/CMakeLists.txt | 22 + stacks/lwip_stack/src/tools/dump_tool.c | 622 ++++++ stacks/lwip_stack/src/tools/dump_tool.h | 81 + 28 files changed, 8616 insertions(+) create mode 100644 stacks/lwip_stack/src/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/alarm/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/alarm/alarm.c create mode 100644 stacks/lwip_stack/src/alarm/alarm.h create mode 100644 stacks/lwip_stack/src/alarm/alarm_api.h create mode 100644 stacks/lwip_stack/src/include/nsfw_msg.h create mode 100644 stacks/lwip_stack/src/include/nsfw_msg_api.h create mode 100644 stacks/lwip_stack/src/include/nsfw_mt_config.h create mode 100644 stacks/lwip_stack/src/include/nsfw_rti.h create mode 100644 stacks/lwip_stack/src/io_adpt/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/io_adpt/dpdk.c create mode 100644 stacks/lwip_stack/src/maintain/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/maintain/fw_mt_config.c create mode 100644 stacks/lwip_stack/src/maintain/nsfw_msg.c create mode 100644 stacks/lwip_stack/src/maintain/nsfw_rti.c create mode 100644 stacks/lwip_stack/src/nStackMain/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/nStackMain/main.c create mode 100644 stacks/lwip_stack/src/sbr/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/sbr/sbr_err.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_index_ring.c create mode 100644 stacks/lwip_stack/src/sbr/sbr_index_ring.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_protocol_api.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_res_mgr.c create mode 100644 stacks/lwip_stack/src/sbr/sbr_res_mgr.h create mode 100644 stacks/lwip_stack/src/sbr/sbr_socket.c create mode 100644 stacks/lwip_stack/src/tools/CMakeLists.txt create mode 100644 stacks/lwip_stack/src/tools/dump_tool.c create mode 100644 stacks/lwip_stack/src/tools/dump_tool.h (limited to 'stacks/lwip_stack/src') 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 +#include +#include "nsfw_init.h" +#include "nstack_log.h" +#include "json.h" +#include "nstack_securec.h" +#include +#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 +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "nsfw_init.h" +#include "hal.h" +#include "nstack_securec.h" +#include + +#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, ð_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 (ð_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, ð_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, ð_addr); + + ret = rte_eth_bond_mac_address_set ((uint8_t) port, ð_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 +#include +#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 +#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 +#include +#include +#include +#include +#include +#include +#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 ] [--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] [--proc-type ] [-- 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 + +#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 +#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 +#include +#include +#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 +#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 + +#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 -- cgit 1.2.3-korg