[OpenWrt-Devel] [PATCH netifd 2/5] wireless: serialize wireless interface configuration

Daniel Golle daniel at makrotopia.org
Wed Oct 30 11:56:27 EDT 2019


From: John Crispin <john at phrozen.org>

Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 wireless.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 wireless.h |  7 +++++++
 2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/wireless.c b/wireless.c
index 9986e9a..06afea3 100644
--- a/wireless.c
+++ b/wireless.c
@@ -23,6 +23,8 @@ struct vlist_tree wireless_devices;
 struct avl_tree wireless_drivers;
 static struct blob_buf b;
 static int drv_fd;
+static LIST_HEAD(handlers);
+static bool handler_pending;
 
 static const struct blobmsg_policy wdev_policy =
 	{ .name = "disabled", .type = BLOBMSG_TYPE_BOOL };
@@ -52,6 +54,15 @@ static const struct uci_blob_param_list vif_param = {
 	.params = vif_policy,
 };
 
+static void
+wireless_handler_stop(struct wireless_device *wdev)
+{
+	if (wdev->handler_pending) {
+		wdev->handler_pending = false;
+		list_del(&wdev->handler);
+	}
+}
+
 static void
 put_container(struct blob_buf *buf, struct blob_attr *attr, const char *name)
 {
@@ -188,6 +199,7 @@ wireless_device_free_state(struct wireless_device *wdev)
 {
 	struct wireless_interface *vif;
 
+	wireless_handler_stop(wdev);
 	uloop_timeout_cancel(&wdev->script_check);
 	uloop_timeout_cancel(&wdev->timeout);
 	wireless_complete_kill_request(wdev);
@@ -236,6 +248,7 @@ wireless_device_setup_cancel(struct wireless_device *wdev)
 	if (wdev->cancel)
 		return;
 
+	wireless_handler_stop(wdev);
 	D(WIRELESS, "Cancel wireless device '%s' setup\n", wdev->name);
 	wdev->cancel = true;
 	uloop_timeout_set(&wdev->timeout, 10 * 1000);
@@ -250,6 +263,17 @@ wireless_device_run_handler(struct wireless_device *wdev, bool up)
 	int i = 0;
 	int fds[2] = { -1, -1 };
 
+	wireless_handler_stop(wdev);
+
+	if (handler_pending && wdev->serialize) {
+		wdev->handler_action = up;
+		wdev->handler_pending = true;
+		list_add_tail(&wdev->handler, &handlers);
+		return;
+	}
+	if (wdev->serialize)
+		handler_pending = true;
+
 	D(WIRELESS, "Wireless device '%s' run %s handler\n", wdev->name, action);
 	if (!up && wdev->prev_config) {
 		config = blobmsg_format_json(wdev->prev_config, true);
@@ -281,6 +305,21 @@ wireless_device_run_handler(struct wireless_device *wdev, bool up)
 	free(config);
 }
 
+static void
+wireless_handler_next(void)
+{
+	struct wireless_device *wdev;
+
+	if (handler_pending)
+		return;
+	if (list_empty(&handlers))
+		return;
+	wdev = list_first_entry(&handlers, struct wireless_device, handler);
+	list_del(&wdev->handler);
+	wdev->handler_pending = false;
+	wireless_device_run_handler(wdev, wdev->handler_action);
+}
+
 static void
 __wireless_device_set_up(struct wireless_device *wdev, int force)
 {
@@ -305,6 +344,7 @@ __wireless_device_set_up(struct wireless_device *wdev, int force)
 static void
 wireless_device_free(struct wireless_device *wdev)
 {
+	wireless_handler_stop(wdev);
 	vlist_flush_all(&wdev->interfaces);
 	avl_delete(&wireless_devices.avl, &wdev->node.avl);
 	free(wdev->config);
@@ -353,6 +393,10 @@ wireless_device_setup_timeout(struct uloop_timeout *timeout)
 {
 	struct wireless_device *wdev = container_of(timeout, struct wireless_device, timeout);
 
+	if (wdev->handler_pending) {
+		wdev->handler_pending = false;
+		list_del(&wdev->handler);
+	}
 	netifd_kill_process(&wdev->script_task);
 	wdev->script_task.cb(&wdev->script_task, -1);
 	wireless_device_mark_down(wdev);
@@ -371,7 +415,7 @@ wireless_device_reconf(struct wireless_device *wdev)
 {
 	wdev->retry = WIRELESS_SETUP_RETRY;
 	wdev->autostart = true;
-	__wireless_device_set_up(wdev, 1);
+	__wireless_device_set_up(wdev, wdev->reconf && (wdev->state == IFS_UP));
 }
 
 static void
@@ -433,6 +477,11 @@ wireless_device_script_task_cb(struct netifd_process *proc, int ret)
 	default:
 		break;
 	}
+
+	if (wdev->serialize) {
+		handler_pending = false;
+		wireless_handler_next();
+	}
 }
 
 void
@@ -452,7 +501,7 @@ wdev_set_config_state(struct wireless_device *wdev, enum interface_config_state
 	wdev->config_state = s;
 	if (wdev->state == IFS_DOWN)
 		wdev_handle_config_change(wdev);
-	else
+	else if (!wdev->reconf || wdev->state != IFS_UP)
 		__wireless_device_set_down(wdev);
 }
 
@@ -501,6 +550,7 @@ wdev_update(struct vlist_tree *tree, struct vlist_node *node_new,
 	struct wireless_device *wd_new = container_of(node_new, struct wireless_device, node);
 
 	if (wd_old && wd_new) {
+		D(WIRELESS, "Update wireless device '%s'\n", wd_old->name);
 		wdev_change_config(wd_old, wd_new);
 	} else if (wd_old) {
 		D(WIRELESS, "Delete wireless device '%s'\n", wd_old->name);
@@ -698,6 +748,9 @@ wireless_device_create(struct wireless_driver *drv, const char *name, struct blo
 	wdev->config_state = IFC_NORMAL;
 	wdev->name = strcpy(name_buf, name);
 	wdev->config = data;
+	wdev->handler_pending = false;
+	wdev->serialize = true;
+	wdev->reconf = true;
 	wdev->retry_setup_failed = false;
 	wdev->autostart = true;
 	INIT_LIST_HEAD(&wdev->script_proc);
diff --git a/wireless.h b/wireless.h
index bade738..f734770 100644
--- a/wireless.h
+++ b/wireless.h
@@ -15,6 +15,7 @@
 #define __NETIFD_WIRELESS_H
 
 #include <libubox/utils.h>
+#include <libubox/list.h>
 #include "interface.h"
 
 extern struct vlist_tree wireless_devices;
@@ -35,6 +36,11 @@ struct wireless_driver {
 struct wireless_device {
 	struct vlist_node node;
 
+	struct list_head handler;
+	bool handler_action;
+	bool handler_pending;
+	bool serialize;
+
 	struct wireless_driver *drv;
 	struct vlist_tree interfaces;
 	char *name;
@@ -59,6 +65,7 @@ struct wireless_device {
 
 	enum interface_state state;
 	enum interface_config_state config_state;
+	bool reconf;
 	bool cancel;
 	int retry;
 
-- 
2.23.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list