1From 08716b71ccb93c6d998d1654c1fac137f29d2851 Mon Sep 17 00:00:00 2001
2From: wuchangsheng <wuchangsheng2@huawei.com>
3Date: Tue, 13 Dec 2022 22:27:33 +0800
4Subject: [PATCH] optimite pcb-list limit , send size and ack now
5
6---
7 src/core/tcp.c         |   1 +
8 src/core/tcp_in.c      |  16 +++++++-
9 src/core/tcp_out.c     | 103 ++++++++++++++++++++++++++++++-------------------
10 src/include/lwip/opt.h |   2 +-
11 src/include/lwip/tcp.h |   2 +
12 src/include/lwipsock.h |   2 -
13 6 files changed, 83 insertions(+), 43 deletions(-)
14
15diff --git a/src/core/tcp.c b/src/core/tcp.c
16index 51ada38..cb08f95 100644
17--- a/src/core/tcp.c
18+++ b/src/core/tcp.c
19@@ -2297,6 +2297,7 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
20     tcp_segs_free(pcb->unsent);
21     tcp_segs_free(pcb->unacked);
22     pcb->unacked = pcb->unsent = NULL;
23+    pcb->last_unacked = pcb->last_unsent = NULL;
24 #if TCP_OVERSIZE
25     pcb->unsent_oversize = 0;
26 #endif /* TCP_OVERSIZE */
27diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c
28index 2d6cb6a..78954bd 100644
29--- a/src/core/tcp_in.c
30+++ b/src/core/tcp_in.c
31@@ -976,8 +976,14 @@ tcp_process(struct tcp_pcb *pcb)
32           rseg = pcb->unsent;
33           LWIP_ASSERT("no segment to free", rseg != NULL);
34           pcb->unsent = rseg->next;
35+          if (pcb->last_unsent == rseg) {
36+            pcb->last_unsent = rseg->next;
37+          }
38         } else {
39           pcb->unacked = rseg->next;
40+          if (pcb->last_unacked == rseg) {
41+            pcb->last_unacked = rseg->next;
42+          }
43         }
44         tcp_seg_free(rseg);
45 
46@@ -1393,6 +1399,8 @@ tcp_receive(struct tcp_pcb *pcb)
47       /* Remove segment from the unacknowledged list if the incoming
48          ACK acknowledges them. */
49       pcb->unacked = tcp_free_acked_segments(pcb, pcb->unacked, "unacked", pcb->unsent);
50+      if (pcb->unacked == NULL)
51+        pcb->last_unacked = NULL;
52       /* We go through the ->unsent list to see if any of the segments
53          on the list are acknowledged by the ACK. This may seem
54          strange since an "unsent" segment shouldn't be acked. The
55@@ -1400,6 +1408,8 @@ tcp_receive(struct tcp_pcb *pcb)
56          ->unsent list after a retransmission, so these segments may
57          in fact have been sent once. */
58       pcb->unsent = tcp_free_acked_segments(pcb, pcb->unsent, "unsent", pcb->unacked);
59+      if (pcb->unsent == NULL)
60+        pcb->last_unsent = NULL;
61 
62       /* If there's nothing left to acknowledge, stop the retransmit
63          timer, otherwise reset it to start again */
64@@ -1736,7 +1746,11 @@ tcp_receive(struct tcp_pcb *pcb)
65 
66 
67         /* Acknowledge the segment(s). */
68-        tcp_ack(pcb);
69+        if (flags & TCP_PSH) {
70+            tcp_ack_now(pcb);
71+        } else {
72+            tcp_ack(pcb);
73+        }
74 
75 #if LWIP_TCP_SACK_OUT
76         if (LWIP_TCP_SACK_VALID(pcb, 0)) {
77diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c
78index f53750b..55053d8 100644
79--- a/src/core/tcp_out.c
80+++ b/src/core/tcp_out.c
81@@ -631,11 +631,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
82 #endif /* TCP_OVERSIZE */
83   }
84 #else /* USE_LIBOS */
85-  if (pcb->unsent != NULL) {
86-    /* @todo: this could be sped up by keeping last_unsent in the pcb */
87-    for (last_unsent = pcb->unsent; last_unsent->next != NULL;
88-         last_unsent = last_unsent->next);
89-  }
90+  last_unsent = pcb->last_unsent;
91 #endif /* USE_LIBOS */
92 
93   /*
94@@ -851,6 +847,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
95    * Finally update the pcb state.
96    */
97 #if USE_LIBOS
98+  if (queue) {
99+    pcb->last_unsent = prev_seg;
100+  }
101   pcb->snd_lbb += pos;
102   pcb->snd_buf -= pos;
103 #else
104@@ -1050,6 +1049,8 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
105   /* Finally insert remainder into queue after split (which stays head) */
106   seg->next = useg->next;
107   useg->next = seg;
108+  if (pcb->last_unsent == useg)
109+    pcb->last_unsent = seg;
110 
111 #if TCP_OVERSIZE
112   /* If remainder is last segment on the unsent, ensure we clear the oversize amount
113@@ -1086,9 +1087,7 @@ tcp_send_fin(struct tcp_pcb *pcb)
114 
115   /* first, try to add the fin to the last unsent segment */
116   if (pcb->unsent != NULL) {
117-    struct tcp_seg *last_unsent;
118-    for (last_unsent = pcb->unsent; last_unsent->next != NULL;
119-         last_unsent = last_unsent->next);
120+    struct tcp_seg *last_unsent = pcb->unsent;
121 
122     if ((TCPH_FLAGS(last_unsent->tcphdr) & (TCP_SYN | TCP_FIN | TCP_RST)) == 0) {
123       /* no SYN/FIN/RST flag in the header, we can add the FIN flag */
124@@ -1182,10 +1181,10 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
125   if (pcb->unsent == NULL) {
126     pcb->unsent = seg;
127   } else {
128-    struct tcp_seg *useg;
129-    for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
130+    struct tcp_seg *useg = pcb->last_unsent;
131     useg->next = seg;
132   }
133+  pcb->last_unsent = seg;
134 #if TCP_OVERSIZE
135   /* The new unsent tail has no space */
136   pcb->unsent_oversize = 0;
137@@ -1314,6 +1313,7 @@ static struct tcp_seg *tcp_output_over(struct tcp_pcb *pcb, struct tcp_seg *seg,
138     seg->next = NULL;
139     if (useg == NULL) {
140       pcb->unacked = seg;
141+      pcb->last_unacked = seg;
142       useg = seg;
143     } else {
144       if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
145@@ -1329,6 +1329,7 @@ static struct tcp_seg *tcp_output_over(struct tcp_pcb *pcb, struct tcp_seg *seg,
146         /* add segment to tail of unacked list */
147         useg->next = seg;
148         useg = seg;
149+        pcb->last_unacked = seg;
150       }
151     }
152   } else {
153@@ -1460,15 +1461,14 @@ tcp_output(struct tcp_pcb *pcb)
154   pcb->persist_backoff = 0;
155 
156   /* useg should point to last segment on unacked queue */
157-  useg = pcb->unacked;
158-  if (useg != NULL) {
159-    for (; useg->next != NULL; useg = useg->next);
160-  }
161+  useg = pcb->last_unacked;
162+
163   /* data available and window allows it to be sent? */
164 
165+  u32_t send_len = 0;
166 #if USE_LIBOS
167   if (get_eth_params_tx_ol() & DEV_TX_OFFLOAD_TCP_TSO) {
168-    while(seg) {
169+    while(seg && send_len < 0xffff) {
170       /**
171        * 1)遍历unsent队列,找到所有的待发送seg. 将seg的buf串起来
172        * 2) 生成新的seg, 调用tcp_output_segment, 新的seg释放掉
173@@ -1510,6 +1510,7 @@ tcp_output(struct tcp_pcb *pcb)
174           pre_pbuf->next = seg->p;
175         }
176 
177+        send_len += seg->len;
178         pre_pbuf = seg->p;
179         next_seqno = seg_seqno + TCP_TCPLEN(seg);
180         seg = seg->next;
181@@ -1519,8 +1520,11 @@ tcp_output(struct tcp_pcb *pcb)
182 
183       if (first_pbuf == NULL) {
184         err = tcp_output_seg(pcb, seg, netif, next_seqno + seg->len);
185-        if (err != ERR_OK)
186+        if (err != ERR_OK) {
187+          if (pcb->unsent == NULL)
188+            pcb->last_unsent = NULL;
189           return err;
190+        }
191         pcb->unsent = seg->next;
192         useg = tcp_output_over(pcb, seg, useg);
193         seg = pcb->unsent;
194@@ -1545,7 +1549,7 @@ tcp_output(struct tcp_pcb *pcb)
195   } else
196 #endif
197 {
198-  while (seg != NULL &&
199+  while (seg != NULL && send_len < 0xffff &&
200          lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
201     LWIP_ASSERT("RST not expected here!",
202                 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
203@@ -1560,6 +1564,7 @@ tcp_output(struct tcp_pcb *pcb)
204         ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
205       break;
206     }
207+    send_len += seg->len;
208 #if TCP_CWND_DEBUG
209     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",
210                                  pcb->snd_wnd, pcb->cwnd, wnd,
211@@ -1577,6 +1582,8 @@ tcp_output(struct tcp_pcb *pcb)
212     if (err != ERR_OK) {
213       /* segment could not be sent, for whatever reason */
214       tcp_set_flags(pcb, TF_NAGLEMEMERR);
215+      if (pcb->unsent == NULL)
216+        pcb->last_unsent = NULL;
217       return err;
218     }
219 #if TCP_OVERSIZE_DBGCHECK
220@@ -1596,6 +1603,7 @@ tcp_output(struct tcp_pcb *pcb)
221       /* unacked list is empty? */
222       if (pcb->unacked == NULL) {
223         pcb->unacked = seg;
224+        pcb->last_unacked = seg;
225         useg = seg;
226         /* unacked list is not empty? */
227       } else {
228@@ -1615,6 +1623,7 @@ tcp_output(struct tcp_pcb *pcb)
229           /* add segment to tail of unacked list */
230           useg->next = seg;
231           useg = useg->next;
232+          pcb->last_unacked = seg;
233         }
234       }
235       /* do not queue empty segments on the unacked list */
236@@ -1632,6 +1641,8 @@ tcp_output(struct tcp_pcb *pcb)
237 #endif /* TCP_OVERSIZE */
238 
239 output_done:
240+  if (pcb->unsent == NULL)
241+    pcb->last_unsent = NULL;
242   tcp_clear_flags(pcb, TF_NAGLEMEMERR);
243   return ERR_OK;
244 }
245@@ -1932,9 +1943,13 @@ tcp_rexmit_rto_prepare(struct tcp_pcb *pcb)
246   }
247 #endif /* TCP_OVERSIZE_DBGCHECK */
248   /* unsent queue is the concatenated queue (of unacked, unsent) */
249+  if (pcb->unsent == NULL) {
250+    pcb->last_unsent = pcb->last_unacked;
251+  }
252   pcb->unsent = pcb->unacked;
253   /* unacked queue is now empty */
254   pcb->unacked = NULL;
255+  pcb->last_unacked = NULL;
256 
257   /* Mark RTO in-progress */
258   tcp_set_flags(pcb, TF_RTO);
259@@ -2004,32 +2019,42 @@ tcp_rexmit(struct tcp_pcb *pcb)
260   }
261 
262   seg = pcb->unacked;
263+  while (seg) {
264+    /* Give up if the segment is still referenced by the netif driver
265+      due to deferred transmission. */
266+    if (tcp_output_segment_busy(seg)) {
267+      LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_rexmit busy\n"));
268+      if (seg == pcb->unacked)
269+        return ERR_VAL;
270+      else
271+        break;
272+    }
273 
274-  /* Give up if the segment is still referenced by the netif driver
275-     due to deferred transmission. */
276-  if (tcp_output_segment_busy(seg)) {
277-    LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_rexmit busy\n"));
278-    return ERR_VAL;
279-  }
280-
281-  /* Move the first unacked segment to the unsent queue */
282-  /* Keep the unsent queue sorted. */
283-  pcb->unacked = seg->next;
284+    /* Move the first unacked segment to the unsent queue */
285+    /* Keep the unsent queue sorted. */
286+    if (pcb->last_unacked == pcb->unacked)
287+      pcb->last_unacked = pcb->unacked->next;
288+    pcb->unacked = pcb->unacked->next;
289 
290-  cur_seg = &(pcb->unsent);
291-  while (*cur_seg &&
292-         TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
293-    cur_seg = &((*cur_seg)->next );
294-  }
295-  seg->next = *cur_seg;
296-  *cur_seg = seg;
297+    cur_seg = &(pcb->unsent);
298+    while (*cur_seg &&
299+          TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
300+      cur_seg = &((*cur_seg)->next);
301+    }
302+    if (*cur_seg == NULL)
303+      pcb->last_unsent = seg;
304+    seg->next = *cur_seg;
305+    *cur_seg = seg;
306 #if TCP_OVERSIZE
307-  if (seg->next == NULL) {
308-    /* the retransmitted segment is last in unsent, so reset unsent_oversize */
309-    pcb->unsent_oversize = 0;
310-  }
311+    if (seg->next == NULL) {
312+      /* the retransmitted segment is last in unsent, so reset unsent_oversize */
313+      pcb->unsent_oversize = 0;
314+    }
315 #endif /* TCP_OVERSIZE */
316 
317+    seg = pcb->unacked;
318+  }
319+
320   if (pcb->nrtx < 0xFF) {
321     ++pcb->nrtx;
322   }
323@@ -2207,7 +2232,7 @@ tcp_output_control_segment(const struct tcp_pcb *pcb, struct pbuf *p,
324       struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload;
325 #if CHECKSUM_GEN_TCP_HW
326     if (get_eth_params_tx_ol() & DEV_TX_OFFLOAD_TCP_CKSUM) {
327-      tcph_cksum_set(p, TCP_HLEN);
328+      tcph_cksum_set(p, TCPH_HDRLEN_BYTES(tcphdr));
329       tcphdr->chksum = ip_chksum_pseudo_offload(IP_PROTO_TCP, p->tot_len, src, dst);
330     } else {
331       tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
332diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h
333index 8294cdd..83e7e93 100644
334--- a/src/include/lwip/opt.h
335+++ b/src/include/lwip/opt.h
336@@ -1281,7 +1281,7 @@
337  * LWIP_TCP_SACK_OUT==1: TCP will support sending selective acknowledgements (SACKs).
338  */
339 #if !defined LWIP_TCP_SACK_OUT || defined __DOXYGEN__
340-#define LWIP_TCP_SACK_OUT               0
341+#define LWIP_TCP_SACK_OUT               1
342 #endif
343 
344 /**
345diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
346index b36bf33..b0ae02c 100644
347--- a/src/include/lwip/tcp.h
348+++ b/src/include/lwip/tcp.h
349@@ -356,7 +356,9 @@ struct tcp_pcb {
350 
351   /* These are ordered by sequence number: */
352   struct tcp_seg *unsent;   /* Unsent (queued) segments. */
353+  struct tcp_seg *last_unsent;
354   struct tcp_seg *unacked;  /* Sent but unacknowledged segments. */
355+  struct tcp_seg *last_unacked;
356 #if TCP_QUEUE_OOSEQ
357   struct tcp_seg *ooseq;    /* Received out of sequence segments. */
358 #endif /* TCP_QUEUE_OOSEQ */
359diff --git a/src/include/lwipsock.h b/src/include/lwipsock.h
360index f919330..bf0d753 100644
361--- a/src/include/lwipsock.h
362+++ b/src/include/lwipsock.h
363@@ -112,8 +112,6 @@ struct lwip_sock {
364   struct list_node send_list;
365   struct pbuf *send_lastdata;
366   struct pbuf *send_pre_del;
367-  uint64_t recv_all;
368-  uint64_t send_all;
369 
370   char pad3 __rte_cache_aligned;
371   /* nerver change */
372-- 
3732.8.4.windows.1
374
375