€•aŒ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/bpf/prog_flow_dissector”Œ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/bpf/prog_flow_dissector”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/it_IT/bpf/prog_flow_dissector”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ja_JP/bpf/prog_flow_dissector”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ+/translations/ko_KR/bpf/prog_flow_dissector”Œ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/bpf/prog_flow_dissector”Œ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/bpf/prog_flow_dissector”Œ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³ŒE/var/lib/git/docbuild/linux/Documentation/bpf/prog_flow_dissector.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒBPF_PROG_TYPE_FLOW_DISSECTOR”h]”hŒBPF_PROG_TYPE_FLOW_DISSECTOR”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒOverview”h]”hŒOverview”…””}”(hhàh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÝh²hh³hÇh´KubhŒ paragraph”“”)”}”(hŒ—Flow dissector is a routine that parses metadata out of the packets. It's used in the various places in the networking subsystem (RFS, flow hash, etc).”h]”hŒ™Flow dissector is a routine that parses metadata out of the packets. It’s used in the various places in the networking subsystem (RFS, flow hash, etc).”…””}”(hhðh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K hhÝh²hubhï)”}”(hŒ»BPF flow dissector is an attempt to reimplement C-based flow dissector logic in BPF to gain all the benefits of BPF verifier (namely, limits on the number of instructions and tail calls).”h]”hŒ»BPF flow dissector is an attempt to reimplement C-based flow dissector logic in BPF to gain all the benefits of BPF verifier (namely, limits on the number of instructions and tail calls).”…””}”(hhþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K hhÝh²hubeh}”(h]”Œoverview”ah ]”h"]”Œoverview”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒAPI”h]”hŒAPI”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´Kubhï)”}”(hŒøBPF flow dissector programs operate on an ``__sk_buff``. However, only the limited set of fields is allowed: ``data``, ``data_end`` and ``flow_keys``. ``flow_keys`` is ``struct bpf_flow_keys`` and contains flow dissector input and output arguments.”h]”(hŒ*BPF flow dissector programs operate on an ”…””}”(hj%h²hh³Nh´NubhŒliteral”“”)”}”(hŒ ``__sk_buff``”h]”hŒ __sk_buff”…””}”(hj/h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj%ubhŒ6. However, only the limited set of fields is allowed: ”…””}”(hj%h²hh³Nh´Nubj.)”}”(hŒ``data``”h]”hŒdata”…””}”(hjAh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj%ubhŒ, ”…””}”(hj%h²hh³Nh´Nubj.)”}”(hŒ ``data_end``”h]”hŒdata_end”…””}”(hjSh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj%ubhŒ and ”…””}”(hj%h²hh³Nh´Nubj.)”}”(hŒ ``flow_keys``”h]”hŒ flow_keys”…””}”(hjeh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj%ubhŒ. ”…””}”(hj%h²hh³Nh´Nubj.)”}”(hŒ ``flow_keys``”h]”hŒ flow_keys”…””}”(hjwh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj%ubhŒ is ”…””}”(hj%h²hh³Nh´Nubj.)”}”(hŒ``struct bpf_flow_keys``”h]”hŒstruct bpf_flow_keys”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj%ubhŒ8 and contains flow dissector input and output arguments.”…””}”(hj%h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khjh²hubhŒdefinition_list”“”)”}”(hhh]”hŒdefinition_list_item”“”)”}”(hŒèThe inputs are: * ``nhoff`` - initial offset of the networking header * ``thoff`` - initial offset of the transport header, initialized to nhoff * ``n_proto`` - L3 protocol type, parsed out of L2 header * ``flags`` - optional flags ”h]”(hŒterm”“”)”}”(hŒThe inputs are:”h]”hŒThe inputs are:”…””}”(hj®h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j¬h³hÇh´Khj¨ubhŒ definition”“”)”}”(hhh]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ3``nhoff`` - initial offset of the networking header”h]”hï)”}”(hjÊh]”(j.)”}”(hŒ ``nhoff``”h]”hŒnhoff”…””}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjÌubhŒ* - initial offset of the networking header”…””}”(hjÌh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KhjÈubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÃubjÇ)”}”(hŒH``thoff`` - initial offset of the transport header, initialized to nhoff”h]”hï)”}”(hjïh]”(j.)”}”(hŒ ``thoff``”h]”hŒthoff”…””}”(hjôh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjñubhŒ? - initial offset of the transport header, initialized to nhoff”…””}”(hjñh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khjíubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÃubjÇ)”}”(hŒ7``n_proto`` - L3 protocol type, parsed out of L2 header”h]”hï)”}”(hjh]”(j.)”}”(hŒ ``n_proto``”h]”hŒn_proto”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjubhŒ, - L3 protocol type, parsed out of L2 header”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÃubjÇ)”}”(hŒ``flags`` - optional flags ”h]”hï)”}”(hŒ``flags`` - optional flags”h]”(j.)”}”(hŒ ``flags``”h]”hŒflags”…””}”(hj?h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj;ubhŒ - optional flags”…””}”(hj;h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khj7ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÃubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ*”uh1jÁh³hÇh´Khj¾ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¼hj¨ubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¦h³hÇh´Khj£ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¡hjh²hh³Nh´Nubhï)”}”(hŒ¨Flow dissector BPF program should fill out the rest of the ``struct bpf_flow_keys`` fields. Input arguments ``nhoff/thoff/n_proto`` should be also adjusted accordingly.”h]”(hŒ;Flow dissector BPF program should fill out the rest of the ”…””}”(hjwh²hh³Nh´Nubj.)”}”(hŒ``struct bpf_flow_keys``”h]”hŒstruct bpf_flow_keys”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjwubhŒ fields. Input arguments ”…””}”(hjwh²hh³Nh´Nubj.)”}”(hŒ``nhoff/thoff/n_proto``”h]”hŒnhoff/thoff/n_proto”…””}”(hj‘h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjwubhŒ% should be also adjusted accordingly.”…””}”(hjwh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khjh²hubhï)”}”(hŒ}The return code of the BPF program is either BPF_OK to indicate successful dissection, or BPF_DROP to indicate parsing error.”h]”hŒ}The return code of the BPF program is either BPF_OK to indicate successful dissection, or BPF_DROP to indicate parsing error.”…””}”(hj©h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K#hjh²hubeh}”(h]”Œapi”ah ]”h"]”Œapi”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KubhÉ)”}”(hhh]”(hÎ)”}”(hŒ__sk_buff->data”h]”hŒ__sk_buff->data”…””}”(hjÂh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¿h²hh³hÇh´K'ubhï)”}”(hŒ\In the VLAN-less case, this is what the initial state of the BPF flow dissector looks like::”h]”hŒ[In the VLAN-less case, this is what the initial state of the BPF flow dissector looks like:”…””}”(hjÐh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K)hj¿h²hubhŒ literal_block”“”)”}”(hŒñ+------+------+------------+-----------+ | DMAC | SMAC | ETHER_TYPE | L3_HEADER | +------+------+------------+-----------+ ^ | +-- flow dissector starts here”h]”hŒñ+------+------+------------+-----------+ | DMAC | SMAC | ETHER_TYPE | L3_HEADER | +------+------+------------+-----------+ ^ | +-- flow dissector starts here”…””}”hjàsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jÞh³hÇh´K,hj¿h²hubjß)”}”(hŒzskb->data + flow_keys->nhoff point to the first byte of L3_HEADER flow_keys->thoff = nhoff flow_keys->n_proto = ETHER_TYPE”h]”hŒzskb->data + flow_keys->nhoff point to the first byte of L3_HEADER flow_keys->thoff = nhoff flow_keys->n_proto = ETHER_TYPE”…””}”hjîsbah}”(h]”h ]”h"]”h$]”h&]”Œforce”‰Œhighlight_args”}”hÅhÆŒlanguage”Œc”uh1jÞh³hÇh´K4hj¿h²hubhï)”}”(hŒLIn case of VLAN, flow dissector can be called with the two different states.”h]”hŒLIn case of VLAN, flow dissector can be called with the two different states.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K:hj¿h²hubhï)”}”(hŒPre-VLAN parsing::”h]”hŒPre-VLAN parsing:”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khj¿h²hubjß)”}”(hŒnskb->data + flow_keys->nhoff point the to first byte of TCI flow_keys->thoff = nhoff flow_keys->n_proto = TPID”h]”hŒnskb->data + flow_keys->nhoff point the to first byte of TCI flow_keys->thoff = nhoff flow_keys->n_proto = TPID”…””}”hj+sbah}”(h]”h ]”h"]”h$]”h&]”Œforce”‰Œhighlight_args”}”hÅhÆjÿjuh1jÞh³hÇh´KEhj¿h²hubhï)”}”(hŒ‚Please note that TPID can be 802.1AD and, hence, BPF program would have to parse VLAN information twice for double tagged packets.”h]”hŒ‚Please note that TPID can be 802.1AD and, hence, BPF program would have to parse VLAN information twice for double tagged packets.”…””}”(hj<h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KKhj¿h²hubhï)”}”(hŒPost-VLAN parsing::”h]”hŒPost-VLAN parsing:”…””}”(hjJh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KOhj¿h²hubjß)”}”(hX9+------+------+------+-----+-----------+-----------+ | DMAC | SMAC | TPID | TCI |ETHER_TYPE | L3_HEADER | +------+------+------+-----+-----------+-----------+ ^ | +-- flow dissector starts here”h]”hX9+------+------+------+-----+-----------+-----------+ | DMAC | SMAC | TPID | TCI |ETHER_TYPE | L3_HEADER | +------+------+------+-----+-----------+-----------+ ^ | +-- flow dissector starts here”…””}”hjXsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jÞh³hÇh´KQhj¿h²hubjß)”}”(hŒzskb->data + flow_keys->nhoff point the to first byte of L3_HEADER flow_keys->thoff = nhoff flow_keys->n_proto = ETHER_TYPE”h]”hŒzskb->data + flow_keys->nhoff point the to first byte of L3_HEADER flow_keys->thoff = nhoff flow_keys->n_proto = ETHER_TYPE”…””}”hjfsbah}”(h]”h ]”h"]”h$]”h&]”Œforce”‰Œhighlight_args”}”hÅhÆjÿjuh1jÞh³hÇh´KXhj¿h²hubhï)”}”(hŒIn this case VLAN information has been processed before the flow dissector and BPF flow dissector is not required to handle it.”h]”hŒIn this case VLAN information has been processed before the flow dissector and BPF flow dissector is not required to handle it.”…””}”(hjwh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K^hj¿h²hubhï)”}”(hX=The takeaway here is as follows: BPF flow dissector program can be called with the optional VLAN header and should gracefully handle both cases: when single or double VLAN is present and when it is not present. The same program can be called for both cases and would have to be written carefully to handle both cases.”h]”hX=The takeaway here is as follows: BPF flow dissector program can be called with the optional VLAN header and should gracefully handle both cases: when single or double VLAN is present and when it is not present. The same program can be called for both cases and would have to be written carefully to handle both cases.”…””}”(hj…h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Kbhj¿h²hubeh}”(h]”Œ sk-buff-data”ah ]”h"]”Œ__sk_buff->data”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K'ubhÉ)”}”(hhh]”(hÎ)”}”(hŒFlags”h]”hŒFlags”…””}”(hjžh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj›h²hh³hÇh´Kjubhï)”}”(hŒM``flow_keys->flags`` might contain optional input flags that work as follows:”h]”(j.)”}”(hŒ``flow_keys->flags``”h]”hŒflow_keys->flags”…””}”(hj°h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj¬ubhŒ9 might contain optional input flags that work as follows:”…””}”(hj¬h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Klhj›h²hubjÂ)”}”(hhh]”(jÇ)”}”(hX!``BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG`` - tells BPF flow dissector to continue parsing first fragment; the default expected behavior is that flow dissector returns as soon as it finds out that the packet is fragmented; used by ``eth_get_headlen`` to estimate length of all headers for GRO.”h]”hï)”}”(hX!``BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG`` - tells BPF flow dissector to continue parsing first fragment; the default expected behavior is that flow dissector returns as soon as it finds out that the packet is fragmented; used by ``eth_get_headlen`` to estimate length of all headers for GRO.”h]”(j.)”}”(hŒ'``BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG``”h]”hŒ#BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG”…””}”(hjÓh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjÏubhŒ¼ - tells BPF flow dissector to continue parsing first fragment; the default expected behavior is that flow dissector returns as soon as it finds out that the packet is fragmented; used by ”…””}”(hjÏh²hh³Nh´Nubj.)”}”(hŒ``eth_get_headlen``”h]”hŒeth_get_headlen”…””}”(hjåh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjÏubhŒ+ to estimate length of all headers for GRO.”…””}”(hjÏh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´KnhjËubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÈh²hh³hÇh´NubjÇ)”}”(hŒ«``BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL`` - tells BPF flow dissector to stop parsing as soon as it reaches IPv6 flow label; used by ``___skb_get_hash`` to get flow hash.”h]”hï)”}”(hŒ«``BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL`` - tells BPF flow dissector to stop parsing as soon as it reaches IPv6 flow label; used by ``___skb_get_hash`` to get flow hash.”h]”(j.)”}”(hŒ+``BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL``”h]”hŒ'BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjubhŒ[ - tells BPF flow dissector to stop parsing as soon as it reaches IPv6 flow label; used by ”…””}”(hjh²hh³Nh´Nubj.)”}”(hŒ``___skb_get_hash``”h]”hŒ___skb_get_hash”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjubhŒ to get flow hash.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Krhjubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÈh²hh³hÇh´NubjÇ)”}”(hŒŸ``BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP`` - tells BPF flow dissector to stop parsing as soon as it reaches encapsulated headers; used by routing infrastructure. ”h]”hï)”}”(hŒ``BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP`` - tells BPF flow dissector to stop parsing as soon as it reaches encapsulated headers; used by routing infrastructure.”h]”(j.)”}”(hŒ&``BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP``”h]”hŒ"BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP”…””}”(hjCh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj?ubhŒw - tells BPF flow dissector to stop parsing as soon as it reaches encapsulated headers; used by routing infrastructure.”…””}”(hj?h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Kuhj;ubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÈh²hh³hÇh´Nubeh}”(h]”h ]”h"]”h$]”h&]”jcjduh1jÁh³hÇh´Knhj›h²hubeh}”(h]”Œflags”ah ]”h"]”Œflags”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KjubhÉ)”}”(hhh]”(hÎ)”}”(hŒReference Implementation”h]”hŒReference Implementation”…””}”(hjrh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjoh²hh³hÇh´K{ubhï)”}”(hŒâSee ``tools/testing/selftests/bpf/progs/bpf_flow.c`` for the reference implementation and ``tools/testing/selftests/bpf/flow_dissector_load.[hc]`` for the loader. bpftool can be used to load BPF flow dissector program as well.”h]”(hŒSee ”…””}”(hj€h²hh³Nh´Nubj.)”}”(hŒ0``tools/testing/selftests/bpf/progs/bpf_flow.c``”h]”hŒ,tools/testing/selftests/bpf/progs/bpf_flow.c”…””}”(hjˆh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj€ubhŒ& for the reference implementation and ”…””}”(hj€h²hh³Nh´Nubj.)”}”(hŒ8``tools/testing/selftests/bpf/flow_dissector_load.[hc]``”h]”hŒ4tools/testing/selftests/bpf/flow_dissector_load.[hc]”…””}”(hjšh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj€ubhŒP for the loader. bpftool can be used to load BPF flow dissector program as well.”…””}”(hj€h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K}hjoh²hubj¢)”}”(hhh]”j§)”}”(hXThe reference implementation is organized as follows: * ``jmp_table`` map that contains sub-programs for each supported L3 protocol * ``_dissect`` routine - entry point; it does input ``n_proto`` parsing and does ``bpf_tail_call`` to the appropriate L3 handler ”h]”(j­)”}”(hŒ5The reference implementation is organized as follows:”h]”hŒ5The reference implementation is organized as follows:”…””}”(hj¹h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j¬h³hÇh´K„hjµubj½)”}”(hhh]”jÂ)”}”(hhh]”(jÇ)”}”(hŒK``jmp_table`` map that contains sub-programs for each supported L3 protocol”h]”hï)”}”(hjÏh]”(j.)”}”(hŒ ``jmp_table``”h]”hŒ jmp_table”…””}”(hjÔh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjÑubhŒ> map that contains sub-programs for each supported L3 protocol”…””}”(hjÑh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K‚hjÍubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÊubjÇ)”}”(hŒ``_dissect`` routine - entry point; it does input ``n_proto`` parsing and does ``bpf_tail_call`` to the appropriate L3 handler ”h]”hï)”}”(hŒ~``_dissect`` routine - entry point; it does input ``n_proto`` parsing and does ``bpf_tail_call`` to the appropriate L3 handler”h]”(j.)”}”(hŒ ``_dissect``”h]”hŒ_dissect”…””}”(hjúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjöubhŒ& routine - entry point; it does input ”…””}”(hjöh²hh³Nh´Nubj.)”}”(hŒ ``n_proto``”h]”hŒn_proto”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjöubhŒ parsing and does ”…””}”(hjöh²hh³Nh´Nubj.)”}”(hŒ``bpf_tail_call``”h]”hŒ bpf_tail_call”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hjöubhŒ to the appropriate L3 handler”…””}”(hjöh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Kƒhjòubah}”(h]”h ]”h"]”h$]”h&]”uh1jÆhjÊubeh}”(h]”h ]”h"]”h$]”h&]”jcjduh1jÁh³hÇh´K‚hjÇubah}”(h]”h ]”h"]”h$]”h&]”uh1j¼hjµubeh}”(h]”h ]”h"]”h$]”h&]”uh1j¦h³hÇh´K„hj²ubah}”(h]”h ]”h"]”h$]”h&]”uh1j¡hjoh²hh³Nh´Nubhï)”}”(hŒŸSince BPF at this point doesn't support looping (or any jumping back), jmp_table is used instead to handle multiple levels of encapsulation (and IPv6 options).”h]”hŒ¡Since BPF at this point doesn’t support looping (or any jumping back), jmp_table is used instead to handle multiple levels of encapsulation (and IPv6 options).”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K†hjoh²hubeh}”(h]”Œreference-implementation”ah ]”h"]”Œreference implementation”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K{ubhÉ)”}”(hhh]”(hÎ)”}”(hŒCurrent Limitations”h]”hŒCurrent Limitations”…””}”(hjmh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjjh²hh³hÇh´KŒubhï)”}”(hX4BPF flow dissector doesn't support exporting all the metadata that in-kernel C-based implementation can export. Notable example is single VLAN (802.1Q) and double VLAN (802.1AD) tags. Please refer to the ``struct bpf_flow_keys`` for a set of information that's currently can be exported from the BPF context.”h]”(hŒÎBPF flow dissector doesn’t support exporting all the metadata that in-kernel C-based implementation can export. Notable example is single VLAN (802.1Q) and double VLAN (802.1AD) tags. Please refer to the ”…””}”(hj{h²hh³Nh´Nubj.)”}”(hŒ``struct bpf_flow_keys``”h]”hŒstruct bpf_flow_keys”…””}”(hjƒh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j-hj{ubhŒR for a set of information that’s currently can be exported from the BPF context.”…””}”(hj{h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´Khjjh²hubhï)”}”(hŒ“When BPF flow dissector is attached to the root network namespace (machine-wide policy), users can't override it in their child network namespaces.”h]”hŒ•When BPF flow dissector is attached to the root network namespace (machine-wide policy), users can’t override it in their child network namespaces.”…””}”(hj›h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hîh³hÇh´K’hjjh²hubeh}”(h]”Œcurrent-limitations”ah ]”h"]”Œcurrent limitations”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KŒubeh}”(h]”Œbpf-prog-type-flow-dissector”ah ]”h"]”Œbpf_prog_type_flow_dissector”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”jÜŒ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”}”(j¶j³jjj¼j¹j˜j•jljijgjdj®j«uŒ nametypes”}”(j¶‰j‰j¼‰j˜‰jl‰jg‰j®‰uh}”(j³hÊjhÝj¹jj•j¿jij›jdjoj«jjuŒ 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.