我正在尝试在我的Ryu脚本(在get_topology
方法中)实现SDN FlowCover算法。任何人都可以帮助实现那些可以在Mininet中运行的Python吗?
您可以在此处查看算法:https://arxiv.org/pdf/1710.05697
这是我的Ryu脚本:
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER, DEAD_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,ipv4
from ryu.lib import hub
from ryu.lib import mac
import copy,itertools
from ryu.topology import event, switches
from ryu.topology.api import get_switch, get_link
import networkx as nx
time_to_collect=10
class SimpleSwitch13(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(SimpleSwitch13, self).__init__(*args, **kwargs)
self.net=nx.DiGraph()
self.all_pair_shortest_path={}
@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
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath, 0, match, actions)
def add_flow(self, dp, p, match, actions, idle_timeout=0, hard_timeout=0,table=0):
ofproto = dp.ofproto
parser = dp.ofproto_parser
inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
actions)]
mod = parser.OFPFlowMod(datapath=dp, priority=p,
idle_timeout=idle_timeout,
hard_timeout=hard_timeout,
match=match, instructions=inst,table_id=table)
dp.send_msg(mod)
def get_shortestPath(self,edges,src,dst):
path=nx.shortest_path(self.net,src,dst)
edges_used = self.pairwise(path)
edges_remain = set(edges) - set(edges_used)
edges_remain = list(edges_remain)
newgraph = nx.DiGraph()
newgraph.add_edges_from(edges_remain)
path2=nx.shortest_path(newgraph,src,dst)# compute second shortest path
return path,path2
def pairwise(self,l):#compute pairwise by given a path list
result = []
for i in range(len(l)):
start = l[i]
end = l[i+1]
result.append((start,end))
if end == l[-1]:
break
return result
def getall_pair_shortest_path(self):
self.all_pair_shortest_path={}
edges=self.net.edges()
edges=set(edges)
edges=list(edges)
nodes=self.net.nodes
nodes=set(nodes)
nodes=list(nodes)
pairs=set(itertools.product(nodes, nodes))
for pair in pairs:
src,dst=pair
try:
if src!=dst:
path,path2=self.get_shortestPath(edges,src,dst)
self.all_pair_shortest_path[pair]=[path,path2]
except:
pass
events = [event.EventSwitchEnter,
event.EventSwitchLeave, event.EventPortAdd,
event.EventLinkAdd]
@set_ev_cls(events)
def get_topology(self, ev):
self.net=nx.DiGraph()
links = copy.copy(get_link(self, None))
edges_list=[] # extra list item for constructing nx graph
if len(links)>0:
for link in links:
src = link.src
dst = link.dst
edges_list.append((src.dpid,dst.dpid,{'port':src.port_no}))
self.net.add_edges_from(edges_list)
self.getall_pair_shortest_path()
def send_group_mod(self,datapath,group_id,watch_port1,out_port1,watch_port2,out_port2):
ofp = datapath.ofproto
ofp_parser = datapath.ofproto_parser
actions1 = [ofp_parser.OFPActionOutput(out_port1)]
actions2 = [ofp_parser.OFPActionOutput(out_port2)]
weight = 0
buckets = [ofp_parser.OFPBucket(weight,watch_port1,ofp.OFPG_ANY,actions1),ofp_parser.OFPBucket(weight,watch_port2,ofp.OFPG_ANY,actions2)]
req = ofp_parser.OFPGroupMod(datapath,ofp.OFPGC_ADD,ofp.OFPGT_FF,group_id,buckets)
datapath.send_msg(req)
def build_flow(self, msg,priority, flow_info, src_port, out_port1,out_port2):
datapath=msg.datapath
parser = datapath.ofproto_parser
actions = []
if out_port2:# if no dst_port2 is supplied meaning that its not group entry
group_id = int(flow_info[2].split('.')[3])-1
self.send_group_mod(datapath,group_id,out_port1,out_port1,out_port2,out_port2)
actions.append(parser.OFPActionGroup(group_id))
else:
actions.append(parser.OFPActionOutput(out_port1))
match = parser.OFPMatch(
in_port=src_port, eth_type=flow_info[0],
ipv4_src=flow_info[1], ipv4_dst=flow_info[2])
self.add_flow(datapath, priority, match, actions,
idle_timeout=100,
hard_timeout=100,table=0)
out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, data=msg.data, in_port=src_port, actions=actions)
datapath.send_msg(out)
def shortest_forwarding(self, msg, eth_type, ip_src, ip_dst):
datapath = msg.datapath
ofproto = datapath.ofproto
parser = datapath.ofproto_parser
in_port = msg.match['in_port']
flow_info = (eth_type, ip_src, ip_dst, in_port)
back_info = (flow_info[0], flow_info[2], flow_info[1])
src_sw=int(ip_src.split('.')[3])
dst_sw=int(ip_dst.split('.')[3])
curr_sw=datapath.id
if curr_sw!=dst_sw:
path,backup_path=self.all_pair_shortest_path[(curr_sw,dst_sw)]
print path,backup_path
next_sw_in_path=path[path.index(curr_sw)+1]
next_sw_in_backuppath=backup_path[backup_path.index(curr_sw)+1]
out_port1=self.net[curr_sw][next_sw_in_path]['port']
out_port2=self.net[curr_sw][next_sw_in_backuppath]['port']
self.build_flow(msg,1, flow_info, in_port, out_port1, out_port2)
else:
out_port=1
self.build_flow(msg,1, flow_info, in_port, out_port,False)
return
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def _packet_in_handler(self, ev):
"""
"""
msg = ev.msg
datapath = msg.datapath
in_port = msg.match['in_port']
pkt = packet.Packet(msg.data)
ip_pkt = pkt.get_protocol(ipv4.ipv4)
if isinstance(ip_pkt, ipv4.ipv4):
if ip_pkt.src == '0.0.0.0':
return
if len(pkt.get_protocols(ethernet.ethernet)):
eth_type = pkt.get_protocols(ethernet.ethernet)[0].ethertype
self.shortest_forwarding(msg, eth_type, ip_pkt.src, ip_pkt.dst)
def _build_packet_out(self, datapath, buffer_id, src_port, dst_port, data):
actions = []
if dst_port:
actions.append(datapath.ofproto_parser.OFPActionOutput(dst_port))
msg_data = None
if buffer_id == datapath.ofproto.OFP_NO_BUFFER:
if data is None:
return None
msg_data = data
out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id,data=msg_data, in_port=src_port, actions=actions)
return out
def send_packet_out(self, datapath, buffer_id, src_port, dst_port, data):
out = self._build_packet_out(datapath, buffer_id,src_port, dst_port, data)
if out:
datapath.send_msg(out)
预期输出:
需要监控交换机:[6,5,21,7,17,19,14,15,22,3,12,24,10,1,11]
总共15个开关 FlowCover计算时间:10.6439590454