Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 8 Sep 2022 16:16:46 GMT
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: e80062a2d433 - main - tcp: avoid call to soisconnected() on transition to ESTABLISHED
Message-ID:  <202209081616.288GGkE7074939@gitrepo.freebsd.org>

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

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

commit e80062a2d43376a3b89ca68ab6c6f63b8e032e1d
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2022-09-08 16:16:04 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2022-09-08 16:16:04 +0000

    tcp: avoid call to soisconnected() on transition to ESTABLISHED
    
    This call existed since pre-FreeBSD times, and it is hard to understand
    why it was there in the first place.  After 6f3caa6d815 it definitely
    became necessary always and commit message from f1ee30ccd60 confirms that.
    Now that 6f3caa6d815 is effectively backed out by 07285bb4c22, the call
    appears to be useful only for sockets that landed on the incomplete queue,
    e.g. sockets that have accept_filter(9) enabled on them.
    
    Provide a new TCP flag to mark connections that are known to be on the
    incomplete queue, and call soisconnected() only for those connections.
    
    Reviewed by:            rrs, tuexen
    Differential revision:  https://reviews.freebsd.org/D36488
---
 sys/kern/uipc_socket.c     | 8 ++++++--
 sys/netinet/tcp_input.c    | 5 ++++-
 sys/netinet/tcp_syncache.c | 3 ++-
 sys/netinet/tcp_usrreq.c   | 4 ++--
 sys/netinet/tcp_var.h      | 2 +-
 sys/sys/socketvar.h        | 2 +-
 6 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 360b7b56cee5..7f5e70d14e91 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -800,7 +800,7 @@ sonewconn(struct socket *head, int connstatus)
 		return (NULL);
 	}
 
-	solisten_enqueue(so, connstatus);
+	(void)solisten_enqueue(so, connstatus);
 
 	return (so);
 }
@@ -808,8 +808,10 @@ sonewconn(struct socket *head, int connstatus)
 /*
  * Enqueue socket cloned by solisten_clone() to the listen queue of the
  * listener it has been cloned from.
+ *
+ * Return 'true' if socket landed on complete queue, otherwise 'false'.
  */
-void
+bool
 solisten_enqueue(struct socket *so, int connstatus)
 {
 	struct socket *head = so->so_listen;
@@ -827,6 +829,7 @@ solisten_enqueue(struct socket *so, int connstatus)
 		so->so_qstate = SQ_COMP;
 		head->sol_qlen++;
 		solisten_wakeup(head);	/* unlocks */
+		return (true);
 	} else {
 		/*
 		 * Keep removing sockets from the head until there's room for
@@ -853,6 +856,7 @@ solisten_enqueue(struct socket *so, int connstatus)
 		so->so_qstate = SQ_INCOMP;
 		head->sol_incqlen++;
 		SOLISTEN_UNLOCK(head);
+		return (false);
 	}
 }
 
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index e8f2676f2aa8..86071141b174 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -2433,7 +2433,10 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
 	case TCPS_SYN_RECEIVED:
 
 		TCPSTAT_INC(tcps_connects);
-		soisconnected(so);
+		if (tp->t_flags & TF_INCQUEUE) {
+			tp->t_flags &= ~TF_INCQUEUE;
+			soisconnected(so);
+		}
 		/* Do window scaling? */
 		if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
 			(TF_RCVD_SCALE|TF_REQ_SCALE)) {
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 76272179dac6..f0ee539fa1ec 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1039,7 +1039,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
 	TCPSTAT_INC(tcps_accepts);
 	TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, TCPS_LISTEN);
 
-	solisten_enqueue(so, SS_ISCONNECTED);
+	if (!solisten_enqueue(so, SS_ISCONNECTED))
+		tp->t_flags |= TF_INCQUEUE;
 
 	return (so);
 
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index d1b7ce5daa67..474cdb4d7787 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -2978,8 +2978,8 @@ db_print_tflags(u_int t_flags)
 		db_printf("%sTF_MORETOCOME", comma ? ", " : "");
 		comma = 1;
 	}
-	if (t_flags & TF_LQ_OVERFLOW) {
-		db_printf("%sTF_LQ_OVERFLOW", comma ? ", " : "");
+	if (t_flags & TF_INCQUEUE) {
+		db_printf("%sTF_INCQUEUE", comma ? ", " : "");
 		comma = 1;
 	}
 	if (t_flags & TF_LASTIDLE) {
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 20bf72dcd9d0..6019f162090e 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -515,7 +515,7 @@ tcp_unlock_or_drop(struct tcpcb *tp, int tcp_output_retval)
 #define	TF_WAKESOR	0x00004000	/* wake up receive socket */
 #define	TF_GPUTINPROG	0x00008000	/* Goodput measurement in progress */
 #define	TF_MORETOCOME	0x00010000	/* More data to be appended to sock */
-#define	TF_LQ_OVERFLOW	0x00020000	/* listen queue overflow */
+#define	TF_INCQUEUE	0x00020000	/* on incomplete queue of listener */
 #define	TF_LASTIDLE	0x00040000	/* connection was previously idle */
 #define	TF_RXWIN0SENT	0x00080000	/* sent a receiver win 0 in response */
 #define	TF_FASTRECOVERY	0x00100000	/* in NewReno Fast Recovery */
diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h
index 678642eeff6d..0c60b9e13cf2 100644
--- a/sys/sys/socketvar.h
+++ b/sys/sys/socketvar.h
@@ -474,7 +474,7 @@ int	solisten(struct socket *so, int backlog, struct thread *td);
 void	solisten_proto(struct socket *so, int backlog);
 void	solisten_proto_abort(struct socket *so);
 int	solisten_proto_check(struct socket *so);
-void	solisten_enqueue(struct socket *, int);
+bool	solisten_enqueue(struct socket *, int);
 int	solisten_dequeue(struct socket *, struct socket **, int);
 struct socket *
 	solisten_clone(struct socket *);



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