summaryrefslogtreecommitdiff
path: root/ofproto
diff options
context:
space:
mode:
authorVasu Dasari <vdasari@gmail.com>2021-12-08 18:05:23 -0500
committerIlya Maximets <i.maximets@ovn.org>2022-04-28 21:27:11 +0200
commitc3e64047d1ccfd8beaedf6e2fe997afa529d293a (patch)
tree2b7fcd11199ee43dfd94594bbabab234dcceca39 /ofproto
parentd8ab75cd69c6eee136636c75f5c8aa6bcd8d7a53 (diff)
downloadopenvswitch-c3e64047d1ccfd8beaedf6e2fe997afa529d293a.tar.gz
ofp-monitor: Support flow monitoring for OpenFlow 1.3, 1.4+.
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 introduced 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 modules 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 Acked-by: Aaron Conole <aconole@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'ofproto')
-rw-r--r--ofproto/connmgr.c47
-rw-r--r--ofproto/connmgr.h6
-rw-r--r--ofproto/ofproto-provider.h4
-rw-r--r--ofproto/ofproto.c89
4 files changed, 96 insertions, 50 deletions
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index b6af9ddb5..7b14cae77 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 47e96e62e..7e3fb6698 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -425,7 +425,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);
@@ -486,6 +486,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 f59413c73..8d5815ff5 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -3220,7 +3220,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)
{
@@ -5292,7 +5292,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);
@@ -5712,8 +5712,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);
@@ -5723,7 +5723,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,
@@ -5732,7 +5732,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);
@@ -6013,7 +6013,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);
@@ -6419,7 +6419,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)
@@ -6428,8 +6428,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;
@@ -6440,7 +6441,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;
@@ -6459,7 +6460,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,
@@ -6473,7 +6474,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;
@@ -6483,11 +6484,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;
}
@@ -6496,13 +6501,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
@@ -6531,7 +6536,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);
}
}
@@ -6594,16 +6599,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: