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 */
