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