wireless: reload wireless device if any vif network bridge changes ifindex
authorFelix Fietkau <nbd@nbd.name>
Sun, 6 Oct 2024 17:40:55 +0000 (19:40 +0200)
committerFelix Fietkau <nbd@nbd.name>
Sun, 6 Oct 2024 17:40:58 +0000 (19:40 +0200)
This fixes an issue where wireless vifs were not added back after the bridge
was recreated due to config changes (e.g. after switching to vlan filtering).

Signed-off-by: Felix Fietkau <nbd@nbd.name>
wireless.c
wireless.h

index 6cec78a1308d98fdb03d3a1eba310a7651c4faf3..c8b89453ad7d6d6c992924766102c11de15e9ac0 100644 (file)
@@ -337,12 +337,39 @@ static void wireless_device_set_mcast_to_unicast(struct device *dev, int val)
        dev->settings.flags |= DEV_OPT_MULTICAST_TO_UNICAST;
 }
 
+static void wireless_check_interface(struct blob_attr *list, int *enabled, int *ifindex)
+{
+       struct interface *iface;
+       struct blob_attr *cur;
+       size_t rem;
+
+       blobmsg_for_each_attr(cur, list, rem) {
+               struct device *mdev;
+
+               iface = vlist_find(&interfaces, blobmsg_get_string(cur), iface, node);
+               if (!iface)
+                       continue;
+
+               if (iface->autostart)
+                       *enabled = 1;
+               else if (*enabled != 1)
+                       *enabled = 0;
+
+               mdev = iface->main_dev.dev;
+               if (!mdev || !mdev->hotplug_ops)
+                       continue;
+
+               *ifindex = mdev->ifindex;
+       }
+}
+
 static void wireless_interface_handle_link(struct wireless_interface *vif, const char *ifname, bool up)
 {
        struct interface *iface;
        struct blob_attr *cur;
        const char *network;
        struct device *dev;
+       int enabled = -1;
        size_t rem;
 
        if (!vif->network || !vif->ifname)
@@ -372,6 +399,7 @@ static void wireless_interface_handle_link(struct wireless_interface *vif, const
        dev->bpdu_filter = dev->wireless_ap;
 
 out:
+       wireless_check_interface(vif->network, &enabled, &vif->network_ifindex);
        blobmsg_for_each_attr(cur, vif->network, rem) {
                network = blobmsg_data(cur);
 
@@ -388,6 +416,7 @@ static void wireless_vlan_handle_link(struct wireless_vlan *vlan, bool up)
        struct interface *iface;
        struct blob_attr *cur;
        const char *network;
+       int enabled = -1;
        size_t rem;
 
        if (!vlan->network || !vlan->ifname)
@@ -406,6 +435,7 @@ static void wireless_vlan_handle_link(struct wireless_vlan *vlan, bool up)
                }
        }
 
+       wireless_check_interface(vlan->network, &enabled, &vlan->network_ifindex);
        blobmsg_for_each_attr(cur, vlan->network, rem) {
                network = blobmsg_data(cur);
 
@@ -1560,34 +1590,42 @@ wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
        return 0;
 }
 
+static void
+wdev_vlan_check_network_enabled(struct wireless_device *wdev,
+                               struct wireless_interface *vif)
+{
+       struct wireless_vlan *vlan;
+
+       vlist_for_each_element(&vif->vlans, vlan, node) {
+               int enabled = -1, ifindex = -1;
+
+               wireless_check_interface(vlan->network, &enabled, &ifindex);
+
+               if (wdev->state != IFS_UP || vlan->network_ifindex == ifindex)
+                       continue;
+
+               vlan->network_ifindex = ifindex;
+               wdev->config_update = true;
+       }
+}
+
 static void
 wdev_check_network_enabled(struct wireless_device *wdev)
 {
        struct wireless_interface *vif;
-       struct interface *iface;
-       struct blob_attr *cur;
-       size_t rem;
 
        vlist_for_each_element(&wdev->interfaces, vif, node) {
-               int enabled = -1;
-
-               blobmsg_for_each_attr(cur, vif->network, rem) {
-                       iface = vlist_find(&interfaces, blobmsg_get_string(cur), iface, node);
-                       if (!iface)
-                               continue;
+               int enabled = -1, ifindex = -1;
 
-                       if (iface->autostart) {
-                               enabled = 1;
-                               break;
-                       }
-                       if (enabled != 1)
-                               enabled = 0;
-               }
+               wireless_check_interface(vif->network, &enabled, &ifindex);
+               wdev_vlan_check_network_enabled(wdev, vif);
 
-               if (vif->disabled == !enabled)
+               if (vif->disabled == !enabled &&
+                   (wdev->state != IFS_UP || vif->network_ifindex == ifindex))
                        continue;
 
                vif->disabled = !enabled;
+               vif->network_ifindex = ifindex;
                wdev->config_update = true;
        }
 }
index 705972392caec786fedd6c6ac31c09fedb365871..7a981e724a751c7ab991a7a6e0e747071b28e0ef 100644 (file)
@@ -96,6 +96,8 @@ struct wireless_interface {
        int vlan_idx;
        int sta_idx;
        bool disabled;
+
+       int network_ifindex;
 };
 
 struct wireless_vlan {
@@ -112,6 +114,8 @@ struct wireless_vlan {
        int multicast_to_unicast;
        bool isolate;
        bool bridge_isolate;
+
+       int network_ifindex;
 };
 
 struct wireless_station {