nl_recv() and handling truncated messages

Jan Gutter jan.gutter at netronome.com
Wed Dec 9 04:24:26 PST 2015


On Wed, Dec 9, 2015 at 12:14 PM, Thomas Haller <thaller at redhat.com> wrote:
> On Tue, 2015-12-08 at 17:37 +0200, Jan Gutter wrote:
>> nl_recv() works as expected if MSG_PEEK has been set, though, so it's
>> possible to fix in libvirt by either making the buffer bigger, or
>> enabling peeking.
>
> using MSG_PEEK requires two syscall to get the data, even if no
> truncation happens. Which is why you want to avoid that and why it's
> opt-in.

Yes, TBD if the performance impact would negatively impact libvirt, I
don't think
it's in fastpath, but I am not sure.

>> However, it would be nice if the error is passed up to the user of
>> libnl3.
>>
>> There's a couple of options open:
>> 1) Return NLE_MSG_TRUNC when a truncated message is received.
>
> I don't really understand the problem yet. Are you testing master?
>
> How does this relate to the two recent fixes:
> https://github.com/thom311/libnl/commit/fd9d1da28c9d989f88b6c5edaa352c0
> https://github.com/thom311/libnl/commit/bbdcaea9a779885fedc04817dcc1195

It has indeed been fixed in master:
http://git.infradead.org/users/tgr/libnl.git/blob_plain/HEAD:/lib/nl.c

I was checking with the older versions in Ubuntu and the docs
generated from v3.2.24-rc1
https://www.infradead.org/~tgr/libnl/doc/api/nl_8c_source.html

I applied the same fix and my test case correctly reports that nl_recv() failed.

>> 2) Enable MSG_TRUNC for all recvmsg calls and resize the buffer as
>> needed (meaning that NLE_MSG_TRUNC won't happen, but receive buffer
>> sizes can grow until realloc fails or a limit is hit...).
>
> With MSG_TRUNC, how can you resize the buffer and recover from the
> error? Isn't the message you failed to read (partly) lost?

Argh, I must have read the man page too optimistically. The idea was
to set MSG_TRUNC (but not MSG_PEEK) in the flags passed to recvmsg,
realloc the receive buffer to the correct size and read the remaining
message. However, it seems the bytes are lost:

recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"\200\34\0\0\20\0\0\0\f\33hV\357\213\0\0\0\0\1\0\6\0\0\0\2\20\0\0\0\0\0\0"...,
4096}], msg_controllen=0, msg_flags=MSG_TRUNC}, MSG_TRUNC) = 7296
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"$\0\0\0\2\0\0\0\f\33hV\357\213\0\0\0\0\0\0004\0\0\0\22\0\5\0\f\33hV"...,
7296}], msg_controllen=0, msg_flags=0}, MSG_TRUNC) = 36

vs

recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"\200\34\0\0\20\0\0\0[\33hV\f\214\0\0\0\0\1\0\6\0\0\0\2\20\0\0\0\0\0\0"...,
4096}], msg_controllen=0, msg_flags=MSG_TRUNC}, MSG_PEEK|MSG_TRUNC) =
7296
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"\200\34\0\0\20\0\0\0[\33hV\f\214\0\0\0\0\1\0\6\0\0\0\2\20\0\0\0\0\0\0"...,
7296}], msg_controllen=0, msg_flags=0}, MSG_TRUNC) = 7296
recvmsg(3, {msg_name(12)={sa_family=AF_NETLINK, pid=0,
groups=00000000},
msg_iov(1)=[{"$\0\0\0\2\0\0\0[\33hV\f\214\0\0\0\0\0\0004\0\0\0\22\0\5\0[\33hV"...,
7296}], msg_controllen=0, msg_flags=0}, 0) = 36

> But this sounds good. How would you do it?

It appears the only way to do this is with peeking.

Sorry to have raised the false alarm, that'll teach me to look at the
docs in stead of the code!

Jan



More information about the libnl mailing list