user1762571 user1762571 - 5 months ago 32
Linux Question

Vlan interface details using NETLINK

I understand that new interface addition can be detected using RTE_NEWLINK message type in NETLINK. Netlink sends a message with which we can get index and name of the interface using (if_indextoname & if_nametoindex).

My question is , if we add a VLAN interface, it sends a message with interface name (example: eth1.10). Does this vlan number only be available in interface name
or is it available anywhere inside NL_MSG structure. I dont want to parse
interface name and get VLAN number

I executed the below code and added a vlan sub interface, but couldn't find vlan information from attribute structures. It didnt print anything even though RTM_NEWLINK detected the new interface. Please correct me if i am looking for VLAN information at a wrong place in code.

if(nl_msg_hdr->nlmsg_type == RTM_NEWLINK)
{
struct ifinfomsg *ifi;
struct rtattr *rt_attr;
int rtattrlen;
ifi = (struct ifinfomsg *) NLMSG_DATA(nl_msg_hdr);
printf("RTM_NEWLINK");
for (;RTA_OK(rt_attr, rtattrlen); rt_attr = RTA_NEXT(rt_attr, rtattrlen)) {

if (rt_attr->rta_type == IFLA_LINKINFO)
printf(" IFLA_LINKINFO \n");
if (rt_attr->rta_type == IFLA_LINK)
printf(" IFLA_LINK \n");
if (rt_attr->rta_type == IFLA_INFO_DATA)
printf(" IFLA_INFO_DATA\n");
if (rt_attr->rta_type == IFLA_VLAN_ID)
printf(" IFLA_VLAN_ID\n");
}
}



x/200bx nl_msg_hdr - 200 bytes hex-dump (VLAN ID is 33 in my case)

0x7fffffffd250: 0xa4 0x04 0x00 0x00 0x10 0x00 0x00 0x00
0x7fffffffd258: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffd260: 0x00 0x00 0x01 0x00 0x27 0x00 0x00 0x00
0x7fffffffd268: 0x02 0x10 0x00 0x00 0xff 0xff 0xff 0xff
0x7fffffffd270: 0x0d 0x00 0x03 0x00 0x76 0x65 0x74 0x68
0x7fffffffd278: 0x31 0x2e 0x33 0x33 0x00 0x00 0x00 0x00
0x7fffffffd280: 0x08 0x00 0x0d 0x00 0x00 0x00 0x00 0x00
0x7fffffffd288: 0x05 0x00 0x10 0x00 0x02 0x00 0x00 0x00
0x7fffffffd290: 0x05 0x00 0x11 0x00 0x00 0x00 0x00 0x00
0x7fffffffd298: 0x08 0x00 0x04 0x00 0xdc 0x05 0x00 0x00
0x7fffffffd2a0: 0x08 0x00 0x1b 0x00 0x00 0x00 0x00 0x00
0x7fffffffd2a8: 0x08 0x00 0x1e 0x00 0x00 0x00 0x00 0x00
0x7fffffffd2b0: 0x08 0x00 0x1f 0x00 0x01 0x00 0x00 0x00
0x7fffffffd2b8: 0x08 0x00 0x20 0x00 0x01 0x00 0x00 0x00
0x7fffffffd2c0: 0x08 0x00 0x05 0x00 0x0a 0x00 0x00 0x00
0x7fffffffd2c8: 0x05 0x00 0x21 0x00 0x01 0x00 0x00 0x00
0x7fffffffd2d0: 0x09 0x00 0x06 0x00 0x6e 0x6f 0x6f 0x70
0x7fffffffd2d8: 0x00 0x00 0x00 0x00 0x24 0x00 0x0e 0x00
0x7fffffffd2e0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffd2e8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffd2f0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7fffffffd2f8: 0x00 0x00 0x00 0x00 0x00 0x88 0xff 0xff
0x7fffffffd300: 0x0a 0x00 0x01 0x00 0x66 0x0f 0x70 0x37
0x7fffffffd308: 0x0b 0x27 0x00 0x00 0x0a 0x00 0x02 0x00
0x7fffffffd310: 0xff 0xff 0xff 0xff 0xff 0xff 0x00 0x00

Answer

The vlan info is available in RTM_NEWLINK messages: IFLA_LINKINFO / IFLA_INFO_DATA / IFLA_VLAN_ID:

# the message structure:

[ nlmsg fields ]
[ ifinfmsg fields ]
nla chain:
  [ IFLA_IFNAME ]
  [ IFLA_… ]
  [ IFLA_LINKINFO ]
  nla chain:
    [ IFLA_INFO_KIND ]
      ...
    [ IFLA_INFO_DATA ]
    nla chain:
      [ IFLA_VLAN_ID ]

and the corresponding code (python sample with pyroute2):

from pyroute2 import IPRoute
ip = IPRoute()
# assume `ifindex` contains VLAN interface index
nlmsg = ip.get_links(ifindex)[0]
vid = nlmsg.get_attr('IFLA_LINKINFO').\
    get_attr('IFLA_INFO_DATA').\
    get_attr('IFLA_VLAN_ID')
print(vid)

Checked on kernels from 2.6.32 (RHEL6.5) to 4.1.0-rc6 (F22).

And yes, you're right — one should not rely on the interface name as the source of VLAN id. The interface name can be literally any.