diff options
| author | Michael Tuexen <tuexen@FreeBSD.org> | 2019-06-06 07:49:03 +0000 |
|---|---|---|
| committer | Michael Tuexen <tuexen@FreeBSD.org> | 2019-06-06 07:49:03 +0000 |
| commit | d1156b0505349f6b27248f5dc33529f425afb22d (patch) | |
| tree | 659cb0db001131d9ccdaf1916187cc7569ae43be | |
| parent | 175e3aa56ea6c29be1d2535c96f8535a9e7f9bf5 (diff) | |
Notes
| -rw-r--r-- | sys/netinet/tcp_stacks/rack.c | 37 |
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; |
