Date: Fri, 17 May 2019 08:25:31 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r347902 - stable/12/sys/netinet Message-ID: <201905170825.x4H8PVoo082105@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905170825.x4H8PVoo082105>