config_add(config, param, data[param]);
}
+function setup_mlo(data) {
+ let config = {};
+ let idx = 0;
+
+ for (let k, v in data.interfaces) {
+ let ifname = v.config.ifname;
+ if (!ifname)
+ ifname = 'ap-mld' + idx++;
+
+ delete v.config.ifname;
+ config[ifname] = v.config;
+ netifd.set_vif(k, ifname);
+
+ v.config.phy = find_phy(v.config.radio_config[0], true);
+ delete v.config.radio_config;
+ }
+
+ let ret = ubus.call('hostapd', 'mld_set', { config });
+ if (type(ret) != "object")
+ return netifd.setup_failed('HOSTAPD_START_FAILED');
+
+ netifd.add_process('/usr/sbin/hostapd', ret.pid, true, true);
+ netifd.set_up();
+
+ return 0;
+}
+
function setup() {
let data = json(ARGV[3]);
+ if (ARGV[2] == "#mlo")
+ return setup_mlo(data);
+
data.phy = find_phy(data.config, true);
if (!data.phy) {
log('Bug: PHY is undefined for device');
}
switch (mode) {
+ case 'link':
case 'ap':
has_ap = true;
// fallthrough
data.config.noscan = true;
validate('iface', v.config);
iface.prepare(v.config, data.phy + data.phy_suffix, data.config.num_global_macaddr, data.config.macaddr_base);
- netifd.set_vif(k, v.config.ifname);
+ if (mode != "link")
+ netifd.set_vif(k, v.config.ifname);
break;
}
function teardown() {
let data = json(ARGV[3]);
+ if (ARGV[2] == "#mlo")
+ return 0;
+
if (!data.data?.phy) {
log('Bug: PHY is undefined for device');
return 1;
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) {
continue;
let config = parse_attribute_list(data, handler.iface);
- if (mlo_vif && dev_name != wdev.mlo_name)
- config.mode = "link";
+ if (mlo_vif)
+ if (dev_name == wdev.mlo_name)
+ config.radio_config = radio_config;
+ else
+ config.mode = "link";
config.radios = radios;
let vif = {