我是netlink
编程的新手。我正在撰写generic
netlink
程序,用于创建netlink
协议系列。我在互联网上搜索了很多文档,我发现了“属性和策略”之类的东西
用于定义netlink
系列。
我对这些事情感到很困惑。
我在linux/netlink.h
<------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
+---------------------------+- - -+- - - - - - - - - -+- - -+
| Header | Pad | Payload | Pad |
| (struct nlattr) | ing | | ing |
+---------------------------+- - -+- - - - - - - - - -+- - -+
<-------------------- nlattr->nla_len -------------->
策略是nla_policy
个结构的数组。
我的问题是:
我发现了一些关于“它定义属性类型”的政策, 这是什么意思?我的意思是“属性类型的含义是什么?”
这可能是一个无稽之谈的问题,但我完全感到困惑。我一直试图了解这些事情超过三天,请帮助我。
谢谢..
答案 0 :(得分:5)
创建/使用netlink
协议时,netlink
属性旨在为协议提供一个干净的自我文档布局,以便将来可扩展。这意味着如果您想要使用除当前协议中已存在的数据类型之外的其他数据类型,则代码将兼容而不会破坏已存在的操作。
“属性”取决于协议,并且与特定消息相关 使用所述协议发送。
以taskstats
界面为例:
enum {
TASKSTATS_CMD_ATTR_UNSPEC = 0,
TASKSTATS_CMD_ATTR_PID,
TASKSTATS_CMD_ATTR_TGID,
TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
__TASKSTATS_CMD_ATTR_MAX,
};
在这些属性中,您可以通过在UNSPEC
和MAX
之间添加自定义属性来轻松地“扩展”它们,将该属性映射到所需的特定功能或操作。
kernel-space taskstat
policy:
static const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
[TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 },
[TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 },
[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING },
[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },};
我相信您已经遇到struct nlattr
的定义,这是使用NETLINK_GENERIC
协议和taskstats
接口加载此结构字段的示例:
struct nlattr na;
na.nla_type = CTRL_ATTR_FAMILY_NAME; // defined in linux/genetlink.h
na.nla_len = strlen(TASKSTATS_GENL_NAME) + 1 // defined in linux/taskstats.h
// note: you will need to copy/access nlattr data in the same way the NLMSG_DATA
// macro operates.
现在在内核方面,在解析这些属性时,将调用相关的函数,并就如何继续进行预期的操作。
我不确定你发布的图表是否会让你失望,但是要缩小一点 给你一个更大的视角:
根据内核源代码 v3.16 include/net/netlink.h
:
/* ========================================================================
* Netlink Messages and Attributes Interface (As Seen On TV)
* ------------------------------------------------------------------------
* Messages Interface
* ------------------------------------------------------------------------
*
* Message Format:
* <--- nlmsg_total_size(payload) --->
* <-- nlmsg_msg_size(payload) ->
* +----------+- - -+-------------+- - -+-------- - -
* | nlmsghdr | Pad | Payload | Pad | nlmsghdr
* +----------+- - -+-------------+- - -+-------- - -
* nlmsg_data(nlh)---^ ^
* nlmsg_next(nlh)-----------------------+
*
* Payload Format:
* <---------------------- nlmsg_len(nlh) --------------------->
* <------ hdrlen ------> <- nlmsg_attrlen(nlh, hdrlen) ->
* +----------------------+- - -+--------------------------------+
* | Family Header | Pad | Attributes |
* +----------------------+- - -+--------------------------------+
* nlmsg_attrdata(nlh, hdrlen)---^
在这里,您可以看到您发布的标头和有效负载图只是更大负载的一部分。该段与消息格式中的struct nlmsghdr
一起使用。
现在在策略上,当发送netlink消息时,发送者需要遵守协议
格式。在访问有效负载之前,消息的接收方将使用struct nla_policy
来验证属性。
内核使用“系列”或标识符来跟踪要与之通信的相应协议接口,无论是标准协议还是自定义Generic Netlink。
当您问“我们可以避免这种情况吗?”时,如果您通过编写自己的自定义通用netlink协议来扩展netlink,则可以轻松调整和维护该协议,而无需通过并更改/修复所有相关操作使用它或使协议发生故障。如果没有关联的长度或类型,您建议如何解析具有不同数据类型的嵌套消息?类型和长度允许在正确的对齐上解析消息并允许进行所需的操作。如果没有为有效负载提供标签的属性类型,您将如何解释它,“有效负载是什么”?没有长度你怎么知道有效载荷“有多大”?可能存在多个具有不同长度的有效载荷,而无需区分它们的大小,因此无法分辨出一个开始和另一个结束的位置。
以下是指向 libnl (用于处理netlink套接字的库,强烈建议使用)文档attributes的链接。