【问题标题】:What are the concepts of policies and attributes in generic netlink?通用网络链接中策略和属性的概念是什么?
【发布时间】:2014-10-06 10:35:55
【问题描述】:

我是netlink 编程的新手。我正在编写一个 generic netlink 程序来创建一个 netlink 协议族。我在互联网上搜索了很多文档,我发现了一些“属性和策略”之类的东西 用于定义netlink 家庭。

我完全对这些事情感到困惑。

我在linux/netlink.h 中发现了类似下面的属性

 <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
+---------------------------+- - -+- - - - - - - - - -+- - -+
|        Header             | Pad |    Payload        | Pad | 
|   (struct nlattr)         | ing |                   | ing |
+---------------------------+- - -+- - - - - - - - - -+- - -+
 <-------------------- nlattr->nla_len -------------->

policy 是nla_policy 结构的数组。 我的问题是:

  1. 标题和属性之间的关系是什么?请解释 “属性”。
  2. 什么是策略,需要什么,为什么我们为此使用数组?

我发现了一些有关政策的信息,例如“它定义了属性的类型”,
这是什么意思?我的意思是“属性类型的含义是什么?”

这可能是一个无意义的问题,但我完全糊涂了。我已经尝试了解这些东西超过三天了,请帮助我。

谢谢..

【问题讨论】:

  • 不确定这是否仍然是一个问题,但如果您仍然感兴趣,我进行了一些编辑。
  • 感谢@tijko 的回复。其实我已经得到了这些东西。我想知道诸如“未来可扩展性”、“家庭”、“策略”等事物的一些字面含义。我正在编写一个带有通用网络链接的模块,我发现数据包结构如下:| NLMSGHDR | GENLMSGHDR |类型 |长度 |实际数据......|所以,我的问题是,类型和长度的需求是什么,以及这些东西在未来将如何帮助我们。我们能避免这种情况吗?如果你有时间请帮我...
  • 我已经扩展了您在上面评论中提到的要点。

标签: linux module kernel netlink


【解决方案1】:

在创建/使用netlink 协议时,netlink 属性旨在为协议提供一个干净的自我记录布局,以便未来可扩展。这意味着如果您想使用除了当前协议中已经存在的数据类型之外的其他数据类型,那么代码将是兼容的,而不会破坏已经存在的操作。

“属性”取决于协议,并与特定消息相关 使用所述协议发送。

taskstats接口为例:

taskstat attributes:

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,
};

在这些属性中,您可以通过在 UNSPECMAX 之间添加自定义属性来轻松“扩展”它们,将该属性映射到所需的特定功能或操作。

内核空间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 的链接。

【讨论】:

  • 为什么在标头和有效载荷之间有一个Pad?从文档中,nlmsghdr 是 alawys 16 个字节,而属性标头始终是 4 个字节。这是否意味着由于对齐始终设置为 4 个字节,因此标头和有效负载之间不需要任何填充?
  • @CMCDragonkai 我使用这个协议已经有好几年了,但是如果我发现任何相关的东西,我可以重新阅读一些文档并回复你。
  • 你发现了吗?该图表明消息头和有效负载之间存在一个 Pad,并且家庭头及其有效负载之间也存在一个 Pad。我想知道分解的破折号是否意味着此填充是可选的,并且仅在标题本身未对齐时才需要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-22
  • 2013-07-28
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多