summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2025-01-16 11:35:47 +0000
committerFelix Fietkau2025-01-17 08:49:18 +0000
commit27520027e10e9d247e822e5c52a8bb294267ecd9 (patch)
treec927b584c19dc9de26cf3573de45fc036828138b
parent99a855121c74974123558fd0ebad7888242c88af (diff)
downloadopenwrt-27520027e10e9d247e822e5c52a8bb294267ecd9.tar.gz
netifd: improve packet steering on ipq40xx (and possibly others)
Some platforms a single ethernet device for all ports with multiple rx rings and NAPI threading enabled. In this case, the steering script was limiting performance by keeping all NAPI threads assigned to the same CPU. Fix this by assigning each rx queue and the corresponding NAPI task separately. Additionally, if the number of rx queues is at least as big as the number of CPUs, skip weight based assignment and distribute the load across all CPUs directly. Fixes: https://github.com/openwrt/openwrt/issues/17611 Signed-off-by: Felix Fietkau <nbd@nbd.name> (cherry picked from commit acce25b789d40f2d88a2326a7d9921bd1743fe54)
-rwxr-xr-xpackage/network/config/netifd/files/usr/libexec/network/packet-steering.uc51
1 files changed, 47 insertions, 4 deletions
diff --git a/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc b/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc
index b2229e5d79..34df46d18e 100755
--- a/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc
+++ b/package/network/config/netifd/files/usr/libexec/network/packet-steering.uc
@@ -65,8 +65,9 @@ function cpu_mask(cpu)
return sprintf("%x", mask);
}
-function set_netdev_cpu(dev, cpu) {
- let queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`);
+function set_netdev_cpu(dev, cpu, rx_queue) {
+ rx_queue ??= "rx-*";
+ let queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_cpus`);
let val = cpu_mask(cpu);
if (disable)
val = 0;
@@ -76,7 +77,7 @@ function set_netdev_cpu(dev, cpu) {
if (!do_nothing)
writefile(queue, `${val}`);
}
- queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_flow_cnt`);
+ queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_flow_cnt`);
for (let queue in queues) {
if (debug || do_nothing)
warn(`echo ${local_flows} > ${queue}\n`);
@@ -160,6 +161,9 @@ for (let dev in netdevs) {
netdev: [],
phy: [],
tasks: [],
+ rx_tasks: [],
+ rx_queues: map(glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`),
+ (v) => basename(dirname(v))),
};
}
@@ -187,11 +191,51 @@ for (let path in glob("/proc/*/exe")) {
continue;
push(dev.tasks, pid);
+
+ let napi_match = match(name, /napi\/([^-]*)-(\d+)/);
+ if (napi_match && napi_match[2] > 0)
+ push(dev.rx_tasks, pid);
break;
}
}
+function assign_dev_queues_cpu(dev) {
+ let num = length(dev.rx_queues);
+ if (num < length(dev.rx_tasks))
+ num = length(dev.rx_tasks);
+
+ for (let i = 0; i < num; i++) {
+ let cpu;
+
+ let task = dev.rx_tasks[i];
+ if (num >= length(cpus))
+ cpu = i % length(cpus);
+ else if (task)
+ cpu = get_next_cpu(napi_weight);
+ else
+ cpu = -1;
+ set_task_cpu(task, cpu);
+
+ let rxq = dev.rx_queues[i];
+ if (!rxq)
+ continue;
+
+ if (num >= length(cpus))
+ cpu = (i + 1) % length(cpus);
+ else if (all_cpus)
+ cpu = -1;
+ else
+ cpu = get_next_cpu(napi_weight, cpu);
+ for (let netdev in dev.netdev)
+ set_netdev_cpu(netdev, cpu, rxq);
+ }
+}
+
function assign_dev_cpu(dev) {
+ if (length(dev.rx_queues) > 1 &&
+ length(dev.rx_tasks) > 1)
+ return assign_dev_queues_cpu(dev);
+
if (length(dev.tasks) > 0) {
let cpu = dev.napi_cpu = get_next_cpu(napi_weight);
for (let task in dev.tasks)
@@ -204,7 +248,6 @@ function assign_dev_cpu(dev) {
cpu = -1;
else
cpu = get_next_cpu(rx_weight, dev.napi_cpu);
- dev.rx_cpu = cpu;
for (let netdev in dev.netdev)
set_netdev_cpu(netdev, cpu);
}