From 57984e0369974e3cf5830db4dfe5e93e8c494b09 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 9 May 2022 10:51:03 +0200 Subject: [PATCH] fw4: always resolve lower flowtable devices Do not restrict lower device resolving to hardware flow offloading, it is required for software flow offloading as well. While we're at it, also refactor and simplify the code to not require ubus runtime state for device resolving anymore. Fixes: #9854 Signed-off-by: Jo-Philipp Wich --- root/usr/share/ucode/fw4.uc | 85 +++++++++++++++++-------------- tests/01_configuration/01_ruleset | 6 +-- 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/root/usr/share/ucode/fw4.uc b/root/usr/share/ucode/fw4.uc index 76360c8..12e0d8c 100644 --- a/root/usr/share/ucode/fw4.uc +++ b/root/usr/share/ucode/fw4.uc @@ -356,26 +356,53 @@ function map_setmatch(set, match, proto) { return fields; } -function resolve_lower_devices(devstatus, devname) { - let dir = fs.opendir(`/sys/class/net/${devname}`); - let devs = []; +function determine_device_type(devname) { + let uevent = fs.open(`/sys/class/net/${devname}/uevent`), + devtype = null; - if (dir) { - if (!devstatus || devstatus[devname]?.["hw-tc-offload"]) { - push(devs, devname); + if (uevent) { + let line; + + while ((line = uevent.read('line')) != null) { + let m = match(line, /^DEVTYPE=(\w+)/); + + if (m) { + devtype = m[1]; + break; + } } - else { + + uevent.close(); + } + + return devtype; +} + +function resolve_lower_devices(devname) { + switch (determine_device_type(devname)) { + case null: + return []; + + case 'vlan': + case 'bridge': + let dir = fs.opendir(`/sys/class/net/${devname}`); + let lower = []; + + if (dir) { let e; while ((e = dir.read()) != null) if (index(e, "lower_") === 0) - push(devs, ...resolve_lower_devices(devstatus, substr(e, 6))); + push(lower, ...resolve_lower_devices(substr(e, 6))); + + dir.close(); } - dir.close(); - } + return lower; - return devs; + default: + return [ devname ]; + } } function nft_json_command(...args) { @@ -433,40 +460,24 @@ return { }, resolve_offload_devices: function() { - if (!this.default_option("flow_offloading")) - return []; - - let devstatus = null; let devices = []; - if (this.default_option("flow_offloading_hw")) { - let bus = ubus.connect(); - - if (bus) { - devstatus = bus.call("network.device", "status") || {}; - bus.disconnect(); - } - + if (this.default_option("flow_offloading")) { for (let zone in this.zones()) for (let device in zone.related_physdevs) - push(devices, ...resolve_lower_devices(devstatus, device)); - - devices = uniq(devices); - - if (nft_try_hw_offload(devices)) - return devices; + push(devices, ...resolve_lower_devices(device)); - this.warn('Hardware flow offloading unavailable, falling back to software offloading'); - this.state.defaults.flow_offloading_hw = false; + if (length(devices)) { + devices = sort(uniq(devices)); - devices = []; + if (this.default_option("flow_offloading_hw") && !nft_try_hw_offload(devices)) { + this.warn('Hardware flow offloading unavailable, falling back to software offloading'); + this.state.defaults.flow_offloading_hw = false; + } + } } - for (let zone in this.zones()) - for (let device in zone.match_devices) - push(devices, ...resolve_lower_devices(null, device)); - - return uniq(devices); + return devices; }, check_set_types: function() { diff --git a/tests/01_configuration/01_ruleset b/tests/01_configuration/01_ruleset index 65cddd1..fa0e7a4 100644 --- a/tests/01_configuration/01_ruleset +++ b/tests/01_configuration/01_ruleset @@ -296,10 +296,10 @@ table inet fw4 { [!] Section @defaults[0] specifies unknown option 'unknown_defaults_option' [!] Section @rule[9] (Test-Deprecated-Rule-Option) option '_name' is deprecated by fw4 [!] Section @rule[9] (Test-Deprecated-Rule-Option) specifies unknown option 'unknown_rule_option' -[call] ctx.call object method args +[call] fs.open path mode [call] fs.opendir path -[call] fs.opendir path -[call] fs.opendir path +[call] fs.open path mode +[call] fs.open path mode [call] system command