blob: fa03371952f98204467c4143bc8bd1452100e994 [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
Andreas Wundsam2be7da52013-08-22 07:34:25 -07008def erase_type_annotation(class_name):
9 m=re.match(r'(.*)<.*>', class_name)
10 if m:
11 return m.group(1)
12 else:
13 return class_name
14
Andreas Wundsam27303462013-07-16 12:52:35 -070015def name_c_to_camel(name):
16 """ 'of_stats_reply' -> 'ofStatsReply' """
17 name = re.sub(r'^_','', name)
18 tokens = name.split('_')
19 for i in range(1, len(tokens)):
20 tokens[i] = tokens[i].title()
21 return "".join(tokens)
22
23def name_c_to_caps_camel(name):
24 """ 'of_stats_reply' to 'OFStatsReply' """
25 camel = name_c_to_camel(name.title())
26 if camel.startswith('Of'):
27 return camel.replace('Of','OF',1)
28 else:
29 return camel
30
Andreas Wundsame916d6f2013-07-30 11:33:58 -070031java_primitive_types = set("byte char short int long".split(" "))
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070032
33### info table about java primitive types, for casting literals in the source code
34# { name : (signed?, length_in_bits) }
Andreas Wundsam46d230f2013-08-02 22:24:06 -070035java_primitives_info = {
36 'byte' : (True, 8),
37 'char' : (False, 16),
38 'short' : (True, 16),
39 'int' : (True, 32),
40 'long' : (True, 64),
41}
42
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070043def format_primitive_literal(t, value):
44 """ Format a primitive numeric literal for inclusion in the
45 java source code. Takes care of casting the literal
46 apropriately for correct representation despite Java's
47 signed-craziness
48 """
Andreas Wundsam46d230f2013-08-02 22:24:06 -070049 signed, bits = java_primitives_info[t]
50 max = (1 << bits)-1
51 if value > max:
52 raise Exception("Value %d to large for type %s" % (value, t))
53
54 if signed:
55 max_pos = (1 << (bits-1)) - 1
56
57 if value > max_pos:
58 if t == "long":
59 return str((1 << bits) - value)
60 else:
61 return "(%s) 0x%x" % (t, value)
62 else:
Andreas Wundsam2bf357c2013-08-03 22:50:40 -070063 return "0x%x%s" % (value, "L" if t=="long" else "")
Yotam Harchold7b84202013-07-26 16:08:10 -070064
Andreas Wundsame916d6f2013-07-30 11:33:58 -070065ANY = 0xFFFFFFFFFFFFFFFF
Yotam Harchold7b84202013-07-26 16:08:10 -070066
67class VersionOp:
68 def __init__(self, version=ANY, read=None, write=None):
69 self.version = version
70 self.read = read
71 self.write = write
Andreas Wundsame916d6f2013-07-30 11:33:58 -070072
Yotam Harchold7b84202013-07-26 16:08:10 -070073 def __str__(self):
74 return "[Version: %d, Read: '%s', Write: '%s']" % (self.version, self.read, self.write)
75
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070076### FIXME: This class should really be cleaned up
Andreas Wundsam27303462013-07-16 12:52:35 -070077class JType(object):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070078 """ Wrapper class to hold C to Java type conversion information. JTypes can have a 'public'
79 and or 'private' java type associated with them and can define how those types can be
80 read from and written to ChannelBuffers.
81
82 """
Andreas Wundsam2bf357c2013-08-03 22:50:40 -070083 def __init__(self, pub_type, priv_type=None, read_op=None, write_op=None):
Andreas Wundsam27303462013-07-16 12:52:35 -070084 self.pub_type = pub_type # the type we expose externally, e.g. 'U8'
85 if priv_type is None:
86 priv_type = pub_type
87 self.priv_type = priv_type # the internal storage type
Yotam Harchold7b84202013-07-26 16:08:10 -070088 self.ops = {}
Yotam Harchold7b84202013-07-26 16:08:10 -070089
Andreas Wundsam46d230f2013-08-02 22:24:06 -070090 def op(self, version=ANY, read=None, write=None, pub_type=ANY):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070091 """
92 define operations to be performed for reading and writing this type
93 (when read_op, write_op is called). The operations 'read' and 'write'
94 can either be strings ($name, and $version and $length will be replaced),
95 or callables (name, version and length) will be passed.
96
97 @param version int OF version to define operation for, or ANY for all
98 @param pub_type boolean whether to define operations for the public type (True), the
99 private type(False) or both (ALL)
100 @param read read expression (either string or callable)s
101 @param write write expression (either string or callable)
102 """
103
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700104 pub_types = [ pub_type ] if pub_type is not ANY else [ False, True ]
105 for pub_type in pub_types:
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700106 self.ops[(version, pub_type)] = VersionOp(version, read, write)
Yotam Harchold7b84202013-07-26 16:08:10 -0700107 return self
Andreas Wundsam27303462013-07-16 12:52:35 -0700108
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700109 def format_value(self, value, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700110 # Format a constant value of this type, for inclusion in the java source code
111 # For primitive types, takes care of casting the value appropriately, to
112 # cope with java's signedness limitation
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700113 t = self.pub_type if pub_type else self.priv_type
114 if t in java_primitive_types:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700115 return format_primitive_literal(t, value)
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700116 else:
117 return value
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700118
Andreas Wundsam27303462013-07-16 12:52:35 -0700119 @property
120 def public_type(self):
121 """ return the public type """
122 return self.pub_type
123
124 def priv(self):
125 """ return the public type """
126 return self.priv_type
127
128 def has_priv(self):
129 """ Is the private type different from the public one?"""
130 return self.pub_type != self.priv_type
131
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700132 def read_op(self, version=None, length=None, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700133 """ return a Java stanza that reads a value of this JType from ChannelBuffer bb.
134 @param version int - OF wire version to generate expression for
135 @param pub_type boolean use this JTypes 'public' (True), or private (False) representation
136 @param length string, for operations that need it (e.g., read a list of unknown length)
137 Java expression evaluating to the byte length to be read. Defaults to the remainig
138 length of the message.
139 @return string containing generated Java expression.
140 """
Andreas Wundsam27303462013-07-16 12:52:35 -0700141 if length is None:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700142 # assumes that
143 # (1) length of the message has been read to 'length'
144 # (2) readerIndex at the start of the message has been stored in 'start'
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700145 length = "length - (bb.readerIndex() - start)";
Andreas Wundsam27303462013-07-16 12:52:35 -0700146
Yotam Harchold7b84202013-07-26 16:08:10 -0700147 ver = ANY if version is None else version.int_version
148 _read_op = None
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700149 if (ver, pub_type) in self.ops:
150 _read_op = self.ops[(ver, pub_type)].read or self.ops[(ANY, pub_type)].read
151 elif (ANY, pub_type) in self.ops:
152 _read_op = self.ops[(ANY, pub_type)].read
Yotam Harchold7b84202013-07-26 16:08:10 -0700153 if _read_op is None:
Andreas Wundsam951ada32013-08-01 22:05:38 -0700154 _read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type
Yotam Harchold7b84202013-07-26 16:08:10 -0700155 if callable(_read_op):
156 return _read_op(version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700157 else:
Yotam Harchold7b84202013-07-26 16:08:10 -0700158 return _read_op.replace("$length", str(length)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700159
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700160 def write_op(self, version=None, name=None, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700161 """ return a Java stanza that writes a value of this JType contained in Java expression
162 'name' to ChannelBuffer bb.
163 @param name string containing Java expression that evaluations to the value to be written
164 @param version int - OF wire version to generate expression for
165 @param pub_type boolean use this JTypes 'public' (True), or private (False) representation
166 @return string containing generated Java expression.
167 """
Yotam Harchold7b84202013-07-26 16:08:10 -0700168 ver = ANY if version is None else version.int_version
169 _write_op = None
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700170 if (ver, pub_type) in self.ops:
171 _write_op = self.ops[(ver, pub_type)].write or self.ops[(ANY, pub_type)].write
172 elif (ANY, pub_type) in self.ops:
173 _write_op = self.ops[(ANY, pub_type)].write
Yotam Harchold7b84202013-07-26 16:08:10 -0700174 if _write_op is None:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700175
Andreas Wundsam951ada32013-08-01 22:05:38 -0700176 _write_op = 'ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type
Yotam Harchold7b84202013-07-26 16:08:10 -0700177 if callable(_write_op):
178 return _write_op(version, name)
Andreas Wundsam27303462013-07-16 12:52:35 -0700179 else:
Yotam Harchold7b84202013-07-26 16:08:10 -0700180 return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700181
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700182 def skip_op(self, version=None, length=None):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700183 """ return a java stanza that skips an instance of JType in the input ChannelBuffer 'bb'.
184 This is used in the Reader implementations for virtual classes (because after the
185 discriminator field, the concrete Reader instance will re-read all the fields)
186 Currently just delegates to read_op + throws away the result."""
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700187 return self.read_op(version, length)
188
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700189 @property
190 def is_primitive(self):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700191 """ return true if the pub_type is a java primitive type (and thus needs
192 special treatment, because it doesn't have methods)"""
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700193 return self.pub_type in java_primitive_types
194
195 @property
196 def is_array(self):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700197 """ return true iff the pub_type is a Java array (and thus requires special
198 treament for equals / toString etc.) """
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700199 return self.pub_type.endswith("[]")
200
201
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700202##### Predefined JType mappings
203# FIXME: This list needs to be pruned / cleaned up. Most of these are schematic.
204
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700205u8 = JType('short', 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700206 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700207u8_list = JType('List<U8>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700208 .op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700209u16 = JType('int', 'short') \
210 .op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))', pub_type=True) \
211 .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
212u32 = JType('long', 'int') \
213 .op(read='U32.f(bb.readInt())', write='bb.writeInt(U32.t($name))', pub_type=True) \
214 .op(read='bb.readInt()', write='bb.writeInt($name)', pub_type=False)
215u32_list = JType('List<U32>', 'int[]') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700216 .op(read='ChannelUtils.readList(bb, $length, U32.READER)', write='ChannelUtils.writeList(bb, $name)')
Yotam Harchol5804f772013-08-21 17:35:31 -0700217u8obj = JType('U8', 'U8') \
218 .op(read='U8.of(bb.readByte())', write='bb.writeByte($name.getRaw())')
219u32obj = JType('U32', 'U32') \
220 .op(read='U32.of(bb.readInt())', write='bb.writeInt($name.getRaw())')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700221u64 = JType('U64', 'U64') \
Andreas Wundsam880a2a82013-08-22 07:55:14 -0700222 .op(read='U64.ofRaw(bb.readLong())', write='bb.writeLong($name.getValue())')
Yotam Harchold7b84202013-07-26 16:08:10 -0700223of_port = JType("OFPort") \
224 .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)") \
225 .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)")
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700226actions_list = JType('List<OFAction>') \
227 .op(read='ChannelUtils.readList(bb, $length, OFActionVer$version.READER)', write='ChannelUtils.writeList(bb, $name);')
228instructions_list = JType('List<OFInstruction>') \
229 .op(read='ChannelUtils.readList(bb, $length, OFInstructionVer$version.READER)', \
230 write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700231buckets_list = JType('List<OFBucket>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700232 .op(read='ChannelUtils.readList(bb, $length, OFBucketVer$version.READER)', write='ChannelUtils.writeList(bb, $name)')
Rob Vaterlaus7db900a2013-09-17 14:18:49 -0700233port_desc_list = JType('List<OFPortDesc>') \
234 .op(read='ChannelUtils.readList(bb, $length, OFPortDescVer$version.READER)', write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700235port_desc = JType('OFPortDesc') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700236 .op(read='OFPortDescVer$version.READER.readFrom(bb)', \
Yotam Harchold7b84202013-07-26 16:08:10 -0700237 write='$name.writeTo(bb)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700238packet_queue_list = JType('List<OFPacketQueue>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700239 .op(read='ChannelUtils.readList(bb, $length, OFPacketQueueVer$version.READER)', write='ChannelUtils.writeList(bb, $name);')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700240octets = JType('byte[]') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700241 .op(read='ChannelUtils.readBytes(bb, $length)', \
Yotam Harchold7b84202013-07-26 16:08:10 -0700242 write='bb.writeBytes($name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700243of_match = JType('Match') \
Andreas Wundsam951ada32013-08-01 22:05:38 -0700244 .op(read='ChannelUtilsVer$version.readOFMatch(bb)', \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700245 write='$name.writeTo(bb)');
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700246flow_mod_cmd = JType('OFFlowModCommand', 'short') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700247 .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \
248 .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)")
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700249mac_addr = JType('MacAddress') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700250 .op(read="MacAddress.read6Bytes(bb)", \
251 write="$name.write6Bytes(bb)")
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700252port_name = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700253 .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
254 write='ChannelUtils.writeFixedLengthString(bb, $name, 16)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700255desc_str = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700256 .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
257 write='ChannelUtils.writeFixedLengthString(bb, $name, 256)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700258serial_num = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700259 .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
260 write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700261table_name = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700262 .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
263 write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
Yotam Harchola289d552013-09-16 10:10:40 -0700264ipv4 = JType("IPv4Address") \
265 .op(read="IPv4Address.read4Bytes(bb)", \
Yotam Harchold7b84202013-07-26 16:08:10 -0700266 write="$name.write4Bytes(bb)")
Yotam Harchola289d552013-09-16 10:10:40 -0700267ipv6 = JType("IPv6Address") \
268 .op(read="IPv6Address.read16Bytes(bb)", \
Yotam Harchold7b84202013-07-26 16:08:10 -0700269 write="$name.write16Bytes(bb)")
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700270packetin_reason = JType("OFPacketInReason")\
271 .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)", write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)")
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700272wildcards = JType("Wildcards")\
273 .op(read="Wildcards.of(bb.readInt())", write="bb.writeInt($name.getInt())");
274transport_port = JType("TransportPort")\
275 .op(read="TransportPort.read2Bytes(bb)", write="$name.write2Bytes(bb)")
Yotam Harcholc742e202013-08-15 12:16:24 -0700276eth_type = JType("EthType")\
277 .op(read="EthType.read2Bytes(bb)", write="$name.write2Bytes(bb)")
278vlan_vid = JType("VlanVid")\
279 .op(read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)")
280vlan_pcp = JType("VlanPcp")\
281 .op(read="VlanPcp.readByte(bb)", write="$name.writeByte(bb)")
282ip_dscp = JType("IpDscp")\
283 .op(read="IpDscp.readByte(bb)", write="$name.writeByte(bb)")
284ip_ecn = JType("IpEcn")\
285 .op(read="IpEcn.readByte(bb)", write="$name.writeByte(bb)")
286ip_proto = JType("IpProtocol")\
287 .op(read="IpProtocol.readByte(bb)", write="$name.writeByte(bb)")
288icmpv4_type = JType("ICMPv4Type")\
289 .op(read="ICMPv4Type.readByte(bb)", write="$name.writeByte(bb)")
290icmpv4_code = JType("ICMPv4Code")\
291 .op(read="ICMPv4Code.readByte(bb)", write="$name.writeByte(bb)")
292arp_op = JType("ArpOpcode")\
293 .op(read="ArpOpcode.read2Bytes(bb)", write="$name.write2Bytes(bb)")
294ipv6_flabel = JType("IPv6FlowLabel")\
295 .op(read="IPv6FlowLabel.read4Bytes(bb)", write="$name.write4Bytes(bb)")
296metadata = JType("OFMetadata")\
297 .op(read="OFMetadata.read8Bytes(bb)", write="$name.write8Bytes(bb)")
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700298oxm = JType("OFOxm<?>")\
299 .op( read="OFOxmVer$version.READER.readFrom(bb)",
300 write="$name.writeTo(bb)")
301oxm_list = JType("OFOxmList") \
302 .op(
303 read= 'OFOxmList.readFrom(bb, $length, OFOxmVer$version.READER)', \
304 write='$name.writeTo(bb)')
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700305meter_features = JType("OFMeterFeatures")\
306 .op(read="OFMeterFeaturesVer$version.READER.readFrom(bb)", write="$name.writeTo(bb)")
307
Andreas Wundsam8ec3bcc2013-09-16 19:44:00 -0700308port_speed = JType("PortSpeed")
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700309boolean = JType("boolean")
310
311generic_t = JType("T")
312
Andreas Wundsam27303462013-07-16 12:52:35 -0700313
314default_mtype_to_jtype_convert_map = {
315 'uint8_t' : u8,
316 'uint16_t' : u16,
317 'uint32_t' : u32,
318 'uint64_t' : u64,
Andreas Wundsam27303462013-07-16 12:52:35 -0700319 'of_port_no_t' : of_port,
320 'list(of_action_t)' : actions_list,
321 'list(of_instruction_t)' : instructions_list,
322 'list(of_bucket_t)': buckets_list,
323 'list(of_port_desc_t)' : port_desc_list,
324 'list(of_packet_queue_t)' : packet_queue_list,
325 'list(of_uint32_t)' : u32_list,
326 'list(of_uint8_t)' : u8_list,
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700327 'list(of_oxm_t)' : oxm_list,
Andreas Wundsam27303462013-07-16 12:52:35 -0700328 'of_octets_t' : octets,
329 'of_match_t': of_match,
330 'of_fm_cmd_t': flow_mod_cmd,
331 'of_mac_addr_t': mac_addr,
332 'of_port_desc_t': port_desc,
333 'of_desc_str_t': desc_str,
334 'of_serial_num_t': serial_num,
335 'of_port_name_t': port_name,
336 'of_table_name_t': table_name,
337 'of_ipv4_t': ipv4,
338 'of_ipv6_t': ipv6,
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700339 'of_wc_bmap_t': wildcards,
340 'of_oxm_t': oxm,
341 'of_meter_features_t': meter_features,
Andreas Wundsam27303462013-07-16 12:52:35 -0700342 }
343
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700344## Map that defines exceptions from the standard loxi->java mapping scheme
345# map of {<loxi_class_name> : { <loxi_member_name> : <JType instance> } }
Andreas Wundsam27303462013-07-16 12:52:35 -0700346exceptions = {
Yotam Harcholc742e202013-08-15 12:16:24 -0700347 'of_packet_in': { 'data' : octets, 'reason': packetin_reason },
348 'of_oxm_tcp_src' : { 'value' : transport_port },
349 'of_oxm_tcp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
350 'of_oxm_tcp_dst' : { 'value' : transport_port },
351 'of_oxm_tcp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
352 'of_oxm_udp_src' : { 'value' : transport_port },
353 'of_oxm_udp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
354 'of_oxm_udp_dst' : { 'value' : transport_port },
355 'of_oxm_udp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
356 'of_oxm_sctp_src' : { 'value' : transport_port },
357 'of_oxm_sctp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
358 'of_oxm_sctp_dst' : { 'value' : transport_port },
359 'of_oxm_sctp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
360 'of_oxm_eth_type' : { 'value' : eth_type },
361 'of_oxm_eth_type_masked' : { 'value' : eth_type, 'value_mask' : eth_type },
362 'of_oxm_vlan_vid' : { 'value' : vlan_vid },
363 'of_oxm_vlan_vid_masked' : { 'value' : vlan_vid, 'value_mask' : vlan_vid },
364 'of_oxm_vlan_pcp' : { 'value' : vlan_pcp },
365 'of_oxm_vlan_pcp_masked' : { 'value' : vlan_pcp, 'value_mask' : vlan_pcp },
366 'of_oxm_ip_dscp' : { 'value' : ip_dscp },
367 'of_oxm_ip_dscp_masked' : { 'value' : ip_dscp, 'value_mask' : ip_dscp },
368 'of_oxm_ip_ecn' : { 'value' : ip_ecn },
369 'of_oxm_ip_ecn_masked' : { 'value' : ip_ecn, 'value_mask' : ip_ecn },
370 'of_oxm_ip_proto' : { 'value' : ip_proto },
371 'of_oxm_ip_proto_masked' : { 'value' : ip_proto, 'value_mask' : ip_proto },
372 'of_oxm_icmpv4_type' : { 'value' : icmpv4_type },
373 'of_oxm_icmpv4_type_masked' : { 'value' : icmpv4_type, 'value_mask' : icmpv4_type },
374 'of_oxm_icmpv4_code' : { 'value' : icmpv4_code },
375 'of_oxm_icmpv4_code_masked' : { 'value' : icmpv4_code, 'value_mask' : icmpv4_code },
376 'of_oxm_arp_op' : { 'value' : arp_op },
377 'of_oxm_arp_op_masked' : { 'value' : arp_op, 'value_mask' : arp_op },
378 'of_oxm_arp_spa' : { 'value' : ipv4 },
379 'of_oxm_arp_spa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 },
380 'of_oxm_arp_tpa' : { 'value' : ipv4 },
381 'of_oxm_arp_tpa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 },
382 'of_oxm_ipv6_flabel' : { 'value' : ipv6_flabel },
383 'of_oxm_ipv6_flabel_masked' : { 'value' : ipv6_flabel, 'value_mask' : ipv6_flabel },
384 'of_oxm_metadata' : { 'value' : metadata },
385 'of_oxm_metadata_masked' : { 'value' : metadata, 'value_mask' : metadata },
Yotam Harchol5804f772013-08-21 17:35:31 -0700386
387 'of_oxm_icmpv6_code' : { 'value' : u8obj },
388 'of_oxm_icmpv6_code_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
389 'of_oxm_icmpv6_type' : { 'value' : u8obj },
390 'of_oxm_icmpv6_type_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
391 'of_oxm_mpls_label' : { 'value' : u32obj },
392 'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
393 'of_oxm_mpls_tc' : { 'value' : u8obj },
394 'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
Andreas Wundsam27303462013-07-16 12:52:35 -0700395}
396
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700397def make_match_field_jtype(sub_type_name="?"):
398 return JType("MatchField<{}>".format(sub_type_name))
399
Andreas Wundsam27303462013-07-16 12:52:35 -0700400
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700401# Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}>
Andreas Wundsam27303462013-07-16 12:52:35 -0700402def make_standard_list_jtype(c_type):
403 m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
404 if not m:
405 raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
406 base_name = m.group(1)
407 java_base_name = name_c_to_caps_camel(base_name)
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700408
409 # read op assumes the class has a public final static field READER that implements
410 # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer
411 # write op assumes class implements Writeable
Yotam Harchold7b84202013-07-26 16:08:10 -0700412 return JType("List<OF%s>" % java_base_name) \
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700413 .op(
414 read= 'ChannelUtils.readList(bb, $length, OF%sVer$version.READER)' % java_base_name, \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700415 write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700416
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700417
418#### main entry point for conversion of LOXI types (c_types) Java types.
419# FIXME: This badly needs a refactoring
420
Andreas Wundsam27303462013-07-16 12:52:35 -0700421def convert_to_jtype(obj_name, field_name, c_type):
422 """ Convert from a C type ("uint_32") to a java type ("U32")
423 and return a JType object with the size, internal type, and marshalling functions"""
424 if obj_name in exceptions and field_name in exceptions[obj_name]:
425 return exceptions[obj_name][field_name]
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700426 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 -0700427 return JType("OFType", 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700428 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700429 elif field_name == "type" and re.match(r'of_action.*', obj_name):
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700430 return JType("OFActionType", 'short') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700431 .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
432 .op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
Andreas Wundsam27303462013-07-16 12:52:35 -0700433 elif field_name == "version" and c_type == "uint8_t":
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700434 return JType("OFVersion", 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700435 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700436 elif c_type in default_mtype_to_jtype_convert_map:
437 return default_mtype_to_jtype_convert_map[c_type]
438 elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
439 return make_standard_list_jtype(c_type)
440 else:
441 print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
442 jtype = name_c_to_caps_camel(re.sub(r'_t$', "", c_type))
443 return JType(jtype)
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700444
445
446#### Enum specific wiretype definitions
447enum_wire_types = {
448 "uint8_t": JType("byte").op(read="bb.readByte()", write="bb.writeByte($name)"),
449 "uint16_t": JType("short").op(read="bb.readShort()", write="bb.writeShort($name)"),
450 "uint32_t": JType("int").op(read="bb.readInt()", write="bb.writeInt($name)"),
451 "uint64_t": JType("long").op(read="bb.readLong()", write="bb.writeLong($name)"),
452}
453
454def convert_enum_wire_type_to_jtype(wire_type):
455 return enum_wire_types[wire_type]