The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=614087c65e997fcdedcd60f368a035a4b09d106d
commit 614087c65e997fcdedcd60f368a035a4b09d106d Author: Konstantin Belousov <k...@freebsd.org> AuthorDate: 2025-06-24 02:51:52 +0000 Commit: Konstantin Belousov <k...@freebsd.org> CommitDate: 2025-06-24 15:58:53 +0000 sysctl net.inet.tcp.ktlslist: do not rely on global generation for ktls sessions Disallow parallel executions for the sysctl, which makes it possible to have the generation count for the sysctl requests itself instead of for the sessions. When the first pass over inpcbs is done, assign them the request' gen count. On the second pass, only externalize the inpcbs with ktls sessions which gen count is equal to the current request. This way, we can be sure that the second pass does not copy out more inpcbs than was counted for in the first pass, while eliminating the global atomic op during ktls session creation. Requested by: gallatin Reviewed by: gallatin, markj Sponsored by: NVidia networking Differential revision: https://reviews.freebsd.org/D51000 --- sys/kern/uipc_ktls.c | 10 ++-------- sys/netinet/tcp_subr.c | 41 +++++++++++++++++++++++++++++------------ sys/sys/ktls.h | 7 ------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c index 1cbaa7db2e84..ce09042abdac 100644 --- a/sys/kern/uipc_ktls.c +++ b/sys/kern/uipc_ktls.c @@ -595,8 +595,6 @@ start: return (error); } -uint64_t ktls_glob_gen = 1; - static int ktls_create_session(struct socket *so, struct tls_enable *en, struct ktls_session **tlsp, int direction) @@ -821,8 +819,7 @@ ktls_create_session(struct socket *so, struct tls_enable *en, arc4rand(tls->params.iv + 8, sizeof(uint64_t), 0); } - atomic_thread_fence_rel(); - tls->gen = atomic_fetchadd_64(&ktls_glob_gen, 1); + tls->gen = 0; *tlsp = tls; return (0); } @@ -865,8 +862,7 @@ ktls_clone_session(struct ktls_session *tls, int direction) memcpy(tls_new->params.cipher_key, tls->params.cipher_key, tls->params.cipher_key_len); - atomic_thread_fence_rel(); - tls_new->gen = atomic_fetchadd_64(&ktls_glob_gen, 1); + tls_new->gen = 0; return (tls_new); } @@ -1946,8 +1942,6 @@ ktls_destroy(struct ktls_session *tls) MPASS(tls->refcount == 0); - atomic_add_acq_64(&ktls_glob_gen, 1); - inp = tls->inp; if (tls->tx) { wlocked = INP_WLOCKED(inp); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 7cd2168d262b..4542c5ccb8bb 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -2669,8 +2669,13 @@ SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist, #define SND_TAG_STATUS_MAXLEN 128 #ifdef KERN_TLS + +static struct sx ktlslist_lock; +SX_SYSINIT(ktlslistlock, &ktlslist_lock, "ktlslist"); +static uint64_t ktls_glob_gen = 1; + static int -tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) +tcp_ktlslist_locked(SYSCTL_HANDLER_ARGS, bool export_keys) { struct xinpgen xig; struct inpcb *inp; @@ -2684,6 +2689,7 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) int error; bool ek, p; + sx_assert(&ktlslist_lock, SA_XLOCKED); if (req->newptr != NULL) return (EPERM); @@ -2692,7 +2698,7 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) ipi_gencnt = V_tcbinfo.ipi_gencnt; bzero(&xig, sizeof(xig)); xig.xig_len = sizeof(xig); - xig.xig_gen = atomic_load_acq_64(&ktls_glob_gen); + xig.xig_gen = ktls_glob_gen++; xig.xig_sogen = so_gencnt; struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_tcbinfo, @@ -2708,7 +2714,8 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) ek = export_keys && cr_canexport_ktlskeys( req->td, inp); ksr = so->so_rcv.sb_tls_info; - if (ktls_session_genvis(ksr, xig.xig_gen)) { + if (ksr != NULL) { + ksr->gen = xig.xig_gen; p = true; if (ek) { sz = SIZE_T_MAX; @@ -2726,7 +2733,8 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) } } kss = so->so_snd.sb_tls_info; - if (ktls_session_genvis(kss, xig.xig_gen)) { + if (kss != NULL) { + kss->gen = xig.xig_gen; p = true; if (ek) { sz = SIZE_T_MAX; @@ -2783,11 +2791,11 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) ksr = so->so_rcv.sb_tls_info; kss = so->so_snd.sb_tls_info; xktls = (struct xktls_session *)buf; - if (ktls_session_genvis(ksr, xig.xig_gen)) { + if (ksr != NULL && ksr->gen == xig.xig_gen) { p = true; ktls_session_to_xktls_onedir(ksr, ek, &xktls->rcv); } - if (ktls_session_genvis(kss, xig.xig_gen)) { + if (kss != NULL && kss->gen == xig.xig_gen) { p = true; ktls_session_to_xktls_onedir(kss, ek, &xktls->snd); } @@ -2798,7 +2806,7 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) xktls->so_pcb = (kvaddr_t)inp; memcpy(&xktls->coninf, &inp->inp_inc, sizeof(xktls->coninf)); len = sizeof(*xktls); - if (ktls_session_genvis(ksr, xig.xig_gen)) { + if (ksr != NULL && ksr->gen == xig.xig_gen) { if (ek) { sz = buflen - len; ktls_session_copy_keys(ksr, buf + len, &sz); @@ -2815,7 +2823,7 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) len += sz; } } - if (ktls_session_genvis(kss, xig.xig_gen)) { + if (kss != NULL && kss->gen == xig.xig_gen) { if (ek) { sz = buflen - len; ktls_session_copy_keys(kss, buf + len, &sz); @@ -2845,8 +2853,6 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) } if (error == 0) { - atomic_thread_fence_rel(); - xig.xig_gen = atomic_load_64(&ktls_glob_gen); xig.xig_sogen = so_gencnt; xig.xig_count = cnt; error = SYSCTL_OUT(req, &xig, sizeof(xig)); @@ -2856,16 +2862,27 @@ tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys) return (error); } +static int +tcp_ktlslist1(SYSCTL_HANDLER_ARGS, bool export_keys) +{ + int res; + + sx_xlock(&ktlslist_lock); + res = tcp_ktlslist_locked(oidp, arg1, arg2, req, export_keys); + sx_xunlock(&ktlslist_lock); + return (res); +} + static int tcp_ktlslist_nokeys(SYSCTL_HANDLER_ARGS) { - return (tcp_ktlslist(oidp, arg1, arg2, req, false)); + return (tcp_ktlslist1(oidp, arg1, arg2, req, false)); } static int tcp_ktlslist_wkeys(SYSCTL_HANDLER_ARGS) { - return (tcp_ktlslist(oidp, arg1, arg2, req, true)); + return (tcp_ktlslist1(oidp, arg1, arg2, req, true)); } SYSCTL_PROC(_net_inet_tcp, TCPCTL_KTLSLIST, ktlslist, diff --git a/sys/sys/ktls.h b/sys/sys/ktls.h index 0f9e5c5ed87b..a940bcfaba25 100644 --- a/sys/sys/ktls.h +++ b/sys/sys/ktls.h @@ -233,7 +233,6 @@ struct ktls_session { } __aligned(CACHE_LINE_SIZE); extern unsigned int ktls_ifnet_max_rexmit_pct; -extern uint64_t ktls_glob_gen; typedef enum { KTLS_MBUF_CRYPTO_ST_MIXED = 0, @@ -283,12 +282,6 @@ ktls_free(struct ktls_session *tls) ktls_destroy(tls); } -static inline bool -ktls_session_genvis(const struct ktls_session *ks, uint64_t gen) -{ - return (ks != NULL && ks->gen <= gen); -} - void ktls_session_to_xktls_onedir(const struct ktls_session *ks, bool export_keys, struct xktls_session_onedir *xktls_od); void ktls_session_copy_keys(const struct ktls_session *ktls,