Snap refresh over metered connections

It’s up for review already:

2 Likes

wait, does that mean I won’t get my updates any more once a future release lands on my box?

I would suggest that to be rather unexpected considering all the marketing touts updates to snaps being delivered automatically.

if your only network connection is a 3/4G/LTE modem thats probably true

1 Like

If you’re on metered connection all the time, the updates will be postponed for up to 60 days max. After that we’ll update anyway.

1 Like

@mborzecki please note that the settings that nmcli shows do not really reflect the value for the Metered DBus property of the device. The former are static and stored in a file, while the property is dynamic. For a modem connection in a system I can access:

$ nmcli c show verizon | grep metered
connection.metered:                     unknown

But the property for the device shows:

$ dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager /org/freedesktop/NetworkManager/Devices/5 org.freedesktop.DBus.Properties.GetAll string:"org.freedesktop.NetworkManager.Device"
...
      dict entry(
         string "Metered"
         variant             uint32 3
      )
...

Also, I see that you are checking org.freedesktop.NetworkManager.Metered, which shows the Metered property of the principal device, so be careful with that.

The conclusion is that all modems have NM_METERED_GUESS_YES by default, which can have consequences for backwards compatibility. If snapd is going to add this new setting, this needs to be taken into account.

We’re looking at the top level NM property of the manager itself. IIRC this is a sort-of an aggregate value taking into consideration the current default route.

This should get you the value we use for deciding whether the host is metered or not.

busctl --system get-property org.freedesktop.NetworkManager \
/org/freedesktop/NetworkManager org.freedesktop.NetworkManager Metered

It looks like NM_METERED_YES is never set by NM unless explicitly instructed by a user to do so. In that sense, this change would be safe if snapd only stops the automatic updates if org.freedesktop.NetworkManager.Metered is NM_METERED_YES in NM (regardless of whether this had been set from snapd or by the user).

snapd uses bot NM_METERED_YES and NM_METERED_GUESS_YES, see here for details:

We want to stay with the logic as it’s an automatic win for people who roam.

I guess the gist of the problem is determining whether there are Ubuntu Core devices, using NM, which have their default route through a modem connection (i.e. modem is the main connection). In such case, the current code would hold refreshing the snaps for up to 60 days what may be undesired and so we need to find a way to use a different default.

I have been taking a look at snapd’s code, and if I understand it correctly we are safe from regressions as far as refresh.metered is not set to hold by default.

But, there is an issue with the current logic: it considers that all network devices are managed by network-manager. When the network-manager snap is installed, it does not manage ethernet connections by default. You need to set the ethernet.enable property to true for this to happen. If it is not set, in a case when you have a modem and an ethernet connection both active, NM will very possibly report org.freedesktop.NetworkManager.Metered is NM_METERED_GUESS_YES, but actually the default route is through the ethernet (which would be managed by systemd-netwrokd). This would cause the system to not update for 60 days when it should.

In most of our IoT devices, ethernet.enable has been set to true, but it is false if you install manually the snap.

That’s a nice find. Thank you.

Looks like it would be beneficial to split the case when connection if explicitly marked as metered from the case when it’s a guess. I’ve put this down in a table.

Can we refresh?

  • x yes
  • - no
                                    (NetworkManager value)
| device  | setting                | NO | GUESS_NO | GUESS_YES | YES |
|---------+------------------------+----+----------+-----------+-----|
| classic | force                  | x  | x        | x         | x   |
| classic | hold                   | x  | x        | x         | -   |
| classic | hold-guessed           | x  | x        | -         | -   |
| classic | default (hold-guessed) | x  | x        | -         | -   |
|---------+------------------------+----+----------+-----------+-----|
| core    | force                  | x  | x        | x         | x   |
| core    | hold                   | x  | x        | x         | -   |
| core    | hold-guessed           | x  | x        | -         | -   |
| core    | default (hold)         | x  | x        | x         | -   |
  • hold-guessed (strawman atm) could be the new value that we add, which indicates that the refreshes are held when connection is implicitly marked as metered
  • hold is only effective when connection is explicitly marked as metered
  • classic systems default to hold-guessed
  • core systems default to hold

A hypothetical edge case, when a core system has a connection explicitly marked as metered with the intention of the setting being used by another application but would still like to receive snap updates would need to be updated to use refresh.metered=force.

1 Like

@mborzecki your proposal looks safe to me, but you would need to check the interfaces managed by systemd-networkd too. networkctl lists the type so you could apply similar heuristics to what NM does and then merge the value with the one from NM.

Not sure I entirely understand. We only look at NM, because AFAIK networkd has no support for reporting the connections as being metered or marking them as such.

Having NM report METERED_YES effectively means that the connection was explicitly marked as metered in NM (via nmcli or other means), thus the underlying interface must be managed by NM and the (current) default route goes though that connection. In other cases it will be METERED_{NO,GUESS_NO,GUESS_YES} which do not block refreshes.

@mborzecki see my previous comment about the network-manager snap not managing by default ethernet connections. What I am saying is that if you rely only on NM to decide if you can update snaps or not is buggy, as you could be in a case when the default route is via ethernet (managed by networkd) but NM reports GUESS_YES because it only manages a cellular connection (let’s say that this is for classic).

I see what you mean. I recreated this with with a wifi and eth. WiFi managed by NM with the connection marked as metered. Eth managed by systemd-networkd. When both were connected NM keeps reporting METERED_YES. Tweaking the metric of the route obtained via DHCP on eth connectio had no effect. Even if NM is looking at the main routing table it’s either not checking which route is effective or just ignoring routes through connections not managed by it.

At this point I’m thinking that maybe we should disable the feature or have the default allow refreshing just on Core devices. Thoughts?

On a side note, using vanilla config, the route via eth added by networkd had higher metric than the one over WiFi added by NM. Looks like this setup is broken out of the box with default settings.

IMHO I think the right course of action would be to check also interfaces managed by networkd, sort of replicating NM’s logic in snapd. NM actually does not do anything too clever here (wwan -> guess it is metered, otherwise is not), but for bluetooth interfaces which are not supported by networkd anyway. So doing a simple check by using networkd interface type and merging that with NM’s value is feasible. This would have the advantage of making the feature available also when NM is not present.

Hm, this should not happen if netplan is being used, see https://bugs.launchpad.net/ubuntu/+source/nplan/+bug/1639754 . I see metric 100 for eth in Ubuntu Core when the interface is managed by networkd.

I tested this on my Arch box without netplan so ended up using default values from networkd.

We’ll need to discuss that. I’m not particularly fond of poking both.

In which case will networkd have an ethernet connection while network-manager is active and managing a celular connection? If network-manager is active, wouldn’t the most likely route be for network-manager to also be in control of the ethernet connection?

For historical reasons related to console-conf, the NM snap does not manage by default eth connections.