PERFORCE change 207318 for review
Andre Oppermann
andre at FreeBSD.org
Sat Mar 3 18:05:46 UTC 2012
http://p4web.freebsd.org/@@207318?ac=10
Change 207318 by andre at 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
More information about the p4-projects
mailing list