diff options
author | Swarup Nayak <swarupnpvt@gmail.com> | 2018-08-13 19:23:34 +0530 |
---|---|---|
committer | Swarup Nayak <swarupnpvt@gmail.com> | 2018-08-13 19:25:27 +0530 |
commit | 7dc65518819f2b453fd2837e92c115592d8832ec (patch) | |
tree | f9119bb3624ff11af480981c9904b84c172a607c /stacks/lwip_stack/lwip_src/api/spl_tcpip.c | |
parent | bd6e75c243db1b384ba0882ecaf9063ec4cd70bd (diff) |
Feat : LWIP integration part1
Change-Id: Ia26c092d16579c6f845a021ba66bde106363883a
Signed-off-by: Swarup Nayak <swarupnpvt@gmail.com>
Diffstat (limited to 'stacks/lwip_stack/lwip_src/api/spl_tcpip.c')
-rw-r--r-- | stacks/lwip_stack/lwip_src/api/spl_tcpip.c | 1548 |
1 files changed, 1548 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/api/spl_tcpip.c b/stacks/lwip_stack/lwip_src/api/spl_tcpip.c new file mode 100644 index 0000000..688c34b --- /dev/null +++ b/stacks/lwip_stack/lwip_src/api/spl_tcpip.c @@ -0,0 +1,1548 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "spl_opt.h" +#include <pthread.h> +#include <sched.h> +#include <signal.h> +#include "memp.h" +#include "mem.h" +#include "spl_pbuf.h" +//#include "sockets.h" +//#include <netinet/in.h> + +#include "stackx_spl_share.h" +#include "spl_api.h" +#include "spl_tcpip.h" +#include "init.h" +#include "stackx/internal_msg.h" +#include "netif/sc_dpdk.h" +#include "sharedmemory.h" +#include "stackx_instance.h" +#include "netif/common.h" +//#include "nettool/nettool.h" +#include "nstack_log.h" +#include "nstack_securec.h" +#include "spl_hal.h" +#include "spl_sbr.h" +#include "spl_tcpip.h" + +#include "spl_instance.h" +#include "nsfw_mem_api.h" +#include "nsfw_msg_api.h" +#include "configuration_reader.h" + +#include "nsfw_ps_api.h" +#include "alarm_api.h" +#include "nstack_share_res.h" +#include "spl_timers.h" + +#include "etharp.h" +#include "raw.h" +#include "udp.h" +#include "tcp.h" +#include "igmp.h" +#include "memp.h" +#include "inet.h" +#include "sys_arch.h" + +#include "sys.h" + +#define NSTACK_MAIN_MAX_PARA 19 +#define NSTACK_MAIN_MIN_PARA 1 + +#define DPDK_DEFAULT_EAL_MEM_SIZE (1024) + +#define OPT_EAL_MEM_SIZE "--eal-mem-size=" + +/********************/ +/* extern variables */ +/********************/ +extern mring_handle spl_get_msg_pool (); +extern mring_handle spl_get_conn_pool (); +extern u32 spl_get_conn_num (); +extern err_t ethernet_input (struct pbuf *p, struct netif *netif); + +/* tcpip main thread sleep time, configured by user(nStackMain "-sleep" option) */ +extern int g_tcpip_thread_sleep_time; + +/* netif related */ +extern struct stackx_port_info *head_used_port_list; + +extern u32_t uStackArgIndex; + +extern int g_tcpip_thread_stat; + +/********************/ +/* global variables */ +/********************/ + +/* timer thread id */ +sys_thread_t g_timerThread_id = 0; + +/*Add an associative mapping relationship to p_stackx_instance based on lcore_id */ + +int globalArgc = 0; + +/* Set different mem args to PAL and EAL */ +char **gArgv = NULL; + +int g_dpdk_argc = 0; +char **g_dpdk_argv = NULL; + +/*The sum of the four queue processing messages does not exceed TASK_BURST*/ +static u32 g_highestMboxNum = 12; +static u32 g_mediumMboxNum = 8; +static u32 g_lowestMboxNum = 4; +static u32 g_primaryMboxNum = 8; + +/* [set ip_tos2prio size to IPTOS_TOS_MASK >> 1) + 1] */ +u8_t ip_tos2prio[(IPTOS_TOS_MASK >> 1) + 1] = { + TC_PRIO_BESTEFFORT, + ECN_OR_COST (FILLER), + TC_PRIO_BESTEFFORT, + ECN_OR_COST (BESTEFFORT), + TC_PRIO_BULK, + ECN_OR_COST (BULK), + TC_PRIO_BULK, + ECN_OR_COST (BULK), + TC_PRIO_INTERACTIVE, + ECN_OR_COST (INTERACTIVE), + TC_PRIO_INTERACTIVE, + ECN_OR_COST (INTERACTIVE), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST (INTERACTIVE_BULK), + TC_PRIO_INTERACTIVE_BULK, + ECN_OR_COST (INTERACTIVE_BULK) +}; + +/********************/ +/* extern functions */ +/********************/ +extern err_t ethernetif_init (struct netif *pnetif); +extern int nstack_stackx_init (int flag); +extern int nstack_rd_mng_int (int flag); +extern void tcp_sys_rmem_init (); +extern void ethernetif_packets_input (struct netif *pstnetif); + +/********************************/ +/* function forward declaration */ +/********************************/ + +static inline u32 priority_sched_mbox (struct stackx_stack *share_memory, + void **box, u32 n); +static inline char +rt_tos2priority (u8_t tos) +{ + return ip_tos2prio[IPTOS_TOS (tos) >> 1]; +} + +u64 +timer_get_threadid () +{ + return g_timerThread_id; +} + +#if (DPDK_MODULE != 1) +NSTACK_STATIC inline void +do_recv_task (struct disp_netif_list *dnlist, u16 index_task) +{ + struct netifExt *pnetifExt = NULL; + + while (dnlist) + { + struct netif *currentNetif = dnlist->netif; + dnlist = dnlist->next; + + pnetifExt = getNetifExt (currentNetif->num); + if (NULL == pnetifExt) + return; + + if (currentNetif != NULL && pnetifExt->num_packets_recv > index_task) + { + ethernetif_packets_input (currentNetif); + } + } +} + +static inline int +is_valid_sleep_time (int sleep_time) +{ +#define TCP_IP_THREAD_MAX_SLEEP_TIME 500 + if ((sleep_time < 0) || (sleep_time > TCP_IP_THREAD_MAX_SLEEP_TIME)) + { + return 0; + } + + return 1; +} + +static int +thread_init () +{ + sigset_t mask; + + if (0 != sigemptyset (&mask)) + { + NSTCP_LOGERR ("sigemptyset function call error"); + return -1; + } + + if (0 != sigaddset (&mask, SIGRTMIN)) + { + NSTCP_LOGERR ("sigaddset function call error"); + return -1; + } + + if ((pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0) + || (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)) + { + NSTCP_LOGERR ("pthread setcancel function call error"); + return -1; + } + + if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0) + { + NSPOL_LOGERR ("pthread_sigmask function call error"); + return -1; + } + + return 0; +} + +alarm_result +spl_socket_resource_check_func (void) +{ + + mring_handle conn_ring = spl_get_conn_pool (); + unsigned int rate_use = 0; + alarm_result ret_alarm; + u32 ring_size = 0, ring_not_used_count = 0; + u32 socket_num = spl_get_conn_num (); + + ring_size = nsfw_mem_ring_size (conn_ring); + + if (0 == socket_num) + { + /* assign a valid id, then return */ + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + return ret_alarm; + } + + ring_not_used_count = nsfw_mem_ring_using_count (conn_ring); + + rate_use = (ring_size - ring_not_used_count) * 100 / socket_num; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + + if (rate_use >= USEAGE_HIGHT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + NSPOL_LOGWAR (TCPIP_DEBUG, + "app using too much socket resources,the rate is bigger than 80%"); + } + else if (rate_use <= USEAGE_LOW) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_SOCKET; + + return ret_alarm; + +} + +alarm_result +spl_msg_buf_resource_check_func (void) +{ + + mring_handle msg_ring = spl_get_msg_pool (); + unsigned int rate_use = 0; + alarm_result ret_alarm; + u32 ring_size = 0, ring_not_used_count = 0; + + ring_size = nsfw_mem_ring_size (msg_ring); + + if (0 == ring_size) + { + /* assign a valid id, then return */ + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + return ret_alarm; + } + + ring_not_used_count = nsfw_mem_ring_using_count (msg_ring); + + rate_use = (ring_size - ring_not_used_count) * 100 / ring_size; + + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + + if (rate_use >= USEAGE_HIGHT) + { + ret_alarm.alarm_flag_get = ALARM_PRODUCT; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else if (rate_use <= USEAGE_LOW) + { + ret_alarm.alarm_flag_get = ALARM_CLEAN; + ret_alarm.alarm_id_get = ALARM_EVENT_NSTACK_RESOURCE_ALARM; + } + else + { + ret_alarm.alarm_id_get = ALARM_EVENT_MAX; + } + + ret_alarm.alarm_reason_get = ALARM_REASON_MSG_BUF; + + return ret_alarm; + +} + +NSTACK_STATIC int +tcpip_thread_init () +{ + if (thread_init () != 0) + { + return -1; + } + + if (!is_valid_sleep_time (g_tcpip_thread_sleep_time)) + { + g_tcpip_thread_sleep_time = 0; + } + + alarm_para tcp_alarm_para; + tcp_alarm_para.period_alarm.time_length = 5; /* 5 second period */ + tcp_alarm_para.alarm_reason_count = 2; /*both resource */ + tcp_alarm_para.func_alarm_check_period[0] = spl_socket_resource_check_func; + tcp_alarm_para.alarm_reason_set[0] = ALARM_REASON_SOCKET; + tcp_alarm_para.func_alarm_check_period[1] = spl_msg_buf_resource_check_func; + tcp_alarm_para.alarm_reason_set[1] = ALARM_REASON_MSG_BUF; + (void) ns_reg_alarm (ALARM_EVENT_NSTACK_RESOURCE_ALARM, ALARM_PERIOD_CHECK, + &tcp_alarm_para); + + ns_send_init_alarm (ALARM_EVENT_NSTACK_RESOURCE_ALARM); + + printmeminfo (); + return 0; +} + +sys_mbox_t +get_primary_box () +{ + return &p_def_stack_instance->lstack.primary_mbox; +} + +NSTACK_STATIC inline u16 +tcpip_netif_recv (struct disp_netif_list * nif_list) +{ + + u16 num_recv_task = 0, netif_packet_num; + + struct netif *tmpnetif = NULL; + struct netifExt *pnetifExt = NULL; + + while (nif_list) + { + tmpnetif = nif_list->netif; + + netif_packet_num = spl_hal_recv (tmpnetif, 0); + pnetifExt = getNetifExt (tmpnetif->num); + if (NULL == pnetifExt) + return 0; + + /* store the packet number in each netif */ + pnetifExt->num_packets_recv = netif_packet_num; + + /** + * num_recv_task is the maximum packets of the netif among + * all the netifs. + */ + if (num_recv_task < netif_packet_num) + { + num_recv_task = netif_packet_num; + } + + nif_list = nif_list->next; + } + + return num_recv_task; +} + +NSTACK_STATIC inline void +no_task_in_one_loop () +{ +} + +#endif + +/** + * Pass a received packet to tcpip_thread for input processing + * + * @param p the received packet, p->payload pointing to the Ethernet header or + * to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or + * SPL_NETIF_FLAG_ETHERNET flags) + * @param inp the network interface on which the packet was received + */ +err_t +spl_tcpip_input (struct pbuf *p, struct netif *inp) +{ + err_t ret; + NSPOL_LOGINF (TCPIP_DEBUG, "PACKET]p=%p,inp=%p", (void *) p, (void *) inp); + print_pbuf_payload_info (p, false); + + /* every netif has been set NETIF_FLAG_ETHARP flag, no need else branch */ + ret = ethernet_input (p, inp); + return ret; +} + +int +_do_spl_callback_msg (data_com_msg * m) +{ + NSPOL_LOGDBG (TCPIP_DEBUG, "tcpip_thread: CALLBACK]msg=%p", (void *) m); + + m->param.err = ERR_OK; + + msg_internal_callback *callback = (msg_internal_callback *) (m->buffer); + if (!callback->function) + { + NSTCP_LOGERR ("function ptr is null in SPL_TCPIP_MSG_CALLBACK msg"); + ASYNC_MSG_FREE (m); + return 0; + } + + callback->function (callback->ctx); + ASYNC_MSG_FREE (m); + + return 0; +} + +/***************************************************************************** +* Prototype : get_msgbox +* Description : According to the socket tos value to determine which priority queue to send +* Input : struct stackx_stack *sharedmemory, struct netconn *conn, enum api_msg_type type +* Output : Queue pointer +* Return Value : Queue pointer +* Calls : +* Called By : +* +*****************************************************************************/ +struct queue * +get_msgbox (int tos) +{ + struct stackx_stack *sharedmemory = &p_def_stack_instance->lstack; + + if ((MSG_PRIO_QUEUE_NUM < 3) || (0 == tos)) + { + return &sharedmemory->primary_mbox; + } + + char prio = rt_tos2priority ((u8_t) tos); + if ((TC_PRIO_INTERACTIVE == prio)) + { + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the highest mbox....."); + return &sharedmemory->priority_mbox[0]; + } + else if ((TC_PRIO_BESTEFFORT == prio) || (TC_PRIO_INTERACTIVE_BULK == prio)) + { + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the medium mbox....."); + return &sharedmemory->priority_mbox[1]; + } + else if ((TC_PRIO_BULK == prio) || (TC_PRIO_FILLER == prio)) + { + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the lowest mbox....."); + return &sharedmemory->priority_mbox[2]; + } + + NSPOL_LOGDBG (SOCKETS_DEBUG, "sent to the primary mbox....."); + return &sharedmemory->primary_mbox; +} + +/***************************************************************************** +* Prototype : priority_sched_mbox +* Description : According to the priority from the message queue to take +* the message to deal with each cycle to take the total number of messages +* not exceed to TASK_BURST +* Input : struct stackx_stack *sharedmemory, struct netconn *conn, enum api_msg_type type +* Output : Queue pointer +* Return Value : Queue pointer +* Calls : +* Called By : +* +*****************************************************************************/ +static inline u32 +priority_sched_mbox (struct stackx_stack *share_memory, void **box, u32 n) +{ + /* high:primary:medium:low -> 3:2:2:1(total:TASK_BURST) */ + if (unlikely + ((g_highestMboxNum + g_mediumMboxNum + g_primaryMboxNum + + g_lowestMboxNum) != n)) + { + g_mediumMboxNum = n >> 2; + g_lowestMboxNum = n >> 3; + g_primaryMboxNum = n >> 2; + g_highestMboxNum = + n - g_mediumMboxNum - g_primaryMboxNum - g_lowestMboxNum; + } + + u32 highestMboxNum = g_highestMboxNum; + u32 primaryMboxNum = g_primaryMboxNum; + u32 lowestMboxNum = g_lowestMboxNum; + u32 mediumMboxNum = g_mediumMboxNum; + + u32 totalNum = 0; + u32 num = 0; + u32 oldLowestNum = 0; + + num = nsfw_mem_ring_dequeuev (share_memory->priority_mbox[0].llring, + (box + totalNum), highestMboxNum); + if (unlikely (num > highestMboxNum)) + { + num = highestMboxNum; + NSTCP_LOGERR + ("something wrong:num>highestMboxNum]num=%u,highestMboxNum=%u", num, + highestMboxNum); + } + + totalNum += num; + + u32 temp = highestMboxNum - num; + /* bisect the left number of highest */ + primaryMboxNum += (temp >> 1); + mediumMboxNum += temp - (temp >> 1); + + num = nsfw_mem_ring_dequeuev (share_memory->priority_mbox[1].llring, + (box + totalNum), mediumMboxNum); + if (unlikely (num > mediumMboxNum)) + { + num = mediumMboxNum; + NSTCP_LOGERR + ("something wrong.num>mediumMboxNum]num=%u,mediumMboxNum=%u", num, + mediumMboxNum); + } + + totalNum += num; + primaryMboxNum += mediumMboxNum - num; //occupy the left number of medium + + /* dynamically adjust g_mediumMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_mediumMboxNum; + if (0 == num) + { + g_mediumMboxNum = 1; + } + else if (num < g_mediumMboxNum) + { + g_mediumMboxNum = num; + } + else + { + g_mediumMboxNum = n >> 2; + } + + g_highestMboxNum += oldLowestNum - g_mediumMboxNum; + + num = nsfw_mem_ring_dequeuev (share_memory->primary_mbox.llring, + (box + totalNum), primaryMboxNum); + if (unlikely (num > primaryMboxNum)) + { + num = primaryMboxNum; + NSTCP_LOGERR + ("something wrong.num>primaryMboxNum]num=%u,primaryMboxNum=%u", num, + primaryMboxNum); + } + + totalNum += num; + lowestMboxNum += primaryMboxNum - num; //occupy the left number of primary + + /* dynamically adjust g_primaryMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_primaryMboxNum; + if (0 == num) + { + g_primaryMboxNum = 1; + } + else if (num < g_primaryMboxNum) + { + g_primaryMboxNum = num; + } + else + { + g_primaryMboxNum = n >> 2; + } + + g_highestMboxNum += oldLowestNum - g_primaryMboxNum; + + if (lowestMboxNum > (n - totalNum)) + { + lowestMboxNum = n - totalNum; + } + + num = nsfw_mem_ring_dequeuev (share_memory->priority_mbox[2].llring, + (box + totalNum), lowestMboxNum); + if (unlikely (num > lowestMboxNum)) + { + num = lowestMboxNum; + NSTCP_LOGERR + ("something wrong.num>lowestMboxNum]num=%u,lowestMboxNum=%u", num, + lowestMboxNum); + } + + totalNum += num; + + /* dynamically adjust g_lowestMboxNum and g_highestMboxNum, according to 'num' */ + oldLowestNum = g_lowestMboxNum; + if (0 == num) + { + g_lowestMboxNum = 1; + } + else if (num < g_lowestMboxNum) + { + g_lowestMboxNum = num; + } + else + { + g_lowestMboxNum = n >> 3; + } + + g_highestMboxNum += oldLowestNum - g_lowestMboxNum; + + return totalNum; +} + +/** + * call ltt_apimsg in STACKX TIMER THREAD + * + * @param h function to be called on timeout + * @param arg argument to pass to timeout function h + * @return error code given back by the function that was called + */ +err_t +ltt_apimsg (sys_timeout_handler h, void *arg) +{ + data_com_msg *p_msg_entry; + sys_mbox_t mbox = get_primary_box (); + if (sys_mbox_valid (&mbox)) + { + if (-1 == spl_msg_malloc (&p_msg_entry)) + { + NSPOL_LOGERR ("ltt_apimsg:spl_msg_malloc failed."); + return -1; + } + + p_msg_entry->param.module_type = MSG_MODULE_TIMER; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_TIMER; + p_msg_entry->param.minor_type = TIMER_MSG_TIMEOUT; + p_msg_entry->param.op_type = MSG_ASYN_POST; + + sys_sem_init (&p_msg_entry->param.op_completed); + + msg_timer *tmsg = (msg_timer *) (p_msg_entry->buffer); + tmsg->act = h; + tmsg->arg = arg; + + if (msg_post (p_msg_entry, mbox->llring) < 0) + { + NSPOL_LOGERR + ("msg post is failed]module_type=%u, major_type=%u, minor_type=%u", + p_msg_entry->param.module_type, p_msg_entry->param.major_type, + p_msg_entry->param.minor_type); + spl_msg_free (p_msg_entry); + return ERR_VAL; + } + + return ERR_OK; + } + + NSPOL_LOGERR ("mbox is invalid"); + return ERR_VAL; +} + +int +_do_spl_timer_msg (data_com_msg * m) +{ + NSPOL_LOGDBG (TESTSOCKET_DEBUG | STACKX_DBG_TRACE, + "the msg is from TIMER module, minor(%u)", + m->param.minor_type); + return 0; +} + +static int +_do_timeout_handle (data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_timer *tmo_msg = (msg_timer *) m->buffer; + if (!tmo_msg->act) + { + NSTCP_LOGERR ("TIMER_MSG_TIMEOUT msg act is NULL"); + ASYNC_MSG_FREE (m); + return -1; + } + + timeout_phandler (tmo_msg->act, tmo_msg->arg); + ASYNC_MSG_FREE (m); + return 0; +} + +static int +_do_clear_timer (data_com_msg * m) +{ + NSTCP_LOGDBG ("TIMER_CLEAR API]msg=%p", (void *) m); + + msg_timer *handle = (msg_timer *) (m->buffer); + if (!handle->act) + { + NSTCP_LOGERR ("function ptr is null in TIMER_MSG_CLEAR msg"); + SET_MSG_ERR (m, ERR_VAL); + return 0; + } + + //stackxTcpPcbClearTimer((struct tcp_pcb *)handle->act, (unsigned long)handle->arg); + spl_msg_free (m); + + return 0; +} + +err_t +ltt_clearTmrmsg (void *pcb, void *arg) +{ + data_com_msg *p_msg_entry; + sys_mbox_t mbox = get_primary_box (); + if (sys_mbox_valid (&mbox)) + { + if (-1 == spl_msg_malloc (&p_msg_entry) || (NULL == p_msg_entry)) + { + NSPOL_LOGERR ("ltt_clearTmrmsg:spl_msg_malloc failed."); + return -1; + } + + p_msg_entry->param.module_type = MSG_MODULE_TIMER; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_TIMER; + p_msg_entry->param.minor_type = TIMER_MSG_CLEAR; + p_msg_entry->param.op_type = MSG_ASYN_POST; + p_msg_entry->param.receiver = 0; + sys_sem_init (&p_msg_entry->param.op_completed); + + msg_timer *tmo = (msg_timer *) (p_msg_entry->buffer); + tmo->act = pcb; + tmo->arg = arg; + + if (msg_post (p_msg_entry, mbox->llring) < 0) + { + NSPOL_LOGERR + ("msg post is failed]module_type=%u, major_type=%u, minor_type=%u", + p_msg_entry->param.module_type, p_msg_entry->param.major_type, + p_msg_entry->param.minor_type); + spl_msg_free (p_msg_entry); + return ERR_VAL; + } + + return ERR_OK; + } + + NSPOL_LOGERR ("mbox is invalid"); + return ERR_VAL; +} + +#if STACKX_NETIF_API +err_t +tcpip_netif_post (data_com_msg * m) +{ + err_t err = ERR_OK; + sys_mbox_t mbox = get_primary_box (); + + if (NULL == mbox || !sys_mbox_valid (&mbox)) + { + NSPOL_LOGERR ("mbox not initialed well"); + err = ERR_MEM; + goto err_exit; + } + + if (NULL == mbox->llring) + { + int tryCount = 0; +#define TCP_NETIF_WAITINIT_MAX_COUNT 10 + NSPOL_LOGWAR (TCPIP_DEBUG, "mbox->llring not initialed yet..."); + sys_sleep_ns (0, 100000000); + while (!mbox->llring && (++tryCount < TCP_NETIF_WAITINIT_MAX_COUNT)) + { + NSPOL_LOGWAR (TCPIP_DEBUG, "mbox->llring not initialed yet..."); + sys_sleep_ns (0, 100000000); + } + + if (NULL == mbox->llring) + { + NSPOL_LOGERR ("failed to get a valid mbox->llring"); + err = ERR_MEM; + goto err_exit; + } + } + + NSPOL_LOGINF (TCPIP_DEBUG, "post tcpip_netif_msg..."); + + if (msg_post_with_lock_rel (m, mbox->llring) < 0) + { + err = ERR_VAL; + } + else + { + err = m->param.err; + } + +err_exit: + /* it's a sync message */ + spl_msg_free (m); + return err; +} + +/** + * Much like tcpip_apimsg, but calls the lower part of a netifapi_* + * function. + * + * @param netifapimsg a struct containing the function to call and its parameters + * @return error code given back by the function that was called + */ +err_t +tcpip_netif_add (msg_add_netif * tmp) +{ + data_com_msg *p_msg_entry = NULL; + msg_add_netif *nmsg = NULL; + + if (spl_msg_malloc (&p_msg_entry) == -1) + { + NSPOL_LOGERR ("tcpip_netifapi:spl_msg_malloc failed."); + return ERR_MEM; + } + + p_msg_entry->param.module_type = MSG_MODULE_HAL; + p_msg_entry->param.major_type = SPL_TCPIP_MSG_NETIFAPI; + p_msg_entry->param.minor_type = NETIF_DO_ADD; + p_msg_entry->param.op_type = MSG_SYN_POST; + p_msg_entry->param.receiver = 0; + sys_sem_init (&p_msg_entry->param.op_completed); + + nmsg = (msg_add_netif *) p_msg_entry->buffer; + nmsg->function = tmp->function; + nmsg->netif = tmp->netif; + nmsg->ipaddr = tmp->ipaddr; + nmsg->netmask = tmp->netmask; + nmsg->gw = tmp->gw; + nmsg->state = tmp->state; + nmsg->init = tmp->init; + nmsg->input = tmp->input; + nmsg->voidfunc = tmp->voidfunc; + + return tcpip_netif_post (p_msg_entry); +} + +#endif /* STACKX_NETIF_API */ + +/* Added for congestion control, maybe not used end */ + +extern err_t init_ptimer (void); +extern struct cfg_item_info g_cfg_item_info[CFG_SEG_MAX][MAX_CFG_ITEM]; + +/*=========== set share config for nStackMain =============*/ +static inline mzone_handle +create_mem_zone (nsfw_mem_zone * zone_info) +{ + return nsfw_mem_zone_create (zone_info); +} + +static inline int +set_zone_info (nsfw_mem_zone * zone_info, nsfw_mem_name * name_info, u32 len) +{ + if (EOK != + MEMCPY_S (&(zone_info->stname), sizeof (nsfw_mem_name), name_info, + sizeof (nsfw_mem_name))) + { + NSPOL_DUMP_LOGERR ("create pool failed, MEMCPY_S failed."); + return -1; + } + + zone_info->length = len; + zone_info->isocket_id = NSFW_SOCKET_ANY; + + return 0; +} + +int +set_share_config () +{ + static nsfw_mem_name g_cfg_mem_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, NSTACK_SHARE_CONFIG }; + + nsfw_mem_zone zone_info; + if (set_zone_info (&zone_info, &g_cfg_mem_info, get_cfg_share_mem_size ()) < + 0) + { + return -1; + } + + mzone_handle base_cfg_mem = create_mem_zone (&zone_info); + if (NULL == base_cfg_mem) + { + NSPOL_LOGERR ("get config share mem failed."); + return -1; + } + + if (set_share_cfg_to_mem (base_cfg_mem) < 0) + { + NSPOL_LOGERR ("set share config failed."); + return -1; + } + + return 0; +} + +int +init_by_tcpip_thread () +{ + if (spl_init_app_res () != 0) + { + NSPOL_LOGERR ("spl_init_app_res failed"); + return -1; + } + + if (init_instance () != 0) + { + return -1; + } + if (tcpip_thread_init () != 0) + { + NSTCP_LOGERR ("tcpip_thread_init failed!"); + return -1; + } + + init_stackx_lwip (); + + return 0; +} + +void +spl_tcpip_thread (void *arg) +{ + g_tcpip_thread_stat = 1; + + if (init_by_tcpip_thread () != 0) + { + return; + } + + struct stackx_stack *share_memory = &p_def_stack_instance->lstack; + struct disp_netif_list **iflist = &p_def_stack_instance->netif_list; + + u32 run_count = 0; + u16 task_loop; + u16 num_recv_task = 0, num_send_timer_task = 0; + u16 index_task = 0; + int tcpip_thread_sleep_interval = g_tcpip_thread_sleep_time * 1000; + void *task_queue[TASK_BURST]; + data_com_msg *msg; + + while (1) + { + /* try to receive packet from hal layer */ + num_recv_task = tcpip_netif_recv (*iflist); + + /* try to receive message from sbr layer */ + num_send_timer_task = priority_sched_mbox (share_memory, + task_queue, TASK_BURST); + + if (num_recv_task) + { + NSPOL_LOGINF (TCPIP_DEBUG, "num_recv_task %d", num_recv_task); + } + + /* Statistics the total number of messages */ + + /* Separate statistics on socket api messages */ + /* handle the request from upper layer and lower layer one by one */ + task_loop = (num_send_timer_task > num_recv_task ? + num_send_timer_task : num_recv_task); + if (task_loop == 0) + { + no_task_in_one_loop (); + + if (run_count++ > 20) + { + sys_sleep_ns (0, tcpip_thread_sleep_interval); + } + continue; + } + + run_count = 0; + index_task = 0; + + /* at least one task to be handled */ + while (task_loop > index_task) + { + /* handle one packet from hal layer (for multi-nic case, do it for each) */ + if (num_recv_task > index_task) + { + do_recv_task (*iflist, index_task); + } + + /* handle one message from sbr layer */ + if (num_send_timer_task > index_task) + { + msg = (data_com_msg *) (task_queue[index_task]); + + spl_process (msg); + } + + do_update_pcbstate (); + + index_task++; + } + } +} + +int +create_tcpip_thread () +{ + int ret; + u64 arg = 0; + + /* main tcpip thread */ + char thread_name[32] = TCPIP_THREAD_NAME; + + sys_thread_t thread = sys_thread_new (thread_name, spl_tcpip_thread, + (void *) arg, + TCPIP_THREAD_STACKSIZE, + g_cfg_item_info[CFG_SEG_PRI] + [CFG_SEG_THREAD_PRI_PRI].value); + + cpu_set_t cpuset; + CPU_ZERO (&cpuset); /*lint !e534 */ + CPU_SET (g_nstack_bind_cpu, &cpuset); /*lint !e522 */ + ret = pthread_setaffinity_np (thread, sizeof (cpuset), &cpuset); + if (ret != 0) + { + NSPOL_LOGERR ("pthread_setaffinity_np failed]thread_name=%s,ret=%d", + TCPIP_THREAD_NAME, ret); + } + + return 0; +} + +int +create_timer_thread () +{ +#if 1 + if (init_ptimer () != ERR_OK) + { + NSPOL_LOGERR ("init_ptimer failed"); + return -1; + } + + sys_thread_t thread_timer = + sys_thread_new (PTIMER_THREAD_NAME, ptimer_thread, NULL, + TCPIP_THREAD_STACKSIZE, 0); + cpu_set_t cpuset_timer; + CPU_ZERO (&cpuset_timer); + CPU_SET (1, &cpuset_timer); + int ret = pthread_setaffinity_np (thread_timer, sizeof (cpuset_timer), + &cpuset_timer); + if (ret != 0) + { + NSPOL_LOGERR ("TCP init Timer Trhead Failed!"); + } + + g_timerThread_id = thread_timer; +#endif + return 0; +} + +int +init_ip_module_reader () +{ + output_api api = { 0 }; + api.post_to = post_ip_module_msg; + api.add_netif_ip = add_netif_ip; + api.del_netif_ip = del_netif_ip; + regist_output_api (&api); + + if (init_configuration_reader () < 0) + { + NSPOL_LOGERR ("init_configuration_reader failed"); + return -1; + } + + return 0; +} + +extern int init_unmatch_version (void); +extern int init_stackx_global_tick (void); + +int +init_by_main_thread () +{ + NSPOL_LOGINF (TCPIP_DEBUG, "init_by_main_thread start version 1.4"); + + uStackArgIndex++; + if (spl_hal_init (g_dpdk_argc, (char **) g_dpdk_argv) < 0) + { + NSPOL_LOGERR ("spl_hal_init failed"); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 1"); + + if (init_unmatch_version () != 0) + { + return -1; + } + + NSPOL_LOGINF (TCPIP_DEBUG, "stage 2"); + if (init_stackx_global_tick () != 0) + { + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 3"); + + if (spl_init_group_array () != 0) + { + NSPOL_LOGERR ("spl_init_group_array failed"); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 4"); + + if (set_share_config () != 0) + { + NSPOL_LOGERR ("set_share_config failed."); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 5"); + + if (create_timer_thread () != 0) + { + //NSPOL_LOGERR(TCPIP_DEBUG,"init_timer_thread failed."); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 6"); + + if (create_tcpip_thread () != 0) + { + NSPOL_LOGERR ("init_tcpip_thread failed."); + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage 7"); + + if (init_ip_module_reader () != 0) + { + return -1; + } + NSPOL_LOGINF (TCPIP_DEBUG, "stage end"); + + return 0; +} + +void +create_netif (struct stackx_port_info *p_port_info) +{ + int ret; + struct spl_ip_addr ip, mask, gw; + struct netifExt *netifEx = NULL; + struct netif *netif = malloc (sizeof (struct netif)); + if (!netif) + { + NSPOL_LOGERR ("malloc failed"); + return; + } + + if (MEMSET_S (netif, sizeof (struct netif), 0, sizeof (struct netif)) < 0) + { + NSPOL_LOGERR ("MEMSET_S failed"); + goto error; + } + + NSPOL_LOGINF (TCPIP_DEBUG, "I get netif]ip=%s,gw=%s,mask=%s,name=%c %c", + p_port_info->linux_ip.ip_addr_linux, + p_port_info->linux_ip.ip_addr_linux, + p_port_info->linux_ip.mask_linux, + netif->name[0], netif->name[1]); + + if (inet_aton (p_port_info->linux_ip.ip_addr_linux, &ip) + && inet_aton (p_port_info->linux_ip.ip_addr_linux, &gw) + && inet_aton (p_port_info->linux_ip.mask_linux, &mask)) + { + ret = + spl_netifapi_netif_add (netif, &ip, &mask, &gw, NULL, ethernetif_init, + spl_tcpip_input, netif_set_up); + if (ERR_OK != ret) + { + NSPOL_LOGERR ("netifapi_netif_add failed]ret=%d", ret); + goto error; + } +#if 1 + if (0 != netifExt_add (netif)) + return; + +#endif + netifEx = getNetifExt (netif->num); + if (NULL == netifEx) + return; + + netifEx->hdl = p_port_info->linux_ip.hdl; + ret = + STRCPY_S (netifEx->if_name, sizeof (netifEx->if_name), + p_port_info->linux_ip.if_name); + if (EOK != ret) + { + NSPOL_LOGERR ("STRCPY_S failed]ret=%d", ret); + goto error; + } + return; + } + +error: + free (netif); +} + +int +post_ip_module_msg (void *arg, ip_module_type Type, + ip_module_operate_type operate_type) +{ + data_com_msg *p_msg_entry; + msg_ip_module *imsg; + sys_mbox_t mbox = get_primary_box (); + + if (!mbox) + { + NSOPR_LOGERR ("get_cur_mbox failed"); + return ERR_MEM; + } + + if (sys_mbox_valid (&mbox)) + { + if (spl_msg_malloc (&p_msg_entry) == -1) + { + NSOPR_LOGERR ("ip_route_apimsg:spl_msg_malloc failed."); + return ERR_MEM; + } + + sys_sem_init (&p_msg_entry->param.op_completed); + p_msg_entry->param.module_type = MSG_MODULE_IP; + p_msg_entry->param.op_type = MSG_SYN_POST; + + imsg = (msg_ip_module *) (p_msg_entry->buffer); + imsg->arg = arg; + imsg->type = Type; + imsg->operate_type = operate_type; + + NSOPR_LOGINF ("post ip_module msg to tcpip_thread]action=%d,type=%d", + operate_type, Type); + + if (msg_post (p_msg_entry, mbox->llring) != 0) + { + NSOPR_LOGERR + ("msg_post failed,this can not happen]action=%d,type=%d", + operate_type, Type); + } + + spl_msg_free (p_msg_entry); + + return ERR_OK; + } + + NSOPR_LOGERR ("mbox is invalid"); + return ERR_VAL; +} + +int +process_ip_module_msg (void *arg, ip_module_type module_type, + ip_module_operate_type operate_type) +{ + int retval = process_configuration (arg, module_type, operate_type); + + NSOPR_LOGINF ("tcpip_thread: ip_module cmd exec over, send SYNC_MSG_ACK"); + return retval; +} + +int +init_new_network_configuration () +{ + if (spl_hal_port_init () < 0) + { + return -1; + } + + return 0; +} + +static int +_process_ip_module_msg (data_com_msg * m) +{ + m->param.err = ERR_OK; + msg_ip_module *_m = (msg_ip_module *) m->buffer; + int ret = process_ip_module_msg (_m->arg, _m->type, _m->operate_type); + SYNC_MSG_ACK (m); + return ret; +} + +int +spl_post_msg (u16 mod, u16 maj, u16 min, u16 op, char *data, u16 data_len, + u32 src_pid) +{ + data_com_msg *p_msg_entry; + + sys_mbox_t mbox = get_primary_box (); + if (!sys_mbox_valid (&mbox)) + { + NSPOL_LOGERR + ("get mbox null!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", mod, maj, + min, op, data, data_len); + return ERR_MEM; + } + + if (spl_msg_malloc (&p_msg_entry) == -1) + { + NSPOL_LOGERR ("get msg null!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", + mod, maj, min, op, data, data_len); + return ERR_MEM; + } + + sys_sem_init (&p_msg_entry->param.op_completed); + p_msg_entry->param.module_type = mod; + p_msg_entry->param.major_type = maj; + p_msg_entry->param.minor_type = min; + p_msg_entry->param.op_type = op; + p_msg_entry->param.src_pid = src_pid; + + int retVal; + if (NULL != data) + { + retVal = + MEMCPY_S ((char *) p_msg_entry->buffer, sizeof (p_msg_entry->buffer), + data, data_len); + if (EOK != retVal) + { + NSPOL_LOGERR ("MEMCPY_S failed %d.", retVal); + spl_msg_free (p_msg_entry); + return ERR_MEM; + } + } + + if (msg_post_with_lock_rel (p_msg_entry, mbox->llring) != 0) + { + NSPOL_LOGERR + ("post msg error!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", mod, + maj, min, op, data, data_len); + spl_msg_free (p_msg_entry); + return ERR_MEM; + } + + if (MSG_SYN_POST == op) + { + spl_msg_free (p_msg_entry); + } + + NSOPR_LOGDBG ("post msg suc!]mod=%u,maj=%u,min=%u,op=%u,data=%p,len=%u", + mod, maj, min, op, data, data_len); + return ERR_OK; +} + +/* +* Added by eliminate duplicated code degree, the function is moved to the public places +*adjust memory size for pal and eal mem size: this func do the following things: +*1. copy argv to gArgv and g_dpdk_argv +*2. remove OPT_EAL_MEM_SIZE option so that the rtp and rte options process won't reprt unrecognized option error. +*3. set eal mem size and pal_mem_size = mem - eal_mem_size +*/ +int +adjust_mem_arg (int argc, char *argv[]) +{ + int i = 0; + int j = 0; + int retVal; + char *tmp = NULL; + char *tmp2 = NULL; + int arg_mem_index = -1; + char *saveptr1 = NULL; + int mem_size = 0; + int mem_size_parsed = 0; // if multi -m argument is set, then only deal with the first one + int eal_mem_size = DPDK_DEFAULT_EAL_MEM_SIZE; // Default + + if ((argc < NSTACK_MAIN_MIN_PARA) || (argc > NSTACK_MAIN_MAX_PARA)) + { + NSPOL_LOGERR ("The number of parameters is incorrect"); + return -1; + } + + globalArgc = argc; + g_dpdk_argc = argc; + gArgv = (char **) malloc (sizeof (char *) * argc); + if (gArgv == NULL) + { + NSPOL_LOGERR ("Failed to alloc memory for adjust mem args\n"); + goto ERROR_INIT; + } + + g_dpdk_argv = (char **) malloc (sizeof (char *) * argc); + if (g_dpdk_argv == NULL) + { + NSPOL_LOGERR ("Failed to alloc memory for adjust mem args\n"); + goto ERROR_INIT; + } + + retVal = + MEMSET_S (gArgv, sizeof (char *) * argc, 0, sizeof (char *) * argc); + if (EOK != retVal) + { + NSPOL_LOGERR ("MEMSET_S failed %d.", retVal); + goto ERROR_INIT; + } + retVal = + MEMSET_S (g_dpdk_argv, sizeof (char *) * argc, 0, sizeof (char *) * argc); + if (EOK != retVal) + { + NSPOL_LOGERR ("MEMSET_S failed %d.", retVal); + goto ERROR_INIT; + } + + for (i = 0; i < argc; i++) + { + if (!strcmp ("-m", argv[i]) && !mem_size_parsed && (i + 1 < argc)) + { + gArgv[j] = argv[i]; + g_dpdk_argv[j] = argv[i]; + i++; + j++; + gArgv[j] = (char *) malloc (32); + g_dpdk_argv[j] = (char *) malloc (32); + /* gArgv[j] is NULL and g_dpdk_argv[j] isnot NULL, need free g_dpdk_argv[j] */ + arg_mem_index = j; + if ((!gArgv[j]) || (!g_dpdk_argv[j])) + { + NSPOL_LOGERR ("malloc failed."); + goto ERROR_PARSE_MALLOC; + } + mem_size = atoi (argv[i]); + /* add memory range check,avoid handle wrongly later begin */ + if (mem_size < 0) + { + goto ERROR_PARSE_MALLOC; + } + + j++; + mem_size_parsed = 1; + } + else + if (!strncmp (OPT_EAL_MEM_SIZE, argv[i], strlen (OPT_EAL_MEM_SIZE))) + { + tmp = strdup (argv[i]); + if (tmp == NULL) + { + goto ERROR_PARSE_MALLOC; + } + /* Always use re-entrant functions in multi-threaded environments */ + tmp2 = strtok_r (tmp, "=", &saveptr1); + tmp2 = strtok_r (NULL, "=", &saveptr1); + if (tmp2) + { + eal_mem_size = atoi (tmp2); + /* add memory range check,avoid handle wrongly later */ + if (eal_mem_size < 0) + { + free (tmp); + goto ERROR_PARSE_MALLOC; + } + } + free (tmp); + tmp = NULL; + /*remove this option since dpdk can't recognize it and may cause error. */ + /*so we should deduct the count by 1. */ + globalArgc -= 1; + g_dpdk_argc -= 1; + } + else + { + gArgv[j] = argv[i]; + g_dpdk_argv[j] = argv[i]; + j++; + } + } + + /* -m arg is set */ + if (arg_mem_index >= 0) + { + retVal = + SPRINTF_S (gArgv[arg_mem_index], 32, "%d", mem_size - eal_mem_size); + if (-1 == retVal) + { + NSPOL_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + goto ERROR_PARSE_MALLOC; + } + retVal = SPRINTF_S (g_dpdk_argv[arg_mem_index], 32, "%d", eal_mem_size); + if (-1 == retVal) + { + NSPOL_LOGERR ("SPRINTF_S failed]ret=%d", retVal); + goto ERROR_PARSE_MALLOC; + } + } + else + { + // do nothing for no mem arg and leave it for default process of pal and eal. + } + + return 0; +ERROR_PARSE_MALLOC: + if (arg_mem_index >= 0 && gArgv[arg_mem_index]) + { + free (gArgv[arg_mem_index]); + gArgv[arg_mem_index] = NULL; + } + + if (arg_mem_index >= 0 && g_dpdk_argv[arg_mem_index]) + { + free (g_dpdk_argv[arg_mem_index]); + g_dpdk_argv[arg_mem_index] = NULL; + } + +ERROR_INIT: + if (gArgv) + { + free (gArgv); + gArgv = NULL; + globalArgc = 0; + } + + if (g_dpdk_argv) + { + free (g_dpdk_argv); + g_dpdk_argv = NULL; + g_dpdk_argc = 0; + } + + return -1; +} + +REGIST_MSG_MODULE_FUN (MSG_MODULE_IP, _process_ip_module_msg); + +REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_SPL, SPL_TCPIP_MSG_CALLBACK, + _do_spl_callback_msg); + +REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + _do_spl_timer_msg); + +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + TIMER_MSG_TIMEOUT, _do_timeout_handle); + +REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_TIMER, SPL_TCPIP_MSG_TIMER, + TIMER_MSG_CLEAR, _do_clear_timer); |