git: c414347bc572 - main - mbufs: isolate max_linkhdr and max_protohdr handling in the mbuf code

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Tue, 30 Aug 2022 02:24:52 UTC
The branch main has been updated by glebius:

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

commit c414347bc572219a0c849853ade6e664a6092f33
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2022-08-30 02:14:25 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2022-08-30 02:14:25 +0000

    mbufs: isolate max_linkhdr and max_protohdr handling in the mbuf code
    
    o Statically initialize max_linkhdr to default value without relying
      on domain(9) code doing that.
    o Statically initialize max_protohdr to a sane value, without relying
      on TCP being always compiled in.
    o Retire max_datalen. Set, but not used.
    o Don't make the domain(9) system responsible in validating these
      values and updating max_hdr.  Instead provide KPI max_linkhdr_grow()
      and max_protohdr_grow().
    o Call max_linkhdr_grow() from IEEE802.11 and max_protohdr_grow() from
      TCP.  Those are the only protocols today that may want to grow.
    
    Reviewed by:            tuexen
    Differential revision:  https://reviews.freebsd.org/D36376
---
 sys/kern/uipc_domain.c         | 10 -------
 sys/kern/uipc_mbuf.c           | 60 ++++++++++++++++++++++++++++++------------
 sys/net80211/ieee80211_proto.c |  7 +----
 sys/netinet/tcp_subr.c         |  9 ++-----
 sys/sys/mbuf.h                 | 10 ++++---
 5 files changed, 52 insertions(+), 44 deletions(-)

diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 8c6bd93ae703..3c0a570842b0 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -266,13 +266,6 @@ domain_init(struct domain *dp)
 			pr_init(pr);
 		}
 
-	/*
-	 * update global information about maximums
-	 */
-	max_hdr = max_linkhdr + max_protohdr;
-	max_datalen = MHLEN - max_hdr;
-	if (max_datalen < 1)
-		panic("%s: max_datalen < 1", __func__);
 	atomic_set_rel_int(&dp->dom_flags, DOMF_INITED);
 }
 
@@ -330,9 +323,6 @@ static void
 domaininit(void *dummy)
 {
 
-	if (max_linkhdr < 16)		/* XXX */
-		max_linkhdr = 16;
-
 	mtx_lock(&dom_mtx);
 	KASSERT(domain_init_status == 0, ("domaininit called too late!"));
 	domain_init_status = 1;
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 17fa670c9406..3f400d3563c4 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -117,30 +117,56 @@ SDT_PROBE_DEFINE1_XLATE(sdt, , , m__freem,
 
 #include <security/mac/mac_framework.h>
 
-int	max_linkhdr;
-int	max_protohdr;
-int	max_hdr;
-int	max_datalen;
+/*
+ * Provide minimum possible defaults for link and protocol header space,
+ * assuming IPv4 over Ethernet.  Enabling IPv6, IEEE802.11 or some other
+ * protocol may grow these values.
+ */
+u_int	max_linkhdr = 16;
+u_int	max_protohdr = 40;
+u_int	max_hdr = 16 + 40;
+SYSCTL_INT(_kern_ipc, KIPC_MAX_LINKHDR, max_linkhdr, CTLFLAG_RD,
+	   &max_linkhdr, 16, "Size of largest link layer header");
+SYSCTL_INT(_kern_ipc, KIPC_MAX_PROTOHDR, max_protohdr, CTLFLAG_RD,
+	   &max_protohdr, 40, "Size of largest protocol layer header");
+SYSCTL_INT(_kern_ipc, KIPC_MAX_HDR, max_hdr, CTLFLAG_RD,
+	   &max_hdr, 16 + 40, "Size of largest link plus protocol header");
+
+static void
+max_hdr_grow(void)
+{
+
+	max_hdr = max_linkhdr + max_protohdr;
+	MPASS(max_hdr <= MHLEN);
+}
+
+void
+max_linkhdr_grow(u_int new)
+{
+
+	if (new > max_linkhdr) {
+		max_linkhdr = new;
+		max_hdr_grow();
+	}
+}
+
+void
+max_protohdr_grow(u_int new)
+{
+
+	if (new > max_protohdr) {
+		max_protohdr = new;
+		max_hdr_grow();
+	}
+}
+
 #ifdef MBUF_STRESS_TEST
 int	m_defragpackets;
 int	m_defragbytes;
 int	m_defraguseless;
 int	m_defragfailure;
 int	m_defragrandomfailures;
-#endif
 
-/*
- * sysctl(8) exported objects
- */
-SYSCTL_INT(_kern_ipc, KIPC_MAX_LINKHDR, max_linkhdr, CTLFLAG_RD,
-	   &max_linkhdr, 0, "Size of largest link layer header");
-SYSCTL_INT(_kern_ipc, KIPC_MAX_PROTOHDR, max_protohdr, CTLFLAG_RD,
-	   &max_protohdr, 0, "Size of largest protocol layer header");
-SYSCTL_INT(_kern_ipc, KIPC_MAX_HDR, max_hdr, CTLFLAG_RD,
-	   &max_hdr, 0, "Size of largest link plus protocol header");
-SYSCTL_INT(_kern_ipc, KIPC_MAX_DATALEN, max_datalen, CTLFLAG_RD,
-	   &max_datalen, 0, "Minimum space left in mbuf after max_hdr");
-#ifdef MBUF_STRESS_TEST
 SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragpackets, CTLFLAG_RD,
 	   &m_defragpackets, 0, "");
 SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragbytes, CTLFLAG_RD,
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 01da0c2a0768..87fed05a281c 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -273,12 +273,7 @@ ieee80211_proto_attach(struct ieee80211com *ic)
 		+ IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
 		+ IEEE80211_WEP_EXTIVLEN;
 	/* XXX no way to recalculate on ifdetach */
-	if (ALIGN(hdrlen) > max_linkhdr) {
-		/* XXX sanity check... */
-		max_linkhdr = ALIGN(hdrlen);
-		max_hdr = max_linkhdr + max_protohdr;
-		max_datalen = MHLEN - max_hdr;
-	}
+	max_linkhdr_grow(ALIGN(hdrlen));
 	//ic->ic_protmode = IEEE80211_PROT_CTSONLY;
 
 	TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic);
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 1c04de080623..f2dc1b0b2836 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1543,15 +1543,10 @@ tcp_init(void *arg __unused)
 	}
 
 #ifdef INET6
-#define TCP_MINPROTOHDR (sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
+	max_protohdr_grow(sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
 #else /* INET6 */
-#define TCP_MINPROTOHDR (sizeof(struct tcpiphdr))
+	max_protohdr_grow(sizeof(struct tcpiphdr));
 #endif /* INET6 */
-	if (max_protohdr < TCP_MINPROTOHDR)
-		max_protohdr = TCP_MINPROTOHDR;
-	if (max_linkhdr + TCP_MINPROTOHDR > MHLEN)
-		panic("tcp_init");
-#undef TCP_MINPROTOHDR
 
 	ISN_LOCK_INIT();
 	EVENTHANDLER_REGISTER(shutdown_pre_sync, tcp_fini, NULL,
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 601b1e92c172..fa72314f78ed 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -1300,10 +1300,12 @@ m_rcvif(struct mbuf *m)
 /* Length to m_copy to copy all. */
 #define	M_COPYALL	1000000000
 
-extern int		max_datalen;	/* MHLEN - max_hdr */
-extern int		max_hdr;	/* Largest link + protocol header */
-extern int		max_linkhdr;	/* Largest link-level header */
-extern int		max_protohdr;	/* Largest protocol header */
+extern u_int		max_linkhdr;	/* Largest link-level header */
+extern u_int		max_hdr;	/* Largest link + protocol header */
+extern u_int		max_protohdr;	/* Largest protocol header */
+void max_linkhdr_grow(u_int);
+void max_protohdr_grow(u_int);
+
 extern int		nmbclusters;	/* Maximum number of clusters */
 extern bool		mb_use_ext_pgs;	/* Use ext_pgs for sendfile */