Mininet教程(七)Mininet Walkthrough

本文档介绍了Mininet的基本操作,包括使用Wireshark观察OpenFlow控制流,测试主机间连通性,运行Web服务器和客户端,自定义拓扑,以及链路参数调整。此外,还涉及了Mininet的高级命令如回归测试和不同类型的交换机。通过示例展示如何使用Mininet命令行接口和Python接口进行网络调试。
Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

Mininet教程(七)Mininet Walkthrough

官网mininet walkthrough不完全翻译,原文

本教程展示了大部分mininet命令,以及和Wireshark的交互应用。

日常使用指令

显示mininet开启选项

$ sudo mn -h

开启Wireshark

为了通过Wireshark查看控制流,首先打开Wireshark

$ sudo wireshark 

在Wireshark过滤器中,输入openflow"of",点击"Apply"。在Wireshark界面中,点击"Capture",然后"Interfaces",随后选择loopback接口"lo"。当前没有openflow的包显示在界面中。
Wireshark在Mininet虚拟镜像中默认安装的。如果你的系统没有Wireshark以及openflow插件,可以通过Mininet的安装脚本进行安装,命令如下:

$ cd ~
$ git clone https://github.com/mininet/mininet  # if it's not already there
$ mininet/util/install.sh -w

在运行Wireshark中遇到问题,譬如$DISPLAY not set,可以查看这里

我个人Wireshark版本2.6.8,界面和上述稍有不同:点击"捕获",借口选择"Loopback:lo",过滤器输入"openflow_v1"。

主机与路由器之间交互

启动最小拓扑并进入命令行界面:

$ sudo mn

此时Wireshark窗口中,已经可以看到捕获的openflow包。
Wireshark捕获的openflow包
显示MIninet 命令行指令:

mininet> help

显示节点:

mininet> nodes

显示链路:

mininet> net

显示节点所有信息:

mininet> dump

如果命令行的第一个字符串是主机,交换机或者控制器的名字,那么后续的命令就是在该节点中执行。例如:

mininet> h1 ifconfig -a

便能看到主机的"h1-eth0"和"lo"接口。在早期Linux系统中,接口"h1-eth0"在执行ifconfig命令时不能被看到(网络命名空间从linux内核3.8开始支持)。相反的,交换机默认在根网络的命名空间内,因此执行switch的命令和跟平常终端结果一样:

mininet> s1 ifconfig -a

其他例子还有执行"arp"和"route"指令在"s1"和"h1"上。
为每个主机,交换机和控制器都设置一个独立的命名空间也是可以的,但这样没多大好处,除非是在一个复杂的多个控制器网络中。Mininet也支持这样,详情见–innamespace选项。
在Mininet中,只有网络是虚拟的,每个节点其实都有一样的进程和目录。譬如查看主机下的进程目录:

mininet> h1 ps -a

这和交换机下的进程是完全一样的(当然除了ps):

mininet> s1 ps -a

在Linux 容器中设置不同的进程空间也是可以的,但目前Mininet不这么做。将每个进程都置于主进程命名空间会使得调试比较方便,因为你可以看到所有的进程。

测试主机之间连通性

执行命令:

mininet> h1 ping -c 1 h2

在wireshark中抓包可以看到:
在这里插入图片描述
h1主机根据地址解析协议(ARP)分析h2的MAC地址,因为当前并不知道谁是h2,因此发送一个packet_in消息给控制器。控制器随后发送packet_out命令将这条指令广播泛洪向交换机的其他接口。当h2看到这条地址解析请求后会发送一个答复给控制器,控制器将它返回给h1并推送一个流表记录(flow entry)。当h1知道了h2的地址之后,就会通过一个报文控制协议(ICMP)的echo request来ping。这个echo request以及它的答复都会经过控制器并导致流表推送。
再次执行:

mininet> h1 ping -c 1 h2

这次用的ping时间更短。因为这次报文控制已经在上一次的ping中被推送到交换机了。所以这次不会有控制流产生,数据包直接经过交换机,速度更快。
一个更简单的方式实在命令行界面执行"pingall",测试所有主机对的通信:

mininet> pingall

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

Mininet的主机可以运行任何底层Linux系统/虚拟机以及文件系统支持的命令和应用。也可以运行任意的bash命令,包括任务控制的"&",“jobs”,"kill"等等。
接下来,在h1上启动一个简单的HTTP服务器,并从h2发送一个请求,最后关闭这个服务器。

mininet> h1 python -m SimpleHTTPServer 80 &
mininet> h2 wget -O - h1
mininet> h1 kill %python

退出命令行界面:

mininet> exit

清理缓存

如果Mininet因为某些原因崩溃了,可以清理:

$ sudo mn -c

高级命令

运行回归测试

有的时候不必进入命令行界面,Mininet也可以运行自带的回归测试:

$ sudo mn --test pingpair

该命令创建了一个最小拓扑,开启openflow控制器,对所有的主机对进行ping测试,最后删除拓扑和控制器。
另外一个常用的测试命令是"iperf"(大概需要10秒左右完成):

$ sudo mn --test iperf

这条命令同样创建了一个一样的Mininet环境,在一台主机上运行iperf服务器,另一台主机上运行iperf客户端,进行带宽解析。

改变拓扑大小和类型

默认的拓扑是一个交换机连接俩主机,可以通过"–topo"选项改变拓扑并设置不同参数。例如,生成一个一个交换机带三主机的拓扑并进行"pingall"回归测试:

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

另一个例子线型拓扑,每个主机都有一个对应的交换机,所有交换机连成一条线:

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

参数化拓扑是Mininet一个非常实用和重要的特征。

链路修改

Mininet2.0允许设置链路参数,可以通过启动命令进行设置:

$ sudo mn --link tc,bw=10,delay=10ms
mininet> iperf
*** Iperf: testing TCP bandwidth between h1 and h2 
*** Results: ['9.50 Mbits/sec', '12.0 Mbits/sec']
mininet> h1 ping -c10 h2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=48.1 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=40.8 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=40.4 ms
64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=40.2 ms
64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=40.2 ms
64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=40.1 ms
64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=40.4 ms
64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=40.3 ms
64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=40.1 ms
64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=40.3 ms

根据设置,单条链路延时10ms,那么ping测试里RTT大概40ms左右。这是因为ICMP请求要过两条链路(从h1到交换机,从交换机到h2),ICMP的答复也要过这两条链路。
更多的链路设置在这里

调整输出

默认的信息输出等级是"info",输出Mininet在启动和关闭时的动作。和"debug"设置比较:

$ sudo mn -v debug
mininet> exit

"debug"设置会输出更多的细节信息。"output"设置可以直接输出命令行界面而没有中间的信息。

$ sudo mn -v output
mininet> exit

除此之外还可以设置"warning"等级,在回归测试时可以隐藏不需要的功能输出。

自定义拓扑

自定义拓扑可以使用提供的python借口,已有的一个例子在安装目录下custom/topo-2sw-2host.py中。调用自定义的拓扑并进行回归测试:

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

ID=MAC

默认主机分配的MAC地址都是随机的。每次开启Mininet,MAC地址都会改变,这使得调试以及相应的控制流都比较难进行。这时候"–mac"就非常有用了,它使得主机的MAC和IP地址简单易读且唯一。
设置前:

$ sudo mn
mininet> h1 ifconfig
h1-eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.1  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fe80::d4ba:1aff:fee2:fc7a  prefixlen 64  scopeid 0x20<link>
        ether d6:ba:1a:e2:fc:7a  txqueuelen 1000  (Ethernet)
        RX packets 11  bytes 942 (942.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 586 (586.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

mininet> h2 ifconfig
h2-eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.2  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fe80::945d:f3ff:fe94:74be  prefixlen 64  scopeid 0x20<link>
        ether 96:5d:f3:94:74:be  txqueuelen 1000  (Ethernet)
        RX packets 14  bytes 1136 (1.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8  bytes 656 (656.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

设置后:

$ sudo mn --mac
mininet> h1 ifconfig
h1-eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.1  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fe80::200:ff:fe00:1  prefixlen 64  scopeid 0x20<link>
        ether 00:00:00:00:00:01  txqueuelen 1000  (Ethernet)
        RX packets 12  bytes 1052 (1.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 646 (646.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

mininet> h2 ifconfig
h2-eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.2  netmask 255.0.0.0  broadcast 10.255.255.255
        inet6 fe80::200:ff:fe00:2  prefixlen 64  scopeid 0x20<link>
        ether 00:00:00:00:00:02  txqueuelen 1000  (Ethernet)
        RX packets 15  bytes 1246 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9  bytes 786 (786.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

相反的,交换机的MAC地址依然是系统随机分配的。这是因为你可以通过Openflow协议对数据端口分配MAC地址。

XTerm显示

对于更复杂的调试,可以在开启mininet时打开一个或多个XTerm,使用"-x"选项:

$ sudo mn -x

几秒种后,XTerm会弹出来,窗口名字已被自动生成。默认的,只有主机在不同的命名域里面,交换机的XTerm没太有必要(因为这和平常的终端一样),但这样执行调试命令的时候比较方便。
例如,在交换机s1"switch:s1(root)"里面执行:

$ dpctl dump-flows tcp:127.0.0.1:6634

这时并没有输出,数据流没有经过交换机。在主机h1中ping主机2:

$ ping 10.0.0.2

回到交换机s1再次监听端口,就会发现有多条数据流经过。另外一种方法是在Mininet的命令行界面中监听活动端口,这样更方便不用开启XTerm以及不用人工设定IP和端口。还可以在XTerm中通过ifconfig命令检测是否在根命名域中,如果显示所有的接口包括eth0,那么就是位于根命名域。另外,标题栏应该会包含root字样。
当在Mininet命令行中执行exit,XTerm也会自动退出。
6634是交换机默认的监听端口。可以通过ovs-vsctl命令查看监听端口passive listener-ptcp:

$ ovs-vsctl show
...
	Bridge "s1"
		...
		COntroller "ptcp:6654"
		...

其他交换机类型

使用用户态交换机:

$ sudo mn --switch user --test iperf

和内核态交换机相比,用户态的带宽要小很多。如果进行ping测试,会发现延时也要比内核态大。这是因为数据包要经过额外的内核到用户空间的转换。
另外一种交换机类型是Open vSwitch(OVS),TCP带宽和内核态相仿甚至略快一些:

$ sudo mn --switch ovsk --test iperf

Mininet 基准测试

记录从代开到关闭拓扑的时间:

$ sudo mn --test none

各自都有命名域(仅对用户态)

默认下,主机各自拥有自己的命名域,交换机和控制器都在根命名域下。可以通过–innamespace选项使得所有设备都在自己的命名域:

$ sudo mn --innamespace --user switch

交换机和控制器通信不用loopback而是一个分开的桥接控制。

Mininet命令行界面的命令

显示选项

$ sudo mn
...
mininet> help
...

Python解释器

如果Mininet命令行界面第一个就是py,那么命令会被python执行。这对于拓展Mininet以及测试内部工作流很有用。每一个主机,交换机和控制器都有一个对应的Node对象。
在Mininet命令行:

mininet> py 'hello '+'world'

打印可用的本地变量:

mininet> py locals()

查看Node对象的方法和属性,使用dir()函数:

mininet> py dir(s1)

可以阅读Node对象方法的在线说明文档,按q退出

mininet> py help(h1)

也可以执行变量的方法:

mininet> py h1.IP()

关闭\打开链路

mininet> link s1 h1 down
mininet> link s1 h1 up

XTerm显示

mininet> xterm h1 h2

Python接口示例

这里给出了如何使用应用接口的示例。

SSH daemon

其中一个例子是在每个主机上运行SSH daemon,要使用绝对地址:

$ sudo ~/mininet/examples/sshd.py

从另一个终端中可以ssh接入任意主机并运行交互命令:

$ ssh 10.0.0.1
$ ping 10.0.0.2
...
$ exit

下一步

OpenFlow 教程
Mininet介绍和Python接口

补充说明

使用远程控制器

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

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值