--- openflow-2012-03-22-2.h	2015-07-23 09:54:17.072479359 -0700
+++ openflow-2012-02-22-2.h	2015-07-23 09:54:17.080479359 -0700
@@ -1399,6 +1399,7 @@
     OFPET_SWITCH_CONFIG_FAILED = 10, /* Switch config request failed. */
     OFPET_ROLE_REQUEST_FAILED  = 11, /* Controller Role request failed. */
     OFPET_METER_MOD_FAILED     = 12, /* Error in meter. */
+    OFPET_TABLE_FEATURES_FAILED = 13, /* Setting table features failed. */
     OFPET_EXPERIMENTER = 0xffff      /* Experimenter error messages. */
 };
 
@@ -1604,6 +1605,12 @@
                                  * for a meter has been exceeded. */
 };
 
+/* ofp_error_msg 'code' values for OFPET_TABLE_FEATURES_FAILED. 'data' contains
+ * at least the first 64 bytes of the failed request. */
+enum ofp_table_features_failed_code {
+    OFPTFFC_ERROR      = 0,      /* Error setting table features. */
+};
+
 /* OFPT_ERROR: Error message (datapath -> controller). */
 struct ofp_error_msg {
     struct ofp_header header;
@@ -1689,6 +1696,14 @@
      * The reply body is struct ofp_meter_features_stats. */
     OFPST_METER_FEATURES,
 
+    /* Table features.
+     * The request body is either empty or contains an array of
+     * struct ofp_table_features containing the controller's
+     * desired view of the switch. If the switch is unable to
+     * set the specified view an error is returned.
+     * The reply body is an array of struct ofp_table_features. */
+    OFPST_TABLE_FEATURES = 12,
+
     /* Experimenter extension.
      * The request and reply bodies begin with
      * struct ofp_experimenter_stats_header.
@@ -1803,34 +1818,68 @@
 };
 OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
 
-/* Body of reply to OFPST_TABLE request. */
-struct ofp_table_stats {
+struct ofp_table_features {
     uint8_t table_id;        /* Identifier of table.  Lower numbered tables
                                 are consulted first. */
     uint8_t pad[7];          /* Align to 64-bits. */
     char name[OFP_MAX_TABLE_NAME_LEN];
-    uint64_t match;          /* Bitmap of (1 << OFPXMT_*) that indicate the
-                                fields the table can match on. */
-    uint64_t wildcards;      /* Bitmap of (1 << OFPXMT_*) wildcards that are
-                                supported by the table. */
-    uint32_t write_actions;  /* Bitmap of OFPAT_* that are supported
-                                by the table with OFPIT_WRITE_ACTIONS. */
-    uint32_t apply_actions;  /* Bitmap of OFPAT_* that are supported
-                                by the table with OFPIT_APPLY_ACTIONS. */
-    uint64_t write_setfields;/* Bitmap of (1 << OFPXMT_*) header fields that
-                                can be set with OFPIT_WRITE_ACTIONS. */
-    uint64_t apply_setfields;/* Bitmap of (1 << OFPXMT_*) header fields that
-                                can be set with OFPIT_APPLY_ACTIONS. */
     uint64_t metadata_match; /* Bits of metadata table can match. */
     uint64_t metadata_write; /* Bits of metadata table can write. */
-    uint32_t instructions;   /* Bitmap of OFPIT_* values supported. */
     uint32_t config;         /* Bitmap of OFPTC_* values */
     uint32_t max_entries;    /* Max number of entries supported. */
+    uint8_t  next_tables_length;     /* Length (bytes) of
+                                        next_tables. */
+    uint8_t pad2[1];
+    uint16_t match_length;           /* Length (bytes) of
+                                        supported_match_hdrs. */
+    uint16_t write_setfields_length; /* Length (bytes) of
+                                        supported_write_setfield_hdrs. */
+    uint16_t apply_setfields_length; /* Length (bytes) of
+                                        supported_apply_setfields_hdrs. */ 
+    uint16_t instructions_length;    /* Length (bytes) of
+                                        supported_instruction_hdrs. */
+    uint16_t write_actions_length;   /* Length (bytes) of
+                                        supported_write_action_hdrs. */
+    uint16_t apply_actions_length;   /* Length (bytes) of
+                                        supported_apply_action_hdrs. */
+    uint8_t pad3[2];
+
+    /***
+     *  ofp_table_features includes seven variable length lists of headers.
+     *  The names and types here are provided for intuition and cannot
+     *  be referenced directly from the C structure.  The actual offsets
+     *  must be calculated from the XXX_length fields, e.g., the offset
+     *  for supported_apply_setfields[] is:
+     *
+     *  sizeof(ofp_table_features) + next_tables_length + match_length +
+     *      write_setfields_length
+     *
+     *  OXM lists includes both 4 byte standard OXM headers and
+     *  8 byte OXM experimental headers
+     *      uint8_t                  next_tables[];
+     *      uint32_t                 supported_match_hdrs[];
+     *      uint32_t                 supported_write_setfields_hdrs[];
+     *      uint32_t                 supported_apply_setfields_hdrs[];
+     *
+     *  Action and instruction lists contain both both standard length
+     *  and experimental length headers of each type
+     *      struct ofp_instruction   supported_instruction_hdrs[];
+     *      struct ofp_action_header supported_write_action_hdrs[];
+     *      struct ofp_action_header supported_apply_action_hdrs[];
+     */
+};
+OFP_ASSERT(sizeof(struct ofp_table_features) == 80);
+
+/* Body of reply to OFPST_TABLE request. */
+struct ofp_table_stats {
+    uint8_t table_id;        /* Identifier of table.  Lower numbered tables
+                                are consulted first. */
+    uint8_t pad[3];          /* Align to 32-bits. */
     uint32_t active_count;   /* Number of active entries. */
     uint64_t lookup_count;   /* Number of packets looked up in table. */
     uint64_t matched_count;  /* Number of packets that hit table. */
 };
-OFP_ASSERT(sizeof(struct ofp_table_stats) == 128);
+OFP_ASSERT(sizeof(struct ofp_table_stats) == 24);
 
 /* Body for ofp_stats_request of type OFPST_PORT. */
 struct ofp_port_stats_request {
