OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [kern/] [uipc_mbuf.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      sys/kern/uipc_mbuf.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
 
33
/*      $OpenBSD: uipc_mbuf.c,v 1.18 1999/12/05 07:30:31 angelos Exp $  */
34
/*      $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $   */
35
 
36
/*
37
 * Copyright (c) 1982, 1986, 1988, 1991, 1993
38
 *      The Regents of the University of California.  All rights reserved.
39
 *
40
 * Redistribution and use in source and binary forms, with or without
41
 * modification, are permitted provided that the following conditions
42
 * are met:
43
 * 1. Redistributions of source code must retain the above copyright
44
 *    notice, this list of conditions and the following disclaimer.
45
 * 2. Redistributions in binary form must reproduce the above copyright
46
 *    notice, this list of conditions and the following disclaimer in the
47
 *    documentation and/or other materials provided with the distribution.
48
 * 3. All advertising materials mentioning features or use of this software
49
 *    must display the following acknowledgement:
50
 *      This product includes software developed by the University of
51
 *      California, Berkeley and its contributors.
52
 * 4. Neither the name of the University nor the names of its contributors
53
 *    may be used to endorse or promote products derived from this software
54
 *    without specific prior written permission.
55
 *
56
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66
 * SUCH DAMAGE.
67
 *
68
 *      @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
69
 */
70
 
71
/*
72
%%% portions-copyright-nrl-95
73
Portions of this software are Copyright 1995-1998 by Randall Atkinson,
74
Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
75
Reserved. All rights under this copyright have been assigned to the US
76
Naval Research Laboratory (NRL). The NRL Copyright Notice and License
77
Agreement Version 1.1 (January 17, 1995) applies to these portions of the
78
software.
79
You should have received a copy of the license with this software. If you
80
didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
81
*/
82
 
83
#include <sys/param.h>
84
#ifndef __ECOS
85
#include <sys/systm.h>
86
#include <sys/proc.h>
87
#endif
88
#include <sys/malloc.h>
89
#ifndef __ECOS
90
#include <sys/map.h>
91
#endif
92
#define MBTYPES
93
#include <sys/mbuf.h>
94
#include <sys/kernel.h>
95
#ifndef __ECOS
96
#include <sys/syslog.h>
97
#endif
98
#include <sys/domain.h>
99
#include <sys/protosw.h>
100
 
101
#include <machine/cpu.h>
102
 
103
#ifndef __ECOS
104
#include <vm/vm.h>
105
#endif
106
 
107
#if defined(UVM)
108
#include <uvm/uvm_extern.h>
109
#endif
110
 
111
#ifndef __ECOS
112
extern  vm_map_t mb_map;
113
#endif
114
struct  mbuf *mbutl;
115
char    *mclrefcnt;
116
int     needqueuedrain;
117
 
118
#ifdef __ECOS
119
extern void setsoftnet(void);
120
extern void *cyg_net_cluster_alloc(void);
121
#endif
122
 
123
/* Declarations of variables move from mbuf.h to keep g++ happy */
124
#ifdef __ECOS
125
struct mbstat mbstat;
126
union  mcluster *mclfree;
127
int    max_linkhdr;                    /* largest link-level header */
128
int    max_protohdr;                   /* largest protocol header */
129
int    max_hdr;                        /* largest link+protocol header */
130
int    max_datalen;                    /* MHLEN - max_hdr */
131
#ifdef MBTYPES
132
int mbtypes[] = {                              /* XXX */
133
       M_FREE,         /* MT_FREE      0          should be on free list */
134
       M_MBUF,         /* MT_DATA      1          dynamic (data) allocation */
135
       M_MBUF,         /* MT_HEADER    2          packet header */
136
       M_SOCKET,       /* MT_SOCKET    3          socket structure */
137
       M_PCB,          /* MT_PCB       4          protocol control block */
138
       M_RTABLE,       /* MT_RTABLE    5          routing tables */
139
       M_HTABLE,       /* MT_HTABLE    6          IMP host tables */
140
       0,              /* MT_ATABLE    7          address resolution tables */
141
       M_MBUF,         /* MT_SONAME    8          socket name */
142
       0,              /*              9 */
143
       M_SOOPTS,       /* MT_SOOPTS    10         socket options */
144
       M_FTABLE,       /* MT_FTABLE    11         fragment reassembly header */
145
       M_MBUF,         /* MT_RIGHTS    12         access rights */
146
       M_IFADDR,       /* MT_IFADDR    13         interface address */
147
       M_MBUF,         /* MT_CONTROL   14         extra-data protocol message */
148
       M_MBUF,         /* MT_OOBDATA   15         expedited data  */
149
#ifdef DATAKIT
150
       25, 26, 27, 28, 29, 30, 31, 32          /* datakit ugliness */
151
#endif
152
};
153
#endif
154
#endif // __ECOS
155
 
156
void
157
mbinit()
158
{
159
        int s;
160
 
161
        s = splimp();
162
#ifdef __ECOS
163
        if (m_clalloc(1, M_DONTWAIT) == 0)
164
#else
165
        if (m_clalloc(max(4096 / CLBYTES, 1), M_DONTWAIT) == 0)
166
#endif
167
                goto bad;
168
        splx(s);
169
        return;
170
bad:
171
        panic("mbinit");
172
}
173
 
174
/*
175
 * Allocate some number of mbuf clusters
176
 * and place on cluster free list.
177
 * Must be called at splimp.
178
 */
179
/* ARGSUSED */
180
int
181
m_clalloc(ncl, nowait)
182
        register int ncl;
183
        int nowait;
184
{
185
#ifdef __ECOS
186
        caddr_t p;
187
        int i;
188
 
189
        if (ncl != 1) {
190
            panic("Allocate multiple clusters!");
191
        }
192
        p = (caddr_t)cyg_net_cluster_alloc();
193
        if (p == NULL) {
194
                m_reclaim();
195
                return (mclfree != NULL);
196
        }
197
        for (i = 0; i < ncl; i++) {
198
                ((union mcluster *)p)->mcl_next = mclfree;
199
                mclfree = (union mcluster *)p;
200
                p += MCLBYTES;
201
                mbstat.m_clfree++;
202
        }
203
        mbstat.m_clusters += ncl;
204
        return (1);
205
#else // __ECOS
206
        volatile static struct timeval lastlogged;
207
        struct timeval curtime, logdiff;
208
        register caddr_t p;
209
        register int i;
210
        int npg, s;
211
 
212
        npg = ncl * CLSIZE;
213
#if defined(UVM)
214
        p = (caddr_t)uvm_km_kmemalloc(mb_map, uvmexp.mb_object, ctob(npg),
215
            nowait ? 0 : UVM_KMF_NOWAIT);
216
#else
217
        p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait);
218
#endif
219
        if (p == NULL) {
220
                s = splclock();
221
                curtime = time;
222
                splx(s);
223
                timersub(&curtime, &lastlogged, &logdiff);
224
                if (logdiff.tv_sec >= 60) {
225
                        lastlogged = curtime;
226
                        log(LOG_ERR, "mb_map full\n");
227
                }
228
                m_reclaim();
229
                return (mclfree != NULL);
230
        }
231
        ncl = ncl * CLBYTES / MCLBYTES;
232
        for (i = 0; i < ncl; i++) {
233
                ((union mcluster *)p)->mcl_next = mclfree;
234
                mclfree = (union mcluster *)p;
235
                p += MCLBYTES;
236
                mbstat.m_clfree++;
237
        }
238
        mbstat.m_clusters += ncl;
239
        return (1);
240
#endif // __ECOS
241
}
242
 
243
/*
244
 * When MGET failes, ask protocols to free space when short of memory,
245
 * then re-attempt to allocate an mbuf.
246
 */
247
struct mbuf *
248
m_retry(i, t)
249
        int i, t;
250
{
251
        register struct mbuf *m;
252
 
253
        if (i & M_DONTWAIT) {
254
                needqueuedrain = 1;
255
                setsoftnet();
256
                return (NULL);
257
        }
258
        m_reclaim();
259
#define m_retry(i, t)   NULL
260
        MGET(m, i, t);
261
#undef m_retry
262
        return (m);
263
}
264
 
265
/*
266
 * As above; retry an MGETHDR.
267
 */
268
struct mbuf *
269
m_retryhdr(i, t)
270
        int i, t;
271
{
272
        register struct mbuf *m;
273
 
274
        if (i & M_DONTWAIT) {
275
                needqueuedrain = 1;
276
                setsoftnet();
277
                return (NULL);
278
        }
279
        m_reclaim();
280
#define m_retryhdr(i, t) NULL
281
        MGETHDR(m, i, t);
282
#undef m_retryhdr
283
        return (m);
284
}
285
 
286
void
287
m_reclaim()
288
{
289
        register struct domain *dp;
290
        register struct protosw *pr;
291
        int s = splimp();
292
 
293
        needqueuedrain = 0;
294
        for (dp = domains; dp; dp = dp->dom_next)
295
                for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
296
                        if (pr->pr_drain)
297
                                (*pr->pr_drain)();
298
        splx(s);
299
        mbstat.m_drain++;
300
}
301
 
302
/*
303
 * Space allocation routines.
304
 * These are also available as macros
305
 * for critical paths.
306
 */
307
struct mbuf *
308
m_get(nowait, type)
309
        int nowait, type;
310
{
311
        register struct mbuf *m;
312
 
313
        MGET(m, nowait, type);
314
        return (m);
315
}
316
 
317
struct mbuf *
318
m_gethdr(nowait, type)
319
        int nowait, type;
320
{
321
        register struct mbuf *m;
322
 
323
        MGETHDR(m, nowait, type);
324
        return (m);
325
}
326
 
327
struct mbuf *
328
m_getclr(nowait, type)
329
        int nowait, type;
330
{
331
        register struct mbuf *m;
332
 
333
        MGET(m, nowait, type);
334
        if (m == NULL)
335
                return (NULL);
336
        bzero(mtod(m, caddr_t), MLEN);
337
        return (m);
338
}
339
 
340
struct mbuf *
341
m_free(m)
342
        struct mbuf *m;
343
{
344
        register struct mbuf *n;
345
 
346
        MFREE(m, n);
347
        return (n);
348
}
349
 
350
void
351
m_freem(m)
352
        register struct mbuf *m;
353
{
354
        register struct mbuf *n;
355
 
356
        if (m == NULL)
357
                return;
358
        do {
359
                MFREE(m, n);
360
        } while ((m = n) != NULL);
361
}
362
 
363
/*
364
 * Mbuffer utility routines.
365
 */
366
 
367
/*
368
 * Lesser-used path for M_PREPEND:
369
 * allocate new mbuf to prepend to chain,
370
 * copy junk along.
371
 */
372
struct mbuf *
373
m_prepend(m, len, how)
374
        register struct mbuf *m;
375
        int len, how;
376
{
377
        struct mbuf *mn;
378
 
379
        MGET(mn, how, m->m_type);
380
        if (mn == NULL) {
381
                m_freem(m);
382
                return (NULL);
383
        }
384
        if (m->m_flags & M_PKTHDR) {
385
                M_COPY_PKTHDR(mn, m);
386
                m->m_flags &= ~M_PKTHDR;
387
        }
388
        mn->m_next = m;
389
        m = mn;
390
        if (len < MHLEN)
391
                MH_ALIGN(m, len);
392
        m->m_len = len;
393
        return (m);
394
}
395
 
396
/*
397
 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
398
 * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
399
 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
400
 */
401
int MCFail;
402
 
403
struct mbuf *
404
m_copym(m, off0, len, wait)
405
        register struct mbuf *m;
406
        int off0, wait;
407
        register int len;
408
{
409
        register struct mbuf *n, **np;
410
        register int off = off0;
411
        struct mbuf *top;
412
        int copyhdr = 0;
413
 
414
        if (off < 0)
415
                panic("m_copym: off %d < 0", off);
416
        if (len < 0)
417
                panic("m_copym: len %d < 0", len);
418
        if (off == 0 && m->m_flags & M_PKTHDR)
419
                copyhdr = 1;
420
        while (off > 0) {
421
                if (m == NULL)
422
                        panic("m_copym: null mbuf");
423
                if (off < m->m_len)
424
                        break;
425
                off -= m->m_len;
426
                m = m->m_next;
427
        }
428
        np = &top;
429
        top = NULL;
430
        while (len > 0) {
431
                if (m == NULL) {
432
                        if (len != M_COPYALL)
433
                                panic("m_copym: %d not M_COPYALL", len);
434
                        break;
435
                }
436
                MGET(n, wait, m->m_type);
437
                *np = n;
438
                if (n == NULL)
439
                        goto nospace;
440
                if (copyhdr) {
441
                        M_COPY_PKTHDR(n, m);
442
                        if (len == M_COPYALL)
443
                                n->m_pkthdr.len -= off0;
444
                        else
445
                                n->m_pkthdr.len = len;
446
                        copyhdr = 0;
447
                }
448
                n->m_len = min(len, m->m_len - off);
449
                if (m->m_flags & M_EXT) {
450
                        n->m_data = m->m_data + off;
451
                        if (!m->m_ext.ext_ref)
452
                                mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
453
                        else
454
                                (*(m->m_ext.ext_ref))(m);
455
                        n->m_ext = m->m_ext;
456
                        n->m_flags |= M_EXT;
457
                } else
458
                        bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
459
                            (unsigned)n->m_len);
460
                if (len != M_COPYALL)
461
                        len -= n->m_len;
462
                off = 0;
463
                m = m->m_next;
464
                np = &n->m_next;
465
        }
466
        if (top == NULL)
467
                MCFail++;
468
        return (top);
469
nospace:
470
        m_freem(top);
471
        MCFail++;
472
        return (NULL);
473
}
474
 
475
/*
476
 * m_copym2() is like m_copym(), except it COPIES cluster mbufs, instead
477
 * of merely bumping the reference count.
478
 */
479
struct mbuf *
480
m_copym2(m, off0, len, wait)
481
        register struct mbuf *m;
482
        int off0, wait;
483
        register int len;
484
{
485
        register struct mbuf *n, **np;
486
        register int off = off0;
487
        struct mbuf *top;
488
        int copyhdr = 0;
489
 
490
        if (len < 0)
491
                panic("m_copym2: len %d < 0", len);
492
        if (off < 0)
493
                panic("m_copym2: off %d < 0", off);
494
        if (off == 0 && m->m_flags & M_PKTHDR)
495
                copyhdr = 1;
496
        while (off > 0) {
497
                if (m == NULL)
498
                        panic("m_copym2: null mbuf");
499
                if (off < m->m_len)
500
                        break;
501
                off -= m->m_len;
502
                m = m->m_next;
503
        }
504
        np = &top;
505
        top = NULL;
506
        while (len > 0) {
507
                if (m == NULL) {
508
                        if (len != M_COPYALL)
509
                                panic("m_copym2: %d != M_COPYALL", len);
510
                        break;
511
                }
512
                MGET(n, wait, m->m_type);
513
                *np = n;
514
                if (n == NULL)
515
                        goto nospace;
516
                if (copyhdr) {
517
                        M_COPY_PKTHDR(n, m);
518
                        if (len == M_COPYALL)
519
                                n->m_pkthdr.len -= off0;
520
                        else
521
                                n->m_pkthdr.len = len;
522
                        copyhdr = 0;
523
                }
524
                n->m_len = min(len, m->m_len - off);
525
                if ((m->m_flags & M_EXT) && (n->m_len > MHLEN)) {
526
                        /* This is a cheesy hack. */
527
                        MCLGET(n, wait);
528
                        if (n->m_flags & M_EXT)
529
                                bcopy(mtod(m, caddr_t) + off, mtod(n, caddr_t),
530
                                    (unsigned)n->m_len);
531
                        else
532
                                goto nospace;
533
                } else
534
                        bcopy(mtod(m, caddr_t) + off, mtod(n, caddr_t),
535
                            (unsigned)n->m_len);
536
                if (len != M_COPYALL)
537
                        len -= n->m_len;
538
                off = 0;
539
                m = m->m_next;
540
                np = &n->m_next;
541
        }
542
        if (top == NULL)
543
                MCFail++;
544
        return (top);
545
nospace:
546
        m_freem(top);
547
        MCFail++;
548
        return (NULL);
549
}
550
 
551
/*
552
 * Copy data from an mbuf chain starting "off" bytes from the beginning,
553
 * continuing for "len" bytes, into the indicated buffer.
554
 */
555
void
556
m_copydata(m, off, len, cp)
557
        register struct mbuf *m;
558
        register int off;
559
        register int len;
560
        caddr_t cp;
561
{
562
        register unsigned count;
563
 
564
        if (off < 0)
565
                panic("m_copydata: off %d < 0", off);
566
        if (len < 0)
567
                panic("m_copydata: len %d < 0", len);
568
        while (off > 0) {
569
                if (m == NULL)
570
                        panic("m_copydata: null mbuf in skip");
571
                if (off < m->m_len)
572
                        break;
573
                off -= m->m_len;
574
                m = m->m_next;
575
        }
576
        while (len > 0) {
577
                if (m == NULL)
578
                        panic("m_copydata: null mbuf");
579
                count = min(m->m_len - off, len);
580
                bcopy(mtod(m, caddr_t) + off, cp, count);
581
                len -= count;
582
                cp += count;
583
                off = 0;
584
                m = m->m_next;
585
        }
586
}
587
 
588
/*
589
 * Concatenate mbuf chain n to m.
590
 * Both chains must be of the same type (e.g. MT_DATA).
591
 * Any m_pkthdr is not updated.
592
 */
593
void
594
m_cat(m, n)
595
        register struct mbuf *m, *n;
596
{
597
        while (m->m_next)
598
                m = m->m_next;
599
        while (n) {
600
                if (m->m_flags & M_EXT ||
601
                    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
602
                        /* just join the two chains */
603
                        m->m_next = n;
604
                        return;
605
                }
606
                /* splat the data from one into the other */
607
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
608
                    (u_int)n->m_len);
609
                m->m_len += n->m_len;
610
                n = m_free(n);
611
        }
612
}
613
 
614
void
615
m_adj(mp, req_len)
616
        struct mbuf *mp;
617
        int req_len;
618
{
619
        register int len = req_len;
620
        register struct mbuf *m;
621
        register int count;
622
 
623
        if ((m = mp) == NULL)
624
                return;
625
        if (len >= 0) {
626
                /*
627
                 * Trim from head.
628
                 */
629
                while (m != NULL && len > 0) {
630
                        if (m->m_len <= len) {
631
                                len -= m->m_len;
632
                                m->m_len = 0;
633
                                m = m->m_next;
634
                        } else {
635
                                m->m_len -= len;
636
                                m->m_data += len;
637
                                len = 0;
638
                        }
639
                }
640
                m = mp;
641
                if (mp->m_flags & M_PKTHDR)
642
                        m->m_pkthdr.len -= (req_len - len);
643
        } else {
644
                /*
645
                 * Trim from tail.  Scan the mbuf chain,
646
                 * calculating its length and finding the last mbuf.
647
                 * If the adjustment only affects this mbuf, then just
648
                 * adjust and return.  Otherwise, rescan and truncate
649
                 * after the remaining size.
650
                 */
651
                len = -len;
652
                count = 0;
653
                for (;;) {
654
                        count += m->m_len;
655
                        if (m->m_next == NULL)
656
                                break;
657
                        m = m->m_next;
658
                }
659
                if (m->m_len >= len) {
660
                        m->m_len -= len;
661
                        if (mp->m_flags & M_PKTHDR)
662
                                mp->m_pkthdr.len -= len;
663
                        return;
664
                }
665
                count -= len;
666
                if (count < 0)
667
                        count = 0;
668
                /*
669
                 * Correct length for chain is "count".
670
                 * Find the mbuf with last data, adjust its length,
671
                 * and toss data from remaining mbufs on chain.
672
                 */
673
                m = mp;
674
                if (m->m_flags & M_PKTHDR)
675
                        m->m_pkthdr.len = count;
676
                for (; m; m = m->m_next) {
677
                        if (m->m_len >= count) {
678
                                m->m_len = count;
679
                                break;
680
                        }
681
                        count -= m->m_len;
682
                }
683
                while ((m = m->m_next) != NULL)
684
                        m->m_len = 0;
685
        }
686
}
687
 
688
/*
689
 * Rearange an mbuf chain so that len bytes are contiguous
690
 * and in the data area of an mbuf (so that mtod and dtom
691
 * will work for a structure of size len).  Returns the resulting
692
 * mbuf chain on success, frees it and returns null on failure.
693
 * If there is room, it will add up to max_protohdr-len extra bytes to the
694
 * contiguous region in an attempt to avoid being called next time.
695
 */
696
int MPFail;
697
 
698
struct mbuf *
699
m_pullup(n, len)
700
        register struct mbuf *n;
701
        int len;
702
{
703
        register struct mbuf *m;
704
        register int count;
705
        int space;
706
 
707
        /*
708
         * If first mbuf has no cluster, and has room for len bytes
709
         * without shifting current data, pullup into it,
710
         * otherwise allocate a new mbuf to prepend to the chain.
711
         */
712
        if ((n->m_flags & M_EXT) == 0 &&
713
            n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
714
                if (n->m_len >= len)
715
                        return (n);
716
                m = n;
717
                n = n->m_next;
718
                len -= m->m_len;
719
        } else {
720
                if (len > MHLEN)
721
                        goto bad;
722
                MGET(m, M_DONTWAIT, n->m_type);
723
                if (m == NULL)
724
                        goto bad;
725
                m->m_len = 0;
726
                if (n->m_flags & M_PKTHDR) {
727
                        M_COPY_PKTHDR(m, n);
728
                        n->m_flags &= ~M_PKTHDR;
729
                }
730
        }
731
        space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
732
        do {
733
                count = min(min(max(len, max_protohdr), space), n->m_len);
734
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
735
                    (unsigned)count);
736
                len -= count;
737
                m->m_len += count;
738
                n->m_len -= count;
739
                space -= count;
740
                if (n->m_len)
741
                        n->m_data += count;
742
                else
743
                        n = m_free(n);
744
        } while (len > 0 && n);
745
        if (len > 0) {
746
                (void)m_free(m);
747
                goto bad;
748
        }
749
        m->m_next = n;
750
        return (m);
751
bad:
752
        m_freem(n);
753
        MPFail++;
754
        return (NULL);
755
}
756
 
757
/*
758
 * m_pullup2() works like m_pullup, save that len can be <= MCLBYTES.
759
 * m_pullup2() only works on values of len such that MHLEN < len <= MCLBYTES,
760
 * it calls m_pullup() for values <= MHLEN.  It also only coagulates the
761
 * reqested number of bytes.  (For those of us who expect unwieldly option
762
 * headers.
763
 *
764
 * KEBE SAYS:  Remember that dtom() calls with data in clusters does not work!
765
 */
766
struct mbuf *
767
m_pullup2(n, len)
768
        register struct mbuf *n;
769
        int len;
770
{
771
        register struct mbuf *m;
772
        register int count;
773
        int space;
774
        if (len <= MHLEN)
775
                return m_pullup(n, len);
776
 
777
        if ((n->m_flags & M_EXT) != 0 &&
778
            n->m_data + len < &n->m_data[MCLBYTES] && n->m_next) {
779
                if (n->m_len >= len)
780
                        return (n);
781
                m = n;
782
                n = n->m_next;
783
                len -= m->m_len;
784
        } else {
785
                if (len > MCLBYTES)
786
                        goto bad;
787
                MGET(m, M_DONTWAIT, n->m_type);
788
                if (m == NULL)
789
                        goto bad;
790
                MCLGET(m, M_DONTWAIT);
791
                if ((m->m_flags & M_EXT) == 0)
792
                        goto bad;
793
                m->m_len = 0;
794
                if (n->m_flags & M_PKTHDR) {
795
                        /* M_COPY_PKTHDR(m, n);*//* Too many adverse side effects. */
796
                        m->m_pkthdr = n->m_pkthdr;
797
                        m->m_flags = (n->m_flags & M_COPYFLAGS) | M_EXT;
798
                        n->m_flags &= ~M_PKTHDR;
799
                        /* n->m_data is cool. */
800
                }
801
        }
802
 
803
        do {
804
                count = min(len, n->m_len);
805
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
806
                    (unsigned)count);
807
                len -= count;
808
                m->m_len += count;
809
                n->m_len -= count;
810
                space -= count;
811
                if (n->m_len)
812
                        n->m_data += count;
813
                else
814
                        n = m_free(n);
815
        } while (len > 0 && n);
816
        if (len > 0) {
817
                (void)m_free(m);
818
                goto bad;
819
        }
820
        m->m_next = n;
821
 
822
        return (m);
823
bad:
824
        m_freem(n);
825
        MPFail++;
826
        return (NULL);
827
}
828
 
829
/*
830
 * Inject a new mbuf chain of length siz in mbuf chain m0 at
831
 * position len0. Returns a pointer to the first injected mbuf, or
832
 * NULL on failure (m0 is left undisturbed). Note that if there is
833
 * enough space for an object of size siz in the appropriate position,
834
 * no memory will be allocated. Also, there will be no data movement in
835
 * the first len0 bytes (pointers to that will remain valid).
836
 *
837
 * XXX It is assumed that siz is less than the size of an mbuf at the moment.
838
 */
839
struct mbuf *
840
m_inject(m0, len0, siz, wait)
841
        register struct mbuf *m0;
842
        int len0, siz, wait;
843
{
844
        register struct mbuf *m, *n, *n2 = NULL, *n3;
845
        unsigned len = len0, remain;
846
 
847
        if ((siz >= MHLEN) || (len0 <= 0))
848
                return (NULL);
849
        for (m = m0; m && len > m->m_len; m = m->m_next)
850
                len -= m->m_len;
851
        if (m == NULL)
852
                return (NULL);
853
        remain = m->m_len - len;
854
        if (remain == 0) {
855
                if ((m->m_next) &&  (M_LEADINGSPACE(m->m_next) >= siz)) {
856
                        m->m_next->m_len += siz;
857
                        m0->m_pkthdr.len += siz;
858
                        m->m_next->m_data -= siz;
859
                        return m->m_next;
860
                }
861
        } else {
862
                n2 = m_copym2(m, len, remain, wait);
863
                if (n2 == NULL)
864
                        return (NULL);
865
        }
866
 
867
        MGET(n, wait, MT_DATA);
868
        if (n == NULL) {
869
                if (n2)
870
                        m_freem(n2);
871
                return (NULL);
872
        }
873
 
874
        n->m_len = siz;
875
        m0->m_pkthdr.len += siz;
876
        m->m_len -= remain; /* Trim */
877
        if (n2) {
878
                for (n3 = n; n3->m_next != NULL; n3 = n3->m_next)
879
                        ;
880
                n3->m_next = n2;
881
        } else
882
                n3 = n;
883
        for (; n3->m_next != NULL; n3 = n3->m_next)
884
                ;
885
        n3->m_next = m->m_next;
886
        m->m_next = n;
887
        return n;
888
}
889
 
890
/*
891
 * Partition an mbuf chain in two pieces, returning the tail --
892
 * all but the first len0 bytes.  In case of failure, it returns NULL and
893
 * attempts to restore the chain to its original state.
894
 */
895
struct mbuf *
896
m_split(m0, len0, wait)
897
        register struct mbuf *m0;
898
        int len0, wait;
899
{
900
        register struct mbuf *m, *n;
901
        unsigned len = len0, remain, olen;
902
 
903
        for (m = m0; m && len > m->m_len; m = m->m_next)
904
                len -= m->m_len;
905
        if (m == NULL)
906
                return (NULL);
907
        remain = m->m_len - len;
908
        if (m0->m_flags & M_PKTHDR) {
909
                MGETHDR(n, wait, m0->m_type);
910
                if (n == NULL)
911
                        return (NULL);
912
                n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
913
                n->m_pkthdr.len = m0->m_pkthdr.len - len0;
914
                olen = m0->m_pkthdr.len;
915
                m0->m_pkthdr.len = len0;
916
                if (m->m_flags & M_EXT)
917
                        goto extpacket;
918
                if (remain > MHLEN) {
919
                        /* m can't be the lead packet */
920
                        MH_ALIGN(n, 0);
921
                        n->m_next = m_split(m, len, wait);
922
                        if (n->m_next == NULL) {
923
                                (void) m_free(n);
924
                                m0->m_pkthdr.len = olen;
925
                                return (NULL);
926
                        } else
927
                                return (n);
928
                } else
929
                        MH_ALIGN(n, remain);
930
        } else if (remain == 0) {
931
                n = m->m_next;
932
                m->m_next = NULL;
933
                return (n);
934
        } else {
935
                MGET(n, wait, m->m_type);
936
                if (n == NULL)
937
                        return (NULL);
938
                M_ALIGN(n, remain);
939
        }
940
extpacket:
941
        if (m->m_flags & M_EXT) {
942
                n->m_flags |= M_EXT;
943
                n->m_ext = m->m_ext;
944
                if(!m->m_ext.ext_ref)
945
                        mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
946
                else
947
                        (*(m->m_ext.ext_ref))(m);
948
                m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
949
                n->m_data = m->m_data + len;
950
        } else {
951
                bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
952
        }
953
        n->m_len = remain;
954
        m->m_len = len;
955
        n->m_next = m->m_next;
956
        m->m_next = NULL;
957
        return (n);
958
}
959
/*
960
 * Routine to copy from device local memory into mbufs.
961
 */
962
struct mbuf *
963
m_devget(buf, totlen, off0, ifp, copy)
964
        char *buf;
965
        int totlen, off0;
966
        struct ifnet *ifp;
967
        void (*copy) __P((const void *, void *, size_t));
968
{
969
        register struct mbuf *m;
970
        struct mbuf *top = NULL, **mp = &top;
971
        register int off = off0, len;
972
        register char *cp;
973
        char *epkt;
974
 
975
        cp = buf;
976
        epkt = cp + totlen;
977
        if (off) {
978
                /*
979
                 * If 'off' is non-zero, packet is trailer-encapsulated,
980
                 * so we have to skip the type and length fields.
981
                 */
982
                cp += off + 2 * sizeof(u_int16_t);
983
                totlen -= 2 * sizeof(u_int16_t);
984
        }
985
        MGETHDR(m, M_DONTWAIT, MT_DATA);
986
        if (m == NULL)
987
                return (NULL);
988
        m->m_pkthdr.rcvif = ifp;
989
        m->m_pkthdr.len = totlen;
990
        m->m_len = MHLEN;
991
 
992
        while (totlen > 0) {
993
                if (top != NULL) {
994
                        MGET(m, M_DONTWAIT, MT_DATA);
995
                        if (m == NULL) {
996
                                m_freem(top);
997
                                return (NULL);
998
                        }
999
                        m->m_len = MLEN;
1000
                }
1001
                len = min(totlen, epkt - cp);
1002
                if (len >= MINCLSIZE) {
1003
                        MCLGET(m, M_DONTWAIT);
1004
                        if (m->m_flags & M_EXT)
1005
                                m->m_len = len = min(len, MCLBYTES);
1006
                        else
1007
                                len = m->m_len;
1008
                } else {
1009
                        /*
1010
                         * Place initial small packet/header at end of mbuf.
1011
                         */
1012
                        if (len < m->m_len) {
1013
                                if (top == NULL &&
1014
                                    len + max_linkhdr <= m->m_len)
1015
                                        m->m_data += max_linkhdr;
1016
                                m->m_len = len;
1017
                        } else
1018
                                len = m->m_len;
1019
                }
1020
                if (copy)
1021
                        copy(cp, mtod(m, caddr_t), (size_t)len);
1022
                else
1023
                        bcopy(cp, mtod(m, caddr_t), (size_t)len);
1024
                cp += len;
1025
                *mp = m;
1026
                mp = &m->m_next;
1027
                totlen -= len;
1028
                if (cp == epkt)
1029
                        cp = buf;
1030
        }
1031
        return (top);
1032
}
1033
 
1034
void
1035
m_zero(m)
1036
        struct mbuf *m;
1037
{
1038
    while (m) {
1039
        if (m->m_flags & M_PKTHDR)
1040
            bzero((unsigned char *)m + sizeof(struct m_hdr) +
1041
                  sizeof(struct pkthdr), MHLEN);
1042
        else
1043
            bzero((unsigned char *)m + sizeof(struct m_hdr), MLEN);
1044
        if ((m->m_flags & M_EXT) &&
1045
            (m->m_ext.ext_free == NULL) &&
1046
            !mclrefcnt[mtocl((m)->m_ext.ext_buf)])
1047
            bzero(m->m_ext.ext_buf, m->m_ext.ext_size);
1048
        m = m->m_next;
1049
    }
1050
}
1051
 
1052
/*
1053
 * Apply function f to the data in an mbuf chain starting "off" bytes from the
1054
 * beginning, continuing for "len" bytes.
1055
 */
1056
int
1057
m_apply(m, off, len, f, fstate)
1058
        struct mbuf *m;
1059
        int off;
1060
        int len;
1061
        /* fstate, data, len */
1062
        int (*f)(caddr_t, caddr_t, unsigned int);
1063
        caddr_t fstate;
1064
{
1065
        int rval;
1066
        unsigned int count;
1067
 
1068
        if (len < 0)
1069
                panic("m_apply: len %d < 0", len);
1070
        if (off < 0)
1071
                panic("m_apply: off %d < 0", off);
1072
        while (off > 0) {
1073
                if (m == NULL)
1074
                        panic("m_apply: null mbuf in skip");
1075
                if (off < m->m_len)
1076
                        break;
1077
                off -= m->m_len;
1078
                m = m->m_next;
1079
        }
1080
        while (len > 0) {
1081
                if (m == NULL)
1082
                        panic("m_apply: null mbuf");
1083
                count = min(m->m_len - off, len);
1084
 
1085
                rval = f(fstate, mtod(m, caddr_t) + off, count);
1086
                if (rval)
1087
                        return (rval);
1088
 
1089
                len -= count;
1090
                off = 0;
1091
                m = m->m_next;
1092
        }
1093
 
1094
        return (0);
1095
}
1096
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.