mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
86878f14d7
Add "fixed" part of the user space Netlink Spec-based library. This will get linked with the protocol implementations to form a full API. Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
160 lines
5.2 KiB
ReStructuredText
160 lines
5.2 KiB
ReStructuredText
.. SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
=====================================
|
|
Using Netlink protocol specifications
|
|
=====================================
|
|
|
|
This document is a quick starting guide for using Netlink protocol
|
|
specifications. For more detailed description of the specs see :doc:`specs`.
|
|
|
|
Simple CLI
|
|
==========
|
|
|
|
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. Only Generic Netlink is supported.
|
|
|
|
The tool is located at ``tools/net/ynl/cli.py``. It accepts
|
|
a handul of arguments, the most important ones are:
|
|
|
|
- ``--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``
|
|
|
|
YAML specs can be found under ``Documentation/netlink/specs/``.
|
|
|
|
Example use::
|
|
|
|
$ ./tools/net/ynl/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}
|
|
|
|
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.
|
|
|
|
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``.
|
|
|
|
Generating kernel code
|
|
======================
|
|
|
|
``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.
|
|
|
|
By default code is re-generated only if spec is newer than the source,
|
|
to force regeneration use ``-f``.
|
|
|
|
``ynl-regen.sh`` searches for ``YNL-GEN`` 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 ``fou_nl.c`` kernel source contains::
|
|
|
|
/* Documentation/netlink/specs/fou.yaml */
|
|
/* YNL-GEN kernel source */
|
|
|
|
``ynl-regen.sh`` will find this marker and replace the file with
|
|
kernel source based on fou.yaml.
|
|
|
|
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.
|
|
|
|
The code generation itself is performed by ``tools/net/ynl/ynl-gen-c.py``
|
|
but it takes a few arguments so calling it directly for each file
|
|
quickly becomes tedious.
|
|
|
|
YNL lib
|
|
=======
|
|
|
|
``tools/net/ynl/lib/`` contains an implementation of a C library
|
|
(based on libmnl) which integrates with code generated by
|
|
``tools/net/ynl/ynl-gen-c.py`` to create easy to use netlink wrappers.
|
|
|
|
YNL basics
|
|
----------
|
|
|
|
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).
|
|
|
|
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.
|
|
|
|
YNL requests
|
|
------------
|
|
|
|
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):
|
|
|
|
.. code-block:: c
|
|
|
|
// 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);
|
|
|
|
YNL dumps
|
|
---------
|
|
|
|
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.
|
|
|
|
YNL notifications
|
|
-----------------
|
|
|
|
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.
|
|
|
|
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``.
|
|
|
|
Notifications 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.
|