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;
});
}
+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;
function __run_next_handler_name()
{
+ if (wdev_handler[mlo_name])
+ return mlo_name;
+
return sort(keys(wdev_handler), handler_sort_fn)[0];
}
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),
if (wdev.state != "setup")
return;
+ if (wdev.name == mlo_name)
+ mlo_wdev = wdev;
+
if (wdev.config_change) {
wdev.setup();
return;
let handlers = {};
let devices = {};
let vifs = {};
+ let mlo_device;
let sections = {
device: {},
vlan: {},
station: {},
};
+ let radio_idx = {};
for (let name, data in config) {
let type = data[".type"];
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) {
if (!handler)
continue;
+ if (data.radio != null)
+ radio_idx[name] = +data.radio;
+
let config = parse_attribute_list(data, handler.device);
devices[name] = {
name,
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)
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,
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;
}
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;
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;
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;