Scenario: Two threads sending UDP on the same socket, and thread 1 wants to set different diffserv/QoS class than thread 2. We have solved this previously by wrapping sendto() calls in a mutex, and doing setsockopt() of appropriate QoS class before and after the sendto() (and then unlock mutex).
We got a deadlock/hang in rare circumstances (due to interaction with a signal) using this solution, and my question is this - can we remove the mutex entirely if we instead send the wanted QoS class as ancillary data in a sendmsg() call? To clarify, is sendmsg() atomic so the datagrams will be sent using correct QoS class, and not risk having the sendmsg() calls from thread 1 and 2 interfering with each other?
I have found similar questions on SO, so I know normal sendmsg() of one UDP datagram on one socket is 'atomic', but the question is if the entire call, including temporarily changing QoS bits for the socket, is atomic as seen by the user-space thread?
Relevant patch in Linux kernel is this:
commit aa6615814533c634190019ee3a5b10490026d545
Author: Francesco Fusco <ffusco@redhat.com>
Date: Tue Sep 24 15:43:09 2013 +0200
ipv4: processing ancillary IP_TOS or IP_TTL
If IP_TOS or IP_TTL are specified as ancillary data, then sendmsg() sends out
packets with the specified TTL or TOS overriding the socket values specified
with the traditional setsockopt().
The struct inet_cork stores the values of TOS, TTL and priority that are
passed through the struct ipcm_cookie. If there are user-specified TOS
(tos != -1) or TTL (ttl != 0) in the struct ipcm_cookie, these values are
used to override the per-socket values. In case of TOS also the priority
is changed accordingly.
Two helper functions get_rttos and get_rtconn_flags are defined to take
into account the presence of a user specified TOS value when computing
RT_TOS and RT_CONN_FLAGS.
Signed-off-by: Francesco Fusco <ffusco@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>