Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 May 2019 08:25:31 +0000 (UTC)
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r347902 - stable/12/sys/netinet
Message-ID:  <201905170825.x4H8PVoo082105@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905170825.x4H8PVoo082105>