Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 1 | import errno |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 2 | import os |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 3 | import re |
| 4 | import subprocess |
| 5 | import time |
| 6 | |
Andreas Wundsam | 7cfeac3 | 2013-09-17 13:53:48 -0700 | [diff] [blame] | 7 | from generic_utils import memoize |
| 8 | import loxi_utils.loxi_utils as loxi_utils |
| 9 | import of_g |
| 10 | |
Andreas Wundsam | 2be7da5 | 2013-08-22 07:34:25 -0700 | [diff] [blame] | 11 | def 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 Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 18 | def 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 | |
| 26 | def name_c_to_caps_camel(name): |
| 27 | """ 'of_stats_reply' to 'OFStatsReply' """ |
| 28 | camel = name_c_to_camel(name.title()) |
Andreas Wundsam | 7cfeac3 | 2013-09-17 13:53:48 -0700 | [diff] [blame] | 29 | if camel.startswith('Ofp'): |
| 30 | return camel.replace('Ofp','OF',1) |
| 31 | elif camel.startswith('Of'): |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 32 | return camel.replace('Of','OF',1) |
| 33 | else: |
| 34 | return camel |
| 35 | |
Rob Vaterlaus | feee371 | 2013-09-30 11:24:19 -0700 | [diff] [blame] | 36 | java_primitive_types = set("boolean byte char short int long".split(" ")) |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 37 | |
| 38 | ### info table about java primitive types, for casting literals in the source code |
| 39 | # { name : (signed?, length_in_bits) } |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 40 | java_primitives_info = { |
Rob Vaterlaus | feee371 | 2013-09-30 11:24:19 -0700 | [diff] [blame] | 41 | 'boolean' : (False, 8), |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 42 | 'byte' : (True, 8), |
| 43 | 'char' : (False, 16), |
| 44 | 'short' : (True, 16), |
| 45 | 'int' : (True, 32), |
| 46 | 'long' : (True, 64), |
| 47 | } |
| 48 | |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 49 | def format_primitive_literal(t, value): |
| 50 | """ Format a primitive numeric literal for inclusion in the |
| 51 | java source code. Takes care of casting the literal |
Rob Vaterlaus | feee371 | 2013-09-30 11:24:19 -0700 | [diff] [blame] | 52 | appropriately for correct representation despite Java's |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 53 | signed-craziness |
| 54 | """ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 55 | signed, bits = java_primitives_info[t] |
| 56 | max = (1 << bits)-1 |
| 57 | if value > max: |
| 58 | raise Exception("Value %d to large for type %s" % (value, t)) |
| 59 | |
| 60 | if signed: |
| 61 | max_pos = (1 << (bits-1)) - 1 |
| 62 | |
| 63 | if value > max_pos: |
| 64 | if t == "long": |
| 65 | return str((1 << bits) - value) |
| 66 | else: |
| 67 | return "(%s) 0x%x" % (t, value) |
| 68 | else: |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 69 | return "0x%x%s" % (value, "L" if t=="long" else "") |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 70 | |
Andreas Wundsam | e916d6f | 2013-07-30 11:33:58 -0700 | [diff] [blame] | 71 | ANY = 0xFFFFFFFFFFFFFFFF |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 72 | |
| 73 | class VersionOp: |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 74 | def __init__(self, version=ANY, read=None, write=None, default=None): |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 75 | self.version = version |
| 76 | self.read = read |
| 77 | self.write = write |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 78 | self.default = default |
Andreas Wundsam | e916d6f | 2013-07-30 11:33:58 -0700 | [diff] [blame] | 79 | |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 80 | def __str__(self): |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 81 | return "[Version: %d, Read: '%s', Write: '%s', Default: '%s' ]" % (self.version, self.read, self.write, self.default ) |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 82 | |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 83 | ### FIXME: This class should really be cleaned up |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 84 | class JType(object): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 85 | """ Wrapper class to hold C to Java type conversion information. JTypes can have a 'public' |
| 86 | and or 'private' java type associated with them and can define how those types can be |
| 87 | read from and written to ChannelBuffers. |
| 88 | |
| 89 | """ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 90 | def __init__(self, pub_type, priv_type=None): |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 91 | self.pub_type = pub_type # the type we expose externally, e.g. 'U8' |
| 92 | if priv_type is None: |
| 93 | priv_type = pub_type |
| 94 | self.priv_type = priv_type # the internal storage type |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 95 | self.ops = {} |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 96 | |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 97 | def op(self, version=ANY, read=None, write=None, default=None, pub_type=ANY): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 98 | """ |
| 99 | define operations to be performed for reading and writing this type |
| 100 | (when read_op, write_op is called). The operations 'read' and 'write' |
| 101 | can either be strings ($name, and $version and $length will be replaced), |
| 102 | or callables (name, version and length) will be passed. |
| 103 | |
| 104 | @param version int OF version to define operation for, or ANY for all |
| 105 | @param pub_type boolean whether to define operations for the public type (True), the |
| 106 | private type(False) or both (ALL) |
| 107 | @param read read expression (either string or callable)s |
| 108 | @param write write expression (either string or callable) |
| 109 | """ |
| 110 | |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 111 | pub_types = [ pub_type ] if pub_type is not ANY else [ False, True ] |
| 112 | for pub_type in pub_types: |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 113 | self.ops[(version, pub_type)] = VersionOp(version, read, write, default) |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 114 | return self |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 115 | |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 116 | def format_value(self, value, pub_type=True): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 117 | # Format a constant value of this type, for inclusion in the java source code |
| 118 | # For primitive types, takes care of casting the value appropriately, to |
| 119 | # cope with java's signedness limitation |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 120 | t = self.pub_type if pub_type else self.priv_type |
| 121 | if t in java_primitive_types: |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 122 | return format_primitive_literal(t, value) |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 123 | else: |
| 124 | return value |
Andreas Wundsam | bf1dbbd | 2013-07-30 11:07:59 -0700 | [diff] [blame] | 125 | |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 126 | @property |
| 127 | def public_type(self): |
| 128 | """ return the public type """ |
| 129 | return self.pub_type |
| 130 | |
| 131 | def priv(self): |
| 132 | """ return the public type """ |
| 133 | return self.priv_type |
| 134 | |
| 135 | def has_priv(self): |
| 136 | """ Is the private type different from the public one?""" |
| 137 | return self.pub_type != self.priv_type |
| 138 | |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 139 | def read_op(self, version=None, length=None, pub_type=True): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 140 | """ return a Java stanza that reads a value of this JType from ChannelBuffer bb. |
| 141 | @param version int - OF wire version to generate expression for |
| 142 | @param pub_type boolean use this JTypes 'public' (True), or private (False) representation |
| 143 | @param length string, for operations that need it (e.g., read a list of unknown length) |
| 144 | Java expression evaluating to the byte length to be read. Defaults to the remainig |
| 145 | length of the message. |
| 146 | @return string containing generated Java expression. |
| 147 | """ |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 148 | if length is None: |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 149 | # assumes that |
| 150 | # (1) length of the message has been read to 'length' |
| 151 | # (2) readerIndex at the start of the message has been stored in 'start' |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 152 | length = "length - (bb.readerIndex() - start)"; |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 153 | |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 154 | ver = ANY if version is None else version.int_version |
| 155 | _read_op = None |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 156 | if (ver, pub_type) in self.ops: |
| 157 | _read_op = self.ops[(ver, pub_type)].read or self.ops[(ANY, pub_type)].read |
| 158 | elif (ANY, pub_type) in self.ops: |
| 159 | _read_op = self.ops[(ANY, pub_type)].read |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 160 | if _read_op is None: |
Andreas Wundsam | 951ada3 | 2013-08-01 22:05:38 -0700 | [diff] [blame] | 161 | _read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 162 | if callable(_read_op): |
| 163 | return _read_op(version) |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 164 | else: |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 165 | return _read_op.replace("$length", str(length)).replace("$version", version.of_version) |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 166 | |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 167 | def write_op(self, version=None, name=None, pub_type=True): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 168 | """ return a Java stanza that writes a value of this JType contained in Java expression |
| 169 | 'name' to ChannelBuffer bb. |
| 170 | @param name string containing Java expression that evaluations to the value to be written |
| 171 | @param version int - OF wire version to generate expression for |
| 172 | @param pub_type boolean use this JTypes 'public' (True), or private (False) representation |
| 173 | @return string containing generated Java expression. |
| 174 | """ |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 175 | ver = ANY if version is None else version.int_version |
| 176 | _write_op = None |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 177 | if (ver, pub_type) in self.ops: |
| 178 | _write_op = self.ops[(ver, pub_type)].write or self.ops[(ANY, pub_type)].write |
| 179 | elif (ANY, pub_type) in self.ops: |
| 180 | _write_op = self.ops[(ANY, pub_type)].write |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 181 | if _write_op is None: |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 182 | |
Andreas Wundsam | 951ada3 | 2013-08-01 22:05:38 -0700 | [diff] [blame] | 183 | _write_op = 'ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 184 | if callable(_write_op): |
| 185 | return _write_op(version, name) |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 186 | else: |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 187 | return _write_op.replace("$name", str(name)).replace("$version", version.of_version) |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 188 | |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 189 | def default_op(self, version=None, pub_type=True): |
| 190 | """ return a Java stanza that returns a default value of this JType. |
| 191 | @param version JavaOFVersion |
| 192 | @return string containing generated Java expression. |
| 193 | """ |
| 194 | ver = ANY if version is None else version.int_version |
| 195 | _default_op = None |
| 196 | if (ver, pub_type) in self.ops: |
| 197 | _default_op = self.ops[(ver, pub_type)].default or self.ops[(ANY, pub_type)].default |
| 198 | elif (ANY, pub_type) in self.ops: |
| 199 | _default_op = self.ops[(ANY, pub_type)].default |
| 200 | if _default_op is None: |
| 201 | _default_op = self.format_value(0) if self.is_primitive else "null" |
| 202 | if callable(_default_op): |
| 203 | return _default_op(version, name) |
| 204 | else: |
| 205 | return _default_op.replace("$version", version.of_version) |
| 206 | |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 207 | def skip_op(self, version=None, length=None): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 208 | """ return a java stanza that skips an instance of JType in the input ChannelBuffer 'bb'. |
| 209 | This is used in the Reader implementations for virtual classes (because after the |
| 210 | discriminator field, the concrete Reader instance will re-read all the fields) |
| 211 | Currently just delegates to read_op + throws away the result.""" |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 212 | return self.read_op(version, length) |
| 213 | |
Andreas Wundsam | e916d6f | 2013-07-30 11:33:58 -0700 | [diff] [blame] | 214 | @property |
| 215 | def is_primitive(self): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 216 | """ return true if the pub_type is a java primitive type (and thus needs |
| 217 | special treatment, because it doesn't have methods)""" |
Andreas Wundsam | e916d6f | 2013-07-30 11:33:58 -0700 | [diff] [blame] | 218 | return self.pub_type in java_primitive_types |
| 219 | |
| 220 | @property |
| 221 | def is_array(self): |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 222 | """ return true iff the pub_type is a Java array (and thus requires special |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 223 | treatment for equals / toString etc.) """ |
Andreas Wundsam | e916d6f | 2013-07-30 11:33:58 -0700 | [diff] [blame] | 224 | return self.pub_type.endswith("[]") |
| 225 | |
| 226 | |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 227 | ##### Predefined JType mappings |
| 228 | # FIXME: This list needs to be pruned / cleaned up. Most of these are schematic. |
| 229 | |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 230 | u8 = JType('short', 'byte') \ |
Andreas Wundsam | 83d877a | 2013-09-30 14:26:44 -0700 | [diff] [blame] | 231 | .op(read='U8.f(bb.readByte())', write='bb.writeByte(U8.t($name))', pub_type=True) \ |
| 232 | .op(read='bb.readByte()', write='bb.writeByte($name)', pub_type=False) |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 233 | u8_list = JType('List<U8>') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 234 | .op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 235 | u16 = JType('int', 'short') \ |
| 236 | .op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))', pub_type=True) \ |
| 237 | .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False) |
| 238 | u32 = JType('long', 'int') \ |
| 239 | .op(read='U32.f(bb.readInt())', write='bb.writeInt(U32.t($name))', pub_type=True) \ |
| 240 | .op(read='bb.readInt()', write='bb.writeInt($name)', pub_type=False) |
| 241 | u32_list = JType('List<U32>', 'int[]') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 242 | .op( |
| 243 | read='ChannelUtils.readList(bb, $length, U32.READER)', |
| 244 | write='ChannelUtils.writeList(bb, $name)', |
| 245 | default="ImmutableList.<U32>of()"); |
Yotam Harchol | 5804f77 | 2013-08-21 17:35:31 -0700 | [diff] [blame] | 246 | u8obj = JType('U8', 'U8') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 247 | .op(read='U8.of(bb.readByte())', write='bb.writeByte($name.getRaw())', default="U8.ZERO") |
Yotam Harchol | 5804f77 | 2013-08-21 17:35:31 -0700 | [diff] [blame] | 248 | u32obj = JType('U32', 'U32') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 249 | .op(read='U32.of(bb.readInt())', write='bb.writeInt($name.getRaw())', default="U32.ZERO") |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 250 | u64 = JType('U64', 'U64') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 251 | .op(read='U64.ofRaw(bb.readLong())', write='bb.writeLong($name.getValue())', default="U64.ZERO") |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 252 | of_port = JType("OFPort") \ |
Andreas Wundsam | ad499c9 | 2013-09-28 18:56:49 -0700 | [diff] [blame] | 253 | .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFPort.ANY") \ |
| 254 | .op(version=ANY, read="OFPort.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFPort.ANY") |
Andreas Wundsam | e962d37 | 2013-10-02 18:15:58 -0700 | [diff] [blame] | 255 | # the same OFPort, but with a default value of ZERO, only for OF10 match |
| 256 | of_port_match_v1 = JType("OFPort") \ |
| 257 | .op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFPort.ZERO") |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 258 | actions_list = JType('List<OFAction>') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 259 | .op(read='ChannelUtils.readList(bb, $length, OFActionVer$version.READER)', |
| 260 | write='ChannelUtils.writeList(bb, $name);', |
| 261 | default='ImmutableList.<OFAction>of()') |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 262 | instructions_list = JType('List<OFInstruction>') \ |
| 263 | .op(read='ChannelUtils.readList(bb, $length, OFInstructionVer$version.READER)', \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 264 | write='ChannelUtils.writeList(bb, $name)', |
| 265 | default='ImmutableList.<OFInstruction>of()') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 266 | buckets_list = JType('List<OFBucket>') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 267 | .op(read='ChannelUtils.readList(bb, $length, OFBucketVer$version.READER)', |
| 268 | write='ChannelUtils.writeList(bb, $name)', |
| 269 | default='ImmutableList.<OFBucket>of()') |
Rob Vaterlaus | 7db900a | 2013-09-17 14:18:49 -0700 | [diff] [blame] | 270 | port_desc_list = JType('List<OFPortDesc>') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 271 | .op(read='ChannelUtils.readList(bb, $length, OFPortDescVer$version.READER)', |
| 272 | write='ChannelUtils.writeList(bb, $name)', |
| 273 | default='ImmutableList.<OFPortDesc>of()') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 274 | port_desc = JType('OFPortDesc') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 275 | .op(read='OFPortDescVer$version.READER.readFrom(bb)', \ |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 276 | write='$name.writeTo(bb)') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 277 | packet_queue_list = JType('List<OFPacketQueue>') \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 278 | .op(read='ChannelUtils.readList(bb, $length, OFPacketQueueVer$version.READER)', |
| 279 | write='ChannelUtils.writeList(bb, $name);', |
| 280 | default='ImmutableList.<OFPacketQueue>of()') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 281 | octets = JType('byte[]') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 282 | .op(read='ChannelUtils.readBytes(bb, $length)', \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 283 | write='bb.writeBytes($name)', \ |
| 284 | default="new byte[0]"); |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 285 | of_match = JType('Match') \ |
Andreas Wundsam | 951ada3 | 2013-08-01 22:05:38 -0700 | [diff] [blame] | 286 | .op(read='ChannelUtilsVer$version.readOFMatch(bb)', \ |
Andreas Wundsam | e962d37 | 2013-10-02 18:15:58 -0700 | [diff] [blame] | 287 | write='$name.writeTo(bb)', |
| 288 | default="OFFactoryVer$version.MATCH_WILDCARD_ALL"); |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 289 | flow_mod_cmd = JType('OFFlowModCommand', 'short') \ |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 290 | .op(version=1, read="bb.readShort()", write="bb.writeShort($name)") \ |
| 291 | .op(version=ANY, read="bb.readByte()", write="bb.writeByte($name)") |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 292 | mac_addr = JType('MacAddress') \ |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 293 | .op(read="MacAddress.read6Bytes(bb)", \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 294 | write="$name.write6Bytes(bb)", |
| 295 | default="MacAddress.NONE") |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 296 | port_name = JType('String') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 297 | .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 298 | write='ChannelUtils.writeFixedLengthString(bb, $name, 16)', |
| 299 | default='""') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 300 | desc_str = JType('String') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 301 | .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 302 | write='ChannelUtils.writeFixedLengthString(bb, $name, 256)', |
| 303 | default='""') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 304 | serial_num = JType('String') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 305 | .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 306 | write='ChannelUtils.writeFixedLengthString(bb, $name, 32)', |
| 307 | default='""') |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 308 | table_name = JType('String') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 309 | .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 310 | write='ChannelUtils.writeFixedLengthString(bb, $name, 32)', |
| 311 | default='""') |
Yotam Harchol | a289d55 | 2013-09-16 10:10:40 -0700 | [diff] [blame] | 312 | ipv4 = JType("IPv4Address") \ |
| 313 | .op(read="IPv4Address.read4Bytes(bb)", \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 314 | write="$name.write4Bytes(bb)", |
| 315 | default='IPv4Address.NONE') |
Yotam Harchol | a289d55 | 2013-09-16 10:10:40 -0700 | [diff] [blame] | 316 | ipv6 = JType("IPv6Address") \ |
| 317 | .op(read="IPv6Address.read16Bytes(bb)", \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 318 | write="$name.write16Bytes(bb)", |
| 319 | default='IPv6Address.NONE') |
Andreas Wundsam | bf1dbbd | 2013-07-30 11:07:59 -0700 | [diff] [blame] | 320 | packetin_reason = JType("OFPacketInReason")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 321 | .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)", |
| 322 | write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)") |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 323 | transport_port = JType("TransportPort")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 324 | .op(read="TransportPort.read2Bytes(bb)", |
| 325 | write="$name.write2Bytes(bb)", |
| 326 | default="TransportPort.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 327 | eth_type = JType("EthType")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 328 | .op(read="EthType.read2Bytes(bb)", |
| 329 | write="$name.write2Bytes(bb)", |
| 330 | default="EthType.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 331 | vlan_vid = JType("VlanVid")\ |
Andreas Wundsam | 55b71ce | 2013-10-01 19:26:46 -0700 | [diff] [blame] | 332 | .op(version=1, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \ |
| 333 | .op(version=2, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \ |
| 334 | .op(version=ANY, read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="VlanVid.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 335 | vlan_pcp = JType("VlanPcp")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 336 | .op(read="VlanPcp.readByte(bb)", |
| 337 | write="$name.writeByte(bb)", |
| 338 | default="VlanPcp.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 339 | ip_dscp = JType("IpDscp")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 340 | .op(read="IpDscp.readByte(bb)", |
| 341 | write="$name.writeByte(bb)", |
| 342 | default="IpDscp.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 343 | ip_ecn = JType("IpEcn")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 344 | .op(read="IpEcn.readByte(bb)", |
| 345 | write="$name.writeByte(bb)", |
| 346 | default="IpEcn.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 347 | ip_proto = JType("IpProtocol")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 348 | .op(read="IpProtocol.readByte(bb)", |
| 349 | write="$name.writeByte(bb)", |
| 350 | default="IpProtocol.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 351 | icmpv4_type = JType("ICMPv4Type")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 352 | .op(read="ICMPv4Type.readByte(bb)", |
| 353 | write="$name.writeByte(bb)", |
| 354 | default="ICMPv4Type.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 355 | icmpv4_code = JType("ICMPv4Code")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 356 | .op(read="ICMPv4Code.readByte(bb)", |
| 357 | write="$name.writeByte(bb)", |
| 358 | default="ICMPv4Code.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 359 | arp_op = JType("ArpOpcode")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 360 | .op(read="ArpOpcode.read2Bytes(bb)", |
| 361 | write="$name.write2Bytes(bb)", |
| 362 | default="ArpOpcode.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 363 | ipv6_flabel = JType("IPv6FlowLabel")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 364 | .op(read="IPv6FlowLabel.read4Bytes(bb)", |
| 365 | write="$name.write4Bytes(bb)", |
| 366 | default="IPv6FlowLabel.NONE") |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 367 | metadata = JType("OFMetadata")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 368 | .op(read="OFMetadata.read8Bytes(bb)", |
| 369 | write="$name.write8Bytes(bb)", |
| 370 | default="OFMetadata.NONE") |
Andreas Wundsam | 2be7da5 | 2013-08-22 07:34:25 -0700 | [diff] [blame] | 371 | oxm = JType("OFOxm<?>")\ |
| 372 | .op( read="OFOxmVer$version.READER.readFrom(bb)", |
| 373 | write="$name.writeTo(bb)") |
| 374 | oxm_list = JType("OFOxmList") \ |
| 375 | .op( |
| 376 | read= 'OFOxmList.readFrom(bb, $length, OFOxmVer$version.READER)', \ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 377 | write='$name.writeTo(bb)', |
| 378 | default="OFOxmList.EMPTY") |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 379 | meter_features = JType("OFMeterFeatures")\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 380 | .op(read="OFMeterFeaturesVer$version.READER.readFrom(bb)", |
| 381 | write="$name.writeTo(bb)") |
| 382 | flow_wildcards = JType("int") \ |
| 383 | .op(read='bb.readInt()', |
| 384 | write='bb.writeInt($name)', |
| 385 | default="OFFlowWildcardsSerializerVer$version.ALL_VAL") |
| 386 | table_stats_wildcards = JType("int") \ |
| 387 | .op(read='bb.readInt()', |
| 388 | write='bb.writeInt($name)') |
Yotam Harchol | 2c53558 | 2013-10-01 15:50:20 -0700 | [diff] [blame] | 389 | port_bitmap = JType('OFBitMask128') \ |
| 390 | .op(read='OFBitMask128.read16Bytes(bb)', |
Yotam Harchol | a11f38b | 2013-09-26 15:38:17 -0700 | [diff] [blame] | 391 | write='$name.write16Bytes(bb)', |
Yotam Harchol | 2c53558 | 2013-10-01 15:50:20 -0700 | [diff] [blame] | 392 | default='OFBitMask128.NONE') |
Andreas Wundsam | 37e0fb1 | 2013-09-28 18:57:57 -0700 | [diff] [blame] | 393 | table_id = JType("TableId") \ |
| 394 | .op(read='TableId.readByte(bb)', |
| 395 | write='$name.writeByte(bb)', |
| 396 | default='TableId.ALL') |
Andreas Wundsam | 45c95f8 | 2013-10-08 15:04:23 -0700 | [diff] [blame] | 397 | table_id_default_zero = JType("TableId") \ |
| 398 | .op(read='TableId.readByte(bb)', |
| 399 | write='$name.writeByte(bb)', |
| 400 | default='TableId.ZERO') |
Andreas Wundsam | a098102 | 2013-10-02 18:15:06 -0700 | [diff] [blame] | 401 | of_version = JType("OFVersion", 'byte') \ |
| 402 | .op(read='bb.readByte()', write='bb.writeByte($name)') |
Rob Vaterlaus | b10ae55 | 2013-09-23 14:39:39 -0700 | [diff] [blame] | 403 | |
Andreas Wundsam | 8ec3bcc | 2013-09-16 19:44:00 -0700 | [diff] [blame] | 404 | port_speed = JType("PortSpeed") |
Rob Vaterlaus | 4d31194 | 2013-09-24 13:41:44 -0700 | [diff] [blame] | 405 | error_type = JType("OFErrorType") |
Rob Vaterlaus | feee371 | 2013-09-30 11:24:19 -0700 | [diff] [blame] | 406 | boolean = JType("boolean", "byte") \ |
| 407 | .op(read='(bb.readByte() != 0)', |
| 408 | write='bb.writeByte($name ? 1 : 0)', |
| 409 | default="false") |
| 410 | datapath_id = JType("DatapathId") \ |
| 411 | .op(read='DatapathId.of(bb.readLong())', |
| 412 | write='bb.writeLong($name.getLong())', |
| 413 | default='DatapathId.NONE') |
Andreas Wundsam | 2be7da5 | 2013-08-22 07:34:25 -0700 | [diff] [blame] | 414 | |
| 415 | generic_t = JType("T") |
| 416 | |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 417 | |
| 418 | default_mtype_to_jtype_convert_map = { |
| 419 | 'uint8_t' : u8, |
| 420 | 'uint16_t' : u16, |
| 421 | 'uint32_t' : u32, |
| 422 | 'uint64_t' : u64, |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 423 | 'of_port_no_t' : of_port, |
| 424 | 'list(of_action_t)' : actions_list, |
| 425 | 'list(of_instruction_t)' : instructions_list, |
| 426 | 'list(of_bucket_t)': buckets_list, |
| 427 | 'list(of_port_desc_t)' : port_desc_list, |
| 428 | 'list(of_packet_queue_t)' : packet_queue_list, |
| 429 | 'list(of_uint32_t)' : u32_list, |
| 430 | 'list(of_uint8_t)' : u8_list, |
Andreas Wundsam | 2be7da5 | 2013-08-22 07:34:25 -0700 | [diff] [blame] | 431 | 'list(of_oxm_t)' : oxm_list, |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 432 | 'of_octets_t' : octets, |
| 433 | 'of_match_t': of_match, |
| 434 | 'of_fm_cmd_t': flow_mod_cmd, |
| 435 | 'of_mac_addr_t': mac_addr, |
| 436 | 'of_port_desc_t': port_desc, |
| 437 | 'of_desc_str_t': desc_str, |
| 438 | 'of_serial_num_t': serial_num, |
| 439 | 'of_port_name_t': port_name, |
| 440 | 'of_table_name_t': table_name, |
| 441 | 'of_ipv4_t': ipv4, |
| 442 | 'of_ipv6_t': ipv6, |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 443 | 'of_wc_bmap_t': flow_wildcards, |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 444 | 'of_oxm_t': oxm, |
| 445 | 'of_meter_features_t': meter_features, |
Yotam Harchol | 595c644 | 2013-09-27 16:29:08 -0700 | [diff] [blame] | 446 | 'of_bitmap_128_t': port_bitmap |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 447 | } |
| 448 | |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 449 | ## Map that defines exceptions from the standard loxi->java mapping scheme |
| 450 | # map of {<loxi_class_name> : { <loxi_member_name> : <JType instance> } } |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 451 | exceptions = { |
Yotam Harchol | c742e20 | 2013-08-15 12:16:24 -0700 | [diff] [blame] | 452 | 'of_packet_in': { 'data' : octets, 'reason': packetin_reason }, |
| 453 | 'of_oxm_tcp_src' : { 'value' : transport_port }, |
| 454 | 'of_oxm_tcp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port }, |
| 455 | 'of_oxm_tcp_dst' : { 'value' : transport_port }, |
| 456 | 'of_oxm_tcp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port }, |
| 457 | 'of_oxm_udp_src' : { 'value' : transport_port }, |
| 458 | 'of_oxm_udp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port }, |
| 459 | 'of_oxm_udp_dst' : { 'value' : transport_port }, |
| 460 | 'of_oxm_udp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port }, |
| 461 | 'of_oxm_sctp_src' : { 'value' : transport_port }, |
| 462 | 'of_oxm_sctp_src_masked' : { 'value' : transport_port, 'value_mask' : transport_port }, |
| 463 | 'of_oxm_sctp_dst' : { 'value' : transport_port }, |
| 464 | 'of_oxm_sctp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port }, |
| 465 | 'of_oxm_eth_type' : { 'value' : eth_type }, |
| 466 | 'of_oxm_eth_type_masked' : { 'value' : eth_type, 'value_mask' : eth_type }, |
| 467 | 'of_oxm_vlan_vid' : { 'value' : vlan_vid }, |
| 468 | 'of_oxm_vlan_vid_masked' : { 'value' : vlan_vid, 'value_mask' : vlan_vid }, |
| 469 | 'of_oxm_vlan_pcp' : { 'value' : vlan_pcp }, |
| 470 | 'of_oxm_vlan_pcp_masked' : { 'value' : vlan_pcp, 'value_mask' : vlan_pcp }, |
| 471 | 'of_oxm_ip_dscp' : { 'value' : ip_dscp }, |
| 472 | 'of_oxm_ip_dscp_masked' : { 'value' : ip_dscp, 'value_mask' : ip_dscp }, |
| 473 | 'of_oxm_ip_ecn' : { 'value' : ip_ecn }, |
| 474 | 'of_oxm_ip_ecn_masked' : { 'value' : ip_ecn, 'value_mask' : ip_ecn }, |
| 475 | 'of_oxm_ip_proto' : { 'value' : ip_proto }, |
| 476 | 'of_oxm_ip_proto_masked' : { 'value' : ip_proto, 'value_mask' : ip_proto }, |
| 477 | 'of_oxm_icmpv4_type' : { 'value' : icmpv4_type }, |
| 478 | 'of_oxm_icmpv4_type_masked' : { 'value' : icmpv4_type, 'value_mask' : icmpv4_type }, |
| 479 | 'of_oxm_icmpv4_code' : { 'value' : icmpv4_code }, |
| 480 | 'of_oxm_icmpv4_code_masked' : { 'value' : icmpv4_code, 'value_mask' : icmpv4_code }, |
| 481 | 'of_oxm_arp_op' : { 'value' : arp_op }, |
| 482 | 'of_oxm_arp_op_masked' : { 'value' : arp_op, 'value_mask' : arp_op }, |
| 483 | 'of_oxm_arp_spa' : { 'value' : ipv4 }, |
| 484 | 'of_oxm_arp_spa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 }, |
| 485 | 'of_oxm_arp_tpa' : { 'value' : ipv4 }, |
| 486 | 'of_oxm_arp_tpa_masked' : { 'value' : ipv4, 'value_mask' : ipv4 }, |
| 487 | 'of_oxm_ipv6_flabel' : { 'value' : ipv6_flabel }, |
| 488 | 'of_oxm_ipv6_flabel_masked' : { 'value' : ipv6_flabel, 'value_mask' : ipv6_flabel }, |
| 489 | 'of_oxm_metadata' : { 'value' : metadata }, |
| 490 | 'of_oxm_metadata_masked' : { 'value' : metadata, 'value_mask' : metadata }, |
Yotam Harchol | 5804f77 | 2013-08-21 17:35:31 -0700 | [diff] [blame] | 491 | |
| 492 | 'of_oxm_icmpv6_code' : { 'value' : u8obj }, |
| 493 | 'of_oxm_icmpv6_code_masked' : { 'value' : u8obj, 'value_mask' : u8obj }, |
| 494 | 'of_oxm_icmpv6_type' : { 'value' : u8obj }, |
| 495 | 'of_oxm_icmpv6_type_masked' : { 'value' : u8obj, 'value_mask' : u8obj }, |
| 496 | 'of_oxm_mpls_label' : { 'value' : u32obj }, |
| 497 | 'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj }, |
| 498 | 'of_oxm_mpls_tc' : { 'value' : u8obj }, |
| 499 | 'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj }, |
Yotam Harchol | a11f38b | 2013-09-26 15:38:17 -0700 | [diff] [blame] | 500 | |
Yotam Harchol | 595c644 | 2013-09-27 16:29:08 -0700 | [diff] [blame] | 501 | 'of_oxm_bsn_in_ports_128' : { 'value': port_bitmap }, |
| 502 | 'of_oxm_bsn_in_ports_128_masked' : { 'value': port_bitmap, 'value_mask': port_bitmap }, |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 503 | |
| 504 | 'of_table_stats_entry': { 'wildcards': table_stats_wildcards }, |
| 505 | 'of_match_v1': { 'vlan_vid' : vlan_vid, 'vlan_pcp': vlan_pcp, |
| 506 | 'eth_type': eth_type, 'ip_dscp': ip_dscp, 'ip_proto': ip_proto, |
Andreas Wundsam | e962d37 | 2013-10-02 18:15:58 -0700 | [diff] [blame] | 507 | 'tcp_src': transport_port, 'tcp_dst': transport_port, |
| 508 | 'in_port': of_port_match_v1 |
Rob Vaterlaus | feee371 | 2013-09-30 11:24:19 -0700 | [diff] [blame] | 509 | }, |
| 510 | 'of_bsn_set_l2_table_request': { 'l2_table_enable': boolean }, |
| 511 | 'of_bsn_set_l2_table_reply': { 'l2_table_enable': boolean }, |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 512 | } |
| 513 | |
Andreas Wundsam | 7cfeac3 | 2013-09-17 13:53:48 -0700 | [diff] [blame] | 514 | |
| 515 | @memoize |
| 516 | def enum_java_types(): |
| 517 | enum_types = {} |
| 518 | |
| 519 | for protocol in of_g.ir.values(): |
| 520 | for enum in protocol.enums: |
| 521 | java_name = name_c_to_caps_camel(re.sub(r'_t$', "", enum.name)) |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 522 | if enum.is_bitmask: |
| 523 | java_type = "Set<{}>".format(java_name) |
| 524 | default_value = "ImmutableSet.<{}>of()".format(java_name) |
| 525 | else: |
| 526 | java_type = java_name |
| 527 | default_value = "null" |
Andreas Wundsam | 7cfeac3 | 2013-09-17 13:53:48 -0700 | [diff] [blame] | 528 | enum_types[enum.name] = \ |
| 529 | JType(java_type)\ |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 530 | .op(read="{}SerializerVer$version.readFrom(bb)".format(java_name), |
| 531 | write="{}SerializerVer$version.writeTo(bb, $name)".format(java_name), |
| 532 | default=default_value) |
Andreas Wundsam | 7cfeac3 | 2013-09-17 13:53:48 -0700 | [diff] [blame] | 533 | return enum_types |
| 534 | |
Andreas Wundsam | 2be7da5 | 2013-08-22 07:34:25 -0700 | [diff] [blame] | 535 | def make_match_field_jtype(sub_type_name="?"): |
| 536 | return JType("MatchField<{}>".format(sub_type_name)) |
| 537 | |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 538 | |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 539 | # Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}> |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 540 | def make_standard_list_jtype(c_type): |
| 541 | m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type) |
| 542 | if not m: |
| 543 | raise Exception("Not a recgonized standard list type declaration: %s" % c_type) |
| 544 | base_name = m.group(1) |
| 545 | java_base_name = name_c_to_caps_camel(base_name) |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 546 | |
| 547 | # read op assumes the class has a public final static field READER that implements |
| 548 | # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer |
| 549 | # write op assumes class implements Writeable |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 550 | return JType("List<OF{}>".format(java_base_name)) \ |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 551 | .op( |
Andreas Wundsam | b3ed3ff | 2013-09-23 14:46:29 -0700 | [diff] [blame] | 552 | read= 'ChannelUtils.readList(bb, $length, OF{}Ver$version.READER)'.format(java_base_name), \ |
| 553 | write='ChannelUtils.writeList(bb, $name)', |
| 554 | default="ImmutableList.<OF{}>of()".format(java_base_name) |
| 555 | ) |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 556 | |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 557 | |
Andreas Wundsam | 7cfeac3 | 2013-09-17 13:53:48 -0700 | [diff] [blame] | 558 | |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 559 | #### main entry point for conversion of LOXI types (c_types) Java types. |
| 560 | # FIXME: This badly needs a refactoring |
| 561 | |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 562 | def convert_to_jtype(obj_name, field_name, c_type): |
| 563 | """ Convert from a C type ("uint_32") to a java type ("U32") |
| 564 | and return a JType object with the size, internal type, and marshalling functions""" |
| 565 | if obj_name in exceptions and field_name in exceptions[obj_name]: |
| 566 | return exceptions[obj_name][field_name] |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 567 | elif ( obj_name == "of_header" or loxi_utils.class_is_message(obj_name)) and field_name == "type" and c_type == "uint8_t": |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 568 | return JType("OFType", 'byte') \ |
Yotam Harchol | d7b8420 | 2013-07-26 16:08:10 -0700 | [diff] [blame] | 569 | .op(read='bb.readByte()', write='bb.writeByte($name)') |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 570 | elif field_name == "type" and re.match(r'of_action.*', obj_name): |
Andreas Wundsam | 2bf357c | 2013-08-03 22:50:40 -0700 | [diff] [blame] | 571 | return JType("OFActionType", 'short') \ |
Andreas Wundsam | 46d230f | 2013-08-02 22:24:06 -0700 | [diff] [blame] | 572 | .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\ |
| 573 | .op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True) |
Rob Vaterlaus | feee371 | 2013-09-30 11:24:19 -0700 | [diff] [blame] | 574 | elif field_name == "err_type": |
| 575 | return JType("OFErrorType", 'short') \ |
| 576 | .op(read='bb.readShort()', write='bb.writeShort($name)') |
| 577 | elif field_name == "stats_type": |
| 578 | return JType("OFStatsType", 'short') \ |
| 579 | .op(read='bb.readShort()', write='bb.writeShort($name)') |
Andreas Wundsam | 999c073 | 2013-10-01 19:29:16 -0700 | [diff] [blame] | 580 | elif field_name == "type" and re.match(r'of_instruction.*', obj_name): |
| 581 | return JType("OFInstructionType", 'short') \ |
| 582 | .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\ |
| 583 | .op(read="OFInstructionTypeSerializerVer$version.readFrom(bb)", write="OFInstructionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True) |
Andreas Wundsam | 45c95f8 | 2013-10-08 15:04:23 -0700 | [diff] [blame] | 584 | elif obj_name in ("of_flow_add", "of_flow_modify", "of_flow_modify_strict", "of_delete_strict") and field_name == "table_id" and c_type == "uint8_t": |
| 585 | return table_id_default_zero |
Andreas Wundsam | 37e0fb1 | 2013-09-28 18:57:57 -0700 | [diff] [blame] | 586 | elif field_name == "table_id" and c_type == "uint8_t": |
| 587 | return table_id |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 588 | elif field_name == "version" and c_type == "uint8_t": |
Andreas Wundsam | a098102 | 2013-10-02 18:15:06 -0700 | [diff] [blame] | 589 | return of_version |
Rob Vaterlaus | b10ae55 | 2013-09-23 14:39:39 -0700 | [diff] [blame] | 590 | elif field_name == "buffer_id" and c_type == "uint32_t": |
| 591 | return JType("OFBufferId") \ |
Rob Vaterlaus | fbd5b6b | 2013-09-24 15:55:47 -0700 | [diff] [blame] | 592 | .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())", default="OFBufferId.NO_BUFFER") |
Rob Vaterlaus | feee371 | 2013-09-30 11:24:19 -0700 | [diff] [blame] | 593 | elif field_name == 'datapath_id': |
| 594 | return datapath_id |
| 595 | elif field_name == 'actions' and obj_name == 'of_features_reply': |
| 596 | return JType("Set<OFActionType>") \ |
| 597 | .op(read='ChannelUtilsVer10.readSupportedActions(bb)', |
| 598 | write='ChannelUtilsVer10.writeSupportedActions(bb, $name)', |
| 599 | default='ImmutableSet.<OFActionType>of()') |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 600 | elif c_type in default_mtype_to_jtype_convert_map: |
| 601 | return default_mtype_to_jtype_convert_map[c_type] |
| 602 | elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type): |
| 603 | return make_standard_list_jtype(c_type) |
Andreas Wundsam | 7cfeac3 | 2013-09-17 13:53:48 -0700 | [diff] [blame] | 604 | elif c_type in enum_java_types(): |
| 605 | return enum_java_types()[c_type] |
Andreas Wundsam | 2730346 | 2013-07-16 12:52:35 -0700 | [diff] [blame] | 606 | else: |
| 607 | print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name) |
| 608 | jtype = name_c_to_caps_camel(re.sub(r'_t$', "", c_type)) |
| 609 | return JType(jtype) |
Andreas Wundsam | d8bcedf | 2013-08-03 21:23:37 -0700 | [diff] [blame] | 610 | |
| 611 | |
| 612 | #### Enum specific wiretype definitions |
| 613 | enum_wire_types = { |
| 614 | "uint8_t": JType("byte").op(read="bb.readByte()", write="bb.writeByte($name)"), |
| 615 | "uint16_t": JType("short").op(read="bb.readShort()", write="bb.writeShort($name)"), |
| 616 | "uint32_t": JType("int").op(read="bb.readInt()", write="bb.writeInt($name)"), |
| 617 | "uint64_t": JType("long").op(read="bb.readLong()", write="bb.writeLong($name)"), |
| 618 | } |
| 619 | |
| 620 | def convert_enum_wire_type_to_jtype(wire_type): |
| 621 | return enum_wire_types[wire_type] |