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