lwip/0041-optimite-pcb-list-limit-send-size-and-ack-now.patch
kircher f128abedc3 fix TSO snd_nxt incorrectly update
(cherry picked from commit 39a15424167d41a54ad0562581304febf8e737e3)
2023-02-11 21:05:45 +08:00

375 lines
13 KiB
Diff
Raw 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 51ada38..cb08f95 100644
--- a/src/core/tcp.c
+++ b/src/core/tcp.c
@@ -2297,6 +2297,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 2d6cb6a..78954bd 100644
--- a/src/core/tcp_in.c
+++ b/src/core/tcp_in.c
@@ -976,8 +976,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);
@@ -1393,6 +1399,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
@@ -1400,6 +1408,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 */
@@ -1736,7 +1746,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 f53750b..55053d8 100644
--- a/src/core/tcp_out.c
+++ b/src/core/tcp_out.c
@@ -631,11 +631,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 */
/*
@@ -851,6 +847,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
@@ -1050,6 +1049,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
@@ -1086,9 +1087,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 */
@@ -1182,10 +1181,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;
@@ -1314,6 +1313,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))) {
@@ -1329,6 +1329,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 {
@@ -1460,15 +1461,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释放掉
@@ -1510,6 +1510,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;
@@ -1519,8 +1520,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;
@@ -1545,7 +1549,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);
@@ -1560,6 +1564,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,
@@ -1577,6 +1582,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
@@ -1596,6 +1603,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 {
@@ -1615,6 +1623,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 */
@@ -1632,6 +1641,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;
}
@@ -1932,9 +1943,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);
@@ -2004,32 +2019,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;
}
@@ -2207,7 +2232,7 @@ tcp_output_control_segment(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 8294cdd..83e7e93 100644
--- a/src/include/lwip/opt.h
+++ b/src/include/lwip/opt.h
@@ -1281,7 +1281,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 b36bf33..b0ae02c 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