Skip to contentSkip to conversation

Generic netlink interface help

DISCUSSION Rodolfo Giometti 6 participants 18 messages May 24, 2007 – May 30, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Hello,

I'm trying to use this new API for my LinuxPPS support but I have some difficulties in understanding the code!

Looking at http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO
is not clear... for example in line:

   msg_head = genlmsg_put(skb, pid, seq, type, 0, flags, DOC_EXMPL_C_ECHO, 1);

what "pid", "seq", "type" and "flags" stand for?

It could be possible to have a little kernel module implementing the ECHO function as example to compile and test?

Again, I read in a message from Jamal Hadi Salim regarding Kernel < --> User space Communication that:

Essentially nothing new, Communication is as in standard netlink approach. i.e from user space you open a netlink socket to the kernel - in this case family NETLINK_GENERIC - and send and receive response as well as asynchronous events. To receive to events you subscribe to specific multicast groups.

So I suppose I can modify a little my userland programs using old API in order to support this new API. Is that right?

Thanks,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#1 lore raw

Hi Rodolfo,

Quoted 8 lines · Rodolfo Giometti

Hello,

I'm trying to use this new API for my LinuxPPS support but I have some difficulties in understanding the code!

Looking at http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO
is not clear... for example in line:

Quoted 6 lines
  msg_head = genlmsg_put(skb, pid, seq, type, 0, flags, DOC_EXMPL_C_ECHO, 1);

what "pid", "seq", "type" and "flags" stand for?

It could be possible to have a little kernel module implementing the ECHO function as example to compile and test?

You could look at Johannes Berg 802.11 generic netlink implementation for a good example (net/wireless/nl80211.c in John Linville's tree):
http://git.kernel.org/?p=linux/kernel/git/linville/wireless-dev.git;a=blob;f=net/wireless/nl80211.c;h=d6a44a386c2b86b81514b08d3c9b324dd2c7d229;hb=HEAD

Quoted 11 lines

Again, I read in a message from Jamal Hadi Salim regarding Kernel < --> User space Communication that:

Essentially nothing new, Communication is as in standard netlink approach. i.e from user space you open a netlink socket to the kernel - in this case family NETLINK_GENERIC - and send and receive response as well as asynchronous events. To receive to events you subscribe to specific multicast groups.

So I suppose I can modify a little my userland programs using old API in order to support this new API. Is that right?

You probably want to use the libnl library. The latest SVN code has support for generic netlink:
http://people.suug.ch/~tgr/libnl/

Cheers,
Samuel.

#2 lore raw
Quoted 3 lines · Samuel Ortiz

You could look at Johannes Berg 802.11 generic netlink implementation for a good example (net/wireless/nl80211.c in John Linville's tree):
http://git.kernel.org/?p=linux/kernel/git/linville/wireless-dev.git;a=blob;f=net/wireless/nl80211.c;h=d6a44a386c2b86b81514b08d3c9b324dd2c7d229;hb=HEAD

Thanks, I'll take a look to it!

Quoted 3 lines

You probably want to use the libnl library. The latest SVN code has support for generic netlink:
http://people.suug.ch/~tgr/libnl/

Regarding this issue I'd like to know if could be possible to avoid using this library... my LinuxPPS support is strictly relate with NTPD which doesn't use such library. It could be possible still using simple syscalls to access this new layer as for the old API?

Thanks,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#3 lore raw
Quoted 8 lines · Rodolfo Giometti
Quoted 3 lines

You probably want to use the libnl library. The latest SVN code has support for generic netlink:
http://people.suug.ch/~tgr/libnl/

Regarding this issue I'd like to know if could be possible to avoid using this library... my LinuxPPS support is strictly relate with NTPD which doesn't use such library. It could be possible still using simple syscalls to access this new layer as for the old API?

Yes it's possible, even though it could be more tedious and painful.

Cheers,
Samuel.

#4 lore raw
Quoted 2 lines · Samuel Ortiz

Yes it's possible, even though it could be more tedious and painful.

I know that. Have you some links to suggest to me in order to have some programming examples?

Thanks,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#5 lore raw
Quoted 5 lines · Rodolfo Giometti
Quoted 1 line · Samuel Ortiz

Yes it's possible, even though it could be more tedious and painful.

I know that. Have you some links to suggest to me in order to have some programming examples?

The libnl library itself is probably the best example that I have seen. At it's core it is basically just regular Netlink with an extra layer of abstraction, i.e. a new header between the Netlink header and the payload.

Also, if you are still looking for in-kernel examples here are two _very_ simple ones which might help:

* net/netlabel/netlabel_unlabeled.c:netlbl_unlabel_accept() This function reads a single attribute, NLBL_UNLABEL_A_ACPTFLG, sent from user space and acts on the value.

* net/netlabel/netlabel_unlabeled.c:netlbl_unlabel_list() This function generates a reply message with a single attribute, NLBL_UNLABEL_A_ACPTFLG, in response to a request message.

Signature · 2 lines
paul moore
linux security @ hp
#6 lore raw
In reply to Rodolfo Giometti
Quoted 7 lines · Rodolfo Giometti
Quoted 2 lines · Samuel Ortiz

Yes it's possible, even though it could be more tedious and painful.

I know that. Have you some links to suggest to me in order to have some programming examples?

For debugging or writting some simple apps you could also use iproute2/genl
example on my laptop to discover loaded users:

---------------

hadi@lilsol:~$ genl ctrl ls

Name: nlctrl

        ID: 0x10  Version: 0x2  header size: 0  max attribs: 6
        commands supported:
                #1:  ID-0x3  flags-0xe

Name: nl80211

        ID: 0x11  Version: 0x1  header size: 0  max attribs: 22
        commands supported:
                #1:  ID-0x1  flags-0xa
                #2:  ID-0x6  flags-0xa
                #3:  ID-0x8  flags-0xa
                #4:  ID-0x3  flags-0xb
                #5:  ID-0x4  flags-0xb
                #6:  ID-0x5  flags-0xb
                #7:  ID-0xa  flags-0xb
                #8:  ID-0xb  flags-0xa
                #9:  ID-0xf  flags-0xb
                #10:  ID-0x10  flags-0xa
                #11:  ID-0x12  flags-0xb
                #12:  ID-0x13  flags-0xa
                #13:  ID-0x15  flags-0xa
                #14:  ID-0x19  flags-0xb
                #15:  ID-0x17  flags-0xb
                #16:  ID-0x18  flags-0xb
                #17:  ID-0x1a  flags-0xb
                #18:  ID-0x1b  flags-0xa
                #19:  ID-0xd  flags-0xb

Name: TASKSTATS

        ID: 0x12  Version: 0x1  header size: 0  max attribs: 4
        commands supported:
                #1:  ID-0x1  flags-0xa

---------------------------

Load tipc and repeat...

-----------

hadi@lilsol:~$ sudo modprobe tipc
Name: nlctrl
        ID: 0x10  Version: 0x2  header size: 0  max attribs: 6
        commands supported:
                #1:  ID-0x3  flags-0xe

Name: nl80211

        ID: 0x11  Version: 0x1  header size: 0  max attribs: 22
        commands supported:
                #1:  ID-0x1  flags-0xa
                #2:  ID-0x6  flags-0xa
                #3:  ID-0x8  flags-0xa
                #4:  ID-0x3  flags-0xb
                #5:  ID-0x4  flags-0xb
                #6:  ID-0x5  flags-0xb
                #7:  ID-0xa  flags-0xb
                #8:  ID-0xb  flags-0xa
                #9:  ID-0xf  flags-0xb
                #10:  ID-0x10  flags-0xa
                #11:  ID-0x12  flags-0xb
                #12:  ID-0x13  flags-0xa
                #13:  ID-0x15  flags-0xa
                #14:  ID-0x19  flags-0xb
                #15:  ID-0x17  flags-0xb
                #16:  ID-0x18  flags-0xb
                #17:  ID-0x1a  flags-0xb
                #18:  ID-0x1b  flags-0xa
                #19:  ID-0xd  flags-0xb

Name: TASKSTATS

        ID: 0x12  Version: 0x1  header size: 0  max attribs: 4
        commands supported:
                #1:  ID-0x1  flags-0xa

Name: TIPC

        ID: 0x13  Version: 0x1  header size: 8  max attribs: 0
        commands supported:
                #1:  ID-0x1  flags-0x2

===============

You essentially write a little .so in user space that knows how to access/intepret your kernel module
I know you are avoiding to use external libraries etc; but this may be a good way to get started.
I can dig up some simple kernel/user code i have and if you bug Thomas long enough he may give you another sample code he has.

cheers,
jamal

#7 lore raw
In reply to Samuel Ortiz
Quoted 3 lines · Samuel Ortiz

You probably want to use the libnl library. The latest SVN code has support for generic netlink:
http://people.suug.ch/~tgr/libnl/

Huh. I just looked at it and I don't understand anything. What's the point with genl_register/genl_unregister and having a table of commands etc? Thomas, can you explain how I should use libnl for nl80211 now? I mean, I can see what I can do with just sending/receiving messages but it feels like I'm missing something with all that other infrastructure in libnl.

johannes

#8 lore raw

* Johannes Berg <[email protected]> 2007-05-24 18:34

Quoted 6 lines · Samuel Ortiz
Quoted 4 lines

You probably want to use the libnl library. The latest SVN code has support for generic netlink:
http://people.suug.ch/~tgr/libnl/

Quoted 6 lines

Huh. I just looked at it and I don't understand anything. What's the point with genl_register/genl_unregister and having a table of commands etc? Thomas, can you explain how I should use libnl for nl80211 now? I mean, I can see what I can do with just sending/receiving messages but it feels like I'm missing something with all that other infrastructure in libnl.

This area is still work in progress but the basic idea is that like in kernel context, the application defines its set of commands and assigns message parsers for each command. For now, the message parser is linked into the cache operations which means that you have to "update" a cache in order to use this feature. This is obviously not optimal so what I might end up is to allow changing the "valid message" callback to be set to a parser function which takes the list of operations and does the demuxing.

#9 lore raw
Quoted 3 lines · Thomas Graf

This area is still work in progress but the basic idea is that like in kernel context, the application defines its set of commands and assigns message parsers for each command.

Ok, but why? For when we get asynchronous events from the kernel?

Quoted 4 lines

For now,
the message parser is linked into the cache operations which means that you have to "update" a cache in order to use this feature.

What's the cache good for to start with?

My current userland tool just send a message and expects back a response. Obviously that's broken once we have events too, is that when the message parsers come in?

johannes

#10 lore raw
Quoted 3 lines · Johannes Berg

My current userland tool just send a message and expects back a response. Obviously that's broken once we have events too, is that when

Is that written by using the libnl or not? Can you please send to me it, or just a portion of it, in order to better understand how I can send messages to the kernel?

Thanks,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#11 lore raw
Quoted 3 lines · Rodolfo Giometti

Is that written by using the libnl or not? Can you please send to me it, or just a portion of it, in order to better understand how I can send messages to the kernel?

It's written in python without using libnl:
http://git.sipsolutions.net/pynl80211.git

johannes

#15 lore raw
In reply to Samuel Ortiz
Quoted 3 lines · Samuel Ortiz

You could look at Johannes Berg 802.11 generic netlink implementation for a good example (net/wireless/nl80211.c in John Linville's tree):
http://git.kernel.org/?p=linux/kernel/git/linville/wireless-dev.git;a=blob;f=net/wireless/nl80211.c;h=d6a44a386c2b86b81514b08d3c9b324dd2c7d229;hb=HEAD

Looking at that code I suppose that if I want send/receive "struct pps_netlink_msg" to/from the kernel I have to define:

static struct genl_family pps_gnl_family = {
.id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
.name = "PPS",
.hdrsize = 0, /* no private header */
.version = PPS_FAMILY_VER,
.maxattr = 1,
};

static struct nla_policy pps_genl_policy[1] = {
[0] = {
.type = NLA_BINARY,
.len = sizeof(struct pps_netlink_msg),
},
};

static struct genl_ops pps_gnl_ops = {

        .cmd     = 0x1,
        .policy  = pps_genl_policy,
        .doit    = pps_genl_data_ready,

};

Then the pps_genl_data_ready() should do:

static int pps_genl_data_ready(struct sk_buff *skb, struct genl_info *info)

{
        struct pps_netlink_msg *msg = nla_data(info->attrs[0]);
        int cmd, source;
        unsigned long timeout;
        int ret;

        if (!msg)
                return -EINVAL;

	/* Do the job and put the answer into
	   msg struct itself... */

	genlmsg_unicast(skb, info->snd_pid);

        return 0;
}

Is that right?

Thanks,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#12 lore raw
In reply to Johannes Berg
Quoted 2 lines · Johannes Berg

It's written in python without using libnl:
http://git.sipsolutions.net/pynl80211.git

If I well understand I should do something like this:

	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_GENERIC);

        memset(&src_addr, 0, sizeof(src_addr));
        src_addr.nl_family = AF_NETLINK;
        src_addr.nl_pid = 0;            /* ask kernel to choose an unique ID */
        src_addr.nl_groups = 0;         /* not in mcast groups */
        ret = bind(handle->socket, (struct sockaddr *) &src_addr, sizeof(src_add

to get access to the generic netlink, then I should request the generic family name but I don't understand in which structure I should put this request... Can you please halp me?

Thanks a lot,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#16 lore raw
In reply to Rodolfo Giometti

Hi Rodolfo,

Quoted 50 lines · Rodolfo Giometti
Quoted 3 lines · Samuel Ortiz

You could look at Johannes Berg 802.11 generic netlink implementation for a good example (net/wireless/nl80211.c in John Linville's tree):
http://git.kernel.org/?p=linux/kernel/git/linville/wireless-dev.git;a=blob;f=net/wireless/nl80211.c;h=d6a44a386c2b86b81514b08d3c9b324dd2c7d229;hb=HEAD

Looking at that code I suppose that if I want send/receive "struct pps_netlink_msg" to/from the kernel I have to define:

static struct genl_family pps_gnl_family = {
.id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
.name = "PPS",
.hdrsize = 0, /* no private header */
.version = PPS_FAMILY_VER,
.maxattr = 1,
};

static struct nla_policy pps_genl_policy[1] = {
[0] = {
.type = NLA_BINARY,
.len = sizeof(struct pps_netlink_msg),
},
};

static struct genl_ops pps_gnl_ops = {

        .cmd     = 0x1,
        .policy  = pps_genl_policy,
        .doit    = pps_genl_data_ready,

};

Then the pps_genl_data_ready() should do:

static int pps_genl_data_ready(struct sk_buff *skb, struct genl_info *info)

{
        struct pps_netlink_msg *msg = nla_data(info->attrs[0]);
        int cmd, source;
        unsigned long timeout;
        int ret;

        if (!msg)
                return -EINVAL;

	/* Do the job and put the answer into
	   msg struct itself... */

	genlmsg_unicast(skb, info->snd_pid);

        return 0;
}
Quoted 1 line

Is that right?

At first glance, this could work yes.
However, it seems you're trying to encapsulate your pps_netlink_msg into a generic netlink message which itself is already encapsulated into a netlink message, and then multiplex all your PPS commands on ppl_genl_data_ready(). IMHO, you should have your different PPS commands declared as a genl_ops array, and then have a specific doit routine per PPS command. This would make your code cleaner and more secure (see the "Operation Granularity" section at
http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO).

Cheers,
Samuel.

#17 lore raw
Quoted 3 lines · Samuel Ortiz
Quoted 2 lines

Is that right?

At first glance, this could work yes.

Great! Now I have only to write the userland tool. :)

Quoted 8 lines

However, it seems you're trying to encapsulate your pps_netlink_msg into a generic netlink message which itself is already encapsulated into a netlink message, and then multiplex all your PPS commands on ppl_genl_data_ready(). IMHO, you should have your different PPS commands declared as a genl_ops array, and then have a specific doit routine per PPS command. This would make your code cleaner and more secure (see the "Operation Granularity" section at
http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO).

I see. I already supposed that but currently I'm trying to do minimal changes to my code in order to verify that everythink works well again, then I'll do the complete work.

Thanks a lot,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#13 lore raw
In reply to Rodolfo Giometti
Quoted 15 lines · Rodolfo Giometti
Quoted 2 lines · Johannes Berg

It's written in python without using libnl:
http://git.sipsolutions.net/pynl80211.git

If I well understand I should do something like this:

	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_GENERIC);

        memset(&src_addr, 0, sizeof(src_addr));
        src_addr.nl_family = AF_NETLINK;
        src_addr.nl_pid = 0;            /* ask kernel to choose an unique ID */
        src_addr.nl_groups = 0;         /* not in mcast groups */
        ret = bind(handle->socket, (struct sockaddr *) &src_addr, sizeof(src_add
Quoted 3 lines

to get access to the generic netlink, then I should request the generic family name but I don't understand in which structure I should put this request... Can you please halp me?

You should first fetch your attributed family ID by sending a generic netlink request (CTRL_CMD_GETFAMILY) to the generic netlink control family (GENL_ID_CTRL). Once you have your family ID, you can build generic netlink messages and send them there.
I'm linking with libnl, but you can have a look at my irconfig draft at
http://sortiz.org/irda/irconfig.c

Cheers,
Samuel.

Quoted 10 lines

Thanks a lot,

Rodolfo

Signature · 4 lines
GNU/Linux Solutions                  e-mail:    [email protected]
Linux Device Driver                             [email protected]
Embedded Systems                     		[email protected]
UNIX programming                     phone:     +39 349 2432127
#14 lore raw
In reply to Johannes Berg

* Johannes Berg <[email protected]> 2007-05-27 15:24

Quoted 7 lines · Thomas Graf
Quoted 4 lines

This area is still work in progress but the basic idea is that like in kernel context, the application defines its set of commands and assigns message parsers for each command.

Ok, but why? For when we get asynchronous events from the kernel?

I don't want to enforce a separate socket for every generic netlink family.

Quoted 10 lines
Quoted 4 lines

For now,
the message parser is linked into the cache operations which means that you have to "update" a cache in order to use this feature.

What's the cache good for to start with?

My current userland tool just send a message and expects back a response. Obviously that's broken once we have events too, is that when the message parsers come in?

See the documentation, a cache is basically a collection of objects. For events, you'd probably want to have each event added to a cache and then iterate over the cache to handle the events in the right order.