summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/lwip_src/ip_module
diff options
context:
space:
mode:
authorsharath reddy <bs.reddy@huawei.com>2019-06-04 11:53:49 +0530
committersharath reddy <bs.reddy@huawei.com>2019-06-04 20:38:30 +0530
commit2a42ad20b9730706ad371ae3787d4597c4e42276 (patch)
treefa01cd312586ea007468e7233f94c0ce53d75873 /stacks/lwip_stack/lwip_src/ip_module
parenta826fe833d3f2a8fe2673fa05811fe1a22baf045 (diff)
Feature: 19.04 part-2DMM-2
Change-Id: I0b52a6bb67c25c7955d58e29eb81a3cc9efea9e9 Signed-off-by: sharath reddy <bs.reddy@huawei.com>
Diffstat (limited to 'stacks/lwip_stack/lwip_src/ip_module')
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c1039
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/container_ip.c1117
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c356
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/network.c1093
-rw-r--r--stacks/lwip_stack/lwip_src/ip_module/trp_rb_tree.c563
5 files changed, 4168 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..46bdc08
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/configuration_reader.c
@@ -0,0 +1,1039 @@
+/*
+*
+* 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)
+ {
+ NSTCP_LOGINF("Warning! It use the second search path ../configure");
+ tmp_config_path =
+ realpath("../configure/network_data_tonStack.json", NULL);
+ }
+
+ if (!tmp_config_path)
+ {
+ return 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)
+ {
+ NSTCP_LOGINF("Warning! It use the second search path ../configure");
+ tmp_config_path = realpath("../configure/ip_data.json", NULL);
+ }
+
+ if (!tmp_config_path)
+ {
+ return 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;
+ }
+
+ (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.
+
+ 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/log/nStack";
+ 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("CONFIGURATION", "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("CONFIGURATION", "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("CONFIGURATION", "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("CONFIGURATION", "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..1cbcfb3
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/container_ip.c
@@ -0,0 +1,1117 @@
+/*
+*
+* 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 "config_common.h"
+#include "igmp.h"
+#include "spl_def.h"
+#include "stackx_ip_addr.h"
+#include "nsfw_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;
+ }
+}
+
+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)
+ {
+ 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 */
+ NSOPR_LOGWAR("json_object_object_get_ex containerID failed");
+ }
+
+ 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..d7ba054
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/ip_module_api.c
@@ -0,0 +1,356 @@
+/*
+*
+* 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..d34c6a9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/ip_module/network.c
@@ -0,0 +1,1093 @@
+/*
+*
+* 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 "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 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;
+
+ 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)
+ && strncmp(tmp->nic_type_name, "vhost", strlen("vhost")))
+ {
+ 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, *nic_type_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, "nic_type", &nic_type_obj); /*lint !e534 no need to check return value */
+ if (nic_type_obj)
+ {
+ const char *nic_type_name =
+ json_object_get_string(nic_type_obj);
+ if (strcmp(nic_type_name, "pci") != 0
+ && strcmp(nic_type_name, "vhost") != 0)
+ {
+ NSOPR_LOGERR("unsupported nic_type]nic_type=%s",
+ nic_type_name);
+ goto RETURN_ERROR;
+ }
+
+ retVal =
+ strcpy_s(pst_network_configuration->nic_type_name,
+ sizeof(pst_network_configuration->nic_type_name),
+ nic_type_name);
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("strcpy_s failed]ret=%d", retVal);
+ goto RETURN_ERROR;
+ }
+ }
+ else
+ {
+ NSOPR_LOGINF
+ ("nic_type not specified, use default type]defaul nic_type=pci");
+ retVal =
+ strcpy_s(pst_network_configuration->nic_type_name,
+ sizeof(pst_network_configuration->nic_type_name),
+ "pci");
+ if (EOK != retVal)
+ {
+ NSOPR_LOGERR("strcpy_s failed]ret=%d", retVal);
+ 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;
+
+ 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..4f129d4
--- /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;
+}