1. 为什么今天还要聊MSTP
干了这么多年网络,每次带新人排查二层环路问题,最后绕来绕去都会绕回生成树这一套东西。很多人对STP、RSTP、MSTP的印象停留在“考试要背的协议”,真到了现网里,一看到端口状态在discarding和forwarding之间反复横跳,或者VLAN间流量走向莫名其妙,就抓瞎了。这篇东西就是想把MSTP这件事从头到尾捋清楚,顺带把STP、RSTP、MSTP三者之间的血缘关系和差异讲透,让你下次再遇到多VLAN环境下的链路规划,心里有底。
先把结论摆前面:MSTP(Multiple Spanning Tree Protocol,多生成树协议)不是凭空冒出来的新东西,它是STP和RSTP在“多VLAN负载分担”这个需求下自然演进的结果。STP解决了环路问题但收敛慢、拓扑单一;RSTP把收敛速度提上来了,但依然是整网一棵树,所有VLAN共用一条转发路径;MSTP在RSTP快速收敛的基础上,引入了“实例(Instance)”的概念,让不同VLAN可以走不同的树,从而实现负载分担和冗余并存。理解这条演进线,比死记每个协议的状态机有用得多。
这篇文章适合谁看?刚接触园区网、数据中心二层规划的运维和网络工程师,以及那些“配置会敲但不知道为什么这么敲”的朋友。我会从协议设计的底层逻辑讲起,把MSTP的域、实例、映射关系拆开,再给一套可以直接抄的配置思路和排错方法。全程用现网里真实会遇到的场景说话,不堆RFC原文。
2. 从STP到MSTP:一条被需求推着走的演进线
2.1 STP:一棵树打天下,够用但不够快
STP(802.1D)的核心逻辑很朴素:网络里不能有环,有环就广播风暴、MAC表震荡,所以选一个根桥,其他桥算出一条到根的最短路径,把多余的端口堵上,形成一棵无环的树。这套机制在单VLAN或者小规模网络里完全够用,我见过不少老园区到现在还跑着STP,只要拓扑不频繁变动,它老老实实不惹事。
但STP的毛病也很明显。收敛慢是第一个痛点,端口从阻塞到转发要经历blocking、listening、learning、forwarding几个状态,默认计时器下光listening和learning加起来就是30秒,加上拓扑变化后的老化,业务中断动辄几十秒。第二个痛点是拓扑单一,整网只有一棵树,所有VLAN的流量都挤在同一条链路上,另一条冗余链路只能干等着,带宽利用率上不去。第三个是端口角色和状态耦合,根端口、指定端口、阻塞端口和端口状态绑死,灵活性差。
我早年在一个双上行接入的场景里踩过坑:核心到接入有两条千兆链路,跑STP,结果所有流量全走主链路,备链路常年0流量,客户问“我买了两条链路为什么只用一条”,我只能解释这是STP的机制决定的。这个场景其实就是后来推动RSTP和MSTP落地的真实需求。
2.2 RSTP:把收敛速度拉起来,但树还是那棵树
RSTP(802.1w)最直观的改进是端口状态从5个精简到3个:discarding、learning、forwarding。原来的blocking、listening、disabled统一归到discarding,语义更清晰。更重要的是它引入了边缘端口(Edge Port)和提议/同意(Proposal/Agreement)机制,边缘端口接终端直接进转发不参与生成树计算,链路故障时通过P/A握手快速切换,收敛时间从几十秒压到秒级甚至亚秒级。
RSTP还增加了替代端口(Alternate Port)和备份端口(Backup Port)两种角色,替代端口是根端口的备份,根端口挂了替代端口能立刻顶上,不用重新算整棵树。这套机制在现网里非常实用,我一般会在所有接终端的端口上开边缘端口,再配合BPDU保护,既快又防环。
但RSTP有个没解决的问题:它依然是整网一棵树。所有VLAN共享同一套拓扑,负载分担还是做不到。你可以在不同链路上调cost让流量走不同路径,但那是全局的,没法做到“VLAN 10走左边、VLAN 20走右边”。这个缺口,就是MSTP要填的。
2.3 MSTP:一棵树变多棵树,VLAN终于能分道走
MSTP(802.1s)的核心创新是把VLAN映射到不同的生成树实例(Instance)上,每个实例独立计算拓扑,不同实例可以有不同的根桥和阻塞端口。这样一来,VLAN 10的流量可以走链路A,VLAN 20的流量走链路B,两条链路都利用起来,同时各自还有冗余。这就是所谓的负载分担。
MSTP还引入了域(Region)的概念。一个MST域是一组配置了相同域名、修订级别和VLAN-实例映射表的交换机集合。域内跑MSTP,域间通过CIST(Common and Internal Spanning Tree)互通,对外表现得像一棵普通的生成树。这个设计很巧妙,它让MSTP既能在大规模网络里分区管理,又能和跑STP/RSTP的设备兼容。
我个人的理解是,MSTP的本质是“用实例换灵活性”。你多花一点配置成本去规划实例和VLAN映射,换来的是链路利用率和故障隔离能力的提升。但这里有个前提:实例不是越多越好。现网里我见过有人给每个VLAN建一个实例,结果几十个实例把交换机CPU和内存吃满,BPDU泛洪严重。一般园区网规划2到4个实例足够,一个跑主流量,一个跑备流量,再留一个给管理VLAN或者特殊业务。
3. STP、RSTP、MSTP到底差在哪:一张表说清楚
光讲演进线还不够,实际选型和排错时你得能快速判断“这个网络跑的是什么、有什么限制”。下面这张表是我自己整理的核心差异对照,平时带人或者写方案直接拿来用。
| 对比维度 | STP(802.1D) | RSTP(802.1w) | MSTP(802.1s) |
|---|---|---|---|
| 拓扑数量 | 整网1棵 | 整网1棵 | 每实例1棵,多实例并行 |
| 端口状态 | 5个(blocking/listening/learning/forwarding/disabled) | 3个(discarding/learning/forwarding) | 3个,同RSTP |
| 端口角色 | 根端口、指定端口、阻塞端口 | 增加替代端口、备份端口、边缘端口 | 同RSTP,另加域边界相关角色 |
| 收敛速度 | 慢,默认30秒级 | 快,秒级/亚秒级 | 快,同RSTP |
| 负载分担 | 不支持 | 不支持(全局调cost) | 支持,按实例分流 |
| VLAN感知 | 不感知 | 不感知 | 感知,VLAN映射到实例 |
| 域的概念 | 无 | 无 | 有,域名+修订级别+映射表 |
| 兼容性 | 基础 | 兼容STP | 兼容STP/RSTP,域间走CIST |
| 典型场景 | 老旧小网络 | 单VLAN或简单双上行 | 多VLAN园区、需要负载分担的汇聚层 |
这张表里最容易被忽略的是兼容性那一行。MSTP设备在和跑STP/RSTP的设备对接时,会把对方所在的端口当作域外端口,通过CIST来互通。这意味着你可以在一个网络里混跑三种协议,但代价是跨协议边界的那部分收敛速度和负载分担能力会退化到对端协议的水平。我见过一个改造项目,核心换了支持MSTP的新设备,接入层还是老STP交换机,结果整网收敛被接入层拖慢,最后只能分批替换。所以规划时一定要把协议边界想清楚,别指望MSTP能拯救所有老设备。
4. MSTP核心概念拆解:域、实例、映射,一个都不能含糊
4.1 MST域:三要素必须完全一致
MST域(Region)是MSTP管理的基本单位。一台交换机属于哪个域,由三个参数共同决定:域名(Region Name)、修订级别(Revision Level)、VLAN到实例的映射表。这三个参数在域内所有设备上必须完全一致,否则设备会被划到不同的域,域间走CIST,你精心规划的负载分担就失效了。
这里有个现网高频坑:映射表的一致性。很多人配的时候只改了域名和修订级别,映射表用了默认的,结果两台设备映射表不一样,死活进不了同一个域。排查的时候用display stp region-configuration(不同厂商命令略有差异)看三要素,逐项比对。我的习惯是规划阶段就把三要素写进配置模板,部署时直接刷,不给人手改的机会。
注意:修订级别默认是0,很多项目里大家都不改,这本身没问题,但如果你网络里存在多个历史遗留的MST域,建议用修订级别做区分,避免误合并。
4.2 实例与CIST:内部实例和公共树的关系
MSTP里有两类树:CIST(Common and Internal Spanning Tree)和MSTI(Multiple Spanning Tree Instance)。CIST是整网的公共树,负责域间互通和与STP/RSTP的兼容;MSTI是域内每个实例独立的树,负责域内的负载分担。默认情况下,所有VLAN都映射到实例0,而实例0就是CIST,所以你不配任何映射时,MSTP退化成类似RSTP的行为。
规划实例时,我一般遵循“业务分离、数量克制”的原则。比如一个典型园区:VLAN 10-19映射到实例1走主链路,VLAN 20-29映射到实例2走备链路,管理VLAN单独映射到实例3或者留在实例0。这样主备链路都承载流量,任意一条断了另一条能接管,同时管理流量和业务流量在拓扑上隔离,排错时不容易互相干扰。
实例数量为什么克制?因为每个实例都要独立跑一套生成树计算,BPDU要带实例信息,交换机要为每个实例维护端口状态。实例多了,CPU和内存开销线性上升,BPDU报文也变大。我实测过,接入层交换机跑超过8个实例,CPU会有明显抬升,几十个实例基本就是给自己找麻烦。2到4个实例覆盖绝大多数场景,再多就得掂量一下设备性能。
4.3 端口角色与状态:MSTP沿用了RSTP的框架
MSTP的端口角色和状态基本继承RSTP,但多了域边界端口的概念。根端口、指定端口、替代端口、备份端口、边缘端口这些角色在MSTP里含义不变,区别在于每个实例独立计算角色。同一个物理端口,在实例1里可能是根端口,在实例2里可能是替代端口(阻塞),这就是负载分担的物理基础。
端口状态还是discarding、learning、forwarding三个。discarding不转发也不学MAC,learning学MAC但不转发,forwarding正常转发。排错时看端口在哪个实例下处于什么状态,比看全局状态有用得多。我习惯用display stp instance X interface这类命令逐个实例看,能快速定位是哪个实例的拓扑出了问题。
5. 实操:一套可复现的MSTP规划与配置流程
5.1 规划阶段:先画图再敲命令
配置之前必须先把规划做扎实,否则后面改起来很痛苦。我的流程是三步:定拓扑、定实例、定映射。
定拓扑就是画出物理连接和冗余关系,标出哪些链路是主用、哪些是备用、哪些需要负载分担。定实例是根据业务VLAN分组,把需要走同一路径的VLAN归到一个实例。定映射就是写出VLAN和实例的对应表,同时确定每台设备在各实例下的根桥优先级。
根桥规划有个经验:每个实例的主根和备根要分开。比如实例1的主根放在核心A、备根放核心B,实例2反过来,主根核心B、备根核心A。这样两个实例的流量走不同核心,核心间链路也能被利用起来。优先级用4096的倍数,主根设4096,备根设8192,其他设备默认32768,层次清晰。
5.2 配置模板:以两台核心加两台接入为例
下面给一套通用配置思路,命令用伪代码风格表示,不同厂商语法有差异但逻辑一致。假设域名REGION-CORE,修订级别1,实例1映射VLAN 10-19,实例2映射VLAN 20-29。
核心A的配置逻辑:
# 进入MST域配置 stp region-configuration region-name REGION-CORE revision-level 1 instance 1 vlan 10 to 19 instance 2 vlan 20 to 29 active region-configuration # 实例1主根,实例2备根 stp instance 1 priority 4096 stp instance 2 priority 8192 # 全局开启MSTP stp mode mstp stp enable核心B对称配置,实例1备根(8192),实例2主根(4096)。接入交换机只需要配好域三要素和映射表,优先级保持默认,让它自动选根。接入层到核心的双上行链路,通过实例不同自然形成一主一备的转发路径。
配置完必须验证三件事:域是否一致、实例根桥是否符合预期、各实例端口状态是否正确。域一致性用域配置查看命令比对三要素;根桥用display stp instance X看根桥ID是不是你规划的那台;端口状态看每个上行端口在各实例下是forwarding还是discarding,符合“实例1走A链路、实例2走B链路”就对了。
5.3 参数选择:优先级、cost、计时器怎么定
优先级前面说了,4096的倍数,主备拉开差距。cost的话,MSTP默认按端口带宽算,千兆是20000、百兆是200000(不同厂商基数可能不同),一般不需要手动改,除非你有特殊的路径偏好。真要手动调,记住cost越小越优先,调之前先确认默认值,别拍脑袋填个1把路径搞乱。
计时器方面,MSTP沿用了RSTP的快速收敛机制,Hello时间默认2秒,Forward Delay默认15秒,Max Age默认20秒。绝大多数场景不要动这些值,动了容易引发全网震荡。只有在超大规模或者特殊链路质量下才考虑微调,而且必须全网一致。我见过有人为了“加快收敛”把Hello改成1秒,结果BPDU泛洪翻倍,CPU告警,得不偿失。
6. 排错实录:MSTP现网高频问题与排查思路
6.1 域不一致导致负载分担失效
这是最常见的坑。现象是:规划了两个实例走不同链路,结果所有流量还是走同一条,另一条链路闲置。排查第一步就是看域三要素。两台设备域名、修订级别、映射表只要有一项不同,就分属不同域,域间走CIST,实例规划全部作废。
排查命令思路:分别在各设备上查看域配置,逐项比对。映射表最容易出问题,因为它是多行配置,手敲容易漏或者顺序不一致(有些厂商对映射表顺序敏感)。解决办法是用配置模板统一刷,刷完再比对一遍。我现在的习惯是部署前把三要素和映射表做成一个配置片段,所有设备引用同一片段,从源头杜绝不一致。
6.2 实例根桥不是规划的那台
现象是某个实例的流量走向和规划相反。原因通常是优先级没配、配错设备、或者有设备优先级配得更低抢了根。排查用查看根桥的命令,看当前根桥ID和预期是否一致。如果发现是某台接入交换机成了根,多半是它的优先级被误配成了0或者4096。
这里有个细节:根桥优先级是per实例的,你配实例1的优先级不影响实例2。所以配置时要逐个实例确认。另外,有些厂商的默认优先级是32768,有些是32768但支持扩展系统ID,看命令输出时注意区分。
6.3 边缘端口没开导致终端接入慢
终端插上交换机,等好几秒才能上网,多半是端口没配边缘端口,走了生成树的状态迁移。边缘端口接终端不参与生成树计算,直接进forwarding。配置上把接终端的端口统一设为边缘端口,同时开BPDU保护,防止有人私接交换机导致环路。
注意:边缘端口一定要配合BPDU保护。只开边缘端口不开保护,一旦端口收到BPDU,边缘端口会失效并重新参与生成树,可能引发震荡。开了BPDU保护,收到BPDU直接把端口down掉,干净利落。
6.4 常见问题速查表
| 现象 | 可能原因 | 排查动作 | 处理方式 |
|---|---|---|---|
| 负载分担不生效 | 域三要素不一致 | 比对域名、修订级别、映射表 | 统一配置模板重新下发 |
| 流量走向与规划相反 | 实例根桥优先级配错或被抢占 | 查看各实例根桥ID | 修正优先级,确认无更低优先级设备 |
| 终端接入慢 | 端口未设边缘端口 | 查看端口角色 | 设为边缘端口并开BPDU保护 |
| 收敛慢、拓扑震荡 | 计时器被改动或链路质量差 | 检查Hello/Forward Delay/Max Age | 恢复默认值,全网一致 |
| 实例多导致CPU高 | 实例规划过多 | 查看CPU和实例数量 | 精简实例到2-4个 |
| 与老设备对接后变慢 | 跨协议边界退化 | 确认对端跑的协议 | 规划协议边界,分批替换或接受退化 |
7. 我踩过的坑和几条实在建议
先说一个印象最深的。早年做一个多楼层园区的改造,汇聚层双上行到核心,规划了两个实例做负载分担。配置刷完测试都正常,结果上线一周后客户报“部分楼层网速慢”。上去一看,其中一台汇聚交换机的映射表里少配了一个VLAN段,导致那部分VLAN落到了实例0,走了CIST,和规划的路径完全相反,流量绕了一大圈。问题就出在手敲映射表时漏了一行。从那以后,我所有MSTP项目都用配置模板,映射表只写一次,复制下发,下发完用脚本比对每台设备的域配置,确认完全一致才继续。
第二条建议:实例规划要跟着业务走,不要跟着VLAN编号走。很多人习惯按VLAN 10、20、30这样顺序分实例,但业务上可能VLAN 10和VLAN 30是一类流量、VLAN 20是另一类。按业务分组,后续扩容和调整时逻辑清晰,排错时也容易判断“这个实例出问题影响哪些业务”。
第三条:改MSTP配置尽量在窗口期做,并且准备好回滚。MSTP的域配置变更(尤其是映射表)会触发全网重新计算,虽然RSTP/MSTP收敛快,但大规模网络里仍然可能有短暂中断。变更前备份配置,变更后逐台验证,别一次性全推。
最后分享一个排查小技巧:当你不确定某台设备在某个实例下走哪条路时,直接看该实例下各端口的角色和状态,根端口方向就是流量出口,替代端口就是备用方向。比看全局拓扑图快得多,尤其是在实例多、拓扑复杂的时候。这个内容后续还可以往MSTP和堆叠、链路聚合的配合上扩展,那是另一个话题了,先把单域的这套逻辑吃透,现网里八成的问题都能自己搞定。