255 lines
7.9 KiB
Diff
255 lines
7.9 KiB
Diff
From 28f8ba80cd733e14e0540c414a18134b3c3fcc94 Mon Sep 17 00:00:00 2001
|
|
From: FanBin <fanbin12@huawei.com>
|
|
Date: Wed, 15 Feb 2023 10:09:39 +0800
|
|
Subject: [PATCH] lwip reuse ip port
|
|
|
|
---
|
|
src/core/tcp.c | 40 +++++++++++++++++++++++++++++---
|
|
src/core/tcp_in.c | 32 +++++++++++++++++++++++++
|
|
src/include/lwip/api.h | 4 ++++
|
|
src/include/lwip/priv/tcp_priv.h | 19 +++++++++++++++
|
|
src/include/lwip/tcp.h | 8 +++++++
|
|
src/include/lwipopts.h | 4 ++++
|
|
6 files changed, 104 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/core/tcp.c b/src/core/tcp.c
|
|
index b2bee67..2cc1174 100644
|
|
--- a/src/core/tcp.c
|
|
+++ b/src/core/tcp.c
|
|
@@ -111,6 +111,7 @@
|
|
#include "lwip/ip6.h"
|
|
#include "lwip/ip6_addr.h"
|
|
#include "lwip/nd6.h"
|
|
+#include "lwip/api.h"
|
|
|
|
#include <string.h>
|
|
#include <pthread.h>
|
|
@@ -772,6 +773,9 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
|
/* Check if the address already is in use (on all lists) */
|
|
for (i = 0; i < max_pcb_list; i++) {
|
|
for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
|
|
+#if REUSE_IPPORT
|
|
+ continue;
|
|
+#else
|
|
if (cpcb->local_port == port) {
|
|
#if SO_REUSE
|
|
/* Omit checking for the same port if both pcbs have REUSEADDR set.
|
|
@@ -790,6 +794,7 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
|
|
}
|
|
}
|
|
}
|
|
+#endif /* REUSE_IPORT */
|
|
}
|
|
}
|
|
}
|
|
@@ -921,7 +926,18 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
|
|
res = ERR_ALREADY;
|
|
goto done;
|
|
}
|
|
-#if SO_REUSE
|
|
+
|
|
+#if REUSE_IPPORT
|
|
+ struct tcp_pcb_listen *first_same_port_pcb = NULL;
|
|
+ for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
|
+ if ((lpcb->local_port == pcb->local_port) &&
|
|
+ ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
|
|
+ /* this address/port is already used */
|
|
+ first_same_port_pcb = lpcb;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
if (ip_get_option(pcb, SOF_REUSEADDR)) {
|
|
/* Since SOF_REUSEADDR allows reusing a local address before the pcb's usage
|
|
is declared (listen-/connection-pcb), we have to make sure now that
|
|
@@ -936,7 +952,7 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
|
|
}
|
|
}
|
|
}
|
|
-#endif /* SO_REUSE */
|
|
+#endif /* REUSE_IPPORT */
|
|
|
|
#if USE_LIBOS
|
|
vdev_reg_done(REG_RING_TCP_LISTEN, pcb);
|
|
@@ -955,6 +971,16 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
|
|
lpcb->netif_idx = pcb->netif_idx;
|
|
lpcb->ttl = pcb->ttl;
|
|
lpcb->tos = pcb->tos;
|
|
+
|
|
+#if REUSE_IPPORT
|
|
+ lpcb->connect_num = 0;
|
|
+ lpcb->next_same_port_pcb = NULL;
|
|
+
|
|
+ struct netconn* conn = pcb->callback_arg;
|
|
+ lpcb->socket_fd = conn->socket;
|
|
+ lpcb->master_lpcb = conn->is_master_fd;
|
|
+#endif
|
|
+
|
|
#if LWIP_VLAN_PCP
|
|
lpcb->netif_hints.tci = pcb->netif_hints.tci;
|
|
#endif /* LWIP_VLAN_PCP */
|
|
@@ -982,7 +1008,15 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
|
|
lpcb->accepts_pending = 0;
|
|
tcp_backlog_set(lpcb, backlog);
|
|
#endif /* TCP_LISTEN_BACKLOG */
|
|
- TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
|
|
+
|
|
+#if REUSE_IPPORT
|
|
+ if (first_same_port_pcb != NULL) {
|
|
+ TCP_REG_SAMEPORT((struct tcp_pcb_listen *)first_same_port_pcb, (struct tcp_pcb_listen *)lpcb);
|
|
+ } else
|
|
+#endif
|
|
+ {
|
|
+ TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
|
|
+ }
|
|
res = ERR_OK;
|
|
done:
|
|
if (err != NULL) {
|
|
diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c
|
|
index ef95238..77dd235 100644
|
|
--- a/src/core/tcp_in.c
|
|
+++ b/src/core/tcp_in.c
|
|
@@ -356,6 +356,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|
}
|
|
}
|
|
|
|
+#if REUSE_IPPORT
|
|
+ struct tcp_pcb_listen *min_cnts_lpcb = NULL;
|
|
+#endif
|
|
/* Finally, if we still did not get a match, we check all PCBs that
|
|
are LISTENing for incoming connections. */
|
|
prev = NULL;
|
|
@@ -379,6 +382,30 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|
} else if (IP_ADDR_PCB_VERSION_MATCH_EXACT(lpcb, ip_current_dest_addr())) {
|
|
if (ip_addr_eq(&lpcb->local_ip, ip_current_dest_addr())) {
|
|
/* found an exact match */
|
|
+#if REUSE_IPPORT
|
|
+ // check master fd
|
|
+ struct tcp_pcb_listen *tmp_lpcb = lpcb;
|
|
+ u8_t have_master_fd = 0;
|
|
+ while (tmp_lpcb != NULL) {
|
|
+ if (tmp_lpcb->master_lpcb) {
|
|
+ have_master_fd = 1;
|
|
+ }
|
|
+ tmp_lpcb = tmp_lpcb->next_same_port_pcb;
|
|
+ }
|
|
+
|
|
+ tmp_lpcb = lpcb;
|
|
+ min_cnts_lpcb = lpcb;
|
|
+ u16_t min_conn_num = MAX_CONN_NUM_PER_THREAD;
|
|
+ while (tmp_lpcb != NULL) {
|
|
+ if (!have_master_fd || tmp_lpcb->master_lpcb) {
|
|
+ if (tmp_lpcb->connect_num < min_conn_num) {
|
|
+ min_cnts_lpcb = tmp_lpcb;
|
|
+ min_conn_num = tmp_lpcb->connect_num;
|
|
+ }
|
|
+ }
|
|
+ tmp_lpcb = tmp_lpcb->next_same_port_pcb;
|
|
+ }
|
|
+#endif
|
|
break;
|
|
} else if (ip_addr_isany(&lpcb->local_ip)) {
|
|
/* found an ANY-match */
|
|
@@ -428,7 +455,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
|
tcphdr_opt1len, tcphdr_opt2, p) == ERR_OK)
|
|
#endif
|
|
{
|
|
+#if REUSE_IPPORT
|
|
+ tcp_listen_input(min_cnts_lpcb);
|
|
+ min_cnts_lpcb->connect_num++;
|
|
+#else
|
|
tcp_listen_input(lpcb);
|
|
+#endif
|
|
}
|
|
pbuf_free(p);
|
|
return;
|
|
diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h
|
|
index 55fc413..d12312c 100644
|
|
--- a/src/include/lwip/api.h
|
|
+++ b/src/include/lwip/api.h
|
|
@@ -318,6 +318,10 @@ struct netconn {
|
|
#endif /* LWIP_TCP */
|
|
/** A callback function that is informed about events for this netconn */
|
|
netconn_callback callback;
|
|
+
|
|
+#if REUSE_IPPORT
|
|
+ u8_t is_master_fd;
|
|
+#endif
|
|
};
|
|
|
|
/** This vector type is passed to @ref netconn_write_vectors_partly to send
|
|
diff --git a/src/include/lwip/priv/tcp_priv.h b/src/include/lwip/priv/tcp_priv.h
|
|
index 783acf5..02481da 100644
|
|
--- a/src/include/lwip/priv/tcp_priv.h
|
|
+++ b/src/include/lwip/priv/tcp_priv.h
|
|
@@ -353,6 +353,15 @@ static inline int vdev_reg_done(enum reg_ring_type reg_type, const struct tcp_pc
|
|
qtuple.dst_ip = pcb->remote_ip.addr;
|
|
qtuple.dst_port = lwip_htons(pcb->remote_port);
|
|
|
|
+#if REUSE_IPPORT
|
|
+ if (reg_type == REG_RING_TCP_CONNECT_CLOSE) {
|
|
+ struct tcp_pcb_listen* lpcb = pcb->listener;
|
|
+ if (lpcb != NULL) {
|
|
+ lpcb->connect_num--;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+
|
|
return vdev_reg_xmit(reg_type, &qtuple);
|
|
}
|
|
static inline void vdev_unreg_done(const struct tcp_pcb *pcb)
|
|
@@ -473,6 +482,16 @@ static inline void vdev_unreg_done(const struct tcp_pcb *pcb)
|
|
tcp_timer_needed(); \
|
|
} while (0)
|
|
|
|
+#define TCP_REG_SAMEPORT(first_pcb, lpcb) \
|
|
+ do { \
|
|
+ struct tcp_pcb_listen *tmp_pcb = first_pcb; \
|
|
+ while (tmp_pcb->next_same_port_pcb != NULL) { \
|
|
+ tmp_pcb = tmp_pcb->next_same_port_pcb; \
|
|
+ }; \
|
|
+ tmp_pcb->next_same_port_pcb = lpcb; \
|
|
+ tcp_timer_needed(); \
|
|
+ } while (0)
|
|
+
|
|
#define TCP_RMV_HASH(pcbs, npcb) \
|
|
do { \
|
|
hlist_del_init(&(npcb)->tcp_node); \
|
|
diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
|
|
index 9ebdbf2..c5e4654 100644
|
|
--- a/src/include/lwip/tcp.h
|
|
+++ b/src/include/lwip/tcp.h
|
|
@@ -252,6 +252,14 @@ struct tcp_pcb_listen {
|
|
u8_t backlog;
|
|
u8_t accepts_pending;
|
|
#endif /* TCP_LISTEN_BACKLOG */
|
|
+
|
|
+#if REUSE_IPPORT
|
|
+ struct tcp_pcb_listen* next_same_port_pcb;
|
|
+ u16_t connect_num;
|
|
+ int socket_fd;
|
|
+ u8_t master_lpcb;
|
|
+#endif
|
|
+
|
|
};
|
|
|
|
|
|
diff --git a/src/include/lwipopts.h b/src/include/lwipopts.h
|
|
index 97e96ab..f8b3294 100644
|
|
--- a/src/include/lwipopts.h
|
|
+++ b/src/include/lwipopts.h
|
|
@@ -143,6 +143,10 @@
|
|
|
|
#define USE_LIBOS_ZC_RING 0
|
|
|
|
+#define REUSE_IPPORT 1
|
|
+
|
|
+#define MAX_CONN_NUM_PER_THREAD 65535
|
|
+
|
|
#define SO_REUSE 1
|
|
|
|
#define SIOCSHIWAT 1
|
|
--
|
|
2.33.0
|
|
|