-
Notifications
You must be signed in to change notification settings - Fork 4
/
controller.py
79 lines (65 loc) · 2.97 KB
/
controller.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# -*- coding: utf-8 -*-
"""
Ryu Tutorial Controller
This controller allows OpenFlow datapaths to act as Ethernet Hubs. Using the
tutorial you should convert this to a layer 2 learning switch.
See the README for more...
"""
from os_ken.base.app_manager import OSKenApp
from os_ken.controller import ofp_event
from os_ken.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER, set_ev_cls
from os_ken.ofproto import ofproto_v1_3
from os_ken.lib.packet import packet
from os_ken.lib.dpid import dpid_to_str
class Controller(OSKenApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(Controller, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def features_handler(self, ev):
'''
Handshake: Features Request Response Handler
Installs a low level (0) flow table modification that pushes packets to
the controller. This acts as a rule for flow-table misses.
'''
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)]
self.logger.info("Handshake taken place with {}".format(dpid_to_str(datapath.id)))
self.__add_flow(datapath, 0, match, actions)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
'''
Packet In Event Handler
Takes packets provided by the OpenFlow packet in event structure and
floods them to all ports. This is the core functionality of the Ethernet
Hub.
'''
msg = ev.msg
datapath = msg.datapath
ofproto = msg.datapath.ofproto
parser = msg.datapath.ofproto_parser
dpid = msg.datapath.id
pkt = packet.Packet(msg.data)
in_port = msg.match['in_port']
data = msg.data if msg.buffer_id == ofproto.OFP_NO_BUFFER else None
actions = [datapath.ofproto_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data)
self.logger.info("Sending packet out")
datapath.send_msg(out)
return
def __add_flow(self, datapath, priority, match, actions):
'''
Install Flow Table Modification
Takes a set of OpenFlow Actions and a OpenFlow Packet Match and creates
the corresponding Flow-Mod. This is then installed to a given datapath
at a given priority.
'''
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
mod = parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst)
self.logger.info("Flow-Mod written to {}".format(dpid_to_str(datapath.id)))
datapath.send_msg(mod)