14

How can I detect whether the current connection is marked as metered on a system with NetworkManager?

This is from a shell script, but I can easily call any C functions via Python.

phihag
  • 278,196
  • 72
  • 453
  • 469

3 Answers3

15

With the nmcli utility, the necessary steps are:

  1. verify NetworkManager is version 1.0.6+:

    $ nmcli -v nmcli tool, version 1.9.0

  2. check GENERAL.METERED on an interface:

    $ nmcli -t -f GENERAL.METERED dev show eth1 GENERAL.METERED:unknown

  3. values are: unknown, yes, no, yes (guessed), no (guessed)

  4. Forcing the value is done like this:

    $ nmcli dev modify wlan1 connection.METERED yes Connection successfully reapplied to device 'wlan1' $ nmcli -t -f GENERAL.METERED dev show wlan1 GENERAL.METERED:yes

And, to get a list grouped by device:

  $ nmcli -t -f GENERAL.DEVICE,GENERAL.METERED dev show

  GENERAL.DEVICE:wlan1
  GENERAL.METERED:yes

  GENERAL.DEVICE:eth1
  GENERAL.METERED:unknown

  GENERAL.DEVICE:lo
  GENERAL.METERED:unknown

Trying to cut this down to info on just the default route would still require a call to another command as NetworkManager doesn't try to distinguish between multiple devices in a connected state:

  $ nmcli -t -f GENERAL.DEVICE,GENERAL.METERED dev show `ip route list 0/0 | sed -r 's/.*dev (\S*).*/\1/g'`
Community
  • 1
  • 1
lossleader
  • 13,182
  • 2
  • 31
  • 45
  • Excellent! Is there a way to only show the information for the network the first default route is going over? With many VPNs and otherwise virtual networks, the output of `nmcli -t -f GENERAL.METERED dev show` (without a device) is a mixture of all possible values for me. – phihag Apr 07 '17 at 21:50
  • I've added a way to see the device names, but I think you may need to ask `ip route` and ideally `ip monitor` to reliably track the interface of the default route or relevant server then do/redo the nmcli query. – lossleader Apr 07 '17 at 22:29
  • Thanks! I'll award the bounty in a couple of hours. – phihag Apr 08 '17 at 07:52
  • See also https://unix.stackexchange.com/questions/364927/networkmanager-set-current-connection-of-device-as-metered, which describes how to set the connection (i.e. SSID) rather than the interface. This makes sense when you may have more than wifi connection, one to a mobile hotspot. – Luciano Jun 09 '17 at 21:31
  • You can test the output with `[[ "$(nmcli -t -f GENERAL.METERED dev show \`ip route list 0/0 | sed -r 's/.*dev (\S*).*/\1/g'\` | cut -d':' -f2)" == yes* ]]` – darkdragon May 24 '20 at 19:52
10

You can also get the metered status of the current connection via D-Bus. From a shell, you can use busctl:

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

which is only one command, in contrast to the nmcli solution, and in other programming languages it can be more efficient to use D-Bus directly instead of having to call nmcli.

The result is an enum with the following values (documentation):

Name Value Description
NM_METERED_UNKNOWN 0 The metered status is unknown
NM_METERED_YES 1 Metered, the value was explicitly configured
NM_METERED_NO 2 Not metered, the value was explicitly configured
NM_METERED_GUESS_YES 3 Metered, the value was guessed
NM_METERED_GUESS_NO 4 Not metered, the value was guessed
Flimm
  • 136,138
  • 45
  • 251
  • 267
ash
  • 5,139
  • 2
  • 27
  • 39
  • 3
    The result is an enum with the following [values](https://developer.gnome.org/NetworkManager/stable/nm-dbus-types.html#NMMetered) – darkdragon May 24 '20 at 19:42
  • The output is something like: `u 1` . If you prefer JSON, then pass the `-j` flag, and you will get output like `{ "type": "u", "data": 1 }` – Flimm Apr 28 '23 at 16:30
0

For some reason the solution from lossleader always returns no on my system, while using the metered parameter from the connection works fine:

nmcli -f connection.metered connection show `nmcli -t -f GENERAL.CONNECTION --mode tabular device show $DEVICE | head -n1`

untbu
  • 66
  • 2
  • 6