From: Felix Fietkau Date: Fri, 15 Sep 2023 18:30:04 +0000 (+0200) Subject: wireless: dynamically enable/disable virtual interfaces base on network interface... X-Git-Url: http://git.openwrt.org/?p=project%2Fnetifd.git;a=commitdiff_plain;h=afcd3825dad9b6a6712fbf6ed8e4434819a34009 wireless: dynamically enable/disable virtual interfaces base on network interface autostart This allows disabling individual interfaces with ifup/ifdown calls Signed-off-by: Felix Fietkau --- diff --git a/config.c b/config.c index 8f4a383..dbf4425 100644 --- a/config.c +++ b/config.c @@ -784,7 +784,7 @@ config_init_all(void) vlist_flush(&interfaces); interface_refresh_assignments(false); interface_start_pending(); - wireless_start_pending(); + wireless_start_pending(0); return ret; } diff --git a/interface.c b/interface.c index 66e0e80..a18e872 100644 --- a/interface.c +++ b/interface.c @@ -25,6 +25,7 @@ #include "ubus.h" #include "config.h" #include "system.h" +#include "wireless.h" struct vlist_tree interfaces; static LIST_HEAD(iface_all_users); @@ -1125,6 +1126,7 @@ interface_set_up(struct interface *iface) const char *error = NULL; iface->autostart = true; + wireless_check_network_enabled(); if (iface->state != IFS_DOWN) return; @@ -1157,6 +1159,7 @@ interface_set_down(struct interface *iface) __interface_set_down(iface, false); } else { iface->autostart = false; + wireless_check_network_enabled(); __interface_set_down(iface, false); } } diff --git a/wireless.c b/wireless.c index 958080e..a21bf54 100644 --- a/wireless.c +++ b/wireless.c @@ -198,6 +198,9 @@ prepare_config(struct wireless_device *wdev, struct blob_buf *buf, bool up) l = blobmsg_open_table(&b, "interfaces"); vlist_for_each_element(&wdev->interfaces, vif, node) { + if (vif->disabled) + continue; + i = blobmsg_open_table(&b, vif->name); vif_config_add_bridge(&b, vif->network, up); put_container(&b, vif->config, "config"); @@ -1522,19 +1525,78 @@ wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data, return 0; } -/* called on startup and by netifd reload() */ -void -wireless_start_pending(void) +static void +wdev_check_network_enabled(struct wireless_device *wdev) +{ + struct wireless_interface *vif; + struct interface *iface; + struct blob_attr *cur; + int 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; + + if (iface->autostart) { + enabled = 1; + break; + } + if (enabled != 1) + enabled = 0; + } + + if (vif->disabled == !enabled) + continue; + + vif->disabled = !enabled; + wdev->config_update = true; + } +} + +static void +__wireless_start_pending(struct uloop_timeout *t) { struct wireless_device *wdev; vlist_for_each_element(&wireless_devices, wdev, node) { + wdev_check_network_enabled(wdev); if (wdev->config_update) wdev_set_config_state(wdev, IFC_RELOAD); __wireless_device_set_up(wdev, 0); } } +void wireless_start_pending(int timeout) +{ + static struct uloop_timeout timer = { + .cb = __wireless_start_pending + }; + + if (timeout) { + uloop_timeout_set(&timer, timeout); + return; + } + + uloop_timeout_cancel(&timer); + timer.cb(&timer); +} + +void wireless_check_network_enabled(void) +{ + struct wireless_device *wdev; + + vlist_for_each_element(&wireless_devices, wdev, node) { + wdev_check_network_enabled(wdev); + + if (wdev->config_update) + wireless_start_pending(1000); + } +} + void wireless_device_hotplug_event(const char *name, bool add) { struct wireless_interface *vif; diff --git a/wireless.h b/wireless.h index eaf75f7..f8bbd2f 100644 --- a/wireless.h +++ b/wireless.h @@ -94,6 +94,7 @@ struct wireless_interface { int multicast_to_unicast; int vlan_idx; int sta_idx; + bool disabled; }; struct wireless_vlan { @@ -142,7 +143,8 @@ void wireless_station_create(struct wireless_interface *vif, struct blob_attr *d int wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data, struct ubus_request_data *req); -void wireless_start_pending(void); +void wireless_check_network_enabled(void); +void wireless_start_pending(int timeout); void wireless_init(void); void wireless_device_hotplug_event(const char *name, bool add);