Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Spanning Tree
Protocol
Jason Myers / Emma / @jasonamyers
Spanning Tree
Protocol
Jason Myers / Emma / @jasonamyers
Spanning Tree
Protocol
Jason Myers / Emma / @jasonamyers
Radia Perlman
STP, Link State Protocols, TRILL

over 40 years on the same problem set!
Port States
• Disabled - administrator turned the port off
• Blocking - This port would cause a loop
• Listening - Trying ...
def _state_machine(self):!
! role_str = {ROOT_PORT: 'ROOT_PORT ',!
DESIGNATED_PORT: 'DESIGNATED_PORT ',!
NON_DESIGNATED_PO...
def recalculate_spanning_tree(self, init=True):!
""" Re-calculation of spanning tree. """!
# All port down.!
for port in s...
A B
C
I am the root!
32768.00-00-00-00-00-01
I am the root!
32768.00-00-00-00-00-03
I am the root!
32768.00-00-00-00-00-02
def _spanning_tree_algorithm(self):!
port_roles = {}!
!
root_port = self._select_root_port()!
!
if root_port is None:!
# M...
A B
C
I am the root!
32768.00-00-00-00-00-01
I am the root!
32768.00-00-00-00-00-03
I am the root!
32768.00-00-00-00-00-02
A B
C
I am the root!
32768.00-00-00-00-00-01
I am the root!
32768.00-00-00-00-00-03
I am the root!
32768.00-00-00-00-00-02...
A B
C
I am the root!
32768.00-00-00-00-00-01
I am the root!
32768.00-00-00-00-00-03
I am the root!
32768.00-00-00-00-00-02...
BPDU
• Protocol ID
• Version ID
• BPDU Type
• Flags
• Root ID
• Root Path Cost
• bridge id
• Port ID
• Message Age
• Max A...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is C
I am the root!
32768.00-00-00-00-00-02
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is C
I am the root!
32768.00-00-00-00-00-02
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is C
I am the root!
32768.00-00-00-00-00-02
BPDU...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is C
I am the root!
32768.00-00-00-00-00-02
BPDU...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
def _select_root_port(self):!
root_port = None!
!
for port in self.ports.values():!
root_msg = (self.root_priority if root...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
else:!
# Other bridge is a root bridge.!
self.logger.info('Non root bridge.', extra=self.dpid_str)!
root_priority = root_p...
def _select_designated_port(self, root_port):!
d_ports = []!
root_msg = root_port.designated_priority!
!
for port in self....
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwarding
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
X
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwarding
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
def topology_change_notify(self, port_state):!
notice = False!
if port_state is PORT_STATE_FORWARD:!
for port in self.port...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwarding
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwarding
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
A B
C
I am the root!
32768.00-00-00-00-00-01
32768.00-00-00-00-00-03
Root is A
32768.00-00-00-00-00-02
Root is A
Forwardin...
Implementation
• Ryu - https://github.com/osrg/ryu/blob/master/
ryu/lib/stplib.py
• OpenStack Neutron
• Prim’s MST
I think that I shall never see
A graph as lovely as a tree.
A tree which must be sure to span.
So packets can reach every ...
Upcoming SlideShare
Loading in …5
×

Spanning Tree Algorithm

1,214 views

Published on

A detailed look at the STP algorithm

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Spanning Tree Algorithm

  1. 1. Spanning Tree Protocol Jason Myers / Emma / @jasonamyers
  2. 2. Spanning Tree Protocol Jason Myers / Emma / @jasonamyers
  3. 3. Spanning Tree Protocol Jason Myers / Emma / @jasonamyers
  4. 4. Radia Perlman STP, Link State Protocols, TRILL
 over 40 years on the same problem set!
  5. 5. Port States • Disabled - administrator turned the port off • Blocking - This port would cause a loop • Listening - Trying to determine if it should block • Learning - Adding source addresses to it’s CAM • Forwarding - Moving the bits
  6. 6. def _state_machine(self):! ! role_str = {ROOT_PORT: 'ROOT_PORT ',! DESIGNATED_PORT: 'DESIGNATED_PORT ',! NON_DESIGNATED_PORT: 'NON_DESIGNATED_PORT'}! state_str = {PORT_STATE_DISABLE: 'DISABLE',! PORT_STATE_BLOCK: 'BLOCK',! PORT_STATE_LISTEN: 'LISTEN',! PORT_STATE_LEARN: 'LEARN',! PORT_STATE_FORWARD: 'FORWARD'}! ! if self.state is PORT_STATE_DISABLE:! self.ofctl.set_port_status(self.ofport, self.state)! ! while True:! self.logger.info('[port=%d] %s / %s', self.ofport.port_no,! role_str[self.role], state_str[self.state],! extra=self.dpid_str)! ! self.state_event = hub.Event()! timer = self._get_timer()! if timer:! timeout = hub.Timeout(timer)! try:! self.state_event.wait()! except hub.Timeout as t:! if t is not timeout:! err_msg = 'Internal error. Not my timeout.'! raise RyuException(msg=err_msg)! new_state = self._get_next_state()! self._change_status(new_state, thread_switch=False)! finally:! timeout.cancel()! else:! self.state_event.wait()! ! self.state_event = None!
  7. 7. def recalculate_spanning_tree(self, init=True):! """ Re-calculation of spanning tree. """! # All port down.! for port in self.ports.values():! if port.state is not PORT_STATE_DISABLE:! port.down(PORT_STATE_BLOCK, msg_init=init)! ! # Send topology change event.! if init:! self.send_event(EventTopologyChange(self.dp))! ! # Update tree roles.! port_roles = {}! self.root_priority = Priority(self.bridge_id, 0, None, None)! self.root_times = self.bridge_times! ! if init:! self.logger.info('Root bridge.', extra=self.dpid_str)! for port_no in self.ports.keys():! port_roles[port_no] = DESIGNATED_PORT! else:! (port_roles,! self.root_priority,! self.root_times) = self._spanning_tree_algorithm()! ! # All port up.! for port_no, role in port_roles.items():! if self.ports[port_no].state is not PORT_STATE_DISABLE:! self.ports[port_no].up(role, self.root_priority,! self.root_times)!
  8. 8. A B C I am the root! 32768.00-00-00-00-00-01 I am the root! 32768.00-00-00-00-00-03 I am the root! 32768.00-00-00-00-00-02
  9. 9. def _spanning_tree_algorithm(self):! port_roles = {}! ! root_port = self._select_root_port()! ! if root_port is None:! # My bridge is a root bridge.! self.logger.info('Root bridge.', extra=self.dpid_str)! root_priority = self.root_priority! root_times = self.root_times! ! for port_no in self.ports.keys():! if self.ports[port_no].state is not PORT_STATE_DISABLE:! port_roles[port_no] = DESIGNATED_PORT
  10. 10. A B C I am the root! 32768.00-00-00-00-00-01 I am the root! 32768.00-00-00-00-00-03 I am the root! 32768.00-00-00-00-00-02
  11. 11. A B C I am the root! 32768.00-00-00-00-00-01 I am the root! 32768.00-00-00-00-00-03 I am the root! 32768.00-00-00-00-00-02 BPDU from C
  12. 12. A B C I am the root! 32768.00-00-00-00-00-01 I am the root! 32768.00-00-00-00-00-03 I am the root! 32768.00-00-00-00-00-02 BPDU from CBPDU from C
  13. 13. BPDU • Protocol ID • Version ID • BPDU Type • Flags • Root ID • Root Path Cost • bridge id • Port ID • Message Age • Max Age (20 Sec) • Hello Time (2 Sec) • Forward Delay (15 sec) • version 1 Length • version 3 Length
  14. 14. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is C I am the root! 32768.00-00-00-00-00-02
  15. 15. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is C I am the root! 32768.00-00-00-00-00-02
  16. 16. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is C I am the root! 32768.00-00-00-00-00-02 BPDU from A
  17. 17. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is C I am the root! 32768.00-00-00-00-00-02 BPDU from A BPDU from A
  18. 18. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  19. 19. def _select_root_port(self):! root_port = None! ! for port in self.ports.values():! root_msg = (self.root_priority if root_port is None! else root_port.designated_priority)! port_msg = port.designated_priority! if port.state is PORT_STATE_DISABLE or port_msg is None:! continue! if root_msg.root_id.value > port_msg.root_id.value:! result = SUPERIOR! elif root_msg.root_id.value == port_msg.root_id.value:! if root_msg.designated_bridge_id is None:! result = INFERIOR! else:! result = Stp.compare_root_path(! port_msg.root_path_cost,! root_msg.root_path_cost,! port_msg.designated_bridge_id.value,! root_msg.designated_bridge_id.value,! port_msg.designated_port_id.value,! root_msg.designated_port_id.value)! else:! result = INFERIOR! ! if result is SUPERIOR:! root_port = port! ! return root_port!
  20. 20. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  21. 21. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  22. 22. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  23. 23. else:! # Other bridge is a root bridge.! self.logger.info('Non root bridge.', extra=self.dpid_str)! root_priority = root_port.designated_priority! root_times = root_port.designated_times! ! port_roles[root_port.ofport.port_no] = ROOT_PORT! ! d_ports = self._select_designated_port(root_port)! for port_no in d_ports:! port_roles[port_no] = DESIGNATED_PORT! ! for port in self.ports.values():! if port.state is not PORT_STATE_DISABLE:! port_roles.setdefault(port.ofport.port_no,! NON_DESIGNATED_PORT)! ! return port_roles, root_priority, root_times!
  24. 24. def _select_designated_port(self, root_port):! d_ports = []! root_msg = root_port.designated_priority! ! for port in self.ports.values():! port_msg = port.designated_priority! if (port.state is PORT_STATE_DISABLE! or port.ofport.port_no == root_port.ofport.port_no):! continue! if (port_msg is None or! (port_msg.root_id.value != root_msg.root_id.value)):! d_ports.append(port.ofport.port_no)! else:! result = Stp.compare_root_path(! root_msg.root_path_cost,! port_msg.root_path_cost - port.path_cost,! self.bridge_id.value,! port_msg.designated_bridge_id.value,! port.port_id.value,! port_msg.designated_port_id.value)! if result is SUPERIOR:! d_ports.append(port.ofport.port_no)! ! return d_ports
  25. 25. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  26. 26. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  27. 27. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  28. 28. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  29. 29. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A Forwarding
  30. 30. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding
  31. 31. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding
  32. 32. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding Forwarding
  33. 33. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding Forwarding Forwarding
  34. 34. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding Forwarding Forwarding Blocking
  35. 35. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A X
  36. 36. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  37. 37. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A Forwarding
  38. 38. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding
  39. 39. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding
  40. 40. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding Listening
  41. 41. def topology_change_notify(self, port_state):! notice = False! if port_state is PORT_STATE_FORWARD:! for port in self.ports.values():! if port.role is DESIGNATED_PORT:! notice = True! break! else:! notice = True! ! if notice:! self.send_event(EventTopologyChange(self.dp))! if self.is_root_bridge:! self._transmit_tc_bpdu()! else:! self._transmit_tcn_bpdu()! !
  42. 42. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  43. 43. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A Forwarding
  44. 44. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding
  45. 45. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding
  46. 46. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding Learning
  47. 47. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A
  48. 48. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A Forwarding
  49. 49. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding
  50. 50. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding
  51. 51. A B C I am the root! 32768.00-00-00-00-00-01 32768.00-00-00-00-00-03 Root is A 32768.00-00-00-00-00-02 Root is A ForwardingForwarding Forwarding Forwarding
  52. 52. Implementation • Ryu - https://github.com/osrg/ryu/blob/master/ ryu/lib/stplib.py • OpenStack Neutron • Prim’s MST
  53. 53. I think that I shall never see A graph as lovely as a tree. A tree which must be sure to span. So packets can reach every LAN. First the root must be selected. By ID, it is elected. Least cost paths from Root are traced. In the tree these paths are placed. A mesh is made by folks like me. Then bridges find a spanning tree.

×