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