blob: 1dfb2657530ba25a312cd65006801171af413035 [file] [log] [blame]
Yotam Harcholc742e202013-08-15 12:16:24 -07001import errno
Andreas Wundsam27303462013-07-16 12:52:35 -07002import os
Andreas Wundsam27303462013-07-16 12:52:35 -07003import re
4import subprocess
5import time
6
Andreas Wundsam7cfeac32013-09-17 13:53:48 -07007from generic_utils import memoize
8import loxi_utils.loxi_utils as loxi_utils
9import of_g
10
Andreas Wundsam2be7da52013-08-22 07:34:25 -070011def erase_type_annotation(class_name):
12 m=re.match(r'(.*)<.*>', class_name)
13 if m:
14 return m.group(1)
15 else:
16 return class_name
17
Andreas Wundsam27303462013-07-16 12:52:35 -070018def name_c_to_camel(name):
19 """ 'of_stats_reply' -> 'ofStatsReply' """
20 name = re.sub(r'^_','', name)
21 tokens = name.split('_')
22 for i in range(1, len(tokens)):
23 tokens[i] = tokens[i].title()
24 return "".join(tokens)
25
26def name_c_to_caps_camel(name):
27 """ 'of_stats_reply' to 'OFStatsReply' """
28 camel = name_c_to_camel(name.title())
Andreas Wundsam7cfeac32013-09-17 13:53:48 -070029 if camel.startswith('Ofp'):
30 return camel.replace('Ofp','OF',1)
31 elif camel.startswith('Of'):
Andreas Wundsam27303462013-07-16 12:52:35 -070032 return camel.replace('Of','OF',1)
33 else:
34 return camel
35
Andreas Wundsame916d6f2013-07-30 11:33:58 -070036java_primitive_types = set("byte char short int long".split(" "))
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070037
38### info table about java primitive types, for casting literals in the source code
39# { name : (signed?, length_in_bits) }
Andreas Wundsam46d230f2013-08-02 22:24:06 -070040java_primitives_info = {
41 'byte' : (True, 8),
42 'char' : (False, 16),
43 'short' : (True, 16),
44 'int' : (True, 32),
45 'long' : (True, 64),
46}
47
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070048def format_primitive_literal(t, value):
49 """ Format a primitive numeric literal for inclusion in the
50 java source code. Takes care of casting the literal
51 apropriately for correct representation despite Java's
52 signed-craziness
53 """
Andreas Wundsam46d230f2013-08-02 22:24:06 -070054 signed, bits = java_primitives_info[t]
55 max = (1 << bits)-1
56 if value > max:
57 raise Exception("Value %d to large for type %s" % (value, t))
58
59 if signed:
60 max_pos = (1 << (bits-1)) - 1
61
62 if value > max_pos:
63 if t == "long":
64 return str((1 << bits) - value)
65 else:
66 return "(%s) 0x%x" % (t, value)
67 else:
Andreas Wundsam2bf357c2013-08-03 22:50:40 -070068 return "0x%x%s" % (value, "L" if t=="long" else "")
Yotam Harchold7b84202013-07-26 16:08:10 -070069
Andreas Wundsame916d6f2013-07-30 11:33:58 -070070ANY = 0xFFFFFFFFFFFFFFFF
Yotam Harchold7b84202013-07-26 16:08:10 -070071
72class VersionOp:
73 def __init__(self, version=ANY, read=None, write=None):
74 self.version = version
75 self.read = read
76 self.write = write
Andreas Wundsame916d6f2013-07-30 11:33:58 -070077
Yotam Harchold7b84202013-07-26 16:08:10 -070078 def __str__(self):
79 return "[Version: %d, Read: '%s', Write: '%s']" % (self.version, self.read, self.write)
80
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070081### FIXME: This class should really be cleaned up
Andreas Wundsam27303462013-07-16 12:52:35 -070082class JType(object):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070083 """ Wrapper class to hold C to Java type conversion information. JTypes can have a 'public'
84 and or 'private' java type associated with them and can define how those types can be
85 read from and written to ChannelBuffers.
86
87 """
Andreas Wundsam2bf357c2013-08-03 22:50:40 -070088 def __init__(self, pub_type, priv_type=None, read_op=None, write_op=None):
Andreas Wundsam27303462013-07-16 12:52:35 -070089 self.pub_type = pub_type # the type we expose externally, e.g. 'U8'
90 if priv_type is None:
91 priv_type = pub_type
92 self.priv_type = priv_type # the internal storage type
Yotam Harchold7b84202013-07-26 16:08:10 -070093 self.ops = {}
Yotam Harchold7b84202013-07-26 16:08:10 -070094
Andreas Wundsam46d230f2013-08-02 22:24:06 -070095 def op(self, version=ANY, read=None, write=None, pub_type=ANY):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -070096 """
97 define operations to be performed for reading and writing this type
98 (when read_op, write_op is called). The operations 'read' and 'write'
99 can either be strings ($name, and $version and $length will be replaced),
100 or callables (name, version and length) will be passed.
101
102 @param version int OF version to define operation for, or ANY for all
103 @param pub_type boolean whether to define operations for the public type (True), the
104 private type(False) or both (ALL)
105 @param read read expression (either string or callable)s
106 @param write write expression (either string or callable)
107 """
108
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700109 pub_types = [ pub_type ] if pub_type is not ANY else [ False, True ]
110 for pub_type in pub_types:
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700111 self.ops[(version, pub_type)] = VersionOp(version, read, write)
Yotam Harchold7b84202013-07-26 16:08:10 -0700112 return self
Andreas Wundsam27303462013-07-16 12:52:35 -0700113
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700114 def format_value(self, value, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700115 # Format a constant value of this type, for inclusion in the java source code
116 # For primitive types, takes care of casting the value appropriately, to
117 # cope with java's signedness limitation
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700118 t = self.pub_type if pub_type else self.priv_type
119 if t in java_primitive_types:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700120 return format_primitive_literal(t, value)
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700121 else:
122 return value
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700123
Andreas Wundsam27303462013-07-16 12:52:35 -0700124 @property
125 def public_type(self):
126 """ return the public type """
127 return self.pub_type
128
129 def priv(self):
130 """ return the public type """
131 return self.priv_type
132
133 def has_priv(self):
134 """ Is the private type different from the public one?"""
135 return self.pub_type != self.priv_type
136
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700137 def read_op(self, version=None, length=None, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700138 """ return a Java stanza that reads a value of this JType from ChannelBuffer bb.
139 @param version int - OF wire version to generate expression for
140 @param pub_type boolean use this JTypes 'public' (True), or private (False) representation
141 @param length string, for operations that need it (e.g., read a list of unknown length)
142 Java expression evaluating to the byte length to be read. Defaults to the remainig
143 length of the message.
144 @return string containing generated Java expression.
145 """
Andreas Wundsam27303462013-07-16 12:52:35 -0700146 if length is None:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700147 # assumes that
148 # (1) length of the message has been read to 'length'
149 # (2) readerIndex at the start of the message has been stored in 'start'
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700150 length = "length - (bb.readerIndex() - start)";
Andreas Wundsam27303462013-07-16 12:52:35 -0700151
Yotam Harchold7b84202013-07-26 16:08:10 -0700152 ver = ANY if version is None else version.int_version
153 _read_op = None
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700154 if (ver, pub_type) in self.ops:
155 _read_op = self.ops[(ver, pub_type)].read or self.ops[(ANY, pub_type)].read
156 elif (ANY, pub_type) in self.ops:
157 _read_op = self.ops[(ANY, pub_type)].read
Yotam Harchold7b84202013-07-26 16:08:10 -0700158 if _read_op is None:
Andreas Wundsam951ada32013-08-01 22:05:38 -0700159 _read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type
Yotam Harchold7b84202013-07-26 16:08:10 -0700160 if callable(_read_op):
161 return _read_op(version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700162 else:
Yotam Harchold7b84202013-07-26 16:08:10 -0700163 return _read_op.replace("$length", str(length)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700164
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700165 def write_op(self, version=None, name=None, pub_type=True):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700166 """ return a Java stanza that writes a value of this JType contained in Java expression
167 'name' to ChannelBuffer bb.
168 @param name string containing Java expression that evaluations to the value to be written
169 @param version int - OF wire version to generate expression for
170 @param pub_type boolean use this JTypes 'public' (True), or private (False) representation
171 @return string containing generated Java expression.
172 """
Yotam Harchold7b84202013-07-26 16:08:10 -0700173 ver = ANY if version is None else version.int_version
174 _write_op = None
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700175 if (ver, pub_type) in self.ops:
176 _write_op = self.ops[(ver, pub_type)].write or self.ops[(ANY, pub_type)].write
177 elif (ANY, pub_type) in self.ops:
178 _write_op = self.ops[(ANY, pub_type)].write
Yotam Harchold7b84202013-07-26 16:08:10 -0700179 if _write_op is None:
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700180
Andreas Wundsam951ada32013-08-01 22:05:38 -0700181 _write_op = 'ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type
Yotam Harchold7b84202013-07-26 16:08:10 -0700182 if callable(_write_op):
183 return _write_op(version, name)
Andreas Wundsam27303462013-07-16 12:52:35 -0700184 else:
Yotam Harchold7b84202013-07-26 16:08:10 -0700185 return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
Andreas Wundsam27303462013-07-16 12:52:35 -0700186
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700187 def skip_op(self, version=None, length=None):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700188 """ return a java stanza that skips an instance of JType in the input ChannelBuffer 'bb'.
189 This is used in the Reader implementations for virtual classes (because after the
190 discriminator field, the concrete Reader instance will re-read all the fields)
191 Currently just delegates to read_op + throws away the result."""
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700192 return self.read_op(version, length)
193
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700194 @property
195 def is_primitive(self):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700196 """ return true if the pub_type is a java primitive type (and thus needs
197 special treatment, because it doesn't have methods)"""
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700198 return self.pub_type in java_primitive_types
199
200 @property
201 def is_array(self):
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700202 """ return true iff the pub_type is a Java array (and thus requires special
203 treament for equals / toString etc.) """
Andreas Wundsame916d6f2013-07-30 11:33:58 -0700204 return self.pub_type.endswith("[]")
205
206
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700207##### Predefined JType mappings
208# FIXME: This list needs to be pruned / cleaned up. Most of these are schematic.
209
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700210u8 = JType('short', 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700211 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700212u8_list = JType('List<U8>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700213 .op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700214u16 = JType('int', 'short') \
215 .op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))', pub_type=True) \
216 .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
217u32 = JType('long', 'int') \
218 .op(read='U32.f(bb.readInt())', write='bb.writeInt(U32.t($name))', pub_type=True) \
219 .op(read='bb.readInt()', write='bb.writeInt($name)', pub_type=False)
220u32_list = JType('List<U32>', 'int[]') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700221 .op(read='ChannelUtils.readList(bb, $length, U32.READER)', write='ChannelUtils.writeList(bb, $name)')
Yotam Harchol5804f772013-08-21 17:35:31 -0700222u8obj = JType('U8', 'U8') \
223 .op(read='U8.of(bb.readByte())', write='bb.writeByte($name.getRaw())')
224u32obj = JType('U32', 'U32') \
225 .op(read='U32.of(bb.readInt())', write='bb.writeInt($name.getRaw())')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700226u64 = JType('U64', 'U64') \
Andreas Wundsam880a2a82013-08-22 07:55:14 -0700227 .op(read='U64.ofRaw(bb.readLong())', write='bb.writeLong($name.getValue())')
Yotam Harchold7b84202013-07-26 16:08:10 -0700228of_port = JType("OFPort") \
229 .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)") \
230 .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)")
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700231actions_list = JType('List<OFAction>') \
232 .op(read='ChannelUtils.readList(bb, $length, OFActionVer$version.READER)', write='ChannelUtils.writeList(bb, $name);')
233instructions_list = JType('List<OFInstruction>') \
234 .op(read='ChannelUtils.readList(bb, $length, OFInstructionVer$version.READER)', \
235 write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700236buckets_list = JType('List<OFBucket>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700237 .op(read='ChannelUtils.readList(bb, $length, OFBucketVer$version.READER)', write='ChannelUtils.writeList(bb, $name)')
Rob Vaterlaus7db900a2013-09-17 14:18:49 -0700238port_desc_list = JType('List<OFPortDesc>') \
239 .op(read='ChannelUtils.readList(bb, $length, OFPortDescVer$version.READER)', write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700240port_desc = JType('OFPortDesc') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700241 .op(read='OFPortDescVer$version.READER.readFrom(bb)', \
Yotam Harchold7b84202013-07-26 16:08:10 -0700242 write='$name.writeTo(bb)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700243packet_queue_list = JType('List<OFPacketQueue>') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700244 .op(read='ChannelUtils.readList(bb, $length, OFPacketQueueVer$version.READER)', write='ChannelUtils.writeList(bb, $name);')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700245octets = JType('byte[]') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700246 .op(read='ChannelUtils.readBytes(bb, $length)', \
Yotam Harchold7b84202013-07-26 16:08:10 -0700247 write='bb.writeBytes($name)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700248of_match = JType('Match') \
Andreas Wundsam951ada32013-08-01 22:05:38 -0700249 .op(read='ChannelUtilsVer$version.readOFMatch(bb)', \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700250 write='$name.writeTo(bb)');
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700251flow_mod_cmd = JType('OFFlowModCommand', 'short') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700252 .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \
253 .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)")
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700254mac_addr = JType('MacAddress') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700255 .op(read="MacAddress.read6Bytes(bb)", \
256 write="$name.write6Bytes(bb)")
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700257port_name = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700258 .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
259 write='ChannelUtils.writeFixedLengthString(bb, $name, 16)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700260desc_str = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700261 .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
262 write='ChannelUtils.writeFixedLengthString(bb, $name, 256)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700263serial_num = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700264 .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
265 write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700266table_name = JType('String') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700267 .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
268 write='ChannelUtils.writeFixedLengthString(bb, $name, 32)')
Yotam Harchola289d552013-09-16 10:10:40 -0700269ipv4 = JType("IPv4Address") \
270 .op(read="IPv4Address.read4Bytes(bb)", \
Yotam Harchold7b84202013-07-26 16:08:10 -0700271 write="$name.write4Bytes(bb)")
Yotam Harchola289d552013-09-16 10:10:40 -0700272ipv6 = JType("IPv6Address") \
273 .op(read="IPv6Address.read16Bytes(bb)", \
Yotam Harchold7b84202013-07-26 16:08:10 -0700274 write="$name.write16Bytes(bb)")
Andreas Wundsambf1dbbd2013-07-30 11:07:59 -0700275packetin_reason = JType("OFPacketInReason")\
276 .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)", write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)")
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700277wildcards = JType("Wildcards")\
278 .op(read="Wildcards.of(bb.readInt())", write="bb.writeInt($name.getInt())");
279transport_port = JType("TransportPort")\
280 .op(read="TransportPort.read2Bytes(bb)", write="$name.write2Bytes(bb)")
Yotam Harcholc742e202013-08-15 12:16:24 -0700281eth_type = JType("EthType")\
282 .op(read="EthType.read2Bytes(bb)", write="$name.write2Bytes(bb)")
283vlan_vid = JType("VlanVid")\
284 .op(read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)")
285vlan_pcp = JType("VlanPcp")\
286 .op(read="VlanPcp.readByte(bb)", write="$name.writeByte(bb)")
287ip_dscp = JType("IpDscp")\
288 .op(read="IpDscp.readByte(bb)", write="$name.writeByte(bb)")
289ip_ecn = JType("IpEcn")\
290 .op(read="IpEcn.readByte(bb)", write="$name.writeByte(bb)")
291ip_proto = JType("IpProtocol")\
292 .op(read="IpProtocol.readByte(bb)", write="$name.writeByte(bb)")
293icmpv4_type = JType("ICMPv4Type")\
294 .op(read="ICMPv4Type.readByte(bb)", write="$name.writeByte(bb)")
295icmpv4_code = JType("ICMPv4Code")\
296 .op(read="ICMPv4Code.readByte(bb)", write="$name.writeByte(bb)")
297arp_op = JType("ArpOpcode")\
298 .op(read="ArpOpcode.read2Bytes(bb)", write="$name.write2Bytes(bb)")
299ipv6_flabel = JType("IPv6FlowLabel")\
300 .op(read="IPv6FlowLabel.read4Bytes(bb)", write="$name.write4Bytes(bb)")
301metadata = JType("OFMetadata")\
302 .op(read="OFMetadata.read8Bytes(bb)", write="$name.write8Bytes(bb)")
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700303oxm = JType("OFOxm<?>")\
304 .op( read="OFOxmVer$version.READER.readFrom(bb)",
305 write="$name.writeTo(bb)")
306oxm_list = JType("OFOxmList") \
307 .op(
308 read= 'OFOxmList.readFrom(bb, $length, OFOxmVer$version.READER)', \
309 write='$name.writeTo(bb)')
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700310meter_features = JType("OFMeterFeatures")\
311 .op(read="OFMeterFeaturesVer$version.READER.readFrom(bb)", write="$name.writeTo(bb)")
312
Rob Vaterlausb10ae552013-09-23 14:39:39 -0700313
Andreas Wundsam8ec3bcc2013-09-16 19:44:00 -0700314port_speed = JType("PortSpeed")
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700315boolean = JType("boolean")
316
317generic_t = JType("T")
318
Andreas Wundsam27303462013-07-16 12:52:35 -0700319
320default_mtype_to_jtype_convert_map = {
321 'uint8_t' : u8,
322 'uint16_t' : u16,
323 'uint32_t' : u32,
324 'uint64_t' : u64,
Andreas Wundsam27303462013-07-16 12:52:35 -0700325 'of_port_no_t' : of_port,
326 'list(of_action_t)' : actions_list,
327 'list(of_instruction_t)' : instructions_list,
328 'list(of_bucket_t)': buckets_list,
329 'list(of_port_desc_t)' : port_desc_list,
330 'list(of_packet_queue_t)' : packet_queue_list,
331 'list(of_uint32_t)' : u32_list,
332 'list(of_uint8_t)' : u8_list,
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700333 'list(of_oxm_t)' : oxm_list,
Andreas Wundsam27303462013-07-16 12:52:35 -0700334 'of_octets_t' : octets,
335 'of_match_t': of_match,
336 'of_fm_cmd_t': flow_mod_cmd,
337 'of_mac_addr_t': mac_addr,
338 'of_port_desc_t': port_desc,
339 'of_desc_str_t': desc_str,
340 'of_serial_num_t': serial_num,
341 'of_port_name_t': port_name,
342 'of_table_name_t': table_name,
343 'of_ipv4_t': ipv4,
344 'of_ipv6_t': ipv6,
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700345 'of_wc_bmap_t': wildcards,
346 'of_oxm_t': oxm,
347 'of_meter_features_t': meter_features,
Andreas Wundsam27303462013-07-16 12:52:35 -0700348 }
349
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700350## Map that defines exceptions from the standard loxi->java mapping scheme
351# map of {<loxi_class_name> : { <loxi_member_name> : <JType instance> } }
Andreas Wundsam27303462013-07-16 12:52:35 -0700352exceptions = {
Yotam Harcholc742e202013-08-15 12:16:24 -0700353 'of_packet_in': { 'data' : octets, 'reason': packetin_reason },
354 'of_oxm_tcp_src' : { 'value' : transport_port },
355 'of_oxm_tcp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
356 'of_oxm_tcp_dst' : { 'value' : transport_port },
357 'of_oxm_tcp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
358 'of_oxm_udp_src' : { 'value' : transport_port },
359 'of_oxm_udp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
360 'of_oxm_udp_dst' : { 'value' : transport_port },
361 'of_oxm_udp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
362 'of_oxm_sctp_src' : { 'value' : transport_port },
363 'of_oxm_sctp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
364 'of_oxm_sctp_dst' : { 'value' : transport_port },
365 'of_oxm_sctp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
366 'of_oxm_eth_type' : { 'value' : eth_type },
367 'of_oxm_eth_type_masked' : { 'value' : eth_type, 'value_mask' : eth_type },
368 'of_oxm_vlan_vid' : { 'value' : vlan_vid },
369 'of_oxm_vlan_vid_masked' : { 'value' : vlan_vid, 'value_mask' : vlan_vid },
370 'of_oxm_vlan_pcp' : { 'value' : vlan_pcp },
371 'of_oxm_vlan_pcp_masked' : { 'value' : vlan_pcp, 'value_mask' : vlan_pcp },
372 'of_oxm_ip_dscp' : { 'value' : ip_dscp },
373 'of_oxm_ip_dscp_masked' : { 'value' : ip_dscp, 'value_mask' : ip_dscp },
374 'of_oxm_ip_ecn' : { 'value' : ip_ecn },
375 'of_oxm_ip_ecn_masked' : { 'value' : ip_ecn, 'value_mask' : ip_ecn },
376 'of_oxm_ip_proto' : { 'value' : ip_proto },
377 'of_oxm_ip_proto_masked' : { 'value' : ip_proto, 'value_mask' : ip_proto },
378 'of_oxm_icmpv4_type' : { 'value' : icmpv4_type },
379 'of_oxm_icmpv4_type_masked' : { 'value' : icmpv4_type, 'value_mask' : icmpv4_type },
380 'of_oxm_icmpv4_code' : { 'value' : icmpv4_code },
381 'of_oxm_icmpv4_code_masked' : { 'value' : icmpv4_code, 'value_mask' : icmpv4_code },
382 'of_oxm_arp_op' : { 'value' : arp_op },
383 'of_oxm_arp_op_masked' : { 'value' : arp_op, 'value_mask' : arp_op },
384 'of_oxm_arp_spa' : { 'value' : ipv4 },
385 'of_oxm_arp_spa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 },
386 'of_oxm_arp_tpa' : { 'value' : ipv4 },
387 'of_oxm_arp_tpa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 },
388 'of_oxm_ipv6_flabel' : { 'value' : ipv6_flabel },
389 'of_oxm_ipv6_flabel_masked' : { 'value' : ipv6_flabel, 'value_mask' : ipv6_flabel },
390 'of_oxm_metadata' : { 'value' : metadata },
391 'of_oxm_metadata_masked' : { 'value' : metadata, 'value_mask' : metadata },
Yotam Harchol5804f772013-08-21 17:35:31 -0700392
393 'of_oxm_icmpv6_code' : { 'value' : u8obj },
394 'of_oxm_icmpv6_code_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
395 'of_oxm_icmpv6_type' : { 'value' : u8obj },
396 'of_oxm_icmpv6_type_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
397 'of_oxm_mpls_label' : { 'value' : u32obj },
398 'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
399 'of_oxm_mpls_tc' : { 'value' : u8obj },
400 'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
Andreas Wundsam27303462013-07-16 12:52:35 -0700401}
402
Andreas Wundsam7cfeac32013-09-17 13:53:48 -0700403
404@memoize
405def enum_java_types():
406 enum_types = {}
407
408 for protocol in of_g.ir.values():
409 for enum in protocol.enums:
410 java_name = name_c_to_caps_camel(re.sub(r'_t$', "", enum.name))
411 java_type = java_name if not enum.is_bitmask else "Set<{}>".format(java_name)
412 enum_types[enum.name] = \
413 JType(java_type)\
414 .op(read = "{}SerializerVer$version.readFrom(bb)".format(java_name),
415 write ="{}SerializerVer$version.writeTo(bb, $name)".format(java_name))
416 return enum_types
417
Andreas Wundsam2be7da52013-08-22 07:34:25 -0700418def make_match_field_jtype(sub_type_name="?"):
419 return JType("MatchField<{}>".format(sub_type_name))
420
Andreas Wundsam27303462013-07-16 12:52:35 -0700421
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700422# Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}>
Andreas Wundsam27303462013-07-16 12:52:35 -0700423def make_standard_list_jtype(c_type):
424 m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
425 if not m:
426 raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
427 base_name = m.group(1)
428 java_base_name = name_c_to_caps_camel(base_name)
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700429
430 # read op assumes the class has a public final static field READER that implements
431 # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer
432 # write op assumes class implements Writeable
Yotam Harchold7b84202013-07-26 16:08:10 -0700433 return JType("List<OF%s>" % java_base_name) \
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700434 .op(
435 read= 'ChannelUtils.readList(bb, $length, OF%sVer$version.READER)' % java_base_name, \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700436 write='ChannelUtils.writeList(bb, $name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700437
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700438
Andreas Wundsam7cfeac32013-09-17 13:53:48 -0700439
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700440#### main entry point for conversion of LOXI types (c_types) Java types.
441# FIXME: This badly needs a refactoring
442
Andreas Wundsam27303462013-07-16 12:52:35 -0700443def convert_to_jtype(obj_name, field_name, c_type):
444 """ Convert from a C type ("uint_32") to a java type ("U32")
445 and return a JType object with the size, internal type, and marshalling functions"""
446 if obj_name in exceptions and field_name in exceptions[obj_name]:
447 return exceptions[obj_name][field_name]
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700448 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 -0700449 return JType("OFType", 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700450 .op(read='bb.readByte()', write='bb.writeByte($name)')
Andreas Wundsam27303462013-07-16 12:52:35 -0700451 elif field_name == "type" and re.match(r'of_action.*', obj_name):
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700452 return JType("OFActionType", 'short') \
Andreas Wundsam46d230f2013-08-02 22:24:06 -0700453 .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
454 .op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
Andreas Wundsam27303462013-07-16 12:52:35 -0700455 elif field_name == "version" and c_type == "uint8_t":
Andreas Wundsam2bf357c2013-08-03 22:50:40 -0700456 return JType("OFVersion", 'byte') \
Yotam Harchold7b84202013-07-26 16:08:10 -0700457 .op(read='bb.readByte()', write='bb.writeByte($name)')
Rob Vaterlausb10ae552013-09-23 14:39:39 -0700458 elif field_name == "buffer_id" and c_type == "uint32_t":
459 return JType("OFBufferId") \
460 .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())")
Andreas Wundsam27303462013-07-16 12:52:35 -0700461 elif c_type in default_mtype_to_jtype_convert_map:
462 return default_mtype_to_jtype_convert_map[c_type]
463 elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
464 return make_standard_list_jtype(c_type)
Andreas Wundsam7cfeac32013-09-17 13:53:48 -0700465 elif c_type in enum_java_types():
466 return enum_java_types()[c_type]
Andreas Wundsam27303462013-07-16 12:52:35 -0700467 else:
468 print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
469 jtype = name_c_to_caps_camel(re.sub(r'_t$', "", c_type))
470 return JType(jtype)
Andreas Wundsamd8bcedf2013-08-03 21:23:37 -0700471
472
473#### Enum specific wiretype definitions
474enum_wire_types = {
475 "uint8_t": JType("byte").op(read="bb.readByte()", write="bb.writeByte($name)"),
476 "uint16_t": JType("short").op(read="bb.readShort()", write="bb.writeShort($name)"),
477 "uint32_t": JType("int").op(read="bb.readInt()", write="bb.writeInt($name)"),
478 "uint64_t": JType("long").op(read="bb.readLong()", write="bb.writeLong($name)"),
479}
480
481def convert_enum_wire_type_to_jtype(wire_type):
482 return enum_wire_types[wire_type]