From f1003ea7fae8de9aabf9471b2bf8afcfcffbc542 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sat, 22 Apr 2023 18:26:56 +0200 Subject: [PATCH] MINOR: protocol: perform a live check for SO_REUSEPORT support When testing if a protocol supports SO_REUSEPORT, we're now able to verify if the OS does really support it. While it may be supported at build time, it may possibly have been blocked in a container for example so we'd rather know what it's like. --- include/haproxy/protocol-t.h | 1 + src/protocol.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index eec65fed42..47df36641c 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -66,6 +66,7 @@ enum proto_type { /* Flags for protocol->flags */ #define PROTO_F_REUSEPORT_SUPPORTED 0x00000001 /* SO_REUSEPORT is supported */ +#define PROTO_F_REUSEPORT_TESTED 0x00000002 /* SO_REUSEPORT support was tested */ /* protocol families define standard functions acting on a given address family * for a socket implementation, such as AF_INET/PF_INET for example. diff --git a/src/protocol.c b/src/protocol.c index c190a36642..c4b57c5efa 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -92,12 +93,23 @@ void protocol_setf_all(uint flag) int protocol_supports_flag(struct protocol *proto, uint flag) { if (flag == PROTO_F_REUSEPORT_SUPPORTED) { + int ret = 0; + /* check if the protocol supports SO_REUSEPORT */ if (!(_HA_ATOMIC_LOAD(&proto->flags) & PROTO_F_REUSEPORT_SUPPORTED)) return 0; - /* OK it looks like it is supported */ - return 1; + /* at least nobody said it was not supported */ + if (_HA_ATOMIC_LOAD(&proto->flags) & PROTO_F_REUSEPORT_TESTED) + return 1; + + /* run a live check */ + ret = _sock_supports_reuseport(proto->fam, proto->sock_type, proto->sock_prot); + if (!ret) + _HA_ATOMIC_AND(&proto->flags, ~PROTO_F_REUSEPORT_SUPPORTED); + + _HA_ATOMIC_OR(&proto->flags, PROTO_F_REUSEPORT_TESTED); + return ret; } return 0; }