Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1523310/?format=api
http://patchwork.ozlabs.org/api/patches/1523310/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20210901164139.2554647-3-mark.d.gray@redhat.com/", "project": { "id": 68, "url": "http://patchwork.ozlabs.org/api/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": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20210901164139.2554647-3-mark.d.gray@redhat.com>", "list_archive_url": null, "date": "2021-09-01T16:41:39", "name": "[ovs-dev,v2,2/2] northd: Split northd.c", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "96248b72e360564715a029d9b07b9856aed494f8", "submitter": { "id": 79963, "url": "http://patchwork.ozlabs.org/api/people/79963/?format=api", "name": "Mark Gray", "email": "mark.d.gray@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20210901164139.2554647-3-mark.d.gray@redhat.com/mbox/", "series": [ { "id": 260600, "url": "http://patchwork.ozlabs.org/api/series/260600/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/list/?series=260600", "date": "2021-09-01T16:41:37", "name": "northd: Split northd", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/260600/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1523310/comments/", "check": "fail", "checks": "http://patchwork.ozlabs.org/api/patches/1523310/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=Ks0IdLha;\n\tdkim-atps=neutral", "ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.138; helo=smtp1.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN>)", "smtp2.osuosl.org (amavisd-new);\n dkim=fail (1024-bit key) reason=\"fail (body has been altered)\"\n header.d=redhat.com", "relay.mimecast.com;\n auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=mark.d.gray@redhat.com" ], "Received": [ "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 4H08wX6lNCz9sXN\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 2 Sep 2021 02:42:04 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id B2DEB8295A;\n\tWed, 1 Sep 2021 16:42:02 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n\tby localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id idyktg9Bp1rV; Wed, 1 Sep 2021 16:41:58 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp1.osuosl.org (Postfix) with ESMTPS id B5BAD81DBF;\n\tWed, 1 Sep 2021 16:41:57 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 8BDECC0010;\n\tWed, 1 Sep 2021 16:41:57 +0000 (UTC)", "from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id A019BC0010\n for <dev@openvswitch.org>; Wed, 1 Sep 2021 16:41:56 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 6E56740289\n for <dev@openvswitch.org>; Wed, 1 Sep 2021 16:41:56 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n with ESMTP id xhdg6eZ8lU7k for <dev@openvswitch.org>;\n Wed, 1 Sep 2021 16:41:51 +0000 (UTC)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [216.205.24.124])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 8D966401CE\n for <dev@openvswitch.org>; Wed, 1 Sep 2021 16:41:51 +0000 (UTC)", "from mail-wr1-f72.google.com (mail-wr1-f72.google.com\n [209.85.221.72]) (Using TLS) by relay.mimecast.com with ESMTP id\n us-mta-337-t-keNrtGM6aDDtygvbw78w-1; Wed, 01 Sep 2021 12:41:49 -0400", "by mail-wr1-f72.google.com with SMTP id\n d10-20020adffbca000000b00157bc86d94eso84651wrs.20\n for <dev@openvswitch.org>; Wed, 01 Sep 2021 09:41:49 -0700 (PDT)", "from wsfd-netdev91.ntdv.lab.eng.bos.redhat.com\n (nat-pool-bos-t.redhat.com. [66.187.233.206])\n by smtp.gmail.com with ESMTPSA id d28sm4093wrc.4.2021.09.01.09.41.43\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 01 Sep 2021 09:41:44 -0700 (PDT)" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.8.0", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1630514510;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=/eoQGazqgycmY398VH2IxmYWyZY1T3HKpfd/e/JmBn4=;\n b=Ks0IdLham4gqEsrk0sjVRbWsu992ovFshP+M0NCC57JpzJvDYMF5khdsfErpzD7ohQgOsa\n PVPf7OBYBX2yErNCXAP4g7TomcH9u/YbNLH8G11ttoqQXe1YH+1SE8A3N+IItbYXdndPfQ\n O7azq82lto1+Ayx8TPLOkPJ+WYD4Yo0=", "X-MC-Unique": "t-keNrtGM6aDDtygvbw78w-1", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=IJmJTqa5cqWfqPqAYW/7ilQOHwnGgcRzkKcnPxuSCIY=;\n b=TxziTc8guUtCVMThJbuwt7OKC3z3/vpF+M6umuhuur3MZubyCrGbYR85oRKZoonczm\n swZYEWEhZG8mrUcjmOUpucrM+rAN15kPBXyG3/UWdgpx5LH354jY59OiHgNs/yv+QsnM\n bxv1GFULgvoXTp4ND9UhFGz2V/C4Wh9wRhKNyosyUsAY8an4cbdEJ81N7OHkEfkLS9p+\n wu1lKE7oe31RHAW4tbGU0OSG+StOs1CexTBJPthrZ0sD+Ovz+3JDmoBcVZI/Byu/UoRS\n JY83sigRjPKzCIzIYYIc9IrjA57UUG5L2U0/IwccV2YuxXsTWq/tAL77uDSJMeVd7jnY\n W+9g==", "X-Gm-Message-State": "AOAM533j2Lh3GT3hC7FjiZfbPsibXOKXppd/z20AojtjIy2dgXDX4u64\n zm7ojX7dzROqfOIO6l/twqQuSKad3C5fmez5iC4+VPaPhHowN5iKRvFy8+RKz7cCRiScFArvqB2\n lt4HY7WS+APREC1Er+/SZEOR01vq9cFNo7BMP6RO1K7zmVXk2JLTT8EtGLHNqUN0XnSUN", "X-Received": [ "by 2002:a05:600c:294:: with SMTP id\n 20mr454703wmk.180.1630514506420;\n Wed, 01 Sep 2021 09:41:46 -0700 (PDT)", "by 2002:a05:600c:294:: with SMTP id\n 20mr454564wmk.180.1630514505233;\n Wed, 01 Sep 2021 09:41:45 -0700 (PDT)" ], "X-Google-Smtp-Source": "\n ABdhPJxYTuwd7icDDXZy3P8w9FHibDIH5wrpTkIXRLh901wsWKUAX2Uv/q82J/XGwlUf9Y81B2DnUA==", "From": "Mark Gray <mark.d.gray@redhat.com>", "To": "dev@openvswitch.org", "Date": "Wed, 1 Sep 2021 12:41:39 -0400", "Message-Id": "<20210901164139.2554647-3-mark.d.gray@redhat.com>", "X-Mailer": "git-send-email 2.27.0", "In-Reply-To": "<20210901164139.2554647-1-mark.d.gray@redhat.com>", "References": "<20210901164139.2554647-1-mark.d.gray@redhat.com>", "MIME-Version": "1.0", "X-Mimecast-Spam-Score": "0", "X-Mimecast-Originator": "redhat.com", "Cc": "numans@redhat.com", "Subject": "[ovs-dev] [PATCH ovn v2 2/2] northd: Split northd.c", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.15", "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>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "ovs-dev-bounces@openvswitch.org", "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>" }, "content": "This commit splits northd into two parts. One part, ovn-northd.c,\nis responsible for the `ovn-northd` application, and the other is\nresponsible for northd processing.\n\nThis takes one step towards a more modular northd code base.\n\nSigned-off-by: Mark Gray <mark.d.gray@redhat.com>\n---\n northd/automake.mk | 2 +\n northd/northd.c | 1108 +------------------------------------------\n northd/northd.h | 42 ++\n northd/ovn-northd.c | 1100 ++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 1161 insertions(+), 1091 deletions(-)\n create mode 100644 northd/northd.h\n create mode 100644 northd/ovn-northd.c", "diff": "diff --git a/northd/automake.mk b/northd/automake.mk\nindex 306b533a486b..35ad8c09d9ba 100644\n--- a/northd/automake.mk\n+++ b/northd/automake.mk\n@@ -2,6 +2,8 @@\n bin_PROGRAMS += northd/ovn-northd\n northd_ovn_northd_SOURCES = \\\n \tnorthd/northd.c \\\n+\tnorthd/northd.h \\\n+\tnorthd/ovn-northd.c \\\n \tnorthd/ipam.c \\\n \tnorthd/ipam.h\n northd_ovn_northd_LDADD = \\\ndiff --git a/northd/northd.c b/northd/northd.c\nindex e9a8492880e4..262c7755e718 100644\n--- a/northd/northd.c\n+++ b/northd/northd.c\n@@ -14,17 +14,13 @@\n \n #include <config.h>\n \n-#include <getopt.h>\n #include <stdlib.h>\n #include <stdio.h>\n \n #include \"bitmap.h\"\n-#include \"command-line.h\"\n-#include \"daemon.h\"\n #include \"dirs.h\"\n #include \"ipam.h\"\n #include \"openvswitch/dynamic-string.h\"\n-#include \"fatal-signal.h\"\n #include \"hash.h\"\n #include \"hmapx.h\"\n #include \"openvswitch/hmap.h\"\n@@ -40,13 +36,12 @@\n #include \"lib/ovn-util.h\"\n #include \"lib/lb.h\"\n #include \"memory.h\"\n-#include \"ovs-numa.h\"\n+#include \"northd.h\"\n #include \"lib/ovn-parallel-hmap.h\"\n #include \"ovn/actions.h\"\n #include \"ovn/features.h\"\n #include \"ovn/logical-fields.h\"\n #include \"packets.h\"\n-#include \"openvswitch/poll-loop.h\"\n #include \"simap.h\"\n #include \"smap.h\"\n #include \"sset.h\"\n@@ -54,41 +49,12 @@\n #include \"stopwatch.h\"\n #include \"lib/stopwatch-names.h\"\n #include \"stream.h\"\n-#include \"stream-ssl.h\"\n #include \"timeval.h\"\n-#include \"unixctl.h\"\n #include \"util.h\"\n #include \"uuid.h\"\n #include \"openvswitch/vlog.h\"\n \n-VLOG_DEFINE_THIS_MODULE(ovn_northd);\n-\n-static unixctl_cb_func ovn_northd_exit;\n-static unixctl_cb_func ovn_northd_pause;\n-static unixctl_cb_func ovn_northd_resume;\n-static unixctl_cb_func ovn_northd_is_paused;\n-static unixctl_cb_func ovn_northd_status;\n-static unixctl_cb_func cluster_state_reset_cmd;\n-\n-struct northd_context {\n- struct ovsdb_idl *ovnnb_idl;\n- struct ovsdb_idl *ovnsb_idl;\n- struct ovsdb_idl_txn *ovnnb_txn;\n- struct ovsdb_idl_txn *ovnsb_txn;\n- struct ovsdb_idl_index *sbrec_chassis_by_name;\n- struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name;\n- struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp;\n- struct ovsdb_idl_index *sbrec_ip_mcast_by_dp;\n-};\n-\n-struct northd_state {\n- bool had_lock;\n- bool paused;\n-};\n-\n-static const char *ovnnb_db;\n-static const char *ovnsb_db;\n-static const char *unixctl_path;\n+VLOG_DEFINE_THIS_MODULE(northd);\n \n static bool controller_event_en;\n \n@@ -110,12 +76,6 @@ static bool use_ct_inv_match = true;\n #define DEFAULT_PROBE_INTERVAL_MSEC 5000\n static int northd_probe_interval_nb = 0;\n static int northd_probe_interval_sb = 0;\n-\n-/* SSL options */\n-static const char *ssl_private_key_file;\n-static const char *ssl_certificate_file;\n-static const char *ssl_ca_cert_file;\n-\n #define MAX_OVN_TAGS 4096\n \f\n /* Pipeline stages. */\n@@ -403,29 +363,6 @@ ovn_stage_to_datapath_type(enum ovn_stage stage)\n }\n }\n \f\n-static void\n-usage(void)\n-{\n- printf(\"\\\n-%s: OVN northbound management daemon\\n\\\n-usage: %s [OPTIONS]\\n\\\n-\\n\\\n-Options:\\n\\\n- --ovnnb-db=DATABASE connect to ovn-nb database at DATABASE\\n\\\n- (default: %s)\\n\\\n- --ovnsb-db=DATABASE connect to ovn-sb database at DATABASE\\n\\\n- (default: %s)\\n\\\n- --dry-run start in paused state (do not commit db changes)\\n\\\n- --unixctl=SOCKET override default control socket name\\n\\\n- -h, --help display this help message\\n\\\n- -o, --options list available options\\n\\\n- -V, --version display version information\\n\\\n-\", program_name, program_name, default_nb_db(), default_sb_db());\n- daemon_usage();\n- vlog_usage();\n- stream_usage(\"database\", true, true, false);\n-}\n-\f\n struct ovn_chassis_qdisc_queues {\n struct hmap_node key_node;\n uint32_t queue_id;\n@@ -4358,9 +4295,9 @@ ovn_lflow_init(struct ovn_lflow *lflow, struct ovn_datapath *od,\n /* If this option is 'true' northd will combine logical flows that differ by\n * logical datapath only by creating a datapath group. */\n static bool use_logical_dp_groups = false;\n-static bool use_parallel_build = true;\n+static bool use_parallel_build = false;\n \n-static struct hashrow_locks lflow_locks;\n+static struct hashrow_locks *lflow_locks;\n \n /* Adds a row with the specified contents to the Logical_Flow table.\n * Version to use when locking is required.\n@@ -4454,10 +4391,10 @@ ovn_dp_group_add_with_reference(struct ovn_lflow *lflow_ref,\n return false;\n }\n \n- if (use_parallel_build) {\n- lock_hash_row(&lflow_locks, hash);\n+ if (use_logical_dp_groups && use_parallel_build) {\n+ lock_hash_row(lflow_locks, hash);\n hmapx_add(&lflow_ref->od_group, od);\n- unlock_hash_row(&lflow_locks, hash);\n+ unlock_hash_row(lflow_locks, hash);\n } else {\n hmapx_add(&lflow_ref->od_group, od);\n }\n@@ -13171,7 +13108,7 @@ build_lflows(struct northd_context *ctx, struct hmap *datapaths,\n \n fast_hmap_size_for(&lflows, max_seen_lflow_size);\n if (use_parallel_build) {\n- update_hashrow_locks(&lflows, &lflow_locks);\n+ update_hashrow_locks(&lflows, lflow_locks);\n }\n build_lswitch_and_lrouter_flows(datapaths, ports,\n port_groups, &lflows, mcgroups,\n@@ -14239,8 +14176,11 @@ ovnnb_db_run(struct northd_context *ctx,\n smap_destroy(&options);\n \n /* Update the probe interval. */\n- northd_probe_interval_nb = get_probe_interval(ovnnb_db, nb);\n- northd_probe_interval_sb = get_probe_interval(ovnsb_db, nb);\n+ northd_probe_interval_nb = get_probe_interval(ctx->ovnnb_db, nb);\n+ northd_probe_interval_sb = get_probe_interval(ctx->ovnsb_db, nb);\n+\n+ ovsdb_idl_set_probe_interval(ctx->ovnnb_idl, northd_probe_interval_nb);\n+ ovsdb_idl_set_probe_interval(ctx->ovnsb_idl, northd_probe_interval_sb);\n \n use_parallel_build =\n (smap_get_bool(&nb->options, \"use_parallel_build\", false) &&\n@@ -14532,373 +14472,6 @@ handle_port_binding_changes(struct northd_context *ctx, struct hmap *ports,\n }\n }\n \n-static struct gen_opts_map supported_dhcp_opts[] = {\n- OFFERIP,\n- DHCP_OPT_NETMASK,\n- DHCP_OPT_ROUTER,\n- DHCP_OPT_DNS_SERVER,\n- DHCP_OPT_LOG_SERVER,\n- DHCP_OPT_LPR_SERVER,\n- DHCP_OPT_SWAP_SERVER,\n- DHCP_OPT_POLICY_FILTER,\n- DHCP_OPT_ROUTER_SOLICITATION,\n- DHCP_OPT_NIS_SERVER,\n- DHCP_OPT_NTP_SERVER,\n- DHCP_OPT_SERVER_ID,\n- DHCP_OPT_TFTP_SERVER,\n- DHCP_OPT_CLASSLESS_STATIC_ROUTE,\n- DHCP_OPT_MS_CLASSLESS_STATIC_ROUTE,\n- DHCP_OPT_IP_FORWARD_ENABLE,\n- DHCP_OPT_ROUTER_DISCOVERY,\n- DHCP_OPT_ETHERNET_ENCAP,\n- DHCP_OPT_DEFAULT_TTL,\n- DHCP_OPT_TCP_TTL,\n- DHCP_OPT_MTU,\n- DHCP_OPT_LEASE_TIME,\n- DHCP_OPT_T1,\n- DHCP_OPT_T2,\n- DHCP_OPT_WPAD,\n- DHCP_OPT_BOOTFILE,\n- DHCP_OPT_PATH_PREFIX,\n- DHCP_OPT_TFTP_SERVER_ADDRESS,\n- DHCP_OPT_HOSTNAME,\n- DHCP_OPT_DOMAIN_NAME,\n- DHCP_OPT_ARP_CACHE_TIMEOUT,\n- DHCP_OPT_TCP_KEEPALIVE_INTERVAL,\n- DHCP_OPT_DOMAIN_SEARCH_LIST,\n- DHCP_OPT_BOOTFILE_ALT,\n- DHCP_OPT_BROADCAST_ADDRESS,\n- DHCP_OPT_NETBIOS_NAME_SERVER,\n- DHCP_OPT_NETBIOS_NODE_TYPE,\n-};\n-\n-static struct gen_opts_map supported_dhcpv6_opts[] = {\n- DHCPV6_OPT_IA_ADDR,\n- DHCPV6_OPT_SERVER_ID,\n- DHCPV6_OPT_DOMAIN_SEARCH,\n- DHCPV6_OPT_DNS_SERVER\n-};\n-\n-static void\n-check_and_add_supported_dhcp_opts_to_sb_db(struct northd_context *ctx)\n-{\n- struct hmap dhcp_opts_to_add = HMAP_INITIALIZER(&dhcp_opts_to_add);\n- for (size_t i = 0; (i < sizeof(supported_dhcp_opts) /\n- sizeof(supported_dhcp_opts[0])); i++) {\n- hmap_insert(&dhcp_opts_to_add, &supported_dhcp_opts[i].hmap_node,\n- dhcp_opt_hash(supported_dhcp_opts[i].name));\n- }\n-\n- const struct sbrec_dhcp_options *opt_row, *opt_row_next;\n- SBREC_DHCP_OPTIONS_FOR_EACH_SAFE(opt_row, opt_row_next, ctx->ovnsb_idl) {\n- struct gen_opts_map *dhcp_opt =\n- dhcp_opts_find(&dhcp_opts_to_add, opt_row->name);\n- if (dhcp_opt) {\n- if (!strcmp(dhcp_opt->type, opt_row->type) &&\n- dhcp_opt->code == opt_row->code) {\n- hmap_remove(&dhcp_opts_to_add, &dhcp_opt->hmap_node);\n- } else {\n- sbrec_dhcp_options_delete(opt_row);\n- }\n- } else {\n- sbrec_dhcp_options_delete(opt_row);\n- }\n- }\n-\n- struct gen_opts_map *opt;\n- HMAP_FOR_EACH (opt, hmap_node, &dhcp_opts_to_add) {\n- struct sbrec_dhcp_options *sbrec_dhcp_option =\n- sbrec_dhcp_options_insert(ctx->ovnsb_txn);\n- sbrec_dhcp_options_set_name(sbrec_dhcp_option, opt->name);\n- sbrec_dhcp_options_set_code(sbrec_dhcp_option, opt->code);\n- sbrec_dhcp_options_set_type(sbrec_dhcp_option, opt->type);\n- }\n-\n- hmap_destroy(&dhcp_opts_to_add);\n-}\n-\n-static void\n-check_and_add_supported_dhcpv6_opts_to_sb_db(struct northd_context *ctx)\n-{\n- struct hmap dhcpv6_opts_to_add = HMAP_INITIALIZER(&dhcpv6_opts_to_add);\n- for (size_t i = 0; (i < sizeof(supported_dhcpv6_opts) /\n- sizeof(supported_dhcpv6_opts[0])); i++) {\n- hmap_insert(&dhcpv6_opts_to_add, &supported_dhcpv6_opts[i].hmap_node,\n- dhcp_opt_hash(supported_dhcpv6_opts[i].name));\n- }\n-\n- const struct sbrec_dhcpv6_options *opt_row, *opt_row_next;\n- SBREC_DHCPV6_OPTIONS_FOR_EACH_SAFE(opt_row, opt_row_next, ctx->ovnsb_idl) {\n- struct gen_opts_map *dhcp_opt =\n- dhcp_opts_find(&dhcpv6_opts_to_add, opt_row->name);\n- if (dhcp_opt) {\n- hmap_remove(&dhcpv6_opts_to_add, &dhcp_opt->hmap_node);\n- } else {\n- sbrec_dhcpv6_options_delete(opt_row);\n- }\n- }\n-\n- struct gen_opts_map *opt;\n- HMAP_FOR_EACH(opt, hmap_node, &dhcpv6_opts_to_add) {\n- struct sbrec_dhcpv6_options *sbrec_dhcpv6_option =\n- sbrec_dhcpv6_options_insert(ctx->ovnsb_txn);\n- sbrec_dhcpv6_options_set_name(sbrec_dhcpv6_option, opt->name);\n- sbrec_dhcpv6_options_set_code(sbrec_dhcpv6_option, opt->code);\n- sbrec_dhcpv6_options_set_type(sbrec_dhcpv6_option, opt->type);\n- }\n-\n- hmap_destroy(&dhcpv6_opts_to_add);\n-}\n-\n-static const char *rbac_chassis_auth[] =\n- {\"name\"};\n-static const char *rbac_chassis_update[] =\n- {\"nb_cfg\", \"external_ids\", \"encaps\", \"vtep_logical_switches\",\n- \"other_config\", \"transport_zones\"};\n-\n-static const char *rbac_chassis_private_auth[] =\n- {\"name\"};\n-static const char *rbac_chassis_private_update[] =\n- {\"nb_cfg\", \"nb_cfg_timestamp\", \"chassis\", \"external_ids\"};\n-\n-static const char *rbac_encap_auth[] =\n- {\"chassis_name\"};\n-static const char *rbac_encap_update[] =\n- {\"type\", \"options\", \"ip\"};\n-\n-static const char *rbac_controller_event_auth[] =\n- {\"\"};\n-static const char *rbac_controller_event_update[] =\n- {\"chassis\", \"event_info\", \"event_type\", \"seq_num\"};\n-\n-\n-static const char *rbac_fdb_auth[] =\n- {\"\"};\n-static const char *rbac_fdb_update[] =\n- {\"dp_key\", \"mac\", \"port_key\"};\n-\n-static const char *rbac_port_binding_auth[] =\n- {\"\"};\n-static const char *rbac_port_binding_update[] =\n- {\"chassis\", \"encap\", \"up\", \"virtual_parent\"};\n-\n-static const char *rbac_mac_binding_auth[] =\n- {\"\"};\n-static const char *rbac_mac_binding_update[] =\n- {\"logical_port\", \"ip\", \"mac\", \"datapath\"};\n-\n-static const char *rbac_svc_monitor_auth[] =\n- {\"\"};\n-static const char *rbac_svc_monitor_auth_update[] =\n- {\"status\"};\n-static const char *rbac_igmp_group_auth[] =\n- {\"\"};\n-static const char *rbac_igmp_group_update[] =\n- {\"address\", \"chassis\", \"datapath\", \"ports\"};\n-\n-static struct rbac_perm_cfg {\n- const char *table;\n- const char **auth;\n- int n_auth;\n- bool insdel;\n- const char **update;\n- int n_update;\n- const struct sbrec_rbac_permission *row;\n-} rbac_perm_cfg[] = {\n- {\n- .table = \"Chassis\",\n- .auth = rbac_chassis_auth,\n- .n_auth = ARRAY_SIZE(rbac_chassis_auth),\n- .insdel = true,\n- .update = rbac_chassis_update,\n- .n_update = ARRAY_SIZE(rbac_chassis_update),\n- .row = NULL\n- },{\n- .table = \"Chassis_Private\",\n- .auth = rbac_chassis_private_auth,\n- .n_auth = ARRAY_SIZE(rbac_chassis_private_auth),\n- .insdel = true,\n- .update = rbac_chassis_private_update,\n- .n_update = ARRAY_SIZE(rbac_chassis_private_update),\n- .row = NULL\n- },{\n- .table = \"Controller_Event\",\n- .auth = rbac_controller_event_auth,\n- .n_auth = ARRAY_SIZE(rbac_controller_event_auth),\n- .insdel = true,\n- .update = rbac_controller_event_update,\n- .n_update = ARRAY_SIZE(rbac_controller_event_update),\n- .row = NULL\n- },{\n- .table = \"Encap\",\n- .auth = rbac_encap_auth,\n- .n_auth = ARRAY_SIZE(rbac_encap_auth),\n- .insdel = true,\n- .update = rbac_encap_update,\n- .n_update = ARRAY_SIZE(rbac_encap_update),\n- .row = NULL\n- },{\n- .table = \"FDB\",\n- .auth = rbac_fdb_auth,\n- .n_auth = ARRAY_SIZE(rbac_fdb_auth),\n- .insdel = true,\n- .update = rbac_fdb_update,\n- .n_update = ARRAY_SIZE(rbac_fdb_update),\n- .row = NULL\n- },{\n- .table = \"Port_Binding\",\n- .auth = rbac_port_binding_auth,\n- .n_auth = ARRAY_SIZE(rbac_port_binding_auth),\n- .insdel = false,\n- .update = rbac_port_binding_update,\n- .n_update = ARRAY_SIZE(rbac_port_binding_update),\n- .row = NULL\n- },{\n- .table = \"MAC_Binding\",\n- .auth = rbac_mac_binding_auth,\n- .n_auth = ARRAY_SIZE(rbac_mac_binding_auth),\n- .insdel = true,\n- .update = rbac_mac_binding_update,\n- .n_update = ARRAY_SIZE(rbac_mac_binding_update),\n- .row = NULL\n- },{\n- .table = \"Service_Monitor\",\n- .auth = rbac_svc_monitor_auth,\n- .n_auth = ARRAY_SIZE(rbac_svc_monitor_auth),\n- .insdel = false,\n- .update = rbac_svc_monitor_auth_update,\n- .n_update = ARRAY_SIZE(rbac_svc_monitor_auth_update),\n- .row = NULL\n- },{\n- .table = \"IGMP_Group\",\n- .auth = rbac_igmp_group_auth,\n- .n_auth = ARRAY_SIZE(rbac_igmp_group_auth),\n- .insdel = true,\n- .update = rbac_igmp_group_update,\n- .n_update = ARRAY_SIZE(rbac_igmp_group_update),\n- .row = NULL\n- },{\n- .table = NULL,\n- .auth = NULL,\n- .n_auth = 0,\n- .insdel = false,\n- .update = NULL,\n- .n_update = 0,\n- .row = NULL\n- }\n-};\n-\n-static bool\n-ovn_rbac_validate_perm(const struct sbrec_rbac_permission *perm)\n-{\n- struct rbac_perm_cfg *pcfg;\n- int i, j, n_found;\n-\n- for (pcfg = rbac_perm_cfg; pcfg->table; pcfg++) {\n- if (!strcmp(perm->table, pcfg->table)) {\n- break;\n- }\n- }\n- if (!pcfg->table) {\n- return false;\n- }\n- if (perm->n_authorization != pcfg->n_auth ||\n- perm->n_update != pcfg->n_update) {\n- return false;\n- }\n- if (perm->insert_delete != pcfg->insdel) {\n- return false;\n- }\n- /* verify perm->authorization vs. pcfg->auth */\n- n_found = 0;\n- for (i = 0; i < pcfg->n_auth; i++) {\n- for (j = 0; j < perm->n_authorization; j++) {\n- if (!strcmp(pcfg->auth[i], perm->authorization[j])) {\n- n_found++;\n- break;\n- }\n- }\n- }\n- if (n_found != pcfg->n_auth) {\n- return false;\n- }\n-\n- /* verify perm->update vs. pcfg->update */\n- n_found = 0;\n- for (i = 0; i < pcfg->n_update; i++) {\n- for (j = 0; j < perm->n_update; j++) {\n- if (!strcmp(pcfg->update[i], perm->update[j])) {\n- n_found++;\n- break;\n- }\n- }\n- }\n- if (n_found != pcfg->n_update) {\n- return false;\n- }\n-\n- /* Success, db state matches expected state */\n- pcfg->row = perm;\n- return true;\n-}\n-\n-static void\n-ovn_rbac_create_perm(struct rbac_perm_cfg *pcfg,\n- struct northd_context *ctx,\n- const struct sbrec_rbac_role *rbac_role)\n-{\n- struct sbrec_rbac_permission *rbac_perm;\n-\n- rbac_perm = sbrec_rbac_permission_insert(ctx->ovnsb_txn);\n- sbrec_rbac_permission_set_table(rbac_perm, pcfg->table);\n- sbrec_rbac_permission_set_authorization(rbac_perm,\n- pcfg->auth,\n- pcfg->n_auth);\n- sbrec_rbac_permission_set_insert_delete(rbac_perm, pcfg->insdel);\n- sbrec_rbac_permission_set_update(rbac_perm,\n- pcfg->update,\n- pcfg->n_update);\n- sbrec_rbac_role_update_permissions_setkey(rbac_role, pcfg->table,\n- rbac_perm);\n-}\n-\n-static void\n-check_and_update_rbac(struct northd_context *ctx)\n-{\n- const struct sbrec_rbac_role *rbac_role = NULL;\n- const struct sbrec_rbac_permission *perm_row, *perm_next;\n- const struct sbrec_rbac_role *role_row, *role_row_next;\n- struct rbac_perm_cfg *pcfg;\n-\n- for (pcfg = rbac_perm_cfg; pcfg->table; pcfg++) {\n- pcfg->row = NULL;\n- }\n-\n- SBREC_RBAC_PERMISSION_FOR_EACH_SAFE (perm_row, perm_next, ctx->ovnsb_idl) {\n- if (!ovn_rbac_validate_perm(perm_row)) {\n- sbrec_rbac_permission_delete(perm_row);\n- }\n- }\n- SBREC_RBAC_ROLE_FOR_EACH_SAFE (role_row, role_row_next, ctx->ovnsb_idl) {\n- if (strcmp(role_row->name, \"ovn-controller\")) {\n- sbrec_rbac_role_delete(role_row);\n- } else {\n- rbac_role = role_row;\n- }\n- }\n-\n- if (!rbac_role) {\n- rbac_role = sbrec_rbac_role_insert(ctx->ovnsb_txn);\n- sbrec_rbac_role_set_name(rbac_role, \"ovn-controller\");\n- }\n-\n- for (pcfg = rbac_perm_cfg; pcfg->table; pcfg++) {\n- if (!pcfg->row) {\n- ovn_rbac_create_perm(pcfg, ctx, rbac_role);\n- }\n- }\n-}\n-\n /* Updates the sb_cfg and hv_cfg columns in the northbound NB_Global table. */\n static void\n update_northbound_cfg(struct northd_context *ctx,\n@@ -14971,7 +14544,7 @@ ovnsb_db_run(struct northd_context *ctx,\n shash_destroy(&ha_ref_chassis_map);\n }\n \n-static void\n+void\n ovn_db_run(struct northd_context *ctx,\n struct ovsdb_idl_index *sbrec_chassis_by_name,\n struct ovsdb_idl_loop *ovnsb_idl_loop,\n@@ -14982,6 +14555,8 @@ ovn_db_run(struct northd_context *ctx,\n ovs_list_init(&lr_list);\n hmap_init(&datapaths);\n hmap_init(&ports);\n+ use_parallel_build = ctx->use_parallel_build;\n+ lflow_locks = ctx->lflow_locks;\n \n int64_t start_time = time_wall_msec();\n stopwatch_start(OVNNB_DB_RUN_STOPWATCH_NAME, time_msec());\n@@ -14994,653 +14569,4 @@ ovn_db_run(struct northd_context *ctx,\n stopwatch_stop(OVNSB_DB_RUN_STOPWATCH_NAME, time_msec());\n destroy_datapaths_and_ports(&datapaths, &ports, &lr_list);\n }\n-\f\n-static void\n-parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED,\n- bool *paused)\n-{\n- enum {\n- OVN_DAEMON_OPTION_ENUMS,\n- VLOG_OPTION_ENUMS,\n- SSL_OPTION_ENUMS,\n- OPT_DRY_RUN,\n- OPT_DUMMY_NUMA,\n- };\n- static const struct option long_options[] = {\n- {\"ovnsb-db\", required_argument, NULL, 'd'},\n- {\"ovnnb-db\", required_argument, NULL, 'D'},\n- {\"unixctl\", required_argument, NULL, 'u'},\n- {\"help\", no_argument, NULL, 'h'},\n- {\"options\", no_argument, NULL, 'o'},\n- {\"version\", no_argument, NULL, 'V'},\n- {\"dry-run\", no_argument, NULL, OPT_DRY_RUN},\n- {\"dummy-numa\", required_argument, NULL, OPT_DUMMY_NUMA},\n- OVN_DAEMON_LONG_OPTIONS,\n- VLOG_LONG_OPTIONS,\n- STREAM_SSL_LONG_OPTIONS,\n- {NULL, 0, NULL, 0},\n- };\n- char *short_options = ovs_cmdl_long_options_to_short_options(long_options);\n-\n- for (;;) {\n- int c;\n-\n- c = getopt_long(argc, argv, short_options, long_options, NULL);\n- if (c == -1) {\n- break;\n- }\n-\n- switch (c) {\n- OVN_DAEMON_OPTION_HANDLERS;\n- VLOG_OPTION_HANDLERS;\n-\n- case 'p':\n- ssl_private_key_file = optarg;\n- break;\n-\n- case 'c':\n- ssl_certificate_file = optarg;\n- break;\n-\n- case 'C':\n- ssl_ca_cert_file = optarg;\n- break;\n-\n- case 'd':\n- ovnsb_db = optarg;\n- break;\n-\n- case 'D':\n- ovnnb_db = optarg;\n- break;\n-\n- case 'u':\n- unixctl_path = optarg;\n- break;\n-\n- case 'h':\n- usage();\n- exit(EXIT_SUCCESS);\n-\n- case 'o':\n- ovs_cmdl_print_options(long_options);\n- exit(EXIT_SUCCESS);\n-\n- case 'V':\n- ovn_print_version(0, 0);\n- exit(EXIT_SUCCESS);\n-\n- case OPT_DUMMY_NUMA:\n- ovs_numa_set_dummy(optarg);\n- break;\n-\n- case OPT_DRY_RUN:\n- *paused = true;\n- break;\n-\n- default:\n- break;\n- }\n- }\n-\n- if (!ovnsb_db || !ovnsb_db[0]) {\n- ovnsb_db = default_sb_db();\n- }\n-\n- if (!ovnnb_db || !ovnnb_db[0]) {\n- ovnnb_db = default_nb_db();\n- }\n-\n- free(short_options);\n-}\n-\n-static void\n-add_column_noalert(struct ovsdb_idl *idl,\n- const struct ovsdb_idl_column *column)\n-{\n- ovsdb_idl_add_column(idl, column);\n- ovsdb_idl_omit_alert(idl, column);\n-}\n-\n-static void\n-update_ssl_config(void)\n-{\n- if (ssl_private_key_file && ssl_certificate_file) {\n- stream_ssl_set_key_and_cert(ssl_private_key_file,\n- ssl_certificate_file);\n- }\n- if (ssl_ca_cert_file) {\n- stream_ssl_set_ca_cert_file(ssl_ca_cert_file, false);\n- }\n-}\n-\n-int\n-main(int argc, char *argv[])\n-{\n- int res = EXIT_SUCCESS;\n- struct unixctl_server *unixctl;\n- int retval;\n- bool exiting;\n- struct northd_state state = {\n- .had_lock = false,\n- .paused = false\n- };\n-\n- fatal_ignore_sigpipe();\n- ovs_cmdl_proctitle_init(argc, argv);\n- ovn_set_program_name(argv[0]);\n- service_start(&argc, &argv);\n- parse_options(argc, argv, &state.paused);\n-\n- daemonize_start(false);\n-\n- char *abs_unixctl_path = get_abs_unix_ctl_path(unixctl_path);\n- retval = unixctl_server_create(abs_unixctl_path, &unixctl);\n- free(abs_unixctl_path);\n-\n- if (retval) {\n- exit(EXIT_FAILURE);\n- }\n- unixctl_command_register(\"exit\", \"\", 0, 0, ovn_northd_exit, &exiting);\n- unixctl_command_register(\"pause\", \"\", 0, 0, ovn_northd_pause, &state);\n- unixctl_command_register(\"resume\", \"\", 0, 0, ovn_northd_resume, &state);\n- unixctl_command_register(\"is-paused\", \"\", 0, 0, ovn_northd_is_paused,\n- &state);\n- unixctl_command_register(\"status\", \"\", 0, 0, ovn_northd_status, &state);\n-\n- bool reset_ovnsb_idl_min_index = false;\n- unixctl_command_register(\"sb-cluster-state-reset\", \"\", 0, 0,\n- cluster_state_reset_cmd,\n- &reset_ovnsb_idl_min_index);\n-\n- bool reset_ovnnb_idl_min_index = false;\n- unixctl_command_register(\"nb-cluster-state-reset\", \"\", 0, 0,\n- cluster_state_reset_cmd,\n- &reset_ovnnb_idl_min_index);\n-\n- daemonize_complete();\n-\n- init_hash_row_locks(&lflow_locks);\n- use_parallel_build = can_parallelize_hashes(false);\n-\n- /* We want to detect (almost) all changes to the ovn-nb db. */\n- struct ovsdb_idl_loop ovnnb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(\n- ovsdb_idl_create(ovnnb_db, &nbrec_idl_class, true, true));\n- ovsdb_idl_omit_alert(ovnnb_idl_loop.idl,\n- &nbrec_nb_global_col_nb_cfg_timestamp);\n- ovsdb_idl_omit_alert(ovnnb_idl_loop.idl, &nbrec_nb_global_col_sb_cfg);\n- ovsdb_idl_omit_alert(ovnnb_idl_loop.idl,\n- &nbrec_nb_global_col_sb_cfg_timestamp);\n- ovsdb_idl_omit_alert(ovnnb_idl_loop.idl, &nbrec_nb_global_col_hv_cfg);\n- ovsdb_idl_omit_alert(ovnnb_idl_loop.idl,\n- &nbrec_nb_global_col_hv_cfg_timestamp);\n-\n- unixctl_command_register(\"nb-connection-status\", \"\", 0, 0,\n- ovn_conn_show, ovnnb_idl_loop.idl);\n-\n- /* We want to detect only selected changes to the ovn-sb db. */\n- struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(\n- ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, false, true));\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_sb_global);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_nb_cfg);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_options);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_ipsec);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_logical_flow);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_logical_flow_col_logical_datapath);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_logical_flow_col_logical_dp_group);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_pipeline);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_table_id);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_priority);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_match);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_actions);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_logical_flow_col_controller_meter);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_logical_flow_col_external_ids);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl,\n- &sbrec_table_logical_dp_group);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_logical_dp_group_col_datapaths);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_multicast_group);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_multicast_group_col_datapath);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_multicast_group_col_tunnel_key);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_multicast_group_col_name);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_multicast_group_col_ports);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_datapath_binding);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_datapath_binding_col_tunnel_key);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_datapath_binding_col_load_balancers);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_datapath_binding_col_external_ids);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_port_binding);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_datapath);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_logical_port);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_tunnel_key);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_parent_port);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_tag);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_type);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_options);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_mac);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_nat_addresses);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_chassis);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_gateway_chassis);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_ha_chassis_group);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_virtual_parent);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_up);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_gateway_chassis_col_chassis);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_gateway_chassis_col_name);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_gateway_chassis_col_priority);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_gateway_chassis_col_external_ids);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_gateway_chassis_col_options);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_port_binding_col_external_ids);\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_mac_binding);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_datapath);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_ip);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_mac);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_mac_binding_col_logical_port);\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dhcp_options);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_code);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_type);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_name);\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dhcpv6_options);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_code);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_type);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_name);\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_address_set);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_address_set_col_name);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_address_set_col_addresses);\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_port_group);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_group_col_name);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_group_col_ports);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dns);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_datapaths);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_records);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_external_ids);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_rbac_role);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_rbac_role_col_name);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_rbac_role_col_permissions);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_rbac_permission);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_rbac_permission_col_table);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_rbac_permission_col_authorization);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_rbac_permission_col_insert_delete);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_rbac_permission_col_update);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_meter);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_name);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_unit);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_bands);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_meter_band);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_action);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_rate);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_burst_size);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_other_config);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_encaps);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_encap);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_type);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis_private);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_chassis_private_col_name);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_chassis_private_col_chassis);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_chassis_private_col_nb_cfg);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_chassis_private_col_nb_cfg_timestamp);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_ha_chassis);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ha_chassis_col_chassis);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ha_chassis_col_priority);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ha_chassis_col_external_ids);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_ha_chassis_group);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ha_chassis_group_col_name);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ha_chassis_group_col_ha_chassis);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ha_chassis_group_col_external_ids);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ha_chassis_group_col_ref_chassis);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_igmp_group);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_address);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_datapath);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_chassis);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_ports);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_ip_multicast);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_datapath);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_enabled);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_querier);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_eth_src);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_ip4_src);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_ip6_src);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_table_size);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_idle_timeout);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_query_interval);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_ip_multicast_col_query_max_resp);\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_service_monitor);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_ip);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_logical_port);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_port);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_options);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_status);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_protocol);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_src_mac);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_src_ip);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_service_monitor_col_external_ids);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_load_balancer);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_datapaths);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_name);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_vips);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_protocol);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_options);\n- add_column_noalert(ovnsb_idl_loop.idl,\n- &sbrec_load_balancer_col_external_ids);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_bfd);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_logical_port);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_dst_ip);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_status);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_min_tx);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_min_rx);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_detect_mult);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_disc);\n- ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_src_port);\n-\n- ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_fdb);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_fdb_col_mac);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_fdb_col_dp_key);\n- add_column_noalert(ovnsb_idl_loop.idl, &sbrec_fdb_col_port_key);\n-\n- struct ovsdb_idl_index *sbrec_chassis_by_name\n- = chassis_index_create(ovnsb_idl_loop.idl);\n-\n- struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name\n- = ha_chassis_group_index_create(ovnsb_idl_loop.idl);\n-\n- struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp\n- = mcast_group_index_create(ovnsb_idl_loop.idl);\n-\n- struct ovsdb_idl_index *sbrec_ip_mcast_by_dp\n- = ip_mcast_index_create(ovnsb_idl_loop.idl);\n-\n- unixctl_command_register(\"sb-connection-status\", \"\", 0, 0,\n- ovn_conn_show, ovnsb_idl_loop.idl);\n-\n- char *ovn_internal_version = ovn_get_internal_version();\n- VLOG_INFO(\"OVN internal version is : [%s]\", ovn_internal_version);\n-\n- stopwatch_create(NORTHD_LOOP_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(OVNNB_DB_RUN_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(OVNSB_DB_RUN_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(BUILD_LFLOWS_CTX_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(CLEAR_LFLOWS_CTX_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(BUILD_LFLOWS_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(LFLOWS_DATAPATHS_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(LFLOWS_PORTS_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(LFLOWS_LBS_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(LFLOWS_IGMP_STOPWATCH_NAME, SW_MS);\n- stopwatch_create(LFLOWS_DP_GROUPS_STOPWATCH_NAME, SW_MS);\n-\n- /* Main loop. */\n- exiting = false;\n-\n- while (!exiting) {\n- update_ssl_config();\n- memory_run();\n- if (memory_should_report()) {\n- struct simap usage = SIMAP_INITIALIZER(&usage);\n-\n- /* Nothing special to report yet. */\n- memory_report(&usage);\n- simap_destroy(&usage);\n- }\n-\n- if (!state.paused) {\n- if (!ovsdb_idl_has_lock(ovnsb_idl_loop.idl) &&\n- !ovsdb_idl_is_lock_contended(ovnsb_idl_loop.idl))\n- {\n- /* Ensure that only a single ovn-northd is active in the\n- * deployment by acquiring a lock called \"ovn_northd\" on the\n- * southbound database and then only performing DB transactions\n- * if the lock is held.\n- */\n- ovsdb_idl_set_lock(ovnsb_idl_loop.idl, \"ovn_northd\");\n- }\n-\n- struct northd_context ctx = {\n- .ovnnb_idl = ovnnb_idl_loop.idl,\n- .ovnnb_txn = ovsdb_idl_loop_run(&ovnnb_idl_loop),\n- .ovnsb_idl = ovnsb_idl_loop.idl,\n- .ovnsb_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),\n- .sbrec_chassis_by_name = sbrec_chassis_by_name,\n- .sbrec_ha_chassis_grp_by_name = sbrec_ha_chassis_grp_by_name,\n- .sbrec_mcast_group_by_name_dp = sbrec_mcast_group_by_name_dp,\n- .sbrec_ip_mcast_by_dp = sbrec_ip_mcast_by_dp,\n- };\n-\n- if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {\n- VLOG_INFO(\"ovn-northd lock acquired. \"\n- \"This ovn-northd instance is now active.\");\n- state.had_lock = true;\n- } else if (state.had_lock &&\n- !ovsdb_idl_has_lock(ovnsb_idl_loop.idl))\n- {\n- VLOG_INFO(\"ovn-northd lock lost. \"\n- \"This ovn-northd instance is now on standby.\");\n- state.had_lock = false;\n- }\n-\n- if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {\n- ovn_db_run(&ctx, sbrec_chassis_by_name, &ovnsb_idl_loop,\n- ovn_internal_version);\n- if (ctx.ovnsb_txn) {\n- check_and_add_supported_dhcp_opts_to_sb_db(&ctx);\n- check_and_add_supported_dhcpv6_opts_to_sb_db(&ctx);\n- check_and_update_rbac(&ctx);\n- }\n- }\n-\n- ovsdb_idl_loop_commit_and_wait(&ovnnb_idl_loop);\n- ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);\n- } else {\n- /* ovn-northd is paused\n- * - we still want to handle any db updates and update the\n- * local IDL. Otherwise, when it is resumed, the local IDL\n- * copy will be out of sync.\n- * - but we don't want to create any txns.\n- * */\n- if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl) ||\n- ovsdb_idl_is_lock_contended(ovnsb_idl_loop.idl))\n- {\n- /* make sure we don't hold the lock while paused */\n- VLOG_INFO(\"This ovn-northd instance is now paused.\");\n- ovsdb_idl_set_lock(ovnsb_idl_loop.idl, NULL);\n- state.had_lock = false;\n- }\n-\n- ovsdb_idl_run(ovnnb_idl_loop.idl);\n- ovsdb_idl_run(ovnsb_idl_loop.idl);\n- ovsdb_idl_wait(ovnnb_idl_loop.idl);\n- ovsdb_idl_wait(ovnsb_idl_loop.idl);\n- }\n-\n- unixctl_server_run(unixctl);\n- unixctl_server_wait(unixctl);\n- memory_wait();\n- if (exiting) {\n- poll_immediate_wake();\n- }\n-\n-\n- ovsdb_idl_set_probe_interval(ovnnb_idl_loop.idl,\n- northd_probe_interval_nb);\n- ovsdb_idl_set_probe_interval(ovnsb_idl_loop.idl,\n- northd_probe_interval_sb);\n-\n- if (reset_ovnsb_idl_min_index) {\n- VLOG_INFO(\"Resetting southbound database cluster state\");\n- ovsdb_idl_reset_min_index(ovnsb_idl_loop.idl);\n- reset_ovnsb_idl_min_index = false;\n- }\n-\n- if (reset_ovnnb_idl_min_index) {\n- VLOG_INFO(\"Resetting northbound database cluster state\");\n- ovsdb_idl_reset_min_index(ovnnb_idl_loop.idl);\n- reset_ovnnb_idl_min_index = false;\n- }\n-\n- stopwatch_stop(NORTHD_LOOP_STOPWATCH_NAME, time_msec());\n- poll_block();\n- if (should_service_stop()) {\n- exiting = true;\n- }\n- stopwatch_start(NORTHD_LOOP_STOPWATCH_NAME, time_msec());\n- }\n-\n-\n- free(ovn_internal_version);\n- unixctl_server_destroy(unixctl);\n- ovsdb_idl_loop_destroy(&ovnnb_idl_loop);\n- ovsdb_idl_loop_destroy(&ovnsb_idl_loop);\n- service_stop();\n-\n- exit(res);\n-}\n-\n-static void\n-ovn_northd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,\n- const char *argv[] OVS_UNUSED, void *exiting_)\n-{\n- bool *exiting = exiting_;\n- *exiting = true;\n-\n- unixctl_command_reply(conn, NULL);\n-}\n-\n-static void\n-ovn_northd_pause(struct unixctl_conn *conn, int argc OVS_UNUSED,\n- const char *argv[] OVS_UNUSED, void *state_)\n-{\n- struct northd_state *state = state_;\n- state->paused = true;\n-\n- unixctl_command_reply(conn, NULL);\n-}\n-\n-static void\n-ovn_northd_resume(struct unixctl_conn *conn, int argc OVS_UNUSED,\n- const char *argv[] OVS_UNUSED, void *state_)\n-{\n- struct northd_state *state = state_;\n- state->paused = false;\n-\n- unixctl_command_reply(conn, NULL);\n-}\n-\n-static void\n-ovn_northd_is_paused(struct unixctl_conn *conn, int argc OVS_UNUSED,\n- const char *argv[] OVS_UNUSED, void *state_)\n-{\n- struct northd_state *state = state_;\n- if (state->paused) {\n- unixctl_command_reply(conn, \"true\");\n- } else {\n- unixctl_command_reply(conn, \"false\");\n- }\n-}\n-\n-static void\n-ovn_northd_status(struct unixctl_conn *conn, int argc OVS_UNUSED,\n- const char *argv[] OVS_UNUSED, void *state_)\n-{\n- struct northd_state *state = state_;\n- char *status;\n-\n- if (state->paused) {\n- status = \"paused\";\n- } else {\n- status = state->had_lock ? \"active\" : \"standby\";\n- }\n-\n- /*\n- * Use a labelled formatted output so we can add more to the status command\n- * later without breaking any consuming scripts\n- */\n- struct ds s = DS_EMPTY_INITIALIZER;\n- ds_put_format(&s, \"Status: %s\\n\", status);\n- unixctl_command_reply(conn, ds_cstr(&s));\n- ds_destroy(&s);\n-}\n-\n-static void\n-cluster_state_reset_cmd(struct unixctl_conn *conn, int argc OVS_UNUSED,\n- const char *argv[] OVS_UNUSED, void *idl_reset_)\n-{\n- bool *idl_reset = idl_reset_;\n-\n- *idl_reset = true;\n- poll_immediate_wake();\n- unixctl_command_reply(conn, NULL);\n-}\n+ \ndiff --git a/northd/northd.h b/northd/northd.h\nnew file mode 100644\nindex 000000000000..3209d4224803\n--- /dev/null\n+++ b/northd/northd.h\n@@ -0,0 +1,42 @@\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+#ifndef NORTHD_H\n+#define NORTHD_H 1\n+\n+#include \"ovsdb-idl.h\"\n+#include \"lib/ovn-parallel-hmap.h\"\n+\n+struct northd_context {\n+ const char *ovnnb_db;\n+ const char *ovnsb_db;\n+ struct ovsdb_idl *ovnnb_idl;\n+ struct ovsdb_idl *ovnsb_idl;\n+ struct ovsdb_idl_txn *ovnnb_txn;\n+ struct ovsdb_idl_txn *ovnsb_txn;\n+ struct ovsdb_idl_index *sbrec_chassis_by_name;\n+ struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name;\n+ struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp;\n+ struct ovsdb_idl_index *sbrec_ip_mcast_by_dp;\n+\n+ bool use_parallel_build;\n+ struct hashrow_locks *lflow_locks;\n+};\n+\n+void\n+ovn_db_run(struct northd_context *ctx,\n+ struct ovsdb_idl_index *sbrec_chassis_by_name,\n+ struct ovsdb_idl_loop *ovnsb_idl_loop,\n+ const char *ovn_internal_version);\n+\n+#endif /* NORTHD_H */\ndiff --git a/northd/ovn-northd.c b/northd/ovn-northd.c\nnew file mode 100644\nindex 000000000000..ecee14e644af\n--- /dev/null\n+++ b/northd/ovn-northd.c\n@@ -0,0 +1,1100 @@\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+#include \"lib/chassis-index.h\"\n+#include \"command-line.h\"\n+#include \"daemon.h\"\n+#include \"fatal-signal.h\"\n+#include \"lib/ip-mcast-index.h\"\n+#include \"lib/mcast-group-index.h\"\n+#include \"memory.h\"\n+#include \"northd.h\"\n+#include \"ovs-numa.h\"\n+#include \"ovsdb-idl.h\"\n+#include \"lib/ovn-l7.h\"\n+#include \"lib/ovn-nb-idl.h\"\n+#include \"lib/ovn-parallel-hmap.h\"\n+#include \"lib/ovn-sb-idl.h\"\n+#include \"openvswitch/poll-loop.h\"\n+#include \"simap.h\"\n+#include \"stopwatch.h\"\n+#include \"lib/stopwatch-names.h\"\n+#include \"stream.h\"\n+#include \"stream-ssl.h\"\n+#include \"unixctl.h\"\n+#include \"util.h\"\n+#include \"openvswitch/vlog.h\"\n+\n+VLOG_DEFINE_THIS_MODULE(ovn_northd);\n+\n+static unixctl_cb_func ovn_northd_exit;\n+static unixctl_cb_func ovn_northd_pause;\n+static unixctl_cb_func ovn_northd_resume;\n+static unixctl_cb_func ovn_northd_is_paused;\n+static unixctl_cb_func ovn_northd_status;\n+static unixctl_cb_func cluster_state_reset_cmd;\n+\n+struct northd_state {\n+ bool had_lock;\n+ bool paused;\n+};\n+\n+static const char *ovnnb_db;\n+static const char *ovnsb_db;\n+static const char *unixctl_path;\n+\n+/* SSL options */\n+static const char *ssl_private_key_file;\n+static const char *ssl_certificate_file;\n+static const char *ssl_ca_cert_file;\n+\n+static bool use_parallel_build = true;\n+static struct hashrow_locks lflow_locks;\n+\n+static const char *rbac_chassis_auth[] =\n+ {\"name\"};\n+static const char *rbac_chassis_update[] =\n+ {\"nb_cfg\", \"external_ids\", \"encaps\", \"vtep_logical_switches\",\n+ \"other_config\", \"transport_zones\"};\n+\n+static const char *rbac_chassis_private_auth[] =\n+ {\"name\"};\n+static const char *rbac_chassis_private_update[] =\n+ {\"nb_cfg\", \"nb_cfg_timestamp\", \"chassis\", \"external_ids\"};\n+\n+static const char *rbac_encap_auth[] =\n+ {\"chassis_name\"};\n+static const char *rbac_encap_update[] =\n+ {\"type\", \"options\", \"ip\"};\n+\n+static const char *rbac_controller_event_auth[] =\n+ {\"\"};\n+static const char *rbac_controller_event_update[] =\n+ {\"chassis\", \"event_info\", \"event_type\", \"seq_num\"};\n+\n+\n+static const char *rbac_fdb_auth[] =\n+ {\"\"};\n+static const char *rbac_fdb_update[] =\n+ {\"dp_key\", \"mac\", \"port_key\"};\n+\n+static const char *rbac_port_binding_auth[] =\n+ {\"\"};\n+static const char *rbac_port_binding_update[] =\n+ {\"chassis\", \"encap\", \"up\", \"virtual_parent\"};\n+\n+static const char *rbac_mac_binding_auth[] =\n+ {\"\"};\n+static const char *rbac_mac_binding_update[] =\n+ {\"logical_port\", \"ip\", \"mac\", \"datapath\"};\n+\n+static const char *rbac_svc_monitor_auth[] =\n+ {\"\"};\n+static const char *rbac_svc_monitor_auth_update[] =\n+ {\"status\"};\n+static const char *rbac_igmp_group_auth[] =\n+ {\"\"};\n+static const char *rbac_igmp_group_update[] =\n+ {\"address\", \"chassis\", \"datapath\", \"ports\"};\n+\n+static struct rbac_perm_cfg {\n+ const char *table;\n+ const char **auth;\n+ int n_auth;\n+ bool insdel;\n+ const char **update;\n+ int n_update;\n+ const struct sbrec_rbac_permission *row;\n+} rbac_perm_cfg[] = {\n+ {\n+ .table = \"Chassis\",\n+ .auth = rbac_chassis_auth,\n+ .n_auth = ARRAY_SIZE(rbac_chassis_auth),\n+ .insdel = true,\n+ .update = rbac_chassis_update,\n+ .n_update = ARRAY_SIZE(rbac_chassis_update),\n+ .row = NULL\n+ },{\n+ .table = \"Chassis_Private\",\n+ .auth = rbac_chassis_private_auth,\n+ .n_auth = ARRAY_SIZE(rbac_chassis_private_auth),\n+ .insdel = true,\n+ .update = rbac_chassis_private_update,\n+ .n_update = ARRAY_SIZE(rbac_chassis_private_update),\n+ .row = NULL\n+ },{\n+ .table = \"Controller_Event\",\n+ .auth = rbac_controller_event_auth,\n+ .n_auth = ARRAY_SIZE(rbac_controller_event_auth),\n+ .insdel = true,\n+ .update = rbac_controller_event_update,\n+ .n_update = ARRAY_SIZE(rbac_controller_event_update),\n+ .row = NULL\n+ },{\n+ .table = \"Encap\",\n+ .auth = rbac_encap_auth,\n+ .n_auth = ARRAY_SIZE(rbac_encap_auth),\n+ .insdel = true,\n+ .update = rbac_encap_update,\n+ .n_update = ARRAY_SIZE(rbac_encap_update),\n+ .row = NULL\n+ },{\n+ .table = \"FDB\",\n+ .auth = rbac_fdb_auth,\n+ .n_auth = ARRAY_SIZE(rbac_fdb_auth),\n+ .insdel = true,\n+ .update = rbac_fdb_update,\n+ .n_update = ARRAY_SIZE(rbac_fdb_update),\n+ .row = NULL\n+ },{\n+ .table = \"Port_Binding\",\n+ .auth = rbac_port_binding_auth,\n+ .n_auth = ARRAY_SIZE(rbac_port_binding_auth),\n+ .insdel = false,\n+ .update = rbac_port_binding_update,\n+ .n_update = ARRAY_SIZE(rbac_port_binding_update),\n+ .row = NULL\n+ },{\n+ .table = \"MAC_Binding\",\n+ .auth = rbac_mac_binding_auth,\n+ .n_auth = ARRAY_SIZE(rbac_mac_binding_auth),\n+ .insdel = true,\n+ .update = rbac_mac_binding_update,\n+ .n_update = ARRAY_SIZE(rbac_mac_binding_update),\n+ .row = NULL\n+ },{\n+ .table = \"Service_Monitor\",\n+ .auth = rbac_svc_monitor_auth,\n+ .n_auth = ARRAY_SIZE(rbac_svc_monitor_auth),\n+ .insdel = false,\n+ .update = rbac_svc_monitor_auth_update,\n+ .n_update = ARRAY_SIZE(rbac_svc_monitor_auth_update),\n+ .row = NULL\n+ },{\n+ .table = \"IGMP_Group\",\n+ .auth = rbac_igmp_group_auth,\n+ .n_auth = ARRAY_SIZE(rbac_igmp_group_auth),\n+ .insdel = true,\n+ .update = rbac_igmp_group_update,\n+ .n_update = ARRAY_SIZE(rbac_igmp_group_update),\n+ .row = NULL\n+ },{\n+ .table = NULL,\n+ .auth = NULL,\n+ .n_auth = 0,\n+ .insdel = false,\n+ .update = NULL,\n+ .n_update = 0,\n+ .row = NULL\n+ }\n+};\n+\n+static struct gen_opts_map supported_dhcp_opts[] = {\n+ OFFERIP,\n+ DHCP_OPT_NETMASK,\n+ DHCP_OPT_ROUTER,\n+ DHCP_OPT_DNS_SERVER,\n+ DHCP_OPT_LOG_SERVER,\n+ DHCP_OPT_LPR_SERVER,\n+ DHCP_OPT_SWAP_SERVER,\n+ DHCP_OPT_POLICY_FILTER,\n+ DHCP_OPT_ROUTER_SOLICITATION,\n+ DHCP_OPT_NIS_SERVER,\n+ DHCP_OPT_NTP_SERVER,\n+ DHCP_OPT_SERVER_ID,\n+ DHCP_OPT_TFTP_SERVER,\n+ DHCP_OPT_CLASSLESS_STATIC_ROUTE,\n+ DHCP_OPT_MS_CLASSLESS_STATIC_ROUTE,\n+ DHCP_OPT_IP_FORWARD_ENABLE,\n+ DHCP_OPT_ROUTER_DISCOVERY,\n+ DHCP_OPT_ETHERNET_ENCAP,\n+ DHCP_OPT_DEFAULT_TTL,\n+ DHCP_OPT_TCP_TTL,\n+ DHCP_OPT_MTU,\n+ DHCP_OPT_LEASE_TIME,\n+ DHCP_OPT_T1,\n+ DHCP_OPT_T2,\n+ DHCP_OPT_WPAD,\n+ DHCP_OPT_BOOTFILE,\n+ DHCP_OPT_PATH_PREFIX,\n+ DHCP_OPT_TFTP_SERVER_ADDRESS,\n+ DHCP_OPT_HOSTNAME,\n+ DHCP_OPT_DOMAIN_NAME,\n+ DHCP_OPT_ARP_CACHE_TIMEOUT,\n+ DHCP_OPT_TCP_KEEPALIVE_INTERVAL,\n+ DHCP_OPT_DOMAIN_SEARCH_LIST,\n+ DHCP_OPT_BOOTFILE_ALT,\n+ DHCP_OPT_BROADCAST_ADDRESS,\n+ DHCP_OPT_NETBIOS_NAME_SERVER,\n+ DHCP_OPT_NETBIOS_NODE_TYPE,\n+};\n+\n+static struct gen_opts_map supported_dhcpv6_opts[] = {\n+ DHCPV6_OPT_IA_ADDR,\n+ DHCPV6_OPT_SERVER_ID,\n+ DHCPV6_OPT_DOMAIN_SEARCH,\n+ DHCPV6_OPT_DNS_SERVER\n+};\n+\n+static bool\n+ovn_rbac_validate_perm(const struct sbrec_rbac_permission *perm)\n+{\n+ struct rbac_perm_cfg *pcfg;\n+ int i, j, n_found;\n+\n+ for (pcfg = rbac_perm_cfg; pcfg->table; pcfg++) {\n+ if (!strcmp(perm->table, pcfg->table)) {\n+ break;\n+ }\n+ }\n+ if (!pcfg->table) {\n+ return false;\n+ }\n+ if (perm->n_authorization != pcfg->n_auth ||\n+ perm->n_update != pcfg->n_update) {\n+ return false;\n+ }\n+ if (perm->insert_delete != pcfg->insdel) {\n+ return false;\n+ }\n+ /* verify perm->authorization vs. pcfg->auth */\n+ n_found = 0;\n+ for (i = 0; i < pcfg->n_auth; i++) {\n+ for (j = 0; j < perm->n_authorization; j++) {\n+ if (!strcmp(pcfg->auth[i], perm->authorization[j])) {\n+ n_found++;\n+ break;\n+ }\n+ }\n+ }\n+ if (n_found != pcfg->n_auth) {\n+ return false;\n+ }\n+\n+ /* verify perm->update vs. pcfg->update */\n+ n_found = 0;\n+ for (i = 0; i < pcfg->n_update; i++) {\n+ for (j = 0; j < perm->n_update; j++) {\n+ if (!strcmp(pcfg->update[i], perm->update[j])) {\n+ n_found++;\n+ break;\n+ }\n+ }\n+ }\n+ if (n_found != pcfg->n_update) {\n+ return false;\n+ }\n+\n+ /* Success, db state matches expected state */\n+ pcfg->row = perm;\n+ return true;\n+}\n+\n+static void\n+ovn_rbac_create_perm(struct rbac_perm_cfg *pcfg,\n+ struct northd_context *ctx,\n+ const struct sbrec_rbac_role *rbac_role)\n+{\n+ struct sbrec_rbac_permission *rbac_perm;\n+\n+ rbac_perm = sbrec_rbac_permission_insert(ctx->ovnsb_txn);\n+ sbrec_rbac_permission_set_table(rbac_perm, pcfg->table);\n+ sbrec_rbac_permission_set_authorization(rbac_perm,\n+ pcfg->auth,\n+ pcfg->n_auth);\n+ sbrec_rbac_permission_set_insert_delete(rbac_perm, pcfg->insdel);\n+ sbrec_rbac_permission_set_update(rbac_perm,\n+ pcfg->update,\n+ pcfg->n_update);\n+ sbrec_rbac_role_update_permissions_setkey(rbac_role, pcfg->table,\n+ rbac_perm);\n+}\n+\n+static void\n+check_and_update_rbac(struct northd_context *ctx)\n+{\n+ const struct sbrec_rbac_role *rbac_role = NULL;\n+ const struct sbrec_rbac_permission *perm_row, *perm_next;\n+ const struct sbrec_rbac_role *role_row, *role_row_next;\n+ struct rbac_perm_cfg *pcfg;\n+\n+ for (pcfg = rbac_perm_cfg; pcfg->table; pcfg++) {\n+ pcfg->row = NULL;\n+ }\n+\n+ SBREC_RBAC_PERMISSION_FOR_EACH_SAFE (perm_row, perm_next, ctx->ovnsb_idl) {\n+ if (!ovn_rbac_validate_perm(perm_row)) {\n+ sbrec_rbac_permission_delete(perm_row);\n+ }\n+ }\n+ SBREC_RBAC_ROLE_FOR_EACH_SAFE (role_row, role_row_next, ctx->ovnsb_idl) {\n+ if (strcmp(role_row->name, \"ovn-controller\")) {\n+ sbrec_rbac_role_delete(role_row);\n+ } else {\n+ rbac_role = role_row;\n+ }\n+ }\n+\n+ if (!rbac_role) {\n+ rbac_role = sbrec_rbac_role_insert(ctx->ovnsb_txn);\n+ sbrec_rbac_role_set_name(rbac_role, \"ovn-controller\");\n+ }\n+\n+ for (pcfg = rbac_perm_cfg; pcfg->table; pcfg++) {\n+ if (!pcfg->row) {\n+ ovn_rbac_create_perm(pcfg, ctx, rbac_role);\n+ }\n+ }\n+}\n+\n+static void\n+check_and_add_supported_dhcp_opts_to_sb_db(struct northd_context *ctx)\n+{\n+ struct hmap dhcp_opts_to_add = HMAP_INITIALIZER(&dhcp_opts_to_add);\n+ for (size_t i = 0; (i < sizeof(supported_dhcp_opts) /\n+ sizeof(supported_dhcp_opts[0])); i++) {\n+ hmap_insert(&dhcp_opts_to_add, &supported_dhcp_opts[i].hmap_node,\n+ dhcp_opt_hash(supported_dhcp_opts[i].name));\n+ }\n+\n+ const struct sbrec_dhcp_options *opt_row, *opt_row_next;\n+ SBREC_DHCP_OPTIONS_FOR_EACH_SAFE(opt_row, opt_row_next, ctx->ovnsb_idl) {\n+ struct gen_opts_map *dhcp_opt =\n+ dhcp_opts_find(&dhcp_opts_to_add, opt_row->name);\n+ if (dhcp_opt) {\n+ if (!strcmp(dhcp_opt->type, opt_row->type) &&\n+ dhcp_opt->code == opt_row->code) {\n+ hmap_remove(&dhcp_opts_to_add, &dhcp_opt->hmap_node);\n+ } else {\n+ sbrec_dhcp_options_delete(opt_row);\n+ }\n+ } else {\n+ sbrec_dhcp_options_delete(opt_row);\n+ }\n+ }\n+\n+ struct gen_opts_map *opt;\n+ HMAP_FOR_EACH (opt, hmap_node, &dhcp_opts_to_add) {\n+ struct sbrec_dhcp_options *sbrec_dhcp_option =\n+ sbrec_dhcp_options_insert(ctx->ovnsb_txn);\n+ sbrec_dhcp_options_set_name(sbrec_dhcp_option, opt->name);\n+ sbrec_dhcp_options_set_code(sbrec_dhcp_option, opt->code);\n+ sbrec_dhcp_options_set_type(sbrec_dhcp_option, opt->type);\n+ }\n+\n+ hmap_destroy(&dhcp_opts_to_add);\n+}\n+\n+static void\n+check_and_add_supported_dhcpv6_opts_to_sb_db(struct northd_context *ctx)\n+{\n+ struct hmap dhcpv6_opts_to_add = HMAP_INITIALIZER(&dhcpv6_opts_to_add);\n+ for (size_t i = 0; (i < sizeof(supported_dhcpv6_opts) /\n+ sizeof(supported_dhcpv6_opts[0])); i++) {\n+ hmap_insert(&dhcpv6_opts_to_add, &supported_dhcpv6_opts[i].hmap_node,\n+ dhcp_opt_hash(supported_dhcpv6_opts[i].name));\n+ }\n+\n+ const struct sbrec_dhcpv6_options *opt_row, *opt_row_next;\n+ SBREC_DHCPV6_OPTIONS_FOR_EACH_SAFE(opt_row, opt_row_next, ctx->ovnsb_idl) {\n+ struct gen_opts_map *dhcp_opt =\n+ dhcp_opts_find(&dhcpv6_opts_to_add, opt_row->name);\n+ if (dhcp_opt) {\n+ hmap_remove(&dhcpv6_opts_to_add, &dhcp_opt->hmap_node);\n+ } else {\n+ sbrec_dhcpv6_options_delete(opt_row);\n+ }\n+ }\n+\n+ struct gen_opts_map *opt;\n+ HMAP_FOR_EACH(opt, hmap_node, &dhcpv6_opts_to_add) {\n+ struct sbrec_dhcpv6_options *sbrec_dhcpv6_option =\n+ sbrec_dhcpv6_options_insert(ctx->ovnsb_txn);\n+ sbrec_dhcpv6_options_set_name(sbrec_dhcpv6_option, opt->name);\n+ sbrec_dhcpv6_options_set_code(sbrec_dhcpv6_option, opt->code);\n+ sbrec_dhcpv6_options_set_type(sbrec_dhcpv6_option, opt->type);\n+ }\n+\n+ hmap_destroy(&dhcpv6_opts_to_add);\n+}\n+\f\n+static void\n+usage(void)\n+{\n+ printf(\"\\\n+%s: OVN northbound management daemon\\n\\\n+usage: %s [OPTIONS]\\n\\\n+\\n\\\n+Options:\\n\\\n+ --ovnnb-db=DATABASE connect to ovn-nb database at DATABASE\\n\\\n+ (default: %s)\\n\\\n+ --ovnsb-db=DATABASE connect to ovn-sb database at DATABASE\\n\\\n+ (default: %s)\\n\\\n+ --dry-run start in paused state (do not commit db changes)\\n\\\n+ --unixctl=SOCKET override default control socket name\\n\\\n+ -h, --help display this help message\\n\\\n+ -o, --options list available options\\n\\\n+ -V, --version display version information\\n\\\n+\", program_name, program_name, default_nb_db(), default_sb_db());\n+ daemon_usage();\n+ vlog_usage();\n+ stream_usage(\"database\", true, true, false);\n+}\n+\f\n+static void\n+parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED,\n+ bool *paused)\n+{\n+ enum {\n+ OVN_DAEMON_OPTION_ENUMS,\n+ VLOG_OPTION_ENUMS,\n+ SSL_OPTION_ENUMS,\n+ OPT_DRY_RUN,\n+ OPT_DUMMY_NUMA,\n+ };\n+ static const struct option long_options[] = {\n+ {\"ovnsb-db\", required_argument, NULL, 'd'},\n+ {\"ovnnb-db\", required_argument, NULL, 'D'},\n+ {\"unixctl\", required_argument, NULL, 'u'},\n+ {\"help\", no_argument, NULL, 'h'},\n+ {\"options\", no_argument, NULL, 'o'},\n+ {\"version\", no_argument, NULL, 'V'},\n+ {\"dry-run\", no_argument, NULL, OPT_DRY_RUN},\n+ {\"dummy-numa\", required_argument, NULL, OPT_DUMMY_NUMA},\n+ OVN_DAEMON_LONG_OPTIONS,\n+ VLOG_LONG_OPTIONS,\n+ STREAM_SSL_LONG_OPTIONS,\n+ {NULL, 0, NULL, 0},\n+ };\n+ char *short_options = ovs_cmdl_long_options_to_short_options(long_options);\n+\n+ for (;;) {\n+ int c;\n+\n+ c = getopt_long(argc, argv, short_options, long_options, NULL);\n+ if (c == -1) {\n+ break;\n+ }\n+\n+ switch (c) {\n+ OVN_DAEMON_OPTION_HANDLERS;\n+ VLOG_OPTION_HANDLERS;\n+\n+ case 'p':\n+ ssl_private_key_file = optarg;\n+ break;\n+\n+ case 'c':\n+ ssl_certificate_file = optarg;\n+ break;\n+\n+ case 'C':\n+ ssl_ca_cert_file = optarg;\n+ break;\n+\n+ case 'd':\n+ ovnsb_db = optarg;\n+ break;\n+\n+ case 'D':\n+ ovnnb_db = optarg;\n+ break;\n+\n+ case 'u':\n+ unixctl_path = optarg;\n+ break;\n+\n+ case 'h':\n+ usage();\n+ exit(EXIT_SUCCESS);\n+\n+ case 'o':\n+ ovs_cmdl_print_options(long_options);\n+ exit(EXIT_SUCCESS);\n+\n+ case 'V':\n+ ovn_print_version(0, 0);\n+ exit(EXIT_SUCCESS);\n+\n+ case OPT_DUMMY_NUMA:\n+ ovs_numa_set_dummy(optarg);\n+ break;\n+\n+ case OPT_DRY_RUN:\n+ *paused = true;\n+ break;\n+\n+ default:\n+ break;\n+ }\n+ }\n+\n+ if (!ovnsb_db || !ovnsb_db[0]) {\n+ ovnsb_db = default_sb_db();\n+ }\n+\n+ if (!ovnnb_db || !ovnnb_db[0]) {\n+ ovnnb_db = default_nb_db();\n+ }\n+\n+ free(short_options);\n+}\n+\n+static void\n+add_column_noalert(struct ovsdb_idl *idl,\n+ const struct ovsdb_idl_column *column)\n+{\n+ ovsdb_idl_add_column(idl, column);\n+ ovsdb_idl_omit_alert(idl, column);\n+}\n+\n+static void\n+update_ssl_config(void)\n+{\n+ if (ssl_private_key_file && ssl_certificate_file) {\n+ stream_ssl_set_key_and_cert(ssl_private_key_file,\n+ ssl_certificate_file);\n+ }\n+ if (ssl_ca_cert_file) {\n+ stream_ssl_set_ca_cert_file(ssl_ca_cert_file, false);\n+ }\n+}\n+\n+int\n+main(int argc, char *argv[])\n+{\n+ int res = EXIT_SUCCESS;\n+ struct unixctl_server *unixctl;\n+ int retval;\n+ bool exiting;\n+ struct northd_state state = {\n+ .had_lock = false,\n+ .paused = false\n+ };\n+\n+ fatal_ignore_sigpipe();\n+ ovs_cmdl_proctitle_init(argc, argv);\n+ ovn_set_program_name(argv[0]);\n+ service_start(&argc, &argv);\n+ parse_options(argc, argv, &state.paused);\n+\n+ daemonize_start(false);\n+\n+ char *abs_unixctl_path = get_abs_unix_ctl_path(unixctl_path);\n+ retval = unixctl_server_create(abs_unixctl_path, &unixctl);\n+ free(abs_unixctl_path);\n+\n+ if (retval) {\n+ exit(EXIT_FAILURE);\n+ }\n+ unixctl_command_register(\"exit\", \"\", 0, 0, ovn_northd_exit, &exiting);\n+ unixctl_command_register(\"pause\", \"\", 0, 0, ovn_northd_pause, &state);\n+ unixctl_command_register(\"resume\", \"\", 0, 0, ovn_northd_resume, &state);\n+ unixctl_command_register(\"is-paused\", \"\", 0, 0, ovn_northd_is_paused,\n+ &state);\n+ unixctl_command_register(\"status\", \"\", 0, 0, ovn_northd_status, &state);\n+\n+ bool reset_ovnsb_idl_min_index = false;\n+ unixctl_command_register(\"sb-cluster-state-reset\", \"\", 0, 0,\n+ cluster_state_reset_cmd,\n+ &reset_ovnsb_idl_min_index);\n+\n+ bool reset_ovnnb_idl_min_index = false;\n+ unixctl_command_register(\"nb-cluster-state-reset\", \"\", 0, 0,\n+ cluster_state_reset_cmd,\n+ &reset_ovnnb_idl_min_index);\n+\n+ daemonize_complete();\n+\n+ init_hash_row_locks(&lflow_locks);\n+ use_parallel_build = can_parallelize_hashes(false);\n+\n+ /* We want to detect (almost) all changes to the ovn-nb db. */\n+ struct ovsdb_idl_loop ovnnb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(\n+ ovsdb_idl_create(ovnnb_db, &nbrec_idl_class, true, true));\n+ ovsdb_idl_omit_alert(ovnnb_idl_loop.idl,\n+ &nbrec_nb_global_col_nb_cfg_timestamp);\n+ ovsdb_idl_omit_alert(ovnnb_idl_loop.idl, &nbrec_nb_global_col_sb_cfg);\n+ ovsdb_idl_omit_alert(ovnnb_idl_loop.idl,\n+ &nbrec_nb_global_col_sb_cfg_timestamp);\n+ ovsdb_idl_omit_alert(ovnnb_idl_loop.idl, &nbrec_nb_global_col_hv_cfg);\n+ ovsdb_idl_omit_alert(ovnnb_idl_loop.idl,\n+ &nbrec_nb_global_col_hv_cfg_timestamp);\n+\n+ unixctl_command_register(\"nb-connection-status\", \"\", 0, 0,\n+ ovn_conn_show, ovnnb_idl_loop.idl);\n+\n+ /* We want to detect only selected changes to the ovn-sb db. */\n+ struct ovsdb_idl_loop ovnsb_idl_loop = OVSDB_IDL_LOOP_INITIALIZER(\n+ ovsdb_idl_create(ovnsb_db, &sbrec_idl_class, false, true));\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_sb_global);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_nb_cfg);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_options);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_sb_global_col_ipsec);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_logical_flow);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_logical_flow_col_logical_datapath);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_logical_flow_col_logical_dp_group);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_pipeline);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_table_id);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_priority);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_match);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_logical_flow_col_actions);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_logical_flow_col_controller_meter);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_logical_flow_col_external_ids);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl,\n+ &sbrec_table_logical_dp_group);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_logical_dp_group_col_datapaths);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_multicast_group);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_multicast_group_col_datapath);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_multicast_group_col_tunnel_key);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_multicast_group_col_name);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_multicast_group_col_ports);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_datapath_binding);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_datapath_binding_col_tunnel_key);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_datapath_binding_col_load_balancers);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_datapath_binding_col_external_ids);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_port_binding);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_datapath);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_logical_port);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_tunnel_key);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_parent_port);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_tag);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_type);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_options);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_binding_col_mac);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_nat_addresses);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_port_binding_col_chassis);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_gateway_chassis);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_ha_chassis_group);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_virtual_parent);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_up);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_gateway_chassis_col_chassis);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_gateway_chassis_col_name);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_gateway_chassis_col_priority);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_gateway_chassis_col_external_ids);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_gateway_chassis_col_options);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_port_binding_col_external_ids);\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_mac_binding);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_datapath);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_ip);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_mac_binding_col_mac);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_mac_binding_col_logical_port);\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dhcp_options);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_code);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_type);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcp_options_col_name);\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dhcpv6_options);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_code);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_type);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dhcpv6_options_col_name);\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_address_set);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_address_set_col_name);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_address_set_col_addresses);\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_port_group);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_group_col_name);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_port_group_col_ports);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_dns);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_datapaths);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_records);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_dns_col_external_ids);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_rbac_role);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_rbac_role_col_name);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_rbac_role_col_permissions);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_rbac_permission);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_rbac_permission_col_table);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_rbac_permission_col_authorization);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_rbac_permission_col_insert_delete);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_rbac_permission_col_update);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_meter);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_name);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_unit);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_col_bands);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_meter_band);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_action);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_rate);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_meter_band_col_burst_size);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_name);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_other_config);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_chassis_col_encaps);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_encap);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_encap_col_type);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_chassis_private);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_chassis_private_col_name);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_chassis_private_col_chassis);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_chassis_private_col_nb_cfg);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_chassis_private_col_nb_cfg_timestamp);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_ha_chassis);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ha_chassis_col_chassis);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ha_chassis_col_priority);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ha_chassis_col_external_ids);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_ha_chassis_group);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ha_chassis_group_col_name);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ha_chassis_group_col_ha_chassis);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ha_chassis_group_col_external_ids);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ha_chassis_group_col_ref_chassis);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_igmp_group);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_address);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_datapath);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_chassis);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_igmp_group_col_ports);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_ip_multicast);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_datapath);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_enabled);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_querier);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_eth_src);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_ip4_src);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_ip6_src);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_table_size);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_idle_timeout);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_query_interval);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_ip_multicast_col_query_max_resp);\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_service_monitor);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_ip);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_logical_port);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_port);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_options);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_status);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_protocol);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_src_mac);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_src_ip);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_service_monitor_col_external_ids);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_load_balancer);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_datapaths);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_name);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_vips);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_protocol);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_load_balancer_col_options);\n+ add_column_noalert(ovnsb_idl_loop.idl,\n+ &sbrec_load_balancer_col_external_ids);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_bfd);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_logical_port);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_dst_ip);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_status);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_min_tx);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_min_rx);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_detect_mult);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_disc);\n+ ovsdb_idl_add_column(ovnsb_idl_loop.idl, &sbrec_bfd_col_src_port);\n+\n+ ovsdb_idl_add_table(ovnsb_idl_loop.idl, &sbrec_table_fdb);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_fdb_col_mac);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_fdb_col_dp_key);\n+ add_column_noalert(ovnsb_idl_loop.idl, &sbrec_fdb_col_port_key);\n+\n+ struct ovsdb_idl_index *sbrec_chassis_by_name\n+ = chassis_index_create(ovnsb_idl_loop.idl);\n+\n+ struct ovsdb_idl_index *sbrec_ha_chassis_grp_by_name\n+ = ha_chassis_group_index_create(ovnsb_idl_loop.idl);\n+\n+ struct ovsdb_idl_index *sbrec_mcast_group_by_name_dp\n+ = mcast_group_index_create(ovnsb_idl_loop.idl);\n+\n+ struct ovsdb_idl_index *sbrec_ip_mcast_by_dp\n+ = ip_mcast_index_create(ovnsb_idl_loop.idl);\n+\n+ unixctl_command_register(\"sb-connection-status\", \"\", 0, 0,\n+ ovn_conn_show, ovnsb_idl_loop.idl);\n+\n+ char *ovn_internal_version = ovn_get_internal_version();\n+ VLOG_INFO(\"OVN internal version is : [%s]\", ovn_internal_version);\n+\n+ stopwatch_create(NORTHD_LOOP_STOPWATCH_NAME, SW_MS);\n+ stopwatch_create(OVNNB_DB_RUN_STOPWATCH_NAME, SW_MS);\n+ stopwatch_create(OVNSB_DB_RUN_STOPWATCH_NAME, SW_MS);\n+\n+ /* Main loop. */\n+ exiting = false;\n+\n+ while (!exiting) {\n+ update_ssl_config();\n+ memory_run();\n+ if (memory_should_report()) {\n+ struct simap usage = SIMAP_INITIALIZER(&usage);\n+\n+ /* Nothing special to report yet. */\n+ memory_report(&usage);\n+ simap_destroy(&usage);\n+ }\n+\n+ if (!state.paused) {\n+ if (!ovsdb_idl_has_lock(ovnsb_idl_loop.idl) &&\n+ !ovsdb_idl_is_lock_contended(ovnsb_idl_loop.idl))\n+ {\n+ /* Ensure that only a single ovn-northd is active in the\n+ * deployment by acquiring a lock called \"ovn_northd\" on the\n+ * southbound database and then only performing DB transactions\n+ * if the lock is held.\n+ */\n+ ovsdb_idl_set_lock(ovnsb_idl_loop.idl, \"ovn_northd\");\n+ }\n+\n+ struct northd_context ctx = {\n+ .ovnnb_db = ovnnb_db,\n+ .ovnsb_db = ovnsb_db,\n+ .ovnnb_idl = ovnnb_idl_loop.idl,\n+ .ovnnb_txn = ovsdb_idl_loop_run(&ovnnb_idl_loop),\n+ .ovnsb_idl = ovnsb_idl_loop.idl,\n+ .ovnsb_txn = ovsdb_idl_loop_run(&ovnsb_idl_loop),\n+ .sbrec_chassis_by_name = sbrec_chassis_by_name,\n+ .sbrec_ha_chassis_grp_by_name = sbrec_ha_chassis_grp_by_name,\n+ .sbrec_mcast_group_by_name_dp = sbrec_mcast_group_by_name_dp,\n+ .sbrec_ip_mcast_by_dp = sbrec_ip_mcast_by_dp,\n+ .lflow_locks = &lflow_locks,\n+ .use_parallel_build = use_parallel_build,\n+ };\n+\n+ if (!state.had_lock && ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {\n+ VLOG_INFO(\"ovn-northd lock acquired. \"\n+ \"This ovn-northd instance is now active.\");\n+ state.had_lock = true;\n+ } else if (state.had_lock &&\n+ !ovsdb_idl_has_lock(ovnsb_idl_loop.idl))\n+ {\n+ VLOG_INFO(\"ovn-northd lock lost. \"\n+ \"This ovn-northd instance is now on standby.\");\n+ state.had_lock = false;\n+ }\n+\n+ if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl)) {\n+\n+ ovn_db_run(&ctx, sbrec_chassis_by_name, &ovnsb_idl_loop,\n+ ovn_internal_version);\n+ if (ctx.ovnsb_txn) {\n+ check_and_add_supported_dhcp_opts_to_sb_db(&ctx);\n+ check_and_add_supported_dhcpv6_opts_to_sb_db(&ctx);\n+ check_and_update_rbac(&ctx);\n+ }\n+ }\n+\n+ ovsdb_idl_loop_commit_and_wait(&ovnnb_idl_loop);\n+ ovsdb_idl_loop_commit_and_wait(&ovnsb_idl_loop);\n+ } else {\n+ /* ovn-northd is paused\n+ * - we still want to handle any db updates and update the\n+ * local IDL. Otherwise, when it is resumed, the local IDL\n+ * copy will be out of sync.\n+ * - but we don't want to create any txns.\n+ * */\n+ if (ovsdb_idl_has_lock(ovnsb_idl_loop.idl) ||\n+ ovsdb_idl_is_lock_contended(ovnsb_idl_loop.idl))\n+ {\n+ /* make sure we don't hold the lock while paused */\n+ VLOG_INFO(\"This ovn-northd instance is now paused.\");\n+ ovsdb_idl_set_lock(ovnsb_idl_loop.idl, NULL);\n+ state.had_lock = false;\n+ }\n+\n+ ovsdb_idl_run(ovnnb_idl_loop.idl);\n+ ovsdb_idl_run(ovnsb_idl_loop.idl);\n+ ovsdb_idl_wait(ovnnb_idl_loop.idl);\n+ ovsdb_idl_wait(ovnsb_idl_loop.idl);\n+ }\n+\n+ stopwatch_stop(NORTHD_LOOP_STOPWATCH_NAME, time_msec());\n+ stopwatch_start(NORTHD_LOOP_STOPWATCH_NAME, time_msec());\n+ unixctl_server_run(unixctl);\n+ unixctl_server_wait(unixctl);\n+ memory_wait();\n+ if (exiting) {\n+ poll_immediate_wake();\n+ }\n+\n+ if (reset_ovnsb_idl_min_index) {\n+ VLOG_INFO(\"Resetting southbound database cluster state\");\n+ ovsdb_idl_reset_min_index(ovnsb_idl_loop.idl);\n+ reset_ovnsb_idl_min_index = false;\n+ }\n+\n+ if (reset_ovnnb_idl_min_index) {\n+ VLOG_INFO(\"Resetting northbound database cluster state\");\n+ ovsdb_idl_reset_min_index(ovnnb_idl_loop.idl);\n+ reset_ovnnb_idl_min_index = false;\n+ }\n+\n+ poll_block();\n+ if (should_service_stop()) {\n+ exiting = true;\n+ }\n+ }\n+\n+\n+ free(ovn_internal_version);\n+ unixctl_server_destroy(unixctl);\n+ ovsdb_idl_loop_destroy(&ovnnb_idl_loop);\n+ ovsdb_idl_loop_destroy(&ovnsb_idl_loop);\n+ service_stop();\n+\n+ exit(res);\n+}\n+\n+static void\n+ovn_northd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,\n+ const char *argv[] OVS_UNUSED, void *exiting_)\n+{\n+ bool *exiting = exiting_;\n+ *exiting = true;\n+\n+ unixctl_command_reply(conn, NULL);\n+}\n+\n+static void\n+ovn_northd_pause(struct unixctl_conn *conn, int argc OVS_UNUSED,\n+ const char *argv[] OVS_UNUSED, void *state_)\n+{\n+ struct northd_state *state = state_;\n+ state->paused = true;\n+\n+ unixctl_command_reply(conn, NULL);\n+}\n+\n+static void\n+ovn_northd_resume(struct unixctl_conn *conn, int argc OVS_UNUSED,\n+ const char *argv[] OVS_UNUSED, void *state_)\n+{\n+ struct northd_state *state = state_;\n+ state->paused = false;\n+\n+ unixctl_command_reply(conn, NULL);\n+}\n+\n+static void\n+ovn_northd_is_paused(struct unixctl_conn *conn, int argc OVS_UNUSED,\n+ const char *argv[] OVS_UNUSED, void *state_)\n+{\n+ struct northd_state *state = state_;\n+ if (state->paused) {\n+ unixctl_command_reply(conn, \"true\");\n+ } else {\n+ unixctl_command_reply(conn, \"false\");\n+ }\n+}\n+\n+static void\n+ovn_northd_status(struct unixctl_conn *conn, int argc OVS_UNUSED,\n+ const char *argv[] OVS_UNUSED, void *state_)\n+{\n+ struct northd_state *state = state_;\n+ char *status;\n+\n+ if (state->paused) {\n+ status = \"paused\";\n+ } else {\n+ status = state->had_lock ? \"active\" : \"standby\";\n+ }\n+\n+ /*\n+ * Use a labelled formatted output so we can add more to the status command\n+ * later without breaking any consuming scripts\n+ */\n+ struct ds s = DS_EMPTY_INITIALIZER;\n+ ds_put_format(&s, \"Status: %s\\n\", status);\n+ unixctl_command_reply(conn, ds_cstr(&s));\n+ ds_destroy(&s);\n+}\n+\n+static void\n+cluster_state_reset_cmd(struct unixctl_conn *conn, int argc OVS_UNUSED,\n+ const char *argv[] OVS_UNUSED, void *idl_reset_)\n+{\n+ bool *idl_reset = idl_reset_;\n+\n+ *idl_reset = true;\n+ poll_immediate_wake();\n+ unixctl_command_reply(conn, NULL);\n+}\n", "prefixes": [ "ovs-dev", "v2", "2/2" ] }{ "id": 1523310, "url": "