• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From be56e9eed8acf82a862d19ef4f890f309018ddde Mon Sep 17 00:00:00 2001
2From: jiangheng <jiangheng14@huawei.com>
3Date: Sat, 28 Oct 2023 17:21:46 +0800
4Subject: [PATCH] adapt read/write for rtc mode
5
6---
7 src/api/api_msg.c      |  14 ++--
8 src/api/sockets.c      |  21 ++---
9 src/core/init.c        |   2 +-
10 src/core/pbuf.c        |   7 ++
11 src/core/tcp_out.c     | 171 +++++++++++++++++++++++++++++++++--------
12 src/core/udp.c         |   2 +-
13 src/include/lwip/tcp.h |   4 +
14 src/include/lwipopts.h |   6 +-
15 8 files changed, 174 insertions(+), 53 deletions(-)
16
17diff --git a/src/api/api_msg.c b/src/api/api_msg.c
18index 3e982ab..d8b99ee 100644
19--- a/src/api/api_msg.c
20+++ b/src/api/api_msg.c
21@@ -1753,11 +1753,15 @@ lwip_netconn_do_writemore(struct netconn *conn  WRITE_DELAYED_PARAM)
22         write_more = 0;
23       }
24 #if GAZELLE_ENABLE
25-      /* vector->ptr is private arg sock */
26-      LWIP_UNUSED_ARG(dataptr);
27-      write_more = 0;
28-      err = tcp_write(conn->pcb.tcp, conn->current_msg->msg.w.vector->ptr, len, apiflags);
29-      conn->current_msg->msg.w.len = len;
30+      if (netif_is_rtc_mode(netif_default)) {
31+        err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
32+      } else {
33+        /* vector->ptr is private arg sock */
34+        LWIP_UNUSED_ARG(dataptr);
35+        write_more = 0;
36+        err = tcp_write_from_stack(conn->pcb.tcp, conn->current_msg->msg.w.vector->ptr, len, apiflags);
37+        conn->current_msg->msg.w.len = len;
38+      }
39       conn->pcb.tcp->need_tso_send = 1;
40 #else
41       err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
42diff --git a/src/api/sockets.c b/src/api/sockets.c
43index 8d573aa..e374f96 100644
44--- a/src/api/sockets.c
45+++ b/src/api/sockets.c
46@@ -1087,7 +1087,15 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
47     apiflags |= NETCONN_DONTBLOCK;
48   }
49
50-#if !GAZELLE_ENABLE
51+#if GAZELLE_ENABLE
52+  if (!netif_is_rtc_mode(netif_default)) {
53+    LWIP_UNUSED_ARG(recv_left);
54+    recvd = do_lwip_read_from_lwip(sock, flags, apiflags);
55+    if (recvd <= 0) {
56+      return recvd;
57+    }
58+  } else {
59+#endif
60   do {
61     struct pbuf *p;
62     err_t err;
63@@ -1166,15 +1174,10 @@ lwip_recv_tcp(struct lwip_sock *sock, void *mem, size_t len, int flags)
64     apiflags |= NETCONN_DONTBLOCK | NETCONN_NOFIN;
65     /* @todo: do we need to support peeking more than one pbuf? */
66   } while ((recv_left > 0) && !(flags & MSG_PEEK));
67-
68-lwip_recv_tcp_done:
69-#else /* GAZELLE_ENABLE */
70-  LWIP_UNUSED_ARG(recv_left);
71-  recvd = do_lwip_read_from_lwip(sock, flags, apiflags);
72-  if (recvd <= 0) {
73-    return recvd;
74+#if GAZELLE_ENABLE
75   }
76-#endif /* GAZELLE_ENABLE */
77+#endif
78+lwip_recv_tcp_done:
79   if (apiflags & NETCONN_NOAUTORCVD) {
80     if ((recvd > 0) && !(flags & MSG_PEEK)) {
81       /* ensure window update after copying all data */
82diff --git a/src/core/init.c b/src/core/init.c
83index 7b6214f..60e1c68 100644
84--- a/src/core/init.c
85+++ b/src/core/init.c
86@@ -306,7 +306,7 @@ PACK_STRUCT_END
87 #if TCP_SNDLOWAT >= TCP_SND_BUF
88 #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
89 #endif
90-#if TCP_SNDLOWAT >= (0xFFFFFFFF - (4 * TCP_MSS))
91+#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
92 #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
93 #endif
94 #if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
95diff --git a/src/core/pbuf.c b/src/core/pbuf.c
96index 975e240..61690ff 100644
97--- a/src/core/pbuf.c
98+++ b/src/core/pbuf.c
99@@ -117,6 +117,7 @@ pbuf_skip_const(const struct pbuf *in, u16_t in_offset, u16_t *out_offset);
100 volatile u8_t pbuf_free_ooseq_pending;
101 #define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
102
103+#if !GAZELLE_ENABLE
104 /**
105  * Attempt to reclaim some memory from queued out-of-sequence TCP segments
106  * if we run out of pool pbufs. It's better to give priority to new packets
107@@ -176,6 +177,7 @@ pbuf_pool_is_empty(void)
108   }
109 #endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
110 }
111+#endif /* GAZELLE_ENABLE */
112 #endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */
113
114 /* Initialize members of struct pbuf after allocation */
115@@ -238,6 +240,10 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
116       p = pbuf_alloc_reference(NULL, length, type);
117       break;
118     case PBUF_POOL: {
119+#if GAZELLE_ENABLE
120+      // alloc from pktmbuf pool, one pbuf is enough
121+      p = do_lwip_alloc_pbuf(layer, length, type);
122+#else
123       struct pbuf *q, *last;
124       u16_t rem_len; /* remaining length */
125       p = NULL;
126@@ -273,6 +279,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
127         rem_len = (u16_t)(rem_len - qlen);
128         offset = 0;
129       } while (rem_len > 0);
130+#endif /* GAZELLE_ENABLE */
131       break;
132     }
133     case PBUF_RAM: {
134diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c
135index e2c9d63..073d989 100644
136--- a/src/core/tcp_out.c
137+++ b/src/core/tcp_out.c
138@@ -515,15 +515,18 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
139    * pos records progress as data is segmented.
140    */
141
142-#if !GAZELLE_ENABLE
143   /* Find the tail of the unsent queue. */
144   if (pcb->unsent != NULL) {
145     u16_t space;
146     u16_t unsent_optlen;
147
148+#if GAZELLE_ENABLE
149+    last_unsent = pcb->last_unsent;
150+#else
151     /* @todo: this could be sped up by keeping last_unsent in the pcb */
152     for (last_unsent = pcb->unsent; last_unsent->next != NULL;
153          last_unsent = last_unsent->next);
154+#endif
155
156     /* Usable space at the end of the last unsent segment */
157     unsent_optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(last_unsent->flags, pcb);
158@@ -631,9 +634,6 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
159                 pcb->unsent_oversize == 0);
160 #endif /* TCP_OVERSIZE */
161   }
162-#else /* GAZELLE_ENABLE */
163-  last_unsent = pcb->last_unsent;
164-#endif /* GAZELLE_ENABLE */
165
166   /*
167    * Phase 3: Create new segments.
168@@ -651,7 +651,6 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
169     u8_t chksum_swapped = 0;
170 #endif /* TCP_CHECKSUM_ON_COPY */
171
172-#if !GAZELLE_ENABLE
173     if (apiflags & TCP_WRITE_FLAG_COPY) {
174       /* If copy is set, memory should be allocated and data copied
175        * into pbuf */
176@@ -698,13 +697,6 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
177       /* Concatenate the headers and data pbufs together. */
178       pbuf_cat(p/*header*/, p2/*data*/);
179     }
180-#else  /* GAZELLE_ENABLE */
181-    p = do_lwip_get_from_sendring((struct lwip_sock *)arg, len - pos, &apiflags);
182-    if (p == NULL) {
183-      break;
184-    }
185-    seglen = p->tot_len;
186-#endif  /* GAZELLE_ENABLE */
187
188     queuelen += pbuf_clen(p);
189
190@@ -714,14 +706,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
191     if (queuelen > LWIP_MIN(TCP_SND_QUEUELEN, TCP_SNDQUEUELEN_OVERFLOW)) {
192       LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n",
193                   queuelen, (int)TCP_SND_QUEUELEN));
194-#if GAZELLE_ENABLE
195-      if (pos > 0) {
196-        queuelen -= pbuf_clen(p);
197-        break;
198-      }
199-#else
200       pbuf_free(p);
201-#endif
202       goto memerr;
203     }
204
205@@ -730,12 +715,6 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
206 #endif
207
208     if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
209-#if GAZELLE_ENABLE
210-      if (pos > 0) {
211-        queuelen -= pbuf_clen(p);
212-        break;
213-      }
214-#endif
215       goto memerr;
216     }
217 #if TCP_OVERSIZE_DBGCHECK
218@@ -763,9 +742,6 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
219                 lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
220
221     pos += seglen;
222-#if GAZELLE_ENABLE
223-    do_lwip_get_from_sendring_over((struct lwip_sock*)arg);
224-#endif
225   }
226
227   /*
228@@ -855,12 +831,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
229   if (queue) {
230     pcb->last_unsent = prev_seg;
231   }
232-  pcb->snd_lbb += pos;
233-  pcb->snd_buf -= pos;
234-#else
235+#endif
236   pcb->snd_lbb += len;
237   pcb->snd_buf -= len;
238-#endif
239   pcb->snd_queuelen = queuelen;
240
241   LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n",
242@@ -880,14 +853,12 @@ memerr:
243   tcp_set_flags(pcb, TF_NAGLEMEMERR);
244   TCP_STATS_INC(tcp.memerr);
245
246-#if !GAZELLE_ENABLE
247   if (concat_p != NULL) {
248     pbuf_free(concat_p);
249   }
250   if (queue != NULL) {
251     tcp_segs_free(queue);
252   }
253-#endif
254   if (pcb->snd_queuelen != 0) {
255     LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL ||
256                 pcb->unsent != NULL);
257@@ -896,6 +867,137 @@ memerr:
258   return ERR_MEM;
259 }
260
261+#if GAZELLE_ENABLE
262+err_t
263+tcp_write_from_stack(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
264+{
265+  struct tcp_seg *last_unsent = NULL, *seg = NULL, *prev_seg = NULL, *queue = NULL;
266+  u16_t pos = 0; /* position in 'arg' data */
267+  u16_t queuelen;
268+  u8_t optlen;
269+  u8_t optflags = 0;
270+  err_t err;
271+  u16_t mss_local;
272+
273+  /* don't allocate segments bigger than half the maximum window we ever received */
274+  mss_local = LWIP_MIN(pcb->mss, TCPWND_MIN16(pcb->snd_wnd_max / 2));
275+  mss_local = mss_local ? mss_local : pcb->mss;
276+
277+  err = tcp_write_checks(pcb, len);
278+  if (err != ERR_OK) {
279+    return err;
280+  }
281+  queuelen = pcb->snd_queuelen;
282+
283+  optlen = LWIP_TCP_OPT_LENGTH_SEGMENT(0, pcb);
284+
285+  last_unsent = pcb->last_unsent;
286+
287+  /*
288+   * get pbuf from sendring and create new segments.
289+   */
290+  while (pos < len) {
291+    struct pbuf *p;
292+    u16_t left = len - pos;
293+    u16_t max_len = mss_local - optlen;
294+    u16_t seglen = LWIP_MIN(left, max_len);
295+
296+    p = do_lwip_get_from_sendring((struct lwip_sock *)arg, len - pos, &apiflags);
297+    if (p == NULL) {
298+      break;
299+    }
300+    seglen = p->tot_len;
301+
302+    queuelen += pbuf_clen(p);
303+
304+    /* Now that there are more segments queued, we check again if the
305+     * length of the queue exceeds the configured maximum or
306+     * overflows. */
307+    if (queuelen > LWIP_MIN(TCP_SND_QUEUELEN, TCP_SNDQUEUELEN_OVERFLOW)) {
308+      LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("tcp_write: queue too long %"U16_F" (%d)\n",
309+                  queuelen, (int)TCP_SND_QUEUELEN));
310+      if (pos > 0) {
311+        queuelen -= pbuf_clen(p);
312+        break;
313+      }
314+      goto memerr;
315+    }
316+
317+    lstack_calculate_aggregate(2, p->tot_len);
318+
319+    if ((seg = tcp_create_segment(pcb, p, 0, pcb->snd_lbb + pos, optflags)) == NULL) {
320+      if (pos > 0) {
321+        queuelen -= pbuf_clen(p);
322+        break;
323+      }
324+      goto memerr;
325+    }
326+
327+    /* first segment of to-be-queued data? */
328+    if (queue == NULL) {
329+      queue = seg;
330+    } else {
331+      /* Attach the segment to the end of the queued segments */
332+      LWIP_ASSERT("prev_seg != NULL", prev_seg != NULL);
333+      prev_seg->next = seg;
334+    }
335+    /* remember last segment of to-be-queued data for next iteration */
336+    prev_seg = seg;
337+
338+    LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n",
339+                lwip_ntohl(seg->tcphdr->seqno),
340+                lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
341+
342+    pos += seglen;
343+    do_lwip_get_from_sendring_over((struct lwip_sock*)arg);
344+  }
345+
346+  /*
347+   * Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
348+   * is harmless
349+   */
350+  if (last_unsent == NULL) {
351+    pcb->unsent = queue;
352+  } else {
353+    last_unsent->next = queue;
354+  }
355+
356+  /*
357+   * Finally update the pcb state.
358+   */
359+  if (queue) {
360+    pcb->last_unsent = prev_seg;
361+  }
362+  pcb->snd_lbb += pos;
363+  pcb->snd_buf -= pos;
364+  pcb->snd_queuelen = queuelen;
365+
366+  LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_write: %"S16_F" (after enqueued)\n",
367+                               pcb->snd_queuelen));
368+  if (pcb->snd_queuelen != 0) {
369+    LWIP_ASSERT("tcp_write: valid queue length",
370+                pcb->unacked != NULL || pcb->unsent != NULL);
371+  }
372+
373+  /* Set the PSH flag in the last segment that we enqueued. */
374+  if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE) == 0)) {
375+    TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
376+  }
377+
378+  return ERR_OK;
379+memerr:
380+  tcp_set_flags(pcb, TF_NAGLEMEMERR);
381+  TCP_STATS_INC(tcp.memerr);
382+
383+  if (pcb->snd_queuelen != 0) {
384+    LWIP_ASSERT("tcp_write: valid queue length", pcb->unacked != NULL ||
385+                pcb->unsent != NULL);
386+  }
387+  LWIP_DEBUGF(TCP_QLEN_DEBUG | LWIP_DBG_STATE, ("tcp_write: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
388+  return ERR_MEM;
389+}
390+#endif
391+
392 /**
393  * Split segment on the head of the unsent queue.  If return is not
394  * ERR_OK, existing head remains intact
395@@ -2095,6 +2197,7 @@ tcp_rexmit(struct tcp_pcb *pcb)
396
397   /* Don't take any rtt measurements after retransmitting. */
398   pcb->rttest = 0;
399+  pcb->need_tso_send = 1;
400
401   /* Do the actual retransmission. */
402   MIB2_STATS_INC(mib2.tcpretranssegs);
403diff --git a/src/core/udp.c b/src/core/udp.c
404index 937a045..828a489 100644
405--- a/src/core/udp.c
406+++ b/src/core/udp.c
407@@ -414,7 +414,7 @@ udp_input(struct pbuf *p, struct netif *inp)
408         if (udphdr->chksum != 0) {
409 #if CHECKSUM_CHECK_UDP_HW
410           u64_t ret = 0;
411-          if (netif_get_txol_flags(inp) & DEV_RX_OFFLOAD_UDP_CKSUM) {
412+          if (netif_get_rxol_flags(inp) & DEV_RX_OFFLOAD_UDP_CKSUM) {
413             ret = is_cksum_bad(p);
414           } else {
415             ret = ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len,
416diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h
417index e13099c..959df3e 100644
418--- a/src/include/lwip/tcp.h
419+++ b/src/include/lwip/tcp.h
420@@ -567,6 +567,10 @@ err_t            tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx);
421
422 err_t            tcp_write   (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
423                               u8_t apiflags);
424+#if GAZELLE_ENABLE
425+err_t            tcp_write_from_stack (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
426+                                       u8_t apiflags);
427+#endif
428
429 void             tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
430
431diff --git a/src/include/lwipopts.h b/src/include/lwipopts.h
432index baf739e..fdd4f87 100644
433--- a/src/include/lwipopts.h
434+++ b/src/include/lwipopts.h
435@@ -208,8 +208,8 @@
436 #define TCP_LISTEN_BACKLOG 1
437 #define TCP_DEFAULT_LISTEN_BACKLOG 0xff
438
439-#define TCP_OVERSIZE 0
440-#define LWIP_NETIF_TX_SINGLE_PBUF 0
441+#define TCP_OVERSIZE TCP_MSS
442+#define LWIP_NETIF_TX_SINGLE_PBUF 1
443
444 #define TCP_MSS (FRAME_MTU - IP_HLEN - TCP_HLEN)
445
446@@ -219,7 +219,7 @@
447
448 #define TCP_SND_QUEUELEN (8191)
449
450-#define TCP_SNDLOWAT (TCP_SND_BUF / 5)
451+#define TCP_SNDLOWAT (32768)
452
453 #define TCP_SNDQUEUELOWAT (TCP_SND_QUEUELEN / 5)
454
455--
4562.27.0
457
458