aboutsummaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/lwip_src/ip_module
diff options
context:
space:
mode:
Diffstat (limited to 'stacks/lwip_stack/lwip_src/ip_module')
-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
5 files changed, 4250 insertions, 0 deletions
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;
+}