- 第一部分:基础常识
- 第二部分:基本拓扑结构介绍
- 第三部分基本命令
- 第四部分:测试主机间的连通性
- 第五部分:修改网络拓扑大小和类型(single,linear,python定义)
- 第六部分:(略)调整信息输出等级(默认info,可以设置debug:$ sudo mn -v debug)
- 第七部分:ID = MAC
- 第八部分:xterm并显示运用dpctl
- 待更新
一.基础常识
$ 表示在 shell 终端中输入的 Linux 命令
mininet> 表示在 Mininet CLI 中输入的命令
# 表示在超级用户下输入的 Linux 命令
二.最基本的拓扑建设
使用了命令行sudo mn。建立了默认的最小的拓扑结构,两个主机h1,h2连入一个交换机s1,还开启一个控制器
在 Wireshark 窗口中,看到交换机被连接到了控制器上(译注:产生了控制流数据包)。
由图观察可知首先
1.hello
2.feature request,基础配置
3.set config,继续进行一些新的配置
4.三次pack_in and pack_out (前两次为了查地址因为ipv6没有arf,所以运用组播。)
pack_in进行了组播监听
组播侦听发现协议是ipv6才有的协议,他的原理是当源主机发送一份数据到一个组播地址,所有加入了这个组播地址的成员都可以收到一份数据的拷贝。并且只有组播成员才可以接收到数据。路由器通过MLD协议,可以了解自己的直连网段上是否有IPv6组播组的侦听者,并在数据库里做相应记录。同时,路由器还维护与这些IPv6组播地址相关的定时器信息。
pack_out
洪泛
在无状态自动配置(StatelessAutoconfiguration)过程中,主机首先通过将它的网卡MAC地址附加在链接本地地址前缀1111111010之后,产生一个链路本地单点传送地址。
接着主机向该地址发出一个被称为邻居发现(neighbordiscovery)的请求,以验证地址的唯一性。 如果请求没有得到响应,则表明主机自设置的链路本地单点传送地址是唯一的。 否则,主机将使用一个随机产生的接口ID组成一个新的链路本地单点传送地址。 然后,以该地址为源地址,主机向本地链路中所有路由器多点传送一个被称为路由器请求(routersolicitation)的配置信息。 路由器以一个包含一个可聚集全球单点传送地址前缀和其它相关配置信息的路由器公告响应该请求。 主机用它从路由器得到的全球地址前缀加上自己的接口ID,自动配置全球地址,然后就可以与Internet中的其它主机通信了。 使用无状态自动配置,无需手动干预就能够改变网络中所有主机的IP地址。 更简单的理解是无状态就是自动分配,有状态是要用网管分给地址,不完全正解。 但基本可以简单这样理解。
5.port status
原因在于
6.多次pack_in and pack_out
已经确定了控制器的全球地址,通知给所有的路由器。
7.echo request and echo reply。持续通话
三.基本命令
显示所有可用的 Mininet CLI 命令:
mininet> help
- 1
显示网络中所有节点:
mininet> nodes
- 1
显示网络中的所有连接:
mininet> net
- 1
打印所有节点的信息:
mininet> dump

mininet> s1 ifconfig -a
- 1
这条命令会显示和交换机的网卡有关的信息,以及 VM 与外部(eth0)的链接。(ifconfig是linux中用于显示或配置网络设备(网络接口卡)的命令,英文全称是network interfaces configuring。配置网卡的IP地址语法例:ifconfig eth0 192.168.0.1 netmask 255.255.255.0)
注意的是:如果在 Mininet CLI 中输入的命令的第一个参数是某一主机、交换机或者控制器的名字,这条命令就会在那个节点上运行。相当于人称。
注意,只有网络是被虚拟的;每一个主机进程都能看到(和自己)同一组(的)进程和目录。例如,在主机界面打印所有主机进程列表:
mininet> h1 ps -a
- 1
这样子跟在根命名空间看到的是一样的:
mininet> s1 ps -a
- 1
在 Linux 中使用不同的进程空间是能做到的。但目前 Mininet 并不支持这种操作。然而把所有进程都放在根进程的命名空间中是便于 debug 的,因为这样子,你就能用 ps 、kill 等命令在控制台看到所有进程的信息。
四.主机互ping操作
mininet> h1 ping -c 1 h2
主机一的 ARP 包查询主机二的 MAC 地址,并同时发送 packe_in 到信息到控制器中。
然后控制器就会广播 packet_out 信息到网络中。
而主机二在收到这个 ARP 请求后,向对方发送回复。这个回复也会被发送到控制器中,然后控制器就会把这个数据包转发给主机一,并且下发一个流表项(到相关的交换机中)。
现在,主机一已经知道了主机二的 MAC 地址,并且能把它的 ping 数据包通过一个ICMP Echo 请求发送出去。这个请求,以及由主机二所发送的回复,都会被发送控制器,并变成一个流标项下发(以及要发送的实际数据)。
这个结构是最简单的默认拓扑下实现
mininet> pingall
实现所有主机互相ping
五. 修改网络拓扑大小和类型
1)
2)
(创建并测试)一个线性拓扑(每一台交换机都连接着一台主机,并且所有交换机都连接在一根总线上):
$ sudo mn --test pingall --topo linear,4

3)python定义
如果用 Python API,自定义的网络拓扑是很容易创建的。其中一个例子在 custom/topo-2sw-2host.py。这个拓扑把两台交换机直接相连,并给每一台交换机连上了一台主机:
"""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 __init__( self ):
"Create custom topo."
# Initialize topology
Topo.__init__( self )
# 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() ) }
在example下依然有很多例子。
PS顺带写下作业QAQ
在该拓扑下,使用dpctl下发流表,
完成两个host的ping操作,
用wireshark或者tcpdump抓包,
主机一的 ARP 包查询主机二的 MAC 地址,并同时发送 packe_in 到信息到控制器中。
然后控制器就会广播 packet_out 信息到网络中。
而主机二在收到这个 ARP 请求后,向对方发送回复。这个回复也会被发送到控制器中,然后控制器就会把这个数据包转发给主机一,并且下发一个流表项(到相关的交换机中)。
现在,主机一已经知道了主机二的 MAC 地址,并且能把它的 ping 数据包通过一个ICMP Echo 请求发送出去。这个请求,以及由主机二所发送的回复,都会被发送控制器,并变成一个流标项下发(以及要发送的实际数据)。
与简单拓扑不同的是ofp+arp用了两次。博主查端口号前四条分别是(ip都为)从60338到6633,6633-60338,60339-6633,6633-66339。猜测66338代表c3,66339代表c4.是控制器分别通知两个交换机去洪泛。这里具体也有点晕,欢迎指导。
之后就是h2查h1mac。
第二次以后的同路径h1 ping h2就不需要控制器这些了,直接查交换机中的流表自行处理。快了很多。)
7.ID = MAC
默认地,主机在启动的时候会被随机指派 MAC 地址。这样会使 debug 变得更加困难,因为每一次启动 Mininet 时,MAC 地址都会被改变,故某些主机之间的控制流会变得难以传输。
–mac 选项是十分有用的,并且能把主机的 MAC 地址和 IP 地址设置成为简单的、唯一的、便于阅读的 ID。
变换之前:
$ 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
然而,向 Linux 报告的交换机数据端口仍然是随机的。这是因为你能对一个数据端口用 OpenFlow 来指定端口,正如在 FAQ 中提到的那样。这是一个你可能会忽略的小细节。
8.xterm并显示运用dpctl
要为每一个主机和交换机都启动一个XTerm窗口,用 -x 选项:
在 XTerm 窗口“switch: s1 (root)”中运行:
# dpctl dump-flows tcp:127.0.0.1:6634
- 1
不会有输出信息;交换机也不会增加流表项。
现在,在标题为“host: h1”的 XTerm 窗口中运行:
# ping 10.0.0.2
- 1
回到 s1 并打印其中的流表:
# dpctl dump-flows tcp:127.0.0.1:6634
- 1
你应该能看到很多个流表项。
通过检查 ifconfig 来确认一个 XTerm 窗口是否在跟命名空间中;如果所有的网卡都显示出来了(包括 eth0),那么这个窗口就是在根命名空间中。另外,它的标题应该包括“(root)”。