Projects
Eulaceura:Mainline
lwip
_service:obs_scm:0041-optimite-pcb-list-limit-s...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0041-optimite-pcb-list-limit-send-size-and-ack-now.patch of Package lwip
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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2