mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
tcp: implement challenge ACK throttling for the base stack
Implement ACK throttling of challenge ACKs as described in RFC 5961. Reviewed by: Peter Lei, rscheff, cc MFC after: 1 week Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D46066
This commit is contained in:
parent
399362bac3
commit
40299c55a0
3 changed files with 48 additions and 12 deletions
|
|
@ -2208,10 +2208,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
|
|||
}
|
||||
} else {
|
||||
TCPSTAT_INC(tcps_badrst);
|
||||
/* Send challenge ACK. */
|
||||
tcp_respond(tp, mtod(m, void *), th, m,
|
||||
tp->rcv_nxt, tp->snd_nxt, TH_ACK);
|
||||
tp->last_ack_sent = tp->rcv_nxt;
|
||||
tcp_send_challenge_ack(tp, th, m);
|
||||
m = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -2233,10 +2230,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
|
|||
rstreason = BANDLIM_UNLIMITED;
|
||||
} else {
|
||||
tcp_ecn_input_syn_sent(tp, thflags, iptos);
|
||||
/* Send challenge ACK. */
|
||||
tcp_respond(tp, mtod(m, void *), th, m, tp->rcv_nxt,
|
||||
tp->snd_nxt, TH_ACK);
|
||||
tp->last_ack_sent = tp->rcv_nxt;
|
||||
tcp_send_challenge_ack(tp, th, m);
|
||||
m = NULL;
|
||||
}
|
||||
goto drop;
|
||||
|
|
@ -2474,10 +2468,7 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
|
|||
TCPSTAT_INC(tcps_rcvghostack);
|
||||
else
|
||||
TCPSTAT_INC(tcps_rcvacktooold);
|
||||
/* Send a challenge ACK. */
|
||||
tcp_respond(tp, mtod(m, void *), th, m,
|
||||
tp->rcv_nxt, tp->snd_nxt, TH_ACK);
|
||||
tp->last_ack_sent = tp->rcv_nxt;
|
||||
tcp_send_challenge_ack(tp, th, m);
|
||||
m = NULL;
|
||||
goto drop;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2181,6 +2181,45 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
|
|||
lgb->tlb_errno = output_ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a challenge ack (no data, no SACK option), but not more than
|
||||
* tcp_ack_war_cnt per tcp_ack_war_time_window (per TCP connection).
|
||||
*/
|
||||
void
|
||||
tcp_send_challenge_ack(struct tcpcb *tp, struct tcphdr *th, struct mbuf *m)
|
||||
{
|
||||
sbintime_t now;
|
||||
bool send_challenge_ack;
|
||||
|
||||
if (tcp_ack_war_time_window == 0 || tcp_ack_war_cnt == 0) {
|
||||
/* ACK war protection is disabled. */
|
||||
send_challenge_ack = true;
|
||||
} else {
|
||||
/* Start new epoch, if the previous one is already over. */
|
||||
now = getsbinuptime();
|
||||
if (tp->t_challenge_ack_end < now) {
|
||||
tp->t_challenge_ack_cnt = 0;
|
||||
tp->t_challenge_ack_end = now +
|
||||
tcp_ack_war_time_window * SBT_1MS;
|
||||
}
|
||||
/*
|
||||
* Send a challenge ACK, if less than tcp_ack_war_cnt have been
|
||||
* sent in the current epoch.
|
||||
*/
|
||||
if (tp->t_challenge_ack_cnt < tcp_ack_war_cnt) {
|
||||
send_challenge_ack = true;
|
||||
tp->t_challenge_ack_cnt++;
|
||||
} else {
|
||||
send_challenge_ack = false;
|
||||
}
|
||||
}
|
||||
if (send_challenge_ack) {
|
||||
tcp_respond(tp, mtod(m, void *), th, m, tp->rcv_nxt,
|
||||
tp->snd_nxt, TH_ACK);
|
||||
tp->last_ack_sent = tp->rcv_nxt;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new TCP control block, making an empty reassembly queue and hooking
|
||||
* it to the argument protocol control block. The `inp' parameter must have
|
||||
|
|
|
|||
|
|
@ -465,6 +465,11 @@ struct tcpcb {
|
|||
/* TCP Fast Open */
|
||||
uint8_t t_tfo_client_cookie_len; /* TFO client cookie length */
|
||||
uint32_t t_end_info_status; /* Status flag of end info */
|
||||
sbintime_t t_challenge_ack_end; /* End of the challenge ack epoch */
|
||||
uint32_t t_challenge_ack_cnt; /* Number of challenge ACKs sent in
|
||||
* current epoch
|
||||
*/
|
||||
|
||||
unsigned int *t_tfo_pending; /* TFO server pending counter */
|
||||
union {
|
||||
uint8_t client[TCP_FASTOPEN_MAX_COOKIE_LEN];
|
||||
|
|
@ -1460,6 +1465,7 @@ int tcp_default_output(struct tcpcb *);
|
|||
void tcp_state_change(struct tcpcb *, int);
|
||||
void tcp_respond(struct tcpcb *, void *,
|
||||
struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, uint16_t);
|
||||
void tcp_send_challenge_ack(struct tcpcb *, struct tcphdr *, struct mbuf *);
|
||||
bool tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *,
|
||||
struct mbuf *, int);
|
||||
void tcp_setpersist(struct tcpcb *);
|
||||
|
|
|
|||
Loading…
Reference in a new issue