mininet学习记录

为了以后方便写文档,把途中学习到的东西暂时的先记录下来。
一.安装mininet
在安装中遇到了几个问题,首先是在中文版的ubutun下安装mininet报错,报错信息也没有太大看懂,于是就重新装了一个英文版的Ubuntu系统,在安装的过程中倒是没有出现太大的问题。
使用的是官网中的第二中方法进行安装的:
1.安装git以及下载mininet

sudo apt install git git clone git://github.com/mininet/mininet

2.查看mininet中存在版本
cd mininet git tag# list available versions git checkout -b 2.2.1 2.2.1# or whatever version you wish to install cd ..

记得cd.. 要把目录退出到mininet文件夹之外。
3.使用命令安装mininet
mininet/util/install.sh -nfv

我的需求参数-nfv就能够满足了,这三个参数代表了安装mininet,OpenFlow reference switch以及 Open vSwitch
顺道把嗅探器OpenFlow wireshark 给安装了
mininet/util/install.sh -h

4.验证是否安装成功:
在验证之前,先把linux中的一些网络管理工具下载好,主要是ifconfig这个工具,不然也会报错。
sudo apt install net-tools sudo mn --test pingall

若是输出了默认网络之间相互ping的信息,则证明安装成功了。
记录一个小问题,在安装的过程中,git clone的速度不知道为啥突然很慢,于是直接在mininet的github主页下载了其安装包并解压后,当时也是直接按照上面的流程给安装了,但是出现了问题,说找不到mininet这个文件夹。后来发现下载的安装包的名字是mininet-master,所以把名字改回mininet就好了。

二.mininet的初步使用
首先把mininet在github上的introduction和官网上的walkthrough都浏览了一遍,大概了解了mininet的工作流程,把需要用到的几个重要的部分大概的描述一下。
1. 进入到mininet
sudo mn

一切运行mn的指令都必须在sudo的操作下才能够进行,该指令打开了一个mininet默认的拓扑结构,两个主机和一个交换机。
接着就进入到了mininet的操作界面,在此界面下可以进行的基本操作:
mininet> help展示出mininet的一些基本指令和使用介绍 mininet> nodes展示出拓扑中所有的节点 mininet> net展示出拓扑中节点以及接口的链接情况 mininet> dump展示出所有节点的具体信息:ip和接口

2. mininet中的bash操作
若想要对其中的一个节点执行bash操作,只需要在mininet之前加入该节点的名称即可,如要查看节点h1和s1的网络配置:
mininet> h1 ifconfig -a mininet> s1 ifconfig -a

这里有个点需要注意,因为在mininet中默认host建立时是独立的namespace,而交换机的namespace是和linux内核的root namespace共享的。所以在h1的ifconfig中会看到自己的h1-eth0,但是你在本机上ifconfig时,是无法查看到的,而s1的ifconfig信息与本地主机的ifconfig信息是一样的,namespace主要是隔离网络以及其它资源,具体可参考linux中命名空间以及mininet命名空间应用 。
因为命名空间的使用,可以让mininet中虚拟出的host能够配置自己的网络环境,并且不同host之间是相互独立的,但是每次关闭的时候原来配置的host网络环境就消失了,这是因为mininet中虚拟的host只是其中的一个进程,随着进程的关闭,host消失了,自然网络配置也消失了。
其他的bash操作也可以类似于上面的操作,如一些基本的bash操作:ps -a,ls,cat,route等。
3. mininet中测试节点间的连通性
利用ping 操作来进行连通性检查,如检查h1与h2之间的连通:
h1 ping -c 1 h2

由于是第一次的建立两个host之间的通信,会有一个ARP来寻找目的主机MAC的过程,所以会比较慢,但是这个过程会被记录下来,第二次的两个host之间的ping就会快很多。
当然两个主机之间是可以通信的,若是在h1上运行一个简单的HTTP服务时,h2可以去获取h1的服务。
mininet> h1 python -m SimpleHTTPServer 80 & mininet> h2 wget -O - h1 ... mininet> h1 kill %python

4.在本机的命令行bash上的操作
$ sudo mn --test pingpair测试拓扑之间的连接,没有写具体拓扑则为默认拓扑 $ sudo mn --test iperf测试拓扑节点间的带宽 $ sudo mn --test pingall --topo single,3修改了拓扑,并测试拓扑的连通性 $ sudo mn --test pingall --topo linear,4与上一样 $ sudo mn -x打开所有节点的bash框

也可以在bash命令中修改链路之间的参数,如延迟和带宽:
$ sudo mn --link tc,bw=10,delay=10ms mininet> iperf ... mininet> h1 ping -c10 h2

当然这个修改在Python的API中更加容易修改,笔者偏向于在Python的API中修改。
5.自定义拓扑规则
在第4个小节中使用到的拓扑都是mininet内置的,可能满足不了平常工作的需求,于是需要自定义一些拓扑,并且也可以在bash中进行执行,自定义如下,程序写入在custom/topo-2sw-2host.py文件中:
from mininet.topo import Topoclass 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() ) }

注意最后那个字典,topos是规定的,其中的key可以修改,但是在bash中需要用到该key。在bash中的使用如下:
$ sudo mn --custom ~/mininet/custom/topo-2sw-2host.py --topo mytopo --test pingall

MAC地址也是很重要的一个参数,因为在mininet运行时,对host和switch的mac是随机生成,在调试中就会遇到很大的问题,所以给在bash命令中加入--mac这个参数,让mininet按顺序的给host安排mac地址,当然也可以在Python API中设置对应的MAC。
6.mininet中使用Python语句
在建立拓扑之后,mininet命令行中可以通过在开头加入py来进行执行Python语句
mininet> py 'hello ' + 'world' mininet> py locals()打印出所有的变量 mininet> py dir(s1)打印出s1的所有可用的属性和函数 mininet> py h1.IP()查看h1的Ip

6. 使用ssh进行host之间的连接
测试运行mininet自带例子中的ssh.py,构造的拓扑结构为1个switch和4个hosts。在利用scp函数进行在两个host之间传输数据:
$ sudo ~/mininet/examples/sshd.py

打开了host2的xterm,从而使用scp来把host2 的Download底下一个structure1_1文件传输到host1中用户john的/home/john下。
scp /Download/structure1_1 john@10.0.0.1:/home/john

在使用该指令时出现了几次错误,首先是没有注意到需要传输文件的权限,把它改成了777的权限;然后是没有注意到传输到目的文件夹的权限,刚开始传的地方设置的是/etc底下,john没有这个权限,于是改成了/home/john底下,就存在权限了。
还有一个问题就是,不知道为啥不能够直接以root的用户传输,一直显示密码错误,但是都改了好几次的密码,还是显示密码错误,于是只能通过john用户进行保存了文件了。
还有一个有趣的事情是,所有的host都是使用相同的文件系统。而且我自己编写的拓扑结构不知道为嘛不能进行ssh连接,显示connect refuse,有时间需要对这个ssh.py文件好好看一下。

三.mininet的可视化操作
其实就是运行了mininet自带例子中的一个miniedit.py文件,然后生成了一个GUI,在此GUI上进行拓扑结构的画图就ok了,开始我话的一个拓扑图如下:

mininet学习记录
文章图片

有两个网段:ws和h1-h3,只要设置好两个网段之间的IP和默认路由就OK了,然后在r1中打开转发机制就能够相互ping通了,但是不能够进行ssh的链接。对于r1:需要设置,sysctl ipv4.ip_forward=1,开启转发机制。
但是设置对于r1来说设置路由的话需要在命令行中设置,所以需要用ifconfig 来修改IP,route add 来增加路由信息。
四.Python API的使用
对于有一定Python基础来说,更加喜欢使用Python的API来编写结构,并且设置各类参数,以及设置路由和开启转发机制,都能够在Python脚本中实现,所以显得更加容易操作。并且按照官网分成了低级接口、中级接口和高级接口。笔者还是需要使用高级接口,下面Python代码是实现GUI画出的拓扑图:

from mininet.topo import Topo from mininet.net import Mininet from mininet.node import Node from mininet.log import setLogLevel, info from mininet.cli import CLIclass NetworkTopo(Topo): def build(self, **_opts): default_IP1 = '192.168.100.254/24' default_IP2 = '192.168.1.100/24' client_IP1 = '192.168.1.101/24' edge1 = '192.168.100.10/24' edge2 = '192.168.100.20/24' edge3 = '192.168.100.30/24' edge_GW = '192.168.100.254' client_GW = '192.168.1.100' # add the routers r1 = self.addNode('r1', ip=default_IP1) s1 = self.addSwitch('s1') self.addLink(s1, r1, bw=10, delay='5ms',loss=10,intfName2='r1-eth0', params2={'ip': default_IP1}) h1 = self.addHost('h1', ip=edge1, defaultRoute=edge_GW,mac='00:00:00:00:00:01') h2 = self.addHost('h2', ip=edge2, defaultRoute=edge_GW,mac='00:00:00:00:00:02') h3 = self.addHost('h3', ip=edge3, defaultRoute=edge_GW,mac='00:00:00:00:00:03')u1 = self.addHost('u1', ip=client_IP1, defaultRoute=client_GW,mac='00:00:00:00:01:01') self.addLink(u1, r1, bw=10, delay='5ms',loss=10, intfName2='r1-eth1', params2={'ip': default_IP2})for h, s in zip([h1, h2, h3], [s1, s1, s1]): self.addLink(h, s, bw=10, delay='5ms',loss=10)def run(): "Test the first structure" topo = NetworkTopo() net = Mininet(topo=topo) # adding the default gateway net['u1'].cmd('route add default gw 192.168.1.100') for i in ['h1', 'h2', 'h3']: net[i].cmd('route add default gw 192.168.100.254') # opening the ip forward signal net['r1'].cmd('sysctl -w net.ipv4.ip_forward=1') net.start()info('***Routing Table on r1:\n') info(net['r1'].cmd('route -n')) info('***ping the u1 to h1\n') net.pingAll info(net['u1'].cmd('ping -c 5 r1')) info('Testing yhe bandwidth between u1 and h1\n') h1, u1 = net.getNodeByName('h1','u1') net.iperf((h1,u1),l4Type='UDP' ) CLI(net) net.stop()if __name__ == '__main__': setLogLevel('info') run()

其中有几个上面没有提到的操作,net['nodename'].cmd.('bash operate'),在Python脚本中实现bash操作。
在此拓扑结构之上,操作了一下通过ssh进行两个主机之间交换文件,步骤如下:
【mininet学习记录】因为在之前直接使用scp进行文件传输的时候,一直显示connect refuse,于是在传输之前对ssh进行一些简单操作
/usr/sbin/ssh在需要传输文件的主机上都需要运行该操作 ps -a | grep ssh查看ssh服务是否开启

修改了一下传输的端口,在/etc/ssh/sshd_config这个文件之中修改,我的这个文件中port 22被注释掉了,于是去掉注释就好了。
server sshd restart重启一下ssh服务

在mininet打开u1的xterm,进行文件的传输
scp Download/structure1_1 john@192.168.100.20:/home/john

当然,为了省去每次都需要在mininet命令行中执行ssh的开启工作,可以在Python脚本中就添加进去,即:
keys = ['u1', 'h1', 'h2', 'h3'] for key in keys: net[key].cmd('/usr/sbin/sshd')


五.后续工作
之后的工作是如何让host之间调配任务,实现任务的计算等,以及搭载真正的硬件。


.

    推荐阅读