Linux – listing parent interface of a vlan

linuxlinux-networkingnetworkingUbuntuvlan

I have a setup with a bunch of vlan interfaces on a physical interface.

Physical interface: eth1
VLANS on top of this: vlan1, vlan2, vlan3

Now, I want to know which is the parent interface of my vlan (for example, here eth1 is the parent interface of these vlans).

I can get this information by running "ip addr show vlan-name" and then in output, I will get vlan1@eth1, but I need to parse the output of this command or by looking at my network config file, parsing it and interpreting it.

Is there another way by which I can get this information without any parsing logic? For example, for bonded interfaces, the information is present in /sys/class/net/ directory and one can simply read files there.

# cat /sys/class/net/bond0/bonding/slaves
eth0 eth1

Is there a similar path/file available for vlan tagged interfaces? I couldn't figure out if there is some file I can just read without any parsing and extract this information or any command/utility that just gives the parent interface name.

Kindly do let me know if there are other alternatives to this.

Thanks.

Best Answer

I didn't find a way without any parsing to get the underlying interface, so I give 5 (sometimes just slightly) different ways to get this information. The method 5 added last should be preferred: it uses the JSON output of the ip command.


There's a symlink having the name of the physical interface:

$ ls -l /sys/class/net/vlan2
[...]
lrwxrwxrwx. 1 root root 0 nov. 10 02:12 lower_eth1 -> ../eth1
[...]
-rw-r--r--. 1 root root 4096 nov. 10 01:49 uevent

Method 1

$ echo $(basename $(readlink /sys/class/net/vlan2/lower_*))
eth1

There's uevent that is handy too:

$ cat /sys/class/net/vlan2/uevent 
DEVTYPE=vlan
INTERFACE=vlan2
IFINDEX=24
$ cat /sys/class/net/vlan2/lower_*/uevent
INTERFACE=eth1
IFINDEX=22

Method 2

$ cat /sys/class/net/vlan2/lower_*/uevent|sed -n 's/^INTERFACE=//p'
eth1

As root, there are entries in /proc/net/vlan:

# ls /proc/net/vlan/
config  vlan1  vlan2  vlan3  vlan4  vlan5
# cat /proc/net/vlan/config
VLAN Dev name    | VLAN ID
Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
vlan1          | 1  | eth1
vlan3          | 3  | eth1
vlan4          | 4  | eth1
vlan2          | 2  | eth1
vlan5          | 5  | eth2

# cat /proc/net/vlan/vlan2
[...]
Device: eth1
[...]

Method 3

# awk -F ' *\\| *' '$1 == "vlan2" { print $3 }' /proc/net/vlan/config
eth1

Method 4

# sed -n 's/^Device: //p' /proc/net/vlan/vlan2
eth1

Note that in /sys the other direction is also possible with upper_*:

$ ls -l /sys/class/net/eth1

[...]

-rw-r--r--. 1 root root 4096 nov.  10 01:46 uevent
lrwxrwxrwx. 1 root root    0 nov.  10 02:23 upper_vlan1 -> ../vlan1
lrwxrwxrwx. 1 root root    0 nov.  10 02:18 upper_vlan2 -> ../vlan2
lrwxrwxrwx. 1 root root    0 nov.  10 02:23 upper_vlan3 -> ../vlan3
lrwxrwxrwx. 1 root root    0 nov.  10 02:23 upper_vlan4 -> ../vlan4

$ sed -n 's/^INTERFACE=//p' /sys/class/net/eth1/upper_*/uevent
vlan1
vlan2
vlan3
vlan4

Since 2017 ip (which uses the (rt)netlink socket interface to communicate with the kernel) got a JSON output for many of its subcommands to ease its scriptability. Together with the jq command this is probably the best choice:

Method 5

$ ip -json link show vlan1 | jq -r '.[]|.link'
eth1

$ ip -json link show type vlan | jq -j '
    .[] | (.ifname," ∈ ",.link,"\n")
'
vlan1 ∈ eth1
vlan2 ∈ eth1
vlan3 ∈ eth1