From 7c6d623f4009ec40349504281b9af396d05418ec Mon Sep 17 00:00:00 2001
From: jiangheng <jiangheng14@huawei.com>
Date: Mon, 9 Oct 2023 11:36:34 +0800
Subject: [PATCH] preload: support thread hijacking mode

---
 src/lstack/api/lstack_wrap.c        | 208 ++++++++++------------------
 src/lstack/core/lstack_cfg.c        |   3 +-
 src/lstack/core/lstack_init.c       |   2 +-
 src/lstack/core/lstack_preload.c    | 114 ++++++++++++++-
 src/lstack/include/lstack_preload.h |   9 ++
 5 files changed, 202 insertions(+), 134 deletions(-)

diff --git a/src/lstack/api/lstack_wrap.c b/src/lstack/api/lstack_wrap.c
index 236c689..ab39a68 100644
--- a/src/lstack/api/lstack_wrap.c
+++ b/src/lstack/api/lstack_wrap.c
@@ -40,73 +40,15 @@
 #include "gazelle_base_func.h"
 #include "lstack_thread_rpc.h"
 
+#include "lstack_preload.h"
+
 #ifndef SOCK_TYPE_MASK
 #define SOCK_TYPE_MASK 0xf
 #endif
 
-enum KERNEL_LWIP_PATH {
-    PATH_KERNEL = 0,
-    PATH_LWIP,
-    PATH_UNKNOW,
-};
-
-static inline enum KERNEL_LWIP_PATH select_path(int fd, struct lwip_sock **socket)
-{
-    if (unlikely(posix_api == NULL)) {
-        /*
-        * posix api maybe call before gazelle init
-        * So, we must call posix_api_init at the head of select_path
-        */
-        if (posix_api_init() != 0) {
-            LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n");
-        }
-        return PATH_KERNEL;
-    }
-
-    if (unlikely(posix_api->ues_posix)) {
-        return PATH_KERNEL;
-    }
-
-    struct lwip_sock *sock = get_socket_by_fd(fd);
-
-    /* AF_UNIX case */
-    if (!sock || !sock->conn || CONN_TYPE_IS_HOST(sock->conn)) {
-        return PATH_KERNEL;
-    }
-
-    if (socket) {
-        *socket = sock;
-    }
-
-    if (likely(CONN_TYPE_IS_LIBOS(sock->conn))) {
-        return PATH_LWIP;
-    }
-
-    if (NETCONN_IS_UDP(sock)) {
-        return PATH_LWIP;
-    } else {
-        struct tcp_pcb *pcb = sock->conn->pcb.tcp;
-        /* after lwip connect, call send immediately, pcb->state is SYN_SENT, need return PATH_LWIP */
-        /* pcb->state default value is CLOSED when call socket, need return PATH_UNKNOW */
-        if (pcb != NULL && pcb->state <= ESTABLISHED && pcb->state >= LISTEN) {
-            return PATH_LWIP;
-        }
-    }
-
-    return PATH_UNKNOW;
-}
-
 static inline int32_t do_epoll_create1(int32_t flags)
 {
-    if (posix_api == NULL) {
-        /* posix api maybe call before gazelle init */
-        if (posix_api_init() != 0) {
-            LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n");
-        }
-        return posix_api->epoll_create1_fn(flags);
-    }
-
-    if (unlikely(posix_api->ues_posix)) {
+    if (select_posix_path() == PATH_KERNEL) {
         return posix_api->epoll_create1_fn(flags);
     }
 
@@ -115,15 +57,7 @@ static inline int32_t do_epoll_create1(int32_t flags)
 
 static inline int32_t do_epoll_create(int32_t size)
 {
-    if (posix_api == NULL) {
-        /* posix api maybe call before gazelle init */
-        if (posix_api_init() != 0) {
-            LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n");
-        }
-        return posix_api->epoll_create_fn(size);
-    }
-
-    if (unlikely(posix_api->ues_posix)) {
+    if (select_posix_path() == PATH_KERNEL) {
         return posix_api->epoll_create_fn(size);
     }
 
@@ -132,7 +66,7 @@ static inline int32_t do_epoll_create(int32_t size)
 
 static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct epoll_event* event)
 {
-    if (unlikely(posix_api->ues_posix)) {
+    if (select_posix_path() == PATH_KERNEL) {
         return posix_api->epoll_ctl_fn(epfd, op, fd, event);
     }
 
@@ -141,7 +75,7 @@ static inline int32_t do_epoll_ctl(int32_t epfd, int32_t op, int32_t fd, struct
 
 static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, int32_t maxevents, int32_t timeout)
 {
-    if (unlikely(posix_api->ues_posix)) {
+    if (select_posix_path() == PATH_KERNEL) {
         return posix_api->epoll_wait_fn(epfd, events, maxevents, timeout);
     }
 
@@ -158,8 +92,7 @@ static inline int32_t do_epoll_wait(int32_t epfd, struct epoll_event* events, in
 
 static inline int32_t do_accept(int32_t s, struct sockaddr *addr, socklen_t *addrlen)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_KERNEL) {
+    if (select_fd_posix_path(s, NULL) == PATH_KERNEL) {
         return posix_api->accept_fn(s, addr, addrlen);
     }
 
@@ -177,8 +110,7 @@ static int32_t do_accept4(int32_t s, struct sockaddr *addr, socklen_t *addrlen,
         GAZELLE_RETURN(EINVAL);
     }
 
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_KERNEL) {
+    if (select_fd_posix_path(s, NULL) == PATH_KERNEL) {
         return posix_api->accept4_fn(s, addr, addrlen, flags);
     }
 
@@ -219,22 +151,21 @@ static int32_t do_bind(int32_t s, const struct sockaddr *name, socklen_t namelen
     }
 
     struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_KERNEL) {
+    if (select_fd_posix_path(s, &sock) == PATH_KERNEL) {
         return posix_api->bind_fn(s, name, namelen);
     }
 
-    int32_t ret = posix_api->bind_fn(s, name, namelen);
-    if (ret < 0) {
-        /* ip is not lstack, just return */
-        if (!match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) {
-            return ret;
+    if (match_host_addr(((struct sockaddr_in *)name)->sin_addr.s_addr)) {
+        /* maybe kni addr */
+        posix_api->bind_fn(s, name, namelen);
+        if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) {
+            return stack_broadcast_bind(s, name, namelen);
+        } else {
+            return stack_single_bind(s, name, namelen);
         }
-    }
-
-    if (NETCONN_IS_UDP(sock) && get_global_cfg_params()->listen_shadow) {
-        return stack_broadcast_bind(s, name, namelen);
     } else {
-        return stack_single_bind(s, name, namelen);
+        SET_CONN_TYPE_HOST(sock->conn);
+        return posix_api->bind_fn(s, name, namelen);
     }
 }
 
@@ -299,7 +230,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name
     }
 
     struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_KERNEL) {
+    if (select_fd_posix_path(s, &sock) == PATH_KERNEL) {
         return posix_api->connect_fn(s, name, namelen);
     }
 
@@ -309,6 +240,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name
     }
 
     if (!netconn_is_nonblocking(sock->conn)) {
+        LSTACK_LOG(ERR, LSTACK, "connect does not support blocking fd currently\n");
         GAZELLE_RETURN(EINVAL);
     }
 
@@ -330,8 +262,7 @@ static int32_t do_connect(int32_t s, const struct sockaddr *name, socklen_t name
 
 static inline int32_t do_listen(int32_t s, int32_t backlog)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_KERNEL) {
+    if (select_fd_posix_path(s, NULL) == PATH_KERNEL) {
         return posix_api->listen_fn(s, backlog);
     }
 
@@ -355,8 +286,7 @@ static inline int32_t do_getpeername(int32_t s, struct sockaddr *name, socklen_t
         GAZELLE_RETURN(EINVAL);
     }
 
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_LWIP) {
+    if (select_fd_posix_path(s, NULL) == PATH_LWIP) {
         return rpc_call_getpeername(s, name, namelen);
     }
 
@@ -369,8 +299,7 @@ static inline int32_t do_getsockname(int32_t s, struct sockaddr *name, socklen_t
         GAZELLE_RETURN(EINVAL);
     }
 
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_LWIP) {
+    if (select_fd_posix_path(s, NULL) == PATH_LWIP) {
         return rpc_call_getsockname(s, name, namelen);
     }
 
@@ -391,8 +320,7 @@ static bool unsupport_optname(int32_t optname)
 
 static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, void *optval, socklen_t *optlen)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_LWIP && !unsupport_optname(optname)) {
+    if (select_fd_posix_path(s, NULL) == PATH_LWIP && !unsupport_optname(optname)) {
         return rpc_call_getsockopt(s, level, optname, optval, optlen);
     }
 
@@ -401,8 +329,7 @@ static inline int32_t do_getsockopt(int32_t s, int32_t level, int32_t optname, v
 
 static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, const void *optval, socklen_t optlen)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_KERNEL || unsupport_optname(optname)) {
+    if (select_fd_posix_path(s, NULL) == PATH_KERNEL || unsupport_optname(optname)) {
         return posix_api->setsockopt_fn(s, level, optname, optval, optlen);
     }
 
@@ -417,13 +344,27 @@ static inline int32_t do_setsockopt(int32_t s, int32_t level, int32_t optname, c
 
 static inline int32_t do_socket(int32_t domain, int32_t type, int32_t protocol)
 {
-    if ((domain != AF_INET && domain != AF_UNSPEC)
-        || ((type & SOCK_DGRAM) && !get_global_cfg_params()->udp_enable)
-        || posix_api->ues_posix) {
+    int32_t ret;
+    /* process not init completed or not hajacking thread */
+    if (select_posix_path() == PATH_KERNEL) {
+        return posix_api->socket_fn(domain, type, protocol);
+    }
+
+    if ((domain != AF_INET && domain != AF_UNSPEC) ||
+        ((type & SOCK_DGRAM) && !get_global_cfg_params()->udp_enable)) {
         return posix_api->socket_fn(domain, type, protocol);
     }
 
-    return rpc_call_socket(domain, type, protocol);
+    ret = rpc_call_socket(domain, type, protocol);
+    /* if udp_enable = 1 in lstack.conf, udp protocol must be in user path currently */
+    if ((ret >= 0) && (type & SOCK_DGRAM)) {
+        struct lwip_sock *sock = get_socket(ret);
+        if (sock != NULL && sock->conn != NULL) {
+            SET_CONN_TYPE_LIBOS(sock->conn);
+        }
+    }
+
+    return ret;
 }
 
 static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t flags)
@@ -436,12 +377,12 @@ static inline ssize_t do_recv(int32_t sockfd, void *buf, size_t len, int32_t fla
         return 0;
     }
 
-    struct lwip_sock *sock = NULL;
-    if (select_path(sockfd, &sock) == PATH_LWIP) {
-        return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL);
+    if (select_posix_path() == PATH_KERNEL || // maybe fd is created by open before posix_api_init called
+        select_fd_posix_path(sockfd, NULL) == PATH_KERNEL) {
+        return posix_api->recv_fn(sockfd, buf, len, flags);
     }
 
-    return posix_api->recv_fn(sockfd, buf, len, flags);
+    return do_lwip_read_from_stack(sockfd, buf, len, flags, NULL, NULL);
 }
 
 static inline ssize_t do_read(int32_t s, void *mem, size_t len)
@@ -454,17 +395,18 @@ static inline ssize_t do_read(int32_t s, void *mem, size_t len)
         return 0;
     }
 
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_LWIP) {
-        return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL);
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(s, NULL) == PATH_KERNEL) {
+        return posix_api->read_fn(s, mem, len);
     }
-    return posix_api->read_fn(s, mem, len);
+
+    return do_lwip_read_from_stack(s, mem, len, 0, NULL, NULL);
 }
 
 static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) != PATH_LWIP) {
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(s, NULL) == PATH_KERNEL) {
         return posix_api->readv_fn(s, iov, iovcnt);
     }
 
@@ -487,8 +429,8 @@ static inline ssize_t do_readv(int32_t s, const struct iovec *iov, int iovcnt)
 
 static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32_t flags)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(sockfd, &sock) != PATH_LWIP) {
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(sockfd, NULL) == PATH_KERNEL) {
         return posix_api->send_fn(sockfd, buf, len, flags);
     }
 
@@ -497,8 +439,8 @@ static inline ssize_t do_send(int32_t sockfd, const void *buf, size_t len, int32
 
 static inline ssize_t do_write(int32_t s, const void *mem, size_t size)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) != PATH_LWIP) {
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(s, NULL) == PATH_KERNEL) {
         return posix_api->write_fn(s, mem, size);
     }
 
@@ -507,8 +449,9 @@ static inline ssize_t do_write(int32_t s, const void *mem, size_t size)
 
 static inline ssize_t do_writev(int32_t s, const struct iovec *iov, int iovcnt)
 {
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) != PATH_LWIP) {
+    struct lwip_sock *sock;
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(s, &sock) == PATH_KERNEL) {
         return posix_api->writev_fn(s, iov, iovcnt);
     }
 
@@ -530,12 +473,12 @@ static inline ssize_t do_recvmsg(int32_t s, struct msghdr *message, int32_t flag
         GAZELLE_RETURN(EINVAL);
     }
 
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_LWIP) {
-        return do_lwip_recvmsg_from_stack(s, message, flags);
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(s, NULL) == PATH_KERNEL) {
+        return posix_api->recv_msg(s, message, flags);
     }
 
-    return posix_api->recv_msg(s, message, flags);
+    return do_lwip_recvmsg_from_stack(s, message, flags);
 }
 
 static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_t flags)
@@ -544,12 +487,13 @@ static inline ssize_t do_sendmsg(int32_t s, const struct msghdr *message, int32_
         GAZELLE_RETURN(EINVAL);
     }
 
-    struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_LWIP) {
-        return do_lwip_sendmsg_to_stack(sock, s, message, flags);
+    struct lwip_sock *sock;
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(s, &sock) == PATH_KERNEL) {
+        return posix_api->send_msg(s, message, flags);
     }
 
-    return posix_api->send_msg(s, message, flags);
+    return do_lwip_sendmsg_to_stack(sock, s, message, flags);
 }
 
 static inline ssize_t udp_recvfrom(struct lwip_sock *sock, int32_t sockfd, void *buf, size_t len, int32_t flags,
@@ -596,7 +540,7 @@ static inline ssize_t do_recvfrom(int32_t sockfd, void *buf, size_t len, int32_t
     }
 
     struct lwip_sock *sock = NULL;
-    if (select_path(sockfd, &sock) == PATH_LWIP) {
+    if (select_fd_posix_path(sockfd, &sock) == PATH_LWIP) {
         if (NETCONN_IS_UDP(sock)) {
             return udp_recvfrom(sock, sockfd, buf, len, flags, addr, addrlen);
         } else {
@@ -611,7 +555,7 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int
                                 const struct sockaddr *addr, socklen_t addrlen)
 {
     struct lwip_sock *sock = NULL;
-    if (select_path(sockfd, &sock) != PATH_LWIP) {
+    if (select_fd_posix_path(sockfd, &sock) != PATH_LWIP) {
         return posix_api->send_to(sockfd, buf, len, flags, addr, addrlen);
     }
 
@@ -621,7 +565,8 @@ static inline ssize_t do_sendto(int32_t sockfd, const void *buf, size_t len, int
 static inline int32_t do_close(int32_t s)
 {
     struct lwip_sock *sock = NULL;
-    if (select_path(s, &sock) == PATH_KERNEL) {
+    if (select_posix_path() == PATH_KERNEL ||
+        select_fd_posix_path(s, &sock) == PATH_KERNEL) {
         /* we called lwip_socket, even if kernel fd */
         if (posix_api != NULL && !posix_api->ues_posix &&
             /* contain posix_api->close_fn if success */
@@ -639,7 +584,7 @@ static inline int32_t do_close(int32_t s)
 
 static int32_t do_poll(struct pollfd *fds, nfds_t nfds, int32_t timeout)
 {
-    if (unlikely(posix_api->ues_posix) || fds == NULL || nfds == 0) {
+    if ((select_posix_path() == PATH_KERNEL) || fds == NULL || nfds == 0) {
         return posix_api->poll_fn(fds, nfds, timeout);
     }
 
@@ -684,7 +629,8 @@ static int32_t do_sigaction(int32_t signum, const struct sigaction *act, struct
         val = va_arg(ap, typeof(val)); \
         va_end(ap); \
         struct lwip_sock *sock = NULL; \
-        if (select_path(_fd, &sock) == PATH_KERNEL) \
+        if (select_posix_path() == PATH_KERNEL || \
+            select_fd_posix_path(_fd, &sock) == PATH_KERNEL) \
             return _fcntl_fn(_fd, _cmd, val); \
         int32_t ret = _fcntl_fn(_fd, _cmd, val); \
         if (ret == -1) \
diff --git a/src/lstack/core/lstack_cfg.c b/src/lstack/core/lstack_cfg.c
index 0eca86e..189459a 100644
--- a/src/lstack/core/lstack_cfg.c
+++ b/src/lstack/core/lstack_cfg.c
@@ -223,7 +223,8 @@ static int32_t parse_host_addr(void)
 int32_t match_host_addr(uint32_t addr)
 {
     /* network byte order */
-    if (addr == g_config_params.host_addr.addr) {
+    if (addr == g_config_params.host_addr.addr ||
+        addr == INADDR_ANY) {
         return 1;
     }
     return 0;
diff --git a/src/lstack/core/lstack_init.c b/src/lstack/core/lstack_init.c
index 2183e3a..b6e9bf1 100644
--- a/src/lstack/core/lstack_init.c
+++ b/src/lstack/core/lstack_init.c
@@ -285,7 +285,7 @@ __attribute__((constructor)) void gazelle_network_init(void)
     }
 
     if (stack_thread_setup() != 0) {
-        LSTACK_EXIT(1, "stack_init_in_setup failed\n");
+        LSTACK_EXIT(1, "stack_thread_setup failed\n");
     }
 
     /* lwip initialization */
diff --git a/src/lstack/core/lstack_preload.c b/src/lstack/core/lstack_preload.c
index e3a98fc..1d68501 100644
--- a/src/lstack/core/lstack_preload.c
+++ b/src/lstack/core/lstack_preload.c
@@ -12,8 +12,13 @@
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#define __USE_GNU
+#include <pthread.h>
+#include <securec.h>
 
-#include "securec.h"
+#include <lwip/posix_api.h>
+#include <lwip/lwipsock.h>
+#include <lwip/lwipopts.h>
 
 #include "lstack_log.h"
 #include "lstack_preload.h"
@@ -22,10 +27,17 @@
 #define LSTACK_SO_NAME              "liblstack.so"
 #define LSTACK_PRELOAD_NAME_LEN     PATH_MAX
 #define LSTACK_PRELOAD_ENV_PROC     "GAZELLE_BIND_PROCNAME"
+#define LSTACK_PRELOAD_ENV_THRD     "GAZELLE_THREAD_NAME"
+
+#define EXCLUDE_THRD_CNT            1
+const static char *g_exclude_thread[EXCLUDE_THRD_CNT] = {"eal-intr-thread"};
+static PER_THREAD enum KERNEL_LWIP_PATH g_preload_thrdpath = PATH_UNKNOW;
 
 struct lstack_preload {
     int32_t preload_switch;
     char env_procname[LSTACK_PRELOAD_NAME_LEN];
+    bool get_thrdname;
+    char env_thrdname[LSTACK_PRELOAD_NAME_LEN];
 };
 static struct lstack_preload g_preload_info = {0};
 
@@ -52,12 +64,104 @@ static int32_t preload_check_bind_proc(void)
     return -1;
 }
 
+static void preload_get_thrdname(void)
+{
+    g_preload_info.get_thrdname = true;
+
+    char *enval = NULL;
+    enval = getenv(LSTACK_PRELOAD_ENV_THRD);
+    if (enval == NULL) {
+        return;
+    }
+    if (strcpy_s(g_preload_info.env_thrdname, LSTACK_PRELOAD_NAME_LEN, enval) != EOK) {
+        return;
+    }
+
+    LSTACK_PRE_LOG(LSTACK_INFO, "thread name=%s ok\n", g_preload_info.env_thrdname);
+}
+
+enum KERNEL_LWIP_PATH select_fd_posix_path(int32_t fd, struct lwip_sock **socket)
+{
+    struct lwip_sock *sock = get_socket_by_fd(fd);
+
+    /* AF_UNIX case */
+    if (!sock || !sock->conn || CONN_TYPE_IS_HOST(sock->conn)) {
+        return PATH_KERNEL;
+    }
+
+    if (socket) {
+        *socket = sock;
+    }
+
+    if (likely(CONN_TYPE_IS_LIBOS(sock->conn))) {
+        return PATH_LWIP;
+    }
+
+    return PATH_UNKNOW;
+}
+
+enum KERNEL_LWIP_PATH select_posix_path(void)
+{
+    if (unlikely(posix_api == NULL)) {
+        /*
+        * posix api maybe call before gazelle init
+        * So, we must call posix_api_init at the head of select_path
+        */
+        if (posix_api_init() != 0) {
+            LSTACK_PRE_LOG(LSTACK_ERR, "posix_api_init failed\n");
+        }
+        return PATH_KERNEL;
+    }
+
+    if (unlikely(posix_api->ues_posix)) {
+        return PATH_KERNEL;
+    }
+
+    if (g_preload_thrdpath != PATH_UNKNOW) {
+        return g_preload_thrdpath;
+    }
+
+    if (!g_preload_info.get_thrdname) {
+        preload_get_thrdname();
+    }
+
+    char thread_name[PATH_MAX] = {0};
+    if (pthread_getname_np(pthread_self(), thread_name, PATH_MAX) != 0) {
+        g_preload_thrdpath = PATH_KERNEL;
+        return PATH_KERNEL;
+    }
+
+    /* exclude dpdk thread */
+    for (int i = 0; i < EXCLUDE_THRD_CNT; i++) {
+        if (strstr(thread_name, g_exclude_thread[i]) != NULL) {
+            g_preload_thrdpath = PATH_KERNEL;
+            return PATH_KERNEL;
+        }
+    }
+
+    /* not set GAZELLE_THREAD_NAME, select all thread */
+    if (g_preload_info.env_thrdname[0] == '\0') {
+        g_preload_thrdpath = PATH_LWIP;
+        return PATH_LWIP;
+    }
+
+    if (strstr(thread_name, g_preload_info.env_thrdname) == NULL) {
+        g_preload_thrdpath = PATH_KERNEL;
+        return PATH_KERNEL;
+    }
+
+    g_preload_thrdpath = PATH_LWIP;
+    return PATH_LWIP;
+}
+
 int preload_info_init(void)
 {
     char *enval = NULL;
 
     g_preload_info.preload_switch = 0;
 
+    preload_get_thrdname();
+
     enval = getenv(LSTACK_PRELOAD_ENV_SYS);
     if (enval == NULL) {
         return 0;
@@ -75,6 +179,14 @@ int preload_info_init(void)
         return -1;
     }
 
+    enval = getenv(LSTACK_PRELOAD_ENV_THRD);
+    if (enval != NULL) {
+        if (strcpy_s(g_preload_info.env_thrdname, LSTACK_PRELOAD_NAME_LEN, enval) != EOK) {
+            return -1;
+        }
+        g_preload_info.get_thrdname = true;
+    }
+
     g_preload_info.preload_switch = 1;
     LSTACK_PRE_LOG(LSTACK_INFO, "LD_PRELOAD ok\n");
     return preload_check_bind_proc();
diff --git a/src/lstack/include/lstack_preload.h b/src/lstack/include/lstack_preload.h
index 4ba6525..0ad7877 100644
--- a/src/lstack/include/lstack_preload.h
+++ b/src/lstack/include/lstack_preload.h
@@ -11,6 +11,15 @@
 */
 #ifndef __LSTACK_PRELOAD_H__
 #define __LSTACK_PRELOAD_H__
+#include <stdbool.h>
 
+enum KERNEL_LWIP_PATH {
+    PATH_KERNEL = 0,
+    PATH_LWIP,
+    PATH_UNKNOW,
+};
+
+enum KERNEL_LWIP_PATH select_posix_path(void);
+enum KERNEL_LWIP_PATH select_fd_posix_path(int32_t fd, struct lwip_sock **socket);
 int preload_info_init(void);
 #endif
-- 
2.23.0

