RYU+Mininet实现Hub泛洪
系统:Ubuntu20.10 ,已安装 ryu 和 mininet
在ryu/ryu/app下创建了文件hub.py,代码如下:
hub.py(含注释)
from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3 #openflow版本:1.3
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER, CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
#定义一个类hub,继承app_manager,位于ryu下的base内,版本选择openflow1.3,然后初始化操作。
class hub(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]#定义版本
#类的初始化函数
def __init__(self, *args, **kwargs):#最后一个是可变参数#
super(hub, self).__init__(*args, **kwargs)
#在Ryu控制器上,我们需要写一个函数去处理openvswitch的连接,同时需要开启一个监听,监听交换机事件。
@set_ev_cls(ofp_event.EventOFPSwitchFeatures,CONFIG_DISPATCHER)
def switch_features_handler(self,ev):
#解析数据
#datapath如同数据平面的通道,可以等同于网桥
datapath = ev.msg.datapath
ofproto = datapath.ofproto#版本
ofp_parser = datapath.ofproto_parser#基于此版本的一些库类
#接收到交换机的连接之后,要下发一条tableentrys,一个默认流表,来指挥所有匹配不到交换机的数据,将其上传至控制器
#install the table miss flow entry,即在ryu控制器里安装流表项
#匹配域
match = ofp_parser.OFPMatch()
#动作域,OFPActionOutPut将数据包发送出去
#第一个参数:发送端口:控制器(把那些没有匹配的东西给控制器)
#第二个参数:数据包在交换机上缓存buffer_id,由于我们将数据包全部传送到控制器,所以不在交换机上缓存
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)]
self.add_flow(datapath,0,match,actions)
#提高代码重用,对于添加流表,单独拿出了写一个函数。
def add_flow(self,datapath,priority,match,actions):
#add a flow entry and install it into datapath
# 1\ datapath for the switch, 2\priority for flow entry, 3\match field, 4\action for packet
ofproto = datapath.ofproto
ofp_parser = datapath.ofproto_parser
#1.3版本交换机中需有指令
# install flow
# construct a flow_mod msg and sent it
inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]#inst指令的缩写
mod = ofp_parser.OFPFlowMod(datapath=datapath, priority=priority, match=match, instructions=inst)
datapath.send_msg(mod)
#需要定义packet in函数,用来处理交换机和控制器的流表交互,在执行之前需要先对packetin事件进行监听。
@set_ev_cls(ofp_event.EventOFPPackIn,MAIN_DISPATCHER)#MAIN_DISPATCHER:主状态下监听事件
def packet_in_handler(self,ev):
#数据解析
msg = ev.msg
datapath = msg.datapath
ofproto = datapath.ofproto
ofp_parser = datapath.ofproto_parser
#match匹配域中提取in_port
in_port = msg.match['in_port']
#发送出去(通过加一个流表)
#construct a flow entry
match = ofp_parser.OFPMatch()#匹配项为空,因为所有取到的内容都要泛洪出去
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]#泛洪动作
#调用添加流表的函数,把流表发送出去
# install flow mode to avoid match in next time
self.add_flow(datapath,1,match,actions)
#处理当下的pack_in,给他发出去
#buffer_id是一个非常重要的参数,因为,数据包进入交换机,总得有个地方暂存,而取的时候就需要有id来指定
# to output the current packet. for install rules only output later packets
out = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions)
# buffer id: locate the buffered packet
datapath.send_msg(out)
hub.py(建议使用此版本运行)
from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER, CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
class hub(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
def __init__(self, *args, **kwargs):
super(hub, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_feathers_handler(self, ev):
datapath = ev.msg.datapath
ofproto = datapath.ofproto
ofp_parser = datapath.ofproto_parser
# install flow table-miss flow entry
match = ofp_parser.OFPMatch()
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)]
# 1\OUTPUT PORT, 2\BUFF IN SWITCH?
self.add_flow(datapath, 0, match, actions)
def add_flow(self, datapath, priority, match, actions):
# 1\ datapath for the switch, 2\priority for flow entry, 3\match field, 4\action for packet
ofproto = datapath.ofproto
ofp_parser = datapath.ofproto_parser
# install flow
inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)]
mod = ofp_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
ofp_parser = datapath.ofproto_parser
in_port = msg.match['in_port'] # get in port of the packet
# add a flow entry for the packet
match = ofp_parser.OFPMatch()
actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]
self.add_flow(datapath, 1, match, actions)
# to output the current packet. for install rules only output later packets
out = ofp_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions)
# buffer id: locate the buffered packet
datapath.send_msg(out)
运行hub.py成功:
启动mininet ,创建一个最简单的拓扑,pingall命令成功:
说实话还没get到这个实验核心…还是很懵