Wednesday, February 19, 2020

Spanning-Tree LoopGuard and UDLD

If you ever used fiber cables you might have noticed that there is a different connector to transmit and receive traffic.
Fiber Cable ConnectorsIf one of the cables (transmit or receive) fails we’ll have a unidirectional link failure and this can cause spanning tree loops. There are two protocols that can take care of this problem:
  • LoopGuard
  • UDLD ( Unidirectional Link Detection )
Let’s start by taking a close look at what will happen if we have a unidirectional link failure:
switches fiber connections topology
Imagine the links between the switches are fiber links. In reality there’s a different connector for transmit and receive. SW3 is receiving BPDUs from SW2 and as a result the interface has become an alternate port and is in blocking mode.
spanning tree unidirectional link failure
Now something goes wrong…the transmit connector on SW2 towards SW3 was eaten by mice failed due to unknown reasons. As a result SW3 is not receiving any BPDUs from SW2 but it can still send traffic to SW2.
Because SW3 is not receiving anymore BPDUs on its alternate port it will go into forwarding mode. We now have a one way loop as indicated by the green arrow.
One of the methods we can use to solve our unidirectional link failure is to configure LoopGuard. When a switch is sending but not receiving BPDUs on the interface, LoopGuard will place the interface in the loop-inconsistent state and block all traffic:
spanning tree loop guard example
Let’s take a look what this looks like on actual switches. I will use the same topology:
Rapid Spanning Tree UplinkFastLet’s enable loopguard:
SW1(config)#spanning-tree loopguard default
SW2(config)#spanning-tree loopguard default
SW3(config)#spanning-tree loopguard default
Use the spanning-tree loopguard default command to enable LoopGuard globally. I don’t have any fiber connectors so I’m unable to create a unidirectional link failure. I can simulate it however by using BPDUfilter on SW2’s fa0/16 interface. SW3 won’t receive any BPDUs anymore on its alternate port which will cause it to go into forwarding mode:
SW2(config)#interface fa0/16
SW2(config-if)#spanning-tree portfast trunk
SW2(config-if)#spanning-tree bpdufilter enable
Here’s what will happen:
SW3# 
*Mar  1 00:17:14.431: %SPANTREE-2-LOOPGUARD_BLOCK: Loop guard blocking port FastEthernet0/16 on VLAN0001.
Normally this would cause a loop but luckily we have LoopGuard configured. You can see this error message appearing in your console, problem solved!
hostname SW1
!
spanning-tree loopguard default
!
end
hostname SW2
!
spanning-tree loopguard default
!
interface FastEthernet0/16
 spanning-tree portfast trunk
 spanning-tree bpdufilter enable
!
end
hostname SW3
!
spanning-tree loopguard default
!
end
If you want you don’t have to configure LoopGuard globally, you can also do it on the interface level like this:
SW3(config-if)#spanning-tree guard loop
The other protocol we can use to deal with unidirectional link failures is called UDLD (UniDirectional Link Detection). This protocol is not part of the spanning tree toolkit but it does help us to prevent loops.
Simply said UDLD is a layer 2 protocol that works like a keepalive mechanism. You send hello messages, you receive them and life is good. As soon as you still send hello messages but don’t receive them anymore you know something is wrong and we’ll block the interface.
Let’s use the same topology but configure UDLD this time. Don’t forget to get rid of loopguard first…
Rapid Spanning Tree UplinkFast
SW1(config)#udld ?      
  aggressive  Enable UDLD protocol in aggressive mode on fiber ports except
              where locally configured
  enable      Enable UDLD protocol on fiber ports except where locally
              configured
  message     Set UDLD message parameters
There are a number of methods how you can configure UDLD. You can do it globally with the udld command but this will only activate UDLD for fiber links!
There are two options for UDLD:
  • Normal (default)
  • Aggressive
When you set UDLD to normal it will mark the port as undetermined but it won’t shut the interface when something is wrong. This is only used to “inform” you but it won’t stop loops.
Aggressive is a better solution. When it loses connectivity to a neighbor it will send a UDLD frame out once a second for 8 seconds. If the neighbor does not respond the interface will be put in err-disable mode.
Let’s use two switches to demonstrate UDLD:
Spanning-Tree BPDU Guard TopologyLet’s enable UDLD:
SW2(config)#interface fa0/16
SW2(config-if)#udld port aggressive
SW3(config)#interface fa0/16
SW3(config-if)#udld port aggressive
We’ll use SW2 and SW3 to demonstrate UDLD. I’ll use aggressive mode so we can see that the interface goes down when something is wrong. To see what is going on in real time we’ll use a debug:
SW2#debug udld events 
UDLD events debugging is on
SW3#
New_entry = 34422DC (Fa0/16)
Found an entry from same device (Fa0/16)
Cached entries = 2 (Fa0/16)
Entry (0x242BB9C) deleted: 1 entries cached
Cached entries = 1 (Fa0/16)
Checking if multiple neighbors (Fa0/16)
Single neighbor detected (Fa0/16)
Checking if link is bidirectional (Fa0/16)
Found my own ID pair in 2way conn list (Fa0/16)
Now the tricky part will be to simulate a unidirectional link failure. LoopGuard was easier because it was based on BPDUs. UDLD runs its own layer 2 protocol by using the proprietary MAC address 0100.0ccc.cccc. We can create a filter to block the UDLD traffic:
SW3(config)#mac access-list extended UDLD-FILTER
SW3(config-ext-macl)#deny any host 0100.0ccc.cccc
SW3(config-ext-macl)#permit any any
SW3(config-ext-macl)#exit
SW3(config)#interface fa0/16
SW3(config-if)#mac access-group UDLD-FILTER in
This is a creative way to cause trouble. By filtering the MAC address of UDLD on one side it will think that there is an unidirectional link failure! Here’s what you will see:
SW2#
UDLD FSM updated port, bi-flag udld_empty_echo, phase udld_detection (Fa0/16)
timeout timer = 0 (Fa0/16)
Phase set to EXT.  (Fa0/16)
New_entry = 370CED0 (Fa0/16)
Found an entry from same device (Fa0/16)
Cached entries = 2 (Fa0/16)
Entry (0x3792BE0) deleted: 1 entries cached
Cached entries = 1 (Fa0/16)
Zero IDs in 2way conn list (Fa0/16)
Zero IDs in 2way conn list (Fa0/16)
UDLD disabled port, packet received in extended detection (Fa0/16)
%UDLD-4-UDLD_PORT_DISABLED: UDLD disabled interface Fa0/16, unidirectional link detected
%PM-4-ERR_DISABLE: udld error detected on Fa0/16, putting Fa0/16 in err-disable state
You’ll see a lot of debug information flying by but the end result will be that the port is now in err-disable state. Here’s a show command you can use to check it:
SW2#show udld fastEthernet 0/16

Interface Fa0/16
---
Port enable administrative configuration setting: Enabled / in aggressive mode
Port enable operational state: Enabled / in aggressive mode
Current bidirectional state: Unidirectional
Current operational state: Disabled port
You can verify it by using the show udld command.
LoopGuard and UDLD both solve the same problem: Unidirectional Link failures. They have some overlap but there are a number of differences, here’s an overview:
LoopGuardUDLD
ConfigurationGlobal / per portGlobal (for fiber) / per port
Per VLAN?YesNo, per port
AutorecoveryYesYes – requires err-disable timeout.
Protection against STP failures because of unidirectional link failuresYes – need to enable it on all root and alternate portsYes – need to enable it on all interfaces
Protection against STP failures because no BPDUs are sentYesNo
Protection against miswiringNoYes
That’s all there is to it. I hope you enjoyed this lesson about LoopGuard and UDLD.

No comments:

Post a Comment