aboutsummaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack
diff options
context:
space:
mode:
authorSwarup Nayak <swarupnpvt@gmail.com>2018-08-13 19:23:34 +0530
committerSwarup Nayak <swarupnpvt@gmail.com>2018-08-13 19:25:27 +0530
commit7dc65518819f2b453fd2837e92c115592d8832ec (patch)
treef9119bb3624ff11af480981c9904b84c172a607c /stacks/lwip_stack
parentbd6e75c243db1b384ba0882ecaf9063ec4cd70bd (diff)
Feat : LWIP integration part1
Change-Id: Ia26c092d16579c6f845a021ba66bde106363883a Signed-off-by: Swarup Nayak <swarupnpvt@gmail.com>
Diffstat (limited to 'stacks/lwip_stack')
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_api.c51
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_api_msg.c3259
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_netbuf.c58
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_netifapi.c288
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_sbr.c495
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_tcpip.c1548
-rw-r--r--stacks/lwip_stack/lwip_src/common/rb_tree.c393
-rw-r--r--stacks/lwip_stack/lwip_src/common/rb_tree.h112
-rw-r--r--stacks/lwip_stack/lwip_src/common/spl_def.h142
-rw-r--r--stacks/lwip_stack/lwip_src/common/spl_opt.h329
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_app_res.c972
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_app_res.h103
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_common.c357
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_common.h44
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_common_opt.h146
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_debug.h70
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_err.h68
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c280
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h82
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h146
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_netbuf.h43
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_pbuf.c223
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_pbuf.h82
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h109
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h239
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_spl_share.c198
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_spl_share.h478
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h42
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_tx_box.c64
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_tx_box.h39
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackx_types.h68
-rw-r--r--stacks/lwip_stack/lwip_src/common/stackxopts.h53
-rw-r--r--stacks/lwip_stack/lwip_src/core/global_tick.c48
-rw-r--r--stacks/lwip_stack/lwip_src/core/spl_pbuf.c597
-rw-r--r--stacks/lwip_stack/lwip_src/core/spl_timers.c608
-rw-r--r--stacks/lwip_stack/lwip_src/core/unmatch_version.c59
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/config_common.h64
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h26
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h39
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h222
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/network.h36
-rw-r--r--stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h77
-rw-r--r--stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h162
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/common.h233
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/kni_proc.h103
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h80
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h148
-rw-r--r--stacks/lwip_stack/lwip_src/include/netif/spl_hal.h114
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h90
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_api.h276
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h129
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_err.h40
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h30
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h52
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h173
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h33
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h252
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h80
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h108
-rw-r--r--stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h91
60 files changed, 14551 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/api/spl_api.c b/stacks/lwip_stack/lwip_src/api/spl_api.c
new file mode 100644
index 0000000..5c8af7d
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_api.c
@@ -0,0 +1,51 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "nsfw_init.h"
+//#include "sockets.h"
+//#include <netinet/in.h>
+
+#include "stackx_spl_share.h"
+#include "stackx/spl_api.h"
+//#include "stackx/ip.h"
+#include "sharedmemory.h"
+#include "spl_hal.h"
+#include "hal_api.h"
+#include "alarm_api.h"
+#include "nsfw_mt_config.h"
+#include "nsfw_recycle_api.h"
+#include "nstack_dmm_adpt.h"
+
+/* main entry for stackx */
+int
+spl_main_init (void *args)
+{
+ (void) args;
+ if (init_by_main_thread () < 0)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+NSFW_MODULE_NAME ("STACKX_MAIN")
+NSFW_MODULE_PRIORITY (10)
+NSFW_MODULE_DEPENDS (NSFW_ALARM_MODULE)
+NSFW_MODULE_DEPENDS (NSTACK_DMM_MODULE)
+NSFW_MODULE_INIT (spl_main_init)
+/* *INDENT-ON* */
diff --git a/stacks/lwip_stack/lwip_src/api/spl_api_msg.c b/stacks/lwip_stack/lwip_src/api/spl_api_msg.c
new file mode 100644
index 0000000..9ba1e92
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_api_msg.c
@@ -0,0 +1,3259 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "nsfw_msg.h"
+#include "spl_opt.h"
+#include "spl_ip_addr.h"
+//#include "stackx_socket.h"
+#include "cpuid.h"
+//#include "sockets.h"
+#include <netinet/in.h>
+#include <errno.h>
+
+#include "stackx_prot_com.h"
+#include "spl_api.h"
+//#include "stackx/ip.h"
+#include "sc_dpdk.h"
+#include "spl_sbr.h"
+//#include "maintain/spl_dfx.h"
+#include "stackx_tx_box.h"
+#include "spl_instance.h"
+#include "spl_sockets.h"
+
+#include "nstack_dmm_adpt.h"
+
+#include "tcp.h"
+#include "udp.h"
+#include "pbuf.h"
+#include "tcp_priv.h"
+#include "init.h"
+#include "timeouts.h"
+
+#include "stackx_pbuf_comm.h"
+#include "spl_netbuf.h"
+#include "spl_hal.h"
+#include "sys_arch.h"
+#include "tcpip.h"
+#include "debug.h"
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+
+extern struct tcp_pcb *tcp_bound_pcbs;
+extern union tcp_listen_pcbs_t tcp_listen_pcbs;
+extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
+ state in which they accept or send
+ data. */
+extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
+extern struct tcp_pcb **const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
+extern stackx_instance *p_def_stack_instance;
+extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER];
+
+#define TCP_FN_NULL 0
+#define TCP_FN_DEFAULT 1
+#define TCP_FN_STACKX 2
+#define TCP_FN_MAX 3
+
+struct callback_fn tcp_fn[TCP_FN_MAX] = {
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ {NULL, spl_tcp_recv_null, NULL, NULL, NULL, NULL},
+ {spl_sent_tcp, spl_recv_tcp, spl_do_connected, spl_poll_tcp, spl_err_tcp,
+ NULL, spl_accept_function},
+};
+
+// extern int nstack_get_nstack_fd_snapshot_from_proto_fd(int proto_fd);
+extern void tcp_drop_conn (spl_netconn_t * conn);
+extern void unlink_pcb (struct common_pcb *cpcb);
+extern struct queue *get_msgbox (int tos);
+
+#define SPL_SET_NONBLOCKING_CONNECT(conn, val) \
+do { \
+ if (val) \
+ { \
+ (conn)->flags |= SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \
+ } \
+ else \
+ { \
+ (conn)->flags &= ~SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \
+ } \
+ } while (0)
+
+#define SPL_IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0)
+
+extern int tcpip_thread_control;
+
+void
+spl_event_callback (struct spl_netconn *conn, enum spl_netconn_evt evt,
+ int postFlag)
+{
+ NSPOL_LOGDBG (SOCK_INFO, "Get event]conn=%p,evt=%d,postFlag=%d", conn, evt,
+ postFlag);
+ /* Get socket */
+ if (!conn)
+ {
+ NSPOL_LOGDBG (SOCK_INFO, "conn=NULL");
+ return;
+ }
+
+ switch (evt)
+ {
+ case SPL_NETCONN_EVT_RCVPLUS:
+ __sync_fetch_and_add (&conn->rcvevent, 1);
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLIN);
+ }
+ break;
+ case SPL_NETCONN_EVT_RCVMINUS: // This will never be reached
+ __sync_fetch_and_sub (&conn->rcvevent, 1);
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLIN);
+ }
+ break;
+ case SPL_NETCONN_EVT_SENDPLUS:
+ conn->sendevent = 1;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLOUT);
+ }
+ break;
+ case SPL_NETCONN_EVT_SENDMINUS:
+ conn->sendevent = 0;
+
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLOUT);
+ }
+ break;
+ case SPL_NETCONN_EVT_ERROR:
+ conn->errevent |= EPOLLERR;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), conn->errevent);
+ conn->errevent = 0;
+ }
+ break;
+#if 1
+ case SPL_NETCONN_EVT_ACCEPT:
+ __sync_fetch_and_add (&conn->rcvevent, 1);
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), EPOLLIN);
+ }
+ break;
+
+ case SPL_NETCONN_EVT_HUP:
+ conn->errevent |= EPOLLHUP;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), conn->errevent);
+ conn->errevent = 0;
+ }
+ break;
+ case SPL_NETCONN_EVT_RDHUP:
+ conn->errevent |= EPOLLRDHUP;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ nstack_event_callback (ADDR_SHTOL (conn->epInfo), conn->errevent);
+ conn->errevent = 0;
+ }
+ break;
+#endif
+
+ default:
+ NSTCP_LOGERR ("unknown event]conn=%p,event=%d", conn, evt);
+ return;
+ }
+ return;
+}
+
+u8
+get_shut_op (data_com_msg * m)
+{
+ if (m && m->param.module_type == MSG_MODULE_SBR
+ && m->param.major_type == SPL_TCPIP_NEW_MSG_API)
+ {
+ if (m->param.minor_type == SPL_API_DO_CLOSE)
+ return ((msg_close *) (m->buffer))->shut;
+
+ if (m->param.minor_type == SPL_API_DO_DELCON)
+ return ((msg_delete_netconn *) (m->buffer))->shut;
+ }
+
+ return SPL_NETCONN_SHUT_RDWR;
+}
+
+/*
+ Never using head/tail to judge whether need to do enque/deque, just do enque&deque, the return val will tell you ring is full/empty or not
+ rtp_perf_ring never provid ring_full/ring_empty function;
+ one more thing the rtp_ring_enque/deque result must be checked.
+*/
+err_t
+accept_enqueue (spl_netconn_t * conn, void *p)
+{
+ if (conn == NULL)
+ {
+ NSPOL_LOGERR ("accept_enqueue: invalid input]conn=%p", conn);
+ return ERR_VAL;
+ }
+
+ NSPOL_LOGDBG (NEW_RING_DEBUG, "accept_enqueue]conn=%p,p=%p", conn, p);
+ mring_handle ring = conn->recv_ring;
+ if (NULL == ring)
+ {
+ NSPOL_LOGERR ("conn=%p accept new conn=%p enqueue ring addr is null",
+ conn, p);
+ return ERR_VAL;
+ }
+
+ err_t retVal = ERR_MEM;
+ int enQSucCnt = 0;
+ int nTryCnt = 0;
+ do
+ {
+ enQSucCnt = nsfw_mem_ring_enqueue (ring, (void *) p);
+ if (1 == enQSucCnt)
+ {
+ retVal = ERR_OK;
+ break;
+ }
+ else if (0 == enQSucCnt)
+ {
+ sys_sleep_ns (0, 3000);
+ nTryCnt++;
+ }
+ else
+ {
+ retVal = ERR_VAL;
+ break;
+ }
+ }
+ while (nTryCnt < MAX_TRY_GET_MEMORY_TIMES);
+
+ return retVal;
+}
+
+err_t
+accept_dequeue (spl_netconn_t * lconn, void **new_buf,
+ u32_t timeout /*miliseconds */ )
+{
+ struct timespec starttm;
+ struct timespec endtm;
+ long timediff;
+ long timediff_sec;
+ u32_t timeout_sec = timeout / 1000;
+
+#define FAST_SLEEP_TIME 10000
+#define SLOW_SLEEP_TIME 500000
+#define FAST_RETRY_COUNT 100
+ unsigned int retry_count = 0;
+
+ if (NULL == lconn || NULL == new_buf)
+ {
+ NSPOL_LOGERR ("accept_dequeue invalid input]conn=%p,newbuf=%p", lconn,
+ new_buf);
+ return ERR_ARG;
+ }
+
+ if (timeout != 0)
+ {
+ /* Handle system time change side-effects */
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &starttm)))
+ {
+ //NSPOL_LOGERR("Failed to get time]errno=%d", errno);
+ }
+ }
+
+ mring_handle ring = lconn->recv_ring;
+ if (ring == NULL)
+ {
+ NSPOL_LOGERR ("Get rtp_perf_ring failed]conn=%p", lconn);
+ return ERR_ARG;
+ }
+
+ int nDequeRt;
+ int retVal;
+ while (1)
+ {
+ if ((lconn->shut_status) && (-1 != (int) timeout))
+ {
+ retVal = ERR_VAL;
+ break;
+ }
+
+ nDequeRt = nsfw_mem_ring_dequeue (ring, new_buf);
+ if (nDequeRt == 1)
+ {
+ retVal = ERR_OK;
+ break;
+ }
+ else if (nDequeRt == 0)
+ {
+ if ((int) timeout == -1)
+ {
+ retVal = ERR_WOULDBLOCK;
+ break;
+ }
+
+ if (timeout != 0)
+ {
+ /* Handle system time change side-effects */
+ if (unlikely (0 != clock_gettime (CLOCK_MONOTONIC, &endtm)))
+ {
+ //NSPOL_LOGERR("Failed to get time, errno = %d", errno);
+ }
+ timediff_sec = endtm.tv_sec - starttm.tv_sec;
+ if (timediff_sec >= timeout_sec)
+ {
+ timediff = endtm.tv_nsec > starttm.tv_nsec ?
+ (timediff_sec * 1000) + (endtm.tv_nsec -
+ starttm.tv_nsec) /
+ USEC_TO_SEC : (timediff_sec * 1000) -
+ ((starttm.tv_nsec - endtm.tv_nsec) / USEC_TO_SEC);
+
+ /*NOTE: if user configured the timeout as say 0.5 ms, then timediff value
+ will be negetive if still 0.5 ms is not elapsed. this is intended and we should
+ not typecast to any unsigned type during this below if check */
+ if (timediff > (long) timeout)
+ {
+ retVal = ERR_TIMEOUT;
+ break;
+ }
+ }
+ }
+
+ /* reduce CPU usage in blocking mode */
+ if (retry_count < FAST_RETRY_COUNT)
+ {
+ sys_sleep_ns (0, FAST_SLEEP_TIME);
+ retry_count++;
+ }
+ else
+ {
+ sys_sleep_ns (0, SLOW_SLEEP_TIME);
+ }
+
+ continue;
+ }
+ else
+ {
+ retVal = ERR_VAL;
+ break;
+ }
+ }
+
+ return retVal;
+}
+
+err_t
+sp_enqueue (struct common_pcb * cpcb, void *p)
+{
+ mring_handle ring = NULL;
+ spl_netconn_t *conn = NULL;
+ int enQueRet = 0;
+
+ if (cpcb == NULL || (NULL == (conn = cpcb->conn)))
+ {
+ NSTCP_LOGERR ("conn NULL!");
+ return ERR_VAL;
+ }
+
+ NSPOL_LOGDBG (NEW_RING_DEBUG, "]conn=%p,buf=%p", cpcb->conn, p);
+ ring = conn->recv_ring;
+ if (NULL == ring)
+ {
+ NSPOL_LOGERR ("Get rtp_perf_ring failed]conn=%p.", conn);
+ return ERR_CLSD;
+ }
+
+ /* clear LOOP_SEND_FLAG to indicate that this pbuf has been given to upper layer */
+ struct spl_pbuf *tmpbuf = p;
+ while (tmpbuf)
+ {
+ tmpbuf->res_chk.u8Reserve &= ~LOOP_SEND_FLAG;
+ tmpbuf = tmpbuf->next;
+ }
+
+ enQueRet = nsfw_mem_ring_enqueue (ring, p);
+ if (1 != enQueRet)
+ {
+ NS_LOG_CTRL (LOG_CTRL_RECV_QUEUE_FULL, LOGTCP, "NSTCP", NSLOG_WAR,
+ "ringvbox_enqueue buf is full]conn=%p.", conn);
+
+ return ERR_MEM;
+ }
+
+ return ERR_OK;
+}
+
+/**
+ * Receive callback function for UDP netconns.
+ * Posts the packet to conn->recvmbox or deletes it on memory error.
+ *
+ * @see udp.h (struct udp_pcb.recv) for parameters
+ */
+
+static void
+spl_recv_udp (void *arg, struct udp_pcb *pcb, struct pbuf *p,
+ const ip_addr_t * ipaddr, u16_t port)
+{
+ struct spl_netbuf *buf;
+ spl_netconn_t *conn = (spl_netconn_t *) arg;
+ struct spl_pbuf *spb = NULL; //??
+
+ if (NULL == pcb)
+ {
+ NSPOL_LOGERR ("recv_udp must have a pcb argument");
+ pbuf_free (p);
+ return;
+ }
+
+ if (NULL == arg)
+ {
+ NSPOL_LOGERR ("recv_udp must have an argument");
+ pbuf_free (p);
+ return;
+ }
+ /* //@TODO: malloc and Copy splbuf */
+ struct common_pcb *cpcb = (struct common_pcb *) (conn->comm_pcb_data);
+
+ buf = (struct spl_netbuf *) ((char *) p + sizeof (struct spl_pbuf));
+ buf->p = spb;
+ spl_ip_addr_set (&buf->addr, ipaddr);
+ buf->port = port;
+
+ err_t ret = sp_enqueue (cpcb, (void *) p);
+ if (ret != ERR_OK)
+ {
+ NSPOL_LOGDBG (UDP_DEBUG, "mbox post failed");
+ spl_netbuf_delete (buf);
+ return;
+ }
+ else
+ {
+ /* Register event with callback */
+ NSPOL_LOGDBG (UDP_DEBUG | LWIP_DBG_TRACE,
+ "recv a udp packet: and api_event");
+ SPL_API_EVENT (cpcb->conn, SPL_NETCONN_EVT_RCVPLUS, 1);
+ }
+}
+
+/**
+ * Receive callback function for TCP netconns.
+ * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
+ *
+ * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
+ */
+
+err_t
+spl_recv_tcp (void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
+{
+ struct spl_pbuf *spl_pb = NULL;
+ u32_t len;
+
+ if (NULL == pcb)
+ {
+ NSTCP_LOGERR ("recv_tcp must have a pcb argument");
+ pbuf_free (p);
+ return ERR_ARG;
+ }
+
+ if (NULL == arg)
+ {
+ NSTCP_LOGERR ("must have an argument]pcb=%p", pcb);
+ pbuf_free (p);
+ return ERR_ARG;
+ }
+
+ spl_netconn_t *conn = (spl_netconn_t *) arg;
+
+ /* Unlike for UDP or RAW pcbs, don't check for available space
+ using recv_avail since that could break the connection
+ (data is already ACKed) */
+ /* don't overwrite fatal errors! */
+ (void) err;
+ if (p == NULL)
+ {
+ return ERR_OK;
+ }
+
+ len = p->tot_len;
+
+ u16_t proc_id = spl_get_lcore_id ();
+
+ spl_pb = spl_pbuf_alloc_hugepage (SPL_PBUF_TRANSPORT,
+ p->tot_len +
+ g_offSetArry[SPL_PBUF_TRANSPORT],
+ SPL_PBUF_HUGE, proc_id, conn);
+
+ if (!spl_pb)
+ {
+ NSPOL_LOGINF (TCP_DEBUG, "spl_pbuf_alloc_hugepage Failed!!!");
+ return ERR_MEM;
+ }
+
+ pbuf_to_splpbuf_copy (spl_pb, p);
+ pbuf_free (p);
+
+ if (sp_enqueue ((struct common_pcb *) conn->comm_pcb_data, (void *) spl_pb)
+ != ERR_OK)
+ {
+ NSPOL_LOGDBG (TCP_DEBUG, "sp_enqueue!=ERR_OK]conn=%p", conn);
+ spl_pbuf_free (spl_pb);
+ return ERR_MEM;
+ }
+
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_RCVPLUS, 1);
+ conn->recv_avail_prod += len;
+
+ return ERR_OK;
+}
+
+/**
+ * Poll callback function for TCP netconns.
+ * Wakes up an application thread that waits for a connection to close
+ * or data to be sent. The application thread then takes the
+ * appropriate action to go on.
+ *
+ * Signals the conn->sem.
+ * netconn_close waits for conn->sem if closing failed.
+ *
+ * @see tcp.h (struct tcp_pcb.poll) for parameters and return value
+ */
+err_t
+spl_poll_tcp (void *arg, struct tcp_pcb * pcb)
+{
+ spl_netconn_t *conn = (spl_netconn_t *) arg;
+ struct tcp_pcb *tpcb = NULL;
+
+ if (NULL == conn)
+ {
+ NSPOL_LOGERR ("conn==NULL");
+ return ERR_VAL;
+ }
+
+ if (conn->state == SPL_NETCONN_WRITE)
+ {
+ (void) do_writemore (conn);
+
+ /* do_close_internal, can release th PCB
+ and connection CB. so checking NETCONN_FLAG_CHECK_WRITESPACE should not be
+ done after do_close_internal. anyway this flag is used with data send.(do_writemore) */
+ /* Did a nonblocking write fail before? Then check available write-space. */
+ if (conn->flags & SPL_NETCONN_FLAG_CHECK_WRITESPACE)
+ {
+ tpcb = (struct tcp_pcb *) conn->private_data;
+ /* If the queued byte- or pbuf-count drops below the configured low-water limit,
+ let select mark this pcb as writable again. */
+ if ((tpcb != NULL) && (tcp_sndbuf (tpcb) > TCP_SNDLOWAT) &&
+ (tcp_sndqueuelen (tpcb) < TCP_SNDQUEUELOWAT))
+ {
+ conn->flags &= ~SPL_NETCONN_FLAG_CHECK_WRITESPACE;
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1);
+ }
+ }
+ }
+ else if (conn->state == SPL_NETCONN_CLOSE)
+ {
+ (void) do_close_internal ((struct common_pcb *) conn->comm_pcb_data, 0);
+ }
+
+ /* @todo: implement connect timeout here? */
+ return ERR_OK;
+}
+
+/**
+ * Default receive callback that is called if the user didn't register
+ * a recv callback for the pcb.
+ */
+err_t
+spl_tcp_recv_null (void *arg, struct tcp_pcb * pcb, struct pbuf * p,
+ err_t err)
+{
+ LWIP_UNUSED_ARG (arg);
+
+ if (p != NULL)
+ {
+ tcp_recved (pcb, p->tot_len);
+ pbuf_free (p);
+ }
+ else if (err == ERR_OK)
+ {
+ return tcp_close (pcb);
+ }
+
+ return ERR_OK;
+}
+
+/**
+ * Sent callback function for TCP netconns.
+ * Signals the conn->sem and calls API_EVENT.
+ * netconn_write waits for conn->sem if send buffer is low.
+ *
+ * @see tcp.h (struct tcp_pcb.sent) for parameters and return value
+ */
+err_t
+spl_sent_tcp (void *arg, struct tcp_pcb * pcb, u16_t len)
+{
+ spl_netconn_t *conn = (spl_netconn_t *) arg;
+
+ if (NULL == conn)
+ {
+ NSPOL_LOGERR ("conn==NULL");
+ return ERR_VAL;
+ }
+
+ if (conn->state == SPL_NETCONN_WRITE)
+ {
+ (void) do_writemore (conn);
+ }
+ else if (conn->state == SPL_NETCONN_CLOSE)
+ {
+ (void) do_close_internal ((struct common_pcb *) conn->comm_pcb_data, 0);
+ }
+
+ /* conn is already checked for NULL above with ASSERT */
+ /* If the queued byte- or pbuf-count drops below the configured low-water limit,
+ let select mark this pcb as writable again. */
+ if (conn->snd_buf > TCP_SNDLOWAT)
+ {
+ conn->flags &= ~SPL_NETCONN_FLAG_CHECK_WRITESPACE;
+ if (((struct common_pcb *) conn->comm_pcb_data)->model == SOCKET_STACKX)
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1);
+ }
+
+ return ERR_OK;
+}
+
+/**
+ * Error callback function for TCP netconns.
+ * Signals conn->sem, posts to all conn mboxes and calls API_EVENT.
+ * The application thread has then to decide what to do.
+ *
+ * @see tcp.h (struct tcp_pcb.err) for parameters
+ */
+void
+spl_err_tcp (void *arg, err_t err)
+{
+ spl_netconn_t *conn;
+ enum spl_netconn_state old_state;
+ data_com_msg *forFree = NULL;
+
+ struct common_pcb *cpcb;
+
+ NSTCP_LOGINF ("Enter err_tcp.");
+
+ conn = (spl_netconn_t *) arg;
+ cpcb = (struct common_pcb *) (conn->comm_pcb_data);
+
+ old_state = conn->state;
+ conn->state = SPL_NETCONN_NONE;
+
+ /* Call unlink pcb no matter what */
+ unlink_pcb (cpcb);
+ if (old_state == SPL_NETCONN_CLOSE)
+ {
+ /* RST during close: let close return success & dealloc the netconn */
+ err = ERR_OK;
+ SPL_NETCONN_SET_SAFE_ERR (conn, ERR_OK);
+ }
+ else
+ {
+ SPL_NETCONN_SET_SAFE_ERR (conn, err);
+ }
+
+ NSTCP_LOGWAR ("inform HUP and ERROR event.");
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_RCVPLUS, 0);
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 0);
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_ERROR, 0);
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_HUP, 1);
+
+ if ((old_state == SPL_NETCONN_WRITE) || (old_state == SPL_NETCONN_CLOSE)
+ || (old_state == SPL_NETCONN_CONNECT))
+ {
+ int was_nonblocking_connect = spl_netconn_is_nonblocking (conn);
+ SPL_SET_NONBLOCKING_CONNECT (conn, 0);
+
+ if (!was_nonblocking_connect)
+ {
+ /* set error return code */
+ if (NULL == cpcb->current_msg)
+ {
+ NSPOL_LOGERR ("conn->current_msg==NULL");
+ return;
+ }
+
+ /* current msg could be connect msg or write_buf_msg */
+ SET_MSG_ERR (cpcb->current_msg, err);
+ /* signal app to exit */
+ if (old_state == SPL_NETCONN_CONNECT
+ && !spl_netconn_is_nonblocking (conn))
+ {
+ SYNC_MSG_ACK (cpcb->current_msg);
+ }
+
+ /* no matter it's connect msg or write msg, we will no process it any more */
+ cpcb->current_msg = NULL;
+
+ /* but, if msg is write_buf_msg, then we should release the pbuf in msg */
+ if (cpcb->msg_head != NULL)
+ {
+ /* current_msg should be write_buf_msg */
+ msg_write_buf *tmp_msg = cpcb->msg_head;
+ while (tmp_msg != NULL)
+ {
+
+ forFree = MSG_ENTRY (tmp_msg, data_com_msg, buffer);
+ spl_pbuf_free (tmp_msg->p);
+ tmp_msg = tmp_msg->next;
+
+ // free msg
+ ASYNC_MSG_FREE (forFree);
+ }
+ cpcb->current_msg = NULL;
+ cpcb->msg_head = cpcb->msg_tail = NULL;
+ }
+ }
+ }
+ else
+ {
+
+ }
+}
+
+/**
+ * Setup a tcp_pcb with the correct callback function pointers
+ * and their arguments.
+ *
+ * @param conn the TCP netconn to setup
+ */
+NSTACK_STATIC void
+setup_tcp (struct tcp_pcb *pcb, spl_netconn_t * conn)
+{
+ struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data;
+
+ /* callback have the same value as cpcb->conn */
+ cpcb->conn = conn;
+ tcp_arg (pcb, (void *) conn);
+ tcp_recv (pcb, tcp_fn[TCP_FN_STACKX].recv_fn);
+ tcp_sent (pcb, tcp_fn[TCP_FN_STACKX].sent_fn);
+ tcp_poll (pcb, tcp_fn[TCP_FN_STACKX].poll_fn, 4);
+ tcp_err (pcb, tcp_fn[TCP_FN_STACKX].err_fn);
+
+}
+
+/**
+ * Accept callback function for TCP netconns.
+ * Allocates a new netconn and posts that to conn->acceptmbox.
+ *
+ * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
+ */
+err_t
+spl_accept_function (void *arg, struct tcp_pcb *newpcb, err_t err)
+{
+ spl_netconn_t *newconn;
+ spl_netconn_t *lconn = (spl_netconn_t *) arg; /* listen conneciton */
+ struct common_pcb *cpcb = NULL;
+
+ NSPOL_LOGDBG (API_MSG_DEBUG, "]state=%s",
+ tcp_debug_state_str (newpcb->state));
+
+ if (lconn == NULL)
+ {
+ NSPOL_LOGERR ("accept_function: conn is NULL");
+ return ERR_VAL;
+ }
+
+ /* We have to set the callback here even though
+ * the new socket is unknown. conn->socket is marked as -1. */
+ newconn = ss_malloc_conn (lconn->conn_pool, SPL_NETCONN_TCP);
+ if (newconn == NULL)
+ {
+ NSPOL_LOGERR ("conn alloc failed");
+ return ERR_MEM;
+ }
+
+ cpcb = alloc_common_pcb (SPL_NETCONN_TCP);
+ if (cpcb == NULL)
+ {
+ return ERR_MEM;
+ }
+
+ /* used by application to recycle conn */
+ newconn->recycle.accept_from = lconn;
+ newconn->conn_pool = lconn->conn_pool;
+
+ newconn->recv_obj = (i64) & newconn->private_data;
+ newconn->private_data = (i64) newpcb;
+ newconn->comm_pcb_data = (i64) cpcb;
+
+ NSFW_LOGINF ("alloc accept conn]conn=%p,pcb=%p,lconn=%p", newconn, newpcb,
+ lconn);
+ newconn->shut_status = 0xFFFF;
+ newconn->last_err = ERR_OK;
+ newconn->CanNotReceive = 0;
+ newconn->flags = 0;
+
+ newconn->state = SPL_NETCONN_NONE;
+ newconn->mss = newpcb->mss;
+ newconn->remote_ip.addr = newpcb->remote_ip.addr;
+ newconn->remote_port = newpcb->remote_port;
+ ss_set_local_ip (newconn, newpcb->local_ip.addr);
+ ss_set_local_port (newconn, newpcb->local_port);
+
+ setup_tcp (newpcb, newconn);
+ newpcb->state = ESTABLISHED;
+ update_tcp_state (newconn, ESTABLISHED);
+
+ /*Initialize flow control variables */
+ newconn->tcp_sndbuf = CONN_TCP_MEM_DEF_LINE;
+ newconn->tcp_wmem_alloc_cnt = 0;
+ newconn->tcp_wmem_sbr_free_cnt = 0;
+ newconn->tcp_wmem_spl_free_cnt = 0;
+ newconn->snd_buf = 0;
+
+ newconn->bind_thread_index = lconn->bind_thread_index;
+ ss_set_msg_box (newconn,
+ ss_get_instance_msg_box (newconn->bind_thread_index, 0));
+
+ /* no protection: when creating the pcb, the netconn is not yet known
+ to the application thread */
+ newconn->last_err = err;
+
+ NSPOL_LOGDBG (TCP_DEBUG,
+ "trypost]newconn=%p, tcp=%p state=%d conn state=%d ", newconn,
+ newpcb, newpcb->state, newconn->state);
+ if (accept_enqueue (lconn, (void *) newconn) != ERR_OK)
+ {
+ /* remove all references to this netconn from the pcb */
+ NSPOL_LOGERR ("sp_enqueue!=ERR_OK]ring = %p", newconn->recv_ring);
+
+ tcp_arg (newpcb, NULL);
+ tcp_recv (newpcb, tcp_fn[TCP_FN_NULL].recv_fn);
+ tcp_sent (newpcb, tcp_fn[TCP_FN_NULL].sent_fn);
+ tcp_poll (newpcb, tcp_fn[TCP_FN_NULL].poll_fn, 0);
+ tcp_err (newpcb, tcp_fn[TCP_FN_NULL].err_fn);
+ /* drop conn */
+ tcp_drop_conn (newconn);
+ return ERR_MEM;
+ }
+
+ SPL_API_EVENT (lconn, SPL_NETCONN_EVT_ACCEPT, 1);
+ /* tcp_accepted_with_return_value(newpcb); */
+
+ return ERR_OK;
+}
+
+int
+common_pcb_init (struct common_pcb *cpcb)
+{
+ // u32 threadnum = p_lwip_instance->rss_queue_id + 1;//0 for app
+
+ cpcb->hostpid = get_sys_pid ();
+
+ cpcb->socket = 0;
+ /* run and close repeatly nstackmain coredum */
+ cpcb->close_progress = 0;
+ cpcb->model = SOCKET_STACKX;
+ cpcb->current_msg = NULL;
+ cpcb->msg_head = cpcb->msg_tail = NULL;
+ cpcb->write_offset = 0;
+
+ cpcb->recv_timeout = cpcb->send_timeout = 0;
+
+ cpcb->sk_rcvlowat = 1;
+
+ cpcb->l4_tick = 0;
+ cpcb->dataSentFlag = 0;
+ cpcb->recv_ring_not_empty = 0;
+
+ return 0;
+}
+
+int
+common_pcb_reset (struct common_pcb *cpcb)
+{
+ cpcb->conn = NULL;
+ cpcb->hostpid = 0;
+
+ cpcb->socket = 0;
+ /* run and close repeatly nstackmain coredum */
+ cpcb->close_progress = 0;
+ cpcb->model = 0;
+ cpcb->current_msg = NULL;
+ cpcb->msg_head = cpcb->msg_tail = NULL;
+ cpcb->write_offset = 0;
+
+ cpcb->recv_timeout = cpcb->send_timeout = 0;
+
+ cpcb->sk_rcvlowat = 0;
+
+ cpcb->l4_tick = 0;
+ cpcb->dataSentFlag = 0;
+ cpcb->recv_ring_not_empty = 0;
+
+ return 0;
+}
+
+void
+unlink_pcb (struct common_pcb *cpcb)
+{
+ if (cpcb && cpcb->conn)
+ {
+ /* whatever the private data will be reset */
+ cpcb->conn->private_data = 0;
+ update_tcp_state (cpcb->conn, CLOSED);
+ }
+ else
+ {
+ NSPOL_LOGINF (API_MSG_DEBUG, "conn is detached already!");
+ }
+}
+
+void
+unlink_recv_ring (spl_netconn_t * conn)
+{
+ if (conn)
+ conn->recv_ring_valid = 0;
+}
+
+void
+recycle_tmr (void *arg)
+{
+ if (arg == NULL)
+ {
+ NSPOL_LOGERR ("recycle_message is NULL!");
+ }
+ else
+ {
+ (void) ss_recycle_conn (arg, do_try_delconn);
+ }
+}
+
+/**
+ * Create a new pcb of a specific type.
+ * Called from do_newconn().
+ *
+ * @param msg the api_msg_msg describing the connection type
+ * @return msg->conn->err, but the return value is currently ignored
+ */
+int
+spl_pcb_new (msg_new_netconn * pmsg)
+{
+ u16_t thread_index = spl_get_lcore_id ();
+ struct common_pcb *cpcb = NULL;
+ enum lwip_ip_addr_type iptype = IPADDR_TYPE_V4;
+
+ /* Allocate a PCB for this connection */
+ switch (SPL_NETCONNTYPE_GROUP (pmsg->type))
+ {
+ case SPL_NETCONN_UDP:
+ {
+ struct udp_pcb *u = udp_new_ip_type (iptype);
+ if (u == NULL)
+ {
+ return ERR_MEM;
+ }
+
+ if (pmsg->type == SPL_NETCONN_UDPNOCHKSUM)
+ {
+ udp_setflags (u, UDP_FLAGS_NOCHKSUM);
+ }
+
+ cpcb = (struct common_pcb *) alloc_common_pcb (SPL_NETCONN_UDP);
+ if (cpcb == NULL)
+ {
+ return ERR_MEM;
+ }
+
+ pmsg->conn->comm_pcb_data = (i64) cpcb;
+ pmsg->conn->private_data = (i64) u;
+ udp_recv (u, spl_recv_udp, (void *) pmsg->conn);
+ break;
+ }
+
+ case SPL_NETCONN_TCP:
+ {
+ struct tcp_pcb *t = tcp_new_ip_type (iptype);
+ if (t == NULL)
+ {
+ return ERR_MEM;
+ }
+
+ cpcb = alloc_common_pcb (SPL_NETCONN_TCP);
+ if (cpcb == NULL)
+ {
+ return ERR_MEM;
+ }
+
+ pmsg->conn->comm_pcb_data = (i64) cpcb;
+ pmsg->conn->private_data = (i64) t;
+ setup_tcp (t, pmsg->conn);
+ break;
+ }
+
+ default:
+ /* Unsupported netconn type, e.g. protocol disabled */
+ NSPOL_LOGERR ("Unsupported netconn type!");
+ return ERR_VAL;
+ }
+
+ /* type and socket value for all type */
+ cpcb->socket = pmsg->socket;
+ cpcb->conn = pmsg->conn;
+ cpcb->bind_thread_index = thread_index;
+
+ /* used to find pcb when a msg is received */
+ return ERR_OK;
+}
+
+/**
+ * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in
+ * these mboxes
+ *
+ * @param conn the netconn to free
+ * @bytes_drained bytes drained from recvmbox
+ * @accepts_drained pending connections drained from acceptmbox
+ */
+int
+netconn_drain (enum spl_netconn_type type, spl_netconn_t * conn)
+{
+ int i, n;
+ mring_handle ring = NULL;
+ void *addr[32] = { 0 };
+ int not_empty = 0;
+
+ /* This runs in tcpip_thread, so we don't need to lock against rx packets */
+ ring = conn->recv_ring;
+ do
+ {
+ /*every times get atmost 32 to release */
+ n = nsfw_mem_ring_dequeuev (ring, addr, 32);
+ for (i = 0; i < n; i++)
+ {
+ /* if the con is UDP, buffer type also is struct spl_netbuf,it is same as RAW */
+ if ((type == SPL_NETCONN_RAW) || (type == SPL_NETCONN_UDP))
+ {
+ spl_pbuf_free ((struct spl_pbuf *) addr[i]);
+ if (type == SPL_NETCONN_UDP)
+ {
+ UDP_STATS_INC (udp.drop);
+ }
+ }
+ else
+ {
+ spl_pbuf_free ((struct spl_pbuf *) addr[i]);
+ }
+
+ if (not_empty == 0)
+ not_empty = 1;
+ }
+ }
+ while (0 != n);
+ return not_empty;
+}
+
+/* need free mbuf inside recv ring before free conn */
+void
+free_conn_by_spl (spl_netconn_t * conn)
+{
+ struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data;
+
+ free_common_pcb (cpcb);
+
+ (void) netconn_drain (conn->type, conn);
+ ss_free_conn (conn);
+}
+
+int
+do_close_finished (struct common_pcb *cpcb, u8_t close_finished, u8_t shut,
+ err_t err, int OpShutDown)
+{
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data;
+ spl_netconn_t *conn = cpcb->conn;
+
+ if (!close_finished)
+ {
+ /* Closing succeeded */
+ /* Closing failed, restore some of the callbacks */
+ /* Closing of listen pcb will never fail! */
+ if (LISTEN == tpcb->state)
+ {
+ NSPOL_LOGERR ("Closing a listen pcb may not fail!");
+ return ERR_VAL;
+ }
+
+ tcp_sent (tpcb, tcp_fn[TCP_FN_STACKX].sent_fn);
+ tcp_poll (tpcb, tcp_fn[TCP_FN_STACKX].poll_fn, 1);
+ tcp_err (tpcb, tcp_fn[TCP_FN_STACKX].err_fn);
+ tcp_arg (tpcb, conn);
+ /* don't restore recv callback: we don't want to receive any more data */
+ }
+ else
+ {
+ /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */
+ if (cpcb->current_msg)
+ {
+ SET_MSG_ERR (cpcb->current_msg, err);
+ cpcb->current_msg = NULL;
+ }
+
+ conn->state = SPL_NETCONN_NONE;
+ NSTCP_LOGINF ("release pcb]conn=%p,pcb=%p", conn, tpcb);
+ unlink_pcb (cpcb);
+ }
+
+ return ERR_OK;
+}
+
+NSTACK_STATIC void
+reset_tcp_callback (struct tcp_pcb *tpcb, struct common_pcb *cpcb, u8 shut)
+{
+ spl_netconn_t *conn = cpcb->conn;
+
+ /* some callbacks have to be reset if tcp_close is not successful */
+ if (shut & SPL_NETCONN_SHUT_RD)
+ {
+ conn->CanNotReceive = 1;
+ tcp_recv (tpcb, tcp_fn[TCP_FN_NULL].recv_fn);
+ tcp_accept (tpcb, tcp_fn[TCP_FN_NULL].accept_fn);
+ }
+
+ if (shut & SPL_NETCONN_SHUT_WR)
+ {
+ tcp_sent (tpcb, tcp_fn[TCP_FN_NULL].sent_fn);
+ }
+
+ if (shut == SPL_NETCONN_SHUT_RDWR)
+ {
+ tcp_poll (tpcb, tcp_fn[TCP_FN_NULL].poll_fn, 0);
+ tcp_err (tpcb, tcp_fn[TCP_FN_NULL].err_fn);
+ }
+}
+
+/**
+ * Internal helper function to close a TCP netconn: since this sometimes
+ * doesn't work at the first attempt, this function is called from multiple
+ * places.
+ *
+ * @param conn the TCP netconn to close
+ */
+err_t
+do_close_internal (struct common_pcb *cpcb, int OpShutDown)
+{
+ err_t err;
+ u8_t shut, ucclose;
+ u8_t close_finished = 0;
+
+ if (NULL == cpcb)
+ {
+ NSTCP_LOGERR ("invalid conn");
+ return ERR_ARG;
+ }
+
+ spl_netconn_t *conn = cpcb->conn;
+ if (SPL_NETCONN_TCP != cpcb->type || SPL_NETCONN_CLOSE != conn->state)
+ {
+ NSTCP_LOGERR ("conn=%p, err_type=%d, error_state=%d",
+ conn, cpcb->type, conn->state);
+ return ERR_VAL;
+ }
+
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) (conn->private_data);
+
+ if (cpcb->current_msg != NULL)
+ shut = get_shut_op (cpcb->current_msg);
+ else
+ shut = SPL_NETCONN_SHUT_RDWR;
+
+ /* shutting down both ends is the same as closing */
+ ucclose = (shut == SPL_NETCONN_SHUT_RDWR);
+
+ /* Set back some callback pointers */
+ if (ucclose)
+ {
+ conn->CanNotReceive = 1;
+ tcp_arg (tpcb, conn);
+ }
+
+ if (tpcb->state == LISTEN)
+ {
+ tcp_accept (tpcb, tcp_fn[TCP_FN_NULL].accept_fn);
+ }
+ else
+ {
+ reset_tcp_callback (tpcb, cpcb, shut);
+ }
+
+ /* Try to close the connection */
+ if (shut == SPL_NETCONN_SHUT_RDWR && !OpShutDown)
+ {
+ err = tcp_close (tpcb);
+ }
+ else
+ {
+ err =
+ tcp_shutdown (tpcb, shut & SPL_NETCONN_SHUT_RD,
+ shut & SPL_NETCONN_SHUT_WR);
+ }
+
+ if (err == ERR_OK)
+ {
+ close_finished = 1;
+ }
+ else
+ {
+ if (err == ERR_MEM)
+ {
+ /* Blocking close, check the timeout */
+ close_finished = 1;
+ if (ucclose)
+ {
+ /* in this case, we want to RST the connection */
+ tcp_abort (tpcb);
+ err = ERR_OK;
+ }
+ }
+ else
+ {
+ /* Closing failed for a non-memory error: give up */
+ close_finished = 1;
+ }
+ }
+
+ err_t err1 = do_close_finished (cpcb, close_finished,
+ shut, err, OpShutDown);
+ if (err1 != ERR_OK)
+ {
+ NSTCP_LOGERR ("return err1]pcb=%p,err1=%d", tpcb, err1);
+ return err1;
+ }
+ return err;
+
+ /* If closing didn't succeed, we get called again either
+ from poll_tcp or from sent_tcp */
+}
+
+void
+do_try_delconn (void *close_data, u32 delay_sec)
+{
+ msg_delete_netconn *dmsg = (msg_delete_netconn *) close_data;
+ data_com_msg *m = MSG_ENTRY (dmsg, data_com_msg, buffer);
+ struct common_pcb *cpcb = NULL;
+
+ spl_netconn_t *conn = dmsg->conn;
+
+ /* no receiver in some recycle cases */
+ if (0 == m->param.comm_receiver)
+ {
+ if (NULL == conn)
+ {
+ NSFW_LOGERR ("release err conn!]pid=%d", dmsg->pid);
+ /* need to free pbufs which are attached to msg */
+ do_pbuf_free (dmsg->buf);
+ return;
+ }
+
+ cpcb = (struct common_pcb *) conn->comm_pcb_data;
+ }
+ else
+ {
+ cpcb = COMM_PRIVATE_PTR (m);
+ }
+
+ /* no pcb in some recycle cases */
+ if (conn->private_data == 0)
+ {
+ /* though pcb is gone, still need to clean the mbox */
+ if (conn != NULL)
+ (void) netconn_drain (conn->type, conn);
+
+ NSFW_LOGWAR ("release conn pcb null]pcb=%p", m->param.receiver);
+ /* need to free pbufs which are attached to msg */
+ do_pbuf_free (dmsg->buf);
+ return;
+ }
+
+ if (delay_sec)
+ {
+ NSFW_LOGWAR ("delay to recycle!]pcb=%p, msg=%d", cpcb, dmsg);
+ sys_timeout (delay_sec * 1000, recycle_tmr, dmsg);
+ return;
+ }
+
+ do_delconn (cpcb, dmsg);
+
+ /* after the do_delconn, the PCB maybe released, but the conn is ok */
+ sys_sem_s_signal (&dmsg->conn->close_completed);
+
+ return;
+}
+
+/**
+ * Delete the pcb inside a netconn.
+ * Called from netconn_delete.
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+void
+do_delconn (struct common_pcb *cpcb, msg_delete_netconn * dmsg)
+{
+ spl_netconn_t *conn = cpcb->conn;
+ data_com_msg *pmsg = MSG_ENTRY (dmsg, data_com_msg, buffer);
+
+ /*if already close, just return */
+ /* run and close repeatly nstackmain coredum */
+ if (1 == cpcb->close_progress)
+ {
+ SET_MSG_ERR (pmsg, ERR_OK);
+ return;
+ }
+ cpcb->close_progress = 1;
+
+ /* Pbuf free should be done in network stack */
+ do_pbuf_free (dmsg->buf);
+
+ /* @todo TCP: abort running write/connect? */
+ if ((conn->state != SPL_NETCONN_NONE)
+ && (conn->state != SPL_NETCONN_LISTEN)
+ && (conn->state != SPL_NETCONN_CONNECT))
+ {
+ /* this only happens for TCP netconns */
+ if (SPL_NETCONN_TCP != cpcb->type)
+ {
+ NSTCP_LOGERR ("msg->conn->type error!]conn=%p,msg->conn->type=%d",
+ conn, cpcb->type);
+ SET_MSG_ERR (pmsg, ERR_VAL);
+ return;
+ }
+ NSPOL_LOGINF (SOCK_INFO, "conn is not for free state]conn=%p,state=%d",
+ conn, conn->state);
+
+ //need to release pcb
+ if (cpcb->current_msg != NULL && cpcb->msg_tail != NULL)
+ {
+ NSPOL_LOGINF (SOCK_INFO,
+ "conn there is data in conn->current_msg when close the conn]conn=%p,state=%d",
+ conn, conn->state);
+ (void) do_writemore (cpcb->conn);
+ }
+ }
+
+ /*
+ the accpet connections waiting in listen queue will be clear in
+ netconn_drain.
+ */
+ if (conn->state == SPL_NETCONN_LISTEN)
+ {
+ /* This function does nothing in original code. */
+ }
+ else
+ {
+ /* Drain pbuf from non-listen mboxes */
+ if (netconn_drain (cpcb->type, conn))
+ {
+ cpcb->recv_ring_not_empty = 1;
+
+ NSPOL_LOGWAR (SOCK_INFO,
+ "still some data leave in recv ring when close");
+ }
+ }
+
+ /* conn will be released outside */
+
+ switch (SPL_NETCONNTYPE_GROUP (cpcb->type))
+ {
+
+ case SPL_NETCONN_UDP:
+ {
+ struct udp_pcb *upcb = (struct udp_pcb *) cpcb->conn->private_data;
+ upcb->recv_arg = NULL;
+ udp_remove (upcb);
+ break;
+ }
+
+ case SPL_NETCONN_TCP:
+ {
+ conn->state = SPL_NETCONN_CLOSE;
+ dmsg->shut = SPL_NETCONN_SHUT_RDWR;
+ cpcb->current_msg = pmsg;
+
+ if (ERR_INPROGRESS == do_close_internal (cpcb, 0))
+ {
+ return;
+ }
+ }
+ default:
+ break;
+ }
+
+ /* tcp netconns don't come here! */
+
+}
+
+/**
+ * Bind a pcb contained in a netconn
+ * Called from netconn_bind.
+ *
+ * @param msg the api_msg_msg pointing to the connection and containing
+ * the IPaddress and port to bind to
+ */
+void
+do_bind (struct common_pcb *cpcb, msg_bind * bmsg)
+{
+ spl_netconn_t *conn = cpcb->conn;
+ data_com_msg *pmsg = MSG_ENTRY (bmsg, data_com_msg, buffer);
+ ip_addr_t stIpaddr;
+
+ stIpaddr.addr = bmsg->ipaddr.addr;
+
+ if (SPL_ERR_IS_FATAL (conn->last_err)
+ && ERR_CANTASSIGNADDR != conn->last_err)
+ {
+ NSTCP_LOGERR ("bind but conn has err]pcb=%p,conn=%p,err=%d", cpcb, conn,
+ conn->last_err);
+ SET_MSG_ERR (pmsg, conn->last_err);
+ }
+ else
+ {
+ if (!ip_addr_isany (&bmsg->ipaddr)
+ && !ip_addr_ismulticast (&bmsg->ipaddr))
+ {
+ if (!get_netif_by_ip (bmsg->ipaddr.addr)
+ && !netif_check_broadcast_addr (&bmsg->ipaddr))
+ {
+ NSPOL_LOGERR ("ip is not exist]pcb=%p,ip=%u", cpcb,
+ bmsg->ipaddr.addr);
+ SET_MSG_ERR (pmsg, ERR_CANTASSIGNADDR);
+ return;
+ }
+ }
+
+ SET_MSG_ERR (pmsg, ERR_VAL);
+ switch (SPL_NETCONNTYPE_GROUP (cpcb->type))
+ {
+ case SPL_NETCONN_UDP:
+ SET_MSG_ERR (pmsg,
+ udp_bind ((struct udp_pcb *) (cpcb->
+ conn->private_data),
+ &stIpaddr, bmsg->port));
+
+ /* Set local Ip, willbe used during connect */
+ struct udp_pcb *upcb = (struct udp_pcb *) cpcb->conn->private_data;
+ ss_set_local_ip (cpcb->conn, upcb->local_ip.addr);
+ ss_set_local_port (cpcb->conn, upcb->local_port);
+ NSTCP_LOGINF ("updated Ip to spl_netconn_t] %x",
+ upcb->local_ip.addr);
+
+ NSUDP_LOGINF
+ ("udp_bind return]pcb=%p,IP=%u.%u.%u.%u,port=%u,err=%d",
+ (struct udp_pcb *) cpcb->conn->private_data,
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr1_16 (&stIpaddr),
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr2_16 (&stIpaddr),
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr3_16 (&stIpaddr),
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr4_16 (&stIpaddr), bmsg->port,
+ GET_MSG_ERR (pmsg));
+ break;
+
+ case SPL_NETCONN_TCP:
+ SET_MSG_ERR (pmsg,
+ tcp_bind ((struct tcp_pcb *) cpcb->conn->private_data,
+ &stIpaddr, bmsg->port));
+
+ /* Set local Ip, willbe used during connect */
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data;
+ NSTCP_LOGINF ("updated Ip to spl_netconn_t] %x",
+ tpcb->local_ip.addr);
+ ss_set_local_ip (cpcb->conn, tpcb->local_ip.addr);
+ ss_set_local_port (cpcb->conn, tpcb->local_port);
+
+ NSTCP_LOGINF
+ ("tcp_bind return]pcb=%p,IP=%u.%u.%u.%u,port=%u,err=%d",
+ (struct tcp_pcb *) cpcb->conn->private_data,
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr1_16 (&stIpaddr),
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr2_16 (&stIpaddr),
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr3_16 (&stIpaddr),
+ &bmsg->ipaddr == NULL ? 0 : ip4_addr4_16 (&stIpaddr), bmsg->port,
+ GET_MSG_ERR (pmsg));
+ break;
+ default:
+ break;
+ }
+ }
+
+ conn->last_err = GET_MSG_ERR (pmsg);
+ NSPOL_LOGDBG (TESTSOCKET_DEBUG | LWIP_DBG_TRACE, "the msg is doing bind");
+ NSTCP_LOGINF ("the msg is doing bind");
+}
+
+/**
+ * TCP callback function if a connection (opened by tcp_connect/do_connect) has
+ * been established (or reset by the remote host).
+ *
+ * @see tcp.h (struct tcp_pcb.connected) for parameters and return values
+ */
+err_t
+spl_do_connected (void *arg, struct tcp_pcb *pcb, err_t err)
+{
+ spl_netconn_t *conn = (spl_netconn_t *) arg;
+ struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data;
+ data_com_msg *m = cpcb->current_msg;
+ int was_blocking;
+
+ if (conn == NULL)
+ {
+ NSTCP_LOGERR ("conn is NULL!]arg=%p", arg);
+ return ERR_ARG;
+ }
+
+ if (SPL_NETCONN_CONNECT != conn->state)
+ {
+ NSTCP_LOGERR ("conn->state error!]conn=%p,state=%d", conn, conn->state);
+ return ERR_VAL;
+ }
+
+ if ((NULL == m) && (0 == spl_netconn_is_nonblocking (conn)))
+ {
+ NSTCP_LOGERR ("conn->current_msg!]conn=%p,current_msg=%p", conn, m);
+ return ERR_VAL;
+ }
+
+ if (m != NULL)
+ {
+ SET_MSG_ERR (m, err);
+ }
+
+ if ((cpcb->type == SPL_NETCONN_TCP) && (err == ERR_OK))
+ {
+ setup_tcp (pcb, conn);
+ }
+
+ ss_set_local_ip (conn, pcb->local_ip.addr);
+ ss_set_local_port (conn, pcb->local_port);
+ conn->remote_ip.addr = pcb->remote_ip.addr;
+ conn->remote_port = pcb->remote_port;
+
+ conn->mss = pcb->mss;
+ cpcb->current_msg = NULL;
+
+ was_blocking = !SPL_IN_NONBLOCKING_CONNECT (conn);
+ SPL_SET_NONBLOCKING_CONNECT (conn, 0);
+ conn->state = SPL_NETCONN_NONE;
+ SPL_NETCONN_SET_SAFE_ERR (conn, ERR_OK);
+
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1);
+
+ if (was_blocking && m != NULL)
+ {
+ SYNC_MSG_ACK (m);
+ }
+
+ return ERR_OK;
+}
+
+int
+do_internal_tcp_connect (struct common_pcb *cpcb, struct tcp_pcb *tpcb,
+ msg_connect * cmsg)
+{
+ spl_netconn_t *conn = cpcb->conn;
+ data_com_msg *pmsg = MSG_ENTRY (cmsg, data_com_msg, buffer);
+ ip_addr_t ip_addr;
+
+ ip_addr.addr = cmsg->ipaddr.addr;
+
+ /* Prevent connect while doing any other action. */
+ if (conn->state != SPL_NETCONN_NONE)
+ {
+ if (conn->state == SPL_NETCONN_CONNECT
+ || conn->state == SPL_NETCONN_WRITE)
+ {
+ if (tpcb->state != ESTABLISHED)
+ {
+ SET_MSG_ERR (pmsg, ERR_ALREADY);
+ }
+ else
+ {
+ SET_MSG_ERR (pmsg, ERR_ISCONN);
+ }
+ }
+ else
+ {
+ SET_MSG_ERR (pmsg, ERR_ISCONN);
+ }
+
+ NSTCP_LOGINF
+ ("tcp_connect]pcb=%p,state=%d,remote_ip=%u.%u.%u.%u,remote_port=%u,local_ip=%u.%u.%u.%u,local_port=%u,err=%d",
+ tpcb, conn->state, ip4_addr1_16 (&ip_addr), ip4_addr2_16 (&ip_addr),
+ ip4_addr3_16 (&ip_addr), ip4_addr4_16 (&ip_addr), cmsg->port,
+ ip4_addr1_16 (&tpcb->local_ip), ip4_addr2_16 (&tpcb->local_ip),
+ ip4_addr3_16 (&tpcb->local_ip), ip4_addr4_16 (&tpcb->local_ip),
+ tpcb->local_port, GET_MSG_ERR (pmsg));
+ }
+ else
+ {
+ setup_tcp (tpcb, conn);
+ SET_MSG_ERR (pmsg,
+ tcp_connect (tpcb, &ip_addr, cmsg->port,
+ tcp_fn[TCP_FN_STACKX].connected_fn));
+ conn->mss = tpcb->mss;
+ SPL_API_EVENT (conn, NETCONN_EVT_SENDMINUS, 1);
+ SPL_API_EVENT (conn, NETCONN_EVT_RCVMINUS, 1);
+
+ NSTCP_LOGINF
+ ("tcp_connect]pcb=%p,state=%d,remote_ip=%u.%u.%u.%u,remote_port=%u,local_ip=%u.%u.%u.%u,local_port=%u,err=%d",
+ tpcb, conn->state, ip4_addr1_16 (&ip_addr), ip4_addr2_16 (&ip_addr),
+ ip4_addr3_16 (&ip_addr), ip4_addr4_16 (&ip_addr), cmsg->port,
+ ip4_addr1_16 (&tpcb->local_ip), ip4_addr2_16 (&tpcb->local_ip),
+ ip4_addr3_16 (&tpcb->local_ip), ip4_addr4_16 (&tpcb->local_ip),
+ tpcb->local_port, GET_MSG_ERR (pmsg));
+ if (GET_MSG_ERR (pmsg) == ERR_OK)
+ {
+ int nonblock = spl_netconn_is_nonblocking (conn);
+ SPL_SET_NONBLOCKING_CONNECT (conn, nonblock);
+ conn->state = SPL_NETCONN_CONNECT;
+ if (nonblock)
+ {
+ SET_MSG_ERR (pmsg, ERR_INPROGRESS);
+ }
+ else
+ {
+ cpcb->current_msg = pmsg;
+ /* sys_sem_signal() is called from do_connected (or err_tcp()),
+ * when the connection is established! */
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Connect a pcb contained inside a netconn
+ * Called from netconn_connect.
+ *
+ * @param msg the api_msg_msg pointing to the connection and containing
+ * the IPaddress and port to connect to
+ */
+void
+do_connect (struct common_pcb *cpcb, msg_connect * cmsg)
+{
+ data_com_msg *pmsg = MSG_ENTRY (cmsg, data_com_msg, buffer);
+ ip_addr_t ipaddr;
+
+ SET_MSG_ERR (pmsg, ERR_OK);
+
+ if (cpcb == NULL)
+ {
+ /* This may happen when calling netconn_connect() a second time */
+ NSTCP_LOGERR ("conn connect but conn has err]msg=%p", pmsg);
+ SET_MSG_ERR (pmsg, ERR_CLSD);
+ return;
+ }
+
+ ipaddr.addr = cmsg->ipaddr.addr;
+ switch (SPL_NETCONNTYPE_GROUP (cpcb->type))
+ {
+ case SPL_NETCONN_UDP:
+ {
+ struct udp_pcb *upcb = (struct udp_pcb *) (cpcb->conn->private_data);
+ if (ip_addr_isany (&upcb->local_ip))
+ {
+ upcb->local_ip.addr = cmsg->local_ip.addr;
+ ss_set_local_ip (cpcb->conn, upcb->local_ip.addr);
+ }
+
+ SET_MSG_ERR (pmsg, udp_connect (upcb, &ipaddr, cmsg->port));
+ if (ERR_OK == pmsg->param.err)
+ {
+ cpcb->conn->remote_ip.addr = cmsg->ipaddr.addr;
+ cpcb->conn->remote_port = cmsg->port;
+ }
+ break;
+ }
+ case SPL_NETCONN_TCP:
+ {
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) (cpcb->conn->private_data);
+ if (ip_addr_isany (&tpcb->local_ip))
+ {
+ tpcb->local_ip.addr = cmsg->local_ip.addr;
+ ss_set_local_ip (cpcb->conn, tpcb->local_ip.addr);
+ }
+
+ if (0 != do_internal_tcp_connect (cpcb, tpcb, cmsg))
+ {
+ return;
+ }
+
+ }
+ break;
+ default:
+ NSPOL_LOGERR ("Invalid netconn type]type=%d", cpcb->type);
+ SET_MSG_ERR (pmsg, ERR_VAL);
+ break;
+ }
+
+ /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(),
+ so use TCPIP_APIMSG_ACK() here.
+ Do as lwip-2.0.0. set conn->last_error here. */
+ SPL_NETCONN_SET_SAFE_ERR (cpcb->conn, GET_MSG_ERR (pmsg));
+}
+
+/* Pbuf free should be done in network stack */
+void
+do_pbuf_free (struct spl_pbuf *buf)
+{
+ if (buf)
+ {
+ struct spl_pbuf *pCur = buf;
+ while (buf)
+ {
+ pCur = buf;
+ buf = buf->freeNext;
+ spl_pbuf_free (pCur);
+ }
+ }
+}
+
+/**
+ * Set a TCP pcb contained in a netconn into listen mode
+ * Called from netconn_listen.
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+void
+do_listen (struct common_pcb *cpcb, msg_listen * lmsg)
+{
+ err_t err = ERR_OK;
+ spl_netconn_t *conn = cpcb->conn;
+ data_com_msg *pmsg = MSG_ENTRY (lmsg, data_com_msg, buffer);
+
+ if (SPL_ERR_IS_FATAL (conn->last_err))
+ {
+ NSTCP_LOGERR ("conn listern but conn has err]conn=%p,err=%d",
+ conn, conn->last_err);
+ SET_MSG_ERR (pmsg, conn->last_err);
+ }
+ else
+ {
+ SET_MSG_ERR (pmsg, ERR_CONN);
+
+ if (cpcb->type == SPL_NETCONN_TCP)
+ {
+ if (conn->state == SPL_NETCONN_NONE)
+ {
+ struct tcp_pcb *lpcb;
+ if (((struct tcp_pcb *) (cpcb->conn->private_data))->state !=
+ CLOSED)
+ {
+ /* connection is not closed, cannot listen */
+ SET_MSG_ERR (pmsg, ERR_VAL);;
+ }
+ else
+ {
+ u8_t backlog = TCP_DEFAULT_LISTEN_BACKLOG;
+
+ lpcb =
+ tcp_listen_with_backlog_and_err ((struct tcp_pcb
+ *) (cpcb->
+ conn->private_data),
+ backlog, &err);
+ if (lpcb == NULL)
+ {
+ /* in this case, the old pcb is still allocated */
+ SET_MSG_ERR (pmsg, err);
+ }
+ else
+ {
+ SET_MSG_ERR (pmsg, ERR_OK);
+ /* conn now is put on lpcb */
+ conn->state = SPL_NETCONN_LISTEN;
+
+ /* NOTE: pmsg->conn->comm_pcb_data == (i64)cpcb; should be already same. */
+ conn->private_data = (i64) lpcb;
+
+ tcp_arg (lpcb, conn);
+ tcp_accept (lpcb, tcp_fn[TCP_FN_STACKX].accept_fn);
+
+ SPL_API_EVENT (conn, NETCONN_EVT_SENDMINUS, 1);
+ SPL_API_EVENT (conn, NETCONN_EVT_RCVMINUS, 1);
+ }
+ }
+ }
+ else if (conn->state == SPL_NETCONN_LISTEN)
+ {
+ SET_MSG_ERR (pmsg, ERR_OK);
+ }
+ }
+ NSTCP_LOGINF ("listen]conn=%p,pcb=%p,connstate=%d,err=%d",
+ conn, cpcb, conn->state, GET_MSG_ERR (pmsg));
+
+ }
+
+}
+
+/**
+ * Send some data on a RAW or UDP pcb contained in a netconn
+ * Called from netconn_send
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+void
+do_send (struct common_pcb *cpcb, msg_send_buf * smsg)
+{
+ struct spl_pbuf *p = smsg->p;
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+ spl_netconn_t *conn = cpcb->conn;
+
+ pbuf_set_recycle_flg (p, MBUF_HLD_BY_SPL); /* release buf hold by app on abnormal exit */
+
+ if (SPL_ERR_IS_FATAL (conn->last_err))
+ {
+ SET_MSG_ERR (m, conn->last_err);
+ spl_pbuf_free (p);
+ return;
+ }
+
+ switch (SPL_NETCONNTYPE_GROUP (cpcb->type))
+ {
+ case SPL_NETCONN_UDP:
+ {
+ struct udp_pcb *upcb = (struct udp_pcb *) (cpcb->conn->private_data);
+ if (ip_addr_isany (&upcb->local_ip))
+ {
+ upcb->local_ip.addr = smsg->local_ip.addr;
+ ss_set_local_ip (conn, smsg->local_ip.addr);
+ }
+
+ //spl_ip_addr_t *destIP = &smsg->addr;
+
+ //@TODO udp send need to update like TCP. copy pbuf here. Once testing done for TCP we'll update it here.
+ if (ip_addr_isany (&smsg->addr))
+ {
+ //SET_MSG_ERR(m, udp_send(upcb, p));
+ /* destIP.addr == IPADDR_ANY means it is from stackx_send
+ and the destination is stored in remote_ip and remote port */
+ //destIP = &upcb->remote_ip;
+ }
+ else
+ {
+ //SET_MSG_ERR(m, udp_sendto(upcb, p, &smsg->addr, smsg->port));
+ }
+ break;
+ }
+
+ default:
+ SET_MSG_ERR (m, ERR_CONN);
+ break;
+ }
+
+ return;
+}
+
+/**
+ * Indicate data has been received from a TCP pcb contained in a netconn
+ * Called from netconn_recv
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+void
+do_recv (struct common_pcb *cpcb, msg_recv_buf * rmsg)
+{
+ data_com_msg *m = MSG_ENTRY (rmsg, data_com_msg, buffer);
+ SET_MSG_ERR (m, ERR_OK);
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data;
+
+ if (NULL == tpcb)
+ {
+ if (rmsg->p)
+ {
+ NSPOL_LOGDBG (TCP_DEBUG,
+ "When pcb was freed: do recv, and free pbuf");
+ spl_pbuf_free (rmsg->p);
+ rmsg->p = NULL;
+ }
+
+ return;
+ }
+
+ if (cpcb->conn->type == SPL_NETCONN_TCP)
+ {
+ /* Pbuf free should be done in network stack */
+ if (rmsg->p)
+ {
+ NSPOL_LOGDBG (TCP_DEBUG, "do recv, and free pbuf");
+ spl_pbuf_free (rmsg->p);
+ rmsg->p = NULL;
+ }
+ tcp_recved (tpcb, rmsg->len * TCP_MSS);
+ }
+}
+
+/**
+ * See if more data needs to be written from a previous call to netconn_write.
+ * Called initially from do_write. If the first call can't send all data
+ * (because of low memory or empty send-buffer), this function is called again
+ * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the
+ * blocking application thread (waiting in netconn_write) is released.
+ *
+ * @param conn netconn (that is currently in state NETCONN_WRITE) to process
+ * @return ERR_OK
+ * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished
+ */
+
+/**
+ * See if more data needs to be written from a previous call to netconn_write.
+ * Called initially from do_write. If the first call can't send all data
+ * (because of low memory or empty send-buffer), this function is called again
+ * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the
+ * blocking application thread (waiting in netconn_write) is released.
+ *
+ * @param conn netconn (that is currently in state NETCONN_WRITE) to process
+ * @return ERR_OK
+ * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished
+ */
+err_t
+do_writemore (struct spl_netconn *conn)
+{
+ err_t err = ERR_OK;
+ u16_t len = 0, available;
+ u8_t write_finished = 0;
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) conn->private_data;
+ common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data;
+ size_t diff;
+ const void *dataptr;
+
+ if ((NULL == tpcb) || (NULL == conn) || (SPL_NETCONN_WRITE != conn->state)
+ || (NULL == cpcb->current_msg))
+ {
+ NSPOL_LOGERR ("conn=NULL");
+ return ERR_ARG;
+ }
+
+ msg_write_buf *wmsg = (msg_write_buf *) cpcb->current_msg->buffer;
+start_write:
+
+ if (NULL == wmsg->p)
+ {
+ NSPOL_LOGERR ("wmsg->p is NULL]conn=%p,pcb=%p", conn, tpcb);
+ return ERR_VAL;
+ }
+
+ u8_t apiflags = wmsg->apiflags;
+ struct spl_pbuf *current_w_pbuf = wmsg->p;
+ current_w_pbuf->res_chk.u8Reserve |= NEED_ACK_FLAG;
+ wmsg->p = current_w_pbuf->next;
+ current_w_pbuf->next = NULL;
+
+ dataptr = (const u8_t *) current_w_pbuf->payload + cpcb->write_offset;
+ diff = current_w_pbuf->len - cpcb->write_offset;
+
+ if (diff > 0xffffUL)
+ {
+ len = 0xffff;
+ apiflags |= TCP_WRITE_FLAG_MORE;
+ }
+ else
+ {
+ len = (u16_t) diff;
+ }
+
+ available = tcp_sndbuf (tpcb);
+ if (!available)
+ {
+ err = ERR_MEM;
+ goto err_mem;
+ }
+
+ if (available < len)
+ {
+ /* don't try to write more than sendbuf */
+ len = available;
+ apiflags |= TCP_WRITE_FLAG_MORE;
+ }
+
+ err = tcp_write (tpcb, dataptr, len, apiflags);
+ if ((err == ERR_OK) || (err == ERR_MEM))
+ {
+ err_mem:
+ if ((tcp_sndbuf (tpcb) <= TCP_SNDLOWAT) ||
+ (tcp_sndqueuelen (tpcb) >= TCP_SNDQUEUELOWAT))
+ {
+ SPL_API_EVENT (conn, NETCONN_EVT_SENDMINUS, 1);
+ }
+ }
+ if (err == ERR_OK)
+ {
+ cpcb->write_offset += len;
+ tcp_output (tpcb);
+
+ if (cpcb->write_offset == current_w_pbuf->len)
+ {
+ cpcb->write_offset = 0;
+ spl_pbuf_free (current_w_pbuf);
+ if (NULL == wmsg->p)
+ {
+ /* this message is finished */
+ cpcb->write_offset = 0;
+ SET_MSG_ERR (cpcb->current_msg, err);
+
+ /* go to next msg */
+ data_com_msg *forFreemsg = cpcb->current_msg;
+ msg_write_buf *msg_head_prev = cpcb->msg_head;
+ cpcb->msg_head = cpcb->msg_head->next;
+
+ /* no msg remain */
+ if (cpcb->msg_head == NULL)
+ {
+ write_finished = 1;
+ if (cpcb->msg_tail != NULL
+ && msg_head_prev != cpcb->msg_tail)
+ {
+ NSPOL_LOGWAR (TCP_DEBUG,
+ "err maybe lost one mesg]conn=%p,pcb=%p",
+ conn, tpcb);
+ }
+ cpcb->msg_tail = NULL;
+ cpcb->current_msg = NULL;
+ conn->state = SPL_NETCONN_NONE;
+ }
+ else /* go to handle next message */
+ {
+
+ cpcb->current_msg =
+ MSG_ENTRY (cpcb->msg_head, data_com_msg, buffer);
+ wmsg = cpcb->msg_head;
+ write_finished = 0;
+ }
+
+ ASYNC_MSG_FREE (forFreemsg);
+ }
+
+ }
+ else
+ {
+ if (cpcb->write_offset > current_w_pbuf->len)
+ {
+ NSPOL_LOGERR ("Big trouble write_offset > current_w_pbuf->len");
+ }
+
+ current_w_pbuf->next = wmsg->p;
+ wmsg->p = current_w_pbuf;
+ }
+ if ((write_finished == 0) && (NULL != wmsg->p))
+ {
+ goto start_write;
+ }
+ }
+ else if (err == ERR_MEM)
+ {
+ current_w_pbuf->next = wmsg->p;
+ wmsg->p = current_w_pbuf;
+ tcp_output (tpcb);
+ }
+ else
+ {
+ NSPOL_LOGERR ("]pcb=%p, error when send %d", tpcb, err);
+ write_finished = 1;
+ cpcb->write_offset = 0;
+ current_w_pbuf->next = wmsg->p;
+ wmsg->p = current_w_pbuf;
+ tcp_abort (tpcb);
+ return err;
+ }
+ NSTCP_LOGINF ("do_writemore finished with err %d", err);
+ return ERR_OK;
+}
+
+/**
+ * Send some data on a TCP pcb contained in a netconn
+ * Called from netconn_write
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+void
+do_write (struct common_pcb *cpcb, msg_write_buf * wmsg)
+{
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data;
+ spl_netconn_t *conn = cpcb->conn;
+ data_com_msg *m = MSG_ENTRY (wmsg, data_com_msg, buffer);
+
+ pbuf_set_recycle_flg (wmsg->p, MBUF_HLD_BY_SPL); /* release buf hold by app on abnormal exit */
+
+ int tcpState = -1;
+
+ /* if msg->conn is null, then return */
+ if (NULL == conn)
+ {
+ NSPOL_LOGERR ("Invalid param]msg->conn=%p", conn);
+ SET_MSG_ERR (m, ERR_VAL);
+ goto err_return;
+ }
+
+ tcpState = tpcb->state;
+
+ if ((SPL_ERR_IS_FATAL (conn->last_err))
+ && !((ERR_CLSD == conn->last_err) && (CLOSE_WAIT == tcpState)))
+ {
+ SET_MSG_ERR (m, conn->last_err);
+ }
+ else
+ {
+ if (cpcb->type == SPL_NETCONN_TCP)
+ {
+ if (cpcb->current_msg != NULL)
+ {
+ if (NULL == cpcb->msg_head || NULL == cpcb->msg_tail)
+ {
+ /* if possible only if connect is not finished and it's
+ blocking, then the current_msg is connect msg.
+ */
+ NSPOL_LOGERR ("netconn do_write msg is null]msg_type=%d",
+ cpcb->current_msg->param.minor_type);
+ goto err_return;
+ }
+
+ /* only msg_write_buf will be in msg_head-msg_tail queue */
+ wmsg->next = NULL;
+ cpcb->msg_tail->next = wmsg;
+ cpcb->msg_tail = wmsg;
+ (void) do_writemore (conn);
+ NSTCP_LOGINF ("do_write finished....");
+ return;
+ }
+
+ if (conn->state != SPL_NETCONN_NONE)
+ {
+ /* netconn is connecting, closing or in blocking write */
+ NSPOL_LOGINF (TCP_DEBUG,
+ "msg->conn->state != SPL_NETCONN_NONE..netconn is connecting, "
+ "closing or in blocking write]conn=%p", conn);
+ SET_MSG_ERR (m, ERR_INPROGRESS);
+ }
+ /* this means we should start to process this message */
+ else if (tpcb != NULL)
+ {
+ conn->state = SPL_NETCONN_WRITE;
+
+ /* set all the variables used by do_writemore */
+ if (0 != cpcb->write_offset)
+ {
+ NSPOL_LOGERR ("already writing or closing]conn=%p", conn);
+ goto err_return;
+ }
+
+ if (0 == wmsg->len)
+ {
+ NSPOL_LOGERR ("msg->msg.w.len=0]conn=%p", conn);
+ goto err_return;
+ }
+
+ /* record the msg will be processed */
+ cpcb->current_msg = m;
+ if (cpcb->msg_head != NULL || cpcb->msg_tail != NULL)
+ {
+ NSPOL_LOGERR ("error maybe lost mesg]conn=%p", conn);
+ }
+ cpcb->msg_head = cpcb->msg_tail = wmsg;
+ wmsg->next = NULL;
+ cpcb->write_offset = 0;
+
+ (void) do_writemore (conn);
+
+ if ((conn->snd_buf) > TCP_SNDLOWAT)
+ {
+ if (cpcb->model == SOCKET_STACKX)
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_SENDPLUS, 1);
+ }
+ NSTCP_LOGINF ("do_write finished %d", conn->snd_buf);
+
+ /* for both cases: if do_writemore was called, don't ACK the APIMSG
+ since do_writemore ACKs it! */
+ return;
+ }
+ else
+ {
+ SET_MSG_ERR (m, ERR_CONN);
+ }
+ }
+ else
+ {
+ SET_MSG_ERR (m, ERR_VAL);
+ }
+ }
+ NSTCP_LOGINF ("do_write finished");
+
+err_return:
+ pbuf_free_safe (wmsg->p);
+ ASYNC_MSG_FREE (m);
+
+ return;
+}
+
+void
+do_getsockname (struct common_pcb *cpcb, msg_getaddrname * amsg)
+{
+ spl_netconn_t *conn;
+ struct tcp_pcb *tcp;
+ struct udp_pcb *udp;
+ struct sockaddr_in *paddr = (struct sockaddr_in *) &amsg->sock_addr;
+
+ data_com_msg *m = MSG_ENTRY (amsg, data_com_msg, buffer);
+
+ if ((NULL == cpcb) || !(conn = cpcb->conn))
+ {
+ NSTCP_LOGERR ("failed to get sock");
+ paddr->sin_family = 0;
+ paddr->sin_port = 0;
+ paddr->sin_addr.s_addr = 0;
+ SET_MSG_ERR (m, ERR_CONN);
+ return;
+ }
+
+ NS_LOG_CTRL (LOG_CTRL_GETSOCKNAME, LOGTCP, "NSTCP", NSLOG_DBG,
+ "cpcb=%p,conn=%p,cmd=%u", cpcb, cpcb->conn, amsg->cmd);
+
+ paddr->sin_family = AF_INET;
+ SET_MSG_ERR (m, ERR_OK);
+
+ if (amsg->cmd == 0)
+ {
+ if (cpcb->type == SPL_NETCONN_TCP)
+ {
+ tcp = (struct tcp_pcb *) cpcb->conn->private_data;
+ /* add judgement:(NETCONN_LISTEN == conn->state) in following if words */
+ /* If connect is not done in TCP then the remote address will not be there so need to update proper error code
+ if the application call the getpeername in TCP mode */
+ if ((SPL_NETCONN_LISTEN == conn->state)
+ || (tcp->remote_ip.addr == 0) || (tcp->remote_port == 0))
+ {
+ paddr->sin_family = 0;
+ paddr->sin_port = 0;
+ paddr->sin_addr.s_addr = 0;
+ SET_MSG_ERR (m, ERR_CONN);
+ }
+ else
+ {
+ paddr->sin_port = spl_htons (tcp->remote_port);
+ paddr->sin_addr.s_addr = tcp->remote_ip.addr;
+ }
+ }
+ else if (cpcb->type == SPL_NETCONN_UDP)
+ {
+ udp = (struct udp_pcb *) cpcb->conn->private_data;
+ /* If connect is not done in UDP then the remote address will not be there so need to update proper error code
+ if the application call the getpeername in UDP mode
+ */
+ if ((udp->remote_ip.addr == 0) || (udp->remote_port == 0))
+ {
+ paddr->sin_family = 0;
+ paddr->sin_port = 0;
+ paddr->sin_addr.s_addr = 0;
+ SET_MSG_ERR (m, ERR_CONN);
+ }
+ else
+ {
+ paddr->sin_port = spl_htons (udp->remote_port);
+ paddr->sin_addr.s_addr = udp->remote_ip.addr;
+ }
+ }
+ }
+ else
+ {
+ if (cpcb->type == SPL_NETCONN_TCP)
+ {
+ tcp = (struct tcp_pcb *) cpcb->conn->private_data;
+ paddr->sin_port = spl_htons (tcp->local_port);
+ paddr->sin_addr.s_addr = tcp->local_ip.addr;
+ }
+ else if (cpcb->type == SPL_NETCONN_UDP)
+ {
+ udp = (struct udp_pcb *) cpcb->conn->private_data;
+ paddr->sin_port = spl_htons (udp->local_port);
+ paddr->sin_addr.s_addr = udp->local_ip.addr;
+ }
+ }
+}
+
+/**
+ * Close a TCP pcb contained in a netconn
+ * Called from netconn_close
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+void
+do_close (struct common_pcb *cpcb, msg_close * cmsg)
+{
+ spl_netconn_t *conn = cpcb->conn;
+ data_com_msg *m = MSG_ENTRY (cmsg, data_com_msg, buffer);
+
+ NSTCP_LOGDBG ("msg->conn=%p,state=%d", conn, conn->state);
+
+ /* @todo: abort running write/connect? */
+ if ((conn->state != SPL_NETCONN_NONE)
+ && (conn->state != SPL_NETCONN_LISTEN)
+ && (conn->state != SPL_NETCONN_CONNECT))
+ {
+ if (SPL_NETCONN_TCP != cpcb->type)
+ {
+ NSTCP_LOGERR ("msg->conn=%p,type=%d", conn, cpcb->type);
+ return;
+ }
+ NSTCP_LOGWAR ("msg->conn=%p,state=%d", conn, conn->state);
+ SET_MSG_ERR (m, ERR_INPROGRESS);
+ }
+ else if (cpcb->type == SPL_NETCONN_TCP) //clear codeDEX warning , CID:24336, cpcb can't be null.
+ {
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data;
+
+ if (tpcb == NULL)
+ {
+ NSTCP_LOGERR ("tpcb null msg->conn=%p,type=%d", conn, cpcb->type);
+ return;
+ }
+ if ((cmsg->shut != SPL_NETCONN_SHUT_RDWR)
+ && (conn->state == SPL_NETCONN_LISTEN))
+ {
+ /* LISTEN doesn't support half shutdown */
+ NSTCP_LOGERR
+ ("LISTEN doesn't support half shutdown!]conn=%p,pcb=%p,state=%d",
+ conn, tpcb, conn->state);
+ SET_MSG_ERR (m, ERR_CONN);
+ }
+ else
+ {
+ if (cmsg->shut & SPL_NETCONN_SHUT_RD)
+ {
+ /* Drain and delete mboxes */
+ (void) netconn_drain (cpcb->type, conn);
+ unlink_recv_ring (conn);
+ }
+
+ if (((NULL != cpcb->current_msg)
+ && (conn->state != SPL_NETCONN_CONNECT))
+ || (0 != cpcb->write_offset))
+ {
+ NSTCP_LOGERR
+ ("already writing or closing]conn=%p,pcb=%p,offset=%zu,curmsg=%p",
+ conn, tpcb, cpcb->write_offset, cpcb->current_msg);
+ SET_MSG_ERR (m, ERR_CONN);
+ return;
+ }
+
+ if (conn->state == SPL_NETCONN_CONNECT)
+ {
+ if (cpcb->current_msg != NULL
+ && cpcb->current_msg->param.minor_type ==
+ SPL_API_DO_CONNECT)
+ {
+ SET_MSG_ERR (m, ERR_RST);
+ SYNC_MSG_ACK (cpcb->current_msg);
+ }
+ else
+ {
+ NSTCP_LOGINF
+ ("already in connecting]conn=%p,cpcb=%p,msg=%p", conn,
+ cpcb, cpcb->current_msg);
+ }
+ /* maybe need to clean cpcb->msg_head */
+ }
+
+ conn->state = SPL_NETCONN_CLOSE;
+ cpcb->current_msg = m;
+ (void) do_close_internal (cpcb, 1);
+
+ if (SPL_NETCONN_SHUT_RD == cmsg->shut
+ || SPL_NETCONN_SHUT_RDWR == cmsg->shut)
+ {
+ SPL_API_EVENT (conn, SPL_NETCONN_EVT_RCVPLUS, 1);
+ }
+
+ return;
+ }
+ }
+ else
+ {
+ SET_MSG_ERR (m, ERR_VAL);
+ }
+}
+
+/*trans kerner option to stackx option*/
+int
+ks_to_stk_opt (int opt)
+{
+ int stack_opt = opt;
+ switch (opt)
+ {
+ case SO_DEBUG:
+ stack_opt = SOF_DEBUG;
+ break;
+ case SO_ACCEPTCONN:
+ stack_opt = SOF_ACCEPTCONN;
+ break;
+ case SO_BROADCAST:
+ stack_opt = SOF_BROADCAST;
+ break;
+ case SO_KEEPALIVE:
+ stack_opt = SOF_KEEPALIVE;
+ break;
+ case SO_REUSEADDR:
+ stack_opt = SOF_REUSEADDR;
+ break;
+ case SO_DONTROUTE:
+ stack_opt = SOF_DONTROUTE;
+ break;
+ case SO_USELOOPBACK:
+ stack_opt = SOF_USELOOPBACK;
+ break;
+ case SO_OOBINLINE:
+ stack_opt = SOF_OOBINLINE;
+ break;
+ default:
+ stack_opt = opt;
+ break;
+ }
+ return stack_opt;
+}
+
+void
+do_get_tcpproto_getsockopt_internal (struct common_pcb *cpcb,
+ msg_setgetsockopt * smsg)
+{
+ int optname;
+ void *optval;
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) cpcb->conn->private_data;
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+
+ optname = smsg->optname;
+ optval = &smsg->optval;
+
+ switch (optname)
+ {
+ case SPL_TCP_NODELAY:
+ *(int *) optval = tcp_nagle_disabled (tpcb);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,TCP_NODELAY=%s",
+ cpcb->socket, (*(int *) optval) ? "on" : "off");
+ break;
+
+ case SPL_TCP_KEEPIDLE:
+ *(int *) optval = (int) (tpcb->keep_idle / 1000);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPIDLE=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ case SPL_TCP_KEEPINTVL:
+ *(int *) optval = (int) (tpcb->keep_intvl / 1000);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPINTVL=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ case SPL_TCP_KEEPCNT:
+ *(int *) optval = (int) tpcb->keep_cnt;
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,SPL_TCP_KEEPCNT=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+
+ default:
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname);
+ SET_MSG_ERR (m, EOPNOTSUPP);
+ break;
+ }
+}
+
+void
+do_get_ipproto_getsockopt_internal (struct common_pcb *cpcb,
+ msg_setgetsockopt * smsg)
+{
+ int optname;
+ u32_t optlen;
+ void *optval;
+
+ struct ip_pcb *ipcb = (struct ip_pcb *) (cpcb);
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+
+ optname = smsg->optname;
+ optval = &smsg->optval;
+ optlen = smsg->optlen;
+
+ switch (optname)
+ {
+ case IP_TTL:
+ *(int *) optval = ipcb->ttl;
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,IP_TTL=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ case IP_TOS:
+ smsg->optlen =
+ (optlen < sizeof (u32_t)) ? sizeof (u8_t) : sizeof (u32_t);
+ if (smsg->optlen == sizeof (u8_t))
+ {
+ *(u8_t *) optval = ipcb->tos;
+ }
+ else
+ {
+ *(u32_t *) optval = (u32_t) ipcb->tos;
+ }
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,IP_TOS=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ default:
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname);
+ break;
+ }
+}
+
+void
+do_get_solsocket_getsockopt_internal (struct common_pcb *cpcb,
+ msg_setgetsockopt * smsg)
+{
+ int optname;
+ void *optval;
+ struct tcp_pcb *tpcb = NULL;
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+ struct tcp_pcb *pcb = (struct tcp_pcb *) cpcb->conn->private_data;
+
+ optname = smsg->optname;
+ optval = &smsg->optval;
+
+ switch (optname)
+ {
+ /* The option flags */
+ case SO_BROADCAST:
+ case SO_KEEPALIVE:
+ case SO_REUSEADDR:
+ *(int *) optval =
+ (ip_get_option ((struct ip_pcb *) cpcb, ks_to_stk_opt (optname))) ? 1
+ : 0;
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]fd=%d,optname=%d,optval=%s",
+ cpcb->socket, optname, (*(int *) optval ? "on" : "off"));
+ break;
+ case SO_ACCEPTCONN:
+ tpcb = (struct tcp_pcb *) cpcb->conn->private_data;
+ if ((smsg->optlen < sizeof (int)) || (NULL == tpcb))
+ {
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "(SOL_SOCKET, SO_ACCEPTCONN) failed]fd=%d,tcp=%p,optlen=%u",
+ cpcb->socket, cpcb, smsg->optlen);
+ break;
+ }
+ if (tpcb->state == LISTEN)
+ {
+ *(int *) optval = 1;
+ }
+ else
+ {
+ *(int *) optval = 0;
+ }
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "(SOL_SOCKET, SO_ACCEPTCONN)]fd=%d,optval=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ case SO_TYPE:
+ switch (cpcb->type)
+ {
+ case SPL_NETCONN_RAW:
+ *(int *) optval = SOCK_RAW;
+ break;
+ case SPL_NETCONN_TCP:
+ *(int *) optval = SOCK_STREAM;
+ break;
+ case SPL_NETCONN_UDP:
+ *(int *) optval = SOCK_DGRAM;
+ break;
+ default: /* unrecognized socket type */
+ *(int *) optval = cpcb->type;
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "(SOL_SOCKET, SO_TYPE): unrecognized socket type]fd=%d,optval=%d",
+ cpcb->socket, *(int *) optval);
+ } /* switch (sock->conn->type) */
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_TYPE)]fd=%d,optval=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ case SO_RCVTIMEO:
+ (*(struct timeval *) optval).tv_sec =
+ spl_netconn_get_recvtimeout (cpcb) / 1000;
+ (*(struct timeval *) optval).tv_usec =
+ (spl_netconn_get_recvtimeout (cpcb) % 1000) * 1000;
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "stackx_getsockopt(SOL_SOCKET, SO_RCVTIMEO)]fd=%d,sec=%ld,usec=%ld",
+ cpcb->socket, (*(struct timeval *) optval).tv_sec,
+ (*(struct timeval *) optval).tv_usec);
+ break;
+ case SO_SNDTIMEO:
+ (*(struct timeval *) optval).tv_sec =
+ spl_netconn_get_sendtimeout (cpcb) / 1000;
+ (*(struct timeval *) optval).tv_usec =
+ (spl_netconn_get_sendtimeout (cpcb) % 1000) * 1000;
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "(SOL_SOCKET, SO_SNDTIMEO)]fd=%dsec=%ld,usec=%ld",
+ cpcb->socket, (*(struct timeval *) optval).tv_sec,
+ (*(struct timeval *) optval).tv_usec);
+ break;
+ case SO_SNDBUF:
+ {
+ u16_t mss = (pcb->mss > TCP_MSS
+ || pcb->mss == 0) ? TCP_MSS : pcb->mss;
+ *(int *) optval = spl_netconn_get_sendbufsize (cpcb->conn) * mss;
+ /*If user has not configured any sendbuffer value then we should return minimum
+ promissed for the connection based on the flow control. */
+ if (*(int *) optval == 0)
+ {
+ *(int *) optval = CONN_TCP_MEM_MIN_LINE * mss;
+ }
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "(SOL_SOCKET, SO_SNDBUF)]fd=%d,optval=%d", cpcb->socket,
+ *(int *) optval);
+ break;
+ }
+ case SO_NO_CHECK:
+ *(int *) optval =
+ (udp_flags ((struct udp_pcb *) cpcb->conn->private_data) &
+ UDP_FLAGS_NOCHKSUM) ? 1 : 0;
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_NO_CHECK)fd=%d,optval=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ case SO_SNDLOWAT:
+ *(int *) optval = 1;
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_SNDLOWAT)fd=%d,optval=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+
+ case SO_RCVLOWAT:
+ *(int *) optval = spl_netconn_get_reclowbufsize (cpcb);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "(SOL_SOCKET, SO_RCVLOWAT)fd=%d,optval=%d",
+ cpcb->socket, *(int *) optval);
+ break;
+ case SO_ERROR:
+ *(int *) optval = GET_MSG_ERR (m);
+ SET_MSG_ERR (m, 0);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "SOL_SOCKET]fd=%d,optval=%d", cpcb->socket,
+ *(int *) optval);
+ break;
+ default:
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported opt]optname=%d", optname);
+ break;
+ }
+}
+
+void
+do_getsockopt_internal (struct common_pcb *cpcb, msg_setgetsockopt * smsg)
+{
+ int level;
+
+ if (NULL == smsg)
+ {
+ NSTCP_LOGERR ("arg NULL");
+ return;
+ }
+
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+
+ level = smsg->level;
+ switch (level)
+ {
+ /* Level: SOL_SOCKET */
+ case SOL_SOCKET:
+ do_get_solsocket_getsockopt_internal (cpcb, smsg);
+
+ break;
+
+ /* Level: IPPROTO_IP */
+ case IPPROTO_IP:
+ do_get_ipproto_getsockopt_internal (cpcb, smsg);
+
+ break;
+ /* Level: IPPROTO_TCP */
+ case IPPROTO_TCP:
+ do_get_tcpproto_getsockopt_internal (cpcb, smsg);
+
+ break;
+ default:
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported level]level=%d", level);
+ break;
+ } /* switch (level) */
+}
+
+void
+do_tcpsock_setsockopt (spl_netconn_t * conn, msg_setgetsockopt * smsg)
+{
+ const void *optval;
+ int optname;
+ struct common_pcb *cpcb = (struct common_pcb *) conn->comm_pcb_data;
+ struct tcp_pcb *tpcb = (struct tcp_pcb *) conn->private_data;
+
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+
+ optname = smsg->optname;
+ optval = &smsg->optval;
+
+ switch (optname)
+ {
+ case SPL_TCP_NODELAY:
+ if (*(int *) optval)
+ {
+ tcp_nagle_disable (tpcb);
+ }
+ else
+ {
+ tcp_nagle_enable (tpcb);
+ }
+
+ NSTCP_LOGDBG ("IPPROTO_TCP, TCP_NODELAY]fd=%d,optval=%s",
+ cpcb->socket, (*(int *) optval) ? "on" : "off");
+ break;
+
+ case SPL_TCP_KEEPIDLE:
+ /* CID 52121 (#2 of 3): Other violation (HW_VPP_C_FIND_OPERATORS_2_1_1_3) */
+ if ((u32_t) (*(int *) optval) >= INT_MAX / 1000)
+ {
+ NSTCP_LOGWAR ("optval too big]optval=%u",
+ (u32_t) (*(int *) optval));
+ *(int *) optval = INT_MAX / 1000;
+ }
+
+ tpcb->keep_idle = 1000 * (u32_t) (*(int *) optval);
+
+ if (tpcb->keep_idle > TCP_KEEPIDLE_DEFAULT)
+ {
+ NSTCP_LOGWAR
+ ("(%d, IPPROTO_TCP, SPL_TCP_KEEPIDLE. value bigger than 7200000UL so setting to default 7200000UL) requested is -> %"
+ U32_F " ", cpcb->socket, tpcb->keep_idle);
+ tpcb->keep_idle = TCP_KEEPIDLE_DEFAULT;
+ }
+
+ NSTCP_LOGDBG ("IPPROTO_TCP, SPL_TCP_KEEPIDLE](fd=%d,keep_idle=%" U32_F
+ " ", cpcb->socket, tpcb->keep_idle);
+
+ /* Not required lwip_slowtmr will take care about timer. */
+ break;
+ case SPL_TCP_KEEPINTVL:
+ /* CID 52121 (#1 of 3): Other violation (HW_VPP_C_FIND_OPERATORS_2_1_1_3) */
+ if ((u32_t) (*(int *) optval) >= INT_MAX / 1000)
+ {
+ NSTCP_LOGWAR ("optval too big]optval=%u",
+ (u32_t) (*(int *) optval));
+ *(int *) optval = INT_MAX / 1000;
+ }
+
+ tpcb->keep_intvl = 1000 * (u32_t) (*(int *) optval);
+
+ if (tpcb->keep_intvl > TCP_KEEPIDLE_DEFAULT) /*max timer value supported */
+ {
+ NSTCP_LOGWAR
+ ("(%d, IPPROTO_TCP, SPL_TCP_KEEPINTVL. value bigger than 7200000UL so setting to default 7200000UL) requested is -> %"
+ U32_F " ", cpcb->socket, tpcb->keep_intvl);
+ tpcb->keep_intvl = TCP_KEEPIDLE_DEFAULT;
+ }
+ NSTCP_LOGDBG ("IPPROTO_TCP, SPL_TCP_KEEPINTVL]fd=%d,keep_intvl=%" U32_F
+ " ", cpcb->socket, tpcb->keep_intvl);
+ break;
+ case SPL_TCP_KEEPCNT:
+ tpcb->keep_cnt = (u32_t) (*(int *) optval);
+ NSTCP_LOGDBG ("IPPROTO_TCP, SPL_TCP_KEEPCNT]fd=%d,keep_cnt=%" U32_F " ",
+ cpcb->socket, tpcb->keep_cnt);
+ break;
+ default:
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname);
+ break;
+ }
+}
+
+void
+do_ipsock_setsockopt (struct common_pcb *cpcb, msg_setgetsockopt * smsg)
+{
+ const void *optval;
+ u32_t optlen;
+ int optname;
+
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+
+ struct udp_pcb *upcb = (struct udp_pcb *) cpcb->conn->private_data;
+ struct ip_pcb *ipcb = (struct ip_pcb *) upcb;
+
+ optname = smsg->optname;
+ optval = &smsg->optval;
+ optlen = smsg->optlen;
+
+ int val = 0;
+ int bNotAllowSet = 0;
+ switch (optname)
+ {
+ case IP_TTL:
+ ipcb->ttl = (u8_t) (*(int *) optval);
+ NSIP_LOGDBG ("IPPROTO_IP,IP_TTL]fd=%d,ttl=%u", cpcb->socket, ipcb->ttl);
+ break;
+ case IP_TOS:
+ bNotAllowSet = (cpcb->dataSentFlag != 0)
+ && ((SPL_NETCONN_TCP == cpcb->type)
+ || (SPL_NETCONN_UDP == cpcb->type)
+ || (SPL_NETCONN_RAW == cpcb->type));
+ /*not allow set tos value when sending data */
+ if (bNotAllowSet)
+ {
+ SET_MSG_ERR (m, ERR_VAL);
+ break;
+ }
+
+ if (optlen >= sizeof (u32_t))
+ {
+ val = (int) (*(const int *) optval);
+ }
+ else if (optlen >= sizeof (u8_t))
+ {
+ val = (int) (*(const u8_t *) optval);
+ }
+
+ if (SPL_NETCONN_TCP == cpcb->type)
+ {
+ val &= ~INET_ECN_MASK;
+ val |= ipcb->tos & INET_ECN_MASK;
+ }
+ ipcb->tos = (u8_t) (val);
+
+ smsg->msg_box = (get_msgbox ((u8_t) val))->llring;
+
+ NSIP_LOGDBG ("IPPROTO_IP,IP_TOS]]fd=%d,tos=%u", cpcb->socket,
+ ipcb->tos);
+ break;
+ default:
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname);
+ break;
+ }
+}
+
+ /*Made seperate functions to reduce code complexity */
+void
+do_setsockopt_recvtimeout_internal (const void *optval,
+ struct common_pcb *cpcb)
+{
+ if ((*(struct timeval *) optval).tv_sec < 0)
+ {
+ spl_netconn_set_recvtimeout (cpcb, 0);
+ }
+ else
+ {
+ spl_netconn_set_recvtimeout (cpcb, MAX_WAIT_TIMEOUT);
+ if ((*(struct timeval *) optval).tv_sec != 0
+ || (*(struct timeval *) optval).tv_usec != 0)
+ {
+ if ((*(struct timeval *) optval).tv_sec <
+ ((MAX_WAIT_TIMEOUT / 1000) - 1))
+ {
+ spl_netconn_set_recvtimeout (cpcb,
+ (*(struct timeval *) optval).tv_sec
+ * 1000 +
+ (*(struct timeval *)
+ optval).tv_usec / 1000);
+ }
+ }
+ }
+
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "SOL_SOCKET, SO_RCVTIMEO]conn=%p,fd=%d,optval=%d", cpcb,
+ cpcb->socket, cpcb->recv_timeout);
+}
+
+void
+do_setsockopt_sndtimeout_internal (const void *optval,
+ struct common_pcb *cpcb)
+{
+ if ((*(struct timeval *) optval).tv_sec < 0)
+ {
+ spl_netconn_set_sendtimeout (cpcb, 0);
+ }
+ else
+ {
+ spl_netconn_set_sendtimeout (cpcb, MAX_WAIT_TIMEOUT);
+ if ((*(struct timeval *) optval).tv_sec != 0
+ || (*(struct timeval *) optval).tv_usec != 0)
+ {
+ if ((*(struct timeval *) optval).tv_sec <
+ ((MAX_WAIT_TIMEOUT / 1000) - 1))
+ {
+ spl_netconn_set_sendtimeout (cpcb,
+ (*(struct timeval *) optval).tv_sec
+ * 1000 +
+ (*(struct timeval *)
+ optval).tv_usec / 1000);
+ }
+ }
+ }
+
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "SOL_SOCKET, SO_SNDTIMEO]conn=%p,fd=%d,optval=%d", cpcb,
+ cpcb->socket, cpcb->send_timeout);
+}
+
+#define IS_TCP_PCB(cpcb) (cpcb && (cpcb->conn) && (SPL_NETCONN_TCP == cpcb->conn->type))
+NSTACK_STATIC inline void
+set_opt_sol_socket (struct common_pcb *cpcb, struct tcp_pcb *pcb,
+ data_com_msg * m, int level, int optname,
+ const void *optval)
+{
+ switch (optname)
+ {
+ /* The option flags */
+ case SO_BROADCAST:
+
+ /* UNIMPL case SO_DEBUG: */
+ /* UNIMPL case SO_DONTROUTE: */
+ case SO_KEEPALIVE:
+ case SO_REUSEADDR:
+
+ if (NULL == pcb)
+ {
+ NSPOL_LOGERR ("conn->pcb.ip is null");
+ break;
+ }
+
+ if (*(const int *) optval)
+ {
+ ip_set_option ((struct ip_pcb *) pcb, ks_to_stk_opt (optname));
+ }
+ else
+ {
+ ip_reset_option ((struct ip_pcb *) pcb, ks_to_stk_opt (optname));
+ }
+
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "]conn=%p,fd=%d,optname=0x%x,optval=%s",
+ cpcb, cpcb->socket, optname,
+ (*(const int *) optval ? "on" : "off"));
+
+ /* No use now, since tcp_slowtmr will take care about not sending/sending of keepalive */
+ break;
+
+ case SO_RCVLOWAT:
+ spl_netconn_set_reclowbufsize (cpcb, *(int *) optval);
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "SOL_SOCKET, SO_RCVLOWAT]conn=%p,fd=%d,optval=%d", cpcb,
+ cpcb->socket, cpcb->sk_rcvlowat);
+ break;
+
+ case SO_RCVTIMEO:
+ /*to reduce code complexity */
+ do_setsockopt_recvtimeout_internal (optval, cpcb);
+ break;
+
+ case SO_SNDTIMEO:
+ /*to reduce code complexity */
+ do_setsockopt_sndtimeout_internal (optval, cpcb);
+ break;
+
+ case SO_SNDBUF:
+ {
+ /* udp pcb invalid access will cause coredump */
+ if (!IS_TCP_PCB (cpcb))
+ {
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "not support for non tcp socket]optname=%d, level=%d",
+ optname, level);
+ return;
+ }
+
+ u16_t mss = (pcb->mss > TCP_MSS
+ || pcb->mss == 0) ? TCP_MSS : pcb->mss;
+
+ if (*(int *) optval < (int) mss)
+ {
+ /*set value of one TCP_MSS */
+ spl_netconn_set_sendbufsize (cpcb->conn, 1);
+ }
+ else
+ {
+ spl_netconn_set_sendbufsize (cpcb->conn,
+ (*(int *) optval) / (int) mss);
+ }
+
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "SOL_SOCKET, SO_SNDBUF]conn=%p,fd=%d,optval=%d", cpcb,
+ cpcb->socket, cpcb->conn->send_bufsize * mss);
+ break;
+ }
+
+ case SO_NO_CHECK:
+ /* How udp is coming here.. ?? @TODO: May be move to someother function.? */
+ /* solve segment issue when the PCB is not exist */
+ if (NULL == cpcb)
+ {
+ NSPOL_LOGERR ("conn->pcb.udp is null");
+ break;
+ }
+
+ struct udp_pcb *upcb = (struct udp_pcb *) pcb;
+
+ if (*(int *) optval)
+ {
+ udp_setflags (upcb, udp_flags (upcb) | UDP_FLAGS_NOCHKSUM);
+ }
+ else
+ {
+ udp_setflags (upcb, udp_flags (upcb) & ~UDP_FLAGS_NOCHKSUM);
+ }
+
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "SOL_SOCKET, SO_NO_CHECK]conn=%p,fd=%d,optval=0x%x", cpcb,
+ cpcb->socket, upcb->flags);
+ break;
+
+ default:
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]optname=%d", optname);
+ break;
+ } /* switch (optname) */
+
+}
+
+void
+do_setsockopt_internal (struct common_pcb *cpcb, msg_setgetsockopt * smsg)
+{
+ int level, optname;
+ const void *optval;
+
+ data_com_msg *m = MSG_ENTRY (smsg, data_com_msg, buffer);
+ struct tcp_pcb *pcb = (struct tcp_pcb *) cpcb->conn->private_data;
+
+ if (NULL == smsg)
+ {
+ NSTCP_LOGERR ("arg null!");
+ return;
+ }
+
+ level = smsg->level;
+ optname = smsg->optname;
+ optval = &smsg->optval;
+
+ switch (level)
+ {
+ /* Level: SOL_SOCKET */
+ case SOL_SOCKET:
+ set_opt_sol_socket (cpcb, pcb, m, SOL_SOCKET, optname, optval);
+ break;
+
+ /* Level: IPPROTO_IP */
+ case IPPROTO_IP:
+
+ if (NULL == cpcb)
+ {
+ NSPOL_LOGERR ("conn->pcb.ip is null");
+ break;
+ }
+
+ do_ipsock_setsockopt (cpcb, smsg);
+
+ break;
+ /* Level: IPPROTO_TCP */
+ case IPPROTO_TCP:
+ /* udp pcb invalid access will cause coredump */
+ if (!IS_TCP_PCB (cpcb))
+ {
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG,
+ "not support for non tcp socket]optname=%d,level=%d",
+ optname, level);
+ return;
+ }
+
+ if (NULL == cpcb)
+ {
+ NSPOL_LOGERR ("conn->pcb.tcp is null");
+ break;
+ }
+
+ do_tcpsock_setsockopt (cpcb->conn, smsg);
+
+ break;
+ default:
+ SET_MSG_ERR (m, ERR_VAL);
+ NSPOL_LOGDBG (SOCKETS_DEBUG, "unsupported]level=%d", level);
+ break;
+ } /* switch (level) */
+}
+
+/*app send its version info to nStackMain */
+void
+do_app_touch (msg_app_touch * smsg)
+{
+ //write app version info to running.log
+ NSPOL_LOGINF (SOCKETS_DEBUG, "hostpid=%u,app_version=%s", smsg->hostpid,
+ smsg->app_version);
+}
+
+void
+tcp_free_accept_ring (spl_netconn_t * conn)
+{
+ err_t de_err = ERR_OK;
+ spl_netconn_t *newconn;
+ while (1)
+ {
+ newconn = NULL;
+ /* -1 means nonblocking */
+ de_err = accept_dequeue (conn, (void **) &newconn, (u32_t) - 1);
+ if (de_err == ERR_WOULDBLOCK || newconn == NULL)
+ return;
+
+ tcp_drop_conn (newconn);
+ }
+}
+
+void
+tcp_drop_conn (spl_netconn_t * conn)
+{
+ /* usually we should not access pcb by recv_obj, but no choice */
+ struct tcp_pcb *pcb = (struct tcp_pcb *) conn->private_data;
+
+ /* free conn first, even pcb is NULL */
+ free_conn_by_spl (conn);
+
+ if (pcb == NULL)
+ {
+ NSTCP_LOGWAR
+ ("a tcp connection in accept queue without pcb!]newconn=%p", conn);
+ return;
+ }
+
+ /* tell peer conneciton is reset */
+ NSTCP_LOGWAR ("sending RST in accept waiting queue!]pcb=%p", pcb);
+
+ tcp_rst (pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
+ pcb->local_port, pcb->remote_port);
+
+ tcp_pcb_remove (&tcp_active_pcbs, pcb);
+ memp_free (MEMP_TCP_PCB, pcb);
+}
+
+void
+update_tcp_state (spl_netconn_t * conn, enum tcp_state state)
+{
+ spl_tcp_state_t spl_state;
+
+ if (conn != NULL)
+ {
+ switch (state)
+ {
+ case CLOSED:
+ spl_state = SPL_CLOSED;
+ break;
+ case LISTEN:
+ spl_state = SPL_LISTEN;
+ break;
+ case SYN_SENT:
+ spl_state = SPL_SYN_SENT;
+ break;
+ case SYN_RCVD:
+ spl_state = SPL_SYN_RCVD;
+ break;
+ case ESTABLISHED:
+ spl_state = SPL_ESTABLISHED;
+ break;
+ case FIN_WAIT_1:
+ spl_state = SPL_FIN_WAIT_1;
+ break;
+ case FIN_WAIT_2:
+ spl_state = SPL_FIN_WAIT_2;
+ break;
+ case CLOSE_WAIT:
+ spl_state = SPL_CLOSE_WAIT;
+ break;
+ case CLOSING:
+ spl_state = SPL_CLOSING;
+ break;
+ case LAST_ACK:
+ spl_state = SPL_LAST_ACK;
+ break;
+ case TIME_WAIT:
+ spl_state = SPL_TIME_WAIT;
+ break;
+ default:
+ spl_state = SPL_CLOSED;
+ break;
+ }
+ conn->tcp_state = spl_state;
+ NSTCP_LOGINF ("conn=%p,private_data=%p,state=%d", conn,
+ conn->private_data, spl_state);
+ }
+}
+
+void
+do_update_pcbstate ()
+{
+ struct tcp_pcb *tpcb;
+ int i;
+ for (i = 0; i < NUM_TCP_PCB_LISTS; i++)
+ {
+ for (tpcb = *tcp_pcb_lists[i]; tpcb != NULL; tpcb = tpcb->next)
+ {
+ if (tpcb->callback_arg)
+ {
+ update_tcp_state ((spl_netconn_t *) tpcb->callback_arg,
+ tpcb->state);
+ }
+ }
+ }
+
+ return;
+}
+
+void
+init_stackx_lwip ()
+{
+ lwip_init ();
+ sys_timeouts_init ();
+ return;
+}
+
+void
+free_common_pcb (struct common_pcb *cpcb)
+{
+ if (res_free (&cpcb->res_chk))
+ {
+ NSFW_LOGERR ("conn refree!]conn=%p", cpcb->conn);
+ return;
+ }
+
+ common_pcb_reset (cpcb);
+
+ mring_handle pool = p_def_stack_instance->cpcb_seg;
+ if (nsfw_mem_ring_enqueue (pool, (void *) cpcb) != 1)
+ {
+ NSSBR_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ }
+ return;
+}
+
+struct common_pcb *
+alloc_common_pcb (enum spl_netconn_type type)
+{
+ struct common_pcb *cpcb = NULL;
+
+ if (nsfw_mem_ring_dequeue (p_def_stack_instance->cpcb_seg, (void **) &cpcb)
+ != 1)
+ {
+ NSSBR_LOGERR ("malloc conn failed");
+ return NULL;
+ }
+
+ NSFW_LOGINF ("alloc_common_pcb]cpcb=%p", cpcb);
+
+ common_pcb_init (cpcb);
+ cpcb->type = type;
+ return cpcb;
+}
diff --git a/stacks/lwip_stack/lwip_src/api/spl_netbuf.c b/stacks/lwip_stack/lwip_src/api/spl_netbuf.c
new file mode 100644
index 0000000..9c682fc
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_netbuf.c
@@ -0,0 +1,58 @@
+/*
+*
+* 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.
+*/
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+//#include "sc_dpdk.h"
+#include "spl_netbuf.h"
+
+void
+spl_netbuf_delete (struct spl_netbuf *buf)
+{
+ if (likely (buf != NULL))
+ {
+ spl_pbuf_free (PTR_SHTOL (struct spl_pbuf *, buf->p));
+ }
+}
diff --git a/stacks/lwip_stack/lwip_src/api/spl_netifapi.c b/stacks/lwip_stack/lwip_src/api/spl_netifapi.c
new file mode 100644
index 0000000..ab1446a
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_netifapi.c
@@ -0,0 +1,288 @@
+/*
+*
+* 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"
+
+#if STACKX_NETIF_API
+
+#include "nsfw_msg_api.h"
+#include "netifapi.h"
+#include <sys/socket.h>
+//#include <netinet/in.h>
+
+#include "stackx_spl_share.h"
+#include "spl_sbr.h"
+#include "stackx/spl_api.h"
+#include "tcpip.h"
+#include "sc_dpdk.h"
+#include "spl_instance.h"
+#include "spl_hal.h"
+#include "spl_def.h"
+#include <inet.h>
+
+struct netifExt *gNetifExt = NULL;
+
+/**
+ * common operation for sbr message.
+ *
+ * @param msg the api_msg_msg describing the connection type
+ */
+int
+do_halmsg (data_com_msg * m)
+{
+ NSPOL_LOGDBG (TESTSOCKET_DEBUG | STACKX_DBG_TRACE,
+ "the msg is from HAL module, minor(%u)", m->param.minor_type);
+ return 0;
+}
+
+static int
+_do_add_netif (data_com_msg * m)
+{
+ NSPOL_LOGINF (NETIF_DEBUG, "_do_add_netif\n");
+
+ m->param.err = ERR_OK;
+ msg_add_netif *_m = (msg_add_netif *) m->buffer;
+ _m->function (_m);
+ SYNC_MSG_ACK (m);
+ return 0;
+}
+
+struct netif *
+find_netif_by_if_name (char *if_name)
+{
+
+ struct netifExt *netifEx = gNetifExt;
+ struct netif *netif = NULL;
+
+ while (netifEx != NULL)
+ {
+ if (!(strcmp (netifEx->if_name, if_name)))
+ {
+ for (netif = netif_list; netif != NULL; netif = netif->next)
+ {
+ if (netifEx->id == netif->num)
+ return netif;
+ }
+
+ }
+ netifEx = netifEx->next;
+ }
+
+ return NULL;
+}
+
+/*@TODO: May be moved to some other file ? Like HAL*/
+struct netif *
+get_netif_by_ip (unsigned int ip)
+{
+ struct netif *netif;
+
+ if (ip == 0)
+ {
+ return NULL;
+ }
+
+ for (netif = netif_list; netif != NULL; netif = netif->next)
+ {
+ if (ip == netif->ip_addr.addr)
+ {
+ NSPOL_LOGINF (NETIF_DEBUG, "netif_find: found %x %c %c", ip,
+ netif->name[0], netif->name[1]);
+ return netif;
+ }
+ }
+ NSPOL_LOGINF (NETIF_DEBUG, "netif_find: Not found %x", ip);
+ return NULL;
+}
+
+/*
+@TODO:
+*/
+struct netif *
+netif_check_broadcast_addr (spl_ip_addr_t * addr)
+{
+ return NULL;
+}
+
+struct netifExt *
+getNetifExt (u16_t id)
+{
+
+ struct netifExt *netifEx;
+ netifEx = gNetifExt;
+
+ while (netifEx != NULL)
+ {
+ if (netifEx->id == id)
+ {
+ return netifEx;
+ }
+ netifEx = netifEx->next;
+ }
+
+ return NULL;
+}
+
+int
+netifExt_add (struct netif *netif)
+{
+
+ /* If Netif Ext already created for it then just return sucess */
+ if (getNetifExt (netif->num))
+ return 0;
+
+ struct netifExt *netifEx = malloc (sizeof (struct netifExt));
+ if (!netifEx)
+ {
+ return -1;
+ }
+
+ if (memset (netifEx, 0, sizeof (struct netifExt)) < 0)
+ {
+ return -1;
+ }
+
+ NSPOL_LOGINF (NETIF_DEBUG, "netifExt_added \n");
+
+ netifEx->id = netif->num;
+
+ /* add this netif to the list */
+ netifEx->next = gNetifExt;
+ gNetifExt = netifEx;
+ return 0;
+}
+
+void
+do_netifapi_netif_add (msg_add_netif * pmsg)
+{
+ struct netif *netif = NULL;
+ ip_addr_t ipaddr;
+ ip_addr_t netmask;
+ ip_addr_t gw;
+
+ data_com_msg *m = MSG_ENTRY (pmsg, data_com_msg, buffer);
+ ipaddr.addr = pmsg->ipaddr->addr;
+ netmask.addr = pmsg->netmask->addr;
+ gw.addr = pmsg->gw->addr;
+
+ NSPOL_LOGINF (NETIF_DEBUG, "do_netifapi_netif_add \n");
+ netif = netif_add (pmsg->netif,
+ &ipaddr,
+ &netmask, &gw, pmsg->state, pmsg->init, pmsg->input);
+
+ if (NULL == netif)
+ {
+ SET_MSG_ERR (m, ERR_IF);
+ }
+ else
+ {
+
+ SET_MSG_ERR (m, ERR_OK);
+ NSPOL_LOGINF (NETIF_DEBUG, "netif created name %c%c%d\n",
+ netif->name[0], netif->name[1], netif->num);
+ pmsg->voidfunc (pmsg->netif);
+ add_disp_netif (pmsg->netif);
+ }
+
+}
+
+err_t
+spl_netifapi_netif_add (struct netif *pnetif,
+ spl_ip_addr_t * ipaddr,
+ spl_ip_addr_t * netmask,
+ spl_ip_addr_t * gw,
+ void *state,
+ netif_init_fn init,
+ netif_input_fn input, netifapi_void_fn voidfunc)
+{
+ msg_add_netif stmsg;
+
+ stmsg.function = do_netifapi_netif_add;
+ stmsg.netif = pnetif;
+ stmsg.ipaddr = ipaddr;
+ stmsg.netmask = netmask;
+ stmsg.gw = gw;
+ stmsg.state = state;
+ stmsg.init = init;
+ stmsg.input = input;
+ stmsg.voidfunc = voidfunc;
+ return tcpip_netif_add (&stmsg);
+}
+
+int
+add_netif_ip (char *netif_name, unsigned int ip, unsigned int mask)
+{
+ struct netif *pnetif;
+ int retval;
+
+ if (get_netif_by_ip (ip))
+ {
+ NSPOL_LOGERR ("ip is exist]IP=%s", inet_ntoa (ip));
+ return -1;
+ }
+ NSPOL_LOGINF (NETIF_DEBUG, "add_netif_ip] IP=%s", inet_ntoa (ip));
+
+ pnetif = find_netif_by_if_name (netif_name);
+ if (pnetif == NULL)
+ {
+ return -1;
+ }
+
+ pnetif->ip_addr.addr = ip;
+ pnetif->netmask.addr = mask;
+
+ if (ip)
+ {
+ retval = etharp_request (pnetif, &pnetif->ip_addr);
+
+ if (ERR_OK != retval)
+ {
+ NSPOL_LOGERR ("etharp_request failed]retval=%d,netif=%p,ip=%u", retval, pnetif, pnetif->ip_addr.addr); //inet_ntoa is not thread-safe, print u32 instead.
+ }
+ }
+
+ NSPOL_LOGINF (NETIF_DEBUG, "add_netif_ip]netif_name=%s,IP=%s,mask=0x%08x",
+ netif_name, inet_ntoa (ip), spl_htonl (mask));
+ return 0;
+}
+
+/*lint -e438*/
+int
+del_netif_ip (char *netif_name, unsigned int ip)
+{
+ struct netif *pnetif;
+ //struct netif* vnetif = NULL;
+ //struct netif** ref;
+
+ pnetif = find_netif_by_if_name (netif_name);
+ if (NULL == pnetif)
+ {
+ return -1;
+ }
+
+ NSPOL_LOGINF (NETIF_DEBUG, "del_netif_ip] IP=%s", inet_ntoa (ip));
+
+ pnetif->ip_addr.addr = 0;
+ pnetif->netmask.addr = 0;
+ return 0;
+}
+
+REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_HAL, SPL_TCPIP_MSG_NETIFAPI,
+ do_halmsg);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_HAL, SPL_TCPIP_MSG_NETIFAPI,
+ NETIF_DO_ADD, _do_add_netif);
+
+#endif /* STACKX_NETIF_API */
diff --git a/stacks/lwip_stack/lwip_src/api/spl_sbr.c b/stacks/lwip_stack/lwip_src/api/spl_sbr.c
new file mode 100644
index 0000000..4c510a5
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_sbr.c
@@ -0,0 +1,495 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "stackx_spl_share.h"
+#include "spl_api.h"
+#include "ip.h"
+#include "spl_api_msg.h"
+#include "stackx_spl_msg.h"
+#include "internal_msg.h"
+#include "spl_sbr.h"
+#include "spl_pbuf.h"
+
+/**
+ * common operation for sbr message.
+ *
+ * @param msg the api_msg_msg describing the connection type
+ */
+int
+do_sbrmsg (data_com_msg * m)
+{
+ return 0;
+}
+
+/**
+ * Create a new pcb of a specific type inside a netconn.
+ * Called from netconn_new_with_proto_and_callback.
+ *
+ * @param msg the api_msg_msg describing the connection type
+ */
+static int
+_do_newconn (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ msg_new_netconn *_m = (msg_new_netconn *) m->buffer;
+ m->param.err = spl_pcb_new (_m);
+
+ if (ERR_OK != m->param.err)
+ {
+ NSPOL_LOGERR ("pcb_new err]conn=%p,pid=%u,err=%d", _m->conn,
+ m->param.recycle_pid, m->param.err);
+ goto ERROR;
+ }
+
+ NSFW_LOGINF ("alloc pcb]conn=%p,pcb=%p,pid=%u", _m->conn,
+ _m->conn->private_data, m->param.recycle_pid);
+
+ /* sbr use it to set receiver after new connction */
+ m->param.receiver = (i64) & _m->conn->private_data;
+ m->param.comm_receiver = (i64) & _m->conn->comm_pcb_data;
+ _m->conn->recv_obj = m->param.receiver;
+
+ SYNC_MSG_ACK (m);
+ return 0;
+
+ERROR:
+ SYNC_MSG_ACK (m);
+ return 0;
+}
+
+int
+_do_connect (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ if (cpcb == NULL)
+ {
+ m->param.err = ERR_CLSD;
+ SYNC_MSG_ACK (m);
+ return 0;
+ }
+
+ msg_connect *_m = (msg_connect *) m->buffer;
+ do_connect (cpcb, _m);
+
+ /**
+ * err == ERR_OK only applies for blocking connction, so others mean
+ * in progress for nonblocking connection or failed to connect
+ * cpcb may be NULL, so don't change the order of the 2 ifs.
+ */
+ if (m->param.err != ERR_OK || cpcb->type != SPL_NETCONN_TCP)
+ SYNC_MSG_ACK (m);
+
+ return 0;
+}
+
+/**
+ * Close a TCP pcb contained in a netconn
+ * Called from netconn_close
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+int
+_do_close (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ if (cpcb != NULL)
+ {
+ msg_close *_m = (msg_close *) m->buffer;
+ do_close (cpcb, _m);
+ }
+
+ /* if cpcb == NULL, assuming the close is okay, err = ERR_OK */
+ SYNC_MSG_ACK (m);
+
+ return 0;
+}
+
+/**
+ * Delete the pcb inside a netconn.
+ * Called from netconn_delete.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_delconn (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+ msg_delete_netconn *_m = (msg_delete_netconn *) m->buffer;
+
+ if (0 == (--_m->msg_box_ref))
+ {
+ /* the aync msg is released inside */
+ ss_recycle_conn ((void *) _m, do_try_delconn);
+ }
+
+ return 0;
+}
+
+/**
+ * handle message to send UDP packets.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_send (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ msg_send_buf *_m = (msg_send_buf *) m->buffer;
+ if (cpcb == NULL)
+ {
+ NS_LOG_CTRL (LOG_CTRL_SEND, STACKX, "NSPOL", NSLOG_ERR,
+ "failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ spl_pbuf_free (_m->p);
+ _m->p = NULL;
+ ASYNC_MSG_FREE (m);
+ return -1;
+ }
+
+ do_send (cpcb, _m);
+
+ ASYNC_MSG_FREE (m);
+
+ return 0;
+}
+
+/**
+ * handle message to send TCP packets.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_write (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ void *tpcb = TCP_PRIVATE_PTR (m);
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+
+ msg_write_buf *_m = (msg_write_buf *) m->buffer;
+ if ((tpcb == NULL) || (cpcb == NULL))
+ {
+ NS_LOG_CTRL (LOG_CTRL_WRITE, STACKX, "NSPOL", NSLOG_ERR,
+ "failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ spl_pbuf_free (_m->p);
+ _m->p = NULL;
+ ASYNC_MSG_FREE (m);
+ return -1;
+ }
+
+ do_write (cpcb, _m);
+
+ return 0;
+}
+
+/**
+ * handle message to receive.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_recv (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ msg_recv_buf *_m = (msg_recv_buf *) m->buffer;
+ void *tpcb = TCP_PRIVATE_PTR (m);
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+
+ if ((tpcb == NULL) || (cpcb == NULL))
+ {
+ NS_LOG_CTRL (LOG_CTRL_RECV, STACKX, "NSPOL", NSLOG_ERR,
+ "failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ spl_pbuf_free (_m->p);
+ _m->p = NULL;
+ ASYNC_MSG_FREE (m);
+ return -1;
+ }
+
+ do_recv (cpcb, _m);
+ ASYNC_MSG_FREE (m);
+ return 0;
+}
+
+/**
+ * handle message to bind local address.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_bind (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ if (cpcb == NULL)
+ {
+ NSPOL_LOGERR ("failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ m->param.err = ERR_VAL;
+ SYNC_MSG_ACK (m);
+ return -1;
+ }
+
+ msg_bind *_m = (msg_bind *) m->buffer;
+ do_bind (cpcb, _m);
+
+ SYNC_MSG_ACK (m);
+
+ return 0;
+}
+
+/**
+ * handle message to listen for new connection.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_listen (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ if (cpcb == NULL)
+ {
+ NSPOL_LOGERR ("failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ m->param.err = ERR_CONN;
+ SYNC_MSG_ACK (m);
+ return -1;
+ }
+
+ msg_listen *_m = (msg_listen *) m->buffer;
+ do_listen (cpcb, _m);
+
+ /* Update since pcb may have been changed */
+ //m->param.receiver = (i64)&_m->conn->private_data;
+ SYNC_MSG_ACK (m);
+ return 0;
+}
+
+/**
+ * handle message to set socket option.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_setsockopt (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ if (cpcb == NULL)
+ {
+
+ NSPOL_LOGERR ("failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ m->param.err = ERR_VAL;
+ SYNC_MSG_ACK (m);
+ return -1;
+ }
+
+ msg_setgetsockopt *_m = (msg_setgetsockopt *) m->buffer;
+ do_setsockopt_internal (cpcb, _m);
+
+ SYNC_MSG_ACK (m);
+
+ return 0;
+}
+
+/**
+ * handle message to get socket option.
+ *
+ * @param msg the data_com_msg to handle
+ */
+static int
+_do_getsockopt (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ if (cpcb == NULL)
+ {
+ NSPOL_LOGERR ("failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ m->param.err = ERR_VAL;
+ SYNC_MSG_ACK (m);
+ return -1;
+ }
+
+ msg_setgetsockopt *_m = (msg_setgetsockopt *) m->buffer;
+ do_getsockopt_internal (cpcb, _m);
+
+ SYNC_MSG_ACK (m);
+
+ return 0;
+}
+
+/**
+ * handle message to free pbuf which never used afterwards by application.
+ *
+ * @param msg the data_com_msg to handle
+ */
+
+static int
+_do_pbuf_free (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ msg_free_buf *_m = (msg_free_buf *) m->buffer;
+ do_pbuf_free (_m->buf);
+
+ ASYNC_MSG_FREE (m);
+
+ return 0;
+}
+
+static int
+_do_getsock_name (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ struct common_pcb *cpcb = COMM_PRIVATE_PTR (m);
+ if (cpcb == NULL)
+ {
+ NSPOL_LOGERR ("failed to find target pcb, drop the message]"
+ "module=%u, major=%u, minor=%u",
+ m->param.module_type,
+ m->param.major_type, m->param.minor_type);
+
+ m->param.err = ERR_VAL;
+ SYNC_MSG_ACK (m);
+ return -1;
+ }
+
+ msg_getaddrname *_m = (msg_getaddrname *) m->buffer;
+ do_getsockname (cpcb, _m);
+
+ SYNC_MSG_ACK (m);
+
+ return 0;
+}
+
+/* app send its version info to nStackMain */
+static int
+_do_app_touch (data_com_msg * m)
+{
+ m->param.err = ERR_OK;
+
+ msg_app_touch *_m = (msg_app_touch *) m->buffer;
+ do_app_touch (_m);
+
+ ASYNC_MSG_FREE (m);
+ return 0;
+}
+
+/**
+ * process message from sbr module, all the processing function
+ * is registered when nstack is up.
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+int
+spl_sbr_process (data_com_msg * m)
+{
+ if (m == NULL)
+ {
+ NSPOL_LOGERR ("message is NULL");
+ return -1;
+ }
+
+ return call_msg_fun (m);
+}
+
+int
+spl_unsupport_process (data_com_msg * m)
+{
+ NSPOL_LOGINF (TCPIP_DEBUG, "module_type=%u,major_type=%u,minor_type=%u",
+ m->param.module_type, m->param.major_type,
+ m->param.minor_type);
+ if (MSG_SYN_POST == m->param.op_type)
+ {
+ m->param.err = ERR_EPROTONOSUPPORT;
+ SYNC_MSG_ACK (m);
+ }
+ else
+ {
+ ASYNC_MSG_FREE (m);
+ }
+
+ return -1;
+}
+
+REGIST_MSG_UNSUPPORT_FUN (spl_unsupport_process);
+REGIST_MSG_MODULE_MAJOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ do_sbrmsg);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_NEWCONN, _do_newconn);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_CONNECT, _do_connect);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_CLOSE, _do_close);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_DELCON, _do_delconn);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_SEND, _do_send);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_WRITE, _do_write);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_RECV, _do_recv);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_BIND, _do_bind);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_LISTEN, _do_listen);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_GET_SOCK_OPT, _do_getsockopt);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_SET_SOCK_OPT, _do_setsockopt);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_PBUF_FREE, _do_pbuf_free);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API,
+ SPL_API_DO_GETSOCK_NAME, _do_getsock_name);
+REGIST_MSG_MODULE_MAJOR_MINOR_FUN (MSG_MODULE_SBR, SPL_TCPIP_NEW_MSG_API, SPL_API_DO_APP_TOUCH, _do_app_touch); /* app send its version info to nStackMain */
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);
diff --git a/stacks/lwip_stack/lwip_src/common/rb_tree.c b/stacks/lwip_stack/lwip_src/common/rb_tree.c
new file mode 100644
index 0000000..3dcb37a
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/rb_tree.c
@@ -0,0 +1,393 @@
+/*
+*
+* 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 "rb_tree.h"
+
+static void
+__rb_rotate_right (struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *left = node->rb_left;
+ struct rb_node *parent = rb_parent (node);
+
+ if ((node->rb_left = left->rb_right))
+ {
+ rb_set_parent (left->rb_right, node);
+ }
+
+ left->rb_right = node;
+
+ rb_set_parent (left, parent);
+
+ if (parent)
+ {
+ if (node == parent->rb_right)
+ {
+ parent->rb_right = left;
+ }
+ else
+ {
+ parent->rb_left = left;
+ }
+ }
+ else
+ {
+ root->rb_node = left;
+ }
+
+ rb_set_parent (node, left);
+}
+
+static void
+__rb_rotate_left (struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *parent = rb_parent (node);
+
+ struct rb_node *right = node->rb_right;
+
+ if ((node->rb_right = right->rb_left))
+ {
+ rb_set_parent (right->rb_left, node);
+ }
+
+ right->rb_left = node;
+ rb_set_parent (right, parent);
+
+ if (parent) /* judge parent node */
+ {
+ if (node == parent->rb_left)
+ {
+ parent->rb_left = right;
+ }
+ else
+ {
+ parent->rb_right = right;
+ }
+ }
+ else
+ {
+ root->rb_node = right;
+ }
+
+ rb_set_parent (node, right);
+}
+
+static void
+__rb_erase_color (struct rb_node *rb_tree_node,
+ struct rb_node *rb_tree_parent,
+ struct rb_root *rb_tree_root)
+{
+ struct rb_node *rb_tree_other;
+
+ while ((!rb_tree_node || rb_is_black (rb_tree_node))
+ && (rb_tree_node != rb_tree_root->rb_node))
+ {
+ if (rb_tree_parent == NULL)
+ {
+ break;
+ }
+
+ if (rb_tree_parent->rb_left == rb_tree_node)
+ {
+ rb_tree_other = rb_tree_parent->rb_right;
+ if (rb_is_red (rb_tree_other))
+ {
+ rb_set_black (rb_tree_other);
+ rb_set_red (rb_tree_parent);
+ __rb_rotate_left (rb_tree_parent, rb_tree_root);
+ rb_tree_other = rb_tree_parent->rb_right;
+ }
+
+ if ((!rb_tree_other->rb_left
+ || rb_is_black (rb_tree_other->rb_left))
+ && (!rb_tree_other->rb_right
+ || rb_is_black (rb_tree_other->rb_right)))
+ {
+ rb_set_red (rb_tree_other);
+ rb_tree_node = rb_tree_parent;
+ rb_tree_parent = rb_parent (rb_tree_node);
+ }
+ else
+ {
+ if (!rb_tree_other->rb_right
+ || rb_is_black (rb_tree_other->rb_right))
+ {
+ rb_set_black (rb_tree_other->rb_left);
+ rb_set_red (rb_tree_other);
+ __rb_rotate_right (rb_tree_other, rb_tree_root);
+ rb_tree_other = rb_tree_parent->rb_right;
+ }
+
+ rb_set_color (rb_tree_other, rb_color (rb_tree_parent));
+ rb_set_black (rb_tree_parent);
+ rb_set_black (rb_tree_other->rb_right);
+ __rb_rotate_left (rb_tree_parent, rb_tree_root);
+ rb_tree_node = rb_tree_root->rb_node;
+ break;
+ }
+ }
+ else
+ {
+ rb_tree_other = rb_tree_parent->rb_left;
+ if (rb_is_red (rb_tree_other))
+ {
+ rb_set_black (rb_tree_other);
+ rb_set_red (rb_tree_parent);
+ __rb_rotate_right (rb_tree_parent, rb_tree_root);
+ rb_tree_other = rb_tree_parent->rb_left;
+ }
+
+ if ((!rb_tree_other->rb_left
+ || rb_is_black (rb_tree_other->rb_left))
+ && (!rb_tree_other->rb_right
+ || rb_is_black (rb_tree_other->rb_right)))
+ {
+ rb_set_red (rb_tree_other);
+ rb_tree_node = rb_tree_parent;
+ rb_tree_parent = rb_parent (rb_tree_node);
+ }
+ else
+ {
+ if (!rb_tree_other->rb_left
+ || rb_is_black (rb_tree_other->rb_left))
+ {
+ rb_set_black (rb_tree_other->rb_right);
+ rb_set_red (rb_tree_other);
+ __rb_rotate_left (rb_tree_other, rb_tree_root);
+ rb_tree_other = rb_tree_parent->rb_left;
+ }
+
+ rb_set_color (rb_tree_other, rb_color (rb_tree_parent));
+ rb_set_black (rb_tree_parent);
+ rb_set_black (rb_tree_other->rb_left);
+ __rb_rotate_right (rb_tree_parent, rb_tree_root);
+ rb_tree_node = rb_tree_root->rb_node;
+ break;
+ }
+ }
+ }
+
+ if (rb_tree_node)
+ {
+ rb_set_black (rb_tree_node);
+ }
+}
+
+void
+rb_insert_color (struct rb_node *rb_tree_node, struct rb_root *rb_tree_root)
+{
+ struct rb_node *rb_tree_parent, *rb_tree_gparent;
+
+ if (!rb_tree_node || !rb_tree_root)
+ return;
+
+ while ((rb_tree_parent = rb_parent (rb_tree_node))
+ && rb_is_red (rb_tree_parent))
+ {
+ rb_tree_gparent = rb_parent (rb_tree_parent);
+
+ if (rb_tree_parent == rb_tree_gparent->rb_left)
+ {
+ {
+ register struct rb_node *rb_tree_uncle =
+ rb_tree_gparent->rb_right;
+ if (rb_tree_uncle && rb_is_red (rb_tree_uncle))
+ {
+ rb_set_black (rb_tree_uncle);
+ rb_set_black (rb_tree_parent);
+ rb_set_red (rb_tree_gparent);
+ rb_tree_node = rb_tree_gparent;
+ continue;
+ }
+ }
+
+ if (rb_tree_parent->rb_right == rb_tree_node)
+ {
+ register struct rb_node *rb_tree_tmp;
+ __rb_rotate_left (rb_tree_parent, rb_tree_root);
+ rb_tree_tmp = rb_tree_parent;
+ rb_tree_parent = rb_tree_node;
+ rb_tree_node = rb_tree_tmp;
+ }
+
+ rb_set_black (rb_tree_parent);
+ rb_set_red (rb_tree_gparent);
+ __rb_rotate_right (rb_tree_gparent, rb_tree_root);
+ }
+ else
+ {
+ {
+ register struct rb_node *rb_tree_uncle = rb_tree_gparent->rb_left;
+ if (rb_tree_uncle && rb_is_red (rb_tree_uncle))
+ {
+ rb_set_black (rb_tree_uncle);
+ rb_set_black (rb_tree_parent);
+ rb_set_red (rb_tree_gparent);
+ rb_tree_node = rb_tree_gparent;
+ continue;
+ }
+ }
+
+ if (rb_tree_parent->rb_left == rb_tree_node)
+ {
+ register struct rb_node *rb_tree_tmp;
+ __rb_rotate_right (rb_tree_parent, rb_tree_root);
+ rb_tree_tmp = rb_tree_parent;
+ rb_tree_parent = rb_tree_node;
+ rb_tree_node = rb_tree_tmp;
+ }
+
+ rb_set_black (rb_tree_parent);
+ rb_set_red (rb_tree_gparent);
+ __rb_rotate_left (rb_tree_gparent, rb_tree_root);
+ }
+ }
+
+ rb_set_black (rb_tree_root->rb_node);
+}
+
+void
+rb_erase (struct rb_node *node, struct rb_root *root)
+{
+ struct rb_node *child, *parent;
+ int color;
+
+ if (!node || !root)
+ return;
+
+ if (!node->rb_left)
+ {
+ child = node->rb_right;
+ }
+ else if (!node->rb_right)
+ {
+ child = node->rb_left;
+ }
+ else
+ {
+ struct rb_node *old = node, *left;
+
+ node = node->rb_right;
+ while ((left = node->rb_left) != NULL)
+ {
+ node = left;
+ }
+
+ if (rb_parent (old))
+ {
+ if (rb_parent (old)->rb_left == old)
+ {
+ rb_parent (old)->rb_left = node;
+ }
+ else
+ {
+ rb_parent (old)->rb_right = node;
+ }
+ }
+ else
+ {
+ root->rb_node = node;
+ }
+
+ child = node->rb_right;
+ parent = rb_parent (node);
+ color = rb_color (node);
+
+ if (parent == old)
+ {
+ parent = node;
+ }
+ else
+ {
+ if (child)
+ {
+ rb_set_parent (child, parent);
+ }
+
+ parent->rb_left = child;
+
+ node->rb_right = old->rb_right;
+ rb_set_parent (old->rb_right, node);
+ }
+
+ node->rb_parent_color = old->rb_parent_color;
+ node->rb_left = old->rb_left;
+ rb_set_parent (old->rb_left, node);
+
+ goto color;
+ }
+
+ parent = rb_parent (node);
+ color = rb_color (node);
+
+ if (child)
+ {
+ rb_set_parent (child, parent);
+ }
+
+ if (parent)
+ {
+ if (parent->rb_left == node)
+ {
+ parent->rb_left = child;
+ }
+ else
+ {
+ parent->rb_right = child;
+ }
+ }
+ else
+ {
+ root->rb_node = child;
+ }
+
+color:
+ if (color == RB_BLACK)
+ {
+ __rb_erase_color (child, parent, root);
+ }
+}
+
+struct rb_node *
+rb_next (const struct rb_node *node)
+{
+ struct rb_node *parent;
+
+ if (!node)
+ return NULL;
+
+ if (rb_parent (node) == node)
+ {
+ return NULL;
+ }
+
+ if (node->rb_right)
+ {
+ node = node->rb_right;
+ while (node->rb_left)
+ {
+ node = node->rb_left;
+ }
+
+ return (struct rb_node *) node;
+ }
+
+ while ((parent = rb_parent (node)) && (node == parent->rb_right))
+ {
+ node = parent;
+ }
+
+ return parent;
+}
diff --git a/stacks/lwip_stack/lwip_src/common/rb_tree.h b/stacks/lwip_stack/lwip_src/common/rb_tree.h
new file mode 100644
index 0000000..87174fa
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/rb_tree.h
@@ -0,0 +1,112 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _UNX_RBTREE_H
+#define _UNX_RBTREE_H
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+#include <stdint.h>
+#include "types.h"
+#include "common_pal_bitwide_adjust.h"
+
+#define rb_parent(a) ((struct rb_node *)((a)->rb_parent_color & ~3))
+#define rb_color(a) ((a)->rb_parent_color & 1)
+
+struct rb_node
+{
+ union
+ {
+ unsigned long rb_parent_color;
+ u64 rb_parent_color_a;
+ };
+
+#define RB_RED 0
+#define RB_BLACK 1
+ union
+ {
+ struct rb_node *rb_right;
+ u64 rb_right_a;
+ };
+
+ union
+ {
+ struct rb_node *rb_left;
+ u64 rb_left_a;
+ };
+};
+
+#define rb_set_red(c) do { (c)->rb_parent_color &= ~1; } while (0)
+#define rb_set_black(c) do { (c)->rb_parent_color |= 1; } while (0)
+
+/* The alignment might seem pointless, but allegedly CRIS needs it */
+
+struct rb_root
+{
+ union
+ {
+ struct rb_node *rb_node;
+ u64 rb_node_a;
+ };
+};
+
+#define rb_is_red(e) (!rb_color(e))
+#define rb_is_black(e) rb_color(e)
+
+static inline void
+rb_set_color (struct rb_node *rb1, int color2)
+{
+ rb1->rb_parent_color = (rb1->rb_parent_color & ~1) | color2;
+}
+
+static inline void
+rb_set_parent (struct rb_node *rb1, struct rb_node *pa)
+{
+ rb1->rb_parent_color = (rb1->rb_parent_color & 3) | (unsigned long) pa;
+}
+
+#define RB_ROOT (struct rb_root) { NULL, }
+
+extern void rb_erase (struct rb_node *, struct rb_root *);
+
+extern void rb_insert_color (struct rb_node *, struct rb_root *);
+
+extern struct rb_node *rb_next (const struct rb_node *);
+
+#define rb_entry(ptr, type, member) container_of(ptr, type, member)
+
+#define RB_EMPTY_ROOT(root1) ((root1)->rb_node == NULL)
+#define RB_CLEAR_NODE(node2) (rb_set_parent(node2, node2))
+#define RB_EMPTY_NODE(node1) (rb_parent(node1) == node1)
+
+static inline void
+rb_link_node (struct rb_node *node1, struct rb_node *parent1,
+ struct rb_node **rb_link1)
+{
+ node1->rb_left = node1->rb_right = NULL;
+ node1->rb_parent_color = (unsigned long) parent1;
+ *rb_link1 = node1;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#endif /* _UNX_RBTREE_H */
diff --git a/stacks/lwip_stack/lwip_src/common/spl_def.h b/stacks/lwip_stack/lwip_src/common/spl_def.h
new file mode 100644
index 0000000..b62d179
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/spl_def.h
@@ -0,0 +1,142 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_DEF_H__
+#define __STACKX_DEF_H__
+
+/* arch.h might define NULL already */
+//#include "lwip/arch.h"
+#include "spl_opt.h"
+#include "stackx_types.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define STACKX_MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define STACKX_MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+/* Endianess-optimized shifting of two u8_t to create one u16_t */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define STACKX_MAKE_U16(a, b) ((a << 8) | b)
+#else
+#define STACKX_MAKE_U16(a, b) ((b << 8) | a)
+#endif
+
+#ifndef STACKX_PLATFORM_BYTESWAP
+#define STACKX_PLATFORM_BYTESWAP 0
+#endif
+
+#ifndef STACKX_PREFIX_BYTEORDER_FUNCS
+
+/* workaround for naming collisions on some platforms */
+
+#ifdef spl_htons
+#undef spl_htons
+#endif /* htons */
+#ifdef spl_htonl
+#undef spl_htonl
+#endif /* spl_htonl */
+#ifdef spl_ntohs
+#undef spl_ntohs
+#endif /* spl_ntohs */
+#ifdef spl_ntohl
+#undef spl_ntohl
+#endif /* spl_ntohl */
+
+#define spl_htons(x) stackx_htons(x)
+#define spl_ntohs(x) stackx_ntohs(x)
+#define spl_htonl(x) stackx_htonl(x)
+#define spl_ntohl(x) stackx_ntohl(x)
+#endif /* STACKX_PREFIX_BYTEORDER_FUNCS */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define stackx_htons(x) (x)
+#define stackx_ntohs(x) (x)
+#define stackx_htonl(x) (x)
+#define stackx_ntohl(x) (x)
+#define SPL_PP_HTONS(x) (x)
+#define SPL_PP_NTOHS(x) (x)
+#define SPL_PP_HTONL(x) (x)
+#define SPL_PP_NTOHL(x) (x)
+#else /* BYTE_ORDER != BIG_ENDIAN */
+#if STACKX_PLATFORM_BYTESWAP
+#define stackx_htons(x) STACKX_PLATFORM_HTONS(x)
+#define stackx_ntohs(x) STACKX_PLATFORM_HTONS(x)
+#define stackx_htonl(x) STACKX_PLATFORM_HTONL(x)
+#define stackx_ntohl(x) STACKX_PLATFORM_HTONL(x)
+#else /* STACKX_PLATFORM_BYTESWAP */
+ /**
+ * Convert an u16_t from host- to network byte order.
+ *
+ * @param n u16_t in host byte order
+ * @return n in network byte order
+ */
+static inline u16_t
+stackx_htons (u16_t x)
+{
+ return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);
+}
+
+static inline u16_t
+stackx_ntohs (u16_t x)
+{
+ return stackx_htons (x);
+}
+
+ /**
+ * Convert an u32_t from host- to network byte order.
+ *
+ * @param n u32_t in host byte order
+ * @return n in network byte order
+ */
+static inline u32_t
+stackx_htonl (u32_t x)
+{
+ return ((x & 0xff) << 24) |
+ ((x & 0xff00) << 8) |
+ ((x & 0xff0000UL) >> 8) | ((x & 0xff000000UL) >> 24);
+}
+
+static inline u32_t
+stackx_ntohl (u32_t x)
+{
+ return stackx_htonl (x);
+}
+#endif /* STACKX_PLATFORM_BYTESWAP */
+
+/* These macros should be calculated by the preprocessor and are used
+ with compile-time constants only (so that there is no little-endian
+ overhead at runtime). */
+#define SPL_PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define SPL_PP_NTOHS(x) SPL_PP_HTONS(x)
+#define SPL_PP_HTONL(x) ((((x) & 0xff) << 24) | \
+ (((x) & 0xff00) << 8) | \
+ (((x) & 0xff0000UL) >> 8) | \
+ (((x) & 0xff000000UL) >> 24))
+#define SPL_PP_NTOHL(x) SPL_PP_HTONL(x)
+
+#endif /* BYTE_ORDER == BIG_ENDIAN */
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __STACKX_DEF_H__ */
diff --git a/stacks/lwip_stack/lwip_src/common/spl_opt.h b/stacks/lwip_stack/lwip_src/common/spl_opt.h
new file mode 100644
index 0000000..98e6466
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/spl_opt.h
@@ -0,0 +1,329 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_OPT_H__
+#define __STACKX_OPT_H__
+
+#include "stackxopts.h"
+#include "stackx_debug.h"
+#include "compiling_check.h"
+
+#define PBUF_VLAN_HLEN 0
+
+//#define SIZEOF_ETH_HDR (14)
+
+#ifndef STACKX_NETIF_API
+#define STACKX_NETIF_API 1
+#endif
+
+/*
+ ------------------------------------
+ ---------- Thread options ----------
+ ------------------------------------
+ */
+
+#define PTIMER_THREAD_NAME "ptimer_thread"
+
+/**
+ * TCPIP_THREAD_NAME: The name assigned to the main tcpip thread.
+ */
+#ifndef TCPIP_THREAD_NAME
+#define TCPIP_THREAD_NAME "spl_tcpip_thread"
+#endif
+
+#ifndef TCPIP_THREAD_STACKSIZE
+#define TCPIP_THREAD_STACKSIZE 0
+#endif
+
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
+
+#ifndef INT_64_MAX
+#define INT_64_MAX 9223372036854775807
+#endif
+
+#ifndef RECV_BUFSIZE_DEFAULT
+#define RECV_BUFSIZE_DEFAULT INT_MAX
+#endif
+
+/*
+ ----------------------------------------
+ ---------- Statistics options ----------
+ ----------------------------------------
+ */
+
+/*
+ ---------------------------------------
+ ---------- Debugging options ----------
+ ---------------------------------------
+ */
+
+#ifndef STACKX_DBG_TYPES_ON
+#define STACKX_DBG_TYPES_ON STACKX_DBG_ON //ON
+#endif
+
+#ifndef INTERRUPT_DEBUG
+#define INTERRUPT_DEBUG STACKX_DBG_ON //ON
+#endif
+
+#ifndef TESTSOCKET_DEBUG
+#define TESTSOCKET_DEBUG STACKX_DBG_ON //ON
+#endif
+
+#ifndef ETHARP_DEBUG
+#define ETHARP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef NETIF_DEBUG
+#define NETIF_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef PBUF_DEBUG
+#define PBUF_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef API_LIB_DEBUG
+#define API_LIB_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef API_MSG_DEBUG
+#define API_MSG_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef SOCKETS_DEBUG
+#define SOCKETS_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef NS_EPOLL_DBG
+#define NS_EPOLL_DBG STACKX_DBG_ON
+#endif
+
+#ifndef ICMP_DEBUG
+#define ICMP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef IGMP_DEBUG
+#define IGMP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef INET_DEBUG
+#define INET_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef IP_DEBUG
+#define IP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef IP_REASS_DEBUG
+#define IP_REASS_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef RAW_DEBUG
+#define RAW_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef MEMP_DEBUG
+#define MEMP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef SYS_DEBUG
+#define SYS_DEBUG STACKX_DBG_OFF
+#endif
+
+#ifndef TIMERS_DEBUG
+#define TIMERS_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_DEBUG
+#define TCP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_TEST_DEBUG
+#define TCP_TEST_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_INPUT_DEBUG
+#define TCP_INPUT_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_RTO_DEBUG
+#define TCP_RTO_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_FR_DEBUG
+#define TCP_FR_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_FLOW_CTL_DEBUG
+#define TCP_FLOW_CTL_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_CWND_DEBUG
+#define TCP_CWND_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_WND_DEBUG
+#define TCP_WND_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_OUTPUT_DEBUG
+#define TCP_OUTPUT_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCP_RST_DEBUG
+#define TCP_RST_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef UDP_DEBUG
+#define UDP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef TCPIP_DEBUG
+#define TCPIP_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef NEW_RING_DEBUG
+#define NEW_RING_DEBUG STACKX_DBG_ON
+#endif
+
+#ifndef PACKET_DISPATCH
+#define PACKET_DISPATCH 1
+#endif
+
+#ifndef NETSTAT_SWITCH
+#define NETSTAT_SWITCH 1
+#endif
+
+#ifndef DISTRIBUTOR_DEBUG
+
+#define DISTRIBUTOR_DEBUG STACKX_DBG_ON
+#endif
+#define PBUF_REF_DEBUG STACKX_DBG_ON
+
+#ifndef CONTEXT_TIMER_DEBUG
+#define CONTEXT_TIMER_DEBUG STACKX_DBG_OFF
+#endif
+
+#if (DISTRIBUTOR_DEBUG == STACKX_DBG_ON)
+#define PD_DISTRIBUTOR_DEBUG
+
+#define DISTRIBUTOR_SINGLE
+#ifdef DISTRIBUTOR_SINGLE
+
+#ifndef __STACKX_DEBUG_H__
+#define STACKX_DBG_OFF 0x80U
+#define STACKX_DBG_ON 0x00U
+#endif
+
+#ifndef ETHARP_DEBUG
+#define ETHARP_DEBUG STACKX_DBG_ON
+#endif
+#ifndef NETIF_DEBUG
+#define NETIF_DEBUG STACKX_DBG_ON
+#endif
+#ifndef PBUF_DEBUG
+#define PBUF_DEBUG STACKX_DBG_ON
+#endif
+#ifndef API_LIB_DEBUG
+#define API_LIB_DEBUG STACKX_DBG_ON
+#endif
+#ifndef API_MSG_DEBUG
+#define API_MSG_DEBUG STACKX_DBG_ON
+#endif
+#ifndef ICMP_DEBUG
+#define ICMP_DEBUG STACKX_DBG_ON
+#endif
+#ifndef IGMP_DEBUG
+#define IGMP_DEBUG STACKX_DBG_ON
+#endif
+#ifndef INET_DEBUG
+#define INET_DEBUG STACKX_DBG_ON
+#endif
+#ifndef IP_DEBUG
+#define IP_DEBUG STACKX_DBG_ON
+#endif
+#ifndef IP_REASS_DEBUG
+#define IP_REASS_DEBUG STACKX_DBG_ON
+#endif
+#ifndef RAW_DEBUG
+#define RAW_DEBUG STACKX_DBG_ON
+#endif
+#ifndef MEMP_DEBUG
+#define MEMP_DEBUG STACKX_DBG_ON
+#endif
+#ifndef SYS_DEBUG
+#define SYS_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TIMERS_DEBUG
+#define TIMERS_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_DEBUG
+#define TCP_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_TEST_DEBUG
+#define TCP_TEST_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_INPUT_DEBUG
+#define TCP_INPUT_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_FR_DEBUG
+#define TCP_FR_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_RTO_DEBUG
+#define TCP_RTO_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_CWND_DEBUG
+#define TCP_CWND_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_WND_DEBUG
+#define TCP_WND_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_OUTPUT_DEBUG
+#define TCP_OUTPUT_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCP_RST_DEBUG
+#define TCP_RST_DEBUG STACKX_DBG_ON
+#endif
+#ifndef UDP_DEBUG
+#define UDP_DEBUG STACKX_DBG_ON
+#endif
+#ifndef TCPIP_DEBUG
+#define TCPIP_DEBUG STACKX_DBG_ON
+#endif
+
+#define SC_DPDK_INFO STACKX_DBG_ON
+#define SOCK_INFO STACKX_DBG_ON
+#ifndef STACKX_DBG_OFF
+#define STACKX_DBG_OFF 0x00U
+#endif
+
+#ifndef NS_EPOLL_DBG
+#define NS_EPOLL_DBG STACKX_DBG_ON
+#endif
+
+#ifndef DFX_DBG
+#define DFX_DBG STACKX_DBG_ON
+#endif
+
+#endif
+#endif /* DISTRIBUTOR_DEBUG */
+
+#ifndef STACKX_FLOW_CTL
+#define STACKX_FLOW_CTL 0
+#endif
+
+#endif /* __STACKX_OPT_H__ */
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_app_res.c b/stacks/lwip_stack/lwip_src/common/stackx_app_res.c
new file mode 100644
index 0000000..5c30271
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_app_res.c
@@ -0,0 +1,972 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "stackx_app_res.h"
+#include "nstack_securec.h"
+#include "common_pal_bitwide_adjust.h"
+#include "nstack_log.h"
+#include "stackx_common.h"
+#include "nsfw_maintain_api.h"
+#include "stackx_tx_box.h"
+#include "nsfw_msg_api.h"
+#include "nsfw_recycle_api.h"
+#include "common_mem_mbuf.h"
+#include "stackx_pbuf.h"
+#include "nsfw_mt_config.h"
+#include "nsfw_mem_api.h"
+#include "spl_opt.h"
+#define SPL_MAX_MSG_NUM (MBOX_RING_SIZE*8*MAX_THREAD_NUM)
+
+spl_app_res_group *g_spl_app_res_group = NULL;
+
+spl_app_res_group_array *g_res_group_array = NULL;
+
+#ifdef SYS_MEM_RES_STAT
+mpool_handle g_app_tx_pool[SBR_TX_POOL_NUM];
+#endif
+
+/***************************************************
+* description:
+***************************************************/
+int
+spl_init_group_array ()
+{
+ g_res_group_array =
+ (spl_app_res_group_array *) sbr_create_mzone (SPL_RES_GROUP_ARRAY,
+ sizeof
+ (spl_app_res_group_array));
+ if (!g_res_group_array)
+ {
+ NSPOL_LOGERR ("create g_res_group_array failed");
+ return -1;
+ }
+
+ u32 i;
+ for (i = 0; i < SBR_TX_POOL_NUM; ++i)
+ {
+ g_res_group_array->pid_array[i] = 0;
+ }
+
+ for (i = 0; i < MAX_THREAD_NUM; ++i)
+ {
+ g_res_group_array->res_group[i] = NULL;
+ }
+
+ g_res_group_array->thread_num = 0;
+ return 0;
+}
+
+/***************************************************
+* description:
+***************************************************/
+int
+sbr_attach_group_array ()
+{
+ g_res_group_array =
+ (spl_app_res_group_array *) sbr_lookup_mzone (SPL_RES_GROUP_ARRAY);
+ if (!g_res_group_array)
+ {
+ NSPOL_LOGERR ("attach g_res_group_array failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/***************************************************
+* description:
+***************************************************/
+int
+spl_add_instance_res_group (u32 thread_index, spl_app_res_group * group)
+{
+ if (thread_index >= MAX_THREAD_NUM)
+ {
+ NSPOL_LOGERR
+ ("thread_index >= MAX_THREAD_NUM]thread_index=%u, MAX_THREAD_NUM=%u",
+ thread_index, MAX_THREAD_NUM);
+ return -1;
+ }
+
+ if (g_res_group_array->res_group[thread_index] != NULL)
+ {
+ NSPOL_LOGERR
+ ("g_res_group_array in thread_index is not NULL, this can not happen");
+ return -1;
+ }
+
+ g_res_group_array->res_group[thread_index] = group;
+ __sync_add_and_fetch (&g_res_group_array->thread_num, 1);
+ return 0;
+}
+
+/***************************************************
+* description:
+***************************************************/
+int
+spl_add_mbox (mring_handle mbox_array[], u32 array_size)
+{
+ if (array_size != SPL_MSG_BOX_NUM)
+ {
+ NSPOL_LOGERR ("array_size must be %u, but not", SPL_MSG_BOX_NUM);
+ return -1;
+ }
+
+ u32 i;
+ for (i = 0; i < array_size; ++i)
+ {
+ g_spl_app_res_group->mbox_array[i] = mbox_array[i];
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : spl_create_group
+* Description : create group
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+spl_app_res_group *
+spl_create_group ()
+{
+ spl_app_res_group *group =
+ (spl_app_res_group *) sbr_create_mzone (SPL_APP_RES_GROUP_NAME,
+ sizeof (spl_app_res_group));
+ if (!group)
+ {
+ NSPOL_LOGERR ("Create app_res_group zone fail]name=%s, size=%u",
+ SPL_APP_RES_GROUP_NAME, sizeof (spl_app_res_group));
+ return NULL;
+ }
+
+ group->msg_pool = NULL;
+ group->conn_pool = NULL;
+ group->conn_array = NULL;
+ group->recv_ring_pool = NULL;
+
+ u32 i;
+ for (i = 0; i < SBR_TX_POOL_NUM; ++i)
+ {
+ group->tx_pool_array[i] = NULL;
+ }
+
+ for (i = 0; i < SPL_MSG_BOX_NUM; ++i)
+ {
+ group->mbox_array[i] = NULL;
+ }
+
+ group->extend_member_bit = 0;
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "Create app_res_group zone ok]name=%s, size=%u",
+ SPL_APP_RES_GROUP_NAME, sizeof (spl_app_res_group));
+ MEM_STAT (SPL_APP_RES, SPL_APP_RES_GROUP_NAME, NSFW_SHMEM,
+ sizeof (spl_app_res_group));
+ return group;
+}
+
+/*****************************************************************************
+* Prototype : _spl_create_ring_pool
+* Description : create ring pool
+* Input : char* pool_name
+* char* array_name
+* nsfw_mpool_type type
+* Output : None
+* Return Value : static inline mring_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline mring_handle
+_spl_create_ring_pool (char *pool_name, char *array_name,
+ nsfw_mpool_type type, u32 num, u32 ring_size)
+{
+ mring_handle pool = sbr_create_ring (pool_name, num - 1);
+
+ if (!pool)
+ {
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "Create ring pool ok]name=%s, num=%u, size=%d",
+ pool_name, num, nsfw_mem_get_len (pool, NSFW_MEM_RING));
+ MEM_STAT (SPL_APP_RES, pool_name, NSFW_SHMEM,
+ nsfw_mem_get_len (pool, NSFW_MEM_RING));
+
+ mring_handle *array = malloc (num * sizeof (mring_handle));
+ if (!array)
+ {
+ NSPOL_LOGERR ("malloc fail]size=%u", num * sizeof (mring_handle));
+ return NULL;
+ }
+
+ if (sbr_create_multi_ring (array_name, ring_size - 1, num,
+ array, type) != 0)
+ {
+ free (array);
+ return NULL;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "Create multi rings ok]name=%s, ring_size=%u, ring_num=%u, total_mem=%d",
+ array_name, ring_size, num,
+ (nsfw_mem_get_len (array[0], NSFW_MEM_RING) * num));
+ MEM_STAT (SPL_APP_RES, array_name, NSFW_SHMEM,
+ nsfw_mem_get_len (array[0], NSFW_MEM_RING) * num);
+
+ unsigned int i = 0;
+ while (i < num)
+ {
+ if (nsfw_mem_ring_enqueue (pool, (void *) array[i]) != 1)
+ {
+ NSPOL_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ free (array);
+ return NULL;
+ }
+
+ i++;
+ }
+
+ free (array);
+ return pool;
+}
+
+/*****************************************************************************
+* Prototype : spl_create_ring_pool
+* Description : create ring pool
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+spl_create_ring_pool (spl_app_res_group * group)
+{
+ group->recv_ring_pool =
+ _spl_create_ring_pool (SPL_RECV_RING_POOL_NAME, SPL_RECV_RING_ARRAY_NAME,
+ NSFW_MRING_SPSC, CUR_CFG_SOCKET_NUM,
+ SPL_MAX_RING_SIZE);
+ if (!group->recv_ring_pool)
+ {
+ NSPOL_LOGERR ("Create recv ring pool failed");
+ return -1;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "Create recv ring pool ok]name=%s",
+ SPL_RECV_RING_POOL_NAME);
+ return 0;
+}
+
+int
+spl_force_netconn_free (void *data)
+{
+ spl_netconn_t *conn = (spl_netconn_t *) data;
+ if (TRUE == conn->res_chk.alloc_flag)
+ {
+ if (NULL != conn->recycle.accept_from)
+ {
+ return FALSE;
+ }
+
+ if (TRUE != nsfw_pidinfo_empty (&conn->recycle.pid_info))
+ {
+ return FALSE;
+ }
+ }
+ ss_reset_conn (conn);
+ (void) res_free (&conn->res_chk);
+
+ if (nsfw_mem_ring_enqueue (ss_get_conn_pool (conn), (void *) conn) != 1)
+ {
+ NSSBR_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ }
+ NSFW_LOGINF ("force free conn]conn=%p", conn);
+ return TRUE;
+}
+
+/*****************************************************************************
+* Prototype : spl_create_netconn_pool
+* Description : create netconn pool
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+spl_create_netconn_pool (spl_app_res_group * group)
+{
+ spl_netconn_t **conn_array =
+ (spl_netconn_t **) sbr_create_mzone (SPL_CONN_ARRAY_NAME,
+ sizeof (spl_netconn_t *) *
+ CUR_CFG_SOCKET_NUM);
+
+ if (!conn_array)
+ {
+ return -1;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "Create connn_array zone ok]name=%s, size=%zu",
+ SPL_CONN_ARRAY_NAME,
+ sizeof (spl_netconn_t *) * CUR_CFG_SOCKET_NUM);
+ mring_handle pool =
+ sbr_create_pool (SPL_CONN_POOL_NAME, CUR_CFG_SOCKET_NUM - 1,
+ SBR_FD_NETCONN_SIZE);
+
+ if (!pool)
+ {
+ return -1;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "Create conn_pool ok]name=%s, num=%u, total_mem=%d",
+ SPL_CONN_POOL_NAME, CUR_CFG_SOCKET_NUM,
+ nsfw_mem_get_len (pool, NSFW_MEM_SPOOL));
+
+ sbr_recycle_group *recycle_group =
+ (sbr_recycle_group *) sbr_create_mzone (SPL_RECYCLE_GROUP,
+ sizeof (sbr_recycle_group));
+ if (!recycle_group)
+ {
+ return -1;
+ }
+
+ NSPOL_LOGINF (SC_DPDK_INFO, "Create recycle_group zone ok]name=%s, size=%u",
+ SPL_RECYCLE_GROUP, sizeof (sbr_recycle_group));
+
+ recycle_group->conn_array = conn_array;
+ recycle_group->conn_num = spl_get_conn_num ();
+ recycle_group->conn_pool = pool;
+ recycle_group->extend_member_bit = 0;
+ recycle_group->msg_pool = group->msg_pool;
+
+ spl_netconn_t *conn = NULL;
+ unsigned int i = 0;
+ while (i < CUR_CFG_SOCKET_NUM)
+ {
+ if (nsfw_mem_ring_dequeue (pool, (void **) &conn) != 1)
+ {
+ NSPOL_LOGERR ("nsfw_mem_ring_dequeue failed,this can not happen");
+ return -1;
+ }
+
+ ss_reset_conn (conn);
+ conn->recycle.group = recycle_group;
+
+ if (nsfw_mem_ring_dequeue (group->recv_ring_pool, &conn->recv_ring) !=
+ 1)
+ {
+ NSPOL_LOGERR ("nsfw_mem_ring_dequeue failed,this can not happen");
+ return -1;
+ }
+
+ conn_array[i] = conn;
+
+ if (nsfw_mem_ring_enqueue (pool, (void *) conn) != 1)
+ {
+ NSPOL_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ return -1;
+ }
+
+ i++;
+ }
+
+ group->conn_pool = pool;
+ group->conn_array = conn_array;
+
+ MEM_STAT (SPL_APP_RES, SPL_RECYCLE_GROUP, NSFW_SHMEM,
+ sizeof (sbr_recycle_group));
+ MEM_STAT (SPL_APP_RES, SPL_CONN_ARRAY_NAME, NSFW_SHMEM,
+ sizeof (spl_netconn_t *) * CUR_CFG_SOCKET_NUM);
+ MEM_STAT (SPL_APP_RES, SPL_CONN_POOL_NAME, NSFW_SHMEM,
+ nsfw_mem_get_len (group->conn_pool, NSFW_MEM_SPOOL));
+ return 0;
+}
+
+int
+spl_force_msg_free (void *data)
+{
+ data_com_msg *m = (data_com_msg *) data;
+ if (NULL == m)
+ {
+ return FALSE;
+ }
+
+ NSFW_LOGINF ("force free msg]msg=%p", data);
+ (void) res_free (&m->param.res_chk);
+ m->param.recycle_pid = 0;
+ if (nsfw_mem_ring_enqueue (m->param.msg_from, (void *) m) != 1)
+ {
+ NSFW_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ }
+ return TRUE;
+}
+
+/*****************************************************************************
+* Prototype : spl_create_msg_pool
+* Description : create msg pool
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+spl_create_msg_pool (spl_app_res_group * group)
+{
+ mring_handle pool =
+ sbr_create_pool (SPL_MSG_POOL_NAME, SPL_MAX_MSG_NUM - 1, MAX_MSG_SIZE);
+
+ if (!pool)
+ {
+ return -1;
+ }
+
+ data_com_msg *m = NULL;
+ unsigned int i = 0;
+ while (i < SPL_MAX_MSG_NUM)
+ {
+ if (nsfw_mem_ring_dequeue (pool, (void **) &m) != 1)
+ {
+ NSPOL_LOGERR ("nsfw_mem_ring_dequeue failed,this can not happen");
+ return -1;
+ }
+
+ m->param.msg_from = pool;
+ m->param.recycle_pid = 0;
+ sys_sem_init (&m->param.op_completed);
+
+ if (nsfw_mem_ring_enqueue (pool, (void *) m) != 1)
+ {
+ NSPOL_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ return -1;
+ }
+
+ i++;
+ }
+
+ group->msg_pool = pool;
+
+ NSPOL_LOGINF (SC_DPDK_INFO,
+ "Create app msg pool ok]name=%s, num=%u, size=%u, total_mem=%d",
+ SPL_MSG_POOL_NAME, SPL_MAX_MSG_NUM, MAX_MSG_SIZE,
+ nsfw_mem_get_len (group->msg_pool, NSFW_MEM_SPOOL));
+ MEM_STAT (SPL_APP_RES, SPL_MSG_POOL_NAME, NSFW_SHMEM,
+ nsfw_mem_get_len (group->msg_pool, NSFW_MEM_SPOOL));
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : spl_regist_recycle
+* Description : regist recycle
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+spl_regist_recycle (spl_app_res_group * group)
+{
+ void *ret =
+ nsfw_recycle_reg_obj (NSFW_REC_PRO_DEFAULT, NSFW_REC_SBR_SOCKET, NULL);
+
+ if (!ret)
+ {
+ NSSBR_LOGERR ("failed");
+ return -1;
+ }
+
+ if (NULL == group)
+ {
+ NSSBR_LOGERR ("g_spl_app_res_group null");
+ return -1;
+ }
+
+ nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_SPOOL, 90, 3, 16,
+ CUR_CFG_SOCKET_NUM / 128, CUR_CFG_SOCKET_NUM - 1,
+ SBR_FD_NETCONN_SIZE,
+ offsetof (spl_netconn_t, res_chk),
+ (void *) group->conn_pool,
+ (void *) group->conn_pool,
+ spl_force_netconn_free
+ };
+
+ (void) nsfw_res_mgr_reg (&scn_cfg);
+
+ nsfw_res_scn_cfg scn_cfg_msg = { NSFW_RES_SCAN_SPOOL, 60, 3, 16,
+ SPL_MAX_MSG_NUM / 128, SPL_MAX_MSG_NUM,
+ MAX_MSG_SIZE,
+ offsetof (data_com_msg, param.res_chk),
+ (void *) group->msg_pool,
+ (void *) group->msg_pool,
+ spl_force_msg_free
+ };
+ (void) nsfw_res_mgr_reg (&scn_cfg_msg);
+
+ return 0;
+}
+
+void
+spl_reg_tx_pool_mgr (mpool_handle pool_array[], u32 num)
+{
+ u32 loop;
+ for (loop = 0; loop < num; loop++)
+ {
+ (void) spl_reg_res_txrx_mgr (pool_array[loop]); // will only return 0, no need to check return value
+ }
+
+ return;
+}
+
+/*****************************************************************************
+* Prototype : sbr_create_tx_pool
+* Description : create tx pool,spl call this fun
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+spl_create_tx_pool (mpool_handle pool_array[], u32 array_size)
+{
+ data_com_msg *tx_msg_array =
+ (data_com_msg *) sbr_create_mzone (SBR_TX_MSG_ARRAY_NAME,
+ (size_t) sizeof (data_com_msg) *
+ SBR_TX_MSG_NUM);
+
+ if (!tx_msg_array)
+ {
+ NSSBR_LOGERR ("Create tx_msg_array zone fail]name=%s, num=%u, size=%u",
+ SBR_TX_MSG_ARRAY_NAME, SBR_TX_MSG_NUM,
+ (size_t) sizeof (data_com_msg) * SBR_TX_MSG_NUM);
+ return -1;
+ }
+
+ MEM_STAT (SBR_TX_POOL_NAME, SBR_TX_MSG_ARRAY_NAME, NSFW_SHMEM,
+ (size_t) sizeof (data_com_msg) * SBR_TX_MSG_NUM);
+ NSSBR_LOGINF
+ ("Create tx_msg_array zone ok]name=%s, ptr=%p, num=%u, size=%u",
+ SBR_TX_MSG_ARRAY_NAME, tx_msg_array, SBR_TX_MSG_NUM,
+ sizeof (data_com_msg) * SBR_TX_MSG_NUM);
+
+ mpool_handle mp;
+ int ret;
+ char tx_pool_name[64];
+ u32 loop;
+ for (loop = 0; loop < array_size; loop++)
+ {
+ ret =
+ SPRINTF_S (tx_pool_name, sizeof (tx_pool_name), "%s_%d",
+ SBR_TX_POOL_NAME, loop);
+ if (-1 == ret)
+ {
+ NSSBR_LOGERR ("SPRINTF_S failed]ret=%d", ret);
+ return -1;
+ }
+
+ nsfw_mem_mbfpool pool_param;
+ if (STRCPY_S
+ (pool_param.stname.aname, NSFW_MEM_NAME_LENTH, tx_pool_name) != 0)
+ {
+ NSSBR_LOGERR ("STRCPY_S failed]name=%s", tx_pool_name);
+ return -1;
+ }
+
+ pool_param.isocket_id = -1;
+ pool_param.stname.entype = NSFW_SHMEM;
+ pool_param.enmptype = NSFW_MRING_MPMC;
+ pool_param.uscash_size = 0;
+ pool_param.uspriv_size = 0;
+ pool_param.usdata_room = TX_MBUF_MAX_LEN;
+ pool_param.usnum = SBR_TX_POOL_MBUF_NUM - 1;
+
+ mp = nsfw_mem_mbfmp_create (&pool_param);
+ if (!mp)
+ {
+ NSSBR_LOGERR ("Create tx_mbuf_pool fail]name=%s, num=%u, room=%u",
+ tx_pool_name, SBR_TX_POOL_MBUF_NUM,
+ pool_param.usdata_room);
+ return -1;
+ }
+ else
+ {
+ struct common_mem_mbuf *mbuf = NULL;
+ struct spl_pbuf *buf = NULL;
+ int i = 0;
+ while (i < (int) SBR_TX_POOL_MBUF_NUM)
+ {
+ mbuf = nsfw_mem_mbf_alloc (mp, NSFW_SHMEM);
+ if (!mbuf)
+ {
+ NSSBR_LOGERR
+ ("nsfw_mem_mbf_alloc failed,this can not happen");
+ return -1;
+ }
+
+ buf =
+ (struct spl_pbuf *) ((char *) mbuf +
+ sizeof (struct common_mem_mbuf));
+ int idx = loop * (int) SBR_TX_POOL_MBUF_NUM + i;
+ sys_sem_init (&tx_msg_array[idx].param.op_completed);
+ tx_msg_array[idx].param.msg_from = NULL;
+ buf->msg = (void *) &tx_msg_array[idx];
+ (void) res_free (&buf->res_chk); //no need to check return value, as it will do free operation depends on alloc_flag
+
+ if (nsfw_mem_mbf_free (mbuf, NSFW_SHMEM) < 0)
+ {
+ NSSBR_LOGERR
+ ("nsfw_mem_mbf_free failed,this can not happen");
+ return -1;
+ }
+
+ i++;
+ }
+
+ pool_array[loop] = mp;
+#ifdef SYS_MEM_RES_STAT
+ g_app_tx_pool[loop] = mp;
+#endif
+ }
+ }
+
+ spl_reg_tx_pool_mgr (pool_array, array_size);
+
+ NSSBR_LOGINF ("Create all tx_mbuf_pool ok]pool_num=%d, total_mem=%d",
+ array_size, nsfw_mem_get_len (pool_array[0],
+ NSFW_MEM_MBUF) * array_size);
+ MEM_STAT (SBR_TX_POOL_NAME, SBR_TX_POOL_NAME, NSFW_SHMEM,
+ nsfw_mem_get_len (pool_array[0], NSFW_MEM_MBUF) * array_size);
+ return 0;
+}
+
+spl_app_res_group *
+spl_create_res_group ()
+{
+ spl_app_res_group *group = spl_create_group ();
+ if (NULL == group)
+ {
+ NSPOL_LOGERR ("spl_create_group failed");
+ return NULL;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_group ok");
+
+ if (spl_create_ring_pool (group) != 0)
+ {
+ NSPOL_LOGERR ("spl_create_ring_pool failed");
+ return NULL;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_ring_pool ok");
+
+ if (spl_create_msg_pool (group) != 0)
+ {
+ NSPOL_LOGERR ("spl_create_msg_pool failed");
+ return NULL;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_msg_pool ok");
+
+ if (spl_create_netconn_pool (group) != 0)
+ {
+ NSPOL_LOGERR ("spl_create_netconn_pool failed");
+ return NULL;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_netconn_pool ok");
+
+ if (spl_regist_recycle (group) != 0)
+ {
+ NSPOL_LOGERR ("spl_regist_recycle failed");
+ return NULL;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "spl_regist_recycle ok");
+
+ if (spl_create_tx_pool (group->tx_pool_array, SBR_TX_POOL_NUM) != 0)
+ {
+ NSPOL_LOGERR ("spl_create_tx_pool failed");
+ return NULL;
+ }
+
+ NSPOL_LOGDBG (SC_DPDK_INFO, "spl_create_tx_pool ok");
+
+ return group;
+}
+
+/*****************************************************************************
+* Prototype : spl_init_app_res
+* Description : init app res
+* Input : None
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+spl_init_app_res ()
+{
+ g_spl_app_res_group = spl_create_res_group ();
+ if (NULL == g_spl_app_res_group)
+ {
+ NSPOL_LOGERR ("spl_create_group failed");
+ return -1;
+ }
+
+ return spl_add_instance_res_group (0, g_spl_app_res_group);
+}
+
+/*****************************************************************************
+* Prototype : spl_get_conn_array
+* Description : get conn array
+* Input : u32 pid
+* Output : None
+* Return Value : spl_netconn_t**
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+spl_netconn_t **
+spl_get_conn_array (u32 pid)
+{
+ return (spl_netconn_t **) ADDR_SHTOL (g_spl_app_res_group->conn_array);
+}
+
+/*****************************************************************************
+* Prototype : spl_get_conn_pool
+* Description : get conn pool
+* Input : None
+* Output : None
+* Return Value : mring_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+mring_handle
+spl_get_conn_pool ()
+{
+ return (mring_handle) ADDR_SHTOL (g_spl_app_res_group->conn_pool);
+}
+
+/*****************************************************************************
+* Prototype : spl_get_msg_pool
+* Description : get msg pool
+* Input : None
+* Output : None
+* Return Value : mring_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+mring_handle
+spl_get_msg_pool ()
+{
+ return (mring_handle) ADDR_SHTOL (g_spl_app_res_group->msg_pool);
+}
+
+/*****************************************************************************
+* Prototype : spl_recycle_msg
+* Description : recycle msg
+* Input : void *data
+* void* argv
+* Output : None
+* Return Value : static int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static int
+spl_recycle_msg (void *data, void *argv)
+{
+ if (!data)
+ {
+ NSPOL_LOGERR ("data is NULL]data=%p,pid=%p", data, argv);
+ return -1;
+ }
+
+ data_com_msg *m = (data_com_msg *) data;
+ u64 pid_64 = (u64) argv;
+ u32 pid = (u32) pid_64;
+ if (pid == m->param.recycle_pid)
+ {
+ ASYNC_MSG_FREE (m);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : spl_recycle_msg_pool
+* Description : recycle msg pool
+* Input : u32 pid
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+spl_recycle_msg_pool (u32 pid)
+{
+ mring_handle msg_pool = spl_get_msg_pool ();
+ if (!msg_pool)
+ {
+ NSPOL_LOGERR ("msg_pool is NULL,this can not happen]pid=%u", pid);
+ return;
+ }
+
+ u64 pid_64 = pid;
+ (void) nsfw_mem_sp_iterator (msg_pool, 0, SPL_MAX_MSG_NUM, spl_recycle_msg,
+ (void *) pid_64);
+}
+
+/*****************************************************************************
+* Prototype : spl_get_conn_num
+* Description : get conn num
+* Input : None
+* Output : None
+* Return Value : u32
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+u32
+spl_get_conn_num ()
+{
+ return CUR_CFG_SOCKET_NUM;
+}
+
+/***************************************************
+* description:
+***************************************************/
+int
+sbr_malloc_tx_pool (u32 pid, mpool_handle pool[], u32 pool_num)
+{
+ int loop;
+ for (loop = 0; loop < SBR_TX_POOL_NUM; loop++)
+ {
+ if ((0 == g_res_group_array->pid_array[loop])
+ &&
+ __sync_bool_compare_and_swap (&g_res_group_array->pid_array[loop],
+ 0, pid))
+ {
+ u32 i;
+ for (i = 0; i < g_res_group_array->thread_num && i < pool_num; ++i)
+ {
+ spl_app_res_group *group =
+ (spl_app_res_group *)
+ ADDR_SHTOL (g_res_group_array->res_group[i]);
+ pool[i] = ADDR_SHTOL (group->tx_pool_array[loop]);
+ }
+
+ NSSBR_LOGINF ("get tx pool]pid=%d,loop=%d.", pid, loop);
+ return 0;
+ }
+ }
+
+ for (loop = 0; loop < SBR_TX_POOL_NUM; loop++)
+ {
+ NSSBR_LOGERR ("no free pool]loop=%d,pid=%d", loop,
+ g_res_group_array->pid_array[loop]);
+ }
+
+ return -1;
+}
+
+/***************************************************
+* description:
+***************************************************/
+void
+spl_free_tx_pool (u32 pid)
+{
+ int loop;
+ for (loop = 0; loop < SBR_TX_POOL_NUM; loop++)
+ {
+ if (pid == g_res_group_array->pid_array[loop])
+ {
+ u32 i;
+ for (i = 0; i < g_res_group_array->thread_num; ++i)
+ {
+ (void)
+ nsfw_mem_mbuf_pool_recycle (g_res_group_array->res_group
+ [i]->tx_pool_array[loop]);
+ }
+
+ if (!__sync_bool_compare_and_swap
+ (&g_res_group_array->pid_array[loop], pid, 0))
+ {
+ NSSBR_LOGERR ("free tx_pool failed]loop=%d,pid=%d", loop, pid);
+ }
+ else
+ {
+ NSSBR_LOGDBG ("free tx_pool ok]loop=%d,pid=%d", loop, pid);
+ }
+
+ break;
+ }
+ }
+}
+
+/***************************************************
+* description:
+***************************************************/
+mring_handle
+sbr_get_instance_conn_pool (u32 thread_index)
+{
+ if (thread_index >= g_res_group_array->thread_num)
+ {
+ return NULL;
+ }
+
+ spl_app_res_group *group =
+ (spl_app_res_group *)
+ ADDR_SHTOL (g_res_group_array->res_group[thread_index]);
+ return ADDR_SHTOL (group->conn_pool);
+}
+
+/***************************************************
+* description:
+***************************************************/
+mring_handle *
+ss_get_instance_msg_box (u16 thread_index, u16 idx)
+{
+ if (thread_index >= g_res_group_array->thread_num)
+ {
+ thread_index = 0;
+ }
+
+ if (idx >= SPL_MSG_BOX_NUM)
+ {
+ idx = 0;
+ }
+
+ spl_app_res_group *group =
+ (spl_app_res_group *)
+ ADDR_SHTOL (g_res_group_array->res_group[thread_index]);
+ return ADDR_SHTOL (group->mbox_array[idx]);
+}
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_app_res.h b/stacks/lwip_stack/lwip_src/common/stackx_app_res.h
new file mode 100644
index 0000000..435f2f6
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_app_res.h
@@ -0,0 +1,103 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_APP_RES_H
+#define STACKX_APP_RES_H
+#include "types.h"
+#include "nsfw_mem_api.h"
+#include "stackxopts.h"
+#include "stackx_spl_share.h"
+#include "nsfw_mt_config.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define SPL_RES_GROUP_ARRAY "spl_res_group_array"
+
+#define SPL_APP_RES "spl_app_res"
+#define SPL_APP_RES_GROUP_NAME "spl_app_res_group"
+#define SPL_TX_POOL_NAME "spl_tx_pool"
+#define SPL_CONN_POOL_NAME "spl_conn_pool"
+#define SPL_CONN_ARRAY_NAME "spl_conn_array"
+#define SPL_DFX_ARRAY_NAME "spl_dfx_array"
+#define SPL_MSG_POOL_NAME "spl_msg_pool"
+#define SPL_RECYCLE_GROUP "spl_recycle_group"
+#define SPL_RECV_RING_POOL_NAME "spl_recv_ring_pool"
+#define SPL_RECV_RING_ARRAY_NAME "spl_recv_array"
+
+#define SBR_TX_POOL_NUM APP_POOL_NUM
+#define SBR_TX_POOL_MBUF_NUM TX_MBUF_POOL_SIZE
+#define SBR_TX_MSG_NUM (SBR_TX_POOL_NUM * SBR_TX_POOL_MBUF_NUM)
+
+#define SBR_TX_POOL_ARRAY_NAME "sbr_tx_pool_array"
+#define SBR_TX_POOL_NAME "sbr_tx_pool"
+#define SBR_TX_MSG_ARRAY_NAME "sbr_tx_msg_array"
+
+#define SPL_MAX_MSG_NUM (MBOX_RING_SIZE*8*MAX_THREAD_NUM)
+
+typedef struct
+{
+ PRIMARY_ADDR mring_handle msg_pool;
+ PRIMARY_ADDR mring_handle conn_pool;
+ PRIMARY_ADDR spl_netconn_t **conn_array;
+ PRIMARY_ADDR mring_handle recv_ring_pool;
+ PRIMARY_ADDR mpool_handle tx_pool_array[SBR_TX_POOL_NUM];
+ PRIMARY_ADDR mring_handle mbox_array[SPL_MSG_BOX_NUM];
+ i64 extend_member_bit;
+} spl_app_res_group;
+
+typedef struct
+{
+ u32 pid_array[SBR_TX_POOL_NUM];
+ PRIMARY_ADDR spl_app_res_group *res_group[MAX_THREAD_NUM];
+ u16 thread_num;
+} spl_app_res_group_array;
+
+extern spl_app_res_group *g_spl_app_res_group;
+extern spl_app_res_group_array *g_res_group_array;
+
+/* call it main thread */
+int spl_init_group_array ();
+
+/* call these in tcpip thread */
+int spl_init_app_res ();
+spl_netconn_t **spl_get_conn_array (u32 pid);
+mring_handle spl_get_conn_pool ();
+mring_handle spl_get_msg_pool ();
+void spl_recycle_msg_pool (u32 pid);
+u32 spl_get_conn_num ();
+void spl_free_tx_pool (u32 pid);
+int spl_add_mbox (mring_handle mbox_array[], u32 array_size);
+int spl_add_instance_res_group (u32 thread_index, spl_app_res_group * group);
+
+/* call these in app */
+int sbr_malloc_tx_pool (u32 pid, mpool_handle pool[], u32 pool_num);
+int sbr_attach_group_array ();
+mring_handle sbr_get_instance_conn_pool (u32 thread_index);
+
+/* call these in app and spl */
+mring_handle *ss_get_instance_msg_box (u16 thread_index, u16 index);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common.c b/stacks/lwip_stack/lwip_src/common/stackx_common.c
new file mode 100644
index 0000000..750df74
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_common.c
@@ -0,0 +1,357 @@
+/*
+*
+* 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 <stdarg.h>
+#include <stddef.h>
+#include "stackx_common.h"
+#include "nstack_securec.h"
+#include "nstack_log.h"
+#include "types.h"
+#include "stackx_types.h"
+
+int
+spl_snprintf (char *buffer, int buflen, const char *format, ...)
+{
+ int len;
+ va_list ap;
+
+ if ((NULL == buffer) || (0 >= buflen))
+ {
+ return -1;
+ }
+
+ if (format == NULL)
+ {
+ buffer[0] = '\0';
+ return -1;
+ }
+
+ (void) va_start (ap, format);
+ len = VSNPRINTF_S (buffer, buflen, buflen - 1, format, ap);
+ if (-1 == len)
+ {
+ va_end (ap);
+ return -1;
+ }
+
+ va_end (ap);
+ if ((len >= buflen) && (buflen > 0) && (buffer != NULL))
+ {
+ buffer[buflen - 1] = '\0';
+ }
+
+ return len;
+}
+
+/*****************************************************************************
+* Prototype : sbr_create_mzone
+* Description : create mzone
+* Input : const char* name
+* size_t size
+* Output : None
+* Return Value : mzone_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+mzone_handle
+sbr_create_mzone (const char *name, size_t size)
+{
+ if (!name)
+ {
+ NSFW_LOGERR ("name is NULL");
+ return NULL;
+ }
+
+ mzone_handle zone;
+ nsfw_mem_zone param;
+
+ param.isocket_id = -1;
+ param.length = size;
+ param.stname.entype = NSFW_SHMEM;
+
+ if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0)
+ {
+ NSFW_LOGERR ("STRCPY_S failed]name=%s", name);
+ return NULL;
+ }
+
+ zone = nsfw_mem_zone_create (&param);
+ if (!zone)
+ {
+ NSFW_LOGERR ("nsfw_mem_zone_create failed]name=%s, size:%zu", name,
+ size);
+ return NULL;
+ }
+
+ return zone;
+}
+
+/*****************************************************************************
+* Prototype : sbr_lookup_mzone
+* Description : lookup mzone
+* Input : const char* name
+* Output : None
+* Return Value : mzone_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+mzone_handle
+sbr_lookup_mzone (const char *name)
+{
+ if (!name)
+ {
+ NSFW_LOGERR ("name is NULL");
+ return NULL;
+ }
+
+ mzone_handle zone;
+ nsfw_mem_name param;
+
+ param.entype = NSFW_SHMEM;
+ param.enowner = NSFW_PROC_MAIN;
+ if (STRCPY_S (param.aname, NSFW_MEM_NAME_LENTH, name) != 0)
+ {
+ NSFW_LOGERR ("STRCPY_S failed]name=%s", name);
+ return NULL;
+ }
+
+ zone = nsfw_mem_zone_lookup (&param);
+ if (!zone)
+ {
+ NSFW_LOGERR ("nsfw_mem_zone_lookup failed]name=%s", name);
+ return NULL;
+ }
+
+ return zone;
+}
+
+/*****************************************************************************
+* Prototype : sbr_create_pool
+* Description : create pool
+* Input : const char* name
+* i32 num
+* u16 size
+* Output : None
+* Return Value : mring_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+mring_handle
+sbr_create_pool (const char *name, i32 num, u16 size)
+{
+ if (!name)
+ {
+ NSFW_LOGERR ("name is NULL");
+ return NULL;
+ }
+
+ nsfw_mem_sppool param;
+ if (EOK != MEMSET_S (&param, sizeof (param), 0, sizeof (param)))
+ {
+ NSFW_LOGERR ("memset error]name=%s", name);
+ return NULL;
+ }
+
+ param.enmptype = NSFW_MRING_MPMC;
+ param.useltsize = size;
+ param.usnum = num;
+ param.stname.entype = NSFW_SHMEM;
+ param.isocket_id = -1;
+ if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0)
+ {
+ NSFW_LOGERR ("STRCPY_S failed]name=%s", name);
+ return NULL;
+ }
+
+ mring_handle ring = nsfw_mem_sp_create (&param);
+ if (!ring)
+ {
+ NSFW_LOGERR ("Create pool failed]name=%s, num=%d, size=%u", name, num,
+ size);
+ }
+
+ return ring;
+}
+
+/*****************************************************************************
+* Prototype : sbr_create_ring
+* Description : create ring
+* Input : const char* name
+* i32 num
+* Output : None
+* Return Value : mring_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+mring_handle
+sbr_create_ring (const char *name, i32 num)
+{
+ if (!name)
+ {
+ NSFW_LOGERR ("name is NULL");
+ return NULL;
+ }
+
+ nsfw_mem_mring param;
+ if (EOK != MEMSET_S (&param, sizeof (param), 0, sizeof (param)))
+ {
+ NSFW_LOGERR ("memset error]name=%s", name);
+ return NULL;
+ }
+
+ param.enmptype = NSFW_MRING_MPMC;
+ param.isocket_id = -1;
+ param.usnum = num;
+ param.stname.entype = NSFW_SHMEM;
+
+ if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0)
+ {
+ NSFW_LOGERR ("STRCPY_S failed]name=%s", name);
+ return NULL;
+ }
+
+ mring_handle ring = nsfw_mem_ring_create (&param);
+ if (!ring)
+ {
+ NSFW_LOGERR ("Create ring failed]name=%s, num=%d", name, num);
+ }
+
+ return ring;
+}
+
+/*****************************************************************************
+* Prototype : sbr_create_multi_ring
+* Description : create multi ring
+* Input : const char* name
+* u32 ring_size
+* i32 ring_num
+* mring_handle* array
+* nsfw_mpool_type type
+* Output : None
+* Return Value : int
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+int
+sbr_create_multi_ring (const char *name, u32 ring_size, i32 ring_num,
+ mring_handle * array, nsfw_mpool_type type)
+{
+ if (!name)
+ {
+ NSFW_LOGERR ("name is NULL");
+ return -1;
+ }
+
+ if (!array)
+ {
+ NSFW_LOGERR ("array is NULL");
+ return -1;
+ }
+
+ nsfw_mem_mring param;
+
+ if (EOK != MEMSET_S (&param, sizeof (param), 0, sizeof (param)))
+ {
+ NSSBR_LOGERR ("Error to memset]name=%s", name);
+ return -1;
+ }
+
+ param.enmptype = type;
+ param.stname.entype = NSFW_SHMEM;
+ if (STRCPY_S (param.stname.aname, NSFW_MEM_NAME_LENTH, name) != 0)
+ {
+ NSSBR_LOGERR ("STRCPY_S failed]name=%s", name);
+ return -1;
+ }
+
+ param.usnum = ring_size;
+ param.isocket_id = -1;
+ if (nsfw_mem_sp_ring_create (&param, array, ring_num) != 0)
+ {
+ NSSBR_LOGERR ("Create ring pool failed]name=%s, ring_num=%d", name,
+ ring_num);
+ return -1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
+* Prototype : sbr_lookup_ring
+* Description : lookup ring
+* Input : const char* name
+* Output : None
+* Return Value : mring_handle
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+mring_handle
+sbr_lookup_ring (const char *name)
+{
+ nsfw_mem_name param;
+
+ param.entype = NSFW_SHMEM;
+ param.enowner = NSFW_PROC_MAIN;
+ if (STRCPY_S (param.aname, NSFW_MEM_NAME_LENTH, name) != 0)
+ {
+ NSFW_LOGERR ("STRCPY_S failed]name=%s", name);
+ return NULL;
+ }
+
+ mring_handle ring = nsfw_mem_ring_lookup (&param);
+ if (!ring)
+ {
+ NSFW_LOGERR ("lookup ring failed]name=%s", name);
+ }
+
+ return ring;
+}
+
+int
+sbr_timeval2msec (struct timeval *pTime, u64 * msec)
+{
+ if ((pTime->tv_sec < 0) || (pTime->tv_usec < 0))
+ {
+ NSFW_LOGERR ("time->tv_sec is nagative");
+ return -1;
+ }
+
+ if (STACKX_MAX_U64_NUM / 1000 < (u64_t) pTime->tv_sec)
+ {
+ NSFW_LOGERR ("tout.tv_sec is too large]tout.tv_sec=%lu", pTime->tv_sec);
+ return -1;
+ }
+
+ u64 sec2msec = 1000 * pTime->tv_sec;
+ u64 usec2msec = pTime->tv_usec / 1000;
+
+ if (STACKX_MAX_U64_NUM - sec2msec < usec2msec)
+ {
+ NSFW_LOGERR
+ ("nsec2msec plus sec2usec is too large]usec2msec=%lu,usec2msec=%lu",
+ usec2msec, sec2msec);
+ return -1;
+ }
+
+ *msec = sec2msec + usec2msec;
+ return 0;
+}
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common.h b/stacks/lwip_stack/lwip_src/common/stackx_common.h
new file mode 100644
index 0000000..1df97d5
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_common.h
@@ -0,0 +1,44 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_COMMON_H
+#define STACKX_COMMON_H
+#include "nsfw_mem_api.h"
+//#include "lwip/cc.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+int spl_snprintf (char *buffer, int buflen, const char *format, ...);
+mzone_handle sbr_create_mzone (const char *name, size_t size);
+mzone_handle sbr_lookup_mzone (const char *name);
+mring_handle sbr_create_pool (const char *name, i32 num, u16 size);
+mring_handle sbr_create_ring (const char *name, i32 num);
+int sbr_create_multi_ring (const char *name, u32 ring_size, i32 ring_num,
+ mring_handle * array, nsfw_mpool_type type);
+mring_handle sbr_lookup_ring (const char *name);
+int sbr_timeval2msec (struct timeval *pTime, u64 * msec);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h b/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h
new file mode 100644
index 0000000..d2d01e5
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_common_opt.h
@@ -0,0 +1,146 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_COMMON_OPT_H
+#define STACKX_COMMON_OPT_H
+#include <sys/ioctl.h>
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 0X800 /* nonblocking I/O */
+#endif
+
+#if !defined (FIONREAD) || !defined (FIONBIO)
+#define IOC_VOID 0x20000000UL /* no parameters */
+#define IOC_OUT 0x40000000UL /* copy out parameters */
+#define IOC_IN 0x80000000UL /* copy in parameters */
+#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */
+#define IOC_INOUT (IOC_IN | IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */
+#define _IO(x, y) (((x) << 8) | (y) | IOC_VOID)
+#define _IOR(x, y, t) (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y))
+#define _IOW(x, y, t) (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y))
+#endif
+
+#ifndef FIONREAD
+#define FIONREAD _IOR('f', 127, unsigned long)
+#endif
+
+#ifndef FIONBIO
+#define FIONBIO _IOW('f', 126, unsigned long)
+#endif
+
+#ifndef F_GETFL
+#define F_GETFL 3
+#endif
+
+#ifndef F_SETFL
+#define F_SETFL 4
+#endif
+
+#ifndef SPL_SHUT_RD
+#define SPL_SHUT_RD 0
+#define SPL_SHUT_WR 1
+#define SPL_SHUT_RDWR 2
+#endif
+
+/* Flags for struct netconn.flags (u8_t) */
+
+/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
+ this temporarily stores whether to wake up the original application task
+ if data couldn't be sent in the first try. */
+#define SPL_NETCONN_FLAG_WRITE_DELAYED 0x01
+
+/** Should this netconn avoid blocking? */
+#define SPL_NETCONN_FLAG_NON_BLOCKING 0x02
+
+/** Was the last connect action a non-blocking one? */
+#define SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04
+
+/** If this is set, a TCP netconn must call netconn_recved() to update
+ the TCP receive window (done automatically if not set). */
+#define SPL_NETCONN_FLAG_NO_AUTO_RECVED 0x08
+
+/** If a nonblocking write has been rejected before, poll_tcp needs to
+ check if the netconn is writable again */
+#define SPL_NETCONN_FLAG_CHECK_WRITESPACE 0x10
+
+/* For the netconn API, these values are use as a bitmask! */
+#define SPL_NETCONN_SHUT_RD 1
+#define SPL_NETCONN_SHUT_WR 2
+#define SPL_NETCONN_SHUT_RDWR (SPL_NETCONN_SHUT_RD | SPL_NETCONN_SHUT_WR)
+#define STACKX_TIMER_THREAD_SUPPORT 1
+
+/* Flags for netconn_write (u8_t) */
+#define SPL_NETCONN_NOFLAG 0x00
+#define SPL_NETCONN_NOCOPY 0x00
+#define SPL_NETCONN_COPY 0x01
+#define SPL_NETCONN_MORE 0x02
+#define SPL_NETCONN_DONTBLOCK 0x04
+
+#define SPL_TCP_NODELAY 0x01
+#define SPL_TCP_KEEPALIVE 0x02
+#define SPL_TCP_KEEPIDLE 0x04
+#define SPL_TCP_KEEPINTVL 0x05
+#define SPL_TCP_KEEPCNT 0x06
+#define SPL_TCP_LINGER2 0x08
+#define SPL_TCP_DEFER_ACCEPT 0x09
+
+typedef enum spl_netconn_type
+{
+ SPL_NETCONN_INVALID = 0,
+ SPL_NETCONN_TCP = 0x10,
+ SPL_NETCONN_UDP = 0x20,
+ SPL_NETCONN_UDPLITE = 0x21,
+ SPL_NETCONN_UDPNOCHKSUM = 0x22,
+ SPL_NETCONN_RAW = 0x40,
+} spl_netconn_type_t;
+
+typedef enum spl_netconn_state
+{
+ SPL_NETCONN_NONE,
+ SPL_NETCONN_WRITE,
+ SPL_NETCONN_LISTEN,
+ SPL_NETCONN_CONNECT,
+ SPL_NETCONN_CLOSE,
+} spl_netconn_state_t;
+
+typedef enum spl_tcp_state
+{
+ SPL_CLOSED = 0,
+ SPL_LISTEN = 1,
+ SPL_SYN_SENT = 2,
+ SPL_SYN_RCVD = 3,
+ SPL_ESTABLISHED = 4,
+ SPL_FIN_WAIT_1 = 5,
+ SPL_FIN_WAIT_2 = 6,
+ SPL_CLOSE_WAIT = 7,
+ SPL_CLOSING = 8,
+ SPL_LAST_ACK = 9,
+ SPL_TIME_WAIT = 10
+} spl_tcp_state_t;
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_debug.h b/stacks/lwip_stack/lwip_src/common/stackx_debug.h
new file mode 100644
index 0000000..7c6395e
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_debug.h
@@ -0,0 +1,70 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_DEBUG_H__
+#define __STACKX_DEBUG_H__
+
+//#include "lwip/arch.h"
+#include <pthread.h>
+
+#include <sys/syscall.h>
+
+#include "nstack_log.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/** lower two bits indicate dbug level
+ * - 0 all
+ * - 1 warning
+ * - 2 serious
+ * - 3 severe
+ */
+#define STACKX_DBG_LEVEL_ALL 0x00
+#define STACKX_DBG_LEVEL_OFF STACKX_DBG_LEVEL_ALL /* compatibility define only */
+#define STACKX_DBG_LEVEL_WARNING 0x01 /* bad checksums, dropped packets, ... */
+#define STACKX_DBG_LEVEL_SERIOUS 0x02 /* memory allocation failures, ... */
+#define STACKX_DBG_LEVEL_SEVERE 0x03
+#define STACKX_DBG_MASK_LEVEL 0x00
+
+/** flag to enable that dbug message */
+#define STACKX_DBG_ON NS_LOG_STACKX_ON
+
+/** flag to disable that dbug message */
+#define STACKX_DBG_OFF NS_LOG_STACKX_OFF
+
+/** flag for indicating a tracing_message (to follow program flow) */
+#define STACKX_DBG_TRACE NS_LOG_STACKX_TRACE
+
+/** flag for indicating a state dbug message (to follow module states) */
+#define STACKX_DBG_STATE NS_LOG_STACKX_STATE
+
+/** flag for indicating newly added code, not thoroughly tested yet */
+#define STACKX_DBG_FRESH NS_LOG_STACKX_FRESH
+
+/** flag for to halt after printing this dbug message */
+#define STACKX_DBG_HALT NS_LOG_STACKX_HALT
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __STACKX_DEBUG_H__ */
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_err.h b/stacks/lwip_stack/lwip_src/common/stackx_err.h
new file mode 100644
index 0000000..1d0fc20
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_err.h
@@ -0,0 +1,68 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_ERR_H
+#define STACKX_ERR_H
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define ERR_OK 0 /* No error, everything OK. */
+#define ERR_MEM -1 /* Out of memory error. */
+#define ERR_BUF -2 /* Buffer error. */
+#define ERR_TIMEOUT -3 /* Timeout. */
+#define ERR_RTE -4 /* Routing problem. */
+#define ERR_INPROGRESS -5 /* Operation in progress */
+#define ERR_VAL -6 /* Illegal value. */
+#define ERR_WOULDBLOCK -7 /* Operation would block. */
+#define ERR_USE -8 /* Address in use. */
+#define ERR_ISCONN -9 /* Already connected. */
+
+#define SPL_ERR_IS_FATAL(e) ((e) < ERR_ISCONN)
+
+#define ERR_ABRT -10 /* Connection aborted. */
+#define ERR_RST -11 /* Connection reset. */
+#define ERR_CLSD -12 /* Connection closed. */
+#define ERR_CONN -13 /* Not connected. */
+
+#define ERR_ARG -14 /* Illegal argument. */
+
+#define ERR_IF -15 /* Low-level netif error */
+#define ERR_ALREADY -16 /* previous connect attemt has not yet completed */
+#define ERR_PROTOTYPE -17 /* prototype error or some other generic error.
+ the operation is not allowed on current socket */
+
+#define ERR_CALLBACK -18 /* callback error */
+#define ERR_CANTASSIGNADDR -19 /* Cannot assign requested address */
+#define ERR_CONTAINER_ID -20 /*Illegal container id */
+#define ERR_NOTSOCK -21 /*not a socket */
+
+#define ERR_CLOSE_WAIT -22 /*closed in established state */
+
+#define ERR_EPROTONOSUPPORT -23 /* Protocol not supported */
+
+#define ERR_FAULTRECOVERY -24 /*SPL just recovered from a fatal fault */
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c
new file mode 100644
index 0000000..306bcaf
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.c
@@ -0,0 +1,280 @@
+/*
+*
+* 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 <stdint.h>
+#include <stddef.h>
+#include "stackx_ip_addr.h"
+#include "nstack_log.h"
+#include "spl_def.h"
+
+/* Here for now until needed in other places in stackx*/
+#ifndef isprint
+#define in_range(c, lo, up) ((u8)c >= lo && (u8)c <= up)
+#define isprint(c) in_range(c, 0x20, 0x7f)
+#define isdigit(c) in_range(c, '0', '9')
+#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
+#define islower(c) in_range(c, 'a', 'z')
+#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
+#endif
+
+/**
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ *
+ * @param cp IPaddress in ascii represenation (e.g. "127.0.0.1")
+ * @return ipaddress in network order
+ */
+u32
+spl_ipaddr_addr (const char *cp)
+{
+ spl_ip_addr_t val;
+
+ if (spl_ipaddr_aton (cp, &val))
+ {
+ return ip4_addr_get_u32 (&val);
+ }
+
+ return (SPL_IPADDR_NONE);
+}
+
+/**
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broad cast address.
+ *
+ * @param cp IPaddress in ascii represenation (e.g. "127.0.0.1")
+ * @param addr pointer to which to save the ipaddress in network order
+ * @return 1 if cp could be converted to addr, 0 on failure
+ */
+int
+spl_ipaddr_aton (const char *cp, spl_ip_addr_t * addr)
+{
+ u32 val;
+ u8 base;
+ char c;
+ u32 parts[4];
+ u32 *pp = parts;
+
+ if (cp == NULL)
+ {
+ return 0;
+ }
+
+ c = *cp;
+ for (;;)
+ {
+ /*
+ * Get number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, 1-9=decimal.
+ */
+ if (!isdigit (c))
+ {
+ return (0);
+ }
+
+ val = 0;
+ base = 10;
+ if (c == '0')
+ {
+ c = *++cp;
+ if ((c == 'x') || (c == 'X'))
+ {
+ base = 16;
+ c = *++cp;
+ }
+ else
+ {
+ base = 8;
+ }
+ }
+
+ for (;;)
+ {
+ if (isdigit (c))
+ {
+ val = (val * base) + (int) (c - '0');
+ c = *++cp;
+ }
+ else if ((base == 16) && isxdigit (c))
+ {
+ val = (val << 4) | (int) (c + 10 - (islower (c) ? 'a' : 'A'));
+ c = *++cp;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (c == '.')
+ {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3)
+ {
+ return (0);
+ }
+
+ *pp++ = val;
+ c = *++cp;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /*
+ * Check for trailing characters.
+ */
+ if ((c != '\0') && !isspace (c))
+ {
+ return (0);
+ }
+
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ switch (pp - parts + 1)
+ {
+ case 0:
+ return (0); /* initial nondigit */
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffffUL)
+ {
+ return (0);
+ }
+
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ {
+ return (0);
+ }
+
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ {
+ return (0);
+ }
+
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ default:
+ NSPOL_LOGERR ("unhandled");
+
+ return (0);
+ }
+
+ if (addr)
+ {
+ ip4_addr_set_u32 (addr, spl_htonl (val));
+ }
+
+ return (1);
+}
+
+/**
+ * Convert numeric IPaddress into decimal dotted ASCII representation.
+ * returns ptr to static buffer; not reentrant!
+ *
+ * @param addr ipaddress in network order to convert
+ * @return pointer to a global static (!) buffer that holds the ASCII
+ * represenation of addr
+ */
+char *
+spl_ipaddr_ntoa (const spl_ip_addr_t * addr)
+{
+ static char str[16];
+
+ return spl_ipaddr_ntoa_r (addr, str, 16);
+}
+
+/**
+ * Same as spl_ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
+ *
+ * @param addr ipaddress in network order to convert
+ * @param buf target buffer where the string is stored
+ * @param buflen length of buf
+ * @return either pointer to buf which now holds the ASCII
+ * representation of addr or NULL if buf was too small
+ */
+char *
+spl_ipaddr_ntoa_r (const spl_ip_addr_t * addr, char *buf, int buflen)
+{
+ u32 s_addr;
+ char inv[3];
+ char *rp;
+ u8 *ap;
+ u8 rem;
+ u8 n;
+ u8 i;
+ int len = 0;
+
+ s_addr = ip4_addr_get_u32 (addr);
+
+ rp = buf;
+ ap = (u8 *) & s_addr;
+ for (n = 0; n < 4; n++)
+ {
+ i = 0;
+ do
+ {
+ rem = *ap % (u8) 10;
+ *ap /= (u8) 10;
+ inv[i++] = '0' + rem;
+ }
+ while (*ap);
+
+ while (i--)
+ {
+ if (len++ >= buflen)
+ {
+ return NULL;
+ }
+
+ *rp++ = inv[i];
+ }
+
+ if (len++ >= buflen)
+ {
+ return NULL;
+ }
+
+ *rp++ = '.';
+ ap++;
+ }
+
+ *--rp = 0;
+ return buf;
+}
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h
new file mode 100644
index 0000000..9f2dc07
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_addr.h
@@ -0,0 +1,82 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_IP_ADDR_H
+#define STACKX_IP_ADDR_H
+#include "types.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/* This is the aligned version of ip_addr_t,
+ used as local variable, on the stack, etc. */
+typedef struct spl_ip_addr
+{
+ u32 addr;
+} spl_ip_addr_t;
+
+/** 127.0.0.1 */
+#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
+
+/** 0.0.0.0 */
+#define IPADDR_ANY ((u32_t)0x00000000UL)
+
+/** 255.255.255.255 */
+#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
+
+/** 255.255.255.255 */
+#define SPL_IPADDR_NONE ((u32)0xffffffffUL)
+
+/** Set address to IPADDR_ANY (no need for spl_htonl()) */
+#define spl_ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY)
+
+/** Set complete address to zero */
+#define spl_ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
+
+/** IPv4 only: set the IPaddress given as an u32_t */
+#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32))
+
+/** IPv4 only: get the IPaddress as an u32_t */
+#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr)
+
+#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
+#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
+
+/** For backwards compatibility */
+#define spl_ip_ntoa(ipaddr) spl_ipaddr_ntoa(ipaddr)
+
+u32 spl_ipaddr_addr (const char *cp);
+int spl_ipaddr_aton (const char *cp, spl_ip_addr_t * addr);
+
+/** returns ptr to static buffer; not reentrant! */
+char *spl_ipaddr_ntoa (const spl_ip_addr_t * addr);
+char *spl_ipaddr_ntoa_r (const spl_ip_addr_t * addr, char *buf, int buflen);
+
+#define spl_inet_addr(cp) spl_ipaddr_addr(cp)
+#define spl_inet_aton(cp, paddr) spl_ipaddr_aton(cp, (spl_ip_addr_t*)(paddr))
+#define spl_inet_ntoa(paddr) spl_ipaddr_ntoa((spl_ip_addr_t*)&(paddr))
+#define spl_inet_ntoa_r(addr, buf, buflen) spl_ipaddr_ntoa_r((spl_ip_addr_t*)&(addr), buf, buflen)
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h b/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h
new file mode 100644
index 0000000..6ca2598
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_ip_tos.h
@@ -0,0 +1,146 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_IP_TOS_H
+#define STACKX_IP_TOS_H
+#include "types.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/*
+ * The Type of Service provides an indication of the abstract
+ * parameters of the quality of service desired. These parameters are
+ * to be used to guide the selection of the actual service parameters
+ * when transmitting a datagram through a particular network. Several
+ * networks offer service precedence, which somehow treats high
+ * precedence traffic as more important than other traffic (generally
+ * by accepting only traffic above a certain precedence at time of high
+ * load). The major choice is a three way tradeoff between low-delay,
+ * high-reliability, and high-throughput.
+ * The use of the Delay, Throughput, and Reliability indications may
+ * increase the cost (in some sense) of the service. In many networks
+ * better performance for one of these parameters is coupled with worse
+ * performance on another. Except for very unusual cases at most two
+ * of these three indications should be set.
+ */
+#define IPTOS_LOWCOST 0x02
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_TOS_MASK 0x1E
+#define IPTOS_MINCOST IPTOS_LOWCOST
+#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
+
+/*
+ * The Network Control precedence designation is intended to be used
+ * within a network only. The actual use and control of that
+ * designation is up to each network. The Internetwork Control
+ * designation is intended for use by gateway control originators only.
+ * If the actual use of these precedence designations is of concern to
+ * a particular network, it is the responsibility of that network to
+ * control the access to, and use of, those precedence designations.
+ */
+#define IPTOS_PREC_ROUTINE 0x00
+#define IPTOS_PREC_PRIORITY 0x20
+#define IPTOS_PREC_IMMEDIATE 0x40
+#define IPTOS_PREC_FLASH 0x60
+#define IPTOS_PREC_FLASHOVERRIDE 0x80
+#define IPTOS_PREC_CRITIC_ECP 0xa0
+#define IPTOS_PREC_INTERNETCONTROL 0xc0
+#define IPTOS_PREC_MASK 0xe0
+#define IPTOS_PREC_NETCONTROL 0xe0
+#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
+
+#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3)
+
+#define TC_PRIO_BESTEFFORT 0
+#define TC_PRIO_FILLER 1
+#define TC_PRIO_BULK 2
+#define TC_PRIO_INTERACTIVE_BULK 4
+#define TC_PRIO_INTERACTIVE 6
+#define TC_PRIO_CONTROL 7
+#define TC_PRIO_MAX 15
+
+#define ECN_OR_COST(class ) TC_PRIO_ ## class
+
+static u8 stackx_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)
+};
+
+static inline char
+stackx_rt_tos2priority (u8 tos)
+{
+ return stackx_ip_tos2prio[IPTOS_TOS (tos) >> 1];
+}
+
+typedef enum
+{
+ STACKX_PRIM,
+ STACKX_HIGH,
+ STACKX_MEDIUM,
+ STACKX_LOW
+} stackx_prio;
+
+static inline stackx_prio
+stackx_get_prio (u8 tos)
+{
+ if (0 == tos)
+ {
+ return STACKX_PRIM;
+ }
+ char prio = stackx_rt_tos2priority (tos);
+ if ((TC_PRIO_INTERACTIVE == prio))
+ {
+ return STACKX_HIGH;
+ }
+ else if ((TC_PRIO_BESTEFFORT == prio) || (TC_PRIO_INTERACTIVE_BULK == prio))
+ {
+ return STACKX_MEDIUM;
+ }
+ else if ((TC_PRIO_BULK == prio) || (TC_PRIO_FILLER == prio))
+ {
+ return STACKX_LOW;
+ }
+
+ return STACKX_PRIM;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h b/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h
new file mode 100644
index 0000000..a8be1a7
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_netbuf.h
@@ -0,0 +1,43 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_NETBUF_H
+#define STACKX_NETBUF_H
+#include "stackx_pbuf.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef struct spl_netbuf
+{
+ struct spl_pbuf *p;
+ spl_ip_addr_t addr;
+ u16 port;
+} spl_netbuf;
+
+#define netbuf_fromaddr(buf) (&((buf)->addr))
+#define netbuf_fromport(buf) ((buf)->port)
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c
new file mode 100644
index 0000000..c176a4b
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.c
@@ -0,0 +1,223 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "stackx_spl_share.h"
+#include "stackx_pbuf.h"
+#include "common_mem_mbuf.h"
+#include "nstack_securec.h"
+#include "nsfw_maintain_api.h"
+#include "stackx_tcp_opt.h"
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+
+/*****************************************************************************
+* Prototype : sbr_malloc_pbuf
+* Description : malloc spl_pbuf,use it in app
+* Input : mpool_handle mp
+* u16 len
+* u32 mbuf_data_size
+* u16 offset
+* Output : None
+* Return Value : struct pbuf*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+struct spl_pbuf *
+sbr_malloc_pbuf (mpool_handle mp, u16 len, u32 mbuf_data_size, u16 offset)
+{
+ if ((len < offset) || (len > mbuf_data_size))
+ {
+ NSSBR_LOGERR ("len is invalid]len=%u", len);
+ return NULL;
+ }
+
+ struct common_mem_mbuf *mbuf = NULL;
+ struct spl_pbuf *buf = NULL;
+
+ mbuf = nsfw_mem_mbf_alloc (mp, NSFW_SHMEM);
+ if (unlikely (mbuf == NULL))
+ {
+ NS_LOG_CTRL (LOG_CTRL_HUGEPAGE_ALLOC_FAIL, LOGSBR, "NSSBR", NSLOG_WAR,
+ "alloc mbuf failed");
+ return NULL;
+ }
+
+ mbuf->data_len = len;
+ mbuf->next = NULL;
+ mbuf->nb_segs = 1;
+ mbuf->pkt_len = len;
+ buf = (struct spl_pbuf *) ((char *) mbuf + sizeof (struct common_mem_mbuf));
+ res_alloc (&buf->res_chk);
+ buf->next = 0;
+ void *tmp = common_pktmbuf_mtod (mbuf, void *);
+ buf->payload = (void *) (ADDR_LTOSH (tmp) + offset);
+ buf->tot_len = len - offset;
+ buf->len = len - offset;
+ buf->type = SPL_PBUF_HUGE;
+ buf->flags = 0;
+ buf->freeNext = NULL;
+ buf->conn_a = 0;
+ buf->proto_type = SPL_PBUF_PROTO_NONE;
+ NSSBR_LOGDBG ("malloc pbuf ok]buf=%p,PRIMARY_ADDR=%p", buf,
+ ADDR_LTOSH (buf));
+ return buf;
+}
+
+u32_t
+spl_pbuf_copy_partial (struct spl_pbuf * buf, void *dataptr, u32_t len,
+ u32_t offset)
+{
+ struct spl_pbuf *p = buf;
+ u32_t buf_copy_len;
+ u32_t copied_total = 0;
+ char *databuf = (char *) dataptr;
+
+ /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */
+ for (p = buf; len != 0 && p != NULL;
+ p = PTR_SHTOL (struct spl_pbuf *, p->next_a))
+ {
+ if (offset != 0 && offset >= p->len)
+ {
+ /* don't copy from this buffer -> on to the next */
+ offset -= p->len;
+ }
+ else if (p->len - offset > len)
+ {
+ /* copy from this buffer. maybe only partially. */
+ (void) common_memcpy (databuf, ADDR_SHTOL (p->payload_a + offset),
+ len);
+ copied_total += len;
+ break;
+ }
+ else
+ {
+ buf_copy_len = p->len - offset;
+ /* copy the necessary parts of the buffer */
+ (void) common_memcpy (databuf, ADDR_SHTOL (p->payload_a + offset),
+ buf_copy_len);
+
+ copied_total += buf_copy_len;
+ databuf += buf_copy_len;
+ len -= buf_copy_len;
+ offset = 0;
+ }
+ }
+
+ return copied_total;
+}
+
+int
+spl_tx_force_buf_free (void *data)
+{
+ struct common_mem_mbuf *mbuf = data;
+ if (NULL == mbuf)
+ {
+ return FALSE;
+ }
+
+ struct spl_pbuf *p_buf =
+ (struct spl_pbuf *) (((char *) mbuf) + sizeof (struct common_mem_mbuf));
+ u8 tempflag = p_buf->res_chk.u8Reserve;
+ if ((mbuf->refcnt == 0) || (tempflag & DPDK_SEND_FLAG))
+ {
+ return FALSE;
+ }
+
+ NSFW_LOGINF ("free mbuf]%p", data);
+ (void) nsfw_mem_mbf_free ((mbuf_handle) mbuf, NSFW_SHMEM);
+ return TRUE;
+}
+
+int
+spl_force_buf_free (void *data)
+{
+ struct common_mem_mbuf *mbuf = data;
+
+ if (NULL == mbuf || (mbuf->refcnt == 0))
+ {
+ return FALSE;
+ }
+
+ NSFW_LOGINF ("free mbuf]%p", data);
+ (void) nsfw_mem_mbf_free ((mbuf_handle) mbuf, NSFW_SHMEM);
+ return TRUE;
+}
+
+int
+spl_reg_res_tx_mgr (mpool_handle * pool)
+{
+ struct common_mem_mempool *mp = (struct common_mem_mempool *) pool;
+ if (NULL == mp)
+ {
+ return 0;
+ }
+
+ nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16,
+ mp->size / 128, mp->size,
+ mp->elt_size,
+ sizeof (struct common_mem_mbuf) + offsetof (struct spl_pbuf, res_chk),
+ mp,
+ mp->pool_data,
+ spl_tx_force_buf_free
+ };
+ (void) nsfw_res_mgr_reg (&scn_cfg);
+ return 0;
+}
+
+int
+spl_reg_res_rxmt_mgr (mpool_handle * pool)
+{
+ struct common_mem_mempool *mp = (struct common_mem_mempool *) pool;
+ if (NULL == mp)
+ {
+ return 0;
+ }
+
+ nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16,
+ mp->size / 128, mp->size,
+ mp->elt_size,
+ sizeof (struct common_mem_mbuf) + offsetof (struct spl_pbuf, res_chk),
+ mp,
+ mp->pool_data,
+ spl_tx_force_buf_free
+ }; /*Can use same function for time */
+ (void) nsfw_res_mgr_reg (&scn_cfg);
+ return 0;
+}
+
+int
+spl_reg_res_txrx_mgr (mpool_handle * pool)
+{
+ struct common_mem_mempool *mp = (struct common_mem_mempool *) pool;
+ if (NULL == mp)
+ {
+ return 0;
+ }
+
+ nsfw_res_scn_cfg scn_cfg = { NSFW_RES_SCAN_MBUF, 60, 3, 16,
+ mp->size / 128, mp->size,
+ mp->elt_size,
+ sizeof (struct common_mem_mbuf) + offsetof (struct spl_pbuf, res_chk),
+ mp,
+ mp->pool_data,
+ spl_force_buf_free
+ };
+ (void) nsfw_res_mgr_reg (&scn_cfg);
+ return 0;
+}
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h
new file mode 100644
index 0000000..60f1772
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf.h
@@ -0,0 +1,82 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_PBUF_H
+#define STACKX_PBUF_H
+
+#include "common_mem_base_type.h"
+#include "common_mem_mbuf.h"
+#include "nsfw_mem_api.h"
+#include "stackx_pbuf_comm.h"
+#ifdef HAL_LIB
+#else
+#include "common_pal_bitwide_adjust.h"
+#endif
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define NEED_ACK_FLAG 0x01 /* This spl_pbuf may have multiple references. */
+#define PBUF_FREE_FLAG 0x04 /* This spl_pbuf has been free. */
+#define DPDK_SEND_FLAG 0x10 /* This spl_pbuf has been sent to DPDK. */
+#define LOOP_SEND_FLAG 0x40 /* This spl_pbuf has been looped to IP layer and not received by app layer yet. */
+
+struct spl_pbuf *sbr_malloc_pbuf (mpool_handle mp, u16 len,
+ u32 mbuf_data_size, u16 offset);
+void sbr_free_pbuf (struct spl_pbuf *p);
+u32 spl_pbuf_copy_partial (struct spl_pbuf *p, void *dataptr, u32_t len,
+ u32_t offset);
+int spl_reg_res_txrx_mgr (mpool_handle * pool);
+int spl_reg_res_tx_mgr (mpool_handle * pool);
+
+/* release buf hold by app on abnormal exit */
+/*
+ *For TX mbuf: recycle_flg can be: MBUF_UNUSED, MBUF_HLD_BY_APP, MBUF_HLD_BY_SPL.
+ *For TX mbuf: recycle_flg can be: MBUF_UNSUED, app pid.
+ */
+static inline void
+pbuf_set_recycle_flg (struct spl_pbuf *p, uint32_t flg)
+{
+ uint32_t *recycle_flg;
+ struct spl_pbuf *q = p;
+ struct common_mem_mbuf *m;
+
+ while (q != NULL)
+ {
+ m =
+ (struct common_mem_mbuf *) ((char *) q -
+ sizeof (struct common_mem_mbuf));
+#ifdef HAL_LIB
+#else
+ recycle_flg =
+ (uint32_t *) ((char *) (m->buf_addr) + RTE_PKTMBUF_HEADROOM -
+ sizeof (uint32_t));
+#endif
+ *recycle_flg = flg;
+ q = (struct spl_pbuf *) ADDR_SHTOL (q->next_a);
+ }
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h b/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h
new file mode 100644
index 0000000..6a21312
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_pbuf_comm.h
@@ -0,0 +1,109 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_PBUF_COMM_H
+#define STACKX_PBUF_COMM_H
+#include "types.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define SPL_PBUF_TRANSPORT_HLEN 20
+#define SPL_PBUF_UDP_HLEN 8
+#define SPL_PBUF_IP_HLEN 20
+
+#define SPL_PBUF_VLAN_HLEN 0
+
+#ifndef SPL_PBUF_LINK_HLEN
+#define SPL_PBUF_LINK_HLEN (14 + SPL_PBUF_VLAN_HLEN)
+#endif
+
+typedef enum spl_pbuf_layer
+{
+ SPL_PBUF_TRANSPORT,
+ SPL_PBUF_UDP,
+ SPL_PBUF_IP,
+ SPL_PBUF_LINK,
+ SPL_PBUF_RAW,
+ SPL_PBUF_MAX_LAYER,
+} spl_pbuf_layer;
+
+typedef enum spl_pbuf_type
+{
+ SPL_PBUF_RAM, /* pbuf data is stored in RAM */
+ SPL_PBUF_ROM, /* pbuf data is stored in ROM */
+ SPL_PBUF_REF, /* pbuf comes from the pbuf pool */
+ SPL_PBUF_POOL, /* pbuf payload refers to RAM */
+ SPL_PBUF_HUGE /* pbuf is stored in HugePage memory in struct common_mem_mbuf */
+} spl_pbuf_type;
+
+enum spl_pbuf_proto
+{
+ SPL_PBUF_PROTO_NONE,
+ SPL_PBUF_TCP_SEND,
+ SPL_PBUF_TCP_RECV
+} spl_pbuf_proto;
+
+typedef struct spl_pbuf
+{
+ /** next pbuf in singly linked pbuf chain */
+ union
+ {
+ struct spl_pbuf *next;
+ u64 next_a;
+ };
+
+ /** pointer to the actual data in the buffer */
+ union
+ {
+ void *payload;
+ u64 payload_a;
+ };
+
+ union
+ {
+ void *msg;
+ u64 msg_a;
+ };
+
+ union
+ {
+ void *conn;
+ u64 conn_a;
+ };
+
+ struct spl_pbuf *freeNext; // This pointer will point to next pbuf you want to free in stackx
+
+ u32 tot_len;
+ u32 len;
+ int proto_type;
+ u16 ref;
+ u8 type;
+ u8 flags;
+ nsfw_res res_chk;
+
+} spl_pbuf;
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h b/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h
new file mode 100644
index 0000000..119c26a
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_msg.h
@@ -0,0 +1,239 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_SPL_MSG_H
+#define STACKX_SPL_MSG_H
+#include "nsfw_msg.h"
+#include "stackx_ip_addr.h"
+#include "stackx_spl_share.h"
+#include "stackx_common_opt.h"
+#include <sys/socket.h>
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+enum spl_tcpip_msg_type
+{
+ SPL_TCPIP_NEW_MSG_API,
+#if STACKX_TIMER_THREAD_SUPPORT
+ SPL_TCPIP_MSG_TIMER,
+#endif
+#if STACKX_NETIF_API
+ SPL_TCPIP_MSG_NETIFAPI,
+#endif
+ SPL_TCPIP_MSG_CALLBACK,
+ SPL_TCPIP_MSG_IP_MODULE,
+
+ SPL_TCPIP_MSG_MAX, //the number of enum
+ SPL_TCPIP_MSG_BOTTOM = MAX_MAJOR_TYPE //the max number of enum
+};
+
+enum api_msg_type
+{
+ SPL_API_DO_NEWCONN = 0,
+ SPL_API_DO_DELCON,
+ SPL_API_DO_RECV,
+ SPL_API_DO_GETADDR,
+ SPL_API_DO_BIND,
+ SPL_API_DO_CONNECT,
+ SPL_API_DO_LISTEN,
+ SPL_API_DO_CLOSE,
+ SPL_API_DO_SET_SOCK_OPT,
+ SPL_API_DO_GET_SOCK_OPT,
+ SPL_API_DO_SEND,
+ SPL_API_DO_WRITE,
+ SPL_API_DO_POST,
+ SPL_API_DO_SHOW,
+ SPL_API_DO_EXTREN_SOCK_SET,
+ SPL_API_DO_ENABLE_TRACE,
+ SPL_API_GET_PROTOCOL,
+ SPL_API_DO_IOCTL_OPT,
+ SPL_API_DO_GETSOCK_NAME,
+ SPL_API_DO_DUMP_L4,
+ SPL_API_DO_PBUF_FREE,
+ SPL_API_DO_APP_TOUCH, /* app send its version info to nStackMain */
+
+ SPL_API_MSG_MAX, //the number of enum
+ SPL_API_MSG_BOTTOM = MAX_MINOR_TYPE //the max number of enum
+};
+
+/* TODO: move thes to apporpriate file */
+#define TCP_RTO_MAX ((unsigned)(120*1000)) /* 120s */
+#define TCP_RTO_MIN ((unsigned)(200)) /* 200ms */
+
+#define TCP_TIMEOUT_INIT ((unsigned)(1*1000)) /* RFC6298 2.1 initial RTO value */
+#define CONN_TCP_MEM_MIN_LINE ((TX_MBUF_POOL_SIZE)/1024) //conn level : min value of send_buf
+#define CONN_TCP_MEM_DEF_LINE ((TX_MBUF_POOL_SIZE)/128) //conn level : default value of send_buf
+#define CONN_TCP_MEM_MAX_LINE ((TX_MBUF_POOL_SIZE)/12)
+
+#define SOF_DEBUG 0x01U
+#define SOF_ACCEPTCONN 0x02U
+#define SOF_DONTROUTE 0x10U
+#define SOF_USELOOPBACK 0x40U
+#define SOF_LINGER 0x80U
+#define SOF_OOBINLINE 0x0100U
+#define SOF_REUSEPORT 0x0200U
+
+/* General structure for calling APIs*/
+typedef struct api_param_t
+{
+ data_com_msg *m;
+ i64 comm_private_data;
+} api_param;
+
+/* SPL_API_DO_SEND */
+typedef struct
+{
+ PRIMARY_ADDR struct spl_pbuf *p;
+ spl_ip_addr_t local_ip;
+ spl_ip_addr_t addr;
+ spl_ip_addr_t srcAddr;
+ u16 port;
+ u16 srcPort;
+ u16 toport_chksum;
+ u8 tos;
+ u8 pad;
+ u8 flags;
+ i64 extend_member_bit;
+} msg_send_buf;
+
+/* SPL_API_DO_BIND */
+typedef struct
+{
+ spl_ip_addr_t ipaddr;
+ u16 port;
+ i64 extend_member_bit;
+} msg_bind;
+
+/* SPL_API_DO_CLOSE */
+typedef struct
+{
+ long time_started;
+ u8 shut;
+ i64 extend_member_bit;
+} msg_close;
+
+/* SPL_API_DO_CONNECT */
+typedef struct
+{
+ spl_ip_addr_t local_ip;
+ spl_ip_addr_t ipaddr;
+ u16 port;
+ i64 extend_member_bit;
+} msg_connect;
+
+/* SPL_API_DO_DELCON */
+typedef struct
+{
+ PRIMARY_ADDR struct spl_netconn *conn;
+ PRIMARY_ADDR struct spl_pbuf *buf;
+ long time_started;
+ pid_t pid;
+ u8 shut;
+ u8 msg_box_ref; /* use it for priority */
+ u8 notify_omc; /* bool */
+ i64 extend_member_bit;
+} msg_delete_netconn;
+
+/* SPL_API_DO_WRITE */
+typedef struct msg_write_buf_T
+{
+ PRIMARY_ADDR struct spl_pbuf *p;
+ struct msg_write_buf_T *next;
+ size_t len;
+ u8 apiflags;
+ i64 extend_member_bit;
+} msg_write_buf;
+
+/* SPL_API_DO_LISTEN */
+typedef struct
+{
+ mring_handle conn_pool;
+ u8 backlog;
+ i64 extend_member_bit;
+} msg_listen;
+
+/* SPL_API_DO_NEWCONN */
+typedef struct
+{
+ PRIMARY_ADDR struct spl_netconn *conn;
+ spl_netconn_type_t type;
+ u8 proto;
+ int socket;
+ i64 extend_member_bit;
+} msg_new_netconn;
+
+/* SPL_API_DO_RECV */
+typedef struct
+{
+ PRIMARY_ADDR struct spl_pbuf *p;
+ u32 len;
+ i64 extend_member_bit;
+} msg_recv_buf;
+
+/* SPL_API_DO_GETSOCK_NAME */
+typedef struct
+{
+ struct sockaddr sock_addr;
+ u8 cmd;
+ i64 extend_member_bit;
+} msg_getaddrname;
+
+/* SPL_API_DO_GET_SOCK_OPT,SPL_API_DO_SET_SOCK_OPT */
+typedef struct
+{
+ int level;
+ int optname;
+ PRIMARY_ADDR mring_handle msg_box; /* IP_TOS, spl will get new msg box for app */
+ union
+ {
+ int int_optval;
+ //struct in_addr inaddr_optval;
+ //struct linger _linger;
+ struct timeval timeval_optval;
+ //ipmreq ipmreq_optval; //Multicast support later
+ } optval;
+
+ u32 optlen;
+ i64 extend_member_bit;
+} msg_setgetsockopt;
+
+/* SPL_API_DO_PBUF_FREE */
+typedef struct
+{
+ PRIMARY_ADDR struct spl_pbuf *buf;
+ i64 extend_member_bit;
+} msg_free_buf;
+
+/* app send its version info to nStackMain */
+#define NSTACK_VERSION_LEN 128
+/* SPL_API_DO_APP_TOUCH */
+typedef struct
+{
+ u32_t hostpid;
+ char app_version[NSTACK_VERSION_LEN];
+} msg_app_touch;
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c
new file mode 100644
index 0000000..4fa91d8
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.c
@@ -0,0 +1,198 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "stackx_spl_msg.h"
+#include "stackx_spl_share.h"
+#include "nstack_log.h"
+#include "nsfw_msg_api.h"
+#include "nsfw_recycle_api.h"
+
+/*****************************************************************************
+* Prototype : ss_reset_conn_recycle
+* Description : reset conn recycle
+* Input : netconn_recycle* recycle
+* Output : None
+* Return Value : static inline void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_reset_conn_recycle (netconn_recycle * recycle)
+{
+ recycle->accept_from = NULL;
+ recycle->is_listen_conn = 0;
+ (void) nsfw_pidinfo_init (&recycle->pid_info);
+ recycle->fork_ref = 0;
+ recycle->delay_msg = NULL;
+ recycle->delay_flag = SS_DELAY_STOPPED;
+}
+
+/*****************************************************************************
+* Prototype : ss_reset_conn
+* Description : reset conn
+* Input : spl_netconn_t* conn
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+ss_reset_conn (spl_netconn_t * conn)
+{
+ conn->recv_obj = 0;
+ conn->private_data = 0;
+ conn->msg_box = NULL;
+ conn->snd_buf = 0;
+ conn->epoll_flag = 0;
+ conn->recv_avail_prod = 0;
+ conn->recv_avail_cons = 0;
+ conn->rcvevent = 0;
+ conn->state = SPL_NETCONN_NONE;
+ conn->sendevent = 0;
+ conn->errevent = 0;
+ conn->shut_status = 0xFFFF;
+ conn->flags = 0;
+ conn->last_err = 0;
+ conn->CanNotReceive = 0;
+ conn->bind_thread_index = 0;
+ conn->tcp_sndbuf = 0;
+ conn->tcp_wmem_alloc_cnt = 0;
+ conn->tcp_wmem_sbr_free_cnt = 0;
+ conn->tcp_wmem_spl_free_cnt = 0;
+ conn->mss = 0;
+ conn->remote_port = 0;
+ conn->remote_ip.addr = 0;
+ conn->local_ip.addr = 0;
+ conn->local_port = 0;
+ conn->type = SPL_NETCONN_INVALID;
+ conn->tcp_state = SPL_CLOSED;
+ ss_reset_conn_recycle (&conn->recycle);
+ conn->extend_member_bit = 0;
+ conn->epInfo = NULL;
+}
+
+/*****************************************************************************
+* Prototype : ss_init_conn
+* Description : init conn
+* Input : spl_netconn_t* conn
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+static inline void
+ss_init_conn (spl_netconn_t * conn, mring_handle pool,
+ spl_netconn_type_t type)
+{
+ res_alloc (&conn->res_chk);
+
+ conn->type = type;
+ conn->recycle.fork_ref = 1;
+ conn->recv_ring_valid = 1;
+ sys_sem_init (&conn->close_completed);
+ NSSBR_LOGINF ("malloc conn ok]conn=%p,pool=%p", conn, pool);
+}
+
+/*****************************************************************************
+* Prototype : ss_malloc_conn
+* Description : malloc conn, only used in spl
+* Input : mring_handle pool
+* netconn_type_t type
+* Output : None
+* Return Value : spl_netconn_t*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+spl_netconn_t *
+ss_malloc_conn (mring_handle pool, spl_netconn_type_t type)
+{
+ spl_netconn_t *conn = NULL;
+
+ if (nsfw_mem_ring_dequeue (pool, (void **) &conn) != 1)
+ {
+ NSSBR_LOGERR ("malloc conn failed");
+ return NULL;
+ }
+
+ ss_init_conn (conn, pool, type);
+ return conn;
+}
+
+/*****************************************************************************
+* Prototype : ss_malloc_conn_app
+* Description : malloc conn, only used in app
+* Input : mring_handle pool
+* netconn_type_t type
+* Output : None
+* Return Value : spl_netconn_t*
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+spl_netconn_t *
+ss_malloc_conn_app (mring_handle pool, spl_netconn_type_t type)
+{
+ spl_netconn_t *conn = NULL;
+
+ if (nsfw_mem_ring_dequeue (pool, (void **) &conn) != 1)
+ {
+ NSSBR_LOGERR ("malloc conn failed");
+ return NULL;
+ }
+
+ if (ss_add_pid (conn, get_sys_pid ()) < 0)
+ {
+ NSSBR_LOGERR ("ss_add_pid failed]conn=%p", conn);
+ }
+
+ ss_init_conn (conn, pool, type);
+ return conn;
+}
+
+/*****************************************************************************
+* Prototype : ss_free_conn
+* Description : free conn
+* Input : spl_netconn_t* conn
+* mring_handle pool
+* Output : None
+* Return Value : void
+* Calls :
+* Called By :
+*
+*****************************************************************************/
+void
+ss_free_conn (spl_netconn_t * conn)
+{
+ ss_reset_conn (conn);
+
+ if (res_free (&conn->res_chk))
+ {
+ NSFW_LOGERR ("conn refree!]conn=%p", conn);
+ return;
+ }
+
+ mring_handle pool = ss_get_conn_pool (conn);
+ if (nsfw_mem_ring_enqueue (pool, (void *) conn) != 1)
+ {
+ NSSBR_LOGERR ("nsfw_mem_ring_enqueue failed,this can not happen");
+ }
+
+ NSSBR_LOGINF ("free conn ok]conn=%p,pool=%p", conn, pool);
+}
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h
new file mode 100644
index 0000000..3b0c9f9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_spl_share.h
@@ -0,0 +1,478 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_SPL_SHARE_H
+#define STACKX_SPL_SHARE_H
+#include "types.h"
+#include "common_mem_api.h"
+#include "nsfw_mem_api.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_ip_addr.h"
+#include <sys/types.h>
+#include "spl_opt.h"
+#include "stackx_ip_tos.h"
+#include "stackx_common_opt.h"
+#include "stackx_tx_box.h"
+#include "pidinfo.h"
+//#include "stackx_dfx_api.h"
+#include "compiling_check.h"
+#include "nsfw_msg.h"
+#include "stackx_spl_msg.h"
+#include "hal_api.h"
+#include "stackx_types.h"
+#include <errno.h>
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define MSG_PRIO_QUEUE_NUM 3
+COMPAT_PROTECT (MSG_PRIO_QUEUE_NUM, 3);
+
+#define SPL_MSG_BOX_NUM (MSG_PRIO_QUEUE_NUM + 1)
+
+#define SBR_FD_NETCONN_SIZE (256 * 3)
+COMPAT_PROTECT (SBR_FD_NETCONN_SIZE, 256 * 3);
+
+#define SS_NETCONN_SIZE (256 * 2)
+#define SBR_FD_SIZE (SBR_FD_NETCONN_SIZE - SS_NETCONN_SIZE)
+
+typedef struct
+{
+ PRIMARY_ADDR mring_handle msg_pool;
+ PRIMARY_ADDR mring_handle conn_pool;
+ PRIMARY_ADDR struct spl_netconn **conn_array;
+ u32 conn_num;
+ i64 extend_member_bit;
+} sbr_recycle_group;
+
+typedef enum
+{
+ SS_DELAY_STARTED,
+ SS_DELAY_STOPPING,
+ SS_DELAY_STOPPED,
+ SS_DELAY_AGAIN
+} ss_delay_flag;
+
+typedef enum
+{
+ NORMAL_RECV_RING = 0,
+ CUSTOM_RECV_RING = 1,
+} recv_ring_type;
+
+typedef struct
+{
+ PRIMARY_ADDR sbr_recycle_group *group;
+ PRIMARY_ADDR struct spl_netconn *accept_from; /* for recycle fd in listen */
+ void *delay_msg;
+ nsfw_pidinfo pid_info;
+ volatile i16 fork_ref;
+ i8 is_listen_conn;
+ i8 delay_flag;
+} netconn_recycle;
+
+typedef struct spl_netconn
+{
+ i64 recv_obj;
+ i64 comm_pcb_data; /* only used by spl */
+ i64 private_data; /* only used by spl */
+ PRIMARY_ADDR mring_handle msg_box;
+ PRIMARY_ADDR mring_handle recv_ring;
+ volatile u32 snd_buf;
+ volatile i32 epoll_flag;
+ /*here using prod/cons to instead recv_avail, avoid atomic oper. */
+ volatile u32_t recv_avail_prod; /*the product of recv_avail */
+ volatile u32_t recv_avail_cons; /*the consume of recv_avail */
+ volatile i32 rcvevent;
+ spl_netconn_state_t state;
+ u16 sendevent;
+ u16 errevent;
+ volatile u16 shut_status;
+ u8 flags;
+ i8 last_err;
+ u8 CanNotReceive;
+ u8 recv_ring_valid;
+ u16 bind_thread_index;
+ u16 mss;
+ sys_sem_st close_completed;
+ mring_handle conn_pool; /* where the conn in pcb is from */
+
+ void *epInfo;
+
+ /* The following shared field access rules: protocol stack process
+ * is responsible for writing, socket api process read only
+ */
+ i32 send_bufsize;
+ i32 tcp_sndbuf;
+ u32 tcp_wmem_alloc_cnt;
+ u32 tcp_wmem_sbr_free_cnt;
+ volatile u32 tcp_wmem_spl_free_cnt;
+ u16 remote_port;
+ u16 local_port;
+ spl_ip_addr_t remote_ip;
+ spl_ip_addr_t local_ip;
+ spl_netconn_type_t type;
+ spl_tcp_state_t tcp_state;
+
+ /* for recycle */
+ netconn_recycle recycle;
+ nsfw_res res_chk;
+ i64 extend_member_bit;
+} spl_netconn_t; /* sizeof(spl_netconn_t) need < SS_NETCONN_SIZE */
+SIZE_OF_TYPE_PLUS8_NOT_LARGER_THAN (spl_netconn_t, SS_NETCONN_SIZE);
+
+typedef struct
+{
+ /**
+ * it will increase after every restart which used for
+ * tell different runnings.
+ */
+ u32 running_ref_no;
+
+ /* only increased when fault to restart */
+ u32 fault_ref_no;
+
+ /* the procedures before upgrade are finished successfully */
+ u32 prepare_upgrade_done;
+
+} spl_init_info_t;
+
+typedef struct netifExt
+{
+ struct netifExt *next;
+ u16_t id;
+ char if_name[HAL_MAX_NIC_NAME_LEN];
+ hal_hdl_t hdl;
+ u16_t num_packets_recv;
+} netifExt;
+
+static inline mring_handle
+ss_get_msg_pool (spl_netconn_t * sh)
+{
+ sbr_recycle_group *group =
+ (sbr_recycle_group *) ADDR_SHTOL (sh->recycle.group);
+ return ADDR_SHTOL (group->msg_pool);
+}
+
+static inline mring_handle
+ss_get_conn_pool (spl_netconn_t * sh)
+{
+ sbr_recycle_group *group =
+ (sbr_recycle_group *) ADDR_SHTOL (sh->recycle.group);
+ return ADDR_SHTOL (group->conn_pool);
+}
+
+static inline int
+ss_is_nonblock_flag (spl_netconn_t * sh)
+{
+ return (sh->flags & SPL_NETCONN_FLAG_NON_BLOCKING) != 0;
+}
+
+static inline int
+ss_get_nonblock_flag (spl_netconn_t * sh)
+{
+ return ss_is_nonblock_flag (sh) ? O_NONBLOCK : 0;
+}
+
+static inline void
+ss_set_nonblock_flag (spl_netconn_t * sh, u32 flag)
+{
+ if (flag)
+ {
+ sh->flags |= SPL_NETCONN_FLAG_NON_BLOCKING;
+ }
+ else
+ {
+ sh->flags &= ~SPL_NETCONN_FLAG_NON_BLOCKING;
+ }
+}
+
+static inline int
+ss_get_last_errno (spl_netconn_t * sh)
+{
+ return sh->last_err;
+}
+
+static inline i32
+ss_get_recv_event (spl_netconn_t * sh)
+{
+ return sh->rcvevent;
+}
+
+static inline int
+ss_can_not_recv (spl_netconn_t * sh)
+{
+ return sh->CanNotReceive;
+}
+
+static inline int
+ss_is_shut_rd (spl_netconn_t * sh)
+{
+ int status = sh->shut_status;
+ return ((SPL_SHUT_RD == status) || (SPL_SHUT_RDWR == status));
+}
+
+static inline void
+ss_set_shut_status (spl_netconn_t * sh, u16 how)
+{
+ sh->shut_status = how;
+}
+
+static inline u16
+ss_get_shut_status (spl_netconn_t * sh)
+{
+ return sh->shut_status;
+}
+
+static inline void
+ss_sub_recv_event (spl_netconn_t * sh)
+{
+ __sync_fetch_and_sub (&sh->rcvevent, 1);
+}
+
+static inline void
+ss_add_recv_event (spl_netconn_t * sh)
+{
+ __sync_fetch_and_add (&sh->rcvevent, 1);
+}
+
+static inline i64
+ss_get_recv_obj (spl_netconn_t * sh)
+{
+ return sh->recv_obj;
+}
+
+static inline i64
+ss_get_private_data (spl_netconn_t * sh)
+{
+ return sh->private_data;
+}
+
+static inline i64
+ss_get_comm_private_data (spl_netconn_t * sh)
+{
+ return sh->comm_pcb_data;
+}
+
+static inline int
+ss_recv_ring_valid (spl_netconn_t * sh)
+{
+ return sh->recv_ring_valid;
+}
+
+static inline mring_handle
+ss_get_recv_ring (spl_netconn_t * sh)
+{
+ return (mring_handle) ADDR_SHTOL (sh->recv_ring);
+}
+
+static inline void
+ss_set_send_event (spl_netconn_t * sh, u16 value)
+{
+ sh->sendevent = value;
+}
+
+static inline int
+ss_is_noautorecved_flag (spl_netconn_t * sh)
+{
+ return (sh->flags & SPL_NETCONN_FLAG_NO_AUTO_RECVED) != 0;
+}
+
+static inline int
+ss_get_noautorecved_flag (spl_netconn_t * sh)
+{
+ return ss_is_noautorecved_flag (sh) ? SPL_NETCONN_FLAG_NO_AUTO_RECVED : 0;
+}
+
+static inline void
+ss_set_noautorecved_flag (spl_netconn_t * sh, u8 flag)
+{
+ if (flag)
+ {
+ sh->flags |= SPL_NETCONN_FLAG_NO_AUTO_RECVED;
+ }
+ else
+ {
+ sh->flags &= ~SPL_NETCONN_FLAG_NO_AUTO_RECVED;
+ }
+}
+
+static inline void
+ss_set_state (spl_netconn_t * sh, spl_netconn_state_t state)
+{
+ sh->state = state;
+}
+
+static inline int
+ss_is_write_state (spl_netconn_t * sh)
+{
+ return (SPL_NETCONN_WRITE == sh->state);
+}
+
+static inline int
+ss_is_listen_state (spl_netconn_t * sh)
+{
+ return (SPL_NETCONN_LISTEN == sh->state);
+}
+
+static inline void
+ss_sub_recv_avail (spl_netconn_t * sh, int value)
+{
+ sh->recv_avail_cons += value;
+}
+
+static inline i32
+ss_get_recv_avail (spl_netconn_t * sh)
+{
+ return sh->recv_avail_prod - sh->recv_avail_cons;
+}
+
+static inline u16
+ss_get_mss (spl_netconn_t * sh)
+{
+ return sh->mss;
+}
+
+static inline spl_ip_addr_t *
+ss_get_remote_ip (spl_netconn_t * sh)
+{
+ return &(sh->remote_ip);
+}
+
+static inline u16
+ss_get_remote_port (spl_netconn_t * sh)
+{
+ return sh->remote_port;
+}
+
+static inline spl_tcp_state_t
+ss_get_tcp_state (spl_netconn_t * sh)
+{
+ return sh->tcp_state;
+}
+
+static inline u16
+ss_get_bind_thread_index (spl_netconn_t * sh)
+{
+ return sh->bind_thread_index;
+}
+
+static inline void
+ss_set_bind_thread_index (spl_netconn_t * sh, u16 bind_thread_index)
+{
+ sh->bind_thread_index = bind_thread_index;
+}
+
+static inline void
+ss_set_msg_box (spl_netconn_t * sh, mring_handle box)
+{
+ sh->msg_box = (mring_handle) ADDR_LTOSH (box);
+}
+
+static inline mring_handle
+ss_get_msg_box (spl_netconn_t * sh)
+{
+ return (mring_handle) ADDR_SHTOL (sh->msg_box);
+}
+
+static inline spl_ip_addr_t *
+ss_get_local_ip (spl_netconn_t * sh)
+{
+ return &sh->local_ip;
+}
+
+static inline void
+ss_set_local_ip (spl_netconn_t * sh, u32 addr)
+{
+ if (!sh)
+ {
+ return;
+ }
+ sh->local_ip.addr = addr;
+}
+
+static inline u16
+ss_get_local_port (spl_netconn_t * sh)
+{
+ return sh->local_port;
+}
+
+static inline void
+ss_set_local_port (spl_netconn_t * sh, u16 local_port)
+{
+ sh->local_port = local_port;
+}
+
+static inline void
+ss_set_accept_from (spl_netconn_t * sh, spl_netconn_t * accept_from)
+{
+ sh->recycle.accept_from = accept_from;
+}
+
+static inline void
+ss_set_is_listen_conn (spl_netconn_t * sh, i8 is_listen_conn)
+{
+ sh->recycle.is_listen_conn = is_listen_conn;
+}
+
+static inline i32
+ss_dec_fork_ref (spl_netconn_t * sh)
+{
+ return __sync_sub_and_fetch (&sh->recycle.fork_ref, 1);
+}
+
+static inline int
+ss_add_pid (spl_netconn_t * sh, pid_t pid)
+{
+ return nsfw_add_pid (&sh->recycle.pid_info, pid);
+}
+
+static inline int
+ss_del_pid (spl_netconn_t * sh, pid_t pid)
+{
+ return nsfw_del_pid (&sh->recycle.pid_info, pid);
+}
+
+static inline int
+ss_is_pid_exist (spl_netconn_t * sh, pid_t pid)
+{
+ return nsfw_pid_exist (&sh->recycle.pid_info, pid);
+}
+
+static inline int
+ss_is_pid_array_empty (spl_netconn_t * sh)
+{
+ return nsfw_pidinfo_empty (&sh->recycle.pid_info);
+}
+
+spl_netconn_t *ss_malloc_conn (mring_handle pool, spl_netconn_type_t type);
+spl_netconn_t *ss_malloc_conn_app (mring_handle pool,
+ spl_netconn_type_t type);
+void ss_free_conn (spl_netconn_t * conn);
+void ss_reset_conn (spl_netconn_t * conn);
+
+typedef void (*ss_close_conn_fun) (void *close_data, u32 delay_sec);
+int ss_recycle_conn (void *close_data, ss_close_conn_fun close_conn);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h b/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h
new file mode 100644
index 0000000..cac3dcb
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_tcp_opt.h
@@ -0,0 +1,42 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_TCP_OPT_H__
+#define __STACKX_TCP_OPT_H__
+
+#include "spl_opt.h"
+
+/* TCP Options flags */
+#define TF_ACK_DELAY ((u32_t)0x01U) /* Delayed ACK. */
+#define TF_ACK_NOW ((u32_t)0x02U) /* Immediate ACK. */
+#define TF_WINDOWSCALING ((u32_t)0x40U) /* Window scaling option enabled */
+#define TF_INFR ((u32_t)0x04U) /* In fast recovery. */
+#define TF_TIMESTAMP ((u32_t)0x08U) /* Timestamp option enabled */
+#define TF_RXCLOSED ((u32_t)0x10U) /* rx closed by tcp_shutdown */
+#define TF_FIN ((u32_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */
+#define TF_NODELAY ((u32_t)0x100U) /* Disable Nagle algorithm */
+#define TF_NAGLEMEMERR ((u32_t)0x80U)
+
+/* TCP segment Options flags */
+#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
+#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
+#define TF_SEG_OPTS_WS (u8_t)0x08U /* Include window scaling option. */
+
+#define STACKX_TCP_OPT_LENGTH(flags) \
+ (flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
+ (flags & TF_SEG_OPTS_TS ? 12 : 0) + \
+ (flags & TF_SEG_OPTS_WS ? 4 : 0)
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c
new file mode 100644
index 0000000..74673ad
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.c
@@ -0,0 +1,64 @@
+/*
+*
+* 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 "stackxopts.h"
+#include "nstack_log.h"
+#include "stackx_tx_box.h"
+#include "nsfw_mt_config.h"
+
+#define MZ_STACKX_RING_NAME "VppTCP_Ring"
+#define MZ_STACKX_PRIORITY_RING_NAME "VppTCP_Priority%u_Ring"
+
+/*
+ * Given the stackx ring name template above, get the queue name
+ */
+const char *
+get_stackx_ring_name ()
+{
+ /* buffer for return value. Size calculated by %u being replaced
+ * by maximum 3 digits (plus an extra byte for safety) */
+ static char rbuffer[sizeof (MZ_STACKX_RING_NAME) + 16];
+
+ int retVal =
+ spl_snprintf (rbuffer, sizeof (rbuffer) - 1, MZ_STACKX_RING_NAME);
+
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return rbuffer;
+}
+
+const char *
+get_stackx_priority_ring_name (unsigned priority)
+{
+ /* buffer for return value. Size calculated by %u being replaced
+ * by maximum 3 digits (plus an extra byte for safety) */
+ static char prbuffer[sizeof (MZ_STACKX_PRIORITY_RING_NAME) + 32];
+
+ int retVal = spl_snprintf (prbuffer, sizeof (prbuffer) - 1,
+ MZ_STACKX_PRIORITY_RING_NAME, priority);
+
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return prbuffer;
+}
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h
new file mode 100644
index 0000000..edfba5c
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_tx_box.h
@@ -0,0 +1,39 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_TX_BOX_H
+#define STACKX_TX_BOX_H
+#include "sys/types.h"
+#include "nsfw_mem_api.h"
+#include "stackx_common.h"
+#include "nsfw_mt_config.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+const char *get_stackx_ring_name ();
+const char *get_stackx_priority_ring_name (unsigned priority);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackx_types.h b/stacks/lwip_stack/lwip_src/common/stackx_types.h
new file mode 100644
index 0000000..6c78a20
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackx_types.h
@@ -0,0 +1,68 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_TYPES_H
+#define STACKX_TYPES_H
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if 1
+#ifndef STACKX_MAX_S16_NUM
+#define STACKX_MAX_S16_NUM ((s16_t)0x7fff)
+#endif
+
+#ifndef STACKX_MAX_U16_NUM
+#define STACKX_MAX_U16_NUM ((u16_t)0xFfff)
+#endif
+
+#ifndef STACKX_MAX_U32_NUM
+#define STACKX_MAX_U32_NUM ((u32_t)0xffffffff)
+#endif
+
+#ifndef STACKX_MAX_S32_NUM
+#define STACKX_MAX_S32_NUM ((s32_t)0x7fffffff)
+#endif
+
+#ifndef STACKX_MAX_U64_NUM
+#define STACKX_MAX_U64_NUM ((u64_t)0xffffffffffffffff)
+#endif
+
+#ifndef STACKX_MAX_S64_NUM
+#define STACKX_MAX_S64_NUM ((s64_t)0x7fffffffffffffff)
+#endif
+#endif
+
+#if 1
+typedef uint64_t u64_t;
+typedef int64_t s64_t;
+
+typedef uint32_t u32_t;
+typedef int32_t s32_t;
+
+typedef uint16_t u16_t;
+typedef int16_t s16_t;
+
+typedef uint8_t u8_t;
+typedef int8_t s8_t;
+
+typedef uintptr_t mem_ptr_t;
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/common/stackxopts.h b/stacks/lwip_stack/lwip_src/common/stackxopts.h
new file mode 100644
index 0000000..15fc6b8
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/common/stackxopts.h
@@ -0,0 +1,53 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef STACKX_OPTS_H
+#define STACKX_OPTS_H
+
+struct memory_statics
+{
+ char name[120];
+ long size;
+};
+
+extern u32 g_type;
+extern struct memory_statics memory_used_size[80];
+
+#define DPDK_MEMORY_COUNT(memory, len)\
+{\
+ if (g_type < MAX_MEMORY_USED_SIZE)\
+ {\
+ const char * ptr_memory = memory;\
+ if (ptr_memory && EOK != STRCPY_S(memory_used_size[g_type].name, sizeof(memory_used_size[g_type].name), ptr_memory))\
+ {\
+ NSPOL_LOGERR("STRCPY_S failed.");\
+ }\
+ memory_used_size[g_type].size =(long) len;\
+ g_type++;\
+ }\
+}
+
+#define SPL_MAX_UDP_MSG_LEN (0xFFFF -28)
+#define RECV_MAX_POOL 4
+#define MAX_TRY_GET_MEMORY_TIMES 4
+#define MAX_MEMORY_USED_SIZE 80
+#define SPL_IP_HLEN 20
+#define SPL_TCP_HLEN 20
+#define SPL_TCP_MAX_OPTION_LEN 40
+#define SPL_FRAME_MTU 1500
+#define SPL_TCP_SEND_MAX_SEG_PER_MSG 5
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/core/global_tick.c b/stacks/lwip_stack/lwip_src/core/global_tick.c
new file mode 100644
index 0000000..ee180c9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/global_tick.c
@@ -0,0 +1,48 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "nsfw_mem_api.h"
+#include "nstack_share_res.h"
+#include "nstack_securec.h"
+
+extern nstack_tick_info_t g_nstack_timer_tick;
+
+int
+init_stackx_global_tick (void)
+{
+ nsfw_mem_zone mzone;
+
+ if (STRCPY_S
+ (mzone.stname.aname, NSFW_MEM_NAME_LENGTH, NSTACK_GLOBAL_TICK_SHM) != 0)
+ {
+ NSPOL_LOGERR ("STRCPY_S fail");
+ return -1;
+ }
+
+ mzone.stname.entype = NSFW_SHMEM;
+ mzone.isocket_id = -1;
+ mzone.length = sizeof (uint64_t);
+ mzone.ireserv = 0;
+
+ g_nstack_timer_tick.tick_ptr = (uint64_t *) nsfw_mem_zone_create (&mzone);
+ if (NULL == g_nstack_timer_tick.tick_ptr)
+ {
+ NSPOL_LOGERR ("Failed to create global timer tick memory");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/stacks/lwip_stack/lwip_src/core/spl_pbuf.c b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c
new file mode 100644
index 0000000..03e30ed
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c
@@ -0,0 +1,597 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "spl_opt.h"
+
+#include "spl_def.h"
+#include "spl_pbuf.h"
+#include "stackx_pbuf.h"
+
+#include "stackx_spl_share.h"
+#include "spl_api.h"
+
+#include "nsfw_maintain_api.h"
+#include "netif/sc_dpdk.h"
+#include <common_mem_mbuf.h>
+
+#include <string.h>
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "spl_instance.h"
+
+#include "sys.h"
+#include "mem.h"
+#include "memp.h"
+//#include "sockets.h"
+//#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct spl_pbuf))
+u16_t g_offSetArry[SPL_PBUF_MAX_LAYER];
+
+u16_t g_offSetArry[SPL_PBUF_MAX_LAYER] =
+ { PBUF_TRANSPORT_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN,
+ SPL_PBUF_UDP_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN,
+ PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN,
+ SPL_PBUF_LINK_HLEN,
+ 0
+};
+
+inline struct spl_pbuf *
+spl_pbuf_alloc_hugepage (spl_pbuf_layer layer, u16_t length,
+ spl_pbuf_type Type, u16_t proc_id, void *net_conn)
+{
+ struct spl_pbuf *p;
+ u16_t offset;
+ u16_t count = 0;
+ spl_netconn_t *conn = (spl_netconn_t *) net_conn;
+
+ NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE,
+ "spl_pbuf_alloc_hugepage]length=%" U16_F, length);
+
+ /* determine header offset */
+ if (likely (layer < SPL_PBUF_MAX_LAYER))
+ {
+ offset = g_offSetArry[layer];
+ }
+ else
+ {
+ NSPOL_LOGERR ("spl_pbuf_alloc_hugepage: bad pbuf layer");
+ return NULL;
+ }
+
+ if (unlikely (length < offset || Type != SPL_PBUF_HUGE))
+ {
+ NSPOL_LOGERR ("input is invalid!]length=%u, Type = %d", length, Type);
+ return NULL;
+ }
+
+ p = spl_mbuf_malloc (length, SPL_PBUF_HUGE, &count);
+
+ if (p == NULL)
+ {
+ /* last_log_prt_time and unprint_log_count indeed have multi-thread issue,
+ * but their values don't have precision requirement. No risk. */
+ NS_LOG_CTRL (LOG_CTRL_HUGEPAGE_ALLOC_FAIL, STACKX, "NSPOL", NSLOG_ERR,
+ "pbuf_alloc_huge: Could not allocate PBUF for SPL_PBUF_HUGE");
+
+ return NULL;
+ }
+
+ if (conn)
+ {
+ p->conn_a = ADDR_LTOSH (conn);
+ }
+ else
+ {
+ p->conn_a = 0;
+ }
+
+ p->tot_len -= offset;
+ p->len -= offset;
+ p->next_a = 0;
+
+ p->payload_a = p->payload_a + offset;
+
+ p->proto_type = SPL_PBUF_PROTO_NONE;
+
+ NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE,
+ "pbuf_alloc]length=%" U16_F ",p=%p", length, (void *) p);
+ return p;
+}
+
+inline int
+spl_pbuf_internal_copy (struct spl_pbuf *dst, struct spl_pbuf *src)
+{
+ u32_t dst_len = dst->len;
+ u32_t src_len = src->len;
+ u32_t dst_pos = 0;
+ u32_t src_pos = 0;
+ while (dst != NULL && src != NULL)
+ {
+ if (dst_len > src_len)
+ {
+ if (NULL ==
+ common_memcpy (PTR_SHTOL (char *, dst->payload_a) + dst_pos,
+ PTR_SHTOL (char *, src->payload_a) + src_pos,
+ src_len))
+ {
+ NSPOL_LOGERR ("rte_memcpy error");
+ return -1;
+ }
+
+ dst_len -= src_len;
+ dst_pos += src_len;
+ src = ADDR_SHTOL (src->next_a);
+ src_len = src != NULL ? src->len : 0;
+ src_pos = 0;
+ }
+ else if (dst_len < src_len)
+ {
+ if (NULL ==
+ common_memcpy (PTR_SHTOL (char *, dst->payload_a) + dst_pos,
+ PTR_SHTOL (char *, src->payload_a) + src_pos,
+ dst_len))
+ {
+ NSPOL_LOGERR ("rte_memcpy error");
+ return -1;
+ }
+
+ src_len -= dst_len;
+ src_pos += dst_len;
+ dst = ADDR_SHTOL (dst->next_a);
+ dst_len = dst != NULL ? dst->len : 0;
+ dst_pos = 0;
+ }
+ else
+ {
+ if (NULL ==
+ common_memcpy (PTR_SHTOL (char *, dst->payload_a) + dst_pos,
+ PTR_SHTOL (char *, src->payload_a) + src_pos,
+ dst_len))
+ {
+ NSPOL_LOGERR ("rte_memcpy error");
+ return -1;
+ }
+
+ src = ADDR_SHTOL (src->next_a);
+ src_len = src != NULL ? src->len : 0;
+ src_pos = 0;
+ dst = ADDR_SHTOL (dst->next_a);
+ dst_len = dst != NULL ? dst->len : 0;
+ dst_pos = 0;
+ }
+ }
+ return 0;
+}
+
+void
+spl_pbuf_realloc (struct spl_pbuf *p, u32_t new_len)
+{
+ if (NULL != p && p->type == SPL_PBUF_HUGE)
+ {
+ p->tot_len = new_len;
+ p->len = new_len;
+ return;
+ }
+}
+
+void
+spl_pbuf_free (struct spl_pbuf *p)
+{
+ struct spl_pbuf *q;
+ u8_t count = 0;
+
+ NSPOL_LOGINF (PBUF_DEBUG, "Freeing PBF %p", p);
+
+ if (unlikely (p == NULL || p->type != SPL_PBUF_HUGE))
+ {
+ NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_LEVEL_SERIOUS,
+ "input param illegal]p=%p, type=%d", p, p ? p->type : -1);
+ return;
+ }
+
+ (void) count;
+
+ /* de-allocate all consecutive pbufs from the head of the chain that
+ * obtain a zero reference count after decrementing*/
+ do
+ {
+ /* remember next pbuf in chain for next iteration */
+ NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE,
+ "spl_pbuf_free: deallocating]buf=%p", (void *) p);
+ q = (struct spl_pbuf *) ADDR_SHTOL (p->next_a);
+ if (res_free (&p->res_chk))
+ {
+ //NSPOL_LOGERR("res_free failed]p=%p", p);
+ }
+
+ count++;
+ {
+ pbuf_set_recycle_flg (p, MBUF_UNUSED); /* release buf hold by app on abnormal exit */
+ spl_mbuf_free ((char *) p - sizeof (struct common_mem_mbuf));
+ p->res_chk.u8Reserve |= PBUF_FREE_FLAG;
+ }
+
+ /* proceed to next pbuf */
+ p = q;
+ }
+ while (p != NULL);
+
+ /* return number of de-allocated pbufs */
+ return;
+}
+
+void
+spl_pbuf_cat (struct spl_pbuf *h, struct spl_pbuf *t)
+{
+ struct spl_pbuf *p;
+
+ if (h == NULL || t == NULL)
+ {
+ NSPOL_LOGERR ("pbuf_cat: h=NULL||t=NULL!!");
+ return;
+ }
+
+ for (p = h; p->next_a != 0; p = PTR_SHTOL (struct spl_pbuf *, p->next_a))
+ {
+ /* add total length of second chain to all totals of first chain */
+ p->tot_len += t->tot_len;
+ }
+
+ if (0 != p->next_a)
+ {
+ NSPOL_LOGERR
+ ("pbuf_cat: p is not the last pbuf of the first chain, p->next_a != 0");
+ return;
+ }
+
+ /* add total length of second chain to last pbuf total of first chain */
+ p->tot_len += t->tot_len;
+
+ /* chain last pbuf of head (p) with first of tail (t) */
+ p->next_a = (uint64_t) ADDR_LTOSH_EXT (t);
+
+ /* p->next now references t, but the caller will drop its reference to t,
+ * so netto there is no change to the reference count of t.
+ */
+}
+
+err_t
+spl_pbuf_copy (struct spl_pbuf * p_to, struct spl_pbuf * p_from)
+{
+ u32_t offset_to = 0;
+ u32_t offset_from = 0;
+ u32_t len = 0;
+ NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE, "pbuf_copy]p_to=%p,p_from=%p",
+ (void *) p_to, (void *) p_from);
+
+ if (!
+ ((p_to != NULL) && (p_from != NULL)
+ && (p_to->tot_len >= p_from->tot_len)))
+ {
+ NSPOL_LOGERR ("pbuf_copy: target not big enough to hold source");
+ return ERR_ARG;
+ }
+
+ do
+ {
+ if (p_to == NULL)
+ {
+ NSPOL_LOGERR ("pbuf_copy: target pbuf not exist: p_to == NULL!!");
+ return ERR_ARG;
+ }
+
+ if ((p_to->len - offset_to) >= (p_from->len - offset_from))
+ {
+
+ len = p_from->len - offset_from;
+ }
+ else
+ {
+
+ len = p_to->len - offset_to;
+ }
+
+ if (EOK !=
+ MEMMOVE_S ((u8_t *) ADDR_SHTOL (p_to->payload_a) + offset_to, len,
+ (u8_t *) ADDR_SHTOL (p_from->payload_a) + offset_from,
+ len))
+ {
+ NSPOL_LOGERR ("MEMMOVE_S failed");
+ return ERR_MEM;
+ }
+
+ offset_to += len;
+ offset_from += len;
+ if (offset_to > p_to->len)
+ {
+ NSPOL_LOGERR
+ ("pbuf_copy: target offset not match: offset_to > p_to->len.");
+ return ERR_VAL;
+ }
+ if (offset_to == p_to->len)
+ {
+ offset_to = 0;
+ p_to = (struct spl_pbuf *) ADDR_SHTOL (p_to->next_a);
+ }
+
+ if (offset_from >= p_from->len)
+ {
+ /* on to next p_from (if any) */
+ NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE,
+ "pbuf_copy: source offset not match: offset_from >= p_from->len");
+ offset_from = 0;
+ p_from = (struct spl_pbuf *) ADDR_SHTOL (p_from->next_a);
+ }
+
+ if ((p_from != NULL) && (p_from->len == p_from->tot_len))
+ {
+ if ((p_from->next_a != 0))
+ {
+ NSPOL_LOGERR ("pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+
+ if ((p_to != NULL) && (p_to->len == p_to->tot_len))
+ {
+ /* don't copy more than one packet! */
+ if ((p_to->next_a != 0))
+ {
+ NSPOL_LOGERR ("pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+ }
+ while (p_from);
+
+ NSPOL_LOGDBG (PBUF_DEBUG | STACKX_DBG_TRACE,
+ "pbuf_copy: end of chain reached.");
+ return ERR_OK;
+}
+
+err_t
+splpbuf_to_pbuf_copy (struct pbuf * p_to, struct spl_pbuf * p_from)
+{
+ u32_t offset_to = 0;
+ u32_t offset_from = 0;
+ u32_t len = 0;
+
+ NSPOL_LOGINF (NETIF_DEBUG, "splpbuf_to_pbuf_copy");
+
+ if (!
+ ((p_to != NULL) && (p_from != NULL)
+ && (p_to->tot_len >= p_from->tot_len)))
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy: target not big enough to hold source");
+ return ERR_ARG;
+ }
+ NSPOL_LOGINF (PBUF_DEBUG,
+ "splpbuf_to_pbuf_copy]p_to=%p [type %d tot_len %d], p_from=%p [type %d tot_len %d]",
+ (void *) p_to, p_to->type, p_to->tot_len, (void *) p_from,
+ p_from->type, p_from->tot_len);
+ do
+ {
+ NSPOL_LOGINF (NETIF_DEBUG, "copying....");
+ if (p_to == NULL)
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy: target not big enough to hold source p_to len [%d] p_from len [%d]",
+ p_to->tot_len, p_from->tot_len);
+ return ERR_ARG;
+ }
+
+ if ((p_to->len - offset_to) >= (p_from->len - offset_from))
+ {
+
+ len = p_from->len - offset_from;
+ }
+ else
+ {
+
+ len = p_to->len - offset_to;
+ }
+
+ if (EOK != MEMMOVE_S ((u8_t *) p_to->payload + offset_to,
+ len,
+ (u8_t *) ADDR_SHTOL (p_from->payload_a) +
+ offset_from, len))
+ {
+ NSPOL_LOGERR ("MEMMOVE_S failed");
+ return ERR_MEM;
+ }
+
+ offset_to += len;
+ offset_from += len;
+ if (offset_to > p_to->len)
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy: target offset not match: offset_to > p_to->len.");
+ return ERR_VAL;
+ }
+ if (offset_to == p_to->len)
+ {
+ offset_to = 0;
+ p_to = p_to->next;
+
+ NSPOL_LOGINF (NETIF_DEBUG,
+ "splpbuf_to_pbuf_copy: p_to next %p", p_to);
+ }
+
+ if (offset_from >= p_from->len)
+ {
+ /* on to next p_from (if any) */
+ NSPOL_LOGINF (NETIF_DEBUG,
+ "splpbuf_to_pbuf_copy: source offset not match: offset_from >= p_from->len");
+ offset_from = 0;
+ p_from = (struct spl_pbuf *) ADDR_SHTOL (p_from->next_a);
+ NSPOL_LOGINF (NETIF_DEBUG,
+ "splpbuf_to_pbuf_copy: pfrom next %p", p_from);
+ }
+
+ if ((p_from != NULL) && (p_from->len == p_from->tot_len))
+ {
+ if ((p_from->next_a != 0))
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+
+ if ((p_to != NULL) && (p_to->len == p_to->tot_len))
+ {
+ /* don't copy more than one packet! */
+ if ((p_to->next != NULL))
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+ }
+ while (p_from);
+
+ NSPOL_LOGDBG (NETIF_DEBUG, "splpbuf_to_pbuf_copy: end of chain reached.");
+ return ERR_OK;
+}
+
+err_t
+pbuf_to_splpbuf_copy (struct spl_pbuf * p_to, struct pbuf * p_from)
+{
+ int offset = 0;
+ void *data = NULL;
+
+ do
+ {
+ data = (u8_t *) (p_to->payload_a) + offset;
+ memcpy (data, (u8_t *) p_from->payload, p_from->len);
+ offset = offset + p_from->len;
+ if (offset >= 2048)
+ {
+ NSPOL_LOGERR ("More thank 2K size");
+ return ERR_MEM;
+ }
+ p_from = p_from->next;
+ }
+ while (p_from != NULL);
+
+ return ERR_OK;
+}
+
+struct pbuf *
+spl_convert_spl_pbuf_to_pbuf (struct spl_pbuf *p_from)
+{
+ struct pbuf *p_to = NULL;
+
+ p_to = pbuf_alloc (PBUF_RAW, p_from->tot_len, PBUF_POOL);
+ if (p_to)
+ {
+ splpbuf_to_pbuf_copy (p_to, p_from);
+ }
+ return p_to;
+}
+
+spl_pbuf_layer
+get_pbuf_layer_from_pbuf_payload (struct pbuf * buf)
+{
+
+ struct eth_hdr *ethhdr;
+ spl_pbuf_layer layer = SPL_PBUF_TRANSPORT;
+ u16_t type;
+
+ if (buf->len <= SIZEOF_ETH_HDR)
+ {
+ NSPOL_LOGINF (PBUF_DEBUG,
+ "get_pbuf_layer_from_payload failed. length is wrong");
+ return layer;
+ }
+ ethhdr = (struct eth_hdr *) buf->payload;
+ type = spl_htons (ethhdr->type);
+
+ NSPOL_LOGINF (PBUF_DEBUG, "packet type %x", type);
+
+ switch (type)
+ {
+ case ETHTYPE_IP:
+ layer = SPL_PBUF_IP;
+ break;
+ case ETHTYPE_ARP:
+ layer = SPL_PBUF_LINK;
+ break;
+ default:
+ layer = SPL_PBUF_TRANSPORT;
+ break;
+ }
+
+ return layer;
+}
+
+void
+print_pbuf_payload_info (struct pbuf *buf, bool send)
+{
+
+ struct eth_hdr *ethhdr;
+ u16_t type;
+
+ if (buf->len <= SIZEOF_ETH_HDR)
+ {
+ NSPOL_LOGINF (PBUF_DEBUG,
+ "get_pbuf_layer_from_payload failed. length is wrong");
+ return;
+ }
+ ethhdr = (struct eth_hdr *) buf->payload;
+ type = spl_htons (ethhdr->type);
+
+ if (send)
+ {
+ NSPOL_LOGINF (PBUF_DEBUG, "send packet start type %x len %d *****",
+ type, buf->len);
+ }
+ else
+ {
+ NSPOL_LOGINF (PBUF_DEBUG,
+ "receive packet start type %x len %d ########", type,
+ buf->len);
+ }
+
+ switch (type)
+ {
+ case ETHTYPE_IP:
+ NSPOL_LOGINF (TCPIP_DEBUG, "ip packet len %d tot len %d type %x",
+ buf->len, buf->tot_len, type);
+ struct ip_hdr *ip =
+ (struct ip_hdr *) ((char *) buf->payload + SIZEOF_ETH_HDR);
+ NSPOL_LOGINF (PBUF_DEBUG, "ip packet src %x dest %x proto %d", ip->src,
+ ip->dest, ip->_proto);
+ break;
+ case ETHTYPE_ARP:
+ NSPOL_LOGINF (TCPIP_DEBUG, "arp packet len %d tot len %d type %x",
+ buf->len, buf->tot_len, type);
+ break;
+ default:
+ NSPOL_LOGINF (TCPIP_DEBUG, "other packet len %d tot len %d type %x",
+ buf->len, buf->tot_len, type);
+ break;
+ }
+ return;
+}
diff --git a/stacks/lwip_stack/lwip_src/core/spl_timers.c b/stacks/lwip_stack/lwip_src/core/spl_timers.c
new file mode 100644
index 0000000..50582fc
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/spl_timers.c
@@ -0,0 +1,608 @@
+/*
+*
+* 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 "opt.h"
+#include "nsfw_mem_api.h"
+#include "def.h"
+#include "sc_dpdk.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "nstack_share_res.h"
+
+#include <time.h>
+#include <signal.h>
+#include <pthread.h>
+#include <syscall.h>
+#include "nsfw_ps_api.h"
+#include "spl_timers.h"
+#include "common_mem_api.h"
+
+extern sys_thread_t g_timerThread_id;
+
+/*Since the range of the dpdk read TSC value is u64_t, it changes*/
+
+#ifndef typecheck
+#define typecheck(type, x) \
+({ type __dummy; \
+ typeof(x)__dummy2; \
+ (void)(&__dummy == &__dummy2); \
+ 1; \
+ })
+#endif
+
+#ifndef time_after_eq
+#define time_after_eq(a, b) \
+(typecheck(unsigned long, a) \
+ && typecheck(unsigned long, b) \
+ && ((long)(a) - (long)(b) >= 0))
+#endif
+
+#define MIN_TIME_PICE 50
+#define MICRO_PER_SECOND 1000
+#define NANO_PER_MICROSECOND 1000000
+#define NANO_PER_SECOND 1000000000
+
+#define PTIMER_MSG_BUFFER_SIZE 4096
+
+#define PTIMER_STATE_INACTIVE 0x00
+#define PTIMER_STATE_ENQUEUED 0x01
+#define gettid() syscall(__NR_gettid)
+
+#define TIMER_CONTEXT_NAME "TIMER_CONTEXT_NAME"
+
+static timer_t lazy_tim;
+static timer_t lazy_tim_retry;
+static struct ptimer_base ptimer;
+static sys_sem_t ptimer_lock;
+
+extern void recycle_tmr (struct ptimer_node *tmo);
+
+extern nstack_tick_info_t g_nstack_timer_tick;
+
+/*
+ ***************************
+ * rb_tree wrapper function*
+ ***************************
+ */
+NSTACK_STATIC void
+remove_ptimer (struct ptimer_node *tmo, struct ptimer_base *base)
+{
+ if (tmo == NULL)
+ {
+ NSPOL_LOGERR ("input parameter tmo is null");
+ return;
+ }
+ if (!(tmo->state & PTIMER_STATE_ENQUEUED))
+ {
+ NSPOL_LOGWAR (TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ "the timer state is: PTIMER_STATE_INACTIVE, no need to remove!");
+ return;
+ }
+
+ if (base->first == &tmo->node)
+ {
+ base->first = rb_next (&tmo->node);
+ }
+
+ rb_erase (&tmo->node, &base->active);
+
+ tmo->state = PTIMER_STATE_INACTIVE;
+}
+
+NSTACK_STATIC struct ptimer_node *
+search_ptimer (struct ptimer_msg *msg)
+{
+ if (msg == NULL)
+ {
+ NSPOL_LOGERR ("input parameter msg is null");
+ return NULL;
+ }
+ if (msg->node)
+ {
+ return msg->node;
+ }
+
+ return NULL;
+
+}
+
+err_t
+del_ptimer (struct ptimer_msg * msg)
+{
+ struct ptimer_node *tmo;
+
+ tmo = search_ptimer (msg);
+ if (tmo)
+ {
+ remove_ptimer (tmo, &ptimer);
+ NSPOL_LOGDBG (TIMERS_DEBUG, "del]thread=%u,ptimer_node=%p", tmo->index,
+ tmo);
+ return ERR_OK;
+ }
+
+ NSPOL_LOGERR ("ptime_node not found!!");
+ return ERR_VAL;
+}
+
+/*
+ * Ptimer inserted into rb_tree
+ * @param node: the ptimer node pointer
+ * @param base: the ptimer root_base pointer
+ */
+NSTACK_STATIC void
+enqueue_ptimer (struct ptimer_node *tmo, struct ptimer_base *base)
+{
+ struct rb_node **linknode;
+ struct rb_node *parent = NULL;
+ struct ptimer_node *entry;
+ int leftmost = 1;
+ if (tmo == NULL || base == NULL)
+ {
+ NSPOL_LOGERR ("input parameter is null");
+ return;
+ }
+
+ if ((tmo->state & PTIMER_STATE_ENQUEUED))
+ {
+ NSPOL_LOGWAR (TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ "the timer state is: PTIMER_STATE_ENQUEUED");
+ return;
+ }
+
+ linknode = &base->active.rb_node;
+ while (*linknode)
+ {
+ parent = *linknode;
+ entry = rb_entry (parent, struct ptimer_node, node);
+ //XXX: do by the equal case is all of price of the large case
+ if (time_after_eq (entry->abs_nsec, tmo->abs_nsec))
+ {
+ linknode = &(*linknode)->rb_left;
+ }
+ else
+ {
+ linknode = &(*linknode)->rb_right;
+ leftmost = 0;
+ }
+ }
+
+ /*
+ * Insert the timer to the rb_tree and check whether it
+ * replaces the first pending timer
+ */
+ if (leftmost)
+ {
+ base->first = &tmo->node;
+ }
+
+ rb_link_node (&tmo->node, parent, linknode);
+ rb_insert_color (&tmo->node, &base->active);
+ NSPOL_LOGDBG (TIMERS_DEBUG, "enqueue]thread=%u,ptimer_node=%p", tmo->index,
+ tmo);
+ tmo->state |= PTIMER_STATE_ENQUEUED;
+}
+
+void
+launch_tmr (timer_t * tim, u64_t nsec)
+{
+ struct itimerspec vtim;
+
+ vtim.it_value.tv_sec = (nsec) / NANO_PER_SECOND;
+ vtim.it_value.tv_nsec = (nsec) % NANO_PER_SECOND;
+ vtim.it_interval.tv_sec = 0;
+ vtim.it_interval.tv_nsec = 0;
+
+ if (timer_settime (*tim, 0, &vtim, NULL) < 0)
+ {
+ NSPOL_LOGERR ("add_ptimer:timer_settime failed");
+ }
+
+}
+
+/*
+ * add ptimer to rb_tree
+ * @param tmo: the ptimer node pointer
+ */
+void
+add_ptimer (struct ptimer_node *tmo)
+{
+ if (tmo == NULL)
+ {
+ NSPOL_LOGERR ("input parameter is null");
+ return;
+ }
+ enqueue_ptimer (tmo, &ptimer);
+
+ if (ptimer.first == &tmo->node)
+ {
+ launch_tmr (&lazy_tim, tmo->info.msec * NANO_PER_MICROSECOND);
+ }
+}
+
+#if 1
+/*
+ * cond signal ,send a ptimer message
+ * @param type: the message type
+ * @param handler: timeout handler
+ * @param node: the ptimer node pointer
+ */
+void
+regedit_ptimer (enum msg_type Type, sys_timeout_handler handler,
+ struct ptimer_node *node)
+{
+ (void) handler;
+ (void) pthread_mutex_lock (&ptimer.lock);
+ if (ptimer.tail == NULL)
+ {
+ (void) pthread_mutex_unlock (&ptimer.lock);
+ NSPOL_LOGERR ("ptimer.tail is null");
+ free (node);
+ node = NULL;
+ return;
+ }
+ ptimer.tail->msg_type = Type;
+ ptimer.tail->node = node;
+ ptimer.tail = ptimer.tail->next;
+ if (ptimer.head == ptimer.tail)
+ {
+ (void) pthread_mutex_unlock (&ptimer.lock);
+ NSPOL_LOGERR ("ptimer.head equal to ptimer.tail");
+ return;
+ }
+
+ (void) pthread_kill (g_timerThread_id, SIGRTMIN + 2);
+
+ (void) pthread_mutex_unlock (&ptimer.lock);
+ return;
+}
+#endif
+/*
+ * deal with the timeout signal
+ *
+ */
+void
+deal_timeout_sig (void)
+{
+ struct ptimer_node *tmo;
+ struct timespec now;
+ unsigned long abs_nsec;
+ err_t err;
+ int retval;
+ if (ptimer.first == NULL)
+ {
+ NSPOL_LOGERR ("ptimer.first=NULL!!");
+ return;
+ }
+ tmo = rb_entry (ptimer.first, struct ptimer_node, node);
+ retval = clock_gettime (CLOCK_MONOTONIC, &now);
+ if (0 != retval)
+ {
+ NSPOL_LOGERR ("clock_gettime failed]retval=%d,errno=%d", retval, errno);
+ }
+ abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec;
+
+ // deal with all timeout point
+ while (time_after_eq (abs_nsec, tmo->abs_nsec))
+ {
+ remove_ptimer (tmo, &ptimer);
+
+ if (tmo->info.flags & PTIMER_ONESHOT)
+ {
+ }
+ else
+ {
+ //re-entry periodic ptimer
+ tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec
+ + tmo->info.msec * NANO_PER_MICROSECOND;
+ add_ptimer (tmo);
+ }
+
+ //send timeout message
+ NSPOL_LOGDBG (INTERRUPT_DEBUG,
+ "ptimer happened to thread_index]index=%u", tmo->index);
+ if ((err = ltt_apimsg (tmo->info._phandle, (void *) tmo)))
+ {
+ NSPOL_LOGWAR (TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ "send timeout message failed!]errno=%d", err);
+ }
+
+ if (ptimer.first == NULL)
+ {
+ NSPOL_LOGERR ("deal_timeout_sig: ptimer.first == NULL!!");
+ return;
+ }
+ tmo = rb_entry (ptimer.first, struct ptimer_node, node);
+ }
+
+ if (tmo->abs_nsec <= abs_nsec)
+ {
+ NSPOL_LOGERR ("tmo->abs_nsec is smaller than abs_nsec");
+ return;
+ }
+
+ NSPOL_LOGDBG (TIMERS_DEBUG, "TIMERSIGNAL : Launch timer for]time=%ul",
+ tmo->abs_nsec - abs_nsec);
+ launch_tmr (&lazy_tim, tmo->abs_nsec - abs_nsec); //timer interupted eveny 50ms instand by tmo->abs_nsec
+}
+
+/*
+ * timeout signal handle function
+ * @param v: unused argument
+ */
+/*ptimer is already protected and used*/
+
+NSTACK_STATIC void
+timeout_sigaction (int sig)
+{
+ (void) sig;
+ if (!sys_arch_sem_trywait (&ptimer_lock))
+ {
+ launch_tmr (&lazy_tim_retry,
+ (MIN_TIME_PICE / 5) * NANO_PER_MICROSECOND);
+ return;
+ }
+
+ deal_timeout_sig ();
+
+ sys_sem_signal (&ptimer_lock);
+
+ return;
+}
+
+/*
+ * initialize the ptimer buffer and timing mechanism
+ */
+err_t
+init_ptimer (void)
+{
+ int i, retval;
+ struct sigevent timer_event;
+ struct sigevent timer_event1;
+ struct ptimer_msg *ptr;
+
+ if (pthread_mutex_init (&ptimer.lock, NULL))
+ {
+ NSPOL_LOGERR ("pthread_mutex_init failed");
+ return ERR_MEM;
+ }
+ /*codex fix */
+ if (ERR_MEM == sys_sem_new (&ptimer_lock, 1))
+ {
+ NSPOL_LOGERR ("init_ptimer: sys_sem_new failure");
+ return ERR_MEM;
+ }
+
+ ptimer.active.rb_node = NULL;
+ ptimer.first = NULL;
+
+ ptr =
+ (struct ptimer_msg *) malloc (PTIMER_MSG_BUFFER_SIZE *
+ sizeof (struct ptimer_msg));
+ if (!ptr)
+ {
+ NSPOL_LOGERR ("init_ptimer: malloc ptimer buffer failed!");
+ return ERR_MEM;
+ }
+
+ int ret =
+ MEMSET_S (ptr, (PTIMER_MSG_BUFFER_SIZE * sizeof (struct ptimer_msg)),
+ 0, (PTIMER_MSG_BUFFER_SIZE * sizeof (struct ptimer_msg)));
+ if (EOK != ret)
+ {
+ free (ptr);
+ NSPOL_LOGERR ("init_ptimer: MEMSET_S ptimer buffer failed]ret=%d", ret);
+ return ERR_MEM;
+ }
+
+ for (i = 0; i < PTIMER_MSG_BUFFER_SIZE - 1; i++)
+ {
+ ptr[i].next = &ptr[(i + 1)];
+ ptr[(i + 1)].prev = &ptr[i];
+ }
+
+ ptr[i].next = &ptr[0];
+ ptr[0].prev = &ptr[i];
+ ptimer.head = ptimer.tail = &ptr[0];
+ retval =
+ MEMSET_S (&timer_event, sizeof (struct sigevent), 0,
+ sizeof (struct sigevent));
+ if (EOK != retval)
+ {
+ free (ptr);
+ ptr = NULL;
+ NSPOL_LOGERR ("MEMSET_S failed]ret=%d", retval);
+ return ERR_VAL;
+ }
+ timer_event.sigev_notify = SIGEV_SIGNAL;
+ timer_event.sigev_signo = SIGRTMIN;
+ timer_event.sigev_value.sival_ptr = (void *) &lazy_tim;
+ timer_event1 = timer_event;
+ timer_event1.sigev_value.sival_ptr = (void *) &lazy_tim_retry;
+
+ if (timer_create (CLOCK_MONOTONIC, &timer_event, &lazy_tim) < 0)
+ {
+ free (ptr);
+ ptr = NULL;
+ NSPOL_LOGERR ("ptimer_init: timer_create failed!");
+ return ERR_VAL;
+ }
+
+ if (timer_create (CLOCK_MONOTONIC, &timer_event1, &lazy_tim_retry) < 0)
+ {
+ free (ptr);
+ ptr = NULL;
+ NSPOL_LOGERR ("ptimer_init: timer_create failed!");
+ return ERR_VAL;
+ }
+
+ return ERR_OK;
+}
+
+NSTACK_STATIC err_t
+process_timeout_msg (struct ptimer_msg * msg)
+{
+ struct ptimer_node *tmo = msg->node;
+ struct timespec now;
+
+ switch (msg->msg_type)
+ {
+ case SYS_PTIMEROUT_MSG:
+ if (tmo)
+ {
+ int retval = clock_gettime (CLOCK_MONOTONIC, &now);
+ if (0 != retval)
+ {
+ NSPOL_LOGERR ("clock_gettime failed]retval=%d,errno=%d", retval,
+ errno);
+ }
+ tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec
+ + tmo->info.msec * NANO_PER_MICROSECOND;
+ add_ptimer (tmo);
+ }
+ else
+ {
+ NSPOL_LOGERR ("process_timeout_msg: rb_node is NULL!");
+ return ERR_MEM;
+ }
+
+ break;
+ case SYS_UNPTIMEROUT_MSG:
+ if (del_ptimer (msg) != ERR_OK)
+ {
+ NSPOL_LOGERR
+ ("process_timeout_msg: can not find the timeout event(oops)!");
+ }
+
+ break;
+ default:
+ NSPOL_LOGERR
+ ("process_timeout_msg: oops! lwip timeout_thread receive unacquainted message!");
+ break;
+ }
+
+ return ERR_OK;
+}
+
+void
+ptimer_thread (void *arg)
+{
+ LWIP_UNUSED_ARG (arg);
+ int sig, ret = -1;
+ sigset_t waitset;
+ sigset_t oset;
+ struct ptimer_msg *msg;
+
+ if (0 != sigemptyset (&waitset))
+ {
+ NSTCP_LOGERR ("sigemptyset function call error");
+ return;
+ }
+
+ if (0 != sigaddset (&waitset, SIGRTMIN))
+ {
+ NSTCP_LOGERR ("sigaddset function call error");
+ return;
+ }
+
+ if (0 != sigaddset (&waitset, SIGRTMIN + 2))
+ {
+ NSTCP_LOGERR ("sigaddset function call error");
+ return;
+ }
+
+ (void) pthread_sigmask (SIG_BLOCK, &waitset, &oset);
+
+ (void) pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
+ (void) pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+ NSPOL_LOGDBG (TIMERS_DEBUG, "ptimer: init done !");
+
+ if (!g_nstack_timer_tick.tick_ptr)
+ {
+ NSTCP_LOGERR ("g_nstack_timer_tick not inited");
+ return;
+ }
+ (void) gettimeofday (&g_nstack_timer_tick.ref_time, NULL);
+ g_nstack_timer_tick.interval = 100;
+ *g_nstack_timer_tick.tick_ptr = 0;
+ g_nstack_timer_tick.ref_tick = 0;
+ while (1)
+ {
+ ret = sigwait (&waitset, &sig);
+ (void) nsfw_thread_chk (); // will only return TRUE, no need to check return value
+ if (ret != -1)
+ {
+ /* for timer expirt handle */
+ if (SIGRTMIN == sig)
+ {
+ timeout_sigaction (sig);
+ continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+
+ while (1)
+ {
+ (void) pthread_mutex_lock (&ptimer.lock);
+ if (ptimer.head == ptimer.tail)
+ {
+ (void) pthread_mutex_unlock (&ptimer.lock);
+ break;
+ }
+
+ msg = ptimer.head;
+ ptimer.head = ptimer.head->next;
+ (void) pthread_mutex_unlock (&ptimer.lock);
+
+ sys_arch_sem_wait (&ptimer_lock, 0);
+
+ if (process_timeout_msg (msg) != ERR_OK)
+ {
+ NSPOL_LOGERR ("oops: ptimer_thread panic!");
+ }
+
+ sys_sem_signal (&ptimer_lock);
+ }
+ }
+}
+
+void
+timeout_phandler (void *act, void *arg)
+{
+ struct ptimer_node *tmo = arg;
+ if (act == NULL)
+ {
+ NSPOL_LOGERR ("input parameter arg is null");
+ return;
+ }
+
+ NSPOL_LOGINF (TIMERS_DEBUG, "Timer expire @timeout_phandler Handle %p",
+ tmo->info._phandle);
+ if (tmo->info.flags & PTIMER_ONESHOT)
+ {
+ sys_timeout_handler handle = act;
+ handle (tmo->info.ctx);
+ return;
+ }
+ else
+ {
+ NSPOL_LOGINF (TIMERS_DEBUG,
+ "Timer expire error @timeout_phandler Handle %p",
+ tmo->info._phandle);
+ }
+}
diff --git a/stacks/lwip_stack/lwip_src/core/unmatch_version.c b/stacks/lwip_stack/lwip_src/core/unmatch_version.c
new file mode 100644
index 0000000..6c8cad3
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/unmatch_version.c
@@ -0,0 +1,59 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "nsfw_mem_api.h"
+#include "nstack_share_res.h"
+#include "nstack_securec.h"
+
+char *g_nstack_ver_info = NULL;
+
+int
+init_unmatch_version (void)
+{
+ int ret;
+ nsfw_mem_zone mzone;
+
+ ret =
+ STRCPY_S (mzone.stname.aname, NSFW_MEM_NAME_LENGTH, NSTACK_VERSION_SHM);
+ if (EOK != ret)
+ {
+ NSPOL_LOGERR ("STRCPY_S fail]ret=%d", ret);
+ return -1;
+ }
+ mzone.stname.entype = NSFW_SHMEM;
+ mzone.isocket_id = -1;
+ mzone.length =
+ NSTACK_VERSION_LEN + MAX_UNMATCH_VER_CNT * sizeof (unmatch_ver_info_t);
+ mzone.ireserv = 0;
+
+ char *version = (char *) nsfw_mem_zone_create (&mzone);
+ if (NULL == version)
+ {
+ NSPOL_LOGERR ("Failed to create unmatch_version memory");
+ return -1;
+ }
+
+ ret = STRCPY_S (version, NSTACK_VERSION_LEN, NSTACK_VERSION);
+ if (EOK != ret)
+ {
+ NSPOL_LOGERR ("STRCPY_S NSTACK_VERSION fail]ret=%d", ret);
+ return -1;
+ }
+
+ g_nstack_ver_info = version;
+
+ return 0;
+}
diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h b/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h
new file mode 100644
index 0000000..0c88139
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/ip_module/config_common.h
@@ -0,0 +1,64 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _NSTACK_CONFIG_COMMON_H_
+#define _NSTACK_CONFIG_COMMON_H_
+
+#include "ip_module_api.h"
+
+#define MAX_IP_MODULE_BUFF_SIZE 1024*1024
+
+/* ip module config types */
+#define IP_MODULE_TYPE_IP "ip"
+#define IP_MODULE_TYPE_NETWORK "network"
+#define IP_MODULE_TYPE_PORT "port"
+#define IP_MODULE_TYPE_SETLOG "setlog"
+#define IP_MODULE_TYPE_SNAPSHOT "snapshot"
+#define IP_MODULE_TYPE_SETTRACE "settrace"
+
+#define TCP_MODULE_TYPE_SET_OOS_LEN "ooslen"
+
+#define IP_MODULE_NAME "./nStackCtrl: "
+#define IP_MODULE_INVALID_ARGUMENT_S "invalid argument -- \"%s\"\n"
+#define IP_MODULE_MORE_OPTION "need more options -- "
+#define IP_MODULE_LESS_OPTION "no need option -- "
+
+/* Error codes */
+#define IP_MODULE_OK 0
+#define IP_MODULE_DATA_ERROR 1
+#define IP_MODULE_DATA_NOT_EXIST 2
+
+struct config_param
+{
+ int action;
+ char type[IP_MODULE_LENGTH_256];
+ char name[IP_MODULE_LENGTH_256];
+ char value[IP_MODULE_LENGTH_64];
+ char container_id[IP_MODULE_LENGTH_256];
+ int error;
+
+ char error_desc[NSCRTL_ERRBUF_LEN];
+
+ u64 traceid;
+};
+
+struct config_data
+{
+ struct config_param param;
+ char json_buff[MAX_IP_MODULE_BUFF_SIZE - sizeof (struct config_param)];
+};
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h b/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h
new file mode 100644
index 0000000..779ace8
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/ip_module/configuration_reader.h
@@ -0,0 +1,26 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _CONFIGURATION_READER_H
+#define _CONFIGURATION_READER_H
+#include <semaphore.h>
+#include "config_common.h"
+
+struct config_data *get_config_data ();
+int get_str_value (const char *arg);
+int setlog_level_value (const char *param, const char *value);
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h b/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h
new file mode 100644
index 0000000..e83c607
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/ip_module/container_ip.h
@@ -0,0 +1,39 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _CONTAINER_IP_H
+#define _CONTAINER_IP_H
+#include "ip_module_api.h"
+#include "json.h"
+
+struct ip_action_param
+{
+ char container_id[IP_MODULE_LENGTH_256];
+ char port_name[IP_MODULE_LENGTH_256];
+};
+
+void free_container (struct container_ip *container, bool_t only_free);
+struct container_port *parse_port_obj (struct json_object *port_obj);
+struct container_ip *parse_container_ip_json (char *param);
+int add_container (struct container_ip *container);
+struct container_ip *get_container_by_container_id (char *container_id);
+
+int del_port (char *container_id, char *port_name);
+struct container_port *get_port (char *container_id, char *port_name);
+struct container_port *get_port_from_container (struct container_port *port);
+int getIpCfgAll (char *jsonBuf, size_t size);
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h b/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h
new file mode 100644
index 0000000..488e13e
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/ip_module/ip_module_api.h
@@ -0,0 +1,222 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _IP_MODULE_API_H_
+#define _IP_MODULE_API_H_
+#include "types.h"
+
+typedef int bool_t;
+#define IP_MODULE_TRUE 1
+#define IP_MODULE_FALSE 0
+#define IP_MODULE_LENGTH_32 32
+#define IP_MODULE_LENGTH_64 64
+#define IP_MODULE_LENGTH_256 256
+#define IP_MODULE_LENGTH_1024 1024
+#define IP_MODULE_SUBNET_MASK_LEN IP_MODULE_LENGTH_32
+#define IP_MODULE_MAX_NAME_LEN IP_MODULE_LENGTH_256
+#define IP_MODULE_PORT_JSON_LEN (2048 * 2)
+#define IP_MODULE_NETWORK_JSON_LEN (2048 * 2)
+#define MAX_NETWORK_COUNT IP_MODULE_LENGTH_64
+#define MAX_NETWORK_IP_COUNT IP_MODULE_LENGTH_1024
+#define MAX_NETWORK_NUM (MAX_NETWORK_COUNT * 2)
+COMPAT_PROTECT (MAX_NETWORK_NUM, 128);
+#define MAX_PORT_NUM (MAX_NETWORK_IP_COUNT * 2)
+COMPAT_PROTECT (MAX_PORT_NUM, 2048);
+#define NSCRTL_ERRBUF_LEN IP_MODULE_LENGTH_256
+
+#define INVALID_EXPIRE_TIME 0x7FFFFFFF
+#define NSTACLCTRL_MAX_TRY_TIMES 60
+
+/*sockaddr_un.sun_path is an array of 108 bytes*/
+#define IP_MODULE_MAX_PATH_LEN 108
+
+typedef enum enumADERRCODE
+{
+ NSCRTL_OK = 0,
+ NSCRTL_ERR,
+ NSCRTL_RD_NOT_EXIST,
+ NSCRTL_RD_EXIST = 3,
+ NSCRTL_INPUT_ERR,
+ NSCRTL_STATUS_ERR,
+ NSCRTL_NETWORK_COUNT_EXCEED,
+ NSCRTL_IP_COUNT_EXCEED,
+ NSCRTL_FREE_ALL_PORT, //when all ports in container were deleted, need to free container.
+
+ NSCRTL_MAX_ERR = 127
+} NSCRTL_ERR_CODE;
+
+#define NSOPR_SET_ERRINFO(_errno, fmt, ...) \
+ {\
+ struct config_data* cf_data = get_config_data(); \
+ if (cf_data)\
+ {\
+ size_t len_error_desc = strlen(cf_data->param.error_desc); \
+ cf_data->param.error = _errno; \
+ if ((_errno != NSCRTL_OK) && (len_error_desc < NSCRTL_ERRBUF_LEN))\
+ {\
+ if (-1 == (SNPRINTF_S(cf_data->param.error_desc + len_error_desc, \
+ NSCRTL_ERRBUF_LEN - len_error_desc, NSCRTL_ERRBUF_LEN - len_error_desc - 1, fmt, ## __VA_ARGS__)))\
+ {\
+ NSOPR_LOGERR("SNPRINTF_S failed]"); \
+ } \
+ } \
+ } \
+ } \
+
+struct ref_nic
+{
+ struct ref_nic *next;
+ char nic_name[IP_MODULE_MAX_NAME_LEN];
+};
+
+struct phy_net
+{
+ struct ref_nic *header;
+ char bond_name[IP_MODULE_MAX_NAME_LEN];
+ int bond_mode;
+};
+
+struct container_port_ip_cidr
+{
+ struct container_port_ip_cidr *next;
+ unsigned int ip;
+ unsigned int mask_len;
+};
+
+struct container_multicast_id
+{
+ struct container_multicast_id *next;
+ unsigned int ip;
+};
+
+typedef struct
+{
+ char port_json[IP_MODULE_PORT_JSON_LEN];
+} port_buffer;
+
+struct container_port
+{
+ struct container_port *next;
+ struct container_port_ip_cidr *ip_cidr_list;
+ struct container_multicast_id *multicast_list;
+ char port_name[IP_MODULE_MAX_NAME_LEN];
+ port_buffer *buffer;
+};
+
+#define get_port_json(obj) obj->buffer->port_json
+
+struct container_ip
+{
+ struct container_ip *next;
+ struct container_port *ports_list;
+ char container_id[IP_MODULE_MAX_NAME_LEN];
+};
+
+struct container_list
+{
+ struct container_ip *header;
+};
+
+struct ip_subnet
+{
+ struct ip_subnet *next;
+ unsigned int subnet;
+ unsigned int mask_len;
+};
+
+typedef struct
+{
+ char network_json[IP_MODULE_NETWORK_JSON_LEN];
+} network_buffer;
+
+struct network_configuration
+{
+ struct network_configuration *next;
+ struct phy_net *phy_net;
+ struct ip_subnet *ip_subnet;
+ char network_name[IP_MODULE_MAX_NAME_LEN];
+ char type_name[IP_MODULE_MAX_NAME_LEN];
+ network_buffer *buffer;
+};
+
+#define get_network_json(obj) obj->buffer->network_json
+
+struct network_list
+{
+ struct network_configuration *header;
+};
+
+void ip_subnet_print (struct ip_subnet *subnet);
+bool_t is_in_same_network (unsigned int src_ip, unsigned int dst_ip);
+bool_t is_ip_match_netif (unsigned int ip, char *netif_name);
+bool_t is_ip_exist (unsigned int ip);
+struct network_configuration *get_network_list ();
+inline struct network_configuration *get_network_by_ip_with_tree (unsigned int
+ ip);
+
+/* "type" option */
+typedef enum
+{
+ IP_MODULE_NETWORK,
+ IP_MODULE_IP,
+ IP_MODULE_NETWORK_ALL,
+ IP_MODULE_IP_ALL,
+ IP_MODULE_ALL,
+} ip_module_type;
+
+/* "action" option */
+typedef enum
+{
+ IP_MODULE_OPERATE_NULL,
+ IP_MODULE_OPERATE_ADD,
+ IP_MODULE_OPERATE_DEL,
+ IP_MODULE_OPERATE_QUERY,
+ IP_MODULE_OPERATE_SET,
+ IP_MODULE_GET_VERSION,
+ IP_MODULE_QUERY_NET,
+ IP_MODULE_MAX, //new type should be added before IP_MODULE_MAX
+ IP_MODULE_BOTTOM = 0xFFFFFFFF
+} ip_module_operate_type;
+
+typedef int (*post_to_fn) (void *arg, ip_module_type type,
+ ip_module_operate_type operate_type);
+typedef int (*add_netif_ip_fn) (char *netif_name, unsigned int ip,
+ unsigned int mask);
+typedef int (*del_netif_ip_fn) (char *netif_name, unsigned int ip);
+
+typedef struct
+{
+ post_to_fn post_to;
+ add_netif_ip_fn add_netif_ip;
+ del_netif_ip_fn del_netif_ip;
+} output_api;
+
+void regist_output_api (output_api * api);
+output_api *get_output_api ();
+int init_configuration_reader ();
+int process_post (void *arg, ip_module_type type,
+ ip_module_operate_type operate_type);
+int process_configuration (void *arg, ip_module_type type,
+ ip_module_operate_type operate_type);
+
+port_buffer *malloc_port_buffer ();
+void free_port_buffer (port_buffer * buffer);
+network_buffer *malloc_network_buffer ();
+void free_network_buffer (network_buffer * buffer);
+int get_network_json_data ();
+int get_ip_json_data ();
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/network.h b/stacks/lwip_stack/lwip_src/include/ip_module/network.h
new file mode 100644
index 0000000..117b71c
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/ip_module/network.h
@@ -0,0 +1,36 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _NETWORK_H
+#define _NETWORK_H
+#include "ip_module_api.h"
+
+void free_network_configuration (struct network_configuration *network,
+ bool_t only_free);
+struct network_configuration *parse_network_obj (struct json_object
+ *network_obj);
+struct network_configuration *parse_network_json (char *param,
+ struct network_configuration
+ *network_list);
+int add_network_configuration (struct network_configuration
+ *network_configuration);
+struct network_configuration *get_network_by_name (char *name);
+struct network_configuration *get_network_by_nic_name (char *name);
+int del_network_by_name (char *name);
+int get_network_all (char *jsonBuf, size_t size);
+int nic_already_init (const char *nic_name);
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h b/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h
new file mode 100644
index 0000000..ef0ac37
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/ip_module/trp_rb_tree.h
@@ -0,0 +1,77 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __TRP_RB_TREE_H__
+#define __TRP_RB_TREE_H__
+
+typedef void *trp_key_t;
+typedef void *trp_data_t;
+
+#define RB_RED 0
+#define RB_BLACK 1
+
+typedef int (*key_compare) (trp_key_t left, trp_key_t right); // return > 0 left > right, return 0 left = right, return < 0 left < right
+
+typedef struct trp_rb_node
+{
+ struct trp_rb_node *rb_parent;
+ struct trp_rb_node *rb_right;
+ struct trp_rb_node *rb_left;
+ key_compare key_compare_fn;
+ trp_key_t key;
+ trp_data_t data;
+ unsigned int color;
+} trp_rb_node_t;
+
+typedef struct trp_rb_root
+{
+ struct trp_rb_node *rb_node;
+} trp_rb_root_t;
+
+int trp_rb_insert (trp_key_t, trp_data_t, trp_rb_root_t *, key_compare);
+int trp_rb_insert_allow_same_key (trp_key_t, trp_data_t, trp_rb_root_t *,
+ key_compare);
+void trp_rb_erase (trp_key_t, trp_rb_root_t *, key_compare key_compare_fn);
+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);
+
+static inline trp_rb_node_t *
+trp_rb_search (trp_key_t key, trp_rb_root_t * root,
+ key_compare key_compare_fn)
+{
+ trp_rb_node_t *node = root->rb_node;
+ int ret;
+ while (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 node;
+ }
+ }
+
+ return NULL;
+}
+#endif
diff --git a/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h b/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h
new file mode 100644
index 0000000..ae5c31f
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/ipv4/stackx/spl_ip_addr.h
@@ -0,0 +1,162 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __LWIP_IP_ADDR_H__
+#define __LWIP_IP_ADDR_H__
+
+#include "spl_opt.h"
+#include "spl_def.h"
+#include "ip_module_api.h"
+#include "stackx_ip_addr.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/** ip_addr_t uses a struct for convenience only, so that the same defines can
+ * operate both on ip_addr_t as well as on ip_addr_p_t. */
+/* Forward declaration to not include netif.h */
+struct netif;
+#if BYTE_ORDER == BIG_ENDIAN
+
+/** Set an IPaddress given by the four byte-parts */
+#define SPL_IP4_ADDR(ipaddr, a, b, c, d) \
+ (ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \
+ ((u32_t)((b) & 0xff) << 16) | \
+ ((u32_t)((c) & 0xff) << 8) | \
+ (u32_t)((d) & 0xff)
+#else
+
+/** Set an IPaddress given by the four byte-parts.
+ Little-endian version that prevents the use of htonl. */
+#define SPL_IP4_ADDR(ipaddr, a, b, c, d) \
+ (ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \
+ ((u32_t)((c) & 0xff) << 16) | \
+ ((u32_t)((b) & 0xff) << 8) | \
+ (u32_t)((a) & 0xff)
+#endif
+
+/** memcpy-like copying of IPaddresses where addresses are known to be
+ * 16-bit-aligned if the port is correctly configured (so a port could define
+ * this to copying 2 u16_t's) - no NULL-pointer-checking needed. */
+#ifndef IPADDR2_COPY
+#define IPADDR2_COPY(dest, src) MEMCPY_S(dest, sizeof(ip_addr_t), src, sizeof(ip_addr_t))
+#endif
+
+/** Copy IPaddress - faster than spl_ip_addr_set: no NULL check */
+#define spl_ip_addr_copy(dest, src) ((dest).addr = (src).addr)
+
+/** Safely copy one IPaddress to another (src may be NULL) */
+#define spl_ip_addr_set(dest, src) ((dest)->addr = \
+ ((src) == NULL ? 0 : \
+ (src)->addr))
+
+/** Safely copy one IPaddress to another and change byte order
+ * from host- to network-order. */
+#define spl_ip_addr_set_hton(dest, src) ((dest)->addr = \
+ ((src) == NULL ? 0 : \
+ htonl((src)->addr)))
+
+/** Get the network address by combining host address with netmask */
+#define spl_ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr))
+
+/**
+ * Determine if two address are on the same network.
+ *
+ * @arg addr1 IPaddress 1
+ * @arg addr2 IPaddress 2
+ * @arg mask network identifier mask
+ * @return !0 if the network identifiers of both address match
+ */
+#define spl_ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
+ (mask)->addr) == \
+ ((addr2)->addr & \
+ (mask)->addr))
+
+/* && ((dest)->addr & tmp->netmask.addr) == (tmp->ip_addr.addr & tmp->netmask.addr) */
+/* add "netif = netif->root; \"*/
+#define ip_net_netif_cmp( dest, netif) ({ \
+ netif = netif->root; \
+ struct netif* tmp = netif; \
+ int find = 0; \
+ while(tmp) \
+ { \
+ if (is_in_same_network((dest)->addr, tmp->ip_addr.addr)) \
+ { \
+ netif->ip_addr.addr = tmp->ip_addr.addr; \
+ netif->netmask.addr = tmp->netmask.addr; \
+ find = 1; \
+ break; \
+ } \
+ if (netif->is_out) \
+ { \
+ break; \
+ } \
+ tmp = tmp->vnext; \
+ } \
+ (!!find); \
+ })
+
+/* Check if netif match dest , if not , find one and swap */
+/* add "netif = netif->root; \"*/
+
+#define ip_addr_netif_cmp_and_swap( dest, pnetif) ({ \
+ pnetif = pnetif->root; \
+ struct netif* tmp = pnetif; \
+ int find = 0; \
+ while(tmp) \
+ { \
+ if ((dest)->addr == tmp->ip_addr.addr) \
+ { \
+ pnetif->ip_addr.addr = tmp->ip_addr.addr; \
+ pnetif->netmask.addr = tmp->netmask.addr; \
+ find = 1; \
+ break; \
+ } \
+ if (pnetif->is_out) \
+ { \
+ break; \
+ } \
+ tmp = tmp->vnext; \
+ } \
+ (!!find); \
+ })
+
+#define ip_addr_netif_cmp( dest, pnetif) ({ \
+ pnetif = pnetif->root; \
+ struct netif* tmp = pnetif; \
+ int find = 0; \
+ while(tmp) \
+ { \
+ if ((dest)->addr == tmp->ip_addr.addr) \
+ { \
+ find = 1; \
+ break; \
+ } \
+ tmp = tmp->vnext; \
+ } \
+ (!!find); \
+ })
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __LWIP_IP_ADDR_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/netif/common.h b/stacks/lwip_stack/lwip_src/include/netif/common.h
new file mode 100644
index 0000000..45e9c8f
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/netif/common.h
@@ -0,0 +1,233 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+#include <stddef.h> /* for size_t */
+#include "stackx_common.h"
+#include "netif.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+//yyq
+
+/* define common names for structures shared between server and client */
+
+#define MP_STACKX_INSTANCE_POLL_NAME "VppTCP_instance_poll"
+#define MP_STACKX_PORT_ZONE "VppTCP_stackx_port_zone"
+#define MP_STACKX_PORT_INFO "VppTCP_stackx_port_info"
+#define MP_MEMPOLL_RX_NAME "VppTCP_MBUF_%u_%u_RX"
+#define MP_MEMPOLL_RXMSG_NAME "VppTCP_MSG_%u_%u_RX"
+#define MP_MEMPOLL_TX_NAME "VppTCP_MBUF_TX"
+#define MP_MEMPOLL_SEG_NAME "VppTCP_MBUF_SEG"
+#define MP_STACKX_MSG_NAME "VppTCP_msg"
+#define MP_STACKX_RING_NAME "VppTCP_%u_ring"
+#define MP_STACKX_LRING_NAME "VppTCP_%u_lring"
+
+#define MP_STACKX_BIT_SET_NAME "%s_bit_set"
+
+#define MP_STACKX_SOCKET_FREE_LIST_NAME "VppTCP_socket_list"
+
+#define MP_NETIF_LIST_NAME "VppTCP_Netif_list"
+
+/*
+ move sharemem create from App to nstackMain
+advice rename app_tx_mbuf to VppTCP_APP_TXBUF_POOL
+*/
+#define MP_STACKX_APP_TXBUF_POOL "app_tx_mbuf"
+
+#define MP_MEMPOLL_TCP_BUFF_NAME "VppTCP_MBUF_%u_TCP_BUFF"
+
+extern int spl_snprintf (char *buffer, int buflen, const char *format, ...);
+
+/*According to the number of network cards, the establishment of recv lring,
+ *each separate, each proc_id each NIC queue independent lring
+ */
+static inline const char *
+get_mempoll_rx_name (unsigned proc_id, unsigned nic_id)
+{
+ /* buffer for return value. Size calculated by %u being replaced
+ * by maximum 3 digits (plus an extra byte for safety)
+ * the id may reach 65535, need add more space*/
+ static char buffer[sizeof (MP_MEMPOLL_RX_NAME) + 32];
+
+ int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_RX_NAME, proc_id, nic_id); //???????????buffer??
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_mempoll_rxmsg_name (unsigned proc_id, unsigned nic_id)
+{
+ /* buffer for return value. Size calculated by %u being replaced
+ * by maximum 3 digits (plus an extra byte for safety)
+ * the id may reach 65535, need add more space*/
+ static char buffer[sizeof (MP_MEMPOLL_RXMSG_NAME) + 32];
+
+ int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_RXMSG_NAME, proc_id, nic_id); //???????????buffer??
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_mempoll_ring_name (unsigned proc_id)
+{
+ static char buffer[sizeof (MP_STACKX_RING_NAME) + 16];
+
+ int retVal =
+ spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_RING_NAME, proc_id);
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_mempoll_lring_name (unsigned proc_id)
+{
+ static char buffer[sizeof (MP_STACKX_LRING_NAME) + 16];
+
+ int retVal =
+ spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_LRING_NAME, proc_id);
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_mempoll_msg_name ()
+{
+ static char buffer[sizeof (MP_STACKX_MSG_NAME) + 16];
+
+ int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_MSG_NAME);
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_mempoll_tx_name ()
+{
+ /* buffer for return value. Size calculated by %u being replaced
+ * by maximum 3 digits (plus an extra byte for safety) */
+ static char buffer[sizeof (MP_MEMPOLL_TX_NAME) + 16];
+
+ int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_TX_NAME); //???????????buffer??
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_mempoll_seg_name ()
+{
+ /* buffer for return value. Size calculated by %u being replaced
+ * by maximum 3 digits (plus an extra byte for safety) */
+ static char buffer[sizeof (MP_MEMPOLL_SEG_NAME) + 16];
+
+ int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, MP_MEMPOLL_SEG_NAME); //???????????buffer??
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_memStatusBitSet_name (const char *name, unsigned int num)
+{
+ static char buffer[64];
+
+ int retVal =
+ spl_snprintf (buffer, sizeof (buffer) - 1, MP_STACKX_BIT_SET_NAME "%d",
+ name, num);
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_memNameWithProc (const char *name)
+{
+ static char buffer[64];
+
+ int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, "%s", name);
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+static inline const char *
+get_memInstancePoll_name (unsigned int type)
+{
+ static char buffer[sizeof (MP_STACKX_INSTANCE_POLL_NAME) + 32];
+ int retVal = spl_snprintf (buffer, sizeof (buffer) - 1, "%s" "%d",
+ MP_STACKX_INSTANCE_POLL_NAME, type);
+ if (-1 == retVal)
+ {
+ NSPOL_LOGERR ("spl_snprintf failed]");
+ return NULL;
+ }
+
+ return buffer;
+}
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif
diff --git a/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h b/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h
new file mode 100644
index 0000000..bcf4129
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/netif/kni_proc.h
@@ -0,0 +1,103 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _KNI_PROC_H_
+#define _KNI_PROC_H_
+#include <rte_kni.h>
+#include <rte_mempool.h>
+#include <rte_mbuf.h>
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define KNI_MAX_KTHREAD 32
+
+/* the kni is runned on the lcore from below on */
+#define DEFAULT_KNI_LCORE_BASE 24
+
+/* Structure of kni para */
+struct disp_kni_para
+{
+ u8_t queue_id;
+ u8_t port_id;
+};
+
+/*
+ * Structure of port parameters
+ */
+struct kni_port_params
+{
+ uint8_t port_id; /* Port ID */
+ unsigned lcore_rx; /* lcore ID for RX */
+ unsigned lcore_tx; /* lcore ID for TX */
+ uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */
+ uint32_t nb_kni; /* Number of KNI devices to be created */
+ unsigned lcore_k[KNI_MAX_KTHREAD]; /* lcore ID list for kthreads */
+ struct rte_kni *kni[KNI_MAX_KTHREAD]; /* KNI context pointers */
+ struct rte_mempool *kni_pktmbuf_pool;
+ u8_t ip_reconfigured;
+} __rte_cache_aligned;
+
+/* Structure type for storing kni interface specific stats */
+struct kni_interface_stats
+{
+ /* number of pkts received from NIC, and sent to KNI */
+ uint64_t rx_packets;
+
+ /* number of pkts received from NIC, but failed to send to KNI */
+ uint64_t rx_dropped;
+
+ /* number of pkts received from KNI, and sent to NIC */
+ uint64_t tx_packets;
+
+ /* number of pkts received from KNI, but failed to send to NIC */
+ uint64_t tx_dropped;
+};
+
+/* External interface for initilizing KNI subsystem */
+int kni_proc_init (enum rte_proc_type_t proc_type, int proc_id, u32_t pmask,
+ struct kni_port_params **kni_para);
+
+int kni_proc_init_secondary (int proc_id, int port_id);
+/* External interface for destroy KNI subsystem */
+void kni_proc_free (void);
+
+/* External interface for kni tx thread entry */
+void kni_tx_thread_cycle (void *arg);
+
+int kni_config_net (void);
+void kni_handler_eth_operate_request (int port);
+
+/* External interface for commiting packet to kni device */
+void kni_dispatch_to_kernel (uint8_t port_id,
+ struct rte_mbuf *pkts_burst[], uint8_t nb_rx);
+
+/* the lcore kni tx/rx thread run on */
+unsigned kni_get_tx_lcore (uint8_t port_id);
+unsigned kni_get_rx_lcore (uint8_t port_id);
+
+void init_kni (void);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /*#ifndef _KNI_PROC_H_ */
diff --git a/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h b/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h
new file mode 100644
index 0000000..99c3bc6
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/netif/sc_dpdk.h
@@ -0,0 +1,80 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef SC_DPDK_H_
+#define SC_DPDK_H_
+
+#include <pbuf.h>
+#include <sharedmemory.h>
+
+#include "lwip/etharp.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define NSTACK_CONFIG_SHM "nstack_config"
+
+#define MBUF_DATA_SIZE 2048
+#define MBUF_SIZE (MBUF_DATA_SIZE + sizeof(struct common_mem_mbuf) + COMMON_PKTMBUF_HEADROOM)
+
+extern int g_nstack_bind_cpu;
+
+inline uint16_t spl_mbuf_refcnt_update (void *mbuf, int16_t value);
+struct stack_proc_content *get_stack_proc_content ();
+
+inline int spl_msg_malloc (data_com_msg ** p_msg_entry);
+#define spl_msg_free(p_msg_entry) msg_free(p_msg_entry)
+struct spl_pbuf *spl_mbuf_malloc (uint16_t len, spl_pbuf_type type,
+ u16_t * count);
+
+inline void spl_mbuf_free (void *mbuf);
+
+inline int spl_set_lcore_id (unsigned dest_lcore_id);
+
+static inline unsigned
+spl_get_lcore_id ()
+{
+ unsigned core_id = 0;
+
+#if (DPDK_MODULE != 1)
+#ifdef HAL_LIB
+#else
+ core_id = rte_lcore_id ();
+#endif
+ if (core_id >= MAX_THREAD_NUM)
+ {
+ core_id = 0;
+ }
+#endif
+
+ return core_id;
+}
+
+int set_share_config ();
+
+int init_instance ();
+
+void printmeminfo ();
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#endif /* SERVER_DPDK_H_ */
diff --git a/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h b/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h
new file mode 100644
index 0000000..0a92ea0
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/netif/sharedmemory.h
@@ -0,0 +1,148 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef SHAREDMEMORY_H_
+#define SHAREDMEMORY_H_
+#include "stackxopts.h"
+#include <sys/types.h>
+#include <semaphore.h>
+//#include "stackx/raw.h"
+#include "tcp.h"
+#include "udp.h"
+//#include "stackx/ip.h"
+#include "spl_err.h"
+#include "list.h"
+#include "arch/queue.h"
+#include "spl_opt.h"
+#include "stackx/spl_ip_addr.h"
+
+#include "stackx/spl_api.h"
+#include <arch/sys_arch.h>
+#include "common_mem_api.h"
+//#include "stackx/memp.h"
+#include "stackx_instance.h"
+
+#include "hal_api.h"
+#ifdef HAL_LIB
+#else
+#include "rte_ring.h"
+#endif
+
+/** Description for a task waiting in select */
+struct stackx_select_cb
+{
+ /** Pointer to the next waiting task */
+ union
+ {
+ struct stackx_select_cb *next;
+ PTR_ALIGN_TYPE next_a;
+ };
+
+ /** Pointer to the previous waiting task */
+ union
+ {
+ struct stackx_select_cb *prev;
+ PTR_ALIGN_TYPE prev_a;
+ };
+
+ /** semaphore to wake up a task waiting for select */
+ //sys_sem_t sem;
+ union
+ {
+ sys_sem_t_v1 sem;
+ PTR_ALIGN_TYPE sem_a;
+ };
+
+ /** readset passed to select */
+ fd_set readset;
+
+ /** writeset passed to select */
+ fd_set writeset;
+
+ /** unimplemented: exceptset passed to select */
+ fd_set exceptset;
+
+ /** don't signal the same semaphore twice: set to 1 when signalled */
+ volatile int sem_signalled;
+
+ uint8_t pad_64bit[4];
+};
+/** From epoll.h: Definition of struct stackx_sock and stackx_select_cb ---------End*/
+
+enum tcp_run_type
+{
+ TCP_MUTIPL_INSTANCE = 0,
+ TCP_MASTER_WORKER,
+ TCP_DISTRIBUTOR_WORKER,
+ TCP_RUN_TO_COMPETE,
+ TCP_PROC_TYPE_END
+};
+
+enum proc_run_type
+{
+ PROC_MAIN_RUN_TYPE = 0,
+ PROC_BACKUP_RUN_TYPE,
+ PROC_RUN_TYPE_END
+};
+
+struct linux_port_info
+{
+ char if_name[HAL_MAX_NIC_NAME_LEN];
+ char ip_addr_linux[18]; //uint32_t ip_addr_linux;
+ char mask_linux[18]; //uint32_t mask_linux;
+ char bcast_linux[18]; //uint32_t bcast_linux;
+ char mac_addr[20]; //struct ether_addr mac_addr;
+ hal_hdl_t hdl;
+};
+
+struct stackx_port_info
+{
+ struct stackx_port_info *next_use_port;
+ struct linux_port_info linux_ip;
+};
+
+struct stackx_port_zone
+{
+ unsigned int port_num;
+ unsigned int bonded_port_num;
+ struct stackx_port_info *stackx_one_port;
+};
+
+struct select_cb_entry
+{
+ struct stackx_select_cb select_cb;
+
+ union
+ {
+ sem_t semForSelect;
+ ALIGN_TYPE pad_64bit[4];
+ };
+
+ union
+ {
+ struct select_cb_entry *pre_empty_entry;
+ PTR_ALIGN_TYPE pre_empty_entry_a;
+ };
+
+ union
+ {
+ struct select_cb_entry *next_empty_entry;
+ PTR_ALIGN_TYPE next_empty_entry_a;
+ };
+
+};
+
+#endif /* SHAREDMEMORY_H_ */
diff --git a/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h b/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h
new file mode 100644
index 0000000..ca56663
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/netif/spl_hal.h
@@ -0,0 +1,114 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef SPL_HAL_H_
+#define SPL_HAL_H_
+
+#include "hal_api.h"
+#include "netif.h"
+#include "nsfw_maintain_api.h"
+#include "stackx_spl_share.h"
+#include "stackx_pbuf_comm.h"
+#include "netifapi.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+int spl_hal_init (int argc, char *argv[]);
+int spl_hal_port_init ();
+
+int spl_hal_stats_display (struct netif *pnetif, char *str, u32_t len,
+ char *json, u32_t json_len);
+
+err_t spl_hal_output (struct netif *netif, struct pbuf *buf);
+void spl_hal_input (struct netif *netif, struct spl_pbuf **buf);
+
+inline u16_t spl_hal_recv (struct netif *netif, u8_t id);
+
+int spl_hal_tx_ip_cksum_enable ();
+int spl_hal_tx_udp_cksum_enable ();
+int spl_hal_tx_tcp_cksum_enable ();
+
+u32 spl_hal_is_nic_exist (const char *name);
+
+int spl_hal_is_bond_netif (struct netif *pnetif);
+
+static inline void
+spl_do_dump (struct spl_pbuf *p, u16 direction)
+{
+ struct spl_pbuf *q = p;
+ while (q)
+ {
+ ntcpdump (q->payload, q->len, direction);
+ q = q->next;
+ }
+}
+
+/* information of bond*/
+#define MAX_BOND_PORT_NUM 4
+
+/* information of one bond port */
+struct bond_set
+{
+ char bond_port_name[HAL_MAX_NIC_NAME_LEN];
+ char slave_ports[HAL_MAX_SLAVES_PER_BOND][HAL_MAX_NIC_NAME_LEN];
+ u8_t slave_port_cnt;
+};
+
+#define NETIF_ETH_ADDR_LEN 6
+
+/* information of all bond ports */
+struct bond_ports_info
+{
+ u8_t cnt;
+ struct bond_set ports[MAX_BOND_PORT_NUM];
+};
+
+struct ether_addr
+{
+ u8_t addr_bytes[NETIF_ETH_ADDR_LEN];
+
+};
+
+struct netif *get_netif_by_ip (unsigned int ip);
+struct netif *netif_check_broadcast_addr (spl_ip_addr_t * addr);
+struct netifExt *getNetifExt (u16_t id);
+int netifExt_add (struct netif *netif);
+
+int add_netif_ip (char *netif_name, unsigned int ip, unsigned int mask);
+int del_netif_ip (char *netif_name, unsigned int ip);
+
+err_t spl_netifapi_netif_add (struct netif *pnetif,
+ spl_ip_addr_t * ipaddr,
+ spl_ip_addr_t * netmask,
+ spl_ip_addr_t * gw,
+ void *state,
+ netif_init_fn init,
+ netif_input_fn input,
+ netifapi_void_fn voidfunc);
+struct netif *find_netif_by_if_name (char *if_name);
+void ethernetif_packets_input (struct netif *pstnetif);
+err_t ethernetif_init (struct netif *pnetif);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#endif /* SPL_HAL_H_ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h b/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h
new file mode 100644
index 0000000..584ab06
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/internal_msg.h
@@ -0,0 +1,90 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __internal_msg_h__
+#define __internal_msg_h__
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#include "nsfw_msg.h"
+#include "netif.h"
+#include "lwip/netifapi.h"
+#include "ip_module_api.h"
+
+enum netif_msg_type
+{
+ NETIF_DO_ADD,
+ NETIF_MSG_API_MAX = MAX_MINOR_TYPE
+};
+
+/* NETIF_DO_ADD */
+typedef struct msg_add_netif_T
+{
+ void (*function) (struct msg_add_netif_T * m);
+ struct netif *netif;
+ spl_ip_addr_t *ipaddr;
+ spl_ip_addr_t *netmask;
+ spl_ip_addr_t *gw;
+ void *state;
+ netif_init_fn init;
+ netif_input_fn input;
+ netifapi_void_fn voidfunc;
+ /* no need to extend member */
+} msg_add_netif;
+
+typedef struct
+{
+ ip_module_type type;
+ ip_module_operate_type operate_type;
+ void *arg;
+} msg_ip_module;
+
+typedef struct msg_internal_callback_T
+{
+ void (*function) (void *ctx);
+ void *ctx;
+} msg_internal_callback;
+
+enum timer_msg_type
+{
+ TIMER_MSG_TIMEOUT,
+ TIMER_MSG_CLEAR,
+ TIMER_MSG_MAX = MAX_MINOR_TYPE
+};
+
+typedef struct msg_timer_T
+{
+ void *act;
+ void *arg;
+} msg_timer;
+
+enum mt_msg_type
+{
+ MT_MSG_VER_MGR,
+ MT_MSG_MAX = MAX_MINOR_TYPE
+};
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __internal_msg_h__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h
new file mode 100644
index 0000000..ea63e90
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_api.h
@@ -0,0 +1,276 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __SPL_API_H__
+#define __SPL_API_H__
+
+#include "opt.h"
+#include "common_mem_base_type.h"
+#include <stddef.h> /* for size_t */
+#include "arch/queue.h"
+#include "arch/sys_arch.h"
+#include "arch/atomic_32.h"
+#include "stackx_common_opt.h"
+#include "stackx_spl_share.h"
+
+/* From lwip */
+#include "api.h"
+#include "sys.h"
+#include "sys_arch.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define MAX_WAIT_TIMEOUT 0x7FFFFFFF
+
+/* Throughout this file, IPaddresses and port numbers are expected to be in
+ * the same byte order as in the corresponding pcb.
+ */
+
+/* Flags for struct netconn.flags (u8_t) */
+
+/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
+ this temporarily stores whether to wake up the original application task
+ if data couldn't be sent in the first try. */
+#define SPL_NETCONN_FLAG_WRITE_DELAYED 0x01
+
+/** Should this netconn avoid blocking? */
+#define SPL_NETCONN_FLAG_NON_BLOCKING 0x02
+
+/** Was the last connect action a non-blocking one? */
+#define SPL_NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04
+
+/** If this is set, a TCP netconn must call netconn_recved() to update
+ the TCP receive window (done automatically if not set). */
+#define SPL_NETCONN_FLAG_NO_AUTO_RECVED 0x08
+
+/** If a nonblocking write has been rejected before, poll_tcp needs to
+ check if the netconn is writable again */
+// #define NETCONN_FLAG_CHECK_WRITESPACE 0x10
+
+enum stackx_model
+{
+ SOCKET_STACKX = 0,
+ CALLBACK_STACKX
+};
+
+enum callback_type
+{
+ API_ACCEPT_EVENT = 0xF0,
+ API_RECV_EVENT,
+ API_SEND_EVENT,
+ API_CLOSE_EVENT
+};
+#if 1
+/** Use to inform the callback function about changes */
+enum spl_netconn_evt
+{
+ SPL_NETCONN_EVT_RCVPLUS,
+ SPL_NETCONN_EVT_RCVMINUS,
+ SPL_NETCONN_EVT_SENDPLUS,
+ SPL_NETCONN_EVT_SENDMINUS,
+ SPL_NETCONN_EVT_ERROR,
+ SPL_NETCONN_EVT_HUP,
+ SPL_NETCONN_EVT_RDHUP,
+ SPL_NETCONN_EVT_AGAIN,
+ SPL_NETCONN_EVT_ACCEPT
+};
+#endif
+enum
+{
+ INET_ECN_NOT_ECT = 0,
+ INET_ECN_ECT_1 = 1,
+ INET_ECN_ECT_0 = 2,
+ INET_ECN_CE = 3,
+ INET_ECN_MASK = 3,
+};
+
+#define SPL_NETCONNTYPE_GROUP(t) (t & 0xF0)
+#define SPL_NETCONNTYPE_DATAGRAM(t) (t & 0xE0)
+
+/* forward-declare some structs to avoid to include their headers */
+typedef struct common_pcb
+{
+ enum stackx_model model;
+
+ int socket;
+
+ /** type of the netconn (TCP, UDP or RAW) */
+ enum spl_netconn_type type;
+
+ /* share memory between sbr and stackx */
+ spl_netconn_t *conn;
+
+ u16 bind_thread_index;
+ u8 close_progress;
+ u8 recv_ring_not_empty;
+
+ /** TCP: when data passed to netconn_write doesn't fit into the send buffer,
+ this temporarily stores the message.
+ Also used during connect and close.
+ */
+ data_com_msg *current_msg;
+
+ msg_write_buf *msg_head;
+ msg_write_buf *msg_tail;
+
+ size_t write_offset;
+
+ /** timeout to wait for new data to be received
+ (or connections to arrive for listening netconns) */
+ int recv_timeout;
+
+ /* timeout to wait for send buffer writtable */
+ int send_timeout;
+
+ int sk_rcvlowat;
+
+ //DFX stat for connection packet
+ /* dfx_conn_t dfx; */
+
+ /*store the hostpid info for release */
+ uint32_t hostpid;
+ u8_t l4_tick; /* if is odd number, use l4 ring first */
+ u8_t dataSentFlag;
+
+ nsfw_res res_chk;
+} common_pcb;
+
+/** A callback prototype to inform about events for a netconn */
+//typedef void (*netconn_callback)(struct spl_netconn *, enum netconn_evt, u16_t len);
+
+/* Though these callback pointers are not set and referenced in nStack Core, still
+the padding is required since the structure will be used in netconn and it needs
+padding across 32-bit and 64-bit architecture */
+typedef struct
+{
+ union
+ {
+ int (*accept_event) (struct spl_netconn * conn);
+ PTR_ALIGN_TYPE accept_event_a;
+ };
+
+ union
+ {
+ int (*recv_event) (struct spl_netconn * conn);
+ PTR_ALIGN_TYPE recv_event_a;
+ };
+ union
+ {
+ int (*send_event) (struct spl_netconn * conn);
+ PTR_ALIGN_TYPE send_event_a;
+ };
+ union
+ {
+ int (*close_event) (struct spl_netconn * conn);
+ PTR_ALIGN_TYPE close_event_a;
+ };
+} callback_funcation;
+
+union ring_addr_u
+{
+ void *ring_addr;
+ PTR_ALIGN_TYPE ring_addr_a;
+};
+
+struct mem_manage
+{
+ volatile uint32_t current_read;
+ volatile uint32_t current_write;
+ union ring_addr_u ring_addr[RECV_MAX_POOL];
+ union ring_addr_u l4_ring; /* recv ring for l4 */
+ //void *ring_addr[RECV_MAX_POOL];
+};
+
+/* Pbuf free should be done in network stack */
+struct spl_netconn_recvbuf_recoder
+{
+ struct spl_pbuf *head;
+ struct spl_pbuf *tail;
+ int totalLen;
+};
+
+/** Register an Network connection event */
+void spl_event_callback (spl_netconn_t * conn, enum spl_netconn_evt evt,
+ int postFlag);
+
+#define SPL_API_EVENT(c, e, p) spl_event_callback(c, e, p)
+
+/** Set conn->last_err to err but don't overwrite fatal errors */
+#define SPL_NETCONN_SET_SAFE_ERR(conn, err) do { \
+ SYS_ARCH_PROTECT(lev); \
+ if (!ERR_IS_FATAL((conn)->last_err)) { \
+ (conn)->last_err = err; \
+ } \
+ SYS_ARCH_UNPROTECT(lev); \
+ } while (0);
+
+/** Set the blocking status of netconn calls (@todo: write/send is missing) */
+#define spl_netconn_set_nonblocking(conn, val) do { if (val) { \
+ (conn)->flags |= SPL_NETCONN_FLAG_NON_BLOCKING; \
+ } else { \
+ (conn)->flags &= ~SPL_NETCONN_FLAG_NON_BLOCKING; }} while (0)
+
+/** Get the blocking status of netconn calls (@todo: write/send is missing) */
+#define spl_netconn_is_nonblocking(conn) (((conn)->flags & SPL_NETCONN_FLAG_NON_BLOCKING) != 0)
+
+/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
+#define spl_netconn_set_noautorecved(conn, val) do { if (val) { \
+ (conn)->flags |= SPL_NETCONN_FLAG_NO_AUTO_RECVED; \
+ } else { \
+ (conn)->flags &= ~SPL_NETCONN_FLAG_NO_AUTO_RECVED; }} while (0)
+
+/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
+#define spl_netconn_get_noautorecved(conn) (((conn)->flags & SPL_NETCONN_FLAG_NO_AUTO_RECVED) != 0)
+
+/** Set the receive timeout in milliseconds */
+#define spl_netconn_set_recvtimeout(cpcb, timeout) ((cpcb)->recv_timeout = (timeout))
+
+/** Get the receive timeout in milliseconds */
+#define spl_netconn_get_recvtimeout(cpcb) ((cpcb)->recv_timeout)
+
+/** Set the send timeout in milliseconds */
+#define spl_netconn_set_sendtimeout(cpcb, timeout) ((cpcb)->send_timeout = (timeout))
+
+/** Get the send timeout in milliseconds */
+#define spl_netconn_get_sendtimeout(cpcb) ((cpcb)->send_timeout)
+
+#define spl_netconn_set_sendbufsize(conn, sendbufsize) ((conn)->send_bufsize = (sendbufsize))
+
+/* "man 7 socket" information
+ SO_SNDBUF
+ Sets or _gets the maximum socket send buffer in bytes. The kernel doubles
+ this value (to allow space for bookkeeping overhead) when it is set using
+ setsockopt(2), and this doubled value is returned by getsockopt(2).
+*/
+#define spl_netconn_get_sendbufsize(conn) (2 *((conn)->send_bufsize))
+
+#define spl_netconn_set_reclowbufsize(cpcb, recvlowbufsize) ((cpcb)->sk_rcvlowat = ((recvlowbufsize) > 0) ? recvlowbufsize : 1)
+#define spl_netconn_get_reclowbufsize(cpcb) ((cpcb)->sk_rcvlowat)
+
+extern int spl_post_msg (u16 mod, u16 maj, u16 min, u16 op, char *data,
+ u16 data_len, u32 src_pid);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __LWIP_API_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h
new file mode 100644
index 0000000..94b681e
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_api_msg.h
@@ -0,0 +1,129 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __LWIP_API_MSG_H__
+#define __LWIP_API_MSG_H__
+
+#include <stddef.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+
+#include "nsfw_msg.h"
+#include "spl_opt.h"
+#include "spl_ip_addr.h"
+#include "spl_err.h"
+#include "spl_api.h"
+//#include "sockets.h"
+#include "stackx_spl_share.h"
+#include "stackx_spl_msg.h"
+
+/* From lwip */
+#include "tcp.h"
+#include "udp.h"
+#include "sys.h"
+
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/* For the netconn API, these values are use as a bitmask! */
+#define NETCONN_SHUT_RD 1
+#define NETCONN_SHUT_WR 2
+#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR)
+
+struct callback_fn
+{
+ tcp_sent_fn sent_fn;
+ tcp_recv_fn recv_fn;
+ tcp_connected_fn connected_fn;
+ tcp_poll_fn poll_fn;
+ tcp_err_fn err_fn;
+ tcp_err_fn close_fn;
+ tcp_accept_fn accept_fn;
+};
+
+#ifdef HAL_LIB
+#else
+typedef enum _mbuf_recyle_flg
+{
+ MBUF_UNUSED = 0,
+ MBUF_HLD_BY_APP = 1,
+ MBUF_HLD_BY_SPL = 2,
+} mbuf_recycle_flg;
+#endif
+
+err_t sp_enqueue (struct common_pcb *cpcb, void *p);
+err_t accept_dequeue (spl_netconn_t * lconn, void **new_buf,
+ u32_t timeout /*miliseconds */ );
+err_t accept_enqueue (spl_netconn_t * conn, void *p);
+void free_conn_by_spl (spl_netconn_t * conn);
+void unlink_pcb (struct common_pcb *cpcb);
+void do_try_delconn (void *close_data, u32 delay_sec);
+void do_delconn (struct common_pcb *cpcb, msg_delete_netconn * msg);
+void do_bind (struct common_pcb *cpcb, msg_bind * msg);
+void do_pbuf_free (struct spl_pbuf *buf);
+void do_connect (struct common_pcb *cpcb, msg_connect * msg);
+void do_listen (struct common_pcb *cpcb, msg_listen * msg);
+void do_send (struct common_pcb *cpcb, msg_send_buf * msg);
+void do_recv (struct common_pcb *cpcb, msg_recv_buf * msg);
+void do_write (struct common_pcb *cpcb, msg_write_buf * msg);
+void do_getaddr (struct common_pcb *cpcb, msg_getaddrname * msg);
+void do_close (struct common_pcb *cpcb, msg_close * msg);
+void do_getsockopt_internal (struct common_pcb *cpcb,
+ msg_setgetsockopt * smsg);
+void do_setsockopt_internal (struct common_pcb *cpcb,
+ msg_setgetsockopt * smsg);
+void do_getsockname (struct common_pcb *cpcb, msg_getaddrname * amsg);
+int netconn_drain (enum spl_netconn_type t, spl_netconn_t * conn);
+int spl_pcb_new (msg_new_netconn * m);
+void do_app_touch (msg_app_touch * smsg);
+int do_close_finished (struct common_pcb *cpcb, u8_t close_finished,
+ u8_t shut, err_t err, int OpShutDown);
+err_t do_writemore (struct spl_netconn *conn);
+err_t do_close_internal (struct common_pcb *cpcb, int OpShutDown);
+
+u8 get_shut_op (data_com_msg * m);
+int ks_to_stk_opt (int opt);
+void update_tcp_state (spl_netconn_t * conn, enum tcp_state state);
+
+err_t spl_poll_tcp (void *arg, struct tcp_pcb *pcb);
+err_t spl_recv_tcp (void *arg, struct tcp_pcb *pcb, struct pbuf *p,
+ err_t err);
+err_t spl_sent_tcp (void *arg, struct tcp_pcb *pcb, u16_t len);
+void spl_err_tcp (void *arg, err_t err);
+err_t spl_tcp_recv_null (void *arg, struct tcp_pcb *pcb, struct pbuf *p,
+ err_t err);
+err_t spl_do_connected (void *arg, struct tcp_pcb *pcb, err_t err);
+err_t spl_accept_function (void *arg, struct tcp_pcb *newpcb, err_t err);
+
+struct common_pcb *alloc_common_pcb ();
+void free_common_pcb (struct common_pcb *cpcb);
+int common_pcb_init (struct common_pcb *cpcb);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __LWIP_API_MSG_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h
new file mode 100644
index 0000000..a0188be
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_err.h
@@ -0,0 +1,40 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_ERR_H__
+#define __STACKX_ERR_H__
+
+#include "spl_opt.h"
+#include "lwip/arch.h"
+#include "stackx_err.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+typedef s8_t err_t;
+
+/* Definitions for error constants. */
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __LWIP_ERR_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h
new file mode 100644
index 0000000..697c67d
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_instance.h
@@ -0,0 +1,30 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _SPL_INSTANCE_H_
+#define _SPL_INSTANCE_H_
+#include "nsfw_msg_api.h"
+#include "stackx_instance.h"
+
+extern stackx_instance *p_def_stack_instance;
+
+int spl_process (data_com_msg * m);
+
+void add_disp_netif (struct netif *netif);
+void do_update_pcbstate ();
+void init_stackx_lwip ();
+
+#endif /* _SPL_INSTANCE_H_ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h
new file mode 100644
index 0000000..cd2e1bf
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_netbuf.h
@@ -0,0 +1,52 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __LWIP_NETBUF_H__
+#define __LWIP_NETBUF_H__
+
+#include "spl_opt.h"
+#include "spl_pbuf.h"
+#include "spl_ip_addr.h"
+#include "common_mem_base_type.h"
+#include "common_mem_pal.h"
+#include "common_pal_bitwide_adjust.h"
+#include "stackx_netbuf.h"
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/** This spl_netbuf has dest-addr/port set */
+#define NETBUF_FLAG_DESTADDR 0x01
+
+/** This spl_netbuf includes a checksum */
+#define NETBUF_FLAG_CHKSUM 0x02
+
+void spl_netbuf_delete (struct spl_netbuf *buf);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __LWIP_NETBUF_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h
new file mode 100644
index 0000000..01fe242
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_pbuf.h
@@ -0,0 +1,173 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_PBUF_H__
+#define __STACKX_PBUF_H__
+
+#include "cc.h"
+
+#include "common_mem_base_type.h"
+#include "stackx_pbuf_comm.h"
+#include "common_mem_mbuf.h"
+
+#ifdef HAL_LIB
+#else
+#include "common_pal_bitwide_adjust.h"
+#endif
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+extern u16_t g_offSetArry[SPL_PBUF_MAX_LAYER];
+
+/** indicates this pbuf is loop buf .*/
+#define PBUF_FLAG_LOOPBUF 0x08U
+
+#define PBUF_SET_LOOP_FLAG(buf) ((buf)->flags |= PBUF_FLAG_LOOPBUF)
+#define PBUF_IS_LOOP_BUF(buf) ((buf)->flags & PBUF_FLAG_LOOPBUF)
+
+/*Add 1 parameter, the last one, indicating which dpdk_malloc
+ *should be allocated from the pool; non-PBUF_ALLOC type regardless of this parameter*/
+struct spl_pbuf *spl_pbuf_alloc_hugepage (spl_pbuf_layer l, u16_t length,
+ spl_pbuf_type type,
+ u16_t thread_index, void *net_conn);
+struct pbuf *spl_convert_spl_pbuf_to_pbuf (struct spl_pbuf *p_from);
+err_t pbuf_to_splpbuf_copy (struct spl_pbuf *p_to, struct pbuf *p_from);
+err_t splpbuf_to_pbuf_copy (struct pbuf *p_to, struct spl_pbuf *p_from);
+spl_pbuf_layer get_pbuf_layer_from_pbuf_payload (struct pbuf *buf);
+void print_pbuf_payload_info (struct pbuf *buf, bool send);
+
+static inline u8_t
+spl_pbuf_header (struct spl_pbuf *p, s16_t header_size_increment)
+{
+ u8_t pbuf_ret;
+ /* header max len is tcp len+ ip len: 0xf*4+PBUF_IP_HLEN */
+ if (unlikely
+ (((header_size_increment) < 0 && (-(header_size_increment)) > p->len)
+ || (header_size_increment > 0
+ && (header_size_increment) >= (0xf * 4 + SPL_PBUF_IP_HLEN))))
+ {
+ pbuf_ret = 1;
+ }
+ else
+ {
+ p->payload_a = p->payload_a - (header_size_increment);
+ p->len += (header_size_increment);
+ p->tot_len += (header_size_increment);
+ pbuf_ret = 0;
+ }
+ return pbuf_ret;
+}
+
+void spl_pbuf_realloc (struct spl_pbuf *p, u32_t size);
+
+void spl_pbuf_cat (struct spl_pbuf *head, struct spl_pbuf *tail);
+void spl_pbuf_free (struct spl_pbuf *p);
+
+#define pbuf_free_safe(x)\
+{\
+ spl_pbuf_free((x));\
+ (x) = NULL;\
+}
+
+/**
+ * Count number of pbufs in a chain
+ *
+ * @param p first pbuf of chain
+ * @return the number of pbufs in a chain
+ */
+static inline u16_t
+spl_pbuf_clen (struct spl_pbuf *p)
+{
+ u16_t len = 0;
+ while (p != NULL)
+ {
+ ++len;
+ p = (struct spl_pbuf *) ADDR_SHTOL (p->next_a);
+ }
+ return len;
+}
+
+static inline u16_t
+mbuf_count (struct spl_pbuf *p)
+{
+ u16_t count = 0;
+ struct spl_pbuf *buf = p;
+ struct common_mem_mbuf *mbuf;
+ while (buf)
+ {
+ mbuf =
+ (struct common_mem_mbuf *) ((char *) buf -
+ sizeof (struct common_mem_mbuf));
+ while (mbuf)
+ {
+ count++;
+#ifdef HAL_LIB
+#else
+ mbuf = mbuf->next;
+#endif
+ }
+ buf = (struct spl_pbuf *) ADDR_SHTOL (buf->next_a); //buf->next;
+ }
+ return count;
+}
+
+static inline u16_t
+mbuf_count_in_one_pbuf (struct spl_pbuf *p)
+{
+
+ u16_t cnt = 0;
+ struct common_mem_mbuf *mbuf;
+ if (NULL == p)
+ {
+ NSPOL_LOGERR ("Invalid param : p(null) !");
+ return 0;
+ }
+
+ mbuf =
+ (struct common_mem_mbuf *) ((char *) p - sizeof (struct common_mem_mbuf));
+
+ /* no need to check mbuf itself */
+#ifdef HAL_LIB
+#else
+ if (!mbuf->next)
+#endif
+ return 1;
+
+ while (mbuf)
+ {
+ ++cnt;
+#ifdef HAL_LIB
+#else
+ mbuf = mbuf->next;
+#endif
+ }
+
+ return cnt;
+}
+
+inline int pbuf_internal_copy (struct spl_pbuf *dst, struct spl_pbuf *src);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __STACKX_PBUF_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h
new file mode 100644
index 0000000..a4d6ccc
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_sbr.h
@@ -0,0 +1,33 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef _SPL_SBR_H_
+#define _SPL_SBR_H_
+#include "nsfw_msg_api.h"
+#include "tcp.h"
+#include "udp.h"
+//#include "stackx/raw.h"
+#define COMM_PRIVATE_PTR(m) \
+ ((m->param.receiver) ? ((struct common_pcb *)m->param.comm_receiver) : 0)
+#define TCP_PRIVATE_PTR(m) \
+ ((m->param.receiver) ? (*(struct tcp_pcb **)m->param.receiver) : 0)
+#define UDP_PRIVATE_PTR(m) \
+ ((m->param.receiver) ? (*(struct udp_pcb **)m->param.receiver) : 0)
+/*#define RAW_PRIVATE_PTR(m) \
+ ((m->param.receiver) ? (*(void *)m->param.receiver) : 0) */
+
+int spl_sbr_process (data_com_msg * m);
+#endif /* _SPL_SBR_H_ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h
new file mode 100644
index 0000000..278bb02
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_sockets.h
@@ -0,0 +1,252 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_SOCKETS_H__
+#define __STACKX_SOCKETS_H__
+
+#include <errno.h>
+#include <stddef.h> /* for size_t */
+#include "arch/sys_arch.h"
+#include "sys/socket.h"
+#include <errno.h>
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#ifndef socklen_t
+#define socklen_t u32_t
+#endif
+
+#define SET_STACKP_ERRNO(err) (errno = (err)) //thread-local errno
+
+#ifndef set_errno
+#define set_errno(err) SET_STACKP_ERRNO(err)
+#endif
+
+#define sock_set_errno(sk, e) do { \
+ (sk)->err = (e); \
+ if ((sk)->err != 0) \
+ set_errno((sk)->err); \
+ } while (0)
+
+#ifndef __BITS_SOCKET_H
+/* Socket protocol types (TCP/UDP/RAW) */
+#define SOCK_STREAM 1
+#define SOCK_DGRAM 2
+#define SOCK_RAW 3
+/*
+ * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c)
+ */
+#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info storing */
+#define SO_REUSEADDR 0x0002
+#endif
+
+#define SO_DONTROUTE 5 //0x0010 /* Unimplemented: just use interface addresses */
+#define SO_BROADCAST 6 //0x0020 /* permit to send and to receive broad cast messages*/
+#define SO_KEEPALIVE 9 //0x0008 gaussdb /* keep connections alive */
+#define SO_OOBINLINE 10 //0x0100 /* Unimplemented: leave received OOB data in line */
+#define SO_LINGER 13 //0x0080 /* linger on close if data present */
+#define SO_REUSEPORT 15 /* Unimplemented: allow local address & port reuse */
+#define SO_ACCEPTCONN 30 //0x0002 /* socket has had listen() */
+#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
+
+#define SO_DONTLINGER ((int)(~SO_LINGER))
+
+/*
+ * Additional options, not kept in so_options.
+ */
+#define SO_TYPE 3 /* get socket type */
+#define SO_ERROR 4
+#define SO_SNDBUF 7 /* send buffer size */
+#define SO_RCVBUF 8 /* receive buffer size */
+#define SO_NO_CHECK 11 /* don't create UDP checksum */
+#define SO_RCVLOWAT 18 /* receive low-water mark */
+#define SO_SNDLOWAT 19 /* send low-water mark */
+#define SO_RCVTIMEO 20 /* receive timeout */
+#define SO_SNDTIMEO 21 /* Unimplemented: send timeout */
+
+#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */
+
+/*
+ * Level number for (get/set)sockopt() to apply to socket itself.
+ */
+#define SOL_SOCKET 1 //0xfff
+
+#ifndef __BITS_SOCKET_H
+
+#define AF_UNSPEC 0
+#define PF_UNSPEC AF_UNSPEC
+#define AF_INET 2
+#define PF_INET AF_INET
+
+#define IPPROTO_TCP 6
+#define IPPROTO_UDP 17
+#define IPPROTO_UDPLITE 136
+
+#define IPPROTO_IP 0
+
+#define MSG_PEEK 0x02
+#define MSG_WAITALL 0x100
+#define MSG_OOB 0x01
+#define MSG_DONTWAIT 0x40
+#define MSG_MORE 0x8000
+#endif
+
+#define IP_TOS 1
+#define IP_TTL 2
+
+#define RCV_WND 0x21
+#define RCV_ANN_WND 0x22
+#define INIT_CWND 0x23
+#define THRESHOLD_FACTOR 0x24
+#define TMR_INTERVAL 0x25
+
+/*
+ * Options and types for UDP multicast traffic handling
+ */
+#ifndef __BITS_SOCKET_H
+#define IP_ADD_MEMBERSHIP 3
+#define IP_DROP_MEMBERSHIP 4
+#define IP_MULTICAST_TTL 5
+#define IP_MULTICAST_IF 6
+#define IP_MULTICAST_LOOP 7
+#endif
+
+/*
+ * The Type of Service provides an indication of the abstract
+ * parameters of the quality of service desired. These parameters are
+ * to be used to guide the selection of the actual service parameters
+ * when transmitting a datagram through a particular network. Several
+ * networks offer service precedence, which somehow treats high
+ * precedence traffic as more important than other traffic (generally
+ * by accepting only traffic above a certain precedence at time of high
+ * load). The major choice is a three way tradeoff between low-delay,
+ * high-reliability, and high-throughput.
+ * The use of the Delay, Throughput, and Reliability indications may
+ * increase the cost (in some sense) of the service. In many networks
+ * better performance for one of these parameters is coupled with worse
+ * performance on another. Except for very unusual cases at most two
+ * of these three indications should be set.
+ */
+#define IPTOS_LOWCOST 0x02
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_TOS_MASK 0x1E
+#define IPTOS_MINCOST IPTOS_LOWCOST
+#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
+
+/*
+ * The Network Control precedence designation is intended to be used
+ * within a network only. The actual use and control of that
+ * designation is up to each network. The Internetwork Control
+ * designation is intended for use by gateway control originators only.
+ * If the actual use of these precedence designations is of concern to
+ * a particular network, it is the responsibility of that network to
+ * control the access to, and use of, those precedence designations.
+ */
+#define IPTOS_PREC_ROUTINE 0x00
+#define IPTOS_PREC_PRIORITY 0x20
+#define IPTOS_PREC_IMMEDIATE 0x40
+#define IPTOS_PREC_FLASH 0x60
+#define IPTOS_PREC_FLASHOVERRIDE 0x80
+#define IPTOS_PREC_CRITIC_ECP 0xa0
+#define IPTOS_PREC_INTERNETCONTROL 0xc0
+#define IPTOS_PREC_MASK 0xe0
+#define IPTOS_PREC_NETCONTROL 0xe0
+#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
+
+#if !defined (FIONREAD) || !defined (FIONBIO)
+#define IOC_VOID 0x20000000UL /* no parameters */
+#define IOC_OUT 0x40000000UL /* copy out parameters */
+#define IOC_IN 0x80000000UL /* copy in parameters */
+#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */
+#define IOC_INOUT (IOC_IN | IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */
+
+#define _IO(x, y) (((x) << 8) | (y) |IOC_VOID )
+
+#define _IOR(x, y, t) (IOC_OUT | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y))
+
+#define _IOW(x, y, t) (IOC_IN | (((long)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y))
+#endif /* !defined(FIONREAD) || !defined(FIONBIO) */
+
+#ifndef FIONREAD
+#define FIONREAD _IOR('f', 127, unsigned long)
+#endif
+#ifndef FIONBIO
+#define FIONBIO _IOW('f', 126, unsigned long)
+#endif
+
+/*unimplemented */
+#ifndef SIOCSHIWAT
+#define SIOCSHIWAT _IOW('s', 0, unsigned long)
+#define SIOCGHIWAT _IOR('s', 1, unsigned long)
+#define SIOCSLOWAT _IOW('s', 2, unsigned long)
+#define SIOCGLOWAT _IOR('s', 3, unsigned long)
+#ifndef __BITS_SOCKET_H
+#define SIOCATMARK _IOR('s', 7, unsigned long)
+#endif
+#endif
+
+/* commands for fnctl */
+#ifndef F_GETFL
+#define F_GETFL 3
+#endif
+#ifndef F_SETFL
+#define F_SETFL 4
+#endif
+
+/* File status flags and file access modes for fnctl,
+ these are bits in an int. */
+#ifndef O_NONBLOCK
+#define O_NONBLOCK 0X800 /* nonblocking I/O */
+#endif
+#ifndef O_NDELAY
+#define O_NDELAY O_NONBLOCK /* same as O_NONBLOCK, for compatibility */
+#endif
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0x80000 /* set close_on_exec */
+#endif
+#ifndef __BITS_SOCKET_H
+#define SOCK_CLOEXEC O_CLOEXEC
+#endif
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+#ifndef SHUT_RD
+#define SHUT_RD 0
+#define SHUT_WR 1
+#define SHUT_RDWR 2
+#endif
+
+struct pollfd
+{
+
+ int fd; /* file descriptor */
+ short events; /* wait event */
+ short revents; /* actual event happened */
+};
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __STACKX_SOCKETS_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h
new file mode 100644
index 0000000..0f885d6
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_tcpip.h
@@ -0,0 +1,80 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_TCPIP_H__
+#define __STACKX_TCPIP_H__
+
+#include "spl_opt.h"
+#include "stackx/spl_ip_addr.h"
+#include "tcp.h"
+
+#define USEAGE_LOW 60
+#define USEAGE_HIGHT 80
+#define USEAGE_INVALID 0xFF
+
+/*** Put into stackx_instance *********
+
+************************************/
+#include "stackx/spl_api_msg.h"
+#include "netifapi.h"
+#include "stackx/spl_pbuf.h"
+#include "stackx/spl_api.h"
+#include "sys.h"
+#include "netif.h"
+#include "ip_module_api.h"
+#include "internal_msg.h"
+#include "pbuf.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/** Function prototype for send timeout message */
+err_t ltt_apimsg (sys_timeout_handler h, void *arg);
+
+/** Function prototype for the init_done function passed to tcpip_init */
+typedef void (*tcpip_init_done_fn) (void *arg);
+
+/** Function prototype for functions passed to tcpip_callback() */
+typedef void (*tcpip_callback_fn) (void *ctx);
+
+int init_by_main_thread ();
+int init_by_tcpip_thread ();
+err_t spl_tcpip_input (struct pbuf *p, struct netif *inp);
+
+int post_ip_module_msg (void *arg, ip_module_type type,
+ ip_module_operate_type operate_type);
+int process_ip_module_msg (void *arg, ip_module_type type,
+ ip_module_operate_type operate_type);
+int init_new_network_configuration ();
+
+#if STACKX_NETIF_API
+err_t tcpip_netif_add (msg_add_netif * tmp);
+#endif /* STACKX_NETIF_API */
+
+err_t ltt_clearTmrmsg (void *pcb, void *arg);
+
+sys_mbox_t get_primary_box ();
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __STACKX_TCPIP_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h b/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h
new file mode 100644
index 0000000..4809b2b
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/spl_timers.h
@@ -0,0 +1,108 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __SPL_TIMERS_H__
+#define __SPL_TIMERS_H__
+
+#include "opt.h"
+#include "common_mem_base_type.h"
+
+typedef void (*sys_timeout_handler) (void *arg);
+
+#include "rb_tree.h"
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/** Function prototype for a timeout callback function. Register such a function
+ * using sys_timeout().
+ *
+ * @param arg Additional argument to pass to the function - set up by sys_timeout()
+ */
+
+/*
+ * *************************************************************************
+ * PTIMER defined 2013/3/15
+ * *************************************************************************
+ */
+#define PTIMER_DEFAULT 0x00 /* periodic mode */
+#define PTIMER_ONESHOT 0x01
+#define PTIMER_USER_DEF 0x02
+
+enum msg_type
+{
+ SYS_PTIMEROUT_MSG,
+ SYS_UNPTIMEROUT_MSG,
+};
+
+struct msg_context
+{
+ unsigned long msec;
+ union
+ {
+ sys_timeout_handler handle;
+ } action;
+#define _act_category action.act_category
+#define _phandle action.handle
+ u32_t flags; /* oneshot|user_def|... */
+ void *ctx; /* pcb ptr */
+};
+
+struct ptimer_node
+{
+ struct rb_node node;
+ unsigned long abs_nsec;
+ struct msg_context info;
+ unsigned long state;
+ u16_t index; /* store a lwip thread message box id */
+};
+
+struct ptimer_msg
+{
+ enum msg_type msg_type;
+ struct ptimer_node *node;
+ struct ptimer_msg *next, *prev;
+};
+
+struct ptimer_base
+{
+ struct rb_root active;
+ struct rb_node *first; /* point the recently timeout */
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ struct ptimer_msg *head, *tail;
+};
+
+/*
+ * *****************************************************
+ * ptimer E-N-D
+ * *****************************************************
+ */
+void ptimer_thread (void *arg);
+void timeout_phandler (void *act, void *arg);
+void regedit_ptimer (enum msg_type type, sys_timeout_handler handler,
+ struct ptimer_node *node);
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __LWIP_TIMERS_H__ */
diff --git a/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h b/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h
new file mode 100644
index 0000000..679d2ac
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/include/stackx/stackx_instance.h
@@ -0,0 +1,91 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#ifndef __STACKX_INSTANCE_H__
+#define __STACKX_INSTANCE_H__
+
+#include "stackx/spl_tcpip.h"
+#include "netif.h"
+#include "lwip/ip4_frag.h"
+#include "stackx/spl_pbuf.h"
+#include "arch/sys_arch.h"
+#include "arch/queue.h"
+#include "stackx_tx_box.h"
+#include "nsfw_msg.h"
+#include "stackx_app_res.h"
+#include "ip_module_api.h"
+#include "tcp.h"
+#include "udp.h"
+
+#define PKT_BURST 32
+
+#define TASK_BURST 16
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+#define MAX_NETBUFS 1024*2 //define for C10M
+
+#define TOTAL_MSG_QUEUE_NUM (MSG_PRIO_QUEUE_NUM+1) /* three priority queue and one primary queue */
+
+struct stackx_stat
+{
+ struct rti_queue primary_stat; //primary box stat
+ u64_t extend_member_bit;
+};
+
+struct stackx_stack
+{
+ struct queue primary_mbox;
+ struct queue priority_mbox[MSG_PRIO_QUEUE_NUM]; //0-highest; 1-medium; 2-lowest
+ //stackx_apis stackx_api;
+};
+
+struct disp_netif_list
+{
+ struct disp_netif_list *next;
+ struct netif *netif;
+};
+
+typedef struct stackx_instance
+{
+ uint16_t rss_queue_id;
+
+ mpool_handle mp_tx;
+ //mring_handle mp_seg;
+ mring_handle cpcb_seg;
+ mring_handle lmsg_pool;
+
+ struct stackx_stack lstack;
+ struct stackx_stat lstat; //point to p_stackx_table->lstat[i];
+
+ /**
+ * Header of the input packet currently being processed.
+ */
+ /* global variables */
+ struct disp_netif_list *netif_list;
+} stackx_instance;
+
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+
+#endif /* __STACKX_INSTANCE_H__ */