Index: head/sys/netinet/tcp_output.c
===================================================================
--- head/sys/netinet/tcp_output.c
+++ head/sys/netinet/tcp_output.c
@@ -1508,7 +1508,13 @@
 		if (SEQ_GT(tp->snd_nxt + xlen, tp->snd_max))
 			tp->snd_max = tp->snd_nxt + xlen;
 	}
-
+	if ((error == 0) &&
+	    (TCPS_HAVEESTABLISHED(tp->t_state) &&
+	     (tp->t_flags & TF_SACK_PERMIT) &&
+	     tp->rcv_numsacks > 0)) {
+		    /* Clean up any DSACK's sent */
+		    tcp_clean_dsack_blocks(tp);
+	}
 	if (error) {
 		/* Record the error. */
 		TCP_LOG_EVENT(tp, NULL, &so->so_rcv, &so->so_snd, TCP_LOG_OUT,
Index: head/sys/netinet/tcp_sack.c
===================================================================
--- head/sys/netinet/tcp_sack.c
+++ head/sys/netinet/tcp_sack.c
@@ -279,6 +279,45 @@
 	tp->rcv_numsacks = num_head + num_saved;
 }
 
+void
+tcp_clean_dsack_blocks(struct tcpcb *tp)
+{
+	struct sackblk saved_blks[MAX_SACK_BLKS];
+	int num_saved, i;
+
+	INP_WLOCK_ASSERT(tp->t_inpcb);
+	/*
+	 * Clean up any DSACK blocks that
+	 * are in our queue of sack blocks.
+	 * 
+	 */
+	num_saved = 0;
+	for (i = 0; i < tp->rcv_numsacks; i++) {
+		tcp_seq start = tp->sackblks[i].start;
+		tcp_seq end = tp->sackblks[i].end;
+		if (SEQ_GEQ(start, end) || SEQ_LEQ(start, tp->rcv_nxt)) {
+			/*
+			 * Discard this D-SACK block.
+			 */
+			continue;
+		}
+		/*
+		 * Save this SACK block.
+		 */
+		saved_blks[num_saved].start = start;
+		saved_blks[num_saved].end = end;
+		num_saved++;
+	}
+	if (num_saved > 0) {
+		/*
+		 * Copy the saved SACK blocks back.
+		 */
+		bcopy(saved_blks, &tp->sackblks[0],
+		      sizeof(struct sackblk) * num_saved);
+	}
+	tp->rcv_numsacks = num_saved;
+}
+
 /*
  * Delete all receiver-side SACK information.
  */
Index: head/sys/netinet/tcp_stacks/rack.c
===================================================================
--- head/sys/netinet/tcp_stacks/rack.c
+++ head/sys/netinet/tcp_stacks/rack.c
@@ -5087,9 +5087,8 @@
 
 
 	/* Clean receiver SACK report if present */
-/*	if (tp->rcv_numsacks)
+	if (tp->rcv_numsacks)
 	        tcp_clean_sackreport(tp);
-*/
 	TCPSTAT_INC(tcps_preddat);
 	tp->rcv_nxt += tlen;
 	/*
@@ -8537,10 +8536,10 @@
 	 * retransmit.  In persist state, just set snd_max.
 	 */
 	if (error == 0) {
-/*		if (TCPS_HAVEESTABLISHED(tp->t_state) &&
+		if (TCPS_HAVEESTABLISHED(tp->t_state) &&
 		    (tp->t_flags & TF_SACK_PERMIT) &&
 		    tp->rcv_numsacks > 0)
-		    tcp_clean_dsack_blocks(tp);*/
+		    tcp_clean_dsack_blocks(tp);
 		if (len == 0)
 			counter_u64_add(rack_out_size[TCP_MSS_ACCT_SNDACK], 1);
 		else if (len == 1) {
Index: head/sys/netinet/tcp_var.h
===================================================================
--- head/sys/netinet/tcp_var.h
+++ head/sys/netinet/tcp_var.h
@@ -939,6 +939,7 @@
 
 int	 tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq);
 void	 tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_laststart, tcp_seq rcv_lastend);
+void	 tcp_clean_dsack_blocks(struct tcpcb *tp);
 void	 tcp_clean_sackreport(struct tcpcb *tp);
 void	 tcp_sack_adjust(struct tcpcb *tp);
 struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt);