This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 12c0cc7ca723f20bedbd532a29a20449c5175d67
Author: raiden00pl <[email protected]>
AuthorDate: Thu Oct 22 14:03:10 2026 +0200

    net/sixlowpan: fill the TCP header like tcp_send()
    
    6LoWPAN built its TCP header with a copy of tcp_sendcommon() that never
    started the retransmission timer, so a lost segment was not resent, and
    did not scale the receive window. Export the header fill of
    tcp_sendcommon() as tcp_fill_header() and use it, with the segment
    counted as unacknowledged first.
    
    Assisted-by: Claude Code
    Signed-off-by: raiden00pl <[email protected]>
---
 net/sixlowpan/sixlowpan_tcpsend.c | 68 +++++++++------------------------------
 net/tcp/tcp.h                     | 25 ++++++++++++++
 net/tcp/tcp_send.c                | 42 ++++++++++++++++++++----
 3 files changed, 76 insertions(+), 59 deletions(-)

diff --git a/net/sixlowpan/sixlowpan_tcpsend.c 
b/net/sixlowpan/sixlowpan_tcpsend.c
index 8ead0f64459..57069ad883c 100644
--- a/net/sixlowpan/sixlowpan_tcpsend.c
+++ b/net/sixlowpan/sixlowpan_tcpsend.c
@@ -228,50 +228,9 @@ static int sixlowpan_tcp_header(FAR struct tcp_conn_s 
*conn,
 
   /* Initialize the TCP header */
 
-  ipv6tcp->tcp.srcport   = conn->lport;           /* Local port */
-  ipv6tcp->tcp.destport  = conn->rport;           /* Connected remote port */
-
   ipv6tcp->tcp.tcpoffset = (TCP_HDRLEN / 4) << 4; /* No optdata */
   ipv6tcp->tcp.flags     = TCP_ACK | TCP_PSH;     /* No urgent data */
-  ipv6tcp->tcp.urgp[0]   = 0;                     /* No urgent data */
-  ipv6tcp->tcp.urgp[1]   = 0;
-
-  /* Set the sequency number information.
-   *
-   * REVISIT:  There is currently no wait for the data to be ACKed and,
-   * hence, no mechanism to retransmit the packet.
-   */
-
-  memcpy(ipv6tcp->tcp.ackno, conn->rcvseq, 4);    /* ACK number */
-  memcpy(ipv6tcp->tcp.seqno, conn->sndseq, 4);    /* Sequence number */
-
-  /* Set the TCP window */
-
-  if (conn->tcpstateflags & TCP_STOPPED)
-    {
-      /* If the connection has issued TCP_STOPPED, we advertise a zero
-       * window so that the remote host will stop sending data.
-       */
-
-      ipv6tcp->tcp.wnd[0] = 0;
-      ipv6tcp->tcp.wnd[1] = 0;
-    }
-  else
-    {
-      /* Update the TCP received window based on I/O buffer availability */
-
-      uint32_t rcvseq = tcp_getsequence(conn->rcvseq);
-      uint32_t recvwndo = tcp_get_recvwindow(dev, conn);
-
-      /* Set the TCP Window */
-
-      ipv6tcp->tcp.wnd[0] = recvwndo >> 8;
-      ipv6tcp->tcp.wnd[1] = recvwndo & 0xff;
-
-      /* Update the Receiver Window */
-
-      conn->rcv_adv = rcvseq + recvwndo;
-    }
+  tcp_fill_header(dev, conn, &ipv6tcp->tcp);
 
   /* Calculate TCP checksum. */
 
@@ -475,6 +434,18 @@ static uint32_t tcp_send_eventhandler(FAR struct 
net_driver_s *dev,
 
           tcp_setsequence(conn->sndseq, seqno);
 
+          /* Count the segment as unacknowledged before the header is
+           * built, which starts the retransmission timer for it.
+           *
+           * NOTE: tcp_appsend() normally increments conn->tx_unacked based
+           * on the value of dev->d_sndlen.  However, dev->d_len is always
+           * zero for 6LoWPAN since it does not send via the dev->d_buf
+           * but, rather, uses a backdoor frame interface with the IEEE
+           * 802.15.4 MAC.
+           */
+
+          conn->tx_unacked += sndlen;
+
           /* Create the IPv6 + TCP header */
 
           ret = sixlowpan_tcp_header(conn, dev, &sinfo->s_buf[sinfo->s_sent],
@@ -499,18 +470,11 @@ static uint32_t tcp_send_eventhandler(FAR struct 
net_driver_s *dev,
               goto end_wait;
             }
 
-          /* Increment the count of bytes sent, the number of unacked bytes,
-           * and the total count of TCP packets sent.
-           *
-           * NOTE: tcp_appsend() normally increments conn->tx_unacked based
-           * on the value of dev->d_sndlen.  However, dev->d_len is always
-           * zero for 6LoWPAN since it does not send via the dev->d_buf
-           * but, rather, uses a backdoor frame interface with the IEEE
-           * 802.15.4 MAC.
+          /* Increment the count of bytes sent and the total count of TCP
+           * packets sent.
            */
 
-          sinfo->s_sent    += sndlen;
-          conn->tx_unacked += sndlen;
+          sinfo->s_sent += sndlen;
 
 #ifdef CONFIG_NET_TCP_WRITE_BUFFERS
           /* For compatibility with buffered send logic */
diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h
index 09d2fcddb76..13c5843897d 100644
--- a/net/tcp/tcp.h
+++ b/net/tcp/tcp.h
@@ -1172,6 +1172,31 @@ bool tcp_islistener(FAR union ip_binding_u *uaddr, 
uint16_t portno);
 int tcp_accept_connection(FAR struct net_driver_s *dev,
                           FAR struct tcp_conn_s *conn, uint16_t portno);
 
+/****************************************************************************
+ * Name: tcp_fill_header
+ *
+ * Description:
+ *   Fill in the sequence and acknowledgment numbers, the ports, the receive
+ *   window and the urgent pointer of an outgoing TCP header, and start the
+ *   retransmission timer if there is unacknowledged data.
+ *
+ * Input Parameters:
+ *   dev  - The device driver structure to use in the send operation
+ *   conn - The TCP connection structure holding connection information
+ *   tcp  - The TCP header to fill in
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called with the network locked.
+ *
+ ****************************************************************************/
+
+void tcp_fill_header(FAR struct net_driver_s *dev,
+                     FAR struct tcp_conn_s *conn,
+                     FAR struct tcp_hdr_s *tcp);
+
 /****************************************************************************
  * Name: tcp_send
  *
diff --git a/net/tcp/tcp_send.c b/net/tcp/tcp_send.c
index 419b2aafcee..cdf30630c18 100644
--- a/net/tcp/tcp_send.c
+++ b/net/tcp/tcp_send.c
@@ -105,16 +105,17 @@ static inline FAR struct tcp_hdr_s *tcp_header(FAR struct 
net_driver_s *dev)
 }
 
 /****************************************************************************
- * Name: tcp_sendcommon
+ * Name: tcp_fill_header
  *
  * Description:
- *   We're done with the input processing. We are now ready to send a reply
- *   Our job is to fill in all the fields of the TCP and IP headers before
- *   calculating the checksum and finally send the packet.
+ *   Fill in the sequence and acknowledgment numbers, the ports, the receive
+ *   window and the urgent pointer of an outgoing TCP header, and start the
+ *   retransmission timer if there is unacknowledged data.
  *
  * Input Parameters:
  *   dev  - The device driver structure to use in the send operation
  *   conn - The TCP connection structure holding connection information
+ *   tcp  - The TCP header to fill in
  *
  * Returned Value:
  *   None
@@ -124,9 +125,9 @@ static inline FAR struct tcp_hdr_s *tcp_header(FAR struct 
net_driver_s *dev)
  *
  ****************************************************************************/
 
-static void tcp_sendcommon(FAR struct net_driver_s *dev,
-                           FAR struct tcp_conn_s *conn,
-                           FAR struct tcp_hdr_s *tcp)
+void tcp_fill_header(FAR struct net_driver_s *dev,
+                     FAR struct tcp_conn_s *conn,
+                     FAR struct tcp_hdr_s *tcp)
 {
   /* Set TCP sequence numbers and port numbers */
 
@@ -176,6 +177,33 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev,
 
   tcp->urgp[0] = 0;
   tcp->urgp[1] = 0;
+}
+
+/****************************************************************************
+ * Name: tcp_sendcommon
+ *
+ * Description:
+ *   We're done with the input processing. We are now ready to send a reply
+ *   Our job is to fill in all the fields of the TCP and IP headers before
+ *   calculating the checksum and finally send the packet.
+ *
+ * Input Parameters:
+ *   dev  - The device driver structure to use in the send operation
+ *   conn - The TCP connection structure holding connection information
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called with the network locked.
+ *
+ ****************************************************************************/
+
+static void tcp_sendcommon(FAR struct net_driver_s *dev,
+                           FAR struct tcp_conn_s *conn,
+                           FAR struct tcp_hdr_s *tcp)
+{
+  tcp_fill_header(dev, conn, tcp);
 
   /* Update device buffer length before setup the IP header */
 

Reply via email to