ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于Mininet的SDN课程设计实战:从环境搭建到故障切换

基于Mininet的SDN课程设计实战:从环境搭建到故障切换 简介面向高校研究生课程教学的PDF文档围绕软件定义网络SDN实验课程设计展开。针对当前SDN实验科目匮乏、硬件交换设备昂贵且难以大规模部署、实验环境灵活性不足、学生上手难度大等问题文档提出基于Mininet模拟环境配合POX、Kinetic、Pyretic等控制器搭建实验方案的思路可在笔记本上快速构建虚拟网络并支持实验代码向真实硬件无缝迁移。内容涵盖SDN网络环境搭建、特定拓扑绘制、网络分割、二层防火墙编写等基础型、验证型、综合型共11个实验科目并按照体现最新研究进展、增强与传统网络差异对比、模块化组织教学的设计思路展开兼顾不同层次研究生的个性化培养需求。资源包为单个PDF文件大小174KB信息密度高可直接作为SDN实验课程设计模板或教学改革参考资料。目前已有104人学习适合网络工程、通信等相关专业的师生借鉴。1. 基于 Mininet 模拟环境的软件定义网络课程设计一周内交付的落地路线很多网络工程方向的同学在拿到课程设计任务书时第一反应是凑实物设备买两台支持 OpenFlow 的交换机、拉网线、配控制器。其实 SDN 课程设计用 Mininet 这类模拟环境搭十分钟就能把同样的网络拓扑——多台 OpenFlow 交换机、链路、主机——在笔记本上拉起来。这篇笔记围绕“基于 Mininet 模拟环境的软件定义网络实验课程设计”整理一条能直接照做的落地路径从环境搭建、拓扑设计到控制器对接和实验数据记录把我踩过的坑一并写出来。适合准备在一到两周内提交课程设计报告、手里没有真实硬件的学生也适合想快速验证 SDN 思路的从业者。2. 先搭出可信的模拟环境Mininet 安装、自检与自定义拓扑2.1 为什么用 Mininet它到底模拟了什么Mininet 常见的误解是它“模拟”了物理交换机。其实它用 Linux 的 network namespace 把每个主机、交换机、链路都做成独立的虚拟网络节点交换机运行真实的 Open vSwitch 用户态程序主机拥有完整独立的网络协议栈。网络包在 Mininet 里经过的是真实协议栈的处理TCP 拥塞控制、重传、队列调度都是真实内核行为你在课程设计里测到的带宽、时延、丢包是模拟环境下的真实观测值而不是数学仿真算出来的期望值。这和 GNS3、EVE-NG 那种“跑真实网络设备镜像”的思路不同Mininet 明显更轻笔记本上起 20 个节点都不吃力也和 ns-3 那种纯事件仿真不同你手里真的有 OpenFlow 端口、真实接口名和一个可以抓包的网桥。对课程设计来说这是最接近“黑匣子实验”的模拟环境底层越真实报告里引用数据时越有底气。在我接触过的课程设计里最容易拉开分差的不是谁拓扑画得复杂而是谁能在答辩现场说清楚“这个数字在模拟环境里是怎么被制造出来的”。2.2 本机装好最小环境的三条命令最常见做法是直接装发行版打包的 mininet而不是从源码编译。源码编译能拿到新特性但课程设计周期短apt 装好、跑通自检、开始写拓扑才是正路sudo apt update sudo apt install -y mininet sudo mn --test pingallmn是 Mininet 的启动命令--test pingall表示启动一组默认拓扑两台主机挂在一台交换机上后立刻做全网互相 ping全部返回 0% 丢包说明内核模块和虚拟化基础正常。如果这一步就报错先解决系统层问题再往下走不要抱侥幸心理直接开写拓扑文件。自检通过后再花 30 秒确认一下版本和 OVS 状态mn --version ovs-vsctl --versionMininet 与 OVS 的版本组合偶尔会出兼容问题记录下这两个版本号后面控制器对接如果出现“协议版本对不上”的怪问题排查时会快很多。sudo mn --topo linear,3和sudo mn --topo tree,2,3这两个自带拓扑用来做环境验收足够真正的实验拓扑要按第 4 章的需求自己写。提示Mininet 对内核模块有依赖如果跑在虚拟机上优先选 Ubuntu 20.04 或 22.04 这类 LTS 版本。某些精简内核缺少openvswitch相关模块时modprobe openvswitch会报错这属于宿主系统问题得先换内核或装对应模块再回来装 Mininet。2.3 用 Python 拓扑文件代替命令行敲交换机课程设计里经常要“两台交换机之间拉起两根冗余链路”这种结构命令行--topo参数表达不了需要自定义拓扑。Mininet 的 Python API 是标准做法把拓扑写进一个文件再通过--custom引入from mininet.topo import Topo class RedundantTopo(Topo): def build(self): # 三台交换机其中 s1 与 s2 之间两条链路 s1 self.addSwitch(s1, protocolsOpenFlow13) s2 self.addSwitch(s2, protocolsOpenFlow13) s3 self.addSwitch(s3, protocolsOpenFlow13) h1 self.addHost(h1) h2 self.addHost(h2) # 核心冗余链路两条链路模拟不同物理路径 self.addLink(s1, s2, bw100, delay5ms) self.addLink(s1, s2, bw100, delay20ms) self.addLink(s2, s3, bw100, delay5ms) self.addLink(h1, s1, bw100, delay2ms) self.addLink(h2, s3, bw100, delay2ms) topos {redundant: RedundantTopo}这段代码里protocolsOpenFlow13是关键参数它把交换机协议固定在 OpenFlow 1.3避免控制器默认支持 1.3 而交换机在 1.0 上等你导致永远握不上手。bw单位是 Mbpsdelay单位是毫秒写bw100之后 Mininet 会用 Linux TC 做限速链路参数是可观测的不是摆设。运行方式是sudo mn --custom ~/redundant_topo.py --topo redundant \ --controller remote,ip127.0.0.1,port6633 --mac--controller remote指定用外接控制器接管ip和port对应该控制器的监听地址--mac让主机 MAC 地址与 IP 地址尾部对齐抓包和写报告时靠 MAC 一眼认出是哪个主机。这个命令会阻塞在前台实验过程中保留这个窗口后面链路通断都在mininet提示符下操作。如果启动报错九成是topos {redundant: RedundantTopo}这个注册名和--topo后面的名字不一致导致找不到拓扑类先对一下名字。3. 让控制器接上 Mininet控制器选型、Ryu 安装与握手验证3.1 三种控制器的取舍Ryu、OpenDaylight、ONOS 适合谁SDN 的架构里控制面必须有一个真实运行的软件。“基于 Mininet 模拟环境”的实验如果没有外接控制器那只是 Mininet 自带参考控制器在兜底转发没体现出软件定义网络的真正含义。课程设计的控制器选型常见的就是三类控制器上手成本主要语言适合的选题Ryu低Python流表下发、学习交换机、链路故障OpenDaylight中高Java/配置带图形化管理界面的平台型选题ONOS中高Java/配置多控制器、网络分片、服务链我一般建议课程设计选 Ryu。一是代码量小报告里能逐条解释流表是怎么来的二是日志直白交换机连接、PacketIn、FlowRemoved 在终端上看得到三是 Python 生态里协议解析都是现成的不用自己写 OpenFlow 报文解析。OpenDaylight 和 ONOS 适合做“平台演示型”的题目但一两周的课程设计周期里安装、调优和排错过程本身就能吃掉一半时间除非题目明确要求用这类控制器否则性价比不高。3.2 装 Ryu 并让 Mininet 连上它Ryu 用 pip 装即可源码安装主要在需要改动 Ryu 内部协议解析逻辑时才值得做sudo apt install -y python3-pip pip3 install ryu ryu-manager --version装好先运行 Ryu 自带的二层交换机应用验证整条链路sudo ryu-manager --verbose ryu.app.simple_switch_13--verbose会把每个 PacketIn 的详情打到屏幕包括交换机 datapath id、端口号、源 MAC 和目的 MAC。第一次运行时屏幕上会刷大量 ARP 和 ICMP 的 PacketIn这是正常的说明 OpenFlow 交换机把未知地址的包上送给了控制器控制器学习后下发流表并泛洪。看到日志后另开一个终端进入 Mininetsudo mn --custom ~/redundant_topo.py --topo redundant \ --controller remote,ip127.0.0.1,port6633 --mac进到mininet后立刻 ping 一次mininet h1 ping -c 3 h2能通就说明 Ryu 已经把 h1 到 h2 的流表下发到了 s1、s2、s3。注意必须先启动控制器再启动 Mininet顺序反了交换机在启动时找不到控制器会一直处于等待状态。3.3 握手成功才算接通日志、端口与交换机侧三层验证控制器没接上是课程设计里最常见的翻车点而“没接上”的表现并不总是报错有时候网络也能通但走的是兜底转发路径。判断是否真的由 Ryu 接管我按三步排查。第一看 Ryu 日志有没有 datapath。启动后若能看到EVENT ofp_event-...且 datapath id 非空说明 OpenFlow 握手已经完成。第二看端口监听sudo netstat -tlnp | grep 6633默认情况下 Ryu 监听 6633。如果这里看不到监听说明 Ryu 没起来或配置改了端口Mininet 自然连不上。第三去交换机侧确认连接状态sudo ovs-vsctl show sudo ovs-ofctl -O OpenFlow13 dump-ports s1如果 s1 的Controller一栏显示tcp:127.0.0.1:6633且状态是CONNECTED说明控制面对接成功。dump-ports顺带输出每个端口的收发包统计这些计数在写报告时可以直接引用用来描述“控制器接管前后端口的流量变化”。这三步走完整个模拟环境才算真正闭合控制面、数据面和南向协议都在工作。4. 复现一个完整的课程设计实验链路冗余与故障切换4.1 实验设计目标测什么、怎么测、预期什么结论把实验题目定成“链路冗余与故障恢复”是性价比最高的选题。拓扑只有三台交换机和一个冗余链路但呈现出的故障切换现象非常直观同时牵出 OpenFlow 流表、链路发现、故障感知三个软件定义网络的知识点。更重要的是“切换时延”是一个能量化的指标报告评审时比“流量能通”有说服力得多。实验设计s1 与 s2 之间有两条平行链路一条低时延设为主用一条高时延设为备用。h1 挂在 s1 下h2 挂在 s3 下。正常时流量走主链路把主链路断开后流量自动切到备用链路观察 ping 探测的中断秒数以及 iperf 吞吐从掉底到爬升的曲线形状。自变量是断哪条链路、什么时刻断因变量是切换时延与丢包数。前提是控制器已经能在第 3 章的基础上正常接管交换机。4.2 控制器端需要的最小代码逻辑实现故障切换控制器不需要复杂算法一个 MAC 学习逻辑加默认流表就够了收到 PacketIn 就学习源端口目的地址未知就泛洪已知就下发精确匹配流表链路断开时交换机上报 PortStatus旧流表随之失效后续数据包重新触发 PacketIn 学习新路径。以下是 Ryu 应用的核心骨架from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import MAIN_DISPATCHER, CONFIG_DISPATCHER, set_ev_cls from ryu.ofproto import ofproto_v1_3 from ryu.lib.packet import packet, ethernet class LearningSwitch(app_manager.RyuApp): OFP_VERSIONS [ofproto_v1_3.OFP_VERSION] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.mac_to_port {} set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) def switch_features_handler(self, ev): dp ev.msg.datapath parser dp.ofproto_parser match parser.OFPMatch() actions [parser.OFPActionOutput( dp.ofproto.OFPP_CONTROLLER, dp.ofproto.OFPCML_NO_BUFFER)] self.add_flow(dp, 0, match, actions) def add_flow(self, dp, priority, match, actions): inst [dp.ofproto_parser.OFPInstructionActions( dp.ofproto.OFPIT_APPLY_ACTIONS, actions)] mod dp.ofproto_parser.OFPFlowMod( datapathdp, prioritypriority, matchmatch, instructionsinst) dp.send_msg(mod) set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def packet_in_handler(self, ev): msg ev.msg dp msg.datapath in_port msg.match[in_port] pkt packet.Packet(msg.data) eth pkt.get_protocol(ethernet.ethernet) if eth is None: return dst, src eth.dst, eth.src self.mac_to_port.setdefault(src, in_port) out_port self.mac_to_port.get(dst, dp.ofproto.OFPP_FLOOD) actions [dp.ofproto_parser.OFPActionOutput(out_port)] if out_port ! dp.ofproto.OFPP_FLOOD: match dp.ofproto_parser.OFPMatch(eth_srcsrc, eth_dstdst) self.add_flow(dp, 1, match, actions) data msg.data if msg.buffer_id dp.ofproto.OFP_NO_BUFFER else None out dp.ofproto_parser.OFPPacketOut( datapathdp, buffer_idmsg.buffer_id, in_portin_port, actionsactions, datadata) dp.send_msg(out)代码逻辑拆三层。switch_features_handler在握手阶段下发一条priority0的表缺失流表把没匹配上的包全部上送控制器这是整个学习机制的入口。packet_in_handler每次收到上报报文先学习源 MAC 来自哪个端口再决定是精确下发还是泛洪。add_flow里的priority1是精确匹配表项的优先级高于默认的 0保证真实流量先命中精确规则。把文件存成learning_switch.py用sudo ryu-manager --verbose learning_switch.py启动它和 3.2 节的simple_switch_13行为等价但代码是你自己写的答辩时能讲清楚每一行。4.3 用 iperf 制造流量并断开链路把切换时延测出来故障切换实验要有流量变化的过程。在 Mininet 里用 iperf 在 h1、h2 之间制造持续流量mininet h1 iperf -s mininet h2 iperf -c 10.0.0.1 -t 60 -i 1-s起服务端-c起客户端-t 60持续 60 秒-i 1每秒输出一个带宽点。服务端必须加放后台不然占住 Mininet 终端后续命令敲不进去。流量跑起来后断开主链路mininet link s1 s2 down下一秒开始iperf 的带宽值会掉到接近 0再慢慢爬回正常中间那段空白就是从主链路切到备用链路的时间。如果换成 ping 探测会看到连续几个请求超时后恢复超时秒数就是切换时延的粗估计。切换完成后把链路恢复mininet link s1 s2 up整套断链、恢复操作重复做三到五次记录每次的切换时延取平均值。注意每轮实验前清空两台主机的 ARP 缓存否则本地缓存可能导致切换后的第一个包直接发出测出来的时延偏小mininet h1 arp -d 10.0.0.2 mininet h2 arp -d 10.0.0.14.4 把原始数据整理成报告表和结论课程设计报告最怕只有截图没有数据。实验做完第一时间把 iperf 输出重定向存文件mininet h2 iperf -c 10.0.0.1 -t 60 -i 1 /tmp/iperf_1.txt 21回到宿主机把每秒一行的时间、带宽列抽出来整理成 CSV画带宽随时间变化的折线图在断链时刻画一条竖标注线。这张图配合断链前后ovs-ofctl -O OpenFlow13 dump-flows s1的 diff 对比就是“链路故障导致吞吐中断、控制器重路由恢复”的核心证据。报告里给出切换时延的平均值、中位数和最大最小值比任何形容词都管用。5. Mininet 课程设计避坑记录环境到流表的 5 个高频翻车点5.1 xterm 报错与虚拟机里跑 Mininet 的兼容问题现象启动拓扑后在mininet里执行xterm h1报cannot find required executable xterm或在虚拟机里打开终端后窗口闪退。原因Mininet 的xterm功能依赖宿主机装有 X 终端程序精简版 Ubuntu 服务器默认不带这个包在虚拟机和 SSH 环境下还叠加 X11 转发失效的问题xterm 起不来属于正常。解决sudo apt install -y xterm。如果不需要图形终端最好绕开它所有操作都通过mininet提示符里的h1 ping、h1 iperf这类命令完成少一个依赖就少一个翻车点。报告截图也不需要 xterm用终端输出一样能说明问题。5.2 交换机状态停在 SWITCH 不对接控制器先查端口与协议现象ovs-vsctl show里 s1 显示未连接Ryu 日志里一个 datapath id 都没有Mininet 终端上却什么都不报网络也偶尔能 ping 通。原因常见三种。控制器没启动控制器监听端口不是 6633OpenFlow 协议版本不匹配——默认 OVS 只监听 OpenFlow10而 Ryu 应用声明了OFP_VERSIONS [ofproto_v1_3.OFP_VERSION]两边的版本没有交集交换机一直停留在等待状态。解决拓扑文件里给每台交换机显式指定protocolsOpenFlow13启动 Mininet 时的--controller remote,port6633与 Ryu 端口保持一致。按 3.3 节的三层步骤排查先看日志有没有 datapath再看端口有没有监听最后看交换机侧is_connected是否为 true。5.3 流表下发了却 ping 不通多半是 ARP 和默认流表现象Ryu 日志里 PacketIn 刷屏ovs-ofctl dump-flows里也有精确匹配表项但h1 ping h2还是 100% 丢包。原因ARP 请求没被正确处理。目的 MAC 未知时交换机要把 ARP 请求泛洪到所有端口如果默认流表的优先级高于精确匹配表或 FLOOD 动作因端口配置问题没生效ARP 就发不出去后续 ICMP 自然没有回包。另一个高频原因是重启 Mininet 后主机 MAC 变化控制器mac_to_port表里残留旧记录。解决在 Mininet 里执行s1 ovs-ofctl -O OpenFlow13 del-flows s1清空该交换机流表或sudo mn -c整体清理后重来。代码层面检查add_flow的 priority默认流表必须是 0精确匹配必须大于 0顺序不能反。5.4 iperf 带宽和拓扑设置对不上看看是不是 TC 限速在起作用现象拓扑里bw100iperf 测出来只有 80 多 Mbps带宽曲线抖动明显换了不同链路都是类似比例。原因Mininet 的bw通过 Linux TC 在交换机端口做限速令牌桶对突发流量不友好iperf 默认窗口下吞吐先被压一波再爬升到接近上限。跨多台交换机的bw100是逐段限速整体吞吐还会受瓶颈链路约束数值对不上是正常现象。解决把链路带宽统一调大如bw1000时延保持 5ms~20ms 级别再iperf -w 512k调大 TCP 窗口重测。如果报告里本来就要展示“带宽控制生效”就故意把一条链路设成bw10测出 10Mbps 左右的吞吐一高一低的对比比解释 80 和 100 的差距省力得多。5.5 实验结束后的环境残留与端口占用现象第二次运行mn时报端口被占或实验做到一半带宽结果突然和第一次不一样sudo mn -c输出大量清理日志。原因上次实验的 OVS 网桥、命名空间、TC 规则没清干净尤其 CtrlC 或直接关终端异常退出时残留最严重。Mininet 参考控制器进程有时还挂在 6633 端口上。解决每次实验结束统一sudo mn -c不要直接关终端下次运行前确认端口空闲sudo netstat -tlnp | grep 6633 sudo pkill -f ryu-manager; sudo pkill -f mn把这两行写进实验脚本开头每次跑实验自动清理这个习惯能替你挡掉至少一半的“第二个实验复现不了”的尴尬。6. 把实验结果变成可信结论Wireshark 抓包验证与实验脚本固化6.1 用抓包验证 OpenFlow 在起作用并用脚本固化实验流程实验跑通了、数据也在手上但课程设计评审时有一关容易被问到怎么证明这是 OpenFlow 在起作用而不是 Mininet 的内部转发我固定下来的做法是用 Wireshark 在控制面和数据面各抓一份包作为佐证。数据面抓包在 Mininet 里做mininet s1 tcpdump -i s1-eth1 -w /tmp/s1.pcap从 h1 ping h2 后按 CtrlC 停止导出的 pcap 里是带完整以太网头、IP 头、ICMP 报文的原始包直接印证链路通了。控制面抓包更有含金量回到宿主机对回环接口抓 6633 端口sudo tcpdump -i any port 6633 -w /tmp/openflow.pcap用 Wireshark 打开后过滤器填openflow_v1或of能看到OFPT_PACKET_IN、OFPT_FLOW_MOD、OFPT_PORT_STATUS这些消息类型的完整时间线。PORT_STATUS消息就是链路断开时交换机上报给控制器的那条关键报文截到它就等于抓到了“控制器感知故障”的第一手证据。我的习惯是把实验常用命令固定成一个run_experiment.sh推到一个 Gitee 私有仓库里做版本管理。实验迭代频繁Ryu 改一版、拓扑参数调一次git commit后随时能回到任一个可复现版本换机器继续跑时 clone 下来就能恢复环境。脚本骨架#!/bin/bash # 一键启动课程设计实验环境 sudo mn -c sudo pkill -f ryu-manager 2/dev/null sudo pkill -f mn 2/dev/null sudo ryu-manager --verbose learning_switch.py /tmp/ryu.log 21 sleep 3 sudo mn --custom ~/redundant_topo.py --topo redundant \ --controller remote,ip127.0.0.1,port6633 --mac先清环境再后台启动控制器到日志文件sleep 3等控制器完成初始化最后拉起 Mininet。我当年第一次做类似实验时在控制器对接上卡了整整一晚原因是协议版本没对齐这份避坑记录把最常见的坑列在了前面你按第 2、3、4 章顺序跑通后再补上这份抓包证据报告的数据部分基本就稳了。希望帮到你。本文还有配套的精品资源点击获取
返回列表