前言
继上篇《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握手的状态机示意图
如果对这个经典的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的创建过程:
每一个Component都包含有register()和boot()的接口函数用于注册和初始化component。容易意识到的一点是,这些Component的启动肯定是有顺序的,或者说他们之间的以来关系肯定是固定的。如端口必然以来于交换机,没有交换机类,就不会有端口类。下图介绍了Components之间的包含和映射关系。其中实线为包含关系,虚线为映射关系。
ControllerChannelHandler [net.onrc.openvirtex.core.io] 负责OVXSwitch实例到tenant controller的连接,并维持一个状态机如下图所示。当且仅当一个OVXNetwork完成了所有OVXSwitch和控制器的连接时,才能进入ACTIVE状态。此时的OVX对于tenant Controller而言是一个datapath。
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。
1 2 3 4 |
@Override public void handleIO(OFMessage msg, Channel channel) { this.state.handleIO(this, msg, channel); } |
当交换机处于ACTIVE状态时,才会被调用。
PhysicalPhysicalSwitch.Switchstate.ACTIVE满足时,handleIO允许被调用。函数代码如下:
1 2 3 4 5 6 7 |
public void handleIO(PhysicalSwitch psw, final OFMessage msg, Channel ch) { try { ((Virtualizable) msg).virtualize(psw); } catch (final ClassCastException e) { psw.log.error("Received illegal message : " + msg); } } |
OVXSwitch.Switchstate.ACTIVE满足时,函数代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public void handleIO(OVXSwitch vsw, final OFMessage msg, Channel ch) { /* * Save the channel the msg came in on */ msg.setXid(vsw.channelMux.translate(msg.getXid(), ch)); try { /* * Check whether this channel (ie. controller) is permitted * to send this msg to the dataplane */ if (vsw.roleMan.canSend(ch, msg) ) ((Devirtualizable) msg).devirtualize(vsw); else vsw.denyAccess(ch, msg, vsw.roleMan.getRole(ch)); } catch (final ClassCastException e) { OVXSwitch.log.error("Received illegal message : " + msg); } } |
其整个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消息。其处理流程如下图:
根据每一个端口的探测计数器结果(默认为3),可以将端口分为fast和slow端口。其中fast端口为内部端口,即端口对端也是一个交换机端口,能回复LLDP数据包。否则就是slow端口,理论上slow端口为连接主机的端口。每一次发送一个探测包,探测计数器就加1,收到回复则减1,当计数器大于3时,可将端口定义为slow port,这些数据都存储在Map portProbeCount。
3.4.2 PhysicalSwitch Statistics Collection
在OVX中统计信息存储在如下的数据结构中:
1 2 |
AtomicReference<Map<Short, OVXPortStatisticsReply>> portStats; AtomicReference<Map<Integer, List>> flowStats; |
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并发送给租户控制器。
下图介绍了这个处理流程。
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的唯一性以及导向性。
1 2 3 4 5 6 |
private long generateCookie() { ... final int cookie = this.cookieCounter.getAndIncrement(); return (long) this.vswitch.getTenantId() << 32 | 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的流程:
Fig3.7 PacketIn virtualization
Fig3.8 PacketOut 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重新映射到冗余的链路上,保障网络的连通性。以下举例说明:
- 左边的图中,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。
1 2 3 4 5 6 7 8 9 10 |
/* Within class OVXFlowMod */ public void devirtualize(final OVXSwitch sw) { ... FlowTable ft = this.sw.getFlowTable(); ... long cookie = ((OVXFlowTable) ft).getCookie(); //Store the virtual flowMod and obtain the physical cookie ovxMatch.setCookie(cookie); /* update sw's OVXFlowTable */ boolean pflag = ft.handleFlowMods(this, cookie); |
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()函数实现。具体代码实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public void virtualize(final PhysicalSwitch sw) { /* determine tenant from cookie */ int tid = (int) (this.cookie >> 32); ... try { /* find which OVXSwitch's flowtable is affected */ OVXSwitch vsw = sw.getMap().getVirtualSwitch(sw, tid); if (vsw.getFlowTable().hasFlowMod(this.cookie)) { OVXFlowMod fm = vsw.getFlowMod(this.cookie); vsw.deleteFlowMod(this.cookie); /* send north ONLY if tenant controller wanted a FlowRemoved for the FlowMod*/ if (fm.hasFlag(OFFlowMod.OFPFF_SEND_FLOW_REM)) { writeFields(fm); vsw.sendMsg(this, sw); } } ... } |
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恢复的过程。
从上图可以看出,当physical link failed时,OVX将在查找他的备份链路,试图重新映射,并把以前的流表导入到新的link相关的switch中,同时还需要将failed的link加入到broken set,将重新映射的link从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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<pre class="font:consolas font-size:14 line-height:20 lang:java decode:true">// Database collection names public static final String DB_CONFIG = "CONFIG"; public static final String DB_USER = "USER"; public static final String DB_VNET = "VNET"; // Database object private DBConnection dbConnection; // Map of collection names and collection objects private Map<String, DBCollection> collections; // Mapping between physical dpids and a list of vnet managers private Map<Long, List<OVXNetworkManager>> dpidToMngr; // Mapping between physical links and a list of vnet managers private Map<DPIDandPortPair, List<OVXNetworkManager>> linkToMngr; // Mapping between physical ports and a list of vnet managers private Map<DPIDandPort, List<OVXNetworkManager>> portToMngr;</pre> |
Methods
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// Initialize database connection public void init(String host, Integer port, boolean clear) // Create a document in database from persistable object obj public void createDoc(Persistable obj) // Remove a document public void removeDoc(Persistable obj) // Save an element to the list of specified key in document public void save(Persistable obj // Remove an element from the list of specified key in document public void remove(Persistable obj) // Reads all virtual networks from database and spawn an OVXNetworkManager // for each. private void readOVXNetworks() // Reads virtual components from a list of maps in db format and registers the // physical components in their manager. private void readOVXSwitches(List<Map<String, Object>> switches, OVXNetworkManager mngr) private void readOVXLinks(List<Map<String, Object>> links, OVXNetworkManager mngr) private void readOVXPorts(List<Map<String, Object>> ports, OVXNetworkManager mngr) private void readOVXRoutes(List<Map<String, Object>> routes, OVXNetworkManager mngr) |
3.8.3.2 class OVXNetworkManager
OVXNetworkManager负责从数据库中恢复租户的虚网。
Field
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// Document of virtual network private Map<String, Object> vnet; private Integer tenantId; // Set of offline and online physical switches private Set<Long> offlineSwitches; private Set<Long> onlineSwitches; // Set of offline and online physical links identified as (dpid, port number)-pair private Set<DPIDandPortPair> offlineLinks; private Set<DPIDandPortPair> onlineLinks; // Set of offline and online physical ports private Set<DPIDandPort> offlinePorts; private Set<DPIDandPort> onlinePorts; private boolean bootState; |
Methods
1 2 3 4 5 6 7 8 9 10 11 12 |
// Register a physical component to offline list public void registerSwitch(final Long dpid) public void registerLink(final DPIDandPortPair dpp) public void registerPort(final DPIDandPort port) // Delete a physical component from offline list, // add it to online list, // and then, if all physical components are online, // create a virtual network. public synchronized void setSwitch(final Long dpid) public synchronized void unsetSwitch(final Long dpid) public synchronized void setLink(final DPIDandPortPair dpp) |
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