
简介这份资源面向计算机、通信工程等专业的在校学生与网络初学者提供一套中小型SDN园区网络构建的完整项目源码与文档说明帮助读者理解并实践SDN控制器的联通、子网划分、NAT外网访问及防火墙、访问控制列表等安全配置。压缩包共24个文件约170KB以conf配置文件、py脚本、sh执行脚本、txt说明文档为主另含少量pyc缓存、jpg拓扑图与md说明覆盖主干网络与分支网络等模块结构清晰便于按需查阅。目前已有153人学习下载可作为课程设计、毕业设计或项目初期立项的参考案例。项目代码均经测试运行成功下载后建议先阅读README.md遇到运行问题还可私聊作者获得远程教学支持适合在现有代码基础上修改扩展实现更多网络功能。1. 从一台 Ubuntu 虚拟机说起这套 SDN 园区网络源码到底能跑出什么很多人第一次接触 SDN卡在的不是 OpenFlow 协议本身而是我到底该拿什么拓扑练手。真实园区网动辄几十台交换机、划分十几个 VLAN实验室里根本摆不下纯看理论又太虚控制器和转发面怎么交互、流表怎么下发脑子里始终是一团浆糊。这套基于 Python 的中小型 SDN 园区网络构建项目解决的正是这个断层——它用 Mininet 在一台 Ubuntu 机器上模拟出分支网络 主干网络的园区结构配合 SDN 控制器完成联通、子网划分、NAT 外网访问和防火墙 ACL 配置源码、配置文件、README 文档一并打包。适合正在做课设、毕设或者想从零把 SDN 数据面和控制面串起来跑一遍的在校学生和初级网络工程师。它不追求运营商级规模但胜在结构完整、能复现、能改。2. 拓扑与选型为什么是 Mininet SDN 控制器这套组合2.1 中小型园区网的拓扑该怎么切园区网络的核心矛盾是分层和冗余要同时成立。这套项目把拓扑拆成两块主干网络负责核心交换和控制器接入分支网络模拟接入层两者之间通过汇聚节点连接。主干部分通常用一台核心交换机在 Mininet 里就是一个 OpenFlow 交换机实例承载控制器下发的全局流表分支部分则按区域挂多台接入交换机每台下面接若干主机。这样切的好处是子网划分有物理落点。比如主干用 10.0.0.0/24分支 A 用 10.0.1.0/24分支 B 用 10.0.2.0/24每个分支交换机就是一个子网的边界。冗余则体现在主干和汇聚之间可以拉两条链路Mininet 支持给同一对交换机建多条 link配合控制器的组表或快速故障转移逻辑就能演示链路断开后的收敛。常见做法是先用--topo参数把结构画出来确认连通性再往控制器里灌业务逻辑。不要一上来就写控制器代码拓扑没跑通后面全是玄学。2.2 为什么选 Mininet 而不是真机或 GNS3Mininet 的本质是用 Linux 的网络命名空间network namespace虚拟出主机和交换机每个虚拟主机有独立的协议栈、独立的网卡交换机的行为由 Open vSwitch 或内置的 OVS 内核模块提供。这意味着你在 Mininet 里敲的ping、iperf、ovs-ofctl命令和真机上几乎一致但资源开销只有真机的零头。对比另外两条路真机搭建成本高、改拓扑要重新插线GNS3 偏传统路由交换对 OpenFlow 的支持不如 Mininet 原生。这套项目选 Mininet本质是选了可编程性——你能用 Python 脚本动态建拓扑、动态下发流表这对 SDN 教学和课设来说是最短路径。提示Mininet 对内核版本有要求Ubuntu 20.04 及以上用 apt 装最省事别去追最新内核容易和 OVS 模块打架。2.3 控制器选型与源码目录结构项目源码目录里能看到SDN-NET-main、code、配置文件、分支网络、主干网络这几个部分。code下是 Python 脚本通常包含拓扑定义文件和控制器应用文件配置文件放的是控制器和交换机的参数分支网络、主干网络则是按区域拆分的拓扑或配置片段。控制器方面这类项目常见的选择是 Ryu 或 POX。Ryu 用 Python 写和项目语言一致支持 OpenFlow 1.3自带 REST API适合做流表下发和拓扑发现POX 更轻但生态老一些。如果 README 里指定了控制器版本以 README 为准不要自己换版本不匹配会导致ofp_event回调收不到包。选型理由很直接Python 控制器 Python 拓扑脚本整个项目是单一语言栈调试时不用在两种语言间来回切对新手最友好。3. 从零跑通环境搭建、拓扑启动与控制器联调3.1 环境准备与依赖安装先确认系统是 Ubuntu 20.04 或 22.04然后按顺序装依赖。Mininet 官方推荐用 apt 安装源码编译容易缺依赖。# 更新源并安装 Mininet 及 Open vSwitch 相关组件 sudo apt update sudo apt install -y mininet openvswitch-switch python3-pip # 安装 Ryu 控制器若项目用 POX则改为下载 POX 源码 pip3 install ryu # 验证 Mininet 版本确认安装成功 mn --version逻辑说明mininet包会自动拉取 OVS 依赖openvswitch-switch是 OVS 的用户态工具控制器和交换机通信要靠它。pip3 install ryu装的是 Ryu 框架如果项目 README 写的是 POX就去 POX 官方仓库拉源码用python3 pox.py启动。参数说明-y表示自动确认避免交互卡住mn --version只输出版本号用来确认命令可用不启动拓扑。装完后跑一次sudo mn --test pingall如果看到Results: 0% dropped说明 Mininet 本身没问题再动项目代码。3.2 启动项目拓扑并接入控制器进入项目code目录先看 README 里给的启动命令。典型流程是分两个终端一个起控制器一个起拓扑。# 终端 1启动 Ryu 控制器指定项目里的控制器应用文件 ryu-manager controller_app.py --verbose # 终端 2启动自定义拓扑连接到远程控制器 sudo python3 topology.py逻辑说明ryu-manager是 Ryu 的启动入口controller_app.py是项目里的控制器逻辑文件实际文件名以源码为准--verbose打开详细日志方便看流表下发和 packet-in 事件。topology.py是拓扑定义脚本里面用addSwitch、addHost、addLink建好结构后通过RemoteController指向控制器的 IP 和端口默认 6653。参数说明如果控制器和 Mininet 在同一台机器RemoteController的 IP 写127.0.0.1端口默认 6653Ryu 老版本可能用 6633以 README 为准。拓扑脚本里如果有net.start()后接CLI(net)启动后会进入 Mininet 命令行可以直接敲pingall。3.3 验证联通性与子网隔离拓扑起来后第一件事是验证同子网能通、跨子网按预期隔离或经路由转发。# 在 Mininet CLI 中执行 mininet pingall mininet h1 ping h2 mininet h1 ping h3 # 查看交换机流表确认控制器已下发规则 mininet sh ovs-ofctl dump-flows s1逻辑说明pingall会遍历所有主机对输出丢包率h1 ping h2验证同分支连通h1 ping h3验证跨分支行为。ovs-ofctl dump-flows s1看交换机 s1 上的流表如果只有默认的 table-miss 流priority0actionCONTROLLER说明控制器还没下发业务流表需要检查控制器日志里有没有报错。参数说明dump-flows后面跟交换机名Mininet 里交换机默认叫 s1、s2如果流表为空先确认控制器和交换机的 OpenFlow 版本一致Ryu 默认 1.3Mininet 默认也是 1.3不一致会握手失败。3.4 NAT 外网访问与防火墙 ACL 配置项目要求里提到 NAT 外网联通和 ACL这两块通常在控制器应用或拓扑脚本里用额外的主机和流表实现。# 在拓扑脚本中增加 NAT 主机和外部网络接口示意以源码为准 # 常见做法是给一台主机配双网卡一张接内网交换机一张接 NAT 网桥 # 然后在控制器里下发流表把内网出口流量导向 NAT 主机逻辑说明Mininet 本身不直接提供 NAT常见做法是用NAT类Mininet 自带或手动建一个 Linux 网桥把内网流量 SNAT 出去。ACL 则是在控制器里根据源/目的 IP、端口匹配匹配到就drop不匹配就走正常转发。参数说明NAT 的出口网卡要能访问外网通常是宿主机的eth0ACL 规则的优先级要高于默认转发流否则会被覆盖。这部分建议先跑通基础联通再加 NAT 和 ACL一次加一个方便定位。4. 避坑与排查那些让拓扑起不来的常见问题4.1 控制器连不上交换机pingall 全丢现象拓扑起来了但pingall100% 丢包dump-flows只有 table-miss。原因控制器和交换机 OpenFlow 版本不匹配或者控制器没监听正确端口。Ryu 默认 6653有些老拓扑脚本写的是 6633。解决在拓扑脚本里确认RemoteController的端口和ryu-manager启动日志里的监听端口对齐如果版本不一致在 Ryu 启动时加--ofp-tcp-listen-port指定端口或在拓扑里指定protocolsOpenFlow13。4.2 重复执行拓扑脚本报 address already in use现象第二次跑topology.py时报端口或网桥已存在。原因上一次 Mininet 没清理干净残留了网桥或命名空间。解决执行sudo mn -c清理这个命令会删掉 Mininet 创建的网桥、命名空间和临时文件。养成每次重跑前先mn -c的习惯能省很多排查时间。4.3 子网间能 ping 通但不符合预期隔离现象本该隔离的两个分支互相能通。原因控制器下发的流表里默认转发规则优先级太高或者子网网关配置让流量绕过了 ACL。解决检查控制器里 ACL 规则的优先级确保高于默认转发同时确认主机的默认网关指向正确的交换机接口别让流量从别的路径溜过去。4.4 NAT 配好后内网仍上不了外网现象内网主机 ping 外网 IP 不通但 NAT 主机自己能通。原因内网主机的默认路由没指向 NAT 主机或者 NAT 的 SNAT 规则没生效。解决在拓扑里给内网主机设默认网关为 NAT 主机内网口 IP在 NAT 主机上确认iptables -t nat -L能看到 SNAT 规则没有就手动加一条或者检查 Mininet 的 NAT 类是否正确初始化。4.5 修改源码后控制器报 import 错误现象改了控制器文件启动时报模块找不到。原因Python 路径没包含项目目录或者文件名和 import 语句不一致。解决在项目根目录下启动ryu-manager或者用PYTHONPATH. ryu-manager ...把当前目录加进路径确认 import 的文件名和实际文件名大小写一致Linux 下大小写敏感。5. 进阶玩法把这份源码改成你自己的课设跑通只是起点这套源码真正的价值在于它的结构足够清晰方便你往上加东西。我一般会从三个方向改换控制器、加拓扑规模、补业务逻辑。换控制器是最容易出成果的。把 Ryu 换成 POX 或 ONOS控制器应用层的代码要重写但拓扑脚本基本不动。换完对比两种控制器的流表下发时延和吞吐就是一个现成的对比实验。加拓扑规模则是把分支从两个扩到四个观察控制器在更多交换机下的收敛表现这时候pingall的丢包率和dump-flows的流表数量就是你的数据。补业务逻辑更有意思。比如在控制器里加一个简单的负载均衡根据目的 IP 的哈希值把流量分到两条冗余链路上。核心代码就是在packet_in回调里算哈希、选端口、下发流表。# 控制器里根据目的 IP 做简单负载均衡的示意逻辑 def packet_in_handler(self, event): msg event.msg dst_ip msg.match.get(ipv4_dst) # 用目的 IP 最后一段做哈希选两条上行链路之一 out_port 1 if (int(str(dst_ip).split(.)[-1]) % 2 0) else 2 # 下发流表匹配该目的 IP 的流量从选定端口出去 self.add_flow(msg, out_port)逻辑说明packet_in是交换机遇到未知流量时上送控制器的事件控制器在这里决定怎么转发。add_flow是自定义的下发流表方法把匹配规则和动作写进交换机。参数说明out_port是交换机上的端口号Mininet 里端口号按addLink的顺序分配具体值要看你拓扑里怎么连的别照抄。验证方法很简单改完后跑iperf看两条链路的带宽是否接近均分如果一条跑满一条闲着说明哈希没生效或者流表没下发成功。这时候回头看控制器日志里的packet_in次数正常应该是两条链路都有流量。从那以后我每次改完控制器逻辑都强制先跑一遍mn -c再起拓扑然后盯着ryu-manager的日志看有没有EventOFPSwitchFeatures握手成功最后才pingall。这个顺序能帮我快速定位是环境问题还是代码问题省掉大量瞎猜的时间。希望帮到你。本文还有配套的精品资源点击获取