Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the concepts of policies and attributes in generic netlink?

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:

  1. What is the relation between header and attribute? Please explain "Attributes".
  2. What is policy, what is need of it and why do we use an array for this?

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..

like image 693
Nishant Avatar asked Aug 13 '14 06:08

Nishant


People also ask

What is Netlink attribute?

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.

What is generic Netlink?

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.

What is Netlink message?

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.

How do you use Netlink sockets?

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.


1 Answers

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.

like image 72
tijko Avatar answered Oct 21 '22 18:10

tijko