openwrt / openwrt

This repository is a mirror of https://git.openwrt.org/openwrt/openwrt.git It is for reference only and is not active for check-ins. We will continue to accept Pull Requests here. They will be merged via staging trees then into openwrt.git.
Other
19.71k stars 10.28k forks source link

FS#3499 - [netifd] no way to monitor the real state of a connection via protocol handlers #8368

Closed openwrt-bot closed 2 years ago

openwrt-bot commented 3 years ago

aleksander0m:

The current ModemManager integration in netifd is not fully operational right now, and usually requires an additional management script on top of it to properly reconnect the modems under certain scenarios.

The simplest and most common use case is the following:

See e.g. https://github.com/openwrt/packages/issues/14096

What would be the best way to solve this issue?

Is there currently any way to extend the protocol handler in a way that allows some polling inside netifd to ensure the interface is still up? Would that be a big change? Any other solution suggested?

openwrt-bot commented 3 years ago

johnth:

Hi, Thank you for you work with ModemManager! For a long time, I have used a USB NCM modem (without knowing of MM), and have wanted a way for it to detect disconnect and automatically reconnect.

I do not know ModemManager, or ubus / netifd.

I do not know if it works, but it looks like at one stage, ppp used netifd for reconnects: https://github.com/openwrt-mirror/openwrt/commit/3411334dd8d55107fe9dc1fcf018b28fcbbeb90b

Could we use MM's dbus state change to make a ubus call to netifd? Even if it is an external daemon monitoring dbus? https://www.freedesktop.org/software/ModemManager/api/latest/ModemManager-Flags-and-Enumerations.html#MMModemState

Example: From the ppp proto, the proto_run_command uses the ip-down-script /lib/netifd/ppp-down, which sends a message to netifd via ubus through the shell library. https://github.com/openwrt/openwrt/blob/master/package/network/services/ppp/files/lib/netifd/ppp-down

ubus monitor -> 97d0daf0 #97d0daf0 hello: {} <- 97d0daf0 #00000000 lookup: {"objpath":"network.interface"} -> 97d0daf0 #00000000 data: {"objpath":"network.interface","objid":140326987,"objtype":-806725414,"signature":{"up":{},"down":{},"renew":{},"status":{},"prepare":{},"dump":{},"add_device":{"name":3,"link-ext":7,"vlan":1},"remove_device":{"name":3,"link-ext":7,"vlan":1},"notify_proto":{},"remove":{},"set_data":{}}} -> 97d0daf0 #00000000 status: {"status":0} <- 97d0daf0 #085d384b invoke: {"objid":140326987,"method":"notify_proto","data":{"action":0,"ifname":"ifname_example","link-up":false,"keep":false,"interface":"interface_example"}} -> bacdf6e3 #97d0daf0 invoke: {"objid":140326987,"method":"notify_proto","data":{"action":0,"ifname":"ifname_example","link-up":false,"keep":false,"interface":"interface_example"},"user":"root","group":"root"}

. /lib/netifd/netifd-proto.sh proto_init_update "ifname_example" 0 proto_send_update "interface_example"

echo "$(json_dump)" { "action": 0, "ifname": "ifname_example", "link-up": false, "keep": false, "interface": "interface_example" } ubus call network.interface notify_proto "$(json_dump)"

Netifd shell functions: /lib/netifd/netifd-proto.sh https://git.openwrt.org/?p=project/netifd.git;a=blob;f=scripts/netifd-proto.sh

json shell functions: /usr/share/libubox/jshn.sh https://git.openwrt.org/?p=project/libubox.git;a=blob;f=sh/jshn.sh

If something like this //might// work, I can keep digging?

Cheers

openwrt-bot commented 2 years ago

aleksander0m:

I haven't seen your reply until now; sorry!

We recently discussed about how to best handle this in the MM mailing list, and a solution like the one you suggest, using proto_init_update $ifname 0; proto_send_update, makes sense.

The way forward I'm suggesting is to allow ModemManager to run "post-event" dispatcher scripts; e.g. we could allow the user to have custom scripts that are run by the MM daemon when a given connection is connected or disconnected. Then, the openwrt packaging could provide a script to call on network-triggered disconnections, which would do the proto_init_update $ifname 0; proto_send_update call to notify netifd that the connection is really down.

See https://lists.freedesktop.org/archives/modemmanager-devel/2022-January/009075.html

What do you think of this? It would not require a separate daemon to monitor the connection, it would all be managed by MM and the openwrt-installed dispatcher script.

aleksander0m commented 2 years ago

A fix for this is explained here: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/merge_requests/775 Comments welcome

wicadmin commented 2 years ago

This looks great and definitely a welcomed enhancement.

lynxthecat commented 1 year ago

I am confused - this important fix does not seem to be present in 22.03.2?

Also, this fix addresses pushing disconnected state to netifd, but what about automatic reconnection upon such disconnection events? @aleksander0m how should that be addressed? In my case I see:

Mon Oct 31 17:37:46 2022 daemon.info [2719]: <info>  [modem0/bearer1]
verbose call end reason (6,36): [3gpp] regular-deactivation

And output of ifstatus is wrong, and I have lost internet connectivity since there is no automatic reconnection. This default behaviour seems somewhat broken - I mean I installed ModemManager in the first place in the hope it would retain internet connectivity through these 48 hour disconnects that my 4G ISP effects.

aleksander0m commented 1 year ago

And output of ifstatus is wrong,

What is your output of ifstatus after the regular-deactivation event is received in MM?

lynxthecat commented 1 year ago

@aleksander0m I can't get this unless I wait another 48 hours. Can I simulate with:

root@OpenWrt:~# mmcli -m a -K | grep bearers
modem.generic.bearers.length                    : 1
modem.generic.bearers.value[1]                  : /org/freedesktop/ModemManager1/Bearer/15

root@OpenWrt:~# mmcli -b 15 --disconnect

or an alternative?

I did capture the output from both 'logread' and also 'mmcli -m 0' if that's of any use. The connection state in the latter is reported as 'registered' (i.e. not 'connected').

lynxthecat commented 1 year ago

@aleksander0m OK I got it as another disconnect occurred in the meantime:

Wed Nov  2 04:20:11 2022 daemon.info [2719]: <info>  [modem3/bearer9] verbose call end reason (6,36): [3gpp] regular-deactivation
Wed Nov  2 04:20:11 2022 daemon.info [2719]: <info>  [modem3] state changed (connected -> registered)
Wed Nov  2 04:20:11 2022 daemon.info [2719]: <info>  [modem3/bearer9] connection #1 finished: duration 64629s, tx: 940108442 bytes, rx: 9966819431 bytes

root@OpenWrt:~# ifstatus wan
{
        "up": true,
        "pending": false,
        "available": true,
        "autostart": true,
        "dynamic": false,
        "uptime": 76945,
        "l3_device": "wwan0",
        "proto": "modemmanager",
        "updated": [
                "addresses",
                "routes"
        ],
        "metric": 0,
        "dns_metric": 0,
        "delegation": true,
        "ipv4-address": [
                {
                        "address": "10.90.XX.XX",
                        "mask": 30
                }
        ],
        "ipv6-address": [

        ],
        "ipv6-prefix": [

        ],
        "ipv6-prefix-assignment": [

        ],
        "route": [
                {
                        "target": "0.0.0.0",
                        "mask": 0,
                        "nexthop": "10.90.YY.ZZ",
                        "source": "10.90.XX.XX/32"
                }
        ],
        "dns-server": [
                "192.168.XX.1"
        ],
        "dns-search": [

        ],
        "neighbors": [

        ],
        "inactive": {
                "ipv4-address": [

                ],
                "ipv6-address": [

                ],
                "route": [

                ],
                "dns-server": [

                ],
                "dns-search": [

                ],
                "neighbors": [

                ]
        },
        "data": {

        }
}
root@OpenWrt:~# ip addr show dev wan
ip: can't find device 'wan'
root@OpenWrt:~# ip addr show dev wwan0
9: wwan0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 1000
    link/[65534]
    inet 10.90.XX.XX/30 brd 10.90.ZZ.ZZ scope global wwan0
       valid_lft forever preferred_lft forever
    inet6 fe80::92c2:79f2:d9a4:24e3/64 scope link flags 800
       valid_lft forever preferred_lft forever