from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from ryu.lib import dpid as dpid_lib
from ryu.lib import stplib
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import tcp
from ryu.lib.packet import udp
from ryu.lib.packet import icmp
from ryu.lib.packet import ipv4
class SimpleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(SimpleSwitch13, self).__init__(*args, **kwargs)
self.mac_to_port = {}
#used in TCP RST
def _send_packet(self,datapath,port,pkt):
ofproto=datapath.ofproto
parser=datapath.ofproto_parser
pkt.serialize()
self.logger.info("packet-out %s" % (pkt,))
data=pkt.data
actions= [parser.OFPActionOutput(port=port)]
out = parser.OFPPacketOut(datapath=datapath, bufffer_id=ofproto.OFP_NO_BUFFER, in_port=ofproto.OFPP_CONTROLLER, actions=actions,data=data)
datapath.send_msg(out)
#switch connected event
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_features_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
#table-miss entry
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
def add_flow(self, datapath, priority, match, actions,buffer_id=None):
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
# construct flow_mod message and send it.
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
actions)]
mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
match=match, instructions=inst)
datapath.send_msg(mod)
#packet in event
@set_ev_cls(ofp_event.EventOFPPacketIn, 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']
#get packet protocol information
pkt = packet.Packet(msg.data)
eth = pkt.get_protocols(ethernet.ethernet)
tcp = pkt.get_protocols(tcp.tcp)
udp = pkt.get_protocols(udp.udp)
icmp= pkt.get_protocols(icmp.icmp)
ip=pk.get_protocols(ipv4.ip4)
#mac addresses
dst = eth.dst
src = eth.src
#tcp and udp dst ports
tcp_dst=tcp.dst_port
udp_dst=udp.dst_port
#ip addresses and protocol numbers
src_ip=ip.src
dst_ip=ip.dst
protocol=ip.proto
in_port=msg.match['in_port']
dpid = datapath.id
self.mac_to_port.setdefault(dpid, {})
self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)
# cases where path costs are the same (S1 and S3) or (S2 and S4)
if ((src_ip=='10.0.0.1' and dst_ip == '10.0.0.3' )or (dst_ip=='10.0.0.1' and src_ip == '10.0.0.3') or (src_ip=='10.0.0.2' and dst_ip == '10.0.0.4') or (src_ip=='10.0.0.4' and dst_ip == '10.0.0.2')):
if (protocol==1 or protocol==6): #for tcp and icmp match clockwise - port 2 sends clockwise for all switches
match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
actions= [parser.OFPAction(out_port=2)]
self.add_flow(datapath, 1, match, actions, msg.buffer_id)
if (protocol==17): #for udp send counter clockwise - port 3 sends counterclockwise for all switches
actions=[parser.OFPAction(out_port=3)]
self.add_flow(datapath, 1, match, actions, msg.buffer_id)
#if the packet comes from H2 or H4 with HTTP destination - TCP RST sent back
elif ((src_ip=='10.0.0.2' or src_ip=='10.0.0.4') and tcp_dst==80):
#RST packet
mypkt= packet.Paket()
mypkt.add_protocol(ethernet.ethernet(ethertype=eth.ethertype,src=dst,dst=src))
mypkt.add_protocol(ipv4.ipv4(src=ip.dst,dst=ip.src,proto=6))
mypkt.add_protocol(tcp.tcp(srp_port=tcp.dst_port,dst_port=tcp.src_port,ack=tcp.seq+1,bits=0b010100))
self._send_packet(datapath, in_port, mypkt,msg.buffer_id)
print("TCP REJECT")
#if packet comes from H1 or H4 and is a UDP packet - drop it
elif ((src_ip=='10.0.0.1' or src_ip=='10.0.0.4') and protocol==17):
match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
actions[parser.OFPActionInstructionActions(proto.OFPIT_CLEAR_ACTIONS, [])]
self.add_flow(datapath,1,match,actions)
else:
# learn a mac address - set up STP
self.mac_to_port[dpid][src] = in_port
if dst in self.mac_to_port[dpid]:
out_port = self.mac_to_port[dpid][dst]
else:
out_port = ofproto.OFPP_FLOOD
actions = [parser.OFPActionOutput(out_port)]
# install a flow to avoid packet_in next time
if out_port != ofproto.OFPP_FLOOD:
match = parser.OFPMatch(in_port=in_port, eth_dst=dst)
self.add_flow(datapath, 1, match, actions,msg.buffer_id)
#return packet
out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data)
from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER from ryu.controller.handler import set_ev_cls from ryu.ofproto import ofproto_v1_3 from ryu.lib import dpid as dpid_lib from ryu.lib import stplib from ryu.lib.packet import packet from ryu.lib.packet import ethernet from ryu.lib.packet import tcp from ryu.lib.packet import udp from ryu.lib.packet import icmp from ryu.lib.packet import ipv4
class SimpleSwitch13(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]