diff --git a/share/man/man9/mbuf.9 b/share/man/man9/mbuf.9 --- a/share/man/man9/mbuf.9 +++ b/share/man/man9/mbuf.9 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 8, 2021 +.Dd August 8, 2021 .Dt MBUF 9 .Os .\" @@ -73,6 +73,8 @@ .Ft struct mbuf * .Fn m_get2 "int size" "int how" "short type" "int flags" .Ft struct mbuf * +.Fn m_get3 "int size" "int how" "short type" "int flags" +.Ft struct mbuf * .Fn m_getm "struct mbuf *orig" "int len" "int how" "short type" .Ft struct mbuf * .Fn m_getjcl "int how" "short type" "int flags" "int size" @@ -577,6 +579,13 @@ If the size is is larger than .Dv MJUMPAGESIZE , NULL will be returned. +.It Fn m_get3 size how type flags +Allocate an +.Vt mbuf +with enough space to hold specified amount of data. +If the size is is larger than +.Dv MJUM16BYTES, NULL +will be returned. .It Fn m_getm orig len how type Allocate .Fa len diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -1371,6 +1371,44 @@ return (m); } +/* + * m_get3() allocates minimum mbuf that would fit "size" argument. + * Unlike m_get2() it can allocate clusters up to MJUM16BYTES. + */ +struct mbuf * +m_get3(int size, int how, short type, int flags) +{ + struct mb_args args; + struct mbuf *m, *n; + uma_zone_t zone; + + if (size <= MJUMPAGESIZE) + return (m_get2(size, how, type, flags)); + + if (size > MJUM16BYTES) + return (NULL); + + args.flags = flags; + args.type = type; + + m = uma_zalloc_arg(zone_mbuf, &args, how); + if (m == NULL) + return (NULL); + + if (size <= MJUM9BYTES) + zone = zone_jumbo9; + else + zone = zone_jumbo16; + + n = uma_zalloc_arg(zone_jumbop, m, how); + if (n == NULL) { + m_free_raw(m); + return (NULL); + } + + return (m); +} + /* * m_getjcl() returns an mbuf with a cluster of the specified size attached. * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES. diff --git a/sys/net/bpf.c b/sys/net/bpf.c --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -644,14 +644,7 @@ return (EMSGSIZE); /* Allocate a mbuf for our write, since m_get2 fails if len >= to MJUMPAGESIZE, use m_getjcl for bigger buffers */ - if (len < MJUMPAGESIZE) - m = m_get2(len, M_WAITOK, MT_DATA, M_PKTHDR); - else if (len <= MJUM9BYTES) - m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR, MJUM9BYTES); - else if (len <= MJUM16BYTES) - m = m_getjcl(M_WAITOK, MT_DATA, M_PKTHDR, MJUM16BYTES); - else - m = NULL; + m = m_get3(len, M_WAITOK, MT_DATA, M_PKTHDR); if (m == NULL) return (EIO); m->m_pkthdr.len = m->m_len = len; diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -829,6 +829,7 @@ void m_freem(struct mbuf *); void m_free_raw(struct mbuf *); struct mbuf *m_get2(int, int, short, int); +struct mbuf *m_get3(int, int, short, int); struct mbuf *m_getjcl(int, short, int, int); struct mbuf *m_getm2(struct mbuf *, int, int, short, int); struct mbuf *m_getptr(struct mbuf *, int, int *);