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