Initial commit
Some checks failed
Build Kernel / Build all affected Kernels (push) Has been cancelled
Build all core packages / Build all core packages for selected target (push) Has been cancelled
Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
Build Toolchains / Build Toolchains for each target (push) Has been cancelled
Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
Coverity scan build / Coverity x86/64 build (push) Has been cancelled
Some checks failed
Build Kernel / Build all affected Kernels (push) Has been cancelled
Build all core packages / Build all core packages for selected target (push) Has been cancelled
Build and Push prebuilt tools container / Build and Push all prebuilt containers (push) Has been cancelled
Build Toolchains / Build Toolchains for each target (push) Has been cancelled
Build host tools / Build host tools for linux and macos based systems (push) Has been cancelled
Coverity scan build / Coverity x86/64 build (push) Has been cancelled
This commit is contained in:
236
package/network/config/netifd/files/usr/libexec/network/packet-steering.uc
Executable file
236
package/network/config/netifd/files/usr/libexec/network/packet-steering.uc
Executable file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { glob, basename, dirname, readlink, readfile, realpath, writefile, error, open } from "fs";
|
||||
|
||||
let napi_weight = 1.0;
|
||||
let cpu_thread_weight = 0.75;
|
||||
let rx_weight = 0.75;
|
||||
let eth_bias = 2.0;
|
||||
let debug = 0, do_nothing = 0;
|
||||
let disable;
|
||||
let cpus;
|
||||
let all_cpus;
|
||||
let local_flows = 0;
|
||||
|
||||
while (length(ARGV) > 0) {
|
||||
let arg = shift(ARGV);
|
||||
switch (arg) {
|
||||
case "-d":
|
||||
debug++;
|
||||
break;
|
||||
case "-n":
|
||||
do_nothing++;
|
||||
break;
|
||||
case '0':
|
||||
disable = true;
|
||||
break;
|
||||
case '2':
|
||||
all_cpus = true;
|
||||
break;
|
||||
case '-l':
|
||||
local_flows = +shift(ARGV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function task_name(pid)
|
||||
{
|
||||
let stat = open(`/proc/${pid}/status`, "r");
|
||||
if (!stat)
|
||||
return;
|
||||
let line = stat.read("line");
|
||||
stat.close();
|
||||
return trim(split(line, "\t", 2)[1]);
|
||||
}
|
||||
|
||||
function set_task_cpu(pid, cpu) {
|
||||
if (disable)
|
||||
cpu = join(",", map(cpus, (cpu) => cpu.id));
|
||||
let name = task_name(pid);
|
||||
if (!name)
|
||||
return;
|
||||
if (debug || do_nothing)
|
||||
warn(`taskset -p -c ${cpu} ${name}\n`);
|
||||
if (!do_nothing)
|
||||
system(`taskset -p -c ${cpu} ${pid}`);
|
||||
}
|
||||
|
||||
function cpu_mask(cpu)
|
||||
{
|
||||
let mask;
|
||||
if (cpu < 0)
|
||||
mask = (1 << length(cpus)) - 1;
|
||||
else
|
||||
mask = (1 << int(cpu));
|
||||
return sprintf("%x", mask);
|
||||
}
|
||||
|
||||
function set_netdev_cpu(dev, cpu) {
|
||||
let queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`);
|
||||
let val = cpu_mask(cpu);
|
||||
if (disable)
|
||||
val = 0;
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${val} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${val}`);
|
||||
}
|
||||
queues = glob(`/sys/class/net/${dev}/queues/rx-*/rps_flow_cnt`);
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${local_flows} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${local_flows}`);
|
||||
}
|
||||
}
|
||||
|
||||
function task_device_match(name, device)
|
||||
{
|
||||
let napi_match = match(name, /napi\/([^-+])-\d+/);
|
||||
if (!napi_match)
|
||||
napi_match = match(name, /mt76-tx (phy\d+)/);
|
||||
if (napi_match &&
|
||||
(index(device.phy, napi_match[1]) >= 0 ||
|
||||
index(device.netdev, napi_match[1]) >= 0))
|
||||
return true;
|
||||
|
||||
if (device.driver == "mtk_soc_eth" && match(name, /napi\/mtk_eth-/))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
cpus = map(glob("/sys/bus/cpu/devices/*"), (path) => {
|
||||
return {
|
||||
id: int(match(path, /.*cpu(\d+)/)[1]),
|
||||
core: int(trim(readfile(`${path}/topology/core_id`))),
|
||||
load: 0.0,
|
||||
};
|
||||
});
|
||||
|
||||
cpus = slice(cpus, 0, 64);
|
||||
if (length(cpus) < 2)
|
||||
exit(0);
|
||||
|
||||
function cpu_add_weight(cpu_id, weight)
|
||||
{
|
||||
let cpu = cpus[cpu_id];
|
||||
cpu.load += weight;
|
||||
for (let sibling in cpus) {
|
||||
if (sibling == cpu || sibling.core != cpu.core)
|
||||
continue;
|
||||
sibling.load += weight * cpu_thread_weight;
|
||||
}
|
||||
}
|
||||
|
||||
function get_next_cpu(weight, prev_cpu)
|
||||
{
|
||||
if (disable)
|
||||
return 0;
|
||||
|
||||
let sort_cpus = sort(slice(cpus), (a, b) => a.load - b.load);
|
||||
let idx = 0;
|
||||
|
||||
if (prev_cpu != null && sort_cpus[idx].id == prev_cpu)
|
||||
idx++;
|
||||
|
||||
let cpu = sort_cpus[idx].id;
|
||||
cpu_add_weight(cpu, weight);
|
||||
return cpu;
|
||||
}
|
||||
|
||||
let phys_devs = {};
|
||||
let netdev_phys = {};
|
||||
let netdevs = map(glob("/sys/class/net/*"), (dev) => basename(dev));
|
||||
|
||||
for (let dev in netdevs) {
|
||||
let pdev_path = realpath(`/sys/class/net/${dev}/device`);
|
||||
if (!pdev_path)
|
||||
continue;
|
||||
|
||||
if (length(glob(`/sys/class/net/${dev}/lower_*`)) > 0)
|
||||
continue;
|
||||
|
||||
let pdev = phys_devs[pdev_path];
|
||||
if (!pdev) {
|
||||
pdev = phys_devs[pdev_path] = {
|
||||
path: pdev_path,
|
||||
driver: basename(readlink(`${pdev_path}/driver`)),
|
||||
netdev: [],
|
||||
phy: [],
|
||||
tasks: [],
|
||||
};
|
||||
}
|
||||
|
||||
let phyidx = trim(readfile(`/sys/class/net/${dev}/phy80211/index`));
|
||||
if (phyidx != null) {
|
||||
let phy = `phy${phyidx}`;
|
||||
if (index(pdev.phy, phy) < 0)
|
||||
push(pdev.phy, phy);
|
||||
}
|
||||
|
||||
push(pdev.netdev, dev);
|
||||
netdev_phys[dev] = pdev;
|
||||
}
|
||||
|
||||
for (let path in glob("/proc/*/exe")) {
|
||||
readlink(path);
|
||||
if (error() != "No such file or directory")
|
||||
continue;
|
||||
|
||||
let pid = basename(dirname(path));
|
||||
let name = task_name(pid);
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!task_device_match(name, dev))
|
||||
continue;
|
||||
|
||||
push(dev.tasks, pid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function assign_dev_cpu(dev) {
|
||||
if (length(dev.tasks) > 0) {
|
||||
let cpu = dev.napi_cpu = get_next_cpu(napi_weight);
|
||||
for (let task in dev.tasks)
|
||||
set_task_cpu(task, cpu);
|
||||
}
|
||||
|
||||
if (length(dev.netdev) > 0) {
|
||||
let cpu;
|
||||
if (all_cpus)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign ethernet devices first
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.phy))
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
// Add bias to avoid assigning other tasks to CPUs with ethernet NAPI
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.tasks) || dev.napi_cpu == null)
|
||||
continue;
|
||||
cpu_add_weight(dev.napi_cpu, eth_bias);
|
||||
}
|
||||
|
||||
// Assign WLAN devices
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (length(dev.phy) > 0)
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
if (debug > 1)
|
||||
warn(sprintf("devices: %.J\ncpus: %.J\n", phys_devs, cpus));
|
||||
57
package/network/config/netifd/files/usr/share/udhcpc/default.script
Executable file
57
package/network/config/netifd/files/usr/share/udhcpc/default.script
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
|
||||
|
||||
set_classless_routes() {
|
||||
local max=128
|
||||
local type
|
||||
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
|
||||
[ ${1##*/} -eq 32 ] && type=host || type=net
|
||||
echo "udhcpc: adding route for $type $1 via $2"
|
||||
route add -$type "$1" gw "$2" dev "$interface"
|
||||
max=$(($max-1))
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
setup_interface() {
|
||||
echo "udhcpc: ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface"
|
||||
ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface
|
||||
|
||||
[ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && {
|
||||
echo "udhcpc: setting default routers: $router"
|
||||
|
||||
local valid_gw=""
|
||||
for i in $router ; do
|
||||
route add default gw $i dev $interface
|
||||
valid_gw="${valid_gw:+$valid_gw|}$i"
|
||||
done
|
||||
|
||||
eval $(route -n | awk '
|
||||
/^0.0.0.0\W{9}('$valid_gw')\W/ {next}
|
||||
/^0.0.0.0/ {print "route del -net "$1" gw "$2";"}
|
||||
')
|
||||
}
|
||||
|
||||
# CIDR STATIC ROUTES (rfc3442)
|
||||
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
|
||||
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
|
||||
}
|
||||
|
||||
|
||||
applied=
|
||||
case "$1" in
|
||||
deconfig)
|
||||
ip -4 addr flush dev "$interface"
|
||||
;;
|
||||
renew)
|
||||
setup_interface update
|
||||
;;
|
||||
bound)
|
||||
setup_interface ifup
|
||||
;;
|
||||
esac
|
||||
|
||||
# user rules
|
||||
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user