Author: tuexen
Date: Fri May 17 08:25:31 2019
New Revision: 347902
URL: https://svnweb.freebsd.org/changeset/base/347902

Log:
  MFC r347382:
  
  Receiver side DSACK implemenation.
  This adds initial support for RFC 2883.
  This was submitted by Richard Scheffeneffer.
  
  MFC r347407:
  
  Don't use C++ style comments.
  Thanks to ngie@ for reporting the issue.

Modified:
  stable/12/sys/netinet/tcp_input.c
  stable/12/sys/netinet/tcp_sack.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/netinet/tcp_input.c
==============================================================================
--- stable/12/sys/netinet/tcp_input.c   Fri May 17 08:21:27 2019        
(r347901)
+++ stable/12/sys/netinet/tcp_input.c   Fri May 17 08:25:31 2019        
(r347902)
@@ -2278,6 +2278,17 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, stru
                        TCPSTAT_INC(tcps_rcvpartduppack);
                        TCPSTAT_ADD(tcps_rcvpartdupbyte, todrop);
                }
+               /*
+                * DSACK - add SACK block for dropped range
+                */
+               if (tp->t_flags & TF_SACK_PERMIT) {
+                       tcp_update_sack_list(tp, th->th_seq, th->th_seq+tlen);
+                       /*
+                        * ACK now, as the next in-sequence segment
+                        * will clear the DSACK block again
+                        */
+                       tp->t_flags |= TF_ACKNOW;
+               }
                drop_hdrlen += todrop;  /* drop from the top afterwards */
                th->th_seq += todrop;
                tlen -= todrop;
@@ -3006,6 +3017,8 @@ dodata:                                                   
/* XXX */
        if ((tlen || (thflags & TH_FIN) || tfo_syn) &&
            TCPS_HAVERCVDFIN(tp->t_state) == 0) {
                tcp_seq save_start = th->th_seq;
+               tcp_seq save_rnxt  = tp->rcv_nxt;
+               int     save_tlen  = tlen;
                m_adj(m, drop_hdrlen);  /* delayed header drop */
                /*
                 * Insert segment which includes th into TCP reassembly queue
@@ -3045,11 +3058,34 @@ dodata:                                                 
/* XXX */
                         * m_adj() doesn't actually frees any mbufs
                         * when trimming from the head.
                         */
-                       thflags = tcp_reass(tp, th, &save_start, &tlen, m);
+                       tcp_seq temp = save_start;
+                       thflags = tcp_reass(tp, th, &temp, &tlen, m);
                        tp->t_flags |= TF_ACKNOW;
                }
-               if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT))
-                       tcp_update_sack_list(tp, save_start, save_start + tlen);
+               if (tp->t_flags & TF_SACK_PERMIT) {
+                       if (((tlen == 0) && (save_tlen > 0) &&
+                           (SEQ_LT(save_start, save_rnxt)))) {
+                               /*
+                                * DSACK actually handled in the fastpath
+                                * above.
+                                */
+                               tcp_update_sack_list(tp, save_start, save_start 
+ save_tlen);
+                       } else
+                       if ((tlen > 0) && SEQ_GT(tp->rcv_nxt, save_rnxt)) {
+                               /*
+                                * Cleaning sackblks by using zero length
+                                * update.
+                                */
+                               tcp_update_sack_list(tp, save_start, 
save_start);
+                       } else
+                       if ((tlen > 0) && (tlen >= save_tlen)) {
+                               /* Update of sackblks. */
+                               tcp_update_sack_list(tp, save_start, save_start 
+ save_tlen);
+                       } else
+                       if (tlen > 0) {
+                               tcp_update_sack_list(tp, save_start, 
save_start+tlen);
+                       }
+               }
 #if 0
                /*
                 * Note the amount of data that peer has sent into

Modified: stable/12/sys/netinet/tcp_sack.c
==============================================================================
--- stable/12/sys/netinet/tcp_sack.c    Fri May 17 08:21:27 2019        
(r347901)
+++ stable/12/sys/netinet/tcp_sack.c    Fri May 17 08:25:31 2019        
(r347902)
@@ -168,7 +168,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_sta
        INP_WLOCK_ASSERT(tp->t_inpcb);
 
        /* Check arguments. */
-       KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end"));
+       KASSERT(SEQ_LEQ(rcv_start, rcv_end), ("rcv_start <= rcv_end"));
 
        /* SACK block for the received segment. */
        head_blk.start = rcv_start;
@@ -193,12 +193,54 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_sta
                         * Merge this SACK block into head_blk.  This SACK
                         * block itself will be discarded.
                         */
-                       if (SEQ_GT(head_blk.start, start))
+                       /*
+                        * |-|
+                        *   |---|  merge
+                        *
+                        *     |-|
+                        * |---|    merge
+                        *
+                        * |-----|
+                        *   |-|    DSACK smaller
+                        *
+                        *   |-|
+                        * |-----|  DSACK smaller
+                        */
+                       if (head_blk.start == end)
                                head_blk.start = start;
-                       if (SEQ_LT(head_blk.end, end))
+                       else if (head_blk.end == start)
                                head_blk.end = end;
+                       else {
+                               if (SEQ_LT(head_blk.start, start)) {
+                                       tcp_seq temp = start;
+                                       start = head_blk.start;
+                                       head_blk.start = temp;
+                               }
+                               if (SEQ_GT(head_blk.end, end)) {
+                                       tcp_seq temp = end;
+                                       end = head_blk.end;
+                                       head_blk.end = temp;
+                               }
+                               if ((head_blk.start != start) ||
+                                   (head_blk.end != end)) {
+                                       if ((num_saved >= 1) &&
+                                          
SEQ_GEQ(saved_blks[num_saved-1].start, start) &&
+                                          SEQ_LEQ(saved_blks[num_saved-1].end, 
end))
+                                               num_saved--;
+                                       saved_blks[num_saved].start = start;
+                                       saved_blks[num_saved].end = end;
+                                       num_saved++;
+                               }
+                       }
                } else {
                        /*
+                        * This block supercedes the prior block
+                        */
+                       if ((num_saved >= 1) &&
+                          SEQ_GEQ(saved_blks[num_saved-1].start, start) &&
+                          SEQ_LEQ(saved_blks[num_saved-1].end, end))
+                               num_saved--;
+                       /*
                         * Save this SACK block.
                         */
                        saved_blks[num_saved].start = start;
@@ -211,7 +253,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_sta
         * Update SACK list in tp->sackblks[].
         */
        num_head = 0;
-       if (SEQ_GT(head_blk.start, tp->rcv_nxt)) {
+       if (SEQ_LT(rcv_start, rcv_end)) {
                /*
                 * The received data segment is an out-of-order segment.  Put
                 * head_blk at the top of SACK list.
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to