tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / workbench / network / stacks / AROSTCP / bsdsocket / kern / uipc_mbuf.c
blobb5a570c5820313e9499d79207e2d241895e0777d
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
23 /*
24 * Mach Operating System
25 * Copyright (c) 1992 Carnegie Mellon University
26 * All Rights Reserved.
28 * Permission to use, copy, modify and distribute this software and its
29 * documentation is hereby granted, provided that both the copyright
30 * notice and this permission notice appear in all copies of the
31 * software, derivative works or modified versions, and any portions
32 * thereof, and that both notices appear in supporting documentation.
34 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
35 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
36 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
38 * Carnegie Mellon requests users of this software to return to
40 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
41 * School of Computer Science
42 * Carnegie Mellon University
43 * Pittsburgh PA 15213-3890
45 * any improvements or extensions that they make and grant Carnegie Mellon
46 * the rights to redistribute these changes.
50 * Copyright (c) 1982, 1986, 1988, 1991 Regents of the University of California.
51 * All rights reserved.
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
55 * are met:
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 * must display the following acknowledgement:
63 * This product includes software developed by the University of
64 * California, Berkeley and its contributors.
65 * 4. Neither the name of the University nor the names of its contributors
66 * may be used to endorse or promote products derived from this software
67 * without specific prior written permission.
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
79 * SUCH DAMAGE.
81 * @(#)uipc_mbuf.c 7.19 (Berkeley) 4/20/91
84 #include <conf.h>
86 #include <sys/param.h>
87 #include <sys/malloc.h>
88 #include <sys/mbuf.h>
89 #include <sys/kernel.h>
90 #include <sys/syslog.h>
91 #include <sys/systm.h>
92 #include <sys/domain.h>
93 #include <sys/protosw.h>
94 #include <sys/synch.h>
96 #include <kern/amiga_includes.h>
98 #include <dos/rdargs.h>
101 * Configuration information.
103 struct mbconf mbconf = {
104 2, /* # of mbuf chunks to allocate initially */
105 //8,
106 64, /* # of mbufs to allocate at a time */
107 //256,
108 4, /* # of clusters to allocate at a time */
109 //256, /* maximum memory to use (in kilobytes) */
110 1024,
111 2048 /* size of the mbuf cluster */
115 * List of free mbufs. Access to this list is protected by splimp()
117 struct mbuf *mfree = NULL;
119 struct mbstat mbstat = { 0 };
121 struct mcluster *mclfree = NULL;
123 int max_linkhdr = 0; /* largest link-level header */
124 int max_protohdr = 0; /* largest protocol header */
125 int max_hdr = 0; /* largest link+protocol header */
126 int max_datalen = 0; /* MHLEN - max_hdr */
129 * Header structure that is placed at the start of every allocated memory
130 * region to be freed on deinit. All memory alloctions are thus
131 * sizeof(memHeader) larger and the data pointer is set past this header
132 * before used. These headers are linked together and the mbufmem pointer
133 * holds the pointer to the start of the list.
135 struct memHeader {
136 struct memHeader *next;
137 ULONG size;
140 static struct memHeader *mbufmem = NULL;
142 static BOOL initialized = FALSE;
144 LONG mb_read_stats(struct CSource *args, UBYTE **errstrp, struct CSource *res)
146 int i, total = 0;
147 UBYTE *p = res->CS_Buffer;
148 #if defined(__AROS__)
149 D(bug("[AROSTCP](uipc_mbuf.c) mb_read_stats()\n"));
150 #endif
152 for(i = 0; i < MTCOUNT; i++) {
153 p += sprintf(p, "%ld ", (long)mbstat.m_mtypes[i]);
154 total += mbstat.m_mtypes[i];
156 p += sprintf(p, "%ld", (long)total);
158 #if defined(__AROS__)
159 D(bug("[AROSTCP](uipc_mbuf.c) mb_read_stats: %s\n", res->CS_Buffer));
160 #endif
162 res->CS_CurChr = p - res->CS_Buffer;
163 return RETURN_OK;
166 int
167 mb_check_conf(void *dp, IPTR newvalue)
169 #if defined(__AROS__)
170 D(bug("[AROSTCP](uipc_mbuf.c) mb_check_conf(0x%08x, %d)\n", dp, newvalue));
171 #endif
173 if ((u_long *)dp == &mbconf.initial_mbuf_chunks) {
174 if (newvalue > 0)
175 return TRUE;
177 else
178 if (dp == &mbconf.mbufchunk) {
179 if (newvalue >= 32)
180 return TRUE;
182 else
183 if (dp == &mbconf.clusterchunk) {
184 if (newvalue > 0)
185 return TRUE;
187 else
188 if (dp == &mbconf.maxmem) {
189 if (newvalue > 32) /* kilobytes */
190 return TRUE;
192 else
193 if (dp == &mbconf.mclbytes) {
194 if (newvalue >= MINCLSIZE)
195 return TRUE;
198 return FALSE;
202 * mbinit() must be called before any other mbuf related function (exept the
203 * mb_check_conf() which is called at configuration time). This
204 * allocates memory from the system in one big chunk. This memory will not be
205 * freed until AMITCP/IP is shut down.
208 BOOL
209 mbinit(void)
211 spl_t s;
212 #if defined(__AROS__)
213 D(bug("[AROSTCP](uipc_mbuf.c) mbinit()\n"));
214 #endif
217 * Return success if already initialized
219 if (initialized)
220 return TRUE;
222 s = splimp();
224 * Initialize the list headers to NULL
226 mfree = NULL;
227 mclfree = NULL;
230 * Preallocate some mbufs and mbuf clusters.
232 initialized =
233 (m_alloc(mbconf.initial_mbuf_chunks * mbconf.mbufchunk, M_WAIT)
234 && m_clalloc(mbconf.clusterchunk, M_WAIT));
236 splx(s);
238 if (!initialized) {
239 #if defined(__AROS__)
240 D(bug("[AROSTCP](uipc_mbuf.c) mbinit: Failed to allocate memory!\n"));
241 #endif
242 __log(LOG_ERR, "mbinit: Failed to allocate memory.");
243 mbdeinit();
245 return (initialized);
249 * Free all memory allocated by mbuf subsystem. This must be the last mbuf
250 * related function called. (Implying that NO mbuf allocations should be done
251 * concurrently with this!)
253 * This is new function to AMITCP/IP.
255 void
256 mbdeinit(void)
258 struct memHeader *next;
259 #if defined(__AROS__)
260 D(bug("[AROSTCP](uipc_mbuf.c) mbdeinit()\n"));
261 #endif
264 * free all memory chunks
266 while (mbufmem) {
267 #if defined(__AROS__)
268 D(bug("[AROSTCP](uipc_mbuf.c) mbdeinit: Freeing %d bytes @ 0x%08x\n", mbufmem, mbufmem->size));
269 #endif
270 next = mbufmem->next;
271 mbstat.m_memused -= mbufmem->size;
272 FreeMem(mbufmem, mbufmem->size);
273 mbufmem = next;
275 initialized = FALSE;
279 * Allocate memory for mbufs.
280 * and place on the mbuf free list.
281 * The canwait argument is currently ignored.
283 * MUST be called at splimp!
285 BOOL
286 m_alloc(int howmany, int canwait)
289 * Note that mbufs must be aligned on MSIZE boundary
290 * for dtom to work correctly. This is archieved by allocating size for one
291 * additional mbuf per chunk so that given memory can be aligned properly.
293 struct mbuf *m;
294 struct memHeader *mh;
295 ULONG size;
296 #if defined(__AROS__)
297 D(bug("[AROSTCP](uipc_mbuf.c) m_alloc()\n"));
298 #endif
300 size = MSIZE * (howmany + 1) + sizeof(struct memHeader);
303 * check if allowed to allocate more
305 if (mbstat.m_memused + size > mbconf.maxmem * 1024) {
306 #if defined(__AROS__)
307 D(bug("[AROSTCP](uipc_mbuf.c) m_alloc: max amount of memory already used (%ld bytes).\n",
308 mbstat.m_memused));
309 #endif
310 __log(LOG_ERR, "m_alloc: max amount of memory already used (%ld bytes).",
311 mbstat.m_memused);
312 return FALSE;
315 mh = AllocMem(size, MEMF_PUBLIC); /* public since used from interrupts */
316 if (mh == NULL) {
317 #if defined(__AROS__)
318 D(bug("[AROSTCP](uipc_mbuf.c) m_alloc: Cannot allocate memory for mbufs\n"));
319 #endif
320 __log(LOG_ERR, "m_alloc: Cannot allocate memory for mbufs.");
321 return FALSE;
325 * initialize the memHeader and link it to the chain of allocated memory
326 * blocks
328 mbstat.m_memused += size; /* add to the total */
329 mh->size = size;
330 mh->next = mbufmem;
331 mbufmem = mh;
332 mh++; /* pass by the memHeader */
335 * update the statistics
337 mbstat.m_mbufs += howmany;
340 * link mbufs into the free list
342 m = dtom(((caddr_t)mh) + MSIZE - 1); /* correctly aligned mbuf pointer */
343 while(howmany--) {
344 m->m_next = mfree;
345 mfree = m++;
347 return TRUE;
351 * Allocate some number of mbuf clusters
352 * and place on cluster free list.
353 * The canwait argument is currently ignored.
354 * MUST be called at splimp.
356 BOOL
357 m_clalloc(int ncl, int canwait)
359 struct memHeader *mh;
360 struct mcluster *p;
361 ULONG size;
362 short i;
363 #if defined(__AROS__)
364 D(bug("[AROSTCP](uipc_mbuf.c) m_clalloc()\n"));
365 #endif
368 * struct mcluster has variable length buffer so its size is not calculated
369 * in sizeof(struct mcluster). The size of the buffer is mbconf.mclbytes.
370 * Each memory block allocated is prepended by the memHeader, so size
371 * must be allocted for it, too.
373 size = ncl * (sizeof(struct mcluster) + mbconf.mclbytes)
374 + sizeof(struct memHeader);
377 * check if allowed to allocate more
379 if (mbstat.m_memused + size > mbconf.maxmem * 1024) {
380 #if defined(__AROS__)
381 D(bug("[AROSTCP](uipc_mbuf.c) m_clalloc: max amount of memory already used (%ld bytes).\n",
382 mbstat.m_memused));
383 #endif
384 __log(LOG_ERR, "m_clalloc: max amount of memory already used (%ld bytes).",
385 mbstat.m_memused);
386 return FALSE;
389 mh = AllocMem(size, MEMF_PUBLIC); /* public since used from interrupts */
390 if (mh == NULL) {
391 #if defined(__AROS__)
392 D(bug("[AROSTCP](uipc_mbuf.c) m_clalloc: Cannot allocate memory for mbuf clusters\n"));
393 #endif
394 __log(LOG_ERR, "m_clalloc: Cannot allocate memory for mbuf clusters");
395 return FALSE;
398 * initialize the memHeader and link it to the chain of allocated memory
399 * blocks
401 mbstat.m_memused += size;
402 mh->size = size;
403 mh->next = mbufmem;
404 mbufmem = mh;
405 mh++; /* pass by the memHeader */
407 * link clusters to the free list
409 for (i = 0, p = (struct mcluster *)mh;
410 i < ncl;
411 i++, p = (struct mcluster*)((char *)(p + 1) + mbconf.mclbytes)) {
412 p->mcl.mcl_next = mclfree;
413 mclfree = p;
414 mbstat.m_clfree++;
416 mbstat.m_clusters += ncl;
418 return TRUE;
422 * When MGET failes, ask protocols to free space when short of memory,
423 * then re-attempt to allocate an mbuf.
425 * Allocate more memory for mbufs if there still are no mbufs left
427 * MUST be called at splimp.
429 struct mbuf *
430 m_retry(int canwait, int type)
432 register struct mbuf *m;
433 #if defined(__AROS__)
434 D(bug("[AROSTCP](uipc_mbuf.c) m_retry()\n"));
435 #endif
437 m_reclaim();
440 * Try to allocate more memory if still no free mbufs
442 if (!mfree)
443 m_alloc(mbconf.mbufchunk, canwait);
445 #define m_retry(i, t) /*mbstat.m_drops++,*/NULL
446 MGET(m, canwait, type);
447 #undef m_retry
448 return (m);
451 void
452 m_reclaim()
454 register struct domain *dp;
455 register struct protosw *pr;
456 spl_t s = splimp();
457 #if defined(__AROS__)
458 D(bug("[AROSTCP](uipc_mbuf.c) m_reclaim()\n"));
459 #endif
461 for (dp = domains; dp; dp = dp->dom_next)
462 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
463 if (pr->pr_drain)
464 (*pr->pr_drain)();
465 splx(s);
466 mbstat.m_drain++;
470 * Space allocation routines.
471 * These are also available as macros
472 * for critical paths.
474 struct mbuf *
475 m_get(canwait, type)
476 int canwait, type;
478 register struct mbuf *m;
479 #if defined(__AROS__)
480 D(bug("[AROSTCP](uipc_mbuf.c) m_get(canwait:%d, type:%d)\n", canwait, type));
481 #endif
483 MGET(m, canwait, type);
484 #if defined(__AROS__)
485 D(bug("[AROSTCP](uipc_mbuf.c) m_get: returning 0x%08x\n", m));
486 #endif
488 return (m);
491 struct mbuf *
492 m_gethdr(canwait, type)
493 int canwait, type;
495 register struct mbuf *m;
496 #if defined(__AROS__)
497 D(bug("[AROSTCP](uipc_mbuf.c) m_gethdr()\n"));
498 #endif
500 MGETHDR(m, canwait, type);
501 return (m);
504 struct mbuf *
505 m_getclr(canwait, type)
506 int canwait, type;
508 register struct mbuf *m;
509 #if defined(__AROS__)
510 D(bug("[AROSTCP](uipc_mbuf.c) m_getclr()\n"));
511 #endif
513 MGET(m, canwait, type);
514 if (m == 0)
515 return (0);
516 aligned_bzero_const(mtod(m, caddr_t), MLEN);
517 return (m);
520 struct mbuf *
521 m_free(m)
522 struct mbuf *m;
524 register struct mbuf *n;
525 #if defined(__AROS__)
526 D(bug("[AROSTCP](uipc_mbuf.c) m_free()\n"));
527 #endif
529 MFREE(m, n);
530 return (n);
533 void
534 m_freem(m)
535 register struct mbuf *m;
537 register struct mbuf *n;
538 #if defined(__AROS__)
539 D(bug("[AROSTCP](uipc_mbuf.c) m_freem(0x%08x)\n", m));
540 #endif
542 if (m == NULL)
544 #if defined(__AROS__)
545 D(bug("[AROSTCP](uipc_mbuf.c) m_freem: Attempting to free NOTHING!!\n"));
546 #endif
547 return;
549 do {
550 MFREE(m, n);
551 } while (m = n);
555 * Mbuffer utility routines.
559 * Lesser-used path for M_PREPEND:
560 * allocate new mbuf to prepend to chain,
561 * copy junk along.
563 struct mbuf *
564 m_prepend(m, len, canwait)
565 register struct mbuf *m;
566 int len, canwait;
568 struct mbuf *mn;
569 #if defined(__AROS__)
570 D(bug("[AROSTCP](uipc_mbuf.c) m_prepend(0x%08x, len = %d)\n", m, len));
571 #endif
573 MGET(mn, canwait, m->m_type);
574 if (mn == NULL) {
575 m_freem(m);
576 return (NULL);
578 if (m->m_flags & M_PKTHDR) {
579 M_COPY_PKTHDR(mn, m);
580 m->m_flags &= ~M_PKTHDR;
582 mn->m_next = m;
583 m = mn;
584 if (len < MHLEN)
585 MH_ALIGN(m, len);
586 m->m_len = len;
587 return (m);
591 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
592 * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
593 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
595 int MCFail;
597 struct mbuf *
598 m_copym(m, off0, len, wait)
599 register struct mbuf *m;
600 int off0, wait;
601 register int len;
603 register struct mbuf *n, **np;
604 register int off = off0;
605 struct mbuf *top = NULL;
606 int copyhdr = 0;
607 #if defined(__AROS__)
608 D(bug("[AROSTCP](uipc_mbuf.c) m_copym(0x%08x, len = %d)\n", m, len));
609 #endif
611 if (off < 0 || len < 0) {
612 #if defined(__AROS__)
613 D(bug("[AROSTCP](uipc_mbuf.c) m_copym: bad args\n"));
614 #endif
615 __log(LOG_ERR, "m_copym: Bad arguments");
616 goto nospace;
618 if (off == 0 && m->m_flags & M_PKTHDR)
619 copyhdr = 1;
621 * find first mbuf to copy data from
623 while (off > 0) {
624 if (m == 0) {
625 #if defined(__AROS__)
626 D(bug("[AROSTCP](uipc_mbuf.c) m_copym: short mbuf chain!\n"));
627 #endif
628 __log(LOG_ERR, "m_copym: short mbuf chain");
629 goto nospace;
631 if (off < m->m_len)
632 break;
633 off -= m->m_len;
634 m = m->m_next;
636 np = &top;
637 while (len > 0) {
638 if (m == 0) {
639 if (len != M_COPYALL) {
640 #if defined(__AROS__)
641 D(bug("[AROSTCP](uipc_mbuf.c) m_copym: short mbuf chain!!\n"));
642 #endif
643 __log(LOG_ERR, "m_copym: short mbuf chain");
644 goto nospace;
646 break;
648 MGET(n, wait, m->m_type);
649 *np = n;
650 if (n == 0)
651 goto nospace;
652 if (copyhdr) {
653 M_COPY_PKTHDR(n, m);
654 if (len == M_COPYALL)
655 n->m_pkthdr.len -= off0;
656 else
657 n->m_pkthdr.len = len;
658 copyhdr = 0;
660 n->m_len = MIN(len, m->m_len - off);
662 if (m->m_flags & M_EXT) {
663 n->m_data = m->m_data + off;
664 m->m_ext.ext_buf->mcl.mcl_refcnt++;
665 n->m_ext = m->m_ext;
666 n->m_flags |= M_EXT;
667 } else
668 bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
669 (unsigned)n->m_len);
670 if (len != M_COPYALL)
671 len -= n->m_len;
672 off = 0;
673 m = m->m_next;
674 np = &n->m_next;
676 if (top == 0)
677 MCFail++;
678 return (top);
679 nospace:
680 m_freem(top);
681 MCFail++;
682 return NULL;
686 * Copy data from an mbuf chain starting "off" bytes from the beginning,
687 * continuing for "len" bytes, into the indicated buffer.
689 void
690 m_copydata(m, off, len, cp)
691 register struct mbuf *m;
692 register int off;
693 register int len;
694 caddr_t cp;
696 register unsigned count;
697 #if defined(__AROS__)
698 D(bug("[AROSTCP](uipc_mbuf.c) m_copydata(0x%08x, len = %d)\n", m, len));
699 #endif
701 if (off < 0 || len < 0) {
702 #if defined(__AROS__)
703 D(bug("[AROSTCP](uipc_mbuf.c) m_copydata: bad arguments!\n"));
704 #endif
705 __log(LOG_ERR, "m_copydata: bad arguments");
706 return;
708 while (off > 0) {
709 if (m == 0) {
710 #if defined(__AROS__)
711 D(bug("[AROSTCP](uipc_mbuf.c) m_copydata: short mbuf chain to copy from!\n"));
712 #endif
713 __log(LOG_ERR, "m_copydata: short mbuf chain to copy from");
714 return;
716 if (off < m->m_len)
717 break;
718 off -= m->m_len;
719 m = m->m_next;
721 while (len > 0) {
722 if (m == 0) {
723 #if defined(__AROS__)
724 D(bug("[AROSTCP](uipc_mbuf.c) m_copydata: short mbuf chain to copy from!!\n"));
725 #endif
726 __log(LOG_ERR, "m_copydata: short mbuf chain to copy from");
727 return;
729 count = MIN(m->m_len - off, len);
730 bcopy(mtod(m, caddr_t) + off, cp, count);
731 len -= count;
732 cp += count;
733 off = 0;
734 m = m->m_next;
739 * Concatenate mbuf chain n to m.
740 * Both chains must be of the same type (e.g. MT_DATA).
741 * Any m_pkthdr is not updated.
743 void
744 m_cat(m, n)
745 register struct mbuf *m, *n;
747 #if defined(__AROS__)
748 D(bug("[AROSTCP](uipc_mbuf.c) m_cat(0x%08x, 0x%08x)\n", m, n));
749 #endif
751 while (m->m_next)
752 m = m->m_next;
753 while (n) {
754 if (m->m_flags & M_EXT ||
755 m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
756 /* just join the two chains */
757 m->m_next = n;
758 return;
760 /* splat the data from one into the other */
761 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
762 (u_int)n->m_len);
763 m->m_len += n->m_len;
764 n = m_free(n);
768 void
769 m_adj(struct mbuf *mp, int req_len)
771 register int len = req_len;
772 register struct mbuf *m;
773 register int count;
774 #if defined(__AROS__)
775 D(bug("[AROSTCP](uipc_mbuf.c) m_adj()\n"));
776 #endif
778 if ((m = mp) == NULL)
779 return;
780 if (len >= 0) {
782 * Trim from head.
784 while (m != NULL && len > 0) {
785 if (m->m_len <= len) {
786 len -= m->m_len;
787 m->m_len = 0;
788 m = m->m_next;
789 } else {
790 m->m_len -= len;
791 m->m_data += len;
792 len = 0;
795 m = mp;
796 if (mp->m_flags & M_PKTHDR)
797 m->m_pkthdr.len -= (req_len - len);
798 } else {
800 * Trim from tail. Scan the mbuf chain,
801 * calculating its length and finding the last mbuf.
802 * If the adjustment only affects this mbuf, then just
803 * adjust and return. Otherwise, rescan and truncate
804 * after the remaining size.
806 len = -len;
807 count = 0;
808 for (;;) {
809 count += m->m_len;
810 if (m->m_next == (struct mbuf *)0)
811 break;
812 m = m->m_next;
814 if (m->m_len >= len) {
815 m->m_len -= len;
816 if ((mp = m)->m_flags & M_PKTHDR)
817 m->m_pkthdr.len -= len;
818 return;
820 count -= len;
821 if (count < 0)
822 count = 0;
824 * Correct length for chain is "count".
825 * Find the mbuf with last data, adjust its length,
826 * and toss data from remaining mbufs on chain.
828 m = mp;
829 if (m->m_flags & M_PKTHDR)
830 m->m_pkthdr.len = count;
831 for (; m; m = m->m_next) {
832 if (m->m_len >= count) {
833 m->m_len = count;
834 break;
836 count -= m->m_len;
838 while (m = m->m_next)
839 m->m_len = 0;
844 * Rearrange an mbuf chain so that len bytes from the beginning are
845 * contiguous and in the data area of an mbuf (so that mtod and dtom
846 * will work for a structure of size len). Note that resulting
847 * structure is assumed to get properly aligned. This will happen only if
848 * there is no odd-length data before the structure. Fortunately all
849 * headers are before any data in the packet and are of even length.
850 * Returns the resulting mbuf chain on success, frees it and returns
851 * null on failure. If there is room, it will add up to max_protohdr-len
852 * extra bytes to the contiguous region in an attempt to avoid being
853 * called next time.
855 int MPFail;
857 struct mbuf *
858 m_pullup(n, len)
859 register struct mbuf *n;
860 int len;
862 register struct mbuf *m;
863 register int count;
864 int space;
865 #if defined(__AROS__)
866 D(bug("[AROSTCP](uipc_mbuf.c) m_pullup()\n"));
867 #endif
870 * If first mbuf has no cluster, and has room for len bytes
871 * without shifting current data, pullup into it,
872 * otherwise allocate a new mbuf to prepend to the chain.
874 if ((n->m_flags & M_EXT) == 0 &&
875 n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
876 if (n->m_len >= len)
877 return (n);
878 m = n; /* pullup to */
879 n = n->m_next; /* pullup from */
880 len -= m->m_len; /* pullup length */
881 } else {
882 if (len > MHLEN)
883 goto bad;
884 MGET(m, M_DONTWAIT, n->m_type);
885 if (m == 0)
886 goto bad;
887 m->m_len = 0;
888 if (n->m_flags & M_PKTHDR) {
889 M_COPY_PKTHDR(m, n);
890 n->m_flags &= ~M_PKTHDR;
893 space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
894 do {
895 count = MIN(MIN(MAX(len, max_protohdr), space), n->m_len);
896 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
897 (unsigned)count);
898 len -= count;
899 m->m_len += count;
900 n->m_len -= count;
901 space -= count;
902 if (n->m_len)
903 n->m_data += count;
904 else
905 n = m_free(n);
906 } while (len > 0 && n);
907 if (len > 0) {
908 (void) m_free(m);
909 goto bad;
911 m->m_next = n;
912 return (m);
913 bad:
914 m_freem(n);
915 MPFail++;
916 return (0);
919 #if 0 /* not needed (yet), DO NOT DELETE! */
921 * Allocate a "funny" mbuf, that is, one whose data is owned by someone else.
923 struct mbuf *
924 mclgetx(fun, arg, addr, len, wait)
925 void (*fun)();
926 int arg, len, wait;
927 caddr_t addr;
929 register struct mbuf *m;
931 MGETHDR(m, wait, MT_DATA);
932 if (m == 0)
933 return (0);
934 m->m_data = addr ;
935 m->m_len = len;
936 m->m_ext.ext_free = fun;
937 m->m_ext.ext_size = len;
938 m->m_ext.ext_buf = (caddr_t)arg;
939 m->m_flags |= M_EXT;
941 return (m);
944 void mcl_free_routine(buf, size)
945 char *buf;
946 int size;
949 #endif /* 0 */