1. QINQ 技术核心原理与适用场景拆解
QINQ,业内也常叫它 Stacked VLAN 或者 Double VLAN,说白了就是在原来一个 802.1Q 的 VLAN Tag 外面再套一层 Tag。普通 VLAN 帧只有 4 个字节的 Tag 字段,QINQ 就是在它前面再塞 4 个字节,形成两层标签。外层通常叫 S-VLAN(Service VLAN),内层叫 C-VLAN(Customer VLAN)。这个设计最初是为了解决一个很现实的问题:早期 802.1Q 只有 12 个 bit 表示 VLAN ID,满打满算 4094 个可用,一个大型园区或者运营商接入网根本不够分,而且不同客户之间的 VLAN 规划还会撞车。
我最早接触 QINQ 是在一个多租户的接入场景里,每个租户内部都有自己的 VLAN 规划,比如都用 VLAN 10 做管理、VLAN 20 做业务。如果直接把这些 VLAN 透传到汇聚层,冲突是必然的。QINQ 的思路很直接:你内部怎么规划我不管,到了我的接入端口,我统一给你套一个外层 Tag,这个外层 Tag 在整个骨干网里唯一标识你这个租户。这样内层 VLAN 对骨干网就是透明的,冲突问题自然消解。
从技术本质上看,QINQ 解决的是VLAN 空间扩展和租户隔离两个核心诉求。它不改变以太网帧的基本结构,只是在 Tag 层面做叠加,所以对上层协议几乎无感知。这也是它比 MPLS 之类方案更容易落地的地方——你不需要动路由协议,不需要改终端配置,只在交换机端口上做文章。
适用场景我归纳下来主要是三类。第一类是运营商城域网接入,每个用户一个外层 VLAN,内层由用户自己折腾。第二类是大型园区多租户,比如一栋写字楼里多家公司共用一套物理网络,每家一个 S-VLAN。第三类是数据中心租户隔离,尤其是早期没有 VXLAN 的年代,QINQ 是性价比很高的选择。现在虽然 VXLAN 很火,但在一些中小规模场景里,QINQ 依然有它的位置,因为配置简单、对硬件要求低、排障直观。
需要提前说清楚的是,QINQ 不是所有交换机都支持。一般接入层交换机需要支持基本 QINQ或灵活 QINQ,汇聚和核心层需要能识别双层 Tag 并做转发。选型的时候一定要确认芯片是否支持双层 Tag 的线速转发,有些低端芯片虽然标称支持,但实际转发性能会打折扣。这一点我在后面选型部分还会细说。
2. 配置前的整体设计与关键参数规划
2.1 基本 QINQ 与灵活 QINQ 的选型逻辑
动手敲命令之前,先要决定用哪种模式。基本 QINQ 的逻辑是:一个接入端口收到所有带 Tag 的帧,统一打上同一个外层 S-VLAN。灵活 QINQ 则是根据内层 C-VLAN 的不同,映射到不同的外层 S-VLAN。这两者的差别直接决定了你后续的配置复杂度和业务灵活性。
基本 QINQ 适合什么情况?租户内部 VLAN 规划简单,或者你根本不在乎内层是什么,只要把整个端口划给一个租户就行。比如一个客户独占一个物理端口,那基本 QINQ 最省事,一条命令搞定。灵活 QINQ 适合什么情况?多个租户共享一个物理端口,或者同一个租户内部不同业务需要走不同的外层 VLAN。这时候就需要做 VLAN 映射表。
我个人的经验是:能基本就基本,除非业务真的需要灵活映射。因为灵活 QINQ 的映射表维护起来很烦,尤其是租户多了以后,一张表几十条甚至上百条,改一条要反复确认。基本 QINQ 的排障也简单,抓包一看外层 Tag 就知道是哪个租户。
2.2 外层 VLAN 编号规划与冲突规避
外层 S-VLAN 的编号规划是个容易被忽视但很要命的环节。我的建议是外层和内层使用完全不同的编号段,比如内层用 1-1000,外层从 2000 开始。这样做的目的是排障时一眼就能区分哪层是哪层,不至于看花眼。
另外外层 VLAN 在整个骨干网里必须唯一。如果你有多个接入点,每个接入点下面挂不同租户,那外层 VLAN 的分配要有全局台账。我见过有人图省事,每个接入点都从 VLAN 100 开始编外层,结果汇聚层一合并就冲突,业务时通时断,查了两天才发现是外层 VLAN 撞了。这个坑一定要提前避开。
还有一个细节:外层 VLAN 不要用 VLAN 1。VLAN 1 在很多设备上是默认 VLAN,行为特殊,用它做外层容易出幺蛾子。从 VLAN 2 开始编,或者干脆从 100 开始,留出余量。
2.3 端口角色与链路类型确认
QINQ 配置里端口角色分两种:接入侧端口(连客户的)和干道侧端口(连骨干的)。接入侧端口负责打外层 Tag,干道侧端口负责透传双层 Tag。这两个角色的配置逻辑完全不同,搞混了业务就不通。
接入侧端口一般配成dot1q-tunnel类型,或者在某些厂商设备上叫QINQ 端口。干道侧端口配成trunk类型,并且要允许外层 S-VLAN 通过。这里有个关键点:干道侧端口必须允许外层 VLAN,内层 VLAN 不需要在干道侧显式允许,因为内层对骨干是透明的。
我踩过的一个坑是:干道侧端口忘了允许外层 VLAN,结果接入侧打了 Tag,干道侧直接丢了,业务不通。抓包看到接入侧有双层 Tag,干道侧只有单层,才反应过来是干道侧没放行。这个排查思路后面会细讲。
2.4 硬件与芯片能力的前置确认
不是所有交换机都能玩 QINQ。配置前一定要确认三件事:接入侧交换机是否支持 QINQ 功能、干道侧交换机是否支持双层 Tag 转发、整条路径的 MTU 是否够用。
MTU 这个点特别容易被忽略。普通以太网帧 1518 字节,加一层 Tag 变成 1522,加两层变成 1526。如果路径上有设备 MTU 卡在 1522,那双层 Tag 的帧就会被丢。我遇到过核心交换机 MTU 默认 1522,结果 QINQ 帧过大被静默丢弃,现象是 ping 小包通、大包不通,非常迷惑。后来把路径上所有设备 MTU 调到 1536 以上才解决。
芯片能力方面,重点看接入侧是否支持QINQ 硬件打标。有些设备是软件打标,性能差很多,流量一大就丢包。选型时查一下芯片型号,或者直接问厂商要转发性能数据。干道侧看是否支持双层 Tag 线速转发,这个一般中高端交换机都没问题,但低端盒式机要留意。
3. 实操配置流程与核心命令详解
3.1 接入侧交换机基本 QINQ 配置
先拿基本 QINQ 开刀,这是最常用的模式。假设接入侧交换机型号为某主流厂商设备,客户端口是 GigabitEthernet 0/0/1,外层 S-VLAN 规划为 2000。
第一步,创建外层 VLAN。
system-view vlan 2000 description QINQ_SVLAN_FOR_TENANT_A quit第二步,配置接入端口为 dot1q-tunnel 类型,并指定外层 VLAN。
interface GigabitEthernet 0/0/1 port link-type dot1q-tunnel port default vlan 2000 qinq enable quit这几条命令的逻辑是:port link-type dot1q-tunnel把端口设成 QINQ 接入模式,port default vlan 2000指定打上的外层 VLAN,qinq enable开启 QINQ 功能。不同厂商命令略有差异,有的用qinq vlan-translation enable,有的直接在端口下qinq就完事,但核心逻辑一致。
第三步,配置干道侧端口,允许外层 VLAN 通过。
interface GigabitEthernet 0/0/24 port link-type trunk port trunk allow-pass vlan 2000 quit这里只允许 VLAN 2000,不需要允许内层 VLAN。因为内层 Tag 对干道是透明的,交换机只认外层。
配置完可以用display qinq interface GigabitEthernet 0/0/1查看 QINQ 状态,确认端口模式和默认 VLAN 是否正确。
3.2 灵活 QINQ 的 VLAN 映射配置
灵活 QINQ 的核心是 VLAN 映射表。假设客户端口 GigabitEthernet 0/0/2 上,内层 VLAN 10 要映射到外层 2001,内层 VLAN 20 映射到外层 2002。
interface GigabitEthernet 0/0/2 port link-type dot1q-tunnel qinq enable qinq vlan-translation enable port vlan-mapping vlan 10 map-vlan 2001 port vlan-mapping vlan 20 map-vlan 2002 quitport vlan-mapping这条命令就是映射规则。内层 VLAN 10 的帧进来,打上外层 2001;内层 VLAN 20 的帧进来,打上外层 2002。没在映射表里的内层 VLAN 怎么处理?默认是丢弃,或者按端口默认 VLAN 处理,取决于设备实现。我一般建议显式配置一条默认规则,避免意外流量被丢。
干道侧配置和基本 QINQ 一样,允许外层 VLAN 2001 和 2002 通过。
interface GigabitEthernet 0/0/24 port link-type trunk port trunk allow-pass vlan 2001 2002 quit灵活 QINQ 的映射表维护要有台账,建议用表格记录:端口、内层 VLAN、外层 VLAN、租户名称、备注。租户变更时先查台账再改配置,避免改错。
3.3 干道侧与核心侧的双层 Tag 透传配置
干道侧和核心侧的任务是透传双层 Tag,配置相对简单,但有几个细节要注意。
干道侧端口配成 trunk,允许所有外层 S-VLAN 通过。如果外层 VLAN 很多,可以用port trunk allow-pass vlan all,但生产环境我建议显式列出,避免意外流量混入。
interface GigabitEthernet 0/0/24 port link-type trunk port trunk allow-pass vlan 2000 to 2100 quit核心侧如果要做三层终结,需要配置QINQ 终结子接口。比如在核心交换机上,外层 2000 内层任意 VLAN 的流量要终结到某个 VRF 或者做路由。
interface GigabitEthernet 0/0/1.2000 dot1q termination vid 2000 qinq termination pe-vid 2000 ce-vid any ip address 10.0.0.1 255.255.255.0 quitqinq termination pe-vid 2000 ce-vid any的意思是:外层 VLAN 2000,内层任意 VLAN,都终结到这个子接口。如果只想终结特定内层 VLAN,把any换成具体 VLAN ID 即可。
这里有个坑:子接口的 MTU 要调大。默认 1500 的话,双层 Tag 帧可能被丢。建议调到 1504 以上,保险起见 1508。
interface GigabitEthernet 0/0/1.2000 mtu 1508 quit3.4 配置验证与抓包确认方法
配置完不验证等于没配。我习惯分三步验证:先看接口状态,再看 MAC 地址表,最后抓包确认 Tag 结构。
看接口状态:
display interface GigabitEthernet 0/0/1 brief display qinq interface GigabitEthernet 0/0/1确认端口 up、QINQ 使能、默认 VLAN 正确。
看 MAC 地址表:
display mac-address vlan 2000应该能看到客户侧设备的 MAC 地址学习在外层 VLAN 2000 下。如果学不到,说明打标或透传有问题。
抓包是最直接的。在干道侧端口做端口镜像,用抓包工具看帧结构。正常应该看到两层 802.1Q Tag,外层是 2000,内层是客户原始 VLAN。如果只看到一层,说明接入侧没打标或者干道侧把外层剥了。如果看到两层但内层不对,说明映射表配错了。
我一般会在接入侧和干道侧各抓一次,对比 Tag 变化,这样能快速定位问题出在哪一段。
4. 典型故障排查与避坑经验实录
4.1 业务不通的常见原因速查
QINQ 业务不通,原因就那么几类,我整理了一张速查表,按概率从高到低排。
| 故障现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 完全不通 | 接入侧未使能 QINQ | 查display qinq interface | 端口下补qinq enable |
| 完全不通 | 干道侧未允许外层 VLAN | 查display port trunk | trunk 允许外层 VLAN |
| 小包通大包不通 | MTU 不足 | ping 不同大小包测试 | 路径设备 MTU 调至 1508+ |
| 时通时断 | 外层 VLAN 冲突 | 查全局 VLAN 台账 | 重新规划外层 VLAN |
| 部分 VLAN 不通 | 映射表缺失 | 查display qinq vlan-mapping | 补映射规则 |
| 单向不通 | 回程路径未配 QINQ | 双向抓包对比 | 回程设备同步配置 |
这张表是我这些年排障经验的浓缩,基本上 90% 的问题都能对上号。遇到问题先查表,比盲目抓包效率高得多。
4.2 外层 VLAN 冲突导致的间歇性断流
外层 VLAN 冲突这个坑我印象很深。当时是一个园区项目,三个接入点,每个接入点的外层 VLAN 都从 100 开始编。单独测试每个接入点都正常,三个一起上线就出问题,业务时通时断,毫无规律。
排查过程很曲折。先查配置,没发现问题;再抓包,发现有些帧的外层 Tag 是 100,但内层 Tag 不对,明显是串了。后来把三个接入点的外层 VLAN 台账拉出来一对,发现都用了 100、101、102,汇聚层一合并就冲突了。
解决办法是重新规划外层 VLAN,每个接入点分配独立的号段,接入点 A 用 100-199,接入点 B 用 200-299,接入点 C 用 300-399。改完立刻稳定。
这个教训是:外层 VLAN 必须有全局唯一性规划,不能各接入点各自为政。后来我养成了一个习惯,项目开始前先画一张外层 VLAN 分配表,所有接入点共用一张表,谁用哪个号段一目了然。
4.3 MTU 不匹配引发的诡异丢包
MTU 问题最迷惑人,因为现象是 ping 通但业务卡。当时客户反馈说视频会议卡顿,但 ping 网关正常。我上去先 ping 大包,ping -s 1500直接不通,ping -s 1400通。这就基本锁定是 MTU 问题。
查路径上设备 MTU,接入侧默认 1500,干道侧默认 1500,核心侧默认 1500。双层 Tag 帧是 1526 字节,超过 1500 就被丢。但为什么 ping 小包通?因为小包加两层 Tag 也没超 1500。
解决办法是把路径上所有设备的 MTU 调到 1508 以上。接入侧端口 MTU、干道侧端口 MTU、核心侧子接口 MTU,一个都不能漏。改完再 ping 大包就通了。
这里有个经验:QINQ 项目上线前,先用大包 ping 做一次端到端测试。命令很简单,ping -s 1472 -c 100,1472 是 1500 减去 ICMP 头和 IP 头的经典值,能通说明 MTU 没问题。这个测试花不了两分钟,但能省掉后面几小时的排障。
4.4 灵活 QINQ 映射表维护的坑
灵活 QINQ 的映射表是个双刃剑,灵活但难维护。我遇到过映射表配错导致业务串户的事故。当时是一个租户的内层 VLAN 20 应该映射到外层 2002,结果手滑配成了 2003,而 2003 是另一个租户的外层 VLAN。结果两个租户的流量混在一起,虽然没造成数据泄露,但业务互相干扰,排查了半天。
从那以后我定了个规矩:映射表变更必须双人复核,变更后立即抓包验证。抓包看外层 Tag 是否和预期一致,不一致立刻回滚。另外映射表要有版本管理,每次变更记录变更人、时间、原因,方便回溯。
还有一个细节:灵活 QINQ 的映射表在不同厂商设备上语法差异较大,有的用port vlan-mapping,有的用qinq mapping,有的用vlan mapping。跨厂商组网时一定要查清楚对接设备的语法,别想当然照搬。
4.5 排障必备的抓包与日志分析技巧
抓包是 QINQ 排障的终极武器,但抓包也有技巧。我一般会在三个位置抓:接入侧入口、干道侧出口、核心侧入口。三个位置对比,就能定位问题出在哪一段。
接入侧入口抓包,应该看到单层 Tag(客户原始 VLAN)。如果看到双层,说明客户侧设备自己打了外层,这不符合预期,要查客户侧配置。
干道侧出口抓包,应该看到双层 Tag(外层 S-VLAN + 内层 C-VLAN)。如果只看到单层,说明接入侧没打标或者干道侧剥了外层。如果看到双层但外层不对,说明映射表或默认 VLAN 配错。
核心侧入口抓包,应该和干道侧出口一致。如果不一致,说明中间有设备做了 Tag 操作,要逐跳排查。
日志方面,重点关注接口 up/down 日志、VLAN 创建删除日志、QINQ 状态变更日志。有些设备支持 QINQ 调试命令,比如debug qinq packet,但生产环境慎用,可能刷屏影响性能。我一般只在实验室环境开 debug,生产环境靠抓包和计数器。
计数器也是个好帮手。display qinq statistics能看到 QINQ 端口的收发计数,如果收到多但发出少,说明有丢包,结合 MTU 和 VLAN 允许列表排查。
5. 性能优化与规模化部署建议
5.1 外层 VLAN 号段规划的最佳实践
规模化部署 QINQ,外层 VLAN 规划是地基。我的建议是按接入点 + 租户两个维度来编。比如接入点 A 分配 1000-1999,接入点 B 分配 2000-2999,每个接入点内部再按租户细分。这样既保证了全局唯一,又方便定位——看到外层 VLAN 2001,就知道是接入点 B 的 1 号租户。
号段要留足余量。别把 1000-1999 用满,留 20% 给未来扩展。我见过有人把号段用满,后来加租户没号可用,只能重新规划,牵一发动全身。
另外建议把外层 VLAN 和内层 VLAN 的编号段完全分开。内层用 1-1000,外层用 2000 以上,这样抓包时一眼就能区分。如果内外层混在一起,排障时容易看错。
5.2 批量配置与自动化脚本思路
租户多了以后,手工敲命令效率低还容易错。我一般会写个脚本批量生成配置。以 Python 为例,读一个 CSV 文件,里面是端口、内层 VLAN、外层 VLAN 的对应关系,然后生成配置命令。
import csv with open('qinq_mapping.csv') as f: reader = csv.DictReader(f) for row in reader: port = row['port'] inner_vlan = row['inner_vlan'] outer_vlan = row['outer_vlan'] print(f"interface {port}") print(f" port link-type dot1q-tunnel") print(f" qinq enable") print(f" qinq vlan-translation enable") print(f" port vlan-mapping vlan {inner_vlan} map-vlan {outer_vlan}") print(f" quit")生成的命令复制到设备上批量执行,比手工敲快得多,也不容易错。CSV 文件本身就是台账,一举两得。
如果设备支持 NETCONF 或 RESTCONF,可以进一步做成自动化下发。不过中小项目用脚本生成命令就够了,没必要上重型工具。
5.3 监控指标与日常巡检要点
QINQ 上线后要监控几个关键指标:外层 VLAN 的流量计数、QINQ 端口的丢包计数、MTU 超限计数、MAC 地址表容量。
流量计数看趋势,突然掉零说明业务断了,突然飙升说明可能有环路或攻击。丢包计数持续增长说明有 MTU 问题或 VLAN 允许列表不全。MTU 超限计数直接指向 MTU 配置问题。MAC 地址表容量要留意,QINQ 环境下 MAC 地址学习在外层 VLAN 下,如果外层 VLAN 太多,MAC 表可能不够用。
日常巡检我一般每周做一次,重点看丢包计数和 MTU 超限计数。这两个指标只要不为零,就说明有问题,要查。流量趋势和 MAC 表容量每月看一次,做容量规划。
巡检命令:
display interface GigabitEthernet 0/0/1 | include input errors display qinq statistics interface GigabitEthernet 0/0/1 display mac-address count5.4 与 VXLAN 等新技术的对比取舍
现在 VXLAN 很火,很多人问 QINQ 是不是过时了。我的看法是:看场景。VXLAN 的优势是三层可达、租户数量几乎无限、支持跨数据中心。但 VXLAN 的复杂度也高,需要 Underlay 网络支持、需要 VTEP 设备、排障门槛高。
QINQ 的优势是简单、对硬件要求低、排障直观。中小规模园区、运营商接入网、租户数量在几千以内的场景,QINQ 完全够用,而且成本低得多。
我的取舍逻辑是:租户数量在 4000 以内、不需要跨三层、预算有限,选 QINQ。租户数量超过 4000、需要跨数据中心、有自动化运维需求,选 VXLAN。两者不是替代关系,是互补关系。有些场景甚至 QINQ 和 VXLAN 混用,接入侧 QINQ,核心侧 VXLAN,各取所长。
最后分享一个我在实际项目中的体会:QINQ 配置本身不难,难的是规划和排障。规划阶段多花一小时把外层 VLAN 台账、MTU、映射表理清楚,实施阶段能省十小时。排障阶段抓包比看配置快,三个位置抓包对比,基本能定位到段。还有,上线前一定用大包 ping 做端到端测试,这个习惯帮我省了无数次半夜排障。