|
|
ebb439 |
From 9d095799aa11c555bf7d5f8e86fee1be1a16c67b Mon Sep 17 00:00:00 2001
|
|
|
ebb439 |
From: Dumitru Ceara <dceara@redhat.com>
|
|
|
ebb439 |
Date: Sun, 11 Oct 2020 14:05:31 +0200
|
|
|
ebb439 |
Subject: [PATCH 3/7] ofctrl.c: Only merge actions for conjunctive flows.
|
|
|
ebb439 |
|
|
|
ebb439 |
In ofctrl_add_or_append_flow() when merging flow actions make sure we only
|
|
|
ebb439 |
do that for conjunctive flows. All other actions can not be merged with
|
|
|
ebb439 |
action "conjunction".
|
|
|
ebb439 |
|
|
|
ebb439 |
CC: Mark Michelson <mmichels@redhat.com>
|
|
|
ebb439 |
Fixes: e659bab31a91 ("Combine conjunctions with identical matches into one flow.")
|
|
|
ebb439 |
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
|
|
|
ebb439 |
Signed-off-by: Han Zhou <hzhou@ovn.org>
|
|
|
ebb439 |
(cherry picked from upstream commit dadae4f800ccb1f2759378f0bd804dd002e31605)
|
|
|
ebb439 |
|
|
|
ebb439 |
Change-Id: I6fc4091b3110ae595615c7f9006c3f5e53ebc39a
|
|
|
ebb439 |
---
|
|
|
ebb439 |
controller/ofctrl.c | 124 +++++++++++++++++++++++++++++++++++++++++-----------
|
|
|
ebb439 |
1 file changed, 99 insertions(+), 25 deletions(-)
|
|
|
ebb439 |
|
|
|
ebb439 |
diff --git a/controller/ofctrl.c b/controller/ofctrl.c
|
|
|
ebb439 |
index 4425d98..24b55fc 100644
|
|
|
ebb439 |
--- a/controller/ofctrl.c
|
|
|
ebb439 |
+++ b/controller/ofctrl.c
|
|
|
ebb439 |
@@ -206,6 +206,9 @@ struct installed_flow {
|
|
|
ebb439 |
struct desired_flow *desired_flow;
|
|
|
ebb439 |
};
|
|
|
ebb439 |
|
|
|
ebb439 |
+typedef bool
|
|
|
ebb439 |
+(*desired_flow_match_cb)(const struct desired_flow *candidate,
|
|
|
ebb439 |
+ const void *arg);
|
|
|
ebb439 |
static struct desired_flow *desired_flow_alloc(
|
|
|
ebb439 |
uint8_t table_id,
|
|
|
ebb439 |
uint16_t priority,
|
|
|
ebb439 |
@@ -214,8 +217,14 @@ static struct desired_flow *desired_flow_alloc(
|
|
|
ebb439 |
const struct ofpbuf *actions);
|
|
|
ebb439 |
static struct desired_flow *desired_flow_lookup(
|
|
|
ebb439 |
struct ovn_desired_flow_table *,
|
|
|
ebb439 |
+ const struct ovn_flow *target);
|
|
|
ebb439 |
+static struct desired_flow *desired_flow_lookup_check_uuid(
|
|
|
ebb439 |
+ struct ovn_desired_flow_table *,
|
|
|
ebb439 |
const struct ovn_flow *target,
|
|
|
ebb439 |
- const struct uuid *sb_uuid);
|
|
|
ebb439 |
+ const struct uuid *);
|
|
|
ebb439 |
+static struct desired_flow *desired_flow_lookup_conjunctive(
|
|
|
ebb439 |
+ struct ovn_desired_flow_table *,
|
|
|
ebb439 |
+ const struct ovn_flow *target);
|
|
|
ebb439 |
static void desired_flow_destroy(struct desired_flow *);
|
|
|
ebb439 |
|
|
|
ebb439 |
static struct installed_flow *installed_flow_lookup(
|
|
|
ebb439 |
@@ -806,6 +815,19 @@ desired_flow_set_active(struct desired_flow *d)
|
|
|
ebb439 |
d->installed_flow->desired_flow = d;
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
+static bool
|
|
|
ebb439 |
+flow_action_has_conj(const struct ovn_flow *f)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ const struct ofpact *a = NULL;
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ OFPACT_FOR_EACH (a, f->ofpacts, f->ofpacts_len) {
|
|
|
ebb439 |
+ if (a->type == OFPACT_CONJUNCTION) {
|
|
|
ebb439 |
+ return true;
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+ return false;
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
/* Adds the desired flow to the list of desired flows that have same match
|
|
|
ebb439 |
* conditions as the installed flow.
|
|
|
ebb439 |
*
|
|
|
ebb439 |
@@ -962,7 +984,7 @@ ofctrl_check_and_add_flow(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie,
|
|
|
ebb439 |
match, actions);
|
|
|
ebb439 |
|
|
|
ebb439 |
- if (desired_flow_lookup(flow_table, &f->flow, sb_uuid)) {
|
|
|
ebb439 |
+ if (desired_flow_lookup_check_uuid(flow_table, &f->flow, sb_uuid)) {
|
|
|
ebb439 |
if (log_duplicate_flow) {
|
|
|
ebb439 |
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
|
|
|
ebb439 |
if (!VLOG_DROP_DBG(&rl)) {
|
|
|
ebb439 |
@@ -1002,14 +1024,15 @@ ofctrl_add_or_append_flow(struct ovn_desired_flow_table *desired_flows,
|
|
|
ebb439 |
const struct ofpbuf *actions,
|
|
|
ebb439 |
const struct uuid *sb_uuid)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
- struct desired_flow *f = desired_flow_alloc(table_id, priority, cookie,
|
|
|
ebb439 |
- match, actions);
|
|
|
ebb439 |
-
|
|
|
ebb439 |
struct desired_flow *existing;
|
|
|
ebb439 |
- existing = desired_flow_lookup(desired_flows, &f->flow, NULL);
|
|
|
ebb439 |
+ struct desired_flow *f;
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ f = desired_flow_alloc(table_id, priority, cookie, match, actions);
|
|
|
ebb439 |
+ existing = desired_flow_lookup_conjunctive(desired_flows, &f->flow);
|
|
|
ebb439 |
if (existing) {
|
|
|
ebb439 |
- /* There's already a flow with this particular match. Append the
|
|
|
ebb439 |
- * action to that flow rather than adding a new flow
|
|
|
ebb439 |
+ /* There's already a flow with this particular match and action
|
|
|
ebb439 |
+ * 'conjunction'. Append the action to that flow rather than
|
|
|
ebb439 |
+ * adding a new flow.
|
|
|
ebb439 |
*/
|
|
|
ebb439 |
uint64_t compound_stub[64 / 8];
|
|
|
ebb439 |
struct ofpbuf compound;
|
|
|
ebb439 |
@@ -1248,15 +1271,11 @@ installed_flow_dup(struct desired_flow *src)
|
|
|
ebb439 |
return dst;
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
-/* Finds and returns a desired_flow in 'flow_table' whose key is identical to
|
|
|
ebb439 |
- * 'target''s key, or NULL if there is none.
|
|
|
ebb439 |
- *
|
|
|
ebb439 |
- * If sb_uuid is not NULL, the function will also check if the found flow is
|
|
|
ebb439 |
- * referenced by the sb_uuid. */
|
|
|
ebb439 |
static struct desired_flow *
|
|
|
ebb439 |
-desired_flow_lookup(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
- const struct ovn_flow *target,
|
|
|
ebb439 |
- const struct uuid *sb_uuid)
|
|
|
ebb439 |
+desired_flow_lookup__(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
+ const struct ovn_flow *target,
|
|
|
ebb439 |
+ desired_flow_match_cb match_cb,
|
|
|
ebb439 |
+ const void *arg)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
struct desired_flow *d;
|
|
|
ebb439 |
HMAP_FOR_EACH_WITH_HASH (d, match_hmap_node, target->hash,
|
|
|
ebb439 |
@@ -1265,20 +1284,76 @@ desired_flow_lookup(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
if (f->table_id == target->table_id
|
|
|
ebb439 |
&& f->priority == target->priority
|
|
|
ebb439 |
&& minimatch_equal(&f->match, &target->match)) {
|
|
|
ebb439 |
- if (!sb_uuid) {
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ if (!match_cb || match_cb(d, arg)) {
|
|
|
ebb439 |
return d;
|
|
|
ebb439 |
}
|
|
|
ebb439 |
- struct sb_flow_ref *sfr;
|
|
|
ebb439 |
- LIST_FOR_EACH (sfr, sb_list, &d->references) {
|
|
|
ebb439 |
- if (uuid_equals(sb_uuid, &sfr->sb_uuid)) {
|
|
|
ebb439 |
- return d;
|
|
|
ebb439 |
- }
|
|
|
ebb439 |
- }
|
|
|
ebb439 |
}
|
|
|
ebb439 |
}
|
|
|
ebb439 |
return NULL;
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
+/* Finds and returns a desired_flow in 'flow_table' whose key is identical to
|
|
|
ebb439 |
+ * 'target''s key, or NULL if there is none.
|
|
|
ebb439 |
+ */
|
|
|
ebb439 |
+static struct desired_flow *
|
|
|
ebb439 |
+desired_flow_lookup(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
+ const struct ovn_flow *target)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ return desired_flow_lookup__(flow_table, target, NULL, NULL);
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+static bool
|
|
|
ebb439 |
+flow_lookup_match_uuid_cb(const struct desired_flow *candidate,
|
|
|
ebb439 |
+ const void *arg)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ const struct uuid *sb_uuid = arg;
|
|
|
ebb439 |
+ struct sb_flow_ref *sfr;
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ LIST_FOR_EACH (sfr, sb_list, &candidate->references) {
|
|
|
ebb439 |
+ if (uuid_equals(sb_uuid, &sfr->sb_uuid)) {
|
|
|
ebb439 |
+ return true;
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+ return false;
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+/* Finds and returns a desired_flow in 'flow_table' whose key is identical to
|
|
|
ebb439 |
+ * 'target''s key, or NULL if there is none.
|
|
|
ebb439 |
+ *
|
|
|
ebb439 |
+ * The function will also check if the found flow is referenced by the
|
|
|
ebb439 |
+ * 'sb_uuid'.
|
|
|
ebb439 |
+ */
|
|
|
ebb439 |
+static struct desired_flow *
|
|
|
ebb439 |
+desired_flow_lookup_check_uuid(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
+ const struct ovn_flow *target,
|
|
|
ebb439 |
+ const struct uuid *sb_uuid)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ return desired_flow_lookup__(flow_table, target, flow_lookup_match_uuid_cb,
|
|
|
ebb439 |
+ sb_uuid);
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+static bool
|
|
|
ebb439 |
+flow_lookup_match_conj_cb(const struct desired_flow *candidate,
|
|
|
ebb439 |
+ const void *arg OVS_UNUSED)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ return flow_action_has_conj(&candidate->flow);
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+/* Finds and returns a desired_flow in 'flow_table' whose key is identical to
|
|
|
ebb439 |
+ * 'target''s key, or NULL if there is none.
|
|
|
ebb439 |
+ *
|
|
|
ebb439 |
+ * The function will only return a matching flow if it contains action
|
|
|
ebb439 |
+ * 'conjunction'.
|
|
|
ebb439 |
+ */
|
|
|
ebb439 |
+static struct desired_flow *
|
|
|
ebb439 |
+desired_flow_lookup_conjunctive(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
+ const struct ovn_flow *target)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ return desired_flow_lookup__(flow_table, target, flow_lookup_match_conj_cb,
|
|
|
ebb439 |
+ NULL);
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
/* Finds and returns an installed_flow in installed_flows whose key is
|
|
|
ebb439 |
* identical to 'target''s key, or NULL if there is none. */
|
|
|
ebb439 |
static struct installed_flow *
|
|
|
ebb439 |
@@ -1676,8 +1751,7 @@ update_installed_flows_by_compare(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
struct installed_flow *i, *next;
|
|
|
ebb439 |
HMAP_FOR_EACH_SAFE (i, next, match_hmap_node, &installed_flows) {
|
|
|
ebb439 |
unlink_all_refs_for_installed_flow(i);
|
|
|
ebb439 |
- struct desired_flow *d =
|
|
|
ebb439 |
- desired_flow_lookup(flow_table, &i->flow, NULL);
|
|
|
ebb439 |
+ struct desired_flow *d = desired_flow_lookup(flow_table, &i->flow);
|
|
|
ebb439 |
if (!d) {
|
|
|
ebb439 |
/* Installed flow is no longer desirable. Delete it from the
|
|
|
ebb439 |
* switch and from installed_flows. */
|
|
|
ebb439 |
--
|
|
|
ebb439 |
1.8.3.1
|
|
|
ebb439 |
|