summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJo-Philipp Wich2022-02-04 19:34:06 +0000
committerJo-Philipp Wich2022-02-04 19:34:06 +0000
commit52831a00bec8e3676e2747029c0349f6be9c2593 (patch)
treea8685e54fcce17fa04160b23c7e06b6bbe37051d
parent7cb10c809314261c20ddca069eacd469adf44be3 (diff)
downloadfirewall4-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.uc77
-rw-r--r--root/usr/share/firewall4/templates/ruleset.uc3
-rw-r--r--root/usr/share/ucode/fw4.uc2
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)