PERFORCE change 166213 for review

Andre Oppermann andre at FreeBSD.org
Fri Jul 17 21:05:50 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166213

Change 166213 by andre at andre_t61 on 2009/07/17 21:04:59

	Calculate sacked amount in tcp_sack_doack().
	Add tcp_sack_nextseg() function for SACK based recovery.
	Change calculation of dlen and len in tcp_output().

Affected files ...

.. //depot/projects/tcp_new/netinet/tcp_output.c#12 edit
.. //depot/projects/tcp_new/netinet/tcp_sack.c#8 edit
.. //depot/projects/tcp_new/netinet/tcp_var.h#13 edit

Differences ...

==== //depot/projects/tcp_new/netinet/tcp_output.c#12 (text+ko) ====

@@ -107,7 +107,7 @@
 		    int optlen, int rwin, int flags);
 static int	tcp_retransmit(struct tcpcb *tp, struct socket *so,
 		    struct tcpopt *to, u_char *opt, int *len,
-		    int optlen, int rwin, int flags);
+		    int optlen, int rwin, int dlen, int flags);
 static int	tcp_send_segments(struct tcpcb *tp, struct tcphdr *ths,
 		    u_char *opt, int off, int *olen, int optlen);
 static u_int	tcp_rcv_wnd(struct tcpcb *tp, struct socket *so);
@@ -209,8 +209,8 @@
 	duna = SEQ_DELTA(tp->snd_nxt, tp->snd_una);
 	swnd = imax(0, tp->snd_wnd - duna);
 	cwnd = imax(0, tp->snd_cwnd - duna);
-	dlen = so->so_snd.sb_cc - duna;
-	len = min(dlen, min(swnd, cwnd));
+	dlen = min(so->so_snd.sb_cc - duna, swnd);
+	len = min(dlen, cwnd);
 
 	/*
 	 * XXXAO: todo token bucket, mss sized
@@ -262,7 +262,7 @@
 		break;
 	case TP_LOSSRECOV:
 	case TP_REXMT:
-		error = tcp_retransmit(tp, so, &to, &opt[0], &len, optlen, rwin, flags);
+		error = tcp_retransmit(tp, so, &to, &opt[0], &len, optlen, rwin, dlen, flags);
 		if (len == 0)
 			return (0);
 		break;
@@ -538,9 +538,10 @@
 	th->th_seq = tp->snd_nxt;
 	th->th_flags = flags;
 	th->th_ack = tp->rcv_nxt;
+	off = tp->snd_nxt - tp->snd_una;
 
+	/* Send off the data. */
 	SOCKBUF_LOCK(&so->so_snd);
-	off = tp->snd_nxt - tp->snd_una;
 	error = tcp_send_segments(tp, &ths, opt, off, &len, optlen);
 	SOCKBUF_UNLOCK(&so->so_snd);
 
@@ -765,7 +766,7 @@
  */
 static int
 tcp_retransmit(struct tcpcb *tp, struct socket *so, struct tcpopt *to,
-    u_char *opt, int *len, int optlen, int rwin, int flags)
+    u_char *opt, int *len, int optlen, int rwin, int dlen, int flags)
 {
 	int error, off, rlen = 0;
 	struct tcphdr ths, *th = &ths;
@@ -793,18 +794,22 @@
 	 */
 
 	/* Limited transmit */
-	if (tp->snd_dupack < 3)
-		*len = min(*len, tp->snd_mss);		/* one mss */
-	else
-		*len = 0;
+	if (tp->snd_dupack < tcp_dupthresh && dlen > *len)
+		*len = min(dlen, tp->snd_mss);	/* up to one mss above cwnd */
 
-	if (tp->snd_dupack < 3)
+	if (tp->snd_dupack < tcp_dupthresh)
 		return (0);
 
-	/*
-	 * XXXAO: Temporary.
-	 */
-	tp->snd_rxmit = tp->snd_una;
+	/* Remember the highest byte sent. */
+	if (SEQ_LEQ(tp->snd_recover, tp->snd_una)) {
+		tp->snd_recover = tp->snd_nxt;
+		//tcp_cc_fr_enter(tp);
+		tp->snd_rxmit = tp->snd_una;
+	}
+
+	rlen = tcp_sack_nextseg(tp, &tp->snd_rexmit);
+
+	rlen = min(so->so_snd.sb_cc - SEQ_DELTA(tp->snd_una, tp->snd_rxmit), tp->snd_mss);
 
 	/*
 	 * Fill in headers.
@@ -828,6 +833,9 @@
 	error = tcp_send_segments(tp, &ths, opt, off, &rlen, optlen);
 	SOCKBUF_UNLOCK(&so->so_snd);
 
+	/* Start from here the next time. */
+	tp->snd_rxmit += rlen;
+
 	return (error);
 }
 

==== //depot/projects/tcp_new/netinet/tcp_sack.c#8 (text+ko) ====

@@ -133,6 +133,7 @@
 static int
 tcp_sack_verify(struct tcpcb *tp)
 {
+	int sacked = 0;
 	struct tcp_sack_block *tsb, *tsbn;
 
 	RB_FOREACH_SAFE(tsb, tcp_sackblocks, &tp->snd_sackblocks, tsbn) {
@@ -141,7 +142,10 @@
 		    SEQ_GT(tsb->tsb_blk.end, tp->snd_nxt) ||
 		    (tsbn != NULL && SEQ_GEQ(tsb->tsb_blk.end, tsbn->tsb_blk.start)))
 			return (0);
+		sacked += SEQ_DELTA(tsb->tsb_blk.start, tsb->tsb_blk.end);
 	}
+	if (tp->snd_sacked != sacked)
+		return (0);
 	return (1);
 }
 #endif
@@ -162,8 +166,10 @@
 	struct tcp_sack_block *tsb, *tsbn;
 
 	RB_FOREACH_SAFE(tsb, tcp_sackblocks, &tp->snd_sackblocks, tsbn) {
+		tp->snd_sacked -= SEQ_DELTA(tsb->tsb_blk.start, tsb->tsb_blk.end);
 		tcp_sack_free(tp, tsb);
 	}
+	KASSERT(tp->snd_sacked == 0, ("%s: snd_sacked not zero", __func__));
 }
 
 /*
@@ -248,7 +254,7 @@
 				tsb->tsb_blk.end = sack.tsb_blk.end;
 				while ((tsbn = RB_NEXT(tcp_sackblocks, &tp->snd_sackblocks, tsb)) != NULL &&
 				    SEQ_GEQ(tsbn->tsb_blk.start, tsb->tsb_blk.end)) {
-					//sacked -= SEQ_DELTA(sack.tsb_blk.start, tsbn->tsb_blk.start);
+					sacked -= SEQ_DELTA(sack.tsb_blk.end, tsbn->tsb_blk.start);
 					if (SEQ_GT(tsbn->tsb_blk.end, tsb->tsb_blk.end))
 						tsb->tsb_blk.end = tsbn->tsb_blk.end;
 					tcp_sack_free(tp, tsbn);
@@ -260,7 +266,7 @@
 				tsb->tsb_blk.start = sack.tsb_blk.start;
 				while ((tsbn = RB_PREV(tcp_sackblocks, &tp->snd_sackblocks, tsb)) != NULL &&
 				    SEQ_GEQ(tsbn->tsb_blk.end, tsb->tsb_blk.start)) {
-					//sacked -= SEQ_DELTA();
+					sacked -= SEQ_DELTA(sack.tsb_blk.start, tsbn->tsb_blk.end);
 					if (SEQ_LT(tsbn->tsb_blk.start, tsb->tsb_blk.start))
 						tsb->tsb_blk.start = tsbn->tsb_blk.start;
 					tcp_sack_free(tp, tsbn);
@@ -279,9 +285,38 @@
 	KASSERT(tcp_sack_verify(tp),
 	    ("%s: snd_sackblocks RB tree inconsistent", __func__));
 
+	tp->snd_sacked += sacked;
 	return (sacked);
 }
 
+/*
+ * Determine the next start and length of the next hole relative
+ * to rexmit.
+ */
+int
+tcp_sack_nextseg(struct tcpcb *tp, tcp_seq *rexmit)
+{
+	int len = 0;
+	struct tcp_sack_block *tsb, *tsbn;
+	struct tcp_sack_block sack;
+
+	sack.tsb_blk.start = rexmit;
+	sack.tsb_blk.end = rexmit;
+
+	if ((tsb = RB_NFIND(tcp_sackblocks, &tp->snd_sackblocks, &sack)) != NULL) {
+		if (*rexmit < tsb->tsb_blk.start) {
+			len = SEQ_DELTA(*rexmit, tsb->tsb_blk.start);
+		} else if ((tsbn = RB_NEXT(tcp_sackblocks, &tp->snd_sackblocks, tsb)) != NULL) {
+			*rexmit = tsb->tsb_blk.end;
+			len = SEQ_DELTA(tsb->tsb_blk.end, tsbn->tsb_blk.start);
+		} else {
+			*rexmit = tsb->tsb_blk.end;
+			len = (SEQ_DELTA(tsb->tsb_blk.end, tp->snd_nxt);
+		}
+	}
+	return (len);
+}
+
 #ifdef DDB
 static void
 db_print_sackblocks(struct tcpcb *tp)

==== //depot/projects/tcp_new/netinet/tcp_var.h#13 (text+ko) ====

@@ -644,8 +644,9 @@
 tcp_seq tcp_new_isn(struct tcpcb *);
 
 int	 tcp_sack_doack(struct tcpcb *, struct tcpopt *, tcp_seq);
-void	 tcp_sack_flush(struct tcpcb *tp);
+void	 tcp_sack_flush(struct tcpcb *);
 void	 tcp_sack_init(void);
+int	 tcp_sack_nextseg(struct tcpcb *, tcp_seq *);
 
 int	 tcp_newreno(struct tcpcb *, struct tcphdr *);
 u_long	 tcp_seq_subtract(u_long, u_long );


More information about the p4-projects mailing list