Projects
Eulaceura:Factory
lwip
_service:obs_scm:0002-adapt-lstack.patch
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0002-adapt-lstack.patch of Package lwip
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2