Calling on all 4G/QMI Experts! wan IP refresh issue

I have skills but not time. I'd say try to install the ipk package from snapshot, maybe it will just work.

1 Like

Terrific suggestion @patrakov - thanks so much. And so far so good.

I managed to install using this link:

https://downloads.openwrt.org/snapshots/packages/mipsel_24kc/packages/modemmanager_1.18.12-1_mipsel_24kc.ipk

.. and it survived a reboot and seems to work fine.

And better yet - I simulated a disconnect using:

mmcli -b 1 --disconnect

and hooray - @aleksander0m's patch indeed seems to work (at least for my simulated disconnect):

Wed Nov  2 20:38:54 2022 daemon.info [2716]: <info>  [modem0] state changed (connected -> disconnecting)
Wed Nov  2 20:38:54 2022 daemon.info [2716]: <info>  [modem0] state changed (disconnecting -> registered)
Wed Nov  2 20:38:54 2022 daemon.info [2716]: <info>  [modem0/bearer3] connection #1 finished: duration 121s, tx: 258333 bytes, rx: 371928 bytes
Wed Nov  2 20:38:54 2022 user.notice modemmanager: interface wan (network device wwan0) disconnected
Wed Nov  2 20:38:54 2022 daemon.notice netifd: Interface 'wan' has lost the connection
Wed Nov  2 20:38:54 2022 daemon.notice netifd: Network device 'wwan0' link is down
Wed Nov  2 20:38:54 2022 daemon.warn dnsmasq[1]: no servers found in /tmp/resolv.conf.d/resolv.conf.auto, will retry

However, to reconnect I need to type 'ifup wan'.

So my new question is: what setting do I need in /etc/config/network to tell netifd to automatically reconnect?

@aleksander0m for now just simply adding "ifup ${CFG}" to the end of your new report-down script works in terms of reconnecting post disconnection - is this a reasonable temporary fix?

root@OpenWrt:/# cat /usr/lib/ModemManager/connection.d/10-report-down-and-reconnect
#!/bin/sh

# SPDX-License-Identifier: CC0-1.0
# 2022 Aleksander Morgado <aleksander@aleksander.es>
#
# Automatically report to netifd that the underlying modem
# is really disconnected
#
# require program name and at least 4 arguments
[ $# -lt 4 ] && exit 1

MODEM_PATH="$1"
BEARER_PATH="$2"
INTERFACE="$3"
STATE="$4"

[ "${STATE}" = "disconnected" ] || exit 0

. /usr/share/ModemManager/modemmanager.common
. /lib/netifd/netifd-proto.sh
INCLUDE_ONLY=1 . /lib/netifd/proto/modemmanager.sh

MODEM_STATUS=$(mmcli --modem="${MODEM_PATH}" --output-keyvalue)
[ -n "${MODEM_STATUS}" ] || exit 1

MODEM_DEVICE=$(modemmanager_get_field "${MODEM_STATUS}" "modem.generic.device")
[ -n "${MODEM_DEVICE}" ] || exit 2

CFG=$(mm_get_modem_config "${MODEM_DEVICE}")
[ -n "${CFG}" ] || exit 3

logger -t "modemmanager" "interface ${CFG} (network device ${INTERFACE}) ${STATE}"
proto_init_update $INTERFACE 0
proto_send_update $CFG

ifup ${CFG}

exit 0

@patrakov I also tried using a hotplug.d script:

[ ifdown = "$ACTION" ] && [ wan = "$INTERFACE" ] && ifup wan

but this fails because ifup itself calls ifdown! Can you think of another better way if we want to go the hotplug.d route for the temporary fix to this reconnect issue?

will this work?
ubus call network.interface.$INTERFACE up

At the very least, you also need to check these extra things, no matter if this is a hotplug.d or connection.d script:

  • That the interface is indeed intended to be up (i.e., protect against the intentional ifdown wan if e.g. there is a virus in your network and the ISP calls you and asks to disconnect immediately).
  • That the interface is not already up.

I don't really know how to do it. Maybe we should check the ifstatus wan output for something like this?

{
	"up": false,
	"pending": true,
	"available": true,
	"autostart": true,
	"dynamic": true,
	"proto": "dhcpv6",
	"device": "wwan0",
	"data": {
		"zone": "wan"
	}
}
1 Like

to check:

IFUP=$(ifstatus $INTERFACE | jsonfilter -e '@.up')
[ "$IFUP" = "true" ] && log "Interface $INTERFACE is already up"
1 Like

So we could use:

[ $(ifstatus $INTERFACE | jsonfilter -e '@.up') = "false" ] && ubus call network.interface.$INTERFACE up

yes, that works for me

BTW what's the difference between 'ifup $CFG' and 'ubus call network.interface.$INTERFACE up'

And any idea about how to implement @patrakov's check whether interface was manually put down?

No worries if not, since this is really just a hack whilst we wait for the developers to write a proper solution - see here and here.

My example was rather generic than specific to MM, so you should use the same interface name you would use with ifup

Understood, but are ifup and the ubus call the same technically (setting aside the particular target)? I'm just trying to work out why one would replace 'ifup' with 'ubus call network.interface... up'

ifup is actually ifdown+ifup and the actual "up" action is exactly the same as in my example, see in /sbin/ifup

1 Like

So I have settled on this ModemManager dispatcher script to manage reconnection upon modem disconnection (modified from the default 'report-down' script):

root@OpenWrt:~# cat /usr/lib/ModemManager/connection.d/10-report-down-and-reconnect
#!/bin/sh

# Automatically report to netifd that the underlying modem
# is really disconnected and reconnect if interface was up

# require program name and at least 4 arguments
[ $# -lt 4 ] && exit 1

MODEM_PATH="$1"
BEARER_PATH="$2"
INTERFACE="$3"
STATE="$4"

[ "${STATE}" = "disconnected" ] || exit 0

. /usr/share/ModemManager/modemmanager.common
. /lib/netifd/netifd-proto.sh
INCLUDE_ONLY=1 . /lib/netifd/proto/modemmanager.sh

MODEM_STATUS=$(mmcli --modem="${MODEM_PATH}" --output-keyvalue)
[ -n "${MODEM_STATUS}" ] || exit 1

MODEM_DEVICE=$(modemmanager_get_field "${MODEM_STATUS}" "modem.generic.device")
[ -n "${MODEM_DEVICE}" ] || exit 2

CFG=$(mm_get_modem_config "${MODEM_DEVICE}")
[ -n "${CFG}" ] || exit 3

IFUP=$(ifstatus ${CFG} | jsonfilter -e '@.up')

logger -t "modemmanager" "interface ${CFG} (network device ${INTERFACE}) ${STATE}"
proto_init_update $INTERFACE 0
proto_send_update $CFG

[ "${IFUP}" = "true" ] && ifup ${CFG}

exit 0

So the sequence is:

  • various checks such as verifying modem disconnection
  • check whether interface was up
  • send interface down following modem disconnect
  • if interface was previously up, set it up again

I have tested and issuing 'ifdown wan' keeps my wan interface down.

But disconnecting the modem results in an immediate reconnect.

This seems to me like a reasonable temporary solution for those in the same boat.

For those reading this you need to use a recent version of ModemManager from master (more recent than what is presently in 22.03). In my case just installing the .ipkg from master worked in my 22.03.2 install.

Hi All,

I am just struggling with this issue where the mobile carrier drops the connection after 12 hours. I have been reading lots of topic about this problem and eventually landed here.
I am using a Dlink LTE USB modem in QMI mode. I was first running it using plain QMI and switch to ModemManager after reading this.

I added @Lynx 's script, but the connection still drops after a couple of hours. my connection.d folder contains both original 10-report-dozn script and @Lynx 's script

root@NanoPi-R2S-Router:~# ls -l /usr/lib/ModemManager/connection.d/
-rwxr-xr-x    1 root     root           922 Nov 14 14:38 10-report-down
-rwxr-xr-x    1 root     root           953 Mar 31 20:36 10-report-down-and-reconnect

Should I remove the default one? Any other ideas are welcome...

Yes just remove the default one. Should work. Check logs. You can issue mmcli -m any —simple-disconnect to test.

1 Like

I deleted the default script and issued the command

mmcli -m any --simple-disconnect

I could see in the log that it disconnects and reconnects afterwards. Now I need to wait 12 hours to see if it reconnects after the actual mobile carrier disconnect.

Why isn't your script included by default?

I think it more or less has been now on the 'master' branch of OpenWrt - see:

1 Like

Thanks, I have read the discussion in the PR as well, very informative. So it'll be adressed in the upcoming release! Thanks for your Help!

1 Like