1. 从一条闲置的上行链路说起:MSTP到底解决了什么
前阵子帮某单位做核心网络改造,拓扑并不复杂,两台核心交换机做双机互备,十几台接入交换机全部双上联到核心。业务也简单,办公网和视频监控网都在二层跑。结果改造过程中撞上一个非常典型的问题——只要开了STP,两条上行链路里总有一条被阻塞。办公和监控的流量全部挤在一条链路上,另一条上千兆的链路平时完全空着,只有故障切换时才派上用场。后来我把方案切到MSTP上,把VLAN按业务拆成不同实例,让两台核心在不同实例里分别扮演根桥,两条链路同时进入转发状态,链路利用率直接翻倍,冗余能力一点没丢。
这篇文章就围绕MSTP展开,聊聊它为什么会出现、核心机理是什么、实际部署时怎么规划和配置,以及这几年运维中遇到的各种坑。适合正在做园区网、局域网二层改造的运维人员,也适合准备数通认证、想真正理解生成树协议而不只是背命令的朋友。
1.1 二层环路:冗余链路的"原罪"
先说清楚为什么生成树这一类协议会存在。
二层交换机的基本转发行为是:收到广播帧、组播帧或者未知单播帧时,除了接收端口之外的所有端口都转发一份。如果物理拓扑里存在环路,一个广播帧会被无休止地复制、循环,几秒钟就能把交换机的CPU打满,MAC地址表也会因为同一台终端的MAC从不同端口到达而反复震荡,终端直接断网。这不是理论推演,任何人拿两台交换机接成环试一下就明白了,广播风暴起来之后,连管理地址都ping不通。
但网络设计又偏偏需要冗余。核心到接入、接入到终端,总得留一条备用路径,万一主路径光纤被挖断、光模块老化,业务不能断。于是问题就变成:既要保留冗余链路,又要让数据在正常状态下只沿一条逻辑路径走,环路出现时能自动切断备用路径,主路径失效时能快速恢复。
STP(生成树协议)解决的就是这件事。它通过在所有交换机上选举一台根桥,然后通过BPDU报文交换路径信息,计算出每台设备到达根桥的最短路径;最短路径对应的端口进入转发状态,其它构成环路的端口被阻塞。逻辑拓扑就从物理环变成了一棵无环的树。
1.2 STP和RSTP的共同短板:全网只有一棵树
STP能破环,RSTP能让收敛速度从几十秒降到秒级,但它们有一个共同的结构性问题:全网不管有多少个VLAN,最终只生成一棵生成树。
这是什么概念呢。一台接入交换机上有办公VLAN 10、监控VLAN 20,双上联到核心A和核心B。STP计算完之后,假设根桥是核心A,那么接入交换机面向A的端口是根端口,面向B的端口大概率成为Alternate(备用)端口被阻塞。结果就是:VLAN 10和VLAN 20的数据帧都只能走A方向,B方向完全空闲。即便核心B上接了很多服务器,接入层也只能望而兴叹,流量就是绕不过去。
有人会问,多配几个VLAN不就行了吗?没用,STP和RSTP的生成树实例只有一个,所有VLAN共用同一棵树的转发路径,所谓按VLAN分流根本做不到。在某些厂商早期的私有方案里,确实出现过"每个VLAN一棵树"的做法,用流量控制灵活,可一旦VLAN数量上百,生成树实例数量直接失控,CPU和带宽消耗都非常难看,跨厂商互通更是灾难。
这就是MSTP登场的原因。它既要保留RSTP的快速收敛能力,又要解决"多个VLAN共用一条路径导致带宽浪费"的问题,还得控制生成树实例的数量,不能为每个VLAN都算一棵树。
1.3 MSTP的答案:实例、域与多棵树
MSTP的核心思想可以概括成一句话:把一组VLAN捆绑成一个"实例",每个实例独立计算一棵生成树,不同实例可以有完全不同的根桥和转发路径。
举例来说,规划两个实例:实例1绑VLAN 10、20,实例2绑VLAN 30、40。让核心A在实例1中是根桥,核心B在实例2中是根桥。这样接入交换机在实例1中的根端口指向A,在实例2中的根端口指向B。办公流量正常沿A方向走,监控流量正常沿B方向走,两条上行链路同时满负荷工作;万一A宕机,实例1重新选举根桥为B,网络自动收敛,冗余能力依然保留。
这就是MSTP最核心的价值:不是简单"多跑几棵生成树",而是用受控数量的实例,把原本闲置的冗余链路变成可用的转发路径,实现真正意义上的负载均衡。理解了这一点,后面所有机制——MST域、配置标识、CIST、域根——都是在为这个目标服务。
2. MSTP的三个关键机制:域、配置标识与生成树类型
MSTP不是简单地把一个网络切成多个实例就完事。实际部署时,交换机数量可能几十上百台,如果每台交换机都维护全网所有实例的完整信息,协议的开销和调试复杂度会失控。所以协议引入了"域"的概念,把具备相同配置的交换机组装成一个逻辑整体,域内跑多棵实例树,域间只跑一棵公共树,把问题分而治之。
2.1 MST Region三要素:为什么缺一不可
MST域(MST Region)是MSTP中最重要的逻辑边界,由三要素唯一确定:
- 域名,Region Name,相当于这个域的标识名称;
- 配置修订级别,Revision Level,用于区分同一域名下的不同配置版本;
- VLAN与实例的映射关系表,也就是哪些VLAN被划进了哪个实例。
三个要素完全一致的交换机,才会被识别为同一个MST域,它们之间交换完整的多实例BPDU信息。只要有一个要素不一致,设备就会认为对方属于另一个域,双方只能通过域间的公共生成树相连。
举个例子,核心A上配置域名REGION-A,修订级别1,VLAN 10映射到实例1;接入交换机B上配置域名REGION-A,修订级别2,VLAN 10同样映射到实例1。按三要素比对,两者修订级别不同,在协议眼里就是两个不同的域。这种"不一致"在运维中极其常见,而且故障现象往往非常隐蔽——VLAN 10的转发路径可能仍然通,但不符合预期,因为你以为它们在同一棵实例树里,实际却走了域间公共树。
注意:绝大多数MSTP的配置界面里,只要修改了VLAN映射关系,系统就会提示修改修订级别。如果你手动把版本号改回去,或者某些设备同步配置时漏改了这一项,就会出现"配置看起来一样,实际域划分不一样"的坑。排查时务必三要素逐个比对。
2.2 实例、CIST、IST和MSTI的关系
MSTP协议里涉及的生成树类型名词比较多,CIST、IST、CST、MSTI,很多人一开始容易绕晕。我习惯用"范围"来区分它们。
CIST是公共和内部生成树,它是整个交换网络总的一棵生成树,全网无论分成多少个域,最终在逻辑上都要归到CIST这个唯一的总树上。CIST的根桥,也就是全网总根,是唯一的。CIST由两部分拼接而成:一部分是各MST域内部的IST,另一部分是连接各域之间的CST。
IST是实例0,也叫内部生成树。每个MST域内部,实例0天然存在,它负责承载域内那些没有显式映射到其它实例的VLAN,同时承载域内的管理通信。IST把域内的所有设备连接成一个整体,让每个域在CIST中表现为一个"节点"。
CST是域间生成树,负责连接各个MST域以及传统STP/RSTP设备。CST运行在各域之外,只关心域与域的连接关系,不关心域内部的具体拓扑。
MSTI是实例1到实例N,也就是用户定义的其它生成树实例。每个MSTI在域内独立计算、独立选举根桥。同一台交换机在不同MSTI中可以扮演完全不同的角色,既可以是实例1的根桥,也可以是实例2的普通桥。
为了更好地对照,我用表格整理了一下:
| 生成树类型 | 范围 | 作用 |
|---|---|---|
| CIST | 全网 | 总生成树,由IST和CST拼接,根桥全网唯一 |
| IST | 单个MST域内部 | 实例0,承载未映射的VLAN和管理帧 |
| CST | 各MST域之间 | 连接域与域、以及连接外部传统生成树设备 |
| MSTI | 单个MST域内部 | 用户自定义实例,承载映射的VLAN,独立计算路径 |
2.3 BPDU里的配置标识如何决定设备归属
MSTP的BPDU(桥协议数据单元)是在RSTP BPDU基础上扩展的,里面除了常规的根桥ID、路径开销、端口ID,还携带一段MST配置标识,内容就是前面说的三要素。
当一台交换机收到MST BPDU时,首先不是急着比较路径开销,而是先解析配置标识,和自身配置做比对。一致,则把发送方归入同一个域,按MSTI信息参与计算;不一致,则把发送方视为外部区域,走CST处理逻辑。这个"先认亲、再算账"的设计,保证了不同配置的交换机之间不会互相污染实例信息,也大大减少了BPDU的体积。
理解了BPDU中的配置标识,再看常见的"域分裂"故障就容易了——不是协议出bug,而是设备之间对"自己属于哪个域"的判断对不上。配置修订级别、域名、映射表,任何一个变体,都会让原本的域在逻辑上一分为二。
3. 生成树计算到底在算什么:总根、域根与端口角色
MSTP的配置不难,难的是出问题时能根据现象反推计算过程。这一节我把MSTP的计算逻辑拆开讲,重点把总根选举、域根选举、端口角色这三个关键概念理清楚。
3.1 CIST总根的选举规则
CIST总根是全网的"顶配"设备,它的选举规则和STP/RSTP完全一致,比较的是桥ID:优先级数值小者优先,优先级相同则MAC地址小者优先。
每台设备初始时都认为自己是总根,然后通过BPDU向邻居宣告自己的根桥ID、路径开销等信息。收到BPDU后,设备会比较收到的"根桥ID"与自己当前记录的根桥ID,保留更优的那个,同时计算出自己到达总根的最短路径开销,并继续向下游转发。这个过程会在全网泛洪,直到所有设备就总根达成一致。
默认情况下,所有交换机的STP优先级都是32768。如果核心A的MAC比核心B小,A就会成为CIST总根。注意,CIST总根并不一定是物理位置最核心的设备,它只是优先级和MAC地址综合比较的结果。这也是很多网络的隐患所在——某台接入层交换机可能因为MAC地址更小、优先级配置不当,意外成为全网总根,导致所有流量路径全部绕道,核心之间的直连链路反而被阻塞。
3.2 域根与Master端口
CIST总根选举出来之后,每个MST域内部会进一步选举出本域的域根(Regional Root)。域根的定义是:域内距离CIST总根路径开销最小的那台交换机。在同一个MST域里,域根可能有多台设备并列(路径开销相同时),但最终只会选出一台作为域根。
域根是整个域在CIST中的"代言人"。域内的IST计算,是以域根为根来展开的;域内所有设备通过IST共同协作。而域间CST在连接这个域时,看到的"域"的出口就是Master端口——域边界上通往CST方向、路径开销最优的那个端口,它类似整个域面向CIST总根的"根端口"。
在MSTP里,Master端口是必须能正确识别的。如果一台边界交换机有两个以上端口连接外部域,Master端口选出后,其它候选端口会进入Alternate状态等待替换。很多跨域流量走弯路的问题,都是Master端口位置不符合预期导致的。
3.3 端口角色和状态的完整对应
MSTP的端口角色比STP/RSTP多,但逻辑并不复杂。我用表格把角色和典型出现位置列出来:
| 端口角色 | 出现位置 | 作用 |
|---|---|---|
| 根端口 | 非根桥设备上 | 本设备到达域根/CIST总根的最优路径端口 |
| 指定端口 | 每条链路的指定侧 | 负责把桥信息转发到下游网段,根桥上的端口通常都是指定端口 |
| Alternate端口 | 非根桥设备上 | 根端口的备份,主根端口失效时可快速接管 |
| Backup端口 | 某条链路或网段上 | 指定端口的备份,提供冗余但平时阻塞 |
| Master端口 | 域边界设备上 | 域通往CST方向的出口,相当于域在CIST中的根端口 |
| 域边界端口 | 域边界设备上 | 连接其它MST域或传统STP/RSTP区域的端口 |
端口状态则相对简化:Forwarding(转发数据帧)、Learning(学习MAC但暂不转发)、Discarding(不转发也不学习)。需要特别说明的是,Alternate、Backup、Master这些角色都对应Discarding状态,逻辑上阻塞但不影响它们作为备份端口在故障发生时快速切换。
3.4 用实例做负载均衡的底层原理
现在把前面所有的机制串起来,看看负载均衡到底是怎么实现的。
假设有两台核心A和B,接入交换机C双上联。规划实例1承载办公VLAN,实例2承载监控VLAN。我们在A上把实例1的桥优先级设为0,实例2的桥优先级设为4096;在B上反过来,实例1设4096,实例2设0。
这样,CIST总根可能仍然是A,但实例1的根桥是A,实例2的根桥是B。在实例1的生成树计算中,C面向A的端口路径开销更优,成为根端口,面向B的端口成为Alternate,所以办公流量走A;在实例2的计算中,C面向B的端口成为根端口,面向A的端口成为Alternate,所以监控流量走B。两条上行链路同时转发,互不抢道。
注意,实例1和实例2各自独立选举根桥,所以完全可以把根桥分散到两台核心上。这是MSTP负载均衡的精髓——实例划分只是手段,把根桥位置错开才是真正的目的。
4. 从规划到落地:MSTP部署配置与验证
理解了原理,配置就只是把这些逻辑落实到命令里。但实际部署时,很多细节比命令本身更重要,比如实例怎么划分、优先级怎么设、配置完怎么验证。我按实施顺序往下说。
4.1 实例规划的基本原则
实例规划是整个MSTP部署的起点,规划得好,后面几乎没麻烦;规划得随意,后面全是"这里绕路、那里不通"的疑难杂症。
第一,实例0不要承载业务VLAN。实例0是CIST的一部分,负责管理通信和域间互通,让它保持轻量,能减少不必要的拓扑变化。很多生产网把管理VLAN留在实例0里,业务VLAN全部显式映射到其它实例,这是一个好习惯。
第二,按"业务组+转发方向"来分实例。一个实例里的VLAN应该有相近的"流量路径需求"。办公终端数量多、流量零散,适合放一个实例;视频监控流量大、方向集中,适合放另一个实例;服务器和存储对接核心防火墙,可能又是独立的路径。把路径需求相近的VLAN绑在一起,根桥选择才有实际效果。
第三,实例数量要克制。MSTP的价值在于用少量实例实现分流,而不是建几十个实例。二三层网络规划里,3到6个实例足够覆盖绝大多数园区网需求。实例过多,优先级配置、故障排查的复杂度都会成倍上升。
第四,核心设备上要预留故障切换通道。假设实例1根桥在A、实例2根桥在B,如果A宕机,实例1要能快速把根桥切换给B,所以B在实例1里不能只是普通优先级,通常应该设置为次优(比如priority 4096),保证切换路径是设计过的,而不是临时随机选举出来的。
4.2 核心配置命令逐条拆解
我把配置过程按步骤铺开,假设网络里有四台核心设备,两台核心交换机和两台接入交换机,域名统一,实例划分一致。
第一步:全局启用MSTP。如果设备默认运行STP或RSTP,需要切换到MSTP模式:
stp mode mstp第二步:创建MST域配置,配置域名、修订级别和实例映射。以某类企业级交换机的通用命令行风格为例:
stp region-configuration region-name CORE-MIST revision-level 1 instance 1 vlan 10 20 30 instance 2 vlan 40 50 60 active region-configuration注意最后的active region-configuration,这个动作必须执行,配置才会真正生效并参与BPDU交换。很多"配了没反应"的问题,都是忘了激活。
第三步:在核心A上设置实例优先级,让它成为实例1的根桥、实例2的次优根桥:
stp instance 1 priority 0 stp instance 2 priority 4096第四步:在核心B上做相反的设置:
stp instance 1 priority 4096 stp instance 2 priority 0这样实例1的主根桥是A,备份是B;实例2的主根桥是B,备份是A。接入交换机不需要额外配置实例优先级,保持默认32768即可,它们只需要计算路径、选出根端口。
4.3 配置后的验证方法和判断标准
命令配置完,只完成了30%的工作,剩下的70%是验证。我每次实施MSTP,至少会做三件事。
第一,确认全网MST域配置一致性。逐台设备执行:
display stp region-configuration检查域名、修订级别、实例映射三要素,确保每台设备输出完全一致。这一步能排除绝大多数域分裂隐患。
第二,查看实例根桥和端口角色。在核心A上执行:
display stp instance 1 root可以确认实例1的根桥是不是自己,实例2的根桥是不是B。再执行:
display stp instance 1 brief查看接入交换机在实例1中的端口角色,确认面向A的端口是根端口(ROOT)、面向B的端口是Alternate(ALT)。然后在核心B上对实例2做同样的检查。
第三,做一次实际流量验证。最简单的办法是在不同VLAN的终端之间互ping,然后在核心交换机的上联口看流量计数;更严谨的做法是拔掉一条链路看收敛速度和路径切换是否符合预期。上联口有没有流量,实例划分有没有真正生效,一查便知。
4.4 多域场景下的边界问题
如果网络规模较大,比如总部和分公司通过二层专线互联,可能需要在不同站点配置不同的MST域。每个域拥有域名和映射表,域间通过CST连接,跨域VLAN流量只能沿CIST路径走,无法享受域内的多实例分流。
这时要留意两个问题。一是域边界的Master端口位置,它决定了跨域流量从哪个出口走,配置前要明确规划;二是不要为了让多个站点看起来"像一个域"而强行统一域名和映射表。如果VLAN规划不一致,强统反而会引发配置标识紊乱,不如划分成多个域,让CST去完成域间桥接。
5. 运维中常见的MSTP故障:现象、原因与排查链路
协议本身设计得再严谨,配置层面的疏漏也总会出现。这几年处理过的MSTP故障不算少,问题表象五花八门,根因却高度集中,基本都是配置一致性、根桥位置、端口角色这三类。我把典型场景梳理出来,每个都能对应到实际排障过程。
5.1 VLAN映射不一致导致的域分裂
故障现象:某台接入交换机下挂的终端,通过VLAN 10访问服务器时延迟忽高忽低,拓扑偶尔出现环路告警,抓包发现这台交换机和其它设备之间的BPDU频繁被丢弃。
排查链路:先查接入交换机与核心交换机的MST域配置。display stp region-configuration显示:接入交换机把VLAN 10绑定到了实例2,而核心交换机把VLAN 10绑定在实例1。三要素中的映射表不一致,接入交换机和核心交换机被判定为两个不同的MST域,域间CST重新计算,路径变化导致转发震荡。
处理方法:统一所有设备的VLAN映射。如果这是一台新上线设备,直接改配置;如果是批量割接,建议先在图上标好每台设备的映射关系,再逐台修改并执行active region-configuration。改完后必须重新检查display stp region-configuration,确认每一台的输出一致。
5.2 修订级别改完忘同步
故障现象:某次给核心交换机增加新VLAN映射后,网络突然出现间歇性丢包,紧接着接入层的端口角色大面积变化。
排查链路:查看核心交换机的修订级别为2,另一台核心还是1。实际上,改动映射表后,配置变更会自动触发修订级别变化,但部分接入交换机没有得到新配置,还在用旧的修订级别。域里一半设备认为是"新配置域",一半设备认为是"旧配置域",整个域被拆成两半,CIST重新收敛,丢包随之而来。
处理方法:在所有相关设备上统一修订级别。我习惯把修订级别当作配置版本号看待:每次修改实例映射,就主动把revision-level加1,并统一同步到整个域。不要把修订级别当成一个随意填的数字,它在协议里承担着"域身份校验"的责任。
5.3 根桥位置不对造成次优路径
故障现象:核心A和B各有业务流量,但A上联口的转发量远大于B,即使B侧链路明明带宽更大。接入交换机的两条上行链路里,有一条始终没有流量。
排查链路:display stp instance 1 root发现实例1的根桥既不是A也不是B,而是一台接入交换机。原因是这台接入交换机曾经是哪台设备的优先级被误设为4096,加上MAC地址较小,在实例1中意外成为根桥。它这个"根桥"让核心A不得不通过接入交换机中转才能连接到核心B,核心间的直连链路被阻塞,流量路径全部绕远,实际转发效率大打折扣。
处理方法:把根桥优先级重新规划。在同一厂商设备上,设置核心A优先级为0、核心B为4096;核心设备务必压到最低,避免接入层设备抢到根桥。设置完成后再看display stp instance 1 root,确认根桥在预期位置。
根桥位置直接决定全网转发路径。优先级配置不是"随便给核心设个小的就完事",而是要具体到每个实例都明确主根、备份根,并且让接入层优先级保持在默认值以上,不做特殊调整。
5.4 与其它设备对接时的兼容问题
MSTP是标准协议,但不是所有老旧设备都支持完整MSTP特性。和仅支持STP/RSTP的设备对接时,MSTP端口会自动回退到RSTP或STP模式运行,这种兼容行为本身是安全的,但会导致边界端口的角色和预期不一致,进而让某些VLAN的路径不同于域内设计。
处理这类问题,首先要明确定位设备支持的能力,再决定是否在边界端口上做协议模式约束。接入层设备如果长期不更换,而且本身不感知VLAN,可以考虑把核心到它的链路配置成trunk时,端口接入模式显式指定为RSTP,让MSTP域内的复杂实例不延伸到这台设备上。实测下来,这种方式比强行让老旧设备跑MSTP稳定得多,也让后续排障范围更可控。
6. 关于MSTP运维,我沉淀下来的几个习惯
文章最后,说几个纯粹来自实战的习惯,也许可以帮读者少走弯路。
第一个习惯是"改配置前先拍照"。修改MSTP配置之前,我会先执行一遍display stp region-configuration和display stp instance all brief,把当前状态留下来。一旦改动后网络异常,可以直接和改动前对照,快速定位是哪台设备的哪些参数变了。
第二个习惯是"统一变更,全量执行"。MSTP是全局性的协议,配置必须全网一致。如果只改一台设备,剩下的设备会立刻在协议层面感知到"域身份变化"。每次割接时,我会把所有涉及MSTP的设备分组,逐组把域名、修订级别、映射表全部对齐,再逐台激活。永远不要贪快,只在一两台设备上改动就跑去测业务。
第三个习惯是"让实例0保持干净"。实例0承载CIST和三要素校验,是MSTP所有计算的基础。无论业务怎样扩展,我都不会把业务VLAN塞进实例0,也不会让实例0承载过多管理和监控流量。这样CIST收敛快,域间故障排查也简单。
第四个习惯是"把备份路径当主路径一样验证"。配置MSTP负载均衡后,我会主动拔掉核心A的上联,观察实例1的根桥是否快速切换到B,业务是否恢复。备份路径如果不经过实际演练,等到真正出故障时,可能发现交换机之间的链路聚合、优先级限制等细节并没有按预期生效。
MSTP这个协议,表面看是一组配置命令,实际运维中检验的是对"域、实例、根桥、端口角色"这一整套逻辑的理解。把原理吃透,再回头处理那些看起来极度复杂的网络故障,会发现大部分问题其实都出在配置一致性和根桥位置这两个点上。希望这篇梳理,能让正在研究MSTP的朋友少走我之前走过的弯路。