diff options
author | Vasu Dasari <vdasari@gmail.com> | 2021-12-08 18:05:23 -0500 |
---|---|---|
committer | Ilya Maximets <i.maximets@ovn.org> | 2022-04-28 21:27:11 +0200 |
commit | c3e64047d1ccfd8beaedf6e2fe997afa529d293a (patch) | |
tree | 2b7fcd11199ee43dfd94594bbabab234dcceca39 /ofproto | |
parent | d8ab75cd69c6eee136636c75f5c8aa6bcd8d7a53 (diff) | |
download | openvswitch-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.c | 47 | ||||
-rw-r--r-- | ofproto/connmgr.h | 6 | ||||
-rw-r--r-- | ofproto/ofproto-provider.h | 4 | ||||
-rw-r--r-- | ofproto/ofproto.c | 89 |
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: |