/* * * Copyright (c) 2018 Huawei Technologies Co.,Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "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); }