1195972f6Sopenharmony_ciFrom abeef0770f76cd0eff8e5c6e50de0b280079d7f0 Mon Sep 17 00:00:00 2001
2195972f6Sopenharmony_ciFrom: jiangheng <jiangheng14@huawei.com>
3195972f6Sopenharmony_ciDate: Mon, 13 Mar 2023 19:25:42 +0800
4195972f6Sopenharmony_ciSubject: [PATCH] fix tso small packet drop in kernel server
5195972f6Sopenharmony_ci
6195972f6Sopenharmony_ci---
7195972f6Sopenharmony_ci src/core/tcp_out.c     | 254 +++++++++++++++++++++--------------------
8195972f6Sopenharmony_ci src/include/lwipopts.h |   2 +
9195972f6Sopenharmony_ci 2 files changed, 130 insertions(+), 126 deletions(-)
10195972f6Sopenharmony_ci
11195972f6Sopenharmony_cidiff --git a/src/core/tcp_out.c b/src/core/tcp_out.c
12195972f6Sopenharmony_ciindex 8a0d653..b1c317d 100644
13195972f6Sopenharmony_ci--- a/src/core/tcp_out.c
14195972f6Sopenharmony_ci+++ b/src/core/tcp_out.c
15195972f6Sopenharmony_ci@@ -1312,60 +1312,33 @@ tcp_build_wnd_scale_option(u32_t *opts)
16195972f6Sopenharmony_ci #endif
17195972f6Sopenharmony_ci 
18195972f6Sopenharmony_ci #if GAZELLE_ENABLE
19195972f6Sopenharmony_ci-static struct tcp_seg *tcp_output_over(struct tcp_pcb *pcb, struct tcp_seg *seg, struct tcp_seg *useg)
20195972f6Sopenharmony_ci-{
21195972f6Sopenharmony_ci-  if (TCP_TCPLEN(seg) > 0) {
22195972f6Sopenharmony_ci-    seg->next = NULL;
23195972f6Sopenharmony_ci-    if (useg == NULL) {
24195972f6Sopenharmony_ci-      pcb->unacked = seg;
25195972f6Sopenharmony_ci-      pcb->last_unacked = seg;
26195972f6Sopenharmony_ci-      useg = seg;
27195972f6Sopenharmony_ci-    } else {
28195972f6Sopenharmony_ci-      if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
29195972f6Sopenharmony_ci-        /* add segment to before tail of unacked list, keeping the list sorted */
30195972f6Sopenharmony_ci-        struct tcp_seg **cur_seg = &(pcb->unacked);
31195972f6Sopenharmony_ci-        while (*cur_seg &&
32195972f6Sopenharmony_ci-              TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
33195972f6Sopenharmony_ci-          cur_seg = &((*cur_seg)->next );
34195972f6Sopenharmony_ci-        }
35195972f6Sopenharmony_ci-        seg->next = (*cur_seg);
36195972f6Sopenharmony_ci-        (*cur_seg) = seg;
37195972f6Sopenharmony_ci-      } else {
38195972f6Sopenharmony_ci-        /* add segment to tail of unacked list */
39195972f6Sopenharmony_ci-        useg->next = seg;
40195972f6Sopenharmony_ci-        useg = seg;
41195972f6Sopenharmony_ci-        pcb->last_unacked = seg;
42195972f6Sopenharmony_ci-      }
43195972f6Sopenharmony_ci-    }
44195972f6Sopenharmony_ci-  } else {
45195972f6Sopenharmony_ci-    tcp_seg_free(seg);
46195972f6Sopenharmony_ci-  }
47195972f6Sopenharmony_ci-
48195972f6Sopenharmony_ci-  return useg;
49195972f6Sopenharmony_ci-}
50195972f6Sopenharmony_ci-static err_t tcp_output_seg(struct tcp_pcb *pcb, struct tcp_seg *seg, struct netif *netif, u32_t snd_nxt)
51195972f6Sopenharmony_ci-{
52195972f6Sopenharmony_ci-  if (pcb->state != SYN_SENT) {
53195972f6Sopenharmony_ci-    TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
54195972f6Sopenharmony_ci-  }
55195972f6Sopenharmony_ci-
56195972f6Sopenharmony_ci-  err_t err = tcp_output_segment(seg, pcb, netif);
57195972f6Sopenharmony_ci-  if (err != ERR_OK) {
58195972f6Sopenharmony_ci-    /* segment could not be sent, for whatever reason */
59195972f6Sopenharmony_ci-    tcp_set_flags(pcb, TF_NAGLEMEMERR);
60195972f6Sopenharmony_ci-    return err;
61195972f6Sopenharmony_ci-  }
62195972f6Sopenharmony_ci-
63195972f6Sopenharmony_ci-  if (pcb->state != SYN_SENT) {
64195972f6Sopenharmony_ci-    tcp_clear_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
65195972f6Sopenharmony_ci-  }
66195972f6Sopenharmony_ci-
67195972f6Sopenharmony_ci-  if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
68195972f6Sopenharmony_ci-      pcb->snd_nxt = snd_nxt;
69195972f6Sopenharmony_ci-  }
70195972f6Sopenharmony_ci-
71195972f6Sopenharmony_ci-  return ERR_OK;
72195972f6Sopenharmony_ci-}
73195972f6Sopenharmony_ci+u32_t start_seqno = 0;
74195972f6Sopenharmony_ci+#define TCP_INIT_SEGMENT(tem_seg, _pcb, _p, _hdrflags, _seqno, _optflags) \
75195972f6Sopenharmony_ci+do { \
76195972f6Sopenharmony_ci+  struct tcp_seg *_seg = tem_seg; \
77195972f6Sopenharmony_ci+  u8_t _optlen; \
78195972f6Sopenharmony_ci+  rte_prefetch2(_p); \
79195972f6Sopenharmony_ci+ \
80195972f6Sopenharmony_ci+  _optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(_optflags, _pcb); \
81195972f6Sopenharmony_ci+  _seg->flags = _optflags; \
82195972f6Sopenharmony_ci+  _seg->next = NULL; \
83195972f6Sopenharmony_ci+  _seg->p = _p; \
84195972f6Sopenharmony_ci+  _seg->len = _p->tot_len - _optlen; \
85195972f6Sopenharmony_ci+  /* build TCP header */ \
86195972f6Sopenharmony_ci+  pbuf_add_header(_p, TCP_HLEN); \
87195972f6Sopenharmony_ci+  _seg->tcphdr = (struct tcp_hdr *)_seg->p->payload; \
88195972f6Sopenharmony_ci+  _seg->tcphdr->src = lwip_htons(_pcb->local_port); \
89195972f6Sopenharmony_ci+  _seg->tcphdr->dest = lwip_htons(_pcb->remote_port); \
90195972f6Sopenharmony_ci+ /* _seg->tcphdr->src = lwip_htons(_pcb->local_port); \ */ \
91195972f6Sopenharmony_ci+ /* _seg->tcphdr->dest = lwip_htons(_pcb->remote_port); \ */ \
92195972f6Sopenharmony_ci+  _seg->tcphdr->seqno = lwip_htonl(_seqno); \
93195972f6Sopenharmony_ci+                                          \
94195972f6Sopenharmony_ci+  if (start_seqno == 0) {\
95195972f6Sopenharmony_ci+      start_seqno = _seqno; \
96195972f6Sopenharmony_ci+  } \
97195972f6Sopenharmony_ci+  TCPH_HDRLEN_FLAGS_SET(_seg->tcphdr, (5 + _optlen / 4), _hdrflags); \
98195972f6Sopenharmony_ci+  _seg->tcphdr->urgp = 0; \
99195972f6Sopenharmony_ci+} while(0)
100195972f6Sopenharmony_ci #endif
101195972f6Sopenharmony_ci /**
102195972f6Sopenharmony_ci  * @ingroup tcp_raw
103195972f6Sopenharmony_ci@@ -1471,97 +1444,127 @@ tcp_output(struct tcp_pcb *pcb)
104195972f6Sopenharmony_ci   pcb->persist_backoff = 0;
105195972f6Sopenharmony_ci 
106195972f6Sopenharmony_ci   /* useg should point to last segment on unacked queue */
107195972f6Sopenharmony_ci-  useg = pcb->last_unacked;
108195972f6Sopenharmony_ci+  useg = pcb->unacked;
109195972f6Sopenharmony_ci+  if (useg != NULL) {
110195972f6Sopenharmony_ci+    for (; useg->next != NULL; useg = useg->next);
111195972f6Sopenharmony_ci+  }
112195972f6Sopenharmony_ci 
113195972f6Sopenharmony_ci   /* data available and window allows it to be sent? */
114195972f6Sopenharmony_ci-
115195972f6Sopenharmony_ci-  u32_t send_len = 0;
116195972f6Sopenharmony_ci #if GAZELLE_ENABLE
117195972f6Sopenharmony_ci   if ((get_eth_params_tx_ol() & DEV_TX_OFFLOAD_TCP_TSO) && pcb->need_tso_send) {
118195972f6Sopenharmony_ci-    while(seg && send_len < 0xffff) {
119195972f6Sopenharmony_ci-      /**
120195972f6Sopenharmony_ci-       * 1) walk unsent queue, find all seg witch wait to send. chain buf in these segs.
121195972f6Sopenharmony_ci-       * 2) create new segment, send and free new segment.
122195972f6Sopenharmony_ci-       * 3) update snd_nxt, unacked queue, and unsent queue
123195972f6Sopenharmony_ci-       */
124195972f6Sopenharmony_ci-      struct tcp_seg *start_seg = seg;
125195972f6Sopenharmony_ci-      struct pbuf *first_pbuf = NULL;
126195972f6Sopenharmony_ci-      struct pbuf *pre_pbuf = NULL;
127195972f6Sopenharmony_ci-      u8_t pbuf_chain_len = 0;
128195972f6Sopenharmony_ci-      u32_t next_seqno = lwip_ntohl(seg->tcphdr->seqno);
129195972f6Sopenharmony_ci-      while (seg != NULL && pbuf_chain_len < GAZELLE_TCP_MAX_PBUF_CHAIN_LEN) {
130195972f6Sopenharmony_ci+     uint16_t send_pkt = 0;
131195972f6Sopenharmony_ci+
132195972f6Sopenharmony_ci+     do {
133195972f6Sopenharmony_ci+        struct tcp_seg * start_seg = seg;
134195972f6Sopenharmony_ci+        struct pbuf *new_pbuf = NULL;
135195972f6Sopenharmony_ci+
136195972f6Sopenharmony_ci+        struct pbuf *tmp_pbuf = NULL;
137195972f6Sopenharmony_ci         u32_t seg_seqno = lwip_ntohl(seg->tcphdr->seqno);
138195972f6Sopenharmony_ci-        if (seg_seqno - pcb->lastack + seg->len > wnd) {
139195972f6Sopenharmony_ci-          if (first_pbuf)
140195972f6Sopenharmony_ci-            break;
141195972f6Sopenharmony_ci-          else
142195972f6Sopenharmony_ci-            goto output_done;
143195972f6Sopenharmony_ci+        u32_t last_seg_seqno = seg_seqno;
144195972f6Sopenharmony_ci+
145195972f6Sopenharmony_ci+        struct tcp_seg *last_seg = NULL;
146195972f6Sopenharmony_ci+        u16_t last_seg_len = 0;
147195972f6Sopenharmony_ci+        u8_t pbuf_chain_len = 0;
148195972f6Sopenharmony_ci+        while (seg != NULL && seg_seqno - pcb->lastack + seg->len <= wnd && pbuf_chain_len < GAZELLE_TCP_MAX_PBUF_CHAIN_LEN) {
149195972f6Sopenharmony_ci+            if (last_seg_len != 0 && (last_seg_len + seg->len < 1460) && seg->len < GAZELLE_TCP_MIN_TSO_SEG_LEN) {
150195972f6Sopenharmony_ci+                break;
151195972f6Sopenharmony_ci+            }
152195972f6Sopenharmony_ci+
153195972f6Sopenharmony_ci+            if ((tcp_do_output_nagle(pcb) == 0) &&
154195972f6Sopenharmony_ci+                ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
155195972f6Sopenharmony_ci+                break;
156195972f6Sopenharmony_ci+            }
157195972f6Sopenharmony_ci+            if (last_seg_seqno + last_seg_len == seg_seqno) {
158195972f6Sopenharmony_ci+                pbuf_remove_header(seg->p, seg->p->tot_len - seg->len);
159195972f6Sopenharmony_ci+                if (new_pbuf == NULL) {
160195972f6Sopenharmony_ci+                    new_pbuf = seg->p;
161195972f6Sopenharmony_ci+                    tmp_pbuf = new_pbuf;
162195972f6Sopenharmony_ci+                } else {
163195972f6Sopenharmony_ci+                    new_pbuf->tot_len += seg->p->len;
164195972f6Sopenharmony_ci+                    tmp_pbuf->next = seg->p;
165195972f6Sopenharmony_ci+                    tmp_pbuf = tmp_pbuf->next;
166195972f6Sopenharmony_ci+                }
167195972f6Sopenharmony_ci+            } else {
168195972f6Sopenharmony_ci+                break;
169195972f6Sopenharmony_ci+            }
170195972f6Sopenharmony_ci+
171195972f6Sopenharmony_ci+            last_seg = seg;
172195972f6Sopenharmony_ci+            last_seg_len = seg->len;
173195972f6Sopenharmony_ci+            last_seg_seqno = seg_seqno;
174195972f6Sopenharmony_ci+            seg = seg->next;
175195972f6Sopenharmony_ci+            seg_seqno = (seg != NULL) ? lwip_ntohl(seg->tcphdr->seqno) : seg_seqno;
176195972f6Sopenharmony_ci+            pbuf_chain_len++;
177195972f6Sopenharmony_ci         }
178195972f6Sopenharmony_ci 
179195972f6Sopenharmony_ci-        if ((tcp_do_output_nagle(pcb) == 0) && ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
180195972f6Sopenharmony_ci-          if (first_pbuf)
181195972f6Sopenharmony_ci-            break;
182195972f6Sopenharmony_ci-          else
183195972f6Sopenharmony_ci-            goto output_done;
184195972f6Sopenharmony_ci+        // tcp_do_output_nagle, break
185195972f6Sopenharmony_ci+        if (new_pbuf == NULL) {
186195972f6Sopenharmony_ci+            goto end_loop;
187195972f6Sopenharmony_ci         }
188195972f6Sopenharmony_ci 
189195972f6Sopenharmony_ci-        if (seg->len < TCP_MSS || next_seqno != seg_seqno || pbuf_chain_len >= GAZELLE_TCP_MAX_PBUF_CHAIN_LEN) {
190195972f6Sopenharmony_ci-          break;
191195972f6Sopenharmony_ci-        }
192195972f6Sopenharmony_ci-        if (first_pbuf == NULL && (seg->next == NULL || seg->next->len < TCP_MSS)) {
193195972f6Sopenharmony_ci-          break;
194195972f6Sopenharmony_ci-        }
195195972f6Sopenharmony_ci+        struct tcp_seg new_seg;
196195972f6Sopenharmony_ci+        TCP_INIT_SEGMENT(&new_seg, pcb, new_pbuf, 0, lwip_ntohl(start_seg->tcphdr->seqno), 0);
197195972f6Sopenharmony_ci 
198195972f6Sopenharmony_ci-        pbuf_remove_header(seg->p, seg->p->tot_len - seg->len);
199195972f6Sopenharmony_ci-        if (first_pbuf == NULL) {
200195972f6Sopenharmony_ci-          first_pbuf = seg->p;
201195972f6Sopenharmony_ci-        } else {
202195972f6Sopenharmony_ci-          first_pbuf->tot_len += seg->p->len;
203195972f6Sopenharmony_ci-          pre_pbuf->next = seg->p;
204195972f6Sopenharmony_ci+        if (pcb->state != SYN_SENT) {
205195972f6Sopenharmony_ci+              TCPH_SET_FLAG(new_seg.tcphdr, TCP_ACK);
206195972f6Sopenharmony_ci         }
207195972f6Sopenharmony_ci 
208195972f6Sopenharmony_ci-        send_len += seg->len;
209195972f6Sopenharmony_ci-        pre_pbuf = seg->p;
210195972f6Sopenharmony_ci-        next_seqno = seg_seqno + TCP_TCPLEN(seg);
211195972f6Sopenharmony_ci-        seg = seg->next;
212195972f6Sopenharmony_ci-        pcb->unsent = seg;
213195972f6Sopenharmony_ci-        pbuf_chain_len++;
214195972f6Sopenharmony_ci-      }
215195972f6Sopenharmony_ci-
216195972f6Sopenharmony_ci-      if (first_pbuf == NULL) {
217195972f6Sopenharmony_ci-        err = tcp_output_seg(pcb, seg, netif, next_seqno + seg->len);
218195972f6Sopenharmony_ci+        err = tcp_output_segment(&new_seg, pcb, netif);
219195972f6Sopenharmony_ci         if (err != ERR_OK) {
220195972f6Sopenharmony_ci-          if (pcb->unsent == NULL)
221195972f6Sopenharmony_ci-            pcb->last_unsent = NULL;
222195972f6Sopenharmony_ci-	  pcb->need_tso_send = 0;
223195972f6Sopenharmony_ci-          return err;
224195972f6Sopenharmony_ci+            /* segment could not be sent, for whatever reason */
225195972f6Sopenharmony_ci+            tcp_set_flags(pcb, TF_NAGLEMEMERR);
226195972f6Sopenharmony_ci+            return err;
227195972f6Sopenharmony_ci         }
228195972f6Sopenharmony_ci-        pcb->unsent = seg->next;
229195972f6Sopenharmony_ci-        useg = tcp_output_over(pcb, seg, useg);
230195972f6Sopenharmony_ci-        seg = pcb->unsent;
231195972f6Sopenharmony_ci-        continue;
232195972f6Sopenharmony_ci-      }
233195972f6Sopenharmony_ci-
234195972f6Sopenharmony_ci-      struct tcp_seg new_seg;
235195972f6Sopenharmony_ci-      tcp_init_segment(&new_seg, pcb, first_pbuf, 0, lwip_ntohl(start_seg->tcphdr->seqno), 0);
236195972f6Sopenharmony_ci 
237195972f6Sopenharmony_ci-      err = tcp_output_seg(pcb, &new_seg, netif, next_seqno);
238195972f6Sopenharmony_ci+        pcb->unsent = last_seg->next;
239195972f6Sopenharmony_ci+        if (pcb->state != SYN_SENT) {
240195972f6Sopenharmony_ci+            tcp_clear_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
241195972f6Sopenharmony_ci+        }
242195972f6Sopenharmony_ci 
243195972f6Sopenharmony_ci-      for (u32_t i = 0; i < pbuf_chain_len; i++) {
244195972f6Sopenharmony_ci-        struct tcp_seg *next_seg = start_seg->next;
245195972f6Sopenharmony_ci-        start_seg->p->next = NULL;
246195972f6Sopenharmony_ci-        useg = tcp_output_over(pcb, start_seg, useg);
247195972f6Sopenharmony_ci-        start_seg = next_seg;
248195972f6Sopenharmony_ci-      }
249195972f6Sopenharmony_ci+        snd_nxt = last_seg_seqno + TCP_TCPLEN(last_seg);
250195972f6Sopenharmony_ci+        if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
251195972f6Sopenharmony_ci+            pcb->snd_nxt = snd_nxt;
252195972f6Sopenharmony_ci+        }
253195972f6Sopenharmony_ci 
254195972f6Sopenharmony_ci-      pbuf_remove_header(new_seg.p, new_seg.p->tot_len - new_seg.len - TCPH_HDRLEN_BYTES(new_seg.tcphdr));
255195972f6Sopenharmony_ci-      new_seg.p->tot_len = new_seg.p->len;
256195972f6Sopenharmony_ci-    }
257195972f6Sopenharmony_ci-  pcb->need_tso_send = 0;
258195972f6Sopenharmony_ci+        pbuf_remove_header(new_seg.p, new_seg.p->tot_len - new_seg.len - TCP_HLEN);
259195972f6Sopenharmony_ci+        new_seg.p->tot_len = new_seg.p->len;
260195972f6Sopenharmony_ci+
261195972f6Sopenharmony_ci+        for (int start = pbuf_chain_len; start > 0; start--) {
262195972f6Sopenharmony_ci+            struct tcp_seg *tmp_seg = start_seg;
263195972f6Sopenharmony_ci+            start_seg = start_seg->next;
264195972f6Sopenharmony_ci+            tmp_seg->p->next = NULL;
265195972f6Sopenharmony_ci+            if (TCP_TCPLEN(tmp_seg) > 0) {
266195972f6Sopenharmony_ci+                tmp_seg->next = NULL;
267195972f6Sopenharmony_ci+                if (pcb->unacked == NULL) {
268195972f6Sopenharmony_ci+                    pcb->unacked = tmp_seg;
269195972f6Sopenharmony_ci+                    useg = tmp_seg;
270195972f6Sopenharmony_ci+                } else {
271195972f6Sopenharmony_ci+                    if (TCP_SEQ_LT(lwip_ntohl(tmp_seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
272195972f6Sopenharmony_ci+                        /* add segment to before tail of unacked list, keeping the list sorted */
273195972f6Sopenharmony_ci+                        struct tcp_seg **cur_seg = &(pcb->unacked);
274195972f6Sopenharmony_ci+                        while (*cur_seg &&
275195972f6Sopenharmony_ci+                            TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(tmp_seg->tcphdr->seqno)))     {
276195972f6Sopenharmony_ci+                            cur_seg = &((*cur_seg)->next );
277195972f6Sopenharmony_ci+                        }
278195972f6Sopenharmony_ci+                        tmp_seg->next = (*cur_seg);
279195972f6Sopenharmony_ci+                        (*cur_seg) = tmp_seg;
280195972f6Sopenharmony_ci+                    } else {
281195972f6Sopenharmony_ci+                        /* add segment to tail of unacked list */
282195972f6Sopenharmony_ci+                        useg->next = tmp_seg;
283195972f6Sopenharmony_ci+                        useg = useg->next;
284195972f6Sopenharmony_ci+                    }
285195972f6Sopenharmony_ci+                }
286195972f6Sopenharmony_ci+            } else {
287195972f6Sopenharmony_ci+              tcp_seg_free(tmp_seg);
288195972f6Sopenharmony_ci+            }
289195972f6Sopenharmony_ci+        }
290195972f6Sopenharmony_ci+     } while(seg != NULL && lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd && send_pkt++ < 10);
291195972f6Sopenharmony_ci+end_loop:
292195972f6Sopenharmony_ci+    pcb->need_tso_send = 0;
293195972f6Sopenharmony_ci   } else
294195972f6Sopenharmony_ci #endif
295195972f6Sopenharmony_ci {
296195972f6Sopenharmony_ci-  while (seg != NULL && send_len < 0xffff &&
297195972f6Sopenharmony_ci+  uint16_t send_pkt = 0;
298195972f6Sopenharmony_ci+  while (seg != NULL && send_pkt++ < 10 &&
299195972f6Sopenharmony_ci          lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
300195972f6Sopenharmony_ci     LWIP_ASSERT("RST not expected here!",
301195972f6Sopenharmony_ci                 (TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
302195972f6Sopenharmony_ci@@ -1576,7 +1579,6 @@ tcp_output(struct tcp_pcb *pcb)
303195972f6Sopenharmony_ci         ((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)) {
304195972f6Sopenharmony_ci       break;
305195972f6Sopenharmony_ci     }
306195972f6Sopenharmony_ci-    send_len += seg->len;
307195972f6Sopenharmony_ci #if TCP_CWND_DEBUG
308195972f6Sopenharmony_ci     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",
309195972f6Sopenharmony_ci                                  pcb->snd_wnd, pcb->cwnd, wnd,
310195972f6Sopenharmony_cidiff --git a/src/include/lwipopts.h b/src/include/lwipopts.h
311195972f6Sopenharmony_ciindex 742b4a9..0d2a6d9 100644
312195972f6Sopenharmony_ci--- a/src/include/lwipopts.h
313195972f6Sopenharmony_ci+++ b/src/include/lwipopts.h
314195972f6Sopenharmony_ci@@ -55,6 +55,8 @@
315195972f6Sopenharmony_ci 
316195972f6Sopenharmony_ci #define GAZELLE_TCP_MAX_PBUF_CHAIN_LEN 40
317195972f6Sopenharmony_ci 
318195972f6Sopenharmony_ci+#define GAZELLE_TCP_MIN_TSO_SEG_LEN 256
319195972f6Sopenharmony_ci+
320195972f6Sopenharmony_ci /*
321195972f6Sopenharmony_ci    ----------------------------------
322195972f6Sopenharmony_ci    ---------- NIC offloads ----------
323195972f6Sopenharmony_ci-- 
324195972f6Sopenharmony_ci2.33.0
325195972f6Sopenharmony_ci
326