ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Mininet实验报告指南:网络模拟、链路参数与SDN控制器对接

Mininet实验报告指南:网络模拟、链路参数与SDN控制器对接 简介这是一份完整的 Mininet 网络仿真实验报告源自西安财经大学《网络应用设计与系统集成》课程实验一适合计算机网络、SDN 方向学习者对照练习。报告从实验目的出发依次梳理了基础技能与进阶技能既包含 Miniedit 可视化工具创建网络拓扑、命令行直接搭建拓扑、交互式界面创建主机和交换机、节点间 ping 测试也包含通过 Python 脚本构建 linear、single、tree 等常见拓扑并对主机 CPU、链路带宽、延迟、队列大小、丢包率等网络性能参数进行限制。文档还对 Mininet 的背景、特性及常用命令作了说明并分步骤呈现控制器配置、交换机配置、主机配置、全局配置、拓扑保存、运行与停止等完整操作流程。资源为单个 doc 文档大小 1.37MB内含详细步骤和界面截图说明便于随时查阅复现。已有 1066 人学习浏览适合正在完成 Mininet 实验、准备实验报告或复习网络仿真要点的同学参考。1. Mininet实验报告到底在解决什么问题当你在网络课、SDN项目或者性能测试里需要一组“网络设备”时最直接的方案是搬出几台物理交换机、路由器和服务器接线、配置、抓包。但大多数时候你手里只有一台笔记本而且要复现的拓扑可能是三层交换机加五台主机或者一个环形链路。这时候Mininet就派上用场了。它是一个基于进程虚拟化技术的网络模拟器能在单台Linux机器上用命名空间模拟出真实的主机、交换机、链路并且在上面跑真实的网络协议栈和应用程序。Mininet实验报告的核心价值就是让你在几秒钟内搭建出一张可编程的虚拟网络并且用iperf、ping、抓包工具去测量它——结果能反映真实网络的大部分行为又不需要采购任何硬件。这篇笔记专门开给三类人正在做网络实验作业的学生、要验证OpenFlow流表行为的SDN开发者、以及需要做链路断线和延迟抖动测试的运维工程师。2. 跑通第一个Mininet拓扑安装、最小命令与连通性验证2.1 为什么选Mininet而不是GNS3或EVE-NG先回答一个常见疑问GNS3和EVE-NG也能搭虚拟网络为什么Mininet更适合实验因为Mininet不是去模拟整个硬件而是用Linux的network namespace网络命名空间把一台真实内核拆成多套独立的网络栈。每个host是一个单独的命名空间有自己的网卡、路由表和ARP缓存而交换机用软件实现的虚拟交换设备默认是Open vSwitch或用户态交换机来模拟。这意味着你在Mininet里跑的TCP/IP协议栈、socket API、ping命令全部是内核原生的不是重新实现的模拟器逻辑。这也是为什么Mininet实验的结果比如带宽测试往往比GNS3的QEMU虚拟机方案更接近真实。当然代价是它只能在Linux上运行Windows需要WSL2或虚拟机而且不能模拟硬件转发延迟部分物理层行为会失真。对于做协议验证和SDN开发这个取舍是值得的。安装方式常见有两种一种是通过apt直接装适合快速开始另一种是从源码安装适合需要修改Mininet自身或想用最新版的情况。我一般建议第一次直接apt装版本旧一点但稳定。# 方式一apt安装Ubuntu/Debian sudo apt update sudo apt install -y mininet # 方式二源码安装获取最新开发版 git clone https://github.com/mininet/mininet cd mininet sudo util/install.sh -a逻辑说明方式二中的install.sh -a会安装Mininet及其依赖的Open vSwitch、Wireshark等工具适合打算后续做SDN实验的人。如果只跑基础拓扑方式一就够了。参数说明-a表示all包括控制器、交换机和可视化组件如果网络环境不好可以改用-nf只装Mininet本体和Open vSwitch。2.2 最小拓扑一个交换机加两主机的连通性验证安装完成后第一个实验建议用默认的miniedit或者最简单命令来创建一个交换机两个主机的拓扑。Mininet自带一个命令mn它把创建进程、分配IP、启动交换机这几件事全封装了。我习惯先用--test pingall跑一次完整校验再手动进入交互环境。sudo mn --topo single,2 --mac --switch ovsk --controller none参数说明--topo single,2表示用single拓扑即一个交换机后面跟2个主机--mac让主机的MAC地址固定为00:00:00:00:00:01这样的格式便于抓包分析时识别--switch ovsk指定使用Open vSwitch作为虚拟交换机这样后续对接OpenFlow控制器时更顺手--controller none表示不启动控制器交换机工作在普通二层转发模式。这个命令执行后会进入mininet提示符此时可以运行pingall看连通性。mininet pingall如果输出是host0 - host1 OK这类结果说明两个主机之间的二层通路已经打通。这里有个容易被忽略的点--controller none时Open vSwitch默认会学习MAC地址并转发所以ping能通。如果你想验证这一层可以再执行dpctl dump-flows查看流表。2.3 手动验证链路与链路属性拓扑建好之后别急着开iperf。先用net命令看一下每个节点的网络接口和IP分配再确认链路是否按预期工作。mininet net mininet intfs mininet links三个命令的作用分别是net列出host、switch以及它们之间连接关系intfs显示每个接口的详细参数links只看链路状态。多数新手会跳过这一步直接跑应用结果带宽测试失败后开始怀疑Mininet其实是接口没配对。我一般会用xterm打开一个host的终端手动ping对端这样能同时看到两端进程的输出。如果连默认拓扑都没跑通优先检查两个东西第一虚拟化支持是否开启用egrep -c (vmx|svm) /proc/cpuinfo看一下第二是否有残留的虚拟网卡或者老进程占用资源用sudo mn -c清理一次再试。mn -c这个命令可以理解为后悔药它会把上次实验留下的namespace、网桥、临时文件全部清掉避免脏环境。2.4 用--link参数初步设置延迟与丢包Mininet的命令行允许直接给链路附加模拟参数这是它区别于普通虚拟机网络的关键能力。比如执行sudo mn --topo linear,3 --link tc,delay20ms,loss10这个命令创建一条线性拓扑switch1连host1switch1连switch2switch2连host2以此类推并对每条链路叠加tcLinux流量控制配置单向延迟20毫秒、单向丢包率10%。注意这里tc是Mininet link类型的一种底层调用TC工具在虚拟接口上挂载netem队列。loss10表示每一跳随机丢包10%不是一次实验丢10%的包。为什么要在命令行里先试这个因为你可以立刻用ping验证效果pingall会显示部分丢包ping -c 10能算出平均RTT大约40毫秒因为双向。这个结果非常直观让你确信任意链路参数的修改真实生效了。但也别急着把所有参数都堆到命令行里因为一旦拓扑复杂链路参数混在一起后期非常难维护。更合理的做法是回到Python脚本用addLink的bw、delay、loss参数显式声明链路这正好是下一章的主题。Mininet的链路参数底层都交给Linux TC实现。delay20ms会转换成tc qdisc add dev ... root netem delay 20msloss10对应netem loss 10%bw则使用tbf或htb队列。了解这一点对你排错很有用当你看到Mininet里的链路表现不符合预期时直接进到host的接口上看qdisc配置。例如mininet sh tc qdisc show dev s1-eth1这条命令会展示s1连接h1的那张网卡上已经挂载的队列规则。如果输出里没有netem或tbf说明链路参数没有生效。这个底层视角能让你的实验报告更有说服力也更容易解释为什么loss的随机性会影响数据。很多教材只教你用Mininet命令不告诉你TC层发生了什么导致你遇到问题时无从下手。2.5 最小实验报告数据怎么记才有效为了让你之后写实验报告不抓狂我建议从第一个拓扑开始就养成记录习惯。Mininet本身不生成报告但你可以用命令输出重定向保存现场数据。例如sudo mn --topo single,2 --mac --switch ovsk --controller none --test pingall result.txt 21这里--test pingall会让mn直接运行测试后退出不进入交互模式。 result.txt 21把标准输出和错误都写到文件。这样做的好处是你得到的实验证据可以粘贴到报告里而不是靠回忆。注意--test模式下Mininet会套用默认的iperf等其他测试选项如果你只想要ping结果这个写法是对的。21这个重定向在Linux上极其常用但很多新手只写结果报错信息丢了一堆。报告里除了命令输出我一般还会记录一个表格检查项命令预期结果拓扑连通性pingall所有host间OKRTTpy net.hosts[0].cmd(ping -c 3 10.0.0.2)丢包率0%RTT平均0.1ms流表dpctl dump-flows存在两条转发流表项这个表并不是凑字数它是实验报告的核心骨架。很多同学写Mininet实验报告直接贴一张截图截图里只有一个pingall的OK这等于把黑匣子原样交给了老师。有了表格和对应的命令输出别人复现你的实验时才知道要跑哪些命令、期待什么结果。后续的带宽、延迟实验也可以沿用同一套表格模板。3. 自定义拓扑实验用Python脚本控制带宽、延迟与丢包3.1 为什么需要Python脚本而不是mn命令mn命令可以快速演示但真实实验场景里拓扑往往是分层的、链路参数需要逐条指定甚至需要动态修改。这时候就得写Mininet的Python API脚本。它本质上是一段普通的Python程序通过导入mininet库定义Topo子类或直接使用Topo对象来构建网络。相比命令行Python脚本的好处有三个第一参数可以用变量和循环生成比如批量创建20个主机、按矩阵连接交换机第二可以注册启动后的回调比如在start()后自动设置QoS第三实验报告可以嵌在代码注释里让脚本本身变成可复现的文档。一个最小但完整的脚本如下你把它存成my_topo.py然后sudo python3 my_topo.py就能运行。#!/usr/bin/env python3 from mininet.topo import Topo from mininet.net import Mininet from mininet.node import OVSSwitch, RemoteController from mininet.cli import CLI from mininet.link import TCLink class MyTopo(Topo): 自定义拓扑s1连接h1/h2/h3s1-s2级联s2连接h4 def build(self): # 创建交换机 s1 self.addSwitch(s1, clsOVSSwitch) s2 self.addSwitch(s2, clsOVSSwitch) # 创建主机 h1 self.addHost(h1, ip10.0.1.1/24) h2 self.addHost(h2, ip10.0.1.2/24) h3 self.addHost(h3, ip10.0.1.3/24) h4 self.addHost(h4, ip10.0.2.4/24) # 添加链路指定带宽、延迟、丢包 self.addLink(s1, h1, bw10, delay5ms, loss0, use_htbTrue) self.addLink(s1, h2, bw20, delay10ms, loss1) self.addLink(s1, h3, bw30, delay15ms, loss0) self.addLink(s1, s2, bw100, delay2ms, loss0) self.addLink(s2, h4, bw50, delay20ms, loss0) if __name__ __main__: topo MyTopo() net Mininet(topotopo, switchOVSSwitch, linkTCLink, controllerRemoteController) net.start() print(链路状态) for link in net.links: print(link) CLI(net) # 进入交互命令行 net.stop()逻辑说明这个脚本定义了一个继承Topo的类在build()方法里添加节点和边。每个主机显式指定了IP这样可以避免Mininet默认的10.0.0.x分配不够用。self.addLink的前两个参数是端点后面跟的关键字参数都是链路属性bw单位是Mbit/sdelay可以是5ms这样的字符串loss是整数百分比use_htbTrue表示带宽限制使用HTB队列规则默认就是True有时候写出来是提醒读者这里有队列调度。在main部分用Mininet类加载拓扑指定交换机和链路类型。RemoteController是远程控制器的占位如果你还没有启动控制器可以先用Controller默认代替这里写RemoteController只是为了展示如何在后面对接SDN。参数说明需要重点理解linkTCLink是必须的。如果漏掉这一行Mininet会使用Link类它只做数据通路连接完全不施加任何带宽/延迟/丢包限制。你会在实验时发现bw10根本不生效所有链路跑满千兆。这是新手最容易踩的坑之一。另一个细节是delay和loss只对TCLink有效而bw如果不指定默认没有限制。3.2 如何验证链路参数真实生效脚本写好后光靠ping看不出带宽限制。跑一下iperf是最直观的验证方式。在CLI里执行mininet iperf h1 h2但iperf命令默认只测TCP且输出只有带宽值。我建议用更详细的模式进入h1的xterm手动启动iperf3 -s然后在h2里执行iperf3 -c 10.0.1.1 -t 10。这样你可以观察限速效果。比如h1的bw是10Mbpsh2的bw是20Mbps那么h1到h2的方向实际吞吐应该被限制在10Mbps附近。这里有个关键现象由于TCP拥塞控制实测带宽会接近但略低于9Mbps因为还有协议头部开销。这不是Mininet的bug而是TCP对链路容量的正常收敛。如果你想同时验证延迟和丢包在CLI里运行mininet py net.hosts[0].cmd(ping -c 10 10.0.1.2)观察输出里的丢包率。比如loss1时10个包丢1个通常输出9 received, 1% packet loss。但要注意netem丢包是概率性的可能10次刚好0丢包也可能丢2个所以实验报告的丢包率应该用-c 100甚至-c 1000来统计才能逼近设定值。我在做延迟验证时会额外注意RTT值延迟是单向参数ping结果是双向RTT。所以delay5ms的链路ping RTT大约在10ms左右加上处理延迟约0.05ms。很多人报告里写RTT 5ms其实那是理解错了方向。3.3 动态调整链路参数不用重建拓扑的实验技巧Mininet的另一个好处是可以在运行中修改链路参数而不需要重启整个拓扑。在CLI里执行mininet link s1 h1 loss 20 mininet link s1 h1 delay 20mslink命令接受loss、delay、bw这三个关键词后面跟新值。这个操作本质上是重新配置TC的netem和tbf规则。对于做断线实验可以直接用link s1 h1 down和link s1 h1 up模拟物理链路故障和恢复。我当年做链路切换实验就是靠这个命令反复触发交换机重新学习拓扑省去了重启拓扑的等待时间。注意当你用link命令修改了参数后如果想恢复初始值必须显式写回比如link s1 h1 loss 0。CLI不会记住初始配置。动态调整还有一层含义你可以写一个后台Python线程周期性地改变某条链路延迟用来模拟网络抖动。这在验证实时流媒体协议时很有用。但要注意线程与Mininet事件循环的同步不能直接在一个线程里调用net对象建议通过net.monitor或timer来实现。3.4 实验报告的带宽数据怎么记录跑完带宽实验粗心的人只记一个最终带宽。但实验报告需要过程的波动情况。用iperf3 -c 10.0.1.1 -t 10 -i 1可以让iperf每秒输出一次带宽值你把这些值记录成表格能看出TCP是否稳定。如果是UDP测试还需要指定-u -b 100M表示发送速率。比如验证链路限速时UDP包可能会超速或丢包这本身就是重要的实验现象。# 在h1上服务端 iperf3 -s -p 5002 server.log # 在h2上客户端发送UDP 50Mbps iperf3 -c 10.0.1.1 -p 5002 -u -b 50M -t 5 -i 1参数说明-p指定端口-u表示UDP-b 50M表示目标带宽50Mbps-t 5持续5秒-i 1每秒打点。如果你在第二条链路上设置了bw30那么以50Mbps发送会观察到接收带宽约30Mbps和约20Mbps的丢包。这个实验直接证明了TC限速真实有效。把打点数据复制进Excel画一条时间-带宽曲线就是漂亮的实验报告图表了。3.5 常用的链路参数实验组合速查表在写实验报告时很多人不知道如何选择链路参数来模拟不同场景。我一般用这样一套组合模拟局域网时bw100, delay1ms, loss0模拟跨地域广域网bw20, delay20ms, loss0.1模拟无线链路bw50, delay5ms, loss2模拟拥塞链路bw10, delay50ms, loss5。每个组合都建议用iperf和ping同时验证因为这些参数之间会互相影响比如延迟大、带宽小时TCP吞吐受带宽延迟积限制。场景bw(Mbit/s)delay(ms)loss(%)验证重点局域网10010TCP吞吐接近带宽广域网20200.1单程延迟约20msRTT约40ms无线链路5052丢包率约2%ping方差大拥塞链路10505吞吐远低于带宽丢包明显这个表不仅帮助你快速实验还能在报告里展示你对场景与参数映射的理解。如果你做的是对比实验一定要确保所有场景都跑在同样的拓扑下只改变链路参数否则结论就不可信了。4. 对接SDN控制器把Mininet变成OpenFlow实验床4.1 Mininet的控制器类型与选型Mininet自带一个简单的参考控制器Controller但它只实现了基本的二层MAC学习无法满足你对于OpenFlow流表编程的期待。当你开始做SDN实验时通常需要外接一个远程控制器比如Ryu、OpenDaylight、ONOS、Floodlight等。Mininet的角色变成交换机侧的工具它通过OpenFlow协议连接远程控制器并把包转发行为交由控制器决策。这里的关键点是Mininet里每个虚拟交换机都是一个OpenFlow交换机实例默认监听6653端口旧版本是6633。如果你没有启动任何控制器交换机端口是关闭的除非使用--controller none进入自治二层模式。控制器选型没有绝对标准。我个人经验如果做基础教学实验首选Ryu因为它是纯Python、代码量小、用ryu-manager一条命令就能启动配合simple_switch_13.py示例五分钟跑通。如果做生产级多控制器高可用实验可以选ONOS或OpenDaylight。Floodlight也还有人用但新项目不多。注意一点不同控制器版本对OpenFlow协议版本支持不同Mininet默认会尝试1.3Open vSwitch 2.7以上老旧控制器只支持1.0的话需要额外配置。4.2 远程控制器连接启动Ryu并让Mininet接入先给出最标准的三步实验流程。第一步启动Ryu控制器需要先安装pip install ryu。第二步运行一个最简单的二层转发应用ryu-manager --verbose ryu.app.simple_switch_13--verbose会把控制器收到的Packet-In、流表下发等消息打印到屏幕这些日志是后面排查问题的重要依据。simple_switch_13是Ryu自带的OpenFlow 1.3二层自学习应用行为和普通交换机一样但它通过控制器下发流表来实现MAC学习。第三步启动Mininet并指定远程控制器sudo mn --topo single,3 --controller remote --ip 127.0.0.1 --port 6653 --switch ovs参数说明--controller remote告诉Mininet不要用默认控制器--ip是控制器所在地址本机就是127.0.0.1--port是OpenFlow端口。这一步启动后你会看到Ryu的终端滚动日志显示“Subscribed the switch”之类的事件。此时执行pingall理论上应该全通。但如果你跑的是自学习交换机应用第一次ping的包会触发Packet-In控制器下发流表之后就走硬转发。为了确认在Mininet CLI里执行mininet sh ovs-ofctl dump-flows s1这条命令会显示交换机s1的流表项。注意这里的sh表示在Mininet所在Linux主机上执行shell命令不是进入某个host。ovs-ofctl是Open vSwitch自带的控制工具参数dump-flows s1表示打印s1的所有流表。如果看到类似table0, n_packets…, priority…, dl_dst… actionsoutput:…的记录说明流表确实由控制器下发。关于端口参数Mininet默认的OpenFlow端口是6653但有些教程还写6633这是旧版本常值。如果你的Ryu监听的是6633那么Mininet启动时就要指定--port 6633。我见过很多翻车情况是因为一个默认值不一致导致控制器日志毫无反应。统一用6653可以减少不必要的麻烦。此外Ryu应用如果报错No module named ryu.lib.packet之类多半是pip安装时权限不对或版本不兼容。建议在虚拟环境安装python3 -m venv venv source venv/bin/activate pip install ryu。这样能避开系统Python的权限问题。这套虚拟环境的做法也适用于Mininet的Python API脚本但注意Mininet本身需要root权限而venv里的普通用户无法用root运行脚本所以你需要用sudo python3加上venv的Python路径来启动。4.3 用自定义控制器实现一个简单的静态流表实验如果你不想依赖自学习应用想手动控制转发路径可以写一个最小的Ryu控制器只下发一条指定主机到主机的静态流表。这是一个经典实验让h1和h2互通的流表完全由你指定禁止其他流量。代码很短from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import set_ev_cls from ryu.ofproto import ofproto_v1_3 from ryu.lib.packet import packet, ethernet class SimpleStatic(app_manager.RyuApp): OFP_VERSIONS [ofproto_v1_3.OFP_VERSION] set_ev_cls(ofp_event.EventOFPSwitchFeatures, dispatcher0) def switch_features(self, ev): dp ev.msg.datapath ofproto dp.ofproto parser dp.ofproto_parser # 下发两条流表h1 - h2h2 - h1 # h1的MAC是00:00:00:00:00:01h2的MAC是00:00:00:00:00:02 for src_mac, dst_mac, out_port in [ (00:00:00:00:00:01, 00:00:00:00:00:02, 2), (00:00:00:00:00:02, 00:00:00:00:00:01, 1), ]: match parser.OFPMatch( eth_srcsrc_mac, eth_dstdst_mac, eth_type0x0800, ) actions [parser.OFPActionOutput(out_port)] inst [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] mod parser.OFPFlowMod( datapathdp, priority10, matchmatch, instructionsinst, ) dp.send_msg(mod)逻辑说明switch_features事件在交换机连接控制器时触发我们利用它第一时间下发流表。OFPMatch定义了匹配规则源MAC、目的MAC、以太网协议类型IPv4。OFPActionOutput指定从哪个端口送出。端口号2和1分别对应s1连接h2和h1的端口这要依赖实际拓扑顺序。你可以先用sh ovs-ofctl show s1查看端口对应关系再修改代码里的out_port。这段代码的本质是静态路由实验的OpenFlow版它让你看清一个SDN转发规则需要哪些字段、端口号怎么映射。跑这个实验时配合Wireshark抓包会非常直观。在Mininet CLI里启动抓包sh tcpdump -i s1-eth2 -w /tmp/p.pcap然后h1 ping h2再用Wireshark打开pcap文件能看到ICMP包而交换机里的其他流量不会产生任何动作。4.4 控制器连接失败时的排查步骤控制器没连接上是最常见的翻车场景。现象通常有两种Mininet启动时没有报错但pingall全挂或者Ryu日志里完全没有“Switch features”消息。排查顺序我一般这样# 1. 确认控制器进程真的在跑并监听端口 sudo netstat -tlnp | grep 6653 # 2. 确认Mininet的交换机在尝试连接 sudo ovs-vsctl show | grep -A5 Controller # 3. 抓取6653端口流量看是否三次握手成功 sudo tcpdump -i any port 6653 -c 20如果netstat显示Ryu监听的是9000端口或者其他端口那就是启动参数不对。如果ovs-vsctl show显示Controller状态为is_connected: false说明交换机主动连了但被拒绝。常见原因是控制器使用的OpenFlow协议版本与交换机不一致比如Ryu默认只启用了1.3而Mininet的Open vSwitch强制协商版本失败。你可以用--switch ovs,protocolsOpenFlow13来指定协议。还有一个容易被忽略的坑Mininet启动时会以--controller remote连接控制器但如果你的控制器绑定了--app参数而没有--verbose日志可能不打印连接消息并不代表没连上。5. 避坑指南Mininet实验里最常翻车的5个细节Mininet的优点在于轻量但轻量也意味着它的行为受宿主机环境影响很大。这一章我把过去两年实验里踩过最深的5个坑列出来每条都按“现象-原因-解决”的顺序写你在复现自己的拓扑时遇到类似情况直接对号入座。5.1 链路参数不生效设了带宽却跑满千兆现象你在Python脚本里写了addLink(s1, h1, bw10)然后iperf测试h1到h2带宽显示800Mbps以上。原因几乎都是Mininet构造时没有把链路类型指定为TCLink。在Mininet类的初始化参数里link默认是Link类它只是创建一对veth并连接完全不解析bw、delay、loss这些参数。命令行方式也一样如果你不带--link tcmn --topo single,2 --link tc才有TC效果。解决方法是检查你的构造代码是否写了linkTCLink。在CLI里可以用py命令确认链路对象类型mininet py net.links[0].status() mininet link s1 h1link s1 h1如果输出里没有bw字样说明该链路不是TC管控的。另外需要注意的是如果你使用了addLink但漏掉use_htbFalse默认False带宽限制也不会用HTB队列而是默认使用tbf实际上Mininet的TCLink默认use_htbTrue。这里有个细节在某些旧版本里bw参数必须配合use_htbTrue才能准确限速否则可能用的是更简易的tbf导致限速不精确。建议显式加上use_htbTrue。5.2 环境残留导致启动失败mn -c是后悔药现象第二次运行sudo mn时报错“Error creating network namespace”或者Open vSwitch数据库冲突。原因上一次实验的非正常退出比如Ctrl\直接kill、关闭了xterm导致命名空间、虚拟网桥、veth对没有回收。解决强制清理再重试。sudo mn -c sudo ovs-vsctl showmn -c会清理所有Mininet相关的进程、网桥、命名空间、临时文件。执行完后检查ovs-vsctl show的输出是不是空的如果还有残存的bridge可以手动删sudo ovs-vsctl del-br s1。这个操作我可是用血泪经验换来的早期我为了图省事直接重新跑mn反复报错后才发现是残留问题。现在我的习惯是写实验脚本前先执行一次mn -c作为保险。5.3 实验数据抖动太大别让CPU调度背锅现象同一拓扑连续跑三次iperf结果分别是950M、780M、870M。原因Mininet的所有host都是本机进程CPU调度和中断处理都会影响实时性尤其是多主机同时跑iperf时内核栈和netem队列争抢CPU。解决第一减少同一时刻并发测试的主机数量别用iperf命令一次测所有主机而是逐个测试第二给iperf进程足够的时间预热比如-t 10而不是-t 2第三如果你在复用CPU的公用服务器上做实验建议用taskset把Mininet主进程绑定到某个物理核避免跨NUMA节点带来额外延迟。这个方法不能完全消除抖动但能让你在报告中把误差归因到更科学的位置。5.4 远程控制器连接成功但流表为空现象Ryu日志显示交换机已连接pingall失败ovs-ofctl dump-flows s1输出空。原因最常见的是控制器应用没有对Packet-In事件做出响应或者匹配条件写错。排查步骤先在Mininet CLI执行pingall然后立刻在Ryu控制台看有没有打印HTTP或OF消息。如果交换机是回环连接的没有产生Packet-In可能是流表规则里有priority0的table-miss但它只匹配不上其他规则的包正常。如果确实有Packet-In但不下发流表检查你的match字段。我遇到过一个例子控制器应用用了eth_type0x0806来匹配ARP但实际流量是IPv4的ICMPeth_type0x0800导致ARP被正确转发ICMP全丢。这就是协议号写错导致的流表空转排查时可以结合Wireshark抓包看控制器的of消息。5.5 每次结果不可复现把随机因素摆在明面上现象同一条命令ping -c 5 h2第一次丢包20%第二次0%。原因netem的丢包是基于概率的而且Mininet的ARP响应时间也可能影响前几个包的统计。解决把测试次数放大到统计稳定的量级。比如测丢包率用mininet h1 ping -c 100 -i 0.2 -q h2-i 0.2表示间隔0.2秒-q只输出汇总信息。这样100个包的丢包率能稳定到整数位。延迟同理用ping -c 100 | tail -1取平均。另外pingall的结果只适合连通性判断不适合写进实验报告的丢包率。我一般还会记录每个host的CPU型号或任务数防止别人质疑数据时无法解释。实验报告里注明“本测试在空闲CPU下进行重复三次取中位数”这比数值本身更有说服力。6. 把实验写成可复现报告自动化收集结果与拓扑可视化6.1 用脚本一键完成「拓扑创建 测试 数据导出」写实验报告的痛苦往往不是实验本身而是把数据从各个终端复制出来、粘贴到Word。Mininet提供了--test模式但你也可以直接在Python脚本里注册自定义测试函数。下面的脚本演示了如何创建拓扑后自动执行ping和iperf并把结果写入文本文件。from mininet.net import Mininet from mininet.node import OVSSwitch from mininet.link import TCLink from mininet.topo import Topo class TwoHostTopo(Topo): def build(self): s1 self.addSwitch(s1) h1 self.addHost(h1, ip10.0.0.1/24) h2 self.addHost(h2, ip10.0.0.2/24) self.addLink(s1, h1, bw10, delay5ms, loss0) self.addLink(s1, h2, bw10, delay5ms, loss0) if __name__ __main__: topo TwoHostTopo() net Mininet(topotopo, linkTCLink, switchOVSSwitch) net.start() # 在h2上启动iperf服务端 net[h2].cmd(iperf -s ) net[h1].cmd(sleep 1) with open(report.txt, w) as f: f.write( Ping Test \n) f.write(net[h1].cmd(ping -c 10 -q 10.0.0.2)) f.write( IPERF TCP \n) f.write(net[h1].cmd(iperf -c 10.0.0.2 -t 5 -i 1)) net.stop()逻辑说明net[h1].cmd(...)在host节点里执行命令返回值是命令的标准输出字符串直接写入文件即可。这里用ping -c 10 -q获得汇总数据用iperf -c 10.0.0.2 -t 5 -i 1获得每秒带宽。注意iperf默认是客户端模式所以先在对端h2上启动服务端给它1秒时间监听再让h1发起连接。如果漏了服务端启动iperf -c会直接报“connect failed”report.txt里只有错误信息。6.2 导出拓扑图把拓扑画进实验报告Mininet自带一些CLI命令比如net和dump可以列出节点关系但要出图还得靠Graphviz。一个简单做法是写一个小函数遍历net.links生成dot格式的拓扑描述def dump_topo_to_dot(net): with open(topo.dot, w) as f: f.write(graph topo {\n) for host in net.hosts: f.write(f {host.name} [shapecircle];\n) for switch in net.switches: f.write(f {switch.name} [shapebox];\n) for link in net.links: f.write(f {link.intf1.node.name} -- {link.intf2.node.name};\n) f.write(}\n)然后在shell里用dot -Tpng topo.dot -o topo.png渲染。如果你装了Graphviz。这个技巧能帮你生成和实验一致的拓扑图比截图命令行清楚得多。注意dot文件里节点名要保持唯一Mininet的命名规则本来就是s1、h1这种所以直接可用。6.3 一份实验报告应当包含的最小要素我做完实验后整理报告会固定检查四块内容一是实验拓扑图和节点参数表二是连通性验证结果pingall输出三是性能测试数据带宽、延迟、丢包率及测试命令四是关键流的抓包截图或流表快照。这四个要素缺一不可。如果你是用我这篇文章里给出的脚本来做实验那么report.txt自动包含了第二、三块流表快照用ovs-ofctl dump-flows保存拓扑图用dot脚本生成。所有文件放入一个目录放在实验报告的同级目录下方便别人核验。最后说一个我自己的习惯我每个实验都会在同一台Linux物理机上跑三次然后记录CPU占用和空闲内存再取中位数写进报告。原因是Mininet依赖宿主机的实时调度任何后台任务都会污染数据。这个习惯帮我挡下了不少“实验结果无法复现”的质疑。希望帮到你。本文还有配套的精品资源点击获取
返回列表