简介:针对Mininet网络仿真实验的完整实验报告文档,面向计算机网络、SDN方向学习者及需要完成同类实验的高校学生,系统梳理了从环境准备到拓扑构建的实操流程,可用于快速掌握可视化与脚本化两种网络建模方式。资源为1个doc文件,压缩包大小约1.37MB,文档共16页,包含实验目的、实验内容、Mininet技术与知识背景、具体操作步骤及结果截图。报告覆盖可视化工具Miniedit创建拓扑、命令行创建拓扑、交互式界面添加主机与交换机、节点间ping测试,以及Python脚本构建linear/single/tree等典型拓扑的进阶玩法,并附Mininet常用命令清单与配置要点,每个命令均给出交互示例,便于对照练习和排错。文档结构清晰,按实验步骤逐步展开,关键环节有截图示意,适合作为实验参考或答辩材料。已有1067人学习下载,对入门SDN实验具有较高参考价值。
1. 一份 Mininet 实验报告,值得照着跑一遍的拓扑搭建全流程
在没有硬件交换机的前提下验证 SDN 拓扑,Mininet 几乎是唯一能低成本落地的选择。这份实验报告围绕一个明确目标展开:用三种方式搭出同样的网络拓扑,再用 Python 脚本把拓扑定义变成可复用代码。报告里的操作路径非常完整——从可视化工具画拓扑、保存导出脚本,到命令行一句命令起一个 topo,再到交互式界面动态加主机和交换机,覆盖了 Mininet 日常使用的全部入口。适合刚装好 Mininet、正被 mn 参数和 py 命令绕晕的人;把这 16 页走完,基本就把 Mininet 的用法吃透了。
2. Mininet 是什么:一台虚拟机里装下的整套网络实验台
2.1 核心原理:进程虚拟化,不是整机虚拟化
Mininet 和传统的整机虚拟化方案有本质区别。它不跑多个完整的操作系统镜像,而是用轻量级虚拟化技术在单个 Linux 内核上隔离出若干网络命名空间,每个 host 节点都拥有一套独立的网络栈、进程表和 IP 配置,底层却共享同一个内核。这套设计的直接收益是启动快、资源占用低、拓扑可以随时增删,几秒钟就能拉出一个包含多台交换机和主机的完整网络。
正因如此,报告里把它定位成“由虚拟终端节点、交换机、路由器连接而成的网络仿真器,轻量级软件定义网络测试平台”。对 SDN 开发者来说,Mininet 的价值不只是仿真,而是预演。它支持 OpenFlow 协议,也兼容 OpenvSwitch,代码在 Mininet 里跑通后,迁移到支持 OpenFlow 的硬件设备上只需要换一层接口。也就是说,流表下发、拓扑验证、问题排查这些事,全部可以在买交换机之前完成。
2.2 环境准备:把实验台拉起来的三步
报告里的实验环境是虚拟机加命令行终端,这也是 Mininet 最常见的运行形态。我一般会按下面三步准备:
- 系统:Ubuntu 或 Debian 系 Linux 就可以,内核版本不必追新;
- 安装:
sudo apt-get install mininet装完,紧接着跑sudo mn --version确认安装成功; - 权限:mn 命令必须带 sudo 或者直接 root 运行,普通用户执行会报权限错误,这是新手第一道坎。
还有一个容易被忽略的前置条件是 miniedit 的图形依赖。miniedit 基于 Tk 实现,系统里没装 python3-tk 时,可视化工具能启动但画布上拖不出节点,错误信息还藏在终端输出里。遇到这种情况补一句sudo apt-get install python3-tk就好。
启动 miniedit 本身也有坑,它不在 PATH 环境变量里,直接敲 miniedit 会提示 command not found。报告里写的操作顺序是先进入 root 模式、再找到 miniedit 所在目录。常见做法是先执行find / -name "miniedit.py" 2>/dev/null定位,然后 cd 到 mininet/examples 目录,用sudo python miniedit.py启动。顺序固定为“定位、补依赖、sudo 启动”,能省掉大半排查时间。
2.3 交互命令速查:九条命令管住整个 CLI
Mininet 的 CLI 交互界面是全程接触最多的入口,报告里整理了九条命令,我按使用频率重新排了序:
| 命令 | 作用 | 典型场景 |
|---|---|---|
| help | 查看所有可用命令 | 忘了语法时救急 |
| nodes | 列出全部节点 | 确认拓扑创建结果 |
| net | 显示节点连接关系 | 检查链路是否搭对 |
| dump | 显示节点 PID 和接口信息 | 定位具体进程排障 |
| pingall | 所有主机之间互 ping | 拓扑连通性一键验证 |
| h1 ping h2 | 两台指定主机之间 ping | 单条链路延迟测试 |
| h1 ifconfig | 查看 h1 的 IP 等配置 | 确认主机地址是否配好 |
| xterm h1 | 打开 h1 的终端窗口 | 在虚拟主机里跑真实程序 |
| exit | 退出 CLI 并清理网络 | 结束实验 |
这九个命令的编排有规律:不带节点前缀的是 Mininet 自身的管理命令,负责查看和操作整个网络;带 h1、s1 这类前缀的是“在指定虚拟节点里执行命令”,h1 ifconfig的执行效果和真实 Linux 上敲 ifconfig 完全一致。这种设计正是 Mininet“能运行真实程序”特性的来源——Linux 上能跑的程序,基本都能放进 Mininet 的节点里跑,Wireshark 这类抓包工具也不例外。
实验结束时用exit退出 CLI,会连带清理虚拟网络。这里建议不要直接关终端窗口,因为 Mininet 退出时负责释放命名空间和 veth 接口,强杀进程会导致残留虚拟接口,下次启动时报接口被占用。
3. 三种拓扑构建方式:从可视化到命令行的完整走查
3.1 miniedit 可视化:画拓扑、配参数、导出脚本
miniedit 的完整流程在报告里拆成了十步:启动虚拟机、进入 root、定位 miniedit、启动、画拓扑、配控制器、配交换机、配主机、全局配置、保存运行。实际操作不需要这么严格,核心是四件事。
先拖节点。从左侧面板把 Host、Switch、Controller 拖到画布,用连线工具把主机连到交换机、交换机连到控制器,一个最小网络就成型了。
再配参数。右键单击 Host 选 Properties,可以设置 IP 地址和 MAC;右键 Switch 配置协议类型;Controller 选默认的 OpenFlow 控制器即可。这一步对应报告里的“控制器配置、交换机配置、主机配置”,参数决定拓扑跑起来后的真实行为。
第三件事是开 CLI。Edit → Preferences 里勾选 Start CLI,这样导出的脚本运行后会进入交互界面,方便立刻验证连通性。同一处菜单里还可以选择 OpenFlow 协议版本,实验一般选 1.3。
提示:Preferences 里的 Start CLI 选项勾选后,导出的脚本拉起拓扑会自动进入
mininet>交互界面,不用再手动挂一个终端进去。
最后是保存。File → Export Level 2 Script 是关键一步,导出级别一定要选 Level 2。Level 1 导出的是顺序执行脚本,拓扑结构写死在 main 里,不好改;Level 2 导出的是标准 Topo 子类加独立入口,这正是二次开发想要的骨架。保存后,在终端运行sudo python 文件名.py,画布上的拓扑就被重新构建出来了。
3.2 命令行创建拓扑:一个 mn 参数拼出一个网络
命令行是实验里效率最高的方式,三个典型结构对应三条命令:
sudo mn --topo single,2 sudo mn --topo linear,4 sudo mn --topo single,3single,2 是一个交换机下挂两个主机,这是最小可用网络;linear,4 是四台交换机串成一条链、每台交换机带一台主机;single,3 是三台主机共享一个交换机。可以把 single 理解成星形连接,linear 理解成链式连接。
参数怎么读:--topo后面的第一个词是拓扑类型名,逗号后的数字是规模参数。single 后面的数字表示主机数量;linear 后面的数字既决定主机数也决定交换机数,按 1:1 生成。如果觉得这两个太简单,可以试一下树形:
sudo mn --topo tree,depth=2,fanout=2depth 是树的层数,fanout 是每层往下分几个子节点,这条命令会生成 1 个根交换机、2 个第二层交换机和 4 个终端主机,适合体验非对称链路。命令行创建拓扑的另一个优势是能叠加额外参数,比如--controller=remote可以把控制器指到外部 SDN 控制器上,后面做控制器实验时会很有用。
3.3 交互式界面:动态加节点,改完不用重启
命令行创建拓扑后会直接进入mininet>交互界面。报告展示了一个典型场景:在当前网络中动态添加主机 h3,并让它与已有主机互通。操作序列如下:
mininet> py net.addHost('h3') mininet> py net.addSwitch('s2') mininet> py net.addLink(s1, net.get('h3')) mininet> py s1.attach('s1-eth3') mininet> py net.get('h3').cmd('ifconfig h3-eth0 10.3') mininet> h1 ping -c1 10.3每一行都需要解释。py是 CLI 里执行任意 Python 表达式的入口,等于把解释器搬进了交互界面。net.addHost('h3')只创建主机对象,节点还没有数据口;net.addSwitch('s2')同理,之后需要 addLink 把新节点接进现有拓扑。net.get('h3')是按名字取节点对象,返回的是 Host 实例,所以可以直接对它调用 cmd 方法执行 shell 命令。
关键的一行是py s1.attach('s1-eth3')。addLink 创建了 s1 和 h3 之间的虚拟链路,会生成名为 s1-eth3 的交换机接口,但运行中的交换机不会自动把这个接口纳入数据通道,attach 就是手动完成这步注册。之后ifconfig h3-eth0 10.3给新主机配 IP,因为动态添加的主机不在初始拓扑定义里,Mininet 不会自动分配地址,不配就 ping 不通。最后-c1表示只发一个 ICMP 包,快速验证连通性,比 pingall 更精准。
如果要在交互界面里查看当前连接关系,可以用py dumpNodeConnections(net.hosts),它会打印每个主机连接的交换机和接口名。注意这里 import 的模块名是 mininet.util,不是 mininet.until,报告原稿里的拼写错误容易把人带偏。
4. Python 脚本构建拓扑:核心代码拆解
4.1 最小拓扑脚本:Topo 子类的标准骨架
实验任务的进阶部分是“用 Python 脚本定义拓扑”。Mininet 提供了 Topo 基类,自定义拓扑的标准做法是继承它并重写 build 方法。一个交换机和两个主机的脚本可以这样写:
from mininet.topo import Topo class SingleSwitchTopo(Topo): def build(self): # 创建交换机节点和主机节点 s1 = self.addSwitch('s1') h1 = self.addHost('h1') h2 = self.addHost('h2') # 建立主机到交换机的链路 self.addLink(h1, s1) self.addLink(h2, s1) if __name__ == '__main__': from mininet.net import Mininet from mininet.cli import CLI net = Mininet(topo=SingleSwitchTopo()) net.start() CLI(net) net.stop()build 方法是核心。addSwitch 创建交换节点,addHost 创建主机节点,addLink 在两个节点之间建立虚拟链路并自动分配接口名。这个脚本直接运行会拉起拓扑并进入交互界面,exit 后自动停止。入参方面,addHost 支持传入 ip 参数给主机配地址,addLink 支持 bw、delay 等链路参数,后面章节会用到。
如果只想在脚本里快速验证拓扑而不进交互界面,可以把 CLI(net) 换成net.pingAll(),脚本会自动跑一轮全网主机互 ping 并打印丢包率,然后退出。这是我最常用来做回归验证的写法。
4.2 内置拓扑的脚本版本:linear、tree 与 IP 分配
实验要求用 Python 脚本复现四个任务:linear,4、single,3、tree 深度 2 扇出 2、一个交换机挂两个带 IP 的主机。single,3 和上一节的代码几乎一样,只是多一个主机。linear 和 tree 可以这样实现:
from mininet.topo import Topo class MyTreeTopo(Topo): def build(self, depth=2, fanout=2): # 直接调用内置方法生成树形拓扑 self.addTree(depth=depth, fanout=fanout) class MyLinearTopo(Topo): def build(self, n=4): last_switch = None for i in range(1, n + 1): sw = self.addSwitch('s%d' % i) # 从第二台交换机开始,把当前交换机和上一台串联 if last_switch is not None: self.addLink(last_switch, sw) host = self.addHost('h%d' % i, ip='10.0.0.%d' % i) self.addLink(host, sw) last_switch = swMyLinearTopo 的关键在循环里的 if 判断:第一台交换机没有前驱节点,从第二台开始才需要和上一台交换机相连,这个判断保证链路不会多连。addHost 的 ip 参数是实验任务里的明确要求——给主机显式分配 IP,Mininet 会基于这个地址反推子网掩码,拓扑启动后主机之间可以直接 ping 通。
tree 拓扑用 addTree 内置方法一行生成。depth 控制层数,fanout 控制每一层的子节点数,2 层 2 扇出会得到 1 个根交换机、2 个中层交换机和 4 个主机,总共 7 个节点。如果深度和扇出都加大,节点数会指数增长,测试大规模拓扑时好用,但别一次开太大,否则主机进程数和虚拟网卡数量会把笔记本拖垮。
4.3 给拓扑加性能限制:CPU、带宽、延迟和丢包率
实验的最后一个进阶点是给网络加性能限制。report 明确指出 addHost 语法可以对主机 CPU 进行设置,addLink 语法可以设置带宽 bw、延迟 delay、最大队列大小 max_queue_size、损耗率 loss。一段带限制的完整脚本如下:
from mininet.net import Mininet from mininet.node import CPULimitedHost from mininet.link import TCLink from mininet.cli import CLI net = Mininet(host=CPULimitedHost, link=TCLink) h1 = net.addHost('h1', cpu=0.5) h2 = net.addHost('h2', cpu=0.5) s1 = net.addSwitch('s1') # 限制交换机到两台主机的链路参数 net.addLink(h1, s1, bw=10, delay='5ms', max_queue_size=1000, loss=1) net.addLink(h2, s1, bw=10, delay='5ms', max_queue_size=1000, loss=1) net.start() CLI(net) net.stop()这里有两个必须写对的地方。第一,Mininet 默认的 Host 和 Link 实现不支持性能限制,必须显式指定host=CPULimitedHost和link=TCLink,否则 cpu、bw 这些参数会被静默忽略,排错时极难察觉。第二,参数含义要记牢:cpu=0.5 表示该主机最多使用单核 CPU 的 50%;bw=10 是带宽 10 Mbps;delay='5ms' 是链路单向延迟 5 毫秒;max_queue_size=1000 是交换机端口队列最多缓存 1000 个包;loss=1 是丢包率 1%。
TCLink 的实现基于 Linux 的 tc 命令,启动时会在仿真出的虚拟网卡上挂载队列规则。实验里可以配合 iperf 观察效果:先在 CLI 里跑h1 iperf -s &起服务端,再执行h2 iperf -c h1打流量,能看到带宽被稳定限制在 10 Mbps 附近,丢包率也落在 1% 左右。这样就把“限制配置”和“实际效果”对上了。
5. 避坑指南:Mininet 实验里最容易翻车的五个场景
下面五条是我照着这份报告复现实验时踩过的坑,按出现频率排序。每一条都是先讲现象、再讲原因、最后给解决路径,适合直接对照排查。
5.1 miniedit 提示 command not found,或窗口里拖不出节点
现象:在终端敲 miniedit、miniedit.py 都提示 command not found;用sudo python miniedit.py启动后窗口出来了,但画布上双击和拖拽都没反应,右键菜单也不正常。
原因:两层原因叠在一起。第一,miniedit 不在 PATH 里,它位于 Mininet 源码的 examples 目录,必须 cd 过去或写全路径;第二,Tk 图形库缺失时窗口会退化成半残状态,不报明显错误,只是画布操作全部失效。
解决:先find / -name "miniedit.py" 2>/dev/null定位文件,再确认python3-tk已安装,最后进入所在目录用sudo python miniedit.py启动。三步按顺序走,九成问题都出在后两步。
5.2 miniedit 导出的脚本,换目录就跑不起来
现象:在 miniedit 里 File → Export 保存了脚本,复制到另一个目录运行报 ImportError,或者运行后只看到命令行界面,画布上画好的主机和交换机全都不见了。
原因:导出级别选错了。Level 1 Script 是 GUI 状态快照式的顺序脚本,依赖当时界面上下文里的临时对象,离开 GUI 环境就跑不动;Level 2 Script 才是完整可独立运行的 Topo 子类定义。
解决:保存时认准 File → Export Level 2 Script。运行前先打开脚本文件看一眼,开头是不是from mininet.topo import Topo加一个 class 定义,如果是,再sudo python 文件名.py运行,拓扑就会以代码形式完整重现。
5.3 交互式添加的主机,ping 不通
现象:py net.addHost('h3')执行成功,net 命令也能看到 h3,但h1 ping h3超时,或者提示 Network is unreachable。
原因:动态添加的主机不在初始拓扑定义里,Mininet 的自动 IP 分配机制只在 net.start() 时对拓扑内节点生效,运行期加的主机既没有 IP,交换机端口也没有纳入数据通道,两头都不通。
解决:按顺序补齐四步——addHost 创建节点、addLink 建链路、py s1.attach('s1-eth3')注册交换机端口、py net.get('h3').cmd('ifconfig h3-eth0 10.3')配 IP。验证时先用py dumpNodeConnections(net.hosts)确认连接关系,再h1 ping -c1 10.3,通了就说明四步没缺。
5.4 cpu 参数设置了,但性能限制完全没生效
现象:addHost 里写了 cpu=0.5,跑 iperf 打满流量后看 top,CPU 占用还是接近 100%,带宽限制正常但 CPU 限制像没写一样。
原因:三种常见情况。第一,创建 Mininet 对象时没加host=CPULimitedHost,默认 Host 类根本不解析 cpu 参数;第二,cgroup 没有正确挂载,CPU 限制依赖控制组文件系统,权限不足时被静默跳过;第三,cpu 值写成 50,超出 0 到 1 的合法范围,Mininet 把这个值当成满载处理。
解决:先确认 Mininet() 里显式声明了 CPULimitedHost,再检查 /sys/fs/cgroup/cpu 目录是否存在,不存在就手动挂载;最后把 cpu 参数改回 0 到 1 之间的小数。三个点都排除后,再往下谈限制效果。
5.5 pingall 第一次总是丢包,第二次就全通
现象:拓扑刚启动完立刻执行 pingall,部分主机之间 ping 不通,再执行一次全部通过,丢包率降为 0。
原因:这是 Mininet 交换机的正常学习过程。拓扑刚起来时交换机的流表是空的,首个 ICMP 包会触发 ARP 广播和流表下发,控制器处理需要时间,首包往往就在这个窗口里被丢弃了。
解决:实验前先h1 ping -c1 h2跑一次预热,或者在脚本启动后加两秒等待再进交互界面。统计连通性结果时,用第二轮 pingall 的数据,不要拿第一次的下结论。
6. 二次开发:把实验脚本改造成可复用的拓扑工具
6.1 参数化 Topo 类:一套代码切换三种结构
实际做 SDN 测试时,常需要在同一段代码里按参数切换拓扑类型。把报告里的三个拓扑任务合成一个可切换的脚本,是这个实验最有价值的改造方向:
from mininet.topo import Topo from mininet.net import Mininet from mininet.cli import CLI class CustomTopo(Topo): def build(self, kind='single', n=3): # single:一个交换机挂 n 台主机 if kind == 'single': sw = self.addSwitch('s1') for i in range(1, n + 1): host = self.addHost('h%d' % i, ip='10.0.0.%d/24' % i) self.addLink(host, sw) # linear:n 台交换机串联,每台带一个主机 elif kind == 'linear': last_sw = None for i in range(1, n + 1): sw = self.addSwitch('s%d' % i) if last_sw is not None: self.addLink(last_sw, sw) host = self.addHost('h%d' % i, ip='10.0.0.%d/24' % i) self.addLink(host, sw) last_sw = sw # tree:直接复用内置的树形拓扑生成器 elif kind == 'tree': self.addTree(depth=2, fanout=2) if __name__ == '__main__': import sys kind = sys.argv[1] if len(sys.argv) > 1 else 'single' n = int(sys.argv[2]) if len(sys.argv) > 2 else 3 net = Mininet(topo=CustomTopo(kind=kind, n=n)) net.start() print('topology:', kind, 'with', n, 'hosts') CLI(net) net.stop()这里的关键改进有三个:build 方法接收 kind 和 n 两个参数,脚本用 sys.argv 透传,于是sudo python topo.py linear 4和sudo python topo.py single 3一套代码全搞定;ip 统一用 /24 网段,Mininet 会按 10.0.0.x 自动分配,省去逐个配置的麻烦;启动后打印一行当前拓扑信息,确认入参是否按预期生效。
6.2 验证流程:起来之后先看连接,再跑 pingall
改完脚本不能直接信,验证方法要固定成一套流程。脚本拉起进入 CLI 后,先敲net看链路关系,确认交换机之间的串联、主机与交换机的挂载都符合预期;接着dump看各主机 IP 是否分配正确;最后pingall验证全网连通性。如果某个主机不通,用dump看它的接口和 PID,再单独h1 ping -c1 h2定位是链路没连上还是地址配错。
如果要把这套工具升级成支持性能限制的版本,只需要把 Mininet() 构造改成Mininet(topo=CustomTopo(...), host=CPULimitedHost, link=TCLink),然后在 addHost 和 addLink 里按需加上 cpu、bw、delay、loss 参数。这样一个脚本就能在功能验证和性能测试两种模式间切换,不用为每个拓扑单独维护文件。这份实验报告的 16 页操作记录正好可以当核对清单用,每完成一个改造就回去对照一步,不容易漏配置。
从那以后,我每次拉 Mininet 拓扑都强制走一遍“参数化 Topo 类 + 命令行入参 + 先 net 后 pingall 验证”的流程,省掉了大量为每个拓扑单独写脚本的重复劳动。希望帮到你。
本文还有配套的精品资源,点击获取