SDN实验---Ryu的应用开发(一)Hub实现

13 篇文章 4 订阅
12 篇文章 1 订阅

1:集线器原理---设计解决方案

一个数据包从port1进入,会被复制,泛洪转发到其他所有端口发出

2:部署实施---Ryu控制器API学习和使用(Hub集线器开发)

        (一)代码实现

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_features_handler(self,ev):
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        match = ofp_parser.OFPMatch()
        actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]

        self.add_flow(datapath,0,match,actions,"default flow entry")

    def add_flow(self,datapath,priority,match,actions,remind_content):
        ofproto = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]

        mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority,
                                    match=match,instructions=inst);
        print("install to datapath,"+remind_content)
        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']

        print("get packet in, install flow entry,and lookback parket to datapath")
        
        match = ofp_parser.OFPMatch();
        actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]

        self.add_flow(datapath,1,match,actions,"hub flow entry")

        out = ofp_parser.OFPPacketOut(datapath=datapath,buffer_id=msg.buffer_id,
                                            in_port=in_port,actions=actions)    

        datapath.send_msg(out);

        (二)启动控制器

ryu-manager hub.py --verbose  #进入目录,在hub.py文件目录下  --verbose显示调试信息

        (三)启动Mininet进行连接测试

sudo mn --topo=linear,4 --controller=remote

openvswitch交换机与Ryu控制器连接,控制器下发默认流表,提示信息install to datapath,default flow entry

        (三)使用pingall命令,使得主机向交换机发送数据包---从而实现交换机上传数据包到控制器,实现流表获取

获取提示信息get packet in, install flow entry,and lookback parket to datapath

3:Hub代码讲解(注释版)

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):
    '''明确控制器所用OpenFlow版本'''
    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_features_handler(self,ev):
        '''
        在Ryu控制器上,我们需要写一个函数去处理openvswitch的连接
        CONFIG_DISPATCHER : Version negotiated and sent features-request message
        '''
        #对事件进行解析
        datapath = ev.msg.datapath    #从连接中获取数据平面的datapath数据结构
        ofproto = datapath.ofproto    #获取OpenFlow协议信息
        ofp_parser = datapath.ofproto_parser    #获取协议解析
        #解析完成

   '''在连接建立成功以后,需要控制器下发一个默认流表
           来指挥所有匹配不到交换机的数据,把他上传到控制器上
        '''

        #install the table-miss flow entry

        match = ofp_parser.OFPMatch()        #匹配域
        
        #OFPActionOutput将数据包发送出去,
        #第一个参数OFPP_CONTROLLER是接收端口,
        #第二个是数据包在交换机上缓存buffer_id,由于我们将数据包全部传送到控制器,所以不在交换机上缓存
        actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,ofproto.OFPCML_NO_BUFFER)]

        self.add_flow(datapath,0,match,actions,"default flow entry")    #默认缺省流表项,设置优先级最低即可
'''
    数据平面    是由若干网元(Network Element)组成,每个网元包含一个或多个SDN数据路径(SDN Datapath)。
    SDN Datapath是逻辑上的网络设备,负责转发和处理数据无控制能力,
    一个SDN DataPath包含控制数据平面接口(Control Data Plane Interface,CDPI)、代理、转发引擎(Forwarding Engine)表和处理功能(Processing Function) 
    SDN数据面(转发面)的关键技术:对数据面进行抽象建模。
    '''
    def add_flow(self,datapath,priority,match,actions,remind_content):
        '''构建流表项 : add a flow entry, install it into datapath
        datapath:表示给哪一个逻辑设备下发流表
        priority:表示优先级
        match,actions:匹配域和动作
        '''

        #datapath属性        
        ofproto = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        #在OpenFlow1.3版本中定义了instruct指令集(交换机内部的一些操作)
        #construct a flow msg and send it
        inst = [ofp_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]

        mod = ofp_parser.OFPFlowMod(datapath=datapath,priority=priority,
                                    match=match,instructions=inst);
        print("install to datapath,"+remind_content)
        #发送出去
        datapath.send_msg(mod);

        
'''接收数据
        Ryu控制器通过装饰器去注册监听某些事件,去处理这些事件。
        从而实现从数据平面的消息上传到控制器,再从控制器平面到应用平面,应用程序去处理事件,再逐跳返回到openvswitch
    '''

    '''要处理这个事件,需要先去注册监听他
    EventOFPPacketIn: 是我们要监听的事件
    MAIN_DISPATCHER : 是什么状态下,去监听该事件---Switch-features message received and sent set-config message
    '''
    @set_ev_cls(ofp_event.EventOFPPacketIn,MAIN_DISPATCHER)
    def packet_in_handler(self,ev):
        '''Hub集线器类,所实现的功能:
        1.接收从OpenVSwitch发送过来的数据包
        2.将数据包泛洪到Hub中的其他端口中
        '''    

        #解析数据结构
        msg = ev.msg
        datapath = msg.datapath
        ofproto = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        in_port = msg.match['in_port']        #获取源端口

        print("get packet in, install flow entry,and lookback parket to datapath")
        
        match = ofp_parser.OFPMatch();        #因为我们是将所有转发,所以不用管匹配,填空表示全部匹配
        actions = [ofp_parser.OFPActionOutput(ofproto.OFPP_FLOOD)]  #注意:FLOOD是OpenFlow协议保留端口---泛洪使用

        #调用add_flow,将流表项发送    ,指导后续数据包转发    install flwo entry to avoid packet in next time
        self.add_flow(datapath,1,match,actions,"hub flow entry")    #等级稍微比默认流表项高级

        #注意:我们将流表项下发了,但是数据包我们这次接收的,并没有处理
        #就是再将控制器上的数据包,重新发送给datapath,让他按照流表项处理
        #buffer_id是这个数据包,存放在控制器中的缓冲区位置,是在事件中的buffer_id获取
        out = ofp_parser.OFPPacketOut(datapath=datapath,buffer_id=msg.buffer_id,
                                            in_port=in_port,actions=actions,data=msg.data)    

        datapath.send_msg(out);

        通信流程:

        1.当开始一个Hub集线器时,会先与控制器进行连接,我们需要在Ryu中设置函数去处理连接,设置并下发默认流表---------函数switch_features_handler实现

        2.当主机之间通信时,主机上传信息到OpenVSwitch交换机,而交换机无法匹配到流表项时,我们设置将数据全部上传给Ryu控制器,我们在控制器端实现Hub集线器的泛洪功能,即设置流表项(match-actions为所有匹配数据包的动作为ofproto.OFPP_FLOOD,并且将该流变下发给原来datapath,同时我们要将之前交换机发送过来的数据包重新发送给交换机(让其按照新的流表项进行处理)--------函数packet_in_handler实现

        3.我们将公共函数add_flow,构建流表项并且下发流表提出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值