zoukankan      html  css  js  c++  java
  • 2019 SDN上机第5次作业

    1.浏览RYU官网学习RYU控制器的安装和RYU开发入门教程,提交你对于教程代码的理解,包括但不限于:

    (1)描述官方教程实现了一个什么样的交换机功能?

    添加一些功能使交换机能够将接收到的数据包转发到所有端口

    (2)控制器设定交换机支持什么版本的OpenFlow?

    OpenFlow v1.0

    (3)控制器设定了交换机如何处理数据包?
    处理方式:
    • 当Ryu收到OpenFlow交换机送来的packet_in消息时调用新增方法packet_in_handler

    • @set_ev_cls的第二个参数MAIN_DISPATCHER意味着当Ryu和交换机握手过程(即hello, features request/reply, Set Config等)完毕,才会调用packet_in_handler

    • 之后定义packet_in数据结构对象,数据路径对象datapath,OpenFlow协议和解析过程;定义交换机的动作,如何发送数据包;定义Ryu向交换机发送的packet_out内容,最后发送消息
      相关解释:

    • set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)装饰器告诉Ryu何时应调用装饰的函数

    • 第一个参数指示应调用此函数的事件类型。每次Ryu收到packet_in消息时,都会调用此函数。

    • 第二个参数指示开关的状态。在Ryu与交换机之间的协商完成之前忽略packet_in消息,使用“MAIN_DISPATCHER”作为第二个参数表示仅在协商完成后才调用此函数。

    • packet_in_handler函数

    • ev.msg是表示packet_in数据结构的对象。

    • msg.dp是代表数据路径(开关)的对象。

    • dp.ofproto和dp.ofproto_parser是代表Ryu和交换机协商的OpenFlow协议的对象。

    • OFPActionOutput类与packet_out消息一起使用,以指定要从中发送数据包的交换机端口。该应用程序使用OFPP_FLOOD标志来指示应在所有端口上发送数据包。

    • OFPPacketOut类用于构建packet_out消息。

    • 如果使用OpenFlow消息类对象调用Datapath类的send_msg方法,则Ryu会生成联机数据格式并将其发送到交换机。

    2.根据官方教程和提供的示例代码(SimpleSwitch.py),将具有自学习功能的交换机代码(SelfLearning.py)补充完整

    (1)补充完整

    1.浏览RYU官网学习RYU控制器的安装和RYU开发入门教程,提交你对于教程代码的理解,包括但不限于:

    (1)描述官方教程实现了一个什么样的交换机功能?

    添加一些功能使交换机能够将接收到的数据包转发到所有端口

    (2)控制器设定交换机支持什么版本的OpenFlow?

    OpenFlow v1.0

    (3)控制器设定了交换机如何处理数据包?
    处理方式:
    • 当Ryu收到OpenFlow交换机送来的packet_in消息时调用新增方法packet_in_handler

    • @set_ev_cls的第二个参数MAIN_DISPATCHER意味着当Ryu和交换机握手过程(即hello, features request/reply, Set Config等)完毕,才会调用packet_in_handler

    • 之后定义packet_in数据结构对象,数据路径对象datapath,OpenFlow协议和解析过程;定义交换机的动作,如何发送数据包;定义Ryu向交换机发送的packet_out内容,最后发送消息
      相关解释:

    • set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)装饰器告诉Ryu何时应调用装饰的函数

    • 第一个参数指示应调用此函数的事件类型。每次Ryu收到packet_in消息时,都会调用此函数。

    • 第二个参数指示开关的状态。在Ryu与交换机之间的协商完成之前忽略packet_in消息,使用“MAIN_DISPATCHER”作为第二个参数表示仅在协商完成后才调用此函数。

    • packet_in_handler函数

    • ev.msg是表示packet_in数据结构的对象。

    • msg.dp是代表数据路径(开关)的对象。

    • dp.ofproto和dp.ofproto_parser是代表Ryu和交换机协商的OpenFlow协议的对象。

    • OFPActionOutput类与packet_out消息一起使用,以指定要从中发送数据包的交换机端口。该应用程序使用OFPP_FLOOD标志来指示应在所有端口上发送数据包。

    • OFPPacketOut类用于构建packet_out消息。

    • 如果使用OpenFlow消息类对象调用Datapath类的send_msg方法,则Ryu会生成联机数据格式并将其发送到交换机。

    2.根据官方教程和提供的示例代码(SimpleSwitch.py),将具有自学习功能的交换机代码(SelfLearning.py)补充完整

    (1)补充完整代码如下

      #coding=utf-8
      from ryu.base import app_manager
      from ryu.controller import ofp_event
      from ryu.controller.handler import MAIN_DISPATCHER
      from ryu.controller.handler import set_ev_cls
      from ryu.ofproto import ofproto_v1_0
      from ryu.lib.mac import haddr_to_bin
      from ryu.lib.packet import packet
      from ryu.lib.packet import ethernet
      class L2Switch(app_manager.RyuApp):
    
      OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION]  #定下使用的OpenFlow版本
    
      def __init__(self, *args, **kwargs):
        super(L2Switch, self).__init__(*args, **kwargs)
        self.mac_to_port = {}
    
      def add_flow(self, datapath, in_port, dst, actions):
        ofproto = datapath.ofproto
    
        match = datapath.ofproto_parser.OFPMatch(
            in_port = in_port, dl_dst = haddr_to_bin(dst))
    
        mod = datapath.ofproto_parser.OFPFlowMod(
            datapath = datapath, match = match, cookie = 0,
            command = ofproto.OFPFC_ADD, idle_timeout = 10,hard_timeout = 30,
            priority = ofproto.OFP_DEFAULT_PRIORITY,
            flags =ofproto.OFPFF_SEND_FLOW_REM, actions = actions)
    
        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
    
        pkt = packet.Packet(msg.data)
        eth = pkt.get_protocol(ethernet.ethernet)
    
        dst = eth.dst
        src = eth.src
    
        dpid = datapath.id    #获取dpid
        self.mac_to_port.setdefault(dpid, {}) #设置交换机的mac地址表
    
        self.logger.info("packet in %s %s %s %s", dpid, src, dst , msg.in_port)  #显示dpid,映射host的mac地址与交换机那块对应的端口号
        
        self.mac_to_port[dpid][src] = msg.in_port  #判断目的mac地址是否存在于mac位址表中,若不存在,进行洪泛
    
        out_port = ofproto.OFPP_FLOOD #将输出端口指定为洪泛
    
        if dst in self.mac_to_port[dpid]:  #如果已经获取目的mac地址,查询输出用端口
            out_port = self.mac_to_port[dpid][dst]
    
        ofp_parser = datapath.ofproto_parser
    
        actions = [ofp_parser.OFPActionOutput(out_port)]
    
        if out_port != ofproto.OFPP_FLOOD:  #下发流表
            self.logger.info("add flow s:DPID:%s Match:[ MAC_SRC:%s MAC_DST:%s IN_PORT:%s ], Action:[OUT_PUT:%s] ",dpid, src, dst, msg.in_port, out_port) #显示datapath id,目标的MAC地址,源的MAC地址,进入端口,输出端口等信息
            self.add_flow(datapath, msg.in_port, dst, actions)
        packet_out = ofp_parser.OFPPacketOut(datapath = datapath, buffer_id = msg.buffer_id,in_port = msg.in_port, actions = actions)  #发送packet_out消息以处理数据包
        datapath.send_msg(packet_out)
        @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER) #这里则是展示端口状态
        def _port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        port_no = msg.desc.port_no
    
        ofproto = msg.datapath.ofproto
    
        if reason == ofproto.OFPPR_ADD:
            self.logger.info("port added %s", port_no)
        elif reason == ofproto.OFPPR_DELETE:
            self.logger.info("port deleted %s", port_no)
        elif reason == ofproto.OFPPR_MODIFY:
            self.logger.info("port modified %s", port_no)
        else:
            self.logger.info("Illeagal port state %s %s", port_no, reason)
    
    (2)执行该文件,在终端输入:
    ryu-manager sdn5.py
    

    QQekT0.png

    3.在mininet创建一个最简拓扑,并连接RYU控制器

    QQe9yj.png

    (1)关于c0和Preference的设置:

    QQeplQ.png
    QQeVYT.png

    (2)在run之后连接RYU控制器:

    4.验证自学习交换机的功能,提交分析过程和验证结果

    QQeimn.png

    (1)重新执行文件:
    ryu-manager sdn5.py
    

    QQeCOs.png

    (2)输入以下命令,创建拓扑:
    sudo mn --controller=remote,ip=127.0.0.1,port=6633
    

    QQeQmR.png

    (3)输入如下命令,查看流表,此时交换机s1上并无流表:
    sudo ovs-ofctl dump-flows s1
    

    QQenl4.png

    (4)连接到RYU外部控制器后测试连通性,输入如下命令,测试主机之间的连通性:
    h1 ping h2
    

    QQeKX9.png

    (5)再次使用sudo ovs-ofctl dump-flows s1查看流表:

    QQeu6J.png

    5.写下你的实验体会

    通过这次实验,我了解到Ryu是一款开源SDN控制器,是由Python 语言实现的。我们可以用Python语言在其上实现自己的应用。而且Ryu目前支持所有版本的Openflow协议。在实验中我们甚至可以通过Ryu验证自学习交换机的功能。我还了解到Ryu是基于组件的软件定义的网络框架。

  • 相关阅读:
    [数据结构]直接插入排序
    隐藏小程序scroll-view组件的滚动条
    当 uni-app 遇见 vscode
    npm(你怕吗) 全局安装与本地安装、开发依赖和生产依赖
    Vue-resource的使用
    spy-debugger调试、抓包工具
    一个小时学会Git
    flex布局踩过的坑
    Html5移动端布局及(rem布局)页面自适应布局详解
    使用vscode自动编译less
  • 原文地址:https://www.cnblogs.com/caoyuanfeifeixiong/p/11979577.html
Copyright © 2011-2022 走看看