--- openflow-2012-12-05.h	2015-07-23 09:54:17.344479370 -0700
+++ openflow-2012-10-01.h	2015-07-23 09:54:17.348479370 -0700
@@ -1893,6 +1893,11 @@
      * The reply body is an array of struct ofp_queue_desc. */
     OFPMP_QUEUE_DESC = 15,
 
+    /* Flow monitors.
+     * The request body is struct ofp_flow_monitor_request.
+     * The reply body is an array of struct ofp_flow_update_header. */
+    OFPMP_FLOW_MONITOR = 16,
+
     /* Experimenter extension.
      * The request and reply bodies begin with
      * struct ofp_experimenter_multipart_header.
@@ -2498,6 +2503,154 @@
 };
 OFP_ASSERT(sizeof(struct ofp_queue_stats) == 48);
 
+/* Body for ofp_multipart_request of type OFPMP_FLOW_MONITOR.
+ *
+ * The OFPMP_FLOW_MONITOR request's body consists of an array of zero or more
+ * instances of this structure.  The request arranges to monitor the flows
+ * that match the specified criteria, which are interpreted in the same way as
+ * for OFPMP_FLOW.
+ *
+ * 'id' identifies a particular monitor for the purpose of allowing it to be
+ * canceled later with OFP_FLOW_MONITOR_CANCEL.  'id' must be unique among
+ * existing monitors that have not already been canceled.
+ *
+ * The reply includes the initial flow matches for monitors that have the
+ * OFPFMF_INITIAL flag set.  No single flow will be included in the reply more
+ * than once, even if more than one requested monitor matches that flow.  The
+ * reply will be empty if none of the monitors has OFPFMF_INITIAL set or if none
+ * of the monitors initially matches any flows.
+ *
+ * For OFPFMF_ADD, an event will be reported if 'out_port' matches against the
+ * actions of the flow being added or, for a flow that is replacing an existing
+ * flow, if 'out_port' matches against the actions of the flow being replaced.
+ * For OFPFMF_DELETE, 'out_port' matches against the actions of a flow being
+ * deleted.  For OFPFMF_MODIFY, an event will be reported if 'out_port' matches
+ * either the old or the new actions. */
+struct ofp_flow_monitor_request {
+    uint32_t id;                /* Controller-assigned ID for this monitor. */
+    uint32_t flags;             /* OFFMF_*. */
+    uint32_t out_port;          /* Required output port, if not OFPP_ANY. */
+    uint8_t table_id;           /* One table's ID or 0xff for all tables. */
+    uint8_t command;            /* One of OFPFMC_*. */
+    uint8_t zeros[3];           /* Align to 64 bits (must be zero). */
+    struct ofp_match match;     /* Fields to match. Variable size. */
+};
+OFP_ASSERT(sizeof(struct ofp_flow_monitor_request) == 24);
+
+/* Flow monitor commands */
+enum ofp_flow_monitor_command {
+    OFPFMC_ADD    = 0,       /* New flow monitor. */
+    OFPFMC_MODIFY = 1,       /* Modify flow monitor. */
+    OFPFMC_DELETE = 2,       /* Delete flow monitor. */
+};
+
+/* 'flags' bits in struct of_flow_monitor_request. */
+enum ofp_flow_monitor_flags {
+    /* When to send updates. */
+    OFPFMF_INITIAL = 1 << 0,     /* Initially matching flows. */
+    OFPFMF_ADD = 1 << 1,         /* New matching flows as they are added. */
+    OFPFMF_DELETE = 1 << 2,      /* Old matching flows as they are removed. */
+    OFPFMF_MODIFY = 1 << 3,      /* Matching flows as they are changed. */
+
+    /* What to include in updates. */
+    OFPFMF_INSTRUCTIONS = 1 << 4,/* If set, instructions are included. */
+    OFPFMF_OWN = 1 << 5,         /* If set, include own changes in full. */
+};
+
+/* OFPMP_FLOW_MONITOR reply header.
+ *
+ * The body of an OFPMP_FLOW_MONITOR reply is an array of variable-length
+ * structures, each of which begins with this header.  The 'length' member may
+ * be used to traverse the array, and the 'event' member may be used to
+ * determine the particular structure.
+ *
+ * Every instance is a multiple of 8 bytes long. */
+struct ofp_flow_update_header {
+    uint16_t length;            /* Length of this entry. */
+    uint16_t event;             /* One of OFPFME_*. */
+    /* ...other data depending on 'event'... */
+};
+OFP_ASSERT(sizeof(struct ofp_flow_update_header) == 4);
+
+/* 'event' values in struct ofp_flow_update_header. */
+enum ofp_flow_update_event {
+    /* struct ofp_flow_update_full. */
+    OFPFME_ADDED = 0,            /* Flow was added. */
+    OFPFME_DELETED = 1,          /* Flow was deleted. */
+    OFPFME_MODIFIED = 2,         /* Flow instructions were changed. */
+
+    /* struct ofp_flow_update_abbrev. */
+    OFPFME_ABBREV = 3,           /* Abbreviated reply. */
+
+    /* struct ofp_flow_update_header. */
+    OFPFME_PAUSED = 4,          /* Monitoring paused (out of buffer space). */
+    OFPFME_RESUMED = 5,         /* Monitoring resumed. */
+};
+
+/* OFPMP_FLOW_MONITOR reply for OFPFME_ADDED, OFPFME_DELETED, and
+ * OFPFME_MODIFIED. */
+struct ofp_flow_update_full {
+    uint16_t length;            /* Length is 24. */
+    uint16_t event;             /* One of OFPFME_*. */
+    uint64_t cookie;            /* Opaque controller-issued identifier. */
+    uint8_t table_id;           /* ID of flow's table. */
+    uint8_t reason;             /* OFPRR_* for OFPFME_DELETED, else zero. */
+    uint16_t idle_timeout;      /* Number of seconds idle before expiration. */
+    uint16_t hard_timeout;      /* Number of seconds before expiration. */
+    uint16_t priority;          /* Priority of the entry. */
+    uint8_t zeros[4];           /* Reserved, currently zeroed. */
+    struct ofp_match match;     /* Fields to match. Variable size. */
+    /*     Instruction set.
+     *     If OFPFMF_ACTIONS was not specified, or 'event' is
+     *     OFPFME_DELETED, no instructions are included.
+     */
+    //struct ofp_instruction instructions[0];
+};
+OFP_ASSERT(sizeof(struct ofp_flow_update_full) == 32);
+
+/* OFPMP_FLOW_MONITOR reply for OFPFME_ABBREV.
+ *
+ * When the controller does not specify OFPFMF_OWN in a monitor request, any
+ * flow tables changes due to the controller's own requests (on the same
+ * OpenFlow channel) will be abbreviated, when possible, to this form, which
+ * simply specifies the 'xid' of the OpenFlow request (e.g. an OFPT_FLOW_MOD)
+ * that caused the change.
+ *
+ * Some changes cannot be abbreviated and will be sent in full:
+ *
+ *   - Changes that only partially succeed.  This can happen if, for example,
+ *     a flow_mod with type OFPFC_MODIFY affects multiple flows, but only some
+ *     of those modifications succeed (e.g. due to hardware limitations).
+ *
+ *     This cannot occur with the current implementation of the Open vSwitch
+ *     software datapath.  It could happen with other datapath implementations.
+ *
+ *   - Changes that race with conflicting changes made by other controllers or
+ *     other flow_mods (not separated by barriers) by the same controller.
+ *
+ *     This cannot occur with the current Open vSwitch implementation
+ *     (regardless of datapath) because Open vSwitch internally serializes
+ *     potentially conflicting changes.
+ *
+ * A flow_mod that does not change the flow table will not trigger any
+ * notification, even an abbreviated one.  For example, a "modify" or "delete"
+ * flow_mod that does not match any flows will not trigger a notification.
+ * Whether an "add" or "modify" that specifies all the same parameters that a
+ * flow already has triggers a notification is unspecified and subject to
+ * change in future versions of Open vSwitch.
+ *
+ * OVS will always send the notifications for a given flow table change before
+ * the reply to a OFPT_BARRIER_REQUEST request that precedes the flow table
+ * change.  Thus, if the controller does not receive an abbreviated
+ * notification for a flow_mod before the next OFPT_BARRIER_REPLY, it will
+ * never receive one. */
+struct ofp_flow_update_abbrev {
+    uint16_t length;            /* Length is 8. */
+    uint16_t event;             /* OFPFME_ABBREV. */
+    uint32_t xid;               /* Controller-specified xid from flow_mod. */
+};
+OFP_ASSERT(sizeof(struct ofp_flow_update_abbrev) == 8);
+
 /* Body for ofp_multipart_request/reply of type OFPMP_EXPERIMENTER. */
 struct ofp_experimenter_multipart_header {
     uint32_t experimenter;    /* Experimenter ID. */
