【无标题】

ryu controller

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.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types
from ryu.lib.packet import arp
from ryu.lib.packet import ipv4
from ryu.lib.packet import tcp
from ryu.lib.packet import icmp
from ryu.lib.packet import udp


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 = {}
        self.mac_to_port["10.0.0.1"] = "10:00:00:00:00:01"
        self.mac_to_port["10.0.0.2"] = "10:00:00:00:00:02"
        self.mac_to_port["10.0.0.3"] = "10:00:00:00:00:03"
        self.mac_to_port["10.0.0.4"] = "10:00:00:00:00:04"

    @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

        # install table-miss flow entry
        #
        # We specify NO BUFFER to max_len of the output action due to
        # OVS bug. At this moment, if we specify a lesser number, e.g.,
        # 128, OVS will send Packet-In with invalid buffer_id and
        # truncated packet data. In that case, we cannot output packets
        # correctly.  The bug has been fixed in OVS v2.1.0.
        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

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]
        if buffer_id:
            mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
                                    priority=priority, match=match,
                                    instructions=inst)
        else:
            mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
                                    match=match, instructions=inst)
        datapath.send_msg(mod)



    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch

        if ev.msg.msg_len < ev.msg.total_len:
            self.logger.debug("packet truncated: only %s of %s bytes",
                              ev.msg.msg_len, ev.msg.total_len)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return
        dst = eth.dst
        src = eth.src
        dpid = format(datapath.id, "d").zfill(16)

        self.mac_to_port.setdefault(dpid, {})


        self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)


        # ARP
        pk_arp = pkt.get_protocol(arp.arp)
        if pk_arp:

            Arpmac = self.mac_to_port[pk_arp.dst_ip]
            eth_header = ethernet.ethernet(dst=eth.src, src=Arpmac, ethertype=eth.ethertype)
            arp_header = arp.arp(opcode=2, src_mac=Arpmac,
                                 src_ip=pk_arp.dst_ip, dst_mac=eth.src, dst_ip=pk_arp.src_ip)
            reply = packet.Packet()
            reply.add_protocol(eth_header)
            reply.add_protocol(arp_header)

            self._send_packet(datapath, 1, reply)
            print("there is the arp packet::::::::::")

        # IP layer
        pkt_ip = pkt.get_protocol(ipv4.ipv4)
        if pkt_ip:
            src_ip = pkt_ip.src
            dst_ip = pkt_ip.dst
            # tcp packet
            pkt_tcp = pkt.get_protocol(tcp.tcp)
            if pkt_tcp:
                # http packet
                if (datapath.id == 2 or datapath.id == 4) and (pkt_tcp.dst_port == 80) and (in_port == 1):
                    eth_header = ethernet.ethernet(dst=eth.src, src=eth.dst, ethertype=eth.ethertype)
                    ip_header = ipv4.ipv4(src=dst_ip, dst=src_ip, proto=6)
                    tcp_header = tcp.tcp(src_port=pkt_tcp.dst_port, dst_port=pkt_tcp.src_port, ack=pkt_tcp.seq + 1,
                                         bits=0b010100)

                    reply = packet.Packet()
                    reply.add_protocol(eth_header)
                    reply.add_protocol(ip_header)
                    reply.add_protocol(tcp_header)
                    # reply.serialize()
                    print("drop http packet at switch 2 or 4 :::::::")
                    self._send_packet(datapath, in_port, reply)
                # tcp packet
                else:
                    out_port = self._cal_out_port(src, dst, 6, datapath.id)
                    match = parser.OFPMatch(eth_type = 0x0800,ip_proto = 6, ipv4_dst = dst_ip, tcp_dst = pkt_tcp.dst_port)
                    actions = [parser.OFPActionOutput(port = out_port)]
                    self.add_flow(datapath, 500, match, actions)
                    print("send udp packet:::::::::::")
                    self._send_packet(datapath, out_port, pkt)
            # icmp pakcet
            pkt_icmp = pkt.get_protocol(icmp.icmp)
            if pkt_icmp:
                out_port = self._cal_out_port(src, dst, 1, datapath.id)
                match = parser.OFPMatch(eth_type = 0x0800, ip_proto = 1, ipv4_dst = dst_ip)
                actions = [parser.OFPActionOutput(port = out_port)]
                self.add_flow(datapath, 500, match, actions)
                print("send icmp packet::::::::::::")
                self._send_packet(datapath, out_port, pkt)
            # udp packet
            pkt_udp = pkt.get_protocol(udp.udp)
            # udp drop at switch 1 and 4
            if pkt_udp:
                if (datapath.id == 1 or datapath.id == 4) and (in_port == 1):
                    # out_port = self._cal_out_port(src, dst, pkt_ip.proto, datapath.id, in_port)
                    match = parser.OFPMatch(eth_type=0x0800, ip_proto=17, ipv4_dst=dst_ip)
                    actions = []
                    # inst = [parser.OFPInstructionActions(ofproto.OFPIT_CLEAR_ACTIONS, actions)
                    print("drop udp packet at switch 1 or 4::::::::::::::")
                    self.add_flow(datapath,500, match, actions)
                #  udp
                else:
                    out_port = self._cal_out_port(src, dst, 17, datapath.id)
                    match = parser.OFPMatch(eth_type=0x0800, ip_proto=17, ipv4_dst=dst_ip)
                    actions = [parser.OFPActionOutput(port=out_port)]
                    self.add_flow(datapath, 500, match, actions)
                    print("send UDP packet:::::::::::::::")
                    self._send_packet(datapath, out_port, pkt)
    # send packet
    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, buffer_id=ofproto.OFP_NO_BUFFER, in_port=ofproto.OFPP_CONTROLLER,
                                  actions=actions, data=data)
        datapath.send_msg(out)
    # calculate the outport and the shortest path
    @staticmethod
    def _cal_out_port(src_id,dst_id,protocol,switch_id):
         out_port = 0
         dist = int(dst_id[-1]) - int(src_id[-1])
         if(switch_id != int(dst_id[-1])):
             if (abs(dist) == 2):
                 # icmp and TCP
                 if(protocol == 6 or protocol == 1):
                     out_port = 2
                 # udp
                 elif(protocol == 17):
                     out_port = 3
             # shortest path
             elif (dist == -1 or dist == 3):
                 out_port = 3
             elif (dist == 1 or dist == -3):
                 out_port = 2
         # destination
         else:
             out_port = 1
         return out_port



**

topology

**

"""
This setup the topology in lab4
"""

from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import Controller, RemoteController
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.util import dumpNodeConnections
from mininet.link import Link, Intf, TCLink
import os 
from time import sleep
import sys

class Topology(Topo):
    
    
    def __init__(self):
        "Create Topology."
        
        # Initialize topology
        Topo.__init__(self)
        
      
        # Add hosts
        host1 = self.addHost('h1', ip='10.0.0.1/24', mac='10:00:00:00:00:01')
        host2 = self.addHost('h2', ip='10.0.0.2/24', mac='10:00:00:00:00:02')
        host3 = self.addHost('h3', ip='10.0.0.3/24', mac='10:00:00:00:00:03')
        host4 = self.addHost('h4', ip='10.0.0.4/24', mac='10:00:00:00:00:04')
        
        
        # Add switches
        sw1 = self.addSwitch('s1')
        sw2 = self.addSwitch('s2')
        sw3 = self.addSwitch('s3')
        sw4 = self.addSwitch('s4')
        
        self.addLink(host1, sw1, 1, 1)
        self.addLink(host2, sw2, 1, 1)
        self.addLink(host3, sw3, 1, 1)
        self.addLink(host4, sw4, 1, 1)
        
        self.addLink(sw1, sw2, 2, 3)
        self.addLink(sw2, sw3, 2, 3)
        self.addLink(sw3, sw4, 2, 3)
        self.addLink(sw4, sw1, 2, 3)

        

# This is for "mn --custom"
topos = { 'mytopo': ( lambda: Topology() ) }
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.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types
from ryu.lib.packet import arp
from ryu.lib.packet import ipv4
from ryu.lib.packet import tcp
from ryu.lib.packet import udp
from ryu.lib.packet import icmp

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 = {}

    @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

        # install table-miss flow entry
        #
        # We specify NO BUFFER to max_len of the output action due to
        # OVS bug. At this moment, if we specify a lesser number, e.g.,
        # 128, OVS will send Packet-In with invalid buffer_id and
        # truncated packet data. In that case, we cannot output packets
        # correctly.  The bug has been fixed in OVS v2.1.0.
        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

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]
        if buffer_id:
            mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
                                    priority=priority, match=match,
                                    instructions=inst)
        else:
            mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
                                    match=match, instructions=inst)
        datapath.send_msg(mod)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch
        if ev.msg.msg_len < ev.msg.total_len:
            self.logger.debug("packet truncated: only %s of %s bytes",
                              ev.msg.msg_len, ev.msg.total_len)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

        if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            # ignore lldp packet
            return
        dst = eth.dst
        src = eth.src
        
        #modified content
        pkt_arp = pkt.get_protocol(arp.arp)
        pkt_ipv4 = pkt.get_protocol(ipv4.ipv4)
        pkt_icmp = pkt.get_protocol(icmp.icmp)
        pkt_tcp = pkt.get_protocol(tcp.tcp)
        pkt_udp = pkt.get_protocol(udp.udp)

        # ARP
        if pkt_arp:
            # dst_ip, dst_mac=ffffff
            mypkt = packet.Packet()
            mypkt.add_protocol(ethernet.ethernet(
                src=根据dst_ip得到的mac,
                dst=
            ))
            mypkt.add_protocol(arp.arp(
                src_mac=根据dst_ip得到的mac,
                dst_mac=,
                src_ip=,
                dst_ip=,
                opcode=
            ))
            self._send_msg(mypkt)
        # IPV4
        elif pkt_ipv4:
            # ICMP
            if pkt_icmp:
                # calc out port
                out_port =
                # add flow
                match = parser.OFPMatch()
                actions = [parser.OFPActionOutput(port=out_port)]
                self.add_flow(datapath, 1, match, actions)
                # send packet
                self._send_msg(datapath, pkt, out_port)
            # TCP
            elif pkt_tcp:
                # HTTP RST
                if pkt_tcp.dst_port == 80 and (HOST2 or HOST4):
                    # generate an HTTP RST packet
                    # send packet
                # NON-TCP HTTP
                else:
                    # calc out port
                    # add flow
                    # send packet
                    # add http flow
            # UDP
            elif pkt_udp:
                if HOST1 or HOST4:
                    # add drop flow
                else:
                    # calc out port
                    # add flow
                    # send packet





        dpid = format(datapath.id, "d").zfill(16)
        self.mac_to_port.setdefault(dpid, {})

        self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

        # learn a mac address to avoid FLOOD next time.
        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, eth_src=src)
            # verify if we have a valid buffer_id, if yes avoid to send both
            # flow_mod & packet_out
            if msg.buffer_id != ofproto.OFP_NO_BUFFER:
                self.add_flow(datapath, 1, match, actions, msg.buffer_id)
                return
            else:
                self.add_flow(datapath, 1, match, actions)
        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id,
                                  in_port=in_port, actions=actions, data=data)
        datapath.send_msg(out)
        
        def _send_msg(self,switch,pkt,outport):
            return 
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.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types
from ryu.lib.packet import arp
from ryu.lib.packet import ipv4
from ryu.lib.packet import tcp
from ryu.lib.packet import udp
from ryu.lib.packet import icmp


class SimpleSwitch13(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, *args, **kwargs):
        super(SimpleSwitch13, self).__init__(*args, **kwargs)

    @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

        # install table-miss flow entry
        #
        # We specify NO BUFFER to max_len of the output action due to
        # OVS bug. At this moment, if we specify a lesser number, e.g.,
        # 128, OVS will send Packet-In with invalid buffer_id and
        # truncated packet data. In that case, we cannot output packets
        # correctly.  The bug has been fixed in OVS v2.1.0.
        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):
        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)
        datapath.send_msg(mod)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']
        pkt = packet.Packet(msg.data)

        eth = pkt.get_protocol(ethernet.ethernet)

        dst = eth.dst
        src = eth.src

        pkt_arp = pkt.get_protocol(arp.arp)
        pkt_ipv4 = pkt.get_protocol(ipv4.ipv4)
        pkt_icmp = pkt.get_protocol(icmp.icmp)
        pkt_tcp = pkt.get_protocol(tcp.tcp)
        pkt_udp = pkt.get_protocol(udp.udp)

        # ARP
        if pkt_arp:
            # dst_ip, dst_mac=ffffff
            mypkt = packet.Packet()
            mypkt.add_protocol(ethernet.ethernet(
                src=根据dst_ip得到的mac,
                dst=
            ))
            mypkt.add_protocol(arp.arp(
                src_mac=根据dst_ip得到的mac,
                dst_mac=,
                src_ip=,
                dst_ip=,
                opcode=
            ))
            self._send_msg(mypkt)
        # IPV4
        elif pkt_ipv4:
            # ICMP
            if pkt_icmp:
                # calc out port
                out_port =
                # add flow
                match = parser.OFPMatch()
                actions = [parser.OFPActionOutput(port=out_port)]
                self.add_flow(datapath, 1, match, actions)
                # send packet
                self._send_msg(datapath, pkt, out_port)
            # TCP
            elif pkt_tcp:
                # HTTP RST
                if pkt_tcp.dst_port == 80 and (HOST2 or HOST4):
                    # generate an HTTP RST packet
                    # send packet
                # NON-TCP HTTP
                else:
                    # calc out port
                    # add flow
                    # send packet
                    # add http flow
            # UDP
            elif pkt_udp:
                if HOST1 or HOST4:
                    # add drop flow
                else:
                    # calc out port
                    # add flow
                    # send packet

    def _send_msg(self, switch, pkt, out_port):
        return
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.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import ether_types
from ryu.lib.packet import arp
from ryu.lib.packet import ipv4
from ryu.lib.packet import tcp
from ryu.lib.packet import udp
from ryu.lib.packet import icmp

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 = {}

    @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

        # install table-miss flow entry
        #
        # We specify NO BUFFER to max_len of the output action due to
        # OVS bug. At this moment, if we specify a lesser number, e.g.,
        # 128, OVS will send Packet-In with invalid buffer_id and
        # truncated packet data. In that case, we cannot output packets
        # correctly.  The bug has been fixed in OVS v2.1.0.
        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

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]
        if buffer_id:
            mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id,
                                    priority=priority, match=match,
                                    instructions=inst)
        else:
            mod = parser.OFPFlowMod(datapath=datapath, priority=priority,
                                    match=match, instructions=inst)
        datapath.send_msg(mod)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def _packet_in_handler(self, ev):
        # If you hit this you might want to increase
        # the "miss_send_length" of your switch
        if ev.msg.msg_len < ev.msg.total_len:
            self.logger.debug("packet truncated: only %s of %s bytes",
                              ev.msg.msg_len, ev.msg.total_len)
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        in_port = msg.match['in_port']

        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocols(ethernet.ethernet)[0]

	#handle the arp message
        pkt_arp = pkt.get_protocol(arp.arp)
        pkt_ipv4 = pkt.get_protocol(ipv4.ipv4)
        pkt_icmp = pkt.get_protocol(icmp.icmp)
        pkt_tcp = pkt.get_protocol(tcp.tcp)
        pkt_udp = pkt.get_protocol(udp.udp)

        dst = eth.dst
        src = eth.src
	

	#if eth.ethertype == ether_types.ETH_TYPE_LLDP:
            ## ignore lldp packet
            #return

	#ARP
        if pkt_arp:
                #do something
            print('[ARP] arrive at:','S'+ str(datapath.id)+',replied')
            dst_mac = '10:00:00:00:00:0'+ pkt_arp.dst_ip[-1]
            arp_response = packet.Packet()
            arp_response.add_protocol(ethernet.ethernet(
            ethertype=eth.ethertype,
            dst=pkt_arp.src_mac,
            src=dst_mac))
            arp_response.add_protocol(arp.arp(
            src_mac=dst_mac,
            dst_mac=pkt_arp.src_mac,
            src_ip=pkt_arp.dst_ip,
            dst_ip=pkt_arp.src_ip,
            opcode=arp.ARP_REPLY		
            ))
            self._send_packet(datapath,arp_response,in_port)
        # IPV4
        elif pkt_ipv4:
            # ICMP
            if pkt_icmp:
                # calc out port
                print('[ICMP] arrive at:','S'+ str(datapath.id)+',forwarded')
                src_id=int(src[-1])
                dst_id=int(dst[-1])
                protocol='ICMP'
                switch_id=datapath.id
                outport=self._calc_out_port(src_id,dst_id,protocol,switch_id,in_port)
                # add flow
                match = parser.OFPMatch(eth_src=src,eth_dst=dst,eth_type=0x0800,ip_proto=1)
                actions = [parser.OFPActionOutput(port=outport)]
                self.add_flow(datapath, 1, match, actions)
                actions = [parser.OFPActionOutput(port=outport)]
                self.add_flow(datapath, 1, match, actions)
                #send packet
                self._send_packet(datapath,pkt,outport)
            	
            # TCP
            elif pkt_tcp:
                # HTTP RST
                if pkt_tcp.dst_port == 80 and (datapath.id==2 or datapath.id==4) and in_port==1:
                    # generate an HTTP RST packet
                    # send packet
                    print('[HTTP] arrive at:','S'+ str(datapath.id)+',RST')
                    RST=packet.Packet()
                    RST.add_protocol(ethernet.ethernet(ethertype=eth.ethertype,src=dst,dst=src))
                    RST.add_protocol(ipv4.ipv4(src=pkt_ipv4.dst,dst=pkt_ipv4.src,proto=6))
                    RST.add_protocol(tcp.tcp(src_port=pkt_tcp.dst_port,dst_port=pkt_tcp.src_port,ack=pkt_tcp.seq+1,
                    bits=0b010100))
                    self._send_packet(datapath,RST,in_port)
                    print('TCP: reject connection')
                # NON-TCP HTTP
                else:
                    # calc out port
                    print('[TCP] arrive at:','S'+ str(datapath.id)+',forwarded')
                    src_id=int(src[-1])
                    dst_id=int(dst[-1])
                    protocol='TCP'
                    switch_id=datapath.id
                    outport=self._calc_out_port(src_id,dst_id,protocol,switch_id,in_port)
                    # add flow
                    match=parser.OFPMatch(eth_src=src,eth_dst=dst,eth_type=0x0800,ip_proto=pkt_ipv4.proto,in_port=in_port)
                    actions=[parser.OFPActionOutput(port=outport)]
                    self.add_flow(datapath,1,match,actions)
                    # send packet
                    self._send_packet(datapath,pkt,outport)
                    #add http flow
                    match=parser.OFPMatch(eth_src=src,tcp_dst=80,eth_type=0x0800,ip_proto=pkt_ipv4.proto,in_port=in_port)
                    actions=[parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]
                    self.add_flow(datapath,2,match,actions)
                   
            # UDP
            elif pkt_udp:
                    print('[UDP] arrive at:','S'+ str(datapath.id)+',forwarded')
                    src_id=int(src[-1])
                    dst_id=int(dst[-1])
                    protocol='UDP'
                    switch_id=datapath.id

                    if (datapath.id==1 or datapath.id==4) and in_port==1:
                    # calc out port
		    # outport=self._calc_out_port(src_id,dst_id,protocol,switch_id,in_port)

                    # add drop flow
                        match=parser.OFPMatch(eth_src=src,eth_dst=dst,in_port=in_port,ip_proto=pkt_ipv4.proto,eth_type=0x0800)
                        actions=[]
                        self.add_flow(datapath,1,match,actions)

                    else:
                    # calc out port
                        outport=self._calc_out_port(src_id,dst_id,protocol,switch_id,in_port)
                        # add flow
                        match=parser.OFPMatch(eth_src=src,eth_dst=dst,in_port=in_port,ip_proto=pkt_ipv4.proto,eth_type=0x0800)
                        actions=[parser.OFPActionOutput(port=outport)]
                        self.add_flow(datapath,1,match,actions)
                        # send packet
                        self._send_packet(datapath, pkt, outport)

    def _send_packet(self,datapath,pkt,out_port):
        ofproto=datapath.ofproto
        parser=datapath.ofproto_parser
        pkt.serialize()
        self.logger.info('packet-out %s'%(pkt,))
        data=pkt.data
        actions=[parser.OFPActionOutput(port=out_port)]
        out=parser.OFPPacketOut(datapath=datapath,buffer_id=ofproto.OFP_NO_BUFFER,in_port=ofproto.OFPP_CONTROLLER,actions=actions,data=data)
        datapath.send_msg(out)


    def _calc_out_port(self,src_id,dst_id,protocol,switch_id, in_port):
        if protocol == 'TCP' or protocol=='ICMP':
            if (src_id==1 and dst_id==3) or (src_id==2 and dst_id==4) or (src_id==3 and dst_id==1) or (src_id==4 and dst_id==2):
                if switch_id==dst_id:
                    out_port=1
                else:
                    out_port=2
            if (src_id==1 and dst_id==2) or (src_id==2 and dst_id==3) or (src_id==3 and dst_id==4) or (src_id==4 and dst_id==1):
                if switch_id==dst_id:
                    out_port=1
                else:
                    out_port=2
            if (src_id==2 and dst_id==1) or (src_id==3 and dst_id==2) or (src_id==4 and dst_id==3) or (src_id==1 and dst_id==4):
                if switch_id==dst_id:
                    out_port=1
                else:
                    out_port=3
        elif protocol=='UDP':
            if (src_id==1 and dst_id==3) or (src_id==2 and dst_id==4) or (src_id==3 and dst_id==1) or (src_id==4 and dst_id==2):
                if switch_id==dst_id:
                    out_port=1
                else:
                    out_port=3
            if (src_id==1 and dst_id==2) or (src_id==2 and dst_id==3) or (src_id==3 and dst_id==4) or (src_id==4 and dst_id==1):
                if switch_id==dst_id:
                    out_port=1
                else:
                    out_port=2
            if (src_id==2 and dst_id==1) or (src_id==3 and dst_id==2) or (src_id==4 and dst_id==3) or (src_id==1 and dst_id==4):
                if switch_id==dst_id:
                    out_port=1
                else:
                    out_port=3   
        return out_port
                

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值