summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/lwip_src/api
diff options
context:
space:
mode:
authorsharath reddy <bs.reddy@huawei.com>2019-06-04 11:53:49 +0530
committersharath reddy <bs.reddy@huawei.com>2019-06-04 20:38:30 +0530
commit2a42ad20b9730706ad371ae3787d4597c4e42276 (patch)
treefa01cd312586ea007468e7233f94c0ce53d75873 /stacks/lwip_stack/lwip_src/api
parenta826fe833d3f2a8fe2673fa05811fe1a22baf045 (diff)
Feature: 19.04 part-2DMM-2
Change-Id: I0b52a6bb67c25c7955d58e29eb81a3cc9efea9e9 Signed-off-by: sharath reddy <bs.reddy@huawei.com>
Diffstat (limited to 'stacks/lwip_stack/lwip_src/api')
-rw-r--r--stacks/lwip_stack/lwip_src/api/nsfw_msg.c23
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_api.c50
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_api_msg.c3320
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_netbuf.c57
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_netifapi.c279
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_sbr.c477
-rw-r--r--stacks/lwip_stack/lwip_src/api/spl_tcpip.c1531
7 files changed, 5737 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/api/nsfw_msg.c b/stacks/lwip_stack/lwip_src/api/nsfw_msg.c
new file mode 100644
index 0000000..338f803
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/nsfw_msg.c
@@ -0,0 +1,23 @@
+/*
+*
+* 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"
+/* *INDENT-OFF* */
+msg_fun g_msg_module_fun_array[MAX_MODULE_TYPE] = {NULL};
+msg_fun g_msg_module_major_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE] = {{NULL}};
+msg_fun g_msg_module_major_minor_fun_array[MAX_MODULE_TYPE][MAX_MAJOR_TYPE][MAX_MINOR_TYPE] = {{{NULL}}};
+msg_fun g_msg_unsupport_fun = NULL;
+/* *INDENT-ON* */
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..5f48d15
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_api.c
@@ -0,0 +1,50 @@
+/*
+*
+* 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_api.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 "nsfw_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 (NSFW_RECYCLE_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..79ea0b6
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_api_msg.c
@@ -0,0 +1,3320 @@
+/*
+*
+* 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 <netinet/tcp.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
+#include "nstack_epoll_api.h"
+
+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_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLIN,
+ postFlag);
+ }
+ break;
+ case SPL_NETCONN_EVT_RCVMINUS: // This will never be reached
+ __sync_fetch_and_sub(&conn->rcvevent, 1);
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLIN,
+ postFlag);
+ }
+ break;
+ case SPL_NETCONN_EVT_SENDPLUS:
+ conn->sendevent = 1;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLOUT,
+ postFlag);
+ }
+ break;
+ case SPL_NETCONN_EVT_SENDMINUS:
+ conn->sendevent = 0;
+
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLOUT,
+ postFlag);
+ }
+ break;
+ case SPL_NETCONN_EVT_ERROR:
+ conn->errevent |= EPOLLERR;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo),
+ conn->errevent, postFlag);
+ conn->errevent = 0;
+ }
+ break;
+#if 1
+ case SPL_NETCONN_EVT_ACCEPT:
+ __sync_fetch_and_add(&conn->rcvevent, 1);
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo), EPOLLIN,
+ postFlag);
+ }
+ break;
+
+ case SPL_NETCONN_EVT_HUP:
+ conn->errevent |= EPOLLHUP;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo),
+ conn->errevent, postFlag);
+ conn->errevent = 0;
+ }
+ break;
+ case SPL_NETCONN_EVT_RDHUP:
+ conn->errevent |= EPOLLRDHUP;
+ if ((conn->epoll_flag) && (postFlag))
+ {
+ NSTACK_EPOLL_EVENT_ADD(ADDR_SHTOL(conn->epInfo),
+ conn->errevent, postFlag);
+ 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 *spl_pb = 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);
+
+ 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;
+ }
+
+ pbuf_to_splpbuf_copy(spl_pb, p);
+ pbuf_free(p);
+
+ buf = (struct spl_netbuf *) ((char *) spl_pb + sizeof(struct spl_pbuf));
+ buf->p = spl_pb;
+ spl_ip_addr_set(&buf->addr, ipaddr);
+ buf->port = port;
+
+ err_t ret = sp_enqueue(cpcb, (void *) spl_pb);
+ 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);
+
+ update_tcp_state(pcb->callback_arg, ESTABLISHED);
+ 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 UDP pcb contained in a netconn
+ * Called from do_send
+ *
+ * @param msg the api_msg_msg pointing to the connection
+ */
+void spl_udp_send(struct common_pcb *cpcb, msg_send_buf * smsg)
+{
+ struct spl_pbuf *p_from = smsg->p;
+ spl_netconn_t *conn = cpcb->conn;
+ struct udp_pcb *upcb = (struct udp_pcb *) (cpcb->conn->private_data);
+ data_com_msg *m = MSG_ENTRY(smsg, data_com_msg, buffer);
+ struct pbuf *p_to = NULL;
+ err_t err = ERR_OK;
+
+ //allocate pbuf and copy spl_pbuf, send , free pbuf and spl_pbuf
+ do
+ {
+ p_to = pbuf_alloc(PBUF_TRANSPORT, p_from->len, PBUF_RAM);
+ if (NULL == p_to)
+ {
+ NSPOL_LOGERR("pbuf is NULL]conn=%p,pcb=%p", conn, upcb);
+ return;
+ }
+
+ err = splpbuf_to_pbuf_transport_copy(p_to, p_from);
+ if (err != ERR_OK)
+ {
+ SET_MSG_ERR(m, conn->last_err);
+ return;
+ }
+
+ if (ip_addr_isany(&smsg->addr))
+ {
+ SET_MSG_ERR(m, udp_send(upcb, p_to));
+ }
+ else
+ {
+ SET_MSG_ERR(m,
+ udp_sendto(upcb, p_to, (ip_addr_t *) & smsg->addr,
+ smsg->port));
+ }
+
+ p_from = (struct spl_pbuf *) ADDR_SHTOL(p_from->next_a);
+ }
+ while (p_from != NULL);
+
+}
+
+/**
+ * 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);
+ NSPOL_LOGERR("Invalid param]msg->conn=%p", conn);
+ goto err_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_udp_send(cpcb, smsg);
+
+ break;
+ }
+
+ default:
+ SET_MSG_ERR(m, ERR_CONN);
+ break;
+ }
+
+ err_return:
+ pbuf_free_safe(smsg->p);
+ ASYNC_MSG_FREE(m);
+
+ 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;
+ case SPL_TCP_INFO:
+ ((struct tcp_info *) optval)->tcpi_total_retrans =
+ (int) tpcb->nrtx;
+ ((struct tcp_info *) optval)->tcpi_snd_mss = (int) tpcb->mss;
+ ((struct tcp_info *) optval)->tcpi_rtt = (int) tpcb->sa;
+ ((struct tcp_info *) optval)->tcpi_snd_cwnd = (int) tpcb->cwnd;
+ 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;
+ }
+ if (conn->tcp_state != spl_state)
+ {
+ 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;
+
+ res_alloc(&cpcb->res_chk);
+ 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..602e48d
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_netbuf.c
@@ -0,0 +1,57 @@
+/*
+*
+* 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..82ac27b
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_netifapi.c
@@ -0,0 +1,279 @@
+/*
+*
+* 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..58c25a1
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_sbr.c
@@ -0,0 +1,477 @@
+/*
+*
+* 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, STACKPOOL, "NSLWIP", 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, STACKPOOL, "NSLWIP", 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, STACKPOOL, "NSLWIP", 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..f3f0e70
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/api/spl_tcpip.c
@@ -0,0 +1,1531 @@
+/*
+*
+* 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 32
+#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);
+extern int nstack_epoll_init(int flag, int ns_sync_mod);
+
+/* 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 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->lenth = 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_ITEM_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 (nstack_epoll_init(0, 0) != 0)
+ {
+ NSPOL_LOGERR("nstack_epoll_init failed");
+ return -1;
+ }
+
+ 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);