Merge remote-tracking branch 'origin/master' into of14
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index ea05826..07b0ade 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -124,7 +124,7 @@
 # TODO remove header classes and use the corresponding class instead
 def generate_header_classes(install_dir):
     for cls in of_g.standard_class_order:
-        if cls.find("_header") < 0 or cls in ["of_header", "of_bsn_header", "of_nicira_header"]:
+        if not cls.endswith("_header") or cls in ["of_header", "of_bsn_header", "of_nicira_header"]:
             continue
         with template_utils.open_output(install_dir, "loci/src/%s.c" % cls) as out:
             util.render_template(out, "class.c",
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index 3624bcd..239bf57 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -416,5 +416,6 @@
 #define LOCI_SHOW_u8_loglevel(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
 #define LOCI_SHOW_u32_vrf(write, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
 #define LOCI_SHOW_u32_bsn_vlan_xlate_port_group_id(writer, cookie, val) LOCI_SHOW_u32(writer, cookie, val)
+#define LOCI_SHOW_u8_mpls_bos(writer, cookie, val) LOCI_SHOW_u8(writer, cookie, val)
 
 #endif /* _LOCI_SHOW_H_ */
diff --git a/c_gen/type_maps.py b/c_gen/type_maps.py
index 7b745a6..6cbb3a5 100644
--- a/c_gen/type_maps.py
+++ b/c_gen/type_maps.py
@@ -150,7 +150,7 @@
     """
     Returns True if cls is a virtual class
     """
-    if cls.find("header") > 0:
+    if cls.endswith("header"):
         return True
     if loxi_utils.class_is_list(cls):
         return True
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index abd9e5b..e0f0680 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -614,6 +614,8 @@
         'of_oxm_mpls_label_masked' : { 'value' : u32obj, 'value_mask' : u32obj },
         'of_oxm_mpls_tc' : { 'value' : u8obj },
         'of_oxm_mpls_tc_masked' : { 'value' : u8obj, 'value_mask' : u8obj },
+        'of_oxm_mpls_bos' : { 'value' : boolean_value },
+        'of_oxm_mpls_bos_masked' : { 'value' : boolean_value, 'value_mask' : boolean_value },
 
         'of_oxm_bsn_in_ports_128' : { 'value': port_bitmap },
         'of_oxm_bsn_in_ports_128_masked' : { 'value': port_bitmap, 'value_mask': port_bitmap },
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
index 78e6075..2fb58b7 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
@@ -178,6 +178,10 @@
             new MatchField<U8>("mpls_tc", MatchFields.MPLS_TC,
                     new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.MPLS_UNICAST, EthType.MPLS_MULTICAST));
 
+    public final static MatchField<OFBooleanValue> MPLS_BOS =
+            new MatchField<OFBooleanValue>("mpls_bos", MatchFields.MPLS_BOS,
+                    new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.MPLS_UNICAST, EthType.MPLS_MULTICAST));
+
     public final static MatchField<U64> TUNNEL_ID = 
             new MatchField<U64>("tunnel_id", MatchFields.TUNNEL_ID);
 
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
index 863634e..77494cb 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchFields.java
@@ -38,6 +38,7 @@
     IPV6_ND_TLL,
     MPLS_LABEL,
     MPLS_TC,
+    MPLS_BOS,
     TUNNEL_ID,
     BSN_IN_PORTS_128,
     BSN_LAG_ID,
diff --git a/lang_python.py b/lang_python.py
index 019b62d..18fca27 100644
--- a/lang_python.py
+++ b/lang_python.py
@@ -28,12 +28,6 @@
 """
 Python backend for LOXI
 
-This language specific file defines a dictionary 'targets' that
-defines the generated files and the functions used to generate them.
-
-For each generated file there is a generate_* function in py_gen.codegen
-and a Tenjin template under py_gen/templates.
-
 Target directory structure:
     pyloxi:
         loxi:
@@ -64,51 +58,9 @@
 """
 
 import os
-from loxi_globals import OFVersions
-import loxi_globals
-import loxi_utils.loxi_utils as loxi_utils
-import py_gen
-import py_gen.util
 import py_gen.codegen
-import template_utils
 
-versions = {
-    1: "of10",
-    2: "of11",
-    3: "of12",
-    4: "of13",
-}
-
-prefix = 'pyloxi/loxi'
-
-modules = {
-    1: ["action", "common", "const", "message", "util"],
-    2: ["action", "common", "const", "instruction", "message", "util"],
-    3: ["action", "common", "const", "instruction", "message", "oxm", "util"],
-    4: ["action", "action_id", "common", "const", "instruction", "instruction_id", "message", "meter_band", "oxm", "bsn_tlv", "util"],
-}
-
-def make_gen(name, version):
-    fn = getattr(py_gen.codegen, "generate_" + name)
-    return lambda out, name: fn(out, name, version)
-
-def static(template_name):
-    return lambda out, name: py_gen.util.render_template(out, template_name)
-
-targets = {
-    prefix+'/__init__.py': static('toplevel_init.py'),
-    prefix+'/pp.py': static('pp.py'),
-    prefix+'/generic_util.py': static('generic_util.py'),
-}
-
-for version, subdir in versions.items():
-    targets['%s/%s/__init__.py' % (prefix, subdir)] = make_gen('init', version)
-    for module in modules[version]:
-        filename = '%s/%s/%s.py' % (prefix, subdir, module)
-        targets[filename] = make_gen(module, OFVersions.from_wire(version))
+PREFIX = 'pyloxi/loxi'
 
 def generate(install_dir):
-    py_gen.codegen.init()
-    for (name, fn) in targets.items():
-        with template_utils.open_output(install_dir, name) as outfile:
-            fn(outfile, os.path.basename(name))
+    py_gen.codegen.codegen(os.path.join(install_dir, PREFIX))
diff --git a/openflow_input/bsn_tlv b/openflow_input/bsn_tlv
index c4c8995..cc81b96 100644
--- a/openflow_input/bsn_tlv
+++ b/openflow_input/bsn_tlv
@@ -208,3 +208,69 @@
     uint16_t length;
     of_mac_addr_t value;
 };
+
+struct of_bsn_tlv_external_gateway_mac : of_bsn_tlv {
+    uint16_t type == 29;
+    uint16_t length;
+    of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_sampling_rate : of_bsn_tlv {
+    uint16_t type == 30;
+    uint16_t length;
+    uint32_t value;
+};
+
+struct of_bsn_tlv_header_size : of_bsn_tlv {
+    uint16_t type == 31;
+    uint16_t length;
+    uint32_t value; /* bytes */
+};
+
+struct of_bsn_tlv_eth_src : of_bsn_tlv {
+    uint16_t type == 32;
+    uint16_t length;
+    of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_eth_dst : of_bsn_tlv {
+    uint16_t type == 33;
+    uint16_t length;
+    of_mac_addr_t value;
+};
+
+struct of_bsn_tlv_ipv4_src : of_bsn_tlv {
+    uint16_t type == 34;
+    uint16_t length;
+    of_ipv4_t value;
+};
+
+struct of_bsn_tlv_ipv4_dst : of_bsn_tlv {
+    uint16_t type == 35;
+    uint16_t length;
+    of_ipv4_t value;
+};
+
+struct of_bsn_tlv_udp_src : of_bsn_tlv {
+    uint16_t type == 36;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_udp_dst : of_bsn_tlv {
+    uint16_t type == 37;
+    uint16_t length;
+    uint16_t value;
+};
+
+struct of_bsn_tlv_sub_agent_id : of_bsn_tlv {
+    uint16_t type == 38;
+    uint16_t length;
+    uint32_t value;
+};
+
+struct of_bsn_tlv_tx_bytes : of_bsn_tlv {
+    uint16_t type == 39;
+    uint16_t length;
+    uint64_t value;
+};
diff --git a/openflow_input/oxm-1.3 b/openflow_input/oxm-1.3
index 022f416..ac57589 100644
--- a/openflow_input/oxm-1.3
+++ b/openflow_input/oxm-1.3
@@ -41,3 +41,14 @@
     uint64_t value;
     uint64_t value_mask;
 };
+
+struct of_oxm_mpls_bos : of_oxm {
+    uint32_t type_len == 0x80004801;
+    uint8_t value;
+};
+
+struct of_oxm_mpls_bos_masked : of_oxm {
+    uint32_t type_len == 0x80004902;
+    uint8_t value;
+    uint8_t value_mask;
+};
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 9c32e7f..3b0988e 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -26,16 +26,13 @@
 # under the EPL.
 
 from collections import defaultdict
+import os
 import loxi_globals
-import struct
 import template_utils
 import loxi_utils.loxi_utils as utils
 import util
-import oftype
 from loxi_ir import *
 
-modules_by_version = {}
-
 # Map from inheritance root to module name
 roots = {
     'of_header': 'message',
@@ -69,63 +66,36 @@
         modules[module_name].append(ofclass)
     return modules
 
-def generate_init(out, name, version):
-    util.render_template(out, 'init.py', version=version)
+def codegen(install_dir):
+    def render(name, template_name=None, **ctx):
+        if template_name is None:
+            template_name = os.path.basename(name)
+        with template_utils.open_output(install_dir, name) as out:
+            util.render_template(out, template_name, **ctx)
 
-def generate_action(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['action'],
-                         version=version)
+    render('__init__.py', template_name='toplevel_init.py')
+    render('pp.py')
+    render('generic_util.py')
 
-def generate_action_id(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['action_id'],
-                         version=version)
+    for version in loxi_globals.OFVersions.all_supported:
+        subdir = 'of' + version.version.replace('.', '')
+        modules = build_ofclasses(version)
 
-def generate_oxm(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['oxm'],
-                         version=version)
+        render(os.path.join(subdir, '__init__.py'), template_name='init.py',
+               version=version, modules=modules.keys())
 
-def generate_common(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['common'],
-                         version=version,
-                         extra_template='_common_extra.py')
+        render(os.path.join(subdir, 'util.py'), version=version)
 
-def generate_const(out, name, version):
-    util.render_template(out, 'const.py', version=version,
-                         enums=loxi_globals.ir[version].enums)
+        render(os.path.join(subdir, 'const.py'), version=version,
+               enums=loxi_globals.ir[version].enums)
 
-def generate_instruction(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['instruction'],
-                         version=version)
+        args_by_module = {
+            'common': { 'extra_template' : '_common_extra.py' },
+            'message': { 'extra_template' : '_message_extra.py' },
+        }
 
-def generate_instruction_id(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['instruction_id'],
-                         version=version)
-
-def generate_message(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['message'],
-                         version=version,
-                         extra_template='_message_extra.py')
-
-def generate_meter_band(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['meter_band'],
-                         version=version)
-
-def generate_util(out, name, version):
-    util.render_template(out, 'util.py', version=version)
-
-def generate_bsn_tlv(out, name, version):
-    util.render_template(out, 'module.py',
-                         ofclasses=modules_by_version[version]['bsn_tlv'],
-                         version=version)
-
-def init():
-    for version in loxi_globals.OFVersions.target_versions:
-        modules_by_version[version] = build_ofclasses(version)
+        for name, ofclasses in modules.items():
+            args = args_by_module.get(name, {})
+            render(os.path.join(subdir, name + '.py'), template_name='module.py',
+                   version=version, ofclasses=ofclasses, modules=modules.keys(),
+                   **args)
diff --git a/py_gen/templates/init.py b/py_gen/templates/init.py
index 3b73baa..aa968b6 100644
--- a/py_gen/templates/init.py
+++ b/py_gen/templates/init.py
@@ -29,17 +29,10 @@
 
 :: include('_autogen.py')
 
-import action, common, const, message
-:: if version >= 2:
-import instruction
-:: #endif
-:: if version >= 3:
-import oxm
-:: #endif
-:: if version >= 4:
-import meter_band
-import bsn_tlv
-:: #endif
+import const
+:: for module in modules:
+import ${module}
+:: #endfor
 from const import *
 from common import *
 from loxi import ProtocolError
diff --git a/py_gen/templates/module.py b/py_gen/templates/module.py
index dfe23e8..331044d 100644
--- a/py_gen/templates/module.py
+++ b/py_gen/templates/module.py
@@ -34,20 +34,9 @@
 import struct
 import loxi
 import const
-import common
-import action
-:: if version >= OFVersions.VERSION_1_1:
-import instruction
-:: #endif
-:: if version >= OFVersions.VERSION_1_2:
-import oxm
-:: #endif
-:: if version >= OFVersions.VERSION_1_3:
-import action_id
-import instruction_id
-import meter_band
-import bsn_tlv
-:: #endif
+:: for module in modules:
+import ${module}
+:: #endfor
 import util
 import loxi.generic_util
 
diff --git a/test_data/of13/oxm_mpls_bos.data b/test_data/of13/oxm_mpls_bos.data
new file mode 100644
index 0000000..8d43f33
--- /dev/null
+++ b/test_data/of13/oxm_mpls_bos.data
@@ -0,0 +1,7 @@
+-- binary
+80 00 # class
+48 # type/masked
+01 # length
+01 # value
+-- python
+ofp.oxm.mpls_bos(value=01)
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index f7eb79c..48cb447 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -68,8 +68,12 @@
         dissect_of_match_v1_v1(reader, subtree:add("of_match"))
     elseif version == 2 then
         dissect_of_match_v2_v2(reader, subtree:add("of_match"))
-    elseif version >= 3 then
+    elseif version == 3 then
         dissect_of_match_v3_v3(reader, subtree:add("of_match"))
+    elseif version == 4 then
+        dissect_of_match_v3_v4(reader, subtree:add("of_match"))
+    else
+        error("Unsupported match version")
     end
 end
 
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
index 9ce51d2..ef826c1 100644
--- a/wireshark_gen/templates/openflow.lua
+++ b/wireshark_gen/templates/openflow.lua
@@ -52,7 +52,7 @@
 
 :: for version, ofproto in ir.items():
 :: for enum in ofproto.enums:
-local enum_v${version.wire_version}_${enum.name} = {
+enum_v${version.wire_version}_${enum.name} = {
 :: for (name, value) in enum.values:
     [${value}] = "${name}",
 :: #endfor