svn commit: r347902 - stable/12/sys/netinet
Michael Tuexen
tuexen at FreeBSD.org
Fri May 17 08:25:33 UTC 2019
Author: tuexen
Date: Fri May 17 08:25:31 2019
New Revision: 347902
URL: https://svnweb.freebsd.org/changeset/base/347902
Log:
MFC r347382:
Receiver side DSACK implemenation.
This adds initial support for RFC 2883.
This was submitted by Richard Scheffeneffer.
MFC r347407:
Don't use C++ style comments.
Thanks to ngie@ for reporting the issue.
Modified:
stable/12/sys/netinet/tcp_input.c
stable/12/sys/netinet/tcp_sack.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/netinet/tcp_input.c
==============================================================================
--- stable/12/sys/netinet/tcp_input.c Fri May 17 08:21:27 2019 (r347901)
+++ stable/12/sys/netinet/tcp_input.c Fri May 17 08:25:31 2019 (r347902)
@@ -2278,6 +2278,17 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, stru
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;
@@ -3006,6 +3017,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 */
/*
* Insert segment which includes th into TCP reassembly queue
@@ -3045,11 +3058,34 @@ 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 && (tp->t_flags & TF_SACK_PERMIT))
- tcp_update_sack_list(tp, save_start, save_start + tlen);
+ if (tp->t_flags & TF_SACK_PERMIT) {
+ 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);
+ }
+ }
#if 0
/*
* Note the amount of data that peer has sent into
Modified: stable/12/sys/netinet/tcp_sack.c
==============================================================================
--- stable/12/sys/netinet/tcp_sack.c Fri May 17 08:21:27 2019 (r347901)
+++ stable/12/sys/netinet/tcp_sack.c Fri May 17 08:25:31 2019 (r347902)
@@ -168,7 +168,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_sta
INP_WLOCK_ASSERT(tp->t_inpcb);
/* Check arguments. */
- KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end"));
+ KASSERT(SEQ_LEQ(rcv_start, rcv_end), ("rcv_start <= rcv_end"));
/* SACK block for the received segment. */
head_blk.start = rcv_start;
@@ -193,12 +193,54 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_sta
* Merge this SACK block into head_blk. This SACK
* block itself will be discarded.
*/
- if (SEQ_GT(head_blk.start, start))
+ /*
+ * |-|
+ * |---| merge
+ *
+ * |-|
+ * |---| merge
+ *
+ * |-----|
+ * |-| DSACK smaller
+ *
+ * |-|
+ * |-----| DSACK smaller
+ */
+ if (head_blk.start == end)
head_blk.start = start;
- if (SEQ_LT(head_blk.end, end))
+ else if (head_blk.end == start)
head_blk.end = end;
+ else {
+ if (SEQ_LT(head_blk.start, start)) {
+ tcp_seq temp = start;
+ start = head_blk.start;
+ head_blk.start = temp;
+ }
+ if (SEQ_GT(head_blk.end, end)) {
+ tcp_seq temp = end;
+ end = head_blk.end;
+ head_blk.end = temp;
+ }
+ if ((head_blk.start != start) ||
+ (head_blk.end != end)) {
+ if ((num_saved >= 1) &&
+ SEQ_GEQ(saved_blks[num_saved-1].start, start) &&
+ SEQ_LEQ(saved_blks[num_saved-1].end, end))
+ num_saved--;
+ saved_blks[num_saved].start = start;
+ saved_blks[num_saved].end = end;
+ num_saved++;
+ }
+ }
} else {
/*
+ * This block supercedes the prior block
+ */
+ if ((num_saved >= 1) &&
+ SEQ_GEQ(saved_blks[num_saved-1].start, start) &&
+ SEQ_LEQ(saved_blks[num_saved-1].end, end))
+ num_saved--;
+ /*
* Save this SACK block.
*/
saved_blks[num_saved].start = start;
@@ -211,7 +253,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_sta
* Update SACK list in tp->sackblks[].
*/
num_head = 0;
- if (SEQ_GT(head_blk.start, tp->rcv_nxt)) {
+ if (SEQ_LT(rcv_start, rcv_end)) {
/*
* The received data segment is an out-of-order segment. Put
* head_blk at the top of SACK list.
More information about the svn-src-all
mailing list