了解 Ryu OpenFlow 控制器、mininet、WireShark 和 tcpdump
Understanding Ryu OpenFlow Controller, mininet, WireShark and tcpdump
我是 OpenFlow 和 SDN 的新手。我需要帮助在 Ubuntu 或 Debian 机器上设置 Ryu OpenFlow 控制器并了解基本的 Ryu 应用程序。
注意: 这个问题已经有答案了
这可能是我在 Stack Overflow 上写的最长 post 之一。我一直在学习 OpenFlow、SDN 和 Ryu,并想在这里为初学者记录我的知识。需要的话请correct/edit我post
本简短指南假设您已经了解计算机网络和主要网络协议。本指南将帮助您从系统设置开始使用 OpenFlow。
1。什么是 OpenFlow 和 SDN?
请阅读SDN / OpenFlow | Flowgrammable。
开始之前:
基础设施层包括网络核心内部的路由器和交换机。
控制层包括 运行 作为 OpenFlow 控制器的 PC 以及控制器本身。
应用层包括 运行 在该控制器之上的应用程序。在Ryu中,这些应用写在Python.
OpenFlow 是基础架构和控制层交互使用的协议。 OpenFlow 本身不提供 API。它是一种开源协议,供开发支持 OpenFlow 的交换机的供应商和编写控制器的开发人员使用,例如 Ryu。 API 由控制器提供。
2。在 Debian 8 上设置 Ryu OpenFlow 控制器
先决条件
您需要上网。如果您在虚拟机中 运行ning Debian,请发出以下命令通过 NAT 自动配置您的以太网接口:
su
dhclient eth0
启用sudo
默认情况下,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 身份注销 return 到您自己的 shell
exit
启用最佳屏幕分辨率(仅限 VM)
如果您运行在 Virtual Box 中安装 Debian,则默认安装不会为 Virtual Box 启用全屏分辨率支持。稍后在第 3 节中您将需要更大的屏幕。现在启用它是个好主意。
在虚拟机的 window 中,单击设备 > 插入 Guest Additions CD 映像 ...
然后 cd 到包含文件的目录
cd /media/cdrom
由于权限问题,Debian 不允许您 运行 该脚本。将文件复制到您的主目录,更改权限,然后 运行 it:
mkdir ~/VBOXGUEST
cp * ~/VBOXGUEST
cd ~/VBOXGUEST
chmod 755 *
sudo ./VBoxLinuxAdditions.run
重启
sudo shutdown -r now
安装Git
sudo apt-get install git
安装 Mininet
Mininet 允许您在 laptop/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 主机、在它们之间发送数据包等。
打开另一个终端window到运行 Ryu。在此示例中,我们将 运行 一个应用程序 (simple_switch_13.py) 模拟一个简单的第 2 层交换机,它将所有接收到的数据包转发到除接收到的端口之外的所有端口。
cd ~/ryu
PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
确保你在运行 this.
时的主目录
大功告成。要 ping 主机并分析数据包传输,请转到下一部分。
3。试验 Wireshark 和 tcpdump
在本节中,我们将使用 mininet 将数据包从一台主机发送到另一台主机,并使用 tcpdump 和 Wireshark 分析生成的传输。
数据包的传输方式正是我们在软件定义网络中可以控制的。我们通过在控制器之上编写 运行 不同的应用程序来做到这一点。这些应用构成了SDN控制平面的应用层。
设置拓扑和运行控制应用程序
注意:在前面的部分中,您使用 mininet 创建了一个拓扑,并启动了一个 Ryu 应用程序来控制传输。如果您重新启动或退出其中任何一个,我将重复命令以创建拓扑并在此处启动 Ryu 应用程序:
cd ~
sudo mn --topo single,3 --mac --switch ovsk --controller remote
并在单独的终端中 window:
cd ~/ryu
PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
玩数据包
在 mininet 提示符下,发出以下命令为您创建的拓扑中的三个主机中的每一个打开一个控制台 window:
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 之上的应用程序 运行ning。您可以编写一个应用程序来丢弃所有数据包。在那种情况下,您的 ping 将不会对其他两个控制台产生任何影响。
4。了解基本的第 2 层交换机应用程序
在本节中,我们分析了第 3 节中控制数据包传输的第 2 层交换机应用程序的简化版本的工作。
学习网桥(或二层交换机)工作
我之前提到过,如果您正在阅读本指南,我假设您已经了解基本网络协议(包括第 2 层交换机、学习网桥或以太网交换机的工作原理!)我不管怎样,我都会在下面的几行中总结一下。
“学习”网桥根据其端口存储其连接的主机的数据库。主机由其网卡的 MAC 地址标识,如下所示:ab:cd:ef:12:34:56
(十六进制)。这些端口仅通过它们的编号来标识。例如,具有 4 个端口的交换机具有端口 1、2、3 和 4。
如果交换机在其端口 2 上接收到数据包,它将查看该数据包的目标 MAC 地址(它的目标主机)。然后它查看它的数据库,看看它是否知道该主机连接到哪个端口。如果找到它,它只会将该数据包转发到该特定端口。但是,如果它的数据库中还没有条目,它就会将该数据包泛洪到所有端口,并且主机可以自行检查该数据包是否发往它们。
同时,交换机查看那个数据包的源MAC地址,它立即知道主机X位于端口2。它将该条目存储在该数据库中。所以现在您知道如果目标主机回复源主机,交换机将不必泛洪回复数据包!
Ryu简介APIPython代码
与其直接进入 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)
作为 class 的参数,我们通过 ryu.base.app_manager.RyuApp
导入(在第一行导入)。来自 Ryu API 手册app_manager
class 是Ryu 应用程序的中央管理。它加载 Ryu 应用程序,为它们提供上下文并在 Ryu 应用程序之间路由消息。
EventOFPPacketIn事件
新方法 packet_in_handler
添加到 L2Switch
class。当 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.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
class 与 packet_out
消息一起使用,以指定要从中发送数据包的交换机端口。由于在这个简化的应用程序中没有转发数据库,我们将数据包泛洪到所有端口,因此使用常量 OFPP_FLOOD
。
OFPPacketOut
class 用于构建 packet_out
消息。
通过使用datapath
class的send_msg
方法,您可以将OpenFlow消息对象发送到actions变量中定义的端口。我重复一遍,在这种情况下,构建的操作使得目标包括所有端口。
事件
您在上面的代码中多次看到事件这个词。在事件驱动编程中,程序的流程由事件控制,这些事件由系统接收到的消息引发(例如,EventOFPPacketIn
在收到 packet_in
消息时引发 Ryu from (OpenFlow enabled) 开关)。我们之前讨论过,OpenFlow 是一种协议,控制器(Ryu,PC)和基础设施(或交换机)使用该协议进行通信。 像packet_in
这样的消息正是两者之间使用OpenFlow协议进行通信的样子!
后续步骤
您可能想要继续构建您自己的 Ryu 应用程序。学习 Ryu API(或 Python 语言,如果您还不熟悉的话)可能是一个很好的起点。祝你好运!
您可能会发现对使用 Ryu 控制器有用的东西是 Ryuretic。 Ryuretic 是一个用于网络应用程序开发的模块化 SDN-based 框架。它允许网络运营商在 OSI 模型的各个级别(包括 L2、L3、L4 和填充层协议)直接使用 packet header 字段。用户只需选择匹配字段并选择提供的操作即可更新 OpenFlow 交换机。
Ryuretic 后端将所有事件作为 pkt(字典 object)呈现给用户,并且通过提供 header 感兴趣的字段(例如,pkt ['srcmac'], pkt['dstmac'], pkt['ethtype'], pkt['inport'], pkt['srcip'], etc.) 使用信息从 pkt 中,用户可以选择要匹配的字段以及在找到匹配项时采取的操作(转发、丢弃、重定向、镜像、工艺)。
要安装 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 上测试您的网络应用程序。
我是 OpenFlow 和 SDN 的新手。我需要帮助在 Ubuntu 或 Debian 机器上设置 Ryu OpenFlow 控制器并了解基本的 Ryu 应用程序。
注意: 这个问题已经有答案了
这可能是我在 Stack Overflow 上写的最长 post 之一。我一直在学习 OpenFlow、SDN 和 Ryu,并想在这里为初学者记录我的知识。需要的话请correct/edit我post
本简短指南假设您已经了解计算机网络和主要网络协议。本指南将帮助您从系统设置开始使用 OpenFlow。
1。什么是 OpenFlow 和 SDN?
请阅读SDN / OpenFlow | Flowgrammable。
开始之前:
基础设施层包括网络核心内部的路由器和交换机。
控制层包括 运行 作为 OpenFlow 控制器的 PC 以及控制器本身。
应用层包括 运行 在该控制器之上的应用程序。在Ryu中,这些应用写在Python.
OpenFlow 是基础架构和控制层交互使用的协议。 OpenFlow 本身不提供 API。它是一种开源协议,供开发支持 OpenFlow 的交换机的供应商和编写控制器的开发人员使用,例如 Ryu。 API 由控制器提供。
2。在 Debian 8 上设置 Ryu OpenFlow 控制器
先决条件
您需要上网。如果您在虚拟机中 运行ning Debian,请发出以下命令通过 NAT 自动配置您的以太网接口:
su
dhclient eth0
启用sudo
默认情况下,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 身份注销 return 到您自己的 shell
exit
启用最佳屏幕分辨率(仅限 VM)
如果您运行在 Virtual Box 中安装 Debian,则默认安装不会为 Virtual Box 启用全屏分辨率支持。稍后在第 3 节中您将需要更大的屏幕。现在启用它是个好主意。
在虚拟机的 window 中,单击设备 > 插入 Guest Additions CD 映像 ...
然后 cd 到包含文件的目录
cd /media/cdrom
由于权限问题,Debian 不允许您 运行 该脚本。将文件复制到您的主目录,更改权限,然后 运行 it:
mkdir ~/VBOXGUEST
cp * ~/VBOXGUEST
cd ~/VBOXGUEST
chmod 755 *
sudo ./VBoxLinuxAdditions.run
重启
sudo shutdown -r now
安装Git
sudo apt-get install git
安装 Mininet
Mininet 允许您在 laptop/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 主机、在它们之间发送数据包等。
打开另一个终端window到运行 Ryu。在此示例中,我们将 运行 一个应用程序 (simple_switch_13.py) 模拟一个简单的第 2 层交换机,它将所有接收到的数据包转发到除接收到的端口之外的所有端口。
cd ~/ryu
PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
确保你在运行 this.
时的主目录大功告成。要 ping 主机并分析数据包传输,请转到下一部分。
3。试验 Wireshark 和 tcpdump
在本节中,我们将使用 mininet 将数据包从一台主机发送到另一台主机,并使用 tcpdump 和 Wireshark 分析生成的传输。
数据包的传输方式正是我们在软件定义网络中可以控制的。我们通过在控制器之上编写 运行 不同的应用程序来做到这一点。这些应用构成了SDN控制平面的应用层。
设置拓扑和运行控制应用程序
注意:在前面的部分中,您使用 mininet 创建了一个拓扑,并启动了一个 Ryu 应用程序来控制传输。如果您重新启动或退出其中任何一个,我将重复命令以创建拓扑并在此处启动 Ryu 应用程序:
cd ~
sudo mn --topo single,3 --mac --switch ovsk --controller remote
并在单独的终端中 window:
cd ~/ryu
PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
玩数据包
在 mininet 提示符下,发出以下命令为您创建的拓扑中的三个主机中的每一个打开一个控制台 window:
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 之上的应用程序 运行ning。您可以编写一个应用程序来丢弃所有数据包。在那种情况下,您的 ping 将不会对其他两个控制台产生任何影响。
4。了解基本的第 2 层交换机应用程序
在本节中,我们分析了第 3 节中控制数据包传输的第 2 层交换机应用程序的简化版本的工作。
学习网桥(或二层交换机)工作
我之前提到过,如果您正在阅读本指南,我假设您已经了解基本网络协议(包括第 2 层交换机、学习网桥或以太网交换机的工作原理!)我不管怎样,我都会在下面的几行中总结一下。
“学习”网桥根据其端口存储其连接的主机的数据库。主机由其网卡的 MAC 地址标识,如下所示:ab:cd:ef:12:34:56
(十六进制)。这些端口仅通过它们的编号来标识。例如,具有 4 个端口的交换机具有端口 1、2、3 和 4。
如果交换机在其端口 2 上接收到数据包,它将查看该数据包的目标 MAC 地址(它的目标主机)。然后它查看它的数据库,看看它是否知道该主机连接到哪个端口。如果找到它,它只会将该数据包转发到该特定端口。但是,如果它的数据库中还没有条目,它就会将该数据包泛洪到所有端口,并且主机可以自行检查该数据包是否发往它们。
同时,交换机查看那个数据包的源MAC地址,它立即知道主机X位于端口2。它将该条目存储在该数据库中。所以现在您知道如果目标主机回复源主机,交换机将不必泛洪回复数据包!
Ryu简介APIPython代码
与其直接进入 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)
作为 class 的参数,我们通过 ryu.base.app_manager.RyuApp
导入(在第一行导入)。来自 Ryu API 手册app_manager
class 是Ryu 应用程序的中央管理。它加载 Ryu 应用程序,为它们提供上下文并在 Ryu 应用程序之间路由消息。
EventOFPPacketIn事件
新方法 packet_in_handler
添加到 L2Switch
class。当 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.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
class 与 packet_out
消息一起使用,以指定要从中发送数据包的交换机端口。由于在这个简化的应用程序中没有转发数据库,我们将数据包泛洪到所有端口,因此使用常量 OFPP_FLOOD
。
OFPPacketOut
class 用于构建 packet_out
消息。
通过使用datapath
class的send_msg
方法,您可以将OpenFlow消息对象发送到actions变量中定义的端口。我重复一遍,在这种情况下,构建的操作使得目标包括所有端口。
事件
您在上面的代码中多次看到事件这个词。在事件驱动编程中,程序的流程由事件控制,这些事件由系统接收到的消息引发(例如,EventOFPPacketIn
在收到 packet_in
消息时引发 Ryu from (OpenFlow enabled) 开关)。我们之前讨论过,OpenFlow 是一种协议,控制器(Ryu,PC)和基础设施(或交换机)使用该协议进行通信。 像packet_in
这样的消息正是两者之间使用OpenFlow协议进行通信的样子!
后续步骤
您可能想要继续构建您自己的 Ryu 应用程序。学习 Ryu API(或 Python 语言,如果您还不熟悉的话)可能是一个很好的起点。祝你好运!
您可能会发现对使用 Ryu 控制器有用的东西是 Ryuretic。 Ryuretic 是一个用于网络应用程序开发的模块化 SDN-based 框架。它允许网络运营商在 OSI 模型的各个级别(包括 L2、L3、L4 和填充层协议)直接使用 packet header 字段。用户只需选择匹配字段并选择提供的操作即可更新 OpenFlow 交换机。
Ryuretic 后端将所有事件作为 pkt(字典 object)呈现给用户,并且通过提供 header 感兴趣的字段(例如,pkt ['srcmac'], pkt['dstmac'], pkt['ethtype'], pkt['inport'], pkt['srcip'], etc.) 使用信息从 pkt 中,用户可以选择要匹配的字段以及在找到匹配项时采取的操作(转发、丢弃、重定向、镜像、工艺)。
要安装 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 上测试您的网络应用程序。