git: 3eeb22cb8194 - main - tcp: clean scoreboard when releasing the socket buffer

From: Richard Scheffenegger <rscheff_at_FreeBSD.org>
Date: Sat, 10 Feb 2024 09:33:59 UTC
The branch main has been updated by rscheff:

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

commit 3eeb22cb819409b49296ecb0acbd453671168313
Author:     Richard Scheffenegger <rscheff@FreeBSD.org>
AuthorDate: 2024-02-10 09:16:08 +0000
Commit:     Richard Scheffenegger <rscheff@FreeBSD.org>
CommitDate: 2024-02-10 09:20:00 +0000

    tcp: clean scoreboard when releasing the socket buffer
    
    The SACK scoreboard is conceptually an extention of the socket
    buffer. Remove it when the socket buffer goes away with
    soisdisconnected(). Verify that this is also the expected
    state in tcp_discardcb().
    
    PR:                     276761
    Reviewed by:            glebius, tuexen, #transport
    Sponsored by:           NetApp, Inc.
    Differential Revision:  https://reviews.freebsd.org/D43805
---
 sys/netinet/tcp_input.c    | 1 +
 sys/netinet/tcp_subr.c     | 5 ++---
 sys/netinet/tcp_timewait.c | 1 +
 sys/netinet/tcp_usrreq.c   | 1 +
 4 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index afcda60137ec..b3201750c1e6 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -3022,6 +3022,7 @@ process_ACK:
 				 * we'll hang forever.
 				 */
 				if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
+					tcp_free_sackholes(tp);
 					soisdisconnected(so);
 					tcp_timer_activate(tp, TT_2MSL,
 					    (tcp_fast_finwait2_recycle ?
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index be38280aef0a..6043a3d458e5 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2383,6 +2383,7 @@ tcp_discardcb(struct tcpcb *tp)
 #endif
 
 	INP_WLOCK_ASSERT(inp);
+	MPASS(TAILQ_EMPTY(&tp->snd_holes));
 
 	tcp_timer_stop(tp);
 
@@ -2394,9 +2395,6 @@ tcp_discardcb(struct tcpcb *tp)
 	if (tp->t_flags & TF_TOE)
 		tcp_offload_detach(tp);
 #endif
-
-	tcp_free_sackholes(tp);
-
 #ifdef TCPPCAP
 	/* Free the TCP PCAP queues. */
 	tcp_pcap_drain(&(tp->t_inpkts));
@@ -2531,6 +2529,7 @@ tcp_close(struct tcpcb *tp)
 	if (tp->t_state != TCPS_CLOSED)
 		tcp_state_change(tp, TCPS_CLOSED);
 	KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
+	tcp_free_sackholes(tp);
 	soisdisconnected(so);
 	if (inp->inp_flags & INP_SOCKREF) {
 		inp->inp_flags &= ~INP_SOCKREF;
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 328f8fe84a8c..266556274e18 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -119,6 +119,7 @@ tcp_twstart(struct tcpcb *tp)
 	    "(inp->inp_flags & INP_DROPPED) != 0"));
 
 	tcp_state_change(tp, TCPS_TIME_WAIT);
+	tcp_free_sackholes(tp);
 	soisdisconnected(inp->inp_socket);
 
 	if (tp->t_flags & TF_ACKNOW)
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index ccd6a6149dae..a283d308801f 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -2777,6 +2777,7 @@ tcp_usrclosed(struct tcpcb *tp)
 	if (tp->t_acktime == 0)
 		tp->t_acktime = ticks;
 	if (tp->t_state >= TCPS_FIN_WAIT_2) {
+		tcp_free_sackholes(tp);
 		soisdisconnected(tptosocket(tp));
 		/* Prevent the connection hanging in FIN_WAIT_2 forever. */
 		if (tp->t_state == TCPS_FIN_WAIT_2) {