This new engine now maintains the port-binding related data for ovn-ic daemon which was earlier maintained by the ic engine node invoked the port_binding_run() function. The inputs to this engine node are: en_icnb_transit_switch; en_icnb_transit_router; en_icsb_port_binding; en_nb_logical_switch; en_sb_port_binding; en_nb_logical_router; en_sb_chassis; In order to achieve this, we refactor in the following way: * Introduce port_binding_init() which initializes this data. * Introduce port_binding_destroy() which clears this data for a new iteration. * Introduce port_binding_run() which invokes the full recompute of the engine.
This engine node becomes an input to 'ic' node. Signed-off-by: Paulo Guilherme Silva <[email protected]> --- ic/automake.mk | 2 + ic/en-ic.c | 8 - ic/en-port-binding.c | 853 ++++++++++++++++++++++++++++++++++++++++++ ic/en-port-binding.h | 36 ++ ic/inc-proc-ic.c | 13 +- ic/ovn-ic.c | 701 ++-------------------------------- ic/ovn-ic.h | 25 +- lib/stopwatch-names.h | 1 + 8 files changed, 956 insertions(+), 683 deletions(-) create mode 100644 ic/en-port-binding.c create mode 100644 ic/en-port-binding.h diff --git a/ic/automake.mk b/ic/automake.mk index 2766483b7..91783df0f 100644 --- a/ic/automake.mk +++ b/ic/automake.mk @@ -6,6 +6,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \ ic/en-ic.h \ ic/en-enum-datapaths.c \ ic/en-enum-datapaths.h \ + ic/en-port-binding.c \ + ic/en-port-binding.h \ ic/inc-proc-ic.c \ ic/inc-proc-ic.h ic_ovn_ic_LDADD = \ diff --git a/ic/en-ic.c b/ic/en-ic.c index 16b0e12bd..e7c7ab71b 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -116,14 +116,6 @@ ic_get_input_data(struct engine_node *node, engine_ovsdb_node_get_index( engine_get_input("ICSB_port_binding", node), "icsbrec_port_binding_by_az"); - input_data->icsbrec_port_binding_by_ts = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_port_binding", node), - "icsbrec_port_binding_by_ts"); - input_data->icsbrec_port_binding_by_ts_az = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_port_binding", node), - "icsbrec_port_binding_by_ts_az"); input_data->icsbrec_route_by_az = engine_ovsdb_node_get_index( engine_get_input("ICSB_route", node), diff --git a/ic/en-port-binding.c b/ic/en-port-binding.c new file mode 100644 index 000000000..ee9df2830 --- /dev/null +++ b/ic/en-port-binding.c @@ -0,0 +1,853 @@ +/* + * 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-port-binding.h" +#include "inc-proc-ic.h" +#include "lib/inc-proc-eng.h" +#include "lib/ovn-nb-idl.h" +#include "lib/ovn-sb-idl.h" +#include "lib/ovn-ic-nb-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(en_port_binding); +COVERAGE_DEFINE(port_binding_run); + +static void +port_binding_run(const struct engine_context *eng_ctx, + struct pb_input *pb_input, + struct ed_type_port_binding *pb_data, + const struct icnbrec_transit_switch_table *icnb_ts_table, + const struct icnbrec_transit_router_table *icnb_tr_table); +static void port_binding_init(struct ed_type_port_binding *data); +static void port_binding_destroy(struct ed_type_port_binding *data); +static void port_binding_clear(struct ed_type_port_binding *data); +static void port_binding_get_input_data(struct engine_node *node, + struct pb_input *input_data); +static const struct nbrec_logical_router * + find_tr_in_nb(struct pb_input *pb, char *tr_name); +static const struct sbrec_port_binding * + find_peer_port(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb); +static const struct sbrec_port_binding * + find_crp_from_lrp(struct pb_input *pb, + const struct sbrec_port_binding *lrp_pb); +static const struct sbrec_port_binding * + find_crp_for_sb_pb(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb); +static const char * + get_lp_address_for_sb_pb(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb); +static const struct sbrec_chassis * + find_sb_chassis(struct pb_input *pb, const char *name); +static void sync_lsp_tnl_key(const struct nbrec_logical_switch_port *lsp, + int64_t isb_tnl_key); +static inline void + sync_lrp_tnl_key(const struct nbrec_logical_router_port *lrp, + int64_t isb_tnl_key); +static bool + get_router_uuid_by_sb_pb(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb, + struct uuid *router_uuid); +static void + update_isb_pb_external_ids(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb, + const struct icsbrec_port_binding *isb_pb); +static void + sync_local_port(struct pb_input *pb, + const struct icsbrec_port_binding *isb_pb, + const struct sbrec_port_binding *sb_pb, + const struct nbrec_logical_switch_port *lsp); +static void + sync_remote_port(struct pb_input *pb, + const struct icsbrec_port_binding *isb_pb, + const struct nbrec_logical_switch_port *lsp, + const struct sbrec_port_binding *sb_pb); +static void + sync_router_port(const struct icsbrec_port_binding *isb_pb, + const struct icnbrec_transit_router_port *trp, + const struct nbrec_logical_router_port *lrp); +static void + create_nb_lsp(const struct engine_context *ctx, + const struct icsbrec_port_binding *isb_pb, + const struct nbrec_logical_switch *ls); +static uint32_t allocate_port_key(struct hmap *pb_tnlids); +static const struct icsbrec_port_binding * + create_isb_pb(const struct engine_context *ctx, const char *logical_port, + const struct icsbrec_availability_zone *az, + const char *ts_name, const struct uuid *nb_ic_uuid, + const char *type, struct hmap *pb_tnlids); +static bool trp_is_remote(struct pb_input *pb, const char *chassis_name); +static struct nbrec_logical_router_port * + lrp_create(const struct engine_context *ctx, + const struct nbrec_logical_router *lr, + const struct icnbrec_transit_router_port *trp); +static void + sync_ts_isb_pb(struct pb_input *pb, const struct sbrec_port_binding *sb_pb, + const struct icsbrec_port_binding *isb_pb); +static const struct sbrec_port_binding * + find_lsp_in_sb(struct pb_input *pb, + const struct nbrec_logical_switch_port *lsp); + +static void +port_binding_get_input_data(struct engine_node *node, + struct pb_input *input_data) +{ + /* Indexes */ + input_data->icsbrec_port_binding_by_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_port_binding", node), + "icsbrec_port_binding_by_az"); + input_data->icsbrec_port_binding_by_ts = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_port_binding", node), + "icsbrec_port_binding_by_ts"); + input_data->nbrec_ls_by_name = + engine_ovsdb_node_get_index( + engine_get_input("NB_logical_switch", node), + "nbrec_ls_by_name"); + input_data->sbrec_port_binding_by_name = + engine_ovsdb_node_get_index( + engine_get_input("SB_port_binding", node), + "sbrec_port_binding_by_name"); + input_data->nbrec_port_by_name = + engine_ovsdb_node_get_index( + engine_get_input("NB_logical_switch", node), + "nbrec_port_by_name"); + input_data->nbrec_lr_by_name = + engine_ovsdb_node_get_index( + engine_get_input("NB_logical_router", node), + "nbrec_lr_by_name"); + input_data->sbrec_chassis_by_name = + engine_ovsdb_node_get_index( + engine_get_input("SB_chassis", node), + "sbrec_chassis_by_name"); +} + +enum engine_node_state +en_port_binding_run(struct engine_node *node, void *data) +{ + const struct engine_context *eng_ctx = engine_get_context(); + struct ed_type_port_binding *pb_data = data; + struct pb_input pb_input; + + port_binding_clear(pb_data); + + const struct icnbrec_transit_switch_table *icnb_ts_table = + EN_OVSDB_GET(engine_get_input("ICNB_transit_switch", node)); + const struct icnbrec_transit_router_table *icnb_tr_table = + EN_OVSDB_GET(engine_get_input("ICNB_transit_router", node)); + + port_binding_get_input_data(node, &pb_input); + pb_input.runned_az = eng_ctx->client_ctx; + + COVERAGE_INC(port_binding_run); + stopwatch_start(OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME, time_usec()); + port_binding_run(eng_ctx, &pb_input, pb_data, icnb_ts_table, + icnb_tr_table); + stopwatch_stop(OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME, time_usec()); + + return EN_UPDATED; +} + +void * +en_port_binding_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct ed_type_port_binding *data = xzalloc(sizeof *data); + port_binding_init(data); + return data; +} + +void +en_port_binding_cleanup(void *data) +{ + port_binding_destroy(data); +} + +static void +port_binding_init(struct ed_type_port_binding *data) +{ + hmap_init(&data->pb_tnlids); + shash_init(&data->switch_all_local_pbs); + shash_init(&data->router_all_local_pbs); +} + +static void +port_binding_destroy(struct ed_type_port_binding *data) +{ + port_binding_clear(data); + ovn_destroy_tnlids(&data->pb_tnlids); + + shash_destroy(&data->switch_all_local_pbs); + shash_destroy(&data->router_all_local_pbs); +} + +static void +port_binding_clear(struct ed_type_port_binding *data) +{ + ovn_destroy_tnlids(&data->pb_tnlids); + hmap_init(&data->pb_tnlids); + + shash_clear(&data->switch_all_local_pbs); + shash_clear(&data->router_all_local_pbs); +} + +static void +port_binding_run(const struct engine_context *eng_ctx, + struct pb_input *pb_input, + struct ed_type_port_binding *pb_data, + const struct icnbrec_transit_switch_table *icnb_ts_table, + const struct icnbrec_transit_router_table *icnb_tr_table) +{ + if (!eng_ctx->ovnisb_idl_txn || !eng_ctx->ovnnb_idl_txn + || !eng_ctx->ovnsb_idl_txn) { + return; + } + + struct shash_node *node; + const struct icsbrec_port_binding *isb_pb; + const struct icsbrec_port_binding *isb_pb_key = + icsbrec_port_binding_index_init_row( + pb_input->icsbrec_port_binding_by_az); + icsbrec_port_binding_index_set_availability_zone(isb_pb_key, + pb_input->runned_az); + + ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, + pb_input->icsbrec_port_binding_by_az) { + ic_pb_get_type(isb_pb) != IC_ROUTER_PORT + ? shash_add(&pb_data->switch_all_local_pbs, isb_pb->logical_port, + isb_pb) + : shash_add(&pb_data->router_all_local_pbs, isb_pb->logical_port, + isb_pb); + + ovn_add_tnlid(&pb_data->pb_tnlids, isb_pb->tunnel_key); + } + icsbrec_port_binding_index_destroy_row(isb_pb_key); + + const struct sbrec_port_binding *sb_pb; + const struct icnbrec_transit_switch *ts; + ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, icnb_ts_table) { + const struct nbrec_logical_switch *ls = + find_ts_in_nb(pb_input->nbrec_ls_by_name, + ts->name); + if (!ls) { + VLOG_DBG("Transit switch %s not found in NB.", ts->name); + continue; + } + struct shash local_pbs = SHASH_INITIALIZER(&local_pbs); + struct shash remote_pbs = SHASH_INITIALIZER(&remote_pbs); + + isb_pb_key = icsbrec_port_binding_index_init_row( + pb_input->icsbrec_port_binding_by_ts); + icsbrec_port_binding_index_set_transit_switch(isb_pb_key, ts->name); + + ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, + pb_input->icsbrec_port_binding_by_ts) { + if (isb_pb->availability_zone == pb_input->runned_az) { + shash_add(&local_pbs, isb_pb->logical_port, isb_pb); + shash_find_and_delete(&pb_data->switch_all_local_pbs, + isb_pb->logical_port); + } else { + shash_add(&remote_pbs, isb_pb->logical_port, isb_pb); + } + } + icsbrec_port_binding_index_destroy_row(isb_pb_key); + + const struct nbrec_logical_switch_port *lsp; + for (int i = 0; i < ls->n_ports; i++) { + lsp = ls->ports[i]; + + if (!strcmp(lsp->type, "router") + || !strcmp(lsp->type, "switch")) { + /* The port is local. */ + sb_pb = find_lsp_in_sb(pb_input, lsp); + if (!sb_pb) { + continue; + } + isb_pb = shash_find_and_delete(&local_pbs, lsp->name); + if (!isb_pb) { + isb_pb = create_isb_pb( + eng_ctx, sb_pb->logical_port, pb_input->runned_az, + ts->name, &ts->header_.uuid, "transit-switch-port", + &pb_data->pb_tnlids); + sync_ts_isb_pb(pb_input, sb_pb, isb_pb); + } else { + sync_local_port(pb_input, isb_pb, sb_pb, lsp); + } + + if (isb_pb->type) { + icsbrec_port_binding_set_type(isb_pb, + "transit-switch-port"); + } + + if (isb_pb->nb_ic_uuid) { + icsbrec_port_binding_set_nb_ic_uuid(isb_pb, + &ts->header_.uuid, 1); + } + } else if (!strcmp(lsp->type, "remote")) { + /* The port is remote. */ + isb_pb = shash_find_and_delete(&remote_pbs, lsp->name); + if (!isb_pb) { + nbrec_logical_switch_update_ports_delvalue(ls, lsp); + } else { + sb_pb = find_lsp_in_sb(pb_input, lsp); + if (!sb_pb) { + continue; + } + sync_remote_port(pb_input, isb_pb, lsp, sb_pb); + } + } else { + VLOG_DBG("Ignore lsp %s on ts %s with type %s.", + lsp->name, ts->name, lsp->type); + } + } + + /* Delete extra port-binding from ISB */ + SHASH_FOR_EACH (node, &local_pbs) { + icsbrec_port_binding_delete(node->data); + } + + /* Create lsp in NB for remote ports */ + SHASH_FOR_EACH (node, &remote_pbs) { + create_nb_lsp(eng_ctx, node->data, ls); + } + + shash_destroy(&local_pbs); + shash_destroy(&remote_pbs); + } + + SHASH_FOR_EACH (node, &pb_data->switch_all_local_pbs) { + icsbrec_port_binding_delete(node->data); + } + + const struct icnbrec_transit_router *tr; + ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, icnb_tr_table) { + const struct nbrec_logical_router *lr = find_tr_in_nb(pb_input, + tr->name); + if (!lr) { + VLOG_DBG("Transit router %s not found in NB.", tr->name); + continue; + } + + struct shash nb_ports = SHASH_INITIALIZER(&nb_ports); + struct shash local_pbs = SHASH_INITIALIZER(&local_pbs); + struct shash remote_pbs = SHASH_INITIALIZER(&remote_pbs); + + for (size_t i = 0; i < lr->n_ports; i++) { + const struct nbrec_logical_router_port *lrp = lr->ports[i]; + if (smap_get_def(&lrp->options, "interconn-tr", NULL)) { + shash_add(&nb_ports, lrp->name, lrp); + } + } + + isb_pb_key = icsbrec_port_binding_index_init_row( + pb_input->icsbrec_port_binding_by_ts); + icsbrec_port_binding_index_set_transit_switch(isb_pb_key, tr->name); + + ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, + pb_input->icsbrec_port_binding_by_ts) { + if (isb_pb->availability_zone == pb_input->runned_az) { + shash_add(&local_pbs, isb_pb->logical_port, isb_pb); + shash_find_and_delete(&pb_data->router_all_local_pbs, + isb_pb->logical_port); + } else { + shash_add(&remote_pbs, isb_pb->logical_port, isb_pb); + } + } + icsbrec_port_binding_index_destroy_row(isb_pb_key); + + for (size_t i = 0; i < tr->n_ports; i++) { + const struct icnbrec_transit_router_port *trp = tr->ports[i]; + + if (trp_is_remote(pb_input, trp->chassis)) { + isb_pb = shash_find_and_delete(&remote_pbs, trp->name); + } else { + isb_pb = shash_find_and_delete(&local_pbs, trp->name); + if (!isb_pb) { + isb_pb = create_isb_pb(eng_ctx, trp->name, + pb_input->runned_az, tr->name, + &tr->header_.uuid, + "transit-router-port", + &pb_data->pb_tnlids); + icsbrec_port_binding_set_address(isb_pb, trp->mac); + } + } + + /* Don't allow remote ports to create NB LRP until ICSB entry is + * created in the appropriate AZ. */ + if (isb_pb) { + const struct nbrec_logical_router_port *lrp = + shash_find_and_delete(&nb_ports, trp->name); + if (!lrp) { + lrp = lrp_create(eng_ctx, lr, trp); + } + + sync_router_port(isb_pb, trp, lrp); + } + } + + SHASH_FOR_EACH (node, &nb_ports) { + nbrec_logical_router_port_delete(node->data); + nbrec_logical_router_update_ports_delvalue(lr, node->data); + } + + shash_destroy(&nb_ports); + shash_destroy(&local_pbs); + shash_destroy(&remote_pbs); + } + + SHASH_FOR_EACH (node, &pb_data->router_all_local_pbs) { + icsbrec_port_binding_delete(node->data); + } +} + +static const struct nbrec_logical_router * +find_tr_in_nb(struct pb_input *pb, char *tr_name) +{ + const struct nbrec_logical_router *key = + nbrec_logical_router_index_init_row(pb->nbrec_lr_by_name); + nbrec_logical_router_index_set_name(key, tr_name); + + const struct nbrec_logical_router *lr; + bool found = false; + NBREC_LOGICAL_ROUTER_FOR_EACH_EQUAL (lr, key, pb->nbrec_lr_by_name) { + if (smap_get(&lr->options, "interconn-tr")) { + found = true; + break; + } + } + + nbrec_logical_router_index_destroy_row(key); + if (found) { + return lr; + } + + return NULL; +} + +static const struct sbrec_port_binding * +find_peer_port(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb) +{ + const char *peer_name = smap_get(&sb_pb->options, "peer"); + if (!peer_name) { + return NULL; + } + + return find_sb_pb_by_name(pb->sbrec_port_binding_by_name, peer_name); +} + +static const struct sbrec_port_binding * +find_crp_from_lrp(struct pb_input *pb, + const struct sbrec_port_binding *lrp_pb) +{ + char *crp_name = ovn_chassis_redirect_name(lrp_pb->logical_port); + + const struct sbrec_port_binding *sb_pb = + find_sb_pb_by_name(pb->sbrec_port_binding_by_name, crp_name); + + free(crp_name); + return sb_pb; +} + +static const struct sbrec_port_binding * +find_crp_for_sb_pb(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb) +{ + const struct sbrec_port_binding *peer = find_peer_port(pb, sb_pb); + if (!peer) { + return NULL; + } + + return find_crp_from_lrp(pb, peer); +} + +static const char * +get_lp_address_for_sb_pb(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb) +{ + const struct nbrec_logical_switch_port *nb_lsp; + + nb_lsp = get_lsp_by_ts_port_name(pb->nbrec_port_by_name, + sb_pb->logical_port); + if (!strcmp(nb_lsp->type, "switch")) { + /* Switches always have implicit "unknown" address, and IC-SB port + * binding can only have one address specified. */ + return "unknown"; + } + + const struct sbrec_port_binding *peer = find_peer_port(pb, sb_pb); + if (!peer) { + return NULL; + } + + return peer->n_mac ? *peer->mac : NULL; +} + +static const struct sbrec_chassis * +find_sb_chassis(struct pb_input *pb, const char *name) +{ + const struct sbrec_chassis *key = + sbrec_chassis_index_init_row(pb->sbrec_chassis_by_name); + sbrec_chassis_index_set_name(key, name); + + const struct sbrec_chassis *chassis = + sbrec_chassis_index_find(pb->sbrec_chassis_by_name, key); + sbrec_chassis_index_destroy_row(key); + + return chassis; +} + +static void +sync_lsp_tnl_key(const struct nbrec_logical_switch_port *lsp, + int64_t isb_tnl_key) +{ + int64_t tnl_key = smap_get_int(&lsp->options, "requested-tnl-key", 0); + if (tnl_key != isb_tnl_key) { + VLOG_DBG("Set options:requested-tnl-key %"PRId64 + " for lsp %s in NB.", isb_tnl_key, lsp->name); + char *tnl_key_str = xasprintf("%"PRId64, isb_tnl_key); + nbrec_logical_switch_port_update_options_setkey(lsp, + "requested-tnl-key", + tnl_key_str); + free(tnl_key_str); + } +} + +static inline void +sync_lrp_tnl_key(const struct nbrec_logical_router_port *lrp, + int64_t isb_tnl_key) +{ + int64_t tnl_key = smap_get_int(&lrp->options, "requested-tnl-key", 0); + if (tnl_key != isb_tnl_key) { + VLOG_DBG("Set options:requested-tnl-key %" PRId64 " for lrp %s in NB.", + isb_tnl_key, lrp->name); + char *tnl_key_str = xasprintf("%"PRId64, isb_tnl_key); + nbrec_logical_router_port_update_options_setkey( + lrp, "requested-tnl-key", tnl_key_str); + free(tnl_key_str); + } +} + +static bool +get_router_uuid_by_sb_pb(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb, + struct uuid *router_uuid) +{ + const struct sbrec_port_binding *router_pb = find_peer_port(pb, sb_pb); + if (!router_pb || !router_pb->datapath) { + return NULL; + } + + return datapath_get_nb_uuid(router_pb->datapath, router_uuid); +} + +static void +update_isb_pb_external_ids(struct pb_input *pb, + const struct sbrec_port_binding *sb_pb, + const struct icsbrec_port_binding *isb_pb) +{ + struct uuid lr_uuid; + if (!get_router_uuid_by_sb_pb(pb, sb_pb, &lr_uuid)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Can't get router uuid for transit switch port %s.", + isb_pb->logical_port); + return; + } + + struct uuid current_lr_uuid; + if (smap_get_uuid(&isb_pb->external_ids, "router-id", ¤t_lr_uuid) && + uuid_equals(&lr_uuid, ¤t_lr_uuid)) { + return; + } + + char *uuid_s = xasprintf(UUID_FMT, UUID_ARGS(&lr_uuid)); + icsbrec_port_binding_update_external_ids_setkey(isb_pb, "router-id", + uuid_s); + free(uuid_s); +} + +/* For each local port: + * - Sync from NB to ISB. + * - Sync gateway from SB to ISB. + * - Sync tunnel key from ISB to NB. + */ +static void +sync_local_port(struct pb_input *pb, + const struct icsbrec_port_binding *isb_pb, + const struct sbrec_port_binding *sb_pb, + const struct nbrec_logical_switch_port *lsp) +{ + /* Sync address from NB to ISB */ + const char *address = get_lp_address_for_sb_pb(pb, sb_pb); + if (!address) { + VLOG_DBG("Can't get router/switch port address for logical" + " switch port %s", sb_pb->logical_port); + if (isb_pb->address[0]) { + icsbrec_port_binding_set_address(isb_pb, ""); + } + } else { + if (strcmp(address, isb_pb->address)) { + icsbrec_port_binding_set_address(isb_pb, address); + } + } + + /* Sync gateway from SB to ISB */ + const struct sbrec_port_binding *crp = find_crp_for_sb_pb(pb, sb_pb); + if (crp && crp->chassis) { + if (strcmp(crp->chassis->name, isb_pb->gateway)) { + icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name); + } + } else if (!strcmp(lsp->type, "switch") && sb_pb->chassis) { + if (strcmp(sb_pb->chassis->name, isb_pb->gateway)) { + icsbrec_port_binding_set_gateway(isb_pb, sb_pb->chassis->name); + } + } else { + if (isb_pb->gateway[0]) { + icsbrec_port_binding_set_gateway(isb_pb, ""); + } + } + + /* Sync external_ids:router-id to ISB */ + update_isb_pb_external_ids(pb, sb_pb, isb_pb); + + /* Sync back tunnel key from ISB to NB */ + sync_lsp_tnl_key(lsp, isb_pb->tunnel_key); +} + +/* For each remote port: + * - Sync from ISB to NB + * - Sync gateway from ISB to SB + */ +static void +sync_remote_port(struct pb_input *pb, + const struct icsbrec_port_binding *isb_pb, + const struct nbrec_logical_switch_port *lsp, + const struct sbrec_port_binding *sb_pb) +{ + /* Sync address from ISB to NB */ + if (isb_pb->address[0]) { + if (lsp->n_addresses != 1 || + strcmp(isb_pb->address, lsp->addresses[0])) { + nbrec_logical_switch_port_set_addresses( + lsp, (const char **)&isb_pb->address, 1); + } + } else { + if (lsp->n_addresses != 0) { + nbrec_logical_switch_port_set_addresses(lsp, NULL, 0); + } + } + + /* Sync tunnel key from ISB to NB */ + sync_lsp_tnl_key(lsp, isb_pb->tunnel_key); + + /* Skip port binding if it is already requested by the CMS. */ + if (smap_get(&lsp->options, "requested-chassis")) { + return; + } + + /* Sync gateway from ISB to SB */ + if (isb_pb->gateway[0]) { + if (!sb_pb->chassis || strcmp(sb_pb->chassis->name, isb_pb->gateway)) { + const struct sbrec_chassis *chassis = + find_sb_chassis(pb, isb_pb->gateway); + if (!chassis) { + VLOG_DBG("Chassis %s is not found in SB, syncing from ISB " + "to SB skipped for logical port %s.", + isb_pb->gateway, lsp->name); + return; + } + sbrec_port_binding_set_chassis(sb_pb, chassis); + } + } else { + if (sb_pb->chassis) { + sbrec_port_binding_set_chassis(sb_pb, NULL); + } + } +} + +/* For each remote port: + * - Sync from ISB to NB + */ +static void +sync_router_port(const struct icsbrec_port_binding *isb_pb, + const struct icnbrec_transit_router_port *trp, + const struct nbrec_logical_router_port *lrp) +{ + /* Sync from ICNB to NB */ + if (trp->chassis[0]) { + const char *chassis_name = + smap_get_def(&lrp->options, "requested-chassis", ""); + if (strcmp(trp->chassis, chassis_name)) { + nbrec_logical_router_port_update_options_setkey( + lrp, "requested-chassis", trp->chassis); + } + } else { + nbrec_logical_router_port_update_options_delkey( + lrp, "requested-chassis"); + } + + if (strcmp(trp->mac, lrp->mac)) { + nbrec_logical_router_port_set_mac(lrp, trp->mac); + } + + bool sync_networks = false; + if (trp->n_networks != lrp->n_networks) { + sync_networks = true; + } else { + for (size_t i = 0; i < trp->n_networks; i++) { + if (strcmp(trp->networks[i], lrp->networks[i])) { + sync_networks |= true; + break; + } + } + } + + if (sync_networks) { + nbrec_logical_router_port_set_networks( + lrp, (const char **) trp->networks, trp->n_networks); + } + + /* Sync tunnel key from ISB to NB */ + sync_lrp_tnl_key(lrp, isb_pb->tunnel_key); +} + +static void +create_nb_lsp(const struct engine_context *ctx, + const struct icsbrec_port_binding *isb_pb, + const struct nbrec_logical_switch *ls) +{ + const struct nbrec_logical_switch_port *lsp = + nbrec_logical_switch_port_insert(ctx->ovnnb_idl_txn); + nbrec_logical_switch_port_set_name(lsp, isb_pb->logical_port); + nbrec_logical_switch_port_set_type(lsp, "remote"); + + bool up = true; + nbrec_logical_switch_port_set_up(lsp, &up, 1); + + if (isb_pb->address[0]) { + nbrec_logical_switch_port_set_addresses( + lsp, (const char **)&isb_pb->address, 1); + } + sync_lsp_tnl_key(lsp, isb_pb->tunnel_key); + nbrec_logical_switch_update_ports_addvalue(ls, lsp); +} + +static uint32_t +allocate_port_key(struct hmap *pb_tnlids) +{ + static uint32_t hint; + return ovn_allocate_tnlid(pb_tnlids, "transit port", + 1, (1u << 15) - 1, &hint); +} + +static const struct icsbrec_port_binding * +create_isb_pb(const struct engine_context *ctx, const char *logical_port, + const struct icsbrec_availability_zone *az, const char *ts_name, + const struct uuid *nb_ic_uuid, const char *type, + struct hmap *pb_tnlids) +{ + uint32_t pb_tnl_key = allocate_port_key(pb_tnlids); + if (!pb_tnl_key) { + return NULL; + } + + const struct icsbrec_port_binding *isb_pb = + icsbrec_port_binding_insert(ctx->ovnisb_idl_txn); + icsbrec_port_binding_set_availability_zone(isb_pb, az); + icsbrec_port_binding_set_transit_switch(isb_pb, ts_name); + icsbrec_port_binding_set_logical_port(isb_pb, logical_port); + icsbrec_port_binding_set_tunnel_key(isb_pb, pb_tnl_key); + icsbrec_port_binding_set_nb_ic_uuid(isb_pb, nb_ic_uuid, 1); + icsbrec_port_binding_set_type(isb_pb, type); + return isb_pb; +} + +static bool +trp_is_remote(struct pb_input *pb, const char *chassis_name) +{ + if (chassis_name) { + const struct sbrec_chassis *chassis = + find_sb_chassis(pb, chassis_name); + if (chassis) { + return smap_get_bool(&chassis->other_config, "is-remote", false); + } else { + return true; + } + } + + return false; +} + +static struct nbrec_logical_router_port * +lrp_create(const struct engine_context *ctx, + const struct nbrec_logical_router *lr, + const struct icnbrec_transit_router_port *trp) +{ + struct nbrec_logical_router_port *lrp = + nbrec_logical_router_port_insert(ctx->ovnnb_idl_txn); + nbrec_logical_router_port_set_name(lrp, trp->name); + + nbrec_logical_router_port_update_options_setkey(lrp, "interconn-tr", + trp->name); + nbrec_logical_router_update_ports_addvalue(lr, lrp); + return lrp; +} + +static void +sync_ts_isb_pb(struct pb_input *pb, const struct sbrec_port_binding *sb_pb, + const struct icsbrec_port_binding *isb_pb) +{ + const char *address = get_lp_address_for_sb_pb(pb, sb_pb); + if (address) { + icsbrec_port_binding_set_address(isb_pb, address); + } + + const struct sbrec_port_binding *crp = find_crp_for_sb_pb(pb, sb_pb); + if (crp && crp->chassis) { + icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name); + } + + update_isb_pb_external_ids(pb, sb_pb, isb_pb); + + /* Sync encap so that multiple encaps can be used for the same + * gateway. However, it is not needed for now, since we don't yet + * support specifying encap type/ip for gateway chassis or ha-chassis + * for logical router port in NB DB, and now encap should always be + * empty. The sync can be added if we add such support for gateway + * chassis/ha-chassis in NB DB. */ +} + +static const struct sbrec_port_binding * +find_lsp_in_sb(struct pb_input *pb, + const struct nbrec_logical_switch_port *lsp) +{ + return find_sb_pb_by_name(pb->sbrec_port_binding_by_name, lsp->name); +} diff --git a/ic/en-port-binding.h b/ic/en-port-binding.h new file mode 100644 index 000000000..e5f10dced --- /dev/null +++ b/ic/en-port-binding.h @@ -0,0 +1,36 @@ +#ifndef EN_IC_PORT_BINDING_H +#define EN_IC_PORT_BINDING_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_port_binding { + struct hmap pb_tnlids; + struct shash switch_all_local_pbs; + struct shash router_all_local_pbs; +}; + +struct pb_input { + /* Indexes */ + const struct icsbrec_availability_zone *runned_az; + struct ovsdb_idl_index *nbrec_ls_by_name; + struct ovsdb_idl_index *nbrec_port_by_name; + struct ovsdb_idl_index *nbrec_lr_by_name; + struct ovsdb_idl_index *sbrec_port_binding_by_name; + struct ovsdb_idl_index *sbrec_chassis_by_name; + struct ovsdb_idl_index *icsbrec_port_binding_by_az; + struct ovsdb_idl_index *icsbrec_port_binding_by_ts; +}; + +void *en_port_binding_init(struct engine_node *, struct engine_arg *); +enum engine_node_state en_port_binding_run(struct engine_node *, void *data); +void en_port_binding_cleanup(void *data); + +#endif diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index e907a902a..ac360fb9f 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -28,6 +28,7 @@ #include "inc-proc-ic.h" #include "en-ic.h" #include "en-enum-datapaths.h" +#include "en-port-binding.h" #include "unixctl.h" #include "util.h" @@ -160,6 +161,7 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic); * avoid sparse errors. */ static ENGINE_NODE(ic, SB_WRITE); static ENGINE_NODE(enum_datapaths); +static ENGINE_NODE(port_binding, SB_WRITE); void inc_proc_ic_init(struct ovsdb_idl_loop *nb, struct ovsdb_idl_loop *sb, @@ -171,7 +173,16 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_enum_datapaths, &en_icnb_transit_switch, NULL); engine_add_input(&en_enum_datapaths, &en_icsb_datapath_binding, NULL); + engine_add_input(&en_port_binding, &en_icnb_transit_switch, NULL); + engine_add_input(&en_port_binding, &en_icnb_transit_router, NULL); + engine_add_input(&en_port_binding, &en_icsb_port_binding, NULL); + engine_add_input(&en_port_binding, &en_nb_logical_switch, NULL); + engine_add_input(&en_port_binding, &en_sb_port_binding, NULL); + engine_add_input(&en_port_binding, &en_nb_logical_router, NULL); + engine_add_input(&en_port_binding, &en_sb_chassis, 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_nb_nb_global, NULL); engine_add_input(&en_ic, &en_nb_logical_router_static_route, NULL); engine_add_input(&en_ic, &en_nb_logical_router, NULL); @@ -193,11 +204,11 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_ic, &en_icnb_transit_router, NULL); engine_add_input(&en_ic, &en_icnb_transit_router_port, NULL); + engine_add_input(&en_ic, &en_icsb_port_binding, NULL); engine_add_input(&en_ic, &en_icsb_ic_sb_global, NULL); 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_port_binding, NULL); engine_add_input(&en_ic, &en_icsb_gateway, NULL); engine_add_input(&en_ic, &en_icsb_route, NULL); engine_add_input(&en_ic, &en_icsb_datapath_binding, NULL); diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 3ad40583e..7bde85854 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -70,9 +70,6 @@ static const char *ssl_private_key_file; static const char *ssl_certificate_file; static const char *ssl_ca_cert_file; -static const struct sbrec_port_binding * find_sb_pb_by_name( - struct ovsdb_idl_index *sbrec_port_binding_by_name, const char *name); - static void usage(void) @@ -172,7 +169,7 @@ allocate_dp_key(struct hmap *dp_tnlids, bool vxlan_mode, const char *name) &hint); } -static enum ic_port_binding_type +enum ic_port_binding_type ic_pb_get_type(const struct icsbrec_port_binding *isb_pb) { if (isb_pb->type && !strcmp(isb_pb->type, "transit-router-port")) { @@ -579,16 +576,30 @@ gateway_run(struct engine_context *ctx, shash_destroy(&remote_gws); } -static const struct nbrec_logical_switch * -find_ts_in_nb(struct ic_input *ic, char *ts_name) +const struct nbrec_logical_router_port * +get_lrp_by_lrp_name(struct ic_input *ic, const char *lrp_name) +{ + const struct nbrec_logical_router_port *lrp; + const struct nbrec_logical_router_port *lrp_key = + nbrec_logical_router_port_index_init_row(ic->nbrec_lrp_by_name); + nbrec_logical_router_port_index_set_name(lrp_key, lrp_name); + lrp = + nbrec_logical_router_port_index_find(ic->nbrec_lrp_by_name, lrp_key); + nbrec_logical_router_port_index_destroy_row(lrp_key); + + return lrp; +} + +const struct nbrec_logical_switch * +find_ts_in_nb(struct ovsdb_idl_index *nbrec_ls_by_name, char *ts_name) { const struct nbrec_logical_switch *key = - nbrec_logical_switch_index_init_row(ic->nbrec_ls_by_name); + nbrec_logical_switch_index_init_row(nbrec_ls_by_name); nbrec_logical_switch_index_set_name(key, ts_name); const struct nbrec_logical_switch *ls; bool found = false; - NBREC_LOGICAL_SWITCH_FOR_EACH_EQUAL (ls, key, ic->nbrec_ls_by_name) { + NBREC_LOGICAL_SWITCH_FOR_EACH_EQUAL (ls, key, nbrec_ls_by_name) { const char *ls_ts_name = smap_get(&ls->other_config, "interconn-ts"); if (ls_ts_name && !strcmp(ts_name, ls_ts_name)) { found = true; @@ -603,31 +614,21 @@ find_ts_in_nb(struct ic_input *ic, char *ts_name) return NULL; } -static const struct nbrec_logical_router * -find_tr_in_nb(struct ic_input *ic, char *tr_name) +const struct nbrec_logical_switch_port * +get_lsp_by_ts_port_name(struct ovsdb_idl_index *nbrec_port_by_name, + const char *ts_port_name) { - const struct nbrec_logical_router *key = - nbrec_logical_router_index_init_row(ic->nbrec_lr_by_name); - nbrec_logical_router_index_set_name(key, tr_name); - - const struct nbrec_logical_router *lr; - bool found = false; - NBREC_LOGICAL_ROUTER_FOR_EACH_EQUAL (lr, key, ic->nbrec_lr_by_name) { - if (smap_get(&lr->options, "interconn-tr")) { - found = true; - break; - } - } + const struct nbrec_logical_switch_port *lsp, *key; - nbrec_logical_router_index_destroy_row(key); - if (found) { - return lr; - } + key = nbrec_logical_switch_port_index_init_row(nbrec_port_by_name); + nbrec_logical_switch_port_index_set_name(key, ts_port_name); + lsp = nbrec_logical_switch_port_index_find(nbrec_port_by_name, key); + nbrec_logical_switch_port_index_destroy_row(key); - return NULL; + return lsp; } -static const struct sbrec_port_binding * +const struct sbrec_port_binding * find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, const char *name) { @@ -642,641 +643,6 @@ find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, return pb; } -static const struct sbrec_port_binding * -find_peer_port(struct ic_input *ic, - const struct sbrec_port_binding *sb_pb) -{ - const char *peer_name = smap_get(&sb_pb->options, "peer"); - if (!peer_name) { - return NULL; - } - - return find_sb_pb_by_name(ic->sbrec_port_binding_by_name, peer_name); -} - -static const struct sbrec_port_binding * -find_crp_from_lrp(struct ic_input *ic, - const struct sbrec_port_binding *lrp_pb) -{ - char *crp_name = ovn_chassis_redirect_name(lrp_pb->logical_port); - - const struct sbrec_port_binding *pb = - find_sb_pb_by_name(ic->sbrec_port_binding_by_name, crp_name); - - free(crp_name); - return pb; -} - -static const struct sbrec_port_binding * -find_crp_for_sb_pb(struct ic_input *ic, - const struct sbrec_port_binding *sb_pb) -{ - const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb); - if (!peer) { - return NULL; - } - - return find_crp_from_lrp(ic, peer); -} - -static const struct nbrec_logical_switch_port * -get_lsp_by_ts_port_name(struct ic_input *ic, const char *ts_port_name) -{ - const struct nbrec_logical_switch_port *lsp, *key; - - key = nbrec_logical_switch_port_index_init_row(ic->nbrec_port_by_name); - nbrec_logical_switch_port_index_set_name(key, ts_port_name); - lsp = nbrec_logical_switch_port_index_find(ic->nbrec_port_by_name, key); - nbrec_logical_switch_port_index_destroy_row(key); - - return lsp; -} - -static const char * -get_lp_address_for_sb_pb(struct ic_input *ic, - const struct sbrec_port_binding *sb_pb) -{ - const struct nbrec_logical_switch_port *nb_lsp; - - nb_lsp = get_lsp_by_ts_port_name(ic, sb_pb->logical_port); - if (!strcmp(nb_lsp->type, "switch")) { - /* Switches always have implicit "unknown" address, and IC-SB port - * binding can only have one address specified. */ - return "unknown"; - } - - const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb); - if (!peer) { - return NULL; - } - - return peer->n_mac ? *peer->mac : NULL; -} - -static const struct sbrec_chassis * -find_sb_chassis(struct ic_input *ic, const char *name) -{ - const struct sbrec_chassis *key = - sbrec_chassis_index_init_row(ic->sbrec_chassis_by_name); - sbrec_chassis_index_set_name(key, name); - - const struct sbrec_chassis *chassis = - sbrec_chassis_index_find(ic->sbrec_chassis_by_name, key); - sbrec_chassis_index_destroy_row(key); - - return chassis; -} - -static void -sync_lsp_tnl_key(const struct nbrec_logical_switch_port *lsp, - int64_t isb_tnl_key) -{ - int64_t tnl_key = smap_get_int(&lsp->options, "requested-tnl-key", 0); - if (tnl_key != isb_tnl_key) { - VLOG_DBG("Set options:requested-tnl-key %"PRId64 - " for lsp %s in NB.", isb_tnl_key, lsp->name); - char *tnl_key_str = xasprintf("%"PRId64, isb_tnl_key); - nbrec_logical_switch_port_update_options_setkey(lsp, - "requested-tnl-key", - tnl_key_str); - free(tnl_key_str); - } - -} - -static inline void -sync_lrp_tnl_key(const struct nbrec_logical_router_port *lrp, - int64_t isb_tnl_key) -{ - int64_t tnl_key = smap_get_int(&lrp->options, "requested-tnl-key", 0); - if (tnl_key != isb_tnl_key) { - VLOG_DBG("Set options:requested-tnl-key %" PRId64 " for lrp %s in NB.", - isb_tnl_key, lrp->name); - char *tnl_key_str = xasprintf("%"PRId64, isb_tnl_key); - nbrec_logical_router_port_update_options_setkey( - lrp, "requested-tnl-key", tnl_key_str); - free(tnl_key_str); - } -} - -static bool -get_router_uuid_by_sb_pb(struct ic_input *ic, - const struct sbrec_port_binding *sb_pb, - struct uuid *router_uuid) -{ - const struct sbrec_port_binding *router_pb = find_peer_port(ic, sb_pb); - if (!router_pb || !router_pb->datapath) { - return NULL; - } - - return datapath_get_nb_uuid(router_pb->datapath, router_uuid); -} - -static void -update_isb_pb_external_ids(struct ic_input *ic, - const struct sbrec_port_binding *sb_pb, - const struct icsbrec_port_binding *isb_pb) -{ - struct uuid lr_uuid; - if (!get_router_uuid_by_sb_pb(ic, sb_pb, &lr_uuid)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Can't get router uuid for transit switch port %s.", - isb_pb->logical_port); - return; - } - - struct uuid current_lr_uuid; - if (smap_get_uuid(&isb_pb->external_ids, "router-id", ¤t_lr_uuid) && - uuid_equals(&lr_uuid, ¤t_lr_uuid)) { - return; - } - - char *uuid_s = xasprintf(UUID_FMT, UUID_ARGS(&lr_uuid)); - icsbrec_port_binding_update_external_ids_setkey(isb_pb, "router-id", - uuid_s); - free(uuid_s); -} - -/* For each local port: - * - Sync from NB to ISB. - * - Sync gateway from SB to ISB. - * - Sync tunnel key from ISB to NB. - */ -static void -sync_local_port(struct ic_input *ic, - const struct icsbrec_port_binding *isb_pb, - const struct sbrec_port_binding *sb_pb, - const struct nbrec_logical_switch_port *lsp) -{ - /* Sync address from NB to ISB */ - const char *address = get_lp_address_for_sb_pb(ic, sb_pb); - if (!address) { - VLOG_DBG("Can't get router/switch port address for logical" - " switch port %s", sb_pb->logical_port); - if (isb_pb->address[0]) { - icsbrec_port_binding_set_address(isb_pb, ""); - } - } else { - if (strcmp(address, isb_pb->address)) { - icsbrec_port_binding_set_address(isb_pb, address); - } - } - - /* Sync gateway from SB to ISB */ - const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ic, sb_pb); - if (crp && crp->chassis) { - if (strcmp(crp->chassis->name, isb_pb->gateway)) { - icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name); - } - } else if (!strcmp(lsp->type, "switch") && sb_pb->chassis) { - if (strcmp(sb_pb->chassis->name, isb_pb->gateway)) { - icsbrec_port_binding_set_gateway(isb_pb, sb_pb->chassis->name); - } - } else { - if (isb_pb->gateway[0]) { - icsbrec_port_binding_set_gateway(isb_pb, ""); - } - } - - /* Sync external_ids:router-id to ISB */ - update_isb_pb_external_ids(ic, sb_pb, isb_pb); - - /* Sync back tunnel key from ISB to NB */ - sync_lsp_tnl_key(lsp, isb_pb->tunnel_key); -} - -/* For each remote port: - * - Sync from ISB to NB - * - Sync gateway from ISB to SB - */ -static void -sync_remote_port(struct ic_input *ic, - const struct icsbrec_port_binding *isb_pb, - const struct nbrec_logical_switch_port *lsp, - const struct sbrec_port_binding *sb_pb) -{ - /* Sync address from ISB to NB */ - if (isb_pb->address[0]) { - if (lsp->n_addresses != 1 || - strcmp(isb_pb->address, lsp->addresses[0])) { - nbrec_logical_switch_port_set_addresses( - lsp, (const char **)&isb_pb->address, 1); - } - } else { - if (lsp->n_addresses != 0) { - nbrec_logical_switch_port_set_addresses(lsp, NULL, 0); - } - } - - /* Sync tunnel key from ISB to NB */ - sync_lsp_tnl_key(lsp, isb_pb->tunnel_key); - - /* Skip port binding if it is already requested by the CMS. */ - if (smap_get(&lsp->options, "requested-chassis")) { - return; - } - - /* Sync gateway from ISB to SB */ - if (isb_pb->gateway[0]) { - if (!sb_pb->chassis || strcmp(sb_pb->chassis->name, isb_pb->gateway)) { - const struct sbrec_chassis *chassis = - find_sb_chassis(ic, isb_pb->gateway); - if (!chassis) { - VLOG_DBG("Chassis %s is not found in SB, syncing from ISB " - "to SB skipped for logical port %s.", - isb_pb->gateway, lsp->name); - return; - } - sbrec_port_binding_set_chassis(sb_pb, chassis); - } - } else { - if (sb_pb->chassis) { - sbrec_port_binding_set_chassis(sb_pb, NULL); - } - } -} - -/* For each remote port: - * - Sync from ISB to NB - */ -static void -sync_router_port(const struct icsbrec_port_binding *isb_pb, - const struct icnbrec_transit_router_port *trp, - const struct nbrec_logical_router_port *lrp) -{ - /* Sync from ICNB to NB */ - if (trp->chassis[0]) { - const char *chassis_name = - smap_get_def(&lrp->options, "requested-chassis", ""); - if (strcmp(trp->chassis, chassis_name)) { - nbrec_logical_router_port_update_options_setkey( - lrp, "requested-chassis", trp->chassis); - } - } else { - nbrec_logical_router_port_update_options_delkey( - lrp, "requested-chassis"); - } - - if (strcmp(trp->mac, lrp->mac)) { - nbrec_logical_router_port_set_mac(lrp, trp->mac); - } - - bool sync_networks = false; - if (trp->n_networks != lrp->n_networks) { - sync_networks = true; - } else { - for (size_t i = 0; i < trp->n_networks; i++) { - if (strcmp(trp->networks[i], lrp->networks[i])) { - sync_networks |= true; - break; - } - } - } - - if (sync_networks) { - nbrec_logical_router_port_set_networks( - lrp, (const char **) trp->networks, trp->n_networks); - } - - /* Sync tunnel key from ISB to NB */ - sync_lrp_tnl_key(lrp, isb_pb->tunnel_key); -} - -static void -create_nb_lsp(struct engine_context *ctx, - const struct icsbrec_port_binding *isb_pb, - const struct nbrec_logical_switch *ls) -{ - const struct nbrec_logical_switch_port *lsp = - nbrec_logical_switch_port_insert(ctx->ovnnb_idl_txn); - nbrec_logical_switch_port_set_name(lsp, isb_pb->logical_port); - nbrec_logical_switch_port_set_type(lsp, "remote"); - - bool up = true; - nbrec_logical_switch_port_set_up(lsp, &up, 1); - - if (isb_pb->address[0]) { - nbrec_logical_switch_port_set_addresses( - lsp, (const char **)&isb_pb->address, 1); - } - sync_lsp_tnl_key(lsp, isb_pb->tunnel_key); - nbrec_logical_switch_update_ports_addvalue(ls, lsp); -} - -static uint32_t -allocate_port_key(struct hmap *pb_tnlids) -{ - static uint32_t hint; - return ovn_allocate_tnlid(pb_tnlids, "transit port", - 1, (1u << 15) - 1, &hint); -} - -static const struct icsbrec_port_binding * -create_isb_pb(struct engine_context *ctx, const char *logical_port, - const struct icsbrec_availability_zone *az, const char *ts_name, - const struct uuid *nb_ic_uuid, const char *type, - struct hmap *pb_tnlids) -{ - uint32_t pb_tnl_key = allocate_port_key(pb_tnlids); - if (!pb_tnl_key) { - return NULL; - } - - const struct icsbrec_port_binding *isb_pb = - icsbrec_port_binding_insert(ctx->ovnisb_idl_txn); - icsbrec_port_binding_set_availability_zone(isb_pb, az); - icsbrec_port_binding_set_transit_switch(isb_pb, ts_name); - icsbrec_port_binding_set_logical_port(isb_pb, logical_port); - icsbrec_port_binding_set_tunnel_key(isb_pb, pb_tnl_key); - icsbrec_port_binding_set_nb_ic_uuid(isb_pb, nb_ic_uuid, 1); - icsbrec_port_binding_set_type(isb_pb, type); - return isb_pb; -} - -static const struct nbrec_logical_router_port * -get_lrp_by_lrp_name(struct ic_input *ic, const char *lrp_name) -{ - const struct nbrec_logical_router_port *lrp; - const struct nbrec_logical_router_port *lrp_key = - nbrec_logical_router_port_index_init_row(ic->nbrec_lrp_by_name); - nbrec_logical_router_port_index_set_name(lrp_key, lrp_name); - lrp = - nbrec_logical_router_port_index_find(ic->nbrec_lrp_by_name, lrp_key); - nbrec_logical_router_port_index_destroy_row(lrp_key); - - return lrp; -} - -static bool -trp_is_remote(struct ic_input *ic, const char *chassis_name) -{ - if (chassis_name) { - const struct sbrec_chassis *chassis = - find_sb_chassis(ic, chassis_name); - if (chassis) { - return smap_get_bool(&chassis->other_config, "is-remote", false); - } else { - return true; - } - } - - return false; -} - -static struct nbrec_logical_router_port * -lrp_create(struct engine_context *ctx, const struct nbrec_logical_router *lr, - const struct icnbrec_transit_router_port *trp) -{ - struct nbrec_logical_router_port *lrp = - nbrec_logical_router_port_insert(ctx->ovnnb_idl_txn); - nbrec_logical_router_port_set_name(lrp, trp->name); - - nbrec_logical_router_port_update_options_setkey(lrp, "interconn-tr", - trp->name); - nbrec_logical_router_update_ports_addvalue(lr, lrp); - return lrp; -} - -static void -sync_ts_isb_pb(struct ic_input *ic, const struct sbrec_port_binding *sb_pb, - const struct icsbrec_port_binding *isb_pb) -{ - const char *address = get_lp_address_for_sb_pb(ic, sb_pb); - if (address) { - icsbrec_port_binding_set_address(isb_pb, address); - } - - const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ic, sb_pb); - if (crp && crp->chassis) { - icsbrec_port_binding_set_gateway(isb_pb, crp->chassis->name); - } - - update_isb_pb_external_ids(ic, sb_pb, isb_pb); - - /* XXX: Sync encap so that multiple encaps can be used for the same - * gateway. However, it is not needed for now, since we don't yet - * support specifying encap type/ip for gateway chassis or ha-chassis - * for logical router port in NB DB, and now encap should always be - * empty. The sync can be added if we add such support for gateway - * chassis/ha-chassis in NB DB. */ -} - -static const struct sbrec_port_binding * -find_lsp_in_sb(struct ic_input *ic, - const struct nbrec_logical_switch_port *lsp) -{ - return find_sb_pb_by_name(ic->sbrec_port_binding_by_name, lsp->name); -} - -static void -port_binding_run(struct engine_context *ctx, - struct ic_input *ic) -{ - if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn - || !ctx->ovnsb_idl_txn) { - return; - } - - struct shash switch_all_local_pbs = - SHASH_INITIALIZER(&switch_all_local_pbs); - struct shash router_all_local_pbs = - SHASH_INITIALIZER(&router_all_local_pbs); - struct hmap pb_tnlids = HMAP_INITIALIZER(&pb_tnlids); - struct shash_node *node; - - const struct icsbrec_port_binding *isb_pb; - const struct icsbrec_port_binding *isb_pb_key = - icsbrec_port_binding_index_init_row(ic->icsbrec_port_binding_by_az); - icsbrec_port_binding_index_set_availability_zone(isb_pb_key, - ic->runned_az); - - ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, - ic->icsbrec_port_binding_by_az) { - ic_pb_get_type(isb_pb) != IC_ROUTER_PORT - ? shash_add(&switch_all_local_pbs, isb_pb->logical_port, isb_pb) - : shash_add(&router_all_local_pbs, isb_pb->logical_port, isb_pb); - - ovn_add_tnlid(&pb_tnlids, isb_pb->tunnel_key); - } - icsbrec_port_binding_index_destroy_row(isb_pb_key); - - const struct sbrec_port_binding *sb_pb; - const struct icnbrec_transit_switch *ts; - ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, - ic->icnbrec_transit_switch_table) { - const struct nbrec_logical_switch *ls = find_ts_in_nb(ic, ts->name); - if (!ls) { - VLOG_DBG("Transit switch %s not found in NB.", ts->name); - continue; - } - struct shash local_pbs = SHASH_INITIALIZER(&local_pbs); - struct shash remote_pbs = SHASH_INITIALIZER(&remote_pbs); - - isb_pb_key = icsbrec_port_binding_index_init_row( - ic->icsbrec_port_binding_by_ts); - icsbrec_port_binding_index_set_transit_switch(isb_pb_key, ts->name); - - ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, - ic->icsbrec_port_binding_by_ts) { - if (isb_pb->availability_zone == ic->runned_az) { - shash_add(&local_pbs, isb_pb->logical_port, isb_pb); - shash_find_and_delete(&switch_all_local_pbs, - isb_pb->logical_port); - } else { - shash_add(&remote_pbs, isb_pb->logical_port, isb_pb); - } - } - icsbrec_port_binding_index_destroy_row(isb_pb_key); - - const struct nbrec_logical_switch_port *lsp; - for (int i = 0; i < ls->n_ports; i++) { - lsp = ls->ports[i]; - - if (!strcmp(lsp->type, "router") - || !strcmp(lsp->type, "switch")) { - /* The port is local. */ - sb_pb = find_lsp_in_sb(ic, lsp); - if (!sb_pb) { - continue; - } - isb_pb = shash_find_and_delete(&local_pbs, lsp->name); - if (!isb_pb) { - isb_pb = create_isb_pb( - ctx, sb_pb->logical_port, ic->runned_az, ts->name, - &ts->header_.uuid, "transit-switch-port", &pb_tnlids); - sync_ts_isb_pb(ic, sb_pb, isb_pb); - } else { - sync_local_port(ic, isb_pb, sb_pb, lsp); - } - - if (isb_pb->type) { - icsbrec_port_binding_set_type(isb_pb, - "transit-switch-port"); - } - - if (isb_pb->nb_ic_uuid) { - icsbrec_port_binding_set_nb_ic_uuid(isb_pb, - &ts->header_.uuid, 1); - } - } else if (!strcmp(lsp->type, "remote")) { - /* The port is remote. */ - isb_pb = shash_find_and_delete(&remote_pbs, lsp->name); - if (!isb_pb) { - nbrec_logical_switch_update_ports_delvalue(ls, lsp); - } else { - sb_pb = find_lsp_in_sb(ic, lsp); - if (!sb_pb) { - continue; - } - sync_remote_port(ic, isb_pb, lsp, sb_pb); - } - } else { - VLOG_DBG("Ignore lsp %s on ts %s with type %s.", - lsp->name, ts->name, lsp->type); - } - } - - /* Delete extra port-binding from ISB */ - SHASH_FOR_EACH (node, &local_pbs) { - icsbrec_port_binding_delete(node->data); - } - - /* Create lsp in NB for remote ports */ - SHASH_FOR_EACH (node, &remote_pbs) { - create_nb_lsp(ctx, node->data, ls); - } - - shash_destroy(&local_pbs); - shash_destroy(&remote_pbs); - } - - SHASH_FOR_EACH (node, &switch_all_local_pbs) { - icsbrec_port_binding_delete(node->data); - } - shash_destroy(&switch_all_local_pbs); - - const struct icnbrec_transit_router *tr; - ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, - ic->icnbrec_transit_router_table) { - const struct nbrec_logical_router *lr = find_tr_in_nb(ic, tr->name); - if (!lr) { - VLOG_DBG("Transit router %s not found in NB.", tr->name); - continue; - } - - struct shash nb_ports = SHASH_INITIALIZER(&nb_ports); - struct shash local_pbs = SHASH_INITIALIZER(&local_pbs); - struct shash remote_pbs = SHASH_INITIALIZER(&remote_pbs); - - for (size_t i = 0; i < lr->n_ports; i++) { - const struct nbrec_logical_router_port *lrp = lr->ports[i]; - if (smap_get_def(&lrp->options, "interconn-tr", NULL)) { - shash_add(&nb_ports, lrp->name, lrp); - } - } - - isb_pb_key = icsbrec_port_binding_index_init_row( - ic->icsbrec_port_binding_by_ts); - icsbrec_port_binding_index_set_transit_switch(isb_pb_key, tr->name); - - ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, - ic->icsbrec_port_binding_by_ts) { - if (isb_pb->availability_zone == ic->runned_az) { - shash_add(&local_pbs, isb_pb->logical_port, isb_pb); - shash_find_and_delete(&router_all_local_pbs, - isb_pb->logical_port); - } else { - shash_add(&remote_pbs, isb_pb->logical_port, isb_pb); - } - } - icsbrec_port_binding_index_destroy_row(isb_pb_key); - - for (size_t i = 0; i < tr->n_ports; i++) { - const struct icnbrec_transit_router_port *trp = tr->ports[i]; - - if (trp_is_remote(ic, trp->chassis)) { - isb_pb = shash_find_and_delete(&remote_pbs, trp->name); - } else { - isb_pb = shash_find_and_delete(&local_pbs, trp->name); - if (!isb_pb) { - isb_pb = create_isb_pb(ctx, trp->name, ic->runned_az, - tr->name, &tr->header_.uuid, - "transit-router-port", &pb_tnlids); - icsbrec_port_binding_set_address(isb_pb, trp->mac); - } - } - - /* Don't allow remote ports to create NB LRP until ICSB entry is - * created in the appropriate AZ. */ - if (isb_pb) { - const struct nbrec_logical_router_port *lrp = - shash_find_and_delete(&nb_ports, trp->name); - if (!lrp) { - lrp = lrp_create(ctx, lr, trp); - } - - sync_router_port(isb_pb, trp, lrp); - } - } - - SHASH_FOR_EACH(node, &nb_ports) { - nbrec_logical_router_port_delete(node->data); - nbrec_logical_router_update_ports_delvalue(lr, node->data); - } - - shash_destroy(&nb_ports); - shash_destroy(&local_pbs); - shash_destroy(&remote_pbs); - } - - SHASH_FOR_EACH (node, &router_all_local_pbs) { - icsbrec_port_binding_delete(node->data); - } - - ovn_destroy_tnlids(&pb_tnlids); - shash_destroy(&router_all_local_pbs); -} - struct ic_router_info { struct hmap_node node; const struct nbrec_logical_router *lr; /* key of hmap */ @@ -1948,7 +1314,7 @@ get_lrp_name_by_ts_port_name(struct ic_input *ic, const char *ts_port_name) { const struct nbrec_logical_switch_port *nb_lsp; - nb_lsp = get_lsp_by_ts_port_name(ic, ts_port_name); + nb_lsp = get_lsp_by_ts_port_name(ic->nbrec_port_by_name, ts_port_name); if (!nb_lsp) { return NULL; } @@ -1962,7 +1328,7 @@ find_lrp_of_nexthop(struct ic_input *ic, { const struct nbrec_logical_router_port *lrp; const struct nbrec_logical_switch *ls; - ls = find_ts_in_nb(ic, isb_route->transit_switch); + ls = find_ts_in_nb(ic->nbrec_ls_by_name, isb_route->transit_switch); if (!ls) { return NULL; } @@ -2502,7 +1868,8 @@ route_run(struct engine_context *ctx, } const struct nbrec_logical_switch_port *nb_lsp; - nb_lsp = get_lsp_by_ts_port_name(ic, isb_pb->logical_port); + nb_lsp = get_lsp_by_ts_port_name(ic->nbrec_port_by_name, + isb_pb->logical_port); if (!strcmp(nb_lsp->type, "switch")) { VLOG_DBG("IC-SB Port_Binding '%s' on ts '%s' corresponds to a " "switch port, not considering for route collection.", @@ -3118,7 +2485,6 @@ ovn_db_run(struct ic_input *input_data, 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); - port_binding_run(eng_ctx, input_data); route_run(eng_ctx, input_data); sync_service_monitor(eng_ctx, input_data); } @@ -3524,6 +2890,7 @@ main(int argc, char *argv[]) stopwatch_create(OVN_IC_LOOP_STOPWATCH_NAME, SW_MS); stopwatch_create(IC_OVN_DB_RUN_STOPWATCH_NAME, SW_MS); stopwatch_create(OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME, SW_MS); + stopwatch_create(OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME, SW_MS); /* Initialize incremental processing engine for ovn-northd */ inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop, diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h index 9b0009274..ff6317786 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -55,8 +55,6 @@ struct ic_input { struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port; struct ovsdb_idl_index *icnbrec_transit_switch_by_name; struct ovsdb_idl_index *icsbrec_port_binding_by_az; - struct ovsdb_idl_index *icsbrec_port_binding_by_ts; - struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az; struct ovsdb_idl_index *icsbrec_route_by_az; struct ovsdb_idl_index *icsbrec_route_by_ts; struct ovsdb_idl_index *icsbrec_route_by_ts_az; @@ -76,16 +74,29 @@ struct ic_state { bool paused; }; +struct icsbrec_port_binding; + enum ic_datapath_type { IC_SWITCH, IC_ROUTER, IC_DATAPATH_MAX }; enum ic_port_binding_type { IC_SWITCH_PORT, IC_ROUTER_PORT, IC_PORT_MAX }; +const struct nbrec_logical_router_port * + get_lrp_by_lrp_name(struct ic_input *ic, const char *lrp_name); +const struct sbrec_port_binding * find_sb_pb_by_name( + struct ovsdb_idl_index *sbrec_port_binding_by_name, const char *name); +const struct nbrec_logical_switch * + find_ts_in_nb(struct ovsdb_idl_index *nbrec_ls_by_name, char *ts_name); +const struct nbrec_logical_switch_port * + get_lsp_by_ts_port_name(struct ovsdb_idl_index *nbrec_port_by_name, + const char *ts_port_name); +const struct sbrec_port_binding * + find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, + const char *name); +enum ic_port_binding_type + ic_pb_get_type(const struct icsbrec_port_binding *isb_pb); const struct icsbrec_availability_zone * - az_run(struct ovsdb_idl *ovnnb_idl, - struct ovsdb_idl *ovnisb_idl, + az_run(struct ovsdb_idl *ovnnb_idl, struct ovsdb_idl *ovnisb_idl, struct ovsdb_idl_txn *ovnisb_idl_txn); - -void ovn_db_run(struct ic_input *input_data, - struct ic_data *ic_data, +void ovn_db_run(struct ic_input *input_data, struct ic_data *ic_data, struct engine_context *eng_ctx); #endif /* OVN_IC_H */ diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index 4eef534ed..bf5da699c 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -43,5 +43,6 @@ #define OVN_IC_LOOP_STOPWATCH_NAME "ovn-ic-loop" #define IC_OVN_DB_RUN_STOPWATCH_NAME "ovn_db_run" #define OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME "enum_datapaths_run" +#define OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME "port_binding_run" #endif -- 2.34.1 -- _'Esta mensagem é direcionada apenas para os endereços constantes no cabeçalho inicial. Se você não está listado nos endereços constantes no cabeçalho, pedimos-lhe que desconsidere completamente o conteúdo dessa mensagem e cuja cópia, encaminhamento e/ou execução das ações citadas estão imediatamente anuladas e proibidas'._ * **'Apesar do Magazine Luiza tomar todas as precauções razoáveis para assegurar que nenhum vírus esteja presente nesse e-mail, a empresa não poderá aceitar a responsabilidade por quaisquer perdas ou danos causados por esse e-mail ou por seus anexos'.* _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
