summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/vyos/utils/wwan.py42
1 files changed, 40 insertions, 2 deletions
diff --git a/python/vyos/utils/wwan.py b/python/vyos/utils/wwan.py
index fd8cd4f2e..e677c7fa8 100644
--- a/python/vyos/utils/wwan.py
+++ b/python/vyos/utils/wwan.py
@@ -23,6 +23,8 @@ invocations in one place means a re-dial can never drift from what conf_mode
would have done.
"""
+import os
+
from time import sleep
from vyos.utils.dict import dict_search
@@ -39,6 +41,14 @@ service_name = 'ModemManager.service'
modem_wait_timeout = 25
modem_wait_poll = 0.250
+# Markers for WWAN interfaces the operator has taken down with op-mode
+# "disconnect interface wwanN". vyos-netlinkd re-dials every configured
+# interface that has lost its session, which would otherwise bring the
+# interface back up within one reconcile interval and make the disconnect look
+# like it never happened. Kept in /run - a manual disconnect is not meant to
+# survive a reboot, and a commit re-asserts the configured state too.
+admin_disconnect_dir = '/run/vyos-wwan'
+
def modem_index(ifname: str) -> str:
""" Return the ModemManager modem index backing an interface, wwan0 -> 0 """
if not ifname.startswith('wwan'):
@@ -92,11 +102,39 @@ def connect_options(config: dict) -> str:
return options
-def modem_disconnect(ifname: str) -> None:
+def _admin_disconnect_marker(ifname: str) -> str:
+ return os.path.join(admin_disconnect_dir, f'{ifname}.disconnected')
+
+def set_admin_disconnected(ifname: str) -> None:
+ """ Mark a WWAN interface as administratively disconnected, so it is left
+ alone by the re-dial pass in vyos-netlinkd """
+ # rejects anything that is not a WWAN interface, so a bogus name can never
+ # end up creating a file here
+ modem_index(ifname)
+ os.makedirs(admin_disconnect_dir, exist_ok=True)
+ with open(_admin_disconnect_marker(ifname), 'w'):
+ pass
+
+def clear_admin_disconnected(ifname: str) -> None:
+ """ Take a WWAN interface out of the administratively disconnected state """
+ modem_index(ifname)
+ try:
+ os.unlink(_admin_disconnect_marker(ifname))
+ except FileNotFoundError:
+ pass
+
+def is_admin_disconnected(ifname: str) -> bool:
+ """ True if a WWAN interface was taken down with op-mode "disconnect" and
+ has not been connected again since """
+ return os.path.exists(_admin_disconnect_marker(ifname))
+
+def modem_disconnect(ifname: str, quiet: bool = False) -> None:
""" Disconnect every bearer of the modem backing ifname. The number of
bearers a modem can hold is limited, so we always disconnect before we
dial again. """
- call(f'mmcli --modem {modem_index(ifname)} --simple-disconnect')
+ call(f'mmcli --modem {modem_index(ifname)} --simple-disconnect',
+ stdout=DEVNULL if quiet else None,
+ stderr=DEVNULL if quiet else None)
def modem_connect(ifname: str, options: str) -> bool:
""" Dial the modem backing ifname, returns True if the modem connected """