Implement ACK throttling of challenge ACKs as described in RFC 5961.
Details
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
| sys/netinet/tcp_subr.c | ||
|---|---|---|
| 2194 | A little bit less than perfect, I think. For example, tcp_ack_war_time_window requires a zero check within the epoch check. It can be like this: if (tcp_ack_war_time_window > 0 && tcp_ack_war_cnt > 0) {
// check rate limit
// if under limit, pass through; else, just return
}
// send challenge ACK | |
| sys/netinet/tcp_subr.c | ||
|---|---|---|
| 2194 | I am using the negation of your condition. So were is the difference? | |
| sys/netinet/tcp_subr.c | ||
|---|---|---|
| 2194 |
On a second thought, you are right. | |
| sys/netinet/tcp_subr.c | ||
|---|---|---|
| 2194 | Still, I recommend the cleaner approach, which saves the local variable send_challenge_ack and the else branch. | |
Just saw https://reviews.freebsd.org/D46068. If this patch has not been committed, we can still further revise it, so that D46068 can be cleaner on function re-use.
I think the logic here can be split into two functions, such that the refined logic 1 on checking if we should send ACK can be re-used across multiple places.
logic 1:
bool
is_ack_unlimited(struct tcpcb *tp)
{
/* focus on checking the epoch and
* if should send ACK, return true; else return false
*/
}logic 2:
void
tcp_send_challenge_ack(struct tcpcb *tp, struct tcphdr *th, struct mbuf *m)
{
if (is_ack_unlimited(tp)) {.
tcp_respond();
....
}
}I don't get the point. Eventually, all places should use tcp_send_challenge_ack(), I think. But that is multiple commits away.
For example, ctf_ack_war_checks() can be simply refined as this:
ctf_ack_war_checks()
{
if (is_ack_unlimited(tp)) {
tp->t_flags |= TF_ACKNOW;
} else {
tp->t_flags &= ~TF_ACKNOW;
}
}