Besides being one the most popular networking protocols to have a job applicant try to explain during a job interview, the Spanning Tree protocol is a very sophisticated networking protocol designed to prevent networking loops from forming in a Layer 2 network. I’ll be focusing on explaining the Rapid Spanning Tree Protocol.
Loops in your network
Before explaining the various components of the Spanning Tree protocol, we first need to examine what can happen in your network that will possibly create a loop and what will happen at that point. We don’t need a complex network to get the point across. Take a look at the following network topology:
You’ll see two links in between switches A and B. In a normal situation these two links would be bundled together, to form an Ether-channel. This is also called a Port-channel. You can use this concept to group multiple interfaces together and make them act as just one logical interface. Both sides need to be configured as an Ether-channel in order for this to work. Let’s assume for the moment that this is not the case and the two links between switches A and B are not bundled together.
A network loop can form in the following situation. Suppose we’re operating PC 1 and we want to ping PC 2.
- We do not yet know the mac address of PC 2, so we send out an ARP Request packet.
- Switch A received the ARP Request (which is a broadcast frame) and sends it to all of its connected ports except the one it received it on. This means to both interfaces connected to Switch B.
- Switch B receives the two broadcast frames and will also forward the frames to all of its connected ports. PC 2 will receive these frames, but it will also be sent back to Switch A via its connected interfaces.
- At this point, Switch A will yet again forward the broadcast frames to Switch B and vice versa.
The single ARP request of PC 1 has just caused two broadcast frames to endlessly loop the network and therefore hog all system resources of the two switches. Now suppose we have dozens of machines on these two switches which are all generating broadcast frames. The two switches will not be able to handle this, and thus your network will stop functioning. This phenomenon is called a Broadcast Storm. Hence the featured image of this post 🙂
Stopping loops from forming
The simplistic view of Spanning Tree is that the protocol will find the best way to reach the Root Bridge and block all redundant links. Switches will recognize redundant links by sending out Bridge Protocol Data Units. Or BPDU’s in short.
On Cisco switches, Spanning Tree is enabled by default. So in the above example, Switch A would have already sent out BPDU’s on both its connected interfaces to Switch B. BPDU frames will have an identifier called the Bridge ID, by which a switch can recognize itself or other switches. When Switch A sends the BPDU’s, Switch B will send them back to Switch A. When Switch A receives them, it will open up the frame and conclude that it received the BPDU’s that it had sent out himself, because it has its own Bridge ID in the frames. At that point, Switch A or B will block one of the two links, so there won’t be a layer 2 loop.
As said, switches will use Spanning Tree to find the best path to reach the Root Bridge and block all redundant links. The Root Bridge is an important concept, because this will affect the whole operation of Spanning Tree. The decision on whether or not to block a redundant link, is based on who the Root Bridge is. Let’s figure out who the root is for the below network, using default configuration.
The root election is done using the aforementioned Bridge ID. The Bridge ID is made up of two parts: First the priority, then the system MAC address. Here is a wireshark capture from the above topology to show you how the Bridge ID of Switch A is made:
You can see the following:
- Priority: 32768
- System ID Extension: 100 (sys-id-ext)
- System ID: aa:bb:cc:00:01:00
The Priority and System ID Extension are combined, which makes 32868 in total. The System ID Extension is actually made up from the VLAN that is currently used. In this case I’m using VLAN 100. Using the VLAN in the System ID Extension makes sure that the Bridge ID will be unique for this particular VLAN. This is important, because modern STP works on a per VLAN basis, where a whole Spanning Tree topology is computated for each VLAN individually. Lastly we have the System ID, which is basically the system MAC address. In hexadecimal value, the Bridge ID is:
80 64 aa bb cc 00 01 00
Where 8064 is the hexadecimal equivalent of 32868 (combination of priority+sys-id-ext) and the rest is the (already in hexadecimal format) system MAC address.
The above corresponds with the output of the command
SwitchA#show spanning-tree VLAN0100 Spanning tree enabled protocol rstp Root ID Priority 32868 Address aabb.cc00.0100 This bridge is the root Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Bridge ID Priority 32868 (priority 32768 sys-id-ext 100) Address aabb.cc00.0100 Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Aging Time 300 sec Interface Role Sts Cost Prio.Nbr Type ------------------- ---- --- --------- -------- -------------------------------- Et0/2 Desg FWD 100 128.3 Shr Et0/3 Desg FWD 100 128.4 Shr
Now that you have a good understanding of the Bridge ID, how can we now tell which switch will be elected as the Root Bridge? Here’s the golden rule for Spanning Tree:
LOWER IS BETTER!
We can play with the priority to make another switch the Root Bridge, just by lowering the priority. Here’s an important concept:
If we do not change the priority of the switches, then this might have a catastrophic effect to the operation of the network. Because if the priority of the switches are the same, then the MAC address will be the tie breaker. If a lower MAC address is better, then potentially the oldest switch in your network will become the Root Bridge. If we assume that older switches have less capacity / throughput, then your network will get bogged down and will might perform horribly. That is why you should never leave Spanning Tree settings at their defaults.
Spanning Tree port types
Now that we know the operation of the Bridge ID and the root election process, let’s begin to look at how Spanning Tree decides which ports will get blocked and which ones will not. We will again use the following topology, with a few additions now:
We have the following port types within the Spanning Tree topology:
- Root Port
- Designated Port
- Blocked Port
The Root Port role is given to the interface of a switch that has the lowest cost to reach the Root Bridge. Every switch will have exactly one Root Port. In the above topology you will see in blue the cost of all links. The cost is a value that is representative to a particular link speed. It can be changed manually under the interface configuration.
Below you’ll find a table to translate port speed to STP cost:
|Bandwidth||Short path Cost||Long path Cost|
You will notice the difference between the short path cost and the long path cost. In the early days, the STP cost was derived from a formula using a 16-bit value, which has a maximum decimal value of 65535. This was because at the time, link speeds of 10 Gbps or higher were not thought to be even possible. I’ve recently rolled out 100 Gbps links already, and with the 16-bit cost value you can’t differentiate between port speeds anymore, losing all flexibility in path selection in a layer 2 topology with different speeds. Therefore, a 32-bit STP cost has been designed, with newly derived decimal values for the different link speeds. As of right now, for compatibility, the default on Cisco switches is to use the short path cost method. If you want, you can change this with the following command:
spanning-tree pathcost method long
By doing so, you can see how the cost has changed (in bold):
SwitchB#sh spann VLAN0100 Spanning tree enabled protocol rstp Root ID Priority 32868 Address aabb.cc00.0100 Cost 2000000 Port 3 (Ethernet0/2) Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Bridge ID Priority 32868 (priority 32768 sys-id-ext 100) Address aabb.cc00.0200 Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Aging Time 300 sec Interface Role Sts Cost Prio.Nbr Type ------------------- ---- --- --------- -------- -------------------------------- Et0/0 Altn BLK 2000000 128.1 Shr Et0/2 Root FWD 2000000 128.3 Shr
So, returning to the root port role: if you look at the above topology, we have a cost of 100 for all links. The path for Switch B to Switch A over Ethernet0/0 through Switch C would be total of 100 + 100 = 200, in comparison to the cost of 100 if it picked the direct link to Switch A. Therefore, Ethernet0/2 will be the Root Port. If you have multiple links the same switch, then the Port Priority will be the tie breaker, where of course, lower is better. This is notated as the 128.1 and 128.3 in the above example.
A Designated Port role is just a forwarding port. Meaning that it is not a Root Port or a Blocked Port. For example, this could be a connection to an end host or another switch, which has no links to multiple switches. For example, if I daisy chained another switch to Switch B, the interface to that switch will have the Designated Port role.
A designated Port on one side, could be a Blocked Port on the other side. More on that further on.
A Blocked Port role, or Alternate port, is a link which has been selected by the Spanning Tree protocol to be redundant and “inferior” to another link. If we look at the above topology once more, we can assume very quickly, that the directly connected links of Switch B to Switch A and of Switch C to Switch A will have the lowest cost, and these will be selected as the Root Ports. Hence the red R in the topology.
However, this leaves Ethernet0/0 between Switch B and Switch C. Why is it that Switch B will have that port as Designated and why is it that Switch C will have that port in the Blocking role? Can you guess? It’s because of the Bridge ID of course! Since the priority in this topology is the same, the tie breaker will be the MAC address. Since lower is better, Switch B will be superior and will have it’s port as Designated.
Let’s look at the output of
show spanning-tree to confirm this:
SwitchB#sh spann VLAN0100 Spanning tree enabled protocol rstp Root ID Priority 32868 Address aabb.cc00.0100 Cost 100 Port 3 (Ethernet0/2) Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Bridge ID Priority 32868 (priority 32768 sys-id-ext 100) Address aabb.cc00.0200 Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Aging Time 300 sec Interface Role Sts Cost Prio.Nbr Type ------------------- ---- --- --------- -------- -------------------------------- Et0/0 Desg FWD 100 128.1 Shr Et0/2 Root FWD 100 128.3 Shr
SwitchC#sh spann VLAN0100 Spanning tree enabled protocol rstp Root ID Priority 32868 Address aabb.cc00.0100 Cost 100 Port 4 (Ethernet0/3) Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Bridge ID Priority 32868 (priority 32768 sys-id-ext 100) Address aabb.cc00.0300 Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Aging Time 300 sec Interface Role Sts Cost Prio.Nbr Type ------------------- ---- --- --------- -------- -------------------------------- Et0/0 Altn BLK 100 128.1 Shr Et0/3 Root FWD 100 128.4 Shr
It is therefore very important to look at every switch in your topology to come to a conclusion on all the port roles.
Experimenting with Spanning Tree
What I often read is that people will say that the Root Port role is assigned to the interface that is connected to the Root Bridge. Even if this is almost always the case in the real world, it is not the real reason and can be a bit confusing if you’re trying to understand the port roles used with Spanning Tree.
It all comes down to the Bridge ID. Let’s play with the topology a bit:
I’ve changed the cost of the interfaces Ethernet0/0 on both Switch B and C to 10 and also on Switch B Ethernet0/2 and Switch A Ethernet0/2. The total cost for Switch C to now reach Switch A via Switch B will be 10 + 10 = 20. This is lower than its directly connected link Ethernet0/3, which is still 100.
Let’s again look at the output of
show spanning-tree to confirm this:
SwitchC#sh spann VLAN0100 Spanning tree enabled protocol rstp Root ID Priority 32868 Address aabb.cc00.0100 Cost 20 Port 1 (Ethernet0/0) Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Bridge ID Priority 32868 (priority 32768 sys-id-ext 100) Address aabb.cc00.0300 Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Aging Time 300 sec Interface Role Sts Cost Prio.Nbr Type ------------------- ---- --- --------- -------- -------------------------------- Et0/0 Root FWD 10 128.1 Shr Et0/3 Altn BLK 100 128.4 Shr
Now Ethernet0/0 has the Root Port role. There was actually an easier way to make sure that the path selection went via Ethernet0/0 instead of Ethernet0/3, from the perspective of Switch C. The cost from Switch C to Switch B is 100 and from Switch B to Switch A also 100, for a total of 200. If we change the cost on Switch C of Ethernet0/3 to a minimum of 201, we can then change the Root Port to Ethernet0/0 as well. See the output:
SwitchC#sh spann VLAN0100 Spanning tree enabled protocol rstp Root ID Priority 32868 Address aabb.cc00.0100 Cost 200 Port 1 (Ethernet0/0) Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Bridge ID Priority 32868 (priority 32768 sys-id-ext 100) Address aabb.cc00.0300 Hello Time 2 sec Max Age 20 sec Forward Delay 15 sec Aging Time 300 sec Interface Role Sts Cost Prio.Nbr Type ------------------- ---- --- --------- -------- -------------------------------- Et0/0 Root FWD 100 128.1 Shr Et0/3 Altn BLK 201 128.4 Shr
Spanning Tree Configuration and considerations
You now have a good understanding of how Spanning Tree works. There are still a few things to keep in mind in regards to how to optimally configure Spanning Tree in your network. Under your interfaces, there are a number of options which you can configure.
The portfast command is used on edge ports, which connect to end hosts. You use this command to skip the spanning-tree listening and learning phases, which are used when there is a topology change. The listening and learning phases are also called the Forward Delay. If you do not configure this on edge ports, then topology changes in your network cause an outage of 15 seconds on your edge devices. This command is also useful if the operating system of a PC boots faster than the transitioning state of a non-portfast port. If your PC is faster, then it might happen that the DHCP process won’t be able to pick up an IP address from the DHCP server.
You configure spanning-tree portfast under global configuration as a default, or on specific ports:
SwitchA(config)#spanning-tree portfast default
Under an interface:
It’s important to note that portfast does not disable spanning-tree on a configured port. If a BPDU frame was received on a link that has portfast enabled, the port would transition out of portfast and go through the listening and learning phases and act as a normal spanning-tree port.
Spanning-tree bpdufilter and bpduguard
When you configure a BPDU filter on a port, you effectively stop the sending and receiving of BPDU frames to and from that port. This will make that interface passive to the spanning-tree process. You will want to use this if for example, you have a foreign switch that needs to be connected to your network that you do not control over and do not want to be part of your spanning-tree topology. Make sure to not have multiple links that are in the BPDU filter state.
The BPDU guard option will also stop BPDU’s from entering an interface, when configured at the interface level, but will also put the interface in an error-disabled state. You need to manually bring that interface back by shutting an unshutting that specific interface.
These commands can also be configured in global configuration, or on an interface level. When you configure them in global configuration, they will only be enabled for portfast ports.
SwitchA(config)#spanning-tree portfast bpdufilter default SwitchA(config)#spanning-tree portfast bpduguard default
Under an interface:
SwitchA(config-if)#spanning-tree bpduguard enable SwitchA(config-if)#spanning-tree bpdufilter enable
The Spanning Tree Rootguard command is one that you will configure on an interface. It makes sure that the interface on which it is configured, cannot transition to the Root Port role. Let’s say someone plugs in a switch to the network, which has a priority of 0, and you would have no mechanisms in place to prevent another switch to become part of the network, this switch could potentially become the Root Bridge of the Layer 2 network. If a BPDU is received with such conditions, that it would mean the port needs to be transitioned to the Root Port role, it will put the port in an root-inconsistent state. This means that the port will become blocked and is essentially cut off from the network.
SwitchA(config-if)#spanning-tree guard root
If you would like to use this, then you should consider configuring this from the outside of your network to the inside. Meaning that it is a best practice to configure this at the access level of your network, rather than at the distribution or core layer of the network, since it will put the port it received a superior BPDU on in the blocking state, effectively cutting off your network.
Spanning Tree Loopguard
As the name implies, the Spanning Tree Loopguard command will provide additional protection to a Layer 2 loop within your topology. It does this by making sure that some topology changes are not allowed.
If you have a port that is non-designated, meaning a Root Port or a Alternate Blocking port, then you have received BPDU’s on that port and will continue to do so, for that port role to remain so. If one of the interfaces with such a port role all of the sudden stops receiving BPDU’s and that interface would remain to be up, for example, because there is a uni-directional link failure, the normal Spanning Tree operation would be to go through the listening and learning phase and bring that port in a forwarding role. This will cause a loop in the network, in the case where there is still a uni-directional link to the other end. The loopguard feature will prevent this situation from happening and will stop the loop from forming.
You can configure this under global configuration or on a per port basis.
SwitchA(config)#spanning-tree loopguard default
Under an interface:
SwitchA(config-if)#spanning-tree guard loop
This has been quite a long blog post! I hope however, that you find it useful. See you in the next one!