wifi-scripts: ucode: add MLO interface support
MLO can be enabled by configuring a wifi-iface section with multiple
radios, like this:
config wifi-iface
list radio 'radio0'
list radio 'radio1'
option mlo '1'
option ssid 'OpenWrt'
option mode 'ap'
option network 'lan'
...
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
@@ -157,9 +157,39 @@ function config_add_mesh_params(config, data) {
|
|||||||
config_add(config, param, data[param]);
|
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() {
|
function setup() {
|
||||||
let data = json(ARGV[3]);
|
let data = json(ARGV[3]);
|
||||||
|
|
||||||
|
if (ARGV[2] == "#mlo")
|
||||||
|
return setup_mlo(data);
|
||||||
|
|
||||||
data.phy = find_phy(data.config, true);
|
data.phy = find_phy(data.config, true);
|
||||||
if (!data.phy) {
|
if (!data.phy) {
|
||||||
log('Bug: PHY is undefined for device');
|
log('Bug: PHY is undefined for device');
|
||||||
@@ -200,6 +230,7 @@ function setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
case 'link':
|
||||||
case 'ap':
|
case 'ap':
|
||||||
has_ap = true;
|
has_ap = true;
|
||||||
// fallthrough
|
// fallthrough
|
||||||
@@ -210,6 +241,7 @@ function setup() {
|
|||||||
data.config.noscan = true;
|
data.config.noscan = true;
|
||||||
validate('iface', v.config);
|
validate('iface', v.config);
|
||||||
iface.prepare(v.config, data.phy + data.phy_suffix, data.config.num_global_macaddr, data.config.macaddr_base);
|
iface.prepare(v.config, data.phy + data.phy_suffix, data.config.num_global_macaddr, data.config.macaddr_base);
|
||||||
|
if (mode != "link")
|
||||||
netifd.set_vif(k, v.config.ifname);
|
netifd.set_vif(k, v.config.ifname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -277,6 +309,9 @@ function setup() {
|
|||||||
function teardown() {
|
function teardown() {
|
||||||
let data = json(ARGV[3]);
|
let data = json(ARGV[3]);
|
||||||
|
|
||||||
|
if (ARGV[2] == "#mlo")
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!data.data?.phy) {
|
if (!data.data?.phy) {
|
||||||
log('Bug: PHY is undefined for device');
|
log('Bug: PHY is undefined for device');
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -488,6 +488,12 @@ export function generate(interface, data, config, vlans, stas, phy_features) {
|
|||||||
for (let raw in config.hostapd_options)
|
for (let raw in config.hostapd_options)
|
||||||
append_raw(raw);
|
append_raw(raw);
|
||||||
|
|
||||||
|
if (config.mode == 'link') {
|
||||||
|
append_raw('mld_ap=1');
|
||||||
|
if (data.config.radio != null)
|
||||||
|
append_raw('mld_link_id=' + data.config.radio);
|
||||||
|
}
|
||||||
|
|
||||||
if (config.default_macaddr)
|
if (config.default_macaddr)
|
||||||
append_raw('#default_macaddr');
|
append_raw('#default_macaddr');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ export function setup(data) {
|
|||||||
append('\n#macaddr_base', data.config.macaddr_base);
|
append('\n#macaddr_base', data.config.macaddr_base);
|
||||||
|
|
||||||
for (let k, interface in data.interfaces) {
|
for (let k, interface in data.interfaces) {
|
||||||
if (interface.config.mode != 'ap')
|
if (interface.config.mode != 'ap' && interface.config.mode != 'link')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
interface.config.network_bridge = interface.bridge;
|
interface.config.network_bridge = interface.bridge;
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ function config_init(uci)
|
|||||||
let mlo_vif = parse_bool(data.mlo);
|
let mlo_vif = parse_bool(data.mlo);
|
||||||
let radios = map(dev_names, (v) => radio_idx[v]);
|
let radios = map(dev_names, (v) => radio_idx[v]);
|
||||||
radios = filter(radios, (v) => v != null);
|
radios = filter(radios, (v) => v != null);
|
||||||
|
let radio_config = map(dev_names, (v) => devices[v].config);
|
||||||
if (mlo_vif)
|
if (mlo_vif)
|
||||||
dev_names = [ wdev.mlo_name, ...dev_names ];
|
dev_names = [ wdev.mlo_name, ...dev_names ];
|
||||||
for (let dev_name in dev_names) {
|
for (let dev_name in dev_names) {
|
||||||
@@ -120,7 +121,10 @@ function config_init(uci)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
let config = parse_attribute_list(data, handler.iface);
|
let config = parse_attribute_list(data, handler.iface);
|
||||||
if (mlo_vif && dev_name != wdev.mlo_name)
|
if (mlo_vif)
|
||||||
|
if (dev_name == wdev.mlo_name)
|
||||||
|
config.radio_config = radio_config;
|
||||||
|
else
|
||||||
config.mode = "link";
|
config.mode = "link";
|
||||||
config.radios = radios;
|
config.radios = radios;
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,9 @@ function wdev_create(phy, name, data)
|
|||||||
req["4addr"] = data["4addr"];
|
req["4addr"] = data["4addr"];
|
||||||
if (data.macaddr)
|
if (data.macaddr)
|
||||||
req.mac = data.macaddr;
|
req.mac = data.macaddr;
|
||||||
if (data.radio != null && data.radio >= 0)
|
if (data.radio_mask > 0)
|
||||||
|
req.vif_radio_mask = data.radio_mask;
|
||||||
|
else if (data.radio != null && data.radio >= 0)
|
||||||
req.vif_radio_mask = 1 << data.radio;
|
req.vif_radio_mask = 1 << data.radio;
|
||||||
|
|
||||||
nl80211.error();
|
nl80211.error();
|
||||||
|
|||||||
Reference in New Issue
Block a user