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