I am new in netlink
programming. I am writing a generic
netlink
program for creating a netlink
protocol family. I have searched many documents on the internet and I found something "Attributes and Policies" like things
for defining a netlink
family.
I am totally confused with these things.
I found something like bellow about attributes in linux/netlink.h
<------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
+---------------------------+- - -+- - - - - - - - - -+- - -+
| Header | Pad | Payload | Pad |
| (struct nlattr) | ing | | ing |
+---------------------------+- - -+- - - - - - - - - -+- - -+
<-------------------- nlattr->nla_len -------------->
And policy is an array of nla_policy
structures.
My questions are:
I found something about policies like "it defines types of attributes",
what does this mean? I mean "what is the meaning of type of attribute?"
It may be a nonsense question, but I am totally confused. I have been trying to understand these things for more than three days, please help me.
Thanks..
Netlink attributes are unusual in that they are in LTV (length, type, value) format, instead of the typical TLV (type, length, value). As with every other integer in netlink sockets, the type and length values are also encoded with host endianness.
Generic netlink was designed to allow kernel modules to easily communicate with userspace applications using netlink. Instead of creating a new top level netlink family for each module, generic netlink provides a simplified interface to enable modules to plug into the generic netlink bus.
Netlink is used to transfer information between the kernel and user-space processes. It consists of a standard sockets-based interface for user space processes and an internal kernel API for kernel modules.
To use Netlink sockets in code, a standard socket API is used, which is as follows: int socket(int domain, int type , int protocol); Here, domain specifies the protocol family used for communication which is defined in sys/socket. h; domain in the case of Netlink is AF_NETLINK.
When creating/using netlink
protocols, netlink
attributes are intended to give the protocol a clean self documenting layout that allows for future extensibility. Meaning if you were wanting to use a different data type in addition to the ones that already exist in your current protocol, the code would be compatible without breaking the operations that already exist.
The "attributes" are protocol dependent, and relate to a specific message being sent using said 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 could easily "extend" them by adding in a custom attribute between UNSPEC
and MAX
mapping that attribute to a specific function or operation needed.
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 you've already come across the definition for struct nlattr
, an example of loading this struct's fields using the NETLINK_GENERIC
protocol and the taskstats
interface:
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.
Now on the kernel side when parsing these attributes the associated functions will be called and intended actions on how to proceed.
I'm not sure if the diagram you posted is throwing you off but, to zoom out a bit to give you a larger perspective:
As per the kernel source 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)---^
Here you can see that the header and payload diagram you posted are but parts of a larger payload. That segment goes along with a struct nlmsghdr
in the message format.
Now on policy, when sending netlink messages the sender needs to adhere to the protocol
format. The receiver of the message will use struct nla_policy
to validate the attributes before the payload is accessed.
The "family" or identifier is used by the kernel to keep track of the appropriate protocol interface to be communicating with, whether standard protocol or custom as with Generic Netlink.
When you ask "Can we avoid this?", if you're extending netlink by writing your own custom generic netlink protocol these exist to allow that protocol to be easily adjusted and maintained without going through and changing/fixing all operations associated with it or flat-out having the protocol break down. How else would you suggest parsing through nested messages with different data-types without an associated length or type? The type and length are there to allow parsing of the message on the correct alignments and allow the desired actions to take place. Without the attributes type giving the payload a label how would you interpret it, "what is" the payload? Without the length how would you know "how large" the payload is? There could be multiple payloads all with different lengths without something to distinguish their sizes there is no way to be able to tell where one starts and the other ends.
Here is a link to the libnl (a library for working with netlink sockets, and is highly recommended) documentation attributes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With