基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API
介绍
目前protocol 中ovsdb协议层面已经实现,但是基于ovsdb protocol的上层接口并不完善,目前ONOS只支持以下几种
- 网桥操作
boolean addBridge(BridgeDescription bridgeDescription);
void deleteBridge(BridgeName bridgeName);
Collection
getBridges(); - 端口操作
void addPort(BridgeName bridgeName, String portName);
void deletePort(BridgeName bridgeName, String portName);
Collection
getPorts(); Set getPortNumbers(); List getLocalPorts(Iterable ifaceIds); - Controller操作
List
getControllers(); void setControllers(List controllers); - 接口操作 boolean addPatchMode(String ifaceName, PatchDescription patchInterface); boolean removePatchMode(String ifaceName); boolean addTunnelMode(String intf, TunnelDescription tunnelDesc); boolean removeTunnelMode(String intf);
准备工作
增加api配置ovs,首先需要熟悉ovsdb rfc7047内容,其中规定了协议内容,如何操作ovsdb数据库,有哪些限制这一点非常重要,不然可能排查bug时很难找到其中原因。
另外还需要熟悉ovsdb数据库各表的各个字段以及属性,这个可以从ovs-vswitchd.conf.db.5.pdf中查找或者在数据模板/usr/share/openvswitch/vswitch.ovsschema中查看,不需记忆;
需要值得一提的对于写操作,下发的transcat string不能出现字段类型为immutable类型的column值,例如:可以vswitch.ovsschema查看到Interface Name字段是不可更改的,这个字段在通过ovsdb协议下发update或mutate操作,不能再value字段中携带,否则会导致更新失败。这个后面有举例说明。
开发步骤
Api框架图 基于ONOS整体框架良好的封装特性,在ONOS增加对底层接口配置特性,可分为以下四个步骤
- 在onos-api模块中找到所属分类,增加接口,BridgeConfig,ControllerConfig,InterfaceConfig,PortAdmin,PortConfig,PowerConfig,QueueConfig这些配置类是我们需要关注的,在onos api这一层,并没有暴露很多细节,这里它只是定义一个接口参数和返回类型,至于底层如何实现,使用ovsdb还是netconf它并不关心,只要匹配对应的driver就可以了
- 在driver层实现1步骤中的接口,比如现在BridgeConfig中的接口目前只有ovsdbBridgeConfig一种实现,而ControllerConfig中的接口有若干种实现; 以ovsdbBridgeConfig为例,它会获取一个当前设备的ovsdb协议连接,然后调用ovsdb协议封装的API进行具体实现,所有的driver接口实现都类似,另外需要注意,因为java接口implements关系,如果一个onos api在driver有多种实现,除了要实现特定协议的处理流程,其他类型协议需要打桩处理,否则编译出错;另外如果新增driver接口,比如新增ovsdbQueueConfig Driver,需要在onos/drivers/ovsdb/src/main/resources/ovsdb-driver.xml增加对应配置,否则behavior执行时会提示not support。 3. 第二步骤中提到的client中的接口实际上是ovsdb协议实现封装的一层对外API,这一步就需要在这里增加接口,这里增加的接口和第一步中的api类似的,只不过第一步中api是屏蔽底层细节的,底层可以是任何协议,而这一步的api是具体某种协议的api,ovsdb协议的api位置在onos\protocols\ovsdb\api,所有对外接口放在OvsdbClientService抽象接口中;另外其中的一些测试实现类也需要打桩处理。 4. 实现第三步骤中定义的接口,这里就是调用协议接口,来实现自己想要的功能,以创建tunnel隧道接口为例 这里面其实是对数据库的操作,最终会通过ovsdb协议下发到openvswitch,其中的操作适合ovsdb rfc定义是一致的 具体每个表的操作,可以到onos\protocols\ovsdb\rfc\src\main\java\org\onosproject\ovsdb\rfc\table中去参考,其中的表属性是和OpenvSwitch一一对应的
问题排查
按照上述流程开发,所有的ovs操作都是可以支持的,如果遇到问题,改如何排查? 大致可分为两种:1、查看onos log ,如果log中有导致该问题的异常,那么这个问题就比较容易解决,解决掉异常即可 2、如果onos log中没有异常,但是执行配置操作,转发平面ovs没有任何反应,没有看到想要的配置下发,例如onos执行qos的配置,但是转发面没有出现任何相关的配置,而onos也没有报任何错误。这个时候可能就是下发ovsdb协议可能违背了一些限制,导致更新失败,但是onos并不会报违背了哪些限制导致更新失败,如何知道具体什么原因导致的配置失败呢?答案是使用ovsdb-client –v transact命令模拟onos下发ovsdb协议配置操作,在ovs这个地方如果因为某种类型不匹配,它会打印出详细错误信息 但是ovsdb-client –v transact [SERVER] TRANSACTION这条命令的TRANSACTION本身很复杂,手工敲可能不太现实,这个TRANSACTION可以在onos 代码加log打印出来,如下图: transactString就是最终要下发的操作,将这个打印出来,然后使用ovsdb-client命令验证下发操作失败的具体原因,需要强调的是transactString的内容是和rfc7047协议规定吻合的。 以下发ingress policing rate/burst为例,打印出来如下:
|
|
这个时候就可以使用ovsdb-client验证其正确性,
|
|
证明有一个row更新了,这个说明transaction是正确的,如果是不正确的呢,比如在上面的transaction中row中增加一个name字段,它就会提示name字段不可更改
|
|
另外删除Ovsdb Table时需要考虑到各表之间的依赖关系,对于有strong reference关系的表,在删除子表时需要先将父表的引用删除;对于调用deleteConfig接口时,这个接口会根据传入的参数查找父表的引用进行删除,这里特别要注意附表引用的数据类型,以Port、QoS与Queue关系为例。
|
|
这里Port引用Qos的时候,单数据接口type为uuid,Qos引用Queue时的数据类型为map类型,既存在key又有value;关于表元素的数据类型,可以在vswitch.ovsschema的定义中找到
|
|
OpenvSwitch transact命令 example 设置interface rate, mutate采用insert操作失败,采用+=可以
|
|