2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
27 * Copyright (c) 1982, 1986, 1988, 1991, 1993
28 * The Regents of the University of California. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
62 * 10/15/97 Annette DeSchon (deschon@apple.com)
63 * Fixed bug in which all cluster mbufs were broken up
64 * into regular mbufs: Some clusters are now reserved.
65 * When a cluster is needed, regular mbufs are no longer
66 * used. (Radar 1683621)
67 * 20-May-95 Mac Gillon (mgillon) at NeXT
68 * New version based on 4.4
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/malloc.h>
75 #include <sys/kernel.h>
76 #include <sys/syslog.h>
77 #include <sys/protosw.h>
78 #include <sys/domain.h>
79 #include <net/netisr.h>
81 #include <kern/queue.h>
82 #include <kern/kern_types.h>
83 #include <kern/sched_prim.h>
85 #define _MCLREF(p) (++mclrefcnt[mtocl(p)])
86 #define _MCLUNREF(p) (--mclrefcnt[mtocl(p)] == 0)
88 extern kernel_pmap
; /* The kernel's pmap */
90 decl_simple_lock_data(, mbuf_slock
);
91 struct mbuf
*mfree
; /* mbuf free list */
92 struct mbuf
*mfreelater
; /* mbuf deallocation list */
93 extern vm_map_t mb_map
; /* special map */
94 int m_want
; /* sleepers on mbufs */
95 extern int nmbclusters
; /* max number of mapped clusters */
96 short *mclrefcnt
; /* mapped cluster reference counts */
98 union mcluster
*mclfree
; /* mapped cluster free list */
99 int max_linkhdr
; /* largest link-level header */
100 int max_protohdr
; /* largest protocol header */
101 int max_hdr
; /* largest link+protocol header */
102 int max_datalen
; /* MHLEN - max_hdr */
103 struct mbstat mbstat
; /* statistics */
104 union mcluster
*mbutl
; /* first mapped cluster address */
105 union mcluster
*embutl
; /* ending virtual address of mclusters */
107 static int nclpp
; /* # clusters per physical page */
108 static char mbfail
[] = "mbuf not mapped";
110 static int m_howmany();
112 /* The number of cluster mbufs that are allocated, to start. */
113 #define MINCL max(16, 2)
115 extern int dlil_input_thread_wakeup
;
116 extern int dlil_expand_mcl
;
117 extern int dlil_initialized
;
120 static int mfree_munge
= 0;
122 #define _MFREE_MUNGE(m) { \
125 vm_offset_t *element = (vm_offset_t *)(m); \
127 i < sizeof(struct mbuf)/sizeof(vm_offset_t); \
129 (element)[i] = 0xdeadbeef; \
134 munge_mbuf(struct mbuf
*m
)
137 vm_offset_t
*element
= (vm_offset_t
*)(m
);
139 i
< sizeof(struct mbuf
)/sizeof(vm_offset_t
);
141 (element
)[i
] = 0xdeadbeef;
143 #define _MFREE_MUNGE(m) { \
149 #define _MFREE_MUNGE(m)
153 #define _MINTGET(m, type) { \
155 if (((m) = mfree) != 0) { \
157 ++mclrefcnt[mtocl(m)]; \
158 mbstat.m_mtypes[MT_FREE]--; \
159 mbstat.m_mtypes[(type)]++; \
160 mfree = (m)->m_next; \
174 nclpp
= round_page(MCLBYTES
) / MCLBYTES
; /* see mbufgc() */
175 if (nclpp
< 1) nclpp
= 1;
177 // NETISR_LOCKINIT();
179 mbstat
.m_msize
= MSIZE
;
180 mbstat
.m_mclbytes
= MCLBYTES
;
181 mbstat
.m_minclsize
= MINCLSIZE
;
182 mbstat
.m_mlen
= MLEN
;
183 mbstat
.m_mhlen
= MHLEN
;
185 if (nmbclusters
== 0)
186 nmbclusters
= NMBCLUSTERS
;
187 MALLOC(mclrefcnt
, short *, nmbclusters
* sizeof (short),
191 for (m
= 0; m
< nmbclusters
; m
++)
194 MALLOC(mcl_paddr
, int *, (nmbclusters
/(PAGE_SIZE
/CLBYTES
)) * sizeof (int),
198 bzero((char *)mcl_paddr
, (nmbclusters
/(PAGE_SIZE
/CLBYTES
)) * sizeof (int));
200 embutl
= (union mcluster
*)((unsigned char *)mbutl
+ (nmbclusters
* MCLBYTES
));
202 PE_parse_boot_arg("initmcl", &initmcl
);
204 if (m_clalloc(max(PAGE_SIZE
/CLBYTES
, 1) * initmcl
, M_WAIT
) == 0)
213 * Allocate some number of mbuf clusters
214 * and place on cluster free list.
217 m_clalloc(ncl
, nowait
)
221 register union mcluster
*mcl
;
224 static char doing_alloc
;
227 * Honor the caller's wish to block or not block.
228 * We have a way to grow the pool asynchronously,
229 * by kicking the dlil_input_thread.
231 if ((i
= m_howmany()) <= 0)
234 if ((nowait
== M_DONTWAIT
))
239 size
= round_page(ncl
* MCLBYTES
);
240 mcl
= (union mcluster
*)kmem_mb_alloc(mb_map
, size
);
242 if (mcl
== 0 && ncl
> 1) {
243 size
= round_page(MCLBYTES
); /* Try for 1 if failed */
244 mcl
= (union mcluster
*)kmem_mb_alloc(mb_map
, size
);
249 ncl
= size
/ MCLBYTES
;
250 for (i
= 0; i
< ncl
; i
++) {
251 if (++mclrefcnt
[mtocl(mcl
)] != 0)
252 panic("m_clalloc already there");
253 if (((int)mcl
& PAGE_MASK
) == 0)
254 mcl_paddr
[((char *)mcl
- (char *)mbutl
)/PAGE_SIZE
] = pmap_extract(kernel_pmap
, (char *)mcl
);
256 mcl
->mcl_next
= mclfree
;
259 mbstat
.m_clfree
+= ncl
;
260 mbstat
.m_clusters
+= ncl
;
267 * When non-blocking we kick the dlil thread if we havve to grow the
268 * pool or if the number of free clusters is less than requested.
270 if ((nowait
== M_DONTWAIT
) && (i
> 0 || ncl
>= mbstat
.m_clfree
)) {
272 if (dlil_initialized
)
273 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
276 if (mbstat
.m_clfree
>= ncl
)
285 * Add more free mbufs by cutting up a cluster.
290 register caddr_t mcl
;
292 if (mbstat
.m_clfree
< (mbstat
.m_clusters
>> 4))
293 /* 1/16th of the total number of cluster mbufs allocated is
294 reserved for large packets. The number reserved must
295 always be < 1/2, or future allocation will be prevented.
299 MCLALLOC(mcl
, canwait
);
301 register struct mbuf
*m
= (struct mbuf
*)mcl
;
302 register int i
= NMBPCL
;
304 mbstat
.m_mtypes
[MT_FREE
] += i
;
315 if (i
) wakeup((caddr_t
)&mfree
);
322 * When MGET failes, ask protocols to free space when short of memory,
323 * then re-attempt to allocate an mbuf.
326 m_retry(canwait
, type
)
329 register struct mbuf
*m
;
333 boolean_t funnel_state
;
336 (void) m_expand(canwait
);
339 (m
)->m_next
= (m
)->m_nextpkt
= 0;
340 (m
)->m_type
= (type
);
341 (m
)->m_data
= (m
)->m_dat
;
344 if (m
|| canwait
== M_DONTWAIT
)
355 if (dlil_initialized
)
356 wakeup((caddr_t
)&dlil_input_thread_wakeup
);
359 * Grab network funnel because m_reclaim calls into the
360 * socket domains and tsleep end-up calling splhigh
362 fnl
= thread_funnel_get();
363 if (fnl
&& (fnl
== kernel_flock
)) {
365 thread_funnel_switch(KERNEL_FUNNEL
, NETWORK_FUNNEL
);
367 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
371 /* Sleep with a small timeout as insurance */
372 (void) tsleep((caddr_t
)&mfree
, PZERO
-1, "m_retry", hz
);
375 thread_funnel_switch(NETWORK_FUNNEL
, KERNEL_FUNNEL
);
377 thread_funnel_set(network_flock
, funnel_state
);
383 * As above; retry an MGETHDR.
386 m_retryhdr(canwait
, type
)
389 register struct mbuf
*m
;
391 if (m
= m_retry(canwait
, type
)) {
392 m
->m_flags
|= M_PKTHDR
;
393 m
->m_data
= m
->m_pktdat
;
394 m
->m_pkthdr
.rcvif
= NULL
;
396 m
->m_pkthdr
.header
= NULL
;
397 m
->m_pkthdr
.csum_flags
= 0;
398 m
->m_pkthdr
.csum_data
= 0;
399 m
->m_pkthdr
.aux
= (struct mbuf
*)NULL
;
400 m
->m_pkthdr
.reserved1
= NULL
;
401 m
->m_pkthdr
.reserved2
= NULL
;
408 register struct domain
*dp
;
409 register struct protosw
*pr
;
411 for (dp
= domains
; dp
; dp
= dp
->dom_next
)
412 for (pr
= dp
->dom_protosw
; pr
; pr
= pr
->pr_next
)
419 * Space allocation routines.
420 * These are also available as macros
421 * for critical paths.
427 register struct mbuf
*m
;
431 m
->m_next
= m
->m_nextpkt
= 0;
433 m
->m_data
= m
->m_dat
;
436 (m
) = m_retry(nowait
, type
);
442 m_gethdr(nowait
, type
)
445 register struct mbuf
*m
;
449 m
->m_next
= m
->m_nextpkt
= 0;
451 m
->m_data
= m
->m_pktdat
;
452 m
->m_flags
= M_PKTHDR
;
453 m
->m_pkthdr
.rcvif
= NULL
;
454 m
->m_pkthdr
.header
= NULL
;
455 m
->m_pkthdr
.csum_flags
= 0;
456 m
->m_pkthdr
.csum_data
= 0;
457 m
->m_pkthdr
.aux
= (struct mbuf
*)NULL
;
458 m
->m_pkthdr
.reserved1
= NULL
;
459 m
->m_pkthdr
.reserved2
= NULL
;
461 m
= m_retryhdr(nowait
, type
);
467 m_getclr(nowait
, type
)
470 register struct mbuf
*m
;
472 MGET(m
, nowait
, type
);
475 bzero(mtod(m
, caddr_t
), MLEN
);
483 struct mbuf
*n
= m
->m_next
;
486 if (m
->m_type
== MT_FREE
)
487 panic("freeing free mbuf");
489 /* Free the aux data if there is any */
490 if ((m
->m_flags
& M_PKTHDR
) && m
->m_pkthdr
.aux
)
492 m_freem(m
->m_pkthdr
.aux
);
496 if ((m
->m_flags
& M_EXT
))
498 if (MCLHASREFERENCE(m
)) {
499 remque((queue_t
)&m
->m_ext
.ext_refs
);
500 } else if (m
->m_ext
.ext_free
== NULL
) {
501 union mcluster
*mcl
= (union mcluster
*)m
->m_ext
.ext_buf
;
502 if (_MCLUNREF(mcl
)) {
503 mcl
->mcl_next
= mclfree
;
508 /* *** Since m_split() increments "mclrefcnt[mtocl(m->m_ext.ext_buf)]",
509 and AppleTalk ADSP uses m_split(), this incorrect sanity check
512 else /* sanity check - not referenced this way */
513 panic("m_free m_ext cluster not free");
516 (*(m
->m_ext
.ext_free
))(m
->m_ext
.ext_buf
,
517 m
->m_ext
.ext_size
, m
->m_ext
.ext_arg
);
520 mbstat
.m_mtypes
[m
->m_type
]--;
524 mbstat
.m_mtypes
[m
->m_type
]++;
532 if (i
) wakeup((caddr_t
)&mfree
);
536 /* m_mclget() add an mbuf cluster to a normal mbuf */
542 MCLALLOC(m
->m_ext
.ext_buf
, nowait
);
543 if (m
->m_ext
.ext_buf
) {
544 m
->m_data
= m
->m_ext
.ext_buf
;
546 m
->m_ext
.ext_size
= MCLBYTES
;
547 m
->m_ext
.ext_free
= 0;
548 m
->m_ext
.ext_refs
.forward
= m
->m_ext
.ext_refs
.backward
=
555 /* m_mclalloc() allocate an mbuf cluster */
562 (void)m_clalloc(1, nowait
);
563 if ((p
= (caddr_t
)mclfree
)) {
564 ++mclrefcnt
[mtocl(p
)];
566 mclfree
= ((union mcluster
*)p
)->mcl_next
;
573 /* m_mclfree() releases a reference to a cluster allocated by MCLALLOC,
574 * freeing the cluster if the reference count has reached 0. */
580 if (--mclrefcnt
[mtocl(p
)] == 0) {
581 ((union mcluster
*)(p
))->mcl_next
= mclfree
;
582 mclfree
= (union mcluster
*)(p
);
588 /* mcl_hasreference() checks if a cluster of an mbuf is referenced by another mbuf */
593 return (m
->m_ext
.ext_refs
.forward
!= &(m
->m_ext
.ext_refs
));
598 m_copy_pkthdr(to
, from
)
599 struct mbuf
*to
, *from
;
601 to
->m_pkthdr
= from
->m_pkthdr
;
602 from
->m_pkthdr
.aux
= (struct mbuf
*)NULL
;
603 to
->m_flags
= from
->m_flags
& M_COPYFLAGS
;
604 to
->m_data
= (to
)->m_pktdat
;
607 /* Best effort to get a mbuf cluster + pkthdr under one lock.
608 * If we don't have them avail, just bail out and use the regular
610 * Used by drivers to allocated packets on receive ring.
616 m_clalloc(1, M_DONTWAIT
); /* takes the MBUF_LOCK, but doesn't release it... */
617 if ((mfree
!= 0) && (mclfree
!= 0)) { /* mbuf + cluster are available */
621 ++mclrefcnt
[mtocl(m
)];
622 mbstat
.m_mtypes
[MT_FREE
]--;
623 mbstat
.m_mtypes
[MT_DATA
]++;
624 m
->m_ext
.ext_buf
= (caddr_t
)mclfree
; /* get the cluster */
625 ++mclrefcnt
[mtocl(m
->m_ext
.ext_buf
)];
627 mclfree
= ((union mcluster
*)(m
->m_ext
.ext_buf
))->mcl_next
;
629 m
->m_next
= m
->m_nextpkt
= 0;
631 m
->m_data
= m
->m_ext
.ext_buf
;
632 m
->m_flags
= M_PKTHDR
| M_EXT
;
634 m
->m_pkthdr
.rcvif
= NULL
;
635 m
->m_pkthdr
.header
= NULL
;
636 m
->m_pkthdr
.csum_data
= 0;
637 m
->m_pkthdr
.csum_flags
= 0;
638 m
->m_pkthdr
.aux
= (struct mbuf
*)NULL
;
639 m
->m_pkthdr
.reserved1
= 0;
640 m
->m_pkthdr
.reserved2
= 0;
641 m
->m_ext
.ext_free
= 0;
642 m
->m_ext
.ext_size
= MCLBYTES
;
643 m
->m_ext
.ext_refs
.forward
= m
->m_ext
.ext_refs
.backward
=
647 else { /* slow path: either mbuf or cluster need to be allocated anyway */
650 MGETHDR(m
, M_WAITOK
, MT_DATA
);
655 MCLGET( m
, M_WAITOK
);
656 if ( ( m
->m_flags
& M_EXT
) == 0 )
666 * return a list of mbuf hdrs that point to clusters...
667 * try for num_needed, if this can't be met, return whatever
668 * number were available... set up the first num_with_pkthdrs
669 * with mbuf hdrs configured as packet headers... these are
670 * chained on the m_nextpkt field... any packets requested beyond
671 * this are chained onto the last packet header's m_next field.
674 m_getpackets(int num_needed
, int num_with_pkthdrs
, int how
)
677 struct mbuf
**np
, *top
;
682 m_clalloc(num_needed
, how
); /* takes the MBUF_LOCK, but doesn't release it... */
684 while (num_needed
--) {
685 if (mfree
&& mclfree
) { /* mbuf + cluster are available */
689 ++mclrefcnt
[mtocl(m
)];
690 mbstat
.m_mtypes
[MT_FREE
]--;
691 mbstat
.m_mtypes
[MT_DATA
]++;
692 m
->m_ext
.ext_buf
= (caddr_t
)mclfree
; /* get the cluster */
693 ++mclrefcnt
[mtocl(m
->m_ext
.ext_buf
)];
695 mclfree
= ((union mcluster
*)(m
->m_ext
.ext_buf
))->mcl_next
;
697 m
->m_next
= m
->m_nextpkt
= 0;
699 m
->m_data
= m
->m_ext
.ext_buf
;
700 m
->m_ext
.ext_free
= 0;
701 m
->m_ext
.ext_size
= MCLBYTES
;
702 m
->m_ext
.ext_refs
.forward
= m
->m_ext
.ext_refs
.backward
= &m
->m_ext
.ext_refs
;
704 if (num_with_pkthdrs
== 0)
707 m
->m_flags
= M_PKTHDR
| M_EXT
;
709 m
->m_pkthdr
.rcvif
= NULL
;
710 m
->m_pkthdr
.header
= NULL
;
711 m
->m_pkthdr
.csum_flags
= 0;
712 m
->m_pkthdr
.csum_data
= 0;
713 m
->m_pkthdr
.aux
= (struct mbuf
*)NULL
;
714 m
->m_pkthdr
.reserved1
= NULL
;
715 m
->m_pkthdr
.reserved2
= NULL
;
724 if (num_with_pkthdrs
== 0) {
725 MGET(m
, how
, MT_DATA
);
727 MGETHDR(m
, how
, MT_DATA
);
735 if ((m
->m_flags
& M_EXT
) == 0) {
743 if (num_with_pkthdrs
)
755 * return a list of mbuf hdrs set up as packet hdrs
756 * chained together on the m_nextpkt field
759 m_getpackethdrs(int num_needed
, int how
)
762 struct mbuf
**np
, *top
;
769 while (num_needed
--) {
770 if (m
= mfree
) { /* mbufs are available */
773 ++mclrefcnt
[mtocl(m
)];
774 mbstat
.m_mtypes
[MT_FREE
]--;
775 mbstat
.m_mtypes
[MT_DATA
]++;
777 m
->m_next
= m
->m_nextpkt
= 0;
779 m
->m_flags
= M_PKTHDR
;
780 m
->m_data
= m
->m_pktdat
;
782 m
->m_pkthdr
.rcvif
= NULL
;
783 m
->m_pkthdr
.header
= NULL
;
784 m
->m_pkthdr
.csum_flags
= 0;
785 m
->m_pkthdr
.csum_data
= 0;
786 m
->m_pkthdr
.aux
= (struct mbuf
*)NULL
;
787 m
->m_pkthdr
.reserved1
= NULL
;
788 m
->m_pkthdr
.reserved2
= NULL
;
794 m
= m_retryhdr(how
, MT_DATA
);
810 /* free and mbuf list (m_nextpkt) while following m_next under one lock.
811 * returns the count for mbufs packets freed. Used by the drivers.
817 struct mbuf
*nextpkt
;
824 nextpkt
= m
->m_nextpkt
; /* chain of linked mbufs from driver */
830 while (m
) { /* free the mbuf chain (like mfreem) */
834 /* Free the aux data if there is any */
835 if ((m
->m_flags
& M_PKTHDR
) && m
->m_pkthdr
.aux
) {
837 * Treat the current m as the nextpkt and set m
838 * to the aux data. This lets us free the aux
839 * data in this loop without having to call
840 * m_freem recursively, which wouldn't work
841 * because we've still got the lock.
844 m
= nextpkt
->m_pkthdr
.aux
;
845 nextpkt
->m_pkthdr
.aux
= NULL
;
850 if (n
&& n
->m_nextpkt
)
851 panic("m_freem_list: m_nextpkt of m_next != NULL");
852 if (m
->m_type
== MT_FREE
)
853 panic("freeing free mbuf");
855 if (m
->m_flags
& M_EXT
) {
856 if (MCLHASREFERENCE(m
)) {
857 remque((queue_t
)&m
->m_ext
.ext_refs
);
858 } else if (m
->m_ext
.ext_free
== NULL
) {
859 union mcluster
*mcl
= (union mcluster
*)m
->m_ext
.ext_buf
;
860 if (_MCLUNREF(mcl
)) {
861 mcl
->mcl_next
= mclfree
;
866 (*(m
->m_ext
.ext_free
))(m
->m_ext
.ext_buf
,
867 m
->m_ext
.ext_size
, m
->m_ext
.ext_arg
);
870 mbstat
.m_mtypes
[m
->m_type
]--;
873 mbstat
.m_mtypes
[MT_FREE
]++;
881 m
= nextpkt
; /* bump m with saved nextpkt if any */
889 wakeup((caddr_t
)&mfree
);
896 register struct mbuf
*m
;
903 * Mbuffer utility routines.
906 * Compute the amount of space available
907 * before the current start of data in an mbuf.
910 register struct mbuf
*m
;
912 if (m
->m_flags
& M_EXT
) {
913 if (MCLHASREFERENCE(m
))
915 return (m
->m_data
- m
->m_ext
.ext_buf
);
917 if (m
->m_flags
& M_PKTHDR
)
918 return (m
->m_data
- m
->m_pktdat
);
919 return (m
->m_data
- m
->m_dat
);
923 * Compute the amount of space available
924 * after the end of data in an mbuf.
927 register struct mbuf
*m
;
929 if (m
->m_flags
& M_EXT
) {
930 if (MCLHASREFERENCE(m
))
932 return (m
->m_ext
.ext_buf
+ m
->m_ext
.ext_size
-
933 (m
->m_data
+ m
->m_len
));
935 return (&m
->m_dat
[MLEN
] - (m
->m_data
+ m
->m_len
));
939 * Lesser-used path for M_PREPEND:
940 * allocate new mbuf to prepend to chain,
942 * Does not adjust packet header length.
945 m_prepend(m
, len
, how
)
946 register struct mbuf
*m
;
951 MGET(mn
, how
, m
->m_type
);
952 if (mn
== (struct mbuf
*)NULL
) {
954 return ((struct mbuf
*)NULL
);
956 if (m
->m_flags
& M_PKTHDR
) {
957 M_COPY_PKTHDR(mn
, m
);
958 m
->m_flags
&= ~M_PKTHDR
;
969 * Replacement for old M_PREPEND macro:
970 * allocate new mbuf to prepend to chain,
971 * copy junk along, and adjust length.
975 m_prepend_2(m
, len
, how
)
976 register struct mbuf
*m
;
979 if (M_LEADINGSPACE(m
) >= len
) {
983 m
= m_prepend(m
, len
, how
);
985 if ((m
) && (m
->m_flags
& M_PKTHDR
))
986 m
->m_pkthdr
.len
+= len
;
991 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
992 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
993 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
998 m_copym(m
, off0
, len
, wait
)
999 register struct mbuf
*m
;
1003 register struct mbuf
*n
, **np
;
1004 register int off
= off0
;
1008 if (off
< 0 || len
< 0)
1010 if (off
== 0 && m
->m_flags
& M_PKTHDR
)
1013 while (off
>= m
->m_len
) {
1026 if (len
!= M_COPYALL
)
1032 ++mclrefcnt
[mtocl(n
)];
1033 mbstat
.m_mtypes
[MT_FREE
]--;
1034 mbstat
.m_mtypes
[m
->m_type
]++;
1036 n
->m_next
= n
->m_nextpkt
= 0;
1037 n
->m_type
= m
->m_type
;
1038 n
->m_data
= n
->m_dat
;
1042 n
= m_retry(wait
, m
->m_type
);
1050 M_COPY_PKTHDR(n
, m
);
1051 if (len
== M_COPYALL
)
1052 n
->m_pkthdr
.len
-= off0
;
1054 n
->m_pkthdr
.len
= len
;
1057 if (len
== M_COPYALL
) {
1058 if (min(len
, (m
->m_len
- off
)) == len
) {
1059 printf("m->m_len %d - off %d = %d, %d\n",
1060 m
->m_len
, off
, m
->m_len
- off
,
1061 min(len
, (m
->m_len
- off
)));
1064 n
->m_len
= min(len
, (m
->m_len
- off
));
1065 if (n
->m_len
== M_COPYALL
) {
1066 printf("n->m_len == M_COPYALL, fixing\n");
1069 if (m
->m_flags
& M_EXT
) {
1070 n
->m_ext
= m
->m_ext
;
1071 insque((queue_t
)&n
->m_ext
.ext_refs
, (queue_t
)&m
->m_ext
.ext_refs
);
1072 n
->m_data
= m
->m_data
+ off
;
1073 n
->m_flags
|= M_EXT
;
1075 bcopy(mtod(m
, caddr_t
)+off
, mtod(n
, caddr_t
),
1076 (unsigned)n
->m_len
);
1078 if (len
!= M_COPYALL
)
1100 * equivilent to m_copym except that all necessary
1101 * mbuf hdrs are allocated within this routine
1102 * also, the last mbuf and offset accessed are passed
1103 * out and can be passed back in to avoid having to
1104 * rescan the entire mbuf list (normally hung off of the socket)
1107 m_copym_with_hdrs(m
, off0
, len
, wait
, m_last
, m_off
)
1108 register struct mbuf
*m
;
1111 struct mbuf
**m_last
;
1114 register struct mbuf
*n
, **np
;
1115 register int off
= off0
;
1116 struct mbuf
*top
= 0;
1120 if (off
== 0 && m
->m_flags
& M_PKTHDR
)
1127 while (off
>= m
->m_len
) {
1139 panic("m_gethdr_and_copym");
1144 ++mclrefcnt
[mtocl(n
)];
1145 mbstat
.m_mtypes
[MT_FREE
]--;
1146 mbstat
.m_mtypes
[type
]++;
1148 n
->m_next
= n
->m_nextpkt
= 0;
1152 n
->m_data
= n
->m_dat
;
1155 n
->m_data
= n
->m_pktdat
;
1156 n
->m_flags
= M_PKTHDR
;
1157 n
->m_pkthdr
.len
= 0;
1158 n
->m_pkthdr
.rcvif
= NULL
;
1159 n
->m_pkthdr
.header
= NULL
;
1160 n
->m_pkthdr
.csum_flags
= 0;
1161 n
->m_pkthdr
.csum_data
= 0;
1162 n
->m_pkthdr
.aux
= (struct mbuf
*)NULL
;
1163 n
->m_pkthdr
.reserved1
= NULL
;
1164 n
->m_pkthdr
.reserved2
= NULL
;
1169 n
= m_retry(wait
, type
);
1171 n
= m_retryhdr(wait
, type
);
1184 M_COPY_PKTHDR(n
, m
);
1185 n
->m_pkthdr
.len
= len
;
1188 n
->m_len
= min(len
, (m
->m_len
- off
));
1190 if (m
->m_flags
& M_EXT
) {
1191 n
->m_ext
= m
->m_ext
;
1192 insque((queue_t
)&n
->m_ext
.ext_refs
, (queue_t
)&m
->m_ext
.ext_refs
);
1193 n
->m_data
= m
->m_data
+ off
;
1194 n
->m_flags
|= M_EXT
;
1196 bcopy(mtod(m
, caddr_t
)+off
, mtod(n
, caddr_t
),
1197 (unsigned)n
->m_len
);
1202 if ((off
+ n
->m_len
) == m
->m_len
) {
1203 *m_last
= m
->m_next
;
1207 *m_off
= off
+ n
->m_len
;
1229 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1230 * continuing for "len" bytes, into the indicated buffer.
1232 void m_copydata(m
, off
, len
, cp
)
1233 register struct mbuf
*m
;
1238 register unsigned count
;
1240 if (off
< 0 || len
< 0)
1241 panic("m_copydata");
1244 panic("m_copydata");
1252 panic("m_copydata");
1253 count
= min(m
->m_len
- off
, len
);
1254 bcopy(mtod(m
, caddr_t
) + off
, cp
, count
);
1263 * Concatenate mbuf chain n to m.
1264 * Both chains must be of the same type (e.g. MT_DATA).
1265 * Any m_pkthdr is not updated.
1268 register struct mbuf
*m
, *n
;
1273 if (m
->m_flags
& M_EXT
||
1274 m
->m_data
+ m
->m_len
+ n
->m_len
>= &m
->m_dat
[MLEN
]) {
1275 /* just join the two chains */
1279 /* splat the data from one into the other */
1280 bcopy(mtod(n
, caddr_t
), mtod(m
, caddr_t
) + m
->m_len
,
1282 m
->m_len
+= n
->m_len
;
1292 register int len
= req_len
;
1293 register struct mbuf
*m
;
1296 if ((m
= mp
) == NULL
)
1302 while (m
!= NULL
&& len
> 0) {
1303 if (m
->m_len
<= len
) {
1314 if (m
->m_flags
& M_PKTHDR
)
1315 m
->m_pkthdr
.len
-= (req_len
- len
);
1318 * Trim from tail. Scan the mbuf chain,
1319 * calculating its length and finding the last mbuf.
1320 * If the adjustment only affects this mbuf, then just
1321 * adjust and return. Otherwise, rescan and truncate
1322 * after the remaining size.
1328 if (m
->m_next
== (struct mbuf
*)0)
1332 if (m
->m_len
>= len
) {
1335 if (m
->m_flags
& M_PKTHDR
)
1336 m
->m_pkthdr
.len
-= len
;
1343 * Correct length for chain is "count".
1344 * Find the mbuf with last data, adjust its length,
1345 * and toss data from remaining mbufs on chain.
1348 if (m
->m_flags
& M_PKTHDR
)
1349 m
->m_pkthdr
.len
= count
;
1350 for (; m
; m
= m
->m_next
) {
1351 if (m
->m_len
>= count
) {
1357 while (m
= m
->m_next
)
1363 * Rearange an mbuf chain so that len bytes are contiguous
1364 * and in the data area of an mbuf (so that mtod and dtom
1365 * will work for a structure of size len). Returns the resulting
1366 * mbuf chain on success, frees it and returns null on failure.
1367 * If there is room, it will add up to max_protohdr-len extra bytes to the
1368 * contiguous region in an attempt to avoid being called next time.
1374 register struct mbuf
*n
;
1377 register struct mbuf
*m
;
1382 * If first mbuf has no cluster, and has room for len bytes
1383 * without shifting current data, pullup into it,
1384 * otherwise allocate a new mbuf to prepend to the chain.
1386 if ((n
->m_flags
& M_EXT
) == 0 &&
1387 n
->m_data
+ len
< &n
->m_dat
[MLEN
] && n
->m_next
) {
1388 if (n
->m_len
>= len
)
1396 MGET(m
, M_DONTWAIT
, n
->m_type
);
1400 if (n
->m_flags
& M_PKTHDR
) {
1401 M_COPY_PKTHDR(m
, n
);
1402 n
->m_flags
&= ~M_PKTHDR
;
1405 space
= &m
->m_dat
[MLEN
] - (m
->m_data
+ m
->m_len
);
1407 count
= min(min(max(len
, max_protohdr
), space
), n
->m_len
);
1408 bcopy(mtod(n
, caddr_t
), mtod(m
, caddr_t
) + m
->m_len
,
1418 } while (len
> 0 && n
);
1432 * Partition an mbuf chain in two pieces, returning the tail --
1433 * all but the first len0 bytes. In case of failure, it returns NULL and
1434 * attempts to restore the chain to its original state.
1437 m_split(m0
, len0
, wait
)
1438 register struct mbuf
*m0
;
1441 register struct mbuf
*m
, *n
;
1442 unsigned len
= len0
, remain
;
1444 for (m
= m0
; m
&& len
> m
->m_len
; m
= m
->m_next
)
1448 remain
= m
->m_len
- len
;
1449 if (m0
->m_flags
& M_PKTHDR
) {
1450 MGETHDR(n
, wait
, m0
->m_type
);
1453 n
->m_pkthdr
.rcvif
= m0
->m_pkthdr
.rcvif
;
1454 n
->m_pkthdr
.len
= m0
->m_pkthdr
.len
- len0
;
1455 m0
->m_pkthdr
.len
= len0
;
1456 if (m
->m_flags
& M_EXT
)
1458 if (remain
> MHLEN
) {
1459 /* m can't be the lead packet */
1461 n
->m_next
= m_split(m
, len
, wait
);
1462 if (n
->m_next
== 0) {
1468 MH_ALIGN(n
, remain
);
1469 } else if (remain
== 0) {
1474 MGET(n
, wait
, m
->m_type
);
1480 if (m
->m_flags
& M_EXT
) {
1481 n
->m_flags
|= M_EXT
;
1483 n
->m_ext
= m
->m_ext
;
1484 insque((queue_t
)&n
->m_ext
.ext_refs
, (queue_t
)&m
->m_ext
.ext_refs
);
1486 n
->m_data
= m
->m_data
+ len
;
1488 bcopy(mtod(m
, caddr_t
) + len
, mtod(n
, caddr_t
), remain
);
1492 n
->m_next
= m
->m_next
;
1497 * Routine to copy from device local memory into mbufs.
1500 m_devget(buf
, totlen
, off0
, ifp
, copy
)
1506 register struct mbuf
*m
;
1507 struct mbuf
*top
= 0, **mp
= &top
;
1508 register int off
= off0
, len
;
1516 * If 'off' is non-zero, packet is trailer-encapsulated,
1517 * so we have to skip the type and length fields.
1519 cp
+= off
+ 2 * sizeof(u_int16_t
);
1520 totlen
-= 2 * sizeof(u_int16_t
);
1522 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
1525 m
->m_pkthdr
.rcvif
= ifp
;
1526 m
->m_pkthdr
.len
= totlen
;
1529 while (totlen
> 0) {
1531 MGET(m
, M_DONTWAIT
, MT_DATA
);
1538 len
= min(totlen
, epkt
- cp
);
1539 if (len
>= MINCLSIZE
) {
1540 MCLGET(m
, M_DONTWAIT
);
1541 if (m
->m_flags
& M_EXT
)
1542 m
->m_len
= len
= min(len
, MCLBYTES
);
1544 /* give up when it's out of cluster mbufs */
1552 * Place initial small packet/header at end of mbuf.
1554 if (len
< m
->m_len
) {
1555 if (top
== 0 && len
+ max_linkhdr
<= m
->m_len
)
1556 m
->m_data
+= max_linkhdr
;
1562 copy(cp
, mtod(m
, caddr_t
), (unsigned)len
);
1564 bcopy(cp
, mtod(m
, caddr_t
), (unsigned)len
);
1576 * Cluster freelist allocation check. The mbuf lock must be held.
1577 * Ensure hysteresis between hi/lo.
1585 if (mbstat
.m_clusters
< MINCL
)
1586 return (MINCL
- mbstat
.m_clusters
);
1587 /* Too few (free < 1/2 total) and not over maximum */
1588 if (mbstat
.m_clusters
< nmbclusters
&&
1589 (i
= ((mbstat
.m_clusters
>> 1) - mbstat
.m_clfree
)) > 0)
1596 * Copy data from a buffer back into the indicated mbuf chain,
1597 * starting "off" bytes from the beginning, extending the mbuf
1598 * chain if necessary.
1601 m_copyback(m0
, off
, len
, cp
)
1608 register struct mbuf
*m
= m0
, *n
;
1613 while (off
> (mlen
= m
->m_len
)) {
1616 if (m
->m_next
== 0) {
1617 n
= m_getclr(M_DONTWAIT
, m
->m_type
);
1620 n
->m_len
= min(MLEN
, len
+ off
);
1626 mlen
= min (m
->m_len
- off
, len
);
1627 bcopy(cp
, off
+ mtod(m
, caddr_t
), (unsigned)mlen
);
1635 if (m
->m_next
== 0) {
1636 n
= m_get(M_DONTWAIT
, m
->m_type
);
1639 n
->m_len
= min(MLEN
, len
);
1644 out
: if (((m
= m0
)->m_flags
& M_PKTHDR
) && (m
->m_pkthdr
.len
< totlen
))
1645 m
->m_pkthdr
.len
= totlen
;
1649 char *mcl_to_paddr(register char *addr
) {
1650 register int base_phys
;
1652 if (addr
< (char *)mbutl
|| addr
>= (char *)embutl
)
1654 base_phys
= mcl_paddr
[(addr
- (char *)mbutl
) >> PAGE_SHIFT
];
1658 return ((char *)((int)base_phys
| ((int)addr
& PAGE_MASK
)));
1662 * Dup the mbuf chain passed in. The whole thing. No cute additional cruft.
1663 * And really copy the thing. That way, we don't "precompute" checksums
1664 * for unsuspecting consumers.
1665 * Assumption: m->m_nextpkt == 0.
1666 * Trick: for small packets, don't dup into a cluster. That way received
1667 * packets don't take up too much room in the sockbuf (cf. sbspace()).
1672 m_dup(register struct mbuf
*m
, int how
)
1673 { register struct mbuf
*n
, **np
;
1679 if (m
->m_flags
& M_PKTHDR
)
1683 * Quick check: if we have one mbuf and its data fits in an
1684 * mbuf with packet header, just copy and go.
1686 if (m
->m_next
== NULL
)
1687 { /* Then just move the data into an mbuf and be done... */
1689 { if (m
->m_pkthdr
.len
<= MHLEN
)
1690 { if ((n
= m_gethdr(how
, m
->m_type
)) == NULL
)
1692 n
->m_len
= m
->m_len
;
1693 n
->m_flags
|= (m
->m_flags
& M_COPYFLAGS
);
1694 n
->m_pkthdr
.len
= m
->m_pkthdr
.len
;
1695 n
->m_pkthdr
.rcvif
= m
->m_pkthdr
.rcvif
;
1696 n
->m_pkthdr
.header
= NULL
;
1697 n
->m_pkthdr
.csum_flags
= 0;
1698 n
->m_pkthdr
.csum_data
= 0;
1699 n
->m_pkthdr
.aux
= NULL
;
1700 n
->m_pkthdr
.reserved1
= 0;
1701 n
->m_pkthdr
.reserved2
= 0;
1702 bcopy(m
->m_data
, n
->m_data
, m
->m_pkthdr
.len
);
1705 } else if (m
->m_len
<= MLEN
)
1706 { if ((n
= m_get(how
, m
->m_type
)) == NULL
)
1708 bcopy(m
->m_data
, n
->m_data
, m
->m_len
);
1709 n
->m_len
= m
->m_len
;
1716 kprintf("<%x: %x, %x, %x\n", m
, m
->m_flags
, m
->m_len
,
1720 n
= m_gethdr(how
, m
->m_type
);
1722 n
= m_get(how
, m
->m_type
);
1725 if (m
->m_flags
& M_EXT
)
1727 if ((n
->m_flags
& M_EXT
) == 0)
1732 { /* Don't use M_COPY_PKTHDR: preserve m_data */
1733 n
->m_pkthdr
= m
->m_pkthdr
;
1734 n
->m_flags
|= (m
->m_flags
& M_COPYFLAGS
);
1736 if ((n
->m_flags
& M_EXT
) == 0)
1737 n
->m_data
= n
->m_pktdat
;
1739 n
->m_len
= m
->m_len
;
1741 * Get the dup on the same bdry as the original
1742 * Assume that the two mbufs have the same offset to data area
1743 * (up to word bdries)
1745 bcopy(mtod(m
, caddr_t
), mtod(n
, caddr_t
), (unsigned)n
->m_len
);
1749 kprintf(">%x: %x, %x, %x\n", n
, n
->m_flags
, n
->m_len
,
1764 m_mclref(struct mbuf
*p
)
1766 return (_MCLREF(p
));
1770 m_mclunref(struct mbuf
*p
)
1772 return (_MCLUNREF(p
));
1775 /* change mbuf to new type */
1777 m_mchtype(struct mbuf
*m
, int t
)
1780 mbstat
.m_mtypes
[(m
)->m_type
]--;
1781 mbstat
.m_mtypes
[t
]++;
1786 void *m_mtod(struct mbuf
*m
)
1788 return ((m
)->m_data
);
1791 struct mbuf
*m_dtom(void *x
)
1793 return ((struct mbuf
*)((u_long
)(x
) & ~(MSIZE
-1)));
1796 int m_mtocl(void *x
)
1798 return (((char *)(x
) - (char *)mbutl
) / sizeof(union mcluster
));
1801 union mcluster
*m_cltom(int x
)
1803 return ((union mcluster
*)(mbutl
+ (x
)));
1807 void m_mcheck(struct mbuf
*m
)
1809 if (m
->m_type
!= MT_FREE
)
1810 panic("mget MCHECK: m_type=%x m=%x", m
->m_type
, m
);
1814 #include <sys/sysctl.h>
1816 static int mhog_num
= 0;
1817 static struct mbuf
*mhog_chain
= 0;
1818 static int mhog_wait
= 1;
1821 sysctl_mhog_num SYSCTL_HANDLER_ARGS
1826 error
= sysctl_handle_int(oidp
, oidp
->oid_arg1
, oidp
->oid_arg2
, req
);
1827 if (!error
&& req
->newptr
) {
1832 m_freem(mhog_chain
);
1836 for (i
= 0; i
< mhog_num
; i
++) {
1837 MGETHDR(m
, mhog_wait
? M_WAIT
: M_DONTWAIT
, MT_DATA
);
1841 MCLGET(m
, mhog_wait
? M_WAIT
: M_DONTWAIT
);
1842 if ((m
->m_flags
& M_EXT
) == 0) {
1847 m
->m_next
= mhog_chain
;
1856 SYSCTL_NODE(_kern_ipc
, OID_AUTO
, mhog
, CTLFLAG_RW
, 0, "mbuf hog");
1858 SYSCTL_PROC(_kern_ipc_mhog
, OID_AUTO
, cluster
, CTLTYPE_INT
|CTLFLAG_RW
,
1859 &mhog_num
, 0, &sysctl_mhog_num
, "I", "");
1860 SYSCTL_INT(_kern_ipc_mhog
, OID_AUTO
, wait
, CTLFLAG_RW
, &mhog_wait
,