mininet实验部分总结

一、Mininet简介

Mininet是一个可以在有限资源的普通电脑上快速建立大规模SDN原型系统的网络仿真工具。该系统由虚拟的终端节点(End-Host)、OpenFlow交换机、控制器(也支持远程控制器)组成,这使得它可以模拟真实网络,可对各种想法或网络协议等进行开发验证。目前Mininet已经作为官方的演示平台对各个版本的OpenFlow协议进行演示和测试。

Mininet是基于Linux Container这一内核虚拟化技术开发出的虚拟化平台,其实现虚拟化主要是用到了Linux内核的Network namespace资源隔离机制。Linux的Network namespace机制可以让每个namespace拥有独立的网络设备、网络协议栈和端口等。Mininet正是利用了Linux这种Networknamespace机制,才可以在一台电脑上创建多台虚拟主机。此外,Mininet建立的网络拓扑的交换节点可以是OpenvSwitch、Linux Bridge等软件交换机,交换节点之间的链路采用Linux的vethpair(virtual Ethernet pair)机制实现,控制器可以部署在网络可达的任意地方。因此,Mininet可以定制任意灵活的SDN网络拓扑,为实验用户提供快捷可靠的实验环境。

Mininet架构按datapath的运行权限不同,分为kernel datapath和userspace datapath 两种,其中kernel datapath把分组转发的逻辑编译进入Linux内核,效率非常高;userspace datapath把分组转发逻辑实现为一个应用程序,叫做ofdatapath,效率虽不及kernel datapath,但更为灵活,更容易重新编译。

Mininet的kernel datapath架构如图1所示,控制器和交换机的网络接口都在root 命名空间中,每个主机都在自己独立的命名空间里,这也就表明每个主机在自己的命名空间中都会有自己独立的虚拟网卡eth0。控制器就是一个用户进程,它会在loopback上预留的6633端口监听来自交换机安全信道的连接。每个交换机对应几个网络接口,比如s0-eth0、s0-eth1以及一个ofprotocol进程,它负责管理和维护同一控制器之间的安全信道。
Mininet的userspace datapath架构与kernel datapath架构不同,网络的每个节点都拥有自己独立的namespace。因为分组转发逻辑是实现在用户空间,所以多出了一个进程叫ofdatapath。另外,Mininet除了支持kernel datapath和userspace datapath这两种架构以外,还支持OVS交换机。OVS充分利用内核的高效处理能力,它的性能和kernel datapath相差无几。
二、Mininet安装
Mininet的安装有三种方式:一种是从网上直接下载安装好Mininet的虚拟机镜像,然后在VMware或者VirtureBox上打开Mininet虚拟机即可。这种安装方法是最简单的,但是该方法不支持最新版本的OpenvSwitch。第二种是在本地安装Mininet源代码。该安装方法在安装过程中可以设置OpenvSwitch的版本。第三种是安装Mininet文件包,该安装方法也不支持最新版本的OpenvSwitch。推荐使用第二种安装方法,安装命令即参数解释如下:

1、 命令格式

./install.sh [options]

2、 参数解释

典型的[options]主要有下面几种:

“-a”:完整安装,包括Mininet VM,还包括Open
vSwitch的依赖关系、OpenFlow、Wireshark分离器和POX等。默认情况下,这些工具将被安装在home目录中。

“-nfv”:安装Mininet核心文件及依赖、OpenFlow和Open vSwitch。

“-s mydir”:使用此选项可将源代码建立在一个指定的目录中,而不是home目录。

所以,可能会用到下面的某一个命令来安装Mininet:

  • install.sh -a 完整安装(默认安装在home目录下)
  • install.sh -s mydir -a 完整安装(安装在其他目录)
  • install.sh -nfv 安装Mininet+用户交换机+OVS(安装在home目录下)
  • install.sh -s mydir -nfv 安装Mininet+用户交换机+OVS(安装在其他目录下)

步骤1 以root用户登录主机,以下命令全部以root身份运行。
步骤2 执行ll命令,查看平台预置的Mininet安装包,如下图所示。
enter description here
步骤3 执行以下命令,查看当前Mininet版本,查询结果如下图所示。

# cd mininet
# cat INSTALL\|more

说明:Mininet2.1.0p1及以后的版本可以原生支持OpenFlow1.3,所以我们这次安装的Mininet2.3.0d1版本支持OpenFlow1.3协议。

步骤4 源码树获取成功以后,执行以下命令安装Mininet。

# ./install.sh -a

说明:若使用其它命令安装,在安装前请先执行apt-get update命令更新软件列表。

步骤5 安装完成以后,通过简单的命令测试Mininet的基本功能。执行以下命令:
# mn --test pingall

步骤6 执行 mn —version ,查看安装好的Mininet版本。

Mininet的可视化应用

实验原理

Mininet 2.2.0版本中内置了一个Mininet可视化工具Miniedit,使用Mininet可视化界面方便了用户自定义拓扑创建,为不熟悉Python脚本的使用者创造了更简单的环境,界面直观,可操作性强。Mininet在“/home/openlab/openlab/mininet/mininet/examples”目录下提供miniedit.py脚本,执行脚本后将显示Mininet的可视化界面,在界面上可进行自定义拓扑和自定义设置。可视化界面创建拓扑会生成一个python文件,创建的拓扑可以直接运行,也可以通过python文件启动。Miniedit的界面如图所示:
MiniEdit有一个简单的用户界面,在画布的左侧显示一排工具图标,并在窗口顶部显示一个菜单栏。左侧控件依次是Select、Host、Switch、Legancy switch、Legancy router、Netlink、Controller、Run、Stop。
(1)Select:该选择工具用于移动画布上的节点,单击并拖动任何现有的节点。要选择现有的节点或链接,只需将鼠标指针悬停在它上面,然后右键单击以显示所选元素的配置菜单,或者按Delete键以删除选定的元素。
(2)Host:该主机工具用于在画布上创建主机节点。单击该工具,然后单击画布上希望放置节点的任何位置。只要该工具保持选定状态,就可以通过单击画布上的任意位置继续添加主机。用户可以通过右键单击它并从菜单中选择“属性”来配置每个主机。
(3)Switch:该交换机工具用于在画布上创建支持OpenFlow交换机,这些交换机将连接到控制器。该工具的操作方式与Host工具相同,用户可以通过在菜单上右键单击选择“属性”来配置每个交换机。
(4)Legancy switch:该传统交换机工具用于创建具有默认设置的学习以太网交换机。交换机将独立运行,无需控制器。传统交换机不能被配置、设置生成树禁用功能,所以不能在环中连接传统交换机。
(5)Legancy router:该传统路由器工具用于创建独立运作且无需控制器的基本路由器。它基本上只是一个启用了IP转发的主机。传统路由器不能在MiniEdit GUI上配置。
(6)Netlink:该网络链路工具用于在画布上创建节点之间的联系。通过选择Netlink工具创建链接,然后单击一个节点并将链接拖到目标节点。用户可以通过右击选择菜单中的“属性”来配置每个链接的属性。
(7)Controller:该控制器工具用于创建控制器,可以添加多个控制器。默认情况下,MiniEdit创建一个Mininet OpenFlow控制器,它实现控制交换机的行为。控制器类型可以配置,用户可以通过右键单击每个控制器的“属性”来配置每个控制器。
(8)Run/Stop:运行按钮将运行显示在当前画布中的MiniEdit模拟场景,停止按钮将停止运行中的节点。当MininEdit仿真处于“运行”状态时,右键单击网络元素会显示操作功能。例如,打开终端窗口,查看交换机配置或将链接状态设置为“up”或“down”。

实验步骤

一、实验环境检查
步骤1. 选择控制器,单击终端图标,打开终端,执行 ifconfig 命令查看控制器IP,如下图所示。

步骤2. 登录主机1,执行ifconfig命令查看Mininet的IP地址,如下图所示。

二、通过可视化界面构建拓扑
步骤1. 选择主机1,执行如下命令启动Mininet可视化界面。

$ cd openlab/mininet /mininet/examples
 $ sudo ./miniedit.py

Mininet可视化界面如下图所示。

步骤2. 添加如下图所示的网络组件,左击鼠标选择左侧的“线”,拖动鼠标连接网络组件,如下图所示。

说明:在用鼠标选择左侧的对应的网络组件,然后在空白区域单击鼠标左键即可添加网络组件。

步骤3. 鼠标悬停在控制器上,按住鼠标右键,选择Properties即可设置其属性。设置controller type为“remote controller”,并填写控制器的端口和IP地址,如下图所示。

步骤4. 单击“OK”,命令行执行信息显示如下。

步骤5. 鼠标悬停在主机上,按住鼠标右键,选择Properties即可设置其属性。在主机属性中自行设置主机的IP地址等,如下图所示。

步骤6. 单击“OK”,命令行执行信息显示如下。

步骤7. 鼠标悬停在交换机上,按住鼠标右键,选择Properties即可设置其属性。交换机属性配置页面如下图所示,本实验中交换机采用默认配置即可。

步骤8. 单击菜单栏中的“Edit”,选择“Preferences”,进入Preferences界面,勾选“Start CLI”和OpenFlow协议版本,如下图所示。

说明:可勾选“Start CLI”,这样的话,就可以命令行界面直接对主机等进行命令操作。

步骤9. 单击“OK”,命令行执行信息显示如下。

步骤10. 单击左下角“run”按钮,即可启动Mininet,运行设置好的网络拓扑,如下图所示。

步骤11. 查看终端页面显示的运行的拓扑信息,如下图所示。

步骤12. 选择“File -> Export Level 2 Script”,将其保存为Python脚本,如下图所示。

说明:以后直接运行Python脚本即可重现拓扑,重现拓扑后可在命令行直接操作。

步骤13. 在Mininet CLI中输入Mininet常用命令,查看拓扑中的节点和连接关系,主机之间互Ping测试拓扑连通性,如下图所示。

步骤14. 单击可视化界面的“X”图标,退出可视化。
说明:若无法退出,请切换到Mininet CLI中执行exit退出Mininet,将自动关闭Mininet可视化界面。

步骤15. 在“/home/openlab/openlab/mininet/mininet/examples”目录下,执行如下命令,运行脚本。
$ sudo python topo.py

Mininet命令延伸实验扩展

实验原理

Mininet是一个轻量级软件定义网络和测试平台;它采用轻量级的虚拟化技术使一个单一的系统看起来像一个完整的网络运行的内核系统和用户代码,也可简单理解为 SDN 网络系统中的一种基于进程虚拟化平台,它支持OpenFlow等各种协议,Mininet 也可以模拟一个完整的网络主机、链接和交换机在同一台计算机上且有助于互动开发、测试和演示,尤其是那些使用OpenFlow 和 SDN 技术;同时也可将此进程虚拟化的平台下代码迁移到真实的环境中。

实验步骤

一、命令行创建拓扑
步骤1 登录Mininet主机,打开命令行终端,执行sudo mn —topo minimal命令创建最小的网络拓扑,一个交换机下挂两个主机,如下所示。

步骤2 执行如下命令,创建每个交换机连接一个主机,交换机间相连接。本例:4个主机,4个交换机。

exit
$ sudo mn --topo linear,4

步骤3 执行如下命令,创建每个主机都连接到同一个交换机上。本例:3个主机,1个交换机。

exit
$ sudo mn --topo single,3

步骤4 执行如下命令,定义深度和扇出形成基于树的拓扑。本例:深度2,扇出2。。

exit
$ sudo mn --topo tree,fanout=2,depth=2

二、Python脚本定义拓扑
步骤1 使用Python脚本定义拓扑–topo linear,4。
在装有Mininet镜像的虚拟机中执行命令sudo vim linear.py新建文件linear.py,添加以下内容。

from mininet.net import Mininet
from mininet.topo import LinearTopo
Linear4 = LinearTopo(k=4)  #四个交换机,分别下挂一个主机
net = Mininet(topo=Linear4)
net.start()
net.pingAll()
net.stop()

执行命令sudo chmod +x linear.py修改文件linear.py为可执行文件。
执行命令sudo python linear.py运行脚本,结果如下所示。

步骤2 使用Python脚本定义拓扑–topo single,3。
在装有Mininet镜像的虚拟机中执行命令sudo vim single.py新建文件single.py,添加以下内容。

from mininet.net import Mininet
from mininet.topo import SingleSwitchTopo
Single3 = SingleSwitchTopo(k=3)   #一个交换机下挂3个主机
net = Mininet(topo=Single3)
net.start()
net.pingAll()
net.stop()

执行命令sudo chmod +x single.py修改文件single.py为可执行文件。
执行命令sudo python single.py运行脚本,结果如下所示。

步骤3 使用Python脚本定义拓扑–topo tree,depth=2,fanout=2。
在装有Mininet镜像的虚拟机中执行命令sudo vim tree.py新建文件tree.py,添加以下内容。

from mininet.net import Mininet
from mininet.topolib import TreeTopo
Tree22 = TreeTopo(depth=2,fanout=2)
net = Mininet(topo=Tree22)
net.start()
net.pingAll()
net.stop()

执行命令sudo chmod +x tree.py修改文件linear.py为可执行文件。
执行命令sudo python tree.py运行脚本,结果如下所示。

步骤4 如果是非上述三种类型的拓扑,那么下面介绍一种适合各种拓扑形式的脚本创建模式。本例:1个交换机,2个主机,并且赋予主机IP地址。
在装有Mininet镜像的虚拟机中执行命令sudo vim any.py新建文件any.py,添加以下内容。

from mininet.net import Mininet
net = Mininet()
Creating nodes in the network.
c0 = net.addController()
h0 = net.addHost('h0')
s0 = net.addSwitch('s0')
h1 = net.addHost('h1')
#Creating links between nodes in network
net.addLink(h0, s0)
net.addLink(h1, s0)
#Configuration of IP addresses in interfaces
h0.setIP('192.168.1.1', 24)
h1.setIP('192.168.1.2', 24)
net.start()
net.pingAll()
net.stop()

执行命令sudo chmod +x any.py修改文件linear.py为可执行文件。
执行命令sudo python any.py运行脚本,结果如下所示。

步骤5 除了可以通过Python脚本创建基本的拓扑以外,还能在此基础上对性能进行限制。观察下面给出的脚本文件,addHost()语法可以对主机cpu进行设置,以百分数的形式;addLink()语法可以设置带宽bw、延迟delay、最大队列的大小max_queue_size、损耗率loss。
在装有Mininet镜像的虚拟机中执行命令sudo vim performance.py新建文件performance.py,添加以下内容。

from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.link import TCLink
net = Mininet(host=CPULimitedHost, link=TCLink)
c0 = net.addController()
s0 = net.addSwitch('s0')
h0 = net.addHost('h0')
h1 = net.addHost('h1', cpu=0.5)
h2 = net.addHost('h2', cpu=0.5)
net.addLink(s0, h0, bw=10, delay='5ms',
max_queue_size=1000, loss=10, use_htb=True)
net.addLink(s0, h1)
net.addLink(s0, h2)
net.start()
net.pingAll()
net.stop()

执行命令sudo chmod +x performance.py修改文件linear.py为可执行文件。
执行命令sudo python performance.py运行脚本,结果如下所示。

三、交互式界面创建主机、交换机等
步骤1 执行如下命令添加主机h3。

$ sudo mn
> py net.addHost('h3')

步骤2 执行命令py net.addLink(s1,net.get(‘h3’))添加link。

步骤3 执行命令py s1.attach(‘s1-eth3’)给交换机s1添加端口eth3用于连接h3。

步骤4 执行命令py net.get(‘h3’).cmd(‘ifconfig h3-eth0 10.3’)给h3赋予IP(10.0.0.3)。

步骤5 主机1 ping 主机3,结果如下所示。

四、测试网络
步骤1 执行如下命令展示所有的网络信息。

px from mininet.util import dumpNodeConnections
py dumpNodeConnections(net.hosts)

步骤2 执行命令py net.pingAll()进行所有节点的ping测试。

基于Mininet测量路径损耗率

任务目的
1、熟悉Mininet自定义拓扑脚本的编写与损耗率的设定。
2、熟悉编写POX脚本,测量路径损耗速率。

任务环境
设备名称 软件环境(镜像) 硬件环境
控制器 Ubuntu 14.04桌面版
Pox 0.2.0
CPU:2核 内存:4G 磁盘:20G
主机 Ubuntu 14.04桌面版
Mininet 2.2.0_ovs2.3.0
CPU:1核 内存:2G 磁盘:20G
注:系统默认的账户为root/root@openlab,openlab/user@openlab。

任务内容
1、自定义Mininet拓扑脚本的编写并设定损耗率。
2、熟悉编写POX脚本,测量路径损耗速率。

实验原理
在SDN环境中,控制器可以通过对交换机下发流表操作来控制交换机的转发行为,此外,还可以利用控制器测量路径的损耗率。在本实验中,基于Mininet脚本,设置特定的交换机间的路径损耗速率,然后编写POX脚本,实现对路径的损耗率的测量。数据平面拓扑如下图所示。

在该环境下,h0向h1发送数据包,由于在mininet脚本中设置了连接损耗率,在传输过程中会丢失一些包,本次实验的目的是展示如何通过控制器计算路径损耗速率(h0-s0-s1-h1)。这里假设控制器预先知道网络拓扑,所以我没有显示发现网络的代码以及其他相关代码。控制器将向s0和s1发送flow_stats_request,当控制器接收到来自s0的response时,将特定流的数据包数保存在input_pkts中,当控制器接收到来自s1的response时,将接收到特定流的数据包数保存在output_pkts中,差值就是丢失的数据包数量。

实验步骤
一、命令行创建拓扑
登录主机host1,打开命令行终端,执行sudo vim mymininet.py命令,编写mininet脚本,脚本内容如文件/home/ftp/mymininet.py。

脚本代码中控制器的IP地址要根据具体情况修改,本实验中,控制器IP地址为30.0.1.3,上述代码创建了一个两台交换机、两台主机的线性拓扑,并且设定交换机s1与交换机s2之间的链路损耗为10%。

二、编写控制器脚本。
步骤1 登录控制器,执行命令cd pox,进入控制器目录。
步骤2 登录控制器,执行命令sudo vim flow_status.py,编写控制器脚本,脚本内容如/home/ftp/flow_status.py。

步骤3 执行命令ps -ef|grep pox,查看已运行的控制器进程,并通过kill命令删除进程,如下所示。

步骤4 执行命令sudo ./pox.py flow_status,运行控制器脚本,如下所示。

步骤5 登录主机,执行命令sudo python ./mymininet.py,启动脚本,如下所示。

三、观察实验数据
登录控制器,查看控制器脚本打印的数据。

上图可知,控制器脚本检测到的链路损耗为11.6%,与数据平面Mininet模拟拓扑中设定的损耗值非常接近,实验成功。

Mininet设置带宽之简单性能测量

实验原理
Mininet 是一个轻量级软件定义网络和测试平台;它采用轻量级的虚拟化技术使一个单一的系统看起来像一个完整的网络运行想过的内核系统和用户代码,也可简单理解为 SDN 网络系统中的一种基于进程虚拟化平台,它支持 OpenFlow、OpenvSwith 等各种协议,Mininet 也可以模拟一个完整的网络主机、链接和交换机在同一台计算机上且有助于互动开发、测试和演示,尤其是那些使用 OpenFlow 和 SDN 技术的网络,同时也可将此虚拟化的平台下代码迁移到真实的环境中
基于Mininet实现一个单交换机的拓扑,添加一台交换机、一台控制器和6台主机到网络中。交换机和主机之间的每个链路能够设置带宽、延迟时间、以及丢包率。使用iperf测试不同主机之间的带宽。拓扑图如下所示:

实验步骤
一、编写实验脚本
步骤1 登录主机host1,执行命令sudo vim band_test.py,编写实验脚本,脚本内容参考/home/ftp/dynamic_trans.py。构建实验拓扑,其中包含一台控制器、一台交换机、六台主机,host1与host2之间带宽设置为10Mb/s,Host3和host4之间带宽为30Mb/s,host5与host6之间带宽为50Mb/s。

#!/usr/bin/python
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.node import CPULimitedHost
from mininet.link import TCLink
from mininet.util import dumpNodeConnections
from mininet.log import setLogLevel

class SingleSwitchTopo(Topo):
    "Single switch connected to n hosts."
    band_pool = range(0,100)
    def __init__(self, n=2, **opts):
        Topo.__init__(self, **opts)
        switch = self.addSwitch('s1')
        for h in range(0,n,2):
            #Each host gets 50%/n of system CPU
            host1 = self.addHost('h%s' % (h + 1), cpu=.5/n)
            host2 = self.addHost('h%s' % (h + 2), cpu=.5/n)
            #10 Mbps, 5ms delay, 0% Loss, 1000 packet queue
            self.addLink(host1, switch, bw=self.band_pool[h+1]*10, delay='5ms', loss=0, max_queue_size=1000, use_htb=True)
            self.addLink(host2, switch, bw=self.band_pool[h+1]*10, delay='5ms', loss=0, max_queue_size=1000, use_htb=True)

def perfTest():
    "Create network and run simple performance test"
    topo = SingleSwitchTopo(n=6)
    net = Mininet(topo=topo,host=CPULimitedHost, link=TCLink)
    net.start()
    print "Dumping host connections"
    dumpNodeConnections(net.hosts)
    print "Testing network connectivity"
    net.pingAll()
    print "Testing bandwidth between hosts"
    host_pool = net.get('h1','h2','h3', 'h4','h5','h6')
    for i in range(0,6,2):
        net.iperf((host_pool[i],host_pool[i+1]))
   # net.iperf(h3,h4)
    net.stop()

if __name__=='__main__':
    setLogLevel('info')
    perfTest()

步骤2 执行sudo chmod +x band_test.py,赋予脚本可执行权限。
二、观察实验数据
执行以下命令,启动客户端脚本:

$ sudo ./band_test.py

由上可知,实验使用iperf测量的主机间带宽分别为:host1与host2之间带宽设置约10Mb/s,Host3和host4之间带宽约为30Mb/s,host5与host6之间带宽约为50Mb/s。与Mininet中设定的值相仿,实验验证成功。

Mininet动态改变转发规则实验

实验原理
在SDN环境中,控制器可以通过对交换机下发流表操作来控制交换机的转发行为。在本实验中,基于Mininet脚本,编写POX脚本,动态改变交换机的转发规则。
先看一下本次实验的拓扑图:

在该环境下,假设H1 ping H4,初始的路由规则是S1-S2-S5,5秒后,路由转发规则变为S1-S3-S5,再过5秒,规则变为S1-S4-S5,然后再回到最初的转发规则S1-S2-S5。通过这个循环调度的例子动态地改变交换机的转发规则。

实验步骤
一、脚本编写
步骤1 登录控制器,执行命令ifconfig,查看控制器IP地址。

步骤2 执行以下命令,编写控制器脚本,脚本内容参考/home/ftp/dynamic_trans.py。

$ cd pox
$ sudo vim dynamic_trans.py

步骤3 执行命令ps -ef|grep pox,查看已运行的控制器进程,并通过kill命令删除进程,如下所示。

步骤4 执行命令sudo ./pox.py dynamic_trans,启动控制器脚本。

步骤5 登录主机,执行命令sudo vim dynamic_topo.py,脚本内容参考/home/ftp/dynamic_topo.py。

上图中控制器的IP地址要根据实验情况替换。

步骤6 执行命令 sudo python ./dynamic_topo.py,启动Mininet脚本。
二、观察实验数据
步骤1 在Mininet界面内执行命令h1 ping h4,验证不同主机间链路的联通性。

步骤2 隔五秒执行一次命令,sh ovs-ofctl dump-flows s1,查看交换机s1转发策略的变化,如下所示。

由上可知,控制器脚本隔5秒变化一次转发路径,达到了实验的目的。

Mininet脚本实现控制交换机行为

实验原理
在SDN环境中,控制器可以通过对交换机下发流表操作来控制交换机的转发行为。在本实验中,使用Mininet基于python的脚本,调用“ovs-vsctl”命令直接控制Open vSwitch。

任务一:一台交换机两台主机,从1端口进入的数据流转发到2端口,从2端口进入的数据流转发到1端口。

任务二:两台交换机两台主机,主机0连接交换机0,主机1连接交换机1,交换机0连接交换机1,数据转发端口同任务一。

任务三:与任务二类似,但是在创建link的时候,设置带宽、延迟以及丢包率。
实验步骤
一、实验任务一
步骤1 登录Mininet主机,执行命令sudo vim test1.py,编辑Mininet脚本,设计实验拓扑为一台交换机连接两台主机。

#!/usr/bin/python 
from mininet.net import Mininet
from mininet.node import Node
from mininet.link import Link
from mininet.log import setLogLevel, info
from mininet.util import quietRun
from time import sleep
def scratchNet( cname='controller', cargs='-v ptcp:' ):
    "Create network from scratch using Open vSwitch."
    info( "*** Creating nodes\n" )
    controller = Node( 'c0', inNamespace=False )
    switch0 = Node( 's0', inNamespace=False )
    h0 = Node( 'h0' )
    h1 = Node( 'h1' )
    info( "*** Creating links\n" )
    Link( h0, switch0 )
    Link( h1, switch0 )
    info( "*** Configuring hosts\n" )
    h0.setIP( '192.168.123.1/24' )
    h1.setIP( '192.168.123.2/24' )
    info( str( h0 ) + '\n' )
    info( str( h1 ) + '\n' )
    info( "*** Starting network using Open vSwitch\n" )
    controller.cmd( cname + ' ' + cargs + '&' )
    switch0.cmd( 'ovs-vsctl del-br dp0' )
    switch0.cmd( 'ovs-vsctl add-br dp0' )
    for intf in switch0.intfs.values():
        print intf
        print switch0.cmd( 'ovs-vsctl add-port dp0 %s' % intf )
    switch0.cmd( 'ovs-ofctl add-flow dp0 \"in_port=1 actions=output:2\"' )
    switch0.cmd( 'ovs-ofctl add-flow dp0 \"in_port=2 actions=output:1\"' )
    info( "*** Running test\n" )
    h0.cmdPrint( 'ping -c6 ' + h1.IP() )
    h1.cmdPrint( 'ping -c6 ' + h0.IP() )
    info( "*** Stopping network\n" )
    controller.cmd( 'kill %' + cname )
    switch0.cmd( 'ovs-vsctl del-br dp0' )
    switch0.deleteIntfs()
    info( '\n' )
if __name__ == '__main__':
    setLogLevel( 'info' )
    info( '*** Scratch network demo (kernel datapath)\n' )
    Mininet.init()
    scratchNet()

步骤2 执行sudo chmod +x test1.py,为脚本增加可执行权限。
步骤3 执行sudo python ./test1.py,执行Mininet脚本,测试脚本中的ovs命令是否生效。

由上可知,通过ovs命令成功设置了网桥与交换机流表,主机可正常通信。

二、实验任务二
步骤1 登录Mininet主机,执行命令sudo vim test2.py,编辑Mininet脚本,设计实验拓扑为两台交换机直连,每台交换机下挂一台host。

#!/usr/bin/python 
from mininet.net import Mininet
from mininet.node import Node
from mininet.link import Link
from mininet.log import setLogLevel, info
from mininet.util import quietRun
from time import sleep
def scratchNet( cname='controller', cargs='-v ptcp:' ):
    "Create network from scratch using Open vSwitch."
    info( "*** Creating nodes\n" )
    controller = Node( 'c0', inNamespace=False )
    switch0 = Node( 's0', inNamespace=False )
    switch1 = Node( 's1', inNamespace=False )
    h0 = Node( 'h0' )
    h1 = Node( 'h1' )
    info( "*** Creating links\n" )
    Link( h0, switch0 )
    Link( h1, switch1 )
    Link( switch0, switch1 )
    info( "*** Configuring hosts\n" )
    h0.setIP( '192.168.123.1/24' )
    h1.setIP( '192.168.123.2/24' )
    info( str( h0 ) + '\n' )
    info( str( h1 ) + '\n' )
    info( "*** Starting network using Open vSwitch\n" )
    controller.cmd( cname + ' ' + cargs + '&' )
    switch0.cmd( 'ovs-vsctl del-br dp0' )
    switch0.cmd( 'ovs-vsctl add-br dp0' )
    switch1.cmd( 'ovs-vsctl del-br dp1' )
    switch1.cmd( 'ovs-vsctl add-br dp1' )
    for intf in switch0.intfs.values():
        print intf
        print switch0.cmd( 'ovs-vsctl add-port dp0 %s' % intf )
    for intf in switch1.intfs.values():
        print intf
        print switch1.cmd( 'ovs-vsctl add-port dp1 %s' % intf )
    switch0.cmd( 'ovs-ofctl add-flow dp0 \"in_port=1 actions=output:2\"' )
    switch0.cmd( 'ovs-ofctl add-flow dp0 \"in_port=2 actions=output:1\"' )
    switch1.cmd( 'ovs-ofctl add-flow dp1 \"in_port=1 actions=output:2\"' )
    switch1.cmd( 'ovs-ofctl add-flow dp1 \"in_port=2 actions=output:1\"' )
    print switch0.cmd( 'ovs-ofctl show dp0' )
    print switch1.cmd( 'ovs-ofctl show dp1' )
    info( "*** Running test\n" )
    h0.cmdPrint( 'ping -c3 ' + h1.IP() )
    h1.cmdPrint( 'ping -c3 ' + h0.IP() )
    info( "*** Stopping network\n" )
    controller.cmd( 'kill %' + cname )
    switch0.cmd( 'ovs-vsctl del-br dp0' )
    switch0.deleteIntfs()
    switch1.cmd( 'ovs-vsctl del-br dp1' )
    switch1.deleteIntfs()
    info( '\n' )
if __name__ == '__main__':
    setLogLevel( 'info' )
    info( '*** Scratch network demo (kernel datapath)\n' )
    Mininet.init()
    scratchNet()

步骤2 执行sudo chmod +x test2.py,为脚本增加可执行权限。
步骤3 执行sudo python ./test2.py,执行Mininet脚本,测试脚本中的ovs命令是否生效。

由上可知,通过ovs命令成功设置了网桥与交换机流表,主机可正常通信。

三、实验任务三
步骤1 登录Mininet主机,执行命令sudo vim test3.py,编辑Mininet脚本,设计实验拓扑为两台交换机直连,每台交换机下挂一台host,但两台交换机间链路损耗率设为10%。

#!/usr/bin/python 
from mininet.net import Mininet
from mininet.node import Node
from mininet.link import TCLink
from mininet.log import setLogLevel, info
from mininet.util import quietRun
from time import sleep
def scratchNet( cname='controller', cargs='-v ptcp:' ):
    "Create network from scratch using Open vSwitch."
    info( "*** Creating nodes\n" )
    controller = Node( 'c0', inNamespace=False )
    switch0 = Node( 's0', inNamespace=False )
    switch1 = Node( 's1', inNamespace=False )
    h0 = Node( 'h0' )
    h1 = Node( 'h1' )
    info( "*** Creating links\n" )
    linkopts0=dict(bw=10)
    linkopts1=dict(bw=10, delay='5ms', loss=10)
    TCLink( h0, switch0,**linkopts0)
    TCLink( h1, switch1,**linkopts0)
    TCLink( switch0, switch1,**linkopts1)
    info( "*** Configuring hosts\n" )
    h0.setIP( '192.168.123.1/24' )
    h1.setIP( '192.168.123.2/24' )
    info( str( h0 ) + '\n' )
    info( str( h1 ) + '\n' )
    info( "*** Starting network using Open vSwitch\n" )
    controller.cmd( cname + ' ' + cargs + '&' )
    switch0.cmd( 'ovs-vsctl del-br dp0' )
    switch0.cmd( 'ovs-vsctl add-br dp0' )
    switch1.cmd( 'ovs-vsctl del-br dp1' )
    switch1.cmd( 'ovs-vsctl add-br dp1' )
    for intf in switch0.intfs.values():
        print intf
        print switch0.cmd( 'ovs-vsctl add-port dp0 %s' % intf )
    for intf in switch1.intfs.values():
        print intf
        print switch1.cmd( 'ovs-vsctl add-port dp1 %s' % intf )
    switch0.cmd( 'ovs-ofctl add-flow dp0 \"in_port=1 actions=output:2\"' )
    switch0.cmd( 'ovs-ofctl add-flow dp0 \"in_port=2 actions=output:1\"' )
    switch1.cmd( 'ovs-ofctl add-flow dp1 \"in_port=1 actions=output:2\"' )
    switch1.cmd( 'ovs-ofctl add-flow dp1 \"in_port=2 actions=output:1\"' )
    print switch0.cmd( 'ovs-ofctl show dp0' )
    print switch1.cmd( 'ovs-ofctl show dp1' )
    info( "*** Running test\n" )
    h0.cmdPrint( 'ping -c100 '+ h1.IP() )
    h1.cmdPrint( 'ping -c100 '+ h0.IP() )
    info( "*** Stopping network\n" )
    controller.cmd( 'kill %' + cname )
    switch0.cmd( 'ovs-vsctl del-br dp0' )
    switch0.deleteIntfs()
    switch1.cmd( 'ovs-vsctl del-br dp1' )
    switch1.deleteIntfs()
    info( '\n' )
if __name__ == '__main__':
    setLogLevel( 'info' )
    info( '*** Scratch network demo (kernel datapath)\n' )
    Mininet.init()
    scratchNet()

步骤2 执行sudo chmod +x test3.py,为脚本增加可执行权限。
步骤3 执行sudo python ./test3.py,执行Mininet脚本,测试脚本中的ovs命令是否生效以及损耗率设定是否正确。
由上可知,通过ovs命令成功设置了网桥。

使用ping命令测试主机间连通性,测量数据为23% (即ICMP包单程丢失约10%),符合预期,实验验证成功

基于Mininet实现BGP路径挟持攻击实验

实验原理
互联网是由相互连接的自治系统AS组成的,通过一个通用的边界网关协议(BGP)进行交互彼此的路由信息。如果利用BGP进行特殊攻击,比如一个伪装的AS伪造了一个更短的路径到前缀IP,其他的AS要路由到前缀P时就会选择这个更短的路径,受到感染的AS会把该攻击信息继续向其他的AS传播,使得更多的AS受到感染,逐渐形成了BGP劫持攻击。
在BGP消息通告中把BGP邻居作为完全可信的实体,并认为所有从邻居学习到的路由信息都是当前网络拓扑的真实状况。因此当一个攻击者将不属于自己的IP前缀宣告到其他的组织,接收到通告的组织也只是依据自身策略决定到达该IP前缀的下一跳AS,没有机制可以用来验证发布该前缀的组织是否真的拥有该IP前缀。如果选择了攻击者AS作为到达该IP前缀的下一跳地址,则所有到达该IP前缀的流量都会被劫持到攻击者AS。

实验步骤
一、实验环境配置
步骤1 执行命令sudo apt-get install python-setuptools安装easy_install,如果已经安装请跳过此步骤。

步骤2 执行命令如下命令获取实验代码。
sudo git clone https://bitbucket.org/jvimal/bgp.git

说明:为方便实验用户联网下载,已将bgp实验代码预置在镜像中,用户可跳过此步骤。

步骤3 切换到bgp目录下,修改run.py中的如下代码。
$ cd bgp
$ sudo vim run.py
修改内容在第19行,修改前:

修改后:

说明:若镜像中配置正确则不用修改。

步骤4 执行命令sudo ./install.sh安装termcolor和quagga。
步骤5 执行以下步骤配置quagga。
执行命令sudo vim /etc/quagga/daemons编辑/etc/quagga目录下的daemons文件。
将zebra和bgpd对应的值设置为yes后保存退出。

zebra=yes
bgpd=yes
执行以下命令创建zebra、bgp以及vtysh对应的配置文件。
$ sudo cp /usr/share/doc/quagga/examples/zebra.conf.sample /etc/quagga/zebra.conf
$ sudo cp /usr/share/doc/quagga/examples/bgpd.conf.sample /etc/quagga/bgpd.conf
执行命令sudo /etc/init.d/quagga restart重新启动quagga。

步骤6 执行命令sudo apt-get install telnetd安装telnet,如果已经安装请跳过此步骤。
二、BGP路径挟持攻击
步骤1 切换到/home/openlab/bgp目录,执行命令sudo screen python bgp.py创建实验拓扑。

步骤2 打开新的命令终端,执行命令sudo screen -r查看Mininet界面进程号。

步骤3 切换到窗口1即Mininet界面,执行ctrl+a+d切换到系统操作界面,执行命令sudo ./connect.sh启动登录AS1的路由R1。

步骤4 请根据提示输入密码en登录。

步骤5 执行命令sh ip bgp查看AS1的路由表信息。

由上可以看出,要到达“13.0.0.0/8”选择的AS路径是“2 3”(例如通过AS2和AS3)。

步骤6 执行exit退出到系统操作界面。执行以下脚本访问Mininet开启在AS3中的一个默认web服务器,并判定可以直接从AS的host1-1直接访问。
在代码目录下有一个“website.sh”,执行命令sudo screen ./website.sh,脚本执行后会在AS1上循环执行curl -s 13.0.1.1这个命令。

步骤7 执行ctrl+a+d切换到系统操作界面。

可以看到website界面进程号为23258。

步骤8 执行命令sudo ./start_rogue.sh开启伪装的AS。
这个AS连接到AS1并通知它一条路由到“13.0.0.0/8”的更短的路径(例如一个直接从AS1到AS4的路径),这样AS1就会的选择这个更短的路径。

步骤9 查看website.sh的执行结果,执行sudo screen -r 23258选择登录website的执行界面。

可以看出原来的“default web server”变成了“Attacker web server”。
说明:实际的进程号可能会不一样,请会根据实际情况操作。

步骤10 执行ctrl+a+d切换到系统操作界面,执行命令sudo ./connect.sh启动登录AS1的路由R1。
步骤11 请根据提示输入密码en登录。
步骤12 执行命令sh ip bgp查看AS1的路由表信息。

可以在AS1的路由表中看出AS4的选择路径和AS3的路径。因为通过AS4到达“13.0.0.0/8”是比较短的,所以R1选择了AS4作为它的下一跳。

步骤13 执行exit退出到系统操作界面。
步骤14 打开新的命令行终端窗口,在/home/openlab/bgp目录下执行脚本sudo ./stop_rogue.sh关闭R4的路由进程。
步骤15 执行sudo screen -r 23258选择登录website的执行界面,查看界面变化。

可以看出原来的“Attacker web server”又变成了“default web server”。
说明:23258为website.sh的界面进程,实际的进程号可能会不一样,请会根据实际情况操作,可执行screen -r命令查看进程号。

步骤16 执行ctrl+a+d切换到系统操作界面,执行命令sudo screen -r 22290登录到Mininet的操作界面。
说明:22290为Mininet的界面进程,实际的进程号可能会不一样,请会根据实际情况操作,可执行screen -r命令查看进程号。

步骤17 在Mininet操作命令行中输入exit退出拓扑结束实验。

模拟多数据中心带宽实验

实验原理
一、Mininet数据中心应用价值
真实的SDN网络需要很多OpenFlow设备,包括控制器、交换机、功能虚拟化等,但因条件有限,每一位实验者不可能有这样真实的环境来验证或者实验。此处主要介绍在没有OpenFlow硬件设备下,通过Mininet模拟搭建基于不同数据中心的网络拓扑的方法。Mininet数据中心应用价值主要体现在如下几个方面。
1、 树状拓扑结构容错能力强。
2、 降低数据中心成本消耗。
3、 提供重新排列的全带宽无阻碍路径。
4、 提高带宽利用率。
5、 分析数据中心网络流量性能。
6、 为真实数据中心和仿真测试床提供有用信息。

二、数据中心拓扑逻辑网络
本实验主要是基于胖树(Fat-Tree)拓扑创建网络,胖树网络的好处是具有一个多层次的树状拓扑结构固有的容错能力。假设每层具有不同的级别:核心层、汇聚层、边缘层,每一层都只含有交换机,因此,一个简单的交换机/主机层网络可以由核心交换机、汇聚交换机、边缘交换机以及主机组成,也可以根据扇出大小来配置不同的数据中心网络拓扑。在该拓扑中,一个或多个核心交换机构成根;汇聚交换机的一层或多层位于树的中间;终端主机连接至顶端交换机,形成了树的叶子(边缘)。一个简单的基于两个数据中心的网络拓扑如下图所示。

图中c1和c2为核心交换机,a1-a4为聚合交换机,e1-e4为边缘交换机,h1-h8为主机。本实验主要测试及验证交换机下挂主机间的连通性以及主机间通信收发数据包的速度。Mininet中自带的iPerf性能测试工具可以测试不同主机间通信的性能带宽质量,在此实验中,主要是对相同边缘交换机下的主机间、相同聚合交换机下不同边缘交换机间、相同核心交换机不同聚合交换机下的主机间进行测试。
三、流量随机模型在Mininet中的应用
在网络性能评估中一个巨大的挑战就是如何生成真实的网络流量。其中一个方法可以通过程序来创造人工的网络流量,通过建立测试环境来模拟真实的状态。本实验以数据中心网络为目标场景,在Mininet仿真环境中尽可能地还原数据中心内部的真实流量情况。本实验采用的模型是随机模型,随机模型是指主机向在网络中的另一任意主机以等概率发送数据包。实验时使用Mininet中的Iperf工具在网络中生成UDP流量,Iperf客户端传送数据流到Iperf的服务端,由服务端接收并记录相关信息。因此需要实现的是将批处理流的自定义命令添加到Mininet中,在Mininet中使用此自定义命令,实现上述功能。在Mininet中进行自定义命令主要分为4步:
1、 修改mininet/net.py。net模块实现Mininet类,是仿真平台mininet的主体类,该类完成节点添加配置、网络基本功能和一些选项功能的实现。需要将自定义的函数定义在该类中。
2、 修改mininet/cli.py。cli模块定义了CLI类,为用户提供命令行接口,用于解析用户输入的命令,之前定义的自定义命令需要在CLI类中通过注册函数注册这条自定义命令。
3、 修改bin/mn。在完成命令注册与绑定后,需要在Mininet执行解释器中注册命令与对应执行函数的映射关系。
4、 重新安装Mininet核心文件。执行~/mininet/util/install.sh -n命令安装Mininet核心文件。

实验步骤
一、创建实验
步骤1 登录OpenLab实验平台,选择“实验课程 > SDN > 模拟多数据中心带宽实验”。
说明:当前有正在进行的实验课程时,请单击“结束”,结束课程。

步骤2 创建实验,目前支持两种创建实验的模式,具体如下:
实验模式为“上课模式”时:单击实验名称出现一提示框,单击“进入详情”进入实验详情页面,后台自动创建实验,单击“进入实验“即可。
实验模式为“浏览模式”时,单击实验名称进入实验详情页面,单击“开始实验”,创建实验。
步骤3 课程实验创建完成后,进入对应的操作界面。
二、自定义命令功能拓展
步骤1 选择主机1,打开命令行终端,登录Mininet所在主机。
步骤2 执行命令sudo mkdir -p /home/sdnlab/log,创建日志目录/home/sdnlab/log。
步骤3 执行sudo vi openlab/mininet/mininet/net.py命令,打开net.py文件,进行如下编辑。
步骤4 在Mininet类下添加iperf_single函数,具体内容如下:

def iperf_single( self,hosts=None, udpBw='10M', period=60, port=5001):
            """Run iperf between two hosts using UDP.
               hosts: list of hosts; if None, uses opposite hosts
               returns: results two-element array of server and                client speeds"""
            if not hosts:
                return
            else:
                assert len( hosts ) == 2
            client, server = hosts
            filename = client.name[1:] + '.out'
            output( '*** Iperf: testing bandwidth between ' )
            output( "%s and %s\n" % ( client.name, server.name ) )
            iperfArgs = 'iperf -u '
            bwArgs = '-b ' + udpBw + ' '
            print "***start server***"
            server.cmd( iperfArgs + '-s -i 1' + ' > /home/sdnlab/log/' + filename + '&')
            print "***start client***"
            client.cmd(
                iperfArgs + '-t '+ str(period) + ' -c ' + server.IP() + ' ' + bwArgs +' > /home/sdnlab/log/' + 'client' + filename +'&')

说明:该函数主要实现在两个主机之间进行iperf测试,并且在server端记录。上述代码可参考预置在/home/ftp/mininet_net_iperf_single.p文件模板中。
添加完成后的代码如下:

步骤5 在iperf_single函数下面继续添加iperfmulti函数,具体代码如下:

def iperfMulti(self, bw, period=60):
        base_port = 5001
        server_list = []
        client_list = [h for h in self.hosts]
        host_list = []
        host_list = [h for h in self.hosts]

        cli_outs = []
        ser_outs = []

        _len = len(host_list)
        for i in xrange(0, _len):
            client = host_list[i]
            server = client
            while( server == client ):
                server = random.choice(host_list)
            server_list.append(server)
            self.iperf_single(hosts = [client, server], udpBw=bw, period= period, port=base_port)
            sleep(.05)
            base_port += 1

        sleep(period)
        print "test has done"

说明:该命令的作用是依次为每一台主机随机选择另一台主机作为iperf的服务器端,通过调用iperf_single,自身以客户端身份按照指定参数发送UDP流,服务器生成的报告以重定向的方式输出到文件中,使用iperfmulti命令,主机随机地向另一台主机发起一条恒定带宽的UDP数据流。上述代码已经预置在/home/ftp/mininet_net_iperfMulti.py文件中。

步骤6 执行wq命令保存net.py文件。
步骤7 执行sudo vi openlab/mininet/mininet/cli.py命令,打开cli.py文件。
步骤8 添加如下内容,注册iperfmulti命令。

def do_iperfmulti( self, line ):
        """Multi iperf UDP test between nodes"""
        args = line.split()
        if len(args) == 1:
            udpBw = args[ 0 ]
            self.mn.iperfMulti(udpBw)
        elif len(args) == 2:
            udpBw = args[ 0 ]
            period = args[ 1 ]
            err = False
            self.mn.iperfMulti(udpBw, float(period))
        else:
            error('invalid number of args: iperfmulti udpBw period\n' +
                   'udpBw examples: 1M 120\n')

说明:上述代码已经预置在/home/ftp/mininet_cli.py_iperfmulti.py文件中。
添加完成后的代码如下:

步骤9 执行wq命令保存cli.py文件。
步骤10 执行sudo vi openlab/mininet/bin/mn命令,打开mn文件。
步骤11 将iperfmulti加入到对应的列表中,如下图所示。

步骤12 执行wq命令保存mn文件。
步骤13 执行如下命令重新编译Mininet。
$ cd openlab/mininet/util
$ ./install.sh -n
步骤14 执行sudo mn命令,启动Mininet。
步骤15 输入iperf后按Tab键,可以查看iperfmulti命令已添加,如下图所示。

三、创建数据中心网络
步骤1 选择主机1,打开命令行终端,登录Mininet所在主机。执行ifconfig查看IP地址,如下图所示。

步骤2 选择控制器1,打开命令行终端,登录RYU控制器,执行ifconfig命令查看控制器IP,如下图所示。

步骤3 执行cd openlab/ryu/ryu/app命令,进入app目录。
步骤4 执行ryu-manager simple_switch_stp.py,启动RYU。
步骤5 在主机1上执行ping 30.0.1.12 -c 5,向控制器发送5个ping包,测试Mininet虚拟机与RYU控制器之间的连通性,如下图所示。

步骤6 在主机1上执行cd lab命令进入“lab”目录,查看该目录下放置的文件,如下图所示。

为提高用户实验效率,省去输入代码的时间,在lab目录下为用户准备了创建拓扑和连通性测试两部分内容的测试脚本,名称为fattree.py和fullfattree.py,请用户根据实际情况取用。
其中fattree.py脚本就是用于定义拓扑的,可以创建包含两个数据中心的网络拓扑。

步骤7 执行sudo vi fattree.py查看fattree.py脚本具体内容。fattree.py脚本详情如下所示。

#!/usr/bin/python
#创建网络拓扑
"""Custom topology example
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
from mininet.net import Mininet
from mininet.node import RemoteController,CPULimitedHost
from mininet.link import TCLink
from mininet.util import dumpNodeConnections

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

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

 # 初始化拓扑,L1是核心交换机个数,L2是聚合交换机个数,L3是边缘交换机个数
        Topo.__init__( self )
        L1 = 2
        L2 = L1 * 2 
        L3 = L2
        c = []
        a = []
        e = []

        # 添加核心交换机  
        for i in range( L1 ):
                sw = self.addSwitch( 'c{}'.format( i + 1 ) )
                c.append( sw )

        # 添加聚合交换机
        for i in range( L2 ):
                sw = self.addSwitch( 'a{}'.format( L1 + i + 1 ) )
                a.append( sw )

        # 添加边缘交换机
        for i in range( L3 ):
                sw = self.addSwitch( 'e{}'.format( L1 + L2 + i + 1 ) )
                e.append( sw )

        # 创建核心交换机与聚合交换机之间的链路
        for i in range( L1 ):
                sw1 = c[i]
                for sw2 in a[i/2::L1/2]:
                                    self.addLink( sw2, sw1 )

        # 创建聚合交换机和边缘交换机之间的链路
        for i in range( 0, L2, 2 ):
                for sw1 in a[i:i+2]:
                    for sw2 in e[i:i+2]:
                        self.addLink( sw2, sw1 )

        #添加主机,并且连接到对应的边缘交换机上
        count = 1
        for sw1 in e:
                for i in range(2):
                    host = self.addHost( 'h{}'.format( count ) )
                    self.addLink( sw1, host )
                    count += 1
topos = { 'mytopo': ( lambda: MyTopo() ) }

Mininet创建网络拓扑的代码中,可以通过改变代码中定义的L1变量来设置核心交换机的数量,并通过添加额外的交换机和链路来构成更复杂的数据中心网络拓扑。随着边缘交换机的增加,主机个数也随之增长,利用Mininet的易用性和扩展性,可以创建基于多种数据中心场景下的网络拓扑,达到更好更全面的实验效果。

步骤8 启动Mininet,执行如下命令,利用脚本生成自定义拓扑,如下图所示。
$ sudo mn --custom fattree.py --topo mytopo --controller=remote,ip=30.0.1.12,port=6633
其中:

—custom指定自定义拓扑文件,本实验为fattree.py
—topo指定加载拓扑的名字,本实验为mytopo。
—controller指定控制器,本实验使用远程控制器RYU,其IP为30.0.1.12,监听端口为6633。

上述代码拓扑创建了2个核心交换机、4个汇聚交换机、4个边缘交换机,每个边缘交换机分别下挂2个虚拟主机,并给所有的交换机添加了逻辑链路。上述代码中为了提高带宽的利用率、调整流量需求达到均衡的效果,每个核心交换机均与4个汇聚交换机相连,每个汇聚交换机分别下挂两个边缘交换机,与上文相对应的,每个边缘交换机分别连接它所属的父交换机。
四、网络性能测试
步骤1 执行iperf h1 h2命令,测试同一交换机内部的主机间的性能,如下图所示。

从结果可以看出h1、h2之间的带宽是5.12 Gbit/s。
步骤2 执行iperf h1 h3命令,测试相同聚合交换机,但不隶属同一交换机的主机之间的带宽,如下图所示。

从结果可以看出h1、h3之间的带宽是5.07 Gbit/s。
步骤3 执行iperf h1 h5命令,测试同一核心交换机但不属于同一聚合交换机的主机之间的性能,如下图所示。

从结果可以看出h1、h5之间的带宽是7.36 Gbit/s。
步骤4 执行iperfmulti 0.025M命令,设置带宽参数为0.025M,如下图所示。

由上图可知,8台主机随机向另一台主机发送数据包。
步骤5 选择主机1,再打开一个终端,执行cd /home/sdnlab/log命令,进入log目录,文件如下图所示。

步骤6 执行vi 1.out命令,查看服务器端测试结果,如下图所示。

由上图可知,主机10.0.0.4向10.0.0.1发送数据包,每隔一秒打印一次信息,包括带宽、延时抖动和丢包率等。
步骤7 执行vi client1.out命令,查看服务器端测试结果,如下图所示.

Mininet MAC地址学习实验

任务内容
通过Mininet模拟二层交换机和两个主机,通过两个主机通信来了解交换机MAC地址学习过程。

实验原理
MAC(media access control,介质访问控制)地址是识别LAN节点的标识。MAC对设备(通常是网卡)接口是全球唯一的,MAC地址为48位,用12个16进制数表示。前6个16进制数字由IEEE管理,用来识别生产商或者厂商,构成OUI(Organization Unique Identifier,组织唯一识别符)。后6个包括网卡序列号,或者特定硬件厂商的设定值。对于一个网卡来说,MAC地址是它的一个物理地址,是不可变的,而IP地址是它对应的一个逻辑地址,是可以更改的。说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的。在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据这张表负责将数据帧传输到指定的主机上的。交换机在接收到数据帧以后,首先、会记录数据帧中的源MAC地址和对应的接口到MAC表中,接着、会检查自己的MAC表中是否有数据帧中目标MAC地址的信息,如果有则会根据MAC表中记录的对应接口将数据帧发送出去(也就是单播),如果没有,则会将该数据帧从非接受接口发送出去(也就是广播)。下图详细讲解交换机传输数据帧的过程。

主机A会将一个源MAC地址为自己目标MAC地址为主机B的数据帧发送给交换机。

交换机收到此数据帧后,首先将数据帧中的源MAC地址和对应的接口(接口为f
0/1)记录到MAC地址表中。

然后交换机会检查自己的MAC地址表中是否有数据帧中的目标MAC地址的信息,如果有,则从MAC地址表中记录的接口发送出去;如果没有,则会将此数据帧从非接收接口的所有接口发送出去(也就是除了f0/1接口)。

这时,局域网的所有主机都会收到此数据帧,但是只有主机B收到此数据帧时会响应这个广播,并回应一个数据帧,此数据帧中包括主机B的MAC地址。

当交换机收到主机B回应的数据帧后,也会记录数据帧中的源MAC地址(也就是主机B的MAC地址),这时,再当主机A和主机B通信时,交换机根据MAC地址表中的记录,实现单播了。

当局域网存在多个交换机互联的时候,交换机的MAC地址表记录过程如下图所示。

主机A将一个源MAC地址为自己,目标MAC地址主机C的数据帧发送给交换机。

交换机1收到此数据帧后,会学习源MAC地址,并检查MAC地址表,发现没有目标MAC地址的记录,则会将数据帧广播出去,主机B和交换机2都会收到此数据帧。

交换机2收到此数据帧后也会将数据帧中的源MAC地址和对应的接口记录到MAC地址表中,并检查自己的MAC地址表,发现没有目标MAC地址的记录,则会广播此数据帧。

主机C收到数据帧后,会响应这个数据帧,并回复一个源MAC地址为自己的数据帧,这时交换机1和交换机2都会将主机C的MAC地址记录到自己的MAC地址表中,并且以单播的形式将此数据帧发送给主机A。

这时,主机A和主机C通信就是一单播的形式传输数据帧了,主机B和主机C通信如上述过程一样,因此交换机2的MAC地址表中记录着主机A和主机B的MAC地址都对应接口f0/1。

从上面的两幅图可以看出,交换机具有动态学习源MAC地址的功能,并且交换机的一个接口可以对应多个MAC地址,但是一个MAC地址只能对应一个接口。本次实验将通过Mininet来验证交换机的MAC地址学习功能。

注意:交换机动态学习的MAC地址默认只有300S的有效期,如果300S内记录的MAC地址没有通信,则会删除此记录。

实验步骤
一、MAC地址学习操作
步骤1. 登录Mininet虚拟机,执行以下命令创建一个线型拓扑,控制器设置为无。
$ sudo mn --topo linear --mac --switch ovsk --controller=none

步骤2. 执行 nodes 命令查看全部节点,如下图所示。

步骤3. 执行 net 命令查看链路信息,如下图所示。

步骤4. 执行 dump 命令查看节点信息,如下图所示。

步骤5. 再打开一个终端(Terminal窗口2),执行如下命令来打开交换机s1和交换机s2的二层。
$ sudo ovs-vsctl del-fail-mode s1
$ sudo ovs-vsctl del-fail-mode s2
说明:因为交换机s1和交换机s2是两个SDN交换机,在启动Mininet时没有指定任何控制器,交换机中没有流表的存在,无法进行转发操作。主机h1和主机h2无法进行通信。执行上述命令后,s1和s2就是两台普通的二层交换机了。

步骤6. 在Terminal窗口1中,执行如下命令进行两台主机Ping操作。

h1 ping h2

步骤7. 在Terminal窗口2中执行如下命令,查看流表项。
$ sudo ovs-ofctl dump-flows s1
$ sudo ovs-ofctl dump-flows s2

由上图可以看到有两条数据帧转发表,但并不是SDN交换机中的流表。这表明交换机已进行过MAC地址学习。

二、MAC地址学习分析
步骤1. 如下图所示,假设交换机A和B的MAC地址表是空的,主机11向主机33发送数据帧。

步骤2. 交换机A接收到数据帧后,执行以下操作。
(1) 交换机A学习主机11的MAC地址和端口号,此时交换机A的MAC地址表如下图所示。

(2) 交换机A查看自己的MAC地址表。

(3) 如果MAC地址表中有目的主机MAC地址则直接进行数据转发,如果没有则继续执行步骤4。
(4) 交换机A向除源数据发送端口外的其他所有端口发送广播(这里交换机A从端口2和端口3向外发送广播)。

步骤3. 交换机B在接收到数据帧后,执行以下操作。
(1) 交换机B学习源MAC地址和端口号,此时交换机B的MAC地址表如下图所示。

(2) 交换机B查看自己的MAC地址表。

(3) 交换机B向除源数据发送端口外的其他所有端口发送广播(这里交换机B从端口1和端口2向外发送广播)。

步骤4. 主机22查看接收到的数据帧,发现目标MAC地址不是自己,丢弃数据帧。
步骤5. 主机33接收数据帧,主机44丢弃数据帧。
步骤6. 假设这时候主机44要给主机11发送数据帧。
步骤7. 交换机B接收到数据帧后,执行以下操作。
(1) 交换机B学习主机44的MAC地址和端口号,此时交换机B的MAC地址表如下图所示。

(2) 交换机B查看自己的MAC地址表,根据MAC地址表中的条目,单播转发数据到端口3。

步骤8. 交换机A在接收到数据帧后,执行以下操作。
(1) 交换机A学习源MAC地址和端口号,此时交换机A的MAC地址表,如下图所示。

(2) 交换机A查看自己的MAC地址表,根据MAC地址表中的条目,单播转发数据到端口1。

(3) 主机11接收到数据帧。至此,MAC地址学习过程结束。

基于Mininet的VXLAN实验

任务内容
1、基于SDN控制器创建跨主机的VXLAN隧道。
2、基于OVS命令设置流表,创建跨主机的VXLAN隧道。

实验原理
如下图所示,在两台虚拟机中利用Mininet创建两个网络,利用VXLAN连通这两个Mininet环境。关闭默认的控制器后,通过设置流表确保网络的连通性。本实验要求OVS版本在2.0.1以上,实验拓扑如下图所示。

实验步骤
一、实验环境检查
步骤1 登录主机host1,单击终端图标,打开终端,执行ifconfig命令查看主机IP,如下所示。

由上图可知,网卡eth0未分配IP地址。

步骤2 执行命令sudo vim /etc/network/interfaces,为eth0分配静态IP地址,如下所示。

步骤3 执行命令sudo ifdown eth0 && sudo ifup eth0,重启网卡eth0,如下所示。

由上图可知,网卡eth0的IP地址已经正确分配。

步骤4 登录主机host2,重复上述操作,为主机host2的网卡eth0配置静态IP地址10.0.0.7,如下所示。

步骤5 登录交换机,用命令ovs-vsctl del-fail-mode br-sw,修改OVS交换机为传统模式。修改后如下所示。

二、基于控制器实现
步骤1 登录主机host1,执行命令sudo mn --topo=single,1,在host1中创建拓扑(一台交换机连接一台主机)。

步骤2 在Mininet CLI中执行如下命令,为网桥添加端口,端口名称为vxlan。
sh ovs-vsctl add-port s1 vxlan
sh ovs-vsctl show

由上图可知,vxlan端口已成功挂载到网桥s1。
说明:若出现如下错误可忽略不计。

步骤3 在Mininet CLI中执行如下命令,设置VXLAN端口,其中remote_ip为主机host2网卡eth0的IP地址,隧道id为5566。
sh ovs-vsctl set interface vxlan type=vxlan option:remote_ip=10.0.0.7 option:key=5566 ofport_request=9
sh ovs-vsctl show

步骤4 执行命令h1 ifconfig h1-eth0 10.0.0.1,为Mininet所创建拓扑中的h1配置IP地址10.0.0.1。

步骤5 登录主机host2,执行命令sudo mn --topo=single,1,在host2中创建拓扑(一台交换机连接一台host)。

步骤6 在Mininet CLI中执行如下命令,为网桥添加端口,端口名称为vxlan。
sh ovs-vsctl add-port s1 vxlan
sh ovs-vsctl show

由上可知,vxlan端口已成功挂载到网桥s1。

步骤7 在Mininet CLI中执行如下命令,设置VXLAN端口,其中remote_ip为主机host1网卡eth0的IP地址,隧道id为5566。
sh ovs-vsctl set interface vxlan type=vxlan option:remote_ip=10.0.0.6 option:key=5566 ofport_request=9
步骤8 执行命令h1 ifconfig h1-eth0 10.0.0.2,为Mininet所创建拓扑中的h1配置IP地址10.0.0.2。

步骤9 登录主机host1,执行命令h1 ping 10.0.0.2,测试VXLAN隧道的连通性。

三、基于OVS流表实现
步骤1 登录主机host1,打开一个新的命令终端,执行以下命令,查询并终止控制器进程。
$ ps -aux|grep controller
$ sudo kill -9 3627

步骤2 登录主机host2,打开一个新的命令终端,执行以下命令,查询并终止控制器进程。
$ ps -aux|grep controller
$ sudo kill -9 3665

步骤3 登录主机host1,在Mininet操作界面执行以下命令,设置OVS流表。

sh ovs-ofctl show s1
sh ovs-ofctl add-flow s1 ‘in_port=1,actions=set_field:5566->tun_id,output:9’
sh ovs-ofctl add-flow s1 ‘in_port=9,tun_id=5566,actions=output:1’
sh ovs-ofctl show s1

由上可知,交换机s1连接主机h1的端口号为1,s1的vxlan端口号为9。通过上述命令添加了两条流表:由端口1进入的数据包需要打上隧道id:5566,并从端口9转发;由端口9进入的数据包并且tun_id为5566,需要从端口1转发。

步骤4 登录主机host2,在Mininet操作界面执行以下命令,设置OVS流表。

sh ovs-ofctl show s1
sh ovs-ofctl add-flow s1 ‘in_port=1,actions=set_field:5566->tun_id,output:9’
sh ovs-ofctl add-flow s1 ‘in_port=9,tun_id=5566,actions=output:1’
sh ovs-ofctl show s1

由上可知,交换机s1连接主机h1的端口号为1,s1的vxlan端口号为9。通过上述命令添加了两条流表:由端口1进入的数据包需要打上隧道id:5566,并从端口9转发;由端口9进入的数据包并且tun_id为5566,需要从端口1转发。

步骤5 执行以下命令h1 ping 10.0.0.1,测试VXLAN隧道连通性。

由上可知,VXLAN隧道可以正常通信。

基于l2_multi模块寻找最短路径实验

任务内容
1、学习Mininet图形化构建拓扑文件的方法。
2、使用pox控制器的l2_multi模块寻找主机间的最短传输路径。

实验原理
Miniedit是一个使用Python编写的图形用户界面,布局和用法有点类似于packet tracer,用户利用所提供的网络元件自主搭建拓扑,右键单击某个元件可以查看、编辑该元件的基本信息。拓扑搭建完成后,用户可以根据需要导出生成python文件。
forwarding.l2_multi是一个交换机mac地址学习模块,其他模块采用的地址学习方式是基于“交换机——交换机”,交换机与相邻的交换机交换地址信息。而l2_multi模块使用openflow.discovery学习整个网络的拓扑,所有交换机同步地址信息。
本实验利用Miniedit绘制网络拓扑并导出生成mininet脚本。此外利用pox控制器中的l2_multi模块找出该拓扑中两个主机间的最短路径。实验拓扑如下图所示。

实验步骤
一、实验环境检查
登录控制器,单击终端图标,打开终端,执行ifconfig命令查看控制器IP,如下所示。

二、生成Mininet脚本
步骤1 登录Mininet主机,执行以下命令,打开Miniedit。
$ cd openlab/mininet/examples
$ sudo ./miniedit.py

步骤2 左键选择侧栏网元图标,在绘图板中左键点击,绘制网络拓扑,如下图所示。

步骤3 右键点击交换机s1的图标,设置参数,如下图所示。

如上图,设置DPID为00:00:00:00:00:01:6673,选择‘ok’。
注意:交换机s2、s3、s4设置方法相同,具体DPID遵循实验原理中的拓扑图。

步骤4 右键点击主机h1的图标,设置参数,如下图所示。

如上图,设置IP设为10.0.0.5/24,选择‘ok’。
注意:主机h2设置方法相同,具体ID遵循实验原理中的拓扑图。

步骤5 右键点击控制器c0的图标,设置参数,如下图所示。

如上图,控制器IP设为30.0.1.3,选择‘ok’。

步骤6 选择“File → Export Level 2 Script”,将拓扑保存为Python脚本,位于/home/openlab文件夹下,如下图所示。

步骤7 打开新的命令窗口,执行命令sudo vim mytopo.py,修改部分代码,如下图所示。

修改控制器相关代码,如上图红色标记所示,控制器IP地址需要根据具体实验情况填写。

步骤8 执行命令sudo chmod +x mytopo.py,为Mininet脚本添加可执行权限。
三、观测实验数据
步骤1 登录控制器pox,执行以下命令,查询并终止控制器进程。
$ ps –aux|grep pox
$ sudo kill -9 <进程id>
步骤2 执行以下命令,使用l2_multi模块启动pox进程。
$ cd pox
$ ./pox.py log.level --DEBUG log --file=mylog,w forwarding.l2_multi openflow.discovery

步骤3 登录主机host1,执行命令sudo ./mytopo.py,运行Mininet脚本。

步骤4 执行以下命令,测试h1与h2之间的连通性并查看交换机流表。

$ h1 ping –c 5 h2 
$ sh ovs-ofctl dump-flows s1
$ sh ovs-ofctl dump-flows s2
$ sh ovs-ofctl dump-flows s3
$ sh ovs-ofctl dump-flows s4

从h1-h2有两条路径,分别是“h1-s3-s4-h2”和“h1-s3-s1-s2-s4-h2”。由s1、s2、s3、s4的流表可以看出,s3、s4中有相关流表,而s1、s2中并没有流表,说明数据包没有通过s1、s2,h1、h2之间最短的路径是h1-s3-s4-h2。

  • 10
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值