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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [kern/] [uipc_mbuf2.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/kern/uipc_mbuf2.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// -------------------------------------------
18
//
19
//####BSDCOPYRIGHTEND####
20
//==========================================================================
21
 
22
/*      $KAME: uipc_mbuf2.c,v 1.31 2001/11/28 11:08:53 itojun Exp $     */
23
/*      $NetBSD: uipc_mbuf.c,v 1.40 1999/04/01 00:23:25 thorpej Exp $   */
24
 
25
/*
26
 * Copyright (C) 1999 WIDE Project.
27
 * All rights reserved.
28
 *
29
 * Redistribution and use in source and binary forms, with or without
30
 * modification, are permitted provided that the following conditions
31
 * are met:
32
 * 1. Redistributions of source code must retain the above copyright
33
 *    notice, this list of conditions and the following disclaimer.
34
 * 2. Redistributions in binary form must reproduce the above copyright
35
 *    notice, this list of conditions and the following disclaimer in the
36
 *    documentation and/or other materials provided with the distribution.
37
 * 3. Neither the name of the project nor the names of its contributors
38
 *    may be used to endorse or promote products derived from this software
39
 *    without specific prior written permission.
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
 * SUCH DAMAGE.
52
 */
53
 
54
/*
55
 * Copyright (c) 1982, 1986, 1988, 1991, 1993
56
 *      The Regents of the University of California.  All rights reserved.
57
 *
58
 * Redistribution and use in source and binary forms, with or without
59
 * modification, are permitted provided that the following conditions
60
 * are met:
61
 * 1. Redistributions of source code must retain the above copyright
62
 *    notice, this list of conditions and the following disclaimer.
63
 * 2. Redistributions in binary form must reproduce the above copyright
64
 *    notice, this list of conditions and the following disclaimer in the
65
 *    documentation and/or other materials provided with the distribution.
66
 * 3. All advertising materials mentioning features or use of this software
67
 *    must display the following acknowledgement:
68
 *      This product includes software developed by the University of
69
 *      California, Berkeley and its contributors.
70
 * 4. Neither the name of the University nor the names of its contributors
71
 *    may be used to endorse or promote products derived from this software
72
 *    without specific prior written permission.
73
 *
74
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
75
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
76
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
77
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
78
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
79
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
80
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
81
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
82
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
83
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
84
 * SUCH DAMAGE.
85
 *
86
 *      @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95
87
 */
88
 
89
#include <sys/param.h>
90
#include <sys/malloc.h>
91
#include <sys/mbuf.h>
92
 
93
#ifdef __bsdi__
94
#define M_SHAREDCLUSTER(m) \
95
        (((m)->m_flags & M_EXT) != 0 && \
96
         ((m)->m_ext.ext_func || mclrefcnt[mtocl((m)->m_ext.ext_buf)] > 1))
97
#elif defined(__NetBSD__) || defined(__OpenBSD__)
98
#define M_SHAREDCLUSTER(m) \
99
        (((m)->m_flags & M_EXT) != 0 && \
100
         ((m)->m_ext.ext_free || MCLISREFERENCED((m))))
101
#else
102
#define M_SHAREDCLUSTER(m) \
103
        (((m)->m_flags & M_EXT) != 0 && \
104
         ((m)->m_ext.ext_free || mclrefcnt[mtocl((m)->m_ext.ext_buf)] > 1))
105
#endif
106
 
107
#ifndef __NetBSD__
108
/* can't call it m_dup(), as freebsd[34] uses m_dup() with different arg */
109
static struct mbuf *m_dup1 __P((struct mbuf *, int, int, int));
110
#endif
111
 
112
/*
113
 * ensure that [off, off + len) is contiguous on the mbuf chain "m".
114
 * packet chain before "off" is kept untouched.
115
 * if offp == NULL, the target will start at <retval, 0> on resulting chain.
116
 * if offp != NULL, the target will start at <retval, *offp> on resulting chain.
117
 *
118
 * on error return (NULL return value), original "m" will be freed.
119
 *
120
 * XXX M_TRAILINGSPACE/M_LEADINGSPACE on shared cluster (sharedcluster)
121
 */
122
struct mbuf *
123
m_pulldown(m, off, len, offp)
124
        struct mbuf *m;
125
        int off, len;
126
        int *offp;
127
{
128
        struct mbuf *n, *o;
129
        int hlen, tlen, olen;
130
        int sharedcluster;
131
#ifdef PULLDOWN_STAT
132
        static struct mbuf *prev = NULL;
133
        int prevlen = 0, prevmlen = 0;
134
#endif
135
 
136
        /* check invalid arguments. */
137
        if (m == NULL)
138
                panic("m == NULL in m_pulldown()");
139
        if (len > MCLBYTES) {
140
                m_freem(m);
141
                return NULL;    /* impossible */
142
        }
143
 
144
#ifdef PULLDOWN_STAT
145
        mbstat.m_pulldowns++;
146
#endif
147
 
148
#ifdef PULLDOWN_STAT
149
        /* statistics for m_pullup */
150
        mbstat.m_pullups++;
151
        if (off + len > MHLEN)
152
                mbstat.m_pullup_fail++;
153
        else {
154
                int dlen, mlen;
155
 
156
                dlen = (prev == m) ? prevlen : m->m_len;
157
                mlen = (prev == m) ? prevmlen : m->m_len + M_TRAILINGSPACE(m);
158
 
159
                if (dlen >= off + len)
160
                        mbstat.m_pullups--; /* call will not be made! */
161
                else if ((m->m_flags & M_EXT) != 0) {
162
                        mbstat.m_pullup_alloc++;
163
                        mbstat.m_pullup_copy++;
164
                } else {
165
                        if (mlen >= off + len)
166
                                mbstat.m_pullup_copy++;
167
                        else {
168
                                mbstat.m_pullup_alloc++;
169
                                mbstat.m_pullup_copy++;
170
                        }
171
                }
172
 
173
                prevlen = off + len;
174
                prevmlen = MHLEN;
175
        }
176
 
177
        /* statistics for m_pullup2 */
178
        mbstat.m_pullup2++;
179
        if (off + len > MCLBYTES)
180
                mbstat.m_pullup2_fail++;
181
        else {
182
                int dlen, mlen;
183
 
184
                dlen = (prev == m) ? prevlen : m->m_len;
185
                mlen = (prev == m) ? prevmlen : m->m_len + M_TRAILINGSPACE(m);
186
                prevlen = off + len;
187
                prevmlen = mlen;
188
 
189
                if (dlen >= off + len)
190
                        mbstat.m_pullup2--; /* call will not be made! */
191
                else if ((m->m_flags & M_EXT) != 0) {
192
                        mbstat.m_pullup2_alloc++;
193
                        mbstat.m_pullup2_copy++;
194
                        prevmlen = (off + len > MHLEN) ? MCLBYTES : MHLEN;
195
                } else {
196
                        if (mlen >= off + len)
197
                                mbstat.m_pullup2_copy++;
198
                        else {
199
                                mbstat.m_pullup2_alloc++;
200
                                mbstat.m_pullup2_copy++;
201
                                prevmlen = (off + len > MHLEN) ? MCLBYTES
202
                                                               : MHLEN;
203
                        }
204
                }
205
        }
206
 
207
        prev = m;
208
#endif
209
 
210
#ifdef PULLDOWN_DEBUG
211
    {
212
        struct mbuf *t;
213
        printf("before:");
214
        for (t = m; t; t = t->m_next)
215
                printf(" %d", t->m_len);
216
        printf("\n");
217
    }
218
#endif
219
        n = m;
220
        while (n != NULL && off > 0) {
221
                if (n->m_len > off)
222
                        break;
223
                off -= n->m_len;
224
                n = n->m_next;
225
        }
226
        /* be sure to point non-empty mbuf */
227
        while (n != NULL && n->m_len == 0)
228
                n = n->m_next;
229
        if (!n) {
230
                m_freem(m);
231
                return NULL;    /* mbuf chain too short */
232
        }
233
 
234
        sharedcluster = M_SHAREDCLUSTER(n);
235
 
236
        /*
237
         * the target data is on <n, off>.
238
         * if we got enough data on the mbuf "n", we're done.
239
         */
240
        if ((off == 0 || offp) && len <= n->m_len - off && !sharedcluster)
241
                goto ok;
242
 
243
#ifdef PULLDOWN_STAT
244
        mbstat.m_pulldown_copy++;
245
#endif
246
 
247
        /*
248
         * when len <= n->m_len - off and off != 0, it is a special case.
249
         * len bytes from <n, off> sits in single mbuf, but the caller does
250
         * not like the starting position (off).
251
         * chop the current mbuf into two pieces, set off to 0.
252
         */
253
        if (len <= n->m_len - off) {
254
#ifdef __NetBSD__
255
                o = m_dup(n, off, n->m_len - off, M_DONTWAIT);
256
#else
257
                o = m_dup1(n, off, n->m_len - off, M_DONTWAIT);
258
#endif
259
                if (o == NULL) {
260
                        m_freem(m);
261
                        return NULL;    /* ENOBUFS */
262
                }
263
                n->m_len = off;
264
                o->m_next = n->m_next;
265
                n->m_next = o;
266
                n = n->m_next;
267
                off = 0;
268
                goto ok;
269
        }
270
 
271
        /*
272
         * we need to take hlen from <n, off> and tlen from <n->m_next, 0>,
273
         * and construct contiguous mbuf with m_len == len.
274
         * note that hlen + tlen == len, and tlen > 0.
275
         */
276
        hlen = n->m_len - off;
277
        tlen = len - hlen;
278
 
279
        /*
280
         * ensure that we have enough trailing data on mbuf chain.
281
         * if not, we can do nothing about the chain.
282
         */
283
        olen = 0;
284
        for (o = n->m_next; o != NULL; o = o->m_next)
285
                olen += o->m_len;
286
        if (hlen + olen < len) {
287
                m_freem(m);
288
                return NULL;    /* mbuf chain too short */
289
        }
290
 
291
        /*
292
         * easy cases first.
293
         * we need to use m_copydata() to get data from <n->m_next, 0>.
294
         */
295
        if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen &&
296
            !sharedcluster) {
297
                m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
298
                n->m_len += tlen;
299
                m_adj(n->m_next, tlen);
300
                goto ok;
301
        }
302
        if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen &&
303
            !sharedcluster) {
304
                n->m_next->m_data -= hlen;
305
                n->m_next->m_len += hlen;
306
                bcopy(mtod(n, caddr_t) + off, mtod(n->m_next, caddr_t), hlen);
307
                n->m_len -= hlen;
308
                n = n->m_next;
309
                off = 0;
310
                goto ok;
311
        }
312
 
313
        /*
314
         * now, we need to do the hard way.  don't m_copy as there's no room
315
         * on both end.
316
         */
317
#ifdef PULLDOWN_STAT
318
        mbstat.m_pulldown_alloc++;
319
#endif
320
        MGET(o, M_DONTWAIT, m->m_type);
321
        if (o && len > MLEN) {
322
                MCLGET(o, M_DONTWAIT);
323
                if ((o->m_flags & M_EXT) == 0) {
324
                        m_free(o);
325
                        o = NULL;
326
                }
327
        }
328
        if (!o) {
329
                m_freem(m);
330
                return NULL;    /* ENOBUFS */
331
        }
332
        /* get hlen from <n, off> into <o, 0> */
333
        o->m_len = hlen;
334
        bcopy(mtod(n, caddr_t) + off, mtod(o, caddr_t), hlen);
335
        n->m_len -= hlen;
336
        /* get tlen from <n->m_next, 0> into <o, hlen> */
337
        m_copydata(n->m_next, 0, tlen, mtod(o, caddr_t) + o->m_len);
338
        o->m_len += tlen;
339
        m_adj(n->m_next, tlen);
340
        o->m_next = n->m_next;
341
        n->m_next = o;
342
        n = o;
343
        off = 0;
344
 
345
ok:
346
#ifdef PULLDOWN_DEBUG
347
    {
348
        struct mbuf *t;
349
        printf("after:");
350
        for (t = m; t; t = t->m_next)
351
                printf("%c%d", t == n ? '*' : ' ', t->m_len);
352
        printf(" (off=%d)\n", off);
353
    }
354
#endif
355
        if (offp)
356
                *offp = off;
357
        return n;
358
}
359
 
360
#ifndef __NetBSD__
361
static struct mbuf *
362
m_dup1(m, off, len, wait)
363
        struct mbuf *m;
364
        int off;
365
        int len;
366
        int wait;
367
{
368
        struct mbuf *n;
369
        int l;
370
        int copyhdr;
371
 
372
        if (len > MCLBYTES)
373
                return NULL;
374
        if (off == 0 && (m->m_flags & M_PKTHDR) != 0) {
375
                copyhdr = 1;
376
                MGETHDR(n, wait, m->m_type);
377
                l = MHLEN;
378
        } else {
379
                copyhdr = 0;
380
                MGET(n, wait, m->m_type);
381
                l = MLEN;
382
        }
383
        if (n && len > l) {
384
                MCLGET(n, wait);
385
                if ((n->m_flags & M_EXT) == 0) {
386
                        m_free(n);
387
                        n = NULL;
388
                }
389
        }
390
        if (!n)
391
                return NULL;
392
 
393
        if (copyhdr) {
394
#ifdef __OpenBSD__
395
                M_MOVE_PKTHDR(n, m);
396
#else
397
                M_COPY_PKTHDR(n, m);
398
#endif
399
        }
400
        m_copydata(m, off, len, mtod(n, caddr_t));
401
        n->m_len = len;
402
 
403
        return n;
404
}
405
#endif
406
 
407
/*
408
 * pkthdr.aux chain manipulation.
409
 * we don't allow clusters at this moment.
410
 */
411
struct mbuf *
412
m_aux_add2(m, af, type, p)
413
        struct mbuf *m;
414
        int af, type;
415
        void *p;
416
{
417
        struct mbuf *n;
418
        struct mauxtag *t;
419
 
420
        if ((m->m_flags & M_PKTHDR) == 0)
421
                return NULL;
422
 
423
        n = m_aux_find(m, af, type);
424
        if (n)
425
                return n;
426
 
427
        MGET(n, M_DONTWAIT, m->m_type);
428
        if (n == NULL)
429
                return NULL;
430
 
431
        t = mtod(n, struct mauxtag *);
432
        bzero(t, sizeof(*t));
433
        t->af = af;
434
        t->type = type;
435
        t->p = p;
436
        n->m_data += sizeof(struct mauxtag);
437
        n->m_len = 0;
438
        n->m_next = m->m_pkthdr.aux;
439
        m->m_pkthdr.aux = n;
440
        return n;
441
}
442
 
443
struct mbuf *
444
m_aux_find2(m, af, type, p)
445
        struct mbuf *m;
446
        int af, type;
447
        void *p;
448
{
449
        struct mbuf *n;
450
        struct mauxtag *t;
451
 
452
        if ((m->m_flags & M_PKTHDR) == 0)
453
                return NULL;
454
 
455
        for (n = m->m_pkthdr.aux; n; n = n->m_next) {
456
                t = (struct mauxtag *)n->m_dat;
457
                if (n->m_data != ((caddr_t)t) + sizeof(struct mauxtag)) {
458
                        printf("m_aux_find: invalid m_data for mbuf=%p (%p %p)\n", n, t, n->m_data);
459
                        continue;
460
                }
461
                if (t->af == af && t->type == type && t->p == p)
462
                        return n;
463
        }
464
        return NULL;
465
}
466
 
467
struct mbuf *
468
m_aux_find(m, af, type)
469
        struct mbuf *m;
470
        int af, type;
471
{
472
 
473
        return m_aux_find2(m, af, type, NULL);
474
}
475
 
476
struct mbuf *
477
m_aux_add(m, af, type)
478
        struct mbuf *m;
479
        int af, type;
480
{
481
 
482
        return m_aux_add2(m, af, type, NULL);
483
}
484
 
485
void
486
m_aux_delete(m, victim)
487
        struct mbuf *m;
488
        struct mbuf *victim;
489
{
490
        struct mbuf *n, *prev, *next;
491
        struct mauxtag *t;
492
 
493
        if ((m->m_flags & M_PKTHDR) == 0)
494
                return;
495
 
496
        prev = NULL;
497
        n = m->m_pkthdr.aux;
498
        while (n) {
499
                t = (struct mauxtag *)n->m_dat;
500
                next = n->m_next;
501
                if (n->m_data != ((caddr_t)t) + sizeof(struct mauxtag)) {
502
                        printf("m_aux_delete: invalid m_data for mbuf=%p (%p %p)\n", n, t, n->m_data);
503
                        prev = n;
504
                        n = next;
505
                        continue;
506
                }
507
                if (n == victim) {
508
                        if (prev)
509
                                prev->m_next = n->m_next;
510
                        else
511
                                m->m_pkthdr.aux = n->m_next;
512
                        n->m_next = NULL;
513
                        m_free(n);
514
                } else
515
                        prev = n;
516
                n = next;
517
        }
518
}
519
 
520
#ifdef __OpenBSD__
521
/* Get a packet tag structure along with specified data following. */
522
struct m_tag *
523
m_tag_get(type, len, wait)
524
        int type;
525
        int len;
526
        int wait;
527
{
528
        struct m_tag *t;
529
 
530
        if (len < 0)
531
                return (NULL);
532
        MALLOC(t, struct m_tag *, len + sizeof(struct m_tag), M_PACKET_TAGS,
533
            wait);
534
        if (t == NULL)
535
                return (NULL);
536
        t->m_tag_id = type;
537
        t->m_tag_len = len;
538
        return (t);
539
}
540
 
541
/* Free a packet tag. */
542
void
543
m_tag_free(t)
544
        struct m_tag *t;
545
{
546
        FREE(t, M_PACKET_TAGS);
547
}
548
 
549
/* Prepend a packet tag. */
550
void
551
m_tag_prepend(m, t)
552
        struct mbuf *m;
553
        struct m_tag *t;
554
{
555
        SLIST_INSERT_HEAD(&m->m_pkthdr.tags, t, m_tag_link);
556
}
557
 
558
/* Unlink a packet tag. */
559
void
560
m_tag_unlink(m, t)
561
        struct mbuf *m;
562
        struct m_tag *t;
563
{
564
        SLIST_REMOVE(&m->m_pkthdr.tags, t, m_tag, m_tag_link);
565
}
566
 
567
/* Unlink and free a packet tag. */
568
void
569
m_tag_delete(m, t)
570
        struct mbuf *m;
571
        struct m_tag *t;
572
{
573
        m_tag_unlink(m, t);
574
        m_tag_free(t);
575
}
576
 
577
/* Unlink and free a packet tag chain, starting from given tag. */
578
void
579
m_tag_delete_chain(m, t)
580
        struct mbuf *m;
581
        struct m_tag *t;
582
{
583
        struct m_tag *p, *q;
584
 
585
        if (t != NULL)
586
                p = t;
587
        else
588
                p = SLIST_FIRST(&m->m_pkthdr.tags);
589
        if (p == NULL)
590
                return;
591
        while ((q = SLIST_NEXT(p, m_tag_link)) != NULL)
592
                m_tag_delete(m, q);
593
        m_tag_delete(m, p);
594
}
595
 
596
/* Find a tag, starting from a given position. */
597
struct m_tag *
598
m_tag_find(m, type, t)
599
        struct mbuf *m;
600
        int type;
601
        struct m_tag *t;
602
{
603
        struct m_tag *p;
604
 
605
        if (t == NULL)
606
                p = SLIST_FIRST(&m->m_pkthdr.tags);
607
        else
608
                p = SLIST_NEXT(t, m_tag_link);
609
        while (p != NULL) {
610
                if (p->m_tag_id == type)
611
                        return (p);
612
                p = SLIST_NEXT(p, m_tag_link);
613
        }
614
        return (NULL);
615
}
616
 
617
/* Copy a single tag. */
618
struct m_tag *
619
m_tag_copy(t)
620
        struct m_tag *t;
621
{
622
        struct m_tag *p;
623
 
624
        p = m_tag_get(t->m_tag_id, t->m_tag_len, M_NOWAIT);
625
        if (p == NULL)
626
                return (NULL);
627
        bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */
628
        return (p);
629
}
630
 
631
/*
632
 * Copy two tag chains. The destination mbuf (to) loses any attached
633
 * tags even if the operation fails. This should not be a problem, as
634
 * m_tag_copy_chain() is typically called with a newly-allocated
635
 * destination mbuf.
636
 */
637
int
638
m_tag_copy_chain(to, from)
639
        struct mbuf *to;
640
        struct mbuf *from;
641
{
642
        struct m_tag *p, *t, *tprev = NULL;
643
 
644
        m_tag_delete_chain(to, NULL);
645
        SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) {
646
                t = m_tag_copy(p);
647
                if (t == NULL) {
648
                        m_tag_delete_chain(to, NULL);
649
                        return (0);
650
                }
651
                if (tprev == NULL)
652
                        SLIST_INSERT_HEAD(&to->m_pkthdr.tags, t, m_tag_link);
653
                else {
654
                        SLIST_INSERT_AFTER(tprev, t, m_tag_link);
655
                        tprev = t;
656
                }
657
        }
658
        return (1);
659
}
660
 
661
/* Initialize tags on an mbuf. */
662
void
663
m_tag_init(m)
664
        struct mbuf *m;
665
{
666
        SLIST_INIT(&m->m_pkthdr.tags);
667
}
668
 
669
/* Get first tag in chain. */
670
struct m_tag *
671
m_tag_first(m)
672
        struct mbuf *m;
673
{
674
        return (SLIST_FIRST(&m->m_pkthdr.tags));
675
}
676
 
677
/* Get next tag in chain. */
678
struct m_tag *
679
m_tag_next(m, t)
680
        struct mbuf *m;
681
        struct m_tag *t;
682
{
683
        return (SLIST_NEXT(t, m_tag_link));
684
}
685
#endif /* OpenBSD */

powered by: WebSVN 2.1.0

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