ufes-20191-redes-mininet/ex01/l2-verb.py

60 lines
2.3 KiB
Python

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
class L2Switch(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
self.mac_to_port = dict()
def add_flow(self, datapath, in_port, dst, src, actions):
ofp = datapath.ofproto
match = datapath.ofproto_parser.OFPMatch(
in_port=in_port,
dl_dst=haddr_to_bin(dst), dl_src=haddr_to_bin(src))
mod = datapath.ofproto_parser.OFPFlowMod(
datapath=datapath, match=match, cookie=0,
command=ofp.OFPFC_ADD, idle_timeout=3, hard_timeout=9,
priority=ofp.OFP_DEFAULT_PRIORITY,
flags=ofp.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
dp = msg.datapath
ofp = dp.ofproto
ofp_parser = dp.ofproto_parser
# adding some verbose messages
pkt = packet.Packet(msg.data)
eth = pkt.get_protocol(ethernet.ethernet)
self.logger.info("src mac-port: %s-%s", eth.src, msg.in_port)
self.logger.info("dst mac: %s", eth.dst)
# end verbose
# learn mac address for later
if dp.id not in self.mac_to_port:
self.mac_to_port[dp.id] = dict()
self.mac_to_port[dp.id][eth.src] = msg.in_port
# use previous knowledge (if available)
out_port = self.mac_to_port.get(dp.id, dict()).get(eth.dst, ofp.OFPP_FLOOD)
# send the package
actions = [ofp_parser.OFPActionOutput(out_port)]
out = ofp_parser.OFPPacketOut(
datapath=dp, buffer_id=msg.buffer_id,
in_port=msg.in_port, actions=actions)
dp.send_msg(out)
# save path in routing table for later
if out_port != ofp.OFPP_FLOOD:
self.add_flow(dp, msg.in_port, eth.dst, eth.src, actions)