Merge into master from pull request #372:
In ports 512 - merge into master (https://github.com/floodlight/loxigen/pull/372)
diff --git a/c_gen/c_code_gen.py b/c_gen/c_code_gen.py
index 968d939..a9a0576 100644
--- a/c_gen/c_code_gen.py
+++ b/c_gen/c_code_gen.py
@@ -616,19 +616,26 @@
    uint8_t addr[OF_IPV6_BYTES];
 } of_ipv6_t;
 
+typedef struct of_bitmap_512_s {
+    uint64_t words[8];
+} of_bitmap_512_t;
+
 extern const of_mac_addr_t of_mac_addr_all_ones;
-extern const of_mac_addr_t of_mac_addr_all_zeros;
+extern const of_mac_addr_t of_mac_addr_all_zeroes;
 
 extern const of_ipv6_t of_ipv6_all_ones;
 extern const of_ipv6_t of_ipv6_all_zeros;
 
+extern const of_bitmap_512_t of_bitmap_512_all_ones;
+extern const of_bitmap_512_t of_bitmap_512_all_zeroes;
+
 /**
  * Generic zero and all-ones values of size 16 bytes.
  *
- * IPv6 is longest data type we worry about for comparisons
+ * bitmap_512 is longest data type we worry about for comparisons
  */
-#define of_all_zero_value of_ipv6_all_zeros
-#define of_all_ones_value of_ipv6_all_ones
+#define of_all_zero_value of_bitmap_512_all_zeroes
+#define of_all_ones_value of_bitmap_512_all_ones
 
 /**
  * Non-zero/all ones check for arbitrary type of size <= 16 bytes
diff --git a/c_gen/c_match.py b/c_gen/c_match.py
index a703e4f..ccc503d 100644
--- a/c_gen/c_match.py
+++ b/c_gen/c_match.py
@@ -963,55 +963,31 @@
  */
 
 static inline int
-of_match_more_specific(of_match_t *entry, of_match_t *query)
+of_match_more_specific(const of_match_t *entry, const of_match_t *query)
 {
-    of_match_fields_t *q_m, *e_m;  /* Short hand for masks, fields */
-    of_match_fields_t *q_f, *e_f;
+    LOCI_ASSERT(sizeof(of_match_fields_t) % sizeof(uint8_t) == 0);
 
-    q_m = &query->masks;
-    e_m = &entry->masks;
-    q_f = &query->fields;
-    e_f = &entry->fields;
-""")
-    for key, entry in match.of_match_members.items():
-        q_m = "&q_m->%s" % key
-        e_m = "&e_m->%s" % key
-        q_f = "&q_f->%s" % key
-        e_f = "&e_f->%s" % key
-        if entry["m_type"] == "of_ipv6_t":
-            comp = "OF_MORE_SPECIFIC_IPV6"
-            match_type = "OF_RESTRICTED_MATCH_IPV6"
-        elif entry["m_type"] == "of_mac_addr_t":
-            comp = "OF_MORE_SPECIFIC_MAC_ADDR"
-            match_type = "OF_RESTRICTED_MATCH_MAC_ADDR"
-        elif entry["m_type"] == "of_bitmap_128_t":
-            comp = "OF_MORE_SPECIFIC_BITMAP_128"
-            match_type = "OF_RESTRICTED_MATCH_BITMAP_128"
-        else: # Integer
-            comp = "OF_MORE_SPECIFIC_INT"
-            match_type = "OF_RESTRICTED_MATCH_INT"
-            q_m = "q_m->%s" % key
-            e_m = "e_m->%s" % key
-            q_f = "q_f->%s" % key
-            e_f = "e_f->%s" % key
-        out.write("""
-    /* Mask and values for %(key)s */
-    if (!%(comp)s(%(e_m)s, %(q_m)s)) {
-        return 0;
-    }
-    if (!%(match_type)s(%(e_f)s, %(q_f)s,
-            %(q_m)s)) {
-        return 0;
-    }
-""" % dict(match_type=match_type, comp=comp, q_f=q_f, e_f=e_f,
-           q_m=q_m, e_m=e_m, key=key))
+    /* Short hand for masks, fields */
+    const uint8_t *qm = (const uint8_t *)&query->masks;
+    const uint8_t *em = (const uint8_t *)&entry->masks;
+    const uint8_t *qf = (const uint8_t *)&query->fields;
+    const uint8_t *ef = (const uint8_t *)&entry->fields;
 
-    out.write("""
+    int i;
+    for (i = 0; i < sizeof(of_match_fields_t)/sizeof(uint8_t); i++) {
+        if (qm[i] & ~em[i]) {
+            /* Query mask has a bit set that isn't set in the entry mask */
+            return 0;
+        }
+
+        if ((qf[i] ^ ef[i]) & qm[i]) {
+            /* Query and entry disagree on a field bit */
+            return 0;
+        }
+    }
+
     return 1;
 }
-""")
-
-    out.write("""
 
 /**
  * Do two entries overlap?
@@ -1022,42 +998,24 @@
  */
 
 static inline int
-of_match_overlap(of_match_t *match1, of_match_t *match2)
+of_match_overlap(const of_match_t *match1, const of_match_t *match2)
 {
-    of_match_fields_t *m1, *m2;  /* Short hand for masks, fields */
-    of_match_fields_t *f1, *f2;
+    LOCI_ASSERT(sizeof(of_match_fields_t) % sizeof(uint8_t) == 0);
 
-    m1 = &match1->masks;
-    m2 = &match2->masks;
-    f1 = &match1->fields;
-    f2 = &match2->fields;
-""")
-    for key, entry in match.of_match_members.items():
-        m1 = "&m1->%s" % key
-        m2 = "&m2->%s" % key
-        f1 = "&f1->%s" % key
-        f2 = "&f2->%s" % key
-        if entry["m_type"] == "of_ipv6_t":
-            check = "OF_OVERLAP_IPV6"
-        elif entry["m_type"] == "of_mac_addr_t":
-            check = "OF_OVERLAP_MAC_ADDR"
-        elif entry["m_type"] == "of_bitmap_128_t":
-            check = "OF_OVERLAP_BITMAP_128"
-        else: # Integer
-            check = "OF_OVERLAP_INT"
-            m1 = "m1->%s" % key
-            m2 = "m2->%s" % key
-            f1 = "f1->%s" % key
-            f2 = "f2->%s" % key
-        out.write("""
-    /* Check overlap for %(key)s */
-    if (!%(check)s(%(f1)s, %(f2)s,
-        %(m2)s, %(m1)s)) {
-        return 0; /* This field differentiates; all done */
+    /* Short hand for masks, fields */
+    const uint8_t *m1 = (const uint8_t *)&match1->masks;
+    const uint8_t *m2 = (const uint8_t *)&match2->masks;
+    const uint8_t *f1 = (const uint8_t *)&match1->fields;
+    const uint8_t *f2 = (const uint8_t *)&match2->fields;
+
+    int i;
+    for (i = 0; i < sizeof(of_match_fields_t)/sizeof(uint8_t); i++) {
+        if ((f1[i] ^ f2[i]) & (m1[i] & m2[i])) {
+            /* Matches disagree on a field bit they both qualify on */
+            return 0;
+        }
     }
-""" % dict(check=check, f1=f1, f2=f2, m1=m1, m2=m2, key=key))
 
-    out.write("""
     return 1; /* No field differentiates matches */
 }
 """)
diff --git a/c_gen/c_test_gen.py b/c_gen/c_test_gen.py
index 5342a42..955f34f 100644
--- a/c_gen/c_test_gen.py
+++ b/c_gen/c_test_gen.py
@@ -105,6 +105,7 @@
         # BSN extensions
         of_bsn_vport_q_in_q_t="vport",
         of_bitmap_128_t="bitmap_128",
+        of_bitmap_512_t="bitmap_512",
         of_checksum_128_t="checksum_128",
         )
 
@@ -120,7 +121,7 @@
 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", "of_bitmap_128_t", "of_checksum_128_t",
-                "of_str64_t"]
+                "of_str64_t", "of_bitmap_512_t"]
 
 scalar_types = integer_types[:]
 scalar_types.extend(string_types)
diff --git a/c_gen/of_g_legacy.py b/c_gen/of_g_legacy.py
index 87e0680..9c0722c 100644
--- a/c_gen/of_g_legacy.py
+++ b/c_gen/of_g_legacy.py
@@ -213,6 +213,7 @@
 #                         short_name="match_v4"),
     of_octets_t = dict(bytes=-1, short_name="octets"),
     of_bitmap_128_t = dict(bytes=16, short_name="bitmap_128"),
+    of_bitmap_512_t = dict(bytes=64, short_name="bitmap_512"),
     of_checksum_128_t = dict(bytes=16, short_name="checksum_128"),
 )
 
@@ -221,7 +222,7 @@
                    "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_ipv4_t", "of_bitmap_128_t", "of_checksum_128_t",
-                   "of_str64_t"]
+                   "of_str64_t", "of_bitmap_512_t"]
 
 ##
 # LOXI identifiers
diff --git a/c_gen/templates/loci_dump.h b/c_gen/templates/loci_dump.h
index 1344565..89c5f2a 100644
--- a/c_gen/templates/loci_dump.h
+++ b/c_gen/templates/loci_dump.h
@@ -99,6 +99,8 @@
 
 #define LOCI_DUMP_checksum_128(writer, cookie, val) writer(cookie, "%016" PRIx64 "%016" PRIx64, (val).hi, (val).lo)
 
+#define LOCI_DUMP_bitmap_512(writer, cookie, val) writer(cookie, "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64, (val).words[7], (val).words[6], (val).words[5], (val).words[4], (val).words[3], (val).words[2], (val).words[1], (val).words[0])
+
 /**
  * Generic version for any object
  */
diff --git a/c_gen/templates/loci_show.h b/c_gen/templates/loci_show.h
index a227645..dc35959 100644
--- a/c_gen/templates/loci_show.h
+++ b/c_gen/templates/loci_show.h
@@ -113,6 +113,8 @@
 
 #define LOCI_SHOW_checksum_128(writer, cookie, val) writer(cookie, "%016" PRIx64 "%016" PRIx64, (val).hi, (val).lo)
 
+#define LOCI_SHOW_bitmap_512(writer, cookie, val) writer(cookie, "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64 "%" PRIx64, (val).words[7], (val).words[6], (val).words[5], (val).words[4], (val).words[3], (val).words[2], (val).words[1], (val).words[0])
+
 /**
  * Generic version for any object
  */
diff --git a/c_gen/templates/loci_strings.c b/c_gen/templates/loci_strings.c
index f546e12..165bf56 100644
--- a/c_gen/templates/loci_strings.c
+++ b/c_gen/templates/loci_strings.c
@@ -69,6 +69,12 @@
     }
 };
 
+const of_bitmap_512_t of_bitmap_512_all_ones = {
+    { -1, -1, -1, -1, -1, -1, -1, -1, }
+};
+
+const of_bitmap_512_t of_bitmap_512_all_zeroes;
+
 /** @var of_error_strings
  * The error string map; use abs value to index
  */
diff --git a/c_gen/templates/of_wire_buf.h b/c_gen/templates/of_wire_buf.h
index 3d38f53..9ade2c4 100644
--- a/c_gen/templates/of_wire_buf.h
+++ b/c_gen/templates/of_wire_buf.h
@@ -888,6 +888,45 @@
 #define of_wire_buffer_checksum_128_set(buf, offset, checksum) \
     (of_wire_buffer_u64_set(buf, offset, checksum.hi), of_wire_buffer_u64_set(buf, offset+8, checksum.lo))
 
+
+/**
+ * Get a bitmap_512 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_bitmap_512_get(of_wire_buffer_t *wbuf, int offset, of_bitmap_512_t *value)
+{
+    OF_WIRE_BUFFER_ACCESS_CHECK(wbuf, offset + (int) sizeof(of_bitmap_512_t));
+    int i;
+    for (i = 0; i < 8; i++) {
+        buf_u64_get(OF_WIRE_BUFFER_INDEX(wbuf, offset+i*8), &value->words[i]);
+    }
+}
+
+/**
+ * Set a bitmap_512 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_bitmap_512_set(of_wire_buffer_t *wbuf, int offset, of_bitmap_512_t value)
+{
+    OF_WIRE_BUFFER_ACCESS_CHECK(wbuf, offset + (int) sizeof(of_bitmap_512_t));
+    int i;
+    for (i = 0; i < 8; i++) {
+        buf_u64_set(OF_WIRE_BUFFER_INDEX(wbuf, offset+i*8), value.words[i]);
+    }
+}
+
 /* Relocate data from start offset to the end of the buffer to a new position */
 static inline void
 of_wire_buffer_move_end(of_wire_buffer_t *wbuf, int start_offset, int new_offset)
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 3f3a5f2..dbb87eb 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -449,10 +449,14 @@
 table_stats_wildcards = JType("int") \
         .op(read='bb.readInt()',
             write='bb.writeInt($name)')
-port_bitmap = JType('OFBitMask128') \
+port_bitmap_128 = JType('OFBitMask128') \
             .op(read='OFBitMask128.read16Bytes(bb)',
                 write='$name.write16Bytes(bb)',
                 default='OFBitMask128.NONE')
+port_bitmap_512 = JType('OFBitMask512') \
+            .op(read='OFBitMask512.read64Bytes(bb)',
+                write='$name.write64Bytes(bb)',
+                default='OFBitMask512.NONE')
 table_id = JType("TableId") \
         .op(read='TableId.readByte(bb)',
             write='$name.writeByte(bb)',
@@ -573,7 +577,8 @@
         'of_wc_bmap_t': flow_wildcards,
         'of_oxm_t': oxm,
         'of_meter_features_t': meter_features,
-        'of_bitmap_128_t': port_bitmap,
+        'of_bitmap_128_t': port_bitmap_128,
+        'of_bitmap_512_t': port_bitmap_512,
         'of_checksum_128_t': u128,
         'of_bsn_vport_t': bsn_vport,
         'of_table_desc_t': table_desc,
@@ -637,8 +642,11 @@
         'of_oxm_pbb_uca' : { 'value' : boolean_value },
         'of_oxm_pbb_uca_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 },
+        'of_oxm_bsn_in_ports_128' : { 'value': port_bitmap_128 },
+        'of_oxm_bsn_in_ports_128_masked' : { 'value': port_bitmap_128, 'value_mask': port_bitmap_128 },
+
+        'of_oxm_bsn_in_ports_512' : { 'value': port_bitmap_512 },
+        'of_oxm_bsn_in_ports_512_masked' : { 'value': port_bitmap_512, 'value_mask': port_bitmap_512 },
 
         'of_oxm_bsn_lag_id' : { 'value' : lag_id },
         'of_oxm_bsn_lag_id_masked' : { 'value' : lag_id, 'value_mask' : lag_id },
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 e956f78..931211f 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
@@ -14,6 +14,7 @@
 import org.projectfloodlight.openflow.types.LagId;
 import org.projectfloodlight.openflow.types.MacAddress;
 import org.projectfloodlight.openflow.types.OFBitMask128;
+import org.projectfloodlight.openflow.types.OFBitMask512;
 import org.projectfloodlight.openflow.types.OFBooleanValue;
 import org.projectfloodlight.openflow.types.OFMetadata;
 import org.projectfloodlight.openflow.types.OFPort;
@@ -182,7 +183,7 @@
             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 = 
+    public final static MatchField<U64> TUNNEL_ID =
             new MatchField<U64>("tunnel_id", MatchFields.TUNNEL_ID);
 
     public final static MatchField<U16> IPV6_EXTHDR =
@@ -190,7 +191,7 @@
 
     public final static MatchField<OFBooleanValue> PBB_UCA =
             new MatchField<OFBooleanValue>("pbb_uca", MatchFields.PBB_UCA);
-  
+
     public final static MatchField<IPv4Address> TUNNEL_IPV4_SRC =
             new MatchField<IPv4Address>("tunnel_ipv4_src", MatchFields.TUNNEL_IPV4_SRC,
                     new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.IPv4));
@@ -202,6 +203,9 @@
     public final static MatchField<OFBitMask128> BSN_IN_PORTS_128 =
             new MatchField<OFBitMask128>("bsn_in_ports_128", MatchFields.BSN_IN_PORTS_128);
 
+    public final static MatchField<OFBitMask512> BSN_IN_PORTS_512 =
+            new MatchField<OFBitMask512>("bsn_in_ports_512", MatchFields.BSN_IN_PORTS_512);
+
     public final static MatchField<LagId> BSN_LAG_ID =
             new MatchField<LagId>("bsn_lag_id", MatchFields.BSN_LAG_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 28b6f8c..3a0ec89 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
@@ -45,6 +45,7 @@
     TUNNEL_IPV4_SRC,
     TUNNEL_IPV4_DST,
     BSN_IN_PORTS_128,
+    BSN_IN_PORTS_512,
     BSN_LAG_ID,
     BSN_VRF,
     BSN_GLOBAL_VRF_ALLOWED,
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask512.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask512.java
new file mode 100644
index 0000000..3fe9b88
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask512.java
@@ -0,0 +1,205 @@
+package org.projectfloodlight.openflow.types;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+
+import com.google.common.hash.PrimitiveSink;
+
+public class OFBitMask512 implements OFValueType<OFBitMask512> {
+
+    static final int LENGTH = 64;
+
+    private final long raw1;
+    private final long raw2;
+    private final long raw3;
+    private final long raw4;
+    private final long raw5;
+    private final long raw6;
+    private final long raw7;
+    private final long raw8;
+
+    public static final OFBitMask512 ALL = new OFBitMask512(-1, -1, -1, -1,
+                                                            -1, -1, -1, -1);
+    public static final OFBitMask512 NONE = new OFBitMask512(0, 0, 0, 0,
+                                                             0, 0, 0, 0);
+
+    public static final OFBitMask512 NO_MASK = ALL;
+    public static final OFBitMask512 FULL_MASK = NONE;
+
+    private OFBitMask512(long raw1, long raw2, long raw3, long raw4,
+                         long raw5, long raw6, long raw7, long raw8) {
+        this.raw1 = raw1;
+        this.raw2 = raw2;
+        this.raw3 = raw3;
+        this.raw4 = raw4;
+        this.raw5 = raw5;
+        this.raw6 = raw6;
+        this.raw7 = raw7;
+        this.raw8 = raw8;
+    }
+
+    public static OFBitMask512 of(long raw1, long raw2, long raw3, long raw4,
+                                  long raw5, long raw6, long raw7, long raw8) {
+        if (raw1 == -1 && raw2 == -1 && raw3 == -1 && raw4 == -1
+                && raw5 == -1 && raw6 == -1 && raw7 == -1 && raw8 == -1)
+            return ALL;
+        if (raw1 == 0 && raw2 == 0 && raw3 == 0 && raw4 == 0
+                && raw5 == 0 && raw6 == 0 && raw7 == 0 && raw8 == 0)
+            return NONE;
+        return new OFBitMask512(raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8);
+    }
+
+    @Override
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public OFBitMask512 applyMask(OFBitMask512 mask) {
+        return of(this.raw1 & mask.raw1, this.raw2 & mask.raw2,
+                  this.raw3 & mask.raw3, this.raw4 & mask.raw4,
+                  this.raw5 & mask.raw5, this.raw6 & mask.raw6,
+                  this.raw7 & mask.raw7, this.raw8 & mask.raw8);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (raw1 ^ (raw1 >>> 32));
+        result = prime * result + (int) (raw2 ^ (raw2 >>> 32));
+        result = prime * result + (int) (raw3 ^ (raw3 >>> 32));
+        result = prime * result + (int) (raw4 ^ (raw4 >>> 32));
+        result = prime * result + (int) (raw5 ^ (raw5 >>> 32));
+        result = prime * result + (int) (raw6 ^ (raw6 >>> 32));
+        result = prime * result + (int) (raw7 ^ (raw7 >>> 32));
+        result = prime * result + (int) (raw8 ^ (raw8 >>> 32));
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        OFBitMask512 other = (OFBitMask512) obj;
+        if (raw1 != other.raw1) return false;
+        if (raw2 != other.raw2) return false;
+        if (raw3 != other.raw3) return false;
+        if (raw4 != other.raw4) return false;
+        if (raw5 != other.raw5) return false;
+        if (raw6 != other.raw6) return false;
+        if (raw7 != other.raw7) return false;
+        if (raw8 != other.raw8) return false;
+        return true;
+    }
+
+    protected static boolean isBitOn(long raw1, long raw2, long raw3, long raw4,
+                                     long raw5, long raw6, long raw7, long raw8, int bit) {
+        if (bit < 0 || bit >= 512)
+            throw new IndexOutOfBoundsException();
+        long word;
+        if (bit < 64) {
+            word = raw8;
+        } else if (bit < 128) {
+            word = raw7;
+            bit -= 64;
+        } else if (bit < 128) {
+            word = raw6;
+            bit -= 128;
+        } else if (bit < 128) {
+            word = raw5;
+            bit -= 192;
+        } else if (bit < 128) {
+            word = raw4;
+            bit -= 256;
+        } else if (bit < 128) {
+            word = raw3;
+            bit -= 320;
+        } else if (bit < 128) {
+            word = raw2;
+            bit -= 384;
+        } else {
+            word = raw1;
+            bit -= 448;
+        }
+        return (word & ((long)1 << bit)) != 0;
+    }
+
+    public void write64Bytes(ChannelBuffer cb) {
+        cb.writeLong(raw1);
+        cb.writeLong(raw2);
+        cb.writeLong(raw3);
+        cb.writeLong(raw4);
+        cb.writeLong(raw5);
+        cb.writeLong(raw6);
+        cb.writeLong(raw7);
+        cb.writeLong(raw8);
+    }
+
+    public static OFBitMask512 read64Bytes(ChannelBuffer cb) {
+        long raw1 = cb.readLong();
+        long raw2 = cb.readLong();
+        long raw3 = cb.readLong();
+        long raw4 = cb.readLong();
+        long raw5 = cb.readLong();
+        long raw6 = cb.readLong();
+        long raw7 = cb.readLong();
+        long raw8 = cb.readLong();
+        return of(raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8);
+    }
+
+    public boolean isOn(int bit) {
+        return isBitOn(raw1, raw2, raw3, raw4, raw5, raw6, raw7, raw8, bit);
+    }
+
+    @Override
+    public String toString() {
+        return (String.format("%64s", Long.toBinaryString(raw8))
+                + String.format("%64s", Long.toBinaryString(raw7))
+                + String.format("%64s", Long.toBinaryString(raw6))
+                + String.format("%64s", Long.toBinaryString(raw5))
+                + String.format("%64s", Long.toBinaryString(raw4))
+                + String.format("%64s", Long.toBinaryString(raw3))
+                + String.format("%64s", Long.toBinaryString(raw2))
+                + String.format("%64s", Long.toBinaryString(raw1))).replaceAll(" ", "0");
+    }
+
+    @Override
+    public int compareTo(OFBitMask512 o) {
+        long c = this.raw1 - o.raw1;
+        if (c != 0)
+            return Long.signum(c);
+        c = this.raw2 - o.raw2;
+        if (c != 0)
+            return Long.signum(c);
+        c = this.raw3 - o.raw3;
+        if (c != 0)
+            return Long.signum(c);
+        c = this.raw4 - o.raw4;
+        if (c != 0)
+            return Long.signum(c);
+        c = this.raw5 - o.raw5;
+        if (c != 0)
+            return Long.signum(c);
+        c = this.raw6 - o.raw6;
+        if (c != 0)
+            return Long.signum(c);
+        c = this.raw7 - o.raw7;
+        if (c != 0)
+            return Long.signum(c);
+        return Long.signum(this.raw8 - o.raw8);
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+        sink.putLong(raw1);
+        sink.putLong(raw2);
+        sink.putLong(raw3);
+        sink.putLong(raw4);
+        sink.putLong(raw5);
+        sink.putLong(raw6);
+        sink.putLong(raw7);
+        sink.putLong(raw8);
+    }
+
+}
diff --git a/loxi_ir/ir_offset.py b/loxi_ir/ir_offset.py
index db55f24..5eff8e0 100644
--- a/loxi_ir/ir_offset.py
+++ b/loxi_ir/ir_offset.py
@@ -109,6 +109,7 @@
     of_octets_t = (0, False),
     of_bitmap_128_t = (16, True),
     of_checksum_128_t = (16, True),
+    of_bitmap_512_t = (64, True),
 )
 
 def type_dec_to_count_base(m_type):
diff --git a/openflow_input/bsn_in_ports b/openflow_input/bsn_in_ports
index 819bdde..bb4c030 100644
--- a/openflow_input/bsn_in_ports
+++ b/openflow_input/bsn_in_ports
@@ -60,3 +60,14 @@
     of_bitmap_128_t value;
     of_bitmap_128_t value_mask;
 };
+
+struct of_oxm_bsn_in_ports_512 : of_oxm {
+    uint32_t type_len == 0x00032640;
+    of_bitmap_512_t value;
+};
+
+struct of_oxm_bsn_in_ports_512_masked : of_oxm {
+    uint32_t type_len == 0x00032780;
+    of_bitmap_512_t value;
+    of_bitmap_512_t value_mask;
+};
diff --git a/py_gen/oftype.py b/py_gen/oftype.py
index 51b8e13..3893865 100644
--- a/py_gen/oftype.py
+++ b/py_gen/oftype.py
@@ -116,6 +116,11 @@
         init='0',
         pack='util.pack_checksum_128(%s)',
         unpack="util.unpack_checksum_128(%s)"),
+
+    'of_bitmap_512_t': OFTypeData(
+        init='set()',
+        pack='util.pack_bitmap_512(%s)',
+        unpack="util.unpack_bitmap_512(%s)"),
 }
 
 ## Fixed length strings
diff --git a/py_gen/templates/util.py b/py_gen/templates/util.py
index 85181dc..7558576 100644
--- a/py_gen/templates/util.py
+++ b/py_gen/templates/util.py
@@ -173,6 +173,28 @@
         x >>= 1
     return value
 
+def pack_bitmap_512(value):
+    words = [0] * 8
+    for v in value:
+        assert v < 512
+        words[7-v/64] |= 1 << (v % 64)
+    return struct.pack("!8Q", *words)
+
+def unpack_bitmap_512(reader):
+    words = reader.read("!8Q")
+    x = 0l
+    for word in words:
+        x <<= 64
+        x |= word
+    i = 0
+    value = set()
+    while x != 0:
+        if x & 1 == 1:
+            value.add(i)
+        i += 1
+        x >>= 1
+    return value
+
 def pack_checksum_128(value):
     return struct.pack("!QQ", (value >> 64) & MASK64, value & MASK64)
 
diff --git a/py_gen/tests/of13.py b/py_gen/tests/of13.py
index c5a16b2..c99ee34 100644
--- a/py_gen/tests/of13.py
+++ b/py_gen/tests/of13.py
@@ -126,5 +126,18 @@
             else:
                 fn()
 
+class TestUtils(unittest.TestCase):
+    def check_bitmap_512(self, value, data):
+        self.assertEquals(data, ofp.util.pack_bitmap_512(set(value)))
+        self.assertEquals(ofp.util.unpack_bitmap_512(OFReader(data)), set(value))
+
+    def test_bitmap_512(self):
+        self.check_bitmap_512([0], "\x00" * 63 + "\x01")
+        self.check_bitmap_512([8], "\x00" * 62 + "\x01\x00")
+        self.check_bitmap_512([63], "\x00" * 56 + "\x80" + "\x00" * 7)
+        self.check_bitmap_512([64], "\x00" * 55 + "\x01" + "\x00" * 8)
+        self.check_bitmap_512([511], "\x80" + "\x00" * 63)
+        self.check_bitmap_512([5, 67, 90], "\x00" * 52 + "\x04\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x20")
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/test_data/of13/oxm_bsn_in_ports_masked_512.data b/test_data/of13/oxm_bsn_in_ports_masked_512.data
new file mode 100644
index 0000000..82cc45c
--- /dev/null
+++ b/test_data/of13/oxm_bsn_in_ports_masked_512.data
@@ -0,0 +1,36 @@
+-- binary
+00 03 # class
+27 # type/masked
+80 # length
+00 00 00 00 00 00 00 00 # value
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+00 00 00 00 00 00 00 00 # ...
+7f ff ff ff ff ff ff ff # mask - Only ports 0, 17, 96, 511 are selected (and thus are zero)
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff ff ff ff ff ff # ...
+ff ff ff fe ff ff ff ff # ...
+ff ff ff ff ff fd ff fe # ...
+-- python
+ofp.oxm.bsn_in_ports_512_masked(set(), set(range(0,512)) - set((0, 17, 96, 511)))
+-- c
+obj = of_oxm_bsn_in_ports_512_masked_new(OF_VERSION_1_3);
+{
+    of_bitmap_512_t bmap = { { 0, 0, 0, 0, 0, 0, 0, 0 } };
+    of_oxm_bsn_in_ports_512_masked_value_set(obj, bmap);
+}
+{
+    of_bitmap_512_t bmap = { { 0x7fffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xfffffffeffffffff, 0xfffffffffffdfffe } };
+    of_oxm_bsn_in_ports_512_masked_value_mask_set(obj, bmap);
+}
+-- java
+OFPortMap portmap = OFPortMap.ofPorts(OFPort.of(0), OFPort.of(17), OFPort.of(96));
+builder.setValue(portmap.getValue());
+builder.setMask(portmap.getMask());
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index 48cb447..ad0f0c2 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -49,6 +49,10 @@
     read_scalar(reader, subtree, field_name, 16)
 end
 
+function read_of_bitmap_512_t(reader, version, subtree, field_name)
+    read_scalar(reader, subtree, field_name, 64)
+end
+
 function read_of_checksum_128_t(reader, version, subtree, field_name)
     read_scalar(reader, subtree, field_name, 16)
 end