MINOR: protocol: add a function to check if some features are supported

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.
diff --git a/include/haproxy/protocol.h b/include/haproxy/protocol.h
index 5c0871a..828093d 100644
--- a/include/haproxy/protocol.h
+++ b/include/haproxy/protocol.h
@@ -44,6 +44,14 @@
 /* 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.
  */
diff --git a/src/listener.c b/src/listener.c
index 45595cc..994e97a 100644
--- a/src/listener.c
+++ b/src/listener.c
@@ -1669,7 +1669,7 @@
 
 		/* 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 @@
 			}
 		}
 		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;
diff --git a/src/protocol.c b/src/protocol.c
index 7cc9674..c190a36 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -83,6 +83,25 @@
 	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.
  */