From: Numan Siddique <num...@ovn.org>

Signed-off-by: Numan Siddique <num...@ovn.org>
---
 br-controller/automake.mk         |   6 +-
 br-controller/en-bridge-data.c    |  45 +++++
 br-controller/en-bridge-data.h    |  16 ++
 br-controller/en-lflow.c          |  43 +++++
 br-controller/en-lflow.h          |  16 ++
 br-controller/ovn-br-controller.c | 279 +++++++++++++++++++++++++++++-
 lib/inc-proc-eng.h                |  11 ++
 7 files changed, 409 insertions(+), 7 deletions(-)
 create mode 100644 br-controller/en-bridge-data.c
 create mode 100644 br-controller/en-bridge-data.h
 create mode 100644 br-controller/en-lflow.c
 create mode 100644 br-controller/en-lflow.h

diff --git a/br-controller/automake.mk b/br-controller/automake.mk
index 012e9a5ed8..497f440551 100644
--- a/br-controller/automake.mk
+++ b/br-controller/automake.mk
@@ -1,6 +1,10 @@
 bin_PROGRAMS += br-controller/ovn-br-controller
 br_controller_ovn_br_controller_SOURCES = \
-       br-controller/ovn-br-controller.c
+       br-controller/ovn-br-controller.c \
+       br-controller/en-lflow.c \
+       br-controller/en-lflow.h \
+       br-controller/en-bridge-data.c \
+       br-controller/en-bridge-data.h
 
 br_controller_ovn_br_controller_LDADD = lib/libovn.la 
$(OVS_LIBDIR)/libopenvswitch.la
 man_MANS += br-controller/ovn-br-controller.8
diff --git a/br-controller/en-bridge-data.c b/br-controller/en-bridge-data.c
new file mode 100644
index 0000000000..293ae895c0
--- /dev/null
+++ b/br-controller/en-bridge-data.c
@@ -0,0 +1,45 @@
+/*
+ * 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 <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* OVS includes. */
+#include "openvswitch/vlog.h"
+
+/* OVN includes. */
+#include "en-bridge-data.h"
+
+VLOG_DEFINE_THIS_MODULE(en_bridge_data);
+
+void *
+en_bridge_data_init(struct engine_node *node OVS_UNUSED,
+                    struct engine_arg *arg OVS_UNUSED)
+{
+    return NULL;
+}
+
+void
+en_bridge_data_cleanup(void *data OVS_UNUSED)
+{
+}
+
+enum engine_node_state
+en_bridge_data_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED)
+{
+    return EN_UNCHANGED;
+}
diff --git a/br-controller/en-bridge-data.h b/br-controller/en-bridge-data.h
new file mode 100644
index 0000000000..4a280b5cd1
--- /dev/null
+++ b/br-controller/en-bridge-data.h
@@ -0,0 +1,16 @@
+#ifndef EN_RUNTIME_DATA_H
+#define EN_RUNTIME_DATA_H 1
+
+#include <config.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "lib/inc-proc-eng.h"
+
+enum engine_node_state en_bridge_data_run(struct engine_node *, void *data);
+void *en_bridge_data_init(struct engine_node *node, struct engine_arg *arg);
+void en_bridge_data_cleanup(void *data);
+
+#endif /* EN_RUNTIME_DATA_H */
diff --git a/br-controller/en-lflow.c b/br-controller/en-lflow.c
new file mode 100644
index 0000000000..b1a6efbf5f
--- /dev/null
+++ b/br-controller/en-lflow.c
@@ -0,0 +1,43 @@
+/*
+ * 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 <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* OVS includes. */
+#include "openvswitch/vlog.h"
+
+/* OVN includes. */
+#include "en-lflow.h"
+
+VLOG_DEFINE_THIS_MODULE(en_lflow);
+
+void *en_lflow_output_init(struct engine_node *node OVS_UNUSED,
+                          struct engine_arg *arg OVS_UNUSED)
+{
+    return NULL;
+}
+
+void en_lflow_output_cleanup(void *data_ OVS_UNUSED)
+{
+}
+
+enum engine_node_state
+en_lflow_output_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED)
+{
+    return EN_UNCHANGED;
+}
diff --git a/br-controller/en-lflow.h b/br-controller/en-lflow.h
new file mode 100644
index 0000000000..c3889cbdc9
--- /dev/null
+++ b/br-controller/en-lflow.h
@@ -0,0 +1,16 @@
+#ifndef EN_LFLOW_H
+#define EN_LFLOW_H 1
+
+#include <config.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "lib/inc-proc-eng.h"
+
+enum engine_node_state en_lflow_output_run(struct engine_node *, void *data);
+void *en_lflow_output_init(struct engine_node *node, struct engine_arg *arg);
+void en_lflow_output_cleanup(void *data);
+
+#endif /* EN_LFLOW_H */
diff --git a/br-controller/ovn-br-controller.c 
b/br-controller/ovn-br-controller.c
index 0fef0e5fee..27c5e28d0c 100644
--- a/br-controller/ovn-br-controller.c
+++ b/br-controller/ovn-br-controller.c
@@ -22,25 +22,30 @@
 #include <string.h>
 
 /* OVS includes. */
-#include "openvswitch/vlog.h"
 #include "lib/command-line.h"
 #include "lib/daemon.h"
 #include "lib/dirs.h"
 #include "lib/fatal-signal.h"
 #include "lib/stream.h"
 #include "lib/stream-ssl.h"
+#include "lib/vswitch-idl.h"
 #include "lib/unixctl.h"
+#include "openvswitch/poll-loop.h"
+#include "openvswitch/vlog.h"
+
 
 /* OVN includes. */
+#include "en-bridge-data.h"
+#include "en-lflow.h"
 #include "lib/ovn-br-idl.h"
+#include "lib/inc-proc-eng.h"
 #include "lib/ovn-util.h"
 
 VLOG_DEFINE_THIS_MODULE(main);
 
-static void parse_options(int argc, char *argv[]);
+static char *parse_options(int argc, char *argv[]);
 OVS_NO_RETURN static void usage(void);
 
-
 /* SSL/TLS options. */
 static const char *ssl_private_key_file;
 static const char *ssl_certificate_file;
@@ -49,20 +54,225 @@ static const char *ssl_ca_cert_file;
 /* --unixctl-path: Path to use for unixctl server socket. */
 static char *unixctl_path;
 
+#define BRCTL_NODES \
+    BRCTL_NODE(br_global) \
+    BRCTL_NODE(bridge) \
+    BRCTL_NODE(logical_flow)
+
+enum brctl_engine_node {
+#define BRCTL_NODE(NAME) BRCTL_##NAME,
+    BRCTL_NODES
+#undef BRCTL_NODE
+};
+
+#define BRCTL_NODE(NAME) ENGINE_FUNC_BR(NAME);
+    BRCTL_NODES
+#undef BRCTL_NODE
+
+#define OVS_NODES \
+    OVS_NODE(open_vswitch) \
+    OVS_NODE(bridge) \
+    OVS_NODE(port) \
+    OVS_NODE(interface)
+
+enum ovs_engine_node {
+#define OVS_NODE(NAME) OVS_##NAME,
+    OVS_NODES
+#undef OVS_NODE
+};
+
+#define OVS_NODE(NAME) ENGINE_FUNC_OVS(NAME);
+    OVS_NODES
+#undef OVS_NODE
+
+/* Engine static functions. */
+static void *
+en_br_controller_output_init(struct engine_node *node OVS_UNUSED,
+                             struct engine_arg *arg OVS_UNUSED)
+{
+    return NULL;
+}
+
+static void
+en_br_controller_output_cleanup(void *data OVS_UNUSED)
+{
+
+}
+
+static enum engine_node_state
+en_br_controller_output_run(struct engine_node *node OVS_UNUSED,
+                            void *data OVS_UNUSED)
+{
+    return EN_UPDATED;
+}
+
+/* Static function declarations. */
+static void ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl);
+static void update_br_db(struct ovsdb_idl *ovs_idl,
+                         struct ovsdb_idl *ovn_br_idl);
+
 int
 main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
+    struct unixctl_server *unixctl;
+    struct ovn_exit_args exit_args = {0};
+    int retval;
+
     ovs_cmdl_proctitle_init(argc, argv);
     ovn_set_program_name(argv[0]);
     service_start(&argc, &argv);
-    parse_options(argc, argv);
+    char *ovs_remote = parse_options(argc, argv);
     fatal_ignore_sigpipe();
 
-    return 0;
+    daemonize_start(true, false);
+
+    char *abs_unixctl_path = get_abs_unix_ctl_path(unixctl_path);
+    retval = unixctl_server_create(abs_unixctl_path, &unixctl);
+    free(abs_unixctl_path);
+    if (retval) {
+        exit(EXIT_FAILURE);
+    }
+    unixctl_command_register("exit", "", 0, 1, ovn_exit_command_callback,
+                             &exit_args);
+
+    daemonize_complete();
+
+    /* Connect to OVS OVSDB instance. */
+    struct ovsdb_idl_loop ovs_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
+        ovsdb_idl_create(ovs_remote, &ovsrec_idl_class, false, true));
+    ctrl_register_ovs_idl(ovs_idl_loop.idl);
+
+    ovsdb_idl_get_initial_snapshot(ovs_idl_loop.idl);
+
+    /* Configure OVN bridge database. */
+    struct ovsdb_idl_loop ovnbr_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(
+        ovsdb_idl_create_unconnected(&ovnbrrec_idl_class, true));
+    ovsdb_idl_set_leader_only(ovnbr_idl_loop.idl, false);
+
+    ovsdb_idl_track_add_all(ovnbr_idl_loop.idl);
+
+    unixctl_command_register("connection-status", "", 0, 0,
+                             ovn_conn_show, ovnbr_idl_loop.idl);
+
+    /* We don't want to monitor Connection table at all. So omit all the
+     * columns. */
+    ovsdb_idl_omit(ovnbr_idl_loop.idl, &ovnbrrec_connection_col_external_ids);
+    ovsdb_idl_omit(ovnbr_idl_loop.idl,
+                   &ovnbrrec_connection_col_inactivity_probe);
+    ovsdb_idl_omit(ovnbr_idl_loop.idl, &ovnbrrec_connection_col_is_connected);
+    ovsdb_idl_omit(ovnbr_idl_loop.idl, &ovnbrrec_connection_col_max_backoff);
+    ovsdb_idl_omit(ovnbr_idl_loop.idl, &ovnbrrec_connection_col_other_config);
+    ovsdb_idl_omit(ovnbr_idl_loop.idl, &ovnbrrec_connection_col_status);
+    ovsdb_idl_omit(ovnbr_idl_loop.idl, &ovnbrrec_connection_col_target);
+
+    /* Define inc-proc-engine nodes. */
+    ENGINE_NODE(bridge_data);
+    ENGINE_NODE(lflow_output);
+    ENGINE_NODE(br_controller_output);
+
+#define BRCTL_NODE(NAME) ENGINE_NODE_BR(NAME);
+    BRCTL_NODES
+#undef BRCTL_NODE
+
+#define OVS_NODE(NAME) ENGINE_NODE_OVS(NAME);
+    OVS_NODES
+#undef OVS_NODE
+
+    engine_add_input(&en_bridge_data, &en_ovs_open_vswitch, NULL);
+    engine_add_input(&en_bridge_data, &en_ovs_bridge, NULL);
+    engine_add_input(&en_bridge_data, &en_ovs_port, NULL);
+    engine_add_input(&en_bridge_data, &en_ovs_interface, NULL);
+
+    engine_add_input(&en_bridge_data, &en_ovnbr_br_global, NULL);
+    engine_add_input(&en_bridge_data, &en_ovnbr_bridge, NULL);
+
+    engine_add_input(&en_lflow_output, &en_bridge_data, NULL);
+    engine_add_input(&en_lflow_output, &en_ovnbr_logical_flow, NULL);
+    engine_add_input(&en_br_controller_output, &en_lflow_output, NULL);
+
+    struct engine_arg engine_arg = {
+        .ovs_idl = ovs_idl_loop.idl,
+        .ovnbr_idl = ovnbr_idl_loop.idl,
+    };
+    engine_init(&en_br_controller_output, &engine_arg);
+
+    unsigned int ovs_cond_seqno = UINT_MAX;
+    unsigned int ovnbr_cond_seqno = UINT_MAX;
+
+    /* Main loop. */
+    while (!exit_args.exiting) {
+        engine_init_run();
+
+        struct ovsdb_idl_txn *ovs_idl_txn = ovsdb_idl_loop_run(&ovs_idl_loop);
+        unsigned int new_ovs_cond_seqno
+            = ovsdb_idl_get_condition_seqno(ovs_idl_loop.idl);
+        if (new_ovs_cond_seqno != ovs_cond_seqno) {
+            if (!new_ovs_cond_seqno) {
+                VLOG_INFO("OVS IDL reconnected, force recompute.");
+                engine_set_force_recompute();
+            }
+            ovs_cond_seqno = new_ovs_cond_seqno;
+        }
+
+        update_br_db(ovs_idl_loop.idl, ovnbr_idl_loop.idl);
+        struct ovsdb_idl_txn *ovnbr_idl_txn
+            = ovsdb_idl_loop_run(&ovnbr_idl_loop);
+        unsigned int new_ovnbr_cond_seqno
+            = ovsdb_idl_get_condition_seqno(ovnbr_idl_loop.idl);
+        if (new_ovnbr_cond_seqno != ovnbr_cond_seqno) {
+            if (!new_ovnbr_cond_seqno) {
+                VLOG_INFO("OVNBR IDL reconnected, force recompute.");
+                engine_set_force_recompute();
+            }
+            ovnbr_cond_seqno = new_ovnbr_cond_seqno;
+        }
+
+        struct engine_context eng_ctx = {
+            .ovs_idl_txn = ovs_idl_txn,
+            .ovnbr_idl_txn = ovnbr_idl_txn,
+        };
+
+        engine_set_context(&eng_ctx);
+
+        const struct ovsrec_open_vswitch_table *ovs_table =
+            ovsrec_open_vswitch_table_get(ovs_idl_loop.idl);
+        const struct ovsrec_open_vswitch *cfg =
+            ovsrec_open_vswitch_table_first(ovs_table);
+
+        if (ovsdb_idl_has_ever_connected(ovnbr_idl_loop.idl) && cfg) {
+            engine_run(true);
+        }
+
+        unixctl_server_run(unixctl);
+
+        unixctl_server_wait(unixctl);
+        if (exit_args.exiting) {
+            poll_immediate_wake();
+        }
+
+        ovsdb_idl_loop_commit_and_wait(&ovs_idl_loop);
+        ovsdb_idl_loop_commit_and_wait(&ovnbr_idl_loop);
+        ovsdb_idl_track_clear(ovnbr_idl_loop.idl);
+        ovsdb_idl_track_clear(ovs_idl_loop.idl);
+
+        poll_block();
+        if (should_service_stop()) {
+            exit_args.exiting = true;
+        }
+    }
+
+    engine_set_context(NULL);
+    engine_cleanup();
+
+    free(ovs_remote);
+    ovn_exit_args_finish(&exit_args);
+    unixctl_server_destroy(unixctl);
+    service_stop();
+    exit(0);
 }
 
 /* static functions. */
-static void
+static char *
 parse_options(int argc, char *argv[])
 {
     enum {
@@ -153,6 +363,17 @@ parse_options(int argc, char *argv[])
 
     argc -= optind;
     argv += optind;
+
+    char *ovs_remote = NULL;
+    if (argc == 0) {
+        ovs_remote = xasprintf("unix:%s/db.sock", ovs_rundir());
+    } else if (argc == 1) {
+        ovs_remote = xstrdup(argv[0]);
+    } else {
+        VLOG_FATAL("exactly zero or one non-option argument required; "
+                   "use --help for usage");
+    }
+    return ovs_remote;
 }
 
 static void
@@ -173,3 +394,49 @@ usage(void)
            "  -V, --version           display version information\n");
     exit(EXIT_SUCCESS);
 }
+
+static void
+ctrl_register_ovs_idl(struct ovsdb_idl *ovs_idl)
+{
+    /* We do not monitor all tables by default, so modules must register
+     * their interest explicitly.
+     * When the same column is monitored in different modes by different
+     * modules, there is a chance that "track" flag added by
+     * ovsdb_idl_track_add_column by one module being overwritten by a
+     * following ovsdb_idl_add_column by another module. Before this is fixed
+     * in OVSDB IDL, we need to be careful about the order so that the "track"
+     * calls are after the "non-track" calls. */
+    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_open_vswitch);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_other_config);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_bridges);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_datapaths);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_open_vswitch_col_external_ids);
+
+    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_bridge);
+    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_bridge_col_name);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_ports);
+    ovsdb_idl_add_column(ovs_idl, &ovsrec_bridge_col_external_ids);
+
+    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_port);
+    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_name);
+    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_port_col_interfaces);
+
+    ovsdb_idl_add_table(ovs_idl, &ovsrec_table_interface);
+    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_name);
+    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_ofport);
+    ovsdb_idl_track_add_column(ovs_idl, &ovsrec_interface_col_external_ids);
+}
+
+/* Retrieves the pointer to the OVN Bridge Controller database from 'ovs_idl'
+ * and updates 'brdb_idl' with that pointer. */
+static void
+update_br_db(struct ovsdb_idl *ovs_idl, struct ovsdb_idl *ovnbr_idl)
+{
+    const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(ovs_idl);
+    if (!cfg) {
+        return;
+    }
+
+    const char *remote = smap_get(&cfg->external_ids, "ovn-br-remote");
+    ovsdb_idl_set_remote(ovnbr_idl, remote, true);
+}
diff --git a/lib/inc-proc-eng.h b/lib/inc-proc-eng.h
index d9174effa7..5a486f86f8 100644
--- a/lib/inc-proc-eng.h
+++ b/lib/inc-proc-eng.h
@@ -157,6 +157,7 @@ struct engine_context {
     struct ovsdb_idl_txn *ovs_idl_txn;
     struct ovsdb_idl_txn *ovnsb_idl_txn;
     struct ovsdb_idl_txn *ovnnb_idl_txn;
+    struct ovsdb_idl_txn *ovnbr_idl_txn;
 
     void *client_ctx;
 };
@@ -165,6 +166,7 @@ struct engine_context {
 struct engine_arg {
     struct ovsdb_idl *sb_idl;
     struct ovsdb_idl *nb_idl;
+    struct ovsdb_idl *ovnbr_idl;
     struct ovsdb_idl *ovs_idl;
 };
 
@@ -521,6 +523,11 @@ en_##DB_NAME##_##TBL_NAME##_compute_failure_info(struct 
engine_node *node)  \
 #define ENGINE_FUNC_NB(TBL_NAME) \
     ENGINE_FUNC_OVSDB(nb, TBL_NAME)
 
+/* Macro to define member functions of an engine node which represents
+ * a table of OVN BR DB */
+#define ENGINE_FUNC_BR(TBL_NAME) \
+    ENGINE_FUNC_OVSDB(ovnbr, TBL_NAME)
+
 /* Macro to define member functions of an engine node which represents
  * a table of open_vswitch DB */
 #define ENGINE_FUNC_OVS(TBL_NAME) \
@@ -540,6 +547,10 @@ en_##DB_NAME##_##TBL_NAME##_compute_failure_info(struct 
engine_node *node)  \
 #define ENGINE_NODE_NB(TBL_NAME) \
     ENGINE_NODE_OVSDB(nb, "NB", TBL_NAME, #TBL_NAME);
 
+/* Macro to define an engine node which represents a table of OVN BR DB */
+#define ENGINE_NODE_BR(TBL_NAME) \
+    ENGINE_NODE_OVSDB(ovnbr, "BR", TBL_NAME, #TBL_NAME);
+
 /* Macro to define an engine node which represents a table of open_vswitch
  * DB */
 #define ENGINE_NODE_OVS(TBL_NAME) \
-- 
2.50.1

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

Reply via email to