]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/uipc_mbuf.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / kern / uipc_mbuf.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26/*
27 * Copyright (c) 1982, 1986, 1988, 1991, 1993
28 * The Regents of the University of California. All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
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.
45 *
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
56 * SUCH DAMAGE.
57 *
58 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
59 */
60/* HISTORY
61 *
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
69 */
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/malloc.h>
74#include <sys/mbuf.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>
80
81#include <kern/queue.h>
9bccf70c
A
82#include <kern/kern_types.h>
83#include <kern/sched_prim.h>
84
55e303ae
A
85#include <IOKit/IOMapper.h>
86
9bccf70c
A
87#define _MCLREF(p) (++mclrefcnt[mtocl(p)])
88#define _MCLUNREF(p) (--mclrefcnt[mtocl(p)] == 0)
55e303ae
A
89#define _M_CLEAR_PKTHDR(mbuf_ptr) (mbuf_ptr)->m_pkthdr.rcvif = NULL; \
90 (mbuf_ptr)->m_pkthdr.len = 0; \
91 (mbuf_ptr)->m_pkthdr.header = NULL; \
92 (mbuf_ptr)->m_pkthdr.csum_flags = 0; \
93 (mbuf_ptr)->m_pkthdr.csum_data = 0; \
94 (mbuf_ptr)->m_pkthdr.aux = (struct mbuf*)NULL; \
95 (mbuf_ptr)->m_pkthdr.reserved1 = NULL; \
96 (mbuf_ptr)->m_pkthdr.reserved2 = NULL;
97
98extern pmap_t kernel_pmap; /* The kernel's pmap */
99/* kernel translater */
100extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
1c79356b
A
101
102decl_simple_lock_data(, mbuf_slock);
103struct mbuf *mfree; /* mbuf free list */
104struct mbuf *mfreelater; /* mbuf deallocation list */
105extern vm_map_t mb_map; /* special map */
106int m_want; /* sleepers on mbufs */
107extern int nmbclusters; /* max number of mapped clusters */
108short *mclrefcnt; /* mapped cluster reference counts */
109int *mcl_paddr;
55e303ae 110static ppnum_t mcl_paddr_base; /* Handle returned by IOMapper::iovmAlloc() */
1c79356b
A
111union mcluster *mclfree; /* mapped cluster free list */
112int max_linkhdr; /* largest link-level header */
113int max_protohdr; /* largest protocol header */
114int max_hdr; /* largest link+protocol header */
115int max_datalen; /* MHLEN - max_hdr */
116struct mbstat mbstat; /* statistics */
117union mcluster *mbutl; /* first mapped cluster address */
118union mcluster *embutl; /* ending virtual address of mclusters */
119
120static int nclpp; /* # clusters per physical page */
121static char mbfail[] = "mbuf not mapped";
122
123static int m_howmany();
124
125/* The number of cluster mbufs that are allocated, to start. */
126#define MINCL max(16, 2)
127
55e303ae
A
128static int mbuf_expand_thread_wakeup = 0;
129static int mbuf_expand_mcl = 0;
130static int mbuf_expand_thread_initialized = 0;
131
132static void mbuf_expand_thread_init(void);
1c79356b 133
9bccf70c
A
134#if 0
135static int mfree_munge = 0;
136#if 0
137#define _MFREE_MUNGE(m) { \
138 if (mfree_munge) \
139 { int i; \
140 vm_offset_t *element = (vm_offset_t *)(m); \
141 for (i = 0; \
142 i < sizeof(struct mbuf)/sizeof(vm_offset_t); \
143 i++) \
144 (element)[i] = 0xdeadbeef; \
145 } \
146}
147#else
148void
149munge_mbuf(struct mbuf *m)
150{
151 int i;
152 vm_offset_t *element = (vm_offset_t *)(m);
153 for (i = 0;
154 i < sizeof(struct mbuf)/sizeof(vm_offset_t);
155 i++)
156 (element)[i] = 0xdeadbeef;
157}
158#define _MFREE_MUNGE(m) { \
159 if (mfree_munge) \
160 munge_mbuf(m); \
161}
162#endif
163#else
164#define _MFREE_MUNGE(m)
165#endif
166
167
168#define _MINTGET(m, type) { \
169 MBUF_LOCK(); \
170 if (((m) = mfree) != 0) { \
171 MCHECK(m); \
172 ++mclrefcnt[mtocl(m)]; \
173 mbstat.m_mtypes[MT_FREE]--; \
174 mbstat.m_mtypes[(type)]++; \
175 mfree = (m)->m_next; \
176 } \
177 MBUF_UNLOCK(); \
178}
179
1c79356b
A
180
181void
182mbinit()
183{
184 int s,m;
185 int initmcl = 32;
55e303ae 186 int mcl_pages;
1c79356b
A
187
188 if (nclpp)
189 return;
55e303ae 190 nclpp = round_page_32(MCLBYTES) / MCLBYTES; /* see mbufgc() */
1c79356b
A
191 if (nclpp < 1) nclpp = 1;
192 MBUF_LOCKINIT();
193// NETISR_LOCKINIT();
fa4905b1
A
194
195 mbstat.m_msize = MSIZE;
196 mbstat.m_mclbytes = MCLBYTES;
197 mbstat.m_minclsize = MINCLSIZE;
198 mbstat.m_mlen = MLEN;
199 mbstat.m_mhlen = MHLEN;
200
1c79356b
A
201 if (nmbclusters == 0)
202 nmbclusters = NMBCLUSTERS;
203 MALLOC(mclrefcnt, short *, nmbclusters * sizeof (short),
204 M_TEMP, M_WAITOK);
205 if (mclrefcnt == 0)
206 panic("mbinit");
207 for (m = 0; m < nmbclusters; m++)
208 mclrefcnt[m] = -1;
209
55e303ae
A
210 /* Calculate the number of pages assigned to the cluster pool */
211 mcl_pages = nmbclusters/(PAGE_SIZE/CLBYTES);
212 MALLOC(mcl_paddr, int *, mcl_pages * sizeof(int), M_TEMP, M_WAITOK);
1c79356b
A
213 if (mcl_paddr == 0)
214 panic("mbinit1");
55e303ae
A
215 /* Register with the I/O Bus mapper */
216 mcl_paddr_base = IOMapperIOVMAlloc(mcl_pages);
217 bzero((char *)mcl_paddr, mcl_pages * sizeof(int));
1c79356b
A
218
219 embutl = (union mcluster *)((unsigned char *)mbutl + (nmbclusters * MCLBYTES));
220
221 PE_parse_boot_arg("initmcl", &initmcl);
222
223 if (m_clalloc(max(PAGE_SIZE/CLBYTES, 1) * initmcl, M_WAIT) == 0)
224 goto bad;
225 MBUF_UNLOCK();
55e303ae
A
226
227 (void) kernel_thread(kernel_task, mbuf_expand_thread_init);
228
1c79356b
A
229 return;
230bad:
231 panic("mbinit");
232}
233
234/*
235 * Allocate some number of mbuf clusters
236 * and place on cluster free list.
237 */
238/* ARGSUSED */
239m_clalloc(ncl, nowait)
240 register int ncl;
241 int nowait;
242{
243 register union mcluster *mcl;
244 register int i;
245 vm_size_t size;
246 static char doing_alloc;
247
248 /*
249 * Honor the caller's wish to block or not block.
250 * We have a way to grow the pool asynchronously,
251 * by kicking the dlil_input_thread.
252 */
253 if ((i = m_howmany()) <= 0)
254 goto out;
255
256 if ((nowait == M_DONTWAIT))
257 goto out;
258
259 if (ncl < i)
260 ncl = i;
55e303ae 261 size = round_page_32(ncl * MCLBYTES);
1c79356b
A
262 mcl = (union mcluster *)kmem_mb_alloc(mb_map, size);
263
264 if (mcl == 0 && ncl > 1) {
55e303ae 265 size = round_page_32(MCLBYTES); /* Try for 1 if failed */
1c79356b
A
266 mcl = (union mcluster *)kmem_mb_alloc(mb_map, size);
267 }
268
269 if (mcl) {
270 MBUF_LOCK();
271 ncl = size / MCLBYTES;
272 for (i = 0; i < ncl; i++) {
273 if (++mclrefcnt[mtocl(mcl)] != 0)
274 panic("m_clalloc already there");
55e303ae
A
275 if (((int)mcl & PAGE_MASK) == 0) {
276 ppnum_t offset = ((char *)mcl - (char *)mbutl)/PAGE_SIZE;
277 ppnum_t new_page = pmap_find_phys(kernel_pmap, (vm_address_t) mcl);
278
279 /*
280 * In the case of no mapper being available
281 * the following code nops and returns the
282 * input page, if there is a mapper the I/O
283 * page appropriate is returned.
284 */
285 new_page = IOMapperInsertPage(mcl_paddr_base, offset, new_page);
286 mcl_paddr[offset] = new_page << 12;
287 }
1c79356b
A
288
289 mcl->mcl_next = mclfree;
290 mclfree = mcl++;
291 }
292 mbstat.m_clfree += ncl;
293 mbstat.m_clusters += ncl;
294 return (ncl);
295 } /* else ... */
296out:
297 MBUF_LOCK();
298
299 /*
300 * When non-blocking we kick the dlil thread if we havve to grow the
301 * pool or if the number of free clusters is less than requested.
302 */
303 if ((nowait == M_DONTWAIT) && (i > 0 || ncl >= mbstat.m_clfree)) {
55e303ae
A
304 mbuf_expand_mcl = 1;
305 if (mbuf_expand_thread_initialized)
306 wakeup((caddr_t)&mbuf_expand_thread_wakeup);
1c79356b
A
307 }
308
309 if (mbstat.m_clfree >= ncl)
310 return 1;
311
1c79356b
A
312 return 0;
313}
314
315/*
316 * Add more free mbufs by cutting up a cluster.
317 */
318m_expand(canwait)
319 int canwait;
320{
321 register caddr_t mcl;
322
323 if (mbstat.m_clfree < (mbstat.m_clusters >> 4))
324 /* 1/16th of the total number of cluster mbufs allocated is
325 reserved for large packets. The number reserved must
326 always be < 1/2, or future allocation will be prevented.
327 */
328 return 0;
329
330 MCLALLOC(mcl, canwait);
331 if (mcl) {
332 register struct mbuf *m = (struct mbuf *)mcl;
333 register int i = NMBPCL;
334 MBUF_LOCK();
335 mbstat.m_mtypes[MT_FREE] += i;
336 mbstat.m_mbufs += i;
337 while (i--) {
9bccf70c 338 _MFREE_MUNGE(m);
1c79356b
A
339 m->m_type = MT_FREE;
340 m->m_next = mfree;
341 mfree = m++;
342 }
343 i = m_want;
344 m_want = 0;
345 MBUF_UNLOCK();
346 if (i) wakeup((caddr_t)&mfree);
347 return 1;
348 }
349 return 0;
350}
351
352/*
353 * When MGET failes, ask protocols to free space when short of memory,
354 * then re-attempt to allocate an mbuf.
355 */
356struct mbuf *
357m_retry(canwait, type)
358 int canwait, type;
359{
1c79356b
A
360 register struct mbuf *m;
361 int wait, s;
362 funnel_t * fnl;
363 int fnl_switch = 0;
364 boolean_t funnel_state;
365
366 for (;;) {
367 (void) m_expand(canwait);
9bccf70c
A
368 _MINTGET(m, type);
369 if (m) {
370 (m)->m_next = (m)->m_nextpkt = 0;
371 (m)->m_type = (type);
372 (m)->m_data = (m)->m_dat;
373 (m)->m_flags = 0;
374 }
1c79356b
A
375 if (m || canwait == M_DONTWAIT)
376 break;
377 MBUF_LOCK();
378 wait = m_want++;
55e303ae 379 mbuf_expand_mcl = 1;
9bccf70c
A
380 if (wait == 0)
381 mbstat.m_drain++;
382 else
383 mbstat.m_wait++;
1c79356b
A
384 MBUF_UNLOCK();
385
55e303ae
A
386 if (mbuf_expand_thread_initialized)
387 wakeup((caddr_t)&mbuf_expand_thread_wakeup);
1c79356b 388
1c79356b 389 /*
55e303ae 390 * Need to be inside network funnel for m_reclaim because it calls into the
1c79356b
A
391 * socket domains and tsleep end-up calling splhigh
392 */
393 fnl = thread_funnel_get();
55e303ae 394 if (wait == 0 && fnl == network_flock) {
1c79356b 395 m_reclaim();
55e303ae
A
396 } else if (fnl != THR_FUNNEL_NULL) {
397 /* Sleep with a small timeout as insurance */
398 (void) tsleep((caddr_t)&mfree, PZERO-1, "m_retry", hz);
1c79356b 399 } else {
55e303ae
A
400 /* We are called from a non-BSD context: use mach primitives */
401 u_int64_t abstime = 0;
402
403 assert_wait((event_t)&mfree, THREAD_UNINT);
404 clock_interval_to_deadline(hz, NSEC_PER_SEC / hz, &abstime);
405 thread_set_timer_deadline(abstime);
406 if (thread_block(THREAD_CONTINUE_NULL) != THREAD_TIMED_OUT)
407 thread_cancel_timer();
1c79356b 408 }
1c79356b 409 }
55e303ae
A
410 if (m == 0)
411 mbstat.m_drops++;
1c79356b 412 return (m);
1c79356b
A
413}
414
415/*
416 * As above; retry an MGETHDR.
417 */
418struct mbuf *
419m_retryhdr(canwait, type)
420 int canwait, type;
421{
422 register struct mbuf *m;
423
424 if (m = m_retry(canwait, type)) {
425 m->m_flags |= M_PKTHDR;
426 m->m_data = m->m_pktdat;
55e303ae 427 _M_CLEAR_PKTHDR(m);
1c79356b
A
428 }
429 return (m);
430}
431
432m_reclaim()
433{
434 register struct domain *dp;
435 register struct protosw *pr;
436
437 for (dp = domains; dp; dp = dp->dom_next)
438 for (pr = dp->dom_protosw; pr; pr = pr->pr_next)
439 if (pr->pr_drain)
440 (*pr->pr_drain)();
441 mbstat.m_drain++;
442}
443
444/*
445 * Space allocation routines.
446 * These are also available as macros
447 * for critical paths.
448 */
449struct mbuf *
450m_get(nowait, type)
451 int nowait, type;
452{
453 register struct mbuf *m;
454
9bccf70c
A
455 _MINTGET(m, type);
456 if (m) {
457 m->m_next = m->m_nextpkt = 0;
458 m->m_type = type;
459 m->m_data = m->m_dat;
460 m->m_flags = 0;
461 } else
462 (m) = m_retry(nowait, type);
463
1c79356b
A
464 return (m);
465}
466
467struct mbuf *
468m_gethdr(nowait, type)
469 int nowait, type;
470{
471 register struct mbuf *m;
472
9bccf70c
A
473 _MINTGET(m, type);
474 if (m) {
475 m->m_next = m->m_nextpkt = 0;
476 m->m_type = type;
477 m->m_data = m->m_pktdat;
478 m->m_flags = M_PKTHDR;
55e303ae 479 _M_CLEAR_PKTHDR(m)
9bccf70c
A
480 } else
481 m = m_retryhdr(nowait, type);
482
483 return m;
1c79356b
A
484}
485
486struct mbuf *
487m_getclr(nowait, type)
488 int nowait, type;
489{
490 register struct mbuf *m;
491
492 MGET(m, nowait, type);
493 if (m == 0)
494 return (0);
495 bzero(mtod(m, caddr_t), MLEN);
496 return (m);
497}
498
499struct mbuf *
500m_free(m)
501 struct mbuf *m;
502{
503 struct mbuf *n = m->m_next;
504 int i, s;
505
506 if (m->m_type == MT_FREE)
507 panic("freeing free mbuf");
508
9bccf70c
A
509 /* Free the aux data if there is any */
510 if ((m->m_flags & M_PKTHDR) && m->m_pkthdr.aux)
511 {
512 m_freem(m->m_pkthdr.aux);
513 }
514
1c79356b 515 MBUF_LOCK();
9bccf70c
A
516 if ((m->m_flags & M_EXT))
517 {
1c79356b
A
518 if (MCLHASREFERENCE(m)) {
519 remque((queue_t)&m->m_ext.ext_refs);
520 } else if (m->m_ext.ext_free == NULL) {
521 union mcluster *mcl= (union mcluster *)m->m_ext.ext_buf;
9bccf70c 522 if (_MCLUNREF(mcl)) {
1c79356b
A
523 mcl->mcl_next = mclfree;
524 mclfree = mcl;
525 ++mbstat.m_clfree;
526 }
527#ifdef COMMENT_OUT
528/* *** Since m_split() increments "mclrefcnt[mtocl(m->m_ext.ext_buf)]",
529 and AppleTalk ADSP uses m_split(), this incorrect sanity check
530 caused a panic.
531*** */
532 else /* sanity check - not referenced this way */
533 panic("m_free m_ext cluster not free");
534#endif
535 } else {
536 (*(m->m_ext.ext_free))(m->m_ext.ext_buf,
537 m->m_ext.ext_size, m->m_ext.ext_arg);
538 }
539 }
540 mbstat.m_mtypes[m->m_type]--;
9bccf70c
A
541 (void) _MCLUNREF(m);
542 _MFREE_MUNGE(m);
1c79356b
A
543 m->m_type = MT_FREE;
544 mbstat.m_mtypes[m->m_type]++;
545 m->m_flags = 0;
546 m->m_next = mfree;
547 m->m_len = 0;
548 mfree = m;
549 i = m_want;
550 m_want = 0;
551 MBUF_UNLOCK();
552 if (i) wakeup((caddr_t)&mfree);
553 return (n);
554}
555
9bccf70c
A
556/* m_mclget() add an mbuf cluster to a normal mbuf */
557struct mbuf *
558m_mclget(m, nowait)
559 struct mbuf *m;
560 int nowait;
561{
562 MCLALLOC(m->m_ext.ext_buf, nowait);
563 if (m->m_ext.ext_buf) {
564 m->m_data = m->m_ext.ext_buf;
565 m->m_flags |= M_EXT;
566 m->m_ext.ext_size = MCLBYTES;
567 m->m_ext.ext_free = 0;
568 m->m_ext.ext_refs.forward = m->m_ext.ext_refs.backward =
569 &m->m_ext.ext_refs;
570 }
571
572 return m;
573}
574
575/* m_mclalloc() allocate an mbuf cluster */
576caddr_t
577m_mclalloc( nowait)
578 int nowait;
579{
580 caddr_t p;
581
582 (void)m_clalloc(1, nowait);
583 if ((p = (caddr_t)mclfree)) {
584 ++mclrefcnt[mtocl(p)];
585 mbstat.m_clfree--;
586 mclfree = ((union mcluster *)p)->mcl_next;
55e303ae
A
587 } else {
588 mbstat.m_drops++;
9bccf70c
A
589 }
590 MBUF_UNLOCK();
591
592 return p;
593}
594
595/* m_mclfree() releases a reference to a cluster allocated by MCLALLOC,
596 * freeing the cluster if the reference count has reached 0. */
597void
598m_mclfree(p)
599 caddr_t p;
600{
601 MBUF_LOCK();
602 if (--mclrefcnt[mtocl(p)] == 0) {
603 ((union mcluster *)(p))->mcl_next = mclfree;
604 mclfree = (union mcluster *)(p);
605 mbstat.m_clfree++;
606 }
607 MBUF_UNLOCK();
608}
609
610/* mcl_hasreference() checks if a cluster of an mbuf is referenced by another mbuf */
611int
612m_mclhasreference(m)
613 struct mbuf *m;
614{
615 return (m->m_ext.ext_refs.forward != &(m->m_ext.ext_refs));
616}
617
618/* */
619void
620m_copy_pkthdr(to, from)
621 struct mbuf *to, *from;
622{
623 to->m_pkthdr = from->m_pkthdr;
624 from->m_pkthdr.aux = (struct mbuf *)NULL;
625 to->m_flags = from->m_flags & M_COPYFLAGS;
626 to->m_data = (to)->m_pktdat;
627}
628
1c79356b
A
629/* Best effort to get a mbuf cluster + pkthdr under one lock.
630 * If we don't have them avail, just bail out and use the regular
631 * path.
632 * Used by drivers to allocated packets on receive ring.
633 */
634struct mbuf *
635m_getpacket(void)
636{
637 struct mbuf *m;
638 m_clalloc(1, M_DONTWAIT); /* takes the MBUF_LOCK, but doesn't release it... */
639 if ((mfree != 0) && (mclfree != 0)) { /* mbuf + cluster are available */
640 m = mfree;
641 mfree = m->m_next;
642 MCHECK(m);
643 ++mclrefcnt[mtocl(m)];
644 mbstat.m_mtypes[MT_FREE]--;
645 mbstat.m_mtypes[MT_DATA]++;
646 m->m_ext.ext_buf = (caddr_t)mclfree; /* get the cluster */
647 ++mclrefcnt[mtocl(m->m_ext.ext_buf)];
648 mbstat.m_clfree--;
649 mclfree = ((union mcluster *)(m->m_ext.ext_buf))->mcl_next;
650
651 m->m_next = m->m_nextpkt = 0;
1c79356b
A
652 m->m_type = MT_DATA;
653 m->m_data = m->m_ext.ext_buf;
654 m->m_flags = M_PKTHDR | M_EXT;
55e303ae 655 _M_CLEAR_PKTHDR(m)
9bccf70c 656 m->m_ext.ext_free = 0;
1c79356b
A
657 m->m_ext.ext_size = MCLBYTES;
658 m->m_ext.ext_refs.forward = m->m_ext.ext_refs.backward =
659 &m->m_ext.ext_refs;
660 MBUF_UNLOCK();
661 }
662 else { /* slow path: either mbuf or cluster need to be allocated anyway */
663 MBUF_UNLOCK();
664
665 MGETHDR(m, M_WAITOK, MT_DATA );
666
667 if ( m == 0 )
668 return (NULL);
669
670 MCLGET( m, M_WAITOK );
671 if ( ( m->m_flags & M_EXT ) == 0 )
672 {
673 m_free(m); m = 0;
674 }
675 }
676 return (m);
677}
678
fa4905b1 679
9bccf70c
A
680/*
681 * return a list of mbuf hdrs that point to clusters...
682 * try for num_needed, if this can't be met, return whatever
683 * number were available... set up the first num_with_pkthdrs
684 * with mbuf hdrs configured as packet headers... these are
685 * chained on the m_nextpkt field... any packets requested beyond
686 * this are chained onto the last packet header's m_next field.
687 */
fa4905b1
A
688struct mbuf *
689m_getpackets(int num_needed, int num_with_pkthdrs, int how)
690{
691 struct mbuf *m;
692 struct mbuf **np, *top;
693
694 top = NULL;
695 np = &top;
696
697 m_clalloc(num_needed, how); /* takes the MBUF_LOCK, but doesn't release it... */
698
699 while (num_needed--) {
700 if (mfree && mclfree) { /* mbuf + cluster are available */
701 m = mfree;
702 MCHECK(m);
703 mfree = m->m_next;
704 ++mclrefcnt[mtocl(m)];
705 mbstat.m_mtypes[MT_FREE]--;
706 mbstat.m_mtypes[MT_DATA]++;
707 m->m_ext.ext_buf = (caddr_t)mclfree; /* get the cluster */
708 ++mclrefcnt[mtocl(m->m_ext.ext_buf)];
709 mbstat.m_clfree--;
710 mclfree = ((union mcluster *)(m->m_ext.ext_buf))->mcl_next;
711
712 m->m_next = m->m_nextpkt = 0;
713 m->m_type = MT_DATA;
714 m->m_data = m->m_ext.ext_buf;
715 m->m_ext.ext_free = 0;
716 m->m_ext.ext_size = MCLBYTES;
717 m->m_ext.ext_refs.forward = m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
718
719 if (num_with_pkthdrs == 0)
720 m->m_flags = M_EXT;
721 else {
722 m->m_flags = M_PKTHDR | M_EXT;
55e303ae 723 _M_CLEAR_PKTHDR(m);
fa4905b1
A
724
725 num_with_pkthdrs--;
726 }
727
728 } else {
729
730 MBUF_UNLOCK();
731
732 if (num_with_pkthdrs == 0) {
733 MGET(m, how, MT_DATA );
734 } else {
735 MGETHDR(m, how, MT_DATA);
9bccf70c 736
fa4905b1
A
737 num_with_pkthdrs--;
738 }
739 if (m == 0)
740 return(top);
741
742 MCLGET(m, how);
743 if ((m->m_flags & M_EXT) == 0) {
744 m_free(m);
745 return(top);
746 }
747 MBUF_LOCK();
748 }
749 *np = m;
750
751 if (num_with_pkthdrs)
752 np = &m->m_nextpkt;
753 else
754 np = &m->m_next;
755 }
756 MBUF_UNLOCK();
757
758 return (top);
759}
760
761
9bccf70c
A
762/*
763 * return a list of mbuf hdrs set up as packet hdrs
764 * chained together on the m_nextpkt field
765 */
fa4905b1
A
766struct mbuf *
767m_getpackethdrs(int num_needed, int how)
768{
769 struct mbuf *m;
770 struct mbuf **np, *top;
771
772 top = NULL;
773 np = &top;
774
775 MBUF_LOCK();
776
777 while (num_needed--) {
778 if (m = mfree) { /* mbufs are available */
779 MCHECK(m);
780 mfree = m->m_next;
781 ++mclrefcnt[mtocl(m)];
782 mbstat.m_mtypes[MT_FREE]--;
783 mbstat.m_mtypes[MT_DATA]++;
784
785 m->m_next = m->m_nextpkt = 0;
786 m->m_type = MT_DATA;
787 m->m_flags = M_PKTHDR;
788 m->m_data = m->m_pktdat;
55e303ae 789 _M_CLEAR_PKTHDR(m);
fa4905b1
A
790
791 } else {
792
793 MBUF_UNLOCK();
794
795 m = m_retryhdr(how, MT_DATA);
796
797 if (m == 0)
798 return(top);
799
800 MBUF_LOCK();
801 }
802 *np = m;
803 np = &m->m_nextpkt;
804 }
805 MBUF_UNLOCK();
806
807 return (top);
808}
809
810
1c79356b
A
811/* free and mbuf list (m_nextpkt) while following m_next under one lock.
812 * returns the count for mbufs packets freed. Used by the drivers.
813 */
814int
815m_freem_list(m)
816 struct mbuf *m;
817{
818 struct mbuf *nextpkt;
fa4905b1 819 int i, count=0;
1c79356b 820
1c79356b 821 MBUF_LOCK();
fa4905b1 822
1c79356b
A
823 while (m) {
824 if (m)
fa4905b1 825 nextpkt = m->m_nextpkt; /* chain of linked mbufs from driver */
1c79356b 826 else
fa4905b1 827 nextpkt = 0;
9bccf70c 828
1c79356b 829 count++;
fa4905b1 830
1c79356b 831 while (m) { /* free the mbuf chain (like mfreem) */
9bccf70c
A
832
833 struct mbuf *n;
834
835 /* Free the aux data if there is any */
836 if ((m->m_flags & M_PKTHDR) && m->m_pkthdr.aux) {
837 /*
838 * Treat the current m as the nextpkt and set m
55e303ae
A
839 * to the aux data. Preserve nextpkt in m->m_nextpkt.
840 * This lets us free the aux data in this loop
841 * without having to call m_freem recursively,
842 * which wouldn't work because we've still got
843 * the lock.
9bccf70c 844 */
55e303ae 845 m->m_nextpkt = nextpkt;
9bccf70c
A
846 nextpkt = m;
847 m = nextpkt->m_pkthdr.aux;
848 nextpkt->m_pkthdr.aux = NULL;
849 }
850
851 n = m->m_next;
fa4905b1 852
1c79356b
A
853 if (n && n->m_nextpkt)
854 panic("m_freem_list: m_nextpkt of m_next != NULL");
855 if (m->m_type == MT_FREE)
856 panic("freeing free mbuf");
fa4905b1 857
1c79356b
A
858 if (m->m_flags & M_EXT) {
859 if (MCLHASREFERENCE(m)) {
860 remque((queue_t)&m->m_ext.ext_refs);
861 } else if (m->m_ext.ext_free == NULL) {
862 union mcluster *mcl= (union mcluster *)m->m_ext.ext_buf;
9bccf70c 863 if (_MCLUNREF(mcl)) {
1c79356b
A
864 mcl->mcl_next = mclfree;
865 mclfree = mcl;
866 ++mbstat.m_clfree;
867 }
868 } else {
869 (*(m->m_ext.ext_free))(m->m_ext.ext_buf,
870 m->m_ext.ext_size, m->m_ext.ext_arg);
871 }
872 }
873 mbstat.m_mtypes[m->m_type]--;
9bccf70c
A
874 (void) _MCLUNREF(m);
875 _MFREE_MUNGE(m);
fa4905b1 876 mbstat.m_mtypes[MT_FREE]++;
1c79356b 877 m->m_type = MT_FREE;
1c79356b
A
878 m->m_flags = 0;
879 m->m_len = 0;
880 m->m_next = mfree;
881 mfree = m;
882 m = n;
883 }
884 m = nextpkt; /* bump m with saved nextpkt if any */
885 }
fa4905b1
A
886 if (i = m_want)
887 m_want = 0;
888
1c79356b 889 MBUF_UNLOCK();
fa4905b1
A
890
891 if (i)
892 wakeup((caddr_t)&mfree);
893
1c79356b
A
894 return (count);
895}
896
897void
898m_freem(m)
899 register struct mbuf *m;
900{
901 while (m)
902 m = m_free(m);
903}
904
905/*
906 * Mbuffer utility routines.
907 */
908/*
909 * Compute the amount of space available
910 * before the current start of data in an mbuf.
911 */
912m_leadingspace(m)
913register struct mbuf *m;
914{
915 if (m->m_flags & M_EXT) {
916 if (MCLHASREFERENCE(m))
917 return(0);
918 return (m->m_data - m->m_ext.ext_buf);
919 }
920 if (m->m_flags & M_PKTHDR)
921 return (m->m_data - m->m_pktdat);
922 return (m->m_data - m->m_dat);
923}
924
925/*
926 * Compute the amount of space available
927 * after the end of data in an mbuf.
928 */
929m_trailingspace(m)
930register struct mbuf *m;
931{
932 if (m->m_flags & M_EXT) {
933 if (MCLHASREFERENCE(m))
934 return(0);
935 return (m->m_ext.ext_buf + m->m_ext.ext_size -
936 (m->m_data + m->m_len));
937 }
938 return (&m->m_dat[MLEN] - (m->m_data + m->m_len));
939}
940
941/*
942 * Lesser-used path for M_PREPEND:
943 * allocate new mbuf to prepend to chain,
944 * copy junk along.
9bccf70c 945 * Does not adjust packet header length.
1c79356b
A
946 */
947struct mbuf *
948m_prepend(m, len, how)
949 register struct mbuf *m;
950 int len, how;
951{
952 struct mbuf *mn;
953
954 MGET(mn, how, m->m_type);
955 if (mn == (struct mbuf *)NULL) {
956 m_freem(m);
957 return ((struct mbuf *)NULL);
958 }
959 if (m->m_flags & M_PKTHDR) {
960 M_COPY_PKTHDR(mn, m);
961 m->m_flags &= ~M_PKTHDR;
962 }
963 mn->m_next = m;
964 m = mn;
965 if (len < MHLEN)
966 MH_ALIGN(m, len);
967 m->m_len = len;
968 return (m);
969}
970
9bccf70c
A
971/*
972 * Replacement for old M_PREPEND macro:
973 * allocate new mbuf to prepend to chain,
974 * copy junk along, and adjust length.
975 *
976 */
977struct mbuf *
978m_prepend_2(m, len, how)
979 register struct mbuf *m;
980 int len, how;
981{
982 if (M_LEADINGSPACE(m) >= len) {
983 m->m_data -= len;
984 m->m_len += len;
985 } else {
986 m = m_prepend(m, len, how);
987 }
988 if ((m) && (m->m_flags & M_PKTHDR))
989 m->m_pkthdr.len += len;
990 return (m);
991}
992
1c79356b
A
993/*
994 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
995 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
996 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
997 */
998int MCFail;
999
1000struct mbuf *
1001m_copym(m, off0, len, wait)
1002 register struct mbuf *m;
1003 int off0, wait;
1004 register int len;
1005{
1006 register struct mbuf *n, **np;
1007 register int off = off0;
1008 struct mbuf *top;
1009 int copyhdr = 0;
1010
1011 if (off < 0 || len < 0)
1012 panic("m_copym");
1013 if (off == 0 && m->m_flags & M_PKTHDR)
1014 copyhdr = 1;
fa4905b1
A
1015
1016 while (off >= m->m_len) {
1c79356b
A
1017 if (m == 0)
1018 panic("m_copym");
1c79356b
A
1019 off -= m->m_len;
1020 m = m->m_next;
1021 }
1022 np = &top;
1023 top = 0;
fa4905b1
A
1024
1025 MBUF_LOCK();
1026
1c79356b
A
1027 while (len > 0) {
1028 if (m == 0) {
1029 if (len != M_COPYALL)
1030 panic("m_copym");
1031 break;
1032 }
fa4905b1
A
1033 if (n = mfree) {
1034 MCHECK(n);
1035 ++mclrefcnt[mtocl(n)];
1036 mbstat.m_mtypes[MT_FREE]--;
1037 mbstat.m_mtypes[m->m_type]++;
1038 mfree = n->m_next;
1039 n->m_next = n->m_nextpkt = 0;
1040 n->m_type = m->m_type;
1041 n->m_data = n->m_dat;
1042 n->m_flags = 0;
1043 } else {
1044 MBUF_UNLOCK();
1045 n = m_retry(wait, m->m_type);
1046 MBUF_LOCK();
1047 }
1c79356b 1048 *np = n;
fa4905b1 1049
1c79356b
A
1050 if (n == 0)
1051 goto nospace;
1052 if (copyhdr) {
1053 M_COPY_PKTHDR(n, m);
1054 if (len == M_COPYALL)
1055 n->m_pkthdr.len -= off0;
1056 else
1057 n->m_pkthdr.len = len;
1058 copyhdr = 0;
1059 }
1060 if (len == M_COPYALL) {
1061 if (min(len, (m->m_len - off)) == len) {
1062 printf("m->m_len %d - off %d = %d, %d\n",
1063 m->m_len, off, m->m_len - off,
1064 min(len, (m->m_len - off)));
1065 }
1066 }
1067 n->m_len = min(len, (m->m_len - off));
1068 if (n->m_len == M_COPYALL) {
1069 printf("n->m_len == M_COPYALL, fixing\n");
1070 n->m_len = MHLEN;
1071 }
1072 if (m->m_flags & M_EXT) {
1c79356b
A
1073 n->m_ext = m->m_ext;
1074 insque((queue_t)&n->m_ext.ext_refs, (queue_t)&m->m_ext.ext_refs);
1c79356b
A
1075 n->m_data = m->m_data + off;
1076 n->m_flags |= M_EXT;
fa4905b1 1077 } else {
1c79356b
A
1078 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
1079 (unsigned)n->m_len);
fa4905b1 1080 }
1c79356b
A
1081 if (len != M_COPYALL)
1082 len -= n->m_len;
1083 off = 0;
1084 m = m->m_next;
1085 np = &n->m_next;
1086 }
fa4905b1
A
1087 MBUF_UNLOCK();
1088
1c79356b
A
1089 if (top == 0)
1090 MCFail++;
fa4905b1 1091
1c79356b
A
1092 return (top);
1093nospace:
fa4905b1
A
1094 MBUF_UNLOCK();
1095
1c79356b
A
1096 m_freem(top);
1097 MCFail++;
1098 return (0);
1099}
1100
fa4905b1 1101
9bccf70c
A
1102/*
1103 * equivilent to m_copym except that all necessary
1104 * mbuf hdrs are allocated within this routine
1105 * also, the last mbuf and offset accessed are passed
1106 * out and can be passed back in to avoid having to
1107 * rescan the entire mbuf list (normally hung off of the socket)
1108 */
fa4905b1
A
1109struct mbuf *
1110m_copym_with_hdrs(m, off0, len, wait, m_last, m_off)
1111 register struct mbuf *m;
1112 int off0, wait;
1113 register int len;
1114 struct mbuf **m_last;
1115 int *m_off;
1116{
1117 register struct mbuf *n, **np;
1118 register int off = off0;
1119 struct mbuf *top = 0;
1120 int copyhdr = 0;
1121 int type;
1122
1123 if (off == 0 && m->m_flags & M_PKTHDR)
1124 copyhdr = 1;
1125
1126 if (*m_last) {
1127 m = *m_last;
1128 off = *m_off;
1129 } else {
1130 while (off >= m->m_len) {
1131 off -= m->m_len;
1132 m = m->m_next;
1133 }
1134 }
1135 MBUF_LOCK();
1136
1137 while (len > 0) {
1138 if (top == 0)
1139 type = MT_HEADER;
1140 else {
1141 if (m == 0)
1142 panic("m_gethdr_and_copym");
1143 type = m->m_type;
1144 }
1145 if (n = mfree) {
1146 MCHECK(n);
1147 ++mclrefcnt[mtocl(n)];
1148 mbstat.m_mtypes[MT_FREE]--;
1149 mbstat.m_mtypes[type]++;
1150 mfree = n->m_next;
1151 n->m_next = n->m_nextpkt = 0;
1152 n->m_type = type;
1153
1154 if (top) {
1155 n->m_data = n->m_dat;
1156 n->m_flags = 0;
1157 } else {
1158 n->m_data = n->m_pktdat;
1159 n->m_flags = M_PKTHDR;
55e303ae 1160 _M_CLEAR_PKTHDR(n);
fa4905b1
A
1161 }
1162 } else {
1163 MBUF_UNLOCK();
1164 if (top)
1165 n = m_retry(wait, type);
1166 else
1167 n = m_retryhdr(wait, type);
1168 MBUF_LOCK();
1169 }
1170 if (n == 0)
1171 goto nospace;
1172 if (top == 0) {
1173 top = n;
1174 np = &top->m_next;
1175 continue;
1176 } else
1177 *np = n;
1178
1179 if (copyhdr) {
1180 M_COPY_PKTHDR(n, m);
1181 n->m_pkthdr.len = len;
1182 copyhdr = 0;
1183 }
1184 n->m_len = min(len, (m->m_len - off));
1185
1186 if (m->m_flags & M_EXT) {
1187 n->m_ext = m->m_ext;
1188 insque((queue_t)&n->m_ext.ext_refs, (queue_t)&m->m_ext.ext_refs);
1189 n->m_data = m->m_data + off;
1190 n->m_flags |= M_EXT;
1191 } else {
1192 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
1193 (unsigned)n->m_len);
1194 }
1195 len -= n->m_len;
1196
1197 if (len == 0) {
1198 if ((off + n->m_len) == m->m_len) {
1199 *m_last = m->m_next;
1200 *m_off = 0;
1201 } else {
1202 *m_last = m;
1203 *m_off = off + n->m_len;
1204 }
1205 break;
1206 }
1207 off = 0;
1208 m = m->m_next;
1209 np = &n->m_next;
1210 }
1211 MBUF_UNLOCK();
1212
1213 return (top);
1214nospace:
1215 MBUF_UNLOCK();
1216
1217 if (top)
1218 m_freem(top);
1219 MCFail++;
1220 return (0);
1221}
1222
1223
1c79356b
A
1224/*
1225 * Copy data from an mbuf chain starting "off" bytes from the beginning,
1226 * continuing for "len" bytes, into the indicated buffer.
1227 */
1228void m_copydata(m, off, len, cp)
1229 register struct mbuf *m;
1230 register int off;
1231 register int len;
1232 caddr_t cp;
1233{
1234 register unsigned count;
1235
1236 if (off < 0 || len < 0)
1237 panic("m_copydata");
1238 while (off > 0) {
1239 if (m == 0)
1240 panic("m_copydata");
1241 if (off < m->m_len)
1242 break;
1243 off -= m->m_len;
1244 m = m->m_next;
1245 }
1246 while (len > 0) {
1247 if (m == 0)
1248 panic("m_copydata");
1249 count = min(m->m_len - off, len);
1250 bcopy(mtod(m, caddr_t) + off, cp, count);
1251 len -= count;
1252 cp += count;
1253 off = 0;
1254 m = m->m_next;
1255 }
1256}
1257
1258/*
1259 * Concatenate mbuf chain n to m.
1260 * Both chains must be of the same type (e.g. MT_DATA).
1261 * Any m_pkthdr is not updated.
1262 */
1263void m_cat(m, n)
1264 register struct mbuf *m, *n;
1265{
1266 while (m->m_next)
1267 m = m->m_next;
1268 while (n) {
1269 if (m->m_flags & M_EXT ||
1270 m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
1271 /* just join the two chains */
1272 m->m_next = n;
1273 return;
1274 }
1275 /* splat the data from one into the other */
1276 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
1277 (u_int)n->m_len);
1278 m->m_len += n->m_len;
1279 n = m_free(n);
1280 }
1281}
1282
1283void
1284m_adj(mp, req_len)
1285 struct mbuf *mp;
1286 int req_len;
1287{
1288 register int len = req_len;
1289 register struct mbuf *m;
1290 register count;
1291
1292 if ((m = mp) == NULL)
1293 return;
1294 if (len >= 0) {
1295 /*
1296 * Trim from head.
1297 */
1298 while (m != NULL && len > 0) {
1299 if (m->m_len <= len) {
1300 len -= m->m_len;
1301 m->m_len = 0;
1302 m = m->m_next;
1303 } else {
1304 m->m_len -= len;
1305 m->m_data += len;
1306 len = 0;
1307 }
1308 }
1309 m = mp;
1310 if (m->m_flags & M_PKTHDR)
1311 m->m_pkthdr.len -= (req_len - len);
1312 } else {
1313 /*
1314 * Trim from tail. Scan the mbuf chain,
1315 * calculating its length and finding the last mbuf.
1316 * If the adjustment only affects this mbuf, then just
1317 * adjust and return. Otherwise, rescan and truncate
1318 * after the remaining size.
1319 */
1320 len = -len;
1321 count = 0;
1322 for (;;) {
1323 count += m->m_len;
1324 if (m->m_next == (struct mbuf *)0)
1325 break;
1326 m = m->m_next;
1327 }
1328 if (m->m_len >= len) {
1329 m->m_len -= len;
1330 m = mp;
1331 if (m->m_flags & M_PKTHDR)
1332 m->m_pkthdr.len -= len;
1333 return;
1334 }
1335 count -= len;
1336 if (count < 0)
1337 count = 0;
1338 /*
1339 * Correct length for chain is "count".
1340 * Find the mbuf with last data, adjust its length,
1341 * and toss data from remaining mbufs on chain.
1342 */
1343 m = mp;
1344 if (m->m_flags & M_PKTHDR)
1345 m->m_pkthdr.len = count;
1346 for (; m; m = m->m_next) {
1347 if (m->m_len >= count) {
1348 m->m_len = count;
1349 break;
1350 }
1351 count -= m->m_len;
1352 }
1353 while (m = m->m_next)
1354 m->m_len = 0;
1355 }
1356}
1357
1358/*
1359 * Rearange an mbuf chain so that len bytes are contiguous
1360 * and in the data area of an mbuf (so that mtod and dtom
1361 * will work for a structure of size len). Returns the resulting
1362 * mbuf chain on success, frees it and returns null on failure.
1363 * If there is room, it will add up to max_protohdr-len extra bytes to the
1364 * contiguous region in an attempt to avoid being called next time.
1365 */
1366int MPFail;
1367
1368struct mbuf *
1369m_pullup(n, len)
1370 register struct mbuf *n;
1371 int len;
1372{
1373 register struct mbuf *m;
1374 register int count;
1375 int space;
1376
1377 /*
1378 * If first mbuf has no cluster, and has room for len bytes
1379 * without shifting current data, pullup into it,
1380 * otherwise allocate a new mbuf to prepend to the chain.
1381 */
1382 if ((n->m_flags & M_EXT) == 0 &&
1383 n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
1384 if (n->m_len >= len)
1385 return (n);
1386 m = n;
1387 n = n->m_next;
1388 len -= m->m_len;
1389 } else {
1390 if (len > MHLEN)
1391 goto bad;
1392 MGET(m, M_DONTWAIT, n->m_type);
1393 if (m == 0)
1394 goto bad;
1395 m->m_len = 0;
1396 if (n->m_flags & M_PKTHDR) {
1397 M_COPY_PKTHDR(m, n);
1398 n->m_flags &= ~M_PKTHDR;
1399 }
1400 }
1401 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
1402 do {
1403 count = min(min(max(len, max_protohdr), space), n->m_len);
1404 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
1405 (unsigned)count);
1406 len -= count;
1407 m->m_len += count;
1408 n->m_len -= count;
1409 space -= count;
1410 if (n->m_len)
1411 n->m_data += count;
1412 else
1413 n = m_free(n);
1414 } while (len > 0 && n);
1415 if (len > 0) {
1416 (void) m_free(m);
1417 goto bad;
1418 }
1419 m->m_next = n;
1420 return (m);
1421bad:
1422 m_freem(n);
1423 MPFail++;
1424 return (0);
1425}
1426
1427/*
1428 * Partition an mbuf chain in two pieces, returning the tail --
1429 * all but the first len0 bytes. In case of failure, it returns NULL and
1430 * attempts to restore the chain to its original state.
1431 */
1432struct mbuf *
1433m_split(m0, len0, wait)
1434 register struct mbuf *m0;
1435 int len0, wait;
1436{
1437 register struct mbuf *m, *n;
1438 unsigned len = len0, remain;
1439
1440 for (m = m0; m && len > m->m_len; m = m->m_next)
1441 len -= m->m_len;
1442 if (m == 0)
1443 return (0);
1444 remain = m->m_len - len;
1445 if (m0->m_flags & M_PKTHDR) {
1446 MGETHDR(n, wait, m0->m_type);
1447 if (n == 0)
1448 return (0);
1449 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
1450 n->m_pkthdr.len = m0->m_pkthdr.len - len0;
1451 m0->m_pkthdr.len = len0;
1452 if (m->m_flags & M_EXT)
1453 goto extpacket;
1454 if (remain > MHLEN) {
1455 /* m can't be the lead packet */
1456 MH_ALIGN(n, 0);
1457 n->m_next = m_split(m, len, wait);
1458 if (n->m_next == 0) {
1459 (void) m_free(n);
1460 return (0);
1461 } else
1462 return (n);
1463 } else
1464 MH_ALIGN(n, remain);
1465 } else if (remain == 0) {
1466 n = m->m_next;
1467 m->m_next = 0;
1468 return (n);
1469 } else {
1470 MGET(n, wait, m->m_type);
1471 if (n == 0)
1472 return (0);
1473 M_ALIGN(n, remain);
1474 }
1475extpacket:
1476 if (m->m_flags & M_EXT) {
1477 n->m_flags |= M_EXT;
1c79356b 1478 MBUF_LOCK();
0b4e3aa0
A
1479 n->m_ext = m->m_ext;
1480 insque((queue_t)&n->m_ext.ext_refs, (queue_t)&m->m_ext.ext_refs);
1c79356b 1481 MBUF_UNLOCK();
1c79356b
A
1482 n->m_data = m->m_data + len;
1483 } else {
1484 bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
1485 }
1486 n->m_len = remain;
1487 m->m_len = len;
1488 n->m_next = m->m_next;
1489 m->m_next = 0;
1490 return (n);
1491}
1492/*
1493 * Routine to copy from device local memory into mbufs.
1494 */
1495struct mbuf *
1496m_devget(buf, totlen, off0, ifp, copy)
1497 char *buf;
1498 int totlen, off0;
1499 struct ifnet *ifp;
1500 void (*copy)();
1501{
1502 register struct mbuf *m;
1503 struct mbuf *top = 0, **mp = &top;
1504 register int off = off0, len;
1505 register char *cp;
1506 char *epkt;
1507
1508 cp = buf;
1509 epkt = cp + totlen;
1510 if (off) {
1511 /*
1512 * If 'off' is non-zero, packet is trailer-encapsulated,
1513 * so we have to skip the type and length fields.
1514 */
1515 cp += off + 2 * sizeof(u_int16_t);
1516 totlen -= 2 * sizeof(u_int16_t);
1517 }
1518 MGETHDR(m, M_DONTWAIT, MT_DATA);
1519 if (m == 0)
1520 return (0);
1521 m->m_pkthdr.rcvif = ifp;
1522 m->m_pkthdr.len = totlen;
1523 m->m_len = MHLEN;
1524
1525 while (totlen > 0) {
1526 if (top) {
1527 MGET(m, M_DONTWAIT, MT_DATA);
1528 if (m == 0) {
1529 m_freem(top);
1530 return (0);
1531 }
1532 m->m_len = MLEN;
1533 }
1534 len = min(totlen, epkt - cp);
1535 if (len >= MINCLSIZE) {
1536 MCLGET(m, M_DONTWAIT);
1537 if (m->m_flags & M_EXT)
1538 m->m_len = len = min(len, MCLBYTES);
1539 else {
1540 /* give up when it's out of cluster mbufs */
1541 if (top)
1542 m_freem(top);
1543 m_freem(m);
1544 return (0);
1545 }
1546 } else {
1547 /*
1548 * Place initial small packet/header at end of mbuf.
1549 */
1550 if (len < m->m_len) {
1551 if (top == 0 && len + max_linkhdr <= m->m_len)
1552 m->m_data += max_linkhdr;
1553 m->m_len = len;
1554 } else
1555 len = m->m_len;
1556 }
1557 if (copy)
1558 copy(cp, mtod(m, caddr_t), (unsigned)len);
1559 else
1560 bcopy(cp, mtod(m, caddr_t), (unsigned)len);
1561 cp += len;
1562 *mp = m;
1563 mp = &m->m_next;
1564 totlen -= len;
1565 if (cp == epkt)
1566 cp = buf;
1567 }
1568 return (top);
1569}
1570
1571/*
1572 * Cluster freelist allocation check. The mbuf lock must be held.
1573 * Ensure hysteresis between hi/lo.
1574 */
1575static int
1576m_howmany()
1577{
1578 register int i;
1579
1580 /* Under minimum */
1581 if (mbstat.m_clusters < MINCL)
1582 return (MINCL - mbstat.m_clusters);
1583 /* Too few (free < 1/2 total) and not over maximum */
1584 if (mbstat.m_clusters < nmbclusters &&
1585 (i = ((mbstat.m_clusters >> 1) - mbstat.m_clfree)) > 0)
1586 return i;
1587 return 0;
1588}
1589
1590
1591/*
1592 * Copy data from a buffer back into the indicated mbuf chain,
1593 * starting "off" bytes from the beginning, extending the mbuf
1594 * chain if necessary.
1595 */
1596void
1597m_copyback(m0, off, len, cp)
1598 struct mbuf *m0;
1599 register int off;
1600 register int len;
1601 caddr_t cp;
1602{
1603 register int mlen;
1604 register struct mbuf *m = m0, *n;
1605 int totlen = 0;
1606
1607 if (m0 == 0)
1608 return;
1609 while (off > (mlen = m->m_len)) {
1610 off -= mlen;
1611 totlen += mlen;
1612 if (m->m_next == 0) {
1613 n = m_getclr(M_DONTWAIT, m->m_type);
1614 if (n == 0)
1615 goto out;
1616 n->m_len = min(MLEN, len + off);
1617 m->m_next = n;
1618 }
1619 m = m->m_next;
1620 }
1621 while (len > 0) {
1622 mlen = min (m->m_len - off, len);
1623 bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
1624 cp += mlen;
1625 len -= mlen;
1626 mlen += off;
1627 off = 0;
1628 totlen += mlen;
1629 if (len == 0)
1630 break;
1631 if (m->m_next == 0) {
1632 n = m_get(M_DONTWAIT, m->m_type);
1633 if (n == 0)
1634 break;
1635 n->m_len = min(MLEN, len);
1636 m->m_next = n;
1637 }
1638 m = m->m_next;
1639 }
1640out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
1641 m->m_pkthdr.len = totlen;
1642}
1643
1644
1645char *mcl_to_paddr(register char *addr) {
1646 register int base_phys;
1647
1648 if (addr < (char *)mbutl || addr >= (char *)embutl)
1649 return (0);
1650 base_phys = mcl_paddr[(addr - (char *)mbutl) >> PAGE_SHIFT];
1651
1652 if (base_phys == 0)
1653 return (0);
1654 return ((char *)((int)base_phys | ((int)addr & PAGE_MASK)));
1655}
1656
1657/*
1658 * Dup the mbuf chain passed in. The whole thing. No cute additional cruft.
1659 * And really copy the thing. That way, we don't "precompute" checksums
1660 * for unsuspecting consumers.
1661 * Assumption: m->m_nextpkt == 0.
1662 * Trick: for small packets, don't dup into a cluster. That way received
1663 * packets don't take up too much room in the sockbuf (cf. sbspace()).
1664 */
1665int MDFail;
1666
1667struct mbuf *
1668m_dup(register struct mbuf *m, int how)
1669{ register struct mbuf *n, **np;
1670 struct mbuf *top;
1671 int copyhdr = 0;
1672
1673 np = &top;
1674 top = 0;
1675 if (m->m_flags & M_PKTHDR)
1676 copyhdr = 1;
1677
1678 /*
1679 * Quick check: if we have one mbuf and its data fits in an
1680 * mbuf with packet header, just copy and go.
1681 */
1682 if (m->m_next == NULL)
1683 { /* Then just move the data into an mbuf and be done... */
1684 if (copyhdr)
1685 { if (m->m_pkthdr.len <= MHLEN)
1686 { if ((n = m_gethdr(how, m->m_type)) == NULL)
1687 return(NULL);
1688 n->m_len = m->m_len;
1689 n->m_flags |= (m->m_flags & M_COPYFLAGS);
1690 n->m_pkthdr.len = m->m_pkthdr.len;
1691 n->m_pkthdr.rcvif = m->m_pkthdr.rcvif;
1692 n->m_pkthdr.header = NULL;
fa4905b1
A
1693 n->m_pkthdr.csum_flags = 0;
1694 n->m_pkthdr.csum_data = 0;
1c79356b 1695 n->m_pkthdr.aux = NULL;
fa4905b1
A
1696 n->m_pkthdr.reserved1 = 0;
1697 n->m_pkthdr.reserved2 = 0;
1c79356b
A
1698 bcopy(m->m_data, n->m_data, m->m_pkthdr.len);
1699 return(n);
1700 }
1701 } else if (m->m_len <= MLEN)
1702 { if ((n = m_get(how, m->m_type)) == NULL)
1703 return(NULL);
1704 bcopy(m->m_data, n->m_data, m->m_len);
1705 n->m_len = m->m_len;
1706 return(n);
1707 }
1708 }
1709 while (m)
1710 {
1711#if BLUE_DEBUG
1712 kprintf("<%x: %x, %x, %x\n", m, m->m_flags, m->m_len,
1713 m->m_data);
1714#endif
1715 if (copyhdr)
1716 n = m_gethdr(how, m->m_type);
1717 else
1718 n = m_get(how, m->m_type);
1719 if (n == 0)
1720 goto nospace;
1721 if (m->m_flags & M_EXT)
1722 { MCLGET(n, how);
1723 if ((n->m_flags & M_EXT) == 0)
1724 goto nospace;
1725 }
1726 *np = n;
1727 if (copyhdr)
1728 { /* Don't use M_COPY_PKTHDR: preserve m_data */
1729 n->m_pkthdr = m->m_pkthdr;
1730 n->m_flags |= (m->m_flags & M_COPYFLAGS);
1731 copyhdr = 0;
1732 if ((n->m_flags & M_EXT) == 0)
1733 n->m_data = n->m_pktdat;
1734 }
1735 n->m_len = m->m_len;
1736 /*
1737 * Get the dup on the same bdry as the original
1738 * Assume that the two mbufs have the same offset to data area
1739 * (up to word bdries)
1740 */
1741 bcopy(mtod(m, caddr_t), mtod(n, caddr_t), (unsigned)n->m_len);
1742 m = m->m_next;
1743 np = &n->m_next;
1744#if BLUE_DEBUG
1745 kprintf(">%x: %x, %x, %x\n", n, n->m_flags, n->m_len,
1746 n->m_data);
1747#endif
1748 }
1749
1750 if (top == 0)
1751 MDFail++;
1752 return (top);
1753 nospace:
1754 m_freem(top);
1755 MDFail++;
1756 return (0);
1757}
1758
9bccf70c
A
1759int
1760m_mclref(struct mbuf *p)
1761{
1762 return (_MCLREF(p));
1763}
1764
1765int
1766m_mclunref(struct mbuf *p)
1767{
1768 return (_MCLUNREF(p));
1769}
1770
1771/* change mbuf to new type */
1772void
1773m_mchtype(struct mbuf *m, int t)
1774{
1775 MBUF_LOCK();
1776 mbstat.m_mtypes[(m)->m_type]--;
1777 mbstat.m_mtypes[t]++;
1778 (m)->m_type = t;
1779 MBUF_UNLOCK();
1780}
1781
1782void *m_mtod(struct mbuf *m)
1783{
1784 return ((m)->m_data);
1785}
1786
1787struct mbuf *m_dtom(void *x)
1788{
1789 return ((struct mbuf *)((u_long)(x) & ~(MSIZE-1)));
1790}
1791
1792int m_mtocl(void *x)
1793{
1794 return (((char *)(x) - (char *)mbutl) / sizeof(union mcluster));
1795}
1796
1797union mcluster *m_cltom(int x)
1798{
1799 return ((union mcluster *)(mbutl + (x)));
1800}
1801
1802
1803void m_mcheck(struct mbuf *m)
1804{
1805 if (m->m_type != MT_FREE)
1806 panic("mget MCHECK: m_type=%x m=%x", m->m_type, m);
1807}
1808
55e303ae
A
1809void
1810mbuf_expand_thread(void)
1c79356b 1811{
55e303ae
A
1812 while (1) {
1813 int expand_mcl;
1814 MBUF_LOCK();
1815 expand_mcl = mbuf_expand_mcl;
1816 mbuf_expand_mcl = 0;
1817 MBUF_UNLOCK();
1818 if (expand_mcl) {
1819 caddr_t p;
1820 MCLALLOC(p, M_WAIT);
1821 if (p) MCLFREE(p);
1c79356b 1822 }
55e303ae
A
1823 assert_wait(&mbuf_expand_thread_wakeup, THREAD_UNINT);
1824 (void) thread_block(mbuf_expand_thread);
1c79356b 1825 }
1c79356b
A
1826}
1827
55e303ae
A
1828void
1829mbuf_expand_thread_init(void)
1830{
1831 mbuf_expand_thread_initialized++;
1832 mbuf_expand_thread();
1833}
1c79356b 1834