fw4: always resolve lower flowtable devices
authorJo-Philipp Wich <jo@mein.io>
Mon, 9 May 2022 08:51:03 +0000 (10:51 +0200)
committerJo-Philipp Wich <jo@mein.io>
Mon, 9 May 2022 08:54:18 +0000 (10:54 +0200)
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 <jo@mein.io>
root/usr/share/ucode/fw4.uc
tests/01_configuration/01_ruleset

index 76360c8294e1b49e1e4a3e9a9bfbdff6c8cd194c..12e0d8cfe2e092d94c60599da19e0dbb88b9358d 100644 (file)
@@ -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() {
index 65cddd174292f5e34d721f6dbcc306bf5695025f..fa0e7a48eb0046fd57fb940457059f3282c25b30 100644 (file)
@@ -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 <network.device> method <status> args <null>
+[call] fs.open path </sys/class/net/br-lan/uevent> mode <null>
 [call] fs.opendir path </sys/class/net/br-lan>
-[call] fs.opendir path </sys/class/net/eth0>
-[call] fs.opendir path </sys/class/net/eth1>
+[call] fs.open path </sys/class/net/eth0/uevent> mode <null>
+[call] fs.open path </sys/class/net/eth1/uevent> mode <null>
 [call] system command </usr/sbin/nft -c '
                add table inet fw4-hw-offload-test;
                add flowtable inet fw4-hw-offload-test ft {