Netlink 规范对传统通用 Netlink 族的支持¶
本文档描述了描述构成 genetlink-legacy
协议级别的旧通用 Netlink 族所需的许多额外的怪癖和属性。
规范¶
全局变量¶
直接在 spec 文件根级别列出的属性。
version¶
通用 Netlink 族版本,默认为 1。
version
历史上被用来引入可能破坏向后兼容性的族更改。由于通常不允许破坏兼容性的更改,因此很少使用 version
。
属性类型嵌套¶
新的 Netlink 族应该使用 multi-attr
来定义数组。旧的族(例如 genetlink
控制族)尝试重新使用属性类型来携带信息以定义数组类型。
作为参考,multi-attr
数组可能如下所示
[ARRAY-ATTR]
[INDEX (optionally)]
[MEMBER1]
[MEMBER2]
[SOME-OTHER-ATTR]
[ARRAY-ATTR]
[INDEX (optionally)]
[MEMBER1]
[MEMBER2]
其中 ARRAY-ATTR
是数组条目类型。
indexed-array¶
indexed-array
将整个数组包装在一个额外的属性中(因此将其大小限制为 64kB)。ENTRY
嵌套很特殊,它们的类型是条目的索引而不是正常的属性类型。
需要一个 sub-type
来描述 ENTRY
中的类型。nest
sub-type
表示在 ENTRY
中存在嵌套数组,其结构如下所示
[SOME-OTHER-ATTR]
[ARRAY-ATTR]
[ENTRY]
[MEMBER1]
[MEMBER2]
[ENTRY]
[MEMBER1]
[MEMBER2]
其他 sub-type
(例如 u32
)表示在 ENTRY
中只有一个成员(如 sub-type
中所述)。其结构如下所示
[SOME-OTHER-ATTR]
[ARRAY-ATTR]
[ENTRY u32]
[ENTRY u32]
type-value¶
type-value
是一种结构,它使用属性类型来携带有关单个对象的信息(通常在逐个转储条目时使用)。
type-value
可以有多个嵌套级别,例如,genetlink 的策略转储会创建以下结构
[POLICY-IDX]
[ATTR-IDX]
[POLICY-INFO-ATTR1]
[POLICY-INFO-ATTR2]
其中第一层嵌套的属性类型是策略索引,它包含一个嵌套,其类型是属性索引。属性索引嵌套内是策略属性。现代 Netlink 族应该将其定义为平面结构,这里的嵌套没有任何好处。
操作¶
枚举(消息 ID)模型¶
unified¶
现代族使用 unified
消息 ID 模型,该模型对族内的所有消息使用单个枚举。请求和响应共享相同的消息 ID。通知具有来自同一空间的单独 ID。例如,给定以下操作列表
-
name: a
value: 1
do: ...
-
name: b
do: ...
-
name: c
value: 4
notify: a
-
name: d
do: ...
操作 a
的请求和响应将具有 ID 1,b
的请求和响应将具有 ID 2(因为没有显式 value
,它是前一个操作 + 1
)。通知 c
将使用 ID 4,操作 d
将使用 ID 5,依此类推。
directional¶
directional
模型根据消息的方向拆分 ID 分配。来自和发送到内核的消息不能彼此混淆,因此这节省了 ID 空间(代价是使编程更加繁琐)。
在这种情况下,应该在操作的 request
reply
部分中指定 value
属性(如果操作同时具有 do
和 dump
,则 ID 是共享的,应该在 do
中设置 value
)。对于通知,value
在 op 级别提供,但它只分配一个 reply
(即一个“来自内核”的 ID)。让我们看一个例子
-
name: a
do:
request:
value: 2
attributes: ...
reply:
value: 1
attributes: ...
-
name: b
notify: a
-
name: c
notify: a
value: 7
-
name: d
do: ...
在这种情况下,当发送消息到内核时,a
将使用 2,并期望响应中 ID 为 1 的消息。通知 b
分配一个“来自内核”的 ID,即 2。c
分配一个“来自内核”的 ID,即 7。如果操作 d
没有在 spec 中显式设置 values
,则将为请求分配 3(a
是上一个具有请求部分且值为 2 的操作),并为响应分配 8(c
是上一个“来自内核”方向的操作)。
其他怪癖¶
结构¶
传统族可以定义 C 结构,既可以用作属性的内容,也可以用作固定的消息头。结构在 definitions
中定义,并在操作或属性中引用。
成员¶
name
- 结构成员的属性名称
type
- 标量类型之一u8
、u16
、u32
、u64
、s8
、s16
、s32
、s64
、string
、binary
或bitfield32
。
byte-order
-big-endian
或little-endian
doc
、enum
、enum-as-flags
、display-hint
- 与 属性定义 相同
请注意,根据 C 约定,YAML 中定义的结构是隐式打包的。例如,以下结构是 4 个字节,而不是 6 个字节
struct {
u8 a;
u16 b;
u8 c;
}
任何填充都必须显式添加,C 类语言应根据成员是否自然对齐来推断是否需要显式填充。
以下是上面定义的结构,在 YAML 中声明
definitions:
-
name: message-header
type: struct
members:
-
name: a
type: u8
-
name: b
type: u16
-
name: c
type: u8
固定头¶
可以使用 fixed-header
将固定的消息头添加到操作中。默认的 fixed-header
可以在 operations
中设置,并且可以为每个操作设置或覆盖。
operations:
fixed-header: message-header
list:
-
name: get
fixed-header: custom-header
attribute-set: message-attrs
属性¶
可以使用具有结构定义名称的 struct
属性将 binary
属性解释为 C 结构。struct
属性意味着 sub-type: struct
,因此不需要指定子类型。
attribute-sets:
-
name: stats-attrs
attributes:
-
name: stats
type: binary
struct: vport-stats
C 数组¶
传统族还使用 binary
属性来封装 C 数组。sub-type
用于标识要提取的标量类型。
attributes:
-
name: ports
type: binary
sub-type: u32
多消息 DO¶
新的 Netlink 族绝不应使用设置了 NLM_F_MULTI
的多个回复来响应 DO 操作。请改用筛选的转储。
在 spec 级别,我们可以为 do
定义一个 dumps
属性,可能具有 combine
和 multi-object
的值,具体取决于应如何实现解析(解析为单个回复与对象列表,即几乎是转储)。