Actions
Bug #4995
closedhandle ENOBUFS on write to AF_PACKET socket
Start date:
01/30/2021
Due date:
% Done:
100%
Spec Reference:
Description
AF_PACKET sockets have the following "incredible" semantics:
- even when marked write-able by select/poll, they still many return -1 / ENOBUFS in case the socket buffer and/or tx-queue of the driver is full
- there is no way to safely/sanely wait for buffer space to become available again
- the only option is to re-try until it finally succeeds, preferably after a "reasonable" amount of sleep, considering the data rate of the underlying transport medium
I'm attaching a reproducer to demonstrate the problem, both with select() and without.
See also SYS#5343
The problem is further increased due to the fact that libosmocore/ns2 doesn't even notice if this happens.
The call chain looks like this:frame_relay.c:osmo_fr_tx_dlc()
is used to transmit NS messages by the NS2 coreframe_relay.c
will do whatever handling internalygprs_ns2fr.c:fr_tx_cb()
is the call-back we register with the frame_relay.c cre- puts msgb into osmo_wqueue
- wqueue code calls
gprs_ns2_fr.c:handle_netif_write()
as write-callback when the FD is write-able (always!)- we directlry retunr te result of the write() syscall (which is -1 in case of error)
osmo_wqueue_bfd_cb()
calls that write_cb(), but- it expects a -errno type return value, not the return value of a syscall that's likely just -1.
- only treats "-EAGAIN" as a trigger to re-enqueue the just-dequeued message
So all in all, we are using a write_queue, but it will never really queue anything, as the socket is always writable and we don't realize if the write actually fails.
What makes this even worse: A shared write_queue for user traffic and Q.933 LMI (or even NS-ALIVE) traffic is actively dangerous- if Q.933 starts to fail ,the entire link will be marked dead at the FR level
- if NS-ALIVE starts to fail, the NS-VC will be marked as DEAD
- as an absolute minimum, we should have a counter and/or error messages if ENOBUFS or any other error happens
- users of osmo_wqueue should always return a "-errno" style return value. We should audit all our code, not just this example
- there should be some notification of the uppwer layers/application when ENOBUFS happens
- have separate queues or some other prioritization that prefers Q.933 LMI traffic and NS-signaling (ALIVE/ALIVE-ACK) over all user traffic (NS-UNITDATA)
Files
Related issues
Actions