You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2023/01/10 05:46:44 UTC

[GitHub] [nuttx] anchao opened a new pull request, #8062: net/tcp: add Selective-ACK support

anchao opened a new pull request, #8062:
URL: https://github.com/apache/nuttx/pull/8062

   ## Summary
   
   net/tcp: add Selective-ACK support
   net/tcp: parse tcp options in common function
   net/tcp: add out-of-order segment support
   net/tcp: new api tcp_dataconcat() to concatenate/pack iob chain
   
   Reference:
   https://datatracker.ietf.org/doc/html/rfc2018
   
   ## Impact
   
   N/A
   
   ## Testing
   
   iperf tcp test


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] anchao commented on pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
anchao commented on PR #8062:
URL: https://github.com/apache/nuttx/pull/8062#issuecomment-1381349239

   > Hi @anchao do you have iperf results before and after this PR? Did you test with ESP32?
   
   Hi, @acassis 
   I added a tcp drop test, and the result is updated in the comment. after enabling OFO/SACK, iperf passthrough has improved significantly
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] acassis commented on pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
acassis commented on PR #8062:
URL: https://github.com/apache/nuttx/pull/8062#issuecomment-1380378993

   Hi @anchao do you have iperf results before and after this PR? Did you test with ESP32?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] pkarashchenko commented on a diff in pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on code in PR #8062:
URL: https://github.com/apache/nuttx/pull/8062#discussion_r1069143021


##########
net/tcp/tcp.h:
##########
@@ -144,6 +149,23 @@ struct tcp_poll_s
   FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
 };
 
+/* Out-of-order segments */
+
+struct tcp_ofoseg_s
+{
+  uint32_t     left;  /* Left edge of segment */
+  uint32_t     right; /* Right edge of segment */
+  struct iob_s *data; /* Out-of-order buffering */

Review Comment:
   ```suggestion
     FAR struct iob_s *data; /* Out-of-order buffering */
   ```



##########
net/tcp/tcp_callback.c:
##########
@@ -94,10 +94,156 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   return flags;
 }
 
+/****************************************************************************
+ * Name: tcp_ofoseg_data_event
+ *
+ * Description:
+ *   Handle out-of-order segment to readahead poll.
+ *
+ * Assumptions:
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+static uint16_t tcp_ofoseg_data_event(FAR struct net_driver_s *dev,
+                                      FAR struct tcp_conn_s *conn,
+                                      uint16_t flags)
+{
+  struct tcp_ofoseg_s *seg;
+  uint32_t rcvseq;
+  int i;
+
+  /* Assume that we will ACK the data.  The data will be ACKed if it is
+   * placed in the read-ahead buffer -OR- if it zero length
+   */
+
+  flags |= TCP_SNDACK;
+
+  /* Get the receive sequence number */
+
+  rcvseq = tcp_getsequence(conn->rcvseq);
+
+  ninfo("TCP OFOSEG rcvseq [%" PRIu32 "]\n", rcvseq);
+
+  /* Foreach out-of-order segments */
+
+  i = 0;

Review Comment:
   ```suggestion
   ```



##########
net/tcp/tcp_callback.c:
##########
@@ -94,10 +94,156 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   return flags;
 }
 
+/****************************************************************************
+ * Name: tcp_ofoseg_data_event
+ *
+ * Description:
+ *   Handle out-of-order segment to readahead poll.
+ *
+ * Assumptions:
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+static uint16_t tcp_ofoseg_data_event(FAR struct net_driver_s *dev,
+                                      FAR struct tcp_conn_s *conn,
+                                      uint16_t flags)
+{
+  struct tcp_ofoseg_s *seg;

Review Comment:
   ```suggestion
     FAR struct tcp_ofoseg_s *seg;
   ```



##########
net/tcp/tcp_input.c:
##########
@@ -257,6 +257,370 @@ static void tcp_snd_wnd_update(FAR struct tcp_conn_s *conn,
     }
 }
 
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+
+/****************************************************************************
+ * Name: tcp_rebuild_ofosegs
+ *
+ * Description:
+ *   Re-build out-of-order pool from incoming segment
+ *
+ * Input Parameters:
+ *   conn   - The TCP connection of interest
+ *   ofoseg - Pointer to incoming out-of-order segment
+ *   start  - Index of start postion of segment pool
+ *
+ * Returned Value:
+ *   True if incoming data has been consumed
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static bool tcp_rebuild_ofosegs(FAR struct tcp_conn_s *conn,
+                                FAR struct tcp_ofoseg_s *ofoseg,
+                                int start)
+{
+  struct tcp_ofoseg_s *seg;
+  int i;
+
+  for (i = start; i < conn->nofosegs && ofoseg->data != NULL; i++)
+    {
+      seg = &conn->ofosegs[i];
+
+      /* ofoseg    |~~~
+       * segpool |---|
+       */
+
+      if (TCP_SEQ_GTE(ofoseg->left, seg->left))
+        {
+          /* ofoseg        |---|
+           * segpool |---|
+           */
+
+          if (TCP_SEQ_GT(ofoseg->left, seg->right))
+            {
+              continue;
+            }
+
+          /* ofoseg      |---|
+           * segpool |---|
+           */
+
+          else if (ofoseg->left == seg->right)
+            {
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+
+          /* ofoseg   |--|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_LTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(ofoseg->data);
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg    |---|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->right))
+            {
+              ofoseg->data =
+                iob_trimhead(ofoseg->data,
+                             TCP_SEQ_SUB(seg->right, ofoseg->left));
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+        }
+
+      /* ofoseg  |~~~
+       * segpool   |---|
+       */
+
+      else
+        {
+          /* ofoseg  |---|
+           * segpool     |---|
+           */
+
+          if (ofoseg->right == seg->left)
+            {
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool       |---|
+           */
+
+          else if (TCP_SEQ_LT(ofoseg->right, seg->left))
+            {
+              continue;
+            }
+
+          /* ofoseg  |---|~|
+           * segpool  |--|
+           */
+
+          else if (TCP_SEQ_GTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(seg->data);
+              *seg = *ofoseg;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool   |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->left))
+            {
+              ofoseg->data =
+                iob_trimtail(ofoseg->data,
+                             ofoseg->right - seg->left);
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+        }
+    }
+
+  return (ofoseg->data == NULL);
+}
+
+/****************************************************************************
+ * Name: tcp_input_ofosegs
+ *
+ * Description:
+ *   Handle incoming TCP data to out-of-order pool
+ *
+ * Input Parameters:
+ *   dev    - The device driver structure containing the received TCP packet.
+ *   conn   - The TCP connection of interest
+ *   iplen  - Length of the IP header (IPv4_HDRLEN or IPv6_HDRLEN).
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void tcp_input_ofosegs(FAR struct net_driver_s *dev,
+                              FAR struct tcp_conn_s *conn,
+                              unsigned int iplen)
+{
+  struct tcp_ofoseg_s ofoseg;
+  bool rebuild;
+  int len;
+  int i;

Review Comment:
   ```suggestion
     int i = 0;
   ```



##########
net/tcp/tcp_input.c:
##########
@@ -257,6 +257,370 @@ static void tcp_snd_wnd_update(FAR struct tcp_conn_s *conn,
     }
 }
 
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+
+/****************************************************************************
+ * Name: tcp_rebuild_ofosegs
+ *
+ * Description:
+ *   Re-build out-of-order pool from incoming segment
+ *
+ * Input Parameters:
+ *   conn   - The TCP connection of interest
+ *   ofoseg - Pointer to incoming out-of-order segment
+ *   start  - Index of start postion of segment pool
+ *
+ * Returned Value:
+ *   True if incoming data has been consumed
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static bool tcp_rebuild_ofosegs(FAR struct tcp_conn_s *conn,
+                                FAR struct tcp_ofoseg_s *ofoseg,
+                                int start)
+{
+  struct tcp_ofoseg_s *seg;
+  int i;
+
+  for (i = start; i < conn->nofosegs && ofoseg->data != NULL; i++)
+    {
+      seg = &conn->ofosegs[i];
+
+      /* ofoseg    |~~~
+       * segpool |---|
+       */
+
+      if (TCP_SEQ_GTE(ofoseg->left, seg->left))
+        {
+          /* ofoseg        |---|
+           * segpool |---|
+           */
+
+          if (TCP_SEQ_GT(ofoseg->left, seg->right))
+            {
+              continue;
+            }
+
+          /* ofoseg      |---|
+           * segpool |---|
+           */
+
+          else if (ofoseg->left == seg->right)
+            {
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+
+          /* ofoseg   |--|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_LTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(ofoseg->data);
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg    |---|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->right))
+            {
+              ofoseg->data =
+                iob_trimhead(ofoseg->data,
+                             TCP_SEQ_SUB(seg->right, ofoseg->left));
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+        }
+
+      /* ofoseg  |~~~
+       * segpool   |---|
+       */
+
+      else
+        {
+          /* ofoseg  |---|
+           * segpool     |---|
+           */
+
+          if (ofoseg->right == seg->left)
+            {
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool       |---|
+           */
+
+          else if (TCP_SEQ_LT(ofoseg->right, seg->left))
+            {
+              continue;
+            }
+
+          /* ofoseg  |---|~|
+           * segpool  |--|
+           */
+
+          else if (TCP_SEQ_GTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(seg->data);
+              *seg = *ofoseg;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool   |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->left))
+            {
+              ofoseg->data =
+                iob_trimtail(ofoseg->data,
+                             ofoseg->right - seg->left);
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+        }
+    }
+
+  return (ofoseg->data == NULL);
+}
+
+/****************************************************************************
+ * Name: tcp_input_ofosegs
+ *
+ * Description:
+ *   Handle incoming TCP data to out-of-order pool
+ *
+ * Input Parameters:
+ *   dev    - The device driver structure containing the received TCP packet.
+ *   conn   - The TCP connection of interest
+ *   iplen  - Length of the IP header (IPv4_HDRLEN or IPv6_HDRLEN).
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void tcp_input_ofosegs(FAR struct net_driver_s *dev,
+                              FAR struct tcp_conn_s *conn,
+                              unsigned int iplen)
+{
+  struct tcp_ofoseg_s ofoseg;
+  bool rebuild;
+  int len;
+  int i;
+
+  ofoseg.left =
+    tcp_getsequence(((FAR struct tcp_hdr_s *)IPBUF(iplen))->seqno);
+
+  /* Calculate the pending size of out-of-order cache, if the input edge can
+   * not fill the adjacent segments, drop it
+   */
+
+  if (tcp_ofoseg_bufsize(conn) > CONFIG_NET_TCP_OUT_OF_ORDER_BUFSIZE &&
+      ofoseg.left >= conn->ofosegs[0].left)
+    {
+      return;
+    }
+
+  /* Get left/right edge from incoming data */
+
+  len = (dev->d_appdata - dev->d_iob->io_data) - dev->d_iob->io_offset;
+  ofoseg.right = TCP_SEQ_ADD(ofoseg.left, dev->d_iob->io_pktlen - len);
+
+  ninfo("TCP OFOSEG out-of-order "
+        "[%" PRIu32 " : %" PRIu32 " : %" PRIu32 "]\n",
+        ofoseg.left, ofoseg.right, TCP_SEQ_SUB(ofoseg.right, ofoseg.left));
+
+  /* Trim l3/l4 header to reserve appdata */
+
+  dev->d_iob = iob_trimhead(dev->d_iob, len);
+  if (dev->d_iob == NULL)
+    {
+      /* No available data, clear device buffer */
+
+      goto clear;
+    }
+
+  ofoseg.data = dev->d_iob;
+
+  /* Build out-of-order pool */
+
+  rebuild = tcp_rebuild_ofosegs(conn, &ofoseg, 0);
+
+  /* Incoming segment out of order from existing pool, add to new segment */
+
+  if (!rebuild && conn->nofosegs != TCP_SACK_RANGES_MAX)
+    {
+      conn->ofosegs[conn->nofosegs] = ofoseg;
+      conn->nofosegs++;
+      rebuild = true;
+    }
+
+  /* Try Re-order ofosegs */
+
+  if (rebuild &&
+      tcp_reorder_ofosegs(conn->nofosegs, (FAR void *)conn->ofosegs))
+    {
+      /* Re-build out-of-order pool after re-order */
+
+      i = 0;
+      while (i < conn->nofosegs - 1)

Review Comment:
   ```suggestion
         while (i < conn->nofosegs - 1)
   ```
   or change to `for`



##########
net/tcp/tcp_callback.c:
##########
@@ -94,10 +94,156 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   return flags;
 }
 
+/****************************************************************************
+ * Name: tcp_ofoseg_data_event
+ *
+ * Description:
+ *   Handle out-of-order segment to readahead poll.
+ *
+ * Assumptions:
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+static uint16_t tcp_ofoseg_data_event(FAR struct net_driver_s *dev,
+                                      FAR struct tcp_conn_s *conn,
+                                      uint16_t flags)
+{
+  struct tcp_ofoseg_s *seg;
+  uint32_t rcvseq;
+  int i;

Review Comment:
   ```suggestion
     int i = 0;
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] anchao commented on a diff in pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
anchao commented on code in PR #8062:
URL: https://github.com/apache/nuttx/pull/8062#discussion_r1069156779


##########
net/tcp/tcp_callback.c:
##########
@@ -94,10 +94,156 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   return flags;
 }
 
+/****************************************************************************
+ * Name: tcp_ofoseg_data_event
+ *
+ * Description:
+ *   Handle out-of-order segment to readahead poll.
+ *
+ * Assumptions:
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+static uint16_t tcp_ofoseg_data_event(FAR struct net_driver_s *dev,
+                                      FAR struct tcp_conn_s *conn,
+                                      uint16_t flags)
+{
+  struct tcp_ofoseg_s *seg;

Review Comment:
   Done



##########
net/tcp/tcp.h:
##########
@@ -144,6 +149,23 @@ struct tcp_poll_s
   FAR struct devif_callback_s *cb; /* Needed to teardown the poll */
 };
 
+/* Out-of-order segments */
+
+struct tcp_ofoseg_s
+{
+  uint32_t     left;  /* Left edge of segment */
+  uint32_t     right; /* Right edge of segment */
+  struct iob_s *data; /* Out-of-order buffering */

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] anchao commented on a diff in pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
anchao commented on code in PR #8062:
URL: https://github.com/apache/nuttx/pull/8062#discussion_r1069156527


##########
net/tcp/tcp_input.c:
##########
@@ -257,6 +257,370 @@ static void tcp_snd_wnd_update(FAR struct tcp_conn_s *conn,
     }
 }
 
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+
+/****************************************************************************
+ * Name: tcp_rebuild_ofosegs
+ *
+ * Description:
+ *   Re-build out-of-order pool from incoming segment
+ *
+ * Input Parameters:
+ *   conn   - The TCP connection of interest
+ *   ofoseg - Pointer to incoming out-of-order segment
+ *   start  - Index of start postion of segment pool
+ *
+ * Returned Value:
+ *   True if incoming data has been consumed
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static bool tcp_rebuild_ofosegs(FAR struct tcp_conn_s *conn,
+                                FAR struct tcp_ofoseg_s *ofoseg,
+                                int start)
+{
+  struct tcp_ofoseg_s *seg;
+  int i;
+
+  for (i = start; i < conn->nofosegs && ofoseg->data != NULL; i++)
+    {
+      seg = &conn->ofosegs[i];
+
+      /* ofoseg    |~~~
+       * segpool |---|
+       */
+
+      if (TCP_SEQ_GTE(ofoseg->left, seg->left))
+        {
+          /* ofoseg        |---|
+           * segpool |---|
+           */
+
+          if (TCP_SEQ_GT(ofoseg->left, seg->right))
+            {
+              continue;
+            }
+
+          /* ofoseg      |---|
+           * segpool |---|
+           */
+
+          else if (ofoseg->left == seg->right)
+            {
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+
+          /* ofoseg   |--|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_LTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(ofoseg->data);
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg    |---|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->right))
+            {
+              ofoseg->data =
+                iob_trimhead(ofoseg->data,
+                             TCP_SEQ_SUB(seg->right, ofoseg->left));
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+        }
+
+      /* ofoseg  |~~~
+       * segpool   |---|
+       */
+
+      else
+        {
+          /* ofoseg  |---|
+           * segpool     |---|
+           */
+
+          if (ofoseg->right == seg->left)
+            {
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool       |---|
+           */
+
+          else if (TCP_SEQ_LT(ofoseg->right, seg->left))
+            {
+              continue;
+            }
+
+          /* ofoseg  |---|~|
+           * segpool  |--|
+           */
+
+          else if (TCP_SEQ_GTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(seg->data);
+              *seg = *ofoseg;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool   |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->left))
+            {
+              ofoseg->data =
+                iob_trimtail(ofoseg->data,
+                             ofoseg->right - seg->left);
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+        }
+    }
+
+  return (ofoseg->data == NULL);
+}
+
+/****************************************************************************
+ * Name: tcp_input_ofosegs
+ *
+ * Description:
+ *   Handle incoming TCP data to out-of-order pool
+ *
+ * Input Parameters:
+ *   dev    - The device driver structure containing the received TCP packet.
+ *   conn   - The TCP connection of interest
+ *   iplen  - Length of the IP header (IPv4_HDRLEN or IPv6_HDRLEN).
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void tcp_input_ofosegs(FAR struct net_driver_s *dev,
+                              FAR struct tcp_conn_s *conn,
+                              unsigned int iplen)
+{
+  struct tcp_ofoseg_s ofoseg;
+  bool rebuild;
+  int len;
+  int i;

Review Comment:
   Done



##########
net/tcp/tcp_input.c:
##########
@@ -257,6 +257,370 @@ static void tcp_snd_wnd_update(FAR struct tcp_conn_s *conn,
     }
 }
 
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+
+/****************************************************************************
+ * Name: tcp_rebuild_ofosegs
+ *
+ * Description:
+ *   Re-build out-of-order pool from incoming segment
+ *
+ * Input Parameters:
+ *   conn   - The TCP connection of interest
+ *   ofoseg - Pointer to incoming out-of-order segment
+ *   start  - Index of start postion of segment pool
+ *
+ * Returned Value:
+ *   True if incoming data has been consumed
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static bool tcp_rebuild_ofosegs(FAR struct tcp_conn_s *conn,
+                                FAR struct tcp_ofoseg_s *ofoseg,
+                                int start)
+{
+  struct tcp_ofoseg_s *seg;
+  int i;
+
+  for (i = start; i < conn->nofosegs && ofoseg->data != NULL; i++)
+    {
+      seg = &conn->ofosegs[i];
+
+      /* ofoseg    |~~~
+       * segpool |---|
+       */
+
+      if (TCP_SEQ_GTE(ofoseg->left, seg->left))
+        {
+          /* ofoseg        |---|
+           * segpool |---|
+           */
+
+          if (TCP_SEQ_GT(ofoseg->left, seg->right))
+            {
+              continue;
+            }
+
+          /* ofoseg      |---|
+           * segpool |---|
+           */
+
+          else if (ofoseg->left == seg->right)
+            {
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+
+          /* ofoseg   |--|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_LTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(ofoseg->data);
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg    |---|
+           * segpool |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->right))
+            {
+              ofoseg->data =
+                iob_trimhead(ofoseg->data,
+                             TCP_SEQ_SUB(seg->right, ofoseg->left));
+              tcp_dataconcat(&seg->data, &ofoseg->data);
+              seg->right = ofoseg->right;
+            }
+        }
+
+      /* ofoseg  |~~~
+       * segpool   |---|
+       */
+
+      else
+        {
+          /* ofoseg  |---|
+           * segpool     |---|
+           */
+
+          if (ofoseg->right == seg->left)
+            {
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool       |---|
+           */
+
+          else if (TCP_SEQ_LT(ofoseg->right, seg->left))
+            {
+              continue;
+            }
+
+          /* ofoseg  |---|~|
+           * segpool  |--|
+           */
+
+          else if (TCP_SEQ_GTE(ofoseg->right, seg->right))
+            {
+              iob_free_chain(seg->data);
+              *seg = *ofoseg;
+              ofoseg->data = NULL;
+            }
+
+          /* ofoseg  |---|
+           * segpool   |---|
+           */
+
+          else if (TCP_SEQ_GT(ofoseg->right, seg->left))
+            {
+              ofoseg->data =
+                iob_trimtail(ofoseg->data,
+                             ofoseg->right - seg->left);
+              tcp_dataconcat(&ofoseg->data, &seg->data);
+              seg->data = ofoseg->data;
+              seg->left = ofoseg->left;
+              ofoseg->data = NULL;
+            }
+        }
+    }
+
+  return (ofoseg->data == NULL);
+}
+
+/****************************************************************************
+ * Name: tcp_input_ofosegs
+ *
+ * Description:
+ *   Handle incoming TCP data to out-of-order pool
+ *
+ * Input Parameters:
+ *   dev    - The device driver structure containing the received TCP packet.
+ *   conn   - The TCP connection of interest
+ *   iplen  - Length of the IP header (IPv4_HDRLEN or IPv6_HDRLEN).
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   The network is locked.
+ *
+ ****************************************************************************/
+
+static void tcp_input_ofosegs(FAR struct net_driver_s *dev,
+                              FAR struct tcp_conn_s *conn,
+                              unsigned int iplen)
+{
+  struct tcp_ofoseg_s ofoseg;
+  bool rebuild;
+  int len;
+  int i;
+
+  ofoseg.left =
+    tcp_getsequence(((FAR struct tcp_hdr_s *)IPBUF(iplen))->seqno);
+
+  /* Calculate the pending size of out-of-order cache, if the input edge can
+   * not fill the adjacent segments, drop it
+   */
+
+  if (tcp_ofoseg_bufsize(conn) > CONFIG_NET_TCP_OUT_OF_ORDER_BUFSIZE &&
+      ofoseg.left >= conn->ofosegs[0].left)
+    {
+      return;
+    }
+
+  /* Get left/right edge from incoming data */
+
+  len = (dev->d_appdata - dev->d_iob->io_data) - dev->d_iob->io_offset;
+  ofoseg.right = TCP_SEQ_ADD(ofoseg.left, dev->d_iob->io_pktlen - len);
+
+  ninfo("TCP OFOSEG out-of-order "
+        "[%" PRIu32 " : %" PRIu32 " : %" PRIu32 "]\n",
+        ofoseg.left, ofoseg.right, TCP_SEQ_SUB(ofoseg.right, ofoseg.left));
+
+  /* Trim l3/l4 header to reserve appdata */
+
+  dev->d_iob = iob_trimhead(dev->d_iob, len);
+  if (dev->d_iob == NULL)
+    {
+      /* No available data, clear device buffer */
+
+      goto clear;
+    }
+
+  ofoseg.data = dev->d_iob;
+
+  /* Build out-of-order pool */
+
+  rebuild = tcp_rebuild_ofosegs(conn, &ofoseg, 0);
+
+  /* Incoming segment out of order from existing pool, add to new segment */
+
+  if (!rebuild && conn->nofosegs != TCP_SACK_RANGES_MAX)
+    {
+      conn->ofosegs[conn->nofosegs] = ofoseg;
+      conn->nofosegs++;
+      rebuild = true;
+    }
+
+  /* Try Re-order ofosegs */
+
+  if (rebuild &&
+      tcp_reorder_ofosegs(conn->nofosegs, (FAR void *)conn->ofosegs))
+    {
+      /* Re-build out-of-order pool after re-order */
+
+      i = 0;
+      while (i < conn->nofosegs - 1)

Review Comment:
   Done



##########
net/tcp/tcp_callback.c:
##########
@@ -94,10 +94,156 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   return flags;
 }
 
+/****************************************************************************
+ * Name: tcp_ofoseg_data_event
+ *
+ * Description:
+ *   Handle out-of-order segment to readahead poll.
+ *
+ * Assumptions:
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+static uint16_t tcp_ofoseg_data_event(FAR struct net_driver_s *dev,
+                                      FAR struct tcp_conn_s *conn,
+                                      uint16_t flags)
+{
+  struct tcp_ofoseg_s *seg;
+  uint32_t rcvseq;
+  int i;

Review Comment:
   Done



##########
net/tcp/tcp_callback.c:
##########
@@ -94,10 +94,156 @@ tcp_data_event(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
   return flags;
 }
 
+/****************************************************************************
+ * Name: tcp_ofoseg_data_event
+ *
+ * Description:
+ *   Handle out-of-order segment to readahead poll.
+ *
+ * Assumptions:
+ * - This function must be called with the network locked.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NET_TCP_OUT_OF_ORDER
+static uint16_t tcp_ofoseg_data_event(FAR struct net_driver_s *dev,
+                                      FAR struct tcp_conn_s *conn,
+                                      uint16_t flags)
+{
+  struct tcp_ofoseg_s *seg;
+  uint32_t rcvseq;
+  int i;
+
+  /* Assume that we will ACK the data.  The data will be ACKed if it is
+   * placed in the read-ahead buffer -OR- if it zero length
+   */
+
+  flags |= TCP_SNDACK;
+
+  /* Get the receive sequence number */
+
+  rcvseq = tcp_getsequence(conn->rcvseq);
+
+  ninfo("TCP OFOSEG rcvseq [%" PRIu32 "]\n", rcvseq);
+
+  /* Foreach out-of-order segments */
+
+  i = 0;

Review Comment:
   Done



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] pkarashchenko commented on pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
pkarashchenko commented on PR #8062:
URL: https://github.com/apache/nuttx/pull/8062#issuecomment-1381030456

   I will review this PR in upcoming days.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] xiaoxiang781216 merged pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
xiaoxiang781216 merged PR #8062:
URL: https://github.com/apache/nuttx/pull/8062


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [nuttx] anchao commented on pull request #8062: net/tcp: add Selective-ACK support (RFC2018)

Posted by GitBox <gi...@apache.org>.
anchao commented on PR #8062:
URL: https://github.com/apache/nuttx/pull/8062#issuecomment-1381354567

   The detailed test results as below: (config esp32c3-devkit/wapi)
   
   TCP server:
   Original:
   ```
   $ iperf -c 192.168.31.197 -i 1
   ------------------------------------------------------------
   Client connecting to 192.168.31.197, TCP port 5001
   TCP window size:  102 KByte (default)
   ------------------------------------------------------------
   [  3] local 192.168.31.180 port 52172 connected with 192.168.31.197 port 5001
   [ ID] Interval       Transfer     Bandwidth
   [  3]  0.0- 1.0 sec  1.75 MBytes  14.7 Mbits/sec
   [  3]  1.0- 2.0 sec  1.38 MBytes  11.5 Mbits/sec
   [  3]  2.0- 3.0 sec  1.38 MBytes  11.5 Mbits/sec
   [  3]  3.0- 4.0 sec  1.38 MBytes  11.5 Mbits/sec
   [  3]  4.0- 5.0 sec  1.62 MBytes  13.6 Mbits/sec
   [  3]  5.0- 6.0 sec  1.38 MBytes  11.5 Mbits/sec
   [  3]  6.0- 7.0 sec  1.50 MBytes  12.6 Mbits/sec
   [  3]  7.0- 8.0 sec  1.38 MBytes  11.5 Mbits/sec
   [  3]  8.0- 9.0 sec  1.50 MBytes  12.6 Mbits/sec
   [  3]  9.0-10.0 sec  1.38 MBytes  11.5 Mbits/sec
   [  3]  0.0-10.0 sec  14.6 MBytes  12.3 Mbits/sec
   ```
   Drop(1/50):
   ```
   CONFIG_NET_TCP_DEBUG_DROP_RECV=y
   CONFIG_NET_TCP_DEBUG_DROP_RECV_PROBABILITY=50  // Drop probability: 1/50
   ```
   ```
   $ iperf -c 192.168.31.197 -i 1
   ------------------------------------------------------------
   Client connecting to 192.168.31.197, TCP port 5001
   TCP window size:  102 KByte (default)
   ------------------------------------------------------------
   [  3] local 192.168.31.180 port 47072 connected with 192.168.31.197 port 5001
   [ ID] Interval       Transfer     Bandwidth
   [  3]  0.0- 1.0 sec   442 KBytes  3.62 Mbits/sec
   [  3]  1.0- 2.0 sec   128 KBytes  1.05 Mbits/sec
   [  3]  2.0- 3.0 sec  17.1 KBytes   140 Kbits/sec
   [  3]  3.0- 4.0 sec  0.00 Bytes  0.00 bits/sec
   [  3]  4.0- 5.0 sec  59.9 KBytes   491 Kbits/sec
   [  3]  5.0- 6.0 sec  85.5 KBytes   701 Kbits/sec
   [  3]  6.0- 7.0 sec  0.00 Bytes  0.00 bits/sec
   [  3]  7.0- 8.0 sec  77.0 KBytes   631 Kbits/sec
   [  3]  8.0- 9.0 sec  68.4 KBytes   561 Kbits/sec
   [  3]  9.0-10.0 sec   103 KBytes   841 Kbits/sec
   [  3]  0.0-10.0 sec   981 KBytes   802 Kbits/sec
   ```
   
   Drop(1/50) + OFO/SACK:
   ```
   CONFIG_NET_TCP_DEBUG_DROP_RECV=y
   CONFIG_NET_TCP_DEBUG_DROP_RECV_PROBABILITY=50  // Drop probability: 1/50
   
   CONFIG_NET_TCP_OUT_OF_ORDER=y
   CONFIG_NET_TCP_SELECTIVE_ACK=y
   ```
   ```
   $ iperf -c 192.168.31.197 -i 1
   ------------------------------------------------------------
   Client connecting to 192.168.31.197, TCP port 5001
   TCP window size:  102 KByte (default)
   ------------------------------------------------------------
   [  3] local 192.168.31.180 port 59374 connected with 192.168.31.197 port 5001
   [ ID] Interval       Transfer     Bandwidth
   [  3]  0.0- 1.0 sec   896 KBytes  7.34 Mbits/sec
   [  3]  1.0- 2.0 sec   896 KBytes  7.34 Mbits/sec
   [  3]  2.0- 3.0 sec   896 KBytes  7.34 Mbits/sec
   [  3]  3.0- 4.0 sec   768 KBytes  6.29 Mbits/sec
   [  3]  4.0- 5.0 sec   896 KBytes  7.34 Mbits/sec
   [  3]  5.0- 6.0 sec   896 KBytes  7.34 Mbits/sec
   [  3]  6.0- 7.0 sec   768 KBytes  6.29 Mbits/sec
   [  3]  7.0- 8.0 sec   896 KBytes  7.34 Mbits/sec
   [  3]  8.0- 9.0 sec  1.00 MBytes  8.39 Mbits/sec
   [  3]  9.0-10.0 sec   896 KBytes  7.34 Mbits/sec
   [  3]  0.0-10.2 sec  8.62 MBytes  7.11 Mbits/sec
   ```
   
   
   
   
   
   
   
   TCP client:
   Original:
   ```
   $ iperf -s -i 1
   ------------------------------------------------------------
   Server listening on TCP port 5001
   TCP window size:  128 KByte (default)
   ------------------------------------------------------------
   [  4] local 192.168.31.180 port 5001 connected with 192.168.31.197 port 5974
   [ ID] Interval       Transfer     Bandwidth
   [  4]  0.0- 1.0 sec  1.14 MBytes  9.60 Mbits/sec
   [  4]  1.0- 2.0 sec   981 KBytes  8.04 Mbits/sec
   [  4]  2.0- 3.0 sec   930 KBytes  7.62 Mbits/sec
   [  4]  3.0- 4.0 sec  1.20 MBytes  10.0 Mbits/sec
   [  4]  4.0- 5.0 sec  1.05 MBytes  8.79 Mbits/sec
   [  4]  5.0- 6.0 sec  1.04 MBytes  8.71 Mbits/sec
   [  4]  6.0- 7.0 sec  1.07 MBytes  8.96 Mbits/sec
   [  4]  7.0- 8.0 sec  1.04 MBytes  8.75 Mbits/sec
   [  4]  8.0- 9.0 sec  1.10 MBytes  9.20 Mbits/sec
   [  4]  9.0-10.0 sec   992 KBytes  8.13 Mbits/sec
   ```
   
   Drop(1/50):
   ```
   CONFIG_NET_TCP_DEBUG_DROP_SEND=y
   CONFIG_NET_TCP_DEBUG_DROP_SEND_PROBABILITY=50  // Drop probability: 1/50
   ```
   ```
   $ iperf -s -i 1
   ------------------------------------------------------------
   Server listening on TCP port 5001
   TCP window size:  128 KByte (default)
   ------------------------------------------------------------
   [  4] local 192.168.31.180 port 5001 connected with 192.168.31.197 port 13006
   [ ID] Interval       Transfer     Bandwidth
   [  4]  0.0- 1.0 sec  50.9 KBytes   417 Kbits/sec
   [  4]  1.0- 2.0 sec  31.8 KBytes   260 Kbits/sec
   [  4]  2.0- 3.0 sec  0.00 Bytes  0.00 bits/sec
   [  4]  3.0- 4.0 sec  36.0 KBytes   295 Kbits/sec
   [  4]  4.0- 5.0 sec  34.7 KBytes   285 Kbits/sec
   [  4]  5.0- 6.0 sec  23.1 KBytes   189 Kbits/sec
   [  4]  6.0- 7.0 sec  4.47 KBytes  36.6 Kbits/sec
   [  4]  7.0- 8.0 sec  36.0 KBytes   295 Kbits/sec
   [  4]  8.0- 9.0 sec  26.2 KBytes   214 Kbits/sec
   [  4]  9.0-10.0 sec  4.28 KBytes  35.0 Kbits/sec
   [  4] 10.0-11.0 sec  84.1 KBytes   689 Kbits/sec
   ```
   
   Drop(1/50) + OFO/SACK:
   ```
   CONFIG_NET_TCP_DEBUG_DROP_SEND=y
   CONFIG_NET_TCP_DEBUG_DROP_SEND_PROBABILITY=50  // Drop probability: 1/50
   
   CONFIG_NET_TCP_OUT_OF_ORDER=y
   CONFIG_NET_TCP_SELECTIVE_ACK=y
   ```
   
   ```
   $ iperf -s -i 1
   ------------------------------------------------------------
   Server listening on TCP port 5001
   TCP window size:  128 KByte (default)
   ------------------------------------------------------------
   [  4] local 192.168.31.180 port 5001 connected with 192.168.31.197 port 5446
   [ ID] Interval       Transfer     Bandwidth
   [  4]  0.0- 1.0 sec  1.02 MBytes  8.57 Mbits/sec
   [  4]  1.0- 2.0 sec   916 KBytes  7.51 Mbits/sec
   [  4]  2.0- 3.0 sec   770 KBytes  6.31 Mbits/sec
   [  4]  3.0- 4.0 sec   979 KBytes  8.02 Mbits/sec
   [  4]  4.0- 5.0 sec   929 KBytes  7.61 Mbits/sec
   [  4]  5.0- 6.0 sec  1.02 MBytes  8.58 Mbits/sec
   [  4]  6.0- 7.0 sec   989 KBytes  8.10 Mbits/sec
   [  4]  7.0- 8.0 sec  1006 KBytes  8.24 Mbits/sec
   [  4]  8.0- 9.0 sec   919 KBytes  7.53 Mbits/sec
   [  4]  9.0-10.0 sec  1022 KBytes  8.37 Mbits/sec
   [  4] 10.0-11.0 sec   998 KBytes  8.18 Mbits/sec
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org