【问题标题】:Obtaining real device of VLAN-interface through the netlink通过netlink获取VLAN接口的真实设备
【发布时间】:2019-09-09 12:56:18
【问题描述】:

我需要获取给定 VLAN 接口的real_dev(例如 ID)。

我用libnl写了一些测试sn-p:

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 所连接的接口 em>libnl 的 API 似乎没有提供这种可能性。

有没有办法通过libnl或者native netlink API获取VLAN的“父”接口ID?

【问题讨论】:

    标签: c linux linux-kernel netlink vlan


    【解决方案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;
        }
    

    Full example on github.

    【讨论】: