Message ID | 20210729235353.94821-2-vdasari@gmail.com |
---|---|
State | Superseded |
Headers | show |
Series | [ovs-dev,1/2] ofp-monitor: Extend Flow Monitoring support for OF 1.0-1.2 with Nicira Extensions | expand |
Context | Check | Description |
---|---|---|
ovsrobot/apply-robot | warning | apply and check: warning |
ovsrobot/github-robot | success | github build: passed |
Hi Ashish, Here is the patch that supports flow monitoring for 1.3 and 1.4+. I have taken test case to test out_group from your patch <http://patchwork.ozlabs.org/project/openvswitch/patch/1548978579-28929-1-git-send-email-ashishvarma.ovs@gmail.com/> that you shared privately. I wish I had known the existence of your patch, it would have made it a lot easier to support 1.4+ versions. Thanks -Vasu *Vasu Dasari* On Thu, Jul 29, 2021 at 7:54 PM Vasu Dasari <vdasari@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@gmail.com> > Reported-at: > https://mail.openvswitch.org/pipermail/ovs-dev/2021-June/383915.html > --- > 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..a46700f75 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 > >
Bleep bloop. Greetings Vasu Dasari, I am a robot and I have tried out your patch. Thanks for your contribution. I encountered some error that I wasn't expecting. See the details below. checkpatch: WARNING: Line has non-spaces leading whitespace #741 FILE: lib/ofp-monitor.c:613: ofmr->out_port = ofputil_port_to_ofp11(rq->out_port); WARNING: Line has non-spaces leading whitespace #760 FILE: lib/ofp-monitor.c:632: ofmr->out_port = ofputil_port_to_ofp11(rq->out_port); Lines checked: 2471, Warnings: 2, Errors: 0 Please check this out. If you feel there has been an error, please email aconole@redhat.com Thanks, 0-day Robot
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..a46700f75 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")) {
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@gmail.com> Reported-at: https://mail.openvswitch.org/pipermail/ovs-dev/2021-June/383915.html --- 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(-)