--- openflow-2013-10-15-2.h	2015-07-23 09:54:17.668479383 -0700
+++ openflow-2013-07-05.h	2015-07-23 09:54:17.672479383 -0700
@@ -1168,6 +1168,95 @@
 };
 OFP_ASSERT(sizeof(struct ofp_oxm_experimenter_header) == 8);
 
+/* ## -------------------------- ## */
+/* ## OpenFlow Extensible Stats. ## */
+/* ## -------------------------- ## */
+
+/* Flow statistics structure - list of statistic fields. */
+struct ofp_stats {
+    uint16_t length;           /* Length of ofp_stats (excluding padding) */
+    /* Followed by:
+     *   - Exactly (length - 2) (possibly 0) bytes containing OXS TLVs, then
+     *   - Exactly ((length + 7)/8*8 - length) (between 0 and 7) bytes of
+     *     all-zero bytes
+     * In summary, ofp_stats is padded as needed, to make its overall size
+     * a multiple of 8, to preserve alignement in structures using it.
+     */
+    uint8_t oxs_fields[0];     /* 0 or more OXS stat fields */
+    uint8_t pad[6];            /* Zero bytes - see above for sizing */
+};
+OFP_ASSERT(sizeof(struct ofp_stats) == 8);
+
+/* Components of a OXS TLV header. */
+#define OXS_HEADER__(CLASS, FIELD, RESERVED, LENGTH) \
+    (((CLASS) << 16) | ((FIELD) << 9) | ((RESERVED) << 8) | (LENGTH))
+#define OXS_HEADER(CLASS, FIELD, LENGTH) \
+    OXS_HEADER__(CLASS, FIELD, 0, LENGTH)
+#define OXS_CLASS(HEADER) ((HEADER) >> 16)
+#define OXS_FIELD(HEADER) (((HEADER) >> 9) & 0x7f)
+#define OXS_TYPE(HEADER) (((HEADER) >> 9) & 0x7fffff)
+#define OXS_RESERVED(HEADER) (((HEADER) >> 8) & 1)
+#define OXS_LENGTH(HEADER) ((HEADER) & 0xff)
+
+/* OXS Class IDs.
+ * The high order bit differentiate reserved classes from member classes.
+ * Classes 0x0000 to 0x7FFF are member classes, allocated by ONF.
+ * Classes 0x8000 to 0xFFFE are reserved classes, reserved for standardisation.
+ */
+enum ofp_oxs_class {
+    OFPXSC_OPENFLOW_BASIC = 0x8001,    /* Basic stats class for OpenFlow */
+    OFPXSC_EXPERIMENTER   = 0xFFFF,    /* Experimenter class */
+};
+
+/* OXS flow stat field types for OpenFlow basic class. */
+enum oxs_ofb_stat_fields {
+    OFPXST_OFB_DURATION        = 0,  /* Time flow has been alive. */
+    OFPXST_OFB_FLOW_COUNT      = 1,  /* Number of aggregated flows. */
+    OFPXST_OFB_PACKET_COUNT    = 2,  /* Number of packets in flow. */
+    OFPXST_OFB_BYTE_COUNT      = 3,  /* Number of bytes in flow. */
+};
+
+#define OFPXST_OFB_ALL    ((UINT64_C(1) << 3) - 1)
+
+/* OpenFlow flow duration.
+ * Time flow has been alive in seconds and nanoseconds.
+ *
+ * Format: A pair of 32-bit integer in network byte order.
+ *    First 32-bit number is duration in seconds.
+ *    Second 32-bit number is nanoseconds beyond duration in seconds.
+ * Second number must be set to zero if not supported.
+ */
+#define OXS_OF_DURATION      OXS_HEADER  (0x8001, OFPXST_OFB_DURATION, 8)
+
+/* OpenFlow flow count.
+ * Number of aggregated flows.
+ * Required in \verb|OFPMP_AGGREGATE| replies, undefined in other context.
+ *
+ * Format: 32-bit integer in network byte order.
+ */
+#define OXS_OF_FLOW_COUNT    OXS_HEADER  (0x8001, OFPXST_OFB_FLOW_COUNT, 4)
+
+/* OpenFlow flow packet count.
+ * Number of packets in flow.
+ *
+ * Format: 64-bit integer in network byte order.
+ */
+#define OXS_OF_PACKET_COUNT  OXS_HEADER  (0x8001, OFPXST_OFB_PACKET_COUNT, 8)
+
+/* OpenFlow flow packet count.
+ * Number of bytes in flow.
+ *
+ * Format: 64-bit integer in network byte order.
+ */
+#define OXS_OF_BYTE_COUNT    OXS_HEADER  (0x8001, OFPXST_OFB_BYTE_COUNT, 8)
+
+/* Header for OXS experimenter stat fields. */
+struct ofp_oxs_experimenter_header {
+    uint32_t oxs_header;        /* oxs_class = OFPXSC_EXPERIMENTER */
+    uint32_t experimenter;      /* Experimenter ID. */
+};
+OFP_ASSERT(sizeof(struct ofp_oxs_experimenter_header) == 8);
+
 /* ## ----------------- ## */
 /* ## OpenFlow Actions. ## */
 /* ## ----------------- ## */
@@ -1583,16 +1672,12 @@
     uint8_t reason;           /* One of OFPRR_*. */
     uint8_t table_id;         /* ID of the table */
 
-    uint32_t duration_sec;    /* Time flow was alive in seconds. */
-    uint32_t duration_nsec;   /* Time flow was alive in nanoseconds beyond
-                                 duration_sec. */
     uint16_t idle_timeout;    /* Idle timeout from original flow mod. */
     uint16_t hard_timeout;    /* Hard timeout from original flow mod. */
-    uint64_t packet_count;
-    uint64_t byte_count;
     struct ofp_match match;   /* Description of fields. Variable size. */
+    //struct ofp_stats stats; /* Statistics list. Variable size. */
 };
-OFP_ASSERT(sizeof(struct ofp_flow_removed) == 56);
+OFP_ASSERT(sizeof(struct ofp_flow_removed) == 32);
 
 /* Meter numbering. Flow meters can use any number up to OFPM_MAX. */
 enum ofp_meter {
@@ -1681,6 +1766,10 @@
 };
 OFP_ASSERT(sizeof(struct ofp_meter_mod) == 16);
 
+/* ## ---------------- ## */
+/* ## OpenFlow Errors. ## */
+/* ## ---------------- ## */
+
 /* Values for 'type' in ofp_error_message.  These values are immutable: they
  * will not change in future versions of the protocol (although new values may
  * be added). */
@@ -2009,6 +2098,10 @@
 };
 OFP_ASSERT(sizeof(struct ofp_error_experimenter_msg) == 16);
 
+/* ## -------------------- ## */
+/* ## OpenFlow Multiparts. ## */
+/* ## -------------------- ## */
+
 enum ofp_multipart_type {
     /* Description of this OpenFlow switch.
      * The request body is empty.
@@ -2173,9 +2266,6 @@
     uint16_t length;          /* Length of this entry. */
     uint8_t table_id;         /* ID of table flow came from. */
     uint8_t pad;
-    uint32_t duration_sec;    /* Time flow has been alive in seconds. */
-    uint32_t duration_nsec;   /* Time flow has been alive in nanoseconds beyond
-                                 duration_sec. */
     uint16_t priority;        /* Priority of the entry. */
     uint16_t idle_timeout;    /* Number of seconds idle before expiration. */
     uint16_t hard_timeout;    /* Number of seconds before expiration. */
@@ -2183,13 +2273,12 @@
     uint16_t importance;      /* Eviction precedence. */
     uint8_t pad2[2];          /* Align to 64-bits. */
     uint64_t cookie;          /* Opaque controller-issued identifier. */
-    uint64_t packet_count;    /* Number of packets in flow. */
-    uint64_t byte_count;      /* Number of bytes in flow. */
     struct ofp_match match;   /* Description of fields. Variable size. */
+    //struct ofp_stats stats; /* Statistics list. Variable size. */
     //struct ofp_instruction_header instructions[0];
                               /* Instruction set - 0 or more. */
 };
-OFP_ASSERT(sizeof(struct ofp_flow_stats) == 56);
+OFP_ASSERT(sizeof(struct ofp_flow_stats) == 32);
 
 /* Body for ofp_multipart_request of type OFPMP_AGGREGATE. */
 struct ofp_aggregate_stats_request {
@@ -2214,12 +2303,9 @@
 
 /* Body of reply to OFPMP_AGGREGATE request. */
 struct ofp_aggregate_stats_reply {
-    uint64_t packet_count;    /* Number of packets in flows. */
-    uint64_t byte_count;      /* Number of bytes in flows. */
-    uint32_t flow_count;      /* Number of flows. */
-    uint8_t pad[4];           /* Align to 64 bits. */
+    struct ofp_stats stats;   /* Aggregated statistics list. Variable size. */
 };
-OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
+OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 8);
 
 /* Table Feature property types.
  * Low order bit cleared indicates a property for a regular Flow Entry.
