Take the /bin/wifi lock in Waveguide scans.
This should reduce how often conman and waveguide race each other at
system boot time.
Also, fix locking:
* Only take the lock once per invocation of /bin/wifi (!!!)
* Try to release the lock when we're done. :)
Change-Id: Ib86e410f3eb23341ab97f92b4619fa099548dee2
diff --git a/waveguide/fake/wifi b/waveguide/fake/wifi
new file mode 100755
index 0000000..9270bc7
--- /dev/null
+++ b/waveguide/fake/wifi
@@ -0,0 +1,28 @@
+#!/bin/sh
+echo "fake/wifi:" "$@" >&2
+cd "$(dirname "$0")"
+
+if [ "$1" = "scan" ]; then
+ # TODO(willangley): pass the dev in an env var for tests, since looking it up
+ # from the platform cannot be expected to work.
+ iw_scan="./iw dev wlan-22:22 scan"
+ while [ -n "$2" ]; do
+ shift
+ case "$1" in
+ -b)
+ shift
+ ;;
+ --scan-freq)
+ shift
+ iw_scan="$iw_scan freq $1"
+ ;;
+ --scan-*)
+ iw_scan="$iw_scan ${1#--scan-}"
+ ;;
+ esac
+ done
+ exec $iw_scan
+else
+ echo "fake/wifi: first arg ('$1') must be 'scan'" >&2
+ exit 99
+fi
diff --git a/waveguide/waveguide.py b/waveguide/waveguide.py
index b419ced..db2f9ed 100755
--- a/waveguide/waveguide.py
+++ b/waveguide/waveguide.py
@@ -93,6 +93,15 @@
consensus_start = None
+def BandForFreq(freq):
+ if freq / 100 == 24:
+ return '2.4'
+ elif freq / 1000 == 5:
+ return '5'
+ else:
+ raise ValueError('Frequency %d is not in any known band', freq)
+
+
def UpdateConsensus(new_uptime_ms, new_consensus_key):
"""Update the consensus key based on received multicast packets."""
global consensus_key, consensus_start
@@ -324,9 +333,15 @@
args=['iw', 'dev', self.vdevname, 'info'])
# channel scan more than once in case we miss hearing a beacon
for _ in range(opt.initial_scans):
+ if self.flags & wgdata.ApFlags.Can2G:
+ band = '2.4'
+ elif self.flags & wgdata.ApFlags.Can5G:
+ band = '5'
+
RunProc(
callback=self._ScanResults,
- args=['iw', 'dev', self.vdevname, 'scan', 'ap-force', 'passive'])
+ args=['wifi', 'scan', '-b', band, '--scan-ap-force',
+ '--scan-passive'])
self.UpdateStationInfo()
self.next_scan_time = now
self.did_initial_scan = True
@@ -338,8 +353,9 @@
self.Log('scanning %d MHz (%d/%d)', scan_freq, self.scan_idx + 1,
len(self.allowed_freqs))
RunProc(callback=self._ScanResults,
- args=['iw', 'dev', self.vdevname, 'scan', 'freq', str(scan_freq),
- 'ap-force', 'passive'])
+ args=['wifi', 'scan', '-b', BandForFreq(scan_freq),
+ '--scan-freq', str(scan_freq), '--scan-ap-force',
+ '--scan-passive'])
chan_interval = opt.scan_interval / len(self.allowed_freqs)
# Randomly fiddle with the timing to avoid permanent alignment with
# other nodes also doing scans. If we're perfectly aligned with
@@ -586,9 +602,10 @@
disabled = (g.group(3) == 'disabled')
self.Debug('phy freq=%d chan=%d disabled=%d', freq, chan, disabled)
if not disabled:
- if freq / 100 == 24:
+ band = BandForFreq(freq)
+ if band == '2.4':
self.flags |= wgdata.ApFlags.Can2G
- if freq / 1000 == 5:
+ elif band == '5':
self.flags |= wgdata.ApFlags.Can5G
self.allowed_freqs.add(freq)
freq_to_chan[freq] = chan
diff --git a/wifi/iw.py b/wifi/iw.py
index db6590f..647e56c 100644
--- a/wifi/iw.py
+++ b/wifi/iw.py
@@ -53,8 +53,9 @@
return subprocess.check_output(('iw', 'dev', interface, 'link'), **kwargs)
-def _scan(interface, **kwargs):
- return subprocess.check_output(('iw', 'dev', interface, 'scan'), **kwargs)
+def _scan(interface, scan_args, **kwargs):
+ return subprocess.check_output(['iw', 'dev', interface, 'scan'] + scan_args,
+ **kwargs)
_WIPHY_RE = re.compile(r'Wiphy (?P<phy>\S+)')
@@ -362,6 +363,6 @@
return result
-def scan(interface):
+def scan(interface, scan_args):
"""Return 'iw scan' output for printing."""
- return _scan(interface)
+ return _scan(interface, scan_args)
diff --git a/wifi/utils.py b/wifi/utils.py
index 7a90065..c3b237e 100644
--- a/wifi/utils.py
+++ b/wifi/utils.py
@@ -355,3 +355,7 @@
subprocess.call(['lockfile-create', '--use-pid', '--retry', str(retries),
lockfile])
signal.alarm(0)
+
+
+def unlock(lockfile):
+ subprocess.call(['lockfile-remove', lockfile])
diff --git a/wifi/wifi.py b/wifi/wifi.py
index fb38bcd..bd796a1 100755
--- a/wifi/wifi.py
+++ b/wifi/wifi.py
@@ -4,6 +4,7 @@
from __future__ import print_function
+import atexit
import glob
import os
import re
@@ -50,10 +51,14 @@
P,persist For set commands, persist options so we can restore them with 'wifi restore'. For stop commands, remove persisted options.
S,interface-suffix= Interface suffix []
lock-timeout= How long, in seconds, to wait for another /bin/wifi process to finish before giving up. [60]
+scan-ap-force (Scan only) scan when in AP mode
+scan-passive (Scan only) do not probe, scan passively
+scan-freq= (Scan only) limit scan to specific frequencies.
"""
_FINGERPRINTS_DIRECTORY = '/tmp/wifi/fingerprints'
_LOCKFILE = '/tmp/wifi/wifi'
+lockfile_taken = False
# pylint: disable=protected-access
@@ -513,7 +518,15 @@
if interface is None:
raise utils.BinWifiException('No client interface for band %s', band)
- print(iw.scan(interface))
+ scan_args = []
+ if opt.scan_ap_force:
+ scan_args += ['ap-force']
+ if opt.scan_passive:
+ scan_args += ['passive']
+ if opt.scan_freq:
+ scan_args += ['freq', opt.scan_freq]
+
+ print(iw.scan(interface, scan_args))
return True
@@ -976,6 +989,8 @@
Raises:
BinWifiException: On file write failures.
"""
+ global lockfile_taken
+
optspec = _OPTSPEC_FORMAT.format(
bin=__file__.split('/')[-1],
ssid='%s_TestWifi' % subprocess.check_output(('serial')).strip())
@@ -983,8 +998,6 @@
opt, _, extra = parser.parse(argv)
stringify_options(opt)
- utils.lock(_LOCKFILE, int(opt.lock_timeout))
-
if not extra:
parser.fatal('Must specify a command (see usage for details).')
return 1
@@ -1008,6 +1021,11 @@
except KeyError:
parser.fatal('Unrecognized command %s' % extra[0])
+ if not lockfile_taken:
+ utils.lock(_LOCKFILE, int(opt.lock_timeout))
+ atexit.register(utils.unlock, _LOCKFILE)
+ lockfile_taken = True
+
success = function(opt)
if success: