接口没配 BPDU 保护,端口为什么还是被关了?

· 11 分钟阅读

一句话结论:核心交换机全局开启了 spanning-tree portfast bpduguard default,而面向下联交换机的 trunk 口在缺省开启的边缘端口自动识别(autoedge)中被判成了”边缘口”;一次约 3 秒的物理瞬断让下联交换机短暂成为根桥,链路恢复后它发出的第一个 BPDU 正好落在核心 3 秒判定窗口之后,端口被 BPDU Guard 直接 error-disabled

不是环路,是**“面向交换机的口被当成了接终端的口”**

维度信息
设备锐捷 RG-S7800C(核心)× 2,H3C S5130S(接入)
关键配置spanning-tree portfast bpduguard default + autoedge 缺省开启
触发条件互联链路约 3 秒物理瞬断
结局Gi2/6 error-disabled,下联失联,需人工恢复
性质定时炸弹,不是偶然事件

一、故障现象

某日 13:10,二级分行核心 0A(CORE-0A,锐捷 S7800C) 与下联接入交换机 SW-23(H3C S5130S) 的互联链路 Gi2/6 ⇄ Gi1/0/48 发生瞬断;链路恢复后,核心把 Gi2/6 置为 error-disabled,下联交换机上联中断、管理 VLAN 399 失联,核心产生 BPDU Guard 告警

现场第一反应是”这个口是不是配了 BPDU 保护”——结果翻接口配置,什么都没有:

interface GigabitEthernet 2/6
 description To_ACCESS_SW23
 switchport mode trunk
 switchport trunk allowed vlan only <业务 VLAN、管理 VLAN 399、预留段>

没有 spanning-tree portfast,没有 spanning-tree bpduguard enable,没有 bpdufilter。看起来”什么都没配”,但端口就是被关了

文中设备名、接口描述与地址已做脱敏,VLAN 列表做了简化,不影响结论

二、拓扑与关键参数

graph TB
    subgraph CORE["核心层"]
        A["CORE-0A · RG-S7800C · RGOS 11.0(4)<br/>STP 根桥 · priority 0<br/>全局 portfast bpduguard default"]
        B["CORE-0B · RG-S7800C<br/>priority 4096<br/>同样开启全局 BPDU Guard"]
        A ---|"AggregatePort 1(同一隐患)"| B
    end

    A ==>|"Gi2/6 · trunk<br/>无 portfast、无 bpdufilter"| S["SW-23 · H3C S5130S-54S-HI-G<br/>Comware 7.1.070 · priority 8192<br/>stp bpdu-protection"]

    S -->|"GE1/0/36 · VLAN 401"| T1["接入口"]
    S -->|"GE1/0/40 · VLAN 440"| T2["接入口"]
    S -->|"GE1/0/45 · VLAN 460"| T3["接入口"]
    S -.->|"XGE 1/0/53-54 · shutdown"| X["备线(未启用)"]
设备型号 / 版本STP 角色关键配置
核心 0A锐捷 RG-S7800C,RGOS 11.0(4)根桥,priority 0spanning-tree portfast bpduguard default
核心 0B锐捷 RG-S7800C非根,priority 4096同样开启全局 BPDU Guard
接入 SW-23H3C S5130S-54S-HI-G,Comware 7.1.070非根,priority 8192stp global enable、stp bpdu-protection、接入口 stp edged-port

互联链路为 trunk,双方放通 VLAN 399/401/410/440/460/999;SW-23 的 Gi1/0/48 没有配 stp edged-port,它本身不是边缘口

三、现场证据

3.1 核心侧:全局开了保护,接口上却看不到

spanning-tree portfast bpduguard default   ← 全局 BPDU 保护
spanning-tree mst 0 priority 0             ← 0A 是根桥
spanning-tree

核心没有配置 spanning-tree portfast default,Gi2/6 也没有 portfast。也就是说:没有任何人把这个口”手工”配成边缘口

3.2 下联侧:日志把时间线交代得很清楚

13:10:35.050  Gi1/0/48 物理 down;13:10:35 Vlan-interface399 down
13:10:38.211  Gi1/0/48 物理 up;  13:10:38 Vlan-interface399 up
13:10:43.292  STP_NOT_ROOT:The current switch is no longer the root of instance 0
13:10:43.293  Gi1/0/48 进入 forwarding;检测到拓扑变化(TC)
13:10:44.205  Gi1/0/48 再次物理 down;Vlan-interface399 down
13:18:34      NTP 源丢失(隔离后的连带影响)

STP_NOT_ROOT 是关键:它说明在 13:10:43 之前,这台接入交换机曾经把自己当成根桥——而它之所以会发 BPDU,正是因为这件事

3.3 核心侧的告警

%SPANTREE-BLOCK_BPDUGUARD: Received BPDU on port GigabitEthernet 2/6
with BPDU Guard enabled. Disabling port.

配套的 show interfaces status err-disable 中,Gi2/6 的 Reason 为 BPDU Guard。核心配置里没有 errdisable recovery,所以这个口不会自愈,会一直保持 DOWN,直到人工恢复

四、根因:三个条件叠加

4.1 机制:全局保护 + 自动边缘端口

锐捷 RGOS 11.0(4) 的配置指南在 BPDU Guard 一节写得很明确:

可以在全局模式中用 spanning-tree portfast bpduguard default 打开全局的 BPDU Guard 状态,在这种状态下,如果某个 Interface 打开了 Port Fast,或该接口自动识别为边缘口,而该 Interface 收到了 BPDU,该端口就会进入 Error-disabled 状态

而”边缘端口自动识别(autoedge)“在锐捷上是缺省开启的:指派口在 3 秒内收不到下游 BPDU,就判为边缘口,直接进入 Forwarding;一旦收到 BPDU,再自动识别为非边缘口

于是 Gi2/6 的处境是:

  1. 它是核心的指定口(核心是根桥,根桥所有端口都是指定口)
  2. 下联交换机是非根,它的根端口只收不发配置 BPDU,所以 Gi2/6 在日常状态下收不到对端 BPDU
  3. 因此 Gi2/6 会被 autoedge 判成边缘口,并被全局 BPDU Guard 管辖

接口下没有配置,不代表没有行为——保护在全局,边缘口来自自动识别

4.2 触发:一次约 3 秒的物理瞬断

13:10:35 链路物理 down,13:10:38 恢复。这个 down 不是保护造成的:核心没有开 errdisable recovery,被 Guard 关掉的口不会 3 秒后自愈;它自愈了,说明这次是真断了一下

瞬断期间,接入交换机失去了核心的 BPDU,也就失去了根信息。按 STP 规则,它会以自身为根桥继续工作,并在链路恢复后向所有指定口发送 BPDU

4.3 竞态:3 秒判定窗口 vs 约 5 秒的 STP 收敛

这是整件事最”巧”、也最必然的地方:

时间发生了什么
13:10:35链路 DOWN,端口状态被清空
13:10:38链路 UP,核心开始 autoedge 的 3 秒判定窗口
13:10:38 ~ 13:10:43接入交换机还在 STP 收敛(13:10:43 才 Forwarding),尚未发出 BPDU
约 13:10:413 秒窗口到期,核心判定 Gi2/6 为边缘口
约 13:10:43接入交换机作为”临时根桥”,第一个 BPDU 到达 Gi2/6
约 13:10:44边缘口收到 BPDU → BPDU Guard 触发 → Gi2/6 进入 error-disabled

也就是说:闪断同时制造了”判定窗口”和”对端 BPDU”,而对端的 STP 收敛(约 5 秒)比核心的判定窗口(3 秒)慢了 2 秒,于是核心先把它认成”接终端的口”,随后 BPDU 一到就被当成非法报文处理掉了

换一种说法:如果对端能在 3 秒内发出 BPDU,这个口就不会被判定为边缘口,也就不会被关;如果链路不断,对端永远是非根、永远不发 BPDU,这个口就永远”安全”。两个条件同时成立,事故才发生

4.4 为什么之前半年都没事

因为 BPDU Guard 一直在等一个平时永远不会来的 BPDU:

  • 稳态下,接入交换机是根端口,根端口不发配置 BPDU
  • 核心 Gi2/6 收不到 BPDU,autoedge 把它判成边缘口,但没有任何 BPDU 来”踩雷”
  • 这颗雷就这样安静地埋着,直到某一次链路瞬断——这是定时炸弹,不是偶然事件

五、排除环路

现场很容易怀疑”是不是下联环路导致 BPDU 绕回”,但证据不支持:

  1. 接入交换机只有 Gi1/0/48 一条上联,XGE 1/0/53/54 两条 trunk 均为 shutdown
  2. GE1/0/47 是 access vlan 999 + stp edged-port + dot1x 的稽查接入口,不是上联
  3. 在用的 GE1/0/36/40/45 分属 401/440/460 三个不同 VLAN,每个 VLAN 仅 1 个 up 口,不存在同 VLAN 双上行
  4. 下联日志里的 STP_NOT_ROOT 说明 BPDU 是它自己发的(它曾短暂自认根桥),不是核心自己的 BPDU 绕回来
  5. 核心侧 Gi2/6 是唯一连接该接入交换机的链路,且双方 trunk 放通的 VLAN 完全对齐

结论:不是环,是”瞬断 + 边缘端口竞态”

六、为什么别的 trunk 没中招

现场还有个有意思的对照:核心 0B 的同类型 trunk、以及 0A 的 AggregatePort 1,PortOperAutoEdge 和 PortBPDUGuard 都是 Disabled

这恰恰说明 autoedge 的运行态不是”持续轮询”,而是按链路事件判定并保持:端口在一次链路 UP 时如果见过 BPDU,就会被判为非边缘口并锁定;之后对端即使不再发 BPDU,它也不会自动变回边缘口

所以:

  • 那些口”没事”,是因为它们上次链路 UP 时恰好见过 BPDU(例如对端核心在自身重启/倒换期间短暂当过根)
  • Gi2/6 “有事”,是因为这次 UP 时,3 秒内确实没等到 BPDU

当前不是边缘口 ≠ 永远安全:下一次链路翻转,如果对端 STP 收敛再次超过 3 秒,同样的连环还会重演。尤其 AggregatePort 1——它是核心互联链路,一旦被 Guard 关掉,就是双核心隔离 + VRRP 双主,后果比一条下联严重得多

七、处置与整改

7.1 恢复端口

configure terminal
interface GigabitEthernet 2/6
 shutdown
 no shutdown
 end

若配置了 errdisable recovery,也可以用 errdisable recovery 手动恢复;本次核心没有配,必须手动

7.2 把”面向交换机”的 trunk 从边缘口语义里摘出来

configure terminal
interface range GigabitEthernet 2/6-2/7,GigabitEthernet 1/11-1/12,AggregatePort 1
 spanning-tree portfast disabled
 spanning-tree autoedge disabled
 spanning-tree bpduguard disabled
 end
  • 不要动全局 spanning-tree portfast bpduguard default:它对真正的接入口(核心 Gi2/1~2/5 这类 access + portfast 的口)是合适的,保护应该保留
  • 只要 trunk 不再是边缘口,全局保护就管不到它;再在接口上显式关闭 guard,是双保险

7.3 同类隐患清单

核心上还有几条”面向交换机、没有 bpdufilter、会被 autoedge 判定”的 trunk,需要一并处理:

接口描述风险
Gi2/6下联接入 SW-23本次故障口
Gi2/7同 VLAN 备份链路与 2/6 完全相同的隐患
Gi1/11、Gi1/12备份链路同样的”无 filter trunk”
AggregatePort 1核心互联风险最高,一旦触发就是双主

另外两条建议:

  • 接入交换机 stp instance 0 priority 8192 可以抬到 32768/40960,降低它作为”第二顺位根候选”的资格;治本仍靠核心侧关闭 autoedge/guard,优先级只是加固
  • 继续排查 13:10:35 那次瞬断的物理原因(线缆、电口、CRC、接头),否则换个口还会再来一次

7.4 验证

show spanning-tree interface GigabitEthernet 2/6
show interfaces status err-disable
show spanning-tree

预期:PortAdminPortFast、PortOperAutoEdge、PortBPDUGuard 均为 Disabled;端口为 designated/forwarding;err-disable 列表为空;根桥仍是核心 0A

八、复盘 Takeaway

  1. “接口下没有配置”不等于”没有行为”。全局开关、缺省开启的特性、端口模板,都会绕过接口视图
  2. autoedge 缺省开启,是这套网络里最隐蔽的坑之一。面向交换机的 trunk 不能靠”我没配 portfast”来证明安全
  3. BPDU Guard 只该用于终端接入口。接交换机的口一旦被 autoedge 判成边缘口,保护就变成了”等一个迟早会来的 BPDU”
  4. 瞬断是触发条件,不是根本原因。根因是”边缘口语义 + 全局保护”同时压在了这条 trunk 上;物理闪断只是扣动了扳机
  5. 判断”谁关的口”,先分清 err-disable 和链路 DOWN:被保护关掉的口不会自愈(除非配置了恢复),能 3 秒后自己起来的,一定是物理闪断
  6. 排查顺序:先看 err-disable 的 Reason,再看全局配置,再看端口运行态(PortOperAutoEdge / PortBPDUGuard),最后才看接口配置

附录:排查命令清单

锐捷(核心)

show interfaces status err-disable                 # 违例原因
show logging | include BPDUGUARD                   # 告警原文
show running-config | include bpduguard            # 全局保护
show running-config | include portfast
show running-config interface GigabitEthernet 2/6  # 接口配置
show spanning-tree interface GigabitEthernet 2/6   # 运行态字段
show spanning-tree                                 # 根桥与端口角色
show interfaces counters                           # 物理层错包

H3C(接入)

display stp
display stp brief
display interface GigabitEthernet 1/0/48
display logbuffer
display current-configuration interface GigabitEthernet 1/0/48

文中拓扑、时序与配置均来自现场采集与配置备份对比,关键日志已做脱敏处理