blob: 772e5d74555e6bd34ba404d3cd50f7b492a87105 [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
58def ofp_flow_stats_to_loxi_flow_stats(pb):
59 kw = pb2dict(pb)
60 print 'QQQQQQQQQQQ', kw
61
62 def make_loxi_match(match):
63 assert match['type'] == pb2.OFPMT_OXM
64 loxi_match_fields = []
65 for oxm_field in match['oxm_fields']:
66 assert oxm_field['oxm_class'] == pb2.OFPXMC_OPENFLOW_BASIC
67 ofb_field = oxm_field['ofb_field']
68 field_type = ofb_field.get('type', 0)
69 if field_type == pb2.OFPXMT_OFB_ETH_TYPE:
70 loxi_match_fields.append(
71 of13.oxm.eth_type(value=ofb_field['eth_type']))
72 else:
73 raise NotImplementedError(
74 'OXM match field for type %s' % field_type)
75 return of13.match_v3(oxm_list=loxi_match_fields)
76
77 def make_loxi_action(a):
78 print 'AAAAAAAAAA', a
79 type = a.get('type', 0)
80 if type == pb2.OFPAT_OUTPUT:
81 output = a['output']
82 return of13.action.output(**output)
83 else:
84 raise NotImplementedError(
85 'Action decoder for action OFPAT_* %d' % type)
86
87 def make_loxi_instruction(inst):
88 print 'IIIIIIIIIIIIIIII', inst
89 type = inst['type']
90 if type == pb2.OFPIT_APPLY_ACTIONS:
91 return of13.instruction.apply_actions(
92 actions=[make_loxi_action(a)
93 for a in inst['actions']['actions']])
94 else:
95 raise NotImplementedError('Instruction type %d' % type)
96
97 kw['match'] = make_loxi_match(kw['match'])
98 kw['instructions'] = [make_loxi_instruction(i) for i in kw['instructions']]
99 return of13.flow_stats_entry(**kw)
100
101to_loxi_converters = {
102 pb2.ofp_port: ofp_port_to_loxi_port_desc,
103 pb2.ofp_flow_stats: ofp_flow_stats_to_loxi_flow_stats
104}
105
106def loxi_flow_mod_to_ofp_flow_mod(loxi_flow_mod):
107 return pb2.ofp_flow_mod(
108 cookie=loxi_flow_mod.cookie,
109 cookie_mask=loxi_flow_mod.cookie_mask,
110 table_id=loxi_flow_mod.table_id,
111 command=loxi_flow_mod._command,
112 idle_timeout=loxi_flow_mod.idle_timeout,
113 hard_timeout=loxi_flow_mod.hard_timeout,
114 priority=loxi_flow_mod.priority,
115 buffer_id=loxi_flow_mod.buffer_id,
116 out_port=loxi_flow_mod.out_port,
117 out_group=loxi_flow_mod.out_group,
118 flags=loxi_flow_mod.flags,
119 match=to_grpc(loxi_flow_mod.match),
120 instructions=[to_grpc(i) for i in loxi_flow_mod.instructions]
121 )
122
123def loxi_match_v3_to_ofp_match(loxi_match):
124 return pb2.ofp_match(
125 type=pb2.OFPMT_OXM,
126 oxm_fields=[to_grpc(f) for f in loxi_match.oxm_list]
127 )
128
129def loxi_oxm_eth_type_to_ofp_oxm(lo):
130 return pb2.ofp_oxm_field(
131 oxm_class=pb2.OFPXMC_OPENFLOW_BASIC,
132 ofb_field=pb2.ofp_oxm_ofb_field(
133 type=pb2.OFPXMT_OFB_ETH_TYPE,
134 eth_type=lo.value
135 )
136 )
137
138def loxi_apply_actions_to_ofp_instruction(lo):
139 return pb2.ofp_instruction(
140 type=pb2.OFPIT_APPLY_ACTIONS,
141 actions=pb2.ofp_instruction_actions(
142 actions=[to_grpc(a) for a in lo.actions]
143 )
144 )
145
146def loxi_output_action_to_ofp_action(lo):
147 return pb2.ofp_action(
148 type=pb2.OFPAT_OUTPUT,
149 output=pb2.ofp_action_output(
150 port=lo.port,
151 max_len=lo.max_len
152 )
153 )
154
155to_grpc_converters = {
156 of13.message.flow_add: loxi_flow_mod_to_ofp_flow_mod,
157 of13.common.match_v3: loxi_match_v3_to_ofp_match,
158 of13.oxm.eth_type: loxi_oxm_eth_type_to_ofp_oxm,
159 of13.instruction.apply_actions: loxi_apply_actions_to_ofp_instruction,
160 of13.action.output: loxi_output_action_to_ofp_action
161}