How to filter VLAN interfaces using rtnetlink

VLAN interfaces (created with ip link add link <parent> name <name> type vlan id <id>) appear in a rtnetlink RTM_GETLINK dump alongside every other interface. Unlike physical Ethernet adapters, VLANs are always virtual and carry a clear marker: the nested IFLA_LINKINFO attribute with IFLA_INFO_KIND set to "vlan". They also carry IFLA_LINK, which points to the parent interface’s ifindex — the physical or bridge device the VLAN sits on top of.

This post shows a compact C++ program that filters the rtnetlink dump for VLAN interfaces only, printing each VLAN’s name, ifindex, and parent ifindex.

A VLAN interface reports the following distinguishing attributes:

AttributeValueMeaning
ifi_typeARPHRD_ETHER (1)VLANs are Ethernet-framed
IFLA_LINKINFOIFLA_INFO_KIND"vlan"Identifies the link as a VLAN
IFLA_LINKparent ifindex (e.g. 3)The underlying interface the VLAN is stacked on
IFLA_LINKINFOIFLA_INFO_DATAIFLA_VLAN_IDVLAN ID (1–4094)The 802.1Q tag

The key filter is IFLA_INFO_KIND == "vlan". The IFLA_LINK attribute is not unique to VLANs (veths also use it), but it is always present for VLANs and tells you which parent device to look up.

The program

The program walks the top-level attributes of each RTM_NEWLINK message. When it encounters IFLA_LINKINFO, it descends one level into the nested attribute list to read IFLA_INFO_KIND. Only interfaces whose kind is "vlan" are printed.

Building and running

No special privileges are required — reading the link dump via rtnetlink is unprivileged.

Example output

A VLAN interface created on top of a Wi-Fi interface (wlo1, ifindex 3) with ip link add link wlo1 name v77 type vlan id 77 looks like this in the full link dump:

The filter program extracts only the relevant fields and prints:

The parent=3 refers to wlo1’s ifindex — you can resolve it to a name with a second rtnetlink lookup or by cross-referencing the dump.

Extracting the VLAN ID

The VLAN ID (1–4094) is stored one level deeper, inside IFLA_LINKINFOIFLA_INFO_DATAIFLA_VLAN_ID. IFLA_INFO_DATA is itself a nested attribute list, so you need a second level of descent:

IFLA_VLAN_ID is a uint16_t (values 1–4094). Add uint16_t vlan_id = 0; to your variables and include it in the output if needed.

Also see How to list all network links using rtnetlink API for the full link-dump program, How to filter physical ethernet links using rtnetlink for the complementary physical-NIC filter, and How to iterate rtnetlink rtattr attributes for the attribute-walking idiom.


Check out similar posts by category: C/C++ Linux