diff --git a/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc b/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc index d4ede8550..65a7cd2f9 100644 --- a/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc +++ b/feeds/ucentral/rrmd/files/usr/share/rrmd/local.uc @@ -32,6 +32,17 @@ function channel_to_freq(cur_freq, channel) { return null; } +function freq2band(freq) { + if (freq < 2500) { + return "2G"; + } else if (freq <= 5885) { + return "5G"; + } else if (freq < 7115){ + return "6G"; + } + return "na" +} + function channel_survey(dev) { /* trigger the nl80211 call that gathers channel survey data */ let res = nl80211.request(def.NL80211_CMD_GET_SURVEY, def.NLM_F_DUMP, { dev }); @@ -151,6 +162,8 @@ function interfaces_subunsub(path, sub) { interfaces[name][prop] = status[prop]; interfaces[name].config = cfg; interfaces[name].phy = status.phy; + interfaces[name].virtual_phys = length(split(status.phy, ".")) > 1 ? true : false; + interfaces[name].band = freq2band(status?.freq); /* ask hostapd for the local neighbourhood report data */ let rrm = global.ubus.conn.call(path, 'rrm_nr_get_own'); diff --git a/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc b/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc index d8cca25ac..39c1eb2b8 100644 --- a/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc +++ b/feeds/ucentral/rrmd/files/usr/share/rrmd/scan.uc @@ -1,7 +1,13 @@ const SCAN_FLAG_AP = (1<<2); +const PHY_SCAN_STATE_READY = 0; +const PHY_SCAN_STATE_TRIGGERED = 1; +const PHY_SCAN_STATE_STARTED = 2; +const PHY_SCAN_STATE_COMPLETED = 3; +const PHY_SCAN_STATE_BLOCKED = 4; let phys = {}; let beacons = {}; +let scan_blocked_cnt = 0; function scan(phy, params) { if (params.wiphy_freq) { @@ -17,7 +23,7 @@ function scan(phy, params) { printf("Unable to trigger scan: " + global.nl80211.error() + "\n"); else printf('triggered scan on %s\n', params?.dev); - phys[phy].pending = true; + phys[phy].state = PHY_SCAN_STATE_TRIGGERED; phys[phy].last = time(); } @@ -70,21 +76,56 @@ function scan_parse(data) { printf('%.J\n', beacons); } +function get_scan_res(dev) { + let res = global.nl80211.request(global.nl80211.const.NL80211_CMD_GET_SCAN, global.nl80211.const.NLM_F_DUMP, { dev }); + if (!res || res == false) { + ulog_err("Unable to get scan results: " + global.nl80211.error() + "\n"); + return; + } + scan_parse(res); +} + function scan_timer() { try { + let scan_trigger = false; + let cur_blocked = 0; + let last_blocked = 0; for (let k, v in phys) { - if (v.pending && time() - v.last >= v.delay) { + let scan_pending = (v.state == PHY_SCAN_STATE_TRIGGERED || v.state == PHY_SCAN_STATE_STARTED) ? true : false; + + /* It should not happen, get_scan is handled by NL CB */ + if (scan_pending && time() - v.last >= v.delay) { + ulog_warn("Scanning process too long, phy state: %s\n", phys[k]); 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.state = PHY_SCAN_STATE_READY; + scan_pending = false; v.last = time(); - v.delay = 1; } - if (!v.pending && time() - v.last >= global.config.scan_interval) { + if (!v?.channels || !v?.num_chan) + continue; + + /* Running scanning parallel on virtual phys not allowed */ + if (v?.virtual_phys) { + if (v?.state == PHY_SCAN_STATE_BLOCKED) + last_blocked++; + else if (scan_blocked_cnt > 0) + continue; + + if (scan_trigger) { + v.state = PHY_SCAN_STATE_BLOCKED; + cur_blocked++; + continue; + } else if (v.state == PHY_SCAN_STATE_BLOCKED) { + v.state = PHY_SCAN_STATE_READY; + } + } + + if (!scan_pending && time() - v.last >= global.config.scan_interval) { let dev = global.local.lookup(k); scan(k, { dev, @@ -92,8 +133,17 @@ function scan_timer() { measurement_duration: global.config.scan_dwell_time, }); + v.state = PHY_SCAN_STATE_TRIGGERED; + scan_trigger = true; v.curr_chan = (v.curr_chan + 1) % v.num_chan; } + /* Shouldn't never happen */ + if (scan_blocked_cnt > 0 && scan_blocked_cnt != last_blocked) { + log_warn("Mismatch in blocked phys config: %s -> %s\n", phys.blocked, last_blocked); + scan_blocked_cnt = 0; + } else { + scan_blocked_cnt = cur_blocked; + } } @@ -103,17 +153,79 @@ function scan_timer() { // return 1000; } +function get_phy_from_msg(msg) { + if (!msg?.msg) + return; + + let phy = "phy" + msg.msg.wiphy; + let dev = msg.msg?.dev; + if (!dev) + dev = global.local.lookup(phy); + if (!dev) + return null; + + if (global.local.interfaces[dev]?.virtual_phys) + phy = global.local.interfaces[dev].phy; + + if (!phy) + return null; + + return phy; +} + +function nl_handle_scan_msg(msg) { + let phy = get_phy_from_msg(msg); + if (!phy) + return; + + phys[phy].last = time(); + phys[phy].state = PHY_SCAN_STATE_COMPLETED; + //get_scan_res(msg.msg?.dev); +} + +function nl_scan_res_cb(msg) { + nl_handle_scan_msg(msg); +} + +function nl_scan_abort_cb(msg) { + nl_handle_scan_msg(msg); +} + +function nl_scan_start_cb(msg) { + let phy = get_phy_from_msg(msg); + if (!phy) + return; + + if (!phys[phy]) + return; + + if (phys[phy].state != PHY_SCAN_STATE_TRIGGERED) { + ulog_warn("Skip scan results not started by scan module: %s\n", msg); + return; + } + + phys[phy].state = PHY_SCAN_STATE_STARTED; +} + return { beacons, add_wdev: function(dev, phy) { if (phys[phy]) return; + + let p = split(phy, '.'); + let virtual_phys = length(p) > 1 ? true : false; + let bands = global.phy.phys[phy]?.band; + if (!bands) + bands = [ global.local.interfaces[dev].band ]; + + if (!bands) + return; let channels; let offset = 0; - if (!global.phy.phys[phy]) - return; - switch (global.phy.phys[phy].band[0]) { + + switch (bands[0]) { case '2G': channels = global.config.channels_2g; break; @@ -132,8 +244,12 @@ return { channels, offset, num_chan, + bands, curr_chan: 0, - delay: 5, + virtual_phys, + delay: 25, + state: PHY_SCAN_STATE_READY, + parent_phy: p[0], }; }, @@ -143,5 +259,8 @@ return { init: function() { uloop_timeout(scan_timer, 5000); + nl80211.listener(nl_scan_start_cb, [ nl80211.const.NL80211_CMD_TRIGGER_SCAN ]); + nl80211.listener(nl_scan_res_cb, [ nl80211.const.NL80211_CMD_NEW_SCAN_RESULTS ]); + nl80211.listener(nl_scan_abort_cb, [ nl80211.const.NL80211_CMD_SCAN_ABORTED ]); }, };