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