Spanning Tree Using Ryu STP Controller
Spanning Tree Using Ryu STP Controller
Software-Defined Networking
Theoretical Foundation
1. Introduction
The need to have data shared remotely lead to interconnected computers, thus creating
computer networks. Local networks are private networks formed by computers interconnected by
means of a bus (Ethernet) or connected between them forming a ring (Token Ring).
The predominant technology in local networks is Ethernet, in which it assumes a topology in bus
form. In this model, the signal is transmitted on the bus, which is a physical medium such as a
copper wire forming a single collision domain, thus making it for all computers. However, only the
computer that has the network adapter with the physical address contained in the frame header
(link PDU) will extract the datagram and deliver to the network layer. However, this structure
becomes saturated with the increase of hosts and a very high network traffic, thus making
access to the media highly disputed, generating many collisions.
With the evolution of networks and the need for more flexible and scalable topologies, equipment
such as bridges and switches have been developed. These switching devices eliminate the
single collision domain by isolating their ports, thereby forming a collision domain for each
interface. So, the received frame will be processed by the equipment and forwarded to the port
on which the destination host is, according to its switching table which is formed automatically
and dynamically. Then, if a destination address is not included in the switching table, the switch
passes the frame on all its interfaces, and for each received frame, the sender's physical address
is stored in the switch table.
Switches have become very important for network performance, being responsible for the
connection of the local network. In medium to large networks it is necessary to use many
switches. In these cases it is possible to organize these equipments in different topologies, in
order to have redundant paths and avoid failures.
However, forming redundant paths will form loops between switches, which are undesirable
because they generate problems such as allocation of all links, and network locking. These
problems occur due to the standard operation of the equipment and the network protocols, which
send messages in a broadcast generating frame copy forwarding, passing from one switch to
another in a loop. In this way, the frames will cycle through the switches, multiplying
exponentially (Figure 1).
Figure 1
An example of broadcast frame transmission is verified in ARP messages. In a local network, this
protocol is intended to identify the MAC address of the network interface of an equipment, that
has a specific IP address. In order to a host to communicate with this specific equipment, it’s
required to discover the MAC address of whose IP address is already known by the host. Thus,
the source host transmits an ARP broadcast message, asking what is the MAC address of the
host that has the IP address in question.
To avoid the problem of redundant paths between switches, Spanning Tree (STP) protocols are
used. STP act by controlling the switches, determining the ports to be disabled and thus
avoiding loops (Figure 2). For this, the STP protocol sends BPDUs (Bridge PDUs) between the
switches. So, according to Bridge ID, the root bridge will be chosen, determining a topology
according to the ID of the others bridges and the cost of the links, so that they do not form any
loop between them. Although the use of these protocols solve the problem of frames circulating
indefinitely by the switches, to solve the problem they end up reducing the optimization of the
physical resources.
Disabled
Blocking
Listening
Learning
Forwarding
Figura 5 - STP port states
4. Openflow
Openflow is a protocol that enables the implementation of SDN in different routers and switches.
It acts on both the control layer and the physical layer of the switch (datapath), making the
communication interface between them. Defines message streams according with rules defined
through some parameters such as the header fields of the packets, such as MAC address, IP
address, TCP / UDP ports. For these flows are defined actions like forward, drop, rewrite, or
"send to the controller".
As a result of tcpdump output, you can confirm that ARP is not looped.
● Node: s1:
mininet> h1 ping -c11 h2
mininet@mininet-vm:~$ sudo tcpdump -i s1-eth2 arp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on s1-eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
17:08:31.903268 ARP, Request who-has 10.0.0.2 tell 10.0.0.1, length 28
17:08:31.910437 ARP, Reply 10.0.0.2 is-at 3a:e8:46:c0:87:cc (oui Unknown), length 28
17:08:36.930603 ARP, Request who-has 10.0.0.1 tell 10.0.0.2, length 28
17:08:36.930723 ARP, Reply 10.0.0.1 is-at a2:8d:2e:9d:94:a3 (oui Unknown), length 28
● Node: s2:
ininet@mininet-vm:~$ sudo tcpdump -i s2-eth2 arp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on s2-eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
17:08:31.903274 ARP, Request who-has 10.0.0.2 tell 10.0.0.1, length 28
17:08:31.910431 ARP, Reply 10.0.0.2 is-at 3a:e8:46:c0:87:cc (oui Unknown), length
28
17:08:36.930593 ARP, Request who-has 10.0.0.1 tell 10.0.0.2, length 28
17:08:36.930726 ARP, Reply 10.0.0.1 is-at a2:8d:2e:9d:94:a3 (oui Unknown), length
28
● Node: s3:
mininet@mininet-vm:~$ sudo tcpdump -i s3-eth2 arp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on s3-eth2, link-type EN10MB (Ethernet), capture size 262144 bytes
17:08:31.906015 ARP, Request who-has 10.0.0.2 tell 10.0.0.1, length 28
You can confirm that the s3-eth2 port, which was in BLOCK state, became FORWARD state and
frame transfer became available again.
Figure 9 - Re-calculated network state after when a failure is detected
You can confirm that the tree structure becomes the same as that in effect when the application
starts and frame transfer becomes available again.
Next, let’s take a look at the source code of spanning tree implemented using Ryu. The spanning
tree source code is in the Ryu’s source tree.
● ryu/lib/stplib.py
stplib.py is a library that provides spanning tree functions such as BPDU packet
exchange and management of rules, and the status of each port.
● ryu/app/simple_switch_stp_13.py
The simple_switch_stp_13.py is an application program in which the spanning
tree function is added to the switching hub application using the spanning tree
library.
1. Implementing the Library
Library Overview
When the STP library (Stp class instance) detects connection of an OpenFlow switch to the
controller, a Bridge class instance and Port class instance are generated.
After each class instance is generated and started, three types of events are monitored:
● Notification of the OpenFlow message reception from the Stp class instance
● STP calculation of the Bridge class instance (loot bridge selection and selection of the
role of each port)
● Status change of the port of the Port class instance and send/receive of BPDU packets
work together to achieve the spanning tree function.
● port
Sending BDPU Packet
Detecting Failures
STP Calculation
Setting “_CONTEXTS”
A Ryu application that inherits ryu.base.app_manager.RyuApp starts other applications using
separate threads by setting other Ryu applications in the “_CONTEXTS” dictionary. Here, the Stp
class of the STP library is set in “_CONTEXTS” in the name of ” stplib”.
Applications set in “_CONTEXTS” can acquire instances from the kwargs of the __init__()
method.
Setting Configuration
Use the set_config() method of the STP library to set configuration. Here, the following
values are set as a sample.
Using these settings, the bridge ID of the dpid=0000000000000001 OpenFlow switch is always
the smallest value and is selected as the root bridge.
By using the stplib.EventPacketIn event defined in the STP library, it is possible to receive
packets other than BPDU packets
@set_ev_cls(stplib.EventPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
@set_ev_cls(stplib.EventTopologyChange, MAIN_DISPATCHER)
def _topology_change_handler(self, ev):
dp = ev.dp
dpid_str = dpid_lib.dpid_to_str(dp.id)
msg = 'Receive topology change event. Flush MAC table.'
self.logger.debug("[dpid=%s] %s", dpid_str, msg)
if dp.id in self.mac_to_port:
self.delete_flow(dp)
del self.mac_to_port[dp.id]
@set_ev_cls(stplib.EventPortStateChange, MAIN_DISPATCHER)
def _port_state_change_handler(self, ev):
dpid_str = dpid_lib.dpid_to_str(ev.dp.id)
of_state = {stplib.PORT_STATE_DISABLE: 'DISABLE',
stplib.PORT_STATE_BLOCK: 'BLOCK',
stplib.PORT_STATE_LISTEN: 'LISTEN',
stplib.PORT_STATE_LEARN: 'LEARN',
stplib.PORT_STATE_FORWARD: 'FORWARD'}
self.logger.debug("[dpid=%s][port=%d] state=%s",
dpid_str, ev.port_no, of_state[ev.port_state])