[ovs-dev] [RFC v2 01/10] ovn-controller: Incremental processing engine

Han Zhou zhouhan at gmail.com
Thu Mar 22 18:42:18 UTC 2018


This patch implements the engine which will be used in future patches
for ovn-controller incremental processing.
---
 ovn/lib/automake.mk    |   4 +-
 ovn/lib/inc-proc-eng.c |  97 ++++++++++++++++++++++++++++++++++++++++
 ovn/lib/inc-proc-eng.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 218 insertions(+), 1 deletion(-)
 create mode 100644 ovn/lib/inc-proc-eng.c
 create mode 100644 ovn/lib/inc-proc-eng.h

diff --git a/ovn/lib/automake.mk b/ovn/lib/automake.mk
index 6178fc2..c1d37c5 100644
--- a/ovn/lib/automake.mk
+++ b/ovn/lib/automake.mk
@@ -17,7 +17,9 @@ ovn_lib_libovn_la_SOURCES = \
 	ovn/lib/ovn-util.c \
 	ovn/lib/ovn-util.h \
 	ovn/lib/logical-fields.c \
-	ovn/lib/logical-fields.h
+	ovn/lib/logical-fields.h \
+	ovn/lib/inc-proc-eng.c \
+	ovn/lib/inc-proc-eng.h
 nodist_ovn_lib_libovn_la_SOURCES = \
 	ovn/lib/ovn-nb-idl.c \
 	ovn/lib/ovn-nb-idl.h \
diff --git a/ovn/lib/inc-proc-eng.c b/ovn/lib/inc-proc-eng.c
new file mode 100644
index 0000000..c13a065
--- /dev/null
+++ b/ovn/lib/inc-proc-eng.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2018 eBay Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "openvswitch/dynamic-string.h"
+#include "openvswitch/hmap.h"
+#include "openvswitch/vlog.h"
+#include "inc-proc-eng.h"
+
+VLOG_DEFINE_THIS_MODULE(inc_proc_eng);
+
+bool engine_force_recompute = false;
+
+void
+engine_run(struct engine_node *node, uint64_t run_id)
+{
+    if (node->run_id == run_id) {
+        return;
+    }
+    node->run_id = run_id;
+
+    if (node->changed) {
+        node->changed = false;
+    }
+    if (!node->n_inputs) {
+        node->run(node);
+        VLOG_DBG("node: %s, changed: %d", node->name, node->changed);
+        return;
+    }
+
+    size_t i;
+
+    for (i = 0; i < node->n_inputs; i++) {
+        engine_run(node->inputs[i].node, run_id);
+    }
+
+    bool need_compute = false;
+    bool need_recompute = false;
+
+    if (engine_force_recompute) {
+        need_recompute = true;
+    } else {
+        for (i = 0; i < node->n_inputs; i++) {
+            if (node->inputs[i].node->changed) {
+                need_compute = true;
+                if (!node->inputs[i].change_handler) {
+                    need_recompute = true;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (need_recompute) {
+        VLOG_DBG("node: %s, recompute (%s)", node->name,
+                 engine_force_recompute ? "forced" : "triggered");
+        node->run(node);
+    } else if (need_compute) {
+        for (i = 0; i < node->n_inputs; i++) {
+            if (node->inputs[i].node->changed) {
+                VLOG_DBG("node: %s, handle change for input %s",
+                         node->name, node->inputs[i].node->name);
+                if (!node->inputs[i].change_handler(node)) {
+                    VLOG_DBG("node: %s, can't handle change for input %s, "
+                             "fall back to recompute",
+                             node->name, node->inputs[i].node->name);
+                    node->run(node);
+                    break;
+                }
+            }
+        }
+    }
+
+    VLOG_DBG("node: %s, changed: %d", node->name, node->changed);
+
+}
+
diff --git a/ovn/lib/inc-proc-eng.h b/ovn/lib/inc-proc-eng.h
new file mode 100644
index 0000000..99c61a1
--- /dev/null
+++ b/ovn/lib/inc-proc-eng.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018 eBay Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INC_PROC_ENG_H
+#define INC_PROC_ENG_H 1
+
+// TODO: add documentation of incremental processing engine.
+
+#define ENGINE_MAX_INPUT 256
+
+struct engine_node;
+
+struct engine_node_input {
+    struct engine_node *node;
+    /* change_handler handles one input change against "old_data" of all
+     * other inputs, returns:
+     *  - true: if change can be handled
+     *  - false: if change cannot be handled (suggesting full recompute)
+     */
+    bool (*change_handler)(struct engine_node *node);
+};
+
+struct engine_node {
+    uint64_t run_id;
+    char* name;
+    size_t n_inputs;
+    struct engine_node_input inputs[ENGINE_MAX_INPUT];
+    void *data;
+    bool changed;
+    void *context;
+    void (*run)(struct engine_node *node);
+};
+
+void
+engine_run(struct engine_node *node, uint64_t run_id);
+
+static inline struct engine_node *
+engine_get_input(const char *input_name, struct engine_node *node)
+{
+    size_t i;
+    for (i = 0; i < node->n_inputs; i++) {
+        if (!strcmp(node->inputs[i].node->name, input_name)) {
+            return node->inputs[i].node;
+        }
+    }
+    return NULL;
+}
+
+static inline void
+engine_add_input(struct engine_node *node, struct engine_node *input,
+    bool (*change_handler)(struct engine_node *node))
+{
+    node->inputs[node->n_inputs].node = input;
+    node->inputs[node->n_inputs].change_handler = change_handler;
+    node->n_inputs ++;
+}
+
+extern bool engine_force_recompute;
+static inline void
+engine_set_force_recompute(bool val)
+{
+    engine_force_recompute = val;
+}
+
+#define ENGINE_NODE(NAME, NAME_STR) \
+    struct engine_node en_##NAME = { \
+        .name = NAME_STR, \
+        .data = &ed_##NAME, \
+        .context = &ctx, \
+        .run = NAME##_run, \
+    };
+
+#define ENGINE_FUNC_OVSDB(DB_NAME, TBL_NAME, IDL) \
+static void \
+DB_NAME##_##TBL_NAME##_run(struct engine_node *node) \
+{ \
+    static bool first_run = true; \
+    if (first_run) { \
+        first_run = false; \
+        node->changed = true; \
+        return; \
+    } \
+    struct controller_ctx *ctx = (struct controller_ctx *)node->context; \
+    if (DB_NAME##rec_##TBL_NAME##_track_get_first(IDL)) { \
+        node->changed = true; \
+        return; \
+    } \
+    node->changed = false; \
+}
+
+#define ENGINE_FUNC_SB(TBL_NAME) \
+    ENGINE_FUNC_OVSDB(sb, TBL_NAME, ctx->ovnsb_idl)
+
+#define ENGINE_FUNC_OVS(TBL_NAME) \
+    ENGINE_FUNC_OVSDB(ovs, TBL_NAME, ctx->ovs_idl)
+
+#define ENGINE_NODE_SB(TBL_NAME, TBL_NAME_STR) \
+    void *ed_sb_##TBL_NAME; \
+    ENGINE_NODE(sb_##TBL_NAME, TBL_NAME_STR)
+
+#define ENGINE_NODE_OVS(TBL_NAME, TBL_NAME_STR) \
+    void *ed_ovs_##TBL_NAME; \
+    ENGINE_NODE(ovs_##TBL_NAME, TBL_NAME_STR)
+
+#endif /* ovn/lib/inc-proc-eng.h */
-- 
2.1.0



More information about the dev mailing list