Contents

Python-第三方库-mininet-mininet演练

mininet官网

mininet官网文档

mininet官网api

Mininet演练

第 1 部分:Mininet 的日常使用

首先,关于本演练的命令语法的(可能是显而易见的)注释:

  • $ 是 shell 提示符
  • mininet> 是 Mininet CLI
  • # 是 root shell 提示符

显示启动选项

键入以下命令以显示描述 Mininet 启动选项的帮助消息:

1
$ sudo mn -h

启动 Wireshark

要使用 OpenFlow Wireshark dissector 查看控制流量,首先在后台打开 wireshark:

1
$ sudo wireshark &

与主机和交换机交互

启动最小拓扑并输入 CLI:

1
$ sudo mn

默认拓扑是minimal拓扑结构,包括一个OpenFlow内核交换机连接到两个主机,加上OpenFlow参考控制器。此拓扑也可以在命令行上使用–topo=minimal. 开箱即用的其他拓扑也可用;请参阅–topo的输出中的部分mn -h。

如果没有特定的测试作为参数传递,Mininet CLI 就会出现。

在 Wireshark 窗口中,您应该看到内核交换机连接到参考控制器。

显示 Mininet CLI 命令:

1
mininet> help

显示节点:

1
mininet> nodes

显示链接:

1
mininet> net

转储(打印)有关所有节点的信息:

1
mininet> dump

应该会看到列出的交换机和两台主机。

如果在 Mininet CLI 中输入的第一个字符串是主机、交换机或控制器名称,则该命令将在该节点上执行:

1
mininet> h1 ifconfig -a

会看到主机h1-eth0和环回 ( lo) 接口。

h1-eth0 在运行时不会被主 Linux 系统看到,因为它特定于主机进程的网络命名空间。相比之下,交换机默认运行在根网络命名空间中,因此在“交换机”上运行命令与从常规终端运行命令相同:

1
mininet> s1 ifconfig -a

这将显示交换机接口,以及 VM 的连接输出( eth0)。

–innamespace选项可以将每个主机、交换机和控制器都放在自己独立的网络名称空间中,常用于构建复杂的多控制器网络

只有网络是虚拟化的;每个主机可以看到同一组进程和使用同一个文件目录(即python脚本运行的目录或者运行mn命令行所在的目录)

Linux 容器可以使用单独的进程空间,但目前 Mininet 不这样做。让一切都在“根”进程命名空间中运行便于调试,因为它允许您使用ps、kill等从控制台查看所有进程。

测试主机之间的连通性

1
mininet> h1 ping -c 1 h2

如果命令后面出现一个字符串和节点名称,则该节点名称将替换为它的 IP 地址;这发生在 h2 上。

您应该看到 OpenFlow 控制流量。第二个 MAC 地址的第一个主机 ARP,这会导致packet_in消息转到控制器。然后,控制器发送一条packet_out消息,将广播数据包泛洪到交换机上的其他端口(在本例中,是唯一的其他数据端口)。第二台主机看到 ARP 请求并发送回复。该回复到达控制器,控制器将其发送到第一台主机并下推流条目。

由于ovs的地址是127.0.0.1属于回环地址,所以wireshark监听lo就可以看到openflow发出去的数据包。

现在第一台主机知道第二台主机的 MAC 地址,并且可以通过 ICMP Echo Request 发送它的 ping。该请求及其来自第二台主机的相应回复都进入控制器并导致流条目被下推(连同实际数据包被发送出去)。

/images/Python/第三方库/mininet/mininet演练/1.png
第一次ping

重复上一个ping:

1
mininet> h1 ping -c 1 h2

第二次尝试的时间应该短得多ping(< 100us)。之前在交换机中安装了涵盖ICMPping流量的流表项,因此没有产生控制流量,数据包立即通过交换机。

/images/Python/第三方库/mininet/mininet演练/2.png
第二次ping

运行此测试的更简单方法是使用 Mininet CLI 内置pingall命令,该命令执行所有主机对ping:

1
mininet> pingall

运行一个简单的 Web 服务器和客户端

ping不是您可以在主机上运行的唯一命令,Mininet 主机可以运行底层 Linux 系统(或 VM)及其文件系统可用的任何命令或应用程序。还可以输入任何bash命令,包括作业控制(&、jobs、kill等。)

尝试在 h1 上启动一个简单的 HTTP 服务器,从 h2 发出请求,然后关闭 Web 服务器:

1
2
3
4
mininet> h1 python -m http.server 80 &
mininet> h2 wget -O - h1
...
mininet> h1 kill %python

注意:对于 Python 3,HTTP 服务器称为http.server; 对于 Python 2,它被称为SimpleHTTPServer。

退出 CLI:

1
mininet> exit

清理

如果 Mininet 由于某种原因崩溃,请清理它:

1
$ sudo mn -c

第 2 部分:高级启动选项

以下内容都是通过选项来修改默认mn命令的高级用法,但是这些高级用法可以在python里面有对应的api,推荐直接使用python脚本,不要或较少使用选项方式

运行回归测试

您不需要进入 CLI;Mininet 也可用于运行独立的回归测试。

运行回归测试:

1
$ sudo mn --test pingpair

该命令创建了一个最小拓扑,启动了 OpenFlow 参考控制器,运行了所有对ping测试,并拆除了拓扑和控制器。

另一个有用的测试是iperf(给它大约 10 秒来完成):

1
$ sudo mn --test iperf

此命令创建相同的 Mininet,在一台主机上运行 iperf 服务器,在第二台主机上运行 iperf 客户端,并解析所达到的带宽。

更改拓扑大小和类型

默认拓扑是连接到两个主机的单个交换机。您可以使用–topo将其更改为不同的拓扑,并为该拓扑的创建传递参数。例如,验证一台交换机和三台主机的所有对 ping 连接:

运行回归测试:

1
$ sudo mn --test pingall --topo single,3

另一个示例,使用线性拓扑(其中每个交换机都有一个主机,并且所有交换机连接成一条线):

1
$ sudo mn --test pingall --topo linear,4

参数化拓扑是 Mininet 最有用和最强大的特性之一。

链接变体

Mininet 2.0 允许您设置链接参数,这些甚至可以从命令行自动设置:

1
2
3
4
$ sudo mn --link tc,bw=10,delay=10ms
mininet> iperf
...
mininet> h1 ping -c10 h2

如果每条链路的延迟为 10 毫秒,则往返时间 (RTT) 应约为 40 毫秒,因为 ICMP 请求遍历两条链路(一条到交换机,一条到目的地)并且 ICMP 回复遍历两条返回的链路.

您可以使用Mininet 的 Python API自定义每个链接 ,但现在您可能想要继续演练。

可调输出粒度

默认的详细级别是info,它打印 Mininet 在启动和拆卸期间正在做什么。将此与带有参数-v的完整debug输出进行比较:

1
2
3
$ sudo mn -v debug
...
mininet> exit

将打印出许多额外的细节。现在试试output,一个打印 CLI 输出的设置,除此之外别无其他:

1
2
$ sudo mn -v output
mininet> exit

在 CLI 之外,可以使用其他详细级别,例如warning,它与回归测试一起使用以隐藏不需要的函数输出。

自定义拓扑

也可以使用简单的 Python API 轻松定义自定义拓扑,并且在custom/topo-2sw-2host.py. 此示例直接连接两个交换机,每个交换机有一个主机

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"""Custom topology example

Two directly connected switches plus a host for each switch:

   host --- switch --- switch --- host

Adding the 'topos' dict with a key/value pair to generate our newly defined
topology enables one to pass in '--topo=mytopo' from the command line.
"""

from mininet.topo import Topo

class MyTopo( Topo ):
    "Simple topology example."

    def build( self ):
        "Create custom topo."

        # Add hosts and switches
        leftHost = self.addHost( 'h1' )
        rightHost = self.addHost( 'h2' )
        leftSwitch = self.addSwitch( 's3' )
        rightSwitch = self.addSwitch( 's4' )

        # Add links
        self.addLink( leftHost, leftSwitch )
        self.addLink( leftSwitch, rightSwitch )
        self.addLink( rightSwitch, rightHost )


topos = { 'mytopo': ( lambda: MyTopo() ) }

当提供自定义 mininet 文件时,它可以向命令行添加新拓扑、交换机类型和测试。例如:

1
$ sudo mn --custom ~/mininet/custom/topo-2sw-2host.py --topo mytopo --test pingall

ID = MAC

默认情况下,主机以随机分配的 MAC 地址开头。这会使调试变得困难,因为每次创建 Mininet 时,MAC 都会发生变化,因此很难将控制流量与特定主机相关联。

该–mac选项非常有用,它将主机 MAC 和 IP 地址设置为小的、唯一的、易于阅读的 ID。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ sudo mn
...
mininet> h1 ifconfig
h1-eth0  Link encap:Ethernet  HWaddr f6:9d:5a:7f:41:42
          inet addr:10.0.0.1  Bcast:10.255.255.255  Mask:255.0.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:392 (392.0 B)  TX bytes:392 (392.0 B)
mininet> exit
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ sudo mn --mac
...
mininet> h1 ifconfig
h1-eth0  Link encap:Ethernet  HWaddr 00:00:00:00:00:01
          inet addr:10.0.0.1  Bcast:10.255.255.255  Mask:255.0.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
mininet> exit

相反,Linux 报告的交换机数据端口的 MAC 将保持随机。这是因为您可以使用 OpenFlow 将 MAC“分配”到数据端口,如常见问题解答中所述。这是一个有点微妙的问题,您现在可以忽略它。

XTerm 显示

其实更推荐使用命令mx:mx h1。这个命令能快速登录一个host的root用户。

对于更复杂的调试,您可以启动 Mininet 以便它生成一个或多个 xterms。

要为每个主机和交换机启动一个xterm,请传递以下-x选项:

1
$ sudo mn -x

一秒钟后,xterms 将弹出,并自动设置窗口名称。

或者,您可以调出额外的 xterms,如下所示。

默认情况下,只有主机被放在一个单独的命名空间中;每个交换机的窗口都是不必要的(即,相当于一个常规终端),但可以方便地运行和离开交换机调试命令,例如流计数器转储。

Xterms 对于运行您可能需要取消的交互式命令也很有用,您希望看到这些命令的输出。

例如:在标有“switch: s1 (root)”的 xterm 中,运行:

1
# ovs-ofctl dump-flows tcp:127.0.0.1:6654

什么都不会打印出来;交换机没有添加流。要ovs-ofctl与其他交换机使用,请以详细模式启动 mininet,并在创建交换机时查看交换机的被动侦听端口。

现在,在标有“host: h1”的 xterm 中,运行:

1
# ping 10.0.0.2

返回s1并转储流:# ovs-ofctl dump-flows tcp:127.0.0.1:6654

您现在应该看到多个流条目。或者(通常更方便),您可以使用Mininet CLI 中内置的命令dpctl,而无需任何 xterms 或手动指定交换机的 IP 和端口。

您可以通过检查 ifconfig 来判断 xterm 是否在根名称空间中;如果显示所有接口(包括eth0),则它位于根名称空间中。此外,其标题应包含“(root)”。

从 Mininet CLI 关闭设置:

1
mininet> exit

xterms 应该会自动关闭。

其他交换机类型

可以使用其他交换机类型。例如,要运行用户空间交换机:

1
$ sudo mn --switch user --test iperf

请注意,与之前使用内核开关看到的相比,TCP iperf 报告的带宽要低得多。

如果您进行前面所示的 ping 测试,您应该注意到更高的延迟,因为现在数据包必须经受额外的内核到用户空间的转换。ping 时间将更加可变,因为代表主机的用户空间进程可能由操作系统安排进出。

另一方面,用户空间切换可以是实现新功能的一个很好的起点,尤其是在软件性能不重要的情况下。

另一个示例交换机类型是 Open vSwitch (OVS),它预装在 Mininet VM 上。iperf 报告的 TCP 带宽应该类似于 OpenFlow 内核模块,并且可能更快:

1
$ sudo mn --switch ovsk --test iperf

mininet基准

要记录设置和拆除拓扑的时间,请使用测试“none”:

1
$ sudo mn --test none

一切都在自己的命名空间中(仅限用户切换)

默认情况下,主机位于它们自己的命名空间中,而交换机和控制器位于根命名空间中。要将交换机放在它们自己的命名空间中,请传递以下–innamespace选项:

1
$ sudo mn --innamespace --switch user

交换机将通过单独的桥接控制连接与控制器通信,而不是使用环回。这个选项本身并不是很有用,但它确实提供了一个如何隔离不同交换机的示例。

请注意,此选项(自 2012 年 11 月 19 日起)不适用于 Open vSwitch。

1
mininet> exit

第 3 部分:Mininet 命令行界面 (CLI) 命令

显示选项

要查看命令行界面 (CLI) 选项列表,请启动最小拓扑并使其保持运行状态。构建迷你网:

1
$ sudo mn

显示选项:

1
mininet> help

Python解释器

如果 Mininiet 命令行上的第一个短语是py,那么该命令将使用 Python 执行。这可能对扩展 Mininet 以及探索其内部工作机制很有用。每个主机、交换机和控制器都有一个关联的节点对象。

在 Mininet CLI 中,运行:

1
mininet> py 'hello ' + 'world'

打印可访问的局部变量:

1
mininet> py locals()

接下来,使用 dir() 函数查看节点可用的方法和属性:

1
mininet> py dir(s1)

您可以使用 help() 函数阅读节点上可用方法的联机文档:

1
mininet> py help(h1) (Press "q" to quit reading the documentation.)

您还可以评估变量的方法:

1
mininet> py h1.IP()

链接up/down 开启关闭

对于容错测试,打开和关闭链接会很有帮助。

要禁用虚拟以太网对:

1
mininet> link s1 h1 down

这里h1和h2能ping通s1,原因是s1转换的ip地址是127.0.0.1所以他们相当于给自己发包(回环),所以能通。

您应该会看到生成了 OpenFlow 端口状态更改通知。要恢复链接:

1
mininet> link s1 h1 up

XTerm 显示

显示 h1 和 h2 的 xterm:

1
mininet> xterm h1 h2

也可以使用mx命令直接登录h1和h2

第 4 部分:Python API 示例

Mininet 源代码树中的示例目录包括如何使用 Mininet 的 Python API 的示例,以及尚未集成到主代码库中的潜在有用代码。

注意:如开头所述,本演练假定您正在使用 Mininet VM,其中包括您需要的一切,或者使用所有相关工具的本机安装,包括参考控制器controller,它是 OpenFlow 参考实现的一部分install.sh -f如果尚未安装,则可以使用安装。

每个主机的 SSH 守护进程

建议使用mx命令

一个可能特别有用的示例在每台主机上运行 SSH 守护进程:

1
$ sudo ~/mininet/examples/sshd.py

从另一个终端,您可以通过 ssh 连接到任何主机并运行交互式命令:

1
2
3
4
$ ssh 10.0.0.1
$ ping 10.0.0.2
...
$ exit

退出 SSH 示例 mininet:

1
$ exit

在阅读介绍 Python API 的Mininet 简介后,您将希望重新访问这些示例 。

第 5 部分:演练完成!

恭喜!您已经完成了 Mininet 演练。随意尝试新的拓扑结构和控制器或查看源代码。

掌握 Mininet 的后续步骤

虽然您可以使用 Mininet 的 CLI 走得相当远,但是当您掌握了它的 Python API 后,Mininet 会变得更加有用和强大。Mininet 简介 介绍了 Mininet 及其 Python API。

如果您想知道如何使用远程控制器(例如在 Mininet 的控制之外运行的远程控制器),下面将对此进行解释。

附录:补充信息

使用控制器

注意:此步骤不是默认演练的一部分;如果您有一个在 VM 外部运行的控制器,例如在 VM 主机或不同的物理 PC 上,它主要有用。OpenFlow 教程controller –remote用于启动您使用 POX、NOX、Beacon 或 Floodlight 等控制器框架创建的简单学习交换机。

当你启动一个 Mininet 网络时,每个交换机都可以连接到一个远程控制器——它可以在 VM 中、VM 外部和你的本地机器上,或者在世界的任何地方。

如果你想尝试这个,填写主机 IP 和/或监听端口:

1
$ sudo mn --controller=remote,ip=[controller IP],port=[controller listening port]

例如,要运行 POX 的示例学习开关,您可以执行类似

1
2
$ cd ~/pox
$ ./pox.py forwarding.l2_learning

在一个窗口中,在另一个窗口中,启动 Mininet 以连接到“远程”控制器(它实际上在本地运行,但不受 Mininet 的控制):

1
$ sudo mn --controller=remote,ip=127.0.0.1,port=6633

请注意,POX 使用旧的 OpenFlow 端口 6633,该端口未注册,后来被 Cisco 占用。OpenFlow 的当前注册/规范端口是端口 6653。请为您的控制器使用适当的端口号。

默认情况下,–controller=remote将使用127.0.0.1并将尝试端口6653和6633。

如果您生成一些流量(例如h1 ping h2),您应该能够在 POX 窗口中观察到一些输出,表明交换机已连接并且一些流表条目已安装。

许多 OpenFlow 控制器框架很容易获得,只要您启动它们并使用 remote控制器运行所在机器的正确 IP 地址和它正在侦听的正确端口指定控制器选项,就应该很容易与 Mininet 一起工作。

有许多可用的 OpenFlow 控制器,您可以使用 Google 或您最喜欢的搜索引擎轻松找到更多控制器。一些流行的包括(按代码大小、功能和复杂性的近似顺序):

  • Ryu,一个用 Python 编写的基本(有点像 POX)OpenFlow 控制器框架
  • FAUCET,一个控制器(也是用 Python 编写的,基于 Ryu 框架),通过一个简单的 YML 配置文件支持以太网交换和 IP 路由以及其他功能
  • ONOS,一个功能齐全的网络操作系统,用 Java 编写
  • OpenDaylight,“最大的开源 SDN 控制器”

所有这些控制器都可以与 Mininet 或硬件网络一起使用。

Ryu

Ryu是一个用 Python 编写的基本 OpenFlow 控制器框架。它在 Mininet 中是开箱即用的:

1
2
$ sudo pip3 install ryu  # install ryu if it's not already installed
$ sudo mn --controller ryu

这将运行ryu.app.simple_switch。

您还可以在mn命令行中指定 Ryu 应用程序:

1
$ sudo mn --controller,ryu.app.simple_switch_13

您还可以将 Ryu 作为远程控制器运行。

在一个窗口中:

1
$ ryu run ryu.app.simple_switch

然后在另一个窗口中:

1
$ sudo mn --controller remote
 |