1829d1a776d2fc5124c1701da541079d0e17da6b3tuexen/*- 2829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Copyright (c) 1982, 1986, 1988, 1993 3829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * The Regents of the University of California. 4829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * All rights reserved. 5829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 6829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * Redistribution and use in source and binary forms, with or without 7829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * modification, are permitted provided that the following conditions 8829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * are met: 9829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 1. Redistributions of source code must retain the above copyright 10829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * notice, this list of conditions and the following disclaimer. 11829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 2. Redistributions in binary form must reproduce the above copyright 12829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * notice, this list of conditions and the following disclaimer in the 13829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * documentation and/or other materials provided with the distribution. 14829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 3. Neither the name of the University nor the names of its contributors 15829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * may be used to endorse or promote products derived from this software 16829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * without specific prior written permission. 17829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 18829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * SUCH DAMAGE. 29829d1a776d2fc5124c1701da541079d0e17da6b3tuexen * 30829d1a776d2fc5124c1701da541079d0e17da6b3tuexen */ 31829d1a776d2fc5124c1701da541079d0e17da6b3tuexen 32bca1dae6587a640359abee04337c0463b0a3893tuexen/* 33bca1dae6587a640359abee04337c0463b0a3893tuexen * __Userspace__ version of /usr/src/sys/kern/kern_mbuf.c 34bca1dae6587a640359abee04337c0463b0a3893tuexen * We are initializing two zones for Mbufs and Clusters. 3542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * 36bca1dae6587a640359abee04337c0463b0a3893tuexen */ 37bca1dae6587a640359abee04337c0463b0a3893tuexen 38bca1dae6587a640359abee04337c0463b0a3893tuexen#include <stdio.h> 39bca1dae6587a640359abee04337c0463b0a3893tuexen#include <string.h> 40bca1dae6587a640359abee04337c0463b0a3893tuexen/* #include <sys/param.h> This defines MSIZE 256 */ 41bca1dae6587a640359abee04337c0463b0a3893tuexen#if !defined(SCTP_SIMPLE_ALLOCATOR) 42bca1dae6587a640359abee04337c0463b0a3893tuexen#include "umem.h" 43bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 44bca1dae6587a640359abee04337c0463b0a3893tuexen#include "user_mbuf.h" 45bca1dae6587a640359abee04337c0463b0a3893tuexen#include "user_environment.h" 46bca1dae6587a640359abee04337c0463b0a3893tuexen#include "user_atomic.h" 47a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen#include "netinet/sctp_pcb.h" 48bca1dae6587a640359abee04337c0463b0a3893tuexen 49bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbstat mbstat; 50bca1dae6587a640359abee04337c0463b0a3893tuexen#define KIPC_MAX_LINKHDR 4 /* int: max length of link header (see sys/sysclt.h) */ 51c7108437de5af4d0b9f9a24979710b39197ec6cetuexen#define KIPC_MAX_PROTOHDR 5 /* int: max length of network header (see sys/sysclt.h)*/ 52c7108437de5af4d0b9f9a24979710b39197ec6cetuexenint max_linkhdr = KIPC_MAX_LINKHDR; 53c7108437de5af4d0b9f9a24979710b39197ec6cetuexenint max_protohdr = KIPC_MAX_PROTOHDR; /* Size of largest protocol layer header. */ 54bca1dae6587a640359abee04337c0463b0a3893tuexen 55bca1dae6587a640359abee04337c0463b0a3893tuexen/* 56bca1dae6587a640359abee04337c0463b0a3893tuexen * Zones from which we allocate. 57bca1dae6587a640359abee04337c0463b0a3893tuexen */ 58bca1dae6587a640359abee04337c0463b0a3893tuexensctp_zone_t zone_mbuf; 59bca1dae6587a640359abee04337c0463b0a3893tuexensctp_zone_t zone_clust; 60bca1dae6587a640359abee04337c0463b0a3893tuexensctp_zone_t zone_ext_refcnt; 61bca1dae6587a640359abee04337c0463b0a3893tuexen 6242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen/* __Userspace__ clust_mb_args will be passed as callback data to mb_ctor_clust 63bca1dae6587a640359abee04337c0463b0a3893tuexen * and mb_dtor_clust. 64bca1dae6587a640359abee04337c0463b0a3893tuexen * Note: I had to use struct clust_args as an encapsulation for an mbuf pointer. 65bca1dae6587a640359abee04337c0463b0a3893tuexen * struct mbuf * clust_mb_args; does not work. 66bca1dae6587a640359abee04337c0463b0a3893tuexen */ 67bca1dae6587a640359abee04337c0463b0a3893tuexenstruct clust_args clust_mb_args; 68bca1dae6587a640359abee04337c0463b0a3893tuexen 69bca1dae6587a640359abee04337c0463b0a3893tuexen 70bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ 71bca1dae6587a640359abee04337c0463b0a3893tuexen * Local prototypes. 72bca1dae6587a640359abee04337c0463b0a3893tuexen */ 73bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int mb_ctor_mbuf(void *, void *, int); 74bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int mb_ctor_clust(void *, void *, int); 75bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void mb_dtor_mbuf(void *, void *); 76bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void mb_dtor_clust(void *, void *); 77bca1dae6587a640359abee04337c0463b0a3893tuexen 78bca1dae6587a640359abee04337c0463b0a3893tuexen 79bca1dae6587a640359abee04337c0463b0a3893tuexen/***************** Functions taken from user_mbuf.h *************/ 80bca1dae6587a640359abee04337c0463b0a3893tuexen 81bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int mbuf_constructor_dup(struct mbuf *m, int pkthdr, short type) 82bca1dae6587a640359abee04337c0463b0a3893tuexen{ 83bca1dae6587a640359abee04337c0463b0a3893tuexen int flags = pkthdr; 84bca1dae6587a640359abee04337c0463b0a3893tuexen if (type == MT_NOINIT) 85bca1dae6587a640359abee04337c0463b0a3893tuexen return (0); 8642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 87bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = NULL; 88bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_nextpkt = NULL; 89bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len = 0; 90bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_flags = flags; 91bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_type = type; 92bca1dae6587a640359abee04337c0463b0a3893tuexen if (flags & M_PKTHDR) { 93bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_data = m->m_pktdat; 94bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.rcvif = NULL; 95bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.len = 0; 96bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.header = NULL; 97bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.csum_flags = 0; 98bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.csum_data = 0; 99bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.tso_segsz = 0; 100bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.ether_vtag = 0; 101bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_INIT(&m->m_pkthdr.tags); 102bca1dae6587a640359abee04337c0463b0a3893tuexen } else 103bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_data = m->m_dat; 10442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 105bca1dae6587a640359abee04337c0463b0a3893tuexen return (0); 106bca1dae6587a640359abee04337c0463b0a3893tuexen} 107bca1dae6587a640359abee04337c0463b0a3893tuexen 108bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */ 109bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf * 110bca1dae6587a640359abee04337c0463b0a3893tuexenm_get(int how, short type) 111bca1dae6587a640359abee04337c0463b0a3893tuexen{ 112bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *mret; 1139b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR) 1149b332c241dd6df73b563594af7c334e23f5e42b8t struct mb_args mbuf_mb_args; 1159b332c241dd6df73b563594af7c334e23f5e42b8t 116bca1dae6587a640359abee04337c0463b0a3893tuexen /* The following setter function is not yet being enclosed within 117bca1dae6587a640359abee04337c0463b0a3893tuexen * #if USING_MBUF_CONSTRUCTOR - #endif, until I have thoroughly tested 118bca1dae6587a640359abee04337c0463b0a3893tuexen * mb_dtor_mbuf. See comment there 119bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1209b332c241dd6df73b563594af7c334e23f5e42b8t mbuf_mb_args.flags = 0; 1219b332c241dd6df73b563594af7c334e23f5e42b8t mbuf_mb_args.type = type; 1229b332c241dd6df73b563594af7c334e23f5e42b8t#endif 12342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen /* Mbuf master zone, zone_mbuf, has already been 124bca1dae6587a640359abee04337c0463b0a3893tuexen * created in mbuf_init() */ 125bca1dae6587a640359abee04337c0463b0a3893tuexen mret = SCTP_ZONE_GET(zone_mbuf, struct mbuf); 126bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 127bca1dae6587a640359abee04337c0463b0a3893tuexen mb_ctor_mbuf(mret, &mbuf_mb_args, 0); 128bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 129bca1dae6587a640359abee04337c0463b0a3893tuexen /*mret = ((struct mbuf *)umem_cache_alloc(zone_mbuf, UMEM_DEFAULT));*/ 13042d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 131bca1dae6587a640359abee04337c0463b0a3893tuexen /* There are cases when an object available in the current CPU's 132bca1dae6587a640359abee04337c0463b0a3893tuexen * loaded magazine and in those cases the object's constructor is not applied. 133bca1dae6587a640359abee04337c0463b0a3893tuexen * If that is the case, then we are duplicating constructor initialization here, 134bca1dae6587a640359abee04337c0463b0a3893tuexen * so that the mbuf is properly constructed before returning it. 135bca1dae6587a640359abee04337c0463b0a3893tuexen */ 136bca1dae6587a640359abee04337c0463b0a3893tuexen if (mret) { 137bca1dae6587a640359abee04337c0463b0a3893tuexen#if USING_MBUF_CONSTRUCTOR 138bca1dae6587a640359abee04337c0463b0a3893tuexen if (! (mret->m_type == type) ) { 139bca1dae6587a640359abee04337c0463b0a3893tuexen mbuf_constructor_dup(mret, 0, type); 140bca1dae6587a640359abee04337c0463b0a3893tuexen } 14142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen#else 142bca1dae6587a640359abee04337c0463b0a3893tuexen mbuf_constructor_dup(mret, 0, type); 143bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 14442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 145bca1dae6587a640359abee04337c0463b0a3893tuexen } 146bca1dae6587a640359abee04337c0463b0a3893tuexen return mret; 147bca1dae6587a640359abee04337c0463b0a3893tuexen} 148bca1dae6587a640359abee04337c0463b0a3893tuexen 149bca1dae6587a640359abee04337c0463b0a3893tuexen 150bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */ 151bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf * 152bca1dae6587a640359abee04337c0463b0a3893tuexenm_gethdr(int how, short type) 153bca1dae6587a640359abee04337c0463b0a3893tuexen{ 154bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *mret; 1559b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR) 1569b332c241dd6df73b563594af7c334e23f5e42b8t struct mb_args mbuf_mb_args; 1579b332c241dd6df73b563594af7c334e23f5e42b8t 158bca1dae6587a640359abee04337c0463b0a3893tuexen /* The following setter function is not yet being enclosed within 159bca1dae6587a640359abee04337c0463b0a3893tuexen * #if USING_MBUF_CONSTRUCTOR - #endif, until I have thoroughly tested 160bca1dae6587a640359abee04337c0463b0a3893tuexen * mb_dtor_mbuf. See comment there 161bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1629b332c241dd6df73b563594af7c334e23f5e42b8t mbuf_mb_args.flags = M_PKTHDR; 1639b332c241dd6df73b563594af7c334e23f5e42b8t mbuf_mb_args.type = type; 1649b332c241dd6df73b563594af7c334e23f5e42b8t#endif 165bca1dae6587a640359abee04337c0463b0a3893tuexen mret = SCTP_ZONE_GET(zone_mbuf, struct mbuf); 166bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 167bca1dae6587a640359abee04337c0463b0a3893tuexen mb_ctor_mbuf(mret, &mbuf_mb_args, 0); 168bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 169bca1dae6587a640359abee04337c0463b0a3893tuexen /*mret = ((struct mbuf *)umem_cache_alloc(zone_mbuf, UMEM_DEFAULT));*/ 170bca1dae6587a640359abee04337c0463b0a3893tuexen /* There are cases when an object available in the current CPU's 171bca1dae6587a640359abee04337c0463b0a3893tuexen * loaded magazine and in those cases the object's constructor is not applied. 172bca1dae6587a640359abee04337c0463b0a3893tuexen * If that is the case, then we are duplicating constructor initialization here, 173bca1dae6587a640359abee04337c0463b0a3893tuexen * so that the mbuf is properly constructed before returning it. 174bca1dae6587a640359abee04337c0463b0a3893tuexen */ 175bca1dae6587a640359abee04337c0463b0a3893tuexen if (mret) { 176bca1dae6587a640359abee04337c0463b0a3893tuexen#if USING_MBUF_CONSTRUCTOR 177bca1dae6587a640359abee04337c0463b0a3893tuexen if (! ((mret->m_flags & M_PKTHDR) && (mret->m_type == type)) ) { 178bca1dae6587a640359abee04337c0463b0a3893tuexen mbuf_constructor_dup(mret, M_PKTHDR, type); 179bca1dae6587a640359abee04337c0463b0a3893tuexen } 180bca1dae6587a640359abee04337c0463b0a3893tuexen#else 181bca1dae6587a640359abee04337c0463b0a3893tuexen mbuf_constructor_dup(mret, M_PKTHDR, type); 182bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 183bca1dae6587a640359abee04337c0463b0a3893tuexen } 184bca1dae6587a640359abee04337c0463b0a3893tuexen return mret; 185bca1dae6587a640359abee04337c0463b0a3893tuexen} 186bca1dae6587a640359abee04337c0463b0a3893tuexen 187bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */ 188bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf * 189bca1dae6587a640359abee04337c0463b0a3893tuexenm_free(struct mbuf *m) 190bca1dae6587a640359abee04337c0463b0a3893tuexen{ 19142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 192bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *n = m->m_next; 19342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 194bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_EXT) 195bca1dae6587a640359abee04337c0463b0a3893tuexen mb_free_ext(m); 196bca1dae6587a640359abee04337c0463b0a3893tuexen else if ((m->m_flags & M_NOFREE) == 0) { 197bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 1989b332c241dd6df73b563594af7c334e23f5e42b8t mb_dtor_mbuf(m, NULL); 199bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 200bca1dae6587a640359abee04337c0463b0a3893tuexen SCTP_ZONE_FREE(zone_mbuf, m); 201bca1dae6587a640359abee04337c0463b0a3893tuexen } 202bca1dae6587a640359abee04337c0463b0a3893tuexen /*umem_cache_free(zone_mbuf, m);*/ 203bca1dae6587a640359abee04337c0463b0a3893tuexen return (n); 204bca1dae6587a640359abee04337c0463b0a3893tuexen} 205bca1dae6587a640359abee04337c0463b0a3893tuexen 206bca1dae6587a640359abee04337c0463b0a3893tuexen 207bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int clust_constructor_dup(caddr_t m_clust, struct mbuf* m) 208bca1dae6587a640359abee04337c0463b0a3893tuexen{ 209bca1dae6587a640359abee04337c0463b0a3893tuexen u_int *refcnt; 210bca1dae6587a640359abee04337c0463b0a3893tuexen int type, size; 21142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 212bca1dae6587a640359abee04337c0463b0a3893tuexen /* Assigning cluster of MCLBYTES. TODO: Add jumbo frame functionality */ 213bca1dae6587a640359abee04337c0463b0a3893tuexen type = EXT_CLUSTER; 214bca1dae6587a640359abee04337c0463b0a3893tuexen size = MCLBYTES; 21542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 216bca1dae6587a640359abee04337c0463b0a3893tuexen refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int); 217bca1dae6587a640359abee04337c0463b0a3893tuexen /*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/ 218bca1dae6587a640359abee04337c0463b0a3893tuexen if (refcnt == NULL) { 219bca1dae6587a640359abee04337c0463b0a3893tuexen#if !defined(SCTP_SIMPLE_ALLOCATOR) 220bca1dae6587a640359abee04337c0463b0a3893tuexen umem_reap(); 221bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 222bca1dae6587a640359abee04337c0463b0a3893tuexen refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int); 223bca1dae6587a640359abee04337c0463b0a3893tuexen /*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/ 224bca1dae6587a640359abee04337c0463b0a3893tuexen } 225bca1dae6587a640359abee04337c0463b0a3893tuexen *refcnt = 1; 226bca1dae6587a640359abee04337c0463b0a3893tuexen if (m != NULL) { 227bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_buf = (caddr_t)m_clust; 228bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_data = m->m_ext.ext_buf; 229bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_flags |= M_EXT; 230bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_free = NULL; 231bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_args = NULL; 23242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen m->m_ext.ext_size = size; 233bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_type = type; 234bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ref_cnt = refcnt; 235bca1dae6587a640359abee04337c0463b0a3893tuexen } 23642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 237bca1dae6587a640359abee04337c0463b0a3893tuexen return (0); 238bca1dae6587a640359abee04337c0463b0a3893tuexen} 239bca1dae6587a640359abee04337c0463b0a3893tuexen 240bca1dae6587a640359abee04337c0463b0a3893tuexen 241bca1dae6587a640359abee04337c0463b0a3893tuexen 242bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */ 243bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 244bca1dae6587a640359abee04337c0463b0a3893tuexenm_clget(struct mbuf *m, int how) 245bca1dae6587a640359abee04337c0463b0a3893tuexen{ 246bca1dae6587a640359abee04337c0463b0a3893tuexen caddr_t mclust_ret; 2479b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR) 2489b332c241dd6df73b563594af7c334e23f5e42b8t struct clust_args clust_mb_args; 2499b332c241dd6df73b563594af7c334e23f5e42b8t#endif 250a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen if (m->m_flags & M_EXT) { 251e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt SCTPDBG(SCTP_DEBUG_USR, "%s: %p mbuf already has cluster\n", __func__, (void *)m); 252a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen } 253bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_buf = (char *)NULL; 2549b332c241dd6df73b563594af7c334e23f5e42b8t#if defined(SCTP_SIMPLE_ALLOCATOR) 2559b332c241dd6df73b563594af7c334e23f5e42b8t clust_mb_args.parent_mbuf = m; 256bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 257bca1dae6587a640359abee04337c0463b0a3893tuexen mclust_ret = SCTP_ZONE_GET(zone_clust, char); 258bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 259bca1dae6587a640359abee04337c0463b0a3893tuexen mb_ctor_clust(mclust_ret, &clust_mb_args, 0); 260bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 261bca1dae6587a640359abee04337c0463b0a3893tuexen /*mclust_ret = umem_cache_alloc(zone_clust, UMEM_DEFAULT);*/ 26242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen /* 263bca1dae6587a640359abee04337c0463b0a3893tuexen On a cluster allocation failure, call umem_reap() and retry. 264bca1dae6587a640359abee04337c0463b0a3893tuexen */ 26542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 2667d0ed644a4f9767589413cdaaa4026d1ef1140e7tuexen if (mclust_ret == NULL) { 267bca1dae6587a640359abee04337c0463b0a3893tuexen#if !defined(SCTP_SIMPLE_ALLOCATOR) 268bca1dae6587a640359abee04337c0463b0a3893tuexen /* mclust_ret = SCTP_ZONE_GET(zone_clust, char); 269bca1dae6587a640359abee04337c0463b0a3893tuexen mb_ctor_clust(mclust_ret, &clust_mb_args, 0); 270bca1dae6587a640359abee04337c0463b0a3893tuexen#else*/ 271bca1dae6587a640359abee04337c0463b0a3893tuexen umem_reap(); 272bca1dae6587a640359abee04337c0463b0a3893tuexen mclust_ret = SCTP_ZONE_GET(zone_clust, char); 273bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 274bca1dae6587a640359abee04337c0463b0a3893tuexen /*mclust_ret = umem_cache_alloc(zone_clust, UMEM_DEFAULT);*/ 2757d0ed644a4f9767589413cdaaa4026d1ef1140e7tuexen if (NULL == mclust_ret) { 276a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen SCTPDBG(SCTP_DEBUG_USR, "Memory allocation failure in %s\n", __func__); 277bca1dae6587a640359abee04337c0463b0a3893tuexen } 278bca1dae6587a640359abee04337c0463b0a3893tuexen } 27942d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 280bca1dae6587a640359abee04337c0463b0a3893tuexen#if USING_MBUF_CONSTRUCTOR 281bca1dae6587a640359abee04337c0463b0a3893tuexen if ((m->m_ext.ext_buf == NULL)) { 282bca1dae6587a640359abee04337c0463b0a3893tuexen clust_constructor_dup(mclust_ret, m); 283bca1dae6587a640359abee04337c0463b0a3893tuexen } 284bca1dae6587a640359abee04337c0463b0a3893tuexen#else 285bca1dae6587a640359abee04337c0463b0a3893tuexen clust_constructor_dup(mclust_ret, m); 286bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 287bca1dae6587a640359abee04337c0463b0a3893tuexen} 288bca1dae6587a640359abee04337c0463b0a3893tuexen 289bca1dae6587a640359abee04337c0463b0a3893tuexen/* 290bca1dae6587a640359abee04337c0463b0a3893tuexen * Unlink a tag from the list of tags associated with an mbuf. 291bca1dae6587a640359abee04337c0463b0a3893tuexen */ 292bca1dae6587a640359abee04337c0463b0a3893tuexenstatic __inline void 293bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_unlink(struct mbuf *m, struct m_tag *t) 294bca1dae6587a640359abee04337c0463b0a3893tuexen{ 29542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 296bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_REMOVE(&m->m_pkthdr.tags, t, m_tag, m_tag_link); 297bca1dae6587a640359abee04337c0463b0a3893tuexen} 298bca1dae6587a640359abee04337c0463b0a3893tuexen 299bca1dae6587a640359abee04337c0463b0a3893tuexen/* 300bca1dae6587a640359abee04337c0463b0a3893tuexen * Reclaim resources associated with a tag. 301bca1dae6587a640359abee04337c0463b0a3893tuexen */ 302bca1dae6587a640359abee04337c0463b0a3893tuexenstatic __inline void 303bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_free(struct m_tag *t) 304bca1dae6587a640359abee04337c0463b0a3893tuexen{ 30542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 306bca1dae6587a640359abee04337c0463b0a3893tuexen (*t->m_tag_free)(t); 307bca1dae6587a640359abee04337c0463b0a3893tuexen} 308bca1dae6587a640359abee04337c0463b0a3893tuexen 309bca1dae6587a640359abee04337c0463b0a3893tuexen/* 310bca1dae6587a640359abee04337c0463b0a3893tuexen * Set up the contents of a tag. Note that this does not fill in the free 311bca1dae6587a640359abee04337c0463b0a3893tuexen * method; the caller is expected to do that. 312bca1dae6587a640359abee04337c0463b0a3893tuexen * 313bca1dae6587a640359abee04337c0463b0a3893tuexen * XXX probably should be called m_tag_init, but that was already taken. 314bca1dae6587a640359abee04337c0463b0a3893tuexen */ 315bca1dae6587a640359abee04337c0463b0a3893tuexenstatic __inline void 316bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_setup(struct m_tag *t, u_int32_t cookie, int type, int len) 317bca1dae6587a640359abee04337c0463b0a3893tuexen{ 31842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 319bca1dae6587a640359abee04337c0463b0a3893tuexen t->m_tag_id = type; 320bca1dae6587a640359abee04337c0463b0a3893tuexen t->m_tag_len = len; 321bca1dae6587a640359abee04337c0463b0a3893tuexen t->m_tag_cookie = cookie; 322bca1dae6587a640359abee04337c0463b0a3893tuexen} 323bca1dae6587a640359abee04337c0463b0a3893tuexen 324bca1dae6587a640359abee04337c0463b0a3893tuexen/************ End functions from user_mbuf.h ******************/ 325bca1dae6587a640359abee04337c0463b0a3893tuexen 326bca1dae6587a640359abee04337c0463b0a3893tuexen 327bca1dae6587a640359abee04337c0463b0a3893tuexen 328bca1dae6587a640359abee04337c0463b0a3893tuexen/************ End functions to substitute umem_cache_alloc and umem_cache_free **************/ 329bca1dae6587a640359abee04337c0463b0a3893tuexen 33042d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen/* __Userspace__ 331bca1dae6587a640359abee04337c0463b0a3893tuexen * TODO: mbuf_init must be called in the initialization routines 33242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * of userspace stack. 333bca1dae6587a640359abee04337c0463b0a3893tuexen */ 334bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 335bca1dae6587a640359abee04337c0463b0a3893tuexenmbuf_init(void *dummy) 336bca1dae6587a640359abee04337c0463b0a3893tuexen{ 337bca1dae6587a640359abee04337c0463b0a3893tuexen 338bca1dae6587a640359abee04337c0463b0a3893tuexen /* 33942d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * __Userspace__Configure UMA zones for Mbufs and Clusters. 340bca1dae6587a640359abee04337c0463b0a3893tuexen * (TODO: m_getcl() - using packet secondary zone). 34142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * There is no provision for trash_init and trash_fini in umem. 34242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * 343bca1dae6587a640359abee04337c0463b0a3893tuexen */ 344bca1dae6587a640359abee04337c0463b0a3893tuexen /* zone_mbuf = umem_cache_create(MBUF_MEM_NAME, MSIZE, 0, 34542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen mb_ctor_mbuf, mb_dtor_mbuf, NULL, 346bca1dae6587a640359abee04337c0463b0a3893tuexen &mbuf_mb_args, 347bca1dae6587a640359abee04337c0463b0a3893tuexen NULL, 0); 348bca1dae6587a640359abee04337c0463b0a3893tuexen zone_mbuf = umem_cache_create(MBUF_MEM_NAME, MSIZE, 0, NULL, NULL, NULL, NULL, NULL, 0);*/ 349bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 350bca1dae6587a640359abee04337c0463b0a3893tuexen SCTP_ZONE_INIT(zone_mbuf, MBUF_MEM_NAME, MSIZE, 0); 351bca1dae6587a640359abee04337c0463b0a3893tuexen#else 352bca1dae6587a640359abee04337c0463b0a3893tuexen zone_mbuf = umem_cache_create(MBUF_MEM_NAME, MSIZE, 0, 3539b332c241dd6df73b563594af7c334e23f5e42b8t mb_ctor_mbuf, mb_dtor_mbuf, NULL, 3549b332c241dd6df73b563594af7c334e23f5e42b8t NUULL, 3559b332c241dd6df73b563594af7c334e23f5e42b8t NULL, 0); 356bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 357bca1dae6587a640359abee04337c0463b0a3893tuexen /*zone_ext_refcnt = umem_cache_create(MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), 0, 35842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen NULL, NULL, NULL, 359bca1dae6587a640359abee04337c0463b0a3893tuexen NULL, 360bca1dae6587a640359abee04337c0463b0a3893tuexen NULL, 0);*/ 361bca1dae6587a640359abee04337c0463b0a3893tuexen SCTP_ZONE_INIT(zone_ext_refcnt, MBUF_EXTREFCNT_MEM_NAME, sizeof(u_int), 0); 36242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 363bca1dae6587a640359abee04337c0463b0a3893tuexen /*zone_clust = umem_cache_create(MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0, 364bca1dae6587a640359abee04337c0463b0a3893tuexen mb_ctor_clust, mb_dtor_clust, NULL, 365bca1dae6587a640359abee04337c0463b0a3893tuexen &clust_mb_args, 366bca1dae6587a640359abee04337c0463b0a3893tuexen NULL, 0); 367bca1dae6587a640359abee04337c0463b0a3893tuexen zone_clust = umem_cache_create(MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0, NULL, NULL, NULL, NULL, NULL,0);*/ 368bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 369bca1dae6587a640359abee04337c0463b0a3893tuexen SCTP_ZONE_INIT(zone_clust, MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0); 370bca1dae6587a640359abee04337c0463b0a3893tuexen#else 371bca1dae6587a640359abee04337c0463b0a3893tuexen zone_clust = umem_cache_create(MBUF_CLUSTER_MEM_NAME, MCLBYTES, 0, 372bca1dae6587a640359abee04337c0463b0a3893tuexen mb_ctor_clust, mb_dtor_clust, NULL, 373bca1dae6587a640359abee04337c0463b0a3893tuexen &clust_mb_args, 374bca1dae6587a640359abee04337c0463b0a3893tuexen NULL, 0); 375bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 376bca1dae6587a640359abee04337c0463b0a3893tuexen 377bca1dae6587a640359abee04337c0463b0a3893tuexen /* uma_prealloc() goes here... */ 378bca1dae6587a640359abee04337c0463b0a3893tuexen 379bca1dae6587a640359abee04337c0463b0a3893tuexen /* __Userspace__ Add umem_reap here for low memory situation? 380bca1dae6587a640359abee04337c0463b0a3893tuexen * 381bca1dae6587a640359abee04337c0463b0a3893tuexen */ 38242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 383bca1dae6587a640359abee04337c0463b0a3893tuexen 384bca1dae6587a640359abee04337c0463b0a3893tuexen /* 385bca1dae6587a640359abee04337c0463b0a3893tuexen * [Re]set counters and local statistics knobs. 38642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * 387bca1dae6587a640359abee04337c0463b0a3893tuexen */ 38842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 389bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mbufs = 0; 390bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mclusts = 0; 391bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_drain = 0; 392bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_msize = MSIZE; 393bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mclbytes = MCLBYTES; 394bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_minclsize = MINCLSIZE; 395bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mlen = MLEN; 396bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mhlen = MHLEN; 397bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_numtypes = MT_NTYPES; 398bca1dae6587a640359abee04337c0463b0a3893tuexen 399bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mcfail = mbstat.m_mpfail = 0; 400bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.sf_iocnt = 0; 401bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.sf_allocwait = mbstat.sf_allocfail = 0; 40242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 403bca1dae6587a640359abee04337c0463b0a3893tuexen} 404bca1dae6587a640359abee04337c0463b0a3893tuexen 405bca1dae6587a640359abee04337c0463b0a3893tuexen 406bca1dae6587a640359abee04337c0463b0a3893tuexen 407bca1dae6587a640359abee04337c0463b0a3893tuexen/* 408bca1dae6587a640359abee04337c0463b0a3893tuexen * __Userspace__ 409bca1dae6587a640359abee04337c0463b0a3893tuexen * 410bca1dae6587a640359abee04337c0463b0a3893tuexen * Constructor for Mbuf master zone. We have a different constructor 411bca1dae6587a640359abee04337c0463b0a3893tuexen * for allocating the cluster. 412bca1dae6587a640359abee04337c0463b0a3893tuexen * 413bca1dae6587a640359abee04337c0463b0a3893tuexen * The 'arg' pointer points to a mb_args structure which 414bca1dae6587a640359abee04337c0463b0a3893tuexen * contains call-specific information required to support the 415bca1dae6587a640359abee04337c0463b0a3893tuexen * mbuf allocation API. See user_mbuf.h. 416bca1dae6587a640359abee04337c0463b0a3893tuexen * 417bca1dae6587a640359abee04337c0463b0a3893tuexen * The flgs parameter below can be UMEM_DEFAULT or UMEM_NOFAIL depending on what 418bca1dae6587a640359abee04337c0463b0a3893tuexen * was passed when umem_cache_alloc was called. 419bca1dae6587a640359abee04337c0463b0a3893tuexen * TODO: Use UMEM_NOFAIL in umem_cache_alloc and also define a failure handler 420bca1dae6587a640359abee04337c0463b0a3893tuexen * and call umem_nofail_callback(my_failure_handler) in the stack initialization routines 42142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * The advantage of using UMEM_NOFAIL is that we don't have to check if umem_cache_alloc 422bca1dae6587a640359abee04337c0463b0a3893tuexen * was successful or not. The failure handler would take care of it, if we use the UMEM_NOFAIL 423bca1dae6587a640359abee04337c0463b0a3893tuexen * flag. 42442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * 425bca1dae6587a640359abee04337c0463b0a3893tuexen * NOTE Ref: http://docs.sun.com/app/docs/doc/819-2243/6n4i099p2?l=en&a=view&q=umem_zalloc) 426bca1dae6587a640359abee04337c0463b0a3893tuexen * The umem_nofail_callback() function sets the **process-wide** UMEM_NOFAIL callback. 427bca1dae6587a640359abee04337c0463b0a3893tuexen * It also mentions that umem_nofail_callback is Evolving. 42842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * 429bca1dae6587a640359abee04337c0463b0a3893tuexen */ 430bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int 431bca1dae6587a640359abee04337c0463b0a3893tuexenmb_ctor_mbuf(void *mem, void *arg, int flgs) 432bca1dae6587a640359abee04337c0463b0a3893tuexen{ 43342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen#if USING_MBUF_CONSTRUCTOR 434bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *m; 435bca1dae6587a640359abee04337c0463b0a3893tuexen struct mb_args *args; 436bca1dae6587a640359abee04337c0463b0a3893tuexen 437bca1dae6587a640359abee04337c0463b0a3893tuexen int flags; 438bca1dae6587a640359abee04337c0463b0a3893tuexen short type; 439bca1dae6587a640359abee04337c0463b0a3893tuexen 440bca1dae6587a640359abee04337c0463b0a3893tuexen m = (struct mbuf *)mem; 441bca1dae6587a640359abee04337c0463b0a3893tuexen args = (struct mb_args *)arg; 442bca1dae6587a640359abee04337c0463b0a3893tuexen flags = args->flags; 443bca1dae6587a640359abee04337c0463b0a3893tuexen type = args->type; 444bca1dae6587a640359abee04337c0463b0a3893tuexen 445bca1dae6587a640359abee04337c0463b0a3893tuexen /* 44642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * The mbuf is initialized later. 44742d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * 448bca1dae6587a640359abee04337c0463b0a3893tuexen */ 449bca1dae6587a640359abee04337c0463b0a3893tuexen if (type == MT_NOINIT) 450bca1dae6587a640359abee04337c0463b0a3893tuexen return (0); 451bca1dae6587a640359abee04337c0463b0a3893tuexen 452bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = NULL; 453bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_nextpkt = NULL; 454bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len = 0; 455bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_flags = flags; 456bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_type = type; 457bca1dae6587a640359abee04337c0463b0a3893tuexen if (flags & M_PKTHDR) { 458bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_data = m->m_pktdat; 459bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.rcvif = NULL; 460bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.len = 0; 461bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.header = NULL; 462bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.csum_flags = 0; 463bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.csum_data = 0; 464bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.tso_segsz = 0; 465bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.ether_vtag = 0; 466bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_INIT(&m->m_pkthdr.tags); 467bca1dae6587a640359abee04337c0463b0a3893tuexen } else 468bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_data = m->m_dat; 469bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 470bca1dae6587a640359abee04337c0463b0a3893tuexen return (0); 471bca1dae6587a640359abee04337c0463b0a3893tuexen} 472bca1dae6587a640359abee04337c0463b0a3893tuexen 473bca1dae6587a640359abee04337c0463b0a3893tuexen 474bca1dae6587a640359abee04337c0463b0a3893tuexen/* 475bca1dae6587a640359abee04337c0463b0a3893tuexen * __Userspace__ 476bca1dae6587a640359abee04337c0463b0a3893tuexen * The Mbuf master zone destructor. 477bca1dae6587a640359abee04337c0463b0a3893tuexen * This would be called in response to umem_cache_destroy 478bca1dae6587a640359abee04337c0463b0a3893tuexen * TODO: Recheck if this is what we want to do in this destructor. 479bca1dae6587a640359abee04337c0463b0a3893tuexen * (Note: the number of times mb_dtor_mbuf is called is equal to the 480bca1dae6587a640359abee04337c0463b0a3893tuexen * number of individual mbufs allocated from zone_mbuf. 481bca1dae6587a640359abee04337c0463b0a3893tuexen */ 482bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void 483bca1dae6587a640359abee04337c0463b0a3893tuexenmb_dtor_mbuf(void *mem, void *arg) 484bca1dae6587a640359abee04337c0463b0a3893tuexen{ 485bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *m; 486bca1dae6587a640359abee04337c0463b0a3893tuexen 487bca1dae6587a640359abee04337c0463b0a3893tuexen m = (struct mbuf *)mem; 4889b332c241dd6df73b563594af7c334e23f5e42b8t if ((m->m_flags & M_PKTHDR) != 0) { 489bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_delete_chain(m, NULL); 490c7108437de5af4d0b9f9a24979710b39197ec6cetuexen } 491bca1dae6587a640359abee04337c0463b0a3893tuexen} 492bca1dae6587a640359abee04337c0463b0a3893tuexen 493bca1dae6587a640359abee04337c0463b0a3893tuexen 494bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ 495bca1dae6587a640359abee04337c0463b0a3893tuexen * The Cluster zone constructor. 496bca1dae6587a640359abee04337c0463b0a3893tuexen * 497bca1dae6587a640359abee04337c0463b0a3893tuexen * Here the 'arg' pointer points to the Mbuf which we 498bca1dae6587a640359abee04337c0463b0a3893tuexen * are configuring cluster storage for. If 'arg' is 499bca1dae6587a640359abee04337c0463b0a3893tuexen * empty we allocate just the cluster without setting 500bca1dae6587a640359abee04337c0463b0a3893tuexen * the mbuf to it. See mbuf.h. 501bca1dae6587a640359abee04337c0463b0a3893tuexen */ 502bca1dae6587a640359abee04337c0463b0a3893tuexenstatic int 503bca1dae6587a640359abee04337c0463b0a3893tuexenmb_ctor_clust(void *mem, void *arg, int flgs) 504bca1dae6587a640359abee04337c0463b0a3893tuexen{ 50542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 50642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen#if USING_MBUF_CONSTRUCTOR 507bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *m; 508bca1dae6587a640359abee04337c0463b0a3893tuexen struct clust_args * cla; 509bca1dae6587a640359abee04337c0463b0a3893tuexen u_int *refcnt; 510bca1dae6587a640359abee04337c0463b0a3893tuexen int type, size; 511bca1dae6587a640359abee04337c0463b0a3893tuexen sctp_zone_t zone; 51242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 513bca1dae6587a640359abee04337c0463b0a3893tuexen /* Assigning cluster of MCLBYTES. TODO: Add jumbo frame functionality */ 514bca1dae6587a640359abee04337c0463b0a3893tuexen type = EXT_CLUSTER; 515bca1dae6587a640359abee04337c0463b0a3893tuexen zone = zone_clust; 516bca1dae6587a640359abee04337c0463b0a3893tuexen size = MCLBYTES; 517bca1dae6587a640359abee04337c0463b0a3893tuexen 518bca1dae6587a640359abee04337c0463b0a3893tuexen cla = (struct clust_args *)arg; 519bca1dae6587a640359abee04337c0463b0a3893tuexen m = cla->parent_mbuf; 520bca1dae6587a640359abee04337c0463b0a3893tuexen 521bca1dae6587a640359abee04337c0463b0a3893tuexen refcnt = SCTP_ZONE_GET(zone_ext_refcnt, u_int); 522bca1dae6587a640359abee04337c0463b0a3893tuexen /*refcnt = (u_int *)umem_cache_alloc(zone_ext_refcnt, UMEM_DEFAULT);*/ 523bca1dae6587a640359abee04337c0463b0a3893tuexen *refcnt = 1; 524bca1dae6587a640359abee04337c0463b0a3893tuexen 525bca1dae6587a640359abee04337c0463b0a3893tuexen if (m != NULL) { 526bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_buf = (caddr_t)mem; 527bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_data = m->m_ext.ext_buf; 528bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_flags |= M_EXT; 529bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_free = NULL; 530bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_args = NULL; 53142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen m->m_ext.ext_size = size; 532bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_type = type; 533bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ref_cnt = refcnt; 534bca1dae6587a640359abee04337c0463b0a3893tuexen } 535bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 536bca1dae6587a640359abee04337c0463b0a3893tuexen return (0); 537bca1dae6587a640359abee04337c0463b0a3893tuexen} 538bca1dae6587a640359abee04337c0463b0a3893tuexen 539bca1dae6587a640359abee04337c0463b0a3893tuexen/* __Userspace__ */ 540bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void 541bca1dae6587a640359abee04337c0463b0a3893tuexenmb_dtor_clust(void *mem, void *arg) 542bca1dae6587a640359abee04337c0463b0a3893tuexen{ 54342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 544bca1dae6587a640359abee04337c0463b0a3893tuexen /* mem is of type caddr_t. In sys/types.h we have typedef char * caddr_t; */ 545bca1dae6587a640359abee04337c0463b0a3893tuexen /* mb_dtor_clust is called at time of umem_cache_destroy() (the number of times 54642d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * mb_dtor_clust is called is equal to the number of individual mbufs allocated 547bca1dae6587a640359abee04337c0463b0a3893tuexen * from zone_clust. Similarly for mb_dtor_mbuf). 548bca1dae6587a640359abee04337c0463b0a3893tuexen * At this point the following: 549bca1dae6587a640359abee04337c0463b0a3893tuexen * struct mbuf *m; 550bca1dae6587a640359abee04337c0463b0a3893tuexen * m = (struct mbuf *)arg; 551bca1dae6587a640359abee04337c0463b0a3893tuexen * assert (*(m->m_ext.ref_cnt) == 0); is not meaningful since m->m_ext.ref_cnt = NULL; 552bca1dae6587a640359abee04337c0463b0a3893tuexen * has been done in mb_free_ext(). 553bca1dae6587a640359abee04337c0463b0a3893tuexen */ 554bca1dae6587a640359abee04337c0463b0a3893tuexen 555bca1dae6587a640359abee04337c0463b0a3893tuexen} 556bca1dae6587a640359abee04337c0463b0a3893tuexen 557bca1dae6587a640359abee04337c0463b0a3893tuexen 558bca1dae6587a640359abee04337c0463b0a3893tuexen 559bca1dae6587a640359abee04337c0463b0a3893tuexen 560bca1dae6587a640359abee04337c0463b0a3893tuexen/* Unlink and free a packet tag. */ 561bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 562bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_delete(struct mbuf *m, struct m_tag *t) 563bca1dae6587a640359abee04337c0463b0a3893tuexen{ 564e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt KASSERT(m && t, ("m_tag_delete: null argument, m %p t %p", (void *)m, (void *)t)); 565bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_unlink(m, t); 566bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_free(t); 567bca1dae6587a640359abee04337c0463b0a3893tuexen} 568bca1dae6587a640359abee04337c0463b0a3893tuexen 569bca1dae6587a640359abee04337c0463b0a3893tuexen 570bca1dae6587a640359abee04337c0463b0a3893tuexen/* Unlink and free a packet tag chain, starting from given tag. */ 571bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 572bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_delete_chain(struct mbuf *m, struct m_tag *t) 573bca1dae6587a640359abee04337c0463b0a3893tuexen{ 57442d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 575bca1dae6587a640359abee04337c0463b0a3893tuexen struct m_tag *p, *q; 576bca1dae6587a640359abee04337c0463b0a3893tuexen 577c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(m, ("m_tag_delete_chain: null mbuf")); 578bca1dae6587a640359abee04337c0463b0a3893tuexen if (t != NULL) 579bca1dae6587a640359abee04337c0463b0a3893tuexen p = t; 580bca1dae6587a640359abee04337c0463b0a3893tuexen else 581bca1dae6587a640359abee04337c0463b0a3893tuexen p = SLIST_FIRST(&m->m_pkthdr.tags); 582bca1dae6587a640359abee04337c0463b0a3893tuexen if (p == NULL) 583bca1dae6587a640359abee04337c0463b0a3893tuexen return; 584bca1dae6587a640359abee04337c0463b0a3893tuexen while ((q = SLIST_NEXT(p, m_tag_link)) != NULL) 585bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_delete(m, q); 586bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_delete(m, p); 587bca1dae6587a640359abee04337c0463b0a3893tuexen} 588bca1dae6587a640359abee04337c0463b0a3893tuexen 589bca1dae6587a640359abee04337c0463b0a3893tuexen#if 0 590bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void 591bca1dae6587a640359abee04337c0463b0a3893tuexensctp_print_mbuf_chain(struct mbuf *m) 592bca1dae6587a640359abee04337c0463b0a3893tuexen{ 593e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt SCTP_DEBUG_USR(SCTP_DEBUG_USR, "Printing mbuf chain %p.\n", (void *)m); 594bca1dae6587a640359abee04337c0463b0a3893tuexen for(; m; m=m->m_next) { 595e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt SCTP_DEBUG_USR(SCTP_DEBUG_USR, "%p: m_len = %ld, m_type = %x, m_next = %p.\n", (void *)m, m->m_len, m->m_type, (void *)m->m_next); 596bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_EXT) 597e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt SCTP_DEBUG_USR(SCTP_DEBUG_USR, "%p: extend_size = %d, extend_buffer = %p, ref_cnt = %d.\n", (void *)m, m->m_ext.ext_size, (void *)m->m_ext.ext_buf, *(m->m_ext.ref_cnt)); 59842d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen } 599bca1dae6587a640359abee04337c0463b0a3893tuexen} 600bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 601bca1dae6587a640359abee04337c0463b0a3893tuexen 602bca1dae6587a640359abee04337c0463b0a3893tuexen/* 603bca1dae6587a640359abee04337c0463b0a3893tuexen * Free an entire chain of mbufs and associated external buffers, if 604bca1dae6587a640359abee04337c0463b0a3893tuexen * applicable. 605bca1dae6587a640359abee04337c0463b0a3893tuexen */ 606bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 607bca1dae6587a640359abee04337c0463b0a3893tuexenm_freem(struct mbuf *mb) 608bca1dae6587a640359abee04337c0463b0a3893tuexen{ 609bca1dae6587a640359abee04337c0463b0a3893tuexen while (mb != NULL) 610bca1dae6587a640359abee04337c0463b0a3893tuexen mb = m_free(mb); 611bca1dae6587a640359abee04337c0463b0a3893tuexen} 612bca1dae6587a640359abee04337c0463b0a3893tuexen 613bca1dae6587a640359abee04337c0463b0a3893tuexen/* 614bca1dae6587a640359abee04337c0463b0a3893tuexen * __Userspace__ 61542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * clean mbufs with M_EXT storage attached to them 616bca1dae6587a640359abee04337c0463b0a3893tuexen * if the reference count hits 1. 617bca1dae6587a640359abee04337c0463b0a3893tuexen */ 618bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 619bca1dae6587a640359abee04337c0463b0a3893tuexenmb_free_ext(struct mbuf *m) 620bca1dae6587a640359abee04337c0463b0a3893tuexen{ 62142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 622bca1dae6587a640359abee04337c0463b0a3893tuexen int skipmbuf; 62342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 624c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__)); 625c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(m->m_ext.ref_cnt != NULL, ("%s: ref_cnt not set", __func__)); 626bca1dae6587a640359abee04337c0463b0a3893tuexen 627bca1dae6587a640359abee04337c0463b0a3893tuexen /* 628bca1dae6587a640359abee04337c0463b0a3893tuexen * check if the header is embedded in the cluster 62942d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen */ 630bca1dae6587a640359abee04337c0463b0a3893tuexen skipmbuf = (m->m_flags & M_NOFREE); 631bca1dae6587a640359abee04337c0463b0a3893tuexen 63242d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen /* Free the external attached storage if this 63342d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * mbuf is the only reference to it. 634bca1dae6587a640359abee04337c0463b0a3893tuexen *__Userspace__ TODO: jumbo frames 63542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen * 636bca1dae6587a640359abee04337c0463b0a3893tuexen */ 637c7108437de5af4d0b9f9a24979710b39197ec6cetuexen /* NOTE: We had the same code that SCTP_DECREMENT_AND_CHECK_REFCOUNT 638c7108437de5af4d0b9f9a24979710b39197ec6cetuexen reduces to here before but the IPHONE malloc commit had changed 639c7108437de5af4d0b9f9a24979710b39197ec6cetuexen this to compare to 0 instead of 1 (see next line). Why? 640c7108437de5af4d0b9f9a24979710b39197ec6cetuexen . .. this caused a huge memory leak in Linux. 641c7108437de5af4d0b9f9a24979710b39197ec6cetuexen */ 642bca1dae6587a640359abee04337c0463b0a3893tuexen#ifdef IPHONE 643c7108437de5af4d0b9f9a24979710b39197ec6cetuexen if (atomic_fetchadd_int(m->m_ext.ref_cnt, -1) == 0) 644bca1dae6587a640359abee04337c0463b0a3893tuexen#else 645c7108437de5af4d0b9f9a24979710b39197ec6cetuexen if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(m->m_ext.ref_cnt)) 646bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 647c7108437de5af4d0b9f9a24979710b39197ec6cetuexen { 648bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_ext.ext_type == EXT_CLUSTER){ 649bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 650bca1dae6587a640359abee04337c0463b0a3893tuexen mb_dtor_clust(m->m_ext.ext_buf, &clust_mb_args); 651bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 652bca1dae6587a640359abee04337c0463b0a3893tuexen SCTP_ZONE_FREE(zone_clust, m->m_ext.ext_buf); 653bca1dae6587a640359abee04337c0463b0a3893tuexen SCTP_ZONE_FREE(zone_ext_refcnt, (u_int*)m->m_ext.ref_cnt); 654bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ref_cnt = NULL; 655bca1dae6587a640359abee04337c0463b0a3893tuexen } 656c7108437de5af4d0b9f9a24979710b39197ec6cetuexen } 65742d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 658bca1dae6587a640359abee04337c0463b0a3893tuexen if (skipmbuf) 659bca1dae6587a640359abee04337c0463b0a3893tuexen return; 660bca1dae6587a640359abee04337c0463b0a3893tuexen 66142d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 662bca1dae6587a640359abee04337c0463b0a3893tuexen /* __Userspace__ Also freeing the storage for ref_cnt 663bca1dae6587a640359abee04337c0463b0a3893tuexen * Free this mbuf back to the mbuf zone with all m_ext 664bca1dae6587a640359abee04337c0463b0a3893tuexen * information purged. 665bca1dae6587a640359abee04337c0463b0a3893tuexen */ 666bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_buf = NULL; 667bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_free = NULL; 668bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_args = NULL; 669bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ref_cnt = NULL; 670bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_size = 0; 671bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_ext.ext_type = 0; 672bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_flags &= ~M_EXT; 673bca1dae6587a640359abee04337c0463b0a3893tuexen#if defined(SCTP_SIMPLE_ALLOCATOR) 6749b332c241dd6df73b563594af7c334e23f5e42b8t mb_dtor_mbuf(m, NULL); 675bca1dae6587a640359abee04337c0463b0a3893tuexen#endif 676bca1dae6587a640359abee04337c0463b0a3893tuexen SCTP_ZONE_FREE(zone_mbuf, m); 67742d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 678bca1dae6587a640359abee04337c0463b0a3893tuexen /*umem_cache_free(zone_mbuf, m);*/ 679bca1dae6587a640359abee04337c0463b0a3893tuexen} 680bca1dae6587a640359abee04337c0463b0a3893tuexen 681bca1dae6587a640359abee04337c0463b0a3893tuexen/* 682bca1dae6587a640359abee04337c0463b0a3893tuexen * "Move" mbuf pkthdr from "from" to "to". 683bca1dae6587a640359abee04337c0463b0a3893tuexen * "from" must have M_PKTHDR set, and "to" must be empty. 684bca1dae6587a640359abee04337c0463b0a3893tuexen */ 685bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 686bca1dae6587a640359abee04337c0463b0a3893tuexenm_move_pkthdr(struct mbuf *to, struct mbuf *from) 687bca1dae6587a640359abee04337c0463b0a3893tuexen{ 688bca1dae6587a640359abee04337c0463b0a3893tuexen 689bca1dae6587a640359abee04337c0463b0a3893tuexen to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); 690bca1dae6587a640359abee04337c0463b0a3893tuexen if ((to->m_flags & M_EXT) == 0) 691bca1dae6587a640359abee04337c0463b0a3893tuexen to->m_data = to->m_pktdat; 692bca1dae6587a640359abee04337c0463b0a3893tuexen to->m_pkthdr = from->m_pkthdr; /* especially tags */ 693bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_INIT(&from->m_pkthdr.tags); /* purge tags from src */ 694bca1dae6587a640359abee04337c0463b0a3893tuexen from->m_flags &= ~M_PKTHDR; 695bca1dae6587a640359abee04337c0463b0a3893tuexen} 696bca1dae6587a640359abee04337c0463b0a3893tuexen 697bca1dae6587a640359abee04337c0463b0a3893tuexen 698bca1dae6587a640359abee04337c0463b0a3893tuexen/* 699bca1dae6587a640359abee04337c0463b0a3893tuexen * Rearange an mbuf chain so that len bytes are contiguous 700bca1dae6587a640359abee04337c0463b0a3893tuexen * and in the data area of an mbuf (so that mtod and dtom 701bca1dae6587a640359abee04337c0463b0a3893tuexen * will work for a structure of size len). Returns the resulting 702bca1dae6587a640359abee04337c0463b0a3893tuexen * mbuf chain on success, frees it and returns null on failure. 703bca1dae6587a640359abee04337c0463b0a3893tuexen * If there is room, it will add up to max_protohdr-len extra bytes to the 704bca1dae6587a640359abee04337c0463b0a3893tuexen * contiguous region in an attempt to avoid being called next time. 705bca1dae6587a640359abee04337c0463b0a3893tuexen */ 706bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf * 707bca1dae6587a640359abee04337c0463b0a3893tuexenm_pullup(struct mbuf *n, int len) 708bca1dae6587a640359abee04337c0463b0a3893tuexen{ 709bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *m; 710bca1dae6587a640359abee04337c0463b0a3893tuexen int count; 711bca1dae6587a640359abee04337c0463b0a3893tuexen int space; 712bca1dae6587a640359abee04337c0463b0a3893tuexen 713bca1dae6587a640359abee04337c0463b0a3893tuexen /* 714bca1dae6587a640359abee04337c0463b0a3893tuexen * If first mbuf has no cluster, and has room for len bytes 715bca1dae6587a640359abee04337c0463b0a3893tuexen * without shifting current data, pullup into it, 716bca1dae6587a640359abee04337c0463b0a3893tuexen * otherwise allocate a new mbuf to prepend to the chain. 717bca1dae6587a640359abee04337c0463b0a3893tuexen */ 718bca1dae6587a640359abee04337c0463b0a3893tuexen if ((n->m_flags & M_EXT) == 0 && 719bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_data + len < &n->m_dat[MLEN] && n->m_next) { 72007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (n->m_len >= len) 721bca1dae6587a640359abee04337c0463b0a3893tuexen return (n); 722bca1dae6587a640359abee04337c0463b0a3893tuexen m = n; 723bca1dae6587a640359abee04337c0463b0a3893tuexen n = n->m_next; 724bca1dae6587a640359abee04337c0463b0a3893tuexen len -= m->m_len; 725bca1dae6587a640359abee04337c0463b0a3893tuexen } else { 726bca1dae6587a640359abee04337c0463b0a3893tuexen if (len > MHLEN) 727bca1dae6587a640359abee04337c0463b0a3893tuexen goto bad; 728218d5d0df143e859e241afb12d6aaa1e4969d714t MGET(m, M_NOWAIT, n->m_type); 729bca1dae6587a640359abee04337c0463b0a3893tuexen if (m == NULL) 730bca1dae6587a640359abee04337c0463b0a3893tuexen goto bad; 731bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len = 0; 732bca1dae6587a640359abee04337c0463b0a3893tuexen if (n->m_flags & M_PKTHDR) 733bca1dae6587a640359abee04337c0463b0a3893tuexen M_MOVE_PKTHDR(m, n); 734bca1dae6587a640359abee04337c0463b0a3893tuexen } 735bca1dae6587a640359abee04337c0463b0a3893tuexen space = &m->m_dat[MLEN] - (m->m_data + m->m_len); 736bca1dae6587a640359abee04337c0463b0a3893tuexen do { 737bca1dae6587a640359abee04337c0463b0a3893tuexen count = min(min(max(len, max_protohdr), space), n->m_len); 738bca1dae6587a640359abee04337c0463b0a3893tuexen bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 739bca1dae6587a640359abee04337c0463b0a3893tuexen (u_int)count); 740bca1dae6587a640359abee04337c0463b0a3893tuexen len -= count; 741bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len += count; 742bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_len -= count; 743bca1dae6587a640359abee04337c0463b0a3893tuexen space -= count; 744bca1dae6587a640359abee04337c0463b0a3893tuexen if (n->m_len) 745bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_data += count; 746bca1dae6587a640359abee04337c0463b0a3893tuexen else 747bca1dae6587a640359abee04337c0463b0a3893tuexen n = m_free(n); 748bca1dae6587a640359abee04337c0463b0a3893tuexen } while (len > 0 && n); 749bca1dae6587a640359abee04337c0463b0a3893tuexen if (len > 0) { 750bca1dae6587a640359abee04337c0463b0a3893tuexen (void) m_free(m); 751bca1dae6587a640359abee04337c0463b0a3893tuexen goto bad; 752bca1dae6587a640359abee04337c0463b0a3893tuexen } 753bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = n; 754bca1dae6587a640359abee04337c0463b0a3893tuexen return (m); 755bca1dae6587a640359abee04337c0463b0a3893tuexenbad: 756bca1dae6587a640359abee04337c0463b0a3893tuexen m_freem(n); 75707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen mbstat.m_mpfail++; /* XXX: No consistency. */ 758bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 759bca1dae6587a640359abee04337c0463b0a3893tuexen} 760bca1dae6587a640359abee04337c0463b0a3893tuexen 761bca1dae6587a640359abee04337c0463b0a3893tuexen 76207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenstatic struct mbuf * 76307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenm_dup1(struct mbuf *m, int off, int len, int wait) 76407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen{ 765965e9dceb266b9896f53449746275e02b67e04b3tuexen struct mbuf *n = NULL; 76607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen int copyhdr; 76707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 76807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (len > MCLBYTES) 76907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; 77007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (off == 0 && (m->m_flags & M_PKTHDR) != 0) 77107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen copyhdr = 1; 77207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen else 77307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen copyhdr = 0; 77407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (len >= MINCLSIZE) { 7754c82d43c909753945d3f4f3fdcad271c2d8728eftuexen if (copyhdr == 1) { 7764c82d43c909753945d3f4f3fdcad271c2d8728eftuexen m_clget(n, wait); /* TODO: include code for copying the header */ 7774c82d43c909753945d3f4f3fdcad271c2d8728eftuexen m_dup_pkthdr(n, m, wait); 7784c82d43c909753945d3f4f3fdcad271c2d8728eftuexen } else 7794c82d43c909753945d3f4f3fdcad271c2d8728eftuexen m_clget(n, wait); 78007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } else { 78107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (copyhdr == 1) 78207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = m_gethdr(wait, m->m_type); 78307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen else 78407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = m_get(wait, m->m_type); 78507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 78607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (!n) 78707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; /* ENOBUFS */ 78807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 78907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (copyhdr && !m_dup_pkthdr(n, m, wait)) { 79007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_free(n); 79107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; 79207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 79307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_copydata(m, off, len, mtod(n, caddr_t)); 79407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_len = len; 79507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return n; 79607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen} 79707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 79807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 79907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen/* Taken from sys/kern/uipc_mbuf2.c */ 80007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenstruct mbuf * 80107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenm_pulldown(struct mbuf *m, int off, int len, int *offp) 80207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen{ 80307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen struct mbuf *n, *o; 80407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen int hlen, tlen, olen; 80507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen int writable; 80607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 80707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* check invalid arguments. */ 808edd4507cda024159552eb3574f9ba93766ea33d8tuexen KASSERT(m, ("m == NULL in m_pulldown()")); 80907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (len > MCLBYTES) { 81007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_freem(m); 81107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; /* impossible */ 81207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 81307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 81407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#ifdef PULLDOWN_DEBUG 81507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen { 81607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen struct mbuf *t; 817a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen SCTP_DEBUG_USR(SCTP_DEBUG_USR, "before:"); 81807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen for (t = m; t; t = t->m_next) 819a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen SCTP_DEBUG_USR(SCTP_DEBUG_USR, " %d", t->m_len); 820a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen SCTP_DEBUG_USR(SCTP_DEBUG_USR, "\n"); 82107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 82207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif 82307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = m; 82407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen while (n != NULL && off > 0) { 82507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (n->m_len > off) 82607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen break; 82707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen off -= n->m_len; 82807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = n->m_next; 82907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 83007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* be sure to point non-empty mbuf */ 83107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen while (n != NULL && n->m_len == 0) 83207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = n->m_next; 83307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (!n) { 83407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_freem(m); 83507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; /* mbuf chain too short */ 83607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 83707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 83807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen writable = 0; 83907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if ((n->m_flags & M_EXT) == 0 || 84007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen (n->m_ext.ext_type == EXT_CLUSTER && M_WRITABLE(n))) 84107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen writable = 1; 84207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 84307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* 84407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * the target data is on <n, off>. 84507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * if we got enough data on the mbuf "n", we're done. 84607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen */ 84707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if ((off == 0 || offp) && len <= n->m_len - off && writable) 84807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen goto ok; 84907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 85007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* 85107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * when len <= n->m_len - off and off != 0, it is a special case. 85207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * len bytes from <n, off> sits in single mbuf, but the caller does 85307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * not like the starting position (off). 85407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * chop the current mbuf into two pieces, set off to 0. 85507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen */ 85607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (len <= n->m_len - off) { 857218d5d0df143e859e241afb12d6aaa1e4969d714t o = m_dup1(n, off, n->m_len - off, M_NOWAIT); 85807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (o == NULL) { 85907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_freem(m); 86007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; /* ENOBUFS */ 86107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 86207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_len = off; 86307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen o->m_next = n->m_next; 86407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_next = o; 86507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = n->m_next; 86607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen off = 0; 86707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen goto ok; 86807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 86907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* 87007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * we need to take hlen from <n, off> and tlen from <n->m_next, 0>, 87107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * and construct contiguous mbuf with m_len == len. 87207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * note that hlen + tlen == len, and tlen > 0. 87307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen */ 87407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen hlen = n->m_len - off; 87507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen tlen = len - hlen; 87607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 87707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* 87807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * ensure that we have enough trailing data on mbuf chain. 87907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * if not, we can do nothing about the chain. 88007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen */ 88107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen olen = 0; 88207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen for (o = n->m_next; o != NULL; o = o->m_next) 88307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen olen += o->m_len; 88407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (hlen + olen < len) { 88507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_freem(m); 88607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; /* mbuf chain too short */ 88707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 88807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 88907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* 89007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * easy cases first. 89107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * we need to use m_copydata() to get data from <n->m_next, 0>. 89207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen */ 89307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen 89407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen && writable) { 89507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len); 89607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_len += tlen; 89707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_adj(n->m_next, tlen); 89807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen goto ok; 89907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 90007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 90107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen 90207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen && writable) { 90307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_next->m_data -= hlen; 90407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_next->m_len += hlen; 90507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen bcopy(mtod(n, caddr_t) + off, mtod(n->m_next, caddr_t), hlen); 90607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_len -= hlen; 90707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = n->m_next; 90807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen off = 0; 90907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen goto ok; 91007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 91107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 91207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* 91307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * now, we need to do the hard way. don't m_copy as there's no room 91407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen * on both end. 91507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen */ 91607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (len > MLEN) 917218d5d0df143e859e241afb12d6aaa1e4969d714t m_clget(o, M_NOWAIT); 918218d5d0df143e859e241afb12d6aaa1e4969d714t /* o = m_getcl(M_NOWAIT, m->m_type, 0);*/ 91907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen else 920218d5d0df143e859e241afb12d6aaa1e4969d714t o = m_get(M_NOWAIT, m->m_type); 92107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (!o) { 92207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_freem(m); 92307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return NULL; /* ENOBUFS */ 92407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 92507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* get hlen from <n, off> into <o, 0> */ 92607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen o->m_len = hlen; 92707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen bcopy(mtod(n, caddr_t) + off, mtod(o, caddr_t), hlen); 92807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_len -= hlen; 92907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen /* get tlen from <n->m_next, 0> into <o, hlen> */ 93007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_copydata(n->m_next, 0, tlen, mtod(o, caddr_t) + o->m_len); 93107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen o->m_len += tlen; 93207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen m_adj(n->m_next, tlen); 93307961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen o->m_next = n->m_next; 93407961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n->m_next = o; 93507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen n = o; 93607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen off = 0; 93707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexenok: 93807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#ifdef PULLDOWN_DEBUG 93907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen { 94007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen struct mbuf *t; 941a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen SCTP_DEBUG_USR(SCTP_DEBUG_USR, "after:"); 94207961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen for (t = m; t; t = t->m_next) 943a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen SCTP_DEBUG_USR(SCTP_DEBUG_USR, "%c%d", t == n ? '*' : ' ', t->m_len); 944a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen SCTP_DEBUG_USR(SCTP_DEBUG_USR, " (off=%d)\n", off); 94507961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen } 94607961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen#endif 94707961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen if (offp) 94807961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen *offp = off; 94907961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen return n; 95007961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen} 95107961c43dc77daf1aa2b3258312d943f0eaa8b38tuexen 952bca1dae6587a640359abee04337c0463b0a3893tuexen/* 953bca1dae6587a640359abee04337c0463b0a3893tuexen * Attach the the cluster from *m to *n, set up m_ext in *n 954bca1dae6587a640359abee04337c0463b0a3893tuexen * and bump the refcount of the cluster. 955bca1dae6587a640359abee04337c0463b0a3893tuexen */ 956bca1dae6587a640359abee04337c0463b0a3893tuexenstatic void 957bca1dae6587a640359abee04337c0463b0a3893tuexenmb_dupcl(struct mbuf *n, struct mbuf *m) 958bca1dae6587a640359abee04337c0463b0a3893tuexen{ 959c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT((m->m_flags & M_EXT) == M_EXT, ("%s: M_EXT not set", __func__)); 960c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(m->m_ext.ref_cnt != NULL, ("%s: ref_cnt not set", __func__)); 961c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT((n->m_flags & M_EXT) == 0, ("%s: M_EXT set", __func__)); 962bca1dae6587a640359abee04337c0463b0a3893tuexen 963bca1dae6587a640359abee04337c0463b0a3893tuexen if (*(m->m_ext.ref_cnt) == 1) 964a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen *(m->m_ext.ref_cnt) += 1; 965bca1dae6587a640359abee04337c0463b0a3893tuexen else 966a1d7a8516e4d5b2136c5bb3d49aeac80271a36b0tuexen atomic_add_int(m->m_ext.ref_cnt, 1); 967bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_ext.ext_buf = m->m_ext.ext_buf; 968bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_ext.ext_free = m->m_ext.ext_free; 969bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_ext.ext_args = m->m_ext.ext_args; 970bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_ext.ext_size = m->m_ext.ext_size; 971bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_ext.ref_cnt = m->m_ext.ref_cnt; 972bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_ext.ext_type = m->m_ext.ext_type; 973bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_flags |= M_EXT; 974bca1dae6587a640359abee04337c0463b0a3893tuexen} 975bca1dae6587a640359abee04337c0463b0a3893tuexen 976bca1dae6587a640359abee04337c0463b0a3893tuexen 977bca1dae6587a640359abee04337c0463b0a3893tuexen/* 978bca1dae6587a640359abee04337c0463b0a3893tuexen * Make a copy of an mbuf chain starting "off0" bytes from the beginning, 979bca1dae6587a640359abee04337c0463b0a3893tuexen * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf. 980218d5d0df143e859e241afb12d6aaa1e4969d714t * The wait parameter is a choice of M_TRYWAIT/M_NOWAIT from caller. 981bca1dae6587a640359abee04337c0463b0a3893tuexen * Note that the copy is read-only, because clusters are not copied, 982bca1dae6587a640359abee04337c0463b0a3893tuexen * only their reference counts are incremented. 983bca1dae6587a640359abee04337c0463b0a3893tuexen */ 984bca1dae6587a640359abee04337c0463b0a3893tuexen 985bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf * 986bca1dae6587a640359abee04337c0463b0a3893tuexenm_copym(struct mbuf *m, int off0, int len, int wait) 987bca1dae6587a640359abee04337c0463b0a3893tuexen{ 988bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *n, **np; 989bca1dae6587a640359abee04337c0463b0a3893tuexen int off = off0; 990bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *top; 991bca1dae6587a640359abee04337c0463b0a3893tuexen int copyhdr = 0; 992bca1dae6587a640359abee04337c0463b0a3893tuexen 993c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(off >= 0, ("m_copym, negative off %d", off)); 994c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(len >= 0, ("m_copym, negative len %d", len)); 99542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen 996bca1dae6587a640359abee04337c0463b0a3893tuexen if (off == 0 && m->m_flags & M_PKTHDR) 997bca1dae6587a640359abee04337c0463b0a3893tuexen copyhdr = 1; 998bca1dae6587a640359abee04337c0463b0a3893tuexen while (off > 0) { 999c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(m != NULL, ("m_copym, offset > size of mbuf chain")); 1000bca1dae6587a640359abee04337c0463b0a3893tuexen if (off < m->m_len) 1001bca1dae6587a640359abee04337c0463b0a3893tuexen break; 1002bca1dae6587a640359abee04337c0463b0a3893tuexen off -= m->m_len; 1003bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1004bca1dae6587a640359abee04337c0463b0a3893tuexen } 1005bca1dae6587a640359abee04337c0463b0a3893tuexen np = ⊤ 1006bca1dae6587a640359abee04337c0463b0a3893tuexen top = 0; 1007bca1dae6587a640359abee04337c0463b0a3893tuexen while (len > 0) { 1008bca1dae6587a640359abee04337c0463b0a3893tuexen if (m == NULL) { 1009c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(len == M_COPYALL, ("m_copym, length > size of mbuf chain")); 1010c7108437de5af4d0b9f9a24979710b39197ec6cetuexen break; 1011bca1dae6587a640359abee04337c0463b0a3893tuexen } 1012bca1dae6587a640359abee04337c0463b0a3893tuexen if (copyhdr) 1013bca1dae6587a640359abee04337c0463b0a3893tuexen MGETHDR(n, wait, m->m_type); 1014bca1dae6587a640359abee04337c0463b0a3893tuexen else 1015bca1dae6587a640359abee04337c0463b0a3893tuexen MGET(n, wait, m->m_type); 1016bca1dae6587a640359abee04337c0463b0a3893tuexen *np = n; 1017bca1dae6587a640359abee04337c0463b0a3893tuexen if (n == NULL) 1018bca1dae6587a640359abee04337c0463b0a3893tuexen goto nospace; 1019bca1dae6587a640359abee04337c0463b0a3893tuexen if (copyhdr) { 1020bca1dae6587a640359abee04337c0463b0a3893tuexen if (!m_dup_pkthdr(n, m, wait)) 1021bca1dae6587a640359abee04337c0463b0a3893tuexen goto nospace; 1022bca1dae6587a640359abee04337c0463b0a3893tuexen if (len == M_COPYALL) 1023bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_pkthdr.len -= off0; 1024bca1dae6587a640359abee04337c0463b0a3893tuexen else 1025bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_pkthdr.len = len; 1026bca1dae6587a640359abee04337c0463b0a3893tuexen copyhdr = 0; 1027bca1dae6587a640359abee04337c0463b0a3893tuexen } 1028bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_len = min(len, m->m_len - off); 1029bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_EXT) { 1030bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_data = m->m_data + off; 1031bca1dae6587a640359abee04337c0463b0a3893tuexen mb_dupcl(n, m); 1032bca1dae6587a640359abee04337c0463b0a3893tuexen } else 1033bca1dae6587a640359abee04337c0463b0a3893tuexen bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 1034bca1dae6587a640359abee04337c0463b0a3893tuexen (u_int)n->m_len); 1035bca1dae6587a640359abee04337c0463b0a3893tuexen if (len != M_COPYALL) 1036bca1dae6587a640359abee04337c0463b0a3893tuexen len -= n->m_len; 1037bca1dae6587a640359abee04337c0463b0a3893tuexen off = 0; 1038bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1039bca1dae6587a640359abee04337c0463b0a3893tuexen np = &n->m_next; 1040bca1dae6587a640359abee04337c0463b0a3893tuexen } 1041bca1dae6587a640359abee04337c0463b0a3893tuexen if (top == NULL) 1042bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mcfail++; /* XXX: No consistency. */ 1043bca1dae6587a640359abee04337c0463b0a3893tuexen 1044bca1dae6587a640359abee04337c0463b0a3893tuexen return (top); 1045bca1dae6587a640359abee04337c0463b0a3893tuexennospace: 1046bca1dae6587a640359abee04337c0463b0a3893tuexen m_freem(top); 1047bca1dae6587a640359abee04337c0463b0a3893tuexen mbstat.m_mcfail++; /* XXX: No consistency. */ 1048bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 1049bca1dae6587a640359abee04337c0463b0a3893tuexen} 1050bca1dae6587a640359abee04337c0463b0a3893tuexen 1051bca1dae6587a640359abee04337c0463b0a3893tuexen 1052bca1dae6587a640359abee04337c0463b0a3893tuexenint 1053bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how) 1054bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1055bca1dae6587a640359abee04337c0463b0a3893tuexen struct m_tag *p, *t, *tprev = NULL; 1056bca1dae6587a640359abee04337c0463b0a3893tuexen 1057e7eb46f39b8bfc4b5ed9b708232c1c669c06842bt KASSERT(to && from, ("m_tag_copy_chain: null argument, to %p from %p", (void *)to, (void *)from)); 1058bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_delete_chain(to, NULL); 1059bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) { 1060bca1dae6587a640359abee04337c0463b0a3893tuexen t = m_tag_copy(p, how); 1061bca1dae6587a640359abee04337c0463b0a3893tuexen if (t == NULL) { 1062bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_delete_chain(to, NULL); 1063bca1dae6587a640359abee04337c0463b0a3893tuexen return 0; 1064bca1dae6587a640359abee04337c0463b0a3893tuexen } 1065bca1dae6587a640359abee04337c0463b0a3893tuexen if (tprev == NULL) 1066bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_INSERT_HEAD(&to->m_pkthdr.tags, t, m_tag_link); 1067bca1dae6587a640359abee04337c0463b0a3893tuexen else 1068bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_INSERT_AFTER(tprev, t, m_tag_link); 1069bca1dae6587a640359abee04337c0463b0a3893tuexen tprev = t; 1070bca1dae6587a640359abee04337c0463b0a3893tuexen } 1071bca1dae6587a640359abee04337c0463b0a3893tuexen return 1; 1072bca1dae6587a640359abee04337c0463b0a3893tuexen} 1073bca1dae6587a640359abee04337c0463b0a3893tuexen 1074bca1dae6587a640359abee04337c0463b0a3893tuexen/* 1075bca1dae6587a640359abee04337c0463b0a3893tuexen * Duplicate "from"'s mbuf pkthdr in "to". 1076bca1dae6587a640359abee04337c0463b0a3893tuexen * "from" must have M_PKTHDR set, and "to" must be empty. 1077bca1dae6587a640359abee04337c0463b0a3893tuexen * In particular, this does a deep copy of the packet tags. 1078bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1079bca1dae6587a640359abee04337c0463b0a3893tuexenint 1080bca1dae6587a640359abee04337c0463b0a3893tuexenm_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how) 1081bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1082bca1dae6587a640359abee04337c0463b0a3893tuexen 1083bca1dae6587a640359abee04337c0463b0a3893tuexen to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); 1084bca1dae6587a640359abee04337c0463b0a3893tuexen if ((to->m_flags & M_EXT) == 0) 1085bca1dae6587a640359abee04337c0463b0a3893tuexen to->m_data = to->m_pktdat; 1086bca1dae6587a640359abee04337c0463b0a3893tuexen to->m_pkthdr = from->m_pkthdr; 1087bca1dae6587a640359abee04337c0463b0a3893tuexen SLIST_INIT(&to->m_pkthdr.tags); 1088bca1dae6587a640359abee04337c0463b0a3893tuexen return (m_tag_copy_chain(to, from, MBTOM(how))); 1089bca1dae6587a640359abee04337c0463b0a3893tuexen} 1090bca1dae6587a640359abee04337c0463b0a3893tuexen 1091bca1dae6587a640359abee04337c0463b0a3893tuexen/* Copy a single tag. */ 1092bca1dae6587a640359abee04337c0463b0a3893tuexenstruct m_tag * 1093bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_copy(struct m_tag *t, int how) 1094bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1095bca1dae6587a640359abee04337c0463b0a3893tuexen struct m_tag *p; 1096bca1dae6587a640359abee04337c0463b0a3893tuexen 1097c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(t, ("m_tag_copy: null tag")); 1098bca1dae6587a640359abee04337c0463b0a3893tuexen p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, how); 1099bca1dae6587a640359abee04337c0463b0a3893tuexen if (p == NULL) 1100bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 1101bca1dae6587a640359abee04337c0463b0a3893tuexen bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */ 1102bca1dae6587a640359abee04337c0463b0a3893tuexen return p; 1103bca1dae6587a640359abee04337c0463b0a3893tuexen} 1104bca1dae6587a640359abee04337c0463b0a3893tuexen 1105bca1dae6587a640359abee04337c0463b0a3893tuexen/* Get a packet tag structure along with specified data following. */ 1106bca1dae6587a640359abee04337c0463b0a3893tuexenstruct m_tag * 1107bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_alloc(u_int32_t cookie, int type, int len, int wait) 1108bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1109bca1dae6587a640359abee04337c0463b0a3893tuexen struct m_tag *t; 1110bca1dae6587a640359abee04337c0463b0a3893tuexen 1111bca1dae6587a640359abee04337c0463b0a3893tuexen if (len < 0) 1112bca1dae6587a640359abee04337c0463b0a3893tuexen return NULL; 1113bca1dae6587a640359abee04337c0463b0a3893tuexen t = malloc(len + sizeof(struct m_tag)); 1114bca1dae6587a640359abee04337c0463b0a3893tuexen if (t == NULL) 1115bca1dae6587a640359abee04337c0463b0a3893tuexen return NULL; 1116bca1dae6587a640359abee04337c0463b0a3893tuexen m_tag_setup(t, cookie, type, len); 1117bca1dae6587a640359abee04337c0463b0a3893tuexen t->m_tag_free = m_tag_free_default; 1118bca1dae6587a640359abee04337c0463b0a3893tuexen return t; 1119bca1dae6587a640359abee04337c0463b0a3893tuexen} 1120bca1dae6587a640359abee04337c0463b0a3893tuexen 1121bca1dae6587a640359abee04337c0463b0a3893tuexen/* Free a packet tag. */ 1122bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 1123bca1dae6587a640359abee04337c0463b0a3893tuexenm_tag_free_default(struct m_tag *t) 1124bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1125bca1dae6587a640359abee04337c0463b0a3893tuexen free(t); 1126bca1dae6587a640359abee04337c0463b0a3893tuexen} 1127bca1dae6587a640359abee04337c0463b0a3893tuexen 1128bca1dae6587a640359abee04337c0463b0a3893tuexen/* 1129bca1dae6587a640359abee04337c0463b0a3893tuexen * Copy data from a buffer back into the indicated mbuf chain, 1130bca1dae6587a640359abee04337c0463b0a3893tuexen * starting "off" bytes from the beginning, extending the mbuf 1131bca1dae6587a640359abee04337c0463b0a3893tuexen * chain if necessary. 1132bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1133bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 1134a89a6767416760e852d85b2db374f6eebc4e93d7tuexenm_copyback(struct mbuf *m0, int off, int len, caddr_t cp) 1135bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1136bca1dae6587a640359abee04337c0463b0a3893tuexen int mlen; 1137bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *m = m0, *n; 1138bca1dae6587a640359abee04337c0463b0a3893tuexen int totlen = 0; 1139bca1dae6587a640359abee04337c0463b0a3893tuexen 1140bca1dae6587a640359abee04337c0463b0a3893tuexen if (m0 == NULL) 1141bca1dae6587a640359abee04337c0463b0a3893tuexen return; 1142bca1dae6587a640359abee04337c0463b0a3893tuexen while (off > (mlen = m->m_len)) { 1143bca1dae6587a640359abee04337c0463b0a3893tuexen off -= mlen; 1144bca1dae6587a640359abee04337c0463b0a3893tuexen totlen += mlen; 1145bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_next == NULL) { 1146218d5d0df143e859e241afb12d6aaa1e4969d714t n = m_get(M_NOWAIT, m->m_type); 1147bca1dae6587a640359abee04337c0463b0a3893tuexen if (n == NULL) 1148bca1dae6587a640359abee04337c0463b0a3893tuexen goto out; 1149bca1dae6587a640359abee04337c0463b0a3893tuexen bzero(mtod(n, caddr_t), MLEN); 1150bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_len = min(MLEN, len + off); 1151bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = n; 1152bca1dae6587a640359abee04337c0463b0a3893tuexen } 1153bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1154bca1dae6587a640359abee04337c0463b0a3893tuexen } 1155bca1dae6587a640359abee04337c0463b0a3893tuexen while (len > 0) { 1156bca1dae6587a640359abee04337c0463b0a3893tuexen mlen = min (m->m_len - off, len); 1157bca1dae6587a640359abee04337c0463b0a3893tuexen bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen); 1158bca1dae6587a640359abee04337c0463b0a3893tuexen cp += mlen; 1159bca1dae6587a640359abee04337c0463b0a3893tuexen len -= mlen; 1160bca1dae6587a640359abee04337c0463b0a3893tuexen mlen += off; 1161bca1dae6587a640359abee04337c0463b0a3893tuexen off = 0; 1162bca1dae6587a640359abee04337c0463b0a3893tuexen totlen += mlen; 1163bca1dae6587a640359abee04337c0463b0a3893tuexen if (len == 0) 1164bca1dae6587a640359abee04337c0463b0a3893tuexen break; 1165bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_next == NULL) { 1166218d5d0df143e859e241afb12d6aaa1e4969d714t n = m_get(M_NOWAIT, m->m_type); 1167bca1dae6587a640359abee04337c0463b0a3893tuexen if (n == NULL) 1168bca1dae6587a640359abee04337c0463b0a3893tuexen break; 1169bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_len = min(MLEN, len); 1170bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = n; 1171bca1dae6587a640359abee04337c0463b0a3893tuexen } 1172bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1173bca1dae6587a640359abee04337c0463b0a3893tuexen } 1174bca1dae6587a640359abee04337c0463b0a3893tuexenout: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) 1175bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.len = totlen; 1176bca1dae6587a640359abee04337c0463b0a3893tuexen} 1177bca1dae6587a640359abee04337c0463b0a3893tuexen 1178bca1dae6587a640359abee04337c0463b0a3893tuexen 1179bca1dae6587a640359abee04337c0463b0a3893tuexen/* 1180bca1dae6587a640359abee04337c0463b0a3893tuexen * Lesser-used path for M_PREPEND: 1181bca1dae6587a640359abee04337c0463b0a3893tuexen * allocate new mbuf to prepend to chain, 1182bca1dae6587a640359abee04337c0463b0a3893tuexen * copy junk along. 1183bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1184bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf * 1185bca1dae6587a640359abee04337c0463b0a3893tuexenm_prepend(struct mbuf *m, int len, int how) 1186bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1187bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *mn; 1188bca1dae6587a640359abee04337c0463b0a3893tuexen 1189bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_PKTHDR) 1190bca1dae6587a640359abee04337c0463b0a3893tuexen MGETHDR(mn, how, m->m_type); 1191bca1dae6587a640359abee04337c0463b0a3893tuexen else 1192bca1dae6587a640359abee04337c0463b0a3893tuexen MGET(mn, how, m->m_type); 1193bca1dae6587a640359abee04337c0463b0a3893tuexen if (mn == NULL) { 1194bca1dae6587a640359abee04337c0463b0a3893tuexen m_freem(m); 1195bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 1196bca1dae6587a640359abee04337c0463b0a3893tuexen } 1197bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_PKTHDR) 1198bca1dae6587a640359abee04337c0463b0a3893tuexen M_MOVE_PKTHDR(mn, m); 1199bca1dae6587a640359abee04337c0463b0a3893tuexen mn->m_next = m; 1200bca1dae6587a640359abee04337c0463b0a3893tuexen m = mn; 1201bca1dae6587a640359abee04337c0463b0a3893tuexen if(m->m_flags & M_PKTHDR) { 1202bca1dae6587a640359abee04337c0463b0a3893tuexen if (len < MHLEN) 1203bca1dae6587a640359abee04337c0463b0a3893tuexen MH_ALIGN(m, len); 1204bca1dae6587a640359abee04337c0463b0a3893tuexen } else { 120542d0ec7a8a09fcaa90b491d267245606c7caa7edtuexen if (len < MLEN) 1206bca1dae6587a640359abee04337c0463b0a3893tuexen M_ALIGN(m, len); 1207bca1dae6587a640359abee04337c0463b0a3893tuexen } 1208bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len = len; 1209bca1dae6587a640359abee04337c0463b0a3893tuexen return (m); 1210bca1dae6587a640359abee04337c0463b0a3893tuexen} 1211bca1dae6587a640359abee04337c0463b0a3893tuexen 1212bca1dae6587a640359abee04337c0463b0a3893tuexen/* 1213bca1dae6587a640359abee04337c0463b0a3893tuexen * Copy data from an mbuf chain starting "off" bytes from the beginning, 1214bca1dae6587a640359abee04337c0463b0a3893tuexen * continuing for "len" bytes, into the indicated buffer. 1215bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1216bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 1217bca1dae6587a640359abee04337c0463b0a3893tuexenm_copydata(const struct mbuf *m, int off, int len, caddr_t cp) 1218bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1219bca1dae6587a640359abee04337c0463b0a3893tuexen u_int count; 1220bca1dae6587a640359abee04337c0463b0a3893tuexen 1221c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(off >= 0, ("m_copydata, negative off %d", off)); 1222c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(len >= 0, ("m_copydata, negative len %d", len)); 1223bca1dae6587a640359abee04337c0463b0a3893tuexen while (off > 0) { 1224c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(m != NULL, ("m_copydata, offset > size of mbuf chain")); 1225bca1dae6587a640359abee04337c0463b0a3893tuexen if (off < m->m_len) 1226bca1dae6587a640359abee04337c0463b0a3893tuexen break; 1227bca1dae6587a640359abee04337c0463b0a3893tuexen off -= m->m_len; 1228bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1229bca1dae6587a640359abee04337c0463b0a3893tuexen } 1230bca1dae6587a640359abee04337c0463b0a3893tuexen while (len > 0) { 1231c7108437de5af4d0b9f9a24979710b39197ec6cetuexen KASSERT(m != NULL, ("m_copydata, length > size of mbuf chain")); 1232bca1dae6587a640359abee04337c0463b0a3893tuexen count = min(m->m_len - off, len); 1233bca1dae6587a640359abee04337c0463b0a3893tuexen bcopy(mtod(m, caddr_t) + off, cp, count); 1234bca1dae6587a640359abee04337c0463b0a3893tuexen len -= count; 1235bca1dae6587a640359abee04337c0463b0a3893tuexen cp += count; 1236bca1dae6587a640359abee04337c0463b0a3893tuexen off = 0; 1237bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1238bca1dae6587a640359abee04337c0463b0a3893tuexen } 1239bca1dae6587a640359abee04337c0463b0a3893tuexen} 1240bca1dae6587a640359abee04337c0463b0a3893tuexen 1241bca1dae6587a640359abee04337c0463b0a3893tuexen 1242bca1dae6587a640359abee04337c0463b0a3893tuexen/* 1243bca1dae6587a640359abee04337c0463b0a3893tuexen * Concatenate mbuf chain n to m. 1244bca1dae6587a640359abee04337c0463b0a3893tuexen * Both chains must be of the same type (e.g. MT_DATA). 1245bca1dae6587a640359abee04337c0463b0a3893tuexen * Any m_pkthdr is not updated. 1246bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1247bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 1248bca1dae6587a640359abee04337c0463b0a3893tuexenm_cat(struct mbuf *m, struct mbuf *n) 1249bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1250c7108437de5af4d0b9f9a24979710b39197ec6cetuexen while (m->m_next) 1251c7108437de5af4d0b9f9a24979710b39197ec6cetuexen m = m->m_next; 1252c7108437de5af4d0b9f9a24979710b39197ec6cetuexen while (n) { 1253c7108437de5af4d0b9f9a24979710b39197ec6cetuexen if (m->m_flags & M_EXT || 1254c7108437de5af4d0b9f9a24979710b39197ec6cetuexen m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { 1255c7108437de5af4d0b9f9a24979710b39197ec6cetuexen /* just join the two chains */ 1256c7108437de5af4d0b9f9a24979710b39197ec6cetuexen m->m_next = n; 1257c7108437de5af4d0b9f9a24979710b39197ec6cetuexen return; 1258c7108437de5af4d0b9f9a24979710b39197ec6cetuexen } 1259c7108437de5af4d0b9f9a24979710b39197ec6cetuexen /* splat the data from one into the other */ 1260c7108437de5af4d0b9f9a24979710b39197ec6cetuexen bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, (u_int)n->m_len); 1261c7108437de5af4d0b9f9a24979710b39197ec6cetuexen m->m_len += n->m_len; 1262c7108437de5af4d0b9f9a24979710b39197ec6cetuexen n = m_free(n); 1263c7108437de5af4d0b9f9a24979710b39197ec6cetuexen } 1264bca1dae6587a640359abee04337c0463b0a3893tuexen} 1265bca1dae6587a640359abee04337c0463b0a3893tuexen 1266bca1dae6587a640359abee04337c0463b0a3893tuexen 1267bca1dae6587a640359abee04337c0463b0a3893tuexenvoid 1268bca1dae6587a640359abee04337c0463b0a3893tuexenm_adj(struct mbuf *mp, int req_len) 1269bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1270bca1dae6587a640359abee04337c0463b0a3893tuexen int len = req_len; 1271bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *m; 1272bca1dae6587a640359abee04337c0463b0a3893tuexen int count; 1273bca1dae6587a640359abee04337c0463b0a3893tuexen 1274bca1dae6587a640359abee04337c0463b0a3893tuexen if ((m = mp) == NULL) 1275bca1dae6587a640359abee04337c0463b0a3893tuexen return; 1276bca1dae6587a640359abee04337c0463b0a3893tuexen if (len >= 0) { 1277bca1dae6587a640359abee04337c0463b0a3893tuexen /* 1278bca1dae6587a640359abee04337c0463b0a3893tuexen * Trim from head. 1279bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1280bca1dae6587a640359abee04337c0463b0a3893tuexen while (m != NULL && len > 0) { 1281bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_len <= len) { 1282bca1dae6587a640359abee04337c0463b0a3893tuexen len -= m->m_len; 1283bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len = 0; 1284bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1285bca1dae6587a640359abee04337c0463b0a3893tuexen } else { 1286bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len -= len; 1287bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_data += len; 1288bca1dae6587a640359abee04337c0463b0a3893tuexen len = 0; 1289bca1dae6587a640359abee04337c0463b0a3893tuexen } 1290bca1dae6587a640359abee04337c0463b0a3893tuexen } 1291bca1dae6587a640359abee04337c0463b0a3893tuexen m = mp; 1292bca1dae6587a640359abee04337c0463b0a3893tuexen if (mp->m_flags & M_PKTHDR) 1293bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.len -= (req_len - len); 1294bca1dae6587a640359abee04337c0463b0a3893tuexen } else { 1295bca1dae6587a640359abee04337c0463b0a3893tuexen /* 1296bca1dae6587a640359abee04337c0463b0a3893tuexen * Trim from tail. Scan the mbuf chain, 1297bca1dae6587a640359abee04337c0463b0a3893tuexen * calculating its length and finding the last mbuf. 1298bca1dae6587a640359abee04337c0463b0a3893tuexen * If the adjustment only affects this mbuf, then just 1299bca1dae6587a640359abee04337c0463b0a3893tuexen * adjust and return. Otherwise, rescan and truncate 1300bca1dae6587a640359abee04337c0463b0a3893tuexen * after the remaining size. 1301bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1302bca1dae6587a640359abee04337c0463b0a3893tuexen len = -len; 1303bca1dae6587a640359abee04337c0463b0a3893tuexen count = 0; 1304bca1dae6587a640359abee04337c0463b0a3893tuexen for (;;) { 1305bca1dae6587a640359abee04337c0463b0a3893tuexen count += m->m_len; 1306bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_next == (struct mbuf *)0) 1307bca1dae6587a640359abee04337c0463b0a3893tuexen break; 1308bca1dae6587a640359abee04337c0463b0a3893tuexen m = m->m_next; 1309bca1dae6587a640359abee04337c0463b0a3893tuexen } 1310bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_len >= len) { 1311bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len -= len; 1312bca1dae6587a640359abee04337c0463b0a3893tuexen if (mp->m_flags & M_PKTHDR) 1313bca1dae6587a640359abee04337c0463b0a3893tuexen mp->m_pkthdr.len -= len; 1314bca1dae6587a640359abee04337c0463b0a3893tuexen return; 1315bca1dae6587a640359abee04337c0463b0a3893tuexen } 1316bca1dae6587a640359abee04337c0463b0a3893tuexen count -= len; 1317bca1dae6587a640359abee04337c0463b0a3893tuexen if (count < 0) 1318bca1dae6587a640359abee04337c0463b0a3893tuexen count = 0; 1319bca1dae6587a640359abee04337c0463b0a3893tuexen /* 1320bca1dae6587a640359abee04337c0463b0a3893tuexen * Correct length for chain is "count". 1321bca1dae6587a640359abee04337c0463b0a3893tuexen * Find the mbuf with last data, adjust its length, 1322bca1dae6587a640359abee04337c0463b0a3893tuexen * and toss data from remaining mbufs on chain. 1323bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1324bca1dae6587a640359abee04337c0463b0a3893tuexen m = mp; 1325bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_PKTHDR) 1326bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_pkthdr.len = count; 1327bca1dae6587a640359abee04337c0463b0a3893tuexen for (; m; m = m->m_next) { 1328bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_len >= count) { 1329bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len = count; 1330bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_next != NULL) { 1331bca1dae6587a640359abee04337c0463b0a3893tuexen m_freem(m->m_next); 1332bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = NULL; 1333bca1dae6587a640359abee04337c0463b0a3893tuexen } 1334bca1dae6587a640359abee04337c0463b0a3893tuexen break; 1335bca1dae6587a640359abee04337c0463b0a3893tuexen } 1336bca1dae6587a640359abee04337c0463b0a3893tuexen count -= m->m_len; 1337bca1dae6587a640359abee04337c0463b0a3893tuexen } 1338bca1dae6587a640359abee04337c0463b0a3893tuexen } 1339bca1dae6587a640359abee04337c0463b0a3893tuexen} 1340bca1dae6587a640359abee04337c0463b0a3893tuexen 1341bca1dae6587a640359abee04337c0463b0a3893tuexen 1342bca1dae6587a640359abee04337c0463b0a3893tuexen/* m_split is used within sctp_handle_cookie_echo. */ 1343bca1dae6587a640359abee04337c0463b0a3893tuexen 1344bca1dae6587a640359abee04337c0463b0a3893tuexen/* 1345bca1dae6587a640359abee04337c0463b0a3893tuexen * Partition an mbuf chain in two pieces, returning the tail -- 1346bca1dae6587a640359abee04337c0463b0a3893tuexen * all but the first len0 bytes. In case of failure, it returns NULL and 1347bca1dae6587a640359abee04337c0463b0a3893tuexen * attempts to restore the chain to its original state. 1348bca1dae6587a640359abee04337c0463b0a3893tuexen * 1349bca1dae6587a640359abee04337c0463b0a3893tuexen * Note that the resulting mbufs might be read-only, because the new 1350bca1dae6587a640359abee04337c0463b0a3893tuexen * mbuf can end up sharing an mbuf cluster with the original mbuf if 1351bca1dae6587a640359abee04337c0463b0a3893tuexen * the "breaking point" happens to lie within a cluster mbuf. Use the 1352bca1dae6587a640359abee04337c0463b0a3893tuexen * M_WRITABLE() macro to check for this case. 1353bca1dae6587a640359abee04337c0463b0a3893tuexen */ 1354bca1dae6587a640359abee04337c0463b0a3893tuexenstruct mbuf * 1355bca1dae6587a640359abee04337c0463b0a3893tuexenm_split(struct mbuf *m0, int len0, int wait) 1356bca1dae6587a640359abee04337c0463b0a3893tuexen{ 1357bca1dae6587a640359abee04337c0463b0a3893tuexen struct mbuf *m, *n; 1358bca1dae6587a640359abee04337c0463b0a3893tuexen u_int len = len0, remain; 1359bca1dae6587a640359abee04337c0463b0a3893tuexen 1360bca1dae6587a640359abee04337c0463b0a3893tuexen /* MBUF_CHECKSLEEP(wait); */ 1361968138a650335b8836df7433026face9535f9641t for (m = m0; m && (int)len > m->m_len; m = m->m_next) 1362bca1dae6587a640359abee04337c0463b0a3893tuexen len -= m->m_len; 1363bca1dae6587a640359abee04337c0463b0a3893tuexen if (m == NULL) 1364bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 1365bca1dae6587a640359abee04337c0463b0a3893tuexen remain = m->m_len - len; 1366bca1dae6587a640359abee04337c0463b0a3893tuexen if (m0->m_flags & M_PKTHDR) { 1367bca1dae6587a640359abee04337c0463b0a3893tuexen MGETHDR(n, wait, m0->m_type); 1368bca1dae6587a640359abee04337c0463b0a3893tuexen if (n == NULL) 1369bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 1370bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif; 1371bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_pkthdr.len = m0->m_pkthdr.len - len0; 1372bca1dae6587a640359abee04337c0463b0a3893tuexen m0->m_pkthdr.len = len0; 1373bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_EXT) 1374bca1dae6587a640359abee04337c0463b0a3893tuexen goto extpacket; 1375bca1dae6587a640359abee04337c0463b0a3893tuexen if (remain > MHLEN) { 1376bca1dae6587a640359abee04337c0463b0a3893tuexen /* m can't be the lead packet */ 1377bca1dae6587a640359abee04337c0463b0a3893tuexen MH_ALIGN(n, 0); 1378bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_next = m_split(m, len, wait); 1379bca1dae6587a640359abee04337c0463b0a3893tuexen if (n->m_next == NULL) { 1380bca1dae6587a640359abee04337c0463b0a3893tuexen (void) m_free(n); 1381bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 1382bca1dae6587a640359abee04337c0463b0a3893tuexen } else { 1383bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_len = 0; 1384bca1dae6587a640359abee04337c0463b0a3893tuexen return (n); 1385bca1dae6587a640359abee04337c0463b0a3893tuexen } 1386bca1dae6587a640359abee04337c0463b0a3893tuexen } else 1387bca1dae6587a640359abee04337c0463b0a3893tuexen MH_ALIGN(n, remain); 1388bca1dae6587a640359abee04337c0463b0a3893tuexen } else if (remain == 0) { 1389bca1dae6587a640359abee04337c0463b0a3893tuexen n = m->m_next; 1390bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = NULL; 1391bca1dae6587a640359abee04337c0463b0a3893tuexen return (n); 1392bca1dae6587a640359abee04337c0463b0a3893tuexen } else { 1393bca1dae6587a640359abee04337c0463b0a3893tuexen MGET(n, wait, m->m_type); 1394bca1dae6587a640359abee04337c0463b0a3893tuexen if (n == NULL) 1395bca1dae6587a640359abee04337c0463b0a3893tuexen return (NULL); 1396bca1dae6587a640359abee04337c0463b0a3893tuexen M_ALIGN(n, remain); 1397bca1dae6587a640359abee04337c0463b0a3893tuexen } 1398bca1dae6587a640359abee04337c0463b0a3893tuexenextpacket: 1399bca1dae6587a640359abee04337c0463b0a3893tuexen if (m->m_flags & M_EXT) { 1400bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_data = m->m_data + len; 1401bca1dae6587a640359abee04337c0463b0a3893tuexen mb_dupcl(n, m); 1402bca1dae6587a640359abee04337c0463b0a3893tuexen } else { 1403bca1dae6587a640359abee04337c0463b0a3893tuexen bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); 1404bca1dae6587a640359abee04337c0463b0a3893tuexen } 1405bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_len = remain; 1406bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_len = len; 1407bca1dae6587a640359abee04337c0463b0a3893tuexen n->m_next = m->m_next; 1408bca1dae6587a640359abee04337c0463b0a3893tuexen m->m_next = NULL; 1409bca1dae6587a640359abee04337c0463b0a3893tuexen return (n); 1410bca1dae6587a640359abee04337c0463b0a3893tuexen} 1411bca1dae6587a640359abee04337c0463b0a3893tuexen 1412bca1dae6587a640359abee04337c0463b0a3893tuexen 1413bca1dae6587a640359abee04337c0463b0a3893tuexen 1414bca1dae6587a640359abee04337c0463b0a3893tuexen 14159cf3035a03978648d38588875628f98f41deb0cetuexenint 14169cf3035a03978648d38588875628f98f41deb0cetuexenpack_send_buffer(caddr_t buffer, struct mbuf* mb){ 14179cf3035a03978648d38588875628f98f41deb0cetuexen 14189cf3035a03978648d38588875628f98f41deb0cetuexen int count_to_copy; 14199cf3035a03978648d38588875628f98f41deb0cetuexen int total_count_copied = 0; 14209cf3035a03978648d38588875628f98f41deb0cetuexen int offset = 0; 1421bca1dae6587a640359abee04337c0463b0a3893tuexen 1422c7108437de5af4d0b9f9a24979710b39197ec6cetuexen do { 14239cf3035a03978648d38588875628f98f41deb0cetuexen count_to_copy = mb->m_len; 14249cf3035a03978648d38588875628f98f41deb0cetuexen bcopy(mtod(mb, caddr_t), buffer+offset, count_to_copy); 14259cf3035a03978648d38588875628f98f41deb0cetuexen offset += count_to_copy; 14269cf3035a03978648d38588875628f98f41deb0cetuexen total_count_copied += count_to_copy; 14279cf3035a03978648d38588875628f98f41deb0cetuexen mb = mb->m_next; 1428c7108437de5af4d0b9f9a24979710b39197ec6cetuexen } while(mb); 1429bca1dae6587a640359abee04337c0463b0a3893tuexen 14309cf3035a03978648d38588875628f98f41deb0cetuexen return (total_count_copied); 1431bca1dae6587a640359abee04337c0463b0a3893tuexen} 1432