Vasu Dasari <[email protected]> writes: > 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 <[email protected]> > Reported-at: > https://mail.openvswitch.org/pipermail/ovs-dev/2021-June/383915.html > ---
Same as previous - looks good, but needs a respin due to NEWS Acked-by: Aaron Conole <[email protected]> > v1: > - Fixed 0-day Robot errors > v4: > - Rebase code with latest master. > --- > 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 d8e6c06f7..0555cc8fb 100644 > --- a/NEWS > +++ b/NEWS > @@ -47,8 +47,10 @@ v2.16.0 - 16 Aug 2021 > - 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 14b909973..6c91614b2 100644 > --- a/ofproto/ofproto-provider.h > +++ b/ofproto/ofproto-provider.h > @@ -423,7 +423,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); > > @@ -484,6 +484,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 cc0fdc5bb..3b724796f 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -3170,7 +3170,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) > { > @@ -5242,7 +5242,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); > > @@ -5657,8 +5657,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); > @@ -5668,7 +5668,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, > @@ -5677,7 +5677,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); > @@ -5958,7 +5958,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); > > @@ -6364,7 +6364,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) > @@ -6373,8 +6373,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; > @@ -6385,7 +6386,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; > > @@ -6404,7 +6405,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, > @@ -6418,7 +6419,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; > @@ -6428,11 +6429,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; > } > @@ -6441,13 +6446,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 > @@ -6476,7 +6481,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); > } > } > @@ -6539,16 +6544,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/[email protected]/msg27013.html > # https://www.mail-archive.com/[email protected]/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 e903ca12b..3fe6a0cc5 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")) { _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
