aboutsummaryrefslogtreecommitdiffstats
path: root/stacks
diff options
context:
space:
mode:
authorsharath <sharathkumarboyanapally@gmail.com>2018-08-13 19:28:26 +0530
committersharath <sharathkumarboyanapally@gmail.com>2018-08-13 19:29:13 +0530
commit7b1e219c80f5fe44a8f015a369e57ba7d2bc39cc (patch)
tree9fa3ee1ce324478711dfce73425e16e6bcb429a9 /stacks
parentbd6e75c243db1b384ba0882ecaf9063ec4cd70bd (diff)
Feat : LWIP integration part2
Change-Id: I2431581d611659beb9b9b4d6d95d6985e53a8061 Signed-off-by: sharath <sharathkumarboyanapally@gmail.com>
Diffstat (limited to 'stacks')
-rw-r--r--stacks/lwip_stack/lwip_src/instance/spl_instance.c49
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c1045
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/container_ip.c1168
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c347
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/network.c1127
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c563
-rw-r--r--stacks/lwip_stack/lwip_src/netif/ethernetif.c167
-rw-r--r--stacks/lwip_stack/lwip_src/netif/sc_dpdk.c574
-rw-r--r--stacks/lwip_stack/lwip_src/netif/spl_hal.c1753
-rw-r--r--stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c676
-rw-r--r--stacks/lwip_stack/lwip_src/socket/CMakeLists.txt76
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_cfg.h54
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c332
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c150
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h48
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_event.c29
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_event.h46
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_macro.h24
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c775
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h78
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c651
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h159
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c94
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c246
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h69
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_socket.h141
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_tcp.c1696
-rw-r--r--stacks/lwip_stack/lwip_src/socket/stackx_udp.c1169
28 files changed, 13306 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/instance/spl_instance.c b/stacks/lwip_stack/lwip_src/instance/spl_instance.c
new file mode 100644
index 0000000..69b9d82
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/instance/spl_instance.c
@@ -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.
+*/
+
+#include "nsfw_msg_api.h"
+#include "nsfw_init.h"
+#include "stackx/spl_sbr.h"
+#include "stackx/stackx_instance.h"
+
+stackx_instance *p_def_stack_instance = NULL;
+
+/**
+ * process message from other module, but the MT module message will be delayed
+ * to handle in the end of the loop to avoid to lose the message dequeued out.
+ *
+ * @param m the data_com_msg to handle
+ */
+int
+spl_process (data_com_msg * m)
+{
+ return call_msg_fun (m);
+}
+
+void
+add_disp_netif (struct netif *netif)
+{
+ struct disp_netif_list *item = malloc (sizeof (struct disp_netif_list));
+ if (!item)
+ {
+ NSPOL_LOGERR ("malloc failed");
+ return;
+ }
+
+ item->netif = netif;
+ item->next = p_def_stack_instance->netif_list;
+ p_def_stack_instance->netif_list = item;
+}
diff --git a/stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c b/stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c
new file mode 100644
index 0000000..2b71e07
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c
@@ -0,0 +1,1045 @@
+/*
+*
+* 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 <unistd.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "configuration_reader.h"
+#include "container_ip.h"
+#include "network.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "json.h"
+#include "spl_tcpip.h"
+
+#include <types.h>
+#include <nsfw_mgr_com_api.h>
+#include <nsfw_base_linux_api.h>
+#include "nsfw_maintain_api.h"
+
+NSTACK_STATIC struct config_data g_ip_module_buff;
+NSTACK_STATIC struct config_data *g_config_data;
+NSTACK_STATIC char ip_module_unix_socket[IP_MODULE_MAX_PATH_LEN + 1];
+NSTACK_STATIC char ip_module_unix_socket_dir_path[IP_MODULE_MAX_PATH_LEN + 1];
+//static unsigned long int g_thread_id = 0;
+
+#define MAX_CONNECTION_NUMBER 5
+#define TCP_OOS_LEN_MAX 250
+
+NSTACK_STATIC int read_configuration ();
+NSTACK_STATIC int unix_socket_listen (const char *servername);
+NSTACK_STATIC int process_query ();
+
+/*****************************************************************************
+* Prototype : is_digit_str
+* Description : check if a string contains only digit
+* Input : char *input
+* Output : 1 for yes, 0 for no
+* Return Value : int
+* Calls :
+* Called By : get_main_pid
+*
+*****************************************************************************/
+NSTACK_STATIC int
+is_digit_str (char *input)
+{
+ if (NULL == input || '\0' == input[0])
+ {
+ return 0;
+ }
+
+ while (*input)
+ {
+ if (*input > '9' || *input < '0')
+ {
+ return 0;
+ }
+ input++;
+ }
+
+ return 1;
+}
+
+/*****************************************************************************
+* Prototype : process_query
+* Description : ./nStackCtrl -a query
+* Input : none
+* Output : none
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int
+process_query ()
+{
+ int retval;
+
+ if (0 == g_config_data->param.type[0])
+ {
+ return process_post (NULL, IP_MODULE_ALL, IP_MODULE_OPERATE_QUERY);
+ }
+
+ /*name & p are freed inside process_post */
+ if (0 == strcmp (g_config_data->param.type, IP_MODULE_TYPE_PORT))
+ {
+ struct ip_action_param *p = malloc (sizeof (struct ip_action_param));
+ if (p == NULL)
+ {
+ NSOPR_LOGERR ("name allocation failed!");
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "mem alloc error!");
+ return -1;
+ }
+
+ retval =
+ MEMSET_S (p, sizeof (struct ip_action_param), 0,
+ sizeof (struct ip_action_param));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "MEMSET_S error!");
+ free (p);
+ return -1;
+ }
+
+ retval =
+ STRCPY_S (p->container_id, sizeof (p->container_id),
+ g_config_data->param.container_id);
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "STRCPY_S error!");
+ free (p);
+ return -1;
+ }
+
+ retval =
+ STRCPY_S (p->port_name, sizeof (p->port_name),
+ g_config_data->param.name);
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "STRCPY_S error!");
+ free (p);
+ return -1;
+ }
+
+ return process_post ((void *) p, IP_MODULE_IP, IP_MODULE_OPERATE_QUERY);
+ }
+ else if (0 == strcmp (g_config_data->param.type, IP_MODULE_TYPE_NETWORK))
+ {
+ if (0 == g_config_data->param.name[0])
+ {
+ return process_post (NULL, IP_MODULE_NETWORK_ALL,
+ IP_MODULE_OPERATE_QUERY);
+ }
+ else
+ {
+ char *name = malloc (sizeof (g_config_data->param.name));
+ if (NULL == name)
+ {
+ NSOPR_LOGERR ("name allocation failed!");
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "mem alloc error!");
+ return -1;
+ }
+
+ retval =
+ MEMSET_S (name, sizeof (g_config_data->param.name), 0,
+ sizeof (g_config_data->param.name));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "MEMSET_S error!");
+ free (name);
+ return -1;
+ }
+
+ retval =
+ STRCPY_S (name, sizeof (g_config_data->param.name),
+ g_config_data->param.name);
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "STRCPY_S error!");
+ free (name);
+ return -1;
+ }
+
+ return process_post ((void *) name, IP_MODULE_NETWORK,
+ IP_MODULE_OPERATE_QUERY);
+ }
+ }
+ else if (0 == strcmp (g_config_data->param.type, IP_MODULE_TYPE_IP))
+ {
+ if (0 == g_config_data->param.name[0])
+ {
+ return process_post (NULL, IP_MODULE_IP_ALL,
+ IP_MODULE_OPERATE_QUERY);
+ }
+ else
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "input error!");
+ }
+ }
+ else
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "input error!");
+ }
+
+ return -1;
+}
+
+int
+read_ipmoduleoperatesetnet_configuration ()
+{
+ if (strcmp (g_config_data->param.type, IP_MODULE_TYPE_SETLOG) == 0)
+ {
+ if (NSCRTL_OK ==
+ setlog_level_value (g_config_data->param.name,
+ g_config_data->param.value))
+ {
+ NSOPR_LOGDBG ("set log level ok!");
+ }
+ else
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "input error!");
+ }
+ }
+ else if (strcmp (g_config_data->param.type, TCP_MODULE_TYPE_SET_OOS_LEN) ==
+ 0)
+ {
+ if (is_digit_str (g_config_data->param.value) == 0)
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR,
+ "Invalid value:value must be digital and smaller than %u]value=\"%s\"",
+ TCP_OOS_LEN_MAX, g_config_data->param.value);
+ return 0;
+ }
+
+ unsigned int value_len = strlen (g_config_data->param.value);
+ if ((value_len >= 2) && (g_config_data->param.value[0] == '0'))
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR,
+ "Invalid value:value cannot start with 0");
+ return 0;
+ }
+ }
+ else
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "input error!");
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : read_version
+* Description : Query Version by nStackCtrl
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+read_version ()
+{
+ int retVal;
+ json_object *version = json_object_new_object ();
+
+ if (NULL == version)
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "internal error for version=NULL!");
+ return NSCRTL_ERR;
+ }
+
+ json_object_object_add (version, "moudle",
+ json_object_new_string (NSTACK_GETVER_MODULE));
+ json_object_object_add (version, "version",
+ json_object_new_string (NSTACK_GETVER_VERSION));
+ json_object_object_add (version, "buildtime",
+ json_object_new_string (NSTACK_GETVER_BUILDTIME));
+
+ json_object *version_array = json_object_new_array ();
+ if (NULL == version_array)
+ {
+ json_object_put (version);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR,
+ "internal error for version_array=NULL!");
+ return NSCRTL_ERR;
+ }
+
+ retVal = json_object_array_add (version_array, version);
+
+ if (0 != retVal)
+ {
+ json_object_put (version_array);
+ json_object_put (version);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR,
+ "internal error for json_object_array_add failed!");
+ return NSCRTL_ERR;
+ }
+
+ const char *str = json_object_to_json_string (version_array);
+
+ if (NULL == str)
+ {
+ json_object_put (version_array);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "internal error for str=NULL!");
+ return NSCRTL_ERR;
+ }
+
+ size_t str_len = strlen (str);
+ if (str_len >= sizeof (get_config_data ()->json_buff))
+ {
+ json_object_put (version_array);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "internal error!");
+ return NSCRTL_ERR;
+ }
+
+ retVal =
+ STRNCPY_S (get_config_data ()->json_buff,
+ sizeof (get_config_data ()->json_buff), str, str_len);
+ if (EOK != retVal)
+ {
+ json_object_put (version_array);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "STRNCPY_S error!");
+ return NSCRTL_ERR;
+ }
+
+ json_object_put (version_array);
+ return NSCRTL_OK;
+}
+
+void
+reset_config_data (void)
+{
+ int retval = MEMSET_S (g_config_data, sizeof (struct config_data), 0,
+ sizeof (struct config_data));
+ if (EOK != retval)
+ {
+ printf ("MEMSET_S failed]retval=%d.\n", retval);
+ exit (1);
+ }
+}
+
+int
+get_network_json_data ()
+{
+ STRCPY_S (g_config_data->param.type, sizeof (g_config_data->param.type),
+ "network");
+ g_config_data->param.action = IP_MODULE_OPERATE_ADD;
+
+ char *tmp_config_path;
+ tmp_config_path = realpath ("./network_data_tonStack.json", NULL);
+ if (!tmp_config_path)
+ {
+ exit (1);
+ }
+
+ int fp = open (tmp_config_path, O_RDONLY);
+ if (-1 == fp)
+ {
+ free (tmp_config_path);
+ NSTCP_LOGINF ("network file open failed.\n");
+ exit (1);
+ }
+ free (tmp_config_path);
+
+ int nread = read (fp, g_config_data->json_buff,
+ sizeof (g_config_data->json_buff) - 1);
+ if (nread <= 0)
+ {
+ close (fp);
+ NSTCP_LOGINF ("read failed %d.\n", nread);
+ exit (1);
+ }
+
+ /* though MEMSET_S is done above, MEMSET_S can be removed */
+ g_config_data->json_buff[nread] = '\0';
+ close (fp);
+
+ struct network_configuration *network = NULL;
+ struct network_configuration *tmp = NULL;
+
+ /* input shouldnot be same with return */
+ network = parse_network_json (g_config_data->json_buff, NULL);
+ if (!network)
+ {
+ NSTCP_LOGINF ("Invalid network data!");
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "Invalid network data!");
+ return -1;
+ }
+
+ /* run process_post for each network, not only the head node */
+ while (network)
+ {
+ tmp = network;
+ network = network->next;
+ int retval =
+ add_network_configuration ((struct network_configuration *) tmp);
+
+ /* When network exceeds max number, just log warning at operation.log */
+ if (retval == NSCRTL_NETWORK_COUNT_EXCEED)
+ {
+ NSTCP_LOGINF
+ ("Warning!! Network count exceed max allowed number]max=%d",
+ MAX_NETWORK_COUNT);
+ }
+ else
+ {
+
+ NSTCP_LOGINF ("add_network_configuration %d", retval);
+ NSOPR_SET_ERRINFO (retval, "add_network_configuration return %d",
+ retval);
+ }
+
+ if (!retval)
+ {
+ /*init DPDK eth */
+ if ((retval = init_new_network_configuration ()) != ERR_OK)
+ {
+ NSTCP_LOGINF ("process_configuration failed! %d", retval);
+ free_network_configuration ((struct network_configuration *)
+ tmp, IP_MODULE_TRUE);
+ NSOPR_SET_ERRINFO (retval,
+ "init_new_network_configuration return %d",
+ retval);
+ return -1;
+ }
+ }
+ }
+ NSTCP_LOGINF ("Get_network_json_data done!");
+
+ return 0;
+}
+
+int
+get_ip_json_data ()
+{
+ NSTCP_LOGINF ("get_ip_json_data start!");
+
+ STRCPY_S (g_config_data->param.type, sizeof (g_config_data->param.type),
+ "ip");
+ g_config_data->param.action = IP_MODULE_OPERATE_ADD;
+
+ char *tmp_config_path;
+ tmp_config_path = realpath ("./ip_data.json", NULL);
+ if (!tmp_config_path)
+ {
+ exit (1);
+ }
+
+ int fp = open (tmp_config_path, O_RDONLY);
+ if (-1 == fp)
+ {
+ free (tmp_config_path);
+ NSTCP_LOGINF ("network file open failed\n");
+ exit (1);
+ }
+ free (tmp_config_path);
+
+ int nread = read (fp, g_config_data->json_buff,
+ sizeof (g_config_data->json_buff) - 1);
+ if (nread <= 0)
+ {
+ close (fp);
+ NSTCP_LOGINF ("read failed %d.\n", nread);
+ exit (1);
+ }
+
+ /* though MEMSET_S is done above, MEMSET_S can be removed */
+ g_config_data->json_buff[nread] = '\0';
+ close (fp);
+
+ struct container_ip *container =
+ parse_container_ip_json (g_config_data->json_buff);
+ if (container)
+ {
+ int retval = add_container (container);
+
+ NSTCP_LOGINF ("add_container %d", retval);
+ NSOPR_SET_ERRINFO (retval, "add_container return %d", retval);
+ }
+ else
+ {
+ NSTCP_LOGINF ("Invalid IP config data!");
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "Invalid IP config data!");
+ return -1;
+ }
+ NSTCP_LOGINF ("get_ip_json_data done!");
+
+ return 0;
+}
+
+int
+read_ipmoduleoperateadd_configuration ()
+{
+ struct network_configuration *tmp = NULL;
+ if (strcmp (g_config_data->param.type, IP_MODULE_TYPE_IP) == 0)
+ {
+ struct container_ip *container =
+ parse_container_ip_json (g_config_data->json_buff);
+ if (container)
+ {
+ return process_post ((void *) container, IP_MODULE_IP,
+ IP_MODULE_OPERATE_ADD);
+ }
+ else
+ {
+ NSOPR_LOGERR ("Invalid IP config data!");
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "Invalid IP config data!");
+ return -1;
+ }
+ }
+ else if (strcmp (g_config_data->param.type, IP_MODULE_TYPE_NETWORK) == 0)
+ {
+ struct network_configuration *network = NULL;
+
+ //Read network.json
+
+ /* input shouldnot be same with return */
+ network = parse_network_json (g_config_data->json_buff, NULL);
+ if (!network)
+ {
+ NSOPR_LOGERR ("Invalid network data!");
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "Invalid network data!");
+ return -1;
+ }
+
+ /* run process_post for each network, not only the head node */
+ while (network)
+ {
+ tmp = network;
+ network = network->next;
+ int ret = process_post ((void *) tmp, IP_MODULE_NETWORK,
+ IP_MODULE_OPERATE_ADD);
+ if (ret == -1)
+ {
+ NSOPR_LOGERR ("process_configuration failed!");
+ return -1;
+ }
+ }
+ return 0;
+ }
+ else
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "input error!");
+ return -1;
+ }
+}
+
+int
+read_ipmoduleoperatedel_configuration ()
+{
+ int retval;
+
+ if (strcmp (g_config_data->param.type, IP_MODULE_TYPE_IP) == 0)
+ {
+ struct ip_action_param *p = malloc (sizeof (struct ip_action_param));
+ if (NULL == p)
+ {
+ NSOPR_LOGERR ("ip_action_param allocation failed!");
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "mem alloc error!");
+ return -1;
+ }
+
+ retval =
+ MEMSET_S (p, sizeof (struct ip_action_param), 0,
+ sizeof (struct ip_action_param));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "MEMSET_S error!");
+ free (p);
+ return -1;
+ }
+
+ retval =
+ STRCPY_S (p->container_id, sizeof (p->container_id),
+ g_config_data->param.container_id);
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "STRCPY_S error!");
+ free (p);
+ return -1;
+ }
+
+ retval =
+ STRCPY_S (p->port_name, sizeof (p->port_name),
+ g_config_data->param.name);
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "STRCPY_S error!");
+ free (p);
+ return -1;
+ }
+
+ return process_post ((void *) p, IP_MODULE_IP, IP_MODULE_OPERATE_DEL);
+ }
+ else if (strcmp (g_config_data->param.type, IP_MODULE_TYPE_NETWORK) == 0)
+ {
+ char *name = malloc (sizeof (g_config_data->param.name));
+ if (name == NULL)
+ {
+ NSOPR_LOGERR ("name allocation failed!");
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "mem alloc error!");
+ return -1;
+ }
+
+ retval =
+ MEMSET_S (name, sizeof (g_config_data->param.name), 0,
+ sizeof (g_config_data->param.name));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "MEMSET_S error!");
+ free (name);
+ return -1;
+ }
+
+ retval =
+ STRCPY_S (name, sizeof (g_config_data->param.name),
+ g_config_data->param.name);
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "STRCPY_S error!");
+ free (name);
+ return -1;
+ }
+
+ return process_post ((void *) name, IP_MODULE_NETWORK,
+ IP_MODULE_OPERATE_DEL);
+ }
+ else
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "input error!");
+ return -1;
+ }
+}
+
+NSTACK_STATIC int
+read_configuration ()
+{
+ int retval = -1;
+ //u64 traceid = 0;
+
+ /* initialise default memory */
+ g_config_data->param.error = NSCRTL_OK;
+
+ /* Make sure error_desc is inited to null string */
+ g_config_data->param.error_desc[0] = '\0';
+
+ //traceid = g_config_data->param.traceid;
+
+ NSOPR_LOGINF
+ ("g_config_data]type=%s,name=%s,value=%s,container_id=%s,action=%d,Json_buf=%s, traceid=%llu",
+ g_config_data->param.type, g_config_data->param.name,
+ g_config_data->param.value, g_config_data->param.container_id,
+ g_config_data->param.action, g_config_data->json_buff,
+ g_config_data->param.traceid);
+
+ retval =
+ MEMSET_S (g_config_data->param.error_desc,
+ sizeof (g_config_data->param.error_desc), 0,
+ sizeof (g_config_data->param.error_desc));
+ if (0 != retval)
+ {
+ NSOPR_SET_ERRINFO (NSCRTL_ERR, "ERR:internal error, MEMSET_S failed]");
+ return -1;
+ }
+
+ switch (g_config_data->param.action)
+ {
+ case IP_MODULE_OPERATE_DEL:
+ {
+ retval = read_ipmoduleoperatedel_configuration ();
+ break;
+ }
+ case IP_MODULE_OPERATE_QUERY:
+ {
+ retval = process_query ();
+ break;
+ }
+ case IP_MODULE_OPERATE_ADD:
+ {
+ retval = read_ipmoduleoperateadd_configuration ();
+ break;
+ }
+ case IP_MODULE_OPERATE_SET:
+ retval = read_ipmoduleoperatesetnet_configuration ();
+ break;
+ case IP_MODULE_GET_VERSION:
+ {
+ retval = read_version ();
+ break;
+ }
+
+ default:
+ {
+ retval = -1; //here, must set retval to -1
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "input error!");
+ break;
+ }
+ }
+
+ return retval;
+}
+
+NSTACK_STATIC int
+unix_socket_listen (const char *servername)
+{
+ int fd, retval;
+ unsigned int len;
+ struct stat st;
+ struct sockaddr_un un;
+
+ if (stat (ip_module_unix_socket_dir_path, &st) == 0)
+ {
+ NSOPR_LOGDBG (" /directory is present");
+ }
+ else
+ {
+ NSOPR_LOGERR (" /var/run/nStack/ directory is not present ");
+ return (-1);
+ }
+
+ if ((fd = nsfw_base_socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ return -1;
+ }
+
+ retval = unlink (servername); /* in case it already exists */
+ if (0 != retval)
+ {
+ NSOPR_LOGWAR ("unlink failed]retval=%d,errno=%d", retval, errno);
+ }
+
+ retval = MEMSET_S (&un, sizeof (un), 0, sizeof (un));
+ if (EOK != retval)
+ {
+ (void) nsfw_base_close (fd);
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ return -1;
+ }
+
+ un.sun_family = AF_UNIX;
+ retval = STRCPY_S (un.sun_path, sizeof (un.sun_path), servername);
+ if (EOK != retval)
+ {
+ (void) nsfw_base_close (fd);
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ return -1;
+ }
+
+ len =
+ (unsigned int) (offsetof (struct sockaddr_un, sun_path) +
+ strlen (servername));
+
+ if (nsfw_base_bind (fd, (struct sockaddr *) &un, len) < 0)
+ {
+ (void) nsfw_base_close (fd);
+ return -1;
+ }
+ else
+ {
+ if (nsfw_base_listen (fd, MAX_CONNECTION_NUMBER) < 0)
+ {
+ (void) nsfw_base_close (fd);
+ return -1;
+ }
+ else
+ {
+ return fd;
+ }
+ }
+}
+
+/*****************************************************************************
+* Prototype : read_fn
+* Description : process new ip module msg
+* Input : i32 fd
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+read_fn (i32 fd)
+{
+ ssize_t size;
+ ssize_t offset = 0;
+ size_t left = MAX_IP_MODULE_BUFF_SIZE;
+ while (left > 0)
+ {
+ size = nsfw_base_recv (fd, (char *) g_config_data + offset, left, 0);
+ if (size > 0)
+ {
+ offset += size;
+ left -= (size_t) size;
+ }
+ else
+ {
+ NSOPR_LOGERR ("Error when recieving]errno=%d,err_string=%s", errno,
+ strerror (errno));
+ break;
+ }
+ }
+
+ if (left != 0)
+ {
+ (void) nsfw_base_close (fd);
+ return;
+ }
+
+ const char *old_hbt_cnt = "6";
+ const char *new_hbt_cnt = "60";
+ nsfw_set_soft_para (NSFW_PROC_MASTER, NSFW_HBT_COUNT_PARAM,
+ (void *) new_hbt_cnt, sizeof (u16));
+ (void) read_configuration (); // if it returns -1, the err desc info will be wrote to g_config_data, so no need to check return value.
+ nsfw_set_soft_para (NSFW_PROC_MASTER, NSFW_HBT_COUNT_PARAM,
+ (void *) old_hbt_cnt, sizeof (u16));
+
+ offset = 0;
+ left = MAX_IP_MODULE_BUFF_SIZE;
+ while (left > 0)
+ {
+ size =
+ nsfw_base_send (fd, (char *) g_config_data + offset, left,
+ MSG_NOSIGNAL);
+
+ if (size > 0)
+ {
+ offset += size;
+ left -= (size_t) size;
+ }
+ else
+ {
+ NSOPR_LOGERR ("Error when Sending data]errno=%d", errno);
+ break;
+ }
+ }
+
+ (void) nsfw_base_close (fd);
+ return;
+}
+
+/*****************************************************************************
+* Prototype : ip_module_new_msg
+* Description : recv new config message
+* Input : i32 epfd
+* i32 fd
+* u32 events
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+ip_module_new_msg (i32 epfd, i32 fd, u32 events)
+{
+ if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN)))
+ {
+ nsfw_mgr_unreg_sock_fun (fd);
+ (void) nsfw_base_close (fd);
+ return TRUE;
+ }
+
+ nsfw_mgr_unreg_sock_fun (fd);
+ read_fn (fd);
+ return TRUE;
+}
+
+int
+init_ip_module_unix_socket_path ()
+{
+ const char *directory = "/var/run";
+ const char *home_dir = getenv ("HOME");
+
+ if (getuid () != 0 && home_dir != NULL)
+ directory = home_dir;
+
+ if (STRCPY_S
+ (ip_module_unix_socket_dir_path, IP_MODULE_MAX_PATH_LEN, directory) < 0)
+ {
+ NSOPR_LOGERR ("STRCPY_S fail]");
+ return -1;
+ }
+
+ if (STRCAT_S
+ (ip_module_unix_socket_dir_path, IP_MODULE_MAX_PATH_LEN,
+ "/ip_module") < 0)
+ {
+ NSOPR_LOGERR ("STRCAT_S fail]");
+ return -1;
+ }
+
+ if (STRCPY_S
+ (ip_module_unix_socket, IP_MODULE_MAX_PATH_LEN,
+ ip_module_unix_socket_dir_path) < 0)
+ {
+ NSOPR_LOGERR ("STRCPY_S fail]");
+ return -1;
+ }
+
+ if (STRCAT_S
+ (ip_module_unix_socket, IP_MODULE_MAX_PATH_LEN,
+ "/ip_module_unix_sock") < 0)
+ {
+ NSOPR_LOGERR ("STRCAT_S fail]");
+ return -1;
+ }
+
+ NSOPR_LOGINF ("ip_module_unix_socket=%s", ip_module_unix_socket);
+ NSOPR_LOGINF ("ip_module_unix_socket_dir_path=%s",
+ ip_module_unix_socket_dir_path);
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : ip_module_new_connection
+* Description : recv new connect for network config
+* Input : i32 epfd
+* i32 fd
+* u32 events
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+ip_module_new_connection (i32 epfd, i32 fd, u32 events)
+{
+ if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN)))
+ {
+ (void) nsfw_base_close (fd);
+ NSFW_LOGINF ("listen disconnect!]epfd=%d,listen=%d,event=0x%x", epfd,
+ fd, events);
+ nsfw_mgr_unreg_sock_fun (fd);
+
+ if (init_ip_module_unix_socket_path () < 0)
+ {
+ NSFW_LOGERR ("Error when init path]epfd=%d,listen_fd=%d,event=0x%x",
+ epfd, fd, events);
+ return FALSE;
+ }
+
+ i32 listen_fd = unix_socket_listen (ip_module_unix_socket);
+ if (listen_fd < 0)
+ {
+ NSFW_LOGERR ("get listen_fd faied!]epfd=%d,listen_fd=%d,event=0x%x",
+ epfd, fd, events);
+ return FALSE;
+ }
+
+ if (FALSE ==
+ nsfw_mgr_reg_sock_fun (listen_fd, ip_module_new_connection))
+ {
+ (void) nsfw_base_close (listen_fd);
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ struct sockaddr in_addr;
+ socklen_t in_len;
+ int infd;
+ in_len = sizeof in_addr;
+
+ while (1)
+ {
+ infd = nsfw_base_accept (fd, &in_addr, &in_len);
+ if (infd == -1)
+ {
+ break;
+ }
+
+ if (FALSE == nsfw_mgr_reg_sock_fun (infd, ip_module_new_msg))
+ {
+ NSFW_LOGINF ("accept new fd but reg failed]new_mgr_fd=%d", infd);
+ return FALSE;
+ }
+ NSFW_LOGINF ("accept new fd]new_mgr_fd=%d", infd);
+ }
+
+ return TRUE;
+}
+
+int
+init_configuration_reader ()
+{
+ int error_number = 0;
+ INITPOL_LOGINF ("RTP", "init_configuration_reader", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_START);
+ g_config_data = &g_ip_module_buff;
+
+ if (init_ip_module_unix_socket_path () < 0)
+ {
+ INITPOL_LOGERR ("RTP", "init_configuration_reader",
+ "Error when init path", LOG_INVALID_VALUE,
+ MODULE_INIT_FAIL);
+ return -1;
+ }
+
+ i32 listen_fd = unix_socket_listen (ip_module_unix_socket);
+ if (listen_fd < 0)
+ {
+ error_number = errno;
+ INITPOL_LOGERR ("RTP", "init_configuration_reader",
+ "when listening ip_module_unix_socket", error_number,
+ MODULE_INIT_FAIL);
+ return -1;
+ }
+
+ NSOPR_LOGINF ("start mgr_com module!]listern_fd=%d", listen_fd);
+
+ if (FALSE == nsfw_mgr_reg_sock_fun (listen_fd, ip_module_new_connection))
+ {
+ (void) nsfw_base_close (listen_fd);
+ NSOPR_LOGERR ("nsfw_mgr_reg_sock_fun failed]listen_fd=%d", listen_fd);
+ return -1;
+ }
+
+ INITPOL_LOGINF ("RTP", "init_configuration_reader", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_SUCCESS);
+ return 0;
+}
+
+struct config_data *
+get_config_data ()
+{
+ return g_config_data;
+}
diff --git a/stacks/lwip_stack/lwip_src/ip_module/container_ip.c b/stacks/lwip_stack/lwip_src/ip_module/container_ip.c
new file mode 100644
index 0000000..3cbe9b9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/container_ip.c
@@ -0,0 +1,1168 @@
+/*
+*
+* 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 <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include "lwip/inet.h"
+#include "trp_rb_tree.h"
+#include "container_ip.h"
+#include "network.h"
+#include "netif.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "nstack_rd_mng.h"
+#include "config_common.h"
+#include "igmp.h"
+#include "spl_def.h"
+#include "stackx_ip_addr.h"
+#include "hal_api.h"
+#include "spl_hal.h"
+
+struct container_list g_container_list = { 0 };
+static trp_rb_root_t g_container_ip_root = { 0 }; //only handled in tcpip thread, no need protect it with a lock
+static trp_rb_root_t g_container_multicast_root = { 0 }; //only handled in tcpip thread, no need protect it with a lock
+
+static void free_container_port (struct container_port *port,
+ bool_t only_free);
+
+/*unsigned int value is typecasted into void * pointer and passed as argument to
+this function. so the value can never be > 0xFFFFFFFF. so can suppress the warning*/
+
+static int
+ip_compare (trp_key_t left, trp_key_t right)
+{
+ //return (int)((unsigned long)left - (unsigned long)right);
+
+ if (left > right)
+ {
+ return 1;
+ }
+ else if (left < right)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+NSTACK_STATIC bool_t
+is_container_ok (struct container_ip * container)
+{
+ if (!container->ports_list)
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+NSTACK_STATIC void
+add_port (struct container_ip *container, struct container_port *port)
+{
+ if (port->ip_cidr_list)
+ {
+ port->next = container->ports_list;
+ container->ports_list = port;
+ }
+ else
+ {
+ free_container_port (port, IP_MODULE_TRUE);
+ }
+}
+
+static void
+add_ip_cidr (struct container_port *port,
+ struct container_port_ip_cidr *ip_cidr)
+{
+ if (!ip_cidr)
+ {
+ return;
+ }
+
+ ip_cidr->next = port->ip_cidr_list;
+ port->ip_cidr_list = ip_cidr;
+ return;
+}
+
+NSTACK_STATIC void
+add_multilcast_ip (struct container_port *port,
+ struct container_multicast_id *muticastIP)
+{
+ if (!muticastIP)
+ {
+ return;
+ }
+
+ muticastIP->next = port->multicast_list;
+ port->multicast_list = muticastIP;
+ return;
+}
+
+NSTACK_STATIC void
+free_container_port_ip_cidr (struct container_port_ip_cidr *ip_cidr,
+ bool_t only_free)
+{
+ output_api *api = get_output_api ();
+ struct container_port_ip_cidr *ip_cidr_tmp = NULL;
+
+ while (ip_cidr)
+ {
+ ip_cidr_tmp = ip_cidr;
+ ip_cidr = ip_cidr_tmp->next;
+ if (!only_free)
+ {
+ if (api->del_netif_ip)
+ {
+ struct network_configuration *network =
+ get_network_by_ip_with_tree (ip_cidr_tmp->ip);
+ if (network)
+ {
+ if (network->phy_net->bond_name[0] != 0)
+ {
+ (void) api->del_netif_ip (network->phy_net->bond_name, ip_cidr_tmp->ip); //fails only when netif_name not exist, no side effect so don't check return value.
+ }
+ else
+ {
+ (void) api->del_netif_ip (network->phy_net->
+ header->nic_name,
+ ip_cidr_tmp->ip);
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("can't find network by]IP=%u",
+ ip_cidr_tmp->ip);
+ }
+ }
+
+ trp_rb_erase ((void *) (u64_t) ip_cidr_tmp->ip,
+ &g_container_ip_root, ip_compare);
+ }
+
+ free (ip_cidr_tmp);
+ ip_cidr_tmp = NULL;
+ }
+}
+
+/*note:::the ip must be local order*/
+void
+container_multicast_rd (unsigned int ip, int op)
+{
+ rd_ip_data rd_ip = { 0 };
+ int ret = 0;
+
+ rd_ip.addr = ip;
+ rd_ip.masklen = 32;
+ if (0 == op)
+ {
+ ret = nstack_rd_ip_node_insert ("nstack-dpdk", &rd_ip);
+ }
+ else
+ {
+ ret = nstack_rd_ip_node_delete (&rd_ip);
+ }
+
+ if (0 != ret)
+ {
+ NSOPR_LOGERR ("nstack rd multicast ip:0x%x %s fail", ip,
+ (0 == op ? "insert" : "delete"));
+ }
+ else
+ {
+ NSOPR_LOGDBG ("nstack rd multicast ip:0x%x %s success", ip,
+ (0 == op ? "insert" : "delete"));
+ }
+
+ return;
+}
+
+static void
+free_container_multicast (struct container_multicast_id *multicast,
+ bool_t only_free)
+{
+ struct container_multicast_id *tmp = NULL;
+
+ while (multicast)
+ {
+ tmp = multicast;
+ multicast = multicast->next;
+ if (!only_free)
+ {
+ /*note:::multicast ip is network, need to change to local order, delete multicast ip from rd. */
+ container_multicast_rd (spl_ntohl (tmp->ip), 1);
+
+ trp_rb_erase ((void *) (u64_t) tmp->ip, &g_container_multicast_root,
+ ip_compare);
+ }
+
+ free (tmp);
+ tmp = NULL;
+ }
+}
+
+static void
+free_container_port (struct container_port *port, bool_t only_free)
+{
+ struct container_port *port_tmp = NULL;
+ struct container_port *port_curr = port;
+
+ while (port_curr)
+ {
+ port_tmp = port_curr;
+ port_curr = port_tmp->next;
+
+ free_container_multicast (port_tmp->multicast_list, only_free);
+ free_container_port_ip_cidr (port_tmp->ip_cidr_list, only_free);
+
+ if (port_tmp->buffer)
+ {
+ free_port_buffer (port_tmp->buffer);
+ port_tmp->buffer = NULL;
+ }
+
+ free (port_tmp);
+ port_tmp = NULL;
+ }
+}
+
+void
+free_container (struct container_ip *container, bool_t only_free)
+{
+ struct container_ip *container_tmp = NULL;
+ struct container_ip *container_curr = container;
+
+ while (container_curr)
+ {
+ container_tmp = container_curr;
+ container_curr = container_tmp->next;
+ if (container_tmp->ports_list)
+ {
+ free_container_port (container_tmp->ports_list, only_free);
+ }
+
+ free (container_tmp);
+ container_tmp = NULL;
+ }
+}
+
+struct container_port *
+parse_port_obj (struct json_object *port_obj)
+{
+ int retval;
+ struct json_object *port_name_obj = NULL;
+ struct json_object *ip_cidr_list_obj = NULL;
+ struct json_object *mcIDObj = NULL;
+
+ if (!port_obj)
+ {
+ NSOPR_LOGERR ("port_obj is null");
+ return NULL;
+ }
+
+ struct container_port *port = malloc (sizeof (struct container_port));
+ if (!port)
+ {
+ NSOPR_LOGERR ("malloc failed");
+ return NULL;
+ }
+
+ retval =
+ MEMSET_S (port, sizeof (struct container_port), 0,
+ sizeof (struct container_port));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ free (port);
+ return NULL;
+ }
+
+ json_object_object_get_ex (port_obj, "port_name", &port_name_obj);
+ if (port_name_obj)
+ {
+ const char *port_name = json_object_get_string (port_name_obj);
+ if ((NULL == port_name)
+ || (strlen (port_name) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ NSOPR_LOGERR ("port name is not ok");
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ STRCPY_S (port->port_name, sizeof (port->port_name), port_name);
+
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+ }
+
+ json_object_object_get_ex (port_obj, "ip_cidr", &ip_cidr_list_obj);
+ if (ip_cidr_list_obj)
+ {
+ int j;
+ int ip_cidr_num = json_object_array_length (ip_cidr_list_obj);
+ for (j = 0; j < ip_cidr_num; ++j)
+ {
+ struct json_object *ip_cidr_obj =
+ json_object_array_get_idx (ip_cidr_list_obj, j);
+ if (ip_cidr_obj)
+ {
+ char tmp[IP_MODULE_LENGTH_32] = { 0 };
+ struct container_port_ip_cidr *port_ip_cidr =
+ malloc (sizeof (struct container_port_ip_cidr));
+ if (NULL == port_ip_cidr)
+ {
+ NSOPR_LOGERR ("malloc failed");
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ MEMSET_S (port_ip_cidr,
+ sizeof (struct container_port_ip_cidr), 0,
+ sizeof (struct container_port_ip_cidr));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ free (port_ip_cidr);
+ port_ip_cidr = NULL;
+ goto RETURN_ERROR;
+ }
+
+ const char *ip_cidr = json_object_get_string (ip_cidr_obj);
+ if ((NULL == ip_cidr) || (ip_cidr[0] == 0))
+ {
+ NSOPR_LOGERR ("ip_cidr is not ok");
+ free (port_ip_cidr);
+ port_ip_cidr = NULL;
+ goto RETURN_ERROR;
+ }
+
+ const char *sub = strstr (ip_cidr, "/");
+ if ((NULL == sub)
+ || (sizeof (tmp) - 1 < (unsigned int) (sub - ip_cidr))
+ || (strlen (sub) > sizeof (tmp) - 1))
+ {
+ NSOPR_LOGERR
+ ("Error : Ipaddress notation must be in ip cidr notation!");
+ free (port_ip_cidr);
+ port_ip_cidr = NULL;
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ STRNCPY_S (tmp, sizeof (tmp), ip_cidr,
+ (size_t) (sub - ip_cidr));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRNCPY_S failed]ret=%d", retval);
+ free (port_ip_cidr);
+ port_ip_cidr = NULL;
+ goto RETURN_ERROR;
+ }
+
+ struct in_addr addr;
+ int iRet;
+ retval = MEMSET_S (&addr, sizeof (addr), 0, sizeof (addr));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ free (port_ip_cidr);
+ port_ip_cidr = NULL;
+ goto RETURN_ERROR;
+ }
+
+ iRet = spl_inet_aton (tmp, &addr);
+ if (0 == iRet)
+ {
+ NSOPR_LOGERR ("spl_inet_aton failed");
+ free (port_ip_cidr);
+ port_ip_cidr = NULL;
+ goto RETURN_ERROR;
+ }
+
+ port_ip_cidr->ip = addr.s_addr;
+ iRet = atoi (sub + 1);
+ if ((iRet <= 0) || (iRet > IP_MODULE_LENGTH_32))
+ {
+ NSOPR_LOGERR ("IP mask length is not correct");
+ free (port_ip_cidr);
+ port_ip_cidr = NULL;
+ goto RETURN_ERROR;
+ }
+
+ port_ip_cidr->mask_len = (unsigned int) iRet;
+ add_ip_cidr (port, port_ip_cidr);
+ }
+ }
+ }
+
+ json_object_object_get_ex (port_obj, "multicast_id", &mcIDObj);
+ if (mcIDObj)
+ {
+ int j;
+ int arrLen = json_object_array_length (mcIDObj);
+ if (0 == arrLen)
+ {
+ NSOPR_LOGERR ("arrLen is 0");
+ goto RETURN_ERROR;
+ }
+
+ for (j = 0; j < arrLen; ++j)
+ {
+ struct json_object *elemObj =
+ json_object_array_get_idx (mcIDObj, j);
+
+ if (elemObj)
+ {
+ struct json_object *tObj = NULL;
+ const char *tStr;
+ int ret;
+ struct in_addr addr;
+
+ struct container_multicast_id *mcID =
+ malloc (sizeof (struct container_multicast_id));
+ if (NULL == mcID)
+ {
+ NSOPR_LOGERR ("Can't alloc container multicast id");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (elemObj, "group_ip", &tObj);
+ if (NULL == tObj)
+ {
+ NSOPR_LOGERR ("No group_IP");
+ free (mcID);
+ mcID = NULL;
+ goto RETURN_ERROR;
+ }
+
+ tStr = json_object_get_string (tObj);
+ if (NULL == tStr)
+ {
+ NSOPR_LOGERR ("Get Multiple cast group IP Failed");
+ free (mcID);
+ mcID = NULL;
+ goto RETURN_ERROR;
+ }
+
+ ret = spl_inet_aton (tStr, &addr);
+ if (0 == ret)
+ {
+ NSOPR_LOGERR ("Parse group IP Failed");
+ free (mcID);
+ mcID = NULL;
+ goto RETURN_ERROR;
+ }
+
+ mcID->ip = addr.s_addr;
+ add_multilcast_ip (port, mcID);
+ }
+ }
+ }
+
+ const char *port_json = json_object_get_string (port_obj);
+ if ((NULL == port_json) || (0 == strlen (port_json)))
+ {
+ NSOPR_LOGERR ("json_object_get_string failed");
+ goto RETURN_ERROR;
+ }
+
+ port->buffer = malloc_port_buffer ();
+ if (!port->buffer)
+ {
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ STRCPY_S (get_port_json (port), IP_MODULE_PORT_JSON_LEN, port_json);
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+
+ return port;
+RETURN_ERROR:
+ free_container_port (port, IP_MODULE_TRUE);
+ return NULL;
+}
+
+struct container_ip *
+parse_container_ip_json (char *param)
+{
+ int retval;
+ struct json_object *obj = json_tokener_parse (param);
+ struct json_object *container_id_obj = NULL;
+ struct json_object *ports_list_obj = NULL;
+
+ if (!obj)
+ {
+ return NULL;
+ }
+
+ struct container_ip *container = malloc (sizeof (struct container_ip));
+ if (container == NULL)
+ {
+ json_object_put (obj);
+ return NULL;
+ }
+
+ retval =
+ MEMSET_S (container, sizeof (struct container_ip), 0,
+ sizeof (struct container_ip));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (obj, "containerID", &container_id_obj);
+ if (container_id_obj)
+ {
+ const char *container_id = json_object_get_string (container_id_obj);
+ if ((container_id == NULL) || (container_id[0] == 0)
+ || (strlen (container_id) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ MEMSET_S (container->container_id, sizeof (container->container_id),
+ 0, sizeof (container->container_id));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ STRCPY_S (container->container_id, sizeof (container->container_id),
+ container_id);
+
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ /* this mandatory parameter */
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (obj, "ports_list", &ports_list_obj);
+ if (ports_list_obj)
+ {
+ int i;
+ int port_num = json_object_array_length (ports_list_obj);
+
+ if (port_num == 0)
+ {
+ /* this mandatory parameter */
+ goto RETURN_ERROR;
+ }
+
+ for (i = 0; i < port_num; i++)
+ {
+ struct json_object *port_obj =
+ json_object_array_get_idx (ports_list_obj, i);
+ struct container_port *port = parse_port_obj (port_obj);
+ if (!port)
+ {
+ goto RETURN_ERROR;
+ }
+
+ add_port (container, port);
+ }
+ }
+ else
+ {
+ /* mandatory parameter */
+ goto RETURN_ERROR;
+ }
+
+ /* Check if this function is required, or needs more check inside this function,
+ as some of them are alraedy validated
+ */
+ if (!is_container_ok (container))
+ {
+ goto RETURN_ERROR;
+ }
+
+ json_object_put (obj);
+ return container;
+
+RETURN_ERROR:
+ json_object_put (obj);
+ free_container (container, IP_MODULE_TRUE);
+ return NULL;
+}
+
+bool_t
+is_ip_match_netif (unsigned int ip, char *netif_name)
+{
+ if (!netif_name)
+ {
+ return 0;
+ }
+
+ if (trp_rb_search ((void *) (u64_t) ip, &g_container_ip_root, ip_compare))
+ {
+ struct network_configuration *network =
+ get_network_by_ip_with_tree (ip);
+ if (network && network->phy_net && network->phy_net->header)
+ {
+ if (0 ==
+ strncmp (netif_name, network->phy_net->header->nic_name,
+ HAL_MAX_NIC_NAME_LEN))
+ {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+inline bool_t
+is_ip_exist (unsigned int ip)
+{
+ if (trp_rb_search ((void *) (u64_t) ip, &g_container_ip_root, ip_compare))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+validate_addcontainerconfig (struct container_ip *container)
+{
+ struct container_port *port;
+ struct container_ip *old =
+ get_container_by_container_id (container->container_id);
+ struct container_port *tmp = container->ports_list;
+
+ if (old)
+ {
+ struct container_port *last = NULL;
+
+ while (tmp)
+ {
+ if (get_port (container->container_id, tmp->port_name))
+ {
+ NSOPR_LOGERR ("port=%s already exists!", tmp->port_name);
+ return NSCRTL_RD_EXIST;
+ }
+
+ last = tmp;
+ tmp = tmp->next;
+ }
+
+ (void) last;
+ }
+
+ /* check if port_name duplicates in one json configuration */
+ tmp = container->ports_list;
+ while (tmp)
+ {
+ if (get_port_from_container (tmp))
+ {
+ NSOPR_LOGERR ("port=%s duplicates!", tmp->port_name);
+ return NSCRTL_RD_EXIST;
+ }
+
+ tmp = tmp->next;
+ }
+
+ bool_t is_nstack_dpdk_port;
+ struct container_port **ref = &container->ports_list;
+ while ((port = *ref))
+ {
+ is_nstack_dpdk_port = 1;
+ struct container_port_ip_cidr *ip_cidr = port->ip_cidr_list;
+ while (ip_cidr)
+ {
+ struct network_configuration *network =
+ get_network_by_ip_with_tree (ip_cidr->ip);
+ if (network && (0 == strcmp (network->type_name, "nstack-dpdk")))
+ {
+ struct netif *pnetif;
+ if (get_netif_by_ip (ip_cidr->ip))
+ {
+ NSOPR_LOGERR ("ip exists]IP=0x%08x", ip_cidr->ip);
+ return NSCRTL_RD_EXIST;
+ }
+
+ if (network->phy_net->bond_name[0] != 0)
+ {
+ pnetif =
+ find_netif_by_if_name (network->phy_net->bond_name);
+ }
+ else
+ {
+ pnetif =
+ find_netif_by_if_name (network->phy_net->
+ header->nic_name);
+ }
+
+ if (!pnetif)
+ {
+ NSOPR_LOGERR ("can't find netif, network json:%s",
+ get_network_json (network));
+ return NSCRTL_ERR;
+ }
+
+ if (0 == port->port_name[0])
+ {
+ NSOPR_LOGINF
+ ("ip=0x%08x is in nstack dpdk network, but port_name is null, json:%s",
+ ip_cidr->ip, get_port_json (port));
+ is_nstack_dpdk_port = 0;
+ break;
+ }
+ }
+ else
+ {
+ NSOPR_LOGINF ("port %s is not in nstack dpdk network, json:%s",
+ port->port_name, get_port_json (port));
+ is_nstack_dpdk_port = 0;
+ break;
+ }
+
+ ip_cidr = ip_cidr->next;
+ }
+
+ /* only use nstack dpdk port */
+ if (is_nstack_dpdk_port)
+ {
+ ref = &port->next;
+ }
+ else
+ {
+ *ref = port->next;
+ port->next = NULL;
+ free_container_port (port, IP_MODULE_TRUE);
+ }
+ }
+
+ return (!container->ports_list) ? NSCRTL_FREE_ALL_PORT : NSCRTL_OK;
+}
+
+/* get the num of IPs in a container , which in a certain subnet */
+extern struct network_list g_network_list;
+extern inline int is_in_subnet (unsigned int ip, struct ip_subnet *subnet);
+NSTACK_STATIC inline int get_network_ip_count
+ (struct container_ip *container, struct ip_subnet *subnet)
+{
+ int ip_count = 0;
+ struct container_port *port_list = NULL;
+ struct container_ip *ci = container;
+
+ while (ci)
+ {
+ port_list = ci->ports_list;
+ while (port_list)
+ {
+ struct container_port_ip_cidr *ip_list = port_list->ip_cidr_list;
+ while (ip_list)
+ {
+ if (!is_in_subnet (ip_list->ip, subnet))
+ {
+ ip_count++;
+ }
+
+ ip_list = ip_list->next;
+ }
+
+ port_list = port_list->next;
+ }
+
+ ci = ci->next;
+ }
+
+ return ip_count;
+}
+
+int
+check_ip_count (struct container_ip *container)
+{
+ int cur_count = 0;
+ int new_count = 0;
+
+ if (NULL == container)
+ {
+ return 1;
+ }
+
+ struct network_configuration *network = g_network_list.header;
+ while (network)
+ {
+ cur_count =
+ get_network_ip_count (g_container_list.header, network->ip_subnet);
+ new_count = get_network_ip_count (container, network->ip_subnet);
+
+ if ((cur_count > MAX_NETWORK_IP_COUNT)
+ || (new_count > MAX_NETWORK_IP_COUNT)
+ || (cur_count + new_count > MAX_NETWORK_IP_COUNT))
+ {
+ NSOPR_LOGERR
+ ("reach ip addr max count]network=%s, max=%d, current=%d, new=%d.",
+ network->network_name, MAX_NETWORK_IP_COUNT, cur_count,
+ new_count);
+ return 0;
+ }
+
+ network = network->next;
+ }
+
+ return 1;
+}
+
+int
+match_groupaddr (struct container_multicast_id *multi_list,
+ spl_ip_addr_t * groupaddr)
+{
+ struct container_multicast_id *group_info = multi_list;
+
+ while (group_info)
+ {
+ if (group_info->ip == groupaddr->addr)
+ {
+ return 1;
+ }
+
+ group_info = group_info->next;
+ }
+
+ return 0;
+}
+
+int
+add_container (struct container_ip *container)
+{
+ int retVal = 0;
+
+ /* need to check if any of the netif operation failed, then we should return fail */
+ retVal = validate_addcontainerconfig (container);
+ if (retVal != NSCRTL_OK)
+ {
+ free_container (container, IP_MODULE_TRUE);
+ return (NSCRTL_FREE_ALL_PORT == retVal) ? NSCRTL_OK : retVal;
+ }
+
+ /* control max network and ipaddress count */
+ if (!check_ip_count (container))
+ {
+ free_container (container, IP_MODULE_TRUE);
+ return NSCRTL_IP_COUNT_EXCEED;
+ }
+
+ struct container_port *last = NULL;
+ struct container_ip *old =
+ get_container_by_container_id (container->container_id);
+ if (old)
+ {
+ struct container_port *tmp = container->ports_list;
+ while (tmp)
+ {
+ /* here we don't need to check "if tmp->port_name == NULL", as validate_addcontainerconfig() has done this. */
+ if (get_port (container->container_id, tmp->port_name))
+ {
+ free_container (container, IP_MODULE_TRUE);
+ NSOPR_LOGERR ("port exist!");
+ return NSCRTL_RD_EXIST;
+ }
+
+ last = tmp;
+ tmp = tmp->next;
+ }
+ }
+ else
+ {
+ container->next = g_container_list.header;
+ g_container_list.header = container;
+ }
+
+ output_api *api = get_output_api ();
+ struct container_port *port = container->ports_list;
+ while (port)
+ {
+ struct container_port_ip_cidr *ip_cidr = port->ip_cidr_list;
+ while (ip_cidr)
+ {
+ if (api->add_netif_ip)
+ {
+ struct network_configuration *network =
+ get_network_by_ip_with_tree (ip_cidr->ip);
+ if (network)
+ {
+ unsigned int mask = ~0;
+ mask =
+ (mask << (IP_MODULE_SUBNET_MASK_LEN - ip_cidr->mask_len));
+ mask = spl_htonl (mask);
+ if (network->phy_net->bond_name[0] != 0)
+ {
+ (void) api->add_netif_ip (network->phy_net->bond_name, ip_cidr->ip, mask); //no need to check return value, validate_addcontainerconfig() has been checked parameters.
+ }
+ else
+ {
+ (void) api->add_netif_ip (network->phy_net->
+ header->nic_name, ip_cidr->ip,
+ mask);
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("can't find network by]IP=%u,port_name=%s",
+ ip_cidr->ip, port->port_name);
+ }
+ }
+
+ retVal =
+ trp_rb_insert ((void *) (u64_t) ip_cidr->ip, (void *) port,
+ &g_container_ip_root, ip_compare);
+
+ if (0 != retVal)
+ {
+ NSOPR_LOGERR ("trp_rb_insert failed]ip_cidr->ip=%u",
+ ip_cidr->ip);
+ }
+
+ ip_cidr = ip_cidr->next;
+ }
+ port = port->next;
+ }
+
+ if (old)
+ {
+ if (last)
+ {
+ last->next = old->ports_list;
+ old->ports_list = container->ports_list;
+ }
+
+ container->ports_list = NULL;
+ free_container (container, IP_MODULE_FALSE);
+ }
+
+ return NSCRTL_OK;
+}
+
+struct container_ip *
+get_container_by_container_id (char *container_id)
+{
+ if (NULL == container_id)
+ {
+ NSOPR_LOGERR ("Param input container ID is NULL");
+ return NULL;
+ }
+
+ struct container_ip *container = g_container_list.header;
+ while (container)
+ {
+ if (0 == strcmp (container->container_id, container_id))
+ {
+ return container;
+ }
+
+ container = container->next;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************
+* Prototype : getIpCfgAll
+* Description : Get All ip configurations
+* Input : char *
+* size_t
+* Output : char * patern:[***,***,***]
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+getIpCfgAll (char *jsonBuf, size_t size)
+{
+ int retval;
+
+ if (NULL == jsonBuf)
+ {
+ return NSCRTL_ERR;
+ }
+
+ if (size < 2)
+ {
+ NSOPR_LOGERR ("get all ip cfg error, buffer is not enough.");
+ return NSCRTL_STATUS_ERR;
+ }
+
+ char bfirstData = 1;
+ *jsonBuf = '[';
+ jsonBuf = jsonBuf + 1;
+
+ /*need another two char to keep [and ] */
+ size_t len = size - 2;
+ size_t strsize = 0;
+ struct container_port *port = NULL;
+ struct container_ip *container = g_container_list.header;
+ while (container)
+ {
+ port = container->ports_list;
+ while (port)
+ {
+ if (NULL == port->buffer)
+ {
+ port = port->next;
+ continue;
+ }
+
+ strsize = strlen (get_port_json (port)) + 1;
+
+ /*always reserve 1 char */
+ if ((strsize > 0) && (strsize < len))
+ {
+ if (bfirstData)
+ {
+ bfirstData = 0;
+ }
+ else
+ {
+ *jsonBuf = ',';
+ jsonBuf = jsonBuf + 1;
+ len = len - 1;
+ }
+
+ retval = STRCPY_S (jsonBuf, len, get_port_json (port));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ return NSCRTL_ERR;
+ }
+
+ len = len - strlen (get_port_json (port));
+ jsonBuf = jsonBuf + strlen (get_port_json (port));
+ }
+ else
+ {
+ NSOPR_LOGERR ("get all ip cfg error, buffer is not enough.");
+ return NSCRTL_STATUS_ERR;
+ }
+
+ port = port->next;
+ }
+
+ container = container->next;
+ }
+
+ *jsonBuf = ']';
+ return 0;
+}
+
+int
+del_port (char *container_id, char *port_name)
+{
+ struct container_port *port = NULL;
+ struct container_port **ref = NULL;
+ struct container_ip *container = NULL;
+ struct container_ip **container_ref = &g_container_list.header;
+
+ while ((container = *container_ref))
+ {
+ NSOPR_LOGDBG ("container->container_id=%s,container_id=%p",
+ container->container_id, container_id);
+ if (strcmp (container->container_id, container_id) == 0)
+ {
+ ref = &container->ports_list;
+ while ((port = *ref))
+ {
+ if (strcmp (port_name, port->port_name) == 0)
+ {
+ *ref = port->next;
+ port->next = NULL;
+ free_container_port (port, IP_MODULE_FALSE);
+ return 0;
+ }
+
+ ref = &port->next;
+ }
+
+ break;
+ }
+
+ container_ref = &container->next;
+ }
+
+ return NSCRTL_RD_NOT_EXIST;
+}
+
+struct container_port *
+get_port (char *container_id, char *port_name)
+{
+ struct container_port *port = NULL;
+ struct container_ip *container = g_container_list.header;
+
+ while (container)
+ {
+ if (strcmp (container->container_id, container_id) == 0)
+ {
+ port = container->ports_list;
+ while (port)
+ {
+ if (strcmp (port_name, port->port_name) == 0)
+ {
+ return port;
+ }
+
+ port = port->next;
+ }
+ }
+
+ container = container->next;
+ }
+
+ return NULL;
+}
+
+struct container_port *
+get_port_from_container (struct container_port *port)
+{
+ char *port_name = port->port_name;
+ struct container_port *tmp = port->next;
+
+ while (tmp)
+ {
+ if (strcmp (port_name, tmp->port_name) == 0)
+ {
+ return tmp;
+ }
+
+ tmp = tmp->next;
+ }
+
+ return NULL;
+}
diff --git a/stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c b/stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c
new file mode 100644
index 0000000..0ae61ed
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c
@@ -0,0 +1,347 @@
+/*
+*
+* 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 <string.h>
+#include "inet.h"
+#include "spl_ip_addr.h"
+#include "ip_module_api.h"
+#include "container_ip.h"
+#include "network.h"
+#include "config_common.h"
+#include "configuration_reader.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "spl_hal.h"
+#include "stackx_spl_share.h"
+#include "stackx/spl_api.h"
+#include "stackx_common.h"
+#include "spl_tcpip.h"
+
+static output_api g_output_api = { 0 };
+
+void
+regist_output_api (output_api * api)
+{
+ if (NULL == api)
+ {
+ NSOPR_LOGERR ("error!!!param api==NULL]");
+ return;
+ }
+
+ g_output_api = *api;
+}
+
+output_api *
+get_output_api ()
+{
+ return &g_output_api;
+}
+
+int
+process_post (void *arg, ip_module_type Type,
+ ip_module_operate_type operate_type)
+{
+ /* only when add network, in other words:
+ only when (IP_MODULE_NETWORK == Type) && (IP_MODULE_OPERATE_ADD == operate_type),
+ process_configuration() is called in read_fn thread itself.
+ other cases, will post_to tcpip_thread to handle them.
+
+ tips: when add network, it need to post msg(add netif) to tcpip thread and wait a sem,
+ but after the msg is handled by tcpip thread, the sem could be post.
+ so adding netword is handled in read_fn thread, can't be moved to tcpip thread.
+
+ But we should know, many global and static variables maybe not safe(netif,sc_dpdk etc.),
+ because they can be visited by multi-thread. */
+ if ((IP_MODULE_NETWORK == Type) && (IP_MODULE_OPERATE_ADD == operate_type))
+ {
+ return process_configuration (arg, Type, operate_type);
+ }
+
+ if (g_output_api.post_to)
+ {
+ int retval = g_output_api.post_to (arg, Type, operate_type);
+ if ((post_ip_module_msg == g_output_api.post_to) && (retval != ERR_OK)
+ && (arg != NULL))
+ {
+ if ((IP_MODULE_IP == Type)
+ && (IP_MODULE_OPERATE_ADD == operate_type))
+ {
+ free_container ((struct container_ip *) arg, IP_MODULE_TRUE);
+ }
+ else
+ {
+ free (arg);
+ }
+
+ arg = NULL;
+ NSOPR_LOGERR ("post failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_INPUT_ERR, "process_post failed!");
+ }
+
+ return retval;
+ }
+ else
+ {
+ NSOPR_LOGERR ("g_output_api.post_to==NULL");
+ NSOPR_SET_ERRINFO (NSCRTL_ERR,
+ "ERR:internal error, g_output_api.post_to==NULL]");
+ return -1;
+ }
+}
+
+/* arg can be NULL, no need check */
+int
+process_configuration (void *arg, ip_module_type Type,
+ ip_module_operate_type operate_type)
+{
+ NSOPR_LOGINF ("precoess begin]arg=%p,action=%d,type=%d", arg, operate_type,
+ Type);
+ int retval = 0;
+
+ switch (Type)
+ {
+ case IP_MODULE_NETWORK:
+ switch (operate_type)
+ {
+ case IP_MODULE_OPERATE_ADD:
+ retval =
+ add_network_configuration ((struct network_configuration *) arg);
+
+ /* When network exceeds max number, just log warning at operation.log */
+ if (retval == NSCRTL_NETWORK_COUNT_EXCEED)
+ {
+ NSOPR_LOGWAR
+ ("Warning!! Network count exceed max allowed number]max=%d",
+ MAX_NETWORK_COUNT);
+ }
+ else
+ {
+ NSOPR_SET_ERRINFO (retval,
+ "add_network_configuration return %d",
+ retval);
+ }
+
+ if (!retval)
+ {
+ /*init DPDK eth */
+ if ((retval = init_new_network_configuration ()) != ERR_OK)
+ {
+ free_network_configuration ((struct network_configuration *)
+ arg, IP_MODULE_TRUE);
+ NSOPR_SET_ERRINFO (retval,
+ "init_new_network_configuration return %d",
+ retval);
+ }
+ }
+ break;
+ case IP_MODULE_OPERATE_DEL:
+ {
+ retval = del_network_by_name ((char *) arg);
+ NSOPR_SET_ERRINFO (retval, "del_network_by_name return %d",
+ retval);
+ free (arg);
+ arg = NULL;
+ }
+ break;
+ case IP_MODULE_OPERATE_QUERY:
+ {
+ struct network_configuration *network =
+ get_network_by_name ((char *) arg);
+ if (!network)
+ {
+ retval = NSCRTL_RD_NOT_EXIST;
+ NSOPR_SET_ERRINFO (retval, "get_network_by_name return %d",
+ retval);
+ }
+ else
+ {
+ if (strlen (get_network_json (network)) >
+ sizeof (get_config_data ()->json_buff) - 1)
+ {
+ NSOPR_LOGERR
+ ("length of network->network_json too big]len=%u",
+ strlen (get_network_json (network)));
+ NSOPR_SET_ERRINFO (NSCRTL_ERR,
+ "ERR:internal error, buf is not enough]");
+ retval = NSCRTL_ERR;
+ }
+
+ retval =
+ STRCPY_S (get_config_data ()->json_buff,
+ sizeof (get_config_data ()->json_buff),
+ get_network_json (network));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ NSOPR_SET_ERRINFO (NSCRTL_ERR,
+ "ERR:internal error, STRCPY_S failed]ret=%d",
+ retval);
+ retval = NSCRTL_ERR;
+ }
+
+ }
+
+ free (arg);
+ arg = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case IP_MODULE_IP:
+ switch (operate_type)
+ {
+ case IP_MODULE_OPERATE_ADD:
+ retval = add_container ((struct container_ip *) arg);
+ NSOPR_SET_ERRINFO (retval, "add_container return %d", retval);
+ break;
+ case IP_MODULE_OPERATE_DEL:
+ {
+ struct ip_action_param *p = (struct ip_action_param *) arg;
+ retval = del_port (p->container_id, p->port_name);
+ NSOPR_SET_ERRINFO (retval, "del_port return %d", retval);
+ free (arg);
+ arg = NULL;
+ }
+ break;
+ case IP_MODULE_OPERATE_QUERY:
+ {
+ struct ip_action_param *p = (struct ip_action_param *) arg;
+ struct container_port *port =
+ get_port (p->container_id, p->port_name);
+ if (!port)
+ {
+ retval = NSCRTL_RD_NOT_EXIST;
+ NSOPR_SET_ERRINFO (retval, "get_port return %d", retval);
+ }
+ else
+ {
+ if (strlen (get_port_json (port)) >
+ sizeof (get_config_data ()->json_buff) - 1)
+ {
+ NSOPR_LOGERR
+ ("length of network->network_json too big]len=%u",
+ strlen (get_port_json (port)));
+ retval = NSCRTL_ERR;
+ }
+
+ retval =
+ STRCPY_S (get_config_data ()->json_buff,
+ sizeof (get_config_data ()->json_buff),
+ get_port_json (port));
+ if (EOK != retval)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retval);
+ retval = NSCRTL_ERR;
+ }
+
+ }
+
+ free (arg);
+ arg = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ break;
+ case IP_MODULE_NETWORK_ALL:
+ if (operate_type == IP_MODULE_OPERATE_QUERY)
+ {
+ retval =
+ get_network_all (get_config_data ()->json_buff,
+ sizeof (get_config_data ()->json_buff));
+ NSOPR_SET_ERRINFO (retval, "get_network_all return %d", retval);
+ }
+
+ break;
+
+ case IP_MODULE_IP_ALL:
+ if (operate_type == IP_MODULE_OPERATE_QUERY)
+ {
+ retval =
+ getIpCfgAll (get_config_data ()->json_buff,
+ sizeof (get_config_data ()->json_buff));
+ NSOPR_SET_ERRINFO (retval, "getIpCfgAll return %d", retval);
+ }
+
+ break;
+
+ case IP_MODULE_ALL:
+ if (operate_type == IP_MODULE_OPERATE_QUERY)
+ {
+ NSOPR_LOGERR
+ ("---------- IP_MODULE_ALL query is not implemented --------------");
+ NSOPR_SET_ERRINFO (NSCRTL_ERR,
+ "ERR:This query interface is not implemented. ErrCode:%d",
+ NSCRTL_ERR);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ NSOPR_LOGINF ("process finished]result=%d", retval);
+
+ return retval;
+}
+
+void
+ip_subnet_print (struct ip_subnet *subnet)
+{
+ spl_ip_addr_t ipAddr;
+
+ if (subnet == NULL)
+ {
+ return;
+ }
+
+ ipAddr.addr = spl_htonl (subnet->subnet);
+ NSPOL_LOGINF (IP_DEBUG, "]\t Subnet=%s/%u", spl_inet_ntoa (ipAddr),
+ subnet->mask_len);
+}
+
+port_buffer *
+malloc_port_buffer ()
+{
+ port_buffer *buffer = malloc (sizeof (port_buffer));
+ return buffer;
+}
+
+void
+free_port_buffer (port_buffer * buffer)
+{
+ free (buffer);
+}
+
+network_buffer *
+malloc_network_buffer ()
+{
+ network_buffer *buffer = malloc (sizeof (network_buffer));
+ return buffer;
+}
+
+void
+free_network_buffer (network_buffer * buffer)
+{
+ free (buffer);
+}
diff --git a/stacks/lwip_stack/lwip_src/ip_module/network.c b/stacks/lwip_stack/lwip_src/ip_module/network.c
new file mode 100644
index 0000000..83fbb7c
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/network.c
@@ -0,0 +1,1127 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <string.h>
+#include "json.h"
+#include "trp_rb_tree.h"
+#include "network.h"
+#include "nstack_log.h"
+#include "config_common.h"
+#include "stackx_spl_share.h"
+#include "stackx/spl_api.h"
+#include "sharedmemory.h"
+#include "nstack_securec.h"
+#include "nstack_rd_mng.h"
+#include "spl_hal.h"
+#include "inet.h"
+
+struct network_list g_network_list = { 0 };
+
+extern struct stackx_port_zone *p_stackx_port_zone;
+extern u32 spl_hal_is_nic_exist (const char *name);
+
+static bool_t
+is_phy_net_ok (struct phy_net *pst_phy_net)
+{
+ if (!pst_phy_net || !pst_phy_net->header)
+ {
+ NSOPR_LOGERR ("phy_net is not ok");
+ return 0;
+ }
+
+ return 1;
+}
+
+static bool_t
+is_network_configuration_ok (struct network_configuration *network)
+{
+ while (network)
+ {
+ if (!is_phy_net_ok (network->phy_net))
+ {
+ return 0;
+ }
+
+ network = network->next;
+ }
+
+ return 1;
+}
+
+static void
+add_ref_nic (struct phy_net *pst_phy_net, struct ref_nic *pst_ref_nic)
+{
+ pst_ref_nic->next = pst_phy_net->header;
+ pst_phy_net->header = pst_ref_nic;
+}
+
+static void
+free_ref_nic (struct ref_nic *pst_ref_nic)
+{
+ struct ref_nic *nic = pst_ref_nic;
+ struct ref_nic *tmp = NULL;
+
+ while (nic)
+ {
+ tmp = nic;
+ nic = tmp->next;
+ free (tmp);
+ }
+}
+
+static void
+free_phy_net (struct phy_net *pst_phy_net)
+{
+ if (pst_phy_net)
+ {
+ free_ref_nic (pst_phy_net->header);
+ free (pst_phy_net);
+ }
+}
+
+static void
+free_ip_subnet (struct ip_subnet *subnet, bool_t only_free)
+{
+ struct ip_subnet *tmp = NULL;
+
+ while (subnet)
+ {
+ tmp = subnet;
+ subnet = subnet->next;
+ free (tmp);
+ }
+}
+
+void
+free_network_configuration (struct network_configuration *network,
+ bool_t only_free)
+{
+ if (network)
+ {
+ free_ip_subnet (network->ip_subnet, only_free);
+ free_phy_net (network->phy_net);
+
+ if (network->buffer)
+ {
+ free_network_buffer (network->buffer);
+ network->buffer = NULL;
+ }
+
+ free (network);
+ }
+}
+
+inline int
+is_in_subnet (unsigned int ip, struct ip_subnet *subnet)
+{
+ unsigned int mask = ~0;
+ unsigned int seg_ip, seg;
+
+ mask = mask << (IP_MODULE_SUBNET_MASK_LEN - subnet->mask_len);
+
+ seg_ip = ip & mask;
+ seg = subnet->subnet & mask;
+
+ return seg_ip != seg ? 1 : 0;
+}
+
+inline struct network_configuration *
+get_network_by_ip_with_tree (unsigned int ip)
+{
+ unsigned int h_ip = spl_ntohl (ip);
+ struct network_configuration *p = g_network_list.header;
+
+ while (p)
+ {
+ if (!is_in_subnet (h_ip, p->ip_subnet))
+ {
+ return p;
+ }
+
+ p = p->next;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *
+get_network_by_name (char *name)
+{
+ struct network_configuration *network = g_network_list.header;
+
+ while (network)
+ {
+ if (strcasecmp (name, network->network_name) == 0)
+ {
+ return network;
+ }
+
+ network = network->next;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *
+get_network_by_nic_name (char *name)
+{
+ if (NULL == name)
+ {
+ return NULL;
+ }
+
+ struct ref_nic *refnic = NULL;
+ struct phy_net *phynet = NULL;
+ struct network_configuration *network = g_network_list.header;
+ while (network)
+ {
+ phynet = network->phy_net;
+ if (phynet)
+ {
+ if ((phynet->bond_mode != -1)
+ && strcmp (name, phynet->bond_name) == 0)
+ {
+ return network;
+ }
+
+ refnic = phynet->header;
+ while (refnic)
+ {
+ if (strcmp (name, refnic->nic_name) == 0)
+ {
+ return network;
+ }
+
+ refnic = refnic->next;
+ }
+ }
+
+ network = network->next;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *
+get_network_by_name_from_json (struct network_configuration *network)
+{
+ char *name = network->network_name;
+ struct network_configuration *tmp = network->next;
+
+ while (tmp)
+ {
+ if (strcasecmp (name, tmp->network_name) == 0)
+ {
+ return tmp;
+ }
+
+ tmp = tmp->next;
+ }
+
+ return NULL;
+}
+
+NSTACK_STATIC inline int
+get_network_count ()
+{
+ int count = 0;
+ struct network_configuration *network = g_network_list.header;
+
+ while (network)
+ {
+ count++;
+ network = network->next;
+ }
+
+ return count;
+}
+
+int
+get_network_all (char *jsonBuf, size_t size)
+{
+ if (NULL == jsonBuf)
+ {
+ return NSCRTL_ERR;
+ }
+
+ if (size < 2)
+ {
+ NSOPR_LOGERR ("get all ip cfg error, buffer is not enough.");
+ return NSCRTL_STATUS_ERR;
+ }
+
+ int retVal;
+ char bfirstData = 1;
+ *jsonBuf = '[';
+ jsonBuf = jsonBuf + 1;
+
+ size_t len = size - 2; // strlen("[]")
+ size_t strsize = 0;
+ struct network_configuration *network = g_network_list.header;
+ while (network)
+ {
+ if (NULL == network->buffer)
+ {
+ network = network->next;
+ continue;
+ }
+
+ if (bfirstData)
+ {
+ bfirstData = 0;
+ }
+ else
+ {
+ *jsonBuf = ',';
+ jsonBuf = jsonBuf + 1;
+ len = len - 1;
+ }
+
+ strsize = strlen (get_network_json (network)) + 1;
+ if ((strsize > 0) && (strsize < len))
+ {
+ retVal = STRCPY_S (jsonBuf, len, get_network_json (network));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ return NSCRTL_STATUS_ERR;
+ }
+
+ len = len - strlen (get_network_json (network));
+ jsonBuf = jsonBuf + strlen (get_network_json (network));
+ }
+ else
+ {
+ NSOPR_LOGERR ("get all network cfg error, buffer is not enough.");
+ return NSCRTL_STATUS_ERR;
+ }
+
+ network = network->next;
+ }
+
+ *jsonBuf = ']';
+ return 0;
+}
+
+int
+nic_already_bind (const char *nic_name)
+{
+ struct ref_nic *pnic = NULL;
+ struct network_configuration *pnetwork = g_network_list.header;
+
+ while (pnetwork)
+ {
+ pnic = pnetwork->phy_net->header;
+ while (pnic)
+ {
+ if (0 == strcmp (pnic->nic_name, nic_name))
+ {
+ return 1;
+ }
+
+ pnic = pnic->next;
+ }
+
+ pnetwork = pnetwork->next;
+ }
+
+ return 0;
+}
+
+int
+nic_already_init (const char *nic_name)
+{
+ unsigned int i;
+
+ for (i = 0; i < p_stackx_port_zone->port_num; i++)
+ {
+ if (0 ==
+ strcmp (p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name,
+ nic_name))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+extern struct stackx_port_info *head_used_port_list;
+int
+bonded_nic_already_bind (struct network_configuration *pnetwork,
+ const char *nic_name)
+{
+ struct stackx_port_info *p_port_list = head_used_port_list;
+
+ while (p_port_list)
+ {
+ if (0 == strcmp (p_port_list->linux_ip.if_name, nic_name))
+ {
+ return 1;
+ }
+
+ p_port_list = p_port_list->next_use_port;
+ }
+
+ struct ref_nic *pnic = NULL;
+
+ while (pnetwork)
+ {
+ if (pnetwork->phy_net->bond_mode == -1)
+ {
+ pnic = pnetwork->phy_net->header;
+ if (0 == strcmp (pnic->nic_name, nic_name))
+ {
+ return 1;
+ }
+ }
+
+ pnetwork = pnetwork->next;
+ }
+
+ return 0;
+}
+
+extern struct bond_ports_info bond_ports_array;
+int
+nic_already_bond (struct network_configuration *pnetwork,
+ const char *nic_name)
+{
+ u8_t i, j;
+ struct bond_set *s;
+
+ for (i = 0; i < bond_ports_array.cnt; i++)
+ {
+ s = &bond_ports_array.ports[i];
+ for (j = 0; j < s->slave_port_cnt; j++)
+ {
+ if (strcmp (s->slave_ports[j], nic_name) == 0)
+ {
+ return 1;
+ }
+ }
+ }
+
+ struct ref_nic *pnic = NULL;
+
+ while (pnetwork)
+ {
+ if (pnetwork->phy_net->bond_mode != -1)
+ {
+ pnic = pnetwork->phy_net->header;
+ while (pnic)
+ {
+ if (0 == strcmp (pnic->nic_name, nic_name))
+ {
+ return 1;
+ }
+
+ pnic = pnic->next;
+ }
+ }
+
+ pnetwork = pnetwork->next;
+ }
+
+ return 0;
+}
+
+/*add network to rd*/
+void
+network_rd_proc (struct network_configuration *network, int op)
+{
+ struct ip_subnet *ptsubnet = NULL;
+ struct network_configuration *pn = NULL;
+ rd_ip_data rd_ip = { 0 };
+ int ret = 0;
+
+ pn = network;
+
+ while (pn)
+ {
+ if (0 == strcmp ("nstack-dpdk", pn->type_name))
+ {
+ ptsubnet = network->ip_subnet;
+ while (ptsubnet)
+ {
+ rd_ip.addr = ptsubnet->subnet;
+ rd_ip.masklen = ptsubnet->mask_len;
+ if (0 == op)
+ {
+ ret = nstack_rd_ip_node_insert (network->type_name, &rd_ip);
+ }
+ else
+ {
+ ret = nstack_rd_ip_node_delete (&rd_ip);
+ }
+
+ if (0 != ret)
+ {
+ NSOPR_LOGERR ("nstack rd subnet:0x%x, masklen:0x%x %s fail",
+ rd_ip.addr, rd_ip.masklen,
+ (0 == op ? "insert" : "delete"));
+ }
+ else
+ {
+ NSOPR_LOGDBG
+ ("nstack rd subnet:0x%x, masklen:0x%x %s success",
+ rd_ip.addr, rd_ip.masklen,
+ (0 == op ? "insert" : "delete"));
+ }
+
+ ptsubnet = ptsubnet->next;
+ }
+ }
+
+ pn = pn->next;
+ }
+
+ return;
+}
+
+/* add network to list in descending sort */
+void
+add_network_to_list (struct network_configuration *network)
+{
+ struct network_configuration *curr = g_network_list.header;
+ struct network_configuration *prev = NULL;
+
+ network->next = NULL;
+
+ /*add network to rd */
+ network_rd_proc (network, 0);
+
+ while (curr)
+ {
+ if (network->ip_subnet->mask_len >= curr->ip_subnet->mask_len)
+ {
+ break;
+ }
+
+ prev = curr;
+ curr = curr->next;
+ }
+
+ if (NULL == prev)
+ {
+ network->next = curr;
+ g_network_list.header = network;
+ }
+ else
+ {
+ network->next = prev->next;
+ prev->next = network;
+ }
+}
+
+int
+add_network_configuration (struct network_configuration
+ *pst_network_configuration)
+{
+ struct network_configuration *tmp = pst_network_configuration;
+ struct ref_nic *pheader;
+
+ if (tmp)
+ {
+ if (get_network_by_name (tmp->network_name)
+ || get_network_by_name_from_json (tmp))
+ {
+ NSOPR_LOGERR ("network exists or duplicates]network_name=%s",
+ tmp->network_name);
+ free_network_configuration (pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_RD_EXIST;
+ }
+
+ if (strcasecmp ("nstack-dpdk", tmp->type_name) != 0)
+ {
+ NSOPR_LOGWAR ("illegal network type]type_name=%s", tmp->type_name);
+ }
+
+ /* control max network and ipaddress count */
+ if (get_network_count () >= MAX_NETWORK_COUNT)
+ {
+ NSOPR_LOGERR ("network reach]max_count=%d", MAX_NETWORK_COUNT);
+ free_network_configuration (pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_NETWORK_COUNT_EXCEED;
+ }
+
+ /* If nic is not existed or not initiated, return error */
+ pheader = tmp->phy_net->header;
+ while (pheader)
+ {
+ if (!spl_hal_is_nic_exist (pheader->nic_name)
+ && !nic_already_init (pheader->nic_name))
+ {
+ NSOPR_LOGERR ("Invalid configuration %s not exist Error! ",
+ pheader->nic_name);
+ free_network_configuration (pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_RD_NOT_EXIST;
+ }
+
+ pheader = pheader->next;
+ }
+
+ /* if a bonded nic has been inited in a non-bond network, return error */
+ if (tmp->phy_net->bond_mode != -1)
+ {
+ pheader = tmp->phy_net->header;
+ while (pheader)
+ {
+ if (bonded_nic_already_bind
+ (pst_network_configuration, pheader->nic_name))
+ {
+ NSOPR_LOGERR ("Invalid configuration %s already bind! ",
+ pheader->nic_name);
+ free_network_configuration (pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_INPUT_ERR;
+ }
+
+ pheader = pheader->next;
+ }
+ }
+
+ /* if a non-bond nic has been inited in a bonded network, return error */
+ if (tmp->phy_net->bond_mode == -1)
+ {
+ pheader = tmp->phy_net->header;
+ while (pheader)
+ {
+ if (nic_already_bond
+ (pst_network_configuration, pheader->nic_name))
+ {
+ NSOPR_LOGERR ("Invalid configuration %s already bind! ",
+ pheader->nic_name);
+ free_network_configuration (pst_network_configuration,
+ IP_MODULE_TRUE);
+ return NSCRTL_INPUT_ERR;
+ }
+
+ pheader = pheader->next;
+ }
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("Invalid network configuration!");
+ return NSCRTL_INPUT_ERR;
+ }
+
+ /*looping through each node has move to read_ipmoduleoperateadd_configuration */
+ ip_subnet_print (tmp->ip_subnet);
+ add_network_to_list (tmp);
+
+ return NSCRTL_OK;
+}
+
+struct network_configuration *
+parse_network_obj (struct json_object *network_obj)
+{
+ int retVal;
+ struct network_configuration *pst_network_configuration = NULL;
+ struct json_object *network_name_obj = NULL, *args_obj = NULL, *phy_obj =
+ NULL, *type_name_obj = NULL;
+ struct json_object *ref_nic_list_obj = NULL, *bond_mode_obj =
+ NULL, *bond_name_obj = NULL, *ipam_obj = NULL;
+ struct json_object *subnet_obj = NULL;
+
+ if (!network_obj)
+ {
+ NSOPR_LOGERR ("network_obj is null");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration = malloc (sizeof (struct network_configuration));
+ if (NULL == pst_network_configuration)
+ {
+ NSOPR_LOGERR ("malloc failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ MEMSET_S (pst_network_configuration,
+ sizeof (struct network_configuration), 0,
+ sizeof (struct network_configuration));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (network_obj, "name", &network_name_obj);
+ if (network_name_obj)
+ {
+ const char *network_name = json_object_get_string (network_name_obj);
+ if ((NULL == network_name) || (network_name[0] == 0)
+ || (strlen (network_name) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ NSOPR_LOGERR ("network_name is not ok");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ STRCPY_S (pst_network_configuration->network_name,
+ sizeof (pst_network_configuration->network_name),
+ network_name);
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("name is not ok");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (network_obj, "type", &type_name_obj);
+ if (type_name_obj)
+ {
+ const char *type_name = json_object_get_string (type_name_obj);
+ if ((NULL == type_name) || (type_name[0] == 0)
+ || (strlen (type_name) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ NSOPR_LOGERR ("type parse error");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ STRCPY_S (pst_network_configuration->type_name,
+ sizeof (pst_network_configuration->type_name), type_name);
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d", retVal);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("type is not ok");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (network_obj, "args", &args_obj);
+ if (args_obj)
+ {
+ json_object_object_get_ex (args_obj, "phynet", &phy_obj);
+ if (phy_obj)
+ {
+ struct phy_net *pst_phy_net = malloc (sizeof (struct phy_net));
+ if (NULL == pst_phy_net)
+ {
+ NSOPR_LOGERR ("malloc failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ MEMSET_S (pst_phy_net, sizeof (struct phy_net), 0,
+ sizeof (struct phy_net));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d", retVal);
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (phy_obj, "ref_nic", &ref_nic_list_obj);
+ if (ref_nic_list_obj)
+ {
+ int j;
+ int ref_nic_num = json_object_array_length (ref_nic_list_obj);
+ if (0 == ref_nic_num)
+ {
+ NSOPR_LOGERR ("ref_nic is empty");
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ for (j = ref_nic_num - 1; j >= 0; j--)
+ {
+ struct json_object *ref_nic_obj =
+ json_object_array_get_idx (ref_nic_list_obj, j);
+ if (ref_nic_obj)
+ {
+ const char *nic_name =
+ json_object_get_string (ref_nic_obj);
+ if ((NULL == nic_name) || (nic_name[0] == 0)
+ || (strlen (nic_name) >= HAL_MAX_NIC_NAME_LEN))
+ {
+ NSOPR_LOGERR ("nic_name is not ok");
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ struct ref_nic *pst_ref_nic =
+ malloc (sizeof (struct ref_nic));
+ if (NULL == pst_ref_nic)
+ {
+ NSOPR_LOGERR ("malloc failed");
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ MEMSET_S (pst_ref_nic, sizeof (struct ref_nic), 0,
+ sizeof (struct ref_nic));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d.", retVal);
+ free (pst_ref_nic);
+ pst_ref_nic = NULL;
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ STRCPY_S (pst_ref_nic->nic_name,
+ sizeof (pst_ref_nic->nic_name), nic_name);
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ free (pst_ref_nic);
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ add_ref_nic (pst_phy_net, pst_ref_nic);
+ }
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("ref_nic is not ok");
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (phy_obj, "bond_mode", &bond_mode_obj);
+ if (bond_mode_obj)
+ {
+ pst_phy_net->bond_mode = json_object_get_int (bond_mode_obj);
+ if (pst_phy_net->bond_mode != -1)
+ {
+ json_object_object_get_ex (phy_obj, "bond_name",
+ &bond_name_obj);
+ if (bond_name_obj)
+ {
+ const char *bond_name =
+ json_object_get_string (bond_name_obj);
+ if ((NULL == bond_name)
+ || (strlen (bond_name) >= IP_MODULE_MAX_NAME_LEN))
+ {
+ NSOPR_LOGERR ("bond_name is not ok");
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ MEMSET_S (pst_phy_net->bond_name,
+ sizeof (pst_phy_net->bond_name), 0,
+ sizeof (pst_phy_net->bond_name));
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d.", retVal);
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ STRNCPY_S (pst_phy_net->bond_name,
+ sizeof (pst_phy_net->bond_name), bond_name,
+ strlen (bond_name));
+
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("STRNCPY_S failed]retVal=%d", retVal);
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("bond_name is not ok");
+ free_phy_net (pst_phy_net);
+ goto RETURN_ERROR;
+ }
+ }
+ }
+ else
+ {
+ pst_phy_net->bond_mode = -1;
+ }
+
+ pst_network_configuration->phy_net = pst_phy_net;
+ }
+ else
+ {
+ NSOPR_LOGERR ("phy_net is not ok");
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("args is not ok");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (network_obj, "ipam", &ipam_obj);
+ if (ipam_obj)
+ {
+ json_object_object_get_ex (ipam_obj, "subnet", &subnet_obj);
+ if (subnet_obj)
+ {
+ int iRet;
+ char tmp[IP_MODULE_LENGTH_32] = { 0 };
+ const char *subnet = json_object_get_string (subnet_obj);
+ struct in_addr addr;
+
+ retVal = MEMSET_S (&addr, sizeof (addr), 0, sizeof (addr));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ if ((NULL == subnet) || (subnet[0] == 0)
+ || (strlen (subnet) > IP_MODULE_LENGTH_32))
+ {
+ NSOPR_LOGERR ("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+
+ const char *sub = strstr (subnet, "/");
+ if ((NULL == sub)
+ || (sizeof (tmp) - 1 <= (unsigned int) (sub - subnet))
+ || (strlen (sub) >= sizeof (tmp) - 1))
+ {
+ NSOPR_LOGERR ("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+
+ iRet =
+ STRNCPY_S (tmp, sizeof (tmp), subnet, (size_t) (sub - subnet));
+ if (EOK != iRet)
+ {
+ NSOPR_LOGERR ("STRNCPY_S failed]ret=%d", iRet);
+ goto RETURN_ERROR;
+ }
+
+ iRet = spl_inet_aton (tmp, &addr);
+ if (0 == iRet)
+ {
+ NSOPR_LOGERR ("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->ip_subnet =
+ (struct ip_subnet *) malloc (sizeof (struct ip_subnet));
+ if (!pst_network_configuration->ip_subnet)
+ {
+ NSOPR_LOGERR ("malloc failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ MEMSET_S (pst_network_configuration->ip_subnet,
+ sizeof (struct ip_subnet), 0,
+ sizeof (struct ip_subnet));
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("MEMSET_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->ip_subnet->next = NULL;
+ pst_network_configuration->ip_subnet->subnet =
+ spl_ntohl (addr.s_addr);
+
+ iRet = atoi (sub + 1);
+ if ((iRet < 0) || (iRet > IP_MODULE_LENGTH_32))
+ {
+ NSOPR_LOGERR ("mask is not ok");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->ip_subnet->mask_len =
+ (unsigned int) iRet;
+ }
+ else
+ {
+ NSOPR_LOGERR ("subnet is not ok");
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGERR ("ipam is not ok");
+ goto RETURN_ERROR;
+ }
+
+ const char *network_json = json_object_get_string (network_obj);
+ if ((NULL == network_json) || (network_json[0] == 0))
+ {
+ NSOPR_LOGERR ("json_object_get_string failed");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->buffer = malloc_network_buffer ();
+ if (!pst_network_configuration->buffer)
+ {
+ NSOPR_LOGERR ("malloc_network_buffer failed");
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ STRCPY_S (get_network_json (pst_network_configuration),
+ IP_MODULE_NETWORK_JSON_LEN, network_json);
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ goto RETURN_ERROR;
+ }
+
+ return pst_network_configuration;
+
+RETURN_ERROR:
+ if (pst_network_configuration)
+ {
+ free_network_configuration (pst_network_configuration, IP_MODULE_TRUE);
+ pst_network_configuration = NULL;
+ }
+
+ return NULL;
+}
+
+struct network_configuration *
+parse_network_json (char *param, struct network_configuration *pnetwork_list)
+{
+ struct json_object *obj = json_tokener_parse (param);
+ struct network_configuration *pst_network_configuration = NULL;
+
+ if (!obj)
+ {
+ NSOPR_LOGERR ("parse error");
+ return NULL;
+ }
+
+ int network_num = json_object_array_length (obj);
+ if (0 == network_num)
+ {
+ json_object_put (obj);
+ return NULL;
+ }
+
+ int i;
+ for (i = 0; i < network_num; i++)
+ {
+ struct json_object *network_obj = json_object_array_get_idx (obj, i);
+ if (network_obj)
+ {
+ pst_network_configuration = parse_network_obj (network_obj);
+ if (!pst_network_configuration)
+ {
+ NSOPR_LOGERR ("parse_network_obj error");
+ goto RETURN_ERROR;
+ }
+
+ pst_network_configuration->next = pnetwork_list;
+ pnetwork_list = pst_network_configuration;
+ pst_network_configuration = NULL;
+ }
+ else
+ {
+ NSOPR_LOGERR ("network_obj is NULL");
+ goto RETURN_ERROR;
+ }
+ }
+
+ if (pnetwork_list)
+ {
+ if (!is_network_configuration_ok (pnetwork_list))
+ {
+ NSOPR_LOGERR ("network_configuration is not ok");
+ goto RETURN_ERROR;
+ }
+ }
+
+ json_object_put (obj);
+ return pnetwork_list;
+
+RETURN_ERROR:
+ free_network_configuration (pnetwork_list, IP_MODULE_TRUE);
+ json_object_put (obj);
+ return NULL;
+}
+
+int
+del_network_by_name (char *name)
+{
+ struct network_configuration *network = NULL;
+ struct network_configuration **ref = &g_network_list.header;
+
+ while ((network = *ref))
+ {
+ if (strcasecmp (name, network->network_name) == 0)
+ {
+ *ref = network->next;
+ network->next = NULL;
+
+ /*delete netework from rd */
+ network_rd_proc (network, 1);
+
+ free_network_configuration (network, IP_MODULE_FALSE);
+ return 0;
+ }
+
+ ref = &network->next;
+ }
+
+ return NSCRTL_RD_NOT_EXIST;
+}
+
+int
+is_in_same_network (unsigned int src_ip, unsigned int dst_ip)
+{
+ if (src_ip == dst_ip)
+ {
+ return 1;
+ }
+
+ struct network_configuration *src = get_network_by_ip_with_tree (src_ip);
+ struct network_configuration *dst = get_network_by_ip_with_tree (dst_ip);
+ if (src && (src == dst))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+struct network_configuration *
+get_network_list ()
+{
+ return g_network_list.header;
+}
diff --git a/stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c b/stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c
new file mode 100644
index 0000000..1990f52
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c
@@ -0,0 +1,563 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "trp_rb_tree.h"
+
+NSTACK_STATIC void
+__rb_rotate_left (struct trp_rb_node *X, struct trp_rb_root *root)
+{
+ /**************************
+ * rotate Node X to left *
+ **************************/
+
+ struct trp_rb_node *Y = X->rb_right;
+
+ /* estblish X->Right link */
+ X->rb_right = Y->rb_left;
+ if (Y->rb_left != NULL)
+ Y->rb_left->rb_parent = X;
+
+ /* estblish Y->Parent link */
+ Y->rb_parent = X->rb_parent;
+ if (X->rb_parent)
+ {
+ if (X == X->rb_parent->rb_left)
+ X->rb_parent->rb_left = Y;
+ else
+ X->rb_parent->rb_right = Y;
+ }
+ else
+ {
+ root->rb_node = Y;
+ }
+
+ /* link X and Y */
+ Y->rb_left = X;
+ X->rb_parent = Y;
+
+ return;
+}
+
+NSTACK_STATIC void
+__rb_rotate_right (struct trp_rb_node *X, struct trp_rb_root *root)
+{
+ /****************************
+ * rotate Node X to right *
+ ****************************/
+
+ struct trp_rb_node *Y = X->rb_left;
+
+ /* estblish X->Left link */
+ X->rb_left = Y->rb_right;
+ if (Y->rb_right != NULL)
+ Y->rb_right->rb_parent = X;
+
+ /* estblish Y->Parent link */
+ Y->rb_parent = X->rb_parent;
+ if (X->rb_parent)
+ {
+ if (X == X->rb_parent->rb_right)
+ X->rb_parent->rb_right = Y;
+ else
+ X->rb_parent->rb_left = Y;
+ }
+ else
+ {
+ root->rb_node = Y;
+ }
+
+ /* link X and Y */
+ Y->rb_right = X;
+ X->rb_parent = Y;
+
+ return;
+}
+
+/* X, Y are for application */
+NSTACK_STATIC void
+__rb_erase_color (struct trp_rb_node *X, struct trp_rb_node *Parent,
+ struct trp_rb_root *root)
+{
+ /*************************************
+ * maintain red-black tree balance *
+ * after deleting node X *
+ *************************************/
+
+ while (X != root->rb_node && (!X || X->color == RB_BLACK))
+ {
+
+ if (Parent == NULL)
+ {
+ break;
+ }
+
+ if (X == Parent->rb_left)
+ {
+ struct trp_rb_node *W = Parent->rb_right;
+ if (W->color == RB_RED)
+ {
+ W->color = RB_BLACK;
+ Parent->color = RB_RED; /* Parent != NIL? */
+ __rb_rotate_left (Parent, root);
+ W = Parent->rb_right;
+ }
+
+ if ((!W->rb_left || W->rb_left->color == RB_BLACK)
+ && (!W->rb_right || W->rb_right->color == RB_BLACK))
+ {
+ W->color = RB_RED;
+ X = Parent;
+ Parent = X->rb_parent;
+ }
+ else
+ {
+ if (!W->rb_right || W->rb_right->color == RB_BLACK)
+ {
+ if (W->rb_left != NULL)
+ W->rb_left->color = RB_BLACK;
+ W->color = RB_RED;
+ __rb_rotate_right (W, root);
+ W = Parent->rb_right;
+ }
+
+ W->color = Parent->color;
+ Parent->color = RB_BLACK;
+ if (W->rb_right->color != RB_BLACK)
+ {
+ W->rb_right->color = RB_BLACK;
+ }
+ __rb_rotate_left (Parent, root);
+ X = root->rb_node;
+ break;
+ }
+ }
+ else
+ {
+
+ struct trp_rb_node *W = Parent->rb_left;
+ if (W->color == RB_RED)
+ {
+ W->color = RB_BLACK;
+ Parent->color = RB_RED; /* Parent != NIL? */
+ __rb_rotate_right (Parent, root);
+ W = Parent->rb_left;
+ }
+
+ if ((!W->rb_left || (W->rb_left->color == RB_BLACK))
+ && (!W->rb_right || (W->rb_right->color == RB_BLACK)))
+ {
+ W->color = RB_RED;
+ X = Parent;
+ Parent = X->rb_parent;
+ }
+ else
+ {
+ if (!W->rb_left || (W->rb_left->color == RB_BLACK))
+ {
+ if (W->rb_right != NULL)
+ W->rb_right->color = RB_BLACK;
+ W->color = RB_RED;
+ __rb_rotate_left (W, root);
+ W = Parent->rb_left;
+ }
+
+ W->color = Parent->color;
+ Parent->color = RB_BLACK;
+ if (W->rb_left->color != RB_BLACK)
+ {
+ W->rb_left->color = RB_BLACK;
+ }
+ __rb_rotate_right (Parent, root);
+ X = root->rb_node;
+ break;
+ }
+ }
+ }
+
+ if (X)
+ {
+ X->color = RB_BLACK;
+ }
+
+ return;
+}
+
+static void
+rb_insert_color (struct trp_rb_node *X, struct trp_rb_root *root)
+{
+ /*************************************
+ * maintain red-black tree balance *
+ * after inserting node X *
+ *************************************/
+
+ /* check red-black properties */
+ while (X != root->rb_node && X->rb_parent->color == RB_RED)
+ {
+ /* we have a violation */
+ if (X->rb_parent == X->rb_parent->rb_parent->rb_left)
+ {
+ struct trp_rb_node *Y = X->rb_parent->rb_parent->rb_right;
+ if (Y && Y->color == RB_RED)
+ {
+
+ /* uncle is red */
+ X->rb_parent->color = RB_BLACK;
+ Y->color = RB_BLACK;
+ X->rb_parent->rb_parent->color = RB_RED;
+ X = X->rb_parent->rb_parent;
+ }
+ else
+ {
+
+ /* uncle is black */
+ if (X == X->rb_parent->rb_right)
+ {
+ /* make X a left child */
+ X = X->rb_parent;
+ __rb_rotate_left (X, root);
+ }
+
+ /* recolor and rotate */
+ X->rb_parent->color = RB_BLACK;
+ X->rb_parent->rb_parent->color = RB_RED;
+ __rb_rotate_right (X->rb_parent->rb_parent, root);
+ }
+ }
+ else
+ {
+
+ /* miror image of above code */
+ struct trp_rb_node *Y = X->rb_parent->rb_parent->rb_left;
+ if (Y && (Y->color == RB_RED))
+ {
+
+ /* uncle is red */
+ X->rb_parent->color = RB_BLACK;
+ Y->color = RB_BLACK;
+ X->rb_parent->rb_parent->color = RB_RED;
+ X = X->rb_parent->rb_parent;
+ }
+ else
+ {
+
+ /* uncle is black */
+ if (X == X->rb_parent->rb_left)
+ {
+ X = X->rb_parent;
+ __rb_rotate_right (X, root);
+ }
+ X->rb_parent->color = RB_BLACK;
+ X->rb_parent->rb_parent->color = RB_RED;
+ __rb_rotate_left (X->rb_parent->rb_parent, root);
+ }
+ }
+ }
+
+ root->rb_node->color = RB_BLACK;
+
+ return;
+}
+
+static void
+rb_erase (struct trp_rb_node *node, struct trp_rb_root *root)
+{
+ struct trp_rb_node *child, *parent;
+ unsigned int color;
+
+ if (!node->rb_left)
+ {
+ child = node->rb_right;
+ }
+ else if (!node->rb_right)
+ {
+ child = node->rb_left;
+ }
+ else
+ {
+ struct trp_rb_node *old = node, *left;
+
+ node = node->rb_right;
+ while ((left = node->rb_left) != NULL)
+ {
+ node = left;
+ }
+
+ if (old->rb_parent)
+ {
+ if (old->rb_parent->rb_left == old)
+ {
+ old->rb_parent->rb_left = node;
+ }
+ else
+ {
+ old->rb_parent->rb_right = node;
+ }
+ }
+ else
+ {
+ root->rb_node = node;
+ }
+
+ child = node->rb_right;
+ parent = node->rb_parent;
+ color = node->color;
+
+ if (parent == old)
+ {
+ parent = node;
+ }
+ else
+ {
+ if (child)
+ {
+ child->rb_parent = parent;
+ }
+
+ parent->rb_left = child;
+
+ node->rb_right = old->rb_right;
+ old->rb_right->rb_parent = node;
+ }
+
+ node->color = old->color;
+ node->rb_parent = old->rb_parent;
+ node->rb_left = old->rb_left;
+ old->rb_left->rb_parent = node;
+
+ if (color == RB_BLACK)
+ {
+ __rb_erase_color (child, parent, root);
+ }
+
+ return;
+
+ }
+
+ parent = node->rb_parent;
+ color = node->color;
+
+ if (child)
+ {
+ child->rb_parent = parent;
+ }
+
+ if (parent)
+ {
+ if (parent->rb_left == node)
+ {
+ parent->rb_left = child;
+ }
+ else
+ {
+ parent->rb_right = child;
+ }
+ }
+ else
+ {
+ root->rb_node = child;
+ }
+
+ if (color == RB_BLACK)
+ {
+ __rb_erase_color (child, parent, root);
+ }
+
+ return;
+}
+
+NSTACK_STATIC trp_rb_node_t *
+rb_new_node (trp_key_t key, trp_data_t data,
+ trp_rb_node_t * parent /*, key_compare key_compare_fn */ )
+{
+ trp_rb_node_t *node = (trp_rb_node_t *) malloc (sizeof (trp_rb_node_t));
+ if (!node)
+ {
+ return NULL;
+ }
+ node->key = key;
+ node->data = data;
+ node->rb_parent = parent;
+ node->rb_left = node->rb_right = NULL;
+ node->color = RB_RED;
+ /*node->key_compare_fn = key_compare_fn; */
+ return node;
+}
+
+int
+trp_rb_insert (trp_key_t key, trp_data_t data, trp_rb_root_t * root,
+ key_compare key_compare_fn)
+{
+ trp_rb_node_t *node = root->rb_node, *parent = NULL;
+ int ret = 0; /* CID 24640 */
+ while (node)
+ {
+ parent = node;
+ ret = key_compare_fn (node->key, key);
+ if (0 < ret)
+ {
+ node = node->rb_left;
+ }
+ else if (0 > ret)
+ {
+ node = node->rb_right;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ node = rb_new_node (key, data, parent /*, key_compare_fn */ );
+ if (!node)
+ {
+ return -1;
+ }
+
+ if (parent)
+ {
+ if (ret > 0)
+ {
+ parent->rb_left = node;
+ }
+ else
+ {
+ parent->rb_right = node;
+ }
+ }
+ else
+ {
+ root->rb_node = node;
+ }
+
+ rb_insert_color (node, root);
+ return 0;
+}
+
+int
+trp_rb_insert_allow_same_key (trp_key_t key, trp_data_t data,
+ trp_rb_root_t * root,
+ key_compare key_compare_fn)
+{
+ trp_rb_node_t *node = root->rb_node, *parent = NULL;
+ int ret = 0; /*CID 24638 */
+ while (node)
+ {
+ parent = node;
+ ret = key_compare_fn (node->key, key);
+ if (0 < ret)
+ {
+ node = node->rb_left;
+ }
+ else
+ {
+ node = node->rb_right;
+ }
+ }
+
+ node = rb_new_node (key, data, parent /*, key_compare_fn */ );
+ if (!node)
+ {
+ return -1;
+ }
+
+ if (parent)
+ {
+ if (ret > 0)
+ {
+ parent->rb_left = node;
+ }
+ else
+ {
+ parent->rb_right = node;
+ }
+ }
+ else
+ {
+ root->rb_node = node;
+ }
+
+ rb_insert_color (node, root);
+ return 0;
+}
+
+NSTACK_STATIC trp_rb_node_t *
+trp_rb_search_inorder (trp_key_t key, trp_data_t data,
+ trp_rb_node_t * node, int *count,
+ key_compare key_compare_fn)
+{
+ if (!node)
+ {
+ return NULL;
+ }
+
+ int ret = key_compare_fn (node->key, key);;
+ if (0 == ret && data == node->data)
+ {
+ return node;
+ }
+
+ if ((NULL == count) || (0 >= --(*count)))
+ {
+ return NULL;
+ }
+
+ trp_rb_node_t *ret_node =
+ trp_rb_search_inorder (key, data, node->rb_left, count, key_compare_fn);
+ if (ret_node)
+ {
+ return ret_node;
+ }
+
+ ret_node =
+ trp_rb_search_inorder (key, data, node->rb_right, count, key_compare_fn);
+ return ret_node;
+}
+
+void
+trp_rb_erase_with_data (trp_key_t key, trp_data_t data, trp_rb_root_t * root,
+ int count, key_compare key_compare_fn)
+{
+ trp_rb_node_t *node;
+ /* recursion operation need depth protect */
+ if (!
+ (node =
+ trp_rb_search_inorder (key, data, root->rb_node, &count,
+ key_compare_fn)))
+ {
+ return;
+ }
+
+ rb_erase (node, root);
+ free (node);
+ node = NULL;
+}
+
+void
+trp_rb_erase (trp_key_t key, trp_rb_root_t * root, key_compare key_compare_fn)
+{
+ trp_rb_node_t *node;
+ if (!(node = trp_rb_search (key, root, key_compare_fn)))
+ {
+ return;
+ }
+
+ rb_erase (node, root);
+ free (node);
+ node = NULL;
+}
diff --git a/stacks/lwip_stack/lwip_src/netif/ethernetif.c b/stacks/lwip_stack/lwip_src/netif/ethernetif.c
new file mode 100644
index 0000000..6a3e810
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/netif/ethernetif.c
@@ -0,0 +1,167 @@
+/*
+*
+* 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 "spl_opt.h"
+
+#include "spl_def.h"
+#include "mem.h"
+#include "stackx/spl_pbuf.h"
+//#include <stackx/stats.h>
+//#include "sockets.h"
+#include <netinet/in.h>
+
+#include "stackx_spl_share.h"
+#include "stackx/spl_api.h"
+#include "lwip/etharp.h"
+
+#include <sc_dpdk.h>
+#include "sc_dpdk.h"
+
+#include "cpuid.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "spl_hal.h"
+#include "hal_api.h"
+
+#include "sys.h"
+
+#define IFNAME0 'e'
+#define IFNAME1 'n'
+
+struct ethernetif
+{
+ struct eth_addr *ethaddr;
+
+};
+
+#if (DPDK_MODULE != 1)
+NSTACK_STATIC void
+low_level_init (struct netif *pnetif)
+{
+ struct ether_addr eth_addr;
+
+ struct netifExt *pnetifExt = NULL;
+ NSPOL_LOGINF (NETIF_DEBUG, "low_level_init \n");
+
+ pnetifExt = getNetifExt (pnetif->num);
+ if (NULL == pnetifExt)
+ return;
+
+ hal_get_macaddr (pnetifExt->hdl, &eth_addr);
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "low_level_init: Port %s, MAC : %02X:%02X:%02X:%02X:%02X:%02X",
+ pnetifExt->if_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]);
+
+ pnetif->hwaddr_len = 6;
+ pnetif->hwaddr[0] = eth_addr.addr_bytes[0]; //0x00;
+ pnetif->hwaddr[1] = eth_addr.addr_bytes[1]; //0x1b;
+ pnetif->hwaddr[2] = eth_addr.addr_bytes[2]; //0x21;
+ pnetif->hwaddr[3] = eth_addr.addr_bytes[3]; //0x6b;
+ pnetif->hwaddr[4] = eth_addr.addr_bytes[4]; //0x24;
+ pnetif->hwaddr[5] = eth_addr.addr_bytes[5]; //0x40;
+ pnetif->mtu = SPL_FRAME_MTU;
+
+ /* don't set SPL_NETIF_FLAG_ETHARP if this device is not an ethernet one */
+ pnetif->flags =
+ NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
+ pnetif->flags |= NETIF_FLAG_IGMP;
+
+}
+#endif
+
+#if (DPDK_MODULE != 1)
+
+/**
+ * Should be called at the beginning of the program to set up the
+ * network interface. It calls the function low_level_init() to do the
+ * actual setup of the hardware.
+ *
+ * This function should be passed as a parameter to spl_netif_add().
+ *
+ * @param netif the lwip network interface structure for this ethernetif
+ * @return ERR_OK if the loopif is initialized
+ * ERR_MEM if privatedata couldn't be allocated
+ * any other err_t on error
+ */
+err_t
+ethernetif_init (struct netif * pnetif)
+{
+ struct ethernetif *eth_netif;
+
+ if (NULL == pnetif)
+ {
+ NSPOL_LOGERR ("netif=NULL");
+ return ERR_VAL;
+ }
+ NSPOL_LOGINF (NETIF_DEBUG, "ethernetif_init \n");
+
+ eth_netif = (struct ethernetif *) malloc (sizeof (struct ethernetif));
+ if (eth_netif == NULL)
+ {
+ NSPOL_LOGERR ("ethernetif_init: out of memory");
+ return ERR_MEM;
+ }
+
+ pnetif->state = eth_netif;
+ pnetif->name[0] = IFNAME0;
+ pnetif->name[1] = IFNAME1;
+
+ /* We directly use etharp_output() here to save a function call.
+ * You can instead declare your own function an call etharp_output()
+ * from it if you have to do some checks before sending (e.g. if link
+ * is available...) */
+ pnetif->output = etharp_output;
+ pnetif->linkoutput = spl_hal_output;
+
+ eth_netif->ethaddr = (struct eth_addr *) &(pnetif->hwaddr[0]);
+
+ // Add extra netif information here
+ if (0 != netifExt_add (pnetif))
+ {
+ return ERR_VAL;
+ }
+
+ /* initialize the hardware */
+ low_level_init (pnetif);
+ NSPOL_LOGINF (NETIF_DEBUG,
+ "ethernetif_init complete ifname [%c][%c][%d] \n",
+ pnetif->name[0], pnetif->name[1], pnetif->num);
+
+ return ERR_OK;
+}
+
+void
+ethernetif_packets_input (struct netif *pstnetif)
+{
+ struct spl_pbuf *p = NULL;
+ spl_hal_input (pstnetif, &p);
+
+ /* no packet could be read, silently ignore this */
+ if (p != NULL
+ && pstnetif->input (spl_convert_spl_pbuf_to_pbuf (p),
+ pstnetif) != ERR_OK)
+ {
+ NSPOL_LOGERR ("netif->input failed]p=%p, netif=%p", p, pstnetif);
+ }
+
+ /* Free the spl pbuf */
+ spl_pbuf_free (p);
+}
+#endif
+//#endif /* 0 */
diff --git a/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c b/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c
new file mode 100644
index 0000000..95f3eec
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/netif/sc_dpdk.c
@@ -0,0 +1,574 @@
+/*
+*
+* 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 "sc_dpdk.h"
+#include "common_mem_mbuf.h"
+#include "netif/common.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "nsfw_msg_api.h"
+#include "nsfw_maintain_api.h"
+#include "nsfw_recycle_api.h"
+#include "stackx_app_res.h"
+#include "stackx_pbuf.h"
+#ifdef SYS_MEM_RES_STAT
+#include "memp.h"
+#endif
+#include "spl_instance.h"
+#ifdef HAL_LIB
+#else
+#include "rte_memzone.h"
+#endif
+
+#define SPL_MEM_MODULE "spl_mem_module"
+
+#define TMR_TICK_LENGTH TCP_TMR_INTERVAL /* define the tick length */
+
+u32_t uStackArgIndex = 0;
+int stackx_core_mask = 40;
+
+int g_nstack_bind_cpu = 0;
+int g_tcpip_thread_sleep_time = 0;
+
+extern int sbr_create_tx_pool ();
+extern int stackx_stat_zone_create ();
+
+#define GLOBAL_STACK_CORE_ARG "-c"
+#define GLOBAL_STACK_CORE_BINE "-bind_cpu"
+
+u32 g_type;
+struct memory_statics memory_used_size[80];
+
+void
+printmeminfo ()
+{
+ unsigned int i = 0;
+ long size = 0;
+
+ NSPOL_LOGDBG (SC_DPDK_INFO,
+ "*************************************************************");
+ for (i = 0; i < g_type; i++)
+ {
+ NSPOL_LOGDBG (SC_DPDK_INFO, "%s : %ld", memory_used_size[i].name,
+ memory_used_size[i].size);
+ size += memory_used_size[i].size;
+ }
+
+ size += (g_type * sizeof (struct common_mem_memzone));
+ NSPOL_LOGDBG (SC_DPDK_INFO, "total size %ld", size);
+ NSPOL_LOGDBG (SC_DPDK_INFO,
+ "*************************************************************");
+}
+
+void
+print_call_stack ()
+{
+}
+
+/* Parse the argument given in the command line of the application */
+void
+smp_parse_stack_args (int argc, char **argv)
+{
+ int i = 0;
+
+ const unsigned int global_core_length = 2; //GLOBAL_STACK_CORE_ARG "-c" string length is 2
+
+ for (i = uStackArgIndex + 1; i < argc; i++)
+ {
+ if ((i + 1) < argc)
+ {
+ if (strncmp (argv[i], "-sleep", 6) == 0) //compare "-sleep" string, length is 6
+ {
+ g_tcpip_thread_sleep_time = atoi (argv[++i]);
+ NSPOL_LOGDBG (SC_DPDK_INFO, "g_tcpip_thread_sleep_time=%d",
+ g_tcpip_thread_sleep_time);
+ continue;
+ }
+
+ if (strncmp (argv[i], GLOBAL_STACK_CORE_ARG, global_core_length) ==
+ 0)
+ {
+ stackx_core_mask = atoi (argv[++i]);
+ if (stackx_core_mask < 1)
+ {
+ NSPOL_LOGDBG (SC_DPDK_INFO,
+ "Invalid Args:core_mask can't be less than 1,input value is:%s",
+ argv[i]);
+ }
+
+ continue;
+ }
+
+ if (strncmp
+ (argv[i], GLOBAL_STACK_CORE_BINE,
+ sizeof (GLOBAL_STACK_CORE_BINE)) == 0)
+ {
+ if (argv[++i])
+ {
+ g_nstack_bind_cpu = atoi (argv[i]);
+ }
+
+ if (g_nstack_bind_cpu < 0)
+ {
+ g_nstack_bind_cpu = 0;
+ }
+
+ continue;
+ }
+ }
+ else
+ {
+ NSPOL_LOGDBG (SC_DPDK_INFO, "Invalid args:%s miss value ", argv[i]); //now ,only support this format ,others maybe supported in future
+ }
+ }
+
+ return;
+}
+
+mpool_handle
+create_tx_mbuf_pool ()
+{
+ mpool_handle mbf_pool_handle = NULL;
+
+ nsfw_mem_mbfpool mbuf_pool;
+
+ mbuf_pool.stname.entype = NSFW_SHMEM;
+ int retval =
+ spl_snprintf (mbuf_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ get_mempoll_tx_name ());
+ if (retval < 0)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed");
+ return NULL;
+ }
+
+ mbuf_pool.usnum = TX_MBUF_POOL_SIZE - 1;
+ mbuf_pool.uscash_size = 0;
+ mbuf_pool.uspriv_size = 0;
+ mbuf_pool.usdata_room = TX_MBUF_MAX_LEN;
+ mbuf_pool.isocket_id = SOCKET_ID_ANY;
+ mbuf_pool.enmptype = NSFW_MRING_SPSC;
+ mbf_pool_handle = nsfw_mem_mbfmp_create (&mbuf_pool);
+ if (NULL == mbf_pool_handle)
+ {
+ NSPOL_LOGERR ("create_tx_mbuf_pool failed]name=%s, num=%u, room=%u",
+ mbuf_pool.stname.aname, mbuf_pool.usnum,
+ mbuf_pool.usdata_room);
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "tx_mempool_malloc=%p, num=%u, room=%u, total_mem=%d",
+ mbf_pool_handle, TX_MBUF_POOL_SIZE, mbuf_pool.usdata_room,
+ nsfw_mem_get_len (mbf_pool_handle, NSFW_MEM_MBUF));
+ DPDK_MEMORY_COUNT ((get_mempoll_tx_name ()),
+ nsfw_mem_get_len (mbf_pool_handle, NSFW_MEM_MBUF));
+ MEM_STAT (SPL_MEM_MODULE, "spl_mbuf_pool", NSFW_SHMEM,
+ nsfw_mem_get_len (mbf_pool_handle, NSFW_MEM_MBUF));
+
+ return mbf_pool_handle;
+}
+
+mring_handle
+create_segment_pool ()
+{
+ nsfw_mem_sppool seg_pool;
+ seg_pool.stname.entype = NSFW_SHMEM;
+ int retval =
+ spl_snprintf (seg_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ get_mempoll_seg_name ());
+ if (retval < 0)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed");
+ return NULL;
+ }
+
+ seg_pool.usnum = 16;
+ seg_pool.useltsize = sizeof (struct common_pcb);
+ seg_pool.isocket_id = SOCKET_ID_ANY;
+ seg_pool.enmptype = NSFW_MRING_SPSC;
+
+ mring_handle seg_mp_handle = nsfw_mem_sp_create (&seg_pool);
+ if (NULL == seg_mp_handle)
+ {
+ NSPOL_LOGERR
+ ("create_segment_pool common failed]name=%s, num=%u, size=%u",
+ seg_pool.stname.aname, SPL_MEMP_NUM_TCP_SEG, seg_pool.useltsize);
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "common seg_mempool_malloc=%p, num=%u, size=%u, total_mem=%d",
+ seg_mp_handle, SPL_MEMP_NUM_TCP_SEG, seg_pool.useltsize,
+ nsfw_mem_get_len (seg_mp_handle, NSFW_MEM_SPOOL));
+ DPDK_MEMORY_COUNT ((get_mempoll_seg_name ()),
+ nsfw_mem_get_len (seg_mp_handle, NSFW_MEM_SPOOL));
+ MEM_STAT (SPL_MEM_MODULE, "spl_seg_pool", NSFW_SHMEM,
+ nsfw_mem_get_len (seg_mp_handle, NSFW_MEM_SPOOL));
+ return seg_mp_handle;
+}
+
+mring_handle
+create_msg_pool ()
+{
+ nsfw_mem_sppool msg_pool;
+ msg_pool.stname.entype = NSFW_SHMEM;
+ int retval =
+ spl_snprintf (msg_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ get_mempoll_msg_name ());
+ if (retval < 0)
+ {
+ NSPOL_LOGERR ("spl_snprintf fail");
+ return NULL;
+ }
+
+ msg_pool.usnum = TX_MSG_POOL_SIZE;
+ msg_pool.useltsize = sizeof (data_com_msg);
+ msg_pool.isocket_id = SOCKET_ID_ANY;
+ msg_pool.enmptype = NSFW_MRING_MPMC;
+ mring_handle msg_mp_handle = nsfw_mem_sp_create (&msg_pool);
+
+ if (NULL == msg_mp_handle)
+ {
+ NSPOL_LOGERR ("create_msg_pool failed]name=%s, num=%u, size=%u",
+ msg_pool.stname.aname, TX_MSG_POOL_SIZE,
+ msg_pool.useltsize);
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "msg_pool_malloc=%p, num=%u, size=%u, total_mem=%d",
+ msg_mp_handle, TX_MSG_POOL_SIZE, msg_pool.useltsize,
+ nsfw_mem_get_len (msg_mp_handle, NSFW_MEM_SPOOL));
+ DPDK_MEMORY_COUNT ((get_mempoll_msg_name ()),
+ nsfw_mem_get_len (msg_mp_handle, NSFW_MEM_SPOOL));
+ MEM_STAT (SPL_MEM_MODULE, "spl_msg_pool", NSFW_SHMEM,
+ nsfw_mem_get_len (msg_mp_handle, NSFW_MEM_SPOOL));
+ return msg_mp_handle;
+}
+
+mring_handle
+create_primary_box ()
+{
+ nsfw_mem_mring mbox_pool;
+ mbox_pool.stname.entype = NSFW_SHMEM;
+ int retval =
+ spl_snprintf (mbox_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ get_stackx_ring_name ());
+ if (retval < 0)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed");
+ return NULL;
+ }
+
+ mbox_pool.usnum = MBOX_RING_SIZE - 1;
+ mbox_pool.isocket_id = SOCKET_ID_ANY;
+ mbox_pool.enmptype = NSFW_MRING_MPSC;
+ mring_handle mbox_handle = nsfw_mem_ring_create (&mbox_pool);
+ if (NULL == mbox_handle)
+ {
+ NSPOL_LOGERR ("create_primary_mbox failed]name=%s, num=%u",
+ mbox_pool.stname.aname, mbox_pool.usnum + 1);
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "primary_mbox_malloc=%p, num=%u, total_mem=%d",
+ mbox_handle, MBOX_RING_SIZE,
+ (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING)));
+ DPDK_MEMORY_COUNT ((get_stackx_ring_name ()),
+ (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING)));
+ MEM_STAT (SPL_MEM_MODULE, "primary_mbox_ring", NSFW_SHMEM,
+ (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING)));
+ return mbox_handle;
+}
+
+mring_handle
+create_priority_box (u32 prio)
+{
+ nsfw_mem_mring mbox_pool;
+ mbox_pool.stname.entype = NSFW_SHMEM;
+ int retval =
+ spl_snprintf (mbox_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ get_stackx_priority_ring_name (prio));
+ if (retval < 0)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed");
+ return NULL;
+ }
+
+ mbox_pool.usnum = MBOX_RING_SIZE - 1;
+ mbox_pool.isocket_id = SOCKET_ID_ANY;
+ mbox_pool.enmptype = NSFW_MRING_MPSC;
+ mring_handle mbox_handle = nsfw_mem_ring_create (&mbox_pool);
+ if (NULL == mbox_handle)
+ {
+ NSPOL_LOGERR ("Create priority mbox fail]name=%s, num=%u",
+ mbox_pool.stname.aname, mbox_pool.usnum + 1);
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "prio=%u, mbox=%p, num=%u, total_mem=%d", prio,
+ mbox_handle, MBOX_RING_SIZE,
+ (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING)));
+ DPDK_MEMORY_COUNT ((get_stackx_priority_ring_name (prio)),
+ (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING)));
+ MEM_STAT (SPL_MEM_MODULE, mbox_pool.stname.aname, NSFW_SHMEM,
+ (nsfw_mem_get_len (mbox_handle, NSFW_MEM_RING)));
+ return mbox_handle;
+
+}
+
+int
+init_instance ()
+{
+ int ret;
+ p_def_stack_instance =
+ (stackx_instance *) malloc (sizeof (stackx_instance));
+ if (NULL == p_def_stack_instance)
+ {
+ NSPOL_LOGERR ("malloc failed");
+ return -1;
+ }
+
+ ret = MEMSET_S (p_def_stack_instance, sizeof (stackx_instance), 0,
+ sizeof (stackx_instance));
+ if (EOK != ret)
+ {
+ NSPOL_LOGERR ("MEMSET_S failed]ret=%d", ret);
+ return -1;
+ }
+
+ p_def_stack_instance->rss_queue_id = 0;
+ p_def_stack_instance->netif_list = NULL;
+ p_def_stack_instance->mp_tx = create_tx_mbuf_pool ();
+ if (!p_def_stack_instance->mp_tx)
+ {
+ return -1;
+ }
+
+ (void) spl_reg_res_tx_mgr (p_def_stack_instance->mp_tx); // will only return 0, no need to check return value
+
+ /* Modified above code to hold common_pcb */
+ p_def_stack_instance->cpcb_seg = create_segment_pool ();
+ if (!p_def_stack_instance->cpcb_seg)
+ {
+ return -1;
+ }
+
+ p_def_stack_instance->lmsg_pool = create_msg_pool ();
+ if (!p_def_stack_instance->lmsg_pool)
+ {
+ return -1;
+ }
+
+ mring_handle mbox_array[SPL_MSG_BOX_NUM] = { NULL };
+ p_def_stack_instance->lstack.primary_mbox.llring = create_primary_box ();
+ if (!p_def_stack_instance->lstack.primary_mbox.llring)
+ {
+ return -1;
+ }
+ mbox_array[0] = p_def_stack_instance->lstack.primary_mbox.llring;
+
+ u32 m = 0;
+ while (m < MSG_PRIO_QUEUE_NUM)
+ {
+ p_def_stack_instance->lstack.priority_mbox[m].llring =
+ create_priority_box (m);
+ if (!p_def_stack_instance->lstack.priority_mbox[m].llring)
+ {
+ return -1;
+ }
+ mbox_array[m + 1] =
+ p_def_stack_instance->lstack.priority_mbox[m].llring;
+ m++;
+ }
+
+ (void) spl_add_mbox (mbox_array, SPL_MSG_BOX_NUM);
+
+ g_nsfw_rti_primary_stat = &p_def_stack_instance->lstat.primary_stat; //save to g_nsfw_rti_primary_stat(this is a SH addr)
+ return 0;
+}
+
+void
+spl_free_msgs_in_box (mring_handle r)
+{
+ i32 count = 0, i = 0;
+
+ void **msgs = NULL;
+ data_com_msg *m = NULL;
+
+ while ((count = nsfw_mem_ring_dequeuev (r, msgs, 32)) > 0)
+ {
+ /* drop all of them */
+ if (msgs == NULL)
+ break;
+
+ for (i = 0; i < count; i++)
+ {
+ m = (data_com_msg *) msgs[i];
+ if (m->param.op_type == MSG_ASYN_POST)
+ ASYNC_MSG_FREE (m);
+ else
+ SYNC_MSG_ACK (m);
+ }
+ }
+}
+
+inline int
+spl_msg_malloc (data_com_msg ** p_msg_entry)
+{
+ mring_handle msg_pool = NULL;
+ int rslt;
+ stackx_instance *instance = p_def_stack_instance;
+ msg_pool = instance->lmsg_pool;
+ if (!msg_pool)
+ {
+ NSPOL_LOGERR ("msg_pool is NULL");
+ return -1;
+ }
+
+ rslt = nsfw_mem_ring_dequeue (msg_pool, (void **) p_msg_entry);
+ if ((rslt == 0) || (*p_msg_entry == NULL))
+ {
+ NSPOL_LOGERR ("failed to get msg from ring");
+ return -1;
+ }
+
+ res_alloc (&(*p_msg_entry)->param.res_chk);
+
+ (*p_msg_entry)->param.msg_from = msg_pool;
+ (*p_msg_entry)->param.err = ERR_OK;
+ return 0;
+}
+
+struct spl_pbuf *
+spl_mbuf_malloc (uint16_t len, spl_pbuf_type Type, u16_t * count)
+{
+ struct common_mem_mbuf *mbuf = NULL;
+ struct common_mem_mbuf *mbuf_first = NULL;
+ struct common_mem_mbuf *mbuf_tail = NULL;
+ struct spl_pbuf *buf = NULL;
+ struct spl_pbuf *first = NULL;
+ struct spl_pbuf *tail = NULL;
+
+ mpool_handle mp = NULL;
+
+ mp = p_def_stack_instance->mp_tx;
+ if (mp == NULL)
+ {
+ return NULL; /*if mp is NULL when init app will Inform */
+ }
+
+ while (len > 0)
+ {
+ mbuf = (struct common_mem_mbuf *) nsfw_mem_mbf_alloc (mp, NSFW_SHMEM);
+ if (unlikely (mbuf == NULL))
+ {
+ if (mbuf_first != NULL)
+ {
+ if (res_free
+ (&
+ (((struct spl_pbuf *) ((char *) mbuf_first +
+ sizeof (struct
+ common_mem_mbuf)))->res_chk)))
+ {
+ NSPOL_LOGERR ("res_free failed");
+ }
+ spl_mbuf_free (mbuf_first);
+ }
+
+ return NULL;
+ }
+
+ uint16_t alloc = TX_MBUF_MAX_LEN;
+ if (len < TX_MBUF_MAX_LEN)
+ {
+ alloc = len;
+ }
+
+ (*count)++;
+ mbuf->data_len = alloc;
+ mbuf->next = NULL;
+ buf =
+ (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf));
+ res_alloc (&buf->res_chk);
+
+ buf->next_a = 0;
+ buf->payload_a = ADDR_LTOSH_EXT (common_pktmbuf_mtod (mbuf, void *));
+ buf->tot_len = len;
+ buf->len = alloc;
+ buf->type = Type;
+ buf->flags = 0;
+
+ buf->freeNext = NULL;
+
+ buf->conn_a = 0;
+
+ if (first == NULL)
+ {
+ first = buf;
+ mbuf_first = mbuf;
+ tail = buf;
+ mbuf_tail = mbuf;
+ mbuf_first->nb_segs = 1;
+ mbuf_first->pkt_len = alloc;
+ }
+ else
+ {
+ /* Already there is a check for the return value of rtp_pktmbuf_alloc,
+ hence not an issue */
+
+ tail->next_a = ADDR_LTOSH_EXT (buf);
+ tail = buf;
+#ifdef HAL_LIB
+#else
+ mbuf_tail->next = mbuf;
+#endif
+ mbuf_tail = mbuf;
+
+ mbuf_first->pkt_len = (mbuf_first->pkt_len + mbuf->data_len);
+ mbuf_first->nb_segs++;
+
+ }
+
+ len -= alloc;
+ }
+
+ return first;
+}
+
+/*
+ * Ring distribution function: protocol stack once a packet processing, so there is no use of bulk package
+ * @param buf pbuf means * @param packet_inport the packet from which the port to enter, for the configuration table with the ip comparison
+ * @ Protocol stack add location: ip.c-> ip_input () -> (if (netif == NULL) branch)
+ * @ Return value: 0 for the send into * 0 for the transmission failed: send the original failure 1,
+ * err = -20 did not match to the client, err = -1Ring full, overflow, will release the package
+*/
+
+inline void
+spl_mbuf_free (void *mbuf)
+{
+ (void) nsfw_mem_mbf_free ((mbuf_handle) mbuf, NSFW_SHMEM);
+}
+
+inline uint16_t
+spl_mbuf_refcnt_update (void *mbuf, int16_t value)
+{
+ common_mbuf_refcnt_set ((struct common_mem_mbuf *) mbuf,
+ common_mbuf_refcnt_read ((struct common_mem_mbuf *)
+ mbuf) + value);
+ return 1;
+}
diff --git a/stacks/lwip_stack/lwip_src/netif/spl_hal.c b/stacks/lwip_stack/lwip_src/netif/spl_hal.c
new file mode 100644
index 0000000..5f69a9d
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/netif/spl_hal.c
@@ -0,0 +1,1753 @@
+/*
+*
+* 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_arch.h"
+#include "netif.h"
+#include "spl_sockets.h"
+//#include <netinet/in.h>
+
+#include "stackx_spl_share.h"
+#include "stackx_pbuf.h"
+#include "spl_api.h"
+#include "sharedmemory.h"
+//#include "nettool.h"
+#include "lwip/etharp.h"
+#include "ip_module_api.h"
+#include "sc_dpdk.h"
+#include "nstack_log.h"
+#include "common.h"
+#include "nstack_securec.h"
+//#include "ip.h"
+#include "configuration_reader.h"
+#include "spl_hal.h"
+#include "nsfw_maintain_api.h"
+#include "stackx_common.h"
+#include "spl_instance.h"
+#include <netinet/in.h>
+#include "prot/tcp.h"
+
+extern u32_t g_mbuf_size[MAX_THREAD_NUM];
+extern u32_t uStackArgIndex;
+extern void smp_parse_stack_args (int argc, char **argv);
+extern void spl_do_dump (struct spl_pbuf *p, u16 direction);
+
+#define SPL_HAL_SEND_TRY 100000
+
+#define SPL_HAL_MODULE "SPL_HAL_MODULE"
+extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER];
+
+/* structure to store the rx and tx packets. Put two per cache line as ports
+ * used in pairs */
+struct port_stats
+{
+ unsigned rx;
+ unsigned tx;
+ unsigned drop;
+ u64_t rx_size;
+ u64_t tx_size;
+ u64_t recv_last_cycles;
+ u64_t send_last_cycles;
+} __attribute__ ((aligned (COMMON_CACHE_LINE_SIZE / 2)));
+
+struct port_capa
+{
+ u32_t tx_ipv4_cksum_offload;
+ u32_t tx_udp_cksum_offload;
+ u32_t tx_tcp_cksum_offload;
+};
+
+struct rx_pkts
+{
+ u16_t num;
+ u16_t index;
+ struct common_mem_mbuf *pkts[PKT_BURST];
+};
+
+struct tx_pkts
+{
+ u16_t num;
+ struct common_mem_mbuf *pkts[PKT_BURST];
+};
+
+struct port_pkts
+{
+ struct rx_pkts rx;
+ struct tx_pkts tx;
+};
+
+struct psd_header
+{
+ u32_t src_addr; /* IPaddress of source host. */
+ u32_t dst_addr; /* IPaddress of destination host(s). */
+ u8_t zero; /* zero. */
+ u8_t proto; /* L4 protocol type. */
+ u16_t len; /* L4 length. */
+} __attribute__ ((__packed__));
+
+NSTACK_STATIC unsigned num_ports_NIC = 0;
+NSTACK_STATIC unsigned num_ports_NIC_start = 0;
+
+struct stackx_port_info *head_used_port_list;
+struct stackx_port_zone *p_stackx_port_zone = NULL;
+
+struct bond_ports_info bond_ports_array = {.cnt = 0 };
+
+static u8_t bond_ports_array_cnt_start = 0;
+
+static struct port_capa spl_hal_capa = { 0 };
+
+static struct port_pkts spl_hal_pkts[HAL_MAX_NIC_NUM];
+
+NSTACK_STATIC inline u16_t
+get_ipv4_16b_sum (u16_t * ptr16, u32_t nr)
+{
+ u32_t sum = 0;
+
+ while (nr > 1)
+ {
+ sum += *ptr16;
+ nr -= sizeof (u16_t);
+ ptr16++;
+
+ if (sum > UINT16_MAX)
+ {
+ sum -= UINT16_MAX;
+ }
+ }
+
+ /* If length is in odd bytes */
+ if (nr)
+ {
+ sum += *((u8_t *) ptr16);
+ }
+
+ sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
+ sum &= 0x0ffff;
+ return (u16_t) sum;
+}
+
+NSTACK_STATIC inline u16_t
+get_ipv4_bswap16 (u16_t x)
+{
+ return (u16_t) (((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8));
+}
+
+NSTACK_STATIC inline u16_t
+get_ipv4_psd_sum (struct ip_hdr * iphdr, u64_t ol_flags)
+{
+ struct psd_header psd_hdr;
+
+ psd_hdr.src_addr = iphdr->src.addr;
+ psd_hdr.dst_addr = iphdr->dest.addr;
+ psd_hdr.zero = 0;
+ psd_hdr.proto = iphdr->_proto;
+
+ if (ol_flags & PKT_TX_TCP_SEG)
+ {
+ psd_hdr.len = 0;
+ }
+ else
+ {
+ psd_hdr.len = get_ipv4_bswap16 ((get_ipv4_bswap16 (iphdr->_len)
+ - sizeof (struct ip_hdr)));
+ }
+
+ return get_ipv4_16b_sum ((u16_t *) & psd_hdr, sizeof (struct psd_header));
+}
+
+/* should be called after head_used_port_list is initialized */
+NSTACK_STATIC hal_hdl_t
+get_port_hdl_by_name (const char *name)
+{
+ unsigned int i = 0;
+ struct stackx_port_info *p = p_stackx_port_zone->stackx_one_port;
+
+ while (i < p_stackx_port_zone->port_num)
+ {
+ if (!strncasecmp (p->linux_ip.if_name, name, strlen (name)))
+ {
+ return p->linux_ip.hdl;
+ }
+
+ p = &p_stackx_port_zone->stackx_one_port[++i];
+ }
+
+ NSPOL_LOGERR ("failed to find port id]name=%s", name);
+ return hal_get_invalid_hdl ();
+}
+
+NSTACK_STATIC struct stackx_port_info *
+get_port_info_by_name (const char *name)
+{
+ struct stackx_port_info *p = p_stackx_port_zone->stackx_one_port;
+ unsigned int i = 0;
+
+ while (i < p_stackx_port_zone->port_num)
+ {
+ if (!strncasecmp (p->linux_ip.if_name, name, strlen (name)))
+ {
+ return p;
+ }
+
+ p = &p_stackx_port_zone->stackx_one_port[++i];
+ }
+
+ return NULL;
+}
+
+NSTACK_STATIC int
+del_port_in_port_list (const char *name)
+{
+ struct stackx_port_info *inf = head_used_port_list;
+ struct stackx_port_info *prev = NULL;
+
+ while (inf)
+ {
+ if (!strncasecmp (inf->linux_ip.if_name, name, strlen (name)))
+ {
+ if (prev != NULL)
+ {
+ prev->next_use_port = inf->next_use_port;
+ }
+ else
+ {
+ head_used_port_list = inf->next_use_port;
+ }
+
+ break;
+ }
+
+ prev = inf;
+ inf = inf->next_use_port;
+ }
+
+ return 0;
+}
+
+extern void create_netif (struct stackx_port_info *p_port_info);
+
+NSTACK_STATIC int
+add_port_in_port_list (struct stackx_port_info *p)
+{
+ char *name;
+ struct stackx_port_info *inf = head_used_port_list;
+ struct stackx_port_info *prev = NULL;
+
+ name = p->linux_ip.if_name;
+
+ while (inf)
+ {
+ if (!strncasecmp (inf->linux_ip.if_name, name, strlen (name)))
+ {
+ NSPOL_LOGERR ("ERROR: add an existing port!");
+ return -1;
+ }
+
+ prev = inf;
+ inf = inf->next_use_port;
+ }
+
+ if (prev == NULL)
+ {
+ head_used_port_list = p;
+ }
+ else
+ {
+ prev->next_use_port = p;
+ }
+
+ p->next_use_port = NULL;
+ create_netif (p);
+ return 0;
+}
+
+/* Queries the link status of a port and prints it to screen */
+NSTACK_STATIC void
+report_port_link_status (struct stackx_port_info *p)
+{
+ /* get link status */
+ u32 status;
+
+ status = hal_link_status (p->linux_ip.hdl);
+
+ if (status)
+ {
+ NSPOL_LOGINF (SC_DPDK_INFO, "Port=%s: Link Up", p->linux_ip.if_name);
+ }
+ else
+ {
+ NSPOL_LOGINF (SC_DPDK_INFO, "Port=%s: Link Down", p->linux_ip.if_name);
+ }
+}
+
+int
+spl_hal_ether_etoa (const unsigned char *e, int e_len, char *a, int a_len)
+{
+ char *c = a;
+ int i;
+ int retVal;
+
+ if (!e || !a || e_len < 0)
+ return -1;
+
+ if (e_len > NETIF_ETH_ADDR_LEN)
+ e_len = NETIF_ETH_ADDR_LEN;
+
+ if (a_len < e_len * 3)
+ return -1;
+
+ for (i = 0; i < e_len; i++)
+ {
+ if (i)
+ {
+ *c++ = ':';
+ }
+ retVal = SPRINTF_S (c, a_len - (c - a), "%02x", e[i] & 0xff);
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("SPRINTF_S failed]ret=%d.", retVal);
+ return -1;
+ }
+ c = c + retVal;
+ }
+
+ return 0;
+}
+
+NSTACK_STATIC inline void
+spl_hal_buf_convert (struct common_mem_mbuf *mbuf, struct spl_pbuf **buf)
+{
+ struct common_mem_mbuf *before = NULL;
+ struct spl_pbuf *last = NULL;
+ struct spl_pbuf *first = NULL;
+ struct spl_pbuf *tmp = NULL;
+
+ while (mbuf != NULL)
+ {
+ //dpdk 2.1
+ tmp =
+ (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf));
+ res_alloc (&tmp->res_chk);
+ tmp->payload = common_pktmbuf_mtod (mbuf, void *);
+ tmp->tot_len = mbuf->pkt_len;
+ tmp->len = mbuf->data_len;
+ tmp->type = SPL_PBUF_HUGE;
+ tmp->proto_type = SPL_PBUF_PROTO_NONE;
+ tmp->next = NULL;
+ tmp->flags = 0;
+
+ if (first == NULL)
+ {
+ first = tmp;
+ last = first;
+ }
+ else
+ {
+ /* Always the "if(first == NULL)" code segment is executed and then
+ "else" segment code is executed, so the "last" variable is not
+ NULL always when "else" case is executed */
+ last->next = tmp;
+ last = tmp;
+ }
+
+ before = mbuf;
+ mbuf = mbuf->next;
+
+ before->next = NULL;
+ }
+
+ *buf = first;
+}
+
+NSTACK_STATIC int
+spl_hal_port_zone_init ()
+{
+ int retVal;
+ nsfw_mem_zone create_port_zone;
+ nsfw_mem_zone create_port_info;
+ struct stackx_port_info *mz_port_info;
+ INITPOL_LOGINF ("RTP", "spl_hal_port_zone_init", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_START);
+
+ if ((CUR_CFG_HAL_PORT_NUM < 1)
+ || (SIZE_MAX / sizeof (struct stackx_port_info) < CUR_CFG_HAL_PORT_NUM))
+ {
+ NSPOL_LOGERR ("malloc parameter incorrect]max_linux_port=%u",
+ CUR_CFG_HAL_PORT_NUM);
+ return -1;
+ }
+
+ if (spl_snprintf
+ (create_port_zone.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ MP_STACKX_PORT_ZONE) < 0)
+ {
+ NSPOL_LOGERR ("spl_snprintf fail");
+
+ return -1;
+ }
+
+ create_port_zone.stname.entype = NSFW_SHMEM;
+ create_port_zone.isocket_id = SOCKET_ID_ANY;
+ create_port_zone.length = sizeof (struct stackx_port_zone);
+ create_port_zone.ireserv = 0;
+ p_stackx_port_zone =
+ (struct stackx_port_zone *) nsfw_mem_zone_create (&create_port_zone);
+
+ if (NULL == p_stackx_port_zone)
+ {
+ INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init",
+ "Cannot create memory zone for MP_STACKX_PORT_ZONE information",
+ LOG_INVALID_VALUE, MODULE_INIT_FAIL);
+ common_exit (EXIT_FAILURE,
+ "Cannot create memory zone for MP_STACKX_PORT_ZONE information");
+ }
+
+ retVal =
+ MEMSET_S (p_stackx_port_zone, sizeof (struct stackx_port_zone), 0,
+ sizeof (struct stackx_port_zone));
+
+ if (EOK != retVal)
+ {
+ INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init", "MEMSET_S return fail",
+ retVal, MODULE_INIT_FAIL);
+ nsfw_mem_zone_release (&create_port_zone.stname);
+ return -1;
+ }
+
+ if (spl_snprintf
+ (create_port_info.stname.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ MP_STACKX_PORT_INFO) < 0)
+ {
+ NSPOL_LOGERR ("VSNPRINTF_S fail");
+ return -1;
+ }
+
+ create_port_info.stname.entype = NSFW_SHMEM;
+ create_port_info.isocket_id = SOCKET_ID_ANY;
+ create_port_info.length =
+ CUR_CFG_HAL_PORT_NUM * sizeof (struct stackx_port_info);
+ create_port_info.ireserv = 0;
+ mz_port_info =
+ (struct stackx_port_info *) nsfw_mem_zone_create (&create_port_info);
+
+ if (NULL == mz_port_info)
+ {
+ INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init",
+ "Cannot create memory zone for MP_STACKX_PORT_INFO information",
+ LOG_INVALID_VALUE, MODULE_INIT_FAIL);
+ common_exit (EXIT_FAILURE,
+ "Cannot create memory zone for MP_STACKX_PORT_INFO information");
+ }
+
+ retVal =
+ MEMSET_S (mz_port_info, create_port_info.length, 0,
+ create_port_info.length);
+
+ if (EOK != retVal)
+ {
+ INITPOL_LOGERR ("RTP", "spl_hal_port_zone_init", "MEMSET_S return fail",
+ retVal, MODULE_INIT_FAIL);
+ nsfw_mem_zone_release (&create_port_info.stname);
+ nsfw_mem_zone_release (&create_port_zone.stname);
+ return -1;
+ }
+
+ MEM_STAT (SPL_HAL_MODULE, create_port_zone.stname.aname, NSFW_SHMEM,
+ create_port_info.length);
+
+ p_stackx_port_zone->stackx_one_port = mz_port_info;
+
+ INITPOL_LOGINF ("RTP", "spl_hal_port_zone_init", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_SUCCESS);
+
+ return 0;
+}
+
+int
+spl_hal_init (int argc, char *argv[])
+{
+ int retval = -1;
+ int idx_init;
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "spl_hal_init start");
+
+ /* Get nstack args */
+ smp_parse_stack_args (argc, argv);
+
+ if (0 == uStackArgIndex)
+ {
+ NSPOL_LOGERR ("uStackArgIndex is 0, can lead to long loop]");
+ return retval;
+ }
+
+ /* Init DPDK */
+ argc = uStackArgIndex--;
+ INITPOL_LOGINF ("RTP", "hal_init_global", NULL_STRING, LOG_INVALID_VALUE,
+ MODULE_INIT_START);
+
+ for (idx_init = 0; idx_init < argc; idx_init++)
+ {
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "hal_init_global]idx_init=%d,argv[idx_init]=%s", idx_init,
+ argv[idx_init]);
+ }
+
+ retval = hal_init_global (argc, argv);
+
+ if (0 != retval)
+ {
+ NSPOL_LOGERR ("call hal_init_global fail]retval = %d", retval);
+ return -1;
+ }
+
+ retval = hal_init_local ();
+
+ if (0 != retval)
+ {
+ NSPOL_LOGERR ("call hal_init_local fail]retval = %d", retval);
+ return -1;
+ }
+
+ retval = spl_hal_port_zone_init ();
+ if (0 != retval)
+ {
+ NSPOL_LOGERR ("call hal_init_local fail]retval = %d", retval);
+ return -1;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "Finished Process Init");
+
+ return 0;
+
+}
+
+static inline int
+spl_hal_rx_mbuf_free (void *data, void *arg)
+{
+ struct spl_pbuf *tmp = NULL;
+ struct common_mem_mbuf *mbuf = (struct common_mem_mbuf *) data;
+ (void) arg;
+
+ tmp = (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf));
+ if (tmp->res_chk.alloc_flag == TRUE)
+ return 1;
+
+ if (common_mbuf_refcnt_read (mbuf) == 0)
+ return 1;
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "rx_pool init in fault case: free mbuf=%p",
+ mbuf);
+ spl_mbuf_free (mbuf);
+ return 0;
+}
+
+struct common_mem_mempool *
+spl_hal_rx_pool_create (int nic_id, int queue_id, int start_type)
+{
+ int retval;
+ struct common_mem_mempool *mp;
+ nsfw_mem_mbfpool create_mbuf_pool;
+ nsfw_mem_name lookup_mbuf_pool;
+ struct common_mem_ring *ring;
+
+ if (start_type == 1)
+ {
+ create_mbuf_pool.stname.entype = NSFW_SHMEM;
+ create_mbuf_pool.uscash_size = 0;
+ create_mbuf_pool.uspriv_size = 0;
+ create_mbuf_pool.isocket_id = SOCKET_ID_ANY;
+ create_mbuf_pool.enmptype = NSFW_MRING_SPSC;
+
+ retval =
+ spl_snprintf (create_mbuf_pool.stname.aname, NSFW_MEM_NAME_LENGTH - 1,
+ "%s", get_mempoll_rx_name (queue_id, nic_id));
+
+ if (-1 == retval)
+ {
+ NSPOL_LOGERR ("spl_snprintf fail");
+ return NULL;
+ }
+
+ create_mbuf_pool.usnum = RX_MBUF_POOL_SIZE - 1;
+ /*performance, rx buf cap is special, ((size - HEADROOM) >> 10) <<10, see ixgbe_dev_rx_init;
+ if want cap size == TX_MBUF_MAX_LEN, must let data_root=TX_MBUF_MAX_LEN+COMMON_PKTMBUF_HEADROOM and
+ TX_MBUF_MAX_LEN must N*1024;
+ */
+ create_mbuf_pool.usdata_room =
+ TX_MBUF_MAX_LEN + COMMON_PKTMBUF_HEADROOM;
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "hal_rx_pool.usnum=%u, usdata_room=%u",
+ create_mbuf_pool.usnum, create_mbuf_pool.usdata_room);
+
+ mp =
+ (struct common_mem_mempool *)
+ nsfw_mem_mbfmp_create (&create_mbuf_pool);
+
+ if (mp == NULL)
+ {
+ NSPOL_LOGERR ("nsfw_mem_mbfmp_create fail");
+ return NULL;
+ }
+
+ MEM_STAT (SPL_HAL_MODULE, create_mbuf_pool.stname.aname, NSFW_SHMEM,
+ nsfw_mem_get_len (mp, NSFW_MEM_MBUF));
+ NSPOL_LOGDBG (SC_DPDK_INFO, "create:thread=%d,nic_id=%d,mp=%p,size=%d",
+ queue_id, nic_id, mp, nsfw_mem_get_len (mp,
+ NSFW_MEM_MBUF));
+
+ char rx_msg_arr_name[NSFW_MEM_NAME_LENGTH];
+ data_com_msg *rx_msg_array = NULL;
+ retval = spl_snprintf (rx_msg_arr_name, NSFW_MEM_NAME_LENGTH, "%s",
+ get_mempoll_rxmsg_name (queue_id, nic_id));
+
+ if (-1 != retval)
+ {
+ rx_msg_array = (data_com_msg *) sbr_create_mzone (rx_msg_arr_name,
+ (size_t)
+ sizeof
+ (data_com_msg) *
+ RX_MBUF_POOL_SIZE);
+ }
+
+ if (!rx_msg_array)
+ {
+ NSSBR_LOGERR
+ ("Create rx_msg_array zone fail]name=%s, num=%u, size=%zu",
+ rx_msg_arr_name, RX_MBUF_POOL_SIZE,
+ (size_t) sizeof (data_com_msg) * RX_MBUF_POOL_SIZE);
+ }
+ else
+ {
+ /*bind msg to pbuf */
+ MEM_STAT (SPL_HAL_MODULE, rx_msg_arr_name, NSFW_SHMEM,
+ (size_t) sizeof (data_com_msg) * RX_MBUF_POOL_SIZE);
+ NSSBR_LOGINF
+ ("Create rx_msg_array zone ok]name=%s, ptr=%p, num=%u, size=%zu",
+ rx_msg_arr_name, rx_msg_array, RX_MBUF_POOL_SIZE,
+ sizeof (data_com_msg) * RX_MBUF_POOL_SIZE);
+
+ struct common_mem_mbuf *mbuf = NULL;
+ struct spl_pbuf *buf = NULL;
+ u32 loop = 0;
+
+ for (; loop < RX_MBUF_POOL_SIZE; loop++)
+ {
+ mbuf = nsfw_mem_mbf_alloc (mp, NSFW_SHMEM);
+
+ if (!mbuf)
+ {
+ /* alloc failed , still can work, no prebind success just not so faster */
+ NSSBR_LOGERR
+ ("nsfw_mem_mbf_alloc failed,this can not happen");
+ break;
+ }
+
+ buf =
+ (struct spl_pbuf *) ((char *) mbuf +
+ sizeof (struct common_mem_mbuf));
+ sys_sem_init (&rx_msg_array[loop].param.op_completed);
+ rx_msg_array[loop].param.msg_from = NULL;
+ buf->msg = (void *) &rx_msg_array[loop];
+ (void) res_free (&buf->res_chk); //no need to check return value, as it will do free operation depends on alloc_flag
+
+ if (nsfw_mem_mbf_free (mbuf, NSFW_SHMEM) < 0)
+ {
+ /* free failed , still can work, no prebind work just not so faster */
+ NSSBR_LOGERR
+ ("nsfw_mem_mbf_free failed,this can not happen");
+ break;
+ }
+ }
+
+ }
+
+ }
+ else
+ {
+ retval =
+ spl_snprintf (lookup_mbuf_pool.aname, NSFW_MEM_NAME_LENGTH - 1, "%s",
+ get_mempoll_rx_name (queue_id, nic_id));
+
+ if (-1 == retval)
+ {
+ NSPOL_LOGERR ("spl_snprintf fail");
+ return NULL;
+ }
+
+ lookup_mbuf_pool.entype = NSFW_SHMEM;
+ lookup_mbuf_pool.enowner = NSFW_PROC_MAIN;
+ mp =
+ (struct common_mem_mempool *)
+ nsfw_mem_mbfmp_lookup (&lookup_mbuf_pool);
+
+ if (mp == NULL)
+ {
+ NSPOL_LOGERR ("nsfw_mem_mbfmp_lookup fail, name=%s, try to create",
+ lookup_mbuf_pool.aname);
+ return spl_hal_rx_pool_create (nic_id, queue_id, 1);
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "lookup:thread=%d,nic_id=%d,mp=%p,size=%d",
+ queue_id, nic_id, mp, nsfw_mem_get_len (mp,
+ NSFW_MEM_MBUF));
+
+ /*We have to recycle RX mbufs hold by DPDK when fault recovering of upgrading nstack */
+ if (start_type == 3 || start_type == 2)
+ {
+ ring = (struct common_mem_ring *) (mp->pool_data);
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "BEFORE clear rx_mpool]prod.head=%u, prod.tail=%u, "
+ "cons.head=%u, cons.tail=%u", ring->prod.head,
+ ring->prod.tail, ring->cons.head, ring->cons.tail);
+
+ if (nsfw_mem_mbuf_iterator (mp, 0, mp->size,
+ spl_hal_rx_mbuf_free, NULL) < 0)
+ {
+ NSPOL_LOGERR ("nsfw_mem_mbuf_iterator return fail");
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "AFTER clear rx_mpool]prod.head=%u, prod.tail=%u, "
+ "cons.head=%u, cons.tail=%u", ring->prod.head,
+ ring->prod.tail, ring->cons.head, ring->cons.tail);
+ }
+
+ }
+
+ return mp;
+
+}
+
+int
+spl_hal_bond_config (struct network_configuration *network)
+{
+ struct phy_net *phynet = network->phy_net;
+ struct ref_nic *phead = phynet->header;
+ static u8_t bond_index = 0; /* for auto-generating bond_name */
+ unsigned int check_bond = 0, check_name;
+ int retVal;
+ u8_t j, k, idx = 0;
+
+ /* get bond info from network configuration */
+ if (phynet->bond_mode != -1 && bond_ports_array.cnt < MAX_BOND_PORT_NUM)
+ {
+ struct ref_nic *phead_bond = phead;
+ char *name = phynet->bond_name;
+ struct bond_set *s = &bond_ports_array.ports[bond_ports_array.cnt];
+
+ while (phead_bond != NULL)
+ {
+ /* check slave name, repeated slave nic cannot be added to bond set. */
+ check_name = 0;
+
+ for (j = 0; j < idx; j++)
+ {
+ if (strcmp (s->slave_ports[j], phead_bond->nic_name) == 0)
+ {
+ check_name = 1;
+ break;
+ }
+ }
+
+ if (check_name)
+ {
+ break;
+ }
+
+ /* if this nic has been added to a bond_set, ignore it */
+ check_bond = 0;
+
+ for (k = 0; k < bond_ports_array.cnt && !check_bond; k++)
+ {
+ for (j = 0;
+ j < bond_ports_array.ports[k].slave_port_cnt
+ && !check_bond; j++)
+ {
+ if (strcmp
+ (bond_ports_array.ports[k].slave_ports[j],
+ phead_bond->nic_name) == 0)
+ {
+ check_bond = 1;
+
+ if (name[0] == 0)
+ {
+ retVal =
+ STRNCPY_S (name, IP_MODULE_MAX_NAME_LEN,
+ bond_ports_array.
+ ports[k].bond_port_name,
+ strlen (bond_ports_array.
+ ports[k].bond_port_name));
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRNCPY_S failed]ret=%d.",
+ retVal);
+ return -1;
+ }
+ }
+
+ if (strcmp
+ (name,
+ bond_ports_array.ports[k].bond_port_name) != 0)
+ {
+ NSOPR_SET_ERRINFO (-1, "%s init failed!\n", name);
+ NSPOL_LOGERR
+ ("%s init failed! %s in both %s and %s", name,
+ phead_bond->nic_name, name,
+ bond_ports_array.ports[k].bond_port_name);
+ return -1;
+ }
+ }
+ }
+ }
+
+ if (check_bond == 1)
+ {
+ break;
+ }
+
+ /* copy slave ports name to bond array */
+ retVal =
+ STRNCPY_S (s->slave_ports[idx], HAL_MAX_NIC_NAME_LEN,
+ phead_bond->nic_name, strlen (phead_bond->nic_name));
+
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRNCPY_S failed]ret=%d.", retVal);
+ return -1;
+ }
+
+ idx++;
+ phead_bond = phead_bond->next;
+
+ if (idx >= HAL_MAX_SLAVES_PER_BOND)
+ {
+ break;
+ }
+ }
+
+ if (check_bond == 0)
+ {
+ if (name[0] == 0)
+ {
+ /* if bond_name is a empty string, generate a new bond name */
+ retVal =
+ SPRINTF_S (name, HAL_MAX_NIC_NAME_LEN, "bond%u_auto",
+ bond_index++);
+
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("SPRINTF_S failed]ret=%d.", retVal);
+ return -1;
+ }
+ }
+
+ /* copy bond_name to bond array */
+ retVal =
+ STRNCPY_S (s->bond_port_name, HAL_MAX_NIC_NAME_LEN, name,
+ strlen (name));
+
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRNCPY_S failed]ret=%d.", retVal);
+ return -1;
+ }
+
+ s->slave_port_cnt = idx;
+ bond_ports_array.cnt++;
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "bond_ports_array.cnt=%u,slave_port_cnt=%u",
+ bond_ports_array.cnt, s->slave_port_cnt);
+ }
+ }
+
+ return 0;
+}
+
+int
+spl_hal_port_config (unsigned int *port_num)
+{
+ int retVal;
+ unsigned int check;
+ struct phy_net *phynet;
+
+ struct network_configuration *network = get_network_list ();
+
+ if (!network)
+ {
+ NSPOL_LOGERR ("fail to get_provider_node");
+ return -1;
+ }
+
+ unsigned int port_index = p_stackx_port_zone->port_num;
+
+ while (network && (phynet = network->phy_net))
+ {
+ struct ref_nic *phead = phynet->header;
+ NSPOL_LOGINF (SC_DPDK_INFO, "network=%p,network_name=%s", network,
+ network->network_name);
+
+ if (spl_hal_bond_config (network) < 0)
+ {
+ NSPOL_LOGERR ("spl_hal_bond_config fail.");
+ return -1;
+ }
+
+ while (phead != NULL)
+ {
+ /* check if the NIC is inited */
+ for (check = 0; check < port_index; ++check)
+ {
+ if (strcmp
+ (p_stackx_port_zone->stackx_one_port[check].
+ linux_ip.if_name, phead->nic_name) == 0)
+ {
+ break;
+ }
+ }
+
+ if (check != port_index)
+ {
+ phead = phead->next;
+ continue;
+ }
+
+ /* check if the number of VF exceeds MAX_VF_NUM */
+ if (port_index >= MAX_VF_NUM + p_stackx_port_zone->bonded_port_num)
+ {
+ NSOPR_SET_ERRINFO (-1, "Support Only %d VF. %s init failed!\n",
+ MAX_VF_NUM, phead->nic_name);
+ NSPOL_LOGERR ("Support Only %d VF. %s init failed!", MAX_VF_NUM,
+ phead->nic_name);
+ NSOPR_SET_ERRINFO (-1, "Add network %s failed!\n",
+ network->network_name);
+ break;
+ }
+
+ if (strlen (phead->nic_name) >=
+ sizeof (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.if_name) - 1
+ || strlen (phead->nic_name) <= 3)
+ {
+ NSPOL_LOGERR ("Invalid configuration");
+ return -1;
+ }
+
+ retVal =
+ STRCPY_S (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.if_name,
+ sizeof (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.if_name),
+ phead->nic_name);
+
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ return -1;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "if_name %s",
+ p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.if_name);
+ retVal =
+ STRCPY_S (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.ip_addr_linux,
+ sizeof (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.
+ ip_addr_linux), "0.0.0.0");
+
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ return -1;
+ }
+
+ retVal =
+ STRCPY_S (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.mask_linux,
+ sizeof (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.
+ mask_linux), "0.0.0.0");
+
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ return -1;
+ }
+
+ retVal =
+ STRCPY_S (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.bcast_linux,
+ sizeof (p_stackx_port_zone->
+ stackx_one_port[port_index].linux_ip.
+ bcast_linux), "0.0.0.0");
+
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d.", retVal);
+ return -1;
+ }
+
+ ++port_index;
+ NSPOL_LOGINF (SC_DPDK_INFO, "port_index=%u", port_index);
+
+ if (CUR_CFG_HAL_PORT_NUM <= port_index + bond_ports_array.cnt)
+ {
+ // TODO: Invalid configuration received, return immediately
+ NSPOL_LOGERR
+ ("Insufficient nStack configuration when compared to configuration from network.json");
+ return -1;
+ }
+
+ /* [TA33636] [2017-04-11] Do not need provider.json */
+ if (phynet->bond_mode ==
+ -1 /*&& strncmp(network->network_name, "provider", 8) != 0 */ )
+ {
+ break;
+ }
+ else
+ {
+ phead = phead->next;
+ }
+ }
+
+ network = network->next;
+ }
+
+ *port_num = port_index;
+
+ return ERR_OK;
+}
+
+void
+spl_hal_capa_init ()
+{
+ u32_t ipv4_cksum_offload = 1;
+ u32_t udp_cksum_offload = 1;
+ u32_t tcp_cksum_offload = 1;
+ hal_netif_capa_t info = { 0 };
+ struct stackx_port_info *p_port_info = head_used_port_list;
+
+ while (p_port_info)
+ {
+ hal_get_capability (p_port_info->linux_ip.hdl, &info);
+
+ if ((info.tx_offload_capa & HAL_ETH_TX_OFFLOAD_IPV4_CKSUM) == 0)
+ {
+ ipv4_cksum_offload = 0;
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "Port %s TX_OFFLOAD_IPV4_CKSUM Disable",
+ p_port_info->linux_ip.if_name);
+ }
+
+ if ((info.tx_offload_capa & HAL_ETH_TX_OFFLOAD_UDP_CKSUM) == 0)
+ {
+ udp_cksum_offload = 0;
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "Port %s TX_OFFLOAD_UDP_CKSUM Disable",
+ p_port_info->linux_ip.if_name);
+ }
+
+ if ((info.tx_offload_capa & HAL_ETH_TX_OFFLOAD_TCP_CKSUM) == 0)
+ {
+ tcp_cksum_offload = 0;
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "Port %s TX_OFFLOAD_TCP_CKSUM Disable",
+ p_port_info->linux_ip.if_name);
+ }
+
+ p_port_info = p_port_info->next_use_port;
+ }
+
+ spl_hal_capa.tx_ipv4_cksum_offload = ipv4_cksum_offload;
+ spl_hal_capa.tx_udp_cksum_offload = udp_cksum_offload;
+ spl_hal_capa.tx_tcp_cksum_offload = tcp_cksum_offload;
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "ipv4_cksum_offload(%u),udp_cksum_offload(%u),tcp_cksum_offload(%u)",
+ ipv4_cksum_offload, udp_cksum_offload, tcp_cksum_offload);
+
+}
+
+NSTACK_STATIC void
+spl_hal_bond_info_init (hal_hdl_t hdl, struct bond_set *s,
+ struct stackx_port_info *p)
+{
+#define MAX_MAC_STR_LEN 20
+ char mac_string[MAX_MAC_STR_LEN];
+ int retVal;
+ struct ether_addr addr;
+
+ p->linux_ip.hdl = hdl;
+
+ struct stackx_port_info *slave_port;
+ slave_port = get_port_info_by_name (s->slave_ports[0]);
+
+ if (slave_port == NULL)
+ {
+ NSPOL_LOGERR ("get_port_info_by_name failed]bond_port_name=%s",
+ s->bond_port_name);
+ return;
+ }
+
+ /* check the lenght of bond_port_name */
+ retVal =
+ STRCPY_S (p->linux_ip.if_name, sizeof (p->linux_ip.if_name),
+ s->bond_port_name);
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal);
+ return;
+ }
+
+ hal_get_macaddr (hdl, &addr);
+ retVal =
+ spl_hal_ether_etoa (addr.addr_bytes, sizeof (addr.addr_bytes), mac_string,
+ sizeof (mac_string));
+ if (retVal < 0)
+ {
+ NSPOL_LOGERR ("spl_hal_ether_etoa failed]ret=%d", retVal);
+ return;
+ }
+
+ retVal =
+ STRCPY_S (p->linux_ip.mac_addr, sizeof (p->linux_ip.mac_addr),
+ mac_string);
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal);
+ return;
+ }
+
+ retVal =
+ STRCPY_S (p->linux_ip.ip_addr_linux, sizeof (p->linux_ip.ip_addr_linux),
+ slave_port->linux_ip.ip_addr_linux);
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal);
+ return;
+ }
+
+ retVal =
+ STRCPY_S (p->linux_ip.mask_linux, sizeof (p->linux_ip.mask_linux),
+ slave_port->linux_ip.mask_linux);
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal);
+ return;
+ }
+
+ retVal =
+ STRCPY_S (p->linux_ip.bcast_linux, sizeof (p->linux_ip.bcast_linux),
+ slave_port->linux_ip.bcast_linux);
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal);
+ return;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "===== the bond port info ======");
+ NSPOL_LOGINF (SC_DPDK_INFO, "bond port name=%s", p->linux_ip.if_name);
+ NSPOL_LOGINF (SC_DPDK_INFO, "bond port mac=%s", p->linux_ip.mac_addr);
+ NSPOL_LOGINF (SC_DPDK_INFO, "bond port ip=%s", p->linux_ip.ip_addr_linux);
+ NSPOL_LOGINF (SC_DPDK_INFO, "bond port netmask=%s", p->linux_ip.mask_linux);
+ NSPOL_LOGINF (SC_DPDK_INFO, "bond port broad_cast addr=%s",
+ p->linux_ip.bcast_linux);
+
+}
+
+NSTACK_STATIC int
+spl_hal_bond_start (void)
+{
+ u8_t i, j = 0;
+ struct stackx_port_info *bond_port = NULL;
+ hal_hdl_t hdl;
+ hal_hdl_t slave_hdl[HAL_MAX_SLAVES_PER_BOND];
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "bond_ports_array.cnt=%u",
+ bond_ports_array.cnt);
+
+ for (i = bond_ports_array_cnt_start; i < bond_ports_array.cnt; i++)
+ {
+ struct bond_set *s = &bond_ports_array.ports[i];
+ NSPOL_LOGINF (SC_DPDK_INFO, "i=%u,bond_port_name=%s", i,
+ s->bond_port_name);
+
+ u8_t slave_num = 0;
+ for (j = 0; j < s->slave_port_cnt; j++)
+ {
+ NSPOL_LOGINF (SC_DPDK_INFO, "s->slave_ports[%u]=%s", j,
+ s->slave_ports[j]);
+ hdl = get_port_hdl_by_name (s->slave_ports[j]);
+
+ if (!hal_is_valid (hdl))
+ {
+ continue;
+ }
+
+ slave_hdl[slave_num++] = hdl;
+
+ /* here we didn't release the port mem allocated in p_stackx_port_zone */
+ del_port_in_port_list (s->slave_ports[j]);
+ }
+
+ hdl = hal_bond (s->bond_port_name, slave_num, slave_hdl);
+
+ if (!hal_is_valid (hdl))
+ {
+ NSPOL_LOGERR ("hal_bond fail: bond_name =%s", s->bond_port_name);
+ return -1;
+ }
+
+ bond_port =
+ &p_stackx_port_zone->stackx_one_port[p_stackx_port_zone->port_num];
+ num_ports_NIC++;
+ p_stackx_port_zone->port_num++;
+ p_stackx_port_zone->bonded_port_num++;
+
+ spl_hal_bond_info_init (hdl, s, bond_port);
+ add_port_in_port_list (bond_port);
+
+ }
+
+ bond_ports_array_cnt_start = bond_ports_array.cnt;
+ return 0;
+}
+
+/*
+ * Initialises a given port using global settings and with the rx buffers
+ * coming from the mbuf_pool passed as parameter
+ */
+
+NSTACK_STATIC inline int
+spl_hal_port_start (uint16_t nic_id, struct stackx_port_info *p_port_info,
+ u16_t num_queues)
+{
+ u16_t num_queues_request, q;
+ hal_hdl_t hdl;
+ struct common_mem_mempool *mp;
+ hal_netif_config_t conf;
+#define MAX_MAC_STR_LEN 20
+ char mac_string[MAX_MAC_STR_LEN];
+ int retVal;
+ struct ether_addr addr;
+
+ // change the queues number per configuration.
+ // even we only receive packets from one rx queue when dispatch mode is on, the tx queue
+ // shoule set to the queues number requested.
+ num_queues_request = num_queues;
+ if (num_queues_request > HAL_ETH_MAX_QUEUE_NUM)
+ {
+ NSPOL_LOGERR
+ ("no enougth queue num for thread!]num_queues_request=%u,MAX_QUEUE_NUM=%u",
+ num_queues_request, HAL_ETH_MAX_QUEUE_NUM);
+ return -1;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "# Initialising index=%s... ",
+ p_port_info->linux_ip.if_name);
+ /* used to have fflush,no use code ,remove it. */
+
+ conf.bit.hw_vlan_filter = 1;
+ conf.bit.hw_vlan_strip = 1;
+
+ conf.rx.queue_num = num_queues_request;
+ conf.tx.queue_num = num_queues_request;
+
+ for (q = 0; q < num_queues_request; q++)
+ {
+ mp =
+ (struct common_mem_mempool *) spl_hal_rx_pool_create (nic_id, q, 1);
+
+ if (mp == NULL)
+ {
+ NSPOL_LOGERR
+ ("spl_hal_rx_pool_create fail]mp=NULL,nic_id=%u,if_name=%s",
+ nic_id, p_port_info->linux_ip.if_name);
+ return -1;
+ }
+
+ (void) spl_reg_res_txrx_mgr ((mpool_handle *) mp); // will only return 0, no need to check return value
+ conf.rx.ring_pool[q] = mp;
+ conf.rx.ring_size[q] = HAL_RX_RING_SIZE;
+ conf.tx.ring_size[q] = HAL_TX_RING_SIZE;
+ }
+
+ hdl = hal_create (p_port_info->linux_ip.if_name, &conf);
+
+ if (!hal_is_valid (hdl))
+ {
+ NSPOL_LOGERR ("hal_create fail]if_name =%s",
+ p_port_info->linux_ip.if_name);
+ return -1;
+ }
+
+ p_port_info->linux_ip.hdl = hdl;
+
+ /* add mac address */
+ hal_get_macaddr (hdl, &addr);
+ retVal =
+ spl_hal_ether_etoa (addr.addr_bytes, sizeof (addr.addr_bytes), mac_string,
+ sizeof (mac_string));
+ if (retVal < 0)
+ {
+ NSPOL_LOGERR ("spl_hal_ether_etoa failed]ret=%d", retVal);
+ return -1;
+ }
+
+ retVal =
+ STRCPY_S (p_port_info->linux_ip.mac_addr,
+ sizeof (p_port_info->linux_ip.mac_addr), mac_string);
+ if (EOK != retVal)
+ {
+ NSPOL_LOGERR ("STRCPY_S failed]ret=%d", retVal);
+ return -1;
+ }
+
+ return 0;
+}
+
+NSTACK_STATIC int
+spl_hal_port_setup ()
+{
+ unsigned int i;
+ struct stackx_port_info *p_port_info = NULL;
+
+ INITPOL_LOGINF ("RTP", "spl_hal_port_setup", NULL_STRING, LOG_INVALID_VALUE,
+ MODULE_INIT_START);
+
+ for (i = num_ports_NIC_start; i < num_ports_NIC; i++)
+ {
+ p_port_info = &(p_stackx_port_zone->stackx_one_port[i]);
+
+ if (spl_hal_port_start (i, p_port_info, (u16_t) 1) < 0)
+ {
+ NSPOL_LOGERR ("Error initialising]nic_id=%u", i);
+
+ INITPOL_LOGERR ("RTP", "spl_hal_port_setup", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_FAIL);
+
+ return -1;
+ }
+ else
+ {
+ report_port_link_status (p_port_info);
+ add_port_in_port_list (p_port_info);
+ }
+ }
+
+ if (spl_hal_bond_start () < 0)
+ {
+ NSPOL_LOGERR ("bond port init failed!");
+
+ INITPOL_LOGERR ("RTP", "spl_hal_port_setup", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_FAIL);
+
+ return -1;
+ }
+
+ spl_hal_capa_init ();
+
+ INITPOL_LOGINF ("RTP", "spl_hal_port_setup", NULL_STRING, LOG_INVALID_VALUE,
+ MODULE_INIT_SUCCESS);
+
+ return 0;
+
+}
+
+int
+spl_hal_port_init ()
+{
+ int retval;
+ unsigned int i, port_num = 0;
+
+ int port_num_start = p_stackx_port_zone->port_num;
+ num_ports_NIC_start = num_ports_NIC;
+
+ //Read network info
+ INITPOL_LOGINF ("IP", "spl_hal_port_config", NULL_STRING, LOG_INVALID_VALUE,
+ MODULE_INIT_START);
+ retval = spl_hal_port_config (&port_num);
+
+ if (retval != ERR_OK)
+ {
+ INITPOL_LOGERR ("IP", "spl_hal_port_config", NULL_STRING,
+ LOG_INVALID_VALUE, MODULE_INIT_FAIL);
+ return -1;
+ }
+
+ p_stackx_port_zone->port_num = port_num;
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "port_num=%u", port_num);
+ INITPOL_LOGINF ("IP", "spl_hal_port_config", NULL_STRING, LOG_INVALID_VALUE,
+ MODULE_INIT_SUCCESS);
+
+ if (port_num_start == p_stackx_port_zone->port_num)
+ {
+ NSPOL_LOGERR ("No new NIC find.");
+ return 0;
+ }
+
+ //Get ports num
+ for (i = port_num_start; i < p_stackx_port_zone->port_num; i++)
+ {
+ if (p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name[0] != 0)
+ {
+ /* right now hard coded, */
+ int eth_num =
+ atoi (p_stackx_port_zone->stackx_one_port[i].linux_ip.if_name +
+ 3);
+
+ num_ports_NIC++;
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "port_mask=%d ,eth_name=%s", eth_num,
+ p_stackx_port_zone->stackx_one_port[i].
+ linux_ip.if_name);
+ }
+ }
+
+ if (num_ports_NIC > HAL_MAX_NIC_NUM)
+ {
+ NSPOL_LOGERR ("just support one eth");
+ common_exit (EXIT_FAILURE, "just surport one eth");
+ }
+
+ if (num_ports_NIC == num_ports_NIC_start)
+ {
+ NSPOL_LOGERR ("No new NIC find.");
+ return 0;
+ }
+
+ retval = spl_hal_port_setup ();
+
+ if (retval == -1)
+ {
+ return -1;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "Finished Process Init.");
+
+ return 1;
+}
+
+inline NSTACK_STATIC void
+spl_hal_send (struct netif *pnetif)
+{
+ u16_t i, sent = 0;
+ struct netifExt *pnetifExt = NULL;
+ u16_t netif_id = pnetif->num;
+ u16_t tx_num = spl_hal_pkts[netif_id].tx.num;
+ struct common_mem_mbuf **tx_ptks = spl_hal_pkts[netif_id].tx.pkts;
+
+ for (i = 0; i < tx_num; i++)
+ {
+ (void)
+ res_free (&
+ (((struct spl_pbuf *) (((char *) tx_ptks[i]) +
+ sizeof (struct
+ common_mem_mbuf)))->res_chk));
+ }
+
+ int _retry = 0;
+
+ pnetifExt = getNetifExt (pnetif->num);
+ if (NULL == pnetifExt)
+ return;
+
+ do
+ {
+ sent +=
+ hal_send_packet (pnetifExt->hdl, 0, &(tx_ptks[sent]), tx_num - sent);
+ _retry++;
+
+ if (_retry > SPL_HAL_SEND_TRY)
+ {
+ NSPOL_LOGERR ("send loop %d times but dpdk send data fail ",
+ SPL_HAL_SEND_TRY);
+ break;
+ }
+ }
+ while (unlikely (sent != tx_num));
+
+ if (unlikely (sent != tx_num))
+ {
+ for (i = sent; i < tx_num; i++)
+ {
+ (void) nsfw_mem_mbf_free ((mbuf_handle) (tx_ptks[i]), NSFW_SHMEM);
+ }
+ }
+ for (i = 0; i < tx_num; i++)
+ {
+ /* set dpdk_send flag */
+ ((struct spl_pbuf *) (((char *) tx_ptks[i]) +
+ sizeof (struct common_mem_mbuf)))->
+ res_chk.u8Reserve |= DPDK_SEND_FLAG;
+ }
+
+ spl_hal_pkts[netif_id].tx.num = 0;
+
+}
+
+inline u16_t
+spl_hal_recv (struct netif *pnetif, u8_t id)
+{
+ u16_t netif_id, rx_c = 0;
+ struct netifExt *pnetifExt = NULL;
+
+ netif_id = pnetif->num;
+
+ pnetifExt = getNetifExt (pnetif->num);
+ if (NULL == pnetifExt)
+ return 0;
+
+ rx_c =
+ hal_recv_packet (pnetifExt->hdl, 0, spl_hal_pkts[netif_id].rx.pkts,
+ PKT_BURST);
+
+ if (rx_c <= 0)
+ {
+ return 0;
+ }
+
+ spl_hal_pkts[netif_id].rx.num = rx_c;
+ spl_hal_pkts[netif_id].rx.index = 0;
+
+ return rx_c;
+}
+
+/*needflush set 1 has pbuf release problem, ref maybe set 0 before release*/
+NSTACK_STATIC inline void
+spl_hal_set_cksum (struct spl_pbuf *buf, struct common_mem_mbuf *mbuf)
+{
+
+ //need to be careful, special when small packet oversize
+ if (buf->tot_len > mbuf->pkt_len)
+ {
+ NSPOL_LOGWAR (SC_DPDK_INFO,
+ "small packet OVERSIZE]pbuf_len=%u,mbuf_len=%u", buf->len,
+ mbuf->pkt_len);
+ mbuf->pkt_len = buf->len;
+ }
+
+ if (!spl_hal_tx_ip_cksum_enable () || !spl_hal_tx_tcp_cksum_enable ()
+ || !spl_hal_tx_udp_cksum_enable ())
+ {
+ struct tcp_hdr *t_hdr;
+ struct udp_hdr *u_hdr;
+ u16_t flag_offset;
+ u64_t ol_flags = (mbuf->ol_flags); //& (~PKT_TX_L4_MASK));
+
+ struct eth_hdr *ethhdr = (struct eth_hdr *) ((char *) buf->payload);
+
+ if (ethhdr->type == 8)
+ {
+ struct ip_hdr *iphdr =
+ (struct ip_hdr *) ((char *) buf->payload +
+ sizeof (struct eth_hdr));
+
+ if (!spl_hal_tx_ip_cksum_enable ())
+ {
+ ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM;
+ iphdr->_chksum = 0;
+ }
+
+ flag_offset = spl_ntohs (iphdr->_offset);
+
+ /*ip frag, only the first packet has udp or tcp head */
+ if (0 == (flag_offset & IP_OFFMASK))
+ {
+ switch (iphdr->_proto)
+ {
+ case IPPROTO_TCP:
+ if (!spl_hal_tx_tcp_cksum_enable ())
+ {
+ t_hdr =
+ (struct tcp_hdr *) ((char *) buf->payload +
+ sizeof (struct eth_hdr) +
+ sizeof (struct ip_hdr));
+ t_hdr->chksum = get_ipv4_psd_sum (iphdr, ol_flags);
+ ol_flags |= PKT_TX_TCP_CKSUM;
+ }
+
+ break;
+
+ case IPPROTO_UDP:
+ {
+ if ((mbuf->ol_flags & PKT_TX_UDP_CKSUM) ==
+ PKT_TX_UDP_CKSUM)
+ {
+ u_hdr = (struct udp_hdr *) ((char *) buf->payload + sizeof (struct eth_hdr) + sizeof (struct ip_hdr)); //l2_len + l3_len);
+ u_hdr->chksum =
+ get_ipv4_psd_sum (iphdr, mbuf->ol_flags);
+ }
+ }
+
+ break;
+
+ default:
+
+ break;
+ }
+ }
+ mbuf->l2_len = sizeof (struct eth_hdr); //l2_len;
+ mbuf->l3_len = sizeof (struct ip_hdr);
+ mbuf->ol_flags = ol_flags;
+ }
+ }
+}
+
+/*needflush set 1 has pbuf release problem, ref maybe set 0 before release*/
+err_t
+spl_hal_output (struct netif *pnetif, struct pbuf *buf)
+{
+ u16_t netif_id, idx;
+ struct common_mem_mbuf *mbuf;
+ struct spl_pbuf *spbuf = NULL;
+ //spl_pbuf_layer layer = SPL_PBUF_TRANSPORT;
+ //u16_t offset;
+
+ if (!p_def_stack_instance)
+ {
+ NSPOL_LOGERR ("p_def_stack_instance is NULL");
+ return -1;
+ }
+
+ u16_t proc_id = spl_get_lcore_id ();
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "spl_hal_output. len %d totlen %d", buf->len,
+ buf->tot_len);
+ print_pbuf_payload_info (buf, true);
+
+ if (buf->tot_len > DEF_MBUF_DATA_SIZE)
+ {
+ NSPOL_LOGINF (TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!");
+ return ERR_MEM;
+
+ }
+ spbuf = spl_pbuf_alloc_hugepage (SPL_PBUF_RAW,
+ buf->tot_len,
+ SPL_PBUF_HUGE, proc_id, NULL);
+
+ if (!spbuf)
+ {
+ NSPOL_LOGINF (TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!");
+ return ERR_MEM;
+ }
+
+ if (ERR_OK != pbuf_to_splpbuf_copy (spbuf, buf))
+ {
+ NSPOL_LOGERR ("pbuf to splpbuf copy failed");
+ return -1;
+ }
+
+ mbuf =
+ (struct common_mem_mbuf *) ((char *) spbuf -
+ sizeof (struct common_mem_mbuf));
+
+ if (spbuf->tot_len > mbuf->pkt_len)
+ {
+ NSPOL_LOGWAR (SC_DPDK_INFO,
+ "small packet OVERSIZE]pbuf_len=%u,mbuf_len=%u",
+ spbuf->len, mbuf->pkt_len);
+ mbuf->pkt_len = spbuf->len;
+ }
+
+ spl_hal_set_cksum (spbuf, mbuf);
+
+ netif_id = pnetif->num;
+ idx = spl_hal_pkts[netif_id].tx.num++;
+ spl_hal_pkts[netif_id].tx.pkts[idx] = mbuf;
+ spl_do_dump (spbuf, DUMP_SEND);
+ spl_hal_send (pnetif);
+
+ return 0;
+}
+
+void
+spl_hal_input (struct netif *pnetif, struct spl_pbuf **buf)
+{
+ u16_t netif_id;
+
+ struct common_mem_mbuf *mbuf;
+
+ netif_id = pnetif->num;
+
+ if (likely
+ (spl_hal_pkts[netif_id].rx.num > spl_hal_pkts[netif_id].rx.index))
+ {
+ mbuf = spl_hal_pkts[netif_id].rx.pkts[spl_hal_pkts[netif_id].rx.index];
+ spl_hal_pkts[netif_id].rx.index++;
+ spl_hal_buf_convert (mbuf, buf);
+ spl_do_dump (*buf, DUMP_RECV);
+ }
+ else
+ {
+ NSPOL_LOGERR
+ ("recv from spl_dev has a problem]pnetif=%p, num=%u, index=%u",
+ pnetif, spl_hal_pkts[netif_id].rx.num,
+ spl_hal_pkts[netif_id].rx.index);
+ *buf = NULL;
+ }
+ return;
+}
+
+int
+spl_hal_tx_ip_cksum_enable ()
+{
+ return !spl_hal_capa.tx_ipv4_cksum_offload;
+}
+
+int
+spl_hal_tx_udp_cksum_enable ()
+{
+ return !spl_hal_capa.tx_udp_cksum_offload;
+}
+
+int
+spl_hal_tx_tcp_cksum_enable ()
+{
+ return !spl_hal_capa.tx_tcp_cksum_offload;
+}
+
+u32
+spl_hal_is_nic_exist (const char *name)
+{
+ return hal_is_nic_exist (name);
+}
+
+int
+spl_hal_is_bond_netif (struct netif *pnetif)
+{
+ int i;
+ struct bond_set *s;
+ struct netifExt *pnetifExt = NULL;
+
+ pnetifExt = getNetifExt (pnetif->num);
+ if (NULL == pnetifExt)
+ return 0;
+
+ for (i = 0; i < bond_ports_array.cnt; i++)
+ {
+ s = &bond_ports_array.ports[i];
+ if (!strncmp
+ (pnetifExt->if_name, s->bond_port_name, HAL_MAX_NIC_NAME_LEN))
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c b/stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c
new file mode 100644
index 0000000..addc0e6
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/recycle/stackx_recycle.c
@@ -0,0 +1,676 @@
+/*
+*
+* 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 "stackx_spl_share.h"
+#include "nsfw_recycle_api.h"
+#include "nstack_log.h"
+#include "nsfw_msg_api.h"
+#include "stackx_socket.h"
+#include "stackx_spl_msg.h"
+#include "stackx_app_res.h"
+#include "common.h"
+#include "sc_dpdk.h"
+#include "nsfw_mt_config.h"
+#include "spl_instance.h"
+
+#define SS_DELAY_CLOSE_SEC 5
+
+extern struct stackx_port_zone *p_stackx_port_zone;
+
+/*****************************************************************************
+* Prototype : sbr_recycle_rx_mbuf
+* Description : iterator and free rx mbufs with pid flags, when the app
+ with certain pid is no longer exist
+* Input : void *data
+* void *arg
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_recycle_rx_mbuf (void *data, void *arg)
+{
+ u32 *recycle_flg;
+ pid_t *pid = (pid_t *) arg;
+ struct common_mem_mbuf *m_buf = (struct common_mem_mbuf *) data;
+#ifdef HAL_LIB
+#else
+ recycle_flg =
+ (u32 *) ((char *) (m_buf->buf_addr) + RTE_PKTMBUF_HEADROOM -
+ sizeof (u32));
+#endif
+ if (m_buf->refcnt > 0 && *recycle_flg == *pid)
+ {
+ NSSBR_LOGDBG ("free rx mbuf hold by app], mbuf=%p", m_buf);
+ *recycle_flg = MBUF_UNUSED;
+ spl_mbuf_free (m_buf);
+ }
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_recycle_rx_pool
+* Description : recycle rx mbufs hold by app when app crahes
+* Input : pid_t pid
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int
+sbr_recycle_rx_pool (pid_t pid)
+{
+ static struct common_mem_mempool *rx_pool[MAX_VF_NUM * 2][MAX_THREAD_NUM] =
+ { {0} };
+ struct common_mem_mempool *mp;
+ nsfw_mem_name lookup_mbuf_pool;
+ u32 nic_id, queue_id = 0;
+ int retval;
+ struct common_mem_ring *ring;
+
+ for (nic_id = 0;
+ nic_id < p_stackx_port_zone->port_num && nic_id < MAX_VF_NUM * 2;
+ nic_id++)
+ {
+ mp = rx_pool[nic_id][queue_id];
+ if (mp == NULL)
+ {
+ retval =
+ spl_snprintf (lookup_mbuf_pool.aname, NSFW_MEM_NAME_LENGTH - 1,
+ "%s", get_mempoll_rx_name (queue_id, nic_id));
+ if (-1 == retval)
+ {
+ NSPOL_LOGERR ("spl_snprintf fail");
+ break;
+ }
+
+ lookup_mbuf_pool.entype = NSFW_SHMEM;
+ lookup_mbuf_pool.enowner = NSFW_PROC_MAIN;
+ mp =
+ (struct common_mem_mempool *)
+ nsfw_mem_mbfmp_lookup (&lookup_mbuf_pool);
+ if (mp == NULL)
+ break;
+ rx_pool[nic_id][queue_id] = mp;
+ }
+ if (nsfw_mem_mbuf_iterator
+ (mp, 0, mp->size, sbr_recycle_rx_mbuf, (void *) &pid) < 0)
+ {
+ NSSBR_LOGERR ("nsfw_mem_mbuf_iterator return fail");
+ return -1;
+ }
+ ring = (struct common_mem_ring *) (mp->pool_data);
+ NSSBR_LOGINF
+ ("after recycling rx pbuf hold by app]ring=%p,prod.head=%u,prod.tail=%u,"
+ "cons.head=%u,cons.tail=%u.", ring, ring->prod.head, ring->prod.tail,
+ ring->cons.head, ring->cons.tail);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_recycle_rx_pool
+* Description : recycle stackx tx mbufs hold by app when app crahes
+* Input : pid_t pid
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int
+sbr_recycle_tx_pool (pid_t pid)
+{
+ struct common_mem_mempool *mp;
+ struct common_mem_ring *ring;
+
+ /* Try to free all the RX mbufs which are holded in stackx TX pool */
+ mp = (struct common_mem_mempool *) p_def_stack_instance->mp_tx;
+ if (mp == NULL)
+ return -1;
+
+ if (nsfw_mem_mbuf_iterator
+ (mp, 0, mp->size, sbr_recycle_rx_mbuf, (void *) &pid) < 0)
+ {
+ NSSBR_LOGERR ("nsfw_mem_mbuf_iterator return fail");
+ return -1;
+ }
+ ring = (struct common_mem_ring *) (mp->pool_data);
+ NSSBR_LOGINF
+ ("after recycling stackx tx pbuf hold by app]ring=%p,prod.head=%u,prod.tail=%u,"
+ "cons.head=%u,cons.tail=%u.", ring, ring->prod.head, ring->prod.tail,
+ ring->cons.head, ring->cons.tail);
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : ss_free_del_conn_msg
+* Description : free msg
+* Input : msg_delete_netconn *dmsg
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_free_del_conn_msg (msg_delete_netconn * dmsg)
+{
+ data_com_msg *msg = (data_com_msg *) ((char *) dmsg - MAX_MSG_PARAM_SIZE);
+
+ if (MSG_ASYN_POST == msg->param.op_type) /* should check type for linger */
+ {
+ msg_free (msg);
+ }
+}
+
+extern int nsep_recycle_ep (u32 pid);
+
+/*****************************************************************************
+* Prototype : ss_recycle_done
+* Description : recycle done,need recycle ep and rx pool
+* Input : pid_t pid
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_recycle_done (pid_t pid)
+{
+ spl_free_tx_pool (pid);
+ spl_recycle_msg_pool (pid);
+ (void) sbr_recycle_rx_pool (pid);
+ (void) sbr_recycle_tx_pool (pid);
+ (void) nsep_recycle_ep (pid);
+ (void) nsfw_recycle_obj_end (pid);
+}
+
+/*****************************************************************************
+* Prototype : ss_notify_omc
+* Description : try to notify omc
+* Input : spl_netconn_t** conn_array
+* u32 conn_num
+* u8 notify_omc
+* pid_t pid
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_notify_omc (spl_netconn_t ** conn_array, u32 conn_num, u8 notify_omc,
+ pid_t pid)
+{
+ if (notify_omc)
+ {
+ u32 i;
+ for (i = 0; i < conn_num; ++i)
+ {
+ struct spl_netconn *conn = conn_array[i];
+ if (ss_is_pid_exist (conn, pid))
+ {
+ NSSBR_LOGINF ("there are still conn at work]pid=%d", pid);
+ break;
+ }
+
+ msg_delete_netconn *delay_msg = conn->recycle.delay_msg;
+ if (delay_msg && (delay_msg->pid == pid))
+ {
+ delay_msg->notify_omc = notify_omc;
+ NSSBR_LOGINF ("there are still conn at delay]pid=%d", pid);
+ break;
+ }
+ }
+
+ if (conn_num == i)
+ {
+ NSSBR_LOGINF ("recycle done,notify omc]pid=%d", pid);
+ ss_recycle_done (pid);
+ }
+ }
+}
+
+extern void do_pbuf_free (struct spl_pbuf *buf);
+
+static void
+ss_recycle_fd_share (sbr_fd_share * fd_share)
+{
+ /* to free pbufs which are attached to sbr_fd_share */
+ if (fd_share->recoder.head)
+ {
+ struct spl_pbuf *buf = fd_share->recoder.head;
+ fd_share->recoder.head = NULL;
+ fd_share->recoder.tail = NULL;
+ fd_share->recoder.totalLen = 0;
+ do_pbuf_free (buf);
+ }
+}
+
+extern void nsep_recycle_epfd (void *epinfo, u32 pid);
+extern void tcp_free_accept_ring (spl_netconn_t * conn);
+extern void free_conn_by_spl (spl_netconn_t * conn);
+extern void tcp_drop_conn (spl_netconn_t * conn);
+
+/*****************************************************************************
+* Prototype : ss_close_conn_now
+* Description : close netconn now
+* Input : spl_netconn_t *conn
+* msg_delete_netconn *dmsg
+* pid_t pid
+* ss_close_conn_fun close_conn
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_close_conn_now (spl_netconn_t * conn, msg_delete_netconn * dmsg, pid_t pid,
+ ss_close_conn_fun close_conn)
+{
+ spl_netconn_t **conn_array = conn->recycle.group->conn_array;
+ u32 conn_num = conn->recycle.group->conn_num;
+ u8 notify_omc = dmsg->notify_omc;
+
+ close_conn (dmsg, 0);
+
+ nsep_recycle_epfd (conn->epInfo, pid);
+ conn->epInfo = NULL; /*must be set to NULL */
+
+ u32 i;
+ if (conn->recycle.is_listen_conn)
+ {
+ /* drop the conn inside the accept ring */
+ tcp_free_accept_ring (conn);
+
+ /* app coredump and accept_from not changed, need recyle */
+ for (i = 0; i < conn_num; ++i)
+ {
+ struct spl_netconn *accept_conn = conn_array[i];
+ if ((accept_conn->recycle.accept_from == conn)
+ && ss_is_pid_array_empty (accept_conn))
+ {
+ NSSBR_LOGINF
+ ("recycle lost conn]listen_conn=%p,listen_private_data=%p,accept_conn=%p,accept_private_data=%p,pid=%d",
+ conn, conn->private_data, accept_conn,
+ accept_conn->private_data, pid);
+ data_com_msg *msg =
+ (data_com_msg *) ((char *) dmsg - MAX_MSG_PARAM_SIZE);
+ msg->param.receiver = ss_get_recv_obj (accept_conn);
+ dmsg->buf = NULL;
+ dmsg->time_started = sys_now ();
+ dmsg->shut = 0;
+ dmsg->conn = accept_conn;
+ close_conn (dmsg, 0);
+
+ nsep_recycle_epfd (accept_conn->epInfo, pid);
+ accept_conn->epInfo = NULL; /*must be set to NULL */
+
+ /* lost conn need drop first, can't just free conn */
+ tcp_drop_conn (accept_conn);
+ }
+ }
+ }
+
+ if (SS_DELAY_STOPPED == conn->recycle.delay_flag)
+ {
+ sbr_fd_share *fd_share =
+ (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE);
+ ss_recycle_fd_share (fd_share);
+ free_conn_by_spl (conn);
+ }
+
+ ss_free_del_conn_msg (dmsg);
+ ss_notify_omc (conn_array, conn_num, notify_omc, pid);
+}
+
+/*****************************************************************************
+* Prototype : ss_close_conn_delay
+* Description : delay to close conn
+* Input : spl_netconn_t *conn
+* pid_t pid
+* msg_delete_netconn *dmsg
+* ss_close_conn_fun close_conn
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_close_conn_delay (spl_netconn_t * conn, pid_t pid,
+ msg_delete_netconn * dmsg, ss_close_conn_fun close_conn)
+{
+ NSSBR_LOGINF
+ ("ref > 0 and pid array is empty, start delay closing conn]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ close_conn (dmsg, SS_DELAY_CLOSE_SEC);
+}
+
+/*****************************************************************************
+* Prototype : ss_process_delay_up
+* Description : delay is up
+* Input : spl_netconn_t *conn
+* pid_t pid
+* msg_delete_netconn *dmsg
+* ss_close_conn_fun close_conn
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_process_delay_up (spl_netconn_t * conn, pid_t pid,
+ msg_delete_netconn * dmsg, ss_close_conn_fun close_conn)
+{
+ spl_netconn_t **conn_array = conn->recycle.group->conn_array;
+ u32 conn_num = conn->recycle.group->conn_num;
+ u8 notify_omc = dmsg->notify_omc;
+
+ if (SS_DELAY_STARTED == conn->recycle.delay_flag)
+ {
+ if (ss_is_pid_array_empty (conn))
+ {
+ NSSBR_LOGINF
+ ("delay time is up,close conn now]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ conn->recycle.delay_flag = SS_DELAY_STOPPED;
+ conn->recycle.delay_msg = NULL;
+ ss_close_conn_now (conn, dmsg, pid, close_conn);
+ return;
+ }
+ else
+ {
+ NSSBR_LOGINF
+ ("stop delay closing conn,conn still working]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ conn->recycle.delay_flag = SS_DELAY_STOPPED;
+ conn->recycle.delay_msg = NULL;
+ ss_free_del_conn_msg (dmsg);
+ ss_notify_omc (conn_array, conn_num, notify_omc, pid);
+ return;
+ }
+ }
+ else if (SS_DELAY_AGAIN == conn->recycle.delay_flag)
+ {
+ if (ss_is_pid_array_empty (conn))
+ {
+ NSSBR_LOGINF
+ ("delay time is up,but need delay again]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ conn->recycle.delay_flag = SS_DELAY_STARTED;
+ ss_close_conn_delay (conn, pid, dmsg, close_conn);
+ return;
+ }
+ else
+ {
+ NSSBR_LOGINF
+ ("stop delay closing conn,conn still working]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ conn->recycle.delay_flag = SS_DELAY_STOPPED;
+ conn->recycle.delay_msg = NULL;
+ ss_free_del_conn_msg (dmsg);
+ ss_notify_omc (conn_array, conn_num, notify_omc, pid);
+ return;
+ }
+ }
+ else if (SS_DELAY_STOPPING == conn->recycle.delay_flag)
+ {
+ NSSBR_LOGINF
+ ("the conn has been closed,free conn]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ conn->recycle.delay_flag = SS_DELAY_STOPPED;
+ conn->recycle.delay_msg = NULL;
+ free_conn_by_spl (conn);
+ ss_free_del_conn_msg (dmsg);
+ ss_notify_omc (conn_array, conn_num, notify_omc, pid);
+ return;
+ }
+ else
+ {
+ NSSBR_LOGERR ("this can not happen]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ }
+}
+
+/*****************************************************************************
+* Prototype : ss_recycle_conn
+* Description : recycle conn
+* Input : void *close_data
+* ss_close_conn_fun close_conn
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+ss_recycle_conn (void *close_data, ss_close_conn_fun close_conn)
+{
+ msg_delete_netconn *dmsg = (msg_delete_netconn *) close_data;
+ spl_netconn_t *conn = dmsg->conn;
+ pid_t pid = dmsg->pid;
+ u8 notify_omc = dmsg->notify_omc;
+ struct spl_netconn **conn_array = conn->recycle.group->conn_array;
+ u32 conn_num = conn->recycle.group->conn_num;
+
+ int ret = ss_del_pid (conn, pid);
+ if (0 == ret)
+ {
+ i32 ref = ss_dec_fork_ref (conn);
+ if (0 == ref)
+ {
+ if (conn->recycle.delay_flag != SS_DELAY_STOPPED)
+ {
+ conn->recycle.delay_flag = SS_DELAY_STOPPING;
+ NSSBR_LOGINF
+ ("stop delay closing conn,close conn now]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ }
+ else
+ {
+ NSSBR_LOGINF ("close conn now]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ }
+
+ ss_close_conn_now (conn, dmsg, pid, close_conn);
+ return 0;
+ }
+ else
+ {
+ if (ss_is_pid_array_empty (conn))
+ {
+ if (SS_DELAY_STOPPED == conn->recycle.delay_flag) /* only start one delay */
+ {
+ conn->recycle.delay_flag = SS_DELAY_STARTED;
+ conn->recycle.delay_msg = close_data;
+ ss_close_conn_delay (conn, pid, dmsg, close_conn);
+ return 0;
+ }
+ else if (SS_DELAY_STARTED == conn->recycle.delay_flag)
+ {
+ conn->recycle.delay_flag = SS_DELAY_AGAIN;
+ NSSBR_LOGINF
+ ("ref > 0 and pid array is empty, delay again]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (conn->recycle.delay_msg && (conn->recycle.delay_msg == close_data)) /* only the stater can process */
+ {
+ ss_process_delay_up (conn, pid, dmsg, close_conn);
+ return 0;
+ }
+ }
+
+ NSSBR_LOGINF ("go to notify omc]conn=%p,pid=%d,private_data=%p", conn, pid,
+ conn->private_data);
+ ss_free_del_conn_msg (dmsg);
+ ss_notify_omc (conn_array, conn_num, notify_omc, pid);
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_recycle_conn
+* Description : post msg to spl
+* Input : spl_netconn_t* conn
+* pid_t pid
+* u8 notify_omc
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_handle_recycle_conn (spl_netconn_t * conn, pid_t pid, u8 notify_omc)
+{
+ data_com_msg *m = msg_malloc (ss_get_msg_pool (conn));
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]conn=%p,pid=%d,private_data=%p", conn,
+ pid, conn->private_data);
+ return -1;
+ }
+
+ NSSBR_LOGINF ("recycle conn]conn=%p,pid=%d,private_data=%p", conn, pid,
+ conn->private_data);
+
+ m->param.module_type = MSG_MODULE_SBR;
+ m->param.major_type = SPL_TCPIP_NEW_MSG_API;
+ m->param.minor_type = SPL_API_DO_DELCON;
+ m->param.err = 0;
+ m->param.op_type = MSG_ASYN_POST;
+ sys_sem_init (&m->param.op_completed);
+ m->param.receiver = ss_get_recv_obj (conn);
+ m->param.extend_member_bit = 0;
+
+ msg_delete_netconn *p = (msg_delete_netconn *) m->buffer;
+ p->extend_member_bit = 0;
+ p->time_started = sys_now ();
+ p->shut = 0;
+ p->pid = pid;
+ p->conn = conn;
+ p->notify_omc = notify_omc;
+ p->msg_box_ref = SPL_MSG_BOX_NUM;
+ p->buf = NULL;
+
+ /* to ensure that the last deal with SPL_API_DO_DELCON message */
+ int i;
+ for (i = 0; i < SPL_MSG_BOX_NUM; ++i)
+ {
+ if (msg_post_with_lock_rel
+ (m,
+ ss_get_instance_msg_box (ss_get_bind_thread_index (conn), i)) < 0)
+ {
+ msg_free (m);
+ NSSBR_LOGERR ("post msg failed]conn=%p,pid=%d,private_data=%p",
+ conn, pid, conn->private_data);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_recycle_fd_share
+* Description : recycle sbr_fd_share
+* Input : sbr_fd_share* fd_share
+* pid_t pid
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+sbr_recycle_fd_share (sbr_fd_share * fd_share, pid_t pid)
+{
+ if (fd_share->common_lock.locked == pid)
+ {
+ common_spinlock_unlock (&fd_share->common_lock);
+ }
+
+ if (fd_share->recv_lock.locked == pid)
+ {
+ common_spinlock_unlock (&fd_share->recv_lock);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_recycle_conn
+* Description : recycle api,called by recycle module
+* Input : u32 exit_pid
+* void *pdata
+* u16 rec_type
+* Output : None
+* Return Value : nsfw_rcc_stat
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+nsfw_rcc_stat
+sbr_recycle_conn (u32 exit_pid, void *pdata, u16 rec_type)
+{
+ NSSBR_LOGINF ("start recycle]pid=%d", exit_pid);
+
+ if (0 == exit_pid)
+ {
+ NSSBR_LOGERR ("pid is not ok]pid=%d", exit_pid);
+ return NSFW_RCC_CONTINUE;
+ }
+
+ spl_netconn_t **conn_array = spl_get_conn_array (exit_pid);
+ if (!conn_array)
+ {
+ NSSBR_LOGERR ("conn_array is NULL]pid=%d", exit_pid);
+ return NSFW_RCC_CONTINUE;
+ }
+
+ u32 num = spl_get_conn_num ();
+ spl_netconn_t *conn;
+ sbr_fd_share *fd_share;
+ u32 i;
+ for (i = 0; i < num; ++i)
+ {
+ conn = conn_array[i];
+ if (ss_is_pid_exist (conn, exit_pid))
+ {
+ fd_share = (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE);
+ sbr_recycle_fd_share (fd_share, exit_pid);
+ sbr_handle_recycle_conn (conn, exit_pid, FALSE);
+ }
+ }
+
+ sbr_handle_recycle_conn (conn_array[0], exit_pid, TRUE);
+ return NSFW_RCC_SUSPEND;
+}
+
+REGIST_RECYCLE_OBJ_FUN (NSFW_REC_SBR_SOCKET, sbr_recycle_conn)
diff --git a/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt b/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt
new file mode 100644
index 0000000..e7915d2
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/CMakeLists.txt
@@ -0,0 +1,76 @@
+#########################################################################
+#
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#########################################################################
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -g -fPIE -pie -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")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium")
+
+SET(ADAPT_DIRECTORIES "${PROJECT_SOURCE_DIR}/src/adapt/")
+#SET(DMM_API "${PROJECT_SOURCE_DIR}/src/nSocket/include/")
+
+ADD_DEFINITIONS(-D_GNU_SOURCE -D_FORTIFY_SOURCE=2)
+ADD_DEFINITIONS(-DDPDK_MODULE=0)
+if(WITH_HAL_LIB)
+SET(RTP_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../../src/include/rtp_config.h)
+else()
+ SET(PAL_H_DIRECTORIES "/usr/include/dpdk/")
+ SET(RTP_CONFIG ${PROJECT_SOURCE_DIR}/../../src/framework/common/base/include/common/common_sys_config.h)
+ INCLUDE_DIRECTORIES(
+ ${PAL_H_DIRECTORIES}
+ ${ADAPT_DIRECTORIES}
+# ${DMM_API}
+ )
+endif()
+SET(COMPLE_CONFIG ${CMAKE_CURRENT_LIST_DIR}/../../src/include/compile_config.h)
+#SET(MGR_COM ${PROJECT_SOURCE_DIR}/src/framework/ipc/mgr_com/mgr_com.h)
+SET(MGR_COM ${CMAKE_CURRENT_LIST_DIR}/../../src/include/mgr_com.h)
+ADD_DEFINITIONS(-include ${RTP_CONFIG})
+ADD_DEFINITIONS(-include ${COMPLE_CONFIG})
+ADD_DEFINITIONS(-include ${MGR_COM})
+if(WITH_SECUREC_LIB)
+LINK_LIBRARIES(pthread rt securec)
+else()
+LINK_LIBRARIES(pthread rt)
+endif()
+LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC})
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../thirdparty/json/json-c-0.12.1/
+ ${CMAKE_CURRENT_LIST_DIR}/../../../../thirdparty/glog/glog-0.3.4/src/
+ ${CMAKE_CURRENT_LIST_DIR}/../../src/include/
+# ${PROJECT_SOURCE_DIR}/src/framework/include/
+# ${PROJECT_SOURCE_DIR}/src/framework/common/include/
+# ${ADAPT_DIRECTORIES}
+# ${DMM_API}
+)
+
+FILE(GLOB COMMON ../common/*.c)
+FILE(GLOB SOCKET ./*.c)
+ADD_LIBRARY(socket STATIC ${COMMON} ${SOCKET})
+ADD_DEPENDENCIES(socket JSON GLOG DPDK)
+TARGET_INCLUDE_DIRECTORIES(
+ socket
+ PRIVATE
+ ../common/
+ ./
+ ${CMAKE_CURRENT_LIST_DIR}/../../src/sbr/
+ ${CMAKE_CURRENT_LIST_DIR}/../../src/include/
+# ${PROJECT_SOURCE_DIR}/src/framework/include/
+# ${PROJECT_SOURCE_DIR}/src/framework/common/include/
+# ${ADAPT_DIRECTORIES}
+# ${DMM_API}
+)
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h b/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h
new file mode 100644
index 0000000..4f4749d
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_cfg.h
@@ -0,0 +1,54 @@
+/*
+*
+* 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 STACKX_CONTAINER_CFG_H
+#define STACKX_CONTAINER_CFG_H
+#include "types.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define SBR_MAX_CFG_PATH_LEN 256
+#define SBR_MAX_CONTAINER_IP_NUM 1024
+#define SBR_MAX_CFG_FILE_SIZE (1 * 1024 * 1024)
+
+typedef struct
+{
+ u32 ip;
+ u32 mask_len;
+} sbr_container_ip;
+
+typedef struct
+{
+ sbr_container_ip ip_array[SBR_MAX_CONTAINER_IP_NUM];
+ u32 ip_num;
+} sbr_container_ip_group;
+
+extern sbr_container_ip_group g_container_ip_group;
+
+int sbr_init_cfg ();
+int sbr_get_src_ip (u32 dst_ip, u32 * src_ip);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c b/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c
new file mode 100644
index 0000000..b6580ed
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_container_cfg.c
@@ -0,0 +1,332 @@
+/*
+*
+* 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 <sys/stat.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include "stackx_cfg.h"
+#include "json.h"
+#include "nstack_log.h"
+#include "spl_def.h"
+#include "nstack_securec.h"
+#include "stackx_ip_addr.h"
+
+sbr_container_ip_group g_container_ip_group;
+
+/*****************************************************************************
+* Prototype : sbr_parse_container_ip_json
+* Description : parse port json
+* Input : char* param
+* Output : None
+* Return Value : static void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static void
+sbr_parse_container_ip_json (char *param)
+{
+ int retval;
+ struct json_object *obj = json_tokener_parse (param);
+ struct json_object *container_id_obj = NULL;
+ struct json_object *ports_list_obj = NULL;
+ struct json_object *ip_cidr_list_obj = NULL;
+
+ if (!obj)
+ {
+ NSSBR_LOGERR ("json_tokener_parse failed");
+ return;
+ }
+
+ json_object_object_get_ex (obj, "containerID", &container_id_obj);
+ if (!container_id_obj)
+ {
+ NSSBR_LOGERR ("can't get containerID");
+ goto RETURN_ERROR;
+ }
+
+ json_object_object_get_ex (obj, "ports_list", &ports_list_obj);
+ if (ports_list_obj)
+ {
+ int i;
+ int port_num = json_object_array_length (ports_list_obj);
+
+ if (0 == port_num)
+ {
+ NSSBR_LOGERR ("port num is 0");
+ goto RETURN_ERROR;
+ }
+
+ for (i = 0; i < port_num; i++)
+ {
+ struct json_object *port_obj =
+ json_object_array_get_idx (ports_list_obj, i);
+ json_object_object_get_ex (port_obj, "ip_cidr", &ip_cidr_list_obj);
+ if (ip_cidr_list_obj)
+ {
+ int j;
+ int ip_cidr_num = json_object_array_length (ip_cidr_list_obj);
+ for (j = 0; j < ip_cidr_num; ++j)
+ {
+ struct json_object *ip_cidr_obj =
+ json_object_array_get_idx (ip_cidr_list_obj, j);
+ if (ip_cidr_obj)
+ {
+ char tmp[32] = { 0 };
+ const char *ip_cidr =
+ json_object_get_string (ip_cidr_obj);
+ if ((NULL == ip_cidr) || (ip_cidr[0] == 0))
+ {
+ NSSBR_LOGERR ("ip is empty");
+ goto RETURN_ERROR;
+ }
+
+ const char *sub = strstr (ip_cidr, "/");
+ if ((NULL == sub)
+ || (sizeof (tmp) - 1 <
+ (unsigned int) (sub - ip_cidr))
+ || (strlen (sub) > sizeof (tmp) - 1))
+ {
+ NSSBR_LOGERR ("ip format is not ok");
+ goto RETURN_ERROR;
+ }
+
+ retval =
+ STRNCPY_S (tmp, sizeof (tmp), ip_cidr,
+ (size_t) (sub - ip_cidr));
+ if (EOK != retval)
+ {
+ NSSBR_LOGERR ("STRNCPY_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+
+ struct in_addr addr;
+ retval =
+ MEMSET_S (&addr, sizeof (addr), 0, sizeof (addr));
+ if (EOK != retval)
+ {
+ NSSBR_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ goto RETURN_ERROR;
+ }
+
+ retval = spl_inet_aton (tmp, &addr);
+ if (0 == retval)
+ {
+ NSSBR_LOGERR ("spl_inet_aton failed]ret=%d",
+ retval);
+ goto RETURN_ERROR;
+ }
+
+ g_container_ip_group.
+ ip_array[g_container_ip_group.ip_num].ip =
+ addr.s_addr;
+ int mask_len = atoi (sub + 1);
+ if ((mask_len <= 0) || (mask_len > 32))
+ {
+ NSSBR_LOGERR ("mask len is not ok");
+ goto RETURN_ERROR;
+ }
+
+ g_container_ip_group.
+ ip_array[g_container_ip_group.ip_num].mask_len =
+ (u32) mask_len;
+ g_container_ip_group.ip_num++;
+
+ if (g_container_ip_group.ip_num >=
+ SBR_MAX_CONTAINER_IP_NUM)
+ {
+ NSSBR_LOGWAR ("container ip num is full]ip_num=%u",
+ g_container_ip_group.ip_num);
+ goto RETURN_OK;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ NSSBR_LOGERR ("can't get ports_list");
+ goto RETURN_ERROR;
+ }
+
+RETURN_OK:
+ json_object_put (obj);
+ NSSBR_LOGINF ("container ip num is %u", g_container_ip_group.ip_num);
+ u32 idx;
+ for (idx = 0; idx < g_container_ip_group.ip_num; ++idx)
+ {
+ NSSBR_LOGDBG ("container ip=0x%08x",
+ g_container_ip_group.ip_array[idx].ip);
+ }
+ return;
+
+RETURN_ERROR:
+ json_object_put (obj);
+ if (MEMSET_S
+ (&g_container_ip_group, sizeof (sbr_container_ip_group), 0,
+ sizeof (sbr_container_ip_group)) != EOK)
+ {
+ NSSBR_LOGERR ("MEMSET_S failed");
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_cfg_path
+* Description : get cfg path
+* Input : None
+* Output : None
+* Return Value : NSTACK_STATIC const char*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC const char *
+sbr_get_cfg_path ()
+{
+ static char cfg_file[SBR_MAX_CFG_PATH_LEN] = "/canal/output/portinfo.json";
+ return cfg_file;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_cfg
+* Description : init cfg from file
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_init_cfg ()
+{
+ int ret;
+ off_t file_len = 0;
+ off_t buff_len = 0;
+ char *buff = NULL;
+ const char *cfg_file = sbr_get_cfg_path (); /* no need check ret */
+
+ int fp = open (cfg_file, O_RDONLY);
+
+ if (fp < 0)
+ {
+ NSSBR_LOGWAR ("failed to open file]file name=%s", cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ file_len = lseek (fp, 0, SEEK_END);
+ if (file_len <= 0)
+ {
+ NSSBR_LOGWAR ("failed to get file len]file name=%s", cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ if (file_len > SBR_MAX_CFG_FILE_SIZE)
+ {
+ NSSBR_LOGWAR
+ ("file len is too big]file len=%d, max len=%d, file name=%s",
+ file_len, SBR_MAX_CFG_FILE_SIZE, cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ ret = lseek (fp, 0, SEEK_SET);
+ if (ret < 0)
+ {
+ NSSBR_LOGWAR ("seek to start failed]file name=%s", cfg_file);
+ goto RETURN_ERROR;
+ }
+
+ buff_len = file_len + 1;
+ buff = (char *) malloc (buff_len);
+ if (!buff)
+ {
+ NSSBR_LOGWAR ("malloc buff failed]buff_len=%d", buff_len);
+ goto RETURN_ERROR;
+ }
+
+ ret = MEMSET_S (buff, buff_len, 0, buff_len);
+ if (EOK != ret)
+ {
+ NSSBR_LOGWAR ("MEMSET_S failed]ret=%d.", ret);
+ goto RETURN_ERROR;
+ }
+
+ ret = read (fp, buff, buff_len - 1);
+ if (ret <= 0)
+ {
+ NSSBR_LOGWAR ("read failed]ret=%d", ret);
+ goto RETURN_ERROR;
+ }
+
+ sbr_parse_container_ip_json (buff);
+ close (fp);
+ free (buff);
+ return 0;
+
+RETURN_ERROR:
+ if (fp >= 0)
+ {
+ close (fp);
+ }
+
+ if (buff)
+ {
+ free (buff);
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_src_ip
+* Description : get src ip from cfg
+* Input : u32 dst_ip
+* u32* src_ip
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_get_src_ip (u32 dst_ip, u32 * src_ip)
+{
+ if (!src_ip)
+ {
+ NSSBR_LOGERR ("src_ip is NULL");
+ return -1;
+ }
+
+ u32 i;
+ for (i = 0; i < g_container_ip_group.ip_num; ++i)
+ {
+ unsigned int mask = ~0;
+ mask = (mask << (32 - g_container_ip_group.ip_array[i].mask_len));
+ mask = htonl (mask);
+ if ((dst_ip & mask) == (g_container_ip_group.ip_array[i].ip & mask))
+ {
+ *src_ip = g_container_ip_group.ip_array[i].ip;
+ NSSBR_LOGDBG ("find src ip]container_ip=0x%08x,dest_ip=0x%08x",
+ *src_ip, dst_ip);
+ return 0;
+ }
+ }
+
+ NSSBR_LOGDBG ("can't find src ip]dest_ip=0x%08x", dst_ip);
+ return -1;
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c
new file mode 100644
index 0000000..0223ac9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.c
@@ -0,0 +1,150 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "stackx_epoll_api.h"
+#include "stackx_spl_share.h"
+#include "common_pal_bitwide_adjust.h"
+#include "nstack_dmm_adpt.h"
+#include "nstack_dmm_api.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif /* _cplusplus */
+
+void
+epoll_triggle_event_from_api (sbr_socket_t * sock, int op)
+{
+ struct spl_netconn *conn = sbr_get_conn (sock);
+ void *epInfo = ADDR_SHTOL (conn->epInfo);
+ //NSPOL_LOGDBG(SOCKETS_DEBUG, "enter]fd=%d,op=%d", sock, op);
+ switch (op)
+ {
+ case EPOLL_API_OP_RECV:
+ break;
+ case EPOLL_API_OP_SEND:
+ if (conn->epoll_flag && epInfo)
+ {
+ nstack_event_callback (epInfo, EPOLLOUT);
+ }
+ break;
+ case EPOLL_API_OP_STACK_RECV:
+ if (conn->epoll_flag && epInfo)
+ {
+ nstack_event_callback (epInfo, EPOLLIN);
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+/*
+ * This function will be registed to application
+ * The context will be in the application
+ */
+unsigned int
+stackx_eventpoll_triggle (sbr_socket_t * sock, int triggle_ops,
+ struct epoll_event *pevent, void *pdata)
+{
+ struct spl_netconn *conn = sbr_get_conn (sock);
+ unsigned int events = 0;
+ if (!conn)
+ {
+ NSPOL_LOGINF (SOCKETS_DEBUG, "get socket failed]fd=%d", sock->fd);
+ return -1;
+ }
+
+ NSPOL_LOGINF (SOCKETS_DEBUG,
+ "]fd=%d,triggle_ops=%d conn=%p event:%d pdata=%p", sock->fd,
+ triggle_ops, conn, pevent->events, pdata);
+ /*
+ * sock->epoll_flag must be set before sock->rcvevent check.
+ * Consider this Scenario : 1) network stack has got one packet, but event_callback not called yet
+ * 2) Do epoll ctl add, then stackx triggle will check event, it will get 0
+ * 3) network stack call event_callback , it will check epoll_flag
+ * So, if epoll_flag not set before sock->rcvent check, neither of network stack and stackx triggle
+ * will add this event to epoll. because : for network stack, event_callback check epoll_flag fail
+ * for stackx triggle, event check fail.
+ */
+ if (nstack_ep_triggle_add == triggle_ops)
+ {
+ /*log info */
+ conn->epInfo = pdata;
+ __sync_fetch_and_add (&conn->epoll_flag, 1);
+ }
+
+ if ((pevent->events & EPOLLIN)
+ &&
+ (!((conn->rcvevent == 0) && (sbr_get_fd_share (sock)->lastdata == 0)
+ && (sbr_get_fd_share (sock)->lastoffset == 0))))
+ events |= EPOLLIN;
+ if ((pevent->events & EPOLLOUT) && conn->sendevent)
+ events |= EPOLLOUT;
+ if (conn->errevent)
+ events |= pevent->events & (conn->errevent);
+
+ switch (triggle_ops)
+ {
+ case nstack_ep_triggle_add:
+ break;
+ case nstack_ep_triggle_mod:
+ break;
+ case nstack_ep_triggle_del:
+ if (conn->epoll_flag > 0)
+ {
+ __sync_fetch_and_sub (&conn->epoll_flag, 1);
+ }
+ events = 0;
+ break;
+ default:
+ return -1;
+ }
+ return events;
+}
+
+/*
+ * This function will be registed to application
+ * The context will be in the application
+ * RETURN VALUE : Event exists in current protocol
+ */
+unsigned int
+stackx_eventpoll_getEvt (sbr_socket_t * sock, unsigned int events)
+{
+ struct spl_netconn *conn = sbr_get_conn (sock);
+ unsigned int tevent = 0;
+ if ((events & EPOLLIN)
+ &&
+ (!((conn->rcvevent == 0) && (sbr_get_fd_share (sock)->lastdata == 0)
+ && (sbr_get_fd_share (sock)->lastoffset == 0))))
+ {
+ tevent |= EPOLLIN;
+ }
+
+ if ((events & EPOLLOUT) && conn->sendevent)
+ {
+ tevent |= EPOLLOUT;
+ }
+ return tevent;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif /* _cplusplus */
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h
new file mode 100644
index 0000000..59a1d21
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_epoll_api.h
@@ -0,0 +1,48 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_EPOLL_API_H
+#define STACKX_EPOLL_API_H
+#include "stackx_socket.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef enum
+{
+ EPOLL_API_OP_RECV,
+ EPOLL_API_OP_SEND,
+ EPOLL_API_OP_STACK_RECV
+} EPOLL_TRIGGLE_EVENT_API_OPS_T;
+
+extern void epoll_triggle_event_from_api (sbr_socket_t * sock, int op);
+extern unsigned int stackx_eventpoll_getEvt (sbr_socket_t * sock,
+ unsigned int events);
+extern unsigned int stackx_eventpoll_triggle (sbr_socket_t * sock,
+ int triggle_ops,
+ struct epoll_event *pevent,
+ void *pdata);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_event.c b/stacks/lwip_stack/lwip_src/socket/stackx_event.c
new file mode 100644
index 0000000..93e47a3
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_event.c
@@ -0,0 +1,29 @@
+/*
+*
+* 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 "stackx_spl_share.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_event.h"
+#include <netinet/in.h>
+
+#define FREE_FD_SET(readfd, writefd, exceptfd) {\
+ if(readfd)\
+ free(readfd);\
+ if(writefd)\
+ free(writefd);\
+ if(exceptfd)\
+ free(exceptfd);\
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_event.h b/stacks/lwip_stack/lwip_src/socket/stackx_event.h
new file mode 100644
index 0000000..f95b370
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_event.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 __STACKX_EVENT_H__
+#define __STACKX_EVENT_H__
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "stackx_socket.h"
+#include "nstack_securec.h"
+#include "sbr_res_mgr.h"
+#include "sbr_index_ring.h"
+#define NSTACK_SETSIZE SBR_MAX_FD_NUM
+
+typedef struct
+{
+ unsigned char fds_bits[(NSTACK_SETSIZE + 7) / 8];
+} __attribute__ ((packed)) nstack_fd_set;
+
+#define NSTACK_FD_SET(n, p) ((p)->fds_bits[(n)/8]|=1U<<((n)&0x07))
+#define NSTACK_FD_ISSET(n,p) (((p)->fds_bits[(n)/8]&(1U<<((n)&0x07)))?1:0)
+#define NSTACK_FD_CLR(n,p) ((p)->fds_bits[(n)/8]&=~(1U<<((n)&0x07)))
+#define NSTACK_FD_ZERO(p) (MEMSET_S((void *)(p), sizeof(*(p)),0,sizeof(*(p))))
+#define NSTACK_FD_OR(p1 ,p2) {\
+ int i;\
+ for(i = 0; i < (NSTACK_SETSIZE+7)/8; i++){\
+ (p1)->fds_bits[i] |= (p2)->fds_bits[i];\
+ }\
+}
+
+#endif /* __STACKX_EVENT_H__ */
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_macro.h b/stacks/lwip_stack/lwip_src/socket/stackx_macro.h
new file mode 100644
index 0000000..96a0b91
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_macro.h
@@ -0,0 +1,24 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_MACRO_H
+#define STACKX_MACRO_H
+
+#ifndef SBR_USE_LOCK
+#define SBR_USE_LOCK
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c
new file mode 100644
index 0000000..6fcde44
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.c
@@ -0,0 +1,775 @@
+/*
+*
+* 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 "stackx_msg_handler.h"
+#include "stackx_spl_share.h"
+#include "stackx_spl_msg.h"
+#include "nsfw_msg_api.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_res_mgr.h"
+#include "stackx_prot_com.h"
+#include "nstack_securec.h"
+//#include "stackx_dfx_api.h"
+
+#define SBR_MSG_MALLOC(sk) msg_malloc(ss_get_msg_pool(sbr_get_conn(sk)))
+#define SBR_MSG_FREE(msg) msg_free(msg)
+
+#define SBR_MSG_POST(msg, ring) \
+ do { \
+ if (MSG_ASYN_POST == msg->param.op_type)\
+ {\
+ if (msg_post(msg, ring) < 0)\
+ {\
+ SBR_MSG_FREE(msg); \
+ NSSBR_LOGERR("msg_post failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ else \
+ {\
+ if (msg_post(msg, ring) < 0)\
+ {\
+ msg->param.err = ECONNABORTED; \
+ NSSBR_LOGERR("msg_post_with_ref failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ } while (0)
+
+#define SBR_MSG_POST_RET(msg, ring, ret) \
+ do { \
+ if (MSG_ASYN_POST == msg->param.op_type)\
+ {\
+ if ((ret = msg_post(msg, ring)) < 0)\
+ {\
+ SBR_MSG_FREE(msg); \
+ NSSBR_LOGERR("msg_post failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ else \
+ {\
+ if ((ret = msg_post(msg, ring)) < 0)\
+ {\
+ msg->param.err = ECONNABORTED; \
+ NSSBR_LOGERR("msg_post_with_ref failed]major=%u,minor=%u,type=%u", \
+ msg->param.major_type, msg->param.minor_type, msg->param.op_type); \
+ }\
+ } \
+ } while (0)
+
+NSTACK_STATIC inline void
+_sbr_construct_msg (data_com_msg * m, u16 major_type, u16 minor_type,
+ u16 type, sbr_socket_t * sk)
+{
+ m->param.module_type = MSG_MODULE_SBR;
+ m->param.major_type = major_type;
+ m->param.minor_type = minor_type;
+ m->param.err = 0;
+ m->param.op_type = type;
+ sys_sem_init (&m->param.op_completed);
+ m->param.receiver = ss_get_recv_obj (sbr_get_conn (sk));
+ m->param.comm_receiver = ss_get_comm_private_data (sbr_get_conn (sk));
+ m->param.extend_member_bit = 0;
+}
+
+#define sbr_construct_msg(m, major_type, minor_type, type, sk) { \
+ _sbr_construct_msg(m, major_type, minor_type, type, sk); \
+ NSSBR_LOGINF("fd=%d,conn=%p,private_data=%p", sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); \
+ }
+
+#define sbr_construct_msg_dbg(m, major_type, minor_type, type, sk) { \
+ _sbr_construct_msg(m, major_type, minor_type, type, sk); \
+ NSSBR_LOGDBG("fd=%d,conn=%p,private_data=%p", sk->fd, sbr_get_conn(sk), ss_get_private_data(sbr_get_conn(sk))); \
+ }
+
+/*****************************************************************************
+* Prototype : sbr_attach_msg
+* Description : use buf's msg first
+* Input : sbr_socket_t * sk
+* struct pbuf* buf
+* Output : None
+* Return Value : static inline data_com_msg*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline data_com_msg *
+sbr_attach_msg (sbr_socket_t * sk, struct spl_pbuf *buf)
+{
+ data_com_msg *m = NULL;
+ if (!sk)
+ {
+ return m;
+ }
+
+ if (buf && buf->msg)
+ {
+ m = (data_com_msg *) ADDR_SHTOL (buf->msg);
+ }
+ else
+ {
+ m = SBR_MSG_MALLOC (sk);
+ }
+
+ return m;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_socket
+* Description : create socket
+* Input : sbr_socket_t * sk
+* netconn_type_t type
+* u8 proto
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_socket (sbr_socket_t * sk, spl_netconn_type_t type, u8 proto)
+{
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_NEWCONN,
+ MSG_SYN_POST, sk);
+ msg_new_netconn *p = (msg_new_netconn *) m->buffer;
+ p->conn = (spl_netconn_t *) ADDR_LTOSH (sbr_get_conn (sk));
+ p->type = type;
+ p->proto = proto;
+ p->socket = sk->fd;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ int err = sbr_spl_err_to_errno (m->param.err);
+ SBR_MSG_FREE (m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle socket failed]fd=%d,type=%d,proto=%u,err=%d",
+ sk->fd, type, proto, err);
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_bind
+* Description : bind
+* Input : sbr_socket_t * sk
+* spl_ip_addr_t * addr
+* u16 port
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_bind (sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port)
+{
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_BIND, MSG_SYN_POST,
+ sk);
+ msg_bind *p = (msg_bind *) m->buffer;
+ p->ipaddr = *addr;
+ p->port = port;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ int err = sbr_spl_err_to_errno (m->param.err);
+ SBR_MSG_FREE (m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle bind failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+sbr_handle_listen (sbr_socket_t * sk, int backlog)
+{
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_LISTEN,
+ MSG_SYN_POST, sk);
+ msg_listen *p = (msg_listen *) m->buffer;
+ p->conn_pool = sbr_get_conn_pool ();
+ p->backlog = backlog;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ int err = sbr_spl_err_to_errno (m->param.err);
+ SBR_MSG_FREE (m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle listen failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_connect
+* Description : connect
+* Input : sbr_socket_t * sk
+* spl_ip_addr_t * addr
+* u16 port
+* spl_ip_addr_t* local_ip
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_connect (sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port,
+ spl_ip_addr_t * local_ip)
+{
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_CONNECT,
+ MSG_SYN_POST, sk);
+ msg_connect *p = (msg_connect *) m->buffer;
+ p->local_ip = *local_ip;
+ p->ipaddr = *addr;
+ p->port = port;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ int err = sbr_spl_err_to_errno (m->param.err);
+ SBR_MSG_FREE (m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle connect failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_get_name
+* Description : get name
+* Input : sbr_socket_t * sk
+* struct sockaddr * name
+* socklen_t * namelen
+* u8 cmd
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_get_name (sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen, u8 cmd)
+{
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_GETSOCK_NAME,
+ MSG_SYN_POST, sk);
+ msg_getaddrname *p = (msg_getaddrname *) m->buffer;
+ p->cmd = cmd;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ int err = sbr_spl_err_to_errno (m->param.err);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle get name failed]fd=%d,err=%d", sk->fd, err);
+ goto error;
+ }
+ else
+ {
+ if (*namelen > sizeof (p->sock_addr))
+ {
+ *namelen = sizeof (p->sock_addr);
+ }
+
+ int ret = MEMCPY_S (name, *namelen, &p->sock_addr, *namelen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR ("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ *namelen = sizeof (p->sock_addr);
+ }
+
+ SBR_MSG_FREE (m);
+ return 0;
+
+error:
+ sbr_set_sk_errno (sk, err);
+ SBR_MSG_FREE (m);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_setsockopt
+* Description : msg box will changed in IP_TOS
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* const void *optval
+* socklen_t optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_setsockopt (sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_SET_SOCK_OPT,
+ MSG_SYN_POST, sk);
+ msg_setgetsockopt *p = (msg_setgetsockopt *) m->buffer;
+ p->extend_member_bit = 0;
+ p->level = level;
+ p->optname = optname;
+ p->msg_box = NULL; /* init the value to avoid unexpected consequences */
+
+ if (optlen > sizeof (p->optval))
+ {
+ optlen = sizeof (p->optval);
+ }
+
+ p->optlen = optlen;
+ int err;
+ int ret = MEMCPY_S (&p->optval, sizeof (p->optval), optval, optlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR ("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ err = sbr_spl_err_to_errno (m->param.err);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle setsockopt failed]fd=%d,err=%d", sk->fd, err);
+ goto error;
+ }
+
+ if (IPPROTO_IP == level && IP_TOS == optname && p->msg_box)
+ {
+ ss_set_msg_box (sbr_get_conn (sk),
+ (mring_handle) ADDR_SHTOL (p->msg_box));
+ }
+
+ SBR_MSG_FREE (m);
+ return 0;
+
+error:
+ sbr_set_sk_errno (sk, err);
+ SBR_MSG_FREE (m);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_getsockopt
+* Description : get sockopt
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* void *optval
+* socklen_t* optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_getsockopt (sbr_socket_t * sk, int level, int optname,
+ void *optval, socklen_t * optlen)
+{
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_GET_SOCK_OPT,
+ MSG_SYN_POST, sk);
+ msg_setgetsockopt *p = (msg_setgetsockopt *) m->buffer;
+ p->extend_member_bit = 0;
+ p->level = level;
+ p->optname = optname;
+
+ if (*optlen > sizeof (p->optval))
+ {
+ *optlen = sizeof (p->optval);
+ }
+
+ p->optlen = *optlen;
+ int err;
+ int ret = MEMCPY_S (&p->optval, sizeof (p->optval), optval, *optlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR ("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+
+ err = sbr_spl_err_to_errno (m->param.err);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle getsockopt failed]fd=%d,err=%d", sk->fd, err);
+ goto error;
+ }
+
+ ret = MEMCPY_S (optval, *optlen, &p->optval.int_optval, *optlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR ("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ err = EINVAL;
+ goto error;
+ }
+
+ SBR_MSG_FREE (m);
+ return 0;
+
+error:
+ sbr_set_sk_errno (sk, err);
+ SBR_MSG_FREE (m);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_close
+* Description : need care msg_box_ref,make sure to finalize this message
+* Input : sbr_socket_t * sk
+* u8 how
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_close (sbr_socket_t * sk, u8 how)
+{
+ data_com_msg *m = sbr_attach_msg (sk,
+ (struct spl_pbuf *)
+ ADDR_SHTOL (sbr_get_fd_share
+ (sk)->recoder.head));
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("attach msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_DELCON,
+ MSG_ASYN_POST, sk);
+ msg_delete_netconn *p = (msg_delete_netconn *) m->buffer;
+ p->extend_member_bit = 0;
+ p->buf = NULL;
+ p->time_started = sys_now ();
+ p->shut = how;
+ p->pid = get_sys_pid ();
+ p->conn = (spl_netconn_t *) ADDR_LTOSH (sbr_get_conn (sk));
+ p->notify_omc = FALSE;
+ p->msg_box_ref = SPL_MSG_BOX_NUM;
+
+ /* to ensure that the last deal with SPL_API_DO_DELCON message */
+ int i;
+ for (i = 0; i < SPL_MSG_BOX_NUM; ++i)
+ {
+ SBR_MSG_POST (m,
+ ss_get_instance_msg_box (ss_get_bind_thread_index
+ (sbr_get_conn (sk)), i));
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_udp_send
+* Description : udp send
+* Input : sbr_socket_t * sk
+* struct netbuf *buf
+* spl_ip_addr_t* local_ip
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_udp_send (sbr_socket_t * sk, struct spl_netbuf *buf,
+ spl_ip_addr_t * local_ip)
+{
+ data_com_msg *m =
+ sbr_attach_msg (sk, (struct spl_pbuf *) ADDR_SHTOL (buf->p));
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("attach msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg_dbg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_SEND,
+ MSG_ASYN_POST, sk);
+ msg_send_buf *p = (msg_send_buf *) m->buffer;
+ p->local_ip.addr = local_ip->addr;
+ int ret = MEMCPY_S (&p->addr, sizeof (spl_ip_addr_t), &buf->addr,
+ sizeof (spl_ip_addr_t));
+ if (ret != 0)
+ {
+ NSSBR_LOGERR ("MEMCPY_S failed]fd=%d,ret=%d", sk->fd, ret);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ SBR_MSG_FREE (m);
+ return -1;
+ }
+
+ p->p = buf->p;
+ p->port = buf->port;
+ p->extend_member_bit = 0;
+ SBR_MSG_POST_RET (m, sbr_get_msg_box (sk), ret);
+
+ if (0 == ret)
+ {
+ return 0;
+ }
+ else
+ {
+ NSSBR_LOGERR ("post msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EAGAIN);
+ return -1;
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_free_recv_buf
+* Description : free recv buf,can't free buf in app
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+sbr_handle_free_recv_buf (sbr_socket_t * sk)
+{
+ data_com_msg *m = sbr_attach_msg (sk,
+ (struct spl_pbuf *)
+ ADDR_SHTOL (sbr_get_fd_share
+ (sk)->recoder.head));
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("attach msg failed]fd=%d", sk->fd);
+ return;
+ }
+
+ sbr_construct_msg_dbg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_PBUF_FREE,
+ MSG_ASYN_POST, sk);
+ msg_free_buf *p = (msg_free_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->buf = sbr_get_fd_share (sk)->recoder.head;
+ sbr_get_fd_share (sk)->recoder.head = NULL;
+ sbr_get_fd_share (sk)->recoder.tail = NULL;
+ sbr_get_fd_share (sk)->recoder.totalLen = 0;
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+}
+
+void
+sbr_handle_free_send_buf (sbr_socket_t * sk, struct spl_pbuf *buf)
+{
+ if (buf != NULL)
+ {
+ data_com_msg *m = sbr_attach_msg (sk, buf);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("attach msg failed]fd=%d", sk->fd);
+ return;
+ }
+
+ sbr_construct_msg_dbg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_PBUF_FREE,
+ MSG_ASYN_POST, sk);
+ msg_free_buf *p = (msg_free_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->buf = (struct spl_pbuf *) ADDR_LTOSH (buf);
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_handle_shutdown
+* Description : shut down
+* Input : sbr_socket_t * sk
+* u8 how
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_handle_shutdown (sbr_socket_t * sk, u8 how)
+{
+ int err;
+ data_com_msg *m = SBR_MSG_MALLOC (sk);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("malloc msg failed]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_CLOSE, MSG_SYN_POST,
+ sk);
+ msg_close *p = (msg_close *) m->buffer;
+ p->extend_member_bit = 0;
+ p->time_started = sys_now ();
+ p->shut = how;
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+ err = sbr_spl_err_to_errno (m->param.err);
+ SBR_MSG_FREE (m);
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("handle getsockopt failed]fd=%d,err=%d", sk->fd, err);
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+
+ return 0;
+}
+
+void
+sbr_handle_tcp_recv (sbr_socket_t * sk, u32 len, struct spl_pbuf *buf)
+{
+ data_com_msg *m = sbr_attach_msg (sk, buf);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("attach msg failed]fd=%d", sk->fd);
+ return;
+ }
+
+ sbr_construct_msg_dbg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_RECV,
+ MSG_ASYN_POST, sk);
+ msg_recv_buf *p = (msg_recv_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->len = len;
+ p->p = (struct spl_pbuf *) ADDR_LTOSH (buf);
+ SBR_MSG_POST (m, sbr_get_msg_box (sk));
+}
+
+int
+sbr_handle_tcp_send (sbr_socket_t * sk, size_t size, struct spl_pbuf *buf,
+ u8 api_flag)
+{
+ int ret;
+ data_com_msg *m = sbr_attach_msg (sk, buf);
+
+ if (!m)
+ {
+ NSSBR_LOGERR ("attach msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, ENOMEM);
+ return -1;
+ }
+
+ sbr_construct_msg_dbg (m, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_WRITE,
+ MSG_ASYN_POST, sk);
+ msg_write_buf *p = (msg_write_buf *) m->buffer;
+ p->extend_member_bit = 0;
+ p->len = size;
+ p->p = (struct spl_pbuf *) ADDR_LTOSH (buf);
+ p->apiflags = api_flag;
+ SBR_MSG_POST_RET (m, sbr_get_msg_box (sk), ret);
+
+ if (0 == ret)
+ {
+ return 0;
+ }
+ else
+ {
+ NSSBR_LOGERR ("post msg failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EAGAIN);
+ return -1;
+ }
+}
+
+/* need delete sbr_handle_app_touch */
+void
+sbr_handle_app_touch (void)
+{
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.h
new file mode 100644
index 0000000..a52d026
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_msg_handler.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 STACKX_MSG_HANDLER_H
+#define STACKX_MSG_HANDLER_H
+#include "stackx_socket.h"
+#include "stackx_ip_addr.h"
+#include "stackx_netbuf.h"
+#include "stackx_spl_share.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define SBR_GET_SOCK_NAME 1
+#define SBR_GET_PEER_NAME 0
+
+int sbr_handle_socket (sbr_socket_t * sk, spl_netconn_type_t type, u8 proto);
+
+int sbr_handle_bind (sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port);
+
+int sbr_handle_listen (sbr_socket_t * sk, int backlog);
+
+int sbr_handle_connect (sbr_socket_t * sk, spl_ip_addr_t * addr, u16 port,
+ spl_ip_addr_t * local_ip);
+
+int sbr_handle_get_name (sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen, u8 cmd);
+
+int sbr_handle_setsockopt (sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen);
+
+int sbr_handle_getsockopt (sbr_socket_t * sk, int level, int optname,
+ void *optval, socklen_t * optlen);
+
+int sbr_handle_close (sbr_socket_t * sk, u8 how);
+
+int sbr_handle_udp_send (sbr_socket_t * sk, struct spl_netbuf *buf,
+ spl_ip_addr_t * local_ip);
+
+void sbr_handle_free_recv_buf (sbr_socket_t * sk);
+
+void sbr_handle_free_send_buf (sbr_socket_t * sk, struct spl_pbuf *buf);
+
+int sbr_handle_shutdown (sbr_socket_t * sk, u8 how);
+
+void sbr_handle_tcp_recv (sbr_socket_t * sk, u32 len, struct spl_pbuf *buf);
+
+int sbr_handle_tcp_send (sbr_socket_t * sk, size_t size, struct spl_pbuf *buf,
+ u8 api_flag);
+
+int sbr_handle_custom_send (sbr_socket_t * sk, struct spl_pbuf *buf,
+ spl_ip_addr_t * src, spl_ip_addr_t * dst, u8 tos);
+
+int sbr_handle_custom_close (sbr_socket_t * sk, spl_ip_addr_t * addr);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c
new file mode 100644
index 0000000..6af2a77
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.c
@@ -0,0 +1,651 @@
+/*
+*
+* 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 <string.h>
+#include <time.h>
+#include "stackx_msg_handler.h"
+#include "stackx_prot_com.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_err.h"
+#include "nstack_securec.h"
+#include "nsfw_rti.h"
+//#include "stackx_custom.h"
+
+#define FAST_SLEEP_TIME 10000
+#define FAST_RETRY_COUNT 100
+#define MAX_WAIT_TIMEOUT 0x7FFFFFFF
+
+/*****************************************************************************
+* Prototype : sbr_getsockopt_sol_socket
+* Description : get sol socket
+* Input : sbr_socket_t * sk
+* int optname
+* void * optval
+* socklen_t optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_getsockopt_sol_socket (sbr_socket_t * sk, int optname, void *optval,
+ socklen_t optlen)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case SO_ERROR:
+ {
+ if (optlen < sizeof (int))
+ {
+ return EINVAL;
+ }
+
+ /* only overwrite ERR_OK or tempoary errors */
+ err = sbr_get_sk_errno (sk);
+
+ if ((0 == err) || (EINPROGRESS == err))
+ {
+ err =
+ sbr_spl_err_to_errno (ss_get_last_errno (sbr_get_conn (sk)));
+ sbr_set_sk_errno (sk, err);
+ }
+ else
+ {
+ sbr_set_sk_errno (sk, 0);
+ }
+
+ *(int *) optval = sbr_get_sk_errno (sk);
+
+ return 0;
+ }
+ case SO_BROADCAST:
+ case SO_KEEPALIVE:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ case SO_REUSEADDR:
+ if (optlen < sizeof (int))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case SO_RCVTIMEO:
+ case SO_SNDTIMEO:
+ if (optlen < sizeof (struct timeval))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case SO_LINGER:
+ if (optlen < sizeof (struct linger))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_getsockopt_ipproto_ip
+* Description : get ipproto ip
+* Input : int optname
+* void * optval
+* socklen_t optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_getsockopt_ipproto_ip (int optname, void *optval, socklen_t optlen)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case IP_TOS:
+ if (optlen < sizeof (u8))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_pick_timeout
+* Description : pick time
+* Input : const void * optval
+* socklen_t optlen
+* i32* timeout
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_pick_timeout (const void *optval, socklen_t optlen, i32 * timeout)
+{
+ if (optlen < sizeof (struct timeval))
+ {
+ return EINVAL;
+ }
+
+ struct timeval *time_val = (struct timeval *) optval;
+ if ((time_val->tv_usec < 0) || (time_val->tv_usec > USEC_TO_SEC))
+ {
+ return EDOM;
+ }
+ else
+ {
+ if (time_val->tv_sec < 0)
+ {
+ *timeout = 0;
+ }
+ else
+ {
+ *timeout = MAX_WAIT_TIMEOUT;
+ if ((time_val->tv_sec != 0) || (time_val->tv_usec != 0))
+ {
+ if (time_val->tv_sec < ((MAX_WAIT_TIMEOUT / 1000) - 1))
+ {
+ *timeout =
+ time_val->tv_sec * 1000 + time_val->tv_usec / 1000;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_setsockopt_sol_socket
+* Description : set sol socket
+* Input : sbr_socket_t * sk
+* int optname
+* const void * optval
+* socklen_t optlen
+* netconn_type_t type
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_setsockopt_sol_socket (sbr_socket_t * sk, int optname, const void *optval,
+ socklen_t optlen, spl_netconn_type_t type)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case SO_REUSEADDR:
+ case SO_BROADCAST:
+ case SO_KEEPALIVE:
+ case SO_RCVBUF:
+ case SO_SNDBUF:
+ if (optlen < sizeof (int))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case SO_RCVTIMEO:
+ err =
+ sbr_pick_timeout (optval, optlen,
+ &sbr_get_fd_share (sk)->recv_timeout);
+ break;
+ case SO_SNDTIMEO:
+ err =
+ sbr_pick_timeout (optval, optlen,
+ &sbr_get_fd_share (sk)->send_timeout);
+ break;
+ case SO_LINGER:
+ if (optlen < sizeof (struct linger))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_setsockopt_ipproto_ip
+* Description : set ipproto ip
+* Input : int optname
+* const void * optval
+* socklen_t optlen
+* netconn_type_t type
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_setsockopt_ipproto_ip (int optname, const void *optval, socklen_t optlen,
+ spl_netconn_type_t type)
+{
+ int err = 0;
+
+ switch (optname)
+ {
+ case IP_TOS:
+ if (optlen < sizeof (u8))
+ {
+ err = EINVAL;
+ }
+
+ break;
+ case IP_MULTICAST_TTL:
+ if (optlen < sizeof (u8))
+ {
+ err = EINVAL;
+ break;
+ }
+
+ if (type != SPL_NETCONN_UDP)
+ {
+ err = EAFNOSUPPORT;
+ break;
+ }
+
+ break;
+ case IP_MULTICAST_IF:
+ if (optlen < sizeof (struct in_addr))
+ {
+ err = EINVAL;
+ break;
+ }
+
+ if (type != SPL_NETCONN_UDP)
+ {
+ err = EAFNOSUPPORT;
+ break;
+ }
+
+ break;
+ case IP_MULTICAST_LOOP:
+ if (optlen < sizeof (u8))
+ {
+ err = EINVAL;
+ break;
+ }
+
+ if (type != SPL_NETCONN_UDP)
+ {
+ err = EAFNOSUPPORT;
+ break;
+ }
+
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+/*****************************************************************************
+* Prototype : sbr_dequeue_buf
+* Description : dequeue buf
+* Input : sbr_socket_t * sk
+* void **buf
+* i32 timeout
+* u8 use_l4_ring
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_dequeue_buf (sbr_socket_t * sk, void **buf, i32 timeout)
+{
+ mring_handle ring = ss_get_recv_ring (sbr_get_conn (sk));
+
+ struct timespec start, end;
+ long timediff;
+ long timediff_sec;
+ long timeout_sec = (long) (timeout / 1000);
+ unsigned int retry_count = 0;
+
+ if (timeout > 0)
+ {
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &start)))
+ {
+ NSSBR_LOGERR ("Failed to get time, errno = %d", errno);
+ }
+ }
+
+ if (!ss_recv_ring_valid (sbr_get_conn (sk)))
+ {
+ NSSBR_LOGDBG ("ring is invalid]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, ENOTCONN);
+ return -1;
+ }
+
+ int dequeue_ret = 0;
+ pid_t pid = get_sys_pid ();
+
+ while (1)
+ {
+ if (ss_is_shut_rd (sbr_get_conn (sk)))
+ {
+ NSSBR_LOGDBG ("is shut rd]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+
+ dequeue_ret = nsfw_mem_ring_dequeue (ring, buf);
+ if (1 == dequeue_ret)
+ {
+ pbuf_set_recycle_flg ((struct spl_pbuf *) *buf, pid); /*release buf hold by app on abnormal exit */
+ return 0;
+ }
+ else if (0 == dequeue_ret)
+ {
+ /*If the peer reset connect, try to receive data only once */
+ if (ss_can_not_recv (sbr_get_conn (sk)))
+ {
+ NS_LOG_CTRL (LOG_CTRL_RECV_QUEUE_FULL, LOGSBR, "NSSBR",
+ NSLOG_WAR, "try to fetch one more time]fd=%d",
+ sk->fd);
+ /**
+ * l4_ring will not be processed here as can_not_recv flag is
+ * set by TCP only.
+ */
+ if (1 == nsfw_mem_ring_dequeue (ring, buf))
+ {
+ pbuf_set_recycle_flg ((struct spl_pbuf *) *buf, pid);
+ return 0;
+ }
+
+ sbr_set_sk_io_errno (sk, ENOTCONN);
+ return -1;
+ }
+
+ int err = ss_get_last_errno (sbr_get_conn (sk));
+ if (SPL_ERR_IS_FATAL (err) || err == ERR_TIMEOUT) /* have to handle ERR_TIMEOUT here, when TCP keepalive timeout. */
+ {
+ NS_LOG_CTRL (LOG_CTRL_RECV_QUEUE_FULL, LOGSBR, "NSSBR",
+ NSLOG_ERR, "connection fatal error!err=%d", err);
+
+ /* l4_ring need to be handled in the future */
+ if (1 == nsfw_mem_ring_dequeue (ring, buf))
+ {
+ pbuf_set_recycle_flg ((struct spl_pbuf *) *buf, pid);
+ return 0;
+ }
+
+ sbr_set_sk_io_errno (sk, sbr_spl_err_to_errno (err));
+ return -1;
+ }
+
+ if (0 > timeout)
+ {
+ sbr_set_sk_io_errno (sk, EWOULDBLOCK);
+ return -1;
+ }
+
+ if (retry_count < FAST_RETRY_COUNT)
+ {
+ sys_sleep_ns (0, FAST_SLEEP_TIME);
+ retry_count++;
+ }
+ else
+ {
+ sys_sleep_ns (0, sbr_get_fd_share (sk)->block_polling_time);
+ }
+
+ if (timeout > 0)
+ {
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &end)))
+ {
+ NSSBR_LOGERR ("Failed to get time, errno = %d", errno);
+ }
+ timediff_sec = end.tv_sec - start.tv_sec;
+ if (timediff_sec >= timeout_sec)
+ {
+ timediff = end.tv_nsec > start.tv_nsec ?
+ (timediff_sec * 1000) + (end.tv_nsec -
+ start.tv_nsec) /
+ USEC_TO_SEC : (timediff_sec * 1000) -
+ ((start.tv_nsec - end.tv_nsec) / USEC_TO_SEC);
+ if (timediff > timeout)
+ {
+ NSSBR_LOGDBG ("recv timeout]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EWOULDBLOCK);
+ return -1;
+ }
+ }
+ }
+ }
+ else
+ {
+ NSSBR_LOGERR ("dequeue failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+ }
+}
+
+int
+sbr_com_peak (sbr_socket_t * sk)
+{
+ NSSBR_LOGERR ("not implement]fd=%d", sk->fd);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_try_lock_recv
+* Description : try lock recv
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_com_try_lock_recv (sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ return common_spinlock_try_lock_with_pid (&sbr_get_fd_share (sk)->recv_lock,
+ get_sys_pid ());
+#else
+ return 1;
+#endif
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_lock_common
+* Description : lock common
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+sbr_com_lock_common (sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ while (!common_spinlock_try_lock_with_pid
+ (&sbr_get_fd_share (sk)->common_lock, get_sys_pid ()))
+ {
+ sys_sleep_ns (0, 0);
+ }
+#endif
+
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_unlock_common
+* Description : unlock common
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+sbr_com_unlock_common (sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ common_spinlock_unlock (&sbr_get_fd_share (sk)->common_lock);
+#endif
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_free_recv_buf
+* Description : free recv buf,can't free buf in app
+* Input : sbr_socket_t * sk
+* struct spl_pbuf *p
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+sbr_com_free_recv_buf (sbr_socket_t * sk, struct spl_pbuf *p)
+{
+ struct spl_pbuf *p_orig = p;
+ if (p)
+ {
+ p->freeNext = NULL;
+ p = (struct spl_pbuf *) ADDR_LTOSH (p);
+
+ if (sbr_get_fd_share (sk)->recoder.totalLen > 0)
+ {
+ ((struct spl_pbuf *)
+ ADDR_SHTOL (sbr_get_fd_share (sk)->recoder.tail))->freeNext = p;
+ sbr_get_fd_share (sk)->recoder.tail = p;
+ }
+ else
+ {
+ sbr_get_fd_share (sk)->recoder.head = p;
+ sbr_get_fd_share (sk)->recoder.tail = p;
+ }
+
+ sbr_get_fd_share (sk)->recoder.totalLen++;
+ }
+
+ /* send MSG only if it's a big packet or number of packets larger than 32 */
+ if ((p_orig && p_orig->tot_len > MAX_RECV_FREE_LEN) ||
+ (sbr_get_fd_share (sk)->recoder.totalLen >= MAX_RECV_FREE_BUF))
+ {
+ sbr_handle_free_recv_buf (sk);
+ }
+
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_sockaddr_and_len
+* Description : get addr and len
+* Input : u16 port
+* spl_ip_addr_t * ipaddr
+* struct sockaddr * addr
+* socklen_t * addrlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_get_sockaddr_and_len (u16 port, spl_ip_addr_t * ipaddr,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ int ret;
+ struct sockaddr_in sin;
+
+ ret = MEMSET_S (&sin, sizeof (sin), 0, sizeof (sin));
+ if (0 != ret)
+ {
+ NSSBR_LOGERR ("MEMSET_S failed]ret=%d.", ret);
+ return -1;
+ }
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons (port);
+ inet_addr_from_ipaddr (&sin.sin_addr, ipaddr);
+ if (*addrlen > sizeof (struct sockaddr))
+ {
+ *addrlen = sizeof (struct sockaddr);
+ }
+
+ if (*addrlen > 0)
+ {
+ ret = MEMCPY_S (addr, sizeof (struct sockaddr), &sin, *addrlen);
+ if (0 != ret)
+ {
+ NSSBR_LOGERR ("MEMCPY_S failed]ret=%d", ret);
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_set_app_info
+* Description : set app info to netconn
+* Input : sbr_socket_t * sk
+* void* appinfo
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+sbr_com_set_app_info (sbr_socket_t * sk, void *appinfo)
+{
+ return;
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h
new file mode 100644
index 0000000..054393b
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_prot_com.h
@@ -0,0 +1,159 @@
+/*
+*
+* 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 STACKX_PROT_COM_H
+#define STACKX_PROT_COM_H
+#include "stackx_socket.h"
+#include "stackx_ip_addr.h"
+#include "stackx_res_mgr.h"
+#include "stackx_pbuf.h"
+#include "stackx_macro.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define MAX_RECV_FREE_BUF 32
+#define MAX_RECV_FREE_LEN (SPL_FRAME_MTU - SPL_IP_HLEN)
+#define USEC_TO_SEC 1000000
+
+#ifndef NSTACK_SOCKOPT_CHECK
+#define NSTACK_SOCKOPT_CHECK
+/* setsockopt level type*/
+enum
+{
+ NSTACK_SOCKOPT = 0xff02
+};
+/*setsockopt optname type*/
+enum
+{
+ NSTACK_SEM_SLEEP = 0X001
+};
+#endif
+
+#define sbr_malloc_tx_pbuf(len, offset) sbr_malloc_pbuf(sbr_get_tx_pool(), len, TX_MBUF_MAX_LEN, offset)
+
+static inline int
+sbr_spl_err_to_errno (i32 err)
+{
+ static int table[] = {
+ 0, /* ERR_OK 0 No error, everything OK. */
+ ENOMEM, /* ERR_MEM -1 Out of memory error. */
+ ENOBUFS, /* ERR_BUF -2 Buffer error. */
+ ETIMEDOUT, /* ERR_TIMEOUT -3 Timeout */
+ EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
+ EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
+ EINVAL, /* ERR_VAL -6 Illegal value. */
+ EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
+ EADDRINUSE, /* ERR_USE -8 Address in use. */
+ EISCONN, /* ERR_ISCONN -9 Already connected. */
+ ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
+ ECONNRESET, /* ERR_RST -11 Connection reset. */
+ ENOTCONN, /* ERR_CLSD -12 Connection closed. */
+ ENOTCONN, /* ERR_CONN -13 Not connected. */
+ EIO, /* ERR_ARG -14 Illegal argument. */
+ -1, /* ERR_IF -15 Low-level netif error */
+ EALREADY, /*ERR_ALREADY -16 previous connect attemt has not yet completed */
+ EPROTOTYPE, /*ERR_PROTOTYPE -17 prototype error or some other generic error.
+ the operation is not allowed on current socket */
+ EINVAL, /* ERR_CALLBACK -18 callback error */
+ EADDRNOTAVAIL, /* ERR_CANTASSIGNADDR -19 Cannot assign requested address */
+ EIO, /* ERR_CONTAINER_ID -20 Illegal container id */
+ ENOTSOCK, /*ERR_NOTSOCK -21 not a socket */
+ -1, /* ERR_CLOSE_WAIT -22 closed in established state */
+ EPROTONOSUPPORT, /* ERR_EPROTONOSUPPORT -23 Protocol not supported */
+ ECONNABORTED /* ERR_FAULTRECOVERY -24 SPL just recovered from a fatal fault */
+ };
+
+ if (((-(err)) >= 0)
+ && (-(err)) < (i32) (sizeof (table) / sizeof (table[0])))
+ {
+ return table[-(err)];
+ }
+ else
+ {
+ return EIO;
+ }
+}
+
+int sbr_getsockopt_sol_socket (sbr_socket_t * sk, int optname, void *optval,
+ socklen_t optlen);
+int sbr_getsockopt_ipproto_ip (int optname, void *optval, socklen_t optlen);
+int sbr_setsockopt_sol_socket (sbr_socket_t * sk, int optname,
+ const void *optval, socklen_t optlen,
+ spl_netconn_type_t type);
+int sbr_setsockopt_ipproto_ip (int optname, const void *optval,
+ socklen_t optlen, spl_netconn_type_t type);
+int sbr_dequeue_buf (sbr_socket_t * sk, void **buf, i32 timeout);
+int sbr_com_peak (sbr_socket_t * sk);
+int sbr_com_try_lock_recv (sbr_socket_t * sk);
+/*****************************************************************************
+* Prototype : sbr_com_lock_recv
+* Description : lock recv
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+sbr_com_lock_recv (sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ while (!common_spinlock_try_lock_with_pid
+ (&sbr_get_fd_share (sk)->recv_lock, get_sys_pid ()))
+ {
+ sys_sleep_ns (0, 0);
+ }
+#endif
+
+}
+
+/*****************************************************************************
+* Prototype : sbr_com_unlock_recv
+* Description : unlock recv
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+sbr_com_unlock_recv (sbr_socket_t * sk)
+{
+#ifdef SBR_USE_LOCK
+ common_spinlock_unlock (&sbr_get_fd_share (sk)->recv_lock);
+#endif
+}
+
+void sbr_com_lock_common (sbr_socket_t * sk);
+void sbr_com_unlock_common (sbr_socket_t * sk);
+void sbr_com_free_recv_buf (sbr_socket_t * sk, struct spl_pbuf *p);
+int sbr_get_sockaddr_and_len (u16 port, spl_ip_addr_t * ip_addr,
+ struct sockaddr *addr, socklen_t * addrlen);
+void sbr_com_set_app_info (sbr_socket_t * sk, void *appinfo);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c b/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c
new file mode 100644
index 0000000..94ef483
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_protocol_api.c
@@ -0,0 +1,94 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "sbr_protocol_api.h"
+#include "stackx_epoll_api.h"
+#include "stackx_socket.h"
+#include "stackx_res_mgr.h"
+#include "stackx_common_opt.h"
+#include "common_mem_api.h"
+#include "stackx_event.h"
+
+extern sbr_fdopt tcp_fdopt;
+extern sbr_fdopt udp_fdopt;
+extern sbr_fdopt raw_fdopt;
+extern sbr_fdopt custom_fdopt;
+
+/*****************************************************************************
+* Prototype : sbr_init_protocol
+* Description : init protocol
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_init_protocol ()
+{
+ return sbr_init_stackx ();
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_fdopt
+* Description : get fdopt by domain type protocol
+* Input : int domain
+* int type
+* int protocol
+* Output : None
+* Return Value : sbr_fdopt*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+sbr_fdopt *
+sbr_get_fdopt (int domain, int type, int protocol)
+{
+ if (domain != AF_INET)
+ {
+ NSSBR_LOGERR ("domain is not AF_INET]domain=%d", domain);
+ sbr_set_errno (EAFNOSUPPORT);
+ return NULL;
+ }
+
+ sbr_fdopt *fdopt = NULL;
+
+ switch (type & (~(O_NONBLOCK | SOCK_CLOEXEC)))
+ {
+ case SOCK_DGRAM:
+ fdopt = &udp_fdopt;
+ break;
+ case SOCK_STREAM:
+ fdopt = &tcp_fdopt;
+ break;
+
+ default:
+ NSSBR_LOGDBG ("type is unknown]type=%d", type);
+ sbr_set_errno (ESOCKTNOSUPPORT);
+ return NULL;
+ }
+
+ return fdopt;
+}
+
+/* app send its version info to nStackMain */
+extern void sbr_handle_app_touch (void);
+void
+sbr_app_touch_in (void)
+{
+ sbr_handle_app_touch ();
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c
new file mode 100644
index 0000000..331eee1
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.c
@@ -0,0 +1,246 @@
+/*
+*
+* 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 "stackx_res_mgr.h"
+#include "stackx_common.h"
+#include "nstack_securec.h"
+#include "nsfw_msg.h"
+#include "stackx_common.h"
+#include "nsfw_mgr_com_api.h"
+#include "stackx_cfg.h"
+#include "nsfw_maintain_api.h"
+//#include "stackx_dfx_api.h"
+#include "stackx_app_res.h"
+
+sbr_share_group g_share_group = { 0 };
+
+#define SLOW_SLEEP_TIME 500000
+
+NSTACK_STATIC inline void
+sbr_reset_fd_share (sbr_fd_share * fd_share)
+{
+ common_mem_spinlock_init (&fd_share->recv_lock);
+ common_mem_spinlock_init (&fd_share->common_lock);
+ fd_share->err = 0;
+ fd_share->lastoffset = 0;
+ fd_share->lastdata = NULL;
+ fd_share->recoder.head = NULL;
+ fd_share->recoder.tail = NULL;
+ fd_share->recoder.totalLen = 0;
+ fd_share->recv_timeout = 0;
+ fd_share->send_timeout = 0;
+ fd_share->rcvlowat = 1;
+ fd_share->block_polling_time = SLOW_SLEEP_TIME;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_tx_pool
+* Description : get tx buf pool
+* Input : None
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int
+sbr_init_tx_pool ()
+{
+ mpool_handle pool[1];
+ pool[0] = NULL;
+
+ (void) sbr_malloc_tx_pool (get_sys_pid (), pool, 1);
+ if (pool[0])
+ {
+ g_share_group.tx_pool = pool[0];
+ return 0;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_app_res
+* Description : get msg, conn pool
+* Input : None
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+NSTACK_STATIC int
+sbr_init_app_res ()
+{
+ g_share_group.conn_pool = sbr_get_instance_conn_pool (0);
+ if (!g_share_group.conn_pool)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/*=========== get share config for app =============*/
+NSTACK_STATIC inline int
+get_share_config ()
+{
+ static nsfw_mem_name g_cfg_mem_info =
+ { NSFW_SHMEM, NSFW_PROC_MAIN, NSTACK_SHARE_CONFIG };
+
+ mzone_handle base_cfg_mem = nsfw_mem_zone_lookup (&g_cfg_mem_info);
+ if (NULL == base_cfg_mem)
+ {
+ NSSOC_LOGERR ("get config share mem failed.");
+ return -1;
+ }
+
+ if (get_share_cfg_from_mem (base_cfg_mem) < 0)
+ {
+ NSSOC_LOGERR ("get share config failed.");
+ return -1;
+ }
+
+ NSSOC_LOGDBG ("get share config success.");
+ return 0;
+}
+
+int
+nstack_set_share_config ()
+{
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_init_stackx
+* Description : init stackx res
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_init_stackx ()
+{
+ sbr_init_cfg ();
+ if (get_share_config () < 0)
+ {
+ NSSBR_LOGERR ("get_share_config failed");
+ return -1;
+ }
+
+ if (sbr_attach_group_array () != 0)
+ {
+ NSSBR_LOGERR ("sbr_attach_group_array failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG ("sbr_attach_group_array ok");
+
+ if (sbr_init_tx_pool () != 0)
+ {
+ NSSBR_LOGERR ("init tx pool failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG ("init tx pool ok");
+
+ if (sbr_init_app_res () != 0)
+ {
+ NSSBR_LOGERR ("sbr_init_app_res failed");
+ return -1;
+ }
+
+ NSSBR_LOGDBG ("sbr_init_app_res ok");
+ NSSBR_LOGDBG ("sbr_init_stackx ok");
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_malloc_conn_for_sk
+* Description : malloc netconn for sk,need add pid
+* Input : sbr_socket_t* sk
+* netconn_type_t type
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_malloc_conn_for_sk (sbr_socket_t * sk, spl_netconn_type_t type)
+{
+ spl_netconn_t *conn = ss_malloc_conn_app (g_share_group.conn_pool, type);
+
+ if (!conn)
+ {
+ NSSBR_LOGERR ("malloc conn failed]fd=%d", sk->fd);
+ sbr_set_errno (ENOBUFS);
+ return -1;
+ }
+
+ NSSBR_LOGINF ("malloc conn ok]fd=%d,conn=%p", sk->fd, conn);
+
+ u16 thread_index = 0;
+ ss_set_bind_thread_index (conn, thread_index);
+ ss_set_msg_box (conn, ss_get_instance_msg_box (thread_index, 0));
+
+ sbr_fd_share *fd_share = (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE);
+ sbr_reset_fd_share (fd_share);
+
+ sk->stack_obj = (void *) conn;
+ sk->sk_obj = (void *) fd_share;
+ return 0;
+}
+
+int
+sbr_init_conn_for_accept (sbr_socket_t * sk, spl_netconn_t * conn)
+{
+ if (!conn)
+ {
+ sbr_set_sk_errno (sk, ENOBUFS);
+ return -1;
+ }
+
+ NSSBR_LOGINF ("accept conn ok]fd=%d,conn=%p,private_data=%p", sk->fd, conn,
+ conn->private_data);
+
+ if (ss_add_pid (conn, get_sys_pid ()) < 0)
+ {
+ NSSBR_LOGERR ("ss_add_pid failed]fd=%d", sk->fd);
+ }
+
+ ss_set_accept_from (conn, NULL); /* need clear flag */
+
+ sbr_fd_share *fd_share = (sbr_fd_share *) ((char *) conn + SS_NETCONN_SIZE);
+ sbr_reset_fd_share (fd_share);
+
+ sk->stack_obj = (void *) conn;
+ sk->sk_obj = (void *) fd_share;
+
+ return 0;
+}
+
+void
+sbr_free_conn_from_sk (sbr_socket_t * sk)
+{
+ ss_free_conn (sbr_get_conn (sk));
+ sk->stack_obj = NULL;
+ sk->sk_obj = NULL;
+ NSSBR_LOGDBG ("free conn ok]fd=%d", sk->fd);
+}
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h
new file mode 100644
index 0000000..e139644
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_res_mgr.h
@@ -0,0 +1,69 @@
+/*
+*
+* 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 STACKX_RES_MGR_H
+#define STACKX_RES_MGR_H
+#include "stackx_socket.h"
+#include "stackx_ip_tos.h"
+#include "stackx_tx_box.h"
+#include "stackx_app_res.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef struct
+{
+ mring_handle conn_pool;
+ mpool_handle tx_pool;
+} sbr_share_group;
+
+extern sbr_share_group g_share_group;
+
+static inline mpool_handle
+sbr_get_tx_pool ()
+{
+ return g_share_group.tx_pool;
+}
+
+static inline mring_handle
+sbr_get_conn_pool ()
+{
+ return (mring_handle) ADDR_LTOSH (g_share_group.conn_pool);
+}
+
+static inline mring_handle
+sbr_get_spl_msg_box (sbr_socket_t * sk, u8 tos)
+{
+ return
+ ss_get_instance_msg_box (ss_get_bind_thread_index (sbr_get_conn (sk)),
+ stackx_get_prio (tos));
+}
+
+int sbr_init_stackx ();
+int sbr_malloc_conn_for_sk (sbr_socket_t * sk, spl_netconn_type_t type);
+int sbr_init_conn_for_accept (sbr_socket_t * sk, spl_netconn_t * conn);
+void sbr_free_conn_from_sk (sbr_socket_t * sk);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_socket.h b/stacks/lwip_stack/lwip_src/socket/stackx_socket.h
new file mode 100644
index 0000000..e344535
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_socket.h
@@ -0,0 +1,141 @@
+/*
+*
+* 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 STACKX_SOCKET_H
+#define STACKX_SOCKET_H
+#include "sbr_protocol_api.h"
+#include "stackx_spl_share.h"
+#include "nstack_log.h"
+#include "stackx_pbuf.h"
+#include "common_mem_spinlock.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef struct
+{
+ PRIMARY_ADDR struct spl_pbuf *head;
+ PRIMARY_ADDR struct spl_pbuf *tail;
+ int totalLen;
+} sbr_recvbuf_recoder;
+
+/* need fork and recycle */
+typedef struct
+{
+ common_mem_spinlock_t recv_lock;
+ common_mem_spinlock_t common_lock;
+ PRIMARY_ADDR void *lastdata;
+ u32 lastoffset;
+ sbr_recvbuf_recoder recoder;
+ i32 recv_timeout;
+ i32 send_timeout;
+ i32 rcvlowat;
+ int err;
+ u64 block_polling_time;
+ i64 extend_member_bit;
+} sbr_fd_share;
+
+/* check sbr_fd_share size */
+SIZE_OF_TYPE_NOT_LARGER_THAN (sbr_fd_share, SBR_FD_SIZE);
+
+#define sbr_get_fd_share(sk) ((sbr_fd_share*)sk->sk_obj)
+
+#define sbr_get_conn(sk) ((spl_netconn_t*)sk->stack_obj)
+
+#define sbr_get_msg_box(sk) ss_get_msg_box(sbr_get_conn(sk))
+
+/*****************************************************************************
+* Prototype : sbr_set_sk_errno
+* Description : set errno for sk
+* Input : sbr_socket_t * sk
+* int err
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+sbr_set_sk_errno (sbr_socket_t * sk, int err)
+{
+ sbr_get_fd_share (sk)->err = err;
+ if (err != 0)
+ {
+ if (sbr_get_conn (sk))
+ {
+ NSSBR_LOGERR ("fd=%d,errno=%d,conn=%p,private_data=%p", sk->fd, err,
+ sbr_get_conn (sk),
+ ss_get_private_data (sbr_get_conn (sk)));
+ }
+
+ sbr_set_errno (err);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_set_sk_io_errno
+* Description : set errno for sk in send/recv func, in case of too many logs
+* Input : sbr_socket_t * sk
+* int err
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+sbr_set_sk_io_errno (sbr_socket_t * sk, int err)
+{
+ sbr_get_fd_share (sk)->err = err;
+ if (err != 0)
+ {
+ if (sbr_get_conn (sk))
+ {
+ NSSBR_LOGDBG ("fd=%d,errno=%d,conn=%p,private_data=%p", sk->fd, err,
+ sbr_get_conn (sk),
+ ss_get_private_data (sbr_get_conn (sk)));
+ }
+
+ sbr_set_errno (err);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_get_sk_errno
+* Description : get sk's errno
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_get_sk_errno (sbr_socket_t * sk)
+{
+ return sbr_get_fd_share (sk)->err;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c b/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c
new file mode 100644
index 0000000..c64dc7b
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_tcp.c
@@ -0,0 +1,1696 @@
+/*
+*
+* 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 "stackx_prot_com.h"
+#include "stackx_msg_handler.h"
+#include "stackx_pbuf.h"
+#include "stackx_epoll_api.h"
+#include "nstack_securec.h"
+#include "common_pal_bitwide_adjust.h"
+#include "common_mem_mbuf.h"
+#include "stackx_spl_share.h"
+#include "stackx_err.h"
+#include "stackx_cfg.h"
+#include "spl_opt.h"
+//#include "stackx_tcp_sctl.h"
+#include "stackx_tcp_opt.h"
+//#include "stackx_dfx_api.h"
+#include "stackx_spl_msg.h"
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+
+static void
+sbr_tcp_init_conn (spl_netconn_t * conn)
+{
+ conn->tcp_sndbuf = CONN_TCP_MEM_DEF_LINE;
+ conn->conn_pool = sbr_get_conn_pool ();
+}
+
+/* need close after accept failed */
+static void
+sbr_tcp_accept_failed (sbr_socket_t * sk)
+{
+ (void) sbr_handle_close (sk, 0);
+ sk->stack_obj = NULL;
+ sk->sk_obj = NULL;
+}
+
+NSTACK_STATIC int
+sbr_tcp_socket (sbr_socket_t * sk, int domain, int type, int protocol)
+{
+ int err = 0;
+
+ if (sbr_malloc_conn_for_sk (sk, SPL_NETCONN_TCP) != 0)
+ {
+ return -1;
+ }
+
+ sbr_tcp_init_conn (sbr_get_conn (sk));
+
+ err = sbr_handle_socket (sk, SPL_NETCONN_TCP, 0);
+ if (0 == err)
+ {
+ /* Prevent automatic window updates, we do this on our own! */
+ ss_set_noautorecved_flag (sbr_get_conn (sk), 1);
+
+ ss_set_nonblock_flag (sbr_get_conn (sk), (type & O_NONBLOCK));
+
+ ss_add_recv_event (sbr_get_conn (sk));
+
+ ss_set_send_event (sbr_get_conn (sk), 1);
+
+ NSSBR_LOGINF ("add write and read events]fd=%d", sk->fd);
+
+ return 0;
+ }
+ else
+ {
+ sbr_free_conn_from_sk (sk);
+ return err;
+ }
+}
+
+NSTACK_STATIC int
+sbr_tcp_bind (sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+ NSSBR_LOGINF ("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa (addr_in->sin_addr), ntohs (addr_in->sin_port),
+ sbr_get_conn (sk), ss_get_private_data (sbr_get_conn (sk)));
+ spl_ip_addr_t local_addr;
+ inet_addr_to_ipaddr (&local_addr, &addr_in->sin_addr);
+ u16 local_port = addr_in->sin_port;
+ return sbr_handle_bind (sk, &local_addr, ntohs (local_port));
+}
+
+NSTACK_STATIC int
+sbr_tcp_listen (sbr_socket_t * sk, int backlog)
+{
+ ss_set_is_listen_conn (sbr_get_conn (sk), 1);
+ return sbr_handle_listen (sk, backlog);
+}
+
+static inline int
+sbr_tcp_recv_is_timeout (sbr_socket_t * sk, struct timespec *starttm)
+{
+ struct timespec currtm;
+ i64 timediff_ms, timediff_sec;
+ i64 timeout_thr_ms, timeout_thr_sec;
+
+ timeout_thr_ms = sbr_get_fd_share (sk)->recv_timeout;
+ if (0 == timeout_thr_ms)
+ {
+ return ERR_OK;
+ }
+
+ timeout_thr_sec = (i64) (timeout_thr_ms / 1000);
+
+ /* Handle system time change side-effects */
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &currtm)))
+ {
+ NSSBR_LOGERR ("Failed to get time, errno = %d", errno);
+ }
+
+ timediff_sec = currtm.tv_sec - starttm->tv_sec;
+ if (timediff_sec >= timeout_thr_sec)
+ {
+ timediff_ms = currtm.tv_nsec > starttm->tv_nsec ?
+ (timediff_sec * 1000) + (currtm.tv_nsec -
+ starttm->tv_nsec) /
+ USEC_TO_SEC : (timediff_sec * 1000) -
+ ((starttm->tv_nsec - currtm.tv_nsec) / USEC_TO_SEC);
+
+ /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value
+ will be negetive if still 0.5 ms is not elapsed. this is intended and we should
+ not typecast to any unsigned type during this below if check */
+ if (timediff_ms > timeout_thr_ms)
+ {
+ sbr_set_sk_errno (sk, ETIMEDOUT);
+ return ETIMEDOUT;
+ }
+ }
+
+ return ERR_OK;
+}
+
+static inline int
+sbr_tcp_wait_new_conn (sbr_socket_t * sk, void **new_buf)
+{
+ int ret = 0;
+ int elem_num;
+ u32 timeout_thr_sec;
+ struct timespec starttm = { 0, 0 };
+ unsigned int retry_count = 0;
+ mring_handle ring = NULL;
+
+#define FAST_SLEEP_TIME 10000
+#define SLOW_SLEEP_TIME 500000
+#define FAST_RETRY_COUNT 100
+
+ ring = ss_get_recv_ring (sbr_get_conn (sk)); //clear codeDEX warning , CID:24284
+ timeout_thr_sec = sbr_get_fd_share (sk)->recv_timeout / 1000;
+ if (0 != timeout_thr_sec)
+ {
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &starttm)))
+ {
+ NSSBR_LOGERR ("Failed to get time, errno = %d", errno);
+ }
+ }
+
+ while (1)
+ {
+ if (ss_is_shut_rd (sbr_get_conn (sk)))
+ {
+ sbr_set_sk_errno (sk, EINVAL);
+ ret = EINVAL;
+ break;
+ }
+
+ elem_num = nsfw_mem_ring_dequeue (ring, new_buf);
+ if (1 == elem_num)
+ {
+ break;
+ }
+ else if (0 == elem_num)
+ {
+ ret = sbr_tcp_recv_is_timeout (sk, &starttm);
+ if (0 != ret)
+ {
+ break;
+ }
+
+ /* reduce CPU usage in blocking mode- Begin */
+ if (retry_count < FAST_RETRY_COUNT)
+ {
+ sys_sleep_ns (0, FAST_SLEEP_TIME);
+ retry_count++;
+ }
+ else
+ {
+ sys_sleep_ns (0, sbr_get_fd_share (sk)->block_polling_time);
+ }
+
+ continue;
+ }
+ else
+ {
+ sbr_set_sk_errno (sk, EINVAL);
+ ret = EINVAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+NSTACK_STATIC inline int
+sbr_tcp_get_sockaddr (sbr_socket_t * sk, struct sockaddr *addr,
+ socklen_t * addrlen)
+{
+ int ret;
+ spl_netconn_t *conn = sbr_get_conn (sk);
+
+ ret = (addr
+ && addrlen) ? sbr_get_sockaddr_and_len (ss_get_remote_port (conn),
+ ss_get_remote_ip (conn),
+ addr, addrlen) : 0;
+ if (0 != ret)
+ {
+ sbr_set_sk_io_errno (sk, EINVAL);
+ NSSBR_LOGERR ("sbr_tcp_get_sockaddr]fd=%d", sk->fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+sbr_tcp_accept_socket (sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ int err;
+ spl_netconn_t *newconn = NULL;
+
+ err = sbr_tcp_wait_new_conn (sk, (void **) &newconn);
+ if (ERR_OK != err)
+ {
+ return err;
+ }
+
+ err = sbr_init_conn_for_accept (new_sk, newconn);
+ if (ERR_OK != err)
+ {
+ /*When conn is null, return err; then do not need to free conn */
+ return err;
+ }
+
+ err = sbr_tcp_get_sockaddr (new_sk, addr, addrlen);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR ("sbr_get_sockaddr_and_socklen]ret=%d.", err);
+ sbr_tcp_accept_failed (new_sk);
+ return -1;
+ }
+
+ NSSBR_LOGINF
+ ("return]listen fd=%d,listen conn=%p,listen private_data=%p,accept fd=%d,accept conn=%p,accept private_data=%p",
+ sk->fd, sbr_get_conn (sk), ss_get_private_data (sbr_get_conn (sk)),
+ new_sk->fd, sbr_get_conn (new_sk),
+ ss_get_private_data (sbr_get_conn (new_sk)));
+
+ //ip_addr_info_print(SOCKETS_DEBUG, &sbr_get_conn(new_sk)->share_remote_ip);
+
+ /* test_epollCtl_003_001: Accept a conn. Add epoll_ctl with IN event and
+ send a msg from peer. The event will be given once epoll_wait is called.
+ Now, modify to IN|OUT. Calling epoll_event should return immediately since
+ the socket is writable. Currently, returns 0 events.
+ This issue is fixed here
+ */
+
+ /* Prevent automatic window updates, we do this on our own! */
+ ss_set_noautorecved_flag (sbr_get_conn (new_sk), 1);
+
+ ss_set_send_event (sbr_get_conn (new_sk), 1);
+
+ /* don't set conn->last_err: it's only ERR_OK, anyway */
+ return ERR_OK;
+}
+
+NSTACK_STATIC int
+sbr_tcp_accept (sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ int err;
+
+ /* If conn is not in listen state then return failure with error code: EINVAL(22) */
+ if (!ss_is_listen_state (sbr_get_conn (sk)))
+ {
+ NSSBR_LOGERR ("fd is not listening for connections]fd=%d,err=%d",
+ sk->fd, EINVAL);
+ sbr_set_sk_errno (sk, EINVAL);
+
+ return -1;
+ }
+
+ if (ss_is_nonblock_flag (sbr_get_conn (sk))
+ && (0 >= ss_get_recv_event (sbr_get_conn (sk))))
+ {
+ NSSBR_LOGERR ("fd is nonblocking and rcvevent<=0]fd=%d,err=%d", sk->fd,
+ EWOULDBLOCK);
+ sbr_set_sk_errno (sk, EWOULDBLOCK);
+
+ return -1;
+ }
+
+ err = ss_get_last_errno (sbr_get_conn (sk));
+ if (SPL_ERR_IS_FATAL (err))
+ {
+ /* don't recv on fatal errors: this might block the application task
+ waiting on acceptmbox forever! */
+ sbr_set_sk_errno (sk, sbr_spl_err_to_errno (err));
+
+ return -1;
+ }
+
+ /* wait for a new connection */
+ err = sbr_tcp_accept_socket (sk, new_sk, addr, addrlen);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR ("sbr_tcp_accept_socket failed]fd=%d,err=%d", sk->fd, err);
+
+ return -1;
+ }
+
+ /* Prevent automatic window updates, we do this on our own! */
+ ss_sub_recv_event (sbr_get_conn (sk));
+
+ sbr_set_sk_errno (sk, ERR_OK);
+
+ /* test_epollCtl_003_001: Accept a conn. Add epoll_ctl with IN event and
+ send a msg from peer. The event will be given once epoll_wait is called.
+ Now, modify to IN|OUT. Calling epoll_event should return immediately since
+ the socket is writable. Currently, returns 0 events.
+ This issue is fixed here
+ */
+
+ ss_set_send_event (sbr_get_conn (new_sk), 1);
+
+ return new_sk->fd;
+}
+
+NSTACK_STATIC int
+sbr_tcp_accept4 (sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen, int flags)
+{
+ int fd = sbr_tcp_accept (sk, new_sk, addr, addrlen);
+
+ if (0 > fd)
+ {
+ return fd;
+ }
+
+ if (flags & O_NONBLOCK)
+ {
+ int opts = new_sk->fdopt->fcntl (new_sk, F_GETFL, 0);
+ if (opts < 0)
+ {
+ NSSBR_LOGERR ("sbr_tcp_fcntl(sock,GETFL)");
+ sbr_tcp_accept_failed (new_sk);
+ return -1;
+ }
+
+ opts = opts | O_NONBLOCK;
+
+ if (new_sk->fdopt->fcntl (new_sk, F_SETFL, opts) < 0)
+
+ {
+ NSSBR_LOGERR ("sbr_tcp_fcntl(sock,F_SETFL,opts)");
+ sbr_tcp_accept_failed (new_sk);
+ return -1;
+ }
+ }
+
+ return new_sk->fd;
+}
+
+NSTACK_STATIC int
+sbr_tcp_connect (sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+
+ NSSBR_LOGINF ("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa (addr_in->sin_addr), ntohs (addr_in->sin_port),
+ sbr_get_conn (sk), ss_get_private_data (sbr_get_conn (sk)));
+ spl_ip_addr_t remote_addr;
+
+ inet_addr_to_ipaddr (&remote_addr, &addr_in->sin_addr);
+ u16 remote_port = addr_in->sin_port;
+
+ spl_ip_addr_t local_addr;
+ if (IPADDR_ANY == ss_get_local_ip (sbr_get_conn (sk))->addr)
+ {
+ if (sbr_get_src_ip (remote_addr.addr, &local_addr.addr) != 0)
+ {
+ sbr_set_sk_errno (sk, EHOSTUNREACH);
+ NSSBR_LOGERR ("get src ip failed]fd=%d", sk->fd);
+ return -1;
+ }
+ }
+
+ if (sbr_handle_connect (sk, &remote_addr, ntohs (remote_port), &local_addr)
+ != 0)
+ {
+ NSSBR_LOGERR ("fail]fd=%d", sk->fd);
+ return -1;
+ }
+
+ if (ss_is_shut_rd (sbr_get_conn (sk)))
+ {
+ NSSBR_LOGERR ("shut_rd]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ECONNRESET);
+ return -1;
+ }
+
+ NSSBR_LOGINF ("succeeded]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ERR_OK);
+
+ return 0;
+}
+
+static u8 netconn_shutdown_opt[] = {
+ SPL_NETCONN_SHUT_RD,
+ SPL_NETCONN_SHUT_WR,
+ SPL_NETCONN_SHUT_RDWR
+};
+
+NSTACK_STATIC int
+sbr_tcp_shutdown (sbr_socket_t * sk, int how)
+{
+ err_t err;
+
+ if (ss_is_listen_state (sbr_get_conn (sk)))
+ {
+ return 0;
+ }
+
+ ss_set_shut_status (sbr_get_conn (sk), how);
+
+ err = sbr_handle_shutdown (sk, netconn_shutdown_opt[how]);
+
+ return (err == ERR_OK ? 0 : -1);
+}
+
+NSTACK_STATIC int
+sbr_tcp_getsockname (sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+
+ NSSBR_LOGINF ("sockname]fd=%d,tcp_state=%d", sk->fd,
+ ss_get_tcp_state (sbr_get_conn (sk)));
+
+ return sbr_handle_get_name (sk, name, namelen, SBR_GET_SOCK_NAME);
+}
+
+NSTACK_STATIC int
+sbr_tcp_getpeername (sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+
+ if (SPL_CLOSED == ss_get_tcp_state (sbr_get_conn (sk)))
+ {
+ NSSBR_LOGERR ("connection not exist]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, ENOTCONN);
+ return -1;
+ }
+
+ NSSBR_LOGINF ("peername]fd=%d,tcp_state=%d", sk->fd,
+ ss_get_tcp_state (sbr_get_conn (sk)));
+
+ return sbr_handle_get_name (sk, name, namelen, SBR_GET_PEER_NAME);
+}
+
+static int
+sbr_getsockopt_ipproto_tcp (int optname, void *optval, socklen_t optlen)
+{
+ int err = ERR_OK;
+
+ switch (optname)
+ {
+ case SPL_TCP_NODELAY:
+ break;
+ case SPL_TCP_KEEPIDLE:
+ case SPL_TCP_KEEPINTVL:
+ case SPL_TCP_KEEPCNT:
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+NSTACK_STATIC int inline
+sbr_tcp_set_sockopt_err (sbr_socket_t * sk, int err)
+{
+ if (ENOPROTOOPT == err)
+ {
+ return 0;
+ }
+ else
+ {
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+}
+
+NSTACK_STATIC int inline
+sbr_tcp_get_sockopt_err (sbr_socket_t * sk, int err)
+{
+ sbr_set_sk_errno (sk, err);
+ return -1;
+}
+
+NSTACK_STATIC int
+sbr_tcp_getsockopt (sbr_socket_t * sk, int level, int optname, void *optval,
+ socklen_t * optlen)
+{
+ int err = 0;
+
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err = sbr_getsockopt_sol_socket (sk, optname, optval, *optlen);
+ break;
+
+ case IPPROTO_IP:
+ err = sbr_getsockopt_ipproto_ip (optname, optval, *optlen);
+ break;
+
+ case IPPROTO_TCP:
+ err = sbr_getsockopt_ipproto_tcp (optname, optval, *optlen);
+ break;
+
+ case NSTACK_SOCKOPT:
+ if ((optname == NSTACK_SEM_SLEEP) || (*optlen < sizeof (u32_t)))
+ {
+ *(u32_t *) optval =
+ sbr_get_fd_share (sk)->block_polling_time / 1000;
+ NSSOC_LOGINF
+ ("tcp get recv sleep time success, usleep time = %d,fd = %d",
+ sbr_get_fd_share (sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF ("get recv sleep time failed, fd = %d", sk->fd);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (0 != err)
+ {
+ NSSBR_LOGERR ("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+ /* for option not support ,getsockopt() should return fail */
+ return sbr_tcp_get_sockopt_err (sk, err);
+ }
+
+ return sbr_handle_getsockopt (sk, level, optname, optval, optlen);
+}
+
+int
+sbr_setsockopt_ipproto_tcp (int optname, socklen_t optlen)
+{
+ int err = 0;
+
+ if (optlen < sizeof (int))
+ {
+ return EINVAL;
+ }
+
+ switch (optname)
+ {
+ case SPL_TCP_KEEPIDLE:
+ case SPL_TCP_KEEPINTVL:
+ case SPL_TCP_KEEPCNT:
+ break;
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ return err;
+}
+
+NSTACK_STATIC int
+sbr_tcp_setsockopt (sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ int err = 0;
+
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err =
+ sbr_setsockopt_sol_socket (sk, optname, optval, optlen,
+ SPL_NETCONN_TCP);
+ break;
+ case IPPROTO_IP:
+ err =
+ sbr_setsockopt_ipproto_ip (optname, optval, optlen, SPL_NETCONN_TCP);
+ break;
+ case IPPROTO_TCP:
+ err = sbr_setsockopt_ipproto_tcp (optname, optlen);
+ break;
+ case NSTACK_SOCKOPT:
+ {
+ u32_t sleep_time = *(u32_t *) optval;
+ /*sleep time should less than 1s */
+ if ((optname == NSTACK_SEM_SLEEP) && (optlen >= sizeof (u32_t))
+ && (sleep_time < 1000000))
+ {
+ sbr_get_fd_share (sk)->block_polling_time = sleep_time * 1000;
+ NSSOC_LOGINF
+ ("tcp set recv sleep time success, usleep time = %d,fd = %d",
+ sbr_get_fd_share (sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF ("set recv sleep time failed, fd = %d", sk->fd);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+ }
+
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (0 != err)
+ {
+ NSSBR_LOGERR ("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+
+ return sbr_tcp_set_sockopt_err (sk, err);
+ }
+
+ return sbr_handle_setsockopt (sk, level, optname, optval, optlen);
+}
+
+static inline u16
+sbr_tcp_mbuf_count (struct spl_pbuf *p)
+{
+ u16 count = 0;
+ struct spl_pbuf *buf = p;
+ struct common_mem_mbuf *mbuf;
+
+ while (buf)
+ {
+ mbuf =
+ (struct common_mem_mbuf *) ((char *) buf -
+ sizeof (struct common_mem_mbuf));
+ while (mbuf)
+ {
+ count++;
+#ifdef HAL_LIB
+#else
+ mbuf = mbuf->next;
+#endif
+ }
+
+ buf = (struct spl_pbuf *) ADDR_SHTOL (buf->next_a);
+ }
+
+ return count;
+}
+
+static inline void
+sbr_tcp_free_recvbuf (sbr_socket_t * sk, struct spl_pbuf *p)
+{
+ int len;
+
+ if (ss_is_noautorecved_flag (sbr_get_conn (sk)))
+ {
+ len = sbr_tcp_mbuf_count (p);
+ sbr_handle_tcp_recv (sk, len, p);
+ }
+}
+
+static inline void
+sbr_tcp_recv_no_peak (sbr_socket_t * sk, struct spl_pbuf *buf, u32 buflen,
+ u32 copylen)
+{
+ if ((buflen - copylen) > 0)
+ {
+ sbr_get_fd_share (sk)->lastdata = (void *) ADDR_LTOSH (buf);
+ sbr_get_fd_share (sk)->lastoffset += copylen;
+ }
+ else
+ {
+ sbr_get_fd_share (sk)->lastdata = 0;
+ sbr_get_fd_share (sk)->lastoffset = 0;
+ sbr_tcp_free_recvbuf (sk, buf);
+ }
+}
+
+static inline int
+sbr_tcp_recv_from_ring (sbr_socket_t * sk, struct spl_pbuf **buf, i32 timeout)
+{
+ int err;
+ spl_netconn_t *conn = sbr_get_conn (sk);
+
+ err = ss_get_last_errno (conn);
+ if (SPL_ERR_IS_FATAL (err))
+ {
+ /* don't recv on fatal errors: this might block the application task
+ waiting on recvmbox forever! */
+
+ /* @todo: this does not allow us to fetch data that has been put into recvmbox
+ before the fatal error occurred - is that a problem? */
+ NSSBR_LOGDBG ("last err when recv:]=%d", err);
+ if (ERR_CLSD != err)
+ {
+ sbr_set_sk_io_errno (sk, sbr_spl_err_to_errno (err));
+ return -1;
+ }
+ }
+
+ *buf = NULL;
+ if (0 != sbr_dequeue_buf (sk, (void **) buf, timeout))
+ {
+ return -1;
+ }
+
+ ss_sub_recv_avail (sbr_get_conn (sk), (*buf)->tot_len);
+
+ ss_sub_recv_event (sbr_get_conn (sk));
+
+ return 0;
+}
+
+static inline int
+sbr_tcp_recv_state_check (sbr_socket_t * sk)
+{
+
+ spl_tcp_state_t state = ss_get_tcp_state (sbr_get_conn (sk));
+
+ NSSBR_LOGDBG ("tcp state when recv:]=%d", state);
+
+ //close_wait state also can recive data
+ //no connect cannot recive data
+ if (SPL_ESTABLISHED > state)
+ {
+ if (SPL_SHUT_WR != ss_get_shut_status (sbr_get_conn (sk)))
+ {
+ /* after all data retrnasmission, connection is active */
+ /* patch solution as last_err is not maintained properly */
+ if ((SPL_CLOSED == state)
+ && (ERR_TIMEOUT == ss_get_last_errno (sbr_get_conn (sk))))
+ {
+ sbr_set_sk_io_errno (sk, ETIMEDOUT);
+ }
+ else if ((SPL_CLOSED == state)
+ && (ERR_RST == ss_get_last_errno (sbr_get_conn (sk))))
+ {
+ sbr_set_sk_io_errno (sk, ECONNRESET);
+ }
+ else
+ {
+ sbr_set_sk_io_errno (sk, ENOTCONN);
+ }
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+NSTACK_STATIC int
+sbr_tcp_recvfrom (sbr_socket_t * sk, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t * fromlen)
+{
+ struct spl_pbuf *p;
+ u32 buflen;
+ u32 copylen;
+ u32 off = 0;
+ u8 done = 0;
+ int para_len = len;
+ int retval = 0;
+
+ sbr_com_lock_recv (sk);
+ NSSOC_LOGINF ("recv start, fd = %d last data %p flags to be set %d", sk->fd,
+ ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata), MSG_DONTWAIT);
+
+ if (0 != sbr_tcp_recv_state_check (sk))
+ {
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ do
+ {
+ if (sbr_get_fd_share (sk)->lastdata)
+ {
+ p = ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata);
+ }
+ else
+ {
+ if ((flags & MSG_DONTWAIT)
+ || ss_is_nonblock_flag (sbr_get_conn (sk)))
+ {
+ NSSOC_LOGINF ("call ss_get_recv_event");
+ if (0 >= ss_get_recv_event (sbr_get_conn (sk)))
+ {
+ NSSOC_LOGINF ("no recv event]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EWOULDBLOCK);
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+ }
+
+ if (0 !=
+ sbr_tcp_recv_from_ring (sk, &p,
+ sbr_get_fd_share (sk)->recv_timeout))
+ {
+ /* already received data, return that */
+ if (off > 0)
+ {
+ sbr_set_sk_io_errno (sk, ERR_OK);
+ retval = off;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ /* we tell the user the connection is closed by returning zero */
+ if (sbr_get_sk_errno (sk) == ENOTCONN)
+ {
+ retval = 0;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ sbr_get_fd_share (sk)->lastdata = (void *) ADDR_LTOSH (p);
+ }
+
+ buflen = p->tot_len - sbr_get_fd_share (sk)->lastoffset;
+ copylen = len > buflen ? buflen : len;
+
+ if ((copylen > 0)
+ && 0 == spl_pbuf_copy_partial (p, (u8 *) mem + off, copylen,
+ sbr_get_fd_share (sk)->lastoffset))
+ {
+ NSSBR_LOGERR ("copy failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EFAULT);
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+
+ off += copylen;
+
+ len -= copylen;
+
+ if ((len == 0) || (ss_get_recv_event (sbr_get_conn (sk)) <= 0)
+ || ((flags & MSG_PEEK) != 0))
+ {
+ if ((off >= sbr_get_fd_share (sk)->rcvlowat)
+ || (para_len <= sbr_get_fd_share (sk)->rcvlowat))
+ {
+ done = 1;
+ }
+ }
+
+ if (done)
+ {
+ if (sbr_tcp_get_sockaddr (sk, from, fromlen) != 0)
+ {
+ retval = -1;
+ goto sbr_tcp_recvfrom_exit;
+ }
+ }
+
+ /* If this is a TCP socket, check if there is data left in the buffer,
+ If so, it should be saved in the sock structure for next time around. */
+ if (!(flags & MSG_PEEK))
+ {
+ sbr_tcp_recv_no_peak (sk, p, buflen, copylen);
+ }
+ }
+ while (!done);
+
+ retval = off;
+
+ NSSOC_LOGINF ("recv done, fd = %d last data %p", sk->fd);
+sbr_tcp_recvfrom_exit:
+
+ NSSOC_LOGINF ("recv exit, fd = %d last data %p", sk->fd);
+ sbr_com_unlock_recv (sk);
+ return retval;
+}
+
+/*****************************************************************************
+* Prototype : sbr_tcp_recvdata
+* Description : recvdata
+* Input : sbr_socket_t* sk
+* const struct iovec* iov
+* int iovcnt
+* int flags
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_tcp_recvdata (sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ int max = SBR_MAX_INTEGER;
+ int len = 0;
+ int ret = 0;
+ int i = 0;
+
+ do
+ {
+ len += ret;
+
+ if (!iov[i].iov_base || (0 == iov[i].iov_len))
+ {
+ ret = 0;
+ continue;
+ }
+
+ ret = sbr_tcp_recvfrom (sk, (char *) iov[i].iov_base, iov[i].iov_len, 0,
+ NULL, NULL);
+ }
+ while ((ret == (int) iov[i].iov_len) && (iovcnt > (++i))
+ && (max - len - ret > (int) iov[i].iov_len));
+
+ if (len == 0)
+ {
+ return ret;
+ }
+ else
+ {
+ return (ret == -1 ? len : len + ret);
+ }
+}
+
+/*****************************************************************************
+* Prototype : sbr_tcp_readv
+* Description : readv
+* Input : sbr_socket_t* sk
+* const struct iovec* iov
+* int iovcnt
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_tcp_readv (sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ return sbr_tcp_recvdata (sk, iov, iovcnt);
+}
+
+/*****************************************************************************
+* Prototype : sbr_tcp_recvmsg
+* Description : recvmsg,unsupport flags
+* Input : sbr_socket_t* sk
+* struct msghdr* msg
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_tcp_recvmsg (sbr_socket_t * sk, struct msghdr *msg, int flags)
+{
+ if (sbr_tcp_get_sockaddr
+ (sk, (struct sockaddr *) msg->msg_name, &msg->msg_namelen) != 0)
+ {
+ return -1;
+ }
+
+ return sbr_tcp_recvdata (sk, msg->msg_iov, msg->msg_iovlen);
+}
+
+static int
+sbr_tcp_send_is_timeout (sbr_socket_t * sk, struct timespec *starttm)
+{
+ struct timespec currtm;
+ i64 timediff_ms, timediff_sec;
+ i64 timeout_thr_ms, timeout_thr_sec;
+
+ timeout_thr_ms = sbr_get_fd_share (sk)->send_timeout;
+ if (0 == timeout_thr_ms)
+ {
+ return 0;
+ }
+
+ /* it is possible that starttm don't be inited,
+ if send_timeout is change when this write function is running */
+ timeout_thr_sec = (timeout_thr_ms + 240) >> 10;
+
+ /* Handle system time change side-effects */
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &currtm)))
+ {
+ NSSBR_LOGERR ("Failed to get time, errno = %d", errno);
+ }
+
+ timediff_sec = currtm.tv_sec - starttm->tv_sec;
+ if (timediff_sec >= timeout_thr_sec)
+ {
+ timediff_ms = currtm.tv_nsec > starttm->tv_nsec ?
+ (timediff_sec * 1000) + (currtm.tv_nsec -
+ starttm->tv_nsec) /
+ USEC_TO_SEC : (timediff_sec * 1000) -
+ ((starttm->tv_nsec - currtm.tv_nsec) / USEC_TO_SEC);
+
+ /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value
+ will be negetive if still 0.5 ms is not elapsed. this is intended and we should
+ not typecast to any unsigned type during this below if check */
+ if (timediff_ms > timeout_thr_ms)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static inline int
+sbr_tcp_write_is_wait (sbr_socket_t * sk, struct timespec *starttm,
+ int noneblockFlg)
+{
+ if (noneblockFlg || sbr_tcp_send_is_timeout (sk, starttm))
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+static struct spl_pbuf *
+sbr_tcp_write_alloc_buf (sbr_socket_t * sk, size_t seglen, u8 api_flag,
+ struct timespec *starttm, u8 * errno_flag)
+{
+ spl_netconn_t *conn = sbr_get_conn (sk);
+
+ struct spl_pbuf *curr_buf = NULL;
+ size_t head_len = SPL_TCP_HLEN + SPL_PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN;
+ int noneblockFlg = (api_flag & SPL_NETCONN_DONTBLOCK)
+ || ss_is_nonblock_flag (sbr_get_conn (sk));
+
+ do
+ {
+ /* When packages are lost more than TCP_MAXRTX times,
+ * conn will be closed and pcb will be removed. */
+ if (ss_get_tcp_state (conn) == SPL_CLOSED)
+ {
+ NSSBR_LOGERR ("pcb SPL_CLOSED]conn=%p", conn);
+ sbr_set_sk_io_errno (sk, ECONNABORTED);
+ /* Must set errno_flag when set errno, to avoid errnno overwritten by sbr_tcp_write */
+ *errno_flag = 1;
+ return NULL;
+ }
+
+ curr_buf = sbr_malloc_tx_pbuf (seglen + head_len, head_len);
+ if (NULL == curr_buf)
+ {
+ if (!sbr_tcp_write_is_wait (sk, starttm, noneblockFlg))
+ {
+ return NULL;
+ }
+
+ int err = ss_get_last_errno (sbr_get_conn (sk));
+ if (SPL_ERR_IS_FATAL (err))
+ {
+ NSSBR_LOGERR ("connection fatal error!err=%d", err);
+ sbr_set_sk_io_errno (sk, sbr_spl_err_to_errno (err));
+ *errno_flag = 1;
+ return NULL;
+ }
+
+ sched_yield ();
+ }
+ }
+ while (curr_buf == NULL);
+
+ return curr_buf;
+}
+
+static inline void
+sbr_tcp_write_rel_buf (sbr_socket_t * sk, struct spl_pbuf *buf,
+ u32 thread_index)
+{
+ if (buf != NULL)
+ {
+ sbr_handle_free_send_buf (sk, buf);
+ }
+}
+
+static inline int
+sbr_tcp_write_fill_buf (const void *data, size_t * pos,
+ struct spl_pbuf *seg_buf, size_t seglen,
+ size_t optlen)
+{
+ size_t start = *pos;
+ size_t copy = seglen;
+ struct spl_pbuf *first = seg_buf;
+
+ while ((0 < copy) && (NULL != first))
+ {
+ char *dst_ptr = PTR_SHTOL (char *, first->payload_a) + optlen;
+
+ if (NULL ==
+ common_memcpy (dst_ptr, (u8_t *) data + start, first->len - optlen))
+ {
+ NSSBR_LOGERR ("common_memcpy error]dst=%p,src=%p,len=%u",
+ dst_ptr, (u8_t *) data + start, first->len);
+ return -1;
+ }
+
+ start += (first->len - optlen);
+ copy -= (first->len - optlen);
+ first = ADDR_SHTOL (first->next_a);
+ }
+
+ (*pos) = start;
+
+ return 0;
+}
+
+static inline int
+sbr_tcp_writev_fill_buf (const struct iovec *iov, size_t * iov_pos,
+ int *iov_var, size_t * pos, struct spl_pbuf *seg_buf,
+ size_t seglen, size_t optlen)
+{
+ size_t valid_copy_len;
+ size_t iov_data_left;
+
+ size_t copy = seglen;
+ size_t start = *pos;
+ size_t current_iov_pos = *iov_pos;
+ int current_iov_var = *iov_var;
+
+ u32 pbuf_offset = optlen;
+ u32 pbuf_data_len;
+ struct spl_pbuf *first = seg_buf;
+
+ while ((0 < copy) && (NULL != first))
+ {
+ iov_data_left = iov[current_iov_var].iov_len - current_iov_pos;
+ if (seglen == copy)
+ {
+ pbuf_offset = optlen;
+ }
+
+ pbuf_data_len = first->len - pbuf_offset;
+ valid_copy_len =
+ (iov_data_left > pbuf_data_len ? pbuf_data_len : iov_data_left);
+ if (NULL ==
+ common_memcpy ((char *) ADDR_SHTOL (first->payload_a) + pbuf_offset,
+ (u8_t *) iov[current_iov_var].iov_base +
+ current_iov_pos, valid_copy_len))
+ {
+ NSSBR_LOGERR
+ ("common_memcpy error]current_iov_var=%d, dst=%p,src=%p,len=%zu",
+ current_iov_var,
+ (char *) ADDR_SHTOL (first->payload_a) + pbuf_offset,
+ (u8_t *) iov[current_iov_var].iov_base + current_iov_pos,
+ valid_copy_len);
+ return -1;
+ }
+
+ start += valid_copy_len;
+ copy -= valid_copy_len;
+
+ if (iov_data_left == pbuf_data_len)
+ {
+ first = PTR_SHTOL (struct spl_pbuf *, first->next_a);
+ pbuf_offset = optlen; //+= valid_copy_len;
+ current_iov_var++;
+ current_iov_pos = 0;
+ }
+ else if (iov_data_left > pbuf_data_len)
+ {
+ first = PTR_SHTOL (struct spl_pbuf *, first->next_a);
+ pbuf_offset = optlen; //+= valid_copy_len;
+ current_iov_pos += valid_copy_len;
+ }
+ else
+ {
+ pbuf_offset += valid_copy_len;
+
+ current_iov_var++;
+ current_iov_pos = 0;
+ }
+ }
+
+ *iov_pos = current_iov_pos;
+ *iov_var = current_iov_var;
+ *pos = start;
+
+ return 0;
+}
+
+static inline void
+sbr_tcp_write_add_buf_to_list (struct spl_pbuf **p_head,
+ struct spl_pbuf **p_tail,
+ struct spl_pbuf *seg_buf, size_t seglen,
+ size_t optlen)
+{
+ seg_buf->len = seglen + optlen;
+ seg_buf->tot_len = seglen + optlen;
+ seg_buf->next_a = 0;
+
+ /*put seg_buf after p_head */
+ if (NULL == (*p_head))
+ {
+ (*p_head) = seg_buf;
+ (*p_tail) = seg_buf;
+ }
+ else
+ {
+ (*p_tail)->next_a = ADDR_LTOSH (seg_buf);
+ (*p_tail) = seg_buf;
+ }
+}
+
+NSTACK_STATIC int
+sbr_tcp_write (sbr_socket_t * sk, const void *data, size_t size, u8 api_flag,
+ size_t * written)
+{
+ err_t err = -1;
+ size_t pos = 0, left, seglen;
+ u32 pbuf_seg_cnt = 0;
+ u32 thread_index = 0;
+ struct spl_pbuf *seg_buf = NULL;
+ struct spl_pbuf *p_head = NULL;
+ struct spl_pbuf *p_tail = p_head;
+ struct spl_netconn *conn = sbr_get_conn (sk);
+ u32 mss = ss_get_mss (sbr_get_conn (sk));
+
+ if (0 == size)
+ {
+ NSSBR_LOGERR ("fd=%d,size=%u", sk->fd, (u32) size);
+ return 0;
+ }
+
+ struct timespec ts;
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &ts)))
+ {
+ NSSBR_LOGERR ("Failed to get time, errno = %d", errno);
+ }
+
+ while (pos < size)
+ {
+ left = size - pos;
+ seglen = left > mss ? mss : left;
+ u8 errno_set = 0;
+ seg_buf =
+ sbr_tcp_write_alloc_buf (sk, seglen, api_flag, &ts, &errno_set);
+ if (NULL == seg_buf)
+ {
+ NSSBR_LOGINF ("sbr_tcp_write_alloc_buf failed......");
+ if (NULL != p_head)
+ {
+ err = sbr_handle_tcp_send (sk, size, p_head, api_flag);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR ("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+ }
+
+ if (0 == pos)
+ {
+ /* If errno is already set in sbr_tcp_write_alloc_buf, do not overwrite here */
+ if (!errno_set)
+ {
+ sbr_set_sk_io_errno (sk, EWOULDBLOCK);
+ }
+ return -1;
+ }
+
+ NSSBR_LOGDBG ("sent size %zu", pos);
+ *written = pos;
+
+ return ERR_OK;
+ }
+
+ if (0 != sbr_tcp_write_fill_buf (data, &pos, seg_buf, seglen, 0))
+ {
+ sbr_set_sk_io_errno (sk, EFAULT);
+ NSSBR_LOGERR ("sbr_tcp_write_fill_buf error]");
+ goto err_ref_buf;
+ }
+
+ sbr_tcp_write_add_buf_to_list (&p_head, &p_tail, seg_buf, seglen, 0);
+
+ ++pbuf_seg_cnt;
+ if (p_head
+ && ((SPL_TCP_SEND_MAX_SEG_PER_MSG <= pbuf_seg_cnt)
+ || (pos >= size)))
+ {
+ pbuf_seg_cnt = 0;
+ err = sbr_handle_tcp_send (sk, size, p_head, api_flag);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR ("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+
+ p_head = NULL;
+ }
+ }
+
+ *written = size;
+
+ (void) conn;
+ return ERR_OK;
+
+err_ref_buf:
+ sbr_tcp_write_rel_buf (sk, p_head, thread_index);
+ (void) conn;
+ return -1;
+}
+
+NSTACK_STATIC int
+sbr_tcp_writev (sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ err_t err = -1;
+ int idx = 0;
+ size_t pos = 0, left, seglen, optlen = 0;
+ u32 pbuf_seg_cnt = 0;
+ u32 thread_index = 0;
+ size_t size = 0;
+ size_t iov_pos = 0;
+ int iov_var = 0;
+ struct spl_pbuf *seg_buf = NULL;
+ struct spl_pbuf *p_head = NULL;
+ struct spl_pbuf *p_tail = p_head;
+ struct spl_netconn *conn = sbr_get_conn (sk);
+ u32 mss = ss_get_mss (sbr_get_conn (sk));
+
+ if (mss <= optlen)
+ {
+ NSSBR_LOGERR ("mss invalid]mss=%u,optlen=%zu,fd=%d", mss, optlen,
+ sk->fd);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+
+ /* mss dose't include the tcp options length */
+ mss -= optlen;
+
+ while (idx < iovcnt)
+ {
+ if (SBR_MAX_INTEGER - iov[idx].iov_len <= size)
+ {
+ size = SBR_MAX_INTEGER;
+ break;
+ }
+
+ size += iov[idx].iov_len;
+ idx++;
+ }
+
+ struct timespec starttm;
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &starttm)))
+ {
+ NSSBR_LOGERR ("Failed to get time, errno = %d", errno);
+ }
+
+ while (pos < size)
+ {
+ left = size - pos;
+
+ seglen = left > mss ? mss : left;
+ u8 errno_set = 0;
+ seg_buf =
+ sbr_tcp_write_alloc_buf (sk, seglen + optlen, SPL_NETCONN_COPY,
+ &starttm, &errno_set);
+ if (NULL == seg_buf)
+ {
+ if (NULL != p_head)
+ {
+ err = sbr_handle_tcp_send (sk, size, p_head, SPL_NETCONN_COPY);
+ /*If errno is already set in sbr_tcp_write_alloc_buf, do not overwrite here */
+ if (err != ERR_OK)
+ {
+ NSSBR_LOGERR ("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+ }
+
+ /* [Start]
+ 1)Set SO_SNDTIMEO to 10
+ 2)Send a msg of larger buff size.and let the timeout happen for send (dont receive at peer side.)
+ 3)iRet will be 0 and errno received will be 11 (EAGAIN).
+
+ Above issue is fixed.
+ */
+ if (0 == pos)
+ {
+ if (!errno_set)
+ {
+ sbr_set_sk_io_errno (sk, EWOULDBLOCK);
+ }
+ return -1;
+ }
+ /* [End] */
+
+ NSSBR_LOGDBG ("sent size %zu", pos);
+
+ return pos;
+ }
+
+ if (0 !=
+ sbr_tcp_writev_fill_buf (iov, &iov_pos, &iov_var, &pos, seg_buf,
+ seglen, optlen))
+ {
+ sbr_set_sk_io_errno (sk, EFAULT);
+ NSSBR_LOGERR ("sbr_tcp_writev_fill_buf error]");
+ goto err_ref_buf;
+ }
+
+ sbr_tcp_write_add_buf_to_list (&p_head, &p_tail, seg_buf, seglen,
+ optlen);
+
+ /* @todo: for non-blocking write, check if 'size' would ever fit into
+ snd_queue or snd_buf */
+ ++pbuf_seg_cnt;
+ if (p_head
+ && ((SPL_TCP_SEND_MAX_SEG_PER_MSG <= pbuf_seg_cnt)
+ || (pos >= size)))
+ {
+ pbuf_seg_cnt = 0;
+ err = sbr_handle_tcp_send (sk, size, p_head, SPL_NETCONN_COPY);
+ if (ERR_OK != err)
+ {
+ NSSBR_LOGERR ("sbr_handle_tcp_send error]err(%d)", err);
+ goto err_ref_buf;
+ }
+
+ p_head = NULL;
+ }
+ }
+ (void) conn;
+ return size;
+
+err_ref_buf:
+ sbr_tcp_write_rel_buf (sk, p_head, thread_index);
+ (void) conn;
+ return -1;
+}
+
+NSTACK_STATIC int
+sbr_tcp_sendto (sbr_socket_t * sk, const void *data, size_t size, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ return sk->fdopt->send (sk, data, size, flags);
+}
+
+static inline int
+sbr_tcp_send_state_check (sbr_socket_t * sk)
+{
+ if ((SPL_SHUT_WR == ss_get_shut_status (sbr_get_conn (sk)))
+ || (SPL_SHUT_RDWR == ss_get_shut_status (sbr_get_conn (sk))))
+ {
+ sbr_set_sk_io_errno (sk, EPIPE);
+ return -1;
+ }
+
+ spl_tcp_state_t state = ss_get_tcp_state (sbr_get_conn (sk));
+ if ((SPL_ESTABLISHED != state) && (SPL_CLOSE_WAIT != state))
+ {
+ /* after all data retrnasmission, connection is active */
+ /* patch solution as last_err is not maintained properly */
+ if ((SPL_CLOSED == state)
+ && (ERR_TIMEOUT == ss_get_last_errno (sbr_get_conn (sk))))
+ {
+ sbr_set_sk_io_errno (sk, ETIMEDOUT);
+ }
+ else if ((SPL_CLOSED == state)
+ && (ERR_RST == ss_get_last_errno (sbr_get_conn (sk))))
+ {
+ sbr_set_sk_io_errno (sk, ECONNRESET);
+ }
+ else
+ {
+ sbr_set_sk_io_errno (sk, EPIPE);
+ }
+
+ return -1;
+ }
+
+ return 0;
+}
+
+NSTACK_STATIC int
+sbr_tcp_send (sbr_socket_t * sk, const void *data, size_t size, int flags)
+{
+ int err;
+ size_t written = 0;
+ u8 write_flags;
+
+ if (0 != sbr_tcp_send_state_check (sk))
+ {
+ NSSBR_LOGDBG ("tcp state not correct]fd=%d, err=%d", sk->fd,
+ sbr_get_sk_errno (sk));
+ return -1;
+ }
+
+ write_flags = SPL_NETCONN_COPY |
+ ((flags & MSG_MORE) ? SPL_NETCONN_MORE : 0) |
+ ((flags & MSG_DONTWAIT) ? SPL_NETCONN_DONTBLOCK : 0);
+
+ NSSBR_LOGINF ("Sbr tcp write start");
+ err = sbr_tcp_write (sk, data, size, write_flags, &written);
+ NSSBR_LOGINF ("Sbr tcp write end written %d", written);
+
+ return (err == ERR_OK ? written : -1);
+}
+
+NSTACK_STATIC int
+sbr_tcp_sendmsg (sbr_socket_t * sk, const struct msghdr *pmsg, int flags)
+{
+ if (0 != sbr_tcp_send_state_check (sk))
+ {
+ NSSBR_LOGDBG ("tcp state not correct]fd=%d, err=%d", sk->fd,
+ sbr_get_sk_errno (sk));
+ return -1;
+ }
+
+ return sbr_tcp_writev (sk, pmsg->msg_iov, pmsg->msg_iovlen);
+}
+
+NSTACK_STATIC int
+sbr_tcp_fcntl (sbr_socket_t * sk, int cmd, long arg)
+{
+ int ret = 0;
+
+ switch (cmd)
+ {
+ case F_GETFL:
+ ret = ss_get_nonblock_flag (sbr_get_conn (sk));
+ NSSBR_LOGDBG ("F_GETFL]fd=%d,ret=%d", sk->fd, ret);
+ break;
+
+ case F_SETFL:
+ if (arg & O_NONBLOCK)
+ {
+ NSSBR_LOGDBG ("F_SETFL set O_NONBLOCK val]fd=%d,arg=%ld", sk->fd,
+ arg);
+ ss_set_nonblock_flag (sbr_get_conn (sk), (arg & O_NONBLOCK));
+ }
+ else
+ {
+ NSSBR_LOGDBG ("F_SETFL clean O_NONBLOCK val]fd=%d,arg=%ld", sk->fd,
+ arg);
+ ss_set_nonblock_flag (sbr_get_conn (sk), 0);
+ }
+
+ break;
+
+ default:
+ NSSBR_LOGERR ("cmd is not support]fd=%d,cmd=%d", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno (sk, EINVAL);
+ break;
+ }
+
+ return ret;
+}
+
+NSTACK_STATIC int
+sbr_tcp_ioctl (sbr_socket_t * sk, unsigned long cmd, void *arg)
+{
+ int ret = 0;
+ int recv_avail;
+
+ switch (cmd)
+ {
+ case FIONREAD:
+ {
+ if (ss_is_listen_state (sbr_get_conn (sk)))
+ {
+ ret = -1;
+ sbr_set_sk_errno (sk, EINVAL);
+ break;
+ }
+
+ recv_avail = ss_get_recv_avail (sbr_get_conn (sk));
+ *((u32 *) arg) = recv_avail >= 0 ? recv_avail : 0;
+ if (sbr_get_fd_share (sk)->lastdata)
+ {
+ struct spl_pbuf *buf =
+ ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata);
+ *((u32 *) arg) +=
+ (buf->tot_len - sbr_get_fd_share (sk)->lastoffset);
+ }
+ }
+
+ break;
+
+ case FIONBIO:
+ {
+ u8 val = 0;
+
+ if (arg && *(u32 *) arg)
+ {
+ val = 1;
+ }
+
+ ss_set_nonblock_flag (sbr_get_conn (sk), val);
+ NSSBR_LOGDBG ("FIONBIO]fd=%d,val=%u", sk->fd, val);
+ }
+
+ break;
+
+ default:
+ {
+ NSSBR_LOGERR ("cmd is not support]fd=%d,cmd=%lu", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno (sk, ENOTTY);
+ }
+ break;
+ }
+
+ return ret;
+}
+
+NSTACK_STATIC int
+sbr_tcp_close (sbr_socket_t * sk)
+{
+ if (sbr_get_fd_share (sk)->lastdata)
+ {
+ struct spl_netbuf *buf = ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata);
+ struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL (buf->p);
+ sbr_tcp_free_recvbuf (sk, p);
+ }
+
+ return sbr_handle_close (sk, 0);
+}
+
+sbr_fdopt tcp_fdopt = {
+ .socket = sbr_tcp_socket,
+ .bind = sbr_tcp_bind,
+ .listen = sbr_tcp_listen,
+ .accept = sbr_tcp_accept,
+ .accept4 = sbr_tcp_accept4,
+ .connect = sbr_tcp_connect,
+ .shutdown = sbr_tcp_shutdown,
+ .getsockname = sbr_tcp_getsockname,
+ .getpeername = sbr_tcp_getpeername,
+ .getsockopt = sbr_tcp_getsockopt,
+ .setsockopt = sbr_tcp_setsockopt,
+ .recvfrom = sbr_tcp_recvfrom,
+ .readv = sbr_tcp_readv,
+ .recvmsg = sbr_tcp_recvmsg,
+ .send = sbr_tcp_send,
+ .sendto = sbr_tcp_sendto,
+ .sendmsg = sbr_tcp_sendmsg,
+ .writev = sbr_tcp_writev,
+ .fcntl = sbr_tcp_fcntl,
+ .ioctl = sbr_tcp_ioctl,
+ .close = sbr_tcp_close,
+ .peak = sbr_com_peak,
+ .lock_common = sbr_com_lock_common,
+ .unlock_common = sbr_com_unlock_common,
+ .ep_getevt = stackx_eventpoll_getEvt,
+ .ep_ctl = stackx_eventpoll_triggle,
+ .set_close_stat = NULL,
+};
diff --git a/stacks/lwip_stack/lwip_src/socket/stackx_udp.c b/stacks/lwip_stack/lwip_src/socket/stackx_udp.c
new file mode 100644
index 0000000..cf08731
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/socket/stackx_udp.c
@@ -0,0 +1,1169 @@
+/*
+*
+* 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 "stackx_prot_com.h"
+#include "stackx_msg_handler.h"
+#include "stackx_pbuf.h"
+#include "stackx_epoll_api.h"
+#include "stackx_err.h"
+#include "nstack_securec.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_cfg.h"
+#include <netinet/in.h>
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+
+#define SPL_PBUF_UDP_LEN (SPL_FRAME_MTU + SPL_PBUF_LINK_HLEN)
+#define L2_L3_ROOM_LEN (SPL_PBUF_LINK_HLEN + SPL_PBUF_IP_HLEN)
+#define L4_ROOM_LEN SPL_PBUF_UDP_HLEN
+
+/*****************************************************************************
+* Prototype : sbr_udp_socket
+* Description : create socket
+* Input : sbr_socket_t * sk
+* int domain
+* int type
+* int protocol
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_socket (sbr_socket_t * sk, int domain, int type, int protocol)
+{
+ if (sbr_malloc_conn_for_sk (sk, SPL_NETCONN_UDP) != 0)
+ {
+ return -1;
+ }
+
+ int ret = sbr_handle_socket (sk, SPL_NETCONN_UDP, 0);
+ if (ret != 0)
+ {
+ sbr_free_conn_from_sk (sk);
+ return ret;
+ }
+
+ ss_set_nonblock_flag (sbr_get_conn (sk), (type & O_NONBLOCK));
+ ss_set_send_event (sbr_get_conn (sk), 1);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_bind
+* Description : udp bind
+* Input : sbr_socket_t * sk
+* const struct sockaddr * name
+* socklen_t namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_bind (sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+
+ NSSBR_LOGINF ("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa (addr_in->sin_addr), ntohs (addr_in->sin_port),
+ sbr_get_conn (sk), ss_get_private_data (sbr_get_conn (sk)));
+ spl_ip_addr_t local_addr;
+ inet_addr_to_ipaddr (&local_addr, &addr_in->sin_addr);
+ u16 local_port = addr_in->sin_port;
+ return sbr_handle_bind (sk, &local_addr, ntohs (local_port));
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_listen
+* Description : unsupport
+* Input : sbr_socket_t * sk
+* int backlog
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_listen (sbr_socket_t * sk, int backlog)
+{
+ NSSBR_LOGERR ("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_accept
+* Description : unsupport
+* Input : sbr_socket_t * sk
+* sbr_socket_t * new_sk
+* struct sockaddr * addr
+* socklen_t * addrlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_accept (sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen)
+{
+ NSSBR_LOGERR ("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_accept4
+* Description : unsupport
+* Input : sbr_socket_t * sk
+* sbr_socket_t * new_sk
+* struct sockaddr * addr
+* socklen_t * addrlen
+* int flags
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_accept4 (sbr_socket_t * sk, sbr_socket_t * new_sk,
+ struct sockaddr *addr, socklen_t * addrlen, int flags)
+{
+ NSSBR_LOGERR ("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_connect
+* Description : udp connect
+* Input : sbr_socket_t * sk
+* const struct sockaddr * name
+* socklen_t namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_connect (sbr_socket_t * sk, const struct sockaddr *name,
+ socklen_t namelen)
+{
+ const struct sockaddr_in *addr_in = (const struct sockaddr_in *) name;
+
+ NSSBR_LOGINF ("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa (addr_in->sin_addr), ntohs (addr_in->sin_port),
+ sbr_get_conn (sk), ss_get_private_data (sbr_get_conn (sk)));
+ spl_ip_addr_t remote_addr;
+
+ inet_addr_to_ipaddr (&remote_addr, &addr_in->sin_addr);
+ u16 remote_port = addr_in->sin_port;
+
+ spl_ip_addr_t local_addr;
+ if (IPADDR_ANY == ss_get_local_ip (sbr_get_conn (sk))->addr)
+ {
+ if (sbr_get_src_ip (remote_addr.addr, &local_addr.addr) != 0)
+ {
+ sbr_set_sk_errno (sk, EHOSTUNREACH);
+ NSSBR_LOGERR ("get src ip failed]fd=%d", sk->fd);
+ return -1;
+ }
+ }
+
+ return sbr_handle_connect (sk, &remote_addr, ntohs (remote_port),
+ &local_addr);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_shutdown
+* Description : udp shutdown
+* Input : sbr_socket_t * sk
+* int how
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_shutdown (sbr_socket_t * sk, int how)
+{
+ ss_set_shut_status (sbr_get_conn (sk), how);
+ NSSBR_LOGERR ("type is not TCP]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, EOPNOTSUPP);
+ return -1;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_getsockname
+* Description : get sock name
+* Input : sbr_socket_t * sk
+* struct sockaddr * name
+* socklen_t * namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_getsockname (sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+ return sbr_handle_get_name (sk, name, namelen, SBR_GET_SOCK_NAME);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_getpeername
+* Description : get peer name
+* Input : sbr_socket_t * sk
+* struct sockaddr * name
+* socklen_t * namelen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_getpeername (sbr_socket_t * sk, struct sockaddr *name,
+ socklen_t * namelen)
+{
+ return sbr_handle_get_name (sk, name, namelen, SBR_GET_PEER_NAME);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_getsockopt
+* Description : get sockopt
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* void * optval
+* socklen_t * optlen
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_udp_getsockopt (sbr_socket_t * sk, int level, int optname, void *optval,
+ socklen_t * optlen)
+{
+ int err = 0;
+
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err = sbr_getsockopt_sol_socket (sk, optname, optval, *optlen);
+ break;
+ case IPPROTO_IP:
+ err = sbr_getsockopt_ipproto_ip (optname, optval, *optlen);
+ break;
+
+ case NSTACK_SOCKOPT:
+ if ((optname == NSTACK_SEM_SLEEP) || (*optlen < sizeof (u32_t)))
+ {
+ *(u32_t *) optval =
+ sbr_get_fd_share (sk)->block_polling_time / 1000;
+ NSSOC_LOGINF
+ ("udp get recv sleep time success]usleep time=%d,fd=%d",
+ sbr_get_fd_share (sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF ("get recv sleep time failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+ /* for option not support ,getsockopt() should return fail */
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+
+ return sbr_handle_getsockopt (sk, level, optname, optval, optlen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_setsockopt
+* Description : set sockopt
+* Input : sbr_socket_t * sk
+* int level
+* int optname
+* const void * optval
+* socklen_t optlen
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_setsockopt (sbr_socket_t * sk, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ NSSBR_LOGDBG ("udp setsockopt]fd=%d,level=%d,optname=%d", sk->fd, level,
+ optname);
+ int err = 0;
+ switch (level)
+ {
+ case SOL_SOCKET:
+ err =
+ sbr_setsockopt_sol_socket (sk, optname, optval, optlen,
+ SPL_NETCONN_UDP);
+ break;
+ case IPPROTO_IP:
+ err =
+ sbr_setsockopt_ipproto_ip (optname, optval, optlen, SPL_NETCONN_UDP);
+ break;
+ case NSTACK_SOCKOPT:
+ {
+ u32_t sleep_time = *(u32_t *) optval;
+ /*sleep time should less than 1s */
+ if ((optname == NSTACK_SEM_SLEEP) && (optlen >= sizeof (u32_t))
+ && (sleep_time < 1000000))
+ {
+ sbr_get_fd_share (sk)->block_polling_time = sleep_time * 1000;
+ NSSOC_LOGINF
+ ("udp set recv sleep time success]usleep time=%d,fd=%d",
+ sbr_get_fd_share (sk)->block_polling_time, sk->fd);
+ return ERR_OK;
+ }
+ else
+ {
+ NSSOC_LOGINF ("set recv sleep time failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+ }
+
+ default:
+ err = ENOPROTOOPT;
+ break;
+ }
+
+ if (err != 0)
+ {
+ NSSBR_LOGERR ("fail]fd=%d,level=%d,optname=%d,err=%d", sk->fd, level,
+ optname, err);
+
+ if (ENOPROTOOPT == err)
+ {
+ return 0;
+ }
+ else
+ {
+ sbr_set_sk_errno (sk, err);
+ return -1;
+ }
+ }
+
+ return sbr_handle_setsockopt (sk, level, optname, optval, optlen);
+}
+
+static inline int
+sbr_udp_get_from_addr (sbr_socket_t * sk, struct sockaddr *from,
+ socklen_t * fromlen, struct spl_netbuf *buf)
+{
+ int ret;
+ u16 port = netbuf_fromport (buf);
+ spl_ip_addr_t *addr = netbuf_fromaddr (buf);
+
+ ret = (from
+ && fromlen) ? sbr_get_sockaddr_and_len (port, addr, from,
+ fromlen) : 0;
+ if (0 != ret)
+ {
+ sbr_set_sk_io_errno (sk, EINVAL);
+ NSSBR_LOGERR ("sbr_udp_get_from_addr]fd=%d", sk->fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recv_from_ring
+* Description : recv buf from ring
+* Input : sbr_socket_t * sk
+* struct spl_netbuf ** buf
+* i32 timeout
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_udp_recv_from_ring (sbr_socket_t * sk, struct spl_netbuf **buf,
+ i32 timeout)
+{
+ void *p = NULL;
+ spl_netconn_t *conn = sbr_get_conn (sk);
+
+ if (sbr_dequeue_buf (sk, &p, timeout) != 0)
+ {
+ return -1;
+ }
+
+ *buf = (struct spl_netbuf *) ((char *) p + sizeof (struct spl_pbuf));
+ ss_sub_recv_event (conn);
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : _sbr_udp_recvfrom
+* Description : base recvfrom,without lock
+* Input : sbr_socket_t * sk
+* void * mem
+* size_t len
+* int flags
+* struct sockaddr * from
+* socklen_t * fromlen
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+_sbr_udp_recvfrom (sbr_socket_t * sk, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t * fromlen)
+{
+ struct spl_netbuf *buf = NULL;
+ struct spl_pbuf *p;
+ u32 buflen;
+ u32 copylen;
+ u32 off = 0;
+
+ if (sbr_get_fd_share (sk)->lastdata)
+ {
+ buf = ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata);
+ }
+ else
+ {
+ if ((flags & MSG_DONTWAIT) || ss_is_nonblock_flag (sbr_get_conn (sk)))
+ {
+ /*
+ * return with last err when
+ * some fatal err occurs, for example, spl just recovered from a fault.
+ */
+ int err = ss_get_last_errno (sbr_get_conn (sk));
+ if (SPL_ERR_IS_FATAL (err))
+ {
+ NSSBR_LOGDBG ("connection fatal error]sk->fd=%d,errno=%d",
+ sk->fd, err);
+ sbr_set_sk_io_errno (sk, sbr_spl_err_to_errno (err));
+ return -1;
+ }
+
+ if (ss_get_recv_event (sbr_get_conn (sk)) <= 0)
+ {
+ NSSBR_LOGDBG ("no recv event]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EWOULDBLOCK);
+ return -1;
+ }
+ }
+
+ if (sbr_udp_recv_from_ring
+ (sk, &buf, sbr_get_fd_share (sk)->recv_timeout) != 0)
+ {
+ return -1;
+ }
+
+ sbr_get_fd_share (sk)->lastdata = (void *) ADDR_LTOSH (buf);
+ }
+
+ p = (struct spl_pbuf *) ADDR_SHTOL (buf->p);
+ buflen = p->tot_len;
+
+ if (mem)
+ {
+ copylen = len > buflen ? buflen : len;
+
+ if ((copylen > 0) && 0 == spl_pbuf_copy_partial (p, mem, copylen, 0))
+ {
+ NSSBR_LOGERR ("copy failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EFAULT);
+ return -1;
+ }
+
+ off += copylen;
+ }
+
+ if (sbr_udp_get_from_addr (sk, from, fromlen, buf) != 0)
+ {
+ return -1;
+ }
+
+ if (!(flags & MSG_PEEK))
+ {
+ sbr_get_fd_share (sk)->lastdata = NULL;
+ sbr_com_free_recv_buf (sk, (struct spl_pbuf *) ADDR_SHTOL (buf->p));
+ }
+
+ return off;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recvfrom
+* Description : recv from
+* Input : sbr_socket_t * sk
+* void * mem
+* size_t len
+* int flags
+* struct sockaddr * from
+* socklen_t * fromlen
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_recvfrom (sbr_socket_t * sk, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t * fromlen)
+{
+ sbr_com_lock_recv (sk);
+ int ret = _sbr_udp_recvfrom (sk, mem, len, flags, from, fromlen);
+ sbr_com_unlock_recv (sk);
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recvdata
+* Description : recv data
+* Input : sbr_socket_t * sk
+* const struct iovec* iov
+* int iovcnt
+* struct spl_netbuf *buf
+* Output : None
+* Return Value : static inline
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_udp_recvdata (sbr_socket_t * sk, const struct iovec *iov, int iovcnt,
+ int flags, struct sockaddr *from, socklen_t * fromlen)
+{
+ sbr_com_lock_recv (sk);
+ if (-1 == _sbr_udp_recvfrom (sk, NULL, 0, MSG_PEEK, from, fromlen))
+ {
+ sbr_com_unlock_recv (sk);
+ return -1;
+ }
+
+ struct spl_netbuf *buf = ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata);
+ struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL (buf->p);
+ u32 buflen = p->tot_len;
+ u32 copylen = 0;
+ u32 offset = 0;
+
+ int i;
+
+ for (i = 0; i < iovcnt; ++i)
+ {
+ if (!iov[i].iov_base || (0 == iov[i].iov_len))
+ {
+ continue;
+ }
+
+ copylen = buflen > iov[i].iov_len ? iov[i].iov_len : buflen;
+ if ((copylen > 0)
+ && 0 == spl_pbuf_copy_partial (p, iov[i].iov_base, copylen, offset))
+ {
+ NSSBR_LOGERR ("copy failed]fd=%d", sk->fd);
+ goto done;
+ }
+
+ offset += copylen;
+ buflen -= copylen;
+
+ if (0 == buflen)
+ {
+ goto done;
+ }
+ }
+
+done:
+ if (!(flags & MSG_PEEK))
+ {
+ sbr_get_fd_share (sk)->lastdata = NULL;
+ sbr_com_free_recv_buf (sk, (struct spl_pbuf *) ADDR_SHTOL (buf->p));
+ }
+
+ sbr_com_unlock_recv (sk);
+ return offset;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_readv
+* Description : readv
+* Input : sbr_socket_t* sk
+* const struct iovec* iov
+* int iovcnt
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_readv (sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ return sbr_udp_recvdata (sk, iov, iovcnt, 0, NULL, NULL);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_recvmsg
+* Description : recv msg
+* Input : sbr_socket_t* sk
+* struct msghdr* msg
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_recvmsg (sbr_socket_t * sk, struct msghdr *msg, int flags)
+{
+ return sbr_udp_recvdata (sk, msg->msg_iov, msg->msg_iovlen, flags,
+ (struct sockaddr *) msg->msg_name,
+ &msg->msg_namelen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_copy_iov
+* Description : copy iov
+* Input : sbr_socket_t * sk
+* const struct iovec * iov
+* int iovcnt
+* struct spl_pbuf* buf
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_copy_iov (sbr_socket_t * sk, const struct iovec *iov, int iovcnt,
+ struct spl_pbuf *buf)
+{
+ u32 buf_left = buf->len;
+ i8 *buf_data = (i8 *) ADDR_SHTOL (buf->payload);
+ u32 iov_left;
+ i8 *iov_data;
+ u32 copy_len;
+
+ int i;
+
+ for (i = 0; i < iovcnt; ++i)
+ {
+ if (!iov[i].iov_base || (0 == iov[i].iov_len))
+ {
+ continue;
+ }
+
+ iov_left = (u32) iov[i].iov_len; /* to u32 is ok,len is checked in sbr_udp_senddata */
+ iov_data = (i8 *) iov[i].iov_base;
+ while (iov_left)
+ {
+ copy_len = buf_left > iov_left ? iov_left : buf_left;
+
+ if (NULL == common_memcpy (buf_data, iov_data, copy_len))
+ {
+ NSSBR_LOGERR ("common_memcpy error]fd=%d", sk->fd);
+ sbr_set_sk_errno (sk, EFAULT);
+ return -1;
+ }
+
+ buf_data += copy_len;
+ buf_left -= copy_len;
+ iov_data += copy_len;
+ iov_left -= copy_len;
+ if (0 == buf_left)
+ {
+ buf = (struct spl_pbuf *) ADDR_SHTOL (buf->next);
+ if (buf)
+ {
+ buf_left = buf->len;
+ buf_data = (i8 *) ADDR_SHTOL (buf->payload);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_senddata
+* Description : send data
+* Input : sbr_socket_t * sk
+* const struct iovec * iov
+* int iovcnt
+* int flags
+* const struct sockaddr * to
+* socklen_t tolen
+* Output : None
+* Return Value : static inline int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline int
+sbr_udp_senddata (sbr_socket_t * sk, const struct iovec *iov, int iovcnt,
+ int flags, const struct sockaddr *to, socklen_t tolen)
+{
+ size_t size = 0;
+ int iov_idx;
+
+ for (iov_idx = 0; iov_idx < iovcnt; ++iov_idx)
+ {
+ if ((SPL_MAX_UDP_MSG_LEN - size) < iov[iov_idx].iov_len)
+ {
+ NSSBR_LOGERR
+ ("size > SPL_MAX_UDP_MSG_LEN]fd=%d,SPL_MAX_UDP_MSG_LEN=%u",
+ sk->fd, SPL_MAX_UDP_MSG_LEN);
+ sbr_set_sk_io_errno (sk, EMSGSIZE);
+ return -1;
+ }
+
+ size += iov[iov_idx].iov_len;
+ }
+
+ if (to == NULL)
+ {
+ /* if not bind , then dest address should not be NULL */
+ if (IPADDR_ANY == ss_get_remote_ip (sbr_get_conn (sk))->addr)
+ {
+ NSSBR_LOGERR ("dest address is null]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, EDESTADDRREQ);
+ return -1;
+ }
+ }
+ else if (to->sa_family != AF_INET)
+ {
+ NSSBR_LOGERR ("invalid address family]fd=%d,family=%d", sk->fd,
+ to->sa_family);
+ sbr_set_sk_io_errno (sk, EAFNOSUPPORT);
+ return -1;
+ }
+ else if (tolen != sizeof (struct sockaddr_in))
+ {
+ NSSBR_LOGERR ("invalid address len]fd=%d,tolen=%u", sk->fd, tolen);
+ sbr_set_sk_io_errno (sk, EINVAL);
+ return -1;
+ }
+
+ struct spl_netbuf buf;
+ const struct sockaddr_in *to_in = (const struct sockaddr_in *) to;
+ buf.p = NULL;
+ if (to_in)
+ {
+ NSSBR_LOGDBG ("fd=%d,addr=%s,port=%d,conn=%p,private_data=%p", sk->fd,
+ spl_inet_ntoa (to_in->sin_addr), ntohs (to_in->sin_port),
+ sbr_get_conn (sk),
+ ss_get_private_data (sbr_get_conn (sk)));
+ inet_addr_to_ipaddr (&buf.addr, &to_in->sin_addr);
+ netbuf_fromport (&buf) = ntohs (to_in->sin_port);
+ }
+ else
+ {
+ spl_ip_addr_set_any (&buf.addr);
+ netbuf_fromport (&buf) = 0;
+ }
+
+ spl_ip_addr_t local_ip;
+ if (IPADDR_ANY == ss_get_local_ip (sbr_get_conn (sk))->addr)
+ {
+ if (sbr_get_src_ip (buf.addr.addr, &local_ip.addr) != 0)
+ {
+ sbr_set_sk_io_errno (sk, EHOSTUNREACH);
+ NSSBR_LOGERR ("get src ip failed]fd=%d", sk->fd);
+ return -1;
+ }
+ }
+
+ int err = ss_get_last_errno (sbr_get_conn (sk));
+ if (SPL_ERR_IS_FATAL (err))
+ {
+ NS_LOG_CTRL (LOG_CTRL_SEND, LOGSBR, "NSSBR", NSLOG_ERR,
+ "connection fatal error!err=%d", err);
+ sbr_set_sk_errno (sk, sbr_spl_err_to_errno (err));
+ return -1;
+ }
+
+ u16 remain_len = size; //+ head_room_len;
+ struct spl_pbuf *p = NULL;
+ PRIMARY_ADDR struct spl_pbuf *header = NULL;
+ struct spl_pbuf **tail = &header;
+ u16 head_len = L2_L3_ROOM_LEN + L4_ROOM_LEN;
+ u16 copy_len;
+ u16 alloc_len;
+
+ do
+ {
+ copy_len =
+ remain_len >
+ (SPL_PBUF_UDP_LEN - head_len) ? (SPL_PBUF_UDP_LEN -
+ head_len) : remain_len;
+ alloc_len = head_len + copy_len;
+ p = sbr_malloc_tx_pbuf (alloc_len, head_len);
+ if (unlikely (!p))
+ {
+ NSSBR_LOGDBG ("malloc pbuf failed]fd=%d", sk->fd);
+ sbr_set_sk_io_errno (sk, ENOMEM);
+ sbr_handle_free_send_buf (sk,
+ (struct spl_pbuf *) ADDR_SHTOL (header));
+ // ss_set_send_event(sbr_get_conn(sk), 0);
+ return -1;
+ }
+
+ struct spl_pbuf *tmp = (struct spl_pbuf *) ADDR_SHTOL (header);
+ while (tmp)
+ {
+ tmp->tot_len += p->len;
+ tmp = (struct spl_pbuf *) ADDR_SHTOL (tmp->next);
+ }
+
+ *tail = (struct spl_pbuf *) ADDR_LTOSH (p); /* header will changed to share */
+ tail = &p->next;
+
+ remain_len -= copy_len;
+ head_len = L2_L3_ROOM_LEN;
+ }
+ while (remain_len);
+
+ /*udp support len=0 */
+ if (size != 0)
+ {
+ if (sbr_copy_iov
+ (sk, iov, iovcnt, (struct spl_pbuf *) ADDR_SHTOL (header)) != 0)
+ {
+ sbr_handle_free_send_buf (sk,
+ (struct spl_pbuf *) ADDR_SHTOL (header));
+ return -1;
+ }
+ }
+
+ buf.p = header;
+ err = sbr_handle_udp_send (sk, &buf, &local_ip);
+ if (0 == err)
+ {
+ epoll_triggle_event_from_api (sk, EPOLL_API_OP_SEND);
+ //ss_set_send_event(sbr_get_conn(sk), 1);
+ return size;
+ }
+ else
+ {
+ sbr_handle_free_send_buf (sk, (struct spl_pbuf *) ADDR_SHTOL (buf.p));
+ return -1;
+ }
+
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_sendto
+* Description : sendto
+* Input : sbr_socket_t * sk
+* const void * data
+* size_t size
+* int flags
+* const struct sockaddr * to
+* socklen_t tolen
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_sendto (sbr_socket_t * sk, const void *data, size_t size, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ struct iovec iov;
+
+ iov.iov_base = (void *) data;
+ iov.iov_len = size;
+ return sbr_udp_senddata (sk, &iov, 1, flags, to, tolen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_send
+* Description : send
+* Input : sbr_socket_t * sk
+* const void * data
+* size_t size
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_send (sbr_socket_t * sk, const void *data, size_t size, int flags)
+{
+ return sk->fdopt->sendto (sk, data, size, flags, NULL, 0);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_sendmsg
+* Description : send msg
+* Input : sbr_socket_t * sk
+* const struct msghdr * pmsg
+* int flags
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_sendmsg (sbr_socket_t * sk, const struct msghdr *pmsg, int flags)
+{
+ return sbr_udp_senddata (sk, pmsg->msg_iov, pmsg->msg_iovlen, flags,
+ (struct sockaddr *) pmsg->msg_name,
+ pmsg->msg_namelen);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_writev
+* Description : writev
+* Input : sbr_socket_t * sk
+* const struct iovec * iov
+* int iovcnt
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_writev (sbr_socket_t * sk, const struct iovec *iov, int iovcnt)
+{
+ return sbr_udp_senddata (sk, iov, iovcnt, 0, NULL, 0);
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_fcntl
+* Description : fcntl
+* Input : sbr_socket_t * sk
+* int cmd
+* long arg
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_fcntl (sbr_socket_t * sk, int cmd, long arg)
+{
+ int ret = 0;
+
+ switch (cmd)
+ {
+ case F_GETFL:
+ ret = ss_get_nonblock_flag (sbr_get_conn (sk));
+ NSSBR_LOGDBG ("F_GETFL]fd=%d,ret=%d", sk->fd, ret);
+ break;
+ case F_SETFL:
+ if (arg & O_NONBLOCK)
+ {
+ NSSBR_LOGDBG ("F_SETFL set O_NONBLOCK val]fd=%d,arg=%ld", sk->fd,
+ arg);
+ ss_set_nonblock_flag (sbr_get_conn (sk), (arg & O_NONBLOCK));
+ }
+ else
+ {
+ NSSBR_LOGDBG ("F_SETFL clean O_NONBLOCK val]fd=%d,arg=%ld", sk->fd,
+ arg);
+ ss_set_nonblock_flag (sbr_get_conn (sk), 0);
+ }
+
+ break;
+ default:
+ NSSBR_LOGERR ("cmd is not support]fd=%d,cmd=%d", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno (sk, EINVAL);
+
+ break;
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_ioctl
+* Description : ioctl
+* Input : sbr_socket_t * sk
+* unsigned long cmd
+* void * arg
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_ioctl (sbr_socket_t * sk, unsigned long cmd, void *arg)
+{
+ int ret = 0;
+
+ switch (cmd)
+ {
+ case FIONREAD:
+ {
+ if (!sbr_com_try_lock_recv (sk))
+ {
+ return 0;
+ }
+
+ struct spl_pbuf *p = NULL;
+ struct spl_netbuf *buf = NULL;
+ if (!sbr_get_fd_share (sk)->lastdata)
+ {
+ ret = sbr_udp_recv_from_ring (sk, &buf, -1);
+ if (ret != 0)
+ {
+ sbr_com_unlock_recv (sk);
+ return EWOULDBLOCK == errno ? 0 : -1;
+ }
+
+ sbr_get_fd_share (sk)->lastdata = (void *) ADDR_LTOSH (buf);
+ p = (struct spl_pbuf *) ADDR_SHTOL (buf->p);
+ }
+ else
+ {
+ buf =
+ (struct spl_netbuf *)
+ ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata);
+ p = (struct spl_pbuf *) ADDR_SHTOL (buf->p);
+ }
+
+ *((u32 *) arg) = p->tot_len;
+ sbr_com_unlock_recv (sk);
+ }
+ break;
+ case FIONBIO:
+ {
+ u8 val = 0;
+
+ if (arg && *(u32 *) arg)
+ {
+ val = 1;
+ }
+
+ ss_set_nonblock_flag (sbr_get_conn (sk), val);
+ NSSBR_LOGDBG ("FIONBIO]fd=%d,val=%u", sk->fd, val);
+ }
+ break;
+ default:
+ {
+ NSSBR_LOGERR ("cmd is not support]fd=%d,cmd=%lu", sk->fd, cmd);
+ ret = -1;
+ sbr_set_sk_errno (sk, ENOTTY);
+ }
+
+ break;
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+* Prototype : sbr_udp_close
+* Description : close
+* Input : sbr_socket_t * sk
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+sbr_udp_close (sbr_socket_t * sk)
+{
+ if (sbr_get_fd_share (sk)->lastdata)
+ {
+ struct spl_netbuf *buf = ADDR_SHTOL (sbr_get_fd_share (sk)->lastdata);
+ struct spl_pbuf *p = (struct spl_pbuf *) ADDR_SHTOL (buf->p);
+ sbr_com_free_recv_buf (sk, p);
+ }
+
+ /* if failed,free it in recycle */
+ return sbr_handle_close (sk, 0);
+}
+
+sbr_fdopt udp_fdopt = {
+ .socket = sbr_udp_socket,
+ .bind = sbr_udp_bind,
+ .listen = sbr_udp_listen,
+ .accept = sbr_udp_accept,
+ .accept4 = sbr_udp_accept4,
+ .connect = sbr_udp_connect,
+ .shutdown = sbr_udp_shutdown,
+ .getsockname = sbr_udp_getsockname,
+ .getpeername = sbr_udp_getpeername,
+ .getsockopt = sbr_udp_getsockopt,
+ .setsockopt = sbr_udp_setsockopt,
+ .recvfrom = sbr_udp_recvfrom,
+ .readv = sbr_udp_readv,
+ .recvmsg = sbr_udp_recvmsg,
+ .send = sbr_udp_send,
+ .sendto = sbr_udp_sendto,
+ .sendmsg = sbr_udp_sendmsg,
+ .writev = sbr_udp_writev,
+ .fcntl = sbr_udp_fcntl,
+ .ioctl = sbr_udp_ioctl,
+ .close = sbr_udp_close,
+ .peak = sbr_com_peak,
+ .lock_common = sbr_com_lock_common,
+ .unlock_common = sbr_com_unlock_common,
+ .ep_getevt = stackx_eventpoll_getEvt,
+ .ep_ctl = stackx_eventpoll_triggle,
+ .set_close_stat = NULL,
+};