如何解决将学习开关添加到 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 举报,一经查实,本站将立刻删除。