]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: protocol: add a function to check if some features are supported
authorWilly Tarreau <w@1wt.eu>
Sat, 22 Apr 2023 15:39:30 +0000 (17:39 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 23 Apr 2023 07:46:15 +0000 (09:46 +0200)
The new function protocol_supports_flag() checks the protocol flags
to verify if some features are supported, but will support being
extended to refine the tests. Let's use it to check for REUSEPORT.

include/haproxy/protocol.h
src/listener.c
src/protocol.c

index 5c0871aec7b8e7ad58a2a1644c34f2e5c666cbc6..828093d98241c9c87626adcc99dd352ae116f2bd 100644 (file)
@@ -44,6 +44,14 @@ void protocol_clrf_all(uint flag);
 /* sets flag <flag> on all protocols. */
 void protocol_setf_all(uint flag);
 
+/* Checks if protocol <proto> supports PROTO_F flag <flag>. Returns zero if not,
+ * non-zero if supported. It may return a cached value from a previous test,
+ * and may run live tests then update the proto's flags to cache a result. It's
+ * better to call it only if needed so that it doesn't result in modules being
+ * loaded in case of a live test.
+ */
+int protocol_supports_flag(struct protocol *proto, uint flag);
+
 /* binds all listeners of all registered protocols. Returns a composition
  * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL, ERR_ABORT.
  */
index 45595cc69e76b08c01d0d0d0c0cb5a29cd8d7916..994e97a348fc73a548921cf9e734fbd4e42bd4df 100644 (file)
@@ -1669,7 +1669,7 @@ int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code)
 
                /* special values: -1 = "by-thread", -2 = "by-group" */
                if (shards == -1) {
-                       if (li->rx.proto->flags & PROTO_F_REUSEPORT_SUPPORTED)
+                       if (protocol_supports_flag(li->rx.proto, PROTO_F_REUSEPORT_SUPPORTED))
                                shards = todo;
                        else {
                                if (fe != global.cli_fe)
@@ -1680,14 +1680,14 @@ int bind_complete_thread_setup(struct bind_conf *bind_conf, int *err_code)
                        }
                }
                else if (shards == -2)
-                       shards = (li->rx.proto->flags & PROTO_F_REUSEPORT_SUPPORTED) ? my_popcountl(bind_conf->thread_set.grps) : 1;
+                       shards = protocol_supports_flag(li->rx.proto, PROTO_F_REUSEPORT_SUPPORTED) ? my_popcountl(bind_conf->thread_set.grps) : 1;
 
                /* no more shards than total threads */
                if (shards > todo)
                        shards = todo;
 
                /* We also need to check if an explicit shards count was set and cannot be honored */
-               if (shards > 1 && !(li->rx.proto->flags & PROTO_F_REUSEPORT_SUPPORTED)) {
+               if (shards > 1 && !protocol_supports_flag(li->rx.proto, PROTO_F_REUSEPORT_SUPPORTED)) {
                        ha_warning("[%s:%d]: Disabling sharding for listener in %s '%s' because SO_REUSEPORT is disabled\n",
                                   bind_conf->file, bind_conf->line, proxy_type_str(fe), fe->id);
                        shards = 1;
index 7cc96743680345881da77b29e637d09515f0808b..c190a3664223b53619c890504d1ef10b0d49fb14 100644 (file)
@@ -83,6 +83,25 @@ void protocol_setf_all(uint flag)
        HA_SPIN_UNLOCK(PROTO_LOCK, &proto_lock);
 }
 
+/* Checks if protocol <proto> supports PROTO_F flag <flag>. Returns zero if not,
+ * non-zero if supported. It may return a cached value from a previous test,
+ * and may run live tests then update the proto's flags to cache a result. It's
+ * better to call it only if needed so that it doesn't result in modules being
+ * loaded in case of a live test. It is only supposed to be used during boot.
+ */
+int protocol_supports_flag(struct protocol *proto, uint flag)
+{
+       if (flag == PROTO_F_REUSEPORT_SUPPORTED) {
+               /* 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;
+       }
+       return 0;
+}
+
 /* binds all listeners of all registered protocols. Returns a composition
  * of ERR_NONE, ERR_RETRYABLE, ERR_FATAL.
  */