|
|
ebb439 |
From c8cf2e5c7f859bc3c781948e8a9cdd832035a7ee Mon Sep 17 00:00:00 2001
|
|
|
ebb439 |
From: Dumitru Ceara <dceara@redhat.com>
|
|
|
ebb439 |
Date: Sun, 11 Oct 2020 14:05:59 +0200
|
|
|
ebb439 |
Subject: [PATCH 5/7] ofctrl.c: Simplify active desired flow selection.
|
|
|
ebb439 |
|
|
|
ebb439 |
Always consider the first "desired flow" in the list of flows that refer an
|
|
|
ebb439 |
"installed flow" as the active flow. This simplifies the logic of the flow
|
|
|
ebb439 |
update code and is used in a further commit to implement a partial ordering
|
|
|
ebb439 |
of desired flows within installed flows.
|
|
|
ebb439 |
|
|
|
ebb439 |
Signed-off-by: Dumitru Ceara <dceara@redhat.com>
|
|
|
ebb439 |
Signed-off-by: Han Zhou <hzhou@ovn.org>
|
|
|
ebb439 |
(cherry picked from upstream commit 107bb25029350bd0f7dfeeb0ef3053adbd504e3e)
|
|
|
ebb439 |
|
|
|
ebb439 |
Change-Id: I5e5aca6f18601a3cbd9decc913dad3507ee0a448
|
|
|
ebb439 |
---
|
|
|
ebb439 |
controller/ofctrl.c | 91 +++++++++++++++++++++--------------------------------
|
|
|
ebb439 |
1 file changed, 36 insertions(+), 55 deletions(-)
|
|
|
ebb439 |
|
|
|
ebb439 |
diff --git a/controller/ofctrl.c b/controller/ofctrl.c
|
|
|
ebb439 |
index 20cf3ac..ba0c61c 100644
|
|
|
ebb439 |
--- a/controller/ofctrl.c
|
|
|
ebb439 |
+++ b/controller/ofctrl.c
|
|
|
ebb439 |
@@ -188,6 +188,8 @@ struct sb_flow_ref {
|
|
|
ebb439 |
* relationship is 1 to N. A link is added when a flow addition is processed.
|
|
|
ebb439 |
* A link is removed when a flow deletion is processed, the desired flow
|
|
|
ebb439 |
* table is cleared, or the installed flow table is cleared.
|
|
|
ebb439 |
+ * The first desired_flow in the list is the active one, the one that is
|
|
|
ebb439 |
+ * actually installed.
|
|
|
ebb439 |
*/
|
|
|
ebb439 |
struct installed_flow {
|
|
|
ebb439 |
struct ovn_flow flow;
|
|
|
ebb439 |
@@ -199,11 +201,6 @@ struct installed_flow {
|
|
|
ebb439 |
* installed flow, e.g. when there are conflict/duplicated ACLs that
|
|
|
ebb439 |
* generates same match conditions). */
|
|
|
ebb439 |
struct ovs_list desired_refs;
|
|
|
ebb439 |
-
|
|
|
ebb439 |
- /* The corresponding flow in desired table. It must be one of the flows in
|
|
|
ebb439 |
- * desired_refs list. If there are more than one flows in references list,
|
|
|
ebb439 |
- * this is the one that is actually installed. */
|
|
|
ebb439 |
- struct desired_flow *desired_flow;
|
|
|
ebb439 |
};
|
|
|
ebb439 |
|
|
|
ebb439 |
typedef bool
|
|
|
ebb439 |
@@ -231,6 +228,7 @@ static struct installed_flow *installed_flow_lookup(
|
|
|
ebb439 |
const struct ovn_flow *target);
|
|
|
ebb439 |
static void installed_flow_destroy(struct installed_flow *);
|
|
|
ebb439 |
static struct installed_flow *installed_flow_dup(struct desired_flow *);
|
|
|
ebb439 |
+static struct desired_flow *installed_flow_get_active(struct installed_flow *);
|
|
|
ebb439 |
|
|
|
ebb439 |
static uint32_t ovn_flow_match_hash(const struct ovn_flow *);
|
|
|
ebb439 |
static char *ovn_flow_to_string(const struct ovn_flow *);
|
|
|
ebb439 |
@@ -796,24 +794,6 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type)
|
|
|
ebb439 |
log_openflow_rl(&rl, VLL_DBG, oh, "OpenFlow packet ignored");
|
|
|
ebb439 |
}
|
|
|
ebb439 |
}
|
|
|
ebb439 |
-
|
|
|
ebb439 |
-/* Returns true if a desired flow is active (the one currently installed
|
|
|
ebb439 |
- * among the list of desired flows that are linked to the same installed
|
|
|
ebb439 |
- * flow). */
|
|
|
ebb439 |
-static inline bool
|
|
|
ebb439 |
-desired_flow_is_active(struct desired_flow *d)
|
|
|
ebb439 |
-{
|
|
|
ebb439 |
- return (d->installed_flow && d->installed_flow->desired_flow == d);
|
|
|
ebb439 |
-}
|
|
|
ebb439 |
-
|
|
|
ebb439 |
-/* Set a desired flow as the active one among the list of desired flows
|
|
|
ebb439 |
- * that are linked to the same installed flow. */
|
|
|
ebb439 |
-static inline void
|
|
|
ebb439 |
-desired_flow_set_active(struct desired_flow *d)
|
|
|
ebb439 |
-{
|
|
|
ebb439 |
- ovs_assert(d->installed_flow);
|
|
|
ebb439 |
- d->installed_flow->desired_flow = d;
|
|
|
ebb439 |
-}
|
|
|
ebb439 |
|
|
|
ebb439 |
static bool
|
|
|
ebb439 |
flow_action_has_conj(const struct ovn_flow *f)
|
|
|
ebb439 |
@@ -831,27 +811,22 @@ flow_action_has_conj(const struct ovn_flow *f)
|
|
|
ebb439 |
/* Adds the desired flow to the list of desired flows that have same match
|
|
|
ebb439 |
* conditions as the installed flow.
|
|
|
ebb439 |
*
|
|
|
ebb439 |
- * If the newly added desired flow is the first one in the list, it is also set
|
|
|
ebb439 |
- * as the active one.
|
|
|
ebb439 |
- *
|
|
|
ebb439 |
* It is caller's responsibility to make sure the link between the pair didn't
|
|
|
ebb439 |
- * exist before. */
|
|
|
ebb439 |
-static void
|
|
|
ebb439 |
+ * exist before.
|
|
|
ebb439 |
+ *
|
|
|
ebb439 |
+ * Returns true if the newly added desired flow is selected to be the active
|
|
|
ebb439 |
+ * one.
|
|
|
ebb439 |
+ */
|
|
|
ebb439 |
+static bool
|
|
|
ebb439 |
link_installed_to_desired(struct installed_flow *i, struct desired_flow *d)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
- ovs_assert(i->desired_flow != d);
|
|
|
ebb439 |
- if (ovs_list_is_empty(&i->desired_refs)) {
|
|
|
ebb439 |
- ovs_assert(!i->desired_flow);
|
|
|
ebb439 |
- i->desired_flow = d;
|
|
|
ebb439 |
- }
|
|
|
ebb439 |
- ovs_list_insert(&i->desired_refs, &d->installed_ref_list_node);
|
|
|
ebb439 |
d->installed_flow = i;
|
|
|
ebb439 |
+ ovs_list_push_back(&i->desired_refs, &d->installed_ref_list_node);
|
|
|
ebb439 |
+ return installed_flow_get_active(i) == d;
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
/* Replaces 'old_desired' with 'new_desired' in the list of desired flows
|
|
|
ebb439 |
* that have same match conditions as the installed flow.
|
|
|
ebb439 |
- *
|
|
|
ebb439 |
- * If 'old_desired' was the active flow, 'new_desired' becomes the active one.
|
|
|
ebb439 |
*/
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
replace_installed_to_desired(struct installed_flow *i,
|
|
|
ebb439 |
@@ -863,24 +838,22 @@ replace_installed_to_desired(struct installed_flow *i,
|
|
|
ebb439 |
&old_desired->installed_ref_list_node);
|
|
|
ebb439 |
old_desired->installed_flow = NULL;
|
|
|
ebb439 |
new_desired->installed_flow = i;
|
|
|
ebb439 |
- if (i->desired_flow == old_desired) {
|
|
|
ebb439 |
- i->desired_flow = new_desired;
|
|
|
ebb439 |
- }
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
-static void
|
|
|
ebb439 |
+/* Removes the desired flow from the list of desired flows that have the same
|
|
|
ebb439 |
+ * match conditions as the installed flow.
|
|
|
ebb439 |
+ *
|
|
|
ebb439 |
+ * Returns true if the desired flow was the previously active flow.
|
|
|
ebb439 |
+ */
|
|
|
ebb439 |
+static bool
|
|
|
ebb439 |
unlink_installed_to_desired(struct installed_flow *i, struct desired_flow *d)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
- ovs_assert(i && i->desired_flow && !ovs_list_is_empty(&i->desired_refs));
|
|
|
ebb439 |
+ struct desired_flow *old_active = installed_flow_get_active(i);
|
|
|
ebb439 |
+
|
|
|
ebb439 |
ovs_assert(d && d->installed_flow == i);
|
|
|
ebb439 |
ovs_list_remove(&d->installed_ref_list_node);
|
|
|
ebb439 |
d->installed_flow = NULL;
|
|
|
ebb439 |
- if (i->desired_flow == d) {
|
|
|
ebb439 |
- i->desired_flow = ovs_list_is_empty(&i->desired_refs) ? NULL :
|
|
|
ebb439 |
- CONTAINER_OF(ovs_list_front(&i->desired_refs),
|
|
|
ebb439 |
- struct desired_flow,
|
|
|
ebb439 |
- installed_ref_list_node);
|
|
|
ebb439 |
- }
|
|
|
ebb439 |
+ return old_active == d;
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
@@ -1280,7 +1253,6 @@ installed_flow_dup(struct desired_flow *src)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
struct installed_flow *dst = xmalloc(sizeof *dst);
|
|
|
ebb439 |
ovs_list_init(&dst->desired_refs);
|
|
|
ebb439 |
- dst->desired_flow = NULL;
|
|
|
ebb439 |
dst->flow.table_id = src->flow.table_id;
|
|
|
ebb439 |
dst->flow.priority = src->flow.priority;
|
|
|
ebb439 |
minimatch_clone(&dst->flow.match, &src->flow.match);
|
|
|
ebb439 |
@@ -1292,6 +1264,17 @@ installed_flow_dup(struct desired_flow *src)
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
static struct desired_flow *
|
|
|
ebb439 |
+installed_flow_get_active(struct installed_flow *f)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ if (!ovs_list_is_empty(&f->desired_refs)) {
|
|
|
ebb439 |
+ return CONTAINER_OF(ovs_list_front(&f->desired_refs),
|
|
|
ebb439 |
+ struct desired_flow,
|
|
|
ebb439 |
+ installed_ref_list_node);
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+ return NULL;
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+static struct desired_flow *
|
|
|
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 |
@@ -1439,8 +1422,7 @@ static void
|
|
|
ebb439 |
installed_flow_destroy(struct installed_flow *f)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
if (f) {
|
|
|
ebb439 |
- ovs_assert(ovs_list_is_empty(&f->desired_refs));
|
|
|
ebb439 |
- ovs_assert(!f->desired_flow);
|
|
|
ebb439 |
+ ovs_assert(!installed_flow_get_active(f));
|
|
|
ebb439 |
ovn_flow_uninit(&f->flow);
|
|
|
ebb439 |
free(f);
|
|
|
ebb439 |
}
|
|
|
ebb439 |
@@ -1898,10 +1880,10 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
/* The desired flow was deleted */
|
|
|
ebb439 |
if (f->installed_flow) {
|
|
|
ebb439 |
struct installed_flow *i = f->installed_flow;
|
|
|
ebb439 |
- bool was_active = desired_flow_is_active(f);
|
|
|
ebb439 |
- unlink_installed_to_desired(i, f);
|
|
|
ebb439 |
+ bool was_active = unlink_installed_to_desired(i, f);
|
|
|
ebb439 |
+ struct desired_flow *d = installed_flow_get_active(i);
|
|
|
ebb439 |
|
|
|
ebb439 |
- if (!i->desired_flow) {
|
|
|
ebb439 |
+ if (!d) {
|
|
|
ebb439 |
installed_flow_del(&i->flow, msgs);
|
|
|
ebb439 |
ovn_flow_log(&i->flow, "removing installed (tracked)");
|
|
|
ebb439 |
|
|
|
ebb439 |
@@ -1912,7 +1894,6 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
* installed flow, so update the OVS flow for the new
|
|
|
ebb439 |
* active flow (at least the cookie will be different,
|
|
|
ebb439 |
* even if the actions are the same). */
|
|
|
ebb439 |
- struct desired_flow *d = i->desired_flow;
|
|
|
ebb439 |
ovn_flow_log(&i->flow, "updating installed (tracked)");
|
|
|
ebb439 |
installed_flow_mod(&i->flow, &d->flow, msgs);
|
|
|
ebb439 |
}
|
|
|
ebb439 |
@@ -1931,7 +1912,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
|
|
|
ebb439 |
hmap_insert(&installed_flows, &new_node->match_hmap_node,
|
|
|
ebb439 |
new_node->flow.hash);
|
|
|
ebb439 |
link_installed_to_desired(new_node, f);
|
|
|
ebb439 |
- } else if (desired_flow_is_active(f)) {
|
|
|
ebb439 |
+ } else if (installed_flow_get_active(i) == f) {
|
|
|
ebb439 |
/* The installed flow is installed for f, but f has change
|
|
|
ebb439 |
* tracked, so it must have been modified. */
|
|
|
ebb439 |
ovn_flow_log(&i->flow, "updating installed (tracked)");
|
|
|
ebb439 |
--
|
|
|
ebb439 |
1.8.3.1
|
|
|
ebb439 |
|