[ovs-dev] [PATCH v1 2/2] ofp-monitor: Support flow monitoring for OpenFlow 1.3, 1.4+
Vasu Dasari
vdasari at gmail.com
Tue Aug 24 20:23:55 UTC 2021
Great, thanks!
*Vasu Dasari*
On Tue, Aug 24, 2021 at 4:11 PM Ashish Varma <ashishvarma.ovs at gmail.com>
wrote:
> I will take a look.
>
> Thanks,
> Ashish
>
> On Tue, Aug 24, 2021 at 9:29 AM Vasu Dasari <vdasari at gmail.com> wrote:
>
>> Hi Ben/Ashish,
>>
>> When you get a chance, Can you please take a look at my code?
>>
>> -Vasu
>>
>> *Vasu Dasari*
>>
>>
>> On Thu, Jul 29, 2021 at 10:36 PM Vasu Dasari <vdasari at gmail.com> wrote:
>>
>>> Extended OpenFlow monitoring support
>>> * OpenFlow 1.3 with ONF extensions
>>> * OpenFlow 1.4+ as defined in OpenFlow specification 1.4+.
>>>
>>> ONF extensions are similar to Nicira extensions except for
>>> onf_flow_monitor_request{}
>>> where out_port is defined as 32-bit number OF(1.1) number, oxm match
>>> formats are
>>> used in update and request messages.
>>>
>>> Flow monitoring support in 1.4+ is slightly different from Nicira and ONF
>>> extensions.
>>> * More flow monitoring flags are defined.
>>> * Monitor add/modify/delete command is intruduced in flow_monitor
>>> request message.
>>> * Addition of out_group as part of flow_monitor request message
>>>
>>> Description of changes:
>>> 1. Generate ofp-msgs.inc to be able to support 1.3, 1.4+ flow Monitoring
>>> messages.
>>> include/openvswitch/ofp-msgs.h
>>>
>>> 2. Modify openflow header files with protocol specific headers.
>>> include/openflow/openflow-1.3.h
>>> include/openflow/openflow-1.4.h
>>>
>>> 3. Modify OvS abstraction of openflow headers. ofp-monitor.h leverages
>>> enums
>>> from on nicira extensions for creating protocol abstraction headers.
>>> OF(1.4+)
>>> enums are superset of nicira extensions.
>>> include/openvswitch/ofp-monitor.h
>>>
>>> 4. Changes to these files reflect encoding and decoding of new protocol
>>> messages.
>>> lib/ofp-monitor.c
>>>
>>> 5. Changes to mmodules using ofp-monitor APIs. Most of the changes here
>>> are to
>>> migrate enums from nicira to OF 1.4+ versions.
>>> ofproto/connmgr.c
>>> ofproto/connmgr.h
>>> ofproto/ofproto-provider.h
>>> ofproto/ofproto.c
>>>
>>> 6. Extended protocol decoding tests to verify all protocol versions
>>> FLOW_MONITOR_CANCEL
>>> FLOW_MONITOR_PAUSED
>>> FLOW_MONITOR_RESUMED
>>> FLOW_MONITOR request
>>> FLOW_MONITOR reply
>>> tests/ofp-print.at
>>>
>>> 7. Modify flow monitoring tests to be able executed by all protocol
>>> versions.
>>> tests/ofproto.at
>>>
>>> 7. Modified documentation highlighting the change
>>> utilities/ovs-ofctl.8.in
>>> NEWS
>>>
>>> Signed-off-by: Vasu Dasari <vdasari at gmail.com>
>>> Reported-at:
>>> https://mail.openvswitch.org/pipermail/ovs-dev/2021-June/383915.html
>>> ---
>>> v1:
>>> - Fixed 0-day Robot errors
>>>
>>> ---
>>> NEWS | 6 +-
>>> include/openflow/openflow-1.3.h | 89 ++++
>>> include/openflow/openflow-1.4.h | 93 +++-
>>> include/openvswitch/ofp-monitor.h | 9 +-
>>> include/openvswitch/ofp-msgs.h | 39 +-
>>> lib/ofp-monitor.c | 844 ++++++++++++++++++++++++------
>>> lib/ofp-print.c | 24 +-
>>> ofproto/connmgr.c | 47 +-
>>> ofproto/connmgr.h | 6 +-
>>> ofproto/ofproto-provider.h | 4 +-
>>> ofproto/ofproto.c | 89 +++-
>>> tests/ofp-print.at | 122 ++++-
>>> tests/ofproto.at | 176 +++++--
>>> utilities/ovs-ofctl.8.in | 3 +
>>> utilities/ovs-ofctl.c | 6 +
>>> 15 files changed, 1265 insertions(+), 292 deletions(-)
>>>
>>> diff --git a/NEWS b/NEWS
>>> index 02884b774..47ad9de2a 100644
>>> --- a/NEWS
>>> +++ b/NEWS
>>> @@ -25,8 +25,10 @@ v2.16.0 - xx xxx xxxx
>>> - In ovs-vsctl and vtep-ctl, the "find" command now accept new
>>> operators {in} and {not-in}.
>>> - OpenFlow:
>>> - * Extend Flow Monitoring support for OpenFlow 1.0-1.2 with Nicira
>>> - Extensions
>>> + * Extended Flow Monitoring support for all supported OpenFlow
>>> versions
>>> + OpenFlow versions 1.0-1.2 with Nicira Extensions
>>> + OpenFlow versions 1.3 with Open Network Foundation extension
>>> + OpenFlow versions 1.4+, as defined in the OpenFlow
>>> specification
>>> - Userspace datapath:
>>> * Auto load balancing of PMDs now partially supports cross-NUMA
>>> polling
>>> cases, e.g if all PMD threads are running on the same NUMA node.
>>> diff --git a/include/openflow/openflow-1.3.h
>>> b/include/openflow/openflow-1.3.h
>>> index c48a8ea7f..1a818dbb4 100644
>>> --- a/include/openflow/openflow-1.3.h
>>> +++ b/include/openflow/openflow-1.3.h
>>> @@ -374,4 +374,93 @@ struct ofp13_async_config {
>>> };
>>> OFP_ASSERT(sizeof(struct ofp13_async_config) == 24);
>>>
>>> +struct onf_flow_monitor_request {
>>> + ovs_be32 id; /* Controller-assigned ID for this
>>> monitor. */
>>> + ovs_be16 flags; /* ONFFMF_*. */
>>> + ovs_be16 match_len; /* Length of oxm_fields. */
>>> + ovs_be32 out_port; /* Required output port, if not
>>> OFPP_NONE. */
>>> + uint8_t table_id; /* One table’s ID or 0xff for all tables.
>>> */
>>> + uint8_t zeros[3]; /* Align to 64 bits (must be zero). */
>>> + /* Followed by an ofp11_match structure. */
>>> +};
>>> +OFP_ASSERT(sizeof(struct onf_flow_monitor_request) == 16);
>>> +
>>> +/* Header for experimenter requests and replies. */
>>> +struct onf_experimenter_header {
>>> + struct ofp_header header;
>>> + ovs_be32 vendor; /* ONF_EXPERIMENTER_ID. */
>>> + ovs_be32 subtype; /* One of ONFT_*. */
>>> +};
>>> +OFP_ASSERT(sizeof(struct onf_experimenter_header) == 16);
>>> +
>>> +enum onf_flow_monitor_msg_type {
>>> + ONFT_FLOW_MONITOR_CANCEL = 1870,
>>> + ONFT_FLOW_MONITOR_PAUSED = 1871,
>>> + ONFT_FLOW_MONITOR_RESUMED = 1872
>>> +};
>>> +
>>> +/* ’flags’ bits in struct onf_flow_monitor_request. */
>>> +enum onf_flow_monitor_flags {
>>> + /* When to send updates. */
>>> + ONFFMF_INITIAL = 1 << 0, /* Initially matching flows. */
>>> + ONFFMF_ADD = 1 << 1, /* New matching flows as they are added.
>>> */
>>> + ONFFMF_DELETE = 1 << 2, /* Old matching flows as they are
>>> removed. */
>>> + ONFFMF_MODIFY = 1 << 3, /* Matching flows as they are changed. */
>>> +
>>> + /* What to include in updates. */
>>> + ONFFMF_ACTIONS = 1 << 4, /* If set, actions are included. */
>>> + ONFFMF_OWN = 1 << 5, /* If set, include own changes in full. */
>>> +};
>>> +
>>> +/* ONFST_FLOW_MONITOR reply header. */
>>> +struct onf_flow_update_header {
>>> + ovs_be16 length; /* Length of this entry. */
>>> + ovs_be16 event; /* One of ONFFME_*. */
>>> + /* ...other data depending on ’event’... */
>>> +};
>>> +OFP_ASSERT(sizeof(struct onf_flow_update_header) == 4);
>>> +
>>> +/* ’event’ values in struct onf_flow_update_header. */
>>> +enum onf_flow_update_event {
>>> + /* struct onf_flow_update_full. */
>>> + ONFFME_ADDED = 0, /* Flow was added. */
>>> + ONFFME_DELETED = 1, /* Flow was deleted. */
>>> + ONFFME_MODIFIED = 2, /* Flow (generally its actions) was
>>> changed. */
>>> +
>>> + /* struct onf_flow_update_abbrev. */
>>> + ONFFME_ABBREV = 3, /* Abbreviated reply. */
>>> +};
>>> +
>>> +/* ONFST_FLOW_MONITOR reply for ONFFME_ADDED, ONFFME_DELETED, and
>>> +* ONFFME_MODIFIED. */
>>> +struct onf_flow_update_full {
>>> + ovs_be16 length; /* Length is 24. */
>>> + ovs_be16 event; /* One of ONFFME_*. */
>>> + ovs_be16 reason; /* OFPRR_* for ONFFME_DELETED, else zero.
>>> */
>>> + ovs_be16 priority; /* Priority of the entry. */
>>> + ovs_be16 idle_timeout; /* Number of seconds idle before
>>> expiration. */
>>> + ovs_be16 hard_timeout; /* Number of seconds before expiration. */
>>> + ovs_be16 match_len; /* Length of oxm_fields. */
>>> + uint8_t table_id; /* ID of flow’s table. */
>>> + uint8_t pad; /* Reserved, currently zeroed. */
>>> + ovs_be64 cookie; /* Opaque controller-issued identifier. */
>>> + /* Followed by:
>>> + * - Exactly match_len (possibly 0) bytes containing the
>>> oxm_fields, then
>>> + * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7)
>>> bytes of
>>> + * all-zero bytes, then
>>> + * - Instructions to fill out the remainder ’length’ bytes
>>> (always a
>>> + * multiple of 8). If ONFFMF_ACTIONS was not specified, or
>>> ’event’ is
>>> + * ONFFME_DELETED, no actions are included.
>>> + */
>>> +};
>>> +OFP_ASSERT(sizeof(struct onf_flow_update_full) == 24);
>>> +
>>> +/* ONFST_FLOW_MONITOR reply for ONFFME_ABBREV. */
>>> +struct onf_flow_update_abbrev {
>>> + ovs_be16 length; /* Length is 8. */
>>> + ovs_be16 event; /* ONFFME_ABBREV. */
>>> + ovs_be32 xid; /* Controller-specified xid from flow_mod. */
>>> +};
>>> +OFP_ASSERT(sizeof(struct onf_flow_update_abbrev) == 8);
>>> +
>>> #endif /* openflow/openflow-1.3.h */
>>> diff --git a/include/openflow/openflow-1.4.h
>>> b/include/openflow/openflow-1.4.h
>>> index be191180b..8e6a163fd 100644
>>> --- a/include/openflow/openflow-1.4.h
>>> +++ b/include/openflow/openflow-1.4.h
>>> @@ -358,27 +358,100 @@ OFP_ASSERT(sizeof(struct
>>> ofp14_flow_monitor_request) == 16);
>>>
>>> /* Flow monitor commands */
>>> enum ofp14_flow_monitor_command {
>>> - OFPFMC14_ADD = 0, /* New flow monitor. */
>>> - OFPFMC14_MODIFY = 1, /* Modify existing flow monitor. */
>>> - OFPFMC14_DELETE = 2, /* Delete/cancel existing flow monitor. */
>>> + OFPFMC_ADD = 0, /* New flow monitor. */
>>> + OFPFMC_MODIFY = 1, /* Modify existing flow monitor. */
>>> + OFPFMC_DELETE = 2, /* Delete/cancel existing flow monitor. */
>>> };
>>>
>>> /* 'flags' bits in struct of_flow_monitor_request. */
>>> enum ofp14_flow_monitor_flags {
>>> /* When to send updates. */
>>> /* Common to NX and OpenFlow 1.4 */
>>> - OFPFMF14_INITIAL = 1 << 0, /* Initially matching flows. */
>>> - OFPFMF14_ADD = 1 << 1, /* New matching flows as they are
>>> added. */
>>> - OFPFMF14_REMOVED = 1 << 2, /* Old matching flows as they are
>>> removed. */
>>> - OFPFMF14_MODIFY = 1 << 3, /* Matching flows as they are
>>> changed. */
>>> + OFPFMF_INITIAL = 1 << 0, /* Initially matching flows. */
>>> + OFPFMF_ADD = 1 << 1, /* New matching flows as they are
>>> added. */
>>> + OFPFMF_REMOVED = 1 << 2, /* Old matching flows as they are
>>> removed. */
>>> + OFPFMF_MODIFY = 1 << 3, /* Matching flows as they are changed.
>>> */
>>>
>>> /* What to include in updates. */
>>> /* Common to NX and OpenFlow 1.4 */
>>> - OFPFMF14_INSTRUCTIONS = 1 << 4, /* If set, instructions are
>>> included. */
>>> - OFPFMF14_NO_ABBREV = 1 << 5, /* If set, include own changes in
>>> full. */
>>> + OFPFMF_INSTRUCTIONS = 1 << 4, /* If set, instructions are included.
>>> */
>>> + OFPFMF_NO_ABBREV = 1 << 5, /* If set, include own changes in
>>> full. */
>>> /* OpenFlow 1.4 */
>>> - OFPFMF14_ONLY_OWN = 1 << 6, /* If set, don't include other
>>> controllers.
>>> + OFPFMF_ONLY_OWN = 1 << 6, /* If set, don't include other
>>> controllers.
>>> */
>>> };
>>>
>>> +/* 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 {
>>> + ovs_be16 length; /* Length of this entry. */
>>> + ovs_be16 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_INITIAL = 0, /* Flow present when flow monitor
>>> created. */
>>> + OFPFME_ADDED = 1, /* Flow was added. */
>>> + OFPFME_REMOVED = 2, /* Flow was removed. */
>>> + OFPFME_MODIFIED = 3, /* Flow instructions were changed. */
>>> +
>>> + /* struct ofp_flow_update_abbrev. */
>>> + OFPFME_ABBREV = 4, /* Abbreviated reply. */
>>> +
>>> + /* struct ofp_flow_update_header. */
>>> + OFPFME_PAUSED = 5, /* Monitoring paused (out of buffer
>>> space). */
>>> + OFPFME_RESUMED = 6, /* Monitoring resumed. */
>>> +};
>>> +
>>> +/* OFPMP_FLOW_MONITOR reply for OFPFME_INITIAL, OFPFME_ADDED,
>>> OFPFME_REMOVED,
>>> + * and OFPFME_MODIFIED. */
>>> +struct ofp_flow_update_full {
>>> + ovs_be16 length; /* Length is 32 + match + instructions.
>>> */
>>> + ovs_be16 event; /* One of OFPFME_*. */
>>> + uint8_t table_id; /* ID of flow’s table. */
>>> + uint8_t reason; /* OFPRR_* for OFPFME_REMOVED, else
>>> zero. */
>>> + ovs_be16 idle_timeout; /* Number of seconds idle before
>>> expiration. */
>>> + ovs_be16 hard_timeout; /* Number of seconds before expiration.
>>> */
>>> + ovs_be16 priority; /* Priority of the entry. */
>>> + uint8_t zeros[4]; /* Reserved, currently zeroed. */
>>> + ovs_be64 cookie; /* Opaque controller-issued identifier.
>>> */
>>> + /* Instruction set.
>>> + * If OFPFMF_INSTRUCTIONS was not specified, or ’event’ is
>>> + * OFPFME_REMOVED, no instructions are included.
>>> + */
>>> +};
>>> +OFP_ASSERT(sizeof(struct ofp_flow_update_full) == 24);
>>> +
>>> +/* OFPMP_FLOW_MONITOR reply for OFPFME_ABBREV.
>>> + *
>>> + * When the controller does not specify OFPFMF_NO_ABBREV 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.
>>> + */
>>> +struct ofp_flow_update_abbrev {
>>> + ovs_be16 length; /* Length is 8. */
>>> + ovs_be16 event; /* OFPFME_ABBREV. */
>>> + ovs_be32 xid; /* Controller-specified xid from flow_mod. */
>>> +};
>>> +OFP_ASSERT(sizeof(struct ofp_flow_update_abbrev) == 8);
>>> +
>>> +/* OFPMP_FLOW_MONITOR reply for OFPFME_PAUSED and OFPFME_RESUMED.*/
>>> +struct ofp_flow_update_paused {
>>> + ovs_be16 length; /* Length is 8. */
>>> + ovs_be16 event; /* One of OFPFME_*. */
>>> + uint8_t zeros[4]; /* Reserved, currently zeroed. */
>>> +};
>>> +OFP_ASSERT(sizeof(struct ofp_flow_update_paused) == 8);
>>> +
>>> #endif /* openflow/openflow-1.4.h */
>>> diff --git a/include/openvswitch/ofp-monitor.h
>>> b/include/openvswitch/ofp-monitor.h
>>> index 835efd0f3..7c7cfcff4 100644
>>> --- a/include/openvswitch/ofp-monitor.h
>>> +++ b/include/openvswitch/ofp-monitor.h
>>> @@ -61,8 +61,10 @@ void ofputil_flow_removed_format(struct ds *,
>>> /* Abstract nx_flow_monitor_request. */
>>> struct ofputil_flow_monitor_request {
>>> uint32_t id;
>>> - enum nx_flow_monitor_flags flags;
>>> + enum ofp14_flow_monitor_command command;
>>> + enum ofp14_flow_monitor_flags flags;
>>> ofp_port_t out_port;
>>> + uint32_t out_group;
>>> uint8_t table_id;
>>> struct match match;
>>> };
>>> @@ -85,7 +87,7 @@ char *parse_flow_monitor_request(struct
>>> ofputil_flow_monitor_request *,
>>>
>>> /* Abstract nx_flow_update. */
>>> struct ofputil_flow_update {
>>> - enum nx_flow_update_event event;
>>> + enum ofp_flow_update_event event;
>>>
>>> /* Used only for NXFME_ADDED, NXFME_DELETED, NXFME_MODIFIED. */
>>> enum ofp_flow_removed_reason reason;
>>> @@ -119,6 +121,9 @@ uint32_t ofputil_decode_flow_monitor_cancel(const
>>> struct ofp_header *);
>>> struct ofpbuf *ofputil_encode_flow_monitor_cancel(
>>> uint32_t id, enum ofputil_protocol protocol);
>>>
>>> +struct ofpbuf * ofputil_encode_flow_monitor_pause(
>>> + enum ofp_flow_update_event command, enum ofputil_protocol protocol);
>>> +
>>> struct ofputil_requestforward {
>>> ovs_be32 xid;
>>> /* Also used for OF 1.0-1.3 when using Nicira Extension: */
>>> diff --git a/include/openvswitch/ofp-msgs.h
>>> b/include/openvswitch/ofp-msgs.h
>>> index c5fde0270..921a937e5 100644
>>> --- a/include/openvswitch/ofp-msgs.h
>>> +++ b/include/openvswitch/ofp-msgs.h
>>> @@ -453,14 +453,33 @@ enum ofpraw {
>>>
>>> /* OFPST 1.4+ (16): uint8_t[8][]. */
>>> OFPRAW_OFPST14_FLOW_MONITOR_REQUEST,
>>> + /* ONFST 1.3 (1870): uint8_t[8][]. */
>>> + OFPRAW_ONFST13_FLOW_MONITOR_REQUEST,
>>> /* NXST 1.0-1.2 (2): uint8_t[8][]. */
>>> OFPRAW_NXST_FLOW_MONITOR_REQUEST,
>>>
>>> /* OFPST 1.4+ (16): uint8_t[8][]. */
>>> OFPRAW_OFPST14_FLOW_MONITOR_REPLY,
>>> + /* ONFST 1.3 (1870): uint8_t[8][]. */
>>> + OFPRAW_ONFST13_FLOW_MONITOR_REPLY,
>>> /* NXST 1.0-1.2 (2): uint8_t[8][]. */
>>> OFPRAW_NXST_FLOW_MONITOR_REPLY,
>>>
>>> + /* ONFT 1.3 (1870): struct nx_flow_monitor_cancel. */
>>> + OFPRAW_ONFT13_FLOW_MONITOR_CANCEL,
>>> + /* NXT 1.0-1.2 (21): struct nx_flow_monitor_cancel. */
>>> + OFPRAW_NXT_FLOW_MONITOR_CANCEL,
>>> +
>>> + /* ONFT 1.3 (1871): void. */
>>> + OFPRAW_ONFT13_FLOW_MONITOR_PAUSED,
>>> + /* NXT 1.0-1.2 (22): void. */
>>> + OFPRAW_NXT_FLOW_MONITOR_PAUSED,
>>> +
>>> + /* ONFT 1.3 (1872): void. */
>>> + OFPRAW_ONFT13_FLOW_MONITOR_RESUMED,
>>> + /* NXT 1.0-1.2 (23): void. */
>>> + OFPRAW_NXT_FLOW_MONITOR_RESUMED,
>>> +
>>> /* Nicira extension messages.
>>> *
>>> * Nicira extensions that correspond to standard OpenFlow messages are
>>> listed
>>> @@ -481,15 +500,6 @@ enum ofpraw {
>>> /* NXT 1.0+ (20): struct nx_controller_id. */
>>> OFPRAW_NXT_SET_CONTROLLER_ID,
>>>
>>> - /* NXT 1.0+ (21): struct nx_flow_monitor_cancel. */
>>> - OFPRAW_NXT_FLOW_MONITOR_CANCEL,
>>> -
>>> - /* NXT 1.0+ (22): void. */
>>> - OFPRAW_NXT_FLOW_MONITOR_PAUSED,
>>> -
>>> - /* NXT 1.0+ (23): void. */
>>> - OFPRAW_NXT_FLOW_MONITOR_RESUMED,
>>> -
>>> /* NXT 1.0+ (24): struct nx_tlv_table_mod, struct nx_tlv_map[]. */
>>> OFPRAW_NXT_TLV_TABLE_MOD,
>>>
>>> @@ -741,8 +751,10 @@ enum ofptype {
>>> * OFPRAW_OFPST14_PORT_DESC_REPLY.
>>> */
>>>
>>> OFPTYPE_FLOW_MONITOR_STATS_REQUEST, /*
>>> OFPRAW_OFPST14_FLOW_MONITOR_REQUEST.
>>> + *
>>> OFPRAW_ONFST13_FLOW_MONITOR_REQUEST.
>>> *
>>> OFPRAW_NXST_FLOW_MONITOR_REQUEST. */
>>> OFPTYPE_FLOW_MONITOR_STATS_REPLY, /*
>>> OFPRAW_OFPST14_FLOW_MONITOR_REPLY.
>>> + *
>>> OFPRAW_ONFST13_FLOW_MONITOR_REPLY.
>>> *
>>> OFPRAW_NXST_FLOW_MONITOR_REPLY. */
>>>
>>> /* Nicira extensions. */
>>> @@ -762,9 +774,12 @@ enum ofptype {
>>> OFPTYPE_CT_FLUSH_ZONE, /* OFPRAW_NXT_CT_FLUSH_ZONE. */
>>>
>>> /* Flow monitor extension. */
>>> - OFPTYPE_FLOW_MONITOR_CANCEL, /*
>>> OFPRAW_NXT_FLOW_MONITOR_CANCEL. */
>>> - OFPTYPE_FLOW_MONITOR_PAUSED, /*
>>> OFPRAW_NXT_FLOW_MONITOR_PAUSED. */
>>> - OFPTYPE_FLOW_MONITOR_RESUMED, /*
>>> OFPRAW_NXT_FLOW_MONITOR_RESUMED. */
>>> + OFPTYPE_FLOW_MONITOR_CANCEL, /* OFPRAW_NXT_FLOW_MONITOR_CANCEL.
>>> + * OFPRAW_ONFT13_FLOW_MONITOR_CANCEL.
>>> */
>>> + OFPTYPE_FLOW_MONITOR_PAUSED, /* OFPRAW_NXT_FLOW_MONITOR_PAUSED.
>>> + * OFPRAW_ONFT13_FLOW_MONITOR_PAUSED.
>>> */
>>> + OFPTYPE_FLOW_MONITOR_RESUMED, /* OFPRAW_NXT_FLOW_MONITOR_RESUMED.
>>> + * OFPRAW_ONFT13_FLOW_MONITOR_RESUMED
>>> */
>>> };
>>>
>>> /* Decoding messages into OFPTYPE_* values. */
>>> diff --git a/lib/ofp-monitor.c b/lib/ofp-monitor.c
>>> index 51f01b100..1756c9e8e 100644
>>> --- a/lib/ofp-monitor.c
>>> +++ b/lib/ofp-monitor.c
>>> @@ -328,6 +328,98 @@ ofputil_flow_removed_format(struct ds *s,
>>> ds_put_format(s, " pkts%"PRIu64" bytes%"PRIu64"\n",
>>> fr->packet_count, fr->byte_count);
>>> }
>>> +
>>> +static uint16_t
>>> +nx_to_ofp_flow_monitor_flags(uint16_t flags)
>>> +{
>>> + uint16_t oxm_flags = 0;
>>> +
>>> + if (flags & NXFMF_INITIAL) {
>>> + oxm_flags |= OFPFMF_INITIAL;
>>> + }
>>> + if (flags & NXFMF_ADD) {
>>> + oxm_flags |= OFPFMF_ADD;
>>> + }
>>> + if (flags & NXFMF_DELETE) {
>>> + oxm_flags |= OFPFMF_REMOVED;
>>> + }
>>> + if (flags & NXFMF_MODIFY) {
>>> + oxm_flags |= OFPFMF_MODIFY;
>>> + }
>>> + if (flags & NXFMF_ACTIONS) {
>>> + oxm_flags |= OFPFMF_INSTRUCTIONS;
>>> + }
>>> + if (flags & NXFMF_OWN) {
>>> + oxm_flags |= OFPFMF_ONLY_OWN;
>>> + }
>>> +
>>> + return oxm_flags;
>>> +}
>>> +
>>> +static uint16_t
>>> +ofp_to_nx_flow_monitor_flags(uint16_t flags)
>>> +{
>>> + uint16_t nx_flags = 0;
>>> +
>>> + if (flags & OFPFMF_INITIAL) {
>>> + nx_flags |= NXFMF_INITIAL;
>>> + }
>>> + if (flags & OFPFMF_ADD) {
>>> + nx_flags |= NXFMF_ADD;
>>> + }
>>> + if (flags & OFPFMF_REMOVED) {
>>> + nx_flags |= NXFMF_DELETE;
>>> + }
>>> + if (flags & OFPFMF_MODIFY) {
>>> + nx_flags |= NXFMF_MODIFY;
>>> + }
>>> + if (flags & OFPFMF_INSTRUCTIONS) {
>>> + nx_flags |= NXFMF_ACTIONS;
>>> + }
>>> + if (flags & OFPFMF_ONLY_OWN) {
>>> + nx_flags |= NXFMF_OWN;
>>> + }
>>> +
>>> + return nx_flags;
>>> +}
>>> +
>>> +static enum ofp_flow_update_event
>>> +nx_to_ofp_flow_update_event(enum nx_flow_update_event event)
>>> +{
>>> + switch (event) {
>>> + case NXFME_ADDED:
>>> + return OFPFME_ADDED;
>>> + case NXFME_DELETED:
>>> + return OFPFME_REMOVED;
>>> + case NXFME_MODIFIED:
>>> + return OFPFME_MODIFIED;
>>> + case NXFME_ABBREV:
>>> + return OFPFME_ABBREV;
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> +}
>>> +
>>> +static enum nx_flow_update_event
>>> +ofp_to_nx_flow_update_event(enum ofp_flow_update_event event)
>>> +{
>>> + switch (event) {
>>> + case OFPFME_INITIAL:
>>> + case OFPFME_ADDED:
>>> + return NXFME_ADDED;
>>> + case OFPFME_REMOVED:
>>> + return NXFME_DELETED;
>>> + case OFPFME_MODIFIED:
>>> + return NXFME_MODIFIED;
>>> + case OFPFME_ABBREV:
>>> + return NXFME_ABBREV;
>>> + default:
>>> + case OFPFME_PAUSED:
>>> + case OFPFME_RESUMED:
>>> + OVS_NOT_REACHED();
>>> + }
>>> +}
>>> +
>>>
>>> /* ofputil_flow_monitor_request */
>>>
>>> @@ -345,43 +437,129 @@ int
>>> ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request
>>> *rq,
>>> struct ofpbuf *msg)
>>> {
>>> - struct nx_flow_monitor_request *nfmr;
>>> uint16_t flags;
>>> + enum ofperr error;
>>> + enum ofpraw raw;
>>>
>>> - if (!msg->header) {
>>> - ofpraw_pull_assert(msg);
>>> + error = (msg->header ? ofpraw_decode(&raw, msg->header)
>>> + : ofpraw_pull(&raw, msg));
>>> + if (error) {
>>> + return error;
>>> }
>>>
>>> if (!msg->size) {
>>> return EOF;
>>> }
>>>
>>> - nfmr = ofpbuf_try_pull(msg, sizeof *nfmr);
>>> - if (!nfmr) {
>>> - VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR request has %"PRIu32" "
>>> - "leftover bytes at end", msg->size);
>>> - return OFPERR_OFPBRC_BAD_LEN;
>>> - }
>>> + switch ((int) raw) {
>>> + case OFPRAW_NXST_FLOW_MONITOR_REQUEST: {
>>> + struct nx_flow_monitor_request *nfmr;
>>>
>>> - flags = ntohs(nfmr->flags);
>>> - if (!(flags & (NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY))
>>> - || flags & ~(NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE
>>> - | NXFMF_MODIFY | NXFMF_ACTIONS | NXFMF_OWN)) {
>>> - VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR has bad flags %#"PRIx16,
>>> flags);
>>> - return OFPERR_OFPMOFC_BAD_FLAGS;
>>> + nfmr = ofpbuf_try_pull(msg, sizeof *nfmr);
>>> + if (!nfmr) {
>>> + VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR request has %"PRIu32" "
>>> + "leftover bytes at end", msg->size);
>>> + return OFPERR_OFPBRC_BAD_LEN;
>>> + }
>>> +
>>> + flags = ntohs(nfmr->flags);
>>> + if (!(flags & (NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY))
>>> + || flags & ~(NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE
>>> + | NXFMF_MODIFY | NXFMF_ACTIONS | NXFMF_OWN)) {
>>> + VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR has bad flags
>>> %#"PRIx16,
>>> + flags);
>>> + return OFPERR_OFPMOFC_BAD_FLAGS;
>>> + }
>>> +
>>> + if (!is_all_zeros(nfmr->zeros, sizeof nfmr->zeros)) {
>>> + return OFPERR_NXBRC_MUST_BE_ZERO;
>>> + }
>>> +
>>> + rq->id = ntohl(nfmr->id);
>>> + rq->command = OFPFMC_ADD;
>>> + rq->flags = nx_to_ofp_flow_monitor_flags(flags);
>>> + rq->out_port = u16_to_ofp(ntohs(nfmr->out_port));
>>> + rq->table_id = nfmr->table_id;
>>> + rq->out_group = OFPG_ANY;
>>> +
>>> + return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match,
>>> NULL,
>>> + NULL, false, NULL, NULL);
>>> }
>>> + case OFPRAW_ONFST13_FLOW_MONITOR_REQUEST: {
>>> + struct onf_flow_monitor_request *ofmr;
>>> +
>>> + ofmr = ofpbuf_try_pull(msg, sizeof *ofmr);
>>> + if (!ofmr) {
>>> + VLOG_WARN_RL(&rl, "ONFST_FLOW_MONITOR request has %"PRIu32"
>>> "
>>> + "leftover bytes at end", msg->size);
>>> + return OFPERR_OFPBRC_BAD_LEN;
>>> + }
>>> +
>>> + flags = ntohs(ofmr->flags);
>>> + if (!(flags & (ONFFMF_ADD | ONFFMF_DELETE | ONFFMF_MODIFY))
>>> + || flags & ~(ONFFMF_INITIAL | ONFFMF_ADD | ONFFMF_DELETE
>>> + | ONFFMF_MODIFY | ONFFMF_ACTIONS |
>>> ONFFMF_OWN)) {
>>> + VLOG_WARN_RL(&rl, "ONFST_FLOW_MONITOR has bad flags
>>> %#"PRIx16,
>>> + flags);
>>> + return OFPERR_OFPMOFC_BAD_FLAGS;
>>> + }
>>> +
>>> + if (!is_all_zeros(ofmr->zeros, sizeof ofmr->zeros)) {
>>> + return OFPERR_NXBRC_MUST_BE_ZERO;
>>> + }
>>> +
>>> + rq->id = ntohl(ofmr->id);
>>> + rq->command = OFPFMC_ADD;
>>> + rq->flags = nx_to_ofp_flow_monitor_flags(flags);
>>> + error = ofputil_port_from_ofp11(ofmr->out_port, &rq->out_port);
>>> + if (error) {
>>> + return error;
>>> + }
>>> + rq->table_id = ofmr->table_id;
>>> + rq->out_group = OFPG_ANY;
>>>
>>> - if (!is_all_zeros(nfmr->zeros, sizeof nfmr->zeros)) {
>>> - return OFPERR_NXBRC_MUST_BE_ZERO;
>>> + return ofputil_pull_ofp11_match(msg, NULL, NULL, &rq->match,
>>> NULL);
>>> }
>>> + case OFPRAW_OFPST14_FLOW_MONITOR_REQUEST: {
>>> + struct ofp14_flow_monitor_request *ofmr;
>>> +
>>> + ofmr = ofpbuf_try_pull(msg, sizeof *ofmr);
>>> + if (!ofmr) {
>>> + VLOG_WARN_RL(&rl, "OFPST_FLOW_MONITOR request has %"PRIu32"
>>> "
>>> + "leftover bytes at end", msg->size);
>>> + return OFPERR_OFPBRC_BAD_LEN;
>>> + }
>>>
>>> - rq->id = ntohl(nfmr->id);
>>> - rq->flags = flags;
>>> - rq->out_port = u16_to_ofp(ntohs(nfmr->out_port));
>>> - rq->table_id = nfmr->table_id;
>>> + flags = ntohs(ofmr->flags);
>>> + rq->id = ntohl(ofmr->monitor_id);
>>> + rq->command = ofmr->command;
>>> +
>>> + if (ofmr->command == OFPFMC_DELETE) {
>>> + return ofputil_pull_ofp11_match(msg, NULL, NULL,
>>> &rq->match, NULL);
>>> + }
>>>
>>> - return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match, NULL,
>>> - NULL, false, NULL, NULL);
>>> + if (!(flags & (OFPFMF_ADD | OFPFMF_REMOVED | OFPFMF_MODIFY))
>>> + || flags & ~(OFPFMF_INITIAL | OFPFMF_ADD |
>>> OFPFMF_REMOVED
>>> + | OFPFMF_MODIFY | OFPFMF_INSTRUCTIONS |
>>> OFPFMF_ONLY_OWN)) {
>>> + VLOG_WARN_RL(&rl, "OFPST_FLOW_MONITOR has bad flags
>>> %#"PRIx16,
>>> + flags);
>>> + return OFPERR_OFPMOFC_BAD_FLAGS;
>>> + }
>>> +
>>> + rq->command = ofmr->command;
>>> + rq->flags = flags;
>>> + error = ofputil_port_from_ofp11(ofmr->out_port, &rq->out_port);
>>> + if (error) {
>>> + return error;
>>> + }
>>> + rq->out_group = ntohl(ofmr->out_group);
>>> + rq->table_id = ofmr->table_id;
>>> +
>>> + return ofputil_pull_ofp11_match(msg, NULL, NULL, &rq->match,
>>> NULL);
>>> + }
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> }
>>>
>>> void
>>> @@ -389,66 +567,143 @@ ofputil_append_flow_monitor_request(
>>> const struct ofputil_flow_monitor_request *rq, struct ofpbuf *msg,
>>> enum ofputil_protocol protocol)
>>> {
>>> - struct nx_flow_monitor_request *nfmr;
>>> size_t start_ofs;
>>> int match_len;
>>> enum ofp_version version =
>>> ofputil_protocol_to_ofp_version(protocol);
>>>
>>> if (!msg->size) {
>>> - ofpraw_put(OFPRAW_NXST_FLOW_MONITOR_REQUEST, version, msg);
>>> - }
>>> + switch (version) {
>>> + case OFP10_VERSION:
>>> + case OFP11_VERSION:
>>> + case OFP12_VERSION: {
>>> + struct nx_flow_monitor_request *nfmr;
>>> +
>>> + if (!msg->size) {
>>> + ofpraw_put(OFPRAW_NXST_FLOW_MONITOR_REQUEST, version,
>>> msg);
>>> + }
>>>
>>> - start_ofs = msg->size;
>>> - ofpbuf_put_zeros(msg, sizeof *nfmr);
>>> - match_len = nx_put_match(msg, &rq->match, htonll(0), htonll(0));
>>> -
>>> - nfmr = ofpbuf_at_assert(msg, start_ofs, sizeof *nfmr);
>>> - nfmr->id = htonl(rq->id);
>>> - nfmr->flags = htons(rq->flags);
>>> - nfmr->out_port = htons(ofp_to_u16(rq->out_port));
>>> - nfmr->match_len = htons(match_len);
>>> - nfmr->table_id = rq->table_id;
>>> + start_ofs = msg->size;
>>> + ofpbuf_put_zeros(msg, sizeof *nfmr);
>>> + match_len = nx_put_match(msg, &rq->match, htonll(0),
>>> htonll(0));
>>> +
>>> + nfmr = ofpbuf_at_assert(msg, start_ofs, sizeof *nfmr);
>>> + nfmr->id = htonl(rq->id);
>>> + nfmr->flags =
>>> htons(ofp_to_nx_flow_monitor_flags(rq->flags));
>>> + nfmr->out_port = htons(ofp_to_u16(rq->out_port));
>>> + nfmr->match_len = htons(match_len);
>>> + nfmr->table_id = rq->table_id;
>>> + break;
>>> + }
>>> + case OFP13_VERSION: {
>>> + struct onf_flow_monitor_request *ofmr;
>>> +
>>> + if (!msg->size) {
>>> + ofpraw_put(OFPRAW_ONFST13_FLOW_MONITOR_REQUEST,
>>> version, msg);
>>> + }
>>> +
>>> + start_ofs = msg->size;
>>> + ofpbuf_put_zeros(msg, sizeof *ofmr);
>>> + match_len = oxm_put_match(msg, &rq->match, version);
>>> +
>>> + ofmr = ofpbuf_at_assert(msg, start_ofs, sizeof *ofmr);
>>> + ofmr->id = htonl(rq->id);
>>> + ofmr->flags =
>>> htons(ofp_to_nx_flow_monitor_flags(rq->flags));
>>> + ofmr->match_len = htons(match_len);
>>> + ofmr->out_port = ofputil_port_to_ofp11(rq->out_port);
>>> + ofmr->table_id = rq->table_id;
>>> + break;
>>> + }
>>> + case OFP14_VERSION:
>>> + case OFP15_VERSION: {
>>> + struct ofp14_flow_monitor_request *ofmr;
>>> +
>>> + if (!msg->size) {
>>> + ofpraw_put(OFPRAW_OFPST14_FLOW_MONITOR_REQUEST,
>>> version, msg);
>>> + }
>>> +
>>> + start_ofs = msg->size;
>>> + ofpbuf_put_zeros(msg, sizeof *ofmr);
>>> + oxm_put_match(msg, &rq->match, version);
>>> +
>>> + ofmr = ofpbuf_at_assert(msg, start_ofs, sizeof *ofmr);
>>> + ofmr->monitor_id = htonl(rq->id);
>>> + ofmr->command = OFPFMC_ADD;
>>> + ofmr->out_port = ofputil_port_to_ofp11(rq->out_port);
>>> + ofmr->out_group = htonl(rq->out_group);
>>> + ofmr->flags = htons(rq->flags);
>>> + ofmr->table_id = rq->table_id;
>>> + break;
>>> + }
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> + }
>>> }
>>>
>>> static const char *
>>> -nx_flow_monitor_flags_to_name(uint32_t bit)
>>> +ofp_flow_monitor_flags_to_name(uint32_t bit)
>>> {
>>> - enum nx_flow_monitor_flags fmf = bit;
>>> + enum ofp14_flow_monitor_flags fmf = bit;
>>>
>>> switch (fmf) {
>>> - case NXFMF_INITIAL: return "initial";
>>> - case NXFMF_ADD: return "add";
>>> - case NXFMF_DELETE: return "delete";
>>> - case NXFMF_MODIFY: return "modify";
>>> - case NXFMF_ACTIONS: return "actions";
>>> - case NXFMF_OWN: return "own";
>>> + case OFPFMF_INITIAL: return "initial";
>>> + case OFPFMF_ADD: return "add";
>>> + case OFPFMF_REMOVED: return "delete";
>>> + case OFPFMF_MODIFY: return "modify";
>>> + case OFPFMF_INSTRUCTIONS: return "actions";
>>> + case OFPFMF_NO_ABBREV: return "no-abbrev";
>>> + case OFPFMF_ONLY_OWN: return "own";
>>> }
>>>
>>> return NULL;
>>> }
>>>
>>> +static const char *
>>> +ofp_flow_monitor_command_to_string(enum ofp14_flow_monitor_command
>>> command)
>>> +{
>>> + switch (command) {
>>> + case OFPFMC_ADD: return "add";
>>> + case OFPFMC_MODIFY: return "modify";
>>> + case OFPFMC_DELETE: return "delete";
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> +}
>>> +
>>> void
>>> ofputil_flow_monitor_request_format(
>>> struct ds *s, const struct ofputil_flow_monitor_request *request,
>>> const struct ofputil_port_map *port_map,
>>> const struct ofputil_table_map *table_map)
>>> {
>>> + if (request->command == OFPFMC_DELETE) {
>>> + ds_put_format(s, "\n id=%"PRIu32" command=%s", request->id,
>>> +
>>> ofp_flow_monitor_command_to_string(request->command));
>>> + return;
>>> + }
>>> ds_put_format(s, "\n id=%"PRIu32" flags=", request->id);
>>> - ofp_print_bit_names(s, request->flags,
>>> nx_flow_monitor_flags_to_name, ',');
>>> + ofp_print_bit_names(s, request->flags,
>>> + ofp_flow_monitor_flags_to_name, ',');
>>>
>>> if (request->out_port != OFPP_NONE) {
>>> ds_put_cstr(s, " out_port=");
>>> ofputil_format_port(request->out_port, port_map, s);
>>> }
>>>
>>> + if (request->out_group && (request->out_group != OFPG_ANY)) {
>>> + ds_put_format(s, " out_group=%d", request->out_group);
>>> + }
>>> +
>>> if (request->table_id != 0xff) {
>>> ds_put_format(s, " table=");
>>> ofputil_format_table(request->table_id, table_map, s);
>>> }
>>>
>>> - ds_put_char(s, ' ');
>>> - match_format(&request->match, port_map, s, OFP_DEFAULT_PRIORITY);
>>> - ds_chomp(s, ' ');
>>> + if (request->command != OFPFMC_DELETE) {
>>> + ds_put_char(s, ' ');
>>> + match_format(&request->match, port_map, s,
>>> OFP_DEFAULT_PRIORITY);
>>> + ds_chomp(s, ' ');
>>> + }
>>> }
>>>
>>> static char * OVS_WARN_UNUSED_RESULT
>>> @@ -464,9 +719,10 @@ parse_flow_monitor_request__(struct
>>> ofputil_flow_monitor_request *fmr,
>>>
>>> fmr->id = atomic_count_inc(&id);
>>>
>>> - fmr->flags = (NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE |
>>> NXFMF_MODIFY
>>> - | NXFMF_OWN | NXFMF_ACTIONS);
>>> + fmr->flags = (OFPFMF_INITIAL | OFPFMF_ADD | OFPFMF_REMOVED |
>>> OFPFMF_MODIFY
>>> + | OFPFMF_ONLY_OWN | OFPFMF_INSTRUCTIONS);
>>> fmr->out_port = OFPP_NONE;
>>> + fmr->out_group = OFPG_ANY;
>>> fmr->table_id = 0xff;
>>> match_init_catchall(&fmr->match);
>>>
>>> @@ -476,17 +732,19 @@ parse_flow_monitor_request__(struct
>>> ofputil_flow_monitor_request *fmr,
>>> char *error = NULL;
>>>
>>> if (!strcmp(name, "!initial")) {
>>> - fmr->flags &= ~NXFMF_INITIAL;
>>> + fmr->flags &= ~OFPFMF_INITIAL;
>>> } else if (!strcmp(name, "!add")) {
>>> - fmr->flags &= ~NXFMF_ADD;
>>> + fmr->flags &= ~OFPFMF_ADD;
>>> } else if (!strcmp(name, "!delete")) {
>>> - fmr->flags &= ~NXFMF_DELETE;
>>> + fmr->flags &= ~OFPFMF_REMOVED;
>>> } else if (!strcmp(name, "!modify")) {
>>> - fmr->flags &= ~NXFMF_MODIFY;
>>> + fmr->flags &= ~OFPFMF_MODIFY;
>>> } else if (!strcmp(name, "!actions")) {
>>> - fmr->flags &= ~NXFMF_ACTIONS;
>>> + fmr->flags &= ~OFPFMF_INSTRUCTIONS;
>>> + } else if (!strcmp(name, "!abbrev")) {
>>> + fmr->flags &= ~OFPFMF_NO_ABBREV;
>>> } else if (!strcmp(name, "!own")) {
>>> - fmr->flags &= ~NXFMF_OWN;
>>> + fmr->flags &= ~OFPFMF_ONLY_OWN;
>>> } else if (ofp_parse_protocol(name, &p)) {
>>> match_set_dl_type(&fmr->match, htons(p->dl_type));
>>> if (p->nw_proto) {
>>> @@ -511,6 +769,8 @@ parse_flow_monitor_request__(struct
>>> ofputil_flow_monitor_request *fmr,
>>> }
>>> } else if (!strcmp(name, "out_port")) {
>>> fmr->out_port = u16_to_ofp(atoi(value));
>>> + } else if (!strcmp(name, "out_group")) {
>>> + fmr->out_group = atoi(value);
>>> } else {
>>> return xasprintf("%s: unknown keyword %s", str_, name);
>>> }
>>> @@ -562,101 +822,226 @@ int
>>> ofputil_decode_flow_update(struct ofputil_flow_update *update,
>>> struct ofpbuf *msg, struct ofpbuf *ofpacts)
>>> {
>>> - struct nx_flow_update_header *nfuh;
>>> unsigned int length;
>>> struct ofp_header *oh;
>>> + enum ofperr error;
>>> + enum ofpraw raw;
>>>
>>> if (!msg->header) {
>>> ofpraw_pull_assert(msg);
>>> }
>>>
>>> + error = ofpraw_decode(&raw, msg->header);
>>> + if (error) {
>>> + return error;
>>> + }
>>> +
>>> ofpbuf_clear(ofpacts);
>>> if (!msg->size) {
>>> return EOF;
>>> }
>>>
>>> - if (msg->size < sizeof(struct nx_flow_update_header)) {
>>> - goto bad_len;
>>> - }
>>> -
>>> oh = msg->header;
>>>
>>> - nfuh = msg->data;
>>> - update->event = ntohs(nfuh->event);
>>> - length = ntohs(nfuh->length);
>>> - if (length > msg->size || length % 8) {
>>> - goto bad_len;
>>> - }
>>> + switch ((int) raw) {
>>> + case OFPRAW_ONFST13_FLOW_MONITOR_REPLY:
>>> + case OFPRAW_NXST_FLOW_MONITOR_REPLY: {
>>> + struct nx_flow_update_header *nfuh;
>>>
>>> - if (update->event == NXFME_ABBREV) {
>>> - struct nx_flow_update_abbrev *nfua;
>>> + if (msg->size < sizeof(struct nx_flow_update_header)) {
>>> + goto bad_len;
>>> + }
>>>
>>> - if (length != sizeof *nfua) {
>>> + nfuh = msg->data;
>>> + update->event = nx_to_ofp_flow_update_event(ntohs(nfuh->event));
>>> + length = ntohs(nfuh->length);
>>> + if (length > msg->size || length % 8) {
>>> goto bad_len;
>>> }
>>>
>>> - nfua = ofpbuf_pull(msg, sizeof *nfua);
>>> - update->xid = nfua->xid;
>>> - return 0;
>>> - } else if (update->event == NXFME_ADDED
>>> - || update->event == NXFME_DELETED
>>> - || update->event == NXFME_MODIFIED) {
>>> - struct nx_flow_update_full *nfuf;
>>> - unsigned int actions_len;
>>> - unsigned int match_len;
>>> - enum ofperr error;
>>> + if (update->event == OFPFME_ABBREV) {
>>> + struct nx_flow_update_abbrev *nfua;
>>> +
>>> + if (length != sizeof *nfua) {
>>> + goto bad_len;
>>> + }
>>> +
>>> + nfua = ofpbuf_pull(msg, sizeof *nfua);
>>> + update->xid = nfua->xid;
>>> + return 0;
>>> + } else if (update->event == OFPFME_ADDED
>>> + || update->event == OFPFME_REMOVED
>>> + || update->event == OFPFME_MODIFIED) {
>>> + struct nx_flow_update_full *nfuf;
>>> + unsigned int actions_len;
>>> + unsigned int match_len;
>>> +
>>> + if (length < sizeof *nfuf) {
>>> + goto bad_len;
>>> + }
>>>
>>> - if (length < sizeof *nfuf) {
>>> + nfuf = ofpbuf_pull(msg, sizeof *nfuf);
>>> + match_len = ntohs(nfuf->match_len);
>>> + if (sizeof *nfuf + match_len > length) {
>>> + goto bad_len;
>>> + }
>>> +
>>> + update->reason = ntohs(nfuf->reason);
>>> + update->idle_timeout = ntohs(nfuf->idle_timeout);
>>> + update->hard_timeout = ntohs(nfuf->hard_timeout);
>>> + update->table_id = nfuf->table_id;
>>> + update->cookie = nfuf->cookie;
>>> + update->priority = ntohs(nfuf->priority);
>>> +
>>> + if (raw == OFPRAW_ONFST13_FLOW_MONITOR_REPLY) {
>>> + uint16_t padded_match_len = 0;
>>> + unsigned int instructions_len;
>>> +
>>> + error = ofputil_pull_ofp11_match(
>>> + msg, NULL, NULL, &update->match, &padded_match_len);
>>> + if (error) {
>>> + return error;
>>> + }
>>> +
>>> + instructions_len = length - sizeof *nfuf -
>>> padded_match_len;
>>> + error = ofpacts_pull_openflow_instructions(
>>> + msg, instructions_len, oh->version, NULL, NULL,
>>> ofpacts);
>>> + if (error) {
>>> + return error;
>>> + }
>>> + } else {
>>> + error = nx_pull_match(msg, match_len, &update->match,
>>> NULL,
>>> + NULL, false, NULL, NULL);
>>> + if (error) {
>>> + return error;
>>> + }
>>> +
>>> + actions_len = length - sizeof *nfuf -
>>> ROUND_UP(match_len, 8);
>>> + error = ofpacts_pull_openflow_actions(
>>> + msg, actions_len, oh->version, NULL, NULL, ofpacts);
>>> + if (error) {
>>> + return error;
>>> + }
>>> + }
>>> +
>>> + update->ofpacts = ofpacts->data;
>>> + update->ofpacts_len = ofpacts->size;
>>> + return 0;
>>> + } else {
>>> + VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR reply has bad event
>>> %"PRIu16,
>>> + ntohs(nfuh->event));
>>> + return OFPERR_NXBRC_FM_BAD_EVENT;
>>> + }
>>> + }
>>> + case OFPRAW_OFPST14_FLOW_MONITOR_REPLY: {
>>> + struct ofp_flow_update_header *ofuh;
>>> + uint16_t padded_match_len = 0;
>>> +
>>> + if (msg->size < sizeof(struct ofp_flow_update_header)) {
>>> goto bad_len;
>>> }
>>>
>>> - nfuf = ofpbuf_pull(msg, sizeof *nfuf);
>>> - match_len = ntohs(nfuf->match_len);
>>> - if (sizeof *nfuf + match_len > length) {
>>> + ofuh = msg->data;
>>> + update->event = ntohs(ofuh->event);
>>> + length = ntohs(ofuh->length);
>>> + if (length > msg->size || length % 8) {
>>> goto bad_len;
>>> }
>>>
>>> - update->reason = ntohs(nfuf->reason);
>>> - update->idle_timeout = ntohs(nfuf->idle_timeout);
>>> - update->hard_timeout = ntohs(nfuf->hard_timeout);
>>> - update->table_id = nfuf->table_id;
>>> - update->cookie = nfuf->cookie;
>>> - update->priority = ntohs(nfuf->priority);
>>> + if (update->event == OFPFME_ABBREV) {
>>> + struct ofp_flow_update_abbrev *ofua;
>>>
>>> - error = nx_pull_match(msg, match_len, &update->match, NULL,
>>> NULL,
>>> - false, NULL, NULL);
>>> - if (error) {
>>> - return error;
>>> - }
>>> + if (length != sizeof *ofua) {
>>> + goto bad_len;
>>> + }
>>>
>>> - actions_len = length - sizeof *nfuf - ROUND_UP(match_len, 8);
>>> - error = ofpacts_pull_openflow_actions(msg, actions_len,
>>> oh->version,
>>> - NULL, NULL, ofpacts);
>>> - if (error) {
>>> - return error;
>>> - }
>>> + ofua = ofpbuf_pull(msg, sizeof *ofua);
>>> + update->xid = ofua->xid;
>>> + return 0;
>>> + } else if (update->event == OFPFME_PAUSED
>>> + || update->event == OFPFME_RESUMED) {
>>> + struct ofp_flow_update_paused *ofup;
>>>
>>> - update->ofpacts = ofpacts->data;
>>> - update->ofpacts_len = ofpacts->size;
>>> - return 0;
>>> - } else {
>>> - VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR reply has bad event
>>> %"PRIu16,
>>> - ntohs(nfuh->event));
>>> - return OFPERR_NXBRC_FM_BAD_EVENT;
>>> - }
>>> + if (length != sizeof *ofup) {
>>> + goto bad_len;
>>> + }
>>> +
>>> + ofup = ofpbuf_pull(msg, sizeof *ofup);
>>> + return 0;
>>> + } else if (update->event == OFPFME_INITIAL
>>> + || update->event == OFPFME_ADDED
>>> + || update->event == OFPFME_REMOVED
>>> + || update->event == OFPFME_MODIFIED) {
>>> + struct ofp_flow_update_full *ofuf;
>>> + unsigned int instructions_len;
>>> +
>>> + if (length < sizeof *ofuf) {
>>> + goto bad_len;
>>> + }
>>>
>>> + ofuf = ofpbuf_pull(msg, sizeof *ofuf);
>>> + if (sizeof *ofuf > length) {
>>> + goto bad_len;
>>> + }
>>> +
>>> + update->reason = ofuf->reason;
>>> + update->idle_timeout = ntohs(ofuf->idle_timeout);
>>> + update->hard_timeout = ntohs(ofuf->hard_timeout);
>>> + update->table_id = ofuf->table_id;
>>> + update->cookie = ofuf->cookie;
>>> + update->priority = ntohs(ofuf->priority);
>>> +
>>> + error = ofputil_pull_ofp11_match(
>>> + msg, NULL, NULL, &update->match, &padded_match_len);
>>> + if (error) {
>>> + return error;
>>> + }
>>> +
>>> + instructions_len = length - sizeof *ofuf - padded_match_len;
>>> + error = ofpacts_pull_openflow_instructions(
>>> + msg, instructions_len, oh->version, NULL, NULL,
>>> ofpacts);
>>> + if (error) {
>>> + return error;
>>> + }
>>> +
>>> + update->ofpacts = ofpacts->data;
>>> + update->ofpacts_len = ofpacts->size;
>>> + return 0;
>>> + } else {
>>> + VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR reply has bad event
>>> %"PRIu16,
>>> + ntohs(ofuh->event));
>>> + return OFPERR_NXBRC_FM_BAD_EVENT;
>>> + }
>>> + }
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> bad_len:
>>> - VLOG_WARN_RL(&rl, "NXST_FLOW_MONITOR reply has %"PRIu32" "
>>> - "leftover bytes at end", msg->size);
>>> + VLOG_WARN_RL(&rl, "%s reply has %"PRIu32" leftover bytes at end",
>>> + ofpraw_get_name(raw), msg->size);
>>> return OFPERR_OFPBRC_BAD_LEN;
>>> }
>>>
>>> uint32_t
>>> ofputil_decode_flow_monitor_cancel(const struct ofp_header *oh)
>>> {
>>> - const struct nx_flow_monitor_cancel *cancel = ofpmsg_body(oh);
>>> + enum ofperr error;
>>> + enum ofpraw raw;
>>>
>>> - return ntohl(cancel->id);
>>> + error = ofpraw_decode(&raw, oh);
>>> + if (error) {
>>> + return error;
>>> + }
>>> +
>>> + switch ((int) raw) {
>>> + case OFPRAW_ONFT13_FLOW_MONITOR_CANCEL:
>>> + case OFPRAW_NXT_FLOW_MONITOR_CANCEL: {
>>> + const struct nx_flow_monitor_cancel *cancel = ofpmsg_body(oh);
>>> + return ntohl(cancel->id);
>>> + }
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> }
>>>
>>> struct ofpbuf *
>>> @@ -666,9 +1051,99 @@ ofputil_encode_flow_monitor_cancel(uint32_t id,
>>> enum ofputil_protocol protocol)
>>> enum ofp_version version =
>>> ofputil_protocol_to_ofp_version(protocol);
>>> struct ofpbuf *msg;
>>>
>>> - msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MONITOR_CANCEL, version, 0);
>>> - nfmc = ofpbuf_put_uninit(msg, sizeof *nfmc);
>>> - nfmc->id = htonl(id);
>>> + switch (version) {
>>> + case OFP10_VERSION:
>>> + case OFP11_VERSION:
>>> + case OFP12_VERSION:
>>> + case OFP13_VERSION: {
>>> + if (version == OFP13_VERSION) {
>>> + msg = ofpraw_alloc(OFPRAW_ONFT13_FLOW_MONITOR_CANCEL,
>>> version, 0);
>>> + } else {
>>> + msg = ofpraw_alloc(OFPRAW_NXT_FLOW_MONITOR_CANCEL, version,
>>> 0);
>>> + }
>>> + nfmc = ofpbuf_put_uninit(msg, sizeof *nfmc);
>>> + nfmc->id = htonl(id);
>>> + break;
>>> + }
>>> + case OFP14_VERSION:
>>> + case OFP15_VERSION: {
>>> + struct ofp14_flow_monitor_request *ofmr;
>>> +
>>> + msg = ofpbuf_new(0);
>>> +
>>> + ofpraw_put(OFPRAW_OFPST14_FLOW_MONITOR_REQUEST, version, msg);
>>> +
>>> + size_t start_ofs = msg->size;
>>> + ofpbuf_put_zeros(msg, sizeof *ofmr);
>>> +
>>> + ofmr = ofpbuf_at_assert(msg, start_ofs, sizeof *ofmr);
>>> + ofmr->monitor_id = htonl(id);
>>> + ofmr->command = OFPFMC_DELETE;
>>> + break;
>>> + }
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> + return msg;
>>> +}
>>> +
>>> +struct ofpbuf *
>>> +ofputil_encode_flow_monitor_pause(enum ofp_flow_update_event command,
>>> + enum ofputil_protocol protocol)
>>> +{
>>> + struct ofpbuf *msg;
>>> + enum ofp_version version =
>>> ofputil_protocol_to_ofp_version(protocol);
>>> +
>>> + if (!(command == OFPFME_PAUSED || command == OFPFME_RESUMED)) {
>>> + OVS_NOT_REACHED();
>>> + }
>>> +
>>> + switch (version) {
>>> + case OFP10_VERSION:
>>> + case OFP11_VERSION:
>>> + case OFP12_VERSION:
>>> + if (command == OFPFME_PAUSED) {
>>> + msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_MONITOR_PAUSED,
>>> + version, htonl(0), 0);
>>> + } else {
>>> + msg = ofpraw_alloc_xid(OFPRAW_NXT_FLOW_MONITOR_RESUMED,
>>> + version, htonl(0), 0);
>>> + }
>>> + break;
>>> + case OFP13_VERSION:
>>> + if (command == OFPFME_PAUSED) {
>>> + msg = ofpraw_alloc_xid(OFPRAW_ONFT13_FLOW_MONITOR_PAUSED,
>>> + version, htonl(0), 0);
>>> + } else {
>>> + msg = ofpraw_alloc_xid(OFPRAW_ONFT13_FLOW_MONITOR_RESUMED,
>>> + version, htonl(0), 0);
>>> + }
>>> + break;
>>> + case OFP14_VERSION:
>>> + case OFP15_VERSION: {
>>> + msg = ofpraw_alloc_xid(OFPRAW_OFPST14_FLOW_MONITOR_REPLY,
>>> version,
>>> + htonl(0), 1024);
>>> + struct ofp_flow_update_header *ofuh;
>>> + size_t start_ofs = msg->size;
>>> +
>>> + struct ofp_flow_update_paused *ofup;
>>> +
>>> + ofpbuf_put_zeros(msg, sizeof *ofup);
>>> + ofup = ofpbuf_at_assert(msg, start_ofs, sizeof *ofup);
>>> + ofup->event = htons(command);
>>> + ofup->length = htons(8);
>>> +
>>> + ofuh = ofpbuf_at_assert(msg, start_ofs, sizeof *ofuh);
>>> + ofuh->length = htons(msg->size - start_ofs);
>>> + ofuh->event = htons(command);
>>> +
>>> + ofpmsg_update_length(msg);
>>> + break;
>>> + }
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>> +
>>> return msg;
>>> }
>>>
>>> @@ -679,8 +1154,25 @@ ofputil_start_flow_update(struct ovs_list *replies,
>>> struct ofpbuf *msg;
>>> enum ofp_version version =
>>> ofputil_protocol_to_ofp_version(protocol);
>>>
>>> - msg = ofpraw_alloc_xid(OFPRAW_NXST_FLOW_MONITOR_REPLY, version,
>>> - htonl(0), 1024);
>>> + switch (version) {
>>> + case OFP10_VERSION:
>>> + case OFP11_VERSION:
>>> + case OFP12_VERSION:
>>> + msg = ofpraw_alloc_xid(OFPRAW_NXST_FLOW_MONITOR_REPLY, version,
>>> + htonl(0), 1024);
>>> + break;
>>> + case OFP13_VERSION:
>>> + msg = ofpraw_alloc_xid(OFPRAW_ONFST13_FLOW_MONITOR_REPLY,
>>> version,
>>> + htonl(0), 1024);
>>> + break;
>>> + case OFP14_VERSION:
>>> + case OFP15_VERSION:
>>> + msg = ofpraw_alloc_xid(OFPRAW_OFPST14_FLOW_MONITOR_REPLY,
>>> version,
>>> + htonl(0), 1024);
>>> + break;
>>> + default:
>>> + OVS_NOT_REACHED();
>>> + }
>>>
>>> ovs_list_init(replies);
>>> ovs_list_push_back(replies, &msg->list_node);
>>> @@ -695,7 +1187,6 @@ ofputil_append_flow_update(const struct
>>> ofputil_flow_update *update,
>>> CONST_CAST(struct ofputil_flow_update *, update);
>>> const struct tun_table *orig_tun_table;
>>> enum ofp_version version = ofpmp_version(replies);
>>> - struct nx_flow_update_header *nfuh;
>>> struct ofpbuf *msg;
>>> size_t start_ofs;
>>>
>>> @@ -705,32 +1196,80 @@ ofputil_append_flow_update(const struct
>>> ofputil_flow_update *update,
>>> msg = ofpbuf_from_list(ovs_list_back(replies));
>>> start_ofs = msg->size;
>>>
>>> - if (update->event == NXFME_ABBREV) {
>>> - struct nx_flow_update_abbrev *nfua;
>>> + switch (version) {
>>> + case OFP10_VERSION:
>>> + case OFP11_VERSION:
>>> + case OFP12_VERSION:
>>> + case OFP13_VERSION: {
>>> + struct nx_flow_update_header *nfuh;
>>>
>>> - nfua = ofpbuf_put_zeros(msg, sizeof *nfua);
>>> - nfua->xid = update->xid;
>>> - } else {
>>> - struct nx_flow_update_full *nfuf;
>>> - int match_len;
>>> + if (update->event == OFPFME_ABBREV) {
>>> + struct nx_flow_update_abbrev *nfua;
>>>
>>> - ofpbuf_put_zeros(msg, sizeof *nfuf);
>>> - match_len = nx_put_match(msg, &update->match, htonll(0),
>>> htonll(0));
>>> - ofpacts_put_openflow_actions(update->ofpacts,
>>> update->ofpacts_len, msg,
>>> - version);
>>> - nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
>>> - nfuf->reason = htons(update->reason);
>>> - nfuf->priority = htons(update->priority);
>>> - nfuf->idle_timeout = htons(update->idle_timeout);
>>> - nfuf->hard_timeout = htons(update->hard_timeout);
>>> - nfuf->match_len = htons(match_len);
>>> - nfuf->table_id = update->table_id;
>>> - nfuf->cookie = update->cookie;
>>> - }
>>> + nfua = ofpbuf_put_zeros(msg, sizeof *nfua);
>>> + nfua->xid = update->xid;
>>> + } else {
>>> + struct nx_flow_update_full *nfuf;
>>> + int match_len;
>>> +
>>> + ofpbuf_put_zeros(msg, sizeof *nfuf);
>>> + if (version == OFP13_VERSION) {
>>> + match_len = oxm_put_match(msg, &update->match,
>>> version);
>>> + ofpacts_put_openflow_instructions(
>>> + update->ofpacts, update->ofpacts_len, msg,
>>> version);
>>> + } else {
>>> + match_len = nx_put_match(msg, &update->match,
>>> + htonll(0), htonll(0));
>>> + ofpacts_put_openflow_actions(
>>> + update->ofpacts, update->ofpacts_len, msg,
>>> version);
>>> + }
>>> + nfuf = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuf);
>>> + nfuf->reason = htons(update->reason);
>>> + nfuf->priority = htons(update->priority);
>>> + nfuf->idle_timeout = htons(update->idle_timeout);
>>> + nfuf->hard_timeout = htons(update->hard_timeout);
>>> + nfuf->match_len = htons(match_len);
>>> + nfuf->table_id = update->table_id;
>>> + nfuf->cookie = update->cookie;
>>> + }
>>> +
>>> + nfuh = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuh);
>>> + nfuh->length = htons(msg->size - start_ofs);
>>> + nfuh->event =
>>> htons(ofp_to_nx_flow_update_event(update->event));
>>> + break;
>>> + }
>>> + case OFP14_VERSION:
>>> + case OFP15_VERSION: {
>>> + struct ofp_flow_update_header *ofuh;
>>>
>>> - nfuh = ofpbuf_at_assert(msg, start_ofs, sizeof *nfuh);
>>> - nfuh->length = htons(msg->size - start_ofs);
>>> - nfuh->event = htons(update->event);
>>> + if (update->event == OFPFME_ABBREV) {
>>> + struct ofp_flow_update_abbrev *ofua;
>>> +
>>> + ofua = ofpbuf_put_zeros(msg, sizeof *ofua);
>>> + ofua->xid = update->xid;
>>> + } else {
>>> + struct ofp_flow_update_full *ofuf;
>>> +
>>> + ofpbuf_put_zeros(msg, sizeof *ofuf);
>>> + oxm_put_match(msg, &update->match, version);
>>> + ofpacts_put_openflow_instructions(update->ofpacts,
>>> + update->ofpacts_len,
>>> + msg, version);
>>> + ofuf = ofpbuf_at_assert(msg, start_ofs, sizeof *ofuf);
>>> + ofuf->reason = update->reason;
>>> + ofuf->priority = htons(update->priority);
>>> + ofuf->idle_timeout = htons(update->idle_timeout);
>>> + ofuf->hard_timeout = htons(update->hard_timeout);
>>> + ofuf->table_id = update->table_id;
>>> + ofuf->cookie = update->cookie;
>>> + }
>>> +
>>> + ofuh = ofpbuf_at_assert(msg, start_ofs, sizeof *ofuh);
>>> + ofuh->length = htons(msg->size - start_ofs);
>>> + ofuh->event = htons(update->event);
>>> + break;
>>> + }
>>> + }
>>>
>>> ofpmp_postappend(replies, start_ofs);
>>> update_->match.flow.tunnel.metadata.tab = orig_tun_table;
>>> @@ -746,24 +1285,37 @@ ofputil_flow_update_format(struct ds *s,
>>>
>>> ds_put_cstr(s, "\n event=");
>>> switch (update->event) {
>>> - case NXFME_ADDED:
>>> + case OFPFME_INITIAL:
>>> + ds_put_cstr(s, "INITIAL");
>>> + break;
>>> +
>>> + case OFPFME_ADDED:
>>> ds_put_cstr(s, "ADDED");
>>> break;
>>>
>>> - case NXFME_DELETED:
>>> + case OFPFME_REMOVED:
>>> ds_put_format(s, "DELETED reason=%s",
>>> ofp_flow_removed_reason_to_string(update->reason,
>>> reasonbuf,
>>> sizeof
>>> reasonbuf));
>>> break;
>>>
>>> - case NXFME_MODIFIED:
>>> + case OFPFME_MODIFIED:
>>> ds_put_cstr(s, "MODIFIED");
>>> break;
>>>
>>> - case NXFME_ABBREV:
>>> + case OFPFME_ABBREV:
>>> ds_put_format(s, "ABBREV xid=0x%"PRIx32, ntohl(update->xid));
>>> return;
>>> +
>>> + case OFPFME_PAUSED:
>>> + ds_put_cstr(s, "PAUSED");
>>> + return;
>>> +
>>> + case OFPFME_RESUMED:
>>> + ds_put_cstr(s, "RESUMED");
>>> + return;
>>> +
>>> }
>>>
>>> ds_put_format(s, " table=");
>>> diff --git a/lib/ofp-print.c b/lib/ofp-print.c
>>> index b0facbf9f..bd37fa17a 100644
>>> --- a/lib/ofp-print.c
>>> +++ b/lib/ofp-print.c
>>> @@ -744,10 +744,10 @@ ofp_print_nxt_flow_monitor_cancel(struct ds
>>> *string,
>>> }
>>>
>>> static enum ofperr
>>> -ofp_print_nxst_flow_monitor_request(struct ds *string,
>>> - const struct ofp_header *oh,
>>> - const struct ofputil_port_map
>>> *port_map,
>>> - const struct ofputil_table_map
>>> *table_map)
>>> +ofp_print_flow_monitor_request(struct ds *string,
>>> + const struct ofp_header *oh,
>>> + const struct ofputil_port_map *port_map,
>>> + const struct ofputil_table_map
>>> *table_map)
>>> {
>>> struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
>>> for (;;) {
>>> @@ -765,10 +765,10 @@ ofp_print_nxst_flow_monitor_request(struct ds
>>> *string,
>>> }
>>>
>>> static enum ofperr
>>> -ofp_print_nxst_flow_monitor_reply(struct ds *string,
>>> - const struct ofp_header *oh,
>>> - const struct ofputil_port_map
>>> *port_map,
>>> - const struct ofputil_table_map
>>> *table_map)
>>> +ofp_print_flow_monitor_reply(struct ds *string,
>>> + const struct ofp_header *oh,
>>> + const struct ofputil_port_map *port_map,
>>> + const struct ofputil_table_map *table_map)
>>> {
>>> uint64_t ofpacts_stub[1024 / 8];
>>> struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
>>> @@ -1147,12 +1147,12 @@ ofp_to_string__(const struct ofp_header *oh,
>>> break;
>>>
>>> case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
>>> - return ofp_print_nxst_flow_monitor_request(string, msg,
>>> port_map,
>>> - table_map);
>>> + return ofp_print_flow_monitor_request(string, msg, port_map,
>>> + table_map);
>>>
>>> case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
>>> - return ofp_print_nxst_flow_monitor_reply(string, msg, port_map,
>>> - table_map);
>>> + return ofp_print_flow_monitor_reply(string, msg, port_map,
>>> + table_map);
>>>
>>> case OFPTYPE_BUNDLE_CONTROL:
>>> return ofp_print_bundle_ctrl(string, msg);
>>> diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
>>> index c14834f84..325f45966 100644
>>> --- a/ofproto/connmgr.c
>>> +++ b/ofproto/connmgr.c
>>> @@ -2099,6 +2099,7 @@ ofmonitor_create(const struct
>>> ofputil_flow_monitor_request *request,
>>> m->id = request->id;
>>> m->flags = request->flags;
>>> m->out_port = request->out_port;
>>> + m->out_group = request->out_group;
>>> m->table_id = request->table_id;
>>> minimatch_init(&m->match, &request->match);
>>>
>>> @@ -2134,7 +2135,7 @@ ofmonitor_destroy(struct ofmonitor *m)
>>>
>>> void
>>> ofmonitor_report(struct connmgr *mgr, struct rule *rule,
>>> - enum nx_flow_update_event event,
>>> + enum ofp_flow_update_event event,
>>> enum ofp_flow_removed_reason reason,
>>> const struct ofconn *abbrev_ofconn, ovs_be32
>>> abbrev_xid,
>>> const struct rule_actions *old_actions)
>>> @@ -2144,39 +2145,42 @@ ofmonitor_report(struct connmgr *mgr, struct
>>> rule *rule,
>>> return;
>>> }
>>>
>>> - enum nx_flow_monitor_flags update;
>>> + enum ofp14_flow_monitor_flags update;
>>> switch (event) {
>>> - case NXFME_ADDED:
>>> - update = NXFMF_ADD;
>>> + case OFPFME_ADDED:
>>> + update = OFPFMF_ADD;
>>> rule->add_seqno = rule->modify_seqno = monitor_seqno++;
>>> break;
>>>
>>> - case NXFME_DELETED:
>>> - update = NXFMF_DELETE;
>>> + case OFPFME_REMOVED:
>>> + update = OFPFMF_REMOVED;
>>> break;
>>>
>>> - case NXFME_MODIFIED:
>>> - update = NXFMF_MODIFY;
>>> + case OFPFME_MODIFIED:
>>> + update = OFPFMF_MODIFY;
>>> rule->modify_seqno = monitor_seqno++;
>>> break;
>>>
>>> default:
>>> - case NXFME_ABBREV:
>>> + case OFPFME_INITIAL:
>>> + case OFPFME_PAUSED:
>>> + case OFPFME_RESUMED:
>>> + case OFPFME_ABBREV:
>>> OVS_NOT_REACHED();
>>> }
>>>
>>> struct ofconn *ofconn;
>>> LIST_FOR_EACH (ofconn, connmgr_node, &mgr->conns) {
>>> if (ofconn->monitor_paused) {
>>> - /* Only send NXFME_DELETED notifications for flows that
>>> were added
>>> + /* Only send OFPFME_REMOVED notifications for flows that
>>> were added
>>> * before we paused. */
>>> - if (event != NXFME_DELETED
>>> + if (event != OFPFME_REMOVED
>>> || rule->add_seqno > ofconn->monitor_paused) {
>>> continue;
>>> }
>>> }
>>>
>>> - enum nx_flow_monitor_flags flags = 0;
>>> + enum ofp14_flow_monitor_flags flags = 0;
>>> struct ofmonitor *m;
>>> HMAP_FOR_EACH (m, ofconn_node, &ofconn->monitors) {
>>> if (m->flags & update
>>> @@ -2186,6 +2190,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule
>>> *rule,
>>> && ofpacts_output_to_port(old_actions->ofpacts,
>>>
>>> old_actions->ofpacts_len,
>>> m->out_port)))
>>> + && ofproto_rule_has_out_group(rule, m->out_group)
>>> && cls_rule_is_loose_match(&rule->cr, &m->match)) {
>>> flags |= m->flags;
>>> }
>>> @@ -2198,12 +2203,12 @@ ofmonitor_report(struct connmgr *mgr, struct
>>> rule *rule,
>>> ofconn->sent_abbrev_update = false;
>>> }
>>>
>>> - if (flags & NXFMF_OWN || ofconn != abbrev_ofconn
>>> + if (flags & OFPFMF_ONLY_OWN || ofconn != abbrev_ofconn
>>> || ofconn->monitor_paused) {
>>> struct ofputil_flow_update fu;
>>>
>>> fu.event = event;
>>> - fu.reason = event == NXFME_DELETED ? reason : 0;
>>> + fu.reason = event == OFPFME_REMOVED ? reason : 0;
>>> fu.table_id = rule->table_id;
>>> fu.cookie = rule->flow_cookie;
>>> minimatch_expand(&rule->cr.match, &fu.match);
>>> @@ -2214,7 +2219,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule
>>> *rule,
>>> fu.hard_timeout = rule->hard_timeout;
>>> ovs_mutex_unlock(&rule->mutex);
>>>
>>> - if (flags & NXFMF_ACTIONS) {
>>> + if (flags & OFPFMF_INSTRUCTIONS) {
>>> const struct rule_actions *actions
>>> = rule_get_actions(rule);
>>> fu.ofpacts = actions->ofpacts;
>>> @@ -2228,7 +2233,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule
>>> *rule,
>>> } else if (!ofconn->sent_abbrev_update) {
>>> struct ofputil_flow_update fu;
>>>
>>> - fu.event = NXFME_ABBREV;
>>> + fu.event = OFPFME_ABBREV;
>>> fu.xid = abbrev_xid;
>>> ofputil_append_flow_update(&fu, &ofconn->updates,
>>>
>>> ofproto_get_tun_tab(rule->ofproto));
>>> @@ -2263,9 +2268,8 @@ ofmonitor_flush(struct connmgr *mgr)
>>> COVERAGE_INC(ofmonitor_pause);
>>> ofconn->monitor_paused = monitor_seqno++;
>>> protocol = ofconn_get_protocol(ofconn);
>>> - struct ofpbuf *pause = ofpraw_alloc_xid(
>>> - OFPRAW_NXT_FLOW_MONITOR_PAUSED,
>>> - ofputil_protocol_to_ofp_version(protocol), htonl(0), 0);
>>> + struct ofpbuf *pause = ofputil_encode_flow_monitor_pause(
>>> + OFPFME_PAUSED,protocol);
>>> ofconn_send(ofconn, pause, counter);
>>> }
>>> }
>>> @@ -2289,9 +2293,8 @@ ofmonitor_resume(struct ofconn *ofconn)
>>> ofconn_get_protocol(ofconn));
>>>
>>> protocol = ofconn_get_protocol(ofconn);
>>> - struct ofpbuf *resumed = ofpraw_alloc_xid(
>>> - OFPRAW_NXT_FLOW_MONITOR_RESUMED,
>>> - ofputil_protocol_to_ofp_version(protocol), htonl(0), 0);
>>> + struct ofpbuf *resumed = ofputil_encode_flow_monitor_pause(
>>> + OFPFME_RESUMED, protocol);
>>> ovs_list_push_back(&msgs, &resumed->list_node);
>>> ofconn_send_replies(ofconn, &msgs);
>>>
>>> diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
>>> index 56fdc3504..3471d38f9 100644
>>> --- a/ofproto/connmgr.h
>>> +++ b/ofproto/connmgr.h
>>> @@ -168,10 +168,11 @@ struct ofmonitor {
>>> struct hmap_node ofconn_node; /* In ofconn's 'monitors' hmap. */
>>> uint32_t id;
>>>
>>> - enum nx_flow_monitor_flags flags;
>>> + enum ofp14_flow_monitor_flags flags;
>>>
>>> /* Matching. */
>>> ofp_port_t out_port;
>>> + uint32_t out_group;
>>> uint8_t table_id;
>>> struct minimatch match;
>>> };
>>> @@ -187,7 +188,8 @@ void ofmonitor_destroy(struct ofmonitor *)
>>> OVS_REQUIRES(ofproto_mutex);
>>>
>>> void ofmonitor_report(struct connmgr *, struct rule *,
>>> - enum nx_flow_update_event, enum
>>> ofp_flow_removed_reason,
>>> + enum ofp_flow_update_event event,
>>> + enum ofp_flow_removed_reason,
>>> const struct ofconn *abbrev_ofconn, ovs_be32
>>> abbrev_xid,
>>> const struct rule_actions *old_actions)
>>> OVS_REQUIRES(ofproto_mutex);
>>> diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
>>> index 57c7d17cb..373526738 100644
>>> --- a/ofproto/ofproto-provider.h
>>> +++ b/ofproto/ofproto-provider.h
>>> @@ -419,7 +419,7 @@ struct rule {
>>> * 'add_seqno' is the sequence number when this rule was created.
>>> * 'modify_seqno' is the sequence number when this rule was last
>>> modified.
>>> * See 'monitor_seqno' in connmgr.c for more information. */
>>> - enum nx_flow_monitor_flags monitor_flags
>>> OVS_GUARDED_BY(ofproto_mutex);
>>> + enum ofp14_flow_monitor_flags monitor_flags
>>> OVS_GUARDED_BY(ofproto_mutex);
>>> uint64_t add_seqno OVS_GUARDED_BY(ofproto_mutex);
>>> uint64_t modify_seqno OVS_GUARDED_BY(ofproto_mutex);
>>>
>>> @@ -480,6 +480,8 @@ const struct rule_actions *rule_actions_create(const
>>> struct ofpact *, size_t);
>>> void rule_actions_destroy(const struct rule_actions *);
>>> bool ofproto_rule_has_out_port(const struct rule *, ofp_port_t port)
>>> OVS_REQUIRES(ofproto_mutex);
>>> +bool ofproto_rule_has_out_group(const struct rule *rule, uint32_t
>>> group_id)
>>> + OVS_REQUIRES(ofproto_mutex);
>>>
>>> #define DECL_OFPROTO_COLLECTION(TYPE, NAME)
>>> \
>>> DECL_OBJECT_COLLECTION(TYPE, NAME)
>>> \
>>> diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
>>> index 11aadbf20..980d4d53b 100644
>>> --- a/ofproto/ofproto.c
>>> +++ b/ofproto/ofproto.c
>>> @@ -3157,7 +3157,7 @@ ofproto_rule_has_out_port(const struct rule *rule,
>>> ofp_port_t port)
>>> }
>>>
>>> /* Returns true if 'rule' has group and equals group_id. */
>>> -static bool
>>> +bool
>>> ofproto_rule_has_out_group(const struct rule *rule, uint32_t group_id)
>>> OVS_REQUIRES(ofproto_mutex)
>>> {
>>> @@ -5215,7 +5215,7 @@ add_flow_finish(struct ofproto *ofproto, struct
>>> ofproto_flow_mod *ofm,
>>> if (old_rule) {
>>> ovsrcu_postpone(remove_rule_rcu, old_rule);
>>> } else {
>>> - ofmonitor_report(ofproto->connmgr, new_rule, NXFME_ADDED, 0,
>>> + ofmonitor_report(ofproto->connmgr, new_rule, OFPFME_ADDED, 0,
>>> req ? req->ofconn : NULL,
>>> req ? req->request->xid : 0, NULL);
>>>
>>> @@ -5630,8 +5630,8 @@ replace_rule_finish(struct ofproto *ofproto,
>>> struct ofproto_flow_mod *ofm,
>>> learned_cookies_dec(ofproto, old_actions, dead_cookies);
>>>
>>> if (replaced_rule) {
>>> - enum nx_flow_update_event event = ofm->command == OFPFC_ADD
>>> - ? NXFME_ADDED : NXFME_MODIFIED;
>>> + enum ofp_flow_update_event event = ofm->command == OFPFC_ADD
>>> + ? OFPFME_ADDED : OFPFME_MODIFIED;
>>>
>>> bool changed_cookie = (new_rule->flow_cookie
>>> != old_rule->flow_cookie);
>>> @@ -5641,7 +5641,7 @@ replace_rule_finish(struct ofproto *ofproto,
>>> struct ofproto_flow_mod *ofm,
>>> old_actions->ofpacts,
>>>
>>> old_actions->ofpacts_len);
>>>
>>> - if (event != NXFME_MODIFIED || changed_actions
>>> + if (event != OFPFME_MODIFIED || changed_actions
>>> || changed_cookie) {
>>> ofmonitor_report(ofproto->connmgr, new_rule, event, 0,
>>> req ? req->ofconn : NULL,
>>> @@ -5650,7 +5650,7 @@ replace_rule_finish(struct ofproto *ofproto,
>>> struct ofproto_flow_mod *ofm,
>>> }
>>> } else {
>>> /* XXX: This is slight duplication with
>>> delete_flows_finish__() */
>>> - ofmonitor_report(ofproto->connmgr, old_rule, NXFME_DELETED,
>>> + ofmonitor_report(ofproto->connmgr, old_rule, OFPFME_REMOVED,
>>> OFPRR_EVICTION,
>>> req ? req->ofconn : NULL,
>>> req ? req->request->xid : 0, NULL);
>>> @@ -5931,7 +5931,7 @@ delete_flows_finish__(struct ofproto *ofproto,
>>> * before the rule is actually destroyed. */
>>> rule->removed_reason = reason;
>>>
>>> - ofmonitor_report(ofproto->connmgr, rule, NXFME_DELETED,
>>> reason,
>>> + ofmonitor_report(ofproto->connmgr, rule, OFPFME_REMOVED,
>>> reason,
>>> req ? req->ofconn : NULL,
>>> req ? req->request->xid : 0, NULL);
>>>
>>> @@ -6337,7 +6337,7 @@ handle_barrier_request(struct ofconn *ofconn,
>>> const struct ofp_header *oh)
>>>
>>> static void
>>> ofproto_compose_flow_refresh_update(const struct rule *rule,
>>> - enum nx_flow_monitor_flags flags,
>>> + enum ofp14_flow_monitor_flags flags,
>>> struct ovs_list *msgs,
>>> const struct tun_table *tun_table,
>>> enum ofputil_protocol protocol)
>>> @@ -6346,8 +6346,9 @@ ofproto_compose_flow_refresh_update(const struct
>>> rule *rule,
>>> const struct rule_actions *actions;
>>> struct ofputil_flow_update fu;
>>>
>>> - fu.event = (flags & (NXFMF_INITIAL | NXFMF_ADD)
>>> - ? NXFME_ADDED : NXFME_MODIFIED);
>>> + fu.event = flags & OFPFMF_INITIAL ? OFPFME_INITIAL :
>>> + flags & OFPFMF_ADD ?
>>> + OFPFME_ADDED : OFPFME_MODIFIED;
>>> fu.reason = 0;
>>> ovs_mutex_lock(&rule->mutex);
>>> fu.idle_timeout = rule->idle_timeout;
>>> @@ -6358,7 +6359,7 @@ ofproto_compose_flow_refresh_update(const struct
>>> rule *rule,
>>> minimatch_expand(&rule->cr.match, &fu.match);
>>> fu.priority = rule->cr.priority;
>>>
>>> - actions = flags & NXFMF_ACTIONS ? rule_get_actions(rule) : NULL;
>>> + actions = flags & OFPFMF_INSTRUCTIONS ? rule_get_actions(rule) :
>>> NULL;
>>> fu.ofpacts = actions ? actions->ofpacts : NULL;
>>> fu.ofpacts_len = actions ? actions->ofpacts_len : 0;
>>>
>>> @@ -6377,7 +6378,7 @@ ofmonitor_compose_refresh_updates(struct
>>> rule_collection *rules,
>>> struct rule *rule;
>>>
>>> RULE_COLLECTION_FOR_EACH (rule, rules) {
>>> - enum nx_flow_monitor_flags flags = rule->monitor_flags;
>>> + enum ofp14_flow_monitor_flags flags = rule->monitor_flags;
>>> rule->monitor_flags = 0;
>>>
>>> ofproto_compose_flow_refresh_update(rule, flags, msgs,
>>> @@ -6391,7 +6392,7 @@ ofproto_collect_ofmonitor_refresh_rule(const
>>> struct ofmonitor *m,
>>> struct rule_collection *rules)
>>> OVS_REQUIRES(ofproto_mutex)
>>> {
>>> - enum nx_flow_monitor_flags update;
>>> + enum ofp14_flow_monitor_flags update;
>>>
>>> if (rule_is_hidden(rule)) {
>>> return;
>>> @@ -6401,11 +6402,15 @@ ofproto_collect_ofmonitor_refresh_rule(const
>>> struct ofmonitor *m,
>>> return;
>>> }
>>>
>>> + if (!ofproto_rule_has_out_group(rule, m->out_group)) {
>>> + return;
>>> + }
>>> +
>>> if (seqno) {
>>> if (rule->add_seqno > seqno) {
>>> - update = NXFMF_ADD | NXFMF_MODIFY;
>>> + update = OFPFMF_ADD | OFPFMF_MODIFY;
>>> } else if (rule->modify_seqno > seqno) {
>>> - update = NXFMF_MODIFY;
>>> + update = OFPFMF_MODIFY;
>>> } else {
>>> return;
>>> }
>>> @@ -6414,13 +6419,13 @@ ofproto_collect_ofmonitor_refresh_rule(const
>>> struct ofmonitor *m,
>>> return;
>>> }
>>> } else {
>>> - update = NXFMF_INITIAL;
>>> + update = OFPFMF_INITIAL;
>>> }
>>>
>>> if (!rule->monitor_flags) {
>>> rule_collection_add(rules, rule);
>>> }
>>> - rule->monitor_flags |= update | (m->flags & NXFMF_ACTIONS);
>>> + rule->monitor_flags |= update | (m->flags & OFPFMF_INSTRUCTIONS);
>>> }
>>>
>>> static void
>>> @@ -6449,7 +6454,7 @@ ofproto_collect_ofmonitor_initial_rules(struct
>>> ofmonitor *m,
>>> struct rule_collection *rules)
>>> OVS_REQUIRES(ofproto_mutex)
>>> {
>>> - if (m->flags & NXFMF_INITIAL) {
>>> + if (m->flags & OFPFMF_INITIAL) {
>>> ofproto_collect_ofmonitor_refresh_rules(m, 0, rules);
>>> }
>>> }
>>> @@ -6512,16 +6517,50 @@ handle_flow_monitor_request(struct ofconn
>>> *ofconn, const struct ovs_list *msgs)
>>> }
>>>
>>> struct ofmonitor *m;
>>> - error = ofmonitor_create(&request, ofconn, &m);
>>> - if (error) {
>>> - goto error;
>>> + switch (request.command) {
>>> + case OFPFMC_ADD: {
>>> + error = ofmonitor_create(&request, ofconn, &m);
>>> + if (error) {
>>> + goto error;
>>> + }
>>> +
>>> + if (n_monitors >= allocated_monitors) {
>>> + monitors = x2nrealloc(monitors, &allocated_monitors,
>>> + sizeof *monitors);
>>> + }
>>> + monitors[n_monitors++] = m;
>>> + break;
>>> }
>>> + case OFPFMC_MODIFY:
>>> + /* Modify operation is to delete old monitor and create
>>> a
>>> + * new one. */
>>> + m = ofmonitor_lookup(ofconn, request.id);
>>> + if (!m) {
>>> + error = OFPERR_OFPMOFC_UNKNOWN_MONITOR;
>>> + goto error;
>>> + }
>>> + ofmonitor_destroy(m);
>>> +
>>> + error = ofmonitor_create(&request, ofconn, &m);
>>> + if (error) {
>>> + goto error;
>>> + }
>>>
>>> - if (n_monitors >= allocated_monitors) {
>>> - monitors = x2nrealloc(monitors, &allocated_monitors,
>>> - sizeof *monitors);
>>> + if (n_monitors >= allocated_monitors) {
>>> + monitors = x2nrealloc(monitors, &allocated_monitors,
>>> + sizeof *monitors);
>>> + }
>>> + monitors[n_monitors++] = m;
>>> + break;
>>> + case OFPFMC_DELETE:
>>> + m = ofmonitor_lookup(ofconn, request.id);
>>> + if (!m) {
>>> + error = OFPERR_OFPMOFC_UNKNOWN_MONITOR;
>>> + goto error;
>>> + }
>>> + ofmonitor_destroy(m);
>>> + break;
>>> }
>>> - monitors[n_monitors++] = m;
>>> continue;
>>>
>>> error:
>>> diff --git a/tests/ofp-print.at b/tests/ofp-print.at
>>> index 2c7e163bd..ab5c37649 100644
>>> --- a/tests/ofp-print.at
>>> +++ b/tests/ofp-print.at
>>> @@ -3258,32 +3258,89 @@ NXT_SET_CONTROLLER_ID (xid=0x3): id=123
>>> ])
>>> AT_CLEANUP
>>>
>>> -AT_SETUP([NXT_FLOW_MONITOR_CANCEL])
>>> +AT_SETUP([FLOW_MONITOR_CANCEL])
>>> AT_KEYWORDS([ofp-print])
>>> +
>>> +dnl OpenFlow 1.0-1.2
>>> AT_CHECK([ovs-ofctl ofp-print "\
>>> 01 04 00 14 00 00 00 03 00 00 23 20 00 00 00 15 \
>>> 01 02 30 40 \
>>> "], [0], [dnl
>>> NXT_FLOW_MONITOR_CANCEL (xid=0x3): id=16920640
>>> ])
>>> +
>>> +dnl OpenFlow 1.3
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +04 04 00 14 00 00 00 06 4f 4e 46 00 00 00 07 4e \
>>> +01 02 30 40 \
>>> +"], [0], [dnl
>>> +ONFT_FLOW_MONITOR_CANCEL (OF1.3) (xid=0x6): id=16920640
>>> +])
>>> +
>>> +dnl OpenFlow 1.4+
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +05 12 00 28 00 00 00 04 00 10 00 00 00 00 00 00 \
>>> +01 02 30 40 00 00 00 00 00 00 00 00 00 00 00 02 \
>>> +00 01 00 04 00 00 00 00 \
>>> +"], [0], [dnl
>>> +OFPST_FLOW_MONITOR request (OF1.4) (xid=0x4):
>>> + id=16920640 command=delete
>>> +])
>>> +
>>> AT_CLEANUP
>>>
>>> -AT_SETUP([NXT_FLOW_MONITOR_PAUSED])
>>> +AT_SETUP([FLOW_MONITOR_PAUSED])
>>> AT_KEYWORDS([ofp-print])
>>> +
>>> +dnl OpenFlow 1.0-1.2
>>> AT_CHECK([ovs-ofctl ofp-print "\
>>> 01 04 00 10 00 00 00 03 00 00 23 20 00 00 00 16 \
>>> "], [0], [dnl
>>> NXT_FLOW_MONITOR_PAUSED (xid=0x3):
>>> ])
>>> +
>>> +dnl OpenFlow 1.3
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +04 04 00 10 00 00 00 03 4f 4e 46 00 00 00 07 4F \
>>> +"], [0], [dnl
>>> +ONFT_FLOW_MONITOR_PAUSED (OF1.3) (xid=0x3):
>>> +])
>>> +
>>> +dnl OpenFlow 1.4+
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +05 13 00 18 00 00 00 00 00 10 00 00 00 00 00 00 \
>>> +00 08 00 05 00 00 00 00 \
>>> +"], [0], [dnl
>>> +OFPST_FLOW_MONITOR reply (OF1.4) (xid=0x0):
>>> + event=PAUSED
>>> +])
>>> AT_CLEANUP
>>>
>>> -AT_SETUP([NXT_FLOW_MONITOR_RESUMED])
>>> +AT_SETUP([FLOW_MONITOR_RESUMED])
>>> AT_KEYWORDS([ofp-print])
>>> +
>>> +dnl OpenFlow 1.0-1.2
>>> AT_CHECK([ovs-ofctl ofp-print "\
>>> 01 04 00 10 00 00 00 03 00 00 23 20 00 00 00 17 \
>>> "], [0], [dnl
>>> NXT_FLOW_MONITOR_RESUMED (xid=0x3):
>>> ])
>>> +
>>> +dnl OpenFlow 1.3
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +04 04 00 10 00 00 00 03 4f 4e 46 00 00 00 07 50 \
>>> +"], [0], [dnl
>>> +ONFT_FLOW_MONITOR_RESUMED (OF1.3) (xid=0x3):
>>> +])
>>> +
>>> +dnl OpenFlow 1.4+
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +05 13 00 18 00 00 00 00 00 10 00 00 00 00 00 00
>>> +00 08 00 06 00 00 00 00
>>> +"], [0], [dnl
>>> +OFPST_FLOW_MONITOR reply (OF1.4) (xid=0x0):
>>> + event=RESUMED
>>> +])
>>> AT_CLEANUP
>>>
>>> AT_SETUP([NXT_SET_FLOW_FORMAT])
>>> @@ -3629,8 +3686,10 @@ NXST_AGGREGATE reply (xid=0x4): packet_count=7
>>> byte_count=420 flow_count=7
>>> ])
>>> AT_CLEANUP
>>>
>>> -AT_SETUP([NXST_FLOW_MONITOR request])
>>> +AT_SETUP([FLOW_MONITOR request])
>>> AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
>>> +
>>> +dnl OpenFlow 1.0-1.2
>>> AT_CHECK([ovs-ofctl ofp-print "\
>>> 01 10 00 40 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 02 00 00 00 00
>>> \
>>> 00 00 40 00 00 3f ff fe 00 00 01 00 00 00 00 00 \
>>> @@ -3640,10 +3699,37 @@ NXST_FLOW_MONITOR request (xid=0x4):
>>> id=16384 flags=initial,add,delete,modify,actions,own out_port=LOCAL
>>> table=1
>>> id=8192 flags=delete table=2 in_port=1
>>> ])
>>> +
>>> +dnl OpenFlow 1.3
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +04 12 00 48 00 00 00 06 ff ff 00 00 00 00 00 00 \
>>> +4f 4e 46 00 00 00 07 4e \
>>> +00 00 10 00 00 3f 00 04 ff ff ff fe 01 00 00 00 00 01 00 04 00 00 00 00
>>> \
>>> +00 00 20 00 00 04 ff ff 00 00 00 02 01 00 00 00 00 01 00 04 00 00 00 00
>>> \
>>> +"], [0], [dnl
>>> +ONFST_FLOW_MONITOR request (OF1.3) (xid=0x6):
>>> + id=4096 flags=initial,add,delete,modify,actions,own out_port=LOCAL
>>> table=1
>>> + id=8192 flags=delete out_port=2 table=1
>>> +])
>>> +
>>> +dnl OpenFlow 1.4+
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +05 12 00 58 00 00 00 06 00 10 00 00 00 00 00 00 \
>>> +00 00 10 00 ff ff ff fe ff ff ff ff 00 5f 00 00 00 01 00 04 00 00 00 00
>>> \
>>> +00 00 20 00 00 00 00 01 00 00 00 40 00 5f 01 01 00 01 00 04 00 00 00 00
>>> \
>>> +00 00 40 00 00 00 00 02 00 00 00 40 00 5f 02 02 00 01 00 04 00 00 00 00
>>> \
>>> +"], [0], [dnl
>>> +OFPST_FLOW_MONITOR request (OF1.4) (xid=0x6):
>>> + id=4096 flags=initial,add,delete,modify,actions,own out_port=LOCAL
>>> table=0
>>> + id=8192 flags=initial,add,delete,modify,actions,own out_port=1
>>> out_group=64 table=1
>>> + id=16384 command=delete
>>> +])
>>> AT_CLEANUP
>>>
>>> -AT_SETUP([NXST_FLOW_MONITOR reply])
>>> +AT_SETUP([FLOW_MONITOR reply])
>>> AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
>>> +
>>> +dnl OpenFlow 1.0-1.2
>>> AT_CHECK([ovs-ofctl ofp-print "\
>>> 01 11 00 40 00 00 00 04 ff ff 00 00 00 00 23 20 00 00 00 02 00 00 00 00
>>> \
>>> 00 20 00 01 00 05 80 00 00 05 00 10 00 06 01 00 12 34 56 78 9a bc de f0
>>> \
>>> @@ -3654,6 +3740,32 @@ NXST_FLOW_MONITOR reply (xid=0x4):
>>> event=DELETED reason=eviction table=1 idle_timeout=5 hard_timeout=16
>>> cookie=0x123456789abcdef0 in_port=1
>>> event=ABBREV xid=0x186a0
>>> ])
>>> +
>>> +dnl OpenFlow 1.3
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +04 13 00 48 00 00 00 06 ff ff 00 00 00 00 00 00 4f 4e 46 00 00 00 07 4e
>>> \
>>> +00 28 00 01 00 05 80 00 00 00 00 00 00 0c 00 00 \
>>> +12 34 56 78 9a bc de f0 00 01 00 0c 80 00 00 04 \
>>> +00 00 00 01 00 00 00 00 \
>>> +00 08 00 03 00 01 86 a0 \
>>> +"], [0], [dnl
>>> +ONFST_FLOW_MONITOR reply (OF1.3) (xid=0x6):
>>> + event=DELETED reason=eviction table=0 cookie=0x123456789abcdef0
>>> in_port=1
>>> + event=ABBREV xid=0x186a0
>>> +])
>>> +
>>> +dnl OpenFlow 1.4+
>>> +AT_CHECK([ovs-ofctl ofp-print "\
>>> +05 13 00 40 00 00 00 00 00 10 00 00 00 00 00 00 \
>>> +00 28 00 02 00 05 00 00 00 00 80 00 00 00 00 00 \
>>> +12 34 56 78 9a bc de f0 00 01 00 0c 80 00 00 04 \
>>> +00 00 00 01 00 00 00 00 \
>>> +00 08 00 04 00 01 86 a0 \
>>> +"], [0], [dnl
>>> +OFPST_FLOW_MONITOR reply (OF1.4) (xid=0x0):
>>> + event=DELETED reason=eviction table=0 cookie=0x123456789abcdef0
>>> in_port=1
>>> + event=ABBREV xid=0x186a0
>>> +])
>>> AT_CLEANUP
>>>
>>>
>>> diff --git a/tests/ofproto.at b/tests/ofproto.at
>>> index 899c0be55..3502454b9 100644
>>> --- a/tests/ofproto.at
>>> +++ b/tests/ofproto.at
>>> @@ -4592,8 +4592,11 @@ ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=123,actions=output:1
>>> ovs-ofctl -O $2 monitor br0 watch: --detach --no-chdir --pidfile
>>> >monitor.log 2>&1
>>> AT_CAPTURE_FILE([monitor.log])
>>> ovs-appctl -t ovs-ofctl ofctl/barrier
>>> +
>>> +# For OF(1.4+), replace INITIAL to ADDED
>>> +sed -i'.raw' -e 's|event=INITIAL|event=ADDED|' monitor.log
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0],
>>> - [NXST_FLOW_MONITOR reply$3:
>>> + [$4 reply$3:
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=123 actions=output:1
>>> OFPT_BARRIER_REPLY$3:
>>> ])
>>> @@ -4607,7 +4610,7 @@ ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=123,dl_vlan_pcp=1,actions=output:7
>>> ovs-ofctl add-flow br0 in_port=0,dl_vlan=123,actions=output:8
>>> ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=65535,dl_vlan_pcp=0,actions=output:9
>>> ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=65535,dl_vlan_pcp=1,actions=output:10
>>> -ovs-ofctl add-flow br0 in_port=0,dl_vlan=65535,actions=output:11
>>> +ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=65535,dl_vlan_pcp=3,actions=output:11
>>> ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=8191,dl_vlan_pcp=0,actions=output:12
>>> ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=8191,dl_vlan_pcp=1,actions=output:13
>>> ovs-ofctl add-flow br0 in_port=0,dl_vlan=8191,actions=output:14
>>> @@ -4625,71 +4628,74 @@ ovs-ofctl mod-flows br0
>>> cookie=5,dl_vlan=123,actions=output:3
>>> ovs-ofctl del-flows br0 dl_vlan=123
>>> ovs-ofctl del-flows br0
>>> ovs-appctl -t ovs-ofctl ofctl/barrier
>>> +
>>> +# For OF(1.4+), replace INITIAL to ADDED
>>> +sed -i'.raw' -e 's|event=INITIAL|event=ADDED|' monitor.log
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log |
>>> multiline_sort], [0],
>>> -[NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +[$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=124 actions=output:2
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=123 actions=output:5
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=123,dl_vlan_pcp=0
>>> actions=output:6
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=123,dl_vlan_pcp=1
>>> actions=output:7
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=123 actions=output:8
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0,dl_vlan_pcp=0
>>> actions=output:9
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0,dl_vlan_pcp=1
>>> actions=output:10
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> - event=ADDED table=0 cookie=0 in_port=0,vlan_tci=0x0000
>>> actions=output:11
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> + event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0,dl_vlan_pcp=3
>>> actions=output:11
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=4095,dl_vlan_pcp=0
>>> actions=output:12
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=4095,dl_vlan_pcp=1
>>> actions=output:13
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=4095 actions=output:14
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0,dl_vlan_pcp=0
>>> actions=output:15
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0,dl_vlan_pcp=1
>>> actions=output:16
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0 actions=output:17
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0,dl_vlan_pcp=0
>>> actions=output:18
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0,dl_vlan_pcp=1
>>> actions=output:19
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=0 actions=output:20
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan_pcp=0 actions=output:21
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan_pcp=1 actions=output:22
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=0 actions=output:23
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=123 actions=output:3
>>> event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=123,dl_vlan_pcp=0
>>> actions=output:3
>>> event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=123,dl_vlan_pcp=1
>>> actions=output:3
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=MODIFIED table=0 cookie=0x5 in_port=0,dl_vlan=123
>>> actions=output:3
>>> event=MODIFIED table=0 cookie=0x5 in_port=0,dl_vlan=123,dl_vlan_pcp=0
>>> actions=output:3
>>> event=MODIFIED table=0 cookie=0x5 in_port=0,dl_vlan=123,dl_vlan_pcp=1
>>> actions=output:3
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=DELETED reason=delete table=0 cookie=0x5 in_port=0,dl_vlan=123
>>> actions=output:3
>>> event=DELETED reason=delete table=0 cookie=0x5
>>> in_port=0,dl_vlan=123,dl_vlan_pcp=0 actions=output:3
>>> event=DELETED reason=delete table=0 cookie=0x5
>>> in_port=0,dl_vlan=123,dl_vlan_pcp=1 actions=output:3
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=DELETED reason=delete table=0 cookie=0 in_port=0
>>> actions=output:23
>>> event=DELETED reason=delete table=0 cookie=0 in_port=0,dl_vlan=0
>>> actions=output:20
>>> event=DELETED reason=delete table=0 cookie=0
>>> in_port=0,dl_vlan=0,dl_vlan_pcp=0 actions=output:18
>>> event=DELETED reason=delete table=0 cookie=0
>>> in_port=0,dl_vlan=0,dl_vlan_pcp=1 actions=output:19
>>> + event=DELETED reason=delete table=0 cookie=0
>>> in_port=0,dl_vlan=0,dl_vlan_pcp=3 actions=output:11
>>> event=DELETED reason=delete table=0 cookie=0 in_port=0,dl_vlan=124
>>> actions=output:2
>>> event=DELETED reason=delete table=0 cookie=0 in_port=0,dl_vlan=4095
>>> actions=output:14
>>> event=DELETED reason=delete table=0 cookie=0
>>> in_port=0,dl_vlan=4095,dl_vlan_pcp=0 actions=output:12
>>> event=DELETED reason=delete table=0 cookie=0
>>> in_port=0,dl_vlan=4095,dl_vlan_pcp=1 actions=output:13
>>> event=DELETED reason=delete table=0 cookie=0 in_port=0,dl_vlan_pcp=0
>>> actions=output:21
>>> event=DELETED reason=delete table=0 cookie=0 in_port=0,dl_vlan_pcp=1
>>> actions=output:22
>>> - event=DELETED reason=delete table=0 cookie=0 in_port=0,vlan_tci=0x0000
>>> actions=output:11
>>> OFPT_BARRIER_REPLY$3:
>>> ])
>>>
>>> @@ -4703,13 +4709,13 @@ ovs-appctl -t ovs-ofctl ofctl/barrier
>>> AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], [0], [NXST_FLOW
>>> reply:
>>> ])
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log |
>>> multiline_sort], [0],
>>> -[NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +[$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=1 actions=output:2
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=2 actions=output:1
>>> OFPT_BARRIER_REPLY$3:
>>> send: OFPT_FLOW_MOD$3: DEL actions=drop
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=DELETED reason=delete table=0 cookie=0 in_port=1 actions=output:2
>>> event=DELETED reason=delete table=0 cookie=0 in_port=2 actions=output:1
>>> OFPT_BARRIER_REPLY$3:
>>> @@ -4732,8 +4738,11 @@ ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=123,actions=output:1
>>> ovs-ofctl -O $2 monitor br0 watch:\!own --detach --no-chdir --pidfile
>>> >monitor.log 2>&1
>>> AT_CAPTURE_FILE([monitor.log])
>>> ovs-appctl -t ovs-ofctl ofctl/barrier
>>> +
>>> +# For OF(1.4+), replace INITIAL to ADDED
>>> +sed -i'.raw' -e 's|event=INITIAL|event=ADDED|' monitor.log
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0],
>>> - [NXST_FLOW_MONITOR reply$3:
>>> + [$4 reply$3:
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=123 actions=output:1
>>> OFPT_BARRIER_REPLY$3:
>>> ])
>>> @@ -4747,14 +4756,17 @@ ovs-appctl -t ovs-ofctl ofctl/send $send_buf
>>> ovs-appctl -t ovs-ofctl ofctl/barrier
>>> AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], [0], [NXST_FLOW
>>> reply:
>>> ])
>>> +
>>> +# For OF(1.4+), replace INITIAL to ADDED
>>> +sed -i'.raw' -e 's|event=INITIAL|event=ADDED|' monitor.log
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0],
>>> -[NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +[$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=1 actions=output:2
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 in_port=2 actions=output:1
>>> OFPT_BARRIER_REPLY$3:
>>> send: OFPT_FLOW_MOD$3: DEL actions=drop
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=ABBREV xid=0x12345678
>>> OFPT_BARRIER_REPLY$3:
>>> ])
>>> @@ -4775,8 +4787,11 @@ ovs-ofctl add-flow br0
>>> in_port=0,dl_vlan=123,actions=output:2
>>> ovs-ofctl -O $2 monitor br0 watch:out_port=2 --detach --no-chdir
>>> --pidfile >monitor.log 2>&1
>>> AT_CAPTURE_FILE([monitor.log])
>>> ovs-appctl -t ovs-ofctl ofctl/barrier
>>> +
>>> +# For OF(1.4+), replace INITIAL to ADDED
>>> +sed -i'.raw' -e 's|event=INITIAL|event=ADDED|' monitor.log
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0],
>>> - [NXST_FLOW_MONITOR reply$3:
>>> + [$4 reply$3:
>>> event=ADDED table=0 cookie=0 in_port=0,dl_vlan=123 actions=output:2
>>> OFPT_BARRIER_REPLY$3:
>>> ])
>>> @@ -4796,17 +4811,19 @@ ovs-appctl -t ovs-ofctl ofctl/barrier
>>> ovs-ofctl mod-flows br0 dl_vlan=123,actions=output:2
>>> ovs-appctl -t ovs-ofctl ofctl/barrier
>>>
>>> +# For OF(1.4+), replace INITIAL to ADDED
>>> +sed -i'.raw' -e 's|event=INITIAL|event=ADDED|' monitor.log
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0],
>>> -[NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +[$4 reply$3 (xid=0x0):
>>> event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=122
>>> actions=output:1,output:2
>>> OFPT_BARRIER_REPLY$3:
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=123
>>> actions=output:1,output:2
>>> OFPT_BARRIER_REPLY$3:
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=122 actions=output:1
>>> OFPT_BARRIER_REPLY$3:
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3 (xid=0x0):
>>> event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=123 actions=output:2
>>> OFPT_BARRIER_REPLY$3:
>>> ])
>>> @@ -4869,7 +4886,7 @@ ovs-appctl -t ovs-ofctl ofctl/unblock
>>> # A barrier doesn't work for this purpose.
>>> # https://www.mail-archive.com/dev@openvswitch.org/msg27013.html
>>> # https://www.mail-archive.com/dev@openvswitch.org/msg27675.html
>>> -OVS_WAIT_UNTIL([grep NXT_FLOW_MONITOR_RESUMED monitor.log])
>>> +OVS_WAIT_UNTIL([grep RESUMED monitor.log])
>>>
>>> OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
>>>
>>> @@ -4897,24 +4914,30 @@ AT_CHECK([test $adds = $deletes])
>>> # and MODIFIED lines lines depends on hash order, that is, it varies
>>> # as we change the hash function or change architecture. Therefore,
>>> # we use a couple of tests below to accept both orders.
>>> +
>>> +# Rename all version specific strings to a generic one
>>> +sed -i'.raw' -e 's|NXT_FLOW_MONITOR|FLOW_MONITOR|' -e
>>> 's|ONFT_FLOW_MONITOR|FLOW_MONITOR|' monitor.log
>>> +sed -i -z 's|OFPST_FLOW_MONITOR reply$3 (xid=0x0):\n
>>> event=PAUSED|FLOW_MONITOR_PAUSED$3:|' monitor.log
>>> +sed -i -z 's|OFPST_FLOW_MONITOR reply$3 (xid=0x0):\n
>>> event=RESUMED|FLOW_MONITOR_RESUMED$3:|' monitor.log
>>> +
>>> AT_CHECK([ofctl_strip < monitor.log | sed -n -e '
>>> /reg1=0x22$/p
>>> /cookie=0x[[23]]/p
>>> -/NXT_FLOW_MONITOR_PAUSED$3:/p
>>> -/NXT_FLOW_MONITOR_RESUMED$3:/p
>>> +/FLOW_MONITOR_PAUSED$3:/p
>>> +/FLOW_MONITOR_RESUMED$3:/p
>>> ' > monitor.log.subset])
>>> AT_CHECK([grep -v MODIFIED monitor.log.subset], [0], [dnl
>>> event=ADDED table=0 cookie=0x1 reg1=0x22
>>> -NXT_FLOW_MONITOR_PAUSED$3:
>>> +FLOW_MONITOR_PAUSED$3:
>>> event=DELETED reason=delete table=0 cookie=0x1 reg1=0x22
>>> event=ADDED table=0 cookie=0x3 in_port=1
>>> -NXT_FLOW_MONITOR_RESUMED$3:
>>> +FLOW_MONITOR_RESUMED$3:
>>> ])
>>> AT_CHECK([grep -v ADDED monitor.log.subset], [0], [dnl
>>> -NXT_FLOW_MONITOR_PAUSED$3:
>>> +FLOW_MONITOR_PAUSED$3:
>>> event=DELETED reason=delete table=0 cookie=0x1 reg1=0x22
>>> event=MODIFIED table=0 cookie=0x2 in_port=2 actions=output:2
>>> -NXT_FLOW_MONITOR_RESUMED$3:
>>> +FLOW_MONITOR_RESUMED$3:
>>> ])
>>>
>>> OVS_VSWITCHD_STOP
>>> @@ -4931,7 +4954,7 @@ ovs-ofctl -O $2 monitor br0 watch:udp,udp_dst=8
>>> --detach --no-chdir --pidfile >m
>>> AT_CAPTURE_FILE([monitor.log])
>>>
>>> # Wait till reply comes backs with OF Version
>>> -OVS_WAIT_UNTIL([grep "NXST_FLOW_MONITOR reply$3" monitor.log])
>>> +OVS_WAIT_UNTIL([grep "$4 reply$3" monitor.log])
>>> ovs-appctl -t ovs-ofctl exit
>>>
>>> # Make sure protocol type in messages from vswitchd, matches that of
>>> requested protocol
>>> @@ -4940,17 +4963,64 @@ ovs-ofctl add-flow br0
>>> sctp,sctp_dst=9,action=normal
>>>
>>> OVS_WAIT_UNTIL([grep "event=ADDED " monitor.log])
>>> AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0], [dnl
>>> -NXST_FLOW_MONITOR reply$3:
>>> -NXST_FLOW_MONITOR reply$3 (xid=0x0):
>>> +$4 reply$3:
>>> +$4 reply$3 (xid=0x0):
>>> event=ADDED table=0 cookie=0 sctp,tp_dst=9 actions=NORMAL
>>> ])
>>> OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
>>> OVS_VSWITCHD_STOP
>>> AT_CLEANUP
>>> ])
>>> -CHECK_FLOW_MONITORING([1.0], [OpenFlow10], [])
>>> -CHECK_FLOW_MONITORING([1.1], [OpenFlow11], [ (OF1.1)])
>>> -CHECK_FLOW_MONITORING([1.2], [OpenFlow12], [ (OF1.2)])
>>> +CHECK_FLOW_MONITORING([1.0], [OpenFlow10], [],
>>> NXST_FLOW_MONITOR)
>>> +CHECK_FLOW_MONITORING([1.1], [OpenFlow11], [ (OF1.1)],
>>> NXST_FLOW_MONITOR)
>>> +CHECK_FLOW_MONITORING([1.2], [OpenFlow12], [ (OF1.2)],
>>> NXST_FLOW_MONITOR)
>>> +CHECK_FLOW_MONITORING([1.3], [OpenFlow13], [ (OF1.3)],
>>> ONFST_FLOW_MONITOR)
>>> +CHECK_FLOW_MONITORING([1.4], [OpenFlow14], [ (OF1.4)],
>>> OFPST_FLOW_MONITOR)
>>> +CHECK_FLOW_MONITORING([1.5], [OpenFlow15], [ (OF1.5)],
>>> OFPST_FLOW_MONITOR)
>>> +
>>> +AT_SETUP([ofproto - OpenFlow14 flow monitoring with out_group])
>>> +AT_KEYWORDS([monitor])
>>> +OVS_VSWITCHD_START
>>> +
>>> +AT_CHECK([ovs-ofctl -O OpenFlow14 add-group br0
>>> group_id=1,type=all,bucket=output:1])
>>> +AT_CHECK([ovs-ofctl -O OpenFlow14 add-group br0
>>> group_id=2,type=all,bucket=output:2])
>>> +
>>> +ovs-ofctl -OOpenFlow14 add-flow br0
>>> in_port=0,dl_vlan=121,actions=output:1
>>> +ovs-ofctl -OOpenFlow14 add-flow br0
>>> in_port=0,dl_vlan=122,actions=group:1
>>> +ovs-ofctl -OOpenFlow14 add-flow br0
>>> in_port=0,dl_vlan=123,actions=group:2
>>> +
>>> +# Start a monitor watching the flow table and check the initial reply.
>>> +ovs-ofctl -OOpenFlow14 monitor br0 watch:out_group=2 --detach
>>> --no-chdir --pidfile >monitor.log 2>&1
>>> +AT_CAPTURE_FILE([monitor.log])
>>> +ovs-appctl -t ovs-ofctl ofctl/barrier
>>> +AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0],
>>> +[OFPST_FLOW_MONITOR reply (OF1.4):
>>> + event=INITIAL table=0 cookie=0 in_port=0,dl_vlan=123 actions=group:2
>>> +OFPT_BARRIER_REPLY (OF1.4):
>>> +])
>>> +
>>> +ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
>>> +
>>> +# Add, modify flows and check the updates.
>>> +ovs-ofctl -OOpenFlow14 mod-flows br0 dl_vlan=121,actions=group:2
>>> +ovs-ofctl -OOpenFlow14 mod-flows br0 dl_vlan=122,actions=group:2
>>> +ovs-ofctl -OOpenFlow14 mod-flows br0 dl_vlan=123,actions=group:1
>>> +ovs-appctl -t ovs-ofctl ofctl/barrier
>>> +ovs-ofctl -OOpenFlow14 add-flow br0
>>> in_port=0,dl_vlan=124,actions=group:2
>>> +
>>> +AT_CHECK([sed 's/ (xid=0x[[1-9a-fA-F]][[0-9a-fA-F]]*)//' monitor.log],
>>> [0],
>>> +[OFPST_FLOW_MONITOR reply (OF1.4) (xid=0x0):
>>> + event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=121 actions=group:2
>>> +OFPST_FLOW_MONITOR reply (OF1.4) (xid=0x0):
>>> + event=MODIFIED table=0 cookie=0 in_port=0,dl_vlan=122 actions=group:2
>>> +OFPT_BARRIER_REPLY (OF1.4):
>>> +OFPST_FLOW_MONITOR reply (OF1.4) (xid=0x0):
>>> + event=ADDED table=0 cookie=0 in_port=0,dl_vlan=124 actions=group:2
>>> +])
>>> +
>>> +OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
>>> +OVS_VSWITCHD_STOP
>>> +AT_CLEANUP
>>>
>>> AT_SETUP([ofproto - event filtering (OpenFlow 1.3)])
>>> AT_KEYWORDS([monitor])
>>> diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
>>> index 2017c6eba..d9336a43b 100644
>>> --- a/utilities/ovs-ofctl.8.in
>>> +++ b/utilities/ovs-ofctl.8.in
>>> @@ -626,6 +626,9 @@ monitored.
>>> If set, only flows that output to \fIport\fR are monitored. The
>>> \fIport\fR may be an OpenFlow port number or keyword
>>> (e.g. \fBLOCAL\fR).
>>> +.IP "\fBout_group=\fIgroup\fR"
>>> +If set, only flows that output to \fIgroup\fR number are monitored.
>>> +This field requires OpenFlow 1.4 (-OOpenFlow14) or later.
>>> .IP "\fIfield\fB=\fIvalue\fR"
>>> Monitors only flows that have \fIfield\fR specified as the given
>>> \fIvalue\fR. Any syntax valid for matching on \fBdump\-flows\fR may
>>> diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
>>> index 614b73006..5e6823240 100644
>>> --- a/utilities/ovs-ofctl.c
>>> +++ b/utilities/ovs-ofctl.c
>>> @@ -2313,6 +2313,12 @@ ofctl_monitor(struct ovs_cmdl_context *ctx)
>>>
>>> msg = ofpbuf_new(0);
>>> ofputil_append_flow_monitor_request(&fmr, msg, protocol);
>>> +
>>> + if (verbosity) {
>>> + ofpmsg_update_length(msg);
>>> + ofp_print(stdout, msg->data, msg->size, NULL,
>>> + NULL, verbosity + 2);
>>> + }
>>> dump_transaction(vconn, msg);
>>> fflush(stdout);
>>> } else if (!strcmp(arg, "resume")) {
>>> --
>>> 2.29.2
>>>
>>>
More information about the dev
mailing list