Yuhang Zheng

VLAN网桥配置过程中的DefaultPVID和tagged

N 人看过

续接上一篇文章,我们在第二种方法中提到了DefaultPVID参数,那么我们该如何理解DefaultPVID参数呢,它的作用是什么?

DefaultPVID的释意

systemd.netdev (www.freedesktop.org)中可以看到DefaultPVID的解释:

DefaultPVID=
This specifies the default port VLAN ID of a newly attached bridge port. Set this to an integer in the range 1–4094 or "none" to disable the PVID.
这指定了新连接的桥接端口的默认端口 VLAN ID。将其设置为 1–4094 范围内的整数或“无”以禁用 PVID。

以上内容便说明了通过systemd方式配置网桥时,br0.netdev文件中DefaultPVID参数的作用就是给所有加入该网桥的网络端口配置一个PVID,包括网桥自己。

那么这个PVID和普通的VLAN ID有什么区别呢?暂时先保留这个疑问往下看。

pvid和untagged的作用

首先看一下bridge命令的选项说明:

bridge vlan { add | del } dev DEV vid VID [ pvid ] [ untagged ] [ self ] [ master ]

选项说明:

pvid:端口的默认vlan,所有从该端口输入的没有携带vlan的报文,会被打上该vlan标签,该选项只对输入报文有效。
untagged:端口的untag vlan,输出报文携带该vlan时,会被剥离。

一般情况下pvid和untagged是同时使用的。

由上述说明可以看到,在bridge命令中,pvid和untagged参数是高度关联的。那么,这个tag又是什么东西呢?Tagged和Untagged又是什么?

接下来可以参照交换机的发送帧和接受帧时候对VLAN的处理来理解。

1、接收帧时:所有以太网帧在交换机中都是以Tagged的形式处理转发的,因此设备必须给接口收到的Untagged帧加上Tag。为了实现此目的,必须配置接口的缺省VLAN。当该接口收到Untagged帧时给它加上该接口缺省VLAN的VLAN Tag。
2、发送帧时:当该帧的VLAN ID与端口的PVID不同时,直接透传;当该帧的VLAN ID与端口的PVID相同时,则剥去Tag;(前提是看该VLAN ID在允许通过的VLAN ID列表中;如果在列表中,才会去比较PVID)。

※数据帧打不打Tag 与 允不允许带该Tag的数据帧通过 没有必然关系。

1、数据帧到达时:若不带VLAN Tag,无论如何会先打上缺省的VLAN ID,再看该缺省VLAN ID在不在允许通过的VLAN ID列表中。
2、数据帧发送时:先看该VLAN ID在允许通过的VLAN ID列表中;如果不在允许的列表中,直接丢弃;如果在列表中,才会去比较PVID,决定剥还是不剥Tag。

※只要数据帧的VLAN ID不在允许通过的VLAN ID列表里时(无论是接收时就带VLAN ID,还是接收后打上的缺省的VLAN ID),都会丢弃该报文。

简而言之:

1:对于trunk口

当收到的帧不带tag,先打PVID,再比较PVID是否在Allow VLAN,在——接收,不在——丢弃。

当收到的帧带tag,比较TAG是否在Allow VLAN,在—接收,不在-丢弃

2:端口默认时,会转发所有vlan1的数据。为了防止产生广播风暴,在接口下经常要配置undo vlan 1

3:因此trunk口在发送数据时:TAG属于Allow VLAN,比较TAG是否属于PVID,属于——剥离TAG;不属于——保持TAG

实际情况演示

下面我们实际看一下,以上一篇文章中的方法二为一个简单示例搭一个环境,

/etc/systemd/network/fm1-mac1.network

[Match]
Name=fm1-mac1

[Network]
Bridge=br0

[BridgeVLAN]
VLAN=100

[BridgeVLAN]
VLAN=200

/etc/systemd/network/fm1-mac9.network

[Match]
Name=fm1-mac9

[Network]
Bridge=br0

[BridgeVLAN]
VLAN=100

以下是/etc/systemd/network/br0.netdev不同配置时,bridge vlan show命令看到的情况

DefaultPVID=100:

/etc/systemd/network/br0.netdev

[NetDev]
Name=br0
Kind=bridge
[Bridge]
DefaultPVID=100
VLANFiltering=true
STP=false

bridge vlan show

image-20210601165229206

根据上图我们可以看到

port vlan ids 说明
fm1-mac1 100
200
fm1-mac9 100
br0 100 PVID Egress Untagged br0输出报文携带该vlan时,会被剥离

此时向fm1-mac9发送一个VLAN100的数据帧,在fm1-mac9可以看到:(此处看到的是发给fm1-mac9的帧)

root@localhost:~# tcpdump -i fm1-mac9 -vve
tcpdump: listening on fm1-mac9, link-type EN10MB (Ethernet), capture size 262144 bytes
14:07:27.515215 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

fm1-mac9收到了VLAN100的数据帧之后,经过比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,不需要,则保持TAG然后发送。

br0会监听桥上所有流通的数据帧,并将某一个网卡发送的数据帧直接透传转发给所有网卡,所以对br0的抓包只是看到是否有帧通过,以及br0本身对数据帧的处理

在br0可以看到:

root@localhost:~# tcpdump -i br0 -vve
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
12:42:39.071731 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype Unknown (0x88ba), length 337:

br0收到了fm1-mac9发送的VLAN100的数据帧之后,比较TAG是否需要进行Untagged,需要,则剥离TAG

在fm1-mac1可以看到:(此处看到的是fm1-mac1发送的帧)

root@localhost:~# tcpdump -i fm1-mac1 -vve
tcpdump: listening on fm1-mac1, link-type EN10MB (Ethernet), capture size 262144 bytes
12:42:55.192324 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

fm1-mac1收到了fm1-mac9发送的流经了br0的带有VLAN100的数据帧之后,经过比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,不需要,则保持TAG然后发送。

DefaultPVID=none:

/etc/systemd/network/br0.netdev

[NetDev]
Name=br0
Kind=bridge
[Bridge]
DefaultPVID=none
VLANFiltering=true
STP=false

bridge vlan show

image-20210601170653007

根据上图我们可以看到

port vlan ids 说明
fm1-mac1 100
200
fm1-mac9 100
br0 None

此时向fm1-mac9发送一个VLAN100的数据帧,在fm1-mac9可以看到:(此处看到的是发给fm1-mac9的帧)

root@localhost:~# tcpdump -i fm1-mac9 -vve
tcpdump: listening on fm1-mac9, link-type EN10MB (Ethernet), capture size 262144 bytes
14:19:39.249789 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

fm1-mac9收到了VLAN100的数据帧之后,经过比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,不需要,则保持TAG然后发送。

在br0可以看到:

root@localhost:~# tcpdump -i br0 -vve
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:19:57.826871 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

br0收到了fm1-mac9发送的VLAN100的数据帧之后,比较TAG是否需要进行Untagged,不需要,则保持TAG

在fm1-mac1可以看到:

root@localhost:~# tcpdump -i fm1-mac1 -vve
tcpdump: listening on fm1-mac1, link-type EN10MB (Ethernet), capture size 262144 bytes
14:20:14.850848 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

fm1-mac1收到了fm1-mac9发送的流经了br0的带有VLAN100的数据帧之后,经过比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,不需要,则保持TAG然后发送。

DefaultPVID=111:

/etc/systemd/network/br0.netdev

[NetDev]
Name=br0
Kind=bridge
[Bridge]
DefaultPVID=111
VLANFiltering=true
STP=false

bridge vlan show

image-20210601170911530

根据上图我们可以看到

port vlan ids 说明
fm1-mac1 100
111 PVID Egress Untagged fm1-mac1输出报文携带该vlan时,会被剥离
200
fm1-mac9 100
111 PVID Egress Untagged fm1-mac9输出报文携带该vlan时,会被剥离
br0 111 PVID Egress Untagged br0输出报文携带该vlan时,会被剥离

向fm1-mac9发送一个VLAN100的数据帧

此时向fm1-mac9发送一个VLAN100的数据帧,在fm1-mac9可以看到:(此处看到的是发给fm1-mac9的帧)

root@localhost:~# tcpdump -i fm1-mac9 -vve
tcpdump: listening on fm1-mac9, link-type EN10MB (Ethernet), capture size 262144 bytes
14:22:37.590162 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

fm1-mac9收到了VLAN100的数据帧之后,经过比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,不需要,则保持TAG然后发送。

在br0可以看到:

root@localhost:~# tcpdump -i br0 -vve
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:22:58.590664 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

br0收到了fm1-mac9发送的VLAN100的数据帧之后,比较TAG是否需要进行Untagged,不需要,则保持TAG

在fm1-mac1可以看到:

root@localhost:~# tcpdump -i fm1-mac1 -vve
tcpdump: listening on fm1-mac1, link-type EN10MB (Ethernet), capture size 262144 bytes
14:23:17.007224 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 100, p 4, ethertype 0x88ba,

fm1-mac1收到了fm1-mac9发送的流经了br0的带有VLAN100的数据帧之后,经过比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,不需要,则保持TAG然后发送。


向fm1-mac9发送一个VLAN111的数据帧

此时向fm1-mac9发送一个VLAN111的数据帧,在fm1-mac9可以看到:(此处看到的是发给fm1-mac9的帧)

root@localhost:~# tcpdump -i fm1-mac9 -vve
tcpdump: listening on fm1-mac9, link-type EN10MB (Ethernet), capture size 262144 bytes
14:24:26.305122 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 111, p 4, ethertype 0x88ba,

fm1-mac9收到了VLAN111的数据帧之后,比较TAG是否需要进行Untagged,需要,则剥离TAG然后发送。

在br0可以看到:

root@localhost:~# tcpdump -i br0 -vve
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:26:34.613896 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype Unknown (0x88ba), length 337:

br0收到了fm1-mac9发送的Untagged数据帧之后,收到的帧不带TAG,先打PVID111的TAG,比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,需要,则剥离TAG

在fm1-mac1可以看到:

root@localhost:~# tcpdump -i fm1-mac1 -vve
tcpdump: listening on fm1-mac1, link-type EN10MB (Ethernet), capture size 262144 bytes
14:27:03.750824 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype Unknown (0x88ba), length 337:

fm1-mac1收到了fm1-mac9发送的流经了br0的Untagged数据帧之后,收到的帧不带TAG,先打PVID111的TAG,比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,需要,则剥离TAG然后发送。


向fm1-mac9发送一个VLAN120的数据帧

此时向fm1-mac9发送一个VLAN120的数据帧,在fm1-mac9可以看到:(此处看到的是发给fm1-mac9的帧)

root@localhost:~# tcpdump -i fm1-mac9 -vve
tcpdump: listening on fm1-mac9, link-type EN10MB (Ethernet), capture size 262144 bytes
14:36:39.969915 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 120, p 4, ethertype 0x88ba,

fm1-mac9收到了VLAN120的数据帧之后,经过比较TAG不在Allow VLAN中,所以将帧丢弃。

在br0可以看到:

root@localhost:~# tcpdump -i br0 -vve
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes

br0没有监听到fm1-mac9发送的数据帧

在fm1-mac1可以看到:

root@localhost:~# tcpdump -i br0 -vve
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes

fm1-mac1没有数据帧发出


向fm1-mac1发送一个VLAN200的数据帧

此时向fm1-mac1发送一个VLAN200的数据帧,在fm1-mac1可以看到:(此处看到的是发给fm1-mac1的帧)

root@localhost:~# tcpdump -i fm1-mac1 -vve
tcpdump: listening on fm1-mac1, link-type EN10MB (Ethernet), capture size 262144 bytes
09:13:35.014019 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 200, p 4, ethertype 0x88ba,

fm1-mac1收到了VLAN200的数据帧之后,经过比较TAG在Allow VLAN中,所以将帧接收,然后比较TAG是否需要进行Untagged,不需要,则保持TAG然后发送。

在br0可以看到:

root@localhost:~# tcpdump -i br0 -vve
tcpdump: listening on br0, link-type EN10MB (Ethernet), capture size 262144 bytes
09:13:24.918034 4c:e1:73:42:30:7c (oui Unknown) > 01:0c:cd:04:40:01 (oui Unknown), ethertype 802.1Q (0x8100), length 341: vlan 200, p 4, ethertype 0x88ba,

br0收到了fm1-mac1发送的VLAN200的数据帧之后,比较TAG是否需要进行Untagged,不需要,则保持TAG

在fm1-mac9可以看到:

root@localhost:~# tcpdump -i fm1-mac9 -vve
tcpdump: listening on fm1-mac9, link-type EN10MB (Ethernet), capture size 262144 bytes

fm1-mac9收到了VLAN120的数据帧之后,经过比较TAG不在Allow VLAN中,所以将帧丢弃。fm1-mac9没有数据帧发出

我们验证了之前的解释:DefaultPVID参数的作用就是给所有加入该网桥的网络端口配置一个PVID,包括网桥自己。

同时也发现了一个点,那就是如果设置的PVID在VID中存在的话,那么这个VID是untagged的。

命令创建VLAN网桥示例

接下来我们举一些使用命令创建VLAN网桥示例,这些例子来源于networking - Bridged interfaces and VLAN tags - Unix & Linux Stack Exchange

首先是创建一个普通网桥的示例:

# 开启网卡eth0和tap1
ip link set eth0 up
ip link set tap1 up

# 创建一个普通网桥,名字为br0,以下行可以在创建网桥时直接包含附加参数 `vlan_filtering 1`
ip link add name br0 type bridge

# 将网卡eth0和tap1添加到网桥br0中
ip link set tap1 master br0
ip link set eth0 master br0

激活网桥br0的VLAN感知功能:

# 设置网桥附加参数 `vlan_filtering 1`
ip link set dev br0 type bridge vlan_filtering 1

# 删除在添加网卡到网桥的时候为网卡默认创建的vid 1配置
bridge vlan del dev tap1 vid 1
bridge vlan del dev eth0 vid 1

# 为网卡tap1添加vid 5
bridge vlan add dev tap1 vid 5
# 为网卡tap1添加vid 5,同时将其设置为pvid untagged,此处在命令的末尾省略了master参数
bridge vlan add dev eth0 vid 5 pvid untagged

# 开启网桥
ip link set br0 up
# 删除在创建网桥的时候默认创建的vid 1配置
bridge vlan del dev br0 vid 1 self
# 为网桥br0添加vid 5,同时将其设置为pvid untagged
bridge vlan add dev br0 vid 5 pvid untagged self