From 388525230f809bfa61fe31921b54ebfb6aae57ec Mon Sep 17 00:00:00 2001
From: jiangheng <jiangheng12@huawei.com>
Date: Fri, 31 Dec 2021 17:32:49 +0800
Subject: [PATCH] adapt lstack

---
 src/Makefile                         |   5 +-
 src/api/api_lib.c                    |   2 +
 src/api/api_msg.c                    |  46 +++
 src/api/dir.mk                       |   2 +-
 src/api/perf.c                       | 182 ++++++++++++
 src/api/posix_api.c                  | 156 ++++++++++
 src/api/sockets.c                    | 558 ++++++++++++++++++++++++++++++++++-
 src/api/sys_arch.c                   | 379 ++++++++++++++++++++++++
 src/api/tcpip.c                      |  34 ++-
 src/core/dir.mk                      |   8 +-
 src/core/init.c                      |   4 +-
 src/core/ip.c                        |   2 +-
 src/core/ipv4/ip4.c                  |  14 +
 src/core/ipv6/ip6.c                  |  10 +
 src/core/mem.c                       |   6 +-
 src/core/memp.c                      |   4 +
 src/core/netif.c                     |   8 +-
 src/core/pbuf.c                      |   4 +
 src/core/stats.c                     |  13 +-
 src/core/tcp.c                       | 196 +++++++++++-
 src/core/tcp_in.c                    | 101 ++++++-
 src/core/tcp_out.c                   |  25 +-
 src/core/timeouts.c                  |  18 +-
 src/core/udp.c                       |  15 +
 src/include/arch/cc.h                |  80 ++++-
 src/include/arch/perf.h              | 155 ++++++++++
 src/include/arch/sys_arch.h          |  92 +++++-
 src/include/eventpoll.h              |  72 +++++
 src/include/hlist.h                  | 233 +++++++++++++++
 src/include/list.h                   | 110 +++++++
 src/include/lwip/api.h               |  35 +++
 src/include/lwip/debug.h             |   1 +
 src/include/lwip/def.h               |  15 +
 src/include/lwip/ip.h                |   8 +-
 src/include/lwip/memp.h              |  17 ++
 src/include/lwip/netif.h             |   4 +-
 src/include/lwip/opt.h               |  62 +++-
 src/include/lwip/priv/memp_std.h     |   7 +
 src/include/lwip/priv/sockets_priv.h |  49 +--
 src/include/lwip/priv/tcp_priv.h     | 162 +++++++++-
 src/include/lwip/prot/ip4.h          |  15 +
 src/include/lwip/sockets.h           |  67 ++++-
 src/include/lwip/stats.h             |   4 +-
 src/include/lwip/tcp.h               |  94 +++++-
 src/include/lwip/tcpip.h             |   2 +-
 src/include/lwip/timeouts.h          |   4 +
 src/include/lwiplog.h                |  81 +++++
 src/include/lwipopts.h               | 253 ++++++++++++----
 src/include/lwipsock.h               | 155 ++++++++++
 src/include/memp_def.h               |  66 +++++
 src/include/posix_api.h              |  88 ++++++
 src/include/reg_sock.h               |  62 ++++
 src/netif/dir.mk                     |   2 +-
 53 files changed, 3581 insertions(+), 206 deletions(-)
 create mode 100644 src/api/perf.c
 create mode 100644 src/api/posix_api.c
 create mode 100644 src/api/sys_arch.c
 create mode 100644 src/include/arch/perf.h
 create mode 100644 src/include/eventpoll.h
 create mode 100644 src/include/hlist.h
 create mode 100644 src/include/list.h
 create mode 100644 src/include/lwiplog.h
 create mode 100644 src/include/lwipsock.h
 create mode 100644 src/include/memp_def.h
 create mode 100644 src/include/posix_api.h
 create mode 100644 src/include/reg_sock.h

diff --git a/src/Makefile b/src/Makefile
index 3ecf8d2..1676a71 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2,7 +2,7 @@ LWIP_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
 ROOT_DIR := $(dir $(abspath $(LWIP_DIR)))
 
 LWIP_INC = $(LWIP_DIR)/include
-#DPDK_INCLUDE_FILE ?= /usr/include/dpdk
+DPDK_INCLUDE_FILE ?= /usr/include/dpdk
 
 SEC_FLAGS = -fstack-protector-strong -Werror -Wall -Wl,-z,relro,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIC
 
@@ -10,7 +10,8 @@ CC = gcc
 AR = ar
 OPTIMIZATION = -O3
 INC = -I$(LWIP_DIR) \
-      -I$(LWIP_INC)
+      -I$(LWIP_INC) \
+      -I$(DPDK_INCLUDE_FILE)
 
 CFLAGS = -g $(OPTIMIZATION) $(INC) $(SEC_FLAGS)
 ARFLAGS = crDP
diff --git a/src/api/api_lib.c b/src/api/api_lib.c
index 60678f8..4cdb965 100644
--- a/src/api/api_lib.c
+++ b/src/api/api_lib.c
@@ -1061,7 +1061,9 @@ netconn_write_vectors_partly(struct netconn *conn, struct netvector *vectors, u1
   /* For locking the core: this _can_ be delayed on low memory/low send buffer,
      but if it is, this is done inside api_msg.c:do_write(), so we can use the
      non-blocking version here. */
+  PERF_START(PERF_LAYER_TCP, PERF_POINT_TCP_DATA_SEND);
   err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
+  PERF_STOP_INCREASE_COUNT("lwip_netconn_do_write", PERF_LAYER_TCP);
   if (err == ERR_OK) {
     if (bytes_written != NULL) {
       *bytes_written = API_MSG_VAR_REF(msg).msg.w.offset;
diff --git a/src/api/api_msg.c b/src/api/api_msg.c
index 8092be9..d8d6339 100644
--- a/src/api/api_msg.c
+++ b/src/api/api_msg.c
@@ -54,6 +54,11 @@
 #include "lwip/mld6.h"
 #include "lwip/priv/tcpip_priv.h"
 
+#if USE_LIBOS
+#include "lwip/sockets.h"
+#include "lwipsock.h"
+#endif
+
 #include <string.h>
 
 /* netconns are polled once per second (e.g. continue write on memory error) */
@@ -455,6 +460,14 @@ err_tcp(void *arg, err_t err)
   old_state = conn->state;
   conn->state = NETCONN_NONE;
 
+#if USE_LIBOS
+  if (CONN_TYPE_IS_HOST(conn)) {
+    LWIP_DEBUGF(API_MSG_DEBUG, 
+        ("linux localhost connection already success, ignore lwip err_tcp fd=%d\n", conn->socket));
+    return;
+  }
+#endif /* USE_LIBOS */
+
   SYS_ARCH_UNPROTECT(lev);
 
   /* Notify the user layer about a connection error. Used to signal select. */
@@ -598,6 +611,10 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
     API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
   }
 
+#if USE_LIBOS
+  LWIP_DEBUGF(API_MSG_DEBUG, ("libos incoming connection established\n"));
+  SET_CONN_TYPE_LIBOS(newconn);
+#endif
   return ERR_OK;
 }
 #endif /* LWIP_TCP */
@@ -1316,6 +1333,31 @@ lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
     return ERR_VAL;
   }
 
+#if USE_LIBOS
+  if (CONN_TYPE_IS_HOST(conn)) {
+    LWIP_DEBUGF(API_MSG_DEBUG,
+        ("libos outgoing connection abort fd=%d\n", conn->socket));
+    return ERR_ABRT;
+  }
+  
+  LWIP_DEBUGF(API_MSG_DEBUG, ("libos outgoing connection established\n"));
+  if (CONN_TYPE_HAS_INPRG(conn) && CONN_TYPE_HAS_HOST(conn)) {
+    int s = conn->socket;
+    struct lwip_sock *sock = get_socket_without_errno(s);
+  
+    if (!!sock && !!sock->epoll_data) {
+      struct epoll_event ee = {0};
+      ee.data.fd = s;
+      ee.events |= EPOLLIN | EPOLLOUT | EPOLLERR;
+      posix_api->epoll_ctl_fn(sock->epoll_data->fd, EPOLL_CTL_DEL, s, &ee);
+      posix_api->shutdown_fn(s, SHUT_RDWR);
+      LWIP_DEBUGF(API_MSG_DEBUG,
+          ("linux outgoing connection abort fd=%d\n", s));
+    }
+  }
+  SET_CONN_TYPE_LIBOS(conn);
+#endif
+
   LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);
   LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect",
               (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));
@@ -1339,6 +1381,7 @@ lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
   if (was_blocking) {
     sys_sem_signal(op_completed_sem);
   }
+
   return ERR_OK;
 }
 #endif /* LWIP_TCP */
@@ -1373,6 +1416,7 @@ lwip_netconn_do_connect(void *m)
 #endif /* LWIP_UDP */
 #if LWIP_TCP
       case NETCONN_TCP:
+        PERF_START(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_SEND);
         /* Prevent connect while doing any other action. */
         if (msg->conn->state == NETCONN_CONNECT) {
           err = ERR_ALREADY;
@@ -1390,6 +1434,7 @@ lwip_netconn_do_connect(void *m)
               err = ERR_INPROGRESS;
             } else {
               msg->conn->current_msg = msg;
+              PERF_STOP_INCREASE_COUNT("lwip_netconn_do_connect", PERF_LAYER_TCP);
               /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()),
                  when the connection is established! */
 #if LWIP_TCPIP_CORE_LOCKING
@@ -1403,6 +1448,7 @@ lwip_netconn_do_connect(void *m)
             }
           }
         }
+        PERF_STOP_INCREASE_COUNT("lwip_netconn_do_connect", PERF_LAYER_TCP);
         break;
 #endif /* LWIP_TCP */
       default:
diff --git a/src/api/dir.mk b/src/api/dir.mk
index 72142ab..afbf863 100644
--- a/src/api/dir.mk
+++ b/src/api/dir.mk
@@ -1,3 +1,3 @@
-SRC = api_lib.c api_msg.c err.c netbuf.c netdb.c netifapi.c sockets.c tcpip.c
+SRC = api_lib.c api_msg.c err.c netbuf.c netdb.c netifapi.c sockets.c tcpip.c perf.c posix_api.c sys_arch.c
 
 $(eval $(call register_dir, api, $(SRC)))
diff --git a/src/api/perf.c b/src/api/perf.c
new file mode 100644
index 0000000..1c2a273
--- /dev/null
+++ b/src/api/perf.c
@@ -0,0 +1,182 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#include "arch/perf.h"
+
+#include <signal.h>
+
+#include <lwip/stats.h>
+
+#if LWIP_RECORD_PERF
+
+#define SIG_FUNC_NUM      3
+
+#define SIG_STATS_DISPLAY 38
+#define SIG_PERF_BEGIN    39
+#define SIG_PERF_END      40
+
+typedef void (*pSignalFunc) (int);
+static void signal_stats_display(int s);
+static void signal_perf_begin(int s);
+static void signal_perf_end(int s);
+
+uint32_t g_record_perf;
+__thread uint64_t g_timeTaken[PERF_POINT_END];
+__thread int g_perfPoint[PERF_LAYER_END];
+__thread struct timespec tvStart[PERF_LAYER_END];
+volatile uint64_t g_perfMaxtime[PERF_POINT_END];
+volatile uint64_t g_astPacketCnt[PERF_POINT_END];
+volatile uint64_t g_astPacketProcTime[PERF_POINT_END];
+
+char *g_ppLayerName[PERF_POINT_END] = {
+    "IP_RECV",
+    "TCP_DATA_RECV",
+    "UDP_PARTIAL",
+    "TCP_SYN_RECV",
+    "TCP_SYN_ACK_SEND",
+    "TCP_ACK_RECV",
+    "TCP_SYN_SEND",
+    "TCP_SYN_ACK_RECV",
+    "TCP_ACK_SEND",
+    "TCP_DATA_SEND",
+    "IP_SEND"
+};
+
+static int gsig_arr[SIG_FUNC_NUM] = {
+    SIG_STATS_DISPLAY,
+    SIG_PERF_BEGIN,
+    SIG_PERF_END
+};
+
+static pSignalFunc g_Funcs[SIG_FUNC_NUM] = {
+    signal_stats_display,
+    signal_perf_begin,
+    signal_perf_end,
+};
+
+static void print_perf_data_and_reset()
+{
+    int i;
+    printf("\n********* PERF DATA START*************\n");
+    for (i = 0; i < PERF_POINT_END; i++) {
+        printf("%-20s Total:     PacketProcTime: %-15"PRIu64", Maxtime: %-15"PRIu64", packetCnt: %-15"PRIu64"\n",
+            g_ppLayerName[i], __sync_fetch_and_or(&g_astPacketProcTime[i], 0),
+            __sync_fetch_and_or(&g_perfMaxtime[i], 0),
+            __sync_fetch_and_or(&g_astPacketCnt[i], 0));
+
+        if (__sync_fetch_and_or(&g_astPacketProcTime[i], 0) && __sync_fetch_and_or(&g_astPacketCnt[i], 0)) {
+        printf("%-20s Average:   PacketProcTime: %-15lf, MaxTime: %-15"PRIu64"\n", g_ppLayerName[i],
+            (double)__sync_fetch_and_or(&g_astPacketProcTime[i], 0) / (double)__sync_fetch_and_or(&g_astPacketCnt[i], 0),
+            __sync_or_and_fetch(&g_perfMaxtime[i], 0));
+        }
+
+        __sync_fetch_and_and (&g_astPacketProcTime[i], 0);
+        __sync_fetch_and_and (&g_astPacketCnt[i], 0);
+        __sync_fetch_and_and (&g_perfMaxtime[i], 0);
+    }
+    printf("\n********* PERF DATA END*************\n");
+}
+
+static void signal_stats_display(int s)
+{
+    struct sigaction s_test;
+    printf("Received signal %d, stats display.\n", s);
+    stats_display();
+    s_test.sa_handler = (void *) signal_stats_display;
+    if (sigemptyset(&s_test.sa_mask) != 0) {
+        printf("sigemptyset failed.\n");
+    }
+    s_test.sa_flags = SA_RESETHAND;
+    if (sigaction(s, &s_test, NULL) != 0) {
+        printf("Could not register %d signal handler.\n", s);
+    }
+}
+
+static void signal_perf_begin(int s)
+{
+    struct sigaction s_test;
+    printf("Received signal %d, perf_begin.\n", s);
+    g_record_perf = 1;
+    s_test.sa_handler = (void *) signal_perf_begin;
+    if (sigemptyset(&s_test.sa_mask) != 0) {
+        printf("sigemptyset failed.\n");
+    }
+    s_test.sa_flags = SA_RESETHAND;
+    if (sigaction(s, &s_test, NULL) != 0) {
+        printf("Could not register %d signal handler.\n", s);
+    }
+}
+
+static void signal_perf_end(int s)
+{
+    struct sigaction s_test;
+    printf("Received signal %d, perf_end\n", s);
+    g_record_perf = 0;
+    print_perf_data_and_reset();
+    s_test.sa_handler = (void *) signal_perf_end;
+    if (sigemptyset(&s_test.sa_mask) != 0) {
+        printf("sigemptyset failed.\n");
+    }
+    s_test.sa_flags = SA_RESETHAND;
+    if (sigaction(s, &s_test, NULL) != 0) {
+        printf("Could not register %d signal handler.\n", s);
+    }
+}
+
+int check_layer_point(int layer, int point)
+{
+    if (point == g_perfPoint[layer]) {
+        return 1;
+    }
+    return 0;
+}
+
+int perf_init(void)
+{
+    int i;
+    struct sigaction s_test;
+    for (i = 0; i < SIG_FUNC_NUM; i++) {
+        s_test.sa_handler = (void *) g_Funcs[i];
+        if (sigemptyset(&s_test.sa_mask) != 0) {
+            printf("sigemptyset failed.\n");
+            return 1;
+        }
+
+        s_test.sa_flags = SA_RESETHAND;
+        if (sigaction(gsig_arr[i], &s_test, NULL) != 0) {
+            printf("Could not register %d signal handler.\n", gsig_arr[i]);
+            return 1;
+        }
+    }
+    return 0;
+}
+#endif
diff --git a/src/api/posix_api.c b/src/api/posix_api.c
new file mode 100644
index 0000000..a917cea
--- /dev/null
+++ b/src/api/posix_api.c
@@ -0,0 +1,156 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <rte_log.h>
+
+#include "lwip/err.h"
+#include "lwipsock.h"
+
+posix_api_t *posix_api;
+posix_api_t posix_api_val;
+
+static int chld_is_epfd(int fd)
+{
+    return 0;
+}
+
+static struct lwip_sock *chld_get_socket(int fd)
+{
+    return NULL;
+}
+
+void posix_api_fork(void)
+{
+    /* lstack helper api */
+    posix_api->is_chld = 1;
+    posix_api->is_epfd = chld_is_epfd;
+    posix_api->get_socket = chld_get_socket;
+}
+
+static int chose_dlsym_handle(void *__restrict* khandle)
+{
+    void *dlhandle;
+    int (*gazelle_epoll_create)(int size);
+    dlhandle = dlopen ("liblstack.so", RTLD_LAZY);
+    if (dlhandle == NULL) {
+        return ERR_IF;
+    }
+
+    gazelle_epoll_create = dlsym(dlhandle, "epoll_create");
+    if (gazelle_epoll_create == NULL) {
+        return ERR_MEM;
+    }
+
+    dlclose(dlhandle); 
+
+    *khandle = RTLD_NEXT;
+    if (dlsym(*khandle, "epoll_create") == gazelle_epoll_create) {
+        RTE_LOG(ERR, EAL, "posix api use RTLD_DEFAULT\n");
+        *khandle = RTLD_DEFAULT;
+    } else {
+        RTE_LOG(ERR, EAL, "posix api use RTLD_NEXT\n");
+    }
+
+    return ERR_OK;
+}
+
+int posix_api_init(void)
+{
+/* the symbol we use here won't be NULL, so we don't need dlerror()
+ to test error */
+#define CHECK_DLSYM_RET_RETURN(ret) do {  \
+        if ((ret) == NULL)                   \
+            goto err_out;                 \
+    } while (0)
+
+    posix_api = &posix_api_val;
+
+    void *__restrict handle;
+    int ret = chose_dlsym_handle(&handle);
+    if (ret != ERR_OK) {
+        return ret;
+    }
+
+    /* glibc standard api */
+    CHECK_DLSYM_RET_RETURN(posix_api->socket_fn = dlsym(handle, "socket"));
+    CHECK_DLSYM_RET_RETURN(posix_api->accept_fn = dlsym(handle, "accept"));
+    CHECK_DLSYM_RET_RETURN(posix_api->accept4_fn = dlsym(handle, "accept4"));
+    CHECK_DLSYM_RET_RETURN(posix_api->bind_fn = dlsym(handle, "bind"));
+    CHECK_DLSYM_RET_RETURN(posix_api->listen_fn = dlsym(handle, "listen"));
+    CHECK_DLSYM_RET_RETURN(posix_api->connect_fn = dlsym(handle, "connect"));
+    CHECK_DLSYM_RET_RETURN(posix_api->setsockopt_fn = dlsym(handle, "setsockopt"));
+    CHECK_DLSYM_RET_RETURN(posix_api->getsockopt_fn = dlsym(handle, "getsockopt"));
+    CHECK_DLSYM_RET_RETURN(posix_api->getpeername_fn = dlsym(handle, "getpeername"));
+    CHECK_DLSYM_RET_RETURN(posix_api->getsockname_fn = dlsym(handle, "getsockname"));
+    CHECK_DLSYM_RET_RETURN(posix_api->shutdown_fn = dlsym(handle, "shutdown"));
+    CHECK_DLSYM_RET_RETURN(posix_api->close_fn = dlsym(handle, "close"));
+    CHECK_DLSYM_RET_RETURN(posix_api->read_fn = dlsym(handle, "read"));
+    CHECK_DLSYM_RET_RETURN(posix_api->write_fn = dlsym(handle, "write"));
+    CHECK_DLSYM_RET_RETURN(posix_api->recv_fn = dlsym(handle, "recv"));
+    CHECK_DLSYM_RET_RETURN(posix_api->send_fn = dlsym(handle, "send"));
+    CHECK_DLSYM_RET_RETURN(posix_api->recv_msg = dlsym(handle, "recvmsg"));
+    CHECK_DLSYM_RET_RETURN(posix_api->send_msg = dlsym(handle, "sendmsg"));
+    CHECK_DLSYM_RET_RETURN(posix_api->recv_from = dlsym(handle, "recvfrom"));
+    CHECK_DLSYM_RET_RETURN(posix_api->send_to = dlsym(handle, "sendto"));
+    CHECK_DLSYM_RET_RETURN(posix_api->fcntl_fn = dlsym(handle, "fcntl"));
+    CHECK_DLSYM_RET_RETURN(posix_api->fcntl64_fn = dlsym(handle, "fcntl64"));
+    CHECK_DLSYM_RET_RETURN(posix_api->pipe_fn = dlsym(handle, "pipe"));
+    CHECK_DLSYM_RET_RETURN(posix_api->epoll_create_fn = dlsym(handle, "epoll_create"));
+    CHECK_DLSYM_RET_RETURN(posix_api->epoll_ctl_fn = dlsym(handle, "epoll_ctl"));
+    CHECK_DLSYM_RET_RETURN(posix_api->epoll_wait_fn = dlsym(handle, "epoll_wait"));
+    CHECK_DLSYM_RET_RETURN(posix_api->fork_fn = dlsym(handle, "fork"));
+    CHECK_DLSYM_RET_RETURN(posix_api->eventfd_fn = dlsym(handle, "eventfd"));
+    CHECK_DLSYM_RET_RETURN(posix_api->sigaction_fn = dlsym(handle, "sigaction"));
+    CHECK_DLSYM_RET_RETURN(posix_api->poll_fn = dlsym(handle, "poll"));
+    CHECK_DLSYM_RET_RETURN(posix_api->ioctl_fn = dlsym(handle, "ioctl"));
+
+    /* lstack helper api */
+    posix_api->get_socket = get_socket;
+    posix_api->is_epfd = lwip_is_epfd;
+    posix_api->epoll_close_fn = lwip_epoll_close;
+
+    /* support fork */
+    posix_api->is_chld = 0;
+    return ERR_OK;
+
+err_out:
+    return ERR_MEM;
+#undef CHECK_DLSYM_RET_RETURN
+}
diff --git a/src/api/sockets.c b/src/api/sockets.c
index b911194..8df741d 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -62,8 +62,21 @@
 #include <stdarg.h>
 #endif
 
+#if USE_LIBOS
+#include <stdarg.h>
+#include "lwipsock.h"
+#endif
+
 #include <string.h>
 
+#if USE_LIBOS
+enum KERNEL_LWIP_PATH {
+  PATH_KERNEL = 0,
+  PATH_LWIP,
+  PATH_ERR,
+};
+#endif
+
 #ifdef LWIP_HOOK_FILENAME
 #include LWIP_HOOK_FILENAME
 #endif
@@ -92,6 +105,7 @@
 /* Address length safe read and write */
 #if LWIP_SOCKET_HAVE_SA_LEN
 
+
 #if LWIP_IPV4
 #define IP4ADDR_SOCKADDR_SET_LEN(sin) \
       (sin)->sin_len = sizeof(struct sockaddr_in)
@@ -130,12 +144,20 @@
 #endif /* LWIP_SOCKET_HAVE_SA_LEN */
 
 #if LWIP_IPV4
+#if USE_LIBOS
+#define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
+      (sin)->sin_family = AF_INET; \
+      (sin)->sin_port = lwip_htons((port)); \
+      inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
+      memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
+#else
 #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \
       IP4ADDR_SOCKADDR_SET_LEN(sin); \
       (sin)->sin_family = AF_INET; \
       (sin)->sin_port = lwip_htons((port)); \
       inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \
       memset((sin)->sin_zero, 0, SIN_ZERO_LEN); }while(0)
+#endif /* USE_LIBOS */
 #define SOCKADDR4_TO_IP4ADDR_PORT(sin, ipaddr, port) do { \
     inet_addr_to_ip4addr(ip_2_ip4(ipaddr), &((sin)->sin_addr)); \
     (port) = lwip_ntohs((sin)->sin_port); }while(0)
@@ -301,7 +323,12 @@ static void lwip_socket_drop_registered_mld6_memberships(int s);
 #endif /* LWIP_IPV6_MLD */
 
 /** The global array of available sockets */
+#if USE_LIBOS
+uint32_t sockets_num;
+struct lwip_sock *sockets;
+#else
 static struct lwip_sock sockets[NUM_SOCKETS];
+#endif /* USE_LIBOS */
 
 #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
 #if LWIP_TCPIP_CORE_LOCKING
@@ -324,7 +351,7 @@ static struct lwip_select_cb *select_cb_list;
 
 /* Forward declaration of some functions */
 #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
-static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
+void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
 #define DEFAULT_SOCKET_EVENTCB event_callback
 static void select_check_waiters(int s, int has_recvevent, int has_sendevent, int has_errevent);
 #else
@@ -450,7 +477,13 @@ static struct lwip_sock *
 tryget_socket_unconn_nouse(int fd)
 {
   int s = fd - LWIP_SOCKET_OFFSET;
-  if ((s < 0) || (s >= NUM_SOCKETS)) {
+
+#if USE_LIBOS
+  if ((s < 0) || (s >= sockets_num))
+#else
+  if ((s < 0) || (s >= NUM_SOCKETS))
+#endif /* USE_LIBOS */
+  {
     LWIP_DEBUGF(SOCKETS_DEBUG, ("tryget_socket_unconn(%d): invalid\n", fd));
     return NULL;
   }
@@ -514,8 +547,13 @@ tryget_socket(int fd)
  * @param fd externally used socket index
  * @return struct lwip_sock for the socket or NULL if not found
  */
+#if USE_LIBOS
+struct lwip_sock *
+get_socket(int fd)
+#else
 static struct lwip_sock *
 get_socket(int fd)
+#endif /* USE_LIBOS */
 {
   struct lwip_sock *sock = tryget_socket(fd);
   if (!sock) {
@@ -528,6 +566,24 @@ get_socket(int fd)
   return sock;
 }
 
+#if USE_LIBOS
+/**
+ * Map a externally used socket index to the internal socket representation.
+ *
+ * @param s externally used socket index
+ * @return struct lwip_sock for the socket or NULL if not found without
+ * checking.
+ */
+struct lwip_sock *
+get_socket_by_fd(int fd)
+{
+  if ((fd < LWIP_SOCKET_OFFSET) || (fd >= sockets_num + LWIP_SOCKET_OFFSET)) {
+    return NULL;
+  }
+  return &sockets[fd - LWIP_SOCKET_OFFSET];
+}
+#endif /* USE_LIBOS */
+
 /**
  * Allocate a new socket for a given netconn.
  *
@@ -543,6 +599,62 @@ alloc_socket(struct netconn *newconn, int accepted)
   SYS_ARCH_DECL_PROTECT(lev);
   LWIP_UNUSED_ARG(accepted);
 
+#if USE_LIBOS
+  int type, protocol = 0, domain = AF_INET;
+  switch (NETCONNTYPE_GROUP(newconn->type)) {
+    case NETCONN_RAW:
+      type = SOCK_RAW;
+      break;
+    case NETCONN_UDPLITE:
+    case NETCONN_UDP:
+      type = SOCK_DGRAM;
+      break;
+    case NETCONN_TCP:
+      type = SOCK_STREAM;
+      break;
+    default:
+      type = -1;
+      break;
+  }
+
+  SYS_ARCH_PROTECT(lev);
+  i = posix_api->socket_fn(domain, type, protocol);
+  if (i == -1) {
+    goto err;
+  }
+
+  if ((i < LWIP_SOCKET_OFFSET) || (i >= sockets_num + LWIP_SOCKET_OFFSET)) {
+    goto err;
+  }
+
+  if (!sockets[i].conn && (sockets[i].select_waiting == 0)) {
+    /*initialize state as NETCONN_HOST | NETCONN_LIBOS,
+     *if connection accepted and alloc_socket called, it can be only NETCONN_LIBOS*/
+    if (accepted)
+      SET_CONN_TYPE_LIBOS(newconn);
+    else
+      SET_CONN_TYPE_LIBOS_OR_HOST(newconn);
+    sockets[i].conn       = newconn;
+    /* The socket is not yet known to anyone, so no need to protect
+       after having marked it as used. */
+    SYS_ARCH_UNPROTECT(lev);
+    sockets[i].lastdata.pbuf = NULL;
+    sockets[i].rcvevent   = 0;
+    /* TCP sendbuf is empty, but the socket is not yet writable until connected
+     * (unless it has been created by accept()). */
+    sockets[i].sendevent  = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
+    sockets[i].errevent   = 0;
+    sockets[i].epoll_data = NULL;
+    init_list_node_null(&sockets[i].list);
+    return i + LWIP_SOCKET_OFFSET;
+  }
+
+err:
+  posix_api->close_fn(i);
+  SYS_ARCH_UNPROTECT(lev);
+  return -1;
+#else /* USE_LIBOS */
+
   /* allocate a new socket identifier */
   for (i = 0; i < NUM_SOCKETS; ++i) {
     /* Protect socket array */
@@ -574,6 +686,8 @@ alloc_socket(struct netconn *newconn, int accepted)
     SYS_ARCH_UNPROTECT(lev);
   }
   return -1;
+
+#endif /* USE_LIBOS */
 }
 
 /** Free a socket (under lock)
@@ -668,10 +782,43 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
   SYS_ARCH_DECL_PROTECT(lev);
 
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
+#if USE_LIBOS
+  int sys_errno = 0;
+  
+  sock = posix_api->get_socket(s);
+  /*AF_UNIX case*/
+  if (!sock) {
+    if (rearm_accept_fd(s) < 0) {
+      LWIP_DEBUGF(SOCKETS_DEBUG,
+          ("failed to rearm accept fd=%d errno=%d\n", s, errno));
+    }
+    return posix_api->accept_fn(s, addr, addrlen);
+  }
+  
+  /*for AF_INET, we may try both linux and lwip*/
+  if (!CONN_TYPE_HAS_LIBOS_AND_HOST(sock->conn)) {
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("conn->type has libos and host bits"));
+    set_errno(EINVAL);
+    return -1;
+  }
+  
+  if (rearm_accept_fd(s) < 0) {
+    LWIP_DEBUGF(SOCKETS_DEBUG,
+        ("failed to rearm accept fd=%d errno=%d\n", s, errno));
+  }
+  
+  /* raise accept syscall in palce */
+  newsock = posix_api->accept_fn(s, addr, addrlen);
+  if (newsock >= 0) {
+    return newsock;
+  }
+  sys_errno = errno;
+#else
   sock = get_socket(s);
   if (!sock) {
     return -1;
   }
+#endif
 
   /* wait for a new connection */
   err = netconn_accept(sock->conn, &newconn);
@@ -685,6 +832,9 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
       set_errno(err_to_errno(err));
     }
     done_socket(sock);
+#if USE_LIBOS
+    set_errno(sys_errno);
+#endif /* USE_LIBOS */
     return -1;
   }
   LWIP_ASSERT("newconn != NULL", newconn != NULL);
@@ -696,7 +846,11 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
     done_socket(sock);
     return -1;
   }
+#if USE_LIBOS
+  LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < sockets_num + LWIP_SOCKET_OFFSET));
+#else
   LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET));
+#endif /* USE_LIBOS */
   nsock = &sockets[newsock - LWIP_SOCKET_OFFSET];
 
   /* See event_callback: If data comes in right away after an accept, even
@@ -734,9 +888,11 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
     }
 
     IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port);
+#if !USE_LIBOS
     if (*addrlen > IPADDR_SOCKADDR_GET_LEN(&tempaddr)) {
       *addrlen = IPADDR_SOCKADDR_GET_LEN(&tempaddr);
     }
+#endif /* USE_LIBOS */
     MEMCPY(addr, &tempaddr, *addrlen);
 
     LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
@@ -759,11 +915,24 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
   ip_addr_t local_addr;
   u16_t local_port;
   err_t err;
-
+#if USE_LIBOS
+  sock = posix_api->get_socket(s);
+  /*AF_UNIX case*/
+  if (!sock) {
+    return posix_api->bind_fn(s, name, namelen);
+  }
+  /*for AF_INET, we may try both linux and lwip*/
+  if (!CONN_TYPE_HAS_LIBOS_AND_HOST(sock->conn)) {
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("conn->type has libos and host bits"));
+    set_errno(EINVAL);
+    return -1;
+  }
+#else
   sock = get_socket(s);
   if (!sock) {
     return -1;
   }
+#endif
 
   if (!SOCK_ADDR_TYPE_MATCH(name, sock)) {
     /* sockaddr does not match socket type (IPv4/IPv6) */
@@ -783,6 +952,18 @@ lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
   ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr);
   LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port));
 
+#if USE_LIBOS
+  /* Supports kernel NIC IP address. */
+  int ret = posix_api->bind_fn(s, name, namelen);
+  if (ret < 0) {
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("bind syscall failed\n"));
+    /* bind must succeed on both linux and libos */
+    if (!is_host_ipv4(local_addr.addr)) {
+      return ret;
+    }
+  }
+#endif /* USE_LIBOS */
+
 #if LWIP_IPV4 && LWIP_IPV6
   /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */
   if (IP_IS_V6_VAL(local_addr) && ip6_addr_isipv4mappedipv6(ip_2_ip6(&local_addr))) {
@@ -815,10 +996,29 @@ lwip_close(int s)
 
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
 
+#if USE_LIBOS
+  int ret;
+  if (posix_api->is_epfd(s)) {
+    return posix_api->epoll_close_fn(s);
+  }
+
+  ret = posix_api->close_fn(s);
+  if (ret < 0)
+    return ret;
+  if (posix_api->is_chld == 0)
+    clean_host_fd(s);
+
+  sock = posix_api->get_socket(s);
+  /*AF_UNIX case*/
+  if (!sock) {
+    return ret;
+  }
+#else
   sock = get_socket(s);
   if (!sock) {
     return -1;
   }
+#endif /* USE_LIBOS */
 
   if (sock->conn != NULL) {
     is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
@@ -842,6 +1042,13 @@ lwip_close(int s)
     return -1;
   }
 
+#if USE_LIBOS
+  sock->epoll = LIBOS_EPOLLNONE;
+  sock->events = 0;
+  sock->epoll_data = NULL;
+  list_del_node_null(&sock->list);
+#endif
+
   free_socket(sock, is_tcp);
   set_errno(0);
   return 0;
@@ -853,10 +1060,28 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
   struct lwip_sock *sock;
   err_t err;
 
+#if USE_LIBOS
+  int ret;
+  
+  sock = posix_api->get_socket(s);
+  if (!sock) {
+    return posix_api->connect_fn(s, name, namelen);
+  }
+  
+  /* raise connect syscall in place */
+  ADD_CONN_TYPE_INPRG(sock->conn);
+  ret = posix_api->connect_fn(s, name, namelen);
+  if (!ret) {
+    SET_CONN_TYPE_HOST(sock->conn);
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("linux connect succeed fd=%d\n", s));
+    return ret;
+  }
+#else
   sock = get_socket(s);
   if (!sock) {
     return -1;
   }
+#endif
 
   if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) {
     /* sockaddr does not match socket type (IPv4/IPv6) */
@@ -901,6 +1126,11 @@ lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
     return -1;
   }
 
+#if USE_LIBOS
+  LWIP_DEBUGF(SOCKETS_DEBUG, ("libos connect succeed fd=%d\n",s));
+  SET_CONN_TYPE_LIBOS(sock->conn);
+#endif /* USE_LIBOS */
+
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
   set_errno(0);
   done_socket(sock);
@@ -923,10 +1153,29 @@ lwip_listen(int s, int backlog)
 
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
 
+#if USE_LIBOS
+  int ret;
+  
+  sock = posix_api->get_socket(s);
+  /*AF_UNIX case*/
+  if (!sock) {
+    return posix_api->listen_fn(s, backlog);
+  }
+  /*for AF_INET, we may try both linux and lwip*/
+  if (!CONN_TYPE_HAS_LIBOS_AND_HOST(sock->conn)) {
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("conn->type has libos and host bits"));
+    set_errno(EADDRINUSE);
+    return -1;
+  }
+  
+  if ((ret = posix_api->listen_fn(s, backlog)) == -1)
+    return ret;
+#else
   sock = get_socket(s);
   if (!sock) {
     return -1;
   }
+#endif
 
   /* limit the "backlog" parameter to fit in an u8_t */
   backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
@@ -958,6 +1207,9 @@ static ssize_t
 lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
 {
   u8_t apiflags = NETCONN_NOAUTORCVD;
+#if USE_LIBOS
+  apiflags = 0;
+#endif
   ssize_t recvd = 0;
   ssize_t recv_left = (len <= SSIZE_MAX) ? (ssize_t)len : SSIZE_MAX;
 
@@ -977,6 +1229,13 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
     /* Check if there is data left from the last recv operation. */
     if (sock->lastdata.pbuf) {
       p = sock->lastdata.pbuf;
+#if USE_LIBOS
+      if ((flags & MSG_PEEK) == 0) {
+        if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP)) {
+          del_epoll_event(sock->conn, EPOLLIN);
+        }
+      }
+#endif
     } else {
       /* No data was left from the previous operation, so we try to get
          some from the network. */
@@ -1047,10 +1306,22 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
     /* @todo: do we need to support peeking more than one pbuf? */
   } while ((recv_left > 0) && !(flags & MSG_PEEK));
 lwip_recv_tcp_done:
-  if ((recvd > 0) && !(flags & MSG_PEEK)) {
-    /* ensure window update after copying all data */
-    netconn_tcp_recvd(sock->conn, (size_t)recvd);
+#if USE_LIBOS
+  if (apiflags & NETCONN_NOAUTORCVD)
+#endif
+  {
+    if ((recvd > 0) && !(flags & MSG_PEEK)) {
+      /* ensure window update after copying all data */
+      netconn_tcp_recvd(sock->conn, (size_t)recvd);
+    }
   }
+#if USE_LIBOS
+  if ((flags & MSG_PEEK) == 0) {
+    if (((NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP)) && sock->lastdata.pbuf) {
+      add_epoll_event(sock->conn, EPOLLIN);
+    }
+  }
+#endif
   set_errno(0);
   return recvd;
 }
@@ -1079,11 +1350,13 @@ lwip_sock_make_addr(struct netconn *conn, ip_addr_t *fromaddr, u16_t port,
 #endif /* LWIP_IPV4 && LWIP_IPV6 */
 
   IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
+#if !USE_LIBOS
   if (*fromlen < IPADDR_SOCKADDR_GET_LEN(&saddr)) {
     truncated = 1;
   } else if (*fromlen > IPADDR_SOCKADDR_GET_LEN(&saddr)) {
     *fromlen = IPADDR_SOCKADDR_GET_LEN(&saddr);
   }
+#endif
   MEMCPY(from, &saddr, *fromlen);
   return truncated;
 }
@@ -1233,6 +1506,43 @@ lwip_recvfrom_udp_raw(struct lwip_sock *sock, int flags, struct msghdr *msg, u16
   return ERR_OK;
 }
 
+#if USE_LIBOS
+static inline enum KERNEL_LWIP_PATH select_path(int s)
+{
+  struct lwip_sock *sock;
+  
+  sock = posix_api->get_socket(s);
+  /*AF_UNIX case*/
+  if (!sock) {
+    if (rearm_host_fd(s) < 0) {
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("failed to rearm fd=%d errno=%d\n", s, errno));
+    }
+    return PATH_KERNEL;
+  }
+
+  if (CONN_TYPE_HAS_INPRG(sock->conn)) {
+    set_errno(EWOULDBLOCK);
+    return PATH_ERR;
+  }
+
+  /*for AF_INET, we can try erther linux or lwip*/
+  if (CONN_TYPE_IS_HOST(sock->conn)) {
+    if (rearm_host_fd(s) < 0) {
+      LWIP_DEBUGF(SOCKETS_DEBUG, ("failed to rearm read fd=%d errno=%d\n", s, errno));
+    }
+    return PATH_KERNEL;
+  }
+
+  if (!CONN_TYPE_IS_LIBOS(sock->conn)) {
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("conn->type is not libos bit type=%x", netconn_type(sock->conn)));
+    set_errno(EINVAL);
+    return PATH_ERR;
+  }
+
+  return PATH_LWIP;
+}
+#endif
+
 ssize_t
 lwip_recvfrom(int s, void *mem, size_t len, int flags,
               struct sockaddr *from, socklen_t *fromlen)
@@ -1240,6 +1550,15 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
   struct lwip_sock *sock;
   ssize_t ret;
 
+#if USE_LIBOS
+  enum KERNEL_LWIP_PATH path = select_path(s);
+  if (path == PATH_ERR) {
+    return -1;
+  } else if (path == PATH_KERNEL) {
+    return posix_api->recv_from(s, mem, len, flags, from, fromlen);
+  }
+#endif
+
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
   sock = get_socket(s);
   if (!sock) {
@@ -1289,6 +1608,14 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
 ssize_t
 lwip_read(int s, void *mem, size_t len)
 {
+#if USE_LIBOS
+  enum KERNEL_LWIP_PATH path = select_path(s);
+  if (path == PATH_ERR) {
+    return -1;
+  } else if (path == PATH_KERNEL) {
+    return posix_api->read_fn(s, mem, len);
+  }
+#endif
   return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
 }
 
@@ -1322,6 +1649,15 @@ lwip_recvmsg(int s, struct msghdr *message, int flags)
   msg_iovlen_t i;
   ssize_t buflen;
 
+#if USE_LIBOS
+  enum KERNEL_LWIP_PATH path = select_path(s);
+  if (path == PATH_ERR) {
+    return -1;
+  } else if (path == PATH_KERNEL) {
+    return posix_api->recv_msg(s, message, flags);
+  }
+#endif
+
   LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvmsg(%d, message=%p, flags=0x%x)\n", s, (void *)message, flags));
   LWIP_ERROR("lwip_recvmsg: invalid message pointer", message != NULL, return ERR_ARG;);
   LWIP_ERROR("lwip_recvmsg: unsupported flags", (flags & ~(MSG_PEEK|MSG_DONTWAIT)) == 0,
@@ -1466,6 +1802,15 @@ lwip_sendmsg(int s, const struct msghdr *msg, int flags)
 #endif
   err_t err = ERR_OK;
 
+#if USE_LIBOS
+  enum KERNEL_LWIP_PATH path = select_path(s);
+  if (path == PATH_ERR) {
+    return -1;
+  } else if (path == PATH_KERNEL) {
+    return posix_api->send_msg(s, msg, flags);
+  }
+#endif
+
   sock = get_socket(s);
   if (!sock) {
     return -1;
@@ -1629,6 +1974,15 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
   u16_t remote_port;
   struct netbuf buf;
 
+#if USE_LIBOS
+  enum KERNEL_LWIP_PATH path = select_path(s);
+  if (path == PATH_ERR) {
+    return -1;
+  } else if (path == PATH_KERNEL) {
+    return posix_api->send_to(s, data, size, flags, to, tolen);
+  }
+#endif
+
   sock = get_socket(s);
   if (!sock) {
     return -1;
@@ -1727,6 +2081,11 @@ lwip_socket(int domain, int type, int protocol)
 
   LWIP_UNUSED_ARG(domain); /* @todo: check this */
 
+#if USE_LIBOS
+  if ((domain != AF_INET && domain != AF_UNSPEC) || posix_api->is_chld)
+    return posix_api->socket_fn(domain, type, protocol);
+#endif
+
   /* create a netconn */
   switch (type) {
     case SOCK_RAW:
@@ -1783,6 +2142,14 @@ lwip_socket(int domain, int type, int protocol)
 ssize_t
 lwip_write(int s, const void *data, size_t size)
 {
+#if USE_LIBOS
+  enum KERNEL_LWIP_PATH path = select_path(s);
+  if (path == PATH_ERR) {
+    return -1;
+  } else if (path == PATH_KERNEL) {
+    return posix_api->write_fn(s, data, size);
+  }
+#endif
   return lwip_send(s, data, size, 0);
 }
 
@@ -2518,7 +2885,7 @@ lwip_poll_should_wake(const struct lwip_select_cb *scb, int fd, int has_recveven
  *   NETCONN_EVT_ERROR
  * This requirement will be asserted in select_check_waiters()
  */
-static void
+void
 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
 {
   int s, check_waiters;
@@ -2567,23 +2934,38 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
       if (sock->rcvevent > 1) {
         check_waiters = 0;
       }
+#if USE_LIBOS
+      add_epoll_event(conn, EPOLLIN);
+#endif
       break;
     case NETCONN_EVT_RCVMINUS:
       sock->rcvevent--;
       check_waiters = 0;
+#if USE_LIBOS
+      del_epoll_event(conn, EPOLLIN);
+#endif
       break;
     case NETCONN_EVT_SENDPLUS:
       if (sock->sendevent) {
         check_waiters = 0;
       }
       sock->sendevent = 1;
+#if USE_LIBOS
+      add_epoll_event(conn, EPOLLOUT);
+#endif
       break;
     case NETCONN_EVT_SENDMINUS:
       sock->sendevent = 0;
       check_waiters = 0;
+#if USE_LIBOS
+      del_epoll_event(conn, EPOLLOUT);
+#endif
       break;
     case NETCONN_EVT_ERROR:
       sock->errevent = 1;
+#if USE_LIBOS
+      add_epoll_event(conn, EPOLLERR);
+#endif
       break;
     default:
       LWIP_ASSERT("unknown event", 0);
@@ -2778,9 +3160,11 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
   ip_addr_debug_print_val(SOCKETS_DEBUG, naddr);
   LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port));
 
+#if !USE_LIBOS
   if (*namelen > IPADDR_SOCKADDR_GET_LEN(&saddr)) {
     *namelen = IPADDR_SOCKADDR_GET_LEN(&saddr);
   }
+#endif
   MEMCPY(name, &saddr, *namelen);
 
   set_errno(0);
@@ -2791,12 +3175,41 @@ lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
 int
 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
 {
+#if USE_LIBOS
+  struct lwip_sock *sock;
+  
+  sock = posix_api->get_socket(s);
+  if (!sock) {
+    return posix_api->getpeername_fn(s, name, namelen);
+  }
+  /*for AF_INET, if has only host type bit, just call linux api,
+   *if has libos and host type bits, it's a not connected fd, call
+   *linux api and return -1(errno == ENOTCONN) is also ok*/
+  if (CONN_TYPE_HAS_HOST(sock->conn)) {
+    return posix_api->getpeername_fn(s, name, namelen);
+  }
+#endif
+
   return lwip_getaddrname(s, name, namelen, 0);
 }
 
 int
 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
 {
+#if USE_LIBOS
+  struct lwip_sock *sock;
+  
+  sock = posix_api->get_socket(s);
+  if (!sock) {
+    return posix_api->getsockname_fn(s, name, namelen);
+  }
+  /*for AF_INET, if has only host type bit, just call linux api,
+   *if has libos and host type bits, also call linux api*/
+  if (CONN_TYPE_HAS_HOST(sock->conn)) {
+    return posix_api->getsockname_fn(s, name, namelen);
+  }
+#endif
+
   return lwip_getaddrname(s, name, namelen, 1);
 }
 
@@ -2804,15 +3217,28 @@ int
 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
 {
   int err;
-  struct lwip_sock *sock = get_socket(s);
 #if !LWIP_TCPIP_CORE_LOCKING
   err_t cberr;
   LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
 #endif /* !LWIP_TCPIP_CORE_LOCKING */
 
+#if USE_LIBOS
+  struct lwip_sock *sock = posix_api->get_socket(s);
+  
+  if (!sock) {
+    return posix_api->getsockopt_fn(s, level, optname, optval, optlen);
+  }
+  /*for AF_INET, we return linux result? */
+  if (CONN_TYPE_HAS_HOST(sock->conn)) {
+    return posix_api->getsockopt_fn(s, level, optname, optval, optlen);
+  }
+#else
+  struct lwip_sock *sock = get_socket(s);
+
   if (!sock) {
     return -1;
   }
+#endif /* USE_LIBOS */
 
   if ((NULL == optval) || (NULL == optlen)) {
     set_errno(EFAULT);
@@ -3250,15 +3676,30 @@ int
 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
 {
   int err = 0;
-  struct lwip_sock *sock = get_socket(s);
 #if !LWIP_TCPIP_CORE_LOCKING
   err_t cberr;
   LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
 #endif /* !LWIP_TCPIP_CORE_LOCKING */
 
+#if USE_LIBOS
+  struct lwip_sock *sock = posix_api->get_socket(s);
+
+  if (!sock) {
+    return posix_api->setsockopt_fn(s, level, optname, optval, optlen);
+  }
+  /*for AF_INET, we may try both linux and lwip*/
+  if (CONN_TYPE_HAS_HOST(sock->conn)) {
+    if (posix_api->setsockopt_fn(s, level, optname, optval, optlen) < 0) {
+      return -1;
+    }
+  }
+#else
+  struct lwip_sock *sock = get_socket(s);
+
   if (!sock) {
     return -1;
   }
+#endif /* USE_LIBOS */
 
   if (NULL == optval) {
     set_errno(EFAULT);
@@ -3372,6 +3813,7 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
         case SO_KEEPALIVE:
 #if SO_REUSE
         case SO_REUSEADDR:
+        case SO_REUSEPORT:
 #endif /* SO_REUSE */
           if ((optname == SO_BROADCAST) &&
               (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) {
@@ -3784,6 +4226,29 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
   return err;
 }
 
+#if USE_LIBOS
+int
+lwip_ioctl(int s, long cmd, ...)
+{
+  struct lwip_sock *sock = posix_api->get_socket(s);
+  u8_t val;
+
+  int ret = -1;
+  void *argp;
+  va_list ap;
+
+  va_start(ap, cmd);
+  argp = va_arg(ap, void *);
+  va_end(ap);
+
+  if (!sock) {
+    return posix_api->ioctl_fn(s, cmd, argp);
+  }
+  if (CONN_TYPE_HAS_HOST(sock->conn)) {
+    if ((ret = posix_api->ioctl_fn(s, cmd, argp)) == -1)
+      return ret;
+  }
+#else
 int
 lwip_ioctl(int s, long cmd, void *argp)
 {
@@ -3796,6 +4261,7 @@ lwip_ioctl(int s, long cmd, void *argp)
   if (!sock) {
     return -1;
   }
+#endif /* USE_LIBOS */
 
   switch (cmd) {
 #if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE
@@ -3878,6 +4344,26 @@ lwip_ioctl(int s, long cmd, void *argp)
  * the flag O_NONBLOCK is implemented for F_SETFL.
  */
 int
+#if USE_LIBOS
+lwip_fcntl(int s, int cmd, ...)
+{
+  struct lwip_sock *sock = posix_api->get_socket(s);
+  int val, ret = -1;
+  int op_mode = 0;
+  va_list ap;
+
+  va_start(ap, cmd);
+  val = va_arg(ap, int);
+  va_end(ap);
+
+  if (!sock) {
+    return posix_api->fcntl_fn(s, cmd, val);
+  }
+  if (CONN_TYPE_HAS_HOST(sock->conn)) {
+    if ((ret = posix_api->fcntl_fn(s, cmd, val)) == -1)
+      return ret;
+  }
+#else /* USE_LIBOS */
 lwip_fcntl(int s, int cmd, int val)
 {
   struct lwip_sock *sock = get_socket(s);
@@ -3887,6 +4373,7 @@ lwip_fcntl(int s, int cmd, int val)
   if (!sock) {
     return -1;
   }
+#endif /* USE_LIBOS */
 
   switch (cmd) {
     case F_GETFL:
@@ -4202,4 +4689,50 @@ lwip_socket_drop_registered_mld6_memberships(int s)
 }
 #endif /* LWIP_IPV6_MLD */
 
+#if USE_LIBOS
+void lwip_sock_init(void)
+{
+  if (sockets_num == 0) {
+    sockets_num = NUM_SOCKETS;
+    sockets = calloc(sockets_num, sizeof(struct lwip_sock));
+    LWIP_ASSERT("sockets != NULL", sockets != NULL);
+    memset(sockets, 0, sockets_num * sizeof(struct lwip_sock));
+  }
+  return;
+}
+
+//modify from lwip_close
+void lwip_exit(void)
+{
+  int i, is_tcp;
+  struct lwip_sock *sock;
+
+  if (memp_pools[MEMP_SYS_MBOX] == NULL) {
+    return;
+  }
+
+  for (i = 0; i < sockets_num; i++) {
+    sock = &sockets[i];
+    if (!sock->conn)
+      continue;
+#if LWIP_IGMP
+    /* drop all possibly joined IGMP memberships */
+    lwip_socket_drop_registered_memberships(i);
+#endif /* LWIP_IGMP */
+    /*
+     * process is exiting, call netconn_delete to
+     * close tcp connection, and ignore the return value
+     */
+    is_tcp = NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP;
+    netconn_delete(sock->conn);
+    free_socket(sock, is_tcp);
+  }
+
+  free(sockets);
+  sockets = NULL;
+  sockets_num = 0;
+}
+
+#endif /* USE_LIBOS */
+
 #endif /* LWIP_SOCKET */
diff --git a/src/api/sys_arch.c b/src/api/sys_arch.c
new file mode 100644
index 0000000..55561b1
--- /dev/null
+++ b/src/api/sys_arch.c
@@ -0,0 +1,379 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <rte_memzone.h>
+#include <rte_ring.h>
+
+#include "lwip/err.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/opt.h"
+#include "lwip/sys.h"
+#include "lwip/timeouts.h"
+#include "arch/sys_arch.h"
+
+struct sys_mutex {
+    volatile unsigned int m;
+};
+
+struct sys_mutex lstack_mutex;
+
+struct sys_sem lstack_sem;
+
+#define MAX_THREAD_NAME 64
+#define MBOX_NAME_PREFIX  "_mbox_0x"
+#define MAX_MBOX_NAME_LEN (sizeof(MBOX_NAME_PREFIX) + 32) // log(UINT64_MAX) < 32
+
+struct sys_thread {
+    struct sys_thread *next;
+    char name[MAX_THREAD_NAME];
+    lwip_thread_fn fn;
+    void *arg;
+    int stacksize;
+    int prio;
+    pthread_t tid;
+};
+
+
+struct sys_mem_stats {
+    uint32_t tot_len;
+};
+
+static PER_THREAD struct sys_mem_stats hugepage_stats;
+
+static PER_THREAD uint64_t cycles_per_ms __attribute__((aligned(64)));
+static PER_THREAD uint64_t sys_start_ms __attribute__((aligned(64)));
+
+/*
+ * Mailbox
+ * */
+static int mbox_wait_func(void)
+{
+#if LWIP_TIMERS
+    sys_timer_run();
+#endif /* LWIP_TIMER */
+    return eth_dev_poll();
+}
+
+err_t sys_mbox_new(struct sys_mbox **mb, int size)
+{
+    int ret;
+    struct sys_mbox *mbox;
+
+    mbox = (struct sys_mbox *)memp_malloc(MEMP_SYS_MBOX);
+    if (mbox == NULL) {
+        return ERR_MEM;
+    }
+
+    mbox->flags = RING_F_SP_ENQ | RING_F_SC_DEQ;
+
+    ret = snprintf(mbox->name, sizeof(mbox->name), MBOX_NAME_PREFIX"%"PRIXPTR, (uintptr_t)mbox);
+    if (ret < 0) {
+        memp_free(MEMP_SYS_MBOX, mbox);
+        return ERR_VAL;
+    }
+
+    mbox->size = size;
+    mbox->socket_id = rte_socket_id();
+    mbox->ring = rte_ring_create(mbox->name, mbox->size, mbox->socket_id, mbox->flags);
+    if (!mbox->ring) {
+		RTE_LOG(ERR, EAL, "cannot create rte_ring for mbox\n");
+        memp_free(MEMP_SYS_MBOX, mbox);
+        return ERR_MEM;
+    }
+    mbox->wait_fn = mbox_wait_func;
+    *mb = mbox;
+
+    return ERR_OK;
+}
+
+void sys_mbox_free(struct sys_mbox **mb)
+{
+    struct sys_mbox *mbox = *mb;
+    rte_ring_free(mbox->ring);
+    memp_free(MEMP_SYS_MBOX, mbox);
+}
+
+err_t sys_mbox_trypost(struct sys_mbox **mb, void *msg)
+{
+    unsigned int n;
+    struct sys_mbox *mbox = *mb;
+
+    n = rte_ring_sp_enqueue_bulk(mbox->ring, &msg, 1, NULL);
+    if (!n)
+        return ERR_BUF;
+    return ERR_OK;
+}
+
+void sys_mbox_post(struct sys_mbox **mb, void *msg)
+{
+    struct sys_mbox *mbox = *mb;
+
+    /* NOTE:  sys_mbox_post is used on mbox defined in src/api/tcpip.c.
+    * If the ring size of mbox is greater than MEMP_NUM_TCPIP_MSG_API,
+    * enqueue failure will never happen.
+    * */
+    if (!rte_ring_sp_enqueue_bulk(mbox->ring, &msg, 1, NULL)) {
+        LWIP_ASSERT("It is failed to post msg into mbox", 0);
+    }
+}
+
+err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
+{
+    return sys_mbox_trypost(q, msg);
+}
+
+uint32_t sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg)
+{
+    unsigned int n;
+    struct sys_mbox *mbox = *mb;
+
+    n = rte_ring_sc_dequeue_bulk(mbox->ring, msg, 1, NULL);
+    if (!n) {
+        *msg = NULL;
+        return SYS_MBOX_EMPTY;
+    }
+
+    return 0;
+}
+
+uint32_t sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, uint32_t timeout)
+{
+    unsigned int n;
+    uint32_t poll_ts = 0;
+    uint32_t time_needed = 0;
+    struct sys_mbox *mbox = *mb;
+
+    n = rte_ring_sc_dequeue_bulk(mbox->ring, msg, 1, NULL);
+
+    if (timeout > 0)
+        poll_ts = sys_now();
+
+    while (!n) {
+        if (timeout > 0) {
+            time_needed = sys_now() - poll_ts;
+            if (time_needed >= timeout) {
+                return SYS_ARCH_TIMEOUT;
+            }
+        }
+
+        (void)mbox->wait_fn();
+
+        n = rte_ring_sc_dequeue_bulk(mbox->ring, msg, 1, NULL);
+    }
+
+    return time_needed;
+}
+
+int sys_mbox_empty(struct sys_mbox *mb)
+{
+    return rte_ring_count(mb->ring) == 0;
+}
+
+/*
+ * Threads
+ * */
+sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
+{
+    int err;
+    pthread_t tid;
+    struct sys_thread *thread;
+
+    thread = (struct sys_thread *)malloc(sizeof(struct sys_thread));
+    if (thread == NULL) {
+        LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: malloc sys_thread failed\n"));
+        rte_exit(EXIT_FAILURE, "malloc sys_thread failed\n");
+    }
+
+    err = pthread_create(&tid, NULL, (void*(*)(void *))function, arg);
+    if (err > 0) {
+        LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create failed\n"));
+        rte_exit(EXIT_FAILURE, "pthread_create failed\n");
+    }
+
+    err = pthread_setname_np(tid, name);
+    if (err > 0) {
+        LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_setname_np failed\n"));
+    }
+    thread->tid = tid;
+    thread->stacksize = stacksize;
+    thread->prio = prio;
+
+    return thread;
+}
+
+/*
+ * Semaphore
+ * */
+err_t sys_sem_new(struct sys_sem **sem, uint8_t count)
+{
+    *sem = (struct sys_sem *)memp_malloc(MEMP_SYS_SEM);
+    if ((*sem) == NULL) {
+        return ERR_MEM;
+    }
+    (*sem)->c = 0;
+    (*sem)->wait_fn = mbox_wait_func;
+    return ERR_OK;
+}
+
+void sys_sem_signal(struct sys_sem **s)
+{
+    struct sys_sem *sem = NULL;
+    LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL));
+    sem = *s;
+    ++(sem->c);
+}
+
+static uint32_t cond_wait(struct sys_sem *sem, uint32_t timeout)
+{
+    uint32_t used_ms = 0;
+    uint32_t poll_ts;
+
+    if (timeout == 0) {
+        (void)sem->wait_fn();
+        return 0;
+    }
+
+    poll_ts = sys_now();
+
+    while (used_ms < timeout) {
+        if (sem->c > 0)
+            return timeout - used_ms;
+
+        (void)sem->wait_fn();
+        used_ms = sys_now() - poll_ts;
+    }
+
+    return SYS_ARCH_TIMEOUT;
+}
+
+uint32_t sys_arch_sem_wait(struct sys_sem **s, uint32_t timeout)
+{
+    uint32_t time_needed = 0;
+    struct sys_sem *sem = NULL;
+    LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL));
+    sem = *s;
+
+    while (sem->c <= 0) {
+        if (timeout > 0) {
+            time_needed = cond_wait(sem, timeout);
+
+            if (time_needed == SYS_ARCH_TIMEOUT) {
+                return SYS_ARCH_TIMEOUT;
+            }
+        } else {
+            cond_wait(sem, 0);
+        }
+    }
+
+    sem->c--;
+    return time_needed;
+}
+
+void sys_sem_free(struct sys_sem **s)
+{
+    if ((s != NULL) && (*s != SYS_SEM_NULL))
+        memp_free(MEMP_SYS_SEM, *s);
+}
+
+/*
+ * Mutex
+ * */
+err_t sys_mutex_new(struct sys_mutex **mutex)
+{
+    return ERR_OK;
+}
+
+void sys_mutex_lock(struct sys_mutex **mutex)
+{
+}
+
+void sys_mutex_unlock(struct sys_mutex **mutex)
+{
+}
+
+void sys_mutex_free(struct sys_mutex **mutex)
+{
+}
+
+/* Timer from DPDK */
+void sys_calibrate_tsc(void)
+{
+#define MS_PER_SEC  1E3
+    uint64_t freq = rte_get_tsc_hz();
+
+    cycles_per_ms = (freq + MS_PER_SEC - 1) / MS_PER_SEC;
+    sys_start_ms = rte_rdtsc() / cycles_per_ms;
+}
+
+uint32_t sys_now(void)
+{
+    uint64_t cur_ms = rte_rdtsc() / cycles_per_ms;
+    return (uint32_t)(cur_ms - sys_start_ms);
+}
+
+/*
+ * Critical section
+ * */
+sys_prot_t sys_arch_protect(void)
+{
+    return 0;
+}
+
+void sys_arch_unprotect(sys_prot_t pval)
+{
+}
+
+/*
+ * Hugepage memory manager
+ * */
+uint8_t *sys_hugepage_malloc(const char *name, uint32_t size)
+{
+    const struct rte_memzone *mz;
+
+    mz = rte_memzone_reserve(name, size, rte_socket_id(), 0);
+    if (mz == NULL) {
+        rte_exit(EXIT_FAILURE, "failed to reserver memory for mempool[%s]\n", name);
+        return NULL;
+    }
+
+    memset(mz->addr, 0, mz->len);
+    hugepage_stats.tot_len += mz->len;
+
+    return (uint8_t*)mz->addr;
+}
diff --git a/src/api/tcpip.c b/src/api/tcpip.c
index 3aecbd4..05adfe0 100644
--- a/src/api/tcpip.c
+++ b/src/api/tcpip.c
@@ -56,13 +56,13 @@
 #define TCPIP_MSG_VAR_FREE(name)    API_VAR_FREE(MEMP_TCPIP_MSG_API, name)
 
 /* global variables */
-static tcpip_init_done_fn tcpip_init_done;
-static void *tcpip_init_done_arg;
-static sys_mbox_t tcpip_mbox;
+static PER_THREAD tcpip_init_done_fn tcpip_init_done;
+static PER_THREAD void *tcpip_init_done_arg;
+static PER_THREAD sys_mbox_t tcpip_mbox;
 
 #if LWIP_TCPIP_CORE_LOCKING
 /** The global semaphore to lock the stack. */
-sys_mutex_t lock_tcpip_core;
+PER_THREAD sys_mutex_t lock_tcpip_core;
 #endif /* LWIP_TCPIP_CORE_LOCKING */
 
 static void tcpip_thread_handle_msg(struct tcpip_msg *msg);
@@ -123,8 +123,13 @@ again:
  *
  * @param arg unused argument
  */
+#if USE_LIBOS
+__attribute__((unused)) static void
+tcpip_thread(void *arg)
+#else
 static void
 tcpip_thread(void *arg)
+#endif /* USE_LIBOS */
 {
   struct tcpip_msg *msg;
   LWIP_UNUSED_ARG(arg);
@@ -247,6 +252,9 @@ tcpip_inpkt(struct pbuf *p, struct netif *inp, netif_input_fn input_fn)
 #if LWIP_TCPIP_CORE_LOCKING_INPUT
   err_t ret;
   LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_inpkt: PACKET %p/%p\n", (void *)p, (void *)inp));
+#if USE_LIBOS && LWIP_TIMERS
+  sys_timer_run();
+#endif
   LOCK_TCPIP_CORE();
   ret = input_fn(p, inp);
   UNLOCK_TCPIP_CORE();
@@ -326,6 +334,9 @@ tcpip_callback(tcpip_callback_fn function, void *ctx)
   msg->msg.cb.function = function;
   msg->msg.cb.ctx = ctx;
 
+#if USE_LIBOS && LWIP_TIMER
+  sys_timer_run();
+#endif
   sys_mbox_post(&tcpip_mbox, msg);
   return ERR_OK;
 }
@@ -362,6 +373,9 @@ tcpip_try_callback(tcpip_callback_fn function, void *ctx)
   msg->msg.cb.function = function;
   msg->msg.cb.ctx = ctx;
 
+#if USE_LIBOS && LWIP_TIMER
+  sys_timer_run();
+#endif
   if (sys_mbox_trypost(&tcpip_mbox, msg) != ERR_OK) {
     memp_free(MEMP_TCPIP_MSG_API, msg);
     return ERR_MEM;
@@ -443,6 +457,9 @@ tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
 {
 #if LWIP_TCPIP_CORE_LOCKING
   LWIP_UNUSED_ARG(sem);
+#if USE_LIBOS && LWIP_TIMERS
+  sys_timer_run();
+#endif
   LOCK_TCPIP_CORE();
   fn(apimsg);
   UNLOCK_TCPIP_CORE();
@@ -480,6 +497,9 @@ tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call)
 #if LWIP_TCPIP_CORE_LOCKING
   err_t err;
   LOCK_TCPIP_CORE();
+#if USE_LIBOS && LWIP_TIMERS
+  sys_timer_run();
+#endif
   err = fn(call);
   UNLOCK_TCPIP_CORE();
   return err;
@@ -542,6 +562,10 @@ tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
   msg->type = TCPIP_MSG_CALLBACK_STATIC;
   msg->msg.cb.function = function;
   msg->msg.cb.ctx = ctx;
+
+#if USE_LIBOS && LWIP_TIMER
+  sys_timer_run();
+#endif
   return (struct tcpip_callback_msg *)msg;
 }
 
@@ -662,7 +686,9 @@ tcpip_init(tcpip_init_done_fn initfunc, void *arg)
   }
 #endif /* LWIP_TCPIP_CORE_LOCKING */
 
+#if !USE_LIBOS
   sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
+#endif
 }
 
 /**
diff --git a/src/core/dir.mk b/src/core/dir.mk
index e5a055b..ebc01a5 100644
--- a/src/core/dir.mk
+++ b/src/core/dir.mk
@@ -1,6 +1,6 @@
-SRC = inet_chksum.c init.c ip.c mem.c memp.c netif.c pbuf.c \
-	raw.c stats.c tcp.c tcp_in.c tcp_out.c timeouts.c udp.c \
-	ipv4/etharp.c ipv4/icmp.c ipv4/ip4_addr.c ipv4/ip4.c \
-	ipv4/ip4_frag.c
+SRC = def.c inet_chksum.c init.c ip.c mem.c memp.c netif.c pbuf.c \
+	  raw.c tcp.c tcp_in.c tcp_out.c timeouts.c udp.c stats.c\
+	  ipv4/icmp.c ipv4/ip4_addr.c ipv4/ip4_frag.c ipv4/etharp.c \
+	  ipv4/ip4.c
 
 $(eval $(call register_dir, core, $(SRC)))
diff --git a/src/core/init.c b/src/core/init.c
index 0013a89..5b60ed8 100644
--- a/src/core/init.c
+++ b/src/core/init.c
@@ -349,9 +349,7 @@ lwip_init(void)
 
   /* Modules initialization */
   stats_init();
-#if !NO_SYS
-  sys_init();
-#endif /* !NO_SYS */
+
   mem_init();
   memp_init();
   pbuf_init();
diff --git a/src/core/ip.c b/src/core/ip.c
index 18514cf..0d39d2d 100644
--- a/src/core/ip.c
+++ b/src/core/ip.c
@@ -61,7 +61,7 @@
 #include "lwip/ip.h"
 
 /** Global data for both IPv4 and IPv6 */
-struct ip_globals ip_data;
+PER_THREAD struct ip_globals ip_data;
 
 #if LWIP_IPV4 && LWIP_IPV6
 
diff --git a/src/core/ipv4/ip4.c b/src/core/ipv4/ip4.c
index e044bff..ef7771f 100644
--- a/src/core/ipv4/ip4.c
+++ b/src/core/ipv4/ip4.c
@@ -282,7 +282,9 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
 {
   struct netif *netif;
 
+#ifndef LWIP_PERF
   PERF_START;
+#endif
   LWIP_UNUSED_ARG(inp);
 
   if (!ip4_canforward(p)) {
@@ -378,7 +380,9 @@ ip4_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
   MIB2_STATS_INC(mib2.ipforwdatagrams);
   IP_STATS_INC(ip.xmit);
 
+#ifndef LWIP_PERF
   PERF_STOP("ip4_forward");
+#endif
   /* don't fragment if interface has mtu set to 0 [loopif] */
   if (netif->mtu && (p->tot_len > netif->mtu)) {
     if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) {
@@ -472,6 +476,8 @@ ip4_input(struct pbuf *p, struct netif *inp)
 
   LWIP_ASSERT_CORE_LOCKED();
 
+  PERF_START(PERF_LAYER_IP, PERF_POINT_IP_RECV);
+
   IP_STATS_INC(ip.recv);
   MIB2_STATS_INC(mib2.ipinreceives);
 
@@ -734,13 +740,19 @@ ip4_input(struct pbuf *p, struct netif *inp)
       case IP_PROTO_UDPLITE:
 #endif /* LWIP_UDPLITE */
         MIB2_STATS_INC(mib2.ipindelivers);
+        PERF_PAUSE(PERF_LAYER_IP);
         udp_input(p, inp);
+        PERF_RESUME(PERF_LAYER_IP, PERF_POINT_IP_RECV);
         break;
 #endif /* LWIP_UDP */
 #if LWIP_TCP
       case IP_PROTO_TCP:
         MIB2_STATS_INC(mib2.ipindelivers);
+        PERF_PAUSE(PERF_LAYER_IP);
+        PERF_START(PERF_LAYER_TCP, PERF_POINT_TCP_RECV);
         tcp_input(p, inp);
+        PERF_STOP_INCREASE_COUNT("tcp_input", PERF_LAYER_TCP);
+        PERF_RESUME(PERF_LAYER_IP, PERF_POINT_IP_RECV);
         break;
 #endif /* LWIP_TCP */
 #if LWIP_ICMP
@@ -789,6 +801,8 @@ ip4_input(struct pbuf *p, struct netif *inp)
   ip4_addr_set_any(ip4_current_src_addr());
   ip4_addr_set_any(ip4_current_dest_addr());
 
+  PERF_STOP_INCREASE_COUNT("ip4_input", PERF_LAYER_IP);
+
   return ERR_OK;
 }
 
diff --git a/src/core/ipv6/ip6.c b/src/core/ipv6/ip6.c
index 90e90dd..fad4f40 100644
--- a/src/core/ipv6/ip6.c
+++ b/src/core/ipv6/ip6.c
@@ -522,6 +522,8 @@ ip6_input(struct pbuf *p, struct netif *inp)
 
   LWIP_ASSERT_CORE_LOCKED();
 
+  PERF_START(PERF_LAYER_IP, PERF_POINT_IP_RECV);
+
   IP6_STATS_INC(ip6.recv);
 
   /* identify the IP header */
@@ -1069,12 +1071,18 @@ options_done:
 #if LWIP_UDPLITE
     case IP6_NEXTH_UDPLITE:
 #endif /* LWIP_UDPLITE */
+      PERF_PAUSE(PERF_LAYER_IP);
       udp_input(p, inp);
+      PERF_RESUME(PERF_LAYER_IP, PERF_POINT_IP_RECV);
       break;
 #endif /* LWIP_UDP */
 #if LWIP_TCP
     case IP6_NEXTH_TCP:
+      PERF_PAUSE(PERF_LAYER_IP);
+      PERF_START(PERF_LAYER_TCP, PERF_POINT_TCP_RECV);
       tcp_input(p, inp);
+      PERF_STOP_INCREASE_COUNT("tcp_input", PERF_LAYER_TCP);
+      PERF_RESUME(PERF_LAYER_IP, PERF_POINT_IP_RECV);
       break;
 #endif /* LWIP_TCP */
 #if LWIP_ICMP6
@@ -1115,6 +1123,8 @@ ip6_input_cleanup:
   ip6_addr_set_zero(ip6_current_src_addr());
   ip6_addr_set_zero(ip6_current_dest_addr());
 
+  PERF_STOP_INCREASE_COUNT("ip6_input", PERF_LAYER_IP);
+
   return ERR_OK;
 }
 
diff --git a/src/core/mem.c b/src/core/mem.c
index 8566edc..3522825 100644
--- a/src/core/mem.c
+++ b/src/core/mem.c
@@ -381,9 +381,9 @@ LWIP_DECLARE_MEMORY_ALIGNED(ram_heap, MEM_SIZE_ALIGNED + (2U * SIZEOF_STRUCT_MEM
 #endif /* LWIP_RAM_HEAP_POINTER */
 
 /** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */
-static u8_t *ram;
+static PER_THREAD u8_t *ram;
 /** the last entry, always unused! */
-static struct mem *ram_end;
+static PER_THREAD struct mem *ram_end;
 
 /** concurrent access protection */
 #if !NO_SYS
@@ -418,7 +418,7 @@ static volatile u8_t mem_free_count;
 #endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
 
 /** pointer to the lowest free block, this is used for faster search */
-static struct mem * LWIP_MEM_LFREE_VOLATILE lfree;
+static PER_THREAD struct mem * LWIP_MEM_LFREE_VOLATILE lfree;
 
 #if MEM_SANITY_CHECK
 static void mem_sanity(void);
diff --git a/src/core/memp.c b/src/core/memp.c
index 352ce5a..454ba32 100644
--- a/src/core/memp.c
+++ b/src/core/memp.c
@@ -78,10 +78,14 @@
 #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc)
 #include "lwip/priv/memp_std.h"
 
+#if USE_LIBOS
+PER_THREAD struct memp_desc* memp_pools[MEMP_MAX] = {NULL};
+#else
 const struct memp_desc *const memp_pools[MEMP_MAX] = {
 #define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
 #include "lwip/priv/memp_std.h"
 };
+#endif /* USE_LIBOS */
 
 #ifdef LWIP_HOOK_FILENAME
 #include LWIP_HOOK_FILENAME
diff --git a/src/core/netif.c b/src/core/netif.c
index d3a0677..ded3561 100644
--- a/src/core/netif.c
+++ b/src/core/netif.c
@@ -110,12 +110,12 @@ static netif_ext_callback_t *ext_callback;
 #endif
 
 #if !LWIP_SINGLE_NETIF
-struct netif *netif_list;
+PER_THREAD struct netif *netif_list;
 #endif /* !LWIP_SINGLE_NETIF */
-struct netif *netif_default;
+PER_THREAD struct netif *netif_default;
 
 #define netif_index_to_num(index)   ((index) - 1)
-static u8_t netif_num;
+static PER_THREAD u8_t netif_num;
 
 #if LWIP_NUM_NETIF_CLIENT_DATA > 0
 static u8_t netif_client_id;
@@ -141,7 +141,7 @@ static err_t netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const i
 #endif
 
 
-static struct netif loop_netif;
+static PER_THREAD struct netif loop_netif;
 
 #if LWIP_TESTMODE
 struct netif* netif_get_loopif(void)
diff --git a/src/core/pbuf.c b/src/core/pbuf.c
index 1fb64d4..201ddf3 100644
--- a/src/core/pbuf.c
+++ b/src/core/pbuf.c
@@ -739,7 +739,9 @@ pbuf_free(struct pbuf *p)
   }
   LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free(%p)\n", (void *)p));
 
+#ifndef LWIP_PERF
   PERF_START;
+#endif
 
   count = 0;
   /* de-allocate all consecutive pbufs from the head of the chain that
@@ -796,7 +798,9 @@ pbuf_free(struct pbuf *p)
       p = NULL;
     }
   }
+#ifndef LWIP_PERF
   PERF_STOP("pbuf_free");
+#endif
   /* return number of de-allocated pbufs */
   return count;
 }
diff --git a/src/core/stats.c b/src/core/stats.c
index 95445ec..ce6a929 100644
--- a/src/core/stats.c
+++ b/src/core/stats.c
@@ -47,7 +47,7 @@
 
 #include <string.h>
 
-struct stats_ lwip_stats;
+PER_THREAD struct stats_ lwip_stats;
 
 void
 stats_init(void)
@@ -59,6 +59,17 @@ stats_init(void)
 #endif /* LWIP_DEBUG */
 }
 
+int get_mib2_stats(char *buf)
+{
+  int len = 0;
+#if MIB2_STATS
+  len = (long)&((struct stats_mib2 *)0)->udpindatagrams;
+  /* we just need the ip&tcp, others not needed. */
+  memcpy(buf, &lwip_stats.mib2, len);
+#endif
+  return len;
+}
+
 #if LWIP_STATS_DISPLAY
 void
 stats_display_proto(struct stats_proto *proto, const char *name)
diff --git a/src/core/tcp.c b/src/core/tcp.c
index ea95ffe..24d035c 100644
--- a/src/core/tcp.c
+++ b/src/core/tcp.c
@@ -113,6 +113,7 @@
 #include "lwip/nd6.h"
 
 #include <string.h>
+#include <pthread.h>
 
 #ifdef LWIP_HOOK_FILENAME
 #include LWIP_HOOK_FILENAME
@@ -157,36 +158,50 @@ static const char *const tcp_state_str[] = {
 
 /* last local TCP port */
 static u16_t tcp_port = TCP_LOCAL_PORT_RANGE_START;
+static pthread_mutex_t g_tcp_port_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 /* Incremented every coarse grained timer shot (typically every 500 ms). */
-u32_t tcp_ticks;
-static const u8_t tcp_backoff[13] =
+PER_THREAD u32_t tcp_ticks;
+static PER_THREAD const u8_t tcp_backoff[13] =
 { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
 /* Times per slowtmr hits */
-static const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
+static PER_THREAD const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };
 
 /* The TCP PCB lists. */
 
 /** List of all TCP PCBs bound but not yet (connected || listening) */
-struct tcp_pcb *tcp_bound_pcbs;
+PER_THREAD struct tcp_pcb *tcp_bound_pcbs;
 /** List of all TCP PCBs in LISTEN state */
-union tcp_listen_pcbs_t tcp_listen_pcbs;
+PER_THREAD union tcp_listen_pcbs_t tcp_listen_pcbs;
 /** List of all TCP PCBs that are in a state in which
  * they accept or send data. */
-struct tcp_pcb *tcp_active_pcbs;
+PER_THREAD struct tcp_pcb *tcp_active_pcbs;
 /** List of all TCP PCBs in TIME-WAIT state */
-struct tcp_pcb *tcp_tw_pcbs;
+PER_THREAD struct tcp_pcb *tcp_tw_pcbs;
 
 /** An array with all (non-temporary) PCB lists, mainly used for smaller code size */
-struct tcp_pcb **const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs,
-         &tcp_active_pcbs, &tcp_tw_pcbs
-};
+PER_THREAD struct tcp_pcb ** tcp_pcb_lists[NUM_TCP_PCB_LISTS] = {NULL, NULL, NULL, NULL};
+
+#if TCP_PCB_HASH
+#define INIT_TCP_HTABLE(ht_ptr) \
+  do { \
+    int _i; \
+    (ht_ptr)->size = TCP_HTABLE_SIZE; \
+    for (_i = 0; _i < TCP_HTABLE_SIZE; ++_i) { \
+      if (sys_mutex_new(&(ht_ptr)->array[_i].mutex) != ERR_OK) \
+        LWIP_ASSERT("failed to create ht->array[].mutex", 0);\
+      INIT_HLIST_HEAD(&(ht_ptr)->array[_i].chain); \
+    }\
+  } while (0)
+
+PER_THREAD struct tcp_hash_table  *tcp_active_htable; /* key: lport/fport/lip/fip */
+#endif
 
-u8_t tcp_active_pcbs_changed;
+PER_THREAD u8_t tcp_active_pcbs_changed;
 
 /** Timer counter to handle calling slow-timer from tcp_tmr() */
-static u8_t tcp_timer;
-static u8_t tcp_timer_ctr;
+static PER_THREAD u8_t tcp_timer;
+static PER_THREAD u8_t tcp_timer_ctr;
 static u16_t tcp_new_port(void);
 
 static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb);
@@ -200,9 +215,20 @@ static void tcp_ext_arg_invoke_callbacks_destroyed(struct tcp_pcb_ext_args *ext_
 void
 tcp_init(void)
 {
+  tcp_pcb_lists[0] = &tcp_listen_pcbs.pcbs;
+  tcp_pcb_lists[1] = &tcp_bound_pcbs;
+  tcp_pcb_lists[2] = &tcp_active_pcbs;
+  tcp_pcb_lists[3] = &tcp_tw_pcbs;
+
 #ifdef LWIP_RAND
   tcp_port = TCP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());
 #endif /* LWIP_RAND */
+
+#if TCP_PCB_HASH
+  tcp_active_htable = (struct tcp_hash_table*)mem_malloc(sizeof(struct tcp_hash_table));
+  LWIP_ASSERT("malloc tcp_active_htable mem failed.", tcp_active_htable != NULL);
+  INIT_TCP_HTABLE(tcp_active_htable);
+#endif
 }
 
 /** Free a tcp pcb */
@@ -361,6 +387,9 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
               pcb->local_port, pcb->remote_port);
 
       tcp_pcb_purge(pcb);
+#if TCP_PCB_HASH
+      TCP_RMV_ACTIVE_HASH(pcb);
+#endif
       TCP_RMV_ACTIVE(pcb);
       /* Deallocate the pcb since we already sent a RST for it */
       if (tcp_input_pcb == pcb) {
@@ -395,6 +424,9 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
       tcp_free_listen(pcb);
       break;
     case SYN_SENT:
+#if TCP_PCB_HASH
+      TCP_PCB_REMOVE_ACTIVE_HASH(pcb);
+#endif
       TCP_PCB_REMOVE_ACTIVE(pcb);
       tcp_free(pcb);
       MIB2_STATS_INC(mib2.tcpattemptfails);
@@ -494,6 +526,7 @@ tcp_close(struct tcp_pcb *pcb)
     /* Set a flag not to receive any more data... */
     tcp_set_flags(pcb, TF_RXCLOSED);
   }
+
   /* ... and close */
   return tcp_close_shutdown(pcb, 1);
 }
@@ -599,6 +632,9 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
     } else {
       send_rst = reset;
       local_port = pcb->local_port;
+#if TCP_PCB_HASH
+      TCP_PCB_REMOVE_ACTIVE_HASH(pcb);
+#endif
       TCP_PCB_REMOVE_ACTIVE(pcb);
     }
     if (pcb->unacked != NULL) {
@@ -880,6 +916,11 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
     }
   }
 #endif /* SO_REUSE */
+
+#if USE_LIBOS
+  vdev_reg_done(REG_RING_TCP_LISTEN, pcb);
+#endif
+
   lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
   if (lpcb == NULL) {
     res = ERR_MEM;
@@ -1018,6 +1059,7 @@ tcp_new_port(void)
   u16_t n = 0;
   struct tcp_pcb *pcb;
 
+  pthread_mutex_lock(&g_tcp_port_mutex);
 again:
   tcp_port++;
   if (tcp_port == TCP_LOCAL_PORT_RANGE_END) {
@@ -1035,6 +1077,8 @@ again:
       }
     }
   }
+  pthread_mutex_unlock(&g_tcp_port_mutex);
+
   return tcp_port;
 }
 
@@ -1145,6 +1189,10 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
 #endif /* SO_REUSE */
   }
 
+#if USE_LIBOS
+  vdev_reg_done(REG_RING_TCP_CONNECT, pcb);
+#endif
+
   iss = tcp_next_iss(pcb);
   pcb->rcv_nxt = 0;
   pcb->snd_nxt = iss;
@@ -1177,6 +1225,9 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
     if (old_local_port != 0) {
       TCP_RMV(&tcp_bound_pcbs, pcb);
     }
+#if TCP_PCB_HASH
+    TCP_REG_ACTIVE_HASH(pcb);
+#endif
     TCP_REG_ACTIVE(pcb);
     MIB2_STATS_INC(mib2.tcpactiveopens);
 
@@ -1392,11 +1443,26 @@ tcp_slowtmr_start:
       if (prev != NULL) {
         LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs);
         prev->next = pcb->next;
+#if USE_LIBOS
+        if (pcb->next)
+          pcb->next->prev = prev;
+        //dont set next NULL, it will be used below
+        pcb->prev = NULL;
+#endif
       } else {
         /* This PCB was the first. */
         LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb);
         tcp_active_pcbs = pcb->next;
+#if USE_LIBOS
+        if (pcb->next)
+          pcb->next->prev = NULL;
+        //dont set next NULL, it will be used below
+        pcb->prev = NULL;
+#endif
       }
+#if TCP_PCB_HASH
+      TCP_RMV_ACTIVE_HASH(pcb);
+#endif
 
       if (pcb_reset) {
         tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
@@ -1407,6 +1473,9 @@ tcp_slowtmr_start:
       last_state = pcb->state;
       pcb2 = pcb;
       pcb = pcb->next;
+#if USE_LIBOS
+      pcb2->next = NULL;
+#endif
       tcp_free(pcb2);
 
       tcp_active_pcbs_changed = 0;
@@ -1458,13 +1527,28 @@ tcp_slowtmr_start:
       if (prev != NULL) {
         LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_tw_pcbs", pcb != tcp_tw_pcbs);
         prev->next = pcb->next;
+#if USE_LIBOS
+        if (pcb->next)
+          pcb->next->prev = prev;
+        //dont set next NULL, it will be used below
+        pcb->prev = NULL;
+#endif
       } else {
         /* This PCB was the first. */
         LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb);
         tcp_tw_pcbs = pcb->next;
+#if USE_LIBOS
+        if (pcb->next)
+          pcb->next->prev = NULL;
+        //dont set next NULL, it will be used below
+        pcb->prev = NULL;
+#endif
       }
       pcb2 = pcb;
       pcb = pcb->next;
+#if USE_LIBOS
+      pcb2->next = NULL;
+#endif
       tcp_free(pcb2);
     } else {
       prev = pcb;
@@ -2216,6 +2300,14 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
   LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
 }
 
+#if TCP_PCB_HASH
+void
+tcp_pcb_remove_hash(struct tcp_hash_table *htb, struct tcp_pcb *pcb)
+{
+  TCP_RMV_HASH(htb, pcb);
+}
+#endif /* TCP_PCB_HASH */
+
 /**
  * Calculates a new initial sequence number for new connections.
  *
@@ -2390,6 +2482,84 @@ tcp_tcp_get_tcp_addrinfo(struct tcp_pcb *pcb, int local, ip_addr_t *addr, u16_t
   return ERR_VAL;
 }
 
+uint32_t tcp_get_conn_num(void)
+{
+    struct tcp_pcb *pcb = NULL;
+    struct tcp_pcb_listen *pcbl = NULL;
+    uint32_t conn_num = 0;
+
+    for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+        conn_num++;
+    }
+
+    for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) {
+        conn_num++;
+    }
+
+    for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+        conn_num++;
+    }
+
+    return conn_num;
+}
+
+void tcp_get_conn(char *buf, int32_t len, uint32_t *conn_num)
+{
+  int tmp_len = 0;
+  char *tmp_buf = buf;
+  struct tcp_pcb_dp tdp;
+  struct tcp_pcb *pcb = NULL;
+  struct tcp_pcb_listen *pcbl = NULL;
+
+#define COPY_TDP(b, l) \
+  do { \
+    if (l + sizeof(tdp) <= len) { \
+	  memcpy(b, &tdp, sizeof(tdp)); \
+	  b += sizeof(tdp); \
+	  l += sizeof(tdp); \
+      *conn_num += 1; \
+    } else \
+      return; \
+  } while(0);
+
+  *conn_num = 0;
+
+  for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+    tdp.state = ACTIVE_LIST;
+    tdp.lip = pcb->local_ip.addr;
+    tdp.rip = pcb->remote_ip.addr;
+    tdp.l_port = pcb->local_port;
+    tdp.r_port = pcb->remote_port;
+    tdp.s_next = pcb->snd_queuelen;
+    /* lwip not cache rcv buf. Set it to 0. */
+    tdp.r_next = 0;
+    tdp.tcp_sub_state = pcb->state;
+    COPY_TDP(tmp_buf, tmp_len);
+  }
+
+  for (pcbl = tcp_listen_pcbs.listen_pcbs; pcbl != NULL; pcbl = pcbl->next) {
+    tdp.state = LISTEN_LIST;
+    tdp.lip = pcbl->local_ip.addr;
+    tdp.rip = pcbl->remote_ip.addr;
+    tdp.l_port = pcbl->local_port;
+    tdp.tcp_sub_state = pcbl->state;
+    COPY_TDP(tmp_buf, tmp_len);
+  }
+
+  for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
+    tdp.state = TIME_WAIT_LIST;
+    tdp.lip = pcb->local_ip.addr;
+    tdp.rip = pcb->remote_ip.addr;
+    tdp.l_port = pcb->local_port;
+    tdp.r_port = pcb->remote_port;
+    tdp.s_next = pcb->snd_queuelen;
+    /* lwip not cache rcv buf. Set it to 0. */
+    tdp.r_next = 0;
+    tdp.tcp_sub_state = pcb->state;
+    COPY_TDP(tmp_buf, tmp_len);
+  }
+}
+
 #if TCP_QUEUE_OOSEQ
 /* Free all ooseq pbufs (and possibly reset SACK state) */
 void
diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c
index c7a1f7b..48ee11d 100644
--- a/src/core/tcp_in.c
+++ b/src/core/tcp_in.c
@@ -71,21 +71,22 @@
 /* These variables are global to all functions involved in the input
    processing of TCP segments. They are set by the tcp_input()
    function. */
-static struct tcp_seg inseg;
-static struct tcp_hdr *tcphdr;
-static u16_t tcphdr_optlen;
-static u16_t tcphdr_opt1len;
-static u8_t *tcphdr_opt2;
-static u16_t tcp_optidx;
-static u32_t seqno, ackno;
-static tcpwnd_size_t recv_acked;
-static u16_t tcplen;
-static u8_t flags;
-
-static u8_t recv_flags;
-static struct pbuf *recv_data;
-
-struct tcp_pcb *tcp_input_pcb;
+static PER_THREAD struct tcp_seg inseg;
+static PER_THREAD struct tcp_hdr *tcphdr;
+static PER_THREAD u16_t tcphdr_optlen;
+static PER_THREAD u16_t tcphdr_opt1len;
+static PER_THREAD u8_t *tcphdr_opt2;
+static PER_THREAD u16_t tcp_optidx;
+static PER_THREAD u32_t seqno;
+static PER_THREAD u32_t ackno;
+static PER_THREAD tcpwnd_size_t recv_acked;
+static PER_THREAD u16_t tcplen;
+static PER_THREAD u8_t flags;
+
+static PER_THREAD u8_t recv_flags;
+static PER_THREAD struct pbuf *recv_data;
+
+PER_THREAD struct tcp_pcb *tcp_input_pcb;
 
 /* Forward declarations. */
 static err_t tcp_process(struct tcp_pcb *pcb);
@@ -126,11 +127,20 @@ tcp_input(struct pbuf *p, struct netif *inp)
   u8_t hdrlen_bytes;
   err_t err;
 
+#if TCP_PCB_HASH
+  u32_t idx;
+  struct hlist_head *head;
+  struct hlist_node *node;
+  pcb = NULL;
+#endif
+
   LWIP_UNUSED_ARG(inp);
   LWIP_ASSERT_CORE_LOCKED();
   LWIP_ASSERT("tcp_input: invalid pbuf", p != NULL);
 
+#ifndef LWIP_PERF
   PERF_START;
+#endif
 
   TCP_STATS_INC(tcp.recv);
   MIB2_STATS_INC(mib2.tcpinsegs);
@@ -247,7 +257,15 @@ tcp_input(struct pbuf *p, struct netif *inp)
      for an active connection. */
   prev = NULL;
 
+#if TCP_PCB_HASH
+  idx = TUPLE4_HASH_FN( ip_current_dest_addr()->addr, tcphdr->dest,
+                      ip_current_src_addr()->addr, tcphdr->src) &
+         (tcp_active_htable->size - 1);
+  head = &tcp_active_htable->array[idx].chain;
+  tcppcb_hlist_for_each(pcb, node, head) {
+#else
   for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
+#endif
     LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
     LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
     LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
@@ -263,6 +281,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
         pcb->local_port == tcphdr->dest &&
         ip_addr_eq(&pcb->remote_ip, ip_current_src_addr()) &&
         ip_addr_eq(&pcb->local_ip, ip_current_dest_addr())) {
+#if !TCP_PCB_HASH
       /* Move this PCB to the front of the list so that subsequent
          lookups will be faster (we exploit locality in TCP segment
          arrivals). */
@@ -275,9 +294,14 @@ tcp_input(struct pbuf *p, struct netif *inp)
         TCP_STATS_INC(tcp.cachehit);
       }
       LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
+#endif
       break;
     }
+#if TCP_PCB_HASH
+    pcb = NULL;
+#else
     prev = pcb;
+#endif
   }
 
   if (pcb == NULL) {
@@ -363,8 +387,15 @@ tcp_input(struct pbuf *p, struct netif *inp)
          arrivals). */
       if (prev != NULL) {
         ((struct tcp_pcb_listen *)prev)->next = lpcb->next;
+#if USE_LIBOS
+        if (lpcb->next)
+          lpcb->next->prev = (struct tcp_pcb_listen *)prev;
+#endif
         /* our successor is the remainder of the listening list */
         lpcb->next = tcp_listen_pcbs.listen_pcbs;
+#if USE_LIBOS
+        lpcb->prev = NULL;
+#endif
         /* put this listening pcb at the head of the listening list */
         tcp_listen_pcbs.listen_pcbs = lpcb;
       } else {
@@ -445,6 +476,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
            application that the connection is dead before we
            deallocate the PCB. */
         TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST);
+#if TCP_PCB_HASH
+        tcp_pcb_remove_hash(tcp_active_htable, pcb);
+#endif
         tcp_pcb_remove(&tcp_active_pcbs, pcb);
         tcp_free(pcb);
       } else {
@@ -550,7 +584,19 @@ tcp_input(struct pbuf *p, struct netif *inp)
           goto aborted;
         }
         /* Try to send something out. */
+#if LWIP_RECORD_PERF
+        if (check_layer_point(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_ACK_RECV)) {
+          PERF_PAUSE(PERF_LAYER_TCP);
+          PERF_START(PERF_LAYER_TCP, PERF_POINT_TCP_ACK_SEND);
+        }
+#endif
         tcp_output(pcb);
+#if LWIP_RECORD_PERF
+        if (check_layer_point(PERF_LAYER_TCP, PERF_POINT_TCP_ACK_SEND)) {
+          PERF_STOP_INCREASE_COUNT("tcp_in", PERF_LAYER_TCP);
+          PERF_RESUME(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_ACK_RECV);
+        }
+#endif
 #if TCP_INPUT_DEBUG
 #if TCP_DEBUG
         tcp_debug_print_state(pcb->state);
@@ -583,7 +629,9 @@ aborted:
   }
 
   LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
+#ifndef LWIP_PERF
   PERF_STOP("tcp_input");
+#endif
   return;
 dropped:
   TCP_STATS_INC(tcp.drop);
@@ -610,6 +658,9 @@ tcp_input_delayed_close(struct tcp_pcb *pcb)
           ensure the application doesn't continue using the PCB. */
       TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
     }
+#if TCP_PCB_HASH
+    tcp_pcb_remove_hash(tcp_active_htable, pcb);
+#endif
     tcp_pcb_remove(&tcp_active_pcbs, pcb);
     tcp_free(pcb);
     return 1;
@@ -649,6 +700,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
     tcp_rst_netif(ip_data.current_input_netif, ackno, seqno + tcplen, ip_current_dest_addr(),
             ip_current_src_addr(), tcphdr->dest, tcphdr->src);
   } else if (flags & TCP_SYN) {
+    PERF_UPDATE_POINT(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_RECV);
     LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
 #if TCP_LISTEN_BACKLOG
     if (pcb->accepts_pending >= pcb->backlog) {
@@ -698,6 +750,9 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
     npcb->netif_idx = pcb->netif_idx;
     /* Register the new PCB so that we can begin receiving segments
        for it. */
+#if TCP_PCB_HASH
+    TCP_REG_ACTIVE_HASH(npcb);
+#endif
     TCP_REG_ACTIVE(npcb);
 
     /* Parse any options in the SYN. */
@@ -718,13 +773,18 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
     }
 #endif
 
+    PERF_PAUSE(PERF_LAYER_TCP);
+    PERF_START(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_ACK_SEND);
     /* Send a SYN|ACK together with the MSS option. */
     rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
     if (rc != ERR_OK) {
       tcp_abandon(npcb, 0);
+      PERF_RESUME(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_RECV);
       return;
     }
     tcp_output(npcb);
+    PERF_STOP_INCREASE_COUNT("tcp_output", PERF_LAYER_TCP);
+    PERF_RESUME(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_RECV);
   }
   return;
 }
@@ -868,6 +928,7 @@ tcp_process(struct tcp_pcb *pcb)
       /* received SYN ACK with expected sequence number? */
       if ((flags & TCP_ACK) && (flags & TCP_SYN)
           && (ackno == pcb->lastack + 1)) {
+        PERF_UPDATE_POINT(PERF_LAYER_TCP, PERF_POINT_TCP_SYN_ACK_RECV);
         pcb->rcv_nxt = seqno + 1;
         pcb->rcv_ann_right_edge = pcb->rcv_nxt;
         pcb->lastack = ackno;
@@ -940,6 +1001,7 @@ tcp_process(struct tcp_pcb *pcb)
         /* expected ACK number? */
         if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) {
           pcb->state = ESTABLISHED;
+          PERF_UPDATE_POINT(PERF_LAYER_TCP, PERF_POINT_TCP_ACK_RECV);
           LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
 #if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
           if (pcb->listener == NULL) {
@@ -1007,6 +1069,9 @@ tcp_process(struct tcp_pcb *pcb)
                       ("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
           tcp_ack_now(pcb);
           tcp_pcb_purge(pcb);
+#if TCP_PCB_HASH
+          TCP_RMV_ACTIVE_HASH(pcb);
+#endif
           TCP_RMV_ACTIVE(pcb);
           pcb->state = TIME_WAIT;
           TCP_REG(&tcp_tw_pcbs, pcb);
@@ -1025,6 +1090,9 @@ tcp_process(struct tcp_pcb *pcb)
         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
         tcp_ack_now(pcb);
         tcp_pcb_purge(pcb);
+#if TCP_PCB_HASH
+        TCP_RMV_ACTIVE_HASH(pcb);
+#endif
         TCP_RMV_ACTIVE(pcb);
         pcb->state = TIME_WAIT;
         TCP_REG(&tcp_tw_pcbs, pcb);
@@ -1035,6 +1103,9 @@ tcp_process(struct tcp_pcb *pcb)
       if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
         LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
         tcp_pcb_purge(pcb);
+#if TCP_PCB_HASH
+        TCP_RMV_ACTIVE_HASH(pcb);
+#endif
         TCP_RMV_ACTIVE(pcb);
         pcb->state = TIME_WAIT;
         TCP_REG(&tcp_tw_pcbs, pcb);
diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c
index 64579ee..74b22b0 100644
--- a/src/core/tcp_out.c
+++ b/src/core/tcp_out.c
@@ -274,7 +274,7 @@ tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
   return p;
 }
 #else /* TCP_OVERSIZE */
-#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_RAM)
+#define tcp_pbuf_prealloc(layer, length, mx, os, pcb, api, fst) pbuf_alloc((layer), (length), PBUF_POOL)
 #endif /* TCP_OVERSIZE */
 
 #if TCP_CHECKSUM_ON_COPY
@@ -643,7 +643,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
       ((struct pbuf_rom *)p2)->payload = (const u8_t *)arg + pos;
 
       /* Second, allocate a pbuf for the headers. */
-      if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
+      if ((p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_POOL)) == NULL) {
         /* If allocation fails, we have to deallocate the data pbuf as
          * well. */
         pbuf_free(p2);
@@ -1461,6 +1461,11 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
   err_t err;
   u16_t len;
   u32_t *opts;
+
+#if LWIP_RECORD_PERF
+  int tmpPoint;
+#endif
+
 #if TCP_CHECKSUM_ON_COPY
   int seg_chksum_was_swapped = 0;
 #endif
@@ -1607,6 +1612,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
 #endif /* CHECKSUM_GEN_TCP */
   TCP_STATS_INC(tcp.xmit);
 
+  PERF_PAUSE_RETURN_POINT(PERF_LAYER_TCP, tmpPoint);
+  PERF_START(PERF_LAYER_IP, PERF_POINT_IP_SEND);
+
   NETIF_SET_HINTS(netif, &(pcb->netif_hints));
   err = ip_output_if(seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
                      pcb->tos, IP_PROTO_TCP, netif);
@@ -1621,6 +1629,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
   }
 #endif
 
+  PERF_STOP_INCREASE_COUNT("ip_out", PERF_LAYER_IP);
+  PERF_RESUME(PERF_LAYER_TCP, tmpPoint);
+
   return err;
 }
 
@@ -2090,6 +2101,10 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
   u8_t optlen, optflags = 0;
   u8_t num_sacks = 0;
 
+#if LWIP_RECORD_PERF
+  int tmpPoint;
+#endif
+
   LWIP_ASSERT("tcp_send_empty_ack: invalid pcb", pcb != NULL);
 
 #if LWIP_TCP_TIMESTAMPS
@@ -2106,6 +2121,9 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
   }
 #endif
 
+  PERF_PAUSE_RETURN_POINT(PERF_LAYER_TCP, tmpPoint);
+  PERF_START(PERF_LAYER_IP, PERF_POINT_IP_SEND);
+
   p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt));
   if (p == NULL) {
     /* let tcp_fasttmr retry sending this ACK */
@@ -2130,6 +2148,9 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
     tcp_clear_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
   }
 
+  PERF_STOP_INCREASE_COUNT("ip_out", PERF_LAYER_IP);
+  PERF_RESUME(PERF_LAYER_TCP, tmpPoint);
+
   return err;
 }
 
diff --git a/src/core/timeouts.c b/src/core/timeouts.c
index 91657eb..477369f 100644
--- a/src/core/timeouts.c
+++ b/src/core/timeouts.c
@@ -119,9 +119,9 @@ const int lwip_num_cyclic_timers = LWIP_ARRAYSIZE(lwip_cyclic_timers);
 #if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM
 
 /** The one and only timeout list */
-static struct sys_timeo *next_timeout;
+static PER_THREAD struct sys_timeo *next_timeout;
 
-static u32_t current_timeout_due_time;
+static PER_THREAD u32_t current_timeout_due_time;
 
 #if LWIP_TESTMODE
 struct sys_timeo**
@@ -133,7 +133,7 @@ sys_timeouts_get_next_timeout(void)
 
 #if LWIP_TCP
 /** global variable that shows if the tcp timer is currently scheduled or not */
-static int tcpip_tcp_timer_active;
+static PER_THREAD int tcpip_tcp_timer_active;
 
 /**
  * Timer callback function that calls tcp_tmr() and reschedules itself.
@@ -442,6 +442,18 @@ sys_timeouts_sleeptime(void)
   }
 }
 
+#if USE_LIBOS
+void sys_timer_run(void)
+{
+  u32_t sleeptime;
+
+  sleeptime = sys_timeouts_sleeptime();
+  if (sleeptime == 0) {
+    sys_check_timeouts();
+  }
+}
+#endif /* USE_LIBOS */
+
 #else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
 /* Satisfy the TCP code which calls this function */
 void
diff --git a/src/core/udp.c b/src/core/udp.c
index 23c2be2..24fc174 100644
--- a/src/core/udp.c
+++ b/src/core/udp.c
@@ -207,7 +207,11 @@ udp_input(struct pbuf *p, struct netif *inp)
   LWIP_ASSERT("udp_input: invalid pbuf", p != NULL);
   LWIP_ASSERT("udp_input: invalid netif", inp != NULL);
 
+#if LWIP_RECORD_PERF
+  PERF_START(PERF_LAYER_UDP, PERF_POINT_UDP);
+#else
   PERF_START;
+#endif
 
   UDP_STATS_INC(udp.recv);
 
@@ -428,7 +432,12 @@ udp_input(struct pbuf *p, struct netif *inp)
     pbuf_free(p);
   }
 end:
+#if LWIP_RECORD_PERF
+  PERF_STOP_INCREASE_COUNT("udp_input", PERF_LAYER_UDP);
+#else
   PERF_STOP("udp_input");
+#endif
+
   return;
 #if CHECKSUM_CHECK_UDP
 chkerr:
@@ -438,7 +447,13 @@ chkerr:
   UDP_STATS_INC(udp.drop);
   MIB2_STATS_INC(mib2.udpinerrors);
   pbuf_free(p);
+
+#if LWIP_RECORD_PERF
+  PERF_STOP_INCREASE_COUNT("udp_input", PERF_LAYER_UDP);
+#else
   PERF_STOP("udp_input");
+#endif
+
 #endif /* CHECKSUM_CHECK_UDP */
 }
 
diff --git a/src/include/arch/cc.h b/src/include/arch/cc.h
index 52b76f9..33c24b4 100644
--- a/src/include/arch/cc.h
+++ b/src/include/arch/cc.h
@@ -1,7 +1,81 @@
-#ifndef LWIP_CC_H
-#define LWIP_CC_H
+/*
+ * 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: Huawei Technologies
+ *
+ */
 
+#ifndef LWIP_ARCH_CC_H
+#define LWIP_ARCH_CC_H
 
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
 
-#endif /* LWIP_CC_H */
+#include "lwiplog.h"
 
+#define LWIP_NOASSERT
+
+#define LWIP_ERRNO_STDINCLUDE 1
+#define MEMP_MEMORY_BASE_PLACEHOLDER 0
+#define MEMZONE_NAMESIZE 32
+
+#define LWIP_RAND()     ((uint32_t)rand())
+
+extern uint8_t *sys_hugepage_malloc(const char *name, uint32_t size);
+
+#define LWIP_DECLARE_MEMP_BASE_ALIGNED(name, __size)\
+PER_THREAD uint8_t *memp_memory_##name##_base; \
+void alloc_memp_##name##_base(void) \
+{ \
+    memp_ ## name.desc = memp_desc_ ## name; \
+    memp_ ## name.stats = &memp_stat ## name; \
+    memp_ ## name.size = memp_size ## name; \
+    memp_ ## name.num = memp_num ## name; \
+    memp_ ## name.tab = &memp_tab_ ## name; \
+    memp_pools[MEMP_##name] = &memp_ ## name; \
+    \
+    char mpname[MEMZONE_NAMESIZE] = {0}; \
+    snprintf(mpname, MEMZONE_NAMESIZE, "%ld_%s", gettid(), #name); \
+    memp_memory_##name##_base = \
+        sys_hugepage_malloc(mpname, LWIP_MEM_ALIGN_BUFFER(__size)); \
+    memp_pools[MEMP_##name]->base = memp_memory_##name##_base; \
+}
+
+#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) \
+PER_THREAD uint8_t *variable_name; \
+void alloc_memory_##variable_name(void) \
+{ \
+    char mpname[MEMZONE_NAMESIZE] = {0}; \
+    snprintf(mpname, MEMZONE_NAMESIZE, "%ld_%s", gettid(), #variable_name); \
+    (variable_name) = \
+        sys_hugepage_malloc(mpname, LWIP_MEM_ALIGN_BUFFER(size)); \
+}
+
+#endif /* LWIP_ARCH_CC_H */
diff --git a/src/include/arch/perf.h b/src/include/arch/perf.h
new file mode 100644
index 0000000..e505da7
--- /dev/null
+++ b/src/include/arch/perf.h
@@ -0,0 +1,155 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef LWIP_ARCH_PERF_H
+#define LWIP_ARCH_PERF_H
+
+#include <time.h>
+
+#include "lwip/debug.h"
+
+#if LWIP_RECORD_PERF
+enum PERF_POINT {
+    PERF_POINT_IP_RECV,
+    PERF_POINT_TCP_RECV,
+    PERF_POINT_UDP,
+    PERF_POINT_TCP_SYN_RECV,
+    PERF_POINT_TCP_SYN_ACK_SEND,
+    PERF_POINT_TCP_ACK_RECV,
+    PERF_POINT_TCP_SYN_SEND,
+    PERF_POINT_TCP_SYN_ACK_RECV,
+    PERF_POINT_TCP_ACK_SEND,
+    PERF_POINT_TCP_DATA_SEND,
+    PERF_POINT_IP_SEND,
+    PERF_POINT_END
+};
+
+enum PERF_LAYER {
+    PERF_LAYER_IP,
+    PERF_LAYER_TCP,
+    PERF_LAYER_UDP,
+    PERF_LAYER_END
+};
+
+extern uint32_t g_record_perf;
+
+extern __thread uint64_t g_timeTaken[PERF_POINT_END];
+extern __thread int g_perfPoint[PERF_LAYER_END];
+extern __thread struct timespec tvStart[PERF_LAYER_END];
+
+extern char *g_ppLayerName[PERF_POINT_END];
+extern volatile uint64_t g_perfMaxtime[PERF_POINT_END];
+extern volatile uint64_t g_astPacketCnt[PERF_POINT_END];
+extern volatile uint64_t g_astPacketProcTime[PERF_POINT_END];
+
+#define PERF_START(layer, point) do {\
+    g_perfPoint[(layer)] = (point);\
+    LWIP_DEBUGF(PERF_OUTPUT_DEBUG, ("set point %d:%s\n", layer, g_ppLayerName[g_perfPoint[(layer)]]));\
+    clock_gettime(CLOCK_MONOTONIC, &tvStart[(layer)]);\
+    g_timeTaken[(point)] = 0;\
+} while (0)
+
+#define PERF_UPDATE_POINT(layer, point) do {\
+    LWIP_DEBUGF(PERF_OUTPUT_DEBUG, ("old point %d:%s\n", layer, g_ppLayerName[g_perfPoint[(layer)]]));\
+    g_timeTaken[(point)] = g_timeTaken[g_perfPoint[(layer)]];\
+    g_timeTaken[g_perfPoint[(layer)]] = 0;\
+    g_perfPoint[(layer)] = (point);\
+    LWIP_DEBUGF(PERF_OUTPUT_DEBUG, ("new point %d:%s\n", layer, g_ppLayerName[g_perfPoint[(layer)]]));\
+} while (0)
+
+#define PERF_PAUSE(layer) do {\
+    struct timespec tvEnd;\
+    clock_gettime(CLOCK_MONOTONIC, &tvEnd);\
+    LWIP_DEBUGF(PERF_OUTPUT_DEBUG, ("perf pause layer%d\n", layer));\
+    g_timeTaken[g_perfPoint[(layer)]] += ((tvEnd.tv_sec - tvStart[(layer)].tv_sec) \
+            * (1000000000UL) + (tvEnd.tv_nsec - tvStart[(layer)].tv_nsec));\
+} while (0)
+
+#define PERF_PAUSE_RETURN_POINT(layer, pause_point) do {\
+    struct timespec tvEnd;\
+    clock_gettime(CLOCK_MONOTONIC, &tvEnd);\
+    g_timeTaken[g_perfPoint[(layer)]] += ((tvEnd.tv_sec - tvStart[(layer)].tv_sec) \
+            * (1000000000UL) + (tvEnd.tv_nsec - tvStart[(layer)].tv_nsec));\
+    LWIP_DEBUGF(PERF_OUTPUT_DEBUG, ("perf pause point %d:%s\n", layer, g_ppLayerName[g_perfPoint[(layer)]]));\
+    (pause_point) = g_perfPoint[(layer)];\
+} while (0)
+
+
+#define PERF_RESUME(layer, point) do {\
+    LWIP_DEBUGF(PERF_OUTPUT_DEBUG, ("perf resule point %d:%s\n", layer, g_ppLayerName[point]));\
+    clock_gettime(CLOCK_MONOTONIC, &tvStart[(layer)]);\
+    g_perfPoint[(layer)] = (point);\
+} while (0)
+
+
+/* x is a prompt */
+#define PERF_STOP_INCREASE_COUNT(x, layer) do {\
+    if (g_record_perf)\
+    {\
+        struct timespec tvEnd;\
+        int i = 2;\
+        uint32_t oldValue = 0;\
+        clock_gettime(CLOCK_MONOTONIC, &tvEnd);\
+        g_timeTaken[g_perfPoint[(layer)]] += ((tvEnd.tv_sec - tvStart[(layer)].tv_sec) \
+                * (1000000000UL) + (tvEnd.tv_nsec - tvStart[(layer)].tv_nsec));\
+        while (i && !oldValue)\
+        {\
+            oldValue = __sync_or_and_fetch(&g_perfMaxtime[g_perfPoint[(layer)]], 0);\
+            if (oldValue >= g_timeTaken[g_perfPoint[(layer)]])\
+            {\
+                break;\
+            }\
+            oldValue = __sync_val_compare_and_swap(&g_perfMaxtime[g_perfPoint[(layer)]],\
+                    oldValue, g_timeTaken[g_perfPoint[(layer)]]);\
+            i--;\
+        }\
+        __sync_fetch_and_add(&g_astPacketCnt[g_perfPoint[(layer)]], 1);\
+        __sync_fetch_and_add(&g_astPacketProcTime[g_perfPoint[(layer)]], g_timeTaken[g_perfPoint[(layer)]]);\
+        LWIP_DEBUGF(PERF_OUTPUT_DEBUG, ("Time for %s is: %ld\n",\
+                g_ppLayerName[g_perfPoint[(layer)]], g_timeTaken[g_perfPoint[(layer)]]));\
+    }\
+} while (0)
+
+
+int check_layer_point(int layer, int point);
+int perf_init();
+
+#else
+#define PERF_START(layer, point)         do {  } while (0)
+#define PERF_UPDATE_POINT(layer, point)  do {  } while (0)
+#define PERF_PAUSE(layer)                do {  } while (0)
+#define PERF_PAUSE_RETURN_POINT(layer, pause_point) do {  } while (0)
+#define PERF_RESUME(layer, point)           do {  } while (0)
+#define PERF_STOP_INCREASE_COUNT(x, layer)  do {  } while (0)
+#endif
+
+#endif /* LWIP_ARCH_PERF_H */
diff --git a/src/include/arch/sys_arch.h b/src/include/arch/sys_arch.h
index 3f555ee..b8a0d28 100644
--- a/src/include/arch/sys_arch.h
+++ b/src/include/arch/sys_arch.h
@@ -1,7 +1,93 @@
-#ifndef LWIP_SYS_ARCH_H
-#define LWIP_SYS_ARCH_H
+/*
+ * 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: Huawei Technologies
+ *
+ */
 
+#ifndef LWIP_ARCH_SYS_ARCH_H
+#define LWIP_ARCH_SYS_ARCH_H
 
+#include <rte_cycles.h>
+#include <rte_debug.h>
 
-#endif /* LWIP_SYS_ARCH_H */
+#define SYS_MBOX_NULL NULL
+#define SYS_SEM_NULL  NULL
+typedef uint32_t sys_prot_t;
 
+struct sys_sem {
+    volatile unsigned int c;
+    int (*wait_fn)(void);
+};
+
+#define MBOX_NAME_LEN 64
+struct sys_mbox {
+    struct rte_ring *ring;
+    char name[MBOX_NAME_LEN];
+    int size;
+    int socket_id;
+    unsigned flags;
+    int (*wait_fn)(void);
+};
+
+typedef struct sys_sem *sys_sem_t;
+#define sys_sem_valid(sem)             (((sem) != NULL) && (*(sem) != NULL))
+#define sys_sem_valid_val(sem)         ((sem) != NULL)
+#define sys_sem_set_invalid(sem)       do { if ((sem) != NULL) { *(sem) = NULL; }} while(0)
+#define sys_sem_set_invalid_val(sem)   do { (sem) = NULL; } while(0)
+
+struct sys_mutex;
+typedef struct sys_mutex *sys_mutex_t;
+#define sys_mutex_valid(mutex)         sys_sem_valid(mutex)
+#define sys_mutex_set_invalid(mutex)   sys_sem_set_invalid(mutex)
+
+typedef struct sys_mbox *sys_mbox_t;
+#define sys_mbox_valid(mbox)           sys_sem_valid(mbox)
+#define sys_mbox_valid_val(mbox)       sys_sem_valid_val(mbox)
+#define sys_mbox_set_invalid(mbox)     sys_sem_set_invalid(mbox)
+#define sys_mbox_set_invalid_val(mbox) sys_sem_set_invalid_val(mbox)
+int sys_mbox_empty(struct sys_mbox *);
+
+struct sys_thread;
+typedef struct sys_thread *sys_thread_t;
+
+extern int eth_dev_poll(void);
+
+void sys_calibrate_tsc(void);
+uint32_t sys_now(void);
+__attribute__((always_inline)) inline int update_timeout(int timeout, uint32_t poll_ts)
+{
+    uint32_t used_ms = sys_now() - poll_ts;
+    if (timeout > 0 && used_ms < timeout) {
+        return timeout;
+    } else {
+        return 0;
+    }
+}
+
+#endif /* LWIP_ARCH_SYS_ARCH_H */
diff --git a/src/include/eventpoll.h b/src/include/eventpoll.h
new file mode 100644
index 0000000..01f8d64
--- /dev/null
+++ b/src/include/eventpoll.h
@@ -0,0 +1,72 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __EVENTPOLL_H__
+#define __EVENTPOLL_H__
+
+#include <sys/epoll.h>
+
+#include "lwip/api.h"
+#include "list.h"
+
+#define MAX_EPOLLFDS 32
+
+#define LIBOS_EPOLLNONE (0x0)
+#define LIBOS_BADEP     (NULL)
+
+struct event_queue {
+    struct list_node events;
+    /* total number of sockets have events */
+    int num_events;
+};
+
+struct event_array {
+    sys_mbox_t mbox;
+    volatile int num_events;
+    struct epoll_event events[0];
+};
+
+struct libos_epoll {
+    struct event_queue *libos_queue;
+    struct event_array *host_queue;
+    int num_hostfds;
+    int hints;
+    int fd;  /* self fd */
+    int efd; /* eventfd */
+};
+
+extern int add_epoll_event(struct netconn*, uint32_t);
+extern int del_epoll_event(struct netconn*, uint32_t);
+extern int lwip_epoll_close(int);
+extern int lwip_is_epfd(int);
+
+#endif /* __EVENTPOLL_H__ */
diff --git a/src/include/hlist.h b/src/include/hlist.h
new file mode 100644
index 0000000..7059488
--- /dev/null
+++ b/src/include/hlist.h
@@ -0,0 +1,233 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __HLIST_H__
+#define __HLIST_H__
+
+#include "list.h"
+
+//#if TCP_PCB_HASH
+struct hlist_node {
+    /**
+     * @pprev: point the previous node's next pointer
+     */
+    struct hlist_node *next;
+    struct hlist_node **pprev;
+};
+
+struct hlist_head {
+    struct hlist_node *first;
+};
+
+struct hlist_tail {
+    struct hlist_node *end;
+};
+
+struct hlist_ctl {
+    struct hlist_head head;
+    struct hlist_tail tail;
+};
+
+#define INIT_HLIST_CTRL(ptr) {(ptr)->head.first = NULL; (ptr)->tail.end = NULL;}
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+#define INIT_HLIST_NODE(ptr) {(ptr)->next = NULL; (ptr)->pprev = NULL;}
+#define hlist_entry(ptr, type, member) \
+    container_of(ptr, type, member)
+
+/**
+ * hlist_for_each_entry    - iterate over list of given type
+ * @tpos:    the type * to use as a loop cursor.
+ * @pos:    the &struct hlist_node to use as a loop cursor.
+ * @head:    the head for your list.
+ * @member:    the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+    for (pos = (head)->first; \
+        pos && ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
+        pos = (pos)->next)
+
+/**
+ * next must be != NULL
+ * add n node before next node
+ *
+ * @n: new node
+ * @next: node in the hlist
+ */
+static inline void hlist_add_before(struct hlist_node *n, struct hlist_node *next)
+{
+    n->pprev = next->pprev;
+    n->next = next;
+    next->pprev = &n->next;
+    *(n->pprev) = n;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+    return !h->first;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+    return !h->pprev;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+    struct hlist_node *next = n->next;
+    struct hlist_node **pprev = n->pprev;
+
+    if (pprev == NULL) {
+        return;
+    }
+
+    *pprev = next;
+    if (next != NULL) {
+        next->pprev = pprev;
+    }
+
+    n->next = NULL;
+    n->pprev = NULL;
+}
+
+static inline void hlist_ctl_del(struct hlist_ctl *ctl, struct hlist_node *n)
+{
+    if (ctl->head.first == ctl->tail.end) {
+        ctl->head.first = NULL;
+        ctl->tail.end = NULL;
+        return;
+    }
+
+    if (ctl->tail.end == n) {
+        ctl->tail.end = (struct hlist_node *)n->pprev;
+    }
+
+    hlist_del_init(n);
+}
+
+static inline struct hlist_node *hlist_pop_tail(struct hlist_ctl *ctl)
+{
+    if (hlist_empty(&ctl->head)) {
+        return NULL;
+    }
+
+    if (ctl->head.first == ctl->tail.end) {
+        struct hlist_node *ret = ctl->tail.end;
+        ctl->tail.end = NULL;
+        ctl->head.first = NULL;
+        return ret;
+    }
+
+    struct hlist_node *temp = ctl->tail.end;
+
+    struct hlist_node **ptailPrev = ctl->tail.end->pprev;
+    *ptailPrev = NULL;
+
+    ctl->tail.end = (struct hlist_node *)ptailPrev;
+    temp->pprev = NULL;
+    return temp;
+}
+
+static inline void hlist_add_after(struct hlist_node *n, struct hlist_node *next)
+{
+    next->next = n->next;
+    n->next = next;
+    next->pprev = &n->next;
+    if (next->next) {
+        next->next->pprev = &next->next;
+    }
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+    struct hlist_node *first = h->first;
+
+    n->next = first;
+    if (first != NULL) {
+        first->pprev = &n->next;
+    }
+
+    h->first = n;
+    n->pprev = &h->first;
+}
+
+static inline struct hlist_node *hlist_pop_head(struct hlist_ctl *ctl)
+{
+    if (hlist_empty(&ctl->head)) {
+        return NULL;
+    }
+
+    struct hlist_node *temp = ctl->head.first;
+    hlist_ctl_del(ctl, temp);
+    return temp;
+}
+
+static inline void hlist_ctl_add_tail(struct hlist_ctl *ctl, struct hlist_node *node)
+{
+    if (hlist_empty(&ctl->head)) {
+        hlist_add_head(node, &ctl->head);
+        ctl->tail.end = ctl->head.first;
+        return;
+    }
+
+    ctl->tail.end->next = node;
+
+    node->pprev = &(ctl->tail.end->next);
+    node->next = NULL;
+    ctl->tail.end = node;
+}
+
+static inline void hlist_ctl_add_head(struct hlist_node *node, struct hlist_ctl *ctl)
+{
+    hlist_add_head(node, &ctl->head);
+    if (ctl->tail.end == NULL) {
+        ctl->tail.end = ctl->head.first;
+    }
+}
+
+static inline void hlist_ctl_add_before(struct hlist_node *n, struct hlist_node *next, struct hlist_ctl *ctl)
+{
+    hlist_add_before(n, next);
+    if (next == ctl->head.first) {
+        ctl->head.first = n;
+    }
+}
+
+static inline void hlist_ctl_add_after(struct hlist_node *n, struct hlist_node *next, struct hlist_ctl *ctl)
+{
+    hlist_add_after(n, next);
+    if (n == ctl->tail.end) {
+        ctl->tail.end = next;
+    }
+}
+//#endif /* TCP_PCB_HASH */
+
+#endif /* __HLIST_H__ */
diff --git a/src/include/list.h b/src/include/list.h
new file mode 100644
index 0000000..11f94c2
--- /dev/null
+++ b/src/include/list.h
@@ -0,0 +1,110 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+struct list_node {
+    struct list_node *prev;
+    struct list_node *next;
+};
+
+static inline void init_list_node_null(struct list_node *n)
+{
+    n->prev = NULL;
+    n->next = NULL;
+}
+
+static inline void init_list_node(struct list_node *n)
+{
+    n->prev = n;
+    n->next = n;
+}
+
+static inline void list_add_node(struct list_node *h, struct list_node *n)
+{
+    n->next = h;
+    n->prev = h->prev;
+    h->prev->next = n;
+    h->prev = n;
+}
+
+static inline void list_del_node(struct list_node *n)
+{
+    struct list_node *prev = n->prev;
+    struct list_node *next = n->next;
+    next->prev = prev;
+    prev->next = next;
+}
+
+static inline void list_del_node_init(struct list_node *n)
+{
+    list_del_node(n);
+    init_list_node(n);
+}
+
+static inline void list_del_node_null(struct list_node *n)
+{
+    if ((n->next) && (n->prev)) {
+        list_del_node(n);
+    }
+    init_list_node_null(n);
+}
+
+static inline int list_is_null(const struct list_node *n)
+{
+    return (n->prev == NULL) && (n->next == NULL);
+}
+
+static inline int list_is_empty(const struct list_node *h)
+{
+    return h == h->next;
+}
+
+#define list_for_each_safe(pos, n, head) \
+    for (pos = (head)->next, n = (pos)->next; pos != (head); pos = n, n = (pos)->next)
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+    typeof( ((type *)0)->member ) *__mptr = (ptr); \
+    (type *)((char *)__mptr - offsetof(type,member));})
+#endif /* container_of */
+
+#endif /* __LIST_H__ */
diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h
index be8c22a..55fc413 100644
--- a/src/include/lwip/api.h
+++ b/src/include/lwip/api.h
@@ -140,8 +140,43 @@ enum netconn_type {
   /** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */
   , NETCONN_RAW_IPV6    = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */
 #endif /* LWIP_IPV6 */
+
+#if USE_LIBOS
+  /*here must bigger than 0xff, because (type & 0xff) is for lwip inner use*/
+  , NETCONN_LIBOS = 0x100
+  , NETCONN_HOST = 0x200
+  , NETCONN_INPRG = 0x400
+  , NETCONN_STACK = NETCONN_LIBOS | NETCONN_HOST | NETCONN_INPRG
+#endif /* USE_LIBOS */
 };
 
+#ifdef USE_LIBOS
+#define SET_CONN_TYPE_LIBOS_OR_HOST(conn) do { \
+  conn->type &= ~(NETCONN_STACK); \
+  conn->type |= (NETCONN_LIBOS | NETCONN_HOST); } while (0)
+#define SET_CONN_TYPE_LIBOS(conn) do { \
+  conn->type &= ~(NETCONN_STACK); \
+  conn->type |= NETCONN_LIBOS; } while (0)
+#define SET_CONN_TYPE_HOST(conn) do { \
+  conn->type &= ~(NETCONN_STACK); \
+  conn->type |= NETCONN_HOST; } while (0)
+#define ADD_CONN_TYPE_INPRG(conn) do { \
+  conn->type |= NETCONN_INPRG; } while(0)
+#define CONN_TYPE_HAS_LIBOS_AND_HOST(conn) ((conn->type & (NETCONN_LIBOS | NETCONN_HOST)) == (NETCONN_LIBOS | NETCONN_HOST))
+#define CONN_TYPE_HAS_LIBOS(conn) (conn->type & NETCONN_LIBOS)
+#define CONN_TYPE_HAS_HOST(conn) (conn->type & NETCONN_HOST)
+#define CONN_TYPE_HAS_INPRG(conn) (!!(conn->type & NETCONN_INPRG))
+#define CONN_TYPE_IS_LIBOS(conn)  (!!(NETCONN_LIBOS == (conn->type & NETCONN_STACK)))
+#define CONN_TYPE_IS_HOST(conn)   (!!(NETCONN_HOST == (conn->type & NETCONN_STACK)))
+#else
+#define SET_CONN_TYPE_LIBOS_OR_HOST(conn) do {} while (0)
+#define SET_CONN_TYPE_LIBOS(conn) do {} while (0)
+#define SET_CONN_TYPE_HOST(conn) do {} while (0)
+#define CONN_TYPE_HAS_LIBOS_AND_HOST(conn) (0)
+#define CONN_TYPE_HAS_LIBOS(conn) (0)
+#define CONN_TYPE_HAS_HOST(conn) (0)
+#endif /* USE_LIBOS */
+
 /** Current state of the netconn. Non-TCP netconns are always
  * in state NETCONN_NONE! */
 enum netconn_state {
diff --git a/src/include/lwip/debug.h b/src/include/lwip/debug.h
index 0ec7e76..4986973 100644
--- a/src/include/lwip/debug.h
+++ b/src/include/lwip/debug.h
@@ -146,6 +146,7 @@
 
 #define LWIP_DEBUGF(debug, message) do { \
                                if (LWIP_DEBUG_ENABLED(debug)) { \
+                                 LWIP_PLATFORM_LOG(debug, STRIP_BRACES(ESC_ARGS message)); \
                                  LWIP_PLATFORM_DIAG(message); \
                                  if ((debug) & LWIP_DBG_HALT) { \
                                    while(1); \
diff --git a/src/include/lwip/def.h b/src/include/lwip/def.h
index d6bf763..cfc59e2 100644
--- a/src/include/lwip/def.h
+++ b/src/include/lwip/def.h
@@ -116,6 +116,21 @@ u32_t lwip_htonl(u32_t x);
 
 /* Provide usual function names as macros for users, but this can be turned off */
 #ifndef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS
+
+/* avoid conflicts with netinet/in.h */
+#ifdef htons
+#undef htons
+#endif
+#ifdef ntohs
+#undef ntohs
+#endif
+#ifdef htonl
+#undef htonl
+#endif
+#ifdef ntohl
+#undef ntohl
+#endif
+
 #define htons(x) lwip_htons(x)
 #define ntohs(x) lwip_ntohs(x)
 #define htonl(x) lwip_htonl(x)
diff --git a/src/include/lwip/ip.h b/src/include/lwip/ip.h
index 668d831..db031ba 100644
--- a/src/include/lwip/ip.h
+++ b/src/include/lwip/ip.h
@@ -107,9 +107,15 @@ struct ip_pcb {
 /*
  * Option flags per-socket. These are the same like SO_XXX in sockets.h
  */
+#if USE_LIBOS
+#define SOF_REUSEADDR     0x02U /* allow local address reuse */
+#define SOF_KEEPALIVE     0x09U /* keep connections alive */
+#define SOF_BROADCAST     0x06U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
+#else
 #define SOF_REUSEADDR     0x04U  /* allow local address reuse */
 #define SOF_KEEPALIVE     0x08U  /* keep connections alive */
 #define SOF_BROADCAST     0x20U  /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
+#endif /* USE_LIBOS */
 
 /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
 #define SOF_INHERITED   (SOF_REUSEADDR|SOF_KEEPALIVE)
@@ -136,7 +142,7 @@ struct ip_globals
   /** Destination IP address of current_header */
   ip_addr_t current_iphdr_dest;
 };
-extern struct ip_globals ip_data;
+extern PER_THREAD struct ip_globals ip_data;
 
 
 /** Get the interface that accepted the current packet.
diff --git a/src/include/lwip/memp.h b/src/include/lwip/memp.h
index 1630b26..64d8f31 100644
--- a/src/include/lwip/memp.h
+++ b/src/include/lwip/memp.h
@@ -58,7 +58,11 @@ typedef enum {
 #include "lwip/priv/memp_priv.h"
 #include "lwip/stats.h"
 
+#if USE_LIBOS
+extern PER_THREAD struct memp_desc* memp_pools[MEMP_MAX];
+#else
 extern const struct memp_desc* const memp_pools[MEMP_MAX];
+#endif /* USE_LIBOS */
 
 /**
  * @ingroup mempool
@@ -92,6 +96,18 @@ extern const struct memp_desc* const memp_pools[MEMP_MAX];
  * To relocate a pool, declare it as extern in cc.h. Example for GCC:
  *   extern u8_t \_\_attribute\_\_((section(".onchip_mem"))) memp_memory_my_private_pool_base[];
  */
+#if USE_LIBOS
+#define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
+    PER_THREAD struct memp_desc memp_ ## name = {0}; \
+    PER_THREAD char memp_desc_ ## name[] = desc; \
+    PER_THREAD struct stats_mem memp_stat ## name = {0}; \
+    PER_THREAD u16_t memp_size ## name = size; \
+    PER_THREAD u16_t memp_num ## name = num;   \
+    PER_THREAD struct memp *memp_tab_ ## name = NULL; \
+    LWIP_DECLARE_MEMP_BASE_ALIGNED(name, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size))));
+
+#else /* USE_LIBOS */
+
 #define LWIP_MEMPOOL_DECLARE(name,num,size,desc) \
   LWIP_DECLARE_MEMORY_ALIGNED(memp_memory_ ## name ## _base, ((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))); \
     \
@@ -108,6 +124,7 @@ extern const struct memp_desc* const memp_pools[MEMP_MAX];
     &memp_tab_ ## name \
   };
 
+#endif /* USE_LIBOS */
 #endif /* MEMP_MEM_MALLOC */
 
 /**
diff --git a/src/include/lwip/netif.h b/src/include/lwip/netif.h
index 0cde2c2..1e6dc46 100644
--- a/src/include/lwip/netif.h
+++ b/src/include/lwip/netif.h
@@ -420,11 +420,11 @@ struct netif {
 #define NETIF_FOREACH(netif) if (((netif) = netif_default) != NULL)
 #else /* LWIP_SINGLE_NETIF */
 /** The list of network interfaces. */
-extern struct netif *netif_list;
+extern PER_THREAD struct netif *netif_list;
 #define NETIF_FOREACH(netif) for ((netif) = netif_list; (netif) != NULL; (netif) = (netif)->next)
 #endif /* LWIP_SINGLE_NETIF */
 /** The default network interface. */
-extern struct netif *netif_default;
+extern PER_THREAD struct netif *netif_default;
 
 void netif_init(void);
 
diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h
index c27dd03..b738460 100644
--- a/src/include/lwip/opt.h
+++ b/src/include/lwip/opt.h
@@ -525,6 +525,22 @@
 #define MEMP_NUM_NETCONN                4
 #endif
 
+/**
+ * MEMP_NUM_SYS_SEM: the number of struct sys_sems.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#if !defined MEMP_NUM_SYS_SEM || defined __DOXYGEN__
+#define MEMP_NUM_SYS_SEM                128
+#endif
+
+/**
+ * MEMP_NUM_SYS_MBOX: the number of struct sys_sems.
+ * (only needed if you use the sequential API, like api_lib.c)
+ */
+#if !defined MEMP_NUM_SYS_MBOX || defined __DOXYGEN__
+#define MEMP_NUM_SYS_MBOX                128
+#endif
+
 /**
  * MEMP_NUM_SELECT_CB: the number of struct lwip_select_cb.
  * (Only needed if you have LWIP_MPU_COMPATIBLE==1 and use the socket API.
@@ -2294,7 +2310,7 @@
  * MIB2_STATS==1: Stats for SNMP MIB2.
  */
 #if !defined MIB2_STATS || defined __DOXYGEN__
-#define MIB2_STATS                      0
+#define MIB2_STATS                      1
 #endif
 
 #else
@@ -3484,6 +3500,10 @@
 #define TCP_OUTPUT_DEBUG                LWIP_DBG_OFF
 #endif
 
+#ifndef PERF_OUTPUT_DEBUG
+ #define PERF_OUTPUT_DEBUG              LWIP_DBG_OFF
+#endif
+
 /**
  * TCP_RST_DEBUG: Enable debugging for TCP with the RST message.
  */
@@ -3571,6 +3591,46 @@
 #define LWIP_TESTMODE                   0
 #endif
 
+/**
+ * EPOLL_DEBUG: Enable debugging in epoll.c.
+ */
+#if !defined EPOLL_DEBUG || defined __DOXYGEN__ && USE_LIBOS
+#define EPOLL_DEBUG                    LWIP_DBG_OFF
+#endif
+/**
+ * @}
+ */
+
+/**
+ * ETHDEV_DEBUG: Enable debugging in ethdev.c.
+ */
+#if !defined ETHDEV_DEBUG || defined __DOXYGEN__ && USE_LIBOS
+#define ETHDEV_DEBUG                    LWIP_DBG_OFF
+#endif
+/**
+ * @}
+ */
+
+/**
+ * ETHDEV_DEBUG: Enable debugging in ethdev.c.
+ */
+#if !defined SYSCALL_DEBUG || defined __DOXYGEN__ && USE_LIBOS
+#define SYSCALL_DEBUG                    LWIP_DBG_OFF
+#endif
+/**
+ * @}
+ */
+
+/**
+ * CONTROL_DEBUG: Enable debugging in control_plane.c.
+ */
+#if !defined CONTROL_DEBUG || defined __DOXYGEN__ && USE_LIBOS
+#define CONTROL_DEBUG                    LWIP_DBG_ON
+#endif
+/**
+ * @}
+ */
+
 /*
    --------------------------------------------------
    ---------- Performance tracking options ----------
diff --git a/src/include/lwip/priv/memp_std.h b/src/include/lwip/priv/memp_std.h
index 669ad4d..395ac0c 100644
--- a/src/include/lwip/priv/memp_std.h
+++ b/src/include/lwip/priv/memp_std.h
@@ -122,6 +122,13 @@ LWIP_MEMPOOL(MLD6_GROUP,     MEMP_NUM_MLD6_GROUP,      sizeof(struct mld_group),
 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
 
 
+#if USE_LIBOS
+#if !LWIP_NETCONN_SEM_PER_THREAD
+LWIP_MEMPOOL(SYS_SEM,     MEMP_NUM_SYS_SEM,      sizeof(struct sys_sem),     "SYS_SEM")
+#endif
+
+LWIP_MEMPOOL(SYS_MBOX,     MEMP_NUM_SYS_MBOX,      sizeof(struct sys_mbox),     "SYS_MBOX")
+#endif /* USE_LIBOS */
 /*
  * A list of pools of pbuf's used by LWIP.
  *
diff --git a/src/include/lwip/priv/sockets_priv.h b/src/include/lwip/priv/sockets_priv.h
index c604734..f438206 100644
--- a/src/include/lwip/priv/sockets_priv.h
+++ b/src/include/lwip/priv/sockets_priv.h
@@ -45,56 +45,17 @@
 #include "lwip/sockets.h"
 #include "lwip/sys.h"
 
+/* move some definitions to the lwipsock.h for libnet to use, and
+ * at the same time avoid conflict between lwip/sockets.h and sys/socket.h
+ */
+#include "lwipsock.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #define NUM_SOCKETS MEMP_NUM_NETCONN
 
-/** This is overridable for the rare case where more than 255 threads
- * select on the same socket...
- */
-#ifndef SELWAIT_T
-#define SELWAIT_T u8_t
-#endif
-
-union lwip_sock_lastdata {
-  struct netbuf *netbuf;
-  struct pbuf *pbuf;
-};
-
-/** Contains all internal pointers and states used for a socket */
-struct lwip_sock {
-  /** sockets currently are built on netconns, each socket has one netconn */
-  struct netconn *conn;
-  /** data that was left from the previous read */
-  union lwip_sock_lastdata lastdata;
-#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
-  /** number of times data was received, set by event_callback(),
-      tested by the receive and select functions */
-  s16_t rcvevent;
-  /** number of times data was ACKed (free send buffer), set by event_callback(),
-      tested by select */
-  u16_t sendevent;
-  /** error happened for this socket, set by event_callback(), tested by select */
-  u16_t errevent;
-  /** counter of how many threads are waiting for this socket using select */
-  SELWAIT_T select_waiting;
-#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
-#if LWIP_NETCONN_FULLDUPLEX
-  /* counter of how many threads are using a struct lwip_sock (not the 'int') */
-  u8_t fd_used;
-  /* status of pending close/delete actions */
-  u8_t fd_free_pending;
-#define LWIP_SOCK_FD_FREE_TCP  1
-#define LWIP_SOCK_FD_FREE_FREE 2
-#endif
-};
-
-#ifndef set_errno
-#define set_errno(err) do { if (err) { errno = (err); } } while(0)
-#endif
-
 #if !LWIP_TCPIP_CORE_LOCKING
 /** Maximum optlen used by setsockopt/getsockopt */
 #define LWIP_SETGETSOCKOPT_MAXOPTLEN LWIP_MAX(16, sizeof(struct ifreq))
diff --git a/src/include/lwip/priv/tcp_priv.h b/src/include/lwip/priv/tcp_priv.h
index a8e87e5..b1380b6 100644
--- a/src/include/lwip/priv/tcp_priv.h
+++ b/src/include/lwip/priv/tcp_priv.h
@@ -320,25 +320,42 @@ struct tcp_seg {
 #endif /* LWIP_WND_SCALE */
 
 /* Global variables: */
-extern struct tcp_pcb *tcp_input_pcb;
-extern u32_t tcp_ticks;
-extern u8_t tcp_active_pcbs_changed;
+extern PER_THREAD struct tcp_pcb *tcp_input_pcb;
+extern PER_THREAD u32_t tcp_ticks;
+extern PER_THREAD u8_t tcp_active_pcbs_changed;
 
 /* The TCP PCB lists. */
 union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
   struct tcp_pcb_listen *listen_pcbs;
   struct tcp_pcb *pcbs;
 };
-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
+extern PER_THREAD struct tcp_pcb *tcp_bound_pcbs;
+extern PER_THREAD union tcp_listen_pcbs_t tcp_listen_pcbs;
+extern PER_THREAD 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 PER_THREAD struct tcp_pcb *tcp_tw_pcbs;      /* List of all TCP PCBs in TIME-WAIT. */
 
 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT  3
 #define NUM_TCP_PCB_LISTS               4
-extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
+extern PER_THREAD struct tcp_pcb ** tcp_pcb_lists[NUM_TCP_PCB_LISTS];
+
+#if USE_LIBOS
+#include "reg_sock.h"
+static inline int vdev_reg_done(enum reg_ring_type reg_type, const struct tcp_pcb *pcb)
+{
+  LWIP_ASSERT("Invalid parameter", pcb != NULL);
+
+  struct libnet_quintuple qtuple;
+  qtuple.protocol   = 0;
+  qtuple.src_ip     = pcb->local_ip.addr;
+  qtuple.src_port   = lwip_htons(pcb->local_port);
+  qtuple.dst_ip     = pcb->remote_ip.addr;
+  qtuple.dst_port   = lwip_htons(pcb->remote_port);
+
+  return vdev_reg_xmit(reg_type, &qtuple);
+}
+#endif
 
 /* Axioms about the above lists:
    1) Every TCP PCB that is not CLOSED is in one of the lists.
@@ -352,6 +369,54 @@ extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
 #define TCP_DEBUG_PCB_LISTS 0
 #endif
 #if TCP_DEBUG_PCB_LISTS
+#if USE_LIBOS
+#define TCP_REG(pcbs, npcb) do {\
+                            struct tcp_pcb *tcp_tmp_pcb; \
+                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \
+                            for (tcp_tmp_pcb = *(pcbs); \
+          tcp_tmp_pcb != NULL; \
+        tcp_tmp_pcb = tcp_tmp_pcb->next) { \
+                                LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \
+                            } \
+                            LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \
+                            if (*pcbs)                                     \
+                               (*pcbs)->prev = npcb;                       \
+                            (npcb)->prev = NULL;                           \
+                            (npcb)->next = *(pcbs); \
+                            LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \
+                            *(pcbs) = (npcb); \
+                            LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
+              tcp_timer_needed(); \
+                            } while(0)
+#define TCP_RMV(pcbs, npcb) do { \
+                            if (pcb->state == LISTEN)                         \
+                              vdev_reg_done(REG_RING_TCP_LISTEN_CLOSE, npcb); \
+                            else                                              \
+                              vdev_reg_done(REG_RING_TCP_CONNECT_CLOSE, npcb);\
+                            struct tcp_pcb *tcp_tmp_pcb; \
+                            LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \
+                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \
+                            if(*(pcbs) == (npcb)) { \
+                               *(pcbs) = (*pcbs)->next; \
+                               if (*pcbs)                                   \
+                                  (*pcbs)->prev = NULL;                     \
+                            } else { \
+                               struct tcp_pcb *prev, *next;                 \
+                               prev = npcb->prev;                           \
+                               next = npcb->next;                           \
+                               if (prev)                                    \
+                                  prev->next = next;                        \
+                               if (next)                                    \
+                                  next->prev = prev;                        \
+                               } \
+                            } \
+                            (npcb)->prev = NULL; \
+                            (npcb)->next = NULL; \
+                            LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
+                            LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \
+                            } while(0)
+
+#else /* USE_LIBOS */
 #define TCP_REG(pcbs, npcb) do {\
                             struct tcp_pcb *tcp_tmp_pcb; \
                             LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %"U16_F"\n", (void *)(npcb), (npcb)->local_port)); \
@@ -384,8 +449,65 @@ extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
                             LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (void *)(npcb), (void *)(*(pcbs)))); \
                             } while(0)
 
+#endif /* USE_LIBOS */
 #else /* LWIP_DEBUG */
 
+#if TCP_PCB_HASH
+#define TCP_REG_HASH(pcbs, npcb)                   \
+  do {                                             \
+    u32_t idx;                                     \
+    struct hlist_head *hd;                         \
+    struct tcp_hash_table *htb = pcbs;             \
+    idx = TUPLE4_HASH_FN((npcb)->local_ip.addr, (npcb)->local_port,  \
+                       (npcb)->remote_ip.addr, (npcb)->remote_port) & \
+                       (htb->size - 1);            \
+    hd = &htb->array[idx].chain;                   \
+    hlist_add_head(&(npcb)->tcp_node, hd);         \
+    tcp_timer_needed();                            \
+  } while (0)
+
+#define TCP_RMV_HASH(pcbs, npcb)                   \
+  do {                                             \
+    hlist_del_init(&(npcb)->tcp_node);             \
+  } while (0)
+#endif /* TCP_PCB_HASH */
+
+#if USE_LIBOS
+#define TCP_REG(pcbs, npcb)                        \
+  do {                                             \
+    if (*pcbs)                                     \
+      (*pcbs)->prev = npcb;                        \
+    (npcb)->prev = NULL;                           \
+    (npcb)->next = *pcbs;                          \
+    *(pcbs) = (npcb);                              \
+    tcp_timer_needed();                            \
+  } while (0)
+
+#define TCP_RMV(pcbs, npcb)                        \
+  do {                                             \
+    if (pcb->state == LISTEN)                         \
+      vdev_reg_done(REG_RING_TCP_LISTEN_CLOSE, npcb); \
+    else                                              \
+      vdev_reg_done(REG_RING_TCP_CONNECT_CLOSE, npcb);\
+    if(*(pcbs) == (npcb)) {                        \
+      (*(pcbs)) = (*pcbs)->next;                   \
+      if (*pcbs)                                   \
+        (*pcbs)->prev = NULL;                      \
+    }                                              \
+    else {                                         \
+      struct tcp_pcb *prev, *next;                 \
+      prev = npcb->prev;                           \
+      next = npcb->next;                           \
+      if (prev)                                    \
+        prev->next = next;                         \
+      if (next)                                    \
+        next->prev = prev;                         \
+    }                                              \
+    (npcb)->prev = NULL;                           \
+    (npcb)->next = NULL;                           \
+  } while(0)
+
+#else /* USE_LIBOS */
 #define TCP_REG(pcbs, npcb)                        \
   do {                                             \
     (npcb)->next = *pcbs;                          \
@@ -412,8 +534,32 @@ extern struct tcp_pcb ** const tcp_pcb_lists[NUM_TCP_PCB_LISTS];
     (npcb)->next = NULL;                           \
   } while(0)
 
+#endif /* USE_LIBOS */
 #endif /* LWIP_DEBUG */
 
+
+#if TCP_PCB_HASH
+#define TCP_REG_ACTIVE_HASH(npcb)                  \
+  do {                                             \
+    TCP_REG_HASH(tcp_active_htable, npcb);         \
+    tcp_active_pcbs_changed = 1;                   \
+  } while (0)
+
+#define TCP_RMV_ACTIVE_HASH(npcb)                  \
+  do {                                             \
+    TCP_RMV_HASH(tcp_active_htable, npcb);         \
+    tcp_active_pcbs_changed = 1;                   \
+  } while (0)
+
+#define TCP_PCB_REMOVE_ACTIVE_HASH(pcb)            \
+  do {                                             \
+    tcp_pcb_remove_hash(tcp_active_htable, pcb);   \
+    tcp_active_pcbs_changed = 1;                   \
+  } while (0)
+
+void tcp_pcb_remove_hash(struct tcp_hash_table *htb, struct tcp_pcb *pcb);
+#endif /* TCP_PCB_HASH */
+
 #define TCP_REG_ACTIVE(npcb)                       \
   do {                                             \
     TCP_REG(&tcp_active_pcbs, npcb);               \
diff --git a/src/include/lwip/prot/ip4.h b/src/include/lwip/prot/ip4.h
index 9347461..c9ad89c 100644
--- a/src/include/lwip/prot/ip4.h
+++ b/src/include/lwip/prot/ip4.h
@@ -81,6 +81,21 @@ struct ip_hdr {
   PACK_STRUCT_FIELD(u16_t _id);
   /* fragment offset field */
   PACK_STRUCT_FIELD(u16_t _offset);
+
+/* avoid conflicts with netinet/ip.h */
+#ifdef IP_RF
+#undef IP_RF
+#endif
+#ifdef IP_DF
+#undef IP_DF
+#endif
+#ifdef IP_MF
+#undef IP_MF
+#endif
+#ifdef IP_OFFMASK
+#undef IP_OFFMASK
+#endif
+
 #define IP_RF 0x8000U        /* reserved fragment flag */
 #define IP_DF 0x4000U        /* don't fragment flag */
 #define IP_MF 0x2000U        /* more fragments flag */
diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h
index b6f3d52..c8f0fab 100644
--- a/src/include/lwip/sockets.h
+++ b/src/include/lwip/sockets.h
@@ -64,6 +64,11 @@ extern "C" {
 
 /* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED
    to prevent this code from redefining it. */
+#if USE_LIBOS
+#define SA_FAMILY_T_DEFINED
+  typedef u16_t sa_family_t;
+#endif
+
 #if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED)
 typedef u8_t sa_family_t;
 #endif
@@ -76,7 +81,9 @@ typedef u16_t in_port_t;
 #if LWIP_IPV4
 /* members are in network byte order */
 struct sockaddr_in {
+#if !USE_LIBOS
   u8_t            sin_len;
+#endif
   sa_family_t     sin_family;
   in_port_t       sin_port;
   struct in_addr  sin_addr;
@@ -97,7 +104,9 @@ struct sockaddr_in6 {
 #endif /* LWIP_IPV6 */
 
 struct sockaddr {
+#if !USE_LIBOS
   u8_t        sa_len;
+#endif
   sa_family_t sa_family;
   char        sa_data[14];
 };
@@ -198,6 +207,9 @@ struct ifreq {
 #define SOCK_DGRAM      2
 #define SOCK_RAW        3
 
+#if USE_LIBOS
+#include <asm/socket.h>
+#else
 /*
  * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c)
  */
@@ -229,6 +241,12 @@ struct ifreq {
 #define SO_NO_CHECK     0x100a /* don't create UDP checksum */
 #define SO_BINDTODEVICE 0x100b /* bind to device */
 
+/*
+ * Level number for (get/set)sockopt() to apply to socket itself.
+ */
+#define  SOL_SOCKET  0xfff    /* options for socket level */
+#endif /* USE_LIBOS */
+
 /*
  * Structure used for manipulating linger option.
  */
@@ -237,11 +255,6 @@ struct linger {
   int l_linger;               /* linger time in seconds */
 };
 
-/*
- * Level number for (get/set)sockopt() to apply to socket itself.
- */
-#define  SOL_SOCKET  0xfff    /* options for socket level */
-
 
 #define AF_UNSPEC       0
 #define AF_INET         2
@@ -285,11 +298,20 @@ struct linger {
 /*
  * Options for level IPPROTO_TCP
  */
+#if USE_LIBOS
+/* come from netinet/tcp.h */
+#define TCP_NODELAY    0x01    /* don't delay send to coalesce packets */
+#define TCP_KEEPALIVE  0x24    /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */
+#define TCP_KEEPIDLE   0x04    /* set pcb->keep_idle  - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */
+#define TCP_KEEPINTVL  0x05    /* set pcb->keep_intvl - Use seconds for get/setsockopt */
+#define TCP_KEEPCNT    0x06    /* set pcb->keep_cnt   - Use number of probes sent for get/setsockopt */
+#else /* USE_LIBOS */
 #define TCP_NODELAY    0x01    /* don't delay send to coalesce packets */
 #define TCP_KEEPALIVE  0x02    /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */
 #define TCP_KEEPIDLE   0x03    /* set pcb->keep_idle  - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */
 #define TCP_KEEPINTVL  0x04    /* set pcb->keep_intvl - Use seconds for get/setsockopt */
 #define TCP_KEEPCNT    0x05    /* set pcb->keep_cnt   - Use number of probes sent for get/setsockopt */
+#endif /* USE_LIBOS */
 #endif /* LWIP_TCP */
 
 #if LWIP_IPV6
@@ -492,12 +514,30 @@ typedef struct fd_set
   unsigned char fd_bits [(FD_SETSIZE+7)/8];
 } fd_set;
 
-#elif FD_SETSIZE < (LWIP_SOCKET_OFFSET + MEMP_NUM_NETCONN)
+#elif FD_SETSIZE < (LWIP_SOCKET_OFFSET + MEMP_NUM_NETCONN) && !USE_LIBOS
 #error "external FD_SETSIZE too small for number of sockets"
 #else
 #define LWIP_SELECT_MAXNFDS FD_SETSIZE
 #endif /* FD_SET */
 
+#if USE_LIBOS
+#if !defined(POLLIN) && !defined(POLLOUT)
+/* come from bits/poll.h */
+#define POLLIN     0x001
+#define POLLOUT    0x004
+#define POLLERR    0x008
+#define POLLNVAL   0x020
+/* Below values are unimplemented */
+#define POLLRDNORM 0x040
+#define POLLRDBAND 0x080
+#define POLLPRI    0x002
+#define POLLWRNORM 0x100
+#define POLLWRBAND 0x200
+#define POLLHUP    0x010
+#endif
+#endif /* USE_LIBOS */
+
+#if LWIP_SOCKET_POLL
 /* poll-related defines and types */
 /* @todo: find a better way to guard the definition of these defines and types if already defined */
 #if !defined(POLLIN) && !defined(POLLOUT)
@@ -520,6 +560,7 @@ struct pollfd
   short revents;
 };
 #endif
+#endif /* LWIP_SOCKET_POLL */
 
 /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided
  * by your system, set this to 0 and include <sys/time.h> in cc.h */
@@ -622,8 +663,15 @@ int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptse
 #if LWIP_SOCKET_POLL
 int lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout);
 #endif
+
+#if USE_LIBOS
+int lwip_ioctl(int s, long cmd, ...);
+int lwip_fcntl(int s, int cmd, ...);
+#else
 int lwip_ioctl(int s, long cmd, void *argp);
 int lwip_fcntl(int s, int cmd, int val);
+#endif /* USE_LIBOS */
+
 const char *lwip_inet_ntop(int af, const void *src, char *dst, socklen_t size);
 int lwip_inet_pton(int af, const char *src, void *dst);
 
@@ -689,10 +737,17 @@ int lwip_inet_pton(int af, const char *src, void *dst);
 #define writev(s,iov,iovcnt)                      lwip_writev(s,iov,iovcnt)
 /** @ingroup socket */
 #define close(s)                                  lwip_close(s)
+
+#if USE_LIBOS
+#define fcntl(s,cmd...)                           lwip_fcntl(s,cmd)
+#define ioctl(s,cmd...)                           lwip_ioctl(s,cmd)
+#else
 /** @ingroup socket */
 #define fcntl(s,cmd,val)                          lwip_fcntl(s,cmd,val)
 /** @ingroup socket */
 #define ioctl(s,cmd,argp)                         lwip_ioctl(s,cmd,argp)
+#endif /* USE_LIBOS */
+
 #endif /* LWIP_POSIX_SOCKETS_IO_NAMES */
 #endif /* LWIP_COMPAT_SOCKETS != 2 */
 
diff --git a/src/include/lwip/stats.h b/src/include/lwip/stats.h
index b570dba..4470531 100644
--- a/src/include/lwip/stats.h
+++ b/src/include/lwip/stats.h
@@ -301,7 +301,7 @@ struct stats_ {
 };
 
 /** Global variable containing lwIP internal statistics. Add this to your debugger's watchlist. */
-extern struct stats_ lwip_stats;
+extern PER_THREAD struct stats_ lwip_stats;
 
 /** Init statistics */
 void stats_init(void);
@@ -467,6 +467,8 @@ void stats_init(void);
 #define MIB2_STATS_INC(x)
 #endif
 
+int get_mib2_stats(char *buf);
+
 /* Display of statistics */
 #if LWIP_STATS_DISPLAY
 void stats_display(void);
diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
index 3991fd6..8248753 100644
--- a/src/include/lwip/tcp.h
+++ b/src/include/lwip/tcp.h
@@ -51,6 +51,11 @@
 #include "lwip/ip6.h"
 #include "lwip/ip6_addr.h"
 
+#if TCP_PCB_HASH
+#include "lwip/sys.h"
+#include "hlist.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -209,15 +214,27 @@ typedef u16_t tcpflags_t;
 /**
  * members common to struct tcp_pcb and struct tcp_listen_pcb
  */
+#if USE_LIBOS
 #define TCP_PCB_COMMON(type) \
   type *next; /* for the linked list */ \
+  type *prev; /* for the linked list */ \
   void *callback_arg; \
   TCP_PCB_EXTARGS \
   enum tcp_state state; /* TCP state */ \
   u8_t prio; \
   /* ports are in host byte order */ \
   u16_t local_port
-
+  
+#else /* USE_LIBOS */
+#define TCP_PCB_COMMON(type) \
+  type *next; /* for the linked list */ \
+  void *callback_arg; \
+  TCP_PCB_EXTARGS \
+  enum tcp_state state; /* TCP state */ \
+  u8_t prio; \
+  /* ports are in host byte order */ \
+  u16_t local_port
+#endif /* USE_LIBOS */
 
 /** the TCP protocol control block for listening pcbs */
 struct tcp_pcb_listen {
@@ -244,6 +261,9 @@ struct tcp_pcb {
   IP_PCB;
 /** protocol specific PCB members */
   TCP_PCB_COMMON(struct tcp_pcb);
+#if TCP_PCB_HASH
+  struct hlist_node tcp_node;
+#endif
 
   /* ports are in host byte order */
   u16_t remote_port;
@@ -388,6 +408,58 @@ struct tcp_pcb {
 #endif
 };
 
+#if TCP_PCB_HASH
+#define TCP_HTABLE_SIZE MEMP_NUM_NETCONN*12
+
+struct tcp_hashbucket
+{
+  sys_mutex_t mutex;
+  struct hlist_head chain;
+};
+
+struct tcp_hash_table
+{
+  u32_t size;
+  struct tcp_hashbucket array[TCP_HTABLE_SIZE];
+};
+
+extern PER_THREAD struct tcp_hash_table *tcp_active_htable; /* key: lport/fport/lip/fip */
+
+#define JHASH_INITVAL		0xdeadbeef
+
+static inline unsigned int rol32(unsigned int word, unsigned int shift)
+{
+  return (word << shift) | (word >> (32 - shift));
+}
+
+#define __jhash_final(a, b, c)			\
+{						\
+  c ^= b; c -= rol32(b, 14);		\
+  a ^= c; a -= rol32(c, 11);		\
+  b ^= a; b -= rol32(a, 25);		\
+  c ^= b; c -= rol32(b, 16);		\
+  a ^= c; a -= rol32(c, 4);		\
+  b ^= a; b -= rol32(a, 14);		\
+  c ^= b; c -= rol32(b, 24);		\
+}
+
+static inline unsigned int jhash_3words(unsigned int a, unsigned int b, unsigned int c)
+{
+  a += JHASH_INITVAL;
+  b += JHASH_INITVAL;;
+
+  __jhash_final(a, b, c);
+
+  return c;
+}
+
+#define TUPLE4_HASH_FN(laddr, lport, faddr, fport)	 jhash_3words(laddr, faddr,lport|(fport<<16))
+
+#define tcppcb_hlist_for_each(tcppcb, node, list) \
+  hlist_for_each_entry(tcppcb, node, list, tcp_node)
+
+#endif /* TCP_PCB_HASH */
+
 #if LWIP_EVENT_API
 
 enum lwip_event {
@@ -481,6 +553,26 @@ err_t            tcp_tcp_get_tcp_addrinfo(struct tcp_pcb *pcb, int local, ip_add
 
 #define tcp_dbg_get_tcp_state(pcb) ((pcb)->state)
 
+enum tcp_list_state {
+  ACTIVE_LIST,
+  LISTEN_LIST,
+  TIME_WAIT_LIST,
+};
+
+struct tcp_pcb_dp {
+  uint32_t state;
+  uint32_t lip;
+  uint32_t rip;
+  uint16_t l_port;
+  uint16_t r_port;
+  uint32_t r_next;
+  uint32_t s_next;
+  uint32_t tcp_sub_state;
+};
+
+void tcp_get_conn(char *buf, int32_t len, uint32_t *conn_num);
+uint32_t tcp_get_conn_num(void);
+
 /* for compatibility with older implementation */
 #define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6)
 
diff --git a/src/include/lwip/tcpip.h b/src/include/lwip/tcpip.h
index 30ce4fe..76e99c1 100644
--- a/src/include/lwip/tcpip.h
+++ b/src/include/lwip/tcpip.h
@@ -51,7 +51,7 @@ extern "C" {
 
 #if LWIP_TCPIP_CORE_LOCKING
 /** The global semaphore to lock the stack. */
-extern sys_mutex_t lock_tcpip_core;
+extern PER_THREAD sys_mutex_t lock_tcpip_core;
 #if !defined LOCK_TCPIP_CORE || defined __DOXYGEN__
 /** Lock lwIP core mutex (needs @ref LWIP_TCPIP_CORE_LOCKING 1) */
 #define LOCK_TCPIP_CORE()     sys_mutex_lock(&lock_tcpip_core)
diff --git a/src/include/lwip/timeouts.h b/src/include/lwip/timeouts.h
index b601f9e..b451554 100644
--- a/src/include/lwip/timeouts.h
+++ b/src/include/lwip/timeouts.h
@@ -119,6 +119,10 @@ struct sys_timeo** sys_timeouts_get_next_timeout(void);
 void lwip_cyclic_timer(void *arg);
 #endif
 
+#if USE_LIBOS
+void sys_timer_run(void);
+#endif /* USE_LIBOS */
+
 #endif /* LWIP_TIMERS */
 
 #ifdef __cplusplus
diff --git a/src/include/lwiplog.h b/src/include/lwiplog.h
new file mode 100644
index 0000000..363e516
--- /dev/null
+++ b/src/include/lwiplog.h
@@ -0,0 +1,81 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __LWIPLOG_H__
+#define __LWIPLOG_H__
+
+#include <stdio.h>
+#include <sys/syscall.h>
+
+#include <rte_log.h>
+
+#include "lwipopts.h"
+
+#define gettid()    syscall(__NR_gettid)
+
+#if USE_DPDK_LOG
+
+#define LWIP_LOG_WARN   LWIP_DBG_LEVEL_WARNING
+#define LWIP_LOG_ERROR  LWIP_DBG_LEVEL_SERIOUS
+#define LWIP_LOG_FATAL  LWIP_DBG_LEVEL_SEVERE
+
+#define LWIP_PLATFORM_LOG(level, fmt, ...) \
+do { \
+    if ((level) & LWIP_LOG_FATAL) { \
+        RTE_LOG(ERR, EAL, fmt, ##__VA_ARGS__); \
+        abort();                             \
+    } else if ((level) & LWIP_LOG_ERROR) { \
+        RTE_LOG(ERR, EAL, fmt, ##__VA_ARGS__); \
+    } else if ((level) & LWIP_LOG_WARN) { \
+        RTE_LOG(WARNING, EAL, fmt, ##__VA_ARGS__); \
+    } else { \
+        RTE_LOG(INFO, EAL, fmt, ##__VA_ARGS__); \
+    } \
+} while(0)
+
+
+#define LWIP_PLATFORM_DIAG(x)
+
+#define ESC_ARGS(...) __VA_ARGS__
+#define STRIP_BRACES(args) args
+
+#define LWIP_PLATFORM_ASSERT(x) \
+do { LWIP_PLATFORM_LOG(LWIP_LOG_FATAL, "Assertion \"%s\" failed at line %d in %s\n", \
+     x, __LINE__, __FILE__); abort();} while(0)
+
+#else
+
+#define LWIP_PLATFORM_LOG(debug, message)
+
+#endif /* USE_DPDK_LOG */
+
+#endif /* __LWIPLOG_H__ */
diff --git a/src/include/lwipopts.h b/src/include/lwipopts.h
index 4ab26f2..8893a5f 100644
--- a/src/include/lwipopts.h
+++ b/src/include/lwipopts.h
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * 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,
@@ -11,70 +11,193 @@
  *    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. 
+ *    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 
+ * 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: Simon Goldschmidt
+ *
+ * Author: Huawei Technologies
  *
  */
-#ifndef LWIP_HDR_LWIPOPTS_H__
-#define LWIP_HDR_LWIPOPTS_H__
-
-/* Prevent having to link sys_arch.c (we don't test the API layers in unit tests) */
-#define NO_SYS                          1
-#define LWIP_NETCONN                    0
-#define LWIP_SOCKET                     0
-#define SYS_LIGHTWEIGHT_PROT            0
-
-#define LWIP_IPV6                       1
-#define IPV6_FRAG_COPYHEADER            1
-#define LWIP_IPV6_DUP_DETECT_ATTEMPTS   0
-
-/* Enable some protocols to test them */
-#define LWIP_DHCP                       1
-#define LWIP_AUTOIP                     1
-
-#define LWIP_IGMP                       1
-#define LWIP_DNS                        1
-
-#define LWIP_ALTCP                      1
-
-/* Turn off checksum verification of fuzzed data */
-#define CHECKSUM_CHECK_IP               0
-#define CHECKSUM_CHECK_UDP              0
-#define CHECKSUM_CHECK_TCP              0
-#define CHECKSUM_CHECK_ICMP             0
-#define CHECKSUM_CHECK_ICMP6            0
-
-/* Minimal changes to opt.h required for tcp unit tests: */
-#define MEM_SIZE                        16000
-#define TCP_SND_QUEUELEN                40
-#define MEMP_NUM_TCP_SEG                TCP_SND_QUEUELEN
-#define TCP_OVERSIZE                    1
-#define TCP_SND_BUF                     (12 * TCP_MSS)
-#define TCP_WND                         (10 * TCP_MSS)
-#define LWIP_WND_SCALE                  1
-#define TCP_RCV_SCALE                   2
-#define PBUF_POOL_SIZE                  400 /* pbuf tests need ~200KByte */
-
-/* Minimal changes to opt.h required for etharp unit tests: */
-#define ETHARP_SUPPORT_STATIC_ENTRIES   1
-
-#define LWIP_NUM_NETIF_CLIENT_DATA      1
-#define LWIP_SNMP                       1
-#define MIB2_STATS                      1
-#define LWIP_MDNS_RESPONDER             1
-
-#endif /* LWIP_HDR_LWIPOPTS_H__ */
+
+#ifndef __LWIPOPTS_H__
+#define __LWIPOPTS_H__
+
+#define LWIP_TCPIP_CORE_LOCKING 1
+
+#define LWIP_NETCONN_SEM_PER_THREAD 0
+
+#define LWIP_TCP 1
+
+#define LWIP_SO_SENTIMEO 0
+
+#define LIP_SO_LINGER 0
+
+#define MEMP_USE_CUSTOM_POOLS 0
+#define MEM_USE_POOLS 0
+
+#define PER_TCP_PCB_BUFFER (16 * 128)
+
+#define MAX_CLIENTS (20000)
+
+#define RESERVED_CLIENTS (2000)
+
+#define MEMP_NUM_TCP_PCB (MAX_CLIENTS + RESERVED_CLIENTS)
+
+/* we use PBUF_POOL instead of PBUF_RAM in tcp_write, so reduce PBUF_RAM size,
+ * and do NOT let PBUF_POOL_BUFSIZE less then TCP_MSS
+*/
+#define MEM_SIZE (((PER_TCP_PCB_BUFFER + 128) * MEMP_NUM_TCP_SEG) >> 2)
+
+#define MEMP_NUM_TCP_PCB_LISTEN 3000
+
+#define MEMP_NUM_TCP_SEG (128 * 128 * 2)
+
+#define MEMP_NUM_NETCONN (MAX_CLIENTS + RESERVED_CLIENTS)
+
+#define MEMP_NUM_SYS_SEM (MAX_CLIENTS + RESERVED_CLIENTS)
+
+#define MEMP_NUM_SYS_MBOX (MAX_CLIENTS + RESERVED_CLIENTS)
+
+#define PBUF_POOL_SIZE (MAX_CLIENTS * 2)
+
+#define MEMP_MEM_MALLOC 0
+
+#define LWIP_ARP 1
+
+#define ETHARP_SUPPORT_STATIC_ENTRIES 1
+
+#define LWIP_IPV4 1
+
+#define IP_FORWARD 0
+
+#define IP_REASSEMBLY 1
+
+#define LWIP_UDP 0
+
+#define LWIP_TCP 1
+
+#define IP_HLEN 20
+
+#define TCP_HLEN 20
+
+#define FRAME_MTU 1500
+
+#define TCP_MSS (FRAME_MTU - IP_HLEN - TCP_HLEN)
+
+#define TCP_WND (40 * TCP_MSS)
+
+#define TCP_SND_BUF (5 * TCP_MSS)
+
+#define TCP_SND_QUEUELEN (8191)
+
+#define TCP_SNDLOWAT (TCP_SND_BUF / 5)
+
+#define TCP_SNDQUEUELOWAT (TCP_SND_QUEUELEN / 5)
+
+#define TCP_LISTEN_BACKLOG 1
+
+#define TCP_DEFAULT_LISTEN_BACKLOG 0xff
+
+#define TCP_OVERSIZE 0
+
+#define LWIP_NETIF_API 1
+
+#define DEFAULT_TCP_RECVMBOX_SIZE 128
+
+#define DEFAULT_ACCEPTMBOX_SIZE 1024
+
+#define LWIP_NETCONN 1
+
+#define LWIP_TCPIP_TIMEOUT 0
+
+#define LWIP_SOCKET 1
+
+#define LWIP_TCP_KEEPALIVE 1
+
+#define LWIP_STATS 1
+
+#define LWIP_STATS_DISPLAY 1
+
+#define CHECKSUM_GEN_IP 1 /*  master switch */
+
+#define CHECKSUM_GEN_TCP 1 /* master switch */
+
+#define CHECKSUM_CHECK_IP 1 /*  master switch */
+
+#define CHECKSUM_CHECK_TCP 1 /*  master switch */
+
+#define LWIP_TIMEVAL_PRIVATE 0
+
+#define USE_LIBOS 1
+
+#define LWIP_DEBUG 1
+
+#define LWIP_PERF 1
+
+#define LWIP_RECORD_PERF 0
+
+#define LWIP_SOCKET_POLL   0
+
+#define USE_LIBOS_ZC_RING 0
+
+#define SO_REUSE 1
+
+#define SIOCSHIWAT 1
+
+#define O_NONBLOCK 04000 /* same as define in bits/fcntl-linux.h */
+
+#define O_NDELAY O_NONBLOCK
+
+#define FIONBIO 0x5421 /* same as define in asm-generic/ioctls.h */
+
+#define LWIP_SUPPORT_CUSTOM_PBUF 1
+
+#define MEM_LIBC_MALLOC 0
+
+#define LWIP_TIMERS 1
+
+#define TCPIP_MBOX_SIZE (MEMP_NUM_TCPIP_MSG_API)
+
+#define TCP_PCB_HASH 1
+
+#define USE_DPDK_LOG 1
+
+#define LWIP_EPOOL_WAIT_MAX_EVENTS 30
+
+#define ARP_TABLE_SIZE 512
+
+/*
+   ---------------------------------------
+   ------- Syscall thread options --------
+   ---------------------------------------
+*/
+#define USE_SYSCALL_THREAD 1
+
+#define MAX_BLOCKING_ACCEPT_FD (100)
+
+#define MAX_BLOCKING_CONNECT_FD (100)
+
+#define MAX_BLOCKING_EPOLL_FD (100)
+
+#define MAX_SYSCALL_EVENTS (MAX_BLOCKING_ACCEPT_FD + MAX_BLOCKING_CONNECT_FD + MAX_BLOCKING_EPOLL_FD)
+
+#define MAX_HOST_FD (MAX_CLIENTS + RESERVED_CLIENTS)
+
+#if USE_LIBOS
+#define PER_THREAD __thread
+#else
+#define PER_THREAD
+#endif
+
+#endif /* __LWIPOPTS_H__ */
diff --git a/src/include/lwipsock.h b/src/include/lwipsock.h
new file mode 100644
index 0000000..dbc67b9
--- /dev/null
+++ b/src/include/lwipsock.h
@@ -0,0 +1,155 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __LWIPSOCK_H__
+#define __LWIPSOCK_H__
+
+#include "lwip/opt.h"
+#include "lwip/api.h"
+
+#include "posix_api.h"
+#include "eventpoll.h"
+
+/* move some definitions to the lwipsock.h for libnet to use, and
+ * at the same time avoid conflict between lwip/sockets.h and sys/socket.h
+ */
+
+/* --------------------------------------------------
+ * the following definition is copied from lwip/priv/tcpip_priv.h
+ * --------------------------------------------------
+ */
+
+/** This is overridable for the rare case where more than 255 threads
+ * select on the same socket...
+ */
+#ifndef SELWAIT_T
+#define SELWAIT_T u8_t
+#endif
+
+union lwip_sock_lastdata {
+  struct netbuf *netbuf;
+  struct pbuf *pbuf;
+};
+
+/** Contains all internal pointers and states used for a socket */
+struct lwip_sock {
+  /** sockets currently are built on netconns, each socket has one netconn */
+  struct netconn *conn;
+  /** data that was left from the previous read */
+  union lwip_sock_lastdata lastdata;
+#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
+  /** number of times data was received, set by event_callback(),
+      tested by the receive and select functions */
+  s16_t rcvevent;
+  /** number of times data was ACKed (free send buffer), set by event_callback(),
+      tested by select */
+  u16_t sendevent;
+  /** error happened for this socket, set by event_callback(), tested by select */
+  u16_t errevent;
+  /** counter of how many threads are waiting for this socket using select */
+  SELWAIT_T select_waiting;
+#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
+#if LWIP_NETCONN_FULLDUPLEX
+  /* counter of how many threads are using a struct lwip_sock (not the 'int') */
+  u8_t fd_used;
+  /* status of pending close/delete actions */
+  u8_t fd_free_pending;
+#define LWIP_SOCK_FD_FREE_TCP  1
+#define LWIP_SOCK_FD_FREE_FREE 2
+#endif
+
+#if USE_LIBOS
+  struct list_node list;
+  /* registered events */
+  uint32_t epoll;
+  /* available events */
+  uint32_t events;
+  epoll_data_t ep_data;
+  /* libos_epoll pointer in use */
+  struct libos_epoll *epoll_data;
+#endif
+};
+
+#ifndef set_errno
+#define set_errno(err) do { if (err) { errno = (err); } } while(0)
+#endif
+
+
+/* --------------------------------------------------
+ * --------------- LIBNET references ----------------
+ * --------------------------------------------------
+ */
+#if USE_LIBOS
+extern uint32_t sockets_num;
+extern struct lwip_sock *sockets;
+/**
+ * Map a externally used socket index to the internal socket representation.
+ *
+ * @param s externally used socket index
+ * @return struct lwip_sock for the socket or NULL if not found
+ */
+static inline struct lwip_sock *
+get_socket_without_errno(int s)
+{
+  struct lwip_sock *sock = NULL;
+
+  s -= LWIP_SOCKET_OFFSET;
+
+  if ((s < 0) || (s >= sockets_num)) {
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s + LWIP_SOCKET_OFFSET));
+    return NULL;
+  }
+
+  sock = &sockets[s];
+
+  if (!sock->conn) {
+    LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET));
+    return NULL;
+  }
+
+  return sock;
+}
+#endif /* USE_LIBOS */
+
+struct lwip_sock *get_socket(int s);
+struct lwip_sock *get_socket_by_fd(int s);
+void lwip_sock_init(void);
+void lwip_exit(void);
+
+extern int is_host_ipv4(uint32_t ipv4);
+extern int rearm_host_fd(int fd);
+extern int rearm_accept_fd(int fd);
+extern void unarm_host_fd(int fd);
+extern void clean_host_fd(int fd);
+extern int arm_host_fd(struct libos_epoll *ep, int op, int fd, struct epoll_event *event);
+
+#endif /* __LWIPSOCK_H__ */
diff --git a/src/include/memp_def.h b/src/include/memp_def.h
new file mode 100644
index 0000000..082f685
--- /dev/null
+++ b/src/include/memp_def.h
@@ -0,0 +1,66 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __MEMP_DEF_H__
+#define __MEMP_DEF_H__
+
+#include "lwip/opt.h"
+#include "arch/cc.h"
+
+#define LWIP_MEMPOOL_BASE_DECLARE(name) \
+    extern void alloc_memp_##name##_base(void);
+
+#define LWIP_MEM_MEMORY_DECLARE(name) \
+    extern void alloc_memory_##name(void);
+
+#define LWIP_MEMPOOL_BASE_INIT(name) \
+    alloc_memp_##name##_base();
+
+#define LWIP_MEM_MEMORY_INIT(name) \
+    alloc_memory_##name();
+
+#define LWIP_MEMPOOL(name, num, size, desc) LWIP_MEMPOOL_BASE_DECLARE(name)
+#include <lwip/priv/memp_std.h>
+#undef LWIP_MEMPOOL
+
+static inline void hugepage_init(void)
+{
+#define LWIP_MEMPOOL(name,num,size,desc)  LWIP_MEMPOOL_BASE_INIT(name)
+#include "lwip/priv/memp_std.h"
+
+#if !MEM_LIBC_MALLOC
+	LWIP_MEM_MEMORY_DECLARE(ram_heap)
+    LWIP_MEM_MEMORY_INIT(ram_heap)
+#endif /* MEM_LIBC_MALLOC */
+}
+
+#endif /* __MEMP_DEF_H__ */
diff --git a/src/include/posix_api.h b/src/include/posix_api.h
new file mode 100644
index 0000000..8aa8516
--- /dev/null
+++ b/src/include/posix_api.h
@@ -0,0 +1,88 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __POSIX_API_H__
+#define __POSIX_API_H__
+
+#include <signal.h>
+#include <poll.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+
+typedef struct {
+    void *handle;
+    int (*socket_fn)(int domain, int type, int protocol);
+    int (*accept_fn)(int s, struct sockaddr*, socklen_t*);
+    int (*accept4_fn)(int s, struct sockaddr *addr, socklen_t *addrlen, int flags);
+    int (*bind_fn)(int s, const struct sockaddr*, socklen_t);
+    int (*listen_fn)(int s, int backlog);
+    int (*connect_fn)(int s, const struct sockaddr *name, socklen_t namelen);
+    int (*getpeername_fn)(int s, struct sockaddr *name, socklen_t *namelen);
+    int (*getsockname_fn)(int s, struct sockaddr *name, socklen_t *namelen);
+    int (*setsockopt_fn)(int s, int level, int optname, const void *optval, socklen_t optlen);
+    int (*getsockopt_fn)(int s, int level, int optname, void *optval, socklen_t *optlen);
+    int (*shutdown_fn)(int s, int how);
+    int (*close_fn)(int fd);
+    pid_t (*fork_fn)(void);
+    ssize_t (*read_fn)(int fd, void *mem, size_t len);
+    ssize_t (*write_fn)(int fd, const void *data, size_t len);
+    ssize_t (*recv_fn)(int sockfd, void *buf, size_t len, int flags);
+    ssize_t (*send_fn)(int sockfd, const void *buf, size_t len, int flags);
+    ssize_t (*recv_msg)(int sockfd, const struct msghdr *msg, int flags);
+    ssize_t (*send_msg)(int sockfd, const struct msghdr *msg, int flags);
+    ssize_t (*recv_from)(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
+    ssize_t (*send_to)(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, 
+        socklen_t addrlen);
+    int (*fcntl_fn)(int fd, int cmd, ...);
+    int (*fcntl64_fn)(int fd, int cmd, ...);
+    int (*pipe_fn)(int pipefd[2]);
+    int (*epoll_create_fn)(int size);
+    int (*epoll_ctl_fn)(int epfd, int op, int fd, struct epoll_event *event);
+    int (*epoll_wait_fn)(int epfd, struct epoll_event *events, int maxevents, int timeout);
+    int (*epoll_close_fn)(int epfd);
+    int (*eventfd_fn)(unsigned int initval, int flags);
+    int (*is_epfd)(int fd);
+    struct lwip_sock* (*get_socket)(int fd);
+    int (*sigaction_fn)(int signum, const struct sigaction *act, struct sigaction *oldact);
+    int (*poll_fn)(struct pollfd *fds, nfds_t nfds, int timeout);
+    int (*ioctl_fn)(int fd, int cmd, ...);
+
+    int is_chld;
+} posix_api_t;
+
+posix_api_t *posix_api;
+
+int posix_api_init(void);
+void posix_api_free(void);
+void posix_api_fork(void);
+
+#endif /* __POSIX_API_H__ */
diff --git a/src/include/reg_sock.h b/src/include/reg_sock.h
new file mode 100644
index 0000000..76d4c48
--- /dev/null
+++ b/src/include/reg_sock.h
@@ -0,0 +1,62 @@
+/*
+ * 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: Huawei Technologies
+ *
+ */
+
+#ifndef __REG_SOCK_H__
+#define __REG_SOCK_H__
+
+enum reg_ring_type {
+    REG_RING_TCP_LISTEN = 0,
+    REG_RING_TCP_LISTEN_CLOSE,
+    REG_RING_TCP_CONNECT,
+    REG_RING_TCP_CONNECT_CLOSE,
+    RING_REG_MAX,
+};
+
+struct libnet_quintuple {
+	uint32_t protocol;
+    /* net byte order */
+    uint16_t src_port;
+    uint16_t dst_port;
+    uint32_t src_ip;
+    uint32_t dst_ip;
+};
+
+struct reg_ring_msg {
+    enum reg_ring_type type;
+
+    uint32_t tid;
+    struct libnet_quintuple qtuple;
+};
+
+extern int vdev_reg_xmit(enum reg_ring_type type, struct libnet_quintuple *qtuple);
+
+#endif /* __REG_SOCK_H__ */
\ No newline at end of file
diff --git a/src/netif/dir.mk b/src/netif/dir.mk
index 233c79a..f585d5e 100644
--- a/src/netif/dir.mk
+++ b/src/netif/dir.mk
@@ -1,3 +1,3 @@
-SRC = ethernet.c
+SRC = ethernet.c 
 
 $(eval $(call register_dir, netif, $(SRC)))
-- 
1.8.3.1

