Re: [RFC PATCH bpf-next 0/8] Socket migration for SO_REUSEPORT.

From: Martin KaFai Lau
Date: Wed Nov 18 2020 - 20:50:45 EST


On Tue, Nov 17, 2020 at 06:40:15PM +0900, Kuniyuki Iwashima wrote:
> The SO_REUSEPORT option allows sockets to listen on the same port and to
> accept connections evenly. However, there is a defect in the current
> implementation. When a SYN packet is received, the connection is tied to a
> listening socket. Accordingly, when the listener is closed, in-flight
> requests during the three-way handshake and child sockets in the accept
> queue are dropped even if other listeners could accept such connections.
>
> This situation can happen when various server management tools restart
> server (such as nginx) processes. For instance, when we change nginx
> configurations and restart it, it spins up new workers that respect the new
> configuration and closes all listeners on the old workers, resulting in
> in-flight ACK of 3WHS is responded by RST.
>
> As a workaround for this issue, we can do connection draining by eBPF:
>
> 1. Before closing a listener, stop routing SYN packets to it.
> 2. Wait enough time for requests to complete 3WHS.
> 3. Accept connections until EAGAIN, then close the listener.
>
> Although this approach seems to work well, EAGAIN has nothing to do with
> how many requests are still during 3WHS. Thus, we have to know the number
It sounds like the application can already drain the established socket
by accept()? To solve the problem that you have,
does it mean migrating req_sk (the in-progress 3WHS) is enough?

Applications can already use the bpf prog to do (1) and divert
the SYN to the newly started process.

If the application cares about service disruption,
it usually needs to drain the fd(s) that it already has and
finishes serving the pending request (e.g. https) on them anyway.
The time taking to finish those could already be longer than it takes
to drain the accept queue or finish off the 3WHS in reasonable time.
or the application that you have does not need to drain the fd(s)
it already has and it can close them immediately?

> of such requests by counting SYN packets by eBPF to complete connection
> draining.
>
> 1. Start counting SYN packets and accept syscalls using eBPF map.
> 2. Stop routing SYN packets.
> 3. Accept connections up to the count, then close the listener.