From c414347bc572219a0c849853ade6e664a6092f33 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Mon, 29 Aug 2022 19:14:25 -0700 Subject: [PATCH] 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 -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 */