首页 文章

了解Ryu OpenFlow控制器,mininet,WireShark和tcpdump

提问于
浏览
5

我是OpenFlow和SDN的新手 . 我需要帮助在Ubuntu或Debian机器上设置Ryu OpenFlow控制器并理解基本的Ryu应用程序 .

Note :这个问题已经有了答案 .

2 回答

  • 9

    这可能是我在Stack Overflow上写的最长的帖子之一 . 我一直在学习OpenFlow,SDN和Ryu,并希望在这里为初学者记录我的知识 . 如果需要,请更正/编辑我的帖子 .

    本简短指南假设您已经掌握了计算机网络和主要网络协议的知识 . 本指南将帮助您从系统设置开始使用OpenFlow .

    1.什么是OpenFlow和SDN?

    请阅读OpenFlow - Open Networking Foundation .

    进一步阅读:The Future of Networking, and the Past of Protocols by Scott Shenker and Software-defined Networking, IEEE INFOCOM 2009 .

    在你开始之前:

    Infrastructure层包括网络核心内的路由器和交换机 .

    控制层包括运行OpenFlow控制器的PC以及控制器本身 .

    应用程序层包括在该控制器之上运行的应用程序 . 在Ryu中,这些应用程序是用Python编写的 .

    OpenFlow是基础架构和控制层交互的协议 . OpenFlow不提供自身的API . 它是一种开源协议,供开发支持OpenFlow的交换机的供应商和编写控制器的开发人员(如Ryu)使用 . API由控制器提供 .

    2.在Debian 8上设置Ryu OpenFlow控制器

    Prerequisites

    你需要上网 . 如果您在虚拟机中运行Debian,请发出以下命令以通过NAT自动配置以太网接口:

    su  
    dhclient eth0
    

    Enable sudo

    Debian默认不带sudo . 您稍后将使用的一些Ryu应用程序需要sudo . 您可以安装sudo并将自己添加到sudo'ers列表,如下所示:

    su
    apt-get install sudo # you might need to do apt-get update first!
    nano /etc/sudoers
    

    找到%sudo ALL =(ALL:ALL)ALL的行并在其下方添加一个条目:

    yourusername ALL=(ALL:ALL) ALL
    

    按CTRL X,然后按Y将更改保存到sudoers文件 . 现在您可以以root身份注销以返回到您自己的shell

    exit
    

    Enable Optimal Screen Resolution (VM Only)

    如果您在Virtual Box中运行Debian,则默认安装不会启用对Virtual Box的全屏分辨率支持 . 您将在第3节中稍后需要更大的屏幕 . 现在启用它是个好主意 .

    在虚拟机的窗口中,单击设备>插入访客添加CD图像...

    然后cd到包含文件的目录

    cd /media/cdrom
    

    由于权限问题,Debian不允许您运行脚本 . 将文件复制到主目录,更改权限,然后运行它:

    mkdir ~/VBOXGUEST  
    cp * ~/VBOXGUEST  
    cd ~/VBOXGUEST  
    chmod 755 *  
    sudo ./VBoxLinuxAdditions.run
    

    重启

    sudo shutdown -r now
    

    Install Git

    sudo apt-get install git
    

    Install Mininet

    Mininet允许您虚拟模拟笔记本电脑/ PC上的各种网络接口 . 使用Git安装它:

    cd ~  # if you are in some other directory
    git clone git://github.com/mininet/mininet
    cd mininet
    git tag  # this will list available versions
    git checkout -b 2.2.1 2.2.1  # replace 2.2.1 with the version you wish to install
    cd ..
    mininet/util/install.sh -a  # default installation, includes all components, recommended
    

    我建议你安装OpenFlow Wireshark Dissector . 您可以稍后安装Wireshark来分析数据包 . OpenFlow Wireshark Dissector帮助Wireshark从OpenFlow数据包中获取尽可能多的信息 .

    mininet/util/install.sh -h
    

    运行以下命令以检查mininet安装:

    sudo mn --test pingall
    

    Install Ryu OpenFlow Controller

    OpenFlow Controller使用OpenFlow协议在控制层和Infrastructure层之间进行通信 . 此外,它是控制器,它提供API来开发在应用层(在控制层之上)运行的SDN应用程序 . 有许多OpenFlow控制器 . Ryu OpenFlow控制器是使用Python脚本作为其应用程序的控制器 . 再次,使用Git安装它:

    cd ~
    git clone git://github.com/osrg/ryu.git
    

    Install Wireshark

    sudo apt-get install wireshark
    

    Install the supporting Python modules

    Debian 8.3默认安装了Python 2.7和3.4 . 但是,您需要安装Ryu应用程序(Python脚本)使用的一些Python模块 . 您可以使用pip安装Python模块:

    cd ~/ryu  
    sudo apt-get install python-dev python-pip python-setuptools  
    sudo pip install .
    

    以上将自动运行位于此目录中的setup.py并从Python包索引中获取缺少的Python模块 . 该脚本将自动安装所有相关模块 . 但是,请运行以下命令以确保您以后不会丢失任何模块:

    sudo pip install webob  
    sudo pip install eventlet  
    sudo pip install paramiko  
    sudo pip install routes
    

    Starting up

    使用以下命令启动mininet以模拟3个主机和交换机:

    sudo mn --topo single,3 --mac --switch ovsk --controller remote
    

    你会看到一个mininet提示 . 此提示可用于ping主机,在它们之间发送数据包等 .

    打开另一个终端窗口来运行Ryu . 在此示例中,我们将运行一个应用程序(simple_switch_13.py),该应用程序将模拟一个简单的第2层交换机,该交换机将所有收到的数据包转发到除收到的所有端口之外的所有端口 .

    cd ~/ryu  
    PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
    

    运行时,请确保您在主目录中 .

    你们都准备好了 . 要ping主机并分析数据包传输,请转到下一部分 .

    3.尝试使用Wireshark和tcpdump

    在本节中,我们将使用mininet从一个主机向另一个主机发送数据包,并使用tcpdump和Wireshark分析生成的传输 .

    数据包传输的方式是正是我们可以在软件定义网络中控制的内容 . 我们通过编写在控制器上运行的不同应用程序来完成此操作 . 这些应用程序构成SDN控制平面的应用层 .

    Set up topology and run the controlling application

    注意:在前面的部分中,您使用mininet创建了拓扑,并启动了一个Ryu应用程序来控制传输 . 如果您重新启动或退出其中任何一个,我重复命令以创建拓扑并在此处启动Ryu应用程序:

    cd ~
    sudo mn --topo single,3 --mac --switch ovsk --controller remote
    

    并在一个单独的终端窗口中:

    cd ~/ryu
    PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
    

    Play with packets

    在mininet提示符中,发出以下命令为您创建的拓扑中的每个主机打开一个控制台窗口:

    mininet> xterm h1 h2 h3
    

    堆叠这些控制台,以便您可以同时看到它们!然后在h2和h3的xterms中运行tcpdump,这是一个用于打印主机看到的数据包的实用程序:

    tcpdump -XX -n -i h2-eth0  
    tcpdump -XX -n -i h3-eth0
    

    注意:如果您之前使用过Wireshark,则分别在这两个主机的eth0接口上捕获数据包 .

    创建拓扑时,mininet为以下三个主机分配了以下IP地址:

    h1: 10.0.0.1  
    h2: 10.0.0.2  
    h3: 10.0.0.3
    

    从主机1的shell,ping主机2和主机3,并观察每个命令后对其他两个控制台的影响:

    ping 10.0.0.2  
    ping 10.0.0.3
    

    尝试ping一个无法访问(不存在的主机),并在控制台上看到效果:

    ping 10.0.0.7
    

    您应该已经在本节中观察到ICMP(ping)和ARP(具有此IP地址的人)协议!您也可以使用Wireshark而不是tcpdump来完成上述操作 . 这是tcpdump的图形替代品 .

    注意:数据包转发的方式取决于在Ryu上运行的应用程序 . 您可以编写一个应用程序来删除所有数据包 . 在这种情况下,你的ping对其他两个控制台没有任何影响 .

    4.了解基本的第2层交换机应用程序

    在本节中,我们将分析第3节中控制数据包传输的第2层交换机应用程序的简化版本的工作原理 .

    Working of a learning bridge (or a Layer 2 Switch)

    我之前提到过,如果您正在阅读本指南,我假设您已经掌握了基本网络协议(包括第2层交换机,学习桥或以太网交换机的工作!)我将在以下内容中进行总结 . 以下几行无论如何 .

    "learning" bridge存储与其连接的主机的数据库,对应它的端口 . 主机由其网卡的MAC地址标识,如下所示: ab:cd:ef:12:34:56 (以十六进制表示) . 端口仅由其编号标识 . 例如,具有4个端口的交换机具有端口1,2,3和4 .

    如果交换机在其端口2上收到数据包,它将查看该数据包的目标MAC地址(它指向的主机) . 然后它查看它的数据库,看它是否知道该主机连接到哪个端口 . 如果发现它,它只将该数据包转发到该特定端口 . 但是如果它的数据库中没有条目,它会将该数据包泛洪到所有端口,并且主机可以检查数据包是否发往它们 .

    同时,交换机查看该数据包的源MAC地址,并立即知道主机X位于端口2.它将该条目存储在该数据库中 . 所以现在您知道,如果目标主机回复源主机,交换机将不必泛洪回复数据包!

    Introduction to the Ryu API Python code

    而不是直接进入simple_switch_13.py,让我们选择一个没有“学习”能力的非常简单的程序 . 目前,没有转发数据库 . 以下程序只是一个简单的第2层交换机,它将收到的数据包发送到所有端口(泛洪数据包):

    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
    
        class L2Switch(app_manager.RyuApp):
            def __init__(self, *args, **kwargs):
                super(L2Switch, self).__init__(*args, **kwargs)
    
            @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
            def packet_in_handler(self, ev):
                msg = ev.msg
                dp = msg.datapath
                ofp = dp.ofproto
                ofp_parser = dp.ofproto_parser
    
                actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
                out = ofp_parser.OFPPacketOut(
                    datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,
                    actions=actions)
                dp.send_msg(out)
    

    The imports

    我还不会深入研究import语句 . 我们将在分析使用它们的代码时单独讨论导入 .

    The basic application skeleton

    以下代码是完全完整的Ryu应用程序 . 实际上你也可以执行它!它不会做任何事情:

    from ryu.base import app_manager
    
        class L2Switch(app_manager.RyuApp):
            def __init__(self, *args, **kwargs):
                super(L2Switch, self).__init__(*args, **kwargs)
    

    作为类的参数,我们传递 ryu.base.app_manager.RyuApp import(在第一行导入) . 从Ryu API手册中, app_manager 类是Ryu应用程序的中央管理 . 它加载Ryu应用程序,为它们提供上下文并在Ryu应用程序之间路由消息 .

    The EventOFPPacketIn Event

    将一个新方法 packet_in_handler 添加到 L2Switch 类 . 当Ryu收到OpenFlow packet_in 消息时调用此方法 . 当Ryu收到 packet_in 消息时,会引发 ofp_event.EventOFPPacketIn 事件 . set_ev_cls 装饰器告诉Ryu应该调用相关函数 packet_in_handler .

    set_ev_cls 装饰器的第一个参数表示一个使函数调用的事件 . 正如您所期望的那样,每次引发 ofp_event.EventOFPPacketIn 事件时,都会调用此函数 .

    第二个参数表示当您想允许Ryu处理事件时的开关状态 . 也许,你想在Ryu和交换机完成握手之前忽略OpenFlow packet_in 消息 . 使用 MAIN_DISPATCHER 作为第二个参数意味着仅在协商后调用此函数完成 . MAIN_DISPATCHER 表示交换机的正常状态 . 在初始化阶段,开关处于 HANDSHAKE_DISPATCHER 状态!

    现在让我们看看函数的主体 . 我们将其分为两部分 .

    msg = ev.msg  
        dp = msg.datapath  
        ofp = dp.ofproto  
        ofp_parser = dp.ofproto_parser
    

    ev.msg 是包含接收数据包的数据结构 .

    msg.dp 是该数据结构中的一个对象,表示数据路径(交换机) .

    dp.ofprotodp.ofproto_parser 是表示Ryu和交换机协商的OpenFlow协议的对象 .

    actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]  
        out = ofp_parser.OFPPacketOut(  
            datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,  
            actions=actions)  
        dp.send_msg(out)
    

    OFPActionOutput 类与 packet_out 消息一起使用,以指定要从中发送数据包的交换机端口 . 由于此简化应用程序中没有转发数据库,因此我们将数据包泛洪到所有端口,因此使用常量 OFPP_FLOOD .

    OFPPacketOut 类用于构建 packet_out 消息 .

    通过使用 datapath 类的 send_msg 方法,可以将OpenFlow消息对象发送到actions变量中定义的端口 . 我再说一遍,在这种情况下,构建动作使得目的地包括所有端口 .

    Events

    您在上面的代码中反复看到了术语事件 . 在事件驱动编程中,程序的流程由事件控制,事件由系统接收的消息引发(例如,当收到 packet_in 消息 by Ryu from (启用OpenFlow)时,会引发 EventOFPPacketIn ) . 我们之前讨论过OpenFlow是一种协议,控制器(Ryu,PC)和基础设施(或交换机)使用该协议进行通信 . Messages like packet_in are exactly what the communication between the two looks like using the OpenFlow protocol!

    Next steps

    您可能希望继续构建自己的Ryu应用程序 . 学习Ryu API(或Python语言,如果您还不熟悉它)可能是一个很好的起点 . 祝好运!

  • 1

    对于使用Ryu控制器,您可能会发现有用的东西是Ryuretic . Ryuretic是一个基于SDN的模块化网络应用程序开发框架 . 它允许网络运营商直接处理OSI模型各个级别的包头字段,包括L2,L3,L4和垫片层协议 . 用户只需选择匹配字段并选择提供的操作即可更新OpenFlow交换机 .

    Ryuretic后端将所有事件作为pkt(字典对象)呈现给用户,并且通过提供感兴趣的头字段(例如,pkt ['srcmac'],pkt ['dstmac']来检索pkt的内容, pkt ['ethtype'],pkt ['inport'],pkt ['srcip']等 . )使用pkt中的信息,用户可以选择匹配的字段和动作(fwd,drop,redirect,mirror) ,找到匹配时采取的工艺 .

    要安装Ryuretic,只需将[files](https://github.com/Ryuretic/RyureticLabs/tree/master/ryu/ryu/app/Ryuretic)复制到目录/ ryu / ryu / app / Ryuretic即可 . 如果你安装了Ryu,那么你已经有了/ ryu / ryu / app目录 . 您只需创建Ryuretic目录并将文件复制到那里 .

    Ryuretic Labs提供了使用Ryuretic在SDN上实现安全功能的设置说明和一些用例 . 它还提供了一个Mininet测试平台,用于测试SDN-Hub提供的VM上的网络应用程序 .

相关问题