mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 17:42:41 +00:00
1600 lines
50 KiB
Diff
1600 lines
50 KiB
Diff
From f5e2764d23b0f7273b5a25490e67cdbaaeded8af Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <john@phrozen.org>
|
|
Date: Sat, 20 Jun 2020 16:27:12 +0200
|
|
Subject: [PATCH 01/40] netifd: several backports required by ipq807x
|
|
|
|
IPQ807x uses the mac80211.sh/hostapd.sh from owrt HEAD, which require
|
|
these patches.
|
|
|
|
Signed-off-by: John Crispin <john@phrozen.org>
|
|
---
|
|
...add-support-for-tracking-wifi-vlan-s.patch | 703 ++++++++++++++++++
|
|
...add-support-for-tracking-wifi-statio.patch | 427 +++++++++++
|
|
...s-method-for-reloading-configuration.patch | 123 +++
|
|
...conf-opt-in-and-allow-serializing-co.patch | 249 +++++++
|
|
.../0005-netifd-fix-wdev-data-lifetime.patch | 42 ++
|
|
5 files changed, 1544 insertions(+)
|
|
create mode 100644 package/network/config/netifd/patches/0001-netifd-wireless-add-support-for-tracking-wifi-vlan-s.patch
|
|
create mode 100644 package/network/config/netifd/patches/0002-netifd-wireless-add-support-for-tracking-wifi-statio.patch
|
|
create mode 100644 package/network/config/netifd/patches/0003-wireless-add-ubus-method-for-reloading-configuration.patch
|
|
create mode 100644 package/network/config/netifd/patches/0004-wireless-make-reconf-opt-in-and-allow-serializing-co.patch
|
|
create mode 100644 package/network/config/netifd/patches/0005-netifd-fix-wdev-data-lifetime.patch
|
|
|
|
diff --git a/package/network/config/netifd/patches/0001-netifd-wireless-add-support-for-tracking-wifi-vlan-s.patch b/package/network/config/netifd/patches/0001-netifd-wireless-add-support-for-tracking-wifi-vlan-s.patch
|
|
new file mode 100644
|
|
index 0000000000..48185fc16c
|
|
--- /dev/null
|
|
+++ b/package/network/config/netifd/patches/0001-netifd-wireless-add-support-for-tracking-wifi-vlan-s.patch
|
|
@@ -0,0 +1,703 @@
|
|
+From 4ce33cee34e413f69082a80a833f3ed1baf8a761 Mon Sep 17 00:00:00 2001
|
|
+From: John Crispin <john@phrozen.org>
|
|
+Date: Mon, 25 May 2020 11:49:18 +0200
|
|
+Subject: [PATCH 1/2] netifd: wireless: add support for tracking wifi-vlan
|
|
+ sections
|
|
+
|
|
+This new section allows us to create apvlan settings for hostapd.
|
|
+
|
|
+Signed-off-by: John Crispin <john@phrozen.org>
|
|
+---
|
|
+ config.c | 42 ++++++-
|
|
+ scripts/netifd-wireless.sh | 42 ++++++-
|
|
+ wireless.c | 247 +++++++++++++++++++++++++++++++++++--
|
|
+ wireless.h | 23 +++-
|
|
+ 4 files changed, 337 insertions(+), 17 deletions(-)
|
|
+
|
|
+diff --git a/config.c b/config.c
|
|
+index 843c53f..1bb3737 100644
|
|
+--- a/config.c
|
|
++++ b/config.c
|
|
+@@ -338,7 +338,7 @@ config_parse_wireless_device(struct uci_section *s)
|
|
+ wireless_device_create(drv, s->e.name, b.head);
|
|
+ }
|
|
+
|
|
+-static void
|
|
++static struct wireless_interface*
|
|
+ config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section *s)
|
|
+ {
|
|
+ char *name;
|
|
+@@ -348,7 +348,20 @@ config_parse_wireless_interface(struct wireless_device *wdev, struct uci_section
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ uci_to_blob(&b, s, wdev->drv->interface.config);
|
|
+- wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
|
|
++ return wireless_interface_create(wdev, b.head, s->anonymous ? name : s->e.name);
|
|
++}
|
|
++
|
|
++static void
|
|
++config_parse_wireless_vlan(struct wireless_device *wdev, char *vif, struct uci_section *s)
|
|
++{
|
|
++ char *name;
|
|
++
|
|
++ name = alloca(strlen(s->type) + 16);
|
|
++ sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
|
++
|
|
++ blob_buf_init(&b, 0);
|
|
++ uci_to_blob(&b, s, wdev->drv->vlan.config);
|
|
++ wireless_vlan_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
|
|
+ }
|
|
+
|
|
+ static void
|
|
+@@ -378,10 +391,14 @@ config_init_wireless(void)
|
|
+ vlist_for_each_element(&wireless_devices, wdev, node) {
|
|
+ wdev->vif_idx = 0;
|
|
+ vlist_update(&wdev->interfaces);
|
|
++ wdev->vlan_idx = 0;
|
|
++ vlist_update(&wdev->vlans);
|
|
+ }
|
|
+
|
|
+ uci_foreach_element(&uci_wireless->sections, e) {
|
|
+ struct uci_section *s = uci_to_section(e);
|
|
++ struct wireless_interface *vif;
|
|
++ struct uci_element *f;
|
|
+
|
|
+ if (strcmp(s->type, "wifi-iface") != 0)
|
|
+ continue;
|
|
+@@ -396,11 +413,28 @@ config_init_wireless(void)
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+- config_parse_wireless_interface(wdev, s);
|
|
++ vif = config_parse_wireless_interface(wdev, s);
|
|
++
|
|
++ if (!vif || s->anonymous)
|
|
++ continue;
|
|
++ uci_foreach_element(&uci_wireless->sections, f) {
|
|
++ struct uci_section *s = uci_to_section(f);
|
|
++ const char *vif_name;
|
|
++
|
|
++ if (strcmp(s->type, "wifi-vlan") != 0)
|
|
++ continue;
|
|
++
|
|
++ vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
|
|
++ if (vif_name && strcmp(e->name, vif_name))
|
|
++ continue;
|
|
++ config_parse_wireless_vlan(wdev, vif->name, s);
|
|
++ }
|
|
+ }
|
|
+
|
|
+- vlist_for_each_element(&wireless_devices, wdev, node)
|
|
++ vlist_for_each_element(&wireless_devices, wdev, node) {
|
|
+ vlist_flush(&wdev->interfaces);
|
|
++ vlist_flush(&wdev->vlans);
|
|
++ }
|
|
+ }
|
|
+
|
|
+ int
|
|
+diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh
|
|
+index 6bc48c6..41e380f 100644
|
|
+--- a/scripts/netifd-wireless.sh
|
|
++++ b/scripts/netifd-wireless.sh
|
|
+@@ -108,12 +108,13 @@ _wdev_wrapper() {
|
|
+
|
|
+ _wdev_notify_init() {
|
|
+ local command="$1"
|
|
+- local interface="$2"
|
|
++ local name="$2"
|
|
++ local value="$3"
|
|
+
|
|
+ json_init
|
|
+ json_add_int "command" "$command"
|
|
+ json_add_string "device" "$__netifd_device"
|
|
+- [ -n "$interface" ] && json_add_string "interface" "$interface"
|
|
++ [ -n "$name" -a -n "$value" ] && json_add_string "$name" "$value"
|
|
+ json_add_object "data"
|
|
+ }
|
|
+
|
|
+@@ -139,7 +140,17 @@ _wireless_add_vif() {
|
|
+ local name="$1"; shift
|
|
+ local ifname="$1"; shift
|
|
+
|
|
+- _wdev_notify_init $CMD_SET_DATA "$name"
|
|
++ _wdev_notify_init $CMD_SET_DATA "interface" "$name"
|
|
++ json_add_string "ifname" "$ifname"
|
|
++ _wdev_add_variables "$@"
|
|
++ _wdev_notify
|
|
++}
|
|
++
|
|
++_wireless_add_vlan() {
|
|
++ local name="$1"; shift
|
|
++ local ifname="$1"; shift
|
|
++
|
|
++ _wdev_notify_init $CMD_SET_DATA "vlan" "$name"
|
|
+ json_add_string "ifname" "$ifname"
|
|
+ _wdev_add_variables "$@"
|
|
+ _wdev_notify
|
|
+@@ -182,6 +193,7 @@ _wireless_set_retry() {
|
|
+
|
|
+ _wdev_wrapper \
|
|
+ wireless_add_vif \
|
|
++ wireless_add_vlan \
|
|
+ wireless_set_up \
|
|
+ wireless_set_data \
|
|
+ wireless_add_process \
|
|
+@@ -306,6 +318,21 @@ for_each_interface() {
|
|
+ json_select ..
|
|
+ }
|
|
+
|
|
++for_each_vlan() {
|
|
++ local _w_vlans _w_vlan
|
|
++
|
|
++ json_get_keys _w_vlans vlans
|
|
++ json_select vlans
|
|
++ for _w_vlan in $_w_vlans; do
|
|
++ json_select "$_w_vlan"
|
|
++ json_select config
|
|
++ "$@" "$_w_vlan"
|
|
++ json_select ..
|
|
++ json_select ..
|
|
++ done
|
|
++ json_select ..
|
|
++}
|
|
++
|
|
+ _wdev_common_device_config() {
|
|
+ config_add_string channel hwmode htmode noscan
|
|
+ }
|
|
+@@ -314,6 +341,10 @@ _wdev_common_iface_config() {
|
|
+ config_add_string mode ssid encryption 'key:wpakey'
|
|
+ }
|
|
+
|
|
++_wdev_common_vlan_config() {
|
|
++ config_add_string name vid iface
|
|
++}
|
|
++
|
|
+ init_wireless_driver() {
|
|
+ name="$1"; shift
|
|
+ cmd="$1"; shift
|
|
+@@ -336,6 +367,11 @@ init_wireless_driver() {
|
|
+ eval "drv_$1_init_iface_config"
|
|
+ json_close_array
|
|
+
|
|
++ json_add_array vlan
|
|
++ _wdev_common_vlan_config
|
|
++ eval "drv_$1_init_vlan_config"
|
|
++ json_close_array
|
|
++
|
|
+ json_dump
|
|
+ }
|
|
+ ;;
|
|
+diff --git a/wireless.c b/wireless.c
|
|
+index c8e196f..b0b35a1 100644
|
|
+--- a/wireless.c
|
|
++++ b/wireless.c
|
|
+@@ -64,6 +64,24 @@ static const struct uci_blob_param_list vif_param = {
|
|
+ .params = vif_policy,
|
|
+ };
|
|
+
|
|
++enum {
|
|
++ VLAN_ATTR_DISABLED,
|
|
++ VLAN_ATTR_NETWORK,
|
|
++ VLAN_ATTR_ISOLATE,
|
|
++ __VLAN_ATTR_MAX,
|
|
++};
|
|
++
|
|
++static const struct blobmsg_policy vlan_policy[__VLAN_ATTR_MAX] = {
|
|
++ [VLAN_ATTR_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL },
|
|
++ [VLAN_ATTR_NETWORK] = { .name = "network", .type = BLOBMSG_TYPE_ARRAY },
|
|
++ [VLAN_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL },
|
|
++};
|
|
++
|
|
++static const struct uci_blob_param_list vlan_param = {
|
|
++ .n_params = ARRAY_SIZE(vlan_policy),
|
|
++ .params = vlan_policy,
|
|
++};
|
|
++
|
|
+ static void
|
|
+ wireless_handler_stop(struct wireless_device *wdev)
|
|
+ {
|
|
+@@ -125,7 +143,8 @@ static void
|
|
+ prepare_config(struct wireless_device *wdev, struct blob_buf *buf, bool up)
|
|
+ {
|
|
+ struct wireless_interface *vif;
|
|
+- void *l, *i;
|
|
++ struct wireless_vlan *vlan;
|
|
++ void *l, *i, *j, *k;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ put_container(&b, wdev->config, "config");
|
|
+@@ -139,9 +158,23 @@ prepare_config(struct wireless_device *wdev, struct blob_buf *buf, bool up)
|
|
+ put_container(&b, vif->config, "config");
|
|
+ if (vif->data)
|
|
+ blobmsg_add_blob(&b, vif->data);
|
|
++
|
|
++ j = blobmsg_open_table(&b, "vlans");
|
|
++ vlist_for_each_element(&wdev->vlans, vlan, node) {
|
|
++ if (strcmp(vlan->vif, vif->name))
|
|
++ continue;
|
|
++ k = blobmsg_open_table(&b, vlan->name);
|
|
++ vif_config_add_bridge(&b, vlan->network, up);
|
|
++ put_container(&b, vlan->config, "config");
|
|
++ if (vlan->data)
|
|
++ blobmsg_add_blob(&b, vlan->data);
|
|
++ blobmsg_close_table(&b, k);
|
|
++ }
|
|
++ blobmsg_close_table(&b, j);
|
|
+ blobmsg_close_table(&b, i);
|
|
+ }
|
|
+ blobmsg_close_table(&b, l);
|
|
++
|
|
+ }
|
|
+
|
|
+ static bool
|
|
+@@ -208,6 +241,7 @@ static void
|
|
+ wireless_device_free_state(struct wireless_device *wdev)
|
|
+ {
|
|
+ struct wireless_interface *vif;
|
|
++ struct wireless_vlan *vlan;
|
|
+
|
|
+ wireless_handler_stop(wdev);
|
|
+ uloop_timeout_cancel(&wdev->script_check);
|
|
+@@ -220,6 +254,11 @@ wireless_device_free_state(struct wireless_device *wdev)
|
|
+ vif->data = NULL;
|
|
+ vif->ifname = NULL;
|
|
+ }
|
|
++ vlist_for_each_element(&wdev->vlans, vlan, node) {
|
|
++ free(vlan->data);
|
|
++ vlan->data = NULL;
|
|
++ vlan->ifname = NULL;
|
|
++ }
|
|
+ }
|
|
+
|
|
+ static void wireless_interface_handle_link(struct wireless_interface *vif, bool up)
|
|
+@@ -252,6 +291,36 @@ static void wireless_interface_handle_link(struct wireless_interface *vif, bool
|
|
+ }
|
|
+ }
|
|
+
|
|
++static void wireless_vlan_handle_link(struct wireless_vlan *vlan, bool up)
|
|
++{
|
|
++ struct interface *iface;
|
|
++ struct blob_attr *cur;
|
|
++ const char *network;
|
|
++ int rem;
|
|
++
|
|
++ if (!vlan->network || !vlan->ifname)
|
|
++ return;
|
|
++
|
|
++ if (up) {
|
|
++ struct device *dev = device_get(vlan->ifname, 2);
|
|
++ if (dev) {
|
|
++ dev->wireless_isolate = vlan->isolate;
|
|
++ dev->wireless = true;
|
|
++ dev->wireless_ap = true;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ blobmsg_for_each_attr(cur, vlan->network, rem) {
|
|
++ network = blobmsg_data(cur);
|
|
++
|
|
++ iface = vlist_find(&interfaces, network, iface, node);
|
|
++ if (!iface)
|
|
++ continue;
|
|
++
|
|
++ interface_handle_link(iface, vlan->ifname, up, true);
|
|
++ }
|
|
++}
|
|
++
|
|
+ static void
|
|
+ wireless_device_setup_cancel(struct wireless_device *wdev)
|
|
+ {
|
|
+@@ -356,6 +425,7 @@ wireless_device_free(struct wireless_device *wdev)
|
|
+ {
|
|
+ wireless_handler_stop(wdev);
|
|
+ vlist_flush_all(&wdev->interfaces);
|
|
++ vlist_flush_all(&wdev->vlans);
|
|
+ avl_delete(&wireless_devices.avl, &wdev->node.avl);
|
|
+ free(wdev->config);
|
|
+ free(wdev->prev_config);
|
|
+@@ -384,9 +454,13 @@ static void
|
|
+ wireless_device_mark_down(struct wireless_device *wdev)
|
|
+ {
|
|
+ struct wireless_interface *vif;
|
|
++ struct wireless_vlan *vlan;
|
|
+
|
|
+ D(WIRELESS, "Wireless device '%s' is now down\n", wdev->name);
|
|
+
|
|
++ vlist_for_each_element(&wdev->vlans, vlan, node)
|
|
++ wireless_vlan_handle_link(vlan, false);
|
|
++
|
|
+ vlist_for_each_element(&wdev->interfaces, vif, node)
|
|
+ wireless_interface_handle_link(vif, false);
|
|
+
|
|
+@@ -447,6 +521,7 @@ static void
|
|
+ wireless_device_mark_up(struct wireless_device *wdev)
|
|
+ {
|
|
+ struct wireless_interface *vif;
|
|
++ struct wireless_vlan *vlan;
|
|
+
|
|
+ if (wdev->cancel) {
|
|
+ wdev->cancel = false;
|
|
+@@ -458,6 +533,8 @@ wireless_device_mark_up(struct wireless_device *wdev)
|
|
+ wdev->state = IFS_UP;
|
|
+ vlist_for_each_element(&wdev->interfaces, vif, node)
|
|
+ wireless_interface_handle_link(vif, true);
|
|
++ vlist_for_each_element(&wdev->vlans, vlan, node)
|
|
++ wireless_vlan_handle_link(vlan, true);
|
|
+ }
|
|
+
|
|
+ static void
|
|
+@@ -576,18 +653,20 @@ wireless_add_handler(const char *script, const char *name, json_object *obj)
|
|
+ {
|
|
+ struct wireless_driver *drv;
|
|
+ char *name_str, *script_str;
|
|
+- json_object *dev_config_obj, *iface_config_obj;
|
|
+- struct uci_blob_param_list *dev_config, *iface_config;
|
|
++ json_object *dev_config_obj, *iface_config_obj, *vlan_config_obj;
|
|
++ struct uci_blob_param_list *dev_config, *iface_config, *vlan_config;
|
|
+
|
|
+ dev_config_obj = json_get_field(obj, "device", json_type_array);
|
|
+ iface_config_obj = json_get_field(obj, "iface", json_type_array);
|
|
++ vlan_config_obj = json_get_field(obj, "vlan", json_type_array);
|
|
+
|
|
+- if (!dev_config_obj || !iface_config_obj)
|
|
++ if (!dev_config_obj || !iface_config_obj || !vlan_config_obj)
|
|
+ return;
|
|
+
|
|
+ drv = calloc_a(sizeof(*drv),
|
|
+ &dev_config, sizeof(*dev_config) + sizeof(void *),
|
|
+ &iface_config, sizeof(*iface_config) + sizeof(void *),
|
|
++ &vlan_config, sizeof(*vlan_config) + sizeof(void *),
|
|
+ &name_str, strlen(name) + 1,
|
|
+ &script_str, strlen(script) + 1);
|
|
+
|
|
+@@ -602,8 +681,13 @@ wireless_add_handler(const char *script, const char *name, json_object *obj)
|
|
+ iface_config->next[0] = &vif_param;
|
|
+ drv->interface.config = iface_config;
|
|
+
|
|
++ vlan_config->n_next = 1;
|
|
++ vlan_config->next[0] = &vlan_param;
|
|
++ drv->vlan.config = vlan_config;
|
|
++
|
|
+ drv->device.buf = netifd_handler_parse_config(drv->device.config, dev_config_obj);
|
|
+ drv->interface.buf = netifd_handler_parse_config(drv->interface.config, iface_config_obj);
|
|
++ drv->vlan.buf = netifd_handler_parse_config(drv->vlan.config, vlan_config_obj);
|
|
+
|
|
+ drv->node.key = drv->name;
|
|
+ avl_insert(&wireless_drivers, &drv->node);
|
|
+@@ -690,6 +774,67 @@ vif_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
|
+ wdev_set_config_state(wdev, IFC_RELOAD);
|
|
+ }
|
|
+
|
|
++static void
|
|
++wireless_vlan_init_config(struct wireless_vlan *vlan)
|
|
++{
|
|
++ struct blob_attr *tb[__VLAN_ATTR_MAX];
|
|
++ struct blob_attr *cur;
|
|
++
|
|
++ vlan->network = NULL;
|
|
++ blobmsg_parse(vlan_policy, __VLAN_ATTR_MAX, tb, blob_data(vlan->config), blob_len(vlan->config));
|
|
++
|
|
++ if ((cur = tb[VLAN_ATTR_NETWORK]))
|
|
++ vlan->network = cur;
|
|
++
|
|
++ cur = tb[VLAN_ATTR_ISOLATE];
|
|
++ if (cur)
|
|
++ vlan->isolate = blobmsg_get_bool(cur);
|
|
++}
|
|
++
|
|
++static void
|
|
++vlan_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
|
++ struct vlist_node *node_old)
|
|
++{
|
|
++ struct wireless_vlan *vlan_old = container_of(node_old, struct wireless_vlan, node);
|
|
++ struct wireless_vlan *vlan_new = container_of(node_new, struct wireless_vlan, node);
|
|
++ struct wireless_device *wdev;
|
|
++
|
|
++ if (vlan_old)
|
|
++ wdev = vlan_old->wdev;
|
|
++ else
|
|
++ wdev = vlan_new->wdev;
|
|
++
|
|
++ if (vlan_old && vlan_new) {
|
|
++ free((void *) vlan_old->section);
|
|
++ vlan_old->section = strdup(vlan_new->section);
|
|
++ if (blob_attr_equal(vlan_old->config, vlan_new->config)) {
|
|
++ free(vlan_new);
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ D(WIRELESS, "Update wireless vlan %s on device %s\n", vlan_new->name, wdev->name);
|
|
++ wireless_vlan_handle_link(vlan_old, false);
|
|
++ free(vlan_old->config);
|
|
++ vlan_old->config = blob_memdup(vlan_new->config);
|
|
++ vlan_old->isolate = vlan_new->isolate;
|
|
++ wireless_vlan_init_config(vlan_old);
|
|
++ free(vlan_new);
|
|
++ } else if (vlan_new) {
|
|
++ D(WIRELESS, "Create new wireless vlan %s on device %s\n", vlan_new->name, wdev->name);
|
|
++ vlan_new->section = strdup(vlan_new->section);
|
|
++ vlan_new->config = blob_memdup(vlan_new->config);
|
|
++ wireless_vlan_init_config(vlan_new);
|
|
++ } else if (vlan_old) {
|
|
++ D(WIRELESS, "Delete wireless interface %s on device %s\n", vlan_old->name, wdev->name);
|
|
++ wireless_vlan_handle_link(vlan_old, false);
|
|
++ free((void *) vlan_old->section);
|
|
++ free(vlan_old->config);
|
|
++ free(vlan_old);
|
|
++ }
|
|
++
|
|
++ wdev_set_config_state(wdev, IFC_RELOAD);
|
|
++}
|
|
++
|
|
+ static void
|
|
+ wireless_proc_poll_fd(struct uloop_fd *fd, unsigned int events)
|
|
+ {
|
|
+@@ -774,6 +919,8 @@ wireless_device_create(struct wireless_driver *drv, const char *name, struct blo
|
|
+ INIT_LIST_HEAD(&wdev->script_proc);
|
|
+ vlist_init(&wdev->interfaces, avl_strcmp, vif_update);
|
|
+ wdev->interfaces.keep_old = true;
|
|
++ vlist_init(&wdev->vlans, avl_strcmp, vlan_update);
|
|
++ wdev->vlans.keep_old = true;
|
|
+
|
|
+ wdev->timeout.cb = wireless_device_setup_timeout;
|
|
+ wdev->script_task.cb = wireless_device_script_task_cb;
|
|
+@@ -788,7 +935,51 @@ wireless_device_create(struct wireless_driver *drv, const char *name, struct blo
|
|
+ vlist_add(&wireless_devices, &wdev->node, wdev->name);
|
|
+ }
|
|
+
|
|
+-void wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section)
|
|
++void
|
|
++wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section)
|
|
++{
|
|
++ struct wireless_vlan *vlan;
|
|
++ struct blob_attr *tb[__VLAN_ATTR_MAX];
|
|
++ struct blob_attr *cur;
|
|
++ char *name_buf, *vif_buf;
|
|
++ char name[8];
|
|
++
|
|
++ blobmsg_parse(vlan_policy, __VLAN_ATTR_MAX, tb, blob_data(data), blob_len(data));
|
|
++
|
|
++ cur = tb[VLAN_ATTR_DISABLED];
|
|
++ if (cur && blobmsg_get_bool(cur))
|
|
++ return;
|
|
++
|
|
++ sprintf(name, "%d", wdev->vlan_idx++);
|
|
++
|
|
++ vlan = calloc_a(sizeof(*vlan),
|
|
++ &name_buf, strlen(name) + 1,
|
|
++ &vif_buf, strlen(vif) + 1);
|
|
++ vlan->name = strcpy(name_buf, name);
|
|
++ vlan->vif = strcpy(vif_buf, vif);
|
|
++ vlan->wdev = wdev;
|
|
++ vlan->config = data;
|
|
++ vlan->section = section;
|
|
++ vlan->isolate = false;
|
|
++
|
|
++ vlist_add(&wdev->vlans, &vlan->node, vlan->name);
|
|
++}
|
|
++
|
|
++static void
|
|
++wireless_vlan_status(struct wireless_vlan *vlan, struct blob_buf *b)
|
|
++{
|
|
++ void *i;
|
|
++
|
|
++ i = blobmsg_open_table(b, NULL);
|
|
++ if (vlan->section)
|
|
++ blobmsg_add_string(b, "section", vlan->section);
|
|
++ if (vlan->ifname)
|
|
++ blobmsg_add_string(b, "ifname", vlan->ifname);
|
|
++ put_container(b, vlan->config, "config");
|
|
++ blobmsg_close_table(b, i);
|
|
++}
|
|
++
|
|
++struct wireless_interface* wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section)
|
|
+ {
|
|
+ struct wireless_interface *vif;
|
|
+ struct blob_attr *tb[__VIF_ATTR_MAX];
|
|
+@@ -800,7 +991,7 @@ void wireless_interface_create(struct wireless_device *wdev, struct blob_attr *d
|
|
+
|
|
+ cur = tb[VIF_ATTR_DISABLED];
|
|
+ if (cur && blobmsg_get_bool(cur))
|
|
+- return;
|
|
++ return NULL;
|
|
+
|
|
+ sprintf(name, "%d", wdev->vif_idx++);
|
|
+
|
|
+@@ -813,12 +1004,14 @@ void wireless_interface_create(struct wireless_device *wdev, struct blob_attr *d
|
|
+ vif->isolate = false;
|
|
+
|
|
+ vlist_add(&wdev->interfaces, &vif->node, vif->name);
|
|
++ return vif;
|
|
+ }
|
|
+
|
|
+ static void
|
|
+ wireless_interface_status(struct wireless_interface *iface, struct blob_buf *b)
|
|
+ {
|
|
+- void *i;
|
|
++ struct wireless_vlan *vlan;
|
|
++ void *i, *j;
|
|
+
|
|
+ i = blobmsg_open_table(b, NULL);
|
|
+ if (iface->section)
|
|
+@@ -826,6 +1019,11 @@ wireless_interface_status(struct wireless_interface *iface, struct blob_buf *b)
|
|
+ if (iface->ifname)
|
|
+ blobmsg_add_string(b, "ifname", iface->ifname);
|
|
+ put_container(b, iface->config, "config");
|
|
++ j = blobmsg_open_array(b, "vlans");
|
|
++ vlist_for_each_element(&iface->wdev->vlans, vlan, node)
|
|
++ if (!strcmp(iface->name, vlan->vif))
|
|
++ wireless_vlan_status(vlan, b);
|
|
++ blobmsg_close_array(b, j);
|
|
+ blobmsg_close_table(b, i);
|
|
+ }
|
|
+
|
|
+@@ -894,6 +1092,26 @@ wireless_interface_set_data(struct wireless_interface *vif)
|
|
+ vif->ifname = blobmsg_data(cur);
|
|
+ }
|
|
+
|
|
++static void
|
|
++wireless_vlan_set_data(struct wireless_vlan *vlan)
|
|
++{
|
|
++ enum {
|
|
++ VLAN_DATA_IFNAME,
|
|
++ __VLAN_DATA_MAX,
|
|
++ };
|
|
++ static const struct blobmsg_policy data_policy[__VLAN_DATA_MAX] = {
|
|
++ [VLAN_DATA_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
|
|
++ };
|
|
++ struct blob_attr *tb[__VLAN_DATA_MAX];
|
|
++ struct blob_attr *cur;
|
|
++
|
|
++ blobmsg_parse(data_policy, __VLAN_DATA_MAX, tb,
|
|
++ blobmsg_data(vlan->data), blobmsg_data_len(vlan->data));
|
|
++
|
|
++ if ((cur = tb[VLAN_DATA_IFNAME]))
|
|
++ vlan->ifname = blobmsg_data(cur);
|
|
++}
|
|
++
|
|
+ static int
|
|
+ wireless_device_add_process(struct wireless_device *wdev, struct blob_attr *data)
|
|
+ {
|
|
+@@ -1011,15 +1229,18 @@ wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
|
+ enum {
|
|
+ NOTIFY_ATTR_COMMAND,
|
|
+ NOTIFY_ATTR_VIF,
|
|
++ NOTIFY_ATTR_VLAN,
|
|
+ NOTIFY_ATTR_DATA,
|
|
+ __NOTIFY_MAX,
|
|
+ };
|
|
+ static const struct blobmsg_policy notify_policy[__NOTIFY_MAX] = {
|
|
+ [NOTIFY_ATTR_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_INT32 },
|
|
+ [NOTIFY_ATTR_VIF] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
|
|
++ [NOTIFY_ATTR_VLAN] = { .name = "vlan", .type = BLOBMSG_TYPE_STRING },
|
|
+ [NOTIFY_ATTR_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE },
|
|
+ };
|
|
+ struct wireless_interface *vif = NULL;
|
|
++ struct wireless_vlan *vlan = NULL;
|
|
+ struct blob_attr *tb[__NOTIFY_MAX];
|
|
+ struct blob_attr *cur, **pdata;
|
|
+
|
|
+@@ -1034,13 +1255,19 @@ wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
|
+ return UBUS_STATUS_NOT_FOUND;
|
|
+ }
|
|
+
|
|
++ if ((cur = tb[NOTIFY_ATTR_VLAN]) != NULL) {
|
|
++ vlan = vlist_find(&wdev->vlans, blobmsg_data(cur), vlan, node);
|
|
++ if (!vlan)
|
|
++ return UBUS_STATUS_NOT_FOUND;
|
|
++ }
|
|
++
|
|
+ cur = tb[NOTIFY_ATTR_DATA];
|
|
+ if (!cur)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ switch (blobmsg_get_u32(tb[NOTIFY_ATTR_COMMAND])) {
|
|
+ case NOTIFY_CMD_UP:
|
|
+- if (vif)
|
|
++ if (vif || vlan)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (wdev->state != IFS_SETUP)
|
|
+@@ -1051,6 +1278,8 @@ wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
|
+ case NOTIFY_CMD_SET_DATA:
|
|
+ if (vif)
|
|
+ pdata = &vif->data;
|
|
++ else if (vlan)
|
|
++ pdata = &vlan->data;
|
|
+ else
|
|
+ pdata = &wdev->data;
|
|
+
|
|
+@@ -1060,6 +1289,8 @@ wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
|
+ *pdata = blob_memdup(cur);
|
|
+ if (vif)
|
|
+ wireless_interface_set_data(vif);
|
|
++ else if (vlan)
|
|
++ wireless_vlan_set_data(vlan);
|
|
+ break;
|
|
+ case NOTIFY_CMD_PROCESS_ADD:
|
|
+ return wireless_device_add_process(wdev, cur);
|
|
+diff --git a/wireless.h b/wireless.h
|
|
+index f734770..8d0a1f0 100644
|
|
+--- a/wireless.h
|
|
++++ b/wireless.h
|
|
+@@ -30,7 +30,7 @@ struct wireless_driver {
|
|
+ struct {
|
|
+ char *buf;
|
|
+ struct uci_blob_param_list *config;
|
|
+- } device, interface;
|
|
++ } device, interface, vlan;
|
|
+ };
|
|
+
|
|
+ struct wireless_device {
|
|
+@@ -43,6 +43,7 @@ struct wireless_device {
|
|
+
|
|
+ struct wireless_driver *drv;
|
|
+ struct vlist_tree interfaces;
|
|
++ struct vlist_tree vlans;
|
|
+ char *name;
|
|
+
|
|
+ struct netifd_process script_task;
|
|
+@@ -70,6 +71,7 @@ struct wireless_device {
|
|
+ int retry;
|
|
+
|
|
+ int vif_idx;
|
|
++ int vlan_idx;
|
|
+ };
|
|
+
|
|
+ struct wireless_interface {
|
|
+@@ -88,6 +90,22 @@ struct wireless_interface {
|
|
+ bool ap_mode;
|
|
+ };
|
|
+
|
|
++struct wireless_vlan {
|
|
++ struct vlist_node node;
|
|
++ const char *section;
|
|
++ char *name;
|
|
++
|
|
++ struct wireless_device *wdev;
|
|
++ char *vif;
|
|
++
|
|
++ struct blob_attr *config;
|
|
++ struct blob_attr *data;
|
|
++
|
|
++ const char *ifname;
|
|
++ struct blob_attr *network;
|
|
++ bool isolate;
|
|
++};
|
|
++
|
|
+ struct wireless_process {
|
|
+ struct list_head list;
|
|
+
|
|
+@@ -103,7 +121,8 @@ void wireless_device_set_down(struct wireless_device *wdev);
|
|
+ void wireless_device_reconf(struct wireless_device *wdev);
|
|
+ void wireless_device_status(struct wireless_device *wdev, struct blob_buf *b);
|
|
+ void wireless_device_get_validate(struct wireless_device *wdev, struct blob_buf *b);
|
|
+-void wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section);
|
|
++struct wireless_interface* wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section);
|
|
++void wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section);
|
|
+ int wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
|
+ struct ubus_request_data *req);
|
|
+
|
|
+--
|
|
+2.20.1
|
|
+
|
|
diff --git a/package/network/config/netifd/patches/0002-netifd-wireless-add-support-for-tracking-wifi-statio.patch b/package/network/config/netifd/patches/0002-netifd-wireless-add-support-for-tracking-wifi-statio.patch
|
|
new file mode 100644
|
|
index 0000000000..d849fb09e0
|
|
--- /dev/null
|
|
+++ b/package/network/config/netifd/patches/0002-netifd-wireless-add-support-for-tracking-wifi-statio.patch
|
|
@@ -0,0 +1,427 @@
|
|
+From a56b457656218e5b6142b6238286ea54801ac4b2 Mon Sep 17 00:00:00 2001
|
|
+From: John Crispin <john@phrozen.org>
|
|
+Date: Mon, 25 May 2020 11:49:19 +0200
|
|
+Subject: [PATCH 2/2] netifd: wireless: add support for tracking wifi-station
|
|
+ sections
|
|
+
|
|
+This new section allows us to assign mac specific key/vid settings to a
|
|
+station.
|
|
+
|
|
+Signed-off-by: John Crispin <john@phrozen.org>
|
|
+---
|
|
+ config.c | 29 ++++++++
|
|
+ scripts/netifd-wireless.sh | 24 +++++++
|
|
+ wireless.c | 134 ++++++++++++++++++++++++++++++++++++-
|
|
+ wireless.h | 17 ++++-
|
|
+ 4 files changed, 200 insertions(+), 4 deletions(-)
|
|
+
|
|
+diff --git a/config.c b/config.c
|
|
+index 1bb3737..b1b4bf3 100644
|
|
+--- a/config.c
|
|
++++ b/config.c
|
|
+@@ -364,6 +364,19 @@ config_parse_wireless_vlan(struct wireless_device *wdev, char *vif, struct uci_s
|
|
+ wireless_vlan_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
|
|
+ }
|
|
+
|
|
++static void
|
|
++config_parse_wireless_station(struct wireless_device *wdev, char *vif, struct uci_section *s)
|
|
++{
|
|
++ char *name;
|
|
++
|
|
++ name = alloca(strlen(s->type) + 16);
|
|
++ sprintf(name, "@%s[%d]", s->type, config_section_idx(s));
|
|
++
|
|
++ blob_buf_init(&b, 0);
|
|
++ uci_to_blob(&b, s, wdev->drv->station.config);
|
|
++ wireless_station_create(wdev, vif, b.head, s->anonymous ? name : s->e.name);
|
|
++}
|
|
++
|
|
+ static void
|
|
+ config_init_wireless(void)
|
|
+ {
|
|
+@@ -393,6 +406,8 @@ config_init_wireless(void)
|
|
+ vlist_update(&wdev->interfaces);
|
|
+ wdev->vlan_idx = 0;
|
|
+ vlist_update(&wdev->vlans);
|
|
++ wdev->sta_idx = 0;
|
|
++ vlist_update(&wdev->stations);
|
|
+ }
|
|
+
|
|
+ uci_foreach_element(&uci_wireless->sections, e) {
|
|
+@@ -429,11 +444,25 @@ config_init_wireless(void)
|
|
+ continue;
|
|
+ config_parse_wireless_vlan(wdev, vif->name, s);
|
|
+ }
|
|
++
|
|
++ uci_foreach_element(&uci_wireless->sections, f) {
|
|
++ struct uci_section *s = uci_to_section(f);
|
|
++ const char *vif_name;
|
|
++
|
|
++ if (strcmp(s->type, "wifi-station") != 0)
|
|
++ continue;
|
|
++
|
|
++ vif_name = uci_lookup_option_string(uci_ctx, s, "iface");
|
|
++ if (vif_name && strcmp(e->name, vif_name))
|
|
++ continue;
|
|
++ config_parse_wireless_station(wdev, vif->name, s);
|
|
++ }
|
|
+ }
|
|
+
|
|
+ vlist_for_each_element(&wireless_devices, wdev, node) {
|
|
+ vlist_flush(&wdev->interfaces);
|
|
+ vlist_flush(&wdev->vlans);
|
|
++ vlist_flush(&wdev->stations);
|
|
+ }
|
|
+ }
|
|
+
|
|
+diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh
|
|
+index 41e380f..d51380d 100644
|
|
+--- a/scripts/netifd-wireless.sh
|
|
++++ b/scripts/netifd-wireless.sh
|
|
+@@ -333,6 +333,21 @@ for_each_vlan() {
|
|
+ json_select ..
|
|
+ }
|
|
+
|
|
++for_each_station() {
|
|
++ local _w_stas _w_sta
|
|
++
|
|
++ json_get_keys _w_stas stas
|
|
++ json_select stas
|
|
++ for _w_sta in $_w_stas; do
|
|
++ json_select "$_w_sta"
|
|
++ json_select config
|
|
++ "$@" "$_w_sta"
|
|
++ json_select ..
|
|
++ json_select ..
|
|
++ done
|
|
++ json_select ..
|
|
++}
|
|
++
|
|
+ _wdev_common_device_config() {
|
|
+ config_add_string channel hwmode htmode noscan
|
|
+ }
|
|
+@@ -345,6 +360,10 @@ _wdev_common_vlan_config() {
|
|
+ config_add_string name vid iface
|
|
+ }
|
|
+
|
|
++_wdev_common_station_config() {
|
|
++ config_add_string mac key vid iface
|
|
++}
|
|
++
|
|
+ init_wireless_driver() {
|
|
+ name="$1"; shift
|
|
+ cmd="$1"; shift
|
|
+@@ -372,6 +391,11 @@ init_wireless_driver() {
|
|
+ eval "drv_$1_init_vlan_config"
|
|
+ json_close_array
|
|
+
|
|
++ json_add_array station
|
|
++ _wdev_common_station_config
|
|
++ eval "drv_$1_init_station_config"
|
|
++ json_close_array
|
|
++
|
|
+ json_dump
|
|
+ }
|
|
+ ;;
|
|
+diff --git a/wireless.c b/wireless.c
|
|
+index b0b35a1..efb7992 100644
|
|
+--- a/wireless.c
|
|
++++ b/wireless.c
|
|
+@@ -82,6 +82,20 @@ static const struct uci_blob_param_list vlan_param = {
|
|
+ .params = vlan_policy,
|
|
+ };
|
|
+
|
|
++enum {
|
|
++ STA_ATTR_DISABLED,
|
|
++ __STA_ATTR_MAX,
|
|
++};
|
|
++
|
|
++static const struct blobmsg_policy sta_policy[__STA_ATTR_MAX] = {
|
|
++ [STA_ATTR_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL },
|
|
++};
|
|
++
|
|
++static const struct uci_blob_param_list station_param = {
|
|
++ .n_params = ARRAY_SIZE(sta_policy),
|
|
++ .params = sta_policy,
|
|
++};
|
|
++
|
|
+ static void
|
|
+ wireless_handler_stop(struct wireless_device *wdev)
|
|
+ {
|
|
+@@ -144,6 +158,7 @@ prepare_config(struct wireless_device *wdev, struct blob_buf *buf, bool up)
|
|
+ {
|
|
+ struct wireless_interface *vif;
|
|
+ struct wireless_vlan *vlan;
|
|
++ struct wireless_station *sta;
|
|
+ void *l, *i, *j, *k;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+@@ -171,6 +186,18 @@ prepare_config(struct wireless_device *wdev, struct blob_buf *buf, bool up)
|
|
+ blobmsg_close_table(&b, k);
|
|
+ }
|
|
+ blobmsg_close_table(&b, j);
|
|
++
|
|
++ j = blobmsg_open_table(&b, "stas");
|
|
++ vlist_for_each_element(&wdev->stations, sta, node) {
|
|
++ if (strcmp(sta->vif, vif->name))
|
|
++ continue;
|
|
++ k = blobmsg_open_table(&b, sta->name);
|
|
++ put_container(&b, sta->config, "config");
|
|
++ if (sta->data)
|
|
++ blobmsg_add_blob(&b, sta->data);
|
|
++ blobmsg_close_table(&b, k);
|
|
++ }
|
|
++ blobmsg_close_table(&b, j);
|
|
+ blobmsg_close_table(&b, i);
|
|
+ }
|
|
+ blobmsg_close_table(&b, l);
|
|
+@@ -242,6 +269,7 @@ wireless_device_free_state(struct wireless_device *wdev)
|
|
+ {
|
|
+ struct wireless_interface *vif;
|
|
+ struct wireless_vlan *vlan;
|
|
++ struct wireless_station *sta;
|
|
+
|
|
+ wireless_handler_stop(wdev);
|
|
+ uloop_timeout_cancel(&wdev->script_check);
|
|
+@@ -259,6 +287,10 @@ wireless_device_free_state(struct wireless_device *wdev)
|
|
+ vlan->data = NULL;
|
|
+ vlan->ifname = NULL;
|
|
+ }
|
|
++ vlist_for_each_element(&wdev->stations, sta, node) {
|
|
++ free(sta->data);
|
|
++ sta->data = NULL;
|
|
++ }
|
|
+ }
|
|
+
|
|
+ static void wireless_interface_handle_link(struct wireless_interface *vif, bool up)
|
|
+@@ -426,6 +458,7 @@ wireless_device_free(struct wireless_device *wdev)
|
|
+ wireless_handler_stop(wdev);
|
|
+ vlist_flush_all(&wdev->interfaces);
|
|
+ vlist_flush_all(&wdev->vlans);
|
|
++ vlist_flush_all(&wdev->stations);
|
|
+ avl_delete(&wireless_devices.avl, &wdev->node.avl);
|
|
+ free(wdev->config);
|
|
+ free(wdev->prev_config);
|
|
+@@ -653,20 +686,22 @@ wireless_add_handler(const char *script, const char *name, json_object *obj)
|
|
+ {
|
|
+ struct wireless_driver *drv;
|
|
+ char *name_str, *script_str;
|
|
+- json_object *dev_config_obj, *iface_config_obj, *vlan_config_obj;
|
|
+- struct uci_blob_param_list *dev_config, *iface_config, *vlan_config;
|
|
++ json_object *dev_config_obj, *iface_config_obj, *vlan_config_obj, *station_config_obj;
|
|
++ struct uci_blob_param_list *dev_config, *iface_config, *vlan_config, *station_config;
|
|
+
|
|
+ dev_config_obj = json_get_field(obj, "device", json_type_array);
|
|
+ iface_config_obj = json_get_field(obj, "iface", json_type_array);
|
|
+ vlan_config_obj = json_get_field(obj, "vlan", json_type_array);
|
|
++ station_config_obj = json_get_field(obj, "station", json_type_array);
|
|
+
|
|
+- if (!dev_config_obj || !iface_config_obj || !vlan_config_obj)
|
|
++ if (!dev_config_obj || !iface_config_obj || !vlan_config_obj || !station_config_obj)
|
|
+ return;
|
|
+
|
|
+ drv = calloc_a(sizeof(*drv),
|
|
+ &dev_config, sizeof(*dev_config) + sizeof(void *),
|
|
+ &iface_config, sizeof(*iface_config) + sizeof(void *),
|
|
+ &vlan_config, sizeof(*vlan_config) + sizeof(void *),
|
|
++ &station_config, sizeof(*station_config) + sizeof(void *),
|
|
+ &name_str, strlen(name) + 1,
|
|
+ &script_str, strlen(script) + 1);
|
|
+
|
|
+@@ -685,9 +720,14 @@ wireless_add_handler(const char *script, const char *name, json_object *obj)
|
|
+ vlan_config->next[0] = &vlan_param;
|
|
+ drv->vlan.config = vlan_config;
|
|
+
|
|
++ station_config->n_next = 1;
|
|
++ station_config->next[0] = &station_param;
|
|
++ drv->station.config = station_config;
|
|
++
|
|
+ drv->device.buf = netifd_handler_parse_config(drv->device.config, dev_config_obj);
|
|
+ drv->interface.buf = netifd_handler_parse_config(drv->interface.config, iface_config_obj);
|
|
+ drv->vlan.buf = netifd_handler_parse_config(drv->vlan.config, vlan_config_obj);
|
|
++ drv->station.buf = netifd_handler_parse_config(drv->station.config, station_config_obj);
|
|
+
|
|
+ drv->node.key = drv->name;
|
|
+ avl_insert(&wireless_drivers, &drv->node);
|
|
+@@ -835,6 +875,45 @@ vlan_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
|
+ wdev_set_config_state(wdev, IFC_RELOAD);
|
|
+ }
|
|
+
|
|
++static void
|
|
++station_update(struct vlist_tree *tree, struct vlist_node *node_new,
|
|
++ struct vlist_node *node_old)
|
|
++{
|
|
++ struct wireless_station *sta_old = container_of(node_old, struct wireless_station, node);
|
|
++ struct wireless_station *sta_new = container_of(node_new, struct wireless_station, node);
|
|
++ struct wireless_device *wdev;
|
|
++
|
|
++ if (sta_old)
|
|
++ wdev = sta_old->wdev;
|
|
++ else
|
|
++ wdev = sta_new->wdev;
|
|
++
|
|
++ if (sta_old && sta_new) {
|
|
++ free((void *) sta_old->section);
|
|
++ sta_old->section = strdup(sta_new->section);
|
|
++ if (blob_attr_equal(sta_old->config, sta_new->config)) {
|
|
++ free(sta_new);
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ D(WIRELESS, "Update wireless station %s on device %s\n", sta_new->name, wdev->name);
|
|
++ free(sta_old->config);
|
|
++ sta_old->config = blob_memdup(sta_new->config);
|
|
++ free(sta_new);
|
|
++ } else if (sta_new) {
|
|
++ D(WIRELESS, "Create new wireless station %s on device %s\n", sta_new->name, wdev->name);
|
|
++ sta_new->section = strdup(sta_new->section);
|
|
++ sta_new->config = blob_memdup(sta_new->config);
|
|
++ } else if (sta_old) {
|
|
++ D(WIRELESS, "Delete wireless station %s on device %s\n", sta_old->name, wdev->name);
|
|
++ free((void *) sta_old->section);
|
|
++ free(sta_old->config);
|
|
++ free(sta_old);
|
|
++ }
|
|
++
|
|
++ wdev_set_config_state(wdev, IFC_RELOAD);
|
|
++}
|
|
++
|
|
+ static void
|
|
+ wireless_proc_poll_fd(struct uloop_fd *fd, unsigned int events)
|
|
+ {
|
|
+@@ -921,6 +1000,8 @@ wireless_device_create(struct wireless_driver *drv, const char *name, struct blo
|
|
+ wdev->interfaces.keep_old = true;
|
|
+ vlist_init(&wdev->vlans, avl_strcmp, vlan_update);
|
|
+ wdev->vlans.keep_old = true;
|
|
++ vlist_init(&wdev->stations, avl_strcmp, station_update);
|
|
++ wdev->stations.keep_old = true;
|
|
+
|
|
+ wdev->timeout.cb = wireless_device_setup_timeout;
|
|
+ wdev->script_task.cb = wireless_device_script_task_cb;
|
|
+@@ -935,6 +1016,47 @@ wireless_device_create(struct wireless_driver *drv, const char *name, struct blo
|
|
+ vlist_add(&wireless_devices, &wdev->node, wdev->name);
|
|
+ }
|
|
+
|
|
++void
|
|
++wireless_station_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section)
|
|
++{
|
|
++ struct wireless_station *sta;
|
|
++ struct blob_attr *tb[__STA_ATTR_MAX];
|
|
++ struct blob_attr *cur;
|
|
++ char *name_buf, *vif_buf;
|
|
++ char name[8];
|
|
++
|
|
++ blobmsg_parse(sta_policy, __STA_ATTR_MAX, tb, blob_data(data), blob_len(data));
|
|
++
|
|
++ cur = tb[STA_ATTR_DISABLED];
|
|
++ if (cur && blobmsg_get_bool(cur))
|
|
++ return;
|
|
++
|
|
++ sprintf(name, "%d", wdev->vlan_idx++);
|
|
++
|
|
++ sta = calloc_a(sizeof(*sta),
|
|
++ &name_buf, strlen(name) + 1,
|
|
++ &vif_buf, strlen(vif) + 1);
|
|
++ sta->name = strcpy(name_buf, name);
|
|
++ sta->vif = strcpy(vif_buf, vif);
|
|
++ sta->wdev = wdev;
|
|
++ sta->config = data;
|
|
++ sta->section = section;
|
|
++
|
|
++ vlist_add(&wdev->stations, &sta->node, sta->name);
|
|
++}
|
|
++
|
|
++static void
|
|
++wireless_station_status(struct wireless_station *sta, struct blob_buf *b)
|
|
++{
|
|
++ void *i;
|
|
++
|
|
++ i = blobmsg_open_table(b, NULL);
|
|
++ if (sta->section)
|
|
++ blobmsg_add_string(b, "section", sta->section);
|
|
++ put_container(b, sta->config, "config");
|
|
++ blobmsg_close_table(b, i);
|
|
++}
|
|
++
|
|
+ void
|
|
+ wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section)
|
|
+ {
|
|
+@@ -1011,6 +1133,7 @@ static void
|
|
+ wireless_interface_status(struct wireless_interface *iface, struct blob_buf *b)
|
|
+ {
|
|
+ struct wireless_vlan *vlan;
|
|
++ struct wireless_station *sta;
|
|
+ void *i, *j;
|
|
+
|
|
+ i = blobmsg_open_table(b, NULL);
|
|
+@@ -1024,6 +1147,11 @@ wireless_interface_status(struct wireless_interface *iface, struct blob_buf *b)
|
|
+ if (!strcmp(iface->name, vlan->vif))
|
|
+ wireless_vlan_status(vlan, b);
|
|
+ blobmsg_close_array(b, j);
|
|
++ j = blobmsg_open_array(b, "stations");
|
|
++ vlist_for_each_element(&iface->wdev->stations, sta, node)
|
|
++ if (!strcmp(iface->name, sta->vif))
|
|
++ wireless_station_status(sta, b);
|
|
++ blobmsg_close_array(b, j);
|
|
+ blobmsg_close_table(b, i);
|
|
+ }
|
|
+
|
|
+diff --git a/wireless.h b/wireless.h
|
|
+index 8d0a1f0..5fedd20 100644
|
|
+--- a/wireless.h
|
|
++++ b/wireless.h
|
|
+@@ -30,7 +30,7 @@ struct wireless_driver {
|
|
+ struct {
|
|
+ char *buf;
|
|
+ struct uci_blob_param_list *config;
|
|
+- } device, interface, vlan;
|
|
++ } device, interface, vlan, station;
|
|
+ };
|
|
+
|
|
+ struct wireless_device {
|
|
+@@ -44,6 +44,7 @@ struct wireless_device {
|
|
+ struct wireless_driver *drv;
|
|
+ struct vlist_tree interfaces;
|
|
+ struct vlist_tree vlans;
|
|
++ struct vlist_tree stations;
|
|
+ char *name;
|
|
+
|
|
+ struct netifd_process script_task;
|
|
+@@ -72,6 +73,7 @@ struct wireless_device {
|
|
+
|
|
+ int vif_idx;
|
|
+ int vlan_idx;
|
|
++ int sta_idx;
|
|
+ };
|
|
+
|
|
+ struct wireless_interface {
|
|
+@@ -106,6 +108,18 @@ struct wireless_vlan {
|
|
+ bool isolate;
|
|
+ };
|
|
+
|
|
++struct wireless_station {
|
|
++ struct vlist_node node;
|
|
++ const char *section;
|
|
++ char *name;
|
|
++
|
|
++ struct wireless_device *wdev;
|
|
++ char *vif;
|
|
++
|
|
++ struct blob_attr *config;
|
|
++ struct blob_attr *data;
|
|
++};
|
|
++
|
|
+ struct wireless_process {
|
|
+ struct list_head list;
|
|
+
|
|
+@@ -123,6 +137,7 @@ void wireless_device_status(struct wireless_device *wdev, struct blob_buf *b);
|
|
+ void wireless_device_get_validate(struct wireless_device *wdev, struct blob_buf *b);
|
|
+ struct wireless_interface* wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section);
|
|
+ void wireless_vlan_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section);
|
|
++void wireless_station_create(struct wireless_device *wdev, char *vif, struct blob_attr *data, const char *section);
|
|
+ int wireless_device_notify(struct wireless_device *wdev, struct blob_attr *data,
|
|
+ struct ubus_request_data *req);
|
|
+
|
|
+--
|
|
+2.20.1
|
|
+
|
|
diff --git a/package/network/config/netifd/patches/0003-wireless-add-ubus-method-for-reloading-configuration.patch b/package/network/config/netifd/patches/0003-wireless-add-ubus-method-for-reloading-configuration.patch
|
|
new file mode 100644
|
|
index 0000000000..26dc1afaf6
|
|
--- /dev/null
|
|
+++ b/package/network/config/netifd/patches/0003-wireless-add-ubus-method-for-reloading-configuration.patch
|
|
@@ -0,0 +1,123 @@
|
|
+From 7a723d0c797d28823f3d0eae9c72aca3ae69d976 Mon Sep 17 00:00:00 2001
|
|
+From: John Crispin <john@phrozen.org>
|
|
+Date: Fri, 25 Oct 2019 14:02:03 +0200
|
|
+Subject: [PATCH 3/4] wireless: add ubus method for reloading configuration
|
|
+
|
|
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
+---
|
|
+ ubus.c | 23 +++++++++++++++++++++++
|
|
+ wireless.c | 18 +++++++++++++-----
|
|
+ wireless.h | 1 +
|
|
+ 3 files changed, 37 insertions(+), 5 deletions(-)
|
|
+
|
|
+diff --git a/ubus.c b/ubus.c
|
|
+index 150d818..5a2a339 100644
|
|
+--- a/ubus.c
|
|
++++ b/ubus.c
|
|
+@@ -1081,6 +1081,28 @@ get_wdev(struct blob_attr *msg, int *ret)
|
|
+ return wdev;
|
|
+ }
|
|
+
|
|
++static int
|
|
++netifd_handle_wdev_reconf(struct ubus_context *ctx, struct ubus_object *obj,
|
|
++ struct ubus_request_data *req, const char *method,
|
|
++ struct blob_attr *msg)
|
|
++{
|
|
++ struct wireless_device *wdev;
|
|
++ int ret;
|
|
++
|
|
++ wdev = get_wdev(msg, &ret);
|
|
++ if (ret == UBUS_STATUS_NOT_FOUND)
|
|
++ return ret;
|
|
++
|
|
++ if (wdev) {
|
|
++ wireless_device_reconf(wdev);
|
|
++ } else {
|
|
++ vlist_for_each_element(&wireless_devices, wdev, node)
|
|
++ wireless_device_reconf(wdev);
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
+ static int
|
|
+ netifd_handle_wdev_up(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+@@ -1189,6 +1211,7 @@ netifd_handle_wdev_notify(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ static struct ubus_method wireless_object_methods[] = {
|
|
+ { .name = "up", .handler = netifd_handle_wdev_up },
|
|
+ { .name = "down", .handler = netifd_handle_wdev_down },
|
|
++ { .name = "reconf", .handler = netifd_handle_wdev_reconf },
|
|
+ { .name = "status", .handler = netifd_handle_wdev_status },
|
|
+ { .name = "notify", .handler = netifd_handle_wdev_notify },
|
|
+ { .name = "get_validate", .handler = netifd_handle_wdev_get_validate },
|
|
+diff --git a/wireless.c b/wireless.c
|
|
+index 387f4ba..9986e9a 100644
|
|
+--- a/wireless.c
|
|
++++ b/wireless.c
|
|
+@@ -282,7 +282,7 @@ wireless_device_run_handler(struct wireless_device *wdev, bool up)
|
|
+ }
|
|
+
|
|
+ static void
|
|
+-__wireless_device_set_up(struct wireless_device *wdev)
|
|
++__wireless_device_set_up(struct wireless_device *wdev, int force)
|
|
+ {
|
|
+ if (wdev->disabled)
|
|
+ return;
|
|
+@@ -293,7 +293,7 @@ __wireless_device_set_up(struct wireless_device *wdev)
|
|
+ if (!wdev->autostart)
|
|
+ return;
|
|
+
|
|
+- if (wdev->state != IFS_DOWN || config_init)
|
|
++ if (!force && (wdev->state != IFS_DOWN || config_init))
|
|
+ return;
|
|
+
|
|
+ free(wdev->prev_config);
|
|
+@@ -320,7 +320,7 @@ wdev_handle_config_change(struct wireless_device *wdev)
|
|
+ switch(state) {
|
|
+ case IFC_NORMAL:
|
|
+ case IFC_RELOAD:
|
|
+- __wireless_device_set_up(wdev);
|
|
++ __wireless_device_set_up(wdev, 0);
|
|
+
|
|
+ wdev->config_state = IFC_NORMAL;
|
|
+ break;
|
|
+@@ -363,7 +363,15 @@ wireless_device_set_up(struct wireless_device *wdev)
|
|
+ {
|
|
+ wdev->retry = WIRELESS_SETUP_RETRY;
|
|
+ wdev->autostart = true;
|
|
+- __wireless_device_set_up(wdev);
|
|
++ __wireless_device_set_up(wdev, 0);
|
|
++}
|
|
++
|
|
++void
|
|
++wireless_device_reconf(struct wireless_device *wdev)
|
|
++{
|
|
++ wdev->retry = WIRELESS_SETUP_RETRY;
|
|
++ wdev->autostart = true;
|
|
++ __wireless_device_set_up(wdev, 1);
|
|
+ }
|
|
+
|
|
+ static void
|
|
+@@ -1001,5 +1009,5 @@ wireless_start_pending(void)
|
|
+ struct wireless_device *wdev;
|
|
+
|
|
+ vlist_for_each_element(&wireless_devices, wdev, node)
|
|
+- __wireless_device_set_up(wdev);
|
|
++ __wireless_device_set_up(wdev, 0);
|
|
+ }
|
|
+diff --git a/wireless.h b/wireless.h
|
|
+index 3498bd8..bade738 100644
|
|
+--- a/wireless.h
|
|
++++ b/wireless.h
|
|
+@@ -93,6 +93,7 @@ struct wireless_process {
|
|
+ void wireless_device_create(struct wireless_driver *drv, const char *name, struct blob_attr *data);
|
|
+ void wireless_device_set_up(struct wireless_device *wdev);
|
|
+ void wireless_device_set_down(struct wireless_device *wdev);
|
|
++void wireless_device_reconf(struct wireless_device *wdev);
|
|
+ void wireless_device_status(struct wireless_device *wdev, struct blob_buf *b);
|
|
+ void wireless_device_get_validate(struct wireless_device *wdev, struct blob_buf *b);
|
|
+ void wireless_interface_create(struct wireless_device *wdev, struct blob_attr *data, const char *section);
|
|
+--
|
|
+2.25.1
|
|
+
|
|
diff --git a/package/network/config/netifd/patches/0004-wireless-make-reconf-opt-in-and-allow-serializing-co.patch b/package/network/config/netifd/patches/0004-wireless-make-reconf-opt-in-and-allow-serializing-co.patch
|
|
new file mode 100644
|
|
index 0000000000..04bf4397db
|
|
--- /dev/null
|
|
+++ b/package/network/config/netifd/patches/0004-wireless-make-reconf-opt-in-and-allow-serializing-co.patch
|
|
@@ -0,0 +1,249 @@
|
|
+From e15147c272201eb17320c10ec95919e641bd03c5 Mon Sep 17 00:00:00 2001
|
|
+From: John Crispin <john@phrozen.org>
|
|
+Date: Fri, 25 Oct 2019 14:06:30 +0200
|
|
+Subject: [PATCH 4/4] wireless: make reconf opt-in and allow serializing
|
|
+ configuration
|
|
+
|
|
+Add option 'reconf' to make dynamic re-configuration opt-in.
|
|
+Also add option 'serialize' to 'wifi-device' section and if set
|
|
+configure interfaces of wireless devices one-by-one.
|
|
+Both options are disabled by default.
|
|
+
|
|
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
+---
|
|
+ wireless.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
+ wireless.h | 7 +++++
|
|
+ 2 files changed, 88 insertions(+), 10 deletions(-)
|
|
+
|
|
+diff --git a/wireless.c b/wireless.c
|
|
+index 9986e9a..c8e196f 100644
|
|
+--- a/wireless.c
|
|
++++ b/wireless.c
|
|
+@@ -23,13 +23,25 @@ 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 };
|
|
++enum {
|
|
++ WDEV_ATTR_DISABLED,
|
|
++ WDEV_ATTR_RECONF,
|
|
++ WDEV_ATTR_SERIALIZE,
|
|
++ __WDEV_ATTR_MAX,
|
|
++};
|
|
++
|
|
++static const struct blobmsg_policy wdev_policy[__WDEV_ATTR_MAX] = {
|
|
++ [WDEV_ATTR_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL },
|
|
++ [WDEV_ATTR_RECONF] = { .name = "reconf", .type = BLOBMSG_TYPE_BOOL },
|
|
++ [WDEV_ATTR_SERIALIZE] = { .name = "serialize", .type = BLOBMSG_TYPE_BOOL },
|
|
++};
|
|
+
|
|
+ static const struct uci_blob_param_list wdev_param = {
|
|
+- .n_params = 1,
|
|
+- .params = &wdev_policy,
|
|
++ .n_params = ARRAY_SIZE(wdev_policy),
|
|
++ .params = wdev_policy,
|
|
+ };
|
|
+
|
|
+ enum {
|
|
+@@ -52,6 +64,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 +209,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 +258,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 +273,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 +315,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 +354,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 +403,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 +425,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 +487,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 +511,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 +560,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);
|
|
+@@ -686,18 +746,29 @@ wireless_device_create(struct wireless_driver *drv, const char *name, struct blo
|
|
+ {
|
|
+ struct wireless_device *wdev;
|
|
+ char *name_buf;
|
|
+- struct blob_attr *disabled;
|
|
++ struct blob_attr *tb[__WDEV_ATTR_MAX];
|
|
++ struct blob_attr *cur;
|
|
+
|
|
+- blobmsg_parse(&wdev_policy, 1, &disabled, blob_data(data), blob_len(data));
|
|
++ blobmsg_parse(wdev_policy, __WDEV_ATTR_MAX, tb, blob_data(data), blob_len(data));
|
|
+
|
|
+ wdev = calloc_a(sizeof(*wdev), &name_buf, strlen(name) + 1);
|
|
+- if (disabled && blobmsg_get_bool(disabled))
|
|
+- wdev->disabled = true;
|
|
++
|
|
++ cur = tb[WDEV_ATTR_DISABLED];
|
|
++ wdev->disabled = cur && blobmsg_get_bool(cur);
|
|
++
|
|
+ wdev->drv = drv;
|
|
+ wdev->state = IFS_DOWN;
|
|
+ wdev->config_state = IFC_NORMAL;
|
|
+ wdev->name = strcpy(name_buf, name);
|
|
+ wdev->config = data;
|
|
++ wdev->handler_pending = false;
|
|
++
|
|
++ cur = tb[WDEV_ATTR_SERIALIZE];
|
|
++ wdev->serialize = cur && blobmsg_get_bool(cur);
|
|
++
|
|
++ cur = tb[WDEV_ATTR_RECONF];
|
|
++ wdev->reconf = cur && blobmsg_get_bool(cur);
|
|
++
|
|
+ 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.25.1
|
|
+
|
|
diff --git a/package/network/config/netifd/patches/0005-netifd-fix-wdev-data-lifetime.patch b/package/network/config/netifd/patches/0005-netifd-fix-wdev-data-lifetime.patch
|
|
new file mode 100644
|
|
index 0000000000..5ccefc5117
|
|
--- /dev/null
|
|
+++ b/package/network/config/netifd/patches/0005-netifd-fix-wdev-data-lifetime.patch
|
|
@@ -0,0 +1,42 @@
|
|
+From 1aee9aea386a510eb9e0f11fdb57984539294f0d Mon Sep 17 00:00:00 2001
|
|
+From: John Crispin <john@phrozen.org>
|
|
+Date: Tue, 23 Jun 2020 10:09:13 +0200
|
|
+Subject: [PATCH V2] netifd: fix wdev->data lifetime
|
|
+
|
|
+The reconf patch breaks wifi down under certain conditions. The root cause
|
|
+is that during reload the wdev state gets flushed. This has the effect, that
|
|
+the phy is lost from the state resulting in teardown breaking.
|
|
+Fix this by changing the lifetime of wdev->data.
|
|
+
|
|
+Signed-off-by: John Crispin <john@phrozen.org>
|
|
+---
|
|
+Changes in V2
|
|
+* free() call was in the wrong place
|
|
+
|
|
+ wireless.c | 5 +++--
|
|
+ 1 file changed, 3 insertions(+), 2 deletions(-)
|
|
+
|
|
+diff --git a/wireless.c b/wireless.c
|
|
+index efb7992..e295f28 100644
|
|
+--- a/wireless.c
|
|
++++ b/wireless.c
|
|
+@@ -275,8 +275,6 @@ wireless_device_free_state(struct wireless_device *wdev)
|
|
+ uloop_timeout_cancel(&wdev->script_check);
|
|
+ uloop_timeout_cancel(&wdev->timeout);
|
|
+ wireless_complete_kill_request(wdev);
|
|
+- free(wdev->data);
|
|
+- wdev->data = NULL;
|
|
+ vlist_for_each_element(&wdev->interfaces, vif, node) {
|
|
+ free(vif->data);
|
|
+ vif->data = NULL;
|
|
+@@ -460,6 +458,7 @@ wireless_device_free(struct wireless_device *wdev)
|
|
+ vlist_flush_all(&wdev->vlans);
|
|
+ vlist_flush_all(&wdev->stations);
|
|
+ avl_delete(&wireless_devices.avl, &wdev->node.avl);
|
|
++ free(wdev->data);
|
|
+ free(wdev->config);
|
|
+ free(wdev->prev_config);
|
|
+ free(wdev);
|
|
+--
|
|
+2.25.1
|
|
+
|
|
--
|
|
2.25.1
|
|
|