diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index eec65fed4..47df36641 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 c190a3664..c4b57c5ef 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; }