Skip to content

Conversation

@jancelin
Copy link
Collaborator

@jancelin jancelin commented Dec 3, 2025

Version française

Contexte

Plateforme : Orange Pi sous Armbian, avec modem 4G (SIMCom A76xx) configuré par rtkbase.
Le modem est vu comme une interface « USB Ethernet » (enx…) gérée par NetworkManager via la connexion Cellular Modem.

Problème observé : après quelques heures de fonctionnement, la connexion 4G ne permet plus d’accéder à Internet.
Symptômes :

  • nmcli indique toujours la connexion Cellular Modem comme activée ;
  • l’interface 4G a toujours une IP et une route par défaut ;
  • le modem est enregistré sur le réseau (+CEREG=1, +CGATT=1) et a un contexte data actif (AT+CGCONTRDP) ;
  • mais le ping (caster.centipede.fr / pch.net / 8.8.8.8) échoue systématiquement.

Un simple nmcli device disconnect <iface_4g> puis nmcli device connect <iface_4g> suffit à rétablir immédiatement la connexion, sans toucher au modem lui-même.


Comportement actuel de modem_check.py

modem_check.py :

  • vérifie l’état du modem (enregistrement, IP interne / publique) ;
  • teste la connectivité (ping caster.centipede.fr ou pch.net) ;
  • en cas d’échec, passe directement le modem en mode avion (AT+CFUN=0 puis AT+CFUN=1).

Dans le cas décrit ci-dessus, cette séquence CFUN ne suffit pas à rétablir le trafic IP, alors qu’un simple reconnect NetworkManager de l’interface 4G le fait.


Patch proposé

Le patch garde la logique existante mais ajoute une étape intermédiaire plus douce côté host :

  1. Ajout d’une fonction get_interface_name() qui récupère le nom de l’interface associée à la connexion Cellular Modem via nmcli connection show (GENERAL.DEVICES).

  2. Modification du test de connectivité :

    • utilisation d’un ping forcé sur l’interface 4G :
      ping -I <iface_4g> caster.centipede.fr (ou pch.net)
      plutôt qu’un ping global.
  3. En cas de problème (ip_in_use non nulle, public_ip non nulle, modem enregistré, mais ping KO) :

    • tentative de reconnexion NetworkManager uniquement :

      • si l’interface est connue :
        nmcli device disconnect <iface_4g> puis nmcli device connect <iface_4g>
      • sinon :
        nmcli connection down "Cellular Modem" puis nmcli connection up "Cellular Modem"
    • re-lecture de l’état (enregistrement, IP, ping).

    • si tout est OK → on logue que la connectivité a été restaurée et on ne touche pas au modem.

  4. Si après cette tentative NM la situation est toujours incorrecte (pas d’IP / pas d’enregistrement / ping toujours KO), on applique la logique existante : bascule en mode avion du modem (AT+CFUN=0 puis AT+CFUN=1).

  5. En complément, les appels à modem.close() sont protégés avec des try/except pour éviter des exceptions si l’objet n’est pas initialisé correctement.

Ce patch permet de corriger les pertes de connectivité liées à l’interface 4G / NetworkManager, tout en conservant le comportement d’origine sur les cas où le modem lui-même est en défaut.


English version

Context

Platform: Orange Pi running Armbian, with a 4G modem (SIMCom A76xx) configured by rtkbase.
The modem appears as a “USB Ethernet” interface (enx…) managed by NetworkManager through the Cellular Modem connection.

Observed issue: after a few hours, the 4G link stops providing Internet access.
Symptoms:

  • nmcli still reports the Cellular Modem connection as activated;
  • the 4G interface keeps its IP address and default route;
  • the modem is registered on the network (+CEREG=1, +CGATT=1) with an active data context (AT+CGCONTRDP);
  • but pings (caster.centipede.fr / pch.net / 8.8.8.8) always fail.

Running nmcli device disconnect <4g_iface> then nmcli device connect <4g_iface> immediately restores connectivity, without touching the modem itself.


Current modem_check.py behavior

modem_check.py:

  • checks modem status (registration, internal/public IP);
  • tests connectivity (ping caster.centipede.fr or pch.net);
  • on failure, directly toggles airplane mode on the modem (AT+CFUN=0 then AT+CFUN=1).

In the situation described above, the CFUN sequence does not restore IP traffic, while a simple NetworkManager reconnect of the 4G interface does.


Proposed patch

The patch keeps the existing logic, but adds a gentler host-side recovery step:

  1. Add a get_interface_name() helper that retrieves the device name attached to the Cellular Modem connection via nmcli connection show (GENERAL.DEVICES).

  2. Change the connectivity check to use interface-bound ping:

    • ping -I <4g_iface> caster.centipede.fr (or pch.net)
      instead of a global ping, so we really test the 4G path.
  3. When something looks wrong (non-null ip_in_use and public_ip, modem registered, but ping fails):

    • first try a NetworkManager reconnect only:

      • if the device name is known:
        nmcli device disconnect <4g_iface> then nmcli device connect <4g_iface>
      • otherwise:
        nmcli connection down "Cellular Modem" then nmcli connection up "Cellular Modem"
    • then re-check registration, IP addresses and ping.

    • if everything is back to normal → log that connectivity was restored and do not touch the modem.

  4. If, after this NM reconnect, the situation is still wrong (no IP, not registered, ping still failing), fall back to the original behavior: modem airplane-mode reset (AT+CFUN=0 then AT+CFUN=1).

  5. Additionally, modem.close() calls are wrapped in try/except blocks to avoid errors if the modem object is not properly initialized.

This patch fixes connectivity losses caused by the 4G interface / NetworkManager layer, while preserving the original CFUN-based recovery for cases where the modem itself is in a bad state.

…<4g_iface> immediately restores connectivity, without touching the modem itself
@jancelin
Copy link
Collaborator Author

jancelin commented Dec 3, 2025

example of logs with the patch
journalctl -u modem_check.service -n 100 --no-pager

  • Before- the patch
Dec 02 20:00:02 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 02 20:00:34 basegnss python[22714]: ping: caster.centipede.fr: System error
Dec 02 20:00:54 basegnss python[22716]: ping: pch.net: System error
Dec 02 20:01:56 basegnss python[22699]: Internal Ip address in use:  10.28.145.113
Dec 02 20:01:56 basegnss python[22699]: Modem public Ip address:  10.43.117.125
Dec 02 20:01:56 basegnss python[22699]: Request to switch to public IP address done!
Dec 02 20:01:56 basegnss python[22699]: It could take a few minutes to be active
Dec 02 20:01:56 basegnss python[22699]: closing modem connexion
Dec 02 20:01:56 basegnss python[22699]: Internal Ip address in use:  10.28.145.113
Dec 02 20:01:56 basegnss python[22699]: Modem public Ip address:  10.43.117.125
Dec 02 20:01:56 basegnss python[22699]: Ping caster.centipede.fr or pch.net False
Dec 02 20:01:56 basegnss python[22699]: Modem problem. Switching to airplane mode and back to normal
Dec 02 20:01:56 basegnss python[22699]: Connecting to modem...
Dec 02 20:01:56 basegnss python[22699]: Sending AT+CFUN=0
Dec 02 20:01:56 basegnss python[22699]: Sending AT+CFUN=1
Dec 02 20:01:57 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 02 20:01:57 basegnss systemd[1]: modem_check.service: Consumed 1.591s CPU time.
Dec 02 21:00:02 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 02 21:00:34 basegnss python[22875]: ping: caster.centipede.fr: System error
Dec 02 21:00:54 basegnss python[22877]: ping: pch.net: System error
Dec 02 21:01:53 basegnss python[22861]: Internal Ip address in use:  10.43.117.125
Dec 02 21:01:53 basegnss python[22861]: Modem public Ip address:  10.40.172.214
Dec 02 21:01:53 basegnss python[22861]: Request to switch to public IP address done!
Dec 02 21:01:53 basegnss python[22861]: It could take a few minutes to be active
Dec 02 21:01:53 basegnss python[22861]: closing modem connexion
Dec 02 21:01:53 basegnss python[22861]: Internal Ip address in use:  10.43.117.125
Dec 02 21:01:53 basegnss python[22861]: Modem public Ip address:  10.40.172.214
Dec 02 21:01:53 basegnss python[22861]: Ping caster.centipede.fr or pch.net False
Dec 02 21:01:53 basegnss python[22861]: Modem problem. Switching to airplane mode and back to normal
Dec 02 21:01:53 basegnss python[22861]: Connecting to modem...
Dec 02 21:01:53 basegnss python[22861]: Sending AT+CFUN=0
Dec 02 21:01:53 basegnss python[22861]: Sending AT+CFUN=1
Dec 02 21:01:53 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 02 21:01:53 basegnss systemd[1]: modem_check.service: Consumed 1.648s CPU time.
.....
  • After the patch
Dec 03 12:38:19 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 12:38:33 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 12:43:19 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 12:43:33 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 12:48:20 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 12:48:34 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 12:48:34 basegnss systemd[1]: modem_check.service: Consumed 1.015s CPU time.
Dec 03 12:53:20 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 12:53:36 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 12:58:20 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 12:59:15 basegnss python[26683]: Device 'enxae0c29a39b6d' successfully disconnected.
Dec 03 12:59:21 basegnss python[26719]: [97B blob data]
Dec 03 12:59:35 basegnss python[26621]: Internal Ip address in use:  100.68.8.31
Dec 03 12:59:35 basegnss python[26621]: Modem public Ip address:  100.70.142.197
Dec 03 12:59:35 basegnss python[26621]: Request to switch to public IP address done!
Dec 03 12:59:35 basegnss python[26621]: It could take a few minutes to be active
Dec 03 12:59:35 basegnss python[26621]: closing modem connexion
Dec 03 12:59:35 basegnss python[26621]: Internal Ip address in use:  100.68.8.31
Dec 03 12:59:35 basegnss python[26621]: Modem public Ip address:  100.70.142.197
Dec 03 12:59:35 basegnss python[26621]: Ping caster.centipede.fr or pch.net False
Dec 03 12:59:35 basegnss python[26621]: Modem registered and IP configured but ping failed. Trying NetworkManager reconnect on enxae0c29a39b6d
Dec 03 12:59:35 basegnss python[26621]: Connectivity restored after NetworkManager reconnect. No need to toggle airplane mode.
Dec 03 12:59:35 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 12:59:35 basegnss systemd[1]: modem_check.service: Consumed 1.827s CPU time.
Dec 03 13:03:21 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 13:03:36 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 13:03:36 basegnss systemd[1]: modem_check.service: Consumed 1.078s CPU time.
Dec 03 13:08:21 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 13:08:35 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 13:08:35 basegnss systemd[1]: modem_check.service: Consumed 1.026s CPU time.
Dec 03 13:13:21 basegnss systemd[1]: Started modem_check.service - Check Simcom modem status.
Dec 03 13:13:36 basegnss systemd[1]: modem_check.service: Deactivated successfully.
Dec 03 13:13:36 basegnss systemd[1]: modem_check.service: Consumed 1.028s CPU time.
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant