OpenVirteX学习笔记(二)

前言

继上篇《OpenVirteX体系架构学习笔记(一)》之后,本篇将继续介绍OVX的第三部分:Operation and Subsystems。主要讲述OVX内部的运作原理,本文属于个人简介,有误之处敬请指出,希望对读者有所帮助。本篇的顺序依然是按照官网文档的顺序介绍。

简介

本部分将介绍OVX内部的工作原理,如哪些内部子系统实现了哪一些功能,从而使得OVX能支持OpenFlow网络的虚拟化。以下的内容将分为如下的小点介绍:

  • System Overview
  • Startup and Shutdown
  • The Event Loops
  • Network Discovery and Presentation
  • Virtualization and De-virtualization
  • State Synchronization
  • Reslience
  • persistence
  • The JSONRPC API

3.1 System Overveiw

OVX分为以下几个主要的部分:

  • 一半是面向南向物理基础设施的部分,管理了datapath到OVX之间的OpenFlow通道,并建立和维持了一系列数据结构,用于描述物理基础网络。
  • 另一半是面向北向租户控制器的部分,向租户控制器提供由OVXSwicth等组成的虚拟网络,并维护好OVX到各个租户控制器的OpenFlow通道。
  • Global maps则保存了物理设施到OVXNetwork的component之间的映射关系,完成PhysicalNetwork到OVXNetwork之间的桥接路由(其实就是映射)。
  • JSON的API用于配置和获取系统的信息。

Global mapping是在OVXNetwork被创建的时候完成的,两段channel的管理也在不同的IO Loop中完成配置,使得从datapath到tenant controller的两段OpenFlow channel 能够正确对接成一条完整的controller channel。每一个需要被路由到OVXNetwork,或者需要横跨南北两部分的数据包都要在loop中调用virtualize()或者devirtualize()函数以完成消息的转换。由于global map的存在,使得底层物理网络和租户的虚拟网络之间的状态可以解耦,从而使得OVXNetwork可以在运行状态下动态地改变网络,也让OVX可以在没有任何租户网络的情况下控制底层网络。

3.2 Startup and Shutdown

这部分将要介绍的是OVX启动和关闭时OVX内部的程序运作流程。分为以下4个小节:

  • Main process startup
  • PhysicalNetwork / Southbound channel initialization
  • Tenant Network (OVXNetwork) / Northbound channel initialization
  • System shutdown

3.2.1 Main process startup

OVX的入口方法在OpenVirteX.java[package net.onrc.openvirtex.core]文件,通过解析命令行的输入参数来启动OpenVirteXController,OpenVirteXController完成了OVX核心的启动,也完成了环境变量,OVX参数等系统配置和初始化。

启动的内容包括:

  • 初始化单一的PhysicalNetwork实例,用于描述底层物理网络。
  • 尝试连接数据库,恢复数据库中先前存在虚网。
  • 启动API服务,接受API调用。
  • 初始化南向的通道处理函数,监听网络事件。

第三步的时候,OVX监听API调用,第四步时,监听来自datapaths的连接。

3.2.2 PhysicalNetwork population / Southbound channel initialization

交换机连接到OVX以及链路发现的数据都记录到了PhysicalNetwork中。OVX为每一个交换机创建了一个PhysicalSwitch和SwitchDiscoveryManger的对象,用户描述交换机。此时OVX对于交换机而言,就是一个控制器。以下的图形象地描述了OVX在处理datapath连接时的状态变化。

Fig.1 OVX的南向与datapath握手的状态机示意图

Fig.1 OVX的南向与datapath握手的状态机示意图

如果对这个经典的OpenFlow协议的状态机不熟悉,可以参考《OpenFlow通信流程解读》

SwitchChannelHandler [net.onrc.openvirtex.core.io]将这个状态机设置成枚举类型的ChannelState,每一个状态都有对应的方法去处理当前状态下的事件和消息。

当datapath达到WAIT_DESCRIPTION_STAT_REPLY之后,OVX才能将datapath映射成一个PhysicalSwitch。利用datapath提供的信息,OVX可以对datapath对应的PhysicaiSwitch进行配置,并将其加入到PhysicalNetwork中。当SwitchDiscoveryManager找到datapath的PhysicalNetwork,并且PhysicalSwitch的statisticsManager开启之后,datapath进入ACTIVE状态。当datapath进入ACTIVE状态时,datapath将参与到网络发现和OVX的事件循环当中,此时的datapath是一个正常运行状态的交换网桥。

3.2.3 Tenant network (OVXNetwork) / Northbound channel initialization

一个租户的网络的创建、配置和初始化都通过API的调用,其中步骤包括:

  • Declare an OVXNetwork, the Address block used, and tenant controller(s) to
  • connect the OVXNetwork to
  • Create OVXSwitches from available PhysicalSwitches
  • Add OVXPorts to the OVXSwitches
  • Add OVXLinks, Hosts, and for BVSes, SwitchRoutes
  • If manual, specify paths for OVXLinks and SwitchRoutes
  • Optionally, add backup paths for OVXLinks and SwitchRoutes
  • Initialize the OVXNetwork

以上的步骤完成之后,OVX需要将其components初始化,并将virtual components映射到PhysicalNetwork components,并记录在global map中。然后将虚拟的components状态置为ACTIVE,在这种非常具有强制依赖性的顺序之下,最终完成OVXNetwork的初始化。具体的API都写在了API server [net.onrc.openvirtex.api.server]中,他们在tenant handlers [api.server.handlers.tenant]中被调用。具体的接口函数此处不加赘述,读者可到官网查看,也可以直接查看源码。下图描述了OVX中tenant Network的创建过程:

VnetInit

每一个Component都包含有register()和boot()的接口函数用于注册和初始化component。容易意识到的一点是,这些Component的启动肯定是有顺序的,或者说他们之间的以来关系肯定是固定的。如端口必然以来于交换机,没有交换机类,就不会有端口类。下图介绍了Components之间的包含和映射关系。其中实线为包含关系,虚线为映射关系。

dependencies

ControllerChannelHandler [net.onrc.openvirtex.core.io] 负责OVXSwitch实例到tenant controller的连接,并维持一个状态机如下图所示。当且仅当一个OVXNetwork完成了所有OVXSwitch和控制器的连接时,才能进入ACTIVE状态。此时的OVX对于tenant Controller而言是一个datapath。

ServerFSM

OpenVirtexShutdownHook [net.onrc.openvirtex.core.io]调用 OpenVirteXController.terminate()方法完成系统的关闭。这个方法关闭了面向租户和面向datapath两端的channel,也注销了PhysicalNetwork。

3.3 The Event Loops

这部分将介绍OVX的I/O loop。

3.3.1 Overview

OVX event loop主要用于处理OpenFlow messages。主要完成如下三个功能:

  • 负责OVX与datapath、OVX和tenant controller的OpenFlow协议通信。
  • 完成OpenFlow messages的virtualize()和devirtualize():主要是将来自datapath的OpenFlow消息重写,路由到对应的租户控制器以及反向的消息转换。
  • 保持OVX和datapath、OVX和tenant controller的连接。

3.3.2 Message handling and (de)virtualization

OVXMessages部署了以下的两个接口中任意一个或者全部:

Virtualizable: virtualize(PhysicalSwitch sw) : controller-bound messages

Devirtualizable : devirtualize(OVXSwitch sw) : network-bound messages

这两个接口函数的参数都是switch类的子类。对于那些没有必要跨越virtual-physical gap的消息,就没有这些方法,如keep alive的消息(echo-request and echo-reply)。而那些需要从datapath一直交付到tenan controller的消息就必须要这写方法了,如flow_mod。

这些方法在handleIO()调用。handleIO()是PhysicalSwitch和OVXSwitch类中abstract method。

当交换机处于ACTIVE状态时,才会被调用。

PhysicalPhysicalSwitch.Switchstate.ACTIVE满足时,handleIO允许被调用。函数代码如下:

OVXSwitch.Switchstate.ACTIVE满足时,函数代码如下:

其整个event loop(事件循环)示意图如下:

event loop(事件循环)示意图

从上图中我们可以看到一些细节部分,比如来自租户的LLDP数据包是不会发送到datapath的。直接在OVX查询topology的数据结构就可以模拟出LLDP的效果了。同样OVX不断的在发送LLDP数据包,而packet_in数据类型为LLDP时,不会交给租户的控制器,而是由OVX的拓扑发现模块去处理,事实上,OVX就是一个控制器!只不过,它比控制器多出来虚拟化的功能,从而将网络的管理权,交给了各个租户的控制器而已。蓝色部分是面向租户的,橙色部分是面向datapath的,而中间的淡绿色部分是global部分。通过调用virtualize()和devirtualize()函数和使用global map数据完成消息的转换。

3.4 Network Discovery and Presentation

为了保证虚拟化的准确性,OVX必须保证获取到实时的网络试图,这就需要做以下的事情:

  • 探测拓扑和流表的变化
  • 将拓扑变化对应地修改到PhysicalNetwork和PhysicalSwitch数据结构中。
  • 检测拓扑变化是否对租户的虚网有影响,有则更新租户虚网拓扑信息。

这一部分需要注意的一个重点是,OVX对网络拓扑,特别是对虚网拓扑的处理。按常规思路,直接下发转发tenan controller的LLDP数据包,和上传LLDP的packet_in是最简单的。但是代价就是会增加OVX的IO压力,给网络增加过多的流量。优化方法就是由OVX代理获取物理拓扑,而对于租户的拓扑探测请求则直接通过查询OVX的拓扑信息返回,这样就可以使得来自租户控制器的大量LLDP数据包在OVX上就得到回复,从而模拟了拓扑发现过程。

3.4.1 Topology discovery/LLDP handling

Physical LLDP handling

每一个PhysicalNetwork的SwitchDiscoveryManager负责处理LLDP消息。其处理流程如下图:

处理LLDP消息

根据每一个端口的探测计数器结果(默认为3),可以将端口分为fast和slow端口。其中fast端口为内部端口,即端口对端也是一个交换机端口,能回复LLDP数据包。否则就是slow端口,理论上slow端口为连接主机的端口。每一次发送一个探测包,探测计数器就加1,收到回复则减1,当计数器大于3时,可将端口定义为slow port,这些数据都存储在Map portProbeCount。

3.4.2 PhysicalSwitch Statistics Collection

在OVX中统计信息存储在如下的数据结构中:

OVX通过StatisticsManager[net.onrc.openvirtex.elements.datapath.statistics]来获取统计信息。

Physical flow table synchronization

OVX通过周期地发送statisticsRequest来收集网络的统计信息,并存储在PhysicalSwitch.flowStats之中。具体的实现可以查看StatisticsManager[net.onrc.openvirtex.elements.datapath.statistics]等模块。

3.4.3 OVXNetwork Presentation

Virtual topology presentationOVX通过查找OVX拓扑数据,来回复租户的拓扑发现请求,从而显著减少了LLDP消息在物理网络中的传播。其中步骤为:

  • 查找neighborPortMap表中destination port的数据
  • 将结果封装成LLDP报文的packet_in并发送给租户控制器。

下图介绍了这个处理流程。

topology-resolution-1024x616

OVX目前还没有做关于租户多控制器的实现。

3.5 Network Virtualization

本部分将介绍OVX的核心模块,网络虚拟化模块,主要完成virtual<--->physical之间的映射转换。主要完成源目地址的修改,接入端口的翻译,OF消息的翻译等内容。具体的实现将分为以下几部分介绍。

  • Switch Representation Translation
  • OpenFlow field translation – Cookies, Buffer IDs, XIDs
  • Address virtualization
  • Link and Route virtualization

3.5.1 Switch Representation Translation

  • OVXSwitch -> PhysicalSwitch (Southbound)通过拦截从tenant controller发向datapath的消息,以in_port为键值查找对应的PhysicalPort,从而找到对应的物理交换机,也可以通过tenant ID的方式查找OVXMap。具体实现,读者需要自行查看源码。
  • PhysicalSwitch -> OVXSwitch (Northbound)上行数据的查找可以直接通过MAC地址来查找,因为主机的MAC地址是唯一属于一个虚网的,所以可以作为key,用于查找tenantID,从而实现转换。也可以通过OpenFlow协议的消息字段,如xid,来找到某一个controller channel,而一个controller channel将对应一个租户的控制器。

3.5.2 OpenFlow field translation – Cookies, Buffer IDs, XIDs

那些需要从datapath到租户控制器的OpenFlow消息都需要就行翻译。需要翻译的OpenFlow消息的字段包括cookies,buffer_id,xid等。

XIDTranslator.XID需要在datapath上唯一,这个是OpenFlow协议的规定。而OVX在翻译消息的构成中,需要将来自datapath的xid以及生成的xid的键值对存储下来,以便在反向通信时,还原成原来的数据,保证通信的正确性。这个工作由XidTranslator.translate()完成,其中包括以下几个步骤:

  • generates a new XID
  • creates an XidPair to store the original XID and source OVXSwitch
  • stores the XidPair in xidMap, using the new XID as the key
  • returns the new XID value to the caller

反向的处理则由XidTranslator.untranslate()负责。

OVXFlowTable是以cookie为键值存储在OVX上的。而这个cookie的产生由generateCookie() 函数负责。每一个cookie的编码都有tenantID参与,保证在OVX上cookie的唯一性以及导向性。

bufferMap在packet_in/packet_out数据中,他们共用一个buffer_id。在消息的转换过程中,需要将来自packet_in的buffer_id和生成的buffer_id存起来,当packet_out数据下发时,则需要查找,并转换。

3.5.3 Address virtualization

地址虚拟化是OVX中非常关键的部分。为了允许用户使用任意的IP,OVX定义了OVXIPAddress用于描述用户定义的IP,这个IP地址在虚网内是唯一的。OVX还定义了PhysicalIPAddress,用于描述底层物理的IP地址,这个地址在物理网络中是唯一的。在数据层面的通信中,OVX需要将边源端口的入口流量重写IP地址成PhysicalIPAddress,还需要重写边源端口的出流量数据的IP,转换成OVXIPAddress,从而向租户展现一个使用了租户定义地址的通信流程。而中间的转发过程,也即在core datapath的转发过程中,一直都是使用PhysicalIPAddress的,且其转发等行为也由OVX直接完成了。

为了完成这个工作,OVX将datapath分为两种:

  • core datapath:仅和datapath相连的内部datapath,没有host挂载。
  • edge datapath:连接有host的datapath。

对于edge datapath而言,OVX需要作如下两件事情:

  • 对于来自网络侧的流量,查询映射表,将PhysicalIPAddress重写成OVXIPAddress.
  • 对于来自主机测的流量,查询映射表,将OVXIPAddress重写成PhysicalIPAddress.

下图举例介绍了一个简单的通信流程:

简单通信流程

图中蓝色部分为使用OVXIPAddress通信的部分,橙色部分为使用PhysicalIPAddress通信的部分。其中:

  • a为packet_in过程,直接发送给tenant controller;
  • b是packet_out过程,b过程需要将OVXIPAddress重写成PhysicalIPAddress;
  • c过程是core datapath的控制过程,直接由OVX完成,不需要上传给tenant controller,如果在虚妄中并没有这个交换机的存在的话。
  • d过程是对端edge datapath的packet_in过程,上传到OVX上时,需要转换成OVXIPAddress,进行虚拟化转换,才能转发给tenant controller。
  • e过程为packet_out过程,OVX需要将PhysicalIPAddress重写成OVXIPAddress。

3.5.3.2 Implementations

以下介绍哪一些消息需要转换。

PhysicalIPAddress -> OVXIPAddress:

  • OVXPacketIn

OVXIPAddress -> PhysicalIPAddress:

  • OVXPacketOut
  • OVXFlowMod
  • OVXActionNetworkLayerSource/Destination

以下图片举例介绍了virtualize和devirtualize的流程:

virtualize和devirtualize的流程

Fig3.7 PacketIn virtualization

Fig3.8 PacketOut devirtualization

Fig3.8 PacketOut devirtualization

Fig3.9 FlowMod devirtualization

Fig3.9 FlowMod devirtualization

3.5.4 Link and Route virtualization

TODO

3.6 State Synchronization

3.6.1 Components State Coordination

3.6.2 Error Escalation

OVX通过获取到网络的错误来同步PhysicalNetwork,如某一个port Down掉了,那么在PhysicalNetwork就应该更新其状态,并把与之对应的link down掉。这些状态变化依赖于PortStatus消息,这些消息的处理由OVXPortStatus [net.onrc.openvirtex.messages]负责。

OVX拥有错误消除的能力,能在一定范围内,隐藏底层网络中发生的错误事件,及时调整策略,保障租户的虚网正常运行。如一个BVS(Big Virtual Switch)中有一条链路发生故障,OVX可以重新映射一条没有人使用的备用链路,从而向租户隐藏错误。而对于普通的链路,OVX也可以将故障的OVXLink重新映射到冗余的链路上,保障网络的连通性。以下举例说明:

err_ignore
  • 左边的图中,b,c两点并没有映射到租户的虚网中,所以OVX完全向租户控制器隐藏了这些错误,当然租户的控制器才不关心这些不属于他的交换机到底什么状态。
  • 中间的图,a,d两点之间有多条path,当且仅当,所有的path都down掉,OVX才会通知租户控制器这一事件。
  • 右边的图中,当a到b的SwitchRoute都down掉时,才会向租户上报错误。

3.6.3 Flow Table State Synchronization

OVXFlowTable Synchronization

来自tenant controller的flow_mod在进行devirtualize()转换之前,需要存储在OVX上。tenant controller查看流表信息时,直接查看的就是存储在OVX上的流表信息。OVX始终为通过OVXFlowMods [net.onrc.openvirtex.messages]来为OVXSwitch保存着一个实时更新的flow table。

OVXFlowTable.handleFlowMods()根据flow_mod的command类型来修改对应的流表项。

在虚拟的流表被更新之后,OVX将把这个更新下发到datapath,实时修改datapath的流表。

Physical flow table synchronization

datapath的flow table信息被记录在PhysicalSwitch.flowStats数据结构中。每一个PhysicalSwitch实例中的StatisticsManager [net.onrc.openvirtex.elements.datapath.statistics]负责周期地发送 OFFlowStatisticsRequests来获取统计数据,普遍的可以设置为30秒为刷新周期。

Synchronization between flow tables

physical flow table和virtual flow table的同步通过virtualize()函数和devirtualize()函数实现。具体代码实现如下:

 3.7 Resilience

网络中的网元肯定是会有down掉的时候的。为了减少这些底层设施的failures影响到租户的网络,OVX采用了冗余映射的方式,解决这一问题,主要包括以下的方面:

  • OVXLinks : multiple paths
  • SwitchRoute : multiple paths
  • OVXBigSwitch : multiple SwitchRoutes, sets of PhysicalSwitches, or SwitchRoutes with multiple paths

当某一个冗余映射的component发生故障时,他就可以通过调用Resilient[net.onrc.openvirtex.elements]接口完成故障恢复。这个接口提供了以下连个方法:

  • public boolean tryRecovery(Component c) : Given the failure of c, attempt to switch over to any backup mappings, if possible
  • public boolean tryRevert(Component c) : Given the resumed function of c, attempt to switch back to the original (favored) mapping

以下将两个过程介绍了link故障和linkh恢复的过程。

tryRecoverylink故障和linkh恢复的过程

从上图可以看出,当physical link failed时,OVX将在查找他的备份链路,试图重新映射,并把以前的流表导入到新的link相关的switch中,同时还需要将failed的link加入到broken set,将重新映射的link从backup list中删除。

tryRevertlink从backup list中删除

上图介绍了链路恢复的过程。当之前failed的link重新恢复之后,OVX将自动尝试将映射恢复到原来的链路上,这包括流表的倒换等操作。这时需要注意的是链路的优先级问题,假设原先的链路具有最高优先级,这能让问题变得简单一些。

3.8 Persistence

3.8.1 Overview

本部分将介绍OVX中关于配置持续性的描述。OVX使用数据库存储用户的配置信息,并实时更新信息。当OVX重启时,能通过读取用户信息,迅速恢复租户的虚网。不仅仅包括虚网的拓扑,还包括所有的ID(tenantID, DPID等等)。

3.8.2 Configuration Parameters

Option Argument Comments
-dh or –db-host hostname default: "127.0.0.1"
-dp or –db-port port default:27017

值得注意的是,当虚网没有提前进行配置时,会出现以下的问题:

  • If OVX can’t connect to the database: Currently, this generates error messages in the log. These messages won’t interfere with the regular operation of OVX.
  • Using the option “–db-clear”: All persistence data is deleted from storage.

3.8.3 Related Packages and Classes

由于笔者对数据库不了解,所以这部分不做详细介绍,详情读者可以到官网查看文档。

3.8.3.1 class DBManager

Fields

Methods

3.8.3.2 class OVXNetworkManager

OVXNetworkManager负责从数据库中恢复租户的虚网。

Field

Methods

3.8.4 Storing Configurations

3.8.4.1 Overview

当虚网的component初始化之后,他们的信息将以文档的形式存入数据库。目前需要存在数据库中的component的如下所示:

  • OVXNetwork
  • OVXSingleSwitch
  • OVXBigSwitch
  • OVXPort
  • OVXLink
  • SwitchRoute
  • Host

3.8.4.2 Mechanism

当component初始化时,需要调用register()方法。在这个方法中,会调用DBManager.save()方法,用于将信息存储到数据库,其中包括:

  • Gets target collection by getDBName() e.g. “VNET”
  • Gets query index by getDBIndex() e.g. { “tenantId”:1 }
  • Gets key by getDBKey() and value by getDBObject() e.g. key is “switches”, value is { “dpids”:[4], “vdpid”:400 }
  • Adds (updates) this value into the list of this key by using MongoDB’s $addToSet operator. If the initial set is {“switches”:[{“dpids”:[1], “vdpid”:100}]}, this becomes {“switches”:[{“dpids”:[1], “vdpid”:100}, {“dpids”:[4], “vdpid”:400}]}

3.8.4.3 Persistible Components

OVXSwitch subclasses (OVXSingleSwitch, OVXBigSwitch), OVXLink, SwitchRoute, OVXPort and Host等class都具有persistible属性,都会将信息存储在数据库中。

3.8.5 Updating (Deleting) Configurations

当component发生更新时,OVX会创建新对象去描述这个新的component,同时也要把这些新数据存到数据库中。但是这个过程对于全部的component来说并不是统一的,分为以下两种情况:

  • OVXNetworks : DBManager.removeDoc() deletes a document of the specified virtual network. This method is called by OVXNetwork.unregister().
  • Other Elements : DBManager.remove() deletes an element in the list of the value for specified key by the $pull operation of MongoDB. This method is called by component inactivation methods:
    • unregisterDP() – OVXSwitch
    • unregister() – OVXPort, OVXLink, SwitchRoute, OVXHost

3.8.6 Restoring Configurations

当boot完成的时候,physical component是处于在offline状态的。OVX将去查询在offline list中的component是否还是offline,当OVX发现某一个physical element(物理网元)处于活跃状态时,将为其创建对应的physical component。当全部的physical element都处于active时,OVX将试图从数据库中恢复OVXNetwork

后语

原本我想写的是OVX的文档详解,但是目前看来好像写成了文档翻译。因为确实我对于OVX只是通过文档了解到了一些皮毛,没有更深的理解,写出来的文章缺乏主观的观点。这种问题在很久以前我已经意识到。我自己目前陷入一种非常尴尬的状态,对新知识渴望,但是却了解甚少。所以以后的时间可能需要专心读书,沉下心来好好学术。博客已经开了快一年了,但是一直以来写的都是偏工程的教程和代码详解等文章,其学术意义不大。现在也成为一个研究生了,还没有找到一个合适的节奏,希望在以下的学习生活中,能脚踏实地,加强点核心竞争力吧。谢谢浏览本博客的所有人!

转载自:李呈博客@李呈,http://www.muzixing.com/pages/2014/10/28/openvirtexoperation-and-subsystems.html


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/2821.html
分享到:
相关文章
条评论

登录后才可以评论

李呈 发表于14-10-30
3