Merge into master from pull request #35:
generate loci tests from the test_data files (https://github.com/floodlight/loxigen/pull/35)
diff --git a/Makefile b/Makefile
index eef6313..cb60398 100644
--- a/Makefile
+++ b/Makefile
@@ -68,8 +68,9 @@
java: .loxi_ts.java
-.loxi_ts.java: ${LOXI_JAVA_FILES} ${LOXI_TEMPLATE_FILES} ${INPUT_FILES}
+.loxi_ts.java: ${LOXI_PY_FILES} ${LOXI_TEMPLATE_FILES} ${INPUT_FILES}
./loxigen.py --install-dir=${LOXI_OUTPUT_DIR} --lang=java
+ cd ${LOXI_OUTPUT_DIR}/openflowj; mvn package
touch $@
@@ -90,6 +91,7 @@
./utest/test_parser.py
./utest/test_frontend.py
./utest/test_test_data.py
+ ./utest/test_generic_utils.py
check-py: python
PYTHONPATH=${LOXI_OUTPUT_DIR}/pyloxi:. python py_gen/tests/generic_util.py
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index ff111f8..9910b7f 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -81,6 +81,7 @@
uint16_t="val16",
uint32_t="val32",
uint64_t="val64",
+ of_ipv4_t="ipv4",
of_port_no_t="port_no",
of_fm_cmd_t="fm_cmd",
of_wc_bmap_t="wc_bmap",
@@ -107,7 +108,7 @@
integer_types = ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
"of_port_no_t", "of_fm_cmd_t", "of_wc_bmap_t",
- "of_match_bmap_t"]
+ "of_match_bmap_t", "of_ipv4_t"]
string_types = [ "of_port_name_t", "of_table_name_t",
"of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
"of_ipv6_t"]
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index acb06b8..b28b807 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -74,7 +74,7 @@
*/
#define LOCI_SHOW_u32_ipv6_flabel(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
#define LOCI_SHOW_u8_vlan_pcp(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
-#define LOCI_SHOW_u32_ipv4_src(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
+#define LOCI_SHOW_ipv4_ipv4_src(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
#define LOCI_SHOW_ipv6_ipv6_dst(writer, cookie, val) LOCI_SHOW_ipv6(writer, cookie, val)
#define LOCI_SHOW_u32_arp_tpa(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
#define LOCI_SHOW_u8_icmpv6_type(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
@@ -99,7 +99,7 @@
#define LOCI_SHOW_u8_ip_ecn(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
#define LOCI_SHOW_u16_udp_dst(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
#define LOCI_SHOW_port_no_in_phy_port(writer, cookie, val) LOCI_SHOW_port_no(writer, cookie, val)
-#define LOCI_SHOW_u32_ipv4_dst(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
+#define LOCI_SHOW_ipv4_ipv4_dst(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
#define LOCI_SHOW_mac_eth_src(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
#define LOCI_SHOW_u16_udp_src(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
#define LOCI_SHOW_mac_ipv6_nd_tll(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
@@ -266,8 +266,8 @@
#define LOCI_SHOW_u64_metadata_mask(writer, cookie, val) LOCI_SHOW_x64(writer, cookie, val)
#define LOCI_SHOW_mac_eth_src_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
#define LOCI_SHOW_mac_eth_dst_mask(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
-#define LOCI_SHOW_u32_ipv4_src_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u32_ipv4_dst_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
+#define LOCI_SHOW_ipv4_ipv4_src_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
+#define LOCI_SHOW_ipv4_ipv4_dst_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
#define LOCI_SHOW_u32_curr_speed(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
#define LOCI_SHOW_u32_max_speed(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
#define LOCI_SHOW_match_bmap_match(writer, cookie, val) LOCI_SHOW_match_bmap(writer, cookie, val)
@@ -328,11 +328,12 @@
#define LOCI_SHOW_u32_service(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
#define LOCI_SHOW_u32_status(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
#define LOCI_SHOW_u16_subtype(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-#define LOCI_SHOW_u32_ipv4_addr(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
-#define LOCI_SHOW_u32_ipv4_netmask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
+#define LOCI_SHOW_ipv4_ipv4_addr(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
+#define LOCI_SHOW_ipv4_ipv4_netmask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
#define LOCI_SHOW_u8_l2_table_enable(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
#define LOCI_SHOW_u16_l2_table_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
-
+#define LOCI_SHOW_ipv4_value(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
+#define LOCI_SHOW_ipv4_value_mask(writer, cookie, val) LOCI_SHOW_ipv4(writer, cookie, val)
#endif /* _LOCI_SHOW_H_ */
diff --git a/c_gen/templates/of_wire_buf.h b/c_gen/templates/of_wire_buf.h
index 9e91b9b..8750565 100644
--- a/c_gen/templates/of_wire_buf.h
+++ b/c_gen/templates/of_wire_buf.h
@@ -348,6 +348,38 @@
buf_u32_set(OF_WIRE_BUFFER_INDEX(wbuf, offset), value);
}
+
+/**
+ * Get a uint32_t scalar from a wire buffer
+ * @param wbuf The pointer to the wire buffer structure
+ * @param offset Offset in the wire buffer
+ * @param value Pointer to where to put value
+ *
+ * The underlying buffer accessor funtions handle endian and alignment.
+ */
+
+static inline void
+of_wire_buffer_ipv4_get(of_wire_buffer_t *wbuf, int offset, of_ipv4_t *value)
+{
+ of_wire_buffer_u32_get(wbuf, offset, value);
+}
+
+/**
+ * Set a ipv4 (uint32_t) scalar in a wire buffer
+ * @param wbuf The pointer to the wire buffer structure
+ * @param offset Offset in the wire buffer
+ * @param value The value to store
+ *
+ * The underlying buffer accessor funtions handle endian and alignment.
+ */
+
+static inline void
+of_wire_buffer_ipv4_set(of_wire_buffer_t *wbuf, int offset, of_ipv4_t value)
+{
+ of_wire_buffer_u32_set(wbuf, offset, value);
+}
+
+
/**
* Get a uint64_t scalar from a wire buffer
* @param wbuf The pointer to the wire buffer structure
diff --git a/java_gen/.classpath b/java_gen/.classpath
new file mode 100644
index 0000000..050cd9c
--- /dev/null
+++ b/java_gen/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="lib" path="pre-written/lib/netty-3.2.6.Final.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/java_gen/.project b/java_gen/.project
new file mode 100644
index 0000000..b347bd6
--- /dev/null
+++ b/java_gen/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>openflowj-loxi</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/java_gen/codegen.py b/java_gen/codegen.py
new file mode 100644
index 0000000..0765c91
--- /dev/null
+++ b/java_gen/codegen.py
@@ -0,0 +1,116 @@
+# Copyright 2013, Big Switch Networks, Inc.
+#
+# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+# the following special exception:
+#
+# LOXI Exception
+#
+# As a special exception to the terms of the EPL, you may distribute libraries
+# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+# that copyright and licensing notices generated by LoxiGen are not altered or removed
+# from the LoxiGen Libraries and the notice provided below is (i) included in
+# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+# documentation for the LoxiGen Libraries, if distributed in binary form.
+#
+# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+#
+# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+# a copy of the EPL at:
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# EPL for the specific language governing permissions and limitations
+# under the EPL.
+
+"""
+@brief Main Java Generation module
+"""
+
+import pdb
+import os
+import shutil
+
+import of_g
+from loxi_ir import *
+import lang_java
+
+import loxi_utils.loxi_utils as loxi_utils
+
+import java_gen.java_model as java_model
+
+def gen_all_java(out, name):
+ basedir= '%s/openflowj' % of_g.options.install_dir
+ srcdir = "%s/src/main/java/" % basedir
+ print "Outputting to %s" % basedir
+ if os.path.exists(basedir):
+ shutil.rmtree(basedir)
+ os.makedirs(basedir)
+ copy_prewrite_tree(basedir)
+
+ gen = JavaGenerator(srcdir)
+ gen.create_of_interfaces()
+ gen.create_of_classes()
+ gen.create_of_const_enums()
+
+ with open('%s/README.java-lang' % os.path.dirname(__file__)) as readme_src:
+ out.writelines(readme_src.readlines())
+ out.close()
+
+
+class JavaGenerator(object):
+ templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
+
+ def __init__(self, basedir):
+ self.basedir = basedir
+ self.java_model = java_model.model
+
+ def render_class(self, clazz, template, **context):
+ context['class_name'] = clazz.name
+ context['package'] = clazz.package
+
+ filename = os.path.join(self.basedir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
+ dirname = os.path.dirname(filename)
+ if not os.path.exists(dirname):
+ os.makedirs(dirname)
+ prefix = '//::(?=[ \t]|$)'
+ print "filename: %s" % filename
+ with open(filename, "w") as f:
+ loxi_utils.render_template(f, template, [self.templates_dir], context, prefix=prefix)
+
+ def create_of_const_enums(self):
+ for enum in self.java_model.enums:
+ if enum.name in ["OFPort"]:
+ continue
+ self.render_class(clazz=enum,
+ template='const.java', enum=enum, all_versions=self.java_model.versions)
+
+ def create_of_interfaces(self):
+ """ Create the base interfaces for of classes"""
+ for interface in self.java_model.interfaces:
+ #if not utils.class_is_message(interface.c_name):
+ # continue
+ self.render_class(clazz=interface,
+ template="of_interface.java", msg=interface)
+
+ def create_of_classes(self):
+ """ Create the OF classes with implementations for each of the interfaces and versions """
+ for interface in self.java_model.interfaces:
+ if interface.name == "OFTableMod":
+ continue
+ if not loxi_utils.class_is_message(interface.c_name) and not loxi_utils.class_is_oxm(interface.c_name):
+ continue
+ for java_class in interface.versioned_classes:
+ self.render_class(clazz=java_class,
+ template='of_class.java', version=java_class.version, msg=java_class,
+ impl_class=java_class.name)
+
+def copy_prewrite_tree(basedir):
+ """ Recursively copy the directory structure from ./java_gen/pre-write
+ into $basedir"""
+ print "Copying pre-written files into %s" % basedir
+ #subprocess.call("cd java_gen/pre-written && tar cpf - pom.xml | ( cd ../../%s && tar xvpf - )" % basedir,
+ # shell=True)
+ os.symlink(os.path.abspath("%s/pre-written/pom.xml" % os.path.dirname(__file__)), "%s/pom.xml" % basedir)
diff --git a/java_gen/java_code_gen.py b/java_gen/java_code_gen.py
deleted file mode 100644
index 91c89a7..0000000
--- a/java_gen/java_code_gen.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import of_g
-import pdb
-import os
-
-import lang_java
-
-import loxi_utils.loxi_utils as loxi_utils
-
-import java_gen.msgs as msgs
-import java_gen.java_utils as java_utils
-
-def gen_all_java(out, name):
- """ Generate all of the java files
-
- @param out is an open file handle to a file called README
- @param name should be 'README' and is ignored for the java
- driver
- """
- messages = list()
- actions = list()
- instructions = list()
- matches = list()
- stat_types = list()
- queue_prop = list()
- lists = list()
- for cls in of_g.unified:
- print "! Classifying %s" % cls
- if cls in [ 'of_stats_reply', 'of_flow_mod', 'of_stats_request' ] :
- continue # doesn't work?!
- if loxi_utils.class_is_stats_message(cls):
- stat_types.append(cls)
- elif loxi_utils.class_is_message(cls):
- messages.append(cls)
- elif loxi_utils.class_is_action(cls):
- actions.append(cls)
- elif loxi_utils.class_is_instruction(cls):
- instructions.append(cls)
- elif loxi_utils.class_is_oxm(cls):
- matches.append(cls)
- elif loxi_utils.class_is_queue_prop(cls):
- queue_prop.append(cls)
- elif loxi_utils.class_is_list(cls):
- lists.append(cls)
- else:
- print "Skipping Unknown class object %s" % str(cls)
- print "Parsed "
- print " Messages: %d" % len(messages)
- print " Actions: %d" % len(actions)
- print " Instructions: %d" % len(instructions)
- print " OXM matches: %d" % len(matches)
- print " Stat types: %d" % len(stat_types)
- print " Queue properties: %d" % len(queue_prop)
- print " Lists: %d" % len(lists)
- target_dir='loxi_output/openflowj'
- basedir="%s/%s/" % (
- target_dir,
- lang_java.file_to_subdir_map['base_java'])
- srcdir = "%s/src/main/java/org/openflow/protocol" % basedir
- print "Outputting to %s" % basedir
- if not os.path.exists(basedir):
- os.makedirs(basedir)
- java_utils.copy_prewrite_tree(basedir)
- msgs.create_message_interfaces(messages,srcdir)
- msgs.create_message_by_version(messages,srcdir)
- msgs.create_of_type_enum(messages,srcdir)
- with open('README.java-lang') as readme_src:
- out.writelines(readme_src.readlines())
- out.close()
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 062a64d..3755c82 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -1,19 +1,103 @@
+# Copyright 2013, Big Switch Networks, Inc.
+#
+# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+# the following special exception:
+#
+# LOXI Exception
+#
+# As a special exception to the terms of the EPL, you may distribute libraries
+# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+# that copyright and licensing notices generated by LoxiGen are not altered or removed
+# from the LoxiGen Libraries and the notice provided below is (i) included in
+# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+# documentation for the LoxiGen Libraries, if distributed in binary form.
+#
+# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+#
+# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+# a copy of the EPL at:
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# EPL for the specific language governing permissions and limitations
+# under the EPL.
+
# Prototype of an Intermediate Object model for the java code generator
# A lot of this stuff could/should probably be merged with the python utilities
-import of_g
+import collections
+from collections import namedtuple, defaultdict
+import logging
import os
import pdb
import re
+from generic_utils import find, memoize, OrderedSet
+import of_g
+from loxi_ir import *
import loxi_front_end.type_maps as type_maps
import loxi_utils.loxi_utils as utils
import py_gen.util as py_utils
-import java_gen.java_utils as java_utils
-ignore_fields = ['version', 'xid', 'length', 'type' ]
+import java_gen.java_type as java_type
-protected_fields = ['version', 'length']
+class JavaModel(object):
+ write_blacklist = defaultdict(lambda: set(), OFOxm=set(('typeLen',)))
+ virtual_interfaces = set(['OFOxm' ])
+
+ @property
+ @memoize
+ def versions(self):
+ return OrderedSet( JavaOFVersion(raw_version) for raw_version in of_g.target_version_list )
+
+ @property
+ @memoize
+ def interfaces(self):
+ version_map_per_class = collections.defaultdict(lambda: {})
+
+ for raw_version, of_protocol in of_g.ir.items():
+ jversion = JavaOFVersion(of_protocol.wire_version)
+
+ for of_class in of_protocol.classes:
+ version_map_per_class[of_class.name][jversion] = of_class
+
+ interfaces = []
+ for class_name, version_map in version_map_per_class.items():
+ interfaces.append(JavaOFInterface(class_name, version_map))
+
+ return interfaces
+
+ @property
+ @memoize
+ def enums(self):
+ enum_entry_version_value_map = collections.defaultdict(lambda: collections.defaultdict(lambda: collections.OrderedDict()))
+
+ for version in self.versions:
+ of_protocol = of_g.ir[version.int_version]
+ for enum in of_protocol.enums:
+ for entry_name, entry_value in enum.values:
+ enum_entry_version_value_map[enum.name][entry_name][version] = entry_value
+
+ enums = [ JavaEnum(name, entry_version_value_map) for name, entry_version_value_map
+ in enum_entry_version_value_map.items() ]
+
+ return enums
+
+ @memoize
+ def enum_by_name(self, name):
+ try:
+ return find(self.enums, lambda e: e.name == name)
+ except KeyError:
+ raise KeyError("Could not find enum with name %s" % name)
+
+model = JavaModel()
+
+#######################################################################
+### OFVersion
+#######################################################################
class JavaOFVersion(object):
""" Models a version of OpenFlow. contains methods to convert the internal
@@ -29,17 +113,193 @@
def constant_version(self):
return "OF_" + self.of_version
+ def __repr__(self):
+ return "JavaOFVersion(%d)" % self.int_version
+
def __str__(self):
return of_g.param_version_names[self.int_version]
-class JavaProperty(object):
- """ Models a property (member) of an openflow class. """
- def __init__(self, msg, java_type, c_type, name, c_name):
- self.msg = msg
- self.java_type = java_type
- self.c_type = c_type
- self.name = name
+ def __hash__(self):
+ return hash(self.int_version)
+
+ def __eq__(self, other):
+ if other is None or type(self) != type(other):
+ return False
+ return (self.int_version,) == (other.int_version,)
+
+#######################################################################
+### Interface
+#######################################################################
+
+class JavaOFInterface(object):
+ """ Models an OpenFlow Message class for the purpose of the java class.
+ Version agnostic, in contrast to the loxi_ir python model.
+ """
+ def __init__(self, c_name, version_map):
self.c_name = c_name
+ self.version_map = version_map
+ self.name = java_type.name_c_to_caps_camel(c_name)
+ self.builder_name = self.name + "Builder"
+ self.constant_name = c_name.upper().replace("OF_", "")
+
+ pck_suffix, parent_interface = self.class_info()
+ self.package = "org.openflow.protocol.%s" % pck_suffix if pck_suffix else "org.openflow.protocol"
+ if self.name != parent_interface:
+ self.parent_interface = parent_interface
+ else:
+ self.parent_interface = None
+
+ def class_info(self):
+ if re.match(r'OFFlow(Add|Modify(Strict?)|Deleted(Strict?))', self.name):
+ return ("", "OFFlowMod")
+ elif utils.class_is_message(self.c_name):
+ return ("", "OFMessage")
+ elif utils.class_is_action(self.c_name):
+ return ("action", "OFAction")
+ elif utils.class_is_oxm(self.c_name):
+ return ("oxm", "OFOxm")
+ elif utils.class_is_instruction(self.c_name):
+ return ("instruction", "OFInstruction")
+ elif utils.class_is_meter_band(self.c_name):
+ return ("meterband", "OFMeterBand")
+ else:
+ return ("", None)
+
+ @property
+ @memoize
+ def members(self):
+ all_versions = []
+ member_map = collections.OrderedDict()
+
+ for (version, of_class) in self.version_map.items():
+ for of_member in of_class.members:
+ if isinstance(of_member, OFLengthMember) or \
+ isinstance(of_member, OFFieldLengthMember) or \
+ isinstance(of_member, OFPadMember):
+ continue
+ if of_member.name not in member_map:
+ member_map[of_member.name] = JavaMember.for_of_member(self, of_member)
+
+ return member_map.values()
+
+ @property
+ @memoize
+ def is_virtual(self):
+ return self.name in model.virtual_interfaces
+
+ @property
+ @memoize
+ def all_versions(self):
+ return self.version_map.keys()
+
+ def versioned_class(self, version):
+ return JavaOFClass(self, version, self.version_map[version])
+
+ @property
+ @memoize
+ def versioned_classes(self):
+ if self.is_virtual:
+ return []
+ else:
+ return [ self.versioned_class(version) for version in self.all_versions ]
+
+#######################################################################
+### (Versioned) Classes
+#######################################################################
+
+class JavaOFClass(object):
+ """ Models an OpenFlow Message class for the purpose of the java class.
+ Version specific child of a JavaOFInterface
+ """
+ def __init__(self, interface, version, ir_class):
+ self.interface = interface
+ self.ir_class = ir_class
+ self.c_name = self.ir_class.name
+ self.version = version
+ self.constant_name = self.c_name.upper().replace("OF_", "")
+ self.package = "org.openflow.protocol.ver%s" % version.of_version
+
+ @property
+ def name(self):
+ return "%sVer%s" % (self.interface.name, self.version.of_version)
+
+ @property
+ def length(self):
+ if self.is_fixed_length:
+ return self.min_length
+ else:
+ raise Exception("No fixed length for class %s, version %s" % (self.name, self.version))
+
+ @property
+ def min_length(self):
+ id_tuple = (self.ir_class.name, self.version.int_version)
+ return of_g.base_length[id_tuple] if id_tuple in of_g.base_length else -1
+
+ @property
+ def is_fixed_length(self):
+ return (self.ir_class.name, self.version.int_version) in of_g.is_fixed_length
+
+ def all_properties(self):
+ return self.interface.members
+
+ def get_member(self, name):
+ for m in self.members:
+ if m.name == name:
+ return m
+
+ @property
+ @memoize
+ def data_members(self):
+ return [ prop for prop in self.members if prop.is_data ]
+
+ @property
+ @memoize
+ def fixed_value_members(self):
+ return [ prop for prop in self.members if prop.is_fixed_value ]
+
+ @property
+ @memoize
+ def public_members(self):
+ return [ prop for prop in self.members if prop.is_public ]
+
+ @property
+ @memoize
+ def members(self):
+ members = [ JavaMember.for_of_member(self, of_member) for of_member in self.ir_class.members ]
+ return members
+
+ def all_versions(self):
+ return [ JavaOFVersion(int_version)
+ for int_version in of_g.unified[self.c_name]
+ if int_version != 'union' and int_version != 'object_id' ]
+
+ def version_is_inherited(self, version):
+ return 'use_version' in of_g.unified[self.ir_class.name][version.int_version]
+
+ def inherited_from(self, version):
+ return JavaOFVersion(of_g.unified[self.ir_class.name][version.int_version]['use_version'])
+
+ @property
+ def is_virtual(self):
+ return type_maps.class_is_virtual(self.c_name)
+
+ @property
+ def is_extension(self):
+ return type_maps.message_is_extension(self.c_name, -1)
+
+#######################################################################
+### Member
+#######################################################################
+
+
+class JavaMember(object):
+ """ Models a property (member) of an openflow class. """
+ def __init__(self, msg, name, java_type, member):
+ self.msg = msg
+ self.name = name
+ self.java_type = java_type
+ self.member = member
+ self.c_name = self.member.name if(hasattr(self.member, "name")) else ""
@property
def title_name(self):
@@ -51,13 +311,18 @@
@property
def default_name(self):
- return "DEFAULT_"+self.constant_name
+ if self.is_fixed_value:
+ return self.constant_name
+ else:
+ return "DEFAULT_"+self.constant_name
@property
def default_value(self):
java_type = self.java_type.public_type;
- if re.match(r'List.*', java_type):
+ if self.is_fixed_value:
+ return self.enum_value
+ elif re.match(r'List.*', java_type):
return "Collections.emptyList()"
elif java_type == "boolean":
return "false";
@@ -67,114 +332,161 @@
return "null";
@property
+ def enum_value(self):
+ if self.name == "version":
+ return "OFVersion.%s" % self.msg.version.constant_version
+
+ java_type = self.java_type.public_type;
+ try:
+ global model
+ enum = model.enum_by_name(java_type)
+ entry = enum.entry_by_version_value(self.msg.version, self.value)
+ return "%s.%s" % ( enum.name, entry.name)
+ except KeyError, e:
+ print e.message
+ return self.value
+
+ @property
def is_pad(self):
- return self.c_name.startswith("pad")
+ return isinstance(self.member, OFPadMember)
+
+ def is_type_value(self, version=None):
+ if(version==None):
+ return any(self.is_type_value(version) for version in self.msg.all_versions)
+ try:
+ return self.c_name in get_type_values(self.msg.c_name, version.int_version)
+ except:
+ return False
+
+ @property
+ def is_field_length_value(self):
+ return isinstance(self.member, OFFieldLengthMember)
+
+ @property
+ def is_length_value(self):
+ return isinstance(self.member, OFLengthMember)
+
+ @property
+ def is_public(self):
+ return not (self.is_pad or self.is_length_value)
+
+ @property
+ def is_data(self):
+ return isinstance(self.member, OFDataMember) and self.name != "version"
+
+ @property
+ def is_fixed_value(self):
+ return hasattr(self.member, "value") or self.name == "version" \
+ or ( self.name == "length" and self.msg.is_fixed_length) \
+ or ( self.name == "len" and self.msg.is_fixed_length)
+
+ @property
+ def value(self):
+ if self.name == "version":
+ return self.msg.version.int_version
+ elif self.name == "length" or self.name == "len":
+ return self.msg.length
+ elif self.java_type.public_type in ("int", "short", "byte") and self.member.value > 100:
+ return "0x%x" % self.member.value
+ else:
+ return self.member.value
+
+ @property
+ def is_writeable(self):
+ return self.is_data and not self.name in model.write_blacklist[self.msg.name]
+
+ def get_type_value_info(self, version):
+ return get_type_values(msg.c_name, version.int_version)[self.c_name]
@property
def length(self):
- count, base = utils.type_dec_to_count_base(self.c_type)
- return of_g.of_base_types[base]['bytes'] * count
+ if hasattr(self.member, "length"):
+ return self.member.length
+ else:
+ count, base = utils.type_dec_to_count_base(self.member.type)
+ return of_g.of_base_types[base]['bytes'] * count
@staticmethod
- def for_field(msg, field, c_name=None):
- if not c_name:
- c_name = field['name']
-
- name = java_utils.name_c_to_camel(c_name)
- java_type = java_utils.convert_to_jtype(msg.c_name, c_name, field['m_type'])
- c_type = field['m_type']
- return JavaProperty(msg, java_type, c_type, name, c_name)
+ def for_of_member(java_class, member):
+ if isinstance(member, OFPadMember):
+ return JavaMember(None, "", None, member)
+ else:
+ if member.name == 'len':
+ name = 'length'
+ 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)
+ return JavaMember(java_class, name, j_type, member)
@property
def is_universal(self):
+ if not self.msg.c_name in of_g.unified:
+ print("%s not self.unified" % self.msg.c_name)
+ return False
for version in of_g.unified[self.msg.c_name]:
if version == 'union' or version =='object_id':
continue
if 'use_version' in of_g.unified[self.msg.c_name][version]:
continue
- if not self.c_name in (f['name'] for f in of_g.unified[self.msg.c_name][version]['members']):
+ if not self.member.name in (f['name'] for f in of_g.unified[self.msg.c_name][version]['members']):
return False
return True
-class JavaOFMessage(object):
- """ Models an OpenFlow Message class """
- def __init__(self, c_name):
- self.c_name = c_name
- self.interface_name = java_utils.name_c_to_caps_camel(c_name)
- self.builder_name = self.interface_name + "Builder"
- self.constant_name = c_name.upper().replace("OF_", "")
+ def __hash__(self):
+ return hash(self.name)
- def min_length(self, version):
- return of_g.base_length[(self.c_name, version.int_version)] if (self.c_name, version.int_version) in of_g.base_length else -1
-
- def is_fixed_length(self, version):
- return (self.c_name, version.int_version) in of_g.is_fixed_length
-
- def class_name_for_version(self, version):
- return self.interface_name + "Ver"+version.of_version
-
-
- def all_properties(self, skip_pads=True):
- if 'union' in of_g.unified[self.c_name]:
- props = []
- fields = of_g.unified[self.c_name]['union']
- for field_name in sorted( fields.keys(), key=lambda k: fields[k]['memid']):
- if field_name in ignore_fields:
- continue
- if skip_pads and field_name.startswith("pad"):
- continue
-
- java_property = JavaProperty.for_field(self, fields[field_name], c_name=field_name)
- props.append(java_property)
- return props
- else:
- return []
-
- def all_versions(self):
- return [ JavaOFVersion(int_version)
- for int_version in of_g.unified[self.c_name]
- if int_version != 'union' and int_version != 'object_id' ]
-
- def property_in_version(self, prop, version):
- if self.version_is_inherited(version):
- version = self.inherited_from(version)
-
- if 'members' not in of_g.unified[self.c_name][version.int_version]:
+ def __eq__(self, other):
+ if other is None or type(self) != type(other):
return False
- return prop.c_name in (member['name'] for member in of_g.unified[self.c_name][version.int_version]['members'])
+ return (self.name,) == (other.name,)
- def properties_for_version(self, version, skip_pads=True):
- props = []
- if self.version_is_inherited(version):
- version = self.inherited_from(version)
+#######################################################################
+### Enums
+#######################################################################
- for field in of_g.unified[self.c_name][version.int_version]['members']:
- if field['name'] in ignore_fields:
- continue
- if skip_pads and field['name'].startswith("pad"):
- continue
+class JavaEnum(object):
+ def __init__(self, c_name, entry_version_value_map):
+ self.c_name = c_name
+ self.name = "OF" + java_type.name_c_to_caps_camel("_".join(c_name.split("_")[1:]))
- java_property = JavaProperty.for_field(self, field, c_name=field['name'])
- props.append(java_property)
- return props
+ # Port_features has constants that start with digits
+ self.name_prefix = "PF_" if self.name == "OFPortFeatures" else ""
- def version_is_inherited(self, version):
- return 'use_version' in of_g.unified[self.c_name][version.int_version]
+ self.entries = [ JavaEnumEntry(self, name, version_value_map)
+ for (name, version_value_map) in entry_version_value_map.items() ]
+ self.package = "org.openflow.protocol"
- def inherited_from(self, version):
- return JavaOFVersion(of_g.unified[self.c_name][version.int_version]['use_version'])
-
- @property
- def is_virtual(self):
- return type_maps.class_is_virtual(self.c_name)
-
- @property
- def is_extension(self):
- return type_maps.message_is_extension(self.c_name, -1)
-
- def wire_type(self, version):
+ @memoize
+ def entry_by_name(self, name):
try:
- return py_utils.primary_wire_type(self.c_name, version.int_version)
- except ValueError, e:
- return -1
+ return find(self.entries, lambda e: e.name == name)
+ except KeyError:
+ raise KeyError("Enum %s: no entry with name %s" % (self.name, name))
+
+ @memoize
+ def entry_by_c_name(self, name):
+ try:
+ return find(self.entries, lambda e: e.c_name == name)
+ except KeyError:
+ raise KeyError("Enum %s: no entry with c_name %s" % (self.name, name))
+
+ @memoize
+ def entry_by_version_value(self, version, value):
+ try:
+ return find(self.entries, lambda e: e.values[version] == value if version in e.values else False )
+ except KeyError:
+ raise KeyError("Enum %s: no entry with version %s, value %s" % (self.name, version, value))
+
+# values: Map JavaVersion->Value
+class JavaEnumEntry(object):
+ def __init__(self, enum, name, values):
+ self.name = enum.name_prefix + "_".join(name.split("_")[1:]).upper()
+ self.values = values
+
+ def value(self, version):
+ res = self.version_value_map[version]
+ return res
+
+ def all_values(self, versions, not_present=None):
+ return [ self.values[version] if version in self.values else not_present for version in versions ]
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
new file mode 100644
index 0000000..3fa9e81
--- /dev/null
+++ b/java_gen/java_type.py
@@ -0,0 +1,230 @@
+import os
+import errno
+import re
+import subprocess
+import time
+
+def name_c_to_camel(name):
+ """ 'of_stats_reply' -> 'ofStatsReply' """
+ name = re.sub(r'^_','', name)
+ tokens = name.split('_')
+ for i in range(1, len(tokens)):
+ tokens[i] = tokens[i].title()
+ return "".join(tokens)
+
+def name_c_to_caps_camel(name):
+ """ 'of_stats_reply' to 'OFStatsReply' """
+ camel = name_c_to_camel(name.title())
+ if camel.startswith('Of'):
+ return camel.replace('Of','OF',1)
+ else:
+ return camel
+
+
+class JType(object):
+ """ Wrapper class to hold C to Java type conversion information """
+ def __init__(self, pub_type, priv_type=None, size=None, read_op=None, write_op=None):
+ self.pub_type = pub_type # the type we expose externally, e.g. 'U8'
+ if priv_type is None:
+ priv_type = pub_type
+ self.priv_type = priv_type # the internal storage type
+ self.size = size # bytes on the wire; None == variable length or hard to calc
+ if read_op is None:
+ read_op = 'ChannelUtils.read%s(bb)' % self.pub_type
+ if write_op is None:
+ write_op = 'ChannelUtils.write%s(bb, $name)' % self.pub_type
+ self._read_op = read_op
+ self._write_op = write_op
+
+ @property
+ def public_type(self):
+ """ return the public type """
+ return self.pub_type
+
+ def priv(self):
+ """ return the public type """
+ return self.priv_type
+
+ def has_priv(self):
+ """ Is the private type different from the public one?"""
+ return self.pub_type != self.priv_type
+
+ def read_op(self, version=None, length=None):
+ if length is None:
+ length = "length - bb.readerIndex()";
+
+ if callable(self._read_op):
+ return self._read_op(version)
+ else:
+ return self._read_op.replace("$length", str(length)).replace("$version", version.of_version)
+
+ def write_op(self, version=None, name=None):
+ if callable(self._write_op):
+ return self._write_op(version, name)
+ else:
+ return self._write_op.replace("$name", str(name)).replace("$version", version.of_version)
+
+hello_elem_list = JType("List<OFHelloElement>",
+ read_op = 'ChannelUtils.readHelloElementList(bb)',
+ write_op = 'ChannelUtils.writeHelloElementList(bb)'
+ )
+u8 = JType('byte', size=1, read_op='bb.readByte()',
+ write_op='bb.writeByte($name)')
+u8_list = JType('List<U8>', size=1, read_op='bb.readByte()',
+ write_op='bb.writeByte($name)')
+u16 = JType('int', 'int', size=2, read_op='U16.f(bb.readShort())',
+ write_op='bb.writeShort(U16.t($name))')
+u32 = JType('int', 'int', size=4, read_op='bb.readInt()',
+ write_op='bb.writeInt($name)')
+u32_list = JType('List<U32>', 'int[]', size=4, read_op='bb.readInt()',
+ write_op='bb.writeInt($name)')
+u64 = JType('U64', 'U64', size=8, read_op='U64.of(bb.readLong())',
+ write_op='bb.writeLong($name.getValue())')
+of_port= JType('OFPort',size=None,
+ read_op=lambda version: 'OFPort.ofShort(bb.readShort())' if version.int_version < 2 else 'OFPort.ofInt(bb.readInt())',
+ write_op=lambda version, name: 'bb.writeShort(%s.getShortPortNumber())' % name if version.int_version < 2 else 'bb.writeInt(%s.getPortNumber())' % name)
+one_byte_array = JType('byte[]', size=1,
+ read_op = 'ChannelUtils.readBytes(bb, 1)',
+ write_op = 'ChannelUtils.writeBytes(bb, $name)')
+two_byte_array = JType('byte[]', size=2,
+ read_op = 'ChannelUtils.readBytes(bb, 2)',
+ write_op = 'ChannelUtils.writeBytes(bb, $name)')
+three_byte_array = JType('byte[]', size=3,
+ read_op = 'ChannelUtils.readBytes(bb, 3)',
+ write_op = 'ChannelUtils.writeBytes(bb, $name)')
+four_byte_array = JType('byte[]', size=4,
+ read_op = 'ChannelUtils.readBytes(bb, 4)',
+ write_op = 'ChannelUtils.writeBytes(bb, $name)')
+five_byte_array = JType('byte[]', size=5,
+ read_op = 'ChannelUtils.readBytes(bb, 5)',
+ write_op = 'ChannelUtils.writeBytes(bb, $name)')
+six_byte_array = JType('byte[]', size=6,
+ read_op = 'ChannelUtils.readBytes(bb, 6)',
+ write_op = 'ChannelUtils.writeBytes(bb, $name)')
+seven_byte_array = JType('byte[]', size=7,
+ read_op = 'ChannelUtils.readBytes(bb, 7)',
+ write_op = 'ChannelUtils.writeBytes(bb, $name)')
+actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)',
+ read_op = 'ChannelUtils.readActionsList(bb, $length)',
+ write_op = 'ChannelUtils.writeActionsList(bb, $name);')
+instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)',
+ read_op = 'ChannelUtils.readInstructionsList(bb, $length)',
+ write_op = 'ChannelUtils.writeList(bb, $name)')
+buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)',
+ read_op = 'ChannelUtils.readBucketList(bb, $length)',
+ write_op = 'ChannelUtils.writeList(bb, $name)')
+port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)',
+ read_op = 'ChannelUtils.readPhysicalPortList(bb, $length)',
+ write_op = 'ChannelUtils.writeList(bb, $name)')
+port_desc = JType('OFPortDesc', size='$name.getLength()',
+ read_op = 'null; // TODO OFPortDescVer$version.READER.read(bb)',
+ write_op = '$name.writeTo(bb)')
+packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)',
+ read_op = 'ChannelUtils.readPacketQueueList(bb, $length)',
+ write_op = 'ChannelUtils.writeList(bb, $name)')
+octets = JType('byte[]', size="$length",
+ read_op = 'ChannelUtils.readBytes(bb, $length)',
+ write_op = 'bb.writeBytes($name)')
+of_match = JType('Match', size="$name.getLength()",
+ read_op = 'ChannelUtils.readOFMatch(bb)',
+ write_op = 'ChannelUtils.writeOFMatch(bb, $name)')
+flow_mod_cmd = JType('OFFlowModCommand', 'short', size="$name.getLength()",
+ read_op = lambda v: "bb.readShort()" if v.int_version == 1 else "bb.readByte()",
+ write_op = lambda v, name: "bb.writeShort(%s)" % name if v.int_version == 1 else "bb.writeByte(%s)" % name)
+mac_addr = JType('MacAddress', 'byte[]', size=6,
+ read_op = 'MacAddress.readFrom(bb)',
+ write_op = '$name.writeTo(bb)')
+port_name = JType('String', size=16,
+ read_op = 'ChannelUtils.readFixedLengthString(bb, 16)',
+ write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 16)')
+desc_str = JType('String', size=256,
+ read_op = 'ChannelUtils.readFixedLengthString(bb, 256)',
+ write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 256)')
+serial_num = JType('String', size=32,
+ read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
+ write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+table_name = JType('String', size=32,
+ read_op = 'ChannelUtils.readFixedLengthString(bb, 32)',
+ write_op = 'ChannelUtils.writeFixedLengthString(bb, $name, 32)')
+ipv4 = JType("IPv4",
+ read_op = "IPv4.readFrom(bb)",
+ write_op = "$name.writeTo(bb)")
+ipv6 = JType("IPv6",
+ read_op = "IPv6.readFrom(bb)",
+ write_op = "$name.writeTo(bb)")
+
+default_mtype_to_jtype_convert_map = {
+ 'uint8_t' : u8,
+ 'uint16_t' : u16,
+ 'uint32_t' : u32,
+ 'uint64_t' : u64,
+ 'uint8_t[1]' : one_byte_array,
+ 'uint8_t[2]' : two_byte_array,
+ 'uint8_t[3]' : three_byte_array,
+ 'uint8_t[4]' : four_byte_array,
+ 'uint8_t[5]' : five_byte_array,
+ 'uint8_t[6]' : six_byte_array,
+ 'uint8_t[7]' : seven_byte_array,
+ 'of_port_no_t' : of_port,
+ 'list(of_action_t)' : actions_list,
+ 'list(of_instruction_t)' : instructions_list,
+ 'list(of_bucket_t)': buckets_list,
+ 'list(of_port_desc_t)' : port_desc_list,
+ 'list(of_packet_queue_t)' : packet_queue_list,
+ 'list(of_uint32_t)' : u32_list,
+ 'list(of_uint8_t)' : u8_list,
+ 'of_octets_t' : octets,
+ 'of_match_t': of_match,
+ 'of_fm_cmd_t': flow_mod_cmd,
+ 'of_mac_addr_t': mac_addr,
+ 'of_port_desc_t': port_desc,
+ 'of_desc_str_t': desc_str,
+ 'of_serial_num_t': serial_num,
+ 'of_port_name_t': port_name,
+ 'of_table_name_t': table_name,
+ 'of_ipv4_t': ipv4,
+ 'of_ipv6_t': ipv6,
+ 'of_wc_bmap_t': JType("Wildcards")
+ }
+
+## This is where we drop in special case handling for certain types
+exceptions = {
+ 'OFPacketIn': {
+ 'data' : octets
+ },
+}
+
+
+def make_standard_list_jtype(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)
+ return JType("List<OF%s>" % java_base_name,
+ read_op = 'ChannelUtils.read%sList(bb)' % java_base_name,
+ write_op = 'ChannelUtils.write%sList(bb, $name)' % java_base_name
+ )
+
+def convert_to_jtype(obj_name, field_name, c_type):
+ """ Convert from a C type ("uint_32") to a java type ("U32")
+ and return a JType object with the size, internal type, and marshalling functions"""
+ if obj_name in exceptions and field_name in exceptions[obj_name]:
+ return exceptions[obj_name][field_name]
+ elif field_name == "type" and c_type == "uint8_t":
+ return JType("OFType", 'byte', size=1, read_op='bb.readByte()',
+ write_op='bb.writeByte($name)')
+ elif field_name == "type" and re.match(r'of_action.*', obj_name):
+ return JType("OFActionType", 'short', size=2, read_op='bb.readShort()',
+ write_op='bb.writeShort($name)')
+ elif field_name == "version" and c_type == "uint8_t":
+ return JType("OFVersion", 'byte', size=1, read_op='bb.readByte()',
+ write_op='bb.writeByte($name)')
+ 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)
+ else:
+ print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
+ jtype = name_c_to_caps_camel(re.sub(r'_t$', "", c_type))
+ return JType(jtype)
diff --git a/java_gen/java_utils.py b/java_gen/java_utils.py
deleted file mode 100644
index c55b275..0000000
--- a/java_gen/java_utils.py
+++ /dev/null
@@ -1,215 +0,0 @@
-import os
-import errno
-import re
-import subprocess
-import time
-
-def name_c_to_camel(name):
- """ 'of_stats_reply' -> 'ofStatsReply' """
- tokens = name.split('_')
- for i in range(1, len(tokens)):
- tokens[i] = tokens[i].title()
- return "".join(tokens)
-
-def name_c_to_caps_camel(name):
- """ 'of_stats_reply' to 'OFStatsReply' """
- camel = name_c_to_camel(name.title())
- if camel.startswith('Of'):
- return camel.replace('Of','OF',1)
- else:
- return camel
-
-
-class JType(object):
- """ Wrapper class to hold C to Java type conversion information """
- def __init__(self, pub_type, priv_type=None, size=None, read_op=None, write_op=None):
- self.pub_type = pub_type # the type we expose externally, e.g. 'U8'
- if priv_type is None:
- priv_type = pub_type
- self.priv_type = priv_type # the internal storage type
- self.size = size # bytes on the wire; None == variable length or hard to calc
- if read_op is None:
- read_op = 'ChannelUtils.read%s(this, "$name", bb)' % self.pub_type
- if write_op is None:
- write_op = 'ChannelUtils.write($name)'
- self._read_op = read_op
- self.write_op = write_op
-
- @property
- def public_type(self):
- """ return the public type """
- return self.pub_type
-
- def priv(self):
- """ return the public type """
- return self.priv_type
-
- def has_priv(self):
- """ Is the private type different from the public one?"""
- return self.pub_type != self.priv_type
-
- def read_op(self, version=None):
- if callable(self._read_op):
- return self._read_op(version)
- else:
- return self._read_op
-
-hello_elem_list = JType("List<OFHelloElement>",
- read_op = 'ChannelUtils.readHelloElementList(bb)',
- write_op = 'ChannelUtils.writeHelloElementList(bb)'
- )
-
-u8 = JType('byte', size=1, read_op='bb.readByte()',
- write_op='bb.writeByte($name)')
-u16 = JType('int', 'int', size=2, read_op='U16.f(bb.readShort())',
- write_op='bb.writeShort(U16.t($name))')
-u32 = JType('int', 'int', size=4, read_op='bb.readInt()',
- write_op='bb.writeInt($name)')
-u64 = JType('U64', 'U64', size=8, read_op='U64.of(bb.readLong())',
- write_op='bb.writeLong($name.getLong())')
-of_port= JType('OFPort',size=None,
- read_op=lambda(version): 'OFPort.ofShort(bb.readShort())' if version.int_version < 2 else 'OFPort.ofInt(bb.readInt())',
- write_op='$name.writeTo(bb)')
-one_byte_array = JType('byte[]', size=1,
- read_op = 'ChannelUtils.readBytes(bb, 1)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-two_byte_array = JType('byte[]', size=2,
- read_op = 'ChannelUtils.readBytes(bb, 2)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-three_byte_array = JType('byte[]', size=3,
- read_op = 'ChannelUtils.readBytes(bb, 3)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-four_byte_array = JType('byte[]', size=4,
- read_op = 'ChannelUtils.readBytes(bb, 4)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-five_byte_array = JType('byte[]', size=5,
- read_op = 'ChannelUtils.readBytes(bb, 5)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-six_byte_array = JType('byte[]', size=6,
- read_op = 'ChannelUtils.readBytes(bb, 6)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-seven_byte_array = JType('byte[]', size=7,
- read_op = 'ChannelUtils.readBytes(bb, 7)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-actions_list = JType('List<OFAction>', size='ChannelUtils.calcListSize($name)',
- read_op = 'ChannelUtils.readActionsList(bb, length - MINIMUM_LENGTH)',
- write_op = 'ChannelUtils.writeList(this, $name)')
-instructions_list = JType('List<OFInstruction>', size='ChannelUtils.calcListSize($name)',
- read_op = 'ChannelUtils.readInstructionsList(bb, length - MINIMUM_LENGTH)',
- write_op = 'ChannelUtils.writeList(this, $name)')
-buckets_list = JType('List<OFBucket>', size='ChannelUtils.calcListSize($name)',
- read_op = 'ChannelUtils.readBucketList(bb, length - MINIMUM_LENGTH)',
- write_op = 'ChannelUtils.writeList(this, $name)')
-port_desc_list = JType('List<OFPhysicalPort>', size='ChannelUtils.calcListSize($name)',
- read_op = 'ChannelUtils.readPhysicalPortList(bb, length - MINIMUM_LENGTH)',
- write_op = 'ChannelUtils.writeList(this, $name)')
-port_desc = JType('OFPhysicalPort', size='$name.getLength()',
- read_op = 'ChannelUtils.readPhysicalPort(bb)',
- write_op = 'ChannelUtils.write(this, $name)')
-packet_queue_list = JType('List<OFPacketQueue>', size='ChannelUtils.calcListSize($name)',
- read_op = 'ChannelUtils.readPacketQueueList(bb, length - MINIMUM_LENGTH)',
- write_op = 'ChannelUtils.writeList(this, $name)')
-octets = JType('byte[]', size="length - MINIMUM_LENGTH",
- read_op = 'ChannelUtils.readBytes(bb, length - MINIMUM_LENGTH)',
- write_op = 'ChannelUtils.writeBytes(bb, this.$name)')
-of_match = JType('Match', size="$name.getLength()",
- read_op = 'ChannelUtils.readOFMatch(bb)',
- write_op = 'ChannelUtils.writeOFMatch(this, $name)')
-flow_mod_cmd = JType('OFFlowModCmd', size="$name.getLength()",
- read_op = 'ChannelUtils.readOFFlowModCmd(bb)',
- write_op = 'ChannelUtils.writeOFFlowModCmd(this, $name)')
-mac_addr = JType('MacAddress', 'byte[]', size=6,
- read_op = 'MacAddress.readFrom(bb)',
- write_op = 'ChannelUtils.writeBytes(bb, $name)')
-bsn_interface_list = JType("List<OFBsnInterface>",
- read_op = 'ChannelUtils.readBsnInterfaceList(bb)',
- write_op = 'ChannelUtils.writeBsnInterfaceList(bb)'
- )
-meter_band_list = JType("List<OFMeterBand>",
- read_op = 'ChannelUtils.readMeterBandList(bb)',
- write_op = 'ChannelUtils.writeMeterBandList(bb, $name)'
- )
-
-
-
-
-
-default_mtype_to_jtype_convert_map = {
- 'uint8_t' : u8,
- 'uint16_t' : u16,
- 'uint32_t' : u32,
- 'uint64_t' : u64,
- 'uint8_t[1]' : one_byte_array,
- 'uint8_t[2]' : two_byte_array,
- 'uint8_t[3]' : three_byte_array,
- 'uint8_t[4]' : four_byte_array,
- 'uint8_t[5]' : five_byte_array,
- 'uint8_t[6]' : six_byte_array,
- 'uint8_t[7]' : seven_byte_array,
- 'of_port_no_t' : of_port,
- 'of_list_action_t' : actions_list,
- 'of_list_instruction_t' : instructions_list,
- 'of_list_bucket_t': buckets_list,
- 'of_list_port_desc_t' : port_desc_list,
- 'of_list_packet_queue_t' : packet_queue_list,
- 'of_octets_t' : octets,
- 'of_match_t': of_match,
- 'of_fm_cmd_t': flow_mod_cmd,
- 'of_mac_addr_t': mac_addr,
- 'of_port_desc_t': port_desc,
- 'of_list_bsn_interface_t': bsn_interface_list,
- 'of_list_hello_elem_t': hello_elem_list,
- 'of_list_meter_band_t': meter_band_list
- }
-
-## This is where we drop in special case handling for certain types
-exceptions = {
- 'OFPacketIn': {
- 'data' : octets
- },
- }
-
-
-def convert_to_jtype(obj_name, field_name, c_type):
- """ Convert from a C type ("uint_32") to a java type ("U32")
- and return a JType object with the size, internal type, and marshalling functions"""
- if obj_name in exceptions and field_name in exceptions[obj_name]:
- return exceptions[obj_name][field_name]
- elif c_type in default_mtype_to_jtype_convert_map:
- return default_mtype_to_jtype_convert_map[c_type]
- else:
- print "WARN: Couldn't find java type conversion for '%s' in %s:%s" % (c_type, obj_name, field_name)
- jtype = name_c_to_caps_camel(c_type) # not sure... try to fake it
- return JType(jtype)
-
-
-def mkdir_p(path):
- """ Emulates `mkdir -p` """
- try:
- os.makedirs(path)
- except OSError as exc: # Python >2.5
- if exc.errno == errno.EEXIST:
- pass
- else: raise
-
-def copy_file_with_boiler_plate(src_name, dst_name, with_boiler=True):
- with open("java_gen/pre-written/%s" % src_name, "r") as src:
- with open(dst_name, "w") as dst:
- if with_boiler:
- print_boiler_plate(os.path.basename(dst_name), dst)
- dst.writelines(src.readlines())
-
-def frob(s, **kwargs):
- """ Step through string s and for each key in kwargs,
- replace $key with kwargs[key] in s.
- """
- for k,v in kwargs.iteritems():
- s = s.replace('$%s' % k, v)
- return s
-
-def copy_prewrite_tree(basedir):
- """ Recursively copy the directory structure from ./java_gen/pre-write
- into $basedir"""
- print "Copying pre-written files into %s" % basedir
-# subprocess.call("cd java_gen/pre-written && tar cpf - . | ( cd ../../%s && tar xvpf - )" % basedir,
-# shell=True)
diff --git a/java_gen/msgs.py b/java_gen/msgs.py
deleted file mode 100644
index 3cdef2c..0000000
--- a/java_gen/msgs.py
+++ /dev/null
@@ -1,55 +0,0 @@
-import of_g
-import os
-import pdb
-import re
-
-import loxi_front_end.type_maps as type_maps
-import loxi_utils.loxi_utils as utils
-import py_gen.util as py_utils
-
-import java_gen.java_utils as java_utils
-from java_gen.java_model import *
-ignore_fields = ['version', 'xid', 'length', 'type' ]
-
-protected_fields = ['version', 'length']
-
-
-templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
-
-def render_template(out, name, **context):
- prefix = '//::(?=[ \t]|$)'
- utils.render_template(out, name, [templates_dir], context, prefix=prefix)
-
-def create_message_interfaces(message_names, basedir):
- """ Create the base interfaces for OFMessages"""
- for msg_name in message_names:
- msg = JavaOFMessage(msg_name)
-
- filename = os.path.join(basedir, "%s.java" % msg.interface_name)
- dirname = os.path.dirname(filename)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
-
- with open(filename, "w") as f:
- render_template(f, "message_interface.java", msg=msg)
-
-def create_of_type_enum(message_names, basedir):
- all_versions = [ JavaOFVersion(v) for v in of_g.target_version_list ]
- messages = sorted(filter(lambda msg: not msg.is_virtual and not msg.is_extension, [ JavaOFMessage(msg_name) for msg_name in message_names ]), key=lambda msg: msg.wire_type(all_versions[-1]))
- filename = os.path.join(basedir, "../types/OFType.java")
- dirname = os.path.dirname(filename)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
- with open(filename, "w") as f:
- render_template(f, "of_type.java", all_messages=messages, all_versions = all_versions)
-
-def create_message_by_version(message_names, basedir):
- """ Create the OF Messages for each version that implement the above interfaces"""
- for msg_name in message_names:
- msg = JavaOFMessage(msg_name)
-
- for version in msg.all_versions():
- filename = os.path.join(basedir, "%s.java" % msg.class_name_for_version(version))
- with open(filename, "w") as f:
- render_template(f, "message_class.java", msg=msg, version=version,
- impl_class=msg.class_name_for_version(version))
diff --git a/java_gen/pre-written/.classpath b/java_gen/pre-written/.classpath
new file mode 100644
index 0000000..b6bc6ad
--- /dev/null
+++ b/java_gen/pre-written/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="lib" path="lib/netty-3.2.6.Final.jar"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/java_gen/pre-written/.project b/java_gen/pre-written/.project
new file mode 100644
index 0000000..b347bd6
--- /dev/null
+++ b/java_gen/pre-written/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>openflowj-loxi</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/java_gen/pre-written/lib/.gitignore b/java_gen/pre-written/lib/.gitignore
deleted file mode 100644
index b4cb1f8..0000000
--- a/java_gen/pre-written/lib/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-netty-3.2.6.Final.jar
diff --git a/java_gen/pre-written/pom.xml b/java_gen/pre-written/pom.xml
new file mode 100644
index 0000000..d01d797
--- /dev/null
+++ b/java_gen/pre-written/pom.xml
@@ -0,0 +1,55 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.openflow</groupId>
+ <artifactId>openflowj</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>Loxi-Generated OpenFlow/J</name>
+ <url>http://www.projectfloodlight.org/projects/</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.netty</groupId>
+ <artifactId>netty</artifactId>
+ <version>3.2.9.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>14.0.1</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.8</version>
+ <executions>
+ <execution>
+ <phase>generate-sources</phase>
+ <goals><goal>add-source</goal></goals>
+ <configuration>
+ <sources>
+ <source>../../java_gen/pre-written/src/main/java/</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+</plugins>
+</build>
+</project>
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFAbstractMessage.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFAbstractMessage.java
deleted file mode 100644
index bc2218f..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFAbstractMessage.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Copyright 2013, Big Switch Networks, Inc.
- *
- * LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
- * the following special exception:
- *
- * LOXI Exception
- *
- * As a special exception to the terms of the EPL, you may distribute libraries
- * generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
- * that copyright and licensing notices generated by LoxiGen are not altered or removed
- * from the LoxiGen Libraries and the notice provided below is (i) included in
- * the LoxiGen Libraries, if distributed in source code form and (ii) included in any
- * documentation for the LoxiGen Libraries, if distributed in binary form.
- *
- * Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
- *
- * You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
- * a copy of the EPL at:
- *
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * EPL for the specific language governing permissions and limitations
- * under the EPL.
- */
-package org.openflow.protocol;
-
-/**
- * The base interface for all OpenFlow message objects
- */
-
-import org.openflow.types.OFType;
-
-abstract public class OFAbstractMessage implements OFObject {
- private final OFVersion version;
- private final OFType type;
- private int xid;
-
- public static int MINIMUM_SIZE = 8;
-
- public OFAbstractMessage(final OFVersion version, final OFType type) {
- this.version = version;
- this.type = type;
- }
-
- /**
- * Return the wire format version of this message, e.g., 0x01
- */
- OFVersion getVersion() {
- return version;
- }
-
- /**
- * @return the transction ID for this message
- */
- int getXid() {
- return xid;
- }
-
- /**
- * @param newXid
- * Set this transaction ID for this message
- */
- void setXid(final int xid) {
- this.xid = xid;
- }
-
- /**
- * The type that is returned here is agnostic to the underlying wire format
- *
- * @return the type of OpenFlow message.
- */
- OFType getType() {
- return type;
- }
-
- @Override
- public int getLength() {
- return MINIMUM_SIZE;
- }
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFBsnVportQInQT.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFBsnVportQInQT.java
new file mode 100644
index 0000000..c5b884e
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFBsnVportQInQT.java
@@ -0,0 +1,5 @@
+package org.openflow.protocol;
+
+public class OFBsnVportQInQT {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFFlowMod.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFFlowMod.java
new file mode 100644
index 0000000..06d8049
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFFlowMod.java
@@ -0,0 +1,8 @@
+package org.openflow.protocol;
+
+public interface OFFlowMod extends OFMessage {
+
+ public interface Builder extends OFMessage.Builder {
+
+ }
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMatchBmap.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMatchBmap.java
new file mode 100644
index 0000000..6e4dc5b
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMatchBmap.java
@@ -0,0 +1,5 @@
+package org.openflow.protocol;
+
+public class OFMatchBmap {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java
index 4f31741..c1e4456 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessage.java
@@ -1,13 +1,13 @@
package org.openflow.protocol;
-import org.openflow.types.OFType;
-
public interface OFMessage {
int getXid();
- boolean isXidSet();
-
OFType getType();
OFVersion getVersion();
+
+ interface Builder {
+
+ }
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageReader.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageReader.java
index 24c3314..3f34d9b 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageReader.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageReader.java
@@ -3,6 +3,6 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.openflow.exceptions.OFParseError;
-public interface OFMessageReader<T extends OFMessage> {
+public interface OFMessageReader<T> {
T readFrom(ChannelBuffer bb) throws OFParseError;
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageWriter.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageWriter.java
new file mode 100644
index 0000000..84e5507
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFMessageWriter.java
@@ -0,0 +1,8 @@
+package org.openflow.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.exceptions.OFParseError;
+
+public interface OFMessageWriter<T> {
+ public int write(ChannelBuffer bb, T message) throws OFParseError;
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java
index 21a4607..4a7557f 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFObject.java
@@ -1,5 +1,7 @@
package org.openflow.protocol;
+import org.jboss.netty.buffer.ChannelBuffer;
+
/**
* Base interface of all OpenFlow objects (e.g., messages, actions, stats, etc.)
*
@@ -10,26 +12,8 @@
* malformed packets, for example, for negative testing.
*/
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortWrite;
public interface OFObject {
- /**
- * Return a number equal or greater than zero (and currently in OF less than
- * 65536)
- *
- * @return the number of bytes this object will represent on the wire
- */
- public int getLength();
-
- /**
- * Automatically calculate any lengths and write an openflow object into the
- * byte buffer.
- *
- * @param bb
- * A valid byte buffer with sufficient capacity to hold this
- * object/
- */
- public void writeTo(ChannelBuffer bb) throws OFParseError, OFShortWrite;
+ void writeTo(ChannelBuffer bb);
+ int getLength();
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFTableFeature.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFTableFeature.java
new file mode 100644
index 0000000..114f638
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFTableFeature.java
@@ -0,0 +1,5 @@
+package org.openflow.protocol;
+
+public class OFTableFeature {
+ // FIXME implement
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFVersion.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFVersion.java
index afc0393..7241647 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/OFVersion.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/OFVersion.java
@@ -3,7 +3,7 @@
public enum OFVersion {
OF_10(1), OF_11(2), OF_12(3), OF_13(4);
- private final int wireVersion;
+ public final int wireVersion;
OFVersion(final int wireVersion) {
this.wireVersion = wireVersion;
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/Wildcards.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/Wildcards.java
new file mode 100644
index 0000000..25b2c21
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/Wildcards.java
@@ -0,0 +1,5 @@
+package org.openflow.protocol;
+
+public class Wildcards {
+
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/XidGenerator.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/XidGenerator.java
new file mode 100644
index 0000000..0819ac2
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/XidGenerator.java
@@ -0,0 +1,5 @@
+package org.openflow.protocol;
+
+public interface XidGenerator {
+ int nextXid();
+}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/actions/OFAction.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/actions/OFAction.java
deleted file mode 100644
index f01f8fe..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/actions/OFAction.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.openflow.protocol.actions;
-
-import org.openflow.protocol.OFObject;
-
-public interface OFAction extends OFObject {
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/instructions/OFInstruction.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/instructions/OFInstruction.java
deleted file mode 100644
index 8af305c..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/instructions/OFInstruction.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.openflow.protocol.instructions;
-
-import org.openflow.protocol.OFObject;
-
-public interface OFInstruction extends OFObject {
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
index 19ced8f..f00e1b4 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchBuilderVer10.java
@@ -1,8 +1,6 @@
package org.openflow.protocol.match;
import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortWrite;
import org.openflow.protocol.types.IpDscp;
import org.openflow.types.EthType;
import org.openflow.types.IPv4;
@@ -157,7 +155,7 @@
}
@Override
- public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+ public void writeTo(final ChannelBuffer bb) {
// TODO Auto-generated method stub
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
index b4eb8cf..0583d6f 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv4.java
@@ -1,9 +1,6 @@
package org.openflow.types;
import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortRead;
-import org.openflow.exceptions.OFShortWrite;
import org.openflow.protocol.OFObject;
/**
@@ -85,12 +82,12 @@
return LENGTH;
}
- public static IPv4 readFrom(final ChannelBuffer bb) throws OFParseError, OFShortRead {
+ public static IPv4 readFrom(final ChannelBuffer bb) {
return IPv4.of(bb.readInt());
}
@Override
- public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+ public void writeTo(final ChannelBuffer bb) {
bb.writeInt(rawValue);
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
index 5f51665..19002d9 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/IPv6.java
@@ -4,8 +4,6 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortRead;
-import org.openflow.exceptions.OFShortWrite;
import org.openflow.protocol.OFObject;
/**
@@ -161,12 +159,12 @@
return LENGTH;
}
- public static IPv6 readFrom(final ChannelBuffer bb) throws OFParseError, OFShortRead {
+ public static IPv6 readFrom(final ChannelBuffer bb) throws OFParseError {
return IPv6.of(bb.readLong(), bb.readLong());
}
@Override
- public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+ public void writeTo(final ChannelBuffer bb) {
bb.writeLong(raw1);
bb.writeLong(raw2);
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
index 4ce19ab..8806bb3 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/MacAddress.java
@@ -2,7 +2,6 @@
import org.jboss.netty.buffer.ChannelBuffer;
import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortWrite;
import org.openflow.protocol.OFObject;
import org.openflow.util.HexString;
@@ -84,7 +83,7 @@
}
@Override
- public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
+ public void writeTo(final ChannelBuffer bb) {
bb.writeInt((int) (rawValue >> 16));
bb.writeShort((int) rawValue & 0xFFFF);
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFBsnInterface.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFBsnInterface.java
deleted file mode 100644
index d0afb56..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFBsnInterface.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.openflow.types;
-
-public interface OFBsnInterface {
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFBucket.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFBucket.java
deleted file mode 100644
index 47b403b..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFBucket.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.openflow.types;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortWrite;
-import org.openflow.protocol.OFObject;
-
-public class OFBucket implements OFObject {
-
- @Override
- public int getLength() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
- // TODO Auto-generated method stub
-
- }
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFPacketQueue.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFPacketQueue.java
deleted file mode 100644
index d74906f..0000000
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFPacketQueue.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.openflow.types;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortWrite;
-import org.openflow.protocol.OFObject;
-
-public class OFPacketQueue implements OFObject {
-
- @Override
- public int getLength() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public void writeTo(final ChannelBuffer bb) throws OFParseError, OFShortWrite {
- // TODO Auto-generated method stub
-
- }
-
-}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/U64.java b/java_gen/pre-written/src/main/java/org/openflow/types/U64.java
index 211c3ea..c0cd475 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/U64.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/U64.java
@@ -20,8 +20,7 @@
import java.math.BigInteger;
public class U64 {
- private final static BigInteger TWO_POWER_64 = BigInteger.valueOf(Long.MAX_VALUE).add(
- BigInteger.valueOf(1));
+ private static final long UNSIGNED_MASK = 0x7fffffffffffffffL;
private final long raw;
@@ -38,8 +37,11 @@
}
public BigInteger getBigInteger() {
- return raw >= 0 ? BigInteger.valueOf(raw) : TWO_POWER_64.add(BigInteger
- .valueOf(raw));
+ BigInteger bigInt = BigInteger.valueOf(raw & UNSIGNED_MASK);
+ if (raw < 0) {
+ bigInt = bigInt.setBit(Long.SIZE - 1);
+ }
+ return bigInt;
}
@Override
@@ -47,8 +49,12 @@
return getBigInteger().toString();
}
- public static BigInteger f(final long i) {
- return new BigInteger(Long.toBinaryString(i), 2);
+ public static BigInteger f(final long value) {
+ BigInteger bigInt = BigInteger.valueOf(value & UNSIGNED_MASK);
+ if (value < 0) {
+ bigInt = bigInt.setBit(Long.SIZE - 1);
+ }
+ return bigInt;
}
public static long t(final BigInteger l) {
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
index e8eeebd..dab6ff2 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/util/ChannelUtils.java
@@ -3,17 +3,32 @@
import java.util.List;
import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.actions.OFAction;
-import org.openflow.protocol.instructions.OFInstruction;
+import org.openflow.protocol.OFBsnInterface;
+import org.openflow.protocol.OFBsnVportQInQ;
+import org.openflow.protocol.OFBsnVportQInQT;
+import org.openflow.protocol.OFBucket;
+import org.openflow.protocol.OFFlowStatsEntry;
+import org.openflow.protocol.OFGroupDescStatsEntry;
+import org.openflow.protocol.OFGroupStatsEntry;
+import org.openflow.protocol.OFHelloElem;
+import org.openflow.protocol.OFMeterFeatures;
+import org.openflow.protocol.OFMeterStats;
+import org.openflow.protocol.OFPacketQueue;
+import org.openflow.protocol.OFPortStatsEntry;
+import org.openflow.protocol.OFQueueStatsEntry;
+import org.openflow.protocol.OFTableFeature;
+import org.openflow.protocol.OFTableFeatures;
+import org.openflow.protocol.OFTableStatsEntry;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.instruction.OFInstruction;
import org.openflow.protocol.match.Match;
-import org.openflow.types.OFBsnInterface;
-import org.openflow.types.OFBucket;
import org.openflow.types.OFFlowModCmd;
import org.openflow.types.OFHelloElement;
import org.openflow.types.OFMeterBand;
-import org.openflow.types.OFPacketQueue;
import org.openflow.types.OFPhysicalPort;
+import com.google.common.base.Charsets;
+
/**
* Collection of helper functions for reading and writing into ChannelBuffers
*
@@ -90,4 +105,212 @@
return null;
}
+ public static void writeOFMatch(ChannelBuffer bb, Match match) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void writeList(ChannelBuffer bb, List<?> ports) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void writeOFFlowModCmd(ChannelBuffer bb, OFFlowModCmd command) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static String readFixedLengthString(ChannelBuffer bb, int length) {
+ byte[] dst = new byte[length];
+ bb.readBytes(dst, 0, length);
+ return new String(dst, Charsets.US_ASCII);
+ }
+
+ public static void writeFixedLengthString(ChannelBuffer bb, String string, int length) {
+ int l = string.length();
+ if(l > length) {
+ throw new IllegalArgumentException("Error writing string: length="+l+" > max Length="+length);
+ }
+ bb.writeBytes(string.getBytes(Charsets.US_ASCII));
+ if(l < length) {
+ bb.writeZero(length - l);
+ }
+ }
+
+ public static void writeBsnInterfaceList(ChannelBuffer bb, List<OFBsnInterface> interfaces) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void writeTableFeatureList(ChannelBuffer bb,
+ List<OFTableFeature> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void writeBsnInterface(ChannelBuffer bb,
+ List<OFBsnInterface> interfaces) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void writeFlowStatsEntry(ChannelBuffer bb,
+ List<OFFlowStatsEntry> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFFlowStatsEntry> readFlowStatsEntry(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeTableStatsEntryList(ChannelBuffer bb,
+ List<OFTableStatsEntry> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFTableStatsEntry> readTableStatsEntryList(
+ ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static List<OFFlowStatsEntry> readFlowStatsEntryList(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeFlowStatsEntryList(ChannelBuffer bb,
+ List<OFFlowStatsEntry> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void writeGroupDescStatsEntryList(ChannelBuffer bb,
+ List<OFGroupDescStatsEntry> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFGroupDescStatsEntry> readGroupDescStatsEntryList(
+ ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeOFBsnVportQInQT(ChannelBuffer bb,
+ OFBsnVportQInQT vport) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void writeMeterBandList(ChannelBuffer bb,
+ List<OFMeterBand> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static int writeActionsList(ChannelBuffer bb, List<OFAction> actions) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public static OFBsnVportQInQ readOFBsnVportQInQ(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writePortStatsEntryList(ChannelBuffer bb,
+ List<OFPortStatsEntry> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static void write(ChannelBuffer bb, OFPhysicalPort desc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFPortStatsEntry> readPortStatsEntryList(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeOFBsnVportQInQ(ChannelBuffer bb,
+ OFBsnVportQInQ vport) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFHelloElem> readHelloElemList(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeHelloElemList(ChannelBuffer bb,
+ List<OFHelloElem> elements) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFGroupStatsEntry> readGroupStatsEntryList(
+ ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeGroupStatsEntryList(ChannelBuffer bb,
+ List<OFGroupStatsEntry> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFQueueStatsEntry> readQueueStatsEntryList(
+ ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeQueueStatsEntryList(ChannelBuffer bb,
+ List<OFQueueStatsEntry> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static OFMeterFeatures readOFMeterFeatures(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeOFMeterFeatures(ChannelBuffer bb,
+ OFMeterFeatures features) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFMeterStats> readMeterStatsList(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeMeterStatsList(ChannelBuffer bb,
+ List<OFMeterStats> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public static List<OFTableFeatures> readTableFeaturesList(ChannelBuffer bb) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static void writeTableFeaturesList(ChannelBuffer bb,
+ List<OFTableFeatures> entries) {
+ // TODO Auto-generated method stub
+
+ }
+
+
}
diff --git a/java_gen/pre-written/src/main/java/org/openflow/util/LengthCountingPseudoChannelBuffer.java b/java_gen/pre-written/src/main/java/org/openflow/util/LengthCountingPseudoChannelBuffer.java
new file mode 100644
index 0000000..bd0adce
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/openflow/util/LengthCountingPseudoChannelBuffer.java
@@ -0,0 +1,673 @@
+package org.openflow.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.ScatteringByteChannel;
+import java.nio.charset.Charset;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBufferFactory;
+import org.jboss.netty.buffer.ChannelBufferIndexFinder;
+
+public class LengthCountingPseudoChannelBuffer implements ChannelBuffer {
+
+ int writerIndex = 0;
+ private int markedWriterIndex;
+
+ @Override
+ public ChannelBufferFactory factory() {
+ return null;
+ }
+
+ @Override
+ public int capacity() {
+ return Integer.MAX_VALUE;
+ }
+
+ @Override
+ public ByteOrder order() {
+ return ByteOrder.BIG_ENDIAN;
+ }
+
+ @Override
+ public boolean isDirect() {
+ return true;
+ }
+
+ @Override
+ public int readerIndex() {
+ return 0;
+ }
+
+ @Override
+ public void readerIndex(int readerIndex) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int writerIndex() {
+ return writerIndex;
+ }
+
+ @Override
+ public void writerIndex(int writerIndex) {
+ this.writerIndex = writerIndex;
+ }
+
+ @Override
+ public void setIndex(int readerIndex, int writerIndex) {
+ if(readerIndex != 0)
+ throw new UnsupportedOperationException();
+ this.writerIndex = writerIndex;
+ }
+
+ @Override
+ public int readableBytes() {
+ return writerIndex;
+ }
+
+ @Override
+ public int writableBytes() {
+ return Integer.MAX_VALUE - writerIndex;
+ }
+
+ @Override
+ public boolean readable() {
+ return writerIndex > 0;
+ }
+
+ @Override
+ public boolean writable() {
+ return writerIndex < Integer.MAX_VALUE;
+ }
+
+ @Override
+ public void clear() {
+ writerIndex = 0;
+
+ }
+
+ @Override
+ public void markReaderIndex() {
+ }
+
+ @Override
+ public void resetReaderIndex() {
+ }
+
+ @Override
+ public void markWriterIndex() {
+ markedWriterIndex = writerIndex;
+ }
+
+ @Override
+ public void resetWriterIndex() {
+ writerIndex = markedWriterIndex;
+ }
+
+ @Override
+ public void discardReadBytes() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void ensureWritableBytes(int writableBytes) {
+ if(!((Integer.MAX_VALUE - writableBytes) > writerIndex))
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public byte getByte(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public short getUnsignedByte(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public short getShort(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getUnsignedShort(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getMedium(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getUnsignedMedium(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getInt(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getUnsignedInt(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getLong(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public char getChar(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public float getFloat(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public double getDouble(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getBytes(int index, ChannelBuffer dst) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getBytes(int index, ChannelBuffer dst, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getBytes(int index, ChannelBuffer dst, int dstIndex, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getBytes(int index, byte[] dst) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getBytes(int index, byte[] dst, int dstIndex, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getBytes(int index, ByteBuffer dst) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getBytes(int index, OutputStream out, int length)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getBytes(int index, GatheringByteChannel out, int length)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setByte(int index, int value) {
+ }
+
+ @Override
+ public void setShort(int index, int value) {
+ }
+
+ @Override
+ public void setMedium(int index, int value) {
+ }
+
+ @Override
+ public void setInt(int index, int value) {
+ }
+
+ @Override
+ public void setLong(int index, long value) {
+ }
+
+ @Override
+ public void setChar(int index, int value) {
+ }
+
+ @Override
+ public void setFloat(int index, float value) {
+ }
+
+ @Override
+ public void setDouble(int index, double value) {
+ }
+
+ @Override
+ public void setBytes(int index, ChannelBuffer src) {
+ }
+
+ @Override
+ public void setBytes(int index, ChannelBuffer src, int length) {
+ }
+
+ @Override
+ public void setBytes(int index, ChannelBuffer src, int srcIndex, int length) {
+ }
+
+ @Override
+ public void setBytes(int index, byte[] src) {
+ }
+
+ @Override
+ public void setBytes(int index, byte[] src, int srcIndex, int length) {
+ }
+
+ @Override
+ public void setBytes(int index, ByteBuffer src) {
+
+ }
+
+ @Override
+ public int setBytes(int index, InputStream in, int length)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int setBytes(int index, ScatteringByteChannel in, int length)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setZero(int index, int length) {
+ }
+
+ @Override
+ public byte readByte() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public short readUnsignedByte() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public short readShort() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int readUnsignedShort() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int readMedium() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int readUnsignedMedium() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int readInt() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long readUnsignedInt() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long readLong() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public char readChar() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public float readFloat() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public double readDouble() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ChannelBuffer readBytes(int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public ChannelBuffer readBytes(ChannelBufferIndexFinder indexFinder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ChannelBuffer readSlice(int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public
+ ChannelBuffer readSlice(ChannelBufferIndexFinder indexFinder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readBytes(ChannelBuffer dst) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readBytes(ChannelBuffer dst, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readBytes(byte[] dst) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readBytes(byte[] dst, int dstIndex, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readBytes(ByteBuffer dst) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readBytes(OutputStream out, int length) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int readBytes(GatheringByteChannel out, int length)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void skipBytes(int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @Deprecated
+ public int skipBytes(ChannelBufferIndexFinder indexFinder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void writeByte(int value) {
+ writerIndex++;
+ }
+
+ @Override
+ public void writeShort(int value) {
+ writerIndex += 2;
+}
+
+@Override
+public void writeMedium(int value) {
+ writerIndex += 3;
+}
+
+@Override
+public void writeInt(int value) {
+ writerIndex += 4;
+}
+
+@Override
+public void writeLong(long value) {
+ writerIndex += 8;
+}
+
+
+ @Override
+ public void writeChar(int value) {
+ writeShort(value);
+ }
+
+ @Override
+ public void writeFloat(float value) {
+ writeInt(Float.floatToIntBits(value));
+ }
+
+ @Override
+ public void writeDouble(double value) {
+ writeLong(Double.doubleToLongBits(value));
+
+ }
+
+ @Override
+ public void writeBytes(ChannelBuffer src) {
+ writerIndex += src.readableBytes();
+
+ }
+
+ @Override
+ public void writeBytes(ChannelBuffer src, int length) {
+ writerIndex += src.readableBytes();
+
+ }
+
+ @Override
+ public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
+ writerIndex += length;
+ }
+
+ @Override
+ public void writeBytes(byte[] src) {
+ writerIndex += src.length;
+
+ }
+
+ @Override
+ public void writeBytes(byte[] src, int srcIndex, int length) {
+ writerIndex += length;
+ }
+
+ @Override
+ public void writeBytes(ByteBuffer src) {
+ writerIndex += src.remaining();
+
+ }
+
+ @Override
+ public int writeBytes(InputStream in, int length) throws IOException {
+ writerIndex += length;
+ return length;
+ }
+
+ @Override
+ public int writeBytes(ScatteringByteChannel in, int length)
+ throws IOException {
+ writerIndex += length;
+ return length;
+ }
+
+ @Override
+ public void writeZero(int length) {
+ writerIndex += length;
+
+ }
+
+ @Override
+ public int indexOf(int fromIndex, int toIndex, byte value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int indexOf(int fromIndex, int toIndex,
+ ChannelBufferIndexFinder indexFinder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int bytesBefore(byte value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int bytesBefore(ChannelBufferIndexFinder indexFinder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int bytesBefore(int length, byte value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int bytesBefore(int length, ChannelBufferIndexFinder indexFinder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int bytesBefore(int index, int length, byte value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int bytesBefore(int index, int length,
+ ChannelBufferIndexFinder indexFinder) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ChannelBuffer copy() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ChannelBuffer copy(int index, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ChannelBuffer slice() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ChannelBuffer slice(int index, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ChannelBuffer duplicate() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ByteBuffer toByteBuffer() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ByteBuffer toByteBuffer(int index, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ByteBuffer[] toByteBuffers() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ByteBuffer[] toByteBuffers(int index, int length) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] array() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int arrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String toString(Charset charset) {
+ return "LengthCountingPseudoChannelBuffer(length="+writerIndex+")";
+ }
+
+ @Override
+ public String toString(int index, int length, Charset charset) {
+ return toString();
+ }
+
+ @Override
+ @Deprecated
+ public String toString(String charsetName) {
+ return toString();
+ }
+
+ @Override
+ @Deprecated
+ public String toString(String charsetName,
+ ChannelBufferIndexFinder terminatorFinder) {
+ return toString();
+ }
+
+ @Override
+ @Deprecated
+ public String toString(int index, int length, String charsetName) {
+ return toString();
+ }
+
+ @Override
+ @Deprecated
+ public
+ String toString(int index, int length, String charsetName,
+ ChannelBufferIndexFinder terminatorFinder) {
+ return toString();
+ }
+
+ @Override
+ public int compareTo(ChannelBuffer buffer) {
+ throw new UnsupportedOperationException();
+
+ }
+
+}
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/U64Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/U64Test.java
new file mode 100644
index 0000000..16d3d3e
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/U64Test.java
@@ -0,0 +1,26 @@
+package org.openflow.types;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigInteger;
+
+import org.junit.Test;
+
+public class U64Test {
+
+ @Test
+ public void testPositiveRaws() {
+ for(long positive: new long[] { 0, 1, 100, Long.MAX_VALUE }) {
+ assertEquals(positive, U64.of(positive).getValue());
+ assertEquals(BigInteger.valueOf(positive), U64.of(positive).getBigInteger());
+ }
+ }
+
+ @Test
+ public void testNegativeRaws() {
+ long minus_1 = 0xFFffFFffFFffFFffL;
+ assertEquals(minus_1, U64.of(minus_1).getValue());
+ assertEquals(new BigInteger("FFffFFffFFffFFff", 16), U64.of(minus_1).getBigInteger());
+ assertEquals(new BigInteger("18446744073709551615"), U64.of(minus_1).getBigInteger());
+ }
+}
diff --git a/java_gen/templates/_field_accessors.java b/java_gen/templates/_field_accessors.java
new file mode 100644
index 0000000..e8afe47
--- /dev/null
+++ b/java_gen/templates/_field_accessors.java
@@ -0,0 +1,33 @@
+//:: for prop in msg.interface.members:
+ @Override
+ public ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop in msg.members else "throws UnsupportedOperationException"} {
+//:: if prop in msg.members:
+//:: version_prop = msg.get_member(prop.name)
+//:: if version_prop.is_fixed_value:
+ return ${version_prop.enum_value};
+//:: elif version_prop.is_length_value:
+ // FIXME: Hacky and inperformant way to determine a message length. Should be replaced with something better
+ ChannelBuffer c = new LengthCountingPseudoChannelBuffer();
+ WRITER.write(c, ${ "this" if not builder else "({0}) this.getMessage()".format(msg.name) });
+ return c.writerIndex();
+//:: else:
+ return ${version_prop.name};
+//:: #endif
+//:: else:
+ throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
+//:: #endif
+ }
+
+//:: if generate_setters and prop.is_writeable:
+ @Override
+ public ${msg.interface.name}.Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if prop in msg.members else " throws UnsupportedOperationException"} {
+//:: if prop in msg.members:
+ this.${prop.name} = ${prop.name};
+ this.${prop.name}Set = true;
+ return this;
+//:: else:
+ throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
+//:: #endif
+ }
+//:: #endif
+//:: #endfor
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
new file mode 100644
index 0000000..7700546
--- /dev/null
+++ b/java_gen/templates/_imports.java
@@ -0,0 +1,12 @@
+import java.util.Collections;
+import java.util.List;
+import org.openflow.protocol.*;
+import org.openflow.protocol.action.*;
+import org.openflow.protocol.instruction.*;
+import org.openflow.protocol.match.*;
+import org.openflow.protocol.oxm.*;
+import org.openflow.types.*;
+import org.openflow.types.*;
+import org.openflow.util.*;
+import org.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
diff --git a/java_gen/templates/of_type.java b/java_gen/templates/const.java
similarity index 74%
rename from java_gen/templates/of_type.java
rename to java_gen/templates/const.java
index 951a648..7870529 100644
--- a/java_gen/templates/of_type.java
+++ b/java_gen/templates/const.java
@@ -31,21 +31,22 @@
//:: include('_autogen.java')
-package org.openflow.types;
+package ${package};
import org.openflow.protocol.OFVersion;
-public enum OFType {
-//:: for i, msg in enumerate(all_messages):
- ${msg.constant_name}(new byte[] { ${ ", ".join( [str(msg.wire_type(version)) for version in all_versions ]) } } )${ ", " if i < len(all_messages)-1 else ";" }
+public enum ${class_name} {
+//:: for i, entry in enumerate(enum.entries):
+//:: values = [ ("0x%x" % val) if val is not None else "-1" for val in entry.all_values(all_versions) ]
+ ${entry.name}(new int[] { ${ ", ".join( values) } } )${ ", " if i < len(enum.entries)-1 else ";" }
//:: #endfor
- byte[] wireTypes;
- OFType(byte[] wireTypes) {
- this.wireTypes = wireTypes;
+ private final int[] wireValues;
+ ${class_name}(int[] wireValues) {
+ this.wireValues = wireValues;
}
- public byte getWireType(OFVersion version) {
- return this.wireTypes[version.getWireVersion()];
+ public int getWireValue(OFVersion version) {
+ return this.wireValues[version.getWireVersion()];
}
}
diff --git a/java_gen/templates/message_class.java b/java_gen/templates/message_class.java
deleted file mode 100644
index 2b4801c..0000000
--- a/java_gen/templates/message_class.java
+++ /dev/null
@@ -1,258 +0,0 @@
-//:: # Copyright 2013, Big Switch Networks, Inc.
-//:: #
-//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
-//:: # the following special exception:
-//:: #
-//:: # LOXI Exception
-//:: #
-//:: # As a special exception to the terms of the EPL, you may distribute libraries
-//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
-//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
-//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
-//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
-//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
-//:: #
-//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
-//:: #
-//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
-//:: # a copy of the EPL at:
-//:: #
-//:: # http::: #www.eclipse.org/legal/epl-v10.html
-//:: #
-//:: # Unless required by applicable law or agreed to in writing, software
-//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-//:: # EPL for the specific language governing permissions and limitations
-//:: # under the EPL.
-//::
-//:: import itertools
-//:: import of_g
-//:: include('_copyright.java')
-
-//:: include('_autogen.java')
-
-package org.openflow.protocol;
-import java.util.Collections;
-import java.util.List;
-import org.openflow.protocol.actions.OFAction;
-import org.openflow.protocol.instructions.OFInstruction;
-import org.openflow.protocol.match.*;
-import org.openflow.types.*;
-import org.openflow.types.*;
-import org.openflow.util.*;
-import org.openflow.exceptions.*;
-import org.jboss.netty.buffer.ChannelBuffer;
-
-class ${impl_class} implements ${msg.interface_name} {
-//:: if msg.is_fixed_length(version):
- private static final int LENGTH = ${msg.min_length(version) };
-//:: else:
- private static final int MINIMUM_LENGTH = ${msg.min_length(version) };
-//:: #endif
-
-//:: for prop in msg.properties_for_version(version):
- private final static ${prop.java_type.public_type} ${prop.default_name} = ${prop.default_value};
-//:: #end
- private boolean xidSet;
- private final int xid;
-
- // OF message fields
-//:: for prop in msg.properties_for_version(version):
- private final ${prop.java_type.public_type} ${prop.name};
-//:: #endfor
-
- // Constructor
- ${impl_class}(${
- ", ".join(["int xid" ] + [ "%s %s" %(prop.java_type.public_type, prop.name) for prop in msg.properties_for_version(version) ])}) {
- this.xidSet = true;
- this.xid = xid;
-//:: for prop in msg.properties_for_version(version):
- this.${prop.name} = ${prop.name};
-//:: #endfor
- }
-
- ${impl_class}(${
- ", ".join("%s %s" %(prop.java_type.public_type, prop.name) for prop in msg.properties_for_version(version)) }) {
- this.xidSet = false;
- this.xid = 0;
-//:: for prop in msg.properties_for_version(version):
- this.${prop.name} = ${prop.name};
-//:: #endfor
- }
-
- @Override
- public int getXid() {
- return xid;
- }
-
- @Override
- public boolean isXidSet() {
- return xidSet;
- }
-
- @Override
- public OFType getType() {
- return OFType.${msg.constant_name};
- }
-
- @Override
- public OFVersion getVersion() {
- return OFVersion.${version.constant_version};
- }
-
- // Accessors for OF message fields
-//:: for prop in msg.all_properties():
- @Override
- public ${prop.java_type.public_type} get${prop.title_name}()${ "" if msg.property_in_version(prop, version) else "throws UnsupportedOperationException"} {
-//:: if msg.property_in_version(prop, version):
- return ${prop.name};
-//:: else:
- throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
-//:: #endif
- }
-//:: #endfor
-
- public ${msg.interface_name}.Builder createBuilder() {
- return new BuilderImplWithParent(this);
- }
-
- static class BuilderImplWithParent implements ${msg.interface_name}.Builder {
- final ${impl_class} parentMessage;
- private boolean xidSet;
- private int xid;
-
- // OF message fields
-//:: for prop in msg.properties_for_version(version):
- private boolean ${prop.name}Set;
- private ${prop.java_type.public_type} ${prop.name};
-//:: #endfor
-
- BuilderImplWithParent(${impl_class} parentMessage) {
- this.parentMessage = parentMessage;
- }
-
-//:: for prop in msg.all_properties():
- @Override
- public ${prop.java_type.public_type} get${prop.title_name}()${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
-//:: if msg.property_in_version(prop, version):
- return ${prop.name};
-//:: else:
- throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
-//:: #endif
- }
- @Override
- public ${msg.interface_name}.Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
-//:: if msg.property_in_version(prop, version):
- this.${prop.name} = ${prop.name};
- this.${prop.name}Set = true;
- return this;
-//:: else:
- throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
-//:: #endif
- }
-//:: #endfor
- @Override
- public ${msg.interface_name} getMessage() {
- if(this.xidSet) {
- return new ${impl_class}(
- ${",\n ".join(
- [ "xid" ] +
- [ "this.{0}Set ? this.{0} : parentMessage.{0}".format(prop.name)
- for prop in msg.properties_for_version(version)])}
- );
- } else {
- return new ${impl_class}(
- ${",\n ".join(
- [ "this.{0}Set ? this.{0} : parentMessage.{0}".format(prop.name)
- for prop in msg.properties_for_version(version)])}
- );
- }
- }
- }
-
- static class BuilderImpl implements ${msg.interface_name}.Builder {
- private boolean xidSet;
- private int xid;
-
- // OF message fields
-//:: for prop in msg.properties_for_version(version):
- private boolean ${prop.name}Set;
- private ${prop.java_type.public_type} ${prop.name};
-//:: #endfor
-
-//:: for prop in msg.all_properties():
- @Override
- public ${prop.java_type.public_type} get${prop.title_name}()${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
-//:: if msg.property_in_version(prop, version):
- return ${prop.name};
-//:: else:
- throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
-//:: #endif
- }
- @Override
- public ${msg.interface_name}.Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if msg.property_in_version(prop, version) else " throws UnsupportedOperationException"} {
-//:: if msg.property_in_version(prop, version):
- this.${prop.name} = ${prop.name};
- this.${prop.name}Set = true;
- return this;
-//:: else:
- throw new UnsupportedOperationException("Property ${prop.name} not supported in version #{version}");
-//:: #endif
- }
-//:: #endfor
- @Override
- public ${msg.interface_name} getMessage() {
- if(this.xidSet) {
- return new ${impl_class}(
- ${",\n ".join(
- [ "xid" ] +
- [ "this.{0}Set ? this.{0} : {1}.{2}".format(prop.name, impl_class, prop.default_name)
- for prop in msg.properties_for_version(version)])}
- );
- } else {
- return new ${impl_class}(
- ${",\n ".join(
- [ "this.{0}Set ? this.{0} : {1}.{2}".format(prop.name, impl_class, prop.default_name)
- for prop in msg.properties_for_version(version)])}
- );
- }
- }
- }
-
- final static Reader READER = new Reader();
- static class Reader implements OFMessageReader<${msg.interface_name}> {
- @Override
- public ${msg.interface_name} readFrom(ChannelBuffer bb) throws OFParseError {
- byte version = bb.readByte();
- if (version != (byte) ${version.int_version})
- throw new OFParseError("Wrong version: Expected=${version.int_version}, got="+version);
-
- byte type = bb.readByte();
- if(type != ${msg.wire_type(version)})
- throw new OFParseError("Wrong message type: Expected=${msg.constant_name}, got="+type);
-
- int length = bb.readUnsignedShort();
-//:: if msg.is_fixed_length(version):
- if(length != LENGTH)
- throw new OFParseError("Wrong message length: Expected="+LENGTH +", got="+length);
-//:: else:
- if(length < MINIMUM_LENGTH)
- throw new OFParseError("Insufficient message length: minimum length="+MINIMUM_LENGTH +", got="+length);
-//:: #endif
- int xid = bb.readInt();
-//:: for prop in msg.properties_for_version(version, skip_pads=False):
-//:: if prop.is_pad:
- // pad: ${prop.length} bytes
- bb.skipBytes(${prop.length});
-//:: else:
- ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version)};
-//:: #endif
-//:: #endfor
- return new ${impl_class}(
- ${",\n ".join(
- [ "xid" ] + [ prop.name for prop in msg.properties_for_version(version)])}
- );
- }
- }
-
-}
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
new file mode 100644
index 0000000..772858a
--- /dev/null
+++ b/java_gen/templates/of_class.java
@@ -0,0 +1,209 @@
+//:: # Copyright 2013, Big Switch Networks, Inc.
+//:: #
+//:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+//:: # the following special exception:
+//:: #
+//:: # LOXI Exception
+//:: #
+//:: # As a special exception to the terms of the EPL, you may distribute libraries
+//:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+//:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
+//:: # from the LoxiGen Libraries and the notice provided below is (i) included in
+//:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+//:: # documentation for the LoxiGen Libraries, if distributed in binary form.
+//:: #
+//:: # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+//:: #
+//:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+//:: # a copy of the EPL at:
+//:: #
+//:: # http::: #www.eclipse.org/legal/epl-v10.html
+//:: #
+//:: # Unless required by applicable law or agreed to in writing, software
+//:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+//:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+//:: # EPL for the specific language governing permissions and limitations
+//:: # under the EPL.
+//::
+//:: from loxi_ir import *
+//:: import itertools
+//:: import of_g
+//:: include('_copyright.java')
+
+//:: include('_autogen.java')
+
+package ${msg.package};
+
+//:: include("_imports.java", msg=msg)
+
+class ${impl_class} implements ${msg.interface.name} {
+ // version: ${version}
+ private final static byte WIRE_VERSION = ${version.int_version};
+//:: if msg.is_fixed_length:
+ private final static int LENGTH = ${msg.length};
+//:: else:
+ private final static int MINIMUM_LENGTH = ${msg.min_length};
+//:: #endif
+
+//:: for prop in msg.data_members:
+ private final static ${prop.java_type.public_type} ${prop.default_name} = ${prop.default_value};
+//:: #end
+
+ // OF message fields
+//:: for prop in msg.data_members:
+ private final ${prop.java_type.public_type} ${prop.name};
+//:: #endfor
+
+ ${impl_class}(${
+ ", ".join("%s %s" %(prop.java_type.public_type, prop.name) for prop in msg.data_members) }) {
+//:: for prop in msg.data_members:
+ this.${prop.name} = ${prop.name};
+//:: #endfor
+ }
+
+ // Accessors for OF message fields
+//:: include("_field_accessors.java", msg=msg, generate_setters=False, builder=False)
+
+
+ public ${msg.name}.Builder createBuilder() {
+ return new BuilderImplWithParent(this);
+ }
+
+ static class BuilderImplWithParent implements ${msg.interface.name}.Builder {
+ final ${impl_class} parentMessage;
+
+ // OF message fields
+//:: for prop in msg.data_members:
+ private boolean ${prop.name}Set;
+ private ${prop.java_type.public_type} ${prop.name};
+//:: #endfor
+
+ BuilderImplWithParent(${impl_class} parentMessage) {
+ this.parentMessage = parentMessage;
+ }
+
+//:: include("_field_accessors.java", msg=msg, generate_setters=True, builder=True)
+
+ @Override
+ public ${msg.interface.name} getMessage() {
+ return new ${impl_class}(
+ ${",\n ".join(
+ [ "this.{0}Set ? this.{0} : parentMessage.{0}".format(prop.name)
+ for prop in msg.data_members])}
+ );
+ }
+ }
+
+ static class BuilderImpl implements ${msg.interface.name}.Builder {
+ // OF message fields
+//:: for prop in msg.data_members:
+ private boolean ${prop.name}Set;
+ private ${prop.java_type.public_type} ${prop.name};
+//:: #endfor
+
+//:: include("_field_accessors.java", msg=msg, generate_setters=True, builder=True)
+//
+ @Override
+ public ${msg.interface.name} getMessage() {
+ return new ${impl_class}(
+ ${",\n ".join(
+ [ "this.{0}Set ? this.{0} : {1}.{2}".format(prop.name, impl_class, prop.default_name)
+ for prop in msg.data_members])}
+ );
+ }
+ }
+
+ final static Reader READER = new Reader();
+ static class Reader implements OFMessageReader<${msg.interface.name}> {
+ @Override
+ public ${msg.interface.name} readFrom(ChannelBuffer bb) throws OFParseError {
+//:: fields_with_length_member = {}
+//:: for prop in msg.members:
+//:: if prop.is_data:
+ ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version,
+ length=fields_with_length_member[prop.c_name] if prop.c_name in fields_with_length_member else None)};
+//:: elif prop.is_pad:
+ // pad: ${prop.length} bytes
+ bb.skipBytes(${prop.length});
+//:: elif prop.is_fixed_value:
+ // fixed value property ${prop.name} == ${prop.value}
+ ${prop.java_type.priv_type} ${prop.name} = ${prop.java_type.read_op(version)};
+ if(${prop.name} != ${prop.value})
+ throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
+//:: elif prop.is_length_value:
+ ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version)};
+ if(${prop.name} < MINIMUM_LENGTH)
+ throw new OFParseError("Wrong ${prop.name}: Expected to be >= " + MINIMUM_LENGTH + ", was: " + ${prop.name});
+//:: elif prop.is_field_length_value:
+//:: fields_with_length_member[prop.member.field_name] = prop.name
+ int ${prop.name} = ${prop.java_type.read_op(version)};
+//:: else:
+ // fixme: todo ${prop.name}
+//:: #endif
+//:: #endfor
+ return new ${impl_class}(
+ ${",\n ".join(
+ [ prop.name for prop in msg.data_members])}
+ );
+ }
+ }
+
+ public int writeTo(ChannelBuffer bb) {
+ return WRITER.write(bb, this);
+ }
+
+ final static Writer WRITER = new Writer();
+ static class Writer implements OFMessageWriter<${impl_class}> {
+ @Override
+ public int write(ChannelBuffer bb, ${impl_class} message) {
+//:: if not msg.is_fixed_length:
+ int startIndex = bb.writerIndex();
+//:: #end
+
+//:: fields_with_length_member = {}
+//:: for prop in msg.members:
+//:: if prop.c_name in fields_with_length_member:
+ int ${prop.name}StartIndex = bb.writerIndex();
+//:: #endif
+//:: if prop.is_data:
+ ${prop.java_type.write_op(version, "message." + prop.name)};
+//:: elif prop.is_pad:
+ // pad: ${prop.length} bytes
+ bb.writeZero(${prop.length});
+//:: elif prop.is_fixed_value:
+ // fixed value property ${prop.name} = ${prop.value}
+ ${prop.java_type.write_op(version, prop.value)};
+//:: elif prop.is_length_value:
+ // ${prop.name} is length of variable message, will be updated at the end
+ ${prop.java_type.write_op(version, 0)};
+//:: elif prop.is_field_length_value:
+//:: fields_with_length_member[prop.member.field_name] = prop.name
+ // ${prop.name} is length indicator for ${prop.member.field_name}, will be
+ // udpated when ${prop.member.field_name} has been written
+ int ${prop.name}Index = bb.writerIndex();
+ ${prop.java_type.write_op(version, 0)};
+//:: else:
+ // FIXME: todo write ${prop.name}
+//:: #endif
+//:: if prop.c_name in fields_with_length_member:
+//:: length_member_name = fields_with_length_member[prop.c_name]
+ // update field length member ${length_member_name}
+ int ${prop.name}Length = bb.writerIndex() - ${prop.name}StartIndex;
+ bb.setShort(${length_member_name}Index, ${prop.name}Length);
+//:: #endif
+//:: #endfor
+
+//:: if msg.is_fixed_length:
+ return LENGTH;
+//:: else:
+ // update length field
+ int length = bb.writerIndex() - startIndex;
+ bb.setShort(startIndex + 2, length);
+ return length;
+//:: #end
+
+ }
+ }
+
+
+}
diff --git a/java_gen/templates/message_interface.java b/java_gen/templates/of_interface.java
similarity index 71%
rename from java_gen/templates/message_interface.java
rename to java_gen/templates/of_interface.java
index 904be95..af6493e 100644
--- a/java_gen/templates/message_interface.java
+++ b/java_gen/templates/of_interface.java
@@ -31,32 +31,25 @@
//:: include('_autogen.java')
-package org.openflow.protocol;
-import java.util.List;
-import org.openflow.protocol.match.*;
-import org.openflow.protocol.actions.OFAction;
-import org.openflow.protocol.instructions.OFInstruction;
-import org.openflow.types.*;
-import org.openflow.util.*;
-import org.openflow.exceptions.OFUnsupported;
+package ${msg.package};
-public interface ${msg.interface_name} extends OFMessage {
- int getXid();
- boolean isXidSet();
- OFType getType();
- OFVersion getVersion();
+//:: include("_imports.java", msg=msg)
-//:: for prop in msg.all_properties():
- ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop.is_universal else "throws UnsupportedOperationException"};
+public interface ${msg.name} ${"extends %s" % msg.parent_interface if msg.parent_interface else ""} {
+//:: for prop in msg.members:
+ ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop.is_universal else " throws UnsupportedOperationException"};
//:: #endfor
- Builder createBuilder();
+ int writeTo(ChannelBuffer channelBuffer);
- public interface Builder {
- ${msg.interface_name} getMessage();
-//:: for prop in msg.all_properties():
- ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop.is_universal else "throws UnsupportedOperationException"};
+ Builder createBuilder();
+ public interface Builder ${"extends %s.Builder" % msg.parent_interface if msg.parent_interface else ""} {
+ ${msg.name} getMessage();
+//:: for prop in msg.members:
+ ${prop.java_type.public_type} get${prop.title_name}()${ "" if prop.is_universal else " throws UnsupportedOperationException"};
+//:: if prop.is_writeable:
Builder set${prop.title_name}(${prop.java_type.public_type} ${prop.name})${ "" if prop.is_universal else " throws UnsupportedOperationException"};
+//:: #endif
//:: #endfor
}
diff --git a/lang_java.py b/lang_java.py
index db23c82..be94e82 100644
--- a/lang_java.py
+++ b/lang_java.py
@@ -42,35 +42,9 @@
"""
-import java_gen.java_code_gen as java_code_gen
+import java_gen.codegen as java_codegen
targets = {
- 'base_java': java_code_gen.gen_all_java
+ 'openflowj/README': java_codegen.gen_all_java
}
-
-##
-# The list of files to produce. These are the keywords used to index
-# the arrays below giving the external file names, the subdirectory locations
-# and the generating functions.
-
-target_files = ["base_java" ]
-# Internal file name references to actual file names
-file_to_name_map = dict(
- # LOCI source
- base_java="README.openflowj", # not really used by java generator
-)
-
-##
-# The map from the internal file identifier to the function name
-# that generates the content of the file
-
-file_gen_map = dict(
- base_java=java_code_gen.gen_all_java,
-)
-
-
-# Map from file references to target sub-directories
-file_to_subdir_map = dict(
- base_java="openflowj/",
-)
diff --git a/loxi_front_end/match.py b/loxi_front_end/match.py
index 42c0a9e..20d5030 100644
--- a/loxi_front_end/match.py
+++ b/loxi_front_end/match.py
@@ -147,7 +147,7 @@
),
ipv4_src = dict(
name="ipv4_src",
- m_type="uint32_t",
+ m_type="of_ipv4_t",
v1_wc_shift=8,
print_type="PRIx32",
conditions="is_ipv4(match)",
@@ -156,7 +156,7 @@
),
ipv4_dst = dict(
name="ipv4_dst",
- m_type="uint32_t",
+ m_type="of_ipv4_t",
v1_wc_shift=14,
print_type="PRIx32",
conditions="is_ipv4(match)",
diff --git a/loxigen.py b/loxigen.py
index 1d1f245..36d6872 100755
--- a/loxigen.py
+++ b/loxigen.py
@@ -442,7 +442,12 @@
name=m_name))
pad_count += 1
else:
- legacy_members.append(dict(m_type=m.oftype, name=m.name))
+ # HACK the C backend does not yet support of_oxm_t
+ if m.oftype == 'of_oxm_t':
+ m_type = 'of_octets_t'
+ else:
+ m_type = m.oftype
+ legacy_members.append(dict(m_type=m_type, name=m.name))
versions[version_name]['classes'][ofclass.name] = legacy_members
for enum in ofinput.enums:
diff --git a/of_g.py b/of_g.py
index 2e8b5ba..651ee64 100644
--- a/of_g.py
+++ b/of_g.py
@@ -280,6 +280,7 @@
# of_counter_t = dict(bytes=8, to_w="u64_hton", from_w="u64_ntoh", use_as_rv=1,
# short_name="counter"),
of_mac_addr_t = dict(bytes=6, short_name="mac"),
+ of_ipv4_t = dict(bytes=4, short_name="ipv4"),
of_ipv6_t = dict(bytes=16, short_name="ipv6"),
of_port_name_t = dict(bytes=ofp_constants["OF_MAX_PORT_NAME_LEN"],
short_name="port_name"),
@@ -308,7 +309,7 @@
"of_port_no_t", "of_fm_cmd_t", "of_wc_bmap_t",
"of_match_bmap_t", "of_port_name_t", "of_table_name_t",
"of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
- "of_ipv6_t"]
+ "of_ipv6_t", "of_ipv4_t"]
base_object_members = """\
/* The control block for the underlying data buffer */
diff --git a/openflow_input/bsn_get_interfaces b/openflow_input/bsn_get_interfaces
index ba1508c..01902bc 100644
--- a/openflow_input/bsn_get_interfaces
+++ b/openflow_input/bsn_get_interfaces
@@ -40,8 +40,8 @@
of_mac_addr_t hw_addr;
pad(2);
of_port_name_t name;
- uint32_t ipv4_addr;
- uint32_t ipv4_netmask;
+ of_ipv4_t ipv4_addr;
+ of_ipv4_t ipv4_netmask;
};
struct of_bsn_get_interfaces_reply {
diff --git a/openflow_input/oxm-1.2 b/openflow_input/oxm-1.2
index b18c6fb..01af6c6 100644
--- a/openflow_input/oxm-1.2
+++ b/openflow_input/oxm-1.2
@@ -227,24 +227,24 @@
struct of_oxm_ipv4_dst {
uint32_t type_len == 0x80001804;
- uint32_t value;
+ of_ipv4_t value;
};
struct of_oxm_ipv4_dst_masked {
uint32_t type_len == 0x80001908;
- uint32_t value;
- uint32_t value_mask;
+ of_ipv4_t value;
+ of_ipv4_t value_mask;
};
struct of_oxm_ipv4_src {
uint32_t type_len == 0x80001604;
- uint32_t value;
+ of_ipv4_t value;
};
struct of_oxm_ipv4_src_masked {
uint32_t type_len == 0x80001708;
- uint32_t value;
- uint32_t value_mask;
+ of_ipv4_t value;
+ of_ipv4_t value_mask;
};
struct of_oxm_ipv6_dst {
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 5d4405c..e9cb6f0 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -563,8 +563,8 @@
uint8_t ip_dscp;
uint8_t ip_proto;
pad(2);
- uint32_t ipv4_src;
- uint32_t ipv4_dst;
+ of_ipv4_t ipv4_src;
+ of_ipv4_t ipv4_dst;
uint16_t tcp_src;
uint16_t tcp_dst;
};
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index a477d55..553e665 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -779,10 +779,10 @@
uint16_t eth_type;
uint8_t ip_dscp;
uint8_t ip_proto;
- uint32_t ipv4_src;
- uint32_t ipv4_src_mask;
- uint32_t ipv4_dst;
- uint32_t ipv4_dst_mask;
+ of_ipv4_t ipv4_src;
+ of_ipv4_t ipv4_src_mask;
+ of_ipv4_t ipv4_dst;
+ of_ipv4_t ipv4_dst_mask;
uint16_t tcp_src;
uint16_t tcp_dst;
uint32_t mpls_label;
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 4650e06..8b4fa3f 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -692,7 +692,7 @@
struct of_action_set_field {
uint16_t type == 25;
uint16_t len;
- of_octets_t field;
+ of_oxm_t field;
};
struct of_action_experimenter {
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index ccef4db..0d5cec3 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -824,7 +824,7 @@
struct of_action_set_field {
uint16_t type == 25;
uint16_t len;
- of_octets_t field;
+ of_oxm_t field;
};
struct of_action_experimenter {
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 4e93c4c..6570938 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -35,7 +35,8 @@
from loxi_ir import *
PyOFClass = namedtuple('PyOFClass', ['name', 'pyname', 'members', 'type_members',
- 'min_length', 'is_fixed_length'])
+ 'min_length', 'is_fixed_length',
+ 'has_internal_alignment', 'has_external_alignment'])
# Return the name for the generated Python class
def generate_pyname(cls):
@@ -92,7 +93,9 @@
members=members,
type_members=type_members,
min_length=of_g.base_length[(cls, version)],
- is_fixed_length=(cls, version) in of_g.is_fixed_length))
+ is_fixed_length=(cls, version) in of_g.is_fixed_length,
+ has_internal_alignment=cls == 'of_action_set_field',
+ has_external_alignment=cls == 'of_match_v3'))
return ofclasses
def generate_init(out, name, version):
diff --git a/py_gen/oftype.py b/py_gen/oftype.py
index cf87ded..2399266 100644
--- a/py_gen/oftype.py
+++ b/py_gen/oftype.py
@@ -78,6 +78,11 @@
pack='util.pack_match_bmap(%s)',
unpack='util.unpack_match_bmap(%s)'),
+ 'of_ipv4_t': OFTypeData(
+ init='0',
+ pack='struct.pack("!L", %s)',
+ unpack='%s.read("!L")[0]'),
+
'of_ipv6_t': OFTypeData(
init="'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'",
pack='struct.pack("!16s", %s)',
@@ -99,6 +104,11 @@
pack='util.pack_list(%s)',
unpack='oxm.unpack_list(%s.slice(_length-4))'),
+ 'of_oxm_t': OFTypeData(
+ init='None',
+ pack='%s.pack()',
+ unpack='oxm.unpack(%s)'),
+
# TODO implement unpack
'list(of_table_features_t)': OFTypeData(
init='[]',
diff --git a/py_gen/templates/_pack.py b/py_gen/templates/_pack.py
index 4714e97..9956cf6 100644
--- a/py_gen/templates/_pack.py
+++ b/py_gen/templates/_pack.py
@@ -56,8 +56,12 @@
:: #endfor
:: if length_member_index != None:
length = sum([len(x) for x in packed])
+:: if ofclass.has_internal_alignment:
+ packed.append(loxi.generic_util.pad_to(8, length))
+ length += len(packed[-1])
+:: #endif
packed[${length_member_index}] = ${gen_pack_expr(length_member.oftype, 'length')}
:: #endif
-:: if ofclass.name == 'of_match_v3':
- packed.append('\x00' * ((length + 7)/8*8 - length))
+:: if ofclass.has_external_alignment:
+ packed.append(loxi.generic_util.pad_to(8, length))
:: #endif
diff --git a/py_gen/templates/_pretty_print.py b/py_gen/templates/_pretty_print.py
index 7be7a14..ed9d5cc 100644
--- a/py_gen/templates/_pretty_print.py
+++ b/py_gen/templates/_pretty_print.py
@@ -46,7 +46,7 @@
q.text('None')
:: elif m.oftype == 'of_mac_addr_t':
q.text(util.pretty_mac(self.${m.name}))
-:: elif m.oftype == 'uint32_t' and m.name.startswith("ipv4"):
+:: elif m.oftype == 'of_ipv4_t':
q.text(util.pretty_ipv4(self.${m.name}))
:: elif m.oftype == 'of_wc_bmap_t' and version in [1,2]:
q.text(util.pretty_wildcards(self.${m.name}))
diff --git a/py_gen/templates/_unpack.py b/py_gen/templates/_unpack.py
index 133e831..09a0e08 100644
--- a/py_gen/templates/_unpack.py
+++ b/py_gen/templates/_unpack.py
@@ -53,6 +53,6 @@
obj.${m.name} = ${gen_unpack_expr(m.oftype, reader_expr)}
:: #endif
:: #endfor
-:: if ofclass.name == 'of_match_v3':
- reader.skip((_length + 7)/8*8 - _length)
+:: if ofclass.has_external_alignment or ofclass.has_internal_alignment:
+ reader.skip_align()
:: #endif
diff --git a/py_gen/templates/action.py b/py_gen/templates/action.py
index dccb46e..fba5294 100644
--- a/py_gen/templates/action.py
+++ b/py_gen/templates/action.py
@@ -37,6 +37,9 @@
import util
import loxi.generic_util
import loxi
+:: if version >= 3:
+import oxm # for unpack
+:: #endif
def unpack_list(reader):
def deserializer(reader, typ):
diff --git a/py_gen/templates/generic_util.py b/py_gen/templates/generic_util.py
index 53091ed..28d3b5f 100644
--- a/py_gen/templates/generic_util.py
+++ b/py_gen/templates/generic_util.py
@@ -63,6 +63,13 @@
return deserializer(reader.slice(length), typ)
return unpack_list(reader, wrapper)
+def pad_to(alignment, length):
+ """
+ Return a string of zero bytes that will pad a string of length 'length' to
+ a multiple of 'alignment'.
+ """
+ return "\x00" * ((length + alignment - 1)/alignment*alignment - length)
+
class OFReader(object):
"""
Cursor over a read-only buffer
@@ -102,6 +109,12 @@
raise loxi.ProtocolError("Buffer too short")
self.offset += length
+ def skip_align(self):
+ new_offset = (self.offset + 7) / 8 * 8
+ if new_offset > len(self.buf):
+ raise loxi.ProtocolError("Buffer too short")
+ self.offset = new_offset
+
def is_empty(self):
return self.offset == len(self.buf)
diff --git a/py_gen/templates/oxm.py b/py_gen/templates/oxm.py
index d95dd8e..792c277 100644
--- a/py_gen/templates/oxm.py
+++ b/py_gen/templates/oxm.py
@@ -38,15 +38,16 @@
import loxi.generic_util
import loxi
+def unpack(reader):
+ type_len, = reader.peek('!L')
+ if type_len in parsers:
+ return parsers[type_len](reader)
+ else:
+ raise loxi.ProtocolError("unknown OXM cls=%#x type=%#x masked=%d len=%d (%#x)" % \
+ ((type_len >> 16) & 0xffff, (type_len >> 9) & 0x7f, (type_len >> 8) & 1, type_len & 0xff, type_len))
+
def unpack_list(reader):
- def deserializer(reader):
- type_len, = reader.peek('!L')
- if type_len in parsers:
- return parsers[type_len](reader)
- else:
- raise loxi.ProtocolError("unknown OXM cls=%#x type=%#x masked=%d len=%d (%#x)" % \
- ((type_len >> 16) & 0xffff, (type_len >> 9) & 0x7f, (type_len >> 8) & 1, type_len & 0xff, type_len))
- return loxi.generic_util.unpack_list(reader, deserializer)
+ return loxi.generic_util.unpack_list(reader, unpack)
class OXM(object):
type_len = None # override in subclass
diff --git a/py_gen/tests/of12.py b/py_gen/tests/of12.py
index c6c94ab..98d999b 100644
--- a/py_gen/tests/of12.py
+++ b/py_gen/tests/of12.py
@@ -78,7 +78,9 @@
self.klasses.sort(key=lambda x: str(x))
def test_serialization(self):
- expected_failures = []
+ expected_failures = [
+ ofp.action.set_field, # field defaults to None
+ ]
for klass in self.klasses:
def fn():
obj = klass()
diff --git a/py_gen/tests/of13.py b/py_gen/tests/of13.py
index 349881f..8c18f41 100644
--- a/py_gen/tests/of13.py
+++ b/py_gen/tests/of13.py
@@ -93,6 +93,7 @@
def test_serialization(self):
expected_failures = [
+ ofp.action.set_field, # field defaults to None
ofp.common.table_feature_prop_apply_actions,
ofp.common.table_feature_prop_apply_actions_miss,
ofp.common.table_feature_prop_write_actions,
diff --git a/test_data/of13/action_output.data b/test_data/of13/action_output.data
new file mode 100644
index 0000000..7cd52ce
--- /dev/null
+++ b/test_data/of13/action_output.data
@@ -0,0 +1,8 @@
+-- binary
+00 00 # type
+00 10 # length
+00 00 00 32 # port
+ff ff # max_len
+00 00 00 00 00 00 # pad
+-- python
+ofp.action.output(port=50, max_len=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..1e4a971
--- /dev/null
+++ b/test_data/of13/action_set_field_eth_dst.data
@@ -0,0 +1,8 @@
+-- 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_ipv6_src.data b/test_data/of13/action_set_field_ipv6_src.data
new file mode 100644
index 0000000..f440dee
--- /dev/null
+++ b/test_data/of13/action_set_field_ipv6_src.data
@@ -0,0 +1,7 @@
+-- binary
+00 19 # type
+00 18 # length
+80 00 34 10 # OXM header
+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"))
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..a69c7c0
--- /dev/null
+++ b/test_data/of13/action_set_field_tcp_src.data
@@ -0,0 +1,8 @@
+-- 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))