blob: 2b97055648cff0c335c67bfd8a36bd4671668abe [file] [log] [blame]
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -07001#
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08002# Copyright 2017 the original author or authors.
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -07003#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17"""
18Convert loxi objects to openflow_13 messages and back.
19"""
20from copy import copy
21
22from google.protobuf.descriptor import FieldDescriptor
23
24import loxi.of13 as of13
25from protobuf_to_dict import protobuf_to_dict, TYPE_CALLABLE_MAP
26from protos import openflow_13_pb2 as pb2
27
28
29type_callable_map = copy(TYPE_CALLABLE_MAP)
30type_callable_map.update({
31 FieldDescriptor.TYPE_STRING: str
32})
33
34def pb2dict(pb):
35 """
36 Convert protobuf to a dict of values good for instantiating
37 loxi objects (or any other objects). We specialize the protobuf_to_dict
38 library call with our modified decoders.
39 :param pb: protobuf as loaded into Python
40 :return: dict of values
41 """
42 return protobuf_to_dict(pb, type_callable_map)
43
44def to_loxi(grpc_object):
45 cls = grpc_object.__class__
46 converter = to_loxi_converters[cls]
47 return converter(grpc_object)
48
49def to_grpc(loxi_object):
50 cls = loxi_object.__class__
51 converter = to_grpc_converters[cls]
52 return converter(loxi_object)
53
54def ofp_port_to_loxi_port_desc(pb):
55 kw = pb2dict(pb)
56 return of13.common.port_desc(**kw)
57
Zsolt Haraszti217a12e2016-12-19 16:37:55 -080058def ofp_port_status_to_loxi_port_status(pb):
59 return of13.message.port_status(
60 reason=pb.reason,
61 desc=ofp_port_to_loxi_port_desc(pb.desc)
62 )
63
Zsolt Haraszticd22adc2016-10-25 00:13:06 -070064def make_loxi_match(match):
Zsolt Haraszti66862032016-11-28 14:28:39 -080065 assert match.get('type', pb2.OFPMT_STANDARD) == pb2.OFPMT_OXM
Zsolt Haraszticd22adc2016-10-25 00:13:06 -070066 loxi_match_fields = []
Zsolt Haraszti66862032016-11-28 14:28:39 -080067 for oxm_field in match.get('oxm_fields', []):
Zsolt Haraszticd22adc2016-10-25 00:13:06 -070068 assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
69 ofb_field = oxm_field['ofb_field']
70 field_type = ofb_field.get('type', 0)
71 if field_type == pb2.OFPXMT_OFB_ETH_TYPE:
72 loxi_match_fields.append(
73 of13.oxm.eth_type(value=ofb_field['eth_type']))
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -080074 elif field_type == pb2.OFPXMT_OFB_IN_PORT:
75 loxi_match_fields.append(
76 of13.oxm.in_port(value=ofb_field['port']))
Zsolt Haraszticd22adc2016-10-25 00:13:06 -070077 else:
78 raise NotImplementedError(
79 'OXM match field for type %s' % field_type)
80 return of13.match_v3(oxm_list=loxi_match_fields)
81
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070082def ofp_flow_stats_to_loxi_flow_stats(pb):
83 kw = pb2dict(pb)
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070084
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070085 def make_loxi_action(a):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070086 type = a.get('type', 0)
87 if type == pb2.OFPAT_OUTPUT:
88 output = a['output']
89 return of13.action.output(**output)
90 else:
91 raise NotImplementedError(
92 'Action decoder for action OFPAT_* %d' % type)
93
94 def make_loxi_instruction(inst):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070095 type = inst['type']
96 if type == pb2.OFPIT_APPLY_ACTIONS:
97 return of13.instruction.apply_actions(
98 actions=[make_loxi_action(a)
99 for a in inst['actions']['actions']])
100 else:
101 raise NotImplementedError('Instruction type %d' % type)
102
103 kw['match'] = make_loxi_match(kw['match'])
104 kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
Zsolt Haraszti66862032016-11-28 14:28:39 -0800105 del kw['id']
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700106 return of13.flow_stats_entry(**kw)
107
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -0800108
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700109def ofp_packet_in_to_loxi_packet_in(pb):
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -0800110 packet_in = of13.message.packet_in(
111 buffer_id=pb.buffer_id,
112 reason=pb.reason,
113 table_id=pb.table_id,
114 cookie=pb.cookie,
115 match=make_loxi_match(pb2dict(pb.match)),
116 data=pb.data
117 )
118 return packet_in
119
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700120
Zsolt Haraszti66862032016-11-28 14:28:39 -0800121def ofp_group_entry_to_loxi_group_entry(pb):
122 return of13.group_stats_entry(
123 group_id=pb.stats.group_id,
124 ref_count=pb.stats.ref_count,
125 packet_count=pb.stats.packet_count,
126 byte_count=pb.stats.byte_count,
127 duration_sec=pb.stats.duration_sec,
128 duration_nsec=pb.stats.duration_nsec,
129 bucket_stats=[to_loxi(bstat) for bstat in pb.stats.bucket_stats])
130
Zsolt Haraszti6a5107c2017-01-09 23:42:41 -0800131
Zsolt Haraszti66862032016-11-28 14:28:39 -0800132def ofp_bucket_counter_to_loxy_bucket_counter(pb):
133 return of13.bucket_counter(
134 packet_count=pb.packet_count,
135 byte_count=pb.byte_count)
136
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700137
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700138to_loxi_converters = {
139 pb2.ofp_port: ofp_port_to_loxi_port_desc,
Zsolt Haraszti217a12e2016-12-19 16:37:55 -0800140 pb2.ofp_port_status: ofp_port_status_to_loxi_port_status,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700141 pb2.ofp_flow_stats: ofp_flow_stats_to_loxi_flow_stats,
142 pb2.ofp_packet_in: ofp_packet_in_to_loxi_packet_in,
Zsolt Haraszti66862032016-11-28 14:28:39 -0800143 pb2.ofp_group_entry: ofp_group_entry_to_loxi_group_entry,
144 pb2.ofp_bucket_counter: ofp_bucket_counter_to_loxy_bucket_counter
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700145}
146
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700147
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700148def loxi_flow_mod_to_ofp_flow_mod(lo):
149 return pb2.ofp_flow_mod(
150 cookie=lo.cookie,
151 cookie_mask=lo.cookie_mask,
152 table_id=lo.table_id,
153 command=lo._command,
154 idle_timeout=lo.idle_timeout,
155 hard_timeout=lo.hard_timeout,
156 priority=lo.priority,
157 buffer_id=lo.buffer_id,
158 out_port=lo.out_port,
159 out_group=lo.out_group,
160 flags=lo.flags,
161 match=to_grpc(lo.match),
162 instructions=[to_grpc(i) for i in lo.instructions])
163
164
165def loxi_group_mod_to_ofp_group_mod(lo):
166 return pb2.ofp_group_mod(
167 command=lo.command,
Zsolt Haraszti9125b1a2016-10-24 22:54:33 -0700168 type=lo.group_type,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700169 group_id=lo.group_id,
170 buckets=[to_grpc(b) for b in lo.buckets])
171
172
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700173def loxi_packet_out_to_ofp_packet_out(lo):
174 return pb2.ofp_packet_out(
175 buffer_id=lo.buffer_id,
176 in_port=lo.in_port,
177 actions=[to_grpc(a) for a in lo.actions],
178 data=lo.data)
179
180
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700181def loxi_match_v3_to_ofp_match(lo):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700182 return pb2.ofp_match(
183 type=pb2.OFPMT_OXM,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700184 oxm_fields=[to_grpc(f) for f in lo.oxm_list])
185
186
187def loxi_bucket_to_ofp_bucket(lo):
188 return pb2.ofp_bucket(
189 weight=lo.weight,
190 watch_port=lo.watch_port,
191 watch_group=lo.watch_group,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700192 actions=[to_grpc(a) for a in lo.actions])
193
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700194
195def loxi_oxm_eth_type_to_ofp_oxm(lo):
196 return pb2.ofp_oxm_field(
197 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
198 ofb_field=pb2.ofp_oxm_ofb_field(
199 type=pb2.OFPXMT_OFB_ETH_TYPE,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700200 eth_type=lo.value))
201
202
203def loxi_oxm_in_port_to_ofp_oxm(lo):
204 return pb2.ofp_oxm_field(
205 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
206 ofb_field=pb2.ofp_oxm_ofb_field(
207 type=pb2.OFPXMT_OFB_IN_PORT,
208 port=lo.value))
209
210
211def loxi_oxm_ip_proto_to_ofp_oxm(lo):
212 return pb2.ofp_oxm_field(
213 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
214 ofb_field=pb2.ofp_oxm_ofb_field(
215 type=pb2.OFPXMT_OFB_IP_PROTO,
216 ip_proto=lo.value))
217
218
219def loxi_oxm_vlan_vid_to_ofp_oxm(lo):
220 return pb2.ofp_oxm_field(
221 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
222 ofb_field=pb2.ofp_oxm_ofb_field(
223 type=pb2.OFPXMT_OFB_VLAN_VID,
224 vlan_vid=lo.value))
225
226
227def loxi_oxm_vlan_pcp_to_ofp_oxm(lo):
228 return pb2.ofp_oxm_field(
229 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
230 ofb_field=pb2.ofp_oxm_ofb_field(
231 type=pb2.OFPXMT_OFB_VLAN_PCP,
232 vlan_pcp=lo.value))
233
234
235def loxi_oxm_ipv4_dst_to_ofp_oxm(lo):
236 return pb2.ofp_oxm_field(
237 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
238 ofb_field=pb2.ofp_oxm_ofb_field(
239 type=pb2.OFPXMT_OFB_IPV4_DST,
240 ipv4_dst=lo.value))
241
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700242
Zsolt Haraszti6a5107c2017-01-09 23:42:41 -0800243def loxi_oxm_udp_dst_to_ofp_oxm(lo):
244 return pb2.ofp_oxm_field(
245 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
246 ofb_field=pb2.ofp_oxm_ofb_field(
247 type=pb2.OFPXMT_OFB_UDP_DST,
248 udp_dst=lo.value))
249
250
251def loxi_oxm_metadata_to_ofp_oxm(lo):
252 return pb2.ofp_oxm_field(
253 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
254 ofb_field=pb2.ofp_oxm_ofb_field(
255 type=pb2.OFPXMT_OFB_METADATA,
256 table_metadata=lo.value))
257
258
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700259def loxi_apply_actions_to_ofp_instruction(lo):
260 return pb2.ofp_instruction(
261 type=pb2.OFPIT_APPLY_ACTIONS,
262 actions=pb2.ofp_instruction_actions(
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700263 actions=[to_grpc(a) for a in lo.actions]))
264
265
266def loxi_goto_table_to_ofp_instruction(lo):
267 return pb2.ofp_instruction(
268 type=pb2.OFPIT_GOTO_TABLE,
269 goto_table=pb2.ofp_instruction_goto_table(table_id=lo.table_id))
270
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700271
272def loxi_output_action_to_ofp_action(lo):
273 return pb2.ofp_action(
274 type=pb2.OFPAT_OUTPUT,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700275 output=pb2.ofp_action_output(port=lo.port, max_len=lo.max_len))
276
277
278def loxi_group_action_to_ofp_action(lo):
279 return pb2.ofp_action(
280 type=pb2.OFPAT_GROUP,
281 group=pb2.ofp_action_group(group_id=lo.group_id))
282
283
284def loxi_set_field_action_to_ofp_action(lo):
285 return pb2.ofp_action(
286 type=pb2.OFPAT_SET_FIELD,
287 set_field=pb2.ofp_action_set_field(field=to_grpc(lo.field)))
288
289
290def loxi_pop_vlan_action_to_ofp_action(lo):
291 return pb2.ofp_action(type=pb2.OFPAT_POP_VLAN)
292
293
294def loxi_push_vlan_action_to_ofp_action(lo):
295 return pb2.ofp_action(
296 type=pb2.OFPAT_PUSH_VLAN,
297 push=pb2.ofp_action_push(ethertype=lo.ethertype))
298
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700299
300to_grpc_converters = {
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700301
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700302 of13.message.flow_add: loxi_flow_mod_to_ofp_flow_mod,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700303 of13.message.flow_delete: loxi_flow_mod_to_ofp_flow_mod,
304 of13.message.flow_delete_strict: loxi_flow_mod_to_ofp_flow_mod,
305 of13.message.flow_modify: loxi_flow_mod_to_ofp_flow_mod,
306 of13.message.flow_modify_strict: loxi_flow_mod_to_ofp_flow_mod,
307
308 of13.message.group_add: loxi_group_mod_to_ofp_group_mod,
309 of13.message.group_delete: loxi_group_mod_to_ofp_group_mod,
310 of13.message.group_modify: loxi_group_mod_to_ofp_group_mod,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700311 of13.message.packet_out: loxi_packet_out_to_ofp_packet_out,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700312
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700313 of13.common.match_v3: loxi_match_v3_to_ofp_match,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700314 of13.common.bucket: loxi_bucket_to_ofp_bucket,
315
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700316 of13.oxm.eth_type: loxi_oxm_eth_type_to_ofp_oxm,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700317 of13.oxm.in_port: loxi_oxm_in_port_to_ofp_oxm,
318 of13.oxm.ip_proto: loxi_oxm_ip_proto_to_ofp_oxm,
319 of13.oxm.vlan_vid: loxi_oxm_vlan_vid_to_ofp_oxm,
320 of13.oxm.vlan_pcp: loxi_oxm_vlan_pcp_to_ofp_oxm,
321 of13.oxm.ipv4_dst: loxi_oxm_ipv4_dst_to_ofp_oxm,
Zsolt Haraszti6a5107c2017-01-09 23:42:41 -0800322 of13.oxm.udp_dst: loxi_oxm_udp_dst_to_ofp_oxm,
323 of13.oxm.metadata: loxi_oxm_metadata_to_ofp_oxm,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700324
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700325 of13.instruction.apply_actions: loxi_apply_actions_to_ofp_instruction,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700326 of13.instruction.goto_table: loxi_goto_table_to_ofp_instruction,
327
328 of13.action.output: loxi_output_action_to_ofp_action,
329 of13.action.group: loxi_group_action_to_ofp_action,
330 of13.action.set_field: loxi_set_field_action_to_ofp_action,
331 of13.action.pop_vlan: loxi_pop_vlan_action_to_ofp_action,
332 of13.action.push_vlan: loxi_push_vlan_action_to_ofp_action,
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700333}