1099a0e58SBosko Milekic /*- 28076cb52SBosko Milekic * Copyright (c) 2004, 2005, 38076cb52SBosko Milekic * Bosko Milekic <bmilekic@FreeBSD.org>. All rights reserved. 4099a0e58SBosko Milekic * 5099a0e58SBosko Milekic * Redistribution and use in source and binary forms, with or without 6099a0e58SBosko Milekic * modification, are permitted provided that the following conditions 7099a0e58SBosko Milekic * are met: 8099a0e58SBosko Milekic * 1. Redistributions of source code must retain the above copyright 9099a0e58SBosko Milekic * notice unmodified, this list of conditions and the following 10099a0e58SBosko Milekic * disclaimer. 11099a0e58SBosko Milekic * 2. Redistributions in binary form must reproduce the above copyright 12099a0e58SBosko Milekic * notice, this list of conditions and the following disclaimer in the 13099a0e58SBosko Milekic * documentation and/or other materials provided with the distribution. 14099a0e58SBosko Milekic * 15099a0e58SBosko Milekic * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16099a0e58SBosko Milekic * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17099a0e58SBosko Milekic * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18099a0e58SBosko Milekic * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19099a0e58SBosko Milekic * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20099a0e58SBosko Milekic * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21099a0e58SBosko Milekic * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22099a0e58SBosko Milekic * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23099a0e58SBosko Milekic * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24099a0e58SBosko Milekic * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25099a0e58SBosko Milekic * SUCH DAMAGE. 26099a0e58SBosko Milekic */ 27099a0e58SBosko Milekic 28099a0e58SBosko Milekic #include <sys/cdefs.h> 29099a0e58SBosko Milekic __FBSDID("$FreeBSD$"); 30099a0e58SBosko Milekic 31099a0e58SBosko Milekic #include "opt_param.h" 32099a0e58SBosko Milekic 33099a0e58SBosko Milekic #include <sys/param.h> 34099a0e58SBosko Milekic #include <sys/malloc.h> 35099a0e58SBosko Milekic #include <sys/systm.h> 36099a0e58SBosko Milekic #include <sys/mbuf.h> 37099a0e58SBosko Milekic #include <sys/domain.h> 38099a0e58SBosko Milekic #include <sys/eventhandler.h> 39099a0e58SBosko Milekic #include <sys/kernel.h> 40099a0e58SBosko Milekic #include <sys/protosw.h> 41099a0e58SBosko Milekic #include <sys/smp.h> 42099a0e58SBosko Milekic #include <sys/sysctl.h> 43099a0e58SBosko Milekic 44aed55708SRobert Watson #include <security/mac/mac_framework.h> 45aed55708SRobert Watson 46099a0e58SBosko Milekic #include <vm/vm.h> 47c45c0034SAlan Cox #include <vm/vm_extern.h> 48c45c0034SAlan Cox #include <vm/vm_kern.h> 49099a0e58SBosko Milekic #include <vm/vm_page.h> 5037140716SAndre Oppermann #include <vm/vm_map.h> 51099a0e58SBosko Milekic #include <vm/uma.h> 52121f0509SMike Silbersack #include <vm/uma_int.h> 53121f0509SMike Silbersack #include <vm/uma_dbg.h> 54099a0e58SBosko Milekic 55099a0e58SBosko Milekic /* 56099a0e58SBosko Milekic * In FreeBSD, Mbufs and Mbuf Clusters are allocated from UMA 57099a0e58SBosko Milekic * Zones. 58099a0e58SBosko Milekic * 59099a0e58SBosko Milekic * Mbuf Clusters (2K, contiguous) are allocated from the Cluster 60099a0e58SBosko Milekic * Zone. The Zone can be capped at kern.ipc.nmbclusters, if the 61099a0e58SBosko Milekic * administrator so desires. 62099a0e58SBosko Milekic * 63099a0e58SBosko Milekic * Mbufs are allocated from a UMA Master Zone called the Mbuf 64099a0e58SBosko Milekic * Zone. 65099a0e58SBosko Milekic * 66099a0e58SBosko Milekic * Additionally, FreeBSD provides a Packet Zone, which it 67099a0e58SBosko Milekic * configures as a Secondary Zone to the Mbuf Master Zone, 68099a0e58SBosko Milekic * thus sharing backend Slab kegs with the Mbuf Master Zone. 69099a0e58SBosko Milekic * 70099a0e58SBosko Milekic * Thus common-case allocations and locking are simplified: 71099a0e58SBosko Milekic * 72099a0e58SBosko Milekic * m_clget() m_getcl() 73099a0e58SBosko Milekic * | | 74099a0e58SBosko Milekic * | .------------>[(Packet Cache)] m_get(), m_gethdr() 75099a0e58SBosko Milekic * | | [ Packet ] | 76099a0e58SBosko Milekic * [(Cluster Cache)] [ Secondary ] [ (Mbuf Cache) ] 77099a0e58SBosko Milekic * [ Cluster Zone ] [ Zone ] [ Mbuf Master Zone ] 78099a0e58SBosko Milekic * | \________ | 79099a0e58SBosko Milekic * [ Cluster Keg ] \ / 80099a0e58SBosko Milekic * | [ Mbuf Keg ] 81099a0e58SBosko Milekic * [ Cluster Slabs ] | 82099a0e58SBosko Milekic * | [ Mbuf Slabs ] 83099a0e58SBosko Milekic * \____________(VM)_________________/ 8456a4e45aSAndre Oppermann * 8556a4e45aSAndre Oppermann * 86fcf90618SGleb Smirnoff * Whenever an object is allocated with uma_zalloc() out of 8756a4e45aSAndre Oppermann * one of the Zones its _ctor_ function is executed. The same 88fcf90618SGleb Smirnoff * for any deallocation through uma_zfree() the _dtor_ function 8956a4e45aSAndre Oppermann * is executed. 9056a4e45aSAndre Oppermann * 9156a4e45aSAndre Oppermann * Caches are per-CPU and are filled from the Master Zone. 9256a4e45aSAndre Oppermann * 93fcf90618SGleb Smirnoff * Whenever an object is allocated from the underlying global 9456a4e45aSAndre Oppermann * memory pool it gets pre-initialized with the _zinit_ functions. 9556a4e45aSAndre Oppermann * When the Keg's are overfull objects get decomissioned with 9656a4e45aSAndre Oppermann * _zfini_ functions and free'd back to the global memory pool. 9756a4e45aSAndre Oppermann * 98099a0e58SBosko Milekic */ 99099a0e58SBosko Milekic 100ead46972SAndre Oppermann int nmbufs; /* limits number of mbufs */ 10156a4e45aSAndre Oppermann int nmbclusters; /* limits number of mbuf clusters */ 102ec63cb90SAndre Oppermann int nmbjumbop; /* limits number of page size jumbo clusters */ 10356a4e45aSAndre Oppermann int nmbjumbo9; /* limits number of 9k jumbo clusters */ 10456a4e45aSAndre Oppermann int nmbjumbo16; /* limits number of 16k jumbo clusters */ 105099a0e58SBosko Milekic struct mbstat mbstat; 106099a0e58SBosko Milekic 107*e0c00addSAndre Oppermann static quad_t maxmbufmem; /* overall real memory limit for all mbufs */ 108*e0c00addSAndre Oppermann 109*e0c00addSAndre Oppermann SYSCTL_QUAD(_kern_ipc, OID_AUTO, maxmbufmem, CTLFLAG_RDTUN, &maxmbufmem, 0, 110*e0c00addSAndre Oppermann "Maximum real memory allocateable to various mbuf types"); 111*e0c00addSAndre Oppermann 11262938659SBjoern A. Zeeb /* 11337140716SAndre Oppermann * tunable_mbinit() has to be run before any mbuf allocations are done. 11462938659SBjoern A. Zeeb */ 115099a0e58SBosko Milekic static void 116099a0e58SBosko Milekic tunable_mbinit(void *dummy) 117099a0e58SBosko Milekic { 118*e0c00addSAndre Oppermann quad_t realmem; 11937140716SAndre Oppermann 12037140716SAndre Oppermann /* 12137140716SAndre Oppermann * The default limit for all mbuf related memory is 1/2 of all 12237140716SAndre Oppermann * available kernel memory (physical or kmem). 12337140716SAndre Oppermann * At most it can be 3/4 of available kernel memory. 12437140716SAndre Oppermann */ 12537140716SAndre Oppermann realmem = qmin((quad_t)physmem * PAGE_SIZE, 1262ebcc8acSAndre Oppermann vm_map_max(kmem_map) - vm_map_min(kmem_map)); 12737140716SAndre Oppermann maxmbufmem = realmem / 2; 128*e0c00addSAndre Oppermann TUNABLE_QUAD_FETCH("kern.ipc.maxmbufmem", &maxmbufmem); 12937140716SAndre Oppermann if (maxmbufmem > realmem / 4 * 3) 13037140716SAndre Oppermann maxmbufmem = realmem / 4 * 3; 131099a0e58SBosko Milekic 132812302c3SNavdeep Parhar TUNABLE_INT_FETCH("kern.ipc.nmbclusters", &nmbclusters); 133416a434cSAndre Oppermann if (nmbclusters == 0) 134416a434cSAndre Oppermann nmbclusters = maxmbufmem / MCLBYTES / 4; 135812302c3SNavdeep Parhar 136812302c3SNavdeep Parhar TUNABLE_INT_FETCH("kern.ipc.nmbjumbop", &nmbjumbop); 137812302c3SNavdeep Parhar if (nmbjumbop == 0) 138416a434cSAndre Oppermann nmbjumbop = maxmbufmem / MJUMPAGESIZE / 4; 139812302c3SNavdeep Parhar 140812302c3SNavdeep Parhar TUNABLE_INT_FETCH("kern.ipc.nmbjumbo9", &nmbjumbo9); 141812302c3SNavdeep Parhar if (nmbjumbo9 == 0) 142416a434cSAndre Oppermann nmbjumbo9 = maxmbufmem / MJUM9BYTES / 6; 143812302c3SNavdeep Parhar 144812302c3SNavdeep Parhar TUNABLE_INT_FETCH("kern.ipc.nmbjumbo16", &nmbjumbo16); 145812302c3SNavdeep Parhar if (nmbjumbo16 == 0) 146416a434cSAndre Oppermann nmbjumbo16 = maxmbufmem / MJUM16BYTES / 6; 147416a434cSAndre Oppermann 148416a434cSAndre Oppermann /* 149416a434cSAndre Oppermann * We need at least as many mbufs as we have clusters of 150416a434cSAndre Oppermann * the various types added together. 151416a434cSAndre Oppermann */ 152416a434cSAndre Oppermann TUNABLE_INT_FETCH("kern.ipc.nmbufs", &nmbufs); 153416a434cSAndre Oppermann if (nmbufs < nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) 154416a434cSAndre Oppermann nmbufs = lmax(maxmbufmem / MSIZE / 5, 155416a434cSAndre Oppermann nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16); 156099a0e58SBosko Milekic } 15737140716SAndre Oppermann SYSINIT(tunable_mbinit, SI_SUB_KMEM, SI_ORDER_MIDDLE, tunable_mbinit, NULL); 158099a0e58SBosko Milekic 1594f590175SPaul Saab static int 1604f590175SPaul Saab sysctl_nmbclusters(SYSCTL_HANDLER_ARGS) 1614f590175SPaul Saab { 1624f590175SPaul Saab int error, newnmbclusters; 1634f590175SPaul Saab 1644f590175SPaul Saab newnmbclusters = nmbclusters; 165041b706bSDavid Malone error = sysctl_handle_int(oidp, &newnmbclusters, 0, req); 1664f590175SPaul Saab if (error == 0 && req->newptr) { 167ead46972SAndre Oppermann if (newnmbclusters > nmbclusters && 168ead46972SAndre Oppermann nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) { 1694f590175SPaul Saab nmbclusters = newnmbclusters; 1704f590175SPaul Saab uma_zone_set_max(zone_clust, nmbclusters); 171ead46972SAndre Oppermann nmbclusters = uma_zone_get_max(zone_clust); 1724f590175SPaul Saab EVENTHANDLER_INVOKE(nmbclusters_change); 1734f590175SPaul Saab } else 1744f590175SPaul Saab error = EINVAL; 1754f590175SPaul Saab } 1764f590175SPaul Saab return (error); 1774f590175SPaul Saab } 1784f590175SPaul Saab SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbclusters, CTLTYPE_INT|CTLFLAG_RW, 1794f590175SPaul Saab &nmbclusters, 0, sysctl_nmbclusters, "IU", 180099a0e58SBosko Milekic "Maximum number of mbuf clusters allowed"); 181cf70a46bSRandall Stewart 182cf70a46bSRandall Stewart static int 183cf70a46bSRandall Stewart sysctl_nmbjumbop(SYSCTL_HANDLER_ARGS) 184cf70a46bSRandall Stewart { 185cf70a46bSRandall Stewart int error, newnmbjumbop; 186cf70a46bSRandall Stewart 187cf70a46bSRandall Stewart newnmbjumbop = nmbjumbop; 188cf70a46bSRandall Stewart error = sysctl_handle_int(oidp, &newnmbjumbop, 0, req); 189cf70a46bSRandall Stewart if (error == 0 && req->newptr) { 190ead46972SAndre Oppermann if (newnmbjumbop > nmbjumbop && 191ead46972SAndre Oppermann nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) { 192cf70a46bSRandall Stewart nmbjumbop = newnmbjumbop; 193cf70a46bSRandall Stewart uma_zone_set_max(zone_jumbop, nmbjumbop); 194ead46972SAndre Oppermann nmbjumbop = uma_zone_get_max(zone_jumbop); 195cf70a46bSRandall Stewart } else 196cf70a46bSRandall Stewart error = EINVAL; 197cf70a46bSRandall Stewart } 198cf70a46bSRandall Stewart return (error); 199cf70a46bSRandall Stewart } 200cf70a46bSRandall Stewart SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbjumbop, CTLTYPE_INT|CTLFLAG_RW, 201cf70a46bSRandall Stewart &nmbjumbop, 0, sysctl_nmbjumbop, "IU", 202ec63cb90SAndre Oppermann "Maximum number of mbuf page size jumbo clusters allowed"); 203cf70a46bSRandall Stewart 204cf70a46bSRandall Stewart static int 205cf70a46bSRandall Stewart sysctl_nmbjumbo9(SYSCTL_HANDLER_ARGS) 206cf70a46bSRandall Stewart { 207cf70a46bSRandall Stewart int error, newnmbjumbo9; 208cf70a46bSRandall Stewart 209cf70a46bSRandall Stewart newnmbjumbo9 = nmbjumbo9; 210cf70a46bSRandall Stewart error = sysctl_handle_int(oidp, &newnmbjumbo9, 0, req); 211cf70a46bSRandall Stewart if (error == 0 && req->newptr) { 212ead46972SAndre Oppermann if (newnmbjumbo9 > nmbjumbo9 && 213ead46972SAndre Oppermann nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) { 214cf70a46bSRandall Stewart nmbjumbo9 = newnmbjumbo9; 215cf70a46bSRandall Stewart uma_zone_set_max(zone_jumbo9, nmbjumbo9); 216ead46972SAndre Oppermann nmbjumbo9 = uma_zone_get_max(zone_jumbo9); 217cf70a46bSRandall Stewart } else 218cf70a46bSRandall Stewart error = EINVAL; 219cf70a46bSRandall Stewart } 220cf70a46bSRandall Stewart return (error); 221cf70a46bSRandall Stewart } 222cf70a46bSRandall Stewart SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbjumbo9, CTLTYPE_INT|CTLFLAG_RW, 223cf70a46bSRandall Stewart &nmbjumbo9, 0, sysctl_nmbjumbo9, "IU", 22456a4e45aSAndre Oppermann "Maximum number of mbuf 9k jumbo clusters allowed"); 225cf70a46bSRandall Stewart 226cf70a46bSRandall Stewart static int 227cf70a46bSRandall Stewart sysctl_nmbjumbo16(SYSCTL_HANDLER_ARGS) 228cf70a46bSRandall Stewart { 229cf70a46bSRandall Stewart int error, newnmbjumbo16; 230cf70a46bSRandall Stewart 231cf70a46bSRandall Stewart newnmbjumbo16 = nmbjumbo16; 232cf70a46bSRandall Stewart error = sysctl_handle_int(oidp, &newnmbjumbo16, 0, req); 233cf70a46bSRandall Stewart if (error == 0 && req->newptr) { 234ead46972SAndre Oppermann if (newnmbjumbo16 > nmbjumbo16 && 235ead46972SAndre Oppermann nmbufs >= nmbclusters + nmbjumbop + nmbjumbo9 + nmbjumbo16) { 236cf70a46bSRandall Stewart nmbjumbo16 = newnmbjumbo16; 237cf70a46bSRandall Stewart uma_zone_set_max(zone_jumbo16, nmbjumbo16); 238ead46972SAndre Oppermann nmbjumbo16 = uma_zone_get_max(zone_jumbo16); 239cf70a46bSRandall Stewart } else 240cf70a46bSRandall Stewart error = EINVAL; 241cf70a46bSRandall Stewart } 242cf70a46bSRandall Stewart return (error); 243cf70a46bSRandall Stewart } 244cf70a46bSRandall Stewart SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbjumbo16, CTLTYPE_INT|CTLFLAG_RW, 245cf70a46bSRandall Stewart &nmbjumbo16, 0, sysctl_nmbjumbo16, "IU", 24656a4e45aSAndre Oppermann "Maximum number of mbuf 16k jumbo clusters allowed"); 247cf70a46bSRandall Stewart 248ead46972SAndre Oppermann static int 249ead46972SAndre Oppermann sysctl_nmbufs(SYSCTL_HANDLER_ARGS) 250ead46972SAndre Oppermann { 251ead46972SAndre Oppermann int error, newnmbufs; 252ead46972SAndre Oppermann 253ead46972SAndre Oppermann newnmbufs = nmbufs; 254ead46972SAndre Oppermann error = sysctl_handle_int(oidp, &newnmbufs, 0, req); 255ead46972SAndre Oppermann if (error == 0 && req->newptr) { 256ead46972SAndre Oppermann if (newnmbufs > nmbufs) { 257ead46972SAndre Oppermann nmbufs = newnmbufs; 258ead46972SAndre Oppermann uma_zone_set_max(zone_mbuf, nmbufs); 259416a434cSAndre Oppermann nmbufs = uma_zone_get_max(zone_mbuf); 260ead46972SAndre Oppermann EVENTHANDLER_INVOKE(nmbufs_change); 261ead46972SAndre Oppermann } else 262ead46972SAndre Oppermann error = EINVAL; 263ead46972SAndre Oppermann } 264ead46972SAndre Oppermann return (error); 265ead46972SAndre Oppermann } 266*e0c00addSAndre Oppermann SYSCTL_PROC(_kern_ipc, OID_AUTO, nmbufs, CTLTYPE_INT|CTLFLAG_RW, 267ead46972SAndre Oppermann &nmbufs, 0, sysctl_nmbufs, "IU", 268ead46972SAndre Oppermann "Maximum number of mbufs allowed"); 269cf70a46bSRandall Stewart 270099a0e58SBosko Milekic SYSCTL_STRUCT(_kern_ipc, OID_AUTO, mbstat, CTLFLAG_RD, &mbstat, mbstat, 271099a0e58SBosko Milekic "Mbuf general information and statistics"); 272099a0e58SBosko Milekic 273099a0e58SBosko Milekic /* 274099a0e58SBosko Milekic * Zones from which we allocate. 275099a0e58SBosko Milekic */ 276099a0e58SBosko Milekic uma_zone_t zone_mbuf; 277099a0e58SBosko Milekic uma_zone_t zone_clust; 278099a0e58SBosko Milekic uma_zone_t zone_pack; 279ec63cb90SAndre Oppermann uma_zone_t zone_jumbop; 28056a4e45aSAndre Oppermann uma_zone_t zone_jumbo9; 28156a4e45aSAndre Oppermann uma_zone_t zone_jumbo16; 28256a4e45aSAndre Oppermann uma_zone_t zone_ext_refcnt; 283099a0e58SBosko Milekic 284099a0e58SBosko Milekic /* 285099a0e58SBosko Milekic * Local prototypes. 286099a0e58SBosko Milekic */ 287b23f72e9SBrian Feldman static int mb_ctor_mbuf(void *, int, void *, int); 288b23f72e9SBrian Feldman static int mb_ctor_clust(void *, int, void *, int); 289b23f72e9SBrian Feldman static int mb_ctor_pack(void *, int, void *, int); 290099a0e58SBosko Milekic static void mb_dtor_mbuf(void *, int, void *); 29156a4e45aSAndre Oppermann static void mb_dtor_clust(void *, int, void *); 29256a4e45aSAndre Oppermann static void mb_dtor_pack(void *, int, void *); 29356a4e45aSAndre Oppermann static int mb_zinit_pack(void *, int, int); 29456a4e45aSAndre Oppermann static void mb_zfini_pack(void *, int); 295099a0e58SBosko Milekic 296099a0e58SBosko Milekic static void mb_reclaim(void *); 29760ae52f7SEd Schouten static void *mbuf_jumbo_alloc(uma_zone_t, int, uint8_t *, int); 298099a0e58SBosko Milekic 29937140716SAndre Oppermann /* Ensure that MSIZE is a power of 2. */ 300a04946cfSBrian Somers CTASSERT((((MSIZE - 1) ^ MSIZE) + 1) >> 1 == MSIZE); 301a04946cfSBrian Somers 302099a0e58SBosko Milekic /* 303099a0e58SBosko Milekic * Initialize FreeBSD Network buffer allocation. 304099a0e58SBosko Milekic */ 305099a0e58SBosko Milekic static void 306099a0e58SBosko Milekic mbuf_init(void *dummy) 307099a0e58SBosko Milekic { 308099a0e58SBosko Milekic 309099a0e58SBosko Milekic /* 310099a0e58SBosko Milekic * Configure UMA zones for Mbufs, Clusters, and Packets. 311099a0e58SBosko Milekic */ 31256a4e45aSAndre Oppermann zone_mbuf = uma_zcreate(MBUF_MEM_NAME, MSIZE, 31356a4e45aSAndre Oppermann mb_ctor_mbuf, mb_dtor_mbuf, 314121f0509SMike Silbersack #ifdef INVARIANTS 31556a4e45aSAndre Oppermann trash_init, trash_fini, 316121f0509SMike Silbersack #else 31756a4e45aSAndre Oppermann NULL, NULL, 318121f0509SMike Silbersack #endif 31956a4e45aSAndre Oppermann MSIZE - 1, UMA_ZONE_MAXBUCKET); 32045fe0bf7SPawel Jakub Dawidek if (nmbufs > 0) 32145fe0bf7SPawel Jakub Dawidek nmbufs = uma_zone_set_max(zone_mbuf, nmbufs); 3226e0b6746SPawel Jakub Dawidek uma_zone_set_warning(zone_mbuf, "kern.ipc.nmbufs limit reached"); 32356a4e45aSAndre Oppermann 32468352adfSRobert Watson zone_clust = uma_zcreate(MBUF_CLUSTER_MEM_NAME, MCLBYTES, 32556a4e45aSAndre Oppermann mb_ctor_clust, mb_dtor_clust, 326121f0509SMike Silbersack #ifdef INVARIANTS 32756a4e45aSAndre Oppermann trash_init, trash_fini, 328121f0509SMike Silbersack #else 32956a4e45aSAndre Oppermann NULL, NULL, 330121f0509SMike Silbersack #endif 33156a4e45aSAndre Oppermann UMA_ALIGN_PTR, UMA_ZONE_REFCNT); 33245fe0bf7SPawel Jakub Dawidek if (nmbclusters > 0) 33345fe0bf7SPawel Jakub Dawidek nmbclusters = uma_zone_set_max(zone_clust, nmbclusters); 3346e0b6746SPawel Jakub Dawidek uma_zone_set_warning(zone_clust, "kern.ipc.nmbclusters limit reached"); 335099a0e58SBosko Milekic 33656a4e45aSAndre Oppermann zone_pack = uma_zsecond_create(MBUF_PACKET_MEM_NAME, mb_ctor_pack, 33756a4e45aSAndre Oppermann mb_dtor_pack, mb_zinit_pack, mb_zfini_pack, zone_mbuf); 33856a4e45aSAndre Oppermann 339fcf90618SGleb Smirnoff /* Make jumbo frame zone too. Page size, 9k and 16k. */ 340ec63cb90SAndre Oppermann zone_jumbop = uma_zcreate(MBUF_JUMBOP_MEM_NAME, MJUMPAGESIZE, 341d5269a63SAndre Oppermann mb_ctor_clust, mb_dtor_clust, 342d5269a63SAndre Oppermann #ifdef INVARIANTS 343d5269a63SAndre Oppermann trash_init, trash_fini, 344d5269a63SAndre Oppermann #else 345d5269a63SAndre Oppermann NULL, NULL, 346d5269a63SAndre Oppermann #endif 347d5269a63SAndre Oppermann UMA_ALIGN_PTR, UMA_ZONE_REFCNT); 34845fe0bf7SPawel Jakub Dawidek if (nmbjumbop > 0) 34945fe0bf7SPawel Jakub Dawidek nmbjumbop = uma_zone_set_max(zone_jumbop, nmbjumbop); 3506e0b6746SPawel Jakub Dawidek uma_zone_set_warning(zone_jumbop, "kern.ipc.nmbjumbop limit reached"); 351d5269a63SAndre Oppermann 35256a4e45aSAndre Oppermann zone_jumbo9 = uma_zcreate(MBUF_JUMBO9_MEM_NAME, MJUM9BYTES, 35356a4e45aSAndre Oppermann mb_ctor_clust, mb_dtor_clust, 35456a4e45aSAndre Oppermann #ifdef INVARIANTS 35556a4e45aSAndre Oppermann trash_init, trash_fini, 35656a4e45aSAndre Oppermann #else 35756a4e45aSAndre Oppermann NULL, NULL, 35856a4e45aSAndre Oppermann #endif 35956a4e45aSAndre Oppermann UMA_ALIGN_PTR, UMA_ZONE_REFCNT); 360ba63339aSAlan Cox uma_zone_set_allocf(zone_jumbo9, mbuf_jumbo_alloc); 36145fe0bf7SPawel Jakub Dawidek if (nmbjumbo9 > 0) 36245fe0bf7SPawel Jakub Dawidek nmbjumbo9 = uma_zone_set_max(zone_jumbo9, nmbjumbo9); 3636e0b6746SPawel Jakub Dawidek uma_zone_set_warning(zone_jumbo9, "kern.ipc.nmbjumbo9 limit reached"); 36456a4e45aSAndre Oppermann 36556a4e45aSAndre Oppermann zone_jumbo16 = uma_zcreate(MBUF_JUMBO16_MEM_NAME, MJUM16BYTES, 36656a4e45aSAndre Oppermann mb_ctor_clust, mb_dtor_clust, 36756a4e45aSAndre Oppermann #ifdef INVARIANTS 36856a4e45aSAndre Oppermann trash_init, trash_fini, 36956a4e45aSAndre Oppermann #else 37056a4e45aSAndre Oppermann NULL, NULL, 37156a4e45aSAndre Oppermann #endif 37256a4e45aSAndre Oppermann UMA_ALIGN_PTR, UMA_ZONE_REFCNT); 373ba63339aSAlan Cox uma_zone_set_allocf(zone_jumbo16, mbuf_jumbo_alloc); 37445fe0bf7SPawel Jakub Dawidek if (nmbjumbo16 > 0) 37545fe0bf7SPawel Jakub Dawidek nmbjumbo16 = uma_zone_set_max(zone_jumbo16, nmbjumbo16); 3766e0b6746SPawel Jakub Dawidek uma_zone_set_warning(zone_jumbo16, "kern.ipc.nmbjumbo16 limit reached"); 37756a4e45aSAndre Oppermann 37856a4e45aSAndre Oppermann zone_ext_refcnt = uma_zcreate(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), 37956a4e45aSAndre Oppermann NULL, NULL, 38056a4e45aSAndre Oppermann NULL, NULL, 38156a4e45aSAndre Oppermann UMA_ALIGN_PTR, UMA_ZONE_ZINIT); 38256a4e45aSAndre Oppermann 38356a4e45aSAndre Oppermann /* uma_prealloc() goes here... */ 384099a0e58SBosko Milekic 385099a0e58SBosko Milekic /* 386099a0e58SBosko Milekic * Hook event handler for low-memory situation, used to 387099a0e58SBosko Milekic * drain protocols and push data back to the caches (UMA 388099a0e58SBosko Milekic * later pushes it back to VM). 389099a0e58SBosko Milekic */ 390099a0e58SBosko Milekic EVENTHANDLER_REGISTER(vm_lowmem, mb_reclaim, NULL, 391099a0e58SBosko Milekic EVENTHANDLER_PRI_FIRST); 392099a0e58SBosko Milekic 393099a0e58SBosko Milekic /* 394099a0e58SBosko Milekic * [Re]set counters and local statistics knobs. 395099a0e58SBosko Milekic * XXX Some of these should go and be replaced, but UMA stat 396099a0e58SBosko Milekic * gathering needs to be revised. 397099a0e58SBosko Milekic */ 398099a0e58SBosko Milekic mbstat.m_mbufs = 0; 399099a0e58SBosko Milekic mbstat.m_mclusts = 0; 400099a0e58SBosko Milekic mbstat.m_drain = 0; 401099a0e58SBosko Milekic mbstat.m_msize = MSIZE; 402099a0e58SBosko Milekic mbstat.m_mclbytes = MCLBYTES; 403099a0e58SBosko Milekic mbstat.m_minclsize = MINCLSIZE; 404099a0e58SBosko Milekic mbstat.m_mlen = MLEN; 405099a0e58SBosko Milekic mbstat.m_mhlen = MHLEN; 406099a0e58SBosko Milekic mbstat.m_numtypes = MT_NTYPES; 407099a0e58SBosko Milekic 408099a0e58SBosko Milekic mbstat.m_mcfail = mbstat.m_mpfail = 0; 409099a0e58SBosko Milekic mbstat.sf_iocnt = 0; 410099a0e58SBosko Milekic mbstat.sf_allocwait = mbstat.sf_allocfail = 0; 411099a0e58SBosko Milekic } 41237140716SAndre Oppermann SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbuf_init, NULL); 413099a0e58SBosko Milekic 414099a0e58SBosko Milekic /* 415ba63339aSAlan Cox * UMA backend page allocator for the jumbo frame zones. 416ba63339aSAlan Cox * 417ba63339aSAlan Cox * Allocates kernel virtual memory that is backed by contiguous physical 418ba63339aSAlan Cox * pages. 419ba63339aSAlan Cox */ 420ba63339aSAlan Cox static void * 42160ae52f7SEd Schouten mbuf_jumbo_alloc(uma_zone_t zone, int bytes, uint8_t *flags, int wait) 422ba63339aSAlan Cox { 423ba63339aSAlan Cox 4247630c265SAlan Cox /* Inform UMA that this allocator uses kernel_map/object. */ 4257630c265SAlan Cox *flags = UMA_SLAB_KERNEL; 426c45c0034SAlan Cox return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, 4273153e878SAlan Cox (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_MEMATTR_DEFAULT)); 428ba63339aSAlan Cox } 429ba63339aSAlan Cox 430ba63339aSAlan Cox /* 431099a0e58SBosko Milekic * Constructor for Mbuf master zone. 432099a0e58SBosko Milekic * 433099a0e58SBosko Milekic * The 'arg' pointer points to a mb_args structure which 434099a0e58SBosko Milekic * contains call-specific information required to support the 43556a4e45aSAndre Oppermann * mbuf allocation API. See mbuf.h. 436099a0e58SBosko Milekic */ 437b23f72e9SBrian Feldman static int 438b23f72e9SBrian Feldman mb_ctor_mbuf(void *mem, int size, void *arg, int how) 439099a0e58SBosko Milekic { 440099a0e58SBosko Milekic struct mbuf *m; 441099a0e58SBosko Milekic struct mb_args *args; 442b23f72e9SBrian Feldman #ifdef MAC 443b23f72e9SBrian Feldman int error; 444b23f72e9SBrian Feldman #endif 445099a0e58SBosko Milekic int flags; 446099a0e58SBosko Milekic short type; 447099a0e58SBosko Milekic 448121f0509SMike Silbersack #ifdef INVARIANTS 449121f0509SMike Silbersack trash_ctor(mem, size, arg, how); 450121f0509SMike Silbersack #endif 451099a0e58SBosko Milekic m = (struct mbuf *)mem; 452099a0e58SBosko Milekic args = (struct mb_args *)arg; 453099a0e58SBosko Milekic flags = args->flags; 454099a0e58SBosko Milekic type = args->type; 455099a0e58SBosko Milekic 45656a4e45aSAndre Oppermann /* 45756a4e45aSAndre Oppermann * The mbuf is initialized later. The caller has the 458fcf90618SGleb Smirnoff * responsibility to set up any MAC labels too. 45956a4e45aSAndre Oppermann */ 46056a4e45aSAndre Oppermann if (type == MT_NOINIT) 46156a4e45aSAndre Oppermann return (0); 46256a4e45aSAndre Oppermann 463099a0e58SBosko Milekic m->m_next = NULL; 464099a0e58SBosko Milekic m->m_nextpkt = NULL; 46556a4e45aSAndre Oppermann m->m_len = 0; 4666bc72ab9SBosko Milekic m->m_flags = flags; 46756a4e45aSAndre Oppermann m->m_type = type; 468099a0e58SBosko Milekic if (flags & M_PKTHDR) { 469099a0e58SBosko Milekic m->m_data = m->m_pktdat; 470099a0e58SBosko Milekic m->m_pkthdr.rcvif = NULL; 47156a4e45aSAndre Oppermann m->m_pkthdr.header = NULL; 4728aa7a581SKip Macy m->m_pkthdr.len = 0; 473099a0e58SBosko Milekic m->m_pkthdr.csum_flags = 0; 47456a4e45aSAndre Oppermann m->m_pkthdr.csum_data = 0; 475a855e2b4SAndre Oppermann m->m_pkthdr.tso_segsz = 0; 476a855e2b4SAndre Oppermann m->m_pkthdr.ether_vtag = 0; 477877e8812SRobert Watson m->m_pkthdr.flowid = 0; 4784591f0d3SJulian Elischer m->m_pkthdr.fibnum = 0; 479099a0e58SBosko Milekic SLIST_INIT(&m->m_pkthdr.tags); 480099a0e58SBosko Milekic #ifdef MAC 481099a0e58SBosko Milekic /* If the label init fails, fail the alloc */ 48230d239bcSRobert Watson error = mac_mbuf_init(m, how); 483b23f72e9SBrian Feldman if (error) 484b23f72e9SBrian Feldman return (error); 485099a0e58SBosko Milekic #endif 4866bc72ab9SBosko Milekic } else 487099a0e58SBosko Milekic m->m_data = m->m_dat; 488b23f72e9SBrian Feldman return (0); 489099a0e58SBosko Milekic } 490099a0e58SBosko Milekic 491099a0e58SBosko Milekic /* 49256a4e45aSAndre Oppermann * The Mbuf master zone destructor. 493099a0e58SBosko Milekic */ 494099a0e58SBosko Milekic static void 495099a0e58SBosko Milekic mb_dtor_mbuf(void *mem, int size, void *arg) 496099a0e58SBosko Milekic { 497099a0e58SBosko Milekic struct mbuf *m; 498629b9e08SKip Macy unsigned long flags; 499099a0e58SBosko Milekic 500099a0e58SBosko Milekic m = (struct mbuf *)mem; 501629b9e08SKip Macy flags = (unsigned long)arg; 502629b9e08SKip Macy 503629b9e08SKip Macy if ((flags & MB_NOTAGS) == 0 && (m->m_flags & M_PKTHDR) != 0) 504099a0e58SBosko Milekic m_tag_delete_chain(m, NULL); 50556a4e45aSAndre Oppermann KASSERT((m->m_flags & M_EXT) == 0, ("%s: M_EXT set", __func__)); 506457869b9SKip Macy KASSERT((m->m_flags & M_NOFREE) == 0, ("%s: M_NOFREE set", __func__)); 507121f0509SMike Silbersack #ifdef INVARIANTS 508121f0509SMike Silbersack trash_dtor(mem, size, arg); 509121f0509SMike Silbersack #endif 510099a0e58SBosko Milekic } 511099a0e58SBosko Milekic 51256a4e45aSAndre Oppermann /* 51356a4e45aSAndre Oppermann * The Mbuf Packet zone destructor. 51456a4e45aSAndre Oppermann */ 515099a0e58SBosko Milekic static void 516099a0e58SBosko Milekic mb_dtor_pack(void *mem, int size, void *arg) 517099a0e58SBosko Milekic { 518099a0e58SBosko Milekic struct mbuf *m; 519099a0e58SBosko Milekic 520099a0e58SBosko Milekic m = (struct mbuf *)mem; 521099a0e58SBosko Milekic if ((m->m_flags & M_PKTHDR) != 0) 522099a0e58SBosko Milekic m_tag_delete_chain(m, NULL); 52356a4e45aSAndre Oppermann 52456a4e45aSAndre Oppermann /* Make sure we've got a clean cluster back. */ 52556a4e45aSAndre Oppermann KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__)); 52656a4e45aSAndre Oppermann KASSERT(m->m_ext.ext_buf != NULL, ("%s: ext_buf == NULL", __func__)); 52756a4e45aSAndre Oppermann KASSERT(m->m_ext.ext_free == NULL, ("%s: ext_free != NULL", __func__)); 528cf827063SPoul-Henning Kamp KASSERT(m->m_ext.ext_arg1 == NULL, ("%s: ext_arg1 != NULL", __func__)); 529cf827063SPoul-Henning Kamp KASSERT(m->m_ext.ext_arg2 == NULL, ("%s: ext_arg2 != NULL", __func__)); 53056a4e45aSAndre Oppermann KASSERT(m->m_ext.ext_size == MCLBYTES, ("%s: ext_size != MCLBYTES", __func__)); 53149d46b61SGleb Smirnoff KASSERT(m->m_ext.ext_type == EXT_PACKET, ("%s: ext_type != EXT_PACKET", __func__)); 53256a4e45aSAndre Oppermann KASSERT(*m->m_ext.ref_cnt == 1, ("%s: ref_cnt != 1", __func__)); 533121f0509SMike Silbersack #ifdef INVARIANTS 534121f0509SMike Silbersack trash_dtor(m->m_ext.ext_buf, MCLBYTES, arg); 535121f0509SMike Silbersack #endif 5366c125b8dSMohan Srinivasan /* 537ef44c8d2SDavid E. O'Brien * If there are processes blocked on zone_clust, waiting for pages 538ef44c8d2SDavid E. O'Brien * to be freed up, * cause them to be woken up by draining the 539ef44c8d2SDavid E. O'Brien * packet zone. We are exposed to a race here * (in the check for 540ef44c8d2SDavid E. O'Brien * the UMA_ZFLAG_FULL) where we might miss the flag set, but that 541ef44c8d2SDavid E. O'Brien * is deliberate. We don't want to acquire the zone lock for every 542ef44c8d2SDavid E. O'Brien * mbuf free. 5436c125b8dSMohan Srinivasan */ 5446c125b8dSMohan Srinivasan if (uma_zone_exhausted_nolock(zone_clust)) 5456c125b8dSMohan Srinivasan zone_drain(zone_pack); 546099a0e58SBosko Milekic } 547099a0e58SBosko Milekic 548099a0e58SBosko Milekic /* 549ec63cb90SAndre Oppermann * The Cluster and Jumbo[PAGESIZE|9|16] zone constructor. 550099a0e58SBosko Milekic * 551099a0e58SBosko Milekic * Here the 'arg' pointer points to the Mbuf which we 55256a4e45aSAndre Oppermann * are configuring cluster storage for. If 'arg' is 55356a4e45aSAndre Oppermann * empty we allocate just the cluster without setting 55456a4e45aSAndre Oppermann * the mbuf to it. See mbuf.h. 555099a0e58SBosko Milekic */ 556b23f72e9SBrian Feldman static int 557b23f72e9SBrian Feldman mb_ctor_clust(void *mem, int size, void *arg, int how) 558099a0e58SBosko Milekic { 559099a0e58SBosko Milekic struct mbuf *m; 56056a4e45aSAndre Oppermann u_int *refcnt; 5610f4d9d04SKip Macy int type; 5620f4d9d04SKip Macy uma_zone_t zone; 563099a0e58SBosko Milekic 564121f0509SMike Silbersack #ifdef INVARIANTS 565121f0509SMike Silbersack trash_ctor(mem, size, arg, how); 566121f0509SMike Silbersack #endif 56756a4e45aSAndre Oppermann switch (size) { 56856a4e45aSAndre Oppermann case MCLBYTES: 56956a4e45aSAndre Oppermann type = EXT_CLUSTER; 5700f4d9d04SKip Macy zone = zone_clust; 57156a4e45aSAndre Oppermann break; 572ec63cb90SAndre Oppermann #if MJUMPAGESIZE != MCLBYTES 573ec63cb90SAndre Oppermann case MJUMPAGESIZE: 574ec63cb90SAndre Oppermann type = EXT_JUMBOP; 5750f4d9d04SKip Macy zone = zone_jumbop; 576d5269a63SAndre Oppermann break; 57736ae3fd3SAndre Oppermann #endif 57856a4e45aSAndre Oppermann case MJUM9BYTES: 57956a4e45aSAndre Oppermann type = EXT_JUMBO9; 5800f4d9d04SKip Macy zone = zone_jumbo9; 58156a4e45aSAndre Oppermann break; 58256a4e45aSAndre Oppermann case MJUM16BYTES: 58356a4e45aSAndre Oppermann type = EXT_JUMBO16; 5840f4d9d04SKip Macy zone = zone_jumbo16; 58556a4e45aSAndre Oppermann break; 58656a4e45aSAndre Oppermann default: 58756a4e45aSAndre Oppermann panic("unknown cluster size"); 58856a4e45aSAndre Oppermann break; 58956a4e45aSAndre Oppermann } 5900f4d9d04SKip Macy 5910f4d9d04SKip Macy m = (struct mbuf *)arg; 5920f4d9d04SKip Macy refcnt = uma_find_refcnt(zone, mem); 5930f4d9d04SKip Macy *refcnt = 1; 5940f4d9d04SKip Macy if (m != NULL) { 595099a0e58SBosko Milekic m->m_ext.ext_buf = (caddr_t)mem; 596099a0e58SBosko Milekic m->m_data = m->m_ext.ext_buf; 597099a0e58SBosko Milekic m->m_flags |= M_EXT; 598099a0e58SBosko Milekic m->m_ext.ext_free = NULL; 599cf827063SPoul-Henning Kamp m->m_ext.ext_arg1 = NULL; 600cf827063SPoul-Henning Kamp m->m_ext.ext_arg2 = NULL; 60156a4e45aSAndre Oppermann m->m_ext.ext_size = size; 60256a4e45aSAndre Oppermann m->m_ext.ext_type = type; 6030f4d9d04SKip Macy m->m_ext.ref_cnt = refcnt; 60456a4e45aSAndre Oppermann } 6050f4d9d04SKip Macy 606b23f72e9SBrian Feldman return (0); 607099a0e58SBosko Milekic } 608099a0e58SBosko Milekic 60956a4e45aSAndre Oppermann /* 61056a4e45aSAndre Oppermann * The Mbuf Cluster zone destructor. 61156a4e45aSAndre Oppermann */ 612099a0e58SBosko Milekic static void 613099a0e58SBosko Milekic mb_dtor_clust(void *mem, int size, void *arg) 614099a0e58SBosko Milekic { 615121f0509SMike Silbersack #ifdef INVARIANTS 6160f4d9d04SKip Macy uma_zone_t zone; 6170f4d9d04SKip Macy 6180f4d9d04SKip Macy zone = m_getzone(size); 6190f4d9d04SKip Macy KASSERT(*(uma_find_refcnt(zone, mem)) <= 1, 6200f4d9d04SKip Macy ("%s: refcnt incorrect %u", __func__, 6210f4d9d04SKip Macy *(uma_find_refcnt(zone, mem))) ); 6220f4d9d04SKip Macy 623121f0509SMike Silbersack trash_dtor(mem, size, arg); 624121f0509SMike Silbersack #endif 625099a0e58SBosko Milekic } 626099a0e58SBosko Milekic 627099a0e58SBosko Milekic /* 628099a0e58SBosko Milekic * The Packet secondary zone's init routine, executed on the 62956a4e45aSAndre Oppermann * object's transition from mbuf keg slab to zone cache. 630099a0e58SBosko Milekic */ 631b23f72e9SBrian Feldman static int 63256a4e45aSAndre Oppermann mb_zinit_pack(void *mem, int size, int how) 633099a0e58SBosko Milekic { 634099a0e58SBosko Milekic struct mbuf *m; 635099a0e58SBosko Milekic 63656a4e45aSAndre Oppermann m = (struct mbuf *)mem; /* m is virgin. */ 637a7bd90efSAndre Oppermann if (uma_zalloc_arg(zone_clust, m, how) == NULL || 638a7bd90efSAndre Oppermann m->m_ext.ext_buf == NULL) 639b23f72e9SBrian Feldman return (ENOMEM); 640cd5bb63bSAndre Oppermann m->m_ext.ext_type = EXT_PACKET; /* Override. */ 641121f0509SMike Silbersack #ifdef INVARIANTS 642121f0509SMike Silbersack trash_init(m->m_ext.ext_buf, MCLBYTES, how); 643121f0509SMike Silbersack #endif 644b23f72e9SBrian Feldman return (0); 645099a0e58SBosko Milekic } 646099a0e58SBosko Milekic 647099a0e58SBosko Milekic /* 648099a0e58SBosko Milekic * The Packet secondary zone's fini routine, executed on the 649099a0e58SBosko Milekic * object's transition from zone cache to keg slab. 650099a0e58SBosko Milekic */ 651099a0e58SBosko Milekic static void 65256a4e45aSAndre Oppermann mb_zfini_pack(void *mem, int size) 653099a0e58SBosko Milekic { 654099a0e58SBosko Milekic struct mbuf *m; 655099a0e58SBosko Milekic 656099a0e58SBosko Milekic m = (struct mbuf *)mem; 657121f0509SMike Silbersack #ifdef INVARIANTS 658121f0509SMike Silbersack trash_fini(m->m_ext.ext_buf, MCLBYTES); 659121f0509SMike Silbersack #endif 660099a0e58SBosko Milekic uma_zfree_arg(zone_clust, m->m_ext.ext_buf, NULL); 661a7b844d2SMike Silbersack #ifdef INVARIANTS 662a7b844d2SMike Silbersack trash_dtor(mem, size, NULL); 663a7b844d2SMike Silbersack #endif 664099a0e58SBosko Milekic } 665099a0e58SBosko Milekic 666099a0e58SBosko Milekic /* 667099a0e58SBosko Milekic * The "packet" keg constructor. 668099a0e58SBosko Milekic */ 669b23f72e9SBrian Feldman static int 670b23f72e9SBrian Feldman mb_ctor_pack(void *mem, int size, void *arg, int how) 671099a0e58SBosko Milekic { 672099a0e58SBosko Milekic struct mbuf *m; 673099a0e58SBosko Milekic struct mb_args *args; 674b23f72e9SBrian Feldman #ifdef MAC 675b23f72e9SBrian Feldman int error; 676b23f72e9SBrian Feldman #endif 677b23f72e9SBrian Feldman int flags; 678099a0e58SBosko Milekic short type; 679099a0e58SBosko Milekic 680099a0e58SBosko Milekic m = (struct mbuf *)mem; 681099a0e58SBosko Milekic args = (struct mb_args *)arg; 682099a0e58SBosko Milekic flags = args->flags; 683099a0e58SBosko Milekic type = args->type; 684099a0e58SBosko Milekic 685121f0509SMike Silbersack #ifdef INVARIANTS 686121f0509SMike Silbersack trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how); 687121f0509SMike Silbersack #endif 688099a0e58SBosko Milekic m->m_next = NULL; 6896bc72ab9SBosko Milekic m->m_nextpkt = NULL; 690099a0e58SBosko Milekic m->m_data = m->m_ext.ext_buf; 69156a4e45aSAndre Oppermann m->m_len = 0; 69256a4e45aSAndre Oppermann m->m_flags = (flags | M_EXT); 69356a4e45aSAndre Oppermann m->m_type = type; 694099a0e58SBosko Milekic 695099a0e58SBosko Milekic if (flags & M_PKTHDR) { 696099a0e58SBosko Milekic m->m_pkthdr.rcvif = NULL; 69756a4e45aSAndre Oppermann m->m_pkthdr.len = 0; 69856a4e45aSAndre Oppermann m->m_pkthdr.header = NULL; 699099a0e58SBosko Milekic m->m_pkthdr.csum_flags = 0; 70056a4e45aSAndre Oppermann m->m_pkthdr.csum_data = 0; 701a855e2b4SAndre Oppermann m->m_pkthdr.tso_segsz = 0; 702a855e2b4SAndre Oppermann m->m_pkthdr.ether_vtag = 0; 703877e8812SRobert Watson m->m_pkthdr.flowid = 0; 7044591f0d3SJulian Elischer m->m_pkthdr.fibnum = 0; 705099a0e58SBosko Milekic SLIST_INIT(&m->m_pkthdr.tags); 706099a0e58SBosko Milekic #ifdef MAC 707099a0e58SBosko Milekic /* If the label init fails, fail the alloc */ 70830d239bcSRobert Watson error = mac_mbuf_init(m, how); 709b23f72e9SBrian Feldman if (error) 710b23f72e9SBrian Feldman return (error); 711099a0e58SBosko Milekic #endif 712099a0e58SBosko Milekic } 71356a4e45aSAndre Oppermann /* m_ext is already initialized. */ 71456a4e45aSAndre Oppermann 715b23f72e9SBrian Feldman return (0); 716099a0e58SBosko Milekic } 717099a0e58SBosko Milekic 7185b204a11SKip Macy int 7195b204a11SKip Macy m_pkthdr_init(struct mbuf *m, int how) 7205b204a11SKip Macy { 7215b204a11SKip Macy #ifdef MAC 7225b204a11SKip Macy int error; 7235b204a11SKip Macy #endif 7245b204a11SKip Macy m->m_data = m->m_pktdat; 7255b204a11SKip Macy SLIST_INIT(&m->m_pkthdr.tags); 7265b204a11SKip Macy m->m_pkthdr.rcvif = NULL; 7275b204a11SKip Macy m->m_pkthdr.header = NULL; 7285b204a11SKip Macy m->m_pkthdr.len = 0; 7295b204a11SKip Macy m->m_pkthdr.flowid = 0; 7304591f0d3SJulian Elischer m->m_pkthdr.fibnum = 0; 7315b204a11SKip Macy m->m_pkthdr.csum_flags = 0; 7325b204a11SKip Macy m->m_pkthdr.csum_data = 0; 7335b204a11SKip Macy m->m_pkthdr.tso_segsz = 0; 7345b204a11SKip Macy m->m_pkthdr.ether_vtag = 0; 7355b204a11SKip Macy #ifdef MAC 7365b204a11SKip Macy /* If the label init fails, fail the alloc */ 7375b204a11SKip Macy error = mac_mbuf_init(m, how); 7385b204a11SKip Macy if (error) 7395b204a11SKip Macy return (error); 7405b204a11SKip Macy #endif 7415b204a11SKip Macy 7425b204a11SKip Macy return (0); 7435b204a11SKip Macy } 7445b204a11SKip Macy 745099a0e58SBosko Milekic /* 746099a0e58SBosko Milekic * This is the protocol drain routine. 747099a0e58SBosko Milekic * 748099a0e58SBosko Milekic * No locks should be held when this is called. The drain routines have to 749099a0e58SBosko Milekic * presently acquire some locks which raises the possibility of lock order 750099a0e58SBosko Milekic * reversal. 751099a0e58SBosko Milekic */ 752099a0e58SBosko Milekic static void 753099a0e58SBosko Milekic mb_reclaim(void *junk) 754099a0e58SBosko Milekic { 755099a0e58SBosko Milekic struct domain *dp; 756099a0e58SBosko Milekic struct protosw *pr; 757099a0e58SBosko Milekic 758099a0e58SBosko Milekic WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL, 759099a0e58SBosko Milekic "mb_reclaim()"); 760099a0e58SBosko Milekic 761099a0e58SBosko Milekic for (dp = domains; dp != NULL; dp = dp->dom_next) 762099a0e58SBosko Milekic for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) 763099a0e58SBosko Milekic if (pr->pr_drain != NULL) 764099a0e58SBosko Milekic (*pr->pr_drain)(); 765099a0e58SBosko Milekic } 766