git: ac56d68b1b71 - stable/14 - tcp: simplify endpoint creation at the passive side
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 03 Aug 2024 23:07:33 UTC
The branch stable/14 has been updated by tuexen:
URL: https://cgit.FreeBSD.org/src/commit/?id=ac56d68b1b71031370e94577adc5fbc12a0353d2
commit ac56d68b1b71031370e94577adc5fbc12a0353d2
Author: Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2024-07-21 09:49:37 +0000
Commit: Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2024-08-03 23:06:50 +0000
tcp: simplify endpoint creation at the passive side
Use the intended TCP stack when creating a TCP endpoint instead of
creating it the endpoint the default stack first and after that
switching it to use the intended TCP stack.
Reviewed by: Peter Lei, rrs and jtl (older version)
Sponsored by: Netflix, Inc.
Differential Revision: https://reviews.freebsd.org/D45411
(cherry picked from commit baee801c92d26f4b7d1b2a9edd755c1b07b84167)
---
sys/netinet/tcp_subr.c | 19 +++++++++++++++++--
sys/netinet/tcp_syncache.c | 39 ++++++---------------------------------
sys/netinet/tcp_usrreq.c | 2 +-
sys/netinet/tcp_var.h | 2 +-
4 files changed, 25 insertions(+), 37 deletions(-)
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 6feb1916bb35..5d87d0327148 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2221,9 +2221,11 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m,
* Create a new TCP control block, making an empty reassembly queue and hooking
* it to the argument protocol control block. The `inp' parameter must have
* come from the zone allocator set up by tcpcbstor declaration.
+ * The caller can provide a pointer to a tcpcb of the listener to inherit the
+ * TCP function block from the listener.
*/
struct tcpcb *
-tcp_newtcpcb(struct inpcb *inp)
+tcp_newtcpcb(struct inpcb *inp, struct tcpcb *listening_tcb)
{
struct tcpcb *tp = intotcpcb(inp);
#ifdef INET6
@@ -2241,8 +2243,21 @@ tcp_newtcpcb(struct inpcb *inp)
tp->t_ccv.type = IPPROTO_TCP;
tp->t_ccv.ccvc.tcp = tp;
rw_rlock(&tcp_function_lock);
- tp->t_fb = V_tcp_func_set_ptr;
+ if (listening_tcb != NULL) {
+ INP_LOCK_ASSERT(tptoinpcb(listening_tcb));
+ KASSERT(listening_tcb->t_fb != NULL,
+ ("tcp_newtcpcb: listening_tcb->t_fb is NULL"));
+ if (listening_tcb->t_fb->tfb_flags & TCP_FUNC_BEING_REMOVED) {
+ rw_runlock(&tcp_function_lock);
+ return (NULL);
+ }
+ tp->t_fb = listening_tcb->t_fb;
+ } else {
+ tp->t_fb = V_tcp_func_set_ptr;
+ }
refcount_acquire(&tp->t_fb->tfb_refcnt);
+ KASSERT((tp->t_fb->tfb_flags & TCP_FUNC_BEING_REMOVED) == 0,
+ ("tcp_newtcpcb: using TFB being removed"));
rw_runlock(&tcp_function_lock);
/*
* Use the current system default CC algorithm.
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 21dfe8dd123e..052e257a3cb5 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -777,7 +777,7 @@ done:
static struct socket *
syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
{
- struct tcp_function_block *blk;
+ struct tcpcb *listening_tcb;
struct inpcb *inp = NULL;
struct socket *so;
struct tcpcb *tp;
@@ -802,7 +802,11 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
goto allocfail;
}
inp = sotoinpcb(so);
- if ((tp = tcp_newtcpcb(inp)) == NULL) {
+ if (V_functions_inherit_listen_socket_stack)
+ listening_tcb = sototcpcb(lso);
+ else
+ listening_tcb = NULL;
+ if ((tp = tcp_newtcpcb(inp, listening_tcb)) == NULL) {
in_pcbfree(inp);
sodealloc(so);
goto allocfail;
@@ -912,37 +916,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
tp->t_port = sc->sc_port;
tcp_rcvseqinit(tp);
tcp_sendseqinit(tp);
- blk = sototcpcb(lso)->t_fb;
- if (V_functions_inherit_listen_socket_stack && blk != tp->t_fb) {
- /*
- * Our parents t_fb was not the default,
- * we need to release our ref on tp->t_fb and
- * pickup one on the new entry.
- */
- struct tcp_function_block *rblk;
- void *ptr = NULL;
-
- rblk = find_and_ref_tcp_fb(blk);
- KASSERT(rblk != NULL,
- ("cannot find blk %p out of syncache?", blk));
-
- if (rblk->tfb_tcp_fb_init == NULL ||
- (*rblk->tfb_tcp_fb_init)(tp, &ptr) == 0) {
- /* Release the old stack */
- if (tp->t_fb->tfb_tcp_fb_fini != NULL)
- (*tp->t_fb->tfb_tcp_fb_fini)(tp, 0);
- refcount_release(&tp->t_fb->tfb_refcnt);
- /* Now set in all the pointers */
- tp->t_fb = rblk;
- tp->t_fb_ptr = ptr;
- } else {
- /*
- * Initialization failed. Release the reference count on
- * the looked up default stack.
- */
- refcount_release(&rblk->tfb_refcnt);
- }
- }
tp->snd_wl1 = sc->sc_irs;
tp->snd_max = tp->iss + 1;
tp->snd_nxt = tp->iss + 1;
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 4e754965487b..384c27b3a6cd 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -174,7 +174,7 @@ tcp_usr_attach(struct socket *so, int proto, struct thread *td)
if (error)
goto out;
inp = sotoinpcb(so);
- tp = tcp_newtcpcb(inp);
+ tp = tcp_newtcpcb(inp, NULL);
if (tp == NULL) {
error = ENOBUFS;
in_pcbfree(inp);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 010ad748260a..4632474c1d11 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1463,7 +1463,7 @@ void tcp_mss_update(struct tcpcb *, int, int, struct hc_metrics_lite *,
void tcp_mss(struct tcpcb *, int);
int tcp_mssopt(struct in_conninfo *);
struct tcpcb *
- tcp_newtcpcb(struct inpcb *);
+ tcp_newtcpcb(struct inpcb *, struct tcpcb *);
int tcp_default_output(struct tcpcb *);
void tcp_state_change(struct tcpcb *, int);
void tcp_respond(struct tcpcb *, void *,