基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API

基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API

  1. 介绍
  2. 准备工作
  3. 开发步骤
  4. 问题排查

介绍
目前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字段中携带,否则会导致更新失败。这个后面有举例说明。
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API_第1张图片
开发步骤
Api框架图
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API_第2张图片
基于ONOS整体框架良好的封装特性,在ONOS增加对底层接口配置特性,可分为以下四个步骤
1、 在onos-api模块中找到所属分类,增加接口,BridgeConfig,ControllerConfig,InterfaceConfig,PortAdmin,PortConfig,PowerConfig,QueueConfig这些配置类是我们需要关注的,在onos api这一层,并没有暴露很多细节,这里它只是定义一个接口参数和返回类型,至于底层如何实现,使用ovsdb还是netconf它并不关心,只要匹配对应的driver就可以了
2、 在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。
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API_第3张图片
3、 第二步骤中提到的client中的接口实际上是ovsdb协议实现封装的一层对外API,这一步就需要在这里增加接口,这里增加的接口和第一步中的api类似的,只不过第一步中api是屏蔽底层细节的,底层可以是任何协议,而这一步的api是具体某种协议的api,ovsdb协议的api位置在onos\protocols\ovsdb\api,所有对外接口放在OvsdbClientService抽象接口中;另外其中的一些测试实现类也需要打桩处理。
4、 实现第三步骤中定义的接口,这里就是调用协议接口,来实现自己想要的功能,以创建tunnel隧道接口为例
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API_第4张图片
这里面其实是对数据库的操作,最终会通过ovsdb协议下发到openvswitch,其中的操作适合ovsdb rfc定义是一致的
具体每个表的操作,可以到onos\protocols\ovsdb\rfc\src\main\java\org\onosproject\ovsdb\rfc\table中去参考,其中的表属性是和OpenvSwitch一一对应的
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API_第5张图片
问题排查
按照上述流程开发,所有的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打印出来,如下图:
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API_第6张图片
transactString就是最终要下发的操作,将这个打印出来,然后使用ovsdb-client命令验证下发操作失败的具体原因,需要强调的是transactString的内容是和rfc7047协议规定吻合的。
以下发ingress policing rate/burst为例,打印出来如下:
transact string{“id”:”e676f626-4e80-45cb-ae45-2f5500b016d6”,”method”:”transact”,”params”:[“Open_vSwitch”,{“op”:”update”,”row”:{“ingress_policing_rate”:[“set”,[100]],”ingress_policing_burst”:[“set”,[100]]},”where”:[[“_uuid”,”==”,[“uuid”,”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b”]]],”table”:”Interface”}]}

这个时候就可以使用ovsdb-client验证其正确性,
o[root@localhost ~]# ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”update\”,\”row\”:{\”ingress_policing_rate\”:[\”set\”,[200]],\”ingress_policing_burst\”:[\”set\”,[200]]},\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b\”]]],\”table\”:\”Interface\”}]”
下面是执行上面命令打印的信息
[root@localhost ~]# ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”update\”,\”row\”:{\”ingress_policing_rate\”:[\”set\”,[200]],\”ingress_policing_burst\”:[\”set\”,[200]]},\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b\”]]],\”table\”:\”Interface\”}]”
2016-09-08T06:29:50Z|00001|jsonrpc|DBG|unix:/var/run/openvswitch/db.sock: send request, method=”transact”, params=[“Open_vSwitch”,{“where”:[[“_uuid”,”==”,[“uuid”,”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b”]]],”table”:”Interface”,”op”:”update”,”row”:{“ingress_policing_burst”:[“set”,[200]],”ingress_policing_rate”:[“set”,[200]]}}], id=0
2016-09-08T06:29:50Z|00002|poll_loop|DBG|wakeup due to 0-ms timeout
2016-09-08T06:29:50Z|00003|poll_loop|DBG|wakeup due to [POLLIN] on fd 3 (<->/var/run/openvswitch/db.sock) at lib/stream-fd.c:155
2016-09-08T06:29:50Z|00004|jsonrpc|DBG|unix:/var/run/openvswitch/db.sock: received reply, result=[{“count”:1}], id=0
[{“count”:1}]
证明有一个row更新了,这个说明transaction是正确的,如果是不正确的呢,比如在上面的transaction中row中增加一个name字段,它就会提示name字段不可更改
[root@localhost ~]# ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”update\”,\”row\”:{\”name\”:\”vnet0\”,\”ingress_policing_rate\”:[\”set\”,[200]],\”ingress_policing_burst\”:[\”set\”,[200]]},\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b\”]]],\”table\”:\”Interface\”}]”
2016-09-08T06:34:52Z|00001|jsonrpc|DBG|unix:/var/run/openvswitch/db.sock: send request, method=”transact”, params=[“Open_vSwitch”,{“where”:[[“_uuid”,”==”,[“uuid”,”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b”]]],”table”:”Interface”,”op”:”update”,”row”:{“name”:”vnet0”,”ingress_policing_burst”:[“set”,[200]],”ingress_policing_rate”:[“set”,[200]]}}], id=0
2016-09-08T06:34:52Z|00002|poll_loop|DBG|wakeup due to 0-ms timeout
2016-09-08T06:34:52Z|00003|poll_loop|DBG|wakeup due to [POLLIN] on fd 3 (<->/var/run/openvswitch/db.sock) at lib/stream-fd.c:155
2016-09-08T06:34:52Z|00004|jsonrpc|DBG|unix:/var/run/openvswitch/db.sock: received reply, result=[{“syntax”:”{\”op\”:\”update\”,\”row\”:{\”ingress_policing_burst\”:[\”set\”,[200]],\”ingress_policing_rate\”:[\”set\”,[200]],\”name\”:\”vnet0\”},\”table\”:\”Interface\”,\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b\”]]]}”,”details”:”Cannot update immutable column name in table Interface.”,”error”:”constraint violation”}], id=0
[{“details”:”Cannot update immutable column name in table Interface.”,”error”:”constraint violation”,”syntax”:”{\”op\”:\”update\”,\”row\”:{\”ingress_policing_burst\”:[\”set\”,[200]],\”ingress_policing_rate\”:[\”set\”,[200]],\”name\”:\”vnet0\”},\”table\”:\”Interface\”,\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b\”]]]}”}]
另外删除Ovsdb Table时需要考虑到各表之间的依赖关系,对于有strong reference关系的表,在删除子表时需要先将父表的引用删除;对于调用deleteConfig接口时,这个接口会根据传入的参数查找父表的引用进行删除,这里特别要注意附表引用的数据类型,以Port、QoS与Queue关系为例。
基于OVSDB协议在SDN控制器ONOS开发配置管理OVS API_第7张图片
“Port”: {
“columns”: {
“name”: {
“type”: “string”,
“mutable”: false},

“qos”: {
“type”: {“key”: {“type”: “uuid”,
“refTable”: “QoS”},
“min”: 0, “max”: 1}},
“QoS”: {
“columns”: {
“type”: {
“type”: “string”},
“queues”: {
“type”: {“key”: {“type”: “integer”,
“minInteger”: 0,
“maxInteger”: 4294967295},
“value”: {“type”: “uuid”,
“refTable”: “Queue”},
“min”: 0, “max”: “unlimited”}},

这里Port引用Qos的时候,单数据接口type为uuid,Qos引用Queue时的数据类型为map类型,既存在key又有value;关于表元素的数据类型,可以在vswitch.ovsschema的定义中找到
错误的删除Queue元素的操作
ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”mutate\”,\”where\”:[[\”queues\”,\”includes\”,[\”uuid\”,\”dd2de53c-e4e7-4252-a191-72968a0f7859\”]]],\”mutations\”:[[\”queues\”,\”delete\”,[\”uuid\”,\”dd2de53c-e4e7-4252-a191-72968a0f7859\”]]],\”table\”:\”QoS\”},{\”op\”:\”delete\”,\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”dd2de53c-e4e7-4252-a191-72968a0f7859\”]]],\”table\”:\”Queue\”}]”
正确
ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”mutate\”,\”where\”:[[\”queues\”,\”includes\”,[\”map\”,[[0,[\”uuid\”,\”dd2de53c-e4e7-4252-a191-72968a0f7859\”]]]]]],\”mutations\”:[[\”queues\”,\”delete\”,[\”map\”,[[0,[\”uuid\”,\”dd2de53c-e4e7-4252-a191-72968a0f7859\”]]]]]],\”table\”:\”QoS\”},{\”op\”:\”delete\”,\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”dd2de53c-e4e7-4252-a191-72968a0f7859\”]]],\”table\”:\”Queue\”}]”

OpenvSwitch transact命令 example
设置interface rate, mutate采用insert操作失败,采用+=可以
ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”mutate\”,\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”4aa0e983-29fd-4661-a05f-623e60fdf8e2\”]]],\”mutations\”:[[\”ingress_policing_rate\”,\”+=\”,200]],\”table\”:\”Interface\”}]”

设置interface rate, update操作,去掉interface name不可更新的column
ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”update\”,\”row\”:{\”mac_in_use\”:[\”set\”,[\”fe:54:00:78:6d:17\”]],\”duplex\”:[\”set\”,[\”full\”]],\”admin_state\”:[\”set\”,[\”up\”]],\”error\”:[\”set\”,[]],\”type\”:\”\”,\”ingress_policing_burst\”:[\”set\”,[100]],\”cfm_mpid\”:[\”set\”,[]],\”mac\”:[\”set\”,[]],\”cfm_fault\”:[\”set\”,[]],\”cfm_flap_count\”:[\”set\”,[]],\”options\”:[\”map\”,[]],\”cfm_health\”:[\”set\”,[]],\”ingress_policing_rate\”:[\”set\”,[100]],\”bfd\”:[\”map\”,[]],\”ifindex\”:[\”set\”,[36]],\”ofport\”:[\”set\”,[6]],\”other_config\”:[\”map\”,[]],\”bfd_status\”:[\”map\”,[]],\”cfm_remote_mpids\”:[\”set\”,[]],\”cfm_fault_status\”:[\”set\”,[]],\”link_speed\”:[\”set\”,[10000000]],\”external_ids\”:[\”map\”,[[\”vm-id\”,\”e570935c-693a-458c-8a59-ca687e0473a3\”],[\”attached-mac\”,\”52:54:00:78:6d:17\”],[\”iface-status\”,\”active\”],[\”iface-id\”,\”2cf8fa66-3b07-4db1-8e0b-ec635af99237\”]]],\”mtu\”:[\”set\”,[1500]],\”lacp_current\”:[\”set\”,[]],\”link_resets\”:[\”set\”,[1]],\”cfm_remote_opstate\”:[\”set\”,[]],\”link_state\”:[\”set\”,[\”up\”]],\”ofport_request\”:[\”set\”,[]],\”lldp\”:[\”map\”,[]],\”statistics\”:[\”map\”,[[\”tx_packets\”,1732],[\”tx_errors\”,0],[\”collisions\”,0],[\”tx_dropped\”,0],[\”rx_dropped\”,0],[\”rx_crc_err\”,0],[\”rx_bytes\”,0],[\”rx_frame_err\”,0],[\”rx_over_err\”,0],[\”tx_bytes\”,140292],[\”rx_errors\”,0],[\”rx_packets\”,0]]],\”status\”:[\”map\”,[[\”driver_name\”,\”tun\”],[\”driver_version\”,\”1.6\”],[\”firmware_version\”,\”\”]]]},\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”4aa0e983-29fd-4661-a05f-623e60fdf8e2\”]]],\”table\”:\”Interface\”}]”

ovsdb-client -v transact “[\”Open_vSwitch\”,{\”op\”:\”update\”,\”row\”:{\”ingress_policing_rate\”:[\”set\”,[200]],\”ingress_policing_burst\”:[\”set\”,[200]]},\”where\”:[[\”_uuid\”,\”==\”,[\”uuid\”,\”58dfdd10-43b9-45c7-aca6-e6fe6b5b6a7b\”]]],\”table\”:\”Interface\”}]”

你可能感兴趣的:(SDN)