From: Lorenzo Bianconi <lorenzo.bianc...@redhat.com>

Introduce Incremetal processing logic to datapath-sync node for
en_datapath_logical_switch and en_datapath_logical_router inputs.

One test change that may seem unrelated is the propage sb_cfg test in
ovn-northd.at. That test checked for a specific sequence of events to
happen based on northbound database manipulation. The test had used the
insertion of a logical switch to test this. Now, inserting a logical
switch causes more than one engine run to occur because of the way
en-datapath-sync works. The easiest way to fix the test was to insert a
different type of row into the database, so this commit changes to
using a port group now.

Reported-at: https://issues.redhat.com/browse/FDP-1519
Signed-off-by: Lorenzo Bianconi <lorenzo.bianc...@redhat.com>
---
v13
 * Rebased.
 * The previous version of this patch introduced a delay for SB
   propagation of synced datapaths until we had a permanent pointer
   to the datapath binding. This no longer happens with this patch.
   We now pass the synced datapath when the northbound logical datapath
   is created. We then use a new collection, new_sb, to communicate
   when the datapath pointer needs to be updated. This allows for
   ovn-nbctl --wait=sb to work the same as it always has.

v12
 * Rebased
 * Use hmapx_is_empty() instead of hmapx_count() to determine if there
   are unsynced datapaths that need to be handled.
 * Fix typo where EN_UPDATED was being returned in the case where
   EN_UNCHANGED should have been returned.
 * The previous version of this patch changed en_northd to no longer
   have a handler for en_sb_datapath_binding. This caused a bunch of
   test failures. This change is now delayed until patch 8 in the
   series.
---
 northd/datapath-sync.h    |  30 ++++
 northd/en-datapath-sync.c | 283 +++++++++++++++++++++++++++++++++++++-
 northd/en-datapath-sync.h |   7 +
 northd/en-northd.c        |   2 -
 northd/inc-proc-northd.c  |  11 +-
 northd/northd.h           |   1 -
 tests/ovn-northd.at       |  40 ++++++
 7 files changed, 360 insertions(+), 14 deletions(-)

diff --git a/northd/datapath-sync.h b/northd/datapath-sync.h
index f3725617e..7e9f3e860 100644
--- a/northd/datapath-sync.h
+++ b/northd/datapath-sync.h
@@ -74,11 +74,41 @@ struct ovn_synced_datapath {
     struct hmap_node hmap_node;
     const struct ovsdb_idl_row *nb_row;
     const struct sbrec_datapath_binding *sb_dp;
+    /* This boolean indicates if the synced datapath
+     * has a transient sb_dp pointer. If "true", then
+     * it means the sb_dp field is the return value of
+     * sbrec_datapath_binding_insert(). If "false", then
+     * it means the sb_dp field was provided by an IDL
+     * update.
+     *
+     * This field is only necessary in order to distinguish
+     * duplicate southbound datapath binding records. If a
+     * mischievous agent inserts a datapath binding that walks,
+     * looks, and quacks like an existing datapath binding,
+     * this is what helps us distinguish that the inserted
+     * datapath is actually a duplicate of a known datapath.
+     */
+    bool pending_sb_dp;
 };
 
 struct ovn_synced_datapaths {
     struct hmap synced_dps;
     struct hmap dp_tnlids;
+
+    struct hmapx new;
+    struct hmapx updated;
+    struct hmapx deleted;
+
+    /* The new_sb hmapx contains synced datapaths whose southbound
+     * datapath pointer was detected as "new" from the datapath sync
+     * node. This means that the southbound datapath binding pointer
+     * has been updated to a new value, but the contents of the southbound
+     * datapath binding are the same as they had been in the previous
+     * engine run. Synced datapath binding handlers know to update
+     * their pointer but not to present the synced datapath as "new" or
+     * "updated" in this situation.
+     */
+    struct hmapx new_sb;
 };
 
 /* This is a simple wrapper for a southbound datapath binding. Its purpose
diff --git a/northd/en-datapath-sync.c b/northd/en-datapath-sync.c
index db84448e0..19b9a3264 100644
--- a/northd/en-datapath-sync.c
+++ b/northd/en-datapath-sync.c
@@ -36,6 +36,10 @@ en_datapath_sync_init(struct engine_node *node OVS_UNUSED,
     *synced_datapaths = (struct ovn_synced_datapaths) {
         .synced_dps = HMAP_INITIALIZER(&synced_datapaths->synced_dps),
         .dp_tnlids = HMAP_INITIALIZER(&synced_datapaths->dp_tnlids),
+        .new = HMAPX_INITIALIZER(&synced_datapaths->new),
+        .new_sb = HMAPX_INITIALIZER(&synced_datapaths->new_sb),
+        .deleted = HMAPX_INITIALIZER(&synced_datapaths->deleted),
+        .updated = HMAPX_INITIALIZER(&synced_datapaths->updated),
     };
 
     return synced_datapaths;
@@ -70,6 +74,38 @@ find_unsynced_datapath(const struct 
ovn_unsynced_datapath_map **maps,
     return NULL;
 }
 
+static struct ovn_synced_datapath *
+find_synced_datapath_from_udp(
+        const struct ovn_synced_datapaths *synced_datapaths,
+        const struct ovn_unsynced_datapath *udp)
+{
+    struct ovn_synced_datapath *sdp;
+    uint32_t hash = uuid_hash(&udp->nb_row->uuid);
+    HMAP_FOR_EACH_WITH_HASH (sdp, hmap_node, hash,
+                             &synced_datapaths->synced_dps) {
+        if (uuid_equals(&sdp->nb_row->uuid, &udp->nb_row->uuid)) {
+            return sdp;
+        }
+    }
+
+    return NULL;
+}
+
+static struct ovn_synced_datapath *
+find_synced_datapath_from_sb(const struct hmap *datapaths,
+                             const struct sbrec_datapath_binding *sb_dp)
+{
+    struct ovn_synced_datapath *sdp;
+    uint32_t hash = uuid_hash(sb_dp->nb_uuid);
+    HMAP_FOR_EACH_WITH_HASH (sdp, hmap_node, hash, datapaths) {
+        if (uuid_equals(&sdp->nb_row->uuid, sb_dp->nb_uuid)) {
+            return sdp;
+        }
+    }
+
+    return NULL;
+}
+
 struct candidate_sdp {
     struct ovn_synced_datapath *sdp;
     uint32_t requested_tunnel_key;
@@ -79,21 +115,43 @@ struct candidate_sdp {
 
 static struct ovn_synced_datapath *
 synced_datapath_alloc(const struct ovn_unsynced_datapath *udp,
-                      const struct sbrec_datapath_binding *sb_dp)
+                      const struct sbrec_datapath_binding *sb_dp,
+                      bool pending_sb_dp)
 {
     struct ovn_synced_datapath *sdp;
     sdp = xmalloc(sizeof *sdp);
     *sdp = (struct ovn_synced_datapath) {
         .sb_dp = sb_dp,
         .nb_row = udp->nb_row,
+        .pending_sb_dp = pending_sb_dp
     };
+    return sdp;
+}
+
+static void
+synced_datapath_set_sb_fields(const struct sbrec_datapath_binding *sb_dp,
+                              const struct ovn_unsynced_datapath *udp)
+{
     sbrec_datapath_binding_set_external_ids(sb_dp, &udp->external_ids);
 
     sbrec_datapath_binding_set_nb_uuid(sb_dp, &udp->nb_row->uuid, 1);
 
     sbrec_datapath_binding_set_type(sb_dp,
                                     ovn_datapath_type_to_string(udp->type));
-    return sdp;
+}
+
+static void
+clear_tracked_data(struct ovn_synced_datapaths *synced_datapaths)
+{
+    hmapx_clear(&synced_datapaths->new);
+    hmapx_clear(&synced_datapaths->new_sb);
+    hmapx_clear(&synced_datapaths->updated);
+
+    struct hmapx_node *node;
+    HMAPX_FOR_EACH_SAFE (node, &synced_datapaths->deleted) {
+        free(node->data);
+        hmapx_delete(&synced_datapaths->deleted, node);
+    }
 }
 
 static void
@@ -104,6 +162,7 @@ reset_synced_datapaths(struct ovn_synced_datapaths 
*synced_datapaths)
         free(sdp);
     }
     ovn_destroy_tnlids(&synced_datapaths->dp_tnlids);
+    clear_tracked_data(synced_datapaths);
     hmap_init(&synced_datapaths->dp_tnlids);
 }
 
@@ -135,10 +194,11 @@ create_synced_datapath_candidates_from_sb(
         }
 
         struct candidate_sdp candidate = {
-            .sdp = synced_datapath_alloc(udp, sb_dp),
+            .sdp = synced_datapath_alloc(udp, sb_dp, false),
             .requested_tunnel_key = udp->requested_tunnel_key,
             .existing_tunnel_key = sb_dp->tunnel_key,
         };
+        synced_datapath_set_sb_fields(sb_dp, udp);
         vector_push(candidate_sdps, &candidate);
         uuidset_insert(visited, &udp->nb_row->uuid);
     }
@@ -161,10 +221,11 @@ create_synced_datapath_candidates_from_nb(
             struct sbrec_datapath_binding *sb_dp;
             sb_dp = sbrec_datapath_binding_insert(ovnsb_idl_txn);
             struct candidate_sdp candidate = {
-                .sdp = synced_datapath_alloc(udp, sb_dp),
+                .sdp = synced_datapath_alloc(udp, sb_dp, true),
                 .requested_tunnel_key = udp->requested_tunnel_key,
                 .existing_tunnel_key = sb_dp->tunnel_key,
             };
+            synced_datapath_set_sb_fields(sb_dp, udp);
             vector_push(candidate_sdps, &candidate);
         }
     }
@@ -190,7 +251,8 @@ assign_requested_tunnel_keys(struct vector *candidate_sdps,
         }
         sbrec_datapath_binding_set_tunnel_key(candidate->sdp->sb_dp,
                                               candidate->requested_tunnel_key);
-        hmap_insert(&synced_datapaths->synced_dps, &candidate->sdp->hmap_node,
+        hmap_insert(&synced_datapaths->synced_dps,
+                    &candidate->sdp->hmap_node,
                     uuid_hash(candidate->sdp->sb_dp->nb_uuid));
         candidate->tunnel_key_assigned = true;
     }
@@ -239,7 +301,8 @@ allocate_tunnel_keys(struct vector *candidate_sdps,
         }
         sbrec_datapath_binding_set_tunnel_key(candidate->sdp->sb_dp,
                                               tunnel_key);
-        hmap_insert(&synced_datapaths->synced_dps, &candidate->sdp->hmap_node,
+        hmap_insert(&synced_datapaths->synced_dps,
+                    &candidate->sdp->hmap_node,
                     uuid_hash(candidate->sdp->sb_dp->nb_uuid));
         candidate->tunnel_key_assigned = true;
     }
@@ -258,6 +321,199 @@ delete_unassigned_candidates(struct vector 
*candidate_sdps)
     }
 }
 
+static enum engine_input_handler_result
+datapath_sync_unsynced_datapath_handler(
+        const struct ovn_unsynced_datapath_map *map,
+        const struct ed_type_global_config *global_config,
+        struct ovsdb_idl_txn *ovnsb_idl_txn, void *data)
+{
+    enum engine_input_handler_result ret = EN_HANDLED_UNCHANGED;
+    struct ovn_synced_datapaths *synced_datapaths = data;
+    struct ovn_unsynced_datapath *udp;
+    struct ovn_synced_datapath *sdp;
+
+    if (hmapx_is_empty(&map->new) &&
+        hmapx_is_empty(&map->deleted) &&
+        hmapx_is_empty(&map->updated)) {
+        return EN_UNHANDLED;
+    }
+
+    struct hmapx_node *n;
+    HMAPX_FOR_EACH (n, &map->deleted) {
+        udp = n->data;
+        sdp = find_synced_datapath_from_udp(synced_datapaths, udp);
+        if (!sdp) {
+            return EN_UNHANDLED;
+        }
+        hmap_remove(&synced_datapaths->synced_dps, &sdp->hmap_node);
+        hmapx_add(&synced_datapaths->deleted, sdp);
+        ovn_free_tnlid(&synced_datapaths->dp_tnlids,
+                       sdp->sb_dp->tunnel_key);
+        sbrec_datapath_binding_delete(sdp->sb_dp);
+        ret = EN_HANDLED_UPDATED;
+    }
+
+    HMAPX_FOR_EACH (n, &map->new) {
+        udp = n->data;
+        uint32_t tunnel_key;
+
+        if (find_synced_datapath_from_udp(synced_datapaths, udp)) {
+            return EN_UNHANDLED;
+        }
+
+        if (udp->requested_tunnel_key) {
+            tunnel_key = udp->requested_tunnel_key;
+            if (!ovn_add_tnlid(&synced_datapaths->dp_tnlids, tunnel_key)) {
+                return EN_UNHANDLED;
+            }
+        } else {
+            uint32_t hint = 0;
+            tunnel_key = ovn_allocate_tnlid(&synced_datapaths->dp_tnlids,
+                                            "datapath", OVN_MIN_DP_KEY_LOCAL,
+                                            global_config->max_dp_tunnel_id,
+                                            &hint);
+            if (!tunnel_key) {
+                return EN_UNHANDLED;
+            }
+        }
+
+        struct sbrec_datapath_binding *sb_dp =
+            sbrec_datapath_binding_insert(ovnsb_idl_txn);
+        sbrec_datapath_binding_set_tunnel_key(sb_dp, tunnel_key);
+        sdp = synced_datapath_alloc(udp, sb_dp, true);
+        synced_datapath_set_sb_fields(sb_dp, udp);
+        hmap_insert(&synced_datapaths->synced_dps, &sdp->hmap_node,
+                    uuid_hash(sb_dp->nb_uuid));
+        hmapx_add(&synced_datapaths->new, sdp);
+        ret = EN_HANDLED_UPDATED;
+    }
+
+    HMAPX_FOR_EACH (n, &map->updated) {
+        udp = n->data;
+        sdp = find_synced_datapath_from_udp(synced_datapaths, udp);
+        if (!sdp || !sdp->sb_dp) {
+            return EN_UNHANDLED;
+        }
+        if (udp->requested_tunnel_key &&
+            udp->requested_tunnel_key != sdp->sb_dp->tunnel_key) {
+            ovn_free_tnlid(&synced_datapaths->dp_tnlids,
+                           sdp->sb_dp->tunnel_key);
+            if (!ovn_add_tnlid(&synced_datapaths->dp_tnlids,
+                               udp->requested_tunnel_key)) {
+                return EN_UNHANDLED;
+            }
+            sbrec_datapath_binding_set_tunnel_key(sdp->sb_dp,
+                                                  udp->requested_tunnel_key);
+        }
+        if (!smap_equal(&udp->external_ids, &sdp->sb_dp->external_ids)) {
+            sbrec_datapath_binding_set_external_ids(sdp->sb_dp,
+                                                    &udp->external_ids);
+        }
+        hmapx_add(&synced_datapaths->updated, sdp);
+        ret = EN_HANDLED_UPDATED;
+    }
+
+    return ret;
+}
+
+enum engine_input_handler_result
+datapath_sync_logical_switch_handler(struct engine_node *node, void *data)
+{
+    const struct ovn_unsynced_datapath_map *map =
+        engine_get_input_data("datapath_logical_switch", node);
+    const struct engine_context *eng_ctx = engine_get_context();
+    const struct ed_type_global_config *global_config =
+        engine_get_input_data("global_config", node);
+
+    return datapath_sync_unsynced_datapath_handler(map, global_config,
+                                                   eng_ctx->ovnsb_idl_txn,
+                                                   data);
+}
+
+enum engine_input_handler_result
+datapath_sync_logical_router_handler(struct engine_node *node, void *data)
+{
+    const struct ovn_unsynced_datapath_map *map =
+        engine_get_input_data("datapath_logical_router", node);
+    const struct engine_context *eng_ctx = engine_get_context();
+    const struct ed_type_global_config *global_config =
+        engine_get_input_data("global_config", node);
+
+    return datapath_sync_unsynced_datapath_handler(map, global_config,
+                                                   eng_ctx->ovnsb_idl_txn,
+                                                   data);
+}
+
+enum engine_input_handler_result
+datapath_sync_sb_datapath_binding(struct engine_node *node, void *data)
+{
+    const struct sbrec_datapath_binding_table *sb_dp_table =
+        EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node));
+    enum engine_input_handler_result ret = EN_HANDLED_UNCHANGED;
+    struct ovn_synced_datapaths *synced_datapaths = data;
+
+    const struct sbrec_datapath_binding *sb_dp;
+    SBREC_DATAPATH_BINDING_TABLE_FOR_EACH_TRACKED (sb_dp, sb_dp_table) {
+        struct ovn_synced_datapath *sdp =
+            find_synced_datapath_from_sb(&synced_datapaths->synced_dps, sb_dp);
+        if (sbrec_datapath_binding_is_deleted(sb_dp)) {
+            if (sdp) {
+                /* The SB datapath binding was deleted, but we still have a
+                 * record of it locally. This implies the SB datapath binding
+                 * was deleted by something other than ovn-northd. We need
+                 * to recompute in this case.
+                 */
+                return EN_UNHANDLED;
+            }
+            continue;
+        }
+
+        if (sbrec_datapath_binding_is_new(sb_dp)) {
+            if (!sdp) {
+                /* There is a new datapath binding, but we have no record
+                 * of the synced datapath. This indicates that
+                 * something other than ovn-northd added this datapath
+                 * binding to the database, and we need to recompute.
+                 */
+                return EN_UNHANDLED;
+            } else {
+                if (sdp->pending_sb_dp) {
+                    /* Update the existing synced datapath pointer to the safer
+                     * version to cache.
+                     */
+                    sdp->sb_dp = sb_dp;
+                    sdp->pending_sb_dp = false;
+                    hmapx_add(&synced_datapaths->new_sb, sdp);
+                    ret = EN_HANDLED_UPDATED;
+                } else {
+                    /* Some jerk has inserted a duplicate datapath to try to
+                     * fool us. Not on my watch!
+                     */
+                    return EN_UNHANDLED;
+                }
+            }
+            continue;
+        }
+
+        /* Datapath binding is updated. This happens if the northbound
+         * logical datapath is updated and we make changes to the existing
+         * southbound datapath binding. In this case, the handler for the
+         * unsynced datapath will add sdp to synced_datapaths->updated, so
+         * we don't need to do anything here.
+         */
+    }
+
+    return ret;
+}
+
+void
+en_datapath_sync_clear_tracked_data(void *data)
+{
+    struct ovn_synced_datapaths *synced_datapaths = data;
+
+    clear_tracked_data(synced_datapaths);
+}
+
 enum engine_node_state
 en_datapath_sync_run(struct engine_node *node , void *data)
 {
@@ -304,7 +560,11 @@ en_datapath_sync_run(struct engine_node *node , void *data)
     delete_unassigned_candidates(&candidate_sdps);
     vector_destroy(&candidate_sdps);
 
-    return EN_UPDATED;
+    if (hmap_count(&synced_datapaths->synced_dps)) {
+        return EN_UPDATED;
+    } else {
+        return EN_UNCHANGED;
+    }
 }
 
 void en_datapath_sync_cleanup(void *data)
@@ -312,6 +572,15 @@ void en_datapath_sync_cleanup(void *data)
     struct ovn_synced_datapaths *synced_datapaths = data;
     struct ovn_synced_datapath *sdp;
 
+    hmapx_destroy(&synced_datapaths->new);
+    hmapx_destroy(&synced_datapaths->new_sb);
+    hmapx_destroy(&synced_datapaths->updated);
+    struct hmapx_node *node;
+    HMAPX_FOR_EACH_SAFE (node, &synced_datapaths->deleted) {
+        free(node->data);
+    }
+    hmapx_destroy(&synced_datapaths->deleted);
+
     HMAP_FOR_EACH_POP (sdp, hmap_node, &synced_datapaths->synced_dps) {
         free(sdp);
     }
diff --git a/northd/en-datapath-sync.h b/northd/en-datapath-sync.h
index 3b3262304..bed2d5a7b 100644
--- a/northd/en-datapath-sync.h
+++ b/northd/en-datapath-sync.h
@@ -21,7 +21,14 @@
 
 void *en_datapath_sync_init(struct engine_node *,
                             struct engine_arg *);
+enum engine_input_handler_result
+datapath_sync_logical_switch_handler(struct engine_node *, void *data);
+enum engine_input_handler_result
+datapath_sync_logical_router_handler(struct engine_node *, void *data);
+enum engine_input_handler_result
+datapath_sync_sb_datapath_binding(struct engine_node *, void *data);
 enum engine_node_state en_datapath_sync_run(struct engine_node *, void *data);
 void en_datapath_sync_cleanup(void *data);
+void en_datapath_sync_clear_tracked_data(void *data);
 
 #endif /* EN_DATAPATH_SYNC_H */
diff --git a/northd/en-northd.c b/northd/en-northd.c
index b991d3a1c..b2986edf1 100644
--- a/northd/en-northd.c
+++ b/northd/en-northd.c
@@ -81,8 +81,6 @@ northd_get_input_data(struct engine_node *node,
     input_data->nbrec_port_group_table =
         EN_OVSDB_GET(engine_get_input("NB_port_group", node));
 
-    input_data->sbrec_datapath_binding_table =
-        EN_OVSDB_GET(engine_get_input("SB_datapath_binding", node));
     input_data->sbrec_port_binding_table =
         EN_OVSDB_GET(engine_get_input("SB_port_binding", node));
     input_data->sbrec_mac_binding_table =
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index 0dfbf00b5..243c0c0c0 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -184,7 +184,7 @@ static ENGINE_NODE(dynamic_routes);
 static ENGINE_NODE(group_ecmp_route, CLEAR_TRACKED_DATA);
 static ENGINE_NODE(datapath_logical_router, CLEAR_TRACKED_DATA);
 static ENGINE_NODE(datapath_logical_switch, CLEAR_TRACKED_DATA);
-static ENGINE_NODE(datapath_sync);
+static ENGINE_NODE(datapath_sync, CLEAR_TRACKED_DATA);
 static ENGINE_NODE(datapath_synced_logical_router);
 static ENGINE_NODE(datapath_synced_logical_switch);
 
@@ -225,10 +225,13 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
     engine_add_input(&en_datapath_logical_router, &en_nb_logical_router,
                      en_datapath_logical_router_logical_router_handler);
 
-    engine_add_input(&en_datapath_sync, &en_datapath_logical_switch, NULL);
-    engine_add_input(&en_datapath_sync, &en_datapath_logical_router, NULL);
-    engine_add_input(&en_datapath_sync, &en_sb_datapath_binding, NULL);
     engine_add_input(&en_datapath_sync, &en_global_config, NULL);
+    engine_add_input(&en_datapath_sync, &en_sb_datapath_binding,
+                     datapath_sync_sb_datapath_binding);
+    engine_add_input(&en_datapath_sync, &en_datapath_logical_switch,
+                     datapath_sync_logical_switch_handler);
+    engine_add_input(&en_datapath_sync, &en_datapath_logical_router,
+                     datapath_sync_logical_router_handler);
 
     engine_add_input(&en_datapath_synced_logical_router, &en_datapath_sync,
                      NULL);
diff --git a/northd/northd.h b/northd/northd.h
index e223a54da..3541a9160 100644
--- a/northd/northd.h
+++ b/northd/northd.h
@@ -42,7 +42,6 @@ struct northd_input {
     const struct nbrec_port_group_table *nbrec_port_group_table;
 
     /* Southbound table references */
-    const struct sbrec_datapath_binding_table *sbrec_datapath_binding_table;
     const struct sbrec_port_binding_table *sbrec_port_binding_table;
     const struct sbrec_mac_binding_table *sbrec_mac_binding_table;
     const struct sbrec_ha_chassis_group_table *sbrec_ha_chassis_group_table;
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 8620c5382..c919735cc 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -17822,3 +17822,43 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
 AT_CLEANUP
 ])
 
+OVN_FOR_EACH_NORTHD_NO_HV([
+AT_SETUP([Datapath Sync incremental processing])
+ovn_start
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb ls-add sw0
+check_engine_stats datapath_sync norecompute compute
+CHECK_NO_CHANGE_AFTER_RECOMPUTE
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb set logical_switch sw0 
other_config:fdb_age_threshold=5
+check_engine_stats datapath_sync norecompute compute
+CHECK_NO_CHANGE_AFTER_RECOMPUTE
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb set logical_switch sw0 
other_config:requested-tnl-key=123
+check_engine_stats datapath_sync norecompute compute
+CHECK_NO_CHANGE_AFTER_RECOMPUTE
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb ls-del sw0
+check_engine_stats datapath_sync norecompute compute
+CHECK_NO_CHANGE_AFTER_RECOMPUTE
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb lr-add lr0
+check_engine_stats datapath_sync norecompute compute
+CHECK_NO_CHANGE_AFTER_RECOMPUTE
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl set Logical_Router lr0 options:ct-zone-limit=10
+check_engine_stats datapath_sync norecompute compute
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb lr-del lr0
+check_engine_stats datapath_sync norecompute compute
+CHECK_NO_CHANGE_AFTER_RECOMPUTE
+
+AT_CLEANUP
+])
-- 
2.49.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to