From: Jiayuan Chen <jiayuan.c...@linux.dev> Date: Thu, 1 May 2025 11:51:08 +0800 > For some services we are using "established-over-unconnected" model. > > ''' > // create unconnected socket and 'listen()' > srv_fd = socket(AF_INET, SOCK_DGRAM) > setsockopt(srv_fd, SO_REUSEPORT) > bind(srv_fd, SERVER_ADDR, SERVER_PORT) > > // 'accept()' > data, client_addr = recvmsg(srv_fd) > > // create a connected socket for this request > cli_fd = socket(AF_INET, SOCK_DGRAM) > setsockopt(cli_fd, SO_REUSEPORT) > bind(cli_fd, SERVER_ADDR, SERVER_PORT) > connect(cli, client_addr) > ... > // do handshake with cli_fd > ''' > > This programming pattern simulates accept() using UDP, creating a new > socket for each client request. The server can then use separate sockets > to handle client requests, avoiding the need to use a single UDP socket > for I/O transmission. > > But there is a race condition between the bind() and connect() of the > connected socket: > We might receive unexpected packets belonging to the unconnected socket > before connect() is executed, which is not what we need. > (Of course, before connect(), the unconnected socket will also receive > packets from the connected socket, which is easily resolved because > upper-layer protocols typically require explicit boundaries, and we > receive a complete packet before creating a connected socket.) > > Before this patch, the connected socket had to filter requests at recvmsg > time, acting as a dispatcher to some extent. With this patch, we can > consider the bind and connect operations to be atomic.
SO_ATTACH_REUSEPORT_EBPF is what you want. The socket won't receive any packets until the socket is added to the BPF map. No need to reinvent a subset of BPF functionalities.