Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.0/patches/2186659/?format=api
{ "id": 2186659, "url": "http://patchwork.ozlabs.org/api/1.0/patches/2186659/?format=api", "project": { "id": 68, "url": "http://patchwork.ozlabs.org/api/1.0/projects/68/?format=api", "name": "Open Virtual Network development", "link_name": "ovn", "list_id": "ovs-dev.openvswitch.org", "list_email": "ovs-dev@openvswitch.org", "web_url": "http://openvswitch.org/", "scm_url": "", "webscm_url": "" }, "msgid": "<20260120114948.2289909-9-guilherme.paulo@luizalabs.com>", "date": "2026-01-20T11:49:47", "name": "[ovs-dev,v0,8/9] ovn-ic: Add a new engine-node 'service-monitor'.", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "d304c491e9dead0e20060021bdc6bd0aa6ee2a4c", "submitter": { "id": 90256, "url": "http://patchwork.ozlabs.org/api/1.0/people/90256/?format=api", "name": "Paulo Guilherme Silva", "email": "guilherme.paulo@luizalabs.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260120114948.2289909-9-guilherme.paulo@luizalabs.com/mbox/", "series": [ { "id": 489037, "url": "http://patchwork.ozlabs.org/api/1.0/series/489037/?format=api", "date": "2026-01-20T11:49:40", "name": "Create multiple engines nodes for ovn-ic.", "version": 0, "mbox": "http://patchwork.ozlabs.org/series/489037/mbox/" } ], "check": "success", "checks": "http://patchwork.ozlabs.org/api/patches/2186659/checks/", "tags": {}, "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=luizalabs.com header.i=@luizalabs.com\n header.a=rsa-sha256 header.s=google header.b=AN+LEYhh;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp4.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=luizalabs.com header.i=@luizalabs.com header.a=rsa-sha256\n header.s=google header.b=AN+LEYhh", "smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=luizalabs.com", "smtp2.osuosl.org;\n dkim=pass (1024-bit key) header.d=luizalabs.com header.i=@luizalabs.com\n header.a=rsa-sha256 header.s=google header.b=AN+LEYhh" ], "Received": [ "from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4dwQdn0NMJz1xsW\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 20 Jan 2026 22:51:25 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 7000242DEE;\n\tTue, 20 Jan 2026 11:51:23 +0000 (UTC)", "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id o0tkfIQQkUeJ; Tue, 20 Jan 2026 11:51:19 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp4.osuosl.org (Postfix) with ESMTPS id EB23540FD4;\n\tTue, 20 Jan 2026 11:51:07 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 7CE62C02A6;\n\tTue, 20 Jan 2026 11:51:07 +0000 (UTC)", "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 142BBC02A5\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:51:06 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 1DD1B42FF4\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:43 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id LbCZ3kpR2zpV for <dev@openvswitch.org>;\n Tue, 20 Jan 2026 11:50:36 +0000 (UTC)", "from mail-dy1-x1336.google.com (mail-dy1-x1336.google.com\n [IPv6:2607:f8b0:4864:20::1336])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 8810E42F57\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 11:50:36 +0000 (UTC)", "by mail-dy1-x1336.google.com with SMTP id\n 5a478bee46e88-2b6f5a9cecaso1368900eec.0\n for <dev@openvswitch.org>; Tue, 20 Jan 2026 03:50:36 -0800 (PST)", "from WNLEC-CW22RF4.. ([177.75.155.81])\n by smtp.gmail.com with ESMTPSA id\n 5a478bee46e88-2b6b367cbc9sm18630559eec.32.2026.01.20.03.50.31\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 20 Jan 2026 03:50:32 -0800 (PST)" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp4.osuosl.org EB23540FD4", "OpenDKIM Filter v2.11.0 smtp2.osuosl.org 8810E42F57" ], "Received-SPF": "Pass (mailfrom) identity=mailfrom;\n client-ip=2607:f8b0:4864:20::1336; helo=mail-dy1-x1336.google.com;\n envelope-from=guilherme.paulo@luizalabs.com; receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp2.osuosl.org 8810E42F57", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=luizalabs.com; s=google; t=1768909835; x=1769514635; darn=openvswitch.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=+VgCmqfL/f3KqfuCqqjFuFCkDpS0OkQo/Z+JIzb4h3g=;\n b=AN+LEYhhcCFs2jDrIEvelWFDakhoZX3NJj4nCAGdEXiugqtw5n2wgKd5YDMry8+JkZ\n lVr+P+lDNmk4BxwQnHRT8mpzMycl1fOjtLCO20ykBF0hh8bE9cPasriw0PP82w6R6zQ2\n bcQFRMAI91DnyiGg6GCCITYSu2wI92891UxhA=", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1768909835; x=1769514635;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=+VgCmqfL/f3KqfuCqqjFuFCkDpS0OkQo/Z+JIzb4h3g=;\n b=EEV7JQ5SqqjzYnqDMwe9pSK0OjvuZdoFqHflXLIFo5osd+8w8UUNfY46E/3rkZLzDG\n C5hKD3DU2/5Qp6OnFcsd2fx65LlPwwzOHUnIsgp9z17MMz7dm82sJ0VnzZaTXiqs+ghu\n BbzQT1jHUPFqKlPJC7lR1lTS3d+UGA3pJ/XG5mjDD3jtYHFb0914qVP0yEmi57W6mD0z\n uhPm9OHJrTL4RT86aDraTGOcJcXUeLRSspmRMgRiwRRdfenYsJaGttC9+/nZMK0ArSM3\n gQ9OdUDpt1KT2yuSUNXYmb1jX8gwI4SXrS7Dvol0DBXODRnK7WvKnpilZ7NW+pjS2zFS\n cCoA==", "X-Gm-Message-State": "AOJu0YyeVOpk0GIWbGA/41lV4u2Bk3J/rYhALVeu1CSV+ndGnBkv5ULx\n 1kXrDKW4jy380kQf7YmuHbGC38NFN0OvYT4fyvLug8NXI7DyO8Rddk0vbcKDAoRSczRMCoVNsTi\n lnVNs54q4BiWfsmoZqqLFmQfd4n9VVDXkU8KYyNMZSpQmyzs4EBOstuUbVMSR", "X-Gm-Gg": "AZuq6aJAHZBI2E2XBvS/RopDZdWnQL5KoKaMTzUt/O+5huby2Jsdbg4aPYfsDr2w+oC\n cKqe13IoZj8E47KstxaOdP4NDBfyND9Clb1Xg9SmJHeL3vWkzychGwATnl2SceGdGJlK2jgoGxs\n StTpJv8ZjwXNT4SGsV8LLzR18QuCeKmiiKEClCxl922oql+uv6TpyOFfGwGxJG1qdiEYCDRPIgV\n iHAkATvuc6+ArVUHk/4eR+NnL9+vM2Lok2q4epfuNuLIjqbdpdkkBIbPviwdvHIxSViun7845Zk\n f9VcYAC4hQQHeUWWspw6pPPPZ+sOaQR9utBO/q+62iobEeNmwroxy8NFMc8ls0/Pxnf9NFdpmtP\n gnZtg68K8PCuDT3/QbdK/VpZO7mf7Pu2e2iaLIJoNw48OXzbTUg+0Ft6QOwcAUZIZXXqx+DwZBN\n q2QgoTZdkeQ7+CJLprkwkMYQZyvrZgQjsB2wi8IQ==", "X-Received": "by 2002:a05:7301:9f18:b0:2b1:76f9:e094 with SMTP id\n 5a478bee46e88-2b6fd7d80a5mr1017998eec.36.1768909833233;\n Tue, 20 Jan 2026 03:50:33 -0800 (PST)", "To": "dev@openvswitch.org", "Date": "Tue, 20 Jan 2026 08:49:47 -0300", "Message-Id": "<20260120114948.2289909-9-guilherme.paulo@luizalabs.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20260120114948.2289909-1-guilherme.paulo@luizalabs.com>", "References": "<20260120114948.2289909-1-guilherme.paulo@luizalabs.com>", "MIME-Version": "1.0", "Subject": "[ovs-dev] [PATCH ovn v0 8/9] ovn-ic: Add a new engine-node\n 'service-monitor'.", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "<ovs-dev.openvswitch.org>", "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>", "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>", "List-Post": "<mailto:ovs-dev@openvswitch.org>", "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>", "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>", "From": "Paulo Guilherme Silva via dev <ovs-dev@openvswitch.org>", "Reply-To": "Paulo Guilherme Silva <guilherme.paulo@luizalabs.com>", "Content-Type": "text/plain; charset=\"iso-8859-1\"", "Content-Transfer-Encoding": "quoted-printable", "Errors-To": "ovs-dev-bounces@openvswitch.org", "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>" }, "content": "This new engine now maintains the service-monitor related data for ovn-ic\ndaemon which was earlier maintained by the ic engine node invoked the\nsync_service_monitor() function. The inputs to this engine node are:\n en_icsb_service_monitor;\n en_sb_sb_global;\n en_sb_service_monitor;\n en_nb_load_balancer;\n en_nb_load_balancer_group;\n en_sb_port_binding;\n\nIn order to achieve this, we refactor in the following way:\n* Introduce srv_mon_init() which initializes this data.\n* Introduce srv_mon_destroy() which clears this data for a new iteration.\n* Introduce srv_mon_run() which invokes the full recompute of the engine.\n\nThis engine node becomes an input to 'ic' node.\n\nSigned-off-by: Paulo Guilherme Silva <guilherme.paulo@luizalabs.com>\n---\n ic/automake.mk | 2 +\n ic/en-ic.c | 30 ---\n ic/en-srv-mon.c | 586 ++++++++++++++++++++++++++++++++++++++++++\n ic/en-srv-mon.h | 67 +++++\n ic/inc-proc-ic.c | 16 +-\n ic/ovn-ic.c | 439 +------------------------------\n ic/ovn-ic.h | 7 -\n lib/stopwatch-names.h | 1 +\n 8 files changed, 670 insertions(+), 478 deletions(-)\n create mode 100644 ic/en-srv-mon.c\n create mode 100644 ic/en-srv-mon.h", "diff": "diff --git a/ic/automake.mk b/ic/automake.mk\nindex 84a487dc1..b84685f60 100644\n--- a/ic/automake.mk\n+++ b/ic/automake.mk\n@@ -16,6 +16,8 @@ ic_ovn_ic_SOURCES = ic/ovn-ic.c \\\n \tic/en-port-binding.h \\\n \tic/en-route.c \\\n \tic/en-route.h \\\n+\tic/en-srv-mon.c \\\n+\tic/en-srv-mon.h \\\n \tic/inc-proc-ic.c \\\n \tic/inc-proc-ic.h\n ic_ovn_ic_LDADD = \\\ndiff --git a/ic/en-ic.c b/ic/en-ic.c\nindex 14c5c29cb..ecdc1ab5d 100644\n--- a/ic/en-ic.c\n+++ b/ic/en-ic.c\n@@ -50,8 +50,6 @@ ic_get_input_data(struct engine_node *node,\n EN_OVSDB_GET(engine_get_input(\"NB_logical_router\", node));\n input_data->sbrec_chassis_table =\n EN_OVSDB_GET(engine_get_input(\"SB_chassis\", node));\n- input_data->sbrec_sb_global_table =\n- EN_OVSDB_GET(engine_get_input(\"SB_sb_global\", node));\n input_data->icsbrec_ic_sb_global_table =\n EN_OVSDB_GET(engine_get_input(\"ICSB_ic_sb_global\", node));\n input_data->icsbrec_availability_zone_table =\n@@ -78,34 +76,6 @@ ic_get_input_data(struct engine_node *node,\n engine_ovsdb_node_get_index(\n engine_get_input(\"SB_chassis\", node),\n \"sbrec_chassis_by_name\");\n- input_data->sbrec_port_binding_by_name =\n- engine_ovsdb_node_get_index(\n- engine_get_input(\"SB_port_binding\", node),\n- \"sbrec_port_binding_by_name\");\n- input_data->sbrec_service_monitor_by_remote_type =\n- engine_ovsdb_node_get_index(\n- engine_get_input(\"SB_service_monitor\", node),\n- \"sbrec_service_monitor_by_remote_type\");\n- input_data->sbrec_service_monitor_by_ic_learned =\n- engine_ovsdb_node_get_index(\n- engine_get_input(\"SB_service_monitor\", node),\n- \"sbrec_service_monitor_by_ic_learned\");\n- input_data->sbrec_service_monitor_by_remote_type_logical_port =\n- engine_ovsdb_node_get_index(\n- engine_get_input(\"SB_service_monitor\", node),\n- \"sbrec_service_monitor_by_remote_type_logical_port\");\n- input_data->icsbrec_service_monitor_by_source_az =\n- engine_ovsdb_node_get_index(\n- engine_get_input(\"ICSB_service_monitor\", node),\n- \"icsbrec_service_monitor_by_source_az\");\n- input_data->icsbrec_service_monitor_by_target_az =\n- engine_ovsdb_node_get_index(\n- engine_get_input(\"ICSB_service_monitor\", node),\n- \"icsbrec_service_monitor_by_target_az\");\n- input_data->icsbrec_service_monitor_by_target_az_logical_port =\n- engine_ovsdb_node_get_index(\n- engine_get_input(\"ICSB_service_monitor\", node),\n- \"icsbrec_service_monitor_by_target_az_logical_port\");\n }\n \n enum engine_node_state\ndiff --git a/ic/en-srv-mon.c b/ic/en-srv-mon.c\nnew file mode 100644\nindex 000000000..a2d6739de\n--- /dev/null\n+++ b/ic/en-srv-mon.c\n@@ -0,0 +1,586 @@\n+/*\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at:\n+ *\n+ * http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+*/\n+\n+#include <config.h>\n+\n+#include <getopt.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+\n+/* OVS includes. */\n+#include \"openvswitch/vlog.h\"\n+\n+/* OVN includes. */\n+#include \"ovn-ic.h\"\n+#include \"en-srv-mon.h\"\n+#include \"inc-proc-ic.h\"\n+#include \"lib/inc-proc-eng.h\"\n+#include \"lib/ovn-nb-idl.h\"\n+#include \"lib/ovn-sb-idl.h\"\n+#include \"lib/ovn-ic-sb-idl.h\"\n+#include \"lib/ovn-util.h\"\n+#include \"lib/stopwatch-names.h\"\n+#include \"coverage.h\"\n+#include \"stopwatch.h\"\n+#include \"stopwatch-names.h\"\n+\n+VLOG_DEFINE_THIS_MODULE(en_srv_mon);\n+COVERAGE_DEFINE(srv_monitor_run);\n+\n+static void\n+srv_mon_run(const struct engine_context *eng_ctx,\n+ struct ed_type_sync_service_monitor *srv_mon_data,\n+ struct srv_mon_input *srv_mon_input,\n+ const struct sbrec_sb_global_table *sbrec_sb_global_table);\n+\n+static void srv_mon_init(struct ed_type_sync_service_monitor *data);\n+static void srv_mon_destroy(struct ed_type_sync_service_monitor *data);\n+static void srv_mon_clear(struct ed_type_sync_service_monitor *data);\n+\n+static void\n+create_service_monitor_info(struct hmap *svc_map,\n+ const void *db_rec,\n+ const struct uuid *uuid,\n+ const char *src_az_name,\n+ const char *target_az_name,\n+ const char *chassis_name,\n+ bool ic_rec);\n+static void\n+destroy_service_monitor_info(struct service_monitor_info *svc_mon);\n+static void\n+refresh_sb_record_cache(struct hmap *svc_mon_map,\n+ const struct sbrec_service_monitor *lookup_rec);\n+static void\n+refresh_ic_record_cache(struct hmap *svc_mon_map,\n+ const struct icsbrec_service_monitor *lookup_rec);\n+static void\n+remove_unused_ic_records(struct hmap *local_ic_svcs_map);\n+static void\n+remove_unused_sb_records(struct hmap *local_sb_svcs_map);\n+static void\n+create_pushed_svcs_mon(struct srv_mon_input *srv_mon_input,\n+ struct hmap *pushed_svcs_map);\n+static void\n+create_synced_svcs_mon(struct srv_mon_input *srv_mon_input,\n+ struct hmap *synced_svcs_map);\n+static void\n+create_local_ic_svcs_map(struct srv_mon_input *srv_mon_input,\n+ struct hmap *owned_svc_map);\n+static void\n+create_local_sb_svcs_map(struct srv_mon_input *srv_mon_input,\n+ struct hmap *owned_svc_map);\n+static const struct sbrec_service_monitor *\n+lookup_sb_svc_rec(struct srv_mon_input *srv_mon_input,\n+ const struct service_monitor_info *svc_mon);\n+static const struct icsbrec_service_monitor *\n+lookup_icsb_svc_rec(struct srv_mon_input *srv_mon_input,\n+ const struct service_monitor_info *svc_mon);\n+static void\n+create_service_monitor_data(struct srv_mon_input *srv_mon_input,\n+ const struct sbrec_sb_global_table *sbrec_sb_global_table,\n+ struct ed_type_sync_service_monitor *sync_data);\n+static void\n+destroy_service_monitor_data(struct ed_type_sync_service_monitor *sync_data);\n+\n+static void\n+srv_mon_get_input_data(struct engine_node *node,\n+ struct srv_mon_input *input_data)\n+{\n+ /* Indexes */\n+ input_data->sbrec_port_binding_by_name =\n+ engine_ovsdb_node_get_index(\n+ engine_get_input(\"SB_port_binding\", node),\n+ \"sbrec_port_binding_by_name\");\n+ input_data->sbrec_service_monitor_by_remote_type =\n+ engine_ovsdb_node_get_index(\n+ engine_get_input(\"SB_service_monitor\", node),\n+ \"sbrec_service_monitor_by_remote_type\");\n+ input_data->sbrec_service_monitor_by_ic_learned =\n+ engine_ovsdb_node_get_index(\n+ engine_get_input(\"SB_service_monitor\", node),\n+ \"sbrec_service_monitor_by_ic_learned\");\n+ input_data->sbrec_service_monitor_by_remote_type_logical_port =\n+ engine_ovsdb_node_get_index(\n+ engine_get_input(\"SB_service_monitor\", node),\n+ \"sbrec_service_monitor_by_remote_type_logical_port\");\n+ input_data->icsbrec_service_monitor_by_source_az =\n+ engine_ovsdb_node_get_index(\n+ engine_get_input(\"ICSB_service_monitor\", node),\n+ \"icsbrec_service_monitor_by_source_az\");\n+ input_data->icsbrec_service_monitor_by_target_az =\n+ engine_ovsdb_node_get_index(\n+ engine_get_input(\"ICSB_service_monitor\", node),\n+ \"icsbrec_service_monitor_by_target_az\");\n+ input_data->icsbrec_service_monitor_by_target_az_logical_port =\n+ engine_ovsdb_node_get_index(\n+ engine_get_input(\"ICSB_service_monitor\", node),\n+ \"icsbrec_service_monitor_by_target_az_logical_port\");\n+}\n+\n+enum engine_node_state\n+en_srv_mon_run(struct engine_node *node, void *data)\n+{\n+ const struct engine_context *eng_ctx = engine_get_context();\n+ struct ed_type_sync_service_monitor *srv_mon_data = data;\n+ struct srv_mon_input srv_mon_input;\n+\n+ srv_mon_clear(srv_mon_data);\n+\n+ const struct sbrec_sb_global_table *sbrec_sb_global_table =\n+ EN_OVSDB_GET(engine_get_input(\"SB_sb_global\", node));\n+\n+ srv_mon_get_input_data(node, &srv_mon_input);\n+ srv_mon_input.runned_az = eng_ctx->client_ctx;\n+\n+ COVERAGE_INC(srv_monitor_run);\n+ stopwatch_start(OVN_IC_SERVICE_MONITOR_RUN_STOPWATCH_NAME, time_usec());\n+ srv_mon_run(eng_ctx, srv_mon_data, &srv_mon_input, sbrec_sb_global_table);\n+ stopwatch_stop(OVN_IC_SERVICE_MONITOR_RUN_STOPWATCH_NAME, time_usec());\n+\n+ return EN_UPDATED;\n+}\n+\n+void *\n+en_srv_mon_init(struct engine_node *node OVS_UNUSED,\n+ struct engine_arg *arg OVS_UNUSED)\n+{\n+ struct ed_type_sync_service_monitor *data = xzalloc(sizeof *data);\n+ srv_mon_init(data);\n+ return data;\n+}\n+\n+void\n+en_srv_mon_cleanup(void *data)\n+{\n+ srv_mon_destroy(data);\n+}\n+\n+static void\n+srv_mon_init(struct ed_type_sync_service_monitor *data)\n+{\n+ hmap_init(&data->pushed_svcs_map);\n+ hmap_init(&data->synced_svcs_map);\n+ hmap_init(&data->local_ic_svcs_map);\n+ hmap_init(&data->local_sb_svcs_map);\n+ data->prpg_svc_monitor_mac = NULL;\n+ data->tracked = false;\n+}\n+\n+static void\n+srv_mon_destroy(struct ed_type_sync_service_monitor *data)\n+{\n+ destroy_service_monitor_data(data);\n+}\n+\n+static void\n+srv_mon_clear(struct ed_type_sync_service_monitor *data)\n+{\n+ destroy_service_monitor_data(data);\n+ srv_mon_init(data);\n+}\n+\n+static void\n+srv_mon_run(const struct engine_context *eng_ctx,\n+ struct ed_type_sync_service_monitor *srv_mon_data,\n+ struct srv_mon_input *srv_mon_input,\n+ const struct sbrec_sb_global_table *sbrec_sb_global_table)\n+{\n+ if (!eng_ctx->ovnisb_idl_txn || !eng_ctx->ovnsb_idl_txn) {\n+ return;\n+ }\n+\n+ create_service_monitor_data(srv_mon_input, sbrec_sb_global_table,\n+ srv_mon_data);\n+\n+ struct service_monitor_info *svc_mon;\n+ HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &srv_mon_data->pushed_svcs_map) {\n+ const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec;\n+ const struct icsbrec_service_monitor *ic_rec =\n+ lookup_icsb_svc_rec(srv_mon_input, svc_mon);\n+\n+ if (ic_rec) {\n+ sbrec_service_monitor_set_status(db_rec, ic_rec->status);\n+ } else {\n+ ic_rec = icsbrec_service_monitor_insert(eng_ctx->ovnisb_idl_txn);\n+ icsbrec_service_monitor_set_type(ic_rec, db_rec->type);\n+ icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip);\n+ icsbrec_service_monitor_set_port(ic_rec, db_rec->port);\n+ icsbrec_service_monitor_set_src_ip(ic_rec, db_rec->src_ip);\n+ icsbrec_service_monitor_set_src_mac(ic_rec,\n+ srv_mon_data->prpg_svc_monitor_mac);\n+ icsbrec_service_monitor_set_protocol(ic_rec, db_rec->protocol);\n+ icsbrec_service_monitor_set_logical_port(ic_rec,\n+ db_rec->logical_port);\n+ icsbrec_service_monitor_set_target_availability_zone(ic_rec,\n+ svc_mon->dst_az_name);\n+ icsbrec_service_monitor_set_source_availability_zone(ic_rec,\n+ svc_mon->src_az_name);\n+ }\n+\n+ /* Always update options because they change from NB. */\n+ icsbrec_service_monitor_set_options(ic_rec, &db_rec->options);\n+ refresh_ic_record_cache(&srv_mon_data->local_ic_svcs_map, ic_rec);\n+ }\n+\n+ HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &srv_mon_data->synced_svcs_map) {\n+ const struct icsbrec_service_monitor *db_rec =\n+ svc_mon->db_rec.ic_rec;\n+ const struct sbrec_service_monitor *sb_rec =\n+ lookup_sb_svc_rec(srv_mon_input, svc_mon);\n+\n+ if (sb_rec) {\n+ icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec,\n+ sb_rec->status);\n+ } else {\n+ sb_rec = sbrec_service_monitor_insert(eng_ctx->ovnsb_idl_txn);\n+ sbrec_service_monitor_set_type(sb_rec, db_rec->type);\n+ sbrec_service_monitor_set_ip(sb_rec, db_rec->ip);\n+ sbrec_service_monitor_set_port(sb_rec, db_rec->port);\n+ sbrec_service_monitor_set_src_ip(sb_rec, db_rec->src_ip);\n+ /* Set svc_monitor_mac from local SBDB. */\n+ sbrec_service_monitor_set_src_mac(sb_rec,\n+ srv_mon_data->prpg_svc_monitor_mac);\n+ sbrec_service_monitor_set_protocol(sb_rec,\n+ db_rec->protocol);\n+ sbrec_service_monitor_set_logical_port(sb_rec,\n+ db_rec->logical_port);\n+ sbrec_service_monitor_set_remote(sb_rec, false);\n+ sbrec_service_monitor_set_ic_learned(sb_rec, true);\n+ }\n+\n+ /* Always update options since they may change via\n+ * NB configuration. Also update chassis_name if\n+ * the port has been reassigned to a different chassis.\n+ */\n+ if (svc_mon->chassis_name) {\n+ sbrec_service_monitor_set_chassis_name(sb_rec,\n+ svc_mon->chassis_name);\n+ }\n+ sbrec_service_monitor_set_options(sb_rec, &db_rec->options);\n+ refresh_sb_record_cache(&srv_mon_data->local_sb_svcs_map, sb_rec);\n+ }\n+\n+ /* Delete local created records that are no longer used. */\n+ remove_unused_ic_records(&srv_mon_data->local_ic_svcs_map);\n+ remove_unused_sb_records(&srv_mon_data->local_sb_svcs_map);\n+}\n+\n+static void\n+create_service_monitor_info(struct hmap *svc_map,\n+ const void *db_rec,\n+ const struct uuid *uuid,\n+ const char *src_az_name,\n+ const char *target_az_name,\n+ const char *chassis_name,\n+ bool ic_rec)\n+{\n+ struct service_monitor_info *svc_mon = xzalloc(sizeof(*svc_mon));\n+ size_t hash = uuid_hash(uuid);\n+\n+ if (ic_rec) {\n+ svc_mon->db_rec.ic_rec =\n+ (const struct icsbrec_service_monitor *) db_rec;\n+ } else {\n+ svc_mon->db_rec.sb_rec =\n+ (const struct sbrec_service_monitor *) db_rec;\n+ }\n+\n+ svc_mon->dst_az_name = target_az_name ? xstrdup(target_az_name) : NULL;\n+ svc_mon->chassis_name = chassis_name ? xstrdup(chassis_name) : NULL;\n+ svc_mon->src_az_name = xstrdup(src_az_name);\n+\n+ hmap_insert(svc_map, &svc_mon->hmap_node, hash);\n+}\n+\n+static void\n+destroy_service_monitor_info(struct service_monitor_info *svc_mon)\n+{\n+ free(svc_mon->src_az_name);\n+ free(svc_mon->dst_az_name);\n+ free(svc_mon->chassis_name);\n+ free(svc_mon);\n+}\n+\n+static void\n+refresh_sb_record_cache(struct hmap *svc_mon_map,\n+ const struct sbrec_service_monitor *lookup_rec)\n+{\n+ size_t hash = uuid_hash(&lookup_rec->header_.uuid);\n+ struct service_monitor_info *svc_mon;\n+\n+ HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) {\n+ ovs_assert(svc_mon->db_rec.sb_rec);\n+ if (svc_mon->db_rec.sb_rec == lookup_rec) {\n+ hmap_remove(svc_mon_map, &svc_mon->hmap_node);\n+ destroy_service_monitor_info(svc_mon);\n+ return;\n+ }\n+ }\n+}\n+\n+static void\n+refresh_ic_record_cache(struct hmap *svc_mon_map,\n+ const struct icsbrec_service_monitor *lookup_rec)\n+{\n+ size_t hash = uuid_hash(&lookup_rec->header_.uuid);\n+ struct service_monitor_info *svc_mon;\n+\n+ HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) {\n+ ovs_assert(svc_mon->db_rec.ic_rec);\n+ if (svc_mon->db_rec.ic_rec == lookup_rec) {\n+ hmap_remove(svc_mon_map, &svc_mon->hmap_node);\n+ destroy_service_monitor_info(svc_mon);\n+ return;\n+ }\n+ }\n+}\n+\n+static void\n+remove_unused_ic_records(struct hmap *local_ic_svcs_map)\n+{\n+ struct service_monitor_info *svc_mon;\n+ HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_ic_svcs_map) {\n+ icsbrec_service_monitor_delete(svc_mon->db_rec.ic_rec);\n+ destroy_service_monitor_info(svc_mon);\n+ }\n+\n+ hmap_destroy(local_ic_svcs_map);\n+}\n+\n+static void\n+remove_unused_sb_records(struct hmap *local_sb_svcs_map)\n+{\n+ struct service_monitor_info *svc_mon;\n+ HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_sb_svcs_map) {\n+ sbrec_service_monitor_delete(svc_mon->db_rec.sb_rec);\n+ destroy_service_monitor_info(svc_mon);\n+ }\n+\n+ hmap_destroy(local_sb_svcs_map);\n+}\n+\n+static void\n+create_pushed_svcs_mon(struct srv_mon_input *srv_mon_input,\n+ struct hmap *pushed_svcs_map)\n+{\n+ struct sbrec_service_monitor *key =\n+ sbrec_service_monitor_index_init_row(\n+ srv_mon_input->sbrec_service_monitor_by_remote_type);\n+\n+ sbrec_service_monitor_index_set_remote(key, true);\n+\n+ const struct sbrec_service_monitor *sb_rec;\n+ SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n+ srv_mon_input->sbrec_service_monitor_by_remote_type) {\n+ const char *target_az_name = smap_get(&sb_rec->options,\n+ \"az-name\");\n+ if (!target_az_name) {\n+ continue;\n+ }\n+ create_service_monitor_info(pushed_svcs_map, sb_rec,\n+ &sb_rec->header_.uuid,\n+ srv_mon_input->runned_az->name,\n+ target_az_name, NULL, false);\n+ }\n+\n+ sbrec_service_monitor_index_destroy_row(key);\n+}\n+\n+static void\n+create_synced_svcs_mon(struct srv_mon_input *srv_mon_input,\n+ struct hmap *synced_svcs_map)\n+{\n+ struct icsbrec_service_monitor *key =\n+ icsbrec_service_monitor_index_init_row(\n+ srv_mon_input->icsbrec_service_monitor_by_target_az);\n+\n+ icsbrec_service_monitor_index_set_target_availability_zone(\n+ key, srv_mon_input->runned_az->name);\n+\n+ const struct icsbrec_service_monitor *ic_rec;\n+ ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n+ srv_mon_input->icsbrec_service_monitor_by_target_az) {\n+\n+ const struct sbrec_port_binding *pb =\n+ find_sb_pb_by_name(srv_mon_input->sbrec_port_binding_by_name,\n+ ic_rec->logical_port);\n+\n+ if (!pb || !pb->up) {\n+ continue;\n+ }\n+\n+ const char *chassis_name = pb->chassis ? pb->chassis->name : NULL;\n+ create_service_monitor_info(synced_svcs_map, ic_rec,\n+ &ic_rec->header_.uuid,\n+ srv_mon_input->runned_az->name, NULL,\n+ chassis_name, true);\n+ }\n+\n+ icsbrec_service_monitor_index_destroy_row(key);\n+}\n+\n+static void\n+create_local_ic_svcs_map(struct srv_mon_input *srv_mon_input,\n+ struct hmap *owned_svc_map)\n+{\n+ struct icsbrec_service_monitor *key =\n+ icsbrec_service_monitor_index_init_row(\n+ srv_mon_input->icsbrec_service_monitor_by_source_az);\n+\n+ icsbrec_service_monitor_index_set_source_availability_zone(\n+ key, srv_mon_input->runned_az->name);\n+\n+ const struct icsbrec_service_monitor *ic_rec;\n+ ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n+ srv_mon_input->icsbrec_service_monitor_by_source_az) {\n+ create_service_monitor_info(owned_svc_map, ic_rec,\n+ &ic_rec->header_.uuid,\n+ srv_mon_input->runned_az->name, NULL,\n+ NULL, true);\n+ }\n+\n+ icsbrec_service_monitor_index_destroy_row(key);\n+}\n+\n+static void\n+create_local_sb_svcs_map(struct srv_mon_input *srv_mon_input,\n+ struct hmap *owned_svc_map)\n+{\n+ struct sbrec_service_monitor *key =\n+ sbrec_service_monitor_index_init_row(\n+ srv_mon_input->sbrec_service_monitor_by_ic_learned);\n+\n+ sbrec_service_monitor_index_set_ic_learned(\n+ key, true);\n+\n+ const struct sbrec_service_monitor *sb_rec;\n+ SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n+ srv_mon_input->sbrec_service_monitor_by_ic_learned) {\n+ create_service_monitor_info(owned_svc_map, sb_rec,\n+ &sb_rec->header_.uuid,\n+ srv_mon_input->runned_az->name, NULL,\n+ NULL, false);\n+ }\n+\n+ sbrec_service_monitor_index_destroy_row(key);\n+}\n+\n+static const struct sbrec_service_monitor *\n+lookup_sb_svc_rec(struct srv_mon_input *srv_mon_input,\n+ const struct service_monitor_info *svc_mon)\n+{\n+ const struct icsbrec_service_monitor *db_rec =\n+ svc_mon->db_rec.ic_rec;\n+ struct sbrec_service_monitor *key =\n+ sbrec_service_monitor_index_init_row(\n+ srv_mon_input->sbrec_service_monitor_by_remote_type_logical_port);\n+\n+ sbrec_service_monitor_index_set_remote(key, false);\n+ sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port);\n+\n+ const struct sbrec_service_monitor *sb_rec;\n+ SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n+ srv_mon_input->sbrec_service_monitor_by_remote_type_logical_port) {\n+ if (db_rec->port == sb_rec->port &&\n+ ((db_rec->type && sb_rec->type &&\n+ !strcmp(db_rec->type, sb_rec->type)) ||\n+ (!db_rec->type && !sb_rec->type)) &&\n+ !strcmp(db_rec->ip, sb_rec->ip) &&\n+ !strcmp(db_rec->src_ip, sb_rec->src_ip) &&\n+ !strcmp(db_rec->protocol, sb_rec->protocol)) {\n+ sbrec_service_monitor_index_destroy_row(key);\n+ return sb_rec;\n+ }\n+ }\n+\n+ sbrec_service_monitor_index_destroy_row(key);\n+\n+ return NULL;\n+}\n+\n+static const struct icsbrec_service_monitor *\n+lookup_icsb_svc_rec(struct srv_mon_input *srv_mon_input,\n+ const struct service_monitor_info *svc_mon)\n+{\n+ const struct sbrec_service_monitor *db_rec =\n+ svc_mon->db_rec.sb_rec;\n+ struct icsbrec_service_monitor *key =\n+ icsbrec_service_monitor_index_init_row(\n+ srv_mon_input->icsbrec_service_monitor_by_target_az_logical_port);\n+\n+ ovs_assert(svc_mon->dst_az_name);\n+ icsbrec_service_monitor_index_set_target_availability_zone(\n+ key, svc_mon->dst_az_name);\n+\n+ icsbrec_service_monitor_index_set_logical_port(\n+ key, db_rec->logical_port);\n+\n+ const struct icsbrec_service_monitor *ic_rec;\n+ ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n+ srv_mon_input->icsbrec_service_monitor_by_target_az_logical_port) {\n+ if (db_rec->port == ic_rec->port &&\n+ ((db_rec->type && ic_rec->type &&\n+ !strcmp(db_rec->type, ic_rec->type)) ||\n+ (!db_rec->type && !ic_rec->type)) &&\n+ !strcmp(db_rec->ip, ic_rec->ip) &&\n+ !strcmp(db_rec->src_ip, ic_rec->src_ip) &&\n+ !strcmp(db_rec->protocol, ic_rec->protocol) &&\n+ !strcmp(db_rec->logical_port, ic_rec->logical_port)) {\n+ icsbrec_service_monitor_index_destroy_row(key);\n+ return ic_rec;\n+ }\n+ }\n+\n+ icsbrec_service_monitor_index_destroy_row(key);\n+\n+ return NULL;\n+}\n+\n+static void\n+create_service_monitor_data(struct srv_mon_input *srv_mon_input,\n+ const struct sbrec_sb_global_table *sbrec_sb_global_table,\n+ struct ed_type_sync_service_monitor *sync_data)\n+{\n+ const struct sbrec_sb_global *ic_sb =\n+ sbrec_sb_global_table_first(sbrec_sb_global_table);\n+ const char *svc_monitor_mac = smap_get(&ic_sb->options,\n+ \"svc_monitor_mac\");\n+\n+ if (!svc_monitor_mac) {\n+ return;\n+ }\n+\n+ sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac);\n+ create_pushed_svcs_mon(srv_mon_input, &sync_data->pushed_svcs_map);\n+ create_synced_svcs_mon(srv_mon_input, &sync_data->synced_svcs_map);\n+ create_local_ic_svcs_map(srv_mon_input, &sync_data->local_ic_svcs_map);\n+ create_local_sb_svcs_map(srv_mon_input, &sync_data->local_sb_svcs_map);\n+}\n+\n+static void\n+destroy_service_monitor_data(struct ed_type_sync_service_monitor *sync_data)\n+{\n+ struct service_monitor_info *svc_mon;\n+ HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->pushed_svcs_map) {\n+ destroy_service_monitor_info(svc_mon);\n+ }\n+\n+ HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->synced_svcs_map) {\n+ destroy_service_monitor_info(svc_mon);\n+ }\n+\n+ hmap_destroy(&sync_data->pushed_svcs_map);\n+ hmap_destroy(&sync_data->synced_svcs_map);\n+ free(sync_data->prpg_svc_monitor_mac);\n+}\ndiff --git a/ic/en-srv-mon.h b/ic/en-srv-mon.h\nnew file mode 100644\nindex 000000000..1b160dd4d\n--- /dev/null\n+++ b/ic/en-srv-mon.h\n@@ -0,0 +1,67 @@\n+#ifndef EN_IC_SRV_MONITOR_RUN_H\n+#define EN_IC_SRV_MONITOR_RUN_H 1\n+\n+#include <config.h>\n+\n+#include <stdbool.h>\n+#include <getopt.h>\n+#include <stdlib.h>\n+#include <stdio.h>\n+\n+/* OVS includes. */\n+#include \"openvswitch/hmap.h\"\n+\n+/* OVN includes. */\n+#include \"lib/inc-proc-eng.h\"\n+\n+/*\n+ * Data structures and functions related to\n+ * synchronize health checks for load balancers\n+ * between availability zones.\n+ */\n+struct ed_type_sync_service_monitor {\n+ /* Map of service monitors to be pushed to other AZs. */\n+ struct hmap pushed_svcs_map;\n+ /* Map of service monitors synced from other AZs to our. */\n+ struct hmap synced_svcs_map;\n+ /* Map of local service monitors in the ICSBDB. */\n+ struct hmap local_ic_svcs_map;\n+ /* Map of local service monitors in SBDB. */\n+ struct hmap local_sb_svcs_map;\n+ /* MAC address used for service monitor. */\n+ char *prpg_svc_monitor_mac;\n+\n+ bool tracked;\n+};\n+\n+struct service_monitor_info {\n+ struct hmap_node hmap_node;\n+ union {\n+ const struct sbrec_service_monitor *sb_rec;\n+ const struct icsbrec_service_monitor *ic_rec;\n+ } db_rec;\n+ /* Destination availability zone name. */\n+ char *dst_az_name;\n+ /* Source availability zone name. */\n+ char *src_az_name;\n+ /* Chassis name associated with monitor logical port. */\n+ char *chassis_name;\n+};\n+\n+struct srv_mon_input {\n+ /* Indexes */\n+ const struct icsbrec_availability_zone *runned_az;\n+ struct ovsdb_idl_index *sbrec_port_binding_by_name;\n+ struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type;\n+ struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned;\n+ struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port;\n+ struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az;\n+ struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az;\n+ struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port;\n+};\n+\n+void *en_srv_mon_init(struct engine_node *, struct engine_arg *);\n+enum engine_node_state en_srv_mon_run(struct engine_node *, void *data);\n+void en_srv_mon_cleanup(void *data);\n+\n+#endif\ndiff --git a/ic/inc-proc-ic.c b/ic/inc-proc-ic.c\nindex af282fad6..0fe787a19 100644\n--- a/ic/inc-proc-ic.c\n+++ b/ic/inc-proc-ic.c\n@@ -33,6 +33,7 @@\n #include \"en-tr.h\"\n #include \"en-port-binding.h\"\n #include \"en-route.h\"\n+#include \"en-srv-mon.h\"\n #include \"unixctl.h\"\n #include \"util.h\"\n \n@@ -170,6 +171,7 @@ static ENGINE_NODE(tr);\n static ENGINE_NODE(ts, SB_WRITE);\n static ENGINE_NODE(port_binding, SB_WRITE);\n static ENGINE_NODE(route);\n+static ENGINE_NODE(srv_mon, SB_WRITE);\n \n void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n struct ovsdb_idl_loop *sb,\n@@ -213,30 +215,32 @@ void inc_proc_ic_init(struct ovsdb_idl_loop *nb,\n engine_add_input(&en_route, &en_icsb_route, NULL);\n engine_add_input(&en_route, &en_nb_logical_router_static_route, NULL);\n \n+ engine_add_input(&en_srv_mon, &en_icsb_service_monitor, NULL);\n+ engine_add_input(&en_srv_mon, &en_sb_sb_global, NULL);\n+ engine_add_input(&en_srv_mon, &en_sb_service_monitor, NULL);\n+ engine_add_input(&en_srv_mon, &en_nb_load_balancer, NULL);\n+ engine_add_input(&en_srv_mon, &en_nb_load_balancer_group, NULL);\n+ engine_add_input(&en_srv_mon, &en_sb_port_binding, NULL);\n+\n engine_add_input(&en_ic, &en_gateway, NULL);\n engine_add_input(&en_ic, &en_enum_datapaths, NULL);\n engine_add_input(&en_ic, &en_ts, NULL);\n engine_add_input(&en_ic, &en_tr, NULL);\n engine_add_input(&en_ic, &en_port_binding, NULL);\n engine_add_input(&en_ic, &en_route, NULL);\n+ engine_add_input(&en_ic, &en_srv_mon, NULL);\n \n engine_add_input(&en_ic, &en_nb_logical_router, NULL);\n engine_add_input(&en_ic, &en_nb_logical_router_port, NULL);\n engine_add_input(&en_ic, &en_nb_logical_switch, NULL);\n engine_add_input(&en_ic, &en_nb_logical_switch_port, NULL);\n- engine_add_input(&en_ic, &en_nb_load_balancer, NULL);\n- engine_add_input(&en_ic, &en_nb_load_balancer_group, NULL);\n \n- engine_add_input(&en_ic, &en_sb_sb_global, NULL);\n engine_add_input(&en_ic, &en_sb_chassis, NULL);\n engine_add_input(&en_ic, &en_sb_encap, NULL);\n engine_add_input(&en_ic, &en_sb_datapath_binding, NULL);\n- engine_add_input(&en_ic, &en_sb_port_binding, NULL);\n- engine_add_input(&en_ic, &en_sb_service_monitor, NULL);\n \n engine_add_input(&en_ic, &en_icsb_ic_sb_global, NULL);\n engine_add_input(&en_ic, &en_icsb_availability_zone, NULL);\n- engine_add_input(&en_ic, &en_icsb_service_monitor, NULL);\n \n struct engine_arg engine_arg = {\n .nb_idl = nb->idl,\ndiff --git a/ic/ovn-ic.c b/ic/ovn-ic.c\nindex 301b54fb2..3406c4d5d 100644\n--- a/ic/ovn-ic.c\n+++ b/ic/ovn-ic.c\n@@ -247,438 +247,6 @@ find_sb_pb_by_name(struct ovsdb_idl_index *sbrec_port_binding_by_name,\n return pb;\n }\n \n-/*\n- * Data structures and functions related to\n- * synchronize health checks for load balancers\n- * between availability zones.\n- */\n-struct sync_service_monitor_data {\n- /* Map of service monitors to be pushed to other AZs. */\n- struct hmap pushed_svcs_map;\n- /* Map of service monitors synced from other AZs to our. */\n- struct hmap synced_svcs_map;\n- /* Map of local service monitors in the ICSBDB. */\n- struct hmap local_ic_svcs_map;\n- /* Map of local service monitors in SBDB. */\n- struct hmap local_sb_svcs_map;\n- /* MAC address used for service monitor. */\n- char *prpg_svc_monitor_mac;\n-};\n-\n-struct service_monitor_info {\n- struct hmap_node hmap_node;\n- union {\n- const struct sbrec_service_monitor *sb_rec;\n- const struct icsbrec_service_monitor *ic_rec;\n- } db_rec;\n- /* Destination availability zone name. */\n- char *dst_az_name;\n- /* Source availability zone name. */\n- char *src_az_name;\n- /* Chassis name associated with monitor logical port. */\n- char *chassis_name;\n-};\n-\n-static void\n-create_service_monitor_info(struct hmap *svc_map,\n- const void *db_rec,\n- const struct uuid *uuid,\n- const char *src_az_name,\n- const char *target_az_name,\n- const char *chassis_name,\n- bool ic_rec)\n-{\n- struct service_monitor_info *svc_mon = xzalloc(sizeof(*svc_mon));\n- size_t hash = uuid_hash(uuid);\n-\n- if (ic_rec) {\n- svc_mon->db_rec.ic_rec =\n- (const struct icsbrec_service_monitor *) db_rec;\n- } else {\n- svc_mon->db_rec.sb_rec =\n- (const struct sbrec_service_monitor *) db_rec;\n- }\n-\n- svc_mon->dst_az_name = target_az_name ? xstrdup(target_az_name) : NULL;\n- svc_mon->chassis_name = chassis_name ? xstrdup(chassis_name) : NULL;\n- svc_mon->src_az_name = xstrdup(src_az_name);\n-\n- hmap_insert(svc_map, &svc_mon->hmap_node, hash);\n-}\n-\n-static void\n-destroy_service_monitor_info(struct service_monitor_info *svc_mon)\n-{\n- free(svc_mon->src_az_name);\n- free(svc_mon->dst_az_name);\n- free(svc_mon->chassis_name);\n- free(svc_mon);\n-}\n-\n-static void\n-refresh_sb_record_cache(struct hmap *svc_mon_map,\n- const struct sbrec_service_monitor *lookup_rec)\n-{\n- size_t hash = uuid_hash(&lookup_rec->header_.uuid);\n- struct service_monitor_info *svc_mon;\n-\n- HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) {\n- ovs_assert(svc_mon->db_rec.sb_rec);\n- if (svc_mon->db_rec.sb_rec == lookup_rec) {\n- hmap_remove(svc_mon_map, &svc_mon->hmap_node);\n- destroy_service_monitor_info(svc_mon);\n- return;\n- }\n- }\n-}\n-\n-static void\n-refresh_ic_record_cache(struct hmap *svc_mon_map,\n- const struct icsbrec_service_monitor *lookup_rec)\n-{\n- size_t hash = uuid_hash(&lookup_rec->header_.uuid);\n- struct service_monitor_info *svc_mon;\n-\n- HMAP_FOR_EACH_WITH_HASH (svc_mon, hmap_node, hash, svc_mon_map) {\n- ovs_assert(svc_mon->db_rec.ic_rec);\n- if (svc_mon->db_rec.ic_rec == lookup_rec) {\n- hmap_remove(svc_mon_map, &svc_mon->hmap_node);\n- destroy_service_monitor_info(svc_mon);\n- return;\n- }\n- }\n-}\n-\n-static void\n-remove_unused_ic_records(struct hmap *local_ic_svcs_map)\n-{\n- struct service_monitor_info *svc_mon;\n- HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_ic_svcs_map) {\n- icsbrec_service_monitor_delete(svc_mon->db_rec.ic_rec);\n- destroy_service_monitor_info(svc_mon);\n- }\n-\n- hmap_destroy(local_ic_svcs_map);\n-}\n-\n-static void\n-remove_unused_sb_records(struct hmap *local_sb_svcs_map)\n-{\n- struct service_monitor_info *svc_mon;\n- HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, local_sb_svcs_map) {\n- sbrec_service_monitor_delete(svc_mon->db_rec.sb_rec);\n- destroy_service_monitor_info(svc_mon);\n- }\n-\n- hmap_destroy(local_sb_svcs_map);\n-}\n-\n-static void\n-create_pushed_svcs_mon(struct ic_input *ic,\n- struct hmap *pushed_svcs_map)\n-{\n- struct sbrec_service_monitor *key =\n- sbrec_service_monitor_index_init_row(\n- ic->sbrec_service_monitor_by_remote_type);\n-\n- sbrec_service_monitor_index_set_remote(key, true);\n-\n- const struct sbrec_service_monitor *sb_rec;\n- SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n- ic->sbrec_service_monitor_by_remote_type) {\n- const char *target_az_name = smap_get(&sb_rec->options,\n- \"az-name\");\n- if (!target_az_name) {\n- continue;\n- }\n- create_service_monitor_info(pushed_svcs_map, sb_rec,\n- &sb_rec->header_.uuid,\n- ic->runned_az->name, target_az_name,\n- NULL, false);\n- }\n-\n- sbrec_service_monitor_index_destroy_row(key);\n-}\n-\n-static void\n-create_synced_svcs_mon(struct ic_input *ic,\n- struct hmap *synced_svcs_map)\n-{\n- struct icsbrec_service_monitor *key =\n- icsbrec_service_monitor_index_init_row(\n- ic->icsbrec_service_monitor_by_target_az);\n-\n- icsbrec_service_monitor_index_set_target_availability_zone(\n- key, ic->runned_az->name);\n-\n- const struct icsbrec_service_monitor *ic_rec;\n- ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n- ic->icsbrec_service_monitor_by_target_az) {\n-\n- const struct sbrec_port_binding *pb =\n- find_sb_pb_by_name(ic->sbrec_port_binding_by_name,\n- ic_rec->logical_port);\n-\n- if (!pb || !pb->up) {\n- continue;\n- }\n-\n- const char *chassis_name = pb->chassis ? pb->chassis->name : NULL;\n- create_service_monitor_info(synced_svcs_map, ic_rec,\n- &ic_rec->header_.uuid,\n- ic->runned_az->name,\n- NULL, chassis_name, true);\n- }\n-\n- icsbrec_service_monitor_index_destroy_row(key);\n-}\n-\n-static void\n-create_local_ic_svcs_map(struct ic_input *ic,\n- struct hmap *owned_svc_map)\n-{\n- struct icsbrec_service_monitor *key =\n- icsbrec_service_monitor_index_init_row(\n- ic->icsbrec_service_monitor_by_source_az);\n-\n- icsbrec_service_monitor_index_set_source_availability_zone(\n- key, ic->runned_az->name);\n-\n- const struct icsbrec_service_monitor *ic_rec;\n- ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n- ic->icsbrec_service_monitor_by_source_az) {\n- create_service_monitor_info(owned_svc_map, ic_rec,\n- &ic_rec->header_.uuid,\n- ic->runned_az->name, NULL,\n- NULL, true);\n- }\n-\n- icsbrec_service_monitor_index_destroy_row(key);\n-}\n-\n-static void\n-create_local_sb_svcs_map(struct ic_input *ic,\n- struct hmap *owned_svc_map)\n-{\n- struct sbrec_service_monitor *key =\n- sbrec_service_monitor_index_init_row(\n- ic->sbrec_service_monitor_by_ic_learned);\n-\n- sbrec_service_monitor_index_set_ic_learned(\n- key, true);\n-\n- const struct sbrec_service_monitor *sb_rec;\n- SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n- ic->sbrec_service_monitor_by_ic_learned) {\n- create_service_monitor_info(owned_svc_map, sb_rec,\n- &sb_rec->header_.uuid,\n- ic->runned_az->name, NULL,\n- NULL, false);\n- }\n-\n- sbrec_service_monitor_index_destroy_row(key);\n-}\n-\n-static const struct sbrec_service_monitor *\n-lookup_sb_svc_rec(struct ic_input *ic,\n- const struct service_monitor_info *svc_mon)\n-{\n- const struct icsbrec_service_monitor *db_rec =\n- svc_mon->db_rec.ic_rec;\n- struct sbrec_service_monitor *key =\n- sbrec_service_monitor_index_init_row(\n- ic->sbrec_service_monitor_by_remote_type_logical_port);\n-\n- sbrec_service_monitor_index_set_remote(key, false);\n- sbrec_service_monitor_index_set_logical_port(key, db_rec->logical_port);\n-\n- const struct sbrec_service_monitor *sb_rec;\n- SBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (sb_rec, key,\n- ic->sbrec_service_monitor_by_remote_type_logical_port) {\n- if (db_rec->port == sb_rec->port &&\n- ((db_rec->type && sb_rec->type &&\n- !strcmp(db_rec->type, sb_rec->type)) ||\n- (!db_rec->type && !sb_rec->type)) &&\n- !strcmp(db_rec->ip, sb_rec->ip) &&\n- !strcmp(db_rec->src_ip, sb_rec->src_ip) &&\n- !strcmp(db_rec->protocol, sb_rec->protocol)) {\n- sbrec_service_monitor_index_destroy_row(key);\n- return sb_rec;\n- }\n- }\n-\n- sbrec_service_monitor_index_destroy_row(key);\n-\n- return NULL;\n-}\n-\n-static const struct icsbrec_service_monitor *\n-lookup_icsb_svc_rec(struct ic_input *ic,\n- const struct service_monitor_info *svc_mon)\n-{\n- const struct sbrec_service_monitor *db_rec =\n- svc_mon->db_rec.sb_rec;\n- struct icsbrec_service_monitor *key =\n- icsbrec_service_monitor_index_init_row(\n- ic->icsbrec_service_monitor_by_target_az_logical_port);\n-\n- ovs_assert(svc_mon->dst_az_name);\n- icsbrec_service_monitor_index_set_target_availability_zone(\n- key, svc_mon->dst_az_name);\n-\n- icsbrec_service_monitor_index_set_logical_port(\n- key, db_rec->logical_port);\n-\n- const struct icsbrec_service_monitor *ic_rec;\n- ICSBREC_SERVICE_MONITOR_FOR_EACH_EQUAL (ic_rec, key,\n- ic->icsbrec_service_monitor_by_target_az_logical_port) {\n- if (db_rec->port == ic_rec->port &&\n- ((db_rec->type && ic_rec->type &&\n- !strcmp(db_rec->type, ic_rec->type)) ||\n- (!db_rec->type && !ic_rec->type)) &&\n- !strcmp(db_rec->ip, ic_rec->ip) &&\n- !strcmp(db_rec->src_ip, ic_rec->src_ip) &&\n- !strcmp(db_rec->protocol, ic_rec->protocol) &&\n- !strcmp(db_rec->logical_port, ic_rec->logical_port)) {\n- icsbrec_service_monitor_index_destroy_row(key);\n- return ic_rec;\n- }\n- }\n-\n- icsbrec_service_monitor_index_destroy_row(key);\n-\n- return NULL;\n-}\n-\n-static void\n-create_service_monitor_data(struct ic_input *ic,\n- struct sync_service_monitor_data *sync_data)\n-{\n- const struct sbrec_sb_global *ic_sb =\n- sbrec_sb_global_table_first(ic->sbrec_sb_global_table);\n- const char *svc_monitor_mac = smap_get(&ic_sb->options,\n- \"svc_monitor_mac\");\n-\n- if (!svc_monitor_mac) {\n- return;\n- }\n-\n- sync_data->prpg_svc_monitor_mac = xstrdup(svc_monitor_mac);\n- create_pushed_svcs_mon(ic, &sync_data->pushed_svcs_map);\n- create_synced_svcs_mon(ic, &sync_data->synced_svcs_map);\n- create_local_ic_svcs_map(ic, &sync_data->local_ic_svcs_map);\n- create_local_sb_svcs_map(ic, &sync_data->local_sb_svcs_map);\n-}\n-\n-static void\n-destroy_service_monitor_data(struct sync_service_monitor_data *sync_data)\n-{\n- struct service_monitor_info *svc_mon;\n- HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->pushed_svcs_map) {\n- destroy_service_monitor_info(svc_mon);\n- }\n-\n- HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data->synced_svcs_map) {\n- destroy_service_monitor_info(svc_mon);\n- }\n-\n- hmap_destroy(&sync_data->pushed_svcs_map);\n- hmap_destroy(&sync_data->synced_svcs_map);\n- free(sync_data->prpg_svc_monitor_mac);\n-}\n-\n-static void\n-sync_service_monitor(struct engine_context *ctx,\n- struct ic_input *ic)\n-{\n- if (!ctx->ovnisb_idl_txn || !ctx->ovnsb_idl_txn) {\n- return;\n- }\n-\n- struct sync_service_monitor_data sync_data;\n- memset(&sync_data, 0, sizeof(sync_data));\n- hmap_init(&sync_data.pushed_svcs_map);\n- hmap_init(&sync_data.synced_svcs_map);\n- hmap_init(&sync_data.local_ic_svcs_map);\n- hmap_init(&sync_data.local_sb_svcs_map);\n-\n- create_service_monitor_data(ic, &sync_data);\n-\n- struct service_monitor_info *svc_mon;\n- HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.pushed_svcs_map) {\n- const struct sbrec_service_monitor *db_rec = svc_mon->db_rec.sb_rec;\n- const struct icsbrec_service_monitor *ic_rec =\n- lookup_icsb_svc_rec(ic, svc_mon);\n-\n- if (ic_rec) {\n- sbrec_service_monitor_set_status(db_rec, ic_rec->status);\n- } else {\n- ic_rec = icsbrec_service_monitor_insert(ctx->ovnisb_idl_txn);\n- icsbrec_service_monitor_set_type(ic_rec, db_rec->type);\n- icsbrec_service_monitor_set_ip(ic_rec, db_rec->ip);\n- icsbrec_service_monitor_set_port(ic_rec, db_rec->port);\n- icsbrec_service_monitor_set_src_ip(ic_rec, db_rec->src_ip);\n- icsbrec_service_monitor_set_src_mac(ic_rec,\n- sync_data.prpg_svc_monitor_mac);\n- icsbrec_service_monitor_set_protocol(ic_rec, db_rec->protocol);\n- icsbrec_service_monitor_set_logical_port(ic_rec,\n- db_rec->logical_port);\n- icsbrec_service_monitor_set_target_availability_zone(ic_rec,\n- svc_mon->dst_az_name);\n- icsbrec_service_monitor_set_source_availability_zone(ic_rec,\n- svc_mon->src_az_name);\n- }\n-\n- /* Always update options because they change from NB. */\n- icsbrec_service_monitor_set_options(ic_rec, &db_rec->options);\n- refresh_ic_record_cache(&sync_data.local_ic_svcs_map, ic_rec);\n- }\n-\n- HMAP_FOR_EACH_SAFE (svc_mon, hmap_node, &sync_data.synced_svcs_map) {\n- const struct icsbrec_service_monitor *db_rec =\n- svc_mon->db_rec.ic_rec;\n- const struct sbrec_service_monitor *sb_rec =\n- lookup_sb_svc_rec(ic, svc_mon);\n-\n- if (sb_rec) {\n- icsbrec_service_monitor_set_status(svc_mon->db_rec.ic_rec,\n- sb_rec->status);\n- } else {\n- sb_rec = sbrec_service_monitor_insert(ctx->ovnsb_idl_txn);\n- sbrec_service_monitor_set_type(sb_rec, db_rec->type);\n- sbrec_service_monitor_set_ip(sb_rec, db_rec->ip);\n- sbrec_service_monitor_set_port(sb_rec, db_rec->port);\n- sbrec_service_monitor_set_src_ip(sb_rec, db_rec->src_ip);\n- /* Set svc_monitor_mac from local SBDB. */\n- sbrec_service_monitor_set_src_mac(sb_rec,\n- sync_data.prpg_svc_monitor_mac);\n- sbrec_service_monitor_set_protocol(sb_rec,\n- db_rec->protocol);\n- sbrec_service_monitor_set_logical_port(sb_rec,\n- db_rec->logical_port);\n- sbrec_service_monitor_set_remote(sb_rec, false);\n- sbrec_service_monitor_set_ic_learned(sb_rec, true);\n- }\n-\n- /* Always update options since they may change via\n- * NB configuration. Also update chassis_name if\n- * the port has been reassigned to a different chassis.\n- */\n- if (svc_mon->chassis_name) {\n- sbrec_service_monitor_set_chassis_name(sb_rec,\n- svc_mon->chassis_name);\n- }\n- sbrec_service_monitor_set_options(sb_rec, &db_rec->options);\n- refresh_sb_record_cache(&sync_data.local_sb_svcs_map, sb_rec);\n- }\n-\n- /* Delete local created records that are no longer used. */\n- remove_unused_ic_records(&sync_data.local_ic_svcs_map);\n- remove_unused_sb_records(&sync_data.local_sb_svcs_map);\n-\n- destroy_service_monitor_data(&sync_data);\n-}\n-\n /*\n * This function implements a sequence number protocol that can be used by\n * the INB end user to verify that ISB is synced with all the changes that\n@@ -791,11 +359,11 @@ inc_proc_graph_dump(const char *end_node)\n }\n \n void\n-ovn_db_run(struct ic_input *input_data,\n+ovn_db_run(struct ic_input *input_data OVS_UNUSED,\n struct ic_data *ic_data OVS_UNUSED,\n- struct engine_context *eng_ctx)\n+ struct engine_context *eng_ctx OVS_UNUSED)\n {\n- sync_service_monitor(eng_ctx, input_data);\n+\n }\n \f\n static void\n@@ -1204,6 +772,7 @@ main(int argc, char *argv[])\n stopwatch_create(OVN_IC_GATEWAY_RUN_STOPWATCH_NAME, SW_MS);\n stopwatch_create(OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME, SW_MS);\n stopwatch_create(OVN_IC_TRANSIT_SWITCH_RUN_STOPWATCH_NAME, SW_MS);\n+ stopwatch_create(OVN_IC_SERVICE_MONITOR_RUN_STOPWATCH_NAME, SW_MS);\n \n /* Initialize incremental processing engine for ovn-northd */\n inc_proc_ic_init(&ovnnb_idl_loop, &ovnsb_idl_loop,\ndiff --git a/ic/ovn-ic.h b/ic/ovn-ic.h\nindex 7e057cc1b..f60e218f6 100644\n--- a/ic/ovn-ic.h\n+++ b/ic/ovn-ic.h\n@@ -46,13 +46,6 @@ struct ic_input {\n struct ovsdb_idl_index *nbrec_port_by_name;\n struct ovsdb_idl_index *sbrec_chassis_by_name;\n struct ovsdb_idl_index *sbrec_port_binding_by_name;\n- struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type;\n- struct ovsdb_idl_index *sbrec_service_monitor_by_ic_learned;\n- struct ovsdb_idl_index *sbrec_service_monitor_by_remote_type_logical_port;\n- struct ovsdb_idl_index *icnbrec_transit_switch_by_name;\n- struct ovsdb_idl_index *icsbrec_service_monitor_by_source_az;\n- struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az;\n- struct ovsdb_idl_index *icsbrec_service_monitor_by_target_az_logical_port;\n };\n \n struct ic_data {\ndiff --git a/lib/stopwatch-names.h b/lib/stopwatch-names.h\nindex c9fe2e639..ec4edf83c 100644\n--- a/lib/stopwatch-names.h\n+++ b/lib/stopwatch-names.h\n@@ -48,5 +48,6 @@\n #define OVN_IC_TRANSIT_ROUTER_RUN_STOPWATCH_NAME \"transit_router_run\"\n #define OVN_IC_PORT_BINDING_RUN_STOPWATCH_NAME \"port_binding_run\"\n #define OVN_IC_ROUTE_RUN_STOPWATCH_NAME \"route_run\"\n+#define OVN_IC_SERVICE_MONITOR_RUN_STOPWATCH_NAME \"service_monitor_run\"\n \n #endif\n", "prefixes": [ "ovs-dev", "v0", "8/9" ] }