diff --git a/controller/ofctrl.c b/controller/ofctrl.c
index 843c7b2be..890ab4bb5 100644
--- a/controller/ofctrl.c
+++ b/controller/ofctrl.c
@@ -188,6 +188,8 @@ struct sb_flow_ref {
  * relationship is 1 to N. A link is added when a flow addition is processed.
  * A link is removed when a flow deletion is processed, the desired flow
  * table is cleared, or the installed flow table is cleared.
+ * The first desired_flow in the list is the active one, the one that is
+ * actually installed.
  */
 struct installed_flow {
     struct ovn_flow flow;
@@ -199,11 +201,6 @@ struct installed_flow {
      * installed flow, e.g. when there are conflict/duplicated ACLs that
      * generates same match conditions). */
     struct ovs_list desired_refs;
-
-    /* The corresponding flow in desired table. It must be one of the flows in
-     * desired_refs list.  If there are more than one flows in references list,
-     * this is the one that is actually installed. */
-    struct desired_flow *desired_flow;
 };
 
 typedef bool
@@ -231,6 +228,7 @@ static struct installed_flow *installed_flow_lookup(
     const struct ovn_flow *target);
 static void installed_flow_destroy(struct installed_flow *);
 static struct installed_flow *installed_flow_dup(struct desired_flow *);
+static struct desired_flow *installed_flow_get_active(struct installed_flow *);
 
 static uint32_t ovn_flow_match_hash(const struct ovn_flow *);
 static char *ovn_flow_to_string(const struct ovn_flow *);
@@ -796,24 +794,6 @@ ofctrl_recv(const struct ofp_header *oh, enum ofptype type)
         log_openflow_rl(&rl, VLL_DBG, oh, "OpenFlow packet ignored");
     }
 }
-
-/* Returns true if a desired flow is active (the one currently installed
- * among the list of desired flows that are linked to the same installed
- * flow). */
-static inline bool
-desired_flow_is_active(struct desired_flow *d)
-{
-    return (d->installed_flow && d->installed_flow->desired_flow == d);
-}
-
-/* Set a desired flow as the active one among the list of desired flows
- * that are linked to the same installed flow. */
-static inline void
-desired_flow_set_active(struct desired_flow *d)
-{
-    ovs_assert(d->installed_flow);
-    d->installed_flow->desired_flow = d;
-}
 
 static bool
 flow_action_has_conj(const struct ovn_flow *f)
@@ -831,27 +811,22 @@ flow_action_has_conj(const struct ovn_flow *f)
 /* Adds the desired flow to the list of desired flows that have same match
  * conditions as the installed flow.
  *
- * If the newly added desired flow is the first one in the list, it is also set
- * as the active one.
- *
  * It is caller's responsibility to make sure the link between the pair didn't
- * exist before. */
-static void
+ * exist before.
+ *
+ * Returns true if the newly added desired flow is selected to be the active
+ * one.
+ */
+static bool
 link_installed_to_desired(struct installed_flow *i, struct desired_flow *d)
 {
-    ovs_assert(i->desired_flow != d);
-    if (ovs_list_is_empty(&i->desired_refs)) {
-        ovs_assert(!i->desired_flow);
-        i->desired_flow = d;
-    }
-    ovs_list_insert(&i->desired_refs, &d->installed_ref_list_node);
     d->installed_flow = i;
+    ovs_list_push_back(&i->desired_refs, &d->installed_ref_list_node);
+    return installed_flow_get_active(i) == d;
 }
 
 /* Replaces 'old_desired' with 'new_desired' in the list of desired flows
  * that have same match conditions as the installed flow.
- *
- * If 'old_desired' was the active flow, 'new_desired' becomes the active one.
  */
 static void
 replace_installed_to_desired(struct installed_flow *i,
@@ -863,24 +838,22 @@ replace_installed_to_desired(struct installed_flow *i,
                      &old_desired->installed_ref_list_node);
     old_desired->installed_flow = NULL;
     new_desired->installed_flow = i;
-    if (i->desired_flow == old_desired) {
-        i->desired_flow = new_desired;
-    }
 }
 
-static void
+/* Removes the desired flow from the list of desired flows that have the same
+ * match conditions as the installed flow.
+ *
+ * Returns true if the desired flow was the previously active flow.
+ */
+static bool
 unlink_installed_to_desired(struct installed_flow *i, struct desired_flow *d)
 {
-    ovs_assert(i && i->desired_flow && !ovs_list_is_empty(&i->desired_refs));
+    struct desired_flow *old_active = installed_flow_get_active(i);
+
     ovs_assert(d && d->installed_flow == i);
     ovs_list_remove(&d->installed_ref_list_node);
     d->installed_flow = NULL;
-    if (i->desired_flow == d) {
-        i->desired_flow = ovs_list_is_empty(&i->desired_refs) ? NULL :
-            CONTAINER_OF(ovs_list_front(&i->desired_refs),
-                         struct desired_flow,
-                         installed_ref_list_node);
-    }
+    return old_active == d;
 }
 
 static void
@@ -1280,7 +1253,6 @@ installed_flow_dup(struct desired_flow *src)
 {
     struct installed_flow *dst = xmalloc(sizeof *dst);
     ovs_list_init(&dst->desired_refs);
-    dst->desired_flow = NULL;
     dst->flow.table_id = src->flow.table_id;
     dst->flow.priority = src->flow.priority;
     minimatch_clone(&dst->flow.match, &src->flow.match);
@@ -1291,6 +1263,17 @@ installed_flow_dup(struct desired_flow *src)
     return dst;
 }
 
+static struct desired_flow *
+installed_flow_get_active(struct installed_flow *f)
+{
+    if (!ovs_list_is_empty(&f->desired_refs)) {
+        return CONTAINER_OF(ovs_list_front(&f->desired_refs),
+                            struct desired_flow,
+                            installed_ref_list_node);
+    }
+    return NULL;
+}
+
 static struct desired_flow *
 desired_flow_lookup__(struct ovn_desired_flow_table *flow_table,
                       const struct ovn_flow *target,
@@ -1439,8 +1422,7 @@ static void
 installed_flow_destroy(struct installed_flow *f)
 {
     if (f) {
-        ovs_assert(ovs_list_is_empty(&f->desired_refs));
-        ovs_assert(!f->desired_flow);
+        ovs_assert(!installed_flow_get_active(f));
         ovn_flow_uninit(&f->flow);
         free(f);
     }
@@ -1837,10 +1819,10 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
             /* The desired flow was deleted */
             if (f->installed_flow) {
                 struct installed_flow *i = f->installed_flow;
-                bool was_active = desired_flow_is_active(f);
-                unlink_installed_to_desired(i, f);
+                bool was_active = unlink_installed_to_desired(i, f);
+                struct desired_flow *d = installed_flow_get_active(i);
 
-                if (!i->desired_flow) {
+                if (!d) {
                     installed_flow_del(&i->flow, msgs);
                     ovn_flow_log(&i->flow, "removing installed (tracked)");
 
@@ -1851,7 +1833,6 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
                      * installed flow, so update the OVS flow for the new
                      * active flow (at least the cookie will be different,
                      * even if the actions are the same). */
-                    struct desired_flow *d = i->desired_flow;
                     ovn_flow_log(&i->flow, "updating installed (tracked)");
                     installed_flow_mod(&i->flow, &d->flow, msgs);
                 }
@@ -1870,7 +1851,7 @@ update_installed_flows_by_track(struct ovn_desired_flow_table *flow_table,
                 hmap_insert(&installed_flows, &new_node->match_hmap_node,
                             new_node->flow.hash);
                 link_installed_to_desired(new_node, f);
-            } else if (desired_flow_is_active(f)) {
+            } else if (installed_flow_get_active(i) == f) {
                 /* The installed flow is installed for f, but f has change
                  * tracked, so it must have been modified. */
                 ovn_flow_log(&i->flow, "updating installed (tracked)");
