Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Sep 2025 18:24:45 GMT
From:      Michael Tuexen <tuexen@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: db37256ce543 - main - tcp: refactor tcp_send_challenge_ack()
Message-ID:  <202509251824.58PIOjDq047609@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by tuexen:

URL: https://cgit.FreeBSD.org/src/commit/?id=db37256ce5437e6c667a537afff0fd9f59576514

commit db37256ce5437e6c667a537afff0fd9f59576514
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2025-09-25 01:40:33 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2025-09-25 01:40:33 +0000

    tcp: refactor tcp_send_challenge_ack()
    
    Refactor tcp_send_challenge_ack() such that the logic checking whether
    a challenge ACK is sent or not is available in the separate function
    tcp_challenge_ack_check(). This new function will also be used for
    sending challenge ACKs in the SYN-cache code, which will be added in
    upcoming commits.
    No functional change intended.
    
    Reviewed by:            cc, Nick Banks, Peter Lei
    MFC after:              3 days
    Sponsored by:           Netflix, Inc.
    Differential Revision:  https://reviews.freebsd.org/D52717
---
 sys/netinet/tcp_subr.c | 42 +++++++++++++++++++++++++++---------------
 sys/netinet/tcp_var.h  |  1 +
 2 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index cc83a21773a8..c817c79881d6 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2148,14 +2148,16 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
 }
 
 /*
- * Send a challenge ack (no data, no SACK option), but not more than
- * V_tcp_ack_war_cnt per V_tcp_ack_war_time_window (per TCP connection).
+ * Check that no more than V_tcp_ack_war_cnt per V_tcp_ack_war_time_window
+ * are sent. *epoch_end is the end of the current epoch and is updated, if the
+ * current epoch ended in the past. *ack_cnt is the counter used during the
+ * current epoch. It might be reset and incremented.
+ * The function returns true if a challenge ACK should be sent.
  */
-void
-tcp_send_challenge_ack(struct tcpcb *tp, struct tcphdr *th, struct mbuf *m)
+bool
+tcp_challenge_ack_check(sbintime_t *epoch_end, uint32_t *ack_cnt)
 {
 	sbintime_t now;
-	bool send_challenge_ack;
 
 	/*
 	 * The sending of a challenge ACK could be triggered by a blind attacker
@@ -2164,29 +2166,39 @@ tcp_send_challenge_ack(struct tcpcb *tp, struct tcphdr *th, struct mbuf *m)
 	 * would have guessed wrongly.
 	 */
 	(void)badport_bandlim(BANDLIM_TCP_RST);
+
 	if (V_tcp_ack_war_time_window == 0 || V_tcp_ack_war_cnt == 0) {
 		/* ACK war protection is disabled. */
-		send_challenge_ack = true;
+		return (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 +
-			    V_tcp_ack_war_time_window * SBT_1MS;
+		if (*epoch_end < now) {
+			*ack_cnt = 0;
+			*epoch_end = now + V_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 < V_tcp_ack_war_cnt) {
-			send_challenge_ack = true;
-			tp->t_challenge_ack_cnt++;
+		if (*ack_cnt < V_tcp_ack_war_cnt) {
+			(*ack_cnt)++;
+			return (true);
 		} else {
-			send_challenge_ack = false;
+			return (false);
 		}
 	}
-	if (send_challenge_ack) {
+}
+
+/*
+ * Send a challenge ack (no data, no SACK option), but not more than
+ * V_tcp_ack_war_cnt per V_tcp_ack_war_time_window (per TCP connection).
+ */
+void
+tcp_send_challenge_ack(struct tcpcb *tp, struct tcphdr *th, struct mbuf *m)
+{
+	if (tcp_challenge_ack_check(&tp->t_challenge_ack_end,
+	    &tp->t_challenge_ack_cnt)) {
 		tcp_respond(tp, mtod(m, void *), th, m, tp->rcv_nxt,
 		    tp->snd_nxt, TH_ACK);
 		tp->last_ack_sent = tp->rcv_nxt;
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 53856bae9a66..c3be95c80798 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1462,6 +1462,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);
+bool	 tcp_challenge_ack_check(sbintime_t *, uint32_t *);
 void	 tcp_send_challenge_ack(struct tcpcb *, struct tcphdr *, struct mbuf *);
 bool	 tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *,
 	    struct mbuf *, int);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202509251824.58PIOjDq047609>