diff options
author | sharath reddy <bs.reddy@huawei.com> | 2019-06-04 11:53:49 +0530 |
---|---|---|
committer | sharath reddy <bs.reddy@huawei.com> | 2019-06-04 20:38:30 +0530 |
commit | 2a42ad20b9730706ad371ae3787d4597c4e42276 (patch) | |
tree | fa01cd312586ea007468e7233f94c0ce53d75873 /stacks/lwip_stack/src | |
parent | a826fe833d3f2a8fe2673fa05811fe1a22baf045 (diff) |
Feature: 19.04 part-2DMM-2
Change-Id: I0b52a6bb67c25c7955d58e29eb81a3cc9efea9e9
Signed-off-by: sharath reddy <bs.reddy@huawei.com>
Diffstat (limited to 'stacks/lwip_stack/src')
58 files changed, 13625 insertions, 0 deletions
diff --git a/stacks/lwip_stack/src/CMakeLists.txt b/stacks/lwip_stack/src/CMakeLists.txt new file mode 100644 index 0000000..1bf74ec --- /dev/null +++ b/stacks/lwip_stack/src/CMakeLists.txt @@ -0,0 +1,61 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +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.5/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}/mem/include/common_sys_config.h) +endif() +SET(COMPLE_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../src/framework/include/common/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(sbr) +ADD_SUBDIRECTORY(io_adpt) +ADD_SUBDIRECTORY(nStackMain) +ADD_SUBDIRECTORY(tools) +ADD_SUBDIRECTORY(alarm) +ADD_SUBDIRECTORY(mem) diff --git a/stacks/lwip_stack/src/alarm/CMakeLists.txt b/stacks/lwip_stack/src/alarm/CMakeLists.txt new file mode 100644 index 0000000..d46220a --- /dev/null +++ b/stacks/lwip_stack/src/alarm/CMakeLists.txt @@ -0,0 +1,38 @@ +######################################################################### +# +# 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 nStackFw) +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/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ +) +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..82e7e54 --- /dev/null +++ b/stacks/lwip_stack/src/alarm/alarm.c @@ -0,0 +1,857 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "types.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_fd_timer_api.h" +#include "alarm.h" +#include "alarm_api.h" +#include<time.h> +#include<sys/time.h> +#include "nsfw_init_api.h" +#include "nstack_log.h" +#include "json.h" +#include "nstack_securec.h" +#include <stdlib.h> +#include "nstack_dmm_adpt.h" + +char g_vmid[MAX_VMID_LEN + 1] = "agent-node-x"; + +extern nsfw_timer_info *nsfw_timer_reg_timer(u32 timer_type, void *data, + nsfw_timer_proc_fun fun, + struct timespec time_left); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +// note:the first element is reserved +alarm_data g_alarm_data[ALARM_EVENT_MAX] = { }; + +alarm_result ms_alarm_check_func(void *para) +{ + alarm_result ret_alarm; + int para_value = (long) para; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_MAIN_ABNORMAL; + + if (para_value == ALARM_PRODUCT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + } + else if (para_value == ALARM_CLEAN) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_NSMAIN; + + return ret_alarm; + +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : period check alarm expire handle function +********************************************************************/ + +int ns_alarm_timer_resend_fun(u32 timer_type, void *argv) +{ + int i; + struct timespec time_left; + alarm_data *alarm_value; + + for (i = ALARM_EVENT_BASE; i < ALARM_EVENT_MAX; i++) + { + alarm_value = &g_alarm_data[i]; + + if ((alarm_value->valid_flag == 1) + && (alarm_value->send_succ_flag == ALARM_SEND_FAIL)) + { + /* nStack only send nsMain normal alarm */ + ns_send_alarm_inner(alarm_value->_alarm_id, + (void *) (alarm_value->_alarm_flag), 1, 0); + } + } + + time_left.tv_sec = ALARM_RESEND_TIMER_LENGTH; + time_left.tv_nsec = 0; + nsfw_timer_info *timer_info = + nsfw_timer_reg_timer(0, NULL, ns_alarm_timer_resend_fun, time_left); + if (NULL == timer_info) + { + NSAM_LOGERR("nsfw_timer_reg_timer fail"); + } + + return 0; +} + +void ns_alarm_set_sendFlag(enum_alarm_id alarmId, int flag) +{ + if ((alarmId <= 0) || (alarmId >= ALARM_EVENT_MAX) + || (0 == g_alarm_data[alarmId].valid_flag) + || ((flag != ALARM_SEND_FAIL) && (flag != ALARM_SEND_SUCC))) + { + NSAM_LOGERR("alarm_id is invalid or not reg or flag invalid"); + return; + } + g_alarm_data[alarmId].send_succ_flag = flag; +} + +/******************************************************************* +* Copyright 2017, Huawei Tech. Co., Ltd. +* ALL RIGHTS RESERVED +*Description : alarm module init +********************************************************************/ +int ns_alarm_module_init(void *param) +{ + u32 proc_type = (u32) ((long long) param); + enum_alarm_id i = ALARM_EVENT_BASE; + alarm_reason j = ALARM_REASON_BEGIN; + const char *pst_vm_id = NULL; + alarm_para tcp_alarm_para; + struct timespec time_left; + + for (i = ALARM_EVENT_BASE; i < ALARM_EVENT_MAX; i++) + { + g_alarm_data[i]._alarm_type = ALARM_SEND_ONCE; + + for (j = ALARM_REASON_BEGIN; j < ALARM_REASON_MAX; j++) + { + g_alarm_data[i]._alarm_para.func_alarm_check[j] = NULL; + g_alarm_data[i]._alarm_para.alarm_reason_set[j] = + ALARM_REASON_MAX; + g_alarm_data[i].alarm_time_laps[j] = 0; + } + g_alarm_data[i]._alarm_para.period_alarm.time_length = 0; + g_alarm_data[i]._alarm_id = i; + g_alarm_data[i].valid_flag = 0; + g_alarm_data[i]._alarm_flag = ALARM_CLEAN; + g_alarm_data[i].alarm_reason_cnt = 0; + g_alarm_data[i].send_succ_flag = ALARM_SEND_SUCC; + } + + switch (proc_type) + { + case NSFW_PROC_MAIN: + case NSFW_PROC_CTRL: + + /* 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(NSFW_TIMER_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..6c55400 --- /dev/null +++ b/stacks/lwip_stack/src/alarm/alarm.h @@ -0,0 +1,80 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _ALARM_H_ +#define _ALARM_H_ + +#include <stdint.h> +#include "alarm_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/* alarm clean time = 1*3 */ + +#define ALARM_RESEND_TIMER_LENGTH 60 +#define ALARM_INIT_RESEND_TIMER_LENGTH 40 + +#define ALARM_SEND_SUCC 1 +#define ALARM_SEND_FAIL 0 + +#define ALARM_PARA_LENGTH_OUTER 2048 + +#define ALARM_PERIOD_CHECK_TIMES 3 + +#define MAX_VMID_LEN 256 + +#define MIN_VM_ID_LEN 1 +#define MAX_VM_ID_LEN 256 + +#define INVALID_STR_LEN(_str, _min_len, _maxlen) (NULL == _str || strlen(_str) < _min_len || strlen(_str) > _maxlen) + +typedef struct _alarm_data +{ + alarm_para _alarm_para; + alarm_type _alarm_type; + enum_alarm_id _alarm_id; + int alarm_time_laps[ALARM_REASON_MAX]; + alarm_flag _alarm_flag; + int alarm_reason_cnt; + int valid_flag; + int send_succ_flag; + +} alarm_data; + +typedef struct _alarm_info_s_out +{ + char alarmId[16]; + char comptentname[32]; + char alarmtime[32]; + char alarmcontent[ALARM_PARA_LENGTH_OUTER]; +} alarm_info_s_out; + +int ns_send_alarm_to_alarm_module(alarm_result alarm_res); + +void ns_send_alarm_inner(enum_alarm_id alarm_id, void *para, int check_times, + int check_state_flag); + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/alarm/alarm_api.h b/stacks/lwip_stack/src/alarm/alarm_api.h new file mode 100644 index 0000000..c9dcafb --- /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/common_func.h b/stacks/lwip_stack/src/include/common_func.h new file mode 100644 index 0000000..db1aee7 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_func.h @@ -0,0 +1,140 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _RTE_COMM_FUNC_H_ +#define _RTE_COMM_FUNC_H_ + +#ifdef HAL_LIB + +#else +#include "common_mem_rwlock.h" + +#define common_mem_rwlock_t rte_rwlock_t +#define common_mem_spinlock_t rte_spinlock_t + //typedef rte_rwlock_t common_mem_rwlock_t; + +#define nsfw_write_lock(plock) rte_rwlock_write_lock(plock) +#define nsfw_write_unlock(plock) rte_rwlock_write_unlock(plock) +#define nsfw_read_lock(plock) rte_rwlock_read_lock(plock) +#define nsfw_read_unlock(plock) rte_rwlock_read_unlock(plock) + +#define common_mem_align32pow2 rte_align32pow2 + +#define common_mem_atomic32_cmpset rte_atomic32_cmpset +#define common_mem_pause rte_pause + +#define COMMON_MEM_MAX_MEMZONE RTE_MAX_MEMZONE + +#define common_mem_atomic32_t rte_atomic32_t + +#define common_mem_memseg rte_memseg +#define common_mem_mem_config rte_mem_config + +#define common_mem_pal_get_configuration rte_eal_get_configuration + + //#define commem_mem_pal_module_info rte_eal_module_info + // +#define common_mem_pal_init rte_eal_init + +#define COMMON_MEM_MEMPOOL_NAMESIZE RTE_MEMPOOL_NAMESIZE + +#define common_mem_memzone_lookup rte_memzone_lookup +#define common_mem_memzone rte_memzone +#define common_mem_atomic32_add_return rte_atomic32_add_return + +#define common_mem_spinlock_init rte_spinlock_init +#define common_mem_spinlock_lock rte_spinlock_lock +#define common_mem_spinlock_unlock rte_spinlock_unlock + +#define common_mem_memzone_free rte_memzone_free +#define common_mem_pktmbuf_pool_create rte_pktmbuf_pool_create + +#define common_mem_pktmbuf_alloc rte_pktmbuf_alloc + +#define common_mem_mempool rte_mempool + +#define common_mem_pktmbuf_free rte_pktmbuf_free +#define common_mem_mbuf rte_mbuf + +#define common_mem_mempool_lookup rte_mempool_lookup + +#define common_mem_ring_get_memsize rte_ring_get_memsize +#define common_mem_ring rte_ring + +#define COMMON_MEM_MAX_MEMSEG RTE_MAX_MEMSEG + +#define common_mem_memzone_reserve rte_memzone_reserve +#define common_mem_rwlock_read_lock rte_rwlock_read_lock +#define common_mem_rwlock_read_unlock rte_rwlock_read_unlock + +#define common_mem_rwlock_write_lock rte_rwlock_write_lock +#define common_mem_rwlock_write_unlock rte_rwlock_write_unlock +#define common_mem_spinlock_trylock rte_spinlock_trylock + +#define common_mem_socket_id rte_socket_id +#define common_mem_malloc_socket_stats rte_malloc_socket_stats + +#define COMMON_MEM_MIN RTE_MIN + +#define common_pal_module_init nscomm_pal_module_init +#define common_memzone_data_reserve_name nscomm_memzone_data_reserve_name +#define common_memzone_data_lookup_name nscomm_memzone_data_lookup_name + +#define common_dump_stack rte_dump_stack +#define COMMON_PKTMBUF_HEADROOM RTE_PKTMBUF_HEADROOM + +#define common_pktmbuf_mtod rte_pktmbuf_mtod +#define common_memcpy rte_memcpy +#define common_spinlock_try_lock_with_pid dmm_spinlock_try_lock_with_pid +#define common_spinlock_unlock rte_spinlock_unlock +#define common_atomic64_t rte_atomic64_t +#define common_atomic64_inc rte_atomic64_inc +#define common_atomic64_read rte_atomic64_read +#define common_atomic64_dec rte_atomic64_dec +#define common_mbuf_refcnt_set rte_mbuf_refcnt_set +#define common_mbuf_refcnt_read rte_mbuf_refcnt_read +#define common_exit rte_exit +#define COMMON_CACHE_LINE_SIZE RTE_CACHE_LINE_SIZE +#define common_eal_process_type rte_eal_process_type +#define COMMON_PROC_PRIMARY RTE_PROC_PRIMARY + +void dmm_addr_print(void); + +#define NSFW_NAME_LENCHECK_RET(name, desc) \ + { \ + i32 inamelen = strlen(name); \ + if (inamelen >= NSFW_MEM_APPNAME_LENTH) \ + { \ + NSRTP_LOGERR("name length check fail]desc=%s,name len=%d,expected max=%d", \ + #desc, inamelen, NSFW_MEM_APPNAME_LENTH); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_NAME_LENCHECK_RET_NULL(name, desc) \ + { \ + i32 inamelen = strlen(name); \ + if (inamelen >= NSFW_MEM_APPNAME_LENTH) \ + { \ + NSRTP_LOGERR("name length check fail]desc=%s,name len=%d,expected max=%d", \ + #desc, inamelen, NSFW_MEM_APPNAME_LENTH); \ + return NULL; \ + } \ + } + +#endif + +#endif // _RTE_COMM_FUNC_H_ diff --git a/stacks/lwip_stack/src/include/common_mem_api.h b/stacks/lwip_stack/src/include/common_mem_api.h new file mode 100644 index 0000000..a799677 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_api.h @@ -0,0 +1,134 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __COMMON_MEM_API_H__ +#define __COMMON_MEM_API_H__ + +#ifdef HAL_LIB +#else + +#include "rte_atomic.h" +#include "common_mem_spinlock.h" +#include <sys/types.h> +#include <unistd.h> +#include <semaphore.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef NSTACK_LINT_CODE_DISABLE +#define NSTACK_LINT_CODE_DISABLE(code) /*lint -e#code */ +#endif + +#ifndef NSTACK_LINT_CODE_ENABLE +#define NSTACK_LINT_CODE_ENABLE(code) /*lint +e#code */ +#endif + +#define SYS_MBOX_NULL (sys_mbox_t)0 + +typedef sem_t *sys_sem_t_v1; +typedef sem_t sys_sem_st_v1; +typedef struct queue *sys_mbox_t; + +typedef rte_spinlock_t *sys_sem_t_v2; +typedef rte_spinlock_t sys_sem_st_v2; + +#ifndef u32_t +typedef uint32_t u32_t; +#endif + +#ifndef u8_t +typedef uint8_t u8_t; +#endif + +#ifndef s8_t +typedef int8_t s8_t; +#endif + +#ifndef err_t +typedef s8_t err_t; +#endif + +/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */ +#define SYS_ARCH_TIMEOUT 0xffffffffUL + +/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate. + * For now we use the same magic value, but we allow this to change in future. + */ +#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT + +void sys_sem_signal_s_v2(sys_sem_t_v2 sem); +void sys_sem_init_v2(sys_sem_t_v2 sem); +u32_t sys_arch_sem_trywait_v2(sys_sem_t_v2 * sem); + +u32_t sys_arch_sem_wait_s_v2(sys_sem_t_v2 sem); + +#define SYS_HOST_INITIAL_PID 1 +extern volatile pid_t g_sys_host_pid; +pid_t sys_get_hostpid_from_file(pid_t pid); + +u32_t sys_now(void); + +#define sys_sem_t sys_sem_t_v2 +#define sys_sem_st sys_sem_st_v2 +#define sys_sem_new(sem, count) sys_sem_new_v2(sem, count) +#define sys_sem_free(sem) sys_sem_free_v2(sem) +#define sys_sem_signal(sem) sys_sem_signal_v2(sem) +#define sys_arch_sem_wait(sem, timeout) sys_arch_sem_wait_v2(sem) +#define sys_arch_sem_trywait(sem) sys_arch_sem_trywait_v2(sem) + +#define sys_sem_init(sem) sys_sem_init_v2(sem) +#define sys_sem_s_signal(sem) sys_sem_signal_s_v2(sem) +#define sys_arch_sem_s_wait(sem, timeout) sys_arch_sem_wait_s_v2(sem) +#define sys_arch_lock_with_pid(sem) (void)sys_arch_lock_with_pid_v2(sem) + +#define BUF_SIZE_FILEPATH 256 +#define STR_PID "pid:" +#define READ_FILE_BUFLEN 512 + +extern pid_t sys_get_hostpid_from_file(pid_t pid); +extern pid_t get_hostpid_from_file(u32_t pid); +extern void get_exec_name_by_pid(pid_t pid, char *task_name, + int task_name_len); + +static inline u32_t sys_arch_lock_with_pid_v2(sys_sem_t_v2 sem) +{ + if (SYS_HOST_INITIAL_PID == g_sys_host_pid) + (void) sys_get_hostpid_from_file(getpid()); + dmm_spinlock_lock_with_pid(sem, g_sys_host_pid); + return 0; +} + +#define NSTACK_SEM_MALLOC(sys_sem,count) \ +{ \ + rte_spinlock_init(&(sys_sem)); \ + if (!(count)) \ + { \ + rte_spinlock_lock(&(sys_sem)); \ + } \ +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#endif + +#endif /* __COMMON_MEM_API_H__ */ diff --git a/stacks/lwip_stack/src/include/common_mem_base_type.h b/stacks/lwip_stack/src/include/common_mem_base_type.h new file mode 100644 index 0000000..01707d9 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_base_type.h @@ -0,0 +1,85 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_BASE_TYPE_H_ +#define _COMMON_MEM_BASE_TYPE_H_ + +#ifdef HAL_LIB + +#else + +#define ALIGN_TYPE uint64_t +#define PTR_ALIGN_TYPE uint64_t + +/*alignment define*/ +#define ALIGNMENT_DEF(name, type, aligntype) \ + union { \ + type name; \ + aligntype name##_align; \ + } + +#define PTR_ALIGNMENT_DEF(name, type) ALIGNMENT_DEF(name, type, PTR_ALIGN_TYPE) + +#define OTHER_ALIGNMENT_DEF(name, type) ALIGNMENT_DEF(name, type, ALIGN_TYPE) + +/* + * * List definitions. + * */ +#define DMM_LIST_HEAD(name, type) \ +struct name { \ + PTR_ALIGNMENT_DEF(lh_first, struct type *); /* first element */ \ +} + +#define DMM_LIST_ENTRY(type) \ +struct { \ + PTR_ALIGNMENT_DEF(le_next, struct type *); /* next element */\ + PTR_ALIGNMENT_DEF(le_prev, struct type **); /* address of previous next element */ \ +} + +/* + * * Tail queue definitions. + * */ +#define _DMM_TAILQ_HEAD(name, type, qual) \ +struct name { \ + PTR_ALIGNMENT_DEF(tqh_first, qual type *); /* first element */ \ + PTR_ALIGNMENT_DEF(tqh_last, qual type * qual *); /* addr of last next element */ \ +} + +#define DMM_TAILQ_HEAD(name, type) _DMM_TAILQ_HEAD(name, struct type,) + +#define _DMM_TAILQ_ENTRY(type, qual) \ +struct { \ + PTR_ALIGNMENT_DEF(tqe_next, qual type *); /* next element */\ + PTR_ALIGNMENT_DEF(tqe_prev, qual type * qual*); /* address of previous next element */\ +} +#define DMM_TAILQ_ENTRY(type) _DMM_TAILQ_ENTRY(struct type,) + +/* + * * Singly-linked Tail queue declarations. + * */ +#define DMM_STAILQ_HEAD(name, type) \ + struct name { \ + PTR_ALIGNMENT_DEF(stqh_first, struct type *); /* first element */ \ + PTR_ALIGNMENT_DEF(stqh_last, struct type **); /* addr of last next element */ \ + } + +#define DMM_STAILQ_ENTRY(type) \ + struct { \ + PTR_ALIGNMENT_DEF(stqe_next, struct type *); /* next element */ \ + } +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/common_mem_buf.h b/stacks/lwip_stack/src/include/common_mem_buf.h new file mode 100644 index 0000000..9ba0008 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_buf.h @@ -0,0 +1,78 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_BUF_H_ +#define _COMMON_MEM_BUF_H_ + +#ifdef HAL_LIB +#else + +#include "nsfw_mem_api.h" +#include "common_mem_base_type.h" +#include "types.h" + +typedef enum __DMM_PROC_TYPE +{ + DMM_PROC_T_AUTO = 0, /*auto detect */ + DMM_PROC_T_PRIMARY = 1, /* set to primary */ + DMM_PROC_T_SECONDARY = 2, /* set to secondary */ + DMM_PROC_T_INVALID +} DMM_PROC_TYPE; + +#define DMM_MBUF_RET_OK 0 +#define DMM_MBUF_RET_ERR 1 + +#define LCORE_MAX 128 +#define LCORE_MASK_PER (sizeof(int) * 8) +#define LCORE_MASK_MAX (LCORE_MAX/LCORE_MASK_PER) + +#define LCORE_MASK_SET(ilcoremask, value) \ + if (value < LCORE_MAX) \ + { \ + ilcoremask[(value/LCORE_MASK_PER)] = (int) ( (ilcoremask[(value/LCORE_MASK_PER)]) | (1< (value%LCORE_MASK_PER))); \ + } \ + +#define DMM_HUGTBL_ENABLE 0 +#define DMM_HUGTBL_DISABLE 1 + +typedef struct __common_pal_module_info +{ + int ishare_mem_size; /*shared memory size */ + int ilcoremask[LCORE_MASK_MAX]; + /**/ unsigned char uchugeflag; + unsigned char ucproctype; + unsigned char ucinstance; + unsigned char ucresrv2; +} common_mem_pal_module_info; + +/** + * rte pal module init. + * + * + * @param name + * The name of the buf pool. + */ +int nscomm_pal_module_init(nsfw_mem_para * para, + common_mem_pal_module_info * pinfo, u8 app_mode); + +void *nscomm_memzone_data_reserve_name(const char *name, size_t len, + int socket_id); + +void *nscomm_memzone_data_lookup_name(const char *name); + +#endif + +#endif /* _COMMON_MEM_BUF_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_common.h b/stacks/lwip_stack/src/include/common_mem_common.h new file mode 100644 index 0000000..1e4cf56 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_common.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_COMMON_H_ +#define _COMMON_MEM_COMMON_H_ + +#ifdef HAL_LIB +#else +#include "rte_common.h" +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/common_mem_mbuf.h b/stacks/lwip_stack/src/include/common_mem_mbuf.h new file mode 100644 index 0000000..ee8cfa2 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_mbuf.h @@ -0,0 +1,40 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/******************************************************************* + Copyright 2017 - 2047, Huawei Tech. Co., Ltd. + ALL RIGHTS RESERVED + +Filename : common_mem_mbuf.h +Description : +Version : 1.1 +********************************************************************/ + +#ifndef _COMMON_MEM_MBUF_H_ +#define _COMMON_MEM_MBUF_H_ + +#ifdef HAL_LIB +#else +#include "rte_mbuf.h" +#include "common_func.h" + +typedef uint32_t(*dmm_mbuf_item_fun) (void *data, void *argv); +int32_t dmm_pktmbuf_pool_iterator(struct common_mem_mempool *mp, + uint32_t start, uint32_t end, + dmm_mbuf_item_fun fun, void *argv); +#endif + +#endif /* _COMMON_MEM_MBUF_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_mempool.h b/stacks/lwip_stack/src/include/common_mem_mempool.h new file mode 100644 index 0000000..58a8e82 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_mempool.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_MEMPOOL_H_ +#define _COMMON_MEM_MEMPOOL_H_ + +#ifdef HAL_LIB +#else +#include "rte_mempool.h" +#endif + +#endif /* _COMMON_MEM_MEMPOOL_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_pal_memconfig.h b/stacks/lwip_stack/src/include/common_mem_pal_memconfig.h new file mode 100644 index 0000000..65b6e04 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_pal_memconfig.h @@ -0,0 +1,26 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_PAL_MEMCONFIG_H_ +#define _COMMON_MEM_PAL_MEMCONFIG_H_ + +#ifdef HAL_LIB +#else +#include "rte_eal_memconfig.h" + +#endif + +#endif diff --git a/stacks/lwip_stack/src/include/common_mem_rwlock.h b/stacks/lwip_stack/src/include/common_mem_rwlock.h new file mode 100644 index 0000000..2eed259 --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_rwlock.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_RWLOCK_H_ +#define _COMMON_MEM_RWLOCK_H_ + +#ifdef HAL_LIB +#else +#include "rte_rwlock.h" +#endif + +#endif /* _COMMON_MEM_RWLOCK_H_ */ diff --git a/stacks/lwip_stack/src/include/common_mem_spinlock.h b/stacks/lwip_stack/src/include/common_mem_spinlock.h new file mode 100644 index 0000000..482e87b --- /dev/null +++ b/stacks/lwip_stack/src/include/common_mem_spinlock.h @@ -0,0 +1,38 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_SPINLOCK_X86_64_H_ +#define _COMMON_MEM_SPINLOCK_X86_64_H_ + +#ifdef HAL_LIB +#else +#include "rte_spinlock.h" + +static inline void dmm_spinlock_lock_with_pid(rte_spinlock_t * sl, int pid) +{ + while (!__sync_bool_compare_and_swap(&sl->locked, 0, pid)) + while (sl->locked) + rte_pause(); +} + +static inline int dmm_spinlock_try_lock_with_pid(rte_spinlock_t * sl, int pid) +{ + return __sync_bool_compare_and_swap(&sl->locked, 0, pid); +} + +#endif + +#endif /* _COMMON_MEM_SPINLOCK_X86_64_H_ */ diff --git a/stacks/lwip_stack/src/include/nsfw_msg.h b/stacks/lwip_stack/src/include/nsfw_msg.h new file mode 100644 index 0000000..9efa694 --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_msg.h @@ -0,0 +1,201 @@ +/* +* +* 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_RETURN(MAX_MSG_SIZE, 512); +#define MAX_MSG_PARAM_SIZE 128 +COMPAT_PROTECT_RETURN(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..b7e0d1c --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_msg_api.h @@ -0,0 +1,305 @@ +/* +* +* 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" +#include "pid_common.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..3735be4 --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_mt_config.h @@ -0,0 +1,63 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _FW_MT_CONFIG_H +#define _FW_MT_CONFIG_H + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#include "nsfw_maintain_api.h" + +/* socket num config */ +#define SOCKET_NUM_PER_THREAD 1024 /* socket number per thread */ + +#define APP_POOL_NUM 32 + +#define DEF_HAL_RX_RING_SIZE 2048 + +/* stackx recv ring size config */ +#define DEF_SPL_MAX_RING_SIZE 1024 + +/* pcb number config */ +#define DEF_TCP_PCB_NUM 4096 /* tcp pcb number, per thread */ +#define DEF_UDP_PCB_NUM 512 /* udp pcb number, per thread */ +#define DEF_RAW_PCB_NUM 600 /* raw pcb number, per thread */ + +#define DEF_ARP_QUEUE_NUM 300 + +/* tx mbuf pool size config */ +#define DEF_TX_MBUF_POOL_SIZE (4*POOL_RING_BASE_SIZE) + +/* rx mbuf pool size config */ +#define DEF_RX_MBUF_POOL_SIZE (8*POOL_RING_BASE_SIZE) /* rx mbuf pool size */ + +/* 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) + +/* mbox ring size config */ +#define DEF_MBOX_RING_SIZE (DEF_RING_BASE_SIZE/4) + +#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..f6eb1b8 --- /dev/null +++ b/stacks/lwip_stack/src/include/nsfw_rti.h @@ -0,0 +1,49 @@ +/* +* +* 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; + +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/include/nstack_dmm_adpt.h b/stacks/lwip_stack/src/include/nstack_dmm_adpt.h new file mode 100644 index 0000000..7e6e9cb --- /dev/null +++ b/stacks/lwip_stack/src/include/nstack_dmm_adpt.h @@ -0,0 +1,64 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#ifndef __NSTACK_DMM_ADPT_H__ +#define __NSTACK_DMM_ADPT_H__ + +typedef enum +{ + NSTACK_MODEL_TYPE1 = 1, /*nSocket and stack belong to the same process */ + NSTACK_MODEL_TYPE2 = 2, /*nSocket and stack belong to different processes, + *and nStack don't take care the communication between stack and stack adpt + */ + NSTACK_MODEL_TYPE3 = 3, /*nSocket and stack belong to different processes, and sbr was supplied to communicate whit stack */ + NSTACK_MODEL_TYPE_SIMPLE_STACK = 4, /* like TYPE1, DMM will NOT provide SBR or pipeline mode, just allocate 32M, and use dpdk file + * prefix to support multiple running app under DMM */ + NSTACK_MODEL_INVALID, +} nstack_model_deploy_type; + +#define NSTACK_DMM_MODULE "nstack_dmm_module" + +typedef struct nsfw_com_attr +{ + int policy; + int pri; +} nsfw_com_attr; + +typedef struct __nstack_dmm_para +{ + nstack_model_deploy_type deploy_type; + int proc_type; + nsfw_com_attr attr; + int argc; + char **argv; +} nstack_dmm_para; + +extern int nstack_adpt_init(nstack_dmm_para * para); +extern int nstack_event_callback(void *pdata, int events); + +#endif + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ diff --git a/stacks/lwip_stack/src/io_adpt/CMakeLists.txt b/stacks/lwip_stack/src/io_adpt/CMakeLists.txt new file mode 100644 index 0000000..53915f1 --- /dev/null +++ b/stacks/lwip_stack/src/io_adpt/CMakeLists.txt @@ -0,0 +1,41 @@ +######################################################################### +# +# 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_SECUREC_LIB) +INCLUDE_DIRECTORIES( + ./ + ${JSON_C_SRC} + ${SECUREC_SRC} + ${CMAKE_CURRENT_LIST_DIR}/../include/ +) +else() +SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") +INCLUDE_DIRECTORIES( + ${PAL_H_DIRECTORIES} + ./ + ${JSON_C_SRC} + ${CMAKE_CURRENT_LIST_DIR}/../include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/hal/ +) +endif() +ADD_LIBRARY(nStackHal STATIC ${HAL}) +LINK_LIBRARIES(m dl rt nStackFw) 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..e662a21 --- /dev/null +++ b/stacks/lwip_stack/src/io_adpt/dpdk.c @@ -0,0 +1,2499 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdint.h> +#include <sched.h> +#include <dlfcn.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <net/if.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <sys/file.h> +#include <pwd.h> +#include <dirent.h> +#include <sys/stat.h> +#include <fnmatch.h> +#include <linux/ethtool.h> +#include <linux/sockios.h> + +#include <rte_config.h> +#include <rte_ethdev.h> +#include <rte_mbuf.h> +#include <rte_eth_bond.h> +#include "nstack_log.h" +#include "nsfw_init_api.h" +#include "common_mem_mbuf.h" +#include "common_mem_mempool.h" +#include "common_func.h" +#include "hal.h" +#include "nstack_securec.h" +#include <rte_ethdev_driver.h> + +#define DPDK_NON_ROOT_USER_NAME "paas" +#define DPDK_TOOL_ENV "DPDK_TOOL_DIR" +#define DPDK_NIC_LIST_FILE "%s/ip_module/.nstack_dpdk_nic_list" +#define SOCKET_ID_0 0 + +NSTACK_STATIC struct passwd *dpdk_non_root_user; +NSTACK_STATIC char dpdk_tool_path[HAL_MAX_PATH_LEN] = { 0 }; + +/* Default configuration for rx and tx thresholds etc. */ +NSTACK_STATIC const struct rte_eth_rxconf rx_conf_default_igb = { + .rx_thresh = { + .pthresh = 8, + .hthresh = 8, + .wthresh = 1, //not bigger than 1 + }, +}; + +/* + * These default values are optimized for use with the Intel(R) 82576 1 GbE + * Controller and the DPDK e1000 PMD. Consider using other values for other + * network controllers and/or network drivers. + */ +NSTACK_STATIC const struct rte_eth_txconf tx_conf_default_igb = { + .tx_thresh = { + .pthresh = 8, + .hthresh = 1, + .wthresh = 16, + }, + .tx_free_thresh = 0, /* Use PMD default values */ + .tx_rs_thresh = 0, /* Use PMD default values */ +}; + +/* + * RX and TX Prefetch, Host, and Write-back threshold values should be + * carefully set for optimal performance. Consult the network + * controller's datasheet and supporting DPDK documentation for guidance + * on how these parameters should be set. + */ + +/* Default configuration for rx and tx thresholds etc. */ +NSTACK_STATIC const struct rte_eth_rxconf rx_conf_default_ixgbe = { + .rx_thresh = { + .pthresh = 8, + .hthresh = 8, + .wthresh = 4, + }, + .rx_free_thresh = 0, +}; + +/* + * These default values are optimized for use with the Intel(R) 82599 10 GbE + * Controller and the DPDK ixgbe PMD. Consider using other values for other + * network controllers and/or network drivers. + */ +NSTACK_STATIC const struct rte_eth_txconf tx_conf_default_ixgbe = { + .tx_thresh = { + .pthresh = 36, + .hthresh = 0, + .wthresh = 0, + }, + .tx_free_thresh = 0, /* Use PMD default values */ + .tx_rs_thresh = 0, /* Use PMD default values */ + .txq_flags = 0, +}; + +/* the port configuration of normal port */ +NSTACK_STATIC struct rte_eth_conf port_conf_default_normal = { + .rxmode = { + .mq_mode = ETH_RSS, + .max_rx_pkt_len = ETHER_MAX_LEN, + .split_hdr_size = 0, + .header_split = 0, + .hw_ip_checksum = 1, + .hw_vlan_filter = 1, + .hw_vlan_strip = 1, + .jumbo_frame = 0, + .hw_strip_crc = 0, + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = (ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP), //rss hash key + }, + }, + .txmode = { + .mq_mode = ETH_DCB_NONE, + }, + .intr_conf = { + .lsc = 0, + }, +}; + +/* the port configuration of virtio port */ +NSTACK_STATIC struct rte_eth_conf port_conf_default_virtio = { + .rxmode = { + .mq_mode = ETH_RSS, + .max_rx_pkt_len = ETHER_MAX_LEN, + .split_hdr_size = 0, + .header_split = 0, + .hw_ip_checksum = 0, /* Virtio NIC doesn't support HW IP CheckSUM */ + .hw_vlan_filter = 1, + .hw_vlan_strip = 1, + .jumbo_frame = 0, + .hw_strip_crc = 0, + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = (ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP), //rss hash key + }, + }, + .txmode = { + .mq_mode = ETH_DCB_NONE, + }, + .intr_conf = { + .lsc = 0, + }, +}; + +/* the port configuration of bond port */ +NSTACK_STATIC struct rte_eth_conf port_conf_default_bond = { + .rxmode = { + .mq_mode = ETH_MQ_RX_NONE, + .max_rx_pkt_len = ETHER_MAX_LEN, + .split_hdr_size = 0, + .header_split = 0, + /**< Header Split disabled */ + .hw_ip_checksum = 0, + /**< IP checksum offload enabled */ + .hw_vlan_filter = 1, + /**< VLAN filtering enabled */ + .hw_vlan_strip = 1, + .jumbo_frame = 0, + /**< Jumbo Frame Support disabled */ + .hw_strip_crc = 0, + /**< CRC stripped by hardware */ + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = ETH_RSS_IP, + }, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; + +NSTACK_STATIC struct rte_eth_conf port_conf_default_vhost = { + .rxmode = { + .hw_ip_checksum = 0, /* vhost nic doesn't support hw_ip_checksum and hw_vlan_filter */ + .hw_vlan_filter = 0, + } +}; + +/***************************************************************************** +* Prototype : dpdk_mbuf_to_file +* Description : write the packet data into a file +* Input : uint16_t pkt_number +* struct rte_mbuf **pkts +* Output : None +* Return Value : +* Calls : +* Called By : +* +*****************************************************************************/ +NSTACK_STATIC void +dpdk_mbuf_to_file(uint16_t pkt_number, struct rte_mbuf **pkts) +{ + char line[100] = { 0 }; + FILE *f = NULL; + struct rte_mbuf *p = NULL; + uint16_t len = 0, offset, i; + uint16_t pktlen = 0; + uint16_t start = 0; + uint16_t number = 0; + unsigned char *data = NULL; + + f = fopen("/var/log/nStack/packet.txt", "a+"); + if (f == NULL) + { + NSHAL_LOGERR("can not open the file:%s", "packet.txt"); + return; + } + + for (i = 0; i < pkt_number; i++) + { + pktlen = 0; + p = pkts[i]; + while (p) + { + len = 0; + data = rte_pktmbuf_mtod(p, unsigned char *); + while (len < p->data_len) + { + start = pktlen % 16; /* start of the line */ + if (start == 0) + { + number = snprintf_s(line, sizeof(line), sizeof(line) - 1, + "%08X", len); + } + + for (offset = 0; + ((offset + start) < 16) + && ((len + offset) < p->data_len); offset++) + { + number += + snprintf_s(line + number, sizeof(line), + sizeof(line) - 1, " %02X", + data[len + offset]); + } + + fprintf(f, "%s", line); + if ((offset + start) == 16) + fprintf(f, "\n"); + + len += offset; + pktlen += offset; + (void) memset_s(line, sizeof(line), 0, sizeof(line)); + } + + p = p->next; + + } + fprintf(f, "\n"); + } + + fclose(f); + return; +} + +/***************************************************************************** +* 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; + char *pst_capture_packet = NULL; + 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 + + //pst_capture_packet = getenv ("NSTACK_CAPTURE_PACKET"); + if (pst_capture_packet && strcmp(pst_capture_packet, "1") == 0) + { + dpdk_mbuf_to_file(nb_rx, rx_pkts); + } + 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 + int16_t nb_tx = 0; + char *pst_capture_packet = NULL; + 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 + + nb_tx = (*dev->tx_pkt_burst) (dev->data->tx_queues[queue_id], tx_pkts, + nb_pkts); + + //pst_capture_packet = getenv ("NSTACK_CAPTURE_PACKET"); + if (pst_capture_packet && strcmp(pst_capture_packet, "1") == 0) + { + dpdk_mbuf_to_file(nb_tx, tx_pkts); + } + + return nb_tx; +} + +/***************************************************************************** + 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_type + Description : check and save nic type + Input : netif_inst_t* inst + const char* type + Output : None + Return Value : NSTACK_STATIC + Calls : + Called By : + +*****************************************************************************/ +NSTACK_STATIC int dpdk_set_nic_type(netif_inst_t * inst, const char *type) +{ + int ret; + + ret = + strcpy_s(inst->data.dpdk_if.nic_type, + sizeof(inst->data.dpdk_if.nic_type), type); + if (EOK != ret) + { + NSHAL_LOGERR("strcpy_s set nic_type failed]ret=%d", ret); + return -1; + } + + /* + * *nic_type is first checked at read_ipmoduleoperateadd_configuration, + * *thus here we dont boring validating it once more and just return. + * */ + + 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) + { + NSHAL_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, const char *type) +{ + int ret; + + if ((inst == NULL) || (name == NULL) || (type == NULL)) + { + NSHAL_LOGERR + ("invaliad arguments]inst==NULL, nic_type==NULL or type==NULL"); + return -1; + } + + ret = dpdk_set_nic_type(inst, type); + + if (0 != ret) + { + NSHAL_LOGERR("dpdk_set_nic_type fail]nic_type=%s, ret=%d", type, ret); + return -1; + } + + 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; + } + + if (!strncmp(type, "vhost", strlen("vhost"))) + { + /*for vhost-user device, the remaining steps is unnecessary, y0413485 */ + NSHAL_LOGERR("initting vhost device]nic_name=%s type=%s", name, type); + return 0; + } + + 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 if (strncmp("vhost", inst->data.dpdk_if.nic_type, (size_t) 5) == 0) + { + *port_conf = &port_conf_default_vhost; + return; + } + 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 = + (struct rte_mempool **) 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, + struct hal_netif_hw_feature *capa) +{ + int retVal = memset_s(capa, sizeof(struct hal_netif_hw_feature), 0, + sizeof(struct hal_netif_hw_feature)); + if (EOK != retVal) + { + NSHAL_LOGERR("MEMSET_S fail]retVal=%d", retVal); + } + + /* Set Rx checksum checking */ + if (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) + { + NSHAL_LOGINF("RX IP checksum offload supported."); + capa->rx_csum_ip = 1; + } + if ((dev_info->rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) && + (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)) + { + NSHAL_LOGINF("RX L4 checksum offload supported."); + capa->rx_csum_l4 = 1; + } + if (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) + { + NSHAL_LOGINF("RX LRO supported."); + capa->rx_lro = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) + { + NSHAL_LOGINF("TX IP checksum offload supported."); + capa->tx_csum_ip = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) + { + NSHAL_LOGINF("TX UDP checksum offload supported."); + capa->tx_csum_udp = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) + { + NSHAL_LOGINF("TX TCP checksum offload supported."); + capa->tx_csum_tcp = 1; + } + if (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) + { + NSHAL_LOGINF("TSO is supported."); + capa->tx_tso = 1; + } + else + { + NSHAL_LOGINF("TSO is disabled."); + capa->tx_tso = 0; + } +} + +/***************************************************************************** + 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, struct hal_netif_hw_feature *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, + void **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, + void **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/mem/CMakeLists.txt b/stacks/lwip_stack/src/mem/CMakeLists.txt new file mode 100644 index 0000000..eb4e0b5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/CMakeLists.txt @@ -0,0 +1,36 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +if(WITH_HAL_LIB) +else() + SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") +endif() + + +FILE(GLOB_RECURSE MEM *.c) +ADD_LIBRARY(nsfw_mem STATIC ${MEM}) +ADD_DEPENDENCIES(nsfw_mem GLOG) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../include + ${PAL_H_DIRECTORIES} + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include + nsfw_shmem/ + include/ + ${CMAKE_CURRENT_LIST_DIR}/../include/ + ${CMAKE_CURRENT_LIST_DIR}/nsfw_nshmem/ +) diff --git a/stacks/lwip_stack/src/mem/include/common_mem_memzone.h b/stacks/lwip_stack/src/mem/include/common_mem_memzone.h new file mode 100644 index 0000000..20e18c2 --- /dev/null +++ b/stacks/lwip_stack/src/mem/include/common_mem_memzone.h @@ -0,0 +1,25 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_MEM_MEMZONE_H_ +#define _COMMON_MEM_MEMZONE_H_ + +#ifdef HAL_LIB +#else +#include "rte_memzone.h" +#endif + +#endif /* _COMMON_MEM_MEMZONE_H_ */ diff --git a/stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h b/stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h new file mode 100644 index 0000000..086460c --- /dev/null +++ b/stacks/lwip_stack/src/mem/include/common_pal_bitwide_adjust.h @@ -0,0 +1,204 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _COMMON_PAL_BITWIDE_ADJUST_H_ +#define _COMMON_PAL_BITWIDE_ADJUST_H_ + +#ifdef HAL_LIB +#include "pal_bitwide_adjust.h" +#else +#define MODULE(name) (1) + +#include "common_mem_common.h" + +#include "common_func.h" + +#define ALIGN_SIZET(size) ((uint64_t)(size)) +#define ALIGN_PTR(PTR) ((uint64_t)(PTR)) + +extern struct common_mem_memseg *g_PMemSegArry; +extern void **g_LMegAddrArry; + +/*get Local Seg addr by segIdx*/ +#define HMEM_SEG_LVADDR(segid) (g_LMegAddrArry[segid]) +/*get SegIDX by PrimSegAddr, just get the array Idx of g_PMemSegArry*/ +#define HMEM_SEGID(segaddr) ((struct common_mem_memseg*)segaddr - &(g_PMemSegArry[0])) + +/***************************************************************** +Parameters : LMegAddrArry[] Local common_mem_memseg addr Array + SegNum common_mem_memseg Num. +Return : +Description : init g_PrimAddr2LocalMap g_LocalAddr2PrimMap while the process start +*****************************************************************/ +void *pal_shddr_to_laddr(uint64_t shaddr); +uint64_t pal_laddr_to_shddr(void *laddr); +int dmm_pal_addr_align(); +void *shmem_shddr_to_laddr(void *addr); +uint64_t shmem_laddr_to_shddr(void *addr); + +extern int g_PrimSameFlg; + +/* if __NSTACK_MAIN__ is defined, no need do addr trans*/ +#ifndef __NSTACK_MAIN__ +/* g_PrimSameFlg check should be done before calling cast functions */ + +/*share memory address to local virtual address*/ +#define ADDR_SHTOL(addr) (g_PrimSameFlg ? ((void*) (addr)) : pal_shddr_to_laddr((uint64_t)(addr))) + +/*local virtual address to share memory address according to memseg*/ +#define ADDR_LTOSH(addr) (g_PrimSameFlg ? ((uint64_t)(addr)) : pal_laddr_to_shddr((void*)(addr))) + +#define PTR_SHTOL(type, addr) ((type)ADDR_SHTOL(addr)) + +/*local virtual address to share memory address; for compatible, not delete ADDR_LTOSH_EXT*/ +#define ADDR_LTOSH_EXT(addr) ADDR_LTOSH(addr) +#else +/*share memory address to local virtual address*/ +#define ADDR_SHTOL(addr) ((void*)(addr)) + +/*local virtual address to share memory address according to memseg*/ +#define ADDR_LTOSH(addr) ((uint64_t)(addr)) + +#define PTR_SHTOL(type, addr) ((type)(addr)) + +/*local virtual address to share memory address; for compatible, not delete ADDR_LTOSH_EXT*/ +#define ADDR_LTOSH_EXT(addr) ADDR_LTOSH(addr) +#endif + +#if MODULE("list") +#define COMMON_LIST_INSERT_HEAD(lhead, lelm, field) do { \ + if (((lelm)->field.le_next_align = (lhead)->lh_first_align) != ((typeof((lhead)->lh_first_align))(long)NULL)) \ + ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align))->field.le_prev_align = \ + ADDR_LTOSH(&(lelm)->field.le_next); \ + (lhead)->lh_first_align = ADDR_LTOSH(lelm); \ + (lelm)->field.le_prev_align = ADDR_LTOSH(&(lhead)->lh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_LIST_REMOVE(lelm, field) do { \ + if ((lelm)->field.le_next_align != ((typeof((lelm)->field.le_next_align))ALIGN_PTR(NULL))) \ + ((typeof((lelm)->field.le_next))ADDR_SHTOL((lelm)->field.le_next_align))->field.le_prev_align = \ + (lelm)->field.le_prev_align; \ + if (EOK != (MEMCPY_S((typeof((lelm)->field.le_prev))ADDR_SHTOL((lelm)->field.le_prev_align), \ + sizeof((lelm)->field.le_next_align), \ + &((lelm)->field.le_next_align), \ + sizeof((lelm)->field.le_next_align)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + return;\ + }\ +} while (/*CONSTCOND*/0) + +#define COMMON_LIST_EMPTY(lhead) ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align) == NULL) +#define COMMON_LIST_FIRST(lhead) ((typeof((lhead)->lh_first))ADDR_SHTOL((lhead)->lh_first_align)) +#define COMMON_LIST_NEXT(lelm, field) ((typeof((lelm)->field.le_next))ADDR_SHTOL((lelm)->field.le_next_align)) + +#endif + +#if MODULE("tailq") + +#define COMMON_TAILQ_INSERT_TAIL(lhead, lelm, field) do { \ + (lelm)->field.tqe_next_align = (typeof((lelm)->field.tqe_next_align))NULL; \ + (lelm)->field.tqe_prev_align = (lhead)->tqh_last_align; \ + typeof((lhead)->tqh_last_align) tempelm = ADDR_LTOSH(lelm);\ + if (EOK != (MEMCPY_S(ADDR_SHTOL((lhead)->tqh_last_align), sizeof(tempelm), &tempelm, sizeof(tempelm)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + (lhead)->tqh_last_align = ADDR_LTOSH(&(lelm)->field.tqe_next); \ +} while (/*CONSTCOND*/0) + +#define COMMON_TAILQ_FOREACH(lvar, lhead, field) \ + for ((lvar) = (typeof(lvar))ADDR_SHTOL((lhead)->tqh_first_align); \ + (lvar); \ + (lvar) = (typeof(lvar))ADDR_SHTOL((lvar)->field.tqe_next_align)) + +#define COMMON_TAILQ_REMOVE(lhead, lelm, field) do { \ + if (((lelm)->field.tqe_next_align) != (typeof((lelm)->field.tqe_next_align))NULL) \ + ((typeof((lelm)->field.tqe_next))ADDR_SHTOL((lelm)->field.tqe_next_align))->field.tqe_prev_align = \ + (lelm)->field.tqe_prev_align; \ + else \ + (lhead)->tqh_last_align = (lelm)->field.tqe_prev_align; \ + if (EOK != (MEMCPY_S(ADDR_SHTOL((lelm)->field.tqe_prev_align), \ + sizeof((lelm)->field.tqe_next_align), \ + &((lelm)->field.tqe_next_align), \ + sizeof((lelm)->field.tqe_next_align)))) \ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + } while (/*CONSTCOND*/0) + +/* + * Tail queue functions. + */ +#define COMMON_TAILQ_INIT(head) do { \ + (head)->tqh_first_align = (typeof((head)->tqh_first_align))NULL; \ + (head)->tqh_last_align = ADDR_LTOSH(&(head)->tqh_first); \ + } while (/*CONSTCOND*/0) + +/* + * Tail queue access methods. + */ +#define COMMON_TAILQ_EMPTY(head) ((head)->tqh_first_align == (typeof((head)->tqh_first_align))NULL) +#define COMMON_TAILQ_FIRST(head) ((typeof((head)->tqh_first))ADDR_SHTOL((head)->tqh_first_align)) +#define COMMON_TAILQ_NEXT(elm, field) ((typeof((elm)->field.tqe_next))ADDR_SHTOL((elm)->field.tqe_next_align)) + +#endif + +#if MODULE("stailq") +/* +* Singly-linked Tail queue functions. +*/ +#define COMMON_STAILQ_INIT(head) do { \ + (head)->stqh_first_align = ALIGN_PTR(NULL); \ + (head)->stqh_last_align = ADDR_LTOSH(&(head)->stqh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next_align = ALIGN_PTR(NULL); \ + typeof((head)->stqh_last_align) telm = ADDR_LTOSH(elm);\ + if (EOK != (MEMCPY_S(ADDR_SHTOL((head)->stqh_last_align), sizeof(telm), &telm, sizeof(telm))))\ + {\ + NSCOMM_LOGERR("MEMCPY_S failed.");\ + }\ + (head)->stqh_last_align = ADDR_LTOSH(&(elm)->field.stqe_next); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first_align = \ + ((typeof((head)->stqh_first))ADDR_SHTOL((head)->stqh_first_align))->field.stqe_next_align) == \ + (PTR_ALIGN_TYPE)NULL) \ + (head)->stqh_last_align = ADDR_LTOSH(&(head)->stqh_first); \ +} while (/*CONSTCOND*/0) + +#define COMMON_STAILQ_FOREACH(var, head, field) \ + for ((var) = ADDR_SHTOL((head)->stqh_first_align); \ + (var); \ + (var) = ADDR_SHTOL((var)->field.stqe_next_align)) + +/* +* Singly-linked Tail queue access methods. +*/ + +#define COMMON_STAILQ_EMPTY(head) ((head)->stqh_first_align == (PTR_ALIGN_TYPE)NULL) + +#define COMMON_STAILQ_FIRST(head) (ADDR_SHTOL((head)->stqh_first_align)) + +#define COMMON_STAILQ_NEXT(elm, field) (ADDR_SHTOL((elm)->field.stqe_next_align)) +#endif + +#endif + +#endif diff --git a/stacks/lwip_stack/src/mem/include/common_sys_config.h b/stacks/lwip_stack/src/mem/include/common_sys_config.h new file mode 100644 index 0000000..736c47b --- /dev/null +++ b/stacks/lwip_stack/src/mem/include/common_sys_config.h @@ -0,0 +1,46 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __COMMON_SYS_CONFIG_H_ +#define __COMMON_SYS_CONFIG_H_ + +/* Below compile macro is used only in UT makefile */ +#if (HAL_LIB) +#else +#undef RTE_CACHE_LINE_SIZE +#define RTE_CACHE_LINE_SIZE 64 /* RTE_CACHE_LINE_SIZE */ +#undef RTE_MAX_LCORE +#define RTE_MAX_LCORE 128 /* RTE_MAX_LCORE */ +#undef RTE_MAX_NUMA_NODES +#define RTE_MAX_NUMA_NODES 8 /* RTE_MAX_NUMA_NODES */ +#undef RTE_MAX_MEMSEG +#define RTE_MAX_MEMSEG 256 /* RTE_MAX_MEMSEG */ +#undef RTE_MAX_MEMZONE +#define RTE_MAX_MEMZONE 2560 /* RTE_MAX_MEMZONE */ +#undef RTE_MAX_TAILQ +#define RTE_MAX_TAILQ 32 /* RTE_MAX_TAILQ */ +#undef RTE_ARCH_X86 +#define RTE_ARCH_X86 1 /* RTE_ARCH_64 */ +#undef RTE_ARCH_64 +#define RTE_ARCH_64 1 /* RTE_ARCH_64 */ +#undef RTE_PKTMBUF_HEADROOM +#define RTE_PKTMBUF_HEADROOM 128 /* RTE_PKTMBUF_HEADROOM */ +#undef RTE_MEMPOOL_CACHE_MAX_SIZE +#define RTE_MEMPOOL_CACHE_MAX_SIZE 512 /* RTE_MEMPOOL_CACHE_MAX_SIZE */ + +#endif + +#endif // __COMMON_SYS_CONFIG_H_ diff --git a/stacks/lwip_stack/src/mem/lib_common_mem/common_api.c b/stacks/lwip_stack/src/mem/lib_common_mem/common_api.c new file mode 100644 index 0000000..453f33f --- /dev/null +++ b/stacks/lwip_stack/src/mem/lib_common_mem/common_api.c @@ -0,0 +1,163 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include "common_mem_api.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "common_func.h" +#include "pid_common.h" + +void sys_sem_init_v2(sys_sem_t_v2 sem) +{ + sem->locked = 1; +} + +/** Returns the current time in milliseconds, + * may be the same as sys_jiffies or at least based on it. */ +u32_t sys_now(void) +{ + struct timespec now; + + if (unlikely(0 != clock_gettime(CLOCK_MONOTONIC, &now))) + { + NSRTP_LOGERR("Failed to get time, errno = %d", errno); + } + + return 1000 * now.tv_sec + now.tv_nsec / 1000000; +} + +long sys_jiffies(void) +{ + return sys_now(); +} + +err_t sys_sem_new_v2(sys_sem_t_v2 * sem, u8_t isUnLockd) +{ + int retVal; + if (!sem) + { + return -1; + } + *sem = malloc(sizeof(common_mem_spinlock_t)); + + if (NULL == *sem) + { + return -1; + } + else + { + retVal = + memset_s(*sem, sizeof(common_mem_spinlock_t), 0, + sizeof(common_mem_spinlock_t)); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + free(*sem); + *sem = NULL; + return -1; + } + common_mem_spinlock_init(*sem); + } + + if (!isUnLockd) + { + common_mem_spinlock_lock(*sem); + } + + return 0; +} + +void sys_sem_free_v2(sys_sem_t_v2 * sem) +{ + if ((sem != NULL) && (*sem != NULL)) + { + free(*sem); + *sem = NULL; + } + else + { + } +} + +void sys_sem_signal_v2(sys_sem_t_v2 * sem) +{ + common_mem_spinlock_unlock(*sem); +} + +void sys_sem_signal_s_v2(sys_sem_t_v2 sem) +{ + common_mem_spinlock_unlock(sem); +} + +u32_t sys_arch_sem_trywait_v2(sys_sem_t_v2 * sem) +{ + return (u32_t) common_mem_spinlock_trylock(*sem); +} + +u32_t sys_arch_sem_wait_v2(sys_sem_t_v2 * pstsem) +{ + common_mem_spinlock_lock(*pstsem); + return 0; +} + +u32_t sys_arch_sem_wait_s_v2(sys_sem_t_v2 sem) +{ + common_mem_spinlock_lock(sem); + return 0; +} + +/***************************************************************************** +* Prototype : get_pid_namespace +* Description : Get namespace of pid +* Input : uint32_t pid +* Output : None +* Return Value : uint64_t +* Calls : +* Called By : +*****************************************************************************/ +uint64_t get_pid_namespace(pid_t pid) +{ + char buf[BUF_SIZE_FILEPATH] = { 0 }; + char path[BUF_SIZE_FILEPATH] = { 0 }; + const char *pstart; + int ret = 0; + if (!pid) + { + NSSOC_LOGERR("Pid is zero!"); + return 0; + } + + ret = + snprintf_s(path, sizeof(path), sizeof(path) - 1, "/proc/%d/ns/pid", + pid); + if (-1 == ret) + { + NSSOC_LOGERR("SNPRINTF_S failed]ret=%d", ret); + return 0; + } + + ret = readlink(path, buf, sizeof(buf) - 1); + if (ret <= (int) sizeof(STR_PID)) + { + NSSOC_LOGERR("readlink pid ns file error]ret=%d", ret); + return 0; + } + + buf[ret - 1] = 0; + pstart = &(buf[sizeof(STR_PID)]); + return strtoull(pstart, NULL, 10); +} diff --git a/stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c b/stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c new file mode 100644 index 0000000..98983d5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/lib_common_mem/common_buf.c @@ -0,0 +1,299 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdarg.h> +#include <inttypes.h> +#include <errno.h> +#include <ctype.h> +#include <sys/queue.h> + +#include "common_mem_base_type.h" + +#include "common_mem_common.h" + +#include "common_mem_memzone.h" + +#include "common_mem_mempool.h" +#include "common_mem_buf.h" + +#include "nstack_log.h" +#include "nstack_securec.h" + +#include "common_func.h" +#include "common_pal_bitwide_adjust.h" + +#define LOG_ERR 0 +#define LOG_WARN 1 +#define LOG_INFO 2 +#define LOG_DEBUG 3 +#define LOG_MAX 4 + +#define COMMON_LOG_PRINT(level, fmt, args...) \ + if (level <= log_level) NSRTP_LOGERR("===>[COMMON]"fmt, ##args); \ + +#define COMMON_PANIC(fmt) \ + NSRTP_LOGERR("==>[COMMON_PANIC]"fmt); \ + common_dump_stack(); \ + +#define PARA1_SET(argv, tempargv, Index, para1) do {\ + retVal = strcpy_s(tempargv[Index], PATA_STRLENT, para1);\ + if (retVal != EOK)\ + {\ + NSRTP_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index ++; } while (0) + +#define PARA2_SET(argv, tempargv, Index, para1, para2) do {\ + retVal = strcpy_s(tempargv[Index], PATA_STRLENT, para1); \ + if (retVal != EOK)\ + {\ + NSRTP_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index++; \ + retVal = strcpy_s(tempargv[Index], PATA_STRLENT, para2); \ + if (retVal != EOK)\ + {\ + NSRTP_LOGERR("STRCPY_S failed]ret=%d", retVal);\ + return DMM_MBUF_RET_ERR;\ + }\ + argv[Index] = tempargv[Index]; \ + Index ++; } while (0) + +#define PATA_STRLENT 64 +#define PATA_NUM_MAX 12 + +int log_level = LOG_INFO; + +int +nscomm_pal_module_init(nsfw_mem_para * para, + common_mem_pal_module_info * pinfo, u8 app_mode) +{ + char tempargv[PATA_NUM_MAX][PATA_STRLENT]; + char *argv[PATA_NUM_MAX]; + char tempbuf[PATA_STRLENT]; + unsigned int Index = 0; + int ioffset = 0; + int agindex = 0; + int intmask = 0; + int retVal; + char name[10] = { '\0' }; + + if (para == NULL) + { + NSRTP_LOGERR("para is null"); + return DMM_MBUF_RET_ERR; + } + + retVal = memset_s(tempargv, sizeof(tempargv), '\0', sizeof(tempargv)); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + retVal = memset_s(argv, sizeof(argv), 0, sizeof(argv)); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + if (NSFW_PROC_MAIN == para->enflag) + { + if (para->iargsnum != 0) + { + if (common_mem_pal_init(para->iargsnum, para->pargs) < 0) + { + COMMON_LOG_PRINT(LOG_ERR, "Cannot init pal\r\n"); + return DMM_MBUF_RET_ERR; + } + else + { + return DMM_MBUF_RET_OK; + } + } + + PARA1_SET(argv, tempargv, agindex, "nStackMain"); + PARA2_SET(argv, tempargv, agindex, "-c", "0x1"); + PARA2_SET(argv, tempargv, agindex, "-n", "4"); + PARA1_SET(argv, tempargv, agindex, "--huge-dir=/mnt/nstackhuge"); + PARA1_SET(argv, tempargv, agindex, "--proc-type=primary"); + + if (app_mode == 1) + { + sprintf(name, "dmm_app_%ld", (long) getpid()); + PARA2_SET(argv, tempargv, agindex, "--file-prefix", name); + PARA1_SET(argv, tempargv, agindex, "--no-pci"); + + // TODO: the size of the memory should not be fixed + PARA2_SET(argv, tempargv, agindex, "-m", "32"); + } + else + { + // TODO: replay the name 'nStackMain' + /* snprintf(name, 10, "dmm_main_%ld", (long) getpid()); */ + PARA2_SET(argv, tempargv, agindex, "--file-prefix", "nStackMain"); + PARA2_SET(argv, tempargv, agindex, "-m", "2048"); + } + + } + else + { + PARA1_SET(argv, tempargv, agindex, "nStackMain"); + PARA2_SET(argv, tempargv, agindex, "--file-prefix", "nStackMain"); + + retVal = sprintf_s(tempbuf, PATA_STRLENT, "0x"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", ioffset); + return DMM_MBUF_RET_ERR; + } + ioffset = retVal; + for (Index = 0; Index < LCORE_MASK_MAX; Index++) + { + if (ioffset >= PATA_STRLENT) + { + NSRTP_LOGERR("SPRINTF_S tempbuf overflow]ioffset=%d", + ioffset); + return DMM_MBUF_RET_ERR; + } + retVal = + sprintf_s(&(tempbuf[ioffset]), PATA_STRLENT - ioffset, "%8u", + pinfo->ilcoremask[Index]); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", ioffset); + return DMM_MBUF_RET_ERR; + } + ioffset = ioffset + retVal; + intmask |= pinfo->ilcoremask[Index]; + } + if (0 == intmask) + { + PARA2_SET(argv, tempargv, agindex, "-c", "0x1"); + } + else + { + PARA2_SET(argv, tempargv, agindex, "-c", tempbuf); + } + if (pinfo->ishare_mem_size > 0) + { + retVal = memset_s(tempbuf, PATA_STRLENT, 0, PATA_NUM_MAX); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + retVal = + sprintf_s(tempbuf, PATA_STRLENT, "%d", + pinfo->ishare_mem_size); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + PARA2_SET(argv, tempargv, agindex, "-m", tempbuf); + } + + retVal = memset_s(tempbuf, PATA_STRLENT, 0, PATA_NUM_MAX); + if (EOK != retVal) + { + NSRTP_LOGERR("MEMSET_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + + switch (pinfo->ucproctype) + { + case DMM_PROC_T_PRIMARY: + retVal = + sprintf_s(tempbuf, PATA_STRLENT, "--proc-type=primary"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + case DMM_PROC_T_SECONDARY: + retVal = + sprintf_s(tempbuf, PATA_STRLENT, "--proc-type=secondary"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + case DMM_PROC_T_AUTO: + default: + retVal = sprintf_s(tempbuf, PATA_STRLENT, "--proc-type=auto"); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + return DMM_MBUF_RET_ERR; + } + break; + } + PARA1_SET(argv, tempargv, agindex, tempbuf); + + if (DMM_HUGTBL_DISABLE == pinfo->uchugeflag) + { + PARA1_SET(argv, tempargv, agindex, "--no-huge"); + } + } + if (common_mem_pal_init(agindex, argv) < 0) + { + COMMON_LOG_PRINT(LOG_ERR, "Cannot init pal\r\n"); + return DMM_MBUF_RET_ERR; + } + return DMM_MBUF_RET_OK; +} + +void *nscomm_memzone_data_reserve_name(const char *name, size_t len, + int socket_id) +{ + const struct common_mem_memzone *mz = NULL; + /* + rte_memzone_reserve must Call first, cause rte_memzone_reserve has a globe lock. + while proc race happen, who(calls A) got lock first will create memzone success. + others create same memzone proc will got lock after A, and rte_memzone_reserve return NULL; + so while rte_memzone_reserve return NULL we need do rte_memzone_lookup; + */ + mz = common_mem_memzone_reserve(name, len, socket_id, 0); + if (mz == NULL) + { + mz = common_mem_memzone_lookup(name); + } + + return mz ? (void *) ADDR_SHTOL(mz->addr_64) : NULL; +} + +void *nscomm_memzone_data_lookup_name(const char *name) +{ + void *addr = NULL; + const struct common_mem_memzone *mz = NULL; + mz = common_mem_memzone_lookup(name); + if (mz == NULL) + { + return NULL; + } + addr = (void *) ADDR_SHTOL(mz->addr_64); + return addr; +} diff --git a/stacks/lwip_stack/src/mem/lib_common_mem/common_func.c b/stacks/lwip_stack/src/mem/lib_common_mem/common_func.c new file mode 100644 index 0000000..6dd3d13 --- /dev/null +++ b/stacks/lwip_stack/src/mem/lib_common_mem/common_func.c @@ -0,0 +1,211 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "common_mem_pal_memconfig.h" +#include "common_mem_mbuf.h" +#include "common_mem_common.h" +#include "nstack_log.h" +#include "common_pal_bitwide_adjust.h" + +#include "common_func.h" + +#include "nstack_securec.h" + +#define COMMON_PROCESS_MAPS "/proc/self/maps" + +int g_PrimSameFlg = 1; + +NSTACK_STATIC void **g_PrimAddr2LocalMap = NULL; +NSTACK_STATIC void *g_LocalBaseAddr = NULL; +NSTACK_STATIC void *g_LocalMaxAddr = NULL; +NSTACK_STATIC void *g_LocalCfgAddrBase = NULL; + +NSTACK_STATIC uint64_t *g_LocalAddr2PrimMap = NULL; +NSTACK_STATIC uint64_t g_PrimBaseAddr = 0; +NSTACK_STATIC uint64_t g_PrimMaxAddr = 0; +NSTACK_STATIC uint64_t g_PrimCfgAddrBase = 0; + +NSTACK_STATIC uint64_t g_LBitMask = 0; +NSTACK_STATIC int g_LBitMaskLen = 0; + +uint64_t pal_laddr_to_shddr(void *LAddr) +{ + size_t l2pIdx; + + if (g_PrimSameFlg || LAddr == NULL) + { + return (uint64_t) LAddr; + } + + /*calculate the IDX */ + l2pIdx = (ALIGN_PTR(LAddr) - ALIGN_PTR(g_LocalBaseAddr)) >> g_LBitMaskLen; + + /*check the Hugepage Addr Rang */ + if (LAddr <= g_LocalMaxAddr && LAddr >= g_LocalBaseAddr + && g_LocalAddr2PrimMap[l2pIdx]) + { + return g_LocalAddr2PrimMap[l2pIdx] + (ALIGN_PTR(LAddr) & g_LBitMask); + } + + /*check the Cfg Mapping Addr Rang */ + if (LAddr >= g_LocalCfgAddrBase + && LAddr <= + (void *) ((char *) g_LocalCfgAddrBase + + sizeof(struct common_mem_mem_config))) + { + return g_PrimCfgAddrBase + ((char *) LAddr - + (char *) g_LocalCfgAddrBase); + } + + NSRTP_LOGWAR + ("WARNING!!! Input invalid LAddr]LAddr=%p, g_LocalBaseAddr=%p, g_LocalMaxAddr=%p, g_LocalCfgAddrBase=%p, g_LocalCfgAddrMax=%p.", + LAddr, g_LocalBaseAddr, g_LocalMaxAddr, g_LocalCfgAddrBase, + (char *) g_LocalCfgAddrBase + sizeof(struct common_mem_mem_config)); + + return (uint64_t) LAddr; +} + +void *pal_shddr_to_laddr(uint64_t PAddr) +{ + size_t p2lIdx; + + if (g_PrimSameFlg || PAddr == ALIGN_PTR(NULL)) + { + return (void *) PAddr; + } + + p2lIdx = (PAddr - g_PrimBaseAddr) >> g_LBitMaskLen; + /*check the Hugepage Addr Rang */ + if (PAddr <= g_PrimMaxAddr && PAddr >= g_PrimBaseAddr + && g_PrimAddr2LocalMap[p2lIdx]) + { + return (void *) ((uint64_t) g_PrimAddr2LocalMap[p2lIdx] + + (PAddr & g_LBitMask)); + } + + /*check the Cfg Mapping Addr Rang */ + if (PAddr >= g_PrimCfgAddrBase + && PAddr <= g_PrimCfgAddrBase + sizeof(struct common_mem_mem_config)) + { + return (void *) ((uint64_t) g_LocalCfgAddrBase + PAddr - + g_PrimCfgAddrBase); + } + + NSRTP_LOGWAR + ("WARNING!!! Input invalid PAddr]PAddr=%lx, g_PrimBaseAddr=%lx, g_PrimMaxAddr=%lx, g_PrimCfgAddrBase=%lx, g_PrimCfgAddrMax=%lx.", + PAddr, g_PrimBaseAddr, g_PrimMaxAddr, g_PrimCfgAddrBase, + g_PrimCfgAddrBase + sizeof(struct common_mem_mem_config)); + + return (void *) PAddr; +} + +/*lint +e539 */ + +int dmm_pal_addr_align() +{ + return g_PrimSameFlg; +} + +int32_t +dmm_pktmbuf_pool_iterator(struct common_mem_mempool * mp, uint32_t start, + uint32_t end, dmm_mbuf_item_fun fun, void *argv) +{ + if (NULL == mp || fun == NULL) + { + return 0; + } + + if (start >= mp->size || end <= start) + { + return 0; + } + + int32_t elm_size = mp->elt_size + mp->header_size + mp->trailer_size; + struct common_mem_mbuf *elm_mbuf = (struct common_mem_mbuf *) (STAILQ_FIRST(&mp->mem_list)->addr + start * elm_size + mp->header_size); /*lint !e647 */ + + uint32_t i; + uint32_t mbuf_end = COMMON_MEM_MIN(end, mp->size) - start; + for (i = 0; i < mbuf_end; i++) + { + (void) fun(elm_mbuf, argv); + elm_mbuf = (struct common_mem_mbuf *) ((char *) elm_mbuf + elm_size); + } + + return mbuf_end; +} + +void dmm_addr_print(void) +{ + const struct common_mem_mem_config *mcfg = + common_mem_pal_get_configuration()->mem_config; + int s; + FILE *fd; + char *ptembuf = NULL; + if (!mcfg) + { + NSRTP_LOGERR("mcfg is null"); + return; + } + /*printf base address */ + NSRTP_LOGINF("********master baseaddr begin***************"); + for (s = 0; s < COMMON_MEM_MAX_MEMSEG; ++s) + { + if ((mcfg->memseg[s].len > 0) && (mcfg->memseg[s].addr != 0)) + { + NSRTP_LOGINF("addr:%p, len:%u", mcfg->memseg[s].addr, + mcfg->memseg[s].len); + } + } + NSRTP_LOGINF("********master baseaddr end***************"); + + fd = fopen(COMMON_PROCESS_MAPS, "r"); + if (!fd) + { + NSRTP_LOGERR("/proc/self/maps open fail, erro:%d", errno); + return; + } + + ptembuf = (char *) malloc(BUFSIZ); + if (!ptembuf) + { + NSRTP_LOGERR("malloc buff failed]buff_len=%d", BUFSIZ); + fclose(fd); + return; + } + if (EOK != memset_s(ptembuf, BUFSIZ, 0, BUFSIZ)) + { + NSRTP_LOGERR("MEMSET_S failed] buff=%p", ptembuf); + } + NSRTP_LOGINF("********self process addr space begin***************"); + while (fgets(ptembuf, BUFSIZ, fd) != NULL) + { + NSRTP_LOGERR("%s", ptembuf); + } + NSRTP_LOGINF("********self process addr space end*****************"); + fclose(fd); + free(ptembuf); + return; +} + +void *shmem_shddr_to_laddr(void *addr) +{ + return ADDR_SHTOL(addr); +} + +uint64_t shmem_laddr_to_shddr(void *addr) +{ + return ADDR_LTOSH(addr); +} diff --git a/stacks/lwip_stack/src/mem/lwip_mem_api.c b/stacks/lwip_stack/src/mem/lwip_mem_api.c new file mode 100644 index 0000000..72dd9e5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/lwip_mem_api.c @@ -0,0 +1,86 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <sys/types.h> +#include <unistd.h> +#include <dlfcn.h> +#include "nsfw_mem_api.h" +#include "nstack_securec.h" +#include "nsfw_ring_data.h" +#include "nsfw_init_api.h" +#include "nsfw_shmem_mng.h" + +#define NSFW_MEM_MBUF_CHECK_RET_ERR(mhandle, entype, desc) {\ + if ((NULL == mhandle) || (entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSRTP_LOGERR("input para error]desc=%s,mhandle=%p,mtype=%d", desc, mhandle, entype); \ + return NSFW_MEM_ERR; \ + } \ + } + +#define NSFW_MEM_MBUF_CHECK_RET_NULL(mhandle, entype, desc) {\ + if ((NULL == mhandle) || (entype >= NSFW_MEM_TYPEMAX)) \ + { \ + NSRTP_LOGERR("input para error]desc=%s,mhandle=%p,mtype=%d", desc, mhandle, entype); \ + return NULL; \ + } \ + } + +/***************************************************************************** +* Prototype : nsfw_mem_mbf_alloc +* Description : alloc a mbuf from mbuf pool +* Input : mpool_handle mhandle +* nsfw_mem_type entype +* Output : None +* Return Value : mbuf_handle +* Calls : +* Called By : +*****************************************************************************/ +mbuf_handle nsfw_mem_mbf_alloc(mpool_handle mhandle, nsfw_mem_type entype) +{ + if (entype == NSFW_SHMEM) + { + return nsfw_shmem_mbfalloc(mhandle); + } + + NSPOL_LOGINF(NS_LOG_STACKPOOL_ON, "mbf alloc fail] handle=%p, type=%d", + mhandle, entype); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_mem_mbf_free +* Description : put a mbuf backintp mbuf pool +* Input : mbuf_handle mhandle +* nsfw_mem_type entype +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_mem_mbf_free(mbuf_handle mhandle, nsfw_mem_type entype) +{ + if (entype == NSFW_SHMEM) + { + return nsfw_shmem_mbffree(mhandle); + } + + NSPOL_LOGINF(NS_LOG_STACKPOOL_ON, "mbf free fail] handle=%p, type=%d", + mhandle, entype); + return NSFW_MEM_ERR; + +} diff --git a/stacks/lwip_stack/src/mem/lwip_mem_desc.c b/stacks/lwip_stack/src/mem/lwip_mem_desc.c new file mode 100644 index 0000000..217649a --- /dev/null +++ b/stacks/lwip_stack/src/mem/lwip_mem_desc.c @@ -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. +*/ + +#include <sys/types.h> +#include <unistd.h> +#include "nsfw_mem_api.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_nshmem_ring.h" + +/* *INDENT-OFF* */ +nsfw_ring_ops g_ring_ops_arry_lwip[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX] = { + { + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_shmem_ring_singlethread_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_shmem_ring_singlethread_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_shmem_ring_singlethread_dequeuev + } + }, + { + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_sc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_sc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_sp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_mp_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_mc_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_mc_dequeuev + }, + { + (nsfw_mem_ring_enqueue_fun)nsfw_nshmem_ring_singlethread_enqueue, \ + (nsfw_mem_ring_dequeue_fun)nsfw_nshmem_ring_singlethread_dequeue, \ + (nsfw_mem_ring_dequeuev_fun)nsfw_nshmem_ring_singlethread_dequeuev + } + } +}; +/* *INDENT-ON* */ diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c new file mode 100644 index 0000000..1be5f82 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.c @@ -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. +*/ + +#include "nsfw_mem_api.h" +#include "nsfw_nshmem_mng.h" +#include "nsfw_nshmem_mdesc.h" + +/*no share memory access inferface*/ +nsfw_mem_ops g_nshmem_ops = { + nsfw_nshmem_init, + nsfw_nshmem_destory, + nsfw_nshmem_create, + NULL, + nsfw_nshmem_lookup, + nsfw_nshmem_release, + NULL, + NULL, + NULL, + NULL, + nsfw_nshmem_spcreate, + NULL, + NULL, + nsfw_nshmem_sprelease, + nsfw_nshmem_sp_lookup, + nsfw_nshmem_ringcreate, + NULL, + nsfw_nshmem_ringrelease, + nsfw_nshmem_static, + NULL, /*mem_ops_sp_iterator */ + NULL, /*mem_ops_mbuf_iterator */ +}; diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h new file mode 100644 index 0000000..1b63520 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mdesc.h @@ -0,0 +1,22 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_MDESC_H +#define _NSFW_NSHMEM_MDESC_H + +extern nsfw_mem_ops g_nshmem_ops; + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c new file mode 100644 index 0000000..a3c7f60 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.c @@ -0,0 +1,529 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include "nstack_log.h" +#include "nstack_securec.h" +#include "nsfw_mem_api.h" +#include "nsfw_ring_fun.h" +#include "nsfw_nshmem_ring.h" +#include "nsfw_nshmem_mng.h" + +#include "common_func.h" + +#define nsfw_get_glb_lock() (&g_nshmem_internal_cfg->mlock) + +#define NSFW_NSHMEM_INIT_CHK_RET_NULL() \ + if ((!g_nshmem_internal_cfg) || (!g_nshmem_localdata)) \ + { \ + NSRTP_LOGDBG("Error] g_nshmem_internal_cfg=%p, g_nshmem_localdata=%p", g_nshmem_internal_cfg, g_nshmem_localdata); \ + return NULL; \ + } + +#define NSFW_NSHMEM_INIT_CHK_RET() \ + if ((!g_nshmem_internal_cfg) || (!g_nshmem_localdata)) \ + { \ + NSRTP_LOGDBG("Error] g_nshmem_internal_cfg=%p, g_nshmem_localdata=%p", g_nshmem_internal_cfg, g_nshmem_localdata); \ + return NSFW_MEM_ERR; \ + } + +nsfw_mem_localdata *g_nshmem_localdata = NULL; +nsfw_nshmem_cfg *g_nshmem_internal_cfg = NULL; + +/*look up a mem zone*/ +NSTACK_STATIC inline nsfw_nshmem_mzone *nsfw_nshmem_get_free_zone(void) +{ + int icnt = 0; + + /*g_nshmem_internal_cfg must not be null if come here */ + for (icnt = 0; icnt < COMMON_MEM_MAX_MEMZONE; icnt++) + { + if (g_nshmem_internal_cfg->amemzone[icnt].addr == NULL) + { + return &g_nshmem_internal_cfg->amemzone[icnt]; + } + } + + return NULL; +} + +NSTACK_STATIC inline void nsfw_nshmem_free_zone(nsfw_nshmem_mzone * pzone) +{ + nsfw_nshmem_mzone *pzonebase = &g_nshmem_internal_cfg->amemzone[0]; + nsfw_nshmem_mzone *pzoneend = + &g_nshmem_internal_cfg->amemzone[NSFW_NSHMEM_ZONE_MAX - 1]; + + if ((((int) ((char *) pzone - (char *) pzonebase) < 0) + || ((int) ((char *) pzone - (char *) pzoneend) > 0)) + && ((unsigned int) ((char *) pzone - (char *) pzonebase) % + sizeof(nsfw_nshmem_mzone) != 0)) + { + NSRTP_LOGERR("nshmem free fail] mem=%p", pzone); + return; + } + if (pzone->addr) + { + free(pzone->addr); + } + pzone->addr = NULL; + + int ret = memset_s((void *) pzone, sizeof(nsfw_nshmem_mzone), 0, + sizeof(nsfw_nshmem_mzone)); + if (EOK != ret) + { + NSRTP_LOGERR("MEMSET_S failed] mem=%p, ret=%d", pzone, ret); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_init +* Description : nsh module init +* Input : nsfw_mem_para* para +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 nsfw_nshmem_init(nsfw_mem_para * para) +{ + i32 iret = NSFW_MEM_OK; + NSRTP_LOGINF("nsfw nshmem init begin"); + g_nshmem_localdata = + (nsfw_mem_localdata *) malloc(sizeof(nsfw_mem_localdata)); + + if (NULL == g_nshmem_localdata) + { + NSRTP_LOGERR("nshmem init g_nshmem_localdata malloc fail"); + return NSFW_MEM_ERR; + } + + iret = + memset_s(g_nshmem_localdata, sizeof(nsfw_mem_localdata), 0, + sizeof(nsfw_mem_localdata)); + + if (EOK != iret) + { + NSRTP_LOGERR("nshmem init g_nshmem_localdata MEMSET_S fail"); + goto ERROR; + } + + g_nshmem_internal_cfg = + (nsfw_nshmem_cfg *) malloc(sizeof(nsfw_nshmem_cfg)); + + if (NULL == g_nshmem_internal_cfg) + { + NSRTP_LOGERR("nshmem init g_nshmem_internal_cfg malloc fail"); + goto ERROR; + } + + iret = + memset_s(g_nshmem_internal_cfg, sizeof(nsfw_nshmem_cfg), 0, + sizeof(nsfw_nshmem_cfg)); + + if (EOK != iret) + { + NSRTP_LOGERR("nshmem init g_nshmem_internal_cfg MEMSET_S fail"); + goto ERROR; + } + + g_nshmem_localdata->enflag = para->enflag; + NSRTP_LOGINF("nsfw nshmem init end"); + goto OK; + + ERROR: + iret = NSFW_MEM_ERR; + nsfw_nshmem_destory(); + return iret; + OK: + iret = NSFW_MEM_OK; + return iret; +} + +/* + * memory destory + */ +void nsfw_nshmem_destory(void) +{ + if (g_nshmem_localdata) + { + free(g_nshmem_localdata); + g_nshmem_localdata = NULL; + } + + if (g_nshmem_internal_cfg) + { + free(g_nshmem_internal_cfg); + g_nshmem_internal_cfg = NULL; + } + + return; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_reserv_safe +* Description : malloc a memory and save to memzone +* Input : const char* name +* size_t length +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle nsfw_nshmem_reserv_safe(const char *name, size_t length) +{ + void *addr = NULL; + i32 iret = NSFW_MEM_OK; + nsfw_nshmem_mzone *pmemzone = NULL; + + if (length <= 0) + { + return NULL; + } + + nsfw_write_lock(nsfw_get_glb_lock()); + + addr = malloc(length); + if (!addr) + { + NSRTP_LOGERR("nshmem malloc addr fail] addr=%p", addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + iret = memset_s(addr, length, 0, length); + if (EOK != iret) + { + NSRTP_LOGERR("nshmem malloc addr MEMSET_S fail] addr=%p", addr); + free(addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + pmemzone = nsfw_nshmem_get_free_zone(); + + if (!pmemzone) + { + NSRTP_LOGERR("nshmem get free zone fail"); + free(addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + pmemzone->addr = addr; + pmemzone->length = length; + /*name must be less than NSFW_MEM_APPNAME_LENGTH */ + if (EOK != + strcpy_s((char *) pmemzone->aname, sizeof(pmemzone->aname), name)) + { + NSRTP_LOGERR("STRCPY_S failed]name=%s", name); + free(addr); + nsfw_write_unlock(nsfw_get_glb_lock()); + return NULL; + } + + nsfw_write_unlock(nsfw_get_glb_lock()); + return addr; +} + +/* + * create no shared memory + * nsfw_mem_zone::stname no shared memory name + * nsfw_mem_zone::isize memory size + */ +mzone_handle nsfw_nshmem_create(nsfw_mem_zone * pinfo) +{ + + NSFW_NAME_LENCHECK_RET_NULL(pinfo->stname.aname, "nshmem create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + return nsfw_nshmem_reserv_safe(pinfo->stname.aname, pinfo->lenth); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_lookup +* Description : find a block memory by name +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mzone_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mzone_handle nsfw_nshmem_lookup(nsfw_mem_name * pname) +{ + int icnt = 0; + nsfw_nshmem_mzone *mz = NULL; + + NSFW_NAME_LENCHECK_RET_NULL(pname->aname, "nshmem lookup"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + nsfw_read_lock(nsfw_get_glb_lock()); + + for (icnt = 0; icnt < NSFW_NSHMEM_ZONE_MAX; icnt++) + { + mz = &g_nshmem_internal_cfg->amemzone[icnt]; + + if (mz->addr != NULL + && !strncmp(pname->aname, mz->aname, NSFW_MEM_NAME_LENTH)) + { + nsfw_read_unlock(nsfw_get_glb_lock()); + return mz->addr; + } + } + + nsfw_read_unlock(nsfw_get_glb_lock()); + return NULL; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_release +* Description : free a block memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_nshmem_release(nsfw_mem_name * pname) +{ + int icnt = 0; + nsfw_nshmem_mzone *mz = NULL; + + NSFW_NAME_LENCHECK_RET(pname->aname, "nshmem release"); + NSFW_NSHMEM_INIT_CHK_RET(); + nsfw_read_lock(nsfw_get_glb_lock()); + + for (icnt = 0; icnt < NSFW_NSHMEM_ZONE_MAX; icnt++) + { + mz = &g_nshmem_internal_cfg->amemzone[icnt]; + + if (mz->addr != NULL + && !strncmp(pname->aname, mz->aname, NSFW_MEM_NAME_LENTH)) + { + nsfw_nshmem_free_zone(mz); + nsfw_read_unlock(nsfw_get_glb_lock()); + return NSFW_MEM_OK; + } + } + + nsfw_read_unlock(nsfw_get_glb_lock()); + return NSFW_MEM_OK; + +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_spcreate +* Description : create a memory pool by ring +* Input : nsfw_mem_sppool* pmpinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +*****************************************************************************/ +mring_handle nsfw_nshmem_spcreate(nsfw_mem_sppool * pmpinfo) +{ + size_t len = 0; + unsigned int usnum = common_mem_align32pow2(pmpinfo->usnum + 1); + unsigned int uselt_size = pmpinfo->useltsize; + struct nsfw_mem_ring *pringhead = NULL; + unsigned int uscnt = 0; + char *pmz = NULL; + NSFW_NAME_LENCHECK_RET_NULL(pmpinfo->stname.aname, "nshmem sp create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + + len = + sizeof(struct nsfw_mem_ring) + + (size_t) usnum *sizeof(union RingData_U) + (size_t) usnum *uselt_size; + pringhead = + (struct nsfw_mem_ring *) nsfw_nshmem_reserv_safe(pmpinfo-> + stname.aname, len); + + if (!pringhead) + { + NSRTP_LOGERR("nshmem sp create mzone reserv fail"); + return NULL; + } + + nsfw_mem_ring_init(pringhead, usnum, pringhead, NSFW_NSHMEM, + pmpinfo->enmptype); + pmz = + ((char *) pringhead + sizeof(struct nsfw_mem_ring) + + usnum * sizeof(union RingData_U)); + + for (uscnt = 0; uscnt < usnum; uscnt++) + { + if (0 == + g_ring_ops_arry[pringhead->memtype][pringhead-> + ringflag].ring_ops_enqueue + (pringhead, (void *) pmz)) + { + NSRTP_LOGERR("nsfw_nshmem_ringenqueue enqueue fail] uscnt=%u", + uscnt); + } + + pmz = pmz + uselt_size; + } + + return pringhead; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sp_lookup +* Description : look up a sppool memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +*****************************************************************************/ +mring_handle nsfw_nshmem_sp_lookup(nsfw_mem_name * pname) +{ + return nsfw_nshmem_lookup(pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sprelease +* Description : release a sp pool +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_nshmem_sprelease(nsfw_mem_name * pname) +{ + NSFW_NAME_LENCHECK_RET(pname->aname, "nshmem sp mempool release"); + NSFW_NSHMEM_INIT_CHK_RET(); + return nsfw_nshmem_release(pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ringcreate +* Description : create a ring +* Input : nsfw_mem_mring* pringinfo +* Output : None +* Return Value : mring_handle +* Calls : +* Called By : +* +*****************************************************************************/ +mring_handle nsfw_nshmem_ringcreate(nsfw_mem_mring * pringinfo) +{ + size_t len = 0; + unsigned int usnum = common_mem_align32pow2(pringinfo->usnum + 1); + struct nsfw_mem_ring *pringhead = NULL; + NSFW_NAME_LENCHECK_RET_NULL(pringinfo->stname.aname, + "nshmem ring create"); + NSFW_NSHMEM_INIT_CHK_RET_NULL(); + + len = sizeof(struct nsfw_mem_ring) + usnum * sizeof(union RingData_U); + pringhead = + (struct nsfw_mem_ring *) nsfw_nshmem_reserv_safe(pringinfo-> + stname.aname, len); + + if (!pringhead) + { + NSRTP_LOGERR("nshmem ring create mzone reserv fail"); + return NULL; + } + + nsfw_mem_ring_init(pringhead, usnum, (void *) pringhead, NSFW_NSHMEM, + pringinfo->enmptype); + return pringhead; + +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ringrelease +* Description : release a nsh ring memory +* Input : nsfw_mem_name* pname +* Output : None +* Return Value : i32 +* Calls : +* Called By : +* +*****************************************************************************/ +i32 nsfw_nshmem_ringrelease(nsfw_mem_name * pname) +{ + NSFW_NAME_LENCHECK_RET(pname->aname, "nshmem ring mempool release"); + NSFW_NSHMEM_INIT_CHK_RET(); + return nsfw_nshmem_release(pname); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_sppool_statics +* Description : static the memory size of sppool +* Input : mring_handle sppool +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_nshmem_sppool_statics(mring_handle sppool) +{ + struct nsfw_mem_ring *phead = (struct nsfw_mem_ring *) sppool; + + return sizeof(struct nsfw_mem_ring) + + (ssize_t) phead->size * sizeof(union RingData_U) + + (ssize_t) phead->size * phead->eltsize; +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_ring_statics +* Description : static the memory size of ring +* Input : mring_handle handle +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_nshmem_ring_statics(mring_handle handle) +{ + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) handle; + return ring->size * sizeof(union RingData_U) + + sizeof(struct nsfw_mem_ring); +} + +/***************************************************************************** +* Prototype : nsfw_nshmem_static +* Description : static the memory size according to mem type +* Input : void* handle +* nsfw_mem_struct_type type +* Output : None +* Return Value : ssize_t +* Calls : +* Called By : +* +*****************************************************************************/ +ssize_t nsfw_nshmem_static(void *handle, nsfw_mem_struct_type type) +{ + switch (type) + { + case NSFW_MEM_MBUF: + return -1; + case NSFW_MEM_SPOOL: + return nsfw_nshmem_sppool_statics(handle); + case NSFW_MEM_RING: + return nsfw_nshmem_ring_statics(handle); + default: + break; + } + return -1; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h new file mode 100644 index 0000000..fa5bc6b --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_mng.h @@ -0,0 +1,70 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_MNG_H_ +#define _NSFW_NSHMEM_MNG_H_ + +#include "common_mem_rwlock.h" + +#include "common_func.h" + +#define NSFW_NSHMEM_ZONE_MAX 2560 + +typedef struct +{ + i8 aname[NSFW_MEM_NAME_LENTH]; + void *addr; + int length; +} nsfw_nshmem_mzone; + +typedef struct +{ + nsfw_nshmem_mzone amemzone[NSFW_NSHMEM_ZONE_MAX]; + common_mem_rwlock_t mlock; +} nsfw_nshmem_cfg; + +/* + * no share memory module init + */ +i32 nsfw_nshmem_init(nsfw_mem_para * para); + +/* + * no share memory module destory + */ +void nsfw_nshmem_destory(void); + +/* + * create a no shared memory + */ +mzone_handle nsfw_nshmem_create(nsfw_mem_zone * pinfo); + +mzone_handle nsfw_nshmem_lookup(nsfw_mem_name * pname); + +i32 nsfw_nshmem_release(nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_spcreate(nsfw_mem_sppool * pmpinfo); + +i32 nsfw_nshmem_sprelease(nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_sp_lookup(nsfw_mem_name * pname); + +mring_handle nsfw_nshmem_ringcreate(nsfw_mem_mring * pringinfo); + +i32 nsfw_nshmem_ringrelease(nsfw_mem_name * pname); + +ssize_t nsfw_nshmem_static(void *handle, nsfw_mem_struct_type type); + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c new file mode 100644 index 0000000..51f1fa4 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.c @@ -0,0 +1,434 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include <sched.h> +#include "nstack_securec.h" + +#include "nsfw_mem_api.h" +#include "nsfw_nshmem_ring.h" +#include "nsfw_ring_fun.h" +#include "common_func.h" + +/*copy the data to obj*/ +NSTACK_STATIC inline void +nsfw_nshmem_ring_obj_copy(struct nsfw_mem_ring *r, uint32_t cons_head, + void **obj_table, unsigned n) +{ + uint32_t idx = cons_head & r->mask; + unsigned i = 0; + const uint32_t size = r->size; + + if (likely(idx + n < size)) + { + for (i = 0; i < (n & (~(unsigned) 0x3)); i += 4, idx += 4) + { + obj_table[i] = (void *) r->ring[idx].data_l; + obj_table[i + 1] = (void *) r->ring[idx + 1].data_l; + obj_table[i + 2] = (void *) r->ring[idx + 2].data_l; + obj_table[i + 3] = (void *) r->ring[idx + 3].data_l; + } + switch (n & 0x3) + { + case 3: + obj_table[i++] = (void *) r->ring[idx++].data_l; + + case 2: + obj_table[i++] = (void *) r->ring[idx++].data_l; + + case 1: + obj_table[i++] = (void *) r->ring[idx++].data_l; + } + } + else + { + for (i = 0; idx < size; i++, idx++) + { + obj_table[i] = (void *) r->ring[idx].data_l; + } + + for (idx = 0; i < n; i++, idx++) + { + obj_table[i] = (void *) r->ring[idx].data_l; + } + } +} + +/*fork recover*/ +NSTACK_STATIC inline void +nsfw_nshmem_enqueue_fork_recov(struct nsfw_mem_ring *r) +{ + u32_t pidflag = 0; + u32_t curpid = get_sys_pid(); + int success = 0; + /*if pid is not the same, maybe mult thread fork happen */ + pidflag = r->prodhflag; + + if (unlikely(pidflag != curpid)) + { + success = common_mem_atomic32_cmpset(&r->prodhflag, pidflag, curpid); + + if (unlikely(success != 0)) + { + /*recover it */ + if (r->prod.tail != r->prod.head) + { + r->prod.head = r->prod.tail; + } + + r->prodtflag = curpid; + } + } + + return; +} + +NSTACK_STATIC inline void +nsfw_nshmem_dequeue_fork_recov(struct nsfw_mem_ring *r) +{ + u32_t pidflag = 0; + u32_t curpid = get_sys_pid(); + int success = 0; + /*if pid is not the same, maybe mult thread fork happen */ + pidflag = r->conshflag; + + if (unlikely(pidflag != curpid)) + { + success = common_mem_atomic32_cmpset(&r->conshflag, pidflag, curpid); + + if (unlikely(success != 0)) + { + /*recover it */ + if (r->cons.tail != r->cons.head) + { + r->cons.head = r->cons.tail; + } + + r->constflag = curpid; + } + } + + return; +} + +/* +this is a multi thread/process enqueue function, please pay attention to the bellow point +1. while Enqueue corrupt, we may lose one element; because no one to add the Head +*/ +int +nsfw_nshmem_ring_mp_enqueue(struct nsfw_mem_ring *mem_ring, void *obj_table) +{ + uint32_t producer_head, producer_next; + uint32_t consumer_tail, free_entries; + int success; + unsigned rep = 0; + uint32_t mask = mem_ring->mask; + uint32_t size = mem_ring->size; + uint32_t n = 1; + + /* move prod.head atomically */ + do + { + + producer_head = mem_ring->prod.head; + consumer_tail = mem_ring->cons.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * producer_head > consumer_tail). So 'free_entries' is always between 0 + * and size(ring)-1. */ + free_entries = (size + consumer_tail - producer_head); + + /* check that we have enough room in ring */ + if (unlikely(n > free_entries)) + { + return 0; + /* Below code is commented currenlty as its a dead code. */ + } + + /*if pid is not the same, maybe mult thread fork happen */ + nsfw_nshmem_enqueue_fork_recov(mem_ring); + + while (unlikely + ((mem_ring->prod.tail != mem_ring->prod.head) + || (mem_ring->prodtflag != mem_ring->prodhflag))) + { + common_mem_pause(); + } + + producer_next = producer_head + n; + success = + common_mem_atomic32_cmpset(&mem_ring->prod.head, producer_head, + producer_next); + } + while (unlikely(success == 0)); + + mem_ring->ring[producer_head & mask].data_l = (u64) obj_table; + + /* + * If there are other enqueues in progress that preceded us, + * we need to wait for them to complete + */ + while (unlikely(mem_ring->prod.tail != producer_head)) + { + common_mem_pause(); + + /* Set COMMON_RING_PAUSE_REP_COUNT to avoid spin too long waiting + * for other thread finish. It gives pre-emptied thread a chance + * to proceed and finish with ring dequeue operation. */ + /* check the queue can be operate */ + if (++rep == 5) + { + rep = 0; + (void) sched_yield(); + } + } + + mem_ring->prod.tail = producer_next; + return (int) n; +} + +/* + this is a single thread/process enqueue function + */ +int nsfw_nshmem_ring_sp_enqueue(struct nsfw_mem_ring *r, void *obj_table) +{ + uint32_t producer_head, consumer_tail; + uint32_t producer_next, free_entries; + uint32_t mask = r->mask; + uint32_t n = 1; + uint32_t size = r->size; + + producer_head = r->prod.head; + consumer_tail = r->cons.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * producer_head > consumer_tail). So 'free_entries' is always between 0 + * and size(ring)-1. */ + free_entries = size + consumer_tail - producer_head; + + /* check that we have enough room in ring */ + if (unlikely(n > free_entries)) + { + return 0; + } + + nsfw_nshmem_enqueue_fork_recov(r); + + producer_next = producer_head + n; + r->prod.head = producer_next; + + r->ring[producer_head & mask].data_l = (u64) obj_table; + + r->prod.tail = producer_next; + return (int) n; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_nshmem_ring_mc_dequeuev(struct nsfw_mem_ring *r, void **obj_table, + unsigned int n) +{ + uint32_t consumer_head, producer_tail; + uint32_t consumer_next, entries; + int success; + unsigned rep = 0; + uint32_t num = n; + + /* Avoid the unnecessary cmpset operation below, which is also + * potentially harmful when n equals 0. */ + if (unlikely(num == 0)) + { + return 0; + } + + nsfw_nshmem_dequeue_fork_recov(r); + + /* move cons.head atomically */ + do + { + num = n; + consumer_head = r->cons.head; + producer_tail = r->prod.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * cons_head > prod_tail). So 'entries' is always between 0 + * and size(ring)-1. */ + entries = (producer_tail - consumer_head); + + /* Set the actual entries for dequeue */ + if (unlikely(num > entries)) + { + if (likely(entries > 0)) + { + num = entries; + } + else + { + return 0; + } + } + + /* check the queue can be operate */ + while (unlikely + ((r->cons.tail != r->cons.head) + || (r->conshflag != r->constflag))) + { + common_mem_pause(); + } + + consumer_next = consumer_head + num; + + success = + common_mem_atomic32_cmpset(&r->cons.head, consumer_head, + consumer_next); + } + while (unlikely(success == 0)); + + nsfw_nshmem_ring_obj_copy(r, consumer_head, obj_table, num); + + /* + * If there are other dequeues in progress that preceded us, + * we need to wait for them to complete + */ + while (unlikely(r->cons.tail != consumer_head)) + { + common_mem_pause(); + + /* Set COMMON_RING_PAUSE_REP_COUNT to avoid spin too long waiting + * for other thread finish. It gives pre-emptied thread a chance + * to proceed and finish with ring dequeue operation. */ + /* check the queue can be operate */ + if (++rep == 5) + { + rep = 0; + (void) sched_yield(); + } + } + + r->cons.tail = consumer_next; + + return (int) num; +} + +/*this is a multi thread/process dequeue function, please pay attention to the bellow point +1. while dequeue corrupt, the tail no one added, may multi the try times. +*/ +int nsfw_nshmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_mc_dequeuev(ring, box, 1); +} + +/* + this is a single thread/process dequeue function +*/ +int +nsfw_nshmem_ring_sc_dequeuev(struct nsfw_mem_ring *r, void **obj_table, + unsigned int n) +{ + uint32_t consumer_head, producer_tail; + uint32_t consumer_next, entries; + uint32_t inum = n; + consumer_head = r->cons.head; + producer_tail = r->prod.tail; + /* The subtraction is done between two unsigned 32bits value + * (the result is always modulo 32 bits even if we have + * cons_head > prod_tail). So 'entries' is always between 0 + * and size(ring)-1. */ + entries = producer_tail - consumer_head; + + if (unlikely(inum > entries)) + { + if (likely(entries > 0)) + { + inum = entries; + } + else + { + return 0; + } + } + + nsfw_nshmem_dequeue_fork_recov(r); + + consumer_next = consumer_head + inum; + r->cons.head = consumer_next; + + nsfw_nshmem_ring_obj_copy(r, consumer_head, obj_table, inum); + + r->cons.tail = consumer_next; + return (int) inum; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int nsfw_nshmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_sc_dequeuev(ring, box, 1); +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + u32 head = 0; + + /*if queue is full, just return 0 */ + if (unlikely(ring->prod.head >= (ring->size + ring->cons.tail))) + { + return 0; + } + + head = ring->prod.head; + ring->ring[head & ring->mask].data_l = (u64) box; + ring->prod.head++; + return 1; +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + return nsfw_nshmem_ring_singlethread_dequeuev(ring, box, 1); +} + +/*stack just using one thread, for performance using que not support multi thread*/ +int +nsfw_nshmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, + void **box, unsigned int n) +{ + u32 tail = 0; + u32 num = 0; + + while (num < n) + { + tail = ring->cons.tail; + + /* if all entries are dequeued return 0 */ + if (unlikely(ring->prod.head == ring->cons.tail)) + { + return num; + } + + box[num] = (void *) ring->ring[tail & ring->mask].data_l; + ring->cons.tail++; + num++; + } + + return num; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h new file mode 100644 index 0000000..f7f7732 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_nshmem/nsfw_nshmem_ring.h @@ -0,0 +1,38 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_NSHMEM_RING_H_ +#define _NSFW_NSHMEM_RING_H_ + +#include <stdint.h> +#include "nsfw_ring_data.h" + +int nsfw_nshmem_ring_mp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_nshmem_ring_sp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_nshmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_nshmem_ring_mc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_nshmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_nshmem_ring_sc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_nshmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, + void *box); +int nsfw_nshmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, + void **box); +int nsfw_nshmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, + void **box, unsigned int n); + +#endif /*_NSFW_NSHMEM_RING_H_*/ diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c new file mode 100644 index 0000000..9016282 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.c @@ -0,0 +1,989 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdint.h> +#include "nstack_securec.h" +#include "nstack_log.h" +#include "nsfw_ring_fun.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_shmem_mng.h" +#include "common_mem_buf.h" +#include "common_mem_common.h" + +#include "common_func.h" +#include "common_pal_bitwide_adjust.h" + +/*get the base address of msg data */ +#define NSFW_SHMEM_GET_DATA(pmsg, type) (type *)&((pmsg)->aidata[0]) + +/*if input point is nun, just return null*/ +#define NSFW_POINT_CHK_RET_NULL(p, desc) \ + if (NULL == (p)) \ + { \ + NSRTP_LOGERR("point check fail] desc_para=%s", desc); \ + return NULL; \ + } + +/*if input point is nun, just return err num*/ +#define NSFW_POINT_CHK_RET_ERR(p, desc) \ + if (NULL == (p)) \ + { \ + NSRTP_LOGDBG("point check fail] desc_para=%s", desc); \ + return NSFW_MEM_ERR; \ + } + +/*if input point is nun, goto flag*/ +#define NSFW_POINT_CHK_RET_GOTO(p, gotoflag, desc) \ + if (NULL == (p)) \ + { \ + NSRTP_LOGERR("point check fail] desc_para=%s", desc); \ + goto gotoflag; \ + } + +/*init the msg head*/ +#define NSFW_SHMEM_MSG_HEAD_INIT(pmsg, type, length) { \ + (pmsg)->usmsg_type = (type); \ + (pmsg)->uslenth = (length); \ + } + +/*rsp msg head check, and if err goto*/ +#define NSFW_SHMEM_MSGHEAD_CHK_GOTO(pmsg, type, length, gotoflag) { \ + if (((type) != pmsg->usmsg_type) && ((length) != pmsg->uslenth)) \ + { \ + NSRTP_LOGERR("check fail] msgtype=%d, type_para=%d, len=%d", (pmsg->usmsg_type), (type), (length)); \ + goto gotoflag; \ + } \ + } + +/*rsp check the state*/ +#define NSFW_SHMEM_ACKSTATE_CHK_GOTO(expret, ret, expseg, seg, gotoflag) { \ + if (((ret) != (expret)) || ((expseg) != (seg))) \ + { \ + NSRTP_LOGERR("ackstate check fail]msgack exp=%d, real=%d,eseg=%d, rseg=%d", (expret), (ret), (expseg), (seg)); \ + goto gotoflag; \ + } \ + } + +/*mzone msg init*/ +#define NSFW_SHMEM_MZONE_DATA_INIT(pdata, slength, seg, socketid) { \ + (pdata)->isocket_id = (socketid); \ + (pdata)->lenth = (slength); \ + (pdata)->usseq = (seg); \ + (pdata)->ireserv = 0; \ + } + +/*mbuf msg init*/ +#define NSFW_SHMEM_MBUF_DATA_INIT(pdata, seg, num, cashsize, priv_size, data_room, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->uscash_size = (cashsize); \ + (pdata)->uspriv_size = (priv_size); \ + (pdata)->usdata_room = (data_room); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +/*mpool msg init*/ +#define NSFW_SHMEM_MPOOL_DATA_INIT(pdata, seg, num, eltsize, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->useltsize = (eltsize); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +/*mring msg init*/ +#define NSFW_SHMEM_MRING_DATA_INIT(pdata, seg, num, flag, socketid) { \ + (pdata)->usseq = (seg); \ + (pdata)->usnum = (num); \ + (pdata)->enmptype = (flag); \ + (pdata)->isocket_id = (socketid); \ + (pdata)->ireserv = 0; \ + } + +#define NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg) {\ + if (pmsg) \ + { \ + nsfw_mgr_msg_free(pmsg); \ + } \ + if (prsp_msg) \ + { \ + nsfw_mgr_msg_free(prsp_msg); \ + } \ +} + +/* + * create a block memory by send a msg + * + */ +mzone_handle +nsfw_memzone_remote_reserv(const i8 * name, size_t mlen, i32 socket_id) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head point define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data point define */ + nsfw_shmem_reserv_req *pdata = NULL; + nsfw_shmem_msg_head *pack_head = NULL; + + /*ack msg define */ + nsfw_shmem_ack *pack_data = NULL; + + mzone_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote reserv pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, "remote reserv rspmsg alloc"); + + /*msg head init */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RESERV_REQ_MSG, + sizeof(nsfw_shmem_reserv_req)); + + /*msg data init */ + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_reserv_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("reserv mem copy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MZONE_DATA_INIT(pdata, mlen, (u16) 0, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("reserv mem req rsp fail] ret=%u", ucret); + goto release; + } + + /*interrupt msg head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RESERV_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, pack_data->cstate, 0, + pack_data->usseq, release); + + hhandle = (mzone_handle) ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("mem reserve] name=%s, handle=%p, seg=%u", name, hhandle, + pack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create some memories by send a msg + */ +i32 +nsfw_memzone_remote_reserv_v(nsfw_mem_zone * pmeminfo, + mzone_handle * paddr_array, i32 inum, pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_reserv_req *pdata = NULL; + nsfw_shmem_reserv_req *ptempdata = NULL; + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + u16 ussegbase = 0; + u16 ustempv = 0; + i32 ieltnum = 0; + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof(nsfw_shmem_msg_head)) / sizeof(nsfw_shmem_reserv_req); + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO(pmsg, err, "remote reserv_v msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, err, "remote reserv_v rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + + ptempdata = pdata = + NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_reserv_req); + + do + { + icount++; + ieltnum++; + + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RESERV_REQ_MSG, + ieltnum * sizeof(nsfw_shmem_reserv_req)); + + itindex = icount - 1; + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmeminfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + } + NSFW_SHMEM_MZONE_DATA_INIT(ptempdata, pmeminfo[itindex].lenth, + (u16) itindex, + pmeminfo[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("reserv v mem req rsp fail] ret=%u", ucret); + goto err; + } + + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RESERV_ACK_MSG, + ieltnum * sizeof(nsfw_shmem_ack), + err); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + ustempv = ussegbase + iindex; + + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, ustempv, + (u16) pack_data->usseq, err); + + paddr_array[ustempv] = ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("remote reserve]index=%u, seg=%u, handle=%p", + ustempv, pack_data->usseq, paddr_array[ustempv]); + pack_data++; + } + + ussegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmeminfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + } + NSFW_SHMEM_MZONE_DATA_INIT(ptempdata, pmeminfo[itindex].lenth, + (u16) itindex, + pmeminfo[itindex].isocket_id); + ptempdata++; + } + } + while (icount < inum); + + iretval = NSFW_MEM_OK; + goto free; + + err: + iretval = NSFW_MEM_ERR; + free: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return iretval; +} + +/* + *release a block memory with name by send msg + */ +i32 nsfw_remote_free(const i8 * name, nsfw_mem_struct_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + nsfw_shmem_msg_head *pdata_head = NULL; + + nsfw_shmem_free_req *pdata = NULL; + + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *pack_data = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_ERR(pmsg, "remote free msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, terr, "remote free rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RELEASE_REQ_MSG, + sizeof(nsfw_shmem_free_req)); + + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_free_req); + if (EOK != strcpy_s(pdata->aname, sizeof(pdata->aname), name)) + { + NSRTP_LOGERR("STRCPY_S failed]name=%s", name); + } + pdata->usseq = 0; + pdata->ustype = entype; + pdata->ireserv = 0; + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("free mem req rsp fail] ret=%u", ucret); + goto release; + } + + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RELEASE_ACK_MSG, + sizeof(nsfw_shmem_ack), terr); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, pack_data->cstate, 0, + pack_data->usseq, terr); + + iretval = NSFW_MEM_OK; + goto release; + terr: + iretval = NSFW_MEM_ERR; + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return iretval; +} + +/* + *create a mbuf pool by send a msg + */ +mpool_handle +nsfw_remote_shmem_mbf_create(const i8 * name, unsigned n, + unsigned cache_size, unsigned priv_size, + unsigned data_room_size, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_mbuf_req *pdata = NULL; + nsfw_shmem_msg_head *tpack_head = NULL; + nsfw_shmem_ack *tpack_data = NULL; + mpool_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote mbf create pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, "remote mbf create msg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_MBUF_REQ_MSG, + sizeof(nsfw_shmem_mbuf_req)); + + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_mbuf_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("mbf create name cpy fail] ret=%d", iretval); + goto release; + } + + NSFW_SHMEM_MBUF_DATA_INIT(pdata, 0, n, cache_size, priv_size, + data_room_size, (u16) entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mbf create mem req rsp fail] ret=%u", ucret); + goto release; + } + + tpack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(tpack_head, NSFW_MBUF_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + tpack_data = NSFW_SHMEM_GET_DATA(tpack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, tpack_data->cstate, 0, + tpack_data->usseq, release); + + hhandle = ADDR_SHTOL(tpack_data->pbase_addr); + NSRTP_LOGDBG("mbf create] name=%s, handle=%p, seg=%u", name, hhandle, + tpack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create some mbuf pools + */ +i32 +nsfw_remote_shmem_mbf_createv(nsfw_mem_mbfpool * pmbfname, + mpool_handle * phandle_array, i32 inum, + pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *mbpmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + + nsfw_shmem_mbuf_req *pdata = NULL; + nsfw_shmem_mbuf_req *ptempdata = NULL; + + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + mpool_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + i32 isegbase = 0; + i32 ieltnum = 0; + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof(nsfw_shmem_msg_head)) / sizeof(nsfw_shmem_mbuf_req); + + mbpmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO(mbpmsg, lerr, "remote mbf createv msg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, lerr, + "remote mbf createv rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, mbpmsg); + + ptempdata = pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_mbuf_req); + + do + { + icount++; + ieltnum++; + + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_MBUF_REQ_MSG, + ieltnum * sizeof(nsfw_shmem_mbuf_req)); + + /*fill msg data */ + itindex = icount - 1; + if (-1 == + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmbfname[itindex].stname.aname, pid)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + goto lerr; + } + NSFW_SHMEM_MBUF_DATA_INIT(ptempdata, (u16) itindex, + pmbfname[itindex].usnum, + pmbfname[itindex].uscash_size, + pmbfname[itindex].uspriv_size, + pmbfname[itindex].usdata_room, + pmbfname[itindex].enmptype, + pmbfname[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(mbpmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mbf createv mem req rsp fail] ret=%d", ucret); + goto lerr; + } + + /*interrupt msg head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_MBUF_ACK_MSG, + ieltnum * sizeof(nsfw_shmem_ack), + lerr); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, + (isegbase + iindex), + (u16) pack_data->usseq, lerr); + phandle_array[isegbase + iindex] = + ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("mbf createv] seg=%d, handle=%p", + pack_data->usseq, hhandle); + pack_data++; + } + + isegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + if (-1 == + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmbfname[itindex].stname.aname, pid)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + goto lerr; + } + NSFW_SHMEM_MBUF_DATA_INIT(ptempdata, (u16) itindex, + pmbfname[itindex].usnum, + pmbfname[itindex].uscash_size, + pmbfname[itindex].uspriv_size, + pmbfname[itindex].usdata_room, + pmbfname[itindex].enmptype, + pmbfname[itindex].isocket_id); + ptempdata++; + } + } + while (icount < inum); + + /*release memory */ + iretval = NSFW_MEM_OK; + goto release; + + lerr: + iretval = NSFW_MEM_ERR; + release: + NSFW_SHMEM_MSG_FREE(mbpmsg, prsp_msg); + return iretval; +} + +/* + *create a simpile pool + */ +mring_handle +nsfw_remote_shmem_mpcreate(const char *name, unsigned int n, + unsigned int elt_size, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + nsfw_shmem_msg_head *pdata_head = NULL; + nsfw_shmem_sppool_req *pdata = NULL; + nsfw_shmem_msg_head *mppack_head = NULL; + nsfw_shmem_ack *mppack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote mbf mpcreate pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, + "remote mpcreate rspmsg alloc"); + + /*init msg head */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_SPPOOL_REQ_MSG, + sizeof(nsfw_shmem_sppool_req)); + + /*fill msg data */ + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_sppool_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("mp create copy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MPOOL_DATA_INIT(pdata, 0, n, elt_size, entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mp create rsp fail] ret=%d", ucret); + goto release; + } + + /*get msg head */ + mppack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(mppack_head, NSFW_SPPOOL_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + mppack_data = NSFW_SHMEM_GET_DATA(mppack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, mppack_data->cstate, 0, + mppack_data->usseq, release); + + hhandle = ADDR_SHTOL(mppack_data->pbase_addr); + NSRTP_LOGDBG("mpcreate] name=%s, handle=%p, seg=%d", name, hhandle, + mppack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create some simpile pools by send a msg + */ +i32 +nsfw_remote_shmem_mpcreatev(nsfw_mem_sppool * pmpinfo, + mring_handle * pringhandle_array, i32 inum, + pid_t pid) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_sppool_req *pdata = NULL; + nsfw_shmem_sppool_req *ptempdata = NULL; + + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + + nsfw_shmem_ack *pack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + i32 icount = 0; + i32 itindex = 0; + i32 iindex = 0; + i32 isegbase = 0; + i32 ieltnum = 0; + /*the max members that a msg can take */ + i32 ieltnum_max = + (NSFW_MGR_MSG_BODY_LEN - + sizeof(nsfw_shmem_msg_head)) / sizeof(nsfw_shmem_sppool_req); + + /*alloc a msg */ + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_GOTO(pmsg, mperr, "remote mpcreatev pmsg alloc"); + + /*alloc rsp msg */ + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, mperr, "remote mpcreatev rspmsg alloc"); + + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + + ptempdata = pdata = + NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_sppool_req); + + do + { + icount++; + ieltnum++; + + /*if the element num reach the bigest, or already send all, just deal */ + if (((icount % ieltnum_max) == 0) || (icount >= inum)) + { + /*init msg header */ + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_SPPOOL_REQ_MSG, + ieltnum * sizeof(nsfw_shmem_sppool_req)); + + /*fill the msg data */ + itindex = icount - 1; + + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmpinfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S fail]ret=%d", retVal); + goto mperr; + } + NSFW_SHMEM_MPOOL_DATA_INIT(ptempdata, itindex, + pmpinfo[itindex].usnum, + pmpinfo[itindex].useltsize, + pmpinfo[itindex].enmptype, + pmpinfo[itindex].isocket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mpcreatev create fail] ret=%u", ucret); + goto mperr; + } + + /*interrupt mgs head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_SPPOOL_ACK_MSG, + ieltnum * sizeof(nsfw_shmem_ack), + mperr); + + pack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + + for (iindex = 0; iindex < ieltnum; iindex++) + { + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, + pack_data->cstate, + (isegbase + iindex), + (u16) pack_data->usseq, mperr); + pringhandle_array[isegbase + iindex] = + ADDR_SHTOL(pack_data->pbase_addr); + NSRTP_LOGDBG("mpcreatev] seg=%u, handle=%p", pack_data->usseq, + hhandle); + pack_data++; + } + + isegbase = icount; + ieltnum = 0; + ptempdata = pdata; + } + else + { + itindex = icount - 1; + int retVal = + sprintf_s(ptempdata->aname, sizeof(ptempdata->aname), "%s_%x", + pmpinfo[itindex].stname.aname, pid); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S fail]ret=%d", retVal); + goto mperr; + } + NSFW_SHMEM_MPOOL_DATA_INIT(ptempdata, itindex, + pmpinfo[itindex].usnum, + pmpinfo[itindex].useltsize, + pmpinfo[itindex].enmptype, + pmpinfo[itindex].isocket_id); + + ptempdata++; + } + } + while (icount < inum); + + /*release the memory */ + iretval = NSFW_MEM_OK; + goto release; + + mperr: + iretval = NSFW_MEM_ERR; + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return iretval; +} + +/* + *create a ring + */ +mring_handle +nsfw_remote_shmem_ringcreate(const char *name, unsigned int n, i32 socket_id, + nsfw_mpool_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + + /*msg head define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_ring_req *pdata = NULL; + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *ppack_data = NULL; + mring_handle hhandle = NULL; + u8 ucret = TRUE; + i32 iretval = NSFW_MEM_OK; + + //pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MASTER); + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote ringcreate pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, release, + "remote ringcreate rspmsg alloc"); + + /*fill msg head */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_RING_REQ_MSG, + sizeof(nsfw_shmem_ring_req)); + + /*fill msg data */ + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_ring_req); + iretval = strcpy_s(pdata->aname, sizeof(pdata->aname), name); + if (EOK != iretval) + { + NSRTP_LOGERR("ring create cpy name fail] ret=%d", iretval); + goto release; + } + + /*fill msg data */ + NSFW_SHMEM_MRING_DATA_INIT(pdata, 0, n, entype, socket_id); + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("ring create rsp fail] ret=%d", ucret); + goto release; + } + + /*interrupt mgs head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_RING_ACK_MSG, + sizeof(nsfw_shmem_ack), release); + + ppack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, ppack_data->cstate, 0, + ppack_data->usseq, release); + + hhandle = ADDR_SHTOL(ppack_data->pbase_addr); + NSRTP_LOGDBG("ring create] name=%s, handle=%p, seg=%u", name, hhandle, + ppack_data->usseq); + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return hhandle; +} + +/* + *create a mem pool that the members are rings by send a msg + *ieltnum:the num of ring member + *iringnum:the num of ring in simple mem pool + *entype:the default the of ring + */ +i32 +nsfw_remote_shmem_ringcreatev(const char *name, i32 ieltnum, + mring_handle * pringhandle_array, i32 iringnum, + i32 socket_id, nsfw_mpool_type entype) +{ + unsigned int useltsize = 0; + mring_handle nhandle = NULL; + i32 icount = 0; + i32 n = 0; + uint64_t baseaddr = 0; + uint64_t endaddr = 0; + /*the num of ring member must be power of 2 */ + unsigned int usnum = common_mem_align32pow2(ieltnum + 1); + + useltsize = + sizeof(struct nsfw_mem_ring) + usnum * sizeof(union RingData_U); + nhandle = + nsfw_remote_shmem_mpcreate(name, iringnum, useltsize, socket_id, + NSFW_MRING_SPSC); + NSFW_POINT_CHK_RET_ERR(nhandle, "remote ringcreatev msg alloc"); + + n = nsfw_shmem_ring_sc_dequeuev(nhandle, (void **) pringhandle_array, + iringnum); + + if (n != iringnum) + { + NSRTP_LOGERR("ring dequeue fail] ringnum=%d, retnum=%d", iringnum, n); + return NSFW_MEM_ERR; + } + + nsfw_shmem_ring_baseaddr_query(&baseaddr, &endaddr); + + for (icount = 0; icount < iringnum; icount++) + { + nsfw_mem_ring_init(pringhandle_array[icount], usnum, + (void *) baseaddr, NSFW_SHMEM, entype); + } + + return NSFW_MEM_OK; +} + +/* + *look up a msg by send a msg + */ +void *nsfw_remote_shmem_lookup(const i8 * name, nsfw_mem_struct_type entype) +{ + /*msg point define */ + nsfw_mgr_msg *pmsg = NULL; + nsfw_mgr_msg *prsp_msg = NULL; + void *addr = NULL; + /*msg head data define */ + nsfw_shmem_msg_head *pdata_head = NULL; + + /*msg data define */ + nsfw_shmem_lookup_req *pdata = NULL; + + /*ack msg define */ + nsfw_shmem_msg_head *pack_head = NULL; + nsfw_shmem_ack *lpack_data = NULL; + u8 ucret = TRUE; + + pmsg = nsfw_mgr_msg_alloc(MGR_MSG_MEM_ALLOC_REQ, NSFW_PROC_MAIN); + NSFW_POINT_CHK_RET_NULL(pmsg, "remote lookup pmsg alloc"); + + prsp_msg = nsfw_mgr_null_rspmsg_alloc(); + NSFW_POINT_CHK_RET_GOTO(prsp_msg, perr, "remote lookup rspmsg alloc"); + + /*msg head init */ + pdata_head = GET_USER_MSG(nsfw_shmem_msg_head, pmsg); + NSFW_SHMEM_MSG_HEAD_INIT(pdata_head, NSFW_MEM_LOOKUP_REQ_MSG, + sizeof(nsfw_shmem_lookup_req)); + + pdata = NSFW_SHMEM_GET_DATA(pdata_head, nsfw_shmem_lookup_req); + if (EOK != strcpy_s(pdata->aname, sizeof(pdata->aname), name)) + { + NSRTP_LOGERR("STRCPY_S failed]name=%s", name); + } + pdata->usseq = 0; + pdata->ustype = entype; + pdata->ireserv = 0; + + ucret = nsfw_mgr_send_req_wait_rsp(pmsg, prsp_msg); + + if (FALSE == ucret) + { + NSRTP_LOGERR("mem lookup fail] ret=%u", ucret); + goto release; + } + + /*interrupt mgs head */ + pack_head = GET_USER_MSG(nsfw_shmem_msg_head, prsp_msg); + NSFW_SHMEM_MSGHEAD_CHK_GOTO(pack_head, NSFW_MEM_LOOKUP_ACK_MSG, + sizeof(nsfw_shmem_ack), perr); + + lpack_data = NSFW_SHMEM_GET_DATA(pack_head, nsfw_shmem_ack); + NSFW_SHMEM_ACKSTATE_CHK_GOTO(NSFW_MEM_ALLOC_SUCC, lpack_data->cstate, 0, + lpack_data->usseq, perr); + + addr = ADDR_SHTOL(lpack_data->pbase_addr); + NSRTP_LOGDBG("shmem lookup] name=%s, handle=%p, seg=%u", name, addr, + lpack_data->usseq); + goto release; + perr: + addr = NULL; + + release: + NSFW_SHMEM_MSG_FREE(pmsg, prsp_msg); + return addr; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h new file mode 100644 index 0000000..0ae5cd5 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_rshmem_mng.h @@ -0,0 +1,51 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_RSHMEM_MNG_H +#define _NSFW_RSHMEM_MNG_H + +mzone_handle nsfw_memzone_remote_reserv(const i8 * name, size_t mlen, + i32 socket_id); +i32 nsfw_memzone_remote_reserv_v(nsfw_mem_zone * pmeminfo, + mzone_handle * paddr_array, i32 inum, + pid_t pid); +i32 nsfw_remote_free(const i8 * name, nsfw_mem_struct_type entype); +mpool_handle nsfw_remote_shmem_mbf_create(const i8 * name, unsigned int n, + unsigned cache_size, + unsigned priv_size, + unsigned data_room_size, + i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_mbf_createv(nsfw_mem_mbfpool * pmbfname, + mpool_handle * phandle_array, i32 inum, + pid_t pid); +mring_handle nsfw_remote_shmem_mpcreate(const char *name, unsigned int n, + unsigned int elt_size, i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_mpcreatev(nsfw_mem_sppool * pmpinfo, + mring_handle * pringhandle_array, i32 inum, + pid_t pid); +mring_handle nsfw_remote_shmem_ringcreate(const char *name, unsigned int n, + i32 socket_id, + nsfw_mpool_type entype); +i32 nsfw_remote_shmem_ringcreatev(const char *name, i32 ieltnum, + mring_handle * pringhandle_array, + i32 iringnum, i32 socket_id, + nsfw_mpool_type entype); + +void *nsfw_remote_shmem_lookup(const i8 * name, nsfw_mem_struct_type entype); + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c new file mode 100644 index 0000000..3d4dd42 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.c @@ -0,0 +1,48 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nsfw_mem_api.h" +#include "nsfw_shmem_mng.h" +#include "nsfw_shmem_mdesc.h" +#include "common_pal_bitwide_adjust.h" +/*the inferaces accessing memory*/ +nsfw_mem_ops g_shmem_ops = { + nsfw_shmem_init, + nsfw_shmem_destroy, + nsfw_shmem_create, + nsfw_shmem_createv, + nsfw_shmem_lookup, + nsfw_shmem_release, + nsfw_shmem_mbfmpcreate, + nsfw_shmem_mbfmpcreatev, + nsfw_shmem_mbfmplookup, + nsfw_shmem_mbfmprelease, + nsfw_shmem_spcreate, + nsfw_shmem_spcreatev, + nswf_shmem_sp_ringcreate, + nsfw_shmem_sprelease, + nsfw_shmem_sp_lookup, + nsfw_shmem_ringcreate, + nsfw_shmem_ring_lookup, + nsfw_shmem_ringrelease, + nsfw_shmem_static, + nsfw_shmem_sp_iterator, + nsfw_shmem_mbuf_iterator, + NULL, + shmem_shddr_to_laddr, + shmem_laddr_to_shddr, + nsfw_attach_core_id +}; diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h new file mode 100644 index 0000000..afd9e29 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mdesc.h @@ -0,0 +1,22 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_MDESC_H_ +#define _NSFW_SHMEM_MDESC_H_ + +extern nsfw_mem_ops g_shmem_ops; + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c new file mode 100644 index 0000000..1066b9a --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.c @@ -0,0 +1,800 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "nstack_securec.h" +#include "nstack_log.h" +#include "nsfw_mem_api.h" +#include "nsfw_ring_fun.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_shmem_mng.h" +#include "common_mem_mempool.h" +#include "common_mem_memzone.h" +#include "common_mem_buf.h" +#include "common_mem_mbuf.h" +#include "nsfw_rshmem_mng.h" +#include "common_mem_api.h" +#include "common_sys_config.h" +#include "nsfw_maintain_api.h" +#include "common_pal_bitwide_adjust.h" + +#include "common_func.h" + +#define NSFW_SHMEM_PID (get_sys_pid()) +#define NSFW_SHMEM_FLAG (g_shmem_localdata->enflag) + +/* app_mode 1: simple stack with APP*/ +extern u8 app_mode; +u8 app_mode = 0; + +nsfw_mem_localdata *g_shmem_localdata = NULL; + +/*check g_mem_localdata*/ +#define NSFW_INIT_CHK_RET() \ + if (!g_shmem_localdata) \ + { \ + return NSFW_MEM_ERR; \ + } + +#define NSFW_INIT_CHK_RET_NULL() \ + if (!g_shmem_localdata) \ + { \ + return NULL; \ + } + +/* + *share memory mng module init + * + */ +i32 nsfw_shmem_init(nsfw_mem_para * para) +{ + common_mem_pal_module_info rteinfo = { 0 }; + i32 iret = NSFW_MEM_ERR; + int flag = 0; + if (!para) + { + return NSFW_MEM_ERR; + } + + NSRTP_LOGINF("nsfw shmem init begin"); + + LCORE_MASK_SET(rteinfo.ilcoremask, 1); + rteinfo.ucproctype = DMM_PROC_T_SECONDARY; + iret = common_pal_module_init(para, &rteinfo, app_mode); + + if (DMM_MBUF_RET_OK != iret) + { + NSRTP_LOGERR("rte init fail] ret=0x%x", iret); + return NSFW_MEM_ERR; + } + + flag = dmm_pal_addr_align(); + if ((0 == flag) && (NSFW_PROC_MAIN == para->enflag)) + { + dmm_addr_print(); + NSRTP_LOGERR + ("rte init addr is not the same with primary] nstackmain flag=%d", + flag); + return NSFW_MEM_ERR; + } + + g_shmem_localdata = + (nsfw_mem_localdata *) malloc(sizeof(nsfw_mem_localdata)); + + if (NULL == g_shmem_localdata) + { + NSRTP_LOGERR("g_shmem_localdata malloc fail"); + return NSFW_MEM_ERR; + } + + iret = + memset_s(g_shmem_localdata, sizeof(nsfw_mem_localdata), 0, + sizeof(nsfw_mem_localdata)); + if (EOK != iret) + { + NSRTP_LOGERR("memset fail] g_shmem_localdata=%p ", g_shmem_localdata); + free(g_shmem_localdata); + g_shmem_localdata = NULL; + return NSFW_MEM_ERR; + } + + g_shmem_localdata->enflag = para->enflag; + + NSRTP_LOGINF("nsfw shmem init end] enflag=%d", para->enflag); + return NSFW_MEM_OK; + +} + +/* + *module destroy + */ +void nsfw_shmem_destroy(void) +{ + if (g_shmem_localdata) + { + free(g_shmem_localdata); + g_shmem_localdata = NULL; + } + + return; +} + +/* + * create a shared memory + * nsfw_mem_zone::stname memory name + * nsfw_mem_zone::isize + */ +mzone_handle nsfw_shmem_create(nsfw_mem_zone * pinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL()if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_memzone_data_reserve_name(pinfo->stname.aname, + pinfo->lenth, + pinfo->isocket_id); + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pinfo->stname.aname, "shmem create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + return NULL; + } + } + + return nsfw_memzone_remote_reserv((char *) &aname[0], pinfo->lenth, + SOCKET_ID_ANY); +} + +/* + *create some memory + *inum must be equal iarray_num + */ +i32 +nsfw_shmem_createv(nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_memzone_remote_reserv_v(pmeminfo, paddr_array, iarray_num, + 0); + } + else + { + return nsfw_memzone_remote_reserv_v(pmeminfo, paddr_array, iarray_num, + NSFW_SHMEM_PID); + } + return NSFW_MEM_ERR; +} + +mzone_handle nsfw_shmem_lookup(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_memzone_data_lookup_name(pname->aname); + } + + if ((NSFW_PROC_NULL == pname->enowner) + || (NSFW_PROC_MAIN == pname->enowner)) + { + int retVal = + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", pname->aname); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed"); + return NULL; + } + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pname->aname, "shmem lookup") + int retVal = + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, + NSFW_SHMEM_PID); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed"); + return NULL; + } + } + + return nsfw_remote_shmem_lookup(aname, NSFW_MEM_MZONE); +} + +i32 nsfw_shmem_release(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + const struct common_mem_memzone *pmzone = NULL; + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + pmzone = common_mem_memzone_lookup(pname->aname); + + if (pmzone) + { + common_mem_memzone_free(pmzone); + } + return NSFW_MEM_OK; + } + else + { + NSFW_NAME_LENCHECK_RET(pname->aname, "shmem free") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed"); + return NSFW_MEM_ERR; + } + } + + return nsfw_remote_free(aname, NSFW_MEM_MZONE); +} + +mpool_handle nsfw_shmem_mbfmpcreate(nsfw_mem_mbfpool * pbufinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_mem_pktmbuf_pool_create(pbufinfo->stname.aname, + pbufinfo->usnum, + pbufinfo->uscash_size, + pbufinfo->uspriv_size, + pbufinfo->usdata_room, + pbufinfo->isocket_id); + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pbufinfo->stname.aname, "mbufpool create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pbufinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_mbf_create(aname, pbufinfo->usnum, + pbufinfo->uscash_size, + pbufinfo->uspriv_size, + pbufinfo->usdata_room, SOCKET_ID_ANY, + pbufinfo->enmptype); +} + +/* + *create some mbuf pools + */ +i32 +nsfw_shmem_mbfmpcreatev(nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_remote_shmem_mbf_createv(pmbfname, phandle_array, + iarray_num, 0); + } + else + { + return nsfw_remote_shmem_mbf_createv(pmbfname, phandle_array, + iarray_num, NSFW_SHMEM_PID); + } + + return NSFW_MEM_ERR; +} + +mbuf_handle nsfw_shmem_mbfalloc(mpool_handle mhandle) +{ + return (mbuf_handle) + common_mem_pktmbuf_alloc((struct common_mem_mempool *) mhandle); +} + +i32 nsfw_shmem_mbffree(mbuf_handle mhandle) +{ + common_mem_pktmbuf_free((struct common_mem_mbuf *) mhandle); + return NSFW_MEM_OK; +} + +i32 nsfw_shmem_mbfmprelease(nsfw_mem_name * pname) +{ + return NSFW_MEM_OK; +} + +mpool_handle nsfw_shmem_mbfmplookup(nsfw_mem_name * pmbfname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return common_mem_mempool_lookup(pmbfname->aname); + } + + if ((NSFW_PROC_NULL == pmbfname->enowner) + || (NSFW_PROC_MAIN == pmbfname->enowner)) + { + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", + pmbfname->aname)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + else + { + /*app must less than NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pmbfname->aname, "shmem lookup") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pmbfname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_lookup(aname, NSFW_MEM_MBUF); +} + +mring_handle nsfw_shmem_spcreate(nsfw_mem_sppool * pmpinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_shmem_pool_create(pmpinfo->stname.aname, pmpinfo->usnum, + pmpinfo->useltsize, pmpinfo->isocket_id, + pmpinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET_NULL(pmpinfo->stname.aname, "mpool create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pmpinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_mpcreate(aname, pmpinfo->usnum, + pmpinfo->useltsize, SOCKET_ID_ANY, + pmpinfo->enmptype); +} + +i32 +nsfw_shmem_spcreatev(nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num) +{ + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_remote_shmem_mpcreatev(pmpinfo, pringhandle_array, inum, + 0); + } + else + { + return nsfw_remote_shmem_mpcreatev(pmpinfo, pringhandle_array, inum, + NSFW_SHMEM_PID); + } + return NSFW_MEM_ERR; +} + +i32 +nsfw_lshmem_ringcreatev(const char *name, i32 ieltnum, + mring_handle * pringhandle_array, i32 iringnum, + i32 socket_id, nsfw_mpool_type entype) +{ + i32 useltsize = 0; + mring_handle nhandle = NULL; + i32 icount = 0; + i32 n = 0; + uint64_t baseaddr = 0; + uint64_t endaddr = 0; + i32 usnum = common_mem_align32pow2(ieltnum + 1); + + useltsize = + sizeof(struct nsfw_mem_ring) + usnum * sizeof(union RingData_U); + nhandle = + nsfw_shmem_pool_create(name, iringnum, useltsize, socket_id, + NSFW_MRING_SPSC); + if (NULL == (nhandle)) + { + return NSFW_MEM_ERR; + } + + n = nsfw_shmem_ring_sc_dequeuev(nhandle, (void **) pringhandle_array, + iringnum); + + if (n != iringnum) + { + NSRTP_LOGERR + ("ring dequeuev failed] ring=%p, dequeue num=%d, expect num=%d", + nhandle, n, iringnum); + return NSFW_MEM_ERR; + } + + nsfw_shmem_ring_baseaddr_query(&baseaddr, &endaddr); + + for (icount = 0; icount < iringnum; icount++) + { + nsfw_mem_ring_init(pringhandle_array[icount], usnum, + (void *) baseaddr, NSFW_SHMEM, entype); + } + + return NSFW_MEM_OK; +} + +i32 +nswf_shmem_sp_ringcreate(nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, i32 iringnum) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_lshmem_ringcreatev(prpoolinfo->stname.aname, + prpoolinfo->usnum, pringhandle_array, + iringnum, SOCKET_ID_ANY, + prpoolinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET(prpoolinfo->stname.aname, "ring pool") + int retVal = + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + prpoolinfo->stname.aname, NSFW_SHMEM_PID); + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_ringcreatev(aname, prpoolinfo->usnum, + pringhandle_array, iringnum, + SOCKET_ID_ANY, prpoolinfo->enmptype); +} + +i32 nsfw_shmem_sprelease(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + void *mz_mem = NULL; + struct nsfw_mem_ring *ring_ptr = NULL; + NSFW_INIT_CHK_RET(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + mz_mem = common_memzone_data_lookup_name(pname->aname); + + if (mz_mem) + { + ring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof(struct + nsfw_shmem_ring_head)); + nsfw_shmem_pool_free(ring_ptr); + } + return NSFW_MEM_OK; + } + else + { + NSFW_NAME_LENCHECK_RET(pname->aname, "shmem free") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_free(aname, NSFW_MEM_SPOOL); +} + +mring_handle nsfw_shmem_sp_lookup(nsfw_mem_name * pname) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + void *mz_mem = NULL; + struct nsfw_mem_ring *ring_ptr = NULL; + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + mz_mem = common_memzone_data_lookup_name(pname->aname); + + if (mz_mem) + { + ring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof(struct + nsfw_shmem_ring_head)); + return ring_ptr; + } + return mz_mem; + } + + if ((NSFW_PROC_NULL == pname->enowner) + || (NSFW_PROC_MAIN == pname->enowner)) + { + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s", pname->aname)) + { + NSRTP_LOGERR("SPRINTF_S fails]"); + } + } + else + { + /*app's name can not over NSFW_MEM_APPNAME_LENGTH */ + NSFW_NAME_LENCHECK_RET_NULL(pname->aname, "shmem lookup") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pname->aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_lookup(aname, NSFW_MEM_SPOOL); +} + +mring_handle nsfw_shmem_ringcreate(nsfw_mem_mring * pringinfo) +{ + i8 aname[COMMON_MEM_MEMPOOL_NAMESIZE] = { 0 }; + + NSFW_INIT_CHK_RET_NULL(); + + if (NSFW_PROC_MAIN == NSFW_SHMEM_FLAG) + { + return nsfw_shmem_ring_create(pringinfo->stname.aname, + pringinfo->usnum, pringinfo->isocket_id, + pringinfo->enmptype); + } + else + { + NSFW_NAME_LENCHECK_RET_NULL(pringinfo->stname.aname, "ring create") + if (-1 == + sprintf_s(aname, COMMON_MEM_MEMPOOL_NAMESIZE, "%s_%x", + pringinfo->stname.aname, NSFW_SHMEM_PID)) + { + NSRTP_LOGERR("SPRINTF_S failed]"); + } + } + + return nsfw_remote_shmem_ringcreate(aname, pringinfo->usnum, + SOCKET_ID_ANY, pringinfo->enmptype); +} + +mring_handle nsfw_shmem_ring_lookup(nsfw_mem_name * pname) +{ + return nsfw_shmem_lookup(pname); +} + +i32 nsfw_shmem_ringrelease(nsfw_mem_name * pname) +{ + return nsfw_shmem_release(pname); +} + +size_t nsfw_shmem_mbufpool_statics(mpool_handle mbufpool) +{ + struct common_mem_mempool *mp = (struct common_mem_mempool *) mbufpool; + return (size_t) mp->size * (mp->header_size + mp->elt_size + + mp->trailer_size) + + (size_t) mp->private_data_size + + (size_t) + common_mem_ring_get_memsize(common_mem_align32pow2(mp->size + 1)); +} + +size_t nsfw_shmem_sppool_statics(mring_handle sppool) +{ + struct nsfw_shmem_ring_head *temp = NULL; + size_t lent = 0; + temp = + (struct nsfw_shmem_ring_head *) ((char *) sppool - + sizeof(struct nsfw_shmem_ring_head)); + + while (temp) + { + lent += temp->mem_zone->len; + temp = temp->next; + } + + return lent; +} + +size_t nsfw_shmem_ring_statics(mring_handle handle) +{ + struct nsfw_mem_ring *ring = (struct nsfw_mem_ring *) handle; + return ring->size * sizeof(union RingData_U) + + sizeof(struct nsfw_mem_ring); +} + +ssize_t nsfw_shmem_static(void *handle, nsfw_mem_struct_type type) +{ + switch (type) + { + case NSFW_MEM_MBUF: + return nsfw_shmem_mbufpool_statics(handle); + case NSFW_MEM_SPOOL: + return nsfw_shmem_sppool_statics(handle); + case NSFW_MEM_RING: + return nsfw_shmem_ring_statics(handle); + default: + break; + } + return -1; +} + +i32 nsfw_shmem_mbuf_recycle(mpool_handle handle) +{ + return NSFW_MEM_OK; +} + +/***************************************************************************** +* Prototype : nsfw_shmem_sp_iterator +* Description : sp pool iterator +* Input : mpool_handle handle +* u32 start +* u32 end +* nsfw_mem_item_fun fun +* void *argv +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_shmem_sp_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + struct nsfw_mem_ring *perfring_ptr = (struct nsfw_mem_ring *) handle; + if (NULL == perfring_ptr || NULL == fun) + { + return 0; + } + + if (0 == perfring_ptr->eltsize) + { + return 0; + } + + int num = perfring_ptr->size; + if (start >= (u32) num || end <= start) + { + return 0; + } + + struct nsfw_shmem_ring_head *ring_head = + (struct nsfw_shmem_ring_head *) ((char *) handle - + sizeof(struct nsfw_shmem_ring_head)); + void *mz = + (void *) ((char *) perfring_ptr + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U)); + + if (ring_head->mem_zone->len < + sizeof(struct nsfw_shmem_ring_head) + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U)) + { + return 0; + } + + u32 mz_len = + ring_head->mem_zone->len - sizeof(struct nsfw_shmem_ring_head) - + sizeof(struct nsfw_mem_ring) - num * sizeof(union RingData_U); + + u32 start_idx = 0; + u32 elm_num = 0; + elm_num = mz_len / perfring_ptr->eltsize; + while (start > start_idx + elm_num) + { + if (NULL == ring_head->next || NULL == ring_head->next->mem_zone + || 0 == elm_num) + { + return 0; + } + + ring_head = + (struct nsfw_shmem_ring_head *) ring_head->next-> + mem_zone->addr_64; + mz_len = + ring_head->mem_zone->len - sizeof(struct nsfw_shmem_ring_head); + + elm_num = mz_len / perfring_ptr->eltsize; + mz = (void *) ((char *) ring_head + + sizeof(struct nsfw_shmem_ring_head)); + start_idx += elm_num; + } + + u32 cur_idx = start - start_idx; + char *cur_elm = NULL; + int proc_count = 0; + while (cur_idx + start_idx < end && cur_idx + start_idx < (u32) num) + { + if (cur_idx >= elm_num) + { + if (NULL == ring_head->next || NULL == ring_head->next->mem_zone + || 0 == elm_num) + { + break; + } + + ring_head = + (struct nsfw_shmem_ring_head *) ring_head->next-> + mem_zone->addr_64; + mz_len = + ring_head->mem_zone->len - + sizeof(struct nsfw_shmem_ring_head); + + elm_num = mz_len / perfring_ptr->eltsize; + mz = (void *) ((char *) ring_head + + sizeof(struct nsfw_shmem_ring_head)); + start_idx += elm_num; + + cur_idx = 0; + cur_elm = NULL; + continue; + } + + if (NULL == cur_elm) + { + cur_elm = ((char *) mz + cur_idx * perfring_ptr->eltsize); + } + else + { + cur_elm += perfring_ptr->eltsize; + } + + cur_idx++; + proc_count++; + (void) fun(cur_elm, argv); + } + + return proc_count; +} + +i32 +nsfw_shmem_mbuf_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv) +{ + return dmm_pktmbuf_pool_iterator((struct common_mem_mempool *) handle, + start, end, (dmm_mbuf_item_fun) fun, + argv); +} + +int nsfw_attach_core_id(nsfw_mem_name * name) +{ + return 0; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h new file mode 100644 index 0000000..6fbff59 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_mng.h @@ -0,0 +1,135 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_MNG_H +#define _NSFW_SHMEM_MNG_H + +/* + * mem mgr module init + * para:point to nstack_fwmem_para + */ +i32 nsfw_shmem_init(nsfw_mem_para * para); + +/* + * mem mgr module destory + * + */ +void nsfw_shmem_destroy(void); + +/* + * create a block memory with name + * fw_mem_zone::stname name of memory + * fw_mem_zone::isize memory size + */ +mzone_handle nsfw_shmem_create(nsfw_mem_zone * pinfo); + +/* + *create some blocks memory + */ +i32 nsfw_shmem_createv(nsfw_mem_zone * pmeminfo, i32 inum, + mzone_handle * paddr_array, i32 iarray_num); + +/* + *lookup a memory + */ +mzone_handle nsfw_shmem_lookup(nsfw_mem_name * pname); + +/*release the memory*/ +i32 nsfw_shmem_release(nsfw_mem_name * pname); + +/* + *create mbuf pool + */ +mpool_handle nsfw_shmem_mbfmpcreate(nsfw_mem_mbfpool * pbufinfo); + +/* + *create some mbuf pool + */ +i32 nsfw_shmem_mbfmpcreatev(nsfw_mem_mbfpool * pmbfname, i32 inum, + mpool_handle * phandle_array, i32 iarray_num); + +/* + *alloc a mbuf from mbuf pool + */ +mbuf_handle nsfw_shmem_mbfalloc(mpool_handle mhandle); + +/* + *release a mbuf pool + */ +i32 nsfw_shmem_mbffree(mbuf_handle mhandle); + +/* + *put mbuf back to mbuf pool + */ +i32 nsfw_shmem_mbfmprelease(nsfw_mem_name * pname); + +/*look up mbuf mpool*/ +mpool_handle nsfw_shmem_mbfmplookup(nsfw_mem_name * pmbfname); + +/* + *create simple pool + */ +mring_handle nsfw_shmem_spcreate(nsfw_mem_sppool * pmpinfo); + +/* + *create some simple pools + */ +i32 nsfw_shmem_spcreatev(nsfw_mem_sppool * pmpinfo, i32 inum, + mring_handle * pringhandle_array, i32 iarray_num); + +/* + *create a simple pool that members are rings + */ +i32 nswf_shmem_sp_ringcreate(nsfw_mem_mring * prpoolinfo, + mring_handle * pringhandle_array, i32 iringnum); + +/* + *release a simple pool + */ +i32 nsfw_shmem_sprelease(nsfw_mem_name * pname); + +/* + *look up a simple pool + */ +mring_handle nsfw_shmem_sp_lookup(nsfw_mem_name * pname); + +/* + *create a ring with name + */ +mring_handle nsfw_shmem_ringcreate(nsfw_mem_mring * pringinfo); + +/* + *look up a ring with name + */ +mring_handle nsfw_shmem_ring_lookup(nsfw_mem_name * pname); + +/* + *release ring + */ +i32 nsfw_shmem_ringrelease(nsfw_mem_name * pname); + +ssize_t nsfw_shmem_static(void *handle, nsfw_mem_struct_type type); + +i32 nsfw_shmem_mbuf_recycle(mpool_handle handle); + +i32 nsfw_shmem_sp_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); +i32 nsfw_shmem_mbuf_iterator(mpool_handle handle, u32 start, u32 end, + nsfw_mem_item_fun fun, void *argv); + +int nsfw_attach_core_id(nsfw_mem_name * name); + +#endif diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.c b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.c new file mode 100644 index 0000000..f580640 --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.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 <string.h> +#include <common_sys_config.h> + +#include "common_mem_pal_memconfig.h" +#include "nstack_securec.h" +#include "nsfw_shmem_ring.h" +#include "nsfw_ring_fun.h" +#include "common_mem_buf.h" +#include "common_func.h" +#include "common_pal_bitwide_adjust.h" + +void +nsfw_shmem_ring_baseaddr_query(uint64_t * rte_lowest_addr, + uint64_t * rte_highest_addr) +{ + struct common_mem_mem_config *pMemCfg = + common_mem_pal_get_configuration()->mem_config; + struct common_mem_memseg *PMemSegArry = pMemCfg->memseg; + + *rte_lowest_addr = PMemSegArry[0].addr_64; + *rte_highest_addr = PMemSegArry[0].addr_64 + PMemSegArry[0].len; + + int s = 1; + + while (s < COMMON_MEM_MAX_MEMSEG && PMemSegArry[s].len > 0) + { + if (*rte_lowest_addr > PMemSegArry[s].addr_64) + { + *rte_lowest_addr = PMemSegArry[s].addr_64; + } + + if (*rte_highest_addr < PMemSegArry[s].addr_64 + PMemSegArry[s].len) + { + *rte_highest_addr = PMemSegArry[s].addr_64 + PMemSegArry[s].len; + } + + s++; + } + +} + +static unsigned +nsfw_shmem_pool_node_alloc(struct nsfw_mem_ring *perfring_ptr, + unsigned alloc_index, unsigned max_index, + void *mz, size_t mz_len, unsigned elt_size) +{ + size_t alloc_size = 0; + unsigned offset_idx = 0; + NSTCP_LOGINF("mz(%p), mz_len = 0x%x", mz, mz_len); + + while (alloc_size + elt_size <= mz_len) + { + perfring_ptr->ring[alloc_index + offset_idx].data_s.ver = + alloc_index + offset_idx; + perfring_ptr->ring[alloc_index + offset_idx].data_s.val = + ADDR_LTOSH_EXT(mz) - ((uint64_t) perfring_ptr->Addrbase); + mz = (char *) mz + elt_size; + alloc_size += elt_size; + offset_idx++; + + if (alloc_index + offset_idx == max_index) + { + break; + } + } + + return offset_idx; +} + +void nsfw_shmem_pool_free(struct nsfw_mem_ring *perfring_ptr) +{ + struct nsfw_shmem_ring_head *ptemp; + + if (NULL == perfring_ptr) + { + return; + } + + struct nsfw_shmem_ring_head *pnode = + (struct nsfw_shmem_ring_head *) ((char *) perfring_ptr - + sizeof(struct nsfw_shmem_ring_head)); + + while (pnode) + { + // phead is involved in phead->mem_zone + ptemp = pnode->next; + common_mem_memzone_free(pnode->mem_zone); + pnode = ptemp; + } +} + +struct nsfw_mem_ring *nsfw_shmem_pool_create(const char *name, unsigned int n, + unsigned int elt_size, + int socket_id, + unsigned char flag) +{ + struct nsfw_mem_ring *perfring_ptr = NULL; + struct common_mem_memzone *mz_mem; + void *mz = NULL; + + /*get pool size, pool size must pow of 2 */ + unsigned int num = common_mem_align32pow2(n + 1); + + struct nsfw_shmem_ring_head *pcur = NULL; + /*calculate the empty rte_perf_ring Size */ + size_t len = + sizeof(struct nsfw_shmem_ring_head) + sizeof(struct nsfw_mem_ring) + + (size_t) num * sizeof(union RingData_U) + (size_t) num * elt_size; + size_t alloc_len = len; + unsigned int alloc_num = 0; + unsigned int alloc_index = 0; + + size_t mz_len = 0; + + unsigned int mz_index = 1; + char mz_name[128] = { 0 }; + int retVal; + /*we'd better use `strlen(src)` or `sizeof(dst)` to explain copying length of src string. + it's meaningless using `sizeof(dst) - 1` to reserve 1 byte for '\0'. + if copying length equals to or bigger than dst length, just let STRNCPY_S() returns failure. */ + retVal = strncpy_s(mz_name, sizeof(mz_name), name, sizeof(mz_name)); + + if (EOK != retVal) + { + NSTCP_LOGERR("STRNCPY_S failed]ret=%d", retVal); + return NULL; + } + + mz_mem = common_memzone_data_lookup_name(name); + NSTCP_LOGINF("memzone data look up] n=%u,num=%u,len=%zu", n, num, len); + + if (mz_mem) + { + perfring_ptr = + (struct nsfw_mem_ring *) ((char *) mz_mem + + sizeof(struct nsfw_shmem_ring_head)); + return perfring_ptr; + } + + while (alloc_len > 0) + { + if (NULL != perfring_ptr) + { + retVal = + sprintf_s(mz_name, sizeof(mz_name), "%s_%03d", name, + mz_index); + + if (-1 == retVal) + { + NSRTP_LOGERR("SPRINTF_S failed]ret=%d", retVal); + nsfw_shmem_pool_free(perfring_ptr); + return NULL; + } + } + + mz_mem = + (struct common_mem_memzone *) common_mem_memzone_reserve(mz_name, + alloc_len, + socket_id, + 0); + + if (mz_mem == NULL) + { + mz_mem = + (struct common_mem_memzone *) + common_mem_memzone_reserve(mz_name, 0, socket_id, 0); + } + + if (mz_mem == NULL) + { + nsfw_shmem_pool_free(perfring_ptr); + return NULL; + } + + if (NULL == perfring_ptr + && (mz_mem->len < + sizeof(struct nsfw_shmem_ring_head) + + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U))) + { + common_mem_memzone_free(mz_mem); + return NULL; + } + + if (NULL == perfring_ptr) + { + pcur = + (struct nsfw_shmem_ring_head *) ADDR_SHTOL(mz_mem->addr_64); + pcur->mem_zone = mz_mem; + pcur->next = NULL; + + perfring_ptr = + (struct nsfw_mem_ring *) ((char *) pcur + + sizeof(struct + nsfw_shmem_ring_head)); + + mz = (void *) ((char *) perfring_ptr + + sizeof(struct nsfw_mem_ring) + + num * sizeof(union RingData_U)); + mz_len = + mz_mem->len - sizeof(struct nsfw_shmem_ring_head) - + sizeof(struct nsfw_mem_ring) - num * sizeof(union RingData_U); + + uint64_t rte_base_addr; + uint64_t rte_highest_addr; + nsfw_shmem_ring_baseaddr_query(&rte_base_addr, &rte_highest_addr); + nsfw_mem_pool_head_init(perfring_ptr, num, elt_size, + (void *) rte_base_addr, NSFW_SHMEM, + (nsfw_mpool_type) flag); + } + else + { + if (pcur) + { + pcur->next = + (struct nsfw_shmem_ring_head *) + ADDR_SHTOL(mz_mem->addr_64); + pcur = pcur->next; + pcur->mem_zone = mz_mem; + pcur->next = NULL; + + if (mz_mem->len < sizeof(struct nsfw_shmem_ring_head)) + { + NSRTP_LOGERR("mz_len error %d", mz_mem->len); + nsfw_shmem_pool_free(perfring_ptr); + return NULL; + } + + mz = (void *) ((char *) pcur + + sizeof(struct nsfw_shmem_ring_head)); + mz_len = mz_mem->len - sizeof(struct nsfw_shmem_ring_head); + } + } + + alloc_num = + nsfw_shmem_pool_node_alloc(perfring_ptr, alloc_index, num, mz, + mz_len, elt_size); + alloc_index += alloc_num; + + if (alloc_index >= num) + { + break; + } + + // second time allocate should not contained all ring head + alloc_len = + (size_t) (num - alloc_index) * elt_size + + sizeof(struct nsfw_shmem_ring_head); + mz_index++; + } + + return perfring_ptr; +} + +/*ring create*/ +struct nsfw_mem_ring *nsfw_shmem_ring_create(const char *name, unsigned int n, + int socket_id, + unsigned char flag) +{ + struct nsfw_mem_ring *perfring_ptr; + struct common_mem_memzone *mz; + uint64_t rte_base_addr; + uint64_t rte_highest_addr; + + unsigned int num = common_mem_align32pow2(n); + + mz = (struct common_mem_memzone *) common_mem_memzone_reserve(name, + sizeof + (struct + nsfw_mem_ring) + + + num * + sizeof(union + RingData_U), + socket_id, + 0); + + if (mz == NULL) + { + return NULL; + } + + perfring_ptr = mz->addr; + + nsfw_shmem_ring_baseaddr_query(&rte_base_addr, &rte_highest_addr); + nsfw_mem_ring_init(perfring_ptr, num, (void *) rte_base_addr, NSFW_SHMEM, + flag); + + return perfring_ptr; +} + +/* +this is a multi thread/process enqueue function, please pay attention to the bellow point +1. while Enqueue corrupt, we may lose one element; because no one to add the Head +*/ +int nsfw_shmem_ring_mp_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + union RingData_U expectPostVal; + union RingData_U curVal; + unsigned int tmpHead; + unsigned int tmpTail; + unsigned int CurHead = ring->prod.head; + unsigned int mask = ring->mask; + unsigned int size = ring->size; + void *prmBox = NULL; + + prmBox = (void *) ADDR_LTOSH_EXT(box); + + /*do box range check */ + if ((char *) prmBox <= (char *) ring->Addrbase + || (char *) prmBox > (char *) ring->Addrbase + PERFRING_ADDR_RANGE) + { + /*invalid addr of box, can't put in rte_perf_ring, maybe should set a errno here */ + return -1; + } + + do + { + /* + if the ring is Full return directly; this not a exact check, cause we made tail++ after dequeue success. + the thing we could make sure is ring[ring->Tail&mask] already dequeue + */ + tmpTail = ring->cons.tail; + + if (tmpTail + size - CurHead == 0) + { + /* + here we give enqueue a chance to recorrect the Tail, if tail not has Data let tail++ + */ + if (ring->ring[tmpTail & mask].data_s.val == 0) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + tmpTail + 1); + } + else + { + return 0; + } + } + + /* + the old version of ring->ring[CurHead&mask] must CurHead - size, which enqueue set to this pos lasttime + & the val must already dequeue. otherwise this pos can't enqueue; + */ + expectPostVal.data_l = + (((unsigned long long) (CurHead - size)) << VALUE_LEN); + + /* + the new version of ring->ring[CurHead&mask] must CurHead, which enqueue set to this pos this time. + */ + curVal.data_l = + ((((unsigned long long) CurHead) << VALUE_LEN) | + ((char *) prmBox - (char *) ring->Addrbase)); + if (ring->ring[CurHead & mask].data_s.ver == expectPostVal.data_s.ver + && __sync_bool_compare_and_swap(&ring-> + ring[CurHead & mask].data_l, + expectPostVal.data_l, + curVal.data_l)) + { + /* + enqueue success, add Head Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Head, 1) to assume that, if one process enqueue success && been killed before + add Head, other process can recorrect the Head Value; + one more thing the direction of Tail must been add-direction, so we using the condition (ring->Head - CurHead >0x80000000); + while many thread do enqueue at same time, Head may not correct,exp: + thread A get old head 10, thread A want set head to 11 + thread B get old head 10, thread B want set head to 12 + thread A do CAS && thread B do CAS at same time, thread A do CAS success; + the result of head is 11, but the correct Value should be 12; + + then thread C get old head 11, thread C will set head to 13[cause pos 12 already has value, thread C will skill 12], + the head will be recorrect by thread C. + if no thread C, thread A& B are the last enqueue thread; the head must recorrect by the deque function. + */ + tmpHead = ring->prod.head; + + if (0 == (CurHead & 0x03) && tmpHead - CurHead > 0x80000000) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + CurHead + 1); + } + + break; + } + + /* + CurHead++ here; + may be cpu slice is end here; while re-sched CurHead < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurHead++ instead CurHead++ directly. + if using CurHead++ will amplify the probability of ABA problem + */ + /*CurHead++; */ + tmpHead = ring->prod.head; + CurHead = CurHead - tmpHead < mask - 1 ? CurHead + 1 : tmpHead; + } + while (1); + + return 1; +} + +/* + this is a single thread/process enqueue function + */ +int nsfw_shmem_ring_sp_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + union RingData_U texpectPostVal; + union RingData_U curVal; + unsigned int tmpTail; + unsigned int CurHead = ring->prod.head; + unsigned int mask = ring->mask; + unsigned int uisize = ring->size; + void *prmBox = NULL; + + prmBox = (void *) ADDR_LTOSH_EXT(box); + + if ((char *) prmBox <= (char *) ring->Addrbase + || (char *) prmBox > (char *) ring->Addrbase + PERFRING_ADDR_RANGE) + { + return -1; + } + + do + { + tmpTail = ring->cons.tail; + if (tmpTail + uisize - CurHead == 0) + { + /* + *here we give enqueue a chance to recorrect the Tail, if tail not has Data let tail++ + */ + if (ring->ring[tmpTail & mask].data_s.val == 0) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + tmpTail + 1); + } + else + { + return 0; + } + } + texpectPostVal.data_l = + (((unsigned long long) (CurHead - uisize)) << VALUE_LEN); + + curVal.data_l = + ((((unsigned long long) CurHead) << VALUE_LEN) | + ((char *) prmBox - (char *) ring->Addrbase)); + + if (ring->ring[CurHead & mask].data_l == texpectPostVal.data_l) + { + ring->ring[CurHead & mask].data_l = curVal.data_l; + ring->prod.head = CurHead + 1; + break; + } + + CurHead++; + } + while (1); + return 1; +} + +/*this is a multi thread/process dequeue function, please pay attention to the bellow point +*/ +int nsfw_shmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + unsigned int CurTail; + unsigned int tmpTail; + unsigned int tmpHead; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + + CurTail = ring->cons.tail; + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + + if (CurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++ + */ + if (ring->ring[tmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return 0; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + /* + *the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val) + && __sync_bool_compare_and_swap(&ring-> + ring[CurTail & mask].data_l, + ExcpRingVal.data_l, + curNullVal.data_l)) + { + + *box = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + /* + enqueue success, add Tail Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Tail, 1) to assume that, if one process dequeue success && been killed before + add Tail, other process can recorrect the Tail Value; + one more thing the direction of Tail must been add-direction, so we using the condition (rlTail - CurTail >0x80000000); + while multi CAS done the result value of CurTail may not correct, but we don't care, it will be recorrect while next deque done. + + avg CAS cost 200-300 Cycles, so we using cache loop to instead some CAS;[head&tail not exact guide, so no need Do CAS evertime] + here we using 0 == (CurTail&0x11) means we only do CAS while head/tail low bit is 0x11; four times do one CAS. + */ + tmpTail = ring->cons.tail; + + if (0 == (CurTail & 0x03) && tmpTail - CurTail > 0x80000000) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + CurTail + 1); + } + break; + } + + /* + CurTail++ here; + may be cpu slice is end here; while re-sched CurTail < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurTail++ instead CurTail++ directly. + if using CurTail++ will amplify the probability of ABA problem + */ + /*CurTail++; */ + tmpTail = ring->cons.tail; + CurTail = CurTail - tmpTail < mask - 1 ? CurTail + 1 : tmpTail; + } + while (1); + + return 1; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int +nsfw_shmem_ring_mc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + unsigned int uiCurTail; + unsigned int tmpTail; + unsigned int tmpHead; + unsigned int uimask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int deqNum = 0; + uiCurTail = ring->cons.tail; + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + if (uiCurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++; + here must done to avoid some msg can't deque. + */ + if (deqNum == 0 && ring->ring[tmpHead & uimask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return deqNum; + } + } + + curNullVal.data_l = (((unsigned long long) uiCurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[uiCurTail & uimask]; + + /* + *the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val) + && __sync_bool_compare_and_swap(&ring-> + ring[uiCurTail & uimask].data_l, + ExcpRingVal.data_l, + curNullVal.data_l)) + { + + box[deqNum] = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + /* + enqueue success, add Tail Value now + here we using CAS set instead __sync_fetch_and_add(&ring->Tail, 1) to assume that, if one process dequeue success && been killed before + add Tail, other process can recorrect the Tail Value; + one more thing the direction of Tail must been add-direction, so we using the condition (rlTail - CurTail >0x80000000); + + avg CAS cost 200-300 Cycles, so we using cache loop to instead some CAS;[head&tail not exact guide, so no need Do CAS evertime] + here we using 0 == (CurTail&0x11) means we only do CAS while head/tail low bit is 0x11; four times do one CAS. + */ + tmpTail = ring->cons.tail; + + if (0 == (uiCurTail & 0x03) && tmpTail - uiCurTail > 0x80000000) + { + (void) __sync_bool_compare_and_swap(&ring->cons.tail, tmpTail, + uiCurTail + 1); + } + + deqNum++; + } + + /* + CurTail++ here; + may be cpu slice is end here; while re-sched CurTail < ring->Tail < ring->Head; to avoid multi try + we using a cmp & CurTail++ instead CurTail++ directly. + if using CurTail++ will amplify the probability of ABA problem + */ + /*CurTail++; */ + tmpTail = ring->cons.tail; + uiCurTail = + uiCurTail - tmpTail < uimask - 1 ? uiCurTail + 1 : tmpTail; + + } + while (n > deqNum); + + return deqNum; +} + +/* + this is enhanced mc_ring_dequeue, support dequeue multi element one time. +*/ +int nsfw_shmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + unsigned int CurTail; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int uitmpHead; + + CurTail = ring->cons.tail; + + do + { + /*if ring is empty return directly */ + uitmpHead = ring->prod.head; + if (CurTail == uitmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++ + */ + if (ring->ring[uitmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, + uitmpHead, uitmpHead + 1); + } + else + { + return 0; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val)) + { + ring->ring[CurTail & mask].data_l = curNullVal.data_l; + + *box = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + ring->cons.tail = CurTail + 1; + break; + } + + CurTail++; + } + while (1); + + return 1; +} + +/* + this is a single thread/process dequeue function +*/ +int +nsfw_shmem_ring_sc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + unsigned int CurTail; + unsigned int tmpHead; + unsigned int mask = ring->mask; + union RingData_U curNullVal; + union RingData_U ExcpRingVal; + unsigned int usdeqNum = 0; + + CurTail = ring->cons.tail; + + do + { + /*if ring is empty return directly */ + tmpHead = ring->prod.head; + if (CurTail == tmpHead) + { + /* + here we give deque a chance to recorrect the Head, if head has Data let Head++; + here must done to avoid some msg can't deque. + */ + if (usdeqNum == 0 && ring->ring[tmpHead & mask].data_s.val != 0) + { + (void) __sync_bool_compare_and_swap(&ring->prod.head, tmpHead, + tmpHead + 1); + } + else + { + return usdeqNum; + } + } + curNullVal.data_l = (((unsigned long long) CurTail) << VALUE_LEN); + ExcpRingVal = ring->ring[CurTail & mask]; + + /* + the version of ring->ring[CurTail&mask] must CurTail&0xFFFFFF + */ + if ((curNullVal.data_s.ver == ExcpRingVal.data_s.ver) + && (ExcpRingVal.data_s.val)) + { + ring->ring[CurTail & mask].data_l = curNullVal.data_l; + + box[usdeqNum] = + ADDR_SHTOL(((char *) ring->Addrbase + + ExcpRingVal.data_s.val)); + + ring->cons.tail = CurTail + 1; + usdeqNum++; + } + + CurTail++; + } + while (n > usdeqNum); + + return usdeqNum; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, void *box) +{ + u32 head = 0; + void *prmBox = NULL; + + /*if queue is full, just return 0 */ + if (ring->prod.head >= (ring->size + ring->cons.tail)) + { + return 0; + } + + prmBox = (void *) ADDR_LTOSH_EXT(box); + + head = ring->prod.head; + ring->prod.head = head + 1; + ring->ring[head & ring->mask].data_s.ver = head; + ring->ring[head & ring->mask].data_s.val = + (char *) prmBox - (char *) ring->Addrbase; + return 1; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, void **box) +{ + u32 tail = 0; + + /* if all entries are dequeued return 0 */ + if (unlikely(ring->prod.head == ring->cons.tail)) + { + return 0; + } + + tail = ring->cons.tail; + *box = + ADDR_SHTOL((char *) ring->Addrbase + + ring->ring[tail & ring->mask].data_s.val); + ring->ring[tail & ring->mask].data_s.val = 0; + ring->ring[tail & ring->mask].data_s.ver = tail; + ring->cons.tail++; + return 1; +} + +/* nstack just using one thread, for performance using que not support multi thread*/ +int +nsfw_shmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n) +{ + u32 tail = 0; + u32 num = 0; + + while (num < n) + { + tail = ring->cons.tail; + + /* if all entries are dequeued return 0 */ + if (unlikely(ring->prod.head == ring->cons.tail)) + { + return num; + } + + ring->cons.tail = tail + 1; + + box[num] = + ADDR_SHTOL((char *) ring->Addrbase + + ring->ring[tail & ring->mask].data_s.val); + + ring->ring[tail & ring->mask].data_s.val = 0; + ring->ring[tail & ring->mask].data_s.ver = tail; + num++; + } + + return num; +} diff --git a/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h new file mode 100644 index 0000000..af7c30c --- /dev/null +++ b/stacks/lwip_stack/src/mem/nsfw_shmem/nsfw_shmem_ring.h @@ -0,0 +1,60 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef _NSFW_SHMEM_RING_H_ +#define _NSFW_SHMEM_RING_H_ + +#include <stdint.h> + +#include "common_func.h" + +struct nsfw_shmem_ring_head +{ + struct common_mem_memzone *mem_zone; + struct nsfw_shmem_ring_head *next; + unsigned int uireserv[4]; +}; + +void nsfw_shmem_ring_baseaddr_query(uint64_t * rte_lowest_addr, + uint64_t * rte_highest_addr); +struct nsfw_mem_ring *nsfw_shmem_pool_create(const char *name, + unsigned int n, + unsigned int elt_size, + int socket_id, + unsigned char flag); +struct nsfw_mem_ring *nsfw_shmem_ring_create(const char *name, + unsigned int n, int socket_id, + unsigned char flag); + +void nsfw_shmem_pool_free(struct nsfw_mem_ring *perfring_ptr); + +void nsfw_shmem_ring_reset(struct nsfw_mem_ring *ring, unsigned char flag); +int nsfw_shmem_ring_mp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_shmem_ring_sp_enqueue(struct nsfw_mem_ring *ring, void *box); +int nsfw_shmem_ring_mc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_shmem_ring_mc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_shmem_ring_sc_dequeue(struct nsfw_mem_ring *ring, void **box); +int nsfw_shmem_ring_sc_dequeuev(struct nsfw_mem_ring *ring, void **box, + unsigned int n); +int nsfw_shmem_ring_singlethread_enqueue(struct nsfw_mem_ring *ring, + void *box); +int nsfw_shmem_ring_singlethread_dequeue(struct nsfw_mem_ring *ring, + void **box); +int nsfw_shmem_ring_singlethread_dequeuev(struct nsfw_mem_ring *ring, + void **box, unsigned int n); + +#endif /*_NSFW_SHMEM_RING_H_*/ diff --git a/stacks/lwip_stack/src/nStackMain/CMakeLists.txt b/stacks/lwip_stack/src/nStackMain/CMakeLists.txt new file mode 100644 index 0000000..22bf8b8 --- /dev/null +++ b/stacks/lwip_stack/src/nStackMain/CMakeLists.txt @@ -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. +######################################################################### + +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 + nStackFw + stacklwip + nStackHal + nStackAlarm + nTcpdump + nsfw_mem + -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 nStackAlarm stacklwip SECUREC) +else() +ADD_DEPENDENCIES(nStackMain nStackAlarm stacklwip) +endif() + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../alarm/ + ${CMAKE_CURRENT_LIST_DIR}/../maintain/ + ${CMAKE_CURRENT_LIST_DIR}/../include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_shmem/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_nshmem/ +) diff --git a/stacks/lwip_stack/src/nStackMain/main.c b/stacks/lwip_stack/src/nStackMain/main.c new file mode 100644 index 0000000..6f58823 --- /dev/null +++ b/stacks/lwip_stack/src/nStackMain/main.c @@ -0,0 +1,457 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <signal.h> +#include <stdio.h> +#include <pthread.h> +#include <unistd.h> +#include <sched.h> +#include <fcntl.h> +#include <malloc.h> +#include "nstack_securec.h" +#include "nstack_log.h" +#include "types.h" +#include "nsfw_init_api.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" +#include "nsfw_shmem_mdesc.h" +#include "nsfw_nshmem_mdesc.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 32 +#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(); +extern nsfw_ring_ops + g_ring_ops_arry_lwip[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX]; + +#ifdef SYS_MEM_RES_STAT +extern void get_resource_stat(); +#endif + +extern alarm_result ms_alarm_check_func(void *para); +int g_tcpip_thread_stat = 0; //this variable will be used at health check feature + +#if (DPDK_MODULE) +extern void pal_common_usage(void); +#endif + +typedef void (*pSignalFunc) (int); +int app_init(void); + +void helpInfo() +{ + NSPOL_LOGERR + ("-----------------------------------------------------------------" + "\nThe format of arg" + "\nbash:./nStackMain RTE-ARGS stack STACK-ARGS" + "\n RTE-ARGS=-c COREMASK -n NUM [-b <domain:bus:devid.func>] [--socket-mem=MB,...] [-m MB] [-r NUM] [-v] [--file-prefix] [--proc-type <primary|secondary|auto>] [-- xen-dom0]" + "\n STACK-ARGS=-port PORTMASK [-c COREMASK] [-thread NUM]" + "\nUser examples:" + "\nTo make the DPDK run on core mask:0xf,Number of memory channels per processor socket in DPDK is 3 " + "\nTo make the stack run on eth coremask:f" + "\nbash: ./nStackMain -c 0xf -n 3 stack -port f" + "\nTo get more help info for stack:" "\n ./nStackMain --help stack" + "\nTo get more help info for dpdk:" "\n ./nStackMain --help dpdk" + "\n-----------------------------------------------------------------"); + +#ifndef FOR_NSTACK_UT + exit(0); +#endif + +} + +#define SIG_PTRACE __SIGRTMIN + 5 + +void signal_handler(int s) +{ + NSPOL_LOGERR("Received signal exiting.]s=%d", s); + if (s == SIGSEGV) /* add for gdb attach work */ + { + print_call_stack(); + } + + nstack_segment_error(s); + if ((SIG_PTRACE != s) && (SIG_PTRACE + 2 != s)) + { +#ifndef FOR_NSTACK_UT + exit(0); +#endif + } + + int i; + for (i = 0; i < MAX_THREAD; i++) + { + if (g_all_thread[i] != pthread_self() && 0 != g_all_thread[i]) + { + NSFW_LOGERR("send sig thread %d", g_all_thread[i]); + if (0 == pthread_kill(g_all_thread[i], SIG_PTRACE + 2)) + { + return; + } + } + g_all_thread[i] = 0; + } + + for (i = 0; i < MAX_THREAD; i++) + { + if (0 != g_all_thread[i]) + { + return; + } + } + +#ifndef FOR_NSTACK_UT + exit(0); +#endif + + //dpdk_signal_handler(); +} + +void register_signal_handler() +{ +/* donot catch SIGHUP SIGTERM */ + static const int s_need_handle_signals[] = { + SIGABRT, + SIGBUS, + SIGFPE, + SIGILL, + SIGIOT, + SIGQUIT, + SIGSEGV, + //SIGTRAP, + SIGXCPU, + SIGXFSZ, + //SIGALRM, + //SIGHUP, + SIGINT, + //SIGKILL, + SIGPIPE, + SIGPROF, + SIGSYS, + //SIGTERM, + SIGUSR1, + SIGUSR2, + //SIGVTALRM, + //SIGSTOP, + //SIGTSTP, + //SIGTTIN, + //SIGTTOU + }; + + /* here mask signal that will use in sigwait() */ + sigset_t waitset, oset; + + if (0 != sigemptyset(&waitset)) + { + NSPOL_LOGERR("sigemptyset failed."); + } + sigaddset(&waitset, SIGRTMIN); /* for timer */ + sigaddset(&waitset, SIGRTMIN + 2); + pthread_sigmask(SIG_BLOCK, &waitset, &oset); + unsigned int i = 0; + + struct sigaction s; + s.sa_handler = signal_handler; + if (0 != sigemptyset(&s.sa_mask)) + { + NSPOL_LOGERR("sigemptyset failed."); + } + + s.sa_flags = (int) SA_RESETHAND; + + /* register sig handler for more signals */ + for (i = 0; i < sizeof(s_need_handle_signals) / sizeof(int); i++) + { + if (sigaction(s_need_handle_signals[i], &s, NULL) != 0) + { + NSPOL_LOGERR("Could not register %d signal handler.", + s_need_handle_signals[i]); + } + + } + +} + +void checkArgs(int argc, char **argv) +{ + int uStackArg = 0; //mark the status whether need helpinfo and return + int i; + const unsigned int global_para_length = 5; //GLOBAL_Stack_ARG "stack" and GLOBAL_STACK_PORT "-port" string length, both are 5 + const unsigned int global_help_length = 6; //GlOBAL_HELP "--help" string length is 6 + const unsigned int global_dpdk_length = 4; //GLOBAL_Dpdk_ARG "dpdk" string length is 4 + + for (i = 0; i < argc; i++) + { + if (argc > 1) + { + if (strncmp(argv[i], GLOBAL_Stack_ARG, global_para_length) == 0) + { + if (i < 5) + { + NSPOL_LOGERR("Too less args"); + helpInfo(); + return; + } + + uStackArg = 1; + uStackArgIndex = i; + continue; + } + + if (strncmp(argv[i], GLOBAL_STACK_PORT, global_para_length) == 0) + { + continue; + } + + if (strncmp(argv[i], GlOBAL_HELP, global_help_length) == 0) + { + if (i == (argc - 1)) + { + helpInfo(); + return; + } + else if ((++i < argc) + && + (strncmp + (argv[i], GLOBAL_Dpdk_ARG, + global_dpdk_length) == 0)) + { +#if (DPDK_MODULE != 1) + //eal_common_usage(); +#else + pal_common_usage(); +#endif + return; + } + else + { + helpInfo(); + return; + } + } + } + else + { + NSPOL_LOGERR("Too less args"); + helpInfo(); + return; + } + } + + if (!uStackArg) + { + helpInfo(); + return; + } +} + +extern u64 timer_get_threadid(); + +#ifdef FOR_NSTACK_UT +int nstack_main(void) +{ + int argc; + + char *argv[NSTACK_MAIN_MAX_PARA]; + argv[0] = "nStackMain"; + argv[1] = "-c";; + argv[2] = "0xffffffff"; + argv[3] = "-n"; + argv[4] = "3"; + argv[5] = "stack"; + argv[6] = "-port"; + argv[7] = "288"; + argv[8] = "-c"; + argv[9] = "2"; + argc = 10; + +#else +int main(int argc, char *argv[]) +{ +#endif + fw_poc_type proc_type = NSFW_PROC_MAIN; + + /* although nStackMaster has set close on exec, here can't be removed. + * in upgrade senario, if Master is old which has not set close on exec, here, + * if new version Main not close, problem will reappear. Add Begin*/ + int i; + for (i = 4; i < MAX_MASTER_OPEN_FD; i++) + { + close(i); + } + + cfg_module_param config_para; + config_para.proc_type = proc_type; + config_para.argc = argc; + config_para.argv = (unsigned char **) argv; + config_module_init(&config_para); + + set_log_proc_type(LOG_PRO_NSTACK); + (void) nstack_log_init(); + +// nstack_tracing_enable(); + if (0 != nsfw_proc_start_with_lock(NSFW_PROC_MAIN)) + { + NSFW_LOGERR("another process is running!!"); + return 0; + } + + if (1 != mallopt(M_ARENA_MAX, 1)) + { + NSPOL_LOGERR("Error: mallopt fail, continue init"); + } + + /* Set different mem args to PAL and EAL */ + INITPOL_LOGINF("main_thread", "adjust_mem_arg init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_START); + if (adjust_mem_arg(argc, argv)) + { + INITPOL_LOGERR("main_thread", "adjust_mem_arg init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_FAIL); + return -1; + } + INITPOL_LOGINF("main_thread", "adjust_mem_arg init", NULL_STRING, + LOG_INVALID_VALUE, MODULE_INIT_SUCCESS); + + checkArgs(globalArgc, gArgv); + register_signal_handler(); + + (void) signal(SIG_PTRACE, signal_handler); + (void) signal(SIG_PTRACE + 2, signal_handler); + + if (nsfw_mgr_comm_fd_init(NSFW_PROC_MAIN) < 0) + { + NSFW_LOGERR("nsfw_mgr_comm_fd_init failed"); + } + + (void) nsfw_reg_trace_thread(pthread_self()); + + nsfw_mem_para stinfo = { 0 }; + stinfo.iargsnum = uStackArgIndex; + stinfo.pargs = gArgv; + stinfo.enflag = proc_type; + (void) nstack_framework_set_module_param(NSFW_MEM_MGR_MODULE, &stinfo); + (void) nstack_framework_set_module_param(NSFW_MGR_COM_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_TIMER_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_RECYCLE_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_LOG_CFG_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_VER_MGR_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(SPL_RES_MGR_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_SOFT_PARAM_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_ALARM_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(TCPDUMP_MODULE, + (void *) ((u64) proc_type)); + proc_type = NSFW_PROC_MASTER; + (void) nstack_framework_set_module_param(NSFW_PS_MODULE, + (void *) ((u64) proc_type)); + (void) nstack_framework_set_module_param(NSFW_PS_MEM_MODULE, + (void *) ((u64) proc_type)); + + g_nsfw_mem_ops[NSFW_SHMEM].stmemop = &g_shmem_ops; + g_nsfw_mem_ops[NSFW_NSHMEM].stmemop = &g_nshmem_ops; + nsfw_ring_ops *ring_ops = (nsfw_ring_ops *) g_ring_ops_arry; + nsfw_ring_ops *temp_ring_ops = (nsfw_ring_ops *) g_ring_ops_arry_lwip; + for (i = 0; i < NSFW_MEM_TYPEMAX * NSFW_MPOOL_TYPEMAX; i++) + { + ring_ops[i] = *temp_ring_ops; + temp_ring_ops++; + } + + int init_ret = nstack_framework_init(); + if (init_ret < 0) + { + NSFW_LOGERR + ("######################init failed!!!!######################"); + 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"); + return -1; + } + + if (0 != get_ip_json_data()) + { + NSFW_LOGINF("get_ip_json_data error"); + return -1; + } + + 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..8bd5007 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/CMakeLists.txt @@ -0,0 +1,37 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +if(WITH_HAL_LIB) +else() + SET(PAL_H_DIRECTORIES "/usr/include/dpdk/") +endif() + + +FILE(GLOB SBR *.c) +ADD_LIBRARY(lwip_dpdk SHARED ${SBR}) +TARGET_LINK_LIBRARIES(lwip_dpdk -Wl,--whole-archive socket nsfw_mem -Wl,--no-whole-archive rte_eal rte_mempool rte_ring rte_mbuf) +ADD_DEPENDENCIES(lwip_dpdk socket DPDK) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../include + ${PAL_H_DIRECTORIES} + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../stacks/lwip_stack/src/mem/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_shmem/ + ${CMAKE_CURRENT_LIST_DIR}/../mem/nsfw_nshmem/ +) 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..96b5399 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_err.h @@ -0,0 +1,190 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SBR_ERR_H +#define SBR_ERR_H +#include <errno.h> + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifdef SBR_PROVIDE_ERRNO +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No stored locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +#define ENSROK 0 +#define ENSRNODATA 160 +#define ENSRFORMERR 161 +#define ENSRSERVFAIL 162 +#define ENSRNOTFOUND 163 +#define ENSRNOTIMP 164 +#define ENSRREFUSED 165 +#define ENSRBADQUERY 166 +#define ENSRBADNAME 167 +#define ENSRBADFAMILY 168 +#define ENSRBADRESP 169 +#define ENSRCONNREFUSED 170 +#define ENSRTIMEOUT 171 +#define ENSROF 172 +#define ENSRFILE 173 +#define ENSRNOMEM 174 +#define ENSRDESTRUCTION 175 +#define ENSRQUERYDOMAINTOOLONG 176 +#define ENSRCNAMELOOP 177 +#define OPTION_DEG 200 + +#endif + +static inline void sbr_set_errno(int err) +{ + errno = err; +} + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif + +#endif diff --git a/stacks/lwip_stack/src/sbr/sbr_index_ring.c b/stacks/lwip_stack/src/sbr/sbr_index_ring.c new file mode 100644 index 0000000..b684918 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_index_ring.c @@ -0,0 +1,212 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <string.h> +#include "sbr_index_ring.h" +#include "nstack_securec.h" +#include "common_mem_common.h" +#include "common_func.h" + +/***************************************************************************** +* Prototype : sbr_init_index_ring +* Description : init index ring +* Input : sbr_index_ring* ring +* u32 num +* Output : None +* Return Value : static inline void +* Calls : +* Called By : +* +*****************************************************************************/ +static inline void sbr_init_index_ring(sbr_index_ring * ring, u32 num) +{ + u32 loop; + + ring->head = 0; + ring->tail = 0; + ring->num = num; + ring->mask = num - 1; + + for (loop = 0; loop < num; loop++) + { + ring->nodes[loop].ver = (loop - num); + ring->nodes[loop].val = 0; + } +} + +/***************************************************************************** +* Prototype : sbr_create_index_ring +* Description : create index ring +* Input : u32 num +* Output : None +* Return Value : sbr_index_ring* +* Calls : +* Called By : +* +*****************************************************************************/ +sbr_index_ring *sbr_create_index_ring(u32 num) +{ + num = common_mem_align32pow2(num + 1); + sbr_index_ring *ring = + (sbr_index_ring *) malloc(sizeof(sbr_index_ring) + + num * sizeof(sbr_index_node)); + if (!ring) + { + return NULL; + } + + sbr_init_index_ring(ring, num); + return ring; +} + +/***************************************************************************** +* Prototype : sbr_index_ring_enqueue +* Description : enqueue data,val != 0 +* Input : sbr_index_ring* ring +* i32 val +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_index_ring_enqueue(sbr_index_ring * ring, i32 val) +{ + if (0 == val) + { + return -1; + } + + sbr_index_node expect_node; + sbr_index_node cur_node; + u32 tmp_head; + u32 tmp_tail; + u32 cur_head = ring->head; + u32 mask = ring->mask; + u32 size = ring->num; + + do + { + tmp_tail = ring->tail; + if (tmp_tail + size - cur_head == 0) + { + if (ring->nodes[tmp_tail & mask].val == 0) + { + (void) __sync_bool_compare_and_swap(&ring->tail, tmp_tail, + tmp_tail + 1); + } + else + { + return 0; + } + } + + expect_node.ver = cur_head - size; + expect_node.val = 0; + + cur_node.ver = cur_head; + cur_node.val = val; + + if ((ring->nodes[cur_head & mask].ver == expect_node.ver) + && __sync_bool_compare_and_swap(&ring-> + nodes[cur_head & mask].data, + expect_node.data, cur_node.data)) + { + tmp_head = ring->head; + if ((tmp_head - cur_head > 0x80000000) + && (0 == (cur_head & 0x11))) + { + (void) __sync_bool_compare_and_swap(&ring->head, tmp_head, + cur_head); + } + + break; + } + + tmp_head = ring->head; + cur_head = cur_head - tmp_head < mask - 1 ? cur_head + 1 : tmp_head; + } + while (1); + + return 1; +} + +/***************************************************************************** +* Prototype : sbr_index_ring_dequeue +* Description : dequeue +* Input : sbr_index_ring* ring +* i32* val +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int sbr_index_ring_dequeue(sbr_index_ring * ring, i32 * val) +{ + u32 cur_tail; + u32 tmp_tail; + u32 tmp_head; + u32 mask = ring->mask; + sbr_index_node null_node; + sbr_index_node expect_node; + + cur_tail = ring->tail; + do + { + tmp_head = ring->head; + if (cur_tail == tmp_head) + { + if (0 != (ring->nodes[tmp_head & mask].val)) + { + (void) __sync_bool_compare_and_swap(&ring->head, tmp_head, + tmp_head + 1); + } + else + { + return 0; + } + } + + null_node.ver = cur_tail; + null_node.val = 0; + expect_node = ring->nodes[cur_tail & mask]; + + if ((null_node.ver == expect_node.ver) && (expect_node.val) + && __sync_bool_compare_and_swap(&ring-> + nodes[cur_tail & mask].data, + expect_node.data, null_node.data)) + + { + *val = expect_node.val; + tmp_tail = ring->tail; + if ((tmp_tail - cur_tail > 0x80000000) + && (0 == (cur_tail & 0x11))) + { + (void) __sync_bool_compare_and_swap(&ring->tail, tmp_tail, + cur_tail); + } + + break; + } + + tmp_tail = ring->tail; + cur_tail = cur_tail - tmp_tail < mask - 1 ? cur_tail + 1 : tmp_tail; + } + while (1); + + return 1; +} diff --git a/stacks/lwip_stack/src/sbr/sbr_index_ring.h b/stacks/lwip_stack/src/sbr/sbr_index_ring.h new file mode 100644 index 0000000..7a1e396 --- /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..16608bc --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_protocol_api.h @@ -0,0 +1,102 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef SBR_PROTOCOL_API_H +#define SBR_PROTOCOL_API_H +#include <sys/uio.h> +#include <sys/epoll.h> +#include <netinet/in.h> +#include "sbr_err.h" +#include "nsfw_msg_api.h" +#include "nsfw_mt_config.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +#ifndef SBR_MAX_INTEGER +#define SBR_MAX_INTEGER 0x7FFFFFFF +#endif + +#ifndef socklen_t +#define socklen_t u32 +#endif + +#define SBR_MAX_FD_NUM MAX_SOCKET_NUM + +typedef struct sbr_socket_s sbr_socket_t; +typedef struct +{ + int (*socket) (sbr_socket_t *, int, int, int); + int (*bind) (sbr_socket_t *, const struct sockaddr *, socklen_t); + int (*listen) (sbr_socket_t *, int); + int (*accept) (sbr_socket_t *, sbr_socket_t *, struct sockaddr *, + socklen_t *); + int (*accept4) (sbr_socket_t *, sbr_socket_t *, struct sockaddr *, + socklen_t *, int); + int (*connect) (sbr_socket_t *, const struct sockaddr *, socklen_t); + int (*shutdown) (sbr_socket_t *, int); + int (*getsockname) (sbr_socket_t *, struct sockaddr *, socklen_t *); + int (*getpeername) (sbr_socket_t *, struct sockaddr *, socklen_t *); + int (*getsockopt) (sbr_socket_t *, int, int, void *, socklen_t *); + int (*setsockopt) (sbr_socket_t *, int, int, const void *, socklen_t); + int (*recvfrom) (sbr_socket_t *, void *, size_t, int, struct sockaddr *, + socklen_t *); + int (*readv) (sbr_socket_t *, const struct iovec *, int); + int (*recvmsg) (sbr_socket_t *, struct msghdr *, int); + int (*send) (sbr_socket_t *, const void *, size_t, int); + int (*sendto) (sbr_socket_t *, const void *, size_t, int, + const struct sockaddr *, socklen_t); + int (*sendmsg) (sbr_socket_t *, const struct msghdr *, int); + int (*writev) (sbr_socket_t *, const struct iovec *, int); + int (*fcntl) (sbr_socket_t *, int, long); + int (*ioctl) (sbr_socket_t *, unsigned long, void *); + int (*close) (sbr_socket_t *); + int (*peak) (sbr_socket_t *); + void (*lock_common) (sbr_socket_t *); + void (*unlock_common) (sbr_socket_t *); + void (*fork_parent) (sbr_socket_t *, pid_t); + void (*fork_child) (sbr_socket_t *, pid_t, pid_t); + void (*(*ep_triggle) (sbr_socket_t *, int triggle_ops, void *, void *)); + int (*ep_getevt) (sbr_socket_t *); + 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(); +int sbr_fork_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 */ +int lwip_try_select(int fdsize, fd_set * fdread, fd_set * fdwrite, + fd_set * fderr, struct timeval *timeout); + +#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..3758084 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_res_mgr.c @@ -0,0 +1,87 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#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..d597ef7 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_res_mgr.h @@ -0,0 +1,155 @@ +/* +* +* 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; +} + +/***************************************************************************** +* 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_fd(int fd) +{ + if ((fd < 1) || (fd > SBR_MAX_FD_NUM)) + { + NSSBR_LOGERR("fd is not ok]fd=%d", fd); + sbr_set_errno(EBADF); + return; + } + + sbr_socket_t *sk = &g_res_group.sk[fd]; + if (!sk->fdopt && !sk->sk_obj && !sk->stack_obj) + { + NSSBR_LOGERR + ("can't free empty fd] fd=%d, fdopt=%p, sk_obj=%p, stack_obj=%p", + fd, sk->fdopt, sk->sk_obj, sk->stack_obj); + return; + } + sbr_free_sk(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..27f3ad1 --- /dev/null +++ b/stacks/lwip_stack/src/sbr/sbr_socket.c @@ -0,0 +1,1324 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <dlfcn.h> +#include "sbr_protocol_api.h" +#include "sbr_res_mgr.h" +#include "nstack_log.h" +#include "nsfw_shmem_mdesc.h" +#include "nsfw_nshmem_mdesc.h" +#include "nstack_callback_ops.h" +#include "nstack_rd_data.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 + +void *lwip_rd_table = NULL; +extern nsfw_ring_ops + g_ring_ops_arry_lwip[NSFW_MEM_TYPEMAX][NSFW_MPOOL_TYPEMAX]; + +/***************************************************************************** +* 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(ssize_t, 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(ssize_t, 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(ssize_t, 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(ssize_t, 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(ssize_t, 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(ssize_t, 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(ssize_t, 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(ssize_t, 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(ssize_t, 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(ssize_t, 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 lwip_try_select(nfds, readfd, writefd, exceptfd, timeout); +} + +SBR_INTERCEPT(int, ep_getevt, (int profd)) +{ + NSSBR_LOGDBG("proFD=%d", profd); + sbr_socket_t *sk = sbr_lookup_sk(profd); + + if (!sk) + { + return -1; + } + + return sk->fdopt->ep_getevt(sk); +} + +SBR_INTERCEPT(void *, ep_triggle, + (int proFD, int triggle_ops, void *epinfo, void *epitem)) +{ + NSSBR_LOGDBG("proFD=%d,triggle_ops=%d,epinfo=%p,epi=%p", proFD, + triggle_ops, epinfo, epitem); + sbr_socket_t *sk = sbr_lookup_sk(proFD); + + if (!sk) + { + return NULL; + } + + return sk->fdopt->ep_triggle(sk, triggle_ops, epinfo, epitem); +} + +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); +} + +SBR_INTERCEPT(int, fork_init_child, (pid_t p, pid_t c)) +{ + NSSBR_LOGDBG("fork_init_child() is called]"); + return sbr_fork_protocol(); +} + +SBR_INTERCEPT(void, fork_parent_fd, (int s, pid_t p)) +{ + NSSBR_LOGDBG("fork_parent_fd() is called]"); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return; + } + + sk->fdopt->fork_parent(sk, p); +} + +SBR_INTERCEPT(void, fork_child_fd, (int s, pid_t p, pid_t c)) +{ + NSSBR_LOGDBG("fork_child_fd() is called]"); + sbr_socket_t *sk = sbr_lookup_sk(s); + + if (!sk) + { + return; + } + + sk->fdopt->fork_child(sk, p, c); + +} + +SBR_INTERCEPT(void, fork_free_fd, (int s)) +{ + NSSBR_LOGDBG("fork_free_fd() is called]"); + sbr_free_fd(s); +} + +SBR_INTERCEPT(void *, get_ip_shmem, (void)) +{ + lwip_rd_table = nstack_rd_malloc("lwip_rd_table"); + + if (!lwip_rd_table) + { + NSSOC_LOGERR("lwip rd table create failed!"); + return NULL; + } + + if (nstack_rd_parse("lwip", lwip_rd_table)) + { + NSSOC_LOGWAR("lwip parse rd data failed, load default instead"); + } + + return lwip_rd_table; +} + +SBR_INTERCEPT(int, module_init_pre, + (void *op1, void *op2, int memtype, int pooltype)) +{ + int i; + nsfw_mem_attr *mem_ops = (nsfw_mem_attr *) op1; + nsfw_ring_ops *ring_ops = (nsfw_ring_ops *) op2; + nsfw_ring_ops *tmp_ring_ops; + + if (!mem_ops || !ring_ops) + { + return -1; + } + + mem_ops[NSFW_SHMEM].stmemop = &g_shmem_ops; + mem_ops[NSFW_NSHMEM].stmemop = &g_nshmem_ops; + + tmp_ring_ops = (nsfw_ring_ops *) g_ring_ops_arry_lwip; + for (i = 0; i < memtype * pooltype; i++) + { + ring_ops[i] = tmp_ring_ops[i]; + } + + return 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 +lwip_stack_register(nstack_socket_ops * ops, nstack_event_ops * val, + nstack_proc_ops * deal) +{ + if (!ops || !val || !val->handle) + { + return -1; + } + +#undef NSTACK_MK_DECL +#define NSTACK_MK_DECL(ret, fn, args) \ + ops->pf ## fn = (typeof(((nstack_socket_ops*)0)->pf ## fn))dlsym(val->handle, "sbr_" # fn); +#include "declare_syscalls.h.tmpl" + + deal->module_init = sbr_init_res; + deal->fork_init_child = GET_SBR_INTERCEPT(fork_init_child); + deal->fork_fd = GET_SBR_INTERCEPT(fork_child_fd); + deal->fork_free_fd = GET_SBR_INTERCEPT(fork_free_fd); + deal->ep_getEvt = GET_SBR_INTERCEPT(ep_getevt); + deal->ep_triggle = GET_SBR_INTERCEPT(ep_triggle); + deal->peak = GET_SBR_INTERCEPT(peak); + //deal->stack_alloc_fd = GET_SBR_INTERCEPT (fd_alloc); /*alloc a fd id for epoll */ + deal->fork_parent_fd = GET_SBR_INTERCEPT(fork_parent_fd); + deal->get_ip_shmem = GET_SBR_INTERCEPT(get_ip_shmem); + deal->module_init_pre = GET_SBR_INTERCEPT(module_init_pre); + 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..018b338 --- /dev/null +++ b/stacks/lwip_stack/src/tools/CMakeLists.txt @@ -0,0 +1,26 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +######################################################################### + +FILE(GLOB_RECURSE Tcpdump *.c) +ADD_LIBRARY(nTcpdump STATIC ${Tcpdump}) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_LIST_DIR}/../include + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/ + ${CMAKE_CURRENT_LIST_DIR}/../../../../src/framework/include/common/generic/ +) +TARGET_LINK_LIBRARIES(nTcpdump nStackFw) 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..7e6e67c --- /dev/null +++ b/stacks/lwip_stack/src/tools/dump_tool.c @@ -0,0 +1,611 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <arpa/inet.h> + +#include "nsfw_init_api.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_RING_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 = MAX_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 = MAX_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(NSFW_MEM_MGR_MODULE) +NSFW_MODULE_DEPENDS(NSFW_MGR_COM_MODULE) +NSFW_MODULE_DEPENDS(NSFW_TIMER_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..7727bc1 --- /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 |