MEDIUM: udp: implement udp_suspend() and udp_resume()
authorWilly Tarreau <w@1wt.eu>
Wed, 7 Oct 2020 17:55:15 +0000 (19:55 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 9 Oct 2020 16:29:04 +0000 (18:29 +0200)
commite122dc5316bc065b7ea345b6dfc769f8d8e86f3c
tree635a497fea902da6869879b610ffc8c62352c816
parent626f3a7beb33f921b7b13fda4d1d585160fe2051
MEDIUM: udp: implement udp_suspend() and udp_resume()

In Linux kernel's net/ipv4/udp.c there's a udp_disconnect() function
which is called when connecting to AF_UNSPEC, and which unhashes a
"connection". This property, which is also documented in connect(2)
both in Linux and Open Group's man pages for datagrams, is interesting
because it allows to reverse a connect() which is in fact a filter on
the source. As such we can suspend a receiver by making it connect to
itself, which will cause it not to receive any traffic anymore, letting
a new one receive it all, then resume it by breaking this connection.

This was tested to work well on Linux, other operating systems should
also be tested. Before this, sending a SIGTTOU to a process having a
UDP syslog forwarder would cause this error:

  [WARNING] 280/194249 (3268) : Paused frontend GLOBAL.
  [WARNING] 280/194249 (3268) : Some proxies refused to pause, performing soft stop now.
  [WARNING] 280/194249 (3268) : Proxy GLOBAL stopped (cumulated conns: FE: 0, BE: 0).
  [WARNING] 280/194249 (3268) : Proxy sylog-loadb stopped (cumulated conns: FE: 0, BE: 0).

With this change, it now proceeds just like with TCP listeners:

  [WARNING] 280/195503 (3885) : Paused frontend GLOBAL.
  [WARNING] 280/195503 (3885) : Paused frontend sylog-loadb.

And SIGTTIN also works:

  [WARNING] 280/195507 (3885) : Resumed frontend GLOBAL.
  [WARNING] 280/195507 (3885) : Resumed frontend sylog-loadb.

On Linux this also works with TCP listeners (which can then be resumed
using listen()) and established TCP sockets (which we currently kill
using setsockopt(so_linger)), both not being portable on other OSes.
UNIX sockets and ABNS sockets do not support it however (connect
always fails). This needs to be further explored to see if other OSes
might benefit from this to perform portable and reliable resets
particularly on the backend side.
src/proto_udp.c