rubybvc 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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