### 单线程
NOX[9]是首个实现的SDN控制器,NOX的思想来自于计算机结构。在计算机早期,编程通常是机器语言,没有对底层物理资源进行任何通用抽象,这使得编程很难编写、调试和跟踪定位。现代操作系统通过提供对简单资源抽象(内存、存储和通信)和信息(文件和目录)的控制访问使得编程更容易。这些抽象使得程序能够在兼容不同硬件资源,并以更安全、高效的执行不同任务。而目前的网络就像没有操作系统的计算机,采用依赖于网络的组件配置完成类似于传统机器语言编程的功能。因此,NOX通过抽象网络资源控制接口,设计网络操作系统,提供对整个网络的统一集中的编程接口。
网络操作系统并不直接控制网络,它仅提供对网络的编程接口,运行于其上的应用程序则直接观察控制网络。如图 1-2所示是文献[9]给出的基于NOX的部署结构。NOX运行于单独的PC服务器,其通过OpenFlow交换机接入OpenFlow使能的交换机网络。NOX收集整个网络的网络状态视图,并将其存储在网络视图数据库之中。NOX的网络视图包括交换机网络拓扑,用户、主机、中间件以及其他网络元素,提供的各种服务等。基于NOX接口实现的各种应用程序通过访问网络视图数据库,生成控制命令,并发送到相应OpenFlow交换机中。

<center>图 1-2 基于NOX的网络部署</center>
NOX对上层应用程序提供统一的基于事件的编程接口,将网络各种状态改变提供事件句柄(Event handler),方便上层应用程序调用。一些事件可能直接生成OpenFlow消息,例如,交换机加入网络(Switch join),交换机离开网络(Switch leave),分组接收等。另一些事件则是由NOX应用程序在处理底层事件过程中产生的。另外,NOX提供一组基础应用收集整个网络的网络视图并保持网络命名空间。因为网络视图必须在所有NOX控制实例之间保持一致,因此,当探测到网络变化时,需要更新网络状态数据库。对于大量应用程序均可能需要的更基础的功能,NOX开发了系统库提供高效的共用功能,例如,快速报文分类,路由等。
然而,NOX作为最早的基于OpenFlow的SDN控制器实现,简化了企业网的管理,但是它是单线程设计,不能利用当前高性能的计算平台,例如,多核平台。因此,大量基于多线程的控制器被设计和开发,一部分是改进NOX,如POX[10],NOX-MT[11]等,另一部分则从性能、扩展性等不同角度全新设计实现,如Masterto[12],Beacon[13]。
### 多线程
#### Maestro
在每条流的初始化阶段,SDN网络的控制器需要与其负责的所有相关交换机通信,因此,控制器易成为性能瓶颈。OpenFlow控制器NOX基于事件机制实现了控制功能开发的简化模型,但其是单线程的,未考虑并行特性。Maestro[12]从可扩展性的角度,在保证简单编程接口的同时,设计并开发了多线程控制器。

<center>图 1-3 Maestro控制器结构</center>
如图 1-3所示为Maestro的结构给出了三个执行流程。Maestro通过与每个交换机的TCP连接向交换机网络发送或从其接收OpenFlow消息。那么“Input Stage”和“Output Stage”分别处理底层套接字缓存的读取和写入,并将原始OpenFlow消息转化为高层次数据结构或相反的方向转换。这些底层功能随着OpenFlow协议标准更新。而上层功能则以应用程序的形式不断地更新和重新实现。编程人员可以灵活修改这些应用程序的行为,或添加新的应用程序。图3中的应用程序包括“Discovery”,“IntradomainRouting”,“Authentication”和“RouteFlow”。
交换机加入网络中时会建立与Maestro的TCP连接,“Discovery”应用周期性地发送探测消息,并通过LLDP发现并识别交换机。“Discovery”通过接收来自交换机的对探测报文的回应发现整个网络的拓扑结构。而当拓扑改变时,“Discovery”会调用“IntradomainRouting”应用修改路由表信息。
当Maestro接收到一个流请求时,该请求消息首先通过认证是否违反安全策略。如果符合安全策略,“RouteFlow”应用将为其计算一条最短路径,生成配置输出到目的交换机中,请求报文发送回初始交换机中。
上述三个执行流程并行运行,为实现公共数据结构——路由表的一致性,路由表更新延迟提交。即,当“IntradomainRouting”路由表更新时,若“RouteFlow ”应用已经启动,则“RouteFlow ”仍然使用原来的路由表信息,而当“RouteFlow ”下次启动时访问更新后的路由表信息。
Maestro将应用程序编排为执行流程(execution path),并使用有向无环图(Directed Acyclic Graph, DAG)抽象建模。DAG的节点标识应用程序,DAG的边标识数据流向。执行流程的添加通过配置一个DAG实例,并扩展一个新的线程运行DAG实例。
为了管理不同的任务,Maestro设计了任务管理器提供统一接口管理所有未决的计算。任何具有计算消耗的任务均实现为一个任务,并为每个任务分配一个线程。为了在多线程之间兼顾公平与效率,任务管理器采用“pull”的方式管理工作线程,即,IO缓存队列与线程分离形成缓存池和工作线程池,当某队列不空时,可以随机“pull”空闲线程或轻负载线程处理该队列中的消息。虽然该设计需要维护缓存池的多线程同步的额外开销,但是其实现了更加公平的线程调度和多线程的负载均衡,提高了工作效率。
#### Beacon
与Maestro 类似,Beacon也是基于Java开发的开放源代码控制器。但是,与其主要用于研究和试验不同,Beacon更加注重生产环境的应用。因此,Beacon致力于提高应用程序的开发效率和处理性能。另外,由于Beacon基于OSGi开发,应用程序以“束”(bundle)的形式在系统运行时地被添加或停止。
首先,为了实现代码重用及提供更友好的编程接口,Beacon采用了控制反转容器(Inversion of Control, IoC)框架—Spring。开发过程中只需要创建对象的实例,并将一个对象作为另一对象的属性分配以实现彼此的关联。IoC框架允许开发人员采用XML配置文件或Java注解的方式创建对象和关联多个对象,降低了开发人员的开发时间。另外,Spring的Web框架在Web和REST请求之间映射,简化方法调用,执行请求和响应的数据类型与Java对象之间的自动转化。
Beacon提供基于事件的API接口,任何应用程序均可以注册监听器接收各种事件。应用程序可以调用IBeaconProvider实现与OpenFlow交换机之间交互。监听器可以注册当交换机添加或删除时被通告(IOFSwitchListener),或执行交换机初始化(IOFInitializerListener),以及接收特定OpenFlow消息类型(IOFMessageListener)。另外,Beacon还包括实现了OpenFlow 1.0标准协议的OpenFlowJ库,用于管理设备的设备管理接口(IDeviceManager)处理设备相关的事件,用户探测交换机网络的接口(ITopology)处理拓扑变化事件(例如,链路消失),提供最短路服务的接口(IRoutingEngine)等。
其次,与现有控制器实现的另一不同点是Beacon可以在运行时启动新的应用程序,停止正在运行的应用程序。为了实现运行时启动或停止应用程序,Beacon采用OSGi规范实现框架—Equinox。OSGi定义了“束”,即JAR文件,标识了ID,与其它束之间的依赖关系以及规定向外部提供的可供外部使用的程序包。开发人员可以定制上述内容。
Beacon利用了OSGi规范中服务注册的组件实现服务提供者与服务消费者之间的联系。如图 1-4所示,服务提供者输出服务接口,服务消费者请求并接收满足服务需求的实例。任何服务实例均可随着其它服务的运行或停止而动态变化。

图 1-4 Beacon服务注册 </center>
最后,在性能方面,如图 5所示Beacon采用多线程机制,应用程序通过注册监听特定消息类型的OpenFlow消息,如PacketIn消息,对于监听相同消息类型的应用程序形成处理流水线(pipeline)。消息被解析后依次经过流水线上的应用程序处理。Beacon采用“Run-to-completion”模式读取消息,具体如图 5所示。Beacon可以配置线程池大小,对交换机的连接请求通过轮训的方式选择线程,每个交换机固定一个线程处理,因此该设计无需同步锁。Beacon采用批量模式读取消息,以减少用户态程序访问套接字的次数,提高性能。与其它开源集中式控制器相比,实验证明Beacon在吞吐量,处理延迟以及多线程扩展性方面最优。

图 5 Beacon 多线程示例
#### 基于Beacon的扩展
Floodlight[14]是基于Beacon内核开发的另一款由开源社区维护的控制器。另外,Volkan Yazıcı等[15]将Beacon扩展为分布式控制器应用于组播网络中。FlowScale[16]则部分采用了Beacon模块。由于这些控制器都起源于Beacon,所以其实现细节不再综述。
另外,其它较著名的多线程控制器还有Ryu[17],Trema[18],Mul[19],SNAC[20],RouteFlow[21]等,这里不再一一描述它们的结构和功能。
- 目录
- 前言
- 第一部分 SDN基础
- 第一章 SDN控制器综述
- 1 引言
- 2 控制器架构
- 2.1 集中式控制器
- 2.2 分布式控制器
- 2.3 北向接口编程语言
- 2.4 SDN功能组合
- 2.5 策略更新一致性
- 参考文献
- 第二章 OpenFlow学习指南
- 1 概述
- 2 环境配置
- 2.1 相关软件
- 3 虚拟机设置
- 3.1 导入虚拟机镜像
- 3.2 网络访问
- 4 开发工具手册
- 4.1 Hello world网络
- 4.2 Mininet简介
- 4.3 其它工具
- 4.4 初识控制器
- 5 控制器介绍:以创建学习型交换机为例
- 5.1 POX控制器
- 参考文献
- 第三章 Karaf使用手册
- 1 Apache Karaf
- 2 安装Apache Karaf
- 2.1 依赖条件
- 2.2 获得Apache Karaf发布包
- 2.3 安装Apache Karaf
- 2.4 首次启动
- 2.5 总结
- 3 命令行操作
- 3.1 常用命令
- 3.2 远程控制台访问
- 3.3 自定义命令
- 3.4 可选的web控制台
- 3.5 总结
- 4 仓库
- 4.1 Apache Maven库
- 4.2 Karaf系统库
- 第二部分 ONOS体系架构
- 第一章 ONOS体系概述
- 1.1 设计目标
- 1.2 剩余章节
- 第二章 系统组件
- 2.1 系统层级(system ties)
- 2.2 服务和子系统
- 2.3 子系统结构
- 2.4 事件和描述
- 第三章 构建网络状态
- 3.1 ONOS表示网络
- 3.2 网络发现
- 3.3 网络配置子系统
- 第四章 设备子对象
- 4.1 概述
- 4.2 模型对象和提供者表达
- 4.3 OpenFlow子系统
- 4.4 交换机状态
- 第五章 设备驱动子系统
- 5.1 定义
- 5.2 交付机制
- 5.3 查询机制
- 5.4 模型
- 5.5 上下文
- 第六章 分布式操作
- 6.1 集群协同
- 6.2 网络拓扑状态
- 第七章 意图框架(intent framework)
- 7.1 概述
- 7.2 意图
- 7.3 意图汇编
- 第八章 Web UI架构
- 8.1 概述
- 8.2 客户端架构
- 8.3 服务端架构
- 8.4 处理流程
- 第九章 核心UI扩展体系
- 9.1 拓扑视图架构
- 9.2 关于链路
- 第十章 联盟ONOS web UI
- 第十一章 GUI源代码目录结构
- 第十二章 组件配置
- 12.1 概述
- 12.2 组件代码示例
- 12.3 Maven例子
- 12.4 CLI命令
- 第十三章 应用程序子系统
- 13.1 概述
- 13.2 应用程序包
- 13.3 CLI命令
- 13.4 REST API和shell工具
- 13.5 Maven例子
- 13.6 内建范例和测试应用程序
- 第十四章 分布式原语
- 第十五章 标签(Label)子系统
- 15.1 概述
- 15.2 ONOS应用程序编程接口
- 15.3 使用CLI命令管理标签
- 第十六章 隧道(tunnel)子系统
- 16.1 概述
- 16.2 ONOS应用程序使用的可编程APIs
- 16.3 使用CLI命令管理隧道
- 第十七章 北向接口扩展
- 17.1 概述
- 17.2 驱动器行为
- 17.3 Treatment扩展
- 17.4 selector扩展
- 17.5 应用程序使用范例
- 第三部分 ONOS用户手册(未完,待续)
- 1 获得ONOS
- 2 ONOS源码安装
- 2.1 系统要求
- 2.2 安装JAVA,Maven and Karaf
- 2.3 使用onos测试工具远程部署onos
- 3 ONOS可执行程序安装和配置
- 3.1 运行要求
- 3.2 单机安装ONOS
- 3.3 将ONOS作为系统服务
- 3.4 通过CLI和GUI访问ONOS
- 3.5 组合一个集群
- 4 配置ONOS
- 4.1 管理ONOS应用程序
- 5 ONOS交互接口
- 6 附录A-CLI命令大全
- 7 附录B-REST APIs大全
- 第四部分 ONOS开发指南(未完,待续)
- 开发者快速入门(...)
- 开发ONOS应用程序
- 导入ONOS源码到IDEA
- 开发前配置
- 基于Maven原型生成ONOS应用工程
- 1.3.1 生成应用模板
- 1.3.2 导入APP
- 1.3.3 app添加CLI支持
- 1.3.4 app添加GUI支持
- 第五部分 OpenVirteX架构
- 第一章 OpenVirteX概述
- 1.1 网络虚拟化
- 1.2 OpenVirteX架构
- 第二章 OpenVirteX组件简介
- 2.1 概述
- 2.1.1 实现类
- 2.2 组件状态机
- 2.2.1 基本FSM状态
- 2.2.2 组件FSM的接口
- 2.3 组件的持久化
- 2.4 交换机[net.onrc.openvirtex.elements.datapath]
- 2.5 Ports[package net.onrc.openvirtex.elements.port]
- 2.6 Links和Routes[package net.onrc.openvirtex.elements.link/net.onrc.openvirtex.routing]
- 2.7 Addresses[package net.onrc.openvirtex.elements.address]
- 2.8 Hosts[package net.onrc.openvirtex.elements.host]
- 2.9 Networks[package net.onrc.openvirtex.elements.network]
- 2.10 共享的全局映射[package net.onrc.openvirtex.elements]和 ovxPortMap
- 2.11 消息[package net.onrc.openvirtex.messages]
- 第三章 操作和子系统
- 3.1 系统概述
- 3.2 启动和关闭
- 3.3 事件循环
- OpenVirteX API
- 使用指南
- 第六部分 实验设置