Several nlmsghdr in the message netlink packet

Emmanuel Thierry emmanuel.thierry at telecom-bretagne.eu
Fri Dec 13 13:34:03 EST 2013


Le 13 déc. 2013 à 15:55, Thomas Graf <tgraf at suug.ch> a écrit :

> On 12/11/13 at 06:21pm, Emmanuel Thierry wrote:
>> Hello,
>> 
>> I'm working on a daemon that needs to send a lot of netlink messages in the same time. For performance purposes, i thought about sending all of it in batch in the same netlink message.
>> I tried a proof of concept implementation with the code below, on the XFRM system. All nlmsghdr are independent, they all give a distinct order and all have distinct sequence numbers, they can issue distinct ACKs. As an example you can in the same batch add a policy and delete it afterward. So the netlink system clearly supports this.
>> 
>> However, i didn't see any function to ease this kind of operations in libnl3. This results in a really hacky code (see below).
>> Did i miss something ? Is there a plan to support such a feature ?
> 
> You didn't miss anything. It does not exist yet. A standard API for what
> you describe would be very welcome.
> 
> I guess it should be doable to modify the message object to support
> chaining and have a function to finalize an existing message and
> prepare the message object to allow constructing a new message
> though the existing message API.


About the implementation, from the few i understood from libnl code, i agree that it doesn't require too much changes, and may permit to keep the same API to work in single and multi modes.
In terms of design, i would have proposed something as described below:

1/ Distinguish struct nlmsghdr *nm_nlh (redefined as "the working nlmsghdr structure") from void *nm_buf (a new field representing the whole message buffer).
2/ Keep the same API to manipulate nl_msg in single and multi mode
3/ Introduce modifiers:
* int nlmsg_append_hdr(struct nl_msg*):	move the nm_nlh pointer after the last nlmsghdr message and initialize the new message (setting nm_nlh->nlmsg_len to NLMSG_HDRLEN)
* int nlmsg_strip_hdr(struct nl_msg*):		bzero() the last nlmsghdr message
4/ Introduce iterator functions to move the nm_nlh pointer:
* struct nlmsghdr *nlmsg_hdr_first(struct nl_msg*):	reset the return the nm_nlh pointer to the base message buffer
* struct nlmsghdr *nlmsg_hdr(struct nl_msg*):		return the current position (unchanged from the current implementation)
* struct nlmsghdr *nlmsg_hdr_next(struct nl_msg*):	move the nm_nlh pointer to the next nlmsghdr structure
This may avoid modifications to most of functions that plays with nm_nlh. These functions (e.g. nl_complete_msg, nlmsg_validate, nlmsg_put, nl_msg_parse, print_*_msg, ... may be used in multi mode without any changes to the implementation nor to the API). In that case, it would be up to the user to iterate over the message stream and apply these functions on all headers.
5/ An adaptation is needed for functions playing with nm_size

However, some functions may not be supported easily:
* nl_send_sync: for which ACK do we wait ?
* ... other incompatibilities ?

Does it look a nice design to you ?

Thanks.
Emmanuel Thierry




More information about the libnl mailing list