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
This commit is contained in:
Gleb Smirnoff 2022-08-29 19:14:25 -07:00
parent bb31aee26b
commit c414347bc5
5 changed files with 52 additions and 44 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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 */