对旧式 Generic Netlink 族群的 Netlink 规范支持¶
本文档描述了描述构成 genetlink-legacy 协议级别的旧式 Generic Netlink 族群所需的许多附加怪癖和属性。
规范¶
全局变量¶
直接在规范文件根级别列出的属性。
版本¶
Generic 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 将整个数组包装在一个额外的属性中(因此将其大小限制为 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 可以具有多个嵌套级别,例如 genetlink 的策略转储创建以下结构
[POLICY-IDX]
[ATTR-IDX]
[POLICY-INFO-ATTR1]
[POLICY-INFO-ATTR2]
第一级嵌套的策略索引作为其属性类型,它包含一个具有属性索引作为其类型的嵌套。属性索引嵌套内部是策略属性。现代 Netlink 族群应该将其定义为扁平结构,嵌套在这里没有好处。
操作¶
枚举(消息 ID)模型¶
统一¶
现代族群使用 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 模型按消息的方向分割 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 未在规范中显式设置 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- 与 属性定义 相同
请注意,YAML 中定义的结构体根据 C 约定隐式打包。例如,以下结构体为 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 操作。请改用过滤的转储。
在规范级别,我们可以为 do 定义一个 dumps 属性,可能具有值 combine 和 multi-object,具体取决于应如何实现解析(解析为单个回复与对象列表,即几乎是一个转储)。