blob: 2a221b7cfddceefc60a7c7d391cdaf3ce3521069 [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__
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -080046 converter = to_loxi_converters[cls.__name__]
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070047 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 Haraszti3578a1c2017-01-10 15:29:02 -080064def make_loxi_field(oxm_field):
65 assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
66 ofb_field = oxm_field['ofb_field']
67 field_type = ofb_field.get('type', 0)
68
69 if field_type == pb2.OFPXMT_OFB_ETH_TYPE:
70 return (
71 of13.oxm.eth_type(value=ofb_field['eth_type']))
72
73 elif field_type == pb2.OFPXMT_OFB_IN_PORT:
74 return (
75 of13.oxm.in_port(value=ofb_field['port']))
76
77 elif field_type == pb2.OFPXMT_OFB_IP_PROTO:
78 return (
79 of13.oxm.ip_proto(value=ofb_field['ip_proto']))
80
81 elif field_type == pb2.OFPXMT_OFB_VLAN_VID:
82 return (
83 of13.oxm.vlan_vid(value=ofb_field['vlan_vid']))
84
85 elif field_type == pb2.OFPXMT_OFB_VLAN_PCP:
86 return (
87 of13.oxm.vlan_pcp(value=ofb_field['vlan_pcp']))
88
89 elif field_type == pb2.OFPXMT_OFB_IPV4_SRC:
90 return (
91 of13.oxm.ipv4_src(value=ofb_field['ipv4_src']))
92
93 elif field_type == pb2.OFPXMT_OFB_IPV4_DST:
94 return (
95 of13.oxm.ipv4_dst(value=ofb_field['ipv4_dst']))
96
97 elif field_type == pb2.OFPXMT_OFB_UDP_SRC:
98 return (
99 of13.oxm.udp_src(value=ofb_field['udp_src']))
100
101 elif field_type == pb2.OFPXMT_OFB_UDP_DST:
102 return (
103 of13.oxm.udp_dst(value=ofb_field['udp_dst']))
104
105 elif field_type == pb2.OFPXMT_OFB_METADATA:
106 return (
107 of13.oxm.metadata(value=ofb_field['table_metadata']))
108
109 else:
110 raise NotImplementedError(
111 'OXM match field for type %s' % field_type)
112
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700113def make_loxi_match(match):
Zsolt Haraszti66862032016-11-28 14:28:39 -0800114 assert match.get('type', pb2.OFPMT_STANDARD) == pb2.OFPMT_OXM
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700115 loxi_match_fields = []
Zsolt Haraszti66862032016-11-28 14:28:39 -0800116 for oxm_field in match.get('oxm_fields', []):
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -0800117 loxi_match_fields.append(make_loxi_field(oxm_field))
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700118 return of13.match_v3(oxm_list=loxi_match_fields)
119
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700120def ofp_flow_stats_to_loxi_flow_stats(pb):
121 kw = pb2dict(pb)
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700122
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700123 def make_loxi_action(a):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700124 type = a.get('type', 0)
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -0800125
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700126 if type == pb2.OFPAT_OUTPUT:
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -0800127 output_kws = a['output']
128 return of13.action.output(**output_kws)
129
130 elif type == pb2.OFPAT_POP_VLAN:
131 return of13.action.pop_vlan()
132
133 elif type == pb2.OFPAT_PUSH_VLAN:
134 push_vlan_kws = a['push']
135 return of13.action.push_vlan(**push_vlan_kws)
136
137 elif type == pb2.OFPAT_SET_FIELD:
138 loxi_field = make_loxi_field(a['set_field']['field'])
139 return of13.action.set_field(loxi_field)
140
141 elif type == pb2.OFPAT_GROUP:
142 group_kws = a['group']
143 return of13.action.group(**group_kws)
144
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700145 else:
146 raise NotImplementedError(
147 'Action decoder for action OFPAT_* %d' % type)
148
149 def make_loxi_instruction(inst):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700150 type = inst['type']
151 if type == pb2.OFPIT_APPLY_ACTIONS:
152 return of13.instruction.apply_actions(
153 actions=[make_loxi_action(a)
154 for a in inst['actions']['actions']])
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -0800155 elif type == pb2.OFPIT_GOTO_TABLE:
156 return of13.instruction.goto_table(
157 table_id=inst['goto_table']['table_id'])
158
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700159 else:
160 raise NotImplementedError('Instruction type %d' % type)
161
162 kw['match'] = make_loxi_match(kw['match'])
163 kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
Zsolt Haraszti66862032016-11-28 14:28:39 -0800164 del kw['id']
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700165 return of13.flow_stats_entry(**kw)
166
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -0800167
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700168def ofp_packet_in_to_loxi_packet_in(pb):
Zsolt Haraszti8925d1f2016-12-21 00:45:19 -0800169 packet_in = of13.message.packet_in(
170 buffer_id=pb.buffer_id,
171 reason=pb.reason,
172 table_id=pb.table_id,
173 cookie=pb.cookie,
174 match=make_loxi_match(pb2dict(pb.match)),
175 data=pb.data
176 )
177 return packet_in
178
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700179
Zsolt Haraszti66862032016-11-28 14:28:39 -0800180def ofp_group_entry_to_loxi_group_entry(pb):
181 return of13.group_stats_entry(
182 group_id=pb.stats.group_id,
183 ref_count=pb.stats.ref_count,
184 packet_count=pb.stats.packet_count,
185 byte_count=pb.stats.byte_count,
186 duration_sec=pb.stats.duration_sec,
187 duration_nsec=pb.stats.duration_nsec,
188 bucket_stats=[to_loxi(bstat) for bstat in pb.stats.bucket_stats])
189
Zsolt Haraszti6a5107c2017-01-09 23:42:41 -0800190
Zsolt Haraszti66862032016-11-28 14:28:39 -0800191def ofp_bucket_counter_to_loxy_bucket_counter(pb):
192 return of13.bucket_counter(
193 packet_count=pb.packet_count,
194 byte_count=pb.byte_count)
195
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700196
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700197to_loxi_converters = {
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -0800198 'ofp_port': ofp_port_to_loxi_port_desc,
199 'ofp_port_status': ofp_port_status_to_loxi_port_status,
200 'ofp_flow_stats': ofp_flow_stats_to_loxi_flow_stats,
201 'ofp_packet_in': ofp_packet_in_to_loxi_packet_in,
202 'ofp_group_entry': ofp_group_entry_to_loxi_group_entry,
203 'ofp_bucket_counter': ofp_bucket_counter_to_loxy_bucket_counter
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700204}
205
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700206
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700207def loxi_flow_mod_to_ofp_flow_mod(lo):
208 return pb2.ofp_flow_mod(
209 cookie=lo.cookie,
210 cookie_mask=lo.cookie_mask,
211 table_id=lo.table_id,
212 command=lo._command,
213 idle_timeout=lo.idle_timeout,
214 hard_timeout=lo.hard_timeout,
215 priority=lo.priority,
216 buffer_id=lo.buffer_id,
217 out_port=lo.out_port,
218 out_group=lo.out_group,
219 flags=lo.flags,
220 match=to_grpc(lo.match),
221 instructions=[to_grpc(i) for i in lo.instructions])
222
223
224def loxi_group_mod_to_ofp_group_mod(lo):
225 return pb2.ofp_group_mod(
226 command=lo.command,
Zsolt Haraszti9125b1a2016-10-24 22:54:33 -0700227 type=lo.group_type,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700228 group_id=lo.group_id,
229 buckets=[to_grpc(b) for b in lo.buckets])
230
231
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700232def loxi_packet_out_to_ofp_packet_out(lo):
233 return pb2.ofp_packet_out(
234 buffer_id=lo.buffer_id,
235 in_port=lo.in_port,
236 actions=[to_grpc(a) for a in lo.actions],
237 data=lo.data)
238
239
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700240def loxi_match_v3_to_ofp_match(lo):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700241 return pb2.ofp_match(
242 type=pb2.OFPMT_OXM,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700243 oxm_fields=[to_grpc(f) for f in lo.oxm_list])
244
245
246def loxi_bucket_to_ofp_bucket(lo):
247 return pb2.ofp_bucket(
248 weight=lo.weight,
249 watch_port=lo.watch_port,
250 watch_group=lo.watch_group,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700251 actions=[to_grpc(a) for a in lo.actions])
252
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700253
254def loxi_oxm_eth_type_to_ofp_oxm(lo):
255 return pb2.ofp_oxm_field(
256 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
257 ofb_field=pb2.ofp_oxm_ofb_field(
258 type=pb2.OFPXMT_OFB_ETH_TYPE,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700259 eth_type=lo.value))
260
261
262def loxi_oxm_in_port_to_ofp_oxm(lo):
263 return pb2.ofp_oxm_field(
264 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
265 ofb_field=pb2.ofp_oxm_ofb_field(
266 type=pb2.OFPXMT_OFB_IN_PORT,
267 port=lo.value))
268
269
270def loxi_oxm_ip_proto_to_ofp_oxm(lo):
271 return pb2.ofp_oxm_field(
272 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
273 ofb_field=pb2.ofp_oxm_ofb_field(
274 type=pb2.OFPXMT_OFB_IP_PROTO,
275 ip_proto=lo.value))
276
277
278def loxi_oxm_vlan_vid_to_ofp_oxm(lo):
279 return pb2.ofp_oxm_field(
280 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
281 ofb_field=pb2.ofp_oxm_ofb_field(
282 type=pb2.OFPXMT_OFB_VLAN_VID,
283 vlan_vid=lo.value))
284
285
286def loxi_oxm_vlan_pcp_to_ofp_oxm(lo):
287 return pb2.ofp_oxm_field(
288 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
289 ofb_field=pb2.ofp_oxm_ofb_field(
290 type=pb2.OFPXMT_OFB_VLAN_PCP,
291 vlan_pcp=lo.value))
292
293
294def loxi_oxm_ipv4_dst_to_ofp_oxm(lo):
295 return pb2.ofp_oxm_field(
296 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
297 ofb_field=pb2.ofp_oxm_ofb_field(
298 type=pb2.OFPXMT_OFB_IPV4_DST,
299 ipv4_dst=lo.value))
300
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700301
Zsolt Haraszti6a5107c2017-01-09 23:42:41 -0800302def loxi_oxm_udp_dst_to_ofp_oxm(lo):
303 return pb2.ofp_oxm_field(
304 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
305 ofb_field=pb2.ofp_oxm_ofb_field(
306 type=pb2.OFPXMT_OFB_UDP_DST,
307 udp_dst=lo.value))
308
309
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -0800310def loxi_oxm_udp_src_to_ofp_oxm(lo):
311 return pb2.ofp_oxm_field(
312 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
313 ofb_field=pb2.ofp_oxm_ofb_field(
314 type=pb2.OFPXMT_OFB_UDP_SRC,
315 udp_src=lo.value))
316
317
Zsolt Haraszti6a5107c2017-01-09 23:42:41 -0800318def loxi_oxm_metadata_to_ofp_oxm(lo):
319 return pb2.ofp_oxm_field(
320 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
321 ofb_field=pb2.ofp_oxm_ofb_field(
322 type=pb2.OFPXMT_OFB_METADATA,
323 table_metadata=lo.value))
324
325
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700326def loxi_apply_actions_to_ofp_instruction(lo):
327 return pb2.ofp_instruction(
328 type=pb2.OFPIT_APPLY_ACTIONS,
329 actions=pb2.ofp_instruction_actions(
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700330 actions=[to_grpc(a) for a in lo.actions]))
331
332
333def loxi_goto_table_to_ofp_instruction(lo):
334 return pb2.ofp_instruction(
335 type=pb2.OFPIT_GOTO_TABLE,
336 goto_table=pb2.ofp_instruction_goto_table(table_id=lo.table_id))
337
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700338
339def loxi_output_action_to_ofp_action(lo):
340 return pb2.ofp_action(
341 type=pb2.OFPAT_OUTPUT,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700342 output=pb2.ofp_action_output(port=lo.port, max_len=lo.max_len))
343
344
345def loxi_group_action_to_ofp_action(lo):
346 return pb2.ofp_action(
347 type=pb2.OFPAT_GROUP,
348 group=pb2.ofp_action_group(group_id=lo.group_id))
349
350
351def loxi_set_field_action_to_ofp_action(lo):
352 return pb2.ofp_action(
353 type=pb2.OFPAT_SET_FIELD,
354 set_field=pb2.ofp_action_set_field(field=to_grpc(lo.field)))
355
356
357def loxi_pop_vlan_action_to_ofp_action(lo):
358 return pb2.ofp_action(type=pb2.OFPAT_POP_VLAN)
359
360
361def loxi_push_vlan_action_to_ofp_action(lo):
362 return pb2.ofp_action(
363 type=pb2.OFPAT_PUSH_VLAN,
364 push=pb2.ofp_action_push(ethertype=lo.ethertype))
365
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700366
367to_grpc_converters = {
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700368
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700369 of13.message.flow_add: loxi_flow_mod_to_ofp_flow_mod,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700370 of13.message.flow_delete: loxi_flow_mod_to_ofp_flow_mod,
371 of13.message.flow_delete_strict: loxi_flow_mod_to_ofp_flow_mod,
372 of13.message.flow_modify: loxi_flow_mod_to_ofp_flow_mod,
373 of13.message.flow_modify_strict: loxi_flow_mod_to_ofp_flow_mod,
374
375 of13.message.group_add: loxi_group_mod_to_ofp_group_mod,
376 of13.message.group_delete: loxi_group_mod_to_ofp_group_mod,
377 of13.message.group_modify: loxi_group_mod_to_ofp_group_mod,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700378 of13.message.packet_out: loxi_packet_out_to_ofp_packet_out,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700379
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700380 of13.common.match_v3: loxi_match_v3_to_ofp_match,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700381 of13.common.bucket: loxi_bucket_to_ofp_bucket,
382
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700383 of13.oxm.eth_type: loxi_oxm_eth_type_to_ofp_oxm,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700384 of13.oxm.in_port: loxi_oxm_in_port_to_ofp_oxm,
385 of13.oxm.ip_proto: loxi_oxm_ip_proto_to_ofp_oxm,
386 of13.oxm.vlan_vid: loxi_oxm_vlan_vid_to_ofp_oxm,
387 of13.oxm.vlan_pcp: loxi_oxm_vlan_pcp_to_ofp_oxm,
388 of13.oxm.ipv4_dst: loxi_oxm_ipv4_dst_to_ofp_oxm,
Zsolt Haraszti3578a1c2017-01-10 15:29:02 -0800389 of13.oxm.udp_src: loxi_oxm_udp_src_to_ofp_oxm,
Zsolt Haraszti6a5107c2017-01-09 23:42:41 -0800390 of13.oxm.udp_dst: loxi_oxm_udp_dst_to_ofp_oxm,
391 of13.oxm.metadata: loxi_oxm_metadata_to_ofp_oxm,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700392
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700393 of13.instruction.apply_actions: loxi_apply_actions_to_ofp_instruction,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700394 of13.instruction.goto_table: loxi_goto_table_to_ofp_instruction,
395
396 of13.action.output: loxi_output_action_to_ofp_action,
397 of13.action.group: loxi_group_action_to_ofp_action,
398 of13.action.set_field: loxi_set_field_action_to_ofp_action,
399 of13.action.pop_vlan: loxi_pop_vlan_action_to_ofp_action,
400 of13.action.push_vlan: loxi_push_vlan_action_to_ofp_action,
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700401}