Merge remote-tracking branch 'upstream/master'
diff --git a/c_gen/templates/locitest/Makefile b/c_gen/templates/locitest/Makefile
index ed4ba13..a7a6f37 100644
--- a/c_gen/templates/locitest/Makefile
+++ b/c_gen/templates/locitest/Makefile
@@ -10,3 +10,6 @@
locitest: $(OBJS)
$(CC) $^ -o $@
+
+# BSN build system magic
+MODULE := locitest
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index b9e3ee1..feb3c72 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -49,7 +49,7 @@
class JavaModel(object):
# registry for enums that should not be generated
# set(${java_enum_name})
- enum_blacklist = set(("OFDefinitions", "OFPortNo", "OFVlanId"))
+ enum_blacklist = set(("OFDefinitions", "OFPortNo", "OFVlanId", "OFGroup"))
# registry for enum *entry* that should not be generated
# map: ${java_enum_name} -> set(${java_entry_entry_name})
enum_entry_blacklist = defaultdict(lambda: set(), OFFlowWildcards=set([ "NW_DST_BITS", "NW_SRC_BITS", "NW_SRC_SHIFT", "NW_DST_SHIFT" ]))
@@ -773,6 +773,10 @@
return int(self.ir_class.params['align']) if 'align' in self.ir_class.params else 0
@property
+ def length_includes_align(self):
+ return self.ir_class.params['length_includes_align'] == "True" if 'length_includes_align' in self.ir_class.params else False
+
+ @property
@memoize
def superclass(self):
return find(lambda c: c.version == self.version and c.c_name == self.ir_class.superclass, model.all_classes)
@@ -895,9 +899,9 @@
@property
def priv_value(self):
if self.name == "version":
- return self.msg.version.int_version
+ return self.java_type.format_value(self.msg.version.int_version, pub_type=False)
elif self.name == "length" or self.name == "len":
- return self.msg.length
+ return self.java_type.format_value(self.msg.length, pub_type=False)
else:
return self.java_type.format_value(self.member.value, pub_type=False)
@@ -926,6 +930,8 @@
name = 'length'
elif member.name == 'value_mask':
name = 'mask'
+ elif member.name == 'group_id':
+ name = 'group'
else:
name = java_type.name_c_to_camel(member.name)
j_type = java_type.convert_to_jtype(java_class.c_name, member.name, member.oftype)
@@ -999,16 +1005,23 @@
self.java_class = java_class
first_data_file_name = "of{version}/{name}.data".format(version=java_class.version.of_version,
name=java_class.c_name[3:])
- data_file_template = "of{version}/{name}.".format(version=java_class.version.of_version,
- name=java_class.c_name[3:]) + "{i}.data"
+ glob_file_name = "of{version}/{name}__*.data".format(version=java_class.version.of_version,
+ name=java_class.c_name[3:])
test_class_name = self.java_class.name + "Test"
self.test_units = []
if test_data.exists(first_data_file_name):
self.test_units.append(JavaUnitTest(java_class, first_data_file_name, test_class_name))
+
i = 1
- while test_data.exists(data_file_template.format(i=i)):
- self.test_units.append(JavaUnitTest(java_class, data_file_template.format(i=i), test_class_name + str(i)))
- i = i + 1
+ for f in test_data.glob(glob_file_name):
+ m = re.match(".*__(.*).data", f)
+ if m:
+ suffix = java_type.name_c_to_caps_camel(m.group(1))
+ else:
+ suffix = str(i)
+ i += 1
+ test_class_name = self.java_class.name + suffix + "Test"
+ self.test_units.append(JavaUnitTest(java_class, f, test_class_name))
@property
def package(self):
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 6de71ba..331aeea 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -38,12 +38,12 @@
### info table about java primitive types, for casting literals in the source code
# { name : (signed?, length_in_bits) }
java_primitives_info = {
- 'boolean' : (False, 8),
- 'byte' : (True, 8),
- 'char' : (False, 16),
- 'short' : (True, 16),
- 'int' : (True, 32),
- 'long' : (True, 64),
+ 'boolean' : (False, 8, False),
+ 'byte' : (True, 8, True),
+ 'char' : (False, 16, True),
+ 'short' : (True, 16, True),
+ 'int' : (True, 32, False),
+ 'long' : (True, 64, False),
}
def format_primitive_literal(t, value):
@@ -52,7 +52,7 @@
appropriately for correct representation despite Java's
signed-craziness
"""
- signed, bits = java_primitives_info[t]
+ signed, bits, cast_needed = java_primitives_info[t]
max = (1 << bits)-1
if value > max:
raise Exception("Value %d to large for type %s" % (value, t))
@@ -65,20 +65,21 @@
return str((1 << bits) - value)
else:
return "(%s) 0x%x" % (t, value)
- else:
- return "0x%x%s" % (value, "L" if t=="long" else "")
+ return "%s0x%x%s" % ("(%s) " % t if cast_needed else "", value, "L" if t=="long" else "")
+
ANY = 0xFFFFFFFFFFFFFFFF
class VersionOp:
- def __init__(self, version=ANY, read=None, write=None, default=None):
+ def __init__(self, version=ANY, read=None, write=None, default=None, funnel=None):
self.version = version
self.read = read
self.write = write
self.default = default
+ self.funnel = funnel
def __str__(self):
- return "[Version: %d, Read: '%s', Write: '%s', Default: '%s' ]" % (self.version, self.read, self.write, self.default )
+ return "[Version: %d, Read: '%s', Write: '%s', Default: '%s', Funnel: '%s' ]" % (self.version, self.read, self.write, self.default, self.funnel )
### FIXME: This class should really be cleaned up
class JType(object):
@@ -94,7 +95,11 @@
self.priv_type = priv_type # the internal storage type
self.ops = {}
- def op(self, version=ANY, read=None, write=None, default=None, pub_type=ANY):
+ def set_priv_type(self, priv_type):
+ self.priv_type = priv_type
+ return self
+
+ def op(self, version=ANY, read=None, write=None, default=None, funnel=None, pub_type=ANY):
"""
define operations to be performed for reading and writing this type
(when read_op, write_op is called). The operations 'read' and 'write'
@@ -110,7 +115,7 @@
pub_types = [ pub_type ] if pub_type is not ANY else [ False, True ]
for pub_type in pub_types:
- self.ops[(version, pub_type)] = VersionOp(version, read, write, default)
+ self.ops[(version, pub_type)] = VersionOp(version, read, write, default, funnel)
return self
def format_value(self, value, pub_type=True):
@@ -136,6 +141,24 @@
""" Is the private type different from the public one?"""
return self.pub_type != self.priv_type
+ def get_op(self, op_type, version, pub_type, default_value, arguments):
+ ver = ANY if version is None else version.int_version
+
+ if not "version" in arguments:
+ arguments["version"] = version.of_version
+
+ def lookup(ver, pub_type):
+ if (ver, pub_type) in self.ops:
+ return getattr(self.ops[(ver, pub_type)], op_type)
+ else:
+ return None
+
+ _op = lookup(ver, pub_type) or lookup(ANY, pub_type) or default_value
+ if callable(_op):
+ return _op(**arguments)
+ else:
+ return reduce(lambda a,repl: a.replace("$%s" % repl[0], str(repl[1])), arguments.items(), _op)
+
def read_op(self, version=None, length=None, pub_type=True):
""" return a Java stanza that reads a value of this JType from ChannelBuffer bb.
@param version int - OF wire version to generate expression for
@@ -149,20 +172,12 @@
# assumes that
# (1) length of the message has been read to 'length'
# (2) readerIndex at the start of the message has been stored in 'start'
- length = "length - (bb.readerIndex() - start)";
+ length = "length - (bb.readerIndex() - start)"
- ver = ANY if version is None else version.int_version
- _read_op = None
- if (ver, pub_type) in self.ops:
- _read_op = self.ops[(ver, pub_type)].read or self.ops[(ANY, pub_type)].read
- elif (ANY, pub_type) in self.ops:
- _read_op = self.ops[(ANY, pub_type)].read
- if _read_op is None:
- _read_op = 'ChannelUtilsVer$version.read%s(bb)' % self.pub_type
- if callable(_read_op):
- return _read_op(version)
- else:
- return _read_op.replace("$length", str(length)).replace("$version", version.of_version)
+ return self.get_op("read", version, pub_type,
+ default_value='ChannelUtilsVer$version.read%s(bb)' % self.pub_type,
+ arguments=dict(length=length)
+ )
def write_op(self, version=None, name=None, pub_type=True):
""" return a Java stanza that writes a value of this JType contained in Java expression
@@ -172,37 +187,22 @@
@param pub_type boolean use this JTypes 'public' (True), or private (False) representation
@return string containing generated Java expression.
"""
- ver = ANY if version is None else version.int_version
- _write_op = None
- if (ver, pub_type) in self.ops:
- _write_op = self.ops[(ver, pub_type)].write or self.ops[(ANY, pub_type)].write
- elif (ANY, pub_type) in self.ops:
- _write_op = self.ops[(ANY, pub_type)].write
- if _write_op is None:
- _write_op = 'ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type
- if callable(_write_op):
- return _write_op(version, name)
- else:
- return _write_op.replace("$name", str(name)).replace("$version", version.of_version)
+ return self.get_op("write", version, pub_type,
+ default_value='ChannelUtilsVer$version.write%s(bb, $name)' % self.pub_type,
+ arguments=dict(name=name)
+ )
+
def default_op(self, version=None, pub_type=True):
""" return a Java stanza that returns a default value of this JType.
@param version JavaOFVersion
@return string containing generated Java expression.
"""
- ver = ANY if version is None else version.int_version
- _default_op = None
- if (ver, pub_type) in self.ops:
- _default_op = self.ops[(ver, pub_type)].default or self.ops[(ANY, pub_type)].default
- elif (ANY, pub_type) in self.ops:
- _default_op = self.ops[(ANY, pub_type)].default
- if _default_op is None:
- _default_op = self.format_value(0) if self.is_primitive else "null"
- if callable(_default_op):
- return _default_op(version, name)
- else:
- return _default_op.replace("$version", version.of_version)
+ return self.get_op("default", version, pub_type,
+ arguments = dict(),
+ default_value = self.format_value(0) if self.is_primitive else "null"
+ )
def skip_op(self, version=None, length=None):
""" return a java stanza that skips an instance of JType in the input ChannelBuffer 'bb'.
@@ -211,18 +211,68 @@
Currently just delegates to read_op + throws away the result."""
return self.read_op(version, length)
+ def funnel_op(self, version=None, name=None, pub_type=True):
+ t = self.pub_type if pub_type else self.priv_type
+ return self.get_op("funnel", version, pub_type,
+ arguments = dict(name=name),
+ default_value = '$name.putTo(sink)' if not self._is_primitive(pub_type) else "sink.put{}($name)".format(t[0].upper() + t[1:])
+ )
+
@property
def is_primitive(self):
+ return self._is_primitive()
+
+ def _is_primitive(self, pub_type=True):
""" return true if the pub_type is a java primitive type (and thus needs
special treatment, because it doesn't have methods)"""
- return self.pub_type in java_primitive_types
+ t = self.pub_type if pub_type else self.priv_type
+ return t in java_primitive_types
@property
def is_array(self):
- """ return true iff the pub_type is a Java array (and thus requires special
- treatment for equals / toString etc.) """
- return self.pub_type.endswith("[]")
+ return self._is_array()
+ def _is_array(self, pub_type=True):
+ t = self.pub_type if pub_type else self.priv_type
+ return t.endswith("[]")
+
+# Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}>
+def gen_enum_jtype(java_name, is_bitmask=False):
+ if is_bitmask:
+ java_type = "Set<{}>".format(java_name)
+ default_value = "ImmutableSet.<{}>of()".format(java_name)
+ else:
+ java_type = java_name
+ default_value = "null"
+
+ serializer = "{}SerializerVer$version".format(java_name)
+
+ return JType(java_type)\
+ .op(read="{}.readFrom(bb)".format(serializer),
+ write="{}.writeTo(bb, $name)".format(serializer),
+ default=default_value,
+ funnel="{}.putTo($name, sink)".format(serializer)
+ )
+
+def gen_list_jtype(java_base_name):
+ # read op assumes the class has a public final static field READER that implements
+ # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer
+ # write op assumes class implements Writeable
+ return JType("List<{}>".format(java_base_name)) \
+ .op(
+ read= 'ChannelUtils.readList(bb, $length, {}Ver$version.READER)'.format(java_base_name), \
+ write='ChannelUtils.writeList(bb, $name)',
+ default="ImmutableList.<{}>of()".format(java_base_name),
+ funnel='FunnelUtils.putList($name, sink)'
+ )
+
+def gen_fixed_length_string_jtype(length):
+ return JType('String').op(
+ read='ChannelUtils.readFixedLengthString(bb, {})'.format(length),
+ write='ChannelUtils.writeFixedLengthString(bb, $name, {})'.format(length),
+ default='""',
+ funnel='sink.putUnencodedChars($name)'
+ )
##### Predefined JType mappings
# FIXME: This list needs to be pruned / cleaned up. Most of these are schematic.
@@ -231,7 +281,11 @@
.op(read='U8.f(bb.readByte())', write='bb.writeByte(U8.t($name))', pub_type=True) \
.op(read='bb.readByte()', write='bb.writeByte($name)', pub_type=False)
u8_list = JType('List<U8>') \
- .op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)')
+ .op(read='ChannelUtils.readList(bb, $length, U8.READER)',
+ write='ChannelUtils.writeList(bb, $name)',
+ default='ImmutableList.<U8>of()',
+ funnel='FunnelUtils.putList($name, sink)'
+ )
u16 = JType('int', 'short') \
.op(read='U16.f(bb.readShort())', write='bb.writeShort(U16.t($name))', pub_type=True) \
.op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
@@ -242,7 +296,8 @@
.op(
read='ChannelUtils.readList(bb, $length, U32.READER)',
write='ChannelUtils.writeList(bb, $name)',
- default="ImmutableList.<U32>of()");
+ default="ImmutableList.<U32>of()",
+ funnel="FunnelUtils.putList($name, sink)")
u8obj = JType('U8', 'U8') \
.op(read='U8.of(bb.readByte())', write='bb.writeByte($name.getRaw())', default="U8.ZERO")
u32obj = JType('U32', 'U32') \
@@ -255,33 +310,20 @@
# the same OFPort, but with a default value of ZERO, only for OF10 match
of_port_match_v1 = JType("OFPort") \
.op(version=1, read="OFPort.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFPort.ZERO")
-actions_list = JType('List<OFAction>') \
- .op(read='ChannelUtils.readList(bb, $length, OFActionVer$version.READER)',
- write='ChannelUtils.writeList(bb, $name);',
- default='ImmutableList.<OFAction>of()')
-instructions_list = JType('List<OFInstruction>') \
- .op(read='ChannelUtils.readList(bb, $length, OFInstructionVer$version.READER)', \
- write='ChannelUtils.writeList(bb, $name)',
- default='ImmutableList.<OFInstruction>of()')
-buckets_list = JType('List<OFBucket>') \
- .op(read='ChannelUtils.readList(bb, $length, OFBucketVer$version.READER)',
- write='ChannelUtils.writeList(bb, $name)',
- default='ImmutableList.<OFBucket>of()')
-port_desc_list = JType('List<OFPortDesc>') \
- .op(read='ChannelUtils.readList(bb, $length, OFPortDescVer$version.READER)',
- write='ChannelUtils.writeList(bb, $name)',
- default='ImmutableList.<OFPortDesc>of()')
+actions_list = gen_list_jtype("OFAction")
+instructions_list = gen_list_jtype("OFInstruction")
+buckets_list = gen_list_jtype("OFBucket")
+port_desc_list = gen_list_jtype("OFPortDesc")
+packet_queue_list = gen_list_jtype("OFPacketQueue")
port_desc = JType('OFPortDesc') \
.op(read='OFPortDescVer$version.READER.readFrom(bb)', \
write='$name.writeTo(bb)')
-packet_queue_list = JType('List<OFPacketQueue>') \
- .op(read='ChannelUtils.readList(bb, $length, OFPacketQueueVer$version.READER)',
- write='ChannelUtils.writeList(bb, $name);',
- default='ImmutableList.<OFPacketQueue>of()')
-octets = JType('byte[]') \
+octets = JType('byte[]')\
.op(read='ChannelUtils.readBytes(bb, $length)', \
write='bb.writeBytes($name)', \
- default="new byte[0]");
+ default="new byte[0]",
+ funnel="sink.putBytes($name)"
+ );
of_match = JType('Match') \
.op(read='ChannelUtilsVer$version.readOFMatch(bb)', \
write='$name.writeTo(bb)',
@@ -293,22 +335,11 @@
.op(read="MacAddress.read6Bytes(bb)", \
write="$name.write6Bytes(bb)",
default="MacAddress.NONE")
-port_name = JType('String') \
- .op(read='ChannelUtils.readFixedLengthString(bb, 16)', \
- write='ChannelUtils.writeFixedLengthString(bb, $name, 16)',
- default='""')
-desc_str = JType('String') \
- .op(read='ChannelUtils.readFixedLengthString(bb, 256)', \
- write='ChannelUtils.writeFixedLengthString(bb, $name, 256)',
- default='""')
-serial_num = JType('String') \
- .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
- write='ChannelUtils.writeFixedLengthString(bb, $name, 32)',
- default='""')
-table_name = JType('String') \
- .op(read='ChannelUtils.readFixedLengthString(bb, 32)', \
- write='ChannelUtils.writeFixedLengthString(bb, $name, 32)',
- default='""')
+
+port_name = gen_fixed_length_string_jtype(16)
+desc_str = gen_fixed_length_string_jtype(256)
+serial_num = gen_fixed_length_string_jtype(32)
+table_name = gen_fixed_length_string_jtype(32)
ipv4 = JType("IPv4Address") \
.op(read="IPv4Address.read4Bytes(bb)", \
write="$name.write4Bytes(bb)",
@@ -317,9 +348,7 @@
.op(read="IPv6Address.read16Bytes(bb)", \
write="$name.write16Bytes(bb)",
default='IPv6Address.NONE')
-packetin_reason = JType("OFPacketInReason")\
- .op(read="OFPacketInReasonSerializerVer$version.readFrom(bb)",
- write="OFPacketInReasonSerializerVer$version.writeTo(bb, $name)")
+packetin_reason = gen_enum_jtype("OFPacketInReason")
transport_port = JType("TransportPort")\
.op(read="TransportPort.read2Bytes(bb)",
write="$name.write2Bytes(bb)",
@@ -403,6 +432,16 @@
port_speed = JType("PortSpeed")
error_type = JType("OFErrorType")
+of_type = JType("OFType", 'byte') \
+ .op(read='bb.readByte()', write='bb.writeByte($name)')
+action_type= gen_enum_jtype("OFActionType")\
+ .set_priv_type("short")\
+ .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
+instruction_type = gen_enum_jtype("OFInstructionType")\
+ .set_priv_type('short') \
+ .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)
+buffer_id = JType("OFBufferId") \
+ .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())", default="OFBufferId.NO_BUFFER")
boolean = JType("boolean", "byte") \
.op(read='(bb.readByte() != 0)',
write='bb.writeByte($name ? 1 : 0)',
@@ -411,6 +450,18 @@
.op(read='DatapathId.of(bb.readLong())',
write='bb.writeLong($name.getLong())',
default='DatapathId.NONE')
+action_type_set = JType("Set<OFActionType>") \
+ .op(read='ChannelUtilsVer10.readSupportedActions(bb)',
+ write='ChannelUtilsVer10.writeSupportedActions(bb, $name)',
+ default='ImmutableSet.<OFActionType>of()',
+ funnel='ChannelUtilsVer10.putSupportedActionsTo($name, sink)')
+of_group = JType("OFGroup") \
+ .op(version=ANY, read="OFGroup.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFGroup.ALL")
+# the outgroup field of of_flow_stats_request has a special default value
+of_group_default_any = JType("OFGroup") \
+ .op(version=ANY, read="OFGroup.read4Bytes(bb)", write="$name.write4Bytes(bb)", default="OFGroup.ANY")
+buffer_id = JType("OFBufferId") \
+ .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())", default="OFBufferId.NO_BUFFER")
generic_t = JType("T")
@@ -497,7 +548,7 @@
'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
'of_oxm_mpls_tc' : { 'value' : u8obj },
'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
-
+
'of_oxm_bsn_in_ports_128' : { 'value': port_bitmap },
'of_oxm_bsn_in_ports_128_masked' : { 'value': port_bitmap, 'value_mask': port_bitmap },
@@ -509,6 +560,8 @@
},
'of_bsn_set_l2_table_request': { 'l2_table_enable': boolean },
'of_bsn_set_l2_table_reply': { 'l2_table_enable': boolean },
+ 'of_bsn_set_pktin_suppression_request': { 'enabled': boolean },
+ 'of_flow_stats_request': { 'out_group': of_group_default_any },
}
@@ -519,41 +572,20 @@
for protocol in of_g.ir.values():
for enum in protocol.enums:
java_name = name_c_to_caps_camel(re.sub(r'_t$', "", enum.name))
- if enum.is_bitmask:
- java_type = "Set<{}>".format(java_name)
- default_value = "ImmutableSet.<{}>of()".format(java_name)
- else:
- java_type = java_name
- default_value = "null"
- enum_types[enum.name] = \
- JType(java_type)\
- .op(read="{}SerializerVer$version.readFrom(bb)".format(java_name),
- write="{}SerializerVer$version.writeTo(bb, $name)".format(java_name),
- default=default_value)
+
+ enum_types[enum.name] = gen_enum_jtype(java_name, enum.is_bitmask)
return enum_types
def make_match_field_jtype(sub_type_name="?"):
return JType("MatchField<{}>".format(sub_type_name))
-# Create a default mapping for a list type. Type defauls to List<${java_mapping_of_name}>
-def make_standard_list_jtype(c_type):
+def list_cname_to_java_name(c_type):
m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
if not m:
raise Exception("Not a recgonized standard list type declaration: %s" % c_type)
base_name = m.group(1)
- java_base_name = name_c_to_caps_camel(base_name)
-
- # read op assumes the class has a public final static field READER that implements
- # OFMessageReader<$class> i.e., can deserialize an instance of class from a ChannelBuffer
- # write op assumes class implements Writeable
- return JType("List<OF{}>".format(java_base_name)) \
- .op(
- read= 'ChannelUtils.readList(bb, $length, OF{}Ver$version.READER)'.format(java_base_name), \
- write='ChannelUtils.writeList(bb, $name)',
- default="ImmutableList.<OF{}>of()".format(java_base_name)
- )
-
+ return "OF" + name_c_to_caps_camel(base_name)
#### main entry point for conversion of LOXI types (c_types) Java types.
@@ -565,12 +597,9 @@
if obj_name in exceptions and field_name in exceptions[obj_name]:
return exceptions[obj_name][field_name]
elif ( obj_name == "of_header" or loxi_utils.class_is_message(obj_name)) and field_name == "type" and c_type == "uint8_t":
- return JType("OFType", 'byte') \
- .op(read='bb.readByte()', write='bb.writeByte($name)')
+ return of_type
elif field_name == "type" and re.match(r'of_action.*', obj_name):
- return JType("OFActionType", 'short') \
- .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
- .op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
+ return action_type
elif field_name == "err_type":
return JType("OFErrorType", 'short') \
.op(read='bb.readShort()', write='bb.writeShort($name)')
@@ -578,9 +607,7 @@
return JType("OFStatsType", 'short') \
.op(read='bb.readShort()', write='bb.writeShort($name)')
elif field_name == "type" and re.match(r'of_instruction.*', obj_name):
- return JType("OFInstructionType", 'short') \
- .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
- .op(read="OFInstructionTypeSerializerVer$version.readFrom(bb)", write="OFInstructionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
+ return instruction_type
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":
return table_id_default_zero
elif field_name == "table_id" and c_type == "uint8_t":
@@ -588,19 +615,17 @@
elif field_name == "version" and c_type == "uint8_t":
return of_version
elif field_name == "buffer_id" and c_type == "uint32_t":
- return JType("OFBufferId") \
- .op(read="OFBufferId.of(bb.readInt())", write="bb.writeInt($name.getInt())", default="OFBufferId.NO_BUFFER")
+ return buffer_id
+ elif field_name == "group_id" and c_type == "uint32_t":
+ return of_group
elif field_name == 'datapath_id':
return datapath_id
elif field_name == 'actions' and obj_name == 'of_features_reply':
- return JType("Set<OFActionType>") \
- .op(read='ChannelUtilsVer10.readSupportedActions(bb)',
- write='ChannelUtilsVer10.writeSupportedActions(bb, $name)',
- default='ImmutableSet.<OFActionType>of()')
+ return action_type_set
elif c_type in default_mtype_to_jtype_convert_map:
return default_mtype_to_jtype_convert_map[c_type]
elif re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type):
- return make_standard_list_jtype(c_type)
+ return gen_list_jtype(list_cname_to_java_name(c_type))
elif c_type in enum_java_types():
return enum_java_types()[c_type]
else:
diff --git a/java_gen/pre-written/pom.xml b/java_gen/pre-written/pom.xml
index ea9a43f..5715704 100644
--- a/java_gen/pre-written/pom.xml
+++ b/java_gen/pre-written/pom.xml
@@ -10,7 +10,7 @@
<groupId>org.projectfloodlight</groupId>
<artifactId>openflowj</artifactId>
- <version>0.2.0-SNAPSHOT</version>
+ <version>0.3.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>OpenFlowJ-Loxi</name>
@@ -37,12 +37,12 @@
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
- <version>2.0.1</version>
+ <version>2.0.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.8.2</version>
+ <version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -53,7 +53,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
- <version>14.0.1</version>
+ <version>15.0</version>
</dependency>
</dependencies>
<build>
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java
index e17796a..68ca86d 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFMatchBmap.java
@@ -1,5 +1,13 @@
package org.projectfloodlight.openflow.protocol;
-public class OFMatchBmap {
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+
+import com.google.common.hash.PrimitiveSink;
+
+public class OFMatchBmap implements PrimitiveSinkable{
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java
index 852b803..5d37987 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFObject.java
@@ -1,9 +1,11 @@
package org.projectfloodlight.openflow.protocol;
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+
/**
* Base interface of all OpenFlow objects (e.g., messages, actions, stats, etc.)
*/
-public interface OFObject extends Writeable {
+public interface OFObject extends Writeable, PrimitiveSinkable {
OFVersion getVersion();
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
index ac48c8d..c6ba116 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
@@ -9,13 +9,15 @@
import org.projectfloodlight.openflow.exceptions.OFParseError;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.match.MatchFields;
-import org.projectfloodlight.openflow.types.OFValueType;
-import org.projectfloodlight.openflow.util.ChannelUtils;
import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.types.OFValueType;
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+import org.projectfloodlight.openflow.util.ChannelUtils;
import com.google.common.collect.ImmutableMap;
+import com.google.common.hash.PrimitiveSink;
-public class OFOxmList implements Iterable<OFOxm<?>>, Writeable {
+public class OFOxmList implements Iterable<OFOxm<?>>, Writeable, PrimitiveSinkable {
private final Map<MatchFields, OFOxm<?>> oxmMap;
public final static OFOxmList EMPTY = new OFOxmList(ImmutableMap.<MatchFields, OFOxm<?>>of());
@@ -124,5 +126,12 @@
return "OFOxmList" + oxmMap;
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ for (OFOxm<?> o : this) {
+ o.putTo(sink);
+ }
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java
index 3f2f23f..ed7c0c8 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/ver10/ChannelUtilsVer10.java
@@ -5,10 +5,11 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
-import org.projectfloodlight.openflow.protocol.match.Match;
-import org.projectfloodlight.openflow.protocol.ver10.OFMatchV1Ver10;
import org.projectfloodlight.openflow.protocol.OFActionType;
import org.projectfloodlight.openflow.protocol.OFBsnVportQInQ;
+import org.projectfloodlight.openflow.protocol.match.Match;
+
+import com.google.common.hash.PrimitiveSink;
/**
* Collection of helper functions for reading and writing into ChannelBuffers
@@ -62,8 +63,7 @@
return supportedActions;
}
- public static void writeSupportedActions(ChannelBuffer bb,
- Set<OFActionType> supportedActions) {
+ public static int supportedActionsToWire(Set<OFActionType> supportedActions) {
int supportedActionsVal = 0;
if (supportedActions.contains(OFActionType.OUTPUT))
supportedActionsVal |= (1 << OFActionTypeSerializerVer10.OUTPUT_VAL);
@@ -89,6 +89,15 @@
supportedActionsVal |= (1 << OFActionTypeSerializerVer10.SET_TP_DST_VAL);
if (supportedActions.contains(OFActionType.ENQUEUE))
supportedActionsVal |= (1 << OFActionTypeSerializerVer10.ENQUEUE_VAL);
- bb.writeInt(supportedActionsVal);
+ return supportedActionsVal;
}
+
+ public static void putSupportedActionsTo(Set<OFActionType> supportedActions, PrimitiveSink sink) {
+ sink.putInt(supportedActionsToWire(supportedActions));
+ }
+
+ public static void writeSupportedActions(ChannelBuffer bb, Set<OFActionType> supportedActions) {
+ bb.writeInt(supportedActionsToWire(supportedActions));
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java
index c8999b8..bfedaeb 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ArpOpcode.java
@@ -2,6 +2,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
public class ArpOpcode implements OFValueType<ArpOpcode> {
@@ -189,4 +190,9 @@
return UnsignedInts.compare(opcode, o.opcode);
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort((short) this.opcode);
+ }
+
}
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
index a6f2106..72ed3da 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
@@ -2,6 +2,7 @@
import javax.annotation.concurrent.Immutable;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
@Immutable
@@ -68,4 +69,9 @@
public int compareTo(ClassId o) {
return UnsignedInts.compare(rawValue, rawValue);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(rawValue);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java
index ad86d29..79fa14f 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/DatapathId.java
@@ -1,16 +1,20 @@
package org.projectfloodlight.openflow.types;
+import org.projectfloodlight.openflow.annotations.Immutable;
import org.projectfloodlight.openflow.util.HexString;
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.Longs;
import com.google.common.primitives.UnsignedLongs;
/**
* Abstraction of a datapath ID that can be set and/or accessed as either a
- * long value or a colon-separated string.
+ * long value or a colon-separated string. Immutable
*
* @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
*/
-public class DatapathId implements Comparable<DatapathId> {
+@Immutable
+public class DatapathId implements PrimitiveSinkable, Comparable<DatapathId> {
public static final DatapathId NONE = new DatapathId(0);
@@ -28,6 +32,10 @@
return new DatapathId(HexString.toLong(s));
}
+ public static DatapathId of(byte[] bytes) {
+ return new DatapathId(Longs.fromByteArray(bytes));
+ }
+
public long getLong() {
return rawValue;
}
@@ -36,6 +44,10 @@
return U64.of(rawValue);
}
+ public byte[] getBytes() {
+ return Longs.toByteArray(rawValue);
+ }
+
@Override
public String toString() {
return HexString.toHexString(rawValue);
@@ -64,6 +76,11 @@
}
@Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putLong(rawValue);
+ }
+
+ @Override
public int compareTo(DatapathId o) {
return UnsignedLongs.compare(rawValue, o.rawValue);
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java
index 7031a0d..c5f4f86 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/EthType.java
@@ -2,6 +2,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
@@ -260,5 +261,10 @@
return UnsignedInts.compare(rawValue, o.rawValue);
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(rawValue);
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java
index c66486f..6466eee 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Code.java
@@ -2,6 +2,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Shorts;
/**
@@ -84,4 +85,9 @@
public int compareTo(ICMPv4Code o) {
return Shorts.compare(code, o.code);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort(code);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java
index bfd0d99..a0aa152 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ICMPv4Type.java
@@ -2,6 +2,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Shorts;
public class ICMPv4Type implements OFValueType<ICMPv4Type> {
@@ -193,4 +194,10 @@
public int compareTo(ICMPv4Type o) {
return Shorts.compare(type, o.type);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort(type);
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
index 77b792f..51d10f3 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4Address.java
@@ -4,6 +4,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
@@ -152,4 +153,10 @@
public int compareTo(IPv4Address o) {
return UnsignedInts.compare(rawValue, o.rawValue);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(rawValue);
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
index b58de1a..1aad85b 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6Address.java
@@ -5,6 +5,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Longs;
/**
@@ -308,4 +309,10 @@
else
return Longs.compare(raw2, o.raw2);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putLong(raw1);
+ sink.putLong(raw2);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java
index 45bbf4b..de49b51 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6FlowLabel.java
@@ -3,6 +3,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
public class IPv6FlowLabel implements OFValueType<IPv6FlowLabel> {
@@ -76,4 +77,9 @@
public int compareTo(IPv6FlowLabel o) {
return UnsignedInts.compare(label, o.label);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(this.label);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java
index ec78315..27596b7 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpDscp.java
@@ -3,6 +3,8 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
+
public enum IpDscp implements OFValueType<IpDscp> {
DSCP_0((byte)0),
DSCP_1((byte)1),
@@ -244,4 +246,9 @@
public byte getDscpValue() {
return dscp;
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putByte(dscp);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java
index 7e1cdf0..654df01 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpEcn.java
@@ -3,6 +3,8 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
+
public enum IpEcn implements OFValueType<IpEcn> {
ECN_00((byte)0),
ECN_01((byte)1),
@@ -63,4 +65,9 @@
public byte getEcnValue() {
return ecn;
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putByte(ecn);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java
index b9eae68..69f497e 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IpProtocol.java
@@ -2,6 +2,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Shorts;
/**
@@ -655,4 +656,10 @@
return Shorts.compare(proto, o.proto);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort(proto);
+ }
+
}
\ No newline at end of file
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
index b7f7f67..2046d71 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
@@ -4,6 +4,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
@Immutable
@@ -72,4 +73,9 @@
public LagId applyMask(LagId mask) {
return LagId.of(rawValue & mask.rawValue);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(rawValue);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
index 009dae5..aaa31eb 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
@@ -4,6 +4,7 @@
import org.projectfloodlight.openflow.exceptions.OFParseError;
import org.projectfloodlight.openflow.util.HexString;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Longs;
/**
@@ -169,6 +170,12 @@
return Longs.compare(rawValue, o.rawValue);
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt((int) (this.rawValue >> 16));
+ sink.putShort((short) (this.rawValue & 0xFFFF));
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java
index 4d88793..ea2317a 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Masked.java
@@ -1,5 +1,7 @@
package org.projectfloodlight.openflow.types;
+import com.google.common.hash.PrimitiveSink;
+
public class Masked<T extends OFValueType<T>> implements OFValueType<Masked<T>> {
@@ -66,4 +68,10 @@
else
return mask.compareTo(o.mask);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ value.putTo(sink);
+ mask.putTo(sink);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
index 2827a72..5cec233 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
@@ -2,6 +2,8 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
+
public class OFBitMask128 implements OFValueType<OFBitMask128> {
static final int LENGTH = 16;
@@ -89,4 +91,10 @@
return Long.signum(this.raw2 - o.raw2);
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putLong(raw1);
+ sink.putLong(raw2);
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
index f3812dd..7f76b4d 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
@@ -2,6 +2,7 @@
import org.projectfloodlight.openflow.annotations.Immutable;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
/**
@@ -10,7 +11,7 @@
* @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
*/
@Immutable
-public class OFBufferId implements Comparable<OFBufferId> {
+public class OFBufferId implements Comparable<OFBufferId>, PrimitiveSinkable {
public static final OFBufferId NO_BUFFER = new OFBufferId(0xFFFFFFFF);
private final int rawValue;
@@ -60,4 +61,9 @@
public int compareTo(OFBufferId o) {
return UnsignedInts.compare(rawValue, o.rawValue);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(rawValue);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java
new file mode 100644
index 0000000..b05d5fa
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFGroup.java
@@ -0,0 +1,156 @@
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.annotations.Immutable;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.UnsignedInts;
+
+/**
+ * Abstraction of an logical / OpenFlow group (ofp_group) in OpenFlow.
+ * Immutable.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+@Immutable
+public class OFGroup implements OFValueType<OFGroup> {
+ static final int LENGTH = 4;
+
+ // private int constants (OF1.1+) to avoid duplication in the code
+ // should not have to use these outside this class
+ private static final int ZERO_VAL = 0x00;
+ private static final int MAX_VAL = 0xffffff00;
+ private static final int ALL_VAL = 0xfffffffc;
+ private static final int ANY_VAL = 0xffffffff;
+
+
+ // ////////////// public constants - use to access well known OpenFlow group constants
+
+ /** Maximum number of physical and logical switch groups. */
+ public final static OFGroup MAX = new NamedGroup(MAX_VAL, "max");
+
+ /** All groups */
+ public final static OFGroup ALL = new NamedGroup(ALL_VAL, "all");
+
+ /**
+ * Wildcard group used only for flow mod (delete) and flow stats requests. */
+ public final static OFGroup ANY = new NamedGroup(ANY_VAL, "any");
+
+ /** group 0 in case we need it */
+ public static final OFGroup ZERO = OFGroup.of(ZERO_VAL);
+
+ public static final OFGroup NO_MASK = ANY;
+ public static final OFGroup FULL_MASK = ZERO;
+
+ /** raw openflow group number as a signed 32 bit integer */
+ private final int groupNumber;
+
+ /** private constructor. use of*-Factory methods instead */
+ private OFGroup(final int portNumber) {
+ this.groupNumber = portNumber;
+ }
+
+ /**
+ * get an OFGroup object corresponding to a raw 32-bit integer group number.
+ * NOTE: The group object may either be newly allocated or cached. Do not
+ * rely on either behavior.
+ *
+ * @param groupNumber the raw 32-bit group number
+ * @return a corresponding OFPort
+ */
+ public static OFGroup of(final int groupNumber) {
+ switch(groupNumber) {
+ case ZERO_VAL:
+ return MAX;
+ case MAX_VAL:
+ return MAX;
+ case ALL_VAL:
+ return ALL;
+ case ANY_VAL:
+ return ANY;
+ default:
+ if(UnsignedInts.compare(groupNumber, MAX_VAL) > 0) {
+ // greater than max_val, but not one of the reserved values
+ throw new IllegalArgumentException("Unknown special group number: "
+ + groupNumber);
+ }
+ return new OFGroup(groupNumber);
+ }
+ }
+
+ /** return the group number as a int32 */
+ public int getGroupNumber() {
+ return groupNumber;
+ }
+
+ @Override
+ public String toString() {
+ return UnsignedInts.toString(groupNumber);
+ }
+
+ /** Extension of OFGroup for named groups */
+ static class NamedGroup extends OFGroup {
+ private final String name;
+
+ NamedGroup(final int portNo, final String name) {
+ super(portNo);
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ @Override
+ public int getLength() {
+ return LENGTH;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof OFGroup))
+ return false;
+ OFGroup other = (OFGroup)obj;
+ if (other.groupNumber != this.groupNumber)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 53;
+ int result = 1;
+ result = prime * result + groupNumber;
+ return result;
+ }
+
+ public void write4Bytes(ChannelBuffer c) {
+ c.writeInt(this.groupNumber);
+ }
+
+ public static OFGroup read4Bytes(ChannelBuffer c) throws OFParseError {
+ return OFGroup.of(c.readInt());
+ }
+
+ @Override
+ public OFGroup applyMask(OFGroup mask) {
+ return OFGroup.of(this.groupNumber & mask.groupNumber);
+ }
+
+ @Override
+ public int compareTo(OFGroup o) {
+ return UnsignedInts.compare(this.groupNumber, o.groupNumber);
+ }
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(groupNumber);
+ }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java
index 0844d89..d1a23df 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFMetadata.java
@@ -2,6 +2,8 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
+
public class OFMetadata implements OFValueType<OFMetadata> {
static int LENGTH = 8;
@@ -67,4 +69,9 @@
public int compareTo(OFMetadata o) {
return u64.compareTo(o.u64);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ u64.putTo(sink);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java
index 0028cd8..155a9db 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPort.java
@@ -4,6 +4,7 @@
import org.projectfloodlight.openflow.annotations.Immutable;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
/**
@@ -554,4 +555,9 @@
public int compareTo(OFPort o) {
return UnsignedInts.compare(this.portNumber, o.portNumber);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(portNumber);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java
new file mode 100644
index 0000000..49c8c4e
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java
@@ -0,0 +1,126 @@
+package org.projectfloodlight.openflow.types;
+
+
+/** User-facing object representing a bitmap of ports that can be matched on.
+ * This is implemented by the custom BSN OXM type of_oxm_bsn_in_ports_182.
+ *
+ * You can call set() on the builder for all the Ports you want to match on
+ * and unset to exclude the port.
+ *
+ * <b>Implementation note:</b> to comply with the matching semantics of OXM (which is a logical "AND" not "OR")
+ * the underlying match uses a data format which is very unintuitive. The value is always
+ * 0, and the mask has the bits set for the ports that should <b>NOT</b> be included in the
+ * range.
+ *
+ * For the curious: We transformed the bitmap (a logical OR) problem into a logical
+ * AND NOT problem.
+ *
+ * We logically mean: Inport is 1 OR 3
+ * We technically say: Inport IS NOT 2 AND IS NOT 4 AND IS NOT 5 AND IS NOT ....
+ * The second term cannot be represented in OXM, the second can.
+ *
+ * That said, all that craziness is hidden from the user of this object.
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class OFPortBitMap extends Masked<OFBitMask128> {
+
+ private OFPortBitMap(OFBitMask128 mask) {
+ super(OFBitMask128.NONE, mask);
+ }
+
+ /** @return whether or not the given port is logically included in the
+ * match, i.e., whether a packet from in-port <emph>port</emph> be matched by
+ * this OXM.
+ */
+ public boolean isOn(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ return !(this.mask.isOn(port.getPortNumber()));
+ }
+
+ public static OFPortBitMap ofPorts(OFPort... ports) {
+ Builder builder = new Builder();
+ for (OFPort port: ports) {
+ builder.set(port);
+ }
+ return builder.build();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof OFPortBitMap))
+ return false;
+ OFPortBitMap other = (OFPortBitMap)obj;
+ return (other.value.equals(this.value) && other.mask.equals(this.mask));
+ }
+
+ @Override
+ public int hashCode() {
+ return 619 * mask.hashCode() + 257 * value.hashCode();
+ }
+
+ public static class Builder {
+ private long raw1 = -1, raw2 = -1;
+
+ public Builder() {
+
+ }
+
+ /** @return whether or not the given port is logically included in the
+ * match, i.e., whether a packet from in-port <emph>port</emph> be matched by
+ * this OXM.
+ */
+ public boolean isOn(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ return !(OFBitMask128.isBitOn(raw1, raw2, port.getPortNumber()));
+ }
+
+ /** remove this port from the match, i.e., packets from this in-port
+ * will NOT be matched.
+ */
+ public Builder unset(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ int bit = port.getPortNumber();
+ if (bit < 0 || bit > 127)
+ throw new IndexOutOfBoundsException("Port number is out of bounds");
+ else if (bit == 127)
+ // the highest order bit in the bitmask is reserved. The switch will
+ // set that bit for all ports >= 127. The reason is that we don't want
+ // the OFPortMap to match all ports out of its range (i.e., a packet
+ // coming in on port 181 would match *any* OFPortMap).
+ throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
+ else if (bit < 64) {
+ raw2 |= ((long)1 << bit);
+ } else {
+ raw1 |= ((long)1 << (bit - 64));
+ }
+ return this;
+ }
+
+ /** add this port from the match, i.e., packets from this in-port
+ * will NOT be matched.
+ */
+ public Builder set(OFPort port) {
+ // see the implementation note above about the logical inversion of the mask
+ int bit = port.getPortNumber();
+ if (bit < 0 || bit > 127)
+ throw new IndexOutOfBoundsException("Port number is out of bounds");
+ else if (bit == 127)
+ // the highest order bit in the bitmask is reserved. The switch will
+ // set that bit for all ports >= 127. The reason is that we don't want
+ // the OFPortMap to match all ports out of its range (i.e., a packet
+ // coming in on port 181 would match *any* OFPortMap).
+ throw new IndexOutOfBoundsException("The highest order bit in the bitmask is reserved.");
+ else if (bit < 64) {
+ raw2 &= ~((long)1 << bit);
+ } else {
+ raw1 &= ~((long)1 << (bit - 64));
+ }
+ return this;
+ }
+
+ public OFPortBitMap build() {
+ return new OFPortBitMap(OFBitMask128.of(raw1, raw2));
+ }
+ }
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortMap.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortMap.java
deleted file mode 100644
index 8ec056e..0000000
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortMap.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.projectfloodlight.openflow.types;
-
-
-public class OFPortMap extends Masked<OFBitMask128> {
-
- private OFPortMap(OFBitMask128 mask) {
- super(OFBitMask128.NONE, mask);
- }
-
- public boolean isOn(OFPort port) {
- return !(this.mask.isOn(port.getPortNumber()));
- }
-
- public static OFPortMap ofPorts(OFPort... ports) {
- Builder builder = new Builder();
- for (OFPort port: ports) {
- builder.set(port);
- }
- return builder.build();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof OFPortMap))
- return false;
- OFPortMap other = (OFPortMap)obj;
- return (other.value.equals(this.value) && other.mask.equals(this.mask));
- }
-
- @Override
- public int hashCode() {
- return 619 * mask.hashCode() + 257 * value.hashCode();
- }
-
- public static class Builder {
- private long raw1 = -1, raw2 = -1;
-
- public Builder() {
-
- }
-
- public boolean isOn(OFPort port) {
- return !(OFBitMask128.isBitOn(raw1, raw2, port.getPortNumber()));
- }
-
- public Builder unset(OFPort port) {
- int bit = port.getPortNumber();
- if (bit < 0 || bit >= 127) // MAX PORT IS 127
- throw new IndexOutOfBoundsException("Port number is out of bounds");
- if (bit < 64) {
- raw2 |= ((long)1 << bit);
- } else {
- raw1 |= ((long)1 << (bit - 64));
- }
- return this;
- }
-
- public Builder set(OFPort port) {
- int bit = port.getPortNumber();
- if (bit < 0 || bit >= 127)
- throw new IndexOutOfBoundsException("Port number is out of bounds");
- if (bit < 64) {
- raw2 &= ~((long)1 << bit);
- } else {
- raw1 &= ~((long)1 << (bit - 64));
- }
- return this;
- }
-
- public OFPortMap build() {
- return new OFPortMap(OFBitMask128.of(raw1, raw2));
- }
- }
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java
index 3d8d1cd..03e84dd 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFValueType.java
@@ -3,8 +3,9 @@
-public interface OFValueType<T extends OFValueType<T>> extends Comparable<T> {
+public interface OFValueType<T extends OFValueType<T>> extends Comparable<T>, PrimitiveSinkable {
public int getLength();
public T applyMask(T mask);
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/PrimitiveSinkable.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/PrimitiveSinkable.java
new file mode 100644
index 0000000..e50cb75
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/PrimitiveSinkable.java
@@ -0,0 +1,7 @@
+package org.projectfloodlight.openflow.types;
+
+import com.google.common.hash.PrimitiveSink;
+
+public interface PrimitiveSinkable {
+ public void putTo(PrimitiveSink sink);
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java
index 698bc8e..950087d 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TableId.java
@@ -3,6 +3,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Shorts;
public class TableId implements OFValueType<TableId>, Comparable<TableId> {
@@ -91,4 +92,9 @@
return Shorts.compare(this.id, other.id);
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putByte((byte) id);
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java
index 540ad1a..01019b0 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/TransportPort.java
@@ -3,6 +3,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Ints;
/**
@@ -87,4 +88,9 @@
return Ints.compare(port, o.port);
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort((short) port);
+ }
+
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java
index 2f8bfee..9de7e14 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U16.java
@@ -22,6 +22,7 @@
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.protocol.Writeable;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Ints;
public class U16 implements Writeable, OFValueType<U16> {
@@ -117,4 +118,9 @@
public int compareTo(U16 o) {
return Ints.compare(f(raw), f(o.raw));
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort(raw);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
index daf5fa6..9fafc30 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
@@ -22,6 +22,7 @@
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.protocol.Writeable;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
public class U32 implements Writeable, OFValueType<U32> {
@@ -117,4 +118,7 @@
return UnsignedInts.compare(raw, o.raw);
}
-}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(raw);
+ }}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
index 8cd577f..d77d700 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U64.java
@@ -22,6 +22,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.protocol.Writeable;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedLongs;
public class U64 implements Writeable, OFValueType<U64> {
@@ -120,4 +121,8 @@
return UnsignedLongs.compare(raw, o.raw);
}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putLong(raw);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
index b85627e..078a846 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
@@ -22,6 +22,7 @@
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.protocol.Writeable;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedBytes;
public class U8 implements Writeable, OFValueType<U8> {
@@ -119,4 +120,8 @@
return UnsignedBytes.compare(raw, o.raw);
}
-}
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putByte(raw);
+ }
+ }
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java
index 10e2ebc..b3f187f 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VRF.java
@@ -4,6 +4,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedInts;
@Immutable
@@ -75,4 +76,9 @@
public int compareTo(VRF o) {
return UnsignedInts.compare(rawValue, o.rawValue);
}
+
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putInt(rawValue);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java
index dcc7d60..cbb7004 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanPcp.java
@@ -3,6 +3,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.UnsignedBytes;
public class VlanPcp implements OFValueType<VlanPcp> {
@@ -74,5 +75,8 @@
public int compareTo(VlanPcp o) {
return UnsignedBytes.compare(pcp, o.pcp);
}
-
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putByte(pcp);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
index 6bd7581..d370711 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
@@ -3,6 +3,7 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Shorts;
/** Represents an OpenFlow Vlan VID, as specified by the OpenFlow 1.3 spec.
@@ -159,5 +160,8 @@
public int compareTo(VlanVid o) {
return Shorts.compare(vid, o.vid);
}
-
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort(vid);
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/FunnelUtils.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/FunnelUtils.java
new file mode 100644
index 0000000..f62d7f9
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/FunnelUtils.java
@@ -0,0 +1,14 @@
+package org.projectfloodlight.openflow.util;
+
+import java.util.List;
+
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+
+import com.google.common.hash.PrimitiveSink;
+
+public class FunnelUtils {
+ public static void putList(List<? extends PrimitiveSinkable> sinkables, PrimitiveSink sink) {
+ for(PrimitiveSinkable p: sinkables)
+ p.putTo(sink);
+ }
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
index ed380ee..3ccceb3 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
@@ -84,7 +84,7 @@
for(String invalid : invalidMacStrings) {
try {
MacAddress.of(invalid);
- fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+ fail("Invalid MAC address "+invalid+ " should have raised IllegalArgumentException");
} catch(IllegalArgumentException e) {
// ok
}
@@ -96,7 +96,7 @@
for(byte[] invalid : invalidMacBytes) {
try {
MacAddress.of(invalid);
- fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+ fail("Invalid MAC address bytes "+ Arrays.toString(invalid) + " should have raised IllegalArgumentException");
} catch(IllegalArgumentException e) {
// ok
}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortMapTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
similarity index 60%
rename from java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortMapTest.java
rename to java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
index 7a75248..7f5ab5d 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortMapTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
@@ -5,48 +5,48 @@
import org.junit.Test;
-public class OFPortMapTest extends TestCase {
+public class OFPortBitMapTest extends TestCase {
@Test
- public void testOFPortMap() {
- Boolean[] on = new Boolean[128];
- for (int i = 0; i < 128; i++) {
+ public void testOFPortBitMap() {
+ Boolean[] on = new Boolean[127];
+ for (int i = 0; i < 127; i++) {
on[i] = false;
}
- OFPortMap.Builder builder = new OFPortMap.Builder();
+ OFPortBitMap.Builder builder = new OFPortBitMap.Builder();
- for (int i = 0; i < 128; i += 3) {
+ for (int i = 0; i < 127; i += 3) {
OFPort p = OFPort.of(i);
builder.set(p);
on[p.getPortNumber()] = true;
}
// Test that all ports that were added are actually on, and all other ports are off
- OFPortMap portmap = builder.build();
+ OFPortBitMap portmap = builder.build();
//System.out.println(portmap);
- Boolean[] actual = new Boolean[128];
- for (int i = 0; i < 128; i++) {
+ Boolean[] actual = new Boolean[127];
+ for (int i = 0; i < 127; i++) {
actual[i] = false;
}
- for (int i = 0; i < 128; i++) {
+ for (int i = 0; i < 127; i++) {
actual[i] = portmap.isOn(OFPort.of(i));
}
assertArrayEquals(on, actual);
// Turn some ports off
- for (int i = 0; i < 128; i += 7) {
+ for (int i = 0; i < 127; i += 7) {
on[i] = false;
builder.unset(OFPort.of(i));
}
// Test again
portmap = builder.build();
- actual = new Boolean[128];
- for (int i = 0; i < 128; i++) {
+ actual = new Boolean[127];
+ for (int i = 0; i < 127; i++) {
actual[i] = false;
}
- for (int i = 0; i < 128; i++) {
+ for (int i = 0; i < 127; i++) {
actual[i] = portmap.isOn(OFPort.of(i));
}
assertArrayEquals(on, actual);
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
index 7fd0719..55e9a2d 100644
--- a/java_gen/templates/_imports.java
+++ b/java_gen/templates/_imports.java
@@ -1,5 +1,6 @@
import java.util.Arrays;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.Map;
@@ -18,3 +19,5 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
+import com.google.common.hash.Funnel;
+import com.google.common.hash.PrimitiveSink;
diff --git a/java_gen/templates/const_serializer.java b/java_gen/templates/const_serializer.java
index 5710f9c..12ff28a 100644
--- a/java_gen/templates/const_serializer.java
+++ b/java_gen/templates/const_serializer.java
@@ -33,10 +33,7 @@
package ${package};
-import org.projectfloodlight.openflow.types.*;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.projectfloodlight.openflow.exceptions.OFParseError;
-import org.projectfloodlight.openflow.protocol.OFVersion;
+//:: include('_imports.java')
import ${enum.package}.${enum.name};
public class ${class_name} {
@@ -60,6 +57,10 @@
${wire_type.write_op(version=version, name="toWireValue(e)")};
}
+ public static void putTo(${enum.name} e, PrimitiveSink sink) {
+ ${wire_type.funnel_op(version=version, name="toWireValue(e)")};
+ }
+
public static ${enum.name} ofWireValue(${int_wire_type} val) {
switch(val) {
//:: for entry, _ in entries:
@@ -71,6 +72,7 @@
}
}
+
public static ${int_wire_type} toWireValue(${enum.name} e) {
switch(e) {
//:: for entry, _ in entries:
diff --git a/java_gen/templates/const_set_serializer.java b/java_gen/templates/const_set_serializer.java
index 4fcff22..4c624ee 100644
--- a/java_gen/templates/const_set_serializer.java
+++ b/java_gen/templates/const_set_serializer.java
@@ -33,14 +33,8 @@
package ${package};
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.Set;
+//:: include('_imports.java')
-import org.projectfloodlight.openflow.types.*;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.projectfloodlight.openflow.exceptions.OFParseError;
-import org.projectfloodlight.openflow.protocol.OFVersion;
import ${enum.package}.${enum.name};
public class ${class_name} {
@@ -64,6 +58,11 @@
${wire_type.write_op(version=version, name="toWireValue(set)")};
}
+ public static void putTo(Set<${enum.name}> set, PrimitiveSink sink) {
+ ${wire_type.funnel_op(version=version, name="toWireValue(set)")};
+ }
+
+
public static Set<${enum.name}> ofWireValue(${int_wire_type} val) {
EnumSet<${enum.name}> set = EnumSet.noneOf(${enum.name}.class);
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index 458d3f0..7b3b762 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -229,9 +229,14 @@
//:: #endif
//:: #endfor
//:: if msg.align:
- // align message to ${msg.align} bytes
+ //:: if msg.length_includes_align:
+ // align message to ${msg.align} bytes (length contains aligned value)
+ bb.skipBytes(length - (bb.readerIndex() - start));
+ //:: else:
+ // align message to ${msg.align} bytes (length does not contain alignment)
bb.skipBytes(((length + ${msg.align-1})/${msg.align} * ${msg.align} ) - length );
//:: #endif
+ //:: #endif
//:: if msg.data_members:
//:: if os.path.exists("%s/custom/%s.Reader_normalize_stanza.java" % (template_dir, msg.name)):
@@ -247,6 +252,33 @@
}
}
+ public void putTo(PrimitiveSink sink) {
+ FUNNEL.funnel(this, sink);
+ }
+
+ final static ${impl_class}Funnel FUNNEL = new ${impl_class}Funnel();
+ static class ${impl_class}Funnel implements Funnel<${impl_class}> {
+ private static final long serialVersionUID = 1L;
+ @Override
+ public void funnel(${impl_class} message, PrimitiveSink sink) {
+//:: for prop in msg.members:
+//:: if prop.is_virtual:
+//:: continue
+//:: elif prop.is_data:
+ ${prop.java_type.funnel_op(version, "message." + prop.name, pub_type=True)};
+//:: elif prop.is_pad:
+ // skip pad (${prop.length} bytes)
+//:: elif prop.is_fixed_value:
+ // fixed value property ${prop.name} = ${prop.value}
+ ${prop.java_type.funnel_op(version, prop.priv_value, pub_type=False)};
+//:: else:
+ // FIXME: skip funnel of ${prop.name}
+//:: #endif
+//:: #endfor
+ }
+ }
+
+
public void writeTo(ChannelBuffer bb) {
WRITER.write(bb, this);
}
@@ -300,10 +332,13 @@
//:: if not msg.is_fixed_length:
// update length field
int length = bb.writerIndex() - startIndex;
- bb.setShort(lengthIndex, length);
+ //:: if msg.align:
+ int alignedLength = ((length + ${msg.align-1})/${msg.align} * ${msg.align});
+ //:: #endif
+ bb.setShort(lengthIndex, ${"alignedLength" if msg.length_includes_align else "length"});
//:: if msg.align:
// align message to ${msg.align} bytes
- bb.writeZero( ((length + ${msg.align-1})/${msg.align} * ${msg.align}) - length);
+ bb.writeZero(alignedLength - length);
//:: #endif
//:: #end
diff --git a/java_gen/templates/of_factories.java b/java_gen/templates/of_factories.java
index 0a27c59..f8c9a80 100644
--- a/java_gen/templates/of_factories.java
+++ b/java_gen/templates/of_factories.java
@@ -37,7 +37,7 @@
public final class OFFactories {
- private final static GenericReader GENERIC_READER = new GenericReader();
+ private static final GenericReader GENERIC_READER = new GenericReader();
public static OFFactory getFactory(OFVersion version) {
switch(version) {
diff --git a/java_gen/templates/unit_test.java b/java_gen/templates/unit_test.java
index 5a525e4..cd85a74 100644
--- a/java_gen/templates/unit_test.java
+++ b/java_gen/templates/unit_test.java
@@ -80,6 +80,7 @@
// FIXME should invoke the overall reader once implemented
${var_type} ${var_name}Read = ${msg.name}.READER.readFrom(input);
+ assertEquals(${msg.constant_name}_SERIALIZED.length, input.readerIndex());
assertEquals(${var_name}Built, ${var_name}Read);
}
@@ -93,6 +94,7 @@
// FIXME should invoke the overall reader once implemented
${var_type} ${var_name} = ${msg.name}.READER.readFrom(input);
+ assertEquals(${msg.constant_name}_SERIALIZED.length, input.readerIndex());
// write message again
ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
diff --git a/loxi_front_end/parser.py b/loxi_front_end/parser.py
index f2cf4b0..4a465f7 100644
--- a/loxi_front_end/parser.py
+++ b/loxi_front_end/parser.py
@@ -56,7 +56,7 @@
type_member = P.Group(tag('type') + any_type + identifier + s('==') + integer)
data_member = P.Group(tag('data') + any_type - identifier)
-struct_param_name = kw("align")
+struct_param_name = kw("align") | kw("length_includes_align")
struct_param = P.Group(struct_param_name - s('=') - word)
struct_param_list = P.Forward()
struct_param_list << struct_param + P.Optional(s(',') - P.Optional(struct_param_list))
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 79d5bad..ad2e76f 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -211,6 +211,10 @@
OFPFF_EMERG = 0x4,
};
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+};
+
+
enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
OFPSF_REPLY_MORE = 0x1,
};
@@ -825,7 +829,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
};
struct of_stats_reply : of_header {
@@ -834,7 +838,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
};
struct of_desc_stats_request : of_stats_request {
@@ -843,7 +847,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
};
struct of_desc_stats_reply : of_stats_reply {
@@ -852,7 +856,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
of_desc_str_t mfr_desc;
of_desc_str_t hw_desc;
of_desc_str_t sw_desc;
@@ -866,7 +870,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
of_match_t match;
uint8_t table_id;
pad(1);
@@ -879,7 +883,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
list(of_flow_stats_entry_t) entries;
};
@@ -889,7 +893,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
of_match_t match;
uint8_t table_id;
pad(1);
@@ -902,7 +906,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
uint64_t packet_count;
uint64_t byte_count;
uint32_t flow_count;
@@ -915,7 +919,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
};
struct of_table_stats_reply : of_stats_reply {
@@ -924,7 +928,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
list(of_table_stats_entry_t) entries;
};
@@ -934,7 +938,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
of_port_no_t port_no;
pad(6);
};
@@ -945,7 +949,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
list(of_port_stats_entry_t) entries;
};
@@ -955,7 +959,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
of_port_no_t port_no;
pad(2);
uint32_t queue_id;
@@ -967,7 +971,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
list(of_queue_stats_entry_t) entries;
};
@@ -977,7 +981,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0xffff;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
uint32_t experimenter == ?;
of_octets_t data;
};
@@ -988,7 +992,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0xffff;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
uint32_t experimenter == ?;
of_octets_t data;
};
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index 9937c6d..9b72e8c 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -72,9 +72,6 @@
OFPP_ALL = 0xfffffffc,
OFPP_CONTROLLER = 0xfffffffd,
OFPP_LOCAL = 0xfffffffe,
-};
-
-enum ofp_port_no(wire_type=uint32_t, complete=False) {
OFPP_ANY = 0xffffffff,
};
@@ -399,6 +396,11 @@
OFPST_EXPERIMENTER = 0xffff,
};
+// none defined
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+};
+
+
enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
OFPSF_REPLY_MORE = 0x1,
};
@@ -1217,7 +1219,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1227,7 +1229,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
};
@@ -1237,7 +1239,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1247,7 +1249,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
of_desc_str_t mfr_desc;
of_desc_str_t hw_desc;
@@ -1262,7 +1264,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint8_t table_id;
pad(3);
@@ -1280,7 +1282,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_flow_stats_entry_t) entries;
};
@@ -1291,7 +1293,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint8_t table_id;
pad(3);
@@ -1309,7 +1311,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
uint64_t packet_count;
uint64_t byte_count;
@@ -1323,7 +1325,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1333,7 +1335,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_table_stats_entry_t) entries;
};
@@ -1344,7 +1346,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
of_port_no_t port_no;
pad(4);
@@ -1356,7 +1358,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_port_stats_entry_t) entries;
};
@@ -1367,7 +1369,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
of_port_no_t port_no;
uint32_t queue_id;
@@ -1379,7 +1381,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_queue_stats_entry_t) entries;
};
@@ -1390,7 +1392,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 6;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint32_t group_id;
pad(4);
@@ -1402,7 +1404,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 6;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_group_stats_entry_t) entries;
};
@@ -1413,7 +1415,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 7;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1423,7 +1425,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 7;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_group_desc_stats_entry_t) entries;
};
@@ -1434,7 +1436,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0xffff;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint32_t experimenter == ?;
pad(4);
@@ -1447,7 +1449,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0xffff;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
uint32_t experimenter == ?;
pad(4);
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 182794e..e9d915a 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -68,9 +68,6 @@
OFPP_ALL = 0xfffffffc,
OFPP_CONTROLLER = 0xfffffffd,
OFPP_LOCAL = 0xfffffffe,
-};
-
-enum ofp_port_no(wire_type=uint32_t, complete=False) {
OFPP_ANY = 0xffffffff,
};
@@ -424,6 +421,9 @@
OFPST_EXPERIMENTER = 0xffff,
};
+enum ofp_stats_request_flags(wire_type=uint16_t, bitmask=True) {
+};
+
enum ofp_stats_reply_flags(wire_type=uint16_t, bitmask=True) {
OFPSF_REPLY_MORE = 0x1,
};
@@ -600,7 +600,7 @@
pad(4);
};
-struct of_match_v3(align=8) {
+struct of_match_v3(align=8, length_includes_align=False) {
uint16_t type == 1;
uint16_t length;
list(of_oxm_t) oxm_list;
@@ -691,13 +691,13 @@
pad(4);
};
-struct of_action_set_field : of_action {
+struct of_action_set_field(align=8, length_includes_align=True) : of_action {
uint16_t type == 25;
uint16_t len;
of_oxm_t field;
};
-struct of_action_experimenter : of_action {
+struct of_action_experimenter(align=8, length_includes_align=True) : of_action {
uint16_t type == 65535;
uint16_t len;
uint32_t experimenter == ?;
@@ -1187,7 +1187,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1197,7 +1197,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
};
@@ -1207,7 +1207,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1217,7 +1217,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
of_desc_str_t mfr_desc;
of_desc_str_t hw_desc;
@@ -1232,7 +1232,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint8_t table_id;
pad(3);
@@ -1250,7 +1250,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_flow_stats_entry_t) entries;
};
@@ -1261,7 +1261,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint8_t table_id;
pad(3);
@@ -1279,7 +1279,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
uint64_t packet_count;
uint64_t byte_count;
@@ -1293,7 +1293,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1303,7 +1303,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_table_stats_entry_t) entries;
};
@@ -1314,7 +1314,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
of_port_no_t port_no;
pad(4);
@@ -1326,7 +1326,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_port_stats_entry_t) entries;
};
@@ -1337,7 +1337,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
of_port_no_t port_no;
uint32_t queue_id;
@@ -1349,7 +1349,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_queue_stats_entry_t) entries;
};
@@ -1360,7 +1360,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 6;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint32_t group_id;
pad(4);
@@ -1372,7 +1372,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 6;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_group_stats_entry_t) entries;
};
@@ -1383,7 +1383,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 7;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1393,7 +1393,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 7;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_group_desc_stats_entry_t) entries;
};
@@ -1404,7 +1404,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 8;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1414,7 +1414,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 8;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
uint32_t types;
uint32_t capabilities;
@@ -1434,7 +1434,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0xffff;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint32_t experimenter == ?;
uint32_t subtype;
@@ -1447,7 +1447,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0xffff;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
uint32_t experimenter == ?;
uint32_t subtype;
@@ -1519,7 +1519,7 @@
uint8_t type == 24;
uint16_t length;
uint32_t xid;
- uint32_t role;
+ enum ofp_controller_role role;
pad(4);
uint64_t generation_id;
};
@@ -1529,5 +1529,7 @@
uint8_t type == 25;
uint16_t length;
uint32_t xid;
- of_octets_t data;
+ enum ofp_controller_role role;
+ pad(4);
+ uint64_t generation_id;
};
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index 9d53f11..db7ff0d 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -58,10 +58,6 @@
OFPQ_MIN_RATE_UNCFG = 0xffff,
};
-enum ofp_port_no(wire_type=uint32_t, complete=False) {
- OFPP_ANY = 0xffffffff,
-};
-
enum ofp_port(wire_type=uint32_t) {
OFPP_MAX = 0xffffff00,
OFPP_IN_PORT = 0xfffffff8,
@@ -71,6 +67,7 @@
OFPP_ALL = 0xfffffffc,
OFPP_CONTROLLER = 0xfffffffd,
OFPP_LOCAL = 0xfffffffe,
+ OFPP_ANY = 0xffffffff,
};
enum ofp_type(wire_type=uint8_t) {
@@ -280,6 +277,13 @@
OFPR_NO_MATCH = 0,
OFPR_ACTION = 1,
OFPR_INVALID_TTL = 2,
+
+ // non-standard BSN extensions. OF does not have a standard-conformant
+ // way to extend the set of packet_in reasons
+ OFPR_BSN_NEW_HOST = 128,
+ OFPR_BSN_STATION_MOVE = 129,
+ OFPR_BSN_BAD_VLAN = 130,
+ OFPR_BSN_DESTINATION_LOOKUP_FAILURE = 131,
};
enum ofp_flow_removed_reason(wire_type=uint8_t) {
@@ -730,7 +734,7 @@
};
// FIXME Does this need to be v4?
-struct of_match_v3(align=8) {
+struct of_match_v3(align=8, length_includes_align=False) {
uint16_t type == 1;
uint16_t length;
list(of_oxm_t) oxm_list;
@@ -829,13 +833,13 @@
pad(4);
};
-struct of_action_set_field : of_action {
+struct of_action_set_field(align=8, length_includes_align=True) : of_action {
uint16_t type == 25;
uint16_t len;
of_oxm_t field;
};
-struct of_action_experimenter : of_action {
+struct of_action_experimenter(align=8, length_includes_align=True): of_action {
uint16_t type == 65535;
uint16_t len;
uint32_t experimenter == ?;
@@ -1402,7 +1406,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1412,7 +1416,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == ?;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
};
@@ -1422,7 +1426,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1432,7 +1436,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 0;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
of_desc_str_t mfr_desc;
of_desc_str_t hw_desc;
@@ -1447,7 +1451,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint8_t table_id;
pad(3);
@@ -1465,7 +1469,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 1;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_flow_stats_entry_t) entries;
};
@@ -1476,7 +1480,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint8_t table_id;
pad(3);
@@ -1494,7 +1498,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 2;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
uint64_t packet_count;
uint64_t byte_count;
@@ -1508,7 +1512,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1518,7 +1522,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 3;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_table_stats_entry_t) entries;
};
@@ -1659,7 +1663,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
of_port_no_t port_no;
pad(4);
@@ -1671,7 +1675,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 4;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_port_stats_entry_t) entries;
};
@@ -1682,7 +1686,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
of_port_no_t port_no;
uint32_t queue_id;
@@ -1694,7 +1698,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 5;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_queue_stats_entry_t) entries;
};
@@ -1705,7 +1709,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 6;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint32_t group_id;
pad(4);
@@ -1717,7 +1721,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 6;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_group_stats_entry_t) entries;
};
@@ -1728,7 +1732,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 7;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1738,7 +1742,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 7;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_group_desc_stats_entry_t) entries;
};
@@ -1749,7 +1753,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 8;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1759,7 +1763,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 8;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
uint32_t types;
uint32_t capabilities;
@@ -1779,7 +1783,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 9;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint32_t meter_id;
pad(4);
@@ -1791,7 +1795,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 9;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_meter_stats_t) entries;
};
@@ -1802,7 +1806,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 10;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
uint32_t meter_id;
pad(4);
@@ -1814,7 +1818,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 10;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_meter_band_t) entries;
};
@@ -1826,7 +1830,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 11;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1837,7 +1841,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 11;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
of_meter_features_t features;
};
@@ -1849,7 +1853,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 12;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
list(of_table_features_t) entries;
};
@@ -1861,7 +1865,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 12;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_table_features_t) entries;
};
@@ -1873,7 +1877,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 13;
- uint16_t flags;
+ enum ofp_stats_request_flags flags;
pad(4);
};
@@ -1884,7 +1888,7 @@
uint16_t length;
uint32_t xid;
uint16_t stats_type == 13;
- uint16_t flags;
+ enum ofp_stats_reply_flags flags;
pad(4);
list(of_port_desc_t) entries;
};
@@ -1983,7 +1987,7 @@
uint8_t type == 24;
uint16_t length;
uint32_t xid;
- uint32_t role;
+ enum ofp_controller_role role;
pad(4);
uint64_t generation_id;
};
@@ -1993,7 +1997,9 @@
uint8_t type == 25;
uint16_t length;
uint32_t xid;
- of_octets_t data;
+ enum ofp_controller_role role;
+ pad(4);
+ uint64_t generation_id;
};
////////////////////////////////////////////////////////////////
diff --git a/test_data/__init__.py b/test_data/__init__.py
index 7a55c11..dc063fa 100644
--- a/test_data/__init__.py
+++ b/test_data/__init__.py
@@ -26,6 +26,7 @@
# EPL for the specific language governing permissions and limitations
# under the EPL.
+import fnmatch
import os
_test_data_dir = os.path.dirname(os.path.realpath(__file__))
@@ -45,6 +46,11 @@
result.append(dirname + '/' + filename)
return sorted(result)
+def glob(pattern):
+ for f in list_files():
+ if fnmatch.fnmatch(f, pattern):
+ yield f
+
def exists(name):
return os.path.exists(os.path.join(_test_data_dir, name))
diff --git a/test_data/of13/action_output.data b/test_data/of13/action_output.data
index 7cd52ce..7653a30 100644
--- a/test_data/of13/action_output.data
+++ b/test_data/of13/action_output.data
@@ -6,3 +6,5 @@
00 00 00 00 00 00 # pad
-- python
ofp.action.output(port=50, max_len=65535)
+-- java
+builder.setPort(OFPort.of(50)).setMaxLen(65535)
diff --git a/test_data/of13/action_set_field__eth_dst.data b/test_data/of13/action_set_field__eth_dst.data
new file mode 100644
index 0000000..833bb36
--- /dev/null
+++ b/test_data/of13/action_set_field__eth_dst.data
@@ -0,0 +1,11 @@
+-- binary
+00 19 # type
+00 10 # length
+80 00 06 06 # OXM header
+00 01 02 03 04 05 # OXM value
+00 00 # pad
+-- python
+ofp.action.set_field(field=ofp.oxm.eth_dst([0, 1, 2, 3, 4, 5]))
+-- java
+OFOxms oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+builder.setField(oxms.ethDst(MacAddress.of("00:01:02:03:04:05")))
diff --git a/test_data/of13/action_set_field_ipv6_src.data b/test_data/of13/action_set_field__ipv6_src.data
similarity index 60%
rename from test_data/of13/action_set_field_ipv6_src.data
rename to test_data/of13/action_set_field__ipv6_src.data
index f440dee..cfa2738 100644
--- a/test_data/of13/action_set_field_ipv6_src.data
+++ b/test_data/of13/action_set_field__ipv6_src.data
@@ -5,3 +5,6 @@
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f # OXM value
-- python
ofp.action.set_field(field=ofp.oxm.ipv6_src("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"))
+-- java
+OFOxms oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+builder.setField(oxms.ipv6Src(IPv6Address.of("0001:0203:0405:0607:0809:0a0b:0c0d:0e0f")))
diff --git a/test_data/of13/action_set_field__tcp_src.data b/test_data/of13/action_set_field__tcp_src.data
new file mode 100644
index 0000000..41c4780
--- /dev/null
+++ b/test_data/of13/action_set_field__tcp_src.data
@@ -0,0 +1,11 @@
+-- binary
+00 19 # type
+00 10 # length
+80 00 1a 02 # OXM header
+00 32 # OXM value
+00 00 00 00 00 00 # pad
+-- python
+ofp.action.set_field(field=ofp.oxm.tcp_src(50))
+-- java
+OFOxms oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+builder.setField(oxms.tcpSrc(TransportPort.of(50)))
diff --git a/test_data/of13/action_set_field_eth_dst.data b/test_data/of13/action_set_field_eth_dst.data
deleted file mode 100644
index 1e4a971..0000000
--- a/test_data/of13/action_set_field_eth_dst.data
+++ /dev/null
@@ -1,8 +0,0 @@
--- binary
-00 19 # type
-00 10 # length
-80 00 06 06 # OXM header
-00 01 02 03 04 05 # OXM value
-00 00 # pad
--- python
-ofp.action.set_field(field=ofp.oxm.eth_dst([0, 1, 2, 3, 4, 5]))
diff --git a/test_data/of13/action_set_field_tcp_src.data b/test_data/of13/action_set_field_tcp_src.data
deleted file mode 100644
index a69c7c0..0000000
--- a/test_data/of13/action_set_field_tcp_src.data
+++ /dev/null
@@ -1,8 +0,0 @@
--- binary
-00 19 # type
-00 10 # length
-80 00 1a 02 # OXM header
-00 32 # OXM value
-00 00 00 00 00 00 # pad
--- python
-ofp.action.set_field(field=ofp.oxm.tcp_src(50))
diff --git a/wireshark_gen/__init__.py b/wireshark_gen/__init__.py
index b4135ea..c4ff7f4 100644
--- a/wireshark_gen/__init__.py
+++ b/wireshark_gen/__init__.py
@@ -35,7 +35,7 @@
templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
-DissectorField = namedtuple("DissectorField", ["fullname", "name", "type", "base"])
+DissectorField = namedtuple("DissectorField", ["fullname", "name", "type", "base", "enum_table"])
proto_names = { 1: 'of10', 2: 'of11', 3: 'of12', 4: 'of13' }
def make_field_name(wire_version, ofclass_name, member_name):
@@ -43,6 +43,17 @@
ofclass_name[3:],
member_name)
+def get_reader(version, cls, m):
+ """
+ Decide on a reader function to use for the given field
+ """
+ ofproto = of_g.ir[version]
+ enum = ofproto.enum_by_name(m.oftype)
+ if enum and 'wire_type' in enum.params:
+ return "read_" + enum.params['wire_type']
+ else:
+ return "read_" + m.oftype.replace(')', '').replace('(', '_')
+
def get_field_info(version, cls, name, oftype):
"""
Decide on a Wireshark type and base for a given field.
@@ -50,10 +61,14 @@
Returns (type, base)
"""
if oftype.startswith("list"):
- return "bytes", "NONE"
+ return "bytes", "NONE", "nil"
ofproto = of_g.ir[version]
+
enum = ofproto.enum_by_name(oftype)
+ if not enum and (cls, name) in field_info.class_field_to_enum:
+ enum_name = field_info.class_field_to_enum[(cls, name)]
+ enum = ofproto.enum_by_name(enum_name)
if enum:
field_type = "uint32"
@@ -76,7 +91,12 @@
print "WARN missing oftype_to_base for", oftype
field_base = "NONE"
- return field_type, field_base
+ if enum:
+ enum_table = 'enum_v%d_%s' % (version, enum.name)
+ else:
+ enum_table = 'nil'
+
+ return field_type, field_base, enum_table
def create_fields():
r = []
@@ -86,8 +106,8 @@
if isinstance(m, OFPadMember):
continue
fullname = make_field_name(wire_version, ofclass.name, m.name)
- field_type, field_base = get_field_info(wire_version, ofclass.name, m.name, m.oftype)
- r.append(DissectorField(fullname, m.name, field_type, field_base))
+ field_type, field_base, enum_table = get_field_info(wire_version, ofclass.name, m.name, m.oftype)
+ r.append(DissectorField(fullname, m.name, field_type, field_base, enum_table))
return r
diff --git a/wireshark_gen/field_info.py b/wireshark_gen/field_info.py
index 167ff32..2809c2a 100644
--- a/wireshark_gen/field_info.py
+++ b/wireshark_gen/field_info.py
@@ -81,6 +81,32 @@
"of_bitmap_128_t": "NONE",
}
+# Use enums for certain fields where it isn't specified in the LOXI input
+class_field_to_enum = {
+ ('of_flow_mod', 'type'): 'ofp_type',
+ ('of_error_msg', 'type'): 'ofp_type',
+ ('of_stats_request', 'type'): 'ofp_type',
+ ('of_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_stats_request', 'flags'): 'ofp_stats_request_flags',
+ ('of_stats_reply', 'type'): 'ofp_type',
+ ('of_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_stats_reply', 'flags'): 'ofp_stats_reply_flags',
+ ('of_flow_mod', 'table_id'): 'ofp_table',
+ ('of_flow_mod', '_command'): 'ofp_flow_mod_command',
+ ('of_flow_mod', 'out_port'): 'ofp_port',
+ ('of_flow_mod', 'out_group'): 'ofp_group',
+ ('of_error_msg', 'err_type'): 'ofp_error_type',
+ ('of_port_mod', 'type'): 'ofp_type',
+ ('of_hello', 'type'): 'ofp_type',
+ ('of_features_request', 'type'): 'ofp_type',
+ ('of_features_reply', 'type'): 'ofp_type',
+ ('of_barrier_request', 'type'): 'ofp_type',
+ ('of_barrier_reply', 'type'): 'ofp_type',
+ ('of_echo_request', 'type'): 'ofp_type',
+ ('of_echo_reply', 'type'): 'ofp_type',
+ ('of_match_v3', 'type'): 'ofp_match_type'
+}
+
# Override oftype_to_base for certain field names
field_to_base = {
"eth_type": "HEX",
diff --git a/wireshark_gen/templates/_ofclass_dissector.lua b/wireshark_gen/templates/_ofclass_dissector.lua
index f1c81b0..4aef886 100644
--- a/wireshark_gen/templates/_ofclass_dissector.lua
+++ b/wireshark_gen/templates/_ofclass_dissector.lua
@@ -26,7 +26,7 @@
:: # under the EPL.
::
:: from loxi_ir import *
-:: from wireshark_gen import make_field_name
+:: from wireshark_gen import make_field_name, get_reader
:: attrs = []
:: if ofclass.virtual: attrs.append("virtual")
:: if ofclass.superclass: attrs.append("child")
@@ -45,7 +45,7 @@
:: continue
:: #endif
:: field_name = make_field_name(version, ofclass.name, m.name)
-:: reader_name = "read_" + m.oftype.replace(')', '').replace('(', '_')
+:: reader_name = get_reader(version, ofclass, m)
${reader_name}(reader, ${version}, subtree, '${field_name}')
:: #endfor
return '${ofclass.name}'
diff --git a/wireshark_gen/templates/_ofreader.lua b/wireshark_gen/templates/_ofreader.lua
index b25f7c8..a4c57be 100644
--- a/wireshark_gen/templates/_ofreader.lua
+++ b/wireshark_gen/templates/_ofreader.lua
@@ -64,5 +64,9 @@
return r
end
+ self.skip_align = function()
+ offset = math.floor((offset + 7)/8)*8
+ end
+
return self
end
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index fb6eb6f..8f01718 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -89,6 +89,10 @@
read_scalar(reader, subtree, field_name, 4)
end
+function read_of_ipv6_t(reader, version, subtree, field_name)
+ read_scalar(reader, subtree, field_name, 16)
+end
+
function read_of_fm_cmd_t(reader, version, subtree, field_name)
if version == 1 then
read_scalar(reader, subtree, field_name, 2)
@@ -97,10 +101,6 @@
end
end
-function read_ofp_flow_mod_flags(reader, version, subtree, field_name)
- read_scalar(reader, subtree, field_name, 2)
-end
-
function read_list_of_action_t(reader, version, subtree, field_name)
if reader.is_empty() then
return
@@ -123,3 +123,32 @@
function read_list_of_packet_queue_t(reader, version, subtree, field_name)
-- TODO
end
+
+function read_list_of_oxm_t(reader, version, subtree, field_name)
+ if reader.is_empty() then
+ return
+ end
+ local list_len = reader.peek(-2,2):uint()
+ local reader2 = reader.slice(list_len - 4)
+ local list = nil
+ if not reader2.is_empty() then
+ list = subtree:add(fields[field_name], reader2.peek_all(0))
+ end
+ while not reader2.is_empty() do
+ local match_len = 4 + reader2.peek(3,1):uint()
+ local child_reader = reader2.slice(match_len)
+ local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+ local info = dissect_of_oxm_v3(child_reader, child_subtree)
+ child_subtree:set_text(info)
+ end
+ reader.skip_align()
+end
+
+function read_list_of_instruction_t(reader, version, subtree, field_name)
+ if reader.is_empty() then
+ return
+ end
+ if not reader.is_empty() then
+ subtree:add(fields[field_name], reader.read_all())
+ end
+end
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
index 1b1bc8a..5ab11cd 100644
--- a/wireshark_gen/templates/openflow.lua
+++ b/wireshark_gen/templates/openflow.lua
@@ -53,10 +53,11 @@
:: #endfor
+
fields = {}
:: for field in fields:
:: if field.type in ["uint8", "uint16", "uint32", "uint64"]:
-fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}", base.${field.base})
+fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}", base.${field.base}, ${field.enum_table})
:: elif field.type in ["ipv4", "ipv6", "ether", "bytes", "stringz"]:
fields[${repr(field.fullname)}] = ProtoField.${field.type}("${field.fullname}", "${field.name}")
:: else:
@@ -119,6 +120,16 @@
return protocol, info
end
+function dissect_of_oxm_v3(reader, subtree)
+ local type_val = reader.peek(0,4):uint()
+
+ local info = "unknown"
+ if of_oxm_v3_dissectors[type_val] then
+ info = of_oxm_v3_dissectors[type_val](reader, subtree)
+ end
+
+ return info
+end
-- of dissector function
function p_of.dissector (buf, pkt, root)
local offset = 0