mirror of
https://github.com/opnsense/src.git
synced 2026-06-06 23:32:52 -04:00
tcp: do not purge SACK scoreboard on first RTO
Keeping the SACK scoreboard intact after the first RTO and retransmitting all data anew only on subsequent RTOs allows a more timely and efficient loss recovery under many adverse cirumstances. Reviewed By: tuexen, #transport MFC after: 10 weeks Sponsored by: NetApp, Inc. Differential Revision: https://reviews.freebsd.org/D42906
This commit is contained in:
parent
893ed42eca
commit
30409ecdb6
4 changed files with 28 additions and 3 deletions
|
|
@ -439,7 +439,10 @@ cc_cong_signal(struct tcpcb *tp, struct tcphdr *th, uint32_t type)
|
|||
case CC_RTO:
|
||||
tp->t_dupacks = 0;
|
||||
tp->t_bytes_acked = 0;
|
||||
EXIT_RECOVERY(tp->t_flags);
|
||||
if ((tp->t_rxtshift > 1) ||
|
||||
!((tp->t_flags & TF_SACK_PERMIT) &&
|
||||
(!TAILQ_EMPTY(&tp->snd_holes))))
|
||||
EXIT_RECOVERY(tp->t_flags);
|
||||
if (tp->t_flags2 & TF2_ECN_PERMIT)
|
||||
tp->t_flags2 |= TF2_ECN_SND_CWR;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -908,6 +908,25 @@ tcp_free_sackholes(struct tcpcb *tp)
|
|||
("tp->sackhint.nexthole == NULL"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Resend all the currently existing SACK holes of
|
||||
* the scoreboard. This is in line with the Errata to
|
||||
* RFC 2018, which allows the use of SACK data past
|
||||
* an RTO to good effect typically.
|
||||
*/
|
||||
void
|
||||
tcp_resend_sackholes(struct tcpcb *tp)
|
||||
{
|
||||
struct sackhole *p;
|
||||
|
||||
INP_WLOCK_ASSERT(tptoinpcb(tp));
|
||||
TAILQ_FOREACH(p, &tp->snd_holes, scblink) {
|
||||
p->rxmit = p->start;
|
||||
}
|
||||
tp->sackhint.nexthole = TAILQ_FIRST(&tp->snd_holes);
|
||||
tp->sackhint.sack_bytes_rexmit = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Partial ack handling within a sack recovery episode. Keeping this very
|
||||
* simple for now. When a partial ack is received, force snd_cwnd to a value
|
||||
|
|
|
|||
|
|
@ -559,7 +559,6 @@ tcp_timer_rexmt(struct tcpcb *tp)
|
|||
|
||||
TCP_PROBE2(debug__user, tp, PRU_SLOWTIMO);
|
||||
CURVNET_SET(inp->inp_vnet);
|
||||
tcp_free_sackholes(tp);
|
||||
if (tp->t_fb->tfb_tcp_rexmit_tmr) {
|
||||
/* The stack has a timer action too. */
|
||||
(*tp->t_fb->tfb_tcp_rexmit_tmr)(tp);
|
||||
|
|
@ -619,8 +618,11 @@ tcp_timer_rexmt(struct tcpcb *tp)
|
|||
* the retransmitted packet's to_tsval to by tcp_output
|
||||
*/
|
||||
tp->t_flags |= TF_PREVVALID;
|
||||
} else
|
||||
tcp_resend_sackholes(tp);
|
||||
} else {
|
||||
tp->t_flags &= ~TF_PREVVALID;
|
||||
tcp_free_sackholes(tp);
|
||||
}
|
||||
TCPSTAT_INC(tcps_rexmttimeo);
|
||||
if ((tp->t_state == TCPS_SYN_SENT) ||
|
||||
(tp->t_state == TCPS_SYN_RECEIVED))
|
||||
|
|
|
|||
|
|
@ -1499,6 +1499,7 @@ struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt);
|
|||
void tcp_do_prr_ack(struct tcpcb *, struct tcphdr *, struct tcpopt *, sackstatus_t);
|
||||
void tcp_lost_retransmission(struct tcpcb *, struct tcphdr *);
|
||||
void tcp_sack_partialack(struct tcpcb *, struct tcphdr *);
|
||||
void tcp_resend_sackholes(struct tcpcb *tp);
|
||||
void tcp_free_sackholes(struct tcpcb *tp);
|
||||
void tcp_sack_lost_retransmission(struct tcpcb *, struct tcphdr *);
|
||||
int tcp_newreno(struct tcpcb *, struct tcphdr *);
|
||||
|
|
|
|||
Loading…
Reference in a new issue