summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/lwip_src/core
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/core
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/core')
-rw-r--r--stacks/lwip_stack/lwip_src/core/global_tick.c48
-rw-r--r--stacks/lwip_stack/lwip_src/core/spl_pbuf.c605
-rw-r--r--stacks/lwip_stack/lwip_src/core/spl_timers.c599
-rw-r--r--stacks/lwip_stack/lwip_src/core/unmatch_version.c59
4 files changed, 1311 insertions, 0 deletions
diff --git a/stacks/lwip_stack/lwip_src/core/global_tick.c b/stacks/lwip_stack/lwip_src/core/global_tick.c
new file mode 100644
index 0000000..5e09218
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/global_tick.c
@@ -0,0 +1,48 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "nsfw_mem_api.h"
+#include "nstack_share_res.h"
+#include "nstack_securec.h"
+
+extern nstack_tick_info_t g_nstack_timer_tick;
+
+int init_stackx_global_tick(void)
+{
+ nsfw_mem_zone mzone;
+
+ if (strcpy_s
+ (mzone.stname.aname, NSFW_MEM_NAME_LENGTH,
+ NSTACK_GLOBAL_TICK_SHM) != 0)
+ {
+ NSPOL_LOGERR("STRCPY_S fail");
+ return -1;
+ }
+
+ mzone.stname.entype = NSFW_SHMEM;
+ mzone.isocket_id = -1;
+ mzone.lenth = sizeof(uint64_t);
+ mzone.ireserv = 0;
+
+ g_nstack_timer_tick.tick_ptr = (u64 *) nsfw_mem_zone_create(&mzone);
+ if (NULL == g_nstack_timer_tick.tick_ptr)
+ {
+ NSPOL_LOGERR("Failed to create global timer tick memory");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/stacks/lwip_stack/lwip_src/core/spl_pbuf.c b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c
new file mode 100644
index 0000000..dea577f
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/spl_pbuf.c
@@ -0,0 +1,605 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "spl_opt.h"
+
+#include "spl_def.h"
+#include "spl_pbuf.h"
+#include "stackx_pbuf.h"
+
+#include "stackx_spl_share.h"
+#include "spl_api.h"
+
+#include "nsfw_maintain_api.h"
+#include "netif/sc_dpdk.h"
+#include <common_mem_mbuf.h>
+
+#include <string.h>
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "spl_instance.h"
+
+#include "sys.h"
+#include "mem.h"
+#include "memp.h"
+//#include "sockets.h"
+//#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAL_LIB
+#else
+#include "rte_memcpy.h"
+#endif
+#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct spl_pbuf))
+u16_t g_offSetArry[SPL_PBUF_MAX_LAYER];
+
+u16_t g_offSetArry[SPL_PBUF_MAX_LAYER] =
+ { PBUF_TRANSPORT_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN,
+ SPL_PBUF_UDP_HLEN + PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN,
+ PBUF_IP_HLEN + SPL_PBUF_LINK_HLEN,
+ SPL_PBUF_LINK_HLEN,
+ 0
+};
+
+inline struct spl_pbuf *spl_pbuf_alloc_hugepage(spl_pbuf_layer layer,
+ u16_t length,
+ spl_pbuf_type Type,
+ u16_t proc_id, void *net_conn)
+{
+ struct spl_pbuf *p;
+ u16_t offset;
+ u16_t count = 0;
+ spl_netconn_t *conn = (spl_netconn_t *) net_conn;
+
+ NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE,
+ "spl_pbuf_alloc_hugepage]length=%" U16_F, length);
+
+ /* determine header offset */
+ if (likely(layer < SPL_PBUF_MAX_LAYER))
+ {
+ offset = g_offSetArry[layer];
+ }
+ else
+ {
+ NSPOL_LOGERR("spl_pbuf_alloc_hugepage: bad pbuf layer");
+ return NULL;
+ }
+
+ if (unlikely(length < offset || Type != SPL_PBUF_HUGE))
+ {
+ NSPOL_LOGERR("input is invalid!]length=%u, Type = %d", length, Type);
+ return NULL;
+ }
+
+ p = spl_mbuf_malloc(length, SPL_PBUF_HUGE, &count);
+
+ if (p == NULL)
+ {
+ /* last_log_prt_time and unprint_log_count indeed have multi-thread issue,
+ * but their values don't have precision requirement. No risk. */
+ NS_LOG_CTRL(LOG_CTRL_HUGEPAGE_ALLOC_FAIL, STACKPOOL, "NSLWIP",
+ NSLOG_ERR,
+ "pbuf_alloc_huge: Could not allocate PBUF for SPL_PBUF_HUGE");
+
+ return NULL;
+ }
+
+ if (conn)
+ {
+ p->conn_a = ADDR_LTOSH(conn);
+ }
+ else
+ {
+ p->conn_a = 0;
+ }
+
+ p->tot_len -= offset;
+ p->len -= offset;
+ p->next_a = 0;
+
+ p->payload_a = p->payload_a + offset;
+
+ p->proto_type = SPL_PBUF_PROTO_NONE;
+
+ NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE,
+ "pbuf_alloc]length=%" U16_F ",p=%p", length, (void *) p);
+ return p;
+}
+
+inline int spl_pbuf_internal_copy(struct spl_pbuf *dst, struct spl_pbuf *src)
+{
+ u32_t dst_len = dst->len;
+ u32_t src_len = src->len;
+ u32_t dst_pos = 0;
+ u32_t src_pos = 0;
+ while (dst != NULL && src != NULL)
+ {
+ if (dst_len > src_len)
+ {
+ if (NULL ==
+ common_memcpy(PTR_SHTOL(char *, dst->payload_a) + dst_pos,
+ PTR_SHTOL(char *, src->payload_a) + src_pos,
+ src_len))
+ {
+ NSPOL_LOGERR("rte_memcpy error");
+ return -1;
+ }
+
+ dst_len -= src_len;
+ dst_pos += src_len;
+ src = ADDR_SHTOL(src->next_a);
+ src_len = src != NULL ? src->len : 0;
+ src_pos = 0;
+ }
+ else if (dst_len < src_len)
+ {
+ if (NULL ==
+ common_memcpy(PTR_SHTOL(char *, dst->payload_a) + dst_pos,
+ PTR_SHTOL(char *, src->payload_a) + src_pos,
+ dst_len))
+ {
+ NSPOL_LOGERR("rte_memcpy error");
+ return -1;
+ }
+
+ src_len -= dst_len;
+ src_pos += dst_len;
+ dst = ADDR_SHTOL(dst->next_a);
+ dst_len = dst != NULL ? dst->len : 0;
+ dst_pos = 0;
+ }
+ else
+ {
+ if (NULL ==
+ common_memcpy(PTR_SHTOL(char *, dst->payload_a) + dst_pos,
+ PTR_SHTOL(char *, src->payload_a) + src_pos,
+ dst_len))
+ {
+ NSPOL_LOGERR("rte_memcpy error");
+ return -1;
+ }
+
+ src = ADDR_SHTOL(src->next_a);
+ src_len = src != NULL ? src->len : 0;
+ src_pos = 0;
+ dst = ADDR_SHTOL(dst->next_a);
+ dst_len = dst != NULL ? dst->len : 0;
+ dst_pos = 0;
+ }
+ }
+ return 0;
+}
+
+void spl_pbuf_realloc(struct spl_pbuf *p, u32_t new_len)
+{
+ if (NULL != p && p->type == SPL_PBUF_HUGE)
+ {
+ p->tot_len = new_len;
+ p->len = new_len;
+ return;
+ }
+}
+
+void spl_pbuf_free(struct spl_pbuf *p)
+{
+ struct spl_pbuf *q;
+ u8_t count = 0;
+
+ NSPOL_LOGINF(PBUF_DEBUG, "Freeing PBF %p", p);
+
+ if (unlikely(p == NULL || p->type != SPL_PBUF_HUGE))
+ {
+ NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_LEVEL_SERIOUS,
+ "input param illegal]p=%p, type=%d", p,
+ p ? p->type : -1);
+ return;
+ }
+
+ (void) count;
+
+ /* de-allocate all consecutive pbufs from the head of the chain that
+ * obtain a zero reference count after decrementing*/
+ do
+ {
+ /* remember next pbuf in chain for next iteration */
+ NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE,
+ "spl_pbuf_free: deallocating]buf=%p", (void *) p);
+ q = (struct spl_pbuf *) ADDR_SHTOL(p->next_a);
+ if (res_free(&p->res_chk))
+ {
+ //NSPOL_LOGERR("res_free failed]p=%p", p);
+ }
+
+ count++;
+ {
+ pbuf_set_recycle_flg(p, MBUF_UNUSED); /* release buf hold by app on abnormal exit */
+ spl_mbuf_free((char *) p - sizeof(struct common_mem_mbuf));
+ p->res_chk.u8Reserve |= PBUF_FREE_FLAG;
+ }
+
+ /* proceed to next pbuf */
+ p = q;
+ }
+ while (p != NULL);
+
+ /* return number of de-allocated pbufs */
+ return;
+}
+
+void spl_pbuf_cat(struct spl_pbuf *h, struct spl_pbuf *t)
+{
+ struct spl_pbuf *p;
+
+ if (h == NULL || t == NULL)
+ {
+ NSPOL_LOGERR("pbuf_cat: h=NULL||t=NULL!!");
+ return;
+ }
+
+ for (p = h; p->next_a != 0; p = PTR_SHTOL(struct spl_pbuf *, p->next_a))
+ {
+ /* add total length of second chain to all totals of first chain */
+ p->tot_len += t->tot_len;
+ }
+
+ if (0 != p->next_a)
+ {
+ NSPOL_LOGERR
+ ("pbuf_cat: p is not the last pbuf of the first chain, p->next_a != 0");
+ return;
+ }
+
+ /* add total length of second chain to last pbuf total of first chain */
+ p->tot_len += t->tot_len;
+
+ /* chain last pbuf of head (p) with first of tail (t) */
+ p->next_a = (uint64_t) ADDR_LTOSH_EXT(t);
+
+ /* p->next now references t, but the caller will drop its reference to t,
+ * so netto there is no change to the reference count of t.
+ */
+}
+
+err_t spl_pbuf_copy(struct spl_pbuf * p_to, struct spl_pbuf * p_from)
+{
+ u32_t offset_to = 0;
+ u32_t offset_from = 0;
+ u32_t len = 0;
+ NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE, "pbuf_copy]p_to=%p,p_from=%p",
+ (void *) p_to, (void *) p_from);
+
+ if (!
+ ((p_to != NULL) && (p_from != NULL)
+ && (p_to->tot_len >= p_from->tot_len)))
+ {
+ NSPOL_LOGERR("pbuf_copy: target not big enough to hold source");
+ return ERR_ARG;
+ }
+
+ do
+ {
+ if (p_to == NULL)
+ {
+ NSPOL_LOGERR("pbuf_copy: target pbuf not exist: p_to == NULL!!");
+ return ERR_ARG;
+ }
+
+ if ((p_to->len - offset_to) >= (p_from->len - offset_from))
+ {
+
+ len = p_from->len - offset_from;
+ }
+ else
+ {
+
+ len = p_to->len - offset_to;
+ }
+
+ if (EOK !=
+ memmove_s((u8_t *) ADDR_SHTOL(p_to->payload_a) + offset_to, len,
+ (u8_t *) ADDR_SHTOL(p_from->payload_a) + offset_from,
+ len))
+ {
+ NSPOL_LOGERR("MEMMOVE_S failed");
+ return ERR_MEM;
+ }
+
+ offset_to += len;
+ offset_from += len;
+ if (offset_to > p_to->len)
+ {
+ NSPOL_LOGERR
+ ("pbuf_copy: target offset not match: offset_to > p_to->len.");
+ return ERR_VAL;
+ }
+ if (offset_to == p_to->len)
+ {
+ offset_to = 0;
+ p_to = (struct spl_pbuf *) ADDR_SHTOL(p_to->next_a);
+ }
+
+ if (offset_from >= p_from->len)
+ {
+ /* on to next p_from (if any) */
+ NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE,
+ "pbuf_copy: source offset not match: offset_from >= p_from->len");
+ offset_from = 0;
+ p_from = (struct spl_pbuf *) ADDR_SHTOL(p_from->next_a);
+ }
+
+ if ((p_from != NULL) && (p_from->len == p_from->tot_len))
+ {
+ if ((p_from->next_a != 0))
+ {
+ NSPOL_LOGERR("pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+
+ if ((p_to != NULL) && (p_to->len == p_to->tot_len))
+ {
+ /* don't copy more than one packet! */
+ if ((p_to->next_a != 0))
+ {
+ NSPOL_LOGERR("pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+ }
+ while (p_from);
+
+ NSPOL_LOGDBG(PBUF_DEBUG | STACKX_DBG_TRACE,
+ "pbuf_copy: end of chain reached.");
+ return ERR_OK;
+}
+
+err_t
+splpbuf_to_pbuf_transport_copy(struct pbuf * p_to, struct spl_pbuf * p_from)
+{
+ if (EOK != memmove_s((u8_t *) p_to->payload,
+ p_to->len, (u8_t *) ADDR_SHTOL(p_from->payload_a),
+ p_from->len))
+ {
+ NSPOL_LOGERR("MEMMOVE_S failed");
+ return ERR_MEM;
+ }
+
+ return ERR_OK;
+}
+
+err_t splpbuf_to_pbuf_copy(struct pbuf * p_to, struct spl_pbuf * p_from)
+{
+ u32_t offset_to = 0;
+ u32_t offset_from = 0;
+ u32_t len = 0;
+
+ NSPOL_LOGINF(NETIF_DEBUG, "splpbuf_to_pbuf_copy");
+
+ if (!
+ ((p_to != NULL) && (p_from != NULL)
+ && (p_to->tot_len >= p_from->tot_len)))
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy: target not big enough to hold source");
+ return ERR_ARG;
+ }
+ NSPOL_LOGINF(PBUF_DEBUG,
+ "splpbuf_to_pbuf_copy]p_to=%p [type %d tot_len %d], p_from=%p [type %d tot_len %d]",
+ (void *) p_to, p_to->type, p_to->tot_len, (void *) p_from,
+ p_from->type, p_from->tot_len);
+ do
+ {
+ NSPOL_LOGINF(NETIF_DEBUG, "copying....");
+ if (p_to == NULL)
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy: target not big enough to hold source p_to len [%d] p_from len [%d]",
+ p_to->tot_len, p_from->tot_len);
+ return ERR_ARG;
+ }
+
+ if ((p_to->len - offset_to) >= (p_from->len - offset_from))
+ {
+
+ len = p_from->len - offset_from;
+ }
+ else
+ {
+
+ len = p_to->len - offset_to;
+ }
+
+ if (EOK != memmove_s((u8_t *) p_to->payload + offset_to,
+ len,
+ (u8_t *) ADDR_SHTOL(p_from->payload_a) +
+ offset_from, len))
+ {
+ NSPOL_LOGERR("MEMMOVE_S failed");
+ return ERR_MEM;
+ }
+
+ offset_to += len;
+ offset_from += len;
+ if (offset_to > p_to->len)
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy: target offset not match: offset_to > p_to->len.");
+ return ERR_VAL;
+ }
+ if (offset_to == p_to->len)
+ {
+ offset_to = 0;
+ p_to = p_to->next;
+
+ NSPOL_LOGINF(NETIF_DEBUG,
+ "splpbuf_to_pbuf_copy: p_to next %p", p_to);
+ }
+
+ if (offset_from >= p_from->len)
+ {
+ /* on to next p_from (if any) */
+ NSPOL_LOGINF(NETIF_DEBUG,
+ "splpbuf_to_pbuf_copy: source offset not match: offset_from >= p_from->len");
+ offset_from = 0;
+ p_from = (struct spl_pbuf *) ADDR_SHTOL(p_from->next_a);
+ NSPOL_LOGINF(NETIF_DEBUG,
+ "splpbuf_to_pbuf_copy: pfrom next %p", p_from);
+ }
+
+ if ((p_from != NULL) && (p_from->len == p_from->tot_len))
+ {
+ if ((p_from->next_a != 0))
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+
+ if ((p_to != NULL) && (p_to->len == p_to->tot_len))
+ {
+ /* don't copy more than one packet! */
+ if ((p_to->next != NULL))
+ {
+ NSPOL_LOGERR
+ ("splpbuf_to_pbuf_copy() does not allow packet queues!");
+ return ERR_VAL;
+ }
+ }
+ }
+ while (p_from);
+
+ NSPOL_LOGDBG(NETIF_DEBUG, "splpbuf_to_pbuf_copy: end of chain reached.");
+ return ERR_OK;
+}
+
+err_t pbuf_to_splpbuf_copy(struct spl_pbuf * p_to, struct pbuf * p_from)
+{
+ int offset = 0;
+ void *data = NULL;
+
+ do
+ {
+ data = (u8_t *) (p_to->payload_a) + offset;
+ memcpy(data, (u8_t *) p_from->payload, p_from->len);
+ offset = offset + p_from->len;
+ if (offset >= 2048)
+ {
+ NSPOL_LOGERR("More thank 2K size");
+ return ERR_MEM;
+ }
+ p_from = p_from->next;
+ }
+ while (p_from != NULL);
+
+ return ERR_OK;
+}
+
+struct pbuf *spl_convert_spl_pbuf_to_pbuf(struct spl_pbuf *p_from)
+{
+ struct pbuf *p_to = NULL;
+
+ p_to = pbuf_alloc(PBUF_RAW, p_from->tot_len, PBUF_POOL);
+ if (p_to)
+ {
+ splpbuf_to_pbuf_copy(p_to, p_from);
+ }
+ return p_to;
+}
+
+spl_pbuf_layer get_pbuf_layer_from_pbuf_payload(struct pbuf * buf)
+{
+
+ struct eth_hdr *ethhdr;
+ spl_pbuf_layer layer = SPL_PBUF_TRANSPORT;
+ u16_t type;
+
+ if (buf->len <= SIZEOF_ETH_HDR)
+ {
+ NSPOL_LOGINF(PBUF_DEBUG,
+ "get_pbuf_layer_from_payload failed. length is wrong");
+ return layer;
+ }
+ ethhdr = (struct eth_hdr *) buf->payload;
+ type = spl_htons(ethhdr->type);
+
+ NSPOL_LOGINF(PBUF_DEBUG, "packet type %x", type);
+
+ switch (type)
+ {
+ case ETHTYPE_IP:
+ layer = SPL_PBUF_IP;
+ break;
+ case ETHTYPE_ARP:
+ layer = SPL_PBUF_LINK;
+ break;
+ default:
+ layer = SPL_PBUF_TRANSPORT;
+ break;
+ }
+
+ return layer;
+}
+
+void print_pbuf_payload_info(struct pbuf *buf, bool send)
+{
+
+ struct eth_hdr *ethhdr;
+ u16_t type;
+
+ if (buf->len <= SIZEOF_ETH_HDR)
+ {
+ NSPOL_LOGINF(PBUF_DEBUG,
+ "get_pbuf_layer_from_payload failed. length is wrong");
+ return;
+ }
+ ethhdr = (struct eth_hdr *) buf->payload;
+ type = spl_htons(ethhdr->type);
+
+ if (send)
+ {
+ NSPOL_LOGINF(PBUF_DEBUG, "send packet start type %x len %d *****",
+ type, buf->len);
+ }
+ else
+ {
+ NSPOL_LOGINF(PBUF_DEBUG,
+ "receive packet start type %x len %d ########", type,
+ buf->len);
+ }
+
+ switch (type)
+ {
+ case ETHTYPE_IP:
+ NSPOL_LOGINF(TCPIP_DEBUG, "ip packet len %d tot len %d type %x",
+ buf->len, buf->tot_len, type);
+ struct ip_hdr *ip =
+ (struct ip_hdr *) ((char *) buf->payload + SIZEOF_ETH_HDR);
+ NSPOL_LOGINF(PBUF_DEBUG, "ip packet src %x dest %x proto %d",
+ ip->src, ip->dest, ip->_proto);
+ break;
+ case ETHTYPE_ARP:
+ NSPOL_LOGINF(TCPIP_DEBUG, "arp packet len %d tot len %d type %x",
+ buf->len, buf->tot_len, type);
+ break;
+ default:
+ NSPOL_LOGINF(TCPIP_DEBUG,
+ "other packet len %d tot len %d type %x", buf->len,
+ buf->tot_len, type);
+ break;
+ }
+ return;
+}
diff --git a/stacks/lwip_stack/lwip_src/core/spl_timers.c b/stacks/lwip_stack/lwip_src/core/spl_timers.c
new file mode 100644
index 0000000..5e8e5d9
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/spl_timers.c
@@ -0,0 +1,599 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "opt.h"
+#include "nsfw_mem_api.h"
+#include "def.h"
+#include "sc_dpdk.h"
+#include "nstack_log.h"
+#include "nstack_securec.h"
+#include "nstack_share_res.h"
+
+#include <time.h>
+#include <signal.h>
+#include <pthread.h>
+#include <syscall.h>
+#include "nsfw_ps_api.h"
+#include "spl_timers.h"
+#include "common_mem_api.h"
+
+extern sys_thread_t g_timerThread_id;
+
+/*Since the range of the dpdk read TSC value is u64_t, it changes*/
+
+#ifndef typecheck
+#define typecheck(type, x) \
+({ type __dummy; \
+ typeof(x)__dummy2; \
+ (void)(&__dummy == &__dummy2); \
+ 1; \
+ })
+#endif
+
+#ifndef time_after_eq
+#define time_after_eq(a, b) \
+(typecheck(unsigned long, a) \
+ && typecheck(unsigned long, b) \
+ && ((long)(a) - (long)(b) >= 0))
+#endif
+
+#define MIN_TIME_PICE 50
+#define MICRO_PER_SECOND 1000
+#define NANO_PER_MICROSECOND 1000000
+#define NANO_PER_SECOND 1000000000
+
+#define PTIMER_MSG_BUFFER_SIZE 4096
+
+#define PTIMER_STATE_INACTIVE 0x00
+#define PTIMER_STATE_ENQUEUED 0x01
+#define gettid() syscall(__NR_gettid)
+
+#define TIMER_CONTEXT_NAME "TIMER_CONTEXT_NAME"
+
+static timer_t lazy_tim;
+static timer_t lazy_tim_retry;
+static struct ptimer_base ptimer;
+static sys_sem_t ptimer_lock;
+
+extern void recycle_tmr(struct ptimer_node *tmo);
+
+extern nstack_tick_info_t g_nstack_timer_tick;
+
+/*
+ ***************************
+ * rb_tree wrapper function*
+ ***************************
+ */
+NSTACK_STATIC void
+remove_ptimer(struct ptimer_node *tmo, struct ptimer_base *base)
+{
+ if (tmo == NULL)
+ {
+ NSPOL_LOGERR("input parameter tmo is null");
+ return;
+ }
+ if (!(tmo->state & PTIMER_STATE_ENQUEUED))
+ {
+ NSPOL_LOGWAR(TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ "the timer state is: PTIMER_STATE_INACTIVE, no need to remove!");
+ return;
+ }
+
+ if (base->first == &tmo->node)
+ {
+ base->first = rb_next(&tmo->node);
+ }
+
+ rb_erase(&tmo->node, &base->active);
+
+ tmo->state = PTIMER_STATE_INACTIVE;
+}
+
+NSTACK_STATIC struct ptimer_node *search_ptimer(struct ptimer_msg *msg)
+{
+ if (msg == NULL)
+ {
+ NSPOL_LOGERR("input parameter msg is null");
+ return NULL;
+ }
+ if (msg->node)
+ {
+ return msg->node;
+ }
+
+ return NULL;
+
+}
+
+err_t del_ptimer(struct ptimer_msg * msg)
+{
+ struct ptimer_node *tmo;
+
+ tmo = search_ptimer(msg);
+ if (tmo)
+ {
+ remove_ptimer(tmo, &ptimer);
+ NSPOL_LOGDBG(TIMERS_DEBUG, "del]thread=%u,ptimer_node=%p", tmo->index,
+ tmo);
+ return ERR_OK;
+ }
+
+ NSPOL_LOGERR("ptime_node not found!!");
+ return ERR_VAL;
+}
+
+/*
+ * Ptimer inserted into rb_tree
+ * @param node: the ptimer node pointer
+ * @param base: the ptimer root_base pointer
+ */
+NSTACK_STATIC void
+enqueue_ptimer(struct ptimer_node *tmo, struct ptimer_base *base)
+{
+ struct rb_node **linknode;
+ struct rb_node *parent = NULL;
+ struct ptimer_node *entry;
+ int leftmost = 1;
+ if (tmo == NULL || base == NULL)
+ {
+ NSPOL_LOGERR("input parameter is null");
+ return;
+ }
+
+ if ((tmo->state & PTIMER_STATE_ENQUEUED))
+ {
+ NSPOL_LOGWAR(TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ "the timer state is: PTIMER_STATE_ENQUEUED");
+ return;
+ }
+
+ linknode = &base->active.rb_node;
+ while (*linknode)
+ {
+ parent = *linknode;
+ entry = rb_entry(parent, struct ptimer_node, node);
+ //XXX: do by the equal case is all of price of the large case
+ if (time_after_eq(entry->abs_nsec, tmo->abs_nsec))
+ {
+ linknode = &(*linknode)->rb_left;
+ }
+ else
+ {
+ linknode = &(*linknode)->rb_right;
+ leftmost = 0;
+ }
+ }
+
+ /*
+ * Insert the timer to the rb_tree and check whether it
+ * replaces the first pending timer
+ */
+ if (leftmost)
+ {
+ base->first = &tmo->node;
+ }
+
+ rb_link_node(&tmo->node, parent, linknode);
+ rb_insert_color(&tmo->node, &base->active);
+ NSPOL_LOGDBG(TIMERS_DEBUG, "enqueue]thread=%u,ptimer_node=%p", tmo->index,
+ tmo);
+ tmo->state |= PTIMER_STATE_ENQUEUED;
+}
+
+void launch_tmr(timer_t * tim, u64_t nsec)
+{
+ struct itimerspec vtim;
+
+ vtim.it_value.tv_sec = (nsec) / NANO_PER_SECOND;
+ vtim.it_value.tv_nsec = (nsec) % NANO_PER_SECOND;
+ vtim.it_interval.tv_sec = 0;
+ vtim.it_interval.tv_nsec = 0;
+
+ if (timer_settime(*tim, 0, &vtim, NULL) < 0)
+ {
+ NSPOL_LOGERR("add_ptimer:timer_settime failed");
+ }
+
+}
+
+/*
+ * add ptimer to rb_tree
+ * @param tmo: the ptimer node pointer
+ */
+void add_ptimer(struct ptimer_node *tmo)
+{
+ if (tmo == NULL)
+ {
+ NSPOL_LOGERR("input parameter is null");
+ return;
+ }
+ enqueue_ptimer(tmo, &ptimer);
+
+ if (ptimer.first == &tmo->node)
+ {
+ launch_tmr(&lazy_tim, tmo->info.msec * NANO_PER_MICROSECOND);
+ }
+}
+
+#if 1
+/*
+ * cond signal ,send a ptimer message
+ * @param type: the message type
+ * @param handler: timeout handler
+ * @param node: the ptimer node pointer
+ */
+void
+regedit_ptimer(enum msg_type Type, sys_timeout_handler handler,
+ struct ptimer_node *node)
+{
+ (void) handler;
+ (void) pthread_mutex_lock(&ptimer.lock);
+ if (ptimer.tail == NULL)
+ {
+ (void) pthread_mutex_unlock(&ptimer.lock);
+ NSPOL_LOGERR("ptimer.tail is null");
+ free(node);
+ node = NULL;
+ return;
+ }
+ ptimer.tail->msg_type = Type;
+ ptimer.tail->node = node;
+ ptimer.tail = ptimer.tail->next;
+ if (ptimer.head == ptimer.tail)
+ {
+ (void) pthread_mutex_unlock(&ptimer.lock);
+ NSPOL_LOGERR("ptimer.head equal to ptimer.tail");
+ return;
+ }
+
+ (void) pthread_kill(g_timerThread_id, SIGRTMIN + 2);
+
+ (void) pthread_mutex_unlock(&ptimer.lock);
+ return;
+}
+#endif
+/*
+ * deal with the timeout signal
+ *
+ */
+void deal_timeout_sig(void)
+{
+ struct ptimer_node *tmo;
+ struct timespec now;
+ unsigned long abs_nsec;
+ err_t err;
+ int retval;
+ if (ptimer.first == NULL)
+ {
+ return;
+ }
+ tmo = rb_entry(ptimer.first, struct ptimer_node, node);
+ retval = clock_gettime(CLOCK_MONOTONIC, &now);
+ if (0 != retval)
+ {
+ NSPOL_LOGERR("clock_gettime failed]retval=%d,errno=%d", retval,
+ errno);
+ }
+ abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec;
+
+ // deal with all timeout point
+ while (time_after_eq(abs_nsec, tmo->abs_nsec))
+ {
+ remove_ptimer(tmo, &ptimer);
+
+ if (tmo->info.flags & PTIMER_ONESHOT)
+ {
+ }
+ else
+ {
+ //re-entry periodic ptimer
+ tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec
+ + tmo->info.msec * NANO_PER_MICROSECOND;
+ add_ptimer(tmo);
+ }
+
+ //send timeout message
+ NSPOL_LOGDBG(INTERRUPT_DEBUG,
+ "ptimer happened to thread_index]index=%u", tmo->index);
+ if ((err = ltt_apimsg(tmo->info._phandle, (void *) tmo)))
+ {
+ NSPOL_LOGWAR(TIMERS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ "send timeout message failed!]errno=%d", err);
+ }
+
+ if (ptimer.first == NULL)
+ {
+ NSPOL_LOGERR("deal_timeout_sig: ptimer.first == NULL!!");
+ return;
+ }
+ tmo = rb_entry(ptimer.first, struct ptimer_node, node);
+ }
+
+ if (tmo->abs_nsec <= abs_nsec)
+ {
+ NSPOL_LOGERR("tmo->abs_nsec is smaller than abs_nsec");
+ return;
+ }
+
+ NSPOL_LOGDBG(TIMERS_DEBUG, "TIMERSIGNAL : Launch timer for]time=%ul",
+ tmo->abs_nsec - abs_nsec);
+ launch_tmr(&lazy_tim, tmo->abs_nsec - abs_nsec); //timer interupted eveny 50ms instand by tmo->abs_nsec
+}
+
+/*
+ * timeout signal handle function
+ * @param v: unused argument
+ */
+/*ptimer is already protected and used*/
+
+NSTACK_STATIC void timeout_sigaction(int sig)
+{
+ (void) sig;
+ if (!sys_arch_sem_trywait(&ptimer_lock))
+ {
+ launch_tmr(&lazy_tim_retry,
+ (MIN_TIME_PICE / 5) * NANO_PER_MICROSECOND);
+ return;
+ }
+
+ deal_timeout_sig();
+
+ sys_sem_signal(&ptimer_lock);
+
+ return;
+}
+
+/*
+ * initialize the ptimer buffer and timing mechanism
+ */
+err_t init_ptimer(void)
+{
+ int i, retval;
+ struct sigevent timer_event;
+ struct sigevent timer_event1;
+ struct ptimer_msg *ptr;
+
+ if (pthread_mutex_init(&ptimer.lock, NULL))
+ {
+ NSPOL_LOGERR("pthread_mutex_init failed");
+ return ERR_MEM;
+ }
+ /*codex fix */
+ if (ERR_MEM == sys_sem_new(&ptimer_lock, 1))
+ {
+ NSPOL_LOGERR("init_ptimer: sys_sem_new failure");
+ return ERR_MEM;
+ }
+
+ ptimer.active.rb_node = NULL;
+ ptimer.first = NULL;
+
+ ptr =
+ (struct ptimer_msg *) malloc(PTIMER_MSG_BUFFER_SIZE *
+ sizeof(struct ptimer_msg));
+ if (!ptr)
+ {
+ NSPOL_LOGERR("init_ptimer: malloc ptimer buffer failed!");
+ return ERR_MEM;
+ }
+
+ int ret =
+ memset_s(ptr, (PTIMER_MSG_BUFFER_SIZE * sizeof(struct ptimer_msg)),
+ 0, (PTIMER_MSG_BUFFER_SIZE * sizeof(struct ptimer_msg)));
+ if (EOK != ret)
+ {
+ free(ptr);
+ NSPOL_LOGERR("init_ptimer: MEMSET_S ptimer buffer failed]ret=%d",
+ ret);
+ return ERR_MEM;
+ }
+
+ for (i = 0; i < PTIMER_MSG_BUFFER_SIZE - 1; i++)
+ {
+ ptr[i].next = &ptr[(i + 1)];
+ ptr[(i + 1)].prev = &ptr[i];
+ }
+
+ ptr[i].next = &ptr[0];
+ ptr[0].prev = &ptr[i];
+ ptimer.head = ptimer.tail = &ptr[0];
+ retval =
+ memset_s(&timer_event, sizeof(struct sigevent), 0,
+ sizeof(struct sigevent));
+ if (EOK != retval)
+ {
+ free(ptr);
+ ptr = NULL;
+ NSPOL_LOGERR("MEMSET_S failed]ret=%d", retval);
+ return ERR_VAL;
+ }
+ timer_event.sigev_notify = SIGEV_SIGNAL;
+ timer_event.sigev_signo = SIGRTMIN;
+ timer_event.sigev_value.sival_ptr = (void *) &lazy_tim;
+ timer_event1 = timer_event;
+ timer_event1.sigev_value.sival_ptr = (void *) &lazy_tim_retry;
+
+ if (timer_create(CLOCK_MONOTONIC, &timer_event, &lazy_tim) < 0)
+ {
+ free(ptr);
+ ptr = NULL;
+ NSPOL_LOGERR("ptimer_init: timer_create failed!");
+ return ERR_VAL;
+ }
+
+ if (timer_create(CLOCK_MONOTONIC, &timer_event1, &lazy_tim_retry) < 0)
+ {
+ free(ptr);
+ ptr = NULL;
+ NSPOL_LOGERR("ptimer_init: timer_create failed!");
+ return ERR_VAL;
+ }
+
+ return ERR_OK;
+}
+
+NSTACK_STATIC err_t process_timeout_msg(struct ptimer_msg * msg)
+{
+ struct ptimer_node *tmo = msg->node;
+ struct timespec now;
+
+ switch (msg->msg_type)
+ {
+ case SYS_PTIMEROUT_MSG:
+ if (tmo)
+ {
+ int retval = clock_gettime(CLOCK_MONOTONIC, &now);
+ if (0 != retval)
+ {
+ NSPOL_LOGERR("clock_gettime failed]retval=%d,errno=%d",
+ retval, errno);
+ }
+ tmo->abs_nsec = now.tv_sec * NANO_PER_SECOND + now.tv_nsec
+ + tmo->info.msec * NANO_PER_MICROSECOND;
+ add_ptimer(tmo);
+ }
+ else
+ {
+ NSPOL_LOGERR("process_timeout_msg: rb_node is NULL!");
+ return ERR_MEM;
+ }
+
+ break;
+ case SYS_UNPTIMEROUT_MSG:
+ if (del_ptimer(msg) != ERR_OK)
+ {
+ NSPOL_LOGERR
+ ("process_timeout_msg: can not find the timeout event(oops)!");
+ }
+
+ break;
+ default:
+ NSPOL_LOGERR
+ ("process_timeout_msg: oops! lwip timeout_thread receive unacquainted message!");
+ break;
+ }
+
+ return ERR_OK;
+}
+
+void ptimer_thread(void *arg)
+{
+ LWIP_UNUSED_ARG(arg);
+ int sig, ret = -1;
+ sigset_t waitset;
+ sigset_t oset;
+ struct ptimer_msg *msg;
+
+ if (0 != sigemptyset(&waitset))
+ {
+ NSTCP_LOGERR("sigemptyset function call error");
+ return;
+ }
+
+ if (0 != sigaddset(&waitset, SIGRTMIN))
+ {
+ NSTCP_LOGERR("sigaddset function call error");
+ return;
+ }
+
+ if (0 != sigaddset(&waitset, SIGRTMIN + 2))
+ {
+ NSTCP_LOGERR("sigaddset function call error");
+ return;
+ }
+
+ (void) pthread_sigmask(SIG_BLOCK, &waitset, &oset);
+
+ (void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ (void) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+ NSPOL_LOGDBG(TIMERS_DEBUG, "ptimer: init done !");
+
+ if (!g_nstack_timer_tick.tick_ptr)
+ {
+ NSTCP_LOGERR("g_nstack_timer_tick not inited");
+ return;
+ }
+ (void) gettimeofday(&g_nstack_timer_tick.ref_time, NULL);
+ g_nstack_timer_tick.interval = 100;
+ *g_nstack_timer_tick.tick_ptr = 0;
+ g_nstack_timer_tick.ref_tick = 0;
+ while (1)
+ {
+ ret = sigwait(&waitset, &sig);
+ (void) nsfw_thread_chk(); // will only return TRUE, no need to check return value
+ if (ret != -1)
+ {
+ /* for timer expirt handle */
+ if (SIGRTMIN == sig)
+ {
+ timeout_sigaction(sig);
+ continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+
+ while (1)
+ {
+ (void) pthread_mutex_lock(&ptimer.lock);
+ if (ptimer.head == ptimer.tail)
+ {
+ (void) pthread_mutex_unlock(&ptimer.lock);
+ break;
+ }
+
+ msg = ptimer.head;
+ ptimer.head = ptimer.head->next;
+ (void) pthread_mutex_unlock(&ptimer.lock);
+
+ sys_arch_sem_wait(&ptimer_lock, 0);
+
+ if (process_timeout_msg(msg) != ERR_OK)
+ {
+ NSPOL_LOGERR("oops: ptimer_thread panic!");
+ }
+
+ sys_sem_signal(&ptimer_lock);
+ }
+ }
+}
+
+void timeout_phandler(void *act, void *arg)
+{
+ struct ptimer_node *tmo = arg;
+ if (act == NULL)
+ {
+ NSPOL_LOGERR("input parameter arg is null");
+ return;
+ }
+
+ NSPOL_LOGINF(TIMERS_DEBUG, "Timer expire @timeout_phandler Handle %p",
+ tmo->info._phandle);
+ if (tmo->info.flags & PTIMER_ONESHOT)
+ {
+ sys_timeout_handler handle = act;
+ handle(tmo->info.ctx);
+ return;
+ }
+ else
+ {
+ NSPOL_LOGINF(TIMERS_DEBUG,
+ "Timer expire error @timeout_phandler Handle %p",
+ tmo->info._phandle);
+ }
+}
diff --git a/stacks/lwip_stack/lwip_src/core/unmatch_version.c b/stacks/lwip_stack/lwip_src/core/unmatch_version.c
new file mode 100644
index 0000000..e215a85
--- /dev/null
+++ b/stacks/lwip_stack/lwip_src/core/unmatch_version.c
@@ -0,0 +1,59 @@
+/*
+*
+* Copyright (c) 2018 Huawei Technologies Co.,Ltd.
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+#include "nsfw_mem_api.h"
+#include "nstack_share_res.h"
+#include "nstack_securec.h"
+
+char *g_nstack_ver_info = NULL;
+
+int init_unmatch_version(void)
+{
+ int ret;
+ nsfw_mem_zone mzone;
+
+ ret =
+ strcpy_s(mzone.stname.aname, NSFW_MEM_NAME_LENGTH,
+ NSTACK_VERSION_SHM);
+ if (EOK != ret)
+ {
+ NSPOL_LOGERR("STRCPY_S fail]ret=%d", ret);
+ return -1;
+ }
+ mzone.stname.entype = NSFW_SHMEM;
+ mzone.isocket_id = -1;
+ mzone.lenth =
+ NSTACK_VERSION_LEN + MAX_UNMATCH_VER_CNT * sizeof(unmatch_ver_info_t);
+ mzone.ireserv = 0;
+
+ char *version = (char *) nsfw_mem_zone_create(&mzone);
+ if (NULL == version)
+ {
+ NSPOL_LOGERR("Failed to create unmatch_version memory");
+ return -1;
+ }
+
+ ret = strcpy_s(version, NSTACK_VERSION_LEN, NSTACK_VERSION);
+ if (EOK != ret)
+ {
+ NSPOL_LOGERR("STRCPY_S NSTACK_VERSION fail]ret=%d", ret);
+ return -1;
+ }
+
+ g_nstack_ver_info = version;
+
+ return 0;
+}