mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 09:32:34 +00:00
rrm: add background scanning
Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
@@ -1,6 +1,20 @@
|
||||
config base
|
||||
option station_update 1000
|
||||
option station_expiry 120
|
||||
option beacon_request_assoc 1
|
||||
option station_stats_interval 60
|
||||
option scan_interval 5
|
||||
option scan_dwell_time 70
|
||||
list channels_2g 2412
|
||||
list channels_2g 2437
|
||||
list channels_2g 2462
|
||||
list channels_5g 5180
|
||||
list channels_5g 5260
|
||||
list channels_5g 5500
|
||||
list channels_5g 5580
|
||||
list channels_5g 5660
|
||||
list channels_5g 5745
|
||||
option offset_5g 30
|
||||
|
||||
config policy
|
||||
option name snr
|
||||
|
||||
@@ -11,3 +11,11 @@ start_service() {
|
||||
procd_set_param respawn 3600 5 0
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger rrm
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
ubus call rrm reload
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
push(REQUIRE_SEARCH_PATH, '/usr/share/rrmd/*.uc');
|
||||
|
||||
global.nl80211 = require("nl80211");
|
||||
global.uloop = require("uloop");
|
||||
global.fs = require('fs');
|
||||
|
||||
global.ulog = {
|
||||
@@ -60,6 +61,20 @@ global.ubus = {
|
||||
return global.policy.status(msg);
|
||||
},
|
||||
},
|
||||
|
||||
reload: {
|
||||
cb: function(msg) {
|
||||
global.config.init();
|
||||
for (let module in [ 'local', 'station' ])
|
||||
global[module].reload();
|
||||
},
|
||||
},
|
||||
|
||||
scan_dump: {
|
||||
cb: function(msg) {
|
||||
return global.scan.beacons;
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -68,7 +83,7 @@ global.start = function() {
|
||||
global.uci = require('uci').cursor();
|
||||
global.ubus.conn = require('ubus').connect();
|
||||
|
||||
for (let module in [ 'config', 'event', 'phy', 'neighbor', 'local', 'station', 'command', 'policy' ]) {
|
||||
for (let module in [ 'config', 'event', 'phy', 'scan', 'neighbor', 'local', 'station', 'command', 'policy' ]) {
|
||||
printf('loading ' + module + '\n');
|
||||
global[module] = require(module);
|
||||
if (exists(global[module], 'init'))
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
let nl80211 = require("nl80211");
|
||||
let def = nl80211.const;
|
||||
let hapd_subscriber;
|
||||
let interfaces_subscriber;
|
||||
let ucentral_subscriber;
|
||||
let state = {};
|
||||
let hapd = {};
|
||||
let interfaces = {};
|
||||
let handlers = {};
|
||||
|
||||
function channel_to_freq(cur_freq, channel) {
|
||||
@@ -41,10 +41,10 @@ function channel_survey(dev) {
|
||||
|
||||
/* iterate over the result and filter out the correct channel */
|
||||
for (let survey in res) {
|
||||
if (survey?.survey_info?.frequency != hapd[dev].freq)
|
||||
if (survey?.survey_info?.frequency != interfaces[dev].freq)
|
||||
continue;
|
||||
if (survey.survey_info.noise)
|
||||
hapd[dev].noise = survey.survey_info.noise;
|
||||
interfaces[dev].noise = survey.survey_info.noise;
|
||||
if (survey.survey_info.time && survey.survey_info.busy) {
|
||||
let time = survey.survey_info.time - (state[dev].time || 0);
|
||||
let busy = survey.survey_info.busy - (state[dev].busy || 0);
|
||||
@@ -52,22 +52,58 @@ function channel_survey(dev) {
|
||||
state[dev].busy = survey.survey_info.busy;
|
||||
|
||||
let load = (100 * busy) / time;
|
||||
if (hapd[dev].load)
|
||||
hapd[dev].load = 0.85 * hapd[dev].load + 0.15 * load;
|
||||
if (interfaces[dev].load)
|
||||
interfaces[dev].load = 0.85 * interfaces[dev].load + 0.15 * load;
|
||||
else
|
||||
hapd[dev].load = load;
|
||||
interfaces[dev].load = load;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hapd_update() {
|
||||
function interfaces_update() {
|
||||
/* todo: prefilter frequency */
|
||||
for (let key in state)
|
||||
channel_survey(key);
|
||||
return 5000;
|
||||
}
|
||||
|
||||
function hapd_subunsub(path, sub) {
|
||||
let prev_station = {};
|
||||
let stations_stats;
|
||||
stations_stats = {
|
||||
run: function() {
|
||||
if (+global.config.station_stats_interval)
|
||||
this.timer = global.uloop.timer(+global.config.station_stats_interval, stations_stats.run);
|
||||
let stations = { };
|
||||
let next_stations = { };
|
||||
|
||||
for (let iface in interfaces) {
|
||||
let clients = global.ubus.conn.call('hostapd.' + iface, 'get_clients');
|
||||
for (let k, v in clients?.clients) {
|
||||
stations[k] = {};
|
||||
next_stations[k] = {};
|
||||
for (let val in [ 'bytes', 'airtime', 'packets', ])
|
||||
if (v[val]) {
|
||||
stations[k][val] = v[val];
|
||||
next_stations[k][val] = v[val];
|
||||
if (prev_station[k])
|
||||
for (let type in [ 'tx', 'rx' ])
|
||||
stations[k][val][type] -= prev_station[k][val][type];
|
||||
|
||||
}
|
||||
for (let val in [ 'rate', 'mcs', 'signal', 'signal_mgmt', 'retries', 'failed', ])
|
||||
stations[k][val] = v[val];
|
||||
if (global.station.stations[k]) {
|
||||
stations[k].bssid = global.station.stations[k].bssid;
|
||||
stations[k].ssid = global.station.stations[k].ssid;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_station = next_stations;
|
||||
global.event.send('rrm.stations', stations);
|
||||
}
|
||||
};
|
||||
|
||||
function interfaces_subunsub(path, sub) {
|
||||
/* check if this is a hostapd instance */
|
||||
let name = split(path, '.');
|
||||
|
||||
@@ -79,9 +115,9 @@ function hapd_subunsub(path, sub) {
|
||||
|
||||
/* the hostapd instance disappeared */
|
||||
if (!sub) {
|
||||
global.event.send('rrm.bss.del', { bssid: hapd[name] });
|
||||
global.event.send('rrm.bss.del', { bssid: interfaces[name] });
|
||||
global.neighbor.local_del(name);
|
||||
delete hapd[name];
|
||||
delete interfaces[name];
|
||||
delete state[name];
|
||||
return;
|
||||
}
|
||||
@@ -96,7 +132,7 @@ function hapd_subunsub(path, sub) {
|
||||
cfg = {};
|
||||
|
||||
/* subscibe to hostapd */
|
||||
hapd_subscriber.subscribe(path);
|
||||
interfaces_subscriber.subscribe(path);
|
||||
|
||||
/* tell hostapd to wait for a reply before answering probe requests */
|
||||
//global.ubus.conn.call(path, 'notify_response', { 'notify_response': 1 });
|
||||
@@ -105,18 +141,19 @@ function hapd_subunsub(path, sub) {
|
||||
global.ubus.conn.call(path, 'bss_mgmt_enable', { 'neighbor_report': 1, 'beacon_report': 1, 'bss_transition': 1 });
|
||||
|
||||
/* instantiate state */
|
||||
hapd[name] = { };
|
||||
interfaces[name] = { };
|
||||
state[name] = { };
|
||||
|
||||
for (let prop in [ 'ssid', 'bssid', 'freq', 'channel', 'op_class', 'uci_section' ])
|
||||
if (status[prop])
|
||||
hapd[name][prop] = status[prop];
|
||||
hapd[name].config = cfg;
|
||||
interfaces[name][prop] = status[prop];
|
||||
interfaces[name].config = cfg;
|
||||
interfaces[name].phy = status.phy;
|
||||
|
||||
/* ask hostapd for the local neighbourhood report data */
|
||||
let rrm = global.ubus.conn.call(path, 'rrm_nr_get_own');
|
||||
if (rrm && rrm.value) {
|
||||
hapd[name].rrm_nr = rrm.value;
|
||||
interfaces[name].rrm_nr = rrm.value;
|
||||
global.neighbor.local_add(name, rrm.value);
|
||||
}
|
||||
|
||||
@@ -127,13 +164,16 @@ function hapd_subunsub(path, sub) {
|
||||
|
||||
/* send an event */
|
||||
global.event.send('rrm.bss.add', {
|
||||
bssid: hapd[name].bssid,
|
||||
ssid: hapd[name].ssid,
|
||||
freq: hapd[name].freq,
|
||||
channel: hapd[name].channel,
|
||||
op_class: hapd[name].op_class,
|
||||
rrm_nr: hapd[name].rrm_nr,
|
||||
bssid: interfaces[name].bssid,
|
||||
ssid: interfaces[name].ssid,
|
||||
freq: interfaces[name].freq,
|
||||
channel: interfaces[name].channel,
|
||||
op_class: interfaces[name].op_class,
|
||||
rrm_nr: interfaces[name].rrm_nr,
|
||||
});
|
||||
|
||||
/* tell the scanning code about the device */
|
||||
global.scan.add_wdev(name, status.phy);
|
||||
}
|
||||
|
||||
function ucentral_subunsub(sub) {
|
||||
@@ -142,14 +182,14 @@ function ucentral_subunsub(sub) {
|
||||
ucentral_subscriber.subscribe('ucentral');
|
||||
}
|
||||
|
||||
function hapd_listener(event, msg) {
|
||||
hapd_subunsub(msg.path, event == 'ubus.object.add');
|
||||
function interfaces_listener(event, msg) {
|
||||
interfaces_subunsub(msg.path, event == 'ubus.object.add');
|
||||
|
||||
if (msg.path == 'ucentral')
|
||||
ucentral_subunsub(event == 'ubus.object.add');
|
||||
}
|
||||
|
||||
function hapd_handle_event(req) {
|
||||
function interfaces_handle_event(req) {
|
||||
/* iterate over all handlers for this event type, if 1 or more handlers replied with false, do not reply to the notification */
|
||||
let reply = true;
|
||||
for (let handler in handlers[req.type])
|
||||
@@ -169,31 +209,43 @@ function channel_switch_handler(type, data) {
|
||||
}
|
||||
|
||||
return {
|
||||
interfaces,
|
||||
|
||||
status: function() {
|
||||
return hapd;
|
||||
return interfaces;
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
/* stations statistics */
|
||||
if (+global.config.station_stats_interval)
|
||||
stations_stat.timer = global.uloop.timer(+global.config.station_stats_interval, stations_stats.run);
|
||||
else if (stations_stat.timer)
|
||||
stations_stat.timer.cancel();
|
||||
},
|
||||
|
||||
init: function() {
|
||||
hapd_subscriber = global.ubus.conn.subscriber(
|
||||
hapd_handle_event,
|
||||
interfaces_subscriber = global.ubus.conn.subscriber(
|
||||
interfaces_handle_event,
|
||||
function(msg) { });
|
||||
ucentral_subscriber = global.ubus.conn.subscriber(
|
||||
ucentral_handle_event,
|
||||
function(msg) { });
|
||||
|
||||
/* register a callback that will monitor hostapd instances spawning and disappearing */
|
||||
global.ubus.conn.listener('ubus.object.add', hapd_listener);
|
||||
global.ubus.conn.listener('ubus.object.remove', hapd_listener);
|
||||
global.ubus.conn.listener('ubus.object.add', interfaces_listener);
|
||||
global.ubus.conn.listener('ubus.object.remove', interfaces_listener);
|
||||
|
||||
/* iterade over all existing hostapd instances and subscribe to them */
|
||||
for (let path in global.ubus.conn.list()) {
|
||||
hapd_subunsub(path, true);
|
||||
interfaces_subunsub(path, true);
|
||||
if (path == 'ucentral')
|
||||
ucentral_subunsub(true);
|
||||
}
|
||||
|
||||
// uloop_timeout(hapd_update, 5000);
|
||||
// uloop_timeout(interfaces_update, 5000);
|
||||
global.local.register_handler('channel-switch', channel_switch_handler);
|
||||
|
||||
this.reload();
|
||||
},
|
||||
|
||||
register_handler: function(event, handler) {
|
||||
@@ -205,7 +257,7 @@ return {
|
||||
switch_chan: function(msg) {
|
||||
if (!msg.bssid || !msg.channel)
|
||||
return false;
|
||||
for (let bss, v in hapd) {
|
||||
for (let bss, v in interfaces) {
|
||||
if (v.bssid != lc(msg.bssid))
|
||||
continue;
|
||||
return global.ubus.conn.call('hostapd.' + bss, 'switch_chan', {
|
||||
@@ -217,7 +269,7 @@ return {
|
||||
},
|
||||
|
||||
bssid_to_phy: function(bssid) {
|
||||
for (let bss, v in hapd) {
|
||||
for (let bss, v in interfaces) {
|
||||
if (v.bssid != lc(bssid))
|
||||
continue;
|
||||
let iface = global.nl80211.request(global.nl80211.const.NL80211_CMD_GET_INTERFACE, 0, { dev: bss });
|
||||
@@ -227,7 +279,7 @@ return {
|
||||
},
|
||||
|
||||
txpower: function(bssid) {
|
||||
for (let bss, v in hapd) {
|
||||
for (let bss, v in interfaces) {
|
||||
if (v.bssid != lc(bssid))
|
||||
continue;
|
||||
let iface = global.nl80211.request(global.nl80211.const.NL80211_CMD_GET_INTERFACE, 0, { dev: bss });
|
||||
@@ -235,4 +287,15 @@ return {
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
lookup: function(phy) {
|
||||
for (let bss, v in interfaces)
|
||||
if (v.phy == phy)
|
||||
return bss;
|
||||
return null;
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
let uci = require("uci");
|
||||
let cursor = uci ? uci.cursor() : null;
|
||||
|
||||
const SCAN_FLAG_AP = (1<<2);
|
||||
|
||||
function freq2channel(freq) {
|
||||
if (freq == 2484)
|
||||
return 14;
|
||||
@@ -76,7 +78,7 @@ function lookup_phys() {
|
||||
if (!path)
|
||||
continue;
|
||||
|
||||
let p = { phyname, index: phy.wiphy };
|
||||
let p = { path, phyname, index: phy.wiphy };
|
||||
p.htmode = [];
|
||||
p.band = [];
|
||||
for (let band in phy.wiphy_bands) {
|
||||
@@ -129,7 +131,7 @@ function lookup_phys() {
|
||||
p.band = uniq(p.band);
|
||||
if (!length(p.dfs_channels))
|
||||
delete p.dfs_channels;
|
||||
ret[path] = p;
|
||||
ret[phyname] = p;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
156
feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc
Normal file
156
feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc
Normal file
@@ -0,0 +1,156 @@
|
||||
const SCAN_FLAG_AP = (1<<2);
|
||||
|
||||
let phys = {};
|
||||
let beacons = {};
|
||||
|
||||
function scan(phy, params) {
|
||||
if (params.wiphy_freq) {
|
||||
params.center_freq1 = params.wiphy_freq + phys[phy].offset;
|
||||
params.scan_ssids = [ '' ];
|
||||
}
|
||||
|
||||
params.scan_flags = SCAN_FLAG_AP;
|
||||
|
||||
printf('%.J\n', params);
|
||||
let res = global.nl80211.request(global.nl80211.const.NL80211_CMD_TRIGGER_SCAN, 0, params);
|
||||
if (res === false)
|
||||
printf("Unable to trigger scan: " + global.nl80211.error() + "\n");
|
||||
else
|
||||
printf('triggered scan on %s\n', params?.dev);
|
||||
phys[phy].pending = true;
|
||||
phys[phy].last = time();
|
||||
}
|
||||
|
||||
function scan_parse(data) {
|
||||
let seen = time();
|
||||
for (let bss in data) {
|
||||
bss = bss.bss;
|
||||
if (!bss)
|
||||
continue;
|
||||
let beacon = {
|
||||
freq: bss.frequency,
|
||||
signal: bss.signal_mbm / 100,
|
||||
seen,
|
||||
};
|
||||
for (let ie in bss.beacon_ies)
|
||||
switch (ie.type) {
|
||||
case 0:
|
||||
beacon.ssid = ie.data;
|
||||
break;
|
||||
case 114:
|
||||
beacon.meshid = ie.data;
|
||||
break;
|
||||
case 0xdd:
|
||||
let oui = hexenc(substr(ie.data, 0, 3));
|
||||
let type = ord(ie.data, 3);
|
||||
let data = substr(ie.data, 4);
|
||||
switch (oui) {
|
||||
case '48d017':
|
||||
beacon.tip = true;
|
||||
switch(type) {
|
||||
case 1:
|
||||
if (data)
|
||||
beacon.tip_name = data;
|
||||
break;
|
||||
case 2:
|
||||
if (data)
|
||||
beacon.tip_serial = data;
|
||||
break;
|
||||
case 3:
|
||||
if (data)
|
||||
beacon.tip_network_id = data;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
beacons[bss.bssid] = beacon;
|
||||
}
|
||||
printf('%.J\n', beacons);
|
||||
}
|
||||
|
||||
function scan_timer() {
|
||||
try {
|
||||
for (let k, v in phys) {
|
||||
if (v.pending && time() - v.last >= v.delay) {
|
||||
let dev = global.local.lookup(k);
|
||||
if (dev) {
|
||||
let res = global.nl80211.request(global.nl80211.const.NL80211_CMD_GET_SCAN, global.nl80211.const.NLM_F_DUMP, { dev });
|
||||
scan_parse(res);
|
||||
}
|
||||
v.pending = false;
|
||||
v.last = time();
|
||||
v.delay = 1;
|
||||
}
|
||||
|
||||
if (!v.pending && time() - v.last >= global.config.scan_interval) {
|
||||
let dev = global.local.lookup(k);
|
||||
scan(k, {
|
||||
dev,
|
||||
wiphy_freq: v.channels[v.curr_chan],
|
||||
measurement_duration: global.config.scan_dwell_time,
|
||||
|
||||
});
|
||||
v.curr_chan = (v.curr_chan + 1) % v.num_chan;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch(e) {
|
||||
printf('%.J\n', e.stacktrace[0].context);
|
||||
};
|
||||
return 1000;
|
||||
}
|
||||
|
||||
return {
|
||||
beacons,
|
||||
|
||||
add_wdev: function(dev, phy) {
|
||||
if (phys[phy])
|
||||
return;
|
||||
let channels;
|
||||
let offset = 0;
|
||||
printf('%s \n', global.phy.phys[phy].band[0]);
|
||||
switch (global.phy.phys[phy].band[0]) {
|
||||
case '2G':
|
||||
printf('fooo abc\n');
|
||||
channels = global.config.channels_2g;
|
||||
break;
|
||||
case '5G':
|
||||
channels = global.config.channels_5g;
|
||||
offset = global.config.offset_5g || 0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
printf('fooo, %.J\n', channels);
|
||||
|
||||
if (!channels)
|
||||
return;
|
||||
printf('fooo2\n');
|
||||
let num_chan = length(channels);
|
||||
printf('fooo3\n');
|
||||
phys[phy] = {
|
||||
channels,
|
||||
offset,
|
||||
num_chan,
|
||||
curr_chan: 0,
|
||||
delay: 5,
|
||||
};
|
||||
|
||||
printf('%.J\n', phys[phy]);
|
||||
|
||||
// scan(phy, { dev });
|
||||
// scan(phy, { dev, scan_ssids: [ '' ], });
|
||||
},
|
||||
|
||||
status: function() {
|
||||
return beacons;
|
||||
},
|
||||
|
||||
init: function() {
|
||||
uloop_timeout(scan_timer, 5000);
|
||||
},
|
||||
};
|
||||
@@ -29,17 +29,33 @@ function station_add(device, addr, data, seen, bssid) {
|
||||
beacon_report: {},
|
||||
};
|
||||
|
||||
if (config.beacon_request_assoc)
|
||||
stations[addr].beacon_request_assoc = time();
|
||||
}
|
||||
|
||||
/* update device, seen and signal data */
|
||||
stations[addr].device = device;
|
||||
stations[addr].seen = seen;
|
||||
stations[addr].ssid = global.local.interfaces[device].ssid;
|
||||
stations[addr].channel = global.local.interfaces[device].channel;
|
||||
stations[addr].op_class = global.local.interfaces[device].op_class;
|
||||
if (data.signal)
|
||||
stations[addr].signal = data.signal;
|
||||
|
||||
/* if the station just joined, send an event */
|
||||
if (add)
|
||||
global.event.send('rrm.station.add', { addr, rrm: stations[addr].rrm, bssid });
|
||||
|
||||
/* check if a beacon_report should be triggered */
|
||||
if (stations[addr].beacon_request_assoc && time() - stations[addr].beacon_request_assoc >= 30) {
|
||||
global.station.beacon_request({ addr, channel: stations[addr].channel});
|
||||
stations[addr].beacon_request_assoc = 0;
|
||||
}
|
||||
|
||||
if (stations[addr].beacon_report_seen && time() - stations[addr].beacon_report_seen > 3) {
|
||||
global.event.send('rrm.beacon.report', { addr, report: stations[addr].beacon_report });
|
||||
stations[addr].beacon_report_seen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function station_del(addr) {
|
||||
@@ -90,11 +106,15 @@ function beacon_report(type, report) {
|
||||
/* make sure that the station exists */
|
||||
if (!stations[report.address]) {
|
||||
ulog_err(`beacon report on unknown station ${report.address}\n`);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stations[report.address].beacon_report[report.bssid])
|
||||
return true;
|
||||
|
||||
/* store the report */
|
||||
let payload = {
|
||||
addr: report.address,
|
||||
bssid: report.bssid,
|
||||
seen: time(),
|
||||
channel: report.channel,
|
||||
@@ -102,7 +122,7 @@ function beacon_report(type, report) {
|
||||
rsni: report.rsni,
|
||||
};
|
||||
stations[report.address].beacon_report[report.bssid] = payload;
|
||||
global.event.send('rrm.beacon.report', payload);
|
||||
stations[report.address].beacon_report_seen = time();;
|
||||
}
|
||||
|
||||
function probe_handler(type, data) {
|
||||
@@ -122,6 +142,7 @@ function disassoc_handler(type, data) {
|
||||
}
|
||||
|
||||
return {
|
||||
stations,
|
||||
init: function() {
|
||||
/* register the mgmt frame handlers */
|
||||
global.local.register_handler('beacon-report', beacon_report);
|
||||
@@ -164,7 +185,7 @@ return {
|
||||
},
|
||||
|
||||
beacon_request: function(msg) {
|
||||
if (!msg.addr || (!msg.channel && !msg.ssid))
|
||||
if (!msg.addr)
|
||||
return false;
|
||||
|
||||
let station = stations[msg.addr];
|
||||
@@ -184,13 +205,12 @@ return {
|
||||
station.beacon_report = {};
|
||||
let payload = {
|
||||
addr: msg.addr,
|
||||
mode: msg.params?.mode || 1,
|
||||
op_class: msg.op_class || 128,
|
||||
mode: msg.mode || 1,
|
||||
op_class: station.op_class || 128,
|
||||
duration: msg.duration || 100,
|
||||
channel: (msg.channel == null) ? station.channel : msg.channel,
|
||||
};
|
||||
if (msg.channel)
|
||||
payload.channel = msg.channel;
|
||||
else
|
||||
if (msg.ssid)
|
||||
payload.ssid = msg.ssid;
|
||||
global.ubus.conn.call(`hostapd.${station.device}`, 'rrm_beacon_req', payload);
|
||||
|
||||
@@ -238,4 +258,7 @@ return {
|
||||
addr: msg.addr, duration: 20, abridged: 1, neighbors }) == null;
|
||||
return ret;
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"uuid": 2,
|
||||
"radios": [
|
||||
{
|
||||
"band": "2G",
|
||||
"country": "CA",
|
||||
"channel-mode": "HE",
|
||||
"channel-width": 80,
|
||||
"channel": 32
|
||||
}
|
||||
],
|
||||
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "WAN",
|
||||
"role": "upstream",
|
||||
"services": [ "lldp" ],
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"WAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "dynamic"
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "OpenWifi",
|
||||
"wifi-bands": [
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "LAN",
|
||||
"role": "downstream",
|
||||
"services": [ "ssh", "lldp" ],
|
||||
"ethernet": [
|
||||
{
|
||||
"select-ports": [
|
||||
"LAN*"
|
||||
]
|
||||
}
|
||||
],
|
||||
"ipv4": {
|
||||
"addressing": "static",
|
||||
"subnet": "192.168.1.1/24",
|
||||
"dhcp": {
|
||||
"lease-first": 10,
|
||||
"lease-count": 100,
|
||||
"lease-time": "6h"
|
||||
}
|
||||
},
|
||||
"ssids": [
|
||||
{
|
||||
"name": "OpenWifi",
|
||||
"wifi-bands": [
|
||||
"2G"
|
||||
],
|
||||
"bss-mode": "ap",
|
||||
"encryption": {
|
||||
"proto": "psk2",
|
||||
"key": "OpenWifi",
|
||||
"ieee80211w": "optional"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"statistics": {
|
||||
"interval": 120,
|
||||
"types": [ "ssids", "lldp", "clients" ]
|
||||
},
|
||||
"health": {
|
||||
"interval": 120
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"lldp": {
|
||||
"describe": "uCentral",
|
||||
"location": "universe"
|
||||
},
|
||||
"ssh": {
|
||||
"port": 22
|
||||
},
|
||||
"rrm": {
|
||||
"beacon-request-assoc": true,
|
||||
"station-stats-interval": 30
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user