blob: 35503e502d4e28fd03a5b66344e24878b59de2da [file] [log] [blame]
Yotam Harcholc742e202013-08-15 12:16:24 -07001import errno
Andreas Wundsam46d230f2013-08-02 22:24:06 -07002import loxi_utils.loxi_utils as loxi_utils
Andreas Wundsam27303462013-07-16 12:52:35 -07003import os
Andreas Wundsam27303462013-07-16 12:52:35 -07004import re
5import subprocess
6import time
7
8def name_c_to_camel(name):
9 """ 'of_stats_reply' -> 'ofStatsReply' """
10 name = re.sub(r'^_','', name)
11 tokens = name.split('_')
12 for i in range(1, len(tokens)):
13 tokens[i] = tokens[i].title()
14 return "".join(tokens)
15
16def name_c_to_caps_camel(name):
17 """ 'of_stats_reply' to 'OFStatsReply' """
18 camel = name_c_to_camel(name.title())
19 if camel.startswith('Of'):
20 return camel.replace('Of','OF',1)
21 else:
22 return camel
23
Andreas Wundsame916d6f2013-07-30 11:33:58 -070024java_primitive_types = set("byte char short int long".split(" "))
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070025
26### info table about java primitive types, for casting literals in the source code
27# { name : (signed?, length_in_bits) }
Andreas Wundsam46d230f2013-08-02 22:24:06 -070028java_primitives_info = {
29 'byte' : (True, 8),
30 'char' : (False, 16),
31 'short' : (True, 16),
32 'int' : (True, 32),
33 'long' : (True, 64),
34}
35
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070036def format_primitive_literal(t, value):
37 """ Format a primitive numeric literal for inclusion in the
38 java source code. Takes care of casting the literal
39 apropriately for correct representation despite Java's
40 signed-craziness
41 """
Andreas Wundsam46d230f2013-08-02 22:24:06 -070042 signed, bits = java_primitives_info[t]
43 max = (1 << bits)-1
44 if value > max:
45 raise Exception("Value %d to large for type %s" % (value, t))
46
47 if signed:
48 max_pos = (1 << (bits-1)) - 1
49
50 if value > max_pos:
51 if t == "long":
52 return str((1 << bits) - value)
53 else:
54 return "(%s) 0x%x" % (t, value)
55 else:
Andreas Wundsam2bf357c2013-08-03 22:50:40 -070056 return "0x%x%s" % (value, "L" if t=="long" else "")
Yotam Harchold7b84202013-07-26 16:08:10 -070057
Andreas Wundsame916d6f2013-07-30 11:33:58 -070058ANY = 0xFFFFFFFFFFFFFFFF
Yotam Harchold7b84202013-07-26 16:08:10 -070059
60class VersionOp:
61 def __init__(self, version=ANY, read=None, write=None):
62 self.version = version
63 self.read = read
64 self.write = write
Andreas Wundsame916d6f2013-07-30 11:33:58 -070065
Yotam Harchold7b84202013-07-26 16:08:10 -070066 def __str__(self):
67 return "[Version: %d, Read: '%s', Write: '%s']" % (self.version, self.read, self.write)
68
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070069### FIXME: This class should really be cleaned up
Andreas Wundsam27303462013-07-16 12:52:35 -070070class JType(object):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070071 """ Wrapper class to hold C to Java type conversion information. JTypes can have a 'public'
72 and or 'private' java type associated with them and can define how those types can be
73 read from and written to ChannelBuffers.
74
75 """
Andreas Wundsam2bf357c2013-08-03 22:50:40 -070076 def __init__(self, pub_type, priv_type=None, read_op=None, write_op=None):
Andreas Wundsam27303462013-07-16 12:52:35 -070077 self.pub_type = pub_type # the type we expose externally, e.g. 'U8'
78 if priv_type is None:
79 priv_type = pub_type
80 self.priv_type = priv_type # the internal storage type
Yotam Harchold7b84202013-07-26 16:08:10 -070081 self.ops = {}
Yotam Harchold7b84202013-07-26 16:08:10 -070082
Andreas Wundsam46d230f2013-08-02 22:24:06 -070083 def op(self, version=ANY, read=None, write=None, pub_type=ANY):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070084 """
85 define operations to be performed for reading and writing this type
86 (when read_op, write_op is called). The operations 'read' and 'write'
87 can either be strings ($name, and $version and $length will be replaced),
88 or callables (name, version and length) will be passed.
89
90 @param version int OF version to define operation for, or ANY for all
91 @param pub_type boolean whether to define operations for the public type (True), the
92 private type(False) or both (ALL)
93 @param read read expression (either string or callable)s
94 @param write write expression (either string or callable)
95 """
96
Andreas Wundsam46d230f2013-08-02 22:24:06 -070097 pub_types = [ pub_type ] if pub_type is not ANY else [ False, True ]
98 for pub_type in pub_types:
Andreas Wundsam2bf357c2013-08-03 22:50:40 -070099 self.ops[(version, pub_type)] = VersionOp(version, read, write)
Yotam Harchold7b84202013-07-26 16:08:10 -0700100 return self
Andreas Wundsam27303462013-07-16 12:52:35 -0700101
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700102 def format_value(self, value, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700103 # Format a constant value of this type, for inclusion in the java source code
104 # For primitive types, takes care of casting the value appropriately, to
105 # cope with java's signedness limitation
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700106 t = self.pub_type if pub_type else self.priv_type
107 if t in java_primitive_types:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700108 return format_primitive_literal(t, value)
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700109 else:
110 return value
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700111
Andreas Wundsam27303462013-07-16 12:52:35 -0700112 @property
113 def public_type(self):
114 """ return the public type """
115 return self.pub_type
116
117 def priv(self):
118 """ return the public type """
119 return self.priv_type
120
121 def has_priv(self):
122 """ Is the private type different from the public one?"""
123 return self.pub_type != self.priv_type
124
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700125 def read_op(self, version=None, length=None, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700126 """ return a Java stanza that reads a value of this JType from ChannelBuffer bb.
127 @param version int - OF wire version to generate expression for
128 @param pub_type boolean use this JTypes 'public' (True), or private (False) representation
129 @param length string, for operations that need it (e.g., read a list of unknown length)
130 Java expression evaluating to the byte length to be read. Defaults to the remainig
131 length of the message.
132 @return string containing generated Java expression.
133 """
Andreas Wundsam27303462013-07-16 12:52:35 -0700134 if length is None:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700135 # assumes that
136 # (1) length of the message has been read to 'length'
137 # (2) readerIndex at the start of the message has been stored in 'start'
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700138 length = "length - (bb.readerIndex() - start)";
Andreas Wundsam27303462013-07-16 12:52:35 -0700139
Yotam Harchold7b84202013-07-26 16:08:10 -0700140 ver = ANY if version is None else version.int_version
141 _read_op = None
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700142 if (ver, pub_type) in self.ops:
143 _read_op = self.ops[(ver, pub_type)].read or self.ops[(ANY, pub_type)].read
144 elif (ANY, pub_type) in self.ops:
145 _read_op = self.ops[(ANY, pub_type)].read
Yotam Harchold7b84202013-07-26 16:08:10 -0700146 if _read_op is None:
Andreas Wundsam951ada32013-08-01 22:05:38 -0700147 _read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type
Yotam Harchold7b84202013-07-26 16:08:10 -0700148 if callable(_read_op):
149 return _read_op(version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700150 else:
Yotam Harchold7b84202013-07-26 16:08:10 -0700151 return _read_op.replace("$length", str(length)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700152
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700153 def write_op(self, version=None, name=None, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700154 """ return a Java stanza that writes a value of this JType contained in Java expression
155 'name' to ChannelBuffer bb.
156 @param name string containing Java expression that evaluations to the value to be written
157 @param version int - OF wire version to generate expression for
158 @param pub_type boolean use this JTypes 'public' (True), or private (False) representation
159 @return string containing generated Java expression.
160 """
Yotam Harchold7b84202013-07-26 16:08:10 -0700161 ver = ANY if version is None else version.int_version
162 _write_op = None
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700163 if (ver, pub_type) in self.ops:
164 _write_op = self.ops[(ver, pub_type)].write or self.ops[(ANY, pub_type)].write
165 elif (ANY, pub_type) in self.ops:
166 _write_op = self.ops[(ANY, pub_type)].write
Yotam Harchold7b84202013-07-26 16:08:10 -0700167 if _write_op is None:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700168
Andreas Wundsam951ada32013-08-01 22:05:38 -0700169 _write_op = 'ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type
Yotam Harchold7b84202013-07-26 16:08:10 -0700170 if callable(_write_op):
171 return _write_op(version, name)
Andreas Wundsam27303462013-07-16 12:52:35 -0700172 else:
Yotam Harchold7b84202013-07-26 16:08:10 -0700173 return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700174
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700175 def skip_op(self, version=None, length=None):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700176 """ return a java stanza that skips an instance of JType in the input ChannelBuffer 'bb'.
177 This is used in the Reader implementations for virtual classes (because after the
178 discriminator field, the concrete Reader instance will re-read all the fields)
179 Currently just delegates to read_op + throws away the result."""
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700180 return self.read_op(version, length)
181
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700182 @property
183 def is_primitive(self):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700184 """ return true if the pub_type is a java primitive type (and thus needs
185 special treatment, because it doesn't have methods)"""
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700186 return self.pub_type in java_primitive_types
187
188 @property
189 def is_array(self):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700190 """ return true iff the pub_type is a Java array (and thus requires special
191 treament for equals / toString etc.) """
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700192 return self.pub_type.endswith("[]")
193
194
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700195##### Predefined JType mappings
196# FIXME: This list needs to be pruned / cleaned up. Most of these are schematic.
197
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700198u8 = JType('short', 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700199 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700200u8_list = JType('List<U8>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700201 .op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700202u16 = JType('int', 'short') \
203 .op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))', pub_type=True) \
204 .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
205u32 = JType('long', 'int') \
206 .op(read='U32.f(bb.readInt())', write='bb.writeInt(U32.t($name))', pub_type=True) \
207 .op(read='bb.readInt()', write='bb.writeInt($name)', pub_type=False)
208u32_list = JType('List<U32>', 'int[]') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700209 .op(read='ChannelUtils.readList(bb, $length, U32.READER)', write='ChannelUtils.writeList(bb, $name)')
Yotam Harchol5804f772013-08-21 17:35:31 -0700210u8obj = JType('U8', 'U8') \
211 .op(read='U8.of(bb.readByte())', write='bb.writeByte($name.getRaw())')
212u32obj = JType('U32', 'U32') \
213 .op(read='U32.of(bb.readInt())', write='bb.writeInt($name.getRaw())')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700214u64 = JType('U64', 'U64') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700215 .op(read='U64.of(bb.readLong())', write='bb.writeLong($name.getValue())')
216of_port = JType("OFPort") \
217 .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)") \
218 .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)")
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700219actions_list = JType('List<OFAction>') \
220 .op(read='ChannelUtils.readList(bb, $length, OFActionVer$version.READER)', write='ChannelUtils.writeList(bb, $name);')
221instructions_list = JType('List<OFInstruction>') \
222 .op(read='ChannelUtils.readList(bb, $length, OFInstructionVer$version.READER)', \
223 write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700224buckets_list = JType('List<OFBucket>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700225 .op(read='ChannelUtils.readList(bb, $length, OFBucketVer$version.READER)', write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700226port_desc_list = JType('List<OFPhysicalPort>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700227 .op(read='ChannelUtils.readList(bb, $length, OFPhysicalPort.READER)', write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700228port_desc = JType('OFPortDesc') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700229 .op(read='OFPortDescVer$version.READER.readFrom(bb)', \
Yotam Harchold7b84202013-07-26 16:08:10 -0700230 write='$name.writeTo(bb)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700231packet_queue_list = JType('List<OFPacketQueue>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700232 .op(read='ChannelUtils.readList(bb, $length, OFPacketQueueVer$version.READER)', write='ChannelUtils.writeList(bb, $name);')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700233octets = JType('byte[]') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700234 .op(read='ChannelUtils.readBytes(bb, $length)', \
Yotam Harchold7b84202013-07-26 16:08:10 -0700235 write='bb.writeBytes($name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700236of_match = JType('Match') \
Andreas Wundsam951ada32013-08-01 22:05:38 -0700237 .op(read='ChannelUtilsVer$version.readOFMatch(bb)', \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700238 write='$name.writeTo(bb)');
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700239flow_mod_cmd = JType('OFFlowModCommand', 'short') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700240 .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \
241 .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)")
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700242mac_addr = JType('MacAddress') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700243 .op(read="MacAddress.read6Bytes(bb)", \
244 write="$name.write6Bytes(bb)")
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700245port_name = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700246 .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
247 write='ChannelUtils.writeFixedLengthString(bb, $name, 16)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700248desc_str = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700249 .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
250 write='ChannelUtils.writeFixedLengthString(bb, $name, 256)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700251serial_num = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700252 .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
253 write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700254table_name = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700255 .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
256 write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
Yotam Harchold7b84202013-07-26 16:08:10 -0700257ipv4 = JType("IPv4") \
258 .op(read="IPv4.read4Bytes(bb)", \
259 write="$name.write4Bytes(bb)")
260ipv6 = JType("IPv6") \
261 .op(read="IPv6.read16Bytes(bb)", \
262 write="$name.write16Bytes(bb)")
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700263packetin_reason = JType("OFPacketInReason")\
264 .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)", write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)")
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700265wildcards = JType("Wildcards")\
266 .op(read="Wildcards.of(bb.readInt())", write="bb.writeInt($name.getInt())");
267transport_port = JType("TransportPort")\
268 .op(read="TransportPort.read2Bytes(bb)", write="$name.write2Bytes(bb)")
Yotam Harcholc742e202013-08-15 12:16:24 -0700269eth_type = JType("EthType")\
270 .op(read="EthType.read2Bytes(bb)", write="$name.write2Bytes(bb)")
271vlan_vid = JType("VlanVid")\
272 .op(read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)")
273vlan_pcp = JType("VlanPcp")\
274 .op(read="VlanPcp.readByte(bb)", write="$name.writeByte(bb)")
275ip_dscp = JType("IpDscp")\
276 .op(read="IpDscp.readByte(bb)", write="$name.writeByte(bb)")
277ip_ecn = JType("IpEcn")\
278 .op(read="IpEcn.readByte(bb)", write="$name.writeByte(bb)")
279ip_proto = JType("IpProtocol")\
280 .op(read="IpProtocol.readByte(bb)", write="$name.writeByte(bb)")
281icmpv4_type = JType("ICMPv4Type")\
282 .op(read="ICMPv4Type.readByte(bb)", write="$name.writeByte(bb)")
283icmpv4_code = JType("ICMPv4Code")\
284 .op(read="ICMPv4Code.readByte(bb)", write="$name.writeByte(bb)")
285arp_op = JType("ArpOpcode")\
286 .op(read="ArpOpcode.read2Bytes(bb)", write="$name.write2Bytes(bb)")
287ipv6_flabel = JType("IPv6FlowLabel")\
288 .op(read="IPv6FlowLabel.read4Bytes(bb)", write="$name.write4Bytes(bb)")
289metadata = JType("OFMetadata")\
290 .op(read="OFMetadata.read8Bytes(bb)", write="$name.write8Bytes(bb)")
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700291oxm = JType("OFOxm")\
292 .op(read="OFOxmVer$version.READER.readFrom(bb)", write="$name.writeTo(bb)")
293meter_features = JType("OFMeterFeatures")\
294 .op(read="OFMeterFeaturesVer$version.READER.readFrom(bb)", write="$name.writeTo(bb)")
295
Andreas Wundsam27303462013-07-16 12:52:35 -0700296
297default_mtype_to_jtype_convert_map = {
298 'uint8_t' : u8,
299 'uint16_t' : u16,
300 'uint32_t' : u32,
301 'uint64_t' : u64,
Andreas Wundsam27303462013-07-16 12:52:35 -0700302 'of_port_no_t' : of_port,
303 'list(of_action_t)' : actions_list,
304 'list(of_instruction_t)' : instructions_list,
305 'list(of_bucket_t)': buckets_list,
306 'list(of_port_desc_t)' : port_desc_list,
307 'list(of_packet_queue_t)' : packet_queue_list,
308 'list(of_uint32_t)' : u32_list,
309 'list(of_uint8_t)' : u8_list,
310 'of_octets_t' : octets,
311 'of_match_t': of_match,
312 'of_fm_cmd_t': flow_mod_cmd,
313 'of_mac_addr_t': mac_addr,
314 'of_port_desc_t': port_desc,
315 'of_desc_str_t': desc_str,
316 'of_serial_num_t': serial_num,
317 'of_port_name_t': port_name,
318 'of_table_name_t': table_name,
319 'of_ipv4_t': ipv4,
320 'of_ipv6_t': ipv6,
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700321 'of_wc_bmap_t': wildcards,
322 'of_oxm_t': oxm,
323 'of_meter_features_t': meter_features,
Andreas Wundsam27303462013-07-16 12:52:35 -0700324 }
325
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700326## Map that defines exceptions from the standard loxi->java mapping scheme
327# map of {<loxi_class_name> : { <loxi_member_name> : <JType instance> } }
Andreas Wundsam27303462013-07-16 12:52:35 -0700328exceptions = {
Yotam Harcholc742e202013-08-15 12:16:24 -0700329 'of_packet_in': { 'data' : octets, 'reason': packetin_reason },
330 'of_oxm_tcp_src' : { 'value' : transport_port },
331 'of_oxm_tcp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
332 'of_oxm_tcp_dst' : { 'value' : transport_port },
333 'of_oxm_tcp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
334 'of_oxm_udp_src' : { 'value' : transport_port },
335 'of_oxm_udp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
336 'of_oxm_udp_dst' : { 'value' : transport_port },
337 'of_oxm_udp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
338 'of_oxm_sctp_src' : { 'value' : transport_port },
339 'of_oxm_sctp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
340 'of_oxm_sctp_dst' : { 'value' : transport_port },
341 'of_oxm_sctp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
342 'of_oxm_eth_type' : { 'value' : eth_type },
343 'of_oxm_eth_type_masked' : { 'value' : eth_type, 'value_mask' : eth_type },
344 'of_oxm_vlan_vid' : { 'value' : vlan_vid },
345 'of_oxm_vlan_vid_masked' : { 'value' : vlan_vid, 'value_mask' : vlan_vid },
346 'of_oxm_vlan_pcp' : { 'value' : vlan_pcp },
347 'of_oxm_vlan_pcp_masked' : { 'value' : vlan_pcp, 'value_mask' : vlan_pcp },
348 'of_oxm_ip_dscp' : { 'value' : ip_dscp },
349 'of_oxm_ip_dscp_masked' : { 'value' : ip_dscp, 'value_mask' : ip_dscp },
350 'of_oxm_ip_ecn' : { 'value' : ip_ecn },
351 'of_oxm_ip_ecn_masked' : { 'value' : ip_ecn, 'value_mask' : ip_ecn },
352 'of_oxm_ip_proto' : { 'value' : ip_proto },
353 'of_oxm_ip_proto_masked' : { 'value' : ip_proto, 'value_mask' : ip_proto },
354 'of_oxm_icmpv4_type' : { 'value' : icmpv4_type },
355 'of_oxm_icmpv4_type_masked' : { 'value' : icmpv4_type, 'value_mask' : icmpv4_type },
356 'of_oxm_icmpv4_code' : { 'value' : icmpv4_code },
357 'of_oxm_icmpv4_code_masked' : { 'value' : icmpv4_code, 'value_mask' : icmpv4_code },
358 'of_oxm_arp_op' : { 'value' : arp_op },
359 'of_oxm_arp_op_masked' : { 'value' : arp_op, 'value_mask' : arp_op },
360 'of_oxm_arp_spa' : { 'value' : ipv4 },
361 'of_oxm_arp_spa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 },
362 'of_oxm_arp_tpa' : { 'value' : ipv4 },
363 'of_oxm_arp_tpa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 },
364 'of_oxm_ipv6_flabel' : { 'value' : ipv6_flabel },
365 'of_oxm_ipv6_flabel_masked' : { 'value' : ipv6_flabel, 'value_mask' : ipv6_flabel },
366 'of_oxm_metadata' : { 'value' : metadata },
367 'of_oxm_metadata_masked' : { 'value' : metadata, 'value_mask' : metadata },
Yotam Harchol5804f772013-08-21 17:35:31 -0700368
369 'of_oxm_icmpv6_code' : { 'value' : u8obj },
370 'of_oxm_icmpv6_code_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
371 'of_oxm_icmpv6_type' : { 'value' : u8obj },
372 'of_oxm_icmpv6_type_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
373 'of_oxm_mpls_label' : { 'value' : u32obj },
374 'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
375 'of_oxm_mpls_tc' : { 'value' : u8obj },
376 'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
Andreas Wundsam27303462013-07-16 12:52:35 -0700377}
378
379
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700380# Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}>
Andreas Wundsam27303462013-07-16 12:52:35 -0700381def make_standard_list_jtype(c_type):
382 m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
383 if not m:
384 raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
385 base_name = m.group(1)
386 java_base_name = name_c_to_caps_camel(base_name)
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700387
388 # read op assumes the class has a public final static field READER that implements
389 # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer
390 # write op assumes class implements Writeable
Yotam Harchold7b84202013-07-26 16:08:10 -0700391 return JType("List<OF%s>" % java_base_name) \
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700392 .op(
393 read= 'ChannelUtils.readList(bb, $length, OF%sVer$version.READER)' % java_base_name, \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700394 write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700395
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700396
397#### main entry point for conversion of LOXI types (c_types) Java types.
398# FIXME: This badly needs a refactoring
399
Andreas Wundsam27303462013-07-16 12:52:35 -0700400def convert_to_jtype(obj_name, field_name, c_type):
401 """ Convert from a C type ("uint_32") to a java type ("U32")
402 and return a JType object with the size, internal type, and marshalling functions"""
403 if obj_name in exceptions and field_name in exceptions[obj_name]:
404 return exceptions[obj_name][field_name]
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700405 elif ( obj_name == "of_header" or loxi_utils.class_is_message(obj_name)) and field_name == "type" and c_type == "uint8_t":
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700406 return JType("OFType", 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700407 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700408 elif field_name == "type" and re.match(r'of_action.*', obj_name):
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700409 return JType("OFActionType", 'short') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700410 .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
411 .op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
Andreas Wundsam27303462013-07-16 12:52:35 -0700412 elif field_name == "version" and c_type == "uint8_t":
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700413 return JType("OFVersion", 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700414 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700415 elif c_type in default_mtype_to_jtype_convert_map:
416 return default_mtype_to_jtype_convert_map[c_type]
417 elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
418 return make_standard_list_jtype(c_type)
419 else:
420 print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
421 jtype = name_c_to_caps_camel(re.sub(r'_t$', "", c_type))
422 return JType(jtype)
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700423
424
425#### Enum specific wiretype definitions
426enum_wire_types = {
427 "uint8_t": JType("byte").op(read="bb.readByte()", write="bb.writeByte($name)"),
428 "uint16_t": JType("short").op(read="bb.readShort()", write="bb.writeShort($name)"),
429 "uint32_t": JType("int").op(read="bb.readInt()", write="bb.writeInt($name)"),
430 "uint64_t": JType("long").op(read="bb.readLong()", write="bb.writeLong($name)"),
431}
432
433def convert_enum_wire_type_to_jtype(wire_type):
434 return enum_wire_types[wire_type]