aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2019-06-06 07:49:03 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2019-06-06 07:49:03 +0000
commitd1156b0505349f6b27248f5dc33529f425afb22d (patch)
tree659cb0db001131d9ccdaf1916187cc7569ae43be
parent175e3aa56ea6c29be1d2535c96f8535a9e7f9bf5 (diff)
Notes
-rw-r--r--sys/netinet/tcp_stacks/rack.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/sys/netinet/tcp_stacks/rack.c b/sys/netinet/tcp_stacks/rack.c
index 0b256c73cc3dd..2ead503df0b36 100644
--- a/sys/netinet/tcp_stacks/rack.c
+++ b/sys/netinet/tcp_stacks/rack.c
@@ -1721,6 +1721,17 @@ rack_drop_checks(struct tcpopt *to, struct mbuf *m, struct tcphdr *th, struct tc
TCPSTAT_INC(tcps_rcvpartduppack);
TCPSTAT_ADD(tcps_rcvpartdupbyte, todrop);
}
+ /*
+ * DSACK - add SACK block for dropped range
+ */
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ tcp_update_sack_list(tp, th->th_seq, th->th_seq + tlen);
+ /*
+ * ACK now, as the next in-sequence segment
+ * will clear the DSACK block again
+ */
+ tp->t_flags |= TF_ACKNOW;
+ }
*drop_hdrlen += todrop; /* drop from the top afterwards */
th->th_seq += todrop;
tlen -= todrop;
@@ -4753,6 +4764,8 @@ dodata: /* XXX */
if ((tlen || (thflags & TH_FIN) || tfo_syn) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
tcp_seq save_start = th->th_seq;
+ tcp_seq save_rnxt = tp->rcv_nxt;
+ int save_tlen = tlen;
m_adj(m, drop_hdrlen); /* delayed header drop */
/*
@@ -4795,11 +4808,29 @@ dodata: /* XXX */
* m_adj() doesn't actually frees any mbufs when
* trimming from the head.
*/
- thflags = tcp_reass(tp, th, &save_start, &tlen, m);
+ tcp_seq temp = save_start;
+ thflags = tcp_reass(tp, th, &temp, &tlen, m);
tp->t_flags |= TF_ACKNOW;
}
- if (tlen > 0)
- tcp_update_sack_list(tp, save_start, save_start + tlen);
+ if (((tlen == 0) && (save_tlen > 0) &&
+ (SEQ_LT(save_start, save_rnxt)))) {
+ /*
+ * DSACK actually handled in the fastpath
+ * above.
+ */
+ tcp_update_sack_list(tp, save_start, save_start + save_tlen);
+ } else if ((tlen > 0) && SEQ_GT(tp->rcv_nxt, save_rnxt)) {
+ /*
+ * Cleaning sackblks by using zero length
+ * update.
+ */
+ tcp_update_sack_list(tp, save_start, save_start);
+ } else if ((tlen > 0) && (tlen >= save_tlen)) {
+ /* Update of sackblks. */
+ tcp_update_sack_list(tp, save_start, save_start + save_tlen);
+ } else if (tlen > 0) {
+ tcp_update_sack_list(tp, save_start, save_start+tlen);
+ }
} else {
m_freem(m);
thflags &= ~TH_FIN;