Merge branch 'master' of github.com:floodlight/loxigen
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index f4d3f92..04d863f 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -351,5 +351,16 @@
 #define LOCI_SHOW_u32_bsn_l3_interface_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
 #define LOCI_SHOW_u32_bsn_l3_src_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
 #define LOCI_SHOW_u32_bsn_l3_dst_class_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u8_convergence_status(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
+#define LOCI_SHOW_u16_actor_sys_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_mac_actor_sys_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
+#define LOCI_SHOW_u16_actor_port_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_u16_actor_port_num(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_u16_actor_key(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_u16_partner_sys_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_mac_partner_sys_mac(writer, cookie, val) LOCI_SHOW_mac(writer, cookie, val)
+#define LOCI_SHOW_u16_partner_port_priority(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_u16_partner_port_num(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
+#define LOCI_SHOW_u16_partner_key(writer, cookie, val) LOCI_SHOW_u16(writer, cookie, val)
 
 #endif /* _LOCI_SHOW_H_ */
diff --git a/java_gen/codegen.py b/java_gen/codegen.py
index 6c589c9..f349f9e 100644
--- a/java_gen/codegen.py
+++ b/java_gen/codegen.py
@@ -44,9 +44,7 @@
 
 import java_gen.java_model as java_model
 
-def gen_all_java(out, name):
-    # close the virtual file - we don't need it
-    out.close()
+def gen_all_java():
     basedir= '%s/openflowj' % of_g.options.install_dir
     print "Outputting to %s" % basedir
     if os.path.exists(basedir):
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
index 672a0e1..6eb5743 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
@@ -38,26 +38,6 @@
             this.input = input;
         }
 
-        public WithMaskTaskCase hasMask() {
-            this.hasMask = true;
-            return this;
-        }
-
-        public WithMaskTaskCase maskLength(int l) {
-            this.hasMask = l < 128;
-            for(int j=0; j < 8; j++) {
-                int pos = j * 8;
-                int index = Math.max(0, Math.min(7, pos - l));
-
-                if(index == 0) {
-                    expectedMask[j] = 0;
-                } else {
-                    expectedMask[j] = (byte) (-1 << index);
-                }
-            }
-            return this;
-        }
-
         public WithMaskTaskCase maskHex(String string) {
             string = string.replaceAll(" ", "");
             this.hasMask = true;
diff --git a/lang_c.py b/lang_c.py
index fc016f2..9cfc2fa 100644
--- a/lang_c.py
+++ b/lang_c.py
@@ -39,6 +39,7 @@
 import c_gen.c_show_gen as c_show_gen
 import c_gen.c_validator_gen as c_validator_gen
 import c_gen.util
+import loxi_utils.loxi_utils as loxi_utils
 
 def static(out, name):
     c_gen.util.render_template(out, os.path.basename(name))
@@ -110,3 +111,8 @@
     'locitest/src/main.c': static,
     'locitest/Makefile': static,
 }
+
+def generate():
+    for (name, fn) in targets.items():
+        with loxi_utils.open_output(name) as outfile:
+            fn(outfile, os.path.basename(name))
diff --git a/lang_java.py b/lang_java.py
index be94e82..3891076 100644
--- a/lang_java.py
+++ b/lang_java.py
@@ -27,24 +27,9 @@
 
 """
 @brief Java language specific LOXI generating configuration
-
-This language specific file defines:
-
-target_files:  List of internal references to files to generate
-file_gen_map: The map from above file references to generator functions
-file_to_name_map: The map from internal references to external file names
-file_to_subdir_map: The map from internal references to external subdirectories
-
-HOWEVER, since java files are all a function of their class name, we don't
-know in advance what the names of the files/classes will be, so we just
-define a single directory and generate everything in there.
-    @fixme talk to DanT to see if there isn't something that makes more sense
-
 """
 
 import java_gen.codegen as java_codegen
 
-
-targets = {
-    'openflowj/README': java_codegen.gen_all_java
-}
+def generate():
+    java_codegen.gen_all_java()
diff --git a/lang_python.py b/lang_python.py
index 639cf1a..9c9d13e 100644
--- a/lang_python.py
+++ b/lang_python.py
@@ -61,6 +61,8 @@
 "ofp.OFPP_NONE".
 """
 
+import os
+import loxi_utils.loxi_utils as loxi_utils
 import py_gen
 import py_gen.util
 import py_gen.codegen
@@ -99,3 +101,9 @@
     for module in modules[version]:
         filename = '%s/%s/%s.py' % (prefix, subdir, module)
         targets[filename] = make_gen(module, version)
+
+def generate():
+    py_gen.codegen.init()
+    for (name, fn) in targets.items():
+        with loxi_utils.open_output(name) as outfile:
+            fn(outfile, os.path.basename(name))
diff --git a/lang_wireshark.py b/lang_wireshark.py
index 9f73543..3e862d2 100644
--- a/lang_wireshark.py
+++ b/lang_wireshark.py
@@ -38,6 +38,5 @@
 
 import wireshark_gen
 
-targets = {
-    'wireshark/openflow.lua' : wireshark_gen.generate
-}
+def generate():
+    wireshark_gen.generate()
diff --git a/loxi_utils/loxi_utils.py b/loxi_utils/loxi_utils.py
index 601a65d..059c363 100644
--- a/loxi_utils/loxi_utils.py
+++ b/loxi_utils/loxi_utils.py
@@ -34,6 +34,7 @@
 """
 
 import sys
+import os
 import of_g
 import tenjin
 from generic_utils import find, memoize
@@ -543,3 +544,16 @@
         context.update(kwargs)
         template = self.get_template(template_name, context, globals)
         return template.render(context, globals, _buf=locals["_buf"])
+
+def open_output(name):
+    """
+    Open an output file for writing
+
+    'name' may include slashes. Subdirectories will be automatically created.
+    """
+    print "Writing %s" % name
+    path = os.path.join(of_g.options.install_dir, name)
+    dirpath = os.path.dirname(path)
+    if not os.path.exists(dirpath):
+        os.makedirs(dirpath)
+    return open(path, "w")
diff --git a/loxigen.py b/loxigen.py
index 05dd6b5..7b78f63 100755
--- a/loxigen.py
+++ b/loxigen.py
@@ -630,12 +630,7 @@
     """
     Create the files for the language target
     """
-    for (name, fn) in lang_module.targets.items():
-        path = of_g.options.install_dir + '/' + name
-        os.system("mkdir -p %s" % os.path.dirname(path))
-        with open(path, "w") as outfile:
-            fn(outfile, os.path.basename(name))
-        print("Wrote contents for " + name)
+    lang_module.generate()
 
 if __name__ == '__main__':
     of_g.loxigen_log_file = open("loxigen.log", "w")
diff --git a/openflow_input/bsn_lacp b/openflow_input/bsn_lacp
new file mode 100644
index 0000000..8237641
--- /dev/null
+++ b/openflow_input/bsn_lacp
@@ -0,0 +1,90 @@
+// 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.
+
+#version 4
+
+// LACP Convergence Status set in of_bsn_lacp_convergence_notif message
+enum of_bsn_lacp_convergence_status_t(wire_type=uint8_t, complete=False) {
+    LACP_SUCCESS = 0,
+    LACP_TIMEDOUT = 1,
+    LACP_OUT_OF_SYNC = 2,
+};
+
+struct of_bsn_set_lacp_request : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 41;
+    uint8_t enabled;
+    pad(3);
+    of_port_no_t port_no;
+    uint16_t actor_sys_priority;
+    of_mac_addr_t actor_sys_mac;
+    uint16_t actor_port_priority;
+    uint16_t actor_port_num;
+    uint16_t actor_key;
+};
+
+struct of_bsn_set_lacp_reply : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 42;
+    uint32_t status;
+    of_port_no_t port_no;
+};
+
+struct of_bsn_lacp_convergence_notif : of_bsn_header {
+    uint8_t version;
+    uint8_t type == 4;
+    uint16_t length;
+    uint32_t xid;
+    uint32_t experimenter == 0x5c16c7;
+    uint32_t subtype == 43;
+    uint8_t convergence_status;
+    pad(3);
+    of_port_no_t port_no;
+
+    uint16_t actor_sys_priority;
+    of_mac_addr_t actor_sys_mac;
+    uint16_t actor_port_priority;
+    uint16_t actor_port_num;
+    uint16_t actor_key;
+
+    uint16_t partner_sys_priority;
+    of_mac_addr_t partner_sys_mac;
+    uint16_t partner_port_priority;
+    uint16_t partner_port_num;
+    uint16_t partner_key;
+};
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 540d212..70053f7 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -34,6 +34,8 @@
 import oftype
 from loxi_ir import *
 
+ofclasses_by_version = {}
+
 PyOFClass = namedtuple('PyOFClass', ['name', 'pyname', 'members', 'type_members',
                                      'min_length', 'is_fixed_length',
                                      'has_internal_alignment', 'has_external_alignment'])
@@ -99,17 +101,17 @@
     util.render_template(out, 'init.py', version=version)
 
 def generate_action(out, name, version):
-    ofclasses = [x for x in build_ofclasses(version)
+    ofclasses = [x for x in ofclasses_by_version[version]
                  if utils.class_is_action(x.name)]
     util.render_template(out, 'action.py', ofclasses=ofclasses, version=version)
 
 def generate_oxm(out, name, version):
-    ofclasses = [x for x in build_ofclasses(version)
+    ofclasses = [x for x in ofclasses_by_version[version]
                  if utils.class_is_oxm(x.name)]
     util.render_template(out, 'oxm.py', ofclasses=ofclasses, version=version)
 
 def generate_common(out, name, version):
-    ofclasses = [x for x in build_ofclasses(version)
+    ofclasses = [x for x in ofclasses_by_version[version]
                  if not utils.class_is_message(x.name)
                     and not utils.class_is_action(x.name)
                     and not utils.class_is_instruction(x.name)
@@ -123,17 +125,17 @@
                          enums=of_g.ir[version].enums)
 
 def generate_instruction(out, name, version):
-    ofclasses = [x for x in build_ofclasses(version)
+    ofclasses = [x for x in ofclasses_by_version[version]
                  if utils.class_is_instruction(x.name)]
     util.render_template(out, 'instruction.py', ofclasses=ofclasses, version=version)
 
 def generate_message(out, name, version):
-    ofclasses = [x for x in build_ofclasses(version)
+    ofclasses = [x for x in ofclasses_by_version[version]
                  if utils.class_is_message(x.name)]
     util.render_template(out, 'message.py', ofclasses=ofclasses, version=version)
 
 def generate_meter_band(out, name, version):
-    ofclasses = [x for x in build_ofclasses(version)
+    ofclasses = [x for x in ofclasses_by_version[version]
                  if utils.class_is_meter_band(x.name)]
     util.render_template(out, 'meter_band.py', ofclasses=ofclasses, version=version)
 
@@ -142,3 +144,7 @@
 
 def generate_util(out, name, version):
     util.render_template(out, 'util.py', version=version)
+
+def init():
+    for version in of_g.supported_wire_protos:
+        ofclasses_by_version[version] = build_ofclasses(version)
diff --git a/wireshark_gen/__init__.py b/wireshark_gen/__init__.py
index c4ff7f4..1225131 100644
--- a/wireshark_gen/__init__.py
+++ b/wireshark_gen/__init__.py
@@ -111,8 +111,10 @@
 
     return r
 
-def generate(out, name):
+def generate():
     context = {
         'fields': create_fields(),
     }
-    utils.render_template(out, "openflow.lua", [templates_dir], context)
+
+    with utils.open_output('openflow.lua') as out:
+        utils.render_template(out, "openflow.lua", [templates_dir], context)