arhue1431 / DCCCTEST

0 stars 0 forks source link

ryunew #3

Open arhue1431 opened 4 years ago

arhue1431 commented 4 years ago

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 from ryu.app import simple_switch_13

class SimpleSwitch13(simple_switch_13.SimpleSwitch13): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] _CONTEXTS = {'stplib': stplib.Stp}

def __init__(self, *args, **kwargs):
    super(SimpleSwitch13, self).__init__(*args, **kwargs)
    self.mac_to_port = {}
    self.stp = kwargs['stplib']

    # stp configuration for 4 bridges and ports per bridge
    config = {dpid_lib.str_to_dpid('0000000000000001'):
              {'bridge': {'priority': 0x8000}
               'ports': {1, 2, 3}},
              dpid_lib.str_to_dpid('0000000000000002'):
              {'bridge': {'priority': 0x9000}
               'ports': {1, 2, 3}},
              dpid_lib.str_to_dpid('0000000000000003'):
              {'bridge': {'priority': 0xa000}
               'ports': {1, 2, 3}},
              dpid_lib.str_to_dpid('0000000000000004'):
              {'bridge': {'priority': 0xb000'ports': {1, 2, 3}}}}
    self.stp.set_config(config)

#if topology changes
def delete_flow(self, datapath):
    ofproto = datapath.ofproto
    parser = datapath.ofproto_parser

    for dst in self.mac_to_port[datapath.id].keys():
        match = parser.OFPMatch(eth_dst=dst)
        mod = parser.OFPFlowMod(
            datapath, command=ofproto.OFPFC_DELETE,
            out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY,
            priority=1, match=match)
        datapath.send_msg(mod)

#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)

#packet in event
@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']

    #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

    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)
        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)
    #if the packet comes from H2 or H4 with HTTP destination - TCP RST sent back
    else if ((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)
        print("TCP REJECT")

    #if packet comes from H1 or H4 and is a UDP packet - drop it
    else if ((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.OFPAction(drop)]
        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)

        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

    #return packet
    out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions, data=data)
    datapath.send_msg(out)

@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])