Skip to content
Advertisement

Obtaining real device of VLAN-interface through the netlink

I need to obtain the real_dev (f.e. ID) of the given VLAN-inteface.

I wrote some test snippet using libnl:

int main(void) {
     struct nl_sock *sock;
     struct nl_cache *cache;
     char iface[] = "eno1.10";
     //char iface[] = "eno1";

     if (!(sock = nl_socket_alloc())) {
          perror("nl_socket_alloc");
          return -1; 
     }

     if (nl_connect(sock, NETLINK_ROUTE) < 0) {
          perror("nl_connect");
          nl_socket_free( sock );
          return -1; 
     }

     if (rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache) < 0) {
          perror("rtnl_link_alloc_cache");
          nl_socket_free( sock );
          nl_close( sock );
          return -1; 
     }
     {   
          int ifindex; 
          struct rtnl_link *link = NULL;

          if (!(ifindex = rtnl_link_name2i(cache, iface))) {
               perror("rtnl_link_name2i");
               return -1; 
          }
          printf("ind: %dn", ifindex);

          if (!(link = rtnl_link_get(cache, ifindex))) {
               perror("rtnl_link_get");
               return -1; 
          }

          if (rtnl_link_is_vlan(link)) {
               puts("It's VLAN link");

               /* alas it's not about the 'real' device */
               printf("master: %dn", rtnl_link_get_master(link));
          } else
               puts("It's 'real' link");
     }   

     return 0;
}

So I have some interface ID and I can check if it’s a VLAN-interface, but I have no idea how to obtain the interface the vlan is attached to. It seems that libnl‘s API does not provide such possibility.

Is there a way to obtain the VLAN’s “parent” interface ID through the libnl or the native netlink API?

Advertisement

Answer

It’s all about IFLA_LINK:

/* IFLA_LINK.
   For usual devices it is equal ifi_index.
   If it is a "virtual interface" (f.e. tunnel), ifi_link
   can point to real physical interface (f.e. for bandwidth calculations),
   or maybe 0, what means, that real media is unknown (usual
   for IPIP tunnels, when route to endpoint is allowed to change)
 */

Thus through the native netlink API it could be done such a way:

/* some preparation code */
struct rtattr *rta = IFLA_RTA(msg);
int len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg));
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len))
    if (rta->rta_type == IFLA_LINK) {
        printf("Real device ID:%un",
               *(unsigned short *)((char *) rta + NLA_HDRLEN));
        break;
    }

Full example on github.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement