fix(reliability): rfplan review fixes — cli commit, assoc poll, ensure_attack wiring, idle reload
This commit is contained in:
@@ -1,9 +1,16 @@
|
||||
"""Mark VIII RF role manager: radio1/phy1 is shared between an uplink STA
|
||||
(``wlan1up``) and attack work, so the roles are made mutually exclusive.
|
||||
Uplink pauses channel hopping; attack/idle resumes it."""
|
||||
import time
|
||||
|
||||
ROLE_KEY = 'mk8.rfplan.role'
|
||||
IFACE = 'wlan1up'
|
||||
|
||||
# wifi reload returns while wpa_supplicant is still scanning/authenticating;
|
||||
# poll instead of checking once or every real uplink would false-fail.
|
||||
ASSOC_ATTEMPTS = 5
|
||||
ASSOC_WAIT_SECONDS = 2
|
||||
|
||||
|
||||
def current_role():
|
||||
from server import _uci_values
|
||||
@@ -22,7 +29,9 @@ def associated():
|
||||
for line in (out or '').splitlines():
|
||||
line = line.strip()
|
||||
if line.startswith('Connected to '):
|
||||
return line.split()[2]
|
||||
parts = line.split()
|
||||
if len(parts) >= 3:
|
||||
return parts[2]
|
||||
return None
|
||||
|
||||
|
||||
@@ -31,6 +40,24 @@ def hop_paused():
|
||||
return _read_hop() == '0'
|
||||
|
||||
|
||||
def _ensure_cli_network():
|
||||
"""Make network 'cli' usable for the STA. Returns True when a network
|
||||
change was staged and still needs ``uci commit network``. Stock firmware
|
||||
ships 'cli' present but disabled; create a minimal DHCP interface when it
|
||||
is missing entirely so netifd can bring wlan1up up either way."""
|
||||
from server import device_run
|
||||
rc, _, _ = device_run(['uci', '-q', 'get', 'network.cli'])
|
||||
if rc != 0:
|
||||
device_run(['uci', 'set', 'network.cli=interface'])
|
||||
device_run(['uci', 'set', 'network.cli.proto=dhcp'])
|
||||
return True
|
||||
rc, out, _ = device_run(['uci', '-q', 'get', 'network.cli.disabled'])
|
||||
if rc == 0 and out.strip() == '1':
|
||||
device_run(['uci', 'set', 'network.cli.disabled=0'])
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def set_role(role, ssid=None, psk=None):
|
||||
from server import device_run, _pause_hop, _resume_hop
|
||||
if role not in ('uplink', 'attack', 'idle'):
|
||||
@@ -52,17 +79,19 @@ def set_role(role, ssid=None, psk=None):
|
||||
cmds.append(['uci', 'set', 'wireless.wlan1up.key=%s' % psk])
|
||||
for c in cmds:
|
||||
device_run(c)
|
||||
# The STA rides network 'cli'; stock firmware ships it disabled but
|
||||
# present. If it is missing entirely, create a minimal DHCP interface
|
||||
# so netifd can bring wlan1up up.
|
||||
rc, _, _ = device_run(['uci', 'show', 'network.cli'])
|
||||
if rc != 0:
|
||||
device_run(['uci', 'set', 'network.cli=interface'])
|
||||
device_run(['uci', 'set', 'network.cli.proto=dhcp'])
|
||||
if _ensure_cli_network():
|
||||
# netifd consumes committed config only; staging without commit
|
||||
# would leave the STA with no L3 attachment.
|
||||
device_run(['uci', 'commit', 'network'])
|
||||
device_run(['uci', 'commit', 'wireless'])
|
||||
_pause_hop()
|
||||
device_run(['wifi', 'reload'], timeout=60)
|
||||
assoc = associated()
|
||||
assoc = None
|
||||
for _ in range(ASSOC_ATTEMPTS):
|
||||
time.sleep(ASSOC_WAIT_SECONDS)
|
||||
assoc = associated()
|
||||
if assoc:
|
||||
break
|
||||
if not assoc:
|
||||
disable_uplink()
|
||||
_resume_hop()
|
||||
@@ -71,6 +100,20 @@ def set_role(role, ssid=None, psk=None):
|
||||
# attack/idle: tear down the STA so radio1 is free again.
|
||||
disable_uplink()
|
||||
_resume_hop()
|
||||
if role == 'attack':
|
||||
# The deploy path performs its own wifi reload right after; teardown
|
||||
# converges there without a second reload churn on this phy.
|
||||
try:
|
||||
import mk8_events
|
||||
mk8_events.log_event(
|
||||
'rfplan', msg='rfplan role attack applied; STA teardown '
|
||||
'applies at next wifi reload')
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
# idle has no guaranteed follow-up reload anywhere else, so converge
|
||||
# now while the gated watchdog is still armed.
|
||||
device_run(['wifi', 'reload'], timeout=60)
|
||||
return {'ok': True, 'role': role}
|
||||
|
||||
|
||||
@@ -81,7 +124,8 @@ def disable_uplink():
|
||||
|
||||
|
||||
def ensure_attack():
|
||||
"""Exclusivity hook for attack enable paths: switch uplink off first."""
|
||||
"""Exclusivity hook for radio1 attack-AP enable paths: switch the
|
||||
uplink off first so one phy never carries STA + AP at once."""
|
||||
if current_role() == 'uplink':
|
||||
return set_role('attack')
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user