diff options
| author | Jo-Philipp Wich | 2022-02-04 19:34:06 +0000 |
|---|---|---|
| committer | Jo-Philipp Wich | 2022-02-04 19:34:06 +0000 |
| commit | 52831a00bec8e3676e2747029c0349f6be9c2593 (patch) | |
| tree | a8685e54fcce17fa04160b23c7e06b6bbe37051d | |
| parent | 7cb10c809314261c20ddca069eacd469adf44be3 (diff) | |
| download | firewall4-52831a00bec8e3676e2747029c0349f6be9c2593.tar.gz | |
fw4: improve flowtable handling
- Delete the flowtable while loading the rulset in case it exists already
since flowtable with offload flag canot overwrite ones without and vice
versa
- Resolve higher level devices such as 802.1q or bridge devices to lower,
offload capable ones in case hardware offloading is requested
- Revert disabling of "flow_offloading_hw" option
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
| -rw-r--r-- | root/usr/share/firewall4/main.uc | 77 | ||||
| -rw-r--r-- | root/usr/share/firewall4/templates/ruleset.uc | 3 | ||||
| -rw-r--r-- | root/usr/share/ucode/fw4.uc | 2 |
3 files changed, 77 insertions, 5 deletions
diff --git a/root/usr/share/firewall4/main.uc b/root/usr/share/firewall4/main.uc index d7dfdb0..839346b 100644 --- a/root/usr/share/firewall4/main.uc +++ b/root/usr/share/firewall4/main.uc @@ -1,6 +1,8 @@ {% let fw4 = require("fw4"); +let ubus = require("ubus"); +let fs = require("fs"); /* Find existing sets. * @@ -94,14 +96,81 @@ function reload_sets() { } } -function render_ruleset(use_statefile) { +function resolve_lower_devices(devstatus, devname) { + let dir = fs.opendir("/sys/class/net/" + devname); + let devs = []; + + if (dir) { + if (!devstatus || devstatus[devname]?.["hw-tc-offload"]) { + push(devs, devname); + } + else { + let e; + + while ((e = dir.read()) != null) + if (index(e, "lower_") === 0) + push(devs, ...resolve_lower_devices(devstatus, substr(e, 6))); + } + + dir.close(); + } + + return devs; +} + +function resolve_offload_devices() { + if (!fw4.default_option("flow_offloading")) + return []; + + let devstatus = null; let devices = []; - fw4.load(use_statefile); + if (fw4.default_option("flow_offloading_hw")) { + let bus = require("ubus").connect(); + + if (bus) { + devstatus = bus.call("network.device", "status") || {}; + bus.disconnect(); + } + } - map(fw4.zones(), zone => push(devices, ...zone.match_devices)); + for (let zone in fw4.zones()) + for (let device in zone.match_devices) + push(devices, ...resolve_lower_devices(devstatus, device)); + + return uniq(devices); +} + +function check_flowtable() { + let nft = fs.popen("nft --terse --json list flowtables inet"); + let info; + + if (nft) { + try { + info = json(nft.read("all")); + } + catch (e) { + info = {}; + } + + nft.close(); + } + + for (let item in info?.nftables) + if (item?.flowtable?.table == "fw4" && item?.flowtable?.name == "ft") + return true; + + return false; +} + +function render_ruleset(use_statefile) { + fw4.load(use_statefile); - include("templates/ruleset.uc", { fw4, type, exists, length, include, devices: sort(devices) }); + include("templates/ruleset.uc", { + fw4, type, exists, length, include, + devices: resolve_offload_devices(), + flowtable: check_flowtable() + }); } function lookup_network(net) { diff --git a/root/usr/share/firewall4/templates/ruleset.uc b/root/usr/share/firewall4/templates/ruleset.uc index 004cfca..8020bed 100644 --- a/root/usr/share/firewall4/templates/ruleset.uc +++ b/root/usr/share/firewall4/templates/ruleset.uc @@ -1,5 +1,8 @@ table inet fw4 flush table inet fw4 +{% if (flowtable): %} +delete flowtable inet fw4 ft +{% endif %} table inet fw4 { {% if (fw4.default_option("flow_offloading") && length(devices) > 0): %} diff --git a/root/usr/share/ucode/fw4.uc b/root/usr/share/ucode/fw4.uc index 7a2cd75..175883f 100644 --- a/root/usr/share/ucode/fw4.uc +++ b/root/usr/share/ucode/fw4.uc @@ -1695,7 +1695,7 @@ return { custom_chains: [ "bool", null, UNSUPPORTED ], disable_ipv6: [ "bool", null, UNSUPPORTED ], flow_offloading: [ "bool", "0" ], - flow_offloading_hw: [ "bool", "0", UNSUPPORTED ] + flow_offloading_hw: [ "bool", "0" ] }); if (defs.synflood_protect === null) |