xref: /netbsd-src/share/man/man9/mbuf.9 (revision 87d689fb734c654d2486f87f7be32f1b53ecdbec)
1.\"	$NetBSD: mbuf.9,v 1.53 2018/01/01 12:46:49 wiz Exp $
2.\"
3.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
4.\" All rights reserved.
5.\"
6.\" This documentation is derived from text contributed to The NetBSD Foundation
7.\" by S.P.Zeidler (aka stargazer).
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE.
29.\"
30.Dd January 1, 2018
31.Dt MBUF 9
32.Os
33.Sh NAME
34.Nm mbuf ,
35.Nm m_get ,
36.Nm m_getclr ,
37.Nm m_gethdr ,
38.Nm m_devget ,
39.Nm m_copym ,
40.Nm m_copypacket ,
41.Nm m_copydata ,
42.Nm m_copyback ,
43.Nm m_copyback_cow ,
44.Nm m_cat ,
45.Nm m_dup ,
46.Nm m_makewritable ,
47.Nm m_prepend ,
48.Nm m_pulldown ,
49.Nm m_pullup ,
50.Nm m_copyup ,
51.Nm m_split ,
52.Nm m_adj ,
53.Nm m_apply ,
54.Nm m_free ,
55.Nm m_freem ,
56.Nm mtod ,
57.Nm MGET ,
58.Nm MGETHDR ,
59.Nm MEXTMALLOC ,
60.Nm MEXTADD ,
61.Nm MCLGET ,
62.Nm M_COPY_PKTHDR ,
63.Nm M_MOVE_PKTHDR ,
64.Nm M_ALIGN ,
65.Nm MH_ALIGN ,
66.Nm M_LEADINGSPACE ,
67.Nm M_TRAILINGSPACE ,
68.Nm M_PREPEND ,
69.Nm MCHTYPE
70.Nd "functions and macros for managing memory used by networking code"
71.Sh SYNOPSIS
72.In sys/mbuf.h
73.Ft struct mbuf *
74.Fn m_get "int nowait" "int type"
75.Ft struct mbuf *
76.Fn m_getclr "int nowait" "int type"
77.Ft struct mbuf *
78.Fn m_gethdr "int nowait" "int type"
79.Ft struct mbuf *
80.Fn m_devget "char *buf" "int totlen" "int off0" "struct ifnet *ifp" "void (*copy)(const void *, void *, size_t)"
81.Ft struct mbuf *
82.Fn m_copym "struct mbuf *m" "int off0" "int len" "int wait"
83.Ft struct mbuf *
84.Fn m_copypacket "struct mbuf *m" "int how"
85.Ft void
86.Fn m_copydata "struct mbuf *m" "int off" "int len" "void *cp"
87.Ft void
88.Fn m_copyback "struct mbuf *m0" "int off" "int len" "void *cp"
89.Ft struct mbuf *
90.Fn m_copyback_cow "struct mbuf *m0" "int off" "int len" "void *cp" "int how"
91.Ft int
92.Fn m_makewritable "struct mbuf **mp" "int off" "int len" "int how"
93.Ft void
94.Fn m_cat "struct mbuf *m" "struct mbuf *n"
95.Ft struct mbuf *
96.Fn m_dup "struct mbuf *m" "int off0" "int len" "int wait"
97.Ft struct mbuf *
98.Fn m_prepend "struct mbuf *m" "int len" "int how"
99.Ft struct mbuf *
100.Fn m_pulldown "struct mbuf *m" "int off" "int len" "int *offp"
101.Ft struct mbuf *
102.Fn m_pullup "struct mbuf *n" "int len"
103.Ft struct mbuf *
104.Fn m_copyup "struct mbuf *m" "int len" "int dstoff"
105.Ft struct mbuf *
106.Fn m_split "struct mbuf *m0" "int len0" "int wait"
107.Ft void
108.Fn m_adj "struct mbuf *mp" "int req_len"
109.Ft int
110.Fn m_apply "struct mbuf *m" "int off" "int len" "int *f(void *, void *, unsigned int)" "void *arg"
111.Ft struct mbuf *
112.Fn m_free "struct mbuf *m"
113.Ft void
114.Fn m_freem "struct mbuf *m"
115.Ft datatype
116.Fn mtod "struct mbuf *m" "datatype"
117.Ft void
118.Fn MGET "struct mbuf *m" "int how" "int type"
119.Ft void
120.Fn MGETHDR "struct mbuf *m" "int how" "int type"
121.Ft void
122.Fn MEXTMALLOC "struct mbuf *m" "int len" "int how"
123.Ft void
124.Fn MEXTADD "struct mbuf *m" "void *buf" "int size" "int type" "void (*free)(struct mbuf *, void *, size_t, void *)" "void *arg"
125.Ft void
126.Fn MCLGET "struct mbuf *m" "int how"
127.Ft void
128.Fn M_COPY_PKTHDR "struct mbuf *to" "struct mbuf *from"
129.Ft void
130.Fn M_MOVE_PKTHDR "struct mbuf *to" "struct mbuf *from"
131.Ft void
132.Fn M_ALIGN "struct mbuf *m" "int len"
133.Ft void
134.Fn MH_ALIGN "struct mbuf *m" "int len"
135.Ft int
136.Fn M_LEADINGSPACE "struct mbuf *m"
137.Ft int
138.Fn M_TRAILINGSPACE "struct mbuf *m"
139.Ft void
140.Fn M_PREPEND "struct mbuf *m" "int plen" "int how"
141.Ft void
142.Fn MCHTYPE "struct mbuf *m" "int type"
143.Sh DESCRIPTION
144The
145.Nm
146functions and macros provide an easy and consistent way to handle
147a networking stack's memory management needs.
148An
149.Nm
150consists of a header and a data area.
151It is of a fixed size,
152.Dv MSIZE
153.Pq defined in Aq Pa machine/param.h ,
154which includes overhead.
155The header contains a pointer to the next
156.Nm
157in the
158.Sq "mbuf chain" ,
159a pointer to the next
160.Sq "mbuf chain" ,
161a pointer to the data area, the amount of data in this mbuf, its type
162and a
163.Dv flags
164field.
165.Pp
166The
167.Dv type
168variable can signify:
169.Bl -tag -compact -offset indent -width "XXXXXXXXXXX"
170.It Dv MT_FREE
171the mbuf should be on the ``free'' list
172.It Dv MT_DATA
173data was dynamically allocated
174.It Dv MT_HEADER
175data is a packet header
176.It Dv MT_SONAME
177data is a socket name
178.It Dv MT_SOOPTS
179data is socket options
180.It Dv MT_FTABLE
181data is the fragment reassembly header
182.It Dv MT_CONTROL
183mbuf contains ancillary \&(protocol control\&) data
184.It Dv MT_OOBDATA
185mbuf contains out-of-band data.
186.El
187.Pp
188The
189.Dv flags
190variable contains information describing the
191.Nm ,
192notably:
193.Bl -tag -compact -offset indent -width "XXXXXXXXXXX"
194.It Dv M_EXT
195has external storage
196.It Dv M_PKTHDR
197is start of record
198.It Dv M_EOR
199is end of record
200.It Dv M_CLUSTER
201external storage is a cluster.
202.El
203.Pp
204If an
205.Nm
206designates the start of a record
207.Pq Dv M_PKTHDR ,
208its
209.Dv flags
210field may contain additional information describing the content of
211the record:
212.Bl -tag -compact -offset indent -width "XXXXXXXXXXX"
213.It Dv M_BCAST
214sent/received as link-level broadcast
215.It Dv M_MCAST
216sent/received as link-level multicast
217.It Dv M_LINK0 ,
218.It Dv M_LINK1 ,
219.It Dv M_LINK2
220three link-level specific flags.
221.El
222.Pp
223An
224.Nm
225may add a single
226.Sq "mbuf cluster"
227of
228.Dv MCLBYTES
229bytes
230.Pq also defined in Aq Pa machine/param.h ,
231which has no additional overhead
232and is used instead of the internal data area; this is done when at least
233.Dv MINCLSIZE
234bytes of data must be stored.
235.Pp
236When the
237.Dv M_EXT
238flag is raised for an mbuf,
239the external storage area could be shared among multiple mbufs.
240Be careful when you attempt to overwrite the data content of the mbuf.
241.Bl -tag -width compact
242.It Fn m_get "int nowait" "int type"
243Allocates an mbuf and initializes it to contain internal data.
244The
245.Fa nowait
246parameter is a choice of
247.Dv M_WAIT / M_DONTWAIT
248from caller.
249.Dv M_WAIT
250means the call cannot fail, but may take forever.
251The
252.Fa type
253parameter is an mbuf type.
254.It Fn m_getclr "int nowait" "int type"
255Allocates an mbuf and initializes it to contain internal data, then
256zeros the data area.
257The
258.Fa nowait
259parameter is a choice of
260.Dv M_WAIT / M_DONTWAIT
261from caller.
262The
263.Fa type
264parameter is an mbuf type.
265.It Fn m_gethdr "int nowait" "int type"
266Allocates an mbuf and initializes it to contain a packet header and internal
267data.
268The
269.Fa nowait
270parameter is a choice of
271.Dv M_WAIT / M_DONTWAIT
272from caller.
273The
274.Fa type
275parameter is an mbuf type.
276.It Fn m_devget "char *buf" "int totlen" "int off0" "struct ifnet *ifp" "void (*copy)(const void *, void *, size_t)"
277Copies
278.Fa len
279bytes from device local memory into mbufs using copy routine
280.Fa copy .
281If parameter
282.Fa off
283is non-zero, the packet is supposed to be trailer-encapsulated and
284.Fa off
285bytes plus the type and length fields will be skipped before copying.
286Returns the top of the mbuf chain it created.
287.It Fn m_copym "struct mbuf *m" "int off0" "int len" "int wait"
288Creates a copy of an mbuf chain starting
289.Fa off0
290bytes from the beginning, continuing for
291.Fa len
292bytes.
293If the
294.Fa len
295requested is
296.Dv M_COPYALL ,
297the complete mbuf chain will be copied.
298The
299.Fa wait
300parameter is a choice of
301.Dv M_WAIT / M_DONTWAIT
302from caller.
303.It Fn m_copypacket "struct mbuf *m" "int how"
304Copies an entire packet, including header (which must be present).
305This function is an optimization of the common case
306.Li m_copym ( m , 0 , Dv M_COPYALL , Fa how ) .
307.It Fn m_copydata "struct mbuf *m" "int off" "int len" "void *cp"
308Copies
309.Fa len
310bytes data from mbuf chain
311.Fa m
312into the buffer
313.Fa cp ,
314starting
315.Fa off
316bytes from the beginning.
317.It Fn m_copyback "struct mbuf *m0" "int off" "int len" "void *cp"
318Copies
319.Fa len
320bytes data from buffer
321.Fa cp
322back into the mbuf chain
323.Fa m0 ,
324starting
325.Fa off
326bytes from the beginning of the chain, extending the mbuf chain if necessary.
327.Fn m_copyback
328can only fail when extending the chain.
329The caller should check for this kind of failure
330by checking the resulting length of the chain in that case.
331It is an error to use
332.Fn m_copyback
333on read-only mbufs.
334.It Fn m_copyback_cow "struct mbuf *m0" "int off" "int len" "void *cp" \
335"int how"
336Copies
337.Fa len
338bytes data from buffer
339.Fa cp
340back into the mbuf chain
341.Fa m0
342as
343.Fn m_copyback
344does.
345Unlike
346.Fn m_copyback ,
347it is safe to use
348.Fn m_copyback_cow
349on read-only mbufs.
350If needed,
351.Fn m_copyback_cow
352automatically allocates new mbufs and adjusts the chain.
353On success, it returns a pointer to the resulting mbuf chain,
354and frees the original mbuf
355.Fa m0 .
356Otherwise, it returns
357.Dv NULL .
358The
359.Fa how
360parameter is a choice of
361.Dv M_WAIT / M_DONTWAIT
362from the caller.
363Unlike
364.Fn m_copyback ,
365extending the mbuf chain isn't supported.
366It is an error to attempt to extend the mbuf chain using
367.Fn m_copyback_cow .
368.It Fn m_makewritable "struct mbuf **mp" "int off" "int len" "int how"
369Rearranges an mbuf chain so that
370.Fa len
371bytes from offset
372.Fa off
373are writable.
374When it meets read-only mbufs, it allocates new mbufs, adjusts the chain as
375.Fn m_copyback_cow
376does, and copies the original content into them.
377.Fn m_makewritable
378does
379.Em not
380guarantee that all
381.Fa len
382bytes at
383.Fa off
384are consecutive.
385The
386.Fa how
387parameter is a choice of
388.Dv M_WAIT / M_DONTWAIT
389from the caller.
390.Fn m_makewritable
391preserves the contents of the mbuf chain even in the case of failure.
392It updates a pointer to the mbuf chain pointed to by
393.Fa mp .
394It returns 0 on success.
395Otherwise, it returns an error code, typically
396.Er ENOBUFS .
397.It Fn m_cat "struct mbuf *m" "struct mbuf *n"
398Concatenates mbuf chain
399.Fa n
400to
401.Fa m .
402Both chains must be of the same type; packet headers will
403.Em not
404be updated if present.
405.It Fn m_dup "struct mbuf *m" "int off0" "int len" "int wait"
406Similarly to
407.Fn m_copym ,
408the function creates a copy of an mbuf chain starting
409.Fa off0
410bytes from the beginning, continuing for
411.Fa len
412bytes.
413While
414.Fn m_copym
415tries to share external storage for mbufs with
416.Dv M_EXT
417flag,
418.Fn m_dup
419will deep-copy the whole data content into new mbuf chain
420and avoids shared external storage.
421.It Fn m_prepend "struct mbuf *m" "int len" "int how"
422Lesser-used path for
423.Fn M_PREPEND :
424allocates new mbuf
425.Fa m
426of size
427.Fa len
428to prepend to the chain, copying junk along.
429The
430.Fa how
431parameter is a choice of
432.Dv M_WAIT / M_DONTWAIT
433from caller.
434.It Fn m_pulldown "struct mbuf *m" "int off" "int len" "int *offp"
435Rearranges an mbuf chain so that
436.Fa len
437bytes from offset
438.Fa off
439are contiguous and in the data area of an mbuf.
440The return value points to an mbuf in the middle of the mbuf chain
441.Fa m .
442If we call the return value
443.Fa n ,
444the contiguous data region is available at
445.Li "mtod(n, void *) + *offp" ,
446or
447.Li "mtod(n, void *)"
448if
449.Fa offp
450is
451.Dv NULL .
452The top of the mbuf chain
453.Fa m ,
454and mbufs up to
455.Fa off ,
456will not be modified.
457On successful return, it is guaranteed that the mbuf pointed to by
458.Fa n
459does not have a shared external storage,
460therefore it is safe to update the contiguous region.
461Returns
462.Dv NULL
463and frees the mbuf chain on failure.
464.Fa len
465must be smaller or equal than
466.Dv MCLBYTES .
467.It Fn m_pullup "struct mbuf *m" "int len"
468Rearranges an mbuf chain so that
469.Fa len
470bytes are contiguous
471and in the data area of an mbuf (so that
472.Fn mtod
473will work for a structure of size
474.Fa len ) .
475Returns the resulting
476mbuf chain on success, frees it and returns
477.Dv NULL
478on failure.
479If there is room, it will add up to
480.Dv max_protohdr
481-
482.Fa len
483extra bytes to the
484contiguous region to possibly avoid being called again.
485.Fa len
486must be smaller or equal than
487.Dv MHLEN .
488.It Fn m_copyup "struct mbuf *m" "int len" "int dstoff"
489Similar to
490.Fn m_pullup
491but copies
492.Fa len
493bytes of data into a new mbuf at
494.Fa dstoff
495bytes into the mbuf.
496The
497.Fa dstoff
498argument aligns the data and leaves room for a link layer header.
499Returns the new
500mbuf chain on success, and frees the mbuf chain and returns
501.Dv NULL
502on failure.
503Note that
504the function does not allocate mbuf clusters, so
505.Fa len + dstoff
506must be less than
507.Dv MHLEN .
508.It Fn m_split "struct mbuf *m0" "int len0" "int wait"
509Partitions an mbuf chain in two pieces, returning the tail,
510which is all but the first
511.Fa len0
512bytes.
513In case of failure, it returns
514.Dv NULL
515and attempts to
516restore the chain to its original state.
517.It Fn m_adj "struct mbuf *mp" "int req_len"
518Shaves off
519.Fa req_len
520bytes from head or tail of the (valid) data area.
521If
522.Fa req_len
523is greater than zero, front bytes are being shaved off, if it's smaller,
524from the back (and if it is zero, the mbuf will stay bearded).
525This function does not move data in any way, but is used to manipulate the
526data area pointer and data length variable of the mbuf in a non-clobbering
527way.
528.It Fn m_apply "struct mbuf *m" "int off" "int len" "int (*f)(void *, void *, unsigned int)" "void *arg"
529Apply function
530.Fa f
531to the data in an mbuf chain starting
532.Fa off
533bytes from the beginning, continuing for
534.Fa len
535bytes.
536Neither
537.Fa off
538nor
539.Fa len
540may be negative.
541.Fa arg
542will be supplied as first argument for
543.Fa f ,
544the second argument will be the pointer to the data buffer of a
545packet (starting after
546.Fa off
547bytes in the stream), and the third argument is the amount
548of data in bytes in this call.
549If
550.Fa f
551returns something not equal to zero
552.Fn m_apply
553will bail out, returning the return code of
554.Fa f .
555Upon successful completion it will return zero.
556.It Fn m_free "struct mbuf *m"
557Frees mbuf
558.Fa m .
559.It Fn m_freem "struct mbuf *m"
560Frees the mbuf chain beginning with
561.Fa m .
562This function contains the elementary sanity check for a
563.Dv NULL
564pointer.
565.It Fn mtod "struct mbuf *m" "datatype"
566Returns a pointer to the data contained in the specified mbuf
567.Fa m ,
568type-casted to the specified data type
569.Fa datatype .
570Implemented as a macro.
571.It Fn MGET "struct mbuf *m" "int how" "int type"
572Allocates mbuf
573.Fa m
574and initializes it to contain internal data.
575See
576.Fn m_get .
577Implemented as a macro.
578.It Fn MGETHDR "struct mbuf *m" "int how" "int type"
579Allocates mbuf
580.Fa m
581and initializes it to contain a packet header.
582See
583.Fn m_gethdr .
584Implemented as a macro.
585.It Fn MEXTMALLOC "struct mbuf *m" "int len" "int how"
586Allocates external storage of size
587.Fa len
588for mbuf
589.Fa m .
590The
591.Fa how
592parameter is a choice of
593.Dv M_WAIT / M_DONTWAIT
594from caller.
595The flag
596.Dv M_EXT
597is set upon success.
598Implemented as a macro.
599.It Fn MEXTADD "struct mbuf *m" "void *buf" "int size" "int type" "void (*free)(struct mbuf *, void *, size_t, void *)" "void *arg"
600Adds pre-allocated external storage
601.Fa buf
602to a normal mbuf
603.Fa m ;
604the parameters
605.Fa size ,
606.Fa type ,
607.Fa free
608and
609.Fa arg
610describe the external storage.
611.Fa size
612is the size of the storage,
613.Fa type
614describes its
615.Xr malloc 9
616type,
617.Fa free
618is a free routine (if not the usual one), and
619.Fa arg
620is a possible argument to the free routine.
621The flag
622.Dv M_EXT
623is set upon success.
624Implemented as a macro.
625If a free routine is specified, it will be called when the mbuf is freed.
626In the case of former, the first argument for a free routine is the mbuf
627.Fa m
628and the routine is expected to free it in addition to the external storage
629pointed by second argument.
630In the case of latter, the first argument for the routine is NULL.
631.It Fn MCLGET "struct mbuf *m" "int how"
632Allocates and adds an mbuf cluster to a normal mbuf
633.Fa m .
634The
635.Fa how
636parameter is a choice of
637.Dv M_WAIT / M_DONTWAIT
638from caller.
639The flag
640.Dv M_EXT
641is set upon success.
642Implemented as a macro.
643.It Fn M_COPY_PKTHDR "struct mbuf *to" "struct mbuf *from"
644Copies the mbuf pkthdr from mbuf
645.Fa from
646to mbuf
647.Fa to .
648.Fa from
649must have the type flag
650.Dv M_PKTHDR
651set, and
652.Fa to
653must be empty.
654Implemented as a macro.
655.It Fn M_MOVE_PKTHDR "struct mbuf *to" "struct mbuf *from"
656Moves the mbuf pkthdr from mbuf
657.Fa from
658to mbuf
659.Fa to .
660.Fa from
661must have the type flag
662.Dv M_PKTHDR
663set, and
664.Fa to
665must be empty.
666The flag
667.Dv M_PKTHDR
668in mbuf
669.Fa from
670will be cleared.
671.It Fn M_ALIGN "struct mbuf *m" "int len"
672Sets the data pointer of a newly allocated mbuf
673.Fa m
674to
675.Fa len
676bytes from the end of the mbuf data area, so that
677.Fa len
678bytes of data written to the mbuf
679.Fa m ,
680starting at the data pointer, will be aligned to the end of the data area.
681Implemented as a macro.
682.It Fn MH_ALIGN "struct mbuf *m" "int len"
683Sets the data pointer of a newly allocated packetheader mbuf
684.Fa m
685to
686.Fa len
687bytes from the end of the mbuf data area, so that
688.Fa len
689bytes of data written to the mbuf
690.Fa m ,
691starting at the data pointer, will be aligned to the end of the data area.
692Implemented as a macro.
693.It Fn M_LEADINGSPACE "struct mbuf *m"
694Returns the amount of space available before the current start of valid
695data in mbuf
696.Fa m .
697Returns 0 if the mbuf data part is shared across multiple mbufs
698.Pq i.e. not writable .
699Implemented as a macro.
700.It Fn M_TRAILINGSPACE "struct mbuf *m"
701Returns the amount of space available after the current end of valid
702data in mbuf
703.Fa m .
704Returns 0 if the mbuf data part is shared across multiple mbufs
705.Pq i.e. not writable .
706Implemented as a macro.
707.It Fn M_PREPEND "struct mbuf *m" "int plen" "int how"
708Prepends space of size
709.Fa plen
710to mbuf
711.Fa m .
712If a new mbuf must be allocated,
713.Fa how
714specifies whether to wait.
715If
716.Fa how
717is
718.Dv M_DONTWAIT
719and allocation fails, the original mbuf chain is freed and
720.Fa m
721is set to
722.Dv NULL .
723Implemented as a macro.
724.It Fn MCHTYPE "struct mbuf *m" "int type"
725Change mbuf
726.Fa m
727to new type
728.Fa type .
729Implemented as a macro.
730.El
731.Sh CODE REFERENCES
732The
733.Nm
734management functions are implemented within the file
735.Pa sys/kern/uipc_mbuf.c .
736Function prototypes, and the functions implemented as macros
737are located in
738.Pa sys/sys/mbuf.h .
739.Sh SEE ALSO
740.Pa /usr/share/doc/smm/18.net ,
741.Xr netstat 1 ,
742.Xr m_tag 9 ,
743.Xr malloc 9
744.Rs
745.%A Jun-ichiro Hagino
746.%T "Mbuf issues in 4.4BSD IPv6/IPsec support (experiences from KAME IPv6/IPsec implementation)"
747.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
748.%D June 2000
749.Re
750.Sh AUTHORS
751.An -nosplit
752The original mbuf data structures were designed by Rob Gurwitz
753when he did the initial TCP/IP implementation at BBN.
754.Pp
755Further extensions and enhancements were made by Bill Joy, Sam Leffler,
756and Mike Karels at CSRG.
757.Pp
758Current implementation of external storage by
759.An Matt Thomas
760.Aq matt@3am-software.com
761and
762.An Jason R. Thorpe
763.Aq thorpej@NetBSD.org .
764