简介:面向SDN初学者及网络实验者的《Ubuntu 20.0.4环境下安装OpenDaylight详解》DOCX文档,紧扣OpenFlow协议学习与控制器部署主题,以完整实验流程为主线,从实验背景与目的出发,分步讲解JDK 8安装与JAVA_HOME环境变量配置、Apache Maven构建工具的源添加与GPG密钥验证、OpenDaylight压缩包解压及mvn clean install构建、Karaf控制台启动,以及REST API、L2 Switch和OpenFlow插件安装命令。文档同时说明如何用Mininet生成拓扑并与OpenDaylight连接,通过ping操作和Wireshark抓包验证OpenFlow 1.3协议版本与交互过程,并明确实验任务涵盖回顾JDK配置、创建拓扑、抓包分析,帮助读者深入理解SDN控制平面和数据平面的工作方式。资源共1个DOCX文件,包体大小约1.25MB,内容以操作步骤、命令代码与配置说明为主,结构清晰、可对照执行。已有1338人学习,适合需要从零搭建SDN实验环境并理解OpenFlow机制的研究者参考,也可作为网络工程相关课程的辅助材料。
1. 从网络虚拟化到控制器:OpenDaylight 在 SDN 实验中的定位
SDN 的核心理念是把网络设备的控制平面抽离出来,交给一个集中式控制器统一管理。OpenDaylight 是这类控制器里最典型的开源实现之一,它基于 Java 运行,通过南向接口协议与交换机通信,而 OpenFlow 就是其中最常用的南向协议。在 Ubuntu 20.04 上完整走一遍 JDK、Maven、OpenDaylight 和 Mininet 的对接链路,能同时看清控制平面和数据平面的交互机制。
对于刚接触 SDN 的工程师来说,最容易踩的坑不是 OpenDaylight 本身,而是环境版本不匹配:JDK 版本过高导致 OpenDaylight 启动即报错,Maven 仓库源失效导致组件安装失败,Mininet 的 OpenFlow 协议版本与控制器配置不一致导致 Wireshark 抓不到预期的包。这篇内容从 JDK 安装讲起,直到用控制器下发流表、验证 OpenFlow 1.3 协议消息,过程中会穿插版本选型理由和排错思路。
2. 安装 JDK 与 Maven:版本匹配是 OpenDaylight 能启动的前提
OpenDaylight 控制器本质是一个运行在 Karaf 容器中的 Java 应用。它的核心模块、REST API 服务和 OpenFlow 插件都依赖 Java 运行时环境。版本选型上,OpenDaylight 官方长期使用 JDK 8 作为基准环境,因为高版本 JDK 在模块化、内存管理和字节码层面引入了大量变更,老的 Java 库可能因反射访问受限或垃圾回收器变化而抛异常。当前最新的 OpenDaylight 版本虽然部分支持 JDK 11,但用 JDK 8 搭建实验环境是最稳妥的选择。
2.1 安装 JDK 8 与环境变量配置
在 Ubuntu 20.04 上安装 JDK 8 之前,先确认系统软件源可用,然后通过 apt 直接安装 OpenJDK 8。具体命令如下:
sudo apt update sudo apt install -y openjdk-8-jdk安装完成后,需要显式配置JAVA_HOME环境变量,因为部分构建工具(包括 Maven 和 OpenDaylight 的启动脚本)会直接读取这个变量来定位 Java 安装路径。执行以下命令:
echo "export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64" >> ~/.bashrc echo "export JRE_HOME=${JAVA_HOME}/jre" >> ~/.bashrc echo "export PATH=${JAVA_HOME}/bin:$PATH" >> ~/.bashrc source ~/.bashrc配置后可以通过echo $JAVA_HOME确认路径值是否正确。如果系统里同时存在多个 JDK 版本,需要使用sudo update-alternatives --config java将默认 Java 版本切换为 JDK 8,否则java -version可能仍指向其他版本的运行时。
验证 JDK 是否安装成功的标准操作是查看版本信息:
java -version javac -version正常输出会显示openjdk version "1.8.0_xxx",其中 1.8 即对应 JDK 8。确认这两条命令输出正常后,Java 环境部分就完成了。
2.2 Maven 安装与本地仓库初始化
Maven 是 OpenDaylight 构建过程中不可或缺的工具。OpenDaylight 的组件以 Maven 构件(artifact)的形式组织,通过features:install安装插件时,Karaf 会调用底层 Maven 机制去解析依赖。如果系统里没有 Maven,OpenDaylight 的 feature 安装命令会直接失败并提示找不到org.opendaylight.controller相关构件。
Ubuntu 20.04 的官方软件源中自带的 Maven 版本是 3.6.3,这个版本构建 OpenDaylight 没有问题,直接通过 apt 安装即可:
sudo apt install -y maven安装完成后运行mvn -v看到以下信息即表示安装成功:
Apache Maven 3.6.3 Maven home: /usr/share/maven Java version: 1.8.0_xxx注意Java version这一行必须显示 1.8。如果这里显示的是 11 或 17,说明JAVA_HOME配置没有生效,需要回溯上一步检查~/.bashrc中的路径是否与实际 JDK 安装位置一致。可以用ls /usr/lib/jvm/查看系统实际安装的 JDK 目录名。
这里有必要说明一个常见的误解:mvn clean install -DskipTests编译源码时 Maven 会联网下载大量依赖包到~/.m2/repository目录,首次执行需要几分钟甚至更久,这不代表构建卡死。如果网络较差,建议先用mvn -v确认 Maven 本身可用,再执行后续操作。
3. OpenDaylight 下载与 Karaf 启动流程
OpenDaylight 的发行版是一个带 Karaf 容器的压缩包。Karaf 是 OSGi 容器的实现,OpenDaylight 将控制器功能拆分成一个个 bundle,由 Karaf 统一管理生命周期。下载时要注意选择与 OpenDaylight 版本对应的发行包,不同系列的包名和目录结构有差异,但核心启动方式是一致的。
3.1 下载与解压
从 OpenDaylight 官网下载发行版压缩包后,将其解压到用户目录或桌面。这里以常见的distribution-karaf类型包为例,假设解压后的目录名为opendaylight:
cd ~ tar -zxvf distribution-karaf-xxx.tar.gz mv distribution-karaf-xxx opendaylight cd opendaylight解压完成后,目录内会看到bin、etc、data等子目录。其中bin目录存放启动脚本,etc目录存放 Karaf 和 OpenDaylight 的配置文件,data目录存放运行时产生的日志、缓存和数据库文件。
启动 OpenDaylight 前,建议先查看etc/default.properties或etc/org.apache.karaf.features.cfg中配置的默认 feature 列表,确认哪些组件会在启动时自动加载。默认包通常已经预置了odl-restconf等基础 RPC 服务,这部分信息后面排错时需要用到。
3.2 启动 Karaf 并检查控制台输出
OpenDaylight 启动脚本是一个 bash 脚本,它会读取JAVA_HOME环境变量并使用java命令启动 Karaf 进程。首次启动时,Karaf 会执行历史数据清理和 bundle 初始化,速度取决于机器性能和磁盘 I/O。执行以下命令进入交互式控制台:
./bin/karaf启动过程会滚动输出日志信息,当出现Karaf started或看到opendaylight-user@root>提示符时,表示控制器已经正常运行。如果想在后台启动而不占用当前终端,可以执行./bin/karaf server,日志会写入data/log/karaf.log文件。
进入 Karaf 控制台后,可以输入feature:list | grep odl查看已安装的 OpenDaylight 相关 feature。此时输出列表中的odl-openflowplugin-flow-services等条目显示的[Uninstalled]状态是正常的,因为默认发行版没有预装 OpenFlow 服务,需要手动安装,这部分在下一章展开。
3.3 转发端口与日志定位
OpenDaylight 启动后默认监听 6633 端口作为 OpenFlow 南向端口,同时监听 8181 端口提供 REST API 服务。可以使用netstat -tlnp | grep -E "6633|8181"验证端口状态。如果 8181 端口没有监听,检查etc/jetty.xml中的配置,确认 Jetty HTTP 服务器是否正常加载。
<注意> 端口长时间未被监听时,优先查看data/log/karaf.log中是否出现BindException或Address already in use。这类错误通常是之前残留的 Karaf 进程没有完全退出导致的,用ps -ef | grep karaf找到进程并kill -9后再重新启动。
4. 安装 OpenFlow 插件并打通 Mininet 拓扑
OpenDaylight 要管理 OpenFlow 交换机,必须安装南向协议插件。OpenDaylight 的组件体系里,odl-openflowplugin是处理 OpenFlow 协议解析和消息收发的核心 bundle,odl-l2switch则是基于 OpenFlow 实现 L2 转发功能的模块。两者配合使用,才能让 Mininet 创建的虚拟交换机连接到控制器并正常转发数据包。
4.1 REST API 与 OpenFlow 组件安装
在 Karaf 控制台中依次执行以下命令,安装 REST API 支持组件:
feature:install odl-restconf然后安装 L2 Switch 和 OpenFlow 插件:
feature:install odl-l2switch-switch feature:install odl-openflowplugin-ofagent安装过程会从 Maven 仓库拉取依赖 bundle,输出大量下载日志。如果网络不稳定,推荐先执行feature:repo-add mvn:org.opendaylight.controller/features-rest/1.3.0-SNAPSHOT/xml/features添加功能仓库,再从仓库中安装对应版本。注意此处使用 1.3.0-SNAPSHOT 版本号是与 OpenDaylight 控制器版本匹配的,不同发行版的 feature 版本号需要对应调整,否则feature:install会因找不到构件而报错。
安装完成后用feature:list | grep openflow检查状态,看到odl-openflowplugin-flow-services和odl-openflowplugin-ofagent的状态为[Started]即表示安装成功。之后在控制器中就能通过 REST API 查询到连接上来的交换机信息。
4.2 Mininet 创建拓扑并指定远端控制器
Mininet 是网络仿真工具,它用 Linux Network Namespace 模拟交换机端口和主机。指定--controller=remote参数能让 Mininet 启动的交换机主动向 OpenDaylight 发起 TCP 连接。执行以下命令创建一台交换机与两台主机组成的拓扑:
sudo mn --topo=single,3 --mac --switch=ovsk,protocols=OpenFlow13 --controller=remote,ip=127.0.0.1,port=6633这里--switch=ovsk,protocols=OpenFlow13指定使用 Open vSwitch 并启用 OpenFlow 1.3 协议,--controller=remote将控制器的 IP 和端口指向本机的 OpenDaylight。
启动后,在 OpenDaylight 控制台执行log:display | grep OPENFLOW,能看到 OpenFlow 交换机连接握手成功的日志记录。此时在 Mininet 内执行pingall,检查主机间连通性:
pingall如果所有主机之间都能 ping 通,说明 OpenDaylight 已经通过 OpenFlow 协议下发流表,交换机在控制器协助下完成了转发。
4.3 通过 REST API 验证流表下发情况
OpenDaylight 的 REST API 可以用来查看交换机上报的端口信息和已下发的流表。在浏览器或命令行中执行以下 curl 请求:
curl -u admin:admin -H "Accept: application/json" http://localhost:8181/restconf/operational/opendaylight-inventory:nodes返回的 JSON 数据中会包含节点的 ID、连接状态以及flow-node-inventory:table信息。其中opendaylight-inventory:nodes是 OpenDaylight 定义的 YANG 模型路径,admin:admin是 Karaf 默认的 REST 认证凭据。如果没有返回节点数据,说明 Mininet 的交换机尚未成功连接控制器,需要回头检查 6633 端口的监听状态。
5. 抓包分析 OpenFlow 1.3 协议消息与排错要点
OpenFlow 协议的验证不能只停留在拓扑能 ping 通这个层面,抓包才能确认控制器和交换机之间真实交换了哪些协议消息。Wireshark 是分析链路层协议的首选工具,在 Mininet 环境里,交换机与控制器之间的通信流量会经过本机的回环接口,抓包时要注意过滤条件和协议解析。
5.1 抓取 OpenFlow 消息并确认协议版本
启动 Wireshark 并选择回环接口lo,在过滤栏输入以下表达式:
tcp.port == 6633这个过滤条件会截获 Mininet 交换机与 OpenDaylight 之间的所有 TCP 流量。OpenFlow 协议运行在 TCP 之上,只要端口匹配,Wireshark 就会自动识别并解析数据包中的应用层协议为OpenFlow。
抓包后观察数据包列表,重点看以下几种消息类型:
OFPT_HELLO:连接建立后双方交换的第一条消息,其头部版本字段会标明各自支持的 OpenFlow 最高版本,数值0x04即 OpenFlow 1.3OFPT_FEATURES_REQUEST / REPLY:控制器发送特性请求,交换机回复自己的 DPID、端口数量和缓冲区大小OFPT_PACKET_IN:交换机收到未知目标 MAC 地址的数据包时,封装后上送给控制器决策OFPT_FLOW_MOD:控制器下发流表的命令消息,包含匹配规则和动作指令
如果在抓包结果中能看到OFPT_HELLO且版本字段为0x04,就能确认 OpenFlow 1.3 协议已经协商成功。执行pingall之后,过滤器的输出中会出现大量OFPT_PACKET_IN和OFPT_FLOW_MOD消息,这对应控制器先收到交换机无法处理的数据包,随后计算转发路径并返回流表的完整交互过程。
5.2 从 OpenFlow 消息中读取关键信息
双击一条OFPT_PACKET_IN消息,在 Wireshark 的下方协议树中展开OpenFlow Protocol层级。重点查看以下字段:
| 字段名 | 含义 | 排查价值 |
|---|---|---|
| Version | 协议版本号,1.3 对应 0x04 | 版本不匹配时此字段会显示为 0x01 或 0x02 |
| Xid | 事务 ID,匹配请求和响应 | Xid 不对称说明控制器与交换机间存在状态不一致 |
| Match | 匹配字段,如 in_port、eth_dst | 确认 PacketIn 是否携带了正确的入端口和数据帧信息 |
| Length | 消息总长度 | 数据包被截断或长度异常说明链路传输有问题 |
Wireshark解析 OpenFlow 协议依赖内置的解析器,如果过滤结果显示为Data而不是OpenFlow,多数情况下是因为 Controller 端口配置错误导致抓到了非 OpenFlow 协议的 TCP 连接。可以用tcp.port == 6633 && tcp.flags.syn == 1检查是否存在 TCP 三次握手,如果没有任何 TCP SYN 包,说明 Mininet 根本没有连接到 OpenDaylight。
5.3 高频故障排查清单
OpenFlow 连接建立失败是出现频率最高的问题,以下是几个绕过绕远路的排查步骤:
第一,确认 IP 和端口匹配。Mininet 的remote控制器参数必须与 OpenDaylight 监听地址一致。默认 OpenDaylight 绑定所有网口,但如果修改过etc/jetty.xml或 OpenFlow 监听配置,需要检查实际监听地址是否与--controller参数相同。
第二,检查防火墙和系统服务。Ubuntu 默认没有启用 ufw 的话无需额外操作,但如果之前配置过 iptables 规则,需要放行 6633 和 8181 端口。
第三,清理 Karaf 缓存。OpenDaylight 卸载或重装插件后,data目录下可能会残留旧版 bundle 的缓存。执行rm -rf data/cache data/tmp data/journal后重启 Karaf,可以消除大部分 bundle 加载异常。
5.4 让拓扑验证更接近真实场景
实际网络中的 OpenFlow 交换机远比 Mininet 仿真更复杂。如果想验证多级流表和组表行为,可以把 Mininet 拓扑升级为多交换机级联,再通过 OpenDaylight 的 REST API 向指定 DPID 的设备下发自定义流表项。用一个简单的 curl 请求下发丢弃特定 IP 流量的规则:
curl -u admin:admin -H "Content-Type: application/json" \ -d '{"flow": [{"id": "1", "match": {"ipv4-destination": "10.0.0.2/32"}, "instructions": {"instruction": [{"order": "0", "apply-actions": {"action": [{"order": "0", "drop-action": {}}]}}]}, "priority": "10", "table_id": 0}]}' \ http://localhost:8181/restconf/config/opendaylight-inventory:nodes/node/openflow:1/table/0/flow/1该请求会在openflow:1交换机(即 Mininet 中第一台交换机)的table 0上创建一条丢弃目标 IP 为10.0.0.2的流量规则。配置下发后,在 Mininet 中执行ping 10.0.0.2会观察不到回包,而 Wireshark 中能捕获到交换机上报的OFPT_PACKET_IN消息带着eth_dst=10.0.0.2的数据帧。这个操作把控制器的北向接口、南向协议和交换机流表串在一起,验证链路是完整的。
最后提一个容易被忽略的验证技巧:在 OpenDaylight 的 Karaf 控制台执行log:tail,会实时滚动输出所有模块的日志。当你在 Wireshark 中看到一条OFPT_FLOW_MOD消息,但 Mininet 内的 ping 依然不通时,先看log:tail的输出里有没有L2 switch或TableMiss相关的 WARN 日志,这会直接暴露流表查询失败的环节,建议实验时同时开着 Wireshark、Karaf 控制台和 Mininet 三个终端窗口,对比排查效率会高很多。
本文还有配套的精品资源,点击获取