From patchwork Mon Feb 9 18:28:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194713 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=LeW4ws5O; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tVv1Dxkz1xvc for ; Tue, 10 Feb 2026 05:28:39 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 9BDDA40B4C; Mon, 9 Feb 2026 18:28:37 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id OQZeiWzQ1P7O; Mon, 9 Feb 2026 18:28:34 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org B37F940B7C Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=LeW4ws5O Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp2.osuosl.org (Postfix) with ESMTPS id B37F940B7C; Mon, 9 Feb 2026 18:28:34 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 7E97DC0780; Mon, 9 Feb 2026 18:28:34 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id CD044C077E for ; Mon, 9 Feb 2026 18:28:33 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id B790783DA3 for ; Mon, 9 Feb 2026 18:28:28 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 4dFNRDrhJ-GY for ; Mon, 9 Feb 2026 18:28:27 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::b12d; helo=mail-yx1-xb12d.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org AA28C83DAB Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org AA28C83DAB Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=LeW4ws5O Received: from mail-yx1-xb12d.google.com (mail-yx1-xb12d.google.com [IPv6:2607:f8b0:4864:20::b12d]) by smtp1.osuosl.org (Postfix) with ESMTPS id AA28C83DAB for ; Mon, 9 Feb 2026 18:28:26 +0000 (UTC) Received: by mail-yx1-xb12d.google.com with SMTP id 956f58d0204a3-649d4690174so2863085d50.3 for ; Mon, 09 Feb 2026 10:28:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661705; x=1771266505; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JqsD+K6/GTuvFmQBfuibnOG6ufZ/j/3itwoHhpbn3Hk=; b=LeW4ws5OWwm/vgLPacw4Ec/IJVttsnQWPb2WBBskzyq9r79oY70oisQn/yZrC/xd5P fmdcAD7TrbQIT/Y39teHEYsZ+qeacaXSV7cNto8Y7etnZuA5hKhztCQAKmpE9Lyh4QOe KK8QH7ZdGf6MRswI3+2Q0O3e5+QOHoKwWwK7U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661705; x=1771266505; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=JqsD+K6/GTuvFmQBfuibnOG6ufZ/j/3itwoHhpbn3Hk=; b=kuLjOnYWovlKjnT5d8EBEr9Bhp4MvmVBMVBF7+79swXI9MHWhzvr76S1mC4HlzXYWw U08X8wSxPNgJ4WWSygHrhF0zRVLqR5EVeapkd898n+aJaS6VREehCkofXnFOd1UsMAJd O8uXO5RgXGAPKQS/BRaHfFhMIbf9cYcQ5RJ8I5qx2oC4q3/ZM70G/AHFEo2tl1qzt+Zd SNczOrNHRF/qKxZXD91r/rPnD/HGAg4PQfZSRaRjzes01i8ksNpfY0mFfZDB+lJcBWu6 iD8em5YLu3aZNxQeBc8h4cxLwzE+91cjJn0IwwrL6IWnwk2O9wx3YrOAOAoUiT0j8YYG +nRA== X-Gm-Message-State: AOJu0Yw9+iItIjMdEi0c8VjIcRdv8HjOooECBr0q74tJGXdGdM52LMmU 5qKlsx+0bLpkq8kahli1yjJk8wQqUzr1IzvSwExCTNWtzuD+k8cHqdWGGYV7uTx6fuLQB+6uXk6 j6jQA9/AtSQHxdF/K4CrpF1/UUs+qaHKz0Zf/Rjl3lBBQAG88P4pwtyFioOEOHYo= X-Gm-Gg: AZuq6aIaCpd+jwve44UtLkIGJl0VhtWBNyUBKW9aVjASaBvLEe0blbPxyPYyI4ejJrG SE3A/TbgdOZsvCj9oo1IUsSOdxlh0NHsoZYyuwgNLUiXSb1cX+mORyKI2sPW92G94gUuPrxOAZZ LWfIsMQXrFzXfRwH0S+eGlZEvdtK0qW/UulS0bhUEPHTv3cwhZG8mVnPjuNUdZKMhiPY4WktgJg iasvnthFtF39+ARTgUyBz5XIZ74iFUJHB5RIhrf4mKMu/K2sAp8eq+CYxlAx1w4lD+azb1+haUc WU4X5JHiWpxquvZ95LYyXUOhgzYeiO+BOa8sCuk3fZbwcirf+XNzfK0B8bA4DwrinJMtq5XFxZu 3jZD6vMfM88niRiFQC+VYii2Difyuw9hNZxWgn2TIdh0XkiUDTvDdoh8pmAnzQnNcJc2rLnoW48 Cq3QP5348AF52N9JTY0bfn+pullQODHZ8dF2CFMA== X-Received: by 2002:a53:d64c:0:b0:646:7a21:f03c with SMTP id 956f58d0204a3-649f21841c7mr7777410d50.81.1770661704293; Mon, 09 Feb 2026 10:28:24 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:23 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:06 -0300 Message-Id: <20260209182814.842-2-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 1/9] ovn-ic: Introduce structs ic_data and ic_input. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" 'struct ic_data' is used to hold the global state data for the incremental processing node 'en_ic' and 'struct ic_input' this will hold references to database tables and indexes. In order to achieve this, we refactor in the following way: * Move index and tables into the main 'ic' engine * Adjust inputs of function 'ovn_db_run()' inside the ic engine which in turn ends up calling upon the functions that manage the main groups of actions spreading the new structures: gateway_run(); enumerate_datapaths(); ts_run(); tr_run(); port_binding_run(); route_run(); sync_service_monitor(); * Refactor ovn-ic.c to use 'struct ic_data' and 'struct ic_input' where applicable. Signed-off-by: Paulo Guilherme Silva --- ic/en-ic.c | 168 ++++++++++- ic/en-ic.h | 2 +- ic/inc-proc-ic.c | 154 +++++++++- ic/inc-proc-ic.h | 8 +- ic/ovn-ic.c | 682 +++++++++++++++++++----------------------- ic/ovn-ic.h | 50 +++- lib/stopwatch-names.h | 2 + 7 files changed, 657 insertions(+), 409 deletions(-) -- 2.34.1 diff --git a/ic/en-ic.c b/ic/en-ic.c index 2db9d3b84..ce7d5de76 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -18,33 +18,185 @@ #include #include +/* OVS includes. */ +#include "openvswitch/vlog.h" + +/* OVN includes. */ +#include "ovn-ic.h" #include "en-ic.h" #include "lib/inc-proc-eng.h" +#include "lib/ovn-util.h" #include "lib/stopwatch-names.h" -#include "ovn-ic.h" -#include "openvswitch/vlog.h" +#include "coverage.h" +#include "stopwatch.h" +#include "stopwatch-names.h" VLOG_DEFINE_THIS_MODULE(en_ic); +COVERAGE_DEFINE(ic_run); + +void ic_destroy(struct ic_data *data); +void ic_init(struct ic_data *data); + +static void +ic_get_input_data(struct engine_node *node, + struct ic_input *input_data) +{ + /* Table references */ + input_data->nbrec_nb_global_table = + EN_OVSDB_GET(engine_get_input("NB_nb_global", node)); + input_data->nbrec_logical_switch_table = + EN_OVSDB_GET(engine_get_input("NB_logical_switch", node)); + input_data->nbrec_logical_router_table = + EN_OVSDB_GET(engine_get_input("NB_logical_router", node)); + input_data->sbrec_sb_global_table = + EN_OVSDB_GET(engine_get_input("SB_sb_global", node)); + input_data->sbrec_chassis_table = + EN_OVSDB_GET(engine_get_input("SB_chassis", node)); + input_data->icnbrec_ic_nb_global_table = + EN_OVSDB_GET(engine_get_input("ICNB_ic_nb_global", node)); + input_data->icnbrec_transit_switch_table = + EN_OVSDB_GET(engine_get_input("ICNB_transit_switch", node)); + input_data->icnbrec_transit_router_table = + EN_OVSDB_GET(engine_get_input("ICNB_transit_router", node)); + input_data->icsbrec_ic_sb_global_table = + EN_OVSDB_GET(engine_get_input("ICSB_ic_sb_global", node)); + input_data->icsbrec_availability_zone_table = + 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)); + + /* Indexes */ + input_data->nbrec_ls_by_name = + engine_ovsdb_node_get_index( + engine_get_input("NB_logical_switch", node), + "nbrec_ls_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->nbrec_lrp_by_name = + engine_ovsdb_node_get_index( + engine_get_input("NB_logical_router", node), + "nbrec_lrp_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->sbrec_chassis_by_name = + engine_ovsdb_node_get_index( + engine_get_input("SB_chassis", node), + "sbrec_chassis_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->sbrec_service_monitor_by_remote_type = + engine_ovsdb_node_get_index( + engine_get_input("SB_service_monitor", node), + "sbrec_service_monitor_by_remote_type"); + input_data->sbrec_service_monitor_by_ic_learned = + engine_ovsdb_node_get_index( + engine_get_input("SB_service_monitor", node), + "sbrec_service_monitor_by_ic_learned"); + input_data->sbrec_service_monitor_by_remote_type_logical_port = + engine_ovsdb_node_get_index( + engine_get_input("SB_service_monitor", node), + "sbrec_service_monitor_by_remote_type_logical_port"); + input_data->icnbrec_transit_switch_by_name = + engine_ovsdb_node_get_index( + engine_get_input("ICNB_transit_switch", node), + "icnbrec_transit_switch_by_name"); + 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->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), + "icsbrec_route_by_az"); + input_data->icsbrec_route_by_ts = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_route", node), + "icsbrec_route_by_ts"); + input_data->icsbrec_route_by_ts_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_route", node), + "icsbrec_route_by_ts_az"); + input_data->icsbrec_service_monitor_by_source_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_service_monitor", node), + "icsbrec_service_monitor_by_source_az"); + input_data->icsbrec_service_monitor_by_target_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_service_monitor", node), + "icsbrec_service_monitor_by_target_az"); + input_data->icsbrec_service_monitor_by_target_az_logical_port = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_service_monitor", node), + "icsbrec_service_monitor_by_target_az_logical_port"); +} enum engine_node_state -en_ic_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED) +en_ic_run(struct engine_node *node, void *data) { const struct engine_context *eng_ctx = engine_get_context(); - struct ic_context *ctx = eng_ctx->client_ctx; - ovn_db_run(ctx); + struct ic_input input_data; + + ic_destroy(data); + ic_init(data); + ic_get_input_data(node, &input_data); + input_data.runned_az = eng_ctx->client_ctx; + + COVERAGE_INC(ic_run); + stopwatch_start(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec()); + ovn_db_run(&input_data, data, (struct engine_context *) eng_ctx); + stopwatch_stop(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec()); return EN_UPDATED; } void * en_ic_init(struct engine_node *node OVS_UNUSED, - struct engine_arg *arg OVS_UNUSED) + struct engine_arg *arg OVS_UNUSED) +{ + struct ic_data *data = xzalloc(sizeof *data); + + ic_init(data); + + return data; +} + +void +en_ic_cleanup(void *data) +{ + ic_destroy(data); +} + +void +ic_destroy(struct ic_data *data) { - return NULL; + ovn_destroy_tnlids(&data->dp_tnlids); + shash_destroy(&data->isb_ts_dps); + shash_destroy(&data->isb_tr_dps); } void -en_ic_cleanup(void *data OVS_UNUSED) +ic_init(struct ic_data *data) { + hmap_init(&data->dp_tnlids); + shash_init(&data->isb_ts_dps); + shash_init(&data->isb_tr_dps); } diff --git a/ic/en-ic.h b/ic/en-ic.h index a4b75bb0e..ab1fbaf42 100644 --- a/ic/en-ic.h +++ b/ic/en-ic.h @@ -12,7 +12,7 @@ enum engine_node_state en_ic_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED); void *en_ic_init(struct engine_node *node OVS_UNUSED, - struct engine_arg *arg); + struct engine_arg *arg OVS_UNUSED); void en_ic_cleanup(void *data); #endif /* EN_IC_H */ diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index ba9fdeb9e..0160c3a3e 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -157,12 +157,13 @@ 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); +static ENGINE_NODE(ic, SB_WRITE); -void inc_proc_ic_init(struct ovsdb_idl_loop *nb, - struct ovsdb_idl_loop *sb, - struct ovsdb_idl_loop *icnb, - struct ovsdb_idl_loop *icsb) +void +inc_proc_ic_init(struct ovsdb_idl_loop *nb, + struct ovsdb_idl_loop *sb, + struct ovsdb_idl_loop *icnb, + struct ovsdb_idl_loop *icsb) { /* Define relationships between nodes where first argument is dependent * on the second argument */ @@ -187,11 +188,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_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_ic_sb_global, NULL); engine_add_input(&en_ic, &en_icsb_port_binding, NULL); - engine_add_input(&en_ic, &en_icsb_availability_zone, 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); @@ -203,22 +204,149 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb, .icsb_idl = icsb->idl, }; + /* create IDL indexes*/ + struct ovsdb_idl_index *nbrec_ls_by_name + = ovsdb_idl_index_create1(nb->idl, &nbrec_logical_switch_col_name); + struct ovsdb_idl_index *nbrec_lr_by_name + = ovsdb_idl_index_create1(nb->idl, &nbrec_logical_router_col_name); + struct ovsdb_idl_index *nbrec_lrp_by_name + = ovsdb_idl_index_create1(nb->idl, + &nbrec_logical_router_port_col_name); + struct ovsdb_idl_index *nbrec_port_by_name + = ovsdb_idl_index_create1(nb->idl, + &nbrec_logical_switch_port_col_name); + struct ovsdb_idl_index *sbrec_chassis_by_name + = ovsdb_idl_index_create1(sb->idl, &sbrec_chassis_col_name); + struct ovsdb_idl_index *sbrec_port_binding_by_name + = ovsdb_idl_index_create1(sb->idl, + &sbrec_port_binding_col_logical_port); + struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type + = ovsdb_idl_index_create1(sb->idl, + &sbrec_service_monitor_col_remote); + struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned + = ovsdb_idl_index_create1(sb->idl, + &sbrec_service_monitor_col_ic_learned); + struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port + = ovsdb_idl_index_create2(sb->idl, + &sbrec_service_monitor_col_remote, + &sbrec_service_monitor_col_logical_port); + struct ovsdb_idl_index *icnbrec_transit_switch_by_name + = ovsdb_idl_index_create1(icnb->idl, + &icnbrec_transit_switch_col_name); + struct ovsdb_idl_index *icsbrec_port_binding_by_az + = ovsdb_idl_index_create1(icsb->idl, + &icsbrec_port_binding_col_availability_zone); + struct ovsdb_idl_index *icsbrec_port_binding_by_ts + = ovsdb_idl_index_create1(icsb->idl, + &icsbrec_port_binding_col_transit_switch); + struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az + = ovsdb_idl_index_create2(icsb->idl, + &icsbrec_port_binding_col_transit_switch, + &icsbrec_port_binding_col_availability_zone); + struct ovsdb_idl_index *icsbrec_route_by_az + = ovsdb_idl_index_create1(icsb->idl, + &icsbrec_route_col_availability_zone); + struct ovsdb_idl_index *icsbrec_route_by_ts + = ovsdb_idl_index_create1(icsb->idl, + &icsbrec_route_col_transit_switch); + struct ovsdb_idl_index *icsbrec_route_by_ts_az + = ovsdb_idl_index_create2(icsb->idl, + &icsbrec_route_col_transit_switch, + &icsbrec_route_col_availability_zone); + struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az + = ovsdb_idl_index_create1(icsb->idl, + &icsbrec_service_monitor_col_source_availability_zone); + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az + = ovsdb_idl_index_create1(icsb->idl, + &icsbrec_service_monitor_col_target_availability_zone); + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port + = ovsdb_idl_index_create2(icsb->idl, + &icsbrec_service_monitor_col_target_availability_zone, + &icsbrec_service_monitor_col_logical_port); + engine_init(&en_ic, &engine_arg); + + /* indexes */ + engine_ovsdb_node_add_index(&en_nb_logical_switch, + "nbrec_ls_by_name", + nbrec_ls_by_name); + engine_ovsdb_node_add_index(&en_nb_logical_router, + "nbrec_lr_by_name", + nbrec_lr_by_name); + engine_ovsdb_node_add_index(&en_nb_logical_router, + "nbrec_lrp_by_name", + nbrec_lrp_by_name); + engine_ovsdb_node_add_index(&en_nb_logical_switch, + "nbrec_port_by_name", + nbrec_port_by_name); + engine_ovsdb_node_add_index(&en_sb_chassis, + "sbrec_chassis_by_name", + sbrec_chassis_by_name); + engine_ovsdb_node_add_index(&en_sb_port_binding, + "sbrec_port_binding_by_name", + sbrec_port_binding_by_name); + engine_ovsdb_node_add_index(&en_sb_service_monitor, + "sbrec_service_monitor_by_remote_type", + sbrec_service_monitor_by_remote_type); + engine_ovsdb_node_add_index(&en_sb_service_monitor, + "sbrec_service_monitor_by_ic_learned", + sbrec_service_monitor_by_ic_learned); + engine_ovsdb_node_add_index(&en_sb_service_monitor, + "sbrec_service_monitor_by_remote_type_logical_port", + sbrec_service_monitor_by_remote_type_logical_port); + engine_ovsdb_node_add_index(&en_icnb_transit_switch, + "icnbrec_transit_switch_by_name", + icnbrec_transit_switch_by_name); + engine_ovsdb_node_add_index(&en_icsb_port_binding, + "icsbrec_port_binding_by_az", + icsbrec_port_binding_by_az); + engine_ovsdb_node_add_index(&en_icsb_port_binding, + "icsbrec_port_binding_by_ts", + icsbrec_port_binding_by_ts); + engine_ovsdb_node_add_index(&en_icsb_port_binding, + "icsbrec_port_binding_by_ts_az", + icsbrec_port_binding_by_ts_az); + engine_ovsdb_node_add_index(&en_icsb_route, + "icsbrec_route_by_az", + icsbrec_route_by_az); + engine_ovsdb_node_add_index(&en_icsb_route, + "icsbrec_route_by_ts", + icsbrec_route_by_ts); + engine_ovsdb_node_add_index(&en_icsb_route, + "icsbrec_route_by_ts_az", + icsbrec_route_by_ts_az); + engine_ovsdb_node_add_index(&en_icsb_service_monitor, + "icsbrec_service_monitor_by_source_az", + icsbrec_service_monitor_by_source_az); + engine_ovsdb_node_add_index(&en_icsb_service_monitor, + "icsbrec_service_monitor_by_target_az", + icsbrec_service_monitor_by_target_az); + engine_ovsdb_node_add_index(&en_icsb_service_monitor, + "icsbrec_service_monitor_by_target_az_logical_port", + icsbrec_service_monitor_by_target_az_logical_port); } /* Returns true if the incremental processing ended up updating nodes. */ bool -inc_proc_ic_run(struct ic_context *ctx, - struct ic_engine_context *ic_eng_ctx) +inc_proc_ic_run(struct ovsdb_idl_txn *ovnnb_txn, + struct ovsdb_idl_txn *ovnsb_txn, + struct ovsdb_idl_txn *ovninb_txn, + struct ovsdb_idl_txn *ovnisb_txn, + struct ic_engine_context *ctx, + const struct icsbrec_availability_zone *runned_az) { - ovs_assert(ctx->ovnnb_txn && ctx->ovnsb_txn && - ctx->ovninb_txn && ctx->ovnisb_txn); + ovs_assert(ovnnb_txn && ovnsb_txn && + ovninb_txn && ovnisb_txn); int64_t start = time_msec(); engine_init_run(); struct engine_context eng_ctx = { - .client_ctx = ctx, + .client_ctx = (void *) runned_az, + .ovnnb_idl_txn = ovnnb_txn, + .ovnsb_idl_txn = ovnsb_txn, + .ovninb_idl_txn = ovninb_txn, + .ovnisb_idl_txn = ovnisb_txn, }; engine_set_context(&eng_ctx); @@ -241,7 +369,7 @@ inc_proc_ic_run(struct ic_context *ctx, int64_t now = time_msec(); /* Postpone the next run by length of current run with maximum capped * by "northd-backoff-interval-ms" interval. */ - ic_eng_ctx->next_run_ms = now + MIN(now - start, ic_eng_ctx->backoff_ms); + ctx->next_run_ms = now + MIN(now - start, ctx->backoff_ms); return engine_has_updated(); } diff --git a/ic/inc-proc-ic.h b/ic/inc-proc-ic.h index 9af147fb3..c50c1b02e 100644 --- a/ic/inc-proc-ic.h +++ b/ic/inc-proc-ic.h @@ -21,8 +21,12 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb, struct ovsdb_idl_loop *icnb, struct ovsdb_idl_loop *icsb); -bool inc_proc_ic_run(struct ic_context *ctx, - struct ic_engine_context *ic_eng_ctx); +bool inc_proc_ic_run(struct ovsdb_idl_txn *ovnnb_txn, + struct ovsdb_idl_txn *ovnsb_txn, + struct ovsdb_idl_txn *ovninb_txn, + struct ovsdb_idl_txn *ovnisb_txn, + struct ic_engine_context *ctx, + const struct icsbrec_availability_zone *runned_az); void inc_proc_ic_cleanup(void); bool inc_proc_ic_can_run(struct ic_engine_context *ctx); diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 41596d73a..8327054de 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -48,6 +48,8 @@ #include "vec.h" #include "inc-proc-ic.h" #include "ovn-ic.h" +#include "stopwatch-names.h" +#include "stopwatch.h" VLOG_DEFINE_THIS_MODULE(ovn_ic); @@ -99,11 +101,13 @@ Options:\n\ stream_usage("database", true, true, false); } -static const struct icsbrec_availability_zone * -az_run(struct ic_context *ctx) +const struct icsbrec_availability_zone * +az_run(struct ovsdb_idl *ovnnb_idl, + struct ovsdb_idl *ovnisb_idl, + struct ovsdb_idl_txn *ovnisb_idl_txn) { const struct nbrec_nb_global *nb_global = - nbrec_nb_global_first(ctx->ovnnb_idl); + nbrec_nb_global_first(ovnnb_idl); if (!nb_global) { VLOG_INFO("NB Global not exist."); @@ -115,8 +119,8 @@ az_run(struct ic_context *ctx) * "ovn-ic-sbctl destroy avail ". */ static char *az_name; const struct icsbrec_availability_zone *az; - if (ctx->ovnisb_txn && az_name && strcmp(az_name, nb_global->name)) { - ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) { + if (ovnisb_idl_txn && az_name && strcmp(az_name, nb_global->name)) { + ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ovnisb_idl) { /* AZ name update locally need to update az in ISB. */ if (nb_global->name[0] && !strcmp(az->name, az_name)) { icsbrec_availability_zone_set_name(az, nb_global->name); @@ -138,24 +142,22 @@ az_run(struct ic_context *ctx) az_name = xstrdup(nb_global->name); } - if (ctx->ovnisb_txn) { - ovsdb_idl_txn_add_comment(ctx->ovnisb_txn, "AZ %s", az_name); + if (ovnisb_idl_txn) { + ovsdb_idl_txn_add_comment(ovnisb_idl_txn, "AZ %s", az_name); } - ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ctx->ovnisb_idl) { + ICSBREC_AVAILABILITY_ZONE_FOR_EACH (az, ovnisb_idl) { if (!strcmp(az->name, az_name)) { - ctx->runned_az = az; - return az; + return (struct icsbrec_availability_zone *) az; } } /* Create AZ in ISB */ - if (ctx->ovnisb_txn) { + if (ovnisb_idl_txn) { VLOG_INFO("Register AZ %s to interconnection DB.", az_name); - az = icsbrec_availability_zone_insert(ctx->ovnisb_txn); + az = icsbrec_availability_zone_insert(ovnisb_idl_txn); icsbrec_availability_zone_set_name(az, az_name); - ctx->runned_az = az; - return az; + return (struct icsbrec_availability_zone *) az; } return NULL; } @@ -191,11 +193,14 @@ ic_pb_get_type(const struct icsbrec_port_binding *isb_pb) } static void -enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids, - struct shash *isb_ts_dps, struct shash *isb_tr_dps) +enumerate_datapaths(struct ic_input *ic, + struct hmap *dp_tnlids, + struct shash *isb_ts_dps, + struct shash *isb_tr_dps) { const struct icsbrec_datapath_binding *isb_dp; - ICSBREC_DATAPATH_BINDING_FOR_EACH (isb_dp, ctx->ovnisb_idl) { + ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (isb_dp, + ic->icsbrec_datapath_binding_table) { ovn_add_tnlid(dp_tnlids, isb_dp->tunnel_key); enum ic_datapath_type dp_type = ic_dp_get_type(isb_dp); @@ -210,18 +215,20 @@ enumerate_datapaths(struct ic_context *ctx, struct hmap *dp_tnlids, } static void -ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, +ts_run(struct engine_context *ctx, + struct ic_input *ic, + struct hmap *dp_tnlids, struct shash *isb_ts_dps) { const struct icnbrec_transit_switch *ts; bool dp_key_refresh = false; bool vxlan_mode = false; const struct icnbrec_ic_nb_global *ic_nb = - icnbrec_ic_nb_global_first(ctx->ovninb_idl); + icnbrec_ic_nb_global_table_first(ic->icnbrec_ic_nb_global_table); if (ic_nb && smap_get_bool(&ic_nb->options, "vxlan_mode", false)) { const struct icsbrec_encap *encap; - ICSBREC_ENCAP_FOR_EACH (encap, ctx->ovnisb_idl) { + ICSBREC_ENCAP_TABLE_FOR_EACH (encap, ic->icsbrec_encap_table) { if (!strcmp(encap->type, "vxlan")) { vxlan_mode = true; break; @@ -230,12 +237,13 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, } /* Sync INB TS to AZ NB */ - if (ctx->ovnnb_txn) { + if (ctx->ovnnb_idl_txn) { struct shash nb_tses = SHASH_INITIALIZER(&nb_tses); const struct nbrec_logical_switch *ls; /* Get current NB Logical_Switch with other_config:interconn-ts */ - NBREC_LOGICAL_SWITCH_FOR_EACH (ls, ctx->ovnnb_idl) { + NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH (ls, + ic->nbrec_logical_switch_table) { const char *ts_name = smap_get(&ls->other_config, "interconn-ts"); if (ts_name) { shash_add(&nb_tses, ts_name, ls); @@ -243,10 +251,11 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, } /* Create/update NB Logical_Switch for each TS */ - ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) { + ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, + ic->icnbrec_transit_switch_table) { ls = shash_find_and_delete(&nb_tses, ts->name); if (!ls) { - ls = nbrec_logical_switch_insert(ctx->ovnnb_txn); + ls = nbrec_logical_switch_insert(ctx->ovnnb_idl_txn); nbrec_logical_switch_set_name(ls, ts->name); nbrec_logical_switch_update_other_config_setkey(ls, "interconn-ts", @@ -294,9 +303,10 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, /* Sync TS between INB and ISB. This is performed after syncing with AZ * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to * AZ. */ - if (ctx->ovnisb_txn) { + if (ctx->ovnisb_idl_txn) { /* Create ISB Datapath_Binding */ - ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) { + ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, + ic->icnbrec_transit_switch_table) { const struct icsbrec_datapath_binding *isb_dp = shash_find_and_delete(isb_ts_dps, ts->name); if (!isb_dp) { @@ -307,7 +317,7 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, continue; } - isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_txn); + isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn); icsbrec_datapath_binding_set_transit_switch(isb_dp, ts->name); icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); } else if (dp_key_refresh) { @@ -337,14 +347,17 @@ ts_run(struct ic_context *ctx, struct hmap *dp_tnlids, } static void -tr_run(struct ic_context *ctx, struct hmap *dp_tnlids, +tr_run(struct engine_context *ctx, + struct ic_input *ic, + struct hmap *dp_tnlids, struct shash *isb_tr_dps) { const struct nbrec_logical_router *lr; - if (ctx->ovnnb_txn) { + if (ctx->ovnnb_idl_txn) { struct shash nb_tres = SHASH_INITIALIZER(&nb_tres); - NBREC_LOGICAL_ROUTER_FOR_EACH (lr, ctx->ovnnb_idl) { + NBREC_LOGICAL_ROUTER_TABLE_FOR_EACH (lr, + ic->nbrec_logical_router_table) { const char *tr_name = smap_get(&lr->options, "interconn-tr"); if (tr_name) { shash_add(&nb_tres, tr_name, lr); @@ -352,10 +365,11 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids, } const struct icnbrec_transit_router *tr; - ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) { + ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, + ic->icnbrec_transit_router_table) { lr = shash_find_and_delete(&nb_tres, tr->name); if (!lr) { - lr = nbrec_logical_router_insert(ctx->ovnnb_txn); + lr = nbrec_logical_router_insert(ctx->ovnnb_idl_txn); nbrec_logical_router_set_name(lr, tr->name); nbrec_logical_router_update_options_setkey( lr, "interconn-tr", tr->name); @@ -383,10 +397,11 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids, /* Sync TR between INB and ISB. This is performed after syncing with AZ * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to * AZ. */ - if (ctx->ovnisb_txn) { + if (ctx->ovnisb_idl_txn) { /* Create ISB Datapath_Binding */ const struct icnbrec_transit_router *tr; - ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) { + ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, + ic->icnbrec_transit_router_table) { char *uuid_str = uuid_to_string(&tr->header_.uuid); struct icsbrec_datapath_binding *isb_dp = shash_find_and_delete(isb_tr_dps, uuid_str); @@ -399,7 +414,7 @@ tr_run(struct ic_context *ctx, struct hmap *dp_tnlids, continue; } - isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_txn); + isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn); icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, &tr->header_.uuid, 1); @@ -451,7 +466,7 @@ is_gateway_data_changed(const struct icsbrec_gateway *gw, } static void -sync_isb_gw_to_sb(struct ic_context *ctx, +sync_isb_gw_to_sb(struct engine_context *ctx, const struct icsbrec_gateway *gw, const struct sbrec_chassis *chassis) { @@ -464,7 +479,7 @@ sync_isb_gw_to_sb(struct ic_context *ctx, 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_txn); + 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); @@ -476,7 +491,7 @@ sync_isb_gw_to_sb(struct ic_context *ctx, } static void -sync_sb_gw_to_isb(struct ic_context *ctx, +sync_sb_gw_to_isb(struct engine_context *ctx, const struct sbrec_chassis *chassis, const struct icsbrec_gateway *gw) { @@ -488,7 +503,7 @@ sync_sb_gw_to_isb(struct ic_context *ctx, 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_txn); + 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); @@ -504,17 +519,18 @@ sync_sb_gw_to_isb(struct ic_context *ctx, } static void -gateway_run(struct ic_context *ctx) +gateway_run(struct engine_context *ctx, + struct ic_input *ic) { - if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) { + 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_FOR_EACH (gw, ctx->ovnisb_idl) { - if (gw->availability_zone == ctx->runned_az) { + 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); @@ -522,12 +538,12 @@ gateway_run(struct ic_context *ctx) } const struct sbrec_chassis *chassis; - SBREC_CHASSIS_FOR_EACH (chassis, ctx->ovnsb_idl) { + 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_txn); - icsbrec_gateway_set_availability_zone(gw, ctx->runned_az); + 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)) { @@ -553,7 +569,7 @@ gateway_run(struct ic_context *ctx) /* Create SB chassis for remote gateways in ISB */ SHASH_FOR_EACH (node, &remote_gws) { gw = node->data; - chassis = sbrec_chassis_insert(ctx->ovnsb_txn); + chassis = sbrec_chassis_insert(ctx->ovnsb_idl_txn); sbrec_chassis_set_name(chassis, gw->name); sync_isb_gw_to_sb(ctx, gw, chassis); } @@ -561,15 +577,15 @@ gateway_run(struct ic_context *ctx) } static const struct nbrec_logical_switch * -find_ts_in_nb(struct ic_context *ctx, char *ts_name) +find_ts_in_nb(struct ic_input *ic, char *ts_name) { const struct nbrec_logical_switch *key = - nbrec_logical_switch_index_init_row(ctx->nbrec_ls_by_name); + nbrec_logical_switch_index_init_row(ic->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, ctx->nbrec_ls_by_name) { + NBREC_LOGICAL_SWITCH_FOR_EACH_EQUAL (ls, key, ic->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; @@ -585,15 +601,15 @@ find_ts_in_nb(struct ic_context *ctx, char *ts_name) } static const struct nbrec_logical_router * -find_tr_in_nb(struct ic_context *ctx, char *tr_name) +find_tr_in_nb(struct ic_input *ic, char *tr_name) { const struct nbrec_logical_router *key = - nbrec_logical_router_index_init_row(ctx->nbrec_lr_by_name); + 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, ctx->nbrec_lr_by_name) { + NBREC_LOGICAL_ROUTER_FOR_EACH_EQUAL (lr, key, ic->nbrec_lr_by_name) { if (smap_get(&lr->options, "interconn-tr")) { found = true; break; @@ -624,7 +640,7 @@ find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, } static const struct sbrec_port_binding * -find_peer_port(struct ic_context *ctx, +find_peer_port(struct ic_input *ic, const struct sbrec_port_binding *sb_pb) { const char *peer_name = smap_get(&sb_pb->options, "peer"); @@ -632,61 +648,61 @@ find_peer_port(struct ic_context *ctx, return NULL; } - return find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, peer_name); + 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_context *ctx, +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(ctx->sbrec_port_binding_by_name, crp_name); + 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_context *ctx, +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(ctx, sb_pb); + const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb); if (!peer) { return NULL; } - return find_crp_from_lrp(ctx, peer); + return find_crp_from_lrp(ic, peer); } static const struct nbrec_logical_switch_port * -get_lsp_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name) +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(ctx->nbrec_port_by_name); + 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(ctx->nbrec_port_by_name, key); + 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_context *ctx, +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(ctx, sb_pb->logical_port); + 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(ctx, sb_pb); + const struct sbrec_port_binding *peer = find_peer_port(ic, sb_pb); if (!peer) { return NULL; } @@ -695,14 +711,14 @@ get_lp_address_for_sb_pb(struct ic_context *ctx, } static const struct sbrec_chassis * -find_sb_chassis(struct ic_context *ctx, const char *name) +find_sb_chassis(struct ic_input *ic, const char *name) { const struct sbrec_chassis *key = - sbrec_chassis_index_init_row(ctx->sbrec_chassis_by_name); + 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(ctx->sbrec_chassis_by_name, key); + sbrec_chassis_index_find(ic->sbrec_chassis_by_name, key); sbrec_chassis_index_destroy_row(key); return chassis; @@ -741,11 +757,11 @@ sync_lrp_tnl_key(const struct nbrec_logical_router_port *lrp, } static bool -get_router_uuid_by_sb_pb(struct ic_context *ctx, +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(ctx, sb_pb); + const struct sbrec_port_binding *router_pb = find_peer_port(ic, sb_pb); if (!router_pb || !router_pb->datapath) { return NULL; } @@ -754,12 +770,12 @@ get_router_uuid_by_sb_pb(struct ic_context *ctx, } static void -update_isb_pb_external_ids(struct ic_context *ctx, +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(ctx, sb_pb, &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); @@ -784,13 +800,13 @@ update_isb_pb_external_ids(struct ic_context *ctx, * - Sync tunnel key from ISB to NB. */ static void -sync_local_port(struct ic_context *ctx, +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(ctx, sb_pb); + 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); @@ -804,7 +820,7 @@ sync_local_port(struct ic_context *ctx, } /* Sync gateway from SB to ISB */ - const struct sbrec_port_binding *crp = find_crp_for_sb_pb(ctx, sb_pb); + 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); @@ -820,7 +836,7 @@ sync_local_port(struct ic_context *ctx, } /* Sync external_ids:router-id to ISB */ - update_isb_pb_external_ids(ctx, sb_pb, isb_pb); + 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); @@ -831,7 +847,7 @@ sync_local_port(struct ic_context *ctx, * - Sync gateway from ISB to SB */ static void -sync_remote_port(struct ic_context *ctx, +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) @@ -861,7 +877,7 @@ sync_remote_port(struct ic_context *ctx, 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(ctx, isb_pb->gateway); + 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.", @@ -924,12 +940,12 @@ sync_router_port(const struct icsbrec_port_binding *isb_pb, } static void -create_nb_lsp(struct ic_context *ctx, +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_txn); + 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"); @@ -953,7 +969,7 @@ allocate_port_key(struct hmap *pb_tnlids) } static const struct icsbrec_port_binding * -create_isb_pb(struct ic_context *ctx, const char *logical_port, +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) @@ -964,7 +980,7 @@ create_isb_pb(struct ic_context *ctx, const char *logical_port, } const struct icsbrec_port_binding *isb_pb = - icsbrec_port_binding_insert(ctx->ovnisb_txn); + 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); @@ -975,25 +991,25 @@ create_isb_pb(struct ic_context *ctx, const char *logical_port, } static const struct nbrec_logical_router_port * -get_lrp_by_lrp_name(struct ic_context *ctx, const char *lrp_name) +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(ctx->nbrec_lrp_by_name); + 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(ctx->nbrec_lrp_by_name, lrp_key); + 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_context *ctx, const char *chassis_name) +trp_is_remote(struct ic_input *ic, const char *chassis_name) { if (chassis_name) { const struct sbrec_chassis *chassis = - find_sb_chassis(ctx, chassis_name); + find_sb_chassis(ic, chassis_name); if (chassis) { return smap_get_bool(&chassis->other_config, "is-remote", false); } else { @@ -1005,11 +1021,11 @@ trp_is_remote(struct ic_context *ctx, const char *chassis_name) } static struct nbrec_logical_router_port * -lrp_create(struct ic_context *ctx, const struct nbrec_logical_router *lr, +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_txn); + 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", @@ -1019,20 +1035,20 @@ lrp_create(struct ic_context *ctx, const struct nbrec_logical_router *lr, } static void -sync_ts_isb_pb(struct ic_context *ctx, const struct sbrec_port_binding *sb_pb, +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(ctx, sb_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(ctx, sb_pb); + 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(ctx, sb_pb, isb_pb); + 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 @@ -1043,16 +1059,18 @@ sync_ts_isb_pb(struct ic_context *ctx, const struct sbrec_port_binding *sb_pb, } static const struct sbrec_port_binding * -find_lsp_in_sb(struct ic_context *ctx, +find_lsp_in_sb(struct ic_input *ic, const struct nbrec_logical_switch_port *lsp) { - return find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, lsp->name); + return find_sb_pb_by_name(ic->sbrec_port_binding_by_name, lsp->name); } static void -port_binding_run(struct ic_context *ctx) +port_binding_run(struct engine_context *ctx, + struct ic_input *ic) { - if (!ctx->ovnisb_txn || !ctx->ovnnb_txn || !ctx->ovnsb_txn) { + if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn + || !ctx->ovnsb_idl_txn) { return; } @@ -1065,12 +1083,12 @@ port_binding_run(struct ic_context *ctx) const struct icsbrec_port_binding *isb_pb; const struct icsbrec_port_binding *isb_pb_key = - icsbrec_port_binding_index_init_row(ctx->icsbrec_port_binding_by_az); + icsbrec_port_binding_index_init_row(ic->icsbrec_port_binding_by_az); icsbrec_port_binding_index_set_availability_zone(isb_pb_key, - ctx->runned_az); + ic->runned_az); ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, - ctx->icsbrec_port_binding_by_az) { + 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); @@ -1081,8 +1099,9 @@ port_binding_run(struct ic_context *ctx) const struct sbrec_port_binding *sb_pb; const struct icnbrec_transit_switch *ts; - ICNBREC_TRANSIT_SWITCH_FOR_EACH (ts, ctx->ovninb_idl) { - const struct nbrec_logical_switch *ls = find_ts_in_nb(ctx, ts->name); + 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; @@ -1091,12 +1110,12 @@ port_binding_run(struct ic_context *ctx) struct shash remote_pbs = SHASH_INITIALIZER(&remote_pbs); isb_pb_key = icsbrec_port_binding_index_init_row( - ctx->icsbrec_port_binding_by_ts); + 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, - ctx->icsbrec_port_binding_by_ts) { - if (isb_pb->availability_zone == ctx->runned_az) { + 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); @@ -1113,18 +1132,18 @@ port_binding_run(struct ic_context *ctx) if (!strcmp(lsp->type, "router") || !strcmp(lsp->type, "switch")) { /* The port is local. */ - sb_pb = find_lsp_in_sb(ctx, lsp); + 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, ctx->runned_az, ts->name, + ctx, sb_pb->logical_port, ic->runned_az, ts->name, &ts->header_.uuid, "transit-switch-port", &pb_tnlids); - sync_ts_isb_pb(ctx, sb_pb, isb_pb); + sync_ts_isb_pb(ic, sb_pb, isb_pb); } else { - sync_local_port(ctx, isb_pb, sb_pb, lsp); + sync_local_port(ic, isb_pb, sb_pb, lsp); } if (isb_pb->type) { @@ -1142,11 +1161,11 @@ port_binding_run(struct ic_context *ctx) if (!isb_pb) { nbrec_logical_switch_update_ports_delvalue(ls, lsp); } else { - sb_pb = find_lsp_in_sb(ctx, lsp); + sb_pb = find_lsp_in_sb(ic, lsp); if (!sb_pb) { continue; } - sync_remote_port(ctx, isb_pb, lsp, sb_pb); + sync_remote_port(ic, isb_pb, lsp, sb_pb); } } else { VLOG_DBG("Ignore lsp %s on ts %s with type %s.", @@ -1174,8 +1193,9 @@ port_binding_run(struct ic_context *ctx) shash_destroy(&switch_all_local_pbs); const struct icnbrec_transit_router *tr; - ICNBREC_TRANSIT_ROUTER_FOR_EACH (tr, ctx->ovninb_idl) { - const struct nbrec_logical_router *lr = find_tr_in_nb(ctx, tr->name); + 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; @@ -1193,12 +1213,12 @@ port_binding_run(struct ic_context *ctx) } isb_pb_key = icsbrec_port_binding_index_init_row( - ctx->icsbrec_port_binding_by_ts); + 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, - ctx->icsbrec_port_binding_by_ts) { - if (isb_pb->availability_zone == ctx->runned_az) { + 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); @@ -1211,12 +1231,12 @@ port_binding_run(struct ic_context *ctx) for (size_t i = 0; i < tr->n_ports; i++) { const struct icnbrec_transit_router_port *trp = tr->ports[i]; - if (trp_is_remote(ctx, trp->chassis)) { + 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, ctx->runned_az, + 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); @@ -1548,8 +1568,8 @@ add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix, uint hash = ic_route_hash(&prefix, plen, &nexthop, origin, route_table); - if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, route_table, - hash)) { + if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, + route_table, hash)) { struct ic_route_info *ic_route = xzalloc(sizeof *ic_route); ic_route->prefix = prefix; ic_route->plen = plen; @@ -1921,11 +1941,11 @@ route_need_learn(const struct nbrec_logical_router *lr, } static const char * -get_lrp_name_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name) +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(ctx, ts_port_name); + nb_lsp = get_lsp_by_ts_port_name(ic, ts_port_name); if (!nb_lsp) { return NULL; } @@ -1934,12 +1954,12 @@ get_lrp_name_by_ts_port_name(struct ic_context *ctx, const char *ts_port_name) } static const struct nbrec_logical_router_port * -find_lrp_of_nexthop(struct ic_context *ctx, +find_lrp_of_nexthop(struct ic_input *ic, const struct icsbrec_route *isb_route) { const struct nbrec_logical_router_port *lrp; const struct nbrec_logical_switch *ls; - ls = find_ts_in_nb(ctx, isb_route->transit_switch); + ls = find_ts_in_nb(ic, isb_route->transit_switch); if (!ls) { return NULL; } @@ -1951,13 +1971,13 @@ find_lrp_of_nexthop(struct ic_context *ctx, for (size_t i = 0; i < ls->n_ports; i++) { char *lsp_name = ls->ports[i]->name; - const char *lrp_name = get_lrp_name_by_ts_port_name(ctx, + const char *lrp_name = get_lrp_name_by_ts_port_name(ic, lsp_name); if (!lrp_name) { continue; } - lrp = get_lrp_by_lrp_name(ctx, lrp_name); + lrp = get_lrp_by_lrp_name(ic, lrp_name); if (!lrp) { continue; } @@ -1995,13 +2015,13 @@ find_lrp_of_nexthop(struct ic_context *ctx, } static bool -lrp_is_ts_port(struct ic_context *ctx, struct ic_router_info *ic_lr, +lrp_is_ts_port(struct ic_input *ic, struct ic_router_info *ic_lr, const char *lrp_name) { const struct icsbrec_port_binding *isb_pb; const char *ts_lrp_name; VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { - ts_lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port); + ts_lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); if (!strcmp(ts_lrp_name, lrp_name)) { return true; } @@ -2010,14 +2030,15 @@ lrp_is_ts_port(struct ic_context *ctx, struct ic_router_info *ic_lr, } static void -sync_learned_routes(struct ic_context *ctx, +sync_learned_routes(struct engine_context *ctx, + struct ic_input *ic, struct ic_router_info *ic_lr) { - ovs_assert(ctx->ovnnb_txn); + ovs_assert(ctx->ovnnb_idl_txn); const struct icsbrec_route *isb_route, *isb_route_key; const struct nbrec_nb_global *nb_global = - nbrec_nb_global_first(ctx->ovnnb_idl); + nbrec_nb_global_table_first(ic->nbrec_nb_global_table); ovs_assert(nb_global); const char *lrp_name, *ts_route_table, *route_filter_tag; @@ -2027,8 +2048,8 @@ sync_learned_routes(struct ic_context *ctx, if (!strcmp(isb_pb->address, "")) { continue; } - lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port); - lrp = get_lrp_by_lrp_name(ctx, lrp_name); + lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); + lrp = get_lrp_by_lrp_name(ic, lrp_name); if (lrp) { ts_route_table = smap_get_def(&lrp->options, "route_table", ""); route_filter_tag = smap_get_def(&lrp->options, @@ -2038,12 +2059,12 @@ sync_learned_routes(struct ic_context *ctx, route_filter_tag = ""; } - isb_route_key = icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts); + isb_route_key = icsbrec_route_index_init_row(ic->icsbrec_route_by_ts); icsbrec_route_index_set_transit_switch(isb_route_key, isb_pb->transit_switch); ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, - ctx->icsbrec_route_by_ts) { + ic->icsbrec_route_by_ts) { /* Filters ICSB routes, skipping those that either belong to * current logical router or are legacy routes from the current * availability zone (withoud lr-id). @@ -2055,7 +2076,7 @@ sync_learned_routes(struct ic_context *ctx, || uuid_equals(&ic_lr->lr->header_.uuid, &lr_uuid)) { continue; } - } else if (isb_route->availability_zone == ctx->runned_az) { + } else if (isb_route->availability_zone == ic->runned_az) { continue; } @@ -2117,7 +2138,8 @@ sync_learned_routes(struct ic_context *ctx, } else { /* Create the missing route in NB. */ const struct nbrec_logical_router_static_route *nb_route = - nbrec_logical_router_static_route_insert(ctx->ovnnb_txn); + nbrec_logical_router_static_route_insert( + ctx->ovnnb_idl_txn); nbrec_logical_router_static_route_set_ip_prefix(nb_route, isb_route->ip_prefix); nbrec_logical_router_static_route_set_nexthop(nb_route, @@ -2190,20 +2212,21 @@ ad_route_sync_external_ids(const struct ic_route_info *route_adv, /* Sync routes from routes_ad to IC-SB. */ static void -advertise_routes(struct ic_context *ctx, +advertise_routes(struct engine_context *ctx, + struct ic_input *ic, const struct icsbrec_availability_zone *az, const char *ts_name, struct hmap *routes_ad) { - ovs_assert(ctx->ovnisb_txn); + ovs_assert(ctx->ovnisb_idl_txn); const struct icsbrec_route *isb_route; const struct icsbrec_route *isb_route_key = - icsbrec_route_index_init_row(ctx->icsbrec_route_by_ts_az); + icsbrec_route_index_init_row(ic->icsbrec_route_by_ts_az); icsbrec_route_index_set_transit_switch(isb_route_key, ts_name); icsbrec_route_index_set_availability_zone(isb_route_key, az); ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, - ctx->icsbrec_route_by_ts_az) { + ic->icsbrec_route_by_ts_az) { struct in6_addr prefix, nexthop; unsigned int plen; @@ -2237,7 +2260,7 @@ advertise_routes(struct ic_context *ctx, /* Create the missing routes in IC-SB */ struct ic_route_info *route_adv; HMAP_FOR_EACH_SAFE (route_adv, node, routes_ad) { - isb_route = icsbrec_route_insert(ctx->ovnisb_txn); + isb_route = icsbrec_route_insert(ctx->ovnisb_idl_txn); icsbrec_route_set_transit_switch(isb_route, ts_name); icsbrec_route_set_availability_zone(isb_route, az); @@ -2273,7 +2296,7 @@ advertise_routes(struct ic_context *ctx, } static void -build_ts_routes_to_adv(struct ic_context *ctx, +build_ts_routes_to_adv(struct ic_input *ic, struct ic_router_info *ic_lr, struct hmap *routes_ad, struct lport_addresses *ts_port_addrs, @@ -2310,7 +2333,7 @@ build_ts_routes_to_adv(struct ic_context *ctx, /* Check directly-connected subnets of the LR */ for (int i = 0; i < lr->n_ports; i++) { const struct nbrec_logical_router_port *lrp = lr->ports[i]; - if (!lrp_is_ts_port(ctx, ic_lr, lrp->name)) { + if (!lrp_is_ts_port(ic, ic_lr, lrp->name)) { for (int j = 0; j < lrp->n_networks; j++) { add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp, ts_port_addrs, @@ -2356,12 +2379,13 @@ build_ts_routes_to_adv(struct ic_context *ctx, } static void -collect_lr_routes(struct ic_context *ctx, +collect_lr_routes(struct ic_input *ic, struct ic_router_info *ic_lr, struct shash *routes_ad_by_ts) { const struct nbrec_nb_global *nb_global = - nbrec_nb_global_first(ctx->ovnnb_idl); + nbrec_nb_global_table_first(ic->nbrec_nb_global_table); + ovs_assert(nb_global); const struct icsbrec_port_binding *isb_pb; @@ -2374,10 +2398,10 @@ collect_lr_routes(struct ic_context *ctx, const struct icnbrec_transit_switch *t_sw; VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { key = icnbrec_transit_switch_index_init_row( - ctx->icnbrec_transit_switch_by_name); + ic->icnbrec_transit_switch_by_name); icnbrec_transit_switch_index_set_name(key, isb_pb->transit_switch); t_sw = icnbrec_transit_switch_index_find( - ctx->icnbrec_transit_switch_by_name, key); + ic->icnbrec_transit_switch_by_name, key); icnbrec_transit_switch_index_destroy_row(key); if (!t_sw) { continue; @@ -2398,8 +2422,8 @@ collect_lr_routes(struct ic_context *ctx, ic_lr->lr->name); continue; } - lrp_name = get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port); - lrp = get_lrp_by_lrp_name(ctx, lrp_name); + lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); + lrp = get_lrp_by_lrp_name(ic, lrp_name); if (lrp) { route_table = smap_get_def(&lrp->options, "route_table", ""); route_tag = smap_get_def(&lrp->options, "ic-route-tag", ""); @@ -2407,34 +2431,34 @@ collect_lr_routes(struct ic_context *ctx, route_table = ""; route_tag = ""; } - build_ts_routes_to_adv(ctx, ic_lr, routes_ad, &ts_port_addrs, + build_ts_routes_to_adv(ic, ic_lr, routes_ad, &ts_port_addrs, nb_global, route_table, route_tag, lrp); destroy_lport_addresses(&ts_port_addrs); } } static void -delete_orphan_ic_routes(struct ic_context *ctx, - const struct icsbrec_availability_zone *az) +delete_orphan_ic_routes(struct ic_input *ic, + const struct icsbrec_availability_zone *az) { const struct icsbrec_route *isb_route, *isb_route_key = - icsbrec_route_index_init_row(ctx->icsbrec_route_by_az); + icsbrec_route_index_init_row(ic->icsbrec_route_by_az); icsbrec_route_index_set_availability_zone(isb_route_key, az); const struct icnbrec_transit_switch *t_sw, *t_sw_key; ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, - ctx->icsbrec_route_by_az) + ic->icsbrec_route_by_az) { t_sw_key = icnbrec_transit_switch_index_init_row( - ctx->icnbrec_transit_switch_by_name); + ic->icnbrec_transit_switch_by_name); icnbrec_transit_switch_index_set_name(t_sw_key, isb_route->transit_switch); t_sw = icnbrec_transit_switch_index_find( - ctx->icnbrec_transit_switch_by_name, t_sw_key); + ic->icnbrec_transit_switch_by_name, t_sw_key); icnbrec_transit_switch_index_destroy_row(t_sw_key); - if (!t_sw || !find_lrp_of_nexthop(ctx, isb_route)) { + if (!t_sw || !find_lrp_of_nexthop(ic, isb_route)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_INFO_RL(&rl, "Deleting orphan ICDB:Route: %s->%s (%s, rtb:%s," " transit switch: %s)", isb_route->ip_prefix, @@ -2447,34 +2471,35 @@ delete_orphan_ic_routes(struct ic_context *ctx, } static void -route_run(struct ic_context *ctx) +route_run(struct engine_context *ctx, + struct ic_input *ic) { - if (!ctx->ovnisb_txn || !ctx->ovnnb_txn) { + if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn) { return; } - delete_orphan_ic_routes(ctx, ctx->runned_az); + delete_orphan_ic_routes(ic, ic->runned_az); struct hmap ic_lrs = HMAP_INITIALIZER(&ic_lrs); const struct icsbrec_port_binding *isb_pb; const struct icsbrec_port_binding *isb_pb_key = - icsbrec_port_binding_index_init_row(ctx->icsbrec_port_binding_by_az); + icsbrec_port_binding_index_init_row(ic->icsbrec_port_binding_by_az); icsbrec_port_binding_index_set_availability_zone(isb_pb_key, - ctx->runned_az); + ic->runned_az); /* Each port on TS maps to a logical router, which is stored in the * external_ids:router-id of the IC SB port_binding record. * Here we build info for interconnected Logical Router: * collect IC Port Binding to process routes sync later on. */ ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, - ctx->icsbrec_port_binding_by_az) + ic->icsbrec_port_binding_by_az) { if (ic_pb_get_type(isb_pb) == IC_ROUTER_PORT) { continue; } const struct nbrec_logical_switch_port *nb_lsp; - nb_lsp = get_lsp_by_ts_port_name(ctx, isb_pb->logical_port); + nb_lsp = get_lsp_by_ts_port_name(ic, 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.", @@ -2483,7 +2508,7 @@ route_run(struct ic_context *ctx) } const char *ts_lrp_name = - get_lrp_name_by_ts_port_name(ctx, isb_pb->logical_port); + get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); if (!ts_lrp_name) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_WARN_RL(&rl, "Route sync ignores port %s on ts %s because " @@ -2501,7 +2526,8 @@ route_run(struct ic_context *ctx) } const struct nbrec_logical_router *lr - = nbrec_logical_router_get_for_uuid(ctx->ovnnb_idl, &lr_uuid); + = nbrec_logical_router_table_get_for_uuid( + ic->nbrec_logical_router_table, &lr_uuid); if (!lr) { continue; } @@ -2522,8 +2548,8 @@ route_run(struct ic_context *ctx) struct ic_router_info *ic_lr; struct shash routes_ad_by_ts = SHASH_INITIALIZER(&routes_ad_by_ts); HMAP_FOR_EACH_SAFE (ic_lr, node, &ic_lrs) { - collect_lr_routes(ctx, ic_lr, &routes_ad_by_ts); - sync_learned_routes(ctx, ic_lr); + collect_lr_routes(ic, ic_lr, &routes_ad_by_ts); + sync_learned_routes(ctx, ic, ic_lr); vector_destroy(&ic_lr->isb_pbs); hmap_destroy(&ic_lr->routes_learned); hmap_remove(&ic_lrs, &ic_lr->node); @@ -2531,7 +2557,7 @@ route_run(struct ic_context *ctx) } struct shash_node *node; SHASH_FOR_EACH (node, &routes_ad_by_ts) { - advertise_routes(ctx, ctx->runned_az, node->name, node->data); + advertise_routes(ctx, ic, ic->runned_az, node->name, node->data); hmap_destroy(node->data); } shash_destroy_free_data(&routes_ad_by_ts); @@ -2665,18 +2691,18 @@ remove_unused_sb_records(struct hmap *local_sb_svcs_map) } static void -create_pushed_svcs_mon(struct ic_context *ctx, +create_pushed_svcs_mon(struct ic_input *ic, struct hmap *pushed_svcs_map) { struct sbrec_service_monitor *key = sbrec_service_monitor_index_init_row( - ctx->sbrec_service_monitor_by_remote_type); + ic->sbrec_service_monitor_by_remote_type); sbrec_service_monitor_index_set_remote(key, true); const struct sbrec_service_monitor *sb_rec; SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, - ctx->sbrec_service_monitor_by_remote_type) { + ic->sbrec_service_monitor_by_remote_type) { const char *target_az_name = smap_get(&sb_rec->options, "az-name"); if (!target_az_name) { @@ -2684,7 +2710,7 @@ create_pushed_svcs_mon(struct ic_context *ctx, } create_service_monitor_info(pushed_svcs_map, sb_rec, &sb_rec->header_.uuid, - ctx->runned_az->name, target_az_name, + ic->runned_az->name, target_az_name, NULL, false); } @@ -2692,22 +2718,22 @@ create_pushed_svcs_mon(struct ic_context *ctx, } static void -create_synced_svcs_mon(struct ic_context *ctx, +create_synced_svcs_mon(struct ic_input *ic, struct hmap *synced_svcs_map) { struct icsbrec_service_monitor *key = icsbrec_service_monitor_index_init_row( - ctx->icsbrec_service_monitor_by_target_az); + ic->icsbrec_service_monitor_by_target_az); icsbrec_service_monitor_index_set_target_availability_zone( - key, ctx->runned_az->name); + key, ic->runned_az->name); const struct icsbrec_service_monitor *ic_rec; ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, - ctx->icsbrec_service_monitor_by_target_az) { + ic->icsbrec_service_monitor_by_target_az) { const struct sbrec_port_binding *pb = - find_sb_pb_by_name(ctx->sbrec_port_binding_by_name, + find_sb_pb_by_name(ic->sbrec_port_binding_by_name, ic_rec->logical_port); if (!pb || !pb->up) { @@ -2717,7 +2743,7 @@ create_synced_svcs_mon(struct ic_context *ctx, const char *chassis_name = pb->chassis ? pb->chassis->name : NULL; create_service_monitor_info(synced_svcs_map, ic_rec, &ic_rec->header_.uuid, - ctx->runned_az->name, + ic->runned_az->name, NULL, chassis_name, true); } @@ -2725,22 +2751,22 @@ create_synced_svcs_mon(struct ic_context *ctx, } static void -create_local_ic_svcs_map(struct ic_context *ctx, +create_local_ic_svcs_map(struct ic_input *ic, struct hmap *owned_svc_map) { struct icsbrec_service_monitor *key = icsbrec_service_monitor_index_init_row( - ctx->icsbrec_service_monitor_by_source_az); + ic->icsbrec_service_monitor_by_source_az); icsbrec_service_monitor_index_set_source_availability_zone( - key, ctx->runned_az->name); + key, ic->runned_az->name); const struct icsbrec_service_monitor *ic_rec; ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, - ctx->icsbrec_service_monitor_by_source_az) { + ic->icsbrec_service_monitor_by_source_az) { create_service_monitor_info(owned_svc_map, ic_rec, &ic_rec->header_.uuid, - ctx->runned_az->name, NULL, + ic->runned_az->name, NULL, NULL, true); } @@ -2748,22 +2774,22 @@ create_local_ic_svcs_map(struct ic_context *ctx, } static void -create_local_sb_svcs_map(struct ic_context *ctx, +create_local_sb_svcs_map(struct ic_input *ic, struct hmap *owned_svc_map) { struct sbrec_service_monitor *key = sbrec_service_monitor_index_init_row( - ctx->sbrec_service_monitor_by_ic_learned); + ic->sbrec_service_monitor_by_ic_learned); sbrec_service_monitor_index_set_ic_learned( key, true); const struct sbrec_service_monitor *sb_rec; SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, - ctx->sbrec_service_monitor_by_ic_learned) { + ic->sbrec_service_monitor_by_ic_learned) { create_service_monitor_info(owned_svc_map, sb_rec, &sb_rec->header_.uuid, - ctx->runned_az->name, NULL, + ic->runned_az->name, NULL, NULL, false); } @@ -2771,21 +2797,21 @@ create_local_sb_svcs_map(struct ic_context *ctx, } static const struct sbrec_service_monitor * -lookup_sb_svc_rec(struct ic_context *ctx, +lookup_sb_svc_rec(struct ic_input *ic, const struct service_monitor_info *svc_mon) { const struct icsbrec_service_monitor *db_rec = svc_mon->db_rec.ic_rec; struct sbrec_service_monitor *key = sbrec_service_monitor_index_init_row( - ctx->sbrec_service_monitor_by_remote_type_logical_port); + ic->sbrec_service_monitor_by_remote_type_logical_port); sbrec_service_monitor_index_set_remote(key, false); sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port); const struct sbrec_service_monitor *sb_rec; SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, - ctx->sbrec_service_monitor_by_remote_type_logical_port) { + ic->sbrec_service_monitor_by_remote_type_logical_port) { if (db_rec->port == sb_rec->port && ((db_rec->type && sb_rec->type && !strcmp(db_rec->type, sb_rec->type)) || @@ -2804,14 +2830,14 @@ lookup_sb_svc_rec(struct ic_context *ctx, } static const struct icsbrec_service_monitor * -lookup_icsb_svc_rec(struct ic_context *ctx, +lookup_icsb_svc_rec(struct ic_input *ic, const struct service_monitor_info *svc_mon) { const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec; struct icsbrec_service_monitor *key = icsbrec_service_monitor_index_init_row( - ctx->icsbrec_service_monitor_by_target_az_logical_port); + ic->icsbrec_service_monitor_by_target_az_logical_port); ovs_assert(svc_mon->dst_az_name); icsbrec_service_monitor_index_set_target_availability_zone( @@ -2822,7 +2848,7 @@ lookup_icsb_svc_rec(struct ic_context *ctx, const struct icsbrec_service_monitor *ic_rec; ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, - ctx->icsbrec_service_monitor_by_target_az_logical_port) { + ic->icsbrec_service_monitor_by_target_az_logical_port) { if (db_rec->port == ic_rec->port && ((db_rec->type && ic_rec->type && !strcmp(db_rec->type, ic_rec->type)) || @@ -2842,11 +2868,11 @@ lookup_icsb_svc_rec(struct ic_context *ctx, } static void -create_service_monitor_data(struct ic_context *ctx, +create_service_monitor_data(struct ic_input *ic, struct sync_service_monitor_data *sync_data) { - const struct sbrec_sb_global *ic_sb = sbrec_sb_global_first( - ctx->ovnsb_idl); + const struct sbrec_sb_global *ic_sb = + sbrec_sb_global_table_first(ic->sbrec_sb_global_table); const char *svc_monitor_mac = smap_get(&ic_sb->options, "svc_monitor_mac"); @@ -2855,10 +2881,10 @@ create_service_monitor_data(struct ic_context *ctx, } sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac); - create_pushed_svcs_mon(ctx, &sync_data->pushed_svcs_map); - create_synced_svcs_mon(ctx, &sync_data->synced_svcs_map); - create_local_ic_svcs_map(ctx, &sync_data->local_ic_svcs_map); - create_local_sb_svcs_map(ctx, &sync_data->local_sb_svcs_map); + create_pushed_svcs_mon(ic, &sync_data->pushed_svcs_map); + create_synced_svcs_mon(ic, &sync_data->synced_svcs_map); + create_local_ic_svcs_map(ic, &sync_data->local_ic_svcs_map); + create_local_sb_svcs_map(ic, &sync_data->local_sb_svcs_map); } static void @@ -2879,9 +2905,10 @@ destroy_service_monitor_data(struct sync_service_monitor_data *sync_data) } static void -sync_service_monitor(struct ic_context *ctx) +sync_service_monitor(struct engine_context *ctx, + struct ic_input *ic) { - if (!ctx->ovnisb_txn || !ctx->ovnsb_txn) { + if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) { return; } @@ -2892,18 +2919,18 @@ sync_service_monitor(struct ic_context *ctx) hmap_init(&sync_data.local_ic_svcs_map); hmap_init(&sync_data.local_sb_svcs_map); - create_service_monitor_data(ctx, &sync_data); + create_service_monitor_data(ic, &sync_data); struct service_monitor_info *svc_mon; HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.pushed_svcs_map) { const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec; const struct icsbrec_service_monitor *ic_rec = - lookup_icsb_svc_rec(ctx, svc_mon); + lookup_icsb_svc_rec(ic, svc_mon); if (ic_rec) { sbrec_service_monitor_set_status(db_rec, ic_rec->status); } else { - ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_txn); + ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_idl_txn); icsbrec_service_monitor_set_type(ic_rec, db_rec->type); icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip); icsbrec_service_monitor_set_port(ic_rec, db_rec->port); @@ -2928,13 +2955,13 @@ sync_service_monitor(struct ic_context *ctx) const struct icsbrec_service_monitor *db_rec = svc_mon->db_rec.ic_rec; const struct sbrec_service_monitor *sb_rec = - lookup_sb_svc_rec(ctx, svc_mon); + lookup_sb_svc_rec(ic, svc_mon); if (sb_rec) { icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec, sb_rec->status); } else { - sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_txn); + sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_idl_txn); sbrec_service_monitor_set_type(sb_rec, db_rec->type); sbrec_service_monitor_set_ip(sb_rec, db_rec->ip); sbrec_service_monitor_set_port(sb_rec, db_rec->port); @@ -3002,55 +3029,60 @@ sync_service_monitor(struct ic_context *ctx) * INB:nb_ic_cfg and INB:sb_ic_cfg to INB:nb_ic_cfg. */ static void -update_sequence_numbers(struct ic_context *ctx, - struct ovsdb_idl_loop *ic_sb_loop) -{ - if (!ctx->ovnisb_txn || !ctx->ovninb_txn) { +update_sequence_numbers(struct ovsdb_idl *ovninb_idl, + struct ovsdb_idl *ovnisb_idl, + struct ovsdb_idl_txn *ovninb_txn, + struct ovsdb_idl_txn *ovnisb_txn, + struct ovsdb_idl_loop *ic_sb_loop, + const struct icsbrec_availability_zone *az) +{ + if (!ovnisb_txn || !ovninb_txn) { return; } const struct icnbrec_ic_nb_global *ic_nb = icnbrec_ic_nb_global_first( - ctx->ovninb_idl); + ovninb_idl); if (!ic_nb) { - ic_nb = icnbrec_ic_nb_global_insert(ctx->ovninb_txn); + ic_nb = icnbrec_ic_nb_global_insert(ovninb_txn); } const struct icsbrec_ic_sb_global *ic_sb = icsbrec_ic_sb_global_first( - ctx->ovnisb_idl); + ovnisb_idl); if (!ic_sb) { - ic_sb = icsbrec_ic_sb_global_insert(ctx->ovnisb_txn); + ic_sb = icsbrec_ic_sb_global_insert(ovnisb_txn); } if ((ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) && - (ic_nb->nb_ic_cfg != ctx->runned_az->nb_ic_cfg)) { + (ic_nb->nb_ic_cfg != az->nb_ic_cfg)) { /* Deal with potential overflows. */ - if (ctx->runned_az->nb_ic_cfg == INT64_MAX) { - icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az, 0); + if (az->nb_ic_cfg == INT64_MAX) { + icsbrec_availability_zone_set_nb_ic_cfg(az, 0); } ic_sb_loop->next_cfg = ic_nb->nb_ic_cfg; - ovsdb_idl_txn_increment(ctx->ovnisb_txn, &ctx->runned_az->header_, - &icsbrec_availability_zone_col_nb_ic_cfg, true); + ovsdb_idl_txn_increment(ovnisb_txn, &az->header_, + &icsbrec_availability_zone_col_nb_ic_cfg, + true); return; } /* handle cases where accidentally AZ:ic_nb_cfg exceeds * the INB:ic_nb_cfg. */ - if (ctx->runned_az->nb_ic_cfg != ic_sb_loop->cur_cfg) { - icsbrec_availability_zone_set_nb_ic_cfg(ctx->runned_az, + if (az->nb_ic_cfg != ic_sb_loop->cur_cfg) { + icsbrec_availability_zone_set_nb_ic_cfg(az, ic_sb_loop->cur_cfg); return; } const struct icsbrec_availability_zone *other_az; - ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ctx->ovnisb_idl) { - if (other_az->nb_ic_cfg != ctx->runned_az->nb_ic_cfg) { + ICSBREC_AVAILABILITY_ZONE_FOR_EACH (other_az, ovnisb_idl) { + if (other_az->nb_ic_cfg != az->nb_ic_cfg) { return; } } /* All the AZs are updated successfully, update SB/NB counter. */ if (ic_nb->nb_ic_cfg != ic_sb->nb_ic_cfg) { - icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, ctx->runned_az->nb_ic_cfg); - icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, ctx->runned_az->nb_ic_cfg); + icsbrec_ic_sb_global_set_nb_ic_cfg(ic_sb, az->nb_ic_cfg); + icnbrec_ic_nb_global_set_sb_ic_cfg(ic_nb, az->nb_ic_cfg); } } @@ -3077,23 +3109,18 @@ inc_proc_graph_dump(const char *end_node) } void -ovn_db_run(struct ic_context *ctx) -{ - struct hmap dp_tnlids = HMAP_INITIALIZER(&dp_tnlids); - struct shash isb_ts_dps = SHASH_INITIALIZER(&isb_ts_dps); - struct shash isb_tr_dps = SHASH_INITIALIZER(&isb_tr_dps); - - gateway_run(ctx); - enumerate_datapaths(ctx, &dp_tnlids, &isb_ts_dps, &isb_tr_dps); - ts_run(ctx, &dp_tnlids, &isb_ts_dps); - tr_run(ctx, &dp_tnlids, &isb_tr_dps); - port_binding_run(ctx); - route_run(ctx); - sync_service_monitor(ctx); - - ovn_destroy_tnlids(&dp_tnlids); - shash_destroy(&isb_ts_dps); - shash_destroy(&isb_tr_dps); +ovn_db_run(struct ic_input *input_data, + struct ic_data *ic_data, + struct engine_context *eng_ctx) +{ + gateway_run(eng_ctx, input_data); + enumerate_datapaths(input_data, &ic_data->dp_tnlids, + &ic_data->isb_ts_dps, &ic_data->isb_tr_dps); + 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); } static void @@ -3485,81 +3512,6 @@ main(int argc, char *argv[]) ovsdb_idl_track_add_column(ovnsb_idl_loop.idl, &sbrec_service_monitor_col_options); - /* Create IDL indexes */ - struct ovsdb_idl_index *nbrec_ls_by_name - = ovsdb_idl_index_create1(ovnnb_idl_loop.idl, - &nbrec_logical_switch_col_name); - struct ovsdb_idl_index *nbrec_lr_by_name = ovsdb_idl_index_create1( - ovnnb_idl_loop.idl, &nbrec_logical_router_col_name); - struct ovsdb_idl_index *nbrec_port_by_name - = ovsdb_idl_index_create1(ovnnb_idl_loop.idl, - &nbrec_logical_switch_port_col_name); - struct ovsdb_idl_index *nbrec_lrp_by_name - = ovsdb_idl_index_create1(ovnnb_idl_loop.idl, - &nbrec_logical_router_port_col_name); - struct ovsdb_idl_index *sbrec_port_binding_by_name - = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, - &sbrec_port_binding_col_logical_port); - struct ovsdb_idl_index *sbrec_chassis_by_name - = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, - &sbrec_chassis_col_name); - - struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type - = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, - &sbrec_service_monitor_col_remote); - - struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned - = ovsdb_idl_index_create1(ovnsb_idl_loop.idl, - &sbrec_service_monitor_col_ic_learned); - - struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port - = ovsdb_idl_index_create2(ovnsb_idl_loop.idl, - &sbrec_service_monitor_col_remote, - &sbrec_service_monitor_col_logical_port); - - struct ovsdb_idl_index *icnbrec_transit_switch_by_name - = ovsdb_idl_index_create1(ovninb_idl_loop.idl, - &icnbrec_transit_switch_col_name); - - struct ovsdb_idl_index *icsbrec_port_binding_by_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, - &icsbrec_port_binding_col_availability_zone); - - struct ovsdb_idl_index *icsbrec_port_binding_by_ts - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, - &icsbrec_port_binding_col_transit_switch); - - struct ovsdb_idl_index *icsbrec_port_binding_by_ts_az - = ovsdb_idl_index_create2(ovnisb_idl_loop.idl, - &icsbrec_port_binding_col_transit_switch, - &icsbrec_port_binding_col_availability_zone); - - struct ovsdb_idl_index *icsbrec_route_by_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, - &icsbrec_route_col_availability_zone); - - struct ovsdb_idl_index *icsbrec_route_by_ts - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, - &icsbrec_route_col_transit_switch); - - struct ovsdb_idl_index *icsbrec_route_by_ts_az - = ovsdb_idl_index_create2(ovnisb_idl_loop.idl, - &icsbrec_route_col_transit_switch, - &icsbrec_route_col_availability_zone); - - struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, - &icsbrec_service_monitor_col_source_availability_zone); - - struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az - = ovsdb_idl_index_create1(ovnisb_idl_loop.idl, - &icsbrec_service_monitor_col_target_availability_zone); - - struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port - = ovsdb_idl_index_create2(ovnisb_idl_loop.idl, - &icsbrec_service_monitor_col_target_availability_zone, - &icsbrec_service_monitor_col_logical_port); - unixctl_command_register("nb-connection-status", "", 0, 0, ovn_conn_show, ovnnb_idl_loop.idl); unixctl_command_register("sb-connection-status", "", 0, 0, @@ -3569,6 +3521,8 @@ main(int argc, char *argv[]) unixctl_command_register("ic-sb-connection-status", "", 0, 0, ovn_conn_show, ovnisb_idl_loop.idl); + stopwatch_create(IC_OVN_DB_RUN_STOPWATCH_NAME, SW_MS); + /* Initialize incremental processing engine for ovn-northd */ inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop, &ovninb_idl_loop, &ovnisb_idl_loop); @@ -3662,67 +3616,43 @@ main(int argc, char *argv[]) ovnisb_cond_seqno = new_ovnisb_cond_seqno; } - struct ic_context ctx = { - .ovnnb_idl = ovnnb_idl_loop.idl, - .ovnnb_txn = ovnnb_txn, - .ovnsb_idl = ovnsb_idl_loop.idl, - .ovnsb_txn = ovnsb_txn, - .ovninb_idl = ovninb_idl_loop.idl, - .ovninb_txn = ovninb_txn, - .ovnisb_idl = ovnisb_idl_loop.idl, - .ovnisb_txn = ovnisb_txn, - .nbrec_ls_by_name = nbrec_ls_by_name, - .nbrec_lr_by_name = nbrec_lr_by_name, - .nbrec_lrp_by_name = nbrec_lrp_by_name, - .nbrec_port_by_name = nbrec_port_by_name, - .sbrec_port_binding_by_name = sbrec_port_binding_by_name, - .sbrec_chassis_by_name = sbrec_chassis_by_name, - .sbrec_service_monitor_by_remote_type = - sbrec_service_monitor_by_remote_type, - .sbrec_service_monitor_by_ic_learned = - sbrec_service_monitor_by_ic_learned, - .sbrec_service_monitor_by_remote_type_logical_port = - sbrec_service_monitor_by_remote_type_logical_port, - .icnbrec_transit_switch_by_name = - icnbrec_transit_switch_by_name, - .icsbrec_port_binding_by_az = icsbrec_port_binding_by_az, - .icsbrec_port_binding_by_ts = icsbrec_port_binding_by_ts, - .icsbrec_port_binding_by_ts_az = icsbrec_port_binding_by_ts_az, - .icsbrec_route_by_az = icsbrec_route_by_az, - .icsbrec_route_by_ts = icsbrec_route_by_ts, - .icsbrec_route_by_ts_az = icsbrec_route_by_ts_az, - .icsbrec_service_monitor_by_source_az = - icsbrec_service_monitor_by_source_az, - .icsbrec_service_monitor_by_target_az = - icsbrec_service_monitor_by_target_az, - .icsbrec_service_monitor_by_target_az_logical_port = - icsbrec_service_monitor_by_target_az_logical_port, - }; - - if (!state.had_lock && ovsdb_idl_has_lock(ctx.ovnsb_idl)) { + if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) { VLOG_INFO("ovn-ic lock acquired. " "This ovn-ic instance is now active."); state.had_lock = true; } else if (state.had_lock && - !ovsdb_idl_has_lock(ctx.ovnsb_idl)) { + !ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) { VLOG_INFO("ovn-ic lock lost. " "This ovn-ic instance is now on standby."); state.had_lock = false; } - if (ovsdb_idl_has_lock(ctx.ovnsb_idl) && - ovsdb_idl_has_ever_connected(ctx.ovnnb_idl) && - ovsdb_idl_has_ever_connected(ctx.ovnsb_idl) && - ovsdb_idl_has_ever_connected(ctx.ovninb_idl) && - ovsdb_idl_has_ever_connected(ctx.ovnisb_idl)) { - if (ctx.ovnnb_txn && ctx.ovnsb_txn && ctx.ovninb_txn && - ctx.ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) { - ctx.runned_az = az_run(&ctx); - VLOG_DBG("Availability zone: %s", ctx.runned_az ? - ctx.runned_az->name : "not created yet."); - if (ctx.runned_az) { - (void) inc_proc_ic_run(&ctx, &eng_ctx); - update_sequence_numbers(&ctx, &ovnisb_idl_loop); + if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl) && + ovsdb_idl_has_ever_connected(ovnnb_idl_loop.idl) && + ovsdb_idl_has_ever_connected(ovnsb_idl_loop.idl) && + ovsdb_idl_has_ever_connected(ovninb_idl_loop.idl) && + ovsdb_idl_has_ever_connected(ovnisb_idl_loop.idl)) { + if (ovnnb_txn && ovnsb_txn && ovninb_txn && + ovnisb_txn && inc_proc_ic_can_run(&eng_ctx)) { + const struct icsbrec_availability_zone *az = + az_run(ovnnb_idl_loop.idl, + ovnisb_idl_loop.idl, + ovnisb_txn); + VLOG_DBG("Availability zone: %s", az ? + az->name : "not created yet."); + if (az) { + (void) inc_proc_ic_run(ovnnb_txn, + ovnsb_txn, + ovninb_txn, + ovnisb_txn, + &eng_ctx, + az); + update_sequence_numbers(ovninb_idl_loop.idl, + ovnisb_idl_loop.idl, + ovninb_txn, + ovnisb_txn, + &ovnisb_idl_loop, + az); } } else if (!inc_proc_ic_get_force_recompute()) { clear_idl_track = false; @@ -3812,10 +3742,12 @@ main(int argc, char *argv[]) poll_immediate_wake(); } + stopwatch_stop(NORTHD_LOOP_STOPWATCH_NAME, time_msec()); poll_block(); if (should_service_stop()) { exiting = true; } + stopwatch_start(NORTHD_LOOP_STOPWATCH_NAME, time_msec()); } inc_proc_ic_cleanup(); @@ -3885,8 +3817,8 @@ ovn_ic_status(struct unixctl_conn *conn, int argc OVS_UNUSED, } /* - * Use a labelled formatted output so we can add more to the status command - * later without breaking any consuming scripts + * Use a labelled formatted output so we can add more to the status + * command later without breaking any consuming scripts */ struct ds s = DS_EMPTY_INITIALIZER; ds_put_format(&s, "Status: %s\n", status); diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h index e8d7a970f..2c2efc046 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -16,16 +16,33 @@ #include "ovsdb-idl.h" #include "unixctl.h" +#include "lib/inc-proc-eng.h" -struct ic_context { - struct ovsdb_idl *ovnnb_idl; - struct ovsdb_idl *ovnsb_idl; - struct ovsdb_idl *ovninb_idl; - struct ovsdb_idl *ovnisb_idl; - struct ovsdb_idl_txn *ovnnb_txn; - struct ovsdb_idl_txn *ovnsb_txn; - struct ovsdb_idl_txn *ovninb_txn; - struct ovsdb_idl_txn *ovnisb_txn; +struct ic_input { + /* Northbound table references */ + const struct nbrec_logical_switch_table *nbrec_logical_switch_table; + const struct nbrec_logical_router_table *nbrec_logical_router_table; + const struct nbrec_nb_global_table *nbrec_nb_global_table; + + /* Southbound table references */ + const struct sbrec_chassis_table *sbrec_chassis_table; + const struct sbrec_sb_global_table *sbrec_sb_global_table; + + /* InterconnectNorthbound table references */ + const struct icnbrec_transit_switch_table *icnbrec_transit_switch_table; + const struct icnbrec_ic_nb_global_table *icnbrec_ic_nb_global_table; + const struct icnbrec_transit_router_table *icnbrec_transit_router_table; + + /* 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; + const struct icsbrec_availability_zone_table + *icsbrec_availability_zone_table; + + /* Indexes */ const struct icsbrec_availability_zone *runned_az; struct ovsdb_idl_index *nbrec_ls_by_name; struct ovsdb_idl_index *nbrec_lr_by_name; @@ -48,6 +65,12 @@ struct ic_context { struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port; }; +struct ic_data { + /* Global state for 'en-ic'. */ + struct hmap dp_tnlids; + struct shash isb_ts_dps; + struct shash isb_tr_dps; +}; struct ic_state { bool had_lock; bool paused; @@ -56,6 +79,13 @@ struct ic_state { 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 }; -void ovn_db_run(struct ic_context *ctx); +const struct icsbrec_availability_zone * + 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, + struct engine_context *eng_ctx); #endif /* OVN_IC_H */ diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index b912e813c..e933213d8 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -40,4 +40,6 @@ #define DYNAMIC_ROUTES_RUN_STOPWATCH_NAME "dynamic_routes" #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route" +#define IC_OVN_DB_RUN_STOPWATCH_NAME "ovn_db_run" + #endif From patchwork Mon Feb 9 18:28:07 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194716 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=g2/Ert6U; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tW56HlMz1xwN for ; Tue, 10 Feb 2026 05:28:49 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 70A1E61286; Mon, 9 Feb 2026 18:28:48 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id RLi6Lhc9Q2Eq; Mon, 9 Feb 2026 18:28:45 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 3BA8860E45 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=g2/Ert6U Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 3BA8860E45; Mon, 9 Feb 2026 18:28:45 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 91FA7C0781; Mon, 9 Feb 2026 18:28:44 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0721CC0780 for ; Mon, 9 Feb 2026 18:28:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 9536D41C32 for ; Mon, 9 Feb 2026 18:28:30 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id k-al2UX-KH6W for ; Mon, 9 Feb 2026 18:28:29 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::b134; helo=mail-yx1-xb134.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp4.osuosl.org 30A7B41C3D Authentication-Results: smtp4.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 30A7B41C3D Authentication-Results: smtp4.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=g2/Ert6U Received: from mail-yx1-xb134.google.com (mail-yx1-xb134.google.com [IPv6:2607:f8b0:4864:20::b134]) by smtp4.osuosl.org (Postfix) with ESMTPS id 30A7B41C3D for ; Mon, 9 Feb 2026 18:28:29 +0000 (UTC) Received: by mail-yx1-xb134.google.com with SMTP id 956f58d0204a3-649e456e8a2so28176d50.0 for ; Mon, 09 Feb 2026 10:28:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661708; x=1771266508; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TpDs27/xqA+DtW9+hEhS6M7kNY0JhkVvO1kRuYbmblw=; b=g2/Ert6Usb6004096+dOvAc7m7jikr7W1HeM9MtOrUd4GiBkd5GkaFqu72PnM1+tgD +F3ewM45IPwdE29i4+Xg4mbFn18FOkUyXdU9RESqVMRBtYSnX/T8A3TqlnHAtGiDN4O/ 8J8V2e8OmnKVFNv5DaAF09dpFeHgg2Z6ml30Y= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661708; x=1771266508; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=TpDs27/xqA+DtW9+hEhS6M7kNY0JhkVvO1kRuYbmblw=; b=RyTc5UZW9PPiLQ82UffRkTUWr8L1cb5e3gNldF3OVTVuusaM8TxNsGG6OuNMRxX27M 02dMp8xrsaZDcEdR5W4hnW4aA2LLx78k0+4uIvGMx+rX3eTO5WxYEzRd6XMQE5oheOHX 7/ijbvvn/otNJNciwNRBCO/dWxszW/plKF/0NpWDdB+bQxk02owEhk4sZzDzik9JJqRd QzOfhb4RqygJm9U0xZjwSnSr1cc7EU63tQcN1C0upLi1iZAVykqU4RFL3fPK++jl5Bq0 ICUidiZuAdf5qakBNLle6aKQl6KGA9XgcXVoAsKoaTCNhRmVR7T8tQdVd5RWgnDAl7o1 u+Vg== X-Gm-Message-State: AOJu0YwLPs1TEMpJ7kLPt+0Eblak9csinshAaggw53axWT9fn2k+mCBp zxC2mTJDA87WYOJ4Ebr0xifm5D546pn+PACDZeWREaeEJbigNTr1E4y/1XzKiB+EhRiEgn/WWWn J0Fd13k+VZdtDrBwr5bSI9rFGfxxHwrUb9J92nTPNDr08p27NbySIQnBlG1/GRw4= X-Gm-Gg: AZuq6aKFGRETqAKhaf6RPiIPR9/npRvyNoZuaBPFZoGcFHEyF/SRajyVRqdXXH0hYYz fm1JoyOTQlLtmCBwruXReLhFzcS1VbzWgahipMoPa+TQDX5K8tB+ofanbOvJ4vdAxZM8euBx1oB b0wEEwm+p4m1xCrsORBpq2C53Iip8ufjxzg51wSYmlayQ93guVX8X+i71qkdzLgGIYRwR5EWWek PYRoHwAr8XhbN3crdMmC9WAh7K/JpaR1fXCVkolbFLMkRVov+26nyof0eDu3lsXxUeIkWZihsBq IVhMVi7d9asq6p8NHC65h2kJyYEerqJhlHKl5zlaMUaLZD8ePl5omRN5tT4Q4XCzNJ3oa+PxcXH BHG1gyjDR2IlldaIMelx/rKD62Shppl1kBCd9MwZj7xaanUnJJClxPBhuPmffXbEBQfMbdQRKSb I3uzPQR5QZEXL3DgLcSjvqh2Yq76kZ5fkkRclpow== X-Received: by 2002:a05:690c:680f:b0:796:5b5e:f4fc with SMTP id 00721157ae682-7965b5efab9mr12484377b3.24.1770661707439; Mon, 09 Feb 2026 10:28:27 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:27 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:07 -0300 Message-Id: <20260209182814.842-3-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 2/9] ovn-ic: Add a new engine-node 'enum-datapath'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This new engine now maintains the enum_datapath related data for ovn-ic daemon which was earlier maintained by the ic engine node invoked the enumerate_datapaths() function. The inputs to this engine node are en_icnb_transit_switch; en_icsb_datapath_binding'; In order to achieve this, we refactor in the following way: * Introduce enum_datapaths_init() which initializes this data. * Introduce enum_datapaths_destroy() which clears this data for a new iteration. * Introduce enum_datapaths_run() which invokes the full recompute of the engine. This engine node becomes an input to 'ic' node. Signed-off-by: Paulo Guilherme Silva --- ic/automake.mk | 2 + ic/en-enum-datapaths.c | 141 +++++++++++++++++++++++++++++++++++++++++ ic/en-enum-datapaths.h | 30 +++++++++ ic/en-ic.c | 29 +++++---- ic/inc-proc-ic.c | 6 ++ ic/ovn-ic.c | 82 ++++++++++++------------ ic/ovn-ic.h | 8 +-- lib/stopwatch-names.h | 1 + 8 files changed, 244 insertions(+), 55 deletions(-) create mode 100644 ic/en-enum-datapaths.c create mode 100644 ic/en-enum-datapaths.h -- 2.34.1 diff --git a/ic/automake.mk b/ic/automake.mk index a69b1030d..2766483b7 100644 --- a/ic/automake.mk +++ b/ic/automake.mk @@ -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-enum-datapaths.c \ + ic/en-enum-datapaths.h \ ic/inc-proc-ic.c \ ic/inc-proc-ic.h ic_ovn_ic_LDADD = \ diff --git a/ic/en-enum-datapaths.c b/ic/en-enum-datapaths.c new file mode 100644 index 000000000..7515c0b85 --- /dev/null +++ b/ic/en-enum-datapaths.c @@ -0,0 +1,141 @@ +/* + * 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 + +#include +#include +#include + +/* OVS includes. */ +#include "openvswitch/vlog.h" +#include "openvswitch/shash.h" +#include "openvswitch/hmap.h" + +/* OVN includes. */ +#include "ovn-ic.h" +#include "en-enum-datapaths.h" +#include "inc-proc-ic.h" +#include "lib/inc-proc-eng.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_enum_datapaths); +COVERAGE_DEFINE(enum_datapaths_run); + +static void +enum_datapath_run(const struct icsbrec_datapath_binding_table *dp_table, + struct ed_type_enum_datapaths *dp_data); +static enum ic_datapath_type + ic_dp_get_type(const struct icsbrec_datapath_binding *isb_dp); +static void enum_datapaths_init(struct ed_type_enum_datapaths *data); +static void enum_datapaths_destroy(struct ed_type_enum_datapaths *data); +static void enum_datapaths_clear(struct ed_type_enum_datapaths *data); + +void * +en_enum_datapaths_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct ed_type_enum_datapaths *data = xzalloc(sizeof *data); + enum_datapaths_init(data); + return data; +} + +void +en_enum_datapaths_cleanup(void *data) +{ + enum_datapaths_destroy(data); +} + +enum engine_node_state +en_enum_datapaths_run(struct engine_node *node, void *data) +{ + struct ed_type_enum_datapaths *dp_data = data; + + enum_datapaths_clear(dp_data); + + const struct icsbrec_datapath_binding_table *dp_table = + EN_OVSDB_GET(engine_get_input("ICSB_datapath_binding", node)); + + COVERAGE_INC(enum_datapaths_run); + stopwatch_start(OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME, time_msec()); + enum_datapath_run(dp_table, dp_data); + stopwatch_stop(OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME, time_msec()); + + return EN_UPDATED; +} + +static void +enum_datapath_run(const struct icsbrec_datapath_binding_table *dp_table, + struct ed_type_enum_datapaths *dp_data) +{ + const struct icsbrec_datapath_binding *isb_dp; + ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (isb_dp, dp_table) { + /* 1. Adiciona Tunnel ID */ + ovn_add_tnlid(&dp_data->dp_tnlids, isb_dp->tunnel_key); + + /* 2. Classifica o Datapath */ + enum ic_datapath_type dp_type = ic_dp_get_type(isb_dp); + if (dp_type == IC_ROUTER) { + char *uuid_str = uuid_to_string(isb_dp->nb_ic_uuid); + shash_add(&dp_data->isb_tr_dps, uuid_str, (void *) isb_dp); + free(uuid_str); + } else { + shash_add(&dp_data->isb_ts_dps, isb_dp->transit_switch, + (void *) isb_dp); + } + } +} + +static enum ic_datapath_type +ic_dp_get_type(const struct icsbrec_datapath_binding *isb_dp) +{ + if (isb_dp->type && !strcmp(isb_dp->type, "transit-router")) { + return IC_ROUTER; + } + + return IC_SWITCH; +} + +static void +enum_datapaths_init(struct ed_type_enum_datapaths *data) +{ + hmap_init(&data->dp_tnlids); + shash_init(&data->isb_ts_dps); + shash_init(&data->isb_tr_dps); +} + +static void +enum_datapaths_destroy(struct ed_type_enum_datapaths *data) +{ + enum_datapaths_clear(data); + ovn_destroy_tnlids(&data->dp_tnlids); + + shash_destroy(&data->isb_ts_dps); + shash_destroy(&data->isb_tr_dps); +} + +static void +enum_datapaths_clear(struct ed_type_enum_datapaths *data) +{ + ovn_destroy_tnlids(&data->dp_tnlids); + hmap_init(&data->dp_tnlids); + + shash_clear(&data->isb_ts_dps); + shash_clear(&data->isb_tr_dps); +} diff --git a/ic/en-enum-datapaths.h b/ic/en-enum-datapaths.h new file mode 100644 index 000000000..0aff9fc89 --- /dev/null +++ b/ic/en-enum-datapaths.h @@ -0,0 +1,30 @@ +#ifndef EN_IC_ENUM_DATAPATHS_H +#define EN_IC_ENUM_DATAPATHS_H 1 + +#include + +#include +#include +#include +#include + +/* OVS includes. */ +#include "lib/hmapx.h" +#include "openvswitch/hmap.h" +#include "openvswitch/shash.h" + +/* OVN includes. */ +#include "lib/inc-proc-eng.h" + +/* struct which maintains the data of the engine node enumerate datapaths. */ +struct ed_type_enum_datapaths { + struct hmap dp_tnlids; + struct shash isb_ts_dps; + struct shash isb_tr_dps; +}; + +void *en_enum_datapaths_init(struct engine_node *, struct engine_arg *); +enum engine_node_state en_enum_datapaths_run(struct engine_node *, void *data); +void en_enum_datapaths_cleanup(void *data); + +#endif \ No newline at end of file diff --git a/ic/en-ic.c b/ic/en-ic.c index ce7d5de76..16b0e12bd 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -24,6 +24,8 @@ /* OVN includes. */ #include "ovn-ic.h" #include "en-ic.h" +#include "en-enum-datapaths.h" +#include "lib/ovn-ic-sb-idl.h" #include "lib/inc-proc-eng.h" #include "lib/ovn-util.h" #include "lib/stopwatch-names.h" @@ -152,18 +154,26 @@ enum engine_node_state en_ic_run(struct engine_node *node, void *data) { const struct engine_context *eng_ctx = engine_get_context(); - + struct ic_data *ic_data = data; struct ic_input input_data; - ic_destroy(data); - ic_init(data); + struct ed_type_enum_datapaths *dp_node_data = + engine_get_input_data("enum_datapaths", node); + + if (!dp_node_data) { + return EN_UNCHANGED; + } + + ic_data->dp_tnlids = &dp_node_data->dp_tnlids; + ic_data->isb_ts_dps = &dp_node_data->isb_ts_dps; + ic_data->isb_tr_dps = &dp_node_data->isb_tr_dps; ic_get_input_data(node, &input_data); input_data.runned_az = eng_ctx->client_ctx; COVERAGE_INC(ic_run); stopwatch_start(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec()); - ovn_db_run(&input_data, data, (struct engine_context *) eng_ctx); + ovn_db_run(&input_data, ic_data, (struct engine_context *) eng_ctx); stopwatch_stop(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec()); return EN_UPDATED; } @@ -186,17 +196,14 @@ en_ic_cleanup(void *data) } void -ic_destroy(struct ic_data *data) +ic_destroy(struct ic_data *data OVS_UNUSED) { - ovn_destroy_tnlids(&data->dp_tnlids); - shash_destroy(&data->isb_ts_dps); - shash_destroy(&data->isb_tr_dps); } void ic_init(struct ic_data *data) { - hmap_init(&data->dp_tnlids); - shash_init(&data->isb_ts_dps); - shash_init(&data->isb_tr_dps); + data->dp_tnlids = NULL; + data->isb_ts_dps = NULL; + data->isb_tr_dps = NULL; } diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 0160c3a3e..d7d247e7a 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -27,6 +27,7 @@ #include "openvswitch/vlog.h" #include "inc-proc-ic.h" #include "en-ic.h" +#include "en-enum-datapaths.h" #include "unixctl.h" #include "util.h" @@ -158,6 +159,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(enum_datapaths); void inc_proc_ic_init(struct ovsdb_idl_loop *nb, @@ -167,6 +169,10 @@ 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_enum_datapaths, &en_icnb_transit_switch, NULL); + engine_add_input(&en_enum_datapaths, &en_icsb_datapath_binding, NULL); + + engine_add_input(&en_ic, &en_enum_datapaths, 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); diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 8327054de..724201616 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -172,16 +172,6 @@ allocate_dp_key(struct hmap *dp_tnlids, bool vxlan_mode, const char *name) &hint); } -static enum ic_datapath_type -ic_dp_get_type(const struct icsbrec_datapath_binding *isb_dp) -{ - if (isb_dp->type && !strcmp(isb_dp->type, "transit-router")) { - return IC_ROUTER; - } - - return IC_SWITCH; -} - static enum ic_port_binding_type ic_pb_get_type(const struct icsbrec_port_binding *isb_pb) { @@ -192,28 +182,6 @@ ic_pb_get_type(const struct icsbrec_port_binding *isb_pb) return IC_SWITCH_PORT; } -static void -enumerate_datapaths(struct ic_input *ic, - struct hmap *dp_tnlids, - struct shash *isb_ts_dps, - struct shash *isb_tr_dps) -{ - const struct icsbrec_datapath_binding *isb_dp; - ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (isb_dp, - ic->icsbrec_datapath_binding_table) { - ovn_add_tnlid(dp_tnlids, isb_dp->tunnel_key); - - enum ic_datapath_type dp_type = ic_dp_get_type(isb_dp); - if (dp_type == IC_ROUTER) { - char *uuid_str = uuid_to_string(isb_dp->nb_ic_uuid); - shash_add(isb_tr_dps, uuid_str, isb_dp); - free(uuid_str); - } else { - shash_add(isb_ts_dps, isb_dp->transit_switch, isb_dp); - } - } -} - static void ts_run(struct engine_context *ctx, struct ic_input *ic, @@ -275,7 +243,17 @@ ts_run(struct engine_context *ctx, const struct icsbrec_datapath_binding *isb_dp; isb_dp = shash_find_data(isb_ts_dps, ts->name); - if (isb_dp) { + if (!isb_dp) { + const struct icsbrec_datapath_binding *raw; + ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw, + ic->icsbrec_datapath_binding_table) { + if (raw->transit_switch && !strcmp(raw->transit_switch, + ts->name)) { + isb_dp = raw; + break; + } + } + } else { int64_t nb_tnl_key = smap_get_int(&ls->other_config, "requested-tnl-key", 0); @@ -309,6 +287,24 @@ ts_run(struct engine_context *ctx, ic->icnbrec_transit_switch_table) { const struct icsbrec_datapath_binding *isb_dp = shash_find_and_delete(isb_ts_dps, ts->name); + + if (!isb_dp) { + const struct icsbrec_datapath_binding *raw_isb; + ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw_isb, + ic->icsbrec_datapath_binding_table) { + if (raw_isb->n_nb_ic_uuid > 0 && + uuid_equals(&raw_isb->nb_ic_uuid[0], + &ts->header_.uuid)) { + isb_dp = raw_isb; + if (isb_dp->transit_switch) { + shash_find_and_delete(isb_ts_dps, + isb_dp->transit_switch); + } + break; + } + } + } + if (!isb_dp) { /* Allocate tunnel key */ int64_t dp_key = allocate_dp_key(dp_tnlids, vxlan_mode, @@ -320,6 +316,9 @@ ts_run(struct engine_context *ctx, isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn); icsbrec_datapath_binding_set_transit_switch(isb_dp, ts->name); icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); + icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, + &ts->header_.uuid, 1); + icsbrec_datapath_binding_set_type(isb_dp, "transit-switch"); } else if (dp_key_refresh) { /* Refresh tunnel key since encap mode has changed. */ int64_t dp_key = allocate_dp_key(dp_tnlids, vxlan_mode, @@ -339,9 +338,13 @@ ts_run(struct engine_context *ctx, } } - struct shash_node *node; - SHASH_FOR_EACH (node, isb_ts_dps) { - icsbrec_datapath_binding_delete(node->data); + struct shash_node *node, *next; + SHASH_FOR_EACH_SAFE (node, next, isb_ts_dps) { + struct icsbrec_datapath_binding *isb_dp_to_del = node->data; + if (isb_dp_to_del->n_nb_ic_uuid > 0) { + icsbrec_datapath_binding_delete(isb_dp_to_del); + } + shash_delete(isb_ts_dps, node); } } } @@ -3114,10 +3117,8 @@ ovn_db_run(struct ic_input *input_data, struct engine_context *eng_ctx) { gateway_run(eng_ctx, input_data); - enumerate_datapaths(input_data, &ic_data->dp_tnlids, - &ic_data->isb_ts_dps, &ic_data->isb_tr_dps); - 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); + 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); @@ -3522,6 +3523,7 @@ main(int argc, char *argv[]) ovn_conn_show, ovnisb_idl_loop.idl); stopwatch_create(IC_OVN_DB_RUN_STOPWATCH_NAME, SW_MS); + stopwatch_create(OVN_IC_ENUM_DATAPATHS_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 2c2efc046..9b0009274 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -66,10 +66,10 @@ struct ic_input { }; struct ic_data { - /* Global state for 'en-ic'. */ - struct hmap dp_tnlids; - struct shash isb_ts_dps; - struct shash isb_tr_dps; + /* Global state for 'en-enum-datapaths'. */ + struct hmap *dp_tnlids; + struct shash *isb_ts_dps; + struct shash *isb_tr_dps; }; struct ic_state { bool had_lock; diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index e933213d8..21572f023 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -41,5 +41,6 @@ #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route" #define IC_OVN_DB_RUN_STOPWATCH_NAME "ovn_db_run" +#define OVN_IC_ENUM_DATAPATHS_RUN_STOPWATCH_NAME "enum_datapaths_run" #endif From patchwork Mon Feb 9 18:28:08 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194714 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=ZqjsZxCX; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tW348z0z1xvc for ; Tue, 10 Feb 2026 05:28:47 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 49C7A83DDB; Mon, 9 Feb 2026 18:28:45 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 9Jxh6De57eM5; Mon, 9 Feb 2026 18:28:42 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 0516083DC2 Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=ZqjsZxCX Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTPS id 0516083DC2; Mon, 9 Feb 2026 18:28:42 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id C837AC077F; Mon, 9 Feb 2026 18:28:41 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1264DC077F for ; Mon, 9 Feb 2026 18:28:40 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id EDBA240B81 for ; Mon, 9 Feb 2026 18:28:34 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id Z8TgjFwFH7Y1 for ; Mon, 9 Feb 2026 18:28:33 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::112e; helo=mail-yw1-x112e.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org 7DE1F40B7A Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 7DE1F40B7A Authentication-Results: smtp2.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=ZqjsZxCX Received: from mail-yw1-x112e.google.com (mail-yw1-x112e.google.com [IPv6:2607:f8b0:4864:20::112e]) by smtp2.osuosl.org (Postfix) with ESMTPS id 7DE1F40B7A for ; Mon, 9 Feb 2026 18:28:32 +0000 (UTC) Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-794719afcd4so47903027b3.1 for ; Mon, 09 Feb 2026 10:28:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661711; x=1771266511; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qmPW5d95/ycOO7VIT3Q/7nUycTLBFC2JIz2OFOQcUG8=; b=ZqjsZxCXxneqQMX78E2W+SRmJnjuhhaHhnYxWHFyHaxXQA90L1R+B85csCtiak0gvE 2n8cx30dfR7zjwuh8/jbyzJ4ycCKhIe0BiQbYO5v5pspP/8HNMIfQrnR7YDRqLNM2m2B hE3UkTfdUlEHALbkiTC8wIHYwYjsAt5d/2vj0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661711; x=1771266511; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=qmPW5d95/ycOO7VIT3Q/7nUycTLBFC2JIz2OFOQcUG8=; b=XiIwT9mvbaIL1rHvZL5AETXptAx5d5EQsPSe0K6Cgo75vSs7loE/4+KFgVmq+8FtTM UszacgFT07n1b5e+5lj2K65SmsKkv0lqfI9BSDcEj1qLRh56qGk8Jmb18r3DcWW83woZ 7n5dYSW0Clh9yt1JL0DgRWcXricyQmnUPhTJya+R8t3shxBB1F/Q0aLP2lNuXnU78VHx NgNgn5TVS0EV7kBEKZPtNn2nZJFVMKNA2ybQ3FKPtc9EyBFHrzjeZ9ICX41sfmuA8O1G kJujjH7rq3iBDDKCfddRaPqkN4zvZM2b0kNyy71DTn10898ZKBkamIypYZEDlZ5Hu4zq zSqw== X-Gm-Message-State: AOJu0YxoyIl8eOo6fe7Pb01EkwJroabsz5GrgD255Eb9xC0lVol3grqR rp9mNWnvrqxtSxFUKBTmRRo0rjidAFgCkKZbLgwjoDUaxve5nz2Tb96JRCbpgLoZj/q/QKpOw+Y 5swQYH6oVWZjSfdbpYOjYwrH7tgjIYJGbpwBfN6b3IkCFNtWN3qeBv+N7eWKANwk= X-Gm-Gg: AZuq6aJL7xlgQ2h8bWcljMeqyZzIgq+slZYwJjHHvNBlJ0vk8ariDDGkYWXWndrkLsA hcIVkvvwCfP8ErXdTFDmDZ0As2qF4S72IrU5Zf6bu4trWCIdYo2temSpgK5pIZlxQ/TqjBuMPFY aHlO6j3gk35kRbuOeU0qOXl4sTGA1VU+q7up/o+bzNYrWfWA/plKs7n3FR+HU8EPTM0Xfhzbwsf pi9G4jiICYScrrs2ZjRrrRZ6ZFKF4oQYhWMs4NrPIsq7lgkT7MxZ5cVCZKf4XG86KHLB2GVP7Pf SuyFkdGxLmBsw9aBfCViTjQk1Ollqu1wRMX8byLnSZji7K4WcsIhAjVznk7V7pHXwCzLRFxpCc0 hl5zJIkDmW3rcDSG8oktbYopLOPHoHLle00EWi0rUbJXn6+XA8eyEcKtzutGdrawI/Pw3qXtl8b HilmVEi7Y2nDUaHienqreCyLkIS0+6yl0w/0xhGQ== X-Received: by 2002:a05:690c:906:b0:794:722c:3a2f with SMTP id 00721157ae682-7952aab5cb4mr106708247b3.31.1770661710264; Mon, 09 Feb 2026 10:28:30 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:29 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:08 -0300 Message-Id: <20260209182814.842-4-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 3/9] ovn-ic: Add a new engine-node 'port-binding'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" 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 --- 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 -- 2.34.1 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 + +#include +#include +#include + +/* 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 + +#include +#include +#include +#include + +/* 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 d7d247e7a..2d83a3e52 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, @@ -172,7 +174,16 @@ 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); @@ -194,11 +205,11 @@ 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 724201616..979779e1d 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.", @@ -3119,7 +2486,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(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 21572f023..55945edf9 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -42,5 +42,6 @@ #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 From patchwork Mon Feb 9 18:28:09 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194717 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=PmelH0jd; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tWG3TYWz1xvc for ; Tue, 10 Feb 2026 05:28:58 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 7E31D83DDD; Mon, 9 Feb 2026 18:28:56 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id TUfJ5HgyUwRa; Mon, 9 Feb 2026 18:28:49 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org 24DDE83D96 Authentication-Results: smtp1.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=PmelH0jd Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp1.osuosl.org (Postfix) with ESMTPS id 24DDE83D96; Mon, 9 Feb 2026 18:28:47 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E0BF3C0780; Mon, 9 Feb 2026 18:28:46 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3C8ACC077E for ; Mon, 9 Feb 2026 18:28:46 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 8CF6C40B88 for ; Mon, 9 Feb 2026 18:28:41 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id LL7XBQPjw90t for ; Mon, 9 Feb 2026 18:28:38 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::1136; helo=mail-yw1-x1136.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org EB7D940BA3 Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org EB7D940BA3 Authentication-Results: smtp2.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=PmelH0jd Received: from mail-yw1-x1136.google.com (mail-yw1-x1136.google.com [IPv6:2607:f8b0:4864:20::1136]) by smtp2.osuosl.org (Postfix) with ESMTPS id EB7D940BA3 for ; Mon, 9 Feb 2026 18:28:35 +0000 (UTC) Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-7964fb9ae3dso10575987b3.0 for ; Mon, 09 Feb 2026 10:28:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661714; x=1771266514; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=arYOyK8bo1qfhUmzo7iUtiGc9jyngw5wEJIi3dbKRQ8=; b=PmelH0jd/H5s5gARsqSqJtPJdBfPtb6uLZ6RYkZGVsj4hJy6A+jlRzSJoqCTAQIfy8 Q8hXsvnu2caCCoEcObMVKJ0JiS3seUybIlKj/3MRuYzuStskREb1ye4UWTOha8QX+A9a bjIEieqHj3/A/mSHgyoP3H6aQS4MY6hWeX40U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661714; x=1771266514; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=arYOyK8bo1qfhUmzo7iUtiGc9jyngw5wEJIi3dbKRQ8=; b=Szau5dWiNLARm0urpLwv8yaebfp0eQAhXDu3K2ygZSURwdVE9sRuV6b496wCw4rvfQ uczV/i4Bu3p4u4wCfQ9WP1UgScP+eGPZK9qrf2cYpgX55zxYPnQeRrAlGLOyD8gBeNmU gflxyz470DgM/UTSOZArOawKHBYxQ88L1GZSTjKOpegJevCXYmA9QoubWGUJvFsOQ3Ib 7iJPHWK85HzdPiF6k5PqIY4JIe4H1r+ivGiORSakasIvbvyxcpTLrLbwdwU6VeKeTivG 8YuMkbAncROKrh01uAW95tT5QERiVb9ox3Elx/0Xz2aBWFW/qFd3r0EWOfRFgDtbIaKM umcw== X-Gm-Message-State: AOJu0YzYSRtZnyW18xyGdwpKbiEOhH+ZTNRk1zWz740dKPM5rjYTD3wL BII3kYD7lNelkBksqJprVWf9LIbX8WnInFvG1reCxYptdlnTRPfP0zzl+CZ5H304wgb1GMkNmRw Hg19sbu2nCezOxHKEu3WF8J9x3SyCS1AGBNpdl+/SQT9PrjG30pIKRNAkCG/+1ro= X-Gm-Gg: AZuq6aK2fgkT7P0vd09k2geFyc6jAmsNcrWGBeR3mKZQSUl9qZU6lFrHQYQ/vQxUrGq 0teqmdLwtQ3w034s44FhfB1yvHfKDsd3sKLhgXKbZNU3zhQcM9M+00kReoONIk6JAHVjiJrASLr j3PgcFrMl6B3S49k8lEShogOKa3xYB2MrJ88dSIXW/GnH8u7yHeEfzUpHOpt2Ylisb/r8URGVP3 982RF0LdMUgRchrU3cLlb5960kU5PXN+eH+OrM5fFzMySfHUjy6Yv9vJcw2ms7mMwZePYUG9EiP iKfJ/EXsfwdl14cH06tBBMcglZSgWRhE/dX8mI8AF7hZCBeXrnQqg8gV+qTT7aFvSN08iVuujx9 cXmDFFKqzd/L4PxxHNjZshTFqtZgIpiY1OYN1AdB6uvtgncL9zcijtyOpp/roSlKu3hI3nHynML bsCrDh6RU8Mk2D+tjnKo6J223jK/FOLs576ShxAA== X-Received: by 2002:a05:690c:968f:b0:794:c5b8:7d1f with SMTP id 00721157ae682-7952aaa960cmr93862877b3.23.1770661713365; Mon, 09 Feb 2026 10:28:33 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:32 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:09 -0300 Message-Id: <20260209182814.842-5-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 4/9] ovn-ic: Add a new engine-node 'route'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This new engine now maintains the route related data for ovn-ic daemon which was earlier maintained by the ic engine node invoked the route_run() function. The inputs to this engine node are: en_nb_nb_global; en_nb_logical_switch; en_nb_logical_router; en_icnb_transit_switch; en_icsb_port_binding; en_icsb_route; en_nb_logical_router_static_route; In order to achieve this, we refactor in the following way: * Introduce route_init() which initializes this data. * Introduce route_destroy() which clears this data for a new iteration. * Introduce route_run() which invokes the full recompute of the engine. This engine node becomes an input to 'ic' node. Signed-off-by: Paulo Guilherme Silva --- ic/automake.mk | 2 + ic/en-ic.c | 18 - ic/en-route.c | 1554 +++++++++++++++++++++++++++++++++++++++++ ic/en-route.h | 70 ++ ic/inc-proc-ic.c | 15 +- ic/ovn-ic.c | 1300 +--------------------------------- ic/ovn-ic.h | 8 +- lib/stopwatch-names.h | 1 + 8 files changed, 1646 insertions(+), 1322 deletions(-) create mode 100644 ic/en-route.c create mode 100644 ic/en-route.h -- 2.34.1 diff --git a/ic/automake.mk b/ic/automake.mk index 91783df0f..24807a360 100644 --- a/ic/automake.mk +++ b/ic/automake.mk @@ -8,6 +8,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \ ic/en-enum-datapaths.h \ ic/en-port-binding.c \ ic/en-port-binding.h \ + ic/en-route.c \ + ic/en-route.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 e7c7ab71b..e0956bdee 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -44,8 +44,6 @@ ic_get_input_data(struct engine_node *node, struct ic_input *input_data) { /* Table references */ - input_data->nbrec_nb_global_table = - EN_OVSDB_GET(engine_get_input("NB_nb_global", node)); input_data->nbrec_logical_switch_table = EN_OVSDB_GET(engine_get_input("NB_logical_switch", node)); input_data->nbrec_logical_router_table = @@ -112,22 +110,6 @@ ic_get_input_data(struct engine_node *node, engine_ovsdb_node_get_index( engine_get_input("ICNB_transit_switch", node), "icnbrec_transit_switch_by_name"); - 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_route_by_az = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_route", node), - "icsbrec_route_by_az"); - input_data->icsbrec_route_by_ts = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_route", node), - "icsbrec_route_by_ts"); - input_data->icsbrec_route_by_ts_az = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_route", node), - "icsbrec_route_by_ts_az"); input_data->icsbrec_service_monitor_by_source_az = engine_ovsdb_node_get_index( engine_get_input("ICSB_service_monitor", node), diff --git a/ic/en-route.c b/ic/en-route.c new file mode 100644 index 000000000..d893a3dc0 --- /dev/null +++ b/ic/en-route.c @@ -0,0 +1,1554 @@ +/* + * 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 + +#include +#include +#include +#include "vec.h" + +/* OVS includes. */ +#include "openvswitch/vlog.h" + +/* OVN includes. */ +#include "ovn-ic.h" +#include "en-route.h" +#include "inc-proc-ic.h" +#include "lib/inc-proc-eng.h" +#include "lib/ovn-nb-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_route); +COVERAGE_DEFINE(route_run); + +static void +route_run(const struct engine_context *eng_ctx, + struct route_input *route_input, + struct ed_type_route *route_data, + const struct nbrec_logical_router_table *nb_lr_table, + const struct nbrec_nb_global_table *nb_global_table); +static void route_init(struct ed_type_route *data); +static void route_destroy(struct ed_type_route *data); +static void route_clear(struct ed_type_route *data); +static void route_get_input_data(struct engine_node *node, + struct route_input *input_data); + +static uint32_t + ic_route_hash(const struct in6_addr *prefix, unsigned int plen, + const struct in6_addr *nexthop, const char *origin, + const char *route_table); +static struct ic_route_info * + ic_route_find(struct hmap *routes, const struct in6_addr *prefix, + unsigned int plen, const struct in6_addr *nexthop, + const char *origin, const char *route_table, uint32_t hash); +static struct ic_router_info * + ic_router_find(struct hmap *ic_lrs, const struct nbrec_logical_router *lr); +static bool + parse_route(const char *s_prefix, const char *s_nexthop, + struct in6_addr *prefix, unsigned int *plen, + struct in6_addr *nexthop); +static bool + add_to_routes_learned(struct hmap *routes_learned, + const struct nbrec_logical_router_static_route *nb_route, + const struct nbrec_logical_router *nb_lr); +static bool + get_nexthop_from_lport_addresses(bool is_v4, + const struct lport_addresses *laddr, + struct in6_addr *nexthop); +static bool + prefix_is_filtered(struct in6_addr *prefix, + unsigned int plen, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_logical_router_port *ts_lrp, + bool is_advertisement); +static bool + prefix_is_deny_filtered(struct in6_addr *prefix, + unsigned int plen, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_logical_router_port *ts_lrp, + bool is_advertisement); +static bool + route_need_advertise(const char *policy, + struct in6_addr *prefix, + unsigned int plen, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_logical_router_port *ts_lrp); +static void + add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix, + unsigned int plen, const struct in6_addr nexthop, + const char *origin, const char *route_table, + const struct nbrec_logical_router_port *nb_lrp, + const struct nbrec_logical_router_static_route *nb_route, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_load_balancer *nb_lb, + const char *route_tag); +static void + add_static_to_routes_ad(struct hmap *routes_ad, + const struct nbrec_logical_router_static_route *nb_route, + const struct nbrec_logical_router *nb_lr, + const struct lport_addresses *nexthop_addresses, + const struct smap *nb_options, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp); +static void + add_network_to_routes_ad(struct hmap *routes_ad, const char *network, + const struct nbrec_logical_router_port *nb_lrp, + const struct lport_addresses *nexthop_addresses, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp); +static void + add_lb_vip_to_routes_ad(struct hmap *routes_ad, const char *vip_key, + const struct nbrec_load_balancer *nb_lb, + const struct lport_addresses *nexthop_addresses, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp); +static bool + route_has_local_gw(const struct nbrec_logical_router *lr, + const char *route_table, const char *ip_prefix); +static bool + lrp_has_neighbor_in_ts(const struct nbrec_logical_router_port *lrp, + struct in6_addr *nexthop); +static bool + route_matches_local_lb(const struct nbrec_load_balancer *nb_lb, + const char *ip_prefix); +static bool + route_need_learn(const struct nbrec_logical_router *lr, + const struct icsbrec_route *isb_route, + struct in6_addr *prefix, unsigned int plen, + const struct smap *nb_options, + const struct nbrec_logical_router_port *ts_lrp, + struct in6_addr *nexthop); +static const char * + get_lrp_name_by_ts_port_name(struct route_input *ic, + const char *ts_port_name); +static const struct nbrec_logical_router_port * + find_lrp_of_nexthop(struct route_input *ic, + const struct icsbrec_route *isb_route); +static bool + lrp_is_ts_port(struct route_input *ic, struct ic_router_info *ic_lr, + const char *lrp_name); +static void + sync_learned_routes(const struct engine_context *ctx, + struct route_input *ic, struct ic_router_info *ic_lr, + const struct nbrec_nb_global_table *nb_global_table); +static void + ad_route_sync_external_ids(const struct ic_route_info *route_adv, + const struct icsbrec_route *isb_route); +static void + advertise_routes(const struct engine_context *ctx, + struct route_input *ic, + const struct icsbrec_availability_zone *az, + const char *ts_name, struct hmap *routes_ad); +static void + build_ts_routes_to_adv(struct route_input *ic, + struct ic_router_info *ic_lr, + struct hmap *routes_ad, + struct lport_addresses *ts_port_addrs, + const struct nbrec_nb_global *nb_global, + const char *ts_route_table, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp); +static void + collect_lr_routes(struct route_input *ic, + struct ic_router_info *ic_lr, + struct shash *routes_ad_by_ts, + const struct nbrec_nb_global_table *nb_global_table); +static void + delete_orphan_ic_routes(struct route_input *ic, + const struct icsbrec_availability_zone *az); + +static void +route_get_input_data(struct engine_node *node, + struct route_input *input_data) +{ + /* Indexes */ + input_data->nbrec_ls_by_name = + engine_ovsdb_node_get_index( + engine_get_input("NB_logical_switch", node), + "nbrec_ls_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_lrp_by_name = + engine_ovsdb_node_get_index( + engine_get_input("NB_logical_router", node), + "nbrec_lrp_by_name"); + input_data->icnbrec_transit_switch_by_name = + engine_ovsdb_node_get_index( + engine_get_input("ICNB_transit_switch", node), + "icnbrec_transit_switch_by_name"); + 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_route_by_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_route", node), + "icsbrec_route_by_az"); + input_data->icsbrec_route_by_ts = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_route", node), + "icsbrec_route_by_ts"); + input_data->icsbrec_route_by_ts_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_route", node), + "icsbrec_route_by_ts_az"); +} + +enum engine_node_state +en_route_run(struct engine_node *node, void *data) +{ + const struct engine_context *eng_ctx = engine_get_context(); + struct ed_type_route *route_data = data; + struct route_input route_input; + + route_clear(route_data); + + const struct nbrec_logical_router_table *nb_lr_table = + EN_OVSDB_GET(engine_get_input("NB_logical_router", node)); + const struct nbrec_nb_global_table *nb_global_table = + EN_OVSDB_GET(engine_get_input("NB_nb_global", node)); + + route_get_input_data(node, &route_input); + route_input.runned_az = eng_ctx->client_ctx; + + COVERAGE_INC(route_run); + stopwatch_start(OVN_IC_ROUTE_RUN_STOPWATCH_NAME, time_usec()); + route_run(eng_ctx, &route_input, route_data, nb_lr_table, nb_global_table); + stopwatch_stop(OVN_IC_ROUTE_RUN_STOPWATCH_NAME, time_usec()); + + return EN_UPDATED; +} + +void * +en_route_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct ed_type_route *data = xzalloc(sizeof *data); + route_init(data); + return data; +} + +void +en_route_cleanup(void *data) +{ + route_destroy(data); +} + +static void +route_init(struct ed_type_route *data) +{ + hmap_init(&data->pb_tnlids); + shash_init(&data->switch_all_local_pbs); + shash_init(&data->router_all_local_pbs); +} + +static void +route_destroy(struct ed_type_route *data) +{ + route_clear(data); + ovn_destroy_tnlids(&data->pb_tnlids); + + shash_destroy(&data->switch_all_local_pbs); + shash_destroy(&data->router_all_local_pbs); +} + +static void +route_clear(struct ed_type_route *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 +route_run(const struct engine_context *eng_ctx, + struct route_input *route_input, + struct ed_type_route *route_data OVS_UNUSED, + const struct nbrec_logical_router_table *nb_lr_table, + const struct nbrec_nb_global_table *nb_global_table) +{ + if (!eng_ctx->ovnisb_idl_txn || !eng_ctx->ovnnb_idl_txn) { + return; + } + + delete_orphan_ic_routes(route_input, route_input->runned_az); + + struct hmap ic_lrs = HMAP_INITIALIZER(&ic_lrs); + const struct icsbrec_port_binding *isb_pb; + const struct icsbrec_port_binding *isb_pb_key = + icsbrec_port_binding_index_init_row( + route_input->icsbrec_port_binding_by_az); + icsbrec_port_binding_index_set_availability_zone(isb_pb_key, + route_input->runned_az); + + /* Each port on TS maps to a logical router, which is stored in the + * external_ids:router-id of the IC SB port_binding record. + * Here we build info for interconnected Logical Router: + * collect IC Port Binding to process routes sync later on. */ + ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, + route_input->icsbrec_port_binding_by_az) + { + if (ic_pb_get_type(isb_pb) == IC_ROUTER_PORT) { + continue; + } + const struct nbrec_logical_switch_port *nb_lsp; + + nb_lsp = get_lsp_by_ts_port_name(route_input->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.", + isb_pb->logical_port, isb_pb->transit_switch); + continue; + } + + const char *ts_lrp_name = + get_lrp_name_by_ts_port_name(route_input, isb_pb->logical_port); + if (!ts_lrp_name) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Route sync ignores port %s on ts %s because " + "logical router port is not found in NB. Deleting it", + isb_pb->logical_port, isb_pb->transit_switch); + icsbrec_port_binding_delete(isb_pb); + continue; + } + + struct uuid lr_uuid; + if (!smap_get_uuid(&isb_pb->external_ids, "router-id", &lr_uuid)) { + VLOG_DBG("IC-SB Port_Binding %s doesn't have " + "external_ids:router-id set.", isb_pb->logical_port); + continue; + } + + const struct nbrec_logical_router *lr + = nbrec_logical_router_table_get_for_uuid(nb_lr_table, &lr_uuid); + if (!lr) { + continue; + } + + struct ic_router_info *ic_lr = ic_router_find(&ic_lrs, lr); + if (!ic_lr) { + ic_lr = xzalloc(sizeof *ic_lr); + ic_lr->lr = lr; + ic_lr->isb_pbs = + VECTOR_EMPTY_INITIALIZER(const struct icsbrec_port_binding *); + hmap_init(&ic_lr->routes_learned); + hmap_insert(&ic_lrs, &ic_lr->node, uuid_hash(&lr->header_.uuid)); + } + vector_push(&ic_lr->isb_pbs, &isb_pb); + } + icsbrec_port_binding_index_destroy_row(isb_pb_key); + + struct ic_router_info *ic_lr; + struct shash routes_ad_by_ts = SHASH_INITIALIZER(&routes_ad_by_ts); + HMAP_FOR_EACH_SAFE (ic_lr, node, &ic_lrs) { + collect_lr_routes(route_input, ic_lr, &routes_ad_by_ts, + nb_global_table); + sync_learned_routes(eng_ctx, route_input, ic_lr, nb_global_table); + vector_destroy(&ic_lr->isb_pbs); + hmap_destroy(&ic_lr->routes_learned); + hmap_remove(&ic_lrs, &ic_lr->node); + free(ic_lr); + } + struct shash_node *node; + SHASH_FOR_EACH (node, &routes_ad_by_ts) { + advertise_routes(eng_ctx, route_input, route_input->runned_az, + node->name, node->data); + hmap_destroy(node->data); + } + shash_destroy_free_data(&routes_ad_by_ts); + hmap_destroy(&ic_lrs); +} + +static uint32_t +ic_route_hash(const struct in6_addr *prefix, unsigned int plen, + const struct in6_addr *nexthop, const char *origin, + const char *route_table) +{ + uint32_t basis = hash_bytes(prefix, sizeof *prefix, (uint32_t) plen); + basis = hash_string(origin, basis); + basis = hash_string(route_table, basis); + return hash_bytes(nexthop, sizeof *nexthop, basis); +} + +static struct ic_route_info * +ic_route_find(struct hmap *routes, const struct in6_addr *prefix, + unsigned int plen, const struct in6_addr *nexthop, + const char *origin, const char *route_table, uint32_t hash) +{ + struct ic_route_info *r; + if (!hash) { + hash = ic_route_hash(prefix, plen, nexthop, origin, route_table); + } + HMAP_FOR_EACH_WITH_HASH (r, node, hash, routes) { + if (ipv6_addr_equals(&r->prefix, prefix) && + r->plen == plen && + ipv6_addr_equals(&r->nexthop, nexthop) && + !strcmp(r->origin, origin) && + !strcmp(r->route_table ? r->route_table : "", route_table)) { + return r; + } + } + return NULL; +} + +static struct ic_router_info * +ic_router_find(struct hmap *ic_lrs, const struct nbrec_logical_router *lr) +{ + struct ic_router_info *ic_lr; + HMAP_FOR_EACH_WITH_HASH (ic_lr, node, uuid_hash(&lr->header_.uuid), + ic_lrs) { + if (ic_lr->lr == lr) { + return ic_lr; + } + } + return NULL; +} + +static bool +parse_route(const char *s_prefix, const char *s_nexthop, + struct in6_addr *prefix, unsigned int *plen, + struct in6_addr *nexthop) +{ + if (!ip46_parse_cidr(s_prefix, prefix, plen)) { + return false; + } + + unsigned int nlen; + if (strcmp(s_nexthop, "discard") && + !ip46_parse_cidr(s_nexthop, nexthop, &nlen)) { + return false; + } + + /* Do not learn routes with link-local next hop. */ + return !in6_is_lla(nexthop); +} + +/* Return false if can't be added due to bad format. */ +static bool +add_to_routes_learned(struct hmap *routes_learned, + const struct nbrec_logical_router_static_route *nb_route, + const struct nbrec_logical_router *nb_lr) +{ + struct in6_addr prefix, nexthop; + unsigned int plen; + if (!parse_route(nb_route->ip_prefix, nb_route->nexthop, + &prefix, &plen, &nexthop)) { + return false; + } + const char *origin = smap_get_def(&nb_route->options, "origin", ""); + if (ic_route_find(routes_learned, &prefix, plen, &nexthop, origin, + nb_route->route_table, 0)) { + /* Route was added to learned on previous iteration. */ + return true; + } + + struct ic_route_info *ic_route = xzalloc(sizeof *ic_route); + ic_route->prefix = prefix; + ic_route->plen = plen; + ic_route->nexthop = nexthop; + ic_route->nb_route = nb_route; + ic_route->origin = origin; + ic_route->route_table = nb_route->route_table; + ic_route->nb_lr = nb_lr; + hmap_insert(routes_learned, &ic_route->node, + ic_route_hash(&prefix, plen, &nexthop, origin, + nb_route->route_table)); + return true; +} + +static bool +get_nexthop_from_lport_addresses(bool is_v4, + const struct lport_addresses *laddr, + struct in6_addr *nexthop) +{ + if (is_v4) { + if (!laddr->n_ipv4_addrs) { + return false; + } + in6_addr_set_mapped_ipv4(nexthop, laddr->ipv4_addrs[0].addr); + return true; + } + + /* ipv6 */ + if (laddr->n_ipv6_addrs) { + *nexthop = laddr->ipv6_addrs[0].addr; + return true; + } + + /* ipv6 link local */ + in6_generate_lla(laddr->ea, nexthop); + return true; +} + +static bool +prefix_is_filtered(struct in6_addr *prefix, + unsigned int plen, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_logical_router_port *ts_lrp, + bool is_advertisement) +{ + struct ds filter_list = DS_EMPTY_INITIALIZER; + const char *filter_direction = is_advertisement ? "ic-route-filter-adv" : + "ic-route-filter-learn"; + if (ts_lrp) { + const char *lrp_route_filter = smap_get(&ts_lrp->options, + filter_direction); + if (lrp_route_filter) { + ds_put_format(&filter_list, "%s,", lrp_route_filter); + } + } + const char *lr_route_filter = smap_get(&nb_lr->options, + filter_direction); + if (lr_route_filter) { + ds_put_format(&filter_list, "%s,", lr_route_filter); + } + + struct sset prefix_set = SSET_INITIALIZER(&prefix_set); + sset_from_delimited_string(&prefix_set, ds_cstr(&filter_list), ","); + + bool matched = true; + if (!sset_is_empty(&prefix_set)) { + matched = find_prefix_in_set(prefix, plen, &prefix_set, + filter_direction); + } + + ds_destroy(&filter_list); + sset_destroy(&prefix_set); + return matched; +} + +static bool +prefix_is_deny_filtered(struct in6_addr *prefix, + unsigned int plen, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_logical_router_port *ts_lrp, + bool is_advertisement) +{ + struct ds deny_list = DS_EMPTY_INITIALIZER; + const char *deny_key = is_advertisement ? "ic-route-deny-adv" : + "ic-route-deny-learn"; + + if (ts_lrp) { + const char *lrp_deny_filter = smap_get(&ts_lrp->options, deny_key); + if (lrp_deny_filter) { + ds_put_format(&deny_list, "%s,", lrp_deny_filter); + } + } + + if (nb_lr) { + const char *lr_deny_filter = smap_get(&nb_lr->options, deny_key); + if (lr_deny_filter) { + ds_put_format(&deny_list, "%s,", lr_deny_filter); + } + } + + if (nb_options) { + const char *global_deny = smap_get(nb_options, "ic-route-denylist"); + if (!global_deny || !global_deny[0]) { + global_deny = smap_get(nb_options, "ic-route-blacklist"); + } + if (global_deny && global_deny[0]) { + ds_put_format(&deny_list, "%s,", global_deny); + } + } + + struct sset prefix_set = SSET_INITIALIZER(&prefix_set); + sset_from_delimited_string(&prefix_set, ds_cstr(&deny_list), ","); + + bool denied = false; + if (!sset_is_empty(&prefix_set)) { + denied = find_prefix_in_set(prefix, plen, &prefix_set, deny_key); + } + + ds_destroy(&deny_list); + sset_destroy(&prefix_set); + return denied; +} + +static bool +route_need_advertise(const char *policy, + struct in6_addr *prefix, + unsigned int plen, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_logical_router_port *ts_lrp) +{ + if (!smap_get_bool(nb_options, "ic-route-adv", false)) { + return false; + } + + if (plen == 0 && + !smap_get_bool(nb_options, "ic-route-adv-default", false)) { + return false; + } + + if (policy && !strcmp(policy, "src-ip")) { + return false; + } + + if (prefix_is_link_local(prefix, plen)) { + return false; + } + + if (prefix_is_deny_filtered(prefix, plen, nb_options, + nb_lr, ts_lrp, true)) { + return false; + } + + if (!prefix_is_filtered(prefix, plen, nb_lr, ts_lrp, true)) { + return false; + } + + return true; +} + +static void +add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix, + unsigned int plen, const struct in6_addr nexthop, + const char *origin, const char *route_table, + const struct nbrec_logical_router_port *nb_lrp, + const struct nbrec_logical_router_static_route *nb_route, + const struct nbrec_logical_router *nb_lr, + const struct nbrec_load_balancer *nb_lb, + const char *route_tag) +{ + ovs_assert(nb_route || nb_lrp || nb_lb); + + if (route_table == NULL) { + route_table = ""; + } + + uint hash = ic_route_hash(&prefix, plen, &nexthop, origin, route_table); + + if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, + route_table, hash)) { + struct ic_route_info *ic_route = xzalloc(sizeof *ic_route); + ic_route->prefix = prefix; + ic_route->plen = plen; + ic_route->nexthop = nexthop; + ic_route->nb_route = nb_route; + ic_route->origin = origin; + ic_route->route_table = route_table; + ic_route->nb_lrp = nb_lrp; + ic_route->nb_lr = nb_lr; + ic_route->nb_lb = nb_lb; + ic_route->route_tag = route_tag; + hmap_insert(routes_ad, &ic_route->node, hash); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + const char *msg_fmt = "Duplicate %s route advertisement was " + "suppressed! NB %s uuid: "UUID_FMT; + if (nb_route) { + VLOG_WARN_RL(&rl, msg_fmt, origin, "route", + UUID_ARGS(&nb_route->header_.uuid)); + } else if (nb_lb) { + VLOG_WARN_RL(&rl, msg_fmt, origin, "loadbalancer", + UUID_ARGS(&nb_lb->header_.uuid)); + } else { + VLOG_WARN_RL(&rl, msg_fmt, origin, "lrp", + UUID_ARGS(&nb_lrp->header_.uuid)); + } + } +} + +static void +add_static_to_routes_ad( + struct hmap *routes_ad, + const struct nbrec_logical_router_static_route *nb_route, + const struct nbrec_logical_router *nb_lr, + const struct lport_addresses *nexthop_addresses, + const struct smap *nb_options, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp) +{ + struct in6_addr prefix, nexthop; + unsigned int plen; + if (!parse_route(nb_route->ip_prefix, nb_route->nexthop, + &prefix, &plen, &nexthop)) { + return; + } + + if (!route_need_advertise(nb_route->policy, &prefix, plen, nb_options, + nb_lr, ts_lrp)) { + return; + } + + if (!get_nexthop_from_lport_addresses(IN6_IS_ADDR_V4MAPPED(&prefix), + nexthop_addresses, + &nexthop)) { + return; + } + + if (VLOG_IS_DBG_ENABLED()) { + struct ds msg = DS_EMPTY_INITIALIZER; + + ds_put_format(&msg, "Advertising static route: %s -> %s, ic nexthop: ", + nb_route->ip_prefix, nb_route->nexthop); + + if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { + ds_put_format(&msg, IP_FMT, + IP_ARGS(in6_addr_get_mapped_ipv4(&nexthop))); + } else { + ipv6_format_addr(&nexthop, &msg); + } + + ds_put_format(&msg, ", route_table: %s", nb_route->route_table[0] + ? nb_route->route_table + : "
"); + + VLOG_DBG("%s", ds_cstr(&msg)); + ds_destroy(&msg); + } + + add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_STATIC, + nb_route->route_table, NULL, nb_route, nb_lr, + NULL, route_tag); +} + +static void +add_network_to_routes_ad(struct hmap *routes_ad, const char *network, + const struct nbrec_logical_router_port *nb_lrp, + const struct lport_addresses *nexthop_addresses, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp) +{ + struct in6_addr prefix, nexthop; + unsigned int plen; + if (!ip46_parse_cidr(network, &prefix, &plen)) { + return; + } + + if (!route_need_advertise(NULL, &prefix, plen, nb_options, + nb_lr, ts_lrp)) { + VLOG_DBG("Route ad: skip network %s of lrp %s.", + network, nb_lrp->name); + return; + } + + if (!get_nexthop_from_lport_addresses(IN6_IS_ADDR_V4MAPPED(&prefix), + nexthop_addresses, + &nexthop)) { + return; + } + + if (VLOG_IS_DBG_ENABLED()) { + struct ds msg = DS_EMPTY_INITIALIZER; + + ds_put_format(&msg, "Adding direct network route to
routing " + "table: %s of lrp %s, nexthop ", network, nb_lrp->name); + + if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { + ds_put_format(&msg, IP_FMT, + IP_ARGS(in6_addr_get_mapped_ipv4(&nexthop))); + } else { + ipv6_format_addr(&nexthop, &msg); + } + + VLOG_DBG("%s", ds_cstr(&msg)); + ds_destroy(&msg); + } + + /* directly-connected routes go to
route table */ + add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_CONNECTED, + NULL, nb_lrp, NULL, nb_lr, NULL, route_tag); +} + +static void +add_lb_vip_to_routes_ad(struct hmap *routes_ad, const char *vip_key, + const struct nbrec_load_balancer *nb_lb, + const struct lport_addresses *nexthop_addresses, + const struct smap *nb_options, + const struct nbrec_logical_router *nb_lr, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp) +{ + char *vip_str = NULL; + struct in6_addr vip_ip, nexthop; + uint16_t vip_port; + int addr_family; + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + + if (!ip_address_and_port_from_lb_key(vip_key, &vip_str, &vip_ip, + &vip_port, &addr_family)) { + VLOG_WARN_RL(&rl, "Route ad: Parsing failed for lb vip %s", vip_key); + return; + } + if (vip_str == NULL) { + return; + } + unsigned int plen = (addr_family == AF_INET) ? 32 : 128; + if (!route_need_advertise(NULL, &vip_ip, plen, nb_options, + nb_lr, ts_lrp)) { + VLOG_DBG("Route ad: skip lb vip %s.", vip_key); + goto out; + } + if (!get_nexthop_from_lport_addresses(IN6_IS_ADDR_V4MAPPED(&vip_ip), + nexthop_addresses, + &nexthop)) { + VLOG_WARN_RL(&rl, "Route ad: failed to get nexthop for lb vip"); + goto out; + } + + if (VLOG_IS_DBG_ENABLED()) { + struct ds msg = DS_EMPTY_INITIALIZER; + + ds_put_format(&msg, "Adding lb vip route to
routing " + "table: %s, nexthop ", vip_str); + + if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { + ds_put_format(&msg, IP_FMT, + IP_ARGS(in6_addr_get_mapped_ipv4(&nexthop))); + } else { + ipv6_format_addr(&nexthop, &msg); + } + + VLOG_DBG("%s", ds_cstr(&msg)); + ds_destroy(&msg); + } + + /* Lb vip routes go to
route table */ + add_to_routes_ad(routes_ad, vip_ip, plen, nexthop, ROUTE_ORIGIN_LB, + NULL, NULL, NULL, nb_lr, nb_lb, route_tag); +out: + free(vip_str); +} + +static bool +route_has_local_gw(const struct nbrec_logical_router *lr, + const char *route_table, const char *ip_prefix) { + + const struct nbrec_logical_router_static_route *route; + for (int i = 0; i < lr->n_static_routes; i++) { + route = lr->static_routes[i]; + if (!smap_get(&route->external_ids, "ic-learned-route") && + !strcmp(route->route_table, route_table) && + !strcmp(route->ip_prefix, ip_prefix)) { + return true; + } + } + return false; +} + +static bool +lrp_has_neighbor_in_ts(const struct nbrec_logical_router_port *lrp, + struct in6_addr *nexthop) +{ + if (!lrp || !nexthop) { + return false; + } + + struct lport_addresses lrp_networks; + if (!extract_lrp_networks(lrp, &lrp_networks)) { + destroy_lport_addresses(&lrp_networks); + return false; + } + + if (IN6_IS_ADDR_V4MAPPED(nexthop)) { + ovs_be32 neigh_prefix_v4 = in6_addr_get_mapped_ipv4(nexthop); + for (size_t i = 0; i < lrp_networks.n_ipv4_addrs; i++) { + struct ipv4_netaddr address = lrp_networks.ipv4_addrs[i]; + if (address.network == (neigh_prefix_v4 & address.mask)) { + destroy_lport_addresses(&lrp_networks); + return true; + } + } + } else { + for (size_t i = 0; i < lrp_networks.n_ipv6_addrs; i++) { + struct ipv6_netaddr address = lrp_networks.ipv6_addrs[i]; + struct in6_addr neigh_prefix = ipv6_addr_bitand(nexthop, + &address.mask); + if (ipv6_addr_equals(&address.network, &neigh_prefix)) { + destroy_lport_addresses(&lrp_networks); + return true; + } + } + } + + destroy_lport_addresses(&lrp_networks); + return false; +} + +static bool +route_matches_local_lb(const struct nbrec_load_balancer *nb_lb, + const char *ip_prefix) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + struct in6_addr prefix; + unsigned int plen; + + if (!ip46_parse_cidr(ip_prefix, &prefix, &plen)) { + return false; + } + + struct smap_node *node; + SMAP_FOR_EACH (node, &nb_lb->vips) { + char *vip_str = NULL; + struct in6_addr vip_ip; + uint16_t vip_port; + int addr_family; + if (ip_address_and_port_from_lb_key(node->key, &vip_str, + &vip_ip, &vip_port, + &addr_family)) { + if (IN6_IS_ADDR_V4MAPPED(&prefix) && addr_family == AF_INET) { + ovs_be32 vip = in6_addr_get_mapped_ipv4(&vip_ip); + ovs_be32 mask = be32_prefix_mask(plen); + + if ((vip & mask) == in6_addr_get_mapped_ipv4(&prefix)) { + free(vip_str); + return true; + } + } else if (!IN6_IS_ADDR_V4MAPPED(&prefix) + && addr_family == AF_INET6) { + struct in6_addr mask = ipv6_create_mask(plen); + struct in6_addr vip_prefix = ipv6_addr_bitand(&vip_ip, &mask); + if (ipv6_addr_equals(&prefix, &vip_prefix)) { + free(vip_str); + return true; + } + } + free(vip_str); + } else { + VLOG_WARN_RL(&rl, + "Route learn: Parsing failed for local lb vip %s", + node->key); + } + } + return false; +} + +static bool +route_need_learn(const struct nbrec_logical_router *lr, + const struct icsbrec_route *isb_route, + struct in6_addr *prefix, unsigned int plen, + const struct smap *nb_options, + const struct nbrec_logical_router_port *ts_lrp, + struct in6_addr *nexthop) +{ + if (!smap_get_bool(nb_options, "ic-route-learn", false)) { + return false; + } + + if (plen == 0 && + !smap_get_bool(nb_options, "ic-route-learn-default", false)) { + return false; + } + + if (!strcmp(isb_route->origin, ROUTE_ORIGIN_LB) && + !smap_get_bool(nb_options, "ic-route-learn-lb", false)) { + return false; + } + + if (!lrouter_is_enabled(lr)) { + return false; + } + + if (prefix_is_link_local(prefix, plen)) { + return false; + } + + if (prefix_is_deny_filtered(prefix, plen, nb_options, lr, ts_lrp, false)) { + return false; + } + + if (!prefix_is_filtered(prefix, plen, lr, ts_lrp, false)) { + return false; + } + + if (route_has_local_gw(lr, isb_route->route_table, isb_route->ip_prefix)) { + VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got one with " + "local GW", isb_route->ip_prefix, isb_route->route_table); + return false; + } + + if (!lrp_has_neighbor_in_ts(ts_lrp, nexthop)) { + return false; + } + + for (size_t i = 0; i < lr->n_load_balancer; i++) { + if (route_matches_local_lb(lr->load_balancer[i], + isb_route->ip_prefix)) { + VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got local" + " LB with matching VIP", isb_route->ip_prefix, + isb_route->route_table); + return false; + } + } + for (size_t i = 0; i < lr->n_load_balancer_group; i++) { + const struct nbrec_load_balancer_group *nb_lbg = + lr->load_balancer_group[i]; + for (size_t j = 0; j < nb_lbg->n_load_balancer; j++) { + if (route_matches_local_lb(nb_lbg->load_balancer[j], + isb_route->ip_prefix)) { + VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got local" + " LB with matching VIP", isb_route->ip_prefix, + isb_route->route_table); + return false; + } + } + } + + return true; +} + +static const char * +get_lrp_name_by_ts_port_name(struct route_input *ic, const char *ts_port_name) +{ + const struct nbrec_logical_switch_port *nb_lsp; + + nb_lsp = get_lsp_by_ts_port_name(ic->nbrec_port_by_name, ts_port_name); + if (!nb_lsp) { + return NULL; + } + + return smap_get(&nb_lsp->options, "router-port"); +} + +static const struct nbrec_logical_router_port * +find_lrp_of_nexthop(struct route_input *ic, + const struct icsbrec_route *isb_route) +{ + const struct nbrec_logical_router_port *lrp; + const struct nbrec_logical_switch *ls; + ls = find_ts_in_nb(ic->nbrec_ls_by_name, isb_route->transit_switch); + if (!ls) { + return NULL; + } + + struct in6_addr nexthop; + if (!ip46_parse(isb_route->nexthop, &nexthop)) { + return NULL; + } + + for (size_t i = 0; i < ls->n_ports; i++) { + char *lsp_name = ls->ports[i]->name; + const char *lrp_name = get_lrp_name_by_ts_port_name(ic, + lsp_name); + if (!lrp_name) { + continue; + } + + lrp = get_lrp_by_lrp_name(ic->nbrec_lrp_by_name, lrp_name); + if (!lrp) { + continue; + } + + struct lport_addresses lrp_networks; + if (!extract_lrp_networks(lrp, &lrp_networks)) { + destroy_lport_addresses(&lrp_networks); + continue; + } + + if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { + ovs_be32 nexthop_v4 = in6_addr_get_mapped_ipv4(&nexthop); + for (size_t i_v4 = 0; i_v4 < lrp_networks.n_ipv4_addrs; i_v4++) { + struct ipv4_netaddr address = lrp_networks.ipv4_addrs[i_v4]; + if (address.addr == nexthop_v4) { + destroy_lport_addresses(&lrp_networks); + return lrp; + } + } + } else { + for (size_t i_v6 = 0; i_v6 < lrp_networks.n_ipv6_addrs; i_v6++) { + struct ipv6_netaddr address = lrp_networks.ipv6_addrs[i_v6]; + struct in6_addr nexthop_v6 = ipv6_addr_bitand(&nexthop, + &address.mask); + if (ipv6_addr_equals(&address.network, &nexthop_v6)) { + destroy_lport_addresses(&lrp_networks); + return lrp; + } + } + } + destroy_lport_addresses(&lrp_networks); + } + + return NULL; +} + +static bool +lrp_is_ts_port(struct route_input *ic, struct ic_router_info *ic_lr, + const char *lrp_name) +{ + const struct icsbrec_port_binding *isb_pb; + const char *ts_lrp_name; + VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { + ts_lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); + if (!strcmp(ts_lrp_name, lrp_name)) { + return true; + } + } + return false; +} + +static void +sync_learned_routes(const struct engine_context *ctx, + struct route_input *ic, + struct ic_router_info *ic_lr, + const struct nbrec_nb_global_table *nb_global_table) +{ + ovs_assert(ctx->ovnnb_idl_txn); + const struct icsbrec_route *isb_route, *isb_route_key; + + const struct nbrec_nb_global *nb_global = + nbrec_nb_global_table_first(nb_global_table); + ovs_assert(nb_global); + + const char *lrp_name, *ts_route_table, *route_filter_tag; + const struct icsbrec_port_binding *isb_pb; + const struct nbrec_logical_router_port *lrp; + VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { + if (!strcmp(isb_pb->address, "")) { + continue; + } + lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); + lrp = get_lrp_by_lrp_name(ic->nbrec_lrp_by_name, lrp_name); + if (lrp) { + ts_route_table = smap_get_def(&lrp->options, "route_table", ""); + route_filter_tag = smap_get_def(&lrp->options, + "ic-route-filter-tag", ""); + } else { + ts_route_table = ""; + route_filter_tag = ""; + } + + isb_route_key = icsbrec_route_index_init_row(ic->icsbrec_route_by_ts); + icsbrec_route_index_set_transit_switch(isb_route_key, + isb_pb->transit_switch); + + ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, + ic->icsbrec_route_by_ts) { + /* Filters ICSB routes, skipping those that either belong to + * current logical router or are legacy routes from the current + * availability zone (withoud lr-id). + */ + const char *lr_id = smap_get(&isb_route->external_ids, "lr-id"); + struct uuid lr_uuid; + if (lr_id) { + if (!uuid_from_string(&lr_uuid, lr_id) + || uuid_equals(&ic_lr->lr->header_.uuid, &lr_uuid)) { + continue; + } + } else if (isb_route->availability_zone == ic->runned_az) { + continue; + } + + const char *isb_route_tag = smap_get(&isb_route->external_ids, + "ic-route-tag"); + if (isb_route_tag && !strcmp(isb_route_tag, route_filter_tag)) { + VLOG_DBG("Skip learning route %s -> %s as its route tag " + "[%s] is filtered by the filter tag [%s] of TS LRP ", + isb_route->ip_prefix, isb_route->nexthop, + isb_route_tag, route_filter_tag); + continue; + } + + if (isb_route->route_table[0] && + strcmp(isb_route->route_table, ts_route_table)) { + if (VLOG_IS_DBG_ENABLED()) { + VLOG_DBG("Skip learning static route %s -> %s as either " + "its route table %s != %s of TS port or ", + isb_route->ip_prefix, isb_route->nexthop, + isb_route->route_table, ts_route_table); + } + continue; + } + + struct in6_addr prefix, nexthop; + unsigned int plen; + if (!parse_route(isb_route->ip_prefix, isb_route->nexthop, + &prefix, &plen, &nexthop)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Bad route format in IC-SB: %s -> %s. " + "Ignored.", isb_route->ip_prefix, + isb_route->nexthop); + continue; + } + if (!route_need_learn(ic_lr->lr, isb_route, &prefix, plen, + &nb_global->options, lrp, &nexthop)) { + continue; + } + + struct ic_route_info *route_learned + = ic_route_find(&ic_lr->routes_learned, &prefix, plen, + &nexthop, isb_route->origin, + isb_route->route_table, 0); + if (route_learned) { + /* Sync external-ids */ + struct uuid ext_id; + smap_get_uuid(&route_learned->nb_route->external_ids, + "ic-learned-route", &ext_id); + if (!uuid_equals(&ext_id, &isb_route->header_.uuid)) { + char *uuid_s = + xasprintf(UUID_FMT, + UUID_ARGS(&isb_route->header_.uuid)); + nbrec_logical_router_static_route_update_external_ids_setkey( + route_learned->nb_route, "ic-learned-route", uuid_s); + free(uuid_s); + } + hmap_remove(&ic_lr->routes_learned, &route_learned->node); + free(route_learned); + } else { + /* Create the missing route in NB. */ + const struct nbrec_logical_router_static_route *nb_route = + nbrec_logical_router_static_route_insert( + ctx->ovnnb_idl_txn); + nbrec_logical_router_static_route_set_ip_prefix(nb_route, + isb_route->ip_prefix); + nbrec_logical_router_static_route_set_nexthop(nb_route, + isb_route->nexthop); + char *uuid_s = xasprintf(UUID_FMT, + UUID_ARGS(&isb_route->header_.uuid)); + nbrec_logical_router_static_route_set_route_table(nb_route, + isb_route->route_table); + nbrec_logical_router_static_route_update_external_ids_setkey( + nb_route, "ic-learned-route", uuid_s); + nbrec_logical_router_static_route_update_options_setkey( + nb_route, "origin", isb_route->origin); + free(uuid_s); + nbrec_logical_router_update_static_routes_addvalue(ic_lr->lr, + nb_route); + } + } + icsbrec_route_index_destroy_row(isb_route_key); + } + + /* Delete extra learned routes. */ + struct ic_route_info *route_learned; + HMAP_FOR_EACH_SAFE (route_learned, node, &ic_lr->routes_learned) { + VLOG_DBG("Delete route %s -> %s that is not in IC-SB from NB.", + route_learned->nb_route->ip_prefix, + route_learned->nb_route->nexthop); + nbrec_logical_router_update_static_routes_delvalue( + ic_lr->lr, route_learned->nb_route); + hmap_remove(&ic_lr->routes_learned, &route_learned->node); + free(route_learned); + } +} + +static void +ad_route_sync_external_ids(const struct ic_route_info *route_adv, + const struct icsbrec_route *isb_route) +{ + struct uuid isb_ext_id, nb_id, isb_ext_lr_id, lr_id; + const char *route_tag; + smap_get_uuid(&isb_route->external_ids, "nb-id", &isb_ext_id); + smap_get_uuid(&isb_route->external_ids, "lr-id", &isb_ext_lr_id); + nb_id = route_adv->nb_lb ? route_adv->nb_lb->header_.uuid : + route_adv->nb_route ? route_adv->nb_route->header_.uuid : + route_adv->nb_lrp->header_.uuid; + + lr_id = route_adv->nb_lr->header_.uuid; + if (!uuid_equals(&isb_ext_id, &nb_id)) { + char *uuid_s = xasprintf(UUID_FMT, UUID_ARGS(&nb_id)); + icsbrec_route_update_external_ids_setkey(isb_route, "nb-id", + uuid_s); + free(uuid_s); + } + if (!uuid_equals(&isb_ext_lr_id, &lr_id)) { + char *uuid_s = xasprintf(UUID_FMT, UUID_ARGS(&lr_id)); + icsbrec_route_update_external_ids_setkey(isb_route, "lr-id", + uuid_s); + free(uuid_s); + } + if (strcmp(route_adv->route_tag, "")) { + icsbrec_route_update_external_ids_setkey(isb_route, "ic-route-tag", + route_adv->route_tag); + } else { + route_tag = smap_get(&isb_route->external_ids, "ic-route-tag"); + if (route_tag) { + icsbrec_route_update_external_ids_delkey(isb_route, + "ic-route-tag"); + } + } +} + +/* Sync routes from routes_ad to IC-SB. */ +static void +advertise_routes(const struct engine_context *ctx, + struct route_input *ic, + const struct icsbrec_availability_zone *az, + const char *ts_name, struct hmap *routes_ad) +{ + ovs_assert(ctx->ovnisb_idl_txn); + const struct icsbrec_route *isb_route; + const struct icsbrec_route *isb_route_key = + icsbrec_route_index_init_row(ic->icsbrec_route_by_ts_az); + icsbrec_route_index_set_transit_switch(isb_route_key, ts_name); + icsbrec_route_index_set_availability_zone(isb_route_key, az); + + ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, + ic->icsbrec_route_by_ts_az) { + struct in6_addr prefix, nexthop; + unsigned int plen; + + if (!parse_route(isb_route->ip_prefix, isb_route->nexthop, + &prefix, &plen, &nexthop)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Bad route format in IC-SB: %s -> %s. " + "Delete it.", + isb_route->ip_prefix, isb_route->nexthop); + icsbrec_route_delete(isb_route); + continue; + } + struct ic_route_info *route_adv = + ic_route_find(routes_ad, &prefix, plen, &nexthop, + isb_route->origin, isb_route->route_table, 0); + if (!route_adv) { + /* Delete the extra route from IC-SB. */ + VLOG_DBG("Delete route %s -> %s from IC-SB, which is not found" + " in local routes to be advertised.", + isb_route->ip_prefix, isb_route->nexthop); + icsbrec_route_delete(isb_route); + } else { + ad_route_sync_external_ids(route_adv, isb_route); + + hmap_remove(routes_ad, &route_adv->node); + free(route_adv); + } + } + icsbrec_route_index_destroy_row(isb_route_key); + + /* Create the missing routes in IC-SB */ + struct ic_route_info *route_adv; + HMAP_FOR_EACH_SAFE (route_adv, node, routes_ad) { + isb_route = icsbrec_route_insert(ctx->ovnisb_idl_txn); + icsbrec_route_set_transit_switch(isb_route, ts_name); + icsbrec_route_set_availability_zone(isb_route, az); + + char *prefix_s, *nexthop_s; + if (IN6_IS_ADDR_V4MAPPED(&route_adv->prefix)) { + ovs_be32 ipv4 = in6_addr_get_mapped_ipv4(&route_adv->prefix); + ovs_be32 nh = in6_addr_get_mapped_ipv4(&route_adv->nexthop); + prefix_s = xasprintf(IP_FMT "/%d", IP_ARGS(ipv4), route_adv->plen); + nexthop_s = xasprintf(IP_FMT, IP_ARGS(nh)); + } else { + char network_s[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &route_adv->prefix, network_s, + INET6_ADDRSTRLEN); + prefix_s = xasprintf("%s/%d", network_s, route_adv->plen); + inet_ntop(AF_INET6, &route_adv->nexthop, network_s, + INET6_ADDRSTRLEN); + nexthop_s = xstrdup(network_s); + } + icsbrec_route_set_ip_prefix(isb_route, prefix_s); + icsbrec_route_set_nexthop(isb_route, nexthop_s); + icsbrec_route_set_origin(isb_route, route_adv->origin); + icsbrec_route_set_route_table(isb_route, route_adv->route_table + ? route_adv->route_table + : ""); + free(prefix_s); + free(nexthop_s); + + ad_route_sync_external_ids(route_adv, isb_route); + + hmap_remove(routes_ad, &route_adv->node); + free(route_adv); + } +} + +static void +build_ts_routes_to_adv(struct route_input *ic, + struct ic_router_info *ic_lr, + struct hmap *routes_ad, + struct lport_addresses *ts_port_addrs, + const struct nbrec_nb_global *nb_global, + const char *ts_route_table, + const char *route_tag, + const struct nbrec_logical_router_port *ts_lrp) +{ + const struct nbrec_logical_router *lr = ic_lr->lr; + + /* Check static routes of the LR */ + for (int i = 0; i < lr->n_static_routes; i++) { + const struct nbrec_logical_router_static_route *nb_route + = lr->static_routes[i]; + struct uuid isb_uuid; + if (smap_get_uuid(&nb_route->external_ids, "ic-learned-route", + &isb_uuid)) { + /* It is a learned route */ + if (!add_to_routes_learned(&ic_lr->routes_learned, nb_route, lr)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Bad format of learned route in NB: " + "%s -> %s. Delete it.", nb_route->ip_prefix, + nb_route->nexthop); + nbrec_logical_router_update_static_routes_delvalue(lr, + nb_route); + } + } else if (!strcmp(ts_route_table, nb_route->route_table)) { + /* It may be a route to be advertised */ + add_static_to_routes_ad(routes_ad, nb_route, lr, ts_port_addrs, + &nb_global->options, route_tag, ts_lrp); + } + } + + /* Check directly-connected subnets of the LR */ + for (int i = 0; i < lr->n_ports; i++) { + const struct nbrec_logical_router_port *lrp = lr->ports[i]; + if (!lrp_is_ts_port(ic, ic_lr, lrp->name)) { + for (int j = 0; j < lrp->n_networks; j++) { + add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp, + ts_port_addrs, + &nb_global->options, + lr, route_tag, ts_lrp); + } + } else { + /* The router port of the TS port is ignored. */ + VLOG_DBG("Skip advertising direct route of lrp %s (TS port)", + lrp->name); + } + } + + /* Check loadbalancers associated with the LR */ + if (smap_get_bool(&nb_global->options, "ic-route-adv-lb", false)) { + for (size_t i = 0; i < lr->n_load_balancer; i++) { + const struct nbrec_load_balancer *nb_lb = lr->load_balancer[i]; + struct smap_node *node; + SMAP_FOR_EACH (node, &nb_lb->vips) { + add_lb_vip_to_routes_ad(routes_ad, node->key, nb_lb, + ts_port_addrs, + &nb_global->options, + lr, route_tag, ts_lrp); + } + } + + for (size_t i = 0; i < lr->n_load_balancer_group; i++) { + const struct nbrec_load_balancer_group *nb_lbg = + lr->load_balancer_group[i]; + for (size_t j = 0; j < nb_lbg->n_load_balancer; j++) { + const struct nbrec_load_balancer *nb_lb = + nb_lbg->load_balancer[j]; + struct smap_node *node; + SMAP_FOR_EACH (node, &nb_lb->vips) { + add_lb_vip_to_routes_ad(routes_ad, node->key, nb_lb, + ts_port_addrs, + &nb_global->options, + lr, route_tag, ts_lrp); + } + } + } + } +} + +static void +collect_lr_routes(struct route_input *ic, + struct ic_router_info *ic_lr, + struct shash *routes_ad_by_ts, + const struct nbrec_nb_global_table *nb_global_table) +{ + const struct nbrec_nb_global *nb_global = + nbrec_nb_global_table_first(nb_global_table); + + ovs_assert(nb_global); + + const struct icsbrec_port_binding *isb_pb; + const char *lrp_name, *ts_name, *route_table, *route_tag; + struct lport_addresses ts_port_addrs; + const struct icnbrec_transit_switch *key; + const struct nbrec_logical_router_port *lrp; + + struct hmap *routes_ad; + const struct icnbrec_transit_switch *t_sw; + VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { + key = icnbrec_transit_switch_index_init_row( + ic->icnbrec_transit_switch_by_name); + icnbrec_transit_switch_index_set_name(key, isb_pb->transit_switch); + t_sw = icnbrec_transit_switch_index_find( + ic->icnbrec_transit_switch_by_name, key); + icnbrec_transit_switch_index_destroy_row(key); + if (!t_sw) { + continue; + } + ts_name = t_sw->name; + routes_ad = shash_find_data(routes_ad_by_ts, ts_name); + if (!routes_ad) { + routes_ad = xzalloc(sizeof *routes_ad); + hmap_init(routes_ad); + shash_add(routes_ad_by_ts, ts_name, routes_ad); + } + + if (!extract_lsp_addresses(isb_pb->address, &ts_port_addrs)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_INFO_RL(&rl, "Route sync ignores port %s on ts %s for router" + " %s because the addresses are invalid.", + isb_pb->logical_port, isb_pb->transit_switch, + ic_lr->lr->name); + continue; + } + lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); + lrp = get_lrp_by_lrp_name(ic->nbrec_lrp_by_name, lrp_name); + if (lrp) { + route_table = smap_get_def(&lrp->options, "route_table", ""); + route_tag = smap_get_def(&lrp->options, "ic-route-tag", ""); + } else { + route_table = ""; + route_tag = ""; + } + build_ts_routes_to_adv(ic, ic_lr, routes_ad, &ts_port_addrs, + nb_global, route_table, route_tag, lrp); + destroy_lport_addresses(&ts_port_addrs); + } +} + +static void +delete_orphan_ic_routes(struct route_input *ic, + const struct icsbrec_availability_zone *az) +{ + const struct icsbrec_route *isb_route, *isb_route_key = + icsbrec_route_index_init_row(ic->icsbrec_route_by_az); + icsbrec_route_index_set_availability_zone(isb_route_key, az); + + const struct icnbrec_transit_switch *t_sw, *t_sw_key; + + ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, + ic->icsbrec_route_by_az) + { + t_sw_key = icnbrec_transit_switch_index_init_row( + ic->icnbrec_transit_switch_by_name); + icnbrec_transit_switch_index_set_name(t_sw_key, + isb_route->transit_switch); + t_sw = icnbrec_transit_switch_index_find( + ic->icnbrec_transit_switch_by_name, t_sw_key); + icnbrec_transit_switch_index_destroy_row(t_sw_key); + + if (!t_sw || !find_lrp_of_nexthop(ic, isb_route)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_INFO_RL(&rl, "Deleting orphan ICDB:Route: %s->%s (%s, rtb:%s," + " transit switch: %s)", isb_route->ip_prefix, + isb_route->nexthop, isb_route->origin, + isb_route->route_table, isb_route->transit_switch); + icsbrec_route_delete(isb_route); + } + } + icsbrec_route_index_destroy_row(isb_route_key); +} diff --git a/ic/en-route.h b/ic/en-route.h new file mode 100644 index 000000000..2365edcbf --- /dev/null +++ b/ic/en-route.h @@ -0,0 +1,70 @@ +#ifndef EN_IC_ROUTE_H +#define EN_IC_ROUTE_H 1 + +#include + +#include +#include +#include +#include +#include "vec.h" + +/* OVN includes. */ +#include "lib/inc-proc-eng.h" + +struct ed_type_route { + struct hmap pb_tnlids; + struct shash switch_all_local_pbs; + struct shash router_all_local_pbs; +}; + +struct ic_router_info { + struct hmap_node node; + const struct nbrec_logical_router *lr; /* key of hmap */ + struct vector isb_pbs; /* Vector of const struct icsbrec_port_binding *. */ + struct hmap routes_learned; +}; + +/* Represents an interconnection route entry. */ +struct ic_route_info { + struct hmap_node node; + struct in6_addr prefix; + unsigned int plen; + struct in6_addr nexthop; + const char *origin; + const char *route_table; + const char *route_tag; + + const struct nbrec_logical_router *nb_lr; + + /* One of nb_route, nb_lrp, nb_lb is set and the other ones must be NULL. + * - For a route that is learned from IC-SB, or a static route that is + * generated from a route that is configured in NB, the "nb_route" + * is set. + * - For a route that is generated from a direct-connect subnet of + * a logical router port, the "nb_lrp" is set. + * - For a route that is generated from a load-balancer vip of + * a logical router, the "nb_lb" is set. */ + const struct nbrec_logical_router_static_route *nb_route; + const struct nbrec_logical_router_port *nb_lrp; + const struct nbrec_load_balancer *nb_lb; +}; + +struct route_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_lrp_by_name; + 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; + struct ovsdb_idl_index *icsbrec_port_binding_by_az; + struct ovsdb_idl_index *icnbrec_transit_switch_by_name; +}; + +void *en_route_init(struct engine_node *, struct engine_arg *); +enum engine_node_state en_route_run(struct engine_node *, void *data); +void en_route_cleanup(void *data); + +#endif diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 2d83a3e52..177647119 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -29,6 +29,7 @@ #include "en-ic.h" #include "en-enum-datapaths.h" #include "en-port-binding.h" +#include "en-route.h" #include "unixctl.h" #include "util.h" @@ -162,6 +163,7 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic); static ENGINE_NODE(ic, SB_WRITE); static ENGINE_NODE(enum_datapaths); static ENGINE_NODE(port_binding, SB_WRITE); +static ENGINE_NODE(route); void inc_proc_ic_init(struct ovsdb_idl_loop *nb, @@ -182,10 +184,18 @@ inc_proc_ic_init(struct ovsdb_idl_loop *nb, 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_route, &en_nb_nb_global, NULL); + engine_add_input(&en_route, &en_nb_logical_switch, NULL); + engine_add_input(&en_route, &en_nb_logical_router, NULL); + engine_add_input(&en_route, &en_icnb_transit_switch, NULL); + engine_add_input(&en_route, &en_icsb_port_binding, NULL); + 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_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_route, NULL); + engine_add_input(&en_ic, &en_nb_logical_router, NULL); engine_add_input(&en_ic, &en_nb_logical_router_port, NULL); engine_add_input(&en_ic, &en_nb_logical_switch, NULL); @@ -211,7 +221,6 @@ inc_proc_ic_init(struct ovsdb_idl_loop *nb, 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_route, NULL); engine_add_input(&en_ic, &en_icsb_datapath_binding, NULL); struct engine_arg engine_arg = { diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 979779e1d..b97ba5624 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -577,14 +577,15 @@ gateway_run(struct engine_context *ctx, } const struct nbrec_logical_router_port * -get_lrp_by_lrp_name(struct ic_input *ic, const char *lrp_name) +get_lrp_by_lrp_name(struct ovsdb_idl_index *nbrec_lrp_by_name, + 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_init_row(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_find(nbrec_lrp_by_name, lrp_key); nbrec_logical_router_port_index_destroy_row(lrp_key); return lrp; @@ -643,1297 +644,6 @@ find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, return pb; } -struct ic_router_info { - struct hmap_node node; - const struct nbrec_logical_router *lr; /* key of hmap */ - struct vector isb_pbs; /* Vector of const struct icsbrec_port_binding *. */ - struct hmap routes_learned; -}; - -/* Represents an interconnection route entry. */ -struct ic_route_info { - struct hmap_node node; - struct in6_addr prefix; - unsigned int plen; - struct in6_addr nexthop; - const char *origin; - const char *route_table; - const char *route_tag; - - const struct nbrec_logical_router *nb_lr; - - /* One of nb_route, nb_lrp, nb_lb is set and the other ones must be NULL. - * - For a route that is learned from IC-SB, or a static route that is - * generated from a route that is configured in NB, the "nb_route" - * is set. - * - For a route that is generated from a direct-connect subnet of - * a logical router port, the "nb_lrp" is set. - * - For a route that is generated from a load-balancer vip of - * a logical router, the "nb_lb" is set. */ - const struct nbrec_logical_router_static_route *nb_route; - const struct nbrec_logical_router_port *nb_lrp; - const struct nbrec_load_balancer *nb_lb; -}; - -static uint32_t -ic_route_hash(const struct in6_addr *prefix, unsigned int plen, - const struct in6_addr *nexthop, const char *origin, - const char *route_table) -{ - uint32_t basis = hash_bytes(prefix, sizeof *prefix, (uint32_t)plen); - basis = hash_string(origin, basis); - basis = hash_string(route_table, basis); - return hash_bytes(nexthop, sizeof *nexthop, basis); -} - -static struct ic_route_info * -ic_route_find(struct hmap *routes, const struct in6_addr *prefix, - unsigned int plen, const struct in6_addr *nexthop, - const char *origin, const char *route_table, uint32_t hash) -{ - struct ic_route_info *r; - if (!hash) { - hash = ic_route_hash(prefix, plen, nexthop, origin, route_table); - } - HMAP_FOR_EACH_WITH_HASH (r, node, hash, routes) { - if (ipv6_addr_equals(&r->prefix, prefix) && - r->plen == plen && - ipv6_addr_equals(&r->nexthop, nexthop) && - !strcmp(r->origin, origin) && - !strcmp(r->route_table ? r->route_table : "", route_table)) { - return r; - } - } - return NULL; -} - -static struct ic_router_info * -ic_router_find(struct hmap *ic_lrs, const struct nbrec_logical_router *lr) -{ - struct ic_router_info *ic_lr; - HMAP_FOR_EACH_WITH_HASH (ic_lr, node, uuid_hash(&lr->header_.uuid), - ic_lrs) { - if (ic_lr->lr == lr) { - return ic_lr; - } - } - return NULL; -} - -static bool -parse_route(const char *s_prefix, const char *s_nexthop, - struct in6_addr *prefix, unsigned int *plen, - struct in6_addr *nexthop) -{ - if (!ip46_parse_cidr(s_prefix, prefix, plen)) { - return false; - } - - unsigned int nlen; - if (strcmp(s_nexthop, "discard") && - !ip46_parse_cidr(s_nexthop, nexthop, &nlen)) { - return false; - } - - /* Do not learn routes with link-local next hop. */ - return !in6_is_lla(nexthop); -} - -/* Return false if can't be added due to bad format. */ -static bool -add_to_routes_learned(struct hmap *routes_learned, - const struct nbrec_logical_router_static_route *nb_route, - const struct nbrec_logical_router *nb_lr) -{ - struct in6_addr prefix, nexthop; - unsigned int plen; - if (!parse_route(nb_route->ip_prefix, nb_route->nexthop, - &prefix, &plen, &nexthop)) { - return false; - } - const char *origin = smap_get_def(&nb_route->options, "origin", ""); - if (ic_route_find(routes_learned, &prefix, plen, &nexthop, origin, - nb_route->route_table, 0)) { - /* Route was added to learned on previous iteration. */ - return true; - } - - struct ic_route_info *ic_route = xzalloc(sizeof *ic_route); - ic_route->prefix = prefix; - ic_route->plen = plen; - ic_route->nexthop = nexthop; - ic_route->nb_route = nb_route; - ic_route->origin = origin; - ic_route->route_table = nb_route->route_table; - ic_route->nb_lr = nb_lr; - hmap_insert(routes_learned, &ic_route->node, - ic_route_hash(&prefix, plen, &nexthop, origin, - nb_route->route_table)); - return true; -} - -static bool -get_nexthop_from_lport_addresses(bool is_v4, - const struct lport_addresses *laddr, - struct in6_addr *nexthop) -{ - if (is_v4) { - if (!laddr->n_ipv4_addrs) { - return false; - } - in6_addr_set_mapped_ipv4(nexthop, laddr->ipv4_addrs[0].addr); - return true; - } - - /* ipv6 */ - if (laddr->n_ipv6_addrs) { - *nexthop = laddr->ipv6_addrs[0].addr; - return true; - } - - /* ipv6 link local */ - in6_generate_lla(laddr->ea, nexthop); - return true; -} - -static bool -prefix_is_filtered(struct in6_addr *prefix, - unsigned int plen, - const struct nbrec_logical_router *nb_lr, - const struct nbrec_logical_router_port *ts_lrp, - bool is_advertisement) -{ - struct ds filter_list = DS_EMPTY_INITIALIZER; - const char *filter_direction = is_advertisement ? "ic-route-filter-adv" : - "ic-route-filter-learn"; - if (ts_lrp) { - const char *lrp_route_filter = smap_get(&ts_lrp->options, - filter_direction); - if (lrp_route_filter) { - ds_put_format(&filter_list, "%s,", lrp_route_filter); - } - } - const char *lr_route_filter = smap_get(&nb_lr->options, - filter_direction); - if (lr_route_filter) { - ds_put_format(&filter_list, "%s,", lr_route_filter); - } - - struct sset prefix_set = SSET_INITIALIZER(&prefix_set); - sset_from_delimited_string(&prefix_set, ds_cstr(&filter_list), ","); - - bool matched = true; - if (!sset_is_empty(&prefix_set)) { - matched = find_prefix_in_set(prefix, plen, &prefix_set, - filter_direction); - } - - ds_destroy(&filter_list); - sset_destroy(&prefix_set); - return matched; -} - -static bool -prefix_is_deny_filtered(struct in6_addr *prefix, - unsigned int plen, - const struct smap *nb_options, - const struct nbrec_logical_router *nb_lr, - const struct nbrec_logical_router_port *ts_lrp, - bool is_advertisement) -{ - struct ds deny_list = DS_EMPTY_INITIALIZER; - const char *deny_key = is_advertisement ? "ic-route-deny-adv" : - "ic-route-deny-learn"; - - if (ts_lrp) { - const char *lrp_deny_filter = smap_get(&ts_lrp->options, deny_key); - if (lrp_deny_filter) { - ds_put_format(&deny_list, "%s,", lrp_deny_filter); - } - } - - if (nb_lr) { - const char *lr_deny_filter = smap_get(&nb_lr->options, deny_key); - if (lr_deny_filter) { - ds_put_format(&deny_list, "%s,", lr_deny_filter); - } - } - - if (nb_options) { - const char *global_deny = smap_get(nb_options, "ic-route-denylist"); - if (!global_deny || !global_deny[0]) { - global_deny = smap_get(nb_options, "ic-route-blacklist"); - } - if (global_deny && global_deny[0]) { - ds_put_format(&deny_list, "%s,", global_deny); - } - } - - struct sset prefix_set = SSET_INITIALIZER(&prefix_set); - sset_from_delimited_string(&prefix_set, ds_cstr(&deny_list), ","); - - bool denied = false; - if (!sset_is_empty(&prefix_set)) { - denied = find_prefix_in_set(prefix, plen, &prefix_set, deny_key); - } - - ds_destroy(&deny_list); - sset_destroy(&prefix_set); - return denied; -} - -static bool -route_need_advertise(const char *policy, - struct in6_addr *prefix, - unsigned int plen, - const struct smap *nb_options, - const struct nbrec_logical_router *nb_lr, - const struct nbrec_logical_router_port *ts_lrp) -{ - if (!smap_get_bool(nb_options, "ic-route-adv", false)) { - return false; - } - - if (plen == 0 && - !smap_get_bool(nb_options, "ic-route-adv-default", false)) { - return false; - } - - if (policy && !strcmp(policy, "src-ip")) { - return false; - } - - if (prefix_is_link_local(prefix, plen)) { - return false; - } - - if (prefix_is_deny_filtered(prefix, plen, nb_options, - nb_lr, ts_lrp, true)) { - return false; - } - - if (!prefix_is_filtered(prefix, plen, nb_lr, ts_lrp, true)) { - return false; - } - - return true; -} - -static void -add_to_routes_ad(struct hmap *routes_ad, const struct in6_addr prefix, - unsigned int plen, const struct in6_addr nexthop, - const char *origin, const char *route_table, - const struct nbrec_logical_router_port *nb_lrp, - const struct nbrec_logical_router_static_route *nb_route, - const struct nbrec_logical_router *nb_lr, - const struct nbrec_load_balancer *nb_lb, - const char *route_tag) -{ - ovs_assert(nb_route || nb_lrp || nb_lb); - - if (route_table == NULL) { - route_table = ""; - } - - uint hash = ic_route_hash(&prefix, plen, &nexthop, origin, route_table); - - if (!ic_route_find(routes_ad, &prefix, plen, &nexthop, origin, - route_table, hash)) { - struct ic_route_info *ic_route = xzalloc(sizeof *ic_route); - ic_route->prefix = prefix; - ic_route->plen = plen; - ic_route->nexthop = nexthop; - ic_route->nb_route = nb_route; - ic_route->origin = origin; - ic_route->route_table = route_table; - ic_route->nb_lrp = nb_lrp; - ic_route->nb_lr = nb_lr; - ic_route->nb_lb = nb_lb; - ic_route->route_tag = route_tag; - hmap_insert(routes_ad, &ic_route->node, hash); - } else { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - const char *msg_fmt = "Duplicate %s route advertisement was " - "suppressed! NB %s uuid: "UUID_FMT; - if (nb_route) { - VLOG_WARN_RL(&rl, msg_fmt, origin, "route", - UUID_ARGS(&nb_route->header_.uuid)); - } else if (nb_lb) { - VLOG_WARN_RL(&rl, msg_fmt, origin, "loadbalancer", - UUID_ARGS(&nb_lb->header_.uuid)); - } else { - VLOG_WARN_RL(&rl, msg_fmt, origin, "lrp", - UUID_ARGS(&nb_lrp->header_.uuid)); - } - } -} - -static void -add_static_to_routes_ad( - struct hmap *routes_ad, - const struct nbrec_logical_router_static_route *nb_route, - const struct nbrec_logical_router *nb_lr, - const struct lport_addresses *nexthop_addresses, - const struct smap *nb_options, - const char *route_tag, - const struct nbrec_logical_router_port *ts_lrp) -{ - struct in6_addr prefix, nexthop; - unsigned int plen; - if (!parse_route(nb_route->ip_prefix, nb_route->nexthop, - &prefix, &plen, &nexthop)) { - return; - } - - if (!route_need_advertise(nb_route->policy, &prefix, plen, nb_options, - nb_lr, ts_lrp)) { - return; - } - - if (!get_nexthop_from_lport_addresses(IN6_IS_ADDR_V4MAPPED(&prefix), - nexthop_addresses, - &nexthop)) { - return; - } - - if (VLOG_IS_DBG_ENABLED()) { - struct ds msg = DS_EMPTY_INITIALIZER; - - ds_put_format(&msg, "Advertising static route: %s -> %s, ic nexthop: ", - nb_route->ip_prefix, nb_route->nexthop); - - if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { - ds_put_format(&msg, IP_FMT, - IP_ARGS(in6_addr_get_mapped_ipv4(&nexthop))); - } else { - ipv6_format_addr(&nexthop, &msg); - } - - ds_put_format(&msg, ", route_table: %s", nb_route->route_table[0] - ? nb_route->route_table - : "
"); - - VLOG_DBG("%s", ds_cstr(&msg)); - ds_destroy(&msg); - } - - add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_STATIC, - nb_route->route_table, NULL, nb_route, nb_lr, - NULL, route_tag); -} - -static void -add_network_to_routes_ad(struct hmap *routes_ad, const char *network, - const struct nbrec_logical_router_port *nb_lrp, - const struct lport_addresses *nexthop_addresses, - const struct smap *nb_options, - const struct nbrec_logical_router *nb_lr, - const char *route_tag, - const struct nbrec_logical_router_port *ts_lrp) -{ - struct in6_addr prefix, nexthop; - unsigned int plen; - if (!ip46_parse_cidr(network, &prefix, &plen)) { - return; - } - - if (!route_need_advertise(NULL, &prefix, plen, nb_options, - nb_lr, ts_lrp)) { - VLOG_DBG("Route ad: skip network %s of lrp %s.", - network, nb_lrp->name); - return; - } - - if (!get_nexthop_from_lport_addresses(IN6_IS_ADDR_V4MAPPED(&prefix), - nexthop_addresses, - &nexthop)) { - return; - } - - if (VLOG_IS_DBG_ENABLED()) { - struct ds msg = DS_EMPTY_INITIALIZER; - - ds_put_format(&msg, "Adding direct network route to
routing " - "table: %s of lrp %s, nexthop ", network, nb_lrp->name); - - if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { - ds_put_format(&msg, IP_FMT, - IP_ARGS(in6_addr_get_mapped_ipv4(&nexthop))); - } else { - ipv6_format_addr(&nexthop, &msg); - } - - VLOG_DBG("%s", ds_cstr(&msg)); - ds_destroy(&msg); - } - - /* directly-connected routes go to
route table */ - add_to_routes_ad(routes_ad, prefix, plen, nexthop, ROUTE_ORIGIN_CONNECTED, - NULL, nb_lrp, NULL, nb_lr, NULL, route_tag); -} - -static void -add_lb_vip_to_routes_ad(struct hmap *routes_ad, const char *vip_key, - const struct nbrec_load_balancer *nb_lb, - const struct lport_addresses *nexthop_addresses, - const struct smap *nb_options, - const struct nbrec_logical_router *nb_lr, - const char *route_tag, - const struct nbrec_logical_router_port *ts_lrp) -{ - char *vip_str = NULL; - struct in6_addr vip_ip, nexthop; - uint16_t vip_port; - int addr_family; - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - - if (!ip_address_and_port_from_lb_key(vip_key, &vip_str, &vip_ip, - &vip_port, &addr_family)) { - VLOG_WARN_RL(&rl, "Route ad: Parsing failed for lb vip %s", vip_key); - return; - } - if (vip_str == NULL) { - return; - } - unsigned int plen = (addr_family == AF_INET) ? 32 : 128; - if (!route_need_advertise(NULL, &vip_ip, plen, nb_options, - nb_lr, ts_lrp)) { - VLOG_DBG("Route ad: skip lb vip %s.", vip_key); - goto out; - } - if (!get_nexthop_from_lport_addresses(IN6_IS_ADDR_V4MAPPED(&vip_ip), - nexthop_addresses, - &nexthop)) { - VLOG_WARN_RL(&rl, "Route ad: failed to get nexthop for lb vip"); - goto out; - } - - if (VLOG_IS_DBG_ENABLED()) { - struct ds msg = DS_EMPTY_INITIALIZER; - - ds_put_format(&msg, "Adding lb vip route to
routing " - "table: %s, nexthop ", vip_str); - - if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { - ds_put_format(&msg, IP_FMT, - IP_ARGS(in6_addr_get_mapped_ipv4(&nexthop))); - } else { - ipv6_format_addr(&nexthop, &msg); - } - - VLOG_DBG("%s", ds_cstr(&msg)); - ds_destroy(&msg); - } - - /* Lb vip routes go to
route table */ - add_to_routes_ad(routes_ad, vip_ip, plen, nexthop, ROUTE_ORIGIN_LB, - NULL, NULL, NULL, nb_lr, nb_lb, route_tag); -out: - free(vip_str); -} - -static bool -route_has_local_gw(const struct nbrec_logical_router *lr, - const char *route_table, const char *ip_prefix) { - - const struct nbrec_logical_router_static_route *route; - for (int i = 0; i < lr->n_static_routes; i++) { - route = lr->static_routes[i]; - if (!smap_get(&route->external_ids, "ic-learned-route") && - !strcmp(route->route_table, route_table) && - !strcmp(route->ip_prefix, ip_prefix)) { - return true; - } - } - return false; -} - -static bool -lrp_has_neighbor_in_ts(const struct nbrec_logical_router_port *lrp, - struct in6_addr *nexthop) -{ - if (!lrp || !nexthop) { - return false; - } - - struct lport_addresses lrp_networks; - if (!extract_lrp_networks(lrp, &lrp_networks)) { - destroy_lport_addresses(&lrp_networks); - return false; - } - - if (IN6_IS_ADDR_V4MAPPED(nexthop)) { - ovs_be32 neigh_prefix_v4 = in6_addr_get_mapped_ipv4(nexthop); - for (size_t i = 0; i < lrp_networks.n_ipv4_addrs; i++) { - struct ipv4_netaddr address = lrp_networks.ipv4_addrs[i]; - if (address.network == (neigh_prefix_v4 & address.mask)) { - destroy_lport_addresses(&lrp_networks); - return true; - } - } - } else { - for (size_t i = 0; i < lrp_networks.n_ipv6_addrs; i++) { - struct ipv6_netaddr address = lrp_networks.ipv6_addrs[i]; - struct in6_addr neigh_prefix = ipv6_addr_bitand(nexthop, - &address.mask); - if (ipv6_addr_equals(&address.network, &neigh_prefix)) { - destroy_lport_addresses(&lrp_networks); - return true; - } - } - } - - destroy_lport_addresses(&lrp_networks); - return false; -} - -static bool -route_matches_local_lb(const struct nbrec_load_balancer *nb_lb, - const char *ip_prefix) -{ - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - struct in6_addr prefix; - unsigned int plen; - - if (!ip46_parse_cidr(ip_prefix, &prefix, &plen)) { - return false; - } - - struct smap_node *node; - SMAP_FOR_EACH (node, &nb_lb->vips) { - char *vip_str = NULL; - struct in6_addr vip_ip; - uint16_t vip_port; - int addr_family; - if (ip_address_and_port_from_lb_key(node->key, &vip_str, - &vip_ip, &vip_port, - &addr_family)) { - if (IN6_IS_ADDR_V4MAPPED(&prefix) && addr_family == AF_INET) { - ovs_be32 vip = in6_addr_get_mapped_ipv4(&vip_ip); - ovs_be32 mask = be32_prefix_mask(plen); - - if ((vip & mask) == in6_addr_get_mapped_ipv4(&prefix)) { - free(vip_str); - return true; - } - } else if (!IN6_IS_ADDR_V4MAPPED(&prefix) - && addr_family == AF_INET6) { - struct in6_addr mask = ipv6_create_mask(plen); - struct in6_addr vip_prefix = ipv6_addr_bitand(&vip_ip, &mask); - if (ipv6_addr_equals(&prefix, &vip_prefix)) { - free(vip_str); - return true; - } - } - free(vip_str); - } else { - VLOG_WARN_RL(&rl, - "Route learn: Parsing failed for local lb vip %s", - node->key); - } - } - return false; -} - -static bool -route_need_learn(const struct nbrec_logical_router *lr, - const struct icsbrec_route *isb_route, - struct in6_addr *prefix, unsigned int plen, - const struct smap *nb_options, - const struct nbrec_logical_router_port *ts_lrp, - struct in6_addr *nexthop) -{ - if (!smap_get_bool(nb_options, "ic-route-learn", false)) { - return false; - } - - if (plen == 0 && - !smap_get_bool(nb_options, "ic-route-learn-default", false)) { - return false; - } - - if (!strcmp(isb_route->origin, ROUTE_ORIGIN_LB) && - !smap_get_bool(nb_options, "ic-route-learn-lb", false)) { - return false; - } - - if (!lrouter_is_enabled(lr)) { - return false; - } - - if (prefix_is_link_local(prefix, plen)) { - return false; - } - - if (prefix_is_deny_filtered(prefix, plen, nb_options, lr, ts_lrp, false)) { - return false; - } - - if (!prefix_is_filtered(prefix, plen, lr, ts_lrp, false)) { - return false; - } - - if (route_has_local_gw(lr, isb_route->route_table, isb_route->ip_prefix)) { - VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got one with " - "local GW", isb_route->ip_prefix, isb_route->route_table); - return false; - } - - if (!lrp_has_neighbor_in_ts(ts_lrp, nexthop)) { - return false; - } - - for (size_t i = 0; i < lr->n_load_balancer; i++) { - if (route_matches_local_lb(lr->load_balancer[i], - isb_route->ip_prefix)) { - VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got local" - " LB with matching VIP", isb_route->ip_prefix, - isb_route->route_table); - return false; - } - } - for (size_t i = 0; i < lr->n_load_balancer_group; i++) { - const struct nbrec_load_balancer_group *nb_lbg = - lr->load_balancer_group[i]; - for (size_t j = 0; j < nb_lbg->n_load_balancer; j++) { - if (route_matches_local_lb(nb_lbg->load_balancer[j], - isb_route->ip_prefix)) { - VLOG_DBG("Skip learning %s (rtb:%s) route, as we've got local" - " LB with matching VIP", isb_route->ip_prefix, - isb_route->route_table); - return false; - } - } - } - - return true; -} - -static const char * -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->nbrec_port_by_name, ts_port_name); - if (!nb_lsp) { - return NULL; - } - - return smap_get(&nb_lsp->options, "router-port"); -} - -static const struct nbrec_logical_router_port * -find_lrp_of_nexthop(struct ic_input *ic, - const struct icsbrec_route *isb_route) -{ - const struct nbrec_logical_router_port *lrp; - const struct nbrec_logical_switch *ls; - ls = find_ts_in_nb(ic->nbrec_ls_by_name, isb_route->transit_switch); - if (!ls) { - return NULL; - } - - struct in6_addr nexthop; - if (!ip46_parse(isb_route->nexthop, &nexthop)) { - return NULL; - } - - for (size_t i = 0; i < ls->n_ports; i++) { - char *lsp_name = ls->ports[i]->name; - const char *lrp_name = get_lrp_name_by_ts_port_name(ic, - lsp_name); - if (!lrp_name) { - continue; - } - - lrp = get_lrp_by_lrp_name(ic, lrp_name); - if (!lrp) { - continue; - } - - struct lport_addresses lrp_networks; - if (!extract_lrp_networks(lrp, &lrp_networks)) { - destroy_lport_addresses(&lrp_networks); - continue; - } - - if (IN6_IS_ADDR_V4MAPPED(&nexthop)) { - ovs_be32 nexthop_v4 = in6_addr_get_mapped_ipv4(&nexthop); - for (size_t i_v4 = 0; i_v4 < lrp_networks.n_ipv4_addrs; i_v4++) { - struct ipv4_netaddr address = lrp_networks.ipv4_addrs[i_v4]; - if (address.addr == nexthop_v4) { - destroy_lport_addresses(&lrp_networks); - return lrp; - } - } - } else { - for (size_t i_v6 = 0; i_v6 < lrp_networks.n_ipv6_addrs; i_v6++) { - struct ipv6_netaddr address = lrp_networks.ipv6_addrs[i_v6]; - struct in6_addr nexthop_v6 = ipv6_addr_bitand(&nexthop, - &address.mask); - if (ipv6_addr_equals(&address.network, &nexthop_v6)) { - destroy_lport_addresses(&lrp_networks); - return lrp; - } - } - } - destroy_lport_addresses(&lrp_networks); - } - - return NULL; -} - -static bool -lrp_is_ts_port(struct ic_input *ic, struct ic_router_info *ic_lr, - const char *lrp_name) -{ - const struct icsbrec_port_binding *isb_pb; - const char *ts_lrp_name; - VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { - ts_lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); - if (!strcmp(ts_lrp_name, lrp_name)) { - return true; - } - } - return false; -} - -static void -sync_learned_routes(struct engine_context *ctx, - struct ic_input *ic, - struct ic_router_info *ic_lr) -{ - ovs_assert(ctx->ovnnb_idl_txn); - const struct icsbrec_route *isb_route, *isb_route_key; - - const struct nbrec_nb_global *nb_global = - nbrec_nb_global_table_first(ic->nbrec_nb_global_table); - ovs_assert(nb_global); - - const char *lrp_name, *ts_route_table, *route_filter_tag; - const struct icsbrec_port_binding *isb_pb; - const struct nbrec_logical_router_port *lrp; - VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { - if (!strcmp(isb_pb->address, "")) { - continue; - } - lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); - lrp = get_lrp_by_lrp_name(ic, lrp_name); - if (lrp) { - ts_route_table = smap_get_def(&lrp->options, "route_table", ""); - route_filter_tag = smap_get_def(&lrp->options, - "ic-route-filter-tag", ""); - } else { - ts_route_table = ""; - route_filter_tag = ""; - } - - isb_route_key = icsbrec_route_index_init_row(ic->icsbrec_route_by_ts); - icsbrec_route_index_set_transit_switch(isb_route_key, - isb_pb->transit_switch); - - ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, - ic->icsbrec_route_by_ts) { - /* Filters ICSB routes, skipping those that either belong to - * current logical router or are legacy routes from the current - * availability zone (withoud lr-id). - */ - const char *lr_id = smap_get(&isb_route->external_ids, "lr-id"); - struct uuid lr_uuid; - if (lr_id) { - if (!uuid_from_string(&lr_uuid, lr_id) - || uuid_equals(&ic_lr->lr->header_.uuid, &lr_uuid)) { - continue; - } - } else if (isb_route->availability_zone == ic->runned_az) { - continue; - } - - const char *isb_route_tag = smap_get(&isb_route->external_ids, - "ic-route-tag"); - if (isb_route_tag && !strcmp(isb_route_tag, route_filter_tag)) { - VLOG_DBG("Skip learning route %s -> %s as its route tag " - "[%s] is filtered by the filter tag [%s] of TS LRP ", - isb_route->ip_prefix, isb_route->nexthop, - isb_route_tag, route_filter_tag); - continue; - } - - if (isb_route->route_table[0] && - strcmp(isb_route->route_table, ts_route_table)) { - if (VLOG_IS_DBG_ENABLED()) { - VLOG_DBG("Skip learning static route %s -> %s as either " - "its route table %s != %s of TS port or ", - isb_route->ip_prefix, isb_route->nexthop, - isb_route->route_table, ts_route_table); - } - continue; - } - - struct in6_addr prefix, nexthop; - unsigned int plen; - if (!parse_route(isb_route->ip_prefix, isb_route->nexthop, - &prefix, &plen, &nexthop)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Bad route format in IC-SB: %s -> %s. " - "Ignored.", isb_route->ip_prefix, - isb_route->nexthop); - continue; - } - if (!route_need_learn(ic_lr->lr, isb_route, &prefix, plen, - &nb_global->options, lrp, &nexthop)) { - continue; - } - - struct ic_route_info *route_learned - = ic_route_find(&ic_lr->routes_learned, &prefix, plen, - &nexthop, isb_route->origin, - isb_route->route_table, 0); - if (route_learned) { - /* Sync external-ids */ - struct uuid ext_id; - smap_get_uuid(&route_learned->nb_route->external_ids, - "ic-learned-route", &ext_id); - if (!uuid_equals(&ext_id, &isb_route->header_.uuid)) { - char *uuid_s = - xasprintf(UUID_FMT, - UUID_ARGS(&isb_route->header_.uuid)); - nbrec_logical_router_static_route_update_external_ids_setkey( - route_learned->nb_route, "ic-learned-route", uuid_s); - free(uuid_s); - } - hmap_remove(&ic_lr->routes_learned, &route_learned->node); - free(route_learned); - } else { - /* Create the missing route in NB. */ - const struct nbrec_logical_router_static_route *nb_route = - nbrec_logical_router_static_route_insert( - ctx->ovnnb_idl_txn); - nbrec_logical_router_static_route_set_ip_prefix(nb_route, - isb_route->ip_prefix); - nbrec_logical_router_static_route_set_nexthop(nb_route, - isb_route->nexthop); - char *uuid_s = xasprintf(UUID_FMT, - UUID_ARGS(&isb_route->header_.uuid)); - nbrec_logical_router_static_route_set_route_table(nb_route, - isb_route->route_table); - nbrec_logical_router_static_route_update_external_ids_setkey( - nb_route, "ic-learned-route", uuid_s); - nbrec_logical_router_static_route_update_options_setkey( - nb_route, "origin", isb_route->origin); - free(uuid_s); - nbrec_logical_router_update_static_routes_addvalue(ic_lr->lr, - nb_route); - } - } - icsbrec_route_index_destroy_row(isb_route_key); - } - - /* Delete extra learned routes. */ - struct ic_route_info *route_learned; - HMAP_FOR_EACH_SAFE (route_learned, node, &ic_lr->routes_learned) { - VLOG_DBG("Delete route %s -> %s that is not in IC-SB from NB.", - route_learned->nb_route->ip_prefix, - route_learned->nb_route->nexthop); - nbrec_logical_router_update_static_routes_delvalue( - ic_lr->lr, route_learned->nb_route); - hmap_remove(&ic_lr->routes_learned, &route_learned->node); - free(route_learned); - } -} - -static void -ad_route_sync_external_ids(const struct ic_route_info *route_adv, - const struct icsbrec_route *isb_route) -{ - struct uuid isb_ext_id, nb_id, isb_ext_lr_id, lr_id; - const char *route_tag; - smap_get_uuid(&isb_route->external_ids, "nb-id", &isb_ext_id); - smap_get_uuid(&isb_route->external_ids, "lr-id", &isb_ext_lr_id); - nb_id = route_adv->nb_lb ? route_adv->nb_lb->header_.uuid : - route_adv->nb_route ? route_adv->nb_route->header_.uuid : - route_adv->nb_lrp->header_.uuid; - - lr_id = route_adv->nb_lr->header_.uuid; - if (!uuid_equals(&isb_ext_id, &nb_id)) { - char *uuid_s = xasprintf(UUID_FMT, UUID_ARGS(&nb_id)); - icsbrec_route_update_external_ids_setkey(isb_route, "nb-id", - uuid_s); - free(uuid_s); - } - if (!uuid_equals(&isb_ext_lr_id, &lr_id)) { - char *uuid_s = xasprintf(UUID_FMT, UUID_ARGS(&lr_id)); - icsbrec_route_update_external_ids_setkey(isb_route, "lr-id", - uuid_s); - free(uuid_s); - } - if (strcmp(route_adv->route_tag, "")) { - icsbrec_route_update_external_ids_setkey(isb_route, "ic-route-tag", - route_adv->route_tag); - } else { - route_tag = smap_get(&isb_route->external_ids, "ic-route-tag"); - if (route_tag) { - icsbrec_route_update_external_ids_delkey(isb_route, - "ic-route-tag"); - } - } -} - -/* Sync routes from routes_ad to IC-SB. */ -static void -advertise_routes(struct engine_context *ctx, - struct ic_input *ic, - const struct icsbrec_availability_zone *az, - const char *ts_name, - struct hmap *routes_ad) -{ - ovs_assert(ctx->ovnisb_idl_txn); - const struct icsbrec_route *isb_route; - const struct icsbrec_route *isb_route_key = - icsbrec_route_index_init_row(ic->icsbrec_route_by_ts_az); - icsbrec_route_index_set_transit_switch(isb_route_key, ts_name); - icsbrec_route_index_set_availability_zone(isb_route_key, az); - - ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, - ic->icsbrec_route_by_ts_az) { - struct in6_addr prefix, nexthop; - unsigned int plen; - - if (!parse_route(isb_route->ip_prefix, isb_route->nexthop, - &prefix, &plen, &nexthop)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Bad route format in IC-SB: %s -> %s. " - "Delete it.", - isb_route->ip_prefix, isb_route->nexthop); - icsbrec_route_delete(isb_route); - continue; - } - struct ic_route_info *route_adv = - ic_route_find(routes_ad, &prefix, plen, &nexthop, - isb_route->origin, isb_route->route_table, 0); - if (!route_adv) { - /* Delete the extra route from IC-SB. */ - VLOG_DBG("Delete route %s -> %s from IC-SB, which is not found" - " in local routes to be advertised.", - isb_route->ip_prefix, isb_route->nexthop); - icsbrec_route_delete(isb_route); - } else { - ad_route_sync_external_ids(route_adv, isb_route); - - hmap_remove(routes_ad, &route_adv->node); - free(route_adv); - } - } - icsbrec_route_index_destroy_row(isb_route_key); - - /* Create the missing routes in IC-SB */ - struct ic_route_info *route_adv; - HMAP_FOR_EACH_SAFE (route_adv, node, routes_ad) { - isb_route = icsbrec_route_insert(ctx->ovnisb_idl_txn); - icsbrec_route_set_transit_switch(isb_route, ts_name); - icsbrec_route_set_availability_zone(isb_route, az); - - char *prefix_s, *nexthop_s; - if (IN6_IS_ADDR_V4MAPPED(&route_adv->prefix)) { - ovs_be32 ipv4 = in6_addr_get_mapped_ipv4(&route_adv->prefix); - ovs_be32 nh = in6_addr_get_mapped_ipv4(&route_adv->nexthop); - prefix_s = xasprintf(IP_FMT "/%d", IP_ARGS(ipv4), route_adv->plen); - nexthop_s = xasprintf(IP_FMT, IP_ARGS(nh)); - } else { - char network_s[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &route_adv->prefix, network_s, - INET6_ADDRSTRLEN); - prefix_s = xasprintf("%s/%d", network_s, route_adv->plen); - inet_ntop(AF_INET6, &route_adv->nexthop, network_s, - INET6_ADDRSTRLEN); - nexthop_s = xstrdup(network_s); - } - icsbrec_route_set_ip_prefix(isb_route, prefix_s); - icsbrec_route_set_nexthop(isb_route, nexthop_s); - icsbrec_route_set_origin(isb_route, route_adv->origin); - icsbrec_route_set_route_table(isb_route, route_adv->route_table - ? route_adv->route_table - : ""); - free(prefix_s); - free(nexthop_s); - - ad_route_sync_external_ids(route_adv, isb_route); - - hmap_remove(routes_ad, &route_adv->node); - free(route_adv); - } -} - -static void -build_ts_routes_to_adv(struct ic_input *ic, - struct ic_router_info *ic_lr, - struct hmap *routes_ad, - struct lport_addresses *ts_port_addrs, - const struct nbrec_nb_global *nb_global, - const char *ts_route_table, - const char *route_tag, - const struct nbrec_logical_router_port *ts_lrp) -{ - const struct nbrec_logical_router *lr = ic_lr->lr; - - /* Check static routes of the LR */ - for (int i = 0; i < lr->n_static_routes; i++) { - const struct nbrec_logical_router_static_route *nb_route - = lr->static_routes[i]; - struct uuid isb_uuid; - if (smap_get_uuid(&nb_route->external_ids, "ic-learned-route", - &isb_uuid)) { - /* It is a learned route */ - if (!add_to_routes_learned(&ic_lr->routes_learned, nb_route, lr)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Bad format of learned route in NB: " - "%s -> %s. Delete it.", nb_route->ip_prefix, - nb_route->nexthop); - nbrec_logical_router_update_static_routes_delvalue(lr, - nb_route); - } - } else if (!strcmp(ts_route_table, nb_route->route_table)) { - /* It may be a route to be advertised */ - add_static_to_routes_ad(routes_ad, nb_route, lr, ts_port_addrs, - &nb_global->options, route_tag, ts_lrp); - } - } - - /* Check directly-connected subnets of the LR */ - for (int i = 0; i < lr->n_ports; i++) { - const struct nbrec_logical_router_port *lrp = lr->ports[i]; - if (!lrp_is_ts_port(ic, ic_lr, lrp->name)) { - for (int j = 0; j < lrp->n_networks; j++) { - add_network_to_routes_ad(routes_ad, lrp->networks[j], lrp, - ts_port_addrs, - &nb_global->options, - lr, route_tag, ts_lrp); - } - } else { - /* The router port of the TS port is ignored. */ - VLOG_DBG("Skip advertising direct route of lrp %s (TS port)", - lrp->name); - } - } - - /* Check loadbalancers associated with the LR */ - if (smap_get_bool(&nb_global->options, "ic-route-adv-lb", false)) { - for (size_t i = 0; i < lr->n_load_balancer; i++) { - const struct nbrec_load_balancer *nb_lb = lr->load_balancer[i]; - struct smap_node *node; - SMAP_FOR_EACH (node, &nb_lb->vips) { - add_lb_vip_to_routes_ad(routes_ad, node->key, nb_lb, - ts_port_addrs, - &nb_global->options, - lr, route_tag, ts_lrp); - } - } - - for (size_t i = 0; i < lr->n_load_balancer_group; i++) { - const struct nbrec_load_balancer_group *nb_lbg = - lr->load_balancer_group[i]; - for (size_t j = 0; j < nb_lbg->n_load_balancer; j++) { - const struct nbrec_load_balancer *nb_lb = - nb_lbg->load_balancer[j]; - struct smap_node *node; - SMAP_FOR_EACH (node, &nb_lb->vips) { - add_lb_vip_to_routes_ad(routes_ad, node->key, nb_lb, - ts_port_addrs, - &nb_global->options, - lr, route_tag, ts_lrp); - } - } - } - } -} - -static void -collect_lr_routes(struct ic_input *ic, - struct ic_router_info *ic_lr, - struct shash *routes_ad_by_ts) -{ - const struct nbrec_nb_global *nb_global = - nbrec_nb_global_table_first(ic->nbrec_nb_global_table); - - ovs_assert(nb_global); - - const struct icsbrec_port_binding *isb_pb; - const char *lrp_name, *ts_name, *route_table, *route_tag; - struct lport_addresses ts_port_addrs; - const struct icnbrec_transit_switch *key; - const struct nbrec_logical_router_port *lrp; - - struct hmap *routes_ad; - const struct icnbrec_transit_switch *t_sw; - VECTOR_FOR_EACH (&ic_lr->isb_pbs, isb_pb) { - key = icnbrec_transit_switch_index_init_row( - ic->icnbrec_transit_switch_by_name); - icnbrec_transit_switch_index_set_name(key, isb_pb->transit_switch); - t_sw = icnbrec_transit_switch_index_find( - ic->icnbrec_transit_switch_by_name, key); - icnbrec_transit_switch_index_destroy_row(key); - if (!t_sw) { - continue; - } - ts_name = t_sw->name; - routes_ad = shash_find_data(routes_ad_by_ts, ts_name); - if (!routes_ad) { - routes_ad = xzalloc(sizeof *routes_ad); - hmap_init(routes_ad); - shash_add(routes_ad_by_ts, ts_name, routes_ad); - } - - if (!extract_lsp_addresses(isb_pb->address, &ts_port_addrs)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_INFO_RL(&rl, "Route sync ignores port %s on ts %s for router" - " %s because the addresses are invalid.", - isb_pb->logical_port, isb_pb->transit_switch, - ic_lr->lr->name); - continue; - } - lrp_name = get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); - lrp = get_lrp_by_lrp_name(ic, lrp_name); - if (lrp) { - route_table = smap_get_def(&lrp->options, "route_table", ""); - route_tag = smap_get_def(&lrp->options, "ic-route-tag", ""); - } else { - route_table = ""; - route_tag = ""; - } - build_ts_routes_to_adv(ic, ic_lr, routes_ad, &ts_port_addrs, - nb_global, route_table, route_tag, lrp); - destroy_lport_addresses(&ts_port_addrs); - } -} - -static void -delete_orphan_ic_routes(struct ic_input *ic, - const struct icsbrec_availability_zone *az) -{ - const struct icsbrec_route *isb_route, *isb_route_key = - icsbrec_route_index_init_row(ic->icsbrec_route_by_az); - icsbrec_route_index_set_availability_zone(isb_route_key, az); - - const struct icnbrec_transit_switch *t_sw, *t_sw_key; - - ICSBREC_ROUTE_FOR_EACH_EQUAL (isb_route, isb_route_key, - ic->icsbrec_route_by_az) - { - t_sw_key = icnbrec_transit_switch_index_init_row( - ic->icnbrec_transit_switch_by_name); - icnbrec_transit_switch_index_set_name(t_sw_key, - isb_route->transit_switch); - t_sw = icnbrec_transit_switch_index_find( - ic->icnbrec_transit_switch_by_name, t_sw_key); - icnbrec_transit_switch_index_destroy_row(t_sw_key); - - if (!t_sw || !find_lrp_of_nexthop(ic, isb_route)) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_INFO_RL(&rl, "Deleting orphan ICDB:Route: %s->%s (%s, rtb:%s," - " transit switch: %s)", isb_route->ip_prefix, - isb_route->nexthop, isb_route->origin, - isb_route->route_table, isb_route->transit_switch); - icsbrec_route_delete(isb_route); - } - } - icsbrec_route_index_destroy_row(isb_route_key); -} - -static void -route_run(struct engine_context *ctx, - struct ic_input *ic) -{ - if (!ctx->ovnisb_idl_txn || !ctx->ovnnb_idl_txn) { - return; - } - - delete_orphan_ic_routes(ic, ic->runned_az); - - struct hmap ic_lrs = HMAP_INITIALIZER(&ic_lrs); - 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); - - /* Each port on TS maps to a logical router, which is stored in the - * external_ids:router-id of the IC SB port_binding record. - * Here we build info for interconnected Logical Router: - * collect IC Port Binding to process routes sync later on. */ - ICSBREC_PORT_BINDING_FOR_EACH_EQUAL (isb_pb, isb_pb_key, - ic->icsbrec_port_binding_by_az) - { - if (ic_pb_get_type(isb_pb) == IC_ROUTER_PORT) { - continue; - } - const struct nbrec_logical_switch_port *nb_lsp; - - 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.", - isb_pb->logical_port, isb_pb->transit_switch); - continue; - } - - const char *ts_lrp_name = - get_lrp_name_by_ts_port_name(ic, isb_pb->logical_port); - if (!ts_lrp_name) { - static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); - VLOG_WARN_RL(&rl, "Route sync ignores port %s on ts %s because " - "logical router port is not found in NB. Deleting it", - isb_pb->logical_port, isb_pb->transit_switch); - icsbrec_port_binding_delete(isb_pb); - continue; - } - - struct uuid lr_uuid; - if (!smap_get_uuid(&isb_pb->external_ids, "router-id", &lr_uuid)) { - VLOG_DBG("IC-SB Port_Binding %s doesn't have " - "external_ids:router-id set.", isb_pb->logical_port); - continue; - } - - const struct nbrec_logical_router *lr - = nbrec_logical_router_table_get_for_uuid( - ic->nbrec_logical_router_table, &lr_uuid); - if (!lr) { - continue; - } - - struct ic_router_info *ic_lr = ic_router_find(&ic_lrs, lr); - if (!ic_lr) { - ic_lr = xzalloc(sizeof *ic_lr); - ic_lr->lr = lr; - ic_lr->isb_pbs = - VECTOR_EMPTY_INITIALIZER(const struct icsbrec_port_binding *); - hmap_init(&ic_lr->routes_learned); - hmap_insert(&ic_lrs, &ic_lr->node, uuid_hash(&lr->header_.uuid)); - } - vector_push(&ic_lr->isb_pbs, &isb_pb); - } - icsbrec_port_binding_index_destroy_row(isb_pb_key); - - struct ic_router_info *ic_lr; - struct shash routes_ad_by_ts = SHASH_INITIALIZER(&routes_ad_by_ts); - HMAP_FOR_EACH_SAFE (ic_lr, node, &ic_lrs) { - collect_lr_routes(ic, ic_lr, &routes_ad_by_ts); - sync_learned_routes(ctx, ic, ic_lr); - vector_destroy(&ic_lr->isb_pbs); - hmap_destroy(&ic_lr->routes_learned); - hmap_remove(&ic_lrs, &ic_lr->node); - free(ic_lr); - } - struct shash_node *node; - SHASH_FOR_EACH (node, &routes_ad_by_ts) { - advertise_routes(ctx, ic, ic->runned_az, node->name, node->data); - hmap_destroy(node->data); - } - shash_destroy_free_data(&routes_ad_by_ts); - hmap_destroy(&ic_lrs); -} - /* * Data structures and functions related to * synchronize health checks for load balancers @@ -2486,7 +1196,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); - route_run(eng_ctx, input_data); sync_service_monitor(eng_ctx, input_data); } @@ -2891,6 +1600,7 @@ main(int argc, char *argv[]) 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); + stopwatch_create(OVN_IC_ROUTE_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 ff6317786..bc4a1e6e0 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -22,7 +22,6 @@ struct ic_input { /* Northbound table references */ const struct nbrec_logical_switch_table *nbrec_logical_switch_table; const struct nbrec_logical_router_table *nbrec_logical_router_table; - const struct nbrec_nb_global_table *nbrec_nb_global_table; /* Southbound table references */ const struct sbrec_chassis_table *sbrec_chassis_table; @@ -54,10 +53,6 @@ struct ic_input { struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned; 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_route_by_az; - struct ovsdb_idl_index *icsbrec_route_by_ts; - struct ovsdb_idl_index *icsbrec_route_by_ts_az; struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az; struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az; struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port; @@ -80,7 +75,8 @@ 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); +get_lrp_by_lrp_name(struct ovsdb_idl_index *nbrec_lrp_by_name, + 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 * diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index 55945edf9..7f1a10690 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -43,5 +43,6 @@ #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" +#define OVN_IC_ROUTE_RUN_STOPWATCH_NAME "route_run" #endif From patchwork Mon Feb 9 18:28:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194715 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=lqI6pd2B; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tW53hbqz1xvc for ; Tue, 10 Feb 2026 05:28:49 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 1818F41C73; Mon, 9 Feb 2026 18:28:48 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id X-wac6N-DV1P; Mon, 9 Feb 2026 18:28:44 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 183A141C32 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=lqI6pd2B Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp4.osuosl.org (Postfix) with ESMTPS id 183A141C32; Mon, 9 Feb 2026 18:28:44 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BB13CC0784; Mon, 9 Feb 2026 18:28:43 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0E1C4C077F for ; Mon, 9 Feb 2026 18:28:43 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id EBBE040BB0 for ; Mon, 9 Feb 2026 18:28:40 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id HUYc_5x4jpuV for ; Mon, 9 Feb 2026 18:28:38 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::1136; helo=mail-yw1-x1136.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org D3F9440B84 Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org D3F9440B84 Authentication-Results: smtp2.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=lqI6pd2B Received: from mail-yw1-x1136.google.com (mail-yw1-x1136.google.com [IPv6:2607:f8b0:4864:20::1136]) by smtp2.osuosl.org (Postfix) with ESMTPS id D3F9440B84 for ; Mon, 9 Feb 2026 18:28:37 +0000 (UTC) Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-794f701a3e6so44439237b3.2 for ; Mon, 09 Feb 2026 10:28:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661716; x=1771266516; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=csOZMJTPDGMjxX+xTLr36/ZeFSz/JWfdTcEODqUwWvQ=; b=lqI6pd2BUqzvNryJqGiFTEOJT+uIowb5oOOY6J1TGGbDPcfqC89d4LT02qUKU2cStx 3UREXvywxyplUIE5/DXwiZgSkWRJlso4uO8HnvWiy6baWW0CL8+gezz5Sxzl36V9n6sV sQ+yR3M6RNteDFA7FG6X7VOQFw2bBAY/HHUd0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661716; x=1771266516; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=csOZMJTPDGMjxX+xTLr36/ZeFSz/JWfdTcEODqUwWvQ=; b=eQD1Xvbi0uxe8gW9pEO5rX0WEX5cWPQ6zoDI+70WzqewsLuNbsIoG0JjsAGuJvZbd0 5tyYu2ugtkwucvPziDcHkiwKABHfiutMK8LF7RkZfk8PjlC3z3qd4avZA1745/G4LsCx LGLJiXH2ieiQuMYUDZUvdjHMC5FpYWhsivY6yHl6BhfEh8ogBIMX96bHaGsinUTVSRoi 6fUcni9obZhBMhLHBJcYDavuOiWMhrJ7IdgwCPanv8F7kzq78rU08MLWuG4Ojz1KIpnH e5+zBJAvof8JvXbuRj3Cs6QU5LjfVVv2Pj/KsBhKQwFhGDxn+AdjUWSQXK2hx0QhBkSH rgFw== X-Gm-Message-State: AOJu0YzxIgpMQgdHJOieEykTsCJfVdua08Qr/xX+cOazq7b+JmZvyeia 3Jx0pzu97VzLrbEu+ercZ6fjgbFAyexcEjcmPv8fyHUOCq9yCIUlQaApvSvEYxLsvFT4E3keD0H 9XldUN/xcpogtZC4CEizozRa3ZHKH/7Etbuj2dA3Au9FVpHrbDNGgjwdXbtX9odg= X-Gm-Gg: AZuq6aJ1Pdt+W10Z0LSiZz5CH08PmyD6tOQLwYs83c53VbqJL8vRPInKbtIldtHalMx OQmlihj8WczU/llG5ACpD9ytn19Uo44sI8tWK3j7Ro4bQg0jFvJf1RiacQjyu50Q253TEDquwh6 Yr7/Hy39XSaBSDk0/Kl+QvGbFPi8vZWEhLfMwdLabP+MS7KrmuCwtbeILRsyevtUZkpqAStU7yg 9pRfLQbq+CjSeI+dCUvntGcTJmh1gEiBtf7+YASUXpONJbYd5CU3v15hrWSj5Y/DpTB0pA3xiTx 0WJVH5m+4mRuq93rQKEdz/7eUel6eBNZysPNAT99tox7WlreBN1AKgNzF49+YfSimOGwaTfoPfT B0cS9sNwdGdI+9Soe5vD+8+D5aVHwrbnagr+v/p9qg4tBcoOfTj6wy2/Xn7vIe6GHTskjnXiGN6 huG7m73sGA5Fb9iCRh4ifas3aVPwWF44PiXYj4jw== X-Received: by 2002:a05:690c:34c9:b0:796:2442:a3e8 with SMTP id 00721157ae682-7962442a5b7mr89213767b3.24.1770661716043; Mon, 09 Feb 2026 10:28:36 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:35 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:10 -0300 Message-Id: <20260209182814.842-6-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 5/9] ovn-ic: Add a new engine-node 'gateway'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" 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 --- 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 -- 2.34.1 diff --git a/ic/automake.mk b/ic/automake.mk index 24807a360..1fca1eb38 100644 --- a/ic/automake.mk +++ b/ic/automake.mk @@ -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 \ diff --git a/ic/en-gateway.c b/ic/en-gateway.c new file mode 100644 index 000000000..d0eb77564 --- /dev/null +++ b/ic/en-gateway.c @@ -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 + +#include +#include +#include + +/* 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); +} diff --git a/ic/en-gateway.h b/ic/en-gateway.h new file mode 100644 index 000000000..9010d27f4 --- /dev/null +++ b/ic/en-gateway.h @@ -0,0 +1,28 @@ +#ifndef EN_IC_GATEWAY_H +#define EN_IC_GATEWAY_H 1 + +#include + +#include +#include +#include +#include + +/* 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 diff --git a/ic/en-ic.c b/ic/en-ic.c index e0956bdee..af240c20a 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -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)); diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 177647119..6ee9a3fc7 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -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); @@ -173,6 +175,9 @@ 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); @@ -192,6 +197,7 @@ 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); @@ -220,7 +226,6 @@ 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 = { diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index b97ba5624..e5e3fd617 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -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) @@ -1193,7 +1046,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, diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h index bc4a1e6e0..e6918c8d2 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -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; diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index 7f1a10690..e62434aad 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -41,6 +41,7 @@ #define GROUP_ECMP_ROUTE_RUN_STOPWATCH_NAME "group_ecmp_route" #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" From patchwork Mon Feb 9 18:28:11 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194718 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=fW16n9EZ; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tWR4sMBz1xvc for ; Tue, 10 Feb 2026 05:29:07 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id DF57B41C6C; Mon, 9 Feb 2026 18:29:05 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 30_y_WClHy2n; Mon, 9 Feb 2026 18:29:03 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 9E15241C35 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=fW16n9EZ Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 9E15241C35; Mon, 9 Feb 2026 18:28:58 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 754DDC077F; Mon, 9 Feb 2026 18:28:58 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 079C6C077F for ; Mon, 9 Feb 2026 18:28:57 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id D70A761294 for ; Mon, 9 Feb 2026 18:28:42 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id mvqOuzJ1lAY4 for ; Mon, 9 Feb 2026 18:28:41 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::1133; helo=mail-yw1-x1133.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp3.osuosl.org 6CDF161275 Authentication-Results: smtp3.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 6CDF161275 Authentication-Results: smtp3.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=fW16n9EZ Received: from mail-yw1-x1133.google.com (mail-yw1-x1133.google.com [IPv6:2607:f8b0:4864:20::1133]) by smtp3.osuosl.org (Postfix) with ESMTPS id 6CDF161275 for ; Mon, 9 Feb 2026 18:28:40 +0000 (UTC) Received: by mail-yw1-x1133.google.com with SMTP id 00721157ae682-79274e0e56bso43837b3.0 for ; Mon, 09 Feb 2026 10:28:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661719; x=1771266519; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7VuuQlQPdY8azz48N32GVmMRiBLwBHXoEGq6aHV0jMQ=; b=fW16n9EZzflBRP4G2CroMaujPO2Rv9Y0d27uHFN6jps6vVpAcGu5WUpJLxzfFVKA1O D0q58T4hYabAA3OSQ7j9/TmhivIadxL+Ljaj4+VAxxy1ypuFaoW2vLRzJRBu+sV9dOql CorXGppK7wuiPa+6nJ7h2UZ9uSwdFmxFJxt1k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661719; x=1771266519; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=7VuuQlQPdY8azz48N32GVmMRiBLwBHXoEGq6aHV0jMQ=; b=TTTAiuxJ8huRm0mAaLJBAYVPiNp8TgJJX69NgZPciSar2SnHLwyYZmjcUEDKqE7426 /1hH0SRAiDc8baK+sZfm+Kw/U+BaHUP0ZKXASCdhLRjxrui/h4yabxlVQZcPkZIahbGN jsRLcMAUQsIlts6hLX/+HJQ97O/ANnDczLUs2At/qVqRNoeacR2WFzZc07pzVYVgvTEW q6eFdhgdf4tdG9gJMeZ0VngPa4ci81Qi8SwMlqqA2sS01lQGyy/xRKiLvt8gxv1X295A 7o510qvnQqLTyF22DzZ75m4qipexUe0a3ef6yTSEYjOCsXp7vwWp4UrQmrfc//e0/5G5 13vw== X-Gm-Message-State: AOJu0YzvMZeAX0uNKIM5hXtylvIzR1/7teTVe/YGaD/MxvhWdWp2fvau zz3i0e1ublK3/X/dl3XN0JMdIFIQB4iUgXszp+lHu654wFM45WX/t4YOsjh9zb6Pe+UnC+3qXqm 5RvmNc/fX5bfnX0D614GOjARlCLJqvOL2t8kNJmQcAKJ1nUrlnmQl4iyqrLc3eu4= X-Gm-Gg: AZuq6aJQ0HNqMuwaT0WBUYmwjA1MIS3Frm+g+DjtLlP7otFz5x7gP223bX1SSS9T3Dp gVku1bcBxXD+A5JbHue8z4zfRjhmsuVQ9Q+kIwj/vjcIfti3Ju70Cgarq5x40bqqIuq+vAUGSn8 E8FPkm4kWRMfkYCnKZ1OSyCj0OGLtyjdmz14IWySi7x8iK55RbtAYku5YYlJrtiEEVrXGTEQwDk CdDRi0ZMFSgX/ZD39DqTTauFpwVLpcyHGpgpnw087Fbe8vw9Z0TjN5pDAONBHc7YxxyrTKkTAo3 Sy8aLiZ8rTjw9BlKL8CGlzs4G+1tXawbwDpQ6JfwhOu6KYDpKr5+VsbIJ36h/I2vTXy4OWWFaYT dHCc8Yt6+la20QQpNP1/uNxuU0EGGtl8Jk1L+V977A06EkGl+9tpH/Syx7KnLnBxeja6u7in+1n 6bmRvtUuJKv5rfXKGSdD3qnA/NhQF5GeZOvqqrRg== X-Received: by 2002:a05:690c:28b:b0:794:f92a:103f with SMTP id 00721157ae682-7952aa70e98mr101107707b3.20.1770661718583; Mon, 09 Feb 2026 10:28:38 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:38 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:11 -0300 Message-Id: <20260209182814.842-7-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 6/9] ovn-ic: Add a new engine-node 'transit-router'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This new engine now maintains the transit-router related data for ovn-ic daemon which was earlier maintained by the ic engine node invoked the tr_run() function. The inputs to this engine node are: en_enum_datapaths; en_icsb_datapath_binding; en_nb_logical_router; en_icnb_transit_router; en_icnb_transit_router_port; In order to achieve this, we refactor in the following way: * Introduce tr_init() which initializes this data. * Introduce tr_destroy() which clears this data for a new iteration. * Introduce tr_run() which invokes the full recompute of the engine. This engine node becomes an input to 'ic' node. Signed-off-by: Paulo Guilherme Silva --- ic/automake.mk | 2 + ic/en-ic.c | 2 - ic/en-tr.c | 181 ++++++++++++++++++++++++++++++++++++++++++ ic/en-tr.h | 23 ++++++ ic/inc-proc-ic.c | 11 ++- ic/ovn-ic.c | 87 +------------------- ic/ovn-ic.h | 3 +- lib/stopwatch-names.h | 1 + 8 files changed, 220 insertions(+), 90 deletions(-) create mode 100644 ic/en-tr.c create mode 100644 ic/en-tr.h -- 2.34.1 diff --git a/ic/automake.mk b/ic/automake.mk index 1fca1eb38..180fcb252 100644 --- a/ic/automake.mk +++ b/ic/automake.mk @@ -8,6 +8,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \ ic/en-gateway.h \ ic/en-enum-datapaths.c \ ic/en-enum-datapaths.h \ + ic/en-tr.c \ + ic/en-tr.h \ ic/en-port-binding.c \ ic/en-port-binding.h \ ic/en-route.c \ diff --git a/ic/en-ic.c b/ic/en-ic.c index af240c20a..e9450a290 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -56,8 +56,6 @@ ic_get_input_data(struct engine_node *node, EN_OVSDB_GET(engine_get_input("ICNB_ic_nb_global", node)); input_data->icnbrec_transit_switch_table = EN_OVSDB_GET(engine_get_input("ICNB_transit_switch", node)); - input_data->icnbrec_transit_router_table = - EN_OVSDB_GET(engine_get_input("ICNB_transit_router", node)); input_data->icsbrec_ic_sb_global_table = EN_OVSDB_GET(engine_get_input("ICSB_ic_sb_global", node)); input_data->icsbrec_availability_zone_table = diff --git a/ic/en-tr.c b/ic/en-tr.c new file mode 100644 index 000000000..642d11b85 --- /dev/null +++ b/ic/en-tr.c @@ -0,0 +1,181 @@ +/* + * 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 + +#include +#include +#include + +/* OVS includes. */ +#include "openvswitch/vlog.h" + +/* OVN includes. */ +#include "ovn-ic.h" +#include "en-tr.h" +#include "en-enum-datapaths.h" +#include "inc-proc-ic.h" +#include "lib/inc-proc-eng.h" +#include "lib/ovn-nb-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_transit_router); +COVERAGE_DEFINE(tr_run); + +static void +tr_run(const struct engine_context *eng_ctx, + struct ed_type_transit_router *tr_data, + struct ed_type_enum_datapaths *dp_node_data, + const struct nbrec_logical_router_table *nbrec_lr_table, + const struct icnbrec_transit_router_table *icnbrec_tr_table); +static void tr_init(struct ed_type_transit_router *data); +static void tr_destroy(struct ed_type_transit_router *data); + +enum engine_node_state +en_tr_run(struct engine_node *node, void *data) +{ + const struct engine_context *eng_ctx = engine_get_context(); + struct ed_type_transit_router *tr_data = data; + + struct ed_type_enum_datapaths *dp_node_data = + engine_get_input_data("enum_datapaths", node); + + const struct nbrec_logical_router_table *nbrec_lr_table = + EN_OVSDB_GET(engine_get_input("NB_logical_router", node)); + const struct icnbrec_transit_router_table *icnbrec_tr_table = + EN_OVSDB_GET(engine_get_input("ICNB_transit_router", node)); + + COVERAGE_INC(tr_run); + stopwatch_start(OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME, time_usec()); + tr_run(eng_ctx, tr_data, dp_node_data, nbrec_lr_table, icnbrec_tr_table); + stopwatch_stop(OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME, time_usec()); + + return EN_UPDATED; +} + +void * +en_tr_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct ed_type_transit_router *data = xzalloc(sizeof *data); + tr_init(data); + return data; +} + +void +en_tr_cleanup(void *data) +{ + tr_destroy(data); +} + +static void +tr_init(struct ed_type_transit_router *data) +{ + shash_init(&data->isb_tr_dps); + hmap_init(&data->dp_tnlids); +} + +static void +tr_destroy(struct ed_type_transit_router *data) +{ + shash_destroy(&data->isb_tr_dps); + ovn_destroy_tnlids(&data->dp_tnlids); +} + +static void +tr_run(const struct engine_context *eng_ctx, + struct ed_type_transit_router *tr_data OVS_UNUSED, + struct ed_type_enum_datapaths *dp_node_data, + const struct nbrec_logical_router_table *nbrec_lr_table, + const struct icnbrec_transit_router_table *icnbrec_tr_table) +{ + const struct nbrec_logical_router *lr; + if (eng_ctx->ovnnb_idl_txn) { + struct shash nb_tres = SHASH_INITIALIZER(&nb_tres); + NBREC_LOGICAL_ROUTER_TABLE_FOR_EACH (lr, nbrec_lr_table) { + const char *tr_name = smap_get(&lr->options, "interconn-tr"); + if (tr_name) { + shash_add(&nb_tres, tr_name, lr); + } + } + + const struct icnbrec_transit_router *tr; + ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, icnbrec_tr_table) { + lr = shash_find_and_delete(&nb_tres, tr->name); + if (!lr) { + lr = nbrec_logical_router_insert(eng_ctx->ovnnb_idl_txn); + nbrec_logical_router_set_name(lr, tr->name); + nbrec_logical_router_update_options_setkey( + lr, "interconn-tr", tr->name); + } + char *uuid_str = uuid_to_string(&tr->header_.uuid); + struct icsbrec_datapath_binding *isb_dp = shash_find_data( + &dp_node_data->isb_tr_dps, uuid_str); + free(uuid_str); + + if (isb_dp) { + char *tnl_key_str = xasprintf("%"PRId64, isb_dp->tunnel_key); + nbrec_logical_router_update_options_setkey( + lr, "requested-tnl-key", tnl_key_str); + free(tnl_key_str); + } + } + + struct shash_node *node; + SHASH_FOR_EACH (node, &nb_tres) { + nbrec_logical_router_delete(node->data); + } + shash_destroy(&nb_tres); + } + + /* Sync TR between INB and ISB. This is performed after syncing with AZ + * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to + * AZ. */ + if (eng_ctx->ovnisb_idl_txn) { + /* Create ISB Datapath_Binding */ + const struct icnbrec_transit_router *tr; + ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, icnbrec_tr_table) { + char *uuid_str = uuid_to_string(&tr->header_.uuid); + struct icsbrec_datapath_binding *isb_dp = + shash_find_and_delete(&dp_node_data->isb_tr_dps, uuid_str); + free(uuid_str); + + if (!isb_dp) { + int dp_key = allocate_dp_key(&dp_node_data->dp_tnlids, false, + "transit router datapath"); + if (!dp_key) { + continue; + } + + isb_dp = icsbrec_datapath_binding_insert( + eng_ctx->ovnisb_idl_txn); + icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); + icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, + &tr->header_.uuid, 1); + icsbrec_datapath_binding_set_type(isb_dp, "transit-router"); + } + } + + struct shash_node *node; + SHASH_FOR_EACH (node, &dp_node_data->isb_tr_dps) { + icsbrec_datapath_binding_delete(node->data); + } + } +} diff --git a/ic/en-tr.h b/ic/en-tr.h new file mode 100644 index 000000000..674e1c07d --- /dev/null +++ b/ic/en-tr.h @@ -0,0 +1,23 @@ +#ifndef EN_IC_TR_RUN_H +#define EN_IC_TR_RUN_H 1 + +#include + +#include +#include +#include +#include + +/* OVN includes. */ +#include "lib/inc-proc-eng.h" + +struct ed_type_transit_router { + struct hmap dp_tnlids; + struct shash isb_tr_dps; +}; + +void *en_tr_init(struct engine_node *, struct engine_arg *); +enum engine_node_state en_tr_run(struct engine_node *, void *data); +void en_tr_cleanup(void *data); + +#endif diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 6ee9a3fc7..77bc1dd50 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -29,6 +29,7 @@ #include "en-ic.h" #include "en-gateway.h" #include "en-enum-datapaths.h" +#include "en-tr.h" #include "en-port-binding.h" #include "en-route.h" #include "unixctl.h" @@ -164,6 +165,7 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic); static ENGINE_NODE(ic, SB_WRITE); static ENGINE_NODE(gateway, SB_WRITE); static ENGINE_NODE(enum_datapaths); +static ENGINE_NODE(tr); static ENGINE_NODE(port_binding, SB_WRITE); static ENGINE_NODE(route); @@ -181,6 +183,12 @@ 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_tr, &en_enum_datapaths, NULL); + engine_add_input(&en_tr, &en_icsb_datapath_binding, NULL); + engine_add_input(&en_tr, &en_nb_logical_router, NULL); + engine_add_input(&en_tr, &en_icnb_transit_router, NULL); + engine_add_input(&en_tr, &en_icnb_transit_router_port, 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); @@ -199,6 +207,7 @@ inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_ic, &en_gateway, NULL); engine_add_input(&en_ic, &en_enum_datapaths, NULL); + engine_add_input(&en_ic, &en_tr, NULL); engine_add_input(&en_ic, &en_port_binding, NULL); engine_add_input(&en_ic, &en_route, NULL); @@ -218,8 +227,6 @@ inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_ic, &en_icnb_ic_nb_global, NULL); engine_add_input(&en_ic, &en_icnb_transit_switch, NULL); - 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); diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index e5e3fd617..7a0aa567d 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -159,7 +159,7 @@ az_run(struct ovsdb_idl *ovnnb_idl, return NULL; } -static uint32_t +uint32_t allocate_dp_key(struct hmap *dp_tnlids, bool vxlan_mode, const char *name) { uint32_t hint = vxlan_mode ? OVN_MIN_DP_VXLAN_KEY_GLOBAL @@ -346,89 +346,6 @@ ts_run(struct engine_context *ctx, } } -static void -tr_run(struct engine_context *ctx, - struct ic_input *ic, - struct hmap *dp_tnlids, - struct shash *isb_tr_dps) -{ - const struct nbrec_logical_router *lr; - - if (ctx->ovnnb_idl_txn) { - struct shash nb_tres = SHASH_INITIALIZER(&nb_tres); - NBREC_LOGICAL_ROUTER_TABLE_FOR_EACH (lr, - ic->nbrec_logical_router_table) { - const char *tr_name = smap_get(&lr->options, "interconn-tr"); - if (tr_name) { - shash_add(&nb_tres, tr_name, lr); - } - } - - const struct icnbrec_transit_router *tr; - ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, - ic->icnbrec_transit_router_table) { - lr = shash_find_and_delete(&nb_tres, tr->name); - if (!lr) { - lr = nbrec_logical_router_insert(ctx->ovnnb_idl_txn); - nbrec_logical_router_set_name(lr, tr->name); - nbrec_logical_router_update_options_setkey( - lr, "interconn-tr", tr->name); - } - char *uuid_str = uuid_to_string(&tr->header_.uuid); - struct icsbrec_datapath_binding *isb_dp = shash_find_data( - isb_tr_dps, uuid_str); - free(uuid_str); - - if (isb_dp) { - char *tnl_key_str = xasprintf("%"PRId64, isb_dp->tunnel_key); - nbrec_logical_router_update_options_setkey( - lr, "requested-tnl-key", tnl_key_str); - free(tnl_key_str); - } - } - - struct shash_node *node; - SHASH_FOR_EACH (node, &nb_tres) { - nbrec_logical_router_delete(node->data); - } - shash_destroy(&nb_tres); - } - - /* Sync TR between INB and ISB. This is performed after syncing with AZ - * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to - * AZ. */ - if (ctx->ovnisb_idl_txn) { - /* Create ISB Datapath_Binding */ - const struct icnbrec_transit_router *tr; - ICNBREC_TRANSIT_ROUTER_TABLE_FOR_EACH (tr, - ic->icnbrec_transit_router_table) { - char *uuid_str = uuid_to_string(&tr->header_.uuid); - struct icsbrec_datapath_binding *isb_dp = - shash_find_and_delete(isb_tr_dps, uuid_str); - free(uuid_str); - - if (!isb_dp) { - int dp_key = allocate_dp_key(dp_tnlids, false, - "transit router datapath"); - if (!dp_key) { - continue; - } - - isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn); - icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); - icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, - &tr->header_.uuid, 1); - icsbrec_datapath_binding_set_type(isb_dp, "transit-router"); - } - } - - struct shash_node *node; - SHASH_FOR_EACH (node, isb_tr_dps) { - icsbrec_datapath_binding_delete(node->data); - } - } -} - const struct nbrec_logical_router_port * get_lrp_by_lrp_name(struct ovsdb_idl_index *nbrec_lrp_by_name, const char *lrp_name) @@ -1047,7 +964,6 @@ ovn_db_run(struct ic_input *input_data, struct engine_context *eng_ctx) { 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); } @@ -1454,6 +1370,7 @@ main(int argc, char *argv[]) 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); + stopwatch_create(OVN_IC_TRANSIT_ROUTER_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 e6918c8d2..225dc73f5 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -30,7 +30,6 @@ struct ic_input { /* InterconnectNorthbound table references */ const struct icnbrec_transit_switch_table *icnbrec_transit_switch_table; const struct icnbrec_ic_nb_global_table *icnbrec_ic_nb_global_table; - const struct icnbrec_transit_router_table *icnbrec_transit_router_table; /* InterconnectSouthbound table references */ const struct icsbrec_encap_table *icsbrec_encap_table; @@ -73,6 +72,8 @@ 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 }; +uint32_t +allocate_dp_key(struct hmap *dp_tnlids, bool vxlan_mode, const char *name); const struct nbrec_logical_router_port * get_lrp_by_lrp_name(struct ovsdb_idl_index *nbrec_lrp_by_name, const char *lrp_name); diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index e62434aad..869384271 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -43,6 +43,7 @@ #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_TRANSIT_ROUTER_RUN_STOPWATCH_NAME "transit_router_run" #define OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME "port_binding_run" #define OVN_IC_ROUTE_RUN_STOPWATCH_NAME "route_run" From patchwork Mon Feb 9 18:28:12 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194719 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=g8kKLPdW; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tWW6Yfkz1xvc for ; Tue, 10 Feb 2026 05:29:11 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp4.osuosl.org (Postfix) with ESMTP id 7873041CF2; Mon, 9 Feb 2026 18:29:10 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp4.osuosl.org ([127.0.0.1]) by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id gCYmGgOMqm7V; Mon, 9 Feb 2026 18:29:06 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=140.211.9.56; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp4.osuosl.org 8C80741CF0 Authentication-Results: smtp4.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=g8kKLPdW Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by smtp4.osuosl.org (Postfix) with ESMTPS id 8C80741CF0; Mon, 9 Feb 2026 18:28:59 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 09736C0784; Mon, 9 Feb 2026 18:28:59 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1CD60C0780 for ; Mon, 9 Feb 2026 18:28:58 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 387A340AFC for ; Mon, 9 Feb 2026 18:28:46 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 0zyViW0UV8xf for ; Mon, 9 Feb 2026 18:28:43 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::1134; helo=mail-yw1-x1134.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org DF48A40BF4 Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org DF48A40BF4 Authentication-Results: smtp2.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=g8kKLPdW Received: from mail-yw1-x1134.google.com (mail-yw1-x1134.google.com [IPv6:2607:f8b0:4864:20::1134]) by smtp2.osuosl.org (Postfix) with ESMTPS id DF48A40BF4 for ; Mon, 9 Feb 2026 18:28:42 +0000 (UTC) Received: by mail-yw1-x1134.google.com with SMTP id 00721157ae682-794719afcd4so47905387b3.1 for ; Mon, 09 Feb 2026 10:28:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661721; x=1771266521; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2dnnOo0P2Vop3+6mpg9BPmjOZoYrd+ao/IS2RhsxpCc=; b=g8kKLPdWO5kTp8TZ6kT3maA1R8nPVWqSUk/o8o1IXB0s6iEQfoQh8qxcQFifOCbGet TSFBKL/I/vzjQAZUpTbOvW7OsHWnldg7Mfwrfv7/sG54Qvc209TfarBQmdIxToxWQ9Ta WxyVbCAiVbJZ/Co3wkQBRPbCNGNbajnldGer8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661721; x=1771266521; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=2dnnOo0P2Vop3+6mpg9BPmjOZoYrd+ao/IS2RhsxpCc=; b=V622C1WEr/3HdLZrhwLKx5s/kl4tkXiJn8e5JLD+uGxIbTnwap4fvjDHa0MnaOE6o7 1phNyH82b4jkRjIVMeNP4YsYrlfJ/5Y7cUXufp3B1YT1a4FwDICHCAzu7AOGMJeWKJBz 8Xucq0OeBs19ngUsHObVIb5i10ChG6oYo7rC0Lg4EnhWLafkNvlI0xneC4MzVcxP2hYH vZKihXGa7lBayxOZ28icGUZ8vFEqrFdLZQWa5Auvwhc28w6FWhjtGbIcqPdRrSxWC9rF aHa7kULmYoHEIl6sLTwWmNPzZEzSrVqsOLzpYC6udmjFx+WTf+iLBs0ZfWNpI4NenlVS KTrw== X-Gm-Message-State: AOJu0YwUEJ8LQ7O7IdLmvWnzZQlbhRvm7/jVX1vu0ZdSUaJTW+QDxqnG rRTTRvf6sNzY987uL2wZH8iadHZisl5ZkcfQj7kz2IR4m2yhVdra0UB/vG6XPo/i9apeeV+Uuje rBbJC3lPPDFgJ3eoEhGB+Ddk2HWwplobFrwSTPi0027b2WHWAq7PiSsNUmvIV5Bc= X-Gm-Gg: AZuq6aLbpQ4kaTS5l/4Bk6NBPYcI8Cl+cOm6Q6h1nb/TZhHIdYi1MwUlCIphKU+7xsC FahqN9AiFRxWtRGLYsnp0SX2wleAv/Q90X8zswU31D0ikbaFLb/KppuZpsVqzrr1LF+EW5RhQyr +qa7Jq5pl81hCwsaLGt2n1eIBnSqnpRm+AnyM7AcBrmFIqJ6VCJaCeIleZJclseg7V14JmMcMrb Y/7fZRxGL0T2rfJ8nEujQbHPOMpOjcJMEeQ57bmWld3XB9kBm2gL1CxrE62S0D8c8TVkZDq402n 2+qc9PAqM1RC91vuhbmfz+BLB7b0vEPS4enVbSgksLyJqh7L4zXyb+o9t4lnpQhOax/DH6f+AC0 F70aIUapwUDlyWQaR9FE6lGJRpphBbkTK95gOm0av0byc4d/sFyIWDbOYPe17jEVCwnH+OB9maA dilbZ+kHGHI6hvxsL4xDM709kd3+sOwrMZL4GRrw== X-Received: by 2002:a05:690c:4445:b0:796:2dfb:4af1 with SMTP id 00721157ae682-7962dfb5660mr77578127b3.9.1770661721142; Mon, 09 Feb 2026 10:28:41 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:40 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:12 -0300 Message-Id: <20260209182814.842-8-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 7/9] ovn-ic: Add a new engine-node 'transit-switch'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This new engine now maintains the transit-switch related data for ovn-ic daemon which was earlier maintained by the ic engine node invoked the ts_run() function. The inputs to this engine node are: en_enum_datapaths; en_icsb_datapath_binding; en_nb_logical_switch; en_icnb_ic_nb_global; en_icnb_transit_switch; en_icsb_encap; In order to achieve this, we refactor in the following way: * Introduce ts_init() which initializes this data. * Introduce ts_destroy() which clears this data for a new iteration. * Introduce ts_run() which invokes the full recompute of the engine. This engine node becomes an input to 'ic' node. Signed-off-by: Paulo Guilherme Silva --- ic/automake.mk | 2 + ic/en-ic.c | 16 +-- ic/en-ts.c | 282 ++++++++++++++++++++++++++++++++++++++++++ ic/en-ts.h | 23 ++++ ic/inc-proc-ic.c | 16 ++- ic/ovn-ic.c | 171 +------------------------ ic/ovn-ic.h | 1 - lib/stopwatch-names.h | 1 + 8 files changed, 322 insertions(+), 190 deletions(-) create mode 100644 ic/en-ts.c create mode 100644 ic/en-ts.h -- 2.34.1 diff --git a/ic/automake.mk b/ic/automake.mk index 180fcb252..84a487dc1 100644 --- a/ic/automake.mk +++ b/ic/automake.mk @@ -8,6 +8,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \ ic/en-gateway.h \ ic/en-enum-datapaths.c \ ic/en-enum-datapaths.h \ + ic/en-ts.c \ + ic/en-ts.h \ ic/en-tr.c \ ic/en-tr.h \ ic/en-port-binding.c \ diff --git a/ic/en-ic.c b/ic/en-ic.c index e9450a290..14c5c29cb 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -48,22 +48,14 @@ ic_get_input_data(struct engine_node *node, EN_OVSDB_GET(engine_get_input("NB_logical_switch", node)); input_data->nbrec_logical_router_table = EN_OVSDB_GET(engine_get_input("NB_logical_router", node)); - input_data->sbrec_sb_global_table = - EN_OVSDB_GET(engine_get_input("SB_sb_global", node)); input_data->sbrec_chassis_table = EN_OVSDB_GET(engine_get_input("SB_chassis", node)); - input_data->icnbrec_ic_nb_global_table = - EN_OVSDB_GET(engine_get_input("ICNB_ic_nb_global", node)); - input_data->icnbrec_transit_switch_table = - EN_OVSDB_GET(engine_get_input("ICNB_transit_switch", node)); + input_data->sbrec_sb_global_table = + EN_OVSDB_GET(engine_get_input("SB_sb_global", node)); input_data->icsbrec_ic_sb_global_table = EN_OVSDB_GET(engine_get_input("ICSB_ic_sb_global", node)); input_data->icsbrec_availability_zone_table = 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_datapath_binding_table = - EN_OVSDB_GET(engine_get_input("ICSB_datapath_binding", node)); /* Indexes */ input_data->nbrec_ls_by_name = @@ -102,10 +94,6 @@ ic_get_input_data(struct engine_node *node, engine_ovsdb_node_get_index( engine_get_input("SB_service_monitor", node), "sbrec_service_monitor_by_remote_type_logical_port"); - input_data->icnbrec_transit_switch_by_name = - engine_ovsdb_node_get_index( - engine_get_input("ICNB_transit_switch", node), - "icnbrec_transit_switch_by_name"); input_data->icsbrec_service_monitor_by_source_az = engine_ovsdb_node_get_index( engine_get_input("ICSB_service_monitor", node), diff --git a/ic/en-ts.c b/ic/en-ts.c new file mode 100644 index 000000000..4f9322326 --- /dev/null +++ b/ic/en-ts.c @@ -0,0 +1,282 @@ +/* + * 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 + +#include +#include +#include + +/* OVS includes. */ +#include "openvswitch/vlog.h" + +/* OVN includes. */ +#include "ovn-ic.h" +#include "en-ts.h" +#include "en-enum-datapaths.h" +#include "inc-proc-ic.h" +#include "lib/inc-proc-eng.h" +#include "lib/ovn-nb-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_transit_switch); +COVERAGE_DEFINE(ts_run); + +static void +ts_run(const struct engine_context *eng_ctx, + struct ed_type_transit_switch *ts_data, + struct ed_type_enum_datapaths *dp_node_data, + const struct nbrec_logical_switch_table *nbrec_ls_table, + const struct icnbrec_ic_nb_global_table *icnbrec_nb_global_table, + const struct icnbrec_transit_switch_table *icnbrec_ts_table, + const struct icsbrec_encap_table *icsbrec_encap_table, + const struct icsbrec_datapath_binding_table *icsbrec_dp_table); +static void ts_init(struct ed_type_transit_switch *data); +static void ts_destroy(struct ed_type_transit_switch *data); + +enum engine_node_state +en_ts_run(struct engine_node *node, void *data) +{ + const struct engine_context *eng_ctx = engine_get_context(); + struct ed_type_transit_switch *ts_data = data; + + struct ed_type_enum_datapaths *dp_node_data = + engine_get_input_data("enum_datapaths", node); + + const struct nbrec_logical_switch_table *nbrec_ls_table = + EN_OVSDB_GET(engine_get_input("NB_logical_switch", node)); + const struct icnbrec_ic_nb_global_table *icnbrec_nb_global_table = + EN_OVSDB_GET(engine_get_input("ICNB_ic_nb_global", node)); + const struct icnbrec_transit_switch_table *icnbrec_ts_table = + EN_OVSDB_GET(engine_get_input("ICNB_transit_switch", node)); + const struct icsbrec_encap_table *icsbrec_encap_table = + EN_OVSDB_GET(engine_get_input("ICSB_encap", node)); + const struct icsbrec_datapath_binding_table *icsbrec_dp_table = + EN_OVSDB_GET(engine_get_input("ICSB_datapath_binding", node)); + + COVERAGE_INC(ts_run); + stopwatch_start(OVN_IC_TRANSIT_SWITCH_RUN_STOPWATCH_NAME, time_usec()); + ts_run(eng_ctx, ts_data, dp_node_data, nbrec_ls_table, + icnbrec_nb_global_table, icnbrec_ts_table, icsbrec_encap_table, + icsbrec_dp_table); + stopwatch_stop(OVN_IC_TRANSIT_SWITCH_RUN_STOPWATCH_NAME, time_usec()); + + return EN_UPDATED; +} + +void * +en_ts_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct ed_type_transit_switch *data = xzalloc(sizeof *data); + ts_init(data); + return data; +} + +void +en_ts_cleanup(void *data) +{ + ts_destroy(data); +} + +static void +ts_init(struct ed_type_transit_switch *data) +{ + shash_init(&data->isb_ts_dps); + hmap_init(&data->dp_tnlids); +} + +static void +ts_destroy(struct ed_type_transit_switch *data) +{ + shash_destroy(&data->isb_ts_dps); + ovn_destroy_tnlids(&data->dp_tnlids); +} + +static void +ts_run(const struct engine_context *eng_ctx, + struct ed_type_transit_switch *ts_data OVS_UNUSED, + struct ed_type_enum_datapaths *dp_node_data, + const struct nbrec_logical_switch_table *nbrec_ls_table, + const struct icnbrec_ic_nb_global_table *icnbrec_nb_global_table, + const struct icnbrec_transit_switch_table *icnbrec_ts_table, + const struct icsbrec_encap_table *icsbrec_encap_table, + const struct icsbrec_datapath_binding_table *icsbrec_dp_table) +{ + const struct icnbrec_transit_switch *ts; + bool dp_key_refresh = false; + bool vxlan_mode = false; + const struct icnbrec_ic_nb_global *ic_nb = + icnbrec_ic_nb_global_table_first(icnbrec_nb_global_table); + + if (ic_nb && smap_get_bool(&ic_nb->options, "vxlan_mode", false)) { + const struct icsbrec_encap *encap; + ICSBREC_ENCAP_TABLE_FOR_EACH (encap, icsbrec_encap_table) { + if (!strcmp(encap->type, "vxlan")) { + vxlan_mode = true; + break; + } + } + } + + /* Sync INB TS to AZ NB */ + if (eng_ctx->ovnnb_idl_txn) { + struct shash nb_tses = SHASH_INITIALIZER(&nb_tses); + const struct nbrec_logical_switch *ls; + + /* Get current NB Logical_Switch with other_config:interconn-ts */ + NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH (ls, nbrec_ls_table) { + const char *ts_name = smap_get(&ls->other_config, "interconn-ts"); + if (ts_name) { + shash_add(&nb_tses, ts_name, ls); + } + } + + /* Create/update NB Logical_Switch for each TS */ + ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, icnbrec_ts_table) { + ls = shash_find_and_delete(&nb_tses, ts->name); + if (!ls) { + ls = nbrec_logical_switch_insert(eng_ctx->ovnnb_idl_txn); + nbrec_logical_switch_set_name(ls, ts->name); + nbrec_logical_switch_update_other_config_setkey(ls, + "interconn-ts", + ts->name); + nbrec_logical_switch_update_other_config_setkey( + ls, "ic-vxlan_mode", vxlan_mode ? "true" : "false"); + } else { + bool _vxlan_mode = smap_get_bool(&ls->other_config, + "ic-vxlan_mode", false); + if (_vxlan_mode != vxlan_mode) { + dp_key_refresh = true; + nbrec_logical_switch_update_other_config_setkey( + ls, "ic-vxlan_mode", + vxlan_mode ? "true" : "false"); + } + } + + const struct icsbrec_datapath_binding *isb_dp; + isb_dp = shash_find_data(&dp_node_data->isb_ts_dps, ts->name); + if (!isb_dp) { + const struct icsbrec_datapath_binding *raw; + ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw, + icsbrec_dp_table) { + if (raw->transit_switch && !strcmp(raw->transit_switch, + ts->name)) { + isb_dp = raw; + break; + } + } + } else { + int64_t nb_tnl_key = smap_get_int(&ls->other_config, + "requested-tnl-key", + 0); + if (nb_tnl_key != isb_dp->tunnel_key) { + VLOG_DBG("Set other_config:requested-tnl-key %"PRId64 + " for transit switch %s in NB.", + isb_dp->tunnel_key, ts->name); + char *tnl_key_str = xasprintf("%"PRId64, + isb_dp->tunnel_key); + nbrec_logical_switch_update_other_config_setkey( + ls, "requested-tnl-key", tnl_key_str); + free(tnl_key_str); + } + } + } + + /* Delete extra NB Logical_Switch with other_config:interconn-ts */ + struct shash_node *node; + SHASH_FOR_EACH (node, &nb_tses) { + nbrec_logical_switch_delete(node->data); + } + shash_destroy(&nb_tses); + } + + /* Sync TS between INB and ISB. This is performed after syncing with AZ + * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to + * AZ. */ + if (eng_ctx->ovnisb_idl_txn) { + /* Create ISB Datapath_Binding */ + ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, icnbrec_ts_table) { + const struct icsbrec_datapath_binding *isb_dp = + shash_find_and_delete(&dp_node_data->isb_ts_dps, ts->name); + + if (!isb_dp) { + const struct icsbrec_datapath_binding *raw_isb; + ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw_isb, + icsbrec_dp_table) { + if (raw_isb->n_nb_ic_uuid > 0 && + uuid_equals(&raw_isb->nb_ic_uuid[0], + &ts->header_.uuid)) { + isb_dp = raw_isb; + if (isb_dp->transit_switch) { + shash_find_and_delete(&dp_node_data->isb_ts_dps, + isb_dp->transit_switch); + } + break; + } + } + } + + if (!isb_dp) { + /* Allocate tunnel key */ + int64_t dp_key = allocate_dp_key(&dp_node_data->dp_tnlids, + vxlan_mode, + "transit switch datapath"); + if (!dp_key) { + continue; + } + + isb_dp = + icsbrec_datapath_binding_insert(eng_ctx->ovnisb_idl_txn); + icsbrec_datapath_binding_set_transit_switch(isb_dp, ts->name); + icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); + icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, + &ts->header_.uuid, 1); + icsbrec_datapath_binding_set_type(isb_dp, "transit-switch"); + } else if (dp_key_refresh) { + /* Refresh tunnel key since encap mode has changed. */ + int64_t dp_key = allocate_dp_key(&dp_node_data->dp_tnlids, + vxlan_mode, + "transit switch datapath"); + if (dp_key) { + icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); + } + } + + if (!isb_dp->type) { + icsbrec_datapath_binding_set_type(isb_dp, "transit-switch"); + } + + if (!isb_dp->nb_ic_uuid) { + icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, + &ts->header_.uuid, 1); + } + } + + struct shash_node *node, *next; + SHASH_FOR_EACH_SAFE (node, next, &dp_node_data->isb_ts_dps) { + struct icsbrec_datapath_binding *isb_dp_to_del = node->data; + if (isb_dp_to_del->n_nb_ic_uuid > 0) { + icsbrec_datapath_binding_delete(isb_dp_to_del); + } + shash_delete(&dp_node_data->isb_ts_dps, node); + } + } +} diff --git a/ic/en-ts.h b/ic/en-ts.h new file mode 100644 index 000000000..c63c1aef7 --- /dev/null +++ b/ic/en-ts.h @@ -0,0 +1,23 @@ +#ifndef EN_IC_TS_RUN_H +#define EN_IC_TS_RUN_H 1 + +#include + +#include +#include +#include +#include + +/* OVN includes. */ +#include "lib/inc-proc-eng.h" + +struct ed_type_transit_switch { + struct hmap dp_tnlids; + struct shash isb_ts_dps; +}; + +void *en_ts_init(struct engine_node *, struct engine_arg *); +enum engine_node_state en_ts_run(struct engine_node *, void *data); +void en_ts_cleanup(void *data); + +#endif diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 77bc1dd50..6b0723db6 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -29,6 +29,7 @@ #include "en-ic.h" #include "en-gateway.h" #include "en-enum-datapaths.h" +#include "en-ts.h" #include "en-tr.h" #include "en-port-binding.h" #include "en-route.h" @@ -166,6 +167,7 @@ static ENGINE_NODE(ic, SB_WRITE); static ENGINE_NODE(gateway, SB_WRITE); static ENGINE_NODE(enum_datapaths); static ENGINE_NODE(tr); +static ENGINE_NODE(ts, SB_WRITE); static ENGINE_NODE(port_binding, SB_WRITE); static ENGINE_NODE(route); @@ -183,6 +185,13 @@ 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_ts, &en_enum_datapaths, NULL); + engine_add_input(&en_ts, &en_icsb_datapath_binding, NULL); + engine_add_input(&en_ts, &en_nb_logical_switch, NULL); + engine_add_input(&en_ts, &en_icnb_ic_nb_global, NULL); + engine_add_input(&en_ts, &en_icnb_transit_switch, NULL); + engine_add_input(&en_ts, &en_icsb_encap, NULL); + engine_add_input(&en_tr, &en_enum_datapaths, NULL); engine_add_input(&en_tr, &en_icsb_datapath_binding, NULL); engine_add_input(&en_tr, &en_nb_logical_router, NULL); @@ -207,6 +216,7 @@ inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_ic, &en_gateway, NULL); engine_add_input(&en_ic, &en_enum_datapaths, NULL); + engine_add_input(&en_ic, &en_ts, NULL); engine_add_input(&en_ic, &en_tr, NULL); engine_add_input(&en_ic, &en_port_binding, NULL); engine_add_input(&en_ic, &en_route, NULL); @@ -225,15 +235,9 @@ inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_ic, &en_sb_port_binding, NULL); engine_add_input(&en_ic, &en_sb_service_monitor, NULL); - engine_add_input(&en_ic, &en_icnb_ic_nb_global, NULL); - engine_add_input(&en_ic, &en_icnb_transit_switch, 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_datapath_binding, NULL); struct engine_arg engine_arg = { .nb_idl = nb->idl, diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 7a0aa567d..7f43e6301 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -179,173 +179,6 @@ ic_pb_get_type(const struct icsbrec_port_binding *isb_pb) return IC_SWITCH_PORT; } -static void -ts_run(struct engine_context *ctx, - struct ic_input *ic, - struct hmap *dp_tnlids, - struct shash *isb_ts_dps) -{ - const struct icnbrec_transit_switch *ts; - bool dp_key_refresh = false; - bool vxlan_mode = false; - const struct icnbrec_ic_nb_global *ic_nb = - icnbrec_ic_nb_global_table_first(ic->icnbrec_ic_nb_global_table); - - if (ic_nb && smap_get_bool(&ic_nb->options, "vxlan_mode", false)) { - const struct icsbrec_encap *encap; - ICSBREC_ENCAP_TABLE_FOR_EACH (encap, ic->icsbrec_encap_table) { - if (!strcmp(encap->type, "vxlan")) { - vxlan_mode = true; - break; - } - } - } - - /* Sync INB TS to AZ NB */ - if (ctx->ovnnb_idl_txn) { - struct shash nb_tses = SHASH_INITIALIZER(&nb_tses); - const struct nbrec_logical_switch *ls; - - /* Get current NB Logical_Switch with other_config:interconn-ts */ - NBREC_LOGICAL_SWITCH_TABLE_FOR_EACH (ls, - ic->nbrec_logical_switch_table) { - const char *ts_name = smap_get(&ls->other_config, "interconn-ts"); - if (ts_name) { - shash_add(&nb_tses, ts_name, ls); - } - } - - /* Create/update NB Logical_Switch for each TS */ - ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, - ic->icnbrec_transit_switch_table) { - ls = shash_find_and_delete(&nb_tses, ts->name); - if (!ls) { - ls = nbrec_logical_switch_insert(ctx->ovnnb_idl_txn); - nbrec_logical_switch_set_name(ls, ts->name); - nbrec_logical_switch_update_other_config_setkey(ls, - "interconn-ts", - ts->name); - nbrec_logical_switch_update_other_config_setkey( - ls, "ic-vxlan_mode", vxlan_mode ? "true" : "false"); - } else { - bool _vxlan_mode = smap_get_bool(&ls->other_config, - "ic-vxlan_mode", false); - if (_vxlan_mode != vxlan_mode) { - dp_key_refresh = true; - nbrec_logical_switch_update_other_config_setkey( - ls, "ic-vxlan_mode", - vxlan_mode ? "true" : "false"); - } - } - - const struct icsbrec_datapath_binding *isb_dp; - isb_dp = shash_find_data(isb_ts_dps, ts->name); - if (!isb_dp) { - const struct icsbrec_datapath_binding *raw; - ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw, - ic->icsbrec_datapath_binding_table) { - if (raw->transit_switch && !strcmp(raw->transit_switch, - ts->name)) { - isb_dp = raw; - break; - } - } - } else { - int64_t nb_tnl_key = smap_get_int(&ls->other_config, - "requested-tnl-key", - 0); - if (nb_tnl_key != isb_dp->tunnel_key) { - VLOG_DBG("Set other_config:requested-tnl-key %"PRId64 - " for transit switch %s in NB.", - isb_dp->tunnel_key, ts->name); - char *tnl_key_str = xasprintf("%"PRId64, - isb_dp->tunnel_key); - nbrec_logical_switch_update_other_config_setkey( - ls, "requested-tnl-key", tnl_key_str); - free(tnl_key_str); - } - } - } - - /* Delete extra NB Logical_Switch with other_config:interconn-ts */ - struct shash_node *node; - SHASH_FOR_EACH (node, &nb_tses) { - nbrec_logical_switch_delete(node->data); - } - shash_destroy(&nb_tses); - } - - /* Sync TS between INB and ISB. This is performed after syncing with AZ - * SB, to avoid uncommitted ISB datapath tunnel key to be synced back to - * AZ. */ - if (ctx->ovnisb_idl_txn) { - /* Create ISB Datapath_Binding */ - ICNBREC_TRANSIT_SWITCH_TABLE_FOR_EACH (ts, - ic->icnbrec_transit_switch_table) { - const struct icsbrec_datapath_binding *isb_dp = - shash_find_and_delete(isb_ts_dps, ts->name); - - if (!isb_dp) { - const struct icsbrec_datapath_binding *raw_isb; - ICSBREC_DATAPATH_BINDING_TABLE_FOR_EACH (raw_isb, - ic->icsbrec_datapath_binding_table) { - if (raw_isb->n_nb_ic_uuid > 0 && - uuid_equals(&raw_isb->nb_ic_uuid[0], - &ts->header_.uuid)) { - isb_dp = raw_isb; - if (isb_dp->transit_switch) { - shash_find_and_delete(isb_ts_dps, - isb_dp->transit_switch); - } - break; - } - } - } - - if (!isb_dp) { - /* Allocate tunnel key */ - int64_t dp_key = allocate_dp_key(dp_tnlids, vxlan_mode, - "transit switch datapath"); - if (!dp_key) { - continue; - } - - isb_dp = icsbrec_datapath_binding_insert(ctx->ovnisb_idl_txn); - icsbrec_datapath_binding_set_transit_switch(isb_dp, ts->name); - icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); - icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, - &ts->header_.uuid, 1); - icsbrec_datapath_binding_set_type(isb_dp, "transit-switch"); - } else if (dp_key_refresh) { - /* Refresh tunnel key since encap mode has changed. */ - int64_t dp_key = allocate_dp_key(dp_tnlids, vxlan_mode, - "transit switch datapath"); - if (dp_key) { - icsbrec_datapath_binding_set_tunnel_key(isb_dp, dp_key); - } - } - - if (!isb_dp->type) { - icsbrec_datapath_binding_set_type(isb_dp, "transit-switch"); - } - - if (!isb_dp->nb_ic_uuid) { - icsbrec_datapath_binding_set_nb_ic_uuid(isb_dp, - &ts->header_.uuid, 1); - } - } - - struct shash_node *node, *next; - SHASH_FOR_EACH_SAFE (node, next, isb_ts_dps) { - struct icsbrec_datapath_binding *isb_dp_to_del = node->data; - if (isb_dp_to_del->n_nb_ic_uuid > 0) { - icsbrec_datapath_binding_delete(isb_dp_to_del); - } - shash_delete(isb_ts_dps, node); - } - } -} - const struct nbrec_logical_router_port * get_lrp_by_lrp_name(struct ovsdb_idl_index *nbrec_lrp_by_name, const char *lrp_name) @@ -960,10 +793,9 @@ inc_proc_graph_dump(const char *end_node) void ovn_db_run(struct ic_input *input_data, - struct ic_data *ic_data, + struct ic_data *ic_data OVS_UNUSED, struct engine_context *eng_ctx) { - ts_run(eng_ctx, input_data, ic_data->dp_tnlids, ic_data->isb_ts_dps); sync_service_monitor(eng_ctx, input_data); } @@ -1371,6 +1203,7 @@ main(int argc, char *argv[]) stopwatch_create(OVN_IC_ROUTE_RUN_STOPWATCH_NAME, SW_MS); stopwatch_create(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, SW_MS); stopwatch_create(OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME, SW_MS); + stopwatch_create(OVN_IC_TRANSIT_SWITCH_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 225dc73f5..7e057cc1b 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -29,7 +29,6 @@ struct ic_input { /* InterconnectNorthbound table references */ const struct icnbrec_transit_switch_table *icnbrec_transit_switch_table; - const struct icnbrec_ic_nb_global_table *icnbrec_ic_nb_global_table; /* InterconnectSouthbound table references */ const struct icsbrec_encap_table *icsbrec_encap_table; diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index 869384271..42f8dddc9 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -43,6 +43,7 @@ #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_TRANSIT_SWITCH_RUN_STOPWATCH_NAME "transit_switch_run" #define OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME "transit_router_run" #define OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME "port_binding_run" #define OVN_IC_ROUTE_RUN_STOPWATCH_NAME "route_run" From patchwork Mon Feb 9 18:28:13 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194720 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=NyvgAKVp; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=smtp3.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tWZ750xz1xvc for ; Tue, 10 Feb 2026 05:29:14 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id EE9966130C; Mon, 9 Feb 2026 18:29:12 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id N6oWS6150yIg; Mon, 9 Feb 2026 18:29:06 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 4FEE2612C1 Authentication-Results: smtp3.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=NyvgAKVp Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp3.osuosl.org (Postfix) with ESMTPS id 4FEE2612C1; Mon, 9 Feb 2026 18:29:01 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0AEE4C0780; Mon, 9 Feb 2026 18:29:01 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1932FC0783 for ; Mon, 9 Feb 2026 18:29:00 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 3010F83E55 for ; Mon, 9 Feb 2026 18:28:53 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id invnV-jBEM9v for ; Mon, 9 Feb 2026 18:28:48 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::112b; helo=mail-yw1-x112b.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp1.osuosl.org CE80883DE7 Authentication-Results: smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.osuosl.org CE80883DE7 Authentication-Results: smtp1.osuosl.org; dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=NyvgAKVp Received: from mail-yw1-x112b.google.com (mail-yw1-x112b.google.com [IPv6:2607:f8b0:4864:20::112b]) by smtp1.osuosl.org (Postfix) with ESMTPS id CE80883DE7 for ; Mon, 9 Feb 2026 18:28:45 +0000 (UTC) Received: by mail-yw1-x112b.google.com with SMTP id 00721157ae682-79427f739b0so49446407b3.3 for ; Mon, 09 Feb 2026 10:28:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661724; x=1771266524; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ymgykwykej8A1pVeFriL98FvojNFKzXlFZNlR5PNkDM=; b=NyvgAKVpFtZmmuoRPaR9bNNIvyKTuAdZvVk8UNuCPUirwnDpwuii88uTb5q9TrWXnK dC+n+jrtEY+C5Mcy8ZdlE8DsOy52LL0AXgn1G45k9gDrXVRrVGgLM0PGHIqScTbmYl7v nbmO1+7M/RXxpSb+M3Q/xx8yTnS98UXu+betI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661724; x=1771266524; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Ymgykwykej8A1pVeFriL98FvojNFKzXlFZNlR5PNkDM=; b=PtCi3Ae4nSLqIgcbxW+S3FH0go4QXB85x/WAw1kTIWyHD9DMSwmMhR3a2chCgcKpKP PE8n8HYXCZx25WXW0xANNOWAr5u1rVv5VdGiCdFLZlGqRc+WqX+JXr+um1VZycFAk2T7 BgP0mReiZ/xAdEheZF638kGreuZ6KayKetgGH3L9AsPwEXDfjd+41/31x8KXLRkQ+s/+ tDUm4YTf3dsjnKaWzePGAtcC+o1W2bXV30VDi5MY6SZcJ0ZvnrwCTNcqVBQkVEwDJ5aO JajSZBqwJ1kWRFdejrsVPAdy4ROq06daz1IfT3ha+d4FSF7EBgPuuds/DB1jrvR3Prfd mjZQ== X-Gm-Message-State: AOJu0YyoyVoRO5HXUTIOrbmh1w78t/qiHwNdskzODEPZ+TDmy0ePuO0y bVHatykfV5QWZSNLHwVsq9yAwJx5ajX5cmZUWAXAgaDlyUvfNC7CIFk70NnjrxPCqep0fL1EBlG s3hpnqp1Tag8eUW1KX9r7cbr8hRuwudhWXx5nUFGDCR+VWHeU5hZLgBjbXFAQ2oU= X-Gm-Gg: AZuq6aKsOvOJfx1V3pnHMtrlHrQkmsxrF+EaOSOjDs/CoHizGW2Poe4s97wm3RXzTHi Ug4nDoZhasKBnH0VfdmDk3qtDeiko6DK3cKQSC/aDtC9d0JaQA8z3hazhrmf0yFpeRs9WlptdLn ijaMlPvsvqeixf0XcMmNeFFpeWZZzLBipY3r4q+0F0aYKFASLQ3uc95GaPnLQhMw8rsqHYVI0di 13+jBoXjOdLMrDLmHnoWVNQJW3x+3KPcpwhYJ0SMMdsg4NcUsly8uwZTXs0o+w1kDZ2xx9Kroex LC89d2ZB1FLjv5qnFuTD1z03kAVMjtfiboz/7dLbH5sjWVwYpQRrelSREs9FiW2lFQ5KD/6S2F7 lQxUz8TNZJwGhY4/ofchBjiG/thMD8ZcXvK74b+jWhQLZGDXR1JqdaRsl3dknlgywXSSoWCJoKp h6vyk/2nX29oqbGWFpqwXgZni2B5L5y507oGnikQ== X-Received: by 2002:a05:690c:660e:b0:796:32e3:7d4e with SMTP id 00721157ae682-79632e3898fmr61866347b3.54.1770661723879; Mon, 09 Feb 2026 10:28:43 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:43 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:13 -0300 Message-Id: <20260209182814.842-9-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 8/9] ovn-ic: Add a new engine-node 'service-monitor'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" This new engine now maintains the service-monitor related data for ovn-ic daemon which was earlier maintained by the ic engine node invoked the sync_service_monitor() function. The inputs to this engine node are: en_icsb_service_monitor; en_sb_sb_global; en_sb_service_monitor; en_nb_load_balancer; en_nb_load_balancer_group; en_sb_port_binding; In order to achieve this, we refactor in the following way: * Introduce srv_mon_init() which initializes this data. * Introduce srv_mon_destroy() which clears this data for a new iteration. * Introduce srv_mon_run() which invokes the full recompute of the engine. This engine node becomes an input to 'ic' node. Signed-off-by: Paulo Guilherme Silva --- ic/automake.mk | 2 + ic/en-ic.c | 30 --- ic/en-srv-mon.c | 586 ++++++++++++++++++++++++++++++++++++++++++ ic/en-srv-mon.h | 67 +++++ ic/inc-proc-ic.c | 16 +- ic/ovn-ic.c | 439 +------------------------------ ic/ovn-ic.h | 7 - lib/stopwatch-names.h | 1 + 8 files changed, 670 insertions(+), 478 deletions(-) create mode 100644 ic/en-srv-mon.c create mode 100644 ic/en-srv-mon.h -- 2.34.1 diff --git a/ic/automake.mk b/ic/automake.mk index 84a487dc1..b84685f60 100644 --- a/ic/automake.mk +++ b/ic/automake.mk @@ -16,6 +16,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \ ic/en-port-binding.h \ ic/en-route.c \ ic/en-route.h \ + ic/en-srv-mon.c \ + ic/en-srv-mon.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 14c5c29cb..ecdc1ab5d 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -50,8 +50,6 @@ ic_get_input_data(struct engine_node *node, EN_OVSDB_GET(engine_get_input("NB_logical_router", node)); input_data->sbrec_chassis_table = EN_OVSDB_GET(engine_get_input("SB_chassis", node)); - input_data->sbrec_sb_global_table = - EN_OVSDB_GET(engine_get_input("SB_sb_global", node)); input_data->icsbrec_ic_sb_global_table = EN_OVSDB_GET(engine_get_input("ICSB_ic_sb_global", node)); input_data->icsbrec_availability_zone_table = @@ -78,34 +76,6 @@ ic_get_input_data(struct engine_node *node, engine_ovsdb_node_get_index( engine_get_input("SB_chassis", node), "sbrec_chassis_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->sbrec_service_monitor_by_remote_type = - engine_ovsdb_node_get_index( - engine_get_input("SB_service_monitor", node), - "sbrec_service_monitor_by_remote_type"); - input_data->sbrec_service_monitor_by_ic_learned = - engine_ovsdb_node_get_index( - engine_get_input("SB_service_monitor", node), - "sbrec_service_monitor_by_ic_learned"); - input_data->sbrec_service_monitor_by_remote_type_logical_port = - engine_ovsdb_node_get_index( - engine_get_input("SB_service_monitor", node), - "sbrec_service_monitor_by_remote_type_logical_port"); - input_data->icsbrec_service_monitor_by_source_az = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_service_monitor", node), - "icsbrec_service_monitor_by_source_az"); - input_data->icsbrec_service_monitor_by_target_az = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_service_monitor", node), - "icsbrec_service_monitor_by_target_az"); - input_data->icsbrec_service_monitor_by_target_az_logical_port = - engine_ovsdb_node_get_index( - engine_get_input("ICSB_service_monitor", node), - "icsbrec_service_monitor_by_target_az_logical_port"); } enum engine_node_state diff --git a/ic/en-srv-mon.c b/ic/en-srv-mon.c new file mode 100644 index 000000000..7b1c3b65e --- /dev/null +++ b/ic/en-srv-mon.c @@ -0,0 +1,586 @@ +/* + * 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 + +#include +#include +#include + +/* OVS includes. */ +#include "openvswitch/vlog.h" + +/* OVN includes. */ +#include "ovn-ic.h" +#include "en-srv-mon.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-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_srv_mon); +COVERAGE_DEFINE(srv_monitor_run); + +static void +srv_mon_run(const struct engine_context *eng_ctx, + struct ed_type_sync_service_monitor *srv_mon_data, + struct srv_mon_input *srv_mon_input, + const struct sbrec_sb_global_table *sbrec_sb_global_table); + +static void srv_mon_init(struct ed_type_sync_service_monitor *data); +static void srv_mon_destroy(struct ed_type_sync_service_monitor *data); +static void srv_mon_clear(struct ed_type_sync_service_monitor *data); + +static void +create_service_monitor_info(struct hmap *svc_map, + const void *db_rec, + const struct uuid *uuid, + const char *src_az_name, + const char *target_az_name, + const char *chassis_name, + bool ic_rec); +static void +destroy_service_monitor_info(struct service_monitor_info *svc_mon); +static void +refresh_sb_record_cache(struct hmap *svc_mon_map, + const struct sbrec_service_monitor *lookup_rec); +static void +refresh_ic_record_cache(struct hmap *svc_mon_map, + const struct icsbrec_service_monitor *lookup_rec); +static void +remove_unused_ic_records(struct hmap *local_ic_svcs_map); +static void +remove_unused_sb_records(struct hmap *local_sb_svcs_map); +static void +create_pushed_svcs_mon(struct srv_mon_input *srv_mon_input, + struct hmap *pushed_svcs_map); +static void +create_synced_svcs_mon(struct srv_mon_input *srv_mon_input, + struct hmap *synced_svcs_map); +static void +create_local_ic_svcs_map(struct srv_mon_input *srv_mon_input, + struct hmap *owned_svc_map); +static void +create_local_sb_svcs_map(struct srv_mon_input *srv_mon_input, + struct hmap *owned_svc_map); +static const struct sbrec_service_monitor * +lookup_sb_svc_rec(struct srv_mon_input *srv_mon_input, + const struct service_monitor_info *svc_mon); +static const struct icsbrec_service_monitor * +lookup_icsb_svc_rec(struct srv_mon_input *srv_mon_input, + const struct service_monitor_info *svc_mon); +static void +create_service_monitor_data(struct srv_mon_input *srv_mon_input, + const struct sbrec_sb_global_table *sbrec_sb_global_table, + struct ed_type_sync_service_monitor *sync_data); +static void +destroy_service_monitor_data(struct ed_type_sync_service_monitor *sync_data); + +static void +srv_mon_get_input_data(struct engine_node *node, + struct srv_mon_input *input_data) +{ + /* Indexes */ + 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->sbrec_service_monitor_by_remote_type = + engine_ovsdb_node_get_index( + engine_get_input("SB_service_monitor", node), + "sbrec_service_monitor_by_remote_type"); + input_data->sbrec_service_monitor_by_ic_learned = + engine_ovsdb_node_get_index( + engine_get_input("SB_service_monitor", node), + "sbrec_service_monitor_by_ic_learned"); + input_data->sbrec_service_monitor_by_remote_type_logical_port = + engine_ovsdb_node_get_index( + engine_get_input("SB_service_monitor", node), + "sbrec_service_monitor_by_remote_type_logical_port"); + input_data->icsbrec_service_monitor_by_source_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_service_monitor", node), + "icsbrec_service_monitor_by_source_az"); + input_data->icsbrec_service_monitor_by_target_az = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_service_monitor", node), + "icsbrec_service_monitor_by_target_az"); + input_data->icsbrec_service_monitor_by_target_az_logical_port = + engine_ovsdb_node_get_index( + engine_get_input("ICSB_service_monitor", node), + "icsbrec_service_monitor_by_target_az_logical_port"); +} + +enum engine_node_state +en_srv_mon_run(struct engine_node *node, void *data) +{ + const struct engine_context *eng_ctx = engine_get_context(); + struct ed_type_sync_service_monitor *srv_mon_data = data; + struct srv_mon_input srv_mon_input; + + srv_mon_clear(srv_mon_data); + + const struct sbrec_sb_global_table *sbrec_sb_global_table = + EN_OVSDB_GET(engine_get_input("SB_sb_global", node)); + + srv_mon_get_input_data(node, &srv_mon_input); + srv_mon_input.runned_az = eng_ctx->client_ctx; + + COVERAGE_INC(srv_monitor_run); + stopwatch_start(OVN_IC_SERVICE_MONITOR_RUN_STOPWATCH_NAME, time_usec()); + srv_mon_run(eng_ctx, srv_mon_data, &srv_mon_input, sbrec_sb_global_table); + stopwatch_stop(OVN_IC_SERVICE_MONITOR_RUN_STOPWATCH_NAME, time_usec()); + + return EN_UPDATED; +} + +void * +en_srv_mon_init(struct engine_node *node OVS_UNUSED, + struct engine_arg *arg OVS_UNUSED) +{ + struct ed_type_sync_service_monitor *data = xzalloc(sizeof *data); + srv_mon_init(data); + return data; +} + +void +en_srv_mon_cleanup(void *data) +{ + srv_mon_destroy(data); +} + +static void +srv_mon_init(struct ed_type_sync_service_monitor *data) +{ + hmap_init(&data->pushed_svcs_map); + hmap_init(&data->synced_svcs_map); + hmap_init(&data->local_ic_svcs_map); + hmap_init(&data->local_sb_svcs_map); + data->prpg_svc_monitor_mac = NULL; + data->tracked = false; +} + +static void +srv_mon_destroy(struct ed_type_sync_service_monitor *data) +{ + destroy_service_monitor_data(data); +} + +static void +srv_mon_clear(struct ed_type_sync_service_monitor *data) +{ + destroy_service_monitor_data(data); + srv_mon_init(data); +} + +static void +srv_mon_run(const struct engine_context *eng_ctx, + struct ed_type_sync_service_monitor *srv_mon_data, + struct srv_mon_input *srv_mon_input, + const struct sbrec_sb_global_table *sbrec_sb_global_table) +{ + if (!eng_ctx->ovnisb_idl_txn || !eng_ctx->ovnsb_idl_txn) { + return; + } + + create_service_monitor_data(srv_mon_input, sbrec_sb_global_table, + srv_mon_data); + + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &srv_mon_data->pushed_svcs_map) { + const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec; + const struct icsbrec_service_monitor *ic_rec = + lookup_icsb_svc_rec(srv_mon_input, svc_mon); + + if (ic_rec) { + sbrec_service_monitor_set_status(db_rec, ic_rec->status); + } else { + ic_rec = icsbrec_service_monitor_insert(eng_ctx->ovnisb_idl_txn); + icsbrec_service_monitor_set_type(ic_rec, db_rec->type); + icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip); + icsbrec_service_monitor_set_port(ic_rec, db_rec->port); + icsbrec_service_monitor_set_src_ip(ic_rec, db_rec->src_ip); + icsbrec_service_monitor_set_src_mac(ic_rec, + srv_mon_data->prpg_svc_monitor_mac); + icsbrec_service_monitor_set_protocol(ic_rec, db_rec->protocol); + icsbrec_service_monitor_set_logical_port(ic_rec, + db_rec->logical_port); + icsbrec_service_monitor_set_target_availability_zone(ic_rec, + svc_mon->dst_az_name); + icsbrec_service_monitor_set_source_availability_zone(ic_rec, + svc_mon->src_az_name); + } + + /* Always update options because they change from NB. */ + icsbrec_service_monitor_set_options(ic_rec, &db_rec->options); + refresh_ic_record_cache(&srv_mon_data->local_ic_svcs_map, ic_rec); + } + + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &srv_mon_data->synced_svcs_map) { + const struct icsbrec_service_monitor *db_rec = + svc_mon->db_rec.ic_rec; + const struct sbrec_service_monitor *sb_rec = + lookup_sb_svc_rec(srv_mon_input, svc_mon); + + if (sb_rec) { + icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec, + sb_rec->status); + } else { + sb_rec = sbrec_service_monitor_insert(eng_ctx->ovnsb_idl_txn); + sbrec_service_monitor_set_type(sb_rec, db_rec->type); + sbrec_service_monitor_set_ip(sb_rec, db_rec->ip); + sbrec_service_monitor_set_port(sb_rec, db_rec->port); + sbrec_service_monitor_set_src_ip(sb_rec, db_rec->src_ip); + /* Set svc_monitor_mac from local SBDB. */ + sbrec_service_monitor_set_src_mac(sb_rec, + srv_mon_data->prpg_svc_monitor_mac); + sbrec_service_monitor_set_protocol(sb_rec, + db_rec->protocol); + sbrec_service_monitor_set_logical_port(sb_rec, + db_rec->logical_port); + sbrec_service_monitor_set_remote(sb_rec, false); + sbrec_service_monitor_set_ic_learned(sb_rec, true); + } + + /* Always update options since they may change via + * NB configuration. Also update chassis_name if + * the port has been reassigned to a different chassis. + */ + if (svc_mon->chassis_name) { + sbrec_service_monitor_set_chassis_name(sb_rec, + svc_mon->chassis_name); + } + sbrec_service_monitor_set_options(sb_rec, &db_rec->options); + refresh_sb_record_cache(&srv_mon_data->local_sb_svcs_map, sb_rec); + } + + /* Delete local created records that are no longer used. */ + remove_unused_ic_records(&srv_mon_data->local_ic_svcs_map); + remove_unused_sb_records(&srv_mon_data->local_sb_svcs_map); +} + +static void +create_service_monitor_info(struct hmap *svc_map, + const void *db_rec, + const struct uuid *uuid, + const char *src_az_name, + const char *target_az_name, + const char *chassis_name, + bool ic_rec) +{ + struct service_monitor_info *svc_mon = xzalloc(sizeof(*svc_mon)); + size_t hash = uuid_hash(uuid); + + if (ic_rec) { + svc_mon->db_rec.ic_rec = + (const struct icsbrec_service_monitor *) db_rec; + } else { + svc_mon->db_rec.sb_rec = + (const struct sbrec_service_monitor *) db_rec; + } + + svc_mon->dst_az_name = target_az_name ? xstrdup(target_az_name) : NULL; + svc_mon->chassis_name = chassis_name ? xstrdup(chassis_name) : NULL; + svc_mon->src_az_name = xstrdup(src_az_name); + + hmap_insert(svc_map, &svc_mon->hmap_node, hash); +} + +static void +destroy_service_monitor_info(struct service_monitor_info *svc_mon) +{ + free(svc_mon->src_az_name); + free(svc_mon->dst_az_name); + free(svc_mon->chassis_name); + free(svc_mon); +} + +static void +refresh_sb_record_cache(struct hmap *svc_mon_map, + const struct sbrec_service_monitor *lookup_rec) +{ + size_t hash = uuid_hash(&lookup_rec->header_.uuid); + struct service_monitor_info *svc_mon; + + HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) { + ovs_assert(svc_mon->db_rec.sb_rec); + if (svc_mon->db_rec.sb_rec == lookup_rec) { + hmap_remove(svc_mon_map, &svc_mon->hmap_node); + destroy_service_monitor_info(svc_mon); + return; + } + } +} + +static void +refresh_ic_record_cache(struct hmap *svc_mon_map, + const struct icsbrec_service_monitor *lookup_rec) +{ + size_t hash = uuid_hash(&lookup_rec->header_.uuid); + struct service_monitor_info *svc_mon; + + HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) { + ovs_assert(svc_mon->db_rec.ic_rec); + if (svc_mon->db_rec.ic_rec == lookup_rec) { + hmap_remove(svc_mon_map, &svc_mon->hmap_node); + destroy_service_monitor_info(svc_mon); + return; + } + } +} + +static void +remove_unused_ic_records(struct hmap *local_ic_svcs_map) +{ + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_ic_svcs_map) { + icsbrec_service_monitor_delete(svc_mon->db_rec.ic_rec); + destroy_service_monitor_info(svc_mon); + } + + hmap_destroy(local_ic_svcs_map); +} + +static void +remove_unused_sb_records(struct hmap *local_sb_svcs_map) +{ + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_sb_svcs_map) { + sbrec_service_monitor_delete(svc_mon->db_rec.sb_rec); + destroy_service_monitor_info(svc_mon); + } + + hmap_destroy(local_sb_svcs_map); +} + +static void +create_pushed_svcs_mon(struct srv_mon_input *srv_mon_input, + struct hmap *pushed_svcs_map) +{ + struct sbrec_service_monitor *key = + sbrec_service_monitor_index_init_row( + srv_mon_input->sbrec_service_monitor_by_remote_type); + + sbrec_service_monitor_index_set_remote(key, true); + + const struct sbrec_service_monitor *sb_rec; + SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, + srv_mon_input->sbrec_service_monitor_by_remote_type) { + const char *target_az_name = smap_get(&sb_rec->options, + "az-name"); + if (!target_az_name) { + continue; + } + create_service_monitor_info(pushed_svcs_map, sb_rec, + &sb_rec->header_.uuid, + srv_mon_input->runned_az->name, + target_az_name, NULL, false); + } + + sbrec_service_monitor_index_destroy_row(key); +} + +static void +create_synced_svcs_mon(struct srv_mon_input *srv_mon_input, + struct hmap *synced_svcs_map) +{ + struct icsbrec_service_monitor *key = + icsbrec_service_monitor_index_init_row( + srv_mon_input->icsbrec_service_monitor_by_target_az); + + icsbrec_service_monitor_index_set_target_availability_zone( + key, srv_mon_input->runned_az->name); + + const struct icsbrec_service_monitor *ic_rec; + ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, + srv_mon_input->icsbrec_service_monitor_by_target_az) { + + const struct sbrec_port_binding *pb = + find_sb_pb_by_name(srv_mon_input->sbrec_port_binding_by_name, + ic_rec->logical_port); + + if (!pb || !pb->up) { + continue; + } + + const char *chassis_name = pb->chassis ? pb->chassis->name : NULL; + create_service_monitor_info(synced_svcs_map, ic_rec, + &ic_rec->header_.uuid, + srv_mon_input->runned_az->name, NULL, + chassis_name, true); + } + + icsbrec_service_monitor_index_destroy_row(key); +} + +static void +create_local_ic_svcs_map(struct srv_mon_input *srv_mon_input, + struct hmap *owned_svc_map) +{ + struct icsbrec_service_monitor *key = + icsbrec_service_monitor_index_init_row( + srv_mon_input->icsbrec_service_monitor_by_source_az); + + icsbrec_service_monitor_index_set_source_availability_zone( + key, srv_mon_input->runned_az->name); + + const struct icsbrec_service_monitor *ic_rec; + ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, + srv_mon_input->icsbrec_service_monitor_by_source_az) { + create_service_monitor_info(owned_svc_map, ic_rec, + &ic_rec->header_.uuid, + srv_mon_input->runned_az->name, NULL, + NULL, true); + } + + icsbrec_service_monitor_index_destroy_row(key); +} + +static void +create_local_sb_svcs_map(struct srv_mon_input *srv_mon_input, + struct hmap *owned_svc_map) +{ + struct sbrec_service_monitor *key = + sbrec_service_monitor_index_init_row( + srv_mon_input->sbrec_service_monitor_by_ic_learned); + + sbrec_service_monitor_index_set_ic_learned( + key, true); + + const struct sbrec_service_monitor *sb_rec; + SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, + srv_mon_input->sbrec_service_monitor_by_ic_learned) { + create_service_monitor_info(owned_svc_map, sb_rec, + &sb_rec->header_.uuid, + srv_mon_input->runned_az->name, NULL, + NULL, false); + } + + sbrec_service_monitor_index_destroy_row(key); +} + +static const struct sbrec_service_monitor * +lookup_sb_svc_rec(struct srv_mon_input *srv_mon_input, + const struct service_monitor_info *svc_mon) +{ + const struct icsbrec_service_monitor *db_rec = + svc_mon->db_rec.ic_rec; + struct sbrec_service_monitor *key = + sbrec_service_monitor_index_init_row( + srv_mon_input->sbrec_service_monitor_by_remote_type_logical_port); + + sbrec_service_monitor_index_set_remote(key, false); + sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port); + + const struct sbrec_service_monitor *sb_rec; + SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, + srv_mon_input->sbrec_service_monitor_by_remote_type_logical_port) { + if (db_rec->port == sb_rec->port && + ((db_rec->type && sb_rec->type && + !strcmp(db_rec->type, sb_rec->type)) || + (!db_rec->type && !sb_rec->type)) && + !strcmp(db_rec->ip, sb_rec->ip) && + !strcmp(db_rec->src_ip, sb_rec->src_ip) && + !strcmp(db_rec->protocol, sb_rec->protocol)) { + sbrec_service_monitor_index_destroy_row(key); + return sb_rec; + } + } + + sbrec_service_monitor_index_destroy_row(key); + + return NULL; +} + +static const struct icsbrec_service_monitor * +lookup_icsb_svc_rec(struct srv_mon_input *srv_mon_input, + const struct service_monitor_info *svc_mon) +{ + const struct sbrec_service_monitor *db_rec = + svc_mon->db_rec.sb_rec; + struct icsbrec_service_monitor *key = + icsbrec_service_monitor_index_init_row( + srv_mon_input->icsbrec_service_monitor_by_target_az_logical_port); + + ovs_assert(svc_mon->dst_az_name); + icsbrec_service_monitor_index_set_target_availability_zone( + key, svc_mon->dst_az_name); + + icsbrec_service_monitor_index_set_logical_port( + key, db_rec->logical_port); + + const struct icsbrec_service_monitor *ic_rec; + ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, + srv_mon_input->icsbrec_service_monitor_by_target_az_logical_port) { + if (db_rec->port == ic_rec->port && + ((db_rec->type && ic_rec->type && + !strcmp(db_rec->type, ic_rec->type)) || + (!db_rec->type && !ic_rec->type)) && + !strcmp(db_rec->ip, ic_rec->ip) && + !strcmp(db_rec->src_ip, ic_rec->src_ip) && + !strcmp(db_rec->protocol, ic_rec->protocol) && + !strcmp(db_rec->logical_port, ic_rec->logical_port)) { + icsbrec_service_monitor_index_destroy_row(key); + return ic_rec; + } + } + + icsbrec_service_monitor_index_destroy_row(key); + + return NULL; +} + +static void +create_service_monitor_data(struct srv_mon_input *srv_mon_input, + const struct sbrec_sb_global_table *sbrec_sb_global_table, + struct ed_type_sync_service_monitor *sync_data) +{ + const struct sbrec_sb_global *ic_sb = + sbrec_sb_global_table_first(sbrec_sb_global_table); + const char *svc_monitor_mac = smap_get(&ic_sb->options, + "svc_monitor_mac"); + + if (!svc_monitor_mac) { + return; + } + + sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac); + create_pushed_svcs_mon(srv_mon_input, &sync_data->pushed_svcs_map); + create_synced_svcs_mon(srv_mon_input, &sync_data->synced_svcs_map); + create_local_ic_svcs_map(srv_mon_input, &sync_data->local_ic_svcs_map); + create_local_sb_svcs_map(srv_mon_input, &sync_data->local_sb_svcs_map); +} + +static void +destroy_service_monitor_data(struct ed_type_sync_service_monitor *sync_data) +{ + struct service_monitor_info *svc_mon; + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->pushed_svcs_map) { + destroy_service_monitor_info(svc_mon); + } + + HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->synced_svcs_map) { + destroy_service_monitor_info(svc_mon); + } + + hmap_destroy(&sync_data->pushed_svcs_map); + hmap_destroy(&sync_data->synced_svcs_map); + free(sync_data->prpg_svc_monitor_mac); +} diff --git a/ic/en-srv-mon.h b/ic/en-srv-mon.h new file mode 100644 index 000000000..1b160dd4d --- /dev/null +++ b/ic/en-srv-mon.h @@ -0,0 +1,67 @@ +#ifndef EN_IC_SRV_MONITOR_RUN_H +#define EN_IC_SRV_MONITOR_RUN_H 1 + +#include + +#include +#include +#include +#include + +/* OVS includes. */ +#include "openvswitch/hmap.h" + +/* OVN includes. */ +#include "lib/inc-proc-eng.h" + +/* + * Data structures and functions related to + * synchronize health checks for load balancers + * between availability zones. + */ +struct ed_type_sync_service_monitor { + /* Map of service monitors to be pushed to other AZs. */ + struct hmap pushed_svcs_map; + /* Map of service monitors synced from other AZs to our. */ + struct hmap synced_svcs_map; + /* Map of local service monitors in the ICSBDB. */ + struct hmap local_ic_svcs_map; + /* Map of local service monitors in SBDB. */ + struct hmap local_sb_svcs_map; + /* MAC address used for service monitor. */ + char *prpg_svc_monitor_mac; + + bool tracked; +}; + +struct service_monitor_info { + struct hmap_node hmap_node; + union { + const struct sbrec_service_monitor *sb_rec; + const struct icsbrec_service_monitor *ic_rec; + } db_rec; + /* Destination availability zone name. */ + char *dst_az_name; + /* Source availability zone name. */ + char *src_az_name; + /* Chassis name associated with monitor logical port. */ + char *chassis_name; +}; + +struct srv_mon_input { + /* Indexes */ + const struct icsbrec_availability_zone *runned_az; + struct ovsdb_idl_index *sbrec_port_binding_by_name; + struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type; + struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned; + struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port; + struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az; + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az; + struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port; +}; + +void *en_srv_mon_init(struct engine_node *, struct engine_arg *); +enum engine_node_state en_srv_mon_run(struct engine_node *, void *data); +void en_srv_mon_cleanup(void *data); + +#endif diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 6b0723db6..75479b55a 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -33,6 +33,7 @@ #include "en-tr.h" #include "en-port-binding.h" #include "en-route.h" +#include "en-srv-mon.h" #include "unixctl.h" #include "util.h" @@ -170,6 +171,7 @@ static ENGINE_NODE(tr); static ENGINE_NODE(ts, SB_WRITE); static ENGINE_NODE(port_binding, SB_WRITE); static ENGINE_NODE(route); +static ENGINE_NODE(srv_mon, SB_WRITE); void inc_proc_ic_init(struct ovsdb_idl_loop *nb, @@ -214,30 +216,32 @@ 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_srv_mon, &en_icsb_service_monitor, NULL); + engine_add_input(&en_srv_mon, &en_sb_sb_global, NULL); + engine_add_input(&en_srv_mon, &en_sb_service_monitor, NULL); + engine_add_input(&en_srv_mon, &en_nb_load_balancer, NULL); + engine_add_input(&en_srv_mon, &en_nb_load_balancer_group, NULL); + engine_add_input(&en_srv_mon, &en_sb_port_binding, NULL); + engine_add_input(&en_ic, &en_gateway, NULL); engine_add_input(&en_ic, &en_enum_datapaths, NULL); engine_add_input(&en_ic, &en_ts, NULL); engine_add_input(&en_ic, &en_tr, NULL); engine_add_input(&en_ic, &en_port_binding, NULL); engine_add_input(&en_ic, &en_route, NULL); + engine_add_input(&en_ic, &en_srv_mon, NULL); engine_add_input(&en_ic, &en_nb_logical_router, NULL); engine_add_input(&en_ic, &en_nb_logical_router_port, NULL); engine_add_input(&en_ic, &en_nb_logical_switch, NULL); engine_add_input(&en_ic, &en_nb_logical_switch_port, NULL); - engine_add_input(&en_ic, &en_nb_load_balancer, NULL); - engine_add_input(&en_ic, &en_nb_load_balancer_group, NULL); - engine_add_input(&en_ic, &en_sb_sb_global, NULL); engine_add_input(&en_ic, &en_sb_chassis, NULL); engine_add_input(&en_ic, &en_sb_encap, NULL); engine_add_input(&en_ic, &en_sb_datapath_binding, NULL); - engine_add_input(&en_ic, &en_sb_port_binding, NULL); - engine_add_input(&en_ic, &en_sb_service_monitor, 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_service_monitor, NULL); struct engine_arg engine_arg = { .nb_idl = nb->idl, diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 7f43e6301..94e4310ba 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -247,438 +247,6 @@ find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name, return pb; } -/* - * Data structures and functions related to - * synchronize health checks for load balancers - * between availability zones. - */ -struct sync_service_monitor_data { - /* Map of service monitors to be pushed to other AZs. */ - struct hmap pushed_svcs_map; - /* Map of service monitors synced from other AZs to our. */ - struct hmap synced_svcs_map; - /* Map of local service monitors in the ICSBDB. */ - struct hmap local_ic_svcs_map; - /* Map of local service monitors in SBDB. */ - struct hmap local_sb_svcs_map; - /* MAC address used for service monitor. */ - char *prpg_svc_monitor_mac; -}; - -struct service_monitor_info { - struct hmap_node hmap_node; - union { - const struct sbrec_service_monitor *sb_rec; - const struct icsbrec_service_monitor *ic_rec; - } db_rec; - /* Destination availability zone name. */ - char *dst_az_name; - /* Source availability zone name. */ - char *src_az_name; - /* Chassis name associated with monitor logical port. */ - char *chassis_name; -}; - -static void -create_service_monitor_info(struct hmap *svc_map, - const void *db_rec, - const struct uuid *uuid, - const char *src_az_name, - const char *target_az_name, - const char *chassis_name, - bool ic_rec) -{ - struct service_monitor_info *svc_mon = xzalloc(sizeof(*svc_mon)); - size_t hash = uuid_hash(uuid); - - if (ic_rec) { - svc_mon->db_rec.ic_rec = - (const struct icsbrec_service_monitor *) db_rec; - } else { - svc_mon->db_rec.sb_rec = - (const struct sbrec_service_monitor *) db_rec; - } - - svc_mon->dst_az_name = target_az_name ? xstrdup(target_az_name) : NULL; - svc_mon->chassis_name = chassis_name ? xstrdup(chassis_name) : NULL; - svc_mon->src_az_name = xstrdup(src_az_name); - - hmap_insert(svc_map, &svc_mon->hmap_node, hash); -} - -static void -destroy_service_monitor_info(struct service_monitor_info *svc_mon) -{ - free(svc_mon->src_az_name); - free(svc_mon->dst_az_name); - free(svc_mon->chassis_name); - free(svc_mon); -} - -static void -refresh_sb_record_cache(struct hmap *svc_mon_map, - const struct sbrec_service_monitor *lookup_rec) -{ - size_t hash = uuid_hash(&lookup_rec->header_.uuid); - struct service_monitor_info *svc_mon; - - HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) { - ovs_assert(svc_mon->db_rec.sb_rec); - if (svc_mon->db_rec.sb_rec == lookup_rec) { - hmap_remove(svc_mon_map, &svc_mon->hmap_node); - destroy_service_monitor_info(svc_mon); - return; - } - } -} - -static void -refresh_ic_record_cache(struct hmap *svc_mon_map, - const struct icsbrec_service_monitor *lookup_rec) -{ - size_t hash = uuid_hash(&lookup_rec->header_.uuid); - struct service_monitor_info *svc_mon; - - HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) { - ovs_assert(svc_mon->db_rec.ic_rec); - if (svc_mon->db_rec.ic_rec == lookup_rec) { - hmap_remove(svc_mon_map, &svc_mon->hmap_node); - destroy_service_monitor_info(svc_mon); - return; - } - } -} - -static void -remove_unused_ic_records(struct hmap *local_ic_svcs_map) -{ - struct service_monitor_info *svc_mon; - HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_ic_svcs_map) { - icsbrec_service_monitor_delete(svc_mon->db_rec.ic_rec); - destroy_service_monitor_info(svc_mon); - } - - hmap_destroy(local_ic_svcs_map); -} - -static void -remove_unused_sb_records(struct hmap *local_sb_svcs_map) -{ - struct service_monitor_info *svc_mon; - HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_sb_svcs_map) { - sbrec_service_monitor_delete(svc_mon->db_rec.sb_rec); - destroy_service_monitor_info(svc_mon); - } - - hmap_destroy(local_sb_svcs_map); -} - -static void -create_pushed_svcs_mon(struct ic_input *ic, - struct hmap *pushed_svcs_map) -{ - struct sbrec_service_monitor *key = - sbrec_service_monitor_index_init_row( - ic->sbrec_service_monitor_by_remote_type); - - sbrec_service_monitor_index_set_remote(key, true); - - const struct sbrec_service_monitor *sb_rec; - SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, - ic->sbrec_service_monitor_by_remote_type) { - const char *target_az_name = smap_get(&sb_rec->options, - "az-name"); - if (!target_az_name) { - continue; - } - create_service_monitor_info(pushed_svcs_map, sb_rec, - &sb_rec->header_.uuid, - ic->runned_az->name, target_az_name, - NULL, false); - } - - sbrec_service_monitor_index_destroy_row(key); -} - -static void -create_synced_svcs_mon(struct ic_input *ic, - struct hmap *synced_svcs_map) -{ - struct icsbrec_service_monitor *key = - icsbrec_service_monitor_index_init_row( - ic->icsbrec_service_monitor_by_target_az); - - icsbrec_service_monitor_index_set_target_availability_zone( - key, ic->runned_az->name); - - const struct icsbrec_service_monitor *ic_rec; - ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, - ic->icsbrec_service_monitor_by_target_az) { - - const struct sbrec_port_binding *pb = - find_sb_pb_by_name(ic->sbrec_port_binding_by_name, - ic_rec->logical_port); - - if (!pb || !pb->up) { - continue; - } - - const char *chassis_name = pb->chassis ? pb->chassis->name : NULL; - create_service_monitor_info(synced_svcs_map, ic_rec, - &ic_rec->header_.uuid, - ic->runned_az->name, - NULL, chassis_name, true); - } - - icsbrec_service_monitor_index_destroy_row(key); -} - -static void -create_local_ic_svcs_map(struct ic_input *ic, - struct hmap *owned_svc_map) -{ - struct icsbrec_service_monitor *key = - icsbrec_service_monitor_index_init_row( - ic->icsbrec_service_monitor_by_source_az); - - icsbrec_service_monitor_index_set_source_availability_zone( - key, ic->runned_az->name); - - const struct icsbrec_service_monitor *ic_rec; - ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, - ic->icsbrec_service_monitor_by_source_az) { - create_service_monitor_info(owned_svc_map, ic_rec, - &ic_rec->header_.uuid, - ic->runned_az->name, NULL, - NULL, true); - } - - icsbrec_service_monitor_index_destroy_row(key); -} - -static void -create_local_sb_svcs_map(struct ic_input *ic, - struct hmap *owned_svc_map) -{ - struct sbrec_service_monitor *key = - sbrec_service_monitor_index_init_row( - ic->sbrec_service_monitor_by_ic_learned); - - sbrec_service_monitor_index_set_ic_learned( - key, true); - - const struct sbrec_service_monitor *sb_rec; - SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, - ic->sbrec_service_monitor_by_ic_learned) { - create_service_monitor_info(owned_svc_map, sb_rec, - &sb_rec->header_.uuid, - ic->runned_az->name, NULL, - NULL, false); - } - - sbrec_service_monitor_index_destroy_row(key); -} - -static const struct sbrec_service_monitor * -lookup_sb_svc_rec(struct ic_input *ic, - const struct service_monitor_info *svc_mon) -{ - const struct icsbrec_service_monitor *db_rec = - svc_mon->db_rec.ic_rec; - struct sbrec_service_monitor *key = - sbrec_service_monitor_index_init_row( - ic->sbrec_service_monitor_by_remote_type_logical_port); - - sbrec_service_monitor_index_set_remote(key, false); - sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port); - - const struct sbrec_service_monitor *sb_rec; - SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key, - ic->sbrec_service_monitor_by_remote_type_logical_port) { - if (db_rec->port == sb_rec->port && - ((db_rec->type && sb_rec->type && - !strcmp(db_rec->type, sb_rec->type)) || - (!db_rec->type && !sb_rec->type)) && - !strcmp(db_rec->ip, sb_rec->ip) && - !strcmp(db_rec->src_ip, sb_rec->src_ip) && - !strcmp(db_rec->protocol, sb_rec->protocol)) { - sbrec_service_monitor_index_destroy_row(key); - return sb_rec; - } - } - - sbrec_service_monitor_index_destroy_row(key); - - return NULL; -} - -static const struct icsbrec_service_monitor * -lookup_icsb_svc_rec(struct ic_input *ic, - const struct service_monitor_info *svc_mon) -{ - const struct sbrec_service_monitor *db_rec = - svc_mon->db_rec.sb_rec; - struct icsbrec_service_monitor *key = - icsbrec_service_monitor_index_init_row( - ic->icsbrec_service_monitor_by_target_az_logical_port); - - ovs_assert(svc_mon->dst_az_name); - icsbrec_service_monitor_index_set_target_availability_zone( - key, svc_mon->dst_az_name); - - icsbrec_service_monitor_index_set_logical_port( - key, db_rec->logical_port); - - const struct icsbrec_service_monitor *ic_rec; - ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key, - ic->icsbrec_service_monitor_by_target_az_logical_port) { - if (db_rec->port == ic_rec->port && - ((db_rec->type && ic_rec->type && - !strcmp(db_rec->type, ic_rec->type)) || - (!db_rec->type && !ic_rec->type)) && - !strcmp(db_rec->ip, ic_rec->ip) && - !strcmp(db_rec->src_ip, ic_rec->src_ip) && - !strcmp(db_rec->protocol, ic_rec->protocol) && - !strcmp(db_rec->logical_port, ic_rec->logical_port)) { - icsbrec_service_monitor_index_destroy_row(key); - return ic_rec; - } - } - - icsbrec_service_monitor_index_destroy_row(key); - - return NULL; -} - -static void -create_service_monitor_data(struct ic_input *ic, - struct sync_service_monitor_data *sync_data) -{ - const struct sbrec_sb_global *ic_sb = - sbrec_sb_global_table_first(ic->sbrec_sb_global_table); - const char *svc_monitor_mac = smap_get(&ic_sb->options, - "svc_monitor_mac"); - - if (!svc_monitor_mac) { - return; - } - - sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac); - create_pushed_svcs_mon(ic, &sync_data->pushed_svcs_map); - create_synced_svcs_mon(ic, &sync_data->synced_svcs_map); - create_local_ic_svcs_map(ic, &sync_data->local_ic_svcs_map); - create_local_sb_svcs_map(ic, &sync_data->local_sb_svcs_map); -} - -static void -destroy_service_monitor_data(struct sync_service_monitor_data *sync_data) -{ - struct service_monitor_info *svc_mon; - HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->pushed_svcs_map) { - destroy_service_monitor_info(svc_mon); - } - - HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->synced_svcs_map) { - destroy_service_monitor_info(svc_mon); - } - - hmap_destroy(&sync_data->pushed_svcs_map); - hmap_destroy(&sync_data->synced_svcs_map); - free(sync_data->prpg_svc_monitor_mac); -} - -static void -sync_service_monitor(struct engine_context *ctx, - struct ic_input *ic) -{ - if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) { - return; - } - - struct sync_service_monitor_data sync_data; - memset(&sync_data, 0, sizeof(sync_data)); - hmap_init(&sync_data.pushed_svcs_map); - hmap_init(&sync_data.synced_svcs_map); - hmap_init(&sync_data.local_ic_svcs_map); - hmap_init(&sync_data.local_sb_svcs_map); - - create_service_monitor_data(ic, &sync_data); - - struct service_monitor_info *svc_mon; - HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.pushed_svcs_map) { - const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec; - const struct icsbrec_service_monitor *ic_rec = - lookup_icsb_svc_rec(ic, svc_mon); - - if (ic_rec) { - sbrec_service_monitor_set_status(db_rec, ic_rec->status); - } else { - ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_idl_txn); - icsbrec_service_monitor_set_type(ic_rec, db_rec->type); - icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip); - icsbrec_service_monitor_set_port(ic_rec, db_rec->port); - icsbrec_service_monitor_set_src_ip(ic_rec, db_rec->src_ip); - icsbrec_service_monitor_set_src_mac(ic_rec, - sync_data.prpg_svc_monitor_mac); - icsbrec_service_monitor_set_protocol(ic_rec, db_rec->protocol); - icsbrec_service_monitor_set_logical_port(ic_rec, - db_rec->logical_port); - icsbrec_service_monitor_set_target_availability_zone(ic_rec, - svc_mon->dst_az_name); - icsbrec_service_monitor_set_source_availability_zone(ic_rec, - svc_mon->src_az_name); - } - - /* Always update options because they change from NB. */ - icsbrec_service_monitor_set_options(ic_rec, &db_rec->options); - refresh_ic_record_cache(&sync_data.local_ic_svcs_map, ic_rec); - } - - HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.synced_svcs_map) { - const struct icsbrec_service_monitor *db_rec = - svc_mon->db_rec.ic_rec; - const struct sbrec_service_monitor *sb_rec = - lookup_sb_svc_rec(ic, svc_mon); - - if (sb_rec) { - icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec, - sb_rec->status); - } else { - sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_idl_txn); - sbrec_service_monitor_set_type(sb_rec, db_rec->type); - sbrec_service_monitor_set_ip(sb_rec, db_rec->ip); - sbrec_service_monitor_set_port(sb_rec, db_rec->port); - sbrec_service_monitor_set_src_ip(sb_rec, db_rec->src_ip); - /* Set svc_monitor_mac from local SBDB. */ - sbrec_service_monitor_set_src_mac(sb_rec, - sync_data.prpg_svc_monitor_mac); - sbrec_service_monitor_set_protocol(sb_rec, - db_rec->protocol); - sbrec_service_monitor_set_logical_port(sb_rec, - db_rec->logical_port); - sbrec_service_monitor_set_remote(sb_rec, false); - sbrec_service_monitor_set_ic_learned(sb_rec, true); - } - - /* Always update options since they may change via - * NB configuration. Also update chassis_name if - * the port has been reassigned to a different chassis. - */ - if (svc_mon->chassis_name) { - sbrec_service_monitor_set_chassis_name(sb_rec, - svc_mon->chassis_name); - } - sbrec_service_monitor_set_options(sb_rec, &db_rec->options); - refresh_sb_record_cache(&sync_data.local_sb_svcs_map, sb_rec); - } - - /* Delete local created records that are no longer used. */ - remove_unused_ic_records(&sync_data.local_ic_svcs_map); - remove_unused_sb_records(&sync_data.local_sb_svcs_map); - - destroy_service_monitor_data(&sync_data); -} - /* * This function implements a sequence number protocol that can be used by * the INB end user to verify that ISB is synced with all the changes that @@ -792,11 +360,11 @@ inc_proc_graph_dump(const char *end_node) } void -ovn_db_run(struct ic_input *input_data, +ovn_db_run(struct ic_input *input_data OVS_UNUSED, struct ic_data *ic_data OVS_UNUSED, - struct engine_context *eng_ctx) + struct engine_context *eng_ctx OVS_UNUSED) { - sync_service_monitor(eng_ctx, input_data); + } static void @@ -1204,6 +772,7 @@ main(int argc, char *argv[]) stopwatch_create(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, SW_MS); stopwatch_create(OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME, SW_MS); stopwatch_create(OVN_IC_TRANSIT_SWITCH_RUN_STOPWATCH_NAME, SW_MS); + stopwatch_create(OVN_IC_SERVICE_MONITOR_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 7e057cc1b..f60e218f6 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -46,13 +46,6 @@ struct ic_input { struct ovsdb_idl_index *nbrec_port_by_name; struct ovsdb_idl_index *sbrec_chassis_by_name; struct ovsdb_idl_index *sbrec_port_binding_by_name; - struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type; - struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned; - 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_service_monitor_by_source_az; - struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az; - struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port; }; struct ic_data { diff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h index 42f8dddc9..60e5445c2 100644 --- a/lib/stopwatch-names.h +++ b/lib/stopwatch-names.h @@ -47,5 +47,6 @@ #define OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME "transit_router_run" #define OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME "port_binding_run" #define OVN_IC_ROUTE_RUN_STOPWATCH_NAME "route_run" +#define OVN_IC_SERVICE_MONITOR_RUN_STOPWATCH_NAME "service_monitor_run" #endif From patchwork Mon Feb 9 18:28:14 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paulo Guilherme Silva X-Patchwork-Id: 2194721 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=Qxakb9cd; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org) Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4f8tWm19tCz1xvc for ; Tue, 10 Feb 2026 05:29:24 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id B2C0341016; Mon, 9 Feb 2026 18:29:22 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id eJBymAugRrTE; Mon, 9 Feb 2026 18:29:20 +0000 (UTC) X-Comment: SPF check N/A for local connections - client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver= DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 8EC7C40BD2 Authentication-Results: smtp2.osuosl.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256 header.s=google header.b=Qxakb9cd Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp2.osuosl.org (Postfix) with ESMTPS id 8EC7C40BD2; Mon, 9 Feb 2026 18:29:07 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 5CF51C077F; Mon, 9 Feb 2026 18:29:07 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 03D05C077E for ; Mon, 9 Feb 2026 18:29:06 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id B82CB40C44 for ; Mon, 9 Feb 2026 18:28:53 +0000 (UTC) X-Virus-Scanned: amavis at osuosl.org Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP id dPUcOmcv8Iq2 for ; Mon, 9 Feb 2026 18:28:49 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=2607:f8b0:4864:20::112a; helo=mail-yw1-x112a.google.com; envelope-from=guilherme.paulo@luizalabs.com; receiver= DMARC-Filter: OpenDMARC Filter v1.4.2 smtp2.osuosl.org 23D2340C2B Authentication-Results: smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none) header.from=luizalabs.com DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 23D2340C2B Received: from mail-yw1-x112a.google.com (mail-yw1-x112a.google.com [IPv6:2607:f8b0:4864:20::112a]) by smtp2.osuosl.org (Postfix) with ESMTPS id 23D2340C2B for ; Mon, 9 Feb 2026 18:28:47 +0000 (UTC) Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-79640a34aecso14773097b3.3 for ; Mon, 09 Feb 2026 10:28:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=luizalabs.com; s=google; t=1770661726; x=1771266526; darn=openvswitch.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bPqPrN8jnVE9y5o8c7PJyx/l3Brq18+gf4I6BtQ9EF0=; b=Qxakb9cduXdnWk7uPmqTSjnQ/qnVuC7HG86BywvP5GOZjipV+ZYfAKp4AM2YADXjQH XWPsmay25aCoYB9JlRVv2V2q+/LNmVd9tpuLuoiu7XA29SwltAFTOKbPVWvBwUKDqENl vl2yiVN7cdvUaUe92crR+yyC8gcuZMMYeUQIw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770661726; x=1771266526; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bPqPrN8jnVE9y5o8c7PJyx/l3Brq18+gf4I6BtQ9EF0=; b=JyjSPsdmeEquj7KmPbx9R2fq30AgPySzMe0Py4Rdit4DJrvAaCNOvbrCwgy2IIzoqy T7G+smOi0PZ/99F1ZTDK59g4HvGnh5YveiRtE3kyR/+s/WGpIJDbb88X6ij6G3hgEAVd OqVs0+Q4fTo4tKg4oJB9u79bgdw3QUdNV1T1d8VfFvgGJ5t8xanNoloE4QM2nQhi5T2L hlu5uJKUd2fuebCtiqqJNpylqaca6qqb0mY0VZxrcv4EMfeOYxTHzkoJ5GVKD3bwiFzQ WuFUZlNDZEiaDWjdKs6mXADeNyx60M7BCgHtbKoOVG8tZXugsvOtVg7w+KQ0k+XfQN4p Dzsw== X-Gm-Message-State: AOJu0YxYefo/Prt7i0M3wWTAAALgkCppv17e5AZc/a37H7gDPwoGH/0k 7np2U6TkXui8uMiwRqkNrh2iJ/RF3mtSRYLM22f+RSYrQ8BFNKe5SC4tLYWWCmhbZZoQWVeYXT6 mw0KVw8SfPvdR+9NGN5YtreebJaL9+SaZ6BG5sghbrrXtI2cc+ZSuStPrjOxwa8s= X-Gm-Gg: AZuq6aJ8PRbUQXjj2Chy6GDIesmeVSlQ2BsRmHeqwVciCOfNMuI3huZn9yEgwhJS5SG eqfJcHm61PuRLff5qzRyAWwuzkF5VHAMSZocrWcHVC19dYhJOyDLprSPaeBsTVN4KwAGicc2Bxn pnAS0ei6oS27sRstAbvaA/rQCcdG/XDZOWxsE3cyMf+MNnlYGC2j5vQM65FrBLjMM3TVGdb0yqH uqxKoFNzT6k45sAsndWlFg3ME5tBJzjZpcUwLb8eCXX08Q7+HclliFmhRilqXx99TDYWvtdfr6q J3yJoUQ7CiOU5/MWfq7TezX/zUJayXp9Vh9ltKYDyZybs4OfbnLLQ6Ghe0j1avE1hNJFtppBTAC nrx35E6Qp0RpR2k9Vzy5Ts/l1senq4GZZTB23BCMmywSTsr0eiDRZxT/FAgFYo2S+fog29NmukQ 1JGqiWamOUtI6+j7bMyHKiLRdKLmJEpBRfUZoXhA== X-Received: by 2002:a05:690c:c509:b0:796:2f36:490c with SMTP id 00721157ae682-7962f3655fbmr75564217b3.12.1770661726348; Mon, 09 Feb 2026 10:28:46 -0800 (PST) Received: from WNLEC-CW22RF4.. ([181.174.255.13]) by smtp.gmail.com with ESMTPSA id 00721157ae682-796528ef241sm16588387b3.27.2026.02.09.10.28.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Feb 2026 10:28:46 -0800 (PST) To: dev@openvswitch.org Date: Mon, 9 Feb 2026 15:28:14 -0300 Message-Id: <20260209182814.842-10-guilherme.paulo@luizalabs.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260209182814.842-1-guilherme.paulo@luizalabs.com> References: <20260209182814.842-1-guilherme.paulo@luizalabs.com> MIME-Version: 1.0 Subject: [ovs-dev] [PATCH ovn v1 9/9] ovn-ic: Refactor engine-node 'en-ic'. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Paulo Guilherme Silva via dev From: Paulo Guilherme Silva Reply-To: Paulo Guilherme Silva Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" There is a need to refactor by cleaning up the remaining code from the 'ic' engine-node after completing the decentralization from a single engine to multiple engines. In the dependency graph of the incremental processing engine (I+P), it becomes the output node. Signed-off-by: Paulo Guilherme Silva --- ic/en-ic.c | 100 ++--------------------------------------------- ic/en-ic.h | 6 --- ic/inc-proc-ic.c | 18 --------- ic/ovn-ic.c | 20 ---------- ic/ovn-ic.h | 38 ------------------ 5 files changed, 4 insertions(+), 178 deletions(-) -- 2.34.1 diff --git a/ic/en-ic.c b/ic/en-ic.c index ecdc1ab5d..0e7f510db 100644 --- a/ic/en-ic.c +++ b/ic/en-ic.c @@ -19,90 +19,15 @@ #include /* OVS includes. */ -#include "openvswitch/vlog.h" +#include "openvswitch/util.h" /* OVN includes. */ -#include "ovn-ic.h" #include "en-ic.h" -#include "en-enum-datapaths.h" -#include "lib/ovn-ic-sb-idl.h" #include "lib/inc-proc-eng.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_ic); -COVERAGE_DEFINE(ic_run); - -void ic_destroy(struct ic_data *data); -void ic_init(struct ic_data *data); - -static void -ic_get_input_data(struct engine_node *node, - struct ic_input *input_data) -{ - /* Table references */ - input_data->nbrec_logical_switch_table = - EN_OVSDB_GET(engine_get_input("NB_logical_switch", node)); - input_data->nbrec_logical_router_table = - EN_OVSDB_GET(engine_get_input("NB_logical_router", node)); - input_data->sbrec_chassis_table = - EN_OVSDB_GET(engine_get_input("SB_chassis", node)); - input_data->icsbrec_ic_sb_global_table = - EN_OVSDB_GET(engine_get_input("ICSB_ic_sb_global", node)); - input_data->icsbrec_availability_zone_table = - EN_OVSDB_GET(engine_get_input("ICSB_availability_zone", node)); - - /* Indexes */ - input_data->nbrec_ls_by_name = - engine_ovsdb_node_get_index( - engine_get_input("NB_logical_switch", node), - "nbrec_ls_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->nbrec_lrp_by_name = - engine_ovsdb_node_get_index( - engine_get_input("NB_logical_router", node), - "nbrec_lrp_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->sbrec_chassis_by_name = - engine_ovsdb_node_get_index( - engine_get_input("SB_chassis", node), - "sbrec_chassis_by_name"); -} enum engine_node_state -en_ic_run(struct engine_node *node, void *data) +en_ic_run(struct engine_node *node OVS_UNUSED, void *data OVS_UNUSED) { - const struct engine_context *eng_ctx = engine_get_context(); - struct ic_data *ic_data = data; - struct ic_input input_data; - - struct ed_type_enum_datapaths *dp_node_data = - engine_get_input_data("enum_datapaths", node); - - if (!dp_node_data) { - return EN_UNCHANGED; - } - - ic_data->dp_tnlids = &dp_node_data->dp_tnlids; - ic_data->isb_ts_dps = &dp_node_data->isb_ts_dps; - ic_data->isb_tr_dps = &dp_node_data->isb_tr_dps; - - ic_get_input_data(node, &input_data); - input_data.runned_az = eng_ctx->client_ctx; - - COVERAGE_INC(ic_run); - stopwatch_start(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec()); - ovn_db_run(&input_data, ic_data, (struct engine_context *) eng_ctx); - stopwatch_stop(IC_OVN_DB_RUN_STOPWATCH_NAME, time_msec()); return EN_UPDATED; } @@ -110,28 +35,11 @@ void * en_ic_init(struct engine_node *node OVS_UNUSED, struct engine_arg *arg OVS_UNUSED) { - struct ic_data *data = xzalloc(sizeof *data); - - ic_init(data); - - return data; -} - -void -en_ic_cleanup(void *data) -{ - ic_destroy(data); + return NULL; } void -ic_destroy(struct ic_data *data OVS_UNUSED) +en_ic_cleanup(void *data OVS_UNUSED) { -} -void -ic_init(struct ic_data *data) -{ - data->dp_tnlids = NULL; - data->isb_ts_dps = NULL; - data->isb_tr_dps = NULL; } diff --git a/ic/en-ic.h b/ic/en-ic.h index ab1fbaf42..13db7570a 100644 --- a/ic/en-ic.h +++ b/ic/en-ic.h @@ -1,12 +1,6 @@ #ifndef EN_IC_H #define EN_IC_H 1 -#include - -#include -#include -#include - #include "lib/inc-proc-eng.h" enum engine_node_state en_ic_run(struct engine_node *node OVS_UNUSED, diff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c index 75479b55a..43102e6ef 100644 --- a/ic/inc-proc-ic.c +++ b/ic/inc-proc-ic.c @@ -43,9 +43,7 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic); NB_NODE(nb_global, "nb_global") \ NB_NODE(logical_router_static_route, "logical_router_static_route") \ NB_NODE(logical_router, "logical_router") \ - NB_NODE(logical_router_port, "logical_router_port") \ NB_NODE(logical_switch, "logical_switch") \ - NB_NODE(logical_switch_port, "logical_switch_port") \ NB_NODE(load_balancer, "load_balancer") \ NB_NODE(load_balancer_group, "load_balancer_group") @@ -68,8 +66,6 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic); #define SB_NODES \ SB_NODE(sb_global, "sb_global") \ SB_NODE(chassis, "chassis") \ - SB_NODE(encap, "encap") \ - SB_NODE(datapath_binding, "datapath_binding") \ SB_NODE(port_binding, "port_binding") \ SB_NODE(service_monitor, "service_monitor") @@ -112,8 +108,6 @@ VLOG_DEFINE_THIS_MODULE(inc_proc_ic); #undef ICNB_NODE #define ICSB_NODES \ - ICSB_NODE(ic_sb_global, "ic_sb_global") \ - ICSB_NODE(availability_zone, "availability_zone") \ ICSB_NODE(service_monitor, "service_monitor") \ ICSB_NODE(route, "route") \ ICSB_NODE(datapath_binding, "datapath_binding") \ @@ -231,18 +225,6 @@ inc_proc_ic_init(struct ovsdb_idl_loop *nb, engine_add_input(&en_ic, &en_route, NULL); engine_add_input(&en_ic, &en_srv_mon, NULL); - engine_add_input(&en_ic, &en_nb_logical_router, NULL); - engine_add_input(&en_ic, &en_nb_logical_router_port, NULL); - engine_add_input(&en_ic, &en_nb_logical_switch, NULL); - engine_add_input(&en_ic, &en_nb_logical_switch_port, NULL); - - engine_add_input(&en_ic, &en_sb_chassis, NULL); - engine_add_input(&en_ic, &en_sb_encap, NULL); - engine_add_input(&en_ic, &en_sb_datapath_binding, NULL); - - engine_add_input(&en_ic, &en_icsb_ic_sb_global, NULL); - engine_add_input(&en_ic, &en_icsb_availability_zone, NULL); - struct engine_arg engine_arg = { .nb_idl = nb->idl, .sb_idl = sb->idl, diff --git a/ic/ovn-ic.c b/ic/ovn-ic.c index 94e4310ba..9386992a0 100644 --- a/ic/ovn-ic.c +++ b/ic/ovn-ic.c @@ -20,32 +20,19 @@ #include #include -#include "bitmap.h" #include "command-line.h" #include "daemon.h" -#include "dirs.h" -#include "openvswitch/dynamic-string.h" #include "fatal-signal.h" -#include "hash.h" -#include "openvswitch/hmap.h" #include "lib/ovn-ic-nb-idl.h" #include "lib/ovn-ic-sb-idl.h" #include "lib/ovn-nb-idl.h" #include "lib/ovn-sb-idl.h" -#include "lib/ovn-util.h" #include "memory.h" #include "openvswitch/poll-loop.h" -#include "ovsdb-idl.h" #include "simap.h" -#include "smap.h" -#include "sset.h" #include "stream.h" #include "stream-ssl.h" -#include "unixctl.h" -#include "util.h" -#include "uuid.h" #include "openvswitch/vlog.h" -#include "vec.h" #include "inc-proc-ic.h" #include "ovn-ic.h" #include "stopwatch-names.h" @@ -359,13 +346,6 @@ inc_proc_graph_dump(const char *end_node) ovsdb_idl_loop_destroy(&ovnisb_idl_loop); } -void -ovn_db_run(struct ic_input *input_data OVS_UNUSED, - struct ic_data *ic_data OVS_UNUSED, - struct engine_context *eng_ctx OVS_UNUSED) -{ - -} static void parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) diff --git a/ic/ovn-ic.h b/ic/ovn-ic.h index f60e218f6..7cb346c7d 100644 --- a/ic/ovn-ic.h +++ b/ic/ovn-ic.h @@ -18,42 +18,6 @@ #include "unixctl.h" #include "lib/inc-proc-eng.h" -struct ic_input { - /* Northbound table references */ - const struct nbrec_logical_switch_table *nbrec_logical_switch_table; - const struct nbrec_logical_router_table *nbrec_logical_router_table; - - /* Southbound table references */ - const struct sbrec_chassis_table *sbrec_chassis_table; - const struct sbrec_sb_global_table *sbrec_sb_global_table; - - /* InterconnectNorthbound table references */ - const struct icnbrec_transit_switch_table *icnbrec_transit_switch_table; - - /* InterconnectSouthbound table references */ - const struct icsbrec_encap_table *icsbrec_encap_table; - const struct icsbrec_ic_sb_global_table *icsbrec_ic_sb_global_table; - const struct icsbrec_datapath_binding_table - *icsbrec_datapath_binding_table; - const struct icsbrec_availability_zone_table - *icsbrec_availability_zone_table; - - /* Indexes */ - const struct icsbrec_availability_zone *runned_az; - struct ovsdb_idl_index *nbrec_ls_by_name; - struct ovsdb_idl_index *nbrec_lr_by_name; - struct ovsdb_idl_index *nbrec_lrp_by_name; - struct ovsdb_idl_index *nbrec_port_by_name; - struct ovsdb_idl_index *sbrec_chassis_by_name; - struct ovsdb_idl_index *sbrec_port_binding_by_name; -}; - -struct ic_data { - /* Global state for 'en-enum-datapaths'. */ - struct hmap *dp_tnlids; - struct shash *isb_ts_dps; - struct shash *isb_tr_dps; -}; struct ic_state { bool had_lock; bool paused; @@ -84,7 +48,5 @@ enum ic_port_binding_type const struct icsbrec_availability_zone * 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, - struct engine_context *eng_ctx); #endif /* OVN_IC_H */