Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Mar 2012 18:05:45 GMT
From:      Andre Oppermann <andre@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 207318 for review
Message-ID:  <201203031805.q23I5jWN007399@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@207318?ac=10

Change 207318 by andre@andre_t61 on 2012/03/03 18:04:56

	Add some more retransmit logic. Still incomplete.

Affected files ...

.. //depot/projects/tcp_new/netinet/tcp_output.c#20 edit

Differences ...

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

@@ -835,14 +835,14 @@
 	 *     transmit new segment if cwnd allows [output]
 	 */
 
-	/* Transmit one more new data if available. */
+	/* Transmit one more segment of new data if available. */
 	if (len > 0 && (len >= tp->snd_mss || dlen == len))
 		*lenp = len;
 	else
 		*lenp = 0;
 
-	/* Do not retransmit if ack didn't move. */
-	if (tp->snd_dupack != 3 || tp->snd_dupack != 0)
+	/* Do not retransmit if ack didn't move snd_una. */
+	if (tp->snd_dupack != 3 && tp->snd_dupack != 0)
 		return (0);
 
 	/* Retransmit one mss or the unacknowledged amount of data. */
@@ -923,9 +923,15 @@
 tcp_retransmit_sack(struct tcpcb *tp, struct socket *so, struct tcpopt *to,
     u_char *opt, int optlen, int *lenp, int rwin, int dlen, int slen, int flags)
 {
-	int error = 0, off, rlen = 0, rxmit;
+	int error = 0, off, rlen = 0;
+	tcp_seq rxmit;
 	struct tcphdr ths, *th = &ths;
 
+	/* Move the retransmit pointer forward if necessary. */
+	if (SEQ_LT(tp->snd_rxmit, tp->snd_una))
+		tp->snd_rxmit = tp->snd_una;
+	rxmit = tp->snd_rxmit;
+
 	/*
 	 * SACK based retransmission RFC3517
 	 * Retransmit over the SACK holes.
@@ -934,49 +940,51 @@
 	 * Retransmit only the stuff that was not SACK'ed.
 	 * With SACK we may be able to retransmit more than one segment
 	 * from different blocks.
+	 *
+	 * duna = flight size
+	 * dlen = available unsent data in send buffer
+	 * len = data available to be sent (within cwnd and wnd)
 	 */
 	do {
 		/* Calculate amount of data we may inject into the pipe (C). */
-		rxmit = imax(0, tp->snd_cwnd - tp->snd_pipe);
+		rlen = imax(0, tp->snd_cwnd - tp->snd_pipe);
+
+		if (rlen == 0)
+			break;	/* No space in pipe for retransmit. */
 
 		if (!RB_EMPTY(&tp->snd_sackblocks)) {
 			/*
 			 * Get the amount of consequtive data for retransmit.
 			 * (C.1) modulo (C.3)
 			 */
-			if (tp->snd_rxmit == tp->snd_una)
+			if (SEQ_LEQ(tp->snd_rxmit, tp->snd_una))
 				rlen = tcp_sack_firsthole(tp, &rxmit);
 			else
-				rlen = tcp_sack_nextseg(tp, &tp->snd_rxmit, slen);
+				rlen = tcp_sack_nextseg(tp, &rxmit, slen);
 			/*
 			 * If we have nothing to retransmit, see if we can
 			 * send some new data.
 			 * (C.3)
 			 */
-			if (rlen == 0) {
-				if (slen > 0 && (rxmit >= tp->snd_mss ||
-				    (rxmit >= slen && dlen == slen)))
-					*lenp = min(slen, rxmit);
-				else
-					*lenp = 0;
+			if (rlen == 0)
 				break;
-			}
 			/*
 			 * Retransmit what we've got.
 			 * (C.1)
 			 */
-			if (rxmit >= rlen || (rlen > rxmit && rxmit > tp->snd_mss))
+			if (rxmit >= rlen || (rlen > rxmit && rxmit > tp->snd_mss)) {
 				rlen = min(rlen, tp->snd_pipe);
-			else
+			} else
 				break;
-		} else if (tp->snd_rxmit == tp->snd_una)
+		} else if (tp->snd_rxmit == tp->snd_una) {
+			/* Fallback to normal retransmit. */
 			rlen = min(tp->snd_mss, SEQ_DELTA(tp->snd_una, tp->snd_nxt));
-		else
+		} else
 			break;
 
 		/* Fill in headers. */
 		th->th_win = (u_short)rwin;
-		th->th_seq = tp->snd_rxmit;
+		th->th_seq = rxmit;
 		th->th_flags = flags;
 		th->th_ack = tp->rcv_nxt;
 
@@ -992,31 +1000,31 @@
 		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;
-		/* Increase amount of data in the 'pipe' (C.4). */
-		tp->snd_pipe += rlen;
+		if (rlen > 0) {
+			/* Start from here the next time. */
+			tp->snd_rxmit += rlen;
 
-	} while (error == 0);
+			/* Increase amount of data in the 'pipe' (C.4). */
+			tp->snd_pipe += rlen;
+		}
 
-	if (rlen > 0) {
-	}
+		if (error == 0) {
+		}
 
-	if (error == 0) {
-	}
+		if (rlen > 0 || error == 0) {
+			/* Update last send timestamp. */
+			if ((tp->t_flags & TF_TIMESTAMP) && tp->snd_tslast != to->to_tsval)
+				tp->snd_tslast = to->to_tsval;
 
-	if (rlen > 0 || error == 0) {
-		/* Update last send timestamp. */
-		if ((tp->t_flags & TF_TIMESTAMP) && tp->snd_tslast != to->to_tsval)
-			tp->snd_tslast = to->to_tsval;
+			/* Last ACK we sent. */
+			if (tp->snd_lastack != th->th_ack)
+				tp->snd_lastack = th->th_ack;
+		}
 
-		/* Last ACK we sent. */
-		if (tp->snd_lastack != th->th_ack)
-			tp->snd_lastack = th->th_ack;
-	}
+		if (rlen > 0 && error == 0) {
+		}
 
-	if (rlen > 0 && error == 0) {
-	}
+	} while (error == 0);
 
 	switch (error) {
 	case EPERM:
@@ -1039,6 +1047,19 @@
 		    ("%s: unkown error %i", __func__, error));
 	}
 
+	if (slen > 0 && (rlen >= tp->snd_mss ||
+	    (rlen >= slen && dlen == slen)))
+		*lenp = min(slen, rlen);
+	else
+		*lenp = 0;
+	break;
+
+	/* Transmit more new data if available. */
+	if (len > 0 && (len >= tp->snd_mss || dlen == len))
+		*lenp = len;
+	else
+		*lenp = 0;
+
 	return (error);
 }
 
@@ -1399,7 +1420,7 @@
 	 * a rcv_read pointer.
 	 */
 	SOCKBUF_LOCK(&so->so_rcv);
-	if (so->so_rcv.sb_hiwat - so->so_rcv.sb_cc > 0)
+	if (so->so_rcv.sb_hiwat - so->so_rcv.sb_cc > 0) // sbspace()
 		delta = SEQ_DELTA(tp->rcv_wnd - so->so_rcv.sb_hiwat,
 			    tp->rcv_nxt - so->so_rcv.sb_cc);
 	else



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