lwip/0041-optimite-pcb-list-limit-send-size-and-ack-now.patch
jiangheng c341686f0a adapt lwip-2.2.0
(cherry picked from commit 63c40c2ad66e5b32d96cecad0b123db28783ae5c)
2024-02-17 14:46:44 +08:00

375 lines
13 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 08716b71ccb93c6d998d1654c1fac137f29d2851 Mon Sep 17 00:00:00 2001
From: wuchangsheng <wuchangsheng2@huawei.com>
Date: Tue, 13 Dec 2022 22:27:33 +0800
Subject: [PATCH] optimite pcb-list limit , send size and ack now
---
src/core/tcp.c | 1 +
src/core/tcp_in.c | 16 +++++++-
src/core/tcp_out.c | 103 ++++++++++++++++++++++++++++++-------------------
src/include/lwip/opt.h | 2 +-
src/include/lwip/tcp.h | 2 +
src/include/lwipsock.h | 2 -
6 files changed, 83 insertions(+), 43 deletions(-)
diff --git a/src/core/tcp.c b/src/core/tcp.c
index 699dda4..54d9ded 100644
--- a/src/core/tcp.c
+++ b/src/core/tcp.c
@@ -2303,6 +2303,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
tcp_segs_free(pcb->unsent);
tcp_segs_free(pcb->unacked);
pcb->unacked = pcb->unsent = NULL;
+ pcb->last_unacked = pcb->last_unsent = NULL;
#if TCP_OVERSIZE
pcb->unsent_oversize = 0;
#endif /* TCP_OVERSIZE */
diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c
index fa574ff..ef95238 100644
--- a/src/core/tcp_in.c
+++ b/src/core/tcp_in.c
@@ -979,8 +979,14 @@ tcp_process(struct tcp_pcb *pcb)
rseg = pcb->unsent;
LWIP_ASSERT("no segment to free", rseg != NULL);
pcb->unsent = rseg->next;
+ if (pcb->last_unsent == rseg) {
+ pcb->last_unsent = rseg->next;
+ }
} else {
pcb->unacked = rseg->next;
+ if (pcb->last_unacked == rseg) {
+ pcb->last_unacked = rseg->next;
+ }
}
tcp_seg_free(rseg);
@@ -1389,6 +1395,8 @@ tcp_receive(struct tcp_pcb *pcb)
/* Remove segment from the unacknowledged list if the incoming
ACK acknowledges them. */
pcb->unacked = tcp_free_acked_segments(pcb, pcb->unacked, "unacked", pcb->unsent);
+ if (pcb->unacked == NULL)
+ pcb->last_unacked = NULL;
/* We go through the ->unsent list to see if any of the segments
on the list are acknowledged by the ACK. This may seem
strange since an "unsent" segment shouldn't be acked. The
@@ -1396,6 +1404,8 @@ tcp_receive(struct tcp_pcb *pcb)
->unsent list after a retransmission, so these segments may
in fact have been sent once. */
pcb->unsent = tcp_free_acked_segments(pcb, pcb->unsent, "unsent", pcb->unacked);
+ if (pcb->unsent == NULL)
+ pcb->last_unsent = NULL;
/* If there's nothing left to acknowledge, stop the retransmit
timer, otherwise reset it to start again */
@@ -1732,7 +1742,11 @@ tcp_receive(struct tcp_pcb *pcb)
/* Acknowledge the segment(s). */
- tcp_ack(pcb);
+ if (flags & TCP_PSH) {
+ tcp_ack_now(pcb);
+ } else {
+ tcp_ack(pcb);
+ }
#if LWIP_TCP_SACK_OUT
if (LWIP_TCP_SACK_VALID(pcb, 0)) {
diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c
index b1d9f23..342f4aa 100644
--- a/src/core/tcp_out.c
+++ b/src/core/tcp_out.c
@@ -634,11 +634,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
#endif /* TCP_OVERSIZE */
}
#else /* USE_LIBOS */
- if (pcb->unsent != NULL) {
- /* @todo: this could be sped up by keeping last_unsent in the pcb */
- for (last_unsent = pcb->unsent; last_unsent->next != NULL;
- last_unsent = last_unsent->next);
- }
+ last_unsent = pcb->last_unsent;
#endif /* USE_LIBOS */
/*
@@ -854,6 +850,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
* Finally update the pcb state.
*/
#if USE_LIBOS
+ if (queue) {
+ pcb->last_unsent = prev_seg;
+ }
pcb->snd_lbb += pos;
pcb->snd_buf -= pos;
#else
@@ -1053,6 +1052,8 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
/* Finally insert remainder into queue after split (which stays head) */
seg->next = useg->next;
useg->next = seg;
+ if (pcb->last_unsent == useg)
+ pcb->last_unsent = seg;
#if TCP_OVERSIZE
/* If remainder is last segment on the unsent, ensure we clear the oversize amount
@@ -1089,9 +1090,7 @@ tcp_send_fin(struct tcp_pcb *pcb)
/* first, try to add the fin to the last unsent segment */
if (pcb->unsent != NULL) {
- struct tcp_seg *last_unsent;
- for (last_unsent = pcb->unsent; last_unsent->next != NULL;
- last_unsent = last_unsent->next);
+ struct tcp_seg *last_unsent = pcb->unsent;
if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
/* no SYN/FIN/RST flag in the header, we can add the FIN flag */
@@ -1185,10 +1184,10 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
if (pcb->unsent == NULL) {
pcb->unsent = seg;
} else {
- struct tcp_seg *useg;
- for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
+ struct tcp_seg *useg = pcb->last_unsent;
useg->next = seg;
}
+ pcb->last_unsent = seg;
#if TCP_OVERSIZE
/* The new unsent tail has no space */
pcb->unsent_oversize = 0;
@@ -1317,6 +1316,7 @@ static struct tcp_seg *tcp_output_over(struct tcp_pcb *pcb, struct tcp_seg *seg,
seg->next = NULL;
if (useg == NULL) {
pcb->unacked = seg;
+ pcb->last_unacked = seg;
useg = seg;
} else {
if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
@@ -1332,6 +1332,7 @@ static struct tcp_seg *tcp_output_over(struct tcp_pcb *pcb, struct tcp_seg *seg,
/* add segment to tail of unacked list */
useg->next = seg;
useg = seg;
+ pcb->last_unacked = seg;
}
}
} else {
@@ -1463,15 +1464,14 @@ tcp_output(struct tcp_pcb *pcb)
pcb->persist_backoff = 0;
/* useg should point to last segment on unacked queue */
- useg = pcb->unacked;
- if (useg != NULL) {
- for (; useg->next != NULL; useg = useg->next);
- }
+ useg = pcb->last_unacked;
+
/* data available and window allows it to be sent? */
+ u32_t send_len = 0;
#if USE_LIBOS
if (get_eth_params_tx_ol() & DEV_TX_OFFLOAD_TCP_TSO) {
- while(seg) {
+ while(seg && send_len < 0xffff) {
/**
* 1遍历unsent队列找到所有的待发送seg. 将seg的buf串起来
* 2) 生成新的seg, 调用tcp_output_segment, 新的seg释放掉
@@ -1513,6 +1513,7 @@ tcp_output(struct tcp_pcb *pcb)
pre_pbuf->next = seg->p;
}
+ send_len += seg->len;
pre_pbuf = seg->p;
next_seqno = seg_seqno + TCP_TCPLEN(seg);
seg = seg->next;
@@ -1522,8 +1523,11 @@ tcp_output(struct tcp_pcb *pcb)
if (first_pbuf == NULL) {
err = tcp_output_seg(pcb, seg, netif, next_seqno + seg->len);
- if (err != ERR_OK)
+ if (err != ERR_OK) {
+ if (pcb->unsent == NULL)
+ pcb->last_unsent = NULL;
return err;
+ }
pcb->unsent = seg->next;
useg = tcp_output_over(pcb, seg, useg);
seg = pcb->unsent;
@@ -1548,7 +1552,7 @@ tcp_output(struct tcp_pcb *pcb)
} else
#endif
{
- while (seg != NULL &&
+ while (seg != NULL && send_len < 0xffff &&
lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
LWIP_ASSERT("RST not expected here!",
(TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
@@ -1563,6 +1567,7 @@ tcp_output(struct tcp_pcb *pcb)
((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
break;
}
+ send_len += seg->len;
#if TCP_CWND_DEBUG
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
pcb->snd_wnd, pcb->cwnd, wnd,
@@ -1580,6 +1585,8 @@ tcp_output(struct tcp_pcb *pcb)
if (err != ERR_OK) {
/* segment could not be sent, for whatever reason */
tcp_set_flags(pcb, TF_NAGLEMEMERR);
+ if (pcb->unsent == NULL)
+ pcb->last_unsent = NULL;
return err;
}
#if TCP_OVERSIZE_DBGCHECK
@@ -1599,6 +1606,7 @@ tcp_output(struct tcp_pcb *pcb)
/* unacked list is empty? */
if (pcb->unacked == NULL) {
pcb->unacked = seg;
+ pcb->last_unacked = seg;
useg = seg;
/* unacked list is not empty? */
} else {
@@ -1618,6 +1626,7 @@ tcp_output(struct tcp_pcb *pcb)
/* add segment to tail of unacked list */
useg->next = seg;
useg = useg->next;
+ pcb->last_unacked = seg;
}
}
/* do not queue empty segments on the unacked list */
@@ -1635,6 +1644,8 @@ tcp_output(struct tcp_pcb *pcb)
#endif /* TCP_OVERSIZE */
output_done:
+ if (pcb->unsent == NULL)
+ pcb->last_unsent = NULL;
tcp_clear_flags(pcb, TF_NAGLEMEMERR);
return ERR_OK;
}
@@ -1935,9 +1946,13 @@ tcp_rexmit_rto_prepare(struct tcp_pcb *pcb)
}
#endif /* TCP_OVERSIZE_DBGCHECK */
/* unsent queue is the concatenated queue (of unacked, unsent) */
+ if (pcb->unsent == NULL) {
+ pcb->last_unsent = pcb->last_unacked;
+ }
pcb->unsent = pcb->unacked;
/* unacked queue is now empty */
pcb->unacked = NULL;
+ pcb->last_unacked = NULL;
/* Mark RTO in-progress */
tcp_set_flags(pcb, TF_RTO);
@@ -2007,32 +2022,42 @@ tcp_rexmit(struct tcp_pcb *pcb)
}
seg = pcb->unacked;
+ while (seg) {
+ /* Give up if the segment is still referenced by the netif driver
+ due to deferred transmission. */
+ if (tcp_output_segment_busy(seg)) {
+ LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_rexmit busy\n"));
+ if (seg == pcb->unacked)
+ return ERR_VAL;
+ else
+ break;
+ }
- /* Give up if the segment is still referenced by the netif driver
- due to deferred transmission. */
- if (tcp_output_segment_busy(seg)) {
- LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_rexmit busy\n"));
- return ERR_VAL;
- }
-
- /* Move the first unacked segment to the unsent queue */
- /* Keep the unsent queue sorted. */
- pcb->unacked = seg->next;
+ /* Move the first unacked segment to the unsent queue */
+ /* Keep the unsent queue sorted. */
+ if (pcb->last_unacked == pcb->unacked)
+ pcb->last_unacked = pcb->unacked->next;
+ pcb->unacked = pcb->unacked->next;
- cur_seg = &(pcb->unsent);
- while (*cur_seg &&
- TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
- cur_seg = &((*cur_seg)->next );
- }
- seg->next = *cur_seg;
- *cur_seg = seg;
+ cur_seg = &(pcb->unsent);
+ while (*cur_seg &&
+ TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
+ cur_seg = &((*cur_seg)->next);
+ }
+ if (*cur_seg == NULL)
+ pcb->last_unsent = seg;
+ seg->next = *cur_seg;
+ *cur_seg = seg;
#if TCP_OVERSIZE
- if (seg->next == NULL) {
- /* the retransmitted segment is last in unsent, so reset unsent_oversize */
- pcb->unsent_oversize = 0;
- }
+ if (seg->next == NULL) {
+ /* the retransmitted segment is last in unsent, so reset unsent_oversize */
+ pcb->unsent_oversize = 0;
+ }
#endif /* TCP_OVERSIZE */
+ seg = pcb->unacked;
+ }
+
if (pcb->nrtx < 0xFF) {
++pcb->nrtx;
}
@@ -2227,7 +2252,7 @@ tcp_output_control_segment_netif(const struct tcp_pcb *pcb, struct pbuf *p,
struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload;
#if CHECKSUM_GEN_TCP_HW
if (get_eth_params_tx_ol() & DEV_TX_OFFLOAD_TCP_CKSUM) {
- tcph_cksum_set(p, TCP_HLEN);
+ tcph_cksum_set(p, TCPH_HDRLEN_BYTES(tcphdr));
tcphdr->chksum = ip_chksum_pseudo_offload(IP_PROTO_TCP, p->tot_len, src, dst);
} else {
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h
index 570d2de..39fd224 100644
--- a/src/include/lwip/opt.h
+++ b/src/include/lwip/opt.h
@@ -1323,7 +1323,7 @@
* LWIP_TCP_SACK_OUT==1: TCP will support sending selective acknowledgements (SACKs).
*/
#if !defined LWIP_TCP_SACK_OUT || defined __DOXYGEN__
-#define LWIP_TCP_SACK_OUT 0
+#define LWIP_TCP_SACK_OUT 1
#endif
/**
diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
index a19fb0e..9ebdbf2 100644
--- a/src/include/lwip/tcp.h
+++ b/src/include/lwip/tcp.h
@@ -356,7 +356,9 @@ struct tcp_pcb {
/* These are ordered by sequence number: */
struct tcp_seg *unsent; /* Unsent (queued) segments. */
+ struct tcp_seg *last_unsent;
struct tcp_seg *unacked; /* Sent but unacknowledged segments. */
+ struct tcp_seg *last_unacked;
#if TCP_QUEUE_OOSEQ
struct tcp_seg *ooseq; /* Received out of sequence segments. */
#endif /* TCP_QUEUE_OOSEQ */
diff --git a/src/include/lwipsock.h b/src/include/lwipsock.h
index f919330..bf0d753 100644
--- a/src/include/lwipsock.h
+++ b/src/include/lwipsock.h
@@ -112,8 +112,6 @@ struct lwip_sock {
struct list_node send_list;
struct pbuf *send_lastdata;
struct pbuf *send_pre_del;
- uint64_t recv_all;
- uint64_t send_all;
char pad3 __rte_cache_aligned;
/* nerver change */
--
2.8.4.windows.1