blob: 9ab9636b4138fe6e8cc1358f23bacb6c65f768d4 [file] [log] [blame]
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -07001#
2# Copyright 2016 the original author or authors.
3#
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 Haraszticd22adc2016-10-25 00:13:06 -070058def make_loxi_match(match):
Zsolt Haraszti66862032016-11-28 14:28:39 -080059 assert match.get('type', pb2.OFPMT_STANDARD) == pb2.OFPMT_OXM
Zsolt Haraszticd22adc2016-10-25 00:13:06 -070060 loxi_match_fields = []
Zsolt Haraszti66862032016-11-28 14:28:39 -080061 for oxm_field in match.get('oxm_fields', []):
Zsolt Haraszticd22adc2016-10-25 00:13:06 -070062 assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
63 ofb_field = oxm_field['ofb_field']
64 field_type = ofb_field.get('type', 0)
65 if field_type == pb2.OFPXMT_OFB_ETH_TYPE:
66 loxi_match_fields.append(
67 of13.oxm.eth_type(value=ofb_field['eth_type']))
68 else:
69 raise NotImplementedError(
70 'OXM match field for type %s' % field_type)
71 return of13.match_v3(oxm_list=loxi_match_fields)
72
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070073def ofp_flow_stats_to_loxi_flow_stats(pb):
74 kw = pb2dict(pb)
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070075
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070076 def make_loxi_action(a):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070077 type = a.get('type', 0)
78 if type == pb2.OFPAT_OUTPUT:
79 output = a['output']
80 return of13.action.output(**output)
81 else:
82 raise NotImplementedError(
83 'Action decoder for action OFPAT_* %d' % type)
84
85 def make_loxi_instruction(inst):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070086 type = inst['type']
87 if type == pb2.OFPIT_APPLY_ACTIONS:
88 return of13.instruction.apply_actions(
89 actions=[make_loxi_action(a)
90 for a in inst['actions']['actions']])
91 else:
92 raise NotImplementedError('Instruction type %d' % type)
93
94 kw['match'] = make_loxi_match(kw['match'])
95 kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
Zsolt Haraszti66862032016-11-28 14:28:39 -080096 del kw['id']
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -070097 return of13.flow_stats_entry(**kw)
98
Zsolt Haraszticd22adc2016-10-25 00:13:06 -070099def ofp_packet_in_to_loxi_packet_in(pb):
100 kw = pb2dict(pb)
101 if 'match' in kw:
102 kw['match'] = make_loxi_match(kw['match'])
103 return of13.message.packet_in(**kw)
104
Zsolt Haraszti66862032016-11-28 14:28:39 -0800105def ofp_group_entry_to_loxi_group_entry(pb):
106 return of13.group_stats_entry(
107 group_id=pb.stats.group_id,
108 ref_count=pb.stats.ref_count,
109 packet_count=pb.stats.packet_count,
110 byte_count=pb.stats.byte_count,
111 duration_sec=pb.stats.duration_sec,
112 duration_nsec=pb.stats.duration_nsec,
113 bucket_stats=[to_loxi(bstat) for bstat in pb.stats.bucket_stats])
114
115def ofp_bucket_counter_to_loxy_bucket_counter(pb):
116 return of13.bucket_counter(
117 packet_count=pb.packet_count,
118 byte_count=pb.byte_count)
119
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700120
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700121to_loxi_converters = {
122 pb2.ofp_port: ofp_port_to_loxi_port_desc,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700123 pb2.ofp_flow_stats: ofp_flow_stats_to_loxi_flow_stats,
124 pb2.ofp_packet_in: ofp_packet_in_to_loxi_packet_in,
Zsolt Haraszti66862032016-11-28 14:28:39 -0800125 pb2.ofp_group_entry: ofp_group_entry_to_loxi_group_entry,
126 pb2.ofp_bucket_counter: ofp_bucket_counter_to_loxy_bucket_counter
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700127}
128
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700129
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700130def loxi_flow_mod_to_ofp_flow_mod(lo):
131 return pb2.ofp_flow_mod(
132 cookie=lo.cookie,
133 cookie_mask=lo.cookie_mask,
134 table_id=lo.table_id,
135 command=lo._command,
136 idle_timeout=lo.idle_timeout,
137 hard_timeout=lo.hard_timeout,
138 priority=lo.priority,
139 buffer_id=lo.buffer_id,
140 out_port=lo.out_port,
141 out_group=lo.out_group,
142 flags=lo.flags,
143 match=to_grpc(lo.match),
144 instructions=[to_grpc(i) for i in lo.instructions])
145
146
147def loxi_group_mod_to_ofp_group_mod(lo):
148 return pb2.ofp_group_mod(
149 command=lo.command,
Zsolt Haraszti9125b1a2016-10-24 22:54:33 -0700150 type=lo.group_type,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700151 group_id=lo.group_id,
152 buckets=[to_grpc(b) for b in lo.buckets])
153
154
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700155def loxi_packet_out_to_ofp_packet_out(lo):
156 return pb2.ofp_packet_out(
157 buffer_id=lo.buffer_id,
158 in_port=lo.in_port,
159 actions=[to_grpc(a) for a in lo.actions],
160 data=lo.data)
161
162
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700163def loxi_match_v3_to_ofp_match(lo):
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700164 return pb2.ofp_match(
165 type=pb2.OFPMT_OXM,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700166 oxm_fields=[to_grpc(f) for f in lo.oxm_list])
167
168
169def loxi_bucket_to_ofp_bucket(lo):
170 return pb2.ofp_bucket(
171 weight=lo.weight,
172 watch_port=lo.watch_port,
173 watch_group=lo.watch_group,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700174 actions=[to_grpc(a) for a in lo.actions])
175
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700176
177def loxi_oxm_eth_type_to_ofp_oxm(lo):
178 return pb2.ofp_oxm_field(
179 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
180 ofb_field=pb2.ofp_oxm_ofb_field(
181 type=pb2.OFPXMT_OFB_ETH_TYPE,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700182 eth_type=lo.value))
183
184
185def loxi_oxm_in_port_to_ofp_oxm(lo):
186 return pb2.ofp_oxm_field(
187 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
188 ofb_field=pb2.ofp_oxm_ofb_field(
189 type=pb2.OFPXMT_OFB_IN_PORT,
190 port=lo.value))
191
192
193def loxi_oxm_ip_proto_to_ofp_oxm(lo):
194 return pb2.ofp_oxm_field(
195 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
196 ofb_field=pb2.ofp_oxm_ofb_field(
197 type=pb2.OFPXMT_OFB_IP_PROTO,
198 ip_proto=lo.value))
199
200
201def loxi_oxm_vlan_vid_to_ofp_oxm(lo):
202 return pb2.ofp_oxm_field(
203 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
204 ofb_field=pb2.ofp_oxm_ofb_field(
205 type=pb2.OFPXMT_OFB_VLAN_VID,
206 vlan_vid=lo.value))
207
208
209def loxi_oxm_vlan_pcp_to_ofp_oxm(lo):
210 return pb2.ofp_oxm_field(
211 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
212 ofb_field=pb2.ofp_oxm_ofb_field(
213 type=pb2.OFPXMT_OFB_VLAN_PCP,
214 vlan_pcp=lo.value))
215
216
217def loxi_oxm_ipv4_dst_to_ofp_oxm(lo):
218 return pb2.ofp_oxm_field(
219 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
220 ofb_field=pb2.ofp_oxm_ofb_field(
221 type=pb2.OFPXMT_OFB_IPV4_DST,
222 ipv4_dst=lo.value))
223
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700224
225def loxi_apply_actions_to_ofp_instruction(lo):
226 return pb2.ofp_instruction(
227 type=pb2.OFPIT_APPLY_ACTIONS,
228 actions=pb2.ofp_instruction_actions(
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700229 actions=[to_grpc(a) for a in lo.actions]))
230
231
232def loxi_goto_table_to_ofp_instruction(lo):
233 return pb2.ofp_instruction(
234 type=pb2.OFPIT_GOTO_TABLE,
235 goto_table=pb2.ofp_instruction_goto_table(table_id=lo.table_id))
236
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700237
238def loxi_output_action_to_ofp_action(lo):
239 return pb2.ofp_action(
240 type=pb2.OFPAT_OUTPUT,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700241 output=pb2.ofp_action_output(port=lo.port, max_len=lo.max_len))
242
243
244def loxi_group_action_to_ofp_action(lo):
245 return pb2.ofp_action(
246 type=pb2.OFPAT_GROUP,
247 group=pb2.ofp_action_group(group_id=lo.group_id))
248
249
250def loxi_set_field_action_to_ofp_action(lo):
251 return pb2.ofp_action(
252 type=pb2.OFPAT_SET_FIELD,
253 set_field=pb2.ofp_action_set_field(field=to_grpc(lo.field)))
254
255
256def loxi_pop_vlan_action_to_ofp_action(lo):
257 return pb2.ofp_action(type=pb2.OFPAT_POP_VLAN)
258
259
260def loxi_push_vlan_action_to_ofp_action(lo):
261 return pb2.ofp_action(
262 type=pb2.OFPAT_PUSH_VLAN,
263 push=pb2.ofp_action_push(ethertype=lo.ethertype))
264
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700265
266to_grpc_converters = {
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700267
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700268 of13.message.flow_add: loxi_flow_mod_to_ofp_flow_mod,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700269 of13.message.flow_delete: loxi_flow_mod_to_ofp_flow_mod,
270 of13.message.flow_delete_strict: loxi_flow_mod_to_ofp_flow_mod,
271 of13.message.flow_modify: loxi_flow_mod_to_ofp_flow_mod,
272 of13.message.flow_modify_strict: loxi_flow_mod_to_ofp_flow_mod,
273
274 of13.message.group_add: loxi_group_mod_to_ofp_group_mod,
275 of13.message.group_delete: loxi_group_mod_to_ofp_group_mod,
276 of13.message.group_modify: loxi_group_mod_to_ofp_group_mod,
Zsolt Haraszticd22adc2016-10-25 00:13:06 -0700277 of13.message.packet_out: loxi_packet_out_to_ofp_packet_out,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700278
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700279 of13.common.match_v3: loxi_match_v3_to_ofp_match,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700280 of13.common.bucket: loxi_bucket_to_ofp_bucket,
281
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700282 of13.oxm.eth_type: loxi_oxm_eth_type_to_ofp_oxm,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700283 of13.oxm.in_port: loxi_oxm_in_port_to_ofp_oxm,
284 of13.oxm.ip_proto: loxi_oxm_ip_proto_to_ofp_oxm,
285 of13.oxm.vlan_vid: loxi_oxm_vlan_vid_to_ofp_oxm,
286 of13.oxm.vlan_pcp: loxi_oxm_vlan_pcp_to_ofp_oxm,
287 of13.oxm.ipv4_dst: loxi_oxm_ipv4_dst_to_ofp_oxm,
288
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700289 of13.instruction.apply_actions: loxi_apply_actions_to_ofp_instruction,
Zsolt Haraszti8a774382016-10-24 18:25:54 -0700290 of13.instruction.goto_table: loxi_goto_table_to_ofp_instruction,
291
292 of13.action.output: loxi_output_action_to_ofp_action,
293 of13.action.group: loxi_group_action_to_ofp_action,
294 of13.action.set_field: loxi_set_field_action_to_ofp_action,
295 of13.action.pop_vlan: loxi_pop_vlan_action_to_ofp_action,
296 of13.action.push_vlan: loxi_push_vlan_action_to_ofp_action,
Zsolt Haraszti023ea7c2016-10-16 19:30:34 -0700297}