The Linux Kernel Logo
  • Development process
  • Submitting patches
  • Code of conduct
  • Maintainer handbook
  • All development-process docs
  • Core API
  • Driver APIs
  • Subsystems
  • Locking
  • Licensing rules
  • Writing documentation
  • Development tools
  • Testing guide
  • Hacking guide
  • Tracing
  • Fault injection
  • Livepatching
  • Rust
  • Administration
  • Build system
  • Reporting issues
  • Userspace tools
  • Userspace API
    • System calls
    • Security-related interfaces
    • Devices and I/O
    • Everything else
      • Linux-specific ELF idiosyncrasies
      • Netlink Handbook
        • Introduction to Netlink
        • Using Netlink protocol specifications
          • Simple CLI
          • Generating kernel code
          • YNL lib
            • YNL basics
            • YNL requests
            • YNL dumps
            • YNL notifications
        • Netlink protocol specifications (in YAML)
        • Netlink spec C code generation
        • Netlink specification support for legacy Generic Netlink families
        • Netlink specification support for raw Netlink families
      • Platform Profile Selection (e.g. /sys/firmware/acpi/platform_profile)
      • VDUSE - “vDPA Device in Userspace”
      • futex2
      • Perf ring buffer
      • NT synchronization primitive driver
  • Firmware
  • Firmware and Devicetree
  • CPU architectures
  • Unsorted documentation
  • Translations
The Linux Kernel
  • The Linux kernel user-space API guide
  • Netlink Handbook
  • Using Netlink protocol specifications
  • View page source

Using Netlink protocol specifications¶

This document is a quick starting guide for using Netlink protocol specifications. For more detailed description of the specs see Netlink protocol specifications (in YAML).

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/pyynl/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/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}

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/pyynl/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/pyynl/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):

// 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.

Previous Next

© Copyright The kernel development community.

Built with Sphinx using a theme provided by Read the Docs.