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