From nobody Fri Oct 23 18:56:25 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4jBC0n4NGGz6wFH0 for ; Fri, 23 Oct 2026 18:56:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jBC0n3ThBz4MYG for ; Fri, 23 Oct 2026 18:56:25 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1792781785; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tVlv3B8O3/QTRNHyNFncQuHxjEb1ElL7RvhyG9Co0Zk=; b=uuAb7fXrAGuiMMxZQxqde1IOTorcB5O4CzqJDGBx6VxMBlsFWcSbRqYiDZpHcCE6e5/XCQ 1xEy47wt61BCH7tXpW7F9/afcBFGvBdUilhVgEBje6mQQQI7eYNtfkOHl5/z4o7YXKNxI6 kn7p9fnaxHlnSb+Y7H9obn10b4NX1Xm3jD0hckKpDr8DwLGLF13Pd6EAak7fo0rtpaU2+C 1OATbVtyzHZW1FmKlnqhyiKzf62DUUVAtbkId2FAEBPCPXeeR8xMQO695tLu8ubz44RSo/ TNRo9qNlWGxPPiQ1O5V1U+2bjkdJbzYNt69sh+cORnK+XSLZIzjK+XfX5CgJYw== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1792781785; b=bOK6RoYFgr4CiELtuESqkJGvI0eiLGtFTJBZR5xeTcyzCd1LAqTJOjQaGmx6GQFBtbUXYc YfXyNXrPjAXv5x1E8dy8VSdjsDB0Ayd6XUV57g6BGdAfY/IrY34YFn4Nlf34NbSUiyOE1q saHPjdlwLF9t5Ca7vWFUXSVAQcOBLjs8fY+Zdssfx7z/kExxqP1H6IF84OCMpHDJwlG6qm /wqtjj3/kh7DicMrzIRf49nCtdpiTT34PO1psdBOOCjbxy5EJzokZo7uRQmk12V5fa72vy Wn0aPz+TPL6cJ3ni+C98jTH+ceIf+88wA4e1rKynJ5RhJKUI2b2eCV4GNV0afQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1792781785; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tVlv3B8O3/QTRNHyNFncQuHxjEb1ElL7RvhyG9Co0Zk=; b=QUdATjESxTJxj4ibRImLHbJjZ2bhu4iCb0RF/nAyry/ksaxgnNAgNU6TQoR2kN8FTboxr2 hRAs69BI0Q+9zeFGNZsAcfaBCA15BNuCV2hquh1A99He+J+EkTliq+utUont/QxynzjvCW z6yJEztHPuX/mVbM/sM3fD/X8UoN92dOPlzyBUopcl9d3wRZMcDLz1QchP3i9yGpoezFrh IciSJ4VS58bDSoEyBmNs/M5FxyQqT5XrTffAunoiBoEfEFYxqlgSDRpy/J1k4mFXnV+OFO chIQkQkAjXfiAhtOqkPkYru44W51LKFLZg4aoykMh4c8yK40PYHhgVNCVtI1tw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jBC0n384Tzjsq for ; Fri, 23 Oct 2026 18:56:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 224de by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 23 Oct 2026 18:56:25 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 91bff7d7ed46 - main - Revert "inpcb: add single peer local port caching" List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: Commit messages for the main branch of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 91bff7d7ed461360bc992dcd411703db6cd6d2a1 Auto-Submitted: auto-generated Date: Fri, 23 Oct 2026 18:56:25 +0000 Message-Id: <6adbadd9.224de.31ffaac7@gitrepo.freebsd.org> The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=91bff7d7ed461360bc992dcd411703db6cd6d2a1 commit 91bff7d7ed461360bc992dcd411703db6cd6d2a1 Author: Gleb Smirnoff AuthorDate: 2026-10-23 18:56:06 +0000 Commit: Gleb Smirnoff CommitDate: 2026-10-23 18:56:06 +0000 Revert "inpcb: add single peer local port caching" This reverts commit 289082428c764ed282623cc6f7ee9b7448fddad1. Requested by: markj --- sys/netinet/in_pcb.c | 244 +---------------------------------------------- sys/netinet/in_pcb.h | 2 +- sys/netinet/in_pcb_var.h | 1 - sys/netinet6/in6_pcb.c | 1 - 4 files changed, 2 insertions(+), 246 deletions(-) diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 35eb4614e2c6..d72fb4cce587 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -726,226 +726,6 @@ out: #endif } -VNET_DEFINE_STATIC(bool, lport_cache_enable) = true; -#define V_lport_cache_enable VNET(lport_cache_enable) -SYSCTL_BOOL(_net_inet_ip_portrange, OID_AUTO, lport_cache, - CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(lport_cache_enable), 0, - "Enable local port cache for peers that have many outgoing connections to"); - -static MALLOC_DEFINE(M_LPORTS, "inp_lports", "inpcb lport cache"); -#define PORTBITS (IPPORT_MAX + 1) -BITSET_DEFINE(lportbits, PORTBITS); -struct lport_cache { - struct lportbits lports; - struct lport_cache *successor; - uint64_t age; - u_int refcount; -#ifdef INVARIANTS - union in_dependaddr faddr; - uint16_t fport; -#endif -}; - -/* - * Remove one reference from cache, potentially freeing a chain. - */ -static struct lport_cache * -lport_cache_release(struct lport_cache *cache) -{ - - while (cache != NULL && refcount_release(&cache->refcount)) { - struct lport_cache *next; - - next = atomic_load_ptr(&cache->successor); - free(cache, M_LPORTS); - cache = next; - } - - return (cache); -} - -static inline void -lport_acquire(struct lportbits *lports, uint16_t port) -{ - BIT_SET_ATOMIC(PORTBITS, port, lports); -} - -static inline void -lport_release(struct lportbits *lports, uint16_t port) -{ - BIT_CLR_ATOMIC(PORTBITS, port, lports); -} - -static inline bool -lport_check(struct lportbits *lports, uint16_t port) -{ - return (BIT_ISSET(PORTBITS, port, lports)); -} - -static inline void -lport_merge(struct lportbits *dst, struct lportbits *src) -{ - BIT_OR_ATOMIC(PORTBITS, dst, src); -} - -/* - * Return inp->inp_lport_cache, potentially promoting it. - */ -static struct lport_cache * -in_pcb_lport_cache(struct inpcb *inp) -{ - struct lport_cache *cache, *next; - - INP_WLOCK_ASSERT(inp); - - if ((cache = inp->inp_lport_cache) != NULL) - while ((next = atomic_load_ptr(&cache->successor)) != NULL) { - MPASS(next != cache); - inp->inp_lport_cache = next; - if (refcount_release(&cache->refcount)) - free(cache, M_LPORTS); - else - refcount_acquire(&next->refcount); - cache = next; - } - - return (inp->inp_lport_cache); -} - -static void -in_pcb_cache_lport(struct inpcb *new, struct inpcb *old) -{ - struct lport_cache *cache; - - INP_WLOCK_ASSERT(new); - INP_WLOCK_ASSERT(old); - - /* - * When conflicted with a wildcard bound inpcb, we could actually cache - * the port number, but do not attach the cache to the wildcard inpcb. - * This would complicate this function, making each iteration more - * expensive. With the expectation that not so many ports in the - * anonymous range are occupied by wildcard inpcbs, usually zero, seems - * it would be more effective to not cover this case and have just tiny - * increase in attempts rather then making each attempt heavier. - */ -#ifdef INET6 - if (old->inp_vflag & INP_IPV6) { - if (IN6_IS_ADDR_UNSPECIFIED(&old->in6p_faddr)) - goto out; - } else -#endif - if (in_nullhost(old->inp_faddr)) - goto out; - - (void)in_pcb_lport_cache(new); - (void)in_pcb_lport_cache(old); - - if (new->inp_lport_cache == NULL && - old->inp_lport_cache == NULL) { - static uint64_t age; - - cache = malloc(sizeof(*cache), M_LPORTS, M_ZERO | M_NOWAIT); - if (__predict_false(cache == NULL)) - goto out; - refcount_init(&cache->refcount, 2); - cache->age = atomic_fetchadd_64(&age, 1); -#ifdef INVARIANTS - cache->faddr = old->inp_inc.inc_ie.ie_dependfaddr; - cache->fport = old->inp_fport; -#endif - lport_acquire(&cache->lports, ntohs(old->inp_lport)); - new->inp_lport_cache = old->inp_lport_cache = cache; - } else if (new->inp_lport_cache == old->inp_lport_cache) { - /* Race: old has grabbed the port after our lport_check(). */ - } else if (new->inp_lport_cache == NULL) { - cache = old->inp_lport_cache; - MPASS(memcmp(&old->inp_inc.inc_ie.ie_dependfaddr, - &cache->faddr, sizeof(union in_dependaddr)) == 0); - MPASS(old->inp_fport == cache->fport); - refcount_acquire(&cache->refcount); - new->inp_lport_cache = cache; - } else if (old->inp_lport_cache == NULL) { - cache = new->inp_lport_cache; - MPASS(memcmp(&old->inp_inc.inc_ie.ie_dependfaddr, - &cache->faddr, sizeof(union in_dependaddr)) == 0); - MPASS(old->inp_fport == cache->fport); - lport_acquire(&cache->lports, ntohs(old->inp_lport)); - refcount_acquire(&cache->refcount); - old->inp_lport_cache = cache; - } else { - struct lport_cache *second; - - /* - * We can't use caches refcounts here, as it makes it possible - * for two competing caches to be linked against each other by - * two parallel threads. We use age speculating that an older - * cache usually holds more bits. - */ - if (new->inp_lport_cache->age < old->inp_lport_cache->age) { - cache = new->inp_lport_cache; - second = old->inp_lport_cache; - MPASS(cache != second); - old->inp_lport_cache = cache; - } else { - cache = old->inp_lport_cache; - second = new->inp_lport_cache; - MPASS(cache != second); - new->inp_lport_cache = cache; - } - MPASS(memcmp(&old->inp_inc.inc_ie.ie_dependfaddr, - &cache->faddr, sizeof(union in_dependaddr)) == 0); - MPASS(old->inp_fport == cache->fport); - MPASS(memcmp(&second->faddr, &cache->faddr, - sizeof(union in_dependaddr)) == 0); - MPASS(second->fport == cache->fport); - lport_merge(&cache->lports, &second->lports); - refcount_acquire(&cache->refcount); - /* - * Now both inpcbs and winning cache are all set, and tricky - * part is to dereference 'second'. Three possibilities here: - * 1) our reference was the last and we free it 2) we were not - * the last so make it point at the winner 3) we lost the race - * to other thread that was doing the same. - */ - if (lport_cache_release(second) == second && - atomic_cmpset_ptr((uintptr_t *)&second->successor, - (uintptr_t)NULL, (uintptr_t)cache)) - refcount_acquire(&cache->refcount); - } -out: - INP_WUNLOCK(old); -} - -void -in_pcb_lport_cache_free(struct inpcb *inp) -{ - struct lport_cache *cache = inp->inp_lport_cache; - - INP_WLOCK_ASSERT(inp); - - /* Free possible chain of caches, where we were the last reference. */ - while (cache != NULL && refcount_release(&cache->refcount)) { - struct lport_cache *next; - - MPASS(memcmp(&inp->inp_inc.inc_ie.ie_dependfaddr, - &cache->faddr, sizeof(union in_dependaddr)) == 0); - MPASS(inp->inp_fport == cache->fport); - next = atomic_load_ptr(&cache->successor); - free(cache, M_LPORTS); - cache = next; - } - /* Walk through the remaining chain and clear our bit. */ - while (cache != NULL) { - MPASS(memcmp(&inp->inp_inc.inc_ie.ie_dependfaddr, - &cache->faddr, sizeof(union in_dependaddr)) == 0); - MPASS(inp->inp_fport == cache->fport); - lport_release(&cache->lports, ntohs(inp->inp_lport)); - cache = atomic_load_ptr(&cache->successor); - } - inp->inp_lport_cache = NULL; -} - /* * Assign a local port like in_pcb_lport(), but also used with connect() * and a foreign address and port. If fsa is non-NULL, choose a local port @@ -967,11 +747,8 @@ in_pcb_lport_dest(struct inpcbinfo_ctx *ipictx, struct inpcb *inp, #ifdef INET6 const struct in6_addr *laddr6, *faddr6; #endif - const bool use_cache = V_lport_cache_enable && INP_WLOCKED(inp) && - fsa != NULL; INP_LOCK_ASSERT(inp); - MPASS(inp->inp_lport_cache == NULL); if (inp->inp_flags & INP_HIGHPORT) { first = V_ipport_hifirstauto; /* sysctl */ @@ -1037,11 +814,6 @@ in_pcb_lport_dest(struct inpcbinfo_ctx *ipictx, struct inpcb *inp, .pcbinfo = ipictx->pcbinfo }; struct inpcb *tmpinp = NULL; - struct lport_cache *cache; - - if ((cache = in_pcb_lport_cache(inp)) != NULL && - lport_check(&cache->lports, port)) - goto next; lport = htons(port); @@ -1060,9 +832,6 @@ in_pcb_lport_dest(struct inpcbinfo_ctx *ipictx, struct inpcb *inp, M_NODOM, RT_ALL_FIBS); } #endif - if (use_cache && tmpinp != NULL && - inp_trylock(tmpinp, INPLOOKUP_WLOCKPCB)) - in_pcb_cache_lport(inp, tmpinp); } else { #ifdef INET6 if ((inp->inp_vflag & INP_IPV6) != 0) { @@ -1095,22 +864,13 @@ in_pcb_lport_dest(struct inpcbinfo_ctx *ipictx, struct inpcb *inp, break; } inpcbinfo_ctx_release(&tmpctx); -next: ++port; if (port < first || port > last) port = first; } - if (count == 0) { /* completely used? */ - if (inp->inp_lport_cache != NULL) { - lport_cache_release(inp->inp_lport_cache); - inp->inp_lport_cache = NULL; - } + if (count == 0) /* completely used? */ return (EADDRNOTAVAIL); - } - - if (inp->inp_lport_cache != NULL) - lport_acquire(&inp->inp_lport_cache->lports, ntohs(lport)); *lportp = lport; @@ -1752,7 +1512,6 @@ in_pcbdisconnect(struct inpcb *inp) if (inp->inp_flags & INP_UNCONNECTED) return; - in_pcb_lport_cache_free(inp); in_pcbremhash(inp); IPI_LOCK(inp->inp_pcbinfo); CK_LIST_INSERT_HEAD(&inp->inp_pcbinfo->ipi_list_unconn.head, inp, @@ -2180,7 +1939,6 @@ in_pcbfree(struct inpcb *inp) inp->inp_socket->so_pcb = NULL; inp->inp_socket = NULL; - in_pcb_lport_cache_free(inp); RO_INVALIDATE_CACHE(&inp->inp_route); #ifdef MAC mac_inpcb_destroy(inp); diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 5a6bbfd3b5b2..0d889feca7ed 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -382,7 +382,7 @@ struct inpcb { }; CK_LIST_ENTRY(inpcb) inp_portlist; /* (r:e/w:h) port list */ uint64_t inp_gencnt; /* (c) generation count */ - struct lport_cache *inp_lport_cache; + void *spare_ptr; /* Spare pointer. */ rt_gen_t inp_rt_cookie; /* generation for route entry */ union { /* cached L3 information */ struct route inp_route; diff --git a/sys/netinet/in_pcb_var.h b/sys/netinet/in_pcb_var.h index 2c6c342409dd..de9a09c6b2ca 100644 --- a/sys/netinet/in_pcb_var.h +++ b/sys/netinet/in_pcb_var.h @@ -131,7 +131,6 @@ void in_pcbrehash(struct inpcb *, struct inpcbinfo_ctx *); void in_pcbremhash(struct inpcb *); struct inpcblbgroup *in_pcblbgroup_find(struct inpcb *inp, struct lbgroupbucket **bucket); -void in_pcb_lport_cache_free(struct inpcb *); /* * Load balance groups used for the SO_REUSEPORT_LB socket option. Each group diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index e45fc0f3d832..05c04be5dd80 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -565,7 +565,6 @@ in6_pcbdisconnect(struct inpcb *inp) if (inp->inp_flags & INP_UNCONNECTED) return; - in_pcb_lport_cache_free(inp); in_pcbremhash(inp); IPI_LOCK(inp->inp_pcbinfo); CK_LIST_INSERT_HEAD(&inp->inp_pcbinfo->ipi_list_unconn.head, inp,