]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cpu-topo: implement a CPU sorting mechanism by cluster ID
authorWilly Tarreau <w@1wt.eu>
Fri, 10 Jan 2025 18:32:02 +0000 (19:32 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 14 Mar 2025 17:30:31 +0000 (18:30 +0100)
This will be used to detect and fix incorrect setups which report
the same cluster ID for multiple L3 instances.

The arrangement of functions in this file is becoming a real problem.
Maybe we should move all this to cpu_topo for example, and better
distinguish OS-specific and generic code.

include/haproxy/cpu_topo.h
src/cpu_topo.c

index 5271af3ec654c94a3c9b4944ed2c48c68064eb79..a48fee015ec742a98d633a14b21b006893da155b 100644 (file)
@@ -51,10 +51,14 @@ void cpu_reorder_by_locality(struct ha_cpu_topo *topo, int entries);
  */
 void cpu_reorder_by_index(struct ha_cpu_topo *topo, int entries);
 
+/* re-order a CPU topology array by cluster id. */
+void cpu_reorder_by_cluster(struct ha_cpu_topo *topo, int entries);
+
 /* Functions used by qsort to compare hardware CPUs (not meant to be used from
  * outside cpu_topo).
  */
 int _cmp_cpu_index(const void *a, const void *b);
 int _cmp_cpu_locality(const void *a, const void *b);
+int _cmp_cpu_cluster(const void *a, const void *b);
 
 #endif /* _HAPROXY_CPU_TOPO_H */
index d0bf266e58d800cdb8ecc2e849c9d1913ff6bd37..b464f09d7a19b2f39331999ba6460dfc6ce769e0 100644 (file)
@@ -322,6 +322,62 @@ int _cmp_cpu_locality(const void *a, const void *b)
        return 0;
 }
 
+/* function used by qsort to compare two hwcpus and arrange them by cluster to
+ * make sure no cluster crosses L3 boundaries. -1 says a<b, 1 says a>b. It's
+ * only used during topology detection.
+ */
+int _cmp_cpu_cluster(const void *a, const void *b)
+{
+       const struct ha_cpu_topo *l = (const struct ha_cpu_topo *)a;
+       const struct ha_cpu_topo *r = (const struct ha_cpu_topo *)b;
+
+       /* first, online vs offline */
+       if (!(l->st & HA_CPU_F_EXCL_MASK) && (r->st & HA_CPU_F_EXCL_MASK))
+               return -1;
+
+       if (!(r->st & HA_CPU_F_EXCL_MASK) && (l->st & HA_CPU_F_EXCL_MASK))
+               return 1;
+
+       /* next, cluster */
+       if (l->cl_gid >= 0 && l->cl_gid < r->cl_gid)
+               return -1;
+       if (l->cl_gid > r->cl_gid && r->cl_gid >= 0)
+               return  1;
+
+       /* next, package ID */
+       if (l->pk_id >= 0 && l->pk_id < r->pk_id)
+               return -1;
+       if (l->pk_id > r->pk_id && r->pk_id >= 0)
+               return  1;
+
+       /* next, node ID */
+       if (l->no_id >= 0 && l->no_id < r->no_id)
+               return -1;
+       if (l->no_id > r->no_id && r->no_id >= 0)
+               return  1;
+
+       /* next, L3 */
+       if (l->ca_id[3] >= 0 && l->ca_id[3] < r->ca_id[3])
+               return -1;
+       if (l->ca_id[3] > r->ca_id[3] && r->ca_id[3] >= 0)
+               return  1;
+
+       /* if no L3, then L2 */
+       if (l->ca_id[2] >= 0 && l->ca_id[2] < r->ca_id[2])
+               return -1;
+       if (l->ca_id[2] > r->ca_id[2] && r->ca_id[2] >= 0)
+               return  1;
+
+       /* next, IDX, so that SMT ordering is preserved */
+       if (l->idx >= 0 && l->idx < r->idx)
+               return -1;
+       if (l->idx > r->idx && r->idx >= 0)
+               return  1;
+
+       /* exactly the same (e.g. absent) */
+       return 0;
+}
+
 /* re-order a CPU topology array by CPU index only. This is mostly used before
  * listing CPUs regardless of their characteristics.
  */
@@ -336,6 +392,12 @@ void cpu_reorder_by_locality(struct ha_cpu_topo *topo, int entries)
        qsort(topo, entries, sizeof(*topo), _cmp_cpu_locality);
 }
 
+/* re-order a CPU topology array by cluster id. */
+void cpu_reorder_by_cluster(struct ha_cpu_topo *topo, int entries)
+{
+       qsort(topo, entries, sizeof(*topo), _cmp_cpu_cluster);
+}
+
 /* returns an optimal maxcpus for the current system. It will take into
  * account what is reported by the OS, if any, otherwise will fall back
  * to the cpuset size, which serves as an upper limit in any case.