From 1aa27395a4c4b73b6db472c4ae75ed91637a11bf Mon Sep 17 00:00:00 2001
From: kircher <majun65@huawei.com>
Date: Wed, 21 Dec 2022 17:50:50 +0800
Subject: [PATCH] add dataack when recv too many acks with data

---
 src/core/tcp_in.c      | 22 ++++++++++++++++++++++
 src/include/lwip/tcp.h |  1 +
 src/include/lwipopts.h |  2 ++
 3 files changed, 25 insertions(+)

diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c
index 78954bd..35ec6d9 100644
--- a/src/core/tcp_in.c
+++ b/src/core/tcp_in.c
@@ -1260,6 +1260,7 @@ tcp_receive(struct tcp_pcb *pcb)
   s16_t m;
   u32_t right_wnd_edge;
   int found_dupack = 0;
+  int found_dataack = 0;
 
   LWIP_ASSERT("tcp_receive: invalid pcb", pcb != NULL);
   LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED);
@@ -1337,11 +1338,31 @@ tcp_receive(struct tcp_pcb *pcb)
           }
         }
       }
+      /* fast rexmit when receive too many acks with data */
+      if (TCP_SEQ_LT(ackno + 1, pcb->snd_nxt)) {
+        if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge) {
+          if (pcb->rtime >= 0) {
+            if (pcb->lastack == ackno) {
+              found_dataack = 1;
+              ++pcb->dataacks;
+              if (pcb->dataacks > MAX_DATA_ACK_NUM) {
+                if (tcp_rexmit(pcb) == ERR_OK) {
+                  pcb->rtime = 0;
+                  pcb->dataacks = 0;
+                }
+              }
+            }
+          }
+        }
+      }
       /* If Clause (1) or more is true, but not a duplicate ack, reset
        * count of consecutive duplicate acks */
       if (!found_dupack) {
         pcb->dupacks = 0;
       }
+      if (!found_dataack) {
+        pcb->dataacks = 0;
+      }
     } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack + 1, pcb->snd_nxt)) {
       /* We come here when the ACK acknowledges new data. */
       tcpwnd_size_t acked;
@@ -1367,6 +1388,7 @@ tcp_receive(struct tcp_pcb *pcb)
       /* Reset the fast retransmit variables. */
       pcb->dupacks = 0;
       pcb->lastack = ackno;
+      pcb->dataacks = 0;
 
       /* Update the congestion control variables (cwnd and
          ssthresh). */
diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
index 2a61776..97cb882 100644
--- a/src/include/lwip/tcp.h
+++ b/src/include/lwip/tcp.h
@@ -326,6 +326,7 @@ struct tcp_pcb {
 
   /* fast retransmit/recovery */
   u8_t dupacks;
+  u32_t dataacks;
   u32_t lastack; /* Highest acknowledged seqno. */
 
   /* congestion avoidance/control variables */
diff --git a/src/include/lwipopts.h b/src/include/lwipopts.h
index 907c630..405cf11 100644
--- a/src/include/lwipopts.h
+++ b/src/include/lwipopts.h
@@ -177,6 +177,8 @@
 
 #define MIN_TSO_SEG_LEN 256
 
+#define MAX_DATA_ACK_NUM 256
+
 /*  ---------------------------------------
  *  -------      NIC offloads      --------
  *  ---------------------------------------
-- 
2.33.0

