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