git: ef438f7706be - main - tcp: improve consistency of syncache_respond() failure handling

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Thu, 05 Sep 2024 07:20:13 UTC
The branch main has been updated by tuexen:

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

commit ef438f7706be48f1cf7fd4c8a60329e1619cfe30
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2024-09-05 01:33:13 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2024-09-05 01:33:13 +0000

    tcp: improve consistency of syncache_respond() failure handling
    
    When the initial sending of the SYN ACK segment using
    syncache_respond() fails, it is handled as a permanent error.
    To improve consistency, apply this policy in all cases, where
    syncache_respond() is called. These include
    * timer based retransmissions of the SYN ACK
    * retransmitting a SYN ACK in response to a SYN retransmission
    * sending of challenge ACKs in response to received RST segments
    In these cases, fall back to SYN cookies, if enabled.
    While there, also improve consistency of the TCP stats counters.
    
    Reviewed by:            cc, glebius (earlier version)
    MFC after:              1 week
    Sponsored by:           Netflix, Inc.
    Differential Revision:  https://reviews.freebsd.org/D46428
---
 sys/netinet/tcp_syncache.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 33a6a66b7138..d0a7690256f4 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -527,10 +527,16 @@ syncache_timer(void *xsch)
 		}
 
 		NET_EPOCH_ENTER(et);
-		syncache_respond(sc, NULL, TH_SYN|TH_ACK);
+		if (syncache_respond(sc, NULL, TH_SYN|TH_ACK) == 0) {
+			syncache_timeout(sc, sch, 0);
+			TCPSTAT_INC(tcps_sndacks);
+			TCPSTAT_INC(tcps_sndtotal);
+			TCPSTAT_INC(tcps_sc_retransmitted);
+		} else {
+			syncache_drop(sc, sch);
+			TCPSTAT_INC(tcps_sc_dropped);
+		}
 		NET_EPOCH_EXIT(et);
-		TCPSTAT_INC(tcps_sc_retransmitted);
-		syncache_timeout(sc, sch, 0);
 	}
 	if (!TAILQ_EMPTY(&(sch)->sch_bucket))
 		callout_reset(&(sch)->sch_timer, (sch)->sch_nextc - tick,
@@ -688,7 +694,13 @@ syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th, struct mbuf *m,
 				    "sending challenge ACK\n",
 				    s, __func__,
 				    th->th_seq, sc->sc_irs + 1, sc->sc_wnd);
-			syncache_respond(sc, m, TH_ACK);
+			if (syncache_respond(sc, m, TH_ACK) == 0) {
+				TCPSTAT_INC(tcps_sndacks);
+				TCPSTAT_INC(tcps_sndtotal);
+			} else {
+				syncache_drop(sc, sch);
+				TCPSTAT_INC(tcps_sc_dropped);
+			}
 		}
 	} else {
 		if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
@@ -1549,6 +1561,9 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
 			syncache_timeout(sc, sch, 1);
 			TCPSTAT_INC(tcps_sndacks);
 			TCPSTAT_INC(tcps_sndtotal);
+		} else {
+			syncache_drop(sc, sch);
+			TCPSTAT_INC(tcps_sc_dropped);
 		}
 		SCH_UNLOCK(sch);
 		goto donenoprobe;