5

I'm using the getifaddrs Linux function to get information about network interfaces on a Linux machine running Debian Jessie kernel 3.16.0.

Among the info I want to know is network statistics (packets dropped, sent, etc.) which, as the manpage for getifaddrs states, is contained in a rtnl_link_stats structure pointed to by ifaddrs::ifa_addr::ifa_data when ifaddrs::if_addr::sa_family is set to AF_PACKET.

This works well for ethernet interfaces, but does not work for CAN interfaces on the machine, because ifaddrs::ifa_addr is NULL and thus AF_PACKET is never returned for any CAN interface.

The following C++ code...

#include <ifaddrs.h>
#include <linux/if_link.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <cstdio>
#include <cstdlib>

int main() {
  ifaddrs *addrs;
  if (getifaddrs(&addrs) == -1) {
    perror("getifaddrs");
    return EXIT_FAILURE;
  }

  printf("AF_PACKET: %d\n\n", (int)AF_PACKET);

  for (auto addr = addrs; addr != NULL; addr = addr->ifa_next) {
    if (addr->ifa_addr != nullptr) {
      printf("%s: family: %d\n", addr->ifa_name, (int)addr->ifa_addr->sa_family);
    } else {
      printf("%s: family: none\n", addr->ifa_name);
    }
  }

  freeifaddrs(addrs);

  return EXIT_SUCCESS;
}

...prints out

AF_PACKET: 17

lo: family: 17
eth0: family: 17
eth1: family: 17
can0: family: none
can1: family: none
lo: family: 2
eth1: family: 2
lo: family: 10
eth1: family: 10

which means that neither of the CAN interfaces have any family set.

The ifconfig command has no problem showing the information, though:

can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          UP RUNNING NOARP  MTU:16  Metric:1
          RX packets:28481588 errors:0 dropped:8729866 overruns:0 frame:0
          TX packets:8168599 errors:2292404 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10 
          RX bytes:211108099 (201.3 MiB)  TX bytes:64828340 (61.8 MiB)
          Interrupt:17 

can1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          UP RUNNING NOARP  MTU:16  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:17

(note I included only the output for CAN interfaces, not the rest)

What am I doing wrong? What is the correct way to retrieve packet stats for CAN interfaces?

hoz
  • 176
  • 1
  • 7
  • 1
    I don't know anything about CAN specifically, nor have a device - but I _suspect_ the information might be available if you use a netlink socket to call `RTM_GETLINK`, and set `rta_type` to IFLA_STATS. It's a bit of an ordeal to set up, but the starting point is https://man7.org/linux/man-pages/man7/rtnetlink.7.html – KJ Tsanaktsidis Sep 11 '21 at 13:37
  • Does the packet concept apply to a CAN at all? A CAN telegram consists of a header holding a priority. If the header collides with an other device the whole telegram stops. This is done in the hardware CAN protocol handler on the MCU. It is pure hardware! – Ricardo Erckert Sep 14 '21 at 09:16

3 Answers3

0

Use the "address_family" option in the "ifconfig" command; check your "man ifconfig" page, here is the relevant text from mine (no CAN intfs on my system):

...
     address_family
             Specify the address family which affects interpretation of the remaining parameters.  Since an interface
             can receive transmissions in differing protocols with different naming schemes, specifying the address
             family is recommended.  The address or protocol families currently supported are ``inet'', ``inet6'', and
             ``link''.  The default is ``inet''.  ``ether'' and ``lladdr'' are synonyms for ``link''.
Andrew
  • 1
  • 4
  • 19
0

Given net-tools source code it reads file /proc/net/dev in the proc filesystem for this information.

See the following functions in lib/interface.c:

  • if_readlist()

  • if_readlist_proc()

Good luck with your project!

EDIT> With a CAN adapter connected

File /proc/net/dev:

Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
slcan0:       0       0    0    0    0     0          0         0      344      43    0    0    0     0       0          0

Output of ifconfig:

slcan0: flags=193<UP,RUNNING,NOARP>  mtu 16
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 10  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 43  bytes 344 (344.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
vlp
  • 7,811
  • 2
  • 23
  • 51
0

I had a similar problem in my C project nagios-plugins-linux and had to switch from the very easy interface getifaddrs to linux rtnetlink, which is a lot more complex to manage but also more powerfull (getifaddrs provides the network statistics for the AF_PACKET family only, if I remember correctly).

You can find the related code in the library files:

I'm not able to check a can0 interface but my code detects a vcan0 one and should anyway work for any network interface.

Davide Madrisan
  • 1,969
  • 2
  • 14
  • 22