1.. SPDX-License-Identifier: BSD-3-Clause
2
3=================================================================
4Netlink specification support for legacy Generic Netlink families
5=================================================================
6
7This document describes the many additional quirks and properties
8required to describe older Generic Netlink families which form
9the ``genetlink-legacy`` protocol level.
10
11The spec is a work in progress, some of the quirks are just documented
12for future reference.
13
14Specification (defined)
15=======================
16
17Attribute type nests
18--------------------
19
20New Netlink families should use ``multi-attr`` to define arrays.
21Older families (e.g. ``genetlink`` control family) attempted to
22define array types reusing attribute type to carry information.
23
24For reference the ``multi-attr`` array may look like this::
25
26  [ARRAY-ATTR]
27    [INDEX (optionally)]
28    [MEMBER1]
29    [MEMBER2]
30  [SOME-OTHER-ATTR]
31  [ARRAY-ATTR]
32    [INDEX (optionally)]
33    [MEMBER1]
34    [MEMBER2]
35
36where ``ARRAY-ATTR`` is the array entry type.
37
38array-nest
39~~~~~~~~~~
40
41``array-nest`` creates the following structure::
42
43  [SOME-OTHER-ATTR]
44  [ARRAY-ATTR]
45    [ENTRY]
46      [MEMBER1]
47      [MEMBER2]
48    [ENTRY]
49      [MEMBER1]
50      [MEMBER2]
51
52It wraps the entire array in an extra attribute (hence limiting its size
53to 64kB). The ``ENTRY`` nests are special and have the index of the entry
54as their type instead of normal attribute type.
55
56type-value
57~~~~~~~~~~
58
59``type-value`` is a construct which uses attribute types to carry
60information about a single object (often used when array is dumped
61entry-by-entry).
62
63``type-value`` can have multiple levels of nesting, for example
64genetlink's policy dumps create the following structures::
65
66  [POLICY-IDX]
67    [ATTR-IDX]
68      [POLICY-INFO-ATTR1]
69      [POLICY-INFO-ATTR2]
70
71Where the first level of nest has the policy index as it's attribute
72type, it contains a single nest which has the attribute index as its
73type. Inside the attr-index nest are the policy attributes. Modern
74Netlink families should have instead defined this as a flat structure,
75the nesting serves no good purpose here.
76
77Operations
78==========
79
80Enum (message ID) model
81-----------------------
82
83unified
84~~~~~~~
85
86Modern families use the ``unified`` message ID model, which uses
87a single enumeration for all messages within family. Requests and
88responses share the same message ID. Notifications have separate
89IDs from the same space. For example given the following list
90of operations:
91
92.. code-block:: yaml
93
94  -
95    name: a
96    value: 1
97    do: ...
98  -
99    name: b
100    do: ...
101  -
102    name: c
103    value: 4
104    notify: a
105  -
106    name: d
107    do: ...
108
109Requests and responses for operation ``a`` will have the ID of 1,
110the requests and responses of ``b`` - 2 (since there is no explicit
111``value`` it's previous operation ``+ 1``). Notification ``c`` will
112use the ID of 4, operation ``d`` 5 etc.
113
114directional
115~~~~~~~~~~~
116
117The ``directional`` model splits the ID assignment by the direction of
118the message. Messages from and to the kernel can't be confused with
119each other so this conserves the ID space (at the cost of making
120the programming more cumbersome).
121
122In this case ``value`` attribute should be specified in the ``request``
123``reply`` sections of the operations (if an operation has both ``do``
124and ``dump`` the IDs are shared, ``value`` should be set in ``do``).
125For notifications the ``value`` is provided at the op level but it
126only allocates a ``reply`` (i.e. a "from-kernel" ID). Let's look
127at an example:
128
129.. code-block:: yaml
130
131  -
132    name: a
133    do:
134      request:
135        value: 2
136        attributes: ...
137      reply:
138        value: 1
139        attributes: ...
140  -
141    name: b
142    notify: a
143  -
144    name: c
145    notify: a
146    value: 7
147  -
148    name: d
149    do: ...
150
151In this case ``a`` will use 2 when sending the message to the kernel
152and expects message with ID 1 in response. Notification ``b`` allocates
153a "from-kernel" ID which is 2. ``c`` allocates "from-kernel" ID of 7.
154If operation ``d`` does not set ``values`` explicitly in the spec
155it will be allocated 3 for the request (``a`` is the previous operation
156with a request section and the value of 2) and 8 for response (``c`` is
157the previous operation in the "from-kernel" direction).
158
159Other quirks (todo)
160===================
161
162Structures
163----------
164
165Legacy families can define C structures both to be used as the contents of
166an attribute and as a fixed message header. Structures are defined in
167``definitions``  and referenced in operations or attributes. Note that
168structures defined in YAML are implicitly packed according to C
169conventions. For example, the following struct is 4 bytes, not 6 bytes:
170
171.. code-block:: c
172
173  struct {
174          u8 a;
175          u16 b;
176          u8 c;
177  }
178
179Any padding must be explicitly added and C-like languages should infer the
180need for explicit padding from whether the members are naturally aligned.
181
182Here is the struct definition from above, declared in YAML:
183
184.. code-block:: yaml
185
186  definitions:
187    -
188      name: message-header
189      type: struct
190      members:
191        -
192          name: a
193          type: u8
194        -
195          name: b
196          type: u16
197        -
198          name: c
199          type: u8
200
201Fixed Headers
202~~~~~~~~~~~~~
203
204Fixed message headers can be added to operations using ``fixed-header``.
205The default ``fixed-header`` can be set in ``operations`` and it can be set
206or overridden for each operation.
207
208.. code-block:: yaml
209
210  operations:
211    fixed-header: message-header
212    list:
213      -
214        name: get
215        fixed-header: custom-header
216        attribute-set: message-attrs
217
218Attributes
219~~~~~~~~~~
220
221A ``binary`` attribute can be interpreted as a C structure using a
222``struct`` property with the name of the structure definition. The
223``struct`` property implies ``sub-type: struct`` so it is not necessary to
224specify a sub-type.
225
226.. code-block:: yaml
227
228  attribute-sets:
229    -
230      name: stats-attrs
231      attributes:
232        -
233          name: stats
234          type: binary
235          struct: vport-stats
236
237C Arrays
238--------
239
240Legacy families also use ``binary`` attributes to encapsulate C arrays. The
241``sub-type`` is used to identify the type of scalar to extract.
242
243.. code-block:: yaml
244
245  attributes:
246    -
247      name: ports
248      type: binary
249      sub-type: u32
250
251Multi-message DO
252----------------
253
254New Netlink families should never respond to a DO operation with multiple
255replies, with ``NLM_F_MULTI`` set. Use a filtered dump instead.
256
257At the spec level we can define a ``dumps`` property for the ``do``,
258perhaps with values of ``combine`` and ``multi-object`` depending
259on how the parsing should be implemented (parse into a single reply
260vs list of objects i.e. pretty much a dump).
261