The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/uipc_mbuf2.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*      $NetBSD: uipc_mbuf.c,v 1.40 1999/04/01 00:23:25 thorpej Exp $   */
   26 
   27 /*
   28  * Copyright (C) 1999 WIDE Project.
   29  * All rights reserved.
   30  * 
   31  * Redistribution and use in source and binary forms, with or without
   32  * modification, are permitted provided that the following conditions
   33  * are met:
   34  * 1. Redistributions of source code must retain the above copyright
   35  *    notice, this list of conditions and the following disclaimer.
   36  * 2. Redistributions in binary form must reproduce the above copyright
   37  *    notice, this list of conditions and the following disclaimer in the
   38  *    documentation and/or other materials provided with the distribution.
   39  * 3. Neither the name of the project nor the names of its contributors
   40  *    may be used to endorse or promote products derived from this software
   41  *    without specific prior written permission.
   42  * 
   43  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   44  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   46  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   47  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   48  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   49  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   50  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   51  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   52  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   53  * SUCH DAMAGE.
   54  */
   55 
   56 /*
   57  * Copyright (c) 1982, 1986, 1988, 1991, 1993
   58  *      The Regents of the University of California.  All rights reserved.
   59  *
   60  * Redistribution and use in source and binary forms, with or without
   61  * modification, are permitted provided that the following conditions
   62  * are met:
   63  * 1. Redistributions of source code must retain the above copyright
   64  *    notice, this list of conditions and the following disclaimer.
   65  * 2. Redistributions in binary form must reproduce the above copyright
   66  *    notice, this list of conditions and the following disclaimer in the
   67  *    documentation and/or other materials provided with the distribution.
   68  * 3. All advertising materials mentioning features or use of this software
   69  *    must display the following acknowledgement:
   70  *      This product includes software developed by the University of
   71  *      California, Berkeley and its contributors.
   72  * 4. Neither the name of the University nor the names of its contributors
   73  *    may be used to endorse or promote products derived from this software
   74  *    without specific prior written permission.
   75  *
   76  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   77  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   78  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   79  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   80  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   81  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   82  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   83  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   84  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   85  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   86  * SUCH DAMAGE.
   87  *
   88  *      @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95
   89  */
   90 
   91 
   92 /*#define PULLDOWN_DEBUG*/
   93 
   94 #include <sys/param.h>
   95 #include <sys/systm.h>
   96 #include <sys/proc.h>
   97 #include <sys/malloc.h>
   98 #include <sys/mbuf.h>
   99 #if defined(PULLDOWN_STAT) && defined(INET6)
  100 #include <netinet/in.h>
  101 #include <netinet/ip6.h>
  102 #include <netinet6/ip6_var.h>
  103 #endif
  104 
  105 /*
  106  * ensure that [off, off + len) is contiguous on the mbuf chain "m".
  107  * packet chain before "off" is kept untouched.
  108  * if offp == NULL, the target will start at <retval, 0> on resulting chain.
  109  * if offp != NULL, the target will start at <retval, *offp> on resulting chain.
  110  *
  111  * on error return (NULL return value), original "m" will be freed.
  112  *
  113  * XXX M_TRAILINGSPACE/M_LEADINGSPACE on shared cluster (sharedcluster)
  114  */
  115 struct mbuf *
  116 m_pulldown(m, off, len, offp)
  117         struct mbuf *m;
  118         int off, len;
  119         int *offp;
  120 {
  121         struct mbuf *n, *o;
  122         int hlen, tlen, olen;
  123         int sharedcluster;
  124 #if defined(PULLDOWN_STAT) && defined(INET6)
  125         static struct mbuf *prev = NULL;
  126         int prevlen = 0, prevmlen = 0;
  127 #endif
  128 
  129         /* check invalid arguments. */
  130         if (m == NULL)
  131                 panic("m == NULL in m_pulldown()");
  132         if (len > MCLBYTES) {
  133                 m_freem(m);
  134                 return NULL;    /* impossible */
  135         }
  136 
  137 #if defined(PULLDOWN_STAT) && defined(INET6)
  138         ip6stat.ip6s_pulldown++;
  139 #endif
  140 
  141 #if defined(PULLDOWN_STAT) && defined(INET6)
  142         /* statistics for m_pullup */
  143         ip6stat.ip6s_pullup++;
  144         if (off + len > MHLEN)
  145                 ip6stat.ip6s_pullup_fail++;
  146         else {
  147                 int dlen, mlen;
  148 
  149                 dlen = (prev == m) ? prevlen : m->m_len;
  150                 mlen = (prev == m) ? prevmlen : m->m_len + M_TRAILINGSPACE(m);
  151 
  152                 if (dlen >= off + len)
  153                         ip6stat.ip6s_pullup--; /* call will not be made! */
  154                 else if ((m->m_flags & M_EXT) != 0) {
  155                         ip6stat.ip6s_pullup_alloc++;
  156                         ip6stat.ip6s_pullup_copy++;
  157                 } else {
  158                         if (mlen >= off + len)
  159                                 ip6stat.ip6s_pullup_copy++;
  160                         else {
  161                                 ip6stat.ip6s_pullup_alloc++;
  162                                 ip6stat.ip6s_pullup_copy++;
  163                         }
  164                 }
  165 
  166                 prevlen = off + len;
  167                 prevmlen = MHLEN;
  168         }
  169 
  170         /* statistics for m_pullup2 */
  171         ip6stat.ip6s_pullup2++;
  172         if (off + len > MCLBYTES)
  173                 ip6stat.ip6s_pullup2_fail++;
  174         else {
  175                 int dlen, mlen;
  176 
  177                 dlen = (prev == m) ? prevlen : m->m_len;
  178                 mlen = (prev == m) ? prevmlen : m->m_len + M_TRAILINGSPACE(m);
  179                 prevlen = off + len;
  180                 prevmlen = mlen;
  181 
  182                 if (dlen >= off + len)
  183                         ip6stat.ip6s_pullup2--; /* call will not be made! */
  184                 else if ((m->m_flags & M_EXT) != 0) {
  185                         ip6stat.ip6s_pullup2_alloc++;
  186                         ip6stat.ip6s_pullup2_copy++;
  187                         prevmlen = (off + len > MHLEN) ? MCLBYTES : MHLEN;
  188                 } else {
  189                         if (mlen >= off + len)
  190                                 ip6stat.ip6s_pullup2_copy++;
  191                         else {
  192                                 ip6stat.ip6s_pullup2_alloc++;
  193                                 ip6stat.ip6s_pullup2_copy++;
  194                                 prevmlen = (off + len > MHLEN) ? MCLBYTES
  195                                                                : MHLEN;
  196                         }
  197                 }
  198         }
  199 
  200         prev = m;
  201 #endif
  202 
  203 #ifdef PULLDOWN_DEBUG
  204     {
  205         struct mbuf *t;
  206         printf("before:");
  207         for (t = m; t; t = t->m_next)
  208                 printf(" %d", t->m_len);
  209         printf("\n");
  210     }
  211 #endif
  212         n = m;
  213         while (n != NULL && off > 0) {
  214                 if (n->m_len > off)
  215                         break;
  216                 off -= n->m_len;
  217                 n = n->m_next;
  218         }
  219         /* be sure to point non-empty mbuf */
  220         while (n != NULL && n->m_len == 0)
  221                 n = n->m_next;
  222         if (!n) {
  223                 m_freem(m);
  224                 return NULL;    /* mbuf chain too short */
  225         }
  226 
  227         /*
  228          * the target data is on <n, off>.
  229          * if we got enough data on the mbuf "n", we're done.
  230          */
  231         if ((off == 0 || offp) && len <= n->m_len - off)
  232                 goto ok;
  233 
  234 #if defined(PULLDOWN_STAT) && defined(INET6)
  235         ip6stat.ip6s_pulldown_copy++;
  236 #endif
  237 
  238         /*
  239          * when len < n->m_len - off and off != 0, it is a special case.
  240          * len bytes from <n, off> sits in single mbuf, but the caller does
  241          * not like the starting position (off).
  242          * chop the current mbuf into two pieces, set off to 0.
  243          */
  244         if (len < n->m_len - off) {
  245                 o = m_copym(n, off, n->m_len - off, M_DONTWAIT);
  246                 if (o == NULL) {
  247                         m_freem(m);
  248                         return NULL;    /* ENOBUFS */
  249                 }
  250                 n->m_len = off;
  251                 o->m_next = n->m_next;
  252                 n->m_next = o;
  253                 n = n->m_next;
  254                 off = 0;
  255                 goto ok;
  256         }
  257 
  258         /*
  259          * we need to take hlen from <n, off> and tlen from <n->m_next, 0>,
  260          * and construct contiguous mbuf with m_len == len.
  261          * note that hlen + tlen == len, and tlen > 0.
  262          */
  263         hlen = n->m_len - off;
  264         tlen = len - hlen;
  265 
  266         /*
  267          * ensure that we have enough trailing data on mbuf chain.
  268          * if not, we can do nothing about the chain.
  269          */
  270         olen = 0;
  271         for (o = n->m_next; o != NULL; o = o->m_next)
  272                 olen += o->m_len;
  273         if (hlen + olen < len) {
  274                 m_freem(m);
  275                 return NULL;    /* mbuf chain too short */
  276         }
  277 
  278         /*
  279          * easy cases first.
  280          * we need to use m_copydata() to get data from <n->m_next, 0>.
  281          */
  282         if ((n->m_flags & M_EXT) == 0)
  283                 sharedcluster = 0;
  284         else {
  285 #ifdef __bsdi__
  286                 if (n->m_ext.ext_func)
  287 #else
  288                 if (n->m_ext.ext_free)
  289 #endif
  290                         sharedcluster = 1;
  291 #ifdef __NetBSD__
  292                 else if (MCLISREFERENCED(n))
  293 #else
  294                 else if (mclrefcnt[mtocl(n->m_ext.ext_buf)] > 1)
  295 #endif
  296                         sharedcluster = 1;
  297                 else
  298                         sharedcluster = 0;
  299         }
  300         if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen
  301          && !sharedcluster) {
  302                 m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
  303                 n->m_len += tlen;
  304                 m_adj(n->m_next, tlen);
  305                 goto ok;
  306         }
  307         if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen
  308          && !sharedcluster) {
  309                 n->m_next->m_data -= hlen;
  310                 n->m_next->m_len += hlen;
  311                 bcopy(mtod(n, caddr_t) + off, mtod(n->m_next, caddr_t), hlen);
  312                 n->m_len -= hlen;
  313                 n = n->m_next;
  314                 off = 0;
  315                 goto ok;
  316         }
  317 
  318         /*
  319          * now, we need to do the hard way.  don't m_copy as there's no room
  320          * on both end.
  321          */
  322 #if defined(PULLDOWN_STAT) && defined(INET6)
  323         ip6stat.ip6s_pulldown_alloc++;
  324 #endif
  325         MGET(o, M_DONTWAIT, m->m_type);
  326         if (o == NULL) {
  327                 m_freem(m);
  328                 return NULL;    /* ENOBUFS */
  329         }
  330         if (len > MHLEN) {      /* use MHLEN just for safety */
  331                 MCLGET(o, M_DONTWAIT);
  332                 if ((o->m_flags & M_EXT) == 0) {
  333                         m_freem(m);
  334                         m_free(o);
  335                         return NULL;    /* ENOBUFS */
  336                 }
  337         }
  338         /* get hlen from <n, off> into <o, 0> */
  339         o->m_len = hlen;
  340         bcopy(mtod(n, caddr_t) + off, mtod(o, caddr_t), hlen);
  341         n->m_len -= hlen;
  342         /* get tlen from <n->m_next, 0> into <o, hlen> */
  343         m_copydata(n->m_next, 0, tlen, mtod(o, caddr_t) + o->m_len);
  344         o->m_len += tlen;
  345         m_adj(n->m_next, tlen);
  346         o->m_next = n->m_next;
  347         n->m_next = o;
  348         n = o;
  349         off = 0;
  350 
  351 ok:
  352 #ifdef PULLDOWN_DEBUG
  353     {
  354         struct mbuf *t;
  355         printf("after:");
  356         for (t = m; t; t = t->m_next)
  357                 printf("%c%d", t == n ? '*' : ' ', t->m_len);
  358         printf(" (off=%d)\n", off);
  359     }
  360 #endif
  361         if (offp)
  362                 *offp = off;
  363         return n;
  364 }
  365 
  366 /*
  367  * pkthdr.aux chain manipulation.
  368  * we don't allow clusters at this moment. 
  369  */
  370 struct mbuf *
  371 m_aux_add(m, af, type)
  372         struct mbuf *m;
  373         int af, type;
  374 {
  375         struct mbuf *n;
  376         struct mauxtag *t;
  377 
  378         if ((m->m_flags & M_PKTHDR) == 0)
  379                 return NULL;
  380 
  381         n = m_aux_find(m, af, type);
  382         if (n)
  383                 return n;
  384 
  385         MGET(n, M_DONTWAIT, m->m_type);
  386         if (n == NULL)
  387                 return NULL;
  388 
  389         t = mtod(n, struct mauxtag *);
  390         t->af = af;
  391         t->type = type;
  392         n->m_data += sizeof(struct mauxtag);
  393         n->m_len = 0;
  394         n->m_next = m->m_pkthdr.aux;
  395         m->m_pkthdr.aux = n;
  396         return n;
  397 }
  398 
  399 struct mbuf *
  400 m_aux_find(m, af, type)
  401         struct mbuf *m;
  402         int af, type;
  403 {
  404         struct mbuf *n;
  405         struct mauxtag *t;
  406 
  407         if ((m->m_flags & M_PKTHDR) == 0)
  408                 return NULL;
  409 
  410         for (n = m->m_pkthdr.aux; n; n = n->m_next) {
  411                 t = (struct mauxtag *)n->m_dat;
  412                 if (t->af == af && t->type == type)
  413                         return n;
  414         }
  415         return NULL;
  416 }
  417 
  418 void
  419 m_aux_delete(m, victim)
  420         struct mbuf *m;
  421         struct mbuf *victim;
  422 {
  423         struct mbuf *n, *prev, *next;
  424         struct mauxtag *t;
  425 
  426         if ((m->m_flags & M_PKTHDR) == 0)
  427                 return;
  428 
  429         prev = NULL;
  430         n = m->m_pkthdr.aux;
  431         while (n) {
  432                 t = (struct mauxtag *)n->m_dat;
  433                 next = n->m_next;
  434                 if (n == victim) {
  435                         if (prev)
  436                                 prev->m_next = n->m_next;
  437                         else
  438                                 m->m_pkthdr.aux = n->m_next;
  439                         n->m_next = NULL;
  440                         m_free(n);
  441                 } else
  442                         prev = n;
  443                 n = next;
  444         }
  445 }

Cache object: 4a6f0ea1cae0770301793a8b9a9d5755


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.