Byte count on network interfaces

Hi,

Is there a way to get byte counts for network interfaces from within a bridges container?
Using nmcli?
Using supervisor API?
Some other way?

Thanks!

Probably the simplest is to read these from /proc directly, here is an example: https://serverfault.com/a/533523/137589.

You’ll need a label to mount host’s /proc into the container.

1 Like

You could also try using vnstat. I usually install it in containers where I want to track network traffic.
This is for example handy if I have projects where I use a 3G USB dongle and want to monitor the traffic going over the network,

Hi ab77,

We tried to mount the procfs into our container but once we do it systemd stops working. We’re not sure yet why, but suspect it’s maybe overwriting the container’s /proc?? (although we don’t see the correct /proc/net/dev

Any ideas why adding “io.balena.features.procfs: ‘1’” breaks systemd?
Also, is this supposed to replace /proc or will it mount elsewhere?

Thank you!

I noticed these lines in the logs when procfs is enabled:
Jul 13 22:58:34 wellness systemd[1]: Cannot be run in a chroot() environment.
Jul 13 22:58:34 wellness systemd[1]: Freezing execution.
Jul 13 22:58:34 wellness kernel[809]: [ 1249.775377] systemd[1]: Cannot be run in a chroot() environment.
Jul 13 22:58:34 wellness kernel[809]: [ 1249.775476] systemd[1]: Freezing execution.

Hey there, enabling io.balena.features.procfs shouldn’t stop systemd on the host. Are you running systemd in your container, is that what stopped? There would definitely be a conflict in that case, and we normally wouldn’t recommend running systemd in a container.

Yes, we have systemd in the container and it seems to fail to start properly - see error I mentioned above.

Hi

Thanks for confirming. Are you following the best practices we have here to run systemd in a container?

Also, to confirm, yes the current behaviour is to mount /proc from the hostOS to the container at /proc. You can see it here

Hope this is helpful

Thanks

Yes, we used this tutorial to setup systemd in our container. I will review to double check and see if anything has changed.

In any case, my understanding is that most Docker systems mount the host /proc in a different folder in order to avoid collision with the container’s own /proc folder. It would be great if you would give the option to mount /proc in a different location (configurable or hard coded).

Can you try using a different container to inspect the network data with proc, one that doesn’t use systemd? As you suspected the mounting of /proc is conflicting with systemd in your container, but if you had another container that only ran the traffic inspection without systemd you could avoid the conflict.

Probably, but then I need to setup a server in the other container so the container which needs it (reports to our backend) can get the data. So, while it can work, it’s not a really elegant way of doing things.

Agreed that it is not an elegant solution, but it may be the best option for now. You could also try an alternate init system in your primary container, like supervisord that doesn’t have the complications associated with running systemd in a container. It kind of depends on your use case.

Hi,

Seeing as Balena uses NetworkManager, you might get away with using DBus :slight_smile:
You can check the existing devices using this:

root@da3cefd:/# dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager  /org/freedesktop/NetworkManager org.freedesktop.NetworkManager.GetDevices
method return sender=:1.4 -> dest=:1.78309 reply_serial=2
   array [
      object path "/org/freedesktop/NetworkManager/Devices/1"
      object path "/org/freedesktop/NetworkManager/Devices/2"
      object path "/org/freedesktop/NetworkManager/Devices/3"
      object path "/org/freedesktop/NetworkManager/Devices/4"
      object path "/org/freedesktop/NetworkManager/Devices/7"
      object path "/org/freedesktop/NetworkManager/Devices/9"
      object path "/org/freedesktop/NetworkManager/Devices/718"
      object path "/org/freedesktop/NetworkManager/Devices/719"
   ]

Then use the found objects to query interface name:

root@da3cefd:/# dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager  /org/freedesktop/NetworkManager/Devices/7 org.freedesktop.DBus.Properties.Get string:org.freedesktop.NetworkManager.Device string:Interface
method return sender=:1.4 -> dest=:1.78623 reply_serial=2
   variant       string "balena0"

and statistics:

root@da3cefd:/# dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager  /org/freedesktop/NetworkManager/Devices/7 org.freedesktop.DBus.Properties.GetAll string:org.freedesktop.NetworkManager.Device.Statistics
method return sender=:1.4 -> dest=:1.78650 reply_serial=2
   array [
      dict entry(
         string "RefreshRateMs"
         variant             uint32 0
      )
      dict entry(
         string "TxBytes"
         variant             uint64 466542963
      )
      dict entry(
         string "RxBytes"
         variant             uint64 5971957
      )
   ]

I am not sure how accurate these numbers are, or when they get reset, but at the very least it gives you an indication.

2 Likes

Sorry for reviving this old thread but since it’s exactly what I’m facing atm I thought it’d be good keeping the info together.

I tried the solution proposed by @TJvV but always received 0 as result:

# DBUS_SYSTEM_BUS_ADDRESS=unix:path=/host/run/dbus/system_bus_socket \
> dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager  /org/freedesktop/NetworkManager/Devices/2 org.freedesktop.DBus.Properties.GetAll string:org.freedesktop.NetworkManager.Device.Statistics
method return time=1662552677.820402 sender=:1.7 -> destination=:1.1665777 serial=99701 reply_serial=2
   array [
      dict entry(
         string "RefreshRateMs"
         variant             uint32 0
      )
      dict entry(
         string "TxBytes"
         variant             uint64 0
      )
      dict entry(
         string "RxBytes"
         variant             uint64 0
      )
   ]

Only when using the command in a docker-container in network_mode: host it works. Has anybody any idea what might be the issue? In my understanding dbus should run get the info from the host OS so it should work just fine from a bridge container.

Hi,

Can you share the Docker(compose) file you’re using to try this?
Without knowing details, it’s impossible to tell what’s happening.
It’s very well possible you’re trying to communicate with an incorrect dbus, or that in newer versions things got changed.

It might also be a good idea to create a separate thread for your issue.