Merge remote-tracking branch 'upstream/master'
diff --git a/c_gen/c_match.py b/c_gen/c_match.py
index fdb8afe..7fd6a21 100644
--- a/c_gen/c_match.py
+++ b/c_gen/c_match.py
@@ -177,15 +177,19 @@
     of_match_fields_t masks;
 } of_match_t;
 
-/**
- * Mask the values in the match structure according to its fields
+/*
+ * AND 'len' bytes starting from 'value' with the corresponding byte in
+ * 'mask'.
  */
-static inline void of_match_values_mask(of_match_t *match)
+static inline void
+of_memmask(void *value, const void *mask, size_t len)
 {
-    int idx;
+    int i;
+    uint8_t *v = value;
+    const uint8_t *m = mask;
 
-    for (idx = 0; idx < sizeof(of_match_fields_t); idx++) {
-        ((uint8_t *)&match->fields)[idx] &= ((uint8_t *)&match->masks)[idx];
+    for (i = 0; i < len; i++) {
+        v[i] &= m[i];
     }
 }
 
@@ -755,6 +759,7 @@
     if (OF_VARIABLE_IS_NON_ZERO(&dst->masks.%(key)s)) { /* Matching something */
         of_match_v2_%(key)s_get(src, &dst->fields.%(key)s);
     }
+    of_memmask(&dst->fields.%(key)s, &dst->masks.%(key)s, sizeof(&dst->fields.%(key)s));
 """ % dict(ku=key.upper(), key=key))
         else:
             out.write("""
@@ -765,8 +770,6 @@
 """ % dict(ku=key.upper(), key=key))
 
     out.write("""
-    /* Clear values outside of masks */
-    of_match_values_mask(dst);
 
     return OF_ERROR_NONE;
 }
@@ -810,6 +813,7 @@
             of_oxm_%(key)s_masked_value_get(
                 &oxm_entry.%(key)s,
                 &dst->fields.%(key)s);
+            of_memmask(&dst->fields.%(key)s, &dst->masks.%(key)s, sizeof(&dst->fields.%(key)s));
             break;
         case OF_OXM_%(ku)s:
             OF_MATCH_MASK_%(ku)s_EXACT_SET(dst);
@@ -827,9 +831,6 @@
         rv = of_list_oxm_next(&oxm_list, &oxm_entry);
     } /* end OXM iteration */
 
-    /* Clear values outside of masks */
-    of_match_values_mask(dst);
-
     return OF_ERROR_NONE;
 }
 """)
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index 929178d..57d141d 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -274,7 +274,7 @@
     }
 
     /* Restrict values according to masks */
-    of_match_values_mask(match);
+    of_memmask(&match->fields, &match->masks, sizeof(match->fields));
     return value;
 }
 
diff --git a/c_gen/codegen.py b/c_gen/codegen.py
index 77caf2a..9af9223 100644
--- a/c_gen/codegen.py
+++ b/c_gen/codegen.py
@@ -122,7 +122,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:
+        if cls.find("_header") < 0 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/locitest/Makefile b/c_gen/templates/locitest/Makefile
index 70e57ca..00a2f95 100644
--- a/c_gen/templates/locitest/Makefile
+++ b/c_gen/templates/locitest/Makefile
@@ -10,7 +10,7 @@
 all: locitest
 
 locitest: $(LOCITEST_OBJS) loci.a
-	$(CC) $^ -o $@
+	$(CC) -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@
 
 loci.a: $(LOCI_OBJS)
 	ar rc $@ $^
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
index 2e675d4..ee605de 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
@@ -33,6 +33,8 @@
     }
 
     public static VlanVid ofVlan(int vid) {
+        if (vid == NO_MASK.vid)
+            return NO_MASK;
         if ((vid & VALIDATION_MASK) != vid)
             throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
         return new VlanVid((short) vid);
diff --git a/openflow_input/bsn_pktin_flag b/openflow_input/bsn_pktin_flag
new file mode 100644
index 0000000..54c942f
--- /dev/null
+++ b/openflow_input/bsn_pktin_flag
@@ -0,0 +1,45 @@
+// Copyright 2014, 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 2014, 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
+
+// In a realistic switch pipeline there are multiple reasons a given packet
+// should be sent to the controller. The packet-in reason field is only 8 bits,
+// so we use the metadata OXM to carry this information.
+
+enum ofp_bsn_pktin_flag(wire_type=uint64_t, bitmask=True) {
+    OFP_BSN_PKTIN_FLAG_PDU = 0x1,
+    OFP_BSN_PKTIN_FLAG_NEW_HOST = 0x2,
+    OFP_BSN_PKTIN_FLAG_STATION_MOVE = 0x4,
+    OFP_BSN_PKTIN_FLAG_ARP = 0x8,
+    OFP_BSN_PKTIN_FLAG_DHCP = 0x10,
+    OFP_BSN_PKTIN_FLAG_L2_CPU = 0x20,
+    OFP_BSN_PKTIN_FLAG_DEBUG = 0x40,
+    OFP_BSN_PKTIN_FLAG_TTL_EXPIRED = 0x80,
+    OFP_BSN_PKTIN_FLAG_L3_MISS = 0x100,
+    OFP_BSN_PKTIN_FLAG_L3_CPU = 0x200,
+};