When creating / using netlink protocols, netlink attributes are designed to provide the protocol with a clean, self-recording layout that allows for future expansion. If you want to use a different data type in addition to those that already exist in your current protocol, the code will be compatible without breaking existing operations.
“Attributes” are protocol-specific and refer to a specific message sent using the specified protocol.
Using the taskstats interface as an example:
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, };
In these attributes, you can easily “expand” them by adding to the user attribute between UNSPEC and MAX display of this attribute of a specific function or operation.
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 },};
I believe that you have already found the definition for struct nlattr , an example of loading these structure fields using the NETLINK_GENERIC protocol and the taskstats interface:
struct nlattr na; na.nla_type = CTRL_ATTR_FAMILY_NAME;
Now, on the kernel side, when parsing these attributes, the associated functions and the proposed actions to continue them will be called.
I'm not sure the chart you posted casts you off, but to zoom out a bit to give you a great perspective:
According to the v3.16 kernel source code 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)---^
Here you can see that the title and payload diagram you posted is part of a larger payload. This segment conforms to the struct nlmsghdr format in the message format.
Now, in the policy when sending netlink messages, the sender must adhere to the protocol format. The receiver of the message will use struct nla_policy to validate the attributes before accessing the payload.
The "core" or "Identifier" is used by the kernel to track the corresponding protocol interface for communication with it, whether it is a standard protocol or custom, as with Generic Netlink .
When you ask, “Can we avoid it?”, If you expand the network by creating your own common Netlink protocol, they exist to make it easy to configure and maintain this protocol without going through and changing / correcting all related operations with it or with an outbreak that violates the protocol. How else could you suggest parsing nested messages with different data types without the appropriate length or type? Type and length to allow parsing of the message on the correct alignment and to allow the necessary actions. Without the type of attributes that give the payload a label, how do you interpret it, “what is a“ payload ”? Without length, how would you know“ how large ”a payload is? There can be several payloads with different lengths without any difference from their sizes, there is no way to tell where to start, and the other ends.
Here is a link to libnl (a library for working with network sockets and is highly recommended) attributes .