diff --git a/0106-rewrite-tcp-rexmit-function.patch b/0106-rewrite-tcp-rexmit-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..b499280e2c16f4a4d2facea5e8a1e5ffcf2a27e4 --- /dev/null +++ b/0106-rewrite-tcp-rexmit-function.patch @@ -0,0 +1,149 @@ + src/core/tcp_out.c | 101 ++++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 80 insertions(+), 21 deletions(-) + +diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c +index bb03aae..50370a0 100644 +--- a/src/core/tcp_out.c ++++ b/src/core/tcp_out.c +@@ -2141,12 +2141,13 @@ tcp_rexmit_rto(struct tcp_pcb *pcb) + } + } + ++#if GAZELLE_ENABLE + /** +- * Requeue the first unacked segment for retransmission ++ * Requeue all unacked segment for retransmission until next segment is busy + * + * Called by tcp_receive() for fast retransmit. + * +- * @param pcb the tcp_pcb for which to retransmit the first unacked segment ++ * @param pcb the tcp_pcb for which to re-enqueue all unacked segments + */ + err_t + tcp_rexmit(struct tcp_pcb *pcb) +@@ -2161,29 +2162,23 @@ tcp_rexmit(struct tcp_pcb *pcb) + } + + seg = pcb->unacked; +-#if GAZELLE_ENABLE ++ ++ /* 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; ++ } ++ + cur_seg = &(pcb->unsent); + while (seg) { +-#endif +- /* 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; +- } +- + /* 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; ++ if (pcb->unacked == NULL) { ++ pcb->last_unacked = NULL; ++ } + +-#if !GAZELLE_ENABLE +- cur_seg = &(pcb->unsent); +-#endif + while (*cur_seg && + TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) { + cur_seg = &((*cur_seg)->next); +@@ -2199,10 +2194,14 @@ tcp_rexmit(struct tcp_pcb *pcb) + } + #endif /* TCP_OVERSIZE */ + +-#if GAZELLE_ENABLE + seg = pcb->unacked; ++ ++ /* Give up if the segment is still referenced by the netif driver ++ due to deferred transmission. */ ++ if (seg && tcp_output_segment_busy(seg)) { ++ break; ++ } + } +-#endif + + if (pcb->nrtx < 0xFF) { + ++pcb->nrtx; +@@ -2218,7 +2217,67 @@ tcp_rexmit(struct tcp_pcb *pcb) + and thus tcp_output directly returns. */ + return ERR_OK; + } ++# else ++/** ++ * Requeue the first unacked segment for retransmission ++ * ++ * Called by tcp_receive() for fast retransmit. ++ * ++ * @param pcb the tcp_pcb for which to retransmit the first unacked segment ++ */ ++err_t ++tcp_rexmit(struct tcp_pcb *pcb) ++{ ++ struct tcp_seg *seg; ++ struct tcp_seg **cur_seg; + ++ LWIP_ASSERT("tcp_rexmit: invalid pcb", pcb != NULL); ++ ++ if (pcb->unacked == NULL) { ++ return ERR_VAL; ++ } ++ ++ seg = pcb->unacked; ++ ++ /* 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; ++ ++ 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; ++#if TCP_OVERSIZE ++ if (seg->next == NULL) { ++ /* the retransmitted segment is last in unsent, so reset unsent_oversize */ ++ pcb->unsent_oversize = 0; ++ } ++#endif /* TCP_OVERSIZE */ ++ ++ if (pcb->nrtx < 0xFF) { ++ ++pcb->nrtx; ++ } ++ ++ /* Don't take any rtt measurements after retransmitting. */ ++ pcb->rttest = 0; ++ ++ /* Do the actual retransmission. */ ++ MIB2_STATS_INC(mib2.tcpretranssegs); ++ /* No need to call tcp_output: we are always called from tcp_input() ++ and thus tcp_output directly returns. */ ++ return ERR_OK; ++} ++#endif + + /** + * Handle retransmission after three dupacks received diff --git a/lwip.spec b/lwip.spec index 8ee9ddb4b7df4e3048306e8265c31c78efec4d34..63101b64834dcd694098245d09b9cdd568cf5cff 100644 --- a/lwip.spec +++ b/lwip.spec @@ -4,7 +4,7 @@ Summary: lwip is a small independent implementation of the TCP/IP protocol suite Name: lwip Version: 2.1.3 -Release: 110 +Release: 111 License: BSD URL: http://savannah.nongnu.org/projects/lwip/ Source0: http://download.savannah.nongnu.org/releases/lwip/%{name}-%{version}.zip @@ -122,6 +122,7 @@ Patch6005: backport-tcp_in-fix-ooseq-update-error.patch Patch9102: 0103-adapt-for-dpdk-23.11.patch Patch9103: 0104-optimize-enqueue-for-unacked-and-unsent-queue.patch Patch9104: 0105-delete-redundant-logs-in-lwip.patch +Patch9105: 0106-rewrite-tcp-rexmit-function.patch BuildRequires: gcc-c++ dos2unix dpdk-devel @@ -151,6 +152,9 @@ cd %{_builddir}/%{name}-%{version}/src %{_libdir}/liblwip.a %changelog +* Tue Jan 23 2024 zhengjiebing - 2.1.3-111 +- rewrite tcp_rexmit function + * Wed Jan 10 2024 hankangkang - 2.1.3-110 - delete redundant logs in lwip