fw4: filter non hw-offload capable devices when resolving lower devices
[project/firewall4.git] / root / usr / share / ucode / fw4.uc
index 12e0d8cfe2e092d94c60599da19e0dbb88b9358d..39e850741f75d294d9f3404b2f08b3c1a542eb0d 100644 (file)
@@ -356,53 +356,33 @@ function map_setmatch(set, match, proto) {
        return fields;
 }
 
-function determine_device_type(devname) {
-       let uevent = fs.open(`/sys/class/net/${devname}/uevent`),
-           devtype = null;
-
-       if (uevent) {
-               let line;
-
-               while ((line = uevent.read('line')) != null) {
-                       let m = match(line, /^DEVTYPE=(\w+)/);
-
-                       if (m) {
-                               devtype = m[1];
-                               break;
-                       }
-               }
-
-               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) {
+function resolve_lower_devices(devstatus, devname, require_hwoffload) {
+       let dir = fs.opendir(`/sys/class/net/${devname}`);
+       let devs = [];
+
+       if (dir) {
+               switch (devstatus[devname]?.devtype) {
+               case 'vlan':
+               case 'bridge':
                        let e;
 
                        while ((e = dir.read()) != null)
                                if (index(e, "lower_") === 0)
-                                       push(lower, ...resolve_lower_devices(substr(e, 6)));
+                                       push(devs, ...resolve_lower_devices(devstatus, substr(e, 6), require_hwoffload));
 
-                       dir.close();
-               }
+                       break;
+
+               default:
+                       if (!require_hwoffload || devstatus[devname]?.["hw-tc-offload"])
+                               push(devs, devname);
 
-               return lower;
+                       break;
+               }
 
-       default:
-               return [ devname ];
+               dir.close();
        }
+
+       return devs;
 }
 
 function nft_json_command(...args) {
@@ -460,24 +440,41 @@ return {
        },
 
        resolve_offload_devices: function() {
+               if (!this.default_option("flow_offloading"))
+                       return [];
+
+               let devstatus = null;
                let devices = [];
+               let bus = ubus.connect();
 
-               if (this.default_option("flow_offloading")) {
+               if (bus) {
+                       devstatus = bus.call("network.device", "status") || {};
+                       bus.disconnect();
+               }
+
+               if (this.default_option("flow_offloading_hw")) {
                        for (let zone in this.zones())
                                for (let device in zone.related_physdevs)
-                                       push(devices, ...resolve_lower_devices(device));
+                                       push(devices, ...resolve_lower_devices(devstatus, device, true));
 
                        if (length(devices)) {
                                devices = sort(uniq(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;
-                               }
+                               if (nft_try_hw_offload(devices))
+                                       return devices;
+
+                               this.warn('Hardware flow offloading unavailable, falling back to software offloading');
+                               this.state.defaults.flow_offloading_hw = false;
+
+                               devices = [];
                        }
                }
 
-               return devices;
+               for (let zone in this.zones())
+                       for (let device in zone.related_physdevs)
+                               push(devices, ...resolve_lower_devices(devstatus, device, false));
+
+               return sort(uniq(devices));
        },
 
        check_set_types: function() {