diff options
| author | Felix Fietkau | 2023-09-15 18:30:04 +0000 |
|---|---|---|
| committer | Felix Fietkau | 2023-09-15 18:30:05 +0000 |
| commit | afcd3825dad9b6a6712fbf6ed8e4434819a34009 (patch) | |
| tree | f41ae0effbd04b086f10094d827f0e6a83b2d5f1 | |
| parent | 88a3a9e2be07c5a5521d336f8dab485a089a346c (diff) | |
| download | netifd-afcd3825dad9b6a6712fbf6ed8e4434819a34009.tar.gz | |
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 <nbd@nbd.name>
| -rw-r--r-- | config.c | 2 | ||||
| -rw-r--r-- | interface.c | 3 | ||||
| -rw-r--r-- | wireless.c | 68 | ||||
| -rw-r--r-- | wireless.h | 4 |
4 files changed, 72 insertions, 5 deletions
@@ -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); } } @@ -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; @@ -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); |