通过netlink获取VLAN接口的真实设备

时间:2019-04-19 08:13:12

标签: c linux linux-kernel netlink vlan

我需要获取给定VLAN接口的real_dev(f.e。ID)。

我使用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: %d\n", 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: %d\n", rtnl_link_get_master(link));
          } else
               puts("It's 'real' link");
     }   

     return 0;
}

所以我有一些接口ID ,我可以检查它是否是VLAN接口,但是我不知道 如何获取vlan所连接的接口 。 似乎 libnl 的API没有提供这种可能性。

是否可以通过 libnl 本地网络链接API 获取VLAN的“父”接口ID?

1 个答案:

答案 0 :(得分:1)

关于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)
 */

因此,通过 native netlink API 可以这样实现:

/* 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:%u\n",
               *(unsigned short *)((char *) rta + NLA_HDRLEN));
        break;
    }