Date: Fri, 17 Jul 2009 21:05:49 GMT From: Andre Oppermann <andre@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 166213 for review Message-ID: <200907172105.n6HL5npK033129@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=166213 Change 166213 by andre@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 );
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907172105.n6HL5npK033129>