rubybvc 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/lib/controller/controller.rb +445 -0
  3. data/lib/controller/netconf_node.rb +55 -0
  4. data/lib/controller/node.rb +41 -0
  5. data/lib/controller/openflow_node.rb +33 -0
  6. data/lib/netconfdev/vrouter/dataplane_firewall.rb +53 -0
  7. data/lib/netconfdev/vrouter/firewall.rb +44 -0
  8. data/lib/netconfdev/vrouter/rule.rb +53 -0
  9. data/lib/netconfdev/vrouter/rules.rb +53 -0
  10. data/lib/netconfdev/vrouter/vrouter5600.rb +242 -0
  11. data/lib/openflowdev/action_output.rb +71 -0
  12. data/lib/openflowdev/actions/action.rb +39 -0
  13. data/lib/openflowdev/actions/actions.rb +63 -0
  14. data/lib/openflowdev/actions/copy_ttl_inwards_action.rb +39 -0
  15. data/lib/openflowdev/actions/copy_ttl_outwards_action.rb +39 -0
  16. data/lib/openflowdev/actions/dec_mpls_ttl_action.rb +39 -0
  17. data/lib/openflowdev/actions/dec_nw_ttl_action.rb +39 -0
  18. data/lib/openflowdev/actions/drop_action.rb +37 -0
  19. data/lib/openflowdev/actions/flood_action.rb +39 -0
  20. data/lib/openflowdev/actions/flood_all_action.rb +39 -0
  21. data/lib/openflowdev/actions/group_action.rb +44 -0
  22. data/lib/openflowdev/actions/hw_path_action.rb +39 -0
  23. data/lib/openflowdev/actions/loopback_action.rb +39 -0
  24. data/lib/openflowdev/actions/output_action.rb +43 -0
  25. data/lib/openflowdev/actions/pop_mpls_header_action.rb +41 -0
  26. data/lib/openflowdev/actions/pop_pbb_header_action.rb +39 -0
  27. data/lib/openflowdev/actions/pop_vlan_header_action.rb +39 -0
  28. data/lib/openflowdev/actions/push_mpls_header_action.rb +41 -0
  29. data/lib/openflowdev/actions/push_pbb_header_action.rb +40 -0
  30. data/lib/openflowdev/actions/push_vlan_header_action.rb +46 -0
  31. data/lib/openflowdev/actions/set_dl_dst_action.rb +41 -0
  32. data/lib/openflowdev/actions/set_dl_src_action.rb +41 -0
  33. data/lib/openflowdev/actions/set_field_action.rb +43 -0
  34. data/lib/openflowdev/actions/set_mpls_ttl_action.rb +41 -0
  35. data/lib/openflowdev/actions/set_nw_dst_action.rb +41 -0
  36. data/lib/openflowdev/actions/set_nw_src_action.rb +41 -0
  37. data/lib/openflowdev/actions/set_nw_ttl_action.rb +41 -0
  38. data/lib/openflowdev/actions/set_queue_action.rb +44 -0
  39. data/lib/openflowdev/actions/set_tp_dst_action.rb +41 -0
  40. data/lib/openflowdev/actions/set_tp_src_action.rb +41 -0
  41. data/lib/openflowdev/actions/set_vlan_cfi_action.rb +41 -0
  42. data/lib/openflowdev/actions/set_vlan_id_action.rb +41 -0
  43. data/lib/openflowdev/actions/set_vlan_pcp_action.rb +41 -0
  44. data/lib/openflowdev/actions/strip_vlan_action.rb +35 -0
  45. data/lib/openflowdev/actions/sw_path_action.rb +39 -0
  46. data/lib/openflowdev/flow_entry.rb +91 -0
  47. data/lib/openflowdev/instruction.rb +53 -0
  48. data/lib/openflowdev/match.rb +121 -0
  49. data/lib/openflowdev/of_switch.rb +374 -0
  50. data/lib/rubybvc.rb +52 -0
  51. data/lib/utils/hash_with_compact.rb +46 -0
  52. data/lib/utils/netconf_response.rb +67 -0
  53. data/lib/utils/netconf_response_status.rb +41 -0
  54. data/lib/utils/rest_agent.rb +103 -0
  55. data/lib/utils/utilities.rb +51 -0
  56. metadata +111 -0
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # 3. Neither the name of the copyright holder nor the names of its contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
+ # THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ class Instruction
32
+ attr_accessor :order
33
+ attr_reader :actions
34
+
35
+ def initialize(instruction_order: nil)
36
+ raise ArgumentError, "Instruction Order (instruction_order) required" unless instruction_order
37
+ @order = instruction_order
38
+ @actions = []
39
+ end
40
+
41
+ def add_apply_action(action)
42
+ raise ArgumentError, "Action must be a subclass of 'Action'" unless action.is_a?(Action)
43
+ @actions << action
44
+ end
45
+
46
+ def to_hash
47
+ actions_hash = []
48
+ @actions.each do |action|
49
+ actions_hash << action.to_hash
50
+ end
51
+ {:order => @order, 'apply-actions' => {:action => actions_hash}}
52
+ end
53
+ end
@@ -0,0 +1,121 @@
1
+ # Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # 3. Neither the name of the copyright holder nor the names of its contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
+ # THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ class Match
32
+ require 'utils/hash_with_compact'
33
+ attr_reader :eth_type, :ipv4_dst, :ipv4_src, :ipv6_src, :ipv6_dst,
34
+ :ipv6_flabel, :ipv6_ext_hdr, :ethernet_dst, :ethernet_src, :in_phy_port,
35
+ :in_port, :ip_proto, :ip_dscp, :ip_ecn, :tcp_src_port, :tcp_dst_port,
36
+ :udp_src_port, :udp_dst_port, :icmpv4_type, :icmpv4_code, :icmpv6_type,
37
+ :icmpv6_code, :arp_op_code, :arp_src_ipv4, :arp_tgt_ipv4, :arp_src_hw_addr,
38
+ :arp_tgt_hw_addr, :vlan_id, :vlan_pcp, :sctp_dst, :sctp_src, :mpls_label,
39
+ :mpls_tc, :mpls_bos, :tunnel_id, :metadata, :metadata_mask
40
+
41
+ def initialize(eth_type: nil, ipv4_destination: nil, ipv4_source: nil,
42
+ ipv6_source: nil, ipv6_destination: nil, ipv6_flabel: nil,
43
+ ipv6_ext_header: nil, ethernet_destination: nil, ethernet_source: nil,
44
+ in_port: nil, in_physical_port: nil, ip_protocol_num: nil, ip_dscp: nil,
45
+ ip_ecn: nil, tcp_source_port: nil, tcp_destination_port: nil,
46
+ udp_source_port: nil, udp_destination_port: nil, icmpv4_type: nil,
47
+ icmpv4_code: nil, icmpv6_type: nil, icmpv6_code: nil,
48
+ arp_op_code: nil, arp_source_ipv4: nil, arp_target_ipv4: nil,
49
+ arp_source_hardware_address: nil, arp_target_hardware_address: nil,
50
+ vlan_id: nil, vlan_pcp: nil, sctp_destination: nil, sctp_source: nil,
51
+ mpls_label: nil, mpls_tc: nil, mpls_bos: nil, tunnel_id: nil,
52
+ metadata: nil, metadata_mask: nil)
53
+ @eth_type = eth_type
54
+ @ipv4_dst = ipv4_destination
55
+ @ipv4_src = ipv4_source
56
+ @ipv6_dst = ipv6_destination
57
+ @ipv6_src = ipv6_source
58
+ @ipv6_flabel = ipv6_flabel
59
+ @ipv6_ext_hdr = ipv6_ext_header
60
+ @ethernet_dst = ethernet_destination
61
+ @ethernet_src = ethernet_source
62
+ @in_port = in_port
63
+ @in_phy_port = in_physical_port
64
+ @ip_proto = ip_protocol_num
65
+ @ip_dscp = ip_dscp
66
+ @ip_ecn = ip_ecn
67
+ @tcp_src_port = tcp_source_port
68
+ @tcp_dst_port = tcp_destination_port
69
+ @udp_dst_port = udp_destination_port
70
+ @udp_src_port = udp_source_port
71
+ @icmpv4_type = icmpv4_type
72
+ @icmpv4_code = icmpv4_code
73
+ @icmpv6_type = icmpv6_type
74
+ @icmpv6_code = icmpv6_code
75
+ @arp_op_code = arp_op_code
76
+ @arp_src_ipv4 = arp_source_ipv4
77
+ @arp_tgt_ipv4 = arp_target_ipv4
78
+ @arp_src_hw_addr = arp_source_hardware_address
79
+ @arp_tgt_hw_addr = arp_target_hardware_address
80
+ @vlan_id = vlan_id
81
+ @vlan_pcp = vlan_pcp
82
+ @sctp_dst = sctp_destination
83
+ @sctp_src = sctp_source
84
+ @mpls_label = mpls_label
85
+ @mpls_tc = mpls_tc
86
+ @mpls_bos = mpls_bos
87
+ @tunnel_id = tunnel_id
88
+ @metdata = metadata
89
+ @metadata_mask = metadata_mask
90
+ end
91
+
92
+ def to_hash
93
+ hash = {'ethernet-match' => {'ethernet-type' => {:type => @eth_type},
94
+ 'ethernet-destination' => {:address => @ethernet_dst},
95
+ 'ethernet-source' => {:address => @ethernet_src}},
96
+ 'ipv4-destination' => @ipv4_dst, 'ipv4-source' => @ipv4_src,
97
+ 'ipv6-destination' => @ipv6_dst, 'ipv6-source' => @ipv6_src,
98
+ 'ipv6-label' => {'ipv6-flabel' => @ipv6_flabel},
99
+ 'ipv6-ext-header' => {'ipv6-exthdr' => @ipv6_ext_hdr},
100
+ 'in-port' => @in_port, 'in_phy_port' => @in_phy_port,
101
+ 'ip-match' => {'ip-dscp' => @ip_dscp, 'ip-ecn' => @ip_ecn,
102
+ 'ip-protocol' => @ip_proto}, 'tcp-destination-port' => @tcp_dst_port,
103
+ 'tcp-source-port' => @tcp_src_port, 'udp-source-port' => @udp_src_port,
104
+ 'udp-destination-port' => @udp_dst_port, 'icmpv4-match' =>
105
+ {'icmpv4-code' => @icmpv4_code, 'icmpv4-type' => @icmpv4_type},
106
+ 'icmpv6-match' => {'icmpv6-code' => @icmpv6_code, 'icmpv6-type' => @icmpv6_type},
107
+ 'arp-op' => @arp_op_code, 'arp-source-transport-address' => @arp_src_ipv4,
108
+ 'arp-source-hardware-address' => {:address => @arp_src_hw_addr},
109
+ 'arp-target-hardware-address' => {:address => @arp_tgt_hw_addr},
110
+ 'arp-target-transport-address' => @arp_tgt_ipv4,
111
+ 'vlan-match' => {'vlan-id' => {'vlan-id' => @vlan_id,
112
+ 'vlan-id-present' => !@vlan_id.nil?}, 'vlan-pcp' => @vlan_pcp},
113
+ 'sctp-source-port' => @sctp_src, 'sctp-destination-port' => @sctp_dst,
114
+ 'protocol-match-fields' => {'mpls-label' => @mpls_label,
115
+ 'mpls-tc' => @mpls_tc, 'mpls-bos' => @mpls_bos},
116
+ :tunnel => {'tunnel-id' => @tunnel_id},
117
+ :metadata => {:metadata => @metadata, 'metadata-mask' => @metadata_mask}}
118
+ hash.delete("vlan-match") if !@vlan_id
119
+ hash
120
+ end
121
+ end
@@ -0,0 +1,374 @@
1
+ # Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # 3. Neither the name of the copyright holder nor the names of its contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
+ # THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'controller/openflow_node'
32
+ class OFSwitch < OpenflowNode
33
+ require 'json'
34
+ require 'controller/controller'
35
+ require 'openflowdev/flow_entry'
36
+ require 'openflowdev/action_output'
37
+
38
+ attr_reader :name
39
+
40
+ def initialize(controller: nil, name: nil, dpid: nil)
41
+ super(controller: controller, name: name)
42
+ @dpid = dpid
43
+ end
44
+
45
+ def get_switch_info
46
+ get_uri = @controller.get_node_operational_uri(self)
47
+ response = @controller.rest_agent.get_request(get_uri)
48
+ check_response_for_success(response) do |body|
49
+ general_info = {}
50
+ if body.has_key?('node') && body['node'].is_a?(Array)
51
+ properties = body['node'][0]
52
+ if properties.has_key?('flow-node-inventory:manufacturer')
53
+ general_info['manufacturer'] = properties['flow-node-inventory:manufacturer']
54
+ end
55
+ if properties.has_key?('flow-node-inventory:serial-number')
56
+ general_info['serial-number'] = properties['flow-node-inventory:serial-number']
57
+ end
58
+ if properties.has_key?('flow-node-inventory:software')
59
+ general_info['software'] = properties['flow-node-inventory:software']
60
+ end
61
+ if properties.has_key?('flow-node-inventory:hardware')
62
+ general_info['hardware'] = properties['flow-node-inventory:hardware']
63
+ end
64
+ if properties.has_key?('flow-node-inventory:description')
65
+ general_info['description'] = properties['flow-node-inventory:description']
66
+ end
67
+ NetconfResponse.new(NetconfResponseStatus::OK, general_info)
68
+ else
69
+ NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
70
+ end
71
+ end
72
+ end
73
+
74
+ def get_features_info
75
+ get_uri = @controller.get_node_operational_uri(self)
76
+ response = @controller.rest_agent.get_request(get_uri)
77
+ check_response_for_success(response) do |body|
78
+ if body.has_key?('node') && body['node'].is_a?(Array) &&
79
+ body['node'][0].has_key?('flow-node-inventory:switch-features')
80
+ properties = body['node'][0]['flow-node-inventory:switch-features']
81
+ feature_info = {'max_tables' => properties['max_tables'],
82
+ 'max_buffers' => properties['max_buffers']}
83
+ capabilities = []
84
+ properties['capabilities'].each do |capability|
85
+ capabilities << capability.gsub('flow-node-inventory:flow-feature-capability-', '')
86
+ end
87
+ feature_info['capabilities'] = capabilities
88
+ NetconfResponse.new(NetconfResponseStatus::OK, feature_info)
89
+ else
90
+ NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
91
+ end
92
+ end
93
+ end
94
+
95
+ def get_ports_list
96
+ get_uri = @controller.get_node_operational_uri(self)
97
+ response = @controller.rest_agent.get_request(get_uri)
98
+ check_response_for_success(response) do |body|
99
+ if body.has_key?('node') && body['node'].is_a?(Array) &&
100
+ body['node'][0].has_key?('node-connector')
101
+ ports = []
102
+ body['node'][0]['node-connector'].each do |port|
103
+ ports << port['flow-node-inventory:port-number']
104
+ end
105
+ NetconfResponse.new(NetconfResponseStatus::OK, ports)
106
+ else
107
+ NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
108
+ end
109
+ end
110
+ end
111
+
112
+ def get_ports_brief_info
113
+ get_uri = @controller.get_node_operational_uri(self)
114
+ response = @controller.rest_agent.get_request(get_uri)
115
+ check_response_for_success(response) do |body|
116
+ if body.has_key?('node') && body['node'].is_a?(Array) &&
117
+ body['node'][0].has_key?('node-connector')
118
+ ports_info = []
119
+ body['node'][0]['node-connector'].each do |port|
120
+ port_info = {'id' => port['id'],
121
+ 'number' => port['flow-node-inventory:port-number'],
122
+ 'name' => port['flow-node-inventory:name'],
123
+ 'mac-address' => port['flow-node-inventory:hardware-address'],
124
+ 'current-feature' => port['flow-node-inventory:current-feature'].upcase}
125
+ ports_info << port_info
126
+ end
127
+ NetconfResponse.new(NetconfResponseStatus::OK, ports_info)
128
+ else
129
+ NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
130
+ end
131
+ end
132
+ end
133
+
134
+ def get_port_detail_info(port)
135
+ get_uri = "#{@controller.get_node_operational_uri(self)}/node-connector/"\
136
+ "#{self.name}:#{port}"
137
+ response = @controller.rest_agent.get_request(get_uri)
138
+ check_response_for_success(response) do |body|
139
+ if body.has_key?('node-connector') &&
140
+ body['node-connector'].is_a?(Array) && body['node-connector'][0]
141
+ NetconfResponse.new(NetconfResponseStatus::OK, body['node-connector'][0])
142
+ else
143
+ NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
144
+ end
145
+ end
146
+ end
147
+
148
+ def add_modify_flow(flow)
149
+ put_uri = "#{@controller.get_node_config_uri(self)}/table/#{flow.table_id}/"\
150
+ "flow/#{flow.id}"
151
+ response = @controller.rest_agent.put_request(put_uri, flow.to_hash,
152
+ headers: {'Content-Type' => 'application/yang.data+json'})
153
+ if response.code.to_i == 200
154
+ NetconfResponse.new(NetconfResponseStatus::OK)
155
+ else
156
+ handle_error_response(response)
157
+ end
158
+ end
159
+
160
+ def get_configured_flow(table_id: nil, flow_id: nil)
161
+ raise ArgumentError, "Table ID (table_id) required" unless table_id
162
+ raise ArgumentError, "Flow ID (flow_id) required" unless flow_id
163
+ get_uri = "#{@controller.get_node_config_uri(self)}/table/#{table_id}/"\
164
+ "flow/#{flow_id}"
165
+ response = @controller.rest_agent.get_request(get_uri)
166
+ check_response_for_success(response) do |body|
167
+ NetconfResponse.new(NetconfResponseStatus::OK, body)
168
+ end
169
+ end
170
+
171
+ def delete_flow(table_id: nil, flow_id: nil)
172
+ raise ArgumentError, "Table ID (table_id) required" unless table_id
173
+ raise ArgumentError, "Flow ID (flow_id) required" unless flow_id
174
+ delete_uri = "#{@controller.get_node_config_uri(self)}/table/#{table_id}/"\
175
+ "flow/#{flow_id}"
176
+ response = @controller.rest_agent.delete_request(delete_uri)
177
+ if response.code.to_i == 200
178
+ NetconfResponse.new(NetconfResponseStatus::OK)
179
+ else
180
+ handle_error_response(response)
181
+ end
182
+ end
183
+
184
+ def get_operational_flows(table_id: nil)
185
+ raise ArgumentError, "Table ID (table_id) required" unless table_id
186
+ get_flows(table_id: table_id)
187
+ end
188
+
189
+ def get_configured_flows(table_id: nil)
190
+ raise ArgumentError, "Table ID (table_id) required" unless table_id
191
+ get_flows(table_id: table_id, is_operational: false)
192
+ end
193
+
194
+ def get_operational_flows_ovs_syntax(table_id: nil, sort: false)
195
+ raise ArgumentError, "Table ID (table_id) required" unless table_id
196
+ response = get_operational_flows(table_id: table_id)
197
+ if response.status == NetconfResponseStatus::OK
198
+ flows = []
199
+ response.body.sort! { |x,y| x['priority'] <=> y['priority']} if sort
200
+ response.body.each do |flow|
201
+ flows << odl_to_ovs_flow_syntax(flow)
202
+ end
203
+ NetconfResponse.new(NetconfResponseStatus::OK, flows)
204
+ else
205
+ response
206
+ end
207
+ end
208
+
209
+ def get_configured_flows_ovs_syntax(table_id: nil, sort: false)
210
+ raise ArgumentError, "Table ID (table_id) required" unless table_id
211
+ response = get_configured_flows(table_id: table_id)
212
+ if response.status == NetconfResponseStatus::OK
213
+ flows = []
214
+ response.body.sort! { |x,y| x['priority'] <=> y['priority']} if sort
215
+ response.body.each do |flow|
216
+ flows << odl_to_ovs_flow_syntax(flow)
217
+ end
218
+ NetconfResponse.new(NetconfResponseStatus::OK, flows)
219
+ else
220
+ response
221
+ end
222
+ end
223
+
224
+ private
225
+
226
+ def get_flows(table_id: nil, is_operational: true)
227
+ if is_operational
228
+ get_uri = "#{@controller.get_node_operational_uri(self)}/"\
229
+ "flow-node-inventory:table/#{table_id}"
230
+ else
231
+ get_uri = "#{@controller.get_node_config_uri(self)}/"\
232
+ "flow-node-inventory:table/#{table_id}"
233
+ end
234
+
235
+ response = @controller.rest_agent.get_request(get_uri)
236
+ check_response_for_success(response) do |body|
237
+ if body.has_key?('flow-node-inventory:table') &&
238
+ body['flow-node-inventory:table'].is_a?(Array) &&
239
+ body['flow-node-inventory:table'][0].has_key?('flow') &&
240
+ body['flow-node-inventory:table'][0]['flow'].is_a?(Array)
241
+ NetconfResponse.new(NetconfResponseStatus::OK,
242
+ body['flow-node-inventory:table'][0]['flow'])
243
+ else
244
+ NetconfResponse.new(NetconfResponseStatus::DATA_NOT_FOUND)
245
+ end
246
+ end
247
+ end
248
+
249
+ def odl_to_ovs_flow_syntax(odl_flow)
250
+ ovs_flow = {}
251
+ if odl_flow.has_key?('cookie')
252
+ ovs_flow['cookie'] = "0x#{odl_flow['cookie'].to_s(16)}"
253
+ end
254
+
255
+ if odl_flow.has_key?('opendaylight-flow-statistics:flow-statistics')
256
+ stats = odl_flow['opendaylight-flow-statistics:flow-statistics']
257
+ if stats.has_key?('duration')
258
+ nanoseconds = stats['duration']['nanosecond'] ||= 0
259
+ seconds = stats['duration']['second'] ||= 0
260
+ duration = ((seconds * 1000000000 + nanoseconds).to_f / 1000000000.to_f)
261
+ ovs_flow['duration'] = "#{duration}s"
262
+ end
263
+
264
+ if stats.has_key?('byte-count')
265
+ ovs_flow['n_bytes'] = stats['byte-count']
266
+ end
267
+
268
+ if stats.has_key?('packet-count')
269
+ ovs_flow['n_packets'] = stats['packet-count']
270
+ end
271
+ end
272
+
273
+ if odl_flow.has_key?("table_id")
274
+ ovs_flow['table'] = odl_flow['table_id']
275
+ end
276
+
277
+ if odl_flow.has_key?('idle-timeout')
278
+ ovs_flow['idle_timeout'] = odl_flow['idle-timeout'] if odl_flow['idle-timeout'] != 0
279
+ end
280
+
281
+ if odl_flow.has_key?('hard-timeout')
282
+ ovs_flow['hard_timeout'] = odl_flow['hard-timeout'] if odl_flow['hard-timeout'] != 0
283
+ end
284
+
285
+ if odl_flow.has_key?('priority')
286
+ ovs_flow['priority'] = odl_flow['priority']
287
+ end
288
+
289
+ if odl_flow.has_key?('match')
290
+ match = odl_flow['match']
291
+ if match.has_key?('in-port')
292
+ ovs_flow['in_port'] = match['in-port'].partition("#{@name}:")[2]
293
+ end
294
+
295
+ if match.has_key?('vlan-match')
296
+ vlan_match = match['vlan-match']
297
+ if vlan_match.has_key?('vlan-id') &&
298
+ vlan_match['vlan-id'].has_key?('vlan-id')
299
+ ovs_flow['dl_vlan'] = vlan_match['vlan-id']['vlan-id']
300
+ end
301
+
302
+ if vlan_match.has_key?('vlan-pcp')
303
+ ovs_flow['dl_vlan_pcp'] = vlan_match['vlan-pcp']
304
+ end
305
+ end
306
+
307
+ if match.has_key?('ethernet-match')
308
+ eth_match = match['ethernet-match']
309
+ if eth_match.has_key?('ethernet-type') &&
310
+ eth_match['ethernet-type'].has_key?('type')
311
+ ovs_flow['dl_type'] = "0x#{eth_match['ethernet-type']['type'].to_s(16)}"
312
+ end
313
+
314
+ if eth_match.has_key?('ethernet-source') &&
315
+ eth_match['ethernet-source'].has_key?('address')
316
+ ovs_flow['dl_src'] = eth_match['ethernet-source']['address']
317
+ end
318
+
319
+ if eth_match.has_key?('ethernet-destination') &&
320
+ eth_match['ethernet-destination'].has_key?('address')
321
+ ovs_flow['dl_dst'] = eth_match['ethernet-destination']['address']
322
+ end
323
+ end
324
+
325
+ if match.has_key?('ip-match')
326
+ ip_match = match['ip-match']
327
+ if ip_match.has_key?('ip-protocol')
328
+ ovs_flow['nw_proto'] = ip_match['ip-protocol']
329
+ end
330
+ end
331
+
332
+ if match.has_key?('tcp-source-port')
333
+ ovs_flow['tp_src'] = match['tcp-source-port']
334
+ end
335
+
336
+ if match.has_key?('ipv4-source')
337
+ ovs_flow['nw_src'] = match['ipv4-source']
338
+ end
339
+
340
+ if match.has_key?('ipv4-destination')
341
+ ovs_flow['nw_dst'] = match['ipv4-destination']
342
+ end
343
+ end
344
+
345
+ if odl_flow.has_key?('instructions') &&
346
+ odl_flow['instructions'].has_key?('instruction')
347
+ odl_flow['instructions']['instruction'].each do |instruction|
348
+ if instruction.has_key?('apply-actions') &&
349
+ instruction['apply-actions'].has_key?('action')
350
+ actions_list = []
351
+ instruction['apply-actions']['action'].each do |action|
352
+ if action.has_key?('output-action')
353
+ ao = ActionOutput.new
354
+ ao.update_from_object(action)
355
+ actions_list << ao
356
+ end
357
+ end
358
+ actions_list.sort! { |x, y| x.order <=> y.order}
359
+ actions = []
360
+ actions_list.each do |action|
361
+ actions << action.to_s
362
+ end
363
+ ovs_flow['actions'] = actions.join(',')
364
+ end
365
+ end
366
+ else
367
+ # ODL flows do not seem to contain the instructions info for flows that
368
+ # were set with 'drop'
369
+ ovs_flow['actions'] = 'drop'
370
+ end
371
+
372
+ ovs_flow
373
+ end
374
+ end
data/lib/rubybvc.rb ADDED
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # 3. Neither the name of the copyright holder nor the names of its contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
+ # THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'controller/controller'
32
+ require 'controller/node'
33
+ require 'controller/netconf_node'
34
+ require 'controller/openflow_node'
35
+
36
+ require 'netconfdev/vrouter/dataplane_firewall'
37
+ require 'netconfdev/vrouter/firewall'
38
+ require 'netconfdev/vrouter/rule'
39
+ require 'netconfdev/vrouter/rules'
40
+ require 'netconfdev/vrouter/vrouter5600'
41
+
42
+ require 'openflowdev/actions/actions'
43
+ require 'openflowdev/action_output'
44
+ require 'openflowdev/flow_entry'
45
+ require 'openflowdev/instruction'
46
+ require 'openflowdev/match'
47
+ require 'openflowdev/of_switch'
48
+
49
+ require 'utils/hash_with_compact'
50
+ require 'utils/netconf_response'
51
+ require 'utils/netconf_response_status'
52
+ require 'utils/rest_agent'
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2015, BROCADE COMMUNICATIONS SYSTEMS, INC
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without modification,
6
+ # are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # 3. Neither the name of the copyright holder nor the names of its contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
+ # THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ # borrowing from rails implementation
32
+ # https://github.com/rails/rails/blob/c0357d789b4323da64f1f9f82fa720ec9bac17cf/activesupport/lib/active_support/core_ext/hash/compact.rb#L8
33
+ class Hash
34
+ def compact
35
+ self.select { |_, value| value.is_a?(Hash) ? !value.compact_and_check_if_empty : !value.nil? }
36
+ end
37
+
38
+ def compact!
39
+ self.reject! {|_, value| value.is_a?(Hash) ? value.compact_and_check_if_empty : value.nil? }
40
+ end
41
+
42
+ def compact_and_check_if_empty
43
+ self.compact!
44
+ self.empty?
45
+ end
46
+ end