Page MenuHomeFreeBSD

netlink: return ENOBUFS on RX overflow
Needs ReviewPublic

Authored by zishun.yi.dev_gmail.com on Wed, Jun 24, 6:59 AM.

Details

Reviewers
obiwac
melifaro
glebius
Group Reviewers
network
Summary

In send() sync mode, as Linux does, if the recv buffer is full but the user
keeps sending, we record how many replies we dropped, and return ENOBUFS the
next time the user calls recv().

Doing this by checking the dropped bytes at the beginning of nl_soreceive(),
resetting them, and then returning immediately.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 74232
Build 71115: arc lint + arc unit

Event Timeline

could also be interesting to add a test to check whether data is copied into receive buffer or not and that ENOBUFS is returned correctly, but this can be done separately

sys/netlink/netlink_domain.c
845–848

I would rather commit this one before adding NLF_SND_SYNC, so if you can apply the suggested edit and move this down in the stack that'd be great

This revision is now accepted and ready to land.Wed, Jun 24, 1:21 PM
This revision now requires review to proceed.Thu, Jun 25, 9:57 AM

Can you please elaborate what software expects this and what problems the patch tries to address?

Returning ENOBUFS on recv(2) when we actually have data that can be successfully given to the application doesn't look correct at all. I know that Linux likes to return error from one syscall as a return to an other syscall, this was "a feature" since Linux 2.2 and UDP socket. While netlink is originally Linux idea, but it still is a socket(2), and it should behave as a normal socket and recv(2) shall return error from a receive operation, not status of a past send(2). We may want to emulate this bug on sockets opened by processes with Linux ABI, but I definitely don't want to be the behavior of the native socket.

@obiwac please don't rush with pushing this change

Returning ENOBUFS on recv(2) when we actually have data that can be successfully given to the application doesn't look correct at all. I know that Linux likes to return error from one syscall as a return to an other syscall, this was "a feature" since Linux 2.2 and UDP socket. While netlink is originally Linux idea, but it still is a socket(2), and it should behave as a normal socket and recv(2) shall return error from a receive operation, not status of a past send(2). We may want to emulate this bug on sockets opened by processes with Linux ABI, but I definitely don't want to be the behavior of the native socket.

that makes sense. was mainly operating under the idea of keeping our netlink behaviour close to linux's. I will defer to your opinion though.

@obiwac please don't rush with pushing this change

no worries, i wasn't going to commit this before @melifaro had a chance to comment on this anyways :)

Can you please elaborate what software expects this and what problems the patch tries to address?

Linux actually has a specific netlink socket flag, NETLINK_NO_ENOBUFS, which suggests that a lot of Linux software depends on the default ENOBUFS behavior.
As obiwac@ mentioned, our initial thought was to align this behavior with Linux, especially in preparation for the synchronous Netlink patch I plan to introduce.

Returning ENOBUFS on recv(2) when we actually have data that can be successfully given to the application doesn't look correct at all. I know that Linux likes to return error from one syscall as a return to an other syscall, this was "a feature" since Linux 2.2 and UDP socket. While netlink is originally Linux idea, but it still is a socket(2), and it should behave as a normal socket and recv(2) shall return error from a receive operation, not status of a past send(2). We may want to emulate this bug on sockets opened by processes with Linux ABI, but I definitely don't want to be the behavior of the native socket.

I agree with you. I saw the Linux udp(7) manual and know BSD doesn't send asynchronous errors to recv(2).
So, maybe we should implement this in the Linux ABI and implement NETLINK_NO_ENOBUFS along the way. And keep NETLINK_NO_ENOBUFS's behavior as the default behavior in FreeBSD?

What are the actual applications that depend on that?

What are the actual applications that depend on that?

I find a few:

I also found that libnl doesn't depend on it; it depends on NLMSG_OVERRUN: https://github.com/thom311/libnl/blob/655a638d4e1f74be9256a3108ae2abb84827a9ce/lib/nl.c#L957
So maybe implementing the TODO for NLMSG_OVERRUN in FreeBSD would be a better approach. (but I know freebsd use snl(3))