8

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

注意:这个问题已经有了答案。

4

2 回答 2

18

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

本简短指南假定您已经了解计算机网络和主要网络协议。本指南将帮助您从系统设置开始使用 OpenFlow。

1.什么是OpenFlow和SDN?

请阅读SDN / OpenFlow | 流程图

进一步阅读:Scott Shenker 和软件定义网络的网络的未来和协议的过去,IEEE INFOCOM 2009

在你开始之前:

基础设施层包括网络核心内的路由器和交换机。

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

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

OpenFlow 是一种协议,基础设施和控制层使用该协议进行交互。OpenFlow 本身不提供 API。它是一种开源协议,由开发支持 OpenFlow 的交换机的供应商和编写控制器的开发人员(如 Ryu)使用。API 由控制器提供。

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

先决条件

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

su  
dhclient eth0

启用须藤

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

su
apt-get install sudo # you might need to do apt-get update first!
visudo

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

yourusername ALL=(ALL:ALL) ALL

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

exit

启用最佳屏幕分辨率(仅限 VM)

如果您在 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

安装 Git

sudo apt-get install git

安装迷你网

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

安装 Ryu OpenFlow 控制器

OpenFlow 控制器使用 OpenFlow 协议在控制层和基础设施层之间进行通信。此外,它是提供 API 以开发在应用层(在控制层之上)运行的 SDN 应用程序的控制器。有许多 OpenFlow 控制器。Ryu OpenFlow 控制器是一种使用 Python 脚本作为其应用程序的控制器。同样,使用 Git 安装它:

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

安装 Wireshark

sudo apt-get install wireshark

安装支持的 Python 模块

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  

启动

使用以下命令启动 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控制平面的应用层。

设置拓扑并运行控制应用程序

注意:在前面的部分中,您使用 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

玩数据包

在 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 中,对主机 2 和主机 3 执行 ping 操作,并在执行每个命令后观察其他两个控制台上的效果:

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.了解二层交换机的基本应用

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

学习桥(或第 2 层交换机)的工作

我之前提到过,如果您正在阅读本指南,我假设您已经了解基本的网络协议,(包括第 2 层交换机、学习网桥或以太网交换机的工作原理!)我将在不管下面几行。

“学习”网桥根据其端口存储与其连接的主机的数据库。主机由其网卡的 MAC 地址标识,如下所示:(ab:cd:ef:12:34:56它是十六进制的)。端口仅通过其编号来标识。例如,具有 4 个端口的交换机具有端口 1、2、3 和 4。

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

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

Ryu API Python 代码介绍

与其直接进入 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)

进口

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

基本应用骨架

以下代码是一个完美完整的 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.RyuAppimport(在第一行导入)。从 Ryu API 手册中,app_manager类是 Ryu 应用程序的中心管理。它加载 Ryu 应用程序,为它们提供上下文并在 Ryu 应用程序之间路由消息。

EventOFPPacketIn 事件

一个新方法packet_in_handler被添加到L2Switch类中。当 Ryu 收到 OpenFlowpacket_in消息时调用它。当 Ryu 收到packet_in消息时,ofp_event.EventOFPPacketIn会引发一个事件。装饰器set_ev_cls告诉 Ryu 什么时候packet_in_handler应该调用关联的函数。

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

第二个参数表示当您希望允许 Ryu 处理事件时开关的状态。可能,您想packet_in在 Ryu 和交换机之间的握手完成之前忽略 OpenFlow 消息。用作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.ofproto并且dp.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 变量中定义的端口。我重复一遍,在这种情况下,构建的动作使得目的地包括所有端口。

活动

您在上面的代码中反复看到了术语事件。在事件驱动编程中,程序的流程由事件控制,这些事件由系统接收到的消息EventOFPPacketIn引发(例如,当Ryu(启用 OpenFlow 的)交换机接收packet_in消息时引发)。我们之前讨论过 OpenFlow 是一种协议,控制器(Ryu、PC)和基础设施(或交换机)使用该协议进行通信。消息之类的正是两者之间使用 OpenFlow 协议进行通信的样子! packet_in

下一步

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

于 2016-06-23T17:22:32.530 回答
1

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

Ryuretic 后端将所有事件作为 pkt(字典对象)呈现给用户,并通过提供感兴趣的头字段(例如,pkt['srcmac']、pkt['dstmac']、 pkt['ethtype'], pkt['inport'], pkt['srcip'], etc.) 使用来自 pkt 的信息,用户可以选择要匹配的字段和操作(fwd、drop、redirect、mirror , craft) 找到匹配项时获取。

要安装 Ryuretic,只需将 [文件] ( 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 上测试您的网络应用程序。

于 2016-08-25T13:30:41.203 回答