Skip to content

Instantly share code, notes, and snippets.

@andreybleme
Last active June 30, 2021 03:21
Show Gist options
  • Save andreybleme/02d8cf321554cb90e6a1cda0a3834881 to your computer and use it in GitHub Desktop.
Save andreybleme/02d8cf321554cb90e6a1cda0a3834881 to your computer and use it in GitHub Desktop.
Ryu Controller to install flows in L2 switches - Network Systems DCC/UFMG (student Lucas Andrey Caldeira Bleme), prof Marcos Augusto Menezes Vieira
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_0
from ryu.lib.mac import haddr_to_bin
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types
from topology import load_topology
import networkx as nx
# This function takes as input a networkx graph. It then computes
# the minimum Spanning Tree, and returns it, as a networkx graph.
def compute_spanning_tree(G):
# The Spanning Tree of G
ST = nx.minimum_spanning_tree(G)
return ST
class L2Forwarding(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(L2Forwarding, self).__init__(*args, **kwargs)
# Load the topology
topo_file = 'topology.txt'
self.G = load_topology(topo_file)
# For each node in the graph, add an attribute mac-to-port
for n in self.G.nodes():
self.G.add_node(n, mactoport={})
# Compute a Spanning Tree for the graph G
self.ST = compute_spanning_tree(self.G)
print self.get_str_topo(self.G)
print self.get_str_topo(self.ST)
def add_flow(self, datapath, in_port, dst, src, actions):
match = datapath.ofproto_parser.OFPMatch(
in_port=in_port,
dl_dst=haddr_to_bin(dst), dl_src=haddr_to_bin(src))
oflow_proto = datapath.ofproto
mod = datapath.ofproto_parser.OFPFlowMod(
datapath = datapath, match = match, cookie = 0,
command = oflow_proto.OFPFC_ADD, idle_timeout = 0, hard_timeout = 0,
priority = oflow_proto.OFP_DEFAULT_PRIORITY,
flags = oflow_proto.OFPFF_SEND_FLOW_REM, actions = actions)
datapath.send_msg(mod)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
msg = ev.msg
datapath = msg.datapath
oflow_proto = datapath.ofproto
pkt = packet.Packet(msg.data)
eth = pkt.get_protocol(ethernet.ethernet)
dst = eth.dst
src = eth.src
dpid = datapath.id
self.mac_to_port.setdefault(dpid, {})
self.logger.info("-- packet in --")
# learn the mac address
self.mac_to_port[dpid][src] = msg.in_port
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = oflow_proto.OFPP_FLOOD
actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]
# install the flow to avoid repeated packet_in
if out_port != oflow_proto.OFPP_FLOOD:
self.add_flow(datapath, msg.in_port, dst, src, actions)
data = None
if msg.buffer_id == oflow_proto.OFP_NO_BUFFER:
data = msg.data
out = datapath.ofproto_parser.OFPPacketOut(
datapath = datapath, buffer_id = msg.buffer_id, in_port = msg.in_port,
actions = actions, data = data)
datapath.send_msg(out)
@set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
def _port_status_handler(self, ev):
msg = ev.msg
reason = msg.reason
port = msg.desc.port_no
oflow_proto = msg.datapath.ofproto
if reason == oflow_proto.OFPPR_ADD:
self.logger.info("-- added port %s", port)
elif reason == oflow_proto.OFPPR_DELETE:
self.logger.info("-- deleted port %s", port)
elif reason == oflow_proto.OFPPR_MODIFY:
self.logger.info("-- modified port %s", port)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment