简介:IEEE 802.1Q虚拟桥接局域网标准(P802.1Q/D11)由IEEE计算机学会LAN MAN标准委员会编制,面向网络工程师、VLAN学习者和网络架构设计人员,用于规范虚拟桥接局域网的架构、服务提供及协议算法。内容覆盖VLAN逻辑隔离、802.1Q标签机制、MAC桥接管理、流量控制与安全策略,可直接作为理解VLAN原理和原始规范的一手资料。尽管该草案发布于1998年,但其中关于VLAN划分、帧标记与桥接的核心机制仍是现代交换网络的基础。资源为单个PDF文件,包体2.33MB,便于下载后在本地离线阅读或按章检索。目前已有164人浏览学习,适合网络方向学习者对照标准原文掌握VLAN ID封装、不同VLAN间数据包处理逻辑,以及桥接设备在虚拟局域网中的角色与要求,为后续网络配置、故障排查和方案设计提供标准依据。
1. 虚拟桥接局域网不只是VLAN:IEEE 802.1Q准则到底在管什么
把IEEE原版PDF和现场配置对照起来后,我才发现“虚拟桥接局域网”这个名称差点把我带偏,它并不是一本VLAN配置手册。IEEE 802.1Q真正定义的是桥接设备如何在同一条物理链路上承载多个互相隔离的广播域,包括帧格式、端口成员关系、PVID和转发规则。后来我把这些抽象概念一层层对到物理交换机和虚拟化网桥上,才真正解决跨主机虚拟机同VLAN不通、抓包看不到Tag这类现场问题。这篇笔记按“标准模型→落地参数→边界条件→排错验证”的顺序展开,适合正在和VLAN、Trunk、多租户二层网络较劲的工程师对照参考,尤其适合做虚拟化网络改造时被“设备行为不一致”折磨的人。
2. 读懂802.1Q的帧格式与桥接模型:先弄清Tag、PVID和成员关系
标准里最核心的内容不在“VLAN怎么编号”,而在“VLAN信息用什么载体在链路上传递,桥接设备又如何处理”。把这两点吃透,后面交换机和虚拟化平台的配置就不再是背命令,而是按模型推演。
2.1 802.1Q标签的4字节结构:TPID、TCI、VID怎么拆
普通以太网帧由目的MAC(6字节)、源MAC(6字节)、EtherType(2字节)和载荷组成。802.1Q在源MAC之后、EtherType之前插入4字节标签,这个位置选得很关键:交换机只需要读到目的MAC和标签,就能决定查哪张MAC表并打上对应VLAN标记,不需要理会IP层内容。标准原文把这种桥称为虚拟桥接局域网,真正的变化确实发生在二层。
标签字段拆开来看,是下面这张表的结构:
| 字段 | 长度 | 取值 | 作用 |
|---|---|---|---|
| TPID | 2字节 | 0x8100 | 标识这个帧带VLAN标签 |
| TCI | 2字节 | 复合字段 | 包含PCP、DEI、VID三部分 |
| PCP | 3bit | 0~7 | 802.1p优先级,决定入队调度 |
| DEI | 1bit | 0或1 | 拥塞时优先丢弃标志 |
| VID | 12bit | 0~4095 | VLAN编号,0和4095保留 |
抓包时看到81 00后面两个字节就是TCI。举个例子,如果TCI是0xA064,拆开就是PCP=5(101)、DEI=0、VID=100(0x0064)。这套拆法可以直接用来判断线上Tag是否正常:看到TPID不是0x8100,要么是QinQ外层用了运营商TPID 0x88a8,要么是设备做了VLAN翻译,把整个标签改掉了。
需要提前记住一个反直觉事实:很多网卡驱动会在收包时把Tag剥离后再交给协议栈,所以服务器上tcpdump看不到Tag并不代表线上没有Tag。这个偏差会在第6章抓包验证里反复出现,排错时先默认“我看不到的不一定不存在”。
2.2 桥接模型里的成员关系:Access口、Trunk口与PVID各自承担什么
标准里不直接说“Access口”和“Trunk口”,而是把端口描述为某个VLAN的Tagged成员或Untagged成员。Tagged成员表示从该端口发出的这个VLAN帧会带着802.1Q标签;Untagged成员表示发出的帧不带标签。一个端口可以同时是多个VLAN的Tagged成员,但通常只能是一个VLAN的Untagged成员,这个Untagged VLAN在标准实现里由PVID(Port VLAN ID)指定,思科叫Native VLAN,华为里叫Trunk口PVID。
| 端口角色 | 入方向处理 | 出方向处理 |
|---|---|---|
| Access口 | 把Untagged帧打上PVID指定的VLAN | 去掉Tag后转发 |
| Trunk口 | Untagged帧按PVID归入Native VLAN | 除Native VLAN外全部带Tag |
这种设计解决的是终端接入问题:普通终端网卡不理解Tag,它发出的Untagged帧进入交换机后必须有个默认归属,PVID就是这个归属。而交换机之间的Trunk口必须保留Tag,否则对方无法区分这段流量属于哪个VLAN。我一般会把Access口的PVID和业务VLAN设成同一个值,把Trunk口的PVID和相邻设备配成一致,两端一旦错位,未标记帧就会在两个VLAN之间串来串去。
桥接层面还有一个关键变化:传统桥接表项是“MAC→端口”,802.1Q桥接表项多了一个VLAN维度,变成“VLAN+MAC→端口”。同一个终端MAC如果同时出现在VLAN 100和VLAN 200的表项里并不矛盾,查表时必须带上VLAN条件。这也解释了为什么两个VLAN里出现相同MAC时交换机不会搞混——它在虚拟桥接域里分别学习、分别转发的。
标准里还定义了GVRP/MVRP这类VLAN注册协议,能让交换机自动学习成员关系,但生产环境里动态注册会带来额外泛洪和控制报文开销,我基本都关掉,全部用静态成员配置。
3. 把VLAN配到物理交换机和虚拟化网桥上:两种落地路径与参数选择
标准模型落到设备上分成两条路径:一条是物理交换机之间的Trunk,另一条是宿主机和虚拟交换机之间的Tag透传。两条链路任何一条的“成员关系”定义不同,业务就会断。这里把从创建VLAN到虚拟化侧透传的最小步骤列出来,照着做就能跑通一个最简单的同VLAN互通场景。
3.1 物理交换机上的802.1Q配置步骤:从VLAN创建到Trunk放通
先在核心或汇聚交换机创建VLAN。以华为系统视图为例,vlan 100就直接创建了编号为100的VLAN;Cisco对应命令是全局配置模式下的vlan 100。创建时我习惯把业务类型写进description,比如办公网、服务器网、存储网,否则半年后没人知道这个编号对应什么业务。
接着把连接终端的物理口设成Access并划入VLAN。华为命令是port link-type access和port default vlan 100;Cisco是switchport mode access和switchport access vlan 100。这一步常见的坑是:设备默认所有口都在VLAN 1且是Untagged成员,如果忘了把Access口从默认成员关系里剥离,终端可能同时属于两个VLAN,安全策略直接失效。部分新交换机默认会处理,但老设备必须显式检查。
最后在交换机互联口上启用Trunk并放通业务VLAN。华为的大致配置是:port link-type trunk、port trunk pvid vlan 10、port trunk allow-pass vlan 10 100 200;Cisco对应是switchport mode trunk、switchport trunk native vlan 10、switchport trunk allowed vlan add 100,200。两个参数最容易配错:一个是pvid/native vlan,一个是allow-pass/allowed vlan。PVID负责给入方向的Untagged帧贴标签,allowed列表负责决定哪些VLAN能从Trunk口出去。两端交换机的PVID必须一致,allowed列表也必须对称,否则对端收到Untagged帧时会按自己的PVID把它划到另一个VLAN。
这里用一个表把这几个核心参数说清楚:
| 参数 | 作用 | 建议 |
|---|---|---|
| PVID/Native VLAN | 入方向Untagged帧的归属VLAN | 跨设备保持完全一致 |
| allow-pass/allowed vlan | 出方向允许放行的VLAN列表 | 只放通业务所需VLAN |
| Access口VLAN | 终端口的成员关系 | PVID必须等于业务VLAN |
| Trunk封装 | 是否在出方向加Tag | 除非Native VLAN,都要加Tag |
配完先用display vlan或show vlan检查端口和VLAN的绑定关系,再拿两台终端分别划到两个VLAN,验证VLAN内二层互通和VLAN间不可达。我一般还会故意在Trunk口放通一个临时VLAN,用笔记本抓包确认Tag真实出现在线上,再做下一步虚拟化对接。
3.2 虚拟化环境里的802.1Q透传:Linux Bridge、Open vSwitch与虚拟机网卡
虚拟化环境里落地802.1Q,常见做法有三条路线。第一种是宿主机用VLAN子接口终结标签再接桥。物理网卡eth0接入交换机Trunk口,宿主机上执行ip link add link eth0 name eth0.100 type vlan id 100,就创建了一个VLAN 100的子接口,再把这个子接口作为网桥成员。这种模式适合宿主机自身需要管理IP,又希望虚拟机和物理机处于同一VLAN的场景。这里要理解:子接口在内核里完成了802.1Q标签的添加和剥离,虚拟网桥和虚拟机看到的都是Untagged帧,物理链路上才是Tagged帧。
第二种是把物理网卡直接交给虚拟交换机透传。VMware标准交换机里,上行链路连接物理Trunk口,端口组的VLAN ID填具体编号时,虚拟交换机会给虚拟机出口帧打Tag;端口组VLAN ID填4095表示Trunk透传,由虚拟机内部的网卡驱动自己决定Tag。这个模式里虚拟机网卡驱动通常不需要开启VLAN功能,因为标签由虚拟交换机统一加,虚拟机看到的还是Untagged帧。
第三种是Open vSwitch场景,命令和物理交换机高度等价。最小步骤是:
ovs-vsctl add-br br0
ovs-vsctl add-port br0 eth0
ovs-vsctl add-port br0 vif1 tag=100
第一条创建虚拟桥br0,第二条把物理网卡eth0作为Trunk口加入,第三条把虚拟机网卡vif1划到VLAN 100。这里的tag=100就相当于Access口的PVID,vif1发出的Untagged帧会在OVS里被打上VLAN 100;如果虚拟机本身已经带Tag,则需要把tag去掉、改用trunk=100,200的方式配置。实际踩坑最多的是把tag和trunk参数搞混,导致虚拟机发出的帧被OVS重复打标,到物理交换机后变成两层标签,对端按外层Tag查表自然对不上。
3.3 打通物理与虚拟网络时的链路协商:Trunk封装与VLAN ID映射
物理交换机的口接宿主机时,必须先想清楚这一侧期望看到Tagged还是Untagged帧。宿主机用VLAN子接口或OVS时,物理交换机侧必须设为Trunk并放通对应VLAN;如果宿主机侧把物理网卡设成Access口接入,VLAN信息会在交换机入口被剥掉,宿主机所有虚拟机都只能落在同一个VLAN里,等于没有隔离。
链路两端的VLAN ID必须完全一致,这句话听起来是废话,但跨团队协作时最容易翻车。网络侧说放通了100,虚拟化侧实际配的是VLAN 10,两边对着命令和配置文件看半天,最后发现编号差一位。我一般会在物理交换机Trunk口放通一个临时VLAN并接笔记本抓包,先确认Tag出现在线上,再让虚拟机跑业务,这样就把“配置对不对”和“链路通不通”两个变量拆开了。
另外,如果宿主机用多块物理网卡做链路聚合接交换机,聚合成员口的Trunk配置必须完全一致,包括PVID和放通列表。否则哈希选路可能让同一个VLAN的部分帧从这里走、部分从那里走,链路聚合本身没故障,但VLAN过滤策略不一致会把帧丢掉,表现就是流量忽快忽慢、大包偶发丢失。
注意:VLAN ID在两端的映射不只是“一样”就行,还要确认外层封装一致。一个口在打Tag,另一个口在剥Tag,中间必然有一对不通。
4. 边界参数与扩展机制:VLAN ID范围、优先级、MTU和QinQ
配置能通只是第一步。VLAN ID范围、优先级位和MTU这几个边界条件,才是方案设计和排错时真正容易拦路的地方。很多人被夜间电话叫醒,问题往往不是Trunk没放通,而是这些边界参数在某一段链路上没对齐。
4.1 VLAN ID的可用范围与保留值:0、1、1002-1005、4095不能乱用
12位VID只有4096个取值,但并不是1到4094都能直接当业务VLAN用。0在标准里表示“帧中没有有效VLAN ID”,通常用于优先级处理;4095是保留值,绝大多数设备不允许作为普通VLAN创建。VLAN 1是设备默认VLAN,所有Untagged口在没有配置时都归属它,很多交换机不允许删除,我一般只留作管理或带外用途,不承载业务。1002到1005是为兼容令牌环和FDDI时代保留的编号,现在用不到,规划时直接绕开。
| VLAN ID | 状态 | 建议 |
|---|---|---|
| 0 | 保留 | 不创建业务VLAN |
| 1 | 默认存在 | 只做管理/带外 |
| 2~1001 | 通用范围 | 优先做业务VLAN |
| 1002~1005 | 历史保留 | 不规划 |
| 1006~4094 | 扩展范围 | 大二层或多租户时再启用 |
规划时我习惯从10或100开始编号,把1留给设备默认,把2到9留作上行和互联,这样后续加业务不用重构已有配置。还要注意,某些老式交换机对1006以上的VLAN支持不完整,比如MSTP实例映射、QinQ外层VLAN编号范围都可能受限,跨厂商对接前先查对方的VLAN范围支持表。
4.2 优先级字段与QoS映射:PCP的3bit怎么影响队列
802.1Q的TCI里PCP只占3bit,取值0到7。0是尽力而为默认,1到2通常映射到后台或低优先级队列,3到4用于视频等中等优先级,5和6给语音和控制平面,7留给网络管理。DEI位表示“拥塞时可优先丢弃”,适合在链路带宽不足时保护高优先级业务。
| PCP值 | 常见用途 | 队列建议 |
|---|---|---|
| 0 | 默认数据 | 尽力而为 |
| 1~2 | 后台任务、批量复制 | 低优先级 |
| 3~4 | 视频、实时交互 | 中等优先级 |
| 5~6 | 语音、控制平面 | 高优先级 |
| 7 | 网络管理 | 最高优先 |
交换机的CoS映射表决定PCP最终对应哪个硬件队列,厂商默认映射往往不一致,不能只看标准。配置后必须验证优先级位确实从入口一路带到出口。很多Access口把Untagged帧打上PVID时,会把PCP清成0,导致语音质量无法保证。我一般会在入口交换机做基于端口的默认优先级或DSCP到PCP的映射,再在出口用抓包确认vlan.priority数值。QoS的坑通常不在队列算法,而在入口把优先级悄悄清了。
4.3 加了Tag后MTU少4字节:从1500到1496的链路层适配
802.1Q让以太网帧多了4字节,传统“最大帧1518字节”的模型要被打破。标准层面IEEE 802.3ac已经把带Tag的帧扩充到1522字节,所以单一VLAN场景下,1500字节IP包不会因为多4字节Tag就被丢。真正出问题的场景是叠加:QinQ双标签后帧变成1526字节,VXLAN还要再封装大几十字节,此时如果物理链路MTU还按1500配置,大包就会在入端口被静默丢弃。这是“小包通、大包断”最常见的原因。
排错时不要只看接口显示的MTU,要看整条路径的帧预算。我的做法是不对称排查:从终端用ping -M do -s 1400逐步加大到1472,找到丢包阈值,再反推是哪一跳的MTU不够。如果是普通Trunk口,把相关接口的L3 MTU统一到1504,为单个Tag留出4字节预算;要跑QinQ就把1504再往上加。如果设备不支持调整MTU且只认1518字节帧上限,那就只能保守地把上层业务IP包控制在1496字节以下,这也是老文档里“Tag让MTU变1496”说法的来源。
Linux虚拟接口的MTU默认继承物理口,修改父接口MTU后,VLAN子接口要同步调整,否则会出现物理链路正常、子接口通不了大包的怪象。虚拟机内部的网卡MTU也要纳入同一张预算表,不能只在物理交换机上改。
4.4 QinQ的扩展:服务商场景下的双层Tag
QinQ本质是把用户的VLAN Tag作为内层标签,再套一个运营商VLAN Tag。它最早由IEEE 802.1ad定义,后来在802.1Q的修订版里并入Provider Bridging扩展,所以“虚拟桥接局域网”准则能支撑多租户二层,靠的就是这套机制。外层TPID常用0x88a8,但不少厂商默认用0x8100做外层,对接前先确认两端TPID一致,否则对端会把双层Tag当单层来处理,内层信息直接丢失。
配置要点是:接入侧端口通常配成“外层VLAN固定”,用户从该口进入的帧不管内层VLAN编号是什么,统一打上同一个外层Tag;上联Trunk口只放通运营商VLAN。这样用户侧随便规划VLAN都不会冲突,两个租户各自使用VLAN 100也互不干扰。数据中心的典型用法是给每个租户分配一个外层VLAN,租户内部的VLAN标识作为内层透传。
QinQ还影响MAC学习和转发方式:运营商桥只看外层Tag和源MAC,内层Tag在运营商网络里不参与查表,只在用户侧边缘设备被识别。跨城域二层互联时,如果线路服务商只透传一个VLAN,要确认内层标签是否被保留。很多所谓“VLAN透明传输”实际就是QinQ,抓包时能看到原始用户Tag;但如果服务商做的是VLAN翻译,你的Tag会被改写,业务表现就是设备重启后网络地址拿不到、链路恢复但会话全部中断。
5. 802.1Q落地常见问题与排查:现象、原因与解决
这里整理几个我在Trunk对接、虚拟机VLAN透传和抓包验证时反复遇到的现场问题,每条按“现象→原因→解决”顺序写,方便直接对照。这些问题几乎都不是标准本身复杂,而是设备默认行为、驱动处理和人的预期不一致。
5.1 现象:Trunk两端都放通VLAN,大包不通或间歇性卡顿
小包ping同VLAN正常,ping带1472字节数据的大包开始丢,或者数据库同步时随机超时。原因通常是链路没有给802.1Q标签留帧长预算,或者某一段虚拟网卡MTU小于对端。很多交换机默认支持1522字节帧,但网关、负载均衡、虚拟防火墙这类中间设备不一定支持;流量经过QinQ或隧道后帧长被撑到1526以上,任何一环不支持就直接丢弃。
解决时先把两端接口MTU统一提到1504或更大,再用指定大小ICMP探测定位边界。我一般会维护一张“端口MTU表”,覆盖物理交换机Trunk口、宿主机物理网卡、OVS网桥和虚拟机网卡四个层次,四层都一致才认为MTU清理干净。只改一处、不改另一处,问题会从一个点挪到另一个点。
5.2 现象:用户终端拿到了其他VLAN的地址,出现串VLAN
一个普通终端口竟然能访问另一个VLAN的网关,安全审计发现异常。原因一般是终端口被配成了Trunk,或者Trunk口的Native VLAN/PVID和相邻设备不一致,导致未标记帧被PVID映射到不该访问的VLAN。DTP/VTP这类动态协议在思科环境里还可能让某个口自动协商成Trunk,这就是VLAN Hopping的标准攻击路径。
解决思路是所有终端口显式配成Access并指定VLAN,关闭动态Trunk协商;Trunk口的PVID两端核对一致,并把Native VLAN改成不承载业务的编号,例如VLAN 4094。针对双标签攻击,还要确认边界交换机是否把内层Tag剥掉后再重新打外层标签,不要让带两层Tag的帧直接从用户口进入Trunk。这个问题的本质是标准里每一跳都有权处理Tag,所以边界口必须把信任关系写死。
5.3 现象:虚拟机配了VLAN ID还是不通,宿主机tcpdump全是Untagged帧
VMware或OVS里的虚拟机设置了VLAN 100,物理交换机Trunk也放通了100,但虚拟机访问网关不通。抓包时在宿主机看到的却全是不带Tag的帧。原因有两个方向:一是现代网卡驱动的VLAN offload会在收包时把Tag剥离,tcpdump显示的是驱动处理后的帧;二是物理交换机接宿主机那一侧实际是Access口,VLAN 100的Tag在入交换机时被剥掉,虚拟化侧发上来的带Tag帧被交换机按PVID重新归类。
解决时先确认物理口是不是Trunk并把100放通;抓包时用ethtool -K eth0 rxvlan off txvlan off关掉网卡的VLAN硬件处理;OVS场景里再用ovs-ofctl dump-flows br0检查in_port对应的actions里是否带push_vlan动作。需要注意,关闭offload只影响抓包显示,不影响正常转发,但会让CPU消耗上升,抓完包记得恢复。
提示:宿主机tcpdump看不到Tag,不等于线上没有Tag。先用
ethtool关掉网卡VLAN offload,再谈后面排查,这个顺序能省一半时间。
5.4 现象:镜像口抓包看不到预期Tag,Wireshark过滤vlan为空
交换机配置了SPAN/RSPAN,笔记本接到镜像口,过滤vlan却一帧都没有。原因通常是SPAN会话只镜像了Ingress方向,或者源端口是Access而不是Trunk;也可能是抓包网卡驱动默认丢弃带Tag帧。解决时把SPAN源端口设为Trunk接口、方向选both,目的端口用普通物理接口而不是聚合成员口;抓包网卡关闭VLAN offload后,应该能在Wireshark里看到81 00开头的TPID。
此时再用vlan.id == 100和vlan.priority == 5组合过滤,就能快速判断线上帧的VLAN和优先级是否符合预期。如果抓到的帧只有外层Tag但业务预期是QinQ,问题大概率在接入设备把内层Tag剥掉了,不是抓包方法的问题。抓包这件事,最难的不是命令,而是选择正确的观测点。
6. 用抓包和文档精读验证你的802.1Q理解:从标准条款到现场判断
6.1 用Wireshark快速解出Tag字段:过滤规则与关键列
打开抓包文件后,第一件事是确认线上帧长度。普通无Tag帧是1518,带一个Tag是1522,双Tag是1526,长度可以直接告诉你这条链路上有没有VLAN封装。Wireshark的显示过滤器支持vlan、vlan.id == 100、vlan.priority == 5,把vlan.id和vlan.priority加到列显示,扫一眼就能看到每个VLAN的分布。抓包位置建议选交换机的SPAN镜像口或物理Trunk下联口,不要只抓宿主机内部的虚拟端口,因为虚拟机之间的流量可能根本不经过物理链路,看到的是虚拟交换机加工后的帧。
6.2 对照标准原文做一次自查:条款编号与实现偏差
标准原文读起来枯燥,但有一个高效读法:先找PVID和端口成员关系的定义,再看Tagged/Untagged帧的处理顺序,最后核对厂商默认行为。我给自己定的自查清单是:这个接口入方向遇到Untagged帧会归到哪个VLAN;这个接口出方向对Native VLAN是否剥Tag;配置Access后PVID是否等于业务VLAN编号;交换机和宿主机两侧的MTU差是否符合帧长预算。四项全对,再配合一次抓包,二层的转发行为基本不会有意料之外。
我现在的习惯是:遇到VLAN问题,先把线上帧抓出来看Tag,再回头翻标准条款,最后才动手改配置。顺序一旦反过来,大概率会把配置越改越乱,因为你是在猜,不是在看。希望帮到你。
本文还有配套的精品资源,点击获取