summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau2025-06-17 09:16:17 +0000
committerFelix Fietkau2025-08-02 14:44:19 +0000
commit74c22601baad83cc9bc0fddb98f15d7abaa52c67 (patch)
tree62edcd0089ca71e491dcc2f40fba6e7d1ca2ff26
parentd9f2dd2614f2e85fd5219742cce9be748948d19c (diff)
downloadnetifd-74c22601baad83cc9bc0fddb98f15d7abaa52c67.tar.gz
wireless: add MLO support to example scripts
Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--examples/wireless-device.uc28
-rw-r--r--examples/wireless.uc48
-rwxr-xr-xexamples/wireless/mac80211.sh12
3 files changed, 87 insertions, 1 deletions
diff --git a/examples/wireless-device.uc b/examples/wireless-device.uc
index f6db09c..b0faef1 100644
--- a/examples/wireless-device.uc
+++ b/examples/wireless-device.uc
@@ -12,6 +12,9 @@ const NOTIFY_CMD_SET_RETRY = 4;
const DEFAULT_RETRY = 3;
const DEFAULT_SCRIPT_TIMEOUT = 30 * 1000;
+export const mlo_name = "#mlo";
+
+let mlo_wdev;
let wdev_cur;
let wdev_handler = {};
let wdev_script_task, wdev_script_timeout;
@@ -59,6 +62,23 @@ function handle_link(dev, data, up)
});
}
+function wdev_mlo_fixup(config)
+{
+ if (!mlo_wdev)
+ return;
+
+ for (let name, iface in config.interfaces) {
+ let config = iface.config;
+
+ if (config.mode != "link")
+ continue;
+
+ let mlo_config = mlo_wdev.handler_data[iface.name];
+ if (mlo_config && mlo_config.ifname)
+ config.ifname = mlo_config.ifname;
+ }
+}
+
function wdev_config_init(wdev)
{
let data = wdev.data;
@@ -177,6 +197,9 @@ function handler_sort_fn(a, b)
function __run_next_handler_name()
{
+ if (wdev_handler[mlo_name])
+ return mlo_name;
+
return sort(keys(wdev_handler), handler_sort_fn)[0];
}
@@ -194,6 +217,8 @@ function __run_next_handler()
let cb = wdev_cur.cb;
wdev.dbg("run " + op);
+ if (name != mlo_name)
+ wdev_mlo_fixup(wdev.handler_config);
wdev.handler_config.data = wdev.handler_data[wdev.name];
wdev_script_task = netifd.process({
cb: () => run_handler_cb(wdev, cb),
@@ -409,6 +434,9 @@ function wdev_mark_up(wdev)
if (wdev.state != "setup")
return;
+ if (wdev.name == mlo_name)
+ mlo_wdev = wdev;
+
if (wdev.config_change) {
wdev.setup();
return;
diff --git a/examples/wireless.uc b/examples/wireless.uc
index d75aaca..b63ec23 100644
--- a/examples/wireless.uc
+++ b/examples/wireless.uc
@@ -45,6 +45,7 @@ function config_init(uci)
let handlers = {};
let devices = {};
let vifs = {};
+ let mlo_device;
let sections = {
device: {},
@@ -52,6 +53,7 @@ function config_init(uci)
vlan: {},
station: {},
};
+ let radio_idx = {};
for (let name, data in config) {
let type = data[".type"];
@@ -64,6 +66,20 @@ function config_init(uci)
let list = sections[substr(type, 5)];
if (list)
list[name] = data;
+
+ if (type == "wifi-iface" && parse_bool(data.mlo))
+ mlo_device = true;
+ }
+
+ if (mlo_device) {
+ devices[wdev.mlo_name] = {
+ name: wdev.mlo_name,
+ config: {
+ type: "mac80211",
+ },
+ vif: [],
+ };
+ handlers[wdev.mlo_name] = wireless.handlers.mac80211;
}
for (let name, data in sections.device) {
@@ -74,6 +90,9 @@ function config_init(uci)
if (!handler)
continue;
+ if (data.radio != null)
+ radio_idx[name] = +data.radio;
+
let config = parse_attribute_list(data, handler.device);
devices[name] = {
name,
@@ -86,6 +105,12 @@ function config_init(uci)
for (let name, data in sections.iface) {
let dev_names = parse_array(data.device);
+ let mlo_vif = parse_bool(data.mlo);
+ let radios = map(dev_names, (v) => radio_idx[v]);
+ radios = filter(radios, (v) => v != null);
+ let radio_config = map(dev_names, (v) => devices[v].config);
+ if (mlo_vif)
+ dev_names = [ wdev.mlo_name, ...dev_names ];
for (let dev_name in dev_names) {
let dev = devices[dev_name];
if (!dev)
@@ -96,6 +121,12 @@ function config_init(uci)
continue;
let config = parse_attribute_list(data, handler.iface);
+ if (mlo_vif)
+ if (dev_name == wdev.mlo_name)
+ config.radio_config = radio_config;
+ else
+ config.mode = "link";
+ config.radios = radios;
let vif = {
name, config,
@@ -266,8 +297,11 @@ function wdev_call(req, cb)
return cb(dev);
}
- for (let name, dev in wireless.devices)
+ for (let name, dev in wireless.devices) {
+ if (name == wdev.mlo_name)
+ continue;
cb(dev);
+ }
return 0;
}
@@ -308,6 +342,10 @@ const ubus_obj = {
up: {
args: wdev_args,
call: function(req) {
+ let mlo_dev = wireless.devices[wdev.mlo_name];
+ if (mlo_dev)
+ mlo_dev.start();
+
return wdev_call(req, (dev) => {
dev.start();
return 0;
@@ -317,6 +355,10 @@ const ubus_obj = {
down: {
args: wdev_args,
call: function(req) {
+ let mlo_dev = wireless.devices[wdev.mlo_name];
+ if (mlo_dev)
+ mlo_dev.config_change = true;
+
return wdev_call(req, (dev) => {
dev.stop();
return 0;
@@ -326,6 +368,10 @@ const ubus_obj = {
reconf: {
args: wdev_args,
call: function(req) {
+ let mlo_dev = wireless.devices[wdev.mlo_name];
+ if (mlo_dev)
+ mlo_dev.update();
+
return wdev_call(req, (dev) => {
dev.update();
return 0;
diff --git a/examples/wireless/mac80211.sh b/examples/wireless/mac80211.sh
index 28e16f7..8389afa 100755
--- a/examples/wireless/mac80211.sh
+++ b/examples/wireless/mac80211.sh
@@ -287,6 +287,17 @@ setup_vif() {
vifidx=$((vifidx + 1))
}
+setup_link() {
+ local name="$1"
+
+ json_select config
+ json_get_vars ifname
+ json_select ..
+
+ echo "Add link on $radio: $ifname"
+}
+
+
drv_mac80211_cleanup() {
echo "mac80211 cleanup"
}
@@ -296,6 +307,7 @@ drv_mac80211_setup() {
radio=$1
vifidx=0
json_dump
+ for_each_interface "link" setup_link
for_each_interface "sta ap adhoc" setup_vif
wireless_set_data phy=phy0
wireless_set_up