@@ -4,6 +4,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \
ic/ovn-ic.h \
ic/en-ic.c \
ic/en-ic.h \
+ ic/en-gateway.c \
+ ic/en-gateway.h \
ic/en-enum-datapaths.c \
ic/en-enum-datapaths.h \
ic/en-port-binding.c \
new file mode 100644
@@ -0,0 +1,268 @@
+/*
+ * 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 "ovn-ic.h"
+#include "en-gateway.h"
+#include "inc-proc-ic.h"
+#include "lib/inc-proc-eng.h"
+#include "lib/ovn-sb-idl.h"
+#include "lib/ovn-ic-sb-idl.h"
+#include "lib/ovn-util.h"
+#include "lib/stopwatch-names.h"
+#include "coverage.h"
+#include "stopwatch.h"
+#include "stopwatch-names.h"
+
+VLOG_DEFINE_THIS_MODULE(gateway);
+COVERAGE_DEFINE(gateway_run);
+
+static void
+gateway_run(const struct engine_context *eng_ctx,
+ struct gateway_input *gateway_input,
+ struct ed_type_gateway *gateway_data,
+ const struct icsbrec_gateway_table *icsb_gateway_table,
+ const struct sbrec_chassis_table *sb_chassis_table);
+static void gateway_init(struct ed_type_gateway *data);
+static void gateway_destroy(struct ed_type_gateway *data);
+static void gateway_clear(struct ed_type_gateway *data);
+static void
+sync_sb_gw_to_isb(const struct engine_context *ctx,
+ const struct sbrec_chassis *chassis,
+ const struct icsbrec_gateway *gw);
+static void
+sync_isb_gw_to_sb(const struct engine_context *ctx,
+ const struct icsbrec_gateway *gw,
+ const struct sbrec_chassis *chassis);
+static bool
+is_gateway_data_changed(const struct icsbrec_gateway *gw,
+ const struct sbrec_chassis *chassis);
+
+enum engine_node_state
+en_gateway_run(struct engine_node *node, void *data)
+{
+ const struct engine_context *eng_ctx = engine_get_context();
+ struct ed_type_gateway *gateway_data = data;
+ struct gateway_input gateway_input;
+
+ gateway_clear(gateway_data);
+
+ const struct icsbrec_gateway_table *icsb_gateway_table =
+ EN_OVSDB_GET(engine_get_input("ICSB_gateway", node));
+ const struct sbrec_chassis_table *sb_chassis_table =
+ EN_OVSDB_GET(engine_get_input("SB_chassis", node));
+
+ gateway_input.runned_az = eng_ctx->client_ctx;
+
+ COVERAGE_INC(gateway_run);
+ stopwatch_start(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, time_usec());
+ gateway_run(eng_ctx, &gateway_input, gateway_data, icsb_gateway_table,
+ sb_chassis_table);
+ stopwatch_stop(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, time_usec());
+
+ return EN_UPDATED;
+}
+
+void *
+en_gateway_init(struct engine_node *node OVS_UNUSED,
+ struct engine_arg *arg OVS_UNUSED)
+{
+ struct ed_type_gateway *data = xzalloc(sizeof *data);
+ gateway_init(data);
+ return data;
+}
+
+void
+en_gateway_cleanup(void *data)
+{
+ gateway_destroy(data);
+}
+
+static void
+gateway_init(struct ed_type_gateway *data)
+{
+ shash_init(&data->local_gws);
+ shash_init(&data->remote_gws);
+}
+
+static void
+gateway_destroy(struct ed_type_gateway *data)
+{
+ gateway_clear(data);
+
+ shash_destroy(&data->local_gws);
+ shash_destroy(&data->remote_gws);
+}
+
+static void
+gateway_clear(struct ed_type_gateway *data)
+{
+ shash_clear(&data->local_gws);
+ shash_clear(&data->remote_gws);
+}
+
+static void
+gateway_run(const struct engine_context *eng_ctx,
+ struct gateway_input *gw_input,
+ struct ed_type_gateway *gw_data,
+ const struct icsbrec_gateway_table *icsb_gateway_table,
+ const struct sbrec_chassis_table *sb_chassis_table)
+{
+ if (!eng_ctx->ovnisb_idl_txn || !eng_ctx->ovnsb_idl_txn) {
+ return;
+ }
+
+ const struct icsbrec_gateway *gw;
+ ICSBREC_GATEWAY_TABLE_FOR_EACH (gw, icsb_gateway_table) {
+ if (gw->availability_zone == gw_input->runned_az) {
+ shash_add(&gw_data->local_gws, gw->name, gw);
+ } else {
+ shash_add(&gw_data->remote_gws, gw->name, gw);
+ }
+ }
+
+ const struct sbrec_chassis *chassis;
+ SBREC_CHASSIS_TABLE_FOR_EACH (chassis, sb_chassis_table) {
+ if (smap_get_bool(&chassis->other_config, "is-interconn", false)) {
+ gw = shash_find_and_delete(&gw_data->local_gws, chassis->name);
+ if (!gw) {
+ gw = icsbrec_gateway_insert(eng_ctx->ovnisb_idl_txn);
+ icsbrec_gateway_set_availability_zone(gw, gw_input->runned_az);
+ icsbrec_gateway_set_name(gw, chassis->name);
+ sync_sb_gw_to_isb(eng_ctx, chassis, gw);
+ } else if (is_gateway_data_changed(gw, chassis)) {
+ sync_sb_gw_to_isb(eng_ctx, chassis, gw);
+ }
+ } else if (smap_get_bool(&chassis->other_config, "is-remote", false)) {
+ gw = shash_find_and_delete(&gw_data->remote_gws, chassis->name);
+ if (!gw) {
+ sbrec_chassis_delete(chassis);
+ } else if (is_gateway_data_changed(gw, chassis)) {
+ sync_isb_gw_to_sb(eng_ctx, gw, chassis);
+ }
+ }
+ }
+
+ /* Delete extra gateways from ISB for the local AZ */
+ struct shash_node *node;
+ SHASH_FOR_EACH (node, &gw_data->local_gws) {
+ icsbrec_gateway_delete(node->data);
+ }
+
+ /* Create SB chassis for remote gateways in ISB */
+ SHASH_FOR_EACH (node, &gw_data->remote_gws) {
+ gw = node->data;
+ chassis = sbrec_chassis_insert(eng_ctx->ovnsb_idl_txn);
+ sbrec_chassis_set_name(chassis, gw->name);
+ sync_isb_gw_to_sb(eng_ctx, gw, chassis);
+ }
+}
+
+/* Returns true if any information in gw and chassis is different. */
+static bool
+is_gateway_data_changed(const struct icsbrec_gateway *gw,
+ const struct sbrec_chassis *chassis)
+{
+ if (strcmp(gw->hostname, chassis->hostname)) {
+ return true;
+ }
+
+ if (gw->n_encaps != chassis->n_encaps) {
+ return true;
+ }
+
+ for (int g = 0; g < gw->n_encaps; g++) {
+
+ bool found = false;
+ const struct icsbrec_encap *gw_encap = gw->encaps[g];
+ for (int s = 0; s < chassis->n_encaps; s++) {
+ const struct sbrec_encap *chassis_encap = chassis->encaps[s];
+ if (!strcmp(gw_encap->type, chassis_encap->type) &&
+ !strcmp(gw_encap->ip, chassis_encap->ip)) {
+ found = true;
+ if (!smap_equal(&gw_encap->options, &chassis_encap->options)) {
+ return true;
+ }
+ break;
+ }
+ }
+ if (!found) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void
+sync_isb_gw_to_sb(const struct engine_context *ctx,
+ const struct icsbrec_gateway *gw,
+ const struct sbrec_chassis *chassis)
+{
+ sbrec_chassis_set_hostname(chassis, gw->hostname);
+ sbrec_chassis_update_other_config_setkey(chassis, "is-remote", "true");
+
+ /* Sync encaps used by this gateway. */
+ ovs_assert(gw->n_encaps);
+ struct sbrec_encap *sb_encap;
+ struct sbrec_encap **sb_encaps =
+ xmalloc(gw->n_encaps * sizeof *sb_encaps);
+ for (int i = 0; i < gw->n_encaps; i++) {
+ sb_encap = sbrec_encap_insert(ctx->ovnsb_idl_txn);
+ sbrec_encap_set_chassis_name(sb_encap, gw->name);
+ sbrec_encap_set_ip(sb_encap, gw->encaps[i]->ip);
+ sbrec_encap_set_type(sb_encap, gw->encaps[i]->type);
+ sbrec_encap_set_options(sb_encap, &gw->encaps[i]->options);
+ sb_encaps[i] = sb_encap;
+ }
+ sbrec_chassis_set_encaps(chassis, sb_encaps, gw->n_encaps);
+ free(sb_encaps);
+}
+
+static void
+sync_sb_gw_to_isb(const struct engine_context *ctx,
+ const struct sbrec_chassis *chassis,
+ const struct icsbrec_gateway *gw)
+{
+ icsbrec_gateway_set_hostname(gw, chassis->hostname);
+
+ /* Sync encaps used by this chassis. */
+ ovs_assert(chassis->n_encaps);
+ struct icsbrec_encap *isb_encap;
+ struct icsbrec_encap **isb_encaps =
+ xmalloc(chassis->n_encaps * sizeof *isb_encaps);
+ for (int i = 0; i < chassis->n_encaps; i++) {
+ isb_encap = icsbrec_encap_insert(ctx->ovnisb_idl_txn);
+ icsbrec_encap_set_gateway_name(isb_encap,
+ chassis->name);
+ icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);
+ icsbrec_encap_set_type(isb_encap,
+ chassis->encaps[i]->type);
+ icsbrec_encap_set_options(isb_encap,
+ &chassis->encaps[i]->options);
+ isb_encaps[i] = isb_encap;
+ }
+ icsbrec_gateway_set_encaps(gw, isb_encaps,
+ chassis->n_encaps);
+ free(isb_encaps);
+}
new file mode 100644
@@ -0,0 +1,28 @@
+#ifndef EN_IC_GATEWAY_H
+#define EN_IC_GATEWAY_H 1
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* OVN includes. */
+#include "lib/inc-proc-eng.h"
+
+struct ed_type_gateway {
+ struct shash local_gws;
+ struct shash remote_gws;
+};
+
+struct gateway_input {
+ /* Indexes */
+ const struct icsbrec_availability_zone *runned_az;
+};
+
+void *en_gateway_init(struct engine_node *, struct engine_arg *);
+enum engine_node_state en_gateway_run(struct engine_node *, void *data);
+void en_gateway_cleanup(void *data);
+
+#endif
@@ -64,8 +64,6 @@ ic_get_input_data(struct engine_node *node,
EN_OVSDB_GET(engine_get_input("ICSB_availability_zone", node));
input_data->icsbrec_encap_table =
EN_OVSDB_GET(engine_get_input("ICSB_encap", node));
- input_data->icsbrec_gateway_table =
- EN_OVSDB_GET(engine_get_input("ICSB_gateway", node));
input_data->icsbrec_datapath_binding_table =
EN_OVSDB_GET(engine_get_input("ICSB_datapath_binding", node));
@@ -27,6 +27,7 @@
#include "openvswitch/vlog.h"
#include "inc-proc-ic.h"
#include "en-ic.h"
+#include "en-gateway.h"
#include "en-enum-datapaths.h"
#include "en-port-binding.h"
#include "en-route.h"
@@ -161,6 +162,7 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic);
/* Define engine nodes for other nodes. They should be defined as static to
* avoid sparse errors. */
static ENGINE_NODE(ic, SB_WRITE);
+static ENGINE_NODE(gateway, SB_WRITE);
static ENGINE_NODE(enum_datapaths);
static ENGINE_NODE(port_binding, SB_WRITE);
static ENGINE_NODE(route);
@@ -172,6 +174,9 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
{
/* Define relationships between nodes where first argument is dependent
* on the second argument */
+ engine_add_input(&en_gateway, &en_icsb_gateway, NULL);
+ engine_add_input(&en_gateway, &en_sb_chassis, NULL);
+
engine_add_input(&en_enum_datapaths, &en_icnb_transit_switch, NULL);
engine_add_input(&en_enum_datapaths, &en_icsb_datapath_binding, NULL);
@@ -191,6 +196,7 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_route, &en_icsb_route, NULL);
engine_add_input(&en_route, &en_nb_logical_router_static_route, NULL);
+ engine_add_input(&en_ic, &en_gateway, NULL);
engine_add_input(&en_ic, &en_enum_datapaths, NULL);
engine_add_input(&en_ic, &en_port_binding, NULL);
engine_add_input(&en_ic, &en_route, NULL);
@@ -219,7 +225,6 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,
engine_add_input(&en_ic, &en_icsb_availability_zone, NULL);
engine_add_input(&en_ic, &en_icsb_encap, NULL);
engine_add_input(&en_ic, &en_icsb_service_monitor, NULL);
- engine_add_input(&en_ic, &en_icsb_gateway, NULL);
engine_add_input(&en_ic, &en_icsb_datapath_binding, NULL);
struct engine_arg engine_arg = {
@@ -429,153 +429,6 @@ tr_run(struct engine_context *ctx,
}
}
-/* Returns true if any information in gw and chassis is different. */
-static bool
-is_gateway_data_changed(const struct icsbrec_gateway *gw,
- const struct sbrec_chassis *chassis)
-{
- if (strcmp(gw->hostname, chassis->hostname)) {
- return true;
- }
-
- if (gw->n_encaps != chassis->n_encaps) {
- return true;
- }
-
- for (int g = 0; g < gw->n_encaps; g++) {
-
- bool found = false;
- const struct icsbrec_encap *gw_encap = gw->encaps[g];
- for (int s = 0; s < chassis->n_encaps; s++) {
- const struct sbrec_encap *chassis_encap = chassis->encaps[s];
- if (!strcmp(gw_encap->type, chassis_encap->type) &&
- !strcmp(gw_encap->ip, chassis_encap->ip)) {
- found = true;
- if (!smap_equal(&gw_encap->options, &chassis_encap->options)) {
- return true;
- }
- break;
- }
- }
- if (!found) {
- return true;
- }
- }
-
- return false;
-}
-
-static void
-sync_isb_gw_to_sb(struct engine_context *ctx,
- const struct icsbrec_gateway *gw,
- const struct sbrec_chassis *chassis)
-{
- sbrec_chassis_set_hostname(chassis, gw->hostname);
- sbrec_chassis_update_other_config_setkey(chassis, "is-remote", "true");
-
- /* Sync encaps used by this gateway. */
- ovs_assert(gw->n_encaps);
- struct sbrec_encap *sb_encap;
- struct sbrec_encap **sb_encaps =
- xmalloc(gw->n_encaps * sizeof *sb_encaps);
- for (int i = 0; i < gw->n_encaps; i++) {
- sb_encap = sbrec_encap_insert(ctx->ovnsb_idl_txn);
- sbrec_encap_set_chassis_name(sb_encap, gw->name);
- sbrec_encap_set_ip(sb_encap, gw->encaps[i]->ip);
- sbrec_encap_set_type(sb_encap, gw->encaps[i]->type);
- sbrec_encap_set_options(sb_encap, &gw->encaps[i]->options);
- sb_encaps[i] = sb_encap;
- }
- sbrec_chassis_set_encaps(chassis, sb_encaps, gw->n_encaps);
- free(sb_encaps);
-}
-
-static void
-sync_sb_gw_to_isb(struct engine_context *ctx,
- const struct sbrec_chassis *chassis,
- const struct icsbrec_gateway *gw)
-{
- icsbrec_gateway_set_hostname(gw, chassis->hostname);
-
- /* Sync encaps used by this chassis. */
- ovs_assert(chassis->n_encaps);
- struct icsbrec_encap *isb_encap;
- struct icsbrec_encap **isb_encaps =
- xmalloc(chassis->n_encaps * sizeof *isb_encaps);
- for (int i = 0; i < chassis->n_encaps; i++) {
- isb_encap = icsbrec_encap_insert(ctx->ovnisb_idl_txn);
- icsbrec_encap_set_gateway_name(isb_encap,
- chassis->name);
- icsbrec_encap_set_ip(isb_encap, chassis->encaps[i]->ip);
- icsbrec_encap_set_type(isb_encap,
- chassis->encaps[i]->type);
- icsbrec_encap_set_options(isb_encap,
- &chassis->encaps[i]->options);
- isb_encaps[i] = isb_encap;
- }
- icsbrec_gateway_set_encaps(gw, isb_encaps,
- chassis->n_encaps);
- free(isb_encaps);
-}
-
-static void
-gateway_run(struct engine_context *ctx,
- struct ic_input *ic)
-{
- if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) {
- return;
- }
-
- struct shash local_gws = SHASH_INITIALIZER(&local_gws);
- struct shash remote_gws = SHASH_INITIALIZER(&remote_gws);
- const struct icsbrec_gateway *gw;
- ICSBREC_GATEWAY_TABLE_FOR_EACH (gw, ic->icsbrec_gateway_table) {
- if (gw->availability_zone == ic->runned_az) {
- shash_add(&local_gws, gw->name, gw);
- } else {
- shash_add(&remote_gws, gw->name, gw);
- }
- }
-
- const struct sbrec_chassis *chassis;
- SBREC_CHASSIS_TABLE_FOR_EACH (chassis, ic->sbrec_chassis_table) {
- if (smap_get_bool(&chassis->other_config, "is-interconn", false)) {
- gw = shash_find_and_delete(&local_gws, chassis->name);
- if (!gw) {
- gw = icsbrec_gateway_insert(ctx->ovnisb_idl_txn);
- icsbrec_gateway_set_availability_zone(gw, ic->runned_az);
- icsbrec_gateway_set_name(gw, chassis->name);
- sync_sb_gw_to_isb(ctx, chassis, gw);
- } else if (is_gateway_data_changed(gw, chassis)) {
- sync_sb_gw_to_isb(ctx, chassis, gw);
- }
- } else if (smap_get_bool(&chassis->other_config, "is-remote", false)) {
- gw = shash_find_and_delete(&remote_gws, chassis->name);
- if (!gw) {
- sbrec_chassis_delete(chassis);
- } else if (is_gateway_data_changed(gw, chassis)) {
- sync_isb_gw_to_sb(ctx, gw, chassis);
- }
- }
- }
-
- /* Delete extra gateways from ISB for the local AZ */
- struct shash_node *node;
- SHASH_FOR_EACH (node, &local_gws) {
- icsbrec_gateway_delete(node->data);
- }
- shash_destroy(&local_gws);
-
- /* Create SB chassis for remote gateways in ISB */
- SHASH_FOR_EACH (node, &remote_gws) {
- gw = node->data;
- chassis = sbrec_chassis_insert(ctx->ovnsb_idl_txn);
- sbrec_chassis_set_name(chassis, gw->name);
- sync_isb_gw_to_sb(ctx, gw, chassis);
- }
- shash_destroy(&remote_gws);
-}
-
const struct nbrec_logical_router_port *
get_lrp_by_lrp_name(struct ovsdb_idl_index *nbrec_lrp_by_name,
const char *lrp_name)
@@ -1192,7 +1045,6 @@ ovn_db_run(struct ic_input *input_data,
struct ic_data *ic_data,
struct engine_context *eng_ctx)
{
- gateway_run(eng_ctx, input_data);
ts_run(eng_ctx, input_data, ic_data->dp_tnlids, ic_data->isb_ts_dps);
tr_run(eng_ctx, input_data, ic_data->dp_tnlids, ic_data->isb_tr_dps);
sync_service_monitor(eng_ctx, input_data);
@@ -1601,6 +1453,7 @@ main(int argc, char *argv[])
stopwatch_create(OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME, SW_MS);
stopwatch_create(OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME, SW_MS);
stopwatch_create(OVN_IC_ROUTE_RUN_STOPWATCH_NAME, SW_MS);
+ stopwatch_create(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, SW_MS);
/* Initialize incremental processing engine for ovn-northd */
inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop,
@@ -34,7 +34,6 @@ struct ic_input {
/* InterconnectSouthbound table references */
const struct icsbrec_encap_table *icsbrec_encap_table;
- const struct icsbrec_gateway_table *icsbrec_gateway_table;
const struct icsbrec_ic_sb_global_table *icsbrec_ic_sb_global_table;
const struct icsbrec_datapath_binding_table
*icsbrec_datapath_binding_table;
@@ -42,6 +42,7 @@
#define OVN_IC_LOOP_STOPWATCH_NAME "ovn-ic-loop"
#define IC_OVN_DB_RUN_STOPWATCH_NAME "ovn_db_run"
+#define OVN_IC_GATEWAY_RUN_STOPWATCH_NAME "gateway_run"
#define OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME "enum_datapaths_run"
#define OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME "port_binding_run"
#define OVN_IC_ROUTE_RUN_STOPWATCH_NAME "route_run"
This new engine now maintains the gateway related data for ovn-ic daemon which was earlier maintained by the ic engine node invoked the gateway_run() function. The inputs to this engine node are: en_icsb_gateway; en_sb_chassis; In order to achieve this, we refactor in the following way: * Introduce gateway_init() which initializes this data. * Introduce gateway_destroy() which clears this data for a new iteration. * Introduce gateway_run() which invokes the full recompute of the engine. This engine node becomes an input to 'ic' node. Signed-off-by: Paulo Guilherme Silva <guilherme.paulo@luizalabs.com> --- ic/automake.mk | 2 + ic/en-gateway.c | 268 ++++++++++++++++++++++++++++++++++++++++++ ic/en-gateway.h | 28 +++++ ic/en-ic.c | 2 - ic/inc-proc-ic.c | 7 +- ic/ovn-ic.c | 149 +---------------------- ic/ovn-ic.h | 1 - lib/stopwatch-names.h | 1 + 8 files changed, 306 insertions(+), 152 deletions(-) create mode 100644 ic/en-gateway.c create mode 100644 ic/en-gateway.h