微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将学习开关添加到 Ryu 控制器的现有 Python 应用程序

如何解决将学习开关添加到 Ryu 控制器的现有 Python 应用程序

我有以下 python 应用程序,它计算数据包并启动反措施,我正在尝试将可以在帖子底部看到的学习开关应用程序实现到这个应用程序的正下方:

从控制器导入SDNApplication

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
import ryu.ofproto.ofproto_v1_3_parser as parser
import ryu.ofproto.ofproto_v1_3 as ofproto
from ryu.lib.packet import packet
from ryu.lib.packet import ether_types
from ryu.lib.packet import ethernet,arp,ipv4,ipv6
from netaddr import IPAddress,IPNetwork


class DemoApplication(SDNApplication):
    """ A demonstration of a basic controller application
        Helper functions are provided by the super class
        SDNApplication (which can be found in controller.py)
    """
    def __init__(self,*args,**kwargs):
        super(DemoApplication,self).__init__(*args,**kwargs)
        self.info("Demo Application")      
        self.total_packets = 0
        self.packets_by_ip = dict()

    @set_ev_cls(ofp_event.EventOFPPacketIn,MAIN_disPATCHER)
    def packet_in_handler(self,ev):
               
        msg = ev.msg
        datapath = msg.datapath        
        data = msg.data      
        ofproto = datapath.ofproto       
        in_port = msg.match["in_port"]
      
        pkt = packet.Packet(data)     
        eth = pkt.get_protocol(ethernet.ethernet)

        if eth.ethertype == ether_types.ETH_TYPE_ARP:           
            self.handle_arp(datapath,in_port,eth,data)
            return       
        ip = pkt.get_protocol(ipv4.ipv4)

        if ip is None:            
            return

        if self.protect_our_network(datapath,ip.src,ip.dst):
            return

        self.total_packets += 1

       IPNetwork("0.0.0.0/0")
        traffic_type = ""

        if IPAddress(ip.dst) in our_address_range and in_port != 1:
            traffic_type = "ingress"

            # Flood the message on all ports.
            self.send_pkt(datapath,data,port = ofproto.OFPP_FLOOD)
        elif IPAddress(ip.src) in our_address_range and in_port == 1:
            traffic_type = "egress"

            # Flood the message on all ports.
            self.send_pkt(datapath,port = ofproto.OFPP_FLOOD)
        else:           
            traffic_type = "transit"

        print(".. total messages received: {:d} ({:s} traffic)".format(
            self.total_packets,traffic_type
        ))

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONfig_disPATCHER)   
        pass

    def protect_our_network(self,datapath,src_ip,dst_ip):       
       
        if not src_ip in self.packets_by_ip:
            self.packets_by_ip[src_ip] = 0

        self.packets_by_ip[src_ip] += 1

        if in_port != 1:
            if self.packets_by_ip[src_ip] == 10:               
                self.launch_countermeasures(datapath,src_ip)
                return True

            if self.packets_by_ip[src_ip] > 10:
              
                return True

        if in_port == 1 and self.packets_by_ip.get(dst_ip,0) > 10:
            return True

        return False

    def launch_countermeasures(self,src_ip):       
        match = parser.OFPMatch(
            eth_type = ether_types.ETH_TYPE_IP,ipv4_src = src_ip
        )

            self.set_flow(datapath,match,[],priority = 2)

        warn  = "   WARNING! Traffic limit exceeded for IP {:s}!".format(src_ip)
        warn += " Dropping packets!"

        print(warn)

    def handle_arp(self,data):       
        ofproto = datapath.ofproto

        dst = eth.dst
        src = eth.src

        match = parser.OFPMatch(
            eth_type = ether_types.ETH_TYPE_ARP,eth_dst = src
        )      
        self.set_flow(datapath,[parser.OFPActionOutput(in_port)],priority = 1)
      
        self.send_pkt(datapath,port = ofproto.OFPP_FLOOD)

如何将以下学习开关添加到上述应用程序中?:

    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


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

    def __init__(self,**kwargs):
        super(ExampleSwitch13,**kwargs)
        # initialize mac address table.
        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 the table-miss flow entry.
        match = parser.OFPmatch()
        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]
        self.add_flow(datapath,actions)

    def add_flow(self,priority,actions):
        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)

    @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

        # get Datapath ID to identify OpenFlow switches.
        dpid = datapath.id
        self.mac_to_port.setdefault(dpid,{})

        # analyse the received packets using the packet library.
        pkt = packet.Packet(msg.data)
        eth_pkt = pkt.get_protocol(ethernet.ethernet)
        dst = eth_pkt.dst
        src = eth_pkt.src

        # get the received port number from packet_in message.
        in_port = msg.match['in_port']

        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 the destination mac address is already learned,# decide which port to output the packet,otherwise FLOOD.
        if dst in self.mac_to_port[dpid]:
            out_port = self.mac_to_port[dpid][dst]
        else:
            out_port = ofproto.OFPP_FLOOD

        # construct action list.
        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,actions)

        # construct packet_out message and send it.
        out = parser.OFPPacketout(datapath=datapath,buffer_id=ofproto.OFP_NO_BUFFER,in_port=in_port,actions=actions,data=msg.data)
        datapath.send_msg(out)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。