€•W\Œ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”Œ5/translations/zh_CN/userspace-api/netlink/intro-specs”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ5/translations/zh_TW/userspace-api/netlink/intro-specs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ5/translations/it_IT/userspace-api/netlink/intro-specs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ5/translations/ja_JP/userspace-api/netlink/intro-specs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ5/translations/ko_KR/userspace-api/netlink/intro-specs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒPortuguese (Brazilian)”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ5/translations/pt_BR/userspace-api/netlink/intro-specs”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh–sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ5/translations/sp_SP/userspace-api/netlink/intro-specs”Œ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: BSD-3-Clause”h]”hŒ%SPDX-License-Identifier: BSD-3-Clause”…””}”hh·sbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hµhhh²hh³ŒO/var/lib/git/docbuild/linux/Documentation/userspace-api/netlink/intro-specs.rst”h´KubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒ%Using Netlink protocol specifications”h]”hŒ%Using Netlink protocol specifications”…””}”(hhÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhhÊh²hh³hÇh´KubhŒ paragraph”“”)”}”(hŒThis document is a quick starting guide for using Netlink protocol specifications. For more detailed description of the specs see :doc:`specs`.”h]”(hŒ‚This document is a quick starting guide for using Netlink protocol specifications. For more detailed description of the specs see ”…””}”(hhßh²hh³Nh´Nubh)”}”(hŒ :doc:`specs`”h]”hŒinline”“”)”}”(hhéh]”hŒspecs”…””}”(hhíh²hh³Nh´Nubah}”(h]”h ]”(Œxref”Œstd”Œstd-doc”eh"]”h$]”h&]”uh1hëhhçubah}”(h]”h ]”h"]”h$]”h&]”Œrefdoc”Œ!userspace-api/netlink/intro-specs”Œ refdomain”høŒreftype”Œdoc”Œ refexplicit”‰Œrefwarn”ˆŒ reftarget”Œspecs”uh1hh³hÇh´KhhßubhŒ.”…””}”(hhßh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhhÊh²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ Simple CLI”h]”hŒ Simple CLI”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjh²hh³hÇh´K ubhÞ)”}”(hŒÌKernel comes with a simple CLI tool which should be useful when developing Netlink related code. The tool is implemented in Python and can use a YAML specification to issue Netlink requests to the kernel.”h]”hŒÌKernel comes with a simple CLI tool which should be useful when developing Netlink related code. The tool is implemented in Python and can use a YAML specification to issue Netlink requests to the kernel.”…””}”(hj'h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K hjh²hubhÞ)”}”(hŒvThe tool is located at ``tools/net/ynl/pyynl/cli.py``. It accepts a handful of arguments, the most important ones are:”h]”(hŒThe tool is located at ”…””}”(hj5h²hh³Nh´NubhŒliteral”“”)”}”(hŒ``tools/net/ynl/pyynl/cli.py``”h]”hŒtools/net/ynl/pyynl/cli.py”…””}”(hj?h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj5ubhŒA. It accepts a handful of arguments, the most important ones are:”…””}”(hj5h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubhŒ block_quote”“”)”}”(hŒÞ- ``--spec`` - point to the spec file - ``--do $name`` / ``--dump $name`` - issue request ``$name`` - ``--json $attrs`` - provide attributes for the request - ``--subscribe $group`` - receive notifications from ``$group`` ”h]”hŒ bullet_list”“”)”}”(hhh]”(hŒ list_item”“”)”}”(hŒ#``--spec`` - point to the spec file”h]”hÞ)”}”(hjfh]”(j>)”}”(hŒ ``--spec``”h]”hŒ--spec”…””}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjhubhŒ - point to the spec file”…””}”(hjhh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjdubah}”(h]”h ]”h"]”h$]”h&]”uh1jbhj_ubjc)”}”(hŒ;``--do $name`` / ``--dump $name`` - issue request ``$name``”h]”hÞ)”}”(hj‹h]”(j>)”}”(hŒ``--do $name``”h]”hŒ --do $name”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubhŒ / ”…””}”(hjh²hh³Nh´Nubj>)”}”(hŒ``--dump $name``”h]”hŒ --dump $name”…””}”(hj¢h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubhŒ - issue request ”…””}”(hjh²hh³Nh´Nubj>)”}”(hŒ ``$name``”h]”hŒ$name”…””}”(hj´h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khj‰ubah}”(h]”h ]”h"]”h$]”h&]”uh1jbhj_ubjc)”}”(hŒ6``--json $attrs`` - provide attributes for the request”h]”hÞ)”}”(hjÐh]”(j>)”}”(hŒ``--json $attrs``”h]”hŒ --json $attrs”…””}”(hjÕh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjÒubhŒ% - provide attributes for the request”…””}”(hjÒh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KhjÎubah}”(h]”h ]”h"]”h$]”h&]”uh1jbhj_ubjc)”}”(hŒ?``--subscribe $group`` - receive notifications from ``$group`` ”h]”hÞ)”}”(hŒ>``--subscribe $group`` - receive notifications from ``$group``”h]”(j>)”}”(hŒ``--subscribe $group``”h]”hŒ--subscribe $group”…””}”(hjûh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj÷ubhŒ - receive notifications from ”…””}”(hj÷h²hh³Nh´Nubj>)”}”(hŒ ``$group``”h]”hŒ$group”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj÷ubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjóubah}”(h]”h ]”h"]”h$]”h&]”uh1jbhj_ubeh}”(h]”h ]”h"]”h$]”h&]”Œbullet”Œ-”uh1j]h³hÇh´KhjYubah}”(h]”h ]”h"]”h$]”h&]”uh1jWh³hÇh´Khjh²hubhÞ)”}”(hŒ?YAML specs can be found under ``Documentation/netlink/specs/``.”h]”(hŒYAML specs can be found under ”…””}”(hj5h²hh³Nh´Nubj>)”}”(hŒ ``Documentation/netlink/specs/``”h]”hŒDocumentation/netlink/specs/”…””}”(hj=h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj5ubhŒ.”…””}”(hj5h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubhÞ)”}”(hŒ Example use::”h]”hŒ Example use:”…””}”(hjUh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Khjh²hubhŒ literal_block”“”)”}”(hXY$ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/ethtool.yaml \ --do rings-get \ --json '{"header":{"dev-index": 18}}' {'header': {'dev-index': 18, 'dev-name': 'eni1np1'}, 'rx': 0, 'rx-jumbo': 0, 'rx-jumbo-max': 4096, 'rx-max': 4096, 'rx-mini': 0, 'rx-mini-max': 4096, 'tx': 0, 'tx-max': 4096, 'tx-push': 0}”h]”hXY$ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/ethtool.yaml \ --do rings-get \ --json '{"header":{"dev-index": 18}}' {'header': {'dev-index': 18, 'dev-name': 'eni1np1'}, 'rx': 0, 'rx-jumbo': 0, 'rx-jumbo-max': 4096, 'rx-max': 4096, 'rx-mini': 0, 'rx-mini-max': 4096, 'tx': 0, 'tx-max': 4096, 'tx-push': 0}”…””}”hjesbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jch³hÇh´Khjh²hubhÞ)”}”(hŒøThe input arguments are parsed as JSON, while the output is only Python-pretty-printed. This is because some Netlink types can't be expressed as JSON directly. If such attributes are needed in the input some hacking of the script will be necessary.”h]”hŒúThe input arguments are parsed as JSON, while the output is only Python-pretty-printed. This is because some Netlink types can’t be expressed as JSON directly. If such attributes are needed in the input some hacking of the script will be necessary.”…””}”(hjsh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K,hjh²hubhÞ)”}”(hŒ—The spec and Netlink internals are factored out as a standalone library - it should be easy to write Python tools / tests reusing code from ``cli.py``.”h]”(hŒŒThe spec and Netlink internals are factored out as a standalone library - it should be easy to write Python tools / tests reusing code from ”…””}”(hjh²hh³Nh´Nubj>)”}”(hŒ ``cli.py``”h]”hŒcli.py”…””}”(hj‰h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubhŒ.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K1hjh²hubeh}”(h]”Œ simple-cli”ah ]”h"]”Œ simple cli”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K ubhÉ)”}”(hhh]”(hÎ)”}”(hŒGenerating kernel code”h]”hŒGenerating kernel code”…””}”(hj¬h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj©h²hh³hÇh´K6ubhÞ)”}”(hŒ½``tools/net/ynl/ynl-regen.sh`` scans the kernel tree in search of auto-generated files which need to be updated. Using this tool is the easiest way to generate / update auto-generated code.”h]”(j>)”}”(hŒ``tools/net/ynl/ynl-regen.sh``”h]”hŒtools/net/ynl/ynl-regen.sh”…””}”(hj¾h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjºubhŒŸ scans the kernel tree in search of auto-generated files which need to be updated. Using this tool is the easiest way to generate / update auto-generated code.”…””}”(hjºh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K8hj©h²hubhÞ)”}”(hŒhBy default code is re-generated only if spec is newer than the source, to force regeneration use ``-f``.”h]”(hŒaBy default code is re-generated only if spec is newer than the source, to force regeneration use ”…””}”(hjÖh²hh³Nh´Nubj>)”}”(hŒ``-f``”h]”hŒ-f”…””}”(hjÞh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjÖubhŒ.”…””}”(hjÖh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K)”}”(hŒ``ynl-regen.sh``”h]”hŒ ynl-regen.sh”…””}”(hjúh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjöubhŒ searches for ”…””}”(hjöh²hh³Nh´Nubj>)”}”(hŒ ``YNL-GEN``”h]”hŒYNL-GEN”…””}”(hj h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjöubhŒ€ in the contents of files (note that it only scans files in the git index, that is only files tracked by git!) For instance the ”…””}”(hjöh²hh³Nh´Nubj>)”}”(hŒ ``fou_nl.c``”h]”hŒfou_nl.c”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjöubhŒ kernel source contains:”…””}”(hjöh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K?hj©h²hubjd)”}”(hŒI/* Documentation/netlink/specs/fou.yaml */ /* YNL-GEN kernel source */”h]”hŒI/* Documentation/netlink/specs/fou.yaml */ /* YNL-GEN kernel source */”…””}”hj6sbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆuh1jch³hÇh´KChj©h²hubhÞ)”}”(hŒa``ynl-regen.sh`` will find this marker and replace the file with kernel source based on fou.yaml.”h]”(j>)”}”(hŒ``ynl-regen.sh``”h]”hŒ ynl-regen.sh”…””}”(hjHh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjDubhŒQ will find this marker and replace the file with kernel source based on fou.yaml.”…””}”(hjDh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KFhj©h²hubhÞ)”}”(hŒÖThe simplest way to generate a new file based on a spec is to add the two marker lines like above to a file, add that file to git, and run the regeneration tool. Grep the tree for ``YNL-GEN`` to see other examples.”h]”(hŒ´The simplest way to generate a new file based on a spec is to add the two marker lines like above to a file, add that file to git, and run the regeneration tool. Grep the tree for ”…””}”(hj`h²hh³Nh´Nubj>)”}”(hŒ ``YNL-GEN``”h]”hŒYNL-GEN”…””}”(hjhh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj`ubhŒ to see other examples.”…””}”(hj`h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KIhj©h²hubhÞ)”}”(hŒªThe code generation itself is performed by ``tools/net/ynl/pyynl/ynl_gen_c.py`` but it takes a few arguments so calling it directly for each file quickly becomes tedious.”h]”(hŒ+The code generation itself is performed by ”…””}”(hj€h²hh³Nh´Nubj>)”}”(hŒ$``tools/net/ynl/pyynl/ynl_gen_c.py``”h]”hŒ tools/net/ynl/pyynl/ynl_gen_c.py”…””}”(hjˆh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj€ubhŒ[ but it takes a few arguments so calling it directly for each file quickly becomes tedious.”…””}”(hj€h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KNhj©h²hubeh}”(h]”Œgenerating-kernel-code”ah ]”h"]”Œgenerating kernel code”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´K6ubhÉ)”}”(hhh]”(hÎ)”}”(hŒYNL lib”h]”hŒYNL lib”…””}”(hj«h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¨h²hh³hÇh´KSubhÞ)”}”(hŒÇ``tools/net/ynl/lib/`` contains an implementation of a C library (based on libmnl) which integrates with code generated by ``tools/net/ynl/pyynl/ynl_gen_c.py`` to create easy to use netlink wrappers.”h]”(j>)”}”(hŒ``tools/net/ynl/lib/``”h]”hŒtools/net/ynl/lib/”…””}”(hj½h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj¹ubhŒe contains an implementation of a C library (based on libmnl) which integrates with code generated by ”…””}”(hj¹h²hh³Nh´Nubj>)”}”(hŒ$``tools/net/ynl/pyynl/ynl_gen_c.py``”h]”hŒ tools/net/ynl/pyynl/ynl_gen_c.py”…””}”(hjÏh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hj¹ubhŒ( to create easy to use netlink wrappers.”…””}”(hj¹h²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´KUhj¨h²hubhÉ)”}”(hhh]”(hÎ)”}”(hŒ YNL basics”h]”hŒ YNL basics”…””}”(hjêh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjçh²hh³hÇh´KZubhÞ)”}”(hŒ¢The YNL library consists of two parts - the generic code (functions prefix by ``ynl_``) and per-family auto-generated code (prefixed with the name of the family).”h]”(hŒNThe YNL library consists of two parts - the generic code (functions prefix by ”…””}”(hjøh²hh³Nh´Nubj>)”}”(hŒ``ynl_``”h]”hŒynl_”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjøubhŒL) and per-family auto-generated code (prefixed with the name of the family).”…””}”(hjøh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K\hjçh²hubhÞ)”}”(hŒ§To create a YNL socket call ynl_sock_create() passing the family struct (family structs are exported by the auto-generated code). ynl_sock_destroy() closes the socket.”h]”hŒ§To create a YNL socket call ynl_sock_create() passing the family struct (family structs are exported by the auto-generated code). ynl_sock_destroy() closes the socket.”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K`hjçh²hubeh}”(h]”Œ ynl-basics”ah ]”h"]”Œ ynl basics”ah$]”h&]”uh1hÈhj¨h²hh³hÇh´KZubhÉ)”}”(hhh]”(hÎ)”}”(hŒ YNL requests”h]”hŒ YNL requests”…””}”(hj1h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj.h²hh³hÇh´KeubhÞ)”}”(hŒ´Steps for issuing YNL requests are best explained on an example. All the functions and types in this example come from the auto-generated code (for the netdev family in this case):”h]”hŒ´Steps for issuing YNL requests are best explained on an example. All the functions and types in this example come from the auto-generated code (for the netdev family in this case):”…””}”(hj?h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´Kghj.h²hubjd)”}”(hXg// 0. Request and response pointers struct netdev_dev_get_req *req; struct netdev_dev_get_rsp *d; // 1. Allocate a request req = netdev_dev_get_req_alloc(); // 2. Set request parameters (as needed) netdev_dev_get_req_set_ifindex(req, ifindex); // 3. Issues the request d = netdev_dev_get(ys, req); // 4. Free the request arguments netdev_dev_get_req_free(req); // 5. Error check (the return value from step 3) if (!d) { // 6. Print the YNL-generated error fprintf(stderr, "YNL: %s\n", ys->err.msg); return -1; } // ... do stuff with the response @d // 7. Free response netdev_dev_get_rsp_free(d);”h]”hXg// 0. Request and response pointers struct netdev_dev_get_req *req; struct netdev_dev_get_rsp *d; // 1. Allocate a request req = netdev_dev_get_req_alloc(); // 2. Set request parameters (as needed) netdev_dev_get_req_set_ifindex(req, ifindex); // 3. Issues the request d = netdev_dev_get(ys, req); // 4. Free the request arguments netdev_dev_get_req_free(req); // 5. Error check (the return value from step 3) if (!d) { // 6. Print the YNL-generated error fprintf(stderr, "YNL: %s\n", ys->err.msg); return -1; } // ... do stuff with the response @d // 7. Free response netdev_dev_get_rsp_free(d);”…””}”hjMsbah}”(h]”h ]”h"]”h$]”h&]”hÅhÆŒforce”‰Œlanguage”Œc”Œhighlight_args”}”uh1jch³hÇh´Kkhj.h²hubeh}”(h]”Œ ynl-requests”ah ]”h"]”Œ ynl requests”ah$]”h&]”uh1hÈhj¨h²hh³hÇh´KeubhÉ)”}”(hhh]”(hÎ)”}”(hŒ YNL dumps”h]”hŒ YNL dumps”…””}”(hjkh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhjhh²hh³hÇh´K‡ubhÞ)”}”(hŒ½Performing dumps follows similar pattern as requests. Dumps return a list of objects terminated by a special marker, or NULL on error. Use ``ynl_dump_foreach()`` to iterate over the result.”h]”(hŒ‹Performing dumps follows similar pattern as requests. Dumps return a list of objects terminated by a special marker, or NULL on error. Use ”…””}”(hjyh²hh³Nh´Nubj>)”}”(hŒ``ynl_dump_foreach()``”h]”hŒynl_dump_foreach()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjyubhŒ to iterate over the result.”…””}”(hjyh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K‰hjhh²hubeh}”(h]”Œ ynl-dumps”ah ]”h"]”Œ ynl dumps”ah$]”h&]”uh1hÈhj¨h²hh³hÇh´K‡ubhÉ)”}”(hhh]”(hÎ)”}”(hŒYNL notifications”h]”hŒYNL notifications”…””}”(hj¤h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÍhj¡h²hh³hÇh´KubhÞ)”}”(hŒÃYNL lib supports using the same socket for notifications and requests. In case notifications arrive during processing of a request they are queued internally and can be retrieved at a later time.”h]”hŒÃYNL lib supports using the same socket for notifications and requests. In case notifications arrive during processing of a request they are queued internally and can be retrieved at a later time.”…””}”(hj²h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K‘hj¡h²hubhÞ)”}”(hŒÿTo subscribed to notifications use ``ynl_subscribe()``. The notifications have to be read out from the socket, ``ynl_socket_get_fd()`` returns the underlying socket fd which can be plugged into appropriate asynchronous IO API like ``poll``, or ``select``.”h]”(hŒ#To subscribed to notifications use ”…””}”(hjÀh²hh³Nh´Nubj>)”}”(hŒ``ynl_subscribe()``”h]”hŒynl_subscribe()”…””}”(hjÈh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjÀubhŒ9. The notifications have to be read out from the socket, ”…””}”(hjÀh²hh³Nh´Nubj>)”}”(hŒ``ynl_socket_get_fd()``”h]”hŒynl_socket_get_fd()”…””}”(hjÚh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjÀubhŒa returns the underlying socket fd which can be plugged into appropriate asynchronous IO API like ”…””}”(hjÀh²hh³Nh´Nubj>)”}”(hŒ``poll``”h]”hŒpoll”…””}”(hjìh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjÀubhŒ, or ”…””}”(hjÀh²hh³Nh´Nubj>)”}”(hŒ ``select``”h]”hŒselect”…””}”(hjþh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjÀubhŒ.”…””}”(hjÀh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K•hj¡h²hubhÞ)”}”(hX8Notifications can be retrieved using ``ynl_ntf_dequeue()`` and have to be freed using ``ynl_ntf_free()``. Since we don't know the notification type upfront the notifications are returned as ``struct ynl_ntf_base_type *`` and user is expected to cast them to the appropriate full type based on the ``cmd`` member.”h]”(hŒ%Notifications can be retrieved using ”…””}”(hjh²hh³Nh´Nubj>)”}”(hŒ``ynl_ntf_dequeue()``”h]”hŒynl_ntf_dequeue()”…””}”(hjh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubhŒ and have to be freed using ”…””}”(hjh²hh³Nh´Nubj>)”}”(hŒ``ynl_ntf_free()``”h]”hŒynl_ntf_free()”…””}”(hj0h²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubhŒX. Since we don’t know the notification type upfront the notifications are returned as ”…””}”(hjh²hh³Nh´Nubj>)”}”(hŒ``struct ynl_ntf_base_type *``”h]”hŒstruct ynl_ntf_base_type *”…””}”(hjBh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubhŒM and user is expected to cast them to the appropriate full type based on the ”…””}”(hjh²hh³Nh´Nubj>)”}”(hŒ``cmd``”h]”hŒcmd”…””}”(hjTh²hh³Nh´Nubah}”(h]”h ]”h"]”h$]”h&]”uh1j=hjubhŒ member.”…””}”(hjh²hh³Nh´Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1hÝh³hÇh´K›hj¡h²hubeh}”(h]”Œynl-notifications”ah ]”h"]”Œynl notifications”ah$]”h&]”uh1hÈhj¨h²hh³hÇh´Kubeh}”(h]”Œynl-lib”ah ]”h"]”Œynl lib”ah$]”h&]”uh1hÈhhÊh²hh³hÇh´KSubeh}”(h]”Œ%using-netlink-protocol-specifications”ah ]”h"]”Œ%using netlink protocol specifications”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”}”(jj~j¦j£j¥j¢jyjvj+j(jejbjžj›jqjnuŒ nametypes”}”(j‰j¦‰j¥‰jy‰j+‰je‰jž‰jq‰uh}”(j~hÊj£jj¢j©jvj¨j(jçjbj.j›jhjnj¡uŒ 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.