€•2BŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ%/translations/zh_CN/networking/skbuff”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/zh_TW/networking/skbuff”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/it_IT/networking/skbuff”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/ja_JP/networking/skbuff”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/ko_KR/networking/skbuff”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/pt_BR/networking/skbuff”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ%/translations/sp_SP/networking/skbuff”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒcomment”“”)”}”(hŒ SPDX-License-Identifier: GPL-2.0”h]”hŒ SPDX-License-Identifier: GPL-2.0”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³Œ?/var/lib/git/docbuild/linux/Documentation/networking/skbuff.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒstruct sk_buff”h]”hŒstruct sk_buff”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ paragraph”“”)”}”(hŒI:c:type:`sk_buff` is the main networking structure representing a packet.”h]”(h)”}”(hŒ:c:type:`sk_buff`”h]”hŒliteral”“”)”}”(hhåh]”hŒsk_buff”…””}”(hhéh²hh³Nh´Nubah}”(h]”h ]”(Œxref”Œc”Œc-type”eh"]”h$]”h&]”uh1hçhhãubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”Œnetworking/skbuff”Œ refdomain”hôŒreftype”Œtype”Œ refexplicit”‰Œrefwarn”‰Œ reftarget”Œsk_buff”uh1hh³hÇh´KhhßubhŒ8 is the main networking structure representing a packet.”…””}”(hhßh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhhÊh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒBasic sk_buff geometry”h]”hŒBasic sk_buff geometry”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´K ubhÞ)”}”(hŒ|struct sk_buff itself is a metadata structure and does not hold any packet data. All the data is held in associated buffers.”h]”hŒ|struct sk_buff itself is a metadata structure and does not hold any packet data. All the data is held in associated buffers.”…””}”(hj#h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:12: ./include/linux/skbuff.h”h´Màhjh²hubhÞ)”}”(hŒm:c:type:`sk_buff.head ` points to the main "head" buffer. The head buffer is divided into two parts:”h]”(h)”}”(hŒ :c:type:`sk_buff.head `”h]”hè)”}”(hj8h]”hŒ sk_buff.head”…””}”(hj:h²hh³Nh´Nubah}”(h]”h ]”(hóhôŒc-type”eh"]”h$]”h&]”uh1hçhj6ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jŒ refdomain”hôŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰jŒsk_buff”uh1hh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:12: ./include/linux/skbuff.h”h´Mãhj2ubhŒQ points to the main “head†buffer. The head buffer is divided into two parts:”…””}”(hj2h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³jUh´Mãhjh²hubhŒ block_quote”“”)”}”(hX- data buffer, containing headers and sometimes payload; this is the part of the skb operated on by the common helpers such as skb_put() or skb_pull(); - shared info (struct skb_shared_info) which holds an array of pointers to read-only data in the (page, offset, length) format. ”h]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ•data buffer, containing headers and sometimes payload; this is the part of the skb operated on by the common helpers such as skb_put() or skb_pull();”h]”hÞ)”}”(hŒ•data buffer, containing headers and sometimes payload; this is the part of the skb operated on by the common helpers such as skb_put() or skb_pull();”h]”hŒ•data buffer, containing headers and sometimes payload; this is the part of the skb operated on by the common helpers such as skb_put() or skb_pull();”…””}”(hjqh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:12: ./include/linux/skbuff.h”h´Mæhjmubah}”(h]”h ]”h"]”h$]”h&]”uh1jkhjhubjl)”}”(hŒ~shared info (struct skb_shared_info) which holds an array of pointers to read-only data in the (page, offset, length) format. ”h]”hÞ)”}”(hŒ}shared info (struct skb_shared_info) which holds an array of pointers to read-only data in the (page, offset, length) format.”h]”hŒ}shared info (struct skb_shared_info) which holds an array of pointers to read-only data in the (page, offset, length) format.”…””}”(hjŠh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:12: ./include/linux/skbuff.h”h´Méhj†ubah}”(h]”h ]”h"]”h$]”h&]”uh1jkhjhubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1jfh³jh´Mæhjbubah}”(h]”h ]”h"]”h$]”h&]”uh1j`h³jh´Mæhjh²hubhÞ)”}”(hŒZOptionally :c:type:`skb_shared_info.frag_list ` may point to another skb.”h]”(hŒ Optionally ”…””}”(hj­h²hh³Nh´Nubh)”}”(hŒ5:c:type:`skb_shared_info.frag_list `”h]”hè)”}”(hj·h]”hŒskb_shared_info.frag_list”…””}”(hj¹h²hh³Nh´Nubah}”(h]”h ]”(hóhôŒc-type”eh"]”h$]”h&]”uh1hçhjµubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jŒ refdomain”hôŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰jŒskb_shared_info”uh1hh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:12: ./include/linux/skbuff.h”h´Mìhj­ubhŒ may point to another skb.”…””}”(hj­h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³jÔh´Mìhjh²hubhÞ)”}”(hŒ"Basic diagram may look like this::”h]”hŒ!Basic diagram may look like this:”…””}”(hjßh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:12: ./include/linux/skbuff.h”h´Mîhjh²hubhŒ literal_block”“”)”}”(hXB --------------- | sk_buff | --------------- ,--------------------------- + head / ,----------------- + data / / ,----------- + tail | | | , + end | | | | v v v v ----------------------------------------------- | headroom | data | tailroom | skb_shared_info | ----------------------------------------------- + [page frag] + [page frag] + [page frag] + [page frag] --------- + frag_list --> | sk_buff | ---------”h]”hXB --------------- | sk_buff | --------------- ,--------------------------- + head / ,----------------- + data / / ,----------- + tail | | | , + end | | | | v v v v ----------------------------------------------- | headroom | data | tailroom | skb_shared_info | ----------------------------------------------- + [page frag] + [page frag] + [page frag] + [page frag] --------- + frag_list --> | sk_buff | ---------”…””}”hjðsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jîh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:12: ./include/linux/skbuff.h”h´Mðhjh²hubeh}”(h]”Œbasic-sk-buff-geometry”ah ]”h"]”Œbasic sk_buff geometry”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K ubhÉ)”}”(hhh]”(hÎ)”}”(hŒShared skbs and skb clones”h]”hŒShared skbs and skb clones”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´KubhÞ)”}”(hŒ¿:c:member:`sk_buff.users` is a simple refcount allowing multiple entities to keep a struct sk_buff alive. skbs with a ``sk_buff.users != 1`` are referred to as shared skbs (see skb_shared()).”h]”(h)”}”(hŒ:c:member:`sk_buff.users`”h]”hè)”}”(hjh]”hŒ sk_buff.users”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”(hóhôŒc-member”eh"]”h$]”h&]”uh1hçhjubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jŒ refdomain”hôŒreftype”Œmember”Œ refexplicit”‰Œrefwarn”‰jŒ sk_buff.users”uh1hh³hÇh´KhjubhŒ] is a simple refcount allowing multiple entities to keep a struct sk_buff alive. skbs with a ”…””}”(hjh²hh³Nh´Nubhè)”}”(hŒ``sk_buff.users != 1``”h]”hŒsk_buff.users != 1”…””}”(hj?h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hçhjubhŒ3 are referred to as shared skbs (see skb_shared()).”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubhÞ)”}”(hŒôskb_clone() allows for fast duplication of skbs. None of the data buffers get copied, but caller gets a new metadata struct (struct sk_buff). &skb_shared_info.refcount indicates the number of skbs pointing at the same packet data (i.e. clones).”h]”hŒôskb_clone() allows for fast duplication of skbs. None of the data buffers get copied, but caller gets a new metadata struct (struct sk_buff). &skb_shared_info.refcount indicates the number of skbs pointing at the same packet data (i.e. clones).”…””}”(hjWh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubeh}”(h]”Œshared-skbs-and-skb-clones”ah ]”h"]”Œshared skbs and skb clones”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒdataref and headerless skbs”h]”hŒdataref and headerless skbs”…””}”(hjph²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjmh²hh³hÇh´KubhÞ)”}”(hX¥Transport layers send out clones of payload skbs they hold for retransmissions. To allow lower layers of the stack to prepend their headers we split :c:type:`skb_shared_info.dataref ` into two halves. The lower 16 bits count the overall number of references. The higher 16 bits indicate how many of the references are payload-only. skb_header_cloned() checks if skb is allowed to add / write the headers.”h]”(hŒ•Transport layers send out clones of payload skbs they hold for retransmissions. To allow lower layers of the stack to prepend their headers we split ”…””}”(hj~h²hh³Nh´Nubh)”}”(hŒ3:c:type:`skb_shared_info.dataref `”h]”hè)”}”(hjˆh]”hŒskb_shared_info.dataref”…””}”(hjŠh²hh³Nh´Nubah}”(h]”h ]”(hóhôŒc-type”eh"]”h$]”h&]”uh1hçhj†ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jŒ refdomain”hôŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰jŒskb_shared_info”uh1hh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:30: ./include/linux/skbuff.h”h´Mxhj~ubhŒÝ into two halves. The lower 16 bits count the overall number of references. The higher 16 bits indicate how many of the references are payload-only. skb_header_cloned() checks if skb is allowed to add / write the headers.”…””}”(hj~h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³j¥h´Mxhjmh²hubhÞ)”}”(hXoThe creator of the skb (e.g. TCP) marks its skb as :c:type:`sk_buff.nohdr ` (via __skb_header_release()). Any clone created from marked skb will get :c:type:`sk_buff.hdr_len ` populated with the available headroom. If there's the only clone in existence it's able to modify the headroom at will. The sequence of calls inside the transport layer is::”h]”(hŒ3The creator of the skb (e.g. TCP) marks its skb as ”…””}”(hj°h²hh³Nh´Nubh)”}”(hŒ!:c:type:`sk_buff.nohdr `”h]”hè)”}”(hjºh]”hŒ sk_buff.nohdr”…””}”(hj¼h²hh³Nh´Nubah}”(h]”h ]”(hóhôŒc-type”eh"]”h$]”h&]”uh1hçhj¸ubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jŒ refdomain”hôŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰jŒsk_buff”uh1hh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:30: ./include/linux/skbuff.h”h´Mhj°ubhŒJ (via __skb_header_release()). Any clone created from marked skb will get ”…””}”(hj°h²hh³Nh´Nubh)”}”(hŒ#:c:type:`sk_buff.hdr_len `”h]”hè)”}”(hjÞh]”hŒsk_buff.hdr_len”…””}”(hjàh²hh³Nh´Nubah}”(h]”h ]”(hóhôŒc-type”eh"]”h$]”h&]”uh1hçhjÜubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”jŒ refdomain”hôŒreftype”Œtype”Œ refexplicit”ˆŒrefwarn”‰jŒsk_buff”uh1hh³j×h´Mhj°ubhŒ± populated with the available headroom. If there’s the only clone in existence it’s able to modify the headroom at will. The sequence of calls inside the transport layer is:”…””}”(hj°h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³j×h´Mhjmh²hubjï)”}”(hŒ] skb_reserve() __skb_header_release() skb_clone() // send the clone down the stack”h]”hŒ] skb_reserve() __skb_header_release() skb_clone() // send the clone down the stack”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jîh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:30: ./include/linux/skbuff.h”h´M…hjmh²hubhÞ)”}”(hX$This is not a very generic construct and it depends on the transport layers doing the right thing. In practice there's usually only one payload-only skb. Having multiple payload-only skbs with different lengths of hdr_len is not possible. The payload-only skbs should never leave their owner.”h]”hX&This is not a very generic construct and it depends on the transport layers doing the right thing. In practice there’s usually only one payload-only skb. Having multiple payload-only skbs with different lengths of hdr_len is not possible. The payload-only skbs should never leave their owner.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³ŒX/var/lib/git/docbuild/linux/Documentation/networking/skbuff:30: ./include/linux/skbuff.h”h´M‹hjmh²hubeh}”(h]”Œdataref-and-headerless-skbs”ah ]”h"]”Œdataref and headerless skbs”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´Kubeh}”(h]”Œstruct-sk-buff”ah ]”h"]”Œstruct sk_buff”ah$]”h&]”uh1hÈhhh²hh³hÇh´Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”hÇuh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(hÍNŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jVŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”hÇŒ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j0j-jjjjjgj(j%uŒ nametypes”}”(j0‰j‰jj‰j(‰uh}”(j-hÊjjjgjj%jmuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nh²hub.