Reported-at: https://issues.redhat.com/browse/FDP-1522
Reported-at: https://issues.redhat.com/browse/FDP-1523

Signed-off-by: Mark Michelson <mmich...@redhat.com>
---
 northd/en-datapath-logical-router.c | 127 +++++++++++++++++++++++++--
 northd/en-datapath-logical-router.h |  16 +++-
 northd/en-datapath-logical-switch.c | 128 ++++++++++++++++++++++++++--
 northd/en-datapath-logical-switch.h |  14 +++
 northd/inc-proc-northd.c            |   8 +-
 tests/ovn-northd.at                 |  53 ++++++++++++
 6 files changed, 329 insertions(+), 17 deletions(-)

diff --git a/northd/en-datapath-logical-router.c 
b/northd/en-datapath-logical-router.c
index ec974ec53..1b23a5b7b 100644
--- a/northd/en-datapath-logical-router.c
+++ b/northd/en-datapath-logical-router.c
@@ -202,12 +202,30 @@ en_datapath_logical_router_cleanup(void *data)
     ovn_unsynced_datapath_map_destroy(map);
 }
 
+struct ovn_synced_logical_router *
+ovn_synced_logical_router_find(const struct ovn_synced_logical_router_map *map,
+                               const struct uuid *nb_uuid)
+{
+    struct ovn_synced_logical_router *lr;
+    HMAP_FOR_EACH_WITH_HASH (lr, hmap_node, uuid_hash(nb_uuid),
+                             &map->synced_routers) {
+        if (uuid_equals(&lr->nb->header_.uuid, nb_uuid)) {
+            return lr;
+        }
+    }
+
+    return NULL;
+}
+
 static void
 synced_logical_router_map_init(
     struct ovn_synced_logical_router_map *router_map)
 {
     *router_map = (struct ovn_synced_logical_router_map) {
         .synced_routers = HMAP_INITIALIZER(&router_map->synced_routers),
+        .new = HMAPX_INITIALIZER(&router_map->new),
+        .updated = HMAPX_INITIALIZER(&router_map->updated),
+        .deleted = HMAPX_INITIALIZER(&router_map->deleted),
     };
 }
 
@@ -215,7 +233,17 @@ static void
 synced_logical_router_map_destroy(
     struct ovn_synced_logical_router_map *router_map)
 {
+    hmapx_destroy(&router_map->new);
+    hmapx_destroy(&router_map->updated);
+
+    struct hmapx_node *node;
     struct ovn_synced_logical_router *lr;
+    HMAPX_FOR_EACH_SAFE (node, &router_map->deleted) {
+        lr = node->data;
+        free(lr);
+        hmapx_delete(&router_map->deleted, node);
+    }
+    hmapx_destroy(&router_map->deleted);
     HMAP_FOR_EACH_POP (lr, hmap_node, &router_map->synced_routers) {
         free(lr);
     }
@@ -233,6 +261,18 @@ en_datapath_synced_logical_router_init(struct engine_node 
*node OVS_UNUSED,
     return router_map;
 }
 
+static struct ovn_synced_logical_router *
+synced_logical_router_alloc(const struct ovn_synced_datapath *sdp)
+{
+    struct ovn_synced_logical_router *lr = xmalloc(sizeof *lr);
+    *lr = (struct ovn_synced_logical_router) {
+        .nb = CONTAINER_OF(sdp->nb_row, struct nbrec_logical_router,
+                           header_),
+        .sdp = sdp,
+    };
+    return lr;
+}
+
 enum engine_node_state
 en_datapath_synced_logical_router_run(struct engine_node *node , void *data)
 {
@@ -248,12 +288,8 @@ en_datapath_synced_logical_router_run(struct engine_node 
*node , void *data)
         if (sdp->nb_row->table->class_ != &nbrec_table_logical_router) {
             continue;
         }
-        struct ovn_synced_logical_router *lr = xmalloc(sizeof *lr);
-        *lr = (struct ovn_synced_logical_router) {
-            .nb = CONTAINER_OF(sdp->nb_row, struct nbrec_logical_router,
-                               header_),
-            .sdp = sdp,
-        };
+        struct ovn_synced_logical_router *lr =
+            synced_logical_router_alloc(sdp);
         hmap_insert(&router_map->synced_routers, &lr->hmap_node,
                     uuid_hash(&lr->nb->header_.uuid));
     }
@@ -261,6 +297,85 @@ en_datapath_synced_logical_router_run(struct engine_node 
*node , void *data)
     return EN_UPDATED;
 }
 
+void
+en_datapath_synced_logical_router_clear_tracked_data(void *data)
+{
+    struct ovn_synced_logical_router_map *router_map = data;
+
+    hmapx_clear(&router_map->new);
+    hmapx_clear(&router_map->updated);
+
+    struct hmapx_node *node;
+    HMAPX_FOR_EACH_SAFE (node, &router_map->deleted) {
+        struct ovn_synced_logical_router *lr = node->data;
+        free(lr);
+        hmapx_delete(&router_map->deleted, node);
+    }
+}
+
+enum engine_input_handler_result
+en_datapath_synced_logical_router_datapath_sync_handler(
+        struct engine_node *node, void *data)
+{
+    const struct ovn_synced_datapaths *dps =
+        engine_get_input_data("datapath_sync", node);
+    struct ovn_synced_logical_router_map *router_map = data;
+
+    if (hmapx_is_empty(&dps->deleted) &&
+        hmapx_is_empty(&dps->new) &&
+        hmapx_is_empty(&dps->updated)) {
+        return EN_UNHANDLED;
+    }
+
+    struct hmapx_node *hmapx_node;
+    struct ovn_synced_datapath *sdp;
+    struct ovn_synced_logical_router *lr;
+    HMAPX_FOR_EACH (hmapx_node, &dps->new) {
+        sdp = hmapx_node->data;
+        if (sdp->nb_row->table->class_ != &nbrec_table_logical_router) {
+            continue;
+        }
+        lr = synced_logical_router_alloc(sdp);
+        hmap_insert(&router_map->synced_routers, &lr->hmap_node,
+                    uuid_hash(&lr->nb->header_.uuid));
+        hmapx_add(&router_map->new, lr);
+    }
+    HMAPX_FOR_EACH (hmapx_node, &dps->deleted) {
+        sdp = hmapx_node->data;
+        if (sdp->nb_row->table->class_ != &nbrec_table_logical_router) {
+            continue;
+        }
+        lr = ovn_synced_logical_router_find(router_map, &sdp->nb_row->uuid);
+        if (!lr) {
+            return EN_UNHANDLED;
+        }
+        hmap_remove(&router_map->synced_routers, &lr->hmap_node);
+        hmapx_add(&router_map->deleted, lr);
+    }
+    HMAPX_FOR_EACH (hmapx_node, &dps->updated) {
+        sdp = hmapx_node->data;
+        if (sdp->nb_row->table->class_ != &nbrec_table_logical_router) {
+            continue;
+        }
+        lr = ovn_synced_logical_router_find(router_map, &sdp->nb_row->uuid);
+        if (!lr) {
+            return EN_UNHANDLED;
+        }
+        lr->nb = CONTAINER_OF(sdp->nb_row, struct nbrec_logical_router,
+                              header_);
+        lr->sdp = sdp;
+        hmapx_add(&router_map->updated, lr);
+    }
+
+    if (hmapx_is_empty(&router_map->new) &&
+        hmapx_is_empty(&router_map->updated) &&
+        hmapx_is_empty(&router_map->deleted)) {
+        return EN_HANDLED_UNCHANGED;
+    }
+
+    return EN_HANDLED_UPDATED;
+}
+
 void en_datapath_synced_logical_router_cleanup(void *data)
 {
     struct ovn_synced_logical_router_map *router_map = data;
diff --git a/northd/en-datapath-logical-router.h 
b/northd/en-datapath-logical-router.h
index de405dc36..291dbf706 100644
--- a/northd/en-datapath-logical-router.h
+++ b/northd/en-datapath-logical-router.h
@@ -19,6 +19,7 @@
 
 #include "lib/inc-proc-eng.h"
 #include "openvswitch/hmap.h"
+#include "lib/hmapx.h"
 
 void *en_datapath_logical_router_init(struct engine_node *,
                                       struct engine_arg *);
@@ -36,14 +37,27 @@ struct ovn_synced_logical_router {
 
 struct ovn_synced_logical_router_map {
     struct hmap synced_routers;
+
+    bool has_tracked_data;
+    struct hmapx new;
+    struct hmapx updated;
+    struct hmapx deleted;
 };
 
+struct uuid;
+struct ovn_synced_logical_router *
+ovn_synced_logical_router_find(const struct ovn_synced_logical_router_map *map,
+                               const struct uuid *nb_uuid);
+
 void *en_datapath_synced_logical_router_init(struct engine_node *,
                                              struct engine_arg *);
 
 enum engine_node_state en_datapath_synced_logical_router_run(
     struct engine_node *, void *data);
-
+void en_datapath_synced_logical_router_clear_tracked_data(void *data);
+enum engine_input_handler_result
+en_datapath_synced_logical_router_datapath_sync_handler(
+        struct engine_node *node, void *data);
 void en_datapath_synced_logical_router_cleanup(void *data);
 
 enum engine_input_handler_result
diff --git a/northd/en-datapath-logical-switch.c 
b/northd/en-datapath-logical-switch.c
index 29a64ed43..1c401030e 100644
--- a/northd/en-datapath-logical-switch.c
+++ b/northd/en-datapath-logical-switch.c
@@ -200,12 +200,30 @@ en_datapath_logical_switch_cleanup(void *data)
     ovn_unsynced_datapath_map_destroy(map);
 }
 
+struct ovn_synced_logical_switch *
+ovn_synced_logical_switch_find(const struct ovn_synced_logical_switch_map *map,
+                               const struct uuid *nb_uuid)
+{
+    struct ovn_synced_logical_switch *lsw;
+    HMAP_FOR_EACH_WITH_HASH (lsw, hmap_node, uuid_hash(nb_uuid),
+                             &map->synced_switches) {
+        if (uuid_equals(&lsw->nb->header_.uuid, nb_uuid)) {
+            return lsw;
+        }
+    }
+
+    return NULL;
+}
+
 static void
 synced_logical_switch_map_init(
     struct ovn_synced_logical_switch_map *switch_map)
 {
     *switch_map = (struct ovn_synced_logical_switch_map) {
         .synced_switches = HMAP_INITIALIZER(&switch_map->synced_switches),
+        .new = HMAPX_INITIALIZER(&switch_map->new),
+        .updated = HMAPX_INITIALIZER(&switch_map->updated),
+        .deleted = HMAPX_INITIALIZER(&switch_map->deleted),
     };
 }
 
@@ -213,7 +231,17 @@ static void
 synced_logical_switch_map_destroy(
     struct ovn_synced_logical_switch_map *switch_map)
 {
+    hmapx_destroy(&switch_map->new);
+    hmapx_destroy(&switch_map->updated);
+
+    struct hmapx_node *node;
     struct ovn_synced_logical_switch *ls;
+    HMAPX_FOR_EACH_SAFE (node, &switch_map->deleted) {
+        ls = node->data;
+        free(ls);
+        hmapx_delete(&switch_map->deleted, node);
+    }
+    hmapx_destroy(&switch_map->deleted);
     HMAP_FOR_EACH_POP (ls, hmap_node, &switch_map->synced_switches) {
         free(ls);
     }
@@ -231,6 +259,18 @@ en_datapath_synced_logical_switch_init(struct engine_node 
*node OVS_UNUSED,
     return switch_map;
 }
 
+static struct ovn_synced_logical_switch *
+synced_logical_switch_alloc(const struct ovn_synced_datapath *sdp)
+{
+    struct ovn_synced_logical_switch *lsw = xmalloc(sizeof *lsw);
+    *lsw = (struct ovn_synced_logical_switch) {
+        .nb = CONTAINER_OF(sdp->nb_row, struct nbrec_logical_switch,
+                           header_),
+        .sdp = sdp,
+    };
+    return lsw;
+}
+
 enum engine_node_state
 en_datapath_synced_logical_switch_run(struct engine_node *node , void *data)
 {
@@ -246,12 +286,8 @@ en_datapath_synced_logical_switch_run(struct engine_node 
*node , void *data)
         if (sdp->nb_row->table->class_ != &nbrec_table_logical_switch) {
             continue;
         }
-        struct ovn_synced_logical_switch *lsw = xmalloc(sizeof *lsw);
-        *lsw = (struct ovn_synced_logical_switch) {
-            .nb = CONTAINER_OF(sdp->nb_row, struct nbrec_logical_switch,
-                               header_),
-            .sdp = sdp,
-        };
+        struct ovn_synced_logical_switch *lsw =
+            synced_logical_switch_alloc(sdp);
         hmap_insert(&switch_map->synced_switches, &lsw->hmap_node,
                     uuid_hash(&lsw->nb->header_.uuid));
     }
@@ -259,6 +295,86 @@ en_datapath_synced_logical_switch_run(struct engine_node 
*node , void *data)
     return EN_UPDATED;
 }
 
+void
+en_datapath_synced_logical_switch_clear_tracked_data(void *data)
+{
+    struct ovn_synced_logical_switch_map *switch_map = data;
+
+    hmapx_clear(&switch_map->new);
+    hmapx_clear(&switch_map->updated);
+
+    struct hmapx_node *node;
+    HMAPX_FOR_EACH_SAFE (node, &switch_map->deleted) {
+        struct ovn_synced_logical_router *lr = node->data;
+        free(lr);
+        hmapx_delete(&switch_map->deleted, node);
+    }
+}
+
+
+enum engine_input_handler_result
+en_datapath_synced_logical_switch_datapath_sync_handler(
+        struct engine_node *node, void *data)
+{
+    const struct ovn_synced_datapaths *dps =
+        engine_get_input_data("datapath_sync", node);
+    struct ovn_synced_logical_switch_map *switch_map = data;
+
+    if (hmapx_is_empty(&dps->deleted) &&
+        hmapx_is_empty(&dps->new) &&
+        hmapx_is_empty(&dps->updated)) {
+        return EN_UNHANDLED;
+    }
+
+    struct hmapx_node *hmapx_node;
+    struct ovn_synced_datapath *sdp;
+    struct ovn_synced_logical_switch *lsw;
+    HMAPX_FOR_EACH (hmapx_node, &dps->new) {
+        sdp = hmapx_node->data;
+        if (sdp->nb_row->table->class_ != &nbrec_table_logical_switch) {
+            continue;
+        }
+        lsw = synced_logical_switch_alloc(sdp);
+        hmap_insert(&switch_map->synced_switches, &lsw->hmap_node,
+                    uuid_hash(&lsw->nb->header_.uuid));
+        hmapx_add(&switch_map->new, lsw);
+    }
+    HMAPX_FOR_EACH (hmapx_node, &dps->deleted) {
+        sdp = hmapx_node->data;
+        if (sdp->nb_row->table->class_ != &nbrec_table_logical_switch) {
+            continue;
+        }
+        lsw = ovn_synced_logical_switch_find(switch_map, &sdp->nb_row->uuid);
+        if (!lsw) {
+            return EN_UNHANDLED;
+        }
+        hmap_remove(&switch_map->synced_switches, &lsw->hmap_node);
+        hmapx_add(&switch_map->deleted, lsw);
+    }
+    HMAPX_FOR_EACH (hmapx_node, &dps->updated) {
+        sdp = hmapx_node->data;
+        if (sdp->nb_row->table->class_ != &nbrec_table_logical_switch) {
+            continue;
+        }
+        lsw = ovn_synced_logical_switch_find(switch_map, &sdp->nb_row->uuid);
+        if (!lsw) {
+            return EN_UNHANDLED;
+        }
+        lsw->nb = CONTAINER_OF(sdp->nb_row, struct nbrec_logical_switch,
+                               header_);
+        lsw->sdp = sdp;
+        hmapx_add(&switch_map->updated, lsw);
+    }
+
+    if (hmapx_is_empty(&switch_map->new) &&
+        hmapx_is_empty(&switch_map->updated) &&
+        hmapx_is_empty(&switch_map->deleted)) {
+        return EN_HANDLED_UNCHANGED;
+    }
+
+    return EN_HANDLED_UPDATED;
+}
+
 void en_datapath_synced_logical_switch_cleanup(void *data)
 {
     struct ovn_synced_logical_switch_map *switch_map = data;
diff --git a/northd/en-datapath-logical-switch.h 
b/northd/en-datapath-logical-switch.h
index 6abedbd30..db596cdee 100644
--- a/northd/en-datapath-logical-switch.h
+++ b/northd/en-datapath-logical-switch.h
@@ -19,6 +19,7 @@
 
 #include "lib/inc-proc-eng.h"
 #include "openvswitch/hmap.h"
+#include "lib/hmapx.h"
 
 void *en_datapath_logical_switch_init(struct engine_node *,
                                       struct engine_arg *);
@@ -38,13 +39,26 @@ struct ovn_synced_logical_switch {
 
 struct ovn_synced_logical_switch_map {
     struct hmap synced_switches;
+
+    struct hmapx new;
+    struct hmapx updated;
+    struct hmapx deleted;
 };
 
+struct uuid;
+struct ovn_synced_logical_switch *
+ovn_synced_logical_switch_find(const struct ovn_synced_logical_switch_map *map,
+                               const struct uuid *nb_uuid);
+
 void *en_datapath_synced_logical_switch_init(struct engine_node *,
                                              struct engine_arg *);
 
 enum engine_node_state en_datapath_synced_logical_switch_run(
     struct engine_node *, void *data);
+void en_datapath_synced_logical_switch_clear_tracked_data(void *data);
+enum engine_input_handler_result
+en_datapath_synced_logical_switch_datapath_sync_handler(
+        struct engine_node *node, void *data);
 void en_datapath_synced_logical_switch_cleanup(void *data);
 
 #endif /* EN_DATAPATH_LOGICAL_SWITCH_H */
diff --git a/northd/inc-proc-northd.c b/northd/inc-proc-northd.c
index c43c35118..c0f1d067a 100644
--- a/northd/inc-proc-northd.c
+++ b/northd/inc-proc-northd.c
@@ -185,8 +185,8 @@ 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, CLEAR_TRACKED_DATA);
-static ENGINE_NODE(datapath_synced_logical_router);
-static ENGINE_NODE(datapath_synced_logical_switch);
+static ENGINE_NODE(datapath_synced_logical_router, CLEAR_TRACKED_DATA);
+static ENGINE_NODE(datapath_synced_logical_switch, CLEAR_TRACKED_DATA);
 
 void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
                           struct ovsdb_idl_loop *sb)
@@ -235,9 +235,9 @@ void inc_proc_northd_init(struct ovsdb_idl_loop *nb,
                      datapath_sync_logical_router_handler);
 
     engine_add_input(&en_datapath_synced_logical_router, &en_datapath_sync,
-                     NULL);
+                     en_datapath_synced_logical_router_datapath_sync_handler);
     engine_add_input(&en_datapath_synced_logical_switch, &en_datapath_sync,
-                     NULL);
+                     en_datapath_synced_logical_switch_datapath_sync_handler);
 
     engine_add_input(&en_northd, &en_nb_mirror, NULL);
     engine_add_input(&en_northd, &en_nb_mirror_rule, NULL);
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 1013333fd..c5892bc5b 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -17750,3 +17750,56 @@ CHECK_NO_CHANGE_AFTER_RECOMPUTE
 
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD_NO_HV([
+AT_SETUP([Synced logical switch and router incremental procesesing])
+ovn_start
+
+# datapath_synced_logical_switch and datapath_synced_logical_router
+# should only recompute if datapath_sync has to recompute. Therefore,
+# andy situation where datapath_sync can run incrementally, the
+# synced datapath nodes should also run incrementally.
+
+check as northd ovn-appctl -t ovn-northd inc-engine/clear-stats
+check ovn-nbctl --wait=sb ls-add sw0
+check_engine_stats datapath_synced_logical_switch norecompute compute
+check_engine_stats datapath_synced_logical_router 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_synced_logical_switch norecompute compute
+check_engine_stats datapath_synced_logical_router 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_synced_logical_switch norecompute compute
+check_engine_stats datapath_synced_logical_router 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_synced_logical_switch norecompute compute
+check_engine_stats datapath_synced_logical_router 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_synced_logical_switch norecompute compute
+check_engine_stats datapath_synced_logical_router 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_Router lr0 options:ct-zone-limit=10
+check_engine_stats datapath_synced_logical_switch norecompute compute
+check_engine_stats datapath_synced_logical_router 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_synced_logical_switch norecompute compute
+check_engine_stats datapath_synced_logical_router 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