diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2008-11-24 12:57:38 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2008-11-24 12:57:38 +0000 |
commit | 886d2362a0e2964795f03a71c0e918b1b37b5214 (patch) | |
tree | ab635762d022f124b380626fec9d10c185f4ce87 /sys/kern/uipc_mbuf.c | |
parent | cf626db53398f9a16883b8a81bfc6be80564d9ab (diff) |
add several backend pools to allocate mbufs clusters of various sizes out
of. currently limited to MCLBYTES (2048 bytes) and 4096 bytes until pools
can allocate objects of sizes greater than PAGESIZE.
this allows drivers to ask for "jumbo" packets to fill rx rings with.
the second half of this change is per interface mbuf cluster allocator
statistics. drivers can use the new interface (MCLGETI), which will use
these stats to selectively fail allocations based on demand for mbufs. if
the driver isnt rapidly consuming rx mbufs, we dont allow it to allocate
many to put on its rx ring.
drivers require modifications to take advantage of both the new allocation
semantic and large clusters.
this was written and developed with deraadt@ over the last two days
ok deraadt@ claudio@
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r-- | sys/kern/uipc_mbuf.c | 87 |
1 files changed, 65 insertions, 22 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 7db45a81cff..c0c53fb447b 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.94 2008/10/14 18:01:53 naddy Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.95 2008/11/24 12:57:37 dlg Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -90,7 +90,22 @@ struct mbstat mbstat; /* mbuf stats */ struct pool mbpool; /* mbuf pool */ -struct pool mclpool; /* mbuf cluster pool */ + +/* mbuf cluster pools */ +struct mclsizes mclsizes[] = { + { MCLBYTES, 4, 1 }, /* must be at slot 0 */ + { 4 * 1024, 4, 2 }, +#ifdef notyet + /* pool allocator cannot cope with >PAGESIZE objects */ + { 8 * 1024, 4, 2 }, + { 9 * 1024, 4, 2 }, + { 12 * 1024, 4, 2 }, + { 16 * 1024, 4, 2 }, + { 64 * 1024, 4, 2 } +#endif +}; +static char mclnames[MCLPOOLS][8]; +struct pool mclpools[MCLPOOLS]; int max_linkhdr; /* largest link-level header */ int max_protohdr; /* largest protocol header */ @@ -102,7 +117,7 @@ void nmbclust_update(void); const char *mclpool_warnmsg = - "WARNING: mclpool limit reached; increase kern.maxclusters"; + "WARNING: mclpools limit reached; increase kern.maxclusters"; /* * Initialize the mbuf allocator. @@ -110,30 +125,35 @@ const char *mclpool_warnmsg = void mbinit(void) { + int i; + pool_init(&mbpool, MSIZE, 0, 0, 0, "mbpl", NULL); - pool_init(&mclpool, MCLBYTES, 0, 0, 0, "mclpl", NULL); + pool_setlowat(&mbpool, mblowat); - nmbclust_update(); + for (i = 0; i < nitems(mclsizes); i++) { + snprintf(mclnames[i], sizeof(mclnames[0]), "mcl%dk", + mclsizes[i].size >> 10); + pool_init(&mclpools[i], mclsizes[i].size, 0, 0, 0, mclnames[i], + NULL); + pool_setlowat(&mclpools[i], mcllowat); + } - /* - * Set a low water mark for both mbufs and clusters. This should - * help ensure that they can be allocated in a memory starvation - * situation. This is important for e.g. diskless systems which - * must allocate mbufs in order for the pagedaemon to clean pages. - */ - pool_setlowat(&mbpool, mblowat); - pool_setlowat(&mclpool, mcllowat); + nmbclust_update(); } void nmbclust_update(void) { + int i; /* - * Set the hard limit on the mclpool to the number of + * Set the hard limit on the mclpools to the number of * mbuf clusters the kernel is to support. Log the limit * reached message max once a minute. */ - (void)pool_sethardlimit(&mclpool, nmbclust, mclpool_warnmsg, 60); + for (i = 0; i < nitems(mclsizes); i++) { + (void)pool_sethardlimit(&mclpools[i], nmbclust, + mclpool_warnmsg, 60); + } pool_sethiwat(&mbpool, nmbclust); } @@ -244,20 +264,41 @@ m_getclr(int nowait, int type) } void -m_clget(struct mbuf *m, int how) +m_clget(struct mbuf *m, int how, struct ifnet *ifp, u_int pktlen) { + struct pool *mclp; + int pi; int s; + for (pi = 0; pi < nitems(mclpools); pi++) { + mclp = &mclpools[pi]; + if (pktlen <= mclp->pr_size) + break; + } + +#ifdef DIAGNOSTIC + if (mclp == NULL) + panic("m_clget: request for %d sized cluster", pktlen); +#endif + + if (ifp != NULL && m_cldrop(ifp, pi)) + return; + s = splvm(); - m->m_ext.ext_buf = - pool_get(&mclpool, how == M_WAIT ? PR_WAITOK : 0); + m->m_ext.ext_buf = pool_get(mclp, how == M_WAIT ? PR_WAITOK : 0); splx(s); if (m->m_ext.ext_buf != NULL) { m->m_data = m->m_ext.ext_buf; m->m_flags |= M_EXT|M_CLUSTER; - m->m_ext.ext_size = MCLBYTES; + m->m_ext.ext_size = mclp->pr_size; m->m_ext.ext_free = NULL; m->m_ext.ext_arg = NULL; + + m->m_ext.ext_backend = pi; + m->m_ext.ext_ifp = ifp; + if (ifp != NULL) + m_clcount(ifp, pi); + MCLINITREFERENCE(m); } } @@ -278,9 +319,11 @@ m_free(struct mbuf *m) m->m_ext.ext_prevref; m->m_ext.ext_prevref->m_ext.ext_nextref = m->m_ext.ext_nextref; - } else if (m->m_flags & M_CLUSTER) - pool_put(&mclpool, m->m_ext.ext_buf); - else if (m->m_ext.ext_free) + } else if (m->m_flags & M_CLUSTER) { + m_cluncount(m); + pool_put(&mclpools[m->m_ext.ext_backend], + m->m_ext.ext_buf); + } else if (m->m_ext.ext_free) (*(m->m_ext.ext_free))(m->m_ext.ext_buf, m->m_ext.ext_size, m->m_ext.ext_arg); else |