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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [kern/] [uipc_mbuf.c] - Blame information for rev 279

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * Copyright (c) 1982, 1986, 1988, 1991, 1993
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *      This product includes software developed by the University of
16
 *      California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *      @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
34
 * $Id: uipc_mbuf.c,v 1.2 2001-09-27 12:01:51 chris Exp $
35
 */
36
 
37
#include <sys/param.h>
38
#include <sys/systm.h>
39
#include <sys/proc.h>
40
#include <sys/malloc.h>
41
#define MBTYPES
42
#include <sys/mbuf.h>
43
#include <sys/kernel.h>
44
#include <sys/syslog.h>
45
#include <sys/domain.h>
46
#include <sys/protosw.h>
47
 
48
#include <vm/vm.h>
49
#include <vm/vm_param.h>
50
#include <vm/vm_kern.h>
51
#include <vm/vm_extern.h>
52
 
53
static void mbinit __P((void *))  __attribute__ ((unused));
54
SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)
55
 
56
struct mbuf *mbutl;
57
char    *mclrefcnt;
58
struct mbstat mbstat;
59
struct mbuf *mmbfree;
60
union mcluster *mclfree;
61
int     max_linkhdr;
62
int     max_protohdr;
63
int     max_hdr;
64
int     max_datalen;
65
 
66
/* "number of clusters of pages" */
67
#define NCL_INIT        1
68
 
69
#define NMB_INIT        16
70
 
71
/*
72
 * When MGET failes, ask protocols to free space when short of memory,
73
 * then re-attempt to allocate an mbuf.
74
 */
75
struct mbuf *
76
m_retry(i, t)
77
        int i, t;
78
{
79
        register struct mbuf *m;
80
 
81
        m_reclaim();
82
#define m_retry(i, t)   (struct mbuf *)0
83
        MGET(m, i, t);
84
#undef m_retry
85
        if (m != NULL)
86
                mbstat.m_wait++;
87
        else
88
                mbstat.m_drops++;
89
        return (m);
90
}
91
 
92
/*
93
 * As above; retry an MGETHDR.
94
 */
95
struct mbuf *
96
m_retryhdr(i, t)
97
        int i, t;
98
{
99
        register struct mbuf *m;
100
 
101
        m_reclaim();
102
#define m_retryhdr(i, t) (struct mbuf *)0
103
        MGETHDR(m, i, t);
104
#undef m_retryhdr
105
        if (m != NULL)
106
                mbstat.m_wait++;
107
        else
108
                mbstat.m_drops++;
109
        return (m);
110
}
111
 
112
void
113
m_reclaim(void)
114
{
115
        register struct domain *dp;
116
        register struct protosw *pr;
117
        int s = splimp();
118
 
119
        for (dp = domains; dp; dp = dp->dom_next)
120
                for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
121
                        if (pr->pr_drain)
122
                                (*pr->pr_drain)();
123
        splx(s);
124
        mbstat.m_drain++;
125
}
126
 
127
/*
128
 * Space allocation routines.
129
 * These are also available as macros
130
 * for critical paths.
131
 */
132
struct mbuf *
133
m_get(nowait, type)
134
        int nowait, type;
135
{
136
        register struct mbuf *m;
137
 
138
        MGET(m, nowait, type);
139
        return (m);
140
}
141
 
142
struct mbuf *
143
m_gethdr(nowait, type)
144
        int nowait, type;
145
{
146
        register struct mbuf *m;
147
 
148
        MGETHDR(m, nowait, type);
149
        return (m);
150
}
151
 
152
struct mbuf *
153
m_getclr(nowait, type)
154
        int nowait, type;
155
{
156
        register struct mbuf *m;
157
 
158
        MGET(m, nowait, type);
159
        if (m == 0)
160
                return (0);
161
        bzero(mtod(m, caddr_t), MLEN);
162
        return (m);
163
}
164
 
165
struct mbuf *
166
m_free(m)
167
        struct mbuf *m;
168
{
169
        register struct mbuf *n;
170
 
171
        MFREE(m, n);
172
        return (n);
173
}
174
 
175
void
176
m_freem(m)
177
        register struct mbuf *m;
178
{
179
        register struct mbuf *n;
180
 
181
        if (m == NULL)
182
                return;
183
        do {
184
                MFREE(m, n);
185
                m = n;
186
        } while (m);
187
}
188
 
189
/*
190
 * Mbuffer utility routines.
191
 */
192
 
193
/*
194
 * Lesser-used path for M_PREPEND:
195
 * allocate new mbuf to prepend to chain,
196
 * copy junk along.
197
 */
198
struct mbuf *
199
m_prepend(m, len, how)
200
        register struct mbuf *m;
201
        int len, how;
202
{
203
        struct mbuf *mn;
204
 
205
        MGET(mn, how, m->m_type);
206
        if (mn == (struct mbuf *)NULL) {
207
                m_freem(m);
208
                return ((struct mbuf *)NULL);
209
        }
210
        if (m->m_flags & M_PKTHDR) {
211
                M_COPY_PKTHDR(mn, m);
212
                m->m_flags &= ~M_PKTHDR;
213
        }
214
        mn->m_next = m;
215
        m = mn;
216
        if (len < MHLEN)
217
                MH_ALIGN(m, len);
218
        m->m_len = len;
219
        return (m);
220
}
221
 
222
/*
223
 * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
224
 * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
225
 * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
226
 */
227
static int MCFail;
228
 
229
struct mbuf *
230
m_copym(m, off0, len, wait)
231
        register struct mbuf *m;
232
        int off0, wait;
233
        register int len;
234
{
235
        register struct mbuf *n, **np;
236
        register int off = off0;
237
        struct mbuf *top;
238
        int copyhdr = 0;
239
 
240
        if (off < 0 || len < 0)
241
                panic("m_copym");
242
        if (off == 0 && m->m_flags & M_PKTHDR)
243
                copyhdr = 1;
244
        while (off > 0) {
245
                if (m == 0)
246
                        panic("m_copym");
247
                if (off < m->m_len)
248
                        break;
249
                off -= m->m_len;
250
                m = m->m_next;
251
        }
252
        np = &top;
253
        top = 0;
254
        while (len > 0) {
255
                if (m == 0) {
256
                        if (len != M_COPYALL)
257
                                panic("m_copym");
258
                        break;
259
                }
260
                MGET(n, wait, m->m_type);
261
                *np = n;
262
                if (n == 0)
263
                        goto nospace;
264
                if (copyhdr) {
265
                        M_COPY_PKTHDR(n, m);
266
                        if (len == M_COPYALL)
267
                                n->m_pkthdr.len -= off0;
268
                        else
269
                                n->m_pkthdr.len = len;
270
                        copyhdr = 0;
271
                }
272
                n->m_len = min(len, m->m_len - off);
273
                if (m->m_flags & M_EXT) {
274
                        n->m_data = m->m_data + off;
275
                        if(!m->m_ext.ext_ref)
276
                                mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
277
                        else
278
                                (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
279
                                                        m->m_ext.ext_size);
280
                        n->m_ext = m->m_ext;
281
                        n->m_flags |= M_EXT;
282
                } else
283
                        bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
284
                            (unsigned)n->m_len);
285
                if (len != M_COPYALL)
286
                        len -= n->m_len;
287
                off = 0;
288
                m = m->m_next;
289
                np = &n->m_next;
290
        }
291
        if (top == 0)
292
                MCFail++;
293
        return (top);
294
nospace:
295
        m_freem(top);
296
        MCFail++;
297
        return (0);
298
}
299
 
300
/*
301
 * Copy an entire packet, including header (which must be present).
302
 * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
303
 */
304
struct mbuf *
305
m_copypacket(m, how)
306
        struct mbuf *m;
307
        int how;
308
{
309
        struct mbuf *top, *n, *o;
310
 
311
        MGET(n, how, m->m_type);
312
        top = n;
313
        if (!n)
314
                goto nospace;
315
 
316
        M_COPY_PKTHDR(n, m);
317
        n->m_len = m->m_len;
318
        if (m->m_flags & M_EXT) {
319
                n->m_data = m->m_data;
320
                mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
321
                n->m_ext = m->m_ext;
322
                n->m_flags |= M_EXT;
323
        } else {
324
                bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
325
        }
326
 
327
        m = m->m_next;
328
        while (m) {
329
                MGET(o, how, m->m_type);
330
                if (!o)
331
                        goto nospace;
332
 
333
                n->m_next = o;
334
                n = n->m_next;
335
 
336
                n->m_len = m->m_len;
337
                if (m->m_flags & M_EXT) {
338
                        n->m_data = m->m_data;
339
                        mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
340
                        n->m_ext = m->m_ext;
341
                        n->m_flags |= M_EXT;
342
                } else {
343
                        bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
344
                }
345
 
346
                m = m->m_next;
347
        }
348
        return top;
349
nospace:
350
        m_freem(top);
351
        MCFail++;
352
        return 0;
353
}
354
 
355
/*
356
 * Copy data from an mbuf chain starting "off" bytes from the beginning,
357
 * continuing for "len" bytes, into the indicated buffer.
358
 */
359
void
360
m_copydata(m, off, len, cp)
361
        register struct mbuf *m;
362
        register int off;
363
        register int len;
364
        caddr_t cp;
365
{
366
        register unsigned count;
367
 
368
        if (off < 0 || len < 0)
369
                panic("m_copydata");
370
        while (off > 0) {
371
                if (m == 0)
372
                        panic("m_copydata");
373
                if (off < m->m_len)
374
                        break;
375
                off -= m->m_len;
376
                m = m->m_next;
377
        }
378
        while (len > 0) {
379
                if (m == 0)
380
                        panic("m_copydata");
381
                count = min(m->m_len - off, len);
382
                bcopy(mtod(m, caddr_t) + off, cp, count);
383
                len -= count;
384
                cp += count;
385
                off = 0;
386
                m = m->m_next;
387
        }
388
}
389
 
390
/*
391
 * Concatenate mbuf chain n to m.
392
 * Both chains must be of the same type (e.g. MT_DATA).
393
 * Any m_pkthdr is not updated.
394
 */
395
void
396
m_cat(m, n)
397
        register struct mbuf *m, *n;
398
{
399
        while (m->m_next)
400
                m = m->m_next;
401
        while (n) {
402
                if (m->m_flags & M_EXT ||
403
                    m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
404
                        /* just join the two chains */
405
                        m->m_next = n;
406
                        return;
407
                }
408
                /* splat the data from one into the other */
409
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
410
                    (u_int)n->m_len);
411
                m->m_len += n->m_len;
412
                n = m_free(n);
413
        }
414
}
415
 
416
void
417
m_adj(mp, req_len)
418
        struct mbuf *mp;
419
        int req_len;
420
{
421
        register int len = req_len;
422
        register struct mbuf *m;
423
        register int count;
424
 
425
        if ((m = mp) == NULL)
426
                return;
427
        if (len >= 0) {
428
                /*
429
                 * Trim from head.
430
                 */
431
                while (m != NULL && len > 0) {
432
                        if (m->m_len <= len) {
433
                                len -= m->m_len;
434
                                m->m_len = 0;
435
                                m = m->m_next;
436
                        } else {
437
                                m->m_len -= len;
438
                                m->m_data += len;
439
                                len = 0;
440
                        }
441
                }
442
                m = mp;
443
                if (mp->m_flags & M_PKTHDR)
444
                        m->m_pkthdr.len -= (req_len - len);
445
        } else {
446
                /*
447
                 * Trim from tail.  Scan the mbuf chain,
448
                 * calculating its length and finding the last mbuf.
449
                 * If the adjustment only affects this mbuf, then just
450
                 * adjust and return.  Otherwise, rescan and truncate
451
                 * after the remaining size.
452
                 */
453
                len = -len;
454
                count = 0;
455
                for (;;) {
456
                        count += m->m_len;
457
                        if (m->m_next == (struct mbuf *)0)
458
                                break;
459
                        m = m->m_next;
460
                }
461
                if (m->m_len >= len) {
462
                        m->m_len -= len;
463
                        if (mp->m_flags & M_PKTHDR)
464
                                mp->m_pkthdr.len -= len;
465
                        return;
466
                }
467
                count -= len;
468
                if (count < 0)
469
                        count = 0;
470
                /*
471
                 * Correct length for chain is "count".
472
                 * Find the mbuf with last data, adjust its length,
473
                 * and toss data from remaining mbufs on chain.
474
                 */
475
                m = mp;
476
                if (m->m_flags & M_PKTHDR)
477
                        m->m_pkthdr.len = count;
478
                for (; m; m = m->m_next) {
479
                        if (m->m_len >= count) {
480
                                m->m_len = count;
481
                                break;
482
                        }
483
                        count -= m->m_len;
484
                }
485
                while (m->m_next)
486
                        (m = m->m_next) ->m_len = 0;
487
        }
488
}
489
 
490
/*
491
 * Rearange an mbuf chain so that len bytes are contiguous
492
 * and in the data area of an mbuf (so that mtod and dtom
493
 * will work for a structure of size len).  Returns the resulting
494
 * mbuf chain on success, frees it and returns null on failure.
495
 * If there is room, it will add up to max_protohdr-len extra bytes to the
496
 * contiguous region in an attempt to avoid being called next time.
497
 */
498
static int MPFail;
499
 
500
struct mbuf *
501
m_pullup(n, len)
502
        register struct mbuf *n;
503
        int len;
504
{
505
        register struct mbuf *m;
506
        register int count;
507
        int space;
508
 
509
        /*
510
         * If first mbuf has no cluster, and has room for len bytes
511
         * without shifting current data, pullup into it,
512
         * otherwise allocate a new mbuf to prepend to the chain.
513
         */
514
        if ((n->m_flags & M_EXT) == 0 &&
515
            n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
516
                if (n->m_len >= len)
517
                        return (n);
518
                m = n;
519
                n = n->m_next;
520
                len -= m->m_len;
521
        } else {
522
                if (len > MHLEN)
523
                        goto bad;
524
                MGET(m, M_DONTWAIT, n->m_type);
525
                if (m == 0)
526
                        goto bad;
527
                m->m_len = 0;
528
                if (n->m_flags & M_PKTHDR) {
529
                        M_COPY_PKTHDR(m, n);
530
                        n->m_flags &= ~M_PKTHDR;
531
                }
532
        }
533
        space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
534
        do {
535
                count = min(min(max(len, max_protohdr), space), n->m_len);
536
                bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
537
                  (unsigned)count);
538
                len -= count;
539
                m->m_len += count;
540
                n->m_len -= count;
541
                space -= count;
542
                if (n->m_len)
543
                        n->m_data += count;
544
                else
545
                        n = m_free(n);
546
        } while (len > 0 && n);
547
        if (len > 0) {
548
                (void) m_free(m);
549
                goto bad;
550
        }
551
        m->m_next = n;
552
        return (m);
553
bad:
554
        m_freem(n);
555
        MPFail++;
556
        return (0);
557
}
558
 
559
/*
560
 * Partition an mbuf chain in two pieces, returning the tail --
561
 * all but the first len0 bytes.  In case of failure, it returns NULL and
562
 * attempts to restore the chain to its original state.
563
 */
564
struct mbuf *
565
m_split(m0, len0, wait)
566
        register struct mbuf *m0;
567
        int len0, wait;
568
{
569
        register struct mbuf *m, *n;
570
        unsigned len = len0, remain;
571
 
572
        for (m = m0; m && len > m->m_len; m = m->m_next)
573
                len -= m->m_len;
574
        if (m == 0)
575
                return (0);
576
        remain = m->m_len - len;
577
        if (m0->m_flags & M_PKTHDR) {
578
                MGETHDR(n, wait, m0->m_type);
579
                if (n == 0)
580
                        return (0);
581
                n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
582
                n->m_pkthdr.len = m0->m_pkthdr.len - len0;
583
                m0->m_pkthdr.len = len0;
584
                if (m->m_flags & M_EXT)
585
                        goto extpacket;
586
                if (remain > MHLEN) {
587
                        /* m can't be the lead packet */
588
                        MH_ALIGN(n, 0);
589
                        n->m_next = m_split(m, len, wait);
590
                        if (n->m_next == 0) {
591
                                (void) m_free(n);
592
                                return (0);
593
                        } else
594
                                return (n);
595
                } else
596
                        MH_ALIGN(n, remain);
597
        } else if (remain == 0) {
598
                n = m->m_next;
599
                m->m_next = 0;
600
                return (n);
601
        } else {
602
                MGET(n, wait, m->m_type);
603
                if (n == 0)
604
                        return (0);
605
                M_ALIGN(n, remain);
606
        }
607
extpacket:
608
        if (m->m_flags & M_EXT) {
609
                n->m_flags |= M_EXT;
610
                n->m_ext = m->m_ext;
611
                if(!m->m_ext.ext_ref)
612
                        mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
613
                else
614
                        (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
615
                                                m->m_ext.ext_size);
616
                m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
617
                n->m_data = m->m_data + len;
618
        } else {
619
                bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
620
        }
621
        n->m_len = remain;
622
        m->m_len = len;
623
        n->m_next = m->m_next;
624
        m->m_next = 0;
625
        return (n);
626
}
627
/*
628
 * Routine to copy from device local memory into mbufs.
629
 */
630
struct mbuf *
631
m_devget(buf, totlen, off0, ifp, copy)
632
        char *buf;
633
        int totlen, off0;
634
        struct ifnet *ifp;
635
        void (*copy) __P((char *from, caddr_t to, u_int len));
636
{
637
        register struct mbuf *m;
638
        struct mbuf *top = 0, **mp = &top;
639
        register int off = off0, len;
640
        register char *cp;
641
        char *epkt;
642
 
643
        cp = buf;
644
        epkt = cp + totlen;
645
        if (off) {
646
                cp += off + 2 * sizeof(u_short);
647
                totlen -= 2 * sizeof(u_short);
648
        }
649
        MGETHDR(m, M_DONTWAIT, MT_DATA);
650
        if (m == 0)
651
                return (0);
652
        m->m_pkthdr.rcvif = ifp;
653
        m->m_pkthdr.len = totlen;
654
        m->m_len = MHLEN;
655
 
656
        while (totlen > 0) {
657
                if (top) {
658
                        MGET(m, M_DONTWAIT, MT_DATA);
659
                        if (m == 0) {
660
                                m_freem(top);
661
                                return (0);
662
                        }
663
                        m->m_len = MLEN;
664
                }
665
                len = min(totlen, epkt - cp);
666
                if (len >= MINCLSIZE) {
667
                        MCLGET(m, M_DONTWAIT);
668
                        if (m->m_flags & M_EXT)
669
                                m->m_len = len = min(len, MCLBYTES);
670
                        else
671
                                len = m->m_len;
672
                } else {
673
                        /*
674
                         * Place initial small packet/header at end of mbuf.
675
                         */
676
                        if (len < m->m_len) {
677
                                if (top == 0 && len + max_linkhdr <= m->m_len)
678
                                        m->m_data += max_linkhdr;
679
                                m->m_len = len;
680
                        } else
681
                                len = m->m_len;
682
                }
683
                if (copy)
684
                        copy(cp, mtod(m, caddr_t), (unsigned)len);
685
                else
686
                        bcopy(cp, mtod(m, caddr_t), (unsigned)len);
687
                cp += len;
688
                *mp = m;
689
                mp = &m->m_next;
690
                totlen -= len;
691
                if (cp == epkt)
692
                        cp = buf;
693
        }
694
        return (top);
695
}
696
 
697
/*
698
 * Copy data from a buffer back into the indicated mbuf chain,
699
 * starting "off" bytes from the beginning, extending the mbuf
700
 * chain if necessary.
701
 */
702
void
703
m_copyback(m0, off, len, cp)
704
        struct  mbuf *m0;
705
        register int off;
706
        register int len;
707
        caddr_t cp;
708
{
709
        register int mlen;
710
        register struct mbuf *m = m0, *n;
711
        int totlen = 0;
712
 
713
        if (m0 == 0)
714
                return;
715
        while (off > (mlen = m->m_len)) {
716
                off -= mlen;
717
                totlen += mlen;
718
                if (m->m_next == 0) {
719
                        n = m_getclr(M_DONTWAIT, m->m_type);
720
                        if (n == 0)
721
                                goto out;
722
                        n->m_len = min(MLEN, len + off);
723
                        m->m_next = n;
724
                }
725
                m = m->m_next;
726
        }
727
        while (len > 0) {
728
                mlen = min (m->m_len - off, len);
729
                bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
730
                cp += mlen;
731
                len -= mlen;
732
                mlen += off;
733
                off = 0;
734
                totlen += mlen;
735
                if (len == 0)
736
                        break;
737
                if (m->m_next == 0) {
738
                        n = m_get(M_DONTWAIT, m->m_type);
739
                        if (n == 0)
740
                                break;
741
                        n->m_len = min(MLEN, len);
742
                        m->m_next = n;
743
                }
744
                m = m->m_next;
745
        }
746
out:    if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
747
                m->m_pkthdr.len = totlen;
748
}

powered by: WebSVN 2.1.0

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