udev/net: add IRQAffinityNUMA= option for NUMA-aware filtering

Add support for filtering IRQ affinity to CPUs on a specific NUMA node
via the new IRQAffinityNUMA= option in .link files. The option accepts:
- "local": use the NUMA node local to the NIC's PCIe slot
- Explicit node number (0, 1, 2, ...): use CPUs on the specified node

When both IRQAffinity= and IRQAffinityNUMA= are specified, their
intersection is used. If the intersection is empty, an error is logged
and IRQ affinity configuration is skipped.

When "local" is specified but the device's NUMA node cannot be
determined (numa_node shows -1), a warning is logged and IRQ affinity
configuration is skipped.
This commit is contained in:
Quentin Deslandes
2026-05-20 11:39:11 +02:00
parent a9e821549b
commit 7dfbbfb90d
6 changed files with 298 additions and 12 deletions
+17 -10
View File
@@ -89,6 +89,22 @@ int apply_numa_policy(const NUMAPolicy *policy) {
return 0;
}
int numa_node_get_cpus(size_t node, CPUSet *ret) {
char p[STRLEN("/sys/devices/system/node/node//cpulist") + DECIMAL_STR_MAX(size_t) + 1];
_cleanup_free_ char *cpulist = NULL;
int r;
assert(ret);
xsprintf(p, "/sys/devices/system/node/node%zu/cpulist", node);
r = read_virtual_file(p, SIZE_MAX, &cpulist, /* ret_size= */ NULL);
if (r < 0)
return r;
return parse_cpu_set(cpulist, ret);
}
int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) {
_cleanup_(cpu_set_done) CPUSet s = {};
int r;
@@ -97,20 +113,11 @@ int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret) {
assert(ret);
for (size_t i = 0; i < policy->nodes.allocated * 8; i++) {
_cleanup_free_ char *l = NULL;
char p[STRLEN("/sys/devices/system/node/node//cpulist") + DECIMAL_STR_MAX(size_t) + 1];
if (!CPU_ISSET_S(i, policy->nodes.allocated, policy->nodes.set))
continue;
xsprintf(p, "/sys/devices/system/node/node%zu/cpulist", i);
r = read_one_line_file(p, &l);
if (r < 0)
return r;
_cleanup_(cpu_set_done) CPUSet part = {};
r = parse_cpu_set(l, &part);
r = numa_node_get_cpus(i, &part);
if (r < 0)
return r;
+1
View File
@@ -29,6 +29,7 @@ static inline void numa_policy_reset(NUMAPolicy *p) {
}
int apply_numa_policy(const NUMAPolicy *policy);
int numa_node_get_cpus(size_t node, CPUSet *ret);
int numa_to_cpu_set(const NUMAPolicy *policy, CPUSet *ret);
int numa_get_node_from_cpu(unsigned cpu, unsigned *ret);