From a272bffcf16c6c5ced83fb19a35aa3c78bbf7bff Mon Sep 17 00:00:00 2001 From: Adam Smith Date: Tue, 29 Sep 2026 13:41:40 +0000 Subject: wwan: T7487: identify modem by port ownership, not interface number modem_index() in python/vyos/utils/wwan.py derived the ModemManager modem index straight from the interface name (wwan0 -> 0). The kernel-assigned WWAN interface number and ModemManager's own modem index are two independently enumerated values and are not guaranteed to match - on a box with more than one modem, they can enumerate in different orders, so modem index 0 does not necessarily own wwan0. Every function in this module funnels through modem_index() (start_modem_manager, modem_disconnect, modem_connect, and both admin-disconnect marker helpers), and is_wwan_connected() in vyos.utils.network had its own separate copy of the same assumption - so a single reversed enumeration order silently commands the wrong physical modem for every one of them. modem_index() now lists every modem ModemManager currently knows about and returns whichever one actually has ifname in its own port list, instead of assuming the correspondence. A modem that has not shown up on the bus yet looks the same as one that will never exist, so this waits up to the same modem_wait_timeout budget start_modem_manager() already gives a modem to become dialable, then returns None if nothing claimed the interface. is_wwan_connected() now calls the same resolver instead of keeping its own copy of the old assumption. None is a real, expected return now, not just a theoretical one - the three callers that previously assumed modem_index() always produced *a* string (right or wrong) are updated: start_modem_manager() bails out early (matching the tolerance its own caller's w.exists() check already has for hardware that isn't detected yet), modem_disconnect() and modem_connect() treat it as nothing to disconnect / a failed dial, matching each function's own existing return contract. show_wwan.py's modem_info() raises a clear, specific error instead, which its own top-level exception handler already reports cleanly. set_admin_disconnected()/clear_admin_disconnected() only ever used modem_index() to validate the interface name looks like a WWAN interface in the first place, so they're unaffected. --- src/op_mode/show_wwan.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/op_mode/show_wwan.py b/src/op_mode/show_wwan.py index c9371f410..2215b499e 100755 --- a/src/op_mode/show_wwan.py +++ b/src/op_mode/show_wwan.py @@ -68,7 +68,10 @@ def mmcli(*args: str) -> dict: def modem_info(ifname: str) -> dict: """ Return everything ModemManager knows about the modem behind ifname """ - return mmcli('--modem', modem_index(ifname))['modem'] + index = modem_index(ifname) + if index is None: + raise ValueError(f'No modem found for interface "{ifname}"') + return mmcli('--modem', index)['modem'] def sim_info(modem: dict) -> dict: """ Return the properties of the SIM card inserted into a modem """ -- cgit v1.2.3