a-lunev commented on a change in pull request #4659:
URL: https://github.com/apache/incubator-nuttx/pull/4659#discussion_r727627443



##########
File path: net/tcp/tcp_send_unbuffered.c
##########
@@ -243,18 +243,54 @@ static uint16_t tcpsend_eventhandler(FAR struct 
net_driver_s *dev,
 
   else if ((flags & TCP_REXMIT) != 0)
     {
+#if defined(CONFIG_NET_TCP_SPLIT)
       /* Yes.. in this case, reset the number of bytes that have been sent
        * to the number of bytes that have been ACKed.
        */
 
       pstate->snd_sent = pstate->snd_acked;

Review comment:
       Yes, it does. I wrote about this in the PR summary. It contradicts to 
RFC 6298 (5.4) and other TCP related RFCs. Possibly it was done intentionally 
as a workaround (as I understand, CONFIG_NET_TCP_SPLIT algorithm is some sort 
of a trick as it is described in the source code comments).
   If CONFIG_NET_TCP_SPLIT was planned to be removed, the removing would 
simplify this part of the code.

##########
File path: net/tcp/tcp_send_unbuffered.c
##########
@@ -243,18 +243,54 @@ static uint16_t tcpsend_eventhandler(FAR struct 
net_driver_s *dev,
 
   else if ((flags & TCP_REXMIT) != 0)
     {
+#if defined(CONFIG_NET_TCP_SPLIT)
       /* Yes.. in this case, reset the number of bytes that have been sent
        * to the number of bytes that have been ACKed.
        */
 
       pstate->snd_sent = pstate->snd_acked;

Review comment:
       I understand that part of code as follows:
   Here is an example:
   ```
   pstate->snd_sent = 0, pstate->snd_acked = 0: SND.seq = 100 (it's ISN), len = 
10 -> receiver successfully gets the segment by ACKing with RCV.ack = 110.
   pstate->snd_sent = 10, pstate->snd_acked = 10: SND.seq = 110, len = 10 -> 
the segment is lost somewhere in the network
   pstate->snd_sent = 20, pstate->snd_acked = 10: SND.seq = 120, len = 10 -> 
receiver gets the segment, however still ACKing with RCV.ack = 110.
   pstate->snd_sent = 30, pstate->snd_acked = 10: SND.seq = 130, len = 10 -> 
receiver gets the segment, however still ACKing with RCV.ack = 110.
   pstate->snd_sent = 40, pstate->snd_acked = 10: SND.seq = 140, len = 10 -> 
receiver gets the segment, however still ACKing with RCV.ack = 110.
   ```
   
   Due to timeout NuttX TCP sender sets pstate->snd_sent variable back to 10 as 
follows:
   ```
   pstate->snd_sent = 10, pstate->snd_acked = 10: SND.seq = 110, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 120.
   pstate->snd_sent = 20, pstate->snd_acked = 20: SND.seq = 120, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 130.
   pstate->snd_sent = 30, pstate->snd_acked = 30: SND.seq = 130, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 140.
   pstate->snd_sent = 40, pstate->snd_acked = 40: SND.seq = 140, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 150.
   ```
   Thus in this example it re-sends all 4 segments instead of only one segment 
with SND.seq = 110.

##########
File path: net/tcp/tcp_send_unbuffered.c
##########
@@ -243,18 +243,54 @@ static uint16_t tcpsend_eventhandler(FAR struct 
net_driver_s *dev,
 
   else if ((flags & TCP_REXMIT) != 0)
     {
+#if defined(CONFIG_NET_TCP_SPLIT)
       /* Yes.. in this case, reset the number of bytes that have been sent
        * to the number of bytes that have been ACKed.
        */
 
       pstate->snd_sent = pstate->snd_acked;

Review comment:
       I understand that part of code as follows:
   Here is an example:
   ```
   pstate->snd_sent = 0, pstate->snd_acked = 0: SND.seq = 100 (it's ISN), len = 
10 -> receiver successfully gets the segment by ACKing with RCV.ack = 110.
   pstate->snd_sent = 10, pstate->snd_acked = 10: SND.seq = 110, len = 10 -> 
the segment is lost somewhere in the network
   pstate->snd_sent = 20, pstate->snd_acked = 10: SND.seq = 120, len = 10 -> 
receiver gets the segment, however still ACKing with RCV.ack = 110.
   pstate->snd_sent = 30, pstate->snd_acked = 10: SND.seq = 130, len = 10 -> 
receiver gets the segment, however still ACKing with RCV.ack = 110.
   pstate->snd_sent = 40, pstate->snd_acked = 10: SND.seq = 140, len = 10 -> 
receiver gets the segment, however still ACKing with RCV.ack = 110.
   ```
   
   Due to timeout NuttX TCP sender sets pstate->snd_sent variable back to 10 
(and SND.seq is set back to 110) as follows:
   ```
   pstate->snd_sent = 10, pstate->snd_acked = 10: SND.seq = 110, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 120.
   pstate->snd_sent = 20, pstate->snd_acked = 20: SND.seq = 120, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 130.
   pstate->snd_sent = 30, pstate->snd_acked = 30: SND.seq = 130, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 140.
   pstate->snd_sent = 40, pstate->snd_acked = 40: SND.seq = 140, len = 10 -> 
receiver successfully gets the segment by ACKing with RCV.ack = 150.
   ```
   Thus in this example it re-sends all 4 segments instead of only one segment 
with SND.seq = 110.

##########
File path: net/tcp/tcp_send_unbuffered.c
##########
@@ -243,18 +243,54 @@ static uint16_t tcpsend_eventhandler(FAR struct 
net_driver_s *dev,
 
   else if ((flags & TCP_REXMIT) != 0)
     {
+#if defined(CONFIG_NET_TCP_SPLIT)
       /* Yes.. in this case, reset the number of bytes that have been sent
        * to the number of bytes that have been ACKed.
        */
 
       pstate->snd_sent = pstate->snd_acked;

Review comment:
       Just now I have updated the description:
   from "... to the earliest one" 
   to "... to the earliest not acknowledged one".

##########
File path: net/tcp/tcp.h
##########
@@ -172,6 +172,9 @@ struct tcp_conn_s
   uint8_t  rcvseq[4];     /* The sequence number that we expect to
                            * receive next */
   uint8_t  sndseq[4];     /* The sequence number that was last sent by us */
+#if !defined(CONFIG_NET_TCP_SPLIT) && !defined(CONFIG_NET_TCP_WRITE_BUFFERS)
+  uint32_t rexmit_seq;    /* The sequence number to be retrasmitted */

Review comment:
       Previously I read your description in #4293 ("in some cases, we send tcp 
segments with sequence numbers back and forth.
   especially when sending an empty segment. (eg. pure ack, window updates)").
   Thus I have added conn->rexmit_seq field that is used only for retrasmitting 
a single TCP segment w/o a need to modify conn->sndseq each time and recovering 
it back.
   Thus I consider using conn->rexmit_seq as more reliable and stable way 
rather than using conn->sndseq for retransmissions.




-- 
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-unsubscr...@nuttx.apache.org

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


Reply via email to